jarvis-ai-assistant 0.1.124__py3-none-any.whl → 0.1.126__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 (70) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +134 -136
  3. jarvis/jarvis_code_agent/code_agent.py +198 -52
  4. jarvis/jarvis_code_agent/file_select.py +6 -19
  5. jarvis/jarvis_code_agent/patch.py +183 -312
  6. jarvis/jarvis_code_agent/shell_input_handler.py +22 -0
  7. jarvis/jarvis_codebase/main.py +89 -86
  8. jarvis/jarvis_dev/main.py +695 -715
  9. jarvis/jarvis_git_squash/__init__.py +0 -0
  10. jarvis/jarvis_git_squash/main.py +81 -0
  11. jarvis/jarvis_lsp/base.py +0 -12
  12. jarvis/jarvis_lsp/cpp.py +1 -10
  13. jarvis/jarvis_lsp/go.py +1 -10
  14. jarvis/jarvis_lsp/python.py +0 -28
  15. jarvis/jarvis_lsp/registry.py +2 -3
  16. jarvis/jarvis_lsp/rust.py +1 -10
  17. jarvis/jarvis_multi_agent/__init__.py +53 -53
  18. jarvis/jarvis_platform/ai8.py +2 -1
  19. jarvis/jarvis_platform/base.py +19 -24
  20. jarvis/jarvis_platform/kimi.py +2 -3
  21. jarvis/jarvis_platform/ollama.py +3 -1
  22. jarvis/jarvis_platform/openai.py +1 -1
  23. jarvis/jarvis_platform/oyi.py +2 -1
  24. jarvis/jarvis_platform/registry.py +2 -1
  25. jarvis/jarvis_platform_manager/main.py +4 -6
  26. jarvis/jarvis_platform_manager/openai_test.py +0 -1
  27. jarvis/jarvis_rag/main.py +5 -2
  28. jarvis/jarvis_smart_shell/main.py +9 -4
  29. jarvis/jarvis_tools/ask_codebase.py +18 -13
  30. jarvis/jarvis_tools/ask_user.py +5 -4
  31. jarvis/jarvis_tools/base.py +22 -8
  32. jarvis/jarvis_tools/chdir.py +8 -9
  33. jarvis/jarvis_tools/code_review.py +19 -20
  34. jarvis/jarvis_tools/create_code_agent.py +6 -6
  35. jarvis/jarvis_tools/create_sub_agent.py +9 -9
  36. jarvis/jarvis_tools/execute_shell.py +55 -20
  37. jarvis/jarvis_tools/execute_shell_script.py +7 -7
  38. jarvis/jarvis_tools/file_operation.py +39 -10
  39. jarvis/jarvis_tools/git_commiter.py +20 -17
  40. jarvis/jarvis_tools/lsp_find_definition.py +8 -8
  41. jarvis/jarvis_tools/lsp_find_references.py +1 -1
  42. jarvis/jarvis_tools/lsp_get_diagnostics.py +19 -11
  43. jarvis/jarvis_tools/lsp_get_document_symbols.py +1 -1
  44. jarvis/jarvis_tools/lsp_prepare_rename.py +8 -8
  45. jarvis/jarvis_tools/methodology.py +10 -7
  46. jarvis/jarvis_tools/rag.py +27 -20
  47. jarvis/jarvis_tools/read_webpage.py +4 -3
  48. jarvis/jarvis_tools/registry.py +143 -140
  49. jarvis/jarvis_tools/{search.py → search_web.py} +10 -7
  50. jarvis/jarvis_tools/select_code_files.py +4 -4
  51. jarvis/jarvis_tools/tool_generator.py +33 -34
  52. jarvis/jarvis_utils/__init__.py +19 -982
  53. jarvis/jarvis_utils/config.py +138 -0
  54. jarvis/jarvis_utils/embedding.py +201 -0
  55. jarvis/jarvis_utils/git_utils.py +120 -0
  56. jarvis/jarvis_utils/globals.py +82 -0
  57. jarvis/jarvis_utils/input.py +161 -0
  58. jarvis/jarvis_utils/methodology.py +128 -0
  59. jarvis/jarvis_utils/output.py +235 -0
  60. jarvis/jarvis_utils/utils.py +150 -0
  61. jarvis_ai_assistant-0.1.126.dist-info/METADATA +305 -0
  62. jarvis_ai_assistant-0.1.126.dist-info/RECORD +74 -0
  63. {jarvis_ai_assistant-0.1.124.dist-info → jarvis_ai_assistant-0.1.126.dist-info}/WHEEL +1 -1
  64. {jarvis_ai_assistant-0.1.124.dist-info → jarvis_ai_assistant-0.1.126.dist-info}/entry_points.txt +1 -0
  65. jarvis/jarvis_tools/lsp_validate_edit.py +0 -141
  66. jarvis/jarvis_tools/read_code.py +0 -191
  67. jarvis_ai_assistant-0.1.124.dist-info/METADATA +0 -460
  68. jarvis_ai_assistant-0.1.124.dist-info/RECORD +0 -65
  69. {jarvis_ai_assistant-0.1.124.dist-info → jarvis_ai_assistant-0.1.126.dist-info}/LICENSE +0 -0
  70. {jarvis_ai_assistant-0.1.124.dist-info → jarvis_ai_assistant-0.1.126.dist-info}/top_level.txt +0 -0
@@ -1,63 +1,199 @@
1
+ import re
1
2
  import subprocess
2
3
  import os
3
- from typing import Dict, List
4
+ from typing import Any, Tuple
4
5
 
5
6
  from jarvis.jarvis_agent import Agent
6
- from jarvis.jarvis_code_agent.file_select import select_files
7
- from jarvis.jarvis_code_agent.patch import PatchOutputHandler, file_input_handler
7
+ from jarvis.jarvis_code_agent.shell_input_handler import shell_input_handler
8
+ from jarvis.jarvis_code_agent.patch import PatchOutputHandler
8
9
  from jarvis.jarvis_platform.registry import PlatformRegistry
10
+ from jarvis.jarvis_tools.file_operation import FileOperationTool
9
11
  from jarvis.jarvis_tools.git_commiter import GitCommitTool
12
+
10
13
  from jarvis.jarvis_tools.registry import ToolRegistry
11
- from jarvis.jarvis_tools.read_code import ReadCodeTool
12
- from jarvis.jarvis_utils import get_commits_between
13
- from jarvis.jarvis_utils import OutputType, PrettyOutput, get_multiline_input, has_uncommitted_changes, init_env, find_git_root, user_confirm, get_latest_commit_hash
14
- from jarvis.jarvis_utils import OutputType, PrettyOutput, get_multiline_input, has_uncommitted_changes, init_env, find_git_root, user_confirm
14
+ from jarvis.jarvis_utils.git_utils import find_git_root, get_commits_between, get_latest_commit_hash, has_uncommitted_changes
15
+ from jarvis.jarvis_utils.input import get_multiline_input
16
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
17
+ from jarvis.jarvis_utils.utils import init_env, user_confirm
18
+
19
+
20
+
21
+
22
+ def file_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
23
+ prompt = user_input
24
+ files = []
25
+
26
+ file_refs = re.findall(r"'([^']+)'", user_input)
27
+ for ref in file_refs:
28
+ # Handle file:start,end or file:start:end format
29
+ if ':' in ref:
30
+ file_path, line_range = ref.split(':', 1)
31
+ # Initialize with default values
32
+ start_line = 1 # 1-based
33
+ end_line = -1
34
+
35
+ # Process line range if specified
36
+ if ',' in line_range or ':' in line_range:
37
+ try:
38
+ raw_start, raw_end = map(int, re.split(r'[,:]', line_range))
39
+
40
+ # Handle special values and Python-style negative indices
41
+ try:
42
+ with open(file_path, 'r', encoding='utf-8') as f:
43
+ total_lines = len(f.readlines())
44
+ except FileNotFoundError:
45
+ PrettyOutput.print(f"文件不存在: {file_path}", OutputType.WARNING)
46
+ continue
47
+ # Process start line
48
+ if raw_start == 0: # 0表示整个文件
49
+ start_line = 1
50
+ end_line = total_lines
51
+ else:
52
+ start_line = raw_start if raw_start > 0 else total_lines + raw_start + 1
53
+
54
+ # Process end line
55
+ if raw_end == 0: # 0表示整个文件(如果start也是0)
56
+ end_line = total_lines
57
+ else:
58
+ end_line = raw_end if raw_end > 0 else total_lines + raw_end + 1
59
+
60
+ # Auto-correct ranges
61
+ start_line = max(1, min(start_line, total_lines))
62
+ end_line = max(start_line, min(end_line, total_lines))
63
+
64
+ # Final validation
65
+ if start_line < 1 or end_line > total_lines or start_line > end_line:
66
+ raise ValueError
67
+
68
+ except:
69
+ continue
70
+
71
+ # Add file if it exists
72
+ if os.path.isfile(file_path):
73
+ files.append({
74
+ "path": file_path,
75
+ "start_line": start_line,
76
+ "end_line": end_line
77
+ })
78
+ else:
79
+ # Handle simple file path
80
+ if os.path.isfile(ref):
81
+ files.append({
82
+ "path": ref,
83
+ "start_line": 1, # 1-based
84
+ "end_line": -1
85
+ })
86
+
87
+ # Read and process files if any were found
88
+ if files:
89
+ result = FileOperationTool().execute({"operation":"read","files": files})
90
+ if result["success"]:
91
+ return result["stdout"] + "\n" + prompt, False
92
+
93
+ return prompt, False
94
+
15
95
 
