jarvis-ai-assistant 0.1.98__py3-none-any.whl → 0.1.100__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 (45) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/agent.py +199 -157
  3. jarvis/jarvis_code_agent/__init__.py +0 -0
  4. jarvis/jarvis_code_agent/main.py +202 -0
  5. jarvis/jarvis_codebase/main.py +415 -287
  6. jarvis/jarvis_coder/file_select.py +209 -0
  7. jarvis/jarvis_coder/git_utils.py +64 -2
  8. jarvis/jarvis_coder/main.py +13 -397
  9. jarvis/jarvis_coder/patch_handler.py +229 -81
  10. jarvis/jarvis_coder/plan_generator.py +49 -7
  11. jarvis/jarvis_platform/main.py +2 -2
  12. jarvis/jarvis_rag/main.py +11 -11
  13. jarvis/jarvis_smart_shell/main.py +5 -5
  14. jarvis/models/base.py +6 -1
  15. jarvis/models/kimi.py +2 -2
  16. jarvis/models/ollama.py +2 -2
  17. jarvis/models/openai.py +1 -1
  18. jarvis/models/registry.py +38 -18
  19. jarvis/tools/ask_user.py +12 -9
  20. jarvis/tools/chdir.py +9 -5
  21. jarvis/tools/create_code_sub_agent.py +56 -0
  22. jarvis/tools/{sub_agent.py → create_sub_agent.py} +6 -2
  23. jarvis/tools/execute_code_modification.py +70 -0
  24. jarvis/tools/{shell.py → execute_shell.py} +2 -2
  25. jarvis/tools/{file_ops.py → file_operation.py} +19 -15
  26. jarvis/tools/find_files.py +119 -0
  27. jarvis/tools/{generator.py → generate_tool.py} +27 -25
  28. jarvis/tools/methodology.py +32 -26
  29. jarvis/tools/rag.py +37 -33
  30. jarvis/tools/{webpage.py → read_webpage.py} +4 -2
  31. jarvis/tools/registry.py +94 -48
  32. jarvis/tools/search.py +19 -16
  33. jarvis/tools/select_code_files.py +61 -0
  34. jarvis/tools/thinker.py +7 -5
  35. jarvis/utils.py +155 -32
  36. {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/METADATA +9 -8
  37. jarvis_ai_assistant-0.1.100.dist-info/RECORD +51 -0
  38. {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/entry_points.txt +2 -1
  39. jarvis/main.py +0 -155
  40. jarvis/tools/codebase_qa.py +0 -74
  41. jarvis/tools/coder.py +0 -69
  42. jarvis_ai_assistant-0.1.98.dist-info/RECORD +0 -47
  43. {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/LICENSE +0 -0
  44. {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/WHEEL +0 -0
  45. {jarvis_ai_assistant-0.1.98.dist-info → jarvis_ai_assistant-0.1.100.dist-info}/top_level.txt +0 -0
@@ -32,16 +32,15 @@ class ToolGeneratorTool:
32
32
  }
33
33
 
34
34
  def __init__(self):
35
- """初始化工具生成器
36
- """
37
- # 设置工具目录
38
- self.tools_dir = Path.home() / '.jarvis_tools'
35
+ """Initialize tool generator"""
36
+ # Set tool directory
37
+ self.tools_dir = Path.home() / '.jarvis/tools'
39
38
 
40
- # 确保工具目录存在
39
+ # Ensure tool directory exists
41
40
  self.tools_dir.mkdir(parents=True, exist_ok=True)
42
41
 
43
42
  def _generate_tool_code(self, tool_name: str, class_name: str, description: str, parameters: Dict) -> str:
44
- """使用大模型生成工具代码"""
43
+ """Use large model to generate tool code"""
45
44
  model = PlatformRegistry.get_global_platform_registry().get_codegen_platform()
46
45
 
47
46
  prompt = f"""Please generate the code for a Python tool class, with the following requirements, and do not output any content except the code:
@@ -96,36 +95,37 @@ class ExampleTool:
96
95
  PrettyOutput.print(str(e), OutputType.ERROR)
97
96
  return {{
98
97
  "success": False,
99
- "error": str(e)
98
+ "stdout": "",
99
+ "stderr": str(e)
100
100
  }}
101
101
  ```"""
102
102
 
103
- # 调用模型生成代码
103
+ # Call model to generate code
104
104
  response = model.chat_until_success(prompt)
105
105
 
106
- # 提取代码块
106
+ # Extract code block
107
107
  code_start = response.find("```python")
108
108
  code_end = response.find("```", code_start + 9)
109
109
 
110
110
  if code_start == -1 or code_end == -1:
111
- # 如果没有找到代码块标记,假设整个响应都是代码
111
+ # If code block marker not found, assume the entire response is code
112
112
  return response
113
113
 
114
- # 提取代码块内容(去掉```python和```标记)
114
+ # Extract code block content (remove ```python and ``` markers)
115
115
  code = response[code_start + 9:code_end].strip()
116
116
  return code
117
117
 
118
118
  def execute(self, args: Dict) -> Dict[str, Any]:
119
- """生成工具代码"""
119
+ """Generate tool code"""
120
120
  try:
121
121
  tool_name = args["tool_name"]
122
122
  class_name = args["class_name"]
123
123
  description = args["description"]
124
124
  parameters = args["parameters"]
125
125
 
126
- PrettyOutput.print(f"开始生成工具: {tool_name}", OutputType.INFO)
126
+ PrettyOutput.print(f"Start generating tool: {tool_name}", OutputType.INFO)
127
127
 
128
- # 生成工具代码
128
+ # Generate tool code
129
129
  tool_code = self._generate_tool_code(
130
130
  tool_name,
131
131
  class_name,
@@ -133,34 +133,35 @@ class ExampleTool:
133
133
  parameters
134
134
  )
135
135
 
136
- # 获取工具文件路径
136
+ # Get tool file path
137
137
  tool_file = self.tools_dir / f"{tool_name}.py"
138
138
 
139
- # 写入工具文件
139
+ # Write tool file
140
140
  with open(tool_file, "w", encoding="utf-8") as f:
141
141
  f.write(tool_code)
142
142
 
143
- # 创建或更新 __init__.py
143
+ # Create or update __init__.py
144
144
  init_file = self.tools_dir / "__init__.py"
145
145
  if not init_file.exists():
146
146
  with open(init_file, "w", encoding="utf-8") as f:
147
147
  f.write("# Jarvis Tools\n")
148
148
 
149
- # 注册工具
149
+ # Register tool
150
150
  success = ToolRegistry.get_global_tool_registry().register_tool_by_file(str(tool_file))
151
151
  if not success:
152
152
  return {
153
153
  "success": False,
154
- "error": "工具生成成功但注册失败"
154
+ "stdout": "",
155
+ "stderr": "Tool generated successfully but registration failed"
155
156
  }
156
157
 
157
158
  return {
158
159
  "success": True,
159
- "stdout": f"工具已生成并注册到Jarvis\n"
160
- f"工具目录: {self.tools_dir}\n"
161
- f"工具名称: {tool_name}\n"
162
- f"工具描述: {description}\n"
163
- f"工具参数: {parameters}",
160
+ "stdout": f"Tool generated and registered to Jarvis\n"
161
+ f"Tool directory: {self.tools_dir}\n"
162
+ f"Tool name: {tool_name}\n"
163
+ f"Tool description: {description}\n"
164
+ f"Tool parameters: {parameters}",
164
165
  "stderr": ""
165
166
  }
166
167
 
@@ -168,5 +169,6 @@ class ExampleTool:
168
169
  PrettyOutput.print(str(e), OutputType.ERROR)
169
170
  return {
170
171
  "success": False,
171
- "error": f"生成工具失败: {str(e)}"
172
+ "stdout": "",
173
+ "stderr": f"Failed to generate tool: {str(e)}"
172
174
  }
@@ -5,7 +5,7 @@ from jarvis.utils import OutputType, PrettyOutput
5
5
 
6
6
 
7
7
  class MethodologyTool:
8
- """经验管理工具"""
8
+ """Experience management tool"""
9
9
 
10
10
  name = "methodology"
11
11
  description = "Manage problem-solving methodologies, supporting add, update, and delete operations"
@@ -31,47 +31,47 @@ class MethodologyTool:
31
31
  }
32
32
 
33
33
  def __init__(self):
34
- """初始化经验管理工具"""
35
- self.methodology_file = os.path.expanduser("~/.jarvis_methodology")
34
+ """Initialize the experience management tool"""
35
+ self.methodology_file = os.path.expanduser("~/.jarvis/methodology")
36
36
  self._ensure_file_exists()
37
37
 
38
38
  def _ensure_file_exists(self):
39
- """确保方法论文件存在"""
39
+ """Ensure the methodology file exists"""
40
40
  if not os.path.exists(self.methodology_file):
41
41
  try:
42
42
  with open(self.methodology_file, 'w', encoding='utf-8') as f:
43
43
  yaml.safe_dump({}, f, allow_unicode=True)
44
44
  except Exception as e:
45
- PrettyOutput.print(f"创建方法论文件失败: {str(e)}", OutputType.ERROR)
45
+ PrettyOutput.print(f"Failed to create methodology file: {str(e)}", OutputType.ERROR)
46
46
 
47
47
  def _load_methodologies(self) -> Dict:
48
- """加载所有方法论"""
48
+ """Load all methodologies"""
49
49
  try:
50
50
  with open(self.methodology_file, 'r', encoding='utf-8') as f:
51
51
  return yaml.safe_load(f) or {}
52
52
  except Exception as e:
53
- PrettyOutput.print(f"加载方法论失败: {str(e)}", OutputType.ERROR)
53
+ PrettyOutput.print(f"Failed to load methodologies: {str(e)}", OutputType.ERROR)
54
54
  return {}
55
55
 
56
56
  def _save_methodologies(self, methodologies: Dict):
57
- """保存所有方法论"""
57
+ """Save all methodologies"""
58
58
  try:
59
59
  with open(self.methodology_file, 'w', encoding='utf-8') as f:
60
60
  yaml.safe_dump(methodologies, f, allow_unicode=True)
61
61
  except Exception as e:
62
- PrettyOutput.print(f"保存方法论失败: {str(e)}", OutputType.ERROR)
62
+ PrettyOutput.print(f"Failed to save methodologies: {str(e)}", OutputType.ERROR)
63
63
 
64
64
  def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
65
- """执行方法论管理操作
65
+ """Execute the operation of managing methodologies
66
66
 
67
67
  Args:
68
- args: 包含操作参数的字典
69
- - operation: 操作类型 (delete/update/add)
70
- - problem_type: 问题类型
71
- - content: 方法论内容 (update/add 时必需)
68
+ args: A dictionary containing the operation parameters
69
+ - operation: The operation type (delete/update/add)
70
+ - problem_type: The problem type
71
+ - content: The methodology content (required for update/add)
72
72
 
73
73
  Returns:
74
- Dict[str, Any]: 包含执行结果的字典
74
+ Dict[str, Any]: A dictionary containing the execution result
75
75
  """
76
76
  operation = args.get("operation")
77
77
  problem_type = args.get("problem_type")
@@ -80,7 +80,8 @@ class MethodologyTool:
80
80
  if not operation or not problem_type:
81
81
  return {
82
82
  "success": False,
83
- "error": "缺少必要参数: operation 和 problem_type"
83
+ "stdout": "",
84
+ "stderr": "Missing required parameters: operation and problem_type"
84
85
  }
85
86
 
86
87
  methodologies = self._load_methodologies()
@@ -92,50 +93,55 @@ class MethodologyTool:
92
93
  self._save_methodologies(methodologies)
93
94
  return {
94
95
  "success": True,
95
- "stdout": f"已删除问题类型 '{problem_type}' 的方法论"
96
+ "stdout": f"Deleted methodology for problem type '{problem_type}'"
96
97
  }
97
98
  else:
98
99
  return {
99
100
  "success": False,
100
- "error": f"未找到问题类型 '{problem_type}' 的方法论"
101
+ "stdout": "",
102
+ "stderr": f"Methodology for problem type '{problem_type}' not found"
101
103
  }
102
104
 
103
105
  elif operation in ["update", "add"]:
104
106
  if not content:
105
107
  return {
106
108
  "success": False,
107
- "error": "需要提供方法论内容"
109
+ "stdout": "",
110
+ "stderr": "Need to provide methodology content"
108
111
  }
109
112
 
110
113
  methodologies[problem_type] = content
111
114
  self._save_methodologies(methodologies)
112
115
 
113
- action = "更新" if problem_type in methodologies else "添加"
116
+ action = "Update" if problem_type in methodologies else "Add"
114
117
  return {
115
118
  "success": True,
116
- "stdout": f"{action}问题类型 '{problem_type}' 的方法论"
119
+ "stdout": f"{action} methodology for problem type '{problem_type}'",
120
+ "stderr": ""
117
121
  }
118
122
 
119
123
  else:
120
124
  return {
121
125
  "success": False,
122
- "error": f"不支持的操作类型: {operation}"
126
+ "stdout": "",
127
+ "stderr": f"Unsupported operation type: {operation}"
123
128
  }
124
129
 
125
130
  except Exception as e:
126
131
  return {
127
132
  "success": False,
128
- "error": f"执行失败: {str(e)}"
133
+ "stdout": "",
134
+ "stderr": f"Execution failed: {str(e)}"
129
135
  }
130
136
 
131
137
  def get_methodology(self, problem_type: str) -> Optional[str]:
132
- """获取指定问题类型的方法论
138
+ """Get the methodology for a specific problem type
133
139
 
134
140
  Args:
135
- problem_type: 问题类型
141
+ problem_type: The problem type
136
142
 
137
143
  Returns:
138
- Optional[str]: 方法论内容,如果不存在则返回 None
144
+ Optional[str]: The methodology content, or None if it does not exist
139
145
  """
140
146
  methodologies = self._load_methodologies()
141
147
  return methodologies.get(problem_type)
jarvis/tools/rag.py CHANGED
@@ -27,71 +27,74 @@ class RAGTool:
27
27
  }
28
28
 
29
29
  def __init__(self):
30
- """初始化 RAG 工具"""
31
- self.rag_instances = {} # 缓存不同目录的 RAG 实例
30
+ """Initialize RAG tool"""
31
+ self.rag_instances = {} # Cache RAG instances for different directories
32
32
 
33
33
  def _get_rag_instance(self, dir_path: str) -> RAGCore:
34
- """获取或创建 RAG 实例
34
+ """Get or create RAG instance
35
35
 
36
36
  Args:
37
- dir_path: 文档目录的绝对路径
37
+ dir_path: The absolute path of the document directory
38
38
 
39
39
  Returns:
40
- RAGCore: RAG 实例
40
+ RAGCore: RAG instance
41
41
  """
42
42
  if dir_path not in self.rag_instances:
43
43
  self.rag_instances[dir_path] = RAGCore(dir_path)
44
44
  return self.rag_instances[dir_path]
45
45
 
46
46
  def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
47
- """执行文档问答
47
+ """Execute document question and answer
48
48
 
49
49
  Args:
50
- args: 包含参数的字典
51
- - dir: 文档目录路径
52
- - question: 要询问的问题
53
- - rebuild_index: 是否重建索引
50
+ args: A dictionary containing parameters
51
+ - dir: The document directory path
52
+ - question: The question to ask
53
+ - rebuild_index: Whether to rebuild the index
54
54
 
55
55
  Returns:
56
- Dict[str, Any]: 执行结果
56
+ Dict[str, Any]: The execution result
57
57
  """
58
58
  try:
59
- # 获取参数
60
- dir_path = os.path.expanduser(args["dir"]) # 展开 ~ 等路径
61
- dir_path = os.path.abspath(dir_path) # 转换为绝对路径
59
+ # Get parameters
60
+ dir_path = os.path.expanduser(args["dir"]) # Expand ~ paths
61
+ dir_path = os.path.abspath(dir_path) # Convert to absolute path
62
62
  question = args["question"]
63
63
  rebuild_index = args.get("rebuild_index", False)
64
64
 
65
- # 检查目录是否存在
65
+ # Check if the directory exists
66
66
  if not os.path.exists(dir_path):
67
67
  return {
68
68
  "success": False,
69
- "error": f"目录不存在: {dir_path}"
69
+ "stdout": "",
70
+ "stderr": f"Directory does not exist: {dir_path}"
70
71
  }
71
72
 
72
- # 检查是否是目录
73
+ # Check if it is a directory
73
74
  if not os.path.isdir(dir_path):
74
75
  return {
75
76
  "success": False,
76
- "error": f"路径不是目录: {dir_path}"
77
+ "stdout": "",
78
+ "stderr": f"The path is not a directory: {dir_path}"
77
79
  }
78
80
 
79
- # 获取 RAG 实例
81
+ # Get RAG instance
80
82
  rag = self._get_rag_instance(dir_path)
81
83
 
82
- # 如果需要重建索引或索引不存在
84
+ # If you need to rebuild the index or the index does not exist
83
85
  if rebuild_index or not rag.is_index_built():
84
- PrettyOutput.print("正在构建文档索引...", OutputType.INFO)
86
+ PrettyOutput.print("Building document index...", OutputType.INFO)
85
87
  rag.build_index(dir_path)
86
88
 
87
- # 执行问答
88
- PrettyOutput.print(f"问题: {question}", OutputType.INFO)
89
+ # Execute question and answer
90
+ PrettyOutput.print(f"Question: {question}", OutputType.INFO)
89
91
  response = rag.ask(question)
90
92
 
91
93
  if response is None:
92
94
  return {
93
95
  "success": False,
94
- "error": "未能获取答案,可能是没有找到相关文档"
96
+ "stdout": "",
97
+ "stderr": "Failed to get answer, possibly no relevant documents found"
95
98
  }
96
99
 
97
100
  return {
@@ -101,20 +104,21 @@ class RAGTool:
101
104
  }
102
105
 
103
106
  except Exception as e:
104
- PrettyOutput.print(f"文档问答失败: {str(e)}", OutputType.ERROR)
107
+ PrettyOutput.print(f"Document question and answer failed: {str(e)}", OutputType.ERROR)
105
108
  return {
106
109
  "success": False,
107
- "error": f"执行失败: {str(e)}"
110
+ "stdout": "",
111
+ "stderr": f"Execution failed: {str(e)}"
108
112
  }
109
113
 
110
114
  def main():
111
- """命令行直接运行工具"""
115
+ """Run the tool directly from the command line"""
112
116
  import argparse
113
117
 
114
- parser = argparse.ArgumentParser(description='文档问答工具')
115
- parser.add_argument('--dir', required=True, help='文档目录路径')
116
- parser.add_argument('--question', required=True, help='要询问的问题')
117
- parser.add_argument('--rebuild', action='store_true', help='重建索引')
118
+ parser = argparse.ArgumentParser(description='Document question and answer tool')
119
+ parser.add_argument('--dir', required=True, help='Document directory path')
120
+ parser.add_argument('--question', required=True, help='The question to ask')
121
+ parser.add_argument('--rebuild', action='store_true', help='Rebuild index')
118
122
  args = parser.parse_args()
119
123
 
120
124
  tool = RAGTool()
@@ -125,10 +129,10 @@ def main():
125
129
  })
126
130
 
127
131
  if result["success"]:
128
- PrettyOutput.print("\n回答:", OutputType.INFO)
132
+ PrettyOutput.print("\nAnswer:", OutputType.INFO)
129
133
  PrettyOutput.print(result["stdout"], OutputType.INFO)
130
134
  else:
131
- PrettyOutput.print(result["error"], OutputType.ERROR)
135
+ PrettyOutput.print(result["stderr"], OutputType.ERROR)
132
136
 
133
137
  if __name__ == "__main__":
134
138
  main()
@@ -67,10 +67,12 @@ class WebpageTool:
67
67
  except requests.RequestException as e:
68
68
  return {
69
69
  "success": False,
70
- "error": f"Webpage request failed: {str(e)}"
70
+ "stdout": "",
71
+ "stderr": f"Webpage request failed: {str(e)}"
71
72
  }
72
73
  except Exception as e:
73
74
  return {
74
75
  "success": False,
75
- "error": f"Failed to parse webpage: {str(e)}"
76
+ "stdout": "",
77
+ "stderr": f"Failed to parse webpage: {str(e)}"
76
78
  }