jarvis-ai-assistant 0.3.20__py3-none-any.whl → 0.3.21__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.
- jarvis/__init__.py +1 -1
- jarvis/jarvis_agent/__init__.py +24 -3
- jarvis/jarvis_agent/config_editor.py +5 -1
- jarvis/jarvis_agent/edit_file_handler.py +15 -9
- jarvis/jarvis_agent/jarvis.py +99 -3
- jarvis/jarvis_agent/memory_manager.py +3 -3
- jarvis/jarvis_agent/share_manager.py +3 -1
- jarvis/jarvis_agent/task_analyzer.py +0 -1
- jarvis/jarvis_agent/task_manager.py +15 -5
- jarvis/jarvis_agent/tool_executor.py +2 -2
- jarvis/jarvis_code_agent/code_agent.py +39 -16
- jarvis/jarvis_git_utils/git_commiter.py +3 -6
- jarvis/jarvis_mcp/sse_mcp_client.py +9 -3
- jarvis/jarvis_mcp/streamable_mcp_client.py +15 -5
- jarvis/jarvis_memory_organizer/memory_organizer.py +1 -1
- jarvis/jarvis_methodology/main.py +4 -4
- jarvis/jarvis_multi_agent/__init__.py +3 -3
- jarvis/jarvis_platform/base.py +10 -5
- jarvis/jarvis_platform/kimi.py +18 -6
- jarvis/jarvis_platform/tongyi.py +18 -5
- jarvis/jarvis_platform/yuanbao.py +10 -3
- jarvis/jarvis_platform_manager/main.py +21 -7
- jarvis/jarvis_platform_manager/service.py +4 -3
- jarvis/jarvis_rag/cli.py +61 -22
- jarvis/jarvis_rag/embedding_manager.py +10 -3
- jarvis/jarvis_rag/llm_interface.py +4 -1
- jarvis/jarvis_rag/query_rewriter.py +3 -1
- jarvis/jarvis_rag/rag_pipeline.py +11 -3
- jarvis/jarvis_rag/retriever.py +151 -2
- jarvis/jarvis_smart_shell/main.py +59 -18
- jarvis/jarvis_stats/cli.py +11 -9
- jarvis/jarvis_stats/stats.py +14 -8
- jarvis/jarvis_stats/storage.py +23 -6
- jarvis/jarvis_tools/cli/main.py +63 -29
- jarvis/jarvis_tools/edit_file.py +3 -4
- jarvis/jarvis_tools/file_analyzer.py +0 -1
- jarvis/jarvis_tools/generate_new_tool.py +3 -3
- jarvis/jarvis_tools/read_code.py +0 -1
- jarvis/jarvis_tools/read_webpage.py +14 -4
- jarvis/jarvis_tools/registry.py +0 -3
- jarvis/jarvis_tools/retrieve_memory.py +0 -1
- jarvis/jarvis_tools/save_memory.py +0 -1
- jarvis/jarvis_tools/search_web.py +0 -2
- jarvis/jarvis_tools/sub_agent.py +197 -0
- jarvis/jarvis_tools/sub_code_agent.py +194 -0
- jarvis/jarvis_tools/virtual_tty.py +21 -13
- jarvis/jarvis_utils/config.py +35 -5
- jarvis/jarvis_utils/input.py +297 -56
- jarvis/jarvis_utils/methodology.py +3 -1
- jarvis/jarvis_utils/output.py +5 -2
- jarvis/jarvis_utils/utils.py +480 -170
- {jarvis_ai_assistant-0.3.20.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/METADATA +10 -2
- {jarvis_ai_assistant-0.3.20.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/RECORD +57 -55
- {jarvis_ai_assistant-0.3.20.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.3.20.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.3.20.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.3.20.dist-info → jarvis_ai_assistant-0.3.21.dist-info}/top_level.txt +0 -0
jarvis/jarvis_tools/cli/main.py
CHANGED
@@ -23,12 +23,20 @@ def list_tools(
|
|
23
23
|
|
24
24
|
if as_json:
|
25
25
|
if detailed:
|
26
|
-
PrettyOutput.print(
|
26
|
+
PrettyOutput.print(
|
27
|
+
json.dumps(tools, indent=2, ensure_ascii=False),
|
28
|
+
OutputType.CODE,
|
29
|
+
lang="json",
|
30
|
+
)
|
27
31
|
else:
|
28
32
|
simple_tools = [
|
29
33
|
{"name": t["name"], "description": t["description"]} for t in tools
|
30
34
|
]
|
31
|
-
PrettyOutput.print(
|
35
|
+
PrettyOutput.print(
|
36
|
+
json.dumps(simple_tools, indent=2, ensure_ascii=False),
|
37
|
+
OutputType.CODE,
|
38
|
+
lang="json",
|
39
|
+
)
|
32
40
|
else:
|
33
41
|
PrettyOutput.section("可用工具列表", OutputType.SYSTEM)
|
34
42
|
for tool in tools:
|
@@ -37,18 +45,27 @@ def list_tools(
|
|
37
45
|
if detailed:
|
38
46
|
PrettyOutput.print(" 参数:", OutputType.INFO)
|
39
47
|
import json as _json # local import to ensure available
|
40
|
-
|
48
|
+
|
49
|
+
PrettyOutput.print(
|
50
|
+
_json.dumps(tool["parameters"], ensure_ascii=False, indent=2),
|
51
|
+
OutputType.CODE,
|
52
|
+
lang="json",
|
53
|
+
)
|
41
54
|
|
42
55
|
|
43
56
|
@app.command("stat")
|
44
57
|
def stat_tools(
|
45
58
|
as_json: bool = typer.Option(False, "--json", help="以JSON格式输出"),
|
46
|
-
last_days: Optional[int] = typer.Option(
|
47
|
-
|
59
|
+
last_days: Optional[int] = typer.Option(
|
60
|
+
None, "--days", help="显示最近N天的统计(默认显示所有历史数据)"
|
61
|
+
),
|
62
|
+
format: str = typer.Option(
|
63
|
+
"table", "--format", help="显示格式: table, chart, summary"
|
64
|
+
),
|
48
65
|
):
|
49
66
|
"""显示工具调用统计信息"""
|
50
67
|
from jarvis.jarvis_stats.stats import StatsManager
|
51
|
-
|
68
|
+
|
52
69
|
if format == "table":
|
53
70
|
registry = ToolRegistry()
|
54
71
|
stats = registry._get_tool_stats()
|
@@ -64,13 +81,24 @@ def stat_tools(
|
|
64
81
|
table_data.sort(key=lambda x: x[1], reverse=True)
|
65
82
|
|
66
83
|
if as_json:
|
67
|
-
PrettyOutput.print(
|
84
|
+
PrettyOutput.print(
|
85
|
+
json.dumps(dict(table_data), indent=2), OutputType.CODE, lang="json"
|
86
|
+
)
|
68
87
|
else:
|
69
88
|
time_desc = f"最近{last_days}天" if last_days else "所有历史"
|
70
89
|
PrettyOutput.section(f"工具调用统计 ({time_desc})", OutputType.SYSTEM)
|
71
90
|
if table_data:
|
72
|
-
PrettyOutput.print(
|
73
|
-
|
91
|
+
PrettyOutput.print(
|
92
|
+
tabulate(
|
93
|
+
table_data, headers=["工具名称", "调用次数"], tablefmt="grid"
|
94
|
+
),
|
95
|
+
OutputType.CODE,
|
96
|
+
lang="text",
|
97
|
+
)
|
98
|
+
PrettyOutput.print(
|
99
|
+
f"\n总计: {len(table_data)} 个工具被使用,共 {sum(x[1] for x in table_data)} 次调用",
|
100
|
+
OutputType.INFO,
|
101
|
+
)
|
74
102
|
else:
|
75
103
|
PrettyOutput.print("暂无工具调用记录", OutputType.INFO)
|
76
104
|
else:
|
@@ -79,51 +107,59 @@ def stat_tools(
|
|
79
107
|
# 显示所有标记为 tool 组的指标
|
80
108
|
metrics = StatsManager.list_metrics()
|
81
109
|
tool_metrics = []
|
82
|
-
|
110
|
+
|
83
111
|
for metric in metrics:
|
84
112
|
# 检查是否是工具组的指标
|
85
113
|
if last_days:
|
86
114
|
stats_data = StatsManager.get_stats(
|
87
|
-
metric_name=metric,
|
88
|
-
last_days=last_days,
|
89
|
-
tags={"group": "tool"}
|
115
|
+
metric_name=metric, last_days=last_days, tags={"group": "tool"}
|
90
116
|
)
|
91
117
|
else:
|
92
118
|
# 获取所有历史数据
|
93
119
|
from datetime import datetime
|
120
|
+
|
94
121
|
stats_data = StatsManager.get_stats(
|
95
122
|
metric_name=metric,
|
96
123
|
start_time=datetime(2000, 1, 1),
|
97
124
|
end_time=datetime.now(),
|
98
|
-
tags={"group": "tool"}
|
125
|
+
tags={"group": "tool"},
|
99
126
|
)
|
100
127
|
if stats_data and stats_data.get("records"):
|
101
128
|
tool_metrics.append(metric)
|
102
|
-
|
129
|
+
|
103
130
|
if tool_metrics:
|
104
131
|
for metric in tool_metrics:
|
105
132
|
if format == "chart":
|
106
133
|
if last_days:
|
107
|
-
StatsManager.plot(
|
134
|
+
StatsManager.plot(
|
135
|
+
metric, last_days=last_days, tags={"group": "tool"}
|
136
|
+
)
|
108
137
|
else:
|
109
138
|
from datetime import datetime
|
139
|
+
|
110
140
|
StatsManager.plot(
|
111
|
-
metric,
|
112
|
-
start_time=datetime(2000, 1, 1),
|
113
|
-
end_time=datetime.now(),
|
114
|
-
tags={"group": "tool"}
|
141
|
+
metric,
|
142
|
+
start_time=datetime(2000, 1, 1),
|
143
|
+
end_time=datetime.now(),
|
144
|
+
tags={"group": "tool"},
|
115
145
|
)
|
116
146
|
elif format == "summary":
|
117
147
|
if last_days:
|
118
|
-
StatsManager.show(
|
148
|
+
StatsManager.show(
|
149
|
+
metric,
|
150
|
+
last_days=last_days,
|
151
|
+
format="summary",
|
152
|
+
tags={"group": "tool"},
|
153
|
+
)
|
119
154
|
else:
|
120
155
|
from datetime import datetime
|
156
|
+
|
121
157
|
StatsManager.show(
|
122
|
-
metric,
|
123
|
-
start_time=datetime(2000, 1, 1),
|
124
|
-
end_time=datetime.now(),
|
125
|
-
format="summary",
|
126
|
-
tags={"group": "tool"}
|
158
|
+
metric,
|
159
|
+
start_time=datetime(2000, 1, 1),
|
160
|
+
end_time=datetime.now(),
|
161
|
+
format="summary",
|
162
|
+
tags={"group": "tool"},
|
127
163
|
)
|
128
164
|
else:
|
129
165
|
PrettyOutput.print("暂无工具调用记录", OutputType.INFO)
|
@@ -159,9 +195,7 @@ def call_tool(
|
|
159
195
|
with open(args_file, "r", encoding="utf-8") as f:
|
160
196
|
tool_args = json.load(f)
|
161
197
|
except (json.JSONDecodeError, FileNotFoundError) as e:
|
162
|
-
PrettyOutput.print(
|
163
|
-
f"错误: 无法从文件加载参数: {str(e)}", OutputType.ERROR
|
164
|
-
)
|
198
|
+
PrettyOutput.print(f"错误: 无法从文件加载参数: {str(e)}", OutputType.ERROR)
|
165
199
|
raise typer.Exit(code=1)
|
166
200
|
|
167
201
|
required_params = tool_obj.parameters.get("required", [])
|
jarvis/jarvis_tools/edit_file.py
CHANGED
@@ -148,12 +148,13 @@ class FileSearchReplaceTool:
|
|
148
148
|
content = f.read()
|
149
149
|
original_content = content
|
150
150
|
|
151
|
-
|
152
151
|
success, temp_content = EditFileHandler._fast_edit(
|
153
152
|
file_path, changes
|
154
153
|
)
|
155
154
|
if not success:
|
156
|
-
PrettyOutput.print(
|
155
|
+
PrettyOutput.print(
|
156
|
+
f"文件 {file_path} 处理失败", OutputType.ERROR
|
157
|
+
)
|
157
158
|
file_results.append(
|
158
159
|
{
|
159
160
|
"file": file_path,
|
@@ -164,8 +165,6 @@ class FileSearchReplaceTool:
|
|
164
165
|
)
|
165
166
|
continue
|
166
167
|
|
167
|
-
|
168
|
-
|
169
168
|
# 只有当所有替换操作都成功时,才写回文件
|
170
169
|
if success and (
|
171
170
|
temp_content != original_content or not file_exists
|
@@ -80,7 +80,9 @@ class generate_new_tool:
|
|
80
80
|
# 验证工具代码中的名称是否与tool_name一致
|
81
81
|
import re
|
82
82
|
|
83
|
-
match = re.search(
|
83
|
+
match = re.search(
|
84
|
+
r"^\s*name\s*=\s*[\"'](.+?)[\"']", tool_code, re.MULTILINE
|
85
|
+
)
|
84
86
|
if not match:
|
85
87
|
return {
|
86
88
|
"success": False,
|
@@ -146,8 +148,6 @@ class generate_new_tool:
|
|
146
148
|
)
|
147
149
|
success_message += f"\n注册到当前会话失败,可能需要重新启动Jarvis"
|
148
150
|
|
149
|
-
|
150
|
-
|
151
151
|
# 检查并安装缺失的依赖
|
152
152
|
try:
|
153
153
|
required_packages = set()
|
jarvis/jarvis_tools/read_code.py
CHANGED
@@ -81,15 +81,25 @@ class WebpageTool:
|
|
81
81
|
resp = http_get(url, timeout=10.0, allow_redirects=True)
|
82
82
|
content_md = md(resp.text, strip=["script", "style"])
|
83
83
|
except requests.exceptions.HTTPError as e:
|
84
|
-
PrettyOutput.print(
|
85
|
-
|
84
|
+
PrettyOutput.print(
|
85
|
+
f"⚠️ HTTP错误 {e.response.status_code} 访问 {url}",
|
86
|
+
OutputType.WARNING,
|
87
|
+
)
|
88
|
+
return {
|
89
|
+
"success": False,
|
90
|
+
"stdout": "",
|
91
|
+
"stderr": f"HTTP错误:{e.response.status_code}",
|
92
|
+
}
|
86
93
|
except requests.exceptions.RequestException as e:
|
87
94
|
PrettyOutput.print(f"⚠️ 请求错误: {e}", OutputType.WARNING)
|
88
95
|
return {"success": False, "stdout": "", "stderr": f"请求错误:{e}"}
|
89
96
|
|
90
97
|
if not content_md or not content_md.strip():
|
91
|
-
return {
|
92
|
-
|
98
|
+
return {
|
99
|
+
"success": False,
|
100
|
+
"stdout": "",
|
101
|
+
"stderr": "无法从网页抓取有效内容。",
|
102
|
+
}
|
93
103
|
|
94
104
|
summary_prompt = f"""以下是网页 {url} 的内容(已转换为Markdown):
|
95
105
|
----------------
|
jarvis/jarvis_tools/registry.py
CHANGED
@@ -288,7 +288,6 @@ class ToolRegistry(OutputHandlerProtocol):
|
|
288
288
|
if tool_name in self.tools:
|
289
289
|
del self.tools[tool_name]
|
290
290
|
|
291
|
-
|
292
291
|
def _load_mcp_tools(self) -> None:
|
293
292
|
"""加载MCP工具,优先从配置获取,其次从目录扫描"""
|
294
293
|
from jarvis.jarvis_utils.config import get_mcp_config
|
@@ -351,7 +350,6 @@ class ToolRegistry(OutputHandlerProtocol):
|
|
351
350
|
try:
|
352
351
|
import subprocess
|
353
352
|
|
354
|
-
|
355
353
|
subprocess.run(
|
356
354
|
["git", "clone", central_repo, central_repo_path], check=True
|
357
355
|
)
|
@@ -649,7 +647,6 @@ class ToolRegistry(OutputHandlerProtocol):
|
|
649
647
|
|
650
648
|
# Ask user for confirmation
|
651
649
|
|
652
|
-
|
653
650
|
data = temp_data
|
654
651
|
except (yaml.YAMLError, EOFError, KeyboardInterrupt):
|
655
652
|
# Even after fixing, it's not valid YAML, or user cancelled.
|
@@ -0,0 +1,197 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
"""
|
3
|
+
sub_agent 工具
|
4
|
+
将子任务交给通用 Agent 执行,并返回执行结果。
|
5
|
+
|
6
|
+
约定:
|
7
|
+
- 仅接收一个参数:task
|
8
|
+
- 不依赖父 Agent,所有配置使用系统默认与全局变量
|
9
|
+
- 子Agent必须自动完成(auto_complete=True)且需要summary(need_summary=True)
|
10
|
+
"""
|
11
|
+
from typing import Any, Dict, Optional
|
12
|
+
import json
|
13
|
+
|
14
|
+
from jarvis.jarvis_agent import Agent, origin_agent_system_prompt
|
15
|
+
from jarvis.jarvis_utils.globals import delete_agent
|
16
|
+
|
17
|
+
|
18
|
+
class SubAgentTool:
|
19
|
+
"""
|
20
|
+
临时创建一个通用 Agent 执行子任务,执行完立即清理。
|
21
|
+
- 不注册至全局
|
22
|
+
- 使用系统默认/全局配置
|
23
|
+
- 启用自动完成与总结
|
24
|
+
"""
|
25
|
+
|
26
|
+
# 必须与文件名一致,供 ToolRegistry 自动注册
|
27
|
+
name = "sub_agent"
|
28
|
+
description = "将子任务交给通用 Agent 执行,并返回执行结果(使用系统默认配置,自动完成并生成总结)。"
|
29
|
+
parameters = {
|
30
|
+
"type": "object",
|
31
|
+
"properties": {
|
32
|
+
"task": {
|
33
|
+
"type": "string",
|
34
|
+
"description": "要执行的子任务内容(必填)",
|
35
|
+
},
|
36
|
+
"background": {
|
37
|
+
"type": "string",
|
38
|
+
"description": "任务背景与已知信息(可选,将与任务一并提供给子Agent)",
|
39
|
+
},
|
40
|
+
},
|
41
|
+
"required": ["task"],
|
42
|
+
}
|
43
|
+
|
44
|
+
def execute(self, args: Dict[str, Any]) -> Dict[str, Any]:
|
45
|
+
"""
|
46
|
+
执行子任务并返回结果。
|
47
|
+
返回:
|
48
|
+
- success: 是否成功
|
49
|
+
- stdout: 子 Agent 返回的结果(字符串或JSON字符串)
|
50
|
+
- stderr: 错误信息(如有)
|
51
|
+
"""
|
52
|
+
try:
|
53
|
+
task: str = str(args.get("task", "")).strip()
|
54
|
+
if not task:
|
55
|
+
return {
|
56
|
+
"success": False,
|
57
|
+
"stdout": "",
|
58
|
+
"stderr": "task 不能为空",
|
59
|
+
}
|
60
|
+
|
61
|
+
# 读取背景信息并组合任务
|
62
|
+
background: str = str(args.get("background", "")).strip()
|
63
|
+
enhanced_task = (
|
64
|
+
f"背景信息:\n{background}\n\n任务:\n{task}" if background else task
|
65
|
+
)
|
66
|
+
|
67
|
+
# 读取背景信息并组合任务
|
68
|
+
background: str = str(args.get("background", "")).strip()
|
69
|
+
enhanced_task = (
|
70
|
+
f"背景信息:\n{background}\n\n任务:\n{task}" if background else task
|
71
|
+
)
|
72
|
+
|
73
|
+
# 继承父Agent的运行参数(用于覆盖默认值);若无父Agent则使用默认/全局配置
|
74
|
+
parent_agent = args.get("agent")
|
75
|
+
# 如未注入父Agent,尝试从全局获取当前或任一已注册Agent
|
76
|
+
if parent_agent is None:
|
77
|
+
try:
|
78
|
+
from jarvis.jarvis_utils import globals as G # 延迟导入避免循环
|
79
|
+
|
80
|
+
curr = getattr(G, "current_agent_name", "")
|
81
|
+
if curr:
|
82
|
+
parent_agent = getattr(G, "global_agents", {}).get(curr)
|
83
|
+
if parent_agent is None and getattr(G, "global_agents", {}):
|
84
|
+
try:
|
85
|
+
parent_agent = next(iter(G.global_agents.values()))
|
86
|
+
except Exception:
|
87
|
+
parent_agent = None
|
88
|
+
except Exception:
|
89
|
+
parent_agent = None
|
90
|
+
# 默认/全局
|
91
|
+
system_prompt = origin_agent_system_prompt
|
92
|
+
need_summary = True
|
93
|
+
auto_complete = True
|
94
|
+
|
95
|
+
# 可继承参数
|
96
|
+
model_group = None
|
97
|
+
summary_prompt = None
|
98
|
+
execute_tool_confirm = None
|
99
|
+
use_methodology = None
|
100
|
+
use_analysis = None
|
101
|
+
force_save_memory = None
|
102
|
+
use_tools: list[str] = []
|
103
|
+
|
104
|
+
try:
|
105
|
+
if parent_agent is not None:
|
106
|
+
# 继承模型组
|
107
|
+
if getattr(parent_agent, "model", None):
|
108
|
+
model_group = getattr(parent_agent.model, "model_group", None)
|
109
|
+
# 继承开关类参数
|
110
|
+
summary_prompt = getattr(parent_agent, "summary_prompt", None)
|
111
|
+
execute_tool_confirm = getattr(
|
112
|
+
parent_agent, "execute_tool_confirm", None
|
113
|
+
)
|
114
|
+
use_methodology = getattr(parent_agent, "use_methodology", None)
|
115
|
+
use_analysis = getattr(parent_agent, "use_analysis", None)
|
116
|
+
force_save_memory = getattr(parent_agent, "force_save_memory", None)
|
117
|
+
# 继承工具使用集(名称列表)
|
118
|
+
parent_registry = parent_agent.get_tool_registry()
|
119
|
+
if parent_registry:
|
120
|
+
for t in parent_registry.get_all_tools():
|
121
|
+
if isinstance(t, dict) and t.get("name"):
|
122
|
+
use_tools.append(str(t["name"]))
|
123
|
+
except Exception:
|
124
|
+
# 忽略继承失败,退回默认配置
|
125
|
+
pass
|
126
|
+
|
127
|
+
# 为避免交互阻塞:提供自动确认与空输入处理器
|
128
|
+
def _auto_confirm(tip: str, default: bool = True) -> bool:
|
129
|
+
return default
|
130
|
+
|
131
|
+
# 创建子Agent(其余配置使用默认/全局)
|
132
|
+
agent = Agent(
|
133
|
+
system_prompt=system_prompt,
|
134
|
+
name="SubAgent",
|
135
|
+
description="Temporary sub agent for executing a subtask",
|
136
|
+
llm_type="normal", # 使用默认模型类型
|
137
|
+
model_group=model_group, # 继承父Agent模型组(如可用)
|
138
|
+
summary_prompt=summary_prompt, # 继承父Agent总结提示词(如可用)
|
139
|
+
auto_complete=auto_complete,
|
140
|
+
output_handler=None, # 默认 ToolRegistry
|
141
|
+
use_tools=None, # 初始不限定,稍后同步父Agent工具集
|
142
|
+
input_handler=None, # 允许使用系统默认输入链
|
143
|
+
execute_tool_confirm=execute_tool_confirm, # 继承父Agent(如可用)
|
144
|
+
need_summary=need_summary,
|
145
|
+
multiline_inputer=None, # 使用系统默认输入器(允许用户输入)
|
146
|
+
use_methodology=use_methodology, # 继承父Agent(如可用)
|
147
|
+
use_analysis=use_analysis, # 继承父Agent(如可用)
|
148
|
+
force_save_memory=force_save_memory, # 继承父Agent(如可用)
|
149
|
+
files=None,
|
150
|
+
confirm_callback=_auto_confirm, # 自动确认
|
151
|
+
)
|
152
|
+
|
153
|
+
# 同步父Agent的模型名称与工具使用集(若可用)
|
154
|
+
try:
|
155
|
+
if (
|
156
|
+
parent_agent is not None
|
157
|
+
and getattr(parent_agent, "model", None)
|
158
|
+
and getattr(agent, "model", None)
|
159
|
+
):
|
160
|
+
try:
|
161
|
+
model_name = parent_agent.model.name() # type: ignore[attr-defined]
|
162
|
+
if model_name:
|
163
|
+
agent.model.set_model_name(model_name) # type: ignore[attr-defined]
|
164
|
+
except Exception:
|
165
|
+
pass
|
166
|
+
if use_tools:
|
167
|
+
agent.set_use_tools(use_tools)
|
168
|
+
except Exception:
|
169
|
+
pass
|
170
|
+
|
171
|
+
# 执行任务
|
172
|
+
result = agent.run(enhanced_task)
|
173
|
+
|
174
|
+
# 主动清理,避免污染父 Agent 的全局状态
|
175
|
+
try:
|
176
|
+
delete_agent(agent.name)
|
177
|
+
except Exception:
|
178
|
+
pass
|
179
|
+
|
180
|
+
# 规范化输出
|
181
|
+
if isinstance(result, (dict, list)):
|
182
|
+
stdout = json.dumps(result, ensure_ascii=False, indent=2)
|
183
|
+
else:
|
184
|
+
stdout = str(result) if result is not None else "任务执行完成"
|
185
|
+
|
186
|
+
return {
|
187
|
+
"success": True,
|
188
|
+
"stdout": stdout,
|
189
|
+
"stderr": "",
|
190
|
+
}
|
191
|
+
|
192
|
+
except Exception as e:
|
193
|
+
return {
|
194
|
+
"success": False,
|
195
|
+
"stdout": "",
|
196
|
+
"stderr": f"执行子任务失败: {str(e)}",
|
197
|
+
}
|