jarvis-ai-assistant 0.1.206__py3-none-any.whl → 0.1.208__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 (36) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/jarvis_agent/__init__.py +71 -61
  3. jarvis/jarvis_agent/edit_file_handler.py +42 -46
  4. jarvis/jarvis_agent/jarvis.py +33 -39
  5. jarvis/jarvis_code_agent/code_agent.py +26 -27
  6. jarvis/jarvis_code_agent/lint.py +5 -5
  7. jarvis/jarvis_code_analysis/code_review.py +164 -175
  8. jarvis/jarvis_data/config_schema.json +1 -1
  9. jarvis/jarvis_git_utils/git_commiter.py +147 -152
  10. jarvis/jarvis_methodology/main.py +70 -81
  11. jarvis/jarvis_platform/base.py +28 -23
  12. jarvis/jarvis_platform/kimi.py +39 -53
  13. jarvis/jarvis_platform/tongyi.py +108 -126
  14. jarvis/jarvis_platform/yuanbao.py +112 -120
  15. jarvis/jarvis_platform_manager/main.py +102 -502
  16. jarvis/jarvis_platform_manager/service.py +432 -0
  17. jarvis/jarvis_smart_shell/main.py +99 -33
  18. jarvis/jarvis_tools/edit_file.py +64 -55
  19. jarvis/jarvis_tools/file_analyzer.py +17 -25
  20. jarvis/jarvis_tools/read_code.py +80 -81
  21. jarvis/jarvis_utils/builtin_replace_map.py +1 -36
  22. jarvis/jarvis_utils/config.py +14 -4
  23. jarvis/jarvis_utils/git_utils.py +36 -35
  24. jarvis/jarvis_utils/methodology.py +12 -17
  25. {jarvis_ai_assistant-0.1.206.dist-info → jarvis_ai_assistant-0.1.208.dist-info}/METADATA +7 -16
  26. {jarvis_ai_assistant-0.1.206.dist-info → jarvis_ai_assistant-0.1.208.dist-info}/RECORD +30 -35
  27. {jarvis_ai_assistant-0.1.206.dist-info → jarvis_ai_assistant-0.1.208.dist-info}/entry_points.txt +0 -1
  28. jarvis/jarvis_dev/main.py +0 -1247
  29. jarvis/jarvis_tools/chdir.py +0 -72
  30. jarvis/jarvis_tools/code_plan.py +0 -218
  31. jarvis/jarvis_tools/create_code_agent.py +0 -95
  32. jarvis/jarvis_tools/create_sub_agent.py +0 -82
  33. jarvis/jarvis_tools/file_operation.py +0 -238
  34. {jarvis_ai_assistant-0.1.206.dist-info → jarvis_ai_assistant-0.1.208.dist-info}/WHEEL +0 -0
  35. {jarvis_ai_assistant-0.1.206.dist-info → jarvis_ai_assistant-0.1.208.dist-info}/licenses/LICENSE +0 -0
  36. {jarvis_ai_assistant-0.1.206.dist-info → jarvis_ai_assistant-0.1.208.dist-info}/top_level.txt +0 -0
