auto-coder 0.1.201__py3-none-any.whl → 0.1.203__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.
- {auto_coder-0.1.201.dist-info → auto_coder-0.1.203.dist-info}/METADATA +1 -1
- {auto_coder-0.1.201.dist-info → auto_coder-0.1.203.dist-info}/RECORD +16 -16
- autocoder/agent/planner.py +8 -6
- autocoder/auto_coder.py +16 -12
- autocoder/chat_auto_coder.py +190 -72
- autocoder/chat_auto_coder_lang.py +7 -3
- autocoder/command_args.py +1 -0
- autocoder/common/git_utils.py +434 -0
- autocoder/rag/long_context_rag.py +15 -8
- autocoder/utils/__init__.py +6 -16
- autocoder/utils/_markitdown.py +62 -39
- autocoder/version.py +1 -1
- {auto_coder-0.1.201.dist-info → auto_coder-0.1.203.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.201.dist-info → auto_coder-0.1.203.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.201.dist-info → auto_coder-0.1.203.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.201.dist-info → auto_coder-0.1.203.dist-info}/top_level.txt +0 -0
autocoder/chat_auto_coder.py
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
from prompt_toolkit.formatted_text import HTML
|
|
2
|
+
from prompt_toolkit.shortcuts import radiolist_dialog
|
|
3
|
+
from prompt_toolkit import prompt
|
|
1
4
|
import os
|
|
2
5
|
import yaml
|
|
3
6
|
import json
|
|
@@ -6,6 +9,7 @@ import io
|
|
|
6
9
|
import uuid
|
|
7
10
|
import glob
|
|
8
11
|
import time
|
|
12
|
+
import hashlib
|
|
9
13
|
from contextlib import contextmanager
|
|
10
14
|
from typing import List, Dict, Any, Optional
|
|
11
15
|
from prompt_toolkit import PromptSession
|
|
@@ -41,6 +45,7 @@ from rich.live import Live
|
|
|
41
45
|
from byzerllm.utils.nontext import Image
|
|
42
46
|
import re
|
|
43
47
|
import git
|
|
48
|
+
from autocoder.common import git_utils
|
|
44
49
|
from autocoder.utils.request_queue import (
|
|
45
50
|
request_queue,
|
|
46
51
|
RequestValue,
|
|
@@ -65,7 +70,8 @@ def parse_arguments():
|
|
|
65
70
|
import argparse
|
|
66
71
|
|
|
67
72
|
parser = argparse.ArgumentParser(description="Chat Auto Coder")
|
|
68
|
-
parser.add_argument("--debug", action="store_true",
|
|
73
|
+
parser.add_argument("--debug", action="store_true",
|
|
74
|
+
help="Enable debug mode")
|
|
69
75
|
parser.add_argument(
|
|
70
76
|
"--quick",
|
|
71
77
|
action="store_true",
|
|
@@ -81,9 +87,6 @@ if platform.system() == "Windows":
|
|
|
81
87
|
|
|
82
88
|
init()
|
|
83
89
|
|
|
84
|
-
from prompt_toolkit import prompt
|
|
85
|
-
from prompt_toolkit.shortcuts import radiolist_dialog
|
|
86
|
-
from prompt_toolkit.formatted_text import HTML
|
|
87
90
|
|
|
88
91
|
memory = {
|
|
89
92
|
"conversation": [],
|
|
@@ -107,6 +110,7 @@ commands = [
|
|
|
107
110
|
"/coding",
|
|
108
111
|
"/chat",
|
|
109
112
|
"/ask",
|
|
113
|
+
"/commit",
|
|
110
114
|
"/revert",
|
|
111
115
|
"/index/query",
|
|
112
116
|
"/index/build",
|
|
@@ -149,7 +153,10 @@ def show_help():
|
|
|
149
153
|
print(
|
|
150
154
|
f" \033[94m/summon\033[0m \033[93m<query>\033[0m - \033[92m{get_message('summon_desc')}\033[0m"
|
|
151
155
|
)
|
|
152
|
-
print(
|
|
156
|
+
print(
|
|
157
|
+
f" \033[94m/revert\033[0m - \033[92m{get_message('revert_desc')}\033[0m")
|
|
158
|
+
print(
|
|
159
|
+
f" \033[94m/commit\033[0m - \033[92m{get_message('commit_desc')}\033[0m")
|
|
153
160
|
print(
|
|
154
161
|
f" \033[94m/conf\033[0m \033[93m<key>:<value>\033[0m - \033[92m{get_message('conf_desc')}\033[0m"
|
|
155
162
|
)
|
|
@@ -162,7 +169,8 @@ def show_help():
|
|
|
162
169
|
print(
|
|
163
170
|
f" \033[94m/list_files\033[0m - \033[92m{get_message('list_files_desc')}\033[0m"
|
|
164
171
|
)
|
|
165
|
-
print(
|
|
172
|
+
print(
|
|
173
|
+
f" \033[94m/help\033[0m - \033[92m{get_message('help_desc')}\033[0m")
|
|
166
174
|
print(
|
|
167
175
|
f" \033[94m/exclude_dirs\033[0m \033[93m<dir1>,<dir2> ...\033[0m - \033[92m{get_message('exclude_dirs_desc')}\033[0m"
|
|
168
176
|
)
|
|
@@ -172,9 +180,11 @@ def show_help():
|
|
|
172
180
|
print(
|
|
173
181
|
f" \033[94m/voice_input\033[0m - \033[92m{get_message('voice_input_desc')}\033[0m"
|
|
174
182
|
)
|
|
175
|
-
print(
|
|
183
|
+
print(
|
|
184
|
+
f" \033[94m/mode\033[0m - \033[92m{get_message('mode_desc')}\033[0m")
|
|
176
185
|
print(f" \033[94m/lib\033[0m - \033[92m{get_message('lib_desc')}\033[0m")
|
|
177
|
-
print(
|
|
186
|
+
print(
|
|
187
|
+
f" \033[94m/exit\033[0m - \033[92m{get_message('exit_desc')}\033[0m")
|
|
178
188
|
print()
|
|
179
189
|
|
|
180
190
|
|
|
@@ -199,10 +209,12 @@ def configure_project_type():
|
|
|
199
209
|
print_formatted_text(HTML(f"<info>{escape(text)}</info>"), style=style)
|
|
200
210
|
|
|
201
211
|
def print_warning(text):
|
|
202
|
-
print_formatted_text(
|
|
212
|
+
print_formatted_text(
|
|
213
|
+
HTML(f"<warning>{escape(text)}</warning>"), style=style)
|
|
203
214
|
|
|
204
215
|
def print_header(text):
|
|
205
|
-
print_formatted_text(
|
|
216
|
+
print_formatted_text(
|
|
217
|
+
HTML(f"<header>{escape(text)}</header>"), style=style)
|
|
206
218
|
|
|
207
219
|
print_header(f"\n=== {get_message('project_type_config')} ===\n")
|
|
208
220
|
print_info(get_message("project_type_supports"))
|
|
@@ -248,7 +260,8 @@ def initialize_system():
|
|
|
248
260
|
if not os.path.exists(".auto-coder"):
|
|
249
261
|
first_time = True
|
|
250
262
|
print_status(get_message("not_initialized"), "warning")
|
|
251
|
-
init_choice = input(
|
|
263
|
+
init_choice = input(
|
|
264
|
+
f" {get_message('init_prompt')}").strip().lower()
|
|
252
265
|
if init_choice == "y":
|
|
253
266
|
try:
|
|
254
267
|
subprocess.run(
|
|
@@ -265,7 +278,8 @@ def initialize_system():
|
|
|
265
278
|
|
|
266
279
|
if not os.path.exists(base_persist_dir):
|
|
267
280
|
os.makedirs(base_persist_dir, exist_ok=True)
|
|
268
|
-
print_status(get_message("created_dir").format(
|
|
281
|
+
print_status(get_message("created_dir").format(
|
|
282
|
+
base_persist_dir), "success")
|
|
269
283
|
|
|
270
284
|
if first_time:
|
|
271
285
|
configure_project_type()
|
|
@@ -275,7 +289,8 @@ def initialize_system():
|
|
|
275
289
|
init_project()
|
|
276
290
|
# Check if Ray is running
|
|
277
291
|
print_status(get_message("checking_ray"), "")
|
|
278
|
-
ray_status = subprocess.run(
|
|
292
|
+
ray_status = subprocess.run(
|
|
293
|
+
["ray", "status"], capture_output=True, text=True)
|
|
279
294
|
if ray_status.returncode != 0:
|
|
280
295
|
print_status(get_message("ray_not_running"), "warning")
|
|
281
296
|
try:
|
|
@@ -395,7 +410,7 @@ def get_all_file_names_in_project() -> List[str]:
|
|
|
395
410
|
|
|
396
411
|
file_names = []
|
|
397
412
|
final_exclude_dirs = defaut_exclude_dirs + memory.get("exclude_dirs", [])
|
|
398
|
-
for root, dirs, files in os.walk(project_root,followlinks=True):
|
|
413
|
+
for root, dirs, files in os.walk(project_root, followlinks=True):
|
|
399
414
|
dirs[:] = [d for d in dirs if d not in final_exclude_dirs]
|
|
400
415
|
file_names.extend(files)
|
|
401
416
|
return file_names
|
|
@@ -405,7 +420,7 @@ def get_all_file_in_project() -> List[str]:
|
|
|
405
420
|
|
|
406
421
|
file_names = []
|
|
407
422
|
final_exclude_dirs = defaut_exclude_dirs + memory.get("exclude_dirs", [])
|
|
408
|
-
for root, dirs, files in os.walk(project_root,followlinks=True):
|
|
423
|
+
for root, dirs, files in os.walk(project_root, followlinks=True):
|
|
409
424
|
dirs[:] = [d for d in dirs if d not in final_exclude_dirs]
|
|
410
425
|
for file in files:
|
|
411
426
|
file_names.append(os.path.join(root, file))
|
|
@@ -415,17 +430,18 @@ def get_all_file_in_project() -> List[str]:
|
|
|
415
430
|
def get_all_file_in_project_with_dot() -> List[str]:
|
|
416
431
|
file_names = []
|
|
417
432
|
final_exclude_dirs = defaut_exclude_dirs + memory.get("exclude_dirs", [])
|
|
418
|
-
for root, dirs, files in os.walk(project_root,followlinks=True):
|
|
433
|
+
for root, dirs, files in os.walk(project_root, followlinks=True):
|
|
419
434
|
dirs[:] = [d for d in dirs if d not in final_exclude_dirs]
|
|
420
435
|
for file in files:
|
|
421
|
-
file_names.append(os.path.join(
|
|
436
|
+
file_names.append(os.path.join(
|
|
437
|
+
root, file).replace(project_root, "."))
|
|
422
438
|
return file_names
|
|
423
439
|
|
|
424
440
|
|
|
425
441
|
def get_all_dir_names_in_project() -> List[str]:
|
|
426
442
|
dir_names = []
|
|
427
443
|
final_exclude_dirs = defaut_exclude_dirs + memory.get("exclude_dirs", [])
|
|
428
|
-
for root, dirs, files in os.walk(project_root,followlinks=True):
|
|
444
|
+
for root, dirs, files in os.walk(project_root, followlinks=True):
|
|
429
445
|
dirs[:] = [d for d in dirs if d not in final_exclude_dirs]
|
|
430
446
|
for dir in dirs:
|
|
431
447
|
dir_names.append(dir)
|
|
@@ -448,8 +464,8 @@ def find_files_in_project(patterns: List[str]) -> List[str]:
|
|
|
448
464
|
matched_files.append(abs_path)
|
|
449
465
|
else:
|
|
450
466
|
is_added = False
|
|
451
|
-
|
|
452
|
-
for root, dirs, files in os.walk(project_root,followlinks=True):
|
|
467
|
+
# add files belongs to project
|
|
468
|
+
for root, dirs, files in os.walk(project_root, followlinks=True):
|
|
453
469
|
dirs[:] = [d for d in dirs if d not in final_exclude_dirs]
|
|
454
470
|
if pattern in files:
|
|
455
471
|
matched_files.append(os.path.join(root, pattern))
|
|
@@ -460,7 +476,7 @@ def find_files_in_project(patterns: List[str]) -> List[str]:
|
|
|
460
476
|
if _pattern in os.path.join(root, file):
|
|
461
477
|
matched_files.append(os.path.join(root, file))
|
|
462
478
|
is_added = True
|
|
463
|
-
|
|
479
|
+
# add files not belongs to project
|
|
464
480
|
if not is_added:
|
|
465
481
|
matched_files.append(pattern)
|
|
466
482
|
|
|
@@ -546,7 +562,10 @@ def show_help():
|
|
|
546
562
|
print(
|
|
547
563
|
f" \033[94m/summon\033[0m \033[93m<query>\033[0m - \033[92m{get_message('summon_desc')}\033[0m"
|
|
548
564
|
)
|
|
549
|
-
print(
|
|
565
|
+
print(
|
|
566
|
+
f" \033[94m/revert\033[0m - \033[92m{get_message('revert_desc')}\033[0m")
|
|
567
|
+
print(
|
|
568
|
+
f" \033[94m/commit\033[0m - \033[92m{get_message('commit_desc')}\033[0m")
|
|
550
569
|
print(
|
|
551
570
|
f" \033[94m/conf\033[0m \033[93m<key>:<value>\033[0m - \033[92m{get_message('conf_desc')}\033[0m"
|
|
552
571
|
)
|
|
@@ -559,7 +578,8 @@ def show_help():
|
|
|
559
578
|
print(
|
|
560
579
|
f" \033[94m/list_files\033[0m - \033[92m{get_message('list_files_desc')}\033[0m"
|
|
561
580
|
)
|
|
562
|
-
print(
|
|
581
|
+
print(
|
|
582
|
+
f" \033[94m/help\033[0m - \033[92m{get_message('help_desc')}\033[0m")
|
|
563
583
|
print(
|
|
564
584
|
f" \033[94m/exclude_dirs\033[0m \033[93m<dir1>,<dir2> ...\033[0m - \033[92m{get_message('exclude_dirs_desc')}\033[0m"
|
|
565
585
|
)
|
|
@@ -569,9 +589,11 @@ def show_help():
|
|
|
569
589
|
print(
|
|
570
590
|
f" \033[94m/voice_input\033[0m - \033[92m{get_message('voice_input_desc')}\033[0m"
|
|
571
591
|
)
|
|
572
|
-
print(
|
|
592
|
+
print(
|
|
593
|
+
f" \033[94m/mode\033[0m - \033[92m{get_message('mode_desc')}\033[0m")
|
|
573
594
|
print(f" \033[94m/lib\033[0m - \033[92m{get_message('lib_desc')}\033[0m")
|
|
574
|
-
print(
|
|
595
|
+
print(
|
|
596
|
+
f" \033[94m/exit\033[0m - \033[92m{get_message('exit_desc')}\033[0m")
|
|
575
597
|
print()
|
|
576
598
|
|
|
577
599
|
|
|
@@ -635,13 +657,13 @@ class CommandCompleter(Completer):
|
|
|
635
657
|
|
|
636
658
|
if len(words) > 0:
|
|
637
659
|
if words[0] == "/mode":
|
|
638
|
-
left_word = text[len("/mode")
|
|
660
|
+
left_word = text[len("/mode"):]
|
|
639
661
|
for mode in ["normal", "auto_detect", "voice_input"]:
|
|
640
662
|
if mode.startswith(left_word.strip()):
|
|
641
663
|
yield Completion(mode, start_position=-len(left_word.strip()))
|
|
642
664
|
|
|
643
665
|
if words[0] == "/add_files":
|
|
644
|
-
new_text = text[len("/add_files")
|
|
666
|
+
new_text = text[len("/add_files"):]
|
|
645
667
|
parser = CommandTextParser(new_text, words[0])
|
|
646
668
|
parser.add_files()
|
|
647
669
|
current_word = parser.current_word()
|
|
@@ -672,18 +694,21 @@ class CommandCompleter(Completer):
|
|
|
672
694
|
for file_name in self.all_files_with_dot:
|
|
673
695
|
if file_name.startswith(current_word):
|
|
674
696
|
yield Completion(
|
|
675
|
-
file_name, start_position=-
|
|
697
|
+
file_name, start_position=-
|
|
698
|
+
len(current_word)
|
|
676
699
|
)
|
|
677
700
|
else:
|
|
678
701
|
for file_name in self.all_file_names:
|
|
679
702
|
if file_name.startswith(current_word):
|
|
680
703
|
yield Completion(
|
|
681
|
-
file_name, start_position=-
|
|
704
|
+
file_name, start_position=-
|
|
705
|
+
len(current_word)
|
|
682
706
|
)
|
|
683
707
|
for file_name in self.all_files:
|
|
684
708
|
if current_word and current_word in file_name:
|
|
685
709
|
yield Completion(
|
|
686
|
-
file_name, start_position=-
|
|
710
|
+
file_name, start_position=-
|
|
711
|
+
len(current_word)
|
|
687
712
|
)
|
|
688
713
|
elif words[0] in ["/chat", "/coding"]:
|
|
689
714
|
image_extensions = (
|
|
@@ -713,7 +738,7 @@ class CommandCompleter(Completer):
|
|
|
713
738
|
".psd",
|
|
714
739
|
".xcf",
|
|
715
740
|
)
|
|
716
|
-
new_text = text[len(words[0])
|
|
741
|
+
new_text = text[len(words[0]):]
|
|
717
742
|
parser = CommandTextParser(new_text, words[0])
|
|
718
743
|
|
|
719
744
|
parser.coding()
|
|
@@ -740,7 +765,8 @@ class CommandCompleter(Completer):
|
|
|
740
765
|
if len(path_parts) > 3
|
|
741
766
|
else file_name
|
|
742
767
|
)
|
|
743
|
-
relative_path = os.path.relpath(
|
|
768
|
+
relative_path = os.path.relpath(
|
|
769
|
+
file_name, project_root)
|
|
744
770
|
yield Completion(
|
|
745
771
|
relative_path,
|
|
746
772
|
start_position=-len(name),
|
|
@@ -757,7 +783,8 @@ class CommandCompleter(Completer):
|
|
|
757
783
|
if len(path_parts) > 3
|
|
758
784
|
else file_name
|
|
759
785
|
)
|
|
760
|
-
relative_path = os.path.relpath(
|
|
786
|
+
relative_path = os.path.relpath(
|
|
787
|
+
file_name, project_root)
|
|
761
788
|
|
|
762
789
|
yield Completion(
|
|
763
790
|
relative_path,
|
|
@@ -773,7 +800,8 @@ class CommandCompleter(Completer):
|
|
|
773
800
|
if len(path_parts) > 3
|
|
774
801
|
else file_name
|
|
775
802
|
)
|
|
776
|
-
relative_path = os.path.relpath(
|
|
803
|
+
relative_path = os.path.relpath(
|
|
804
|
+
file_name, project_root)
|
|
777
805
|
yield Completion(
|
|
778
806
|
relative_path,
|
|
779
807
|
start_position=-len(name),
|
|
@@ -791,7 +819,8 @@ class CommandCompleter(Completer):
|
|
|
791
819
|
if len(path_parts) > 3
|
|
792
820
|
else symbol.symbol_name
|
|
793
821
|
)
|
|
794
|
-
relative_path = os.path.relpath(
|
|
822
|
+
relative_path = os.path.relpath(
|
|
823
|
+
file_name, project_root)
|
|
795
824
|
yield Completion(
|
|
796
825
|
f"{symbol.symbol_name}(location: {relative_path})",
|
|
797
826
|
start_position=-len(name),
|
|
@@ -826,7 +855,8 @@ class CommandCompleter(Completer):
|
|
|
826
855
|
for dir in dirs:
|
|
827
856
|
full_path = os.path.join(root, dir)
|
|
828
857
|
if full_path.startswith(file_name):
|
|
829
|
-
relative_path = os.path.relpath(
|
|
858
|
+
relative_path = os.path.relpath(
|
|
859
|
+
full_path, search_dir)
|
|
830
860
|
yield Completion(
|
|
831
861
|
relative_path,
|
|
832
862
|
start_position=-len(file_basename),
|
|
@@ -838,7 +868,8 @@ class CommandCompleter(Completer):
|
|
|
838
868
|
image_extensions
|
|
839
869
|
) and file.startswith(file_basename):
|
|
840
870
|
full_path = os.path.join(root, file)
|
|
841
|
-
relative_path = os.path.relpath(
|
|
871
|
+
relative_path = os.path.relpath(
|
|
872
|
+
full_path, search_dir)
|
|
842
873
|
yield Completion(
|
|
843
874
|
relative_path,
|
|
844
875
|
start_position=-len(file_basename),
|
|
@@ -848,7 +879,7 @@ class CommandCompleter(Completer):
|
|
|
848
879
|
break
|
|
849
880
|
|
|
850
881
|
elif words[0] == "/remove_files":
|
|
851
|
-
new_words = text[len("/remove_files")
|
|
882
|
+
new_words = text[len("/remove_files"):].strip().split(",")
|
|
852
883
|
|
|
853
884
|
is_at_space = text[-1] == " "
|
|
854
885
|
last_word = new_words[-2] if len(new_words) > 1 else ""
|
|
@@ -875,7 +906,7 @@ class CommandCompleter(Completer):
|
|
|
875
906
|
file_name, start_position=-len(current_word)
|
|
876
907
|
)
|
|
877
908
|
elif words[0] == "/exclude_dirs":
|
|
878
|
-
new_words = text[len("/exclude_dirs")
|
|
909
|
+
new_words = text[len("/exclude_dirs"):].strip().split(",")
|
|
879
910
|
current_word = new_words[-1]
|
|
880
911
|
|
|
881
912
|
for file_name in self.all_dir_names:
|
|
@@ -883,7 +914,7 @@ class CommandCompleter(Completer):
|
|
|
883
914
|
yield Completion(file_name, start_position=-len(current_word))
|
|
884
915
|
|
|
885
916
|
elif words[0] == "/lib":
|
|
886
|
-
new_text = text[len("/lib")
|
|
917
|
+
new_text = text[len("/lib"):]
|
|
887
918
|
parser = CommandTextParser(new_text, words[0])
|
|
888
919
|
parser.lib()
|
|
889
920
|
current_word = parser.current_word()
|
|
@@ -900,7 +931,7 @@ class CommandCompleter(Completer):
|
|
|
900
931
|
)
|
|
901
932
|
|
|
902
933
|
elif words[0] == "/conf":
|
|
903
|
-
new_words = text[len("/conf")
|
|
934
|
+
new_words = text[len("/conf"):].strip().split()
|
|
904
935
|
is_at_space = text[-1] == " "
|
|
905
936
|
last_word = new_words[-2] if len(new_words) > 1 else ""
|
|
906
937
|
current_word = new_words[-1] if new_words else ""
|
|
@@ -919,7 +950,8 @@ class CommandCompleter(Completer):
|
|
|
919
950
|
]
|
|
920
951
|
# /conf [curosr]
|
|
921
952
|
elif not last_word and not current_word:
|
|
922
|
-
completions = [
|
|
953
|
+
completions = [
|
|
954
|
+
"/drop"] if "/drop".startswith(current_word) else []
|
|
923
955
|
completions += [
|
|
924
956
|
field_name + ":"
|
|
925
957
|
for field_name in AutoCoderArgs.model_fields.keys()
|
|
@@ -927,7 +959,8 @@ class CommandCompleter(Completer):
|
|
|
927
959
|
]
|
|
928
960
|
# /conf p[cursor]
|
|
929
961
|
elif not last_word and current_word:
|
|
930
|
-
completions = [
|
|
962
|
+
completions = [
|
|
963
|
+
"/drop"] if "/drop".startswith(current_word) else []
|
|
931
964
|
completions += [
|
|
932
965
|
field_name + ":"
|
|
933
966
|
for field_name in AutoCoderArgs.model_fields.keys()
|
|
@@ -955,7 +988,7 @@ class CommandCompleter(Completer):
|
|
|
955
988
|
self.all_files = get_all_file_in_project()
|
|
956
989
|
self.all_dir_names = get_all_dir_names_in_project()
|
|
957
990
|
self.all_files_with_dot = get_all_file_in_project_with_dot()
|
|
958
|
-
self.symbol_list = get_symbol_list()
|
|
991
|
+
self.symbol_list = get_symbol_list()
|
|
959
992
|
|
|
960
993
|
|
|
961
994
|
completer = CommandCompleter(commands)
|
|
@@ -1021,7 +1054,8 @@ def add_files(args: List[str]):
|
|
|
1021
1054
|
completer.refresh_files()
|
|
1022
1055
|
load_memory()
|
|
1023
1056
|
console.print(
|
|
1024
|
-
Panel("Refreshed file list.",
|
|
1057
|
+
Panel("Refreshed file list.",
|
|
1058
|
+
title="Files Refreshed", border_style="green")
|
|
1025
1059
|
)
|
|
1026
1060
|
return
|
|
1027
1061
|
|
|
@@ -1029,7 +1063,8 @@ def add_files(args: List[str]):
|
|
|
1029
1063
|
if len(args) == 1 or (len(args) == 2 and args[1] == "list"):
|
|
1030
1064
|
if not groups:
|
|
1031
1065
|
console.print(
|
|
1032
|
-
Panel("No groups defined.", title="Groups",
|
|
1066
|
+
Panel("No groups defined.", title="Groups",
|
|
1067
|
+
border_style="yellow")
|
|
1033
1068
|
)
|
|
1034
1069
|
else:
|
|
1035
1070
|
table = Table(
|
|
@@ -1054,7 +1089,8 @@ def add_files(args: List[str]):
|
|
|
1054
1089
|
)
|
|
1055
1090
|
table.add_row(
|
|
1056
1091
|
group_name,
|
|
1057
|
-
"\n".join([os.path.relpath(f, project_root)
|
|
1092
|
+
"\n".join([os.path.relpath(f, project_root)
|
|
1093
|
+
for f in files]),
|
|
1058
1094
|
query_prefix,
|
|
1059
1095
|
is_active,
|
|
1060
1096
|
end_section=(i == len(groups) - 1),
|
|
@@ -1086,7 +1122,8 @@ def add_files(args: List[str]):
|
|
|
1086
1122
|
if group_name in groups_info:
|
|
1087
1123
|
del memory["current_files"]["groups_info"][group_name]
|
|
1088
1124
|
if group_name in memory["current_files"]["current_groups"]:
|
|
1089
|
-
memory["current_files"]["current_groups"].remove(
|
|
1125
|
+
memory["current_files"]["current_groups"].remove(
|
|
1126
|
+
group_name)
|
|
1090
1127
|
console.print(
|
|
1091
1128
|
Panel(
|
|
1092
1129
|
f"Dropped group '{group_name}'.",
|
|
@@ -1259,7 +1296,8 @@ def remove_files(file_names: List[str]):
|
|
|
1259
1296
|
memory["current_files"]["files"] = []
|
|
1260
1297
|
memory["current_files"]["current_groups"] = []
|
|
1261
1298
|
console.print(
|
|
1262
|
-
Panel("Removed all files.",
|
|
1299
|
+
Panel("Removed all files.",
|
|
1300
|
+
title="Files Removed", border_style="green")
|
|
1263
1301
|
)
|
|
1264
1302
|
else:
|
|
1265
1303
|
removed_files = []
|
|
@@ -1373,6 +1411,76 @@ def get_llm_friendly_package_docs(
|
|
|
1373
1411
|
return docs
|
|
1374
1412
|
|
|
1375
1413
|
|
|
1414
|
+
def convert_yaml_to_config(yaml_file: str):
|
|
1415
|
+
from autocoder.auto_coder import AutoCoderArgs, load_include_files, Template
|
|
1416
|
+
args = AutoCoderArgs()
|
|
1417
|
+
with open(yaml_file, "r") as f:
|
|
1418
|
+
config = yaml.safe_load(f)
|
|
1419
|
+
config = load_include_files(config, yaml_file)
|
|
1420
|
+
for key, value in config.items():
|
|
1421
|
+
if key != "file": # 排除 --file 参数本身
|
|
1422
|
+
# key: ENV {{VARIABLE_NAME}}
|
|
1423
|
+
if isinstance(value, str) and value.startswith("ENV"):
|
|
1424
|
+
template = Template(value.removeprefix("ENV").strip())
|
|
1425
|
+
value = template.render(os.environ)
|
|
1426
|
+
setattr(args, key, value)
|
|
1427
|
+
return args
|
|
1428
|
+
|
|
1429
|
+
def commit():
|
|
1430
|
+
def prepare_commit_yaml():
|
|
1431
|
+
auto_coder_main(["next", "chat_action"])
|
|
1432
|
+
|
|
1433
|
+
prepare_commit_yaml()
|
|
1434
|
+
|
|
1435
|
+
latest_yaml_file = get_last_yaml_file("actions")
|
|
1436
|
+
|
|
1437
|
+
conf = memory.get("conf", {})
|
|
1438
|
+
current_files = memory["current_files"]["files"]
|
|
1439
|
+
execute_file = None
|
|
1440
|
+
|
|
1441
|
+
if latest_yaml_file:
|
|
1442
|
+
try:
|
|
1443
|
+
execute_file = os.path.join("actions", latest_yaml_file)
|
|
1444
|
+
yaml_config = {
|
|
1445
|
+
"include_file": ["./base/base.yml"],
|
|
1446
|
+
"auto_merge": conf.get("auto_merge", "editblock"),
|
|
1447
|
+
"human_as_model": conf.get("human_as_model", "false") == "true",
|
|
1448
|
+
"skip_build_index": conf.get("skip_build_index", "true") == "true",
|
|
1449
|
+
"skip_confirm": conf.get("skip_confirm", "true") == "true",
|
|
1450
|
+
"silence": conf.get("silence", "true") == "true",
|
|
1451
|
+
"include_project_structure": conf.get("include_project_structure", "true")
|
|
1452
|
+
== "true",
|
|
1453
|
+
}
|
|
1454
|
+
for key, value in conf.items():
|
|
1455
|
+
converted_value = convert_config_value(key, value)
|
|
1456
|
+
if converted_value is not None:
|
|
1457
|
+
yaml_config[key] = converted_value
|
|
1458
|
+
|
|
1459
|
+
yaml_config["urls"] = current_files + get_llm_friendly_package_docs(
|
|
1460
|
+
return_paths=True
|
|
1461
|
+
)
|
|
1462
|
+
args = convert_yaml_to_config(execute_file)
|
|
1463
|
+
llm = byzerllm.ByzerLLM.from_default_model(args.code_model or args.model)
|
|
1464
|
+
uncommitted_changes = git_utils.get_uncommitted_changes(".")
|
|
1465
|
+
commit_message = git_utils.generate_commit_message.with_llm(
|
|
1466
|
+
llm).run(uncommitted_changes)
|
|
1467
|
+
memory["conversation"].append({"role": "user", "content": commit_message})
|
|
1468
|
+
yaml_config["query"] = commit_message
|
|
1469
|
+
yaml_content = convert_yaml_config_to_str(yaml_config=yaml_config)
|
|
1470
|
+
with open(os.path.join(execute_file), "w") as f:
|
|
1471
|
+
f.write(yaml_content)
|
|
1472
|
+
|
|
1473
|
+
file_content = open(execute_file).read()
|
|
1474
|
+
md5 = hashlib.md5(file_content.encode('utf-8')).hexdigest()
|
|
1475
|
+
file_name = os.path.basename(execute_file)
|
|
1476
|
+
commit_result = git_utils.commit_changes(".", f"auto_coder_{file_name}_{md5}")
|
|
1477
|
+
git_utils.print_commit_info(commit_result=commit_result)
|
|
1478
|
+
except Exception as e:
|
|
1479
|
+
print(f"Failed to commit: {e}")
|
|
1480
|
+
if execute_file:
|
|
1481
|
+
os.remove(execute_file)
|
|
1482
|
+
|
|
1483
|
+
|
|
1376
1484
|
def coding(query: str):
|
|
1377
1485
|
console = Console()
|
|
1378
1486
|
is_apply = query.strip().startswith("/apply")
|
|
@@ -1415,7 +1523,7 @@ def coding(query: str):
|
|
|
1415
1523
|
return_paths=True
|
|
1416
1524
|
)
|
|
1417
1525
|
|
|
1418
|
-
|
|
1526
|
+
# handle image
|
|
1419
1527
|
v = Image.convert_image_paths_from(query)
|
|
1420
1528
|
yaml_config["query"] = v
|
|
1421
1529
|
|
|
@@ -1424,7 +1532,8 @@ def coding(query: str):
|
|
|
1424
1532
|
active_groups_context = "下面是对上面文件按分组给到的一些描述,当用户的需求正好匹配描述的时候,参考描述来做修改:\n"
|
|
1425
1533
|
for group in current_groups:
|
|
1426
1534
|
group_files = groups.get(group, [])
|
|
1427
|
-
query_prefix = groups_info.get(
|
|
1535
|
+
query_prefix = groups_info.get(
|
|
1536
|
+
group, {}).get("query_prefix", "")
|
|
1428
1537
|
active_groups_context += f"组名: {group}\n"
|
|
1429
1538
|
active_groups_context += f"文件列表:\n"
|
|
1430
1539
|
for file in group_files:
|
|
@@ -1508,10 +1617,10 @@ def code_review(query: str) -> str:
|
|
|
1508
1617
|
|
|
1509
1618
|
def chat(query: str):
|
|
1510
1619
|
conf = memory.get("conf", {})
|
|
1511
|
-
|
|
1620
|
+
|
|
1512
1621
|
yaml_config = {
|
|
1513
1622
|
"include_file": ["./base/base.yml"],
|
|
1514
|
-
"include_project_structure": conf.get("include_project_structure", "true") in ["true","True"],
|
|
1623
|
+
"include_project_structure": conf.get("include_project_structure", "true") in ["true", "True"],
|
|
1515
1624
|
"human_as_model": conf.get("human_as_model", "false") == "true",
|
|
1516
1625
|
"skip_build_index": conf.get("skip_build_index", "true") == "true",
|
|
1517
1626
|
"skip_confirm": conf.get("skip_confirm", "true") == "true",
|
|
@@ -1868,7 +1977,8 @@ def execute_shell_command(command: str):
|
|
|
1868
1977
|
f"[bold red]Command failed with return code {process.returncode}[/bold red]"
|
|
1869
1978
|
)
|
|
1870
1979
|
else:
|
|
1871
|
-
console.print(
|
|
1980
|
+
console.print(
|
|
1981
|
+
"[bold green]Command completed successfully[/bold green]")
|
|
1872
1982
|
|
|
1873
1983
|
except FileNotFoundError:
|
|
1874
1984
|
console.print(
|
|
@@ -1916,7 +2026,8 @@ def lib_command(args: List[str]):
|
|
|
1916
2026
|
proxy_url,
|
|
1917
2027
|
llm_friendly_packages_dir,
|
|
1918
2028
|
)
|
|
1919
|
-
console.print(
|
|
2029
|
+
console.print(
|
|
2030
|
+
"Successfully cloned llm_friendly_packages repository")
|
|
1920
2031
|
except git.exc.GitCommandError as e:
|
|
1921
2032
|
console.print(f"Error cloning repository: {e}")
|
|
1922
2033
|
|
|
@@ -1977,7 +2088,8 @@ def lib_command(args: List[str]):
|
|
|
1977
2088
|
console.print(f"Updated remote URL to: {new_url}")
|
|
1978
2089
|
|
|
1979
2090
|
origin.pull()
|
|
1980
|
-
console.print(
|
|
2091
|
+
console.print(
|
|
2092
|
+
"Successfully updated llm_friendly_packages repository")
|
|
1981
2093
|
|
|
1982
2094
|
except git.exc.GitCommandError as e:
|
|
1983
2095
|
console.print(f"Error updating repository: {e}")
|
|
@@ -1999,7 +2111,8 @@ def lib_command(args: List[str]):
|
|
|
1999
2111
|
table.add_row(doc)
|
|
2000
2112
|
console.print(table)
|
|
2001
2113
|
else:
|
|
2002
|
-
console.print(
|
|
2114
|
+
console.print(
|
|
2115
|
+
f"No markdown files found for package: {package_name}")
|
|
2003
2116
|
|
|
2004
2117
|
else:
|
|
2005
2118
|
console.print(f"Unknown subcommand: {subcommand}")
|
|
@@ -2123,7 +2236,8 @@ def main():
|
|
|
2123
2236
|
FormattedText(prompt_message), default=new_prompt, style=style
|
|
2124
2237
|
)
|
|
2125
2238
|
else:
|
|
2126
|
-
user_input = session.prompt(
|
|
2239
|
+
user_input = session.prompt(
|
|
2240
|
+
FormattedText(prompt_message), style=style)
|
|
2127
2241
|
new_prompt = ""
|
|
2128
2242
|
|
|
2129
2243
|
if "mode" not in memory:
|
|
@@ -2148,13 +2262,14 @@ def main():
|
|
|
2148
2262
|
new_prompt = "/coding " + text
|
|
2149
2263
|
|
|
2150
2264
|
elif user_input.startswith("/add_files"):
|
|
2151
|
-
args = user_input[len("/add_files")
|
|
2265
|
+
args = user_input[len("/add_files"):].strip().split()
|
|
2152
2266
|
add_files(args)
|
|
2153
2267
|
elif user_input.startswith("/remove_files"):
|
|
2154
|
-
file_names = user_input[len(
|
|
2268
|
+
file_names = user_input[len(
|
|
2269
|
+
"/remove_files"):].strip().split(",")
|
|
2155
2270
|
remove_files(file_names)
|
|
2156
2271
|
elif user_input.startswith("/index/query"):
|
|
2157
|
-
query = user_input[len("/index/query")
|
|
2272
|
+
query = user_input[len("/index/query"):].strip()
|
|
2158
2273
|
index_query(query)
|
|
2159
2274
|
|
|
2160
2275
|
elif user_input.startswith("/index/build"):
|
|
@@ -2164,27 +2279,30 @@ def main():
|
|
|
2164
2279
|
list_files()
|
|
2165
2280
|
|
|
2166
2281
|
elif user_input.startswith("/mode"):
|
|
2167
|
-
conf = user_input[len("/mode")
|
|
2282
|
+
conf = user_input[len("/mode"):].strip()
|
|
2168
2283
|
if not conf:
|
|
2169
2284
|
print(memory["mode"])
|
|
2170
2285
|
else:
|
|
2171
2286
|
memory["mode"] = conf
|
|
2172
2287
|
|
|
2173
2288
|
elif user_input.startswith("/conf"):
|
|
2174
|
-
conf = user_input[len("/conf")
|
|
2289
|
+
conf = user_input[len("/conf"):].strip()
|
|
2175
2290
|
if not conf:
|
|
2176
2291
|
print(memory["conf"])
|
|
2177
2292
|
else:
|
|
2178
2293
|
configure(conf)
|
|
2179
2294
|
elif user_input.startswith("/revert"):
|
|
2180
2295
|
revert()
|
|
2296
|
+
elif user_input.startswith("/commit"):
|
|
2297
|
+
commit()
|
|
2181
2298
|
elif user_input.startswith("/help"):
|
|
2182
2299
|
show_help()
|
|
2183
2300
|
elif user_input.startswith("/exclude_dirs"):
|
|
2184
|
-
dir_names = user_input[len(
|
|
2301
|
+
dir_names = user_input[len(
|
|
2302
|
+
"/exclude_dirs"):].strip().split(",")
|
|
2185
2303
|
exclude_dirs(dir_names)
|
|
2186
2304
|
elif user_input.startswith("/ask"):
|
|
2187
|
-
query = user_input[len("/ask")
|
|
2305
|
+
query = user_input[len("/ask"):].strip()
|
|
2188
2306
|
if not query:
|
|
2189
2307
|
print("Please enter your question.")
|
|
2190
2308
|
else:
|
|
@@ -2194,38 +2312,38 @@ def main():
|
|
|
2194
2312
|
raise EOFError()
|
|
2195
2313
|
|
|
2196
2314
|
elif user_input.startswith("/coding"):
|
|
2197
|
-
query = user_input[len("/coding")
|
|
2315
|
+
query = user_input[len("/coding"):].strip()
|
|
2198
2316
|
if not query:
|
|
2199
2317
|
print("\033[91mPlease enter your request.\033[0m")
|
|
2200
2318
|
continue
|
|
2201
2319
|
coding(query)
|
|
2202
2320
|
elif user_input.startswith("/chat"):
|
|
2203
|
-
query = user_input[len("/chat")
|
|
2321
|
+
query = user_input[len("/chat"):].strip()
|
|
2204
2322
|
if not query:
|
|
2205
2323
|
print("\033[91mPlease enter your request.\033[0m")
|
|
2206
2324
|
else:
|
|
2207
2325
|
chat(query)
|
|
2208
2326
|
|
|
2209
2327
|
elif user_input.startswith("/design"):
|
|
2210
|
-
query = user_input[len("/design")
|
|
2328
|
+
query = user_input[len("/design"):].strip()
|
|
2211
2329
|
if not query:
|
|
2212
2330
|
print("\033[91mPlease enter your design request.\033[0m")
|
|
2213
2331
|
else:
|
|
2214
2332
|
design(query)
|
|
2215
2333
|
|
|
2216
2334
|
elif user_input.startswith("/summon"):
|
|
2217
|
-
query = user_input[len("/summon")
|
|
2335
|
+
query = user_input[len("/summon"):].strip()
|
|
2218
2336
|
if not query:
|
|
2219
2337
|
print("\033[91mPlease enter your request.\033[0m")
|
|
2220
2338
|
else:
|
|
2221
2339
|
summon(query)
|
|
2222
2340
|
|
|
2223
2341
|
elif user_input.startswith("/lib"):
|
|
2224
|
-
args = user_input[len("/lib")
|
|
2342
|
+
args = user_input[len("/lib"):].strip().split()
|
|
2225
2343
|
lib_command(args)
|
|
2226
2344
|
|
|
2227
2345
|
elif user_input.startswith("/debug"):
|
|
2228
|
-
code = user_input[len("/debug")
|
|
2346
|
+
code = user_input[len("/debug"):].strip()
|
|
2229
2347
|
try:
|
|
2230
2348
|
result = eval(code)
|
|
2231
2349
|
print(f"Debug result: {result}")
|
|
@@ -2236,7 +2354,7 @@ def main():
|
|
|
2236
2354
|
else:
|
|
2237
2355
|
command = user_input
|
|
2238
2356
|
if user_input.startswith("/shell"):
|
|
2239
|
-
command = user_input[len("/shell")
|
|
2357
|
+
command = user_input[len("/shell"):].strip()
|
|
2240
2358
|
if not command:
|
|
2241
2359
|
print("Please enter a shell command to execute.")
|
|
2242
2360
|
else:
|