jarvis-ai-assistant 0.1.5__py3-none-any.whl → 0.1.7__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 (35) hide show
  1. jarvis/__init__.py +1 -1
  2. jarvis/__pycache__/__init__.cpython-313.pyc +0 -0
  3. jarvis/__pycache__/agent.cpython-313.pyc +0 -0
  4. jarvis/__pycache__/main.cpython-313.pyc +0 -0
  5. jarvis/__pycache__/models.cpython-313.pyc +0 -0
  6. jarvis/__pycache__/utils.cpython-313.pyc +0 -0
  7. jarvis/__pycache__/zte_llm.cpython-313.pyc +0 -0
  8. jarvis/agent.py +235 -70
  9. jarvis/main.py +30 -14
  10. jarvis/models.py +72 -60
  11. jarvis/tools/__init__.py +1 -3
  12. jarvis/tools/__pycache__/__init__.cpython-313.pyc +0 -0
  13. jarvis/tools/__pycache__/base.cpython-313.pyc +0 -0
  14. jarvis/tools/__pycache__/file_ops.cpython-313.pyc +0 -0
  15. jarvis/tools/__pycache__/search.cpython-313.pyc +0 -0
  16. jarvis/tools/__pycache__/shell.cpython-313.pyc +0 -0
  17. jarvis/tools/__pycache__/sub_agent.cpython-313.pyc +0 -0
  18. jarvis/tools/__pycache__/user_input.cpython-313.pyc +0 -0
  19. jarvis/tools/__pycache__/webpage.cpython-313.pyc +0 -0
  20. jarvis/tools/base.py +49 -128
  21. jarvis/tools/file_ops.py +1 -1
  22. jarvis/tools/search.py +77 -14
  23. jarvis/tools/shell.py +44 -49
  24. jarvis/tools/sub_agent.py +29 -25
  25. jarvis/tools/webpage.py +12 -26
  26. jarvis/utils.py +101 -65
  27. jarvis/zte_llm.py +28 -25
  28. {jarvis_ai_assistant-0.1.5.dist-info → jarvis_ai_assistant-0.1.7.dist-info}/METADATA +2 -1
  29. jarvis_ai_assistant-0.1.7.dist-info/RECORD +37 -0
  30. jarvis/.jarvis +0 -1
  31. jarvis/tools/python_script.py +0 -150
  32. jarvis_ai_assistant-0.1.5.dist-info/RECORD +0 -38
  33. {jarvis_ai_assistant-0.1.5.dist-info → jarvis_ai_assistant-0.1.7.dist-info}/WHEEL +0 -0
  34. {jarvis_ai_assistant-0.1.5.dist-info → jarvis_ai_assistant-0.1.7.dist-info}/entry_points.txt +0 -0
  35. {jarvis_ai_assistant-0.1.5.dist-info → jarvis_ai_assistant-0.1.7.dist-info}/top_level.txt +0 -0
jarvis/tools/__init__.py CHANGED
@@ -1,5 +1,4 @@
1
1
  from .base import Tool, ToolRegistry
2
- from .python_script import PythonScript
3
2
  from .file_ops import FileOperationTool
4
3
  from .search import SearchTool
5
4
  from .shell import ShellTool
@@ -8,9 +7,8 @@ from .webpage import WebpageTool
8
7
  __all__ = [
9
8
  'Tool',
10
9
  'ToolRegistry',
11
- 'PythonScript',
12
10
  'FileOperationTool',
13
11
  'SearchTool',
14
12
  'ShellTool',
15
13
  'WebpageTool',
16
- ]
14
+ ]
jarvis/tools/base.py CHANGED
@@ -13,12 +13,9 @@ class Tool:
13
13
  def to_dict(self) -> Dict:
14
14
  """转换为Ollama工具格式"""
15
15
  return {
16
- "type": "function",
17
- "function": {
18
- "name": self.name,
19
- "description": self.description,
20
- "parameters": self.parameters
21
- }
16
+ "name": self.name,
17
+ "description": self.description,
18
+ "parameters": json.dumps(self.parameters)
22
19
  }
23
20
 
24
21
  def execute(self, arguments: Dict) -> Dict[str, Any]:
@@ -35,17 +32,16 @@ class ToolRegistry:
35
32
  """注册所有默认工具"""
