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

Files changed (58) hide show
  1. {auto_coder-0.1.263.dist-info → auto_coder-0.1.265.dist-info}/METADATA +1 -1
  2. {auto_coder-0.1.263.dist-info → auto_coder-0.1.265.dist-info}/RECORD +58 -55
  3. autocoder/agent/planner.py +4 -4
  4. autocoder/auto_coder.py +26 -21
  5. autocoder/auto_coder_server.py +7 -7
  6. autocoder/chat_auto_coder.py +203 -98
  7. autocoder/commands/auto_command.py +81 -4
  8. autocoder/commands/tools.py +48 -50
  9. autocoder/common/__init__.py +6 -1
  10. autocoder/common/auto_coder_lang.py +41 -3
  11. autocoder/common/code_auto_generate.py +3 -3
  12. autocoder/common/code_auto_generate_diff.py +12 -15
  13. autocoder/common/code_auto_generate_editblock.py +3 -3
  14. autocoder/common/code_auto_generate_strict_diff.py +3 -3
  15. autocoder/common/code_auto_merge.py +23 -3
  16. autocoder/common/code_auto_merge_diff.py +29 -4
  17. autocoder/common/code_auto_merge_editblock.py +25 -5
  18. autocoder/common/code_auto_merge_strict_diff.py +26 -6
  19. autocoder/common/code_modification_ranker.py +65 -3
  20. autocoder/common/command_completer.py +3 -0
  21. autocoder/common/command_generator.py +24 -8
  22. autocoder/common/command_templates.py +2 -2
  23. autocoder/common/conf_import_export.py +105 -0
  24. autocoder/common/conf_validator.py +7 -1
  25. autocoder/common/context_pruner.py +305 -0
  26. autocoder/common/files.py +41 -2
  27. autocoder/common/image_to_page.py +11 -11
  28. autocoder/common/index_import_export.py +38 -18
  29. autocoder/common/mcp_hub.py +3 -3
  30. autocoder/common/mcp_server.py +2 -2
  31. autocoder/common/shells.py +254 -13
  32. autocoder/common/stats_panel.py +126 -0
  33. autocoder/dispacher/actions/action.py +6 -18
  34. autocoder/dispacher/actions/copilot.py +2 -2
  35. autocoder/dispacher/actions/plugins/action_regex_project.py +1 -3
  36. autocoder/dispacher/actions/plugins/action_translate.py +1 -1
  37. autocoder/index/entry.py +8 -2
  38. autocoder/index/filter/normal_filter.py +13 -2
  39. autocoder/index/filter/quick_filter.py +127 -13
  40. autocoder/index/index.py +8 -7
  41. autocoder/models.py +2 -2
  42. autocoder/pyproject/__init__.py +5 -5
  43. autocoder/rag/cache/byzer_storage_cache.py +4 -4
  44. autocoder/rag/cache/file_monitor_cache.py +2 -2
  45. autocoder/rag/cache/simple_cache.py +4 -4
  46. autocoder/rag/long_context_rag.py +2 -2
  47. autocoder/regexproject/__init__.py +3 -2
  48. autocoder/suffixproject/__init__.py +3 -2
  49. autocoder/tsproject/__init__.py +3 -2
  50. autocoder/utils/conversation_store.py +1 -1
  51. autocoder/utils/operate_config_api.py +3 -3
  52. autocoder/utils/project_structure.py +258 -3
  53. autocoder/utils/thread_utils.py +6 -1
  54. autocoder/version.py +1 -1
  55. {auto_coder-0.1.263.dist-info → auto_coder-0.1.265.dist-info}/LICENSE +0 -0
  56. {auto_coder-0.1.263.dist-info → auto_coder-0.1.265.dist-info}/WHEEL +0 -0
  57. {auto_coder-0.1.263.dist-info → auto_coder-0.1.265.dist-info}/entry_points.txt +0 -0
  58. {auto_coder-0.1.263.dist-info → auto_coder-0.1.265.dist-info}/top_level.txt +0 -0
