auto-coder 0.1.264__py3-none-any.whl → 0.1.266__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.264.dist-info → auto_coder-0.1.266.dist-info}/METADATA +2 -2
- {auto_coder-0.1.264.dist-info → auto_coder-0.1.266.dist-info}/RECORD +53 -51
- autocoder/agent/planner.py +4 -4
- autocoder/auto_coder.py +26 -21
- autocoder/auto_coder_server.py +7 -7
- autocoder/chat_auto_coder.py +150 -49
- autocoder/commands/auto_command.py +83 -5
- autocoder/commands/tools.py +48 -50
- autocoder/common/__init__.py +0 -1
- autocoder/common/auto_coder_lang.py +43 -3
- autocoder/common/code_auto_generate.py +3 -3
- autocoder/common/code_auto_generate_diff.py +3 -6
- autocoder/common/code_auto_generate_editblock.py +3 -3
- autocoder/common/code_auto_generate_strict_diff.py +3 -3
- autocoder/common/code_auto_merge_diff.py +37 -3
- autocoder/common/code_auto_merge_editblock.py +43 -1
- autocoder/common/code_auto_merge_strict_diff.py +39 -4
- autocoder/common/command_completer.py +3 -0
- autocoder/common/command_generator.py +24 -8
- autocoder/common/command_templates.py +2 -2
- autocoder/common/conf_import_export.py +105 -0
- autocoder/common/conf_validator.py +1 -1
- autocoder/common/files.py +41 -2
- autocoder/common/image_to_page.py +11 -11
- autocoder/common/index_import_export.py +38 -18
- autocoder/common/mcp_hub.py +3 -3
- autocoder/common/mcp_server.py +2 -2
- autocoder/common/shells.py +254 -13
- autocoder/common/stats_panel.py +126 -0
- autocoder/dispacher/actions/action.py +6 -18
- autocoder/dispacher/actions/copilot.py +2 -2
- autocoder/dispacher/actions/plugins/action_regex_project.py +1 -3
- autocoder/dispacher/actions/plugins/action_translate.py +1 -1
- autocoder/index/entry.py +2 -2
- autocoder/index/filter/normal_filter.py +1 -1
- autocoder/index/filter/quick_filter.py +1 -1
- autocoder/index/index.py +5 -5
- autocoder/models.py +2 -2
- autocoder/pyproject/__init__.py +5 -5
- autocoder/rag/cache/byzer_storage_cache.py +4 -4
- autocoder/rag/cache/file_monitor_cache.py +2 -2
- autocoder/rag/cache/simple_cache.py +4 -4
- autocoder/rag/long_context_rag.py +2 -2
- autocoder/regexproject/__init__.py +3 -2
- autocoder/suffixproject/__init__.py +3 -2
- autocoder/tsproject/__init__.py +3 -2
- autocoder/utils/conversation_store.py +1 -1
- autocoder/utils/operate_config_api.py +3 -3
- autocoder/version.py +1 -1
- {auto_coder-0.1.264.dist-info → auto_coder-0.1.266.dist-info}/LICENSE +0 -0
- {auto_coder-0.1.264.dist-info → auto_coder-0.1.266.dist-info}/WHEEL +0 -0
- {auto_coder-0.1.264.dist-info → auto_coder-0.1.266.dist-info}/entry_points.txt +0 -0
- {auto_coder-0.1.264.dist-info → auto_coder-0.1.266.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
import shutil
|
|
4
|
+
from loguru import logger
|
|
5
|
+
from autocoder.common.printer import Printer
|
|
6
|
+
from autocoder.common.result_manager import ResultManager
|
|
7
|
+
|
|
8
|
+
result_manager = ResultManager()
|
|
9
|
+
|
|
10
|
+
def export_conf(project_root: str, export_path: str) -> bool:
|
|
11
|
+
printer = Printer()
|
|
12
|
+
"""
|
|
13
|
+
Export conf from memory.json to a specified directory
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
project_root: Project root directory
|
|
17
|
+
export_path: Path to export the conf file
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
bool: True if successful, False otherwise
|
|
21
|
+
"""
|
|
22
|
+
project_root = os.path.abspath(project_root) or os.getcwd()
|
|
23
|
+
try:
|
|
24
|
+
memory_path = os.path.join(project_root, ".auto-coder", "plugins", "chat-auto-coder", "memory.json")
|
|
25
|
+
if not os.path.exists(memory_path):
|
|
26
|
+
printer.print_in_terminal("conf_not_found", path=memory_path)
|
|
27
|
+
return False
|
|
28
|
+
|
|
29
|
+
# Read and extract conf
|
|
30
|
+
with open(memory_path, "r",encoding="utf-8") as f:
|
|
31
|
+
memory_data = json.load(f)
|
|
32
|
+
|
|
33
|
+
conf_data = memory_data.get("conf", {})
|
|
34
|
+
|
|
35
|
+
# Write to export location
|
|
36
|
+
export_file = os.path.join(export_path, "conf.json")
|
|
37
|
+
os.makedirs(export_path, exist_ok=True)
|
|
38
|
+
with open(export_file, "w",encoding="utf-8") as f:
|
|
39
|
+
json.dump(conf_data, f, indent=2)
|
|
40
|
+
printer.print_in_terminal("conf_export_success", path=export_file)
|
|
41
|
+
result_manager.add_result(content=printer.get_message_from_key_with_format("conf_export_success", path=export_file), meta={"action": "conf_export", "input": {
|
|
42
|
+
"path": export_file
|
|
43
|
+
}})
|
|
44
|
+
return True
|
|
45
|
+
|
|
46
|
+
except Exception as e:
|
|
47
|
+
result_manager.add_result(content=printer.get_message_from_key_with_format("conf_export_error", error=str(e)), meta={"action": "conf_export", "input": {
|
|
48
|
+
"path": export_file
|
|
49
|
+
}})
|
|
50
|
+
printer.print_in_terminal("conf_export_error", error=str(e))
|
|
51
|
+
return False
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def import_conf(project_root: str, import_path: str) -> bool:
|
|
55
|
+
project_root = os.path.abspath(project_root) or os.getcwd()
|
|
56
|
+
printer = Printer()
|
|
57
|
+
"""
|
|
58
|
+
Import conf from a specified directory into memory.json
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
project_root: Project root directory
|
|
62
|
+
import_path: Path containing the conf file to import
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
bool: True if successful, False otherwise
|
|
66
|
+
"""
|
|
67
|
+
try:
|
|
68
|
+
import_file = os.path.join(import_path, "conf.json")
|
|
69
|
+
if not os.path.exists(import_file):
|
|
70
|
+
printer.print_in_terminal("conf_not_found", path=import_file)
|
|
71
|
+
return False
|
|
72
|
+
|
|
73
|
+
# Read conf file
|
|
74
|
+
with open(import_file, "r",encoding="utf-8") as f:
|
|
75
|
+
conf_data = json.load(f)
|
|
76
|
+
|
|
77
|
+
# Backup existing memory
|
|
78
|
+
memory_path = os.path.join(project_root, ".auto-coder", "plugins", "chat-auto-coder", "memory.json")
|
|
79
|
+
if os.path.exists(memory_path):
|
|
80
|
+
backup_path = memory_path + ".bak"
|
|
81
|
+
shutil.copy2(memory_path, backup_path)
|
|
82
|
+
printer.print_in_terminal("conf_backup_success", path=backup_path)
|
|
83
|
+
|
|
84
|
+
# Update conf in memory
|
|
85
|
+
with open(memory_path, "r",encoding="utf-8") as f:
|
|
86
|
+
memory_data = json.load(f)
|
|
87
|
+
|
|
88
|
+
memory_data["conf"] = conf_data
|
|
89
|
+
|
|
90
|
+
# Write updated memory
|
|
91
|
+
with open(memory_path, "w",encoding="utf-8") as f:
|
|
92
|
+
json.dump(memory_data, f, indent=2)
|
|
93
|
+
|
|
94
|
+
printer.print_in_terminal("conf_import_success", path=memory_path)
|
|
95
|
+
result_manager.add_result(content=printer.get_message_from_key_with_format("conf_import_success", path=memory_path), meta={"action": "conf_import", "input": {
|
|
96
|
+
"path": memory_path
|
|
97
|
+
}})
|
|
98
|
+
return True
|
|
99
|
+
|
|
100
|
+
except Exception as e:
|
|
101
|
+
result_manager.add_result(content=printer.get_message_from_key_with_format("conf_import_error", error=str(e)), meta={"action": "conf_import", "input": {
|
|
102
|
+
"path": memory_path
|
|
103
|
+
}})
|
|
104
|
+
printer.print_in_terminal("conf_import_error", error=str(e))
|
|
105
|
+
return False
|
|
@@ -142,7 +142,7 @@ class ConfigValidator:
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
@classmethod
|
|
145
|
-
def validate(cls, key: str, value: Any, product_mode: str) -> Any:
|
|
145
|
+
def validate(cls, key: str, value: Any, product_mode: str) -> Any:
|
|
146
146
|
# 获取配置规范
|
|
147
147
|
spec = cls.CONFIG_SPEC.get(key)
|
|
148
148
|
if not spec:
|
autocoder/common/files.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from autocoder.common.auto_coder_lang import get_message_with_format
|
|
2
|
-
from typing import List, Dict, Union
|
|
2
|
+
from typing import List, Dict, Union, Generator, Tuple
|
|
3
3
|
|
|
4
4
|
def read_file(file_path):
|
|
5
5
|
"""Read a file with automatic encoding detection.
|
|
@@ -30,6 +30,45 @@ def read_file(file_path):
|
|
|
30
30
|
file_path=file_path,
|
|
31
31
|
encodings=", ".join(encodings)))
|
|
32
32
|
|
|
33
|
+
def read_lines(file_path:str):
|
|
34
|
+
encodings = ['utf-8', 'gbk', 'utf-16', 'latin-1']
|
|
35
|
+
for encoding in encodings:
|
|
36
|
+
try:
|
|
37
|
+
with open(file_path, 'r', encoding=encoding) as f:
|
|
38
|
+
return f.readlines()
|
|
39
|
+
except UnicodeDecodeError:
|
|
40
|
+
continue
|
|
41
|
+
raise ValueError(get_message_with_format("file_decode_error",
|
|
42
|
+
file_path=file_path,
|
|
43
|
+
encodings=", ".join(encodings)))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def read_file_with_line_numbers(file_path: str,line_number_start:int=0) -> Generator[Tuple[int, str], None, None]:
|
|
48
|
+
"""Read a file and return its content with line numbers.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
file_path (str): Path to the file to read
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
List[str]: A list of strings where each string is in the format "line_number:line_content"
|
|
55
|
+
|
|
56
|
+
Raises:
|
|
57
|
+
ValueError: If the file cannot be decoded with any of the tried encodings
|
|
58
|
+
"""
|
|
59
|
+
encodings = ['utf-8', 'gbk', 'utf-16', 'latin-1']
|
|
60
|
+
|
|
61
|
+
for encoding in encodings:
|
|
62
|
+
try:
|
|
63
|
+
with open(file_path, 'r', encoding=encoding) as file:
|
|
64
|
+
for line_number, line in enumerate(file, start=line_number_start):
|
|
65
|
+
yield (line_number, line)
|
|
66
|
+
except UnicodeDecodeError:
|
|
67
|
+
continue
|
|
68
|
+
|
|
69
|
+
raise ValueError(get_message_with_format("file_decode_error",
|
|
70
|
+
file_path=file_path,
|
|
71
|
+
encodings=", ".join(encodings)))
|
|
33
72
|
|
|
34
73
|
|
|
35
74
|
def save_file(file_path: str, content: Union[str, List[str]]) -> None:
|
|
@@ -55,4 +94,4 @@ def save_file(file_path: str, content: Union[str, List[str]]) -> None:
|
|
|
55
94
|
except IOError as e:
|
|
56
95
|
raise IOError(get_message_with_format("file_write_error",
|
|
57
96
|
file_path=file_path,
|
|
58
|
-
error=str(e)))
|
|
97
|
+
error=str(e)))
|
|
@@ -122,7 +122,7 @@ class ImageToPageDirectly:
|
|
|
122
122
|
|
|
123
123
|
counter = 1
|
|
124
124
|
target_html_path = os.path.join(html_dir,f"{html_file_name}-{counter}.html")
|
|
125
|
-
with open(target_html_path, "w") as f:
|
|
125
|
+
with open(target_html_path, "w",encoding="utf-8") as f:
|
|
126
126
|
f.write(html)
|
|
127
127
|
|
|
128
128
|
while counter < max_iter:
|
|
@@ -137,11 +137,11 @@ class ImageToPageDirectly:
|
|
|
137
137
|
|
|
138
138
|
target_html_path = os.path.join(html_dir,f"{html_file_name}-{counter}.html")
|
|
139
139
|
logger.info(f"generate html: {target_html_path}")
|
|
140
|
-
with open(target_html_path, "w") as f:
|
|
140
|
+
with open(target_html_path, "w",encoding="utf-8") as f:
|
|
141
141
|
f.write(html)
|
|
142
142
|
|
|
143
143
|
logger.info(f"finally generate html: {html_path}")
|
|
144
|
-
with open(html_path, "w") as f:
|
|
144
|
+
with open(html_path, "w",encoding="utf-8") as f:
|
|
145
145
|
f.write(html)
|
|
146
146
|
|
|
147
147
|
|
|
@@ -248,7 +248,7 @@ class ImageToPage:
|
|
|
248
248
|
file_path = block.path
|
|
249
249
|
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
|
250
250
|
|
|
251
|
-
with open(file_path, "w") as f:
|
|
251
|
+
with open(file_path, "w",encoding="utf-8") as f:
|
|
252
252
|
logger.info(f"Upsert path: {file_path}")
|
|
253
253
|
f.write(block.content)
|
|
254
254
|
file_modified_num += 1
|
|
@@ -268,7 +268,7 @@ class ImageToPage:
|
|
|
268
268
|
## generate html by image description
|
|
269
269
|
content_contains_html_prompt = self.generate_html.prompt(desc,html_path)
|
|
270
270
|
|
|
271
|
-
with open(self.args.target_file, "w") as f:
|
|
271
|
+
with open(self.args.target_file, "w",encoding="utf-8") as f:
|
|
272
272
|
f.write(content_contains_html_prompt)
|
|
273
273
|
|
|
274
274
|
t = self.llm.chat_oai(conversations=[{
|
|
@@ -278,7 +278,7 @@ class ImageToPage:
|
|
|
278
278
|
|
|
279
279
|
content_contains_html = t[0].output
|
|
280
280
|
|
|
281
|
-
with open(self.args.target_file, "w") as f:
|
|
281
|
+
with open(self.args.target_file, "w",encoding="utf-8") as f:
|
|
282
282
|
f.write(content_contains_html)
|
|
283
283
|
|
|
284
284
|
|
|
@@ -296,7 +296,7 @@ class ImageToPage:
|
|
|
296
296
|
|
|
297
297
|
for i in range(max_iter):
|
|
298
298
|
logger.info(f"iterate {i}")
|
|
299
|
-
with open(html_path,"r") as f:
|
|
299
|
+
with open(html_path,"r",encoding="utf-8") as f:
|
|
300
300
|
prev_html = f.read()
|
|
301
301
|
|
|
302
302
|
gen_screenshots(url=html_path,image_dir=new_image_dir)
|
|
@@ -309,7 +309,7 @@ class ImageToPage:
|
|
|
309
309
|
## get new description prompt by comparing old and new image
|
|
310
310
|
new_desc_prompt = self.get_optimize(self.score(origin_image,new_image))
|
|
311
311
|
|
|
312
|
-
with open(self.args.target_file, "w") as f:
|
|
312
|
+
with open(self.args.target_file, "w",encoding="utf-8") as f:
|
|
313
313
|
f.write(new_desc_prompt)
|
|
314
314
|
|
|
315
315
|
t = self.llm.chat_oai(conversations=[{
|
|
@@ -319,7 +319,7 @@ class ImageToPage:
|
|
|
319
319
|
|
|
320
320
|
new_desc = t[0].output
|
|
321
321
|
|
|
322
|
-
with open(self.args.target_file, "w") as f:
|
|
322
|
+
with open(self.args.target_file, "w",encoding="utf-8") as f:
|
|
323
323
|
f.write(new_desc)
|
|
324
324
|
|
|
325
325
|
logger.info(f"score old/new image: {new_desc}")
|
|
@@ -327,7 +327,7 @@ class ImageToPage:
|
|
|
327
327
|
## generate new html by new description
|
|
328
328
|
optimze_html_prompt = self.optimize_html.prompt(desc=new_desc,html=prev_html,html_path=html_path)
|
|
329
329
|
|
|
330
|
-
with open(self.args.target_file, "w") as f:
|
|
330
|
+
with open(self.args.target_file, "w",encoding="utf-8") as f:
|
|
331
331
|
f.write(optimze_html_prompt)
|
|
332
332
|
|
|
333
333
|
t = self.llm.chat_oai(conversations=[{
|
|
@@ -336,7 +336,7 @@ class ImageToPage:
|
|
|
336
336
|
}],llm_config={**extra_llm_config})
|
|
337
337
|
new_code = t[0].output
|
|
338
338
|
|
|
339
|
-
with open(self.args.target_file, "w") as f:
|
|
339
|
+
with open(self.args.target_file, "w",encoding="utf-8") as f:
|
|
340
340
|
f.write(new_code)
|
|
341
341
|
|
|
342
342
|
self.write_code(new_code,html_path)
|
|
@@ -3,6 +3,9 @@ import json
|
|
|
3
3
|
import shutil
|
|
4
4
|
from loguru import logger
|
|
5
5
|
from autocoder.common.printer import Printer
|
|
6
|
+
from autocoder.common.result_manager import ResultManager
|
|
7
|
+
|
|
8
|
+
result_manager = ResultManager()
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
def export_index(project_root: str, export_path: str) -> bool:
|
|
@@ -22,11 +25,11 @@ def export_index(project_root: str, export_path: str) -> bool:
|
|
|
22
25
|
if not os.path.exists(index_path):
|
|
23
26
|
printer.print_in_terminal("index_not_found", path=index_path)
|
|
24
27
|
return False
|
|
25
|
-
|
|
28
|
+
|
|
26
29
|
# Read and convert paths
|
|
27
|
-
with open(index_path, "r") as f:
|
|
30
|
+
with open(index_path, "r",encoding="utf-8") as f:
|
|
28
31
|
index_data = json.load(f)
|
|
29
|
-
|
|
32
|
+
|
|
30
33
|
# Convert absolute paths to relative
|
|
31
34
|
converted_data = {}
|
|
32
35
|
for abs_path, data in index_data.items():
|
|
@@ -35,21 +38,29 @@ def export_index(project_root: str, export_path: str) -> bool:
|
|
|
35
38
|
data["module_name"] = rel_path
|
|
36
39
|
converted_data[rel_path] = data
|
|
37
40
|
except ValueError:
|
|
38
|
-
printer.print_in_terminal(
|
|
41
|
+
printer.print_in_terminal(
|
|
42
|
+
"index_convert_path_fail", path=abs_path)
|
|
39
43
|
converted_data[abs_path] = data
|
|
40
|
-
|
|
44
|
+
|
|
41
45
|
# Write to export location
|
|
42
46
|
export_file = os.path.join(export_path, "index.json")
|
|
43
47
|
os.makedirs(export_path, exist_ok=True)
|
|
44
|
-
with open(export_file, "w") as f:
|
|
48
|
+
with open(export_file, "w",encoding="utf-8") as f:
|
|
45
49
|
json.dump(converted_data, f, indent=2)
|
|
46
|
-
|
|
50
|
+
printer.print_in_terminal("index_export_success", path=export_file)
|
|
51
|
+
result_manager.add_result(content=printer.get_message_from_key_with_format("index_export_success", path=export_file), meta={"action": "index_export", "input": {
|
|
52
|
+
"path": export_file
|
|
53
|
+
}})
|
|
47
54
|
return True
|
|
48
|
-
|
|
55
|
+
|
|
49
56
|
except Exception as e:
|
|
50
57
|
printer.print_in_terminal("index_error", error=str(e))
|
|
58
|
+
result_manager.add_result(content=printer.get_message_from_key_with_format("index_error", error=str(e)), meta={"action": "index_export", "input": {
|
|
59
|
+
"path": export_file
|
|
60
|
+
}})
|
|
51
61
|
return False
|
|
52
62
|
|
|
63
|
+
|
|
53
64
|
def import_index(project_root: str, import_path: str) -> bool:
|
|
54
65
|
printer = Printer()
|
|
55
66
|
"""
|
|
@@ -67,11 +78,11 @@ def import_index(project_root: str, import_path: str) -> bool:
|
|
|
67
78
|
if not os.path.exists(import_file):
|
|
68
79
|
printer.print_in_terminal("index_not_found", path=import_file)
|
|
69
80
|
return False
|
|
70
|
-
|
|
81
|
+
|
|
71
82
|
# Read and convert paths
|
|
72
|
-
with open(import_file, "r") as f:
|
|
83
|
+
with open(import_file, "r",encoding="utf-8") as f:
|
|
73
84
|
index_data = json.load(f)
|
|
74
|
-
|
|
85
|
+
|
|
75
86
|
# Convert relative paths to absolute
|
|
76
87
|
converted_data = {}
|
|
77
88
|
for rel_path, data in index_data.items():
|
|
@@ -80,22 +91,31 @@ def import_index(project_root: str, import_path: str) -> bool:
|
|
|
80
91
|
data["module_name"] = abs_path
|
|
81
92
|
converted_data[abs_path] = data
|
|
82
93
|
except Exception:
|
|
83
|
-
printer.print_in_terminal(
|
|
94
|
+
printer.print_in_terminal(
|
|
95
|
+
"index_convert_path_fail", path=rel_path)
|
|
84
96
|
converted_data[rel_path] = data
|
|
85
|
-
|
|
97
|
+
|
|
86
98
|
# Backup existing index
|
|
87
99
|
index_path = os.path.join(project_root, ".auto-coder", "index.json")
|
|
88
100
|
if os.path.exists(index_path):
|
|
89
101
|
backup_path = index_path + ".bak"
|
|
90
102
|
shutil.copy2(index_path, backup_path)
|
|
91
103
|
printer.print_in_terminal("index_backup_success", path=backup_path)
|
|
92
|
-
|
|
104
|
+
|
|
93
105
|
# Write new index
|
|
94
|
-
with open(index_path, "w") as f:
|
|
106
|
+
with open(index_path, "w",encoding="utf-8") as f:
|
|
95
107
|
json.dump(converted_data, f, indent=2)
|
|
96
|
-
|
|
97
|
-
return True
|
|
98
108
|
|
|
109
|
+
printer.print_in_terminal("index_import_success", path=index_path)
|
|
110
|
+
result_manager.add_result(content=printer.get_message_from_key_with_format("index_import_success", path=index_path), meta={"action": "index_import", "input": {
|
|
111
|
+
"path": index_path
|
|
112
|
+
}})
|
|
113
|
+
|
|
114
|
+
return True
|
|
115
|
+
|
|
99
116
|
except Exception as e:
|
|
100
117
|
printer.print_in_terminal("index_error", error=str(e))
|
|
101
|
-
|
|
118
|
+
result_manager.add_result(content=printer.get_message_from_key_with_format("index_error", error=str(e)), meta={"action": "index_import", "input": {
|
|
119
|
+
"path": index_path
|
|
120
|
+
}})
|
|
121
|
+
return False
|
autocoder/common/mcp_hub.py
CHANGED
|
@@ -116,7 +116,7 @@ class McpHub:
|
|
|
116
116
|
def _write_default_settings(self):
|
|
117
117
|
"""Write default MCP settings file"""
|
|
118
118
|
default_settings = {"mcpServers": {}}
|
|
119
|
-
with open(self.settings_path, "w") as f:
|
|
119
|
+
with open(self.settings_path, "w",encoding="utf-8") as f:
|
|
120
120
|
json.dump(default_settings, f, indent=2)
|
|
121
121
|
|
|
122
122
|
async def add_server_config(self, name: str, config:Dict[str,Any]) -> None:
|
|
@@ -129,7 +129,7 @@ class McpHub:
|
|
|
129
129
|
try:
|
|
130
130
|
settings = self._read_settings()
|
|
131
131
|
settings["mcpServers"][name] = config
|
|
132
|
-
with open(self.settings_path, "w") as f:
|
|
132
|
+
with open(self.settings_path, "w",encoding="utf-8") as f:
|
|
133
133
|
json.dump(settings, f, indent=2, ensure_ascii=False)
|
|
134
134
|
await self.initialize()
|
|
135
135
|
logger.info(f"Added/updated MCP server config: {name}")
|
|
@@ -148,7 +148,7 @@ class McpHub:
|
|
|
148
148
|
settings = self._read_settings()
|
|
149
149
|
if name in settings["mcpServers"]:
|
|
150
150
|
del settings["mcpServers"][name]
|
|
151
|
-
with open(self.settings_path, "w") as f:
|
|
151
|
+
with open(self.settings_path, "w",encoding="utf-8") as f:
|
|
152
152
|
json.dump(settings, f, indent=2, ensure_ascii=False)
|
|
153
153
|
logger.info(f"Removed MCP server config: {name}")
|
|
154
154
|
await self.initialize()
|
autocoder/common/mcp_server.py
CHANGED
|
@@ -80,7 +80,7 @@ def get_mcp_external_servers() -> List[McpExternalServer]:
|
|
|
80
80
|
if os.path.exists(cache_file):
|
|
81
81
|
cache_time = os.path.getmtime(cache_file)
|
|
82
82
|
if time.time() - cache_time < 3600: # 1 hour cache
|
|
83
|
-
with open(cache_file, "r") as f:
|
|
83
|
+
with open(cache_file, "r",encoding="utf-8") as f:
|
|
84
84
|
raw_data = json.load(f)
|
|
85
85
|
return [McpExternalServer(**item) for item in raw_data]
|
|
86
86
|
|
|
@@ -91,7 +91,7 @@ def get_mcp_external_servers() -> List[McpExternalServer]:
|
|
|
91
91
|
response = requests.get(url)
|
|
92
92
|
if response.status_code == 200:
|
|
93
93
|
raw_data = response.json()
|
|
94
|
-
with open(cache_file, "w") as f:
|
|
94
|
+
with open(cache_file, "w",encoding="utf-8") as f:
|
|
95
95
|
json.dump(raw_data, f)
|
|
96
96
|
return [McpExternalServer(**item) for item in raw_data]
|
|
97
97
|
return []
|