jarvis-ai-assistant 0.1.188__py3-none-any.whl → 0.1.190__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/__init__.py +61 -57
- jarvis/jarvis_code_analysis/code_review.py +15 -14
- jarvis/jarvis_data/config_schema.json +1 -1
- jarvis/jarvis_dev/main.py +6 -6
- jarvis/jarvis_git_details/main.py +1 -1
- jarvis/jarvis_git_utils/git_commiter.py +239 -202
- jarvis/jarvis_platform/base.py +4 -3
- jarvis/jarvis_platform/kimi.py +4 -0
- jarvis/jarvis_platform/tongyi.py +4 -0
- jarvis/jarvis_platform/yuanbao.py +4 -0
- jarvis/jarvis_platform_manager/main.py +4 -0
- jarvis/jarvis_tools/edit_file.py +12 -10
- jarvis/jarvis_tools/file_analyzer.py +5 -2
- jarvis/jarvis_tools/generate_new_tool.py +88 -40
- jarvis/jarvis_tools/registry.py +25 -17
- jarvis/jarvis_utils/config.py +1 -1
- jarvis/jarvis_utils/methodology.py +9 -11
- {jarvis_ai_assistant-0.1.188.dist-info → jarvis_ai_assistant-0.1.190.dist-info}/METADATA +14 -3
- {jarvis_ai_assistant-0.1.188.dist-info → jarvis_ai_assistant-0.1.190.dist-info}/RECORD +24 -24
- {jarvis_ai_assistant-0.1.188.dist-info → jarvis_ai_assistant-0.1.190.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.188.dist-info → jarvis_ai_assistant-0.1.190.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.1.188.dist-info → jarvis_ai_assistant-0.1.190.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.188.dist-info → jarvis_ai_assistant-0.1.190.dist-info}/top_level.txt +0 -0
@@ -12,8 +12,7 @@ from yaspin import yaspin
|
|
12
12
|
|
13
13
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
14
14
|
from jarvis.jarvis_utils.config import get_git_commit_prompt
|
15
|
-
from jarvis.jarvis_utils.git_utils import
|
16
|
-
has_uncommitted_changes)
|
15
|
+
from jarvis.jarvis_utils.git_utils import find_git_root, has_uncommitted_changes
|
17
16
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
18
17
|
from jarvis.jarvis_utils.tag import ct, ot
|
19
18
|
from jarvis.jarvis_utils.utils import init_env, is_context_overflow
|
@@ -22,263 +21,301 @@ from jarvis.jarvis_utils.utils import init_env, is_context_overflow
|
|
22
21
|
class GitCommitTool:
|
23
22
|
name = "git_commit_agent"
|
24
23
|
description = "根据代码变更自动生成并执行Git提交"
|
25
|
-
labels = [
|
24
|
+
labels = ["git", "version_control"]
|
26
25
|
parameters = {
|
27
26
|
"type": "object",
|
28
27
|
"properties": {
|
29
28
|
"root_dir": {
|
30
29
|
"type": "string",
|
31
30
|
"description": "Git仓库的根目录路径(可选)",
|
32
|
-
"default": "."
|
31
|
+
"default": ".",
|
33
32
|
},
|
34
|
-
"prefix": {
|
35
|
-
|
36
|
-
"description": "提交信息前缀(可选)",
|
37
|
-
"default": ""
|
38
|
-
},
|
39
|
-
"suffix": {
|
40
|
-
"type": "string",
|
41
|
-
"description": "提交信息后缀(可选)",
|
42
|
-
"default": ""
|
43
|
-
}
|
33
|
+
"prefix": {"type": "string", "description": "提交信息前缀(可选)", "default": ""},
|
34
|
+
"suffix": {"type": "string", "description": "提交信息后缀(可选)", "default": ""},
|
44
35
|
},
|
45
|
-
"required": []
|
36
|
+
"required": [],
|
46
37
|
}
|
47
|
-
|
38
|
+
|
39
|
+
def _extract_commit_message(self, message) -> Optional[str]:
|
48
40
|
"""Raw extraction preserving all characters"""
|
49
41
|
r = re.search(
|
50
42
|
r"(?i)" + ot("COMMIT_MESSAGE") + r"\s*([\s\S]*?)\s*" + ct("COMMIT_MESSAGE"),
|
51
|
-
message
|
43
|
+
message,
|
52
44
|
)
|
53
45
|
if r:
|
54
46
|
# 直接返回原始内容,仅去除外围空白
|
55
47
|
return r.group(1).strip()
|
56
48
|
return None
|
57
49
|
|
58
|
-
def _get_last_commit_hash(self):
|
50
|
+
def _get_last_commit_hash(self) -> str:
|
59
51
|
process = subprocess.Popen(
|
60
52
|
["git", "log", "-1", "--pretty=%H"],
|
61
53
|
stdout=subprocess.PIPE,
|
62
|
-
stderr=subprocess.PIPE
|
54
|
+
stderr=subprocess.PIPE,
|
63
55
|
)
|
64
56
|
stdout, _ = process.communicate()
|
65
57
|
return stdout.decode().strip()
|
66
58
|
|
59
|
+
def _prepare_git_environment(self, root_dir: str) -> Optional[str]:
|
60
|
+
"""Prepare git environment by changing directory and checking for changes"""
|
61
|
+
original_dir = os.getcwd()
|
62
|
+
os.chdir(root_dir)
|
63
|
+
find_git_root()
|
64
|
+
if not has_uncommitted_changes():
|
65
|
+
PrettyOutput.print("没有未提交的更改", OutputType.SUCCESS)
|
66
|
+
return None
|
67
|
+
return original_dir
|
68
|
+
|
69
|
+
def _stage_changes(self, spinner) -> None:
|
70
|
+
"""Stage all changes for commit"""
|
71
|
+
spinner.text = "正在添加文件到提交..."
|
72
|
+
subprocess.Popen(
|
73
|
+
["git", "add", "."], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
|
74
|
+
).wait()
|
75
|
+
spinner.write("✅ 添加文件到提交")
|
76
|
+
|
67
77
|
def execute(self, args: Dict) -> Dict[str, Any]:
|
68
78
|
"""Execute automatic commit process with support for multi-line messages and special characters"""
|
69
79
|
try:
|
80
|
+
original_dir = os.getcwd()
|
70
81
|
root_dir = args.get("root_dir", ".")
|
71
82
|
prefix = args.get("prefix", "")
|
72
83
|
suffix = args.get("suffix", "")
|
73
84
|
|
74
|
-
#
|
75
|
-
|
85
|
+
# Prepare git environment
|
86
|
+
result = self._prepare_git_environment(root_dir)
|
87
|
+
if result is None:
|
88
|
+
return {"success": True, "stdout": "No changes to commit", "stderr": ""}
|
89
|
+
original_dir = result
|
76
90
|
|
77
|
-
|
78
|
-
#
|
79
|
-
|
91
|
+
with yaspin(text="正在初始化提交流程...", color="cyan") as spinner:
|
92
|
+
# 添加文件到暂存区
|
93
|
+
self._stage_changes(spinner)
|
80
94
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
95
|
+
# 获取差异
|
96
|
+
spinner.text = "正在获取代码差异..."
|
97
|
+
# 获取文件列表
|
98
|
+
files_cmd = ["git", "diff", "--cached", "--name-only"]
|
99
|
+
process = subprocess.Popen(
|
100
|
+
files_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
101
|
+
)
|
102
|
+
files_output = process.communicate()[0].decode()
|
103
|
+
files = [f.strip() for f in files_output.split("\n") if f.strip()]
|
104
|
+
file_count = len(files)
|
85
105
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
subprocess.
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
106
|
+
# 获取完整差异
|
107
|
+
process = subprocess.Popen(
|
108
|
+
["git", "diff", "--cached", "--exit-code"],
|
109
|
+
stdout=subprocess.PIPE,
|
110
|
+
stderr=subprocess.PIPE,
|
111
|
+
)
|
112
|
+
diff = process.communicate()[0].decode()
|
113
|
+
spinner.write(f"✅ 获取差异 ({file_count} 个文件)")
|
114
|
+
try:
|
115
|
+
temp_diff_file_path = None
|
116
|
+
# 生成提交信息
|
117
|
+
spinner.text = "正在生成提交消息..."
|
95
118
|
|
96
|
-
#
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
119
|
+
# 准备提示信息
|
120
|
+
custom_prompt = get_git_commit_prompt()
|
121
|
+
base_prompt = (
|
122
|
+
custom_prompt
|
123
|
+
if custom_prompt
|
124
|
+
else f"""根据代码差异生成提交信息:
|
125
|
+
提交信息应使用中文书写
|
126
|
+
# 格式模板
|
127
|
+
必须使用以下格式:
|
128
|
+
|
129
|
+
<类型>(<范围>): <主题>
|
130
|
+
|
131
|
+
[可选] 详细描述变更内容和原因
|
132
|
+
|
133
|
+
# 格式规则
|
134
|
+
1. 类型: fix(修复bug), feat(新功能), docs(文档), style(格式), refactor(重构), test(测试), chore(其他)
|
135
|
+
2. 范围表示变更的模块或组件 (例如: auth, database, ui)
|
136
|
+
3. 主题行不超过72个字符,不以句号结尾,使用祈使语气
|
137
|
+
4. 如有详细描述,使用空行分隔主题和详细描述
|
138
|
+
5. 详细描述部分应解释"是什么"和"为什么",而非"如何"
|
139
|
+
6. 仅输出提交信息,不要输出其他内容
|
140
|
+
"""
|
114
141
|
)
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
# 准备提示信息
|
123
|
-
custom_prompt = get_git_commit_prompt()
|
124
|
-
base_prompt = custom_prompt if custom_prompt else f'''根据代码差异生成提交信息:
|
125
|
-
提交信息应使用中文书写
|
126
|
-
# 格式模板
|
127
|
-
必须使用以下格式:
|
142
|
+
base_prompt += f"""
|
143
|
+
# 输出格式
|
144
|
+
{ot("COMMIT_MESSAGE")}
|
145
|
+
commit信息
|
146
|
+
{ct("COMMIT_MESSAGE")}
|
147
|
+
"""
|
128
148
|
|
129
|
-
|
130
|
-
|
131
|
-
|
149
|
+
# 获取模型并尝试上传文件
|
150
|
+
platform = PlatformRegistry().get_normal_platform()
|
151
|
+
upload_success = False
|
132
152
|
|
133
|
-
|
134
|
-
|
135
|
-
2. 范围表示变更的模块或组件 (例如: auth, database, ui)
|
136
|
-
3. 主题行不超过72个字符,不以句号结尾,使用祈使语气
|
137
|
-
4. 如有详细描述,使用空行分隔主题和详细描述
|
138
|
-
5. 详细描述部分应解释"是什么"和"为什么",而非"如何"
|
139
|
-
6. 仅输出提交信息,不要输出其他内容
|
140
|
-
'''
|
141
|
-
base_prompt += f"""
|
142
|
-
# 输出格式
|
143
|
-
{ot("COMMIT_MESSAGE")}
|
144
|
-
commit信息
|
145
|
-
{ct("COMMIT_MESSAGE")}
|
146
|
-
"""
|
153
|
+
# Check if content is too large
|
154
|
+
is_large_content = is_context_overflow(diff)
|
147
155
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
except Exception as e:
|
171
|
-
spinner.write(f"⚠️ 上传文件时出错: {str(e)}")
|
172
|
-
upload_success = False
|
173
|
-
# 根据上传状态准备完整的提示
|
156
|
+
if is_large_content:
|
157
|
+
if not platform.support_upload_files():
|
158
|
+
spinner.text = "差异文件太大,无法处理"
|
159
|
+
spinner.fail("❌")
|
160
|
+
return {
|
161
|
+
"success": False,
|
162
|
+
"stdout": "",
|
163
|
+
"stderr": "错误:差异文件太大,无法处理",
|
164
|
+
}
|
165
|
+
spinner.text = "正在上传代码差异文件..."
|
166
|
+
with spinner.hidden():
|
167
|
+
# 创建临时文件并写入差异内容
|
168
|
+
with tempfile.NamedTemporaryFile(
|
169
|
+
mode="w", suffix=".diff", delete=False
|
170
|
+
) as temp_diff_file:
|
171
|
+
temp_diff_file_path = temp_diff_file.name
|
172
|
+
temp_diff_file.write(diff)
|
173
|
+
temp_diff_file.flush()
|
174
|
+
spinner.write(f"✅ 差异内容已写入临时文件")
|
175
|
+
upload_success = platform.upload_files(
|
176
|
+
[temp_diff_file_path]
|
177
|
+
)
|
174
178
|
if upload_success:
|
175
|
-
|
176
|
-
spinner.text = "正在生成提交消息..."
|
177
|
-
# 使用上传的文件
|
178
|
-
prompt = base_prompt + f'''
|
179
|
-
# 变更概述
|
180
|
-
- 变更文件数量: {file_count} 个文件
|
181
|
-
- 已上传包含完整代码差异的文件
|
182
|
-
|
183
|
-
请详细分析已上传的代码差异文件,生成符合上述格式的提交信息。
|
184
|
-
'''
|
185
|
-
commit_message = platform.chat_until_success(prompt)
|
179
|
+
spinner.write("✅ 成功上传代码差异文件")
|
186
180
|
else:
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
commit_message = platform.chat_until_success(prompt)
|
220
|
-
spinner.write("✅ 生成提交消息")
|
181
|
+
spinner.text = "上传代码差异文件失败"
|
182
|
+
spinner.fail("❌")
|
183
|
+
return {
|
184
|
+
"success": False,
|
185
|
+
"stdout": "",
|
186
|
+
"stderr": "错误:上传代码差异文件失败",
|
187
|
+
}
|
188
|
+
# 根据上传状态准备完整的提示
|
189
|
+
if is_large_content:
|
190
|
+
# 尝试生成提交信息
|
191
|
+
spinner.text = "正在生成提交消息..."
|
192
|
+
# 使用上传的文件
|
193
|
+
prompt = (
|
194
|
+
base_prompt
|
195
|
+
+ f"""
|
196
|
+
# 变更概述
|
197
|
+
- 变更文件数量: {file_count} 个文件
|
198
|
+
- 已上传包含完整代码差异的文件
|
199
|
+
|
200
|
+
请详细分析已上传的代码差异文件,生成符合上述格式的提交信息。
|
201
|
+
"""
|
202
|
+
)
|
203
|
+
commit_message = platform.chat_until_success(prompt)
|
204
|
+
else:
|
205
|
+
prompt = (
|
206
|
+
base_prompt
|
207
|
+
+ f"""
|
208
|
+
# 分析材料
|
209
|
+
{diff}
|
210
|
+
"""
|
211
|
+
)
|
212
|
+
commit_message = platform.chat_until_success(prompt)
|
221
213
|
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
214
|
+
while True:
|
215
|
+
# 只在特定情况下重新获取commit_message
|
216
|
+
if (
|
217
|
+
not upload_success
|
218
|
+
and not is_large_content
|
219
|
+
and not commit_message
|
220
|
+
):
|
221
|
+
commit_message = platform.chat_until_success(prompt)
|
222
|
+
extracted_message = self._extract_commit_message(commit_message)
|
223
|
+
# 如果成功提取,就跳出循环
|
224
|
+
if extracted_message:
|
225
|
+
commit_message = extracted_message
|
226
|
+
# 应用prefix和suffix
|
227
|
+
if prefix:
|
228
|
+
commit_message = f"{prefix} {commit_message}"
|
229
|
+
if suffix:
|
230
|
+
commit_message = f"{commit_message}\n{suffix}"
|
231
|
+
break
|
232
|
+
prompt = f"""格式错误,请按照以下格式重新生成提交信息:
|
233
|
+
{ot("COMMIT_MESSAGE")}
|
234
|
+
commit信息
|
235
|
+
{ct("COMMIT_MESSAGE")}
|
236
|
+
"""
|
237
|
+
commit_message = platform.chat_until_success(prompt)
|
238
|
+
spinner.write("✅ 生成提交消息")
|
235
239
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
240
|
+
# 执行提交
|
241
|
+
spinner.text = "正在准备提交..."
|
242
|
+
with tempfile.NamedTemporaryFile(mode="w", delete=True) as tmp_file:
|
243
|
+
tmp_file.write(commit_message)
|
244
|
+
tmp_file.flush()
|
245
|
+
spinner.text = "正在执行提交..."
|
246
|
+
commit_cmd = ["git", "commit", "-F", tmp_file.name]
|
247
|
+
subprocess.Popen(
|
248
|
+
commit_cmd,
|
249
|
+
stdout=subprocess.DEVNULL,
|
250
|
+
stderr=subprocess.DEVNULL,
|
251
|
+
).wait()
|
252
|
+
spinner.write("✅ 提交")
|
246
253
|
|
247
|
-
|
254
|
+
commit_hash = self._get_last_commit_hash()
|
255
|
+
spinner.text = "完成提交"
|
256
|
+
spinner.ok("✅")
|
257
|
+
finally:
|
258
|
+
# 清理临时差异文件
|
259
|
+
if temp_diff_file_path is not None and os.path.exists(
|
260
|
+
temp_diff_file_path
|
261
|
+
):
|
262
|
+
try:
|
263
|
+
os.unlink(temp_diff_file_path)
|
264
|
+
except Exception as e:
|
265
|
+
spinner.write(f"⚠️ 无法删除临时文件: {str(e)}")
|
248
266
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
"commit_hash": commit_hash,
|
253
|
-
"commit_message": commit_message
|
254
|
-
}, allow_unicode=True),
|
255
|
-
"stderr": ""
|
256
|
-
}
|
257
|
-
finally:
|
258
|
-
# Always restore original directory
|
259
|
-
os.chdir(original_dir)
|
267
|
+
PrettyOutput.print(
|
268
|
+
f"提交哈希: {commit_hash}\n提交消息: {commit_message}", OutputType.SUCCESS
|
269
|
+
)
|
260
270
|
|
271
|
+
return {
|
272
|
+
"success": True,
|
273
|
+
"stdout": yaml.safe_dump(
|
274
|
+
{"commit_hash": commit_hash, "commit_message": commit_message},
|
275
|
+
allow_unicode=True,
|
276
|
+
),
|
277
|
+
"stderr": "",
|
278
|
+
}
|
261
279
|
except Exception as e:
|
262
280
|
PrettyOutput.print(f"提交失败: {str(e)}", OutputType.ERROR)
|
263
281
|
return {
|
264
282
|
"success": False,
|
265
283
|
"stdout": "",
|
266
|
-
"stderr": f"Commit failed: {str(e)}"
|
284
|
+
"stderr": f"Commit failed: {str(e)}",
|
267
285
|
}
|
286
|
+
finally:
|
287
|
+
# Always restore original directory
|
288
|
+
os.chdir(original_dir)
|
289
|
+
|
268
290
|
|
269
291
|
def main():
|
270
292
|
init_env("欢迎使用 Jarvis-GitCommitTool,您的Git提交助手已准备就绪!")
|
271
|
-
parser = argparse.ArgumentParser(description=
|
272
|
-
parser.add_argument(
|
273
|
-
|
274
|
-
|
293
|
+
parser = argparse.ArgumentParser(description="Git commit tool")
|
294
|
+
parser.add_argument(
|
295
|
+
"--root-dir", type=str, default=".", help="Root directory of the Git repository"
|
296
|
+
)
|
297
|
+
parser.add_argument(
|
298
|
+
"--prefix",
|
299
|
+
type=str,
|
300
|
+
default="",
|
301
|
+
help="Prefix to prepend to commit message (separated by space)",
|
302
|
+
)
|
303
|
+
parser.add_argument(
|
304
|
+
"--suffix",
|
305
|
+
type=str,
|
306
|
+
default="",
|
307
|
+
help="Suffix to append to commit message (separated by newline)",
|
308
|
+
)
|
275
309
|
args = parser.parse_args()
|
276
310
|
tool = GitCommitTool()
|
277
|
-
tool.execute(
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
311
|
+
tool.execute(
|
312
|
+
{
|
313
|
+
"root_dir": args.root_dir,
|
314
|
+
"prefix": args.prefix if hasattr(args, "prefix") else "",
|
315
|
+
"suffix": args.suffix if hasattr(args, "suffix") else "",
|
316
|
+
}
|
317
|
+
)
|
318
|
+
|
282
319
|
|
283
320
|
if __name__ == "__main__":
|
284
|
-
sys.exit(main())
|
321
|
+
sys.exit(main())
|
jarvis/jarvis_platform/base.py
CHANGED
@@ -49,6 +49,10 @@ class BasePlatform(ABC):
|
|
49
49
|
def upload_files(self, file_list: List[str]) -> bool:
|
50
50
|
raise NotImplementedError("upload_files is not implemented")
|
51
51
|
|
52
|
+
@abstractmethod
|
53
|
+
def support_upload_files(self) -> bool:
|
54
|
+
"""Check if platform supports upload files"""
|
55
|
+
return False
|
52
56
|
|
53
57
|
|
54
58
|
def _chat(self, message: str):
|
@@ -56,9 +60,6 @@ class BasePlatform(ABC):
|
|
56
60
|
start_time = time.time()
|
57
61
|
|
58
62
|
input_token_count = get_context_token_count(message)
|
59
|
-
if is_context_overflow(message):
|
60
|
-
PrettyOutput.print("错误:输入内容超过最大限制", OutputType.WARNING)
|
61
|
-
return "错误:输入内容超过最大限制"
|
62
63
|
|
63
64
|
if input_token_count > get_max_input_token_count():
|
64
65
|
max_chunk_size = get_max_input_token_count() - 1024 # 留出一些余量
|
jarvis/jarvis_platform/kimi.py
CHANGED
@@ -90,6 +90,10 @@ class KimiModel(BasePlatform):
|
|
90
90
|
|
91
91
|
response = while_success(lambda: requests.post(url, headers=headers, data=payload), sleep_time=5)
|
92
92
|
return response.json()
|
93
|
+
|
94
|
+
def support_upload_files(self) -> bool:
|
95
|
+
"""Check if platform supports upload files"""
|
96
|
+
return True
|
93
97
|
|
94
98
|
def _upload_file(self, file_path: str, presigned_url: str) -> bool:
|
95
99
|
"""Upload file to presigned URL"""
|
jarvis/jarvis_platform/tongyi.py
CHANGED
@@ -67,6 +67,10 @@ class TongyiPlatform(BasePlatform):
|
|
67
67
|
def _generate_request_id(self):
|
68
68
|
self.request_id = str(uuid.uuid4()).replace("-", "")
|
69
69
|
|
70
|
+
def support_upload_files(self) -> bool:
|
71
|
+
"""Check if platform supports upload files"""
|
72
|
+
return True
|
73
|
+
|
70
74
|
def chat(self, message: str) -> Generator[str, None, None]:
|
71
75
|
if not self.request_id:
|
72
76
|
self._generate_request_id()
|
@@ -107,6 +107,10 @@ class YuanbaoPlatform(BasePlatform):
|
|
107
107
|
PrettyOutput.print(f"错误:创建会话失败:{e}", OutputType.ERROR)
|
108
108
|
return False
|
109
109
|
|
110
|
+
def support_upload_files(self) -> bool:
|
111
|
+
"""Check if platform supports upload files"""
|
112
|
+
return True
|
113
|
+
|
110
114
|
def upload_files(self, file_list: List[str]) -> bool:
|
111
115
|
"""上传文件到元宝平台
|
112
116
|
|
@@ -105,6 +105,10 @@ def chat_with_model(platform_name: str, model_name: str):
|
|
105
105
|
# Remove quotes if present
|
106
106
|
if (file_path.startswith('"') and file_path.endswith('"')) or (file_path.startswith("'") and file_path.endswith("'")):
|
107
107
|
file_path = file_path[1:-1]
|
108
|
+
|
109
|
+
if not platform.support_upload_files():
|
110
|
+
PrettyOutput.print("平台不支持上传文件", OutputType.ERROR)
|
111
|
+
continue
|
108
112
|
|
109
113
|
PrettyOutput.print(f"正在上传文件: {file_path}", OutputType.INFO)
|
110
114
|
if platform.upload_files([file_path]):
|
jarvis/jarvis_tools/edit_file.py
CHANGED
@@ -286,11 +286,11 @@ def slow_edit(filepath: str, patch_content: str, spinner: Yaspin) -> Tuple[bool,
|
|
286
286
|
model = PlatformRegistry().get_normal_platform()
|
287
287
|
try:
|
288
288
|
file_content = FileOperationTool().execute({"operation":"read", "files":[{"path":filepath}]})["stdout"]
|
289
|
-
|
289
|
+
is_large_context = is_context_overflow(file_content)
|
290
290
|
upload_success = False
|
291
291
|
# 读取原始文件内容
|
292
292
|
with spinner.hidden():
|
293
|
-
if
|
293
|
+
if is_large_context and model.support_upload_files() and model.upload_files([filepath]):
|
294
294
|
upload_success = True
|
295
295
|
|
296
296
|
|
@@ -340,19 +340,21 @@ def slow_edit(filepath: str, patch_content: str, spinner: Yaspin) -> Tuple[bool,
|
|
340
340
|
"""
|
341
341
|
|
342
342
|
for _ in range(3):
|
343
|
-
|
344
|
-
|
343
|
+
if is_large_context:
|
344
|
+
if upload_success:
|
345
|
+
response = model.chat_until_success(main_prompt)
|
346
|
+
else:
|
347
|
+
file_prompt = f"""
|
348
|
+
# 原始代码
|
349
|
+
{file_content}
|
350
|
+
"""
|
351
|
+
response = model.chat_until_success(main_prompt + file_prompt)
|
352
|
+
else:
|
345
353
|
file_prompt = f"""
|
346
354
|
# 原始代码
|
347
355
|
{file_content}
|
348
356
|
"""
|
349
|
-
|
350
357
|
response = model.chat_until_success(main_prompt + file_prompt)
|
351
|
-
else:
|
352
|
-
if upload_success:
|
353
|
-
response = model.chat_until_success(main_prompt)
|
354
|
-
else:
|
355
|
-
return False, "文件上传失败"
|
356
358
|
|
357
359
|
# 解析差异化补丁
|
358
360
|
diff_blocks = re.finditer(ot("DIFF")+r'\s*>{4,} SEARCH\n?(.*?)\n?={4,}\n?(.*?)\s*<{4,} REPLACE\n?'+ct("DIFF"),
|