jarvis-ai-assistant 0.1.181__py3-none-any.whl → 0.1.182__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 CHANGED
@@ -1,4 +1,4 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """Jarvis AI Assistant"""
3
3
 
4
- __version__ = "0.1.181"
4
+ __version__ = "0.1.182"
@@ -2,7 +2,7 @@
2
2
  # 标准库导入
3
3
  import datetime
4
4
  import platform
5
- from typing import Any, Callable, List, Optional, Protocol, Tuple, Union
5
+ from typing import Any, Callable, Dict, List, Optional, Protocol, Tuple, Union
6
6
 
7
7
  # 第三方库导入
8
8
  from yaspin import yaspin # type: ignore
@@ -205,6 +205,8 @@ class Agent:
205
205
  if model_name is not None:
206
206
  self.model.set_model_name(model_name)
207
207
 
208
+ self.user_data: Dict[str, Any] = {}
209
+
208
210
  self.model.set_suppress_output(False)
209
211
 
210
212
  from jarvis.jarvis_tools.registry import ToolRegistry
@@ -319,6 +321,14 @@ class Agent:
319
321
  )
320
322
  self.first = True
321
323
 
324
+ def set_user_data(self, key: str, value: Any):
325
+ """设置用户数据"""
326
+ self.user_data[key] = value
327
+
328
+ def get_user_data(self, key: str) -> Optional[Any]:
329
+ """获取用户数据"""
330
+ return self.user_data.get(key, None)
331
+
322
332
  def set_use_tools(self, use_tools):
323
333
  """设置要使用的工具列表"""
324
334
  from jarvis.jarvis_tools.registry import ToolRegistry
@@ -372,7 +382,7 @@ class Agent:
372
382
  )
373
383
 
374
384
  addon_prompt = f"""
375
- [系统提示开始]
385
+ <system_prompt>
376
386
  请判断是否已经完成任务,如果已经完成:
377
387
  - 直接输出完成原因,不需要再有新的操作,不要输出{ot("TOOL_CALL")}标签
378
388
  {complete_prompt}
@@ -381,7 +391,7 @@ class Agent:
381
391
  - 如果信息不明确,请请求用户补充
382
392
  - 如果执行过程中连续失败5次,请使用ask_user询问用户操作
383
393
  - 操作列表:{action_handlers}
384
- [系统提示结束]
394
+ </system_prompt>
385
395
 
386
396
  请继续。
387
397
  """
