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.

Files changed (85) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +62 -14
  3. jarvis/jarvis_agent/builtin_input_handler.py +4 -14
  4. jarvis/jarvis_agent/main.py +1 -1
  5. jarvis/jarvis_agent/patch.py +37 -40
  6. jarvis/jarvis_agent/shell_input_handler.py +2 -3
  7. jarvis/jarvis_code_agent/code_agent.py +23 -30
  8. jarvis/jarvis_code_analysis/checklists/__init__.py +3 -0
  9. jarvis/jarvis_code_analysis/checklists/c_cpp.py +50 -0
  10. jarvis/jarvis_code_analysis/checklists/csharp.py +75 -0
  11. jarvis/jarvis_code_analysis/checklists/data_format.py +82 -0
  12. jarvis/jarvis_code_analysis/checklists/devops.py +107 -0
  13. jarvis/jarvis_code_analysis/checklists/docs.py +87 -0
  14. jarvis/jarvis_code_analysis/checklists/go.py +52 -0
  15. jarvis/jarvis_code_analysis/checklists/infrastructure.py +98 -0
  16. jarvis/jarvis_code_analysis/checklists/java.py +66 -0
  17. jarvis/jarvis_code_analysis/checklists/javascript.py +73 -0
  18. jarvis/jarvis_code_analysis/checklists/kotlin.py +107 -0
  19. jarvis/jarvis_code_analysis/checklists/loader.py +76 -0
  20. jarvis/jarvis_code_analysis/checklists/php.py +77 -0
  21. jarvis/jarvis_code_analysis/checklists/python.py +56 -0
  22. jarvis/jarvis_code_analysis/checklists/ruby.py +107 -0
  23. jarvis/jarvis_code_analysis/checklists/rust.py +58 -0
  24. jarvis/jarvis_code_analysis/checklists/shell.py +75 -0
  25. jarvis/jarvis_code_analysis/checklists/sql.py +72 -0
  26. jarvis/jarvis_code_analysis/checklists/swift.py +77 -0
  27. jarvis/jarvis_code_analysis/checklists/web.py +97 -0
  28. jarvis/jarvis_code_analysis/code_review.py +660 -0
  29. jarvis/jarvis_dev/main.py +61 -88
  30. jarvis/jarvis_git_squash/main.py +3 -3
  31. jarvis/jarvis_git_utils/git_commiter.py +242 -0
  32. jarvis/jarvis_init/main.py +62 -0
  33. jarvis/jarvis_platform/base.py +4 -0
  34. jarvis/jarvis_platform/kimi.py +173 -5
  35. jarvis/jarvis_platform/openai.py +3 -0
  36. jarvis/jarvis_platform/registry.py +1 -0
  37. jarvis/jarvis_platform/yuanbao.py +275 -5
  38. jarvis/jarvis_tools/ask_codebase.py +6 -9
  39. jarvis/jarvis_tools/ask_user.py +17 -5
  40. jarvis/jarvis_tools/base.py +3 -1
  41. jarvis/jarvis_tools/chdir.py +1 -0
  42. jarvis/jarvis_tools/create_code_agent.py +4 -3
  43. jarvis/jarvis_tools/create_sub_agent.py +1 -0
  44. jarvis/jarvis_tools/execute_script.py +170 -0
  45. jarvis/jarvis_tools/file_analyzer.py +90 -239
  46. jarvis/jarvis_tools/file_operation.py +99 -31
  47. jarvis/jarvis_tools/{find_methodolopy.py → find_methodology.py} +2 -1
  48. jarvis/jarvis_tools/lsp_get_diagnostics.py +2 -0
  49. jarvis/jarvis_tools/methodology.py +11 -11
  50. jarvis/jarvis_tools/read_code.py +2 -0
  51. jarvis/jarvis_tools/read_webpage.py +33 -196
  52. jarvis/jarvis_tools/registry.py +68 -131
  53. jarvis/jarvis_tools/search_web.py +14 -6
  54. jarvis/jarvis_tools/virtual_tty.py +399 -0
  55. jarvis/jarvis_utils/config.py +29 -3
  56. jarvis/jarvis_utils/embedding.py +0 -317
  57. jarvis/jarvis_utils/file_processors.py +343 -0
  58. jarvis/jarvis_utils/input.py +0 -1
  59. jarvis/jarvis_utils/methodology.py +94 -435
  60. jarvis/jarvis_utils/utils.py +207 -9
  61. {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/METADATA +4 -4
  62. jarvis_ai_assistant-0.1.141.dist-info/RECORD +94 -0
  63. {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/entry_points.txt +4 -4
  64. jarvis/jarvis_code_agent/file_select.py +0 -202
  65. jarvis/jarvis_platform/ai8.py +0 -268
  66. jarvis/jarvis_platform/ollama.py +0 -137
  67. jarvis/jarvis_platform/oyi.py +0 -307
  68. jarvis/jarvis_rag/file_processors.py +0 -138
  69. jarvis/jarvis_rag/main.py +0 -1734
  70. jarvis/jarvis_tools/code_review.py +0 -333
  71. jarvis/jarvis_tools/execute_python_script.py +0 -58
  72. jarvis/jarvis_tools/execute_shell.py +0 -97
  73. jarvis/jarvis_tools/execute_shell_script.py +0 -58
  74. jarvis/jarvis_tools/find_caller.py +0 -278
  75. jarvis/jarvis_tools/find_symbol.py +0 -295
  76. jarvis/jarvis_tools/function_analyzer.py +0 -331
  77. jarvis/jarvis_tools/git_commiter.py +0 -167
  78. jarvis/jarvis_tools/project_analyzer.py +0 -304
  79. jarvis/jarvis_tools/rag.py +0 -143
  80. jarvis/jarvis_tools/tool_generator.py +0 -221
  81. jarvis_ai_assistant-0.1.138.dist-info/RECORD +0 -85
  82. /jarvis/{jarvis_rag → jarvis_init}/__init__.py +0 -0
  83. {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/LICENSE +0 -0
  84. {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/WHEEL +0 -0
  85. {jarvis_ai_assistant-0.1.138.dist-info → jarvis_ai_assistant-0.1.141.dist-info}/top_level.txt +0 -0
@@ -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 get_max_token_count
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
- name: execute_shell
61
+ want: 当前的git状态,期望获取xxx的提交记录
62
+ name: execute_script
59
63
  arguments:
60
- command: |
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
- if self._extract_tool_calls(response):
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
- tool_calls = self._extract_tool_calls(response)
123
- if len(tool_calls) > 1:
124
- PrettyOutput.print(f"操作失败:检测到多个操作。一次只能执行一个操作。尝试执行的操作:{', '.join([tool_call['name'] for tool_call in tool_calls])}", OutputType.WARNING)
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
- # 确保max_token_count是整数
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 _extract_tool_calls(content: str) -> List[Dict]:
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
- continue
265
- return ret
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
- # Execute tool call
331
+ # 执行工具调用
362
332
  result = self.execute_tool(name, args)
363
333
 
364
- stdout = result["stdout"]
365
- stderr = result.get("stderr", "")
366
- output_parts = []
367
- if stdout:
368
- output_parts.append(f"输出:\n{stdout}")
369
- if stderr:
370
- output_parts.append(f"错误:\n{stderr}")
371
- output = "\n\n".join(output_parts)
372
- output = "无输出和错误" if not output else output
373
-
374
- # Process the result
375
- if result["success"]:
376
- # If the output exceeds 4k characters, use a large model to summarize
377
- if get_context_token_count(output) > self.max_token_count:
378
- PrettyOutput.section("输出过长,正在总结...", OutputType.SYSTEM)
379
- try:
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("yuanbao")
35
+ model = PlatformRegistry().create_platform(self.platform)
28
36
  model.set_suppress_output(False) # type: ignore
29
- model.set_model_name("deep_seek") # type: ignore
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": "",