@@ -1,238 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- import os
3
- from pathlib import Path
4
- from typing import Any, Dict
5
-
6
- from yaspin import yaspin # type: ignore
7
-
8
- # 导入文件处理器
9
- from jarvis.jarvis_utils.file_processors import TextFileProcessor
10
- from jarvis.jarvis_utils.output import OutputType, PrettyOutput
11
-
12
-
13
- class FileOperationTool:
14
- name = "file_operation"
15
- description = "文件批量操作工具,可批量读写多个文件,仅支持文本文件,适用于需要同时处理多个文件的场景(读取配置文件、保存生成内容等)"
16
- parameters = {
17
- "type": "object",
18
- "properties": {
19
- "operation": {
20
- "type": "string",
21
- "enum": ["read", "write"],
22
- "description": "要执行的文件操作类型(读取或写入多个文件)",
23
- },
24
- "files": {
25
- "type": "array",
26
- "items": {
27
- "type": "object",
28
- "properties": {
29
- "path": {"type": "string"},
30
- "content": {"type": "string"},
31
- },
32
- "required": ["path"],
33
- },
34
- "description": "要操作的文件列表",
35
- },
36
- },
37
- "required": ["operation", "files"],
38
- }
39
-
40
- def _get_file_processor(self, file_path: str):
41
- """获取适合处理指定文件的处理器"""
42
- processors = [TextFileProcessor] # 文本文件处理器(放在最后作为兜底)
43
-
44
- for processor in processors:
45
- if processor.can_handle(file_path):
46
- return processor
47
-
48
- return None # 如果没有合适的处理器,返回None
49
-
50
- def _handle_single_file(
51
- self,
52
- operation: str,
53
- filepath: str,
54
- content: str = "",
55
- start_line: int = 1,
56
- end_line: int = -1,
57
- agent: Any = None,
58
- ) -> Dict[str, Any]:
59
- """Handle operations for a single file"""
60
- try:
61
- abs_path = os.path.abspath(filepath)
62
-
63
- if operation == "read":
64
- with yaspin(
65
- text=f"正在读取文件: {abs_path}...", color="cyan"
66
- ) as spinner:
67
- if not os.path.exists(abs_path):
68
- return {
69
- "success": False,
70
- "stdout": "",
71
- "stderr": f"文件不存在: {abs_path}",
72
- }
73
-
74
- # 检查文件大小
75
- if os.path.getsize(abs_path) > 30 * 1024 * 1024: # 30MB
76
- return {
77
- "success": False,
78
- "stdout": "",
79
- "stderr": "文件过大 (>30MB),无法处理",
80
- }
81
-
82
- file_extension = Path(abs_path).suffix.lower()
83
-
84
- # 获取文件处理器
85
- processor = self._get_file_processor(abs_path)
86
-
87
- if processor is None:
88
- return {
89
- "success": False,
90
- "stdout": "",
91
- "stderr": f"不支持的文件类型: {file_extension}",
92
- }
93
-
94
- # 特殊处理纯文本文件,支持行范围选择
95
- if processor == TextFileProcessor:
96
- try:
97
- with open(
98
- abs_path, "r", encoding="utf-8", errors="ignore"
99
- ) as f:
100
- lines = f.readlines()
101
-
102
- total_lines = len(lines)
103
- start_line = (
104
- start_line
105
- if start_line >= 0
106
- else total_lines + start_line + 1
107
- )
108
- end_line = (
109
- end_line
110
- if end_line >= 0
111
- else total_lines + end_line + 1
112
- )
113
- start_line = max(1, min(start_line, total_lines))
114
- end_line = max(1, min(end_line, total_lines))
115
- if end_line == -1:
116
- end_line = total_lines
117
-
118
- if start_line > end_line:
119
- spinner.text = "无效的行范围"
120
- spinner.fail("❌")
121
- error_msg = f"无效的行范围 [{start_line, end_line}] (文件总行数: {total_lines})"
122
- return {
123
- "success": False,
124
- "stdout": "",
125
- "stderr": error_msg,
126
- }
127
-
128
- content = "".join(lines[start_line - 1 : end_line])
129
- file_info = f"\n文件: {abs_path} (文本文件)\n行: [{start_line}-{end_line}]/{total_lines}"
130
- except Exception as e:
131
- return {
132
- "success": False,
133
- "stdout": "",
134
- "stderr": f"读取文本文件失败: {str(e)}",
135
- }
136
- else:
137
- return {
138
- "success": False,
139
- "stdout": "",
140
- "stderr": f"不支持的文件类型: {file_extension}",
141
- }
142
-
143
- # 构建输出信息
144
- output = f"{file_info}\n{content}" + "\n\n"
145
-
146
- spinner.text = f"文件读取完成: {abs_path}"
147
- spinner.ok("✅")
148
-
149
- if agent:
150
- files = agent.get_user_data("files")
151
- if files:
152
- files.append(abs_path)
153
- else:
154
- files = [abs_path]
155
- agent.set_user_data("files", files)
156
-
157
- return {"success": True, "stdout": output, "stderr": ""}
158
- elif operation == "write":
159
- with yaspin(
160
- text=f"正在写入文件: {abs_path}...", color="cyan"
161
- ) as spinner:
162
- os.makedirs(
163
- os.path.dirname(os.path.abspath(abs_path)), exist_ok=True
164
- )
165
- with open(abs_path, "w", encoding="utf-8", errors="ignore") as f:
166
- f.write(content)
167
- spinner.text = f"文件写入完成: {abs_path}"
168
- spinner.ok("✅")
169
- return {
170
- "success": True,
171
- "stdout": f"文件写入成功: {abs_path}",
172
- "stderr": "",
173
- }
174
- return {"success": False, "stdout": "", "stderr": f"未知操作: {operation}"}
175
-
176
- except Exception as e:
177
- PrettyOutput.print(str(e), OutputType.ERROR)
178
- return {
179
- "success": False,
180
- "stdout": "",
181
- "stderr": f"文件操作失败 {abs_path}: {str(e)}",
182
- }
183
-
184
- def execute(self, args: Dict) -> Dict[str, Any]:
185
- """Execute file operations for multiple files
186
-
187
- Args:
188
- args: Dictionary containing operation and files list
189
-
190
- Returns:
191
- Dict containing:
192
- - success: Boolean indicating overall success
193
- - stdout: Combined output of all operations as string
194
- - stderr: Error message if any
195
- """
196
- try:
197
- operation = args["operation"].strip()
198
- agent = args.get("agent", None)
199
- if "files" not in args or not isinstance(args["files"], list):
200
- return {
201
- "success": False,
202
- "stdout": "",
203
- "stderr": "files参数是必需的,且必须是一个列表",
204
- }
205
-
206
- all_outputs = []
207
- success = True
208
-
209
- for file_info in args["files"]:
210
- if not isinstance(file_info, dict) or "path" not in file_info:
211
- continue
212
-
213
- content = file_info.get("content", "") if operation == "write" else ""
214
- result = self._handle_single_file(
215
- operation,
216
- file_info["path"].strip(),
217
- content,
218
- file_info.get("start_line", 1),
219
- file_info.get("end_line", -1),
220
- agent,
221
- )
222
-
223
- if result["success"]:
224
- all_outputs.append(result["stdout"])
225
- else:
226
- all_outputs.append(
227
- f"处理文件 {file_info['path']} 时出错: {result['stderr']}"
228
- )
229
- success = success and result["success"]
230
-
231
- # Combine all outputs with separators
232
- combined_output = "\n\n" + "=" * 80 + "\n\n".join(all_outputs)
233
-
234
- return {"success": success, "stdout": combined_output, "stderr": ""}
235
-
236
- except Exception as e:
237
- PrettyOutput.print(str(e), OutputType.ERROR)
238
- return {"success": False, "stdout": "", "stderr": f"文件操作失败: {str(e)}"}