auto-coder 0.1.215__py3-none-any.whl → 0.1.218__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,14 @@ 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, McpRefreshRequest
48
+ import byzerllm
49
+
65
50
 
66
51
  class SymbolItem(BaseModel):
67
52
  symbol_name: str
@@ -73,7 +58,8 @@ def parse_arguments():
73
58
  import argparse
74
59
 
75
60
  parser = argparse.ArgumentParser(description="Chat Auto Coder")
76
- parser.add_argument("--debug", action="store_true", help="Enable debug mode")
61
+ parser.add_argument("--debug", action="store_true",
62
+ help="Enable debug mode")
77
63
  parser.add_argument(
78
64
  "--quick",
79
65
  action="store_true",
@@ -156,8 +142,10 @@ def show_help():
156
142
  print(
157
143
  f" \033[94m/summon\033[0m \033[93m<query>\033[0m - \033[92m{get_message('summon_desc')}\033[0m"
158
144
  )
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")
145
+ print(
146
+ f" \033[94m/revert\033[0m - \033[92m{get_message('revert_desc')}\033[0m")
147
+ print(
148
+ f" \033[94m/commit\033[0m - \033[92m{get_message('commit_desc')}\033[0m")
161
149
  print(
162
150
  f" \033[94m/conf\033[0m \033[93m<key>:<value>\033[0m - \033[92m{get_message('conf_desc')}\033[0m"
163
151
  )
@@ -170,7 +158,8 @@ def show_help():
170
158
  print(
171
159
  f" \033[94m/list_files\033[0m - \033[92m{get_message('list_files_desc')}\033[0m"
172
160
  )
173
- print(f" \033[94m/help\033[0m - \033[92m{get_message('help_desc')}\033[0m")
161
+ print(
162
+ f" \033[94m/help\033[0m - \033[92m{get_message('help_desc')}\033[0m")
174
163
  print(
175
164
  f" \033[94m/exclude_dirs\033[0m \033[93m<dir1>,<dir2> ...\033[0m - \033[92m{get_message('exclude_dirs_desc')}\033[0m"
176
165
  )
@@ -180,9 +169,11 @@ def show_help():
180
169
  print(
181
170
  f" \033[94m/voice_input\033[0m - \033[92m{get_message('voice_input_desc')}\033[0m"
182
171
  )
183
- print(f" \033[94m/mode\033[0m - \033[92m{get_message('mode_desc')}\033[0m")
172
+ print(
173
+ f" \033[94m/mode\033[0m - \033[92m{get_message('mode_desc')}\033[0m")
184
174
  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")
175
+ print(
176
+ f" \033[94m/exit\033[0m - \033[92m{get_message('exit_desc')}\033[0m")
186
177
  print()
187
178
 
188
179
 
@@ -207,10 +198,12 @@ def configure_project_type():
207
198
  print_formatted_text(HTML(f"<info>{escape(text)}</info>"), style=style)
208
199
 
209
200
  def print_warning(text):
210
- print_formatted_text(HTML(f"<warning>{escape(text)}</warning>"), style=style)
201
+ print_formatted_text(
202
+ HTML(f"<warning>{escape(text)}</warning>"), style=style)
211
203
 
212
204
  def print_header(text):
213
- print_formatted_text(HTML(f"<header>{escape(text)}</header>"), style=style)
205
+ print_formatted_text(
206
+ HTML(f"<header>{escape(text)}</header>"), style=style)
214
207
 
215
208
  print_header(f"\n=== {get_message('project_type_config')} ===\n")
216
209
  print_info(get_message("project_type_supports"))
@@ -256,7 +249,8 @@ def initialize_system():
256
249
  if not os.path.exists(".auto-coder"):
257
250
  first_time = True
258
251
  print_status(get_message("not_initialized"), "warning")
259
- init_choice = input(f" {get_message('init_prompt')}").strip().lower()
252
+ init_choice = input(
253
+ f" {get_message('init_prompt')}").strip().lower()
260
254
  if init_choice == "y":
261
255
  try:
262
256
  subprocess.run(
@@ -273,7 +267,8 @@ def initialize_system():
273
267
 
274
268
  if not os.path.exists(base_persist_dir):
275
269
  os.makedirs(base_persist_dir, exist_ok=True)
276
- print_status(get_message("created_dir").format(base_persist_dir), "success")
270
+ print_status(get_message("created_dir").format(
271
+ base_persist_dir), "success")
277
272
 
278
273
  if first_time:
279
274
  configure_project_type()
@@ -283,7 +278,8 @@ def initialize_system():
283
278
  init_project()
284
279
  # Check if Ray is running
285
280
  print_status(get_message("checking_ray"), "")
286
- ray_status = subprocess.run(["ray", "status"], capture_output=True, text=True)
281
+ ray_status = subprocess.run(
282
+ ["ray", "status"], capture_output=True, text=True)
287
283
  if ray_status.returncode != 0:
288
284
  print_status(get_message("ray_not_running"), "warning")
289
285
  try:
@@ -315,9 +311,9 @@ def initialize_system():
315
311
  print_status(get_message("model_error"), "error")
316
312
 
317
313
  # If deepseek_chat is not available
318
- print_status(get_message("model_not_available"), "warning")
314
+ print_status(get_message("model_not_available"), "warning")
319
315
  api_key = prompt(HTML(f"<b>{get_message('enter_api_key')} </b>"))
320
-
316
+
321
317
  print_status(get_message("deploying_model").format("Deepseek官方"), "")
322
318
  deploy_cmd = [
323
319
  "byzerllm",
@@ -401,7 +397,8 @@ def get_all_file_in_project_with_dot() -> List[str]:
401
397
  for root, dirs, files in os.walk(project_root, followlinks=True):
402
398
  dirs[:] = [d for d in dirs if d not in final_exclude_dirs]
403
399
  for file in files:
404
- file_names.append(os.path.join(root, file).replace(project_root, "."))
400
+ file_names.append(os.path.join(
401
+ root, file).replace(project_root, "."))
405
402
  return file_names
406
403
 
407
404
 
@@ -529,8 +526,10 @@ def show_help():
529
526
  print(
530
527
  f" \033[94m/summon\033[0m \033[93m<query>\033[0m - \033[92m{get_message('summon_desc')}\033[0m"
531
528
  )
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")
529
+ print(
530
+ f" \033[94m/revert\033[0m - \033[92m{get_message('revert_desc')}\033[0m")
531
+ print(
532
+ f" \033[94m/commit\033[0m - \033[92m{get_message('commit_desc')}\033[0m")
534
533
  print(
535
534
  f" \033[94m/conf\033[0m \033[93m<key>:<value>\033[0m - \033[92m{get_message('conf_desc')}\033[0m"
536
535
  )
@@ -543,7 +542,8 @@ def show_help():
543
542
  print(
544
543
  f" \033[94m/list_files\033[0m - \033[92m{get_message('list_files_desc')}\033[0m"
545
544
  )
546
- print(f" \033[94m/help\033[0m - \033[92m{get_message('help_desc')}\033[0m")
545
+ print(
546
+ f" \033[94m/help\033[0m - \033[92m{get_message('help_desc')}\033[0m")
547
547
  print(
548
548
  f" \033[94m/exclude_dirs\033[0m \033[93m<dir1>,<dir2> ...\033[0m - \033[92m{get_message('exclude_dirs_desc')}\033[0m"
549
549
  )
@@ -553,9 +553,11 @@ def show_help():
553
553
  print(
554
554
  f" \033[94m/voice_input\033[0m - \033[92m{get_message('voice_input_desc')}\033[0m"
555
555
  )
556
- print(f" \033[94m/mode\033[0m - \033[92m{get_message('mode_desc')}\033[0m")
556
+ print(
557
+ f" \033[94m/mode\033[0m - \033[92m{get_message('mode_desc')}\033[0m")
557
558
  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")
559
+ print(
560
+ f" \033[94m/exit\033[0m - \033[92m{get_message('exit_desc')}\033[0m")
559
561
  print()
560
562
 
561
563
 
@@ -619,13 +621,13 @@ class CommandCompleter(Completer):
619
621
 
620
622
  if len(words) > 0:
621
623
  if words[0] == "/mode":
622
- left_word = text[len("/mode") :]
624
+ left_word = text[len("/mode"):]
623
625
  for mode in ["normal", "auto_detect", "voice_input"]:
624
626
  if mode.startswith(left_word.strip()):
625
627
  yield Completion(mode, start_position=-len(left_word.strip()))
626
628
 
627
629
  if words[0] == "/add_files":
628
- new_text = text[len("/add_files") :]
630
+ new_text = text[len("/add_files"):]
629
631
  parser = CommandTextParser(new_text, words[0])
630
632
  parser.add_files()
631
633
  current_word = parser.current_word()
@@ -656,18 +658,21 @@ class CommandCompleter(Completer):
656
658
  for file_name in self.all_files_with_dot:
657
659
  if file_name.startswith(current_word):
658
660
  yield Completion(
659
- file_name, start_position=-len(current_word)
661
+ file_name, start_position=-
662
+ len(current_word)
660
663
  )
661
664
  else:
662
665
  for file_name in self.all_file_names:
663
666
  if file_name.startswith(current_word):
664
667
  yield Completion(
665
- file_name, start_position=-len(current_word)
668
+ file_name, start_position=-
669
+ len(current_word)
666
670
  )
667
671
  for file_name in self.all_files:
668
672
  if current_word and current_word in file_name:
669
673
  yield Completion(
670
- file_name, start_position=-len(current_word)
674
+ file_name, start_position=-
675
+ len(current_word)
671
676
  )
672
677
  elif words[0] in ["/chat", "/coding"]:
673
678
  image_extensions = (
@@ -697,7 +702,7 @@ class CommandCompleter(Completer):
697
702
  ".psd",
698
703
  ".xcf",
699
704
  )
700
- new_text = text[len(words[0]) :]
705
+ new_text = text[len(words[0]):]
701
706
  parser = CommandTextParser(new_text, words[0])
702
707
 
703
708
  parser.coding()
@@ -724,7 +729,8 @@ class CommandCompleter(Completer):
724
729
  if len(path_parts) > 3
725
730
  else file_name
726
731
  )
727
- relative_path = os.path.relpath(file_name, project_root)
732
+ relative_path = os.path.relpath(
733
+ file_name, project_root)
728
734
  yield Completion(
729
735
  relative_path,
730
736
  start_position=-len(name),
@@ -741,7 +747,8 @@ class CommandCompleter(Completer):
741
747
  if len(path_parts) > 3
742
748
  else file_name
743
749
  )
744
- relative_path = os.path.relpath(file_name, project_root)
750
+ relative_path = os.path.relpath(
751
+ file_name, project_root)
745
752
 
746
753
  yield Completion(
747
754
  relative_path,
@@ -757,7 +764,8 @@ class CommandCompleter(Completer):
757
764
  if len(path_parts) > 3
758
765
  else file_name
759
766
  )
760
- relative_path = os.path.relpath(file_name, project_root)
767
+ relative_path = os.path.relpath(
768
+ file_name, project_root)
761
769
  yield Completion(
762
770
  relative_path,
763
771
  start_position=-len(name),
@@ -775,7 +783,8 @@ class CommandCompleter(Completer):
775
783
  if len(path_parts) > 3
776
784
  else symbol.symbol_name
777
785
  )
778
- relative_path = os.path.relpath(file_name, project_root)
786
+ relative_path = os.path.relpath(
787
+ file_name, project_root)
779
788
  yield Completion(
780
789
  f"{symbol.symbol_name}(location: {relative_path})",
781
790
  start_position=-len(name),
@@ -810,7 +819,8 @@ class CommandCompleter(Completer):
810
819
  for dir in dirs:
811
820
  full_path = os.path.join(root, dir)
812
821
  if full_path.startswith(file_name):
813
- relative_path = os.path.relpath(full_path, search_dir)
822
+ relative_path = os.path.relpath(
823
+ full_path, search_dir)
814
824
  yield Completion(
815
825
  relative_path,
816
826
  start_position=-len(file_basename),
@@ -822,7 +832,8 @@ class CommandCompleter(Completer):
822
832
  image_extensions
823
833
  ) and file.startswith(file_basename):
824
834
  full_path = os.path.join(root, file)
825
- relative_path = os.path.relpath(full_path, search_dir)
835
+ relative_path = os.path.relpath(
836
+ full_path, search_dir)
826
837
  yield Completion(
827
838
  relative_path,
828
839
  start_position=-len(file_basename),
@@ -832,7 +843,7 @@ class CommandCompleter(Completer):
832
843
  break
833
844
 
834
845
  elif words[0] == "/remove_files":
835
- new_words = text[len("/remove_files") :].strip().split(",")
846
+ new_words = text[len("/remove_files"):].strip().split(",")
836
847
 
837
848
  is_at_space = text[-1] == " "
838
849
  last_word = new_words[-2] if len(new_words) > 1 else ""
@@ -859,7 +870,7 @@ class CommandCompleter(Completer):
859
870
  file_name, start_position=-len(current_word)
860
871
  )
861
872
  elif words[0] == "/exclude_dirs":
862
- new_words = text[len("/exclude_dirs") :].strip().split(",")
873
+ new_words = text[len("/exclude_dirs"):].strip().split(",")
863
874
  current_word = new_words[-1]
864
875
 
865
876
  for file_name in self.all_dir_names:
@@ -867,7 +878,7 @@ class CommandCompleter(Completer):
867
878
  yield Completion(file_name, start_position=-len(current_word))
868
879
 
869
880
  elif words[0] == "/lib":
870
- new_text = text[len("/lib") :]
881
+ new_text = text[len("/lib"):]
871
882
  parser = CommandTextParser(new_text, words[0])
872
883
  parser.lib()
873
884
  current_word = parser.current_word()
@@ -882,8 +893,17 @@ class CommandCompleter(Completer):
882
893
  yield Completion(
883
894
  lib_name, start_position=-len(current_word)
884
895
  )
896
+ elif words[0] == "/mcp":
897
+ new_text = text[len("/mcp"):]
898
+ parser = CommandTextParser(new_text, words[0])
899
+ parser.lib()
900
+ current_word = parser.current_word()
901
+ for command in parser.get_sub_commands():
902
+ if command.startswith(current_word):
903
+ yield Completion(command, start_position=-len(current_word))
904
+
885
905
  elif words[0] == "/coding":
886
- new_text = text[len("/coding") :]
906
+ new_text = text[len("/coding"):]
887
907
  parser = CommandTextParser(new_text, words[0])
888
908
  parser.lib()
889
909
  current_word = parser.current_word()
@@ -892,7 +912,7 @@ class CommandCompleter(Completer):
892
912
  yield Completion(command, start_position=-len(current_word))
893
913
 
894
914
  elif words[0] == "/conf":
895
- new_words = text[len("/conf") :].strip().split()
915
+ new_words = text[len("/conf"):].strip().split()
896
916
  is_at_space = text[-1] == " "
897
917
  last_word = new_words[-2] if len(new_words) > 1 else ""
898
918
  current_word = new_words[-1] if new_words else ""
@@ -911,7 +931,8 @@ class CommandCompleter(Completer):
911
931
  ]
912
932
  # /conf [curosr]
913
933
  elif not last_word and not current_word:
914
- completions = ["/drop"] if "/drop".startswith(current_word) else []
934
+ completions = [
935
+ "/drop"] if "/drop".startswith(current_word) else []
915
936
  completions += [
916
937
  field_name + ":"
917
938
  for field_name in AutoCoderArgs.model_fields.keys()
@@ -919,7 +940,8 @@ class CommandCompleter(Completer):
919
940
  ]
920
941
  # /conf p[cursor]
921
942
  elif not last_word and current_word:
922
- completions = ["/drop"] if "/drop".startswith(current_word) else []
943
+ completions = [
944
+ "/drop"] if "/drop".startswith(current_word) else []
923
945
  completions += [
924
946
  field_name + ":"
925
947
  for field_name in AutoCoderArgs.model_fields.keys()
@@ -1013,7 +1035,8 @@ def add_files(args: List[str]):
1013
1035
  completer.refresh_files()
1014
1036
  load_memory()
1015
1037
  console.print(
1016
- Panel("Refreshed file list.", title="Files Refreshed", border_style="green")
1038
+ Panel("Refreshed file list.",
1039
+ title="Files Refreshed", border_style="green")
1017
1040
  )
1018
1041
  return
1019
1042
 
@@ -1021,7 +1044,8 @@ def add_files(args: List[str]):
1021
1044
  if len(args) == 1 or (len(args) == 2 and args[1] == "list"):
1022
1045
  if not groups:
1023
1046
  console.print(
1024
- Panel("No groups defined.", title="Groups", border_style="yellow")
1047
+ Panel("No groups defined.", title="Groups",
1048
+ border_style="yellow")
1025
1049
  )
1026
1050
  else:
1027
1051
  table = Table(
@@ -1046,7 +1070,8 @@ def add_files(args: List[str]):
1046
1070
  )
1047
1071
  table.add_row(
1048
1072
  group_name,
1049
- "\n".join([os.path.relpath(f, project_root) for f in files]),
1073
+ "\n".join([os.path.relpath(f, project_root)
1074
+ for f in files]),
1050
1075
  query_prefix,
1051
1076
  is_active,
1052
1077
  end_section=(i == len(groups) - 1),
@@ -1078,7 +1103,8 @@ def add_files(args: List[str]):
1078
1103
  if group_name in groups_info:
1079
1104
  del memory["current_files"]["groups_info"][group_name]
1080
1105
  if group_name in memory["current_files"]["current_groups"]:
1081
- memory["current_files"]["current_groups"].remove(group_name)
1106
+ memory["current_files"]["current_groups"].remove(
1107
+ group_name)
1082
1108
  console.print(
1083
1109
  Panel(
1084
1110
  f"Dropped group '{group_name}'.",
@@ -1251,7 +1277,8 @@ def remove_files(file_names: List[str]):
1251
1277
  memory["current_files"]["files"] = []
1252
1278
  memory["current_files"]["current_groups"] = []
1253
1279
  console.print(
1254
- Panel("Removed all files.", title="Files Removed", border_style="green")
1280
+ Panel("Removed all files.",
1281
+ title="Files Removed", border_style="green")
1255
1282
  )
1256
1283
  else:
1257
1284
  removed_files = []
@@ -1383,6 +1410,63 @@ def convert_yaml_to_config(yaml_file: str):
1383
1410
 
1384
1411
 
1385
1412
  def mcp(query: str):
1413
+ query = query.strip()
1414
+ mcp_server = get_mcp_server()
1415
+
1416
+ # Handle remove command
1417
+ if query.startswith("/remove"):
1418
+ server_name = query.replace("/remove", "", 1).strip()
1419
+ response = mcp_server.send_request(
1420
+ McpRemoveRequest(server_name=server_name))
1421
+ if response.error:
1422
+ print(f"Error removing MCP server: {response.error}")
1423
+ else:
1424
+ print(f"Successfully removed MCP server: {response.result}")
1425
+ return
1426
+
1427
+ # Handle list command
1428
+ if query.startswith("/list_running"):
1429
+ response = mcp_server.send_request(McpListRunningRequest())
1430
+ if response.error:
1431
+ print(f"Error listing running MCP servers: {response.error}")
1432
+ else:
1433
+ print("Running MCP servers:")
1434
+ print(response.result)
1435
+ return
1436
+
1437
+ # Handle list command
1438
+ if query.startswith("/list"):
1439
+ response = mcp_server.send_request(McpListRequest())
1440
+ if response.error:
1441
+ print(f"Error listing builtin MCP servers: {response.error}")
1442
+ else:
1443
+ print("Available builtin MCP servers:")
1444
+ print(response.result)
1445
+ return
1446
+
1447
+ # Handle refresh command
1448
+ if query.startswith("/refresh"):
1449
+ server_name = query.replace("/refresh", "", 1).strip()
1450
+ response = mcp_server.send_request(McpRefreshRequest(name=server_name or None))
1451
+ if response.error:
1452
+ print(f"Error refreshing MCP servers: {response.error}")
1453
+ else:
1454
+ print("Successfully refreshed MCP servers")
1455
+ return
1456
+
1457
+ # Handle add command
1458
+ if query.startswith("/add"):
1459
+ query = query.replace("/add", "", 1).strip()
1460
+ request = McpInstallRequest(server_name_or_config=query)
1461
+ response = mcp_server.send_request(request)
1462
+
1463
+ if response.error:
1464
+ print(f"Error installing MCP server: {response.error}")
1465
+ else:
1466
+ print(f"Successfully installed MCP server: {response.result}")
1467
+ return
1468
+
1469
+ # Handle default query
1386
1470
  conf = memory.get("conf", {})
1387
1471
  yaml_config = {
1388
1472
  "include_file": ["./base/base.yml"],
@@ -1406,8 +1490,8 @@ def mcp(query: str):
1406
1490
  args = convert_yaml_to_config(temp_yaml)
1407
1491
  finally:
1408
1492
  if os.path.exists(temp_yaml):
1409
- os.remove(temp_yaml)
1410
-
1493
+ os.remove(temp_yaml)
1494
+
1411
1495
  mcp_server = get_mcp_server()
1412
1496
  response = mcp_server.send_request(
1413
1497
  McpRequest(
@@ -1415,7 +1499,7 @@ def mcp(query: str):
1415
1499
  model=args.inference_model or args.model
1416
1500
  )
1417
1501
  )
1418
-
1502
+
1419
1503
  if response.error:
1420
1504
  print(f"Error from MCP server: {response.error}")
1421
1505
  else:
@@ -1448,9 +1532,11 @@ def code_next(query: str):
1448
1532
  if os.path.exists(temp_yaml):
1449
1533
  os.remove(temp_yaml)
1450
1534
 
1451
- llm = byzerllm.ByzerLLM.from_default_model(args.inference_model or args.model)
1535
+ llm = byzerllm.ByzerLLM.from_default_model(
1536
+ args.inference_model or args.model)
1452
1537
 
1453
- auto_guesser = AutoGuessQuery(llm=llm, project_dir=os.getcwd(), skip_diff=True)
1538
+ auto_guesser = AutoGuessQuery(
1539
+ llm=llm, project_dir=os.getcwd(), skip_diff=True)
1454
1540
 
1455
1541
  predicted_tasks = auto_guesser.predict_next_tasks(
1456
1542
  5, is_human_as_model=args.human_as_model
@@ -1464,20 +1550,25 @@ def code_next(query: str):
1464
1550
  console = Console()
1465
1551
 
1466
1552
  # Create main panel for all predicted tasks
1467
- table = Table(show_header=True, header_style="bold magenta", show_lines=True)
1553
+ table = Table(show_header=True,
1554
+ header_style="bold magenta", show_lines=True)
1468
1555
  table.add_column("Priority", style="cyan", width=8)
1469
- table.add_column("Task Description", style="green", width=40, overflow="fold")
1556
+ table.add_column("Task Description", style="green",
1557
+ width=40, overflow="fold")
1470
1558
  table.add_column("Files", style="yellow", width=30, overflow="fold")
1471
1559
  table.add_column("Reason", style="blue", width=30, overflow="fold")
1472
- table.add_column("Dependencies", style="magenta", width=30, overflow="fold")
1560
+ table.add_column("Dependencies", style="magenta",
1561
+ width=30, overflow="fold")
1473
1562
 
1474
1563
  for task in predicted_tasks:
1475
1564
  # Format file paths to be more readable
1476
- file_list = "\n".join([os.path.relpath(f, os.getcwd()) for f in task.urls])
1565
+ file_list = "\n".join([os.path.relpath(f, os.getcwd())
1566
+ for f in task.urls])
1477
1567
 
1478
1568
  # Format dependencies to be more readable
1479
1569
  dependencies = (
1480
- "\n".join(task.dependency_queries) if task.dependency_queries else "None"
1570
+ "\n".join(
1571
+ task.dependency_queries) if task.dependency_queries else "None"
1481
1572
  )
1482
1573
 
1483
1574
  table.add_row(
@@ -1494,6 +1585,17 @@ def code_next(query: str):
1494
1585
  )
1495
1586
 
1496
1587
 
1588
+ def get_single_llm(model_names: str):
1589
+ if "," in model_names:
1590
+ # Multiple code models specified
1591
+ model_names = model_names.split(",")
1592
+ for _, model_name in enumerate(model_names):
1593
+ return byzerllm.ByzerLLM.from_default_model(model_name)
1594
+ else:
1595
+ # Single code model
1596
+ return byzerllm.ByzerLLM.from_default_model(model_names)
1597
+
1598
+
1497
1599
  def commit(query: str):
1498
1600
  def prepare_commit_yaml():
1499
1601
  auto_coder_main(["next", "chat_action"])
@@ -1536,18 +1638,20 @@ def commit(query: str):
1536
1638
  temp_yaml = os.path.join("actions", f"{uuid.uuid4()}.yml")
1537
1639
  try:
1538
1640
  with open(temp_yaml, "w") as f:
1539
- f.write(convert_yaml_config_to_str(yaml_config=yaml_config))
1641
+ f.write(convert_yaml_config_to_str(
1642
+ yaml_config=yaml_config))
1540
1643
  args = convert_yaml_to_config(temp_yaml)
1541
1644
  finally:
1542
1645
  if os.path.exists(temp_yaml):
1543
1646
  os.remove(temp_yaml)
1544
1647
 
1545
- llm = byzerllm.ByzerLLM.from_default_model(args.code_model or args.model)
1648
+ llm = get_single_llm(args.code_model or args.model)
1546
1649
  uncommitted_changes = git_utils.get_uncommitted_changes(".")
1547
1650
  commit_message = git_utils.generate_commit_message.with_llm(llm).run(
1548
1651
  uncommitted_changes
1549
1652
  )
1550
- memory["conversation"].append({"role": "user", "content": commit_message})
1653
+ memory["conversation"].append(
1654
+ {"role": "user", "content": commit_message})
1551
1655
  yaml_config["query"] = commit_message
1552
1656
  yaml_content = convert_yaml_config_to_str(yaml_config=yaml_config)
1553
1657
  with open(os.path.join(execute_file), "w") as f:
@@ -1607,6 +1711,8 @@ def coding(query: str):
1607
1711
  == "true",
1608
1712
  }
1609
1713
 
1714
+ yaml_config["context"] = ""
1715
+
1610
1716
  for key, value in conf.items():
1611
1717
  converted_value = convert_config_value(key, value)
1612
1718
  if converted_value is not None:
@@ -1625,7 +1731,8 @@ def coding(query: str):
1625
1731
  active_groups_context = "下面是对上面文件按分组给到的一些描述,当用户的需求正好匹配描述的时候,参考描述来做修改:\n"
1626
1732
  for group in current_groups:
1627
1733
  group_files = groups.get(group, [])
1628
- query_prefix = groups_info.get(group, {}).get("query_prefix", "")
1734
+ query_prefix = groups_info.get(
1735
+ group, {}).get("query_prefix", "")
1629
1736
  active_groups_context += f"组名: {group}\n"
1630
1737
  active_groups_context += f"文件列表:\n"
1631
1738
  for file in group_files:
@@ -1664,12 +1771,13 @@ def coding(query: str):
1664
1771
 
1665
1772
  yaml_config[
1666
1773
  "context"
1667
- ] += f"下面是我们的历史对话,参考我们的历史对话从而更好的理解需求和修改代码。\n\n"
1774
+ ] += f"下面是我们的历史对话,参考我们的历史对话从而更好的理解需求和修改代码。\n\n<history>\n"
1668
1775
  for conv in conversations:
1669
1776
  if conv["role"] == "user":
1670
1777
  yaml_config["context"] += f"用户: {conv['content']}\n"
1671
1778
  elif conv["role"] == "assistant":
1672
1779
  yaml_config["context"] += f"你: {conv['content']}\n"
1780
+ yaml_config["context"] += "</history>\n"
1673
1781
 
1674
1782
  yaml_content = convert_yaml_config_to_str(yaml_config=yaml_config)
1675
1783
 
@@ -2070,7 +2178,8 @@ def execute_shell_command(command: str):
2070
2178
  f"[bold red]Command failed with return code {process.returncode}[/bold red]"
2071
2179
  )
2072
2180
  else:
2073
- console.print("[bold green]Command completed successfully[/bold green]")
2181
+ console.print(
2182
+ "[bold green]Command completed successfully[/bold green]")
2074
2183
 
2075
2184
  except FileNotFoundError:
2076
2185
  console.print(
@@ -2118,7 +2227,8 @@ def lib_command(args: List[str]):
2118
2227
  proxy_url,
2119
2228
  llm_friendly_packages_dir,
2120
2229
  )
2121
- console.print("Successfully cloned llm_friendly_packages repository")
2230
+ console.print(
2231
+ "Successfully cloned llm_friendly_packages repository")
2122
2232
  except git.exc.GitCommandError as e:
2123
2233
  console.print(f"Error cloning repository: {e}")
2124
2234
 
@@ -2179,7 +2289,8 @@ def lib_command(args: List[str]):
2179
2289
  console.print(f"Updated remote URL to: {new_url}")
2180
2290
 
2181
2291
  origin.pull()
2182
- console.print("Successfully updated llm_friendly_packages repository")
2292
+ console.print(
2293
+ "Successfully updated llm_friendly_packages repository")
2183
2294
 
2184
2295
  except git.exc.GitCommandError as e:
2185
2296
  console.print(f"Error updating repository: {e}")
@@ -2201,7 +2312,8 @@ def lib_command(args: List[str]):
2201
2312
  table.add_row(doc)
2202
2313
  console.print(table)
2203
2314
  else:
2204
- console.print(f"No markdown files found for package: {package_name}")
2315
+ console.print(
2316
+ f"No markdown files found for package: {package_name}")
2205
2317
 
2206
2318
  else:
2207
2319
  console.print(f"Unknown subcommand: {subcommand}")
@@ -2323,7 +2435,8 @@ def main():
2323
2435
  FormattedText(prompt_message), default=new_prompt, style=style
2324
2436
  )
2325
2437
  else:
2326
- user_input = session.prompt(FormattedText(prompt_message), style=style)
2438
+ user_input = session.prompt(
2439
+ FormattedText(prompt_message), style=style)
2327
2440
  new_prompt = ""
2328
2441
 
2329
2442
  if "mode" not in memory:
@@ -2348,13 +2461,14 @@ def main():
2348
2461
  new_prompt = "/coding " + text
2349
2462
 
2350
2463
  elif user_input.startswith("/add_files"):
2351
- args = user_input[len("/add_files") :].strip().split()
2464
+ args = user_input[len("/add_files"):].strip().split()
2352
2465
  add_files(args)
2353
2466
  elif user_input.startswith("/remove_files"):
2354
- file_names = user_input[len("/remove_files") :].strip().split(",")
2467
+ file_names = user_input[len(
2468
+ "/remove_files"):].strip().split(",")
2355
2469
  remove_files(file_names)
2356
2470
  elif user_input.startswith("/index/query"):
2357
- query = user_input[len("/index/query") :].strip()
2471
+ query = user_input[len("/index/query"):].strip()
2358
2472
  index_query(query)
2359
2473
 
2360
2474
  elif user_input.startswith("/index/build"):
@@ -2364,14 +2478,14 @@ def main():
2364
2478
  list_files()
2365
2479
 
2366
2480
  elif user_input.startswith("/mode"):
2367
- conf = user_input[len("/mode") :].strip()
2481
+ conf = user_input[len("/mode"):].strip()
2368
2482
  if not conf:
2369
2483
  print(memory["mode"])
2370
2484
  else:
2371
2485
  memory["mode"] = conf
2372
2486
 
2373
2487
  elif user_input.startswith("/conf"):
2374
- conf = user_input[len("/conf") :].strip()
2488
+ conf = user_input[len("/conf"):].strip()
2375
2489
  if not conf:
2376
2490
  print(memory["conf"])
2377
2491
  else:
@@ -2379,15 +2493,16 @@ def main():
2379
2493
  elif user_input.startswith("/revert"):
2380
2494
  revert()
2381
2495
  elif user_input.startswith("/commit"):
2382
- query = user_input[len("/commit") :].strip()
2496
+ query = user_input[len("/commit"):].strip()
2383
2497
  commit(query)
2384
2498
  elif user_input.startswith("/help"):
2385
2499
  show_help()
2386
2500
  elif user_input.startswith("/exclude_dirs"):
2387
- dir_names = user_input[len("/exclude_dirs") :].strip().split(",")
2501
+ dir_names = user_input[len(
2502
+ "/exclude_dirs"):].strip().split(",")
2388
2503
  exclude_dirs(dir_names)
2389
2504
  elif user_input.startswith("/ask"):
2390
- query = user_input[len("/ask") :].strip()
2505
+ query = user_input[len("/ask"):].strip()
2391
2506
  if not query:
2392
2507
  print("Please enter your question.")
2393
2508
  else:
@@ -2397,45 +2512,45 @@ def main():
2397
2512
  raise EOFError()
2398
2513
 
2399
2514
  elif user_input.startswith("/coding"):
2400
- query = user_input[len("/coding") :].strip()
2515
+ query = user_input[len("/coding"):].strip()
2401
2516
  if not query:
2402
2517
  print("\033[91mPlease enter your request.\033[0m")
2403
2518
  continue
2404
2519
  coding(query)
2405
2520
  elif user_input.startswith("/chat"):
2406
- query = user_input[len("/chat") :].strip()
2521
+ query = user_input[len("/chat"):].strip()
2407
2522
  if not query:
2408
2523
  print("\033[91mPlease enter your request.\033[0m")
2409
2524
  else:
2410
2525
  chat(query)
2411
2526
 
2412
2527
  elif user_input.startswith("/design"):
2413
- query = user_input[len("/design") :].strip()
2528
+ query = user_input[len("/design"):].strip()
2414
2529
  if not query:
2415
2530
  print("\033[91mPlease enter your design request.\033[0m")
2416
2531
  else:
2417
2532
  design(query)
2418
2533
 
2419
2534
  elif user_input.startswith("/summon"):
2420
- query = user_input[len("/summon") :].strip()
2535
+ query = user_input[len("/summon"):].strip()
2421
2536
  if not query:
2422
2537
  print("\033[91mPlease enter your request.\033[0m")
2423
2538
  else:
2424
2539
  summon(query)
2425
2540
 
2426
2541
  elif user_input.startswith("/lib"):
2427
- args = user_input[len("/lib") :].strip().split()
2542
+ args = user_input[len("/lib"):].strip().split()
2428
2543
  lib_command(args)
2429
2544
 
2430
2545
  elif user_input.startswith("/mcp"):
2431
- query = user_input[len("/mcp") :].strip()
2546
+ query = user_input[len("/mcp"):].strip()
2432
2547
  if not query:
2433
2548
  print("Please enter your query.")
2434
2549
  else:
2435
2550
  mcp(query)
2436
2551
 
2437
2552
  elif user_input.startswith("/debug"):
2438
- code = user_input[len("/debug") :].strip()
2553
+ code = user_input[len("/debug"):].strip()
2439
2554
  try:
2440
2555
  result = eval(code)
2441
2556
  print(f"Debug result: {result}")
@@ -2446,7 +2561,7 @@ def main():
2446
2561
  else:
2447
2562
  command = user_input
2448
2563
  if user_input.startswith("/shell"):
2449
- command = user_input[len("/shell") :].strip()
2564
+ command = user_input[len("/shell"):].strip()
2450
2565
  if not command:
2451
2566
  print("Please enter a shell command to execute.")
2452
2567
  else:
@@ -2459,7 +2574,7 @@ def main():
2459
2574
  save_memory()
2460
2575
  try:
2461
2576
  if get_mcp_server():
2462
- get_mcp_server().stop()
2577
+ get_mcp_server().stop()
2463
2578
  except Exception as e:
2464
2579
  pass
2465
2580
  except Exception as e: