jarvis-ai-assistant 0.1.114__py3-none-any.whl → 0.1.116__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 (51) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/{agent.py → jarvis_agent/__init__.py} +35 -159
  3. jarvis/jarvis_agent/output_handler.py +23 -0
  4. jarvis/jarvis_code_agent/code_agent.py +11 -11
  5. jarvis/jarvis_code_agent/file_select.py +28 -7
  6. jarvis/jarvis_code_agent/patch.py +25 -2
  7. jarvis/jarvis_code_agent/relevant_files.py +1 -1
  8. jarvis/jarvis_codebase/main.py +2 -2
  9. jarvis/jarvis_lsp/cpp.py +1 -1
  10. jarvis/jarvis_lsp/go.py +1 -1
  11. jarvis/jarvis_lsp/registry.py +1 -1
  12. jarvis/jarvis_lsp/rust.py +1 -1
  13. jarvis/jarvis_multi_agent/__init__.py +147 -0
  14. jarvis/jarvis_platform/ai8.py +2 -2
  15. jarvis/jarvis_platform/base.py +14 -4
  16. jarvis/jarvis_platform/kimi.py +2 -2
  17. jarvis/jarvis_platform/ollama.py +1 -1
  18. jarvis/jarvis_platform/openai.py +1 -1
  19. jarvis/jarvis_platform/oyi.py +1 -1
  20. jarvis/jarvis_platform/registry.py +1 -1
  21. jarvis/jarvis_platform_manager/main.py +422 -6
  22. jarvis/jarvis_platform_manager/openai_test.py +139 -0
  23. jarvis/jarvis_rag/main.py +2 -2
  24. jarvis/jarvis_smart_shell/main.py +17 -16
  25. jarvis/jarvis_tools/ask_codebase.py +1 -1
  26. jarvis/jarvis_tools/ask_user.py +1 -1
  27. jarvis/jarvis_tools/chdir.py +1 -1
  28. jarvis/jarvis_tools/code_review.py +3 -3
  29. jarvis/jarvis_tools/create_code_agent.py +1 -1
  30. jarvis/jarvis_tools/create_sub_agent.py +2 -2
  31. jarvis/jarvis_tools/execute_shell.py +1 -1
  32. jarvis/jarvis_tools/file_operation.py +16 -14
  33. jarvis/jarvis_tools/git_commiter.py +2 -2
  34. jarvis/jarvis_tools/methodology.py +1 -1
  35. jarvis/jarvis_tools/rag.py +1 -1
  36. jarvis/jarvis_tools/read_code.py +19 -8
  37. jarvis/jarvis_tools/read_webpage.py +1 -1
  38. jarvis/jarvis_tools/registry.py +53 -6
  39. jarvis/jarvis_tools/search.py +1 -1
  40. jarvis/jarvis_tools/select_code_files.py +1 -1
  41. jarvis/{utils.py → jarvis_utils/__init__.py} +69 -53
  42. {jarvis_ai_assistant-0.1.114.dist-info → jarvis_ai_assistant-0.1.116.dist-info}/METADATA +1 -1
  43. jarvis_ai_assistant-0.1.116.dist-info/RECORD +64 -0
  44. {jarvis_ai_assistant-0.1.114.dist-info → jarvis_ai_assistant-0.1.116.dist-info}/WHEEL +1 -1
  45. {jarvis_ai_assistant-0.1.114.dist-info → jarvis_ai_assistant-0.1.116.dist-info}/entry_points.txt +1 -2
  46. jarvis/jarvis_dev/main.py +0 -664
  47. jarvis/multi_agent.py +0 -76
  48. jarvis/utils/date_utils.py +0 -19
  49. jarvis_ai_assistant-0.1.114.dist-info/RECORD +0 -64
  50. {jarvis_ai_assistant-0.1.114.dist-info → jarvis_ai_assistant-0.1.116.dist-info}/LICENSE +0 -0
  51. {jarvis_ai_assistant-0.1.114.dist-info → jarvis_ai_assistant-0.1.116.dist-info}/top_level.txt +0 -0
jarvis/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """Jarvis AI Assistant"""
2
2
 
3
- __version__ = "0.1.114"
3
+ __version__ = "0.1.116"
@@ -1,15 +1,16 @@
1
1
  import argparse
2
2
  import re
3
3
  import time
4
- from typing import Callable, Dict, List, Optional
4
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Union
5
5
 
6
6
  from prompt_toolkit import prompt
7
7
  import yaml
8
8
 
9
+ from jarvis.jarvis_agent.output_handler import OutputHandler
9
10
  from jarvis.jarvis_platform.base import BasePlatform
10
11
  from jarvis.jarvis_platform.registry import PlatformRegistry
11
12
  from jarvis.jarvis_tools.registry import ToolRegistry
12
- from jarvis.utils import PrettyOutput, OutputType, get_context_token_count, is_auto_complete, is_execute_tool_confirm, is_need_summary, is_record_methodology, load_methodology, set_agent, delete_agent, get_max_token_count, get_multiline_input, init_env, is_use_methodology, make_agent_name, user_confirm
13
+ from jarvis.jarvis_utils import PrettyOutput, OutputType, get_context_token_count, is_auto_complete, is_execute_tool_confirm, is_need_summary, is_record_methodology, load_methodology, set_agent, delete_agent, get_max_token_count, get_multiline_input, init_env, is_use_methodology, make_agent_name, user_confirm
13
14
  import os
14
15
 
15
16
  class Agent:
@@ -25,32 +26,22 @@ class Agent:
25
26
  def __del__(self):
26
27
  delete_agent(self.name)
27
28
 
28
- def set_output_handler_before_tool(self, handler: List[Callable]):
29
- """Set handlers to process output before tool execution.
30
-
31
- Args:
32
- handler: List of callable functions to process output
33
- """
34
- self.output_handler_before_tool = handler
35
29
 
36
30
  def __init__(self,
37
31
  system_prompt: str,
38
32
  name: str = "Jarvis",
39
33
  description: str = "",
40
34
  is_sub_agent: bool = False,
41
- tool_registry: Optional[ToolRegistry|List[str]] = None,
42
- platform: Optional[BasePlatform]|Optional[str] = None,
35
+ platform: Union[Optional[BasePlatform], Optional[str]] = None,
43
36
  model_name: Optional[str] = None,
44
37
  summary_prompt: Optional[str] = None,
45
38
  auto_complete: Optional[bool] = None,
46
- output_handler_before_tool: Optional[List[Callable]] = None,
47
- output_handler_after_tool: Optional[List[Callable]] = None,
39
+ output_handler: List[OutputHandler] = [],
48
40
  input_handler: Optional[List[Callable]] = None,
49
41
  use_methodology: Optional[bool] = None,
50
42
  record_methodology: Optional[bool] = None,
51
43
  need_summary: Optional[bool] = None,
52
44
  max_context_length: Optional[int] = None,
53
- support_send_msg: bool = False,
54
45
  execute_tool_confirm: Optional[bool] = None):
