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