@@ -0,0 +1,112 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+
4
+ import os
5
+ import re
6
+ from typing import Any, Tuple
7
+
8
+ from yaspin import yaspin
9
+
10
+ from jarvis.jarvis_tools.file_operation import FileOperationTool
11
+ from jarvis.jarvis_utils.output import OutputType, PrettyOutput
12
+ from jarvis.jarvis_utils.utils import is_context_overflow
13
+
14
+
15
+ def file_input_handler(user_input: str, agent: Any) -> Tuple[str, bool]:
16
+ """Process user input containing file references and read file contents.
17
+
18
+ Args:
19
+ user_input: Input string that may contain file references in format:
20
+ - 'file_path' (whole file)
21
+ - 'file_path:start_line,end_line' (line range)
22
+ - 'file_path:start_line:end_line' (alternative range format)
23
+ agent: Agent object for further processing (currently unused)
24
+
25
+ Returns:
26
+ Tuple[str, bool]:
27
+ - Processed prompt string with file contents prepended
28
+ - Boolean indicating if context overflow occurred
29
+ """
30
+ prompt = user_input
31
+ files = []
32
+
33
+ file_refs = re.findall(r"'([^']+)'", user_input)
34
+ for ref in file_refs:
35
+ # Handle file:start,end or file:start:end format
36
+ if ':' in ref:
37
+ file_path, line_range = ref.split(':', 1)
38
+ # Initialize with default values
39
+ start_line = 1 # 1-based
40
+ end_line = -1
41
+
42
+ # Process line range if specified
43
+ if ',' in line_range or ':' in line_range:
44
+ try:
45
+ raw_start, raw_end = map(int, re.split(r'[,:]', line_range))
46
+
47
+ # Handle special values and Python-style negative indices
48
+ try:
49
+ with open(file_path, 'r', encoding='utf-8', errors="ignore") as f:
50
+ total_lines = len(f.readlines())
51
+ except FileNotFoundError:
52
+ PrettyOutput.print(f"文件不存在: {file_path}", OutputType.WARNING)
53
+ continue
54
+ # Process start line (0 means whole file, negative means from end)
55
+ if raw_start == 0: # 0表示整个文件
56
+ start_line = 1
57
+ end_line = total_lines
58
+ else:
59
+ start_line = raw_start if raw_start > 0 else total_lines + raw_start + 1
60
+
61
+ # Process end line
62
+ if raw_end == 0: # 0表示整个文件(如果start也是0)
63
+ end_line = total_lines
64
+ else:
65
+ end_line = raw_end if raw_end > 0 else total_lines + raw_end + 1
66
+
67
+ # Auto-correct ranges
68
+ start_line = max(1, min(start_line, total_lines))
69
+ end_line = max(start_line, min(end_line, total_lines))
70
+
71
+ # Final validation
72
+ if start_line < 1 or end_line > total_lines or start_line > end_line:
73
+ raise ValueError
74
+
75
+ except:
76
+ continue
77
+
78
+ # Add file if it exists
79
+ if os.path.isfile(file_path):
80
+ files.append({
81
+ "path": file_path,
82
+ "start_line": start_line,
83
+ "end_line": end_line
84
+ })
85
+ else:
86
+ # Handle simple file path
87
+ if os.path.isfile(ref):
88
+ files.append({
89
+ "path": ref,
90
+ "start_line": 1, # 1-based
91
+ "end_line": -1
92
+ })
93
+
94
+ # Read and process files if any were found
95
+ if files:
96
+ with yaspin(text="正在读取文件...", color="cyan") as spinner:
97
+ old_prompt = prompt
98
+ result = FileOperationTool().execute({"operation":"read","files": files})
99
+ if result["success"]:
100
+ spinner.text = "文件读取完成"
101
+ spinner.ok("✅")
102
+ # Prepend file contents to prompt and check for overflow
103
+ prompt = f"""{prompt}
104
+
105
+ <file_context>
106
+ {result["stdout"]}
107
+ </file_context>"""
108
+ if is_context_overflow(prompt):
109
+ return old_prompt, False
110
+
111
+ return prompt, False
112
+
@@ -15,6 +15,7 @@ from yaspin import yaspin # type: ignore
15
15
  from jarvis import __version__
16
16
  from jarvis.jarvis_agent import Agent
17
17
  from jarvis.jarvis_agent.builtin_input_handler import builtin_input_handler
18
+ from jarvis.jarvis_agent.file_input_handler import file_input_handler
18
19
  from jarvis.jarvis_agent.shell_input_handler import shell_input_handler
19
20
  # 忽略yaspin的类型检查
20
21
  from jarvis.jarvis_code_agent.lint import get_lint_tools
@@ -108,6 +109,7 @@ class CodeAgent:
108
109
  output_handler=[tool_registry],
109
110
  platform=platform_instance,
110
111
  input_handler=[
112
+ file_input_handler,
111
113
  shell_input_handler,
112
114
  builtin_input_handler
113
115
  ],
@@ -138,6 +138,7 @@ class FileSearchReplaceTool:
138
138
 
139
139
  file_path = args["file"]
140
140
  changes = args["changes"]
141
+ agent = args.get("agent", None)
141
142
 
142
143
  # 创建已处理文件变量,用于失败时回滚
143
144
  original_content = None
@@ -153,6 +154,17 @@ class FileSearchReplaceTool:
153
154
  with open(file_path, 'r', encoding='utf-8') as f:
154
155
  content = f.read()
155
156
  original_content = content
157
+
158
+ if file_exists and agent:
159
+ files = agent.get_user_data("files")
160
+ if not files or files.get(file_path, None) is None:
161
+ return {
162
+ "success": False,
163
+ "stdout": "",
164
+ "stderr": f"请先读取文件 {file_path} 的内容后再编辑"
165
+ }
166
+
167
+
156
168
  with yaspin(text=f"正在处理文件 {file_path}...", color="cyan") as spinner:
