auto-coder 0.1.259__py3-none-any.whl → 0.1.260__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.

@@ -0,0 +1,533 @@
1
+ from typing import Optional
2
+ from autocoder.common.result_manager import ResultManager
3
+ from autocoder.index.index import IndexManager
4
+ from autocoder.pyproject import PyProject
5
+ from autocoder.tsproject import TSProject
6
+ from autocoder.suffixproject import SuffixProject
7
+ from autocoder.common import AutoCoderArgs, SourceCode
8
+ from autocoder.common.interpreter import Interpreter
9
+ from autocoder.common import ExecuteSteps, ExecuteStep, detect_env
10
+ from autocoder.common import code_auto_execute
11
+ from typing import List, Tuple
12
+ import os
13
+ import byzerllm
14
+ import json
15
+ from pydantic import BaseModel
16
+ from byzerllm.types import Bool
17
+ from contextlib import contextmanager
18
+ from rich.console import Console
19
+ from rich.panel import Panel
20
+ from rich.text import Text
21
+ from rich.prompt import Prompt
22
+ from typing import Union
23
+ from autocoder.utils.queue_communicate import (
24
+ queue_communicate,
25
+ CommunicateEvent,
26
+ CommunicateEventType,
27
+ )
28
+ import sys
29
+ import io
30
+
31
+ @byzerllm.prompt()
32
+ def detect_rm_command(command: str) -> Bool:
33
+ """
34
+ 给定如下shell脚本:
35
+
36
+ ```shell
37
+ {{ command }}
38
+ ```
39
+
40
+ 如果该脚本中包含删除目录或者文件的命令,请返回True,否则返回False。
41
+ """
42
+
43
+ @contextmanager
44
+ def redirect_stdout():
45
+ original_stdout = sys.stdout
46
+ sys.stdout = f = io.StringIO()
47
+ try:
48
+ yield f
49
+ finally:
50
+ sys.stdout = original_stdout
51
+
52
+ class AutoCommandTools:
53
+ def __init__(self, args: AutoCoderArgs,
54
+ llm: Union[byzerllm.ByzerLLM, byzerllm.SimpleByzerLLM]):
55
+ self.args = args
56
+ self.llm = llm
57
+ self.result_manager = ResultManager()
58
+
59
+ def ask_user(self,question:str) -> str:
60
+ '''
61
+ 如果你对用户的问题有什么疑问,或者你想从用户收集一些额外信息,可以调用此方法。
62
+ 输入参数 question 是你对用户的提问。
63
+ 返回值是 用户对你问题的回答。
64
+
65
+ 注意,尽量不要询问用户,除非你感受到你无法回答用户的问题。
66
+ '''
67
+
68
+ if self.args.request_id and not self.args.silence and not self.args.skip_events:
69
+ event_data = {
70
+ "question": question
71
+ }
72
+ response_json = queue_communicate.send_event(
73
+ request_id=self.args.request_id,
74
+ event=CommunicateEvent(
75
+ event_type=CommunicateEventType.ASK_HUMAN.value,
76
+ data=json.dumps(event_data, ensure_ascii=False),
77
+ ),
78
+ )
79
+ return response_json
80
+
81
+ console = Console()
82
+
83
+ # 创建一个醒目的问题面板
84
+ question_text = Text(question, style="bold cyan")
85
+ question_panel = Panel(
86
+ question_text,
87
+ title="[bold yellow]auto-coder.chat's Question[/bold yellow]",
88
+ border_style="blue",
89
+ expand=False
90
+ )
91
+
92
+ # 显示问题面板
93
+ console.print(question_panel)
94
+
95
+ # 创建一个自定义提示符
96
+ prompt = Prompt.ask(
97
+ "\n[bold green]Your Answer[/bold green]",
98
+ console=console
99
+ )
100
+
101
+ # 获取用户的回答
102
+ answer = prompt
103
+
104
+ # 显示用户的回答
105
+ answer_text = Text(answer, style="italic")
106
+ answer_panel = Panel(
107
+ answer_text,
108
+ title="[bold yellow]Your Response[/bold yellow]",
109
+ border_style="green",
110
+ expand=False
111
+ )
112
+ console.print(answer_panel)
113
+
114
+ self.result_manager.append(content=answer, meta = {
115
+ "action": "ask_user",
116
+ "input": {
117
+ "question": question
118
+ }
119
+ })
120
+
121
+ return answer
122
+
123
+ def run_python_code(self, code: str) -> str:
124
+ """
125
+ 你可以通过该工具运行指定的Python代码。
126
+ 输入参数 code: Python代码
127
+ 返回值是Python代码的sys output 或者 sys error 信息。
128
+
129
+ 通常你需要在代码中指定项目的根目录(前面我们已经提到了)。
130
+ """
131
+ interpreter = Interpreter(cwd=self.args.source_dir)
132
+ s = ""
133
+ try:
134
+ s = interpreter.execute_steps(
135
+ ExecuteSteps(steps=[ExecuteStep(lang="python", code=code)])
136
+ )
137
+ finally:
138
+ interpreter.close()
139
+
140
+ self.result_manager.append(content=s, meta = {
141
+ "action": "run_python_code",
142
+ "input": {
143
+ "code": code
144
+ }
145
+ })
146
+
147
+ return s
148
+
149
+ def run_shell_code(self, script: str) -> str:
150
+ """
151
+ 你可以通过该工具运行指定的Shell代码。主要用于一些编译,运行,测试等任务。
152
+ 输入参数 script: Shell代码
153
+ 返回值是Shell代码的output 或者 error 信息。
154
+ """
155
+
156
+ if detect_rm_command.with_llm(self.llm).run(script).value:
157
+ return "The script contains rm command, which is not allowed."
158
+
159
+ interpreter = Interpreter(cwd=self.args.source_dir)
160
+ s = ""
161
+ try:
162
+ s = interpreter.execute_steps(
163
+ ExecuteSteps(steps=[ExecuteStep(lang="shell", code=script)])
164
+ )
165
+ finally:
166
+ interpreter.close()
167
+
168
+ self.result_manager.append(content=s, meta = {
169
+ "action": "run_shell_code",
170
+ "input": {
171
+ "script": script
172
+ }
173
+ })
174
+
175
+ return s
176
+
177
+ def get_related_files_by_symbols(self, query: str) -> str:
178
+ """
179
+ 你可以给出类名,函数名,以及文件的用途描述等信息,该工具会根据这些信息返回项目中相关的文件。
180
+ """
181
+ v = self.get_project_related_files(query)
182
+ self.result_manager.append(content=v, meta = {
183
+ "action": "get_related_files_by_symbols",
184
+ "input": {
185
+ "query": query
186
+ }
187
+ })
188
+ return v
189
+
190
+ def get_project_related_files(self, query: str) -> str:
191
+ """
192
+ 该工具会根据查询描述,根据索引返回项目中与查询相关的文件。
193
+ 返回值为按逗号分隔的文件路径列表。
194
+
195
+ 注意,该工具无法涵盖当前项目中所有文件,因为有些文件可能没有被索引。
196
+ """
197
+ if self.args.project_type == "ts":
198
+ pp = TSProject(args=self.args, llm=self.llm)
199
+ elif self.args.project_type == "py":
200
+ pp = PyProject(args=self.args, llm=self.llm)
201
+ else:
202
+ pp = SuffixProject(args=self.args, llm=self.llm, file_filter=None)
203
+ pp.run()
204
+ sources = pp.sources
205
+
206
+ index_manager = IndexManager(llm=self.llm, sources=sources, args=self.args)
207
+ target_files = index_manager.get_target_files_by_query(query)
208
+ file_list = target_files.file_list
209
+ v = ",".join([file.file_path for file in file_list])
210
+ self.result_manager.append(content=v, meta = {
211
+ "action": "get_project_related_files",
212
+ "input": {
213
+ "query": query
214
+ }
215
+ })
216
+ return v
217
+
218
+ def get_project_map(self, file_path: Optional[str] = None) -> str:
219
+ """
220
+ 该工具会返回项目中所有已经被构建索引的文件以及该文件的信息,诸如该文件的用途,导入的包,定义的类,函数,变量等信息。
221
+ 返回的是json格式文本。
222
+
223
+ 注意,这个工具无法返回所有文件的信息,因为有些文件可能没有被索引。
224
+ 尽量避免使用该工具。
225
+ """
226
+ if self.args.project_type == "ts":
227
+ pp = TSProject(args=self.args, llm=self.llm)
228
+ elif self.args.project_type == "py":
229
+ pp = PyProject(args=self.args, llm=self.llm)
230
+ else:
231
+ pp = SuffixProject(args=self.args, llm=self.llm, file_filter=None)
232
+ pp.run()
233
+ sources = pp.sources
234
+
235
+ index_manager = IndexManager(llm=self.llm, sources=sources, args=self.args)
236
+ s = index_manager.read_index_as_str()
237
+ index_data = json.loads(s)
238
+
239
+ final_result = []
240
+ for k in index_data.values():
241
+ value = {}
242
+ value["file_name"] = k["module_name"]
243
+ value["symbols"] = k["symbols"]
244
+ value["file_tokens"] = k.get("input_tokens_count", -1)
245
+ value["index_tokens"] = k.get("generated_tokens_count", -1)
246
+ value["file_tokens_cost"] = k.get("input_tokens_cost", -1)
247
+ value["index_tokens_cost"] = k.get("generated_tokens_cost", -1)
248
+ if file_path and file_path in k["module_name"]:
249
+ final_result.append(value)
250
+ v = json.dumps(final_result, ensure_ascii=False)
251
+ self.result_manager.add_result(content=v, meta = {
252
+ "action": "get_project_map",
253
+ "input": {
254
+ }
255
+ })
256
+ return v
257
+
258
+ def read_file_with_keyword_ranges(self, file_path: str, keyword:str, before_size:int = 100, after_size:int = 100) -> str:
259
+ """
260
+ 该函数用于读取包含了关键字(keyword)的行,以及该行前后指定大小的行。
261
+ 输入参数:
262
+ - file_path: 文件路径
263
+ - keyword: 关键字
264
+ - before_size: 关键字所在行之前的行数
265
+ - after_size: 关键字所在行之后的行数
266
+
267
+ 返回值:
268
+ - 返回str类型,返回包含关键字的行,以及该行前后指定大小的行。
269
+
270
+ 返回值的格式如下:
271
+ ```
272
+ ##File: /path/to/file.py
273
+ ##Line: 10-20
274
+
275
+ 内容
276
+ ```
277
+ """
278
+ absolute_path = file_path
279
+ if not os.path.isabs(file_path):
280
+ # Find the first matching absolute path by traversing args.source_dir
281
+ for root, _, files in os.walk(self.args.source_dir):
282
+ for file in files:
283
+ if file_path in os.path.join(root, file):
284
+ absolute_path = os.path.join(root, file)
285
+ break
286
+
287
+ result = []
288
+ try:
289
+ with open(absolute_path, 'r', encoding='utf-8') as f:
290
+ lines = f.readlines()
291
+
292
+ # Find all lines containing the keyword
293
+ keyword_lines = []
294
+ for i, line in enumerate(lines):
295
+ if keyword.lower() in line.lower():
296
+ keyword_lines.append(i)
297
+
298
+ # Process each keyword line and its surrounding range
299
+ processed_ranges = set()
300
+ for line_num in keyword_lines:
301
+ # Calculate range boundaries
302
+ start = max(0, line_num - before_size)
303
+ end = min(len(lines), line_num + after_size + 1)
304
+
305
+ # Check if this range overlaps with any previously processed range
306
+ range_key = (start, end)
307
+ if range_key in processed_ranges:
308
+ continue
309
+
310
+ processed_ranges.add(range_key)
311
+
312
+ # Format the content block
313
+ content = f"##File: {absolute_path}\n"
314
+ content += f"##Line: {start+1}-{end}\n\n"
315
+ content += "".join(lines[start:end])
316
+ result.append(content)
317
+
318
+ except Exception as e:
319
+ v = f"Error reading file {absolute_path}: {str(e)}"
320
+ self.result_manager.add_result(content=v, meta={
321
+ "action": "read_file_with_keyword_ranges",
322
+ "input": {
323
+ "file_path": file_path,
324
+ "keyword": keyword,
325
+ "before_size": before_size,
326
+ "after_size": after_size
327
+ }
328
+ })
329
+ return v
330
+
331
+ final_result = "\n\n".join(result)
332
+ self.result_manager.add_result(content=final_result, meta={
333
+ "action": "read_file_with_keyword_ranges",
334
+ "input": {
335
+ "file_path": file_path,
336
+ "keyword": keyword,
337
+ "before_size": before_size,
338
+ "after_size": after_size
339
+ }
340
+ })
341
+
342
+ return final_result
343
+
344
+ def read_files(self, paths: str, line_ranges: Optional[str] = None) -> str:
345
+ """
346
+ 该工具用于读取指定文件的内容。
347
+
348
+ 参数说明:
349
+ 1. paths (str):
350
+ - 以逗号分隔的文件路径列表
351
+ - 支持两种格式:
352
+ a) 文件名: 如果多个文件匹配该名称,将选择第一个匹配项
353
+ b) 绝对路径: 直接指定文件的完整路径
354
+ - 示例: "main.py,utils.py" 或 "/path/to/main.py,/path/to/utils.py"
355
+ - 建议: 每次调用最多指定5-6个最相关的文件,以避免返回内容过多
356
+
357
+ 2. line_ranges (Optional[str]):
358
+ - 可选参数,用于指定每个文件要读取的具体行范围
359
+ - 格式说明:
360
+ * 使用逗号分隔不同文件的行范围
361
+ * 每个文件可以指定多个行范围,用/分隔
362
+ * 每个行范围使用-连接起始行和结束行
363
+ - 示例:
364
+ * "1-100,2-50" (为两个文件分别指定一个行范围)
365
+ * "1-100/200-300,50-100" (第一个文件指定两个行范围,第二个文件指定一个行范围)
366
+ - 注意: line_ranges中的文件数量必须与paths中的文件数量一致
367
+
368
+ 返回值:
369
+ - 返回str类型,包含所有请求文件的内容
370
+ - 每个文件内容前会标注文件路径和行范围信息(如果指定了行范围)
371
+ """
372
+ paths = [p.strip() for p in paths.split(",")]
373
+ source_code_str = ""
374
+
375
+ # Parse line ranges if provided
376
+ file_line_ranges = {}
377
+ if line_ranges:
378
+ ranges_per_file = line_ranges.split(",")
379
+ if len(ranges_per_file) != len(paths):
380
+ self.result_manager.add_result(content="Number of line ranges must match number of files", meta = {
381
+ "action": "read_files",
382
+ "input": {
383
+ "paths": paths,
384
+ "line_ranges": line_ranges
385
+ }
386
+ })
387
+ raise ValueError("Number of line ranges must match number of files")
388
+
389
+ for path, ranges in zip(paths, ranges_per_file):
390
+ file_line_ranges[path] = []
391
+ for range_str in ranges.split("/"):
392
+ if not range_str:
393
+ continue
394
+ start, end = map(int, range_str.split("-"))
395
+ file_line_ranges[path].append((start, end))
396
+
397
+ for path in paths:
398
+ absolute_path = path
399
+ if not os.path.isabs(path):
400
+ # Find the first matching absolute path by traversing args.source_dir
401
+ for root, _, files in os.walk(self.args.source_dir):
402
+ for file in files:
403
+ if path in os.path.join(root, file):
404
+ absolute_path = os.path.join(root, file)
405
+ break
406
+
407
+ with open(absolute_path, "r", encoding="utf-8") as f:
408
+ if path in file_line_ranges:
409
+ # Read specific line ranges
410
+ lines = f.readlines()
411
+ filtered_lines = []
412
+ for start, end in file_line_ranges[path]:
413
+ # Adjust for 0-based indexing
414
+ start = max(0, start - 1)
415
+ end = min(len(lines), end)
416
+ content = "".join(lines[start:end])
417
+ filtered_lines.extend(f"##File: {absolute_path}\n##Line: {start}-{end}\n\n{content}")
418
+ source_code = "".join(filtered_lines)
419
+ else:
420
+ # Read entire file if no range specified
421
+ content = f.read()
422
+ source_code = f"##File: {absolute_path}\n\n{content}"
423
+
424
+ sc = SourceCode(module_name=absolute_path, source_code=source_code)
425
+ source_code_str += f"{sc.source_code}\n\n"
426
+
427
+ self.result_manager.add_result(content=source_code_str, meta = {
428
+ "action": "read_files",
429
+ "input": {
430
+ "paths": paths,
431
+ "line_ranges": line_ranges
432
+ }
433
+ })
434
+ return source_code_str
435
+
436
+ def get_project_structure(self) -> str:
437
+ if self.args.project_type == "ts":
438
+ pp = TSProject(args=self.args, llm=self.llm)
439
+ elif self.args.project_type == "py":
440
+ pp = PyProject(args=self.args, llm=self.llm)
441
+ else:
442
+ pp = SuffixProject(args=self.args, llm=self.llm, file_filter=None)
443
+ pp.run()
444
+ s = pp.get_tree_like_directory_structure()
445
+ self.result_manager.add_result(content=s, meta = {
446
+ "action": "get_project_structure",
447
+ "input": {
448
+ }
449
+ })
450
+ return s
451
+
452
+
453
+ def find_files_by_name(self, keyword: str) -> str:
454
+ """
455
+ 根据关键字在项目中搜索文件名。
456
+ 输入参数 keyword: 要搜索的关键字
457
+ 返回值是文件名包含该关键字的文件路径列表,以逗号分隔。
458
+
459
+ 该工具会搜索文件名,返回所有匹配的文件。
460
+ 搜索不区分大小写。
461
+ """
462
+ matched_files = []
463
+ for root, _, files in os.walk(self.args.source_dir):
464
+ for file in files:
465
+ if keyword.lower() in file.lower():
466
+ matched_files.append(os.path.join(root, file))
467
+
468
+ v = ",".join(matched_files)
469
+ self.result_manager.add_result(content=v, meta = {
470
+ "action": "find_files_by_name",
471
+ "input": {
472
+ "keyword": keyword
473
+ }
474
+ })
475
+ return v
476
+
477
+ def find_files_by_content(self, keyword: str) -> str:
478
+ """
479
+ 根据关键字在项目中搜索文件内容。
480
+ 输入参数 keyword: 要搜索的关键字
481
+ 返回值是内容包含该关键字的文件路径列表,以逗号分隔。
482
+
483
+ 该工具会搜索文件内容,返回所有匹配的文件。
484
+ 如果结果过多,只返回前10个匹配项。
485
+ 搜索不区分大小写。
486
+
487
+ 默认排除以下目录:['node_modules', '.git', '.venv', 'venv', '__pycache__', 'dist', 'build']
488
+ """
489
+ # 需要排除的目录和文件模式
490
+ excluded_dirs = [
491
+ 'node_modules', '.git', '.venv', 'venv', '__pycache__', 'dist', 'build',
492
+ '.DS_Store', '.idea', '.vscode', 'tmp', 'temp', 'cache', 'coverage',
493
+ 'htmlcov', '.mypy_cache', '.pytest_cache', '.hypothesis'
494
+ ]
495
+ excluded_file_patterns = [
496
+ '*.pyc', '*.pyo', '*.pyd', '*.egg-info', '*.log'
497
+ ]
498
+
499
+ matched_files = []
500
+
501
+ for root, dirs, files in os.walk(self.args.source_dir):
502
+ # 移除需要排除的目录
503
+ dirs[:] = [d for d in dirs if d not in excluded_dirs]
504
+
505
+ # 过滤掉需要排除的文件
506
+ files[:] = [f for f in files if not any(
507
+ f.endswith(pattern[1:]) for pattern in excluded_file_patterns
508
+ )]
509
+
510
+ for file in files:
511
+ file_path = os.path.join(root, file)
512
+ try:
513
+ with open(file_path, "r", encoding="utf-8") as f:
514
+ content = f.read()
515
+ if keyword.lower() in content.lower():
516
+ matched_files.append(file_path)
517
+ # Limit to first 10 matches
518
+ if len(matched_files) >= 10:
519
+ break
520
+ except Exception:
521
+ # Skip files that can't be read
522
+ pass
523
+ if len(matched_files) >= 10:
524
+ break
525
+
526
+ v = ",".join(matched_files[:10])
527
+ self.result_manager.add_result(content=v, meta = {
528
+ "action": "find_files_by_content",
529
+ "input": {
530
+ "keyword": keyword
531
+ }
532
+ })
533
+ return v
@@ -3,7 +3,16 @@ from byzerllm.utils import format_str_jinja2
3
3
 
4
4
  MESSAGES = {
5
5
  "en": {
6
+ "auto_command_action_break": "Command {{command}} execution failed (got {{action}} result), no result can be obtained, please try again",
7
+ "auto_command_break": "Auto command execution failed to execute command: {{command}}",
8
+ "auto_command_executing": "\n\n============= Executing command: {{command}} =============\n\n",
6
9
  "model_provider_select_title": "Select Model Provider",
10
+ "auto_config_analyzing": "Analyzing configuration...",
11
+ "config_delete_success": "Successfully deleted configuration: {{key}}",
12
+ "config_not_found": "Configuration not found: {{key}}",
13
+ "config_invalid_format": "Invalid configuration format. Expected 'key:value'",
14
+ "config_value_empty": "Configuration value cannot be empty",
15
+ "config_set_success": "Successfully set configuration: {{key}} = {{value}}",
7
16
  "model_provider_select_text": "Please select your model provider:",
8
17
  "model_provider_volcano": "Volcano Engine",
9
18
  "model_provider_siliconflow": "SiliconFlow AI",
@@ -71,7 +80,7 @@ MESSAGES = {
71
80
  "Paste the answer to the input box below, use '/break' to exit, '/clear' to clear the screen, '/eof' to submit."
72
81
  ),
73
82
  "code_generation_start": "Auto generate the code...",
74
- "code_generation_complete": "{{ model_names}} Code generation completed in {{ duration }} seconds, input_tokens_count: {{ input_tokens }}, generated_tokens_count: {{ output_tokens }}, input_cost: {{ input_cost }}, output_cost: {{ output_cost }}, speed: {{ speed }} tokens/s",
83
+ "code_generation_complete": "{{ model_names}} Code generation completed in {{ duration }} seconds (sampling_count: {{ sampling_count }}), input_tokens_count: {{ input_tokens }}, generated_tokens_count: {{ output_tokens }}, input_cost: {{ input_cost }}, output_cost: {{ output_cost }}, speed: {{ speed }} tokens/s",
75
84
  "code_merge_start": "Auto merge the code...",
76
85
  "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 }}",
77
86
  "quick_filter_start": "{{ model_name }} Starting filter context(quick_filter)...",
@@ -89,12 +98,12 @@ MESSAGES = {
89
98
  "ranking_start": "Start ranking {{ count }} candidates using model {{ model_name }}",
90
99
  "ranking_failed_request": "Ranking request failed: {{ error }}",
91
100
  "ranking_all_failed": "All ranking requests failed",
92
- "ranking_complete": "{{ model_names }} Ranking completed in {{ elapsed }}s, total voters: {{ total_tasks }}, best candidate index: {{ best_candidate }}, scores: {{ scores }}, input_tokens: {{ input_tokens }}, output_tokens: {{ output_tokens }}, input_cost: {{ input_cost }}, output_cost: {{ output_cost }}",
101
+ "ranking_complete": "{{ model_names }} Ranking completed in {{ elapsed }}s, total voters: {{ total_tasks }}, best candidate index: {{ best_candidate }}, scores: {{ scores }}, input_tokens: {{ input_tokens }}, output_tokens: {{ output_tokens }}, input_cost: {{ input_cost }}, output_cost: {{ output_cost }}, speed: {{ speed }} tokens/s",
93
102
  "ranking_process_failed": "Ranking process failed: {{ error }}",
94
103
  "ranking_failed": "Ranking failed in {{ elapsed }}s, using original order",
95
104
  "begin_index_source_code": "🚀 Begin to index source code in {{ source_dir }}",
96
105
  "stream_out_stats": "Model: {{ model_name }}, Total time: {{ elapsed_time }} seconds, First token time: {{ first_token_time }} seconds, Speed: {{ speed }} tokens/s, Input tokens: {{ input_tokens }}, Output tokens: {{ output_tokens }}, Input cost: {{ input_cost }}, Output cost: {{ output_cost }}",
97
- "quick_filter_stats": "{{ model_names }} 快速过滤器完成,耗时 {{ elapsed_time }} 秒,输入token数: {{ input_tokens }}, 输出token数: {{ output_tokens }}, 输入成本: {{ input_cost }}, 输出成本: {{ output_cost }}",
106
+ "quick_filter_stats": "{{ model_names }} Quick filter completed in {{ elapsed_time }} seconds, input tokens: {{ input_tokens }}, output tokens: {{ output_tokens }}, input cost: {{ input_cost }}, output cost: {{ output_cost }} speed: {{ speed }} tokens/s",
98
107
  "upsert_file": "✅ Updated file: {{ file_path }}",
99
108
  "unmerged_blocks_title": "Unmerged Blocks",
100
109
  "quick_filter_title": "{{ model_name }} is analyzing how to filter context...",
@@ -110,9 +119,23 @@ MESSAGES = {
110
119
  "estimated_chat_input_tokens": "Estimated chat input tokens: {{ estimated_input_tokens }}",
111
120
  "estimated_input_tokens_in_generate": "Estimated input tokens in generate ({{ generate_mode }}): {{ estimated_input_tokens }}",
112
121
  "model_has_access_restrictions": "{{model_name}} has access restrictions, cannot use the current function",
122
+ "auto_command_not_found": "Auto command not found: {{command}}. Please check your input and try again.",
123
+ "auto_command_failed": "Auto command failed: {{error}}. Please check your input and try again.",
124
+ "command_execution_result": "{{action}} execution result",
125
+ "satisfied_prompt": "Requirements satisfied, no further action needed",
126
+ "auto_command_analyzed": "Selected command"
113
127
  },
114
128
  "zh": {
129
+ "auto_command_action_break": "命令 {{command}} 执行失败(获取到了 {{action}} 的结果),无法获得任何结果,请重试",
130
+ "auto_command_break": "自动命令执行失败: {{command}}",
131
+ "auto_command_executing": "\n\n============= 正在执行指令: {{command}} =============\n\n",
115
132
  "model_provider_select_title": "选择模型供应商",
133
+ "auto_config_analyzing": "正在分析配置...",
134
+ "config_delete_success": "成功删除配置: {{key}}",
135
+ "config_not_found": "未找到配置: {{key}}",
136
+ "config_invalid_format": "配置格式无效,应为'key:value'格式",
137
+ "config_value_empty": "配置值不能为空",
138
+ "config_set_success": "成功设置配置: {{key}} = {{value}}",
116
139
  "model_provider_select_text": "请选择您的模型供应商:",
117
140
  "model_provider_volcano": "火山方舟",
118
141
  "model_provider_siliconflow": "硅基流动",
@@ -179,7 +202,7 @@ MESSAGES = {
179
202
  "将获得答案黏贴到下面的输入框,换行后,使用 '/break' 退出,'/clear' 清屏,'/eof' 提交。"
180
203
  ),
181
204
  "code_generation_start": "正在自动生成代码...",
182
- "code_generation_complete": "{{ model_names}} 代码生成完成,耗时 {{ duration }} 秒,输入token数: {{ input_tokens }}, 输出token数: {{ output_tokens }}, 输入成本: {{ input_cost }}, 输出成本: {{ output_cost }}, 速度: {{ speed }} tokens/秒",
205
+ "code_generation_complete": "{{ model_names}} 代码生成完成,耗时 {{ duration }} 秒 (采样数: {{ sampling_count }}), 输入token数: {{ input_tokens }}, 输出token数: {{ output_tokens }}, 输入成本: {{ input_cost }}, 输出成本: {{ output_cost }}, 速度: {{ speed }} tokens/秒",
183
206
  "code_merge_start": "正在自动合并代码...",
184
207
  "code_execution_warning": "发送给模型的内容长度为 {{ content_length }} tokens(您可能收集了太多文件),超过了最大输入长度 {{ max_length }}",
185
208
  "quick_filter_start": "{{ model_name }} 开始查找上下文(quick_filter)...",
@@ -208,16 +231,21 @@ MESSAGES = {
208
231
  "ranking_start": "开始对 {{ count }} 个候选项进行排序,使用模型 {{ model_name }} 打分",
209
232
  "ranking_failed_request": "排序请求失败: {{ error }}",
210
233
  "ranking_all_failed": "所有排序请求都失败",
211
- "ranking_complete": "{{ model_names }} 排序完成,耗时 {{ elapsed }} 秒,总投票数: {{ total_tasks }},最佳候选索引: {{ best_candidate }},得分: {{ scores }},输入token数: {{ input_tokens }},输出token数: {{ output_tokens }} 输入成本: {{ input_cost }}, 输出成本: {{ output_cost }}",
234
+ "ranking_complete": "{{ model_names }} 排序完成,耗时 {{ elapsed }} 秒,总投票数: {{ total_tasks }},最佳候选索引: {{ best_candidate }},得分: {{ scores }},输入token数: {{ input_tokens }},输出token数: {{ output_tokens }},输入成本: {{ input_cost }}, 输出成本: {{ output_cost }},速度: {{ speed }} tokens/秒",
212
235
  "ranking_process_failed": "排序过程失败: {{ error }}",
213
236
  "ranking_failed": "排序失败,耗时 {{ elapsed }} 秒,使用原始顺序",
214
237
  "stream_out_stats": "模型: {{ model_name }},总耗时 {{ elapsed_time }} 秒,首token时间: {{ first_token_time }} 秒, 速度: {{ speed }} tokens/秒, 输入token数: {{ input_tokens }}, 输出token数: {{ output_tokens }}, 输入成本: {{ input_cost }}, 输出成本: {{ output_cost }}",
215
- "quick_filter_stats": "{{ model_names }} Quick filter completed in {{ elapsed_time }} seconds, input tokens: {{ input_tokens }}, output tokens: {{ output_tokens }}, input cost: {{ input_cost }}, output cost: {{ output_cost }}",
238
+ "quick_filter_stats": "{{ model_names }} Quick Filter 完成耗时 {{ elapsed_time }} 秒,输入token数: {{ input_tokens }}, 输出token数: {{ output_tokens }}, 输入成本: {{ input_cost }}, 输出成本: {{ output_cost }} 速度: {{ speed }} tokens/秒",
216
239
  "quick_filter_title": "{{ model_name }} 正在分析如何筛选上下文...",
217
240
  "quick_filter_failed": "❌ 快速过滤器失败: {{ error }}. ",
218
241
  "estimated_chat_input_tokens": "对话输入token预估为: {{ estimated_input_tokens }}",
219
242
  "estimated_input_tokens_in_generate": "生成代码({{ generate_mode }})预计输入token数: {{ estimated_input_tokens_in_generate }}",
220
243
  "model_has_access_restrictions": "{{model_name}} 有访问限制,无法使用当前功能",
244
+ "auto_command_not_found": "未找到自动命令: {{command}}。请检查您的输入并重试。",
245
+ "auto_command_failed": "自动命令执行失败: {{error}}。请检查您的输入并重试。",
246
+ "command_execution_result": "{{action}} 执行结果",
247
+ "satisfied_prompt": "已满足需求,无需进一步操作",
248
+ "auto_command_analyzed": "被选择指令"
221
249
  }}
222
250
 
223
251