36
33
  from .search import SearchTool
37
34
  from .shell import ShellTool
38
- from .python_script import PythonScriptTool
39
35
  from .file_ops import FileOperationTool
40
36
  from .webpage import WebpageTool
41
37
  from .sub_agent import SubAgentTool
42
38
 
43
39
  tools = [
44
- SearchTool(),
40
+ SearchTool(self.model),
45
41
  ShellTool(),
46
- PythonScriptTool(),
47
42
  FileOperationTool(),
48
43
  WebpageTool(),
44
+ SubAgentTool(self.model)
49
45
  ]
50
46
 
51
47
  for tool in tools:
@@ -56,14 +52,6 @@ class ToolRegistry:
56
52
  func=tool.execute
57
53
  )
58
54
 
59
- sub_agent_tool = SubAgentTool(self.model)
60
- self.register_tool(
61
- name=sub_agent_tool.name,
62
- description=sub_agent_tool.description,
63
- parameters=sub_agent_tool.parameters,
64
- func=sub_agent_tool.execute
65
- )
66
-
67
55
  def register_tool(self, name: str, description: str, parameters: Dict, func: Callable):
68
56
  """注册新工具"""
69
57
  self.tools[name] = Tool(name, description, parameters, func)
@@ -84,115 +72,48 @@ class ToolRegistry:
84
72
  return tool.execute(arguments)
85
73
 
86
74
  def handle_tool_calls(self, tool_calls: List[Dict]) -> str:
87
- """处理工具调用"""
88
- results = []
89
- for tool_call in tool_calls:
90
- name = tool_call["function"]["name"]
91
- args = tool_call["function"]["arguments"]
92
- if isinstance(args, str):
93
- try:
94
- args = json.loads(args)
95
- except json.JSONDecodeError:
96
- return f"Invalid JSON in arguments for tool {name}"
97
-
98
- PrettyOutput.print(f"Calling tool: {name}", OutputType.INFO)
99
- if isinstance(args, dict):
100
- for key, value in args.items():
101
- PrettyOutput.print(f" - {key}: {value}", OutputType.INFO)
102
- else:
103
- PrettyOutput.print(f" Arguments: {args}", OutputType.INFO)
104
- PrettyOutput.print("", OutputType.INFO)
75
+ """处理工具调用,只处理第一个工具"""
76
+ if not tool_calls:
77
+ return ""
105
78
 
