auto-coder 0.1.243__py3-none-any.whl → 0.1.244__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.243.dist-info → auto_coder-0.1.244.dist-info}/METADATA +2 -2
- {auto_coder-0.1.243.dist-info → auto_coder-0.1.244.dist-info}/RECORD +17 -17
- autocoder/auto_coder.py +17 -0
- autocoder/chat_auto_coder.py +2 -2
- autocoder/chat_auto_coder_lang.py +5 -0
- autocoder/common/auto_coder_lang.py +11 -1
- autocoder/common/files.py +33 -1
- autocoder/index/index.py +1 -0
- autocoder/models.py +21 -21
- autocoder/suffixproject/__init__.py +2 -3
- autocoder/utils/auto_coder_utils/chat_stream_out.py +103 -227
- autocoder/utils/rest.py +45 -93
- autocoder/version.py +1 -1
- {auto_coder-0.1.243.dist-info → auto_coder-0.1.244.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.243.dist-info → auto_coder-0.1.244.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.243.dist-info → auto_coder-0.1.244.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.243.dist-info → auto_coder-0.1.244.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: auto-coder
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.244
|
|
4
4
|
Summary: AutoCoder: AutoCoder
|
|
5
5
|
Author: allwefantasy
|
|
6
6
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
@@ -26,7 +26,7 @@ Requires-Dist: tabulate
|
|
|
26
26
|
Requires-Dist: jupyter-client
|
|
27
27
|
Requires-Dist: prompt-toolkit
|
|
28
28
|
Requires-Dist: tokenizers
|
|
29
|
-
Requires-Dist: byzerllm[saas] >=0.1.
|
|
29
|
+
Requires-Dist: byzerllm[saas] >=0.1.160
|
|
30
30
|
Requires-Dist: patch
|
|
31
31
|
Requires-Dist: diff-match-patch
|
|
32
32
|
Requires-Dist: GitPython
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
autocoder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
autocoder/auto_coder.py,sha256=
|
|
2
|
+
autocoder/auto_coder.py,sha256=ghIEJ8NzcFr77fosIZhKxI5F55EZoU6DMHFFpw5OFso,62671
|
|
3
3
|
autocoder/auto_coder_lang.py,sha256=Rtupq6N3_HT7JRhDKdgCBcwRaiAnyCOR_Gsp4jUomrI,3229
|
|
4
4
|
autocoder/auto_coder_rag.py,sha256=illKgzP2bv-Tq50ujsofJnOHdI4pzr0ALtfR8NHHWdQ,22351
|
|
5
5
|
autocoder/auto_coder_rag_client_mcp.py,sha256=WV7j5JUiQge0x4-B7Hp5-pSAFXLbvLpzQMcCovbauIM,6276
|
|
6
6
|
autocoder/auto_coder_rag_mcp.py,sha256=-RrjNwFaS2e5v8XDIrKR-zlUNUE8UBaeOtojffBrvJo,8521
|
|
7
7
|
autocoder/auto_coder_server.py,sha256=XU9b4SBH7zjPPXaTWWHV4_zJm-XYa6njuLQaplYJH_c,20290
|
|
8
8
|
autocoder/benchmark.py,sha256=Ypomkdzd1T3GE6dRICY3Hj547dZ6_inqJbBJIp5QMco,4423
|
|
9
|
-
autocoder/chat_auto_coder.py,sha256=
|
|
10
|
-
autocoder/chat_auto_coder_lang.py,sha256=
|
|
9
|
+
autocoder/chat_auto_coder.py,sha256=RJC3Fh_9ywkllETWFgxapHK3aY0M9ORhRON9PNCiKZs,105338
|
|
10
|
+
autocoder/chat_auto_coder_lang.py,sha256=pdGkEMR96TvjYIzgWWB51LYmBYSrS_pO3sjGH-muuDI,15052
|
|
11
11
|
autocoder/command_args.py,sha256=9aYJ-AmPxP1sQh6ciw04FWHjSn31f2W9afXFwo8wgx4,30441
|
|
12
12
|
autocoder/lang.py,sha256=U6AjVV8Rs1uLyjFCZ8sT6WWuNUxMBqkXXIOs4S120uk,14511
|
|
13
|
-
autocoder/models.py,sha256=
|
|
14
|
-
autocoder/version.py,sha256=
|
|
13
|
+
autocoder/models.py,sha256=8Tabnz3wlVswaeTpfPxnBhN55enP_5sdAJIx4Z79nOo,5342
|
|
14
|
+
autocoder/version.py,sha256=nyjL74IBCp8tNAtI88ddAEba5PkcN70aC5Kdv_PKe7w,23
|
|
15
15
|
autocoder/agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
autocoder/agent/auto_demand_organizer.py,sha256=NWSAEsEk94vT3lGjfo25kKLMwYdPcpy9e-i21txPasQ,6942
|
|
17
17
|
autocoder/agent/auto_filegroup.py,sha256=CW7bqp0FW1GIEMnl-blyAc2UGT7O9Mom0q66ITz1ckM,6635
|
|
@@ -28,7 +28,7 @@ autocoder/common/__init__.py,sha256=2isE_u4VgfogwmcUCnFcussVFlzeNOLHDMFm5z_axbU,
|
|
|
28
28
|
autocoder/common/anything2images.py,sha256=0ILBbWzY02M-CiWB-vzuomb_J1hVdxRcenAfIrAXq9M,25283
|
|
29
29
|
autocoder/common/anything2img.py,sha256=4TREa-sOA-iargieUy7MpyCYVUE-9Mmq0wJtwomPqnE,7662
|
|
30
30
|
autocoder/common/audio.py,sha256=Kn9nWKQddWnUrAz0a_ZUgjcu4VUU_IcZBigT7n3N3qc,7439
|
|
31
|
-
autocoder/common/auto_coder_lang.py,sha256=
|
|
31
|
+
autocoder/common/auto_coder_lang.py,sha256=rIr4WJCUHgwkUkGwAaAiEd5kNx1nYRvVArbISbCfXp0,13248
|
|
32
32
|
autocoder/common/buildin_tokenizer.py,sha256=L7d5t39ZFvUd6EoMPXUhYK1toD0FHlRH1jtjKRGokWU,1236
|
|
33
33
|
autocoder/common/chunk_validation.py,sha256=BrR_ZWavW8IANuueEE7hS8NFAwEvm8TX34WnPx_1hs8,3030
|
|
34
34
|
autocoder/common/cleaner.py,sha256=NU72i8C6o9m0vXExab7nao5bstBUsfJFcj11cXa9l4U,1089
|
|
@@ -46,7 +46,7 @@ autocoder/common/command_completer.py,sha256=SSeb8MDH0JPvfdyW-S2uaHnui4VBDfSQvQP
|
|
|
46
46
|
autocoder/common/command_generator.py,sha256=v4LmU7sO-P7jEZIXCWHUC6P-vT7AvBi_x_PTwCqBAE8,1323
|
|
47
47
|
autocoder/common/command_templates.py,sha256=mnB3n8i0yjH1mqzyClEg8Wpr9VbZV44kxky66Zu6OJY,8557
|
|
48
48
|
autocoder/common/const.py,sha256=eTjhjh4Aj4CUzviJ81jaf3Y5cwqsLATySn2wJxaS6RQ,2911
|
|
49
|
-
autocoder/common/files.py,sha256=
|
|
49
|
+
autocoder/common/files.py,sha256=CguxG9digkWBJpRaILErZmL_G5ryPRahPmPFWGB7X18,1973
|
|
50
50
|
autocoder/common/git_utils.py,sha256=btK45sxvfm4tX3fBRNUPRZoGQuZuOEQrWSAwLy1yoLw,23095
|
|
51
51
|
autocoder/common/image_to_page.py,sha256=O0cNO_vHHUP-fP4GXiVojShmNqkPnZXeIyiY1MRLpKg,13936
|
|
52
52
|
autocoder/common/interpreter.py,sha256=62-dIakOunYB4yjmX8SHC0Gdy2h8NtxdgbpdqRZJ5vk,2833
|
|
@@ -79,7 +79,7 @@ autocoder/dispacher/actions/plugins/action_translate.py,sha256=nVAtRSQpdGNmZxg1R
|
|
|
79
79
|
autocoder/index/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
80
80
|
autocoder/index/entry.py,sha256=KJaxqtaKgL27w8-j7OiAqI0anPpmrJSl7PkfeVF2ipE,11713
|
|
81
81
|
autocoder/index/for_command.py,sha256=BFvljE4t6VaMBGboZAuhUCzVK0EitCy_n5D_7FEnihw,3204
|
|
82
|
-
autocoder/index/index.py,sha256=
|
|
82
|
+
autocoder/index/index.py,sha256=VjfcBYHywU4tjQTA7mpHfzRM8nBPhPHrUnkuBbsj6do,20409
|
|
83
83
|
autocoder/index/symbols_utils.py,sha256=CjcjUVajmJZB75Ty3a7kMv1BZphrm-tIBAdOJv6uo-0,2037
|
|
84
84
|
autocoder/index/types.py,sha256=a2s_KV5FJlq7jqA2ELSo9E1sjuLwDB-JJYMhSpzBAhU,596
|
|
85
85
|
autocoder/index/filter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -119,7 +119,7 @@ autocoder/rag/stream_event/event_writer.py,sha256=l7kq_LnDDE8E5dZ-73C7J2MgzSL7Wr
|
|
|
119
119
|
autocoder/rag/stream_event/types.py,sha256=rtLwOE8rShmi1dJdxyBpAV5ZjLBGG9vptMiSzMxGuIA,318
|
|
120
120
|
autocoder/regex_project/__init__.py,sha256=EBZeCL5ORyD_9_5u_UuG4s7XtpXOu0y1sWDmxWFtufE,6781
|
|
121
121
|
autocoder/regexproject/__init__.py,sha256=cEr-ZOaQjLD5sx7T7F2DhD5ips03HcJ02rded9EpSXc,9693
|
|
122
|
-
autocoder/suffixproject/__init__.py,sha256=
|
|
122
|
+
autocoder/suffixproject/__init__.py,sha256=VcXjUbGf3uQrpoqVCItDvGG9DoeHJ_qEmghKwrVNw9w,11058
|
|
123
123
|
autocoder/tsproject/__init__.py,sha256=yloVzkGLnbTd4Hcj9fMO-rcjNTTx4wI3Ga41LWOSYrY,11747
|
|
124
124
|
autocoder/utils/__init__.py,sha256=KtcGElFNBgZPF7dEL8zF9JpXkCAjoyDrzaREJBhJrcs,994
|
|
125
125
|
autocoder/utils/_markitdown.py,sha256=RU88qn4eZfYIy0GDrPxlI8oYXIypbi63VRJjdlnE0VU,47431
|
|
@@ -134,15 +134,15 @@ autocoder/utils/print_table.py,sha256=ZMRhCA9DD0FUfKyJBWd5bDdj1RrtPtgOMWSJwtvZcL
|
|
|
134
134
|
autocoder/utils/queue_communicate.py,sha256=buyEzdvab1QA4i2QKbq35rG5v_9x9PWVLWWMTznWcYM,6832
|
|
135
135
|
autocoder/utils/request_event_queue.py,sha256=r3lo5qGsB1dIjzVQ05dnr0z_9Z3zOkBdP1vmRciKdi4,2095
|
|
136
136
|
autocoder/utils/request_queue.py,sha256=nwp6PMtgTCiuwJI24p8OLNZjUiprC-TsefQrhMI-yPE,3889
|
|
137
|
-
autocoder/utils/rest.py,sha256=
|
|
137
|
+
autocoder/utils/rest.py,sha256=hLBhr78y-WVnV0oQf9Rxc22EwqF78KINkScvYa1MuYA,6435
|
|
138
138
|
autocoder/utils/tests.py,sha256=BqphrwyycGAvs-5mhH8pKtMZdObwhFtJ5MC_ZAOiLq8,1340
|
|
139
139
|
autocoder/utils/types.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
140
140
|
autocoder/utils/auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
141
|
-
autocoder/utils/auto_coder_utils/chat_stream_out.py,sha256=
|
|
141
|
+
autocoder/utils/auto_coder_utils/chat_stream_out.py,sha256=yzh3QYJdYC1CPcdhSTn0fmFHtqV8iSXeH0drV3HjN5A,9053
|
|
142
142
|
autocoder/utils/chat_auto_coder_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
143
|
-
auto_coder-0.1.
|
|
144
|
-
auto_coder-0.1.
|
|
145
|
-
auto_coder-0.1.
|
|
146
|
-
auto_coder-0.1.
|
|
147
|
-
auto_coder-0.1.
|
|
148
|
-
auto_coder-0.1.
|
|
143
|
+
auto_coder-0.1.244.dist-info/LICENSE,sha256=HrhfyXIkWY2tGFK11kg7vPCqhgh5DcxleloqdhrpyMY,11558
|
|
144
|
+
auto_coder-0.1.244.dist-info/METADATA,sha256=EVj3424BKEVPU6GAnoHC-NQ4J2VQFT7kVt3ANVby28A,2616
|
|
145
|
+
auto_coder-0.1.244.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
146
|
+
auto_coder-0.1.244.dist-info/entry_points.txt,sha256=0nzHtHH4pNcM7xq4EBA2toS28Qelrvcbrr59GqD_0Ak,350
|
|
147
|
+
auto_coder-0.1.244.dist-info/top_level.txt,sha256=Jqc0_uJSw2GwoFQAa9iJxYns-2mWla-9ok_Y3Gcznjk,10
|
|
148
|
+
auto_coder-0.1.244.dist-info/RECORD,,
|
autocoder/auto_coder.py
CHANGED
|
@@ -692,6 +692,23 @@ def main(input_args: Optional[List[str]] = None):
|
|
|
692
692
|
)
|
|
693
693
|
llm.setup_sub_client("vl_model", vl_model)
|
|
694
694
|
|
|
695
|
+
if args.index_model:
|
|
696
|
+
model_name = args.index_model.strip()
|
|
697
|
+
model_info = models_module.get_model_by_name(model_name)
|
|
698
|
+
index_model = byzerllm.SimpleByzerLLM(default_model_name=model_name)
|
|
699
|
+
index_model.deploy(
|
|
700
|
+
model_path="",
|
|
701
|
+
pretrained_model_type="saas/openai",
|
|
702
|
+
udf_name=model_name,
|
|
703
|
+
infer_params={
|
|
704
|
+
"saas.base_url": model_info["base_url"],
|
|
705
|
+
"saas.api_key": model_info["api_key"],
|
|
706
|
+
"saas.model": model_info["model_name"],
|
|
707
|
+
"saas.is_reasoning": model_info["is_reasoning"]
|
|
708
|
+
}
|
|
709
|
+
)
|
|
710
|
+
llm.setup_sub_client("index_model", index_model)
|
|
711
|
+
|
|
695
712
|
if args.sd_model:
|
|
696
713
|
model_name = args.sd_model.strip()
|
|
697
714
|
model_info = models_module.get_model_by_name(model_name)
|
autocoder/chat_auto_coder.py
CHANGED
|
@@ -1605,8 +1605,8 @@ def code_next(query: str):
|
|
|
1605
1605
|
if os.path.exists(temp_yaml):
|
|
1606
1606
|
os.remove(temp_yaml)
|
|
1607
1607
|
|
|
1608
|
-
|
|
1609
|
-
|
|
1608
|
+
product_mode = conf.get("product_mode", "lite")
|
|
1609
|
+
llm = get_single_llm(args.chat_model or args.model, product_mode=product_mode)
|
|
1610
1610
|
|
|
1611
1611
|
auto_guesser = AutoGuessQuery(
|
|
1612
1612
|
llm=llm, project_dir=os.getcwd(), skip_diff=True)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import locale
|
|
2
|
+
from byzerllm.utils import format_str_jinja2
|
|
2
3
|
|
|
3
4
|
MESSAGES = {
|
|
4
5
|
"en": {
|
|
@@ -236,3 +237,7 @@ def get_system_language():
|
|
|
236
237
|
def get_message(key):
|
|
237
238
|
lang = get_system_language()
|
|
238
239
|
return MESSAGES.get(lang, MESSAGES['en']).get(key, MESSAGES['en'][key])
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def get_message_with_format(msg_key: str, **kwargs):
|
|
243
|
+
return format_str_jinja2(get_message(msg_key), **kwargs)
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import locale
|
|
2
|
+
from byzerllm.utils import format_str_jinja2
|
|
2
3
|
|
|
3
4
|
MESSAGES = {
|
|
4
|
-
"en": {
|
|
5
|
+
"en": {
|
|
6
|
+
"model_not_found": "Model {{model_name}} not found",
|
|
5
7
|
"new_session_started": "New session started. Previous chat history has been archived.",
|
|
6
8
|
"memory_save_success": "✅ Saved to your memory",
|
|
9
|
+
"file_decode_error": "Failed to decode file: {{file_path}}. Tried encodings: {{encodings}}",
|
|
10
|
+
"file_write_error": "Failed to write file: {{file_path}}. Error: {{error}}",
|
|
7
11
|
"index_file_too_large": "⚠️ File {{ file_path }} is too large ({{ file_size }} > {{ max_length }}), splitting into chunks...",
|
|
8
12
|
"index_update_success": "✅ Successfully updated index for {{ file_path }} (md5: {{ md5 }}) in {{ duration }}s",
|
|
9
13
|
"index_build_error": "❌ Error building index for {{ file_path }}: {{ error }}",
|
|
@@ -73,8 +77,11 @@ MESSAGES = {
|
|
|
73
77
|
"git_init_required": "⚠️ auto_merge only applies to git repositories.\n\nPlease try using git init in the source directory:\n\n```shell\ncd {{ source_dir }}\ngit init.\n```\n\nThen run auto - coder again.\nError: {{ error }}"
|
|
74
78
|
},
|
|
75
79
|
"zh": {
|
|
80
|
+
"model_not_found": "未找到模型: {{model_name}}",
|
|
76
81
|
"new_session_started": "新会话已开始。之前的聊天历史已存档。",
|
|
77
82
|
"memory_save_success": "✅ 已保存到您的记忆中",
|
|
83
|
+
"file_decode_error": "无法解码文件: {{file_path}}。尝试的编码: {{encodings}}",
|
|
84
|
+
"file_write_error": "无法写入文件: {{file_path}}. 错误: {{error}}",
|
|
78
85
|
"index_file_too_large": "⚠️ 文件 {{ file_path }} 过大 ({{ file_size }} > {{ max_length }}), 正在分块处理...",
|
|
79
86
|
"index_update_success": "✅ 成功更新 {{ file_path }} 的索引 (md5: {{ md5 }}), 耗时 {{ duration }} 秒",
|
|
80
87
|
"index_build_error": "❌ 构建 {{ file_path }} 索引时出错: {{ error }}",
|
|
@@ -156,3 +163,6 @@ def get_system_language():
|
|
|
156
163
|
def get_message(key):
|
|
157
164
|
lang = get_system_language()
|
|
158
165
|
return MESSAGES.get(lang, MESSAGES['en']).get(key, MESSAGES['en'][key])
|
|
166
|
+
|
|
167
|
+
def get_message_with_format(msg_key: str, **kwargs):
|
|
168
|
+
return format_str_jinja2(get_message(msg_key), **kwargs)
|
autocoder/common/files.py
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
from autocoder.common.auto_coder_lang import get_message_with_format
|
|
2
|
+
from typing import List, Dict, Union
|
|
3
|
+
|
|
1
4
|
def read_file(file_path):
|
|
2
5
|
"""Read a file with automatic encoding detection.
|
|
3
6
|
|
|
@@ -23,4 +26,33 @@ def read_file(file_path):
|
|
|
23
26
|
except UnicodeDecodeError:
|
|
24
27
|
continue
|
|
25
28
|
|
|
26
|
-
raise ValueError(
|
|
29
|
+
raise ValueError(get_message_with_format("file_decode_error",
|
|
30
|
+
file_path=file_path,
|
|
31
|
+
encodings=", ".join(encodings)))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def save_file(file_path: str, content: Union[str, List[str]]) -> None:
|
|
36
|
+
"""Save content to a file using UTF-8 encoding.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
file_path (str): Path to the file to write
|
|
40
|
+
content (Union[str, List[str]]): Content to write to the file.
|
|
41
|
+
Can be a string or list of strings (will be joined with newlines)
|
|
42
|
+
|
|
43
|
+
Raises:
|
|
44
|
+
IOError: If the file cannot be written
|
|
45
|
+
TypeError: If content is neither str nor List[str]
|
|
46
|
+
"""
|
|
47
|
+
try:
|
|
48
|
+
with open(file_path, 'w', encoding='utf-8') as f:
|
|
49
|
+
if isinstance(content, str):
|
|
50
|
+
f.write(content)
|
|
51
|
+
elif isinstance(content, list):
|
|
52
|
+
f.write('\n'.join(content))
|
|
53
|
+
else:
|
|
54
|
+
raise TypeError("Content must be either str or List[str]")
|
|
55
|
+
except IOError as e:
|
|
56
|
+
raise IOError(get_message_with_format("file_write_error",
|
|
57
|
+
file_path=file_path,
|
|
58
|
+
error=str(e)))
|
autocoder/index/index.py
CHANGED
autocoder/models.py
CHANGED
|
@@ -36,6 +36,22 @@ default_models_list = [
|
|
|
36
36
|
}
|
|
37
37
|
]
|
|
38
38
|
|
|
39
|
+
def process_api_key_path(base_url: str) -> str:
|
|
40
|
+
"""
|
|
41
|
+
从 base_url 中提取 host 部分并处理特殊字符
|
|
42
|
+
例如: https://api.example.com:8080/v1 -> api.example.com_8080
|
|
43
|
+
"""
|
|
44
|
+
if not base_url:
|
|
45
|
+
return ""
|
|
46
|
+
|
|
47
|
+
parsed = urlparse(base_url)
|
|
48
|
+
host = parsed.netloc
|
|
49
|
+
|
|
50
|
+
# 将冒号替换为下划线
|
|
51
|
+
host = host.replace(":", "_")
|
|
52
|
+
|
|
53
|
+
return host
|
|
54
|
+
|
|
39
55
|
def load_models() -> List[Dict]:
|
|
40
56
|
"""
|
|
41
57
|
Load models from ~/.auto-coder/keys/models.json and merge with default_models_list.
|
|
@@ -73,7 +89,7 @@ def load_models() -> List[Dict]:
|
|
|
73
89
|
api_key_file = os.path.join(api_key_dir, model["api_key_path"])
|
|
74
90
|
if os.path.exists(api_key_file):
|
|
75
91
|
with open(api_key_file, "r") as f:
|
|
76
|
-
model["api_key"] = f.read()
|
|
92
|
+
model["api_key"] = f.read()
|
|
77
93
|
return target_models
|
|
78
94
|
|
|
79
95
|
def save_models(models: List[Dict]) -> None:
|
|
@@ -85,22 +101,6 @@ def save_models(models: List[Dict]) -> None:
|
|
|
85
101
|
json.dump(models, f, indent=2, ensure_ascii=False)
|
|
86
102
|
|
|
87
103
|
|
|
88
|
-
def process_api_key_path(base_url: str) -> str:
|
|
89
|
-
"""
|
|
90
|
-
从 base_url 中提取 host 部分并处理特殊字符
|
|
91
|
-
例如: https://api.example.com:8080/v1 -> api.example.com_8080
|
|
92
|
-
"""
|
|
93
|
-
if not base_url:
|
|
94
|
-
return ""
|
|
95
|
-
|
|
96
|
-
parsed = urlparse(base_url)
|
|
97
|
-
host = parsed.netloc
|
|
98
|
-
|
|
99
|
-
# 将冒号替换为下划线
|
|
100
|
-
host = host.replace(":", "_")
|
|
101
|
-
|
|
102
|
-
return host
|
|
103
|
-
|
|
104
104
|
def get_model_by_name(name: str) -> Dict:
|
|
105
105
|
"""
|
|
106
106
|
根据模型名称查找模型
|
|
@@ -109,7 +109,8 @@ def get_model_by_name(name: str) -> Dict:
|
|
|
109
109
|
v = [m for m in models if m["name"] == name.strip()]
|
|
110
110
|
|
|
111
111
|
if len(v) == 0:
|
|
112
|
-
|
|
112
|
+
from autocoder.common.auto_coder_lang import get_message_with_format
|
|
113
|
+
raise Exception(get_message_with_format("model_not_found", model_name=name))
|
|
113
114
|
return v[0]
|
|
114
115
|
|
|
115
116
|
def update_model_with_api_key(name: str, api_key: str) -> Dict:
|
|
@@ -135,9 +136,8 @@ def update_model_with_api_key(name: str, api_key: str) -> Dict:
|
|
|
135
136
|
|
|
136
137
|
if not found_model:
|
|
137
138
|
return None
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
api_key_path = process_api_key_path(found_model["base_url"])
|
|
139
|
+
|
|
140
|
+
api_key_path = name
|
|
141
141
|
if api_key_path:
|
|
142
142
|
found_model["api_key_path"] = api_key_path
|
|
143
143
|
|
|
@@ -36,9 +36,8 @@ class SuffixProject:
|
|
|
36
36
|
self.target_file = args.target_file
|
|
37
37
|
self.project_type = args.project_type
|
|
38
38
|
self.suffixs = [
|
|
39
|
-
|
|
40
|
-
for suffix in self.project_type.split(",")
|
|
41
|
-
if suffix.strip() != ""
|
|
39
|
+
suffix.strip() if suffix.startswith(".") else f".{suffix.strip()}"
|
|
40
|
+
for suffix in self.project_type.split(",") if suffix.strip()
|
|
42
41
|
]
|
|
43
42
|
self.file_filter = file_filter
|
|
44
43
|
self.sources = []
|
|
@@ -11,256 +11,132 @@ from autocoder.utils.request_queue import request_queue
|
|
|
11
11
|
import time
|
|
12
12
|
|
|
13
13
|
MAX_HISTORY_LINES = 40 # 最大保留历史行数
|
|
14
|
-
LAYOUT_TYPES = Literal["vertical", "horizontal"]
|
|
15
14
|
|
|
16
|
-
class
|
|
17
|
-
def __init__(self,
|
|
18
|
-
self.
|
|
19
|
-
self.
|
|
20
|
-
self.queue = Queue()
|
|
15
|
+
class StreamRenderer:
|
|
16
|
+
def __init__(self, title: str):
|
|
17
|
+
self.title = title
|
|
18
|
+
self.content = ""
|
|
21
19
|
self.lock = Lock()
|
|
22
|
-
self.
|
|
23
|
-
self.workers = []
|
|
24
|
-
self.layout_type = layout_type
|
|
25
|
-
self.stream_count = 0
|
|
26
|
-
|
|
27
|
-
def _create_stream_panel(self, idx: int) -> Layout:
|
|
28
|
-
"""创建流面板布局"""
|
|
29
|
-
# 计算安全高度
|
|
30
|
-
current_height = self.console.height or 24 # 默认24行防止获取失败
|
|
31
|
-
safe_height = max(min(50, current_height // 2 - 4), 5) # 限制最小高度为5行
|
|
32
|
-
|
|
33
|
-
# 使用整数设置 Layout 的 size
|
|
34
|
-
panel = Layout(name=f"stream-{idx}", size=safe_height)
|
|
35
|
-
|
|
36
|
-
panel.update(
|
|
37
|
-
Panel(
|
|
38
|
-
Markdown(""),
|
|
39
|
-
title=f"Stream {idx + 1}",
|
|
40
|
-
border_style="green",
|
|
41
|
-
height=safe_height # 确保数值有效
|
|
42
|
-
)
|
|
43
|
-
)
|
|
44
|
-
return panel
|
|
45
|
-
|
|
46
|
-
def prepare_layout(self, count: int):
|
|
47
|
-
"""准备动态布局结构"""
|
|
48
|
-
self.stream_count = count
|
|
49
|
-
|
|
50
|
-
# 创建一个主布局容器
|
|
51
|
-
streams_layout = Layout(name="streams")
|
|
52
|
-
|
|
53
|
-
# 创建所有流的布局
|
|
54
|
-
stream_layouts = []
|
|
55
|
-
for i in range(count):
|
|
56
|
-
stream_layout = Layout(name=f"stream-{i}")
|
|
57
|
-
panel = self._create_stream_panel(i)
|
|
58
|
-
stream_layout.update(panel)
|
|
59
|
-
stream_layouts.append(stream_layout)
|
|
60
|
-
|
|
61
|
-
# 将所有流添加到主布局
|
|
62
|
-
if stream_layouts:
|
|
63
|
-
streams_layout.update(stream_layouts[0])
|
|
64
|
-
for i in range(1, len(stream_layouts)):
|
|
65
|
-
if self.layout_type == "vertical":
|
|
66
|
-
streams_layout.split_column(stream_layouts[i])
|
|
67
|
-
elif self.layout_type == "horizontal":
|
|
68
|
-
streams_layout.split_row(stream_layouts[i])
|
|
69
|
-
else:
|
|
70
|
-
streams_layout.split_column(stream_layouts[i])
|
|
20
|
+
self.is_complete = False
|
|
71
21
|
|
|
72
|
-
|
|
73
|
-
self.layout.split(
|
|
74
|
-
Layout(name="header", size=1),
|
|
75
|
-
streams_layout
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
def update_panel(self, idx: int, content: str, final: bool = False):
|
|
79
|
-
"""线程安全的面板更新方法"""
|
|
22
|
+
def update(self, content: str):
|
|
80
23
|
with self.lock:
|
|
81
|
-
|
|
82
|
-
safe_height = min(50, self.console.height // 2 - 4)
|
|
24
|
+
self.content += content
|
|
83
25
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
else:
|
|
92
|
-
new_panel = Panel(
|
|
93
|
-
Markdown(content),
|
|
94
|
-
title=f"Stream {idx+1}",
|
|
95
|
-
border_style="green",
|
|
96
|
-
height=safe_height
|
|
97
|
-
)
|
|
26
|
+
def get_content(self) -> str:
|
|
27
|
+
with self.lock:
|
|
28
|
+
return self.content
|
|
29
|
+
|
|
30
|
+
def complete(self):
|
|
31
|
+
with self.lock:
|
|
32
|
+
self.is_complete = True
|
|
98
33
|
|
|
99
|
-
|
|
100
|
-
|
|
34
|
+
class MultiStreamRenderer:
|
|
35
|
+
def __init__(self, stream_titles: List[str], layout: str = "horizontal", console: Optional[Console] = None):
|
|
36
|
+
"""
|
|
37
|
+
Initialize multi-stream renderer
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
stream_titles: List of titles for each stream
|
|
41
|
+
layout: "horizontal" or "vertical"
|
|
42
|
+
console: Rich console instance
|
|
43
|
+
"""
|
|
44
|
+
if console is None:
|
|
45
|
+
console = Console(force_terminal=True, color_system="auto")
|
|
101
46
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
47
|
+
self.console = console
|
|
48
|
+
self.layout_type = layout
|
|
49
|
+
self.streams = [StreamRenderer(title) for title in stream_titles]
|
|
50
|
+
self.layout = Layout()
|
|
51
|
+
|
|
52
|
+
# Create named layouts for each stream
|
|
53
|
+
self.stream_layouts = [Layout(name=f"stream{i}") for i in range(len(stream_titles))]
|
|
54
|
+
|
|
55
|
+
# Configure layout
|
|
56
|
+
if layout == "horizontal":
|
|
57
|
+
self.layout.split_row(*self.stream_layouts)
|
|
58
|
+
else:
|
|
59
|
+
self.layout.split_column(*self.stream_layouts)
|
|
111
60
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
61
|
+
def _process_stream(self,
|
|
62
|
+
stream_idx: int,
|
|
63
|
+
stream_generator: Generator[Tuple[str, Dict[str, Any]], None, None]):
|
|
64
|
+
"""Process a single stream in a separate thread"""
|
|
65
|
+
stream = self.streams[stream_idx]
|
|
66
|
+
try:
|
|
67
|
+
for content, meta in stream_generator:
|
|
68
|
+
if content:
|
|
69
|
+
stream.update(content)
|
|
70
|
+
finally:
|
|
71
|
+
stream.complete()
|
|
119
72
|
|
|
120
|
-
def
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
lines_buffer = []
|
|
128
|
-
current_line = ""
|
|
129
|
-
assistant_response = ""
|
|
130
|
-
last_meta = None
|
|
131
|
-
|
|
132
|
-
try:
|
|
133
|
-
for res in generator:
|
|
134
|
-
content, meta = res
|
|
135
|
-
last_meta = meta
|
|
73
|
+
def render_streams(self,
|
|
74
|
+
stream_generators: List[Generator[Tuple[str, Dict[str, Any]], None, None]]) -> List[str]:
|
|
75
|
+
"""
|
|
76
|
+
Render multiple streams simultaneously
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
stream_generators: List of stream generators to render
|
|
136
80
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
81
|
+
Returns:
|
|
82
|
+
List of final content from each stream
|
|
83
|
+
"""
|
|
84
|
+
assert len(stream_generators) == len(self.streams), "Number of generators must match number of streams"
|
|
85
|
+
|
|
86
|
+
# Start processing threads
|
|
87
|
+
threads = []
|
|
88
|
+
for i, generator in enumerate(stream_generators):
|
|
89
|
+
thread = Thread(target=self._process_stream, args=(i, generator))
|
|
90
|
+
thread.daemon = True
|
|
91
|
+
thread.start()
|
|
92
|
+
threads.append(thread)
|
|
145
93
|
|
|
146
|
-
|
|
147
|
-
|
|
94
|
+
try:
|
|
95
|
+
with Live(self.layout, console=self.console, refresh_per_second=10) as live:
|
|
96
|
+
while any(not stream.is_complete for stream in self.streams):
|
|
97
|
+
# Update all panels
|
|
98
|
+
for i, stream in enumerate(self.streams):
|
|
99
|
+
panel = Panel(
|
|
100
|
+
Markdown(stream.get_content() or "Waiting..."),
|
|
101
|
+
title=stream.title,
|
|
102
|
+
border_style="green" if not stream.is_complete else "blue"
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
# Update appropriate layout section
|
|
106
|
+
self.stream_layouts[i].update(panel)
|
|
107
|
+
|
|
108
|
+
time.sleep(0.1) # Prevent excessive CPU usage
|
|
109
|
+
|
|
110
|
+
except KeyboardInterrupt:
|
|
111
|
+
print("\nStopping streams...")
|
|
148
112
|
|
|
149
|
-
|
|
113
|
+
# Wait for all threads to complete
|
|
114
|
+
for thread in threads:
|
|
115
|
+
thread.join()
|
|
150
116
|
|
|
151
|
-
|
|
152
|
-
request_queue.add_request(
|
|
153
|
-
request_id,
|
|
154
|
-
RequestValue(
|
|
155
|
-
value=StreamValue(value=[content]),
|
|
156
|
-
status=RequestOption.RUNNING,
|
|
157
|
-
),
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
if current_line:
|
|
161
|
-
lines_buffer.append(current_line)
|
|
162
|
-
controller.queue.put((idx, assistant_response, True))
|
|
163
|
-
return assistant_response, last_meta
|
|
164
|
-
|
|
165
|
-
except Exception as e:
|
|
166
|
-
error_content = f"Error: {str(e)}"
|
|
167
|
-
controller.queue.put((idx, error_content, True))
|
|
168
|
-
if request_id and request_queue:
|
|
169
|
-
request_queue.add_request(
|
|
170
|
-
request_id,
|
|
171
|
-
RequestValue(
|
|
172
|
-
value=StreamValue(value=[str(e)]),
|
|
173
|
-
status=RequestOption.FAILED
|
|
174
|
-
),
|
|
175
|
-
)
|
|
176
|
-
return assistant_response, last_meta
|
|
177
|
-
finally:
|
|
178
|
-
if request_id and request_queue:
|
|
179
|
-
request_queue.add_request(
|
|
180
|
-
request_id,
|
|
181
|
-
RequestValue(
|
|
182
|
-
value=StreamValue(value=[""]),
|
|
183
|
-
status=RequestOption.COMPLETED
|
|
184
|
-
),
|
|
185
|
-
)
|
|
117
|
+
return [stream.get_content() for stream in self.streams]
|
|
186
118
|
|
|
187
119
|
def multi_stream_out(
|
|
188
120
|
stream_generators: List[Generator[Tuple[str, Dict[str, Any]], None, None]],
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
) -> List[
|
|
121
|
+
titles: List[str],
|
|
122
|
+
layout: str = "horizontal",
|
|
123
|
+
console: Optional[Console] = None
|
|
124
|
+
) -> List[str]:
|
|
193
125
|
"""
|
|
194
|
-
|
|
126
|
+
Render multiple streams with Rich
|
|
195
127
|
|
|
196
128
|
Args:
|
|
197
|
-
stream_generators:
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
129
|
+
stream_generators: List of stream generators
|
|
130
|
+
titles: List of titles for each stream
|
|
131
|
+
layout: "horizontal" or "vertical"
|
|
132
|
+
console: Optional Rich console instance
|
|
201
133
|
|
|
202
134
|
Returns:
|
|
203
|
-
List
|
|
135
|
+
List of final content from each stream
|
|
204
136
|
"""
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
console = Console(force_terminal=True, color_system="auto", height=24)
|
|
208
|
-
|
|
209
|
-
# 初始化控制器
|
|
210
|
-
controller = StreamController(layout_type, console=console)
|
|
211
|
-
stream_count = len(stream_generators)
|
|
212
|
-
controller.prepare_layout(stream_count)
|
|
213
|
-
|
|
214
|
-
# 启动工作线程
|
|
215
|
-
results = [None] * stream_count
|
|
216
|
-
threads = []
|
|
217
|
-
|
|
218
|
-
# 创建工作线程
|
|
219
|
-
def worker_target(idx: int, gen: Generator[Tuple[str, Dict[str, Any]], None, None]):
|
|
220
|
-
req_id = request_ids[idx] if request_ids and idx < len(request_ids) else None
|
|
221
|
-
results[idx] = stream_worker(idx, gen, controller, req_id)
|
|
222
|
-
|
|
223
|
-
# 启动所有工作线程
|
|
224
|
-
for idx, gen in enumerate(stream_generators):
|
|
225
|
-
t = Thread(target=worker_target, args=(idx, gen))
|
|
226
|
-
t.start()
|
|
227
|
-
threads.append(t)
|
|
228
|
-
|
|
229
|
-
# 主渲染线程
|
|
230
|
-
try:
|
|
231
|
-
with Live(
|
|
232
|
-
controller.layout,
|
|
233
|
-
console=console or controller.console,
|
|
234
|
-
refresh_per_second=10,
|
|
235
|
-
screen=True
|
|
236
|
-
) as live:
|
|
237
|
-
while controller.running:
|
|
238
|
-
updated = False
|
|
239
|
-
try:
|
|
240
|
-
while True: # 处理队列中的所有更新
|
|
241
|
-
idx, content, final = controller.queue.get_nowait()
|
|
242
|
-
controller.update_panel(idx, content, final)
|
|
243
|
-
updated = True
|
|
244
|
-
except Empty:
|
|
245
|
-
pass
|
|
246
|
-
|
|
247
|
-
if updated:
|
|
248
|
-
live.refresh()
|
|
249
|
-
|
|
250
|
-
# 检查线程是否全部完成
|
|
251
|
-
if all(not t.is_alive() for t in threads):
|
|
252
|
-
break
|
|
253
|
-
|
|
254
|
-
time.sleep(0.1)
|
|
255
|
-
|
|
256
|
-
finally:
|
|
257
|
-
controller.running = False
|
|
258
|
-
for t in threads:
|
|
259
|
-
t.join()
|
|
137
|
+
renderer = MultiStreamRenderer(titles, layout, console)
|
|
138
|
+
return renderer.render_streams(stream_generators)
|
|
260
139
|
|
|
261
|
-
# 确保最后一次刷新
|
|
262
|
-
(console or controller.console).print(controller.layout)
|
|
263
|
-
return results
|
|
264
140
|
|
|
265
141
|
def stream_out(
|
|
266
142
|
stream_generator: Generator[Tuple[str, Dict[str, Any]], None, None],
|
autocoder/utils/rest.py
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
import requests
|
|
2
2
|
from bs4 import BeautifulSoup
|
|
3
|
-
from typing import List,Dict,
|
|
3
|
+
from typing import List,Dict,Union,Optional
|
|
4
4
|
from autocoder.common import SourceCode
|
|
5
5
|
import byzerllm
|
|
6
|
-
from bs4 import BeautifulSoup
|
|
7
6
|
from loguru import logger
|
|
8
7
|
import os
|
|
9
8
|
from pathlib import Path
|
|
10
9
|
from autocoder.common import files as FileUtils
|
|
10
|
+
import traceback
|
|
11
|
+
from autocoder.rag.loaders import (
|
|
12
|
+
extract_text_from_pdf,
|
|
13
|
+
extract_text_from_docx,
|
|
14
|
+
extract_text_from_ppt,
|
|
15
|
+
extract_text_from_excel
|
|
16
|
+
)
|
|
11
17
|
|
|
12
18
|
class HttpDoc:
|
|
13
|
-
def __init__(self, args, llm: byzerllm.ByzerLLM,urls:Optional[List[str]]=None):
|
|
19
|
+
def __init__(self, args, llm: Union[byzerllm.ByzerLLM, byzerllm.SimpleByzerLLM],urls:Optional[List[str]]=None):
|
|
14
20
|
self.args = args
|
|
15
21
|
urls_from_args = self.args.urls
|
|
16
22
|
if urls_from_args:
|
|
@@ -41,104 +47,50 @@ class HttpDoc:
|
|
|
41
47
|
{{ html }}
|
|
42
48
|
|
|
43
49
|
输出的内容请以 "<MARKER></MARKER> 标签对包裹。
|
|
44
|
-
"""
|
|
45
|
-
|
|
46
|
-
def is_binary_file(self,filepath):
|
|
47
|
-
try:
|
|
48
|
-
with open(filepath, 'rb') as file:
|
|
49
|
-
chunk = file.read(1024*8) # Read first 1024 bytes
|
|
50
|
-
if b'\x00' in chunk: # Binary files often contain null bytes
|
|
51
|
-
return True
|
|
52
|
-
# Attempt to decode as UTF-8 (or any encoding you expect your text files to be in)
|
|
53
|
-
chunk.decode('utf-8')
|
|
54
|
-
return False
|
|
55
|
-
except UnicodeDecodeError:
|
|
56
|
-
return True
|
|
50
|
+
"""
|
|
57
51
|
|
|
58
|
-
def
|
|
52
|
+
def _process_local_file(self, file_path: str) -> List[SourceCode]:
|
|
53
|
+
"""统一处理本地文件,返回标准化的 SourceCode 列表"""
|
|
54
|
+
results = []
|
|
59
55
|
try:
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
raise ImportError(f"`llama-index-readers-file` package not found. {e}")
|
|
56
|
+
ext = os.path.splitext(file_path)[1].lower()
|
|
57
|
+
|
|
58
|
+
# 分发到不同 loader
|
|
59
|
+
if ext == '.pdf':
|
|
60
|
+
content = extract_text_from_pdf(file_path)
|
|
61
|
+
results.append(SourceCode(module_name=file_path, source_code=content))
|
|
62
|
+
elif ext == '.docx':
|
|
63
|
+
content = extract_text_from_docx(file_path)
|
|
64
|
+
results.append(SourceCode(module_name=file_path, source_code=content))
|
|
65
|
+
elif ext in ('.pptx', '.ppt'):
|
|
66
|
+
for slide_id, slide_content in extract_text_from_ppt(file_path):
|
|
67
|
+
results.append(SourceCode(module_name=f"{file_path}#{slide_id}", source_code=slide_content))
|
|
68
|
+
elif ext in ('.xlsx', '.xls'):
|
|
69
|
+
for sheet_name, sheet_content in extract_text_from_excel(file_path):
|
|
70
|
+
results.append(SourceCode(module_name=f"{file_path}#{sheet_name}", source_code=sheet_content))
|
|
71
|
+
else:
|
|
72
|
+
content = FileUtils.read_file(file_path)
|
|
73
|
+
results.append(SourceCode(module_name=file_path, source_code=content))
|
|
79
74
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
# ".ppt": PptxReader(),
|
|
86
|
-
# ".pptm": PptxReader(),
|
|
87
|
-
# ".jpg": ImageReader(),
|
|
88
|
-
# ".png": ImageReader(),
|
|
89
|
-
# ".jpeg": ImageReader(),
|
|
90
|
-
# ".mp3": VideoAudioReader(),
|
|
91
|
-
# ".mp4": VideoAudioReader(),
|
|
92
|
-
# ".csv": PandasCSVReader(),
|
|
93
|
-
".epub": EpubReader(),
|
|
94
|
-
".mbox": MboxReader(),
|
|
95
|
-
".ipynb": IPYNBReader(),
|
|
96
|
-
}
|
|
97
|
-
return default_file_reader_cls
|
|
75
|
+
except Exception as e:
|
|
76
|
+
logger.error(f"Failed to process {file_path}: {str(e)}")
|
|
77
|
+
traceback.print_exc()
|
|
78
|
+
|
|
79
|
+
return results
|
|
98
80
|
|
|
99
81
|
def crawl_urls(self) -> List[SourceCode]:
|
|
100
|
-
source_codes = []
|
|
82
|
+
source_codes = []
|
|
101
83
|
for url in self.urls:
|
|
102
|
-
if not url.startswith("http://"
|
|
84
|
+
if not url.startswith(("http://", "https://")):
|
|
103
85
|
try:
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
def process_single_file(file_path: str,skip_binary_file_test:bool=False):
|
|
109
|
-
temp_documents = []
|
|
110
|
-
ext = os.path.splitext(file_path)[1].lower()
|
|
111
|
-
if not skip_binary_file_test and self.is_binary_file(file_path):
|
|
112
|
-
logger.warning(f"Skipping binary file: {file_path}")
|
|
113
|
-
return temp_documents
|
|
114
|
-
|
|
115
|
-
if ext not in exts.keys():
|
|
116
|
-
main_content = FileUtils.read_file(file_path)
|
|
117
|
-
source_code = SourceCode(module_name=file_path, source_code=main_content)
|
|
118
|
-
source_codes.append(source_code)
|
|
86
|
+
if os.path.isdir(url):
|
|
87
|
+
for root, _, files in os.walk(url, followlinks=True):
|
|
88
|
+
for file in files:
|
|
89
|
+
source_codes.extend(self._process_local_file(os.path.join(root, file)))
|
|
119
90
|
else:
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if os.path.isdir(url):
|
|
124
|
-
for root, dirs, files in os.walk(url,followlinks=True):
|
|
125
|
-
dirs[:] = [d for d in dirs if d not in ['.git',"node_modules"]] # Exclude .git directory
|
|
126
|
-
for file in files:
|
|
127
|
-
file_path = os.path.join(root, file)
|
|
128
|
-
documents.extend(process_single_file(file_path))
|
|
129
|
-
|
|
130
|
-
else:
|
|
131
|
-
documents.extend(process_single_file(url,skip_binary_file_test=True))
|
|
132
|
-
|
|
133
|
-
for document in documents:
|
|
134
|
-
source_code = SourceCode(module_name=document.metadata["file_path"], source_code=document.get_content())
|
|
135
|
-
source_codes.append(source_code)
|
|
136
|
-
|
|
137
|
-
except ImportError as e:
|
|
138
|
-
logger.warning(f"Failed to import llama_index. Please install it using 'pip install llama_index' {e}")
|
|
139
|
-
main_content = FileUtils.read_file(url)
|
|
140
|
-
source_code = SourceCode(module_name=url, source_code=main_content)
|
|
141
|
-
source_codes.append(source_code)
|
|
91
|
+
source_codes.extend(self._process_local_file(url))
|
|
92
|
+
except Exception as e:
|
|
93
|
+
logger.error(f"Error accessing path {url}: {str(e)}")
|
|
142
94
|
else:
|
|
143
95
|
if self.args.urls_use_model:
|
|
144
96
|
from autocoder.common.screenshots import gen_screenshots
|
autocoder/version.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.244"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|