auto-coder 0.1.301__py3-none-any.whl → 0.1.303__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.301.dist-info → auto_coder-0.1.303.dist-info}/METADATA +2 -1
- {auto_coder-0.1.301.dist-info → auto_coder-0.1.303.dist-info}/RECORD +33 -25
- autocoder/auto_coder.py +6 -7
- autocoder/auto_coder_runner.py +9 -9
- autocoder/chat_auto_coder.py +6 -1
- autocoder/commands/auto_command.py +313 -205
- autocoder/commands/tools.py +123 -85
- autocoder/common/__init__.py +2 -0
- autocoder/common/action_yml_file_manager.py +28 -6
- autocoder/common/auto_coder_lang.py +2 -2
- autocoder/common/auto_configure.py +9 -4
- autocoder/common/code_auto_merge.py +1 -1
- autocoder/common/code_auto_merge_diff.py +1 -1
- autocoder/common/code_auto_merge_editblock.py +1 -1
- autocoder/common/code_auto_merge_strict_diff.py +1 -1
- autocoder/common/stream_out_type.py +7 -0
- autocoder/dispacher/actions/action.py +221 -101
- autocoder/dispacher/actions/plugins/action_regex_project.py +18 -0
- autocoder/events/__init__.py +57 -0
- autocoder/events/event_content.py +423 -0
- autocoder/events/event_manager.py +327 -0
- autocoder/events/event_manager_singleton.py +245 -0
- autocoder/events/event_store.py +376 -0
- autocoder/events/event_types.py +103 -0
- autocoder/index/entry.py +88 -60
- autocoder/index/filter/quick_filter.py +71 -3
- autocoder/run_context.py +62 -0
- autocoder/utils/auto_coder_utils/chat_stream_out.py +32 -1
- autocoder/version.py +1 -1
- {auto_coder-0.1.301.dist-info → auto_coder-0.1.303.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.301.dist-info → auto_coder-0.1.303.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.301.dist-info → auto_coder-0.1.303.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.301.dist-info → auto_coder-0.1.303.dist-info}/top_level.txt +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from enum import Enum
|
|
1
2
|
import json
|
|
2
3
|
import os
|
|
3
4
|
import time
|
|
@@ -24,8 +25,12 @@ from autocoder.common.global_cancel import global_cancel
|
|
|
24
25
|
from autocoder.common.auto_configure import config_readme
|
|
25
26
|
from autocoder.utils.auto_project_type import ProjectTypeAnalyzer
|
|
26
27
|
from rich.text import Text
|
|
27
|
-
from autocoder.common.mcp_server import get_mcp_server,McpServerInfoRequest
|
|
28
|
+
from autocoder.common.mcp_server import get_mcp_server, McpServerInfoRequest
|
|
28
29
|
from autocoder.common.action_yml_file_manager import ActionYmlFileManager
|
|
30
|
+
from autocoder.events.event_manager_singleton import get_event_manager
|
|
31
|
+
from autocoder.events import event_content as EventContentCreator
|
|
32
|
+
from autocoder.run_context import get_run_context
|
|
33
|
+
from autocoder.common.stream_out_type import AutoCommandStreamOutType
|
|
29
34
|
class CommandMessage(BaseModel):
|
|
30
35
|
role: str
|
|
31
36
|
content: str
|
|
@@ -38,41 +43,56 @@ class ExtendedCommandMessage(BaseModel):
|
|
|
38
43
|
|
|
39
44
|
class CommandConversation(BaseModel):
|
|
40
45
|
history: Dict[str, ExtendedCommandMessage]
|
|
41
|
-
current_conversation: List[
|
|
46
|
+
current_conversation: List[ExtendedCommandMessage]
|
|
42
47
|
|
|
43
48
|
|
|
44
49
|
def load_memory_file(args: AutoCoderArgs) -> CommandConversation:
|
|
45
|
-
"""Load command conversations from memory file"""
|
|
46
|
-
|
|
50
|
+
"""Load command conversations from memory file"""
|
|
51
|
+
|
|
47
52
|
memory_dir = os.path.join(".auto-coder", "memory")
|
|
48
53
|
file_path = os.path.join(memory_dir, "command_chat_history.json")
|
|
49
54
|
if os.path.exists(file_path):
|
|
50
55
|
with open(file_path, "r", encoding="utf-8") as f:
|
|
51
56
|
try:
|
|
52
|
-
conversation = CommandConversation.model_validate_json(
|
|
53
|
-
|
|
57
|
+
conversation = CommandConversation.model_validate_json(
|
|
58
|
+
f.read())
|
|
54
59
|
return conversation
|
|
55
60
|
except Exception:
|
|
56
61
|
return CommandConversation(history={}, current_conversation=[])
|
|
57
62
|
return CommandConversation(history={}, current_conversation=[])
|
|
58
63
|
|
|
59
64
|
|
|
65
|
+
class TimeBasedStrategy:
|
|
66
|
+
def __init__(self, max_idle_time=3600*24): # 24 hour in seconds
|
|
67
|
+
self.max_idle_time = max_idle_time
|
|
68
|
+
|
|
69
|
+
def should_archive(self, last_message_time):
|
|
70
|
+
"""Check if the conversation should be archived based on last message time"""
|
|
71
|
+
current_time = time.time()
|
|
72
|
+
return current_time - last_message_time > self.max_idle_time
|
|
73
|
+
|
|
74
|
+
|
|
60
75
|
def save_to_memory_file(query: str, response: str):
|
|
61
76
|
"""Save command conversation to memory file using CommandConversation structure"""
|
|
62
77
|
memory_dir = os.path.join(".auto-coder", "memory")
|
|
63
78
|
os.makedirs(memory_dir, exist_ok=True)
|
|
64
79
|
file_path = os.path.join(memory_dir, "command_chat_history.json")
|
|
80
|
+
|
|
81
|
+
# Initialize time-based strategy
|
|
82
|
+
time_strategy = TimeBasedStrategy()
|
|
83
|
+
|
|
65
84
|
# Create new message objects
|
|
85
|
+
current_time = time.time()
|
|
66
86
|
user_msg = CommandMessage(role="user", content=query)
|
|
67
87
|
assistant_msg = CommandMessage(role="assistant", content=response)
|
|
68
88
|
|
|
69
89
|
extended_user_msg = ExtendedCommandMessage(
|
|
70
90
|
message=user_msg,
|
|
71
|
-
timestamp=str(int(
|
|
91
|
+
timestamp=str(int(current_time))
|
|
72
92
|
)
|
|
73
93
|
extended_assistant_msg = ExtendedCommandMessage(
|
|
74
94
|
message=assistant_msg,
|
|
75
|
-
timestamp=str(int(
|
|
95
|
+
timestamp=str(int(current_time))
|
|
76
96
|
)
|
|
77
97
|
|
|
78
98
|
# Load existing conversation or create new
|
|
@@ -81,6 +101,15 @@ def save_to_memory_file(query: str, response: str):
|
|
|
81
101
|
try:
|
|
82
102
|
existing_conv = CommandConversation.model_validate_json(
|
|
83
103
|
f.read())
|
|
104
|
+
# Check if we should archive current conversation
|
|
105
|
+
if existing_conv.current_conversation:
|
|
106
|
+
last_message_time = float(
|
|
107
|
+
existing_conv.current_conversation[-1].timestamp)
|
|
108
|
+
if time_strategy.should_archive(last_message_time):
|
|
109
|
+
# Move current conversation to history
|
|
110
|
+
timestamp = str(int(last_message_time))
|
|
111
|
+
existing_conv.history[timestamp] = existing_conv.current_conversation
|
|
112
|
+
existing_conv.current_conversation = []
|
|
84
113
|
except Exception:
|
|
85
114
|
existing_conv = CommandConversation(
|
|
86
115
|
history={},
|
|
@@ -105,13 +134,14 @@ class CommandSuggestion(BaseModel):
|
|
|
105
134
|
confidence: float
|
|
106
135
|
reasoning: str
|
|
107
136
|
|
|
137
|
+
|
|
108
138
|
class AutoCommandResponse(BaseModel):
|
|
109
139
|
suggestions: List[CommandSuggestion]
|
|
110
140
|
reasoning: Optional[str] = None
|
|
111
141
|
|
|
112
142
|
|
|
113
143
|
class AutoCommandRequest(BaseModel):
|
|
114
|
-
user_input: str
|
|
144
|
+
user_input: str
|
|
115
145
|
|
|
116
146
|
|
|
117
147
|
class MemoryConfig(BaseModel):
|
|
@@ -151,7 +181,6 @@ class CommandConfig(BaseModel):
|
|
|
151
181
|
index_import: SkipValidation[Callable]
|
|
152
182
|
exclude_files: SkipValidation[Callable]
|
|
153
183
|
|
|
154
|
-
|
|
155
184
|
|
|
156
185
|
class CommandAutoTuner:
|
|
157
186
|
def __init__(self, llm: Union[byzerllm.ByzerLLM, byzerllm.SimpleByzerLLM],
|
|
@@ -163,7 +192,8 @@ class CommandAutoTuner:
|
|
|
163
192
|
self.memory_config = memory_config
|
|
164
193
|
self.command_config = command_config
|
|
165
194
|
self.tools = AutoCommandTools(args=args, llm=self.llm)
|
|
166
|
-
self.project_type_analyzer = ProjectTypeAnalyzer(
|
|
195
|
+
self.project_type_analyzer = ProjectTypeAnalyzer(
|
|
196
|
+
args=args, llm=self.llm)
|
|
167
197
|
try:
|
|
168
198
|
self.mcp_server = get_mcp_server()
|
|
169
199
|
mcp_server_info_response = self.mcp_server.send_request(McpServerInfoRequest(
|
|
@@ -174,7 +204,7 @@ class CommandAutoTuner:
|
|
|
174
204
|
except Exception as e:
|
|
175
205
|
logger.error(f"Error getting MCP server info: {str(e)}")
|
|
176
206
|
self.mcp_server_info = ""
|
|
177
|
-
|
|
207
|
+
|
|
178
208
|
def get_conversations(self) -> List[CommandMessage]:
|
|
179
209
|
"""Get conversation history from memory file"""
|
|
180
210
|
conversation = load_memory_file(args=self.args)
|
|
@@ -191,7 +221,7 @@ class CommandAutoTuner:
|
|
|
191
221
|
终端类型: {{ env_info.shell_type }}
|
|
192
222
|
终端编码: {{ env_info.shell_encoding }}
|
|
193
223
|
当前用户: {{ current_user }}
|
|
194
|
-
|
|
224
|
+
|
|
195
225
|
{%- if shell_type %}
|
|
196
226
|
脚本类型:{{ shell_type }}
|
|
197
227
|
{%- endif %}
|
|
@@ -203,9 +233,9 @@ class CommandAutoTuner:
|
|
|
203
233
|
虚拟环境: {{ env_info.virtualenv }}
|
|
204
234
|
{%- endif %}
|
|
205
235
|
</os_info>
|
|
206
|
-
|
|
236
|
+
|
|
207
237
|
我们的目标是根据用户输入和当前上下文,组合多个函数来完成用户的需求。
|
|
208
|
-
|
|
238
|
+
|
|
209
239
|
{% if current_files %}
|
|
210
240
|
## 当前活跃区文件列表:
|
|
211
241
|
<current_files>
|
|
@@ -220,7 +250,7 @@ class CommandAutoTuner:
|
|
|
220
250
|
<current_conf>
|
|
221
251
|
{{ current_conf }}
|
|
222
252
|
</current_conf>
|
|
223
|
-
|
|
253
|
+
|
|
224
254
|
## 可用函数列表:
|
|
225
255
|
{{ available_commands }}
|
|
226
256
|
|
|
@@ -246,7 +276,7 @@ class CommandAutoTuner:
|
|
|
246
276
|
|
|
247
277
|
请分析用户意图,组合一个或者多个函数,帮助用户完成需求。
|
|
248
278
|
返回格式必须是严格的JSON格式:
|
|
249
|
-
|
|
279
|
+
|
|
250
280
|
```json
|
|
251
281
|
{
|
|
252
282
|
"suggestions": [
|
|
@@ -265,7 +295,7 @@ class CommandAutoTuner:
|
|
|
265
295
|
满足需求。
|
|
266
296
|
"""
|
|
267
297
|
|
|
268
|
-
env_info = detect_env()
|
|
298
|
+
env_info = detect_env()
|
|
269
299
|
shell_type = "bash"
|
|
270
300
|
if shells.is_running_in_cmd():
|
|
271
301
|
shell_type = "cmd"
|
|
@@ -274,10 +304,10 @@ class CommandAutoTuner:
|
|
|
274
304
|
|
|
275
305
|
return {
|
|
276
306
|
"user_input": request.user_input,
|
|
277
|
-
"current_files": self.memory_config.memory["current_files"]["files"],
|
|
307
|
+
"current_files": self.memory_config.memory["current_files"]["files"],
|
|
278
308
|
"conversation_history": self.get_conversations(),
|
|
279
309
|
"available_commands": self._command_readme.prompt(),
|
|
280
|
-
"current_conf": json.dumps(self.memory_config.memory["conf"], indent=2),
|
|
310
|
+
"current_conf": json.dumps(self.memory_config.memory["conf"], indent=2),
|
|
281
311
|
"env_info": env_info,
|
|
282
312
|
"shell_type": shell_type,
|
|
283
313
|
"shell_encoding": shells.get_terminal_encoding(),
|
|
@@ -286,7 +316,7 @@ class CommandAutoTuner:
|
|
|
286
316
|
"current_user": shells.get_current_username(),
|
|
287
317
|
"command_combination_readme": self._command_combination_readme.prompt()
|
|
288
318
|
}
|
|
289
|
-
|
|
319
|
+
|
|
290
320
|
@byzerllm.prompt()
|
|
291
321
|
def _command_combination_readme(self) -> str:
|
|
292
322
|
"""
|
|
@@ -295,75 +325,83 @@ class CommandAutoTuner:
|
|
|
295
325
|
|
|
296
326
|
### 是否根据需求动态修改auto-coder软件配置
|
|
297
327
|
关注下当前软件的配置,结合当前用户的需求,如果觉得不合理的地方,可以通过 ask_user 函数来询问用户,是否要通过 help 函数修改一些配置。
|
|
298
|
-
|
|
328
|
+
|
|
299
329
|
### 如何了解当前项目
|
|
300
330
|
|
|
301
331
|
通常可以自己通过调用 get_project_structure 函数来获取项目结构(如果项目结构太大,该函数会拒绝返回,你可以选择 list_files 函数来查看目录),然后通过 get_project_map 函数来获取某几个文件的用途,符号列表,以及
|
|
302
332
|
文件大小(tokens数),最后再通过 read_files/read_file_with_keyword_ranges 函数来读取文件内容,从而更好的结合当前项目理解用户的需求。
|
|
303
|
-
|
|
333
|
+
|
|
304
334
|
### 复杂需求,先做讨论设计
|
|
305
335
|
对于一个比较复杂的代码需求,你可以先通过 chat 函数来获得一些设计,根据chat返回的结果,你可以选择多次调用chat调整最后的设计。最后,当你满意后,可以通过 coding("/apply") 来完成最后的编码。
|
|
306
336
|
注意,为了防止对话过长,你可以使用 chat("/new") 来创新新的会话。然后接着正常再次调用 chat 函数。 即可。
|
|
307
337
|
尽可通过了解项目后,多用 @文件和@@符号,这样 chat 函数可以更清晰的理解你关注的代码,文档和意图。
|
|
308
|
-
|
|
338
|
+
|
|
309
339
|
### 调用 coding 函数应该注意的事项
|
|
310
340
|
调用 coding 函数的时候,尽可能多的 @文件和@@符号,让需求更加清晰明了,建议多描述具体怎么完成对应的需求。
|
|
311
341
|
对于代码需求设计,尽可能使用 chat 函数。如果成功执行了 coding 函数, 最好再调用一次 chat("/review /commit"),方便总结这次代码变更。
|
|
312
342
|
注意,review 完后,需要询问用户是否要做啥调整不,如果用户说不用,那么就停止。否则根据意图进行后续操作。
|
|
313
|
-
|
|
343
|
+
|
|
314
344
|
### 关于对话大小的问题
|
|
315
345
|
我们对话历史以及查看的内容累计不能超过 {{ conversation_safe_zone_tokens }} 个tokens,当你读取索引文件 (get_project_map) 的时候,你可以看到
|
|
316
346
|
每个文件的tokens数,你可以根据这个信息来决定如何读取这个文件。如果不确定,使用 count_file_tokens 函数来获取文件的tokens数,再决定如何读取。
|
|
317
|
-
而对于分析一个超大文件推荐组合 read_files 带上 line_ranges 参数来读取,或者组合
|
|
347
|
+
而对于分析一个超大文件推荐组合 read_files 带上 line_ranges 参数来读取,或者组合 read_file_with_keyword_ranges 等来读取,
|
|
318
348
|
每个函数你还可以使用多次来获取更多信息。
|
|
319
|
-
|
|
349
|
+
|
|
320
350
|
### 善用脚本完成一些基本的操作
|
|
321
351
|
根据操作系统,终端类型,脚本类型等各种信息,在涉及到路径或者脚本的时候,需要考虑平台差异性。
|
|
322
352
|
|
|
353
|
+
### 关于查看文件的技巧
|
|
354
|
+
在使用 read_files 之前,如果你有明确的目标,比如查看这个文件某个函数在这个文件的实现,你可以先用 read_file_with_keyword_ranges 函数来大致定位,该函数会返回你看到的
|
|
355
|
+
内容的行号范围,你可以通过拓展这个行号范围继续使用 read_file_with_line_ranges 来查看完整函数信息,或者使用 read_files 函数带上 line_ranges 参数来精确读取。
|
|
356
|
+
|
|
357
|
+
如果你没有明确目标,需要单纯查看这个文件获取必要的信息,可以先通过 count_file_tokens 函数来获取文件的tokens数,如果数目小于安全对话窗口的tokens数的1/2, 那么可以直接用
|
|
358
|
+
read_files 函数来读取,否则建议一次读取200-600行,多次读取直到找到合适的信息。
|
|
359
|
+
|
|
323
360
|
## 其他一些注意事项
|
|
324
361
|
1. 使用 read_files 时,一次性读取文件数量不要超过1个,每次只读取200行。如果发现读取的内容不够,则继续读取下面200行。
|
|
325
362
|
2. 确实有必要才使用 get_project_structure 函数,否则可以多使用 list_files 函数来查看目录。
|
|
326
363
|
3. 最后,不要局限在我们前面描述的使用说明中,根据各个函数的说明,灵活组合和使用各个函数,发挥自己的想象力,尽可能的完成用户的需求。
|
|
327
364
|
</function_combination_readme>
|
|
328
|
-
"""
|
|
329
|
-
|
|
365
|
+
"""
|
|
366
|
+
|
|
330
367
|
@byzerllm.prompt()
|
|
331
|
-
def _execute_command_result(self, result:str) -> str:
|
|
368
|
+
def _execute_command_result(self, result: str) -> str:
|
|
332
369
|
'''
|
|
333
370
|
根据函数执行结果,返回下一个函数。
|
|
334
371
|
|
|
335
372
|
下面是我们上一个函数执行结果:
|
|
336
|
-
|
|
373
|
+
|
|
337
374
|
<function_result>
|
|
338
375
|
{{ result }}
|
|
339
376
|
</function_result>
|
|
340
377
|
|
|
341
378
|
请根据命令执行结果以及前面的对话,返回下一个函数。
|
|
342
|
-
|
|
379
|
+
|
|
343
380
|
*** 非常非常重要的提示 ***
|
|
344
|
-
1.
|
|
381
|
+
1. 如果已经满足要求,则总是调用 response_user函数,对用户的初始问题根据前面所有信息做一次详细的回复。
|
|
345
382
|
2. 你最多尝试 {{ auto_command_max_iterations }} 次,如果 {{ auto_command_max_iterations }} 次都没有满足要求,则不要返回任何函数,确保 suggestions 为空。
|
|
346
|
-
'''
|
|
383
|
+
'''
|
|
347
384
|
return {
|
|
348
385
|
"auto_command_max_iterations": self.args.auto_command_max_iterations,
|
|
349
386
|
"conversation_safe_zone_tokens": self.args.conversation_prune_safe_zone_tokens
|
|
350
|
-
}
|
|
351
|
-
|
|
387
|
+
}
|
|
388
|
+
|
|
352
389
|
def analyze(self, request: AutoCommandRequest) -> AutoCommandResponse:
|
|
353
390
|
# 获取 prompt 内容
|
|
354
391
|
prompt = self._analyze.prompt(request)
|
|
355
|
-
|
|
392
|
+
|
|
356
393
|
# 获取对当前项目变更的最近8条历史人物
|
|
357
394
|
action_yml_file_manager = ActionYmlFileManager(self.args.source_dir)
|
|
358
395
|
history_tasks = action_yml_file_manager.to_tasks_prompt(limit=8)
|
|
359
396
|
new_messages = []
|
|
360
397
|
if self.args.enable_task_history:
|
|
361
398
|
new_messages.append({"role": "user", "content": history_tasks})
|
|
362
|
-
new_messages.append(
|
|
363
|
-
|
|
399
|
+
new_messages.append(
|
|
400
|
+
{"role": "assistant", "content": "好的,我知道最近的任务对项目的变更了,我会参考这些来更好的理解你的需求。"})
|
|
401
|
+
|
|
364
402
|
# 构造对话上下文
|
|
365
403
|
conversations = new_messages + [{"role": "user", "content": prompt}]
|
|
366
|
-
|
|
404
|
+
|
|
367
405
|
# 使用 stream_out 进行输出
|
|
368
406
|
printer = Printer()
|
|
369
407
|
title = printer.get_message_from_key("auto_command_analyzing")
|
|
@@ -372,116 +410,163 @@ class CommandAutoTuner:
|
|
|
372
410
|
def extract_command_response(content: str) -> str:
|
|
373
411
|
# 提取 JSON 并转换为 AutoCommandResponse
|
|
374
412
|
try:
|
|
375
|
-
response = to_model(content, AutoCommandResponse)
|
|
376
|
-
if response.suggestions:
|
|
413
|
+
response = to_model(content, AutoCommandResponse)
|
|
414
|
+
if response.suggestions:
|
|
377
415
|
command = response.suggestions[0].command
|
|
378
|
-
parameters = response.suggestions[0].parameters
|
|
416
|
+
parameters = response.suggestions[0].parameters
|
|
379
417
|
if parameters:
|
|
380
|
-
params_str = ", ".join(
|
|
418
|
+
params_str = ", ".join(
|
|
419
|
+
[f"{k}={v}" for k, v in parameters.items()])
|
|
381
420
|
else:
|
|
382
|
-
params_str = ""
|
|
421
|
+
params_str = ""
|
|
383
422
|
return f"{command}({params_str})"
|
|
384
423
|
else:
|
|
385
|
-
return printer.get_message_from_key("satisfied_prompt")
|
|
386
|
-
except Exception as e:
|
|
424
|
+
return printer.get_message_from_key("satisfied_prompt")
|
|
425
|
+
except Exception as e:
|
|
387
426
|
logger.error(f"Error extracting command response: {str(e)}")
|
|
388
427
|
return content
|
|
389
|
-
|
|
428
|
+
|
|
390
429
|
model_name = ",".join(llms_utils.get_llm_names(self.llm))
|
|
391
430
|
start_time = time.monotonic()
|
|
392
431
|
result, last_meta = stream_out(
|
|
393
|
-
self.llm.stream_chat_oai(
|
|
432
|
+
self.llm.stream_chat_oai(
|
|
433
|
+
conversations=conversations, delta_mode=True),
|
|
394
434
|
model_name=model_name,
|
|
395
435
|
title=title,
|
|
396
436
|
final_title=final_title,
|
|
397
|
-
display_func=
|
|
437
|
+
display_func=extract_command_response,
|
|
438
|
+
args=self.args,
|
|
439
|
+
extra_meta={
|
|
440
|
+
"stream_out_type": AutoCommandStreamOutType.COMMAND_SUGGESTION.value
|
|
441
|
+
}
|
|
398
442
|
)
|
|
399
|
-
|
|
443
|
+
|
|
400
444
|
if last_meta:
|
|
401
|
-
elapsed_time = time.monotonic() - start_time
|
|
445
|
+
elapsed_time = time.monotonic() - start_time
|
|
402
446
|
speed = last_meta.generated_tokens_count / elapsed_time
|
|
403
|
-
|
|
447
|
+
|
|
404
448
|
# Get model info for pricing
|
|
405
449
|
from autocoder.utils import llms as llm_utils
|
|
406
|
-
model_info = llm_utils.get_model_info(
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
450
|
+
model_info = llm_utils.get_model_info(
|
|
451
|
+
model_name, self.args.product_mode) or {}
|
|
452
|
+
input_price = model_info.get(
|
|
453
|
+
"input_price", 0.0) if model_info else 0.0
|
|
454
|
+
output_price = model_info.get(
|
|
455
|
+
"output_price", 0.0) if model_info else 0.0
|
|
456
|
+
|
|
410
457
|
# Calculate costs
|
|
411
|
-
input_cost = (last_meta.input_tokens_count *
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
458
|
+
input_cost = (last_meta.input_tokens_count *
|
|
459
|
+
input_price) / 1000000 # Convert to millions
|
|
460
|
+
output_cost = (last_meta.generated_tokens_count *
|
|
461
|
+
output_price) / 1000000 # Convert to millions
|
|
462
|
+
|
|
463
|
+
temp_content = printer.get_message_from_key_with_format("stream_out_stats",
|
|
464
|
+
model_name=",".join(
|
|
465
|
+
llms_utils.get_llm_names(self.llm)),
|
|
466
|
+
elapsed_time=elapsed_time,
|
|
467
|
+
first_token_time=last_meta.first_token_time,
|
|
468
|
+
input_tokens=last_meta.input_tokens_count,
|
|
469
|
+
output_tokens=last_meta.generated_tokens_count,
|
|
470
|
+
input_cost=round(
|
|
471
|
+
input_cost, 4),
|
|
472
|
+
output_cost=round(
|
|
473
|
+
output_cost, 4),
|
|
474
|
+
speed=round(speed, 2))
|
|
475
|
+
printer.print_str_in_terminal(temp_content)
|
|
476
|
+
get_event_manager(self.args.event_file).write_result(
|
|
477
|
+
EventContentCreator.create_result(content=EventContentCreator.ResultTokenStatContent(
|
|
478
|
+
model_name=model_name,
|
|
479
|
+
elapsed_time=elapsed_time,
|
|
480
|
+
first_token_time=last_meta.first_token_time,
|
|
481
|
+
input_tokens=last_meta.input_tokens_count,
|
|
482
|
+
output_tokens=last_meta.generated_tokens_count,
|
|
483
|
+
input_cost=round(input_cost, 4),
|
|
484
|
+
output_cost=round(output_cost, 4),
|
|
485
|
+
speed=round(speed, 2)
|
|
486
|
+
)).to_dict()
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
# 这里打印
|
|
490
|
+
|
|
491
|
+
conversations.append({"role": "assistant", "content": result})
|
|
492
|
+
# 提取 JSON 并转换为 AutoCommandResponse
|
|
493
|
+
response = to_model(result, AutoCommandResponse)
|
|
494
|
+
|
|
430
495
|
# 保存对话记录
|
|
431
496
|
save_to_memory_file(
|
|
432
497
|
query=request.user_input,
|
|
433
498
|
response=response.model_dump_json(indent=2)
|
|
434
499
|
)
|
|
435
500
|
result_manager = ResultManager()
|
|
436
|
-
|
|
501
|
+
|
|
437
502
|
while True:
|
|
438
503
|
if global_cancel.requested:
|
|
439
504
|
printer = Printer(console)
|
|
440
|
-
printer.print_in_terminal("generation_cancelled")
|
|
505
|
+
printer.print_in_terminal("generation_cancelled")
|
|
441
506
|
break
|
|
442
507
|
# 执行命令
|
|
443
508
|
command = response.suggestions[0].command
|
|
444
509
|
parameters = response.suggestions[0].parameters
|
|
510
|
+
|
|
511
|
+
# 打印正在执行的命令
|
|
512
|
+
temp_content = printer.get_message_from_key_with_format("auto_command_executing",
|
|
513
|
+
command=command
|
|
514
|
+
)
|
|
515
|
+
printer.print_str_in_terminal(temp_content,style="blue")
|
|
516
|
+
|
|
517
|
+
get_event_manager(self.args.event_file).write_result(EventContentCreator.create_result(content=
|
|
518
|
+
EventContentCreator.ResultCommandPrepareStatContent(
|
|
519
|
+
command=command,
|
|
520
|
+
parameters=parameters
|
|
521
|
+
).to_dict()))
|
|
445
522
|
|
|
446
|
-
|
|
447
|
-
self.printer.print_in_terminal(
|
|
448
|
-
"auto_command_executing",
|
|
449
|
-
style="blue",
|
|
450
|
-
command=command
|
|
451
|
-
)
|
|
452
|
-
|
|
453
|
-
self.execute_auto_command(command, parameters)
|
|
523
|
+
self.execute_auto_command(command, parameters)
|
|
454
524
|
content = ""
|
|
455
525
|
last_result = result_manager.get_last()
|
|
456
526
|
if last_result:
|
|
457
|
-
action = last_result.meta["action"]
|
|
458
|
-
if action == "coding":
|
|
527
|
+
action = last_result.meta["action"]
|
|
528
|
+
if action == "coding":
|
|
459
529
|
# 如果上一步是 coding,则需要把上一步的更改前和更改后的内容作为上下文
|
|
460
|
-
changes = git_utils.get_changes_by_commit_message(
|
|
530
|
+
changes = git_utils.get_changes_by_commit_message(
|
|
531
|
+
"", last_result.meta["commit_message"])
|
|
461
532
|
if changes.success:
|
|
462
533
|
for file_path, change in changes.changes.items():
|
|
463
534
|
if change:
|
|
464
535
|
content += f"## File: {file_path}[更改前]\n{change.before or 'New File'}\n\nFile: {file_path}\n\n[更改后]\n{change.after or 'Deleted File'}\n\n"
|
|
465
536
|
else:
|
|
466
|
-
content = printer.
|
|
537
|
+
content = printer.get_message_from_key("no_changes_made")
|
|
467
538
|
else:
|
|
468
539
|
# 其他的直接获取执行结果
|
|
469
540
|
content = last_result.content
|
|
470
541
|
|
|
471
542
|
if action != command:
|
|
472
543
|
# command 和 action 不一致,则认为命令执行失败,退出
|
|
473
|
-
printer.
|
|
544
|
+
temp_content = printer.get_message_from_key_with_format(
|
|
545
|
+
"auto_command_action_break", command=command, action=action)
|
|
546
|
+
printer.print_str_in_terminal(temp_content,style="yellow")
|
|
547
|
+
get_event_manager(self.args.event_file).write_result(
|
|
548
|
+
EventContentCreator.create_result(content=temp_content))
|
|
474
549
|
break
|
|
475
550
|
|
|
551
|
+
if command == "response_user":
|
|
552
|
+
break
|
|
553
|
+
|
|
554
|
+
get_event_manager(self.args.event_file).write_result(
|
|
555
|
+
EventContentCreator.create_result(content=EventContentCreator.ResultCommandExecuteStatContent(
|
|
556
|
+
command=command,
|
|
557
|
+
content=content
|
|
558
|
+
).to_dict()))
|
|
559
|
+
|
|
476
560
|
# 打印执行结果
|
|
477
561
|
console = Console()
|
|
478
562
|
# 截取content前后200字符
|
|
479
|
-
truncated_content = content[:200] + "\n...\n" +
|
|
563
|
+
truncated_content = content[:200] + "\n...\n" + \
|
|
564
|
+
content[-200:] if len(content) > 400 else content
|
|
480
565
|
title = printer.get_message_from_key_with_format(
|
|
481
|
-
"command_execution_result",
|
|
566
|
+
"command_execution_result",
|
|
482
567
|
action=action
|
|
483
568
|
)
|
|
484
|
-
# 转义内容,避免Rich将内容中的[]解释为markup语法
|
|
569
|
+
# 转义内容,避免Rich将内容中的[]解释为markup语法
|
|
485
570
|
text_content = Text(truncated_content)
|
|
486
571
|
console.print(Panel(
|
|
487
572
|
text_content,
|
|
@@ -489,88 +574,111 @@ class CommandAutoTuner:
|
|
|
489
574
|
border_style="blue",
|
|
490
575
|
padding=(1, 2)
|
|
491
576
|
))
|
|
492
|
-
# 保持原content不变,继续后续处理
|
|
493
577
|
|
|
494
578
|
# 添加新的对话内容
|
|
495
579
|
new_content = self._execute_command_result.prompt(content)
|
|
496
580
|
conversations.append({"role": "user", "content": new_content})
|
|
497
|
-
|
|
498
|
-
# 统计 token 数量
|
|
499
|
-
total_tokens = count_tokens(json.dumps(
|
|
581
|
+
|
|
582
|
+
# 统计 token 数量
|
|
583
|
+
total_tokens = count_tokens(json.dumps(
|
|
584
|
+
conversations, ensure_ascii=False))
|
|
500
585
|
|
|
501
586
|
# 如果对话过长,使用默认策略进行修剪
|
|
502
587
|
if total_tokens > self.args.conversation_prune_safe_zone_tokens:
|
|
503
588
|
self.printer.print_in_terminal(
|
|
504
|
-
"conversation_pruning_start",
|
|
589
|
+
"conversation_pruning_start",
|
|
505
590
|
style="yellow",
|
|
506
591
|
total_tokens=total_tokens,
|
|
507
592
|
safe_zone=self.args.conversation_prune_safe_zone_tokens
|
|
508
593
|
)
|
|
509
594
|
from autocoder.common.conversation_pruner import ConversationPruner
|
|
510
595
|
pruner = ConversationPruner(self.args, self.llm)
|
|
511
|
-
conversations = pruner.prune_conversations(conversations)
|
|
596
|
+
conversations = pruner.prune_conversations(conversations)
|
|
512
597
|
|
|
513
598
|
title = printer.get_message_from_key("auto_command_analyzing")
|
|
514
599
|
model_name = ",".join(llms_utils.get_llm_names(self.llm))
|
|
515
|
-
|
|
600
|
+
|
|
516
601
|
start_time = time.monotonic()
|
|
517
602
|
result, last_meta = stream_out(
|
|
518
|
-
self.llm.stream_chat_oai(
|
|
603
|
+
self.llm.stream_chat_oai(
|
|
604
|
+
conversations=conversations, delta_mode=True),
|
|
519
605
|
model_name=model_name,
|
|
520
606
|
title=title,
|
|
521
607
|
final_title=final_title,
|
|
522
|
-
display_func=
|
|
523
|
-
|
|
524
|
-
|
|
608
|
+
display_func=extract_command_response,
|
|
609
|
+
args=self.args,
|
|
610
|
+
extra_meta={
|
|
611
|
+
"stream_out_type": AutoCommandStreamOutType.COMMAND_SUGGESTION.value
|
|
612
|
+
}
|
|
613
|
+
)
|
|
614
|
+
|
|
525
615
|
if last_meta:
|
|
526
616
|
elapsed_time = time.monotonic() - start_time
|
|
527
617
|
printer = Printer()
|
|
528
618
|
speed = last_meta.generated_tokens_count / elapsed_time
|
|
529
|
-
|
|
619
|
+
|
|
530
620
|
# Get model info for pricing
|
|
531
621
|
from autocoder.utils import llms as llm_utils
|
|
532
|
-
model_info = llm_utils.get_model_info(
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
622
|
+
model_info = llm_utils.get_model_info(
|
|
623
|
+
model_name, self.args.product_mode) or {}
|
|
624
|
+
input_price = model_info.get(
|
|
625
|
+
"input_price", 0.0) if model_info else 0.0
|
|
626
|
+
output_price = model_info.get(
|
|
627
|
+
"output_price", 0.0) if model_info else 0.0
|
|
628
|
+
|
|
536
629
|
# Calculate costs
|
|
537
|
-
input_cost = (last_meta.input_tokens_count *
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
630
|
+
input_cost = (last_meta.input_tokens_count *
|
|
631
|
+
input_price) / 1000000 # Convert to millions
|
|
632
|
+
# Convert to millions
|
|
633
|
+
output_cost = (
|
|
634
|
+
last_meta.generated_tokens_count * output_price) / 1000000
|
|
635
|
+
|
|
636
|
+
temp_content = printer.get_message_from_key_with_format("stream_out_stats",
|
|
637
|
+
model_name=model_name,
|
|
638
|
+
elapsed_time=elapsed_time,
|
|
639
|
+
first_token_time=last_meta.first_token_time,
|
|
640
|
+
input_tokens=last_meta.input_tokens_count,
|
|
641
|
+
output_tokens=last_meta.generated_tokens_count,
|
|
642
|
+
input_cost=round(input_cost, 4),
|
|
643
|
+
output_cost=round(
|
|
644
|
+
output_cost, 4),
|
|
645
|
+
speed=round(speed, 2))
|
|
646
|
+
printer.print_str_in_terminal(temp_content)
|
|
647
|
+
get_event_manager(self.args.event_file).write_result(
|
|
648
|
+
EventContentCreator.create_result(content=EventContentCreator.ResultTokenStatContent(
|
|
649
|
+
model_name=model_name,
|
|
650
|
+
elapsed_time=elapsed_time,
|
|
651
|
+
first_token_time=last_meta.first_token_time,
|
|
652
|
+
input_tokens=last_meta.input_tokens_count,
|
|
653
|
+
output_tokens=last_meta.generated_tokens_count,
|
|
654
|
+
).to_dict()))
|
|
655
|
+
|
|
656
|
+
conversations.append({"role": "assistant", "content": result})
|
|
657
|
+
# 提取 JSON 并转换为 AutoCommandResponse
|
|
658
|
+
response = to_model(result, AutoCommandResponse)
|
|
659
|
+
if not response or not response.suggestions:
|
|
660
|
+
break
|
|
661
|
+
|
|
556
662
|
save_to_memory_file(
|
|
557
663
|
query=request.user_input,
|
|
558
664
|
response=response.model_dump_json(indent=2)
|
|
559
|
-
)
|
|
665
|
+
)
|
|
666
|
+
else:
|
|
667
|
+
temp_content = printer.get_message_from_key_with_format("auto_command_break", command=command)
|
|
668
|
+
printer.print_str_in_terminal(temp_content,style="yellow")
|
|
669
|
+
get_event_manager(self.args.event_file).write_result(
|
|
670
|
+
EventContentCreator.create_result(content=temp_content))
|
|
671
|
+
break
|
|
672
|
+
|
|
673
|
+
return response
|
|
560
674
|
|
|
561
|
-
else:
|
|
562
|
-
self.printer.print_in_terminal("auto_command_break", style="yellow", command=command)
|
|
563
|
-
break
|
|
564
|
-
|
|
565
|
-
return response
|
|
566
|
-
|
|
567
675
|
@byzerllm.prompt()
|
|
568
676
|
def _command_readme(self) -> str:
|
|
569
677
|
'''
|
|
570
678
|
你有如下函数可供使用:
|
|
571
|
-
|
|
679
|
+
|
|
572
680
|
<commands>
|
|
573
|
-
|
|
681
|
+
|
|
574
682
|
<command>
|
|
575
683
|
<name>add_files</name>
|
|
576
684
|
<description>
|
|
@@ -684,7 +792,7 @@ class CommandAutoTuner:
|
|
|
684
792
|
- 如果没有可撤销的操作会提示错误
|
|
685
793
|
</usage>
|
|
686
794
|
</command>
|
|
687
|
-
|
|
795
|
+
|
|
688
796
|
<command>
|
|
689
797
|
<name>help</name>
|
|
690
798
|
<description>
|
|
@@ -702,7 +810,7 @@ class CommandAutoTuner:
|
|
|
702
810
|
help(query="")
|
|
703
811
|
|
|
704
812
|
## 帮助用户执行特定的配置
|
|
705
|
-
|
|
813
|
+
|
|
706
814
|
help(query="关闭索引")
|
|
707
815
|
|
|
708
816
|
这条命令会触发:
|
|
@@ -714,7 +822,7 @@ class CommandAutoTuner:
|
|
|
714
822
|
常见的一些配置选项示例:
|
|
715
823
|
|
|
716
824
|
{{ config_readme }}
|
|
717
|
-
|
|
825
|
+
|
|
718
826
|
比如你想开启索引,则可以执行:
|
|
719
827
|
|
|
720
828
|
help(query="开启索引")
|
|
@@ -725,7 +833,7 @@ class CommandAutoTuner:
|
|
|
725
833
|
|
|
726
834
|
</usage>
|
|
727
835
|
</command>
|
|
728
|
-
|
|
836
|
+
|
|
729
837
|
<command>
|
|
730
838
|
<name>chat</name>
|
|
731
839
|
<description>进入聊天模式,与AI进行交互对话。支持多轮对话和上下文理解。</description>
|
|
@@ -788,7 +896,7 @@ class CommandAutoTuner:
|
|
|
788
896
|
使用例子:
|
|
789
897
|
|
|
790
898
|
coding(query="创建一个处理用户登录的函数")
|
|
791
|
-
|
|
899
|
+
|
|
792
900
|
|
|
793
901
|
## 和 chat 搭配使用
|
|
794
902
|
当你用过 chat 之后,继续使用 coding 时,可以添加 /apply 来带上 chat 的对话内容。
|
|
@@ -829,7 +937,7 @@ class CommandAutoTuner:
|
|
|
829
937
|
使用例子:
|
|
830
938
|
|
|
831
939
|
lib(args=["/add", "byzer-llm"])
|
|
832
|
-
|
|
940
|
+
|
|
833
941
|
|
|
834
942
|
## 移除库
|
|
835
943
|
使用 /remove 移除库
|
|
@@ -871,7 +979,7 @@ class CommandAutoTuner:
|
|
|
871
979
|
<description>模型控制面板命令,用于管理和控制AI模型。</description>
|
|
872
980
|
<usage>
|
|
873
981
|
该命令用于管理和控制AI模型的配置和运行。 包含一个参数:query,字符串类型。
|
|
874
|
-
|
|
982
|
+
|
|
875
983
|
## 罗列模型模板
|
|
876
984
|
|
|
877
985
|
models(query="/list")
|
|
@@ -882,11 +990,11 @@ class CommandAutoTuner:
|
|
|
882
990
|
##添加模型模板
|
|
883
991
|
|
|
884
992
|
比如我想添加 open router 或者硅基流动的模型,则可以通过如下方式:
|
|
885
|
-
|
|
993
|
+
|
|
886
994
|
models(query="/add_model name=openrouter-sonnet-3.5 base_url=https://openrouter.ai/api/v1")
|
|
887
|
-
|
|
995
|
+
|
|
888
996
|
这样就能添加自定义模型: openrouter-sonnet-3.5
|
|
889
|
-
|
|
997
|
+
|
|
890
998
|
|
|
891
999
|
如果你想添加添加硅基流动deepseek 模型的方式为:
|
|
892
1000
|
|
|
@@ -937,7 +1045,7 @@ class CommandAutoTuner:
|
|
|
937
1045
|
models(query="/add_model name=tencent_v3_chat base_url=https://tencent.ai.qq.com/v1 model_name=deepseek-v3")
|
|
938
1046
|
|
|
939
1047
|
*** 特别注意 ***
|
|
940
|
-
|
|
1048
|
+
|
|
941
1049
|
在使用本函数时,如果添加的模型用户在需求中没有提供像推理点名称,激活时的 api key,以及模型名称等,从而导致添加模型会发生不确定性,
|
|
942
1050
|
你务必需要先通过函数 ask_user 来获取,之后得到完整信息再来执行 models 相关的操作。
|
|
943
1051
|
|
|
@@ -947,8 +1055,8 @@ class CommandAutoTuner:
|
|
|
947
1055
|
models(query="/add_model name=ark_r1_chat base_url=https://ark.cn-beijing.volces.com/api/v3 model_name=<收集到的推理点名称> is_reasoning=true")
|
|
948
1056
|
|
|
949
1057
|
models(query="/activate ark_r1_chat <收集到的API key>")
|
|
950
|
-
|
|
951
|
-
|
|
1058
|
+
|
|
1059
|
+
|
|
952
1060
|
</usage>
|
|
953
1061
|
</command>
|
|
954
1062
|
|
|
@@ -962,10 +1070,10 @@ class CommandAutoTuner:
|
|
|
962
1070
|
</description>
|
|
963
1071
|
<usage>
|
|
964
1072
|
该命令接受一个参数 question,为需要向用户询问的问题字符串。
|
|
965
|
-
|
|
1073
|
+
|
|
966
1074
|
使用例子:
|
|
967
1075
|
ask_user(question="请输入火山引擎的 R1 模型推理点")
|
|
968
|
-
|
|
1076
|
+
|
|
969
1077
|
</command>
|
|
970
1078
|
|
|
971
1079
|
<command>
|
|
@@ -973,11 +1081,11 @@ class CommandAutoTuner:
|
|
|
973
1081
|
<description>运行指定的Python代码。主要用于执行一些Python脚本或测试代码。</description>
|
|
974
1082
|
<usage>
|
|
975
1083
|
该命令接受一个参数 code,为要执行的Python代码字符串。
|
|
976
|
-
|
|
1084
|
+
|
|
977
1085
|
使用例子:
|
|
978
|
-
|
|
1086
|
+
|
|
979
1087
|
run_python(code="print('Hello World')")
|
|
980
|
-
|
|
1088
|
+
|
|
981
1089
|
注意:
|
|
982
1090
|
- 代码将在项目根目录下执行
|
|
983
1091
|
- 可以访问项目中的所有文件
|
|
@@ -990,12 +1098,12 @@ class CommandAutoTuner:
|
|
|
990
1098
|
<description>运行指定的Shell脚本。主要用于编译、运行、测试等任务。</description>
|
|
991
1099
|
<usage>
|
|
992
1100
|
该命令接受一个参数 command,为要执行的Shell脚本字符串。
|
|
993
|
-
|
|
994
|
-
|
|
1101
|
+
|
|
1102
|
+
|
|
995
1103
|
使用例子:
|
|
996
|
-
|
|
1104
|
+
|
|
997
1105
|
execute_shell_command(command="ls -l")
|
|
998
|
-
|
|
1106
|
+
|
|
999
1107
|
注意:
|
|
1000
1108
|
- 脚本将在项目根目录下执行
|
|
1001
1109
|
- 禁止执行包含 rm 命令的脚本
|
|
@@ -1022,14 +1130,14 @@ class CommandAutoTuner:
|
|
|
1022
1130
|
<description>返回当前项目结构</description>
|
|
1023
1131
|
<usage>
|
|
1024
1132
|
该命令不需要参数。返回一个目录树结构(类似 tree 命令的输出)
|
|
1025
|
-
|
|
1133
|
+
|
|
1026
1134
|
使用例子:
|
|
1027
|
-
|
|
1135
|
+
|
|
1028
1136
|
get_project_structure()
|
|
1029
|
-
|
|
1137
|
+
|
|
1030
1138
|
该函数特别适合你通过目录结构来了解这个项目是什么类型的项目,有什么文件,如果你对一些文件
|
|
1031
1139
|
感兴趣,可以配合 read_files 函数来读取文件内容,从而帮你做更好的决策
|
|
1032
|
-
|
|
1140
|
+
|
|
1033
1141
|
</usage>
|
|
1034
1142
|
</command>
|
|
1035
1143
|
|
|
@@ -1039,19 +1147,19 @@ class CommandAutoTuner:
|
|
|
1039
1147
|
<usage>
|
|
1040
1148
|
该命令接受一个参数 file_paths,路径list,或者是以逗号分割的多个文件路径。
|
|
1041
1149
|
路径支持相对路径和绝对路径。
|
|
1042
|
-
|
|
1150
|
+
|
|
1043
1151
|
使用例子:
|
|
1044
|
-
|
|
1152
|
+
|
|
1045
1153
|
get_project_map(file_paths=["full/path/to/main.py","partial/path/to/utils.py"]),
|
|
1046
|
-
|
|
1154
|
+
|
|
1047
1155
|
或者:
|
|
1048
|
-
|
|
1156
|
+
|
|
1049
1157
|
get_project_map(file_paths="full/path/to/main.py,partial/path/to/utils.py")
|
|
1050
1158
|
|
|
1051
1159
|
该函数特别适合你想要了解某个文件的用途,以及该文件的导入的包,定义的类,函数,变量等信息。
|
|
1052
1160
|
同时,你还能看到文件的大小(tokens数),以及索引的大小(tokens数),以及构建索引花费费用等信息。
|
|
1053
1161
|
如果你觉得该文件确实是你关注的,你可以通过 read_files 函数来读取文件完整内容,从而帮你做更好的决策。
|
|
1054
|
-
|
|
1162
|
+
|
|
1055
1163
|
注意:
|
|
1056
1164
|
- 返回值为JSON格式文本
|
|
1057
1165
|
- 只能返回已被索引的文件
|
|
@@ -1096,9 +1204,9 @@ class CommandAutoTuner:
|
|
|
1096
1204
|
|
|
1097
1205
|
你可以使用 get_project_structure 函数获取项目结构后,然后再通过 get_project_map 函数获取某个文件的用途,符号列表,以及
|
|
1098
1206
|
文件大小(tokens数),最后再通过 read_files 函数来读取文件内容,从而帮你做更好的决策。如果需要读取的文件过大,
|
|
1099
|
-
|
|
1207
|
+
|
|
1100
1208
|
特别注意:使用 read_files 时,一次性读取文件数量不要超过1个,每次只读取200行。如果发现读取的内容不够,则继续读取下面200行。
|
|
1101
|
-
|
|
1209
|
+
|
|
1102
1210
|
</usage>
|
|
1103
1211
|
</command>
|
|
1104
1212
|
|
|
@@ -1107,11 +1215,11 @@ class CommandAutoTuner:
|
|
|
1107
1215
|
<description>根据文件名中的关键字搜索文件。</description>
|
|
1108
1216
|
<usage>
|
|
1109
1217
|
该命令接受一个参数 keyword,为要搜索的关键字字符串。
|
|
1110
|
-
|
|
1218
|
+
|
|
1111
1219
|
使用例子:
|
|
1112
|
-
|
|
1220
|
+
|
|
1113
1221
|
find_files_by_name(keyword="test")
|
|
1114
|
-
|
|
1222
|
+
|
|
1115
1223
|
注意:
|
|
1116
1224
|
- 搜索不区分大小写
|
|
1117
1225
|
- 返回所有匹配的文件路径,逗号分隔
|
|
@@ -1123,11 +1231,11 @@ class CommandAutoTuner:
|
|
|
1123
1231
|
<description>根据文件内容中的关键字搜索文件。</description>
|
|
1124
1232
|
<usage>
|
|
1125
1233
|
该命令接受一个参数 keyword,为要搜索的关键字字符串。
|
|
1126
|
-
|
|
1234
|
+
|
|
1127
1235
|
使用例子:
|
|
1128
|
-
|
|
1236
|
+
|
|
1129
1237
|
find_files_by_content(keyword="TODO")
|
|
1130
|
-
|
|
1238
|
+
|
|
1131
1239
|
注意:
|
|
1132
1240
|
- 搜索不区分大小写
|
|
1133
1241
|
- 如果结果过多,只返回前10个匹配项
|
|
@@ -1152,7 +1260,7 @@ class CommandAutoTuner:
|
|
|
1152
1260
|
```
|
|
1153
1261
|
##File: /path/to/file.py
|
|
1154
1262
|
##Line: 10-20
|
|
1155
|
-
|
|
1263
|
+
|
|
1156
1264
|
内容
|
|
1157
1265
|
```
|
|
1158
1266
|
|
|
@@ -1170,10 +1278,10 @@ class CommandAutoTuner:
|
|
|
1170
1278
|
<description>配置管理命令,用于管理和控制配置。</description>
|
|
1171
1279
|
<usage>
|
|
1172
1280
|
该命令导出当前软件的配置,并保存到指定路径。
|
|
1173
|
-
|
|
1281
|
+
|
|
1174
1282
|
使用例子:
|
|
1175
1283
|
conf_export(path="导出路径,通常是.json文件")
|
|
1176
|
-
|
|
1284
|
+
|
|
1177
1285
|
</usage>
|
|
1178
1286
|
</command>
|
|
1179
1287
|
|
|
@@ -1182,10 +1290,10 @@ class CommandAutoTuner:
|
|
|
1182
1290
|
<description>配置管理命令,用于管理和控制配置。</description>
|
|
1183
1291
|
<usage>
|
|
1184
1292
|
该命令导入指定路径的配置文件到当前软件。
|
|
1185
|
-
|
|
1293
|
+
|
|
1186
1294
|
使用例子:
|
|
1187
1295
|
conf_import(path="导入路径,通常是.json文件")
|
|
1188
|
-
|
|
1296
|
+
|
|
1189
1297
|
</usage>
|
|
1190
1298
|
</command>
|
|
1191
1299
|
|
|
@@ -1194,10 +1302,10 @@ class CommandAutoTuner:
|
|
|
1194
1302
|
<description>索引管理命令,用于管理和控制索引。</description>
|
|
1195
1303
|
<usage>
|
|
1196
1304
|
该命令导出当前软件的索引,并保存到指定路径。
|
|
1197
|
-
|
|
1305
|
+
|
|
1198
1306
|
使用例子:
|
|
1199
1307
|
index_export(path="导出路径,通常是.json文件")
|
|
1200
|
-
|
|
1308
|
+
|
|
1201
1309
|
</usage>
|
|
1202
1310
|
</command>
|
|
1203
1311
|
|
|
@@ -1206,10 +1314,10 @@ class CommandAutoTuner:
|
|
|
1206
1314
|
<description>索引管理命令,用于管理和控制索引。</description>
|
|
1207
1315
|
<usage>
|
|
1208
1316
|
该命令导入指定路径的索引文件到当前软件。
|
|
1209
|
-
|
|
1317
|
+
|
|
1210
1318
|
使用例子:
|
|
1211
1319
|
index_import(path="导入路径,通常最后是.json文件")
|
|
1212
|
-
|
|
1320
|
+
|
|
1213
1321
|
</usage>
|
|
1214
1322
|
</command>
|
|
1215
1323
|
|
|
@@ -1218,11 +1326,11 @@ class CommandAutoTuner:
|
|
|
1218
1326
|
<description>排除指定文件。</description>
|
|
1219
1327
|
<usage>
|
|
1220
1328
|
该命令接受一个参数 query, 为要排除的文件模式字符串,多个文件模式用逗号分隔。
|
|
1221
|
-
|
|
1329
|
+
|
|
1222
1330
|
使用例子,比如你想要排除 package-lock.json 文件,你可以这样调用:
|
|
1223
|
-
|
|
1331
|
+
|
|
1224
1332
|
exclude_files(query="regex://.*/package-lock\.json")
|
|
1225
|
-
|
|
1333
|
+
|
|
1226
1334
|
注意:
|
|
1227
1335
|
- 文件模式字符串必须以 regex:// 开头
|
|
1228
1336
|
- regex:// 后面部分是标准的正则表达式
|
|
@@ -1255,7 +1363,7 @@ class CommandAutoTuner:
|
|
|
1255
1363
|
<description>响应用户。</description>
|
|
1256
1364
|
<usage>
|
|
1257
1365
|
如果你需要直接发送信息给用户,那么可以通过 response_user 函数来直接回复用户。
|
|
1258
|
-
|
|
1366
|
+
|
|
1259
1367
|
比如用户问你是谁?
|
|
1260
1368
|
你可以通过如下方式来回答:
|
|
1261
1369
|
response_user(response="你好,我是 auto-coder")
|
|
@@ -1270,10 +1378,10 @@ class CommandAutoTuner:
|
|
|
1270
1378
|
|
|
1271
1379
|
使用例子:
|
|
1272
1380
|
count_file_tokens(file_path="full")
|
|
1273
|
-
|
|
1381
|
+
|
|
1274
1382
|
注意:
|
|
1275
1383
|
- 返回值为int类型,表示文件的token数量。
|
|
1276
|
-
|
|
1384
|
+
|
|
1277
1385
|
</usage>
|
|
1278
1386
|
</command>
|
|
1279
1387
|
|
|
@@ -1285,10 +1393,10 @@ class CommandAutoTuner:
|
|
|
1285
1393
|
|
|
1286
1394
|
使用例子:
|
|
1287
1395
|
count_string_tokens(text="你好,世界")
|
|
1288
|
-
|
|
1396
|
+
|
|
1289
1397
|
注意:
|
|
1290
1398
|
- 返回值为int类型,表示文本的token数量。
|
|
1291
|
-
|
|
1399
|
+
|
|
1292
1400
|
</usage>
|
|
1293
1401
|
</command>
|
|
1294
1402
|
|
|
@@ -1301,15 +1409,15 @@ class CommandAutoTuner:
|
|
|
1301
1409
|
使用例子:
|
|
1302
1410
|
find_symbol_definition(symbol="MyClass")
|
|
1303
1411
|
find_symbol_definition(symbol="process_data")
|
|
1304
|
-
|
|
1412
|
+
|
|
1305
1413
|
注意:
|
|
1306
1414
|
- 返回值为字符串,包含符号定义所在的文件路径列表,以逗号分隔
|
|
1307
1415
|
- 支持精确匹配和模糊匹配(不区分大小写)
|
|
1308
1416
|
- 如果未找到匹配项,会返回提示信息
|
|
1309
|
-
|
|
1417
|
+
|
|
1310
1418
|
</usage>
|
|
1311
1419
|
</command>
|
|
1312
|
-
|
|
1420
|
+
|
|
1313
1421
|
<command>
|
|
1314
1422
|
<n>execute_mcp_server</n>
|
|
1315
1423
|
<description>执行MCP服务器</description>
|
|
@@ -1322,13 +1430,13 @@ class CommandAutoTuner:
|
|
|
1322
1430
|
<mcp_server_info>
|
|
1323
1431
|
{{ mcp_server_info }}
|
|
1324
1432
|
</mcp_server_info>
|
|
1325
|
-
|
|
1433
|
+
|
|
1326
1434
|
</usage>
|
|
1327
1435
|
</command>
|
|
1328
1436
|
'''
|
|
1329
1437
|
return {
|
|
1330
1438
|
"config_readme": config_readme.prompt(),
|
|
1331
|
-
"mcp_server_info": self.mcp_server_info
|
|
1439
|
+
"mcp_server_info": self.mcp_server_info
|
|
1332
1440
|
}
|
|
1333
1441
|
|
|
1334
1442
|
def execute_auto_command(self, command: str, parameters: Dict[str, Any]) -> None:
|
|
@@ -1338,7 +1446,7 @@ class CommandAutoTuner:
|
|
|
1338
1446
|
command_map = {
|
|
1339
1447
|
"add_files": self.command_config.add_files,
|
|
1340
1448
|
"remove_files": self.command_config.remove_files,
|
|
1341
|
-
"list_files": self.command_config.list_files,
|
|
1449
|
+
"list_files": self.command_config.list_files,
|
|
1342
1450
|
"revert": self.command_config.revert,
|
|
1343
1451
|
"commit": self.command_config.commit,
|
|
1344
1452
|
"help": self.command_config.help,
|
|
@@ -1358,16 +1466,16 @@ class CommandAutoTuner:
|
|
|
1358
1466
|
"index_import": self.command_config.index_import,
|
|
1359
1467
|
"exclude_files": self.command_config.exclude_files,
|
|
1360
1468
|
|
|
1361
|
-
"run_python": self.tools.run_python_code,
|
|
1469
|
+
"run_python": self.tools.run_python_code,
|
|
1362
1470
|
"get_related_files_by_symbols": self.tools.get_related_files_by_symbols,
|
|
1363
1471
|
"get_project_map": self.tools.get_project_map,
|
|
1364
1472
|
"get_project_structure": self.tools.get_project_structure,
|
|
1365
1473
|
"list_files": self.tools.list_files,
|
|
1366
1474
|
"read_files": self.tools.read_files,
|
|
1367
1475
|
"find_files_by_name": self.tools.find_files_by_name,
|
|
1368
|
-
"find_files_by_content": self.tools.find_files_by_content,
|
|
1476
|
+
"find_files_by_content": self.tools.find_files_by_content,
|
|
1369
1477
|
"get_project_related_files": self.tools.get_project_related_files,
|
|
1370
|
-
"ask_user":self.tools.ask_user,
|
|
1478
|
+
"ask_user": self.tools.ask_user,
|
|
1371
1479
|
"read_file_with_keyword_ranges": self.tools.read_file_with_keyword_ranges,
|
|
1372
1480
|
"get_project_type": self.project_type_analyzer.analyze,
|
|
1373
1481
|
"response_user": self.tools.response_user,
|
|
@@ -1375,7 +1483,7 @@ class CommandAutoTuner:
|
|
|
1375
1483
|
"count_file_tokens": self.tools.count_file_tokens,
|
|
1376
1484
|
"count_string_tokens": self.tools.count_string_tokens,
|
|
1377
1485
|
"find_symbol_definition": self.tools.find_symbol_definition,
|
|
1378
|
-
|
|
1486
|
+
|
|
1379
1487
|
}
|
|
1380
1488
|
|
|
1381
1489
|
if command not in command_map:
|
|
@@ -1388,7 +1496,7 @@ class CommandAutoTuner:
|
|
|
1388
1496
|
if parameters:
|
|
1389
1497
|
command_map[command](**parameters)
|
|
1390
1498
|
else:
|
|
1391
|
-
command_map[command]()
|
|
1499
|
+
command_map[command]()
|
|
1392
1500
|
|
|
1393
1501
|
except Exception as e:
|
|
1394
1502
|
error_msg = str(e)
|