jarvis-ai-assistant 0.1.132__py3-none-any.whl → 0.1.138__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 (82) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +330 -347
  3. jarvis/jarvis_agent/builtin_input_handler.py +16 -6
  4. jarvis/jarvis_agent/file_input_handler.py +9 -9
  5. jarvis/jarvis_agent/jarvis.py +143 -0
  6. jarvis/jarvis_agent/main.py +12 -13
  7. jarvis/jarvis_agent/output_handler.py +3 -3
  8. jarvis/jarvis_agent/patch.py +92 -64
  9. jarvis/jarvis_agent/shell_input_handler.py +5 -3
  10. jarvis/jarvis_code_agent/code_agent.py +263 -177
  11. jarvis/jarvis_code_agent/file_select.py +24 -24
  12. jarvis/jarvis_dev/main.py +45 -59
  13. jarvis/jarvis_git_details/__init__.py +0 -0
  14. jarvis/jarvis_git_details/main.py +179 -0
  15. jarvis/jarvis_git_squash/main.py +7 -7
  16. jarvis/jarvis_lsp/base.py +11 -53
  17. jarvis/jarvis_lsp/cpp.py +13 -28
  18. jarvis/jarvis_lsp/go.py +13 -28
  19. jarvis/jarvis_lsp/python.py +8 -27
  20. jarvis/jarvis_lsp/registry.py +21 -83
  21. jarvis/jarvis_lsp/rust.py +15 -30
  22. jarvis/jarvis_methodology/main.py +101 -0
  23. jarvis/jarvis_multi_agent/__init__.py +10 -51
  24. jarvis/jarvis_multi_agent/main.py +43 -0
  25. jarvis/jarvis_platform/__init__.py +1 -1
  26. jarvis/jarvis_platform/ai8.py +67 -89
  27. jarvis/jarvis_platform/base.py +14 -13
  28. jarvis/jarvis_platform/kimi.py +25 -28
  29. jarvis/jarvis_platform/ollama.py +24 -26
  30. jarvis/jarvis_platform/openai.py +15 -19
  31. jarvis/jarvis_platform/oyi.py +48 -50
  32. jarvis/jarvis_platform/registry.py +29 -44
  33. jarvis/jarvis_platform/yuanbao.py +39 -43
  34. jarvis/jarvis_platform_manager/main.py +81 -81
  35. jarvis/jarvis_platform_manager/openai_test.py +21 -21
  36. jarvis/jarvis_rag/file_processors.py +18 -18
  37. jarvis/jarvis_rag/main.py +262 -278
  38. jarvis/jarvis_smart_shell/main.py +12 -12
  39. jarvis/jarvis_tools/ask_codebase.py +85 -78
  40. jarvis/jarvis_tools/ask_user.py +8 -8
  41. jarvis/jarvis_tools/base.py +4 -4
  42. jarvis/jarvis_tools/chdir.py +9 -9
  43. jarvis/jarvis_tools/code_review.py +40 -21
  44. jarvis/jarvis_tools/create_code_agent.py +15 -15
  45. jarvis/jarvis_tools/create_sub_agent.py +0 -1
  46. jarvis/jarvis_tools/execute_python_script.py +3 -3
  47. jarvis/jarvis_tools/execute_shell.py +11 -11
  48. jarvis/jarvis_tools/execute_shell_script.py +3 -3
  49. jarvis/jarvis_tools/file_analyzer.py +116 -105
  50. jarvis/jarvis_tools/file_operation.py +22 -20
  51. jarvis/jarvis_tools/find_caller.py +105 -40
  52. jarvis/jarvis_tools/find_methodolopy.py +65 -0
  53. jarvis/jarvis_tools/find_symbol.py +123 -39
  54. jarvis/jarvis_tools/function_analyzer.py +140 -57
  55. jarvis/jarvis_tools/git_commiter.py +10 -10
  56. jarvis/jarvis_tools/lsp_get_diagnostics.py +19 -19
  57. jarvis/jarvis_tools/methodology.py +22 -67
  58. jarvis/jarvis_tools/project_analyzer.py +137 -53
  59. jarvis/jarvis_tools/rag.py +15 -20
  60. jarvis/jarvis_tools/read_code.py +25 -23
  61. jarvis/jarvis_tools/read_webpage.py +31 -31
  62. jarvis/jarvis_tools/registry.py +72 -52
  63. jarvis/jarvis_tools/search_web.py +23 -353
  64. jarvis/jarvis_tools/tool_generator.py +19 -19
  65. jarvis/jarvis_utils/config.py +36 -96
  66. jarvis/jarvis_utils/embedding.py +83 -83
  67. jarvis/jarvis_utils/git_utils.py +20 -20
  68. jarvis/jarvis_utils/globals.py +18 -6
  69. jarvis/jarvis_utils/input.py +10 -9
  70. jarvis/jarvis_utils/methodology.py +141 -140
  71. jarvis/jarvis_utils/output.py +13 -13
  72. jarvis/jarvis_utils/utils.py +23 -71
  73. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/METADATA +6 -15
  74. jarvis_ai_assistant-0.1.138.dist-info/RECORD +85 -0
  75. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/entry_points.txt +4 -3
  76. jarvis/jarvis_tools/lsp_find_definition.py +0 -150
  77. jarvis/jarvis_tools/lsp_find_references.py +0 -127
  78. jarvis/jarvis_tools/select_code_files.py +0 -62
  79. jarvis_ai_assistant-0.1.132.dist-info/RECORD +0 -82
  80. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/LICENSE +0 -0
  81. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/WHEEL +0 -0
  82. {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/top_level.txt +0 -0
@@ -85,21 +85,40 @@ class ToolRegistry(OutputHandler):
85
85
  if self._extract_tool_calls(response):
86
86
  return True
87
87
  return False
88
-
88
+
89
89
  def prompt(self) -> str:
90
90
  """加载工具"""
91
91
  tools = self.get_all_tools()
92
92
  if tools:
93
93
  tools_prompt = "## 可用工具:\n"
94
94
  for tool in tools:
95
- tools_prompt += f"- 名称: {tool['name']}\n"
96
- tools_prompt += f" 描述: {tool['description']}\n"
97
- tools_prompt += f" 参数: {tool['parameters']}\n"
98
- tools_prompt += tool_call_help
95
+ try:
96
+ tools_prompt += f"- 名称: {tool['name']}\n"
97
+ tools_prompt += f" 描述: {tool['description']}\n"
98
+ tools_prompt += " 参数: |\n"
99
+
100
+ # 生成格式化的YAML参数
101
+ yaml_params = yaml.dump(
102
+ tool['parameters'],
103
+ allow_unicode=True,
104
+ indent=4,
105
+ sort_keys=False,
106
+ width=120 # 增加行宽限制
107
+ )
108
+
109
+ # 添加缩进并移除尾部空格
110
+ for line in yaml_params.split('\n'):
111
+ tools_prompt += f" {line.rstrip()}\n"
112
+
113
+ except yaml.YAMLError as e:
114
+ PrettyOutput.print(f"工具 {tool['name']} 参数序列化失败: {str(e)}", OutputType.ERROR)
115
+ continue
116
+
117
+ tools_prompt += tool_call_help.rstrip() # 移除帮助文本尾部空格
99
118
  return tools_prompt
100
119
  return ""
101
-
102
- def handle(self, response: str) -> Tuple[bool, Any]:
120
+
121
+ def handle(self, response: str, agent: Any) -> Tuple[bool, Any]:
103
122
  tool_calls = self._extract_tool_calls(response)
104
123
  if len(tool_calls) > 1:
105
124
  PrettyOutput.print(f"操作失败:检测到多个操作。一次只能执行一个操作。尝试执行的操作:{', '.join([tool_call['name'] for tool_call in tool_calls])}", OutputType.WARNING)
@@ -107,7 +126,7 @@ class ToolRegistry(OutputHandler):
107
126
  if len(tool_calls) == 0:
108
127
  return False, ""
109
128
  tool_call = tool_calls[0]
110
- return False, self.handle_tool_calls(tool_call)
129
+ return False, self.handle_tool_calls(tool_call, agent)
111
130
 
112
131
  def __init__(self):
113
132
  """初始化工具注册表"""
@@ -132,13 +151,13 @@ class ToolRegistry(OutputHandler):
132
151
  def _load_builtin_tools(self):
133
152
  """从内置工具目录加载工具"""
134
153
  tools_dir = Path(__file__).parent
135
-
154
+
136
155
  # 遍历目录中的所有.py文件
137
156
  for file_path in tools_dir.glob("*.py"):
138
157
  # 跳过base.py和__init__.py
139
158
  if file_path.name in ["base.py", "__init__.py", "registry.py"]:
140
159
  continue
141
-
160
+
142
161
  self.register_tool_by_file(str(file_path))
143
162
 
144
163
  def _load_external_tools(self):
@@ -146,21 +165,21 @@ class ToolRegistry(OutputHandler):
146
165
  external_tools_dir = Path.home() / '.jarvis/tools'
147
166
  if not external_tools_dir.exists():
148
167
  return
149
-
168
+
150
169
  # 遍历目录中的所有.py文件
151
170
  for file_path in external_tools_dir.glob("*.py"):
152
171
  # 跳过__init__.py
153
172
  if file_path.name == "__init__.py":
154
173
  continue
155
-
174
+
156
175
  self.register_tool_by_file(str(file_path))
157
176
 
158
177
  def register_tool_by_file(self, file_path: str):
159
178
  """从指定文件加载并注册工具
160
-
179
+
161
180
  参数:
162
181
  file_path: 工具文件的路径
163
-
182
+
164
183
  返回:
165
184
  bool: 工具是否加载成功
166
185
  """
@@ -169,35 +188,35 @@ class ToolRegistry(OutputHandler):
169
188
  if not p_file_path.exists() or not p_file_path.is_file():
170
189
  PrettyOutput.print(f"文件不存在: {p_file_path}", OutputType.ERROR)
171
190
  return False
172
-
191
+
173
192
  # 临时将父目录添加到sys.path
174
193
  parent_dir = str(p_file_path.parent)
175
194
  sys.path.insert(0, parent_dir)
176
-
195
+
177
196
  try:
178
197
  # 使用标准导入机制导入模块
179
198
  module_name = p_file_path.stem
180
199
  module = __import__(module_name)
181
-
200
+
182
201
  # 在模块中查找工具类
183
202
  tool_found = False
184
203
  for item_name in dir(module):
185
204
  item = getattr(module, item_name)
186
205
  # 检查是否是类并具有必要属性
187
- if (isinstance(item, type) and
188
- hasattr(item, 'name') and
189
- hasattr(item, 'description') and
206
+ if (isinstance(item, type) and
207
+ hasattr(item, 'name') and
208
+ hasattr(item, 'description') and
190
209
  hasattr(item, 'parameters') and
191
- hasattr(item, 'execute') and
210
+ hasattr(item, 'execute') and
192
211
  item.name == module_name):
193
212
 
194
213
  if hasattr(item, "check"):
195
214
  if not item.check():
196
215
  continue
197
-
216
+
198
217
  # 实例化工具类
199
218
  tool_instance = item()
200
-
219
+
201
220
  # 注册工具
202
221
  self.register_tool(
203
222
  name=tool_instance.name,
@@ -207,29 +226,29 @@ class ToolRegistry(OutputHandler):
207
226
  )
208
227
  tool_found = True
209
228
  break
210
-
229
+
211
230
  if not tool_found:
212
231
  return False
213
-
232
+
214
233
  return True
215
-
234
+
216
235
  finally:
217
236
  # 从sys.path中移除目录
218
237
  sys.path.remove(parent_dir)
219
-
238
+
220
239
  except Exception as e:
221
240
  PrettyOutput.print(f"从 {Path(file_path).name} 加载工具失败: {str(e)}", OutputType.ERROR)
222
241
  return False
223
242
  @staticmethod
224
243
  def _extract_tool_calls(content: str) -> List[Dict]:
225
244
  """从内容中提取工具调用。
226
-
245
+
227
246
  参数:
228
247
  content: 包含工具调用的内容
229
-
248
+
230
249
  返回:
231
250
  List[Dict]: 包含名称和参数的提取工具调用列表
232
-
251
+
233
252
  异常:
234
253
  Exception: 如果工具调用缺少必要字段
235
254
  """
@@ -264,12 +283,13 @@ class ToolRegistry(OutputHandler):
264
283
  return {"success": False, "stderr": f"工具 {name} 不存在,可用的工具有: {', '.join(self.tools.keys())}", "stdout": ""}
265
284
  return tool.execute(arguments)
266
285
 
267
- def handle_tool_calls(self, tool_call: Dict) -> str:
286
+ def handle_tool_calls(self, tool_call: Dict, agent: Any) -> str:
268
287
  """处理工具调用,只处理第一个工具"""
269
288
  try:
270
289
  # 只处理第一个工具调用
271
290
  name = tool_call["name"]
272
291
  args = tool_call["arguments"]
292
+ args["agent"] = agent
273
293
 
274
294
  tool_call_help = f"""
275
295
  # 🛠️ 工具使用系统
@@ -330,14 +350,14 @@ arguments:
330
350
  - 创建虚构对话
331
351
  - 在没有所需信息的情况下继续
332
352
  """
333
-
353
+
334
354
  if isinstance(args, str):
335
355
  try:
336
356
  args = json.loads(args)
337
357
  except json.JSONDecodeError:
338
358
  PrettyOutput.print(f"工具参数格式无效: {name} {tool_call_help}", OutputType.ERROR)
339
359
  return ""
340
-
360
+
341
361
  # Execute tool call
342
362
  result = self.execute_tool(name, args)
343
363
 
@@ -350,14 +370,14 @@ arguments:
350
370
  output_parts.append(f"错误:\n{stderr}")
351
371
  output = "\n\n".join(output_parts)
352
372
  output = "无输出和错误" if not output else output
353
-
373
+
354
374
  # Process the result
355
375
  if result["success"]:
356
376
  # If the output exceeds 4k characters, use a large model to summarize
357
377
  if get_context_token_count(output) > self.max_token_count:
358
378
  PrettyOutput.section("输出过长,正在总结...", OutputType.SYSTEM)
359
379
  try:
360
-
380
+
361
381
  model = PlatformRegistry.get_global_platform_registry().get_normal_platform()
362
382
  model.set_suppress_output(False)
363
383
  # If the output exceeds the maximum context length, only take the last part
@@ -391,7 +411,7 @@ arguments:
391
411
  PrettyOutput.print(f"总结失败: {str(e)}", OutputType.ERROR)
392
412
  output = f"输出过长 ({len(output)} 字符),建议查看原始输出。\n前300字符预览:\n{output[:300]}..."
393
413
  return output
394
-
414
+
395
415
  except Exception as e:
396
416
  PrettyOutput.print(f"工具执行失败:{str(e)}", OutputType.ERROR)
397
417
  return f"工具调用失败: {str(e)}"
@@ -419,13 +439,13 @@ def main():
419
439
  call_parser.add_argument('--args-file', type=str, help='从文件加载工具参数 (JSON格式)')
420
440
 
421
441
  args = parser.parse_args()
422
-
442
+
423
443
  # 初始化工具注册表
424
444
  registry = ToolRegistry()
425
-
445
+
426
446
  if args.command == 'list':
427
447
  tools = registry.get_all_tools()
428
-
448
+
429
449
  if args.json:
430
450
  if args.detailed:
431
451
  print(json.dumps(tools, indent=2, ensure_ascii=False))
@@ -445,17 +465,17 @@ def main():
445
465
  req_mark = "*" if param_name in required else ""
446
466
  desc = param_info.get('description', '无描述')
447
467
  print(f" - {param_name}{req_mark}: {desc}")
448
-
468
+
449
469
  elif args.command == 'call':
450
470
  tool_name = args.tool_name
451
471
  tool = registry.get_tool(tool_name)
452
-
472
+
453
473
  if not tool:
454
474
  PrettyOutput.print(f"错误: 工具 '{tool_name}' 不存在", OutputType.ERROR)
455
475
  available_tools = ", ".join([t["name"] for t in registry.get_all_tools()])
456
476
  print(f"可用工具: {available_tools}")
457
477
  return 1
458
-
478
+
459
479
  # 获取参数
460
480
  tool_args = {}
461
481
  if args.args:
@@ -464,7 +484,7 @@ def main():
464
484
  except json.JSONDecodeError:
465
485
  PrettyOutput.print("错误: 参数必须是有效的JSON格式", OutputType.ERROR)
466
486
  return 1
467
-
487
+
468
488
  elif args.args_file:
469
489
  try:
470
490
  with open(args.args_file, 'r', encoding='utf-8') as f:
@@ -472,11 +492,11 @@ def main():
472
492
  except (json.JSONDecodeError, FileNotFoundError) as e:
473
493
  PrettyOutput.print(f"错误: 无法从文件加载参数: {str(e)}", OutputType.ERROR)
474
494
  return 1
475
-
495
+
476
496
  # 检查必需参数
477
497
  required_params = tool.parameters.get('required', [])
478
498
  missing_params = [p for p in required_params if p not in tool_args]
479
-
499
+
480
500
  if missing_params:
481
501
  PrettyOutput.print(f"错误: 缺少必需参数: {', '.join(missing_params)}", OutputType.ERROR)
482
502
  print("\n参数说明:")
@@ -486,30 +506,30 @@ def main():
486
506
  desc = param_info.get('description', '无描述')
487
507
  print(f" - {param_name}: {desc}")
488
508
  return 1
489
-
509
+
490
510
  # 执行工具
491
511
  with yaspin(text=f"正在执行工具 {tool_name}...").dots12:
492
512
  result = registry.execute_tool(tool_name, tool_args)
493
-
513
+
494
514
  # 显示结果
495
515
  if result["success"]:
496
516
  PrettyOutput.section(f"工具 {tool_name} 执行成功", OutputType.SUCCESS)
497
517
  else:
498
518
  PrettyOutput.section(f"工具 {tool_name} 执行失败", OutputType.ERROR)
499
-
519
+
500
520
  if result.get("stdout"):
501
521
  print("\n输出:")
502
522
  print(result["stdout"])
503
-
523
+
504
524
  if result.get("stderr"):
505
525
  PrettyOutput.print("\n错误:", OutputType.ERROR)
506
526
  print(result["stderr"])
507
-
527
+
508
528
  return 0 if result["success"] else 1
509
-
529
+
510
530
  else:
511
531
  parser.print_help()
512
-
532
+
513
533
  return 0
514
534
 
515
535