auto-coder 0.1.354__py3-none-any.whl → 0.1.356__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.
- {auto_coder-0.1.354.dist-info → auto_coder-0.1.356.dist-info}/METADATA +1 -1
- {auto_coder-0.1.354.dist-info → auto_coder-0.1.356.dist-info}/RECORD +40 -35
- autocoder/agent/agentic_filter.py +1 -1
- autocoder/agent/auto_learn.py +631 -0
- autocoder/auto_coder.py +8 -0
- autocoder/auto_coder_runner.py +59 -87
- autocoder/chat/conf_command.py +270 -0
- autocoder/chat/models_command.py +485 -0
- autocoder/chat/rules_command.py +458 -0
- autocoder/chat_auto_coder.py +34 -24
- autocoder/chat_auto_coder_lang.py +156 -2
- autocoder/commands/auto_command.py +1 -1
- autocoder/commands/auto_web.py +1 -1
- autocoder/common/__init__.py +2 -0
- autocoder/common/auto_coder_lang.py +9 -1
- autocoder/common/command_completer.py +58 -12
- autocoder/common/command_completer_v2.py +615 -0
- autocoder/common/global_cancel.py +53 -16
- autocoder/common/rulefiles/autocoderrules_utils.py +83 -0
- autocoder/common/v2/agent/agentic_edit.py +4 -4
- autocoder/common/v2/code_agentic_editblock_manager.py +9 -9
- autocoder/common/v2/code_diff_manager.py +2 -2
- autocoder/common/v2/code_editblock_manager.py +11 -10
- autocoder/common/v2/code_strict_diff_manager.py +3 -2
- autocoder/dispacher/actions/action.py +6 -6
- autocoder/dispacher/actions/plugins/action_regex_project.py +2 -2
- autocoder/events/event_manager_singleton.py +1 -1
- autocoder/index/index.py +2 -2
- autocoder/rag/cache/local_byzer_storage_cache.py +1 -1
- autocoder/rag/cache/local_duckdb_storage_cache.py +8 -0
- autocoder/rag/loaders/image_loader.py +25 -13
- autocoder/rag/long_context_rag.py +2 -2
- autocoder/utils/auto_coder_utils/chat_stream_out.py +3 -4
- autocoder/utils/model_provider_selector.py +14 -2
- autocoder/utils/thread_utils.py +9 -27
- autocoder/version.py +1 -1
- {auto_coder-0.1.354.dist-info → auto_coder-0.1.356.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.354.dist-info → auto_coder-0.1.356.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.354.dist-info → auto_coder-0.1.356.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.354.dist-info → auto_coder-0.1.356.dist-info}/top_level.txt +0 -0
autocoder/auto_coder_runner.py
CHANGED
|
@@ -34,7 +34,7 @@ from rich.console import Console
|
|
|
34
34
|
from rich.panel import Panel
|
|
35
35
|
from rich.table import Table
|
|
36
36
|
from rich.live import Live
|
|
37
|
-
|
|
37
|
+
# Removed Text import as it's only used in the deleted print_conf
|
|
38
38
|
from rich.live import Live
|
|
39
39
|
from rich.markdown import Markdown
|
|
40
40
|
from byzerllm.utils.nontext import Image
|
|
@@ -53,6 +53,7 @@ from autocoder.common.memory_manager import get_global_memory_file_paths
|
|
|
53
53
|
from autocoder import models as models_module
|
|
54
54
|
import shlex
|
|
55
55
|
from autocoder.utils.llms import get_single_llm
|
|
56
|
+
import fnmatch
|
|
56
57
|
import pkg_resources
|
|
57
58
|
from autocoder.common.printer import Printer
|
|
58
59
|
from autocoder.utils.thread_utils import run_in_raw_thread
|
|
@@ -111,6 +112,7 @@ commands = [
|
|
|
111
112
|
"/chat",
|
|
112
113
|
"/ask",
|
|
113
114
|
"/commit",
|
|
115
|
+
"/rules",
|
|
114
116
|
"/revert",
|
|
115
117
|
"/index/query",
|
|
116
118
|
"/index/build",
|
|
@@ -437,18 +439,10 @@ def initialize_system(args:InitializeSystemRequest):
|
|
|
437
439
|
configure_success[0] = True
|
|
438
440
|
|
|
439
441
|
if first_time[0] and args.product_mode == "pro" and configure_success[0]:
|
|
440
|
-
configure(f"model:v3_chat", skip_print=True)
|
|
441
|
-
configure(f"chat_model:r1_chat", skip_print=True)
|
|
442
|
-
configure(f"generate_rerank_model:r1_chat", skip_print=True)
|
|
443
|
-
configure(f"code_model:v3_chat", skip_print=True)
|
|
444
|
-
configure(f"index_filter_model:r1_chat", skip_print=True)
|
|
442
|
+
configure(f"model:v3_chat", skip_print=True)
|
|
445
443
|
|
|
446
444
|
if first_time[0] and args.product_mode == "lite" and models_module.check_model_exists("v3_chat"):
|
|
447
|
-
configure(f"model:v3_chat", skip_print=True)
|
|
448
|
-
configure(f"chat_model:r1_chat", skip_print=True)
|
|
449
|
-
configure(f"generate_rerank_model:r1_chat", skip_print=True)
|
|
450
|
-
configure(f"code_model:v3_chat", skip_print=True)
|
|
451
|
-
configure(f"index_filter_model:r1_chat", skip_print=True)
|
|
445
|
+
configure(f"model:v3_chat", skip_print=True)
|
|
452
446
|
|
|
453
447
|
|
|
454
448
|
def convert_yaml_config_to_str(yaml_config):
|
|
@@ -541,7 +535,7 @@ def find_files_in_project(patterns: List[str]) -> List[str]:
|
|
|
541
535
|
def convert_config_value(key, value):
|
|
542
536
|
field_info = AutoCoderArgs.model_fields.get(key)
|
|
543
537
|
if field_info:
|
|
544
|
-
if value.lower() in ["true", "false"]:
|
|
538
|
+
if isinstance(value, str) and value.lower() in ["true", "false"]:
|
|
545
539
|
return value.lower() == "true"
|
|
546
540
|
elif "int" in str(field_info.annotation):
|
|
547
541
|
return int(value)
|
|
@@ -652,15 +646,15 @@ def load_memory():
|
|
|
652
646
|
_memory = json.load(f)
|
|
653
647
|
# clear memory
|
|
654
648
|
memory.clear()
|
|
655
|
-
memory.update(_memory)
|
|
656
|
-
completer.update_current_files(memory["current_files"]["files"])
|
|
649
|
+
memory.update(_memory)
|
|
657
650
|
return memory
|
|
658
651
|
|
|
659
652
|
def get_memory():
|
|
660
653
|
return load_memory()
|
|
661
654
|
|
|
662
655
|
|
|
663
|
-
|
|
656
|
+
from autocoder.common.command_completer_v2 import CommandCompleterV2
|
|
657
|
+
completer = CommandCompleterV2(commands,
|
|
664
658
|
file_system_model=CCFileSystemModel(project_root=project_root,
|
|
665
659
|
defaut_exclude_dirs=defaut_exclude_dirs,
|
|
666
660
|
get_all_file_names_in_project=get_all_file_names_in_project,
|
|
@@ -669,57 +663,8 @@ completer = CommandCompleter(commands,
|
|
|
669
663
|
get_all_file_in_project_with_dot=get_all_file_in_project_with_dot,
|
|
670
664
|
get_symbol_list=get_symbol_list
|
|
671
665
|
),
|
|
672
|
-
memory_model=CCMemoryModel(
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
def print_conf(content:Dict[str,Any]):
|
|
679
|
-
"""Display configuration dictionary in a Rich table format with enhanced visual styling.
|
|
680
|
-
|
|
681
|
-
Args:
|
|
682
|
-
conf (Dict[str, Any]): Configuration dictionary to display
|
|
683
|
-
"""
|
|
684
|
-
console = Console()
|
|
685
|
-
|
|
686
|
-
# Create a styled table with rounded borders
|
|
687
|
-
table = Table(
|
|
688
|
-
show_header=True,
|
|
689
|
-
header_style="bold magenta",
|
|
690
|
-
title=get_message("conf_title"),
|
|
691
|
-
title_style="bold blue",
|
|
692
|
-
border_style="blue",
|
|
693
|
-
show_lines=True
|
|
694
|
-
)
|
|
695
|
-
|
|
696
|
-
# Add columns with explicit width and alignment
|
|
697
|
-
table.add_column(get_message("conf_key"), style="cyan", justify="right", width=30, no_wrap=False)
|
|
698
|
-
table.add_column(get_message("conf_value"), style="green", justify="left", width=50, no_wrap=False)
|
|
699
|
-
|
|
700
|
-
# Sort keys for consistent display
|
|
701
|
-
for key in sorted(content.keys()):
|
|
702
|
-
value = content[key]
|
|
703
|
-
# Format value based on type
|
|
704
|
-
if isinstance(value, (dict, list)):
|
|
705
|
-
formatted_value = Text(json.dumps(value, indent=2), style="yellow")
|
|
706
|
-
elif isinstance(value, bool):
|
|
707
|
-
formatted_value = Text(str(value), style="bright_green" if value else "red")
|
|
708
|
-
elif isinstance(value, (int, float)):
|
|
709
|
-
formatted_value = Text(str(value), style="bright_cyan")
|
|
710
|
-
else:
|
|
711
|
-
formatted_value = Text(str(value), style="green")
|
|
712
|
-
|
|
713
|
-
table.add_row(str(key), formatted_value)
|
|
714
|
-
|
|
715
|
-
# Add padding and print with a panel
|
|
716
|
-
console.print(Panel(
|
|
717
|
-
table,
|
|
718
|
-
padding=(1, 2),
|
|
719
|
-
subtitle=f"[italic]{get_message('conf_subtitle')}[/italic]",
|
|
720
|
-
border_style="blue"
|
|
721
|
-
))
|
|
722
|
-
|
|
666
|
+
memory_model=CCMemoryModel(get_memory_func=get_memory,
|
|
667
|
+
save_memory_func=save_memory))
|
|
723
668
|
def revert():
|
|
724
669
|
result_manager = ResultManager()
|
|
725
670
|
last_yaml_file = get_last_yaml_file("actions")
|
|
@@ -1025,7 +970,6 @@ def add_files(args: List[str]):
|
|
|
1025
970
|
result_manager.append(content=f"No files matched.",
|
|
1026
971
|
meta={"action": "add_files","success":False, "input":{ "args": args}})
|
|
1027
972
|
|
|
1028
|
-
completer.update_current_files(memory["current_files"]["files"])
|
|
1029
973
|
save_memory()
|
|
1030
974
|
|
|
1031
975
|
|
|
@@ -1038,39 +982,61 @@ def remove_files(file_names: List[str]):
|
|
|
1038
982
|
memory["current_files"]["files"] = []
|
|
1039
983
|
memory["current_files"]["current_groups"] = []
|
|
1040
984
|
printer.print_in_terminal("remove_files_all", style="green")
|
|
1041
|
-
result_manager.append(content="All files removed.",
|
|
985
|
+
result_manager.append(content="All files removed.",
|
|
1042
986
|
meta={"action": "remove_files","success":True, "input":{ "file_names": file_names}})
|
|
1043
987
|
else:
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
988
|
+
files_to_remove = set()
|
|
989
|
+
current_files_abs = memory["current_files"]["files"]
|
|
990
|
+
|
|
991
|
+
for pattern in file_names:
|
|
992
|
+
pattern = pattern.strip() # Remove leading/trailing whitespace
|
|
993
|
+
if not pattern:
|
|
994
|
+
continue
|
|
995
|
+
|
|
996
|
+
is_wildcard = "*" in pattern or "?" in pattern
|
|
997
|
+
|
|
998
|
+
for file_path_abs in current_files_abs:
|
|
999
|
+
relative_path = os.path.relpath(file_path_abs, project_root)
|
|
1000
|
+
basename = os.path.basename(file_path_abs)
|
|
1001
|
+
|
|
1002
|
+
matched = False
|
|
1003
|
+
if is_wildcard:
|
|
1004
|
+
# Match pattern against relative path or basename
|
|
1005
|
+
if fnmatch.fnmatch(relative_path, pattern) or fnmatch.fnmatch(basename, pattern):
|
|
1006
|
+
matched = True
|
|
1007
|
+
else:
|
|
1008
|
+
# Exact match against relative path, absolute path, or basename
|
|
1009
|
+
if relative_path == pattern or file_path_abs == pattern or basename == pattern:
|
|
1010
|
+
matched = True
|
|
1011
|
+
|
|
1012
|
+
if matched:
|
|
1013
|
+
files_to_remove.add(file_path_abs)
|
|
1014
|
+
|
|
1015
|
+
removed_files_list = list(files_to_remove)
|
|
1016
|
+
if removed_files_list:
|
|
1017
|
+
# Update memory by filtering out the files to remove
|
|
1018
|
+
memory["current_files"]["files"] = [
|
|
1019
|
+
f for f in current_files_abs if f not in files_to_remove
|
|
1020
|
+
]
|
|
1021
|
+
|
|
1022
|
+
table = Table(
|
|
1023
|
+
show_header=True,
|
|
1056
1024
|
header_style="bold magenta"
|
|
1057
1025
|
)
|
|
1058
|
-
table.add_column("
|
|
1059
|
-
for f in
|
|
1026
|
+
table.add_column(printer.get_message_from_key("file_column_title"), style="green")
|
|
1027
|
+
for f in removed_files_list:
|
|
1060
1028
|
table.add_row(os.path.relpath(f, project_root))
|
|
1061
1029
|
|
|
1062
1030
|
console = Console()
|
|
1063
1031
|
console.print(
|
|
1064
1032
|
Panel(table, border_style="green",
|
|
1065
|
-
title=printer.get_message_from_key("files_removed")))
|
|
1066
|
-
result_manager.append(content=f"Removed files: {', '.join(
|
|
1033
|
+
title=printer.get_message_from_key("files_removed")))
|
|
1034
|
+
result_manager.append(content=f"Removed files: {', '.join(removed_files_list)}",
|
|
1067
1035
|
meta={"action": "remove_files","success":True, "input":{ "file_names": file_names}})
|
|
1068
1036
|
else:
|
|
1069
1037
|
printer.print_in_terminal("remove_files_none", style="yellow")
|
|
1070
1038
|
result_manager.append(content=printer.get_message_from_key("remove_files_none"),
|
|
1071
|
-
meta={"action": "remove_files","success":False, "input":{ "file_names": file_names}})
|
|
1072
|
-
|
|
1073
|
-
completer.update_current_files(memory["current_files"]["files"])
|
|
1039
|
+
meta={"action": "remove_files","success":False, "input":{ "file_names": file_names}})
|
|
1074
1040
|
save_memory()
|
|
1075
1041
|
|
|
1076
1042
|
@run_in_raw_thread()
|
|
@@ -1644,6 +1610,12 @@ def coding(query: str):
|
|
|
1644
1610
|
save_memory()
|
|
1645
1611
|
completer.refresh_files()
|
|
1646
1612
|
|
|
1613
|
+
@run_in_raw_thread()
|
|
1614
|
+
def rules(query: str):
|
|
1615
|
+
from autocoder.chat.rules_command import handle_rules_command
|
|
1616
|
+
memory = get_memory()
|
|
1617
|
+
handle_rules_command(query, memory,coding_func=coding)
|
|
1618
|
+
completer.refresh_files()
|
|
1647
1619
|
|
|
1648
1620
|
@byzerllm.prompt()
|
|
1649
1621
|
def code_review(query: str) -> str:
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
|
|
2
|
+
import os
|
|
3
|
+
import io
|
|
4
|
+
import contextlib
|
|
5
|
+
import fnmatch
|
|
6
|
+
import json
|
|
7
|
+
from typing import Dict, Any, List, Callable, Optional
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
from rich.panel import Panel
|
|
10
|
+
from rich.table import Table
|
|
11
|
+
from rich.text import Text
|
|
12
|
+
from autocoder.auto_coder_runner import save_memory # Import save_memory
|
|
13
|
+
from autocoder.common.conf_validator import ConfigValidator
|
|
14
|
+
from autocoder.common.auto_coder_lang import get_message, get_message_with_format
|
|
15
|
+
|
|
16
|
+
# Helper function to print the configuration table (internal implementation)
|
|
17
|
+
def _print_conf_table(content: Dict[str, Any], title: str = "Configuration Settings"):
|
|
18
|
+
"""Display configuration dictionary in a Rich table format."""
|
|
19
|
+
console = Console(file=io.StringIO(), force_terminal=True, color_system="truecolor") # Capture output
|
|
20
|
+
|
|
21
|
+
# Create a styled table with rounded borders
|
|
22
|
+
table = Table(
|
|
23
|
+
show_header=True,
|
|
24
|
+
header_style="bold magenta",
|
|
25
|
+
title=title,
|
|
26
|
+
title_style="bold blue",
|
|
27
|
+
border_style="blue",
|
|
28
|
+
show_lines=True
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Add columns with explicit width and alignment
|
|
32
|
+
table.add_column(get_message("conf_key"), style="cyan", justify="right", width=30, no_wrap=False)
|
|
33
|
+
table.add_column(get_message("conf_value"), style="green", justify="left", width=50, no_wrap=False)
|
|
34
|
+
|
|
35
|
+
# Sort keys for consistent display
|
|
36
|
+
for key in sorted(content.keys()):
|
|
37
|
+
value = content[key]
|
|
38
|
+
# Format value based on type
|
|
39
|
+
if isinstance(value, (dict, list)):
|
|
40
|
+
formatted_value = Text(json.dumps(value, indent=2), style="yellow")
|
|
41
|
+
elif isinstance(value, bool):
|
|
42
|
+
formatted_value = Text(str(value), style="bright_green" if value else "red")
|
|
43
|
+
elif isinstance(value, (int, float)):
|
|
44
|
+
formatted_value = Text(str(value), style="bright_cyan")
|
|
45
|
+
else:
|
|
46
|
+
formatted_value = Text(str(value), style="green")
|
|
47
|
+
|
|
48
|
+
table.add_row(str(key), formatted_value)
|
|
49
|
+
|
|
50
|
+
# Add padding and print with a panel
|
|
51
|
+
console.print(Panel(
|
|
52
|
+
table,
|
|
53
|
+
padding=(1, 2),
|
|
54
|
+
subtitle=f"[italic]{get_message('conf_subtitle')}[/italic]",
|
|
55
|
+
border_style="blue"
|
|
56
|
+
))
|
|
57
|
+
return console.file.getvalue() # Return captured string
|
|
58
|
+
|
|
59
|
+
# --- Command Handlers ---
|
|
60
|
+
|
|
61
|
+
def _handle_list_conf(memory: Dict[str, Any], args: List[str]) -> str:
|
|
62
|
+
"""Handles listing configuration settings, supports wildcard filtering."""
|
|
63
|
+
conf = memory.get("conf", {})
|
|
64
|
+
pattern = args[0] if args else "*" # Default to all if no pattern
|
|
65
|
+
|
|
66
|
+
if pattern == "*":
|
|
67
|
+
title = get_message("conf_title")
|
|
68
|
+
filtered_conf = conf
|
|
69
|
+
else:
|
|
70
|
+
title = f"Filtered Configuration (Pattern: {pattern})"
|
|
71
|
+
filtered_conf = {k: v for k, v in conf.items() if fnmatch.fnmatch(k, pattern)}
|
|
72
|
+
if not filtered_conf:
|
|
73
|
+
return f"No configuration keys found matching pattern: {pattern}"
|
|
74
|
+
|
|
75
|
+
if not filtered_conf and pattern == "*":
|
|
76
|
+
return "No configurations set."
|
|
77
|
+
|
|
78
|
+
return _print_conf_table(filtered_conf, title)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _handle_get_conf(memory: Dict[str, Any], args: List[str]) -> str:
|
|
82
|
+
"""Handles getting a specific configuration setting."""
|
|
83
|
+
if len(args) != 1:
|
|
84
|
+
return "Error: 'get' command requires exactly one argument (the key). Usage: /conf get <key>"
|
|
85
|
+
key = args[0]
|
|
86
|
+
conf = memory.get("conf", {})
|
|
87
|
+
value = conf.get(key)
|
|
88
|
+
if value is None:
|
|
89
|
+
return f"Error: Configuration key '{key}' not found."
|
|
90
|
+
else:
|
|
91
|
+
# Format value for better readability
|
|
92
|
+
if isinstance(value, (list, dict)):
|
|
93
|
+
formatted_value = json.dumps(value, indent=2)
|
|
94
|
+
else:
|
|
95
|
+
formatted_value = repr(value)
|
|
96
|
+
return f"{key}: {formatted_value}"
|
|
97
|
+
|
|
98
|
+
def _parse_value(value_str: str) -> Any:
|
|
99
|
+
"""Attempts to parse the value string into common types."""
|
|
100
|
+
value_str = value_str.strip()
|
|
101
|
+
if value_str.lower() == 'true':
|
|
102
|
+
return True
|
|
103
|
+
if value_str.lower() == 'false':
|
|
104
|
+
return False
|
|
105
|
+
if value_str.lower() == 'none' or value_str.lower() == 'null':
|
|
106
|
+
return None
|
|
107
|
+
# Keep quoted strings as strings without quotes
|
|
108
|
+
if (value_str.startswith('"') and value_str.endswith('"')) or \
|
|
109
|
+
(value_str.startswith("'") and value_str.endswith("'")):
|
|
110
|
+
return value_str[1:-1]
|
|
111
|
+
|
|
112
|
+
try:
|
|
113
|
+
# Try int first
|
|
114
|
+
return int(value_str)
|
|
115
|
+
except ValueError:
|
|
116
|
+
pass
|
|
117
|
+
try:
|
|
118
|
+
# Then try float
|
|
119
|
+
return float(value_str)
|
|
120
|
+
except ValueError:
|
|
121
|
+
pass
|
|
122
|
+
# If none of the above, return as string
|
|
123
|
+
return value_str
|
|
124
|
+
|
|
125
|
+
def _handle_set_conf(memory: Dict[str, Any], args: List[str]) -> str:
|
|
126
|
+
"""Handles setting or updating a configuration setting."""
|
|
127
|
+
if len(args) < 2:
|
|
128
|
+
return "Error: 'set' command requires at least two arguments (key and value). Usage: /conf set <key> <value>"
|
|
129
|
+
key = args[0]
|
|
130
|
+
# Join the rest of the arguments to form the value string
|
|
131
|
+
value_str = " ".join(args[1:])
|
|
132
|
+
try:
|
|
133
|
+
parsed_value = _parse_value(value_str)
|
|
134
|
+
|
|
135
|
+
# Validate before setting
|
|
136
|
+
product_mode = memory.get("conf", {}).get("product_mode", "lite")
|
|
137
|
+
ConfigValidator.validate(key, str(parsed_value), product_mode) # Validate the parsed value as string initially if needed, or adjust validation
|
|
138
|
+
|
|
139
|
+
if "conf" not in memory:
|
|
140
|
+
memory["conf"] = {}
|
|
141
|
+
memory["conf"][key] = parsed_value
|
|
142
|
+
save_memory() # Save after modification
|
|
143
|
+
# Use repr for confirmation message for clarity
|
|
144
|
+
return f"Configuration updated: {key} = {repr(parsed_value)}"
|
|
145
|
+
except Exception as e:
|
|
146
|
+
return f"Error setting configuration for key '{key}': {e}"
|
|
147
|
+
|
|
148
|
+
def _handle_delete_conf(memory: Dict[str, Any], args: List[str]) -> str:
|
|
149
|
+
"""Handles deleting a configuration setting."""
|
|
150
|
+
if len(args) != 1:
|
|
151
|
+
return "Error: 'delete' command requires exactly one argument (the key). Usage: /conf delete <key>"
|
|
152
|
+
key = args[0]
|
|
153
|
+
conf = memory.get("conf", {})
|
|
154
|
+
if key in conf:
|
|
155
|
+
try:
|
|
156
|
+
del memory["conf"][key]
|
|
157
|
+
save_memory() # Save after modification
|
|
158
|
+
return f"Configuration deleted: {key}"
|
|
159
|
+
except Exception as e:
|
|
160
|
+
return f"Error deleting key '{key}': {e}"
|
|
161
|
+
else:
|
|
162
|
+
return f"Error: Configuration key '{key}' not found."
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _handle_help(memory: Dict[str, Any], args: List[str]) -> str:
|
|
166
|
+
"""Provides help text for the /conf command."""
|
|
167
|
+
if args:
|
|
168
|
+
return f"Error: 'help' command takes no arguments. Usage: /conf help"
|
|
169
|
+
|
|
170
|
+
help_text = """
|
|
171
|
+
/conf command usage:
|
|
172
|
+
/conf [pattern] - Show configurations. Optional wildcard pattern (e.g., *_model, api*).
|
|
173
|
+
/conf get <key> - Get the value of a specific configuration key.
|
|
174
|
+
/conf set <key>:<value> - Set or update a configuration key.
|
|
175
|
+
Value parsed (bool, int, float, None) or treated as string.
|
|
176
|
+
Use quotes ("value with spaces") for explicit strings.
|
|
177
|
+
/conf /drop <key> - Delete a configuration key.
|
|
178
|
+
/conf /export <path> - Export current configuration to a file.
|
|
179
|
+
/conf /import <path> - Import configuration from a file.
|
|
180
|
+
/conf help - Show this help message.
|
|
181
|
+
"""
|
|
182
|
+
return help_text.strip()
|
|
183
|
+
|
|
184
|
+
# Command dispatch table
|
|
185
|
+
COMMAND_HANDLERS: Dict[str, Callable[[Dict[str, Any], List[str]], str]] = {
|
|
186
|
+
"list": _handle_list_conf,
|
|
187
|
+
"show": _handle_list_conf, # Alias
|
|
188
|
+
"get": _handle_get_conf,
|
|
189
|
+
"set": _handle_set_conf,
|
|
190
|
+
"delete": _handle_delete_conf,
|
|
191
|
+
"del": _handle_delete_conf, # Alias
|
|
192
|
+
"rm": _handle_delete_conf, # Alias
|
|
193
|
+
"help": _handle_help,
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
def handle_conf_command(command_args: str, memory: Dict[str, Any]) -> str:
|
|
197
|
+
"""
|
|
198
|
+
Handles the /conf command, its subcommands, and wildcard listing.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
command_args: The arguments string following the /conf command.
|
|
202
|
+
Example: "key:value", "get key", "set key value", "*_model", "/export path"
|
|
203
|
+
memory: The current session memory dictionary.
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
A string response to be displayed to the user.
|
|
207
|
+
"""
|
|
208
|
+
conf_str = command_args.strip()
|
|
209
|
+
|
|
210
|
+
# Handle special subcommands first
|
|
211
|
+
if conf_str.startswith("/export"):
|
|
212
|
+
from autocoder.common.conf_import_export import export_conf
|
|
213
|
+
export_path = conf_str[len("/export"):].strip()
|
|
214
|
+
if not export_path:
|
|
215
|
+
return "Error: Please specify a path for export. Usage: /conf /export <path>"
|
|
216
|
+
try:
|
|
217
|
+
export_conf(os.getcwd(), export_path)
|
|
218
|
+
return f"Configuration exported successfully to {export_path}"
|
|
219
|
+
except Exception as e:
|
|
220
|
+
return f"Error exporting configuration: {e}"
|
|
221
|
+
elif conf_str.startswith("/import"):
|
|
222
|
+
from autocoder.common.conf_import_export import import_conf
|
|
223
|
+
import_path = conf_str[len("/import"):].strip()
|
|
224
|
+
if not import_path:
|
|
225
|
+
return "Error: Please specify a path for import. Usage: /conf /import <path>"
|
|
226
|
+
try:
|
|
227
|
+
import_conf(os.getcwd(), import_path)
|
|
228
|
+
# Reload memory after import might be needed depending on import_conf implementation
|
|
229
|
+
# load_memory() # Consider if import_conf modifies the passed memory or global state
|
|
230
|
+
return f"Configuration imported successfully from {import_path}. Use '/conf' to see changes."
|
|
231
|
+
except Exception as e:
|
|
232
|
+
return f"Error importing configuration: {e}"
|
|
233
|
+
|
|
234
|
+
# Handle regular commands and listing/filtering
|
|
235
|
+
args = conf_str.split()
|
|
236
|
+
|
|
237
|
+
if not args:
|
|
238
|
+
# Default action: list all configurations
|
|
239
|
+
return _handle_list_conf(memory, [])
|
|
240
|
+
else:
|
|
241
|
+
command = args[0].lower()
|
|
242
|
+
command_args_list = args[1:]
|
|
243
|
+
|
|
244
|
+
# Check if the first argument is a known command or potentially a pattern
|
|
245
|
+
handler = COMMAND_HANDLERS.get(command)
|
|
246
|
+
|
|
247
|
+
if handler:
|
|
248
|
+
# It's a known command (list, get, set, delete, help)
|
|
249
|
+
try:
|
|
250
|
+
return handler(memory, command_args_list)
|
|
251
|
+
except Exception as e:
|
|
252
|
+
return f"An unexpected error occurred while executing '/conf {command}': {e}"
|
|
253
|
+
elif "*" in command or "?" in command:
|
|
254
|
+
# Treat as a list/filter pattern if it contains wildcards and is not a known command
|
|
255
|
+
return _handle_list_conf(memory, [command]) # Pass the pattern as the argument to list
|
|
256
|
+
else:
|
|
257
|
+
# Handle legacy key:value format for setting (optional, can be removed if only set command is preferred)
|
|
258
|
+
if ":" in conf_str and len(args) == 1: # Check if it looks like key:value and is a single "word"
|
|
259
|
+
parts = conf_str.split(":", 1)
|
|
260
|
+
if len(parts) == 2:
|
|
261
|
+
key, value_str = parts[0].strip(), parts[1].strip()
|
|
262
|
+
if key and value_str:
|
|
263
|
+
return _handle_set_conf(memory, [key, value_str])
|
|
264
|
+
else:
|
|
265
|
+
return f"Error: Invalid key:value format in '{conf_str}'. Use '/conf set {key} {value_str}' or '/conf help'."
|
|
266
|
+
else:
|
|
267
|
+
return f"Error: Unknown command or invalid format '{conf_str}'. Type '/conf help' for available commands."
|
|
268
|
+
else:
|
|
269
|
+
# If it's not a known command, not a wildcard, and not key:value format
|
|
270
|
+
return f"Error: Unknown command '/conf {command}'. Type '/conf help' for available commands."
|