jarvis-ai-assistant 0.1.113__tar.gz → 0.1.115__tar.gz

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 (75) hide show
  1. {jarvis_ai_assistant-0.1.113/src/jarvis_ai_assistant.egg-info → jarvis_ai_assistant-0.1.115}/PKG-INFO +1 -1
  2. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/pyproject.toml +2 -1
  3. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/setup.py +2 -1
  4. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/__init__.py +1 -1
  5. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/agent.py +130 -74
  6. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_code_agent/code_agent.py +1 -1
  7. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_code_agent/patch.py +2 -4
  8. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_codebase/main.py +2 -0
  9. jarvis_ai_assistant-0.1.115/src/jarvis/jarvis_dev/main.py +664 -0
  10. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_platform/ai8.py +1 -1
  11. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_platform/openai.py +9 -1
  12. jarvis_ai_assistant-0.1.115/src/jarvis/jarvis_tools/file_operation.py +146 -0
  13. jarvis_ai_assistant-0.1.115/src/jarvis/jarvis_tools/read_code.py +168 -0
  14. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/registry.py +9 -16
  15. jarvis_ai_assistant-0.1.115/src/jarvis/multi_agent.py +76 -0
  16. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/utils.py +24 -9
  17. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115/src/jarvis_ai_assistant.egg-info}/PKG-INFO +1 -1
  18. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis_ai_assistant.egg-info/SOURCES.txt +2 -2
  19. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis_ai_assistant.egg-info/entry_points.txt +1 -0
  20. jarvis_ai_assistant-0.1.113/src/jarvis/jarvis_tools/deep_thinking.py +0 -160
  21. jarvis_ai_assistant-0.1.113/src/jarvis/jarvis_tools/deep_thinking_agent.py +0 -146
  22. jarvis_ai_assistant-0.1.113/src/jarvis/jarvis_tools/file_operation.py +0 -114
  23. jarvis_ai_assistant-0.1.113/src/jarvis/jarvis_tools/read_code.py +0 -117
  24. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/LICENSE +0 -0
  25. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/MANIFEST.in +0 -0
  26. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/README.md +0 -0
  27. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/setup.cfg +0 -0
  28. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_code_agent/__init__.py +0 -0
  29. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_code_agent/file_select.py +0 -0
  30. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_code_agent/relevant_files.py +0 -0
  31. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_codebase/__init__.py +0 -0
  32. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_lsp/base.py +0 -0
  33. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_lsp/cpp.py +0 -0
  34. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_lsp/go.py +0 -0
  35. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_lsp/python.py +0 -0
  36. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_lsp/registry.py +0 -0
  37. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_lsp/rust.py +0 -0
  38. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_platform/__init__.py +0 -0
  39. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_platform/base.py +0 -0
  40. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_platform/kimi.py +0 -0
  41. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_platform/ollama.py +0 -0
  42. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_platform/oyi.py +0 -0
  43. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_platform/registry.py +0 -0
  44. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_platform_manager/__init__.py +0 -0
  45. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_platform_manager/main.py +0 -0
  46. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_rag/__init__.py +0 -0
  47. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_rag/main.py +0 -0
  48. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_smart_shell/__init__.py +0 -0
  49. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_smart_shell/main.py +0 -0
  50. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/__init__.py +0 -0
  51. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/ask_codebase.py +0 -0
  52. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/ask_user.py +0 -0
  53. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/base.py +0 -0
  54. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/chdir.py +0 -0
  55. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/code_review.py +0 -0
  56. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/create_code_agent.py +0 -0
  57. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/create_sub_agent.py +0 -0
  58. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/execute_shell.py +0 -0
  59. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/git_commiter.py +0 -0
  60. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/lsp_find_definition.py +0 -0
  61. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/lsp_find_references.py +0 -0
  62. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/lsp_get_diagnostics.py +0 -0
  63. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/lsp_get_document_symbols.py +0 -0
  64. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/lsp_prepare_rename.py +0 -0
  65. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/lsp_validate_edit.py +0 -0
  66. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/methodology.py +0 -0
  67. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/rag.py +0 -0
  68. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/read_webpage.py +0 -0
  69. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/search.py +0 -0
  70. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/select_code_files.py +0 -0
  71. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/jarvis_tools/tool_generator.py +0 -0
  72. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis/utils/date_utils.py +0 -0
  73. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis_ai_assistant.egg-info/dependency_links.txt +0 -0
  74. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis_ai_assistant.egg-info/requires.txt +0 -0
  75. {jarvis_ai_assistant-0.1.113 → jarvis_ai_assistant-0.1.115}/src/jarvis_ai_assistant.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: jarvis-ai-assistant