55
46
  """Initialize an Agent instance.
56
47
 
@@ -91,15 +82,7 @@ class Agent:
91
82
  self.model.set_model_name(model_name)
92
83
 
93
84
 
94
- # 初始化工具
95
- if tool_registry is not None:
96
- if isinstance(tool_registry, ToolRegistry):
97
- self.tool_registry = tool_registry
98
- elif isinstance(tool_registry, List):
99
- self.tool_registry = ToolRegistry()
100
- self.tool_registry.use_tools(tool_registry)
101
- else:
102
- self.tool_registry = ToolRegistry()
85
+ self.output_handler = output_handler
103
86
 
104
87
 
105
88
  self.record_methodology = record_methodology if record_methodology is not None else is_record_methodology()
@@ -111,10 +94,7 @@ class Agent:
111
94
  self.need_summary = need_summary if need_summary is not None else is_need_summary()
112
95
  self.input_handler = input_handler if input_handler is not None else []
113
96
  # Load configuration from environment variables
114
- self.output_handler_before_tool = output_handler_before_tool if output_handler_before_tool else []
115
- self.output_handler_after_tool = output_handler_after_tool if output_handler_after_tool else []
116
97
 
117
- self.support_send_msg = support_send_msg
118
98
 
119
99
  self.execute_tool_confirm = execute_tool_confirm if execute_tool_confirm is not None else is_execute_tool_confirm()
120
100
 
@@ -132,48 +112,14 @@ Please describe in concise bullet points, highlighting important information.
132
112
  self.max_token_count = max_context_length if max_context_length is not None else get_max_token_count()
133
113
  self.auto_complete = auto_complete if auto_complete is not None else is_auto_complete()
134
114
  welcome_message = f"{name} 初始化完成 - 使用 {self.model.name()} 模型"
135
- tools = self.tool_registry.get_all_tools()
136
- if tools:
137
- welcome_message += f"\n可用工具: \n{','.join([f'{tool['name']}' for tool in tools])}"
115
+
138
116
  PrettyOutput.print(welcome_message, OutputType.SYSTEM)
139
117
 
140
- tools_prompt = self.tool_registry.load_tools()
118
+ tool_prompt = f"""You can do the following actions: {','.join([handler.name() for handler in self.output_handler])}"""
141
119
 
142
- send_msg_prompt = ""
143
- if self.support_send_msg:
144
- send_msg_prompt = """
145
- ## Send Message Rules
146
-
147
- !!! CRITICAL ACTION RULES !!!
148
- You can ONLY perform ONE action per turn:
149
- - ENSURE USE ONLY ONE TOOL EVERY TURN (file_operation, ask_user, etc.)
150
- - OR SEND ONE MESSAGE TO ANOTHER AGENT
151
- - NEVER DO BOTH IN THE SAME TURN
152
-
153
- 2. Message Format:
154
- <SEND_MESSAGE>
155
- to: agent_name # Target agent name
156
- content: |
157
- message_content # Message content, multi-line must be separated by newlines
158
- </SEND_MESSAGE>
159
-
160
- 3. Message Handling:
161
- - After sending a message, WAIT for response
162
- - Process response before next action
163
- - Never send multiple messages at once
164
- - Never combine message with tool calls
165
-
166
- 4. If Multiple Actions Needed:
167
- a. Choose most important action first
168
- b. Wait for response/result
169
- c. Plan next action based on response
170
- d. Execute next action in new turn
171
-
172
- Remember:
173
- - First action will be executed
174
- - Additional actions will be IGNORED
175
- - Always process responses before new actions
176
- """
120
+ for handler in self.output_handler:
121
+ tool_prompt += f"\n## {handler.name()}:\n"
122
+ tool_prompt += handler.prompt()
177
123
 
178
124
  complete_prompt = ""
179
125
  if self.auto_complete:
@@ -183,69 +129,16 @@ Please describe in concise bullet points, highlighting important information.
183
129
  <!!!COMPLETE!!!>
184
130
  """
185
131
 
186
- additional_prompt = ""
187
- if not tools_prompt and send_msg_prompt:
188
- additional_prompt = """YOU MUST CALL ONE TOOL EVERY TURN, UNLESS YOU THINK THE TASK IS COMPLETED!!!"""
189
- if not send_msg_prompt and tools_prompt:
190
- additional_prompt = """YOU MUST SEND ONE MESSAGE EVERY TURN, UNLESS YOU THINK THE TASK IS COMPLETED!!!"""
191
- if send_msg_prompt and tools_prompt:
192
- additional_prompt = """YOU MUST CALL ONE TOOL OR SEND ONE MESSAGE EVERY TURN, UNLESS YOU THINK THE TASK IS COMPLETED!!!"""
193
-
194
132
  self.model.set_system_message(f"""
195
133
  {self.system_prompt}
196
134
 
197
- {tools_prompt}
198
-
199
- {send_msg_prompt}
135
+ {tool_prompt}
200
136
 
201
137
  {complete_prompt}
202
-
203
- {additional_prompt}
204
138
  """)
205
139
  self.first = True
206
140
 
207
- @staticmethod
208
- def _extract_send_msg(content: str) -> List[Dict]:
209
- """Extract send message from content.
210
-
211
- Args:
212
- content: The content containing send message
213
- """
214
- data = re.findall(r'<SEND_MESSAGE>(.*?)</SEND_MESSAGE>', content, re.DOTALL)
215
- ret = []
216
- for item in data:
217
- try:
218
- msg = yaml.safe_load(item)
219
- if 'to' in msg and 'content' in msg:
220
- ret.append(msg)
221
- except Exception as e:
222
- continue
223
- return ret
224
141
 
225
- @staticmethod
226
- def _extract_tool_calls(content: str) -> List[Dict]:
227
- """Extract tool calls from content.
228
-
229
- Args:
230
- content: The content containing tool calls
231
-
232
- Returns:
233
- List[Dict]: List of extracted tool calls with name and arguments
234
-
235
- Raises:
236
- Exception: If tool call is missing necessary fields
237
- """
238
- # Split content into lines
239
- data = re.findall(r'<TOOL_CALL>(.*?)</TOOL_CALL>', content, re.DOTALL)
240
- ret = []
241
- for item in data:
242
- try:
243
- msg = yaml.safe_load(item)
244
- if 'name' in msg and 'arguments' in msg:
245
- ret.append(msg)
246
- except Exception as e:
247
- continue
248
- return ret
249
142
 
250
143
  def _call_model(self, message: str) -> str:
251
144
  """Call the AI model with retry logic.
@@ -322,6 +215,21 @@ Please continue the task based on the above information.
322
215
  except Exception as e:
323
216
  PrettyOutput.print(f"总结对话历史失败: {str(e)}", OutputType.ERROR)
324
217
 
218
+ def _call_tools(self, response: str) -> Tuple[bool, Any]:
219
+ tool_list = []
220
+ for handler in self.output_handler:
221
+ if handler.can_handle(response):
222
+ tool_list.append(handler)
223
+ if len(tool_list) > 1:
224
+ PrettyOutput.print(f"操作失败:检测到多个操作。一次只能执行一个操作。尝试执行的操作:{', '.join([handler.name() for handler in tool_list])}", OutputType.ERROR)
225
+ return False, f"Action failed: Multiple actions detected. Please only perform one action at a time. Actions attempted: {', '.join([handler.name() for handler in tool_list])}"
226
+ if len(tool_list) == 0:
227
+ return False, ""
228
+ if not self.execute_tool_confirm or user_confirm(f"需要执行{tool_list[0].name()}确认执行?", True):
229
+ return tool_list[0].handle(response)
230
+ return False, ""
231
+
232
+
325
233
  def _complete_task(self) -> str:
326
234
  """Complete the current task and generate summary if needed.
327
235
 
@@ -349,13 +257,7 @@ Please continue the task based on the above information.
349
257
  self.prompt = analysis_prompt
350
258
  response = self._call_model(self.prompt)
351
259
 
352
- # 检查是否包含工具调用
353
- try:
354
- tool_calls = Agent._extract_tool_calls(response)
355
- if tool_calls:
356
- self.tool_registry.handle_tool_calls(tool_calls[0])
357
- except Exception as e:
358
- PrettyOutput.print(f"处理方法论生成失败: {str(e)}", OutputType.ERROR)
260
+ self._call_tools(response)
359
261
 
360
262
  except Exception as e:
361
263
  PrettyOutput.print(f"生成方法论失败: {str(e)}", OutputType.ERROR)
@@ -369,7 +271,7 @@ Please continue the task based on the above information.
369
271
  return "任务完成"
370
272
 
371
273
 
