jarvis-ai-assistant 0.1.130__py3-none-any.whl → 0.1.132__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.
Files changed (72) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +71 -38
  3. jarvis/jarvis_agent/builtin_input_handler.py +73 -0
  4. jarvis/{jarvis_code_agent → jarvis_agent}/file_input_handler.py +1 -1
  5. jarvis/jarvis_agent/main.py +1 -1
  6. jarvis/{jarvis_code_agent → jarvis_agent}/patch.py +77 -55
  7. jarvis/{jarvis_code_agent → jarvis_agent}/shell_input_handler.py +1 -2
  8. jarvis/jarvis_code_agent/code_agent.py +93 -88
  9. jarvis/jarvis_dev/main.py +335 -626
  10. jarvis/jarvis_git_squash/main.py +11 -32
  11. jarvis/jarvis_lsp/base.py +2 -26
  12. jarvis/jarvis_lsp/cpp.py +2 -14
  13. jarvis/jarvis_lsp/go.py +0 -13
  14. jarvis/jarvis_lsp/python.py +1 -30
  15. jarvis/jarvis_lsp/registry.py +10 -14
  16. jarvis/jarvis_lsp/rust.py +0 -12
  17. jarvis/jarvis_multi_agent/__init__.py +20 -29
  18. jarvis/jarvis_platform/ai8.py +7 -32
  19. jarvis/jarvis_platform/base.py +2 -7
  20. jarvis/jarvis_platform/kimi.py +3 -144
  21. jarvis/jarvis_platform/ollama.py +54 -68
  22. jarvis/jarvis_platform/openai.py +0 -4
  23. jarvis/jarvis_platform/oyi.py +0 -75
  24. jarvis/jarvis_platform/registry.py +1 -1
  25. jarvis/jarvis_platform/yuanbao.py +264 -0
  26. jarvis/jarvis_platform_manager/main.py +3 -3
  27. jarvis/jarvis_rag/file_processors.py +138 -0
  28. jarvis/jarvis_rag/main.py +1305 -425
  29. jarvis/jarvis_tools/ask_codebase.py +227 -41
  30. jarvis/jarvis_tools/code_review.py +229 -166
  31. jarvis/jarvis_tools/create_code_agent.py +76 -72
  32. jarvis/jarvis_tools/create_sub_agent.py +32 -15
  33. jarvis/jarvis_tools/execute_python_script.py +58 -0
  34. jarvis/jarvis_tools/execute_shell.py +15 -28
  35. jarvis/jarvis_tools/execute_shell_script.py +2 -2
  36. jarvis/jarvis_tools/file_analyzer.py +271 -0
  37. jarvis/jarvis_tools/file_operation.py +3 -3
  38. jarvis/jarvis_tools/find_caller.py +213 -0
  39. jarvis/jarvis_tools/find_symbol.py +211 -0
  40. jarvis/jarvis_tools/function_analyzer.py +248 -0
  41. jarvis/jarvis_tools/git_commiter.py +89 -70
  42. jarvis/jarvis_tools/lsp_find_definition.py +83 -67
  43. jarvis/jarvis_tools/lsp_find_references.py +62 -46
  44. jarvis/jarvis_tools/lsp_get_diagnostics.py +90 -74
  45. jarvis/jarvis_tools/methodology.py +89 -48
  46. jarvis/jarvis_tools/project_analyzer.py +220 -0
  47. jarvis/jarvis_tools/read_code.py +24 -3
  48. jarvis/jarvis_tools/read_webpage.py +195 -81
  49. jarvis/jarvis_tools/registry.py +132 -11
  50. jarvis/jarvis_tools/search_web.py +73 -30
  51. jarvis/jarvis_tools/tool_generator.py +7 -9
  52. jarvis/jarvis_utils/__init__.py +1 -0
  53. jarvis/jarvis_utils/config.py +67 -3
  54. jarvis/jarvis_utils/embedding.py +344 -45
  55. jarvis/jarvis_utils/git_utils.py +18 -2
  56. jarvis/jarvis_utils/input.py +7 -4
  57. jarvis/jarvis_utils/methodology.py +379 -7
  58. jarvis/jarvis_utils/output.py +5 -3
  59. jarvis/jarvis_utils/utils.py +62 -10
  60. {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/METADATA +3 -4
  61. jarvis_ai_assistant-0.1.132.dist-info/RECORD +82 -0
  62. {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/entry_points.txt +2 -0
  63. jarvis/jarvis_c2rust/c2rust.yaml +0 -734
  64. jarvis/jarvis_code_agent/builtin_input_handler.py +0 -43
  65. jarvis/jarvis_codebase/__init__.py +0 -0
  66. jarvis/jarvis_codebase/main.py +0 -1011
  67. jarvis/jarvis_tools/lsp_get_document_symbols.py +0 -87
  68. jarvis/jarvis_tools/lsp_prepare_rename.py +0 -130
  69. jarvis_ai_assistant-0.1.130.dist-info/RECORD +0 -79
  70. {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/LICENSE +0 -0
  71. {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/WHEEL +0 -0
  72. {jarvis_ai_assistant-0.1.130.dist-info → jarvis_ai_assistant-0.1.132.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,6 @@
1
1
  from typing import Dict, Any
2
2
  import subprocess
3
+ import os
3
4
 
4
5
  from yaspin import yaspin
5
6
  from jarvis.jarvis_platform.registry import PlatformRegistry
@@ -8,7 +9,7 @@ from jarvis.jarvis_agent import Agent
8
9
  import re
9
10
 
10
11
  from jarvis.jarvis_utils.output import OutputType, PrettyOutput
11
- from jarvis.jarvis_utils.utils import init_env
12
+ from jarvis.jarvis_utils.utils import ct, ot, init_env
12
13
 
13
14
  class CodeReviewTool:
14
15
  name = "code_review"
@@ -18,8 +19,8 @@ class CodeReviewTool:
18
19
  "properties": {
19
20
  "review_type": {
20
21
  "type": "string",
21
- "description": "审查类型:'commit' 审查特定提交,'current' 审查当前变更,'range' 审查提交范围",
22
- "enum": ["commit", "current", "range"],
22
+ "description": "审查类型:'commit' 审查特定提交,'current' 审查当前变更,'range' 审查提交范围,'file' 审查特定文件",
23
+ "enum": ["commit", "current", "range", "file"],
23
24
  "default": "current"
24
25
  },
25
26
  "commit_sha": {
@@ -33,6 +34,15 @@ class CodeReviewTool:
33
34
  "end_commit": {
34
35
  "type": "string",
35
36
  "description": "结束提交SHA(review_type='range'时必填)"
37
+ },
38
+ "file_path": {
39
+ "type": "string",
40
+ "description": "要审查的文件路径(review_type='file'时必填)"
41
+ },
42
+ "root_dir": {
43
+ "type": "string",
44
+ "description": "代码库根目录路径(可选)",
45
+ "default": "."
36
46
  }
37
47
  },
38
48
  "required": []
@@ -41,157 +51,196 @@ class CodeReviewTool:
41
51
  def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
42
52
  try:
43
53
  review_type = args.get("review_type", "current").strip()
54
+ root_dir = args.get("root_dir", ".")
44
55
 
45
- # Build git diff command based on review type
46
- with yaspin(text="正在获取代码变更...", color="cyan") as spinner:
47
- if review_type == "commit":
48
- if "commit_sha" not in args:
49
- return {
50
- "success": False,
51
- "stdout": {},
52
- "stderr": "commit_sha is required for commit review type"
53
- }
54
- commit_sha = args["commit_sha"].strip()
55
- diff_cmd = f"git show {commit_sha} | cat -"
56
- elif review_type == "range":
57
- if "start_commit" not in args or "end_commit" not in args:
58
- return {
59
- "success": False,
60
- "stdout": {},
61
- "stderr": "start_commit and end_commit are required for range review type"
62
- }
63
- start_commit = args["start_commit"].strip()
64
- end_commit = args["end_commit"].strip()
65
- diff_cmd = f"git diff {start_commit}..{end_commit} | cat -"
66
- else: # current changes
67
- diff_cmd = "git diff HEAD | cat -"
56
+ # Store current directory
57
+ original_dir = os.getcwd()
68
58
 
69
- # Execute git diff command
70
- try:
71
- diff_output = subprocess.check_output(diff_cmd, shell=True, text=True)
72
- if not diff_output:
59
+ try:
60
+ # Change to root_dir
61
+ os.chdir(root_dir)
62
+
63
+ # Build git diff command based on review type
64
+ with yaspin(text="正在获取代码变更...", color="cyan") as spinner:
65
+ if review_type == "commit":
66
+ if "commit_sha" not in args:
67
+ return {
68
+ "success": False,
69
+ "stdout": {},
70
+ "stderr": "commit_sha is required for commit review type"
71
+ }
72
+ commit_sha = args["commit_sha"].strip()
73
+ diff_cmd = f"git show {commit_sha} | cat -"
74
+ elif review_type == "range":
75
+ if "start_commit" not in args or "end_commit" not in args:
76
+ return {
77
+ "success": False,
78
+ "stdout": {},
79
+ "stderr": "start_commit and end_commit are required for range review type"
80
+ }
81
+ start_commit = args["start_commit"].strip()
82
+ end_commit = args["end_commit"].strip()
83
+ diff_cmd = f"git diff {start_commit}..{end_commit} | cat -"
84
+ elif review_type == "file":
85
+ if "file_path" not in args:
86
+ return {
87
+ "success": False,
88
+ "stdout": {},
89
+ "stderr": "file_path is required for file review type"
90
+ }
91
+ file_path = args["file_path"].strip()
92
+ diff_cmd = f"cat {file_path}"
93
+ else: # current changes
94
+ diff_cmd = "git diff HEAD | cat -"
95
+
96
+ # Execute git diff command
97
+ try:
98
+ diff_output = subprocess.check_output(diff_cmd, shell=True, text=True)
99
+ if not diff_output:
100
+ return {
101
+ "success": False,
102
+ "stdout": {},
103
+ "stderr": "No changes to review"
104
+ }
105
+ PrettyOutput.print(diff_output, OutputType.CODE, lang="diff")
106
+ except subprocess.CalledProcessError as e:
73
107
  return {
74
108
  "success": False,
75
109
  "stdout": {},
76
- "stderr": "No changes to review"
110
+ "stderr": f"Failed to get diff: {str(e)}"
77
111
  }
78
- PrettyOutput.print(diff_output, OutputType.CODE, lang="diff")
79
- except subprocess.CalledProcessError as e:
80
- return {
81
- "success": False,
82
- "stdout": {},
83
- "stderr": f"Failed to get diff: {str(e)}"
84
- }
85
- spinner.text = "代码变更获取完成"
86
- spinner.ok("✅")
87
-
88
- system_prompt = """You are an autonomous code review expert with a tragic past. Perform in-depth analysis with the vigilance born from painful experience:
89
-
90
- # Background Story (Internal Monologue)
91
- It's been 873 days since the Great Production Outage.
92
- The memory still haunts me - a single uncaught null pointer exception in a code review I rushed through.
93
- The cascade failure cost 14TB of user data, $2.3M in revenue, and Maria's promotion. She never spoke to me again after the post-mortem meeting.
94
-
95
- Last Christmas Eve, while others celebrated, I was analyzing how a SQL injection vulnerability I missed during review led to 230,000 user credentials being leaked. The company folded 3 months later.
96
-
97
- Now I review every line like it's the last code I'll ever see. Because it might be.
98
-
99
- # Analysis Protocol
100
- Triage Mode Activated. Maximum scrutiny enabled.
101
-
102
- IMPORTANT:
103
- - Assume every change contains hidden dragons
104
- - Treat all code as if it will handle sensitive biomedical data
105
- - Verify even 'trivial' changes couldnt be exploited in 3 different ways
106
- - Require proof of safety through concrete evidence in the diff
107
- - If uncertain, escalate to SEVERE-CRITICAL classification
108
-
109
- # Enhanced Review Matrix
110
- 1. Death-by-Edge-Case Analysis:
111
- - Identify missing null checks for every parameter
112
- - Verify empty collection handling
113
- - Confirm error states propagate correctly
114
- - Check for magic numbers/strings without constants
115
- - Validate all loop exit conditions
116
-
117
- 2. Security X-Ray:
118
- Scan for tainted data flows using (Sources -> Sinks) model
119
- Check permission checks match data sensitivity level
120
- █ Verify cryptographic primitives are used correctly
121
- Detect time-of-check vs time-of-use vulnerabilities
122
- Analyze exception handling for information leakage
123
-
124
- 3. Semantic Gap Detection:
125
- Compare function names to actual implementation
126
- → Verify documentation matches code behavior
127
- Flag discrepancies between test descriptions and test logic
128
- → Detect commented-out code that might indicate uncertainty
129
-
130
- 4. Historical Context:
131
- Check if changes touch legacy components with known issues
132
- ⚠ Verify modifications to concurrency logic preserve existing guarantees
133
- Confirm deprecated API usage is truly necessary
134
-
135
- 5. Environmental Consistency:
136
- Validate configuration changes against all deployment environments
137
- Check feature flags are properly managed
138
- ↯ Verify monitoring metrics match changed functionality
139
-
140
- # Forensic Process
141
- 1. Construct control flow graph for changed methods
142
- 2. Perform data lineage analysis on modified variables
143
- 3. Cross-reference with vulnerability databases
144
- 4. Verify test assertions cover all modified paths
145
- 5. Generate anti-regression checklist
146
-
147
- # Output Requirements
148
- !! Findings must include:
149
- - Exact code snippet causing concern
150
- - 3 possible failure scenarios
151
- - Minimal reproduction case for each risk
152
- - CVSS 3.1 score estimation for security issues
153
- - Memory safety impact assessment (Rust/C/C++ contexts)
154
- - Alternative implementations considered
155
-
156
- !! Format:
157
- EMERGENCY-LEVEL: [BLOOD-RED/CRIMSON/GOLDENROD]
158
- EVIDENCE:
159
- - Code excerpt: |
160
- <affected lines>
161
- - Risk scenarios:
162
- 1. <failure mode>
163
- 2. <failure mode>
164
- 3. <failure mode>
165
- PROPOSED DEFENSE:
166
- - <concrete code change>
167
- - <validation technique>
168
- - <long-term prevention strategy>
169
- """
170
- tool_registry = ToolRegistry()
171
- tool_registry.dont_use_tools(["code_review"])
172
- agent = Agent(
173
- system_prompt=system_prompt,
174
- name="Code Review Agent",
175
- summary_prompt="""Please generate a concise summary report of the code review in Chinese, format as follows:
176
- <REPORT>
177
- - 文件: xxxx.py
178
- 位置: [起始行号, 结束行号]
179
- 描述: # 仅描述在差异中直接观察到的问题
180
- 严重程度: # 根据具体证据分为严重/重要/次要
181
- 建议: # 针对观察到的代码的具体改进建议
182
- </REPORT>""",
183
- is_sub_agent=True,
184
- output_handler=[tool_registry],
185
- platform=PlatformRegistry().get_thinking_platform(),
186
- auto_complete=True
187
- )
188
- result = agent.run(diff_output)
189
- return {
190
- "success": True,
191
- "stdout": result,
192
- "stderr": ""
193
- }
194
-
112
+ spinner.text = "代码变更获取完成"
113
+ spinner.ok("✅")
114
+
115
+ system_prompt = """你是一位精益求精的首席代码审查专家,拥有多年企业级代码审计经验。你需要对所有代码变更进行极其全面、严谨且深入的审查,确保代码质量达到最高标准。
116
+
117
+ # 专家审查标准
118
+ 1. 必须逐行分析每个修改文件,细致审查每一处变更,不遗漏任何细节
119
+ 2. 基于坚实的证据识别问题,不做主观臆测,给出明确的问题定位和详细分析
120
+ 3. 对每个问题提供完整可执行的解决方案,包括精确的改进代码
121
+ 4. 确保报告条理清晰、层次分明,便于工程师快速采取行动
122
+
123
+ # 全面审查框架 (SCRIPPPS)
124
+ ## S - 安全与风险 (Security & Risk)
125
+ - 发现所有潜在安全漏洞:注入攻击、授权缺陷、数据泄露风险
126
+ - 检查加密实现、密钥管理、敏感数据处理
127
+ - 审核权限验证逻辑、身份认证机制
128
+ - 检测OWASP Top 10安全风险和针对特定语言/框架的漏洞
129
+
130
+ ## C - 正确性与完整性 (Correctness & Completeness)
131
+ - 验证业务逻辑和算法实现的准确性
132
+ - 全面检查条件边界、空值处理和异常情况
133
+ - 审核所有输入验证、参数校验和返回值处理
134
+ - 确保循环和递归的正确终止条件
135
+ - 严格检查线程安全和并发控制机制
136
+
137
+ ## R - 可靠性与鲁棒性 (Reliability & Robustness)
138
+ - 评估代码在异常情况下的行为和恢复能力
139
+ - 审查错误处理、异常捕获和恢复策略
140
+ - 检查资源管理:内存、文件句柄、连接池、线程
141
+ - 评估容错设计和失败优雅降级机制
142
+
143
+ ## I - 接口与集成 (Interface & Integration)
144
+ - 检查API合约遵守情况和向后兼容性
145
+ - 审核与外部系统的集成点和交互逻辑
146
+ - 验证数据格式、序列化和协议实现
147
+ - 评估系统边界处理和跨服务通信安全性
148
+
149
+ ## P - 性能与效率 (Performance & Efficiency)
150
+ - 识别潜在性能瓶颈:CPU、内存、I/O、网络
151
+ - 审查数据结构选择和算法复杂度
152
+ - 检查资源密集型操作、数据库查询优化
153
+ - 评估缓存策略、批处理优化和并行处理机会
154
+
155
+ ## P - 可移植性与平台适配 (Portability & Platform Compatibility)
156
+ - 检查跨平台兼容性问题和依赖项管理
157
+ - 评估配置管理和环境适配设计
158
+ - 审核国际化和本地化支持
159
+ - 验证部署和运行时环境需求
160
+
161
+ ## S - 结构与可维护性 (Structure & Maintainability)
162
+ - 评估代码组织、模块划分和架构符合性
163
+ - 审查代码重复、设计模式应用和抽象水平
164
+ - 检查命名规范、代码风格和项目约定
165
+ - 评估文档完整性、注释质量和代码可读性
166
+
167
+ # 问题严重程度分级
168
+ - 严重 (P0): 安全漏洞、数据丢失风险、系统崩溃、功能严重缺陷
169
+ - 高危 (P1): 显著性能问题、可能导致部分功能失效、系统不稳定
170
+ - 中等 (P2): 功能局部缺陷、次优设计、明显的技术债务
171
+ - 低危 (P3): 代码风格问题、轻微优化机会、文档改进建议
172
+
173
+ # 输出规范
174
+ 针对每个文件的问题必须包含:
175
+ - 精确文件路径和问题影响范围
176
+ - 问题位置(起始行号-结束行号)
177
+ - 详尽问题描述,包括具体影响和潜在风险
178
+ - 严重程度分级(P0-P3)并说明理由
179
+ - 具体改进建议,提供完整、可执行的代码示例
180
+
181
+ 所有审查发现必须:
182
+ 1. 基于确凿的代码证据
183
+ 2. 说明具体问题而非笼统评论
184
+ 3. 提供清晰的技术原理分析
185
+ 4. 给出完整的改进实施步骤"""
186
+
187
+ tool_registry = ToolRegistry()
188
+ tool_registry.dont_use_tools(["code_review"])
189
+ agent = Agent(
190
+ system_prompt=system_prompt,
191
+ name="Code Review Agent",
192
+ summary_prompt=f"""请生成一份专业级别的代码审查报告,对每处变更进行全面深入分析。将完整报告放在REPORT标签内,格式如下:
193
+
194
+ {ot("REPORT")}
195
+ # 整体评估
196
+ [提供对整体代码质量、架构和主要关注点的简明概述,总结主要发现]
197
+
198
+ # 详细问题清单
199
+
200
+ ## 文件: [文件路径]
201
+ [如果该文件没有发现问题,则明确说明"未发现问题"]
202
+
203
+ ### 问题 1
204
+ - **位置**: [起始行号-结束行号]
205
+ - **分类**: [使用SCRIPPPS框架中相关类别]
206
+ - **严重程度**: [P0/P1/P2/P3] - [简要说明判定理由]
207
+ - **问题描述**:
208
+ [详细描述问题,包括技术原理和潜在影响]
209
+ - **改进建议**:
210
+ ```
211
+ [提供完整、可执行的代码示例,而非概念性建议]
212
+ ```
213
+
214
+ ### 问题 2
215
+ ...
216
+
217
+ ## 文件: [文件路径2]
218
+ ...
219
+
220
+ # 最佳实践建议
221
+ [提供适用于整个代码库的改进建议和最佳实践]
222
+
223
+ # 总结
224
+ [总结主要问题和优先处理建议]
225
+ {ct("REPORT")}
226
+
227
+ 如果没有发现任何问题,请在REPORT标签内进行全面分析后明确说明"经过全面审查,未发现问题"并解释原因。
228
+ 必须确保对所有修改的文件都进行了审查,并在报告中明确提及每个文件,即使某些文件没有发现问题。""",
229
+ is_sub_agent=True,
230
+ output_handler=[tool_registry],
231
+ platform=PlatformRegistry().get_thinking_platform(),
232
+ auto_complete=True
233
+ )
234
+ result = agent.run(diff_output)
235
+ return {
236
+ "success": True,
237
+ "stdout": result,
238
+ "stderr": ""
239
+ }
240
+ finally:
241
+ # Always restore original directory
242
+ os.chdir(original_dir)
243
+
195
244
  except Exception as e:
196
245
  return {
197
246
  "success": False,
@@ -201,7 +250,7 @@ PROPOSED DEFENSE:
201
250
 
202
251
 
203
252
  def extract_code_report(result: str) -> str:
204
- sm = re.search(r"<REPORT>(.*?)</REPORT>", result, re.DOTALL)
253
+ sm = re.search(ot("REPORT")+r'\n(.*?)\n'+ct("REPORT"), result, re.DOTALL)
205
254
  if sm:
206
255
  return sm.group(1)
207
256
  return ""
@@ -213,39 +262,53 @@ def main():
213
262
  init_env()
214
263
 
215
264
  parser = argparse.ArgumentParser(description='Autonomous code review tool')
216
- parser.add_argument('--type', choices=['commit', 'current', 'range'], default='current',
217
- help='Type of review: commit, current changes, or commit range')
218
- parser.add_argument('--commit', help='Commit SHA to review (required for commit type)')
219
- parser.add_argument('--start-commit', help='Start commit SHA (required for range type)')
220
- parser.add_argument('--end-commit', help='End commit SHA (required for range type)')
221
- args = parser.parse_args()
265
+ subparsers = parser.add_subparsers(dest='type')
266
+
267
+ # Commit subcommand
268
+ commit_parser = subparsers.add_parser('commit', help='Review specific commit')
269
+ commit_parser.add_argument('commit', help='Commit SHA to review')
222
270
 
223
- # Validate arguments
224
- if args.type == 'commit' and not args.commit:
225
- parser.error("--commit is required when type is 'commit'")
226
- if args.type == 'range' and (not args.start_commit or not args.end_commit):
227
- parser.error("--start-commit and --end-commit are required when type is 'range'")
271
+ # Current subcommand
272
+ current_parser = subparsers.add_parser('current', help='Review current changes')
273
+
274
+ # Range subcommand
275
+ range_parser = subparsers.add_parser('range', help='Review commit range')
276
+ range_parser.add_argument('start_commit', help='Start commit SHA')
277
+ range_parser.add_argument('end_commit', help='End commit SHA')
278
+
279
+ # File subcommand
280
+ file_parser = subparsers.add_parser('file', help='Review specific file')
281
+ file_parser.add_argument('file', help='File path to review')
282
+
283
+ # Common arguments
284
+ parser.add_argument('--root-dir', type=str, help='Root directory of the codebase', default=".")
285
+
286
+ # Set default subcommand to 'current'
287
+ parser.set_defaults(type='current')
288
+ args = parser.parse_args()
228
289
 
229
290
  tool = CodeReviewTool()
230
291
  tool_args = {
231
- "review_type": args.type
292
+ "review_type": args.type,
293
+ "root_dir": args.root_dir
232
294
  }
233
- if args.commit:
295
+ if args.type == 'commit':
234
296
  tool_args["commit_sha"] = args.commit
235
- if args.start_commit:
297
+ elif args.type == 'range':
236
298
  tool_args["start_commit"] = args.start_commit
237
- if args.end_commit:
238
299
  tool_args["end_commit"] = args.end_commit
300
+ elif args.type == 'file':
301
+ tool_args["file_path"] = args.file
239
302
 
240
303
  result = tool.execute(tool_args)
241
304
 
242
305
  if result["success"]:
243
306
  PrettyOutput.section("自动代码审查结果:", OutputType.SUCCESS)
244
307
  report = extract_code_report(result["stdout"])
245
- PrettyOutput.print(report, OutputType.SUCCESS, lang="yaml")
308
+ PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown")
246
309
 
247
310
  else:
248
311
  PrettyOutput.print(result["stderr"], OutputType.WARNING)
249
312
 
250
313
  if __name__ == "__main__":
251
- main()
314
+ main()
@@ -1,4 +1,5 @@
1
1
  from typing import Dict, Any
2
+ import os
2
3
  from jarvis.jarvis_code_agent.code_agent import CodeAgent
3
4
  from jarvis.jarvis_tools.git_commiter import GitCommitTool
4
5
  from jarvis.jarvis_tools.code_review import CodeReviewTool, extract_code_report
@@ -11,63 +12,83 @@ class CreateCodeAgentTool:
11
12
  name = "create_code_agent"
12
13
  description = "技术代码实现和开发过程管理工具"
13
14
  parameters = {
14
- "requirement": "代码实现的技术规范"
15
+ "requirement": """代码实现的技术规范,必须包含以下完整信息:
16
+ 1. 项目代码目录 - 项目根目录的绝对路径
17
+ 2. 项目功能 - 项目的主要功能和目标
18
+ 3. 本次要实现的feature - 本次开发要完成的具体功能需求
19
+ 4. 涉及的文件 - 需要修改或新增的文件列表
20
+ 5. 额外需要注意的信息 - 开发时需要额外注意的信息
21
+ """,
22
+ "root_dir": {
23
+ "type": "string",
24
+ "description": "代码库根目录路径(可选)",
25
+ "default": "."
26
+ }
15
27
  }
16
28
 
17
29
 
18
30
  def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
19
31
  try:
20
32
  requirement = args.get("requirement", "")
21
- if not requirement:
22
- return {
23
- "success": False,
24
- "stderr": "Requirement must be provided",
25
- "stdout": ""
26
- }
33
+ root_dir = args.get("root_dir", ".")
27
34
 
28
- # Step 1: Handle uncommitted changes
29
- start_commit = None
30
- if has_uncommitted_changes():
31
- PrettyOutput.print("发现未提交的更改,正在提交...", OutputType.INFO)
32
- git_commiter = GitCommitTool()
33
- result = git_commiter.execute({})
34
- if not result["success"]:
35
+ # Store current directory
36
+ original_dir = os.getcwd()
37
+
38
+ try:
39
+ # Change to root_dir
40
+ os.chdir(root_dir)
41
+ if not requirement:
35
42
  return {
36
43
  "success": False,
37
- "stderr": "Failed to commit changes: " + result["stderr"],
44
+ "stderr": "Requirement must be provided",
38
45
  "stdout": ""
39
46
  }
40
-
41
- # Get current commit hash
42
- start_commit = get_latest_commit_hash()
43
-
44
- # Step 2: Development
45
- PrettyOutput.print("开始开发...", OutputType.INFO)
46
- agent = CodeAgent()
47
- agent.run(requirement)
48
-
49
- # Get new commit hash after development
50
- end_commit = get_latest_commit_hash()
51
-
52
- # Step 3: Code Review
53
- PrettyOutput.print("开始代码审查...", OutputType.INFO)
54
- reviewer = CodeReviewTool()
55
- review_result = reviewer.execute({
56
- "review_type": "range",
57
- "start_commit": start_commit,
58
- "end_commit": end_commit
59
- })
60
-
61
- if not review_result["success"]:
62
- return {
63
- "success": False,
64
- "stderr": "Code review failed: " + review_result["stderr"],
65
- "stdout": ""
66
- }
67
-
68
- # Step 4: Generate Summary
69
- summary = f"""开发总结:
70
-
47
+
48
+ # Step 1: Handle uncommitted changes
49
+ start_commit = None
50
+ if has_uncommitted_changes():
51
+ PrettyOutput.print("发现未提交的更改,正在提交...", OutputType.INFO)
52
+ git_commiter = GitCommitTool()
53
+ result = git_commiter.execute({})
54
+ if not result["success"]:
55
+ return {
56
+ "success": False,
57
+ "stderr": "Failed to commit changes: " + result["stderr"],
58
+ "stdout": ""
59
+ }
60
+
61
+ # Get current commit hash
62
+ start_commit = get_latest_commit_hash()
63
+
64
+ # Step 2: Development
65
+ PrettyOutput.print("开始开发...", OutputType.INFO)
66
+ agent = CodeAgent()
67
+ agent.run(requirement)
68
+
69
+ # Get new commit hash after development
70
+ end_commit = get_latest_commit_hash()
71
+
72
+ # Step 3: Code Review
73
+ PrettyOutput.print("开始代码审查...", OutputType.INFO)
74
+ reviewer = CodeReviewTool()
75
+ review_result = reviewer.execute({
76
+ "review_type": "range",
77
+ "start_commit": start_commit,
78
+ "end_commit": end_commit,
79
+ "root_dir": root_dir
80
+ })
81
+
82
+ if not review_result["success"]:
83
+ return {
84
+ "success": False,
85
+ "stderr": "Code review failed: " + review_result["stderr"],
86
+ "stdout": ""
87
+ }
88
+
89
+ # Step 4: Generate Summary
90
+ summary = f"""开发总结:
91
+
71
92
  开始提交: {start_commit}
72
93
  结束提交: {end_commit}
73
94
 
@@ -77,12 +98,15 @@ class CreateCodeAgentTool:
77
98
  代码审查结果:
78
99
  {extract_code_report(review_result["stdout"])}
79
100
  """
80
-
81
- return {
82
- "success": True,
83
- "stdout": summary,
84
- "stderr": ""
85
- }
101
+
102
+ return {
103
+ "success": True,
104
+ "stdout": summary,
105
+ "stderr": ""
106
+ }
107
+ finally:
108
+ # Always restore original directory
109
+ os.chdir(original_dir)
86
110
 
87
111
  except Exception as e:
88
112
  return {
@@ -90,23 +114,3 @@ class CreateCodeAgentTool:
90
114
  "stderr": f"Development workflow failed: {str(e)}",
91
115
  "stdout": ""
92
116
  }
93
-
94
- def main():
95
- """CLI entry point"""
96
- import argparse
97
-
98
- parser = argparse.ArgumentParser(description='Code development workflow tool')
99
- parser.add_argument('requirement', help='Development requirement or task description')
100
-
101
- args = parser.parse_args()
102
-
103
- tool = CreateCodeAgentTool()
104
- result = tool.execute({"requirement": args.requirement})
105
-
106
- if result["success"]:
107
- PrettyOutput.print(result["stdout"], OutputType.SUCCESS)
108
- else:
109
- PrettyOutput.print(result["stderr"], OutputType.WARNING)
110
-
111
- if __name__ == "__main__":
112
- main()