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

@@ -26,16 +26,12 @@ from autocoder.version import __version__
26
26
  from autocoder.auto_coder import main as auto_coder_main
27
27
  from autocoder.common.command_completer import CommandTextParser
28
28
  from autocoder.utils import get_last_yaml_file
29
- import pathlib
30
29
  from autocoder.index.symbols_utils import (
31
30
  extract_symbols,
32
- symbols_info_to_str,
33
- SymbolsInfo,
34
31
  SymbolType,
35
32
  )
36
33
  import platform
37
34
  import subprocess
38
- import shlex
39
35
  from rich.console import Console
40
36
  from rich.panel import Panel
41
37
  from rich.table import Table
@@ -43,25 +39,13 @@ from rich.live import Live
43
39
  from rich.text import Text
44
40
  from rich.live import Live
45
41
  from byzerllm.utils.nontext import Image
46
- import re
47
42
  import git
48
43
  from autocoder.common import git_utils
49
- from autocoder.utils.request_queue import (
50
- request_queue,
51
- RequestValue,
52
- DefaultValue,
53
- RequestOption,
54
- )
55
- import asyncio
56
- from byzerllm.utils.langutil import asyncfy_with_semaphore
57
- from prompt_toolkit.patch_stdout import patch_stdout
58
- import byzerllm
59
- from byzerllm.utils import format_str_jinja2
60
44
  from autocoder.chat_auto_coder_lang import get_message
61
45
  from autocoder.utils import operate_config_api
62
46
  from autocoder.agent.auto_guess_query import AutoGuessQuery
63
- from autocoder.common.mcp_server import get_mcp_server, McpRequest
64
- import asyncio
47
+ from autocoder.common.mcp_server import get_mcp_server, McpRequest, McpInstallRequest, McpRemoveRequest, McpListRequest, McpListRunningRequest
48
+ import byzerllm
65
49
 
66
50
  class SymbolItem(BaseModel):
67
51
  symbol_name: str
@@ -73,7 +57,8 @@ def parse_arguments():
73
57
  import argparse
74
58
 
75
59
  parser = argparse.ArgumentParser(description="Chat Auto Coder")