372
- def run(self, user_input: str, file_list: Optional[List[str]] = None) -> str|Dict:
274
+ def run(self, user_input: str, file_list: Optional[List[str]] = None) -> Any:
373
275
  """Process user input and execute the task.
374
276
 
375
277
  Args:
@@ -412,38 +314,10 @@ Please continue the task based on the above information.
412
314
  self.prompt = ""
413
315
  self.conversation_length += get_context_token_count(current_response)
414
316
 
415
- # Check for message first
416
- send_msg = Agent._extract_send_msg(current_response)
417
- tool_calls = Agent._extract_tool_calls(current_response)
317
+ need_return, self.prompt = self._call_tools(current_response)
418
318
 
419
- if len(send_msg) > 1:
420
- PrettyOutput.print(f"收到多个消息,违反规则,重试...", OutputType.WARNING)
421
- self.prompt += f"Only one message can be sent, but {len(send_msg)} messages were received. Please retry."
422
- continue
423
- if len(tool_calls) > 1:
424
- PrettyOutput.print(f"收到多个工具调用,违反规则,重试...", OutputType.WARNING)
425
- self.prompt += f"Only one tool call can be executed, but {len(tool_calls)} tool calls were received. Please retry."
426
- continue
427
- if send_msg and tool_calls:
428
- PrettyOutput.print(f"收到消息和工具调用,违反规则,重试...", OutputType.WARNING)
429
- self.prompt += f"Only one action can be performed, but both a message and a tool call were received. Please retry."
430
- continue
431
-
432
- if send_msg:
433
- return send_msg[0] # Return the first message
434
-
435
- # If no message, process tool calls
436
- for handler in self.output_handler_before_tool:
437
- self.prompt += handler(current_response)
438
-
439
- if tool_calls:
440
- if not self.execute_tool_confirm or user_confirm(f"执行工具调用: {tool_calls[0]['name']}?"):
441
- PrettyOutput.print("正在执行工具调用...", OutputType.PROGRESS)
442
- tool_result = self.tool_registry.handle_tool_calls(tool_calls[0])
443
- self.prompt += tool_result
444
-
445
- for handler in self.output_handler_after_tool:
446
- self.prompt += handler(current_response)
319
+ if need_return:
320
+ return self.prompt
447
321
 
448
322
  if self.prompt:
449
323
  continue
@@ -605,11 +479,13 @@ def main():
605
479
  init_env()
606
480
  parser = argparse.ArgumentParser(description='Jarvis AI assistant')
607
481
  parser.add_argument('-f', '--files', nargs='*', help='List of files to process')
482
+ parser.add_argument('-p', '--platform', type=str, help='Platform to use')
483
+ parser.add_argument('-m', '--model', type=str, help='Model to use')
608
484
  args = parser.parse_args()
609
485
 
610
486
  try:
611
487
  # 获取全局模型实例
612
- agent = Agent(system_prompt=origin_agent_system_prompt)
488
+ agent = Agent(system_prompt=origin_agent_system_prompt, platform=args.platform, model_name=args.model, output_handler=[ToolRegistry()])
613
489
 
614
490
  # 加载预定义任务
615
491
  tasks = _load_tasks()
@@ -0,0 +1,23 @@
1
+
2
+
3
+ from abc import ABC, abstractmethod
4
+ from typing import Any, Tuple
5
+
6
+
7
+
8
+ class OutputHandler(ABC):
9
+ @abstractmethod
10
+ def handle(self, response: str) -> Tuple[bool, Any]:
11
+ pass
12
+
13
+ @abstractmethod
14
+ def can_handle(self, response: str) -> bool:
15
+ pass
16
+
17
+ @abstractmethod
18
+ def prompt(self) -> str:
19
+ pass
20
+
21
+ @abstractmethod
22
+ def name(self) -> str:
23
+ pass
@@ -1,13 +1,15 @@
1
1
  import os
2
2
  from typing import Dict, List
3
3
 
4
- from jarvis.agent import Agent
5
- from jarvis.jarvis_code_agent.patch import apply_patch
4
+ from jarvis.jarvis_agent import Agent
5
+ from jarvis.jarvis_code_agent.file_select import file_input_handler
6
+ from jarvis.jarvis_code_agent.patch import PatchOutputHandler
6
7
  from jarvis.jarvis_code_agent.relevant_files import find_relevant_information
7
8
  from jarvis.jarvis_platform.registry import PlatformRegistry
8
9
  from jarvis.jarvis_tools.git_commiter import GitCommitTool
9
10
  from jarvis.jarvis_tools.registry import ToolRegistry
10
- from jarvis.utils import OutputType, PrettyOutput, get_multiline_input, has_uncommitted_changes, init_env, find_git_root
11
+ from jarvis.jarvis_tools.read_code import ReadCodeTool
12
+ from jarvis.jarvis_utils import OutputType, PrettyOutput, get_multiline_input, has_uncommitted_changes, init_env, find_git_root
11
13
 
12
14
 
13
15
  class CodeAgent:
@@ -49,12 +51,6 @@ class CodeAgent:
49
51
  • Exceptions must be documented
50
52
  • Complex logic must be explained
51
53
 
52
- # Patch Format
53
- <PATCH>
54
- path/file start,end
55
- new_content
56
- </PATCH>
57
-
58
54
  Key Rules:
59
55
  • One modification per patch block
60
56
  • Line numbers are based on original file
@@ -129,10 +125,10 @@ Every Change Must:
129
125
  auto_complete=False,
130
126
  is_sub_agent=False,
131
127
  use_methodology=False,
132
- tool_registry=tool_registry,
128
+ output_handler=[tool_registry, PatchOutputHandler()],
133
129
  platform=PlatformRegistry().get_codegen_platform(),
134
130
  record_methodology=False,
135
- output_handler_after_tool=[apply_patch],
131
+ input_handler=[file_input_handler],
136
132
  need_summary=False)
137
133
 
138
134
 
@@ -160,6 +156,10 @@ Every Change Must:
160
156
  # Then try to add file contents
161
157
  for file in files:
162
158
  prompt_parts.append(f'''- {file['file']} ({file['reason']})''')
159
+
160
+ result = ReadCodeTool().execute({"files": [{"file": file["file"], "reason": file["reason"]} for file in files]})
161
+ if result["success"]:
162
+ prompt_parts.append(result["stdout"])
163
163
 
164
164
  return "\n".join(prompt_parts)
165
165
 
@@ -3,7 +3,8 @@ import re
3
3
  from typing import Dict, List
4
4
  from prompt_toolkit import PromptSession
5
5
  from prompt_toolkit.completion import Completer, Completion
6
- from jarvis.utils import OutputType, PrettyOutput, get_single_line_input, user_confirm
6
+ from jarvis.jarvis_tools.read_code import ReadCodeTool
7
+ from jarvis.jarvis_utils import OutputType, PrettyOutput, get_single_line_input, user_confirm
7
8
 
8
9
 
9
10
  def _parse_file_selection(input_str: str, max_index: int) -> List[int]:
@@ -135,6 +136,9 @@ def select_files(related_files: List[Dict[str, str]], root_dir: str) -> List[Dic
135
136
  for i, file in enumerate(related_files, 1):
136
137
  output += f"[{i}] {file['file']} ({file['reason']})\n"
137
138
 
139
+ # Filter out files that do not exist
140
+ related_files = [f for f in related_files if os.path.isfile(os.path.join(root_dir, f["file"]))]
141
+
138
142
  PrettyOutput.print(output, OutputType.INFO, lang="markdown")
139
143
 
140
144
  if len(related_files) > 0:
@@ -175,9 +179,10 @@ def select_files(related_files: List[Dict[str, str]], root_dir: str) -> List[Dic
175
179
  continue
176
180
 
177
181
  # Display matching files
178
- PrettyOutput.print("找到以下匹配的文件:", OutputType.INFO)
182
+ tips = "找到以下匹配的文件:"
179
183
  for i, path in enumerate(matches, 1):
180
- PrettyOutput.print(f"[{i}] {path}", OutputType.INFO)
184
+ tips += f"\n[{i}] {path}"
185
+ PrettyOutput.print(tips, OutputType.INFO)
181
186
 
182
187
  # Let the user select
183
188
  numbers = get_single_line_input("请选择要添加的文件编号(支持: 1,3-6格式, 按回车选择所有)").strip()
@@ -192,16 +197,32 @@ def select_files(related_files: List[Dict[str, str]], root_dir: str) -> List[Dic
192
197
  paths_to_add = [file_path]
193
198
 
194
199
  # Add selected files
200
+ tips = "添加以下文件:"
195
201
  for path in paths_to_add:
196
202
  full_path = os.path.join(root_dir, path)
197
203
  if not os.path.isfile(full_path):
198
- PrettyOutput.print(f"文件不存在: {path}", OutputType.ERROR)
204
+ tips += f"\n文件不存在: {path}"
199
205
  continue
200
206
 
201
207
  try:
202
208
  selected_files.append({"file": path, "reason": "User Added"})
203
- PrettyOutput.print(f"文件已添加: {path}", OutputType.SUCCESS)
209
+ tips += f"\n文件已添加: {path}"
204
210
  except Exception as e:
205
- PrettyOutput.print(f"读取文件失败: {str(e)}", OutputType.ERROR)
211
+ tips += f"\n读取文件失败: {str(e)}"
212
+ selected_files = [f for f in selected_files if os.path.isfile(os.path.join(root_dir, f["file"]))]
213
+ PrettyOutput.print(tips, OutputType.INFO)
214
+ return selected_files
215
+
216
+ def file_input_handler(user_input: str) -> str:
217
+ prompt = user_input
218
+ files = []
219
+ sm = re.findall(r'`(.+?)`', user_input)
220
+ if sm:
221
+ for s in sm:
222
+ if os.path.isfile(s[0]):
223
+ files.append(s[0])
224
+ result = ReadCodeTool().execute({"files": files})
225
+ if result["success"]:
226
+ return result["stdout"] + "\n" + prompt
206
227
 
207
- return selected_files
228
+ return prompt
@@ -1,8 +1,31 @@
1
1
  import re
2
- from typing import Dict, Any, List
2
+ from typing import Dict, Any, List, Tuple
3
3
  import os
4
+ from jarvis.jarvis_agent.output_handler import OutputHandler
4
5
  from jarvis.jarvis_tools.git_commiter import GitCommitTool
5
- from jarvis.utils import OutputType, PrettyOutput, get_multiline_input, has_uncommitted_changes, user_confirm
6
+ from jarvis.jarvis_utils import OutputType, PrettyOutput, get_multiline_input, has_uncommitted_changes, user_confirm
7
+
8
+
9
+ class PatchOutputHandler(OutputHandler):
10
+ def name(self) -> str:
11
+ return "PATCH"
12
+
13
+ def handle(self, response: str) -> Tuple[bool, Any]:
14
+ return False, apply_patch(response)
15
+
16
+ def can_handle(self, response: str) -> bool:
17
+ if _parse_patch(response):
18
+ return True
19
+ return False
20
+
21
+ def prompt(self) -> str:
22
+ return """
23
+ <PATCH>
24
+ path/to/file start,end
25
+ new_content
26
+ </PATCH>
27
+
28
+ """
6
29
 
7
30
 
8
31
  def _parse_patch(patch_str: str) -> Dict[str, List[Dict[str, Any]]]:
@@ -5,7 +5,7 @@ from typing import Dict, List, Optional, Tuple
5
5
  from jarvis.jarvis_code_agent.file_select import select_files
6
6
  from jarvis.jarvis_codebase.main import CodeBase
7
7
  from jarvis.jarvis_platform.registry import PlatformRegistry
8
- from jarvis.utils import OutputType, PrettyOutput
8
+ from jarvis.jarvis_utils import OutputType, PrettyOutput
9
9
 
10
10
  def make_question(requirement: str) -> Optional[str]:
11
11
  """Generate structured questions to gather necessary information for the requirement."""
@@ -7,8 +7,8 @@ from typing import List, Tuple, Optional, Dict
7
7
  from jarvis.jarvis_platform.registry import PlatformRegistry
8
8
  import concurrent.futures
9
9
  from concurrent.futures import ThreadPoolExecutor
10
- from jarvis.utils import OutputType, PrettyOutput, find_git_root, get_context_token_count, get_embedding, get_file_md5, get_max_token_count, get_thread_count, load_embedding_model, user_confirm
11
- from jarvis.utils import init_env
10
+ from jarvis.jarvis_utils import OutputType, PrettyOutput, find_git_root, get_context_token_count, get_embedding, get_file_md5, get_max_token_count, get_thread_count, load_embedding_model, user_confirm
11
+ from jarvis.jarvis_utils import init_env
12
12
  import argparse
13
13
  import pickle
14
14
  import lzma # 添加 lzma 导入
jarvis/jarvis_lsp/cpp.py CHANGED
@@ -4,7 +4,7 @@ import subprocess
4
4
  from typing import List, Dict, Optional, Tuple, Any
5
5
  import json
6
6
  from jarvis.jarvis_lsp.base import BaseLSP
7
- from jarvis.utils import PrettyOutput, OutputType
7
+ from jarvis.jarvis_utils import PrettyOutput, OutputType
8
8
 
9
9
  class CPPLSP(BaseLSP):
10
10
  """C++ LSP implementation using clangd."""
jarvis/jarvis_lsp/go.py CHANGED
@@ -4,7 +4,7 @@ import subprocess
4
4
  from typing import List, Dict, Optional, Tuple, Any
5
5
  import json
6
6
  from jarvis.jarvis_lsp.base import BaseLSP
7
- from jarvis.utils import PrettyOutput, OutputType
7
+ from jarvis.jarvis_utils import PrettyOutput, OutputType
8
8
 
9
9
  class GoLSP(BaseLSP):
10
10
  """Go LSP implementation using gopls."""
@@ -5,7 +5,7 @@ import re
5
5
  import sys
6
6
  from typing import Dict, Type, Optional, List
7
7
  from jarvis.jarvis_lsp.base import BaseLSP
8
- from jarvis.utils import PrettyOutput, OutputType
8
+ from jarvis.jarvis_utils import PrettyOutput, OutputType
9
9
 
10
10
  REQUIRED_METHODS = [
11
11
  ('initialize', ['workspace_path']),
jarvis/jarvis_lsp/rust.py CHANGED
@@ -4,7 +4,7 @@ import subprocess
4
4
  from typing import List, Dict, Optional, Tuple, Any
5
5
  import json
6
6
  from jarvis.jarvis_lsp.base import BaseLSP
7
- from jarvis.utils import PrettyOutput, OutputType
7
+ from jarvis.jarvis_utils import PrettyOutput, OutputType
8
8
 
9
9
  class RustLSP(BaseLSP):
10
10
  """Rust LSP implementation using rust-analyzer."""