3
- Version: 0.1.113
3
+ Version: 0.1.115
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "jarvis-ai-assistant"
7
- version = "0.1.113"
7
+ version = "0.1.115"
8
8
  description = "Jarvis: An AI assistant that uses tools to interact with the system"
9
9
  readme = "README.md"
10
10
  authors = [{ name = "Your Name", email = "your.email@example.com" }]
@@ -62,3 +62,4 @@ jss = "jarvis.jarvis_smart_shell.main:main"
62
62
  jarvis-platform-manager = "jarvis.jarvis_platform_manager.main:main"
63
63
  jarvis-git-commit = "jarvis.jarvis_tools.git_commiter:main"
64
64
  jarvis-code-review = "jarvis.jarvis_tools.code_review:main"
65
+ jarvis-dev = "jarvis.jarvis_dev.main:main"
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="jarvis-ai-assistant",
5
- version="0.1.113",
5
+ version="0.1.115",
6
6
  author="skyfire",
7
7
  author_email="skyfireitdiy@hotmail.com",
8
8
  description="An AI assistant that uses various tools to interact with the system",
@@ -47,6 +47,7 @@ setup(
47
47
  "jarvis-platform-manager=jarvis.jarvis_platform_manager.main:main",
48
48
  "jarvis-git-commit=jarvis.jarvis_tools.git_commiter:main",
49
49
  "jarvis-code-review=jarvis.jarvis_tools.code_review:main",
50
+ "jarvis-dev=jarvis.jarvis_dev.main:main",
50
51
  ],
51
52
  },
52
53
  python_requires=">=3.8",
@@ -1,3 +1,3 @@
1
1
  """Jarvis AI Assistant"""
2
2
 
3
- __version__ = "0.1.113"
3
+ __version__ = "0.1.115"
@@ -1,5 +1,5 @@
1
1
  import argparse
2
- from ast import Tuple
2
+ import re
3
3
  import time
4
4
  from typing import Callable, Dict, List, Optional
5
5
 
@@ -8,8 +8,8 @@ import yaml
8
8
 
9
9
  from jarvis.jarvis_platform.base import BasePlatform
10
10
  from jarvis.jarvis_platform.registry import PlatformRegistry
11
- from jarvis.jarvis_tools.registry import ToolRegistry, tool_call_help
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, add_agent, delete_current_agent, get_max_token_count, get_multiline_input, init_env, is_use_methodology, user_confirm
11
+ 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
13
  import os
14
14
 
15
15
  class Agent:
@@ -22,6 +22,9 @@ class Agent:
22
22
  """
23
23
  self.summary_prompt = summary_prompt
24
24
 
25
+ def __del__(self):
26
+ delete_agent(self.name)
27
+
25
28
  def set_output_handler_before_tool(self, handler: List[Callable]):
26
29
  """Set handlers to process output before tool execution.
27
30
 
@@ -33,6 +36,7 @@ class Agent:
33
36
  def __init__(self,
34
37
  system_prompt: str,
35
38
  name: str = "Jarvis",
39
+ description: str = "",
36
40
  is_sub_agent: bool = False,
37
41
  tool_registry: Optional[ToolRegistry|List[str]] = None,
38
42
  platform: Optional[BasePlatform]|Optional[str] = None,
@@ -46,12 +50,14 @@ class Agent:
46
50
  record_methodology: Optional[bool] = None,
47
51
  need_summary: Optional[bool] = None,
48
52
  max_context_length: Optional[int] = None,
53
+ support_send_msg: bool = False,
49
54
  execute_tool_confirm: Optional[bool] = None):
50
55
  """Initialize an Agent instance.
51
56
 
52
57
  Args:
53
58
  system_prompt: The system prompt defining agent behavior
54
59
  name: Agent name, defaults to "Jarvis"
60
+ description: Agent description, defaults to ""
55
61
  is_sub_agent: Whether this is a sub-agent
56
62
  tool_registry: Registry of available tools
57
63
  platform: AI platform to use
@@ -63,9 +69,12 @@ class Agent:
63
69
  record_methodology: Whether to record methodology
64
70
  need_summary: Whether to generate summaries
65
71
  max_context_length: Maximum context length
72
+ support_send_msg: Whether to support sending messages
73
+ execute_tool_confirm: Whether to confirm tool execution
66
74
  """
67
- PrettyOutput.print(f"欢迎使用Jarvis,你的AI助手,正在初始化...", OutputType.SYSTEM)
68
75
 
76
+ self.name = make_agent_name(name)
77
+ self.description = description
69
78
  # 初始化平台和模型
70
79
  if platform is not None:
71
80
  if isinstance(platform, str):
@@ -95,7 +104,6 @@ class Agent:
95
104
 
96
105
  self.record_methodology = record_methodology if record_methodology is not None else is_record_methodology()
97
106
  self.use_methodology = use_methodology if use_methodology is not None else is_use_methodology()
98
- self.name = name
99
107
  self.is_sub_agent = is_sub_agent
100
108
  self.prompt = ""
101
109
  self.conversation_length = 0 # Use length counter instead
@@ -106,6 +114,8 @@ class Agent:
106
114
  self.output_handler_before_tool = output_handler_before_tool if output_handler_before_tool else []
107
115
  self.output_handler_after_tool = output_handler_after_tool if output_handler_after_tool else []
108
116
 
117
+ self.support_send_msg = support_send_msg
118
+
109
119
  self.execute_tool_confirm = execute_tool_confirm if execute_tool_confirm is not None else is_execute_tool_confirm()
110
120
 
111
121
  self.summary_prompt = summary_prompt if summary_prompt else f"""Please generate a concise summary report of the task execution, including:
@@ -120,18 +130,52 @@ Please describe in concise bullet points, highlighting important information.
120
130
  """
121
131
 
122
132
  self.max_token_count = max_context_length if max_context_length is not None else get_max_token_count()
123
-
124
133
  self.auto_complete = auto_complete if auto_complete is not None else is_auto_complete()
125
-
126
- PrettyOutput.section(f"Jarvis 初始化完成 - 使用 {self.model.name()} 模型", OutputType.SYSTEM)
127
-
134
+ welcome_message = f"{name} 初始化完成 - 使用 {self.model.name()} 模型"
128
135
  tools = self.tool_registry.get_all_tools()
129
136
  if tools:
130
- PrettyOutput.section(f"可用工具: {', '.join([tool['name'] for tool in tools])}", OutputType.SYSTEM)
131
-
137
+ welcome_message += f"\n可用工具: \n{','.join([f'{tool['name']}' for tool in tools])}"
138
+ PrettyOutput.print(welcome_message, OutputType.SYSTEM)
132
139
 
133
140
  tools_prompt = self.tool_registry.load_tools()
134
- complete_prompt = """"""
141
+
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
+ """
177
+
178
+ complete_prompt = ""
135
179
  if self.auto_complete:
136
180
  complete_prompt = """
137
181
  ## Task Completion
@@ -139,15 +183,45 @@ Please describe in concise bullet points, highlighting important information.
139
183
  <!!!COMPLETE!!!>