76
- parser.add_argument("--debug", action="store_true", help="Enable debug mode")
60
+ parser.add_argument("--debug", action="store_true",
61
+ help="Enable debug mode")
77
62
  parser.add_argument(
78
63
  "--quick",
79
64
  action="store_true",
@@ -156,8 +141,10 @@ def show_help():
156
141
  print(
157
142
  f" \033[94m/summon\033[0m \033[93m<query>\033[0m - \033[92m{get_message('summon_desc')}\033[0m"
158
143
  )
159
- print(f" \033[94m/revert\033[0m - \033[92m{get_message('revert_desc')}\033[0m")
160
- print(f" \033[94m/commit\033[0m - \033[92m{get_message('commit_desc')}\033[0m")
144
+ print(
145
+ f" \033[94m/revert\033[0m - \033[92m{get_message('revert_desc')}\033[0m")
146
+ print(
147
+ f" \033[94m/commit\033[0m - \033[92m{get_message('commit_desc')}\033[0m")
161
148
  print(
162
149
  f" \033[94m/conf\033[0m \033[93m<key>:<value>\033[0m - \033[92m{get_message('conf_desc')}\033[0m"
163
150
  )
@@ -170,7 +157,8 @@ def show_help():
170
157
  print(
171
158
  f" \033[94m/list_files\033[0m - \033[92m{get_message('list_files_desc')}\033[0m"
172
159
  )
173
- print(f" \033[94m/help\033[0m - \033[92m{get_message('help_desc')}\033[0m")
160
+ print(
161
+ f" \033[94m/help\033[0m - \033[92m{get_message('help_desc')}\033[0m")
174
162
  print(
175
163
  f" \033[94m/exclude_dirs\033[0m \033[93m<dir1>,<dir2> ...\033[0m - \033[92m{get_message('exclude_dirs_desc')}\033[0m"
176
164
  )
@@ -180,9 +168,11 @@ def show_help():
180
168
  print(
181
169
  f" \033[94m/voice_input\033[0m - \033[92m{get_message('voice_input_desc')}\033[0m"
182
170
  )
183
- print(f" \033[94m/mode\033[0m - \033[92m{get_message('mode_desc')}\033[0m")
171
+ print(
172
+ f" \033[94m/mode\033[0m - \033[92m{get_message('mode_desc')}\033[0m")
184
173
  print(f" \033[94m/lib\033[0m - \033[92m{get_message('lib_desc')}\033[0m")
185
- print(f" \033[94m/exit\033[0m - \033[92m{get_message('exit_desc')}\033[0m")
174
+ print(
175
+ f" \033[94m/exit\033[0m - \033[92m{get_message('exit_desc')}\033[0m")
186
176
  print()
187
177
 
188
178
 
@@ -207,10 +197,12 @@ def configure_project_type():
207
197
  print_formatted_text(HTML(f"<info>{escape(text)}</info>"), style=style)
208
198
 
209
199
  def print_warning(text):
210
- print_formatted_text(HTML(f"<warning>{escape(text)}</warning>"), style=style)
200
+ print_formatted_text(
201
+ HTML(f"<warning>{escape(text)}</warning>"), style=style)
211
202
 
212
203
  def print_header(text):
213
- print_formatted_text(HTML(f"<header>{escape(text)}</header>"), style=style)
204
+ print_formatted_text(
205
+ HTML(f"<header>{escape(text)}</header>"), style=style)
214
206
 
215
207
  print_header(f"\n=== {get_message('project_type_config')} ===\n")
216
208
  print_info(get_message("project_type_supports"))
@@ -256,7 +248,8 @@ def initialize_system():
256
248
  if not os.path.exists(".auto-coder"):
257
249
  first_time = True
258
250
  print_status(get_message("not_initialized"), "warning")
259
- init_choice = input(f" {get_message('init_prompt')}").strip().lower()
251
+ init_choice = input(
252
+ f" {get_message('init_prompt')}").strip().lower()
260
253
  if init_choice == "y":
261
254
  try:
262
255
  subprocess.run(
@@ -273,7 +266,8 @@ def initialize_system():
273
266
 
274
267
  if not os.path.exists(base_persist_dir):
275
268
  os.makedirs(base_persist_dir, exist_ok=True)
276
- print_status(get_message("created_dir").format(base_persist_dir), "success")
269
+ print_status(get_message("created_dir").format(
270
+ base_persist_dir), "success")
277
271
 
278
272
  if first_time:
279
273
  configure_project_type()
@@ -283,7 +277,8 @@ def initialize_system():
283
277
  init_project()
284
278
  # Check if Ray is running
285
279
  print_status(get_message("checking_ray"), "")
286
- ray_status = subprocess.run(["ray", "status"], capture_output=True, text=True)
280
+ ray_status = subprocess.run(
281
+ ["ray", "status"], capture_output=True, text=True)
287
282
  if ray_status.returncode != 0:
288
283
  print_status(get_message("ray_not_running"), "warning")
289
284
  try:
@@ -315,9 +310,9 @@ def initialize_system():
315
310
  print_status(get_message("model_error"), "error")
316
311
 
317
312
  # If deepseek_chat is not available
318
- print_status(get_message("model_not_available"), "warning")
313
+ print_status(get_message("model_not_available"), "warning")
319
314
  api_key = prompt(HTML(f"<b>{get_message('enter_api_key')} </b>"))
320
-
315
+
321
316
  print_status(get_message("deploying_model").format("Deepseek官方"), "")
322
317
  deploy_cmd = [
323
318
  "byzerllm",
@@ -401,7 +396,8 @@ def get_all_file_in_project_with_dot() -> List[str]:
401
396
  for root, dirs, files in os.walk(project_root, followlinks=True):
402
397
  dirs[:] = [d for d in dirs if d not in final_exclude_dirs]
403
398
  for file in files:
404
- file_names.append(os.path.join(root, file).replace(project_root, "."))
399
+ file_names.append(os.path.join(
400
+ root, file).replace(project_root, "."))
405
401
  return file_names
406
402
 
407
403
 
@@ -529,8 +525,10 @@ def show_help():
529
525
  print(
530
526
  f" \033[94m/summon\033[0m \033[93m<query>\033[0m - \033[92m{get_message('summon_desc')}\033[0m"
531
527
  )
532
- print(f" \033[94m/revert\033[0m - \033[92m{get_message('revert_desc')}\033[0m")
533
- print(f" \033[94m/commit\033[0m - \033[92m{get_message('commit_desc')}\033[0m")
528
+ print(
529
+ f" \033[94m/revert\033[0m - \033[92m{get_message('revert_desc')}\033[0m")
530
+ print(
531
+ f" \033[94m/commit\033[0m - \033[92m{get_message('commit_desc')}\033[0m")
534
532
  print(
535
533
  f" \033[94m/conf\033[0m \033[93m<key>:<value>\033[0m - \033[92m{get_message('conf_desc')}\033[0m"
536
534
  )
@@ -543,7 +541,8 @@ def show_help():
543
541
  print(
544
542
  f" \033[94m/list_files\033[0m - \033[92m{get_message('list_files_desc')}\033[0m"
545
543
  )
546
- print(f" \033[94m/help\033[0m - \033[92m{get_message('help_desc')}\033[0m")
544
+ print(
545
+ f" \033[94m/help\033[0m - \033[92m{get_message('help_desc')}\033[0m")
547
546
  print(
548
547
  f" \033[94m/exclude_dirs\033[0m \033[93m<dir1>,<dir2> ...\033[0m - \033[92m{get_message('exclude_dirs_desc')}\033[0m"
549
548
  )
@@ -553,9 +552,11 @@ def show_help():
553
552
  print(
554
553
  f" \033[94m/voice_input\033[0m - \033[92m{get_message('voice_input_desc')}\033[0m"
555
554
  )
556
- print(f" \033[94m/mode\033[0m - \033[92m{get_message('mode_desc')}\033[0m")
555
+ print(
556
+ f" \033[94m/mode\033[0m - \033[92m{get_message('mode_desc')}\033[0m")
557
557
  print(f" \033[94m/lib\033[0m - \033[92m{get_message('lib_desc')}\033[0m")
558
- print(f" \033[94m/exit\033[0m - \033[92m{get_message('exit_desc')}\033[0m")
558
+ print(
559
+ f" \033[94m/exit\033[0m - \033[92m{get_message('exit_desc')}\033[0m")
559
560
  print()
560
561
 
561
562
 
@@ -619,13 +620,13 @@ class CommandCompleter(Completer):
619
620
 
620
621
  if len(words) > 0:
621
622
  if words[0] == "/mode":
622
- left_word = text[len("/mode") :]
623
+ left_word = text[len("/mode"):]
623
624
  for mode in ["normal", "auto_detect", "voice_input"]:
624
625
  if mode.startswith(left_word.strip()):
625
626
  yield Completion(mode, start_position=-len(left_word.strip()))
626
627
 
627
628
  if words[0] == "/add_files":
628
- new_text = text[len("/add_files") :]
629
+ new_text = text[len("/add_files"):]
629
630
  parser = CommandTextParser(new_text, words[0])
630
631
  parser.add_files()
631
632
  current_word = parser.current_word()
@@ -656,18 +657,21 @@ class CommandCompleter(Completer):
656
657
  for file_name in self.all_files_with_dot:
657
658
  if file_name.startswith(current_word):
658
659
  yield Completion(
659
- file_name, start_position=-len(current_word)
660
+ file_name, start_position=-
661
+ len(current_word)
660
662
  )
661
663
  else:
662
664
  for file_name in self.all_file_names:
663
665
  if file_name.startswith(current_word):
664
666
  yield Completion(
665
- file_name, start_position=-len(current_word)
667
+ file_name, start_position=-
668
+ len(current_word)
666
669
  )
667
670
  for file_name in self.all_files:
668
671
  if current_word and current_word in file_name:
669
672
  yield Completion(
670
- file_name, start_position=-len(current_word)
673
+ file_name, start_position=-
674
+ len(current_word)
671
675
  )
672
676
  elif words[0] in ["/chat", "/coding"]:
673
677
  image_extensions = (
@@ -697,7 +701,7 @@ class CommandCompleter(Completer):
697
701
  ".psd",
698
702
  ".xcf",
699
703
  )
700
- new_text = text[len(words[0]) :]
704
+ new_text = text[len(words[0]):]
701
705
  parser = CommandTextParser(new_text, words[0])
702
706
 
703
707
  parser.coding()
@@ -724,7 +728,8 @@ class CommandCompleter(Completer):
724
728
  if len(path_parts) > 3
725
729
  else file_name
726
730
  )
727
- relative_path = os.path.relpath(file_name, project_root)
731
+ relative_path = os.path.relpath(
732
+ file_name, project_root)
728
733
  yield Completion(
729
734
  relative_path,
730
735
  start_position=-len(name),
@@ -741,7 +746,8 @@ class CommandCompleter(Completer):
741
746
  if len(path_parts) > 3
742
747
  else file_name
743
748
  )
744
- relative_path = os.path.relpath(file_name, project_root)
749
+ relative_path = os.path.relpath(
750
+ file_name, project_root)
745
751
 
746
752
  yield Completion(
747
753
  relative_path,
@@ -757,7 +763,8 @@ class CommandCompleter(Completer):
757
763
  if len(path_parts) > 3
758
764
  else file_name
759
765
  )
760
- relative_path = os.path.relpath(file_name, project_root)
766
+ relative_path = os.path.relpath(
767
+ file_name, project_root)
761
768
  yield Completion(
762
769
  relative_path,
763
770
  start_position=-len(name),
@@ -775,7 +782,8 @@ class CommandCompleter(Completer):
775
782
  if len(path_parts) > 3
776
783
  else symbol.symbol_name
777
784
  )
778
- relative_path = os.path.relpath(file_name, project_root)
785
+ relative_path = os.path.relpath(
786
+ file_name, project_root)
779
787
  yield Completion(
780
788
  f"{symbol.symbol_name}(location: {relative_path})",
781
789
  start_position=-len(name),
@@ -810,7 +818,8 @@ class CommandCompleter(Completer):
810
818
  for dir in dirs:
811
819
  full_path = os.path.join(root, dir)
812
820
  if full_path.startswith(file_name):
813
- relative_path = os.path.relpath(full_path, search_dir)
821
+ relative_path = os.path.relpath(
822
+ full_path, search_dir)
814
823
  yield Completion(
815
824
  relative_path,
816
825
  start_position=-len(file_basename),
@@ -822,7 +831,8 @@ class CommandCompleter(Completer):
822
831
  image_extensions
823
832
  ) and file.startswith(file_basename):
824
833
  full_path = os.path.join(root, file)
825
- relative_path = os.path.relpath(full_path, search_dir)
834
+ relative_path = os.path.relpath(
835
+ full_path, search_dir)
826
836
  yield Completion(
827
837
  relative_path,
828
838
  start_position=-len(file_basename),
@@ -832,7 +842,7 @@ class CommandCompleter(Completer):
832
842
  break
833
843
 
834
844
  elif words[0] == "/remove_files":
835
- new_words = text[len("/remove_files") :].strip().split(",")
845
+ new_words = text[len("/remove_files"):].strip().split(",")
836
846
 
837
847
  is_at_space = text[-1] == " "
838
848
  last_word = new_words[-2] if len(new_words) > 1 else ""
@@ -859,7 +869,7 @@ class CommandCompleter(Completer):
859
869
  file_name, start_position=-len(current_word)
860
870
  )
861
871
  elif words[0] == "/exclude_dirs":
862
- new_words = text[len("/exclude_dirs") :].strip().split(",")
872
+ new_words = text[len("/exclude_dirs"):].strip().split(",")
863
873
  current_word = new_words[-1]
864
874
 
865
875
  for file_name in self.all_dir_names:
@@ -867,7 +877,7 @@ class CommandCompleter(Completer):
867
877
  yield Completion(file_name, start_position=-len(current_word))
868
878
 
869
879
  elif words[0] == "/lib":
870
- new_text = text[len("/lib") :]
880
+ new_text = text[len("/lib"):]
871
881
  parser = CommandTextParser(new_text, words[0])
872
882
  parser.lib()
873
883
  current_word = parser.current_word()
@@ -882,8 +892,17 @@ class CommandCompleter(Completer):
882
892
  yield Completion(
883
893
  lib_name, start_position=-len(current_word)
884
894
  )
895
+ elif words[0] == "/mcp":
896
+ new_text = text[len("/mcp"):]
897
+ parser = CommandTextParser(new_text, words[0])
898
+ parser.lib()
899
+ current_word = parser.current_word()
900
+ for command in parser.get_sub_commands():
901
+ if command.startswith(current_word):
902
+ yield Completion(command, start_position=-len(current_word))
903
+
885
904
  elif words[0] == "/coding":
886
- new_text = text[len("/coding") :]
905
+ new_text = text[len("/coding"):]
887
906
  parser = CommandTextParser(new_text, words[0])
888
907
  parser.lib()
889
908
  current_word = parser.current_word()
@@ -892,7 +911,7 @@ class CommandCompleter(Completer):
892
911
  yield Completion(command, start_position=-len(current_word))
893
912
 
894
913
  elif words[0] == "/conf":
895
- new_words = text[len("/conf") :].strip().split()
914
+ new_words = text[len("/conf"):].strip().split()
896
915
  is_at_space = text[-1] == " "
897
916
  last_word = new_words[-2] if len(new_words) > 1 else ""
898
917
  current_word = new_words[-1] if new_words else ""
@@ -911,7 +930,8 @@ class CommandCompleter(Completer):
911
930
  ]
912
931
  # /conf [curosr]
913
932
  elif not last_word and not current_word:
914
- completions = ["/drop"] if "/drop".startswith(current_word) else []
933
+ completions = [
934
+ "/drop"] if "/drop".startswith(current_word) else []
915
935
  completions += [
916
936
  field_name + ":"
917
937
  for field_name in AutoCoderArgs.model_fields.keys()
@@ -919,7 +939,8 @@ class CommandCompleter(Completer):
919
939
  ]
920
940
  # /conf p[cursor]
921
941
  elif not last_word and current_word:
922
- completions = ["/drop"] if "/drop".startswith(current_word) else []
942
+ completions = [
943
+ "/drop"] if "/drop".startswith(current_word) else []
923
944
  completions += [
924
945
  field_name + ":"
925
946
  for field_name in AutoCoderArgs.model_fields.keys()
@@ -1013,7 +1034,8 @@ def add_files(args: List[str]):
1013
1034
  completer.refresh_files()
1014
1035
  load_memory()
1015
1036
  console.print(
1016
- Panel("Refreshed file list.", title="Files Refreshed", border_style="green")
1037
+ Panel("Refreshed file list.",
1038
+ title="Files Refreshed", border_style="green")
1017
1039
  )
1018
1040
  return
1019
1041
 
@@ -1021,7 +1043,8 @@ def add_files(args: List[str]):
1021
1043
  if len(args) == 1 or (len(args) == 2 and args[1] == "list"):
1022
1044
  if not groups:
1023
1045
  console.print(
1024
- Panel("No groups defined.", title="Groups", border_style="yellow")
1046
+ Panel("No groups defined.", title="Groups",
1047
+ border_style="yellow")
1025
1048
  )
1026
1049
  else:
1027
1050
  table = Table(
@@ -1046,7 +1069,8 @@ def add_files(args: List[str]):
1046
1069
  )
1047
1070
  table.add_row(
1048
1071
  group_name,
1049
- "\n".join([os.path.relpath(f, project_root) for f in files]),
1072
+ "\n".join([os.path.relpath(f, project_root)
1073
+ for f in files]),
1050
1074
  query_prefix,
1051
1075
  is_active,
1052
1076
  end_section=(i == len(groups) - 1),
@@ -1078,7 +1102,8 @@ def add_files(args: List[str]):
1078
1102
  if group_name in groups_info:
1079
1103
  del memory["current_files"]["groups_info"][group_name]
1080
1104
  if group_name in memory["current_files"]["current_groups"]:
1081
- memory["current_files"]["current_groups"].remove(group_name)
1105
+ memory["current_files"]["current_groups"].remove(
1106
+ group_name)
1082
1107
  console.print(
1083
1108
  Panel(
1084
1109
  f"Dropped group '{group_name}'.",
@@ -1251,7 +1276,8 @@ def remove_files(file_names: List[str]):
1251
1276
  memory["current_files"]["files"] = []
1252
1277
  memory["current_files"]["current_groups"] = []
1253
1278
  console.print(
1254
- Panel("Removed all files.", title="Files Removed", border_style="green")
1279
+ Panel("Removed all files.",
1280
+ title="Files Removed", border_style="green")
1255
1281
  )
1256
1282
  else:
1257
1283
  removed_files = []
@@ -1383,6 +1409,53 @@ def convert_yaml_to_config(yaml_file: str):
1383
1409
 
1384
1410
 
1385
1411
  def mcp(query: str):
1412
+ query = query.strip()
1413
+ mcp_server = get_mcp_server()
1414
+
1415
+ # Handle remove command
1416
+ if query.startswith("/remove"):
1417
+ server_name = query.replace("/remove", "", 1).strip()
1418
+ response = mcp_server.send_request(
1419
+ McpRemoveRequest(server_name=server_name))
1420
+ if response.error:
1421
+ print(f"Error removing MCP server: {response.error}")
1422
+ else:
1423
+ print(f"Successfully removed MCP server: {response.result}")
1424
+ return
1425
+
1426
+ # Handle list command
1427
+ if query.startswith("/list_running"):
1428
+ response = mcp_server.send_request(McpListRunningRequest())
1429
+ if response.error:
1430
+ print(f"Error listing running MCP servers: {response.error}")
1431
+ else:
1432
+ print("Running MCP servers:")
1433
+ print(response.result)
1434
+ return
1435
+
1436
+ # Handle list command
1437
+ if query.startswith("/list"):
1438
+ response = mcp_server.send_request(McpListRequest())
1439
+ if response.error:
1440
+ print(f"Error listing builtin MCP servers: {response.error}")
1441
+ else:
1442
+ print("Available builtin MCP servers:")
1443
+ print(response.result)
1444
+ return
1445
+
1446
+ # Handle add command
1447
+ if query.startswith("/add"):
1448
+ query = query.replace("/add", "", 1).strip()
1449
+ request = McpInstallRequest(server_name_or_config=query)
1450
+ response = mcp_server.send_request(request)
1451
+
1452
+ if response.error:
1453
+ print(f"Error installing MCP server: {response.error}")
1454
+ else:
1455
+ print(f"Successfully installed MCP server: {response.result}")
1456
+ return
1457
+
1458
+ # Handle default query
1386
1459
  conf = memory.get("conf", {})
1387
1460
  yaml_config = {
1388
1461
  "include_file": ["./base/base.yml"],
@@ -1406,8 +1479,8 @@ def mcp(query: str):
1406
1479
  args = convert_yaml_to_config(temp_yaml)
1407
1480
  finally:
1408
1481
  if os.path.exists(temp_yaml):
1409
- os.remove(temp_yaml)
1410
-
1482
+ os.remove(temp_yaml)
1483
+
1411
1484
  mcp_server = get_mcp_server()
1412
1485
  response = mcp_server.send_request(
1413
1486
  McpRequest(
@@ -1415,7 +1488,7 @@ def mcp(query: str):
1415
1488
  model=args.inference_model or args.model
1416
1489
  )
1417
1490
  )
1418
-
1491
+
1419
1492
  if response.error:
1420
1493
  print(f"Error from MCP server: {response.error}")
1421
1494
  else:
@@ -1448,9 +1521,11 @@ def code_next(query: str):
1448
1521
  if os.path.exists(temp_yaml):
1449
1522
  os.remove(temp_yaml)
1450
1523
 
1451
- llm = byzerllm.ByzerLLM.from_default_model(args.inference_model or args.model)
1524
+ llm = byzerllm.ByzerLLM.from_default_model(
1525
+ args.inference_model or args.model)
1452
1526
 
1453
- auto_guesser = AutoGuessQuery(llm=llm, project_dir=os.getcwd(), skip_diff=True)
1527
+ auto_guesser = AutoGuessQuery(
1528
+ llm=llm, project_dir=os.getcwd(), skip_diff=True)
1454
1529
 
1455
1530
  predicted_tasks = auto_guesser.predict_next_tasks(
1456
1531
  5, is_human_as_model=args.human_as_model
@@ -1464,20 +1539,25 @@ def code_next(query: str):
1464
1539
  console = Console()
1465
1540
 
1466
1541
  # Create main panel for all predicted tasks
1467
- table = Table(show_header=True, header_style="bold magenta", show_lines=True)
1542
+ table = Table(show_header=True,
1543
+ header_style="bold magenta", show_lines=True)
1468
1544
  table.add_column("Priority", style="cyan", width=8)
1469
- table.add_column("Task Description", style="green", width=40, overflow="fold")
1545
+ table.add_column("Task Description", style="green",
1546
+ width=40, overflow="fold")
1470
1547
  table.add_column("Files", style="yellow", width=30, overflow="fold")
1471
1548
  table.add_column("Reason", style="blue", width=30, overflow="fold")
1472
- table.add_column("Dependencies", style="magenta", width=30, overflow="fold")
1549
+ table.add_column("Dependencies", style="magenta",
1550
+ width=30, overflow="fold")
1473
1551
 
1474
1552
  for task in predicted_tasks:
1475
1553
  # Format file paths to be more readable
1476
- file_list = "\n".join([os.path.relpath(f, os.getcwd()) for f in task.urls])
1554
+ file_list = "\n".join([os.path.relpath(f, os.getcwd())
1555
+ for f in task.urls])
1477
1556
 
1478
1557
  # Format dependencies to be more readable
1479
1558
  dependencies = (
1480
- "\n".join(task.dependency_queries) if task.dependency_queries else "None"
1559
+ "\n".join(
1560
+ task.dependency_queries) if task.dependency_queries else "None"
1481
1561
  )
1482
1562
 
1483
1563
  table.add_row(
@@ -1494,6 +1574,17 @@ def code_next(query: str):
1494
1574
  )
1495
1575
 
1496
1576
 
1577
+ def get_single_llm(model_names: str):
1578
+ if "," in model_names:
1579
+ # Multiple code models specified
1580
+ model_names = model_names.split(",")
1581
+ for _, model_name in enumerate(model_names):
1582
+ return byzerllm.ByzerLLM.from_default_model(model_name)
1583
+ else:
1584
+ # Single code model
1585
+ return byzerllm.ByzerLLM.from_default_model(model_names)
1586
+
1587
+
1497
1588
  def commit(query: str):
1498
1589
  def prepare_commit_yaml():
1499
1590
  auto_coder_main(["next", "chat_action"])
@@ -1536,18 +1627,20 @@ def commit(query: str):
1536
1627
  temp_yaml = os.path.join("actions", f"{uuid.uuid4()}.yml")
1537
1628
  try:
1538
1629
  with open(temp_yaml, "w") as f:
1539
- f.write(convert_yaml_config_to_str(yaml_config=yaml_config))
1630
+ f.write(convert_yaml_config_to_str(
1631
+ yaml_config=yaml_config))
1540
1632
  args = convert_yaml_to_config(temp_yaml)
1541
1633
  finally:
1542
1634
  if os.path.exists(temp_yaml):
1543
1635
  os.remove(temp_yaml)
1544
1636
 
1545
- llm = byzerllm.ByzerLLM.from_default_model(args.code_model or args.model)
1637
+ llm = get_single_llm(args.code_model or args.model)
1546
1638
  uncommitted_changes = git_utils.get_uncommitted_changes(".")
1547
1639
  commit_message = git_utils.generate_commit_message.with_llm(llm).run(
1548
1640
  uncommitted_changes
1549
1641
  )
1550
- memory["conversation"].append({"role": "user", "content": commit_message})
1642
+ memory["conversation"].append(
1643
+ {"role": "user", "content": commit_message})
1551
1644
  yaml_config["query"] = commit_message
1552
1645
  yaml_content = convert_yaml_config_to_str(yaml_config=yaml_config)
1553
1646
  with open(os.path.join(execute_file), "w") as f:
@@ -1607,6 +1700,8 @@ def coding(query: str):
1607
1700
  == "true",
1608
1701
  }
1609
1702
 
1703
+ yaml_config["context"] = ""
1704
+
1610
1705
  for key, value in conf.items():
1611
1706
  converted_value = convert_config_value(key, value)
1612
1707
  if converted_value is not None:
@@ -1625,7 +1720,8 @@ def coding(query: str):
1625
1720
  active_groups_context = "下面是对上面文件按分组给到的一些描述,当用户的需求正好匹配描述的时候,参考描述来做修改:\n"
1626
1721
  for group in current_groups:
1627
1722
  group_files = groups.get(group, [])
1628
- query_prefix = groups_info.get(group, {}).get("query_prefix", "")
1723
+ query_prefix = groups_info.get(
1724
+ group, {}).get("query_prefix", "")
1629
1725
  active_groups_context += f"组名: {group}\n"
1630
1726
  active_groups_context += f"文件列表:\n"
1631
1727
  for file in group_files:
@@ -1664,12 +1760,13 @@ def coding(query: str):
1664
1760
 
1665
1761
  yaml_config[
1666
1762
  "context"
1667
- ] += f"下面是我们的历史对话,参考我们的历史对话从而更好的理解需求和修改代码。\n\n"
1763
+ ] += f"下面是我们的历史对话,参考我们的历史对话从而更好的理解需求和修改代码。\n\n<history>\n"
1668
1764
  for conv in conversations:
1669
1765
  if conv["role"] == "user":
1670
1766
  yaml_config["context"] += f"用户: {conv['content']}\n"
1671
1767
  elif conv["role"] == "assistant":
1672
1768
  yaml_config["context"] += f"你: {conv['content']}\n"
1769
+ yaml_config["context"] += "</history>\n"
1673
1770
 
1674
1771
  yaml_content = convert_yaml_config_to_str(yaml_config=yaml_config)
1675
1772
 
@@ -2070,7 +2167,8 @@ def execute_shell_command(command: str):
2070
2167
  f"[bold red]Command failed with return code {process.returncode}[/bold red]"
2071
2168
  )
2072
2169
  else:
2073
- console.print("[bold green]Command completed successfully[/bold green]")
2170
+ console.print(
2171
+ "[bold green]Command completed successfully[/bold green]")
2074
2172
 
2075
2173
  except FileNotFoundError:
2076
2174
  console.print(
@@ -2118,7 +2216,8 @@ def lib_command(args: List[str]):
2118
2216
  proxy_url,
2119
2217
  llm_friendly_packages_dir,
2120
2218
  )
2121
- console.print("Successfully cloned llm_friendly_packages repository")
2219
+ console.print(
2220
+ "Successfully cloned llm_friendly_packages repository")
2122
2221
  except git.exc.GitCommandError as e:
2123
2222
  console.print(f"Error cloning repository: {e}")
2124
2223
 
@@ -2179,7 +2278,8 @@ def lib_command(args: List[str]):
2179
2278
  console.print(f"Updated remote URL to: {new_url}")
2180
2279
 
2181
2280
  origin.pull()
2182
- console.print("Successfully updated llm_friendly_packages repository")
2281
+ console.print(
2282
+ "Successfully updated llm_friendly_packages repository")
2183
2283
 
2184
2284
  except git.exc.GitCommandError as e:
2185
2285
  console.print(f"Error updating repository: {e}")
@@ -2201,7 +2301,8 @@ def lib_command(args: List[str]):
2201
2301
  table.add_row(doc)
2202
2302
  console.print(table)
2203
2303
  else:
2204
- console.print(f"No markdown files found for package: {package_name}")
2304
+ console.print(
2305
+ f"No markdown files found for package: {package_name}")
2205
2306
 
2206
2307
  else:
2207
2308
  console.print(f"Unknown subcommand: {subcommand}")
@@ -2323,7 +2424,8 @@ def main():
2323
2424
  FormattedText(prompt_message), default=new_prompt, style=style
2324
2425
  )
2325
2426
  else:
2326
- user_input = session.prompt(FormattedText(prompt_message), style=style)
2427
+ user_input = session.prompt(
2428
+ FormattedText(prompt_message), style=style)
2327
2429
  new_prompt = ""
2328
2430
 
2329
2431
  if "mode" not in memory:
@@ -2348,13 +2450,14 @@ def main():
2348
2450
  new_prompt = "/coding " + text
2349
2451
 
2350
2452
  elif user_input.startswith("/add_files"):
2351
- args = user_input[len("/add_files") :].strip().split()
2453
+ args = user_input[len("/add_files"):].strip().split()
2352
2454
  add_files(args)
2353
2455
  elif user_input.startswith("/remove_files"):
2354
- file_names = user_input[len("/remove_files") :].strip().split(",")
2456
+ file_names = user_input[len(
2457
+ "/remove_files"):].strip().split(",")
2355
2458
  remove_files(file_names)
2356
2459
  elif user_input.startswith("/index/query"):
2357
- query = user_input[len("/index/query") :].strip()
2460
+ query = user_input[len("/index/query"):].strip()
2358
2461
  index_query(query)
2359
2462
 
2360
2463
  elif user_input.startswith("/index/build"):
@@ -2364,14 +2467,14 @@ def main():
2364
2467
  list_files()
2365
2468
 
2366
2469
  elif user_input.startswith("/mode"):
2367
- conf = user_input[len("/mode") :].strip()
2470
+ conf = user_input[len("/mode"):].strip()
2368
2471
  if not conf:
2369
2472
  print(memory["mode"])
2370
2473
  else:
2371
2474
  memory["mode"] = conf
2372
2475
 
2373
2476
  elif user_input.startswith("/conf"):
2374
- conf = user_input[len("/conf") :].strip()
2477
+ conf = user_input[len("/conf"):].strip()
2375
2478
  if not conf:
2376
2479
  print(memory["conf"])
2377
2480
  else:
@@ -2379,15 +2482,16 @@ def main():
2379
2482
  elif user_input.startswith("/revert"):
2380
2483
  revert()
2381
2484
  elif user_input.startswith("/commit"):
2382
- query = user_input[len("/commit") :].strip()
2485
+ query = user_input[len("/commit"):].strip()
2383
2486
  commit(query)
2384
2487
  elif user_input.startswith("/help"):
2385
2488
  show_help()
2386
2489
  elif user_input.startswith("/exclude_dirs"):
2387
- dir_names = user_input[len("/exclude_dirs") :].strip().split(",")
2490
+ dir_names = user_input[len(
2491
+ "/exclude_dirs"):].strip().split(",")
2388
2492
  exclude_dirs(dir_names)
2389
2493
  elif user_input.startswith("/ask"):
2390
- query = user_input[len("/ask") :].strip()
2494
+ query = user_input[len("/ask"):].strip()
2391
2495
  if not query:
2392
2496
  print("Please enter your question.")
2393
2497
  else:
@@ -2397,45 +2501,45 @@ def main():
2397
2501
  raise EOFError()
2398
2502
 
2399
2503
  elif user_input.startswith("/coding"):
2400
- query = user_input[len("/coding") :].strip()
2504
+ query = user_input[len("/coding"):].strip()
2401
2505
  if not query:
2402
2506
  print("\033[91mPlease enter your request.\033[0m")
2403
2507
  continue
2404
2508
  coding(query)
2405
2509
  elif user_input.startswith("/chat"):
2406
- query = user_input[len("/chat") :].strip()
2510
+ query = user_input[len("/chat"):].strip()
2407
2511
  if not query:
2408
2512
  print("\033[91mPlease enter your request.\033[0m")
2409
2513
  else:
2410
2514
  chat(query)
2411
2515
 
2412
2516
  elif user_input.startswith("/design"):
2413
- query = user_input[len("/design") :].strip()
2517
+ query = user_input[len("/design"):].strip()
2414
2518
  if not query:
2415
2519
  print("\033[91mPlease enter your design request.\033[0m")
2416
2520
  else:
2417
2521
  design(query)
2418
2522
 
2419
2523
  elif user_input.startswith("/summon"):
2420
- query = user_input[len("/summon") :].strip()
2524
+ query = user_input[len("/summon"):].strip()
2421
2525
  if not query:
2422
2526
  print("\033[91mPlease enter your request.\033[0m")
2423
2527
  else:
2424
2528
  summon(query)
2425
2529
 
2426
2530
  elif user_input.startswith("/lib"):
2427
- args = user_input[len("/lib") :].strip().split()
2531
+ args = user_input[len("/lib"):].strip().split()
2428
2532
  lib_command(args)
2429
2533
 
2430
2534
  elif user_input.startswith("/mcp"):
2431
- query = user_input[len("/mcp") :].strip()
2535
+ query = user_input[len("/mcp"):].strip()
2432
2536
  if not query:
2433
2537
  print("Please enter your query.")
2434
2538
  else:
2435
2539
  mcp(query)
2436
2540
 
2437
2541
  elif user_input.startswith("/debug"):
2438
- code = user_input[len("/debug") :].strip()
2542
+ code = user_input[len("/debug"):].strip()
2439
2543
  try:
2440
2544
  result = eval(code)
2441
2545
  print(f"Debug result: {result}")
@@ -2446,7 +2550,7 @@ def main():
2446
2550
  else:
2447
2551
  command = user_input
2448
2552
  if user_input.startswith("/shell"):
2449
- command = user_input[len("/shell") :].strip()
2553
+ command = user_input[len("/shell"):].strip()
2450
2554
  if not command:
2451
2555
  print("Please enter a shell command to execute.")
2452
2556
  else:
@@ -2459,7 +2563,7 @@ def main():
2459
2563
  save_memory()
2460
2564
  try:
2461
2565
  if get_mcp_server():
2462
- get_mcp_server().stop()
2566
+ get_mcp_server().stop()
2463
2567
  except Exception as e:
2464
2568
  pass
2465
2569
  except Exception as e: