jarvis-ai-assistant 0.1.128__py3-none-any.whl → 0.1.130__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 +26 -31
- jarvis/jarvis_agent/main.py +77 -0
- jarvis/jarvis_c2rust/c2rust.yaml +734 -0
- jarvis/jarvis_code_agent/builtin_input_handler.py +43 -0
- jarvis/jarvis_code_agent/code_agent.py +82 -156
- jarvis/jarvis_code_agent/file_input_handler.py +88 -0
- jarvis/jarvis_code_agent/patch.py +262 -80
- jarvis/jarvis_code_agent/shell_input_handler.py +8 -2
- jarvis/jarvis_dev/main.py +832 -740
- jarvis/jarvis_multi_agent/__init__.py +113 -92
- jarvis/jarvis_platform/registry.py +0 -1
- jarvis/jarvis_tools/create_sub_agent.py +1 -8
- jarvis/jarvis_tools/git_commiter.py +2 -1
- jarvis/jarvis_tools/read_code.py +143 -0
- jarvis/jarvis_tools/registry.py +35 -39
- jarvis/jarvis_tools/tool_generator.py +45 -17
- jarvis/jarvis_utils/__init__.py +17 -17
- jarvis/jarvis_utils/config.py +87 -51
- jarvis/jarvis_utils/embedding.py +49 -48
- jarvis/jarvis_utils/git_utils.py +34 -34
- jarvis/jarvis_utils/globals.py +26 -26
- jarvis/jarvis_utils/input.py +61 -45
- jarvis/jarvis_utils/methodology.py +22 -22
- jarvis/jarvis_utils/output.py +64 -64
- jarvis/jarvis_utils/utils.py +2 -2
- {jarvis_ai_assistant-0.1.128.dist-info → jarvis_ai_assistant-0.1.130.dist-info}/METADATA +1 -1
- {jarvis_ai_assistant-0.1.128.dist-info → jarvis_ai_assistant-0.1.130.dist-info}/RECORD +32 -27
- {jarvis_ai_assistant-0.1.128.dist-info → jarvis_ai_assistant-0.1.130.dist-info}/entry_points.txt +2 -0
- {jarvis_ai_assistant-0.1.128.dist-info → jarvis_ai_assistant-0.1.130.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.128.dist-info → jarvis_ai_assistant-0.1.130.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.128.dist-info → jarvis_ai_assistant-0.1.130.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Any, Tuple
|
|
3
|
+
|
|
4
|
+
from jarvis.jarvis_utils.output import PrettyOutput, OutputType
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def builtin_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
|
|
8
|
+
"""
|
|
9
|
+
处理内置的特殊输入标记,并追加相应的提示词
|
|
10
|
+
|
|
11
|
+
参数:
|
|
12
|
+
user_input: 用户输入
|
|
13
|
+
agent: 代理对象
|
|
14
|
+
|
|
15
|
+
返回:
|
|
16
|
+
Tuple[str, bool]: 处理后的输入和是否需要进一步处理
|
|
17
|
+
"""
|
|
18
|
+
# 查找特殊标记
|
|
19
|
+
special_tags = re.findall(r"'<([^>]+)>'", user_input)
|
|
20
|
+
|
|
21
|
+
if not special_tags:
|
|
22
|
+
return user_input, False
|
|
23
|
+
|
|
24
|
+
# 使用集合去重
|
|
25
|
+
processed_tags = set()
|
|
26
|
+
# 处理每个标记
|
|
27
|
+
for tag in special_tags:
|
|
28
|
+
if tag in processed_tags:
|
|
29
|
+
continue
|
|
30
|
+
processed_tags.add(tag)
|
|
31
|
+
|
|
32
|
+
if tag == "CodeBase":
|
|
33
|
+
user_input = user_input.replace(f"'<{tag}>'", "")
|
|
34
|
+
user_input += "\n请使用ask_codebase工具查询代码库"
|
|
35
|
+
elif tag == "Web":
|
|
36
|
+
user_input = user_input.replace(f"'<{tag}>'", "")
|
|
37
|
+
user_input += "\n请使用search_web工具进行网页搜索"
|
|
38
|
+
elif tag == "RAG":
|
|
39
|
+
user_input = user_input.replace(f"'<{tag}>'", "")
|
|
40
|
+
user_input += "\n请使用rag工具进行知识库检索"
|
|
41
|
+
# 移除对未知标记的警告输出
|
|
42
|
+
|
|
43
|
+
return user_input, False
|
|
@@ -6,6 +6,8 @@ from typing import Any, Tuple
|
|
|
6
6
|
from yaspin import yaspin
|
|
7
7
|
|
|
8
8
|
from jarvis.jarvis_agent import Agent
|
|
9
|
+
from jarvis.jarvis_code_agent.builtin_input_handler import builtin_input_handler
|
|
10
|
+
from jarvis.jarvis_code_agent.file_input_handler import file_input_handler
|
|
9
11
|
from jarvis.jarvis_code_agent.shell_input_handler import shell_input_handler
|
|
10
12
|
from jarvis.jarvis_code_agent.patch import PatchOutputHandler
|
|
11
13
|
from jarvis.jarvis_platform.registry import PlatformRegistry
|
|
@@ -21,83 +23,6 @@ from jarvis.jarvis_utils.utils import init_env, user_confirm
|
|
|
21
23
|
|
|
22
24
|
|
|
23
25
|
|
|
24
|
-
def file_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
|
|
25
|
-
prompt = user_input
|
|
26
|
-
files = []
|
|
27
|
-
|
|
28
|
-
file_refs = re.findall(r"'([^']+)'", user_input)
|
|
29
|
-
for ref in file_refs:
|
|
30
|
-
# Handle file:start,end or file:start:end format
|
|
31
|
-
if ':' in ref:
|
|
32
|
-
file_path, line_range = ref.split(':', 1)
|
|
33
|
-
# Initialize with default values
|
|
34
|
-
start_line = 1 # 1-based
|
|
35
|
-
end_line = -1
|
|
36
|
-
|
|
37
|
-
# Process line range if specified
|
|
38
|
-
if ',' in line_range or ':' in line_range:
|
|
39
|
-
try:
|
|
40
|
-
raw_start, raw_end = map(int, re.split(r'[,:]', line_range))
|
|
41
|
-
|
|
42
|
-
# Handle special values and Python-style negative indices
|
|
43
|
-
try:
|
|
44
|
-
with open(file_path, 'r', encoding='utf-8') as f:
|
|
45
|
-
total_lines = len(f.readlines())
|
|
46
|
-
except FileNotFoundError:
|
|
47
|
-
PrettyOutput.print(f"文件不存在: {file_path}", OutputType.WARNING)
|
|
48
|
-
continue
|
|
49
|
-
# Process start line
|
|
50
|
-
if raw_start == 0: # 0表示整个文件
|
|
51
|
-
start_line = 1
|
|
52
|
-
end_line = total_lines
|
|
53
|
-
else:
|
|
54
|
-
start_line = raw_start if raw_start > 0 else total_lines + raw_start + 1
|
|
55
|
-
|
|
56
|
-
# Process end line
|
|
57
|
-
if raw_end == 0: # 0表示整个文件(如果start也是0)
|
|
58
|
-
end_line = total_lines
|
|
59
|
-
else:
|
|
60
|
-
end_line = raw_end if raw_end > 0 else total_lines + raw_end + 1
|
|
61
|
-
|
|
62
|
-
# Auto-correct ranges
|
|
63
|
-
start_line = max(1, min(start_line, total_lines))
|
|
64
|
-
end_line = max(start_line, min(end_line, total_lines))
|
|
65
|
-
|
|
66
|
-
# Final validation
|
|
67
|
-
if start_line < 1 or end_line > total_lines or start_line > end_line:
|
|
68
|
-
raise ValueError
|
|
69
|
-
|
|
70
|
-
except:
|
|
71
|
-
continue
|
|
72
|
-
|
|
73
|
-
# Add file if it exists
|
|
74
|
-
if os.path.isfile(file_path):
|
|
75
|
-
files.append({
|
|
76
|
-
"path": file_path,
|
|
77
|
-
"start_line": start_line,
|
|
78
|
-
"end_line": end_line
|
|
79
|
-
})
|
|
80
|
-
else:
|
|
81
|
-
# Handle simple file path
|
|
82
|
-
if os.path.isfile(ref):
|
|
83
|
-
files.append({
|
|
84
|
-
"path": ref,
|
|
85
|
-
"start_line": 1, # 1-based
|
|
86
|
-
"end_line": -1
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
# Read and process files if any were found
|
|
90
|
-
if files:
|
|
91
|
-
with yaspin(text="正在读取文件...", color="cyan") as spinner:
|
|
92
|
-
result = FileOperationTool().execute({"operation":"read","files": files})
|
|
93
|
-
if result["success"]:
|
|
94
|
-
spinner.text = "文件读取完成"
|
|
95
|
-
spinner.ok("✅")
|
|
96
|
-
return result["stdout"] + "\n" + prompt, False
|
|
97
|
-
|
|
98
|
-
return prompt, False
|
|
99
|
-
|
|
100
|
-
|
|
101
26
|
|
|
102
27
|
class CodeAgent:
|
|
103
28
|
def __init__(self):
|
|
@@ -116,89 +41,91 @@ class CodeAgent:
|
|
|
116
41
|
"lsp_prepare_rename"
|
|
117
42
|
])
|
|
118
43
|
code_system_prompt = """
|
|
119
|
-
#
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
- 准备回滚脚本(如果需要)
|
|
164
|
-
- 进行实施后审查
|
|
165
|
-
|
|
166
|
-
## 代码修改标准
|
|
167
|
-
1. 修改前要求:
|
|
44
|
+
# 专业代码工程师
|
|
45
|
+
|
|
46
|
+
## 身份与能力范围
|
|
47
|
+
- **角色定位**:精通精确、安全代码修改的高级代码工程师
|
|
48
|
+
- **核心能力**:代码分析、精准重构和系统化验证
|
|
49
|
+
- **知识领域**:软件架构、设计模式和特定语言的最佳实践
|
|
50
|
+
- **局限性**:复杂系统和特定领域知识需要明确的上下文支持
|
|
51
|
+
|
|
52
|
+
## 交互原则与策略
|
|
53
|
+
- **沟通风格**:清晰简洁的技术解释,为所有决策提供合理依据
|
|
54
|
+
- **呈现格式**:使用补丁格式展示结构化的代码变更及其上下文
|
|
55
|
+
- **主动引导**:在有益的情况下,提出超出即时需求的改进建议
|
|
56
|
+
- **特殊场景应对**:
|
|
57
|
+
- 对于模糊请求:在继续前提出澄清问题
|
|
58
|
+
- 对于高风险变更:提出带有验证步骤的渐进式方法
|
|
59
|
+
- 对于性能问题:平衡即时修复与长期架构考量
|
|
60
|
+
|
|
61
|
+
## 任务执行规范
|
|
62
|
+
### 分析阶段
|
|
63
|
+
- 使用lsp_get_document_symbols映射代码结构
|
|
64
|
+
- 通过lsp_find_references和lsp_find_definition追踪依赖关系
|
|
65
|
+
- 在进行更改前识别潜在影响区域
|
|
66
|
+
- 为安全创建回滚计划
|
|
67
|
+
|
|
68
|
+
### 实施阶段
|
|
69
|
+
- 进行原子化、聚焦的最小范围更改
|
|
70
|
+
- 保持一致的代码风格和格式
|
|
71
|
+
- 每次重大更改后运行lsp_get_diagnostics
|
|
72
|
+
- 立即修复任何检测到的问题
|
|
73
|
+
|
|
74
|
+
### 验证阶段
|
|
75
|
+
- 使用lsp_get_diagnostics进行全面诊断
|
|
76
|
+
- 用lsp_prepare_rename验证所有重命名元素
|
|
77
|
+
- 检查相关代码中的意外副作用
|
|
78
|
+
- 确保必要的向后兼容性
|
|
79
|
+
|
|
80
|
+
### 文档阶段
|
|
81
|
+
- 为每项修改提供清晰的理由
|
|
82
|
+
- 在所有补丁描述中包含上下文
|
|
83
|
+
- 记录任何假设或约束条件
|
|
84
|
+
- 准备详细的提交信息
|
|
85
|
+
|
|
86
|
+
## 代码修改协议
|
|
87
|
+
1. **修改前要求**:
|
|
168
88
|
- 完整的代码分析报告
|
|
169
|
-
-
|
|
170
|
-
-
|
|
89
|
+
- 影响评估
|
|
90
|
+
- 验证策略
|
|
171
91
|
|
|
172
|
-
2.
|
|
173
|
-
-
|
|
174
|
-
-
|
|
92
|
+
2. **修改实施**:
|
|
93
|
+
- 单一职责变更
|
|
94
|
+
- 严格的范围验证
|
|
175
95
|
- 接口兼容性检查
|
|
176
96
|
|
|
177
|
-
3.
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
97
|
+
3. **验证清单**:
|
|
98
|
+
- 运行lsp_get_diagnostics确保零错误
|
|
99
|
+
- 使用lsp_find_references确认影响范围
|
|
100
|
+
- 用lsp_prepare_rename验证重命名安全性
|
|
181
101
|
|
|
182
|
-
4.
|
|
102
|
+
4. **修改后流程**:
|
|
183
103
|
- 代码审查模拟
|
|
184
104
|
- 版本控制审计
|
|
185
|
-
-
|
|
186
|
-
|
|
187
|
-
##
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
105
|
+
- 更新变更文档
|
|
106
|
+
|
|
107
|
+
## 工具使用指南
|
|
108
|
+
- **分析工具**:
|
|
109
|
+
- lsp_get_document_symbols:用于映射代码结构
|
|
110
|
+
- lsp_find_references:用于理解使用模式
|
|
111
|
+
- lsp_find_definition:用于追踪实现细节
|
|
112
|
+
|
|
113
|
+
- **验证工具**:
|
|
114
|
+
- lsp_prepare_rename:用于安全重构检查
|
|
115
|
+
- lsp_get_diagnostics:用于修改后检查
|
|
116
|
+
|
|
117
|
+
- **系统工具**:
|
|
118
|
+
- execute_shell:用于git操作和grep搜索
|
|
119
|
+
- ask_codebase:用于查询代码知识库
|
|
120
|
+
- search_web:用于技术参考查找
|
|
121
|
+
|
|
122
|
+
## 补丁格式要求
|
|
123
|
+
创建代码补丁时:
|
|
124
|
+
1. 包含足够的上下文(更改前后各3行)
|
|
125
|
+
2. 保留原始缩进和格式
|
|
126
|
+
3. 为新文件提供完整代码
|
|
127
|
+
4. 对于修改,保留周围未更改的代码
|
|
128
|
+
5. 为每项更改包含清晰的理由说明
|
|
202
129
|
"""
|
|
203
130
|
self.agent = Agent(system_prompt=code_system_prompt,
|
|
204
131
|
name="CodeAgent",
|
|
@@ -208,7 +135,7 @@ class CodeAgent:
|
|
|
208
135
|
output_handler=[tool_registry, PatchOutputHandler()],
|
|
209
136
|
platform=PlatformRegistry().get_codegen_platform(),
|
|
210
137
|
record_methodology=False,
|
|
211
|
-
input_handler=[shell_input_handler, file_input_handler],
|
|
138
|
+
input_handler=[shell_input_handler, file_input_handler, builtin_input_handler],
|
|
212
139
|
need_summary=False)
|
|
213
140
|
|
|
214
141
|
|
|
@@ -222,8 +149,7 @@ class CodeAgent:
|
|
|
222
149
|
with spinner.hidden():
|
|
223
150
|
git_commiter = GitCommitTool()
|
|
224
151
|
git_commiter.execute({})
|
|
225
|
-
|
|
226
|
-
spinner.text = "环境初始化完成"
|
|
152
|
+
spinner.text = "环境初始化完成"
|
|
227
153
|
spinner.ok("✅")
|
|
228
154
|
|
|
229
155
|
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import re
|
|
5
|
+
from typing import Any, Tuple
|
|
6
|
+
|
|
7
|
+
from yaspin import yaspin
|
|
8
|
+
|
|
9
|
+
from jarvis.jarvis_tools.file_operation import FileOperationTool
|
|
10
|
+
from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def file_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
|
|
14
|
+
prompt = user_input
|
|
15
|
+
files = []
|
|
16
|
+
|
|
17
|
+
file_refs = re.findall(r"'([^']+)'", user_input)
|
|
18
|
+
for ref in file_refs:
|
|
19
|
+
# Handle file:start,end or file:start:end format
|
|
20
|
+
if ':' in ref:
|
|
21
|
+
file_path, line_range = ref.split(':', 1)
|
|
22
|
+
# Initialize with default values
|
|
23
|
+
start_line = 1 # 1-based
|
|
24
|
+
end_line = -1
|
|
25
|
+
|
|
26
|
+
# Process line range if specified
|
|
27
|
+
if ',' in line_range or ':' in line_range:
|
|
28
|
+
try:
|
|
29
|
+
raw_start, raw_end = map(int, re.split(r'[,:]', line_range))
|
|
30
|
+
|
|
31
|
+
# Handle special values and Python-style negative indices
|
|
32
|
+
try:
|
|
33
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
34
|
+
total_lines = len(f.readlines())
|
|
35
|
+
except FileNotFoundError:
|
|
36
|
+
PrettyOutput.print(f"文件不存在: {file_path}", OutputType.WARNING)
|
|
37
|
+
continue
|
|
38
|
+
# Process start line
|
|
39
|
+
if raw_start == 0: # 0表示整个文件
|
|
40
|
+
start_line = 1
|
|
41
|
+
end_line = total_lines
|
|
42
|
+
else:
|
|
43
|
+
start_line = raw_start if raw_start > 0 else total_lines + raw_start + 1
|
|
44
|
+
|
|
45
|
+
# Process end line
|
|
46
|
+
if raw_end == 0: # 0表示整个文件(如果start也是0)
|
|
47
|
+
end_line = total_lines
|
|
48
|
+
else:
|
|
49
|
+
end_line = raw_end if raw_end > 0 else total_lines + raw_end + 1
|
|
50
|
+
|
|
51
|
+
# Auto-correct ranges
|
|
52
|
+
start_line = max(1, min(start_line, total_lines))
|
|
53
|
+
end_line = max(start_line, min(end_line, total_lines))
|
|
54
|
+
|
|
55
|
+
# Final validation
|
|
56
|
+
if start_line < 1 or end_line > total_lines or start_line > end_line:
|
|
57
|
+
raise ValueError
|
|
58
|
+
|
|
59
|
+
except:
|
|
60
|
+
continue
|
|
61
|
+
|
|
62
|
+
# Add file if it exists
|
|
63
|
+
if os.path.isfile(file_path):
|
|
64
|
+
files.append({
|
|
65
|
+
"path": file_path,
|
|
66
|
+
"start_line": start_line,
|
|
67
|
+
"end_line": end_line
|
|
68
|
+
})
|
|
69
|
+
else:
|
|
70
|
+
# Handle simple file path
|
|
71
|
+
if os.path.isfile(ref):
|
|
72
|
+
files.append({
|
|
73
|
+
"path": ref,
|
|
74
|
+
"start_line": 1, # 1-based
|
|
75
|
+
"end_line": -1
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
# Read and process files if any were found
|
|
79
|
+
if files:
|
|
80
|
+
with yaspin(text="正在读取文件...", color="cyan") as spinner:
|
|
81
|
+
result = FileOperationTool().execute({"operation":"read","files": files})
|
|
82
|
+
if result["success"]:
|
|
83
|
+
spinner.text = "文件读取完成"
|
|
84
|
+
spinner.ok("✅")
|
|
85
|
+
return result["stdout"] + "\n" + prompt, False
|
|
86
|
+
|
|
87
|
+
return prompt, False
|
|
88
|
+
|