-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #128 from devchat-ai/auto_apply_fix_issue
feat: Enhance issue fixing and add aider integration
- Loading branch information
Showing
21 changed files
with
1,208 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,3 +9,4 @@ custom/* | |
!custom/config.yml.example | ||
|
||
user_settings.yml | ||
.aider* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
### 操作指南 | ||
|
||
aider工作流命令使用步骤如下: | ||
|
||
1. 确保已经使用 `/aider.files.add` 命令添加了需要处理的文件。 | ||
2. 输入 `/aider <message>` 命令,其中 `<message>` 是你想要aider执行的任务描述。 | ||
3. 等待aider生成建议的更改。 | ||
4. 系统会自动显示每个文件的Diff View,你可以选择是否接受修改。 | ||
5. 对于多个文件的更改,系统会在每个文件之后询问是否继续查看下一个文件的更改。 | ||
|
||
注意事项: | ||
- 如果没有添加任何文件到aider,命令将会提示你先使用 'aider.files.add' 命令添加文件。 | ||
- 你可以使用 `aider.files.remove` 命令从aider中移除文件。 | ||
- 所有的更改都会在IDE中以Diff View的形式展示,你可以在查看后决定是否应用这些更改。 | ||
|
||
使用示例: | ||
/aider 重构这段代码以提高性能 | ||
|
||
这个命令会让aider分析当前添加的文件,并提供重构建议以提高代码性能。 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,214 @@ | ||
import json | ||
import os | ||
import subprocess | ||
import sys | ||
|
||
from devchat.ide import IDEService | ||
|
||
from lib.chatmark import Button | ||
|
||
GLOBAL_CONFIG_PATH = os.path.join(os.path.expanduser("~"), ".chat", ".workflow_config.json") | ||
|
||
|
||
def save_config(config_path, item, value): | ||
if os.path.exists(config_path): | ||
with open(config_path, "r", encoding="utf-8") as f: | ||
config = json.load(f) | ||
else: | ||
config = {} | ||
|
||
config[item] = value | ||
with open(config_path, "w", encoding="utf-8") as f: | ||
json.dump(config, f, indent=4) | ||
|
||
|
||
def write_python_path_to_config(): | ||
""" | ||
Write the current system Python path to the configuration. | ||
""" | ||
python_path = sys.executable | ||
save_config(GLOBAL_CONFIG_PATH, "aider_python", python_path) | ||
print(f"Python path '{python_path}' has been written to the configuration.") | ||
|
||
|
||
def get_aider_files(): | ||
""" | ||
从.chat/.aider_files文件中读取aider文件列表 | ||
""" | ||
aider_files_path = os.path.join(".chat", ".aider_files") | ||
if not os.path.exists(aider_files_path): | ||
return [] | ||
|
||
with open(aider_files_path, "r") as f: | ||
return [line.strip() for line in f if line.strip()] | ||
|
||
|
||
def run_aider(message, files): | ||
""" | ||
运行aider命令 | ||
""" | ||
python = sys.executable | ||
model = os.environ.get("LLM_MODEL", "gpt-3.5-turbo-1106") | ||
|
||
cmd = [ | ||
python, | ||
"-m", | ||
"aider", | ||
"--model", | ||
f"openai/{model}", | ||
"--yes", | ||
"--no-auto-commits", | ||
"--dry-run", | ||
"--no-pretty", | ||
"--message", | ||
message, | ||
] + files | ||
|
||
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) | ||
|
||
has_started = False | ||
aider_output = "" | ||
for line in process.stdout: | ||
if "run with --help" in line or 'run "aider --help"' in line: | ||
has_started = True | ||
continue | ||
if has_started: | ||
aider_output += line | ||
print(line, end="", flush=True) | ||
|
||
return_code = process.wait() | ||
|
||
if return_code != 0: | ||
for line in process.stderr: | ||
print(f"Error: {line.strip()}", file=sys.stderr) | ||
sys.exit(return_code) | ||
|
||
return aider_output | ||
|
||
|
||
def apply_changes(changes, files): | ||
""" | ||
应用aider生成的更改 | ||
""" | ||
changes_file = ".chat/changes.txt" | ||
os.makedirs(os.path.dirname(changes_file), exist_ok=True) | ||
with open(changes_file, "w") as f: | ||
f.write(changes) | ||
|
||
python = sys.executable | ||
model = os.environ.get("LLM_MODEL", "gpt-3.5-turbo-1106") | ||
|
||
cmd = [ | ||
python, | ||
"-m", | ||
"aider", | ||
"--model", | ||
f"openai/{model}", | ||
"--yes", | ||
"--no-auto-commits", | ||
"--apply", | ||
changes_file, | ||
] + files | ||
|
||
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) | ||
|
||
has_started = False | ||
for line in process.stdout: | ||
if "Model:" in line: | ||
has_started = True | ||
continue | ||
if has_started: | ||
print(line, end="", flush=True) | ||
|
||
return_code = process.wait() | ||
|
||
if return_code != 0: | ||
for line in process.stderr: | ||
print(f"Error: {line.strip()}", file=sys.stderr) | ||
sys.exit(return_code) | ||
|
||
os.remove(changes_file) | ||
|
||
|
||
def main(): | ||
""" | ||
Main function to run the aider command. | ||
This function performs the following tasks: | ||
1. Checks for correct command-line usage | ||
2. Writes the current Python path to the configuration | ||
3. Retrieves the list of files to be processed | ||
4. Runs the aider command with the given message | ||
5. Applies the suggested changes | ||
6. Displays the differences in the IDE | ||
Usage: python command.py <message> | ||
""" | ||
if len(sys.argv) < 2: | ||
print("Usage: python command.py <message>", file=sys.stderr) | ||
sys.exit(1) | ||
|
||
write_python_path_to_config() | ||
|
||
message = sys.argv[1] | ||
files = get_aider_files() | ||
|
||
if not files: | ||
print( | ||
"No files added to aider. Please add files using 'aider.files.add' command.", | ||
file=sys.stderr, | ||
) | ||
sys.exit(1) | ||
|
||
print("Running aider...\n", flush=True) | ||
changes = run_aider(message, files) | ||
|
||
if not changes: | ||
print("No changes suggested by aider.") | ||
sys.exit(0) | ||
|
||
print("\nApplying changes...\n", flush=True) | ||
|
||
# 保存原始文件内容 | ||
original_contents = {} | ||
for file in files: | ||
with open(file, "r") as f: | ||
original_contents[file] = f.read() | ||
|
||
# 应用更改 | ||
apply_changes(changes, files) | ||
|
||
# 读取更新后的文件内容 | ||
updated_contents = {} | ||
for file in files: | ||
with open(file, "r") as f: | ||
updated_contents[file] = f.read() | ||
|
||
# 还原原始文件内容 | ||
for file in files: | ||
with open(file, "w") as f: | ||
f.write(original_contents[file]) | ||
|
||
# 使用 IDEService 展示差异 | ||
ide_service = IDEService() | ||
for index, file in enumerate(files): | ||
ide_service.diff_apply(file, updated_contents[file]) | ||
if index < len(files) - 1: | ||
# 等待用户确认 | ||
button = Button( | ||
["Show Next Changes", "Cancel"], | ||
) | ||
button.render() | ||
|
||
idx = button.clicked | ||
print("click button:", idx) | ||
if idx == 0: | ||
continue | ||
else: | ||
break | ||
|
||
print("Changes have been displayed in the IDE.") | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
description: "aider command" | ||
workflow_python: | ||
env_name: devchat-aider-env | ||
version: 3.11.0 | ||
dependencies: requirements.txt | ||
input: required | ||
help: README.md | ||
steps: | ||
- run: $workflow_python $command_path/command.py "$input" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
### aider.files.add | ||
|
||
添加文件到aider处理列表中。 | ||
|
||
用法: | ||
/aider.files.add <file_path> | ||
|
||
参数: | ||
- <file_path>: 要添加的文件路径(必需) | ||
|
||
描述: | ||
这个命令将指定的文件添加到aider的处理列表中。添加后,该文件将被包含在后续的aider操作中。 | ||
|
||
注意: | ||
- 文件路径必须是有效的格式。 | ||
- 如果文件已经在列表中,它不会被重复添加。 | ||
- 添加成功后,会显示当前aider文件列表。 | ||
|
||
示例: | ||
/aider.files.add src/main.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import os | ||
import sys | ||
|
||
|
||
def is_valid_path(path): | ||
""" | ||
检查路径是否为有效的文件路径形式 | ||
""" | ||
try: | ||
# 尝试规范化路径 | ||
normalized_path = os.path.normpath(path) | ||
# 检查路径是否是绝对路径或相对路径 | ||
return ( | ||
os.path.isabs(normalized_path) | ||
or not os.path.dirname(normalized_path) == normalized_path | ||
) | ||
except Exception: | ||
return False | ||
|
||
|
||
def add_file(file_path): | ||
# 1. 检查是否为有效的文件路径形式 | ||
if not is_valid_path(file_path): | ||
print(f"Error: '{file_path}' is not a valid file path format.", file=sys.stderr) | ||
sys.exit(1) | ||
|
||
# 获取绝对路径 | ||
abs_file_path = file_path.strip() | ||
|
||
# 2. 将新增文件路径存储到.chat/.aider_files文件中 | ||
aider_files_path = os.path.join(".chat", ".aider_files") | ||
|
||
# 确保.chat目录存在 | ||
os.makedirs(os.path.dirname(aider_files_path), exist_ok=True) | ||
|
||
# 读取现有文件列表 | ||
existing_files = set() | ||
if os.path.exists(aider_files_path): | ||
with open(aider_files_path, "r") as f: | ||
existing_files = set(line.strip() for line in f) | ||
|
||
# 添加新文件 | ||
existing_files.add(abs_file_path) | ||
|
||
# 写入更新后的文件列表 | ||
with open(aider_files_path, "w") as f: | ||
for file in sorted(existing_files): | ||
f.write(f"{file}\n") | ||
|
||
print(f"Added '{abs_file_path}' to aider files.") | ||
print("\nCurrent aider files:") | ||
for file in sorted(existing_files): | ||
print(f"- {file}") | ||
|
||
|
||
def main(): | ||
if len(sys.argv) != 2 or sys.argv[1].strip() == "": | ||
print("Usage: /aider.files.add <file_path>", file=sys.stderr) | ||
sys.exit(1) | ||
|
||
file_path = sys.argv[1] | ||
add_file(file_path) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
description: "add files to aider" | ||
input: required | ||
help: README.md | ||
steps: | ||
- run: $devchat_python $command_path/command.py "$input" |
Oops, something went wrong.