106
- result = self.execute_tool(name, args)
107
- if result["success"]:
108
- stdout = result["stdout"]
109
- stderr = result.get("stderr", "")
110
- output_parts = []
111
- output_parts.append(f"Result:\n{stdout}")
112
- if stderr:
113
- output_parts.append(f"Errors:\n{stderr}")
114
- output = "\n\n".join(output_parts)
115
- else:
116
- error_msg = result["error"]
117
- output = f"Execution failed: {error_msg}"
118
-
119
- results.append(output)
120
- return "\n".join(results)
121
-
122
- def tool_help_text(self) -> str:
123
- """返回所有工具的帮助文本"""
124
- return """Available Tools:
125
-
126
- 1. search: Search for information using DuckDuckGo
127
- 2. read_webpage: Extract content from webpages
128
- 3. execute_python: Run Python code with dependency management
129
- 4. execute_shell: Execute shell commands
130
- 5. file_operation: Read/write files in workspace directory
131
- 6. create_sub_agent: Create a sub-agent to handle subtasks (ONLY for independent subtasks)
132
-
133
- Core Rules:
134
- 1. ONE Step at a Time
135
- - Execute only one action per response
136
- - Explain what you're going to do before doing it
137
- - Wait for the result before planning next step
138
- - No multiple actions or parallel execution
139
-
140
- 2. Sub-Agent Usage (ONLY for Subtasks)
141
- - Create sub-agents ONLY to handle independent subtasks
142
- - Main task should be broken down into clear subtasks first
143
- - Examples of good subtask delegation:
144
- * Analyzing each Python file in a directory
145
- * Processing each data file in a batch
146
- * Researching different aspects of a topic
147
- * Reviewing multiple code components
148
- - Do NOT use for:
149
- * Main task execution
150
- * Single file operations
151
- * Simple sequential steps
152
- * Tasks requiring continuous context
153
-
154
- 3. Output Guidelines
155
- - Focus on essential information
156
- - Clear step-by-step explanations
157
- - Summarize results concisely
158
-
159
- Tool Call Format:
160
- <tool_call>
161
- {
162
- "name": "tool_name",
163
- "arguments": {
164
- "param1": "value1"
165
- }
166
- }
167
- </tool_call>
168
-
169
- Example (Correct - Subtask Delegation):
170
- Assistant: I'll create a sub-agent to handle the code analysis subtask.
171
- <tool_call>
172
- {
173
- "name": "create_sub_agent",
174
- "arguments": {
175
- "name": "CodeAnalyzer",
176
- "task": "Analyze the utils.py file structure and generate documentation",
177
- "context": "This is part of the larger documentation task"
178
- }
179
- }
180
- </tool_call>
181
-
182
- Example (Incorrect - Main Task):
183
- ❌ Assistant: I'll create a sub-agent to handle the entire project analysis.
184
- <tool_call>
185
- {
186
- "name": "create_sub_agent",
187
- "arguments": {
188
- "name": "ProjectAnalyzer",
189
- "task": "Analyze and document the entire project"
190
- }
191
- }
192
- </tool_call>
193
-
194
- Remember:
195
- 1. ONE step at a time
196
- 2. Create sub-agents ONLY for subtasks
197
- 3. Explain before acting
198
- 4. Wait for results"""
79
+ # 只处理第一个工具调用
80
+ tool_call = tool_calls[0]
81
+ name = tool_call["name"]
82
+ args = tool_call["arguments"]
83
+
84
+ if isinstance(args, str):
85
+ try:
86
+ args = json.loads(args)
87
+ except json.JSONDecodeError:
88
+ PrettyOutput.print(f"工具参数格式无效: {name}", OutputType.ERROR)
89
+ return ""
90
+
91
+ # 显示工具调用信息
92
+ PrettyOutput.section(f"执行工具: {name}", OutputType.TOOL)
93
+ if isinstance(args, dict):
94
+ for key, value in args.items():
95
+ PrettyOutput.print(f"参数: {key} = {value}", OutputType.DEBUG)
96
+ else:
97
+ PrettyOutput.print(f"参数: {args}", OutputType.DEBUG)
98
+
99
+ # 执行工具调用
100
+ result = self.execute_tool(name, args)
101
+
102
+ # 处理结果
103
+ if result["success"]:
104
+ stdout = result["stdout"]
105
+ stderr = result.get("stderr", "")
106
+ output_parts = []
107
+ if stdout:
108
+ output_parts.append(f"输出:\n{stdout}")
109
+ if stderr:
110
+ output_parts.append(f"错误:\n{stderr}")
111
+ output = "\n\n".join(output_parts)
112
+ output = "没有输出和错误" if not output else output
113
+ PrettyOutput.section("执行成功", OutputType.SUCCESS)
114
+ else:
115
+ error_msg = result["error"]
116
+ output = f"执行失败: {error_msg}"
117
+ PrettyOutput.section("执行失败", OutputType.ERROR)
118
+
119
+ return output
jarvis/tools/file_ops.py CHANGED
@@ -5,7 +5,7 @@ from ..utils import PrettyOutput, OutputType
5
5
 
6
6
  class FileOperationTool:
7
7
  name = "file_operation"