140
184
  """
141
185
 
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
+
142
194
  self.model.set_system_message(f"""
143
195
  {self.system_prompt}
144
196
 
145
197
  {tools_prompt}
146
198
 
199
+ {send_msg_prompt}
200
+
147
201
  {complete_prompt}
202
+
203
+ {additional_prompt}
148
204
  """)
149
205
  self.first = True
150
206
 
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
+
151
225
  @staticmethod
152
226
  def _extract_tool_calls(content: str) -> List[Dict]:
153
227
  """Extract tool calls from content.
@@ -162,39 +236,17 @@ Please describe in concise bullet points, highlighting important information.
162
236
  Exception: If tool call is missing necessary fields
163
237
  """
164
238
  # Split content into lines
165
- lines = content.split('\n')
166
- tool_call_lines = []
167
- in_tool_call = False
168
-
169
-
170
- # Process line by line
171
- for line in lines:
172
- if '<TOOL_CALL>' in line:
173
- in_tool_call = True
174
- continue
175
- elif '</TOOL_CALL>' in line:
176
- if in_tool_call and tool_call_lines:
177
- # Parse YAML directly
178
- tool_call_text = '\n'.join(tool_call_lines)
179
- tool_call_data = yaml.safe_load(tool_call_text)
180
-
181
- # Validate necessary fields
182
- if "name" in tool_call_data and "arguments" in tool_call_data:
183
- # Return content before tool call and tool call
184
- return [{
185
- "name": tool_call_data["name"],
186
- "arguments": tool_call_data["arguments"]
187
- }]
188
- else:
189
- raise Exception("Tool call missing necessary fields")
190
- in_tool_call = False
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:
191
247
  continue
192
-
193
- if in_tool_call:
194
- tool_call_lines.append(line)
195
-
196
- return []
197
-
248
+ return ret
249
+
198
250
  def _call_model(self, message: str) -> str:
199
251
  """Call the AI model with retry logic.
200
252
 
@@ -301,7 +353,7 @@ Please continue the task based on the above information.
301
353
  try:
302
354
  tool_calls = Agent._extract_tool_calls(response)
303
355
  if tool_calls:
304
- self.tool_registry.handle_tool_calls(tool_calls)
356
+ self.tool_registry.handle_tool_calls(tool_calls[0])
305
357
  except Exception as e:
306
358
  PrettyOutput.print(f"处理方法论生成失败: {str(e)}", OutputType.ERROR)
307
359
 
@@ -317,7 +369,7 @@ Please continue the task based on the above information.
317
369
  return "任务完成"
318
370
 
319
371
 
320
- def run(self, user_input: str, file_list: Optional[List[str]] = None) -> str:
372
+ def run(self, user_input: str, file_list: Optional[List[str]] = None) -> str|Dict:
321
373
  """Process user input and execute the task.
322
374
 
323
375
  Args:
@@ -325,18 +377,10 @@ Please continue the task based on the above information.
325
377
  file_list: Optional list of files to process
326
378
 
327
379
  Returns:
328
- str: Task summary report
329
-
330
- Note:
331
- - Handles context management
332
- - Processes tool calls
333
- - Manages conversation flow
334
- - Supports interactive mode
380
+ str|Dict: Task summary report or message to send
335
381
  """
336
-
337
- add_agent(self.name)
338
-
339
382
  try:
383
+ set_agent(self.name, self)
340
384
  PrettyOutput.section("准备环境", OutputType.PLANNING)
341
385
  if file_list:
342
386
  self.model.upload_files(file_list) # type: ignore
@@ -344,11 +388,12 @@ Please continue the task based on the above information.
344
388
  # 显示任务开始
345
389
  PrettyOutput.section(f"开始新任务: {self.name}", OutputType.PLANNING)
346
390
 
347
- if self.first and self.use_methodology:
348
- self.prompt = f"{user_input}\n\n{load_methodology(user_input)}"
391
+ self.prompt = f"{user_input}"
392
+
393
+ if self.first:
394
+ if self.use_methodology:
395
+ self.prompt = f"{user_input}\n\n{load_methodology(user_input)}"
349
396
  self.first = False
