autocoder-nano 0.1.27__py3-none-any.whl → 0.1.29__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.
@@ -23,11 +23,12 @@ from autocoder_nano.git_utils import (repo_init, commit_changes, revert_changes,
23
23
  get_uncommitted_changes, generate_commit_message)
24
24
  from autocoder_nano.sys_utils import default_exclude_dirs, detect_env
25
25
  from autocoder_nano.project import PyProject, SuffixProject
26
+ from autocoder_nano.utils.printer_utils import Printer
26
27
 
27
28
  import yaml
28
- import tabulate
29
+ # import tabulate
29
30
  from jinja2 import Template
30
- from loguru import logger
31
+ # from loguru import logger
31
32
  from prompt_toolkit import prompt as _toolkit_prompt, PromptSession
32
33
  from prompt_toolkit.completion import Completer, Completion
33
34
  from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
@@ -45,14 +46,16 @@ from rich.table import Table
45
46
  from rich.text import Text
46
47
 
47
48
 
48
- console = Console()
49
+ printer = Printer()
50
+ console = printer.get_console()
51
+ # console = Console()
49
52
  project_root = os.getcwd()
50
53
  base_persist_dir = os.path.join(project_root, ".auto-coder", "plugins", "chat-auto-coder")
51
54
  # defaut_exclude_dirs = [".git", ".svn", "node_modules", "dist", "build", "__pycache__", ".auto-coder", "actions",
52
55
  # ".vscode", ".idea", ".hg"]
53
56
  commands = [
54
57
  "/add_files", "/remove_files", "/list_files", "/conf", "/coding", "/chat", "/revert", "/index/query",
55
- "/index/build", "/exclude_dirs", "/help", "/shell", "/exit", "/mode", "/models", "/commit", "/new"
58
+ "/index/build", "/exclude_dirs", "/exclude_files", "/help", "/shell", "/exit", "/mode", "/models", "/commit", "/new"
56
59
  ]
57
60
 
58
61
  memory = {
@@ -197,7 +200,9 @@ COMMANDS = {
197
200
  "/conf": "",
198
201
  "/mode": "",
199
202
  "/models": ""
200
- }
203
+ },
204
+ "/exclude_files": {"/list": "", "/drop": ""},
205
+ "/exclude_dirs": {}
201
206
  }
202
207
 
203
208
 
@@ -675,6 +680,15 @@ class CommandCompleter(Completer):
675
680
  if current_word and current_word in file_name:
676
681
  yield Completion(file_name, start_position=-len(current_word))
677
682
 
683
+ elif words[0] == "/exclude_files":
684
+ new_text = text[len("/exclude_files"):]
685
+ parser = CommandTextParser(new_text, words[0])
686
+ parser.add_files()
687
+ current_word = parser.current_word()
688
+ for command in parser.get_sub_commands():
689
+ if command.startswith(current_word):
690
+ yield Completion(command, start_position=-len(current_word))
691
+
678
692
  elif words[0] == "/models":
679
693
  new_text = text[len("/models"):]
680
694
  parser = CommandTextParser(new_text, words[0])
@@ -772,11 +786,76 @@ def load_memory():
772
786
  completer.update_current_files(memory["current_files"]["files"])
773
787
 
774
788
 
789
+ def exclude_dirs(dir_names: List[str]):
790
+ new_dirs = dir_names
791
+ existing_dirs = memory.get("exclude_dirs", [])
792
+ dirs_to_add = [d for d in new_dirs if d not in existing_dirs]
793
+
794
+ if dirs_to_add:
795
+ existing_dirs.extend(dirs_to_add)
796
+ if "exclude_dirs" not in memory:
797
+ memory["exclude_dirs"] = existing_dirs
798
+ printer.print_text(Text(f"已添加排除目录: {dirs_to_add}", style="bold green"))
799
+ for d in dirs_to_add:
800
+ exclude_files(f"regex://.*/{d}/*.")
801
+ # exclude_files([f"regex://.*/{d}/*." for d in dirs_to_add])
802
+ else:
803
+ printer.print_text(Text(f"所有指定目录已在排除列表中. ", style="bold green"))
804
+ save_memory()
805
+ completer.refresh_files()
806
+
807
+
808
+ def exclude_files(query: str):
809
+ if "/list" in query:
810
+ query = query.replace("/list", "", 1).strip()
811
+ existing_file_patterns = memory.get("exclude_files", [])
812
+
813
+ printer.print_table_compact(
814
+ headers=["File Pattern"],
815
+ data=[[file_pattern] for file_pattern in existing_file_patterns],
816
+ title="Exclude Files",
817
+ show_lines=False
818
+ )
819
+ return
820
+
821
+ if "/drop" in query:
822
+ query = query.replace("/drop", "", 1).strip()
823
+ existing_file_patterns = memory.get("exclude_files", [])
824
+ existing_file_patterns.remove(query.strip())
825
+ memory["exclude_files"] = existing_file_patterns
826
+ if query.startswith("regex://.*/") and query.endswith("/*."):
827
+ existing_dirs_patterns = memory.get("exclude_dirs", [])
828
+ dir_query = query.replace("regex://.*/", "", 1).replace("/*.", "", 1)
829
+ if dir_query in existing_dirs_patterns:
830
+ existing_dirs_patterns.remove(dir_query.strip())
831
+ save_memory()
832
+ completer.refresh_files()
833
+ return
834
+
835
+ new_file_patterns = query.strip().split(",")
836
+
837
+ existing_file_patterns = memory.get("exclude_files", [])
838
+ file_patterns_to_add = [f for f in new_file_patterns if f not in existing_file_patterns]
839
+
840
+ for file_pattern in file_patterns_to_add:
841
+ if not file_pattern.startswith("regex://"):
842
+ raise
843
+
844
+ if file_patterns_to_add:
845
+ existing_file_patterns.extend(file_patterns_to_add)
846
+ if "exclude_files" not in memory:
847
+ memory["exclude_files"] = existing_file_patterns
848
+ save_memory()
849
+ printer.print_text(f"已添加排除文件: {file_patterns_to_add}. ", style="green")
850
+ else:
851
+ printer.print_text(f"所有指定文件已在排除列表中. ", style="green")
852
+
853
+
775
854
  def index_command(llm):
776
855
  update_config_to_args(query="", delete_execute_file=True)
777
856
 
778
857
  source_dir = os.path.abspath(args.source_dir)
779
- logger.info(f"开始对目录 {source_dir} 中的源代码进行索引")
858
+ printer.print_text(f"开始对目录 {source_dir} 中的源代码进行索引", style="green")
780
859
  if args.project_type == "py":
781
860
  pp = PyProject(llm=llm, args=args)
782
861
  else:
@@ -791,7 +870,7 @@ def index_export(export_path: str) -> bool:
791
870
  try:
792
871
  index_path = os.path.join(project_root, ".auto-coder", "index.json")
793
872
  if not os.path.exists(index_path):
794
- console.print(f"索引文件不存在", style="bold red")
873
+ printer.print_text(Text(f"索引文件不存在. ", style="bold red"))
795
874
  return False
796
875
 
