auto-coder 0.1.244__py3-none-any.whl → 0.1.246__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of auto-coder might be problematic. Click here for more details.
- {auto_coder-0.1.244.dist-info → auto_coder-0.1.246.dist-info}/METADATA +2 -2
- {auto_coder-0.1.244.dist-info → auto_coder-0.1.246.dist-info}/RECORD +19 -18
- autocoder/agent/auto_review_commit.py +207 -0
- autocoder/auto_coder.py +70 -75
- autocoder/chat_auto_coder.py +26 -15
- autocoder/chat_auto_coder_lang.py +4 -2
- autocoder/common/auto_coder_lang.py +17 -7
- autocoder/index/entry.py +13 -7
- autocoder/index/filter/normal_filter.py +11 -9
- autocoder/index/filter/quick_filter.py +1 -1
- autocoder/index/index.py +11 -5
- autocoder/models.py +10 -2
- autocoder/tsproject/__init__.py +2 -2
- autocoder/utils/auto_coder_utils/chat_stream_out.py +8 -5
- autocoder/version.py +1 -1
- {auto_coder-0.1.244.dist-info → auto_coder-0.1.246.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.244.dist-info → auto_coder-0.1.246.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.244.dist-info → auto_coder-0.1.246.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.244.dist-info → auto_coder-0.1.246.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: auto-coder
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.246
|
|
4
4
|
Summary: AutoCoder: AutoCoder
|
|
5
5
|
Author: allwefantasy
|
|
6
6
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
@@ -26,7 +26,7 @@ Requires-Dist: tabulate
|
|
|
26
26
|
Requires-Dist: jupyter-client
|
|
27
27
|
Requires-Dist: prompt-toolkit
|
|
28
28
|
Requires-Dist: tokenizers
|
|
29
|
-
Requires-Dist: byzerllm[saas] >=0.1.
|
|
29
|
+
Requires-Dist: byzerllm[saas] >=0.1.161
|
|
30
30
|
Requires-Dist: patch
|
|
31
31
|
Requires-Dist: diff-match-patch
|
|
32
32
|
Requires-Dist: GitPython
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
autocoder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
autocoder/auto_coder.py,sha256=
|
|
2
|
+
autocoder/auto_coder.py,sha256=VoSRpvXRLIL3BKGudqFVeO8qolFAjKKWbUbbNQUikDE,63074
|
|
3
3
|
autocoder/auto_coder_lang.py,sha256=Rtupq6N3_HT7JRhDKdgCBcwRaiAnyCOR_Gsp4jUomrI,3229
|
|
4
4
|
autocoder/auto_coder_rag.py,sha256=illKgzP2bv-Tq50ujsofJnOHdI4pzr0ALtfR8NHHWdQ,22351
|
|
5
5
|
autocoder/auto_coder_rag_client_mcp.py,sha256=WV7j5JUiQge0x4-B7Hp5-pSAFXLbvLpzQMcCovbauIM,6276
|
|
6
6
|
autocoder/auto_coder_rag_mcp.py,sha256=-RrjNwFaS2e5v8XDIrKR-zlUNUE8UBaeOtojffBrvJo,8521
|
|
7
7
|
autocoder/auto_coder_server.py,sha256=XU9b4SBH7zjPPXaTWWHV4_zJm-XYa6njuLQaplYJH_c,20290
|
|
8
8
|
autocoder/benchmark.py,sha256=Ypomkdzd1T3GE6dRICY3Hj547dZ6_inqJbBJIp5QMco,4423
|
|
9
|
-
autocoder/chat_auto_coder.py,sha256=
|
|
10
|
-
autocoder/chat_auto_coder_lang.py,sha256=
|
|
9
|
+
autocoder/chat_auto_coder.py,sha256=wdFPshtAWiFrDkCKHSxKKDhcnHQnd9mW0vQZcaRQlC4,105965
|
|
10
|
+
autocoder/chat_auto_coder_lang.py,sha256=gbpjfMd1wYiIrOlLDc-G7eI497mMwjM_ud9GvO-wo9k,15261
|
|
11
11
|
autocoder/command_args.py,sha256=9aYJ-AmPxP1sQh6ciw04FWHjSn31f2W9afXFwo8wgx4,30441
|
|
12
12
|
autocoder/lang.py,sha256=U6AjVV8Rs1uLyjFCZ8sT6WWuNUxMBqkXXIOs4S120uk,14511
|
|
13
|
-
autocoder/models.py,sha256=
|
|
14
|
-
autocoder/version.py,sha256=
|
|
13
|
+
autocoder/models.py,sha256=_9Kc8oS_tnnqKzRGnybgOfn1NOey7OXZ8y9qhBmgiB4,5517
|
|
14
|
+
autocoder/version.py,sha256=5HxDu_oJkWkJDjnFdCKsIoI4evQ0gJJY_wccUUoUJTU,23
|
|
15
15
|
autocoder/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
autocoder/agent/auto_demand_organizer.py,sha256=NWSAEsEk94vT3lGjfo25kKLMwYdPcpy9e-i21txPasQ,6942
|
|
17
17
|
autocoder/agent/auto_filegroup.py,sha256=CW7bqp0FW1GIEMnl-blyAc2UGT7O9Mom0q66ITz1ckM,6635
|
|
18
18
|
autocoder/agent/auto_guess_query.py,sha256=rDSdhpPHcOGE5MuDXvIrhCXAPR4ARS1LqpyoLsx2Jhw,11374
|
|
19
|
+
autocoder/agent/auto_review_commit.py,sha256=3_XgcOGNbpOnwq9WMj66rceZFEa4lEQvs9OZdKQi7co,7663
|
|
19
20
|
autocoder/agent/auto_tool.py,sha256=DBzip-P_T6ZtT2eHexPcusmKYD0h7ufzp7TLwXAY10E,11554
|
|
20
21
|
autocoder/agent/coder.py,sha256=x6bdJwDuETGg9ebQnYlUWCxCtQcDGg73LtI6McpWslQ,72034
|
|
21
22
|
autocoder/agent/designer.py,sha256=EpRbzO58Xym3GrnppIT1Z8ZFAlnNfgzHbIzZ3PX-Yv8,27037
|
|
@@ -28,7 +29,7 @@ autocoder/common/__init__.py,sha256=2isE_u4VgfogwmcUCnFcussVFlzeNOLHDMFm5z_axbU,
|
|
|
28
29
|
autocoder/common/anything2images.py,sha256=0ILBbWzY02M-CiWB-vzuomb_J1hVdxRcenAfIrAXq9M,25283
|
|
29
30
|
autocoder/common/anything2img.py,sha256=4TREa-sOA-iargieUy7MpyCYVUE-9Mmq0wJtwomPqnE,7662
|
|
30
31
|
autocoder/common/audio.py,sha256=Kn9nWKQddWnUrAz0a_ZUgjcu4VUU_IcZBigT7n3N3qc,7439
|
|
31
|
-
autocoder/common/auto_coder_lang.py,sha256=
|
|
32
|
+
autocoder/common/auto_coder_lang.py,sha256=Slwyy0LNqsgHbyWIImYz8l4ke9cT9GagZA4HtbTXIX0,14065
|
|
32
33
|
autocoder/common/buildin_tokenizer.py,sha256=L7d5t39ZFvUd6EoMPXUhYK1toD0FHlRH1jtjKRGokWU,1236
|
|
33
34
|
autocoder/common/chunk_validation.py,sha256=BrR_ZWavW8IANuueEE7hS8NFAwEvm8TX34WnPx_1hs8,3030
|
|
34
35
|
autocoder/common/cleaner.py,sha256=NU72i8C6o9m0vXExab7nao5bstBUsfJFcj11cXa9l4U,1089
|
|
@@ -77,14 +78,14 @@ autocoder/dispacher/actions/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQ
|
|
|
77
78
|
autocoder/dispacher/actions/plugins/action_regex_project.py,sha256=ht_HWzZt84IEogoFMggnXI6aFFerrsuksVflAkcodfU,5545
|
|
78
79
|
autocoder/dispacher/actions/plugins/action_translate.py,sha256=nVAtRSQpdGNmZxg1R_9zXG3AuTv3CHf2v7ODgj8u65c,7727
|
|
79
80
|
autocoder/index/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
80
|
-
autocoder/index/entry.py,sha256=
|
|
81
|
+
autocoder/index/entry.py,sha256=hXSOi-jPgRBKQB55eqWkT95vxvWrbVHDuIMtDkqjNNw,12232
|
|
81
82
|
autocoder/index/for_command.py,sha256=BFvljE4t6VaMBGboZAuhUCzVK0EitCy_n5D_7FEnihw,3204
|
|
82
|
-
autocoder/index/index.py,sha256=
|
|
83
|
+
autocoder/index/index.py,sha256=xwh22nY0TtEJMJwYjOUd6xdRZozYXBt47YSwheZSP-4,20679
|
|
83
84
|
autocoder/index/symbols_utils.py,sha256=CjcjUVajmJZB75Ty3a7kMv1BZphrm-tIBAdOJv6uo-0,2037
|
|
84
85
|
autocoder/index/types.py,sha256=a2s_KV5FJlq7jqA2ELSo9E1sjuLwDB-JJYMhSpzBAhU,596
|
|
85
86
|
autocoder/index/filter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
86
|
-
autocoder/index/filter/normal_filter.py,sha256=
|
|
87
|
-
autocoder/index/filter/quick_filter.py,sha256=
|
|
87
|
+
autocoder/index/filter/normal_filter.py,sha256=APu34iSvWhtlLtWgkj8N3Vo4oW1TegtZQq2bwDX_cs4,8031
|
|
88
|
+
autocoder/index/filter/quick_filter.py,sha256=Omvsz9O1xQEH4xP-wNuCZhxn69P7Y59SiLPUIDuGFiA,3851
|
|
88
89
|
autocoder/pyproject/__init__.py,sha256=dQ2_7YZ7guybT9BhfxSGn43eLQJGQN2zgeKa6--JlaQ,14403
|
|
89
90
|
autocoder/rag/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
90
91
|
autocoder/rag/api_server.py,sha256=dRbhAZVRAOlZ64Cnxf4_rKb4iJwHnrWS9Zr67IVORw0,7288
|
|
@@ -120,7 +121,7 @@ autocoder/rag/stream_event/types.py,sha256=rtLwOE8rShmi1dJdxyBpAV5ZjLBGG9vptMiSz
|
|
|
120
121
|
autocoder/regex_project/__init__.py,sha256=EBZeCL5ORyD_9_5u_UuG4s7XtpXOu0y1sWDmxWFtufE,6781
|
|
121
122
|
autocoder/regexproject/__init__.py,sha256=cEr-ZOaQjLD5sx7T7F2DhD5ips03HcJ02rded9EpSXc,9693
|
|
122
123
|
autocoder/suffixproject/__init__.py,sha256=VcXjUbGf3uQrpoqVCItDvGG9DoeHJ_qEmghKwrVNw9w,11058
|
|
123
|
-
autocoder/tsproject/__init__.py,sha256=
|
|
124
|
+
autocoder/tsproject/__init__.py,sha256=boNuRCHi94xI_y4tvL5LKgSZ4gYxcPqUUQTw9MU_STI,11751
|
|
124
125
|
autocoder/utils/__init__.py,sha256=KtcGElFNBgZPF7dEL8zF9JpXkCAjoyDrzaREJBhJrcs,994
|
|
125
126
|
autocoder/utils/_markitdown.py,sha256=RU88qn4eZfYIy0GDrPxlI8oYXIypbi63VRJjdlnE0VU,47431
|
|
126
127
|
autocoder/utils/coder.py,sha256=rK8e0svQBe0NOP26dIGToUXgha_hUDgxlWoC_p_r7oc,5698
|
|
@@ -138,11 +139,11 @@ autocoder/utils/rest.py,sha256=hLBhr78y-WVnV0oQf9Rxc22EwqF78KINkScvYa1MuYA,6435
|
|
|
138
139
|
autocoder/utils/tests.py,sha256=BqphrwyycGAvs-5mhH8pKtMZdObwhFtJ5MC_ZAOiLq8,1340
|
|
139
140
|
autocoder/utils/types.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
140
141
|
autocoder/utils/auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
141
|
-
autocoder/utils/auto_coder_utils/chat_stream_out.py,sha256=
|
|
142
|
+
autocoder/utils/auto_coder_utils/chat_stream_out.py,sha256=64WfP5rFKYwI9OXrpRTQjUQa9n6ULTscubKziot-rAU,9218
|
|
142
143
|
autocoder/utils/chat_auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
143
|
-
auto_coder-0.1.
|
|
144
|
-
auto_coder-0.1.
|
|
145
|
-
auto_coder-0.1.
|
|
146
|
-
auto_coder-0.1.
|
|
147
|
-
auto_coder-0.1.
|
|
148
|
-
auto_coder-0.1.
|
|
144
|
+
auto_coder-0.1.246.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
|
|
145
|
+
auto_coder-0.1.246.dist-info/METADATA,sha256=zENdZdSfMKFmZWd-N1GIOXfm8xWnBv0nG-s9I3UpZqY,2616
|
|
146
|
+
auto_coder-0.1.246.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
147
|
+
auto_coder-0.1.246.dist-info/entry_points.txt,sha256=0nzHtHH4pNcM7xq4EBA2toS28Qelrvcbrr59GqD_0Ak,350
|
|
148
|
+
auto_coder-0.1.246.dist-info/top_level.txt,sha256=Jqc0_uJSw2GwoFQAa9iJxYns-2mWla-9ok_Y3Gcznjk,10
|
|
149
|
+
auto_coder-0.1.246.dist-info/RECORD,,
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
from typing import Generator, List, Dict, Union, Tuple, Optional
|
|
2
|
+
import os
|
|
3
|
+
import yaml
|
|
4
|
+
import byzerllm
|
|
5
|
+
import pydantic
|
|
6
|
+
import git
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
from autocoder.utils.auto_coder_utils.chat_stream_out import stream_out
|
|
9
|
+
from autocoder.common.printer import Printer
|
|
10
|
+
from autocoder.common import AutoCoderArgs
|
|
11
|
+
from autocoder.common.utils_code_auto_generate import stream_chat_with_continue
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def load_yaml_config(yaml_file: str) -> Dict:
|
|
15
|
+
"""加载YAML配置文件"""
|
|
16
|
+
try:
|
|
17
|
+
with open(yaml_file, 'r', encoding='utf-8') as f:
|
|
18
|
+
return yaml.safe_load(f)
|
|
19
|
+
except Exception as e:
|
|
20
|
+
printer = Printer()
|
|
21
|
+
printer.print_in_terminal("yaml_load_error", style="red", yaml_file=yaml_file, error=str(e))
|
|
22
|
+
return {}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class AutoReviewCommit:
|
|
26
|
+
def __init__(self, llm: Union[byzerllm.ByzerLLM,byzerllm.SimpleByzerLLM],
|
|
27
|
+
args:AutoCoderArgs,
|
|
28
|
+
skip_diff: bool = False,
|
|
29
|
+
console: Optional[Console] = None):
|
|
30
|
+
"""
|
|
31
|
+
初始化 AutoReviewCommit
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
llm: ByzerLLM 实例,用于代码审查
|
|
35
|
+
project_dir: 项目根目录
|
|
36
|
+
skip_diff: 是否跳过获取 diff 信息
|
|
37
|
+
"""
|
|
38
|
+
self.project_dir = args.source_dir
|
|
39
|
+
self.actions_dir = os.path.join(args.source_dir, "actions")
|
|
40
|
+
self.llm = llm
|
|
41
|
+
self.skip_diff = skip_diff
|
|
42
|
+
self.console = console or Console()
|
|
43
|
+
|
|
44
|
+
@byzerllm.prompt()
|
|
45
|
+
def review(self, querie_with_urls_and_diffs: List[Tuple[str, List[str], str]], query: str) -> Generator[str,None,None]:
|
|
46
|
+
"""
|
|
47
|
+
如果前面我们对话提供了文档,请参考上面的文档对提交的代码变更进行审查,提供改进建议。
|
|
48
|
+
|
|
49
|
+
下面包含最新一次提交的信息:
|
|
50
|
+
<commit>
|
|
51
|
+
{% for query,urls,diff in querie_with_urls_and_diffs %}
|
|
52
|
+
## 任务需求
|
|
53
|
+
{{ query }}
|
|
54
|
+
|
|
55
|
+
修改的文件:
|
|
56
|
+
{% for url in urls %}
|
|
57
|
+
- {{ url }}
|
|
58
|
+
{% endfor %}
|
|
59
|
+
|
|
60
|
+
代码变更:
|
|
61
|
+
```diff
|
|
62
|
+
{{ diff }}
|
|
63
|
+
```
|
|
64
|
+
{% endfor %}
|
|
65
|
+
</commit>
|
|
66
|
+
|
|
67
|
+
审查要求:
|
|
68
|
+
1. 代码质量评估
|
|
69
|
+
- 代码可读性:命名、注释、代码结构是否清晰
|
|
70
|
+
- 代码风格:是否符合项目规范
|
|
71
|
+
- 实现逻辑:算法和数据结构的选择是否合适
|
|
72
|
+
|
|
73
|
+
2. 潜在问题检查
|
|
74
|
+
- 常见错误:是否存在空指针,数组越界,类型转换,未声明变量,typo等低级错误
|
|
75
|
+
- 安全性:是否存在安全隐患
|
|
76
|
+
- 性能:是否有性能问题
|
|
77
|
+
- 并发:是否有并发安全问题
|
|
78
|
+
- 异常处理:错误处理是否完善
|
|
79
|
+
- 资源管理:是否有资源泄露风险
|
|
80
|
+
|
|
81
|
+
3. 架构合理性
|
|
82
|
+
- 模块化:职责划分是否合理
|
|
83
|
+
- 可扩展性:是否方便未来扩展
|
|
84
|
+
- 依赖关系:组件耦合是否合理
|
|
85
|
+
- 复用性:是否有重复代码
|
|
86
|
+
|
|
87
|
+
返回格式说明:
|
|
88
|
+
返回 markdown 格式,包含以下内容:
|
|
89
|
+
1. issues: 发现的具体问题列表
|
|
90
|
+
2. suggestions: 对应的改进建议列表
|
|
91
|
+
3. severity: 问题的严重程度(low/medium/high)
|
|
92
|
+
4. affected_files: 受影响的文件列表
|
|
93
|
+
5. summary: 总体评价
|
|
94
|
+
|
|
95
|
+
{% if query %}
|
|
96
|
+
用户额外 review 需求:
|
|
97
|
+
<user_review_requirement>
|
|
98
|
+
{{ query }}
|
|
99
|
+
</user_review_requirement>
|
|
100
|
+
{% endif %}
|
|
101
|
+
|
|
102
|
+
注意:
|
|
103
|
+
1. 评审意见应该具体且可操作,而不是泛泛而谈
|
|
104
|
+
2. 对于每个问题都应该提供明确的改进建议
|
|
105
|
+
3. 严重程度的判断要考虑问题对系统的潜在影响
|
|
106
|
+
4. 建议应该符合项目的技术栈和开发规范
|
|
107
|
+
"""
|
|
108
|
+
pass
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def parse_history_tasks(self) -> List[Dict]:
|
|
112
|
+
"""
|
|
113
|
+
解析历史任务信息
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
List[Dict]: 每个字典包含一个历史任务的信息
|
|
117
|
+
"""
|
|
118
|
+
# 获取所有YAML文件
|
|
119
|
+
action_files = [
|
|
120
|
+
f for f in os.listdir(self.actions_dir)
|
|
121
|
+
if f[:3].isdigit() and "_" in f and f.endswith('.yml')
|
|
122
|
+
]
|
|
123
|
+
|
|
124
|
+
# 按序号排序
|
|
125
|
+
def get_seq(name):
|
|
126
|
+
return int(name.split("_")[0])
|
|
127
|
+
|
|
128
|
+
# 获取最新的action文件列表
|
|
129
|
+
action_files = sorted(action_files, key=get_seq)
|
|
130
|
+
action_files.reverse()
|
|
131
|
+
|
|
132
|
+
action_file = action_files[0]
|
|
133
|
+
|
|
134
|
+
querie_with_urls_and_diffs = []
|
|
135
|
+
repo = git.Repo(self.project_dir)
|
|
136
|
+
|
|
137
|
+
# 收集所有query、urls和对应的commit diff
|
|
138
|
+
for yaml_file in [action_file]:
|
|
139
|
+
yaml_path = os.path.join(self.actions_dir, yaml_file)
|
|
140
|
+
config = load_yaml_config(yaml_path)
|
|
141
|
+
|
|
142
|
+
if not config:
|
|
143
|
+
continue
|
|
144
|
+
|
|
145
|
+
query = config.get('query', '')
|
|
146
|
+
urls = config.get('urls', [])
|
|
147
|
+
|
|
148
|
+
if query and urls:
|
|
149
|
+
commit_diff = ""
|
|
150
|
+
if not self.skip_diff:
|
|
151
|
+
# 计算文件的MD5用于匹配commit
|
|
152
|
+
import hashlib
|
|
153
|
+
file_md5 = hashlib.md5(open(yaml_path, 'rb').read()).hexdigest()
|
|
154
|
+
response_id = f"auto_coder_{yaml_file}_{file_md5}"
|
|
155
|
+
# 查找对应的commit
|
|
156
|
+
try:
|
|
157
|
+
for commit in repo.iter_commits():
|
|
158
|
+
if response_id in commit.message:
|
|
159
|
+
if commit.parents:
|
|
160
|
+
parent = commit.parents[0]
|
|
161
|
+
commit_diff = repo.git.diff(
|
|
162
|
+
parent.hexsha, commit.hexsha)
|
|
163
|
+
else:
|
|
164
|
+
commit_diff = repo.git.show(commit.hexsha)
|
|
165
|
+
break
|
|
166
|
+
except git.exc.GitCommandError as e:
|
|
167
|
+
printer = Printer()
|
|
168
|
+
printer.print_in_terminal("git_command_error", style="red", error=str(e))
|
|
169
|
+
except Exception as e:
|
|
170
|
+
printer = Printer()
|
|
171
|
+
printer.print_in_terminal("get_commit_diff_error", style="red", error=str(e))
|
|
172
|
+
|
|
173
|
+
querie_with_urls_and_diffs.append((query, urls, commit_diff))
|
|
174
|
+
|
|
175
|
+
return querie_with_urls_and_diffs
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def review_commit(self,query: str, conversations: List[Dict]) -> Generator[str,None,None]:
|
|
179
|
+
"""
|
|
180
|
+
审查最新的代码提交
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
Optional[ReviewResult]: 审查结果,如果出错则返回None
|
|
184
|
+
"""
|
|
185
|
+
printer = Printer()
|
|
186
|
+
# 获取最新的提交信息
|
|
187
|
+
commits = self.parse_history_tasks()
|
|
188
|
+
if not commits:
|
|
189
|
+
printer.print_in_terminal("no_latest_commit", style="red")
|
|
190
|
+
return None
|
|
191
|
+
|
|
192
|
+
# 调用LLM进行代码审查
|
|
193
|
+
try:
|
|
194
|
+
# 获取 prompt 内容
|
|
195
|
+
query = self.review.prompt(commits, query)
|
|
196
|
+
new_conversations = conversations.copy()[0:-1]
|
|
197
|
+
new_conversations.append({"role": "user", "content": query})
|
|
198
|
+
# 构造对话消息
|
|
199
|
+
v = stream_chat_with_continue(
|
|
200
|
+
llm=self.llm,
|
|
201
|
+
conversations=new_conversations,
|
|
202
|
+
llm_config={}
|
|
203
|
+
)
|
|
204
|
+
return v
|
|
205
|
+
except Exception as e:
|
|
206
|
+
printer.print_in_terminal("code_review_error", style="red", error=str(e))
|
|
207
|
+
return None
|
autocoder/auto_coder.py
CHANGED
|
@@ -278,8 +278,13 @@ def main(input_args: Optional[List[str]] = None):
|
|
|
278
278
|
|
|
279
279
|
llm = byzerllm.ByzerLLM(verbose=args.print_request)
|
|
280
280
|
|
|
281
|
+
# code_model,index_filter_model,generate_rerank_model,chat_model
|
|
282
|
+
# 这四个模型如果用户没有设置,就会使用默认的
|
|
283
|
+
# 如果用户随便填写 deepseek 官方key,就会导致 Authentic(No User) 的错误
|
|
284
|
+
# 或者 Insuffient Balance 之类的错误
|
|
285
|
+
|
|
281
286
|
code_model = byzerllm.ByzerLLM()
|
|
282
|
-
code_model.setup_default_model_name(
|
|
287
|
+
code_model.setup_default_model_name(args.model)
|
|
283
288
|
llm.setup_sub_client("code_model", code_model)
|
|
284
289
|
|
|
285
290
|
index_filter_model = byzerllm.ByzerLLM()
|
|
@@ -295,84 +300,66 @@ def main(input_args: Optional[List[str]] = None):
|
|
|
295
300
|
llm.setup_sub_client("chat_model", chat_model)
|
|
296
301
|
|
|
297
302
|
if args.product_mode == "lite":
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if not os.path.exists(api_key_file):
|
|
303
|
-
raise Exception(f"API key file not found: {api_key_file}")
|
|
304
|
-
|
|
305
|
-
with open(api_key_file, "r") as f:
|
|
306
|
-
api_key = f.read()
|
|
307
|
-
|
|
303
|
+
default_model = args.model
|
|
304
|
+
model_info = models_module.get_model_by_name(default_model)
|
|
305
|
+
llm = byzerllm.SimpleByzerLLM(default_model_name=default_model)
|
|
308
306
|
llm.deploy(
|
|
309
307
|
model_path="",
|
|
310
|
-
pretrained_model_type="
|
|
311
|
-
udf_name=
|
|
308
|
+
pretrained_model_type=model_info["model_type"],
|
|
309
|
+
udf_name=args.model,
|
|
312
310
|
infer_params={
|
|
313
|
-
"saas.base_url": "
|
|
314
|
-
"saas.api_key": api_key,
|
|
315
|
-
"saas.model": "
|
|
316
|
-
"saas.is_reasoning":
|
|
311
|
+
"saas.base_url": model_info["base_url"],
|
|
312
|
+
"saas.api_key": model_info["api_key"],
|
|
313
|
+
"saas.model": model_info["model_name"],
|
|
314
|
+
"saas.is_reasoning": model_info["is_reasoning"]
|
|
317
315
|
}
|
|
318
|
-
)
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
"saas
|
|
327
|
-
"
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
model_path="",
|
|
336
|
-
pretrained_model_type="saas/openai",
|
|
337
|
-
udf_name="deepseek_r1_chat",
|
|
338
|
-
infer_params={
|
|
339
|
-
"saas.base_url": "https://api.deepseek.com/v1",
|
|
340
|
-
"saas.api_key": api_key,
|
|
341
|
-
"saas.model": "deepseek-reasoner",
|
|
342
|
-
"saas.is_reasoning": True
|
|
343
|
-
}
|
|
344
|
-
)
|
|
345
|
-
|
|
346
|
-
generate_rerank_llm = byzerllm.SimpleByzerLLM(default_model_name="deepseek_r1_chat")
|
|
347
|
-
generate_rerank_llm.deploy(
|
|
348
|
-
model_path="",
|
|
349
|
-
pretrained_model_type="saas/openai",
|
|
350
|
-
udf_name="deepseek_r1_chat",
|
|
351
|
-
infer_params={
|
|
352
|
-
"saas.base_url": "https://api.deepseek.com/v1",
|
|
353
|
-
"saas.api_key": api_key,
|
|
354
|
-
"saas.model": "deepseek-reasoner",
|
|
355
|
-
"saas.is_reasoning": True
|
|
356
|
-
}
|
|
357
|
-
)
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
if models_module.check_model_exists("deepseek_r1_chat"):
|
|
319
|
+
r1_model_info = models_module.get_model_by_name("deepseek_r1_chat")
|
|
320
|
+
api_key = r1_model_info["api_key"]
|
|
321
|
+
chat_llm = byzerllm.SimpleByzerLLM(default_model_name="deepseek_r1_chat")
|
|
322
|
+
chat_llm.deploy(
|
|
323
|
+
model_path="",
|
|
324
|
+
pretrained_model_type="saas/openai",
|
|
325
|
+
udf_name="deepseek_r1_chat",
|
|
326
|
+
infer_params={
|
|
327
|
+
"saas.base_url": "https://api.deepseek.com/v1",
|
|
328
|
+
"saas.api_key": api_key,
|
|
329
|
+
"saas.model": "deepseek-reasoner",
|
|
330
|
+
"saas.is_reasoning": True
|
|
331
|
+
}
|
|
332
|
+
)
|
|
358
333
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
334
|
+
generate_rerank_llm = byzerllm.SimpleByzerLLM(default_model_name="deepseek_r1_chat")
|
|
335
|
+
generate_rerank_llm.deploy(
|
|
336
|
+
model_path="",
|
|
337
|
+
pretrained_model_type="saas/openai",
|
|
338
|
+
udf_name="deepseek_r1_chat",
|
|
339
|
+
infer_params={
|
|
340
|
+
"saas.base_url": "https://api.deepseek.com/v1",
|
|
341
|
+
"saas.api_key": api_key,
|
|
342
|
+
"saas.model": "deepseek-reasoner",
|
|
343
|
+
"saas.is_reasoning": True
|
|
344
|
+
}
|
|
345
|
+
)
|
|
371
346
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
347
|
+
index_filter_llm = byzerllm.SimpleByzerLLM(default_model_name="deepseek_r1_chat")
|
|
348
|
+
index_filter_llm.deploy(
|
|
349
|
+
model_path="",
|
|
350
|
+
pretrained_model_type="saas/openai",
|
|
351
|
+
udf_name="deepseek_r1_chat",
|
|
352
|
+
infer_params={
|
|
353
|
+
"saas.base_url": "https://api.deepseek.com/v1",
|
|
354
|
+
"saas.api_key": api_key,
|
|
355
|
+
"saas.model": "deepseek-reasoner",
|
|
356
|
+
"saas.is_reasoning": True
|
|
357
|
+
}
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
llm.setup_sub_client("chat_model", chat_llm)
|
|
361
|
+
llm.setup_sub_client("generate_rerank_model", generate_rerank_llm)
|
|
362
|
+
llm.setup_sub_client("index_filter_model", index_filter_llm)
|
|
376
363
|
|
|
377
364
|
if args.product_mode == "lite":
|
|
378
365
|
# Set up default models based on configuration
|
|
@@ -1349,6 +1336,10 @@ def main(input_args: Optional[List[str]] = None):
|
|
|
1349
1336
|
)
|
|
1350
1337
|
)
|
|
1351
1338
|
v = [[response.result,None]]
|
|
1339
|
+
elif "review_commit" in args.action:
|
|
1340
|
+
from autocoder.agent.auto_review_commit import AutoReviewCommit
|
|
1341
|
+
reviewer = AutoReviewCommit(llm=chat_llm, args=args)
|
|
1342
|
+
v = reviewer.review_commit(args.query)
|
|
1352
1343
|
else:
|
|
1353
1344
|
v = stream_chat_with_continue(
|
|
1354
1345
|
llm=chat_llm,
|
|
@@ -1356,12 +1347,16 @@ def main(input_args: Optional[List[str]] = None):
|
|
|
1356
1347
|
llm_config={}
|
|
1357
1348
|
)
|
|
1358
1349
|
|
|
1359
|
-
|
|
1350
|
+
|
|
1351
|
+
model_name = getattr(chat_llm, 'default_model_name', None)
|
|
1352
|
+
if not model_name:
|
|
1353
|
+
model_name = "unknown(without default model name)"
|
|
1360
1354
|
|
|
1361
1355
|
assistant_response, last_meta = stream_out(
|
|
1362
1356
|
v,
|
|
1363
1357
|
request_id=args.request_id,
|
|
1364
|
-
console=console
|
|
1358
|
+
console=console,
|
|
1359
|
+
model_name=model_name
|
|
1365
1360
|
)
|
|
1366
1361
|
|
|
1367
1362
|
# 打印耗时和token统计
|
autocoder/chat_auto_coder.py
CHANGED
|
@@ -1937,14 +1937,18 @@ def chat(query: str):
|
|
|
1937
1937
|
if "/save" in query:
|
|
1938
1938
|
yaml_config["action"].append("save")
|
|
1939
1939
|
query = query.replace("/save", "", 1).strip()
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
query = query.replace("/review", "", 1).strip()
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
query =
|
|
1940
|
+
|
|
1941
|
+
if "/review" in query and "/commit" in query:
|
|
1942
|
+
yaml_config["action"].append("review_commit")
|
|
1943
|
+
query = query.replace("/review", "", 1).replace("/commit", "", 1).strip()
|
|
1944
|
+
else:
|
|
1945
|
+
is_review = query.strip().startswith("/review")
|
|
1946
|
+
if is_review:
|
|
1947
|
+
query = query.replace("/review", "", 1).strip()
|
|
1948
|
+
if "prompt_review" in conf:
|
|
1949
|
+
query = format_str_jinja2(conf["prompt_review"], query=query)
|
|
1950
|
+
else:
|
|
1951
|
+
query = code_review.prompt(query)
|
|
1948
1952
|
|
|
1949
1953
|
is_no_context = query.strip().startswith("/no_context")
|
|
1950
1954
|
if is_no_context:
|
|
@@ -2194,13 +2198,14 @@ def manage_models(params, query: str):
|
|
|
2194
2198
|
table.add_column("Base URL", style="white", width=50, overflow="fold")
|
|
2195
2199
|
for m in models_data:
|
|
2196
2200
|
# Check if api_key_path exists and file exists
|
|
2197
|
-
|
|
2198
|
-
name = m.get("name", "")
|
|
2199
|
-
if
|
|
2200
|
-
|
|
2201
|
-
if
|
|
2202
|
-
|
|
2203
|
-
|
|
2201
|
+
is_api_key_set = "api_key" in m
|
|
2202
|
+
name = m.get("name", "")
|
|
2203
|
+
if is_api_key_set:
|
|
2204
|
+
api_key = m.get("api_key", "").strip()
|
|
2205
|
+
if not api_key:
|
|
2206
|
+
printer.print_in_terminal("models_api_key_empty", style="yellow", name=name)
|
|
2207
|
+
name = f"{name} *"
|
|
2208
|
+
|
|
2204
2209
|
table.add_row(
|
|
2205
2210
|
name,
|
|
2206
2211
|
m.get("model_name", ""),
|
|
@@ -2700,6 +2705,12 @@ def main():
|
|
|
2700
2705
|
if "mode" not in memory:
|
|
2701
2706
|
memory["mode"] = "normal"
|
|
2702
2707
|
|
|
2708
|
+
# 处理 user_input 的空格
|
|
2709
|
+
if user_input:
|
|
2710
|
+
temp_user_input = user_input.lstrip() # 去掉左侧空格
|
|
2711
|
+
if temp_user_input.startswith('/'):
|
|
2712
|
+
user_input = temp_user_input
|
|
2713
|
+
|
|
2703
2714
|
if (
|
|
2704
2715
|
memory["mode"] == "auto_detect"
|
|
2705
2716
|
and user_input
|
|
@@ -111,7 +111,8 @@ MESSAGES = {
|
|
|
111
111
|
"remove_files_all": "Removed all files.",
|
|
112
112
|
"remove_files_removed": "Removed Files",
|
|
113
113
|
"remove_files_none": "No files were removed.",
|
|
114
|
-
"files_removed": "Files Removed"
|
|
114
|
+
"files_removed": "Files Removed",
|
|
115
|
+
"models_api_key_empty": "Warning : {{name}} API key is empty. Please set a valid API key.",
|
|
115
116
|
},
|
|
116
117
|
"zh": {
|
|
117
118
|
"mcp_remove_error": "移除 MCP 服务器时出错:{error}",
|
|
@@ -222,7 +223,8 @@ MESSAGES = {
|
|
|
222
223
|
"remove_files_all": "已移除所有文件。",
|
|
223
224
|
"remove_files_removed": "已移除的文件",
|
|
224
225
|
"remove_files_none": "没有文件被移除。",
|
|
225
|
-
"files_removed": "移除的文件"
|
|
226
|
+
"files_removed": "移除的文件",
|
|
227
|
+
"models_api_key_empty": "警告: {{name}} API key 为空。请设置一个有效的 API key。",
|
|
226
228
|
}
|
|
227
229
|
}
|
|
228
230
|
|
|
@@ -8,9 +8,14 @@ MESSAGES = {
|
|
|
8
8
|
"memory_save_success": "✅ Saved to your memory",
|
|
9
9
|
"file_decode_error": "Failed to decode file: {{file_path}}. Tried encodings: {{encodings}}",
|
|
10
10
|
"file_write_error": "Failed to write file: {{file_path}}. Error: {{error}}",
|
|
11
|
+
"yaml_load_error": "Error loading yaml file {{yaml_file}}: {{error}}",
|
|
12
|
+
"git_command_error": "Git command execution error: {{error}}",
|
|
13
|
+
"get_commit_diff_error": "Error getting commit diff: {{error}}",
|
|
14
|
+
"no_latest_commit": "Unable to get latest commit information",
|
|
15
|
+
"code_review_error": "Code review process error: {{error}}",
|
|
11
16
|
"index_file_too_large": "⚠️ File {{ file_path }} is too large ({{ file_size }} > {{ max_length }}), splitting into chunks...",
|
|
12
|
-
"index_update_success": "✅ Successfully updated index for {{ file_path }} (md5: {{ md5 }}) in {{ duration }}s",
|
|
13
|
-
"index_build_error": "❌ Error building index for {{ file_path }}: {{ error }}",
|
|
17
|
+
"index_update_success": "✅ {{ model_name }} Successfully updated index for {{ file_path }} (md5: {{ md5 }}) in {{ duration }}s",
|
|
18
|
+
"index_build_error": "❌ {{ model_name }} Error building index for {{ file_path }}: {{ error }}",
|
|
14
19
|
"index_build_summary": "📊 Total Files: {{ total_files }}, Need to Build Index: {{ num_files }}",
|
|
15
20
|
"building_index_progress": "⏳ Building Index: {{ counter }}/{{ num_files }}...",
|
|
16
21
|
"index_source_dir_mismatch": "⚠️ Source directory mismatch (file_path: {{ file_path }}, source_dir: {{ source_dir }})",
|
|
@@ -49,7 +54,7 @@ MESSAGES = {
|
|
|
49
54
|
"code_merge_start": "Auto merge the code...",
|
|
50
55
|
"code_execution_warning": "Content(send to model) is {{ content_length }} tokens (you may collect too much files), which is larger than the maximum input length {{ max_length }}",
|
|
51
56
|
"quick_filter_start": "Starting filter context(quick_filter)...",
|
|
52
|
-
"normal_filter_start": "Starting filter context(normal_filter)...",
|
|
57
|
+
"normal_filter_start": "{{ model_name }} Starting filter context(normal_filter)...",
|
|
53
58
|
"pylint_check_failed": "⚠️ Pylint check failed: {{ error_message }}",
|
|
54
59
|
"pylint_error": "❌ Error running pylint: {{ error_message }}",
|
|
55
60
|
"unmerged_blocks_warning": "⚠️ Found {{ num_blocks }} unmerged blocks, the changes will not be applied. Please review them manually then try again.",
|
|
@@ -82,9 +87,14 @@ MESSAGES = {
|
|
|
82
87
|
"memory_save_success": "✅ 已保存到您的记忆中",
|
|
83
88
|
"file_decode_error": "无法解码文件: {{file_path}}。尝试的编码: {{encodings}}",
|
|
84
89
|
"file_write_error": "无法写入文件: {{file_path}}. 错误: {{error}}",
|
|
90
|
+
"yaml_load_error": "加载YAML文件出错 {{yaml_file}}: {{error}}",
|
|
91
|
+
"git_command_error": "Git命令执行错误: {{error}}",
|
|
92
|
+
"get_commit_diff_error": "获取commit diff时出错: {{error}}",
|
|
93
|
+
"no_latest_commit": "无法获取最新的提交信息",
|
|
94
|
+
"code_review_error": "代码审查过程出错: {{error}}",
|
|
85
95
|
"index_file_too_large": "⚠️ 文件 {{ file_path }} 过大 ({{ file_size }} > {{ max_length }}), 正在分块处理...",
|
|
86
|
-
"index_update_success": "✅ 成功更新 {{ file_path }} 的索引 (md5: {{ md5 }}), 耗时 {{ duration }} 秒",
|
|
87
|
-
"index_build_error": "❌ 构建 {{ file_path }} 索引时出错: {{ error }}",
|
|
96
|
+
"index_update_success": "✅ {{ model_name }} 成功更新 {{ file_path }} 的索引 (md5: {{ md5 }}), 耗时 {{ duration }} 秒",
|
|
97
|
+
"index_build_error": "❌ {{ model_name }} 构建 {{ file_path }} 索引时出错: {{ error }}",
|
|
88
98
|
"index_build_summary": "📊 总文件数: {{ total_files }}, 需要构建索引: {{ num_files }}",
|
|
89
99
|
"building_index_progress": "⏳ 正在构建索引: {{ counter }}/{{ num_files }}...",
|
|
90
100
|
"index_source_dir_mismatch": "⚠️ 源目录不匹配 (文件路径: {{ file_path }}, 源目录: {{ source_dir }})",
|
|
@@ -123,7 +133,7 @@ MESSAGES = {
|
|
|
123
133
|
"code_merge_start": "正在自动合并代码...",
|
|
124
134
|
"code_execution_warning": "发送给模型的内容长度为 {{ content_length }} tokens(您可能收集了太多文件),超过了最大输入长度 {{ max_length }}",
|
|
125
135
|
"quick_filter_start": "开始查找上下文(quick_filter)...",
|
|
126
|
-
"normal_filter_start": "开始查找上下文(normal_filter)...",
|
|
136
|
+
"normal_filter_start": "{{ model_name }} 开始查找上下文(normal_filter)...",
|
|
127
137
|
"pylint_check_failed": "⚠️ Pylint 检查失败: {{ error_message }}",
|
|
128
138
|
"pylint_error": "❌ 运行 Pylint 时出错: {{ error_message }}",
|
|
129
139
|
"begin_index_source_code": "🚀 开始为 {{ source_dir }} 中的源代码建立索引",
|
|
@@ -132,7 +142,7 @@ MESSAGES = {
|
|
|
132
142
|
"merge_success": "✅ 成功合并了 {{ num_files }} 个文件中的更改 {{ num_changes }}/{{ total_blocks }} 个代码块。",
|
|
133
143
|
"no_changes_made": "⚠️ 未对任何文件进行更改。",
|
|
134
144
|
"unmerged_blocks_title": "未合并代码块",
|
|
135
|
-
"unmerged_file_path": "文件: {file_path}",
|
|
145
|
+
"unmerged_file_path": "文件: {{file_path}}",
|
|
136
146
|
"unmerged_search_block": "Search Block({{similarity}}):",
|
|
137
147
|
"unmerged_replace_block": "Replace Block:",
|
|
138
148
|
"unmerged_blocks_total": "未合并代码块数量: {{num_blocks}}",
|
autocoder/index/entry.py
CHANGED
|
@@ -100,14 +100,20 @@ def build_index_and_filter_files(
|
|
|
100
100
|
})
|
|
101
101
|
)
|
|
102
102
|
)
|
|
103
|
+
|
|
104
|
+
if not args.skip_filter_index and args.index_filter_model:
|
|
105
|
+
model_name = getattr(index_manager.index_filter_llm, 'default_model_name', None)
|
|
106
|
+
if not model_name:
|
|
107
|
+
model_name = "unknown(without default model name)"
|
|
108
|
+
printer.print_in_terminal("quick_filter_start", style="blue", model_name=model_name)
|
|
109
|
+
quick_filter = QuickFilter(index_manager,stats,sources)
|
|
110
|
+
final_files = quick_filter.filter(index_manager.read_index(),args.query)
|
|
103
111
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if not final_files:
|
|
110
|
-
printer.print_in_terminal("normal_filter_start", style="blue")
|
|
112
|
+
if not args.skip_filter_index and not args.index_filter_model:
|
|
113
|
+
model_name = getattr(index_manager.llm, 'default_model_name', None)
|
|
114
|
+
if not model_name:
|
|
115
|
+
model_name = "unknown(without default model name)"
|
|
116
|
+
printer.print_in_terminal("normal_filter_start", style="blue",model_name=model_name)
|
|
111
117
|
normal_filter = NormalFilter(index_manager,stats,sources)
|
|
112
118
|
final_files = normal_filter.filter(index_manager.read_index(),args.query)
|
|
113
119
|
|
|
@@ -34,6 +34,7 @@ class NormalFilter():
|
|
|
34
34
|
self.sources = sources
|
|
35
35
|
|
|
36
36
|
def filter(self, index_items: List[IndexItem], query: str) -> Dict[str, TargetFile]:
|
|
37
|
+
|
|
37
38
|
final_files: Dict[str, TargetFile] = {}
|
|
38
39
|
if not self.args.skip_filter_index:
|
|
39
40
|
if self.args.request_id and not self.args.skip_events:
|
|
@@ -59,7 +60,7 @@ class NormalFilter():
|
|
|
59
60
|
phase_end = time.monotonic()
|
|
60
61
|
self.stats["timings"]["normal_filter"]["level1_filter"] = phase_end - phase_start
|
|
61
62
|
|
|
62
|
-
# Phase 4: Level 2 filtering - Related files
|
|
63
|
+
# Phase 4: Level 2 filtering - Related files
|
|
63
64
|
if target_files is not None and self.args.index_filter_level >= 2:
|
|
64
65
|
logger.info(
|
|
65
66
|
"Phase 4: Performing Level 2 filtering (related files)...")
|
|
@@ -83,13 +84,14 @@ class NormalFilter():
|
|
|
83
84
|
phase_end = time.monotonic()
|
|
84
85
|
self.stats["timings"]["normal_filter"]["level2_filter"] = phase_end - phase_start
|
|
85
86
|
|
|
86
|
-
if not final_files:
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
87
|
+
# if not final_files:
|
|
88
|
+
# logger.warning("No related files found, using all files")
|
|
89
|
+
# for source in self.sources:
|
|
90
|
+
# final_files[get_file_path(source.module_name)] = TargetFile(
|
|
91
|
+
# file_path=source.module_name,
|
|
92
|
+
# reason="No related files found, use all files",
|
|
93
|
+
# )
|
|
94
|
+
|
|
93
95
|
|
|
94
96
|
# Phase 5: Relevance verification
|
|
95
97
|
logger.info("Phase 5: Performing relevance verification...")
|
|
@@ -125,7 +127,7 @@ class NormalFilter():
|
|
|
125
127
|
if source.module_name == file.file_path:
|
|
126
128
|
file_content = source.source_code
|
|
127
129
|
try:
|
|
128
|
-
result = self.index_manager.verify_file_relevance.with_llm(llm).with_return_type(VerifyFileRelevance).run(
|
|
130
|
+
result = self.index_manager.verify_file_relevance.with_llm(self.index_manager.llm).with_return_type(VerifyFileRelevance).run(
|
|
129
131
|
file_content=file_content,
|
|
130
132
|
query=self.args.query
|
|
131
133
|
)
|
|
@@ -69,7 +69,7 @@ class QuickFilter():
|
|
|
69
69
|
|
|
70
70
|
def filter(self, index_items: List[IndexItem], query: str) -> Dict[str, TargetFile]:
|
|
71
71
|
final_files: Dict[str, TargetFile] = {}
|
|
72
|
-
if not self.args.skip_filter_index and self.
|
|
72
|
+
if not self.args.skip_filter_index and self.args.index_filter_model:
|
|
73
73
|
start_time = time.monotonic()
|
|
74
74
|
index_items = self.index_manager.read_index()
|
|
75
75
|
|
autocoder/index/index.py
CHANGED
|
@@ -195,7 +195,7 @@ class IndexManager:
|
|
|
195
195
|
return True
|
|
196
196
|
return False
|
|
197
197
|
|
|
198
|
-
def build_index_for_single_source(self, source: SourceCode):
|
|
198
|
+
def build_index_for_single_source(self, source: SourceCode):
|
|
199
199
|
file_path = source.module_name
|
|
200
200
|
if not os.path.exists(file_path):
|
|
201
201
|
return None
|
|
@@ -205,6 +205,10 @@ class IndexManager:
|
|
|
205
205
|
|
|
206
206
|
md5 = hashlib.md5(source.source_code.encode("utf-8")).hexdigest()
|
|
207
207
|
|
|
208
|
+
model_name = getattr(self.index_llm, 'default_model_name', None)
|
|
209
|
+
if not model_name:
|
|
210
|
+
model_name = "unknown(without default model name)"
|
|
211
|
+
|
|
208
212
|
try:
|
|
209
213
|
start_time = time.monotonic()
|
|
210
214
|
source_code = source.source_code
|
|
@@ -230,13 +234,14 @@ class IndexManager:
|
|
|
230
234
|
symbols = self.get_all_file_symbols.with_llm(
|
|
231
235
|
self.index_llm).run(source.module_name, source_code)
|
|
232
236
|
time.sleep(self.anti_quota_limit)
|
|
233
|
-
|
|
237
|
+
|
|
234
238
|
self.printer.print_in_terminal(
|
|
235
239
|
"index_update_success",
|
|
236
240
|
style="green",
|
|
237
241
|
file_path=file_path,
|
|
238
242
|
md5=md5,
|
|
239
|
-
duration=time.monotonic() - start_time
|
|
243
|
+
duration=time.monotonic() - start_time,
|
|
244
|
+
model_name=model_name
|
|
240
245
|
)
|
|
241
246
|
|
|
242
247
|
except Exception as e:
|
|
@@ -246,7 +251,8 @@ class IndexManager:
|
|
|
246
251
|
"index_build_error",
|
|
247
252
|
style="red",
|
|
248
253
|
file_path=file_path,
|
|
249
|
-
error=str(e)
|
|
254
|
+
error=str(e),
|
|
255
|
+
model_name=model_name
|
|
250
256
|
)
|
|
251
257
|
return None
|
|
252
258
|
|
|
@@ -464,7 +470,7 @@ class IndexManager:
|
|
|
464
470
|
{file.file_path: file for file in all_results}.values())
|
|
465
471
|
return FileList(file_list=all_results)
|
|
466
472
|
|
|
467
|
-
def _query_index_with_thread(self, query, func):
|
|
473
|
+
def _query_index_with_thread(self, query, func):
|
|
468
474
|
all_results = []
|
|
469
475
|
lock = threading.Lock()
|
|
470
476
|
completed_threads = 0
|
autocoder/models.py
CHANGED
|
@@ -2,6 +2,7 @@ import os
|
|
|
2
2
|
import json
|
|
3
3
|
from typing import List, Dict
|
|
4
4
|
from urllib.parse import urlparse
|
|
5
|
+
from autocoder.common.auto_coder_lang import get_message_with_format
|
|
5
6
|
|
|
6
7
|
MODELS_JSON = os.path.expanduser("~/.auto-coder/keys/models.json")
|
|
7
8
|
|
|
@@ -108,11 +109,18 @@ def get_model_by_name(name: str) -> Dict:
|
|
|
108
109
|
models = load_models()
|
|
109
110
|
v = [m for m in models if m["name"] == name.strip()]
|
|
110
111
|
|
|
111
|
-
if len(v) == 0:
|
|
112
|
-
from autocoder.common.auto_coder_lang import get_message_with_format
|
|
112
|
+
if len(v) == 0:
|
|
113
113
|
raise Exception(get_message_with_format("model_not_found", model_name=name))
|
|
114
114
|
return v[0]
|
|
115
115
|
|
|
116
|
+
|
|
117
|
+
def check_model_exists(name: str) -> bool:
|
|
118
|
+
"""
|
|
119
|
+
检查模型是否存在
|
|
120
|
+
"""
|
|
121
|
+
models = load_models()
|
|
122
|
+
return any(m["name"] == name.strip() for m in models)
|
|
123
|
+
|
|
116
124
|
def update_model_with_api_key(name: str, api_key: str) -> Dict:
|
|
117
125
|
"""
|
|
118
126
|
根据模型名称查找并更新模型的 api_key_path。
|
autocoder/tsproject/__init__.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from autocoder.common import SourceCode, AutoCoderArgs
|
|
2
|
-
from autocoder import common as
|
|
2
|
+
from autocoder import common as CommonUtils
|
|
3
3
|
from autocoder.utils.rest import HttpDoc
|
|
4
4
|
import os
|
|
5
5
|
from typing import Optional, Generator, List, Dict, Any
|
|
@@ -164,7 +164,7 @@ class TSProject:
|
|
|
164
164
|
logger.warning(f"Failed to read file: {file_path}. Error: {str(e)}")
|
|
165
165
|
return None
|
|
166
166
|
|
|
167
|
-
if not
|
|
167
|
+
if not CommonUtils.has_sufficient_content(source_code, min_line_count=1):
|
|
168
168
|
return None
|
|
169
169
|
|
|
170
170
|
return SourceCode(module_name=module_name, source_code=source_code)
|
|
@@ -141,7 +141,8 @@ def multi_stream_out(
|
|
|
141
141
|
def stream_out(
|
|
142
142
|
stream_generator: Generator[Tuple[str, Dict[str, Any]], None, None],
|
|
143
143
|
request_id: Optional[str] = None,
|
|
144
|
-
console: Optional[Console] = None
|
|
144
|
+
console: Optional[Console] = None,
|
|
145
|
+
model_name: Optional[str] = None
|
|
145
146
|
) -> Tuple[str, Optional[Dict[str, Any]]]:
|
|
146
147
|
"""
|
|
147
148
|
处理流式输出事件并在终端中展示
|
|
@@ -164,7 +165,7 @@ def stream_out(
|
|
|
164
165
|
|
|
165
166
|
try:
|
|
166
167
|
with Live(
|
|
167
|
-
Panel("", title="Response", border_style="green"),
|
|
168
|
+
Panel("", title=f"Response[ {model_name} ]", border_style="green"),
|
|
168
169
|
refresh_per_second=4,
|
|
169
170
|
console=console
|
|
170
171
|
) as live:
|
|
@@ -209,7 +210,7 @@ def stream_out(
|
|
|
209
210
|
live.update(
|
|
210
211
|
Panel(
|
|
211
212
|
Markdown(display_content),
|
|
212
|
-
title="Response",
|
|
213
|
+
title=f"Response[ {model_name} ]",
|
|
213
214
|
border_style="green",
|
|
214
215
|
height=min(50, live.console.height - 4)
|
|
215
216
|
)
|
|
@@ -223,7 +224,7 @@ def stream_out(
|
|
|
223
224
|
live.update(
|
|
224
225
|
Panel(
|
|
225
226
|
Markdown(assistant_response),
|
|
226
|
-
title="Final Response",
|
|
227
|
+
title=f"Final Response[ {model_name} ]",
|
|
227
228
|
border_style="blue"
|
|
228
229
|
)
|
|
229
230
|
)
|
|
@@ -231,9 +232,11 @@ def stream_out(
|
|
|
231
232
|
except Exception as e:
|
|
232
233
|
console.print(Panel(
|
|
233
234
|
f"Error: {str(e)}",
|
|
234
|
-
title="Error",
|
|
235
|
+
title=f"Error[ {model_name} ]",
|
|
235
236
|
border_style="red"
|
|
236
237
|
))
|
|
238
|
+
# import traceback
|
|
239
|
+
# traceback.print_exc()
|
|
237
240
|
|
|
238
241
|
if request_id and request_queue:
|
|
239
242
|
request_queue.add_request(
|
autocoder/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.246"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|