jarvis-ai-assistant 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.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/edit_file_handler.py +50 -38
- jarvis/jarvis_platform/base.py +1 -1
- {jarvis_ai_assistant-0.1.201.dist-info → jarvis_ai_assistant-0.1.203.dist-info}/METADATA +1 -1
- {jarvis_ai_assistant-0.1.201.dist-info → jarvis_ai_assistant-0.1.203.dist-info}/RECORD +9 -9
- {jarvis_ai_assistant-0.1.201.dist-info → jarvis_ai_assistant-0.1.203.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.201.dist-info → jarvis_ai_assistant-0.1.203.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.201.dist-info → jarvis_ai_assistant-0.1.203.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.201.dist-info → jarvis_ai_assistant-0.1.203.dist-info}/top_level.txt +0 -0
jarvis/__init__.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
import os
|
2
2
|
import re
|
3
|
-
from abc import ABC, abstractmethod
|
4
3
|
from typing import Any, Dict, List, Tuple
|
5
4
|
|
6
5
|
from yaspin import yaspin
|
@@ -8,7 +7,6 @@ from yaspin.core import Yaspin
|
|
8
7
|
|
9
8
|
from jarvis.jarvis_agent.output_handler import OutputHandler
|
10
9
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
11
|
-
from jarvis.jarvis_tools.file_operation import FileOperationTool
|
12
10
|
from jarvis.jarvis_utils.git_utils import revert_file
|
13
11
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
14
12
|
from jarvis.jarvis_utils.tag import ct, ot
|
@@ -18,16 +16,16 @@ from jarvis.jarvis_utils.utils import is_context_overflow
|
|
18
16
|
class EditFileHandler(OutputHandler):
|
19
17
|
def __init__(self):
|
20
18
|
self.patch_pattern = re.compile(
|
21
|
-
ot("PATCH file=([^>]+)") + r"\s*"
|
19
|
+
ot("PATCH file=(?:'([^']+)'|\"([^\"]+)\"|([^>]+))") + r"\s*"
|
22
20
|
r"(?:"
|
23
21
|
+ ot("DIFF")
|
24
22
|
+ r"\s*"
|
25
23
|
+ ot("SEARCH")
|
26
|
-
+ r"
|
24
|
+
+ r"(.*?)"
|
27
25
|
+ ct("SEARCH")
|
28
26
|
+ r"\s*"
|
29
27
|
+ ot("REPLACE")
|
30
|
-
+ r"
|
28
|
+
+ r"(.*?)"
|
31
29
|
+ ct("REPLACE")
|
32
30
|
+ r"\s*"
|
33
31
|
+ ct("DIFF")
|
@@ -39,11 +37,11 @@ class EditFileHandler(OutputHandler):
|
|
39
37
|
ot("DIFF")
|
40
38
|
+ r"\s*"
|
41
39
|
+ ot("SEARCH")
|
42
|
-
+ r"
|
40
|
+
+ r"(.*?)"
|
43
41
|
+ ct("SEARCH")
|
44
42
|
+ r"\s*"
|
45
43
|
+ ot("REPLACE")
|
46
|
-
+ r"
|
44
|
+
+ r"(.*?)"
|
47
45
|
+ ct("REPLACE")
|
48
46
|
+ r"\s*"
|
49
47
|
+ ct("DIFF"),
|
@@ -65,12 +63,11 @@ class EditFileHandler(OutputHandler):
|
|
65
63
|
return False, "未找到有效的文件编辑指令"
|
66
64
|
|
67
65
|
results = []
|
68
|
-
overall_success = True
|
69
66
|
|
70
67
|
for file_path, diffs in patches.items():
|
71
68
|
file_path = os.path.abspath(file_path)
|
72
69
|
file_patches = [
|
73
|
-
{"
|
70
|
+
{"SEARCH": diff["SEARCH"], "REPLACE": diff["REPLACE"]} for diff in diffs
|
74
71
|
]
|
75
72
|
|
76
73
|
with yaspin(text=f"正在处理文件 {file_path}...", color="cyan") as spinner:
|
@@ -110,15 +107,12 @@ class EditFileHandler(OutputHandler):
|
|
110
107
|
return f"""文件编辑指令格式:
|
111
108
|
{ot("PATCH file=文件路径")}
|
112
109
|
{ot("DIFF")}
|
113
|
-
{ot("SEARCH")}
|
114
|
-
|
115
|
-
{ct("SEARCH")}
|
116
|
-
{ot("REPLACE")}
|
117
|
-
新代码
|
118
|
-
{ct("REPLACE")}
|
110
|
+
{ot("SEARCH")}原始代码{ct("SEARCH")}
|
111
|
+
{ot("REPLACE")}新代码{ct("REPLACE")}
|
119
112
|
{ct("DIFF")}
|
120
113
|
{ct("PATCH")}
|
121
114
|
|
115
|
+
可以返回多个PATCH块用于同时修改多个文件
|
122
116
|
每个PATCH块可以包含多个DIFF块,每个DIFF块包含一组搜索和替换内容。
|
123
117
|
搜索文本必须能在文件中唯一匹配,否则编辑将失败。"""
|
124
118
|
|
@@ -136,6 +130,7 @@ class EditFileHandler(OutputHandler):
|
|
136
130
|
该方法使用正则表达式从响应文本中提取文件编辑指令(PATCH块),
|
137
131
|
每个PATCH块可以包含多个DIFF块,每个DIFF块包含一组搜索和替换内容。
|
138
132
|
解析后会返回一个字典,键是文件路径,值是该文件对应的补丁列表。
|
133
|
+
如果同一个文件路径出现多次,会将所有DIFF块合并到一起。
|
139
134
|
|
140
135
|
Args:
|
141
136
|
response: 包含补丁信息的响应字符串,格式应符合PATCH指令规范
|
@@ -145,25 +140,29 @@ class EditFileHandler(OutputHandler):
|
|
145
140
|
返回解析后的补丁信息字典,结构为:
|
146
141
|
{
|
147
142
|
"文件路径1": [
|
148
|
-
{"
|
149
|
-
{"
|
143
|
+
{"SEARCH": "搜索文本1", "REPLACE": "替换文本1"},
|
144
|
+
{"SEARCH": "搜索文本2", "REPLACE": "替换文本2"}
|
150
145
|
],
|
151
146
|
"文件路径2": [...]
|
152
147
|
}
|
153
148
|
"""
|
154
149
|
patches = {}
|
155
150
|
for match in self.patch_pattern.finditer(response):
|
156
|
-
|
151
|
+
# Get the file path from the appropriate capture group
|
152
|
+
file_path = match.group(1) or match.group(2) or match.group(3)
|
157
153
|
diffs = []
|
158
154
|
for diff_match in self.diff_pattern.finditer(match.group(0)):
|
159
155
|
diffs.append(
|
160
156
|
{
|
161
|
-
"
|
162
|
-
"
|
157
|
+
"SEARCH": diff_match.group(1).strip(),
|
158
|
+
"REPLACE": diff_match.group(2).strip(),
|
163
159
|
}
|
164
160
|
)
|
165
161
|
if diffs:
|
166
|
-
|
162
|
+
if file_path in patches:
|
163
|
+
patches[file_path].extend(diffs)
|
164
|
+
else:
|
165
|
+
patches[file_path] = diffs
|
167
166
|
return patches
|
168
167
|
|
169
168
|
@staticmethod
|
@@ -203,12 +202,16 @@ class EditFileHandler(OutputHandler):
|
|
203
202
|
modified_content = file_content
|
204
203
|
patch_count = 0
|
205
204
|
for patch in patches:
|
206
|
-
search_text = patch["
|
207
|
-
replace_text = patch["
|
205
|
+
search_text = patch["SEARCH"]
|
206
|
+
replace_text = patch["REPLACE"]
|
208
207
|
patch_count += 1
|
209
208
|
|
210
209
|
if search_text in modified_content:
|
211
210
|
if modified_content.count(search_text) > 1:
|
211
|
+
PrettyOutput.print(
|
212
|
+
f"搜索文本在文件中存在多处匹配:\n{search_text}",
|
213
|
+
output_type=OutputType.WARNING,
|
214
|
+
)
|
212
215
|
return False, f"搜索文本在文件中存在多处匹配:\n{search_text}"
|
213
216
|
modified_content = modified_content.replace(
|
214
217
|
search_text, replace_text
|
@@ -228,6 +231,10 @@ class EditFileHandler(OutputHandler):
|
|
228
231
|
)
|
229
232
|
if indented_search in modified_content:
|
230
233
|
if modified_content.count(indented_search) > 1:
|
234
|
+
PrettyOutput.print(
|
235
|
+
f"搜索文本在文件中存在多处匹配:\n{indented_search}",
|
236
|
+
output_type=OutputType.WARNING,
|
237
|
+
)
|
231
238
|
return (
|
232
239
|
False,
|
233
240
|
f"搜索文本在文件中存在多处匹配:\n{indented_search}",
|
@@ -242,6 +249,10 @@ class EditFileHandler(OutputHandler):
|
|
242
249
|
break
|
243
250
|
|
244
251
|
if not found:
|
252
|
+
PrettyOutput.print(
|
253
|
+
f"搜索文本在文件中不存在:\n{search_text}",
|
254
|
+
output_type=OutputType.WARNING,
|
255
|
+
)
|
245
256
|
return False, f"搜索文本在文件中不存在:\n{search_text}"
|
246
257
|
|
247
258
|
# 写入修改后的内容
|
@@ -312,8 +323,8 @@ class EditFileHandler(OutputHandler):
|
|
312
323
|
patch_content.append(
|
313
324
|
{
|
314
325
|
"reason": "根据用户指令修改代码",
|
315
|
-
"
|
316
|
-
"
|
326
|
+
"SEARCH": patch["SEARCH"],
|
327
|
+
"REPLACE": patch["REPLACE"],
|
317
328
|
}
|
318
329
|
)
|
319
330
|
|
@@ -345,19 +356,13 @@ class EditFileHandler(OutputHandler):
|
|
345
356
|
|
346
357
|
## 输出模板
|
347
358
|
{ot("DIFF")}
|
348
|
-
{"
|
349
|
-
[
|
350
|
-
{'='*5}
|
351
|
-
[替换后的新代码]
|
352
|
-
{"<" * 5} REPLACE
|
359
|
+
{ot("SEARCH")}[需要查找的原始代码,包含足够上下文,避免出现可匹配多处的情况]{ct("SEARCH")}
|
360
|
+
{ot("REPLACE")}[替换后的新代码]{ct("REPLACE")}
|
353
361
|
{ct("DIFF")}
|
354
362
|
|
355
363
|
{ot("DIFF")}
|
356
|
-
{"
|
357
|
-
[
|
358
|
-
{'='*5}
|
359
|
-
[另一处替换后的新代码]
|
360
|
-
{"<" * 5} REPLACE
|
364
|
+
{ot("SEARCH")}[另一处需要查找的原始代码,包含足够上下文,避免出现可匹配多处的情况]{ct("SEARCH")}
|
365
|
+
{ot("REPLACE")}[另一处替换后的新代码]{ct("REPLACE")}
|
361
366
|
{ct("DIFF")}
|
362
367
|
"""
|
363
368
|
|
@@ -383,7 +388,14 @@ class EditFileHandler(OutputHandler):
|
|
383
388
|
diff_blocks = re.finditer(
|
384
389
|
ot("DIFF")
|
385
390
|
+ r"\s*"
|
386
|
-
+
|
391
|
+
+ ot("SEARCH")
|
392
|
+
+ r"(.*?)"
|
393
|
+
+ ct("SEARCH")
|
394
|
+
+ r"\s*"
|
395
|
+
+ ot("REPLACE")
|
396
|
+
+ r"(.*?)"
|
397
|
+
+ ct("REPLACE")
|
398
|
+
+ r"\s*"
|
387
399
|
+ ct("DIFF"),
|
388
400
|
response,
|
389
401
|
re.DOTALL,
|
@@ -393,8 +405,8 @@ class EditFileHandler(OutputHandler):
|
|
393
405
|
for match in diff_blocks:
|
394
406
|
generated_patches.append(
|
395
407
|
{
|
396
|
-
"
|
397
|
-
"
|
408
|
+
"SEARCH": match.group(1).strip(),
|
409
|
+
"REPLACE": match.group(2).strip(),
|
398
410
|
}
|
399
411
|
)
|
400
412
|
|
jarvis/jarvis_platform/base.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
jarvis/__init__.py,sha256=
|
1
|
+
jarvis/__init__.py,sha256=6vjQIk71IT0f_EPgzrHvjWl2bp3n_NOJMy-NtNfAZ-g,75
|
2
2
|
jarvis/jarvis_agent/__init__.py,sha256=X5BWIOzxXUWtCbpDkTFfUYskf6sbNzb1qQu8nQ4NN1k,34371
|
3
3
|
jarvis/jarvis_agent/builtin_input_handler.py,sha256=1V7kV5Zhw2HE3Xgjs1R-43RZ2huq3Kg-32NCdNnyZmA,2216
|
4
|
-
jarvis/jarvis_agent/edit_file_handler.py,sha256=
|
4
|
+
jarvis/jarvis_agent/edit_file_handler.py,sha256=EVEKZUon2CbLHQ1id1_5nka_oGJALGv1k1jmKJva3JA,16478
|
5
5
|
jarvis/jarvis_agent/jarvis.py,sha256=GH2zi8eXNpW8twiY3LKDEZgGmFC5geB0jlkwFrm7hOQ,6279
|
6
6
|
jarvis/jarvis_agent/main.py,sha256=c6bQe-8LXvW2-NBn9Rn_yPYdrwnkJ8KQaSFY2cPvkxw,2775
|
7
7
|
jarvis/jarvis_agent/output_handler.py,sha256=P7oWpXBGFfOsWq7cIhS_z9crkQ19ES7qU5pM92KKjAs,1172
|
@@ -46,7 +46,7 @@ jarvis/jarvis_methodology/main.py,sha256=NMtd6DRn-Q8NcYtQ3qgTKUp9RW0cDGJod8ZXebl
|
|
46
46
|
jarvis/jarvis_multi_agent/__init__.py,sha256=sDd3sK88dS7_qAz2ywIAaEWdQ4iRVCiuBu2rQQmrKbU,4512
|
47
47
|
jarvis/jarvis_multi_agent/main.py,sha256=h7VUSwoPrES0XTK8z5kt3XLX1mmcm8UEuFEHQOUWPH4,1696
|
48
48
|
jarvis/jarvis_platform/__init__.py,sha256=WLQHSiE87PPket2M50_hHzjdMIgPIBx2VF8JfB_NNRk,105
|
49
|
-
jarvis/jarvis_platform/base.py,sha256=
|
49
|
+
jarvis/jarvis_platform/base.py,sha256=dv_O3IcUTRhi_jfoRIG2g_FwnYpFRZo8g8tWIanOgVo,7884
|
50
50
|
jarvis/jarvis_platform/human.py,sha256=r8Vlltp_LirJZeZh1Mmi30iJr9tl1JaNFoqthSRHF6o,2826
|
51
51
|
jarvis/jarvis_platform/kimi.py,sha256=uIpSWQ3MqDBYYMROeXin_YqM2LFrovMICKpwLWO1ODo,12784
|
52
52
|
jarvis/jarvis_platform/openai.py,sha256=uEjBikfFj7kp5wondLvOx4WdkmTX0aqF6kixxAufcHg,4806
|
@@ -91,9 +91,9 @@ jarvis/jarvis_utils/methodology.py,sha256=MhPrMxMqElyAn54BDfpQdUqrRr7IbSlrLvAI39
|
|
91
91
|
jarvis/jarvis_utils/output.py,sha256=PRCgudPOB8gMEP3u-g0FGD2c6tBgJhLXUMqNPglfjV8,10813
|
92
92
|
jarvis/jarvis_utils/tag.py,sha256=f211opbbbTcSyzCDwuIK_oCnKhXPNK-RknYyGzY1yD0,431
|
93
93
|
jarvis/jarvis_utils/utils.py,sha256=RYFQx7OkOu3fe_QhS-5jx7O06k_58X14S-9PFJgwOa4,12178
|
94
|
-
jarvis_ai_assistant-0.1.
|
95
|
-
jarvis_ai_assistant-0.1.
|
96
|
-
jarvis_ai_assistant-0.1.
|
97
|
-
jarvis_ai_assistant-0.1.
|
98
|
-
jarvis_ai_assistant-0.1.
|
99
|
-
jarvis_ai_assistant-0.1.
|
94
|
+
jarvis_ai_assistant-0.1.203.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
|
95
|
+
jarvis_ai_assistant-0.1.203.dist-info/METADATA,sha256=Z2KYARBymf4cu82o1L_vXEo8KXujcOUkbFnb8qZx5Lc,20215
|
96
|
+
jarvis_ai_assistant-0.1.203.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
97
|
+
jarvis_ai_assistant-0.1.203.dist-info/entry_points.txt,sha256=Gy3DOP1PYLMK0GCj4rrP_9lkOyBQ39EK_lKGUSwn41E,869
|
98
|
+
jarvis_ai_assistant-0.1.203.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
|
99
|
+
jarvis_ai_assistant-0.1.203.dist-info/RECORD,,
|
File without changes
|
{jarvis_ai_assistant-0.1.201.dist-info → jarvis_ai_assistant-0.1.203.dist-info}/entry_points.txt
RENAMED
File without changes
|
{jarvis_ai_assistant-0.1.201.dist-info → jarvis_ai_assistant-0.1.203.dist-info}/licenses/LICENSE
RENAMED
File without changes
|
{jarvis_ai_assistant-0.1.201.dist-info → jarvis_ai_assistant-0.1.203.dist-info}/top_level.txt
RENAMED
File without changes
|