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.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +134 -136
- jarvis/jarvis_code_agent/code_agent.py +198 -52
- jarvis/jarvis_code_agent/file_select.py +6 -19
- jarvis/jarvis_code_agent/patch.py +183 -312
- jarvis/jarvis_code_agent/shell_input_handler.py +22 -0
- jarvis/jarvis_codebase/main.py +89 -86
- jarvis/jarvis_dev/main.py +695 -715
- jarvis/jarvis_git_squash/__init__.py +0 -0
- jarvis/jarvis_git_squash/main.py +81 -0
- jarvis/jarvis_lsp/base.py +0 -12
- jarvis/jarvis_lsp/cpp.py +1 -10
- jarvis/jarvis_lsp/go.py +1 -10
- jarvis/jarvis_lsp/python.py +0 -28
- jarvis/jarvis_lsp/registry.py +2 -3
- jarvis/jarvis_lsp/rust.py +1 -10
- jarvis/jarvis_multi_agent/__init__.py +53 -53
- jarvis/jarvis_platform/ai8.py +2 -1
- jarvis/jarvis_platform/base.py +19 -24
- jarvis/jarvis_platform/kimi.py +2 -3
- jarvis/jarvis_platform/ollama.py +3 -1
- jarvis/jarvis_platform/openai.py +1 -1
- jarvis/jarvis_platform/oyi.py +2 -1
- jarvis/jarvis_platform/registry.py +2 -1
- jarvis/jarvis_platform_manager/main.py +4 -6
- jarvis/jarvis_platform_manager/openai_test.py +0 -1
- jarvis/jarvis_rag/main.py +5 -2
- jarvis/jarvis_smart_shell/main.py +9 -4
- jarvis/jarvis_tools/ask_codebase.py +18 -13
- jarvis/jarvis_tools/ask_user.py +5 -4
- jarvis/jarvis_tools/base.py +22 -8
- jarvis/jarvis_tools/chdir.py +8 -9
- jarvis/jarvis_tools/code_review.py +19 -20
- jarvis/jarvis_tools/create_code_agent.py +6 -6
- jarvis/jarvis_tools/create_sub_agent.py +9 -9
- jarvis/jarvis_tools/execute_shell.py +55 -20
- jarvis/jarvis_tools/execute_shell_script.py +7 -7
- jarvis/jarvis_tools/file_operation.py +39 -10
- jarvis/jarvis_tools/git_commiter.py +20 -17
- jarvis/jarvis_tools/lsp_find_definition.py +8 -8
- jarvis/jarvis_tools/lsp_find_references.py +1 -1
- jarvis/jarvis_tools/lsp_get_diagnostics.py +19 -11
- jarvis/jarvis_tools/lsp_get_document_symbols.py +1 -1
- jarvis/jarvis_tools/lsp_prepare_rename.py +8 -8
- jarvis/jarvis_tools/methodology.py +10 -7
- jarvis/jarvis_tools/rag.py +27 -20
- jarvis/jarvis_tools/read_webpage.py +4 -3
- jarvis/jarvis_tools/registry.py +143 -140
- jarvis/jarvis_tools/{search.py → search_web.py} +10 -7
- jarvis/jarvis_tools/select_code_files.py +4 -4
- jarvis/jarvis_tools/tool_generator.py +33 -34
- jarvis/jarvis_utils/__init__.py +19 -982
- jarvis/jarvis_utils/config.py +138 -0
- jarvis/jarvis_utils/embedding.py +201 -0
- jarvis/jarvis_utils/git_utils.py +120 -0
- jarvis/jarvis_utils/globals.py +82 -0
- jarvis/jarvis_utils/input.py +161 -0
- jarvis/jarvis_utils/methodology.py +128 -0
- jarvis/jarvis_utils/output.py +235 -0
- jarvis/jarvis_utils/utils.py +150 -0
- jarvis_ai_assistant-0.1.126.dist-info/METADATA +305 -0
- jarvis_ai_assistant-0.1.126.dist-info/RECORD +74 -0
- {jarvis_ai_assistant-0.1.124.dist-info → jarvis_ai_assistant-0.1.126.dist-info}/WHEEL +1 -1
- {jarvis_ai_assistant-0.1.124.dist-info → jarvis_ai_assistant-0.1.126.dist-info}/entry_points.txt +1 -0
- jarvis/jarvis_tools/lsp_validate_edit.py +0 -141
- jarvis/jarvis_tools/read_code.py +0 -191
- jarvis_ai_assistant-0.1.124.dist-info/METADATA +0 -460
- jarvis_ai_assistant-0.1.124.dist-info/RECORD +0 -65
- {jarvis_ai_assistant-0.1.124.dist-info → jarvis_ai_assistant-0.1.126.dist-info}/LICENSE +0 -0
- {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
|
|
4
|
+
from typing import Any, Tuple
|
|
4
5
|
|
|
5
6
|
from jarvis.jarvis_agent import Agent
|
|
6
|
-
from jarvis.jarvis_code_agent.
|
|
7
|
-
from jarvis.jarvis_code_agent.patch import PatchOutputHandler
|
|
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.
|
|
12
|
-
from jarvis.jarvis_utils import
|
|
13
|
-
from jarvis.jarvis_utils import OutputType, PrettyOutput
|
|
14
|
-
from jarvis.jarvis_utils import
|
|
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(["
|
|
22
|
-
"execute_shell",
|
|
101
|
+
tool_registry.use_tools(["execute_shell",
|
|
23
102
|
"execute_shell_script",
|
|
24
|
-
"
|
|
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
|
-
|
|
111
|
+
"lsp_prepare_rename"
|
|
112
|
+
])
|
|
34
113
|
code_system_prompt = """
|
|
35
|
-
#
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
3.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
|
3
|
+
from typing import Dict, List
|
|
4
4
|
from prompt_toolkit import PromptSession
|
|
5
5
|
from prompt_toolkit.completion import Completer, Completion
|
|
6
|
-
|
|
7
|
-
from jarvis.jarvis_utils import
|
|
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": "
|
|
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)}"
|