157
169
  success, temp_content = fast_edit(file_path, changes, spinner)
158
170
  if not success:
@@ -50,7 +50,7 @@ class FileOperationTool:
50
50
  return None # 如果没有合适的处理器,返回None
51
51
 
52
52
  def _handle_single_file(self, operation: str, filepath: str, content: str = "",
53
- start_line: int = 1, end_line: int = -1) -> Dict[str, Any]:
53
+ start_line: int = 1, end_line: int = -1, agent: Any = None) -> Dict[str, Any]:
54
54
  """Handle operations for a single file"""
55
55
  try:
56
56
  abs_path = os.path.abspath(filepath)
@@ -128,6 +128,15 @@ class FileOperationTool:
128
128
 
129
129
  spinner.text = f"文件读取完成: {abs_path}"
130
130
  spinner.ok("✅")
131
+
132
+ if agent:
133
+ files = agent.get_user_data("files")
134
+ if files:
135
+ files.append(abs_path)
136
+ else:
137
+ files = [abs_path]
138
+ agent.set_user_data("files", files)
139
+
131
140
  return {
132
141
  "success": True,
133
142
  "stdout": output,
@@ -173,7 +182,7 @@ class FileOperationTool:
173
182
  """
174
183
  try:
175
184
  operation = args["operation"].strip()
176
-
185
+ agent = args.get("agent", None)
177
186
  if "files" not in args or not isinstance(args["files"], list):
178
187
  return {
179
188
  "success": False,
@@ -194,7 +203,8 @@ class FileOperationTool:
194
203
  file_info["path"].strip(),
195
204
  content,
196
205
  file_info.get("start_line", 1),
197
- file_info.get("end_line", -1)
206
+ file_info.get("end_line", -1),
207
+ agent
198
208
  )
199
209
 
200
210
  if result["success"]:
@@ -31,7 +31,7 @@ class ReadCodeTool:
31
31
  "required": ["files"]
32
32
  }
33
33
 
34
- def _handle_single_file(self, filepath: str, start_line: int = 1, end_line: int = -1) -> Dict[str, Any]:
34
+ def _handle_single_file(self, filepath: str, start_line: int = 1, end_line: int = -1, agent: Any = None) -> Dict[str, Any]:
35
35
  """处理单个文件的读取操作
36
36
 
37
37
  Args:
@@ -99,6 +99,14 @@ class ReadCodeTool:
99
99
  spinner.text = f"文件读取完成: {abs_path}"
100
100
  spinner.ok("✅")
101
101
 
102
+ if agent:
103
+ files = agent.get_user_data("files")
104
+ if files:
105
+ files.append(abs_path)
106
+ else:
107
+ files = [abs_path]
108
+ agent.set_user_data("files", files)
109
+
102
110
  return {
103
111
  "success": True,
104
112
  "stdout": output,
@@ -123,6 +131,7 @@ class ReadCodeTool:
123
131
  Dict[str, Any]: 包含成功状态、输出内容和错误信息的字典
124
132
  """
125
133
  try:
134
+ agent = args.get("agent", None)
126
135
  if "files" not in args or not isinstance(args["files"], list):
127
136
  return {
128
137
  "success": False,
@@ -140,7 +149,8 @@ class ReadCodeTool:
140
149
  result = self._handle_single_file(
141
150
  file_info["path"].strip(),
142
151
  file_info.get("start_line", 1),
143
- file_info.get("end_line", -1)
152
+ file_info.get("end_line", -1),
153
+ agent
144
154
  )
145
155
 
146
156
  if result["success"]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.181
3
+ Version: 0.1.182
4
4
  Summary: Jarvis: An AI assistant that uses tools to interact with the system
5
5
  Home-page: https://github.com/skyfireitdiy/Jarvis
6
6
  Author: skyfire
@@ -1,12 +1,13 @@
1
- jarvis/__init__.py,sha256=dgQhg6Gd7pGul0ij7e_dHnY6CjyGHRhshKt8hag08qo,74
2
- jarvis/jarvis_agent/__init__.py,sha256=9vyME5JbA4koVoqJ_zv5N9eNdvu6iBkB4o4a1CmkVgA,30054
1
+ jarvis/__init__.py,sha256=0L3xbrhIunJRm7imt5CFTJQk-Ck5Or4XgYyygPYg_Dg,74
2
+ jarvis/jarvis_agent/__init__.py,sha256=AxT_2n-IQkbtoQlAS3SJ0tsvcUenWD7_Xrc-RZZCWiA,30352
3
3
  jarvis/jarvis_agent/builtin_input_handler.py,sha256=f4DaEHPakXcAbgykFP-tiOQP6fh_yGFlZx_h91_j2tQ,1529
4
+ jarvis/jarvis_agent/file_input_handler.py,sha256=LDNXoTtyjhyBmfzDnAdbWZ2BWdu4q-r6thSKRK8Iwjk,4187
4
5
  jarvis/jarvis_agent/jarvis.py,sha256=UkNMVUlSNKV6y3v12eAhqc_gIDB6Obxrwk5f7-sQeiQ,6137
5
6
  jarvis/jarvis_agent/main.py,sha256=GkjMTIbsd56nkVuRwD_tU_PZWyzixZZhMjVOCd0SzOA,2669
6
7
  jarvis/jarvis_agent/output_handler.py,sha256=7qori-RGrQmdiFepoEe3oPPKJIvRt90l_JDmvCoa4zA,1219
7
8
  jarvis/jarvis_agent/shell_input_handler.py,sha256=pi3AtPKrkKc6K9e99S1djKXQ_XrxtP6FrSWebQmRT6E,1261
8
9
  jarvis/jarvis_code_agent/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- jarvis/jarvis_code_agent/code_agent.py,sha256=IHUDqZ2RvJFoYIUuJAVCsbEOtYPHwXLfrmPXnpxKjvU,15721
10
+ jarvis/jarvis_code_agent/code_agent.py,sha256=2TG_Hi_2mbiZHUcWnxYs4C30eYpgSedtIYZLs7BbyUk,15827
10
11
  jarvis/jarvis_code_agent/lint.py,sha256=TZlhNbeaoLzO9DzExjN5GAjrt66owd8lyQV56LTfkrs,4370
11
12
  jarvis/jarvis_code_analysis/code_review.py,sha256=SEK5NOGDWgMNX3zmRMWrIOtq3Xr8cKt_asG51U8h6SA,30219
12
13
  jarvis/jarvis_code_analysis/checklists/__init__.py,sha256=cKQ_FOGy5TQgM-YkRCqORo-mUOZaPAJ9VDmZoFX58us,78
@@ -63,13 +64,13 @@ jarvis/jarvis_tools/chdir.py,sha256=DNKVFrWqu6t_sZ2ipv99s6802QR4cSGlqKlmaI--arE,
63
64
  jarvis/jarvis_tools/code_plan.py,sha256=gWR0lzY62x2PxWKoMRBqW6jq7zQuO8vhpjC4TcHSYjk,7685
64
65
  jarvis/jarvis_tools/create_code_agent.py,sha256=-nHfo5O5pDIG5IX3w1ClQafGvGcdI2_w75-KGrD-gUQ,3458
65
66
  jarvis/jarvis_tools/create_sub_agent.py,sha256=lyFrrg4V0yXULmU3vldwGp_euZjwZzJcRU6mJ20zejY,3023
66
- jarvis/jarvis_tools/edit_file.py,sha256=OiTP50yaUE-WTSKnp8axo96OfddHufWKpGuEa6YRG30,16269
67
+ jarvis/jarvis_tools/edit_file.py,sha256=gxnVijz-mOHpb9A7WTPIqCwmZHInSHwu_Psa_GvNWRQ,16724
67
68
  jarvis/jarvis_tools/execute_script.py,sha256=IA1SkcnwBB9PKG2voBNx5N9GXL303OC7OOtdqRfqWOk,6428
68
69
  jarvis/jarvis_tools/file_analyzer.py,sha256=7ILHkUFm8pPZn1y_s4uT0kaWHP-EmlHnpkovDdA1yRE,4872
69
- jarvis/jarvis_tools/file_operation.py,sha256=RcOKuMFUv01tvKoiOfu1ERCjvDVfJBvkT4oBpq-8vNQ,9036
70
+ jarvis/jarvis_tools/file_operation.py,sha256=WloC1-oPJLwgICu4WBc9f7XA8N_Ggl73QQ5CxM2XTlE,9464
70
71
  jarvis/jarvis_tools/generate_new_tool.py,sha256=k1Vt88kI1bYi1OwxvJqFKr3Ewwwv7lOegYNmZ-1F7x0,10283
71
72
  jarvis/jarvis_tools/methodology.py,sha256=m7cQmVhhQpUUl_uYTVvcW0JBovQLx5pWTXh_8K77HsU,5237
72
- jarvis/jarvis_tools/read_code.py,sha256=j4niDMOAKW_3rVxmOo3wxYBQ2T8vkxqEiTkBt28gUT8,5898
73
+ jarvis/jarvis_tools/read_code.py,sha256=pL2SwZDsJbJMXo4stW96quFsLgbtPVIAW-h4sDKsLtM,6274
73
74
  jarvis/jarvis_tools/read_webpage.py,sha256=PFAYuKjay9j6phWzyuZ99ZfNaHJljmRWAgS0bsvbcvE,2219
74
75
  jarvis/jarvis_tools/registry.py,sha256=WvYPiaUrleFqeXvwRkxM-6TNs1sWm61mpg1MFVo_kas,25113
75
76
  jarvis/jarvis_tools/rewrite_file.py,sha256=3V2l7kG5DG9iRimBce-1qCRuJPL0QM32SBTzOl2zCqM,7004
@@ -89,9 +90,9 @@ jarvis/jarvis_utils/methodology.py,sha256=A8pE8ZqNHvGKaDO4TFtg7Oz-hAXPBcQfhmSPWM
89
90
  jarvis/jarvis_utils/output.py,sha256=QboL42GtG_dnvd1O64sl8o72mEBhXNRADPXQMXgDE7Q,9661
90
91
  jarvis/jarvis_utils/tag.py,sha256=YJHmuedLb7_AiqvKQetHr4R1FxyzIh7HN0RRkWMmYbU,429
91
92
  jarvis/jarvis_utils/utils.py,sha256=atSK-2cUr7_tOIFsQzJnuQxebi7aFN4jtmaoXEaV4jM,10692
92
- jarvis_ai_assistant-0.1.181.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
93
- jarvis_ai_assistant-0.1.181.dist-info/METADATA,sha256=0rpJwI0H5WiJsTHHQgmWeyeM7P4RZ7ei_L-Tnzt5ktI,15059
94
- jarvis_ai_assistant-0.1.181.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
95
- jarvis_ai_assistant-0.1.181.dist-info/entry_points.txt,sha256=Gy3DOP1PYLMK0GCj4rrP_9lkOyBQ39EK_lKGUSwn41E,869
96
- jarvis_ai_assistant-0.1.181.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
97
- jarvis_ai_assistant-0.1.181.dist-info/RECORD,,
93
+ jarvis_ai_assistant-0.1.182.dist-info/licenses/LICENSE,sha256=AGgVgQmTqFvaztRtCAXsAMryUymB18gZif7_l2e1XOg,1063
94
+ jarvis_ai_assistant-0.1.182.dist-info/METADATA,sha256=Op8V2ma_T4C2rrhuEXgSn0qN7lZEfeiozSES036fdak,15059
95
+ jarvis_ai_assistant-0.1.182.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
96
+ jarvis_ai_assistant-0.1.182.dist-info/entry_points.txt,sha256=Gy3DOP1PYLMK0GCj4rrP_9lkOyBQ39EK_lKGUSwn41E,869
97
+ jarvis_ai_assistant-0.1.182.dist-info/top_level.txt,sha256=1BOxyWfzOP_ZXj8rVTDnNCJ92bBGB0rwq8N1PCpoMIs,7
98
+ jarvis_ai_assistant-0.1.182.dist-info/RECORD,,