797
876
  with open(index_path, "r", encoding="utf-8") as f:
@@ -804,16 +883,16 @@ def index_export(export_path: str) -> bool:
804
883
  data["module_name"] = rel_path
805
884
  converted_data[rel_path] = data
806
885
  except ValueError:
807
- console.print(f"索引转换路径失败", style="bold yellow")
886
+ printer.print_text(Text(f"索引转换路径失败. ", style="dim yellow"))
808
887
  converted_data[abs_path] = data
809
888
 
810
889
  export_file = os.path.join(export_path, "index.json")
811
890
  with open(export_file, "w", encoding="utf-8") as f:
812
891
  json.dump(converted_data, f, indent=2)
813
- console.print(f"索引文件导出成功", style="bold green")
892
+ printer.print_text(Text(f"索引文件导出成功. ", style="bold green"))
814
893
  return True
815
894
  except Exception as err:
816
- console.print(f"索引文件导出失败", style="bold red")
895
+ printer.print_text(Text(f"索引文件导出失败: {err}", style="bold red"))
817
896
  return False
818
897
 
819
898
 
@@ -821,12 +900,10 @@ def index_import(import_path: str):
821
900
  try:
822
901
  import_file = os.path.join(import_path, "index.json")
823
902
  if not os.path.exists(import_file):
824
- console.print(f"导入索引文件不存在", style="bold red")
903
+ printer.print_text(Text(f"导入索引文件不存在", style="bold red"))
825
904
  return False
826
- # Read and convert paths
827
905
  with open(import_file, "r", encoding="utf-8") as f:
828
906
  index_data = json.load(f)
829
- # Convert relative paths to absolute
830
907
  converted_data = {}
831
908
  for rel_path, data in index_data.items():
832
909
  try:
@@ -834,12 +911,12 @@ def index_import(import_path: str):
834
911
  data["module_name"] = abs_path
835
912
  converted_data[abs_path] = data
836
913
  except Exception as err:
837
- console.print(f"索引转换路径失败: {err}", style="bold yellow")
914
+ printer.print_text(Text(f"{rel_path} 索引转换路径失败: {err}", style="dim yellow"))
838
915
  converted_data[rel_path] = data
839
916
  # Backup existing index
840
917
  index_path = os.path.join(project_root, ".auto-coder", "index.json")
841
918
  if os.path.exists(index_path):
842
- console.print(f"原索引文件不存在", style="bold yellow")
919
+ printer.print_text(Text(f"原索引文件不存在", style="bold yellow"))
843
920
  backup_path = index_path + ".bak"
844
921
  shutil.copy2(index_path, backup_path)
845
922
 
@@ -848,7 +925,7 @@ def index_import(import_path: str):
848
925
  json.dump(converted_data, f, indent=2)
849
926
  return True
850
927
  except Exception as err:
851
- console.print(f"索引文件导入失败: {err}", style="bold red")
928
+ printer.print_text(Text(f"索引文件导入失败: {err}", style="bold red"))
852
929
  return False
853
930
 
854
931
 
@@ -894,16 +971,23 @@ def index_query_command(query: str, llm: AutoLLM):
894
971
  final_files.extend(related_fiels.file_list)
895
972
 
896
973
  all_results = list({file.file_path: file for file in final_files}.values())
