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

@@ -37,6 +37,9 @@ from autocoder.index.symbols_utils import (
37
37
  SymbolType,
38
38
  symbols_info_to_str,
39
39
  )
40
+ from autocoder.run_context import get_run_context
41
+ from autocoder.events.event_manager_singleton import get_event_manager
42
+ from autocoder.events import event_content as EventContentCreator
40
43
 
41
44
 
42
45
  @byzerllm.prompt()
@@ -51,6 +54,7 @@ def detect_rm_command(command: str) -> Bool:
51
54
  如果该脚本中包含删除目录或者文件的命令,请返回True,否则返回False。
52
55
  """
53
56
 
57
+
54
58
  @contextmanager
55
59
  def redirect_stdout():
56
60
  original_stdout = sys.stdout
@@ -58,10 +62,11 @@ def redirect_stdout():
58
62
  try:
59
63
  yield f
60
64
  finally:
61
- sys.stdout = original_stdout
65
+ sys.stdout = original_stdout
66
+
62
67
 
63
68
  class AutoCommandTools:
64
- def __init__(self, args: AutoCoderArgs,
69
+ def __init__(self, args: AutoCoderArgs,
65
70
  llm: Union[byzerllm.ByzerLLM, byzerllm.SimpleByzerLLM]):
66
71
  self.args = args
67
72
  self.llm = llm
@@ -69,7 +74,7 @@ class AutoCommandTools:
69
74
  self.printer = Printer()
70
75
 
71
76
  def execute_mcp_server(self, query: str) -> str:
72
- from autocoder.common.mcp_server import get_mcp_server, McpRequest, McpInstallRequest, McpRemoveRequest, McpListRequest, McpListRunningRequest, McpRefreshRequest
77
+ from autocoder.common.mcp_server import get_mcp_server, McpRequest, McpInstallRequest, McpRemoveRequest, McpListRequest, McpListRunningRequest, McpRefreshRequest
73
78
  mcp_server = get_mcp_server()
74
79
  response = mcp_server.send_request(
75
80
  McpRequest(
@@ -78,10 +83,10 @@ class AutoCommandTools:
78
83
  product_mode=self.args.product_mode
79
84
  )
80
85
  )
81
-
86
+
82
87
  result = response.result
83
-
84
- self.result_manager.append(content=result, meta = {
88
+
89
+ self.result_manager.append(content=result, meta={
85
90
  "action": "execute_mcp_server",
86
91
  "input": {
87
92
  "query": query
@@ -89,8 +94,7 @@ class AutoCommandTools:
89
94
  })
90
95
  return result
91
96
 
92
-
93
- def ask_user(self,question:str) -> str:
97
+ def ask_user(self, question: str) -> str:
94
98
  '''
95
99
  如果你对用户的问题有什么疑问,或者你想从用户收集一些额外信息,可以调用此方法。
96
100
  输入参数 question 是你对用户的提问。
@@ -101,7 +105,7 @@ class AutoCommandTools:
101
105
 
102
106
  if self.args.request_id and not self.args.silence and not self.args.skip_events:
103
107
  event_data = {
104
- "question": question
108
+ "question": question
105
109
  }
106
110
  response_json = queue_communicate.send_event(
107
111
  request_id=self.args.request_id,
@@ -112,6 +116,18 @@ class AutoCommandTools:
112
116
  )
113
117
  return response_json
114
118
 
119
+ # 如果是在web模式下,则使用event_manager事件来询问用户
120
+ if get_run_context().is_web():
121
+ answer = get_event_manager(
122
+ self.args.event_file).ask_user(prompt=question)
123
+ self.result_manager.append(content=answer, meta={
124
+ "action": "ask_user",
125
+ "input": {
126
+ "question": question
127
+ }
128
+ })
129
+ return answer
130
+
115
131
  console = Console()
116
132
 
117
133
  # 创建一个醒目的问题面板
@@ -124,15 +140,16 @@ class AutoCommandTools:
124
140
  )
125
141
 
126
142
  # 显示问题面板
127
- console.print(question_panel)
143
+ console.print(question_panel)
128
144
 
129
- session = PromptSession( message=self.printer.get_message_from_key('tool_ask_user'))
145
+ session = PromptSession(
146
+ message=self.printer.get_message_from_key('tool_ask_user'))
130
147
  try:
131
148
  answer = session.prompt()
132
149
  except KeyboardInterrupt:
133
- answer = ""
150
+ answer = ""
134
151
 
135
- self.result_manager.append(content=answer, meta = {
152
+ self.result_manager.append(content=answer, meta={
136
153
  "action": "ask_user",
137
154
  "input": {
138
155
  "question": question
@@ -140,8 +157,27 @@ class AutoCommandTools:
140
157
  })
141
158
 
142
159
  return answer
143
-
160
+
144
161
  def response_user(self, response: str):
162
+
163
+ # 如果是在web模式下,则使用event_manager事件来询问用户
164
+ if get_run_context().is_web():
165
+ answer = get_event_manager(
166
+ self.args.event_file).write_result(
167
+ EventContentCreator.create_result(
168
+ EventContentCreator.ResultSummaryContent(
169
+ summary=response
170
+ )
171
+ )
172
+ )
173
+ self.result_manager.append(content=response, meta={
174
+ "action": "response_user",
175
+ "input": {
176
+ "response": response
177
+ }
178
+ })
179
+ return answer
180
+
145
181
  console = Console()
146
182
  answer_text = Text(response, style="italic")
147
183
  answer_panel = Panel(
@@ -152,7 +188,7 @@ class AutoCommandTools:
152
188
  )
153
189
  console.print(answer_panel)
154
190
 
155
- self.result_manager.append(content=response, meta = {
191
+ self.result_manager.append(content=response, meta={
156
192
  "action": "response_user",
157
193
  "input": {
158
194
  "response": response
@@ -160,7 +196,6 @@ class AutoCommandTools:
160
196
  })
161
197
 
162
198
  return response
163
-
164
199
 
165
200
  def run_python_code(self, code: str) -> str:
166
201
  """
