jarvis-ai-assistant 0.1.138__py3-none-any.whl → 0.1.141__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 jarvis-ai-assistant might be problematic. Click here for more details.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +62 -14
- jarvis/jarvis_agent/builtin_input_handler.py +4 -14
- jarvis/jarvis_agent/main.py +1 -1
- jarvis/jarvis_agent/patch.py +37 -40
- jarvis/jarvis_agent/shell_input_handler.py +2 -3
- jarvis/jarvis_code_agent/code_agent.py +23 -30
- jarvis/jarvis_code_analysis/checklists/__init__.py +3 -0
- jarvis/jarvis_code_analysis/checklists/c_cpp.py +50 -0
- jarvis/jarvis_code_analysis/checklists/csharp.py +75 -0
- jarvis/jarvis_code_analysis/checklists/data_format.py +82 -0
- jarvis/jarvis_code_analysis/checklists/devops.py +107 -0
- jarvis/jarvis_code_analysis/checklists/docs.py +87 -0
- jarvis/jarvis_code_analysis/checklists/go.py +52 -0
- jarvis/jarvis_code_analysis/checklists/infrastructure.py +98 -0
- jarvis/jarvis_code_analysis/checklists/java.py +66 -0
- jarvis/jarvis_code_analysis/checklists/javascript.py +73 -0
- jarvis/jarvis_code_analysis/checklists/kotlin.py +107 -0
- jarvis/jarvis_code_analysis/checklists/loader.py +76 -0
- jarvis/jarvis_code_analysis/checklists/php.py +77 -0
- jarvis/jarvis_code_analysis/checklists/python.py +56 -0
- jarvis/jarvis_code_analysis/checklists/ruby.py +107 -0
- jarvis/jarvis_code_analysis/checklists/rust.py +58 -0
- jarvis/jarvis_code_analysis/checklists/shell.py +75 -0
- jarvis/jarvis_code_analysis/checklists/sql.py +72 -0
- jarvis/jarvis_code_analysis/checklists/swift.py +77 -0
- jarvis/jarvis_code_analysis/checklists/web.py +97 -0
- jarvis/jarvis_code_analysis/code_review.py +660 -0
- jarvis/jarvis_dev/main.py +61 -88
- jarvis/jarvis_git_squash/main.py +3 -3
- jarvis/jarvis_git_utils/git_commiter.py +242 -0
- jarvis/jarvis_init/main.py +62 -0
- jarvis/jarvis_platform/base.py +4 -0
- jarvis/jarvis_platform/kimi.py +173 -5
- jarvis/jarvis_platform/openai.py +3 -0
- jarvis/jarvis_platform/registry.py +1 -0
- jarvis/jarvis_platform/yuanbao.py +275 -5
- jarvis/jarvis_tools/ask_codebase.py +6 -9
- jarvis/jarvis_tools/ask_user.py +17 -5
- jarvis/jarvis_tools/base.py +3 -1
- jarvis/jarvis_tools/chdir.py +1 -0
- jarvis/jarvis_tools/create_code_agent.py +4 -3
- jarvis/jarvis_tools/create_sub_agent.py +1 -0
- jarvis/jarvis_tools/execute_script.py +170 -0
- jarvis/jarvis_tools/file_analyzer.py +90 -239
- jarvis/jarvis_tools/file_operation.py +99 -31
- jarvis/jarvis_tools/{find_methodolopy.py → find_methodology.py} +2 -1
- jarvis/jarvis_tools/lsp_get_diagnostics.py +2 -0
- jarvis/jarvis_tools/methodology.py +11 -11
- jarvis/jarvis_tools/read_code.py +2 -0
- jarvis/jarvis_tools/read_webpage.py +33 -196
- jarvis/jarvis_tools/registry.py +68 -131
- jarvis/jarvis_tools/search_web.py +14 -6
- jarvis/jarvis_tools/virtual_tty.py +399 -0
- jarvis/jarvis_utils/config.py +29 -3
- jarvis/jarvis_utils/embedding.py +0 -317
- jarvis/jarvis_utils/file_processors.py +343 -0
- jarvis/jarvis_utils/input.py +0 -1
- jarvis/jarvis_utils/methodology.py +94 -435
- jarvis/jarvis_utils/utils.py +207 -9
- {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/METADATA +4 -4
- jarvis_ai_assistant-0.1.141.dist-info/RECORD +94 -0
- {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/entry_points.txt +4 -4
- jarvis/jarvis_code_agent/file_select.py +0 -202
- jarvis/jarvis_platform/ai8.py +0 -268
- jarvis/jarvis_platform/ollama.py +0 -137
- jarvis/jarvis_platform/oyi.py +0 -307
- jarvis/jarvis_rag/file_processors.py +0 -138
- jarvis/jarvis_rag/main.py +0 -1734
- jarvis/jarvis_tools/code_review.py +0 -333
- jarvis/jarvis_tools/execute_python_script.py +0 -58
- jarvis/jarvis_tools/execute_shell.py +0 -97
- jarvis/jarvis_tools/execute_shell_script.py +0 -58
- jarvis/jarvis_tools/find_caller.py +0 -278
- jarvis/jarvis_tools/find_symbol.py +0 -295
- jarvis/jarvis_tools/function_analyzer.py +0 -331
- jarvis/jarvis_tools/git_commiter.py +0 -167
- jarvis/jarvis_tools/project_analyzer.py +0 -304
- jarvis/jarvis_tools/rag.py +0 -143
- jarvis/jarvis_tools/tool_generator.py +0 -221
- jarvis_ai_assistant-0.1.138.dist-info/RECORD +0 -85
- /jarvis/{jarvis_rag → jarvis_init}/__init__.py +0 -0
- {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/top_level.txt +0 -0
jarvis/jarvis_tools/registry.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import os
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
import re
|
|
4
5
|
import sys
|
|
6
|
+
import tempfile
|
|
5
7
|
from typing import Any, Callable, Dict, List, Optional, Tuple
|
|
6
8
|
|
|
7
9
|
import yaml
|
|
@@ -10,7 +12,7 @@ from yaspin import yaspin
|
|
|
10
12
|
from jarvis.jarvis_agent.output_handler import OutputHandler
|
|
11
13
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
12
14
|
from jarvis.jarvis_tools.base import Tool
|
|
13
|
-
from jarvis.jarvis_utils.config import
|
|
15
|
+
from jarvis.jarvis_utils.config import get_max_input_token_count
|
|
14
16
|
from jarvis.jarvis_utils.embedding import get_context_token_count
|
|
15
17
|
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
16
18
|
from jarvis.jarvis_utils.utils import ct, ot, init_env
|
|
@@ -23,6 +25,7 @@ tool_call_help = f"""
|
|
|
23
25
|
|
|
24
26
|
# 📋 工具调用格式
|
|
25
27
|
{ot("TOOL_CALL")}
|
|
28
|
+
want: 想要从执行结果中获取到的信息,如果工具输出内容过长,会根据此字段尝试提取有效信息
|
|
26
29
|
name: 工具名称
|
|
27
30
|
arguments:
|
|
28
31
|
param1: 值1
|
|
@@ -55,9 +58,11 @@ arguments:
|
|
|
55
58
|
始终使用 | 语法表示字符串参数:
|
|
56
59
|
|
|
57
60
|
{ot("TOOL_CALL")}
|
|
58
|
-
|
|
61
|
+
want: 当前的git状态,期望获取xxx的提交记录
|
|
62
|
+
name: execute_script
|
|
59
63
|
arguments:
|
|
60
|
-
|
|
64
|
+
interpreter: bash
|
|
65
|
+
script_cotent: |
|
|
61
66
|
git status --porcelain
|
|
62
67
|
{ct("TOOL_CALL")}
|
|
63
68
|
|
|
@@ -82,9 +87,7 @@ class ToolRegistry(OutputHandler):
|
|
|
82
87
|
return "TOOL_CALL"
|
|
83
88
|
|
|
84
89
|
def can_handle(self, response: str) -> bool:
|
|
85
|
-
|
|
86
|
-
return True
|
|
87
|
-
return False
|
|
90
|
+
return ToolRegistry._has_tool_calls_block(response)
|
|
88
91
|
|
|
89
92
|
def prompt(self) -> str:
|
|
90
93
|
"""加载工具"""
|
|
@@ -119,13 +122,9 @@ class ToolRegistry(OutputHandler):
|
|
|
119
122
|
return ""
|
|
120
123
|
|
|
121
124
|
def handle(self, response: str, agent: Any) -> Tuple[bool, Any]:
|
|
122
|
-
|
|
123
|
-
if
|
|
124
|
-
|
|
125
|
-
return False, f"调用失败:请一次只处理一个工具调用。"
|
|
126
|
-
if len(tool_calls) == 0:
|
|
127
|
-
return False, ""
|
|
128
|
-
tool_call = tool_calls[0]
|
|
125
|
+
tool_call, err_msg = self._extract_tool_calls(response)
|
|
126
|
+
if err_msg:
|
|
127
|
+
return False, err_msg
|
|
129
128
|
return False, self.handle_tool_calls(tool_call, agent)
|
|
130
129
|
|
|
131
130
|
def __init__(self):
|
|
@@ -134,8 +133,7 @@ class ToolRegistry(OutputHandler):
|
|
|
134
133
|
# 加载内置工具和外部工具
|
|
135
134
|
self._load_builtin_tools()
|
|
136
135
|
self._load_external_tools()
|
|
137
|
-
|
|
138
|
-
self.max_token_count = int(get_max_token_count() * 0.8)
|
|
136
|
+
self.max_input_token_count = get_max_input_token_count() - 2048
|
|
139
137
|
|
|
140
138
|
def use_tools(self, name: List[str]):
|
|
141
139
|
"""使用指定工具"""
|
|
@@ -239,8 +237,14 @@ class ToolRegistry(OutputHandler):
|
|
|
239
237
|
except Exception as e:
|
|
240
238
|
PrettyOutput.print(f"从 {Path(file_path).name} 加载工具失败: {str(e)}", OutputType.ERROR)
|
|
241
239
|
return False
|
|
240
|
+
|
|
242
241
|
@staticmethod
|
|
243
|
-
def
|
|
242
|
+
def _has_tool_calls_block(content: str) -> bool:
|
|
243
|
+
"""从内容中提取工具调用块"""
|
|
244
|
+
return re.search(ot("TOOL_CALL")+r'(.*?)'+ct("TOOL_CALL"), content, re.DOTALL) is not None
|
|
245
|
+
|
|
246
|
+
@staticmethod
|
|
247
|
+
def _extract_tool_calls(content: str) -> Tuple[Dict, str]:
|
|
244
248
|
"""从内容中提取工具调用。
|
|
245
249
|
|
|
246
250
|
参数:
|
|
@@ -258,11 +262,19 @@ class ToolRegistry(OutputHandler):
|
|
|
258
262
|
for item in data:
|
|
259
263
|
try:
|
|
260
264
|
msg = yaml.safe_load(item)
|
|
261
|
-
if 'name' in msg and 'arguments' in msg:
|
|
265
|
+
if 'name' in msg and 'arguments' in msg and 'want' in msg:
|
|
262
266
|
ret.append(msg)
|
|
267
|
+
else:
|
|
268
|
+
return {}, f"""工具调用格式错误,请检查工具调用格式。
|
|
269
|
+
|
|
270
|
+
{tool_call_help}"""
|
|
263
271
|
except Exception as e:
|
|
264
|
-
|
|
265
|
-
|
|
272
|
+
return {}, f"""工具调用格式错误,请检查工具调用格式。
|
|
273
|
+
|
|
274
|
+
{tool_call_help}"""
|
|
275
|
+
if len(ret) > 1:
|
|
276
|
+
return {}, "检测到多个工具调用,请一次只处理一个工具调用。"
|
|
277
|
+
return ret[0] if ret else {}, ""
|
|
266
278
|
|
|
267
279
|
def register_tool(self, name: str, description: str, parameters: Dict, func: Callable):
|
|
268
280
|
"""注册新工具"""
|
|
@@ -283,74 +295,32 @@ class ToolRegistry(OutputHandler):
|
|
|
283
295
|
return {"success": False, "stderr": f"工具 {name} 不存在,可用的工具有: {', '.join(self.tools.keys())}", "stdout": ""}
|
|
284
296
|
return tool.execute(arguments)
|
|
285
297
|
|
|
298
|
+
def _format_tool_output(self, stdout: str, stderr: str) -> str:
|
|
299
|
+
"""格式化工具输出为可读字符串
|
|
300
|
+
|
|
301
|
+
Args:
|
|
302
|
+
stdout: 标准输出
|
|
303
|
+
stderr: 标准错误
|
|
304
|
+
|
|
305
|
+
Returns:
|
|
306
|
+
str: 格式化后的输出
|
|
307
|
+
"""
|
|
308
|
+
output_parts = []
|
|
309
|
+
if stdout:
|
|
310
|
+
output_parts.append(f"输出:\n{stdout}")
|
|
311
|
+
if stderr:
|
|
312
|
+
output_parts.append(f"错误:\n{stderr}")
|
|
313
|
+
output = "\n\n".join(output_parts)
|
|
314
|
+
return "无输出和错误" if not output else output
|
|
315
|
+
|
|
316
|
+
|
|
286
317
|
def handle_tool_calls(self, tool_call: Dict, agent: Any) -> str:
|
|
287
|
-
"""处理工具调用,只处理第一个工具"""
|
|
288
318
|
try:
|
|
289
|
-
# 只处理第一个工具调用
|
|
290
319
|
name = tool_call["name"]
|
|
291
320
|
args = tool_call["arguments"]
|
|
321
|
+
want = tool_call["want"]
|
|
292
322
|
args["agent"] = agent
|
|
293
323
|
|
|
294
|
-
tool_call_help = f"""
|
|
295
|
-
# 🛠️ 工具使用系统
|
|
296
|
-
您正在使用一个需要精确格式和严格规则的工具执行系统。
|
|
297
|
-
|
|
298
|
-
# 📋 工具调用格式
|
|
299
|
-
|
|
300
|
-
{ot("TOOL_CALL")}
|
|
301
|
-
name: 工具名称
|
|
302
|
-
arguments:
|
|
303
|
-
param1: 值1
|
|
304
|
-
param2: 值2
|
|
305
|
-
{ct("TOOL_CALL")}
|
|
306
|
-
|
|
307
|
-
# ❗ 关键规则
|
|
308
|
-
1. 每次只使用一个工具
|
|
309
|
-
- 一次只执行一个工具
|
|
310
|
-
- 等待结果后再进行下一步
|
|
311
|
-
|
|
312
|
-
2. 严格遵守格式
|
|
313
|
-
- 完全按照上述格式
|
|
314
|
-
- 使用正确的YAML缩进
|
|
315
|
-
- 包含所有必需参数
|
|
316
|
-
|
|
317
|
-
3. 结果处理
|
|
318
|
-
- 等待执行结果
|
|
319
|
-
- 不要假设结果
|
|
320
|
-
- 不要创建虚假响应
|
|
321
|
-
- 不要想象对话
|
|
322
|
-
|
|
323
|
-
4. 信息管理
|
|
324
|
-
- 如果信息不足,询问用户
|
|
325
|
-
- 跳过不必要的步骤
|
|
326
|
-
- 如果卡住,请求指导
|
|
327
|
-
- 不要在没有完整信息的情况下继续
|
|
328
|
-
|
|
329
|
-
# 📝 字符串参数格式
|
|
330
|
-
始终使用 | 语法表示字符串参数:
|
|
331
|
-
|
|
332
|
-
{ot("TOOL_CALL")}
|
|
333
|
-
name: execute_shell
|
|
334
|
-
arguments:
|
|
335
|
-
command: |
|
|
336
|
-
git status --porcelain
|
|
337
|
-
{ct("TOOL_CALL")}
|
|
338
|
-
|
|
339
|
-
# 💡 最佳实践
|
|
340
|
-
- 准备好后立即开始执行
|
|
341
|
-
- 无需请求许可即可开始
|
|
342
|
-
- 使用正确的字符串格式
|
|
343
|
-
- 监控进度并调整
|
|
344
|
-
- 遇到困难时请求帮助
|
|
345
|
-
|
|
346
|
-
# ⚠️ 常见错误
|
|
347
|
-
- 同时调用多个工具
|
|
348
|
-
- 字符串参数缺少 |
|
|
349
|
-
- 假设工具结果
|
|
350
|
-
- 创建虚构对话
|
|
351
|
-
- 在没有所需信息的情况下继续
|
|
352
|
-
"""
|
|
353
|
-
|
|
354
324
|
if isinstance(args, str):
|
|
355
325
|
try:
|
|
356
326
|
args = json.loads(args)
|
|
@@ -358,58 +328,25 @@ arguments:
|
|
|
358
328
|
PrettyOutput.print(f"工具参数格式无效: {name} {tool_call_help}", OutputType.ERROR)
|
|
359
329
|
return ""
|
|
360
330
|
|
|
361
|
-
#
|
|
331
|
+
# 执行工具调用
|
|
362
332
|
result = self.execute_tool(name, args)
|
|
363
333
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
model = PlatformRegistry.get_global_platform_registry().get_normal_platform()
|
|
382
|
-
model.set_suppress_output(False)
|
|
383
|
-
# If the output exceeds the maximum context length, only take the last part
|
|
384
|
-
max_count = self.max_token_count
|
|
385
|
-
if get_context_token_count(output) > max_count:
|
|
386
|
-
output_to_summarize = output[-max_count:]
|
|
387
|
-
truncation_notice = f"\n(注意:由于输出过长,仅总结最后 {max_count} 个字符)"
|
|
388
|
-
else:
|
|
389
|
-
output_to_summarize = output
|
|
390
|
-
truncation_notice = ""
|
|
391
|
-
|
|
392
|
-
prompt = f"""请总结以下工具的执行结果,提取关键信息和重要结果。注意:
|
|
393
|
-
1. 保留所有重要的数值、路径、错误信息等
|
|
394
|
-
2. 保持结果的准确性
|
|
395
|
-
3. 用简洁的语言描述主要内容
|
|
396
|
-
4. 如果有错误信息,确保包含在总结中
|
|
397
|
-
|
|
398
|
-
工具名称: {name}
|
|
399
|
-
执行结果:
|
|
400
|
-
{output_to_summarize}
|
|
401
|
-
|
|
402
|
-
请提供总结:"""
|
|
403
|
-
|
|
404
|
-
summary = model.chat_until_success(prompt)
|
|
405
|
-
output = f"""--- 原始输出过长,以下是总结 ---{truncation_notice}
|
|
406
|
-
|
|
407
|
-
{summary}
|
|
408
|
-
|
|
409
|
-
--- 总结结束 ---"""
|
|
410
|
-
except Exception as e:
|
|
411
|
-
PrettyOutput.print(f"总结失败: {str(e)}", OutputType.ERROR)
|
|
412
|
-
output = f"输出过长 ({len(output)} 字符),建议查看原始输出。\n前300字符预览:\n{output[:300]}..."
|
|
334
|
+
# 格式化输出
|
|
335
|
+
output = self._format_tool_output(result["stdout"], result.get("stderr", ""))
|
|
336
|
+
|
|
337
|
+
# 处理结果
|
|
338
|
+
if get_context_token_count(output) > self.max_input_token_count:
|
|
339
|
+
output_file = os.path.join(tempfile.gettempdir(), f"jarvis_output_{os.getpid()}.txt")
|
|
340
|
+
with open(output_file, "w", encoding="utf-8") as f:
|
|
341
|
+
f.write(output)
|
|
342
|
+
model = PlatformRegistry().get_normal_platform()
|
|
343
|
+
model.set_suppress_output(False)
|
|
344
|
+
model.upload_files([output_file])
|
|
345
|
+
prompt = f"该文件为工具执行结果,请阅读文件内容,并根据文件提取出以下信息:{want}"
|
|
346
|
+
return f"""工具调用原始输出过长,以下是根据输出提出的信息:
|
|
347
|
+
|
|
348
|
+
{model.chat_until_success(prompt)}"""
|
|
349
|
+
|
|
413
350
|
return output
|
|
414
351
|
|
|
415
352
|
except Exception as e:
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
1
|
import os
|
|
5
2
|
import statistics
|
|
6
3
|
from typing import Any, Dict
|
|
@@ -10,6 +7,7 @@ from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
|
10
7
|
class SearchWebTool:
|
|
11
8
|
name = "search_web"
|
|
12
9
|
description = "搜索互联网上的信息"
|
|
10
|
+
labels = ['web', 'search', 'information']
|
|
13
11
|
parameters = {
|
|
14
12
|
"type": "object",
|
|
15
13
|
"properties": {
|
|
@@ -17,16 +15,26 @@ class SearchWebTool:
|
|
|
17
15
|
}
|
|
18
16
|
}
|
|
19
17
|
|
|
18
|
+
def __init__(self):
|
|
19
|
+
if os.getenv("YUANBAO_COOKIES", "") != "" and os.getenv("YUANBAO_AGENT_ID", "") != "":
|
|
20
|
+
self.platform = "yuanbao"
|
|
21
|
+
self.model = "deep_seek"
|
|
22
|
+
elif os.getenv("KIMI_API_KEY", "") != "":
|
|
23
|
+
self.platform = "kimi"
|
|
24
|
+
self.model = "k1"
|
|
25
|
+
else:
|
|
26
|
+
self.platform = ""
|
|
27
|
+
|
|
20
28
|
|
|
21
29
|
@staticmethod
|
|
22
30
|
def check() -> bool:
|
|
23
|
-
return os.getenv("YUANBAO_COOKIES", "") != "" and os.getenv("YUANBAO_AGENT_ID", "") != ""
|
|
31
|
+
return os.getenv("YUANBAO_COOKIES", "") != "" and os.getenv("YUANBAO_AGENT_ID", "") != "" or os.getenv("KIMI_API_KEY", "") != ""
|
|
24
32
|
|
|
25
33
|
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]: # type: ignore
|
|
26
34
|
query = args.get("query")
|
|
27
|
-
model = PlatformRegistry().create_platform(
|
|
35
|
+
model = PlatformRegistry().create_platform(self.platform)
|
|
28
36
|
model.set_suppress_output(False) # type: ignore
|
|
29
|
-
model.set_model_name(
|
|
37
|
+
model.set_model_name(self.model) # type: ignore
|
|
30
38
|
return {
|
|
31
39
|
"stdout": model.chat_until_success(query), # type: ignore
|
|
32
40
|
"stderr": "",
|