8
- description = "Execute file operations (read/write/append/exists)"
8
+ description = "文件操作 (read/write/append/exists)"
9
9
  parameters = {
10
10
  "type": "object",
11
11
  "properties": {
jarvis/tools/search.py CHANGED
@@ -1,43 +1,106 @@
1
- from typing import Dict, Any
1
+ from typing import Dict, Any, List
2
2
  from duckduckgo_search import DDGS
3
3
  from ..utils import PrettyOutput, OutputType
4
+ from .webpage import WebpageTool
4
5
 
5
6
  class SearchTool:
6
7
  name = "search"
7
- description = "Search for information using DuckDuckGo search engine"
8
+ description = "使用DuckDuckGo搜索引擎搜索信息,并根据问题提取关键信息"
8
9
  parameters = {
9
10
  "type": "object",
10
11
  "properties": {
11
12
  "query": {
12
13
  "type": "string",
13
- "description": "Search query string"
14
+ "description": "搜索关键词"
15
+ },
16
+ "question": {
17
+ "type": "string",
18
+ "description": "需要回答的具体问题,用于从搜索结果中提取相关信息"
14
19
  },
15
20
  "max_results": {
16
21
  "type": "integer",
17
- "description": "Maximum number of results to return",
18
- "default": 5
22
+ "description": "最大搜索结果数量",
23
+ "default": 3
19
24
  }
20
25
  },
21
- "required": ["query"]
26
+ "required": ["query", "question"]
22
27
  }
23
28
 
29
+ def __init__(self, model):
30
+ """初始化搜索工具,需要传入语言模型用于信息提取"""
31
+ self.model = model
32
+ self.webpage_tool = WebpageTool()
33
+
34
+ def _extract_info(self, contents: List[str], question: str) -> str:
35
+ """使用语言模型从网页内容中提取关键信息"""
36
+ prompt = {
37
+ "role": "user",
38
+ "content": f"""请根据以下搜索结果内容,回答问题:{question}
39
+
40
+ 搜索结果内容:
41
+ {'-' * 40}
42
+ {''.join(contents)}
43
+ {'-' * 40}
44
+
45
+ 请提供一个简洁、准确的答案,重点关注与问题直接相关的信息。如果搜索结果中没有相关信息,请明确说明。
46
+ 回答时注意:
47
+ 1. 保持客观性,只基于搜索结果提供信息
48
+ 2. 如果不同来源有冲突,请指出差异
49
+ 3. 适当引用信息来源
50
+ 4. 如果信息不完整或不确定,请说明"""
51
+ }
52
+
53
+ try:
54
+ response = self.model.chat([prompt])
55
+ return response
56
+ except Exception as e:
57
+ return f"信息提取失败: {str(e)}"
58
+
24
59
  def execute(self, args: Dict) -> Dict[str, Any]:
25
- """使用DuckDuckGo进行搜索"""
60
+ """执行搜索并提取信息"""
26
61
  try:
27
- # 打印搜索查询
28
- PrettyOutput.print(f"搜索查询: {args['query']}", OutputType.INFO)
62
+ query = args["query"]
63
+ question = args["question"]
64
+ max_results = args.get("max_results", 3)
65
+
66
+ # 打印搜索信息
67
+ PrettyOutput.print(f"搜索查询: {query}", OutputType.INFO)
68
+ PrettyOutput.print(f"相关问题: {question}", OutputType.INFO)
29
69
 
30
70
  # 获取搜索结果
71
+ search_results = []
31
72
  with DDGS() as ddgs:
32
- results = ddgs.text(
33
- keywords=args["query"],
34
- max_results=args.get("max_results", 5)
35
- )
73
+ results = list(ddgs.text(
74
+ keywords=query,
75
+ max_results=max_results
76
+ ))
77
+
78
+ # 收集网页内容
79
+ contents = []
80
+ for i, result in enumerate(results, 1):
81
+ try:
82
+ PrettyOutput.print(f"正在读取第 {i}/{len(results)} 个结果... {result['title']} - {result['href']} - {result['body']}", OutputType.PROGRESS)
83
+ webpage_result = self.webpage_tool.execute({"url": result["href"]})
84
+ if webpage_result["success"]:
85
+ contents.append(f"\n来源 {i}:{result['href']}\n")
86
+ contents.append(webpage_result["stdout"])
87
+ except Exception as e:
88
+ PrettyOutput.print(f"读取结果 {i} 失败: {str(e)}", OutputType.WARNING)
89
+ continue
90
+
91
+ if not contents:
92
+ return {
93
+ "success": False,
94
+ "error": "未能获取任何有效的搜索结果"
95
+ }
36
96
 
97
+ # 提取信息
98
+ PrettyOutput.print("正在分析搜索结果...", OutputType.PROGRESS)
99
+ analysis = self._extract_info(contents, question)
37
100
 
38
101
  return {
39
102
  "success": True,
40
- "stdout": results,
103
+ "stdout": f"搜索分析结果:\n\n{analysis}",
41
104
  "stderr": ""
42
105
  }
43
106
 
jarvis/tools/shell.py CHANGED
@@ -1,80 +1,75 @@
1
1
  from typing import Dict, Any
2
- import subprocess
2
+ import os
3
+ import tempfile
4
+ import shlex
5
+ from pathlib import Path
3
6
  from ..utils import PrettyOutput, OutputType
4
7
 
5
8
  class ShellTool:
6
9
  name = "execute_shell"
7
- description = """Execute shell commands and return the results.
8
- Guidelines for output optimization:
9
- 1. Use grep/awk/sed to filter output when possible
10
- 2. Avoid listing all files/dirs unless specifically needed
11
- 3. Prefer -q/--quiet flags when status is all that's needed
12
- 4. Use head/tail to limit long outputs
13
- 5. Redirect stderr to /dev/null for noisy commands
14
-
15
- Examples of optimized commands:
16
- - 'ls -l file.txt' instead of 'ls -l'
17
- - 'grep -c pattern file' instead of 'grep pattern file'
18
- - 'ps aux | grep process | head -n 5' instead of 'ps aux'
19
- - 'command 2>/dev/null' to suppress error messages
20
- - 'df -h . ' instead of 'df -h'
21
- """
10
+ description = """执行shell命令并返回结果"""
11
+
22
12
  parameters = {
23
13
  "type": "object",
24
14
  "properties": {
25
15
  "command": {
26
16
  "type": "string",
27
- "description": "Shell command to execute (use filters/limits for large outputs)"
28
- },
29
- "timeout": {
30
- "type": "integer",
31
- "description": "Command execution timeout in seconds",
32
- "default": 30
17
+ "description": "Shell command to execute (filter output when possible)"
33
18
  }
34
19
  },
35
20
  "required": ["command"]
36
21
  }
37
22
 
23
+ def _escape_command(self, cmd: str) -> str:
24
+ """转义命令中的特殊字符"""
25
+ # 将命令中的单引号替换为'"'"'
26
+ return cmd.replace("'", "'\"'\"'")
27
+
38
28
  def execute(self, args: Dict) -> Dict[str, Any]:
39
29
  """执行shell命令"""
40
30
  try:
41
- # 获取参数
42
31
  command = args["command"]
43
- timeout = args.get("timeout", 30)
44
32
 
45
- # 执行命令
46
- result = subprocess.run(
47
- command,
48
- shell=True,
49
- capture_output=True,
50
- text=True,
51
- timeout=timeout
52
- )
33
+ # 生成临时文件名
34
+ output_file = os.path.join(tempfile.gettempdir(), f"jarvis_shell_{os.getpid()}.log")
53
35
 
54
- # 构建输出
55
- output = []
36
+ # 转义命令中的特殊字符
37
+ escaped_command = self._escape_command(command)
38
+
39
+ # 修改命令以使用script
40
+ tee_command = f"script -q -c '{escaped_command}' {output_file}"
56
41
 
57
- # 添加命令信息
58
42
  PrettyOutput.print(f"执行命令: {command}", OutputType.INFO)
59
- output.append(f"命令: {command}")
60
- output.append("")
61
43
 
62
- # 添加输出
63
- if result.stdout:
64
- output.append(result.stdout)
44
+ # 执行命令
45
+ return_code = os.system(tee_command)
46
+
47
+ # 读取输出文件
48
+ try:
49
+ with open(output_file, 'r', encoding='utf-8', errors='replace') as f:
50
+ output = f.read()
51
+ # 移除script命令添加的头尾
52
+ if output:
53
+ lines = output.splitlines()
54
+ if len(lines) > 2:
55
+ output = "\n".join(lines[1:-1])
56
+ except Exception as e:
57
+ output = f"读取输出文件失败: {str(e)}"
58
+ finally:
59
+ # 清理临时文件
60
+ Path(output_file).unlink(missing_ok=True)
65
61
 
66
62
  return {
67
- "success": True,
68
- "stdout": "\n".join(output),
69
- "stderr": result.stderr,
70
- "return_code": result.returncode
71
- }
72
- except subprocess.TimeoutExpired:
73
- return {
74
- "success": False,
75
- "error": f"命令执行超时 (>{timeout}秒)"
63
+ "success": return_code == 0,
64
+ "stdout": output,
65
+ "stderr": "",
66
+ "return_code": return_code
76
67
  }
68
+
77
69
  except Exception as e:
70
+ # 确保清理临时文件
71
+ if 'output_file' in locals():
72
+ Path(output_file).unlink(missing_ok=True)
78
73
  return {
79
74
  "success": False,
80
75
  "error": str(e)
jarvis/tools/sub_agent.py CHANGED
@@ -6,37 +6,26 @@ from .base import ToolRegistry
6
6
 
7
7
  class SubAgentTool:
8
8
  name = "create_sub_agent"
9
- description = """Create a sub-agent to handle independent tasks.
10
-
11
- Use this tool when:
12
- 1. A subtask can be executed independently
13
- 2. The task requires separate context management
14
- 3. To optimize token usage of the main agent
15
- 4. For parallel task processing
9
+ description = """创建一个子代理来处理独立任务。(重要:子代理启动时没有任何上下文!必须提供完整的步骤和上下文。)"""
16
10
 
17
- The sub-agent will:
18
- 1. Inherit all tools from the parent agent
19
- 2. Maintain its own conversation history
20
- 3. Return a comprehensive task summary
21
- """
22
11
  parameters = {
23
12
  "type": "object",
24
13
  "properties": {
25
14
  "name": {
26
15
  "type": "string",
27
- "description": "Name for the sub-agent (e.g., 'FileAnalyzer', 'CodeReviewer')"
16
+ "description": "子代理名称(例如:'文件分析器'"
28
17
  },
29
18
  "task": {
30
19
  "type": "string",
31
- "description": "Task description with complete context"
20
+ "description": "需要明确步骤和目标的任务"
32
21
  },
33
22
  "context": {
34
23
  "type": "string",
35
- "description": "Additional context or background information",
24
+ "description": "必填:背景信息、执行步骤和预期结果",
36
25
  "default": ""
37
26
  }
38
27
  },
39
- "required": ["name", "task"]
28
+ "required": ["name", "task", "context"]
40
29
  }
41
30
 
42
31
  def __init__(self, model: BaseModel):
@@ -48,32 +37,47 @@ The sub-agent will:
48
37
  try:
49
38
  name = args["name"]
50
39
  task = args["task"]
51
- context = args.get("context", "")
40
+ context = args.get("context")
52
41
 
53
- PrettyOutput.print(f"Creating sub-agent '{name}'...", OutputType.INFO)
42
+ if not context:
43
+ return {
44
+ "success": False,
45
+ "error": "必须提供上下文信息,包括完整的背景和执行步骤。"
46
+ }
47
+
48
+ PrettyOutput.print(f"正在创建子代理 '{name}'...", OutputType.INFO)
54
49
 
55
50
  # Create a new tool registry for the sub-agent
56
51
  tool_registry = ToolRegistry(self.model)
57
52
 
58
53
  # Create the sub-agent with the specified name
59
- sub_agent = Agent(self.model, tool_registry, name=name)
54
+ sub_agent = Agent(self.model, tool_registry, name=name, is_sub_agent=True)
60
55
 
61
- # Prepare the task with context if provided
62
- full_task = f"{context}\n\nTask: {task}" if context else task
56
+ # Prepare the task with context
57
+ full_task = f"""背景和步骤:
58
+ {context}
59
+
60
+ 主要任务:
61
+ {task}
62
+
63
+ 要求:
64
+ 1. 严格按照提供的步骤执行
65
+ 2. 每完成一个步骤都要报告进度
66
+ 3. 突出显示任何问题或不明确的点
67
+ 4. 提供符合预期输出的详细结果"""
63
68
 
64
- PrettyOutput.print(f"Sub-agent '{name}' executing task...", OutputType.INFO)
69
+ PrettyOutput.print(f"子代理 '{name}' 正在执行任务...", OutputType.INFO)
65
70
 
66
71
  # Execute the task and get the summary
67
72
  summary = sub_agent.run(full_task)
68
-
69
73
  return {
70
74
  "success": True,
71
- "stdout": f"Sub-agent '{name}' completed the task.\n\nSummary:\n{summary}",
75
+ "stdout": f"子代理 '{name}' 已完成。\n\n结果:\n{summary}",
72
76
  "stderr": ""
73
77
  }
74
78
 
75
79
  except Exception as e:
76
80
  return {
77
81
  "success": False,
78
- "error": f"Sub-agent execution failed: {str(e)}"
82
+ "error": f"子代理执行失败:{str(e)}"
79
83
  }