@@ -178,8 +213,8 @@ class AutoCommandTools:
178
213
  )
179
214
  finally:
180
215
  interpreter.close()
181
-
182
- self.result_manager.append(content=s, meta = {
216
+
217
+ self.result_manager.append(content=s, meta={
183
218
  "action": "run_python_code",
184
219
  "input": {
185
220
  "code": code
@@ -206,8 +241,8 @@ class AutoCommandTools:
206
241
  )
207
242
  finally:
208
243
  interpreter.close()
209
-
210
- self.result_manager.append(content=s, meta = {
244
+
245
+ self.result_manager.append(content=s, meta={
211
246
  "action": "run_shell_code",
212
247
  "input": {
213
248
  "script": script
@@ -215,13 +250,13 @@ class AutoCommandTools:
215
250
  })
216
251
 
217
252
  return s
218
-
253
+
219
254
  def get_related_files_by_symbols(self, query: str) -> str:
220
255
  """
221
256
  你可以给出类名,函数名,以及文件的用途描述等信息,该工具会根据这些信息返回项目中相关的文件。
222
257
  """
223
258
  v = self.get_project_related_files(query)
224
- self.result_manager.append(content=v, meta = {
259
+ self.result_manager.append(content=v, meta={
225
260
  "action": "get_related_files_by_symbols",
226
261
  "input": {
227
262
  "query": query
@@ -245,18 +280,18 @@ class AutoCommandTools:
245
280
  pp.run()
246
281
  sources = pp.sources
247
282
 
248
- index_manager = IndexManager(llm=self.llm, sources=sources, args=self.args)
283
+ index_manager = IndexManager(
284
+ llm=self.llm, sources=sources, args=self.args)
249
285
  target_files = index_manager.get_target_files_by_query(query)
250
286
  file_list = target_files.file_list
251
- v = ",".join([file.file_path for file in file_list])
252
- self.result_manager.append(content=v, meta = {
287
+ v = ",".join([file.file_path for file in file_list])
288
+ self.result_manager.append(content=v, meta={
253
289
  "action": "get_project_related_files",
254
290
  "input": {
255
291
  "query": query
256
292
  }
257
293
  })
258
294
  return v
259
-
260
295
 
261
296
  def _get_sources(self):
262
297
  if self.args.project_type == "ts":
@@ -268,11 +303,12 @@ class AutoCommandTools:
268
303
  pp.run()
269
304
  return pp.sources
270
305
 
271
- def _get_index(self):
306
+ def _get_index(self):
272
307
  sources = self._get_sources()
273
- index_manager = IndexManager(llm=self.llm, sources=sources, args=self.args)
308
+ index_manager = IndexManager(
309
+ llm=self.llm, sources=sources, args=self.args)
274
310
  return index_manager
275
-
311
+
276
312
  def get_project_map(self, file_paths: Optional[str] = None) -> str:
277
313
  """
278
314
  该工具会返回项目中所有已经被构建索引的文件以及该文件的信息,诸如该文件的用途,导入的包,定义的类,函数,变量等信息。
@@ -284,18 +320,18 @@ class AutoCommandTools:
284
320
 
285
321
  注意,这个工具无法返回所有文件的信息,因为有些文件可能没有被索引。
286
322
  尽量避免使用该工具。
287
- """
323
+ """
288
324
  index_manager = self._get_index()
289
325
  s = index_manager.read_index_as_str()
290
326
  index_data = json.loads(s)
291
327
 
292
328
  final_result = []
293
-
329
+
294
330
  # 解析文件路径列表(如果提供了)
295
331
  file_path_list = []
296
332
  if file_paths:
297
333
  file_path_list = [path.strip() for path in file_paths.split(",")]
298
-
334
+
299
335
  for k in index_data.values():
300
336
  value = {}
301
337
  value["file_name"] = k["module_name"]
@@ -304,19 +340,19 @@ class AutoCommandTools:
304
340
  value["index_tokens"] = k.get("generated_tokens_count", -1)
305
341
  value["file_tokens_cost"] = k.get("input_tokens_cost", -1)
306
342
  value["index_tokens_cost"] = k.get("generated_tokens_cost", -1)
307
-
343
+
308
344
  # 如果提供了文件路径列表,检查当前文件是否匹配任何一个路径
309
345
  if file_path_list:
310
346
  if any(path in k["module_name"] for path in file_path_list):
311
347
  final_result.append(value)
312
348
  else:
313
349
  final_result.append(value)
314
-
350
+
315
351
  v = json.dumps(final_result, ensure_ascii=False)
316
352
  tokens = count_tokens(v)
317
353
  if tokens > self.args.conversation_prune_safe_zone_tokens/2.0:
318
354
  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 = {
355
+ self.result_manager.add_result(content=result, meta={
320
356
  "action": "get_project_map",
321
357
  "input": {
322
358
  "file_paths": file_paths
@@ -324,15 +360,15 @@ class AutoCommandTools:
324
360
  })
325
361
  return result
326
362
 
327
- self.result_manager.add_result(content=v, meta = {
363
+ self.result_manager.add_result(content=v, meta={
328
364
  "action": "get_project_map",
329
365
  "input": {
330
366
  "file_paths": file_paths
331
367
  }
332
368
  })
333
369
  return v
334
-
335
- def read_file_with_keyword_ranges(self, file_path: str, keyword:str, before_size:int = 100, after_size:int = 100) -> str:
370
+
371
+ def read_file_with_keyword_ranges(self, file_path: str, keyword: str, before_size: int = 100, after_size: int = 100) -> str:
336
372
  """
337
373
  该函数用于读取包含了关键字(keyword)的行,以及该行前后指定大小的行。
338
374
  输入参数:
@@ -340,7 +376,7 @@ class AutoCommandTools:
340
376
  - keyword: 关键字
341
377
  - before_size: 关键字所在行之前的行数
342
378
  - after_size: 关键字所在行之后的行数
343
-
379
+
344
380
  返回值:
345
381
  - 返回str类型,返回包含关键字的行,以及该行前后指定大小的行。
346
382
 
@@ -348,7 +384,7 @@ class AutoCommandTools:
348
384
  ```
349
385
  ##File: /path/to/file.py
350
386
  ##Line: 10-20
351
-
387
+
352
388
  内容
353
389
  ```
354
390
  """
@@ -363,34 +399,34 @@ class AutoCommandTools:
363
399
 
364
400
  result = []
365
401
  try:
366
-
367
- lines = files_utils.read_lines(absolute_path)
402
+
403
+ lines = files_utils.read_lines(absolute_path)
368
404
  # Find all lines containing the keyword
369
405
  keyword_lines = []
370
406
  for i, line in enumerate(lines):
371
407
  if keyword.lower() in line.lower():
372
408
  keyword_lines.append(i)
373
-
409
+
374
410
  # Process each keyword line and its surrounding range
375
411
  processed_ranges = set()
376
412
  for line_num in keyword_lines:
377
413
  # Calculate range boundaries
378
414
  start = max(0, line_num - before_size)
379
415
  end = min(len(lines), line_num + after_size + 1)
380
-
416
+
381
417
  # Check if this range overlaps with any previously processed range
382
418
  range_key = (start, end)
383
419
  if range_key in processed_ranges:
384
420
  continue
385
-
421
+
386
422
  processed_ranges.add(range_key)
387
-
423
+
388
424
  # Format the content block
389
425
  content = f"##File: {absolute_path}\n"
390
426
  content += f"##Line: {start+1}-{end}\n\n"
391
427
  content += "".join(lines[start:end])
392
428
  result.append(content)
393
-
429
+
394
430
  except Exception as e:
395
431
  v = f"Error reading file {absolute_path}: {str(e)}"
396
432
  self.result_manager.add_result(content=v, meta={
@@ -403,7 +439,7 @@ class AutoCommandTools:
403
439
  }
404
440
  })
405
441
  return v
406
-
442
+
407
443
  final_result = "\n\n".join(result)
408
444
  self.result_manager.add_result(content=final_result, meta={
409
445
  "action": "read_file_with_keyword_ranges",
@@ -414,7 +450,7 @@ class AutoCommandTools:
414
450
  "after_size": after_size
415
451
  }
416
452
  })
417
-
453
+
418
454
  return final_result
419
455
 
420
456
  def read_files(self, paths: str, line_ranges: Optional[str] = None) -> str:
@@ -447,21 +483,22 @@ class AutoCommandTools:
447
483
  """
448
484
  paths = [p.strip() for p in paths.split(",")]
449
485
  source_code_str = ""
450
-
486
+
451
487
  # Parse line ranges if provided
452
488
  file_line_ranges = {}
453
489
  if line_ranges:
454
490
  ranges_per_file = line_ranges.split(",")
455
491
  if len(ranges_per_file) != len(paths):
456
- self.result_manager.add_result(content="Number of line ranges must match number of files", meta = {
492
+ self.result_manager.add_result(content="Number of line ranges must match number of files", meta={
457
493
  "action": "read_files",
458
494
  "input": {
459
495
  "paths": paths,
460
496
  "line_ranges": line_ranges
461
497
  }
462
498
  })
463
- raise ValueError("Number of line ranges must match number of files")
464
-
499
+ raise ValueError(
500
+ "Number of line ranges must match number of files")
501
+
465
502
  for path, ranges in zip(paths, ranges_per_file):
466
503
  file_line_ranges[path] = []
467
504
  for range_str in ranges.split("/"):
@@ -479,7 +516,7 @@ class AutoCommandTools:
479
516
  if path in os.path.join(root, file):
480
517
  absolute_path = os.path.join(root, file)
481
518
  break
482
-
519
+
483
520
  if path in file_line_ranges:
484
521
  # Read specific line ranges
485
522
  lines = files_utils.read_lines(absolute_path)
@@ -489,7 +526,8 @@ class AutoCommandTools:
489
526
  start = max(0, start - 1)
490
527
  end = min(len(lines), end)
491
528
  content = "".join(lines[start:end])
492
- filtered_lines.extend(f"##File: {absolute_path}\n##Line: {start}-{end}\n\n{content}")
529
+ filtered_lines.extend(
530
+ f"##File: {absolute_path}\n##Line: {start}-{end}\n\n{content}")
493
531
  source_code = "".join(filtered_lines)
494
532
  # Add source_code to source_code_str
495
533
  source_code_str += source_code
@@ -497,11 +535,12 @@ class AutoCommandTools:
497
535
  # Read entire file if no range specified
498
536
  content = files_utils.read_file(absolute_path)
499
537
  source_code = f"##File: {absolute_path}\n\n{content}"
500
-
501
- sc = SourceCode(module_name=absolute_path, source_code=source_code)
538
+
539
+ sc = SourceCode(module_name=absolute_path,
540
+ source_code=source_code)
502
541
  source_code_str += f"{sc.source_code}\n\n"
503
-
504
- self.result_manager.add_result(content=source_code_str, meta = {
542
+
543
+ self.result_manager.add_result(content=source_code_str, meta={
505
544
  "action": "read_files",
506
545
  "input": {
507
546
  "paths": paths,
@@ -519,24 +558,24 @@ class AutoCommandTools:
519
558
  index_manager = self._get_index()
520
559
  result = []
521
560
  index_items = index_manager.read_index()
522
-
561
+
523
562
  for item in index_items:
524
563
  symbols = extract_symbols(item.symbols)
525
564
  for symbol_info in symbols:
526
565
  # 进行精确匹配和模糊匹配
527
- if (symbol_info.name == symbol or
528
- symbol.lower() in symbol_info.name.lower()):
566
+ if (symbol_info.name == symbol or
567
+ symbol.lower() in symbol_info.name.lower()):
529
568
  # 检查是否已经添加过该文件路径
530
569
  if symbol_info.module_name not in result:
531
570
  result.append(symbol_info.module_name)
532
-
571
+
533
572
  # 生成以逗号分隔的文件路径列表
534
573
  file_paths = ",".join(result)
535
-
574
+
536
575
  # 如果没有找到任何匹配项,返回提示信息
537
576
  if not file_paths:
538
577
  file_paths = f"未找到符号 '{symbol}' 的定义"
539
-
578
+
540
579
  # 记录操作结果
541
580
  self.result_manager.add_result(content=file_paths, meta={
542
581
  "action": "find_symbols_definition",
@@ -544,7 +583,7 @@ class AutoCommandTools:
544
583
  "symbol": symbol
545
584
  }
546
585
  })
547
-
586
+
548
587
  return file_paths
549
588
 
550
589
  def list_files(self, path: str) -> str:
@@ -558,7 +597,7 @@ class AutoCommandTools:
558
597
  if not os.path.isabs(path):
559
598
  # 如果是相对路径,将其转换为绝对路径
560
599
  target_path = os.path.join(self.args.source_dir, path)
561
-
600
+
562
601
  # 确保路径存在且是目录
563
602
  if not os.path.exists(target_path):
564
603
  result = f"目录不存在: {target_path}"
@@ -569,7 +608,7 @@ class AutoCommandTools:
569
608
  }
570
609
  })
571
610
  return result
572
-
611
+
573
612
  if not os.path.isdir(target_path):
574
613
  result = f"指定路径不是目录: {target_path}"
575
614
  self.result_manager.add_result(content=result, meta={
@@ -579,7 +618,7 @@ class AutoCommandTools:
579
618
  }
580
619
  })
581
620
  return result
582
-
621
+
583
622
  # 只收集当前目录下的文件,不递归子目录
584
623
  file_list = []
585
624
  for item in os.listdir(target_path):
@@ -587,10 +626,10 @@ class AutoCommandTools:
587
626
  # 只添加文件,不添加目录
588
627
  if os.path.isfile(item_path):
589
628
  file_list.append(item_path)
590
-
629
+
591
630
  # 生成以逗号分隔的文件列表
592
631
  result = ",".join(file_list)
593
-
632
+
594
633
  # 记录结果
595
634
  self.result_manager.add_result(content=result, meta={
596
635
  "action": "list_files",
@@ -598,10 +637,10 @@ class AutoCommandTools:
598
637
  "path": path
599
638
  }
600
639
  })
601
-
640
+
602
641
  return result
603
642
 
604
- def get_project_structure(self) -> str:
643
+ def get_project_structure(self) -> str:
605
644
  if self.args.project_type == "ts":
606
645
  pp = TSProject(args=self.args, llm=self.llm)
607
646
  elif self.args.project_type == "py":
@@ -610,25 +649,24 @@ class AutoCommandTools:
610
649
  pp = SuffixProject(args=self.args, llm=self.llm, file_filter=None)
611
650
  pp.run()
612
651
  s = pp.get_tree_like_directory_structure()
613
-
652
+
614
653
  tokens = count_tokens(s)
615
654
  if tokens > self.args.conversation_prune_safe_zone_tokens / 2.0:
616
655
  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 = {
656
+ self.result_manager.add_result(content=result, meta={
618
657
  "action": "get_project_structure",
619
658
  "input": {
620
659
  }
621
660
  })
622
661
  return result
623
662
 
624
- self.result_manager.add_result(content=s, meta = {
663
+ self.result_manager.add_result(content=s, meta={
625
664
  "action": "get_project_structure",
626
665
  "input": {
627
666
  }
628
667
  })
629
668
  return s
630
669
 
631
-
632
670
  def find_files_by_name(self, keyword: str) -> str:
633
671
  """
634
672
  根据关键字在项目中搜索文件名。
@@ -645,14 +683,14 @@ class AutoCommandTools:
645
683
  matched_files.append(os.path.join(root, file))
646
684
 
647
685
  v = ",".join(matched_files)
648
- self.result_manager.add_result(content=v, meta = {
686
+ self.result_manager.add_result(content=v, meta={
649
687
  "action": "find_files_by_name",
650
688
  "input": {
651
689
  "keyword": keyword
652
690
  }
653
691
  })
654
692
  return v
655
-
693
+
656
694
  def count_file_tokens(self, file_path: str) -> int:
657
695
  """
658
696
  该工具用于计算指定文件的token数量。
@@ -691,18 +729,18 @@ class AutoCommandTools:
691
729
  excluded_file_patterns = [
692
730
  '*.pyc', '*.pyo', '*.pyd', '*.egg-info', '*.log'
693
731
  ]
694
-
732
+
695
733
  matched_files = []
696
-
734
+
697
735
  for root, dirs, files in os.walk(self.args.source_dir):
698
736
  # 移除需要排除的目录
699
737
  dirs[:] = [d for d in dirs if d not in excluded_dirs]
700
-
738
+
701
739
  # 过滤掉需要排除的文件
702
740
  files[:] = [f for f in files if not any(
703
741
  f.endswith(pattern[1:]) for pattern in excluded_file_patterns
704
742
  )]
705
-
743
+
706
744
  for file in files:
707
745
  file_path = os.path.join(root, file)
708
746
  try:
@@ -719,10 +757,10 @@ class AutoCommandTools:
719
757
  break
720
758
 
721
759
  v = ",".join(matched_files[:10])
722
- self.result_manager.add_result(content=v, meta = {
760
+ self.result_manager.add_result(content=v, meta={
723
761
  "action": "find_files_by_content",
724
762
  "input": {
725
763
  "keyword": keyword
726
764
  }
727
765
  })
728
- return v
766
+ return v
@@ -410,6 +410,8 @@ class AutoCoderArgs(pydantic.BaseModel):
410
410
 
411
411
  enable_task_history: Optional[bool] = False
412
412
 
413
+ event_file: Optional[str] = None
414
+
413
415
  class Config:
414
416
  protected_namespaces = ()
415
417
 
@@ -278,6 +278,28 @@ class ActionYmlFileManager:
278
278
  except Exception:
279
279
  return None
280
280
 
281
+ def get_file_name_from_commit_msg(self, commit_msg: str) -> Optional[str]:
282
+ """
283
+ 从 commit 消息中提取文件名,获取消息最后一行,然后调用 get_file_name_from_commit_id
284
+
285
+ Args:
286
+ commit_msg: commit 消息内容
287
+
288
+ Returns:
289
+ Optional[str]: 文件名,如果提取失败返回 None
290
+ """
291
+ if not commit_msg:
292
+ return None
293
+
294
+ try:
295
+ # 获取消息的最后一行
296
+ last_line = commit_msg.strip().split('\n')[-1]
297
+ # 调用 get_file_name_from_commit_id 从最后一行提取文件名
298
+ return self.get_file_name_from_commit_id(last_line)
299
+ except Exception as e:
300
+ logger.error(f"Failed to extract file name from commit message: {e}")
301
+ return None
302
+
281
303
  def get_commit_changes(self, file_name: Optional[str] = None) -> List[Tuple[str, List[str], Dict[str, Tuple[str, str]]]]:
282
304
  """
283
305
  获取与特定文件相关的 commit 变更
@@ -156,13 +156,18 @@ def config_readme() -> str:
156
156
  2. py
157
157
  3. 代码文件后缀名列表(比如.java,.py,.go,.js,.ts),多个按逗号分割
158
158
 
159
- 推荐使用 3 选项,因为项目类型通常为多种后缀名混合。
160
-
161
- ## include_project_structure: 是否包含项目结构
162
- 是否包含项目结构。推荐设置为 true。默认为true,但是项目结构也可能很大,如果项目结构很大,那么可以设置为 false。
159
+ 推荐使用 3 选项,因为项目类型通常为多种后缀名混合。
163
160
 
164
161
  ## conversation_prune_safe_zone_tokens: 对话剪枝安全区token数量
165
162
  在对话剪枝时,会根据对话的token数量,如果token数量超过该值,那么会剪枝掉一部分对话。
163
+
164
+ ## enable_task_history
165
+ 该参数对 /auto 指令有效, 当你使用 /auto 指令的时候,系统会自动将近期对项目的变更(commit) 信息给到大模型,方便大模型对用户的需求有更好的理解。
166
+ 默认为 false
167
+
168
+ ## include_project_structure
169
+ 使用 /chat , /coding 等指令时,是否将项目的目录结构也放到上下文中。
170
+ 默认为true, 如果你项目很大,请设置为 false
166
171
  """
167
172
 
168
173
  class ConfigAutoTuner:
@@ -0,0 +1,7 @@
1
+ from enum import Enum
2
+
3
+ class AutoCommandStreamOutType(Enum):
4
+ COMMAND_SUGGESTION = "command_suggestion"
5
+
6
+ class IndexFilterStreamOutType(Enum):
7
+ FILE_NUMBER_LIST = "file_number_list"