@@ -134,6 +134,7 @@ commands = [
134
134
  "/index/export",
135
135
  "/index/import",
136
136
  "/exclude_dirs",
137
+ "/exclude_files",
137
138
  "/help",
138
139
  "/shell",
139
140
  "/voice_input",
@@ -145,6 +146,8 @@ commands = [
145
146
  "/mcp",
146
147
  "/models",
147
148
  "/auto",
149
+ "/conf/export",
150
+ "/conf/import",
148
151
  ]
149
152
 
150
153
 
@@ -268,7 +271,7 @@ def initialize_system(args):
268
271
  from autocoder.utils.model_provider_selector import ModelProviderSelector
269
272
  from autocoder import models as models_module
270
273
  print(f"\n\033[1;34m{get_message('initializing')}\033[0m")
271
-
274
+
272
275
  first_time = [False]
273
276
  configure_success = [False]
274
277
 
@@ -391,7 +394,7 @@ def initialize_system(args):
391
394
  except subprocess.CalledProcessError:
392
395
  print_status(get_message("deploy_fail"), "error")
393
396
  return
394
-
397
+
395
398
 
396
399
  deploy_cmd = [
397
400
  "byzerllm",
@@ -604,7 +607,7 @@ def get_symbol_list() -> List[SymbolItem]:
604
607
  index_file = os.path.join(".auto-coder", "index.json")
605
608
 
606
609
  if os.path.exists(index_file):
607
- with open(index_file, "r") as file:
610
+ with open(index_file, "r",encoding="utf-8") as file:
608
611
  index_data = json.load(file)
609
612
  else:
610
613
  index_data = {}
@@ -641,7 +644,7 @@ def get_symbol_list() -> List[SymbolItem]:
641
644
 
642
645
 
643
646
  def save_memory():
644
- with open(os.path.join(base_persist_dir, "memory.json"), "w") as f:
647
+ with open(os.path.join(base_persist_dir, "memory.json"), "w",encoding="utf-8") as f:
645
648
  json.dump(memory, f, indent=2, ensure_ascii=False)
646
649
  load_memory()
647
650
 
@@ -650,7 +653,7 @@ def load_memory():
650
653
  global memory
651
654
  memory_path = os.path.join(base_persist_dir, "memory.json")
652
655
  if os.path.exists(memory_path):
653
- with open(memory_path, "r") as f:
656
+ with open(memory_path, "r", encoding="utf-8") as f:
654
657
  memory = json.load(f)
655
658
  completer.update_current_files(memory["current_files"]["files"])
656
659
 
@@ -672,12 +675,12 @@ completer = CommandCompleter(commands,
672
675
 
673
676
  def print_conf(content:Dict[str,Any]):
674
677
  """Display configuration dictionary in a Rich table format with enhanced visual styling.
675
-
678
+
676
679
  Args:
677
680
  conf (Dict[str, Any]): Configuration dictionary to display
678
681
  """
679
682
  console = Console()
680
-
683
+
681
684
  # Create a styled table with rounded borders
682
685
  table = Table(
683
686
  show_header=True,
@@ -687,11 +690,11 @@ def print_conf(content:Dict[str,Any]):
687
690
  border_style="blue",
688
691
  show_lines=True
689
692
  )
690
-
693
+
691
694
  # Add columns with explicit width and alignment
692
695
  table.add_column(get_message("conf_key"), style="cyan", justify="right", width=30, no_wrap=False)
693
696
  table.add_column(get_message("conf_value"), style="green", justify="left", width=50, no_wrap=False)
694
-
697
+
695
698
  # Sort keys for consistent display
696
699
  for key in sorted(content.keys()):
697
700
  value = content[key]
@@ -704,9 +707,9 @@ def print_conf(content:Dict[str,Any]):
704
707
  formatted_value = Text(str(value), style="bright_cyan")
705
708
  else:
706
709
  formatted_value = Text(str(value), style="green")
707
-
710
+
708
711
  table.add_row(str(key), formatted_value)
709
-
712
+
710
713
  # Add padding and print with a panel
711
714
  console.print(Panel(
712
715
  table,
@@ -742,7 +745,7 @@ def revert():
742
745
 
743
746
 
744
747
  def add_files(args: List[str]):
745
-
748
+
746
749
  result_manager = ResultManager()
747
750
  if "groups" not in memory["current_files"]:
748
751
  memory["current_files"]["groups"] = {}
@@ -837,7 +840,7 @@ def add_files(args: List[str]):
837
840
  )
838
841
  result_manager.append(content=f"Added group '{group_name}' with current files.",
839
842
  meta={"action": "add_files","success":True, "input":{ "args": args}})
840
-
843
+
841
844
  elif len(args) >= 3 and args[1] == "/drop":
842
845
  group_name = args[2]
843
846
  if group_name in groups:
@@ -1093,7 +1096,7 @@ def ask(query: str):
1093
1096
 
1094
1097
  execute_file = os.path.join("actions", f"{uuid.uuid4()}.yml")
1095
1098
 
1096
- with open(os.path.join(execute_file), "w") as f:
1099
+ with open(os.path.join(execute_file), "w",encoding="utf-8") as f:
1097
1100
  f.write(yaml_content)
1098
1101
 
1099
1102
  def execute_ask():
@@ -1141,7 +1144,7 @@ def get_llm_friendly_package_docs(
1141
1144
  if return_paths:
1142
1145
  docs.append(file_path)
1143
1146
  else:
1144
- with open(file_path, "r") as f:
1147
+ with open(file_path, "r",encoding="utf-8") as f:
1145
1148
  docs.append(f.read())
1146
1149
 
1147
1150
  return docs
@@ -1151,7 +1154,7 @@ def convert_yaml_to_config(yaml_file: str):
1151
1154
  from autocoder.auto_coder import AutoCoderArgs, load_include_files, Template
1152
1155
 
1153
1156
  args = AutoCoderArgs()
1154
- with open(yaml_file, "r") as f:
1157
+ with open(yaml_file, "r",encoding="utf-8") as f:
1155
1158
  config = yaml.safe_load(f)
1156
1159
  config = load_include_files(config, yaml_file)
1157
1160
  for key, value in config.items():
@@ -1241,7 +1244,7 @@ def mcp(query: str):
1241
1244
 
1242
1245
  temp_yaml = os.path.join("actions", f"{uuid.uuid4()}.yml")
1243
1246
  try:
1244
- with open(temp_yaml, "w") as f:
1247
+ with open(temp_yaml, "w",encoding="utf-8") as f:
1245
1248
  f.write(convert_yaml_config_to_str(yaml_config=yaml_config))
1246
1249
  args = convert_yaml_to_config(temp_yaml)
1247
1250
  finally:
@@ -1272,14 +1275,14 @@ def mcp(query: str):
1272
1275
  os.makedirs(mcp_dir, exist_ok=True)
1273
1276
  timestamp = str(int(time.time()))
1274
1277
  file_path = os.path.join(mcp_dir, f"{timestamp}.md")
1275
-
1278
+
1276
1279
  # Format response as markdown
1277
1280
  markdown_content = response.result
1278
-
1281
+
1279
1282
  # Save to file
1280
1283
  with open(file_path, "w", encoding="utf-8") as f:
1281
1284
  f.write(markdown_content)
1282
-
1285
+
1283
1286
  console = Console()
1284
1287
  console.print(
1285
1288
  Panel(
@@ -1310,7 +1313,7 @@ def code_next(query: str):
1310
1313
 
1311
1314
  temp_yaml = os.path.join("actions", f"{uuid.uuid4()}.yml")
1312
1315
  try:
1313
- with open(temp_yaml, "w") as f:
1316
+ with open(temp_yaml, "w",encoding="utf-8") as f:
1314
1317
  f.write(convert_yaml_config_to_str(yaml_config=yaml_config))
1315
1318
  args = convert_yaml_to_config(temp_yaml)
1316
1319
  finally:
@@ -1417,20 +1420,20 @@ def commit(query: str):
1417
1420
  # 临时保存yaml文件,然后读取yaml文件,转换为args
1418
1421
  temp_yaml = os.path.join("actions", f"{uuid.uuid4()}.yml")
1419
1422
  try:
1420
- with open(temp_yaml, "w") as f:
1423
+ with open(temp_yaml, "w",encoding="utf-8") as f:
1421
1424
  f.write(convert_yaml_config_to_str(
1422
1425
  yaml_config=yaml_config))
1423
1426
  args = convert_yaml_to_config(temp_yaml)
1424
1427
  finally:
1425
1428
  if os.path.exists(temp_yaml):
1426
1429
  os.remove(temp_yaml)
1427
-
1430
+
1428
1431
  target_model = args.commit_model or args.model
1429
1432
  llm = get_single_llm(target_model, product_mode)
1430
1433
  printer = Printer()
1431
1434
  printer.print_in_terminal("commit_generating", style="yellow", model_name=target_model)
1432
1435
  commit_message = ""
1433
-
1436
+
1434
1437
  try:
1435
1438
  uncommitted_changes = git_utils.get_uncommitted_changes(".")
1436
1439
  commit_message = git_utils.generate_commit_message.with_llm(llm).run(
@@ -1441,10 +1444,10 @@ def commit(query: str):
1441
1444
  except Exception as e:
1442
1445
  printer.print_in_terminal("commit_failed", style="red", error=str(e), model_name=target_model)
1443
1446
  return
1444
-
1447
+
1445
1448
  yaml_config["query"] = commit_message
1446
1449
  yaml_content = convert_yaml_config_to_str(yaml_config=yaml_config)
1447
- with open(os.path.join(execute_file), "w") as f:
1450
+ with open(os.path.join(execute_file), "w",encoding="utf-8") as f:
1448
1451
  f.write(yaml_content)
1449
1452
 
1450
1453
  file_content = open(execute_file).read()
@@ -1504,6 +1507,7 @@ def coding(query: str):
1504
1507
  "silence": conf.get("silence", "true") == "true",
1505
1508
  "include_project_structure": conf.get("include_project_structure", "true")
1506
1509
  == "true",
1510
+ "exclude_files": conf.get("exclude_files", []),
1507
1511
  }
1508
1512
 
1509
1513
  yaml_config["context"] = ""
@@ -1513,14 +1517,14 @@ def coding(query: str):
1513
1517
  converted_value = convert_config_value(key, value)
1514
1518
  if converted_value is not None:
1515
1519
  yaml_config[key] = converted_value
1516
-
1520
+
1517
1521
  yaml_config["urls"] = current_files + get_llm_friendly_package_docs(
1518
1522
  return_paths=True
1519
1523
  )
1520
1524
 
1521
1525
  if conf.get("enable_global_memory", "true") in ["true", "True",True]:
1522
1526
  yaml_config["urls"] += get_global_memory_file_paths()
1523
-
1527
+
1524
1528
  # handle image
1525
1529
  v = Image.convert_image_paths_from(query)
1526
1530
  yaml_config["query"] = v
@@ -1559,7 +1563,7 @@ def coding(query: str):
1559
1563
  error_message()
1560
1564
  return
1561
1565
 
1562
- with open(memory_file, "r") as f:
1566
+ with open(memory_file, "r",encoding="utf-8") as f:
1563
1567
  chat_history = json.load(f)
1564
1568
 
1565
1569
  if not chat_history["ask_conversation"]:
@@ -1583,7 +1587,7 @@ def coding(query: str):
1583
1587
  md5 = hashlib.md5(yaml_content.encode("utf-8")).hexdigest()
1584
1588
 
1585
1589
  execute_file = os.path.join("actions", latest_yaml_file)
1586
- with open(os.path.join(execute_file), "w") as f:
1590
+ with open(os.path.join(execute_file), "w",encoding="utf-8") as f:
1587
1591
  f.write(yaml_content)
1588
1592
 
1589
1593
  def execute_chat():
@@ -1632,6 +1636,7 @@ def chat(query: str):
1632
1636
  "skip_build_index": conf.get("skip_build_index", "true") == "true",
1633
1637
  "skip_confirm": conf.get("skip_confirm", "true") == "true",
1634
1638
  "silence": conf.get("silence", "true") == "true",
1639
+ "exclude_files": conf.get("exclude_files", []),
1635
1640
  }
1636
1641
 
1637
1642
  current_files = memory["current_files"]["files"] + get_llm_friendly_package_docs(
@@ -1667,7 +1672,7 @@ def chat(query: str):
1667
1672
  if "/save" in query:
1668
1673
  yaml_config["action"].append("save")
1669
1674
  query = query.replace("/save", "", 1).strip()
1670
-
1675
+
1671
1676
  if "/review" in query and "/commit" in query:
1672
1677
  yaml_config["action"].append("review_commit")
1673
1678
  query = query.replace("/review", "", 1).replace("/commit", "", 1).strip()
@@ -1698,7 +1703,7 @@ def chat(query: str):
1698
1703
 
1699
1704
  execute_file = os.path.join("actions", f"{uuid.uuid4()}.yml")
1700
1705
 
1701
- with open(os.path.join(execute_file), "w") as f:
1706
+ with open(os.path.join(execute_file), "w",encoding="utf-8") as f:
1702
1707
  f.write(yaml_content)
1703
1708
 
1704
1709
  def execute_ask():
@@ -1722,7 +1727,7 @@ def summon(query: str):
1722
1727
  for file in current_files:
1723
1728
  if os.path.exists(file):
1724
1729
  try:
1725
- with open(file, "r") as f:
1730
+ with open(file, "r",encoding="utf-8") as f:
1726
1731
  content = f.read()
1727
1732
  s = f"##File: {file}\n{content}\n\n"
1728
1733
  file_contents.append(s)
@@ -1758,7 +1763,7 @@ def summon(query: str):
1758
1763
 
1759
1764
  execute_file = os.path.join("actions", f"{uuid.uuid4()}.yml")
1760
1765
 
1761
- with open(os.path.join(execute_file), "w") as f:
1766
+ with open(os.path.join(execute_file), "w",encoding="utf-8") as f:
1762
1767
  f.write(yaml_content)
1763
1768
 
1764
1769
  def execute_summon():
@@ -1805,7 +1810,7 @@ def design(query: str):
1805
1810
 
1806
1811
  execute_file = os.path.join("actions", f"{uuid.uuid4()}.yml")
1807
1812
 
1808
- with open(os.path.join(execute_file), "w") as f:
1813
+ with open(os.path.join(execute_file), "w",encoding="utf-8") as f:
1809
1814
  f.write(yaml_content)
1810
1815
 
1811
1816
  def execute_design():
@@ -1834,7 +1839,7 @@ def voice_input():
1834
1839
 
1835
1840
  execute_file = os.path.join("actions", f"{uuid.uuid4()}.yml")
1836
1841
 
1837
- with open(os.path.join(execute_file), "w") as f:
1842
+ with open(os.path.join(execute_file), "w",encoding="utf-8") as f:
1838
1843
  f.write(yaml_content)
1839
1844
 
1840
1845
  def execute_voice2text_command():
@@ -1842,7 +1847,7 @@ def voice_input():
1842
1847
 
1843
1848
  try:
1844
1849
  execute_voice2text_command()
1845
- with open(os.path.join(".auto-coder", "exchange.txt"), "r") as f:
1850
+ with open(os.path.join(".auto-coder", "exchange.txt"), "r",encoding="utf-8") as f:
1846
1851
  return f.read()
1847
1852
  finally:
1848
1853
  os.remove(execute_file)
@@ -1864,12 +1869,12 @@ def generate_shell_command(input_text):
1864
1869
 
1865
1870
  execute_file = os.path.join("actions", f"{uuid.uuid4()}.yml")
1866
1871
 
1867
- with open(os.path.join(execute_file), "w") as f:
1872
+ with open(os.path.join(execute_file), "w",encoding="utf-8") as f:
1868
1873
  f.write(yaml_content)
1869
1874
 
1870
1875
  try:
1871
1876
  auto_coder_main(["agent", "generate_command", "--file", execute_file])
1872
- with open(os.path.join(".auto-coder", "exchange.txt"), "r") as f:
1877
+ with open(os.path.join(".auto-coder", "exchange.txt"), "r",encoding="utf-8") as f:
1873
1878
  shell_script = f.read()
1874
1879
  result_manager = ResultManager()
1875
1880
  result_manager.add_result(content=shell_script,meta={
@@ -1892,22 +1897,22 @@ def manage_models(query: str):
1892
1897
  """
1893
1898
  printer = Printer()
1894
1899
  console = Console()
1895
-
1900
+
1896
1901
  product_mode = memory.get("product_mode", "lite")
1897
1902
  if product_mode != "lite":
1898
1903
  printer.print_in_terminal("models_lite_only", style="red")
1899
1904
  return
1900
-
1905
+
1901
1906
  models_data = models_module.load_models()
1902
1907
  subcmd = ""
1903
1908
  if "/list" in query:
1904
1909
  subcmd = "/list"
1905
1910
  query = query.replace("/list", "", 1).strip()
1906
-
1911
+
1907
1912
  if "/add_model" in query:
1908
1913
  subcmd = "/add_model"
1909
1914
  query = query.replace("/add_model", "", 1).strip()
1910
-
1915
+
1911
1916
  if "/add" in query:
1912
1917
  subcmd = "/add"
1913
1918
  query = query.replace("/add", "", 1).strip()
@@ -1916,7 +1921,7 @@ def manage_models(query: str):
1916
1921
  if "/activate" in query:
1917
1922
  subcmd = "/add"
1918
1923
  query = query.replace("/activate", "", 1).strip()
1919
-
1924
+
1920
1925
  if "/remove" in query:
1921
1926
  subcmd = "/remove"
1922
1927
  query = query.replace("/remove", "", 1).strip()
@@ -1936,23 +1941,23 @@ def manage_models(query: str):
1936
1941
  if "output_price" in query:
1937
1942
  subcmd = "/output_price"
1938
1943
  query = query.replace("/output_price", "", 1).strip()
1939
-
1944
+
1940
1945
  if "/speed" in query:
1941
1946
  subcmd = "/speed"
1942
1947
  query = query.replace("/speed", "", 1).strip()
1943
-
1944
-
1948
+
1949
+
1945
1950
 
1946
1951
  if not subcmd:
1947
1952
  printer.print_in_terminal("models_usage")
1948
-
1953
+
1949
1954
  result_manager = ResultManager()
1950
1955
  if subcmd == "/list":
1951
1956
  if models_data:
1952
1957
  # Sort models by speed (average_speed)
1953
1958
  sorted_models = sorted(models_data, key=lambda x: float(x.get('average_speed', 0)))
1954
1959
  sorted_models.reverse()
1955
-
1960
+
1956
1961
  table = Table(
1957
1962
  title=printer.get_message_from_key("models_title"),
1958
1963
  expand=True,
@@ -1973,7 +1978,7 @@ def manage_models(query: str):
1973
1978
  if not api_key:
1974
1979
  printer.print_in_terminal("models_api_key_empty", style="yellow", name=name)
1975
1980
  name = f"{name} *"
1976
-
1981
+
1977
1982
  table.add_row(
1978
1983
  name,
1979
1984
  m.get("model_name", ""),
@@ -1989,7 +1994,7 @@ def manage_models(query: str):
1989
1994
  "query": query
1990
1995
  }
1991
1996
  })
1992
-
1997
+
1993
1998
  else:
1994
1999
  printer.print_in_terminal("models_no_models", style="yellow")
1995
2000
  result_manager.add_result(content="No models found",meta={
@@ -2037,7 +2042,7 @@ def manage_models(query: str):
2037
2042
  }
2038
2043
  })
2039
2044
  printer.print_in_terminal("models_input_price_usage", style="red")
2040
-
2045
+
2041
2046
  elif subcmd == "/output_price":
2042
2047
  args = query.strip().split()
2043
2048
  if len(args) >= 2:
@@ -2115,11 +2120,11 @@ def manage_models(query: str):
2115
2120
  }
2116
2121
  })
2117
2122
  printer.print_in_terminal("models_speed_usage", style="red")
2118
-
2123
+
2119
2124
  elif subcmd == "/speed-test":
2120
2125
  from autocoder.common.model_speed_test import render_speed_test_in_terminal
2121
2126
  test_rounds = 1 # 默认测试轮数
2122
-
2127
+
2123
2128
  enable_long_context = False
2124
2129
  if "/long_context" in query:
2125
2130
  enable_long_context = True
@@ -2133,7 +2138,7 @@ def manage_models(query: str):
2133
2138
  args = query.strip().split()
2134
2139
  if args and args[0].isdigit():
2135
2140
  test_rounds = int(args[0])
2136
-
2141
+
2137
2142
  render_speed_test_in_terminal(product_mode, test_rounds,enable_long_context=enable_long_context)
2138
2143
  ## 等待优化,获取明细数据
2139
2144
  result_manager.add_result(content="models test success",meta={
@@ -2142,7 +2147,7 @@ def manage_models(query: str):
2142
2147
  "query": query
2143
2148
  }
2144
2149
  })
2145
-
2150
+
2146
2151
  elif subcmd == "/add":
2147
2152
  # Support both simplified and legacy formats
2148
2153
  args = query.strip().split(" ")
@@ -2265,18 +2270,61 @@ def manage_models(query: str):
2265
2270
 
2266
2271
  def exclude_dirs(dir_names: List[str]):
2267
2272
  new_dirs = dir_names
2268
- existing_dirs = memory.get("exclude_dirs", [])
2273
+ existing_dirs = memory.get("exclude_dirs", [])
2269
2274
  dirs_to_add = [d for d in new_dirs if d not in existing_dirs]
2275
+
2270
2276
  if dirs_to_add:
2271
2277
  existing_dirs.extend(dirs_to_add)
2272
2278
  if "exclude_dirs" not in memory:
2273
2279
  memory["exclude_dirs"] = existing_dirs
2274
2280
  print(f"Added exclude dirs: {dirs_to_add}")
2281
+ exclude_files([f"regex://.*/{d}/*." for d in dirs_to_add])
2275
2282
  else:
2276
2283
  print("All specified dirs are already in the exclude list.")
2277
2284
  save_memory()
2278
2285
  completer.refresh_files()
2279
2286
 
2287
+ def exclude_files(file_patterns: List[str]):
2288
+ result_manager = ResultManager()
2289
+ printer = Printer()
2290
+ new_file_patterns = file_patterns
2291
+ existing_file_patterns = memory.get("exclude_files", [])
2292
+ file_patterns_to_add = [f for f in new_file_patterns if f not in existing_file_patterns]
2293
+
2294
+ for file_pattern in file_patterns_to_add:
2295
+ if not file_pattern.startswith("regex://"):
2296
+ result_manager.add_result(content=printer.get_message_from_key_with_format("invalid_file_pattern", file_pattern=file_pattern),meta={
2297
+ "action": "exclude_files",
2298
+ "input": {
2299
+ "query": file_pattern
2300
+ }
2301
+ })
2302
+ raise ValueError(printer.get_message_from_key_with_format("invalid_file_pattern", file_pattern=file_pattern))
2303
+
2304
+ if file_patterns_to_add:
2305
+ existing_file_patterns.extend(file_patterns_to_add)
2306
+ if "exclude_files" not in memory:
2307
+ memory["exclude_files"] = existing_file_patterns
2308
+
2309
+ result_manager.add_result(content=f"Added exclude files: {file_patterns_to_add}",meta={
2310
+ "action": "exclude_files",
2311
+ "input": {
2312
+ "query": file_patterns_to_add
2313
+ }
2314
+ })
2315
+ save_memory()
2316
+ print(f"Added exclude files: {file_patterns_to_add}")
2317
+ else:
2318
+ result_manager.add_result(content=f"All specified files are already in the exclude list.",meta={
2319
+ "action": "exclude_files",
2320
+ "input": {
2321
+ "query": file_patterns_to_add
2322
+ }
2323
+ })
2324
+ print("All specified files are already in the exclude list.")
2325
+
2326
+
2327
+
2280
2328
  @run_in_raw_thread()
2281
2329
  def index_build():
2282
2330
  conf = memory.get("conf", {})
@@ -2292,7 +2340,7 @@ def index_build():
2292
2340
  yaml_content = convert_yaml_config_to_str(yaml_config=yaml_config)
2293
2341
  yaml_file = os.path.join("actions", f"{uuid.uuid4()}.yml")
2294
2342
 
2295
- with open(yaml_file, "w") as f:
2343
+ with open(yaml_file, "w",encoding="utf-8") as f:
2296
2344
  f.write(yaml_content)
2297
2345
  try:
2298
2346
  with redirect_stdout() as output:
@@ -2322,7 +2370,7 @@ def get_final_config()->AutoCoderArgs:
2322
2370
 
2323
2371
  temp_yaml = os.path.join("actions", f"{uuid.uuid4()}.yml")
2324
2372
  try:
2325
- with open(temp_yaml, "w") as f:
2373
+ with open(temp_yaml, "w",encoding="utf-8") as f:
2326
2374
  f.write(convert_yaml_config_to_str(yaml_config=yaml_config))
2327
2375
  args = convert_yaml_to_config(temp_yaml)
2328
2376
  finally:
@@ -2339,26 +2387,26 @@ def help(query: str):
2339
2387
  auto_config_tuner.tune(AutoConfigRequest(query=query))
2340
2388
 
2341
2389
  @run_in_raw_thread()
2342
- def index_export(export_path: str):
2390
+ def index_export(path: str):
2343
2391
  from autocoder.common.index_import_export import export_index
2344
2392
  from autocoder.common.printer import Printer
2345
2393
  printer = Printer()
2346
2394
  project_root = os.getcwd()
2347
- if export_index(project_root, export_path):
2348
- printer.print_in_terminal("index_export_success", path=export_path)
2395
+ if export_index(project_root, path):
2396
+ printer.print_in_terminal("index_export_success", path=path)
2349
2397
  else:
2350
- printer.print_in_terminal("index_export_fail", path=export_path)
2398
+ printer.print_in_terminal("index_export_fail", path=path)
2351
2399
 
2352
2400
  @run_in_raw_thread()
2353
- def index_import(import_path: str):
2401
+ def index_import(path: str):
2354
2402
  from autocoder.common.index_import_export import import_index
2355
2403
  from autocoder.common.printer import Printer
2356
2404
  printer = Printer()
2357
2405
  project_root = os.getcwd()
2358
- if import_index(project_root, import_path):
2359
- printer.print_in_terminal("index_import_success", path=import_path)
2406
+ if import_index(project_root, path):
2407
+ printer.print_in_terminal("index_import_success", path=path)
2360
2408
  else:
2361
- printer.print_in_terminal("index_import_fail", path=import_path)
2409
+ printer.print_in_terminal("index_import_fail", path=path)
2362
2410
 
2363
2411
  @run_in_raw_thread()
2364
2412
  def index_query(query: str):
@@ -2377,7 +2425,7 @@ def index_query(query: str):
2377
2425
  yaml_content = convert_yaml_config_to_str(yaml_config=yaml_config)
2378
2426
  yaml_file = os.path.join("actions", f"{uuid.uuid4()}.yml")
2379
2427
 
2380
- with open(yaml_file, "w") as f:
2428
+ with open(yaml_file, "w",encoding="utf-8") as f:
2381
2429
  f.write(yaml_content)
2382
2430
  try:
2383
2431
  with redirect_stdout() as output:
@@ -2409,10 +2457,30 @@ def list_files():
2409
2457
  )
2410
2458
  )
2411
2459
 
2412
- @run_in_raw_thread()
2413
- def execute_shell_command(command: str):
2414
- from autocoder.common.shells import execute_shell_command as shell_exec
2415
- shell_exec(command)
2460
+
2461
+ def gen_and_exec_shell_command(query: str):
2462
+ from rich.prompt import Confirm
2463
+ from autocoder.common.printer import Printer
2464
+ from rich.console import Console
2465
+
2466
+ printer = Printer()
2467
+ console = Console()
2468
+ # Generate the shell script
2469
+ shell_script = generate_shell_command(query)
2470
+
2471
+ # Ask for confirmation using rich
2472
+ if Confirm.ask(
2473
+ printer.get_message_from_key("confirm_execute_shell_script"),
2474
+ default=False
2475
+ ):
2476
+ execute_shell_command(shell_script)
2477
+ else:
2478
+ console.print(
2479
+ Panel(
2480
+ printer.get_message_from_key("shell_script_not_executed"),
2481
+ border_style="yellow"
2482
+ )
2483
+ )
2416
2484
 
2417
2485
 
2418
2486
  def lib_command(args: List[str]):
@@ -2542,18 +2610,32 @@ def lib_command(args: List[str]):
2542
2610
  else:
2543
2611
  console.print(f"Unknown subcommand: {subcommand}")
2544
2612
 
2613
+
2614
+ def execute_shell_command(command: str):
2615
+ from autocoder.common.shells import execute_shell_command as shell_exec
2616
+ shell_exec(command)
2617
+
2618
+
2619
+ def conf_export(path: str):
2620
+ from autocoder.common.conf_import_export import export_conf
2621
+ export_conf(os.getcwd(), path)
2622
+
2623
+ def conf_import(path: str):
2624
+ from autocoder.common.conf_import_export import import_conf
2625
+ import_conf(os.getcwd(), path)
2626
+
2545
2627
  @run_in_raw_thread()
2546
2628
  def auto_command(params,query: str):
2547
2629
  """处理/auto指令"""
2548
2630
  from autocoder.commands.auto_command import CommandAutoTuner, AutoCommandRequest, CommandConfig, MemoryConfig
2549
2631
  args = get_final_config()
2550
2632
  # help(query)
2551
-
2633
+
2552
2634
  # 准备请求参数
2553
2635
  request = AutoCommandRequest(
2554
2636
  user_input=query
2555
2637
  )
2556
-
2638
+
2557
2639
  # 初始化调优器
2558
2640
  llm = get_single_llm(args.chat_model or args.model,product_mode=args.product_mode)
2559
2641
  tuner = CommandAutoTuner(llm,
@@ -2568,6 +2650,7 @@ def auto_command(params,query: str):
2568
2650
  commit=commit,
2569
2651
  help=help,
2570
2652
  exclude_dirs=exclude_dirs,
2653
+ exclude_files=exclude_files,
2571
2654
  ask=ask,
2572
2655
  chat=chat,
2573
2656
  coding=coding,
@@ -2579,9 +2662,13 @@ def auto_command(params,query: str):
2579
2662
  index_build=index_build,
2580
2663
  index_query=index_query,
2581
2664
  execute_shell_command=execute_shell_command,
2582
- generate_shell_command=generate_shell_command
2665
+ generate_shell_command=generate_shell_command,
2666
+ conf_export=conf_export,
2667
+ conf_import=conf_import,
2668
+ index_export=index_export,
2669
+ index_import=index_import
2583
2670
  ))
2584
-
2671
+
2585
2672
  # 生成建议
2586
2673
  response = tuner.analyze(request)
2587
2674
  printer = Printer()
@@ -2593,7 +2680,7 @@ def auto_command(params,query: str):
2593
2680
  border_style="blue",
2594
2681
  padding=(1, 2)
2595
2682
  ))
2596
-
2683
+
2597
2684
 
2598
2685
  def main():
2599
2686
  from autocoder.rag.variable_holder import VariableHolder
@@ -2606,20 +2693,20 @@ def main():
2606
2693
  VariableHolder.TOKENIZER_MODEL = Tokenizer.from_file(tokenizer_path)
2607
2694
  except FileNotFoundError:
2608
2695
  tokenizer_path = None
2609
-
2696
+
2610
2697
  ARGS = parse_arguments()
2611
-
2698
+
2612
2699
  if ARGS.lite:
2613
2700
  ARGS.product_mode = "lite"
2614
-
2701
+
2615
2702
  if ARGS.pro:
2616
2703
  ARGS.product_mode = "pro"
2617
2704
 
2618
2705
  if not ARGS.quick:
2619
2706
  initialize_system(ARGS)
2620
-
2707
+
2621
2708
  load_memory()
2622
-
2709
+
2623
2710
  configure(f"product_mode:{ARGS.product_mode}")
2624
2711
 
2625
2712
  MODES = {
@@ -2680,7 +2767,11 @@ def main():
2680
2767
  human_as_model = memory["conf"].get("human_as_model", "false")
2681
2768
  if mode not in MODES:
2682
2769
  mode = "auto_detect"
2683
- return f" Mode: {MODES[mode]} (ctl+k) | Human as Model: {human_as_model} (ctl+n or /conf human_as_model:true/false)"
2770
+ pwd = os.getcwd()
2771
+ pwd_parts = pwd.split(os.sep)
2772
+ if len(pwd_parts) > 3:
2773
+ pwd = os.sep.join(pwd_parts[-3:])
2774
+ return f"Current Dir: {pwd} \nMode: {MODES[mode]} | Human as Model: {human_as_model} "
2684
2775
 
2685
2776
  session = PromptSession(
2686
2777
  history=InMemoryHistory(),
@@ -2773,20 +2864,14 @@ def main():
2773
2864
 
2774
2865
  elif user_input.startswith("/index/build"):
2775
2866
  index_build()
2776
-
2867
+
2777
2868
  elif user_input.startswith("/index/export"):
2778
2869
  export_path = user_input[len("/index/export"):].strip()
2779
- if not export_path:
2780
- print("Please specify the export path")
2781
- else:
2782
- index_export(export_path)
2783
-
2870
+ index_export(export_path)
2871
+
2784
2872
  elif user_input.startswith("/index/import"):
2785
- import_path = user_input[len("/index/import"):].strip()
2786
- if not import_path:
2787
- print("Please specify the import path")
2788
- else:
2789
- index_import(import_path)
2873
+ import_path = user_input[len("/index/import"):].strip()
2874
+ index_import(import_path)
2790
2875
 
2791
2876
  elif user_input.startswith("/list_files"):
2792
2877
  list_files()
@@ -2804,7 +2889,17 @@ def main():
2804
2889
  print(memory["mode"])
2805
2890
  else:
2806
2891
  memory["mode"] = conf
2807
-
2892
+
2893
+ elif user_input.startswith("/conf/export"):
2894
+ from autocoder.common.conf_import_export import export_conf
2895
+ export_path = user_input[len("/conf/export"):].strip()
2896
+ export_conf(os.getcwd(), export_path)
2897
+
2898
+ elif user_input.startswith("/conf/import"):
2899
+ from autocoder.common.conf_import_export import import_conf
2900
+ import_path = user_input[len("/conf/import"):].strip()
2901
+ import_conf(os.getcwd(), import_path)
2902
+
2808
2903
  elif user_input.startswith("/conf"):
2809
2904
  conf = user_input[len("/conf"):].strip()
2810
2905
  if not conf:
@@ -2822,11 +2917,17 @@ def main():
2822
2917
  show_help()
2823
2918
  else:
2824
2919
  help(query)
2825
-
2920
+
2826
2921
  elif user_input.startswith("/exclude_dirs"):
2827
2922
  dir_names = user_input[len(
2828
2923
  "/exclude_dirs"):].strip().split(",")
2829
2924
  exclude_dirs(dir_names)
2925
+
2926
+ elif user_input.startswith("/exclude_files"):
2927
+ file_patterns = user_input[len(
2928
+ "/exclude_files"):].strip().split(",")
2929
+ exclude_files(file_patterns)
2930
+
2830
2931
  elif user_input.startswith("/ask"):
2831
2932
  query = user_input[len("/ask"):].strip()
2832
2933
  if not query:
@@ -2889,12 +2990,16 @@ def main():
2889
2990
  # elif user_input.startswith("/shell"):
2890
2991
  else:
2891
2992
  command = user_input
2892
- if user_input.startswith("/shell"):
2993
+ if user_input.startswith("/shell"):
2893
2994
  command = user_input[len("/shell"):].strip()
2894
2995
  if not command:
2895
2996
  print("Please enter a shell command to execute.")
2896
2997
  else:
2897
- execute_shell_command(command)
2998
+ if command.startswith("/chat"):
2999
+ command = command[len("/chat"):].strip()
3000
+ gen_and_exec_shell_command(command)
3001
+ else:
3002
+ execute_shell_command(command)
2898
3003
 
2899
3004
  except KeyboardInterrupt:
2900
3005
  continue