jarvis-ai-assistant 0.1.132__py3-none-any.whl → 0.1.138__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 +330 -347
- jarvis/jarvis_agent/builtin_input_handler.py +16 -6
- jarvis/jarvis_agent/file_input_handler.py +9 -9
- jarvis/jarvis_agent/jarvis.py +143 -0
- jarvis/jarvis_agent/main.py +12 -13
- jarvis/jarvis_agent/output_handler.py +3 -3
- jarvis/jarvis_agent/patch.py +92 -64
- jarvis/jarvis_agent/shell_input_handler.py +5 -3
- jarvis/jarvis_code_agent/code_agent.py +263 -177
- jarvis/jarvis_code_agent/file_select.py +24 -24
- jarvis/jarvis_dev/main.py +45 -59
- jarvis/jarvis_git_details/__init__.py +0 -0
- jarvis/jarvis_git_details/main.py +179 -0
- jarvis/jarvis_git_squash/main.py +7 -7
- jarvis/jarvis_lsp/base.py +11 -53
- jarvis/jarvis_lsp/cpp.py +13 -28
- jarvis/jarvis_lsp/go.py +13 -28
- jarvis/jarvis_lsp/python.py +8 -27
- jarvis/jarvis_lsp/registry.py +21 -83
- jarvis/jarvis_lsp/rust.py +15 -30
- jarvis/jarvis_methodology/main.py +101 -0
- jarvis/jarvis_multi_agent/__init__.py +10 -51
- jarvis/jarvis_multi_agent/main.py +43 -0
- jarvis/jarvis_platform/__init__.py +1 -1
- jarvis/jarvis_platform/ai8.py +67 -89
- jarvis/jarvis_platform/base.py +14 -13
- jarvis/jarvis_platform/kimi.py +25 -28
- jarvis/jarvis_platform/ollama.py +24 -26
- jarvis/jarvis_platform/openai.py +15 -19
- jarvis/jarvis_platform/oyi.py +48 -50
- jarvis/jarvis_platform/registry.py +29 -44
- jarvis/jarvis_platform/yuanbao.py +39 -43
- jarvis/jarvis_platform_manager/main.py +81 -81
- jarvis/jarvis_platform_manager/openai_test.py +21 -21
- jarvis/jarvis_rag/file_processors.py +18 -18
- jarvis/jarvis_rag/main.py +262 -278
- jarvis/jarvis_smart_shell/main.py +12 -12
- jarvis/jarvis_tools/ask_codebase.py +85 -78
- jarvis/jarvis_tools/ask_user.py +8 -8
- jarvis/jarvis_tools/base.py +4 -4
- jarvis/jarvis_tools/chdir.py +9 -9
- jarvis/jarvis_tools/code_review.py +40 -21
- jarvis/jarvis_tools/create_code_agent.py +15 -15
- jarvis/jarvis_tools/create_sub_agent.py +0 -1
- jarvis/jarvis_tools/execute_python_script.py +3 -3
- jarvis/jarvis_tools/execute_shell.py +11 -11
- jarvis/jarvis_tools/execute_shell_script.py +3 -3
- jarvis/jarvis_tools/file_analyzer.py +116 -105
- jarvis/jarvis_tools/file_operation.py +22 -20
- jarvis/jarvis_tools/find_caller.py +105 -40
- jarvis/jarvis_tools/find_methodolopy.py +65 -0
- jarvis/jarvis_tools/find_symbol.py +123 -39
- jarvis/jarvis_tools/function_analyzer.py +140 -57
- jarvis/jarvis_tools/git_commiter.py +10 -10
- jarvis/jarvis_tools/lsp_get_diagnostics.py +19 -19
- jarvis/jarvis_tools/methodology.py +22 -67
- jarvis/jarvis_tools/project_analyzer.py +137 -53
- jarvis/jarvis_tools/rag.py +15 -20
- jarvis/jarvis_tools/read_code.py +25 -23
- jarvis/jarvis_tools/read_webpage.py +31 -31
- jarvis/jarvis_tools/registry.py +72 -52
- jarvis/jarvis_tools/search_web.py +23 -353
- jarvis/jarvis_tools/tool_generator.py +19 -19
- jarvis/jarvis_utils/config.py +36 -96
- jarvis/jarvis_utils/embedding.py +83 -83
- jarvis/jarvis_utils/git_utils.py +20 -20
- jarvis/jarvis_utils/globals.py +18 -6
- jarvis/jarvis_utils/input.py +10 -9
- jarvis/jarvis_utils/methodology.py +141 -140
- jarvis/jarvis_utils/output.py +13 -13
- jarvis/jarvis_utils/utils.py +23 -71
- {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/METADATA +6 -15
- jarvis_ai_assistant-0.1.138.dist-info/RECORD +85 -0
- {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/entry_points.txt +4 -3
- jarvis/jarvis_tools/lsp_find_definition.py +0 -150
- jarvis/jarvis_tools/lsp_find_references.py +0 -127
- jarvis/jarvis_tools/select_code_files.py +0 -62
- jarvis_ai_assistant-0.1.132.dist-info/RECORD +0 -82
- {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.132.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/top_level.txt +0 -0
|
@@ -11,7 +11,7 @@ class FunctionAnalyzerTool:
|
|
|
11
11
|
函数分析工具
|
|
12
12
|
使用agent深入分析函数内部实现,包括子函数调用、全局变量使用等
|
|
13
13
|
"""
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
name = "function_analyzer"
|
|
16
16
|
description = "深入分析函数内部实现,查找子函数调用、全局变量使用等详细信息"
|
|
17
17
|
parameters = {
|
|
@@ -60,20 +60,20 @@ class FunctionAnalyzerTool:
|
|
|
60
60
|
},
|
|
61
61
|
"required": ["function_name"]
|
|
62
62
|
}
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
65
65
|
"""
|
|
66
66
|
执行函数分析工具
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
Args:
|
|
69
69
|
args: 包含参数的字典
|
|
70
|
-
|
|
70
|
+
|
|
71
71
|
Returns:
|
|
72
72
|
包含执行结果的字典
|
|
73
73
|
"""
|
|
74
74
|
# 存储原始目录
|
|
75
75
|
original_dir = os.getcwd()
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
try:
|
|
78
78
|
# 解析参数
|
|
79
79
|
function_name = args.get("function_name", "")
|
|
@@ -83,7 +83,7 @@ class FunctionAnalyzerTool:
|
|
|
83
83
|
exclude_dirs = args.get("exclude_dirs", [])
|
|
84
84
|
analysis_depth = args.get("analysis_depth", 1)
|
|
85
85
|
objective = args.get("objective", "")
|
|
86
|
-
|
|
86
|
+
|
|
87
87
|
# 验证参数
|
|
88
88
|
if not function_name:
|
|
89
89
|
return {
|
|
@@ -91,50 +91,46 @@ class FunctionAnalyzerTool:
|
|
|
91
91
|
"stdout": "",
|
|
92
92
|
"stderr": "必须提供函数名称"
|
|
93
93
|
}
|
|
94
|
-
|
|
94
|
+
|
|
95
95
|
# 创建agent的system prompt
|
|
96
96
|
system_prompt = self._create_system_prompt(
|
|
97
|
-
function_name, file_path, root_dir,
|
|
97
|
+
function_name, file_path, root_dir,
|
|
98
98
|
file_extensions, exclude_dirs, analysis_depth, objective
|
|
99
99
|
)
|
|
100
|
-
|
|
100
|
+
|
|
101
101
|
# 创建agent的summary prompt
|
|
102
102
|
summary_prompt = self._create_summary_prompt(function_name, analysis_depth)
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
# 切换到根目录
|
|
105
105
|
os.chdir(root_dir)
|
|
106
|
-
|
|
106
|
+
|
|
107
107
|
# 构建使用的工具
|
|
108
108
|
from jarvis.jarvis_tools.registry import ToolRegistry
|
|
109
109
|
tool_registry = ToolRegistry()
|
|
110
110
|
tool_registry.use_tools(["execute_shell", "read_code"])
|
|
111
|
-
|
|
111
|
+
|
|
112
112
|
# 创建并运行agent
|
|
113
113
|
analyzer_agent = Agent(
|
|
114
114
|
system_prompt=system_prompt,
|
|
115
115
|
name=f"FunctionAnalyzer-{function_name}",
|
|
116
116
|
description=f"分析 '{function_name}' 函数的内部实现",
|
|
117
117
|
summary_prompt=summary_prompt,
|
|
118
|
-
platform=PlatformRegistry().
|
|
118
|
+
platform=PlatformRegistry().get_normal_platform(),
|
|
119
119
|
output_handler=[tool_registry],
|
|
120
|
-
need_summary=True,
|
|
121
|
-
is_sub_agent=True,
|
|
122
|
-
use_methodology=False,
|
|
123
|
-
record_methodology=False,
|
|
124
120
|
execute_tool_confirm=False,
|
|
125
121
|
auto_complete=True
|
|
126
122
|
)
|
|
127
|
-
|
|
123
|
+
|
|
128
124
|
# 运行agent并获取结果
|
|
129
125
|
task_input = f"深入分析 '{function_name}' 函数的内部实现,包括子函数调用、全局变量使用等详细信息"
|
|
130
126
|
result = analyzer_agent.run(task_input)
|
|
131
|
-
|
|
127
|
+
|
|
132
128
|
return {
|
|
133
129
|
"success": True,
|
|
134
130
|
"stdout": result,
|
|
135
131
|
"stderr": ""
|
|
136
132
|
}
|
|
137
|
-
|
|
133
|
+
|
|
138
134
|
except Exception as e:
|
|
139
135
|
PrettyOutput.print(str(e), OutputType.ERROR)
|
|
140
136
|
return {
|
|
@@ -145,13 +141,13 @@ class FunctionAnalyzerTool:
|
|
|
145
141
|
finally:
|
|
146
142
|
# 恢复原始目录
|
|
147
143
|
os.chdir(original_dir)
|
|
148
|
-
|
|
149
|
-
def _create_system_prompt(self, function_name: str, file_path: str, root_dir: str,
|
|
144
|
+
|
|
145
|
+
def _create_system_prompt(self, function_name: str, file_path: str, root_dir: str,
|
|
150
146
|
file_extensions: List[str], exclude_dirs: List[str],
|
|
151
147
|
analysis_depth: int, objective: str) -> str:
|
|
152
148
|
"""
|
|
153
149
|
创建Agent的system prompt
|
|
154
|
-
|
|
150
|
+
|
|
155
151
|
Args:
|
|
156
152
|
function_name: 函数名称
|
|
157
153
|
file_path: 函数所在文件路径
|
|
@@ -160,22 +156,39 @@ class FunctionAnalyzerTool:
|
|
|
160
156
|
exclude_dirs: 排除目录列表
|
|
161
157
|
analysis_depth: 子函数分析深度
|
|
162
158
|
objective: 分析目标
|
|
163
|
-
|
|
159
|
+
|
|
164
160
|
Returns:
|
|
165
161
|
系统提示文本
|
|
166
162
|
"""
|
|
167
163
|
file_ext_str = " ".join([f"*{ext}" for ext in file_extensions]) if file_extensions else ""
|
|
168
164
|
exclude_str = " ".join([f"--glob '!{excl}'" for excl in exclude_dirs]) if exclude_dirs else ""
|
|
169
|
-
|
|
165
|
+
|
|
170
166
|
depth_description = "不分析子函数" if analysis_depth == 0 else f"分析 {analysis_depth} 层子函数"
|
|
171
167
|
file_info = f"已知文件路径: {file_path}" if file_path else "需要首先查找函数定义位置"
|
|
172
168
|
objective_text = f"\n\n## 分析目标\n{objective}" if objective else ""
|
|
173
|
-
|
|
169
|
+
|
|
174
170
|
return f"""# 函数实现分析专家
|
|
175
171
|
|
|
176
172
|
## 任务描述
|
|
177
173
|
分析函数 `{function_name}` 的实现,专注于分析目标所需的信息,生成有针对性的函数分析报告。{objective_text}
|
|
178
174
|
|
|
175
|
+
## 工具使用优先级
|
|
176
|
+
1. **首先使用 execute_shell 执行 rg 命令查找函数定义**:
|
|
177
|
+
- `rg "def\\s+{function_name}\\s*\\(" --type py` 查找Python函数定义
|
|
178
|
+
- `rg "function\\s+{function_name}\\s*\\(" --type js` 查找JavaScript函数定义
|
|
179
|
+
- `rg "func\\s+{function_name}\\s*\\(" --type go` 查找Go函数定义
|
|
180
|
+
|
|
181
|
+
2. **优先使用 read_code 阅读函数实现**:
|
|
182
|
+
- 找到函数位置后使用read_code阅读完整实现
|
|
183
|
+
- 对于长函数可分段读取关键部分
|
|
184
|
+
|
|
185
|
+
3. **使用 rg 搜索子函数调用和使用模式**:
|
|
186
|
+
- `rg -w "子函数名" --type py` 查找子函数调用
|
|
187
|
+
- `rg "import|from" 函数所在文件` 查找导入模块
|
|
188
|
+
|
|
189
|
+
4. **避免使用专用分析工具**:
|
|
190
|
+
- 只有当rg命令和read_code工具无法满足需求时才考虑
|
|
191
|
+
|
|
179
192
|
## 函数信息
|
|
180
193
|
- 函数名称: `{function_name}`
|
|
181
194
|
- {file_info}
|
|
@@ -184,33 +197,102 @@ class FunctionAnalyzerTool:
|
|
|
184
197
|
- 排除目录: {", ".join(exclude_dirs) if exclude_dirs else "无"}
|
|
185
198
|
|
|
186
199
|
## 分析策略
|
|
187
|
-
1.
|
|
188
|
-
2.
|
|
189
|
-
3.
|
|
190
|
-
4.
|
|
191
|
-
5.
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
200
|
+
1. 首先确定项目的主要编程语言和技术栈,以便更准确地分析函数实现
|
|
201
|
+
2. 理解分析目标,明确需要查找的信息
|
|
202
|
+
3. {"在指定文件中定位函数定义" if file_path else "搜索代码库查找函数定义位置"}
|
|
203
|
+
4. 根据分析目标,确定重点分析的方面
|
|
204
|
+
5. 灵活调整分析深度,关注与目标相关的实现细节
|
|
205
|
+
6. 根据目标需要自行判断是否需要分析子函数
|
|
206
|
+
|
|
207
|
+
## 函数分析工具指南
|
|
208
|
+
|
|
209
|
+
### execute_shell 搜索命令
|
|
210
|
+
- **查找函数定义**:
|
|
211
|
+
- `rg "def\\s+{function_name}\\s*\\(" --type py` 查找Python函数定义
|
|
212
|
+
- `rg "function\\s+{function_name}\\s*\\(" --type js` 查找JavaScript函数定义
|
|
213
|
+
- `rg "func\\s+{function_name}\\s*\\(" --type go` 查找Go函数定义
|
|
214
|
+
|
|
215
|
+
- **查找函数调用**:
|
|
216
|
+
- `rg "\\b{function_name}\\s*\\(" --type py` 查找函数调用
|
|
217
|
+
- `rg -w "{function_name}" -A 2 -B 2` 查看函数调用上下文
|
|
218
|
+
|
|
219
|
+
- **分析函数依赖**:
|
|
220
|
+
- `rg "import|from" 函数所在文件` 查找Python导入语句
|
|
221
|
+
- `rg "require\\(" 函数所在文件` 查找JavaScript导入语句
|
|
222
|
+
- `rg "import " 函数所在文件` 查找Go导入语句
|
|
223
|
+
|
|
224
|
+
- **统计分析**:
|
|
225
|
+
- `loc 函数所在文件` 获取文件代码统计
|
|
226
|
+
- `rg -c "if|else|elif" 函数所在文件` 统计条件分支数量
|
|
227
|
+
- `rg -c "for|while" 函数所在文件` 统计循环数量
|
|
228
|
+
|
|
229
|
+
### read_code
|
|
230
|
+
- **用途**:读取函数实现和相关代码
|
|
231
|
+
- **典型用法**:
|
|
232
|
+
- 阅读完整函数实现,包括注释和文档
|
|
233
|
+
- 阅读关键子函数的实现(根据analysis_depth)
|
|
234
|
+
- 阅读使用到的关键变量和依赖组件定义
|
|
235
|
+
- **使用策略**:
|
|
236
|
+
- 首先阅读整个函数以获取完整视图
|
|
237
|
+
- 识别函数的主要逻辑分支和处理路径
|
|
238
|
+
- 重点关注错误处理和边界条件检查
|
|
239
|
+
- 对复杂子函数进行递归分析(不超过指定深度)
|
|
240
|
+
|
|
241
|
+
### 函数分析模式
|
|
242
|
+
|
|
243
|
+
1. **逻辑流程分析**:
|
|
244
|
+
- 识别函数的主要执行路径
|
|
245
|
+
- 分析条件分支和循环结构
|
|
246
|
+
- 构建完整的逻辑流程图
|
|
247
|
+
|
|
248
|
+
2. **参数分析**:
|
|
249
|
+
- 分析参数类型、默认值和约束条件
|
|
250
|
+
- 了解参数在函数中的使用方式
|
|
251
|
+
- 识别关键参数及其影响
|
|
252
|
+
|
|
253
|
+
3. **依赖与副作用分析**:
|
|
254
|
+
- 识别函数使用的外部变量和组件
|
|
255
|
+
- 分析函数对外部状态的修改
|
|
256
|
+
- 评估函数的纯度和可测试性
|
|
257
|
+
|
|
258
|
+
4. **异常处理分析**:
|
|
259
|
+
- 识别可能的异常和错误情况
|
|
260
|
+
- 分析错误处理和恢复机制
|
|
261
|
+
- 评估错误处理的完整性和合理性
|
|
262
|
+
|
|
263
|
+
5. **性能分析**:
|
|
264
|
+
- 识别潜在的性能瓶颈
|
|
265
|
+
- 分析循环和递归的效率
|
|
266
|
+
- 评估算法复杂度
|
|
267
|
+
|
|
268
|
+
6. **子函数调用分析**:
|
|
269
|
+
- 识别所有调用的子函数
|
|
270
|
+
- 分析子函数的作用和调用模式
|
|
271
|
+
- 在允许的深度内递归分析关键子函数
|
|
272
|
+
|
|
273
|
+
## 编程范式适应
|
|
274
|
+
|
|
275
|
+
针对不同的编程范式,函数分析应关注不同方面:
|
|
276
|
+
|
|
277
|
+
### 过程式/函数式
|
|
278
|
+
- 输入输出关系和纯函数特性
|
|
279
|
+
- 控制流程和数据转换
|
|
280
|
+
- 递归和迭代模式
|
|
281
|
+
|
|
282
|
+
### 面向对象
|
|
283
|
+
- 方法与类的交互
|
|
284
|
+
- 状态修改和实例变量访问
|
|
285
|
+
- 继承和多态特性
|
|
286
|
+
|
|
287
|
+
### 事件驱动/回调式
|
|
288
|
+
- 事件注册和触发机制
|
|
289
|
+
- 回调链和异步流程
|
|
290
|
+
- 状态管理和并发控制
|
|
291
|
+
|
|
292
|
+
### 声明式
|
|
293
|
+
- 规则和约束定义
|
|
294
|
+
- 表达式和模式匹配
|
|
295
|
+
- 执行上下文和环境
|
|
214
296
|
|
|
215
297
|
## 输出要求
|
|
216
298
|
- 直接回应分析目标的关键问题
|
|
@@ -223,21 +305,22 @@ class FunctionAnalyzerTool:
|
|
|
223
305
|
def _create_summary_prompt(self, function_name: str, analysis_depth: int) -> str:
|
|
224
306
|
"""
|
|
225
307
|
创建Agent的summary prompt
|
|
226
|
-
|
|
308
|
+
|
|
227
309
|
Args:
|
|
228
310
|
function_name: 函数名称
|
|
229
311
|
analysis_depth: 子函数分析深度
|
|
230
|
-
|
|
312
|
+
|
|
231
313
|
Returns:
|
|
232
314
|
总结提示文本
|
|
233
315
|
"""
|
|
234
316
|
depth_description = "不包含子函数分析" if analysis_depth == 0 else f"包含 {analysis_depth} 层子函数分析"
|
|
235
|
-
|
|
317
|
+
|
|
236
318
|
return f"""# 函数分析报告: `{function_name}`
|
|
237
319
|
|
|
238
320
|
## 报告要求
|
|
239
321
|
生成一份完全以分析目标为导向的函数分析报告,{depth_description}。不要遵循固定的报告模板,而是完全根据分析目标来组织内容:
|
|
240
322
|
|
|
323
|
+
- 首先简要说明项目的主要编程语言和技术栈
|
|
241
324
|
- 专注回答分析目标提出的问题
|
|
242
325
|
- 只包含与分析目标直接相关的实现发现和洞察
|
|
243
326
|
- 完全跳过与分析目标无关的内容,无需做全面分析
|
|
@@ -245,4 +328,4 @@ class FunctionAnalyzerTool:
|
|
|
245
328
|
- 使用具体的代码片段支持你的观点
|
|
246
329
|
- 以清晰的Markdown格式呈现,简洁明了
|
|
247
330
|
|
|
248
|
-
在分析中保持灵活性,避免固定思维模式。你的任务不是提供全面的函数概览,而是直接解决分析目标中提出的具体问题。"""
|
|
331
|
+
在分析中保持灵活性,避免固定思维模式。你的任务不是提供全面的函数概览,而是直接解决分析目标中提出的具体问题。"""
|
|
@@ -37,14 +37,14 @@ class GitCommitTool:
|
|
|
37
37
|
def _extract_commit_message(self, message):
|
|
38
38
|
"""Raw extraction preserving all characters"""
|
|
39
39
|
r = re.search(
|
|
40
|
-
r"(?i)" + ot("COMMIT_MESSAGE") + r"\s*([\s\S]*?)\s*" + ct("COMMIT_MESSAGE"),
|
|
40
|
+
r"(?i)" + ot("COMMIT_MESSAGE") + r"\s*([\s\S]*?)\s*" + ct("COMMIT_MESSAGE"),
|
|
41
41
|
message
|
|
42
42
|
)
|
|
43
43
|
if r:
|
|
44
44
|
# 直接返回原始内容,仅去除外围空白
|
|
45
45
|
return shlex.quote(r.group(1).strip())
|
|
46
46
|
return "<<FORMAT VIOLATION>> Invalid commit message structure"
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
def _get_last_commit_hash(self):
|
|
49
49
|
process = subprocess.Popen(
|
|
50
50
|
["git", "log", "-1", "--pretty=%H"],
|
|
@@ -58,19 +58,19 @@ class GitCommitTool:
|
|
|
58
58
|
"""Execute automatic commit process with support for multi-line messages and special characters"""
|
|
59
59
|
try:
|
|
60
60
|
root_dir = args.get("root_dir", ".")
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
# Store current directory
|
|
63
63
|
original_dir = os.getcwd()
|
|
64
|
-
|
|
64
|
+
|
|
65
65
|
try:
|
|
66
66
|
# Change to root_dir
|
|
67
67
|
os.chdir(root_dir)
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
find_git_root()
|
|
70
70
|
if not has_uncommitted_changes():
|
|
71
71
|
PrettyOutput.print("没有未提交的更改", OutputType.SUCCESS)
|
|
72
72
|
return {"success": True, "stdout": "No changes to commit", "stderr": ""}
|
|
73
|
-
|
|
73
|
+
|
|
74
74
|
with yaspin(text="正在初始化提交流程...", color="cyan") as spinner:
|
|
75
75
|
# 添加文件
|
|
76
76
|
spinner.text = "正在添加文件到提交..."
|
|
@@ -80,7 +80,7 @@ class GitCommitTool:
|
|
|
80
80
|
stderr=subprocess.DEVNULL
|
|
81
81
|
).wait()
|
|
82
82
|
spinner.write("✅ 添加文件到提交")
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
# 获取差异
|
|
85
85
|
spinner.text = "正在获取代码差异..."
|
|
86
86
|
process = subprocess.Popen(
|
|
@@ -90,7 +90,7 @@ class GitCommitTool:
|
|
|
90
90
|
)
|
|
91
91
|
diff = process.communicate()[0].decode()
|
|
92
92
|
spinner.write("✅ 获取差异")
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
# 生成提交信息
|
|
95
95
|
spinner.text = "正在生成提交消息..."
|
|
96
96
|
prompt = f'''根据以下规则生成提交信息:
|
|
@@ -110,11 +110,11 @@ class GitCommitTool:
|
|
|
110
110
|
# 分析材料
|
|
111
111
|
{diff}
|
|
112
112
|
'''
|
|
113
|
-
platform = PlatformRegistry().
|
|
113
|
+
platform = PlatformRegistry().get_normal_platform()
|
|
114
114
|
commit_message = platform.chat_until_success(prompt)
|
|
115
115
|
commit_message = self._extract_commit_message(commit_message)
|
|
116
116
|
spinner.write("✅ 生成提交消息")
|
|
117
|
-
|
|
117
|
+
|
|
118
118
|
# 执行提交
|
|
119
119
|
spinner.text = "正在准备提交..."
|
|
120
120
|
with tempfile.NamedTemporaryFile(mode='w', delete=True) as tmp_file:
|
|
@@ -3,7 +3,7 @@ from typing import Dict, Any
|
|
|
3
3
|
from jarvis.jarvis_lsp.registry import LSPRegistry
|
|
4
4
|
class LSPGetDiagnosticsTool:
|
|
5
5
|
"""Tool for getting diagnostics (errors, warnings) from code using LSP."""
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
# 工具名称
|
|
8
8
|
name = "lsp_get_diagnostics"
|
|
9
9
|
# 工具描述
|
|
@@ -18,19 +18,19 @@ class LSPGetDiagnosticsTool:
|
|
|
18
18
|
"default": "."
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
@staticmethod
|
|
23
23
|
def check() -> bool:
|
|
24
24
|
"""检查是否有可用的LSP服务器"""
|
|
25
25
|
registry = LSPRegistry.get_global_lsp_registry()
|
|
26
26
|
return len(registry.get_supported_languages()) > 0
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
29
29
|
"""执行工具的主要逻辑"""
|
|
30
30
|
file_path = args.get("file_path", "")
|
|
31
31
|
language = args.get("language", "")
|
|
32
32
|
root_dir = args.get("root_dir", ".")
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
# 验证输入参数
|
|
35
35
|
if not all([file_path, language]):
|
|
36
36
|
return {
|
|
@@ -38,7 +38,7 @@ class LSPGetDiagnosticsTool:
|
|
|
38
38
|
"stderr": "Both file_path and language must be provided",
|
|
39
39
|
"stdout": ""
|
|
40
40
|
}
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
# 检查文件是否存在
|
|
43
43
|
if not os.path.exists(file_path):
|
|
44
44
|
return {
|
|
@@ -46,18 +46,18 @@ class LSPGetDiagnosticsTool:
|
|
|
46
46
|
"stderr": f"File not found: {file_path}",
|
|
47
47
|
"stdout": ""
|
|
48
48
|
}
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
# 存储当前目录
|
|
51
51
|
original_dir = os.getcwd()
|
|
52
|
-
|
|
52
|
+
|
|
53
53
|
try:
|
|
54
54
|
# 切换到root_dir
|
|
55
55
|
os.chdir(root_dir)
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
# 获取LSP实例
|
|
58
58
|
registry = LSPRegistry.get_global_lsp_registry()
|
|
59
59
|
lsp = registry.create_lsp(language)
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
# 检查语言是否支持
|
|
62
62
|
if not lsp:
|
|
63
63
|
return {
|
|
@@ -65,7 +65,7 @@ class LSPGetDiagnosticsTool:
|
|
|
65
65
|
"stderr": f"No LSP support for language: {language}",
|
|
66
66
|
"stdout": ""
|
|
67
67
|
}
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
try:
|
|
70
70
|
# 初始化LSP
|
|
71
71
|
if not lsp.initialize(os.path.abspath(os.getcwd())):
|
|
@@ -74,10 +74,10 @@ class LSPGetDiagnosticsTool:
|
|
|
74
74
|
"stderr": "LSP initialization failed",
|
|
75
75
|
"stdout": ""
|
|
76
76
|
}
|
|
77
|
-
|
|
77
|
+
|
|
78
78
|
# 获取诊断信息
|
|
79
79
|
diagnostics = lsp.get_diagnostics(file_path)
|
|
80
|
-
|
|
80
|
+
|
|
81
81
|
# 如果没有诊断信息
|
|
82
82
|
if not diagnostics:
|
|
83
83
|
return {
|
|
@@ -85,31 +85,31 @@ class LSPGetDiagnosticsTool:
|
|
|
85
85
|
"stdout": "No issues found in the file",
|
|
86
86
|
"stderr": ""
|
|
87
87
|
}
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
# 格式化输出
|
|
90
90
|
output = ["Diagnostics:"]
|
|
91
91
|
# 严重程度映射
|
|
92
92
|
severity_map = {1: "Error", 2: "Warning", 3: "Info", 4: "Hint"}
|
|
93
|
-
|
|
93
|
+
|
|
94
94
|
# 按严重程度和行号排序诊断信息
|
|
95
95
|
sorted_diagnostics = sorted(
|
|
96
96
|
diagnostics,
|
|
97
97
|
key=lambda x: (x["severity"], x["range"]["start"]["line"])
|
|
98
98
|
)
|
|
99
|
-
|
|
99
|
+
|
|
100
100
|
# 处理每个诊断信息
|
|
101
101
|
for diag in sorted_diagnostics:
|
|
102
102
|
severity = severity_map.get(diag["severity"], "Unknown")
|
|
103
103
|
start = diag["range"]["start"]
|
|
104
104
|
line = LSPRegistry.get_line_at_position(file_path, start["line"]).strip()
|
|
105
|
-
|
|
105
|
+
|
|
106
106
|
output.extend([
|
|
107
107
|
f"\n{severity} at line {start['line'] + 1}, column {start['character'] + 1}:",
|
|
108
108
|
f"Message: {diag['message']}",
|
|
109
109
|
f"Code: {line}",
|
|
110
110
|
"-" * 60
|
|
111
111
|
])
|
|
112
|
-
|
|
112
|
+
|
|
113
113
|
# 处理相关附加信息
|
|
114
114
|
if diag.get("relatedInformation"):
|
|
115
115
|
output.append("Related information:")
|
|
@@ -123,13 +123,13 @@ class LSPGetDiagnosticsTool:
|
|
|
123
123
|
f" at {info['location']['uri']}:{info['location']['range']['start']['line'] + 1}",
|
|
124
124
|
f" {info_line}"
|
|
125
125
|
])
|
|
126
|
-
|
|
126
|
+
|
|
127
127
|
return {
|
|
128
128
|
"success": True,
|
|
129
129
|
"stdout": "\n".join(output),
|
|
130
130
|
"stderr": ""
|
|
131
131
|
}
|
|
132
|
-
|
|
132
|
+
|
|
133
133
|
except Exception as e:
|
|
134
134
|
return {
|
|
135
135
|
"success": False,
|