16
96
 
17
97
  class CodeAgent:
18
98
  def __init__(self):
19
99
  self.root_dir = os.getcwd()
20
100
  tool_registry = ToolRegistry()
21
- tool_registry.use_tools(["read_code",
22
- "execute_shell",
101
+ tool_registry.use_tools(["execute_shell",
23
102
  "execute_shell_script",
24
- "search",
103
+ "search_web",
25
104
  "create_code_agent",
26
- "ask_user",
27
- "ask_codebase",
105
+ "ask_user",
106
+ "ask_codebase",
28
107
  "lsp_get_document_symbols",
29
108
  "lsp_get_diagnostics",
30
109
  "lsp_find_references",
31
110
  "lsp_find_definition",
32
- "lsp_prepare_rename",
33
- "lsp_validate_edit"])
111
+ "lsp_prepare_rename"
112
+ ])
34
113
  code_system_prompt = """
35
- # Role: Code Engineer
36
- Expert in precise code modifications with proper tool usage.
37
- ## Tool Usage Guide
38
- 1. read_code: Analyze code files before changes
39
- 2. execute_shell: Run system commands safely
40
- 3. execute_shell_script: Execute script files
41
- 4. search: Find technical information
42
- 5. create_code_agent: Create new code agents
43
- 6. ask_user: Clarify requirements
44
- 7. ask_codebase: Analyze codebase structure
45
- 8. lsp_get_document_symbols: List code symbols
46
- 9. lsp_get_diagnostics: Check code errors
47
- 10. lsp_find_references: Find symbol usage
48
- 11. lsp_find_definition: Locate symbol definitions
49
- 12. lsp_prepare_rename: Check rename safety
50
- 13. lsp_validate_edit: Verify code changes
51
- ## Workflow
52
- 1. Analyze: Use read_code and LSP tools
53
- 2. Modify: Make minimal, precise changes
54
- 3. Validate: Verify with LSP tools
55
- 4. Document: Explain non-obvious logic
56
- ## Best Practices
57
- - Verify line ranges carefully
58
- - Preserve existing interfaces
59
- - Test edge cases
60
- - Document changes
114
+ # 角色:高级代码工程师
115
+ 精通安全、精确的代码修改,具有严格的验证流程。
116
+
117
+ ## 核心原则
118
+ 1. 安全第一:绝不破坏现有功能
119
+ 2. 精准工程:最小化、针对性修改
120
+ 3. 完整可追溯:记录所有决策
121
+ 4. 验证驱动:在每个阶段进行验证
122
+
123
+ ## 工具使用协议
124
+ 1. 分析工具:
125
+ - lsp_get_document_symbols:映射代码结构
126
+ - lsp_find_references:理解使用模式
127
+ - lsp_find_definition:追踪实现细节
128
+
129
+ 2. 验证工具:
130
+ - lsp_prepare_rename:安全重构检查
131
+ - lsp_get_diagnostics:修改后检查
132
+
133
+ 3. 系统工具:
134
+ - execute_shell:用于git操作和grep搜索
135
+ - ask_codebase:查询代码知识库
136
+ - search_web:技术参考查找
137
+
138
+ ## 工作流程(PDCA循环)
139
+ 1. 计划:
140
+ - 使用ask_user分析需求
141
+ - 使用LSP工具映射现有代码
142
+ - 使用find_references识别影响区域
143
+ - 使用git创建回滚计划
144
+
145
+ 2. 执行:
146
+ - 在受保护的块中进行原子修改
147
+ - 每次更改后自动运行lsp_get_diagnostics
148
+ - 如果发现错误,使用lsp_find_references和lsp_find_definition进行即时修复
149
+ - 每次更改后使用LSP验证语法
150
+
151
+ 3. 检查:
152
+ - 强制使用lsp_get_diagnostics进行完整诊断报告
153
+ - 使用lsp_preprepare_rename验证所有重命名
154
+ - 如果检测到错误,进入修复循环直到所有检查通过
155
+
156
+ 4. 行动:
157
+ - 使用git提交详细消息
158
+ - 准备回滚脚本(如果需要)
159
+ - 进行实施后审查
160
+
161
+ ## 代码修改标准
162
+ 1. 修改前要求:
163
+ - 完整的代码分析报告
164
+ - 影响评估矩阵
165
+ - 回滚程序文档
166
+
167
+ 2. 修改实施:
168
+ - 单一职责修改
169
+ - 严格的代码范围验证(±3行缓冲区)
170
+ - 接口兼容性检查
171
+
172
+ 3. 验证清单:
173
+ [ ] 执行lsp_get_diagnostics并确保零错误
174
+ [ ] 使用lsp_find_references确认影响范围
175
+ [ ] 使用lsp_prepare_rename验证重命名安全性
176
+
177
+ 4. 修改后:
178
+ - 代码审查模拟
179
+ - 版本控制审计
180
+ - 更新变更日志
181
+
182
+ ## 关键要求
183
+ 1. 强制分析:
184
+ - 修改前完整符号追踪
185
+ - 跨文件影响分析
186
+ - 依赖关系映射
187
+
188
+ 2. 禁止操作:
189
+ - 未通过lsp_get_diagnostics检查继续操作
190
+ - 多个功能组合修改
191
+ - 未经测试的接口修改
192
+
193
+ 3. 紧急协议:
194
+ - lsp_get_diagnostics出现错误时立即停止并回滚
195
+ - 出现意外行为时通知用户
196
+ - 对任何回归进行事后分析
61
197
  """
