jarvis-ai-assistant 0.1.134__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 +201 -79
- jarvis/jarvis_agent/builtin_input_handler.py +16 -6
- jarvis/jarvis_agent/file_input_handler.py +9 -9
- jarvis/jarvis_agent/jarvis.py +10 -10
- jarvis/jarvis_agent/main.py +12 -11
- jarvis/jarvis_agent/output_handler.py +3 -3
- jarvis/jarvis_agent/patch.py +86 -62
- jarvis/jarvis_agent/shell_input_handler.py +5 -3
- jarvis/jarvis_code_agent/code_agent.py +134 -99
- jarvis/jarvis_code_agent/file_select.py +24 -24
- jarvis/jarvis_dev/main.py +45 -51
- 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 -11
- jarvis/jarvis_lsp/cpp.py +14 -14
- jarvis/jarvis_lsp/go.py +13 -13
- jarvis/jarvis_lsp/python.py +8 -8
- jarvis/jarvis_lsp/registry.py +21 -21
- jarvis/jarvis_lsp/rust.py +15 -15
- jarvis/jarvis_methodology/main.py +101 -0
- jarvis/jarvis_multi_agent/__init__.py +11 -11
- jarvis/jarvis_multi_agent/main.py +6 -6
- 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 +27 -28
- jarvis/jarvis_platform/yuanbao.py +38 -42
- 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 +261 -277
- jarvis/jarvis_smart_shell/main.py +12 -12
- jarvis/jarvis_tools/ask_codebase.py +28 -28
- 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 +19 -19
- jarvis/jarvis_tools/create_code_agent.py +15 -15
- 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 +29 -29
- jarvis/jarvis_tools/file_operation.py +22 -20
- jarvis/jarvis_tools/find_caller.py +25 -25
- jarvis/jarvis_tools/find_methodolopy.py +65 -0
- jarvis/jarvis_tools/find_symbol.py +24 -24
- jarvis/jarvis_tools/function_analyzer.py +27 -27
- jarvis/jarvis_tools/git_commiter.py +9 -9
- jarvis/jarvis_tools/lsp_get_diagnostics.py +19 -19
- jarvis/jarvis_tools/methodology.py +23 -62
- jarvis/jarvis_tools/project_analyzer.py +29 -33
- jarvis/jarvis_tools/rag.py +15 -15
- jarvis/jarvis_tools/read_code.py +24 -22
- jarvis/jarvis_tools/read_webpage.py +31 -31
- jarvis/jarvis_tools/registry.py +72 -52
- jarvis/jarvis_tools/tool_generator.py +18 -18
- jarvis/jarvis_utils/config.py +23 -23
- 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 +140 -136
- jarvis/jarvis_utils/output.py +11 -11
- jarvis/jarvis_utils/utils.py +22 -70
- {jarvis_ai_assistant-0.1.134.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/METADATA +1 -1
- jarvis_ai_assistant-0.1.138.dist-info/RECORD +85 -0
- {jarvis_ai_assistant-0.1.134.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/entry_points.txt +2 -0
- jarvis/jarvis_tools/select_code_files.py +0 -62
- jarvis_ai_assistant-0.1.134.dist-info/RECORD +0 -82
- {jarvis_ai_assistant-0.1.134.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/LICENSE +0 -0
- {jarvis_ai_assistant-0.1.134.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.1.134.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/top_level.txt +0 -0
|
@@ -33,10 +33,10 @@ def execute_command(command: str) -> None:
|
|
|
33
33
|
|
|
34
34
|
def process_request(request: str) -> Optional[str]:
|
|
35
35
|
"""Process user request and return corresponding shell command
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
Args:
|
|
38
38
|
request: User's natural language request
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
Returns:
|
|
41
41
|
Optional[str]: Corresponding shell command, return None if processing fails
|
|
42
42
|
"""
|
|
@@ -46,7 +46,7 @@ def process_request(request: str) -> Optional[str]:
|
|
|
46
46
|
|
|
47
47
|
shell = get_shell_name()
|
|
48
48
|
current_path = os.getcwd()
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
# Set system prompt
|
|
51
51
|
system_message = """
|
|
52
52
|
# 🤖 Role Definition
|
|
@@ -96,18 +96,18 @@ Output: find . -name "*.py"
|
|
|
96
96
|
|
|
97
97
|
prefix = f"Current path: {current_path}\n"
|
|
98
98
|
prefix += f"Current shell: {shell}\n"
|
|
99
|
-
|
|
99
|
+
|
|
100
100
|
with yaspin(text="正在生成命令...", color="cyan") as spinner:
|
|
101
101
|
result = model.chat_until_success(prefix + request)
|
|
102
102
|
spinner.ok("✅ 命令生成成功")
|
|
103
|
-
|
|
103
|
+
|
|
104
104
|
# 提取命令
|
|
105
105
|
if result and isinstance(result, str):
|
|
106
106
|
command = result.strip()
|
|
107
107
|
return command
|
|
108
|
-
|
|
108
|
+
|
|
109
109
|
return None
|
|
110
|
-
|
|
110
|
+
|
|
111
111
|
except Exception as e:
|
|
112
112
|
PrettyOutput.print(f"处理请求失败: {str(e)}", OutputType.WARNING)
|
|
113
113
|
return None
|
|
@@ -124,25 +124,25 @@ Example:
|
|
|
124
124
|
%(prog)s "Compress all jpg images"
|
|
125
125
|
%(prog)s "Find documents modified in the last week"
|
|
126
126
|
""")
|
|
127
|
-
|
|
127
|
+
|
|
128
128
|
# 修改为可选参数,添加从stdin读取的支持
|
|
129
129
|
parser.add_argument(
|
|
130
130
|
"request",
|
|
131
131
|
nargs='?', # 设置为可选参数
|
|
132
132
|
help="描述您想要执行的操作(用自然语言描述),如果未提供则从标准输入读取"
|
|
133
133
|
)
|
|
134
|
-
|
|
134
|
+
|
|
135
135
|
# 解析参数
|
|
136
136
|
args = parser.parse_args()
|
|
137
|
-
|
|
137
|
+
|
|
138
138
|
# 添加标准输入处理
|
|
139
139
|
if not args.request:
|
|
140
140
|
# 检查是否在交互式终端中运行
|
|
141
141
|
args.request = get_multiline_input(tip="请输入您要执行的功能:")
|
|
142
|
-
|
|
142
|
+
|
|
143
143
|
# 处理请求
|
|
144
144
|
command = process_request(args.request)
|
|
145
|
-
|
|
145
|
+
|
|
146
146
|
# 输出结果
|
|
147
147
|
if command:
|
|
148
148
|
execute_command(command) # 显示并执行命令
|
|
@@ -10,12 +10,12 @@ from jarvis.jarvis_utils.utils import init_env
|
|
|
10
10
|
|
|
11
11
|
class AskCodebaseTool:
|
|
12
12
|
"""用于智能代码库查询和分析的工具
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
适用场景:
|
|
15
15
|
- 查询特定功能所在的文件位置(支持所有文件类型)
|
|
16
16
|
- 了解单个功能点的实现原理(支持所有文件类型)
|
|
17
17
|
- 查找特定API或接口的用法(支持所有文件类型)
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
不适用场景:
|
|
20
20
|
- 跨越多文件的大范围分析
|
|
21
21
|
- 复杂系统架构的全面评估
|
|
@@ -45,20 +45,20 @@ class AskCodebaseTool:
|
|
|
45
45
|
|
|
46
46
|
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
47
47
|
"""Execute codebase analysis using an Agent with execute_shell and rag tools
|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
Args:
|
|
50
50
|
args: Dictionary containing:
|
|
51
51
|
- question: The question to answer, preferably about locating functionality
|
|
52
52
|
or understanding implementation details of a specific feature
|
|
53
53
|
- top_k: Optional number of files to analyze
|
|
54
54
|
- root_dir: Optional root directory of the codebase
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
Returns:
|
|
57
57
|
Dict containing:
|
|
58
58
|
- success: Boolean indicating success
|
|
59
59
|
- stdout: Analysis result
|
|
60
60
|
- stderr: Error message if any
|
|
61
|
-
|
|
61
|
+
|
|
62
62
|
Note:
|
|
63
63
|
This tool works best for focused questions about specific features or implementations.
|
|
64
64
|
It is not designed for comprehensive multi-file analysis or complex architectural questions.
|
|
@@ -66,28 +66,28 @@ class AskCodebaseTool:
|
|
|
66
66
|
try:
|
|
67
67
|
question = args["question"]
|
|
68
68
|
root_dir = args.get("root_dir", ".")
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
# Store current directory
|
|
71
71
|
original_dir = os.getcwd()
|
|
72
|
-
|
|
72
|
+
|
|
73
73
|
try:
|
|
74
74
|
# Change to root_dir
|
|
75
75
|
os.chdir(root_dir)
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
# Get git root directory
|
|
78
78
|
git_root = find_git_root() or os.getcwd()
|
|
79
|
-
|
|
79
|
+
|
|
80
80
|
# Create system prompt for the Agent
|
|
81
81
|
system_prompt = self._create_system_prompt(question, git_root)
|
|
82
|
-
|
|
82
|
+
|
|
83
83
|
# Create summary prompt for the Agent
|
|
84
84
|
summary_prompt = self._create_summary_prompt(question)
|
|
85
|
-
|
|
85
|
+
|
|
86
86
|
# Create tools registry
|
|
87
87
|
from jarvis.jarvis_tools.registry import ToolRegistry
|
|
88
88
|
tool_registry = ToolRegistry()
|
|
89
89
|
tool_registry.use_tools(["execute_shell", "read_code", "rag"])
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
# Create and run Agent
|
|
92
92
|
analyzer_agent = Agent(
|
|
93
93
|
system_prompt=system_prompt,
|
|
@@ -99,11 +99,11 @@ class AskCodebaseTool:
|
|
|
99
99
|
execute_tool_confirm=False,
|
|
100
100
|
auto_complete=self.auto_complete
|
|
101
101
|
)
|
|
102
|
-
|
|
102
|
+
|
|
103
103
|
# Run agent and get result
|
|
104
104
|
task_input = f"回答关于代码库的问题: {question}"
|
|
105
105
|
result = analyzer_agent.run(task_input)
|
|
106
|
-
|
|
106
|
+
|
|
107
107
|
return {
|
|
108
108
|
"success": True,
|
|
109
109
|
"stdout": result,
|
|
@@ -120,14 +120,14 @@ class AskCodebaseTool:
|
|
|
120
120
|
"stdout": "",
|
|
121
121
|
"stderr": error_msg
|
|
122
122
|
}
|
|
123
|
-
|
|
123
|
+
|
|
124
124
|
def _create_system_prompt(self, question: str, git_root: str) -> str:
|
|
125
125
|
"""创建Agent的system prompt
|
|
126
|
-
|
|
126
|
+
|
|
127
127
|
Args:
|
|
128
128
|
question: 用户问题
|
|
129
129
|
git_root: Git仓库根目录
|
|
130
|
-
|
|
130
|
+
|
|
131
131
|
Returns:
|
|
132
132
|
系统提示文本
|
|
133
133
|
"""
|
|
@@ -141,16 +141,16 @@ class AskCodebaseTool:
|
|
|
141
141
|
- 代码库根目录: {git_root}
|
|
142
142
|
|
|
143
143
|
## 工具使用优先级
|
|
144
|
-
1. **绝对优先使用 execute_shell**:
|
|
144
|
+
1. **绝对优先使用 execute_shell**:
|
|
145
145
|
- 使用 fd 查找文件: `fd -t f -e py` 查找Python文件等
|
|
146
146
|
- 使用 rg 搜索代码: `rg "pattern" --type py` 在Python文件中搜索等
|
|
147
|
-
- 使用 loc 统计代码: `loc
|
|
147
|
+
- 使用 loc 统计代码: `loc"` 统计代码量
|
|
148
148
|
|
|
149
|
-
2. **优先使用 read_code**:
|
|
149
|
+
2. **优先使用 read_code**:
|
|
150
150
|
- 找到相关文件后优先使用read_code读取文件内容
|
|
151
151
|
- 对大文件使用行范围参数读取指定区域
|
|
152
152
|
|
|
153
|
-
3. **避免使用 rag**:
|
|
153
|
+
3. **避免使用 rag**:
|
|
154
154
|
- 仅在fd、rg和read_code无法解决问题时作为最后手段
|
|
155
155
|
- 使用rag前必须先尝试使用shell命令解决问题
|
|
156
156
|
|
|
@@ -206,10 +206,10 @@ class AskCodebaseTool:
|
|
|
206
206
|
|
|
207
207
|
def _create_summary_prompt(self, question: str) -> str:
|
|
208
208
|
"""创建Agent的summary prompt
|
|
209
|
-
|
|
209
|
+
|
|
210
210
|
Args:
|
|
211
211
|
question: 用户问题
|
|
212
|
-
|
|
212
|
+
|
|
213
213
|
Returns:
|
|
214
214
|
总结提示文本
|
|
215
215
|
"""
|
|
@@ -257,7 +257,7 @@ class AskCodebaseTool:
|
|
|
257
257
|
def main():
|
|
258
258
|
"""
|
|
259
259
|
命令行入口点,允许将ask_codebase作为独立脚本运行
|
|
260
|
-
|
|
260
|
+
|
|
261
261
|
用法示例:
|
|
262
262
|
```
|
|
263
263
|
python -m jarvis.jarvis_tools.ask_codebase "登录功能在哪个文件实现?" --root_dir /path/to/codebase
|
|
@@ -267,22 +267,22 @@ def main():
|
|
|
267
267
|
import sys
|
|
268
268
|
|
|
269
269
|
init_env()
|
|
270
|
-
|
|
270
|
+
|
|
271
271
|
# 创建命令行参数解析器
|
|
272
272
|
parser = argparse.ArgumentParser(description="智能代码库查询工具")
|
|
273
273
|
parser.add_argument("question", help="关于代码库的问题")
|
|
274
274
|
parser.add_argument("--root_dir", "-d", default=".", help="代码库根目录路径")
|
|
275
|
-
|
|
275
|
+
|
|
276
276
|
# 解析命令行参数
|
|
277
277
|
args = parser.parse_args()
|
|
278
|
-
|
|
278
|
+
|
|
279
279
|
# 创建并执行工具
|
|
280
280
|
tool = AskCodebaseTool(auto_complete=False)
|
|
281
281
|
result = tool.execute({
|
|
282
282
|
"question": args.question,
|
|
283
283
|
"root_dir": args.root_dir
|
|
284
284
|
})
|
|
285
|
-
|
|
285
|
+
|
|
286
286
|
# 输出结果
|
|
287
287
|
if result["success"]:
|
|
288
288
|
PrettyOutput.print(result["stdout"], OutputType.SUCCESS)
|
jarvis/jarvis_tools/ask_user.py
CHANGED
|
@@ -16,35 +16,35 @@ class AskUserTool:
|
|
|
16
16
|
},
|
|
17
17
|
"required": ["question"]
|
|
18
18
|
}
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
|
|
21
21
|
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
22
22
|
"""Execute the operation of asking the user
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
Args:
|
|
25
25
|
args: A dictionary containing the question
|
|
26
|
-
|
|
26
|
+
|
|
27
27
|
Returns:
|
|
28
28
|
Dict: A dictionary containing the user's response
|
|
29
29
|
"""
|
|
30
30
|
try:
|
|
31
31
|
question = args["question"]
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
# Display the question
|
|
34
34
|
PrettyOutput.print(f"问题: {question}", OutputType.SYSTEM)
|
|
35
|
-
|
|
35
|
+
|
|
36
36
|
# Get user input
|
|
37
37
|
user_response = get_multiline_input("请输入您的答案 (输入空行结束)")
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
return {
|
|
40
40
|
"success": True,
|
|
41
41
|
"stdout": user_response,
|
|
42
42
|
"stderr": ""
|
|
43
43
|
}
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
except Exception as e:
|
|
46
46
|
return {
|
|
47
47
|
"success": False,
|
|
48
48
|
"stdout": "",
|
|
49
49
|
"stderr": f"Failed to ask user: {str(e)}"
|
|
50
|
-
}
|
|
50
|
+
}
|
jarvis/jarvis_tools/base.py
CHANGED
|
@@ -2,11 +2,11 @@ from typing import Dict, Any, Callable
|
|
|
2
2
|
import json
|
|
3
3
|
class Tool:
|
|
4
4
|
"""工具类,用于封装工具的基本信息和执行方法"""
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
def __init__(self, name: str, description: str, parameters: Dict, func: Callable):
|
|
7
7
|
"""
|
|
8
8
|
初始化工具对象
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
参数:
|
|
11
11
|
name (str): 工具名称
|
|
12
12
|
description (str): 工具描述
|
|
@@ -27,10 +27,10 @@ class Tool:
|
|
|
27
27
|
def execute(self, arguments: Dict) -> Dict[str, Any]:
|
|
28
28
|
"""
|
|
29
29
|
执行工具函数
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
参数:
|
|
32
32
|
arguments (Dict): 工具执行所需的参数
|
|
33
|
-
|
|
33
|
+
|
|
34
34
|
返回:
|
|
35
35
|
Dict[str, Any]: 工具执行结果
|
|
36
36
|
"""
|
jarvis/jarvis_tools/chdir.py
CHANGED
|
@@ -14,19 +14,19 @@ class ChdirTool:
|
|
|
14
14
|
},
|
|
15
15
|
"required": ["path"]
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
19
19
|
"""执行目录切换操作,并提供全面的错误处理。
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
参数:
|
|
22
22
|
args: 包含 'path' 键的字典,目标目录路径
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
返回:
|
|
25
25
|
字典,包含以下内容:
|
|
26
26
|
- success: 布尔值,表示操作状态
|
|
27
27
|
- stdout: 成功消息或空字符串
|
|
28
28
|
- stderr: 错误消息或空字符串
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
异常处理:
|
|
31
31
|
处理并返回适当的错误消息:
|
|
32
32
|
- 不存在的路径
|
|
@@ -39,7 +39,7 @@ class ChdirTool:
|
|
|
39
39
|
# 规范化并展开输入路径(处理 ~ 和相对路径)
|
|
40
40
|
path = os.path.expanduser(args["path"].strip())
|
|
41
41
|
path = os.path.abspath(path)
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
# 验证目标路径是否存在
|
|
44
44
|
if not os.path.exists(path):
|
|
45
45
|
return {
|
|
@@ -47,7 +47,7 @@ class ChdirTool:
|
|
|
47
47
|
"stdout": "",
|
|
48
48
|
"stderr": f"目录不存在: {path}"
|
|
49
49
|
}
|
|
50
|
-
|
|
50
|
+
|
|
51
51
|
# 确保路径指向的是目录,而不是文件
|
|
52
52
|
if not os.path.isdir(path):
|
|
53
53
|
return {
|
|
@@ -55,17 +55,17 @@ class ChdirTool:
|
|
|
55
55
|
"stdout": "",
|
|
56
56
|
"stderr": f"路径不是目录: {path}"
|
|
57
57
|
}
|
|
58
|
-
|
|
58
|
+
|
|
59
59
|
# 获取当前目录并尝试切换到新路径
|
|
60
60
|
old_path = os.getcwd()
|
|
61
61
|
os.chdir(path)
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
return {
|
|
64
64
|
"success": True,
|
|
65
65
|
"stdout": f"成功切换工作目录:\n原目录: {old_path}\n新目录: {path}",
|
|
66
66
|
"stderr": ""
|
|
67
67
|
}
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
# 处理用户没有目录访问权限的情况
|
|
70
70
|
except PermissionError:
|
|
71
71
|
return {
|
|
@@ -53,14 +53,14 @@ class CodeReviewTool:
|
|
|
53
53
|
try:
|
|
54
54
|
review_type = args.get("review_type", "current").strip()
|
|
55
55
|
root_dir = args.get("root_dir", ".")
|
|
56
|
-
|
|
56
|
+
|
|
57
57
|
# Store current directory
|
|
58
58
|
original_dir = os.getcwd()
|
|
59
|
-
|
|
59
|
+
|
|
60
60
|
try:
|
|
61
61
|
# Change to root_dir
|
|
62
62
|
os.chdir(root_dir)
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
# Build git diff command based on review type
|
|
65
65
|
with yaspin(text="正在获取代码变更...", color="cyan") as spinner:
|
|
66
66
|
if review_type == "commit":
|
|
@@ -93,7 +93,7 @@ class CodeReviewTool:
|
|
|
93
93
|
diff_cmd = ReadCodeTool().execute({"files": [{"path": file_path}]})["stdout"]
|
|
94
94
|
else: # current changes
|
|
95
95
|
diff_cmd = "git diff HEAD | cat -"
|
|
96
|
-
|
|
96
|
+
|
|
97
97
|
# Execute git diff command
|
|
98
98
|
try:
|
|
99
99
|
diff_output = subprocess.check_output(diff_cmd, shell=True, text=True)
|
|
@@ -224,9 +224,9 @@ class CodeReviewTool:
|
|
|
224
224
|
- **位置**: [起始行号-结束行号]
|
|
225
225
|
- **分类**: [使用SCRIPPPS框架中相关类别]
|
|
226
226
|
- **严重程度**: [P0/P1/P2/P3] - [简要说明判定理由]
|
|
227
|
-
- **问题描述**:
|
|
227
|
+
- **问题描述**:
|
|
228
228
|
[详细描述问题,包括技术原理和潜在影响]
|
|
229
|
-
- **改进建议**:
|
|
229
|
+
- **改进建议**:
|
|
230
230
|
```
|
|
231
231
|
[提供完整、可执行的代码示例,而非概念性建议]
|
|
232
232
|
```
|
|
@@ -259,14 +259,14 @@ class CodeReviewTool:
|
|
|
259
259
|
finally:
|
|
260
260
|
# Always restore original directory
|
|
261
261
|
os.chdir(original_dir)
|
|
262
|
-
|
|
262
|
+
|
|
263
263
|
except Exception as e:
|
|
264
264
|
return {
|
|
265
265
|
"success": False,
|
|
266
266
|
"stdout": {},
|
|
267
267
|
"stderr": f"Review failed: {str(e)}"
|
|
268
268
|
}
|
|
269
|
-
|
|
269
|
+
|
|
270
270
|
|
|
271
271
|
def extract_code_report(result: str) -> str:
|
|
272
272
|
sm = re.search(ot("REPORT")+r'\n(.*?)\n'+ct("REPORT"), result, re.DOTALL)
|
|
@@ -279,33 +279,33 @@ def main():
|
|
|
279
279
|
import argparse
|
|
280
280
|
|
|
281
281
|
init_env()
|
|
282
|
-
|
|
282
|
+
|
|
283
283
|
parser = argparse.ArgumentParser(description='Autonomous code review tool')
|
|
284
284
|
subparsers = parser.add_subparsers(dest='type')
|
|
285
|
-
|
|
285
|
+
|
|
286
286
|
# Commit subcommand
|
|
287
287
|
commit_parser = subparsers.add_parser('commit', help='Review specific commit')
|
|
288
288
|
commit_parser.add_argument('commit', help='Commit SHA to review')
|
|
289
|
-
|
|
289
|
+
|
|
290
290
|
# Current subcommand
|
|
291
291
|
current_parser = subparsers.add_parser('current', help='Review current changes')
|
|
292
|
-
|
|
292
|
+
|
|
293
293
|
# Range subcommand
|
|
294
294
|
range_parser = subparsers.add_parser('range', help='Review commit range')
|
|
295
295
|
range_parser.add_argument('start_commit', help='Start commit SHA')
|
|
296
296
|
range_parser.add_argument('end_commit', help='End commit SHA')
|
|
297
|
-
|
|
297
|
+
|
|
298
298
|
# File subcommand
|
|
299
299
|
file_parser = subparsers.add_parser('file', help='Review specific file')
|
|
300
300
|
file_parser.add_argument('file', help='File path to review')
|
|
301
|
-
|
|
301
|
+
|
|
302
302
|
# Common arguments
|
|
303
303
|
parser.add_argument('--root-dir', type=str, help='Root directory of the codebase', default=".")
|
|
304
|
-
|
|
304
|
+
|
|
305
305
|
# Set default subcommand to 'current'
|
|
306
306
|
parser.set_defaults(type='current')
|
|
307
307
|
args = parser.parse_args()
|
|
308
|
-
|
|
308
|
+
|
|
309
309
|
tool = CodeReviewTool()
|
|
310
310
|
tool_args = {
|
|
311
311
|
"review_type": args.type,
|
|
@@ -318,14 +318,14 @@ def main():
|
|
|
318
318
|
tool_args["end_commit"] = args.end_commit
|
|
319
319
|
elif args.type == 'file':
|
|
320
320
|
tool_args["file_path"] = args.file
|
|
321
|
-
|
|
321
|
+
|
|
322
322
|
result = tool.execute(tool_args)
|
|
323
|
-
|
|
323
|
+
|
|
324
324
|
if result["success"]:
|
|
325
325
|
PrettyOutput.section("自动代码审查结果:", OutputType.SUCCESS)
|
|
326
326
|
report = extract_code_report(result["stdout"])
|
|
327
327
|
PrettyOutput.print(report, OutputType.SUCCESS, lang="markdown")
|
|
328
|
-
|
|
328
|
+
|
|
329
329
|
else:
|
|
330
330
|
PrettyOutput.print(result["stderr"], OutputType.WARNING)
|
|
331
331
|
|
|
@@ -8,7 +8,7 @@ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
|
|
|
8
8
|
|
|
9
9
|
class CreateCodeAgentTool:
|
|
10
10
|
"""用于管理代码开发工作流的工具"""
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
name = "create_code_agent"
|
|
13
13
|
description = "技术代码实现和开发过程管理工具"
|
|
14
14
|
parameters = {
|
|
@@ -25,16 +25,16 @@ class CreateCodeAgentTool:
|
|
|
25
25
|
"default": "."
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
|
|
29
|
+
|
|
30
30
|
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
|
31
31
|
try:
|
|
32
32
|
requirement = args.get("requirement", "")
|
|
33
33
|
root_dir = args.get("root_dir", ".")
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
# Store current directory
|
|
36
36
|
original_dir = os.getcwd()
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
try:
|
|
39
39
|
# Change to root_dir
|
|
40
40
|
os.chdir(root_dir)
|
|
@@ -44,7 +44,7 @@ class CreateCodeAgentTool:
|
|
|
44
44
|
"stderr": "Requirement must be provided",
|
|
45
45
|
"stdout": ""
|
|
46
46
|
}
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
# Step 1: Handle uncommitted changes
|
|
49
49
|
start_commit = None
|
|
50
50
|
if has_uncommitted_changes():
|
|
@@ -57,18 +57,18 @@ class CreateCodeAgentTool:
|
|
|
57
57
|
"stderr": "Failed to commit changes: " + result["stderr"],
|
|
58
58
|
"stdout": ""
|
|
59
59
|
}
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
# Get current commit hash
|
|
62
62
|
start_commit = get_latest_commit_hash()
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
# Step 2: Development
|
|
65
65
|
PrettyOutput.print("开始开发...", OutputType.INFO)
|
|
66
66
|
agent = CodeAgent()
|
|
67
67
|
agent.run(requirement)
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
# Get new commit hash after development
|
|
70
70
|
end_commit = get_latest_commit_hash()
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
# Step 3: Code Review
|
|
73
73
|
PrettyOutput.print("开始代码审查...", OutputType.INFO)
|
|
74
74
|
reviewer = CodeReviewTool()
|
|
@@ -78,17 +78,17 @@ class CreateCodeAgentTool:
|
|
|
78
78
|
"end_commit": end_commit,
|
|
79
79
|
"root_dir": root_dir
|
|
80
80
|
})
|
|
81
|
-
|
|
81
|
+
|
|
82
82
|
if not review_result["success"]:
|
|
83
83
|
return {
|
|
84
84
|
"success": False,
|
|
85
85
|
"stderr": "Code review failed: " + review_result["stderr"],
|
|
86
86
|
"stdout": ""
|
|
87
87
|
}
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
# Step 4: Generate Summary
|
|
90
90
|
summary = f"""开发总结:
|
|
91
|
-
|
|
91
|
+
|
|
92
92
|
开始提交: {start_commit}
|
|
93
93
|
结束提交: {end_commit}
|
|
94
94
|
|
|
@@ -98,7 +98,7 @@ class CreateCodeAgentTool:
|
|
|
98
98
|
代码审查结果:
|
|
99
99
|
{extract_code_report(review_result["stdout"])}
|
|
100
100
|
"""
|
|
101
|
-
|
|
101
|
+
|
|
102
102
|
return {
|
|
103
103
|
"success": True,
|
|
104
104
|
"stdout": summary,
|
|
@@ -107,7 +107,7 @@ class CreateCodeAgentTool:
|
|
|
107
107
|
finally:
|
|
108
108
|
# Always restore original directory
|
|
109
109
|
os.chdir(original_dir)
|
|
110
|
-
|
|
110
|
+
|
|
111
111
|
except Exception as e:
|
|
112
112
|
return {
|
|
113
113
|
"success": False,
|
|
@@ -29,7 +29,7 @@ class PythonScriptTool:
|
|
|
29
29
|
"stdout": "",
|
|
30
30
|
"stderr": "Missing or empty script_content parameter"
|
|
31
31
|
}
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
# Create temporary script file
|
|
34
34
|
script_path = os.path.join(tempfile.gettempdir(), f"jarvis_script_{os.getpid()}.py")
|
|
35
35
|
try:
|
|
@@ -39,7 +39,7 @@ class PythonScriptTool:
|
|
|
39
39
|
from jarvis.jarvis_tools.execute_shell import ShellTool
|
|
40
40
|
shell_tool = ShellTool()
|
|
41
41
|
result = shell_tool.execute({"command": f"python3 {script_path}"})
|
|
42
|
-
|
|
42
|
+
|
|
43
43
|
return {
|
|
44
44
|
"success": result["success"],
|
|
45
45
|
"stdout": result["stdout"],
|
|
@@ -48,7 +48,7 @@ class PythonScriptTool:
|
|
|
48
48
|
finally:
|
|
49
49
|
# Clean up temporary script file
|
|
50
50
|
Path(script_path).unlink(missing_ok=True)
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
except Exception as e:
|
|
53
53
|
PrettyOutput.print(str(e), OutputType.ERROR)
|
|
54
54
|
return {
|