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.

Files changed (78) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +201 -79
  3. jarvis/jarvis_agent/builtin_input_handler.py +16 -6
  4. jarvis/jarvis_agent/file_input_handler.py +9 -9
  5. jarvis/jarvis_agent/jarvis.py +10 -10
  6. jarvis/jarvis_agent/main.py +12 -11
  7. jarvis/jarvis_agent/output_handler.py +3 -3
  8. jarvis/jarvis_agent/patch.py +86 -62
  9. jarvis/jarvis_agent/shell_input_handler.py +5 -3
  10. jarvis/jarvis_code_agent/code_agent.py +134 -99
  11. jarvis/jarvis_code_agent/file_select.py +24 -24
  12. jarvis/jarvis_dev/main.py +45 -51
  13. jarvis/jarvis_git_details/__init__.py +0 -0
  14. jarvis/jarvis_git_details/main.py +179 -0
  15. jarvis/jarvis_git_squash/main.py +7 -7
  16. jarvis/jarvis_lsp/base.py +11 -11
  17. jarvis/jarvis_lsp/cpp.py +14 -14
  18. jarvis/jarvis_lsp/go.py +13 -13
  19. jarvis/jarvis_lsp/python.py +8 -8
  20. jarvis/jarvis_lsp/registry.py +21 -21
  21. jarvis/jarvis_lsp/rust.py +15 -15
  22. jarvis/jarvis_methodology/main.py +101 -0
  23. jarvis/jarvis_multi_agent/__init__.py +11 -11
  24. jarvis/jarvis_multi_agent/main.py +6 -6
  25. jarvis/jarvis_platform/__init__.py +1 -1
  26. jarvis/jarvis_platform/ai8.py +67 -89
  27. jarvis/jarvis_platform/base.py +14 -13
  28. jarvis/jarvis_platform/kimi.py +25 -28
  29. jarvis/jarvis_platform/ollama.py +24 -26
  30. jarvis/jarvis_platform/openai.py +15 -19
  31. jarvis/jarvis_platform/oyi.py +48 -50
  32. jarvis/jarvis_platform/registry.py +27 -28
  33. jarvis/jarvis_platform/yuanbao.py +38 -42
  34. jarvis/jarvis_platform_manager/main.py +81 -81
  35. jarvis/jarvis_platform_manager/openai_test.py +21 -21
  36. jarvis/jarvis_rag/file_processors.py +18 -18
  37. jarvis/jarvis_rag/main.py +261 -277
  38. jarvis/jarvis_smart_shell/main.py +12 -12
  39. jarvis/jarvis_tools/ask_codebase.py +28 -28
  40. jarvis/jarvis_tools/ask_user.py +8 -8
  41. jarvis/jarvis_tools/base.py +4 -4
  42. jarvis/jarvis_tools/chdir.py +9 -9
  43. jarvis/jarvis_tools/code_review.py +19 -19
  44. jarvis/jarvis_tools/create_code_agent.py +15 -15
  45. jarvis/jarvis_tools/execute_python_script.py +3 -3
  46. jarvis/jarvis_tools/execute_shell.py +11 -11
  47. jarvis/jarvis_tools/execute_shell_script.py +3 -3
  48. jarvis/jarvis_tools/file_analyzer.py +29 -29
  49. jarvis/jarvis_tools/file_operation.py +22 -20
  50. jarvis/jarvis_tools/find_caller.py +25 -25
  51. jarvis/jarvis_tools/find_methodolopy.py +65 -0
  52. jarvis/jarvis_tools/find_symbol.py +24 -24
  53. jarvis/jarvis_tools/function_analyzer.py +27 -27
  54. jarvis/jarvis_tools/git_commiter.py +9 -9
  55. jarvis/jarvis_tools/lsp_get_diagnostics.py +19 -19
  56. jarvis/jarvis_tools/methodology.py +23 -62
  57. jarvis/jarvis_tools/project_analyzer.py +29 -33
  58. jarvis/jarvis_tools/rag.py +15 -15
  59. jarvis/jarvis_tools/read_code.py +24 -22
  60. jarvis/jarvis_tools/read_webpage.py +31 -31
  61. jarvis/jarvis_tools/registry.py +72 -52
  62. jarvis/jarvis_tools/tool_generator.py +18 -18
  63. jarvis/jarvis_utils/config.py +23 -23
  64. jarvis/jarvis_utils/embedding.py +83 -83
  65. jarvis/jarvis_utils/git_utils.py +20 -20
  66. jarvis/jarvis_utils/globals.py +18 -6
  67. jarvis/jarvis_utils/input.py +10 -9
  68. jarvis/jarvis_utils/methodology.py +140 -136
  69. jarvis/jarvis_utils/output.py +11 -11
  70. jarvis/jarvis_utils/utils.py +22 -70
  71. {jarvis_ai_assistant-0.1.134.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/METADATA +1 -1
  72. jarvis_ai_assistant-0.1.138.dist-info/RECORD +85 -0
  73. {jarvis_ai_assistant-0.1.134.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/entry_points.txt +2 -0
  74. jarvis/jarvis_tools/select_code_files.py +0 -62
  75. jarvis_ai_assistant-0.1.134.dist-info/RECORD +0 -82
  76. {jarvis_ai_assistant-0.1.134.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/LICENSE +0 -0
  77. {jarvis_ai_assistant-0.1.134.dist-info → jarvis_ai_assistant-0.1.138.dist-info}/WHEEL +0 -0
  78. {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 --include="*.py"` 统计Python代码量等
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)
@@ -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
+ }
@@ -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
  """
@@ -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 {