350
- else:
351
- self.prompt = f"{user_input}"
352
397
 
353
398
  while True:
354
399
  try:
@@ -367,22 +412,36 @@ Please continue the task based on the above information.
367
412
  self.prompt = ""
368
413
  self.conversation_length += get_context_token_count(current_response)
369
414
 
370
- for handler in self.output_handler_before_tool:
371
- self.prompt += handler(current_response)
415
+ # Check for message first
416
+ send_msg = Agent._extract_send_msg(current_response)
417
+ tool_calls = Agent._extract_tool_calls(current_response)
372
418
 
373
- try:
374
- result = Agent._extract_tool_calls(current_response)
375
- except Exception as e:
376
- PrettyOutput.print(f"工具调用错误: {str(e)}", OutputType.ERROR)
377
- self.prompt += f"Tool call error: {str(e)}"
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."
378
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)
379
438
 
380
- if len(result) > 0:
381
- if not self.execute_tool_confirm or user_confirm(f"执行工具调用: {result[0]['name']}?"):
439
+ if tool_calls:
440
+ if not self.execute_tool_confirm or user_confirm(f"执行工具调用: {tool_calls[0]['name']}?"):
382
441
  PrettyOutput.print("正在执行工具调用...", OutputType.PROGRESS)
383
- tool_result = self.tool_registry.handle_tool_calls(result)
442
+ tool_result = self.tool_registry.handle_tool_calls(tool_calls[0])
384
443
  self.prompt += tool_result
385
-
444
+
386
445
  for handler in self.output_handler_after_tool:
387
446
  self.prompt += handler(current_response)
388
447
 
@@ -409,9 +468,6 @@ Please continue the task based on the above information.
409
468
  except Exception as e:
410
469
  PrettyOutput.print(f"任务失败: {str(e)}", OutputType.ERROR)
411
470
  return f"Task failed: {str(e)}"
412
-
413
- finally:
414
- delete_current_agent()
415
471
 
416
472
  def _clear_history(self):
417
473
  """Clear conversation history while preserving system prompt.
@@ -51,7 +51,7 @@ class CodeAgent:
51
51
 
52
52
  # Patch Format
53
53
  <PATCH>
54
- > path/file start,end
54
+ path/file start,end
55
55
  new_content
56
56
  </PATCH>
57
57
 
@@ -8,7 +8,7 @@ from jarvis.utils import OutputType, PrettyOutput, get_multiline_input, has_unco
8
8
  def _parse_patch(patch_str: str) -> Dict[str, List[Dict[str, Any]]]:
9
9
  """Parse patches from string with format:
10
10
  <PATCH>
11
- > path/to/file start_line,end_line
11
+ path/to/file start_line,end_line
12
12
  content_line1
13
13
  content_line2
14
14
  ...
@@ -24,11 +24,9 @@ def _parse_patch(patch_str: str) -> Dict[str, List[Dict[str, Any]]]:
24
24
 
25
25
  # Parse file path and line range
26
26
  file_info = lines[0].strip()
27
- if not file_info.startswith('>'):
28
- continue
29
27
 
30
28
  # Extract file path and line range
31
- match = re.match(r'>\s*([^\s]+)\s+(\d+),(\d+)', file_info)
29
+ match = re.match(r'([^\s]+)\s+(\d+),(\d+)', file_info)
32
30
  if not match:
33
31
  continue
34
32
 
@@ -686,6 +686,8 @@ Please provide 10 search-optimized expressions in the specified format.
686
686
  if question_match:
687
687
  try:
688
688
  variants = yaml.safe_load(question_match.group(1))
689
+ if not isinstance(variants, list):
690
+ variants = [str(variants)]
689
691
  except Exception as e:
690
692
  PrettyOutput.print(f"解析变体失败: {str(e)}", OutputType.ERROR)
691
693