jarvis-ai-assistant 0.1.120__py3-none-any.whl → 0.1.122__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 +3 -3
- jarvis/jarvis_code_agent/code_agent.py +36 -58
- jarvis/jarvis_code_agent/file_select.py +3 -3
- jarvis/jarvis_code_agent/patch.py +155 -298
- jarvis/jarvis_code_agent/relevant_files.py +2 -4
- jarvis/jarvis_codebase/main.py +2 -2
- jarvis/jarvis_lsp/registry.py +7 -7
- jarvis/jarvis_platform/ai8.py +10 -10
- jarvis/jarvis_platform/kimi.py +3 -5
- jarvis/jarvis_platform/oyi.py +11 -11
- jarvis/jarvis_platform/registry.py +3 -3
- jarvis/jarvis_platform_manager/main.py +2 -2
- jarvis/jarvis_tools/ask_codebase.py +1 -1
- jarvis/jarvis_tools/code_review.py +1 -1
- jarvis/jarvis_tools/create_code_agent.py +1 -1
- jarvis/jarvis_tools/file_operation.py +0 -3
- jarvis/jarvis_tools/git_commiter.py +26 -7
- jarvis/jarvis_tools/rag.py +1 -1
- jarvis/jarvis_tools/read_code.py +1 -2
- jarvis/jarvis_utils/__init__.py +120 -47
- {jarvis_ai_assistant-0.1.120.dist-info → jarvis_ai_assistant-0.1.122.dist-info}/METADATA +1 -1
- {jarvis_ai_assistant-0.1.120.dist-info → jarvis_ai_assistant-0.1.122.dist-info}/RECORD +27 -28
- {jarvis_ai_assistant-0.1.120.dist-info → jarvis_ai_assistant-0.1.122.dist-info}/entry_points.txt +0 -1
- jarvis/jarvis_dev/main.py +0 -878
- {jarvis_ai_assistant-0.1.120.dist-info → jarvis_ai_assistant-0.1.122.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.120.dist-info → jarvis_ai_assistant-0.1.122.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.120.dist-info → jarvis_ai_assistant-0.1.122.dist-info}/top_level.txt +0 -0
jarvis/jarvis_platform/ai8.py
CHANGED
|
@@ -60,12 +60,12 @@ class AI8Model(BasePlatform):
|
|
|
60
60
|
)
|
|
61
61
|
|
|
62
62
|
if response.status_code != 200:
|
|
63
|
-
PrettyOutput.print(f"创建会话失败: {response.status_code}", OutputType.
|
|
63
|
+
PrettyOutput.print(f"创建会话失败: {response.status_code}", OutputType.WARNING)
|
|
64
64
|
return False
|
|
65
65
|
|
|
66
66
|
data = response.json()
|
|
67
67
|
if data['code'] != 0:
|
|
68
|
-
PrettyOutput.print(f"创建会话失败: {data.get('msg', '未知错误')}", OutputType.
|
|
68
|
+
PrettyOutput.print(f"创建会话失败: {data.get('msg', '未知错误')}", OutputType.WARNING)
|
|
69
69
|
return False
|
|
70
70
|
|
|
71
71
|
self.conversation = data['data']
|
|
@@ -93,10 +93,10 @@ class AI8Model(BasePlatform):
|
|
|
93
93
|
self.conversation = data['data']
|
|
94
94
|
return True
|
|
95
95
|
else:
|
|
96
|
-
PrettyOutput.print(f"更新会话设置失败: {data.get('msg', '未知错误')}", OutputType.
|
|
96
|
+
PrettyOutput.print(f"更新会话设置失败: {data.get('msg', '未知错误')}", OutputType.WARNING)
|
|
97
97
|
return False
|
|
98
98
|
else:
|
|
99
|
-
PrettyOutput.print(f"更新会话设置失败: {response.status_code}", OutputType.
|
|
99
|
+
PrettyOutput.print(f"更新会话设置失败: {response.status_code}", OutputType.WARNING)
|
|
100
100
|
return False
|
|
101
101
|
|
|
102
102
|
except Exception as e:
|
|
@@ -162,7 +162,7 @@ class AI8Model(BasePlatform):
|
|
|
162
162
|
|
|
163
163
|
if response.status_code != 200:
|
|
164
164
|
error_msg = f"Failed to chat: {response.status_code} {response.text}"
|
|
165
|
-
PrettyOutput.print(error_msg, OutputType.
|
|
165
|
+
PrettyOutput.print(error_msg, OutputType.WARNING)
|
|
166
166
|
raise Exception(error_msg)
|
|
167
167
|
|
|
168
168
|
# 处理流式响应
|
|
@@ -229,11 +229,11 @@ class AI8Model(BasePlatform):
|
|
|
229
229
|
return True
|
|
230
230
|
else:
|
|
231
231
|
error_msg = f"删除会话失败: {data.get('msg', '未知错误')}"
|
|
232
|
-
PrettyOutput.print(error_msg, OutputType.
|
|
232
|
+
PrettyOutput.print(error_msg, OutputType.WARNING)
|
|
233
233
|
return False
|
|
234
234
|
else:
|
|
235
235
|
error_msg = f"删除会话请求失败: {response.status_code}"
|
|
236
|
-
PrettyOutput.print(error_msg, OutputType.
|
|
236
|
+
PrettyOutput.print(error_msg, OutputType.WARNING)
|
|
237
237
|
return False
|
|
238
238
|
|
|
239
239
|
except Exception as e:
|
|
@@ -265,12 +265,12 @@ class AI8Model(BasePlatform):
|
|
|
265
265
|
)
|
|
266
266
|
|
|
267
267
|
if response.status_code != 200:
|
|
268
|
-
PrettyOutput.print(f"获取模型列表失败: {response.status_code}", OutputType.
|
|
268
|
+
PrettyOutput.print(f"获取模型列表失败: {response.status_code}", OutputType.WARNING)
|
|
269
269
|
return []
|
|
270
270
|
|
|
271
271
|
data = response.json()
|
|
272
272
|
if data['code'] != 0:
|
|
273
|
-
PrettyOutput.print(f"获取模型列表失败: {data.get('msg', '未知错误')}", OutputType.
|
|
273
|
+
PrettyOutput.print(f"获取模型列表失败: {data.get('msg', '未知错误')}", OutputType.WARNING)
|
|
274
274
|
return []
|
|
275
275
|
|
|
276
276
|
# 保存模型信息
|
|
@@ -309,6 +309,6 @@ class AI8Model(BasePlatform):
|
|
|
309
309
|
return list(self.models.keys())
|
|
310
310
|
|
|
311
311
|
except Exception as e:
|
|
312
|
-
PrettyOutput.print(f"获取模型列表失败: {str(e)}", OutputType.
|
|
312
|
+
PrettyOutput.print(f"获取模型列表失败: {str(e)}", OutputType.ERROR)
|
|
313
313
|
return []
|
|
314
314
|
|
jarvis/jarvis_platform/kimi.py
CHANGED
|
@@ -198,11 +198,11 @@ class KimiModel(BasePlatform):
|
|
|
198
198
|
if self._wait_for_parse(file_info["id"]):
|
|
199
199
|
uploaded_files.append(file_info)
|
|
200
200
|
else:
|
|
201
|
-
PrettyOutput.print(f"✗ 文件解析失败: {file_path}", OutputType.
|
|
201
|
+
PrettyOutput.print(f"✗ 文件解析失败: {file_path}", OutputType.WARNING)
|
|
202
202
|
else:
|
|
203
203
|
uploaded_files.append(file_info)
|
|
204
204
|
else:
|
|
205
|
-
PrettyOutput.print(f"错误:文件上传失败: {file_path}", OutputType.
|
|
205
|
+
PrettyOutput.print(f"错误:文件上传失败: {file_path}", OutputType.WARNING)
|
|
206
206
|
|
|
207
207
|
except Exception as e:
|
|
208
208
|
PrettyOutput.print(f"✗ 处理文件出错 {file_path}: {str(e)}", OutputType.ERROR)
|
|
@@ -350,8 +350,6 @@ class KimiModel(BasePlatform):
|
|
|
350
350
|
output.append("")
|
|
351
351
|
|
|
352
352
|
PrettyOutput.print("\n".join(output), OutputType.PROGRESS)
|
|
353
|
-
|
|
354
|
-
PrettyOutput.print(full_response, OutputType.RESULT)
|
|
355
353
|
|
|
356
354
|
return full_response
|
|
357
355
|
|
|
@@ -375,7 +373,7 @@ class KimiModel(BasePlatform):
|
|
|
375
373
|
self.reset()
|
|
376
374
|
return True
|
|
377
375
|
else:
|
|
378
|
-
PrettyOutput.print(f"删除会话失败: HTTP {response.status_code}", OutputType.
|
|
376
|
+
PrettyOutput.print(f"删除会话失败: HTTP {response.status_code}", OutputType.WARNING)
|
|
379
377
|
return False
|
|
380
378
|
except Exception as e:
|
|
381
379
|
PrettyOutput.print(f"删除会话时发生错误: {str(e)}", OutputType.ERROR)
|
jarvis/jarvis_platform/oyi.py
CHANGED
|
@@ -83,10 +83,10 @@ class OyiModel(BasePlatform):
|
|
|
83
83
|
self.conversation = data
|
|
84
84
|
return True
|
|
85
85
|
else:
|
|
86
|
-
PrettyOutput.print(f"创建会话失败: {data['message']}", OutputType.
|
|
86
|
+
PrettyOutput.print(f"创建会话失败: {data['message']}", OutputType.WARNING)
|
|
87
87
|
return False
|
|
88
88
|
else:
|
|
89
|
-
PrettyOutput.print(f"创建会话失败: {response.status_code}", OutputType.
|
|
89
|
+
PrettyOutput.print(f"创建会话失败: {response.status_code}", OutputType.WARNING)
|
|
90
90
|
return False
|
|
91
91
|
|
|
92
92
|
except Exception as e:
|
|
@@ -157,13 +157,13 @@ class OyiModel(BasePlatform):
|
|
|
157
157
|
|
|
158
158
|
if response.status_code != 200:
|
|
159
159
|
error_msg = f"聊天请求失败: {response.status_code}"
|
|
160
|
-
PrettyOutput.print(error_msg, OutputType.
|
|
160
|
+
PrettyOutput.print(error_msg, OutputType.WARNING)
|
|
161
161
|
raise Exception(error_msg)
|
|
162
162
|
|
|
163
163
|
data = response.json()
|
|
164
164
|
if data['code'] != 200 or data['type'] != 'success':
|
|
165
165
|
error_msg = f"聊天失败: {data.get('message', '未知错误')}"
|
|
166
|
-
PrettyOutput.print(error_msg, OutputType.
|
|
166
|
+
PrettyOutput.print(error_msg, OutputType.WARNING)
|
|
167
167
|
raise Exception(error_msg)
|
|
168
168
|
|
|
169
169
|
message_id = data['result'][-1]
|
|
@@ -196,7 +196,7 @@ class OyiModel(BasePlatform):
|
|
|
196
196
|
return full_response
|
|
197
197
|
else:
|
|
198
198
|
error_msg = f"获取响应失败: {response.status_code}"
|
|
199
|
-
PrettyOutput.print(error_msg, OutputType.
|
|
199
|
+
PrettyOutput.print(error_msg, OutputType.WARNING)
|
|
200
200
|
raise Exception(error_msg)
|
|
201
201
|
except Exception as e:
|
|
202
202
|
PrettyOutput.print(f"聊天失败: {str(e)}", OutputType.ERROR)
|
|
@@ -241,11 +241,11 @@ class OyiModel(BasePlatform):
|
|
|
241
241
|
return True
|
|
242
242
|
else:
|
|
243
243
|
error_msg = f"删除会话失败: {data.get('message', '未知错误')}"
|
|
244
|
-
PrettyOutput.print(error_msg, OutputType.
|
|
244
|
+
PrettyOutput.print(error_msg, OutputType.WARNING)
|
|
245
245
|
return False
|
|
246
246
|
else:
|
|
247
247
|
error_msg = f"删除会话请求失败: {response.status_code}"
|
|
248
|
-
PrettyOutput.print(error_msg, OutputType.
|
|
248
|
+
PrettyOutput.print(error_msg, OutputType.WARNING)
|
|
249
249
|
return False
|
|
250
250
|
|
|
251
251
|
except Exception as e:
|
|
@@ -281,7 +281,7 @@ class OyiModel(BasePlatform):
|
|
|
281
281
|
# 检查文件类型
|
|
282
282
|
file_type = mimetypes.guess_type(file_path)[0]
|
|
283
283
|
if not file_type or not file_type.startswith(('image/', 'text/', 'application/')):
|
|
284
|
-
PrettyOutput.print(f"文件类型 {file_type} 不支持", OutputType.
|
|
284
|
+
PrettyOutput.print(f"文件类型 {file_type} 不支持", OutputType.WARNING)
|
|
285
285
|
continue
|
|
286
286
|
|
|
287
287
|
with open(file_path, 'rb') as f:
|
|
@@ -300,10 +300,10 @@ class OyiModel(BasePlatform):
|
|
|
300
300
|
if data.get('code') == 200:
|
|
301
301
|
self.files.append(data)
|
|
302
302
|
else:
|
|
303
|
-
PrettyOutput.print(f"文件上传失败: {data.get('message')}", OutputType.
|
|
303
|
+
PrettyOutput.print(f"文件上传失败: {data.get('message')}", OutputType.WARNING)
|
|
304
304
|
return []
|
|
305
305
|
else:
|
|
306
|
-
PrettyOutput.print(f"文件上传失败: {response.status_code}", OutputType.
|
|
306
|
+
PrettyOutput.print(f"文件上传失败: {response.status_code}", OutputType.WARNING)
|
|
307
307
|
return []
|
|
308
308
|
|
|
309
309
|
return self.files
|
|
@@ -335,7 +335,7 @@ class OyiModel(BasePlatform):
|
|
|
335
335
|
)
|
|
336
336
|
|
|
337
337
|
if response.status_code != 200:
|
|
338
|
-
PrettyOutput.print(f"获取模型列表失败: {response.status_code}", OutputType.
|
|
338
|
+
PrettyOutput.print(f"获取模型列表失败: {response.status_code}", OutputType.WARNING)
|
|
339
339
|
return []
|
|
340
340
|
|
|
341
341
|
data = response.json()
|
|
@@ -72,7 +72,7 @@ class PlatformRegistry:
|
|
|
72
72
|
if missing_methods:
|
|
73
73
|
PrettyOutput.print(
|
|
74
74
|
f"平台 {platform_class.__name__} 缺少必要的方法: {', '.join(missing_methods)}",
|
|
75
|
-
OutputType.
|
|
75
|
+
OutputType.WARNING
|
|
76
76
|
)
|
|
77
77
|
return False
|
|
78
78
|
|
|
@@ -92,7 +92,7 @@ class PlatformRegistry:
|
|
|
92
92
|
|
|
93
93
|
# 确保目录存在
|
|
94
94
|
if not os.path.exists(directory):
|
|
95
|
-
PrettyOutput.print(f"平台目录不存在: {directory}", OutputType.
|
|
95
|
+
PrettyOutput.print(f"平台目录不存在: {directory}", OutputType.WARNING)
|
|
96
96
|
return platforms
|
|
97
97
|
|
|
98
98
|
# 获取目录的包名
|
|
@@ -201,7 +201,7 @@ class PlatformRegistry:
|
|
|
201
201
|
BasePlatform: Platform instance
|
|
202
202
|
"""
|
|
203
203
|
if name not in self.platforms:
|
|
204
|
-
PrettyOutput.print(f"未找到平台: {name}", OutputType.
|
|
204
|
+
PrettyOutput.print(f"未找到平台: {name}", OutputType.WARNING)
|
|
205
205
|
return None
|
|
206
206
|
|
|
207
207
|
try:
|
|
@@ -55,7 +55,7 @@ def chat_with_model(platform_name: str, model_name: str):
|
|
|
55
55
|
# Create platform instance
|
|
56
56
|
platform = registry.create_platform(platform_name)
|
|
57
57
|
if not platform:
|
|
58
|
-
PrettyOutput.print(f"创建平台 {platform_name} 失败", OutputType.
|
|
58
|
+
PrettyOutput.print(f"创建平台 {platform_name} 失败", OutputType.WARNING)
|
|
59
59
|
return
|
|
60
60
|
|
|
61
61
|
try:
|
|
@@ -108,7 +108,7 @@ def chat_with_model(platform_name: str, model_name: str):
|
|
|
108
108
|
# Helper function for platform and model validation
|
|
109
109
|
def validate_platform_model(args):
|
|
110
110
|
if not args.platform or not args.model:
|
|
111
|
-
PrettyOutput.print("请指定平台和模型。使用 'jarvis info' 查看可用平台和模型。", OutputType.
|
|
111
|
+
PrettyOutput.print("请指定平台和模型。使用 'jarvis info' 查看可用平台和模型。", OutputType.WARNING)
|
|
112
112
|
return False
|
|
113
113
|
return True
|
|
114
114
|
|
|
@@ -89,7 +89,7 @@ def main():
|
|
|
89
89
|
if result["success"]:
|
|
90
90
|
PrettyOutput.print(result["stdout"], OutputType.INFO, lang="markdown")
|
|
91
91
|
else:
|
|
92
|
-
PrettyOutput.print(result["stderr"], OutputType.
|
|
92
|
+
PrettyOutput.print(result["stderr"], OutputType.WARNING)
|
|
93
93
|
|
|
94
94
|
|
|
95
95
|
if __name__ == "__main__":
|
|
@@ -241,7 +241,7 @@ def main():
|
|
|
241
241
|
PrettyOutput.print(report, OutputType.SUCCESS, lang="yaml")
|
|
242
242
|
|
|
243
243
|
else:
|
|
244
|
-
PrettyOutput.print(result["stderr"], OutputType.
|
|
244
|
+
PrettyOutput.print(result["stderr"], OutputType.WARNING)
|
|
245
245
|
|
|
246
246
|
if __name__ == "__main__":
|
|
247
247
|
main()
|
|
@@ -109,7 +109,7 @@ def main():
|
|
|
109
109
|
if result["success"]:
|
|
110
110
|
PrettyOutput.print(result["stdout"], OutputType.SUCCESS)
|
|
111
111
|
else:
|
|
112
|
-
PrettyOutput.print(result["stderr"], OutputType.
|
|
112
|
+
PrettyOutput.print(result["stderr"], OutputType.WARNING)
|
|
113
113
|
|
|
114
114
|
if __name__ == "__main__":
|
|
115
115
|
main()
|
|
@@ -57,9 +57,6 @@ class FileOperationTool:
|
|
|
57
57
|
content = open(abs_path, 'r', encoding='utf-8').read()
|
|
58
58
|
output = f"File: {abs_path}\n{content}"
|
|
59
59
|
|
|
60
|
-
# Print file content
|
|
61
|
-
PrettyOutput.print(f"读取文件: {abs_path}\n{content}", OutputType.INFO)
|
|
62
|
-
|
|
63
60
|
return {
|
|
64
61
|
"success": True,
|
|
65
62
|
"stdout": output,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import re
|
|
3
3
|
import shlex
|
|
4
|
+
import subprocess
|
|
4
5
|
from typing import Dict, Any
|
|
5
6
|
import tempfile
|
|
6
|
-
|
|
7
7
|
import yaml
|
|
8
8
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
9
9
|
from jarvis.jarvis_utils import OutputType, PrettyOutput, has_uncommitted_changes, init_env
|
|
@@ -27,7 +27,13 @@ class GitCommitTool:
|
|
|
27
27
|
return "<<FORMAT VIOLATION>> Invalid commit message structure"
|
|
28
28
|
|
|
29
29
|
def _get_last_commit_hash(self):
|
|
30
|
-
|
|
30
|
+
process = subprocess.Popen(
|
|
31
|
+
["git", "log", "-1", "--pretty=%H"],
|
|
32
|
+
stdout=subprocess.PIPE,
|
|
33
|
+
stderr=subprocess.PIPE
|
|
34
|
+
)
|
|
35
|
+
stdout, _ = process.communicate()
|
|
36
|
+
return stdout.decode().strip()
|
|
31
37
|
|
|
32
38
|
def execute(self, args: Dict) -> Dict[str, Any]:
|
|
33
39
|
"""Execute automatic commit process with support for multi-line messages and special characters"""
|
|
@@ -37,10 +43,19 @@ class GitCommitTool:
|
|
|
37
43
|
return {"success": True, "stdout": "No changes to commit", "stderr": ""}
|
|
38
44
|
|
|
39
45
|
PrettyOutput.print("准备添加文件到提交...", OutputType.SYSTEM)
|
|
40
|
-
|
|
46
|
+
subprocess.Popen(
|
|
47
|
+
["git", "add", "."],
|
|
48
|
+
stdout=subprocess.DEVNULL,
|
|
49
|
+
stderr=subprocess.DEVNULL
|
|
50
|
+
).wait()
|
|
41
51
|
|
|
42
52
|
PrettyOutput.print("获取差异...", OutputType.SYSTEM)
|
|
43
|
-
|
|
53
|
+
process = subprocess.Popen(
|
|
54
|
+
["git", "diff", "--cached", "--exit-code"],
|
|
55
|
+
stdout=subprocess.PIPE,
|
|
56
|
+
stderr=subprocess.PIPE
|
|
57
|
+
)
|
|
58
|
+
diff = process.communicate()[0].decode()
|
|
44
59
|
PrettyOutput.print(diff, OutputType.CODE, lang="diff")
|
|
45
60
|
|
|
46
61
|
prompt = f'''Generate commit message with the paranoia of someone who's lost production data:
|
|
@@ -69,7 +84,7 @@ YOU MUST USE EXACTLY THIS FORMAT:
|
|
|
69
84
|
|
|
70
85
|
PrettyOutput.print("生成提交消息...", OutputType.SYSTEM)
|
|
71
86
|
platform = PlatformRegistry().get_codegen_platform()
|
|
72
|
-
|
|
87
|
+
platform.set_suppress_output(True)
|
|
73
88
|
commit_message = platform.chat_until_success(prompt)
|
|
74
89
|
commit_message = self._extract_commit_message(commit_message)
|
|
75
90
|
|
|
@@ -77,9 +92,13 @@ YOU MUST USE EXACTLY THIS FORMAT:
|
|
|
77
92
|
with tempfile.NamedTemporaryFile(mode='w', delete=True) as tmp_file:
|
|
78
93
|
tmp_file.write(commit_message)
|
|
79
94
|
tmp_file.flush() # 确保内容写入文件
|
|
80
|
-
commit_cmd =
|
|
95
|
+
commit_cmd = ["git", "commit", "-F", tmp_file.name]
|
|
81
96
|
PrettyOutput.print("提交...", OutputType.INFO)
|
|
82
|
-
|
|
97
|
+
subprocess.Popen(
|
|
98
|
+
commit_cmd,
|
|
99
|
+
stdout=subprocess.DEVNULL,
|
|
100
|
+
stderr=subprocess.DEVNULL
|
|
101
|
+
).wait()
|
|
83
102
|
|
|
84
103
|
commit_hash = self._get_last_commit_hash()
|
|
85
104
|
PrettyOutput.print(f"提交哈希: {commit_hash}\n提交消息: {commit_message}", OutputType.SUCCESS)
|
jarvis/jarvis_tools/rag.py
CHANGED
|
@@ -135,7 +135,7 @@ def main():
|
|
|
135
135
|
if result["success"]:
|
|
136
136
|
PrettyOutput.print(f"{result['stdout']}", OutputType.INFO, lang="markdown")
|
|
137
137
|
else:
|
|
138
|
-
PrettyOutput.print(result["stderr"], OutputType.
|
|
138
|
+
PrettyOutput.print(result["stderr"], OutputType.WARNING)
|
|
139
139
|
|
|
140
140
|
if __name__ == "__main__":
|
|
141
141
|
main()
|
jarvis/jarvis_tools/read_code.py
CHANGED
|
@@ -52,7 +52,7 @@ class ReadCodeTool:
|
|
|
52
52
|
"""
|
|
53
53
|
try:
|
|
54
54
|
abs_path = os.path.abspath(filepath.strip())
|
|
55
|
-
PrettyOutput.print(f"正在读取代码文件:{abs_path}", OutputType.INFO)
|
|
55
|
+
PrettyOutput.print(f"正在读取代码文件:{abs_path} [范围: [{start_line},{end_line}]]", OutputType.INFO)
|
|
56
56
|
|
|
57
57
|
if not os.path.exists(abs_path):
|
|
58
58
|
PrettyOutput.print(f"文件不存在: {abs_path}", OutputType.WARNING)
|
|
@@ -120,7 +120,6 @@ class ReadCodeTool:
|
|
|
120
120
|
|
|
121
121
|
content = "".join(formatted_lines)
|
|
122
122
|
output = f"File: {filepath}\nLines: [{start_line}, {end_line}]\n{content}"
|
|
123
|
-
PrettyOutput.print(output, OutputType.CODE)
|
|
124
123
|
return {
|
|
125
124
|
"success": True,
|
|
126
125
|
"stdout": output,
|
jarvis/jarvis_utils/__init__.py
CHANGED
|
@@ -23,9 +23,11 @@ import psutil
|
|
|
23
23
|
from rich.console import Console
|
|
24
24
|
from rich.theme import Theme
|
|
25
25
|
from rich.panel import Panel
|
|
26
|
+
from rich.box import HEAVY
|
|
26
27
|
from rich.text import Text
|
|
27
28
|
from rich.traceback import install as install_rich_traceback
|
|
28
29
|
from rich.syntax import Syntax
|
|
30
|
+
from rich.style import Style as RichStyle
|
|
29
31
|
|
|
30
32
|
from prompt_toolkit.completion import Completer, Completion, PathCompleter
|
|
31
33
|
from prompt_toolkit.document import Document
|
|
@@ -45,18 +47,18 @@ install_rich_traceback()
|
|
|
45
47
|
|
|
46
48
|
# Create console with custom theme
|
|
47
49
|
custom_theme = Theme({
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
50
|
+
"INFO": "yellow",
|
|
51
|
+
"WARNING": "yellow",
|
|
52
|
+
"ERROR": "red",
|
|
53
|
+
"SUCCESS": "green",
|
|
54
|
+
"SYSTEM": "cyan",
|
|
55
|
+
"CODE": "green",
|
|
56
|
+
"RESULT": "blue",
|
|
57
|
+
"PLANNING": "magenta",
|
|
58
|
+
"PROGRESS": "white",
|
|
59
|
+
"DEBUG": "blue",
|
|
60
|
+
"USER": "green",
|
|
61
|
+
"TOOL": "yellow",
|
|
60
62
|
})
|
|
61
63
|
|
|
62
64
|
console = Console(theme=custom_theme)
|
|
@@ -76,7 +78,7 @@ def set_agent(agent_name: str, agent: Any):
|
|
|
76
78
|
current_agent_name = agent_name
|
|
77
79
|
|
|
78
80
|
def get_agent_list():
|
|
79
|
-
return "[" + str(len(global_agents)) + "]" + current_agent_name if global_agents else "
|
|
81
|
+
return "[" + str(len(global_agents)) + "]" + current_agent_name if global_agents else ""
|
|
80
82
|
|
|
81
83
|
def delete_agent(agent_name: str):
|
|
82
84
|
if agent_name in global_agents:
|
|
@@ -85,18 +87,18 @@ def delete_agent(agent_name: str):
|
|
|
85
87
|
current_agent_name = ""
|
|
86
88
|
|
|
87
89
|
class OutputType(Enum):
|
|
88
|
-
SYSTEM = "
|
|
89
|
-
CODE = "
|
|
90
|
-
RESULT = "
|
|
91
|
-
ERROR = "
|
|
92
|
-
INFO = "
|
|
93
|
-
PLANNING = "
|
|
94
|
-
PROGRESS = "
|
|
95
|
-
SUCCESS = "
|
|
96
|
-
WARNING = "
|
|
97
|
-
DEBUG = "
|
|
98
|
-
USER = "
|
|
99
|
-
TOOL = "
|
|
90
|
+
SYSTEM = "SYSTEM" # AI assistant message
|
|
91
|
+
CODE = "CODE" # Code related
|
|
92
|
+
RESULT = "RESULT" # Tool execution result
|
|
93
|
+
ERROR = "ERROR" # Error information
|
|
94
|
+
INFO = "INFO" # System prompt
|
|
95
|
+
PLANNING = "PLANNING" # Task planning
|
|
96
|
+
PROGRESS = "PROGRESS" # Execution progress
|
|
97
|
+
SUCCESS = "SUCCESS" # Success information
|
|
98
|
+
WARNING = "WARNING" # Warning information
|
|
99
|
+
DEBUG = "DEBUG" # Debug information
|
|
100
|
+
USER = "USER" # User input
|
|
101
|
+
TOOL = "TOOL" # Tool call
|
|
100
102
|
|
|
101
103
|
class PrettyOutput:
|
|
102
104
|
"""Pretty output using rich"""
|
|
@@ -164,18 +166,20 @@ class PrettyOutput:
|
|
|
164
166
|
return default_lang
|
|
165
167
|
|
|
166
168
|
@staticmethod
|
|
167
|
-
def _format(
|
|
169
|
+
def _format(output_type: OutputType, timestamp: bool = True) -> Text:
|
|
168
170
|
"""Format output text using rich Text"""
|
|
169
171
|
# Create rich Text object
|
|
170
172
|
formatted = Text()
|
|
171
173
|
|
|
172
174
|
# Add timestamp and agent info
|
|
173
175
|
if timestamp:
|
|
174
|
-
formatted.append(f"[{datetime.now().strftime('%H:%M:%S')}]
|
|
175
|
-
|
|
176
|
+
formatted.append(f"[{datetime.now().strftime('%H:%M:%S')}][{output_type.value}]", style=output_type.value)
|
|
177
|
+
agent_info = get_agent_list()
|
|
178
|
+
if agent_info: # Only add brackets if there's agent info
|
|
179
|
+
formatted.append(f"[{agent_info}]", style="blue")
|
|
176
180
|
# Add icon
|
|
177
181
|
icon = PrettyOutput._ICONS.get(output_type, "")
|
|
178
|
-
formatted.append(f"{icon} ", style=output_type.value)
|
|
182
|
+
formatted.append(f" {icon} ", style=output_type.value)
|
|
179
183
|
|
|
180
184
|
return formatted
|
|
181
185
|
|
|
@@ -190,27 +194,86 @@ class PrettyOutput:
|
|
|
190
194
|
lang: Language for syntax highlighting
|
|
191
195
|
traceback: Whether to show traceback for errors
|
|
192
196
|
"""
|
|
193
|
-
|
|
197
|
+
|
|
194
198
|
|
|
195
199
|
# Define styles for different output types
|
|
196
200
|
styles = {
|
|
197
|
-
OutputType.SYSTEM: RichStyle(
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
OutputType.
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
OutputType.
|
|
201
|
+
OutputType.SYSTEM: RichStyle(
|
|
202
|
+
color="bright_cyan",
|
|
203
|
+
italic=True,
|
|
204
|
+
bold=True,
|
|
205
|
+
),
|
|
206
|
+
OutputType.CODE: RichStyle(
|
|
207
|
+
color="green",
|
|
208
|
+
italic=True,
|
|
209
|
+
bgcolor="#1a1a1a",
|
|
210
|
+
frame=True
|
|
211
|
+
),
|
|
212
|
+
OutputType.RESULT: RichStyle(
|
|
213
|
+
color="bright_blue",
|
|
214
|
+
bold=True,
|
|
215
|
+
italic=True,
|
|
216
|
+
bgcolor="navy_blue"
|
|
217
|
+
),
|
|
218
|
+
OutputType.ERROR: RichStyle(
|
|
219
|
+
color="red",
|
|
220
|
+
bold=True,
|
|
221
|
+
italic=True,
|
|
222
|
+
blink=True,
|
|
223
|
+
bgcolor="dark_red",
|
|
224
|
+
),
|
|
225
|
+
OutputType.INFO: RichStyle(
|
|
226
|
+
color="gold1",
|
|
227
|
+
dim=True,
|
|
228
|
+
bgcolor="grey11",
|
|
229
|
+
italic=True
|
|
230
|
+
),
|
|
231
|
+
OutputType.PLANNING: RichStyle(
|
|
232
|
+
color="purple",
|
|
233
|
+
italic=True,
|
|
234
|
+
bold=True,
|
|
235
|
+
),
|
|
236
|
+
OutputType.PROGRESS: RichStyle(
|
|
237
|
+
color="white",
|
|
238
|
+
encircle=True,
|
|
239
|
+
italic=True,
|
|
240
|
+
),
|
|
241
|
+
OutputType.SUCCESS: RichStyle(
|
|
242
|
+
color="bright_green",
|
|
243
|
+
bold=True,
|
|
244
|
+
strike=False,
|
|
245
|
+
meta={"icon": "✓"},
|
|
246
|
+
italic=True
|
|
247
|
+
),
|
|
248
|
+
OutputType.WARNING: RichStyle(
|
|
249
|
+
color="yellow",
|
|
250
|
+
bold=True,
|
|
251
|
+
blink2=True,
|
|
252
|
+
bgcolor="dark_orange",
|
|
253
|
+
italic=True
|
|
254
|
+
),
|
|
255
|
+
OutputType.DEBUG: RichStyle(
|
|
256
|
+
color="grey58",
|
|
257
|
+
dim=True,
|
|
258
|
+
italic=True,
|
|
259
|
+
conceal=True
|
|
260
|
+
),
|
|
261
|
+
OutputType.USER: RichStyle(
|
|
262
|
+
color="spring_green2",
|
|
263
|
+
reverse=True,
|
|
264
|
+
frame=True,
|
|
265
|
+
italic=True
|
|
266
|
+
),
|
|
267
|
+
OutputType.TOOL: RichStyle(
|
|
268
|
+
color="dark_sea_green4",
|
|
269
|
+
italic=True,
|
|
270
|
+
bgcolor="grey19",
|
|
271
|
+
)
|
|
209
272
|
}
|
|
210
273
|
|
|
211
274
|
# Get formatted header
|
|
212
275
|
lang = lang if lang is not None else PrettyOutput._detect_language(text, default_lang='markdown')
|
|
213
|
-
header = PrettyOutput._format(
|
|
276
|
+
header = PrettyOutput._format(output_type, timestamp)
|
|
214
277
|
|
|
215
278
|
# Create syntax highlighted content
|
|
216
279
|
content = Syntax(
|
|
@@ -218,7 +281,6 @@ class PrettyOutput:
|
|
|
218
281
|
lang,
|
|
219
282
|
theme="monokai",
|
|
220
283
|
word_wrap=True,
|
|
221
|
-
background_color="default"
|
|
222
284
|
)
|
|
223
285
|
|
|
224
286
|
# Create panel with styling
|
|
@@ -229,7 +291,8 @@ class PrettyOutput:
|
|
|
229
291
|
title=header,
|
|
230
292
|
title_align="left",
|
|
231
293
|
padding=(0, 0),
|
|
232
|
-
highlight=True
|
|
294
|
+
highlight=True,
|
|
295
|
+
box=HEAVY,
|
|
233
296
|
)
|
|
234
297
|
|
|
235
298
|
# Print panel
|
|
@@ -253,12 +316,22 @@ class PrettyOutput:
|
|
|
253
316
|
@staticmethod
|
|
254
317
|
def print_stream(text: str):
|
|
255
318
|
"""Print stream output without line break"""
|
|
256
|
-
|
|
319
|
+
# 使用进度类型样式
|
|
320
|
+
style = PrettyOutput._get_style(OutputType.SYSTEM)
|
|
321
|
+
console.print(text, style=style, end="")
|
|
257
322
|
|
|
258
323
|
@staticmethod
|
|
259
324
|
def print_stream_end():
|
|
260
325
|
"""End stream output with line break"""
|
|
261
|
-
|
|
326
|
+
# 结束符样式
|
|
327
|
+
end_style = PrettyOutput._get_style(OutputType.SUCCESS)
|
|
328
|
+
console.print("\n", style=end_style)
|
|
329
|
+
console.file.flush()
|
|
330
|
+
|
|
331
|
+
@staticmethod
|
|
332
|
+
def _get_style(output_type: OutputType) -> RichStyle:
|
|
333
|
+
"""Get pre-defined RichStyle for output type"""
|
|
334
|
+
return console.get_style(output_type.value)
|
|
262
335
|
|
|
263
336
|
def get_single_line_input(tip: str) -> str:
|
|
264
337
|
"""Get single line input, support direction key, history function, etc."""
|