897
- logger.info(
898
- f"索引过滤级别: {args.index_filter_level},根据查询条件: {args.query}, 过滤后的文件数: {len(all_results)}"
974
+ printer.print_key_value(
975
+ {"索引过滤级别": f"{args.index_filter_level}", "查询条件": f"{args.query}", "过滤后的文件数": f"{len(all_results)}"},
976
+ panel=True
899
977
  )
900
978
 
901
- headers = TargetFile.model_fields.keys()
902
- table_data = wrap_text_in_table(
903
- [[getattr(file_item, name) for name in headers] for file_item in all_results]
979
+ # headers = TargetFile.model_fields.keys()
980
+ # table_data = wrap_text_in_table(
981
+ # [[getattr(file_item, name) for name in headers] for file_item in all_results]
982
+ # )
983
+ # table_output = tabulate.tabulate(table_data, headers, tablefmt="grid")
984
+ # print(table_output, flush=True)
985
+ printer.print_table_compact(
986
+ headers=["文件路径", "原因"],
987
+ data=[[_target_file.file_path, _target_file.reason] for _target_file in all_results],
988
+ title="Index Query 结果",
989
+ show_lines=True,
904
990
  )
905
- table_output = tabulate.tabulate(table_data, headers, tablefmt="grid")
906
- print(table_output, flush=True)
907
991
  return
908
992
 
909
993
 
@@ -951,7 +1035,7 @@ def convert_config_value(key, value):
951
1035
  else:
952
1036
  return value
953
1037
  else:
954
- logger.error(f"无效的配置项: {key}")
1038
+ printer.print_text(f"无效的配置项: {key}", style="red")
955
1039
  return None
956
1040
 
957
1041
 
@@ -965,7 +1049,8 @@ def update_config_to_args(query, delete_execute_file: bool = False):
965
1049
  "skip_confirm": conf.get("skip_confirm", "true") == "true",
966
1050
  "chat_model": conf.get("chat_model", ""),
967
1051
  "code_model": conf.get("code_model", ""),
968
- "auto_merge": conf.get("auto_merge", "editblock")
1052
+ "auto_merge": conf.get("auto_merge", "editblock"),
1053
+ "exclude_files": memory.get("exclude_files", [])
969
1054
  }
970
1055
  current_files = memory["current_files"]["files"]
971
1056
  yaml_config["urls"] = current_files
@@ -992,23 +1077,14 @@ def update_config_to_args(query, delete_execute_file: bool = False):
992
1077
 
993
1078
  def print_chat_history(history, max_entries=5):
994
1079
  recent_history = history[-max_entries:]
995
- table = Table(show_header=False, padding=(0, 1), expand=True, show_lines=True)
996
- # 遍历聊天记录
1080
+ data_list = []
997
1081
  for entry in recent_history:
998
1082
  role = entry["role"]
999
1083
  content = entry["content"]
1000
-
1001
- # 根据角色设置样式
1002
1084
  if role == "user":
1003
- role_text = Text("提问")
1085
+ printer.print_text(Text(content, style="bold red"))
1004
1086
  else:
1005
- role_text = Text("模型返回")
1006
- markdown_content = Markdown(content)
1007
- # 将内容和角色添加到表格中
1008
- table.add_row(role_text, markdown_content)
1009
- # 使用 Panel 包裹表格,增加美观性
1010
- panel = Panel(table, title="历史聊天记录", border_style="bold yellow")
1011
- console.print(panel)
1087
+ printer.print_markdown(content, panel=True)
1012
1088
 
1013
1089
 
1014
1090
  @prompt()
@@ -1067,13 +1143,10 @@ def chat(query: str, llm: AutoLLM):
1067
1143
  json_str = json.dumps(chat_history, ensure_ascii=False)
1068
1144
  fp.write(json_str)
1069
1145
 
1070
- console.print(
1071
- Panel(
1072
- "新会话已开始, 之前的聊天历史已存档。",
1073
- title="Session Status",
1074
- expand=False,
1075
- border_style="green",
1076
- )
1146
+ printer.print_panel(
1147
+ Text("新会话已开始, 之前的聊天历史已存档.", style="green"),
1148
+ title="Session Status",
1149
+ center=True
1077
1150
  )
1078
1151
  if not query:
1079
1152
  return
@@ -1132,7 +1205,7 @@ def chat(query: str, llm: AutoLLM):
1132
1205
  assistant_response = ""
1133
1206
 
1134
1207
  try:
1135
- with Live(Panel("", title="Response"), refresh_per_second=12) as live:
1208
+ with Live(Panel("", title="Response", style="cyan"), refresh_per_second=12) as live:
1136
1209
  for chunk in v:
1137
1210
  if chunk.choices and chunk.choices[0].delta.content:
1138
1211
  content = chunk.choices[0].delta.content
@@ -1154,7 +1227,7 @@ def chat(query: str, llm: AutoLLM):
1154
1227
  display_content = '\n'.join(lines_buffer[-MAX_HISTORY_LINES:] + [current_line])
1155
1228
 
1156
1229
  live.update(
1157
- Panel(Markdown(display_content), title="模型返回", border_style="green",
1230
+ Panel(Markdown(display_content), title="模型返回", border_style="cyan",
1158
1231
  height=min(25, live.console.height - 4))
1159
1232
  )
1160
1233
 
@@ -1164,10 +1237,10 @@ def chat(query: str, llm: AutoLLM):
1164
1237
 
1165
1238
  # 最终完整渲染
1166
1239
  live.update(
1167
- Panel(Markdown(assistant_response), title="模型返回", border_style="blue")
1240
+ Panel(Markdown(assistant_response), title="模型返回", border_style="dim blue")
1168
1241
  )
1169
1242
  except Exception as e:
1170
- logger.error(str(e))
1243
+ printer.print_panel(Text(f"{str(e)}", style="red"), title="模型返回", center=True)
1171
1244
 
1172
1245
  chat_history["ask_conversation"].append({"role": "assistant", "content": assistant_response})
1173
1246
 
@@ -1180,8 +1253,8 @@ def chat(query: str, llm: AutoLLM):
1180
1253
 
1181
1254
  def init_project():
1182
1255
  if not args.project_type:
1183
- logger.error(
1184
- "请指定项目类型。可选的项目类型包括:py|ts| 或其他文件扩展名(例如:.java,.scala), 多个扩展名可用逗号分隔。"
1256
+ printer.print_text(
1257
+ f"请指定项目类型。可选的项目类型包括:py|ts| 或文件扩展名(例如:.java,.scala), 多个扩展名逗号分隔.", style="green"
1185
1258
  )
1186
1259
  return
1187
1260
  os.makedirs(os.path.join(args.source_dir, "actions"), exist_ok=True)
@@ -1199,7 +1272,7 @@ def init_project():
1199
1272
  f.write("\nactions/")
1200
1273
  f.write("\noutput.txt")
1201
1274
 
1202
- logger.info(f"已在 {os.path.abspath(args.source_dir)} 成功初始化 autocoder-nano 项目(兼容autocoder)")
1275
+ printer.print_text(f"已在 {os.path.abspath(args.source_dir)} 成功初始化 autocoder-nano 项目", style="green")
1203
1276
  return
1204
1277
 
1205
1278
 
@@ -1234,11 +1307,11 @@ def load_include_files(config, base_path, max_depth=10, current_depth=0):
1234
1307
 
1235
1308
  for include_file in include_files:
1236
1309
  abs_include_path = resolve_include_path(base_path, include_file)
1237
- logger.info(f"正在加载 Include file: {abs_include_path}")
1310
+ printer.print_text(f"正在加载 Include file: {abs_include_path}", style="green")
1238
1311
  with open(abs_include_path, "r") as f:
1239
1312
  include_config = yaml.safe_load(f)
1240
1313
  if not include_config:
1241
- logger.info(f"Include file {abs_include_path} 为空,跳过处理。")
1314
+ printer.print_text(f"Include file {abs_include_path} 为空,跳过处理.", style="green")
1242
1315
  continue
1243
1316
  config.update(
1244
1317
  {
@@ -1254,7 +1327,7 @@ def prepare_chat_yaml():
1254
1327
  # auto_coder_main(["next", "chat_action"]) 准备聊天 yaml 文件
1255
1328
  actions_dir = os.path.join(args.source_dir, "actions")
1256
1329
  if not os.path.exists(actions_dir):
1257
- logger.warning("当前目录中未找到 actions 目录。请执行初始化 AutoCoder Nano")
1330
+ printer.print_text("当前目录中未找到 actions 目录。请执行初始化 AutoCoder Nano", style="yellow")
1258
1331
  return
1259
1332
 
1260
1333
  action_files = [
@@ -1285,7 +1358,7 @@ def prepare_chat_yaml():
1285
1358
  with open(new_file, "w") as f:
1286
1359
  f.write(content)
1287
1360
 
1288
- logger.info(f"已成功创建新的 action 文件: {new_file}")
1361
+ printer.print_text(f"已成功创建新的 action 文件: {new_file}", style="green")
1289
1362
  return
1290
1363
 
1291
1364
 
@@ -1344,9 +1417,8 @@ def coding(query: str, llm: AutoLLM):
1344
1417
  memory_file = os.path.join(memory_dir, "chat_history.json")
1345
1418
 
1346
1419
  def error_message():
1347
- console.print(
1348
- Panel("No chat history found to apply.", title="Chat History",
1349
- expand=False, border_style="yellow",)
1420
+ printer.print_panel(
1421
+ Text("No chat history found to apply.", style="yellow"), title="Chat History", center=True
1350
1422
  )
1351
1423
 
1352
1424
  if not os.path.exists(memory_file):
@@ -1379,7 +1451,7 @@ def coding(query: str, llm: AutoLLM):
1379
1451
  dispacher = Dispacher(args=args, llm=llm)
1380
1452
  dispacher.dispach()
1381
1453
  else:
1382
- logger.warning("创建新的 YAML 文件失败。")
1454
+ printer.print_text(f"创建新的 YAML 文件失败.", style="yellow")
1383
1455
 
1384
1456
  save_memory()
1385
1457
  completer.refresh_files()
@@ -1395,9 +1467,9 @@ def execute_revert():
1395
1467
  revert_result = revert_changes(repo_path, f"auto_coder_{file_name}_{md5}")
1396
1468
  if revert_result:
1397
1469
  os.remove(args.file)
1398
- logger.info(f"已成功回退最后一次 chat action 的更改,并移除 YAML 文件 {args.file}")
1470
+ printer.print_text(f"已成功回退最后一次 chat action 的更改,并移除 YAML 文件 {args.file}", style="green")
1399
1471
  else:
1400
- logger.error(f"回退文件 {args.file} 的更改失败")
1472
+ printer.print_text(f"回退文件 {args.file} 的更改失败", style="red")
1401
1473
  return
1402
1474
 
1403
1475
 
@@ -1408,29 +1480,24 @@ def revert():
1408
1480
  convert_yaml_to_config(file_path)
1409
1481
  execute_revert()
1410
1482
  else:
1411
- logger.warning("No previous chat action found to revert.")
1483
+ printer.print_text(f"No previous chat action found to revert.", style="yellow")
1412
1484
 
1413
1485
 
1414
1486
  def print_commit_info(commit_result: CommitResult):
1415
- table = Table(title="提交信息 (使用 /revert 撤销此提交)", show_header=True, header_style="bold magenta")
1416
- table.add_column("属性", style="cyan", no_wrap=True)
1417
- table.add_column("", style="green")
1418
- table.add_row("提交哈希", commit_result.commit_hash)
1419
- table.add_row("提交信息", commit_result.commit_message)
1420
- table.add_row(
1421
- "更改的文件",
1422
- "\n".join(commit_result.changed_files) if commit_result.changed_files else "No files changed"
1423
- )
1424
-
1425
- console.print(
1426
- Panel(table, expand=False, border_style="green", title="Git 提交摘要")
1487
+ printer.print_table_compact(
1488
+ data=[
1489
+ ["提交哈希", commit_result.commit_hash],
1490
+ ["提交信息", commit_result.commit_message],
1491
+ ["更改的文件", "\n".join(commit_result.changed_files) if commit_result.changed_files else "No files changed"]
1492
+ ],
1493
+ title="提交信息", headers=["属性", "值"], caption="(使用 /revert 撤销此提交)"
1427
1494
  )
1428
1495
 
1429
1496
  if commit_result.diffs:
1430
1497
  for file, diff in commit_result.diffs.items():
1431
- console.print(f"\n[bold blue]File: {file}[/bold blue]")
1498
+ printer.print_text(f"File: {file}", style="green")
1432
1499
  syntax = Syntax(diff, "diff", theme="monokai", line_numbers=True)
1433
- console.print(Panel(syntax, expand=False, border_style="yellow", title="File Diff"))
1500
+ printer.print_panel(syntax, title="File Diff", center=True)
1434
1501
 
1435
1502
 
1436
1503
  def commit_info(query: str, llm: AutoLLM):
@@ -1473,7 +1540,7 @@ def commit_info(query: str, llm: AutoLLM):
1473
1540
  # commit_message = ""
1474
1541
  commit_llm = llm
1475
1542
  commit_llm.setup_default_model_name(args.chat_model)
1476
- console.print(f"Commit 信息生成中...", style="yellow")
1543
+ printer.print_text(f"Commit 信息生成中...", style="green")
1477
1544
 
1478
1545
  try:
1479
1546
  uncommitted_changes = get_uncommitted_changes(repo_path)
@@ -1482,7 +1549,7 @@ def commit_info(query: str, llm: AutoLLM):
1482
1549
  )
1483
1550
  memory["conversation"].append({"role": "user", "content": commit_message.output})
1484
1551
  except Exception as err:
1485
- console.print(f"Commit 信息生成失败: {err}", style="red")
1552
+ printer.print_text(f"Commit 信息生成失败: {err}", style="red")
1486
1553
  return
1487
1554
 
1488
1555
  yaml_config["query"] = commit_message.output
@@ -1496,11 +1563,11 @@ def commit_info(query: str, llm: AutoLLM):
1496
1563
  commit_result = commit_changes(repo_path, f"auto_coder_nano_{file_name}_{md5}\n{commit_message}")
1497
1564
  print_commit_info(commit_result=commit_result)
1498
1565
  if commit_message:
1499
- console.print(f"Commit 成功", style="green")
1566
+ printer.print_text(f"Commit 成功", style="green")
1500
1567
  except Exception as err:
1501
1568
  import traceback
1502
1569
  traceback.print_exc()
1503
- logger.error(f"Commit 失败: {err}")
1570
+ printer.print_text(f"Commit 失败: {err}", style="red")
1504
1571
  if execute_file:
1505
1572
  os.remove(execute_file)
1506
1573
 
@@ -1545,22 +1612,14 @@ def generate_shell_command(input_text: str, llm: AutoLLM) -> str | None:
1545
1612
  update_config_to_args(query=input_text, delete_execute_file=True)
1546
1613
 
1547
1614
  try:
1548
- console.print(
1549
- Panel(
1550
- f"正在根据用户输入 {input_text} 生成 Shell 脚本...",
1551
- title="命令生成",
1552
- border_style="green",
1553
- )
1615
+ printer.print_panel(
1616
+ Text(f"正在根据用户输入 {input_text} 生成 Shell 脚本...", style="green"), title="命令生成",
1554
1617
  )
1555
1618
  llm.setup_default_model_name(args.code_model)
1556
1619
  result = _generate_shell_script.with_llm(llm).run(user_input=input_text)
1557
1620
  shell_script = extract_code(result.output)[0][1]
1558
- console.print(
1559
- Panel(
1560
- shell_script,
1561
- title="Shell 脚本",
1562
- border_style="magenta",
1563
- )
1621
+ printer.print_code(
1622
+ code=shell_script, lexer="shell", panel=True
1564
1623
  )
1565
1624
  return shell_script
1566
1625
  finally:
@@ -1591,31 +1650,31 @@ def execute_shell_command(command: str):
1591
1650
  output.append(output_line.strip())
1592
1651
  live.update(
1593
1652
  Panel(
1594
- Text("\n".join(output[-20:])),
1653
+ Text("\n".join(output[-20:]), style="green"),
1595
1654
  title="Shell 输出",
1596
- border_style="green",
1655
+ border_style="dim blue",
1597
1656
  )
1598
1657
  )
1599
1658
  if error_line:
1600
1659
  output.append(f"ERROR: {error_line.strip()}")
1601
1660
  live.update(
1602
1661
  Panel(
1603
- Text("\n".join(output[-20:])),
1662
+ Text("\n".join(output[-20:]), style="red"),
1604
1663
  title="Shell 输出",
1605
- border_style="red",
1664
+ border_style="dim blue",
1606
1665
  )
1607
1666
  )
1608
1667
  if output_line == "" and error_line == "" and process.poll() is not None:
1609
1668
  break
1610
1669
 
1611
1670
  if process.returncode != 0:
1612
- console.print(f"[bold red]命令执行失败,返回码: {process.returncode}[/bold red]")
1671
+ printer.print_text(f"命令执行失败,返回码: {process.returncode}", style="red")
1613
1672
  else:
1614
- console.print("[bold green]命令执行成功[/bold green]")
1673
+ printer.print_text(f"命令执行成功", style="green")
1615
1674
  except FileNotFoundError:
1616
- console.print(f"[bold red]未找到命令:[/bold red] [yellow]{command}[/yellow]")
1675
+ printer.print_text(f"未找到命令:", style="yellow")
1617
1676
  except subprocess.SubprocessError as e:
1618
- console.print(f"[bold red]命令执行错误:[/bold red] [yellow]{str(e)}[/yellow]")
1677
+ printer.print_text(f"命令执行错误:", style="yellow")
1619
1678
 
1620
1679
 
1621
1680
  def parse_args(input_args: Optional[List[str]] = None):
@@ -1767,10 +1826,10 @@ def configure_project_type() -> str:
1767
1826
  print_info("项目类型支持:")
1768
1827
  print_info(" - 语言后缀(例如:.py, .java, .ts)")
1769
1828
  print_info(" - 预定义类型:py(Python), ts(TypeScript/JavaScript)")
1770
- print_info("对于混合语言项目,使用逗号分隔的值。")
1829
+ print_info("对于混合语言项目,使用逗号分隔的值.")
1771
1830
  print_info("示例:'.java,.scala' 或 '.py,.ts'")
1772
1831
 
1773
- print_warning(f"如果留空,默认为 'py'。\n")
1832
+ print_warning(f"如果留空, 默认为 'py'.\n")
1774
1833
 
1775
1834
  project_type = _toolkit_prompt("请输入项目类型:", default="py", style=style).strip()
1776
1835
 
@@ -1787,45 +1846,34 @@ def configure_project_type() -> str:
1787
1846
  return project_type
1788
1847
 
1789
1848
 
1790
- def print_status(message, status):
1791
- if status == "success":
1792
- print(f"\033[32m✓ {message}\033[0m")
1793
- elif status == "warning":
1794
- print(f"\033[33m! {message}\033[0m")
1795
- elif status == "error":
1796
- print(f"\033[31m✗ {message}\033[0m")
1797
- else:
1798
- print(f" {message}")
1799
-
1800
-
1801
1849
  def initialize_system():
1802
- print(f"\n\033[1;34m🚀 正在初始化系统...\033[0m")
1850
+ printer.print_text(f"🚀 正在初始化系统...", style="green")
1803
1851
 
1804
1852
  def _init_project():
1805
1853
  first_time = False
1806
1854
  if not os.path.exists(os.path.join(args.source_dir, ".auto-coder")):
1807
1855
  first_time = True
1808
- print_status("当前目录未初始化为auto-coder项目。", "warning")
1856
+ printer.print_text("当前目录未初始化为auto-coder项目.", style="yellow")
1809
1857
  init_choice = input(f" 是否现在初始化项目?(y/n): ").strip().lower()
1810
1858
  if init_choice == "y":
1811
1859
  try:
1812
1860
  init_project()
1813
- print_status("项目初始化成功。", "success")
1861
+ printer.print_text("项目初始化成功.", style="green")
1814
1862
  except Exception as e:
1815
- print_status(f"项目初始化失败, {str(e)}", "error")
1863
+ printer.print_text(f"项目初始化失败, {str(e)}.", style="red")
1816
1864
  exit(1)
1817
1865
  else:
1818
- print_status("退出而不初始化。", "warning")
1866
+ printer.print_text("退出而不初始化.", style="yellow")
1819
1867
  exit(1)
1820
1868
 
1821
1869
  if not os.path.exists(base_persist_dir):
1822
1870
  os.makedirs(base_persist_dir, exist_ok=True)
1823
- print_status("创建目录:{}".format(base_persist_dir), "success")
1871
+ printer.print_text("创建目录:{}".format(base_persist_dir), style="green")
1824
1872
 
1825
1873
  if first_time: # 首次启动,配置项目类型
1826
1874
  configure_project_type()
1827
1875
 
1828
- print_status("项目初始化完成。", "success")
1876
+ printer.print_text("项目初始化完成.", style="green")
1829
1877
 
1830
1878
  _init_project()
1831
1879
 
@@ -1841,70 +1889,49 @@ def add_files(add_files_args: List[str]):
1841
1889
  groups_info = memory["current_files"]["groups_info"]
1842
1890
 
1843
1891
  if not add_files_args:
1844
- console.print(
1845
- Panel("请为 /add_files 命令提供参数.", title="错误", border_style="red")
1846
- )
1892
+ printer.print_panel(Text("请为 /add_files 命令提供参数.", style="red"), title="错误", center=True)
1847
1893
  return
1848
1894
 
1849
1895
  if add_files_args[0] == "/refresh": # 刷新
1850
1896
  completer.refresh_files()
1851
1897
  load_memory()
1852
- console.print(
1853
- Panel("已刷新的文件列表.", title="文件刷新", border_style="green")
1854
- )
1898
+ printer.print_panel(Text("已刷新的文件列表.", style="green"), title="文件刷新", center=True)
1855
1899
  return
1856
1900
 
1857
1901
  if add_files_args[0] == "/group":
1858
1902
  # 列出组
1859
1903
  if len(add_files_args) == 1 or (len(add_files_args) == 2 and add_files_args[1] == "list"):
1860
1904
  if not groups:
1861
- console.print(
1862
- Panel("未定义任何文件组.", title="文件组",
1863
- border_style="yellow")
1864
- )
1905
+ printer.print_panel(Text("未定义任何文件组.", style="yellow"), title="文件组", center=True)
1865
1906
  else:
1866
- table = Table(
1867
- title="已定义文件组",
1868
- show_header=True,
1869
- header_style="bold magenta",
1870
- show_lines=True,
1871
- )
1872
- table.add_column("Group Name", style="cyan", no_wrap=True)
1873
- table.add_column("Files", style="green")
1874
- table.add_column("Query Prefix", style="yellow")
1875
- table.add_column("Active", style="magenta")
1876
-
1907
+ data_list = []
1877
1908
  for i, (group_name, files) in enumerate(groups.items()):
1878
1909
  query_prefix = groups_info.get(group_name, {}).get("query_prefix", "")
1879
1910
  is_active = ("✓" if group_name in memory["current_files"]["current_groups"] else "")
1880
- table.add_row(
1911
+ data_list.append([
1881
1912
  group_name,
1882
1913
  "\n".join([os.path.relpath(f, project_root) for f in files]),
1883
1914
  query_prefix,
1884
- is_active,
1885
- end_section=(i == len(groups) - 1),
1886
- )
1887
- console.print(Panel(table, border_style="blue")) #
1915
+ is_active
1916
+ ])
1917
+ printer.print_table_compact(
1918
+ data=data_list,
1919
+ title="已定义文件组",
1920
+ headers=["Group Name", "Files", "Query Prefix", "Active"]
1921
+ )
1888
1922
  # 重置活动组
1889
1923
  elif len(add_files_args) >= 2 and add_files_args[1] == "/reset":
1890
1924
  memory["current_files"]["current_groups"] = []
1891
- console.print(
1892
- Panel(
1893
- "活动组名称已重置。如果你想清除活动文件,可使用命令 /remove_files /all .",
1894
- title="活动组重置",
1895
- border_style="green",
1896
- )
1925
+ printer.print_panel(
1926
+ Text("活动组名称已重置。如果你想清除活动文件,可使用命令 /remove_files /all .", style="green"),
1927
+ title="活动组重置", center=True
1897
1928
  )
1898
1929
  # 新增组
1899
1930
  elif len(add_files_args) >= 3 and add_files_args[1] == "/add":
1900
1931
  group_name = add_files_args[2]
1901
1932
  groups[group_name] = memory["current_files"]["files"].copy()
1902
- console.print(
1903
- Panel(
1904
- f"已将当前文件添加到组 '{group_name}' .",
1905
- title="新增组",
1906
- border_style="green",
1907
- )
1933
+ printer.print_panel(
1934
+ Text(f"已将当前文件添加到组 '{group_name}' .", style="green"), title="新增组", center=True
1908
1935
  )
1909
1936
  # 删除组
1910
1937
  elif len(add_files_args) >= 3 and add_files_args[1] == "/drop":
@@ -1915,20 +1942,12 @@ def add_files(add_files_args: List[str]):
1915
1942
  del memory["current_files"]["groups_info"][group_name]
1916
1943
  if group_name in memory["current_files"]["current_groups"]:
1917
1944
  memory["current_files"]["current_groups"].remove(group_name)
1918
- console.print(
1919
- Panel(
1920
- f"已删除组 '{group_name}'.",
1921
- title="删除组",
1922
- border_style="green",
1923
- )
1945
+ printer.print_panel(
1946
+ Text(f"已删除组 '{group_name}'.", style="green"), title="删除组", center=True
1924
1947
  )
1925
1948
  else:
1926
- console.print(
1927
- Panel(
1928
- f"组 '{group_name}' 未找到.",
1929
- title="Error",
1930
- border_style="red",
1931
- )
1949
+ printer.print_panel(
1950
+ Text(f"组 '{group_name}' 未找到.", style="red"), title="Error", center=True
1932
1951
  )
1933
1952
  # 支持多个组的合并,允许组名之间使用逗号或空格分隔
1934
1953
  elif len(add_files_args) >= 2:
@@ -1941,54 +1960,29 @@ def add_files(add_files_args: List[str]):
1941
1960
  else:
1942
1961
  missing_groups.append(group_name)
1943
1962
  if missing_groups:
1944
- console.print(
1945
- Panel(
1946
- f"未找到组: {', '.join(missing_groups)}",
1947
- title="Error",
1948
- border_style="red",
1949
- )
1963
+ printer.print_panel(
1964
+ Text(f"未找到组: {', '.join(missing_groups)}", style="red"), title="Error", center=True
1950
1965
  )
1951
1966
  if merged_files:
1952
1967
  memory["current_files"]["files"] = list(merged_files)
1953
1968
  memory["current_files"]["current_groups"] = [
1954
1969
  name for name in group_names if name in groups
1955
1970
  ]
1956
- console.print(
1957
- Panel(
1958
- f"合并来自组 {', '.join(group_names)} 的文件 .",
1959
- title="文件合并",
1960
- border_style="green",
1961
- )
1971
+ printer.print_panel(
1972
+ Text(f"合并来自组 {', '.join(group_names)} 的文件 .", style="green"), title="文件合并", center=True
1962
1973
  )
1963
- table = Table(
1974
+ printer.print_table_compact(
1975
+ data=[[os.path.relpath(f, project_root)] for f in memory["current_files"]["files"]],
1964
1976
  title="当前文件",
1965
- show_header=True,
1966
- header_style="bold magenta",
1967
- show_lines=True, # 这会在每行之间添加分割线
1977
+ headers=["File"]
1968
1978
  )
1969
- table.add_column("File", style="green")
1970
- for i, f in enumerate(memory["current_files"]["files"]):
1971
- table.add_row(
1972
- os.path.relpath(f, project_root),
1973
- end_section=(
1974
- i == len(memory["current_files"]["files"]) - 1
1975
- ), # 在最后一行之后不添加分割线
1976
- )
1977
- console.print(Panel(table, border_style="blue"))
1978
- console.print(
1979
- Panel(
1980
- f"当前组: {', '.join(memory['current_files']['current_groups'])}",
1981
- title="当前组",
1982
- border_style="green",
1983
- )
1979
+ printer.print_panel(
1980
+ Text(f"当前组: {', '.join(memory['current_files']['current_groups'])}", style="green"),
1981
+ title="当前组", center=True
1984
1982
  )
1985
1983
  elif not missing_groups:
1986
- console.print(
1987
- Panel(
1988
- "指定组中没有文件.",
1989
- title="未添加任何文件",
1990
- border_style="yellow",
1991
- )
1984
+ printer.print_panel(
1985
+ Text(f"指定组中没有文件.", style="yellow"), title="未添加任何文件", center=True
1992
1986
  )
1993
1987
 
1994
1988
  else:
@@ -1998,26 +1992,14 @@ def add_files(add_files_args: List[str]):
1998
1992
  files_to_add = [f for f in matched_files if f not in existing_files]
1999
1993
  if files_to_add:
2000
1994
  memory["current_files"]["files"].extend(files_to_add)
2001
- table = Table(
1995
+ printer.print_table_compact(
1996
+ data=[[os.path.relpath(f, project_root)] for f in files_to_add],
2002
1997
  title="新增文件",
2003
- show_header=True,
2004
- header_style="bold magenta",
2005
- show_lines=True, # 这会在每行之间添加分割线
1998
+ headers=["文件"]
2006
1999
  )
2007
- table.add_column("File", style="green")
2008
- for i, f in enumerate(files_to_add):
2009
- table.add_row(
2010
- os.path.relpath(f, project_root),
2011
- end_section=(i == len(files_to_add) - 1), # 在最后一行之后不添加分割线
2012
- )
2013
- console.print(Panel(table, border_style="green"))
2014
2000
  else:
2015
- console.print(
2016
- Panel(
2017
- "所有指定文件已存在于当前会话中,或者未找到匹配的文件.",
2018
- title="未新增文件",
2019
- border_style="yellow",
2020
- )
2001
+ printer.print_panel(
2002
+ Text(f"所有指定文件已存在于当前会话中,或者未找到匹配的文件.", style="yellow"), title="未新增文件", center=True
2021
2003
  )
2022
2004
 
2023
2005
  completer.update_current_files(memory["current_files"]["files"])
@@ -2028,7 +2010,7 @@ def remove_files(file_names: List[str]):
2028
2010
  if "/all" in file_names:
2029
2011
  memory["current_files"]["files"] = []
2030
2012
  memory["current_files"]["current_groups"] = []
2031
- console.print(Panel("已移除所有文件。", title="文件移除", border_style="green"))
2013
+ printer.print_panel("已移除所有文件", title="文件移除", center=True)
2032
2014
  else:
2033
2015
  removed_files = []
2034
2016
  for file in memory["current_files"]["files"]:
@@ -2040,13 +2022,13 @@ def remove_files(file_names: List[str]):
2040
2022
  memory["current_files"]["files"].remove(file)
2041
2023
 
2042
2024
  if removed_files:
2043
- table = Table(title="文件移除", show_header=True, header_style="bold magenta")
2044
- table.add_column("File", style="green")
2045
- for f in removed_files:
2046
- table.add_row(os.path.relpath(f, project_root))
2047
- console.print(Panel(table, border_style="green"))
2025
+ printer.print_table_compact(
2026
+ data=[[os.path.relpath(f, project_root)] for f in removed_files],
2027
+ title="文件移除",
2028
+ headers=["File"]
2029
+ )
2048
2030
  else:
2049
- console.print(Panel("未移除任何文件。", title="未移除文件", border_style="yellow"))
2031
+ printer.print_panel("未移除任何文件", title="未移除文件", border_style="dim yellow", center=True)
2050
2032
  completer.update_current_files(memory["current_files"]["files"])
2051
2033
  save_memory()
2052
2034
 
@@ -2055,21 +2037,17 @@ def list_files():
2055
2037
  current_files = memory["current_files"]["files"]
2056
2038
 
2057
2039
  if current_files:
2058
- table = Table(
2059
- title="当前活跃文件", show_header=True, header_style="bold magenta"
2040
+ printer.print_table_compact(
2041
+ data=[[os.path.relpath(file, project_root)] for file in current_files],
2042
+ title="当前活跃文件",
2043
+ headers=["File"]
2060
2044
  )
2061
- table.add_column("File", style="green")
2062
- for file in current_files:
2063
- table.add_row(os.path.relpath(file, project_root))
2064
- console.print(Panel(table, border_style="blue"))
2065
2045
  else:
2066
- console.print(Panel("当前会话中无文件。", title="当前文件", border_style="yellow"))
2046
+ printer.print_panel("当前会话中无文件。", title="当前文件", center=True)
2067
2047
 
2068
2048
 
2069
2049
  def print_conf(content: Dict[str, Any]):
2070
- table = Table(title=f"[italic]使用 /conf <key>:<value> 修改这些设置[/italic]", expand=True, show_lines=True)
2071
- table.add_column("键", style="cyan", justify="right", width=30, no_wrap=True)
2072
- table.add_column("值", style="green", justify="left", width=50, no_wrap=True)
2050
+ data_list = []
2073
2051
  for key in sorted(content.keys()):
2074
2052
  value = content[key]
2075
2053
  # Format value based on type
@@ -2081,31 +2059,32 @@ def print_conf(content: Dict[str, Any]):
2081
2059
  formatted_value = Text(str(value), style="bright_cyan")
2082
2060
  else:
2083
2061
  formatted_value = Text(str(value), style="green")
2084
- table.add_row(str(key), formatted_value)
2085
- console.print(table)
2062
+ data_list.append([str(key), formatted_value])
2063
+ printer.print_table_compact(
2064
+ data=data_list,
2065
+ title="Conf 配置",
2066
+ headers=["键", "值"],
2067
+ caption="使用 /conf <key>:<value> 修改这些设置"
2068
+ )
2086
2069
 
2087
2070
 
2088
2071
  def print_models(content: Dict[str, Any]):
2089
- table = Table(title="模型", expand=True, show_lines=True)
2090
- table.add_column("Name", style="cyan", width=40, no_wrap=False)
2091
- table.add_column("Model Name", style="magenta", width=30, overflow="fold")
2092
- table.add_column("Base URL", style="white", width=50, overflow="fold")
2072
+ data_list = []
2093
2073
  if content:
2094
2074
  for name in content:
2095
- table.add_row(
2096
- name,
2097
- content[name].get("model", ""),
2098
- content[name].get("base_url", "")
2099
- )
2075
+ data_list.append([name, content[name].get("model", ""), content[name].get("base_url", "")])
2100
2076
  else:
2101
- table.add_row("", "", "")
2102
- console.print(table)
2077
+ data_list.append(["", "", ""])
2078
+ printer.print_table_compact(
2079
+ headers=["Name", "Model Name", "Base URL"],
2080
+ title="模型列表",
2081
+ data=data_list,
2082
+ show_lines=True,
2083
+ expand=True
2084
+ )
2103
2085
 
2104
2086
 
2105
2087
  def check_models(content: Dict[str, Any], llm: AutoLLM):
2106
-
2107
- status_info = {}
2108
-
2109
2088
  def _check_single_llm(model):
2110
2089
  _start_time = time.monotonic()
2111
2090
  try:
@@ -2119,25 +2098,21 @@ def check_models(content: Dict[str, Any], llm: AutoLLM):
2119
2098
  except Exception as e:
2120
2099
  return False, str(e)
2121
2100
 
2122
- table = Table(title="模型状态检测", show_header=True, header_style="bold magenta")
2123
- table.add_column("模型", style="cyan")
2124
- table.add_column("状态", justify="center")
2125
- table.add_column("延迟", justify="right", style="green")
2101
+ data_list = []
2126
2102
  if content:
2127
2103
  for name in content:
2128
- logger.info(f"正在测试 {name} 模型")
2129
2104
  attempt_ok, attempt_latency = _check_single_llm(name)
2130
2105
  if attempt_ok:
2131
- table.add_row(
2132
- name, Text("✓", style="green"), f"{attempt_latency:.2f}s"
2133
- )
2106
+ data_list.append([name, Text("✓", style="green"), f"{attempt_latency:.2f}s"])
2134
2107
  else:
2135
- table.add_row(
2136
- "✗", Text("✓", style="red"), "-"
2137
- )
2108
+ data_list.append([name, Text("✗", style="red"), "-"])
2138
2109
  else:
2139
- table.add_row("", "", "")
2140
- console.print(table)
2110
+ data_list.append(["", "", ""])
2111
+ printer.print_table_compact(
2112
+ headers=["模型名称", "状态", "延迟情况"],
2113
+ title="模型状态检测",
2114
+ data=data_list
2115
+ )
2141
2116
 
2142
2117
 
2143
2118
  def manage_models(models_args, models_data, llm: AutoLLM):
@@ -2155,30 +2130,30 @@ def manage_models(models_args, models_data, llm: AutoLLM):
2155
2130
  elif models_args[0] == "/add_model":
2156
2131
  add_model_args = models_args[1:]
2157
2132
  add_model_info = {item.split('=')[0]: item.split('=')[1] for item in add_model_args if item}
2158
- _name = add_model_info["name"]
2159
- logger.info(f"正在为 {_name} 更新缓存信息")
2160
- if _name not in memory["models"]:
2161
- memory["models"][_name] = {
2133
+ mn = add_model_info["name"]
2134
+ printer.print_text(f"正在为 {mn} 更新缓存信息", style="green")
2135
+ if mn not in memory["models"]:
2136
+ memory["models"][mn] = {
2162
2137
  "base_url": add_model_info["base_url"],
2163
2138
  "api_key": add_model_info["api_key"],
2164
2139
  "model": add_model_info["model"]
2165
2140
  }
2166
2141
  else:
2167
- logger.error(f"{_name} 已经存在, 请执行 /models /remove <name> 进行删除")
2168
- logger.info(f"正在部署 {_name} 模型")
2169
- llm.setup_sub_client(_name, add_model_info["api_key"], add_model_info["base_url"], add_model_info["model"])
2142
+ printer.print_text(f"{mn} 已经存在, 请执行 /models /remove <name> 进行删除", style="red")
2143
+ printer.print_text(f"正在部署 {mn} 模型", style="green")
2144
+ llm.setup_sub_client(mn, add_model_info["api_key"], add_model_info["base_url"], add_model_info["model"])
2170
2145
  elif models_args[0] == "/remove":
2171
- remove_model_name = models_args[1]
2172
- logger.info(f"正在清理 {remove_model_name} 缓存信息")
2173
- if remove_model_name in memory["models"]:
2174
- del memory["models"][remove_model_name]
2175
- logger.info(f"正在卸载 {remove_model_name} 模型")
2176
- if llm.get_sub_client(remove_model_name):
2177
- llm.remove_sub_client(remove_model_name)
2178
- if remove_model_name == memory["conf"]["chat_model"]:
2179
- logger.warning(f"当前首选 Chat 模型 {remove_model_name} 已被删除, 请立即 /conf chat_model: 调整 !!!")
2180
- if remove_model_name == memory["conf"]["code_model"]:
2181
- logger.warning(f"当前首选 Code 模型 {remove_model_name} 已被删除, 请立即 /conf code_model: 调整 !!!")
2146
+ rmn = models_args[1]
2147
+ printer.print_text(f"正在清理 {rmn} 缓存信息", style="green")
2148
+ if rmn in memory["models"]:
2149
+ del memory["models"][rmn]
2150
+ printer.print_text(f"正在卸载 {rmn} 模型", style="green")
2151
+ if llm.get_sub_client(rmn):
2152
+ llm.remove_sub_client(rmn)
2153
+ if rmn == memory["conf"]["chat_model"]:
2154
+ printer.print_text(f"当前首选Chat模型 {rmn} 已被删除, 请立即 /conf chat_model: 调整", style="yellow")
2155
+ if rmn == memory["conf"]["code_model"]:
2156
+ printer.print_text(f"当前首选Code模型 {rmn} 已被删除, 请立即 /conf code_model: 调整", style="yellow")
2182
2157
 
2183
2158
 
2184
2159
  def configure_project_model():
@@ -2229,7 +2204,7 @@ def configure_project_model():
2229
2204
  model_num = input(f" 请选择您想使用的模型供应商编号(1-6): ").strip().lower()
2230
2205
 
2231
2206
  if int(model_num) < 1 or int(model_num) > 7:
2232
- print_status(f"请选择 1-7", "error")
2207
+ printer.print_text("请选择 1-7", style="red")
2233
2208
  exit(1)
2234
2209
 
2235
2210
  if model_num == "7":
@@ -2309,7 +2284,7 @@ def is_old_version():
2309
2284
  不再使用 current_chat_model 和 current_chat_model
2310
2285
  """
2311
2286
  if 'current_chat_model' in memory['conf'] and 'current_code_model' in memory['conf']:
2312
- logger.warning(f"您当前版本使用的版本偏低, 正在进行配置兼容性处理")
2287
+ printer.print_text(f"您当前使用的版本偏低 {__version__}, 正在进行配置兼容性处理", style="yellow")
2313
2288
  memory['conf']['chat_model'] = memory['conf']['current_chat_model']
2314
2289
  memory['conf']['code_model'] = memory['conf']['current_code_model']
2315
2290
  del memory['conf']['current_chat_model']
@@ -2331,30 +2306,30 @@ def main():
2331
2306
  _model_pass = input(f" 是否跳过模型配置(y/n): ").strip().lower()
2332
2307
  if _model_pass == "n":
2333
2308
  m1, m2, m3, m4 = configure_project_model()
2334
- print_status(f"正在更新缓存...", "warning")
2309
+ printer.print_text("正在更新缓存...", style="yellow")
2335
2310
  memory["conf"]["chat_model"] = m1
2336
2311
  memory["conf"]["code_model"] = m1
2337
2312
  memory["models"][m1] = {"base_url": m3, "api_key": m4, "model": m2}
2338
- print_status(f"供应商配置已成功完成!后续你可以使用 /models 命令, 查看, 新增和修改所有模型", "success")
2313
+ printer.print_text(f"供应商配置已成功完成!后续你可以使用 /models 命令, 查看, 新增和修改所有模型", style="green")
2339
2314
  else:
2340
- print_status("你已跳过模型配置,后续请使用 /models /add_model 添加模型...", "error")
2341
- print_status("添加示例 /models /add_model name=xxx base_url=xxx api_key=xxxx model=xxxxx", "error")
2315
+ printer.print_text("你已跳过模型配置,后续请使用 /models /add_model 添加模型...", style="yellow")
2316
+ printer.print_text("添加示例 /models /add_model name=& base_url=& api_key=& model=&", style="yellow")
2342
2317
 
2343
2318
  auto_llm = AutoLLM() # 创建模型
2344
2319
  if len(memory["models"]) > 0:
2345
2320
  for _model_name in memory["models"]:
2346
- print_status(f"正在部署 {_model_name} 模型...", "warning")
2321
+ printer.print_text(f"正在部署 {_model_name} 模型...", style="green")
2347
2322
  auto_llm.setup_sub_client(_model_name,
2348
2323
  memory["models"][_model_name]["api_key"],
2349
2324
  memory["models"][_model_name]["base_url"],
2350
2325
  memory["models"][_model_name]["model"])
2351
2326
 
2352
- print_status("初始化完成。", "success")
2327
+ printer.print_text("初始化完成.", style="green")
2353
2328
 
2354
2329
  if memory["conf"]["chat_model"] not in memory["models"].keys():
2355
- print_status("首选 Chat 模型与部署模型不一致, 请使用 /conf chat_model:xxx 设置", "error")
2330
+ printer.print_text("首选 Chat 模型与部署模型不一致, 请使用 /conf chat_model:& 设置", style="red")
2356
2331
  if memory["conf"]["code_model"] not in memory["models"].keys():
2357
- print_status("首选 Code 模型与部署模型不一致, 请使用 /conf code_model:xxx 设置", "error")
2332
+ printer.print_text("首选 Code 模型与部署模型不一致, 请使用 /conf code_model:& 设置", style="red")
2358
2333
 
2359
2334
  MODES = {
2360
2335
  "normal": "正常模式",
@@ -2402,9 +2377,13 @@ def main():
2402
2377
  key_bindings=kb,
2403
2378
  bottom_toolbar=get_bottom_toolbar,
2404
2379
  )
2405
- print(f"""\033[1;32mAutoCoder Nano v{__version__}\033[0m""")
2406
- print("\033[1;34m输入 /help 可以查看可用的命令.\033[0m\n")
2407
- # show_help()
2380
+ printer.print_key_value(
2381
+ {
2382
+ "AutoCoder Nano": f"v{__version__}",
2383
+ "Url": "https://github.com/w4n9H/autocoder-nano",
2384
+ "Help": "输入 /help 可以查看可用的命令."
2385
+ }
2386
+ )
2408
2387
 
2409
2388
  style = Style.from_dict(
2410
2389
  {
@@ -2509,6 +2488,12 @@ def main():
2509
2488
  print(f"{memory['mode']} [{MODES[memory['mode']]}]")
2510
2489
  else:
2511
2490
  memory["mode"] = conf
2491
+ elif user_input.startswith("/exclude_dirs"):
2492
+ dir_names = user_input[len("/exclude_dirs"):].strip().split(",")
2493
+ exclude_dirs(dir_names)
2494
+ elif user_input.startswith("/exclude_files"):
2495
+ query = user_input[len("/exclude_files"):].strip()
2496
+ exclude_files(query)
2512
2497
  else:
2513
2498
  command = user_input
2514
2499
  if user_input.startswith("/shell"):