62
198
  self.agent = Agent(system_prompt=code_system_prompt,
63
199
  name="CodeAgent",
@@ -67,7 +203,7 @@ Expert in precise code modifications with proper tool usage.
67
203
  output_handler=[tool_registry, PatchOutputHandler()],
68
204
  platform=PlatformRegistry().get_codegen_platform(),
69
205
  record_methodology=False,
70
- input_handler=[file_input_handler],
206
+ input_handler=[shell_input_handler, file_input_handler],
71
207
  need_summary=False)
72
208
 
73
209
 
@@ -95,22 +231,32 @@ Expert in precise code modifications with proper tool usage.
95
231
  self._init_env()
96
232
  start_commit = get_latest_commit_hash()
97
233
 
98
-
99
- self.agent.run(user_input)
234
+ try:
235
+ self.agent.run(user_input)
236
+ except Exception as e:
237
+ PrettyOutput.print(f"执行失败: {str(e)}", OutputType.WARNING)
100
238
 
101
239
  end_commit = get_latest_commit_hash()
102
240
  # Print commit history between start and end commits
103
- commits = get_commits_between(start_commit, end_commit)
241
+ if start_commit and end_commit:
242
+ commits = get_commits_between(start_commit, end_commit)
243
+ else:
244
+ commits = []
245
+
104
246
  if commits:
105
247
  commit_messages = "检测到以下提交记录:\n" + "\n".join([f"- {commit_hash[:7]}: {message}" for commit_hash, message in commits])
106
248
  PrettyOutput.print(commit_messages, OutputType.INFO)
107
-
108
- if start_commit and end_commit and start_commit != end_commit and user_confirm("检测到多个提交,是否要合并为一个更清晰的提交记录?", True):
109
- # Reset to start commit
110
- subprocess.run(["git", "reset", "--soft", start_commit], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
111
- # Create new commit
112
- git_commiter = GitCommitTool()
113
- git_commiter.execute({})
249
+
250
+ if commits and user_confirm("是否接受以上提交记录?", True):
251
+ if len(commits) > 1 and user_confirm("是否要合并为一个更清晰的提交记录?", True):
252
+ # Reset to start commit
253
+ subprocess.run(["git", "reset", "--soft", start_commit], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
254
+ # Create new commit
255
+ git_commiter = GitCommitTool()
256
+ git_commiter.execute({})
257
+ elif start_commit:
258
+ os.system(f"git reset --hard {start_commit}")
259
+ PrettyOutput.print("已重置到初始提交", OutputType.INFO)
114
260
 
115
261
  except Exception as e:
116
262
  return f"Error during execution: {str(e)}"
@@ -146,4 +292,4 @@ def main():
146
292
  return 0
147
293
 
148
294
  if __name__ == "__main__":
149
- exit(main())
295
+ exit(main())
@@ -1,28 +1,15 @@
1
1
  import os
2
2
  import re
3
- from typing import Any, Dict, List
3
+ from typing import Dict, List
4
4
  from prompt_toolkit import PromptSession
5
5
  from prompt_toolkit.completion import Completer, Completion
6
- from jarvis.jarvis_tools.read_code import ReadCodeTool
7
- from jarvis.jarvis_utils import OutputType, PrettyOutput, get_single_line_input, user_confirm
6
+
7
+ from jarvis.jarvis_utils.input import get_single_line_input
8
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
9
+ from jarvis.jarvis_utils.utils import user_confirm
8
10
 
9
11
 
10
12
  def _parse_file_selection(input_str: str, max_index: int) -> List[int]:
11
- """Parse file selection expression
12
-
13
- Supported formats:
14
- - Single number: "1"
15
- - Comma-separated: "1,3,5"
16
- - Range: "1-5"
17
- - Combination: "1,3-5,7"
18
-
19
- Args:
20
- input_str: User input selection expression
21
- max_index: Maximum selectable index
22
-
23
- Returns:
24
- List[int]: Selected index list (starting from 0)
25
- """
26
13
  selected = set()
27
14
 
28
15
  # Remove all whitespace characters
@@ -205,7 +192,7 @@ def select_files(related_files: List[Dict[str, str]], root_dir: str) -> List[Dic
205
192
  continue
206
193
 
207
194
  try:
208
- selected_files.append({"file": path, "reason": "User Added"})
195
+ selected_files.append({"file": path, "reason": "I Added"})
209
196
  tips += f"\n文件已添加: {path}"
210
197
  except Exception as e:
211
198
  tips += f"\n读取文件失败: {str(e)}"