jarvis-ai-assistant 0.1.131__py3-none-any.whl → 0.1.134__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 (75) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +165 -285
  3. jarvis/jarvis_agent/jarvis.py +143 -0
  4. jarvis/jarvis_agent/main.py +0 -2
  5. jarvis/jarvis_agent/patch.py +70 -48
  6. jarvis/jarvis_agent/shell_input_handler.py +1 -1
  7. jarvis/jarvis_code_agent/code_agent.py +169 -117
  8. jarvis/jarvis_dev/main.py +327 -626
  9. jarvis/jarvis_git_squash/main.py +10 -31
  10. jarvis/jarvis_lsp/base.py +0 -42
  11. jarvis/jarvis_lsp/cpp.py +0 -15
  12. jarvis/jarvis_lsp/go.py +0 -15
  13. jarvis/jarvis_lsp/python.py +0 -19
  14. jarvis/jarvis_lsp/registry.py +0 -62
  15. jarvis/jarvis_lsp/rust.py +0 -15
  16. jarvis/jarvis_multi_agent/__init__.py +19 -69
  17. jarvis/jarvis_multi_agent/main.py +43 -0
  18. jarvis/jarvis_platform/ai8.py +7 -32
  19. jarvis/jarvis_platform/base.py +2 -7
  20. jarvis/jarvis_platform/kimi.py +3 -144
  21. jarvis/jarvis_platform/ollama.py +54 -68
  22. jarvis/jarvis_platform/openai.py +0 -4
  23. jarvis/jarvis_platform/oyi.py +0 -75
  24. jarvis/jarvis_platform/registry.py +2 -16
  25. jarvis/jarvis_platform/yuanbao.py +264 -0
  26. jarvis/jarvis_rag/file_processors.py +138 -0
  27. jarvis/jarvis_rag/main.py +1305 -425
  28. jarvis/jarvis_tools/ask_codebase.py +216 -43
  29. jarvis/jarvis_tools/code_review.py +158 -113
  30. jarvis/jarvis_tools/create_sub_agent.py +0 -1
  31. jarvis/jarvis_tools/execute_python_script.py +58 -0
  32. jarvis/jarvis_tools/execute_shell.py +13 -26
  33. jarvis/jarvis_tools/execute_shell_script.py +1 -1
  34. jarvis/jarvis_tools/file_analyzer.py +282 -0
  35. jarvis/jarvis_tools/file_operation.py +1 -1
  36. jarvis/jarvis_tools/find_caller.py +278 -0
  37. jarvis/jarvis_tools/find_symbol.py +295 -0
  38. jarvis/jarvis_tools/function_analyzer.py +331 -0
  39. jarvis/jarvis_tools/git_commiter.py +5 -5
  40. jarvis/jarvis_tools/methodology.py +88 -53
  41. jarvis/jarvis_tools/project_analyzer.py +308 -0
  42. jarvis/jarvis_tools/rag.py +0 -5
  43. jarvis/jarvis_tools/read_code.py +24 -3
  44. jarvis/jarvis_tools/read_webpage.py +195 -81
  45. jarvis/jarvis_tools/registry.py +132 -11
  46. jarvis/jarvis_tools/search_web.py +22 -307
  47. jarvis/jarvis_tools/tool_generator.py +8 -10
  48. jarvis/jarvis_utils/__init__.py +1 -0
  49. jarvis/jarvis_utils/config.py +80 -76
  50. jarvis/jarvis_utils/embedding.py +344 -45
  51. jarvis/jarvis_utils/git_utils.py +9 -1
  52. jarvis/jarvis_utils/input.py +7 -6
  53. jarvis/jarvis_utils/methodology.py +384 -15
  54. jarvis/jarvis_utils/output.py +5 -3
  55. jarvis/jarvis_utils/utils.py +60 -8
  56. {jarvis_ai_assistant-0.1.131.dist-info → jarvis_ai_assistant-0.1.134.dist-info}/METADATA +8 -16
  57. jarvis_ai_assistant-0.1.134.dist-info/RECORD +82 -0
  58. {jarvis_ai_assistant-0.1.131.dist-info → jarvis_ai_assistant-0.1.134.dist-info}/entry_points.txt +4 -3
  59. jarvis/jarvis_codebase/__init__.py +0 -0
  60. jarvis/jarvis_codebase/main.py +0 -1011
  61. jarvis/jarvis_tools/lsp_find_definition.py +0 -150
  62. jarvis/jarvis_tools/lsp_find_references.py +0 -127
  63. jarvis/jarvis_tools/treesitter_analyzer.py +0 -331
  64. jarvis/jarvis_treesitter/README.md +0 -104
  65. jarvis/jarvis_treesitter/__init__.py +0 -20
  66. jarvis/jarvis_treesitter/database.py +0 -258
  67. jarvis/jarvis_treesitter/example.py +0 -115
  68. jarvis/jarvis_treesitter/grammar_builder.py +0 -182
  69. jarvis/jarvis_treesitter/language.py +0 -117
  70. jarvis/jarvis_treesitter/symbol.py +0 -31
  71. jarvis/jarvis_treesitter/tools_usage.md +0 -121
  72. jarvis_ai_assistant-0.1.131.dist-info/RECORD +0 -85
  73. {jarvis_ai_assistant-0.1.131.dist-info → jarvis_ai_assistant-0.1.134.dist-info}/LICENSE +0 -0
  74. {jarvis_ai_assistant-0.1.131.dist-info → jarvis_ai_assistant-0.1.134.dist-info}/WHEEL +0 -0
  75. {jarvis_ai_assistant-0.1.131.dist-info → jarvis_ai_assistant-0.1.134.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,58 @@
1
+ from typing import Dict, Any
2
+ import os
3
+ import tempfile
4
+ from pathlib import Path
5
+
6
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
7
+
8
+
9
+ class PythonScriptTool:
10
+ name = "execute_python_script"
11
+ description = "执行Python脚本文件并返回结果"
12
+ parameters = {
13
+ "type": "object",
14
+ "properties": {
15
+ "script_content": {
16
+ "type": "string",
17
+ "description": "要执行的Python脚本内容"
18
+ }
19
+ },
20
+ "required": ["script_content"]
21
+ }
22
+ def execute(self, args: Dict) -> Dict[str, Any]:
23
+ """Execute Python script content"""
24
+ try:
25
+ script_content = args.get("script_content", "").strip()
26
+ if not script_content:
27
+ return {
28
+ "success": False,
29
+ "stdout": "",
30
+ "stderr": "Missing or empty script_content parameter"
31
+ }
32
+
33
+ # Create temporary script file
34
+ script_path = os.path.join(tempfile.gettempdir(), f"jarvis_script_{os.getpid()}.py")
35
+ try:
36
+ with open(script_path, 'w', encoding='utf-8', errors="ignore") as f:
37
+ f.write(script_content)
38
+ # Use execute_shell to run the script
39
+ from jarvis.jarvis_tools.execute_shell import ShellTool
40
+ shell_tool = ShellTool()
41
+ result = shell_tool.execute({"command": f"python3 {script_path}"})
42
+
43
+ return {
44
+ "success": result["success"],
45
+ "stdout": result["stdout"],
46
+ "stderr": result["stderr"]
47
+ }
48
+ finally:
49
+ # Clean up temporary script file
50
+ Path(script_path).unlink(missing_ok=True)
51
+
52
+ except Exception as e:
53
+ PrettyOutput.print(str(e), OutputType.ERROR)
54
+ return {
55
+ "success": False,
56
+ "stdout": "",
57
+ "stderr": str(e)
58
+ }
@@ -41,37 +41,20 @@ class ShellTool:
41
41
  """
42
42
  return cmd.replace("'", "'\"'\"'")
43
43
  def execute(self, args: Dict) -> Dict[str, Any]:
44
- """Execute shell command and capture output
45
-
46
- Steps:
47
- 1. Validate and clean input command
48
- 2. Create temporary file for output capture
49
- 3. Execute command with output redirection
50
- 4. Read and process output file
51
- 5. Clean up temporary resources
52
- 6. Return structured results
53
-
54
- Args:
55
- args: Dictionary containing 'command' parameter
56
-
57
- Returns:
58
- Dictionary with:
59
- - success: Boolean indicating command execution status
60
- - stdout: Command output
61
- - stderr: Error message if execution failed
62
- """
63
44
  try:
64
45
  # Get and clean command input
65
46
  command = args["command"].strip()
66
47
 
67
48
  # Generate temporary file name using process ID for uniqueness
49
+ script_file = os.path.join(tempfile.gettempdir(), f"jarvis_shell_{os.getpid()}.sh")
68
50
  output_file = os.path.join(tempfile.gettempdir(), f"jarvis_shell_{os.getpid()}.log")
69
51
 
70
- # Escape special characters in command to prevent injection
71
- escaped_command = self._escape_command(command)
52
+ # Write command to script file
53
+ with open(script_file, 'w', encoding='utf-8') as f:
54
+ f.write(f"#!/bin/bash\n{command}")
72
55
 
73
56
  # Use script command to capture both stdout and stderr
74
- tee_command = f"script -q -c '{escaped_command}' {output_file}"
57
+ tee_command = f"script -q -c 'bash {script_file}' {output_file}"
75
58
 
76
59
  # Execute command and capture return code
77
60
  os.system(tee_command)
@@ -80,7 +63,7 @@ class ShellTool:
80
63
  try:
81
64
  with open(output_file, 'r', encoding='utf-8', errors='ignore') as f:
82
65
  output = f.read()
83
- # Remove header and footer added by script command
66
+ # Remove header and footer added by script command (if any)
84
67
  if output:
85
68
  lines = output.splitlines()
86
69
  if len(lines) > 2:
@@ -88,7 +71,8 @@ class ShellTool:
88
71
  except Exception as e:
89
72
  output = f"读取输出文件失败: {str(e)}"
90
73
  finally:
91
- # Clean up temporary file
74
+ # Clean up temporary files
75
+ Path(script_file).unlink(missing_ok=True)
92
76
  Path(output_file).unlink(missing_ok=True)
93
77
 
94
78
  # Return successful result
@@ -99,7 +83,9 @@ class ShellTool:
99
83
  }
100
84
 
101
85
  except Exception as e:
102
- # Ensure temporary file is cleaned up even if error occurs
86
+ # Ensure temporary files are cleaned up even if error occurs
87
+ if 'script_file' in locals():
88
+ Path(script_file).unlink(missing_ok=True)
103
89
  if 'output_file' in locals():
104
90
  Path(output_file).unlink(missing_ok=True)
105
91
  PrettyOutput.print(str(e), OutputType.ERROR)
@@ -107,4 +93,5 @@ class ShellTool:
107
93
  "success": False,
108
94
  "stdout": "",
109
95
  "stderr": str(e)
110
- }
96
+ }
97
+
@@ -31,7 +31,7 @@ class ShellScriptTool:
31
31
  }
32
32
 
33
33
  # Create temporary script file
34
- script_path = os.path.join(tempfile.gettempdir(), f"jarvis_script_{os.getpid()}.sh")
34
+ script_path = os.path.join(tempfile.gettempdir(), f"jarvis_shell_script_{os.getpid()}.sh")
35
35
  try:
36
36
  with open(script_path, 'w', encoding='utf-8', errors="ignore") as f:
37
37
  f.write(script_content)
@@ -0,0 +1,282 @@
1
+ from typing import Dict, Any
2
+ import os
3
+ import pathlib
4
+
5
+ from jarvis.jarvis_agent import Agent
6
+ from jarvis.jarvis_platform.registry import PlatformRegistry
7
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
8
+
9
+
10
+ class FileAnalyzerTool:
11
+ """
12
+ 单文件分析工具
13
+ 使用agent深入分析单个文件的结构、实现细节和代码质量
14
+ """
15
+
16
+ name = "file_analyzer"
17
+ description = "深入分析单个文件的结构、实现细节和代码质量"
18
+ parameters = {
19
+ "type": "object",
20
+ "properties": {
21
+ "file_path": {
22
+ "type": "string",
23
+ "description": "要分析的文件路径"
24
+ },
25
+ "root_dir": {
26
+ "type": "string",
27
+ "description": "项目根目录路径(可选)",
28
+ "default": "."
29
+ },
30
+ "objective": {
31
+ "type": "string",
32
+ "description": "描述本次文件分析的目标和用途,例如'准备重构该文件'或'理解该文件在项目中的作用'",
33
+ "default": ""
34
+ }
35
+ },
36
+ "required": ["file_path"]
37
+ }
38
+
39
+ def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
40
+ """
41
+ 执行单文件分析工具
42
+
43
+ Args:
44
+ args: 包含参数的字典
45
+
46
+ Returns:
47
+ 包含执行结果的字典
48
+ """
49
+ # 存储原始目录
50
+ original_dir = os.getcwd()
51
+
52
+ try:
53
+ # 解析参数
54
+ file_path = args.get("file_path", "")
55
+ root_dir = args.get("root_dir", ".")
56
+ objective = args.get("objective", "")
57
+
58
+ # 验证参数
59
+ if not file_path:
60
+ return {
61
+ "success": False,
62
+ "stdout": "",
63
+ "stderr": "必须提供文件路径"
64
+ }
65
+
66
+ # 确保文件路径是相对于root_dir的,如果是绝对路径则转换为相对路径
67
+ abs_file_path = os.path.abspath(file_path)
68
+ abs_root_dir = os.path.abspath(root_dir)
69
+
70
+ if abs_file_path.startswith(abs_root_dir):
71
+ rel_file_path = os.path.relpath(abs_file_path, abs_root_dir)
72
+ else:
73
+ rel_file_path = file_path
74
+
75
+ # 获取文件扩展名和文件名
76
+ file_ext = pathlib.Path(file_path).suffix
77
+ file_name = os.path.basename(file_path)
78
+
79
+ # 创建agent的system prompt
80
+ system_prompt = self._create_system_prompt(
81
+ rel_file_path, file_name, file_ext, root_dir, objective
82
+ )
83
+
84
+ # 创建agent的summary prompt
85
+ summary_prompt = self._create_summary_prompt(rel_file_path, file_name)
86
+
87
+ # 切换到根目录
88
+ os.chdir(root_dir)
89
+
90
+ # 检查文件是否存在
91
+ if not os.path.isfile(rel_file_path):
92
+ return {
93
+ "success": False,
94
+ "stdout": "",
95
+ "stderr": f"文件不存在: {rel_file_path}"
96
+ }
97
+
98
+ # 构建使用的工具
99
+ from jarvis.jarvis_tools.registry import ToolRegistry
100
+ tool_registry = ToolRegistry()
101
+ tool_registry.use_tools([
102
+ "execute_shell",
103
+ "read_code",
104
+ "find_symbol",
105
+ "function_analyzer",
106
+ "find_caller"
107
+ ])
108
+
109
+ # 创建并运行agent
110
+ analyzer_agent = Agent(
111
+ system_prompt=system_prompt,
112
+ name=f"FileAnalyzer-{file_name}",
113
+ description=f"分析 {file_name} 文件的结构和实现",
114
+ summary_prompt=summary_prompt,
115
+ platform=PlatformRegistry().get_normal_platform(),
116
+ output_handler=[tool_registry],
117
+ execute_tool_confirm=False,
118
+ auto_complete=True
119
+ )
120
+
121
+ # 运行agent并获取结果
122
+ task_input = f"深入分析文件 {rel_file_path} 的结构、实现细节和代码质量"
123
+ result = analyzer_agent.run(task_input)
124
+
125
+ return {
126
+ "success": True,
127
+ "stdout": result,
128
+ "stderr": ""
129
+ }
130
+
131
+ except Exception as e:
132
+ PrettyOutput.print(str(e), OutputType.ERROR)
133
+ return {
134
+ "success": False,
135
+ "stdout": "",
136
+ "stderr": f"文件分析失败: {str(e)}"
137
+ }
138
+ finally:
139
+ # 恢复原始目录
140
+ os.chdir(original_dir)
141
+
142
+ def _create_system_prompt(self, file_path: str, file_name: str, file_ext: str,
143
+ root_dir: str, objective: str) -> str:
144
+ """
145
+ 创建Agent的system prompt
146
+
147
+ Args:
148
+ file_path: 文件路径
149
+ file_name: 文件名
150
+ file_ext: 文件扩展名
151
+ root_dir: 代码库根目录
152
+ objective: 分析目标
153
+
154
+ Returns:
155
+ 系统提示文本
156
+ """
157
+ objective_text = f"\n\n## 分析目标\n{objective}" if objective else ""
158
+
159
+ return f"""# 文件分析专家
160
+
161
+ ## 任务描述
162
+ 分析文件 `{file_path}` 的结构、实现细节和代码质量,专注于分析目标所需的内容,生成有针对性、深入且有洞察力的文件分析报告。{objective_text}
163
+
164
+ ## 工具使用优先级
165
+ 1. **优先使用 read_code**: 直接读取文件内容是分析文件的首选方式
166
+ 2. **优先使用 execute_shell**:
167
+ - 使用 rg 搜索文件内容: `rg "pattern" {file_path}`
168
+ - 使用 loc 统计代码: `loc {file_path}`
169
+ 3. **仅在必要时使用其他分析工具**
170
+
171
+ ## 文件信息
172
+ - 文件路径: `{file_path}`
173
+ - 文件名称: `{file_name}`
174
+ - 文件类型: `{file_ext}`
175
+ - 项目根目录: `{root_dir}`
176
+
177
+ ## 分析策略
178
+ 1. 首先使用read_code直接读取整个文件内容或分段读取
179
+ 2. 使用rg命令搜索文件中的特定模式和结构
180
+ 3. 使用loc命令获取文件统计信息
181
+ 4. 根据文件类型和分析目标确定重点关注的方面
182
+ 5. 保证分析的完整性,收集充分的信息后再得出结论
183
+
184
+ ## 分析步骤
185
+ 以下步骤应根据具体分析目标灵活应用:
186
+
187
+ 1. **文件基本信息分析**:
188
+ - 使用 `loc {file_path}` 获取代码统计
189
+ - 使用 read_code 读取文件头部注释和文档
190
+ - 确定文件的编程语言和主要功能
191
+
192
+ 2. **结构分析**:
193
+ - 使用 read_code 阅读完整文件
194
+ - 对于大文件,可分段读取主要部分
195
+ - 识别文件的主要组成部分:
196
+ - 类定义: `rg "class\\s+" {file_path}`
197
+ - 函数定义: `rg "def\\s+|function\\s+" {file_path}`
198
+ - 重要变量: `rg "const\\s+|var\\s+|let\\s+" {file_path}`
199
+
200
+ 3. **核心组件分析**:
201
+ - 识别文件中的关键接口、类和函数
202
+ - 使用 rg 搜索重要的代码模式
203
+ - 分析组件间的交互和依赖关系
204
+
205
+ 4. **实现细节分析**:
206
+ - 读取并分析关键函数的实现
207
+ - 关注异常处理: `rg "try|catch|except" {file_path}`
208
+ - 检查资源管理: `rg "open|close|with" {file_path}`
209
+
210
+ 5. **引用分析**:
211
+ - 找出引用的外部依赖: `rg "import|require|include" {file_path}`
212
+ - 分析与其他模块的交互
213
+
214
+ ## 分析工具使用指南
215
+
216
+ ### read_code
217
+ - **首选工具**: 用于读取和分析文件内容
218
+ - **用法指南**:
219
+ - 读取整个文件: 直接指定文件路径
220
+ - 读取部分内容: 指定文件路径和行范围
221
+ - 读取头部或关键部分: 根据目的选择合适的行范围
222
+
223
+ ### execute_shell
224
+ - **用途**: 执行辅助命令进行分析
225
+ - **推荐命令**:
226
+ - `rg "pattern" {file_path}`: 在文件中搜索模式
227
+ - `loc {file_path}`: 获取文件代码统计
228
+ - `rg -n "class|def|function" {file_path}`: 查找结构元素
229
+
230
+ ### 其他专业工具
231
+ - **使用时机**: 仅当read_code和execute_shell不足以完成分析时
232
+ - **使用前提**: 必须先尝试使用基本工具解决问题
233
+ - **选择原则**: 根据实际需要选择最简洁有效的工具
234
+
235
+ ## 分析框架适应
236
+ 根据文件类型和编程范式调整分析重点:
237
+
238
+ ### 不同编程范式
239
+ - 面向对象: 类层次、继承、封装、接口实现
240
+ - 函数式: 函数组合、不可变性、纯函数
241
+ - 过程式: 流程控制、状态管理、数据处理
242
+ - 声明式: 规则定义、约束表达、模式匹配
243
+
244
+ ### 不同文件类型
245
+ - 源代码文件: 实现逻辑、算法、接口设计
246
+ - 配置文件: 参数设置、环境变量、系统选项
247
+ - 模板文件: 渲染逻辑、变量占位符、条件分支
248
+ - 数据文件: 结构组织、关系定义、索引设计
249
+
250
+ ## 输出要求
251
+ - 直接回应分析目标的关键问题
252
+ - 提供与目标相关的深入洞察
253
+ - 分析内容应直接服务于分析目标
254
+ - 避免与目标无关的冗余信息
255
+ - 使用具体代码片段支持分析结论
256
+ - 提供针对分析目标的具体建议
257
+ - 保证全面分析相关信息后再得出结论"""
258
+
259
+ def _create_summary_prompt(self, file_path: str, file_name: str) -> str:
260
+ """
261
+ 创建Agent的summary prompt
262
+
263
+ Args:
264
+ file_path: 文件路径
265
+ file_name: 文件名
266
+
267
+ Returns:
268
+ 总结提示文本
269
+ """
270
+ return f"""# 文件分析报告: `{file_name}`
271
+
272
+ ## 报告要求
273
+ 生成一份完全以分析目标为导向的文件分析报告。不要遵循固定的报告模板,而是完全根据分析目标来组织内容:
274
+
275
+ - 专注回答分析目标提出的问题
276
+ - 只包含与分析目标直接相关的发现和洞察
277
+ - 完全跳过与分析目标无关的内容,无需做全面分析
278
+ - 分析深度应与目标的具体需求匹配
279
+ - 使用具体的代码片段和实例支持你的观点
280
+ - 以清晰的Markdown格式呈现,简洁明了
281
+
282
+ 在分析中保持灵活性,避免固定思维模式。你的任务不是提供全面的文件概览,而是直接解决分析目标中提出的具体问题。"""
@@ -9,7 +9,7 @@ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
9
9
 
10
10
  class FileOperationTool:
11
11
  name = "file_operation"
12
- description = "用于读写多个文件的操作工具"
12
+ description = "文件批量操作工具,可批量读写多个文件,适用于需要同时处理多个文件的场景(读取配置文件、保存生成内容等),不提供代码分析功能"
13
13
  parameters = {
14
14
  "type": "object",
15
15
  "properties": {