auto-coder 0.1.299__py3-none-any.whl → 0.1.301__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.299.dist-info → auto_coder-0.1.301.dist-info}/METADATA +1 -1
- {auto_coder-0.1.299.dist-info → auto_coder-0.1.301.dist-info}/RECORD +26 -24
- autocoder/agent/auto_learn_from_commit.py +125 -59
- autocoder/agent/auto_review_commit.py +106 -16
- autocoder/auto_coder.py +65 -66
- autocoder/auto_coder_runner.py +23 -40
- autocoder/command_parser.py +280 -0
- autocoder/commands/auto_command.py +130 -40
- autocoder/commands/tools.py +170 -10
- autocoder/common/__init__.py +9 -1
- autocoder/common/action_yml_file_manager.py +432 -0
- autocoder/common/auto_coder_lang.py +8 -2
- autocoder/common/auto_configure.py +6 -0
- autocoder/common/code_auto_merge.py +14 -0
- autocoder/common/code_auto_merge_diff.py +14 -0
- autocoder/common/code_auto_merge_editblock.py +14 -0
- autocoder/common/code_auto_merge_strict_diff.py +13 -0
- autocoder/common/command_completer.py +8 -1
- autocoder/common/memory_manager.py +5 -1
- autocoder/index/entry.py +17 -0
- autocoder/utils/__init__.py +13 -9
- autocoder/version.py +1 -1
- {auto_coder-0.1.299.dist-info → auto_coder-0.1.301.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.299.dist-info → auto_coder-0.1.301.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.299.dist-info → auto_coder-0.1.301.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.299.dist-info → auto_coder-0.1.301.dist-info}/top_level.txt +0 -0
|
@@ -25,7 +25,7 @@ from autocoder.common.auto_configure import config_readme
|
|
|
25
25
|
from autocoder.utils.auto_project_type import ProjectTypeAnalyzer
|
|
26
26
|
from rich.text import Text
|
|
27
27
|
from autocoder.common.mcp_server import get_mcp_server,McpServerInfoRequest
|
|
28
|
-
|
|
28
|
+
from autocoder.common.action_yml_file_manager import ActionYmlFileManager
|
|
29
29
|
class CommandMessage(BaseModel):
|
|
30
30
|
role: str
|
|
31
31
|
content: str
|
|
@@ -41,14 +41,17 @@ class CommandConversation(BaseModel):
|
|
|
41
41
|
current_conversation: List[CommandMessage]
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
def load_memory_file() -> CommandConversation:
|
|
45
|
-
"""Load command conversations from memory file"""
|
|
44
|
+
def load_memory_file(args: AutoCoderArgs) -> CommandConversation:
|
|
45
|
+
"""Load command conversations from memory file"""
|
|
46
|
+
|
|
46
47
|
memory_dir = os.path.join(".auto-coder", "memory")
|
|
47
48
|
file_path = os.path.join(memory_dir, "command_chat_history.json")
|
|
48
49
|
if os.path.exists(file_path):
|
|
49
50
|
with open(file_path, "r", encoding="utf-8") as f:
|
|
50
51
|
try:
|
|
51
|
-
|
|
52
|
+
conversation = CommandConversation.model_validate_json(f.read())
|
|
53
|
+
conversation.current_conversation = conversation.current_conversation
|
|
54
|
+
return conversation
|
|
52
55
|
except Exception:
|
|
53
56
|
return CommandConversation(history={}, current_conversation=[])
|
|
54
57
|
return CommandConversation(history={}, current_conversation=[])
|
|
@@ -174,13 +177,13 @@ class CommandAutoTuner:
|
|
|
174
177
|
|
|
175
178
|
def get_conversations(self) -> List[CommandMessage]:
|
|
176
179
|
"""Get conversation history from memory file"""
|
|
177
|
-
conversation = load_memory_file()
|
|
178
|
-
return [
|
|
180
|
+
conversation = load_memory_file(args=self.args)
|
|
181
|
+
return [command_message.message for command_message in conversation.current_conversation]
|
|
179
182
|
|
|
180
183
|
@byzerllm.prompt()
|
|
181
184
|
def _analyze(self, request: AutoCommandRequest) -> str:
|
|
182
185
|
"""
|
|
183
|
-
当前用户环境信息如下:
|
|
186
|
+
## 当前用户环境信息如下:
|
|
184
187
|
<os_info>
|
|
185
188
|
操作系统: {{ env_info.os_name }} {{ env_info.os_version }}
|
|
186
189
|
操作系统发行版: {{ os_distribution }}
|
|
@@ -204,7 +207,7 @@ class CommandAutoTuner:
|
|
|
204
207
|
我们的目标是根据用户输入和当前上下文,组合多个函数来完成用户的需求。
|
|
205
208
|
|
|
206
209
|
{% if current_files %}
|
|
207
|
-
当前活跃区文件列表:
|
|
210
|
+
## 当前活跃区文件列表:
|
|
208
211
|
<current_files>
|
|
209
212
|
{% for file in current_files %}
|
|
210
213
|
- {{ file }}
|
|
@@ -213,41 +216,22 @@ class CommandAutoTuner:
|
|
|
213
216
|
{% endif %}
|
|
214
217
|
|
|
215
218
|
|
|
216
|
-
当前用户的配置选项如下:
|
|
219
|
+
## 当前用户的配置选项如下:
|
|
217
220
|
<current_conf>
|
|
218
221
|
{{ current_conf }}
|
|
219
222
|
</current_conf>
|
|
220
223
|
|
|
221
|
-
可用函数列表:
|
|
224
|
+
## 可用函数列表:
|
|
222
225
|
{{ available_commands }}
|
|
223
226
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
如果用户是一个编码需求,你可以先简单观察当前活跃区文件列表:
|
|
227
|
-
0. 关注下当前软件的配置,诸如索引开启关闭。如果有觉得不合理的可以通过 help 函数来修改。
|
|
228
|
-
1. 如果你觉得这些文件不够满足用户的需求,而当前的索引配置关闭的,那么你可以通过help("将skip_filter_index 和 skip_build_index 设置为 false") 让
|
|
229
|
-
chat,coding 函数来获取更多文件,或者你也可以自己通过调用 get_project_structure 函数来获取项目结构,然后通过 get_project_map 函数来获取某个文件的用途,符号列表,以及
|
|
230
|
-
文件大小(tokens数),最后再通过 read_files/read_file_with_keyword_ranges 函数来读取文件内容, 最后通过 add_files 函数来添加文件到活跃区。
|
|
231
|
-
确保 chat,coding 函数能够正常使用。
|
|
232
|
-
2. 对于一个比较复杂的代码需求,你可以先通过 chat 函数来获得一些设计,根据chat返回的结果,你可以选择多次调用chat调整最后的设计。最后,当你满意后,可以通过 coding("/apply 根据历史对话实现代码,请不要有遗漏") 来完成最后的编码。
|
|
233
|
-
3. 注意,为了防止对话过长,你可以使用 chat("/new") 来创新新的会话。然后接着正常再次调用 chat 函数。 即可
|
|
234
|
-
4. 当用户询问项目,比如询问什么什么功能在哪里的时候,或者哪个文件实现了什么功能,推荐的工具组合是 get_project_map 和 get_project_structure。可以直通过 get_project_map 查看整个项目文件的索引(该索引包含了文件列表,每个文件的用途和符号列表),也可以
|
|
235
|
-
通过 get_project_structure 来获取项目结构,然后通过 get_project_map 来获取你想看的某个文件的用途,符号列表,最后再通过 read_files/read_file_with_keyword_ranges 函数来读取文件内容,确认对应的功能是否在相关的文件里。
|
|
236
|
-
5. 调用 coding 函数的时候,尽可能多的 @文件和@@符号,让需求更加清晰明了,建议多描述具体怎么完成对应的需求。
|
|
237
|
-
6. 对于代码需求设计,尽可能使用 chat 函数。
|
|
238
|
-
7. 如果成功执行了 coding 函数,最好再调用一次 chat("/review /commit")
|
|
239
|
-
8. 我们所有的对话不能超过 {{ conversation_safe_zone_tokens }} 个tokens,当你读取索引文件 (get_project_map) 的时候,你可以看到
|
|
240
|
-
每个文件的tokens数,你可以根据这个信息来决定如何读取这个文件。比如对于很小的文件,那么可以直接全部读取,
|
|
241
|
-
而对于分析一个超大文件推荐组合 read_files 带上 line_ranges 参数来读取,或者组合 read_file_withread_file_with_keyword_ranges 等来读取,
|
|
242
|
-
每个函数你还可以使用多次来获取更多信息。
|
|
243
|
-
9. 根据操作系统,终端类型,脚本类型等各种信息,在涉及到路径或者脚本的时候,需要考虑平台差异性。
|
|
244
|
-
10. 使用 read_files 时,一次性读取文件数量不要超过1个,每次只读取200行。如果发现读取的内容不够,则继续读取下面200行。
|
|
245
|
-
</function_combination_readme>
|
|
246
|
-
|
|
227
|
+
## 当前大模型窗口安全值
|
|
228
|
+
{{ conversation_safe_zone_tokens }}
|
|
247
229
|
|
|
230
|
+
## 函数组合说明:
|
|
231
|
+
{{ command_combination_readme }}
|
|
248
232
|
|
|
249
233
|
{% if conversation_history %}
|
|
250
|
-
历史对话:
|
|
234
|
+
## 历史对话:
|
|
251
235
|
<conversation_history>
|
|
252
236
|
{% for conv in conversation_history %}
|
|
253
237
|
({{ conv.role }}): {{ conv.content }}
|
|
@@ -255,7 +239,7 @@ class CommandAutoTuner:
|
|
|
255
239
|
</conversation_history>
|
|
256
240
|
{% endif %}
|
|
257
241
|
|
|
258
|
-
用户需求:
|
|
242
|
+
## 用户需求:
|
|
259
243
|
<user_input>
|
|
260
244
|
{{ user_input }}
|
|
261
245
|
</user_input>
|
|
@@ -299,9 +283,50 @@ class CommandAutoTuner:
|
|
|
299
283
|
"shell_encoding": shells.get_terminal_encoding(),
|
|
300
284
|
"conversation_safe_zone_tokens": self.args.conversation_prune_safe_zone_tokens,
|
|
301
285
|
"os_distribution": shells.get_os_distribution(),
|
|
302
|
-
"current_user": shells.get_current_username()
|
|
286
|
+
"current_user": shells.get_current_username(),
|
|
287
|
+
"command_combination_readme": self._command_combination_readme.prompt()
|
|
303
288
|
}
|
|
304
289
|
|
|
290
|
+
@byzerllm.prompt()
|
|
291
|
+
def _command_combination_readme(self) -> str:
|
|
292
|
+
"""
|
|
293
|
+
<function_combination_readme>
|
|
294
|
+
如果用户是一个编码需求,你可以先简单观察当前活跃区文件列表:
|
|
295
|
+
|
|
296
|
+
### 是否根据需求动态修改auto-coder软件配置
|
|
297
|
+
关注下当前软件的配置,结合当前用户的需求,如果觉得不合理的地方,可以通过 ask_user 函数来询问用户,是否要通过 help 函数修改一些配置。
|
|
298
|
+
|
|
299
|
+
### 如何了解当前项目
|
|
300
|
+
|
|
301
|
+
通常可以自己通过调用 get_project_structure 函数来获取项目结构(如果项目结构太大,该函数会拒绝返回,你可以选择 list_files 函数来查看目录),然后通过 get_project_map 函数来获取某几个文件的用途,符号列表,以及
|
|
302
|
+
文件大小(tokens数),最后再通过 read_files/read_file_with_keyword_ranges 函数来读取文件内容,从而更好的结合当前项目理解用户的需求。
|
|
303
|
+
|
|
304
|
+
### 复杂需求,先做讨论设计
|
|
305
|
+
对于一个比较复杂的代码需求,你可以先通过 chat 函数来获得一些设计,根据chat返回的结果,你可以选择多次调用chat调整最后的设计。最后,当你满意后,可以通过 coding("/apply") 来完成最后的编码。
|
|
306
|
+
注意,为了防止对话过长,你可以使用 chat("/new") 来创新新的会话。然后接着正常再次调用 chat 函数。 即可。
|
|
307
|
+
尽可通过了解项目后,多用 @文件和@@符号,这样 chat 函数可以更清晰的理解你关注的代码,文档和意图。
|
|
308
|
+
|
|
309
|
+
### 调用 coding 函数应该注意的事项
|
|
310
|
+
调用 coding 函数的时候,尽可能多的 @文件和@@符号,让需求更加清晰明了,建议多描述具体怎么完成对应的需求。
|
|
311
|
+
对于代码需求设计,尽可能使用 chat 函数。如果成功执行了 coding 函数, 最好再调用一次 chat("/review /commit"),方便总结这次代码变更。
|
|
312
|
+
注意,review 完后,需要询问用户是否要做啥调整不,如果用户说不用,那么就停止。否则根据意图进行后续操作。
|
|
313
|
+
|
|
314
|
+
### 关于对话大小的问题
|
|
315
|
+
我们对话历史以及查看的内容累计不能超过 {{ conversation_safe_zone_tokens }} 个tokens,当你读取索引文件 (get_project_map) 的时候,你可以看到
|
|
316
|
+
每个文件的tokens数,你可以根据这个信息来决定如何读取这个文件。如果不确定,使用 count_file_tokens 函数来获取文件的tokens数,再决定如何读取。
|
|
317
|
+
而对于分析一个超大文件推荐组合 read_files 带上 line_ranges 参数来读取,或者组合 read_file_withread_file_with_keyword_ranges 等来读取,
|
|
318
|
+
每个函数你还可以使用多次来获取更多信息。
|
|
319
|
+
|
|
320
|
+
### 善用脚本完成一些基本的操作
|
|
321
|
+
根据操作系统,终端类型,脚本类型等各种信息,在涉及到路径或者脚本的时候,需要考虑平台差异性。
|
|
322
|
+
|
|
323
|
+
## 其他一些注意事项
|
|
324
|
+
1. 使用 read_files 时,一次性读取文件数量不要超过1个,每次只读取200行。如果发现读取的内容不够,则继续读取下面200行。
|
|
325
|
+
2. 确实有必要才使用 get_project_structure 函数,否则可以多使用 list_files 函数来查看目录。
|
|
326
|
+
3. 最后,不要局限在我们前面描述的使用说明中,根据各个函数的说明,灵活组合和使用各个函数,发挥自己的想象力,尽可能的完成用户的需求。
|
|
327
|
+
</function_combination_readme>
|
|
328
|
+
"""
|
|
329
|
+
|
|
305
330
|
@byzerllm.prompt()
|
|
306
331
|
def _execute_command_result(self, result:str) -> str:
|
|
307
332
|
'''
|
|
@@ -328,8 +353,16 @@ class CommandAutoTuner:
|
|
|
328
353
|
# 获取 prompt 内容
|
|
329
354
|
prompt = self._analyze.prompt(request)
|
|
330
355
|
|
|
356
|
+
# 获取对当前项目变更的最近8条历史人物
|
|
357
|
+
action_yml_file_manager = ActionYmlFileManager(self.args.source_dir)
|
|
358
|
+
history_tasks = action_yml_file_manager.to_tasks_prompt(limit=8)
|
|
359
|
+
new_messages = []
|
|
360
|
+
if self.args.enable_task_history:
|
|
361
|
+
new_messages.append({"role": "user", "content": history_tasks})
|
|
362
|
+
new_messages.append({"role": "assistant", "content": "好的,我知道最近的任务对项目的变更了,我会参考这些来更好的理解你的需求。"})
|
|
363
|
+
|
|
331
364
|
# 构造对话上下文
|
|
332
|
-
conversations = [{"role": "user", "content": prompt}]
|
|
365
|
+
conversations = new_messages + [{"role": "user", "content": prompt}]
|
|
333
366
|
|
|
334
367
|
# 使用 stream_out 进行输出
|
|
335
368
|
printer = Printer()
|
|
@@ -1004,11 +1037,16 @@ class CommandAutoTuner:
|
|
|
1004
1037
|
<name>get_project_map</name>
|
|
1005
1038
|
<description>返回项目中指定文件包括文件用途、导入的包、定义的类、函数、变量等。</description>
|
|
1006
1039
|
<usage>
|
|
1007
|
-
该命令接受一个参数
|
|
1040
|
+
该命令接受一个参数 file_paths,路径list,或者是以逗号分割的多个文件路径。
|
|
1041
|
+
路径支持相对路径和绝对路径。
|
|
1008
1042
|
|
|
1009
1043
|
使用例子:
|
|
1010
1044
|
|
|
1011
|
-
get_project_map(
|
|
1045
|
+
get_project_map(file_paths=["full/path/to/main.py","partial/path/to/utils.py"]),
|
|
1046
|
+
|
|
1047
|
+
或者:
|
|
1048
|
+
|
|
1049
|
+
get_project_map(file_paths="full/path/to/main.py,partial/path/to/utils.py")
|
|
1012
1050
|
|
|
1013
1051
|
该函数特别适合你想要了解某个文件的用途,以及该文件的导入的包,定义的类,函数,变量等信息。
|
|
1014
1052
|
同时,你还能看到文件的大小(tokens数),以及索引的大小(tokens数),以及构建索引花费费用等信息。
|
|
@@ -1223,9 +1261,57 @@ class CommandAutoTuner:
|
|
|
1223
1261
|
response_user(response="你好,我是 auto-coder")
|
|
1224
1262
|
</usage>
|
|
1225
1263
|
</command>
|
|
1264
|
+
|
|
1265
|
+
<command>
|
|
1266
|
+
<name>count_file_tokens</name>
|
|
1267
|
+
<description>计算指定文件的token数量。</description>
|
|
1268
|
+
<usage>
|
|
1269
|
+
该函数接受一个参数 file_path, 为要计算的文件路径。
|
|
1270
|
+
|
|
1271
|
+
使用例子:
|
|
1272
|
+
count_file_tokens(file_path="full")
|
|
1273
|
+
|
|
1274
|
+
注意:
|
|
1275
|
+
- 返回值为int类型,表示文件的token数量。
|
|
1276
|
+
|
|
1277
|
+
</usage>
|
|
1278
|
+
</command>
|
|
1279
|
+
|
|
1280
|
+
<command>
|
|
1281
|
+
<name>count_string_tokens</name>
|
|
1282
|
+
<description>计算指定字符串的token数量。</description>
|
|
1283
|
+
<usage>
|
|
1284
|
+
该函数接受一个参数 text, 为要计算的文本。
|
|
1285
|
+
|
|
1286
|
+
使用例子:
|
|
1287
|
+
count_string_tokens(text="你好,世界")
|
|
1288
|
+
|
|
1289
|
+
注意:
|
|
1290
|
+
- 返回值为int类型,表示文本的token数量。
|
|
1291
|
+
|
|
1292
|
+
</usage>
|
|
1293
|
+
</command>
|
|
1294
|
+
|
|
1295
|
+
<command>
|
|
1296
|
+
<n>find_symbol_definition</n>
|
|
1297
|
+
<description>查找指定符号的定义所在的文件路径。</description>
|
|
1298
|
+
<usage>
|
|
1299
|
+
该函数接受一个参数 symbol, 为要查找的符号名称。
|
|
1300
|
+
|
|
1301
|
+
使用例子:
|
|
1302
|
+
find_symbol_definition(symbol="MyClass")
|
|
1303
|
+
find_symbol_definition(symbol="process_data")
|
|
1304
|
+
|
|
1305
|
+
注意:
|
|
1306
|
+
- 返回值为字符串,包含符号定义所在的文件路径列表,以逗号分隔
|
|
1307
|
+
- 支持精确匹配和模糊匹配(不区分大小写)
|
|
1308
|
+
- 如果未找到匹配项,会返回提示信息
|
|
1309
|
+
|
|
1310
|
+
</usage>
|
|
1311
|
+
</command>
|
|
1226
1312
|
|
|
1227
1313
|
<command>
|
|
1228
|
-
<
|
|
1314
|
+
<n>execute_mcp_server</n>
|
|
1229
1315
|
<description>执行MCP服务器</description>
|
|
1230
1316
|
<usage>
|
|
1231
1317
|
该函数接受一个参数 query, 为要执行的MCP服务器查询字符串。
|
|
@@ -1276,6 +1362,7 @@ class CommandAutoTuner:
|
|
|
1276
1362
|
"get_related_files_by_symbols": self.tools.get_related_files_by_symbols,
|
|
1277
1363
|
"get_project_map": self.tools.get_project_map,
|
|
1278
1364
|
"get_project_structure": self.tools.get_project_structure,
|
|
1365
|
+
"list_files": self.tools.list_files,
|
|
1279
1366
|
"read_files": self.tools.read_files,
|
|
1280
1367
|
"find_files_by_name": self.tools.find_files_by_name,
|
|
1281
1368
|
"find_files_by_content": self.tools.find_files_by_content,
|
|
@@ -1285,6 +1372,9 @@ class CommandAutoTuner:
|
|
|
1285
1372
|
"get_project_type": self.project_type_analyzer.analyze,
|
|
1286
1373
|
"response_user": self.tools.response_user,
|
|
1287
1374
|
"execute_mcp_server": self.tools.execute_mcp_server,
|
|
1375
|
+
"count_file_tokens": self.tools.count_file_tokens,
|
|
1376
|
+
"count_string_tokens": self.tools.count_string_tokens,
|
|
1377
|
+
"find_symbol_definition": self.tools.find_symbol_definition,
|
|
1288
1378
|
|
|
1289
1379
|
}
|
|
1290
1380
|
|
autocoder/commands/tools.py
CHANGED
|
@@ -31,6 +31,12 @@ from autocoder.common import files as files_utils
|
|
|
31
31
|
from autocoder.common.printer import Printer
|
|
32
32
|
from prompt_toolkit import PromptSession
|
|
33
33
|
from prompt_toolkit.styles import Style
|
|
34
|
+
from autocoder.rag.token_counter import count_tokens
|
|
35
|
+
from autocoder.index.symbols_utils import (
|
|
36
|
+
extract_symbols,
|
|
37
|
+
SymbolType,
|
|
38
|
+
symbols_info_to_str,
|
|
39
|
+
)
|
|
34
40
|
|
|
35
41
|
|
|
36
42
|
@byzerllm.prompt()
|
|
@@ -251,14 +257,8 @@ class AutoCommandTools:
|
|
|
251
257
|
})
|
|
252
258
|
return v
|
|
253
259
|
|
|
254
|
-
def get_project_map(self, file_path: Optional[str] = None) -> str:
|
|
255
|
-
"""
|
|
256
|
-
该工具会返回项目中所有已经被构建索引的文件以及该文件的信息,诸如该文件的用途,导入的包,定义的类,函数,变量等信息。
|
|
257
|
-
返回的是json格式文本。
|
|
258
260
|
|
|
259
|
-
|
|
260
|
-
尽量避免使用该工具。
|
|
261
|
-
"""
|
|
261
|
+
def _get_sources(self):
|
|
262
262
|
if self.args.project_type == "ts":
|
|
263
263
|
pp = TSProject(args=self.args, llm=self.llm)
|
|
264
264
|
elif self.args.project_type == "py":
|
|
@@ -266,13 +266,36 @@ class AutoCommandTools:
|
|
|
266
266
|
else:
|
|
267
267
|
pp = SuffixProject(args=self.args, llm=self.llm, file_filter=None)
|
|
268
268
|
pp.run()
|
|
269
|
-
|
|
269
|
+
return pp.sources
|
|
270
270
|
|
|
271
|
+
def _get_index(self):
|
|
272
|
+
sources = self._get_sources()
|
|
271
273
|
index_manager = IndexManager(llm=self.llm, sources=sources, args=self.args)
|
|
274
|
+
return index_manager
|
|
275
|
+
|
|
276
|
+
def get_project_map(self, file_paths: Optional[str] = None) -> str:
|
|
277
|
+
"""
|
|
278
|
+
该工具会返回项目中所有已经被构建索引的文件以及该文件的信息,诸如该文件的用途,导入的包,定义的类,函数,变量等信息。
|
|
279
|
+
返回的是json格式文本。
|
|
280
|
+
|
|
281
|
+
参数说明:
|
|
282
|
+
file_paths (Optional[str]): 可选参数,以逗号分隔的文件路径列表,用于筛选特定文件。
|
|
283
|
+
例如:"main.py,utils.py"或"/path/to/main.py,/path/to/utils.py"
|
|
284
|
+
|
|
285
|
+
注意,这个工具无法返回所有文件的信息,因为有些文件可能没有被索引。
|
|
286
|
+
尽量避免使用该工具。
|
|
287
|
+
"""
|
|
288
|
+
index_manager = self._get_index()
|
|
272
289
|
s = index_manager.read_index_as_str()
|
|
273
290
|
index_data = json.loads(s)
|
|
274
291
|
|
|
275
292
|
final_result = []
|
|
293
|
+
|
|
294
|
+
# 解析文件路径列表(如果提供了)
|
|
295
|
+
file_path_list = []
|
|
296
|
+
if file_paths:
|
|
297
|
+
file_path_list = [path.strip() for path in file_paths.split(",")]
|
|
298
|
+
|
|
276
299
|
for k in index_data.values():
|
|
277
300
|
value = {}
|
|
278
301
|
value["file_name"] = k["module_name"]
|
|
@@ -281,12 +304,30 @@ class AutoCommandTools:
|
|
|
281
304
|
value["index_tokens"] = k.get("generated_tokens_count", -1)
|
|
282
305
|
value["file_tokens_cost"] = k.get("input_tokens_cost", -1)
|
|
283
306
|
value["index_tokens_cost"] = k.get("generated_tokens_cost", -1)
|
|
284
|
-
|
|
307
|
+
|
|
308
|
+
# 如果提供了文件路径列表,检查当前文件是否匹配任何一个路径
|
|
309
|
+
if file_path_list:
|
|
310
|
+
if any(path in k["module_name"] for path in file_path_list):
|
|
311
|
+
final_result.append(value)
|
|
312
|
+
else:
|
|
285
313
|
final_result.append(value)
|
|
314
|
+
|
|
286
315
|
v = json.dumps(final_result, ensure_ascii=False)
|
|
316
|
+
tokens = count_tokens(v)
|
|
317
|
+
if tokens > self.args.conversation_prune_safe_zone_tokens/2.0:
|
|
318
|
+
result = f"The project map is too large to return. (tokens: {tokens}). Try to use another function."
|
|
319
|
+
self.result_manager.add_result(content=result, meta = {
|
|
320
|
+
"action": "get_project_map",
|
|
321
|
+
"input": {
|
|
322
|
+
"file_paths": file_paths
|
|
323
|
+
}
|
|
324
|
+
})
|
|
325
|
+
return result
|
|
326
|
+
|
|
287
327
|
self.result_manager.add_result(content=v, meta = {
|
|
288
328
|
"action": "get_project_map",
|
|
289
|
-
"input": {
|
|
329
|
+
"input": {
|
|
330
|
+
"file_paths": file_paths
|
|
290
331
|
}
|
|
291
332
|
})
|
|
292
333
|
return v
|
|
@@ -469,6 +510,97 @@ class AutoCommandTools:
|
|
|
469
510
|
})
|
|
470
511
|
return source_code_str
|
|
471
512
|
|
|
513
|
+
def find_symbol_definition(self, symbol: str) -> str:
|
|
514
|
+
"""
|
|
515
|
+
该工具用于查找指定符号的定义。
|
|
516
|
+
输入参数 symbol: 要查找的符号
|
|
517
|
+
返回值是符号的定义所在的文件路径列表,以逗号分隔。
|
|
518
|
+
"""
|
|
519
|
+
index_manager = self._get_index()
|
|
520
|
+
result = []
|
|
521
|
+
index_items = index_manager.read_index()
|
|
522
|
+
|
|
523
|
+
for item in index_items:
|
|
524
|
+
symbols = extract_symbols(item.symbols)
|
|
525
|
+
for symbol_info in symbols:
|
|
526
|
+
# 进行精确匹配和模糊匹配
|
|
527
|
+
if (symbol_info.name == symbol or
|
|
528
|
+
symbol.lower() in symbol_info.name.lower()):
|
|
529
|
+
# 检查是否已经添加过该文件路径
|
|
530
|
+
if symbol_info.module_name not in result:
|
|
531
|
+
result.append(symbol_info.module_name)
|
|
532
|
+
|
|
533
|
+
# 生成以逗号分隔的文件路径列表
|
|
534
|
+
file_paths = ",".join(result)
|
|
535
|
+
|
|
536
|
+
# 如果没有找到任何匹配项,返回提示信息
|
|
537
|
+
if not file_paths:
|
|
538
|
+
file_paths = f"未找到符号 '{symbol}' 的定义"
|
|
539
|
+
|
|
540
|
+
# 记录操作结果
|
|
541
|
+
self.result_manager.add_result(content=file_paths, meta={
|
|
542
|
+
"action": "find_symbols_definition",
|
|
543
|
+
"input": {
|
|
544
|
+
"symbol": symbol
|
|
545
|
+
}
|
|
546
|
+
})
|
|
547
|
+
|
|
548
|
+
return file_paths
|
|
549
|
+
|
|
550
|
+
def list_files(self, path: str) -> str:
|
|
551
|
+
"""
|
|
552
|
+
该工具用于列出指定目录下的所有文件(不包括子目录中的文件)。
|
|
553
|
+
输入参数 path: 要列出文件的目录路径
|
|
554
|
+
返回值是目录下所有文件的列表,以逗号分隔。
|
|
555
|
+
"""
|
|
556
|
+
# 处理绝对路径和相对路径
|
|
557
|
+
target_path = path
|
|
558
|
+
if not os.path.isabs(path):
|
|
559
|
+
# 如果是相对路径,将其转换为绝对路径
|
|
560
|
+
target_path = os.path.join(self.args.source_dir, path)
|
|
561
|
+
|
|
562
|
+
# 确保路径存在且是目录
|
|
563
|
+
if not os.path.exists(target_path):
|
|
564
|
+
result = f"目录不存在: {target_path}"
|
|
565
|
+
self.result_manager.add_result(content=result, meta={
|
|
566
|
+
"action": "list_files",
|
|
567
|
+
"input": {
|
|
568
|
+
"path": path
|
|
569
|
+
}
|
|
570
|
+
})
|
|
571
|
+
return result
|
|
572
|
+
|
|
573
|
+
if not os.path.isdir(target_path):
|
|
574
|
+
result = f"指定路径不是目录: {target_path}"
|
|
575
|
+
self.result_manager.add_result(content=result, meta={
|
|
576
|
+
"action": "list_files",
|
|
577
|
+
"input": {
|
|
578
|
+
"path": path
|
|
579
|
+
}
|
|
580
|
+
})
|
|
581
|
+
return result
|
|
582
|
+
|
|
583
|
+
# 只收集当前目录下的文件,不递归子目录
|
|
584
|
+
file_list = []
|
|
585
|
+
for item in os.listdir(target_path):
|
|
586
|
+
item_path = os.path.join(target_path, item)
|
|
587
|
+
# 只添加文件,不添加目录
|
|
588
|
+
if os.path.isfile(item_path):
|
|
589
|
+
file_list.append(item_path)
|
|
590
|
+
|
|
591
|
+
# 生成以逗号分隔的文件列表
|
|
592
|
+
result = ",".join(file_list)
|
|
593
|
+
|
|
594
|
+
# 记录结果
|
|
595
|
+
self.result_manager.add_result(content=result, meta={
|
|
596
|
+
"action": "list_files",
|
|
597
|
+
"input": {
|
|
598
|
+
"path": path
|
|
599
|
+
}
|
|
600
|
+
})
|
|
601
|
+
|
|
602
|
+
return result
|
|
603
|
+
|
|
472
604
|
def get_project_structure(self) -> str:
|
|
473
605
|
if self.args.project_type == "ts":
|
|
474
606
|
pp = TSProject(args=self.args, llm=self.llm)
|
|
@@ -478,6 +610,17 @@ class AutoCommandTools:
|
|
|
478
610
|
pp = SuffixProject(args=self.args, llm=self.llm, file_filter=None)
|
|
479
611
|
pp.run()
|
|
480
612
|
s = pp.get_tree_like_directory_structure()
|
|
613
|
+
|
|
614
|
+
tokens = count_tokens(s)
|
|
615
|
+
if tokens > self.args.conversation_prune_safe_zone_tokens / 2.0:
|
|
616
|
+
result = f"The project structure is too large to return. (tokens: {tokens}). Try to use another function."
|
|
617
|
+
self.result_manager.add_result(content=result, meta = {
|
|
618
|
+
"action": "get_project_structure",
|
|
619
|
+
"input": {
|
|
620
|
+
}
|
|
621
|
+
})
|
|
622
|
+
return result
|
|
623
|
+
|
|
481
624
|
self.result_manager.add_result(content=s, meta = {
|
|
482
625
|
"action": "get_project_structure",
|
|
483
626
|
"input": {
|
|
@@ -509,6 +652,23 @@ class AutoCommandTools:
|
|
|
509
652
|
}
|
|
510
653
|
})
|
|
511
654
|
return v
|
|
655
|
+
|
|
656
|
+
def count_file_tokens(self, file_path: str) -> int:
|
|
657
|
+
"""
|
|
658
|
+
该工具用于计算指定文件的token数量。
|
|
659
|
+
输入参数 file_path: 文件路径
|
|
660
|
+
返回值是文件的token数量。
|
|
661
|
+
"""
|
|
662
|
+
content = files_utils.read_file(file_path)
|
|
663
|
+
return count_tokens(content)
|
|
664
|
+
|
|
665
|
+
def count_string_tokens(self, text: str) -> int:
|
|
666
|
+
"""
|
|
667
|
+
该工具用于计算指定字符串的token数量。
|
|
668
|
+
输入参数 text: 要计算的文本
|
|
669
|
+
返回值是字符串的token数量。
|
|
670
|
+
"""
|
|
671
|
+
return count_tokens(text)
|
|
512
672
|
|
|
513
673
|
def find_files_by_content(self, keyword: str) -> str:
|
|
514
674
|
"""
|
autocoder/common/__init__.py
CHANGED
|
@@ -377,7 +377,7 @@ class AutoCoderArgs(pydantic.BaseModel):
|
|
|
377
377
|
# block:给定每个文件修改的代码块 file: 给定每个文件修改前后内容
|
|
378
378
|
rank_strategy: Optional[str] = "file"
|
|
379
379
|
|
|
380
|
-
action: List[str] = []
|
|
380
|
+
action: Union[List[str], Dict[str, Any]] = []
|
|
381
381
|
enable_global_memory: Optional[bool] = False
|
|
382
382
|
product_mode: Optional[str] = "lite"
|
|
383
383
|
|
|
@@ -402,6 +402,14 @@ class AutoCoderArgs(pydantic.BaseModel):
|
|
|
402
402
|
|
|
403
403
|
enable_beta: Optional[bool] = False
|
|
404
404
|
|
|
405
|
+
how_to_reproduce: Optional[str] = None
|
|
406
|
+
|
|
407
|
+
dynamic_urls: List[str] = []
|
|
408
|
+
|
|
409
|
+
add_updated_urls: List[str] = []
|
|
410
|
+
|
|
411
|
+
enable_task_history: Optional[bool] = False
|
|
412
|
+
|
|
405
413
|
class Config:
|
|
406
414
|
protected_namespaces = ()
|
|
407
415
|
|