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