jarvis-ai-assistant 0.3.20__py3-none-any.whl → 0.3.22__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 +42 -18
- 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 +47 -3
- jarvis/jarvis_rag/retriever.py +240 -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 +17 -90
- 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 +16 -9
- 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 +483 -170
- {jarvis_ai_assistant-0.3.20.dist-info → jarvis_ai_assistant-0.3.22.dist-info}/METADATA +10 -2
- {jarvis_ai_assistant-0.3.20.dist-info → jarvis_ai_assistant-0.3.22.dist-info}/RECORD +57 -55
- {jarvis_ai_assistant-0.3.20.dist-info → jarvis_ai_assistant-0.3.22.dist-info}/WHEEL +0 -0
- {jarvis_ai_assistant-0.3.20.dist-info → jarvis_ai_assistant-0.3.22.dist-info}/entry_points.txt +0 -0
- {jarvis_ai_assistant-0.3.20.dist-info → jarvis_ai_assistant-0.3.22.dist-info}/licenses/LICENSE +0 -0
- {jarvis_ai_assistant-0.3.20.dist-info → jarvis_ai_assistant-0.3.22.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
@@ -31,7 +31,6 @@ class FileSearchReplaceTool:
|
|
31
31
|
- reason: 修改原因描述
|
32
32
|
- SEARCH: 需要查找的原始代码(必须包含足够上下文)
|
33
33
|
- REPLACE: 替换后的新代码
|
34
|
-
3. 工具会自动选择最适合的编辑模式
|
35
34
|
|
36
35
|
## 核心原则
|
37
36
|
1. **精准修改**: 只修改必要的代码部分,保持其他部分不变
|
@@ -132,107 +131,35 @@ class FileSearchReplaceTool:
|
|
132
131
|
file_path = os.path.abspath(file_info["path"])
|
133
132
|
changes = file_info["changes"]
|
134
133
|
|
135
|
-
# 创建已处理文件变量,用于失败时回滚
|
136
|
-
original_content = None
|
137
|
-
processed = False
|
138
|
-
file_success = True
|
139
|
-
|
140
134
|
try:
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
135
|
+
success, result = EditFileHandler._fast_edit(file_path, changes)
|
136
|
+
if success:
|
137
|
+
stdout_message = f"文件 {file_path} 修改完成"
|
138
|
+
stdout_messages.append(stdout_message)
|
139
|
+
overall_success = True
|
140
|
+
file_results.append(
|
141
|
+
{
|
142
|
+
"file": file_path,
|
143
|
+
"success": True,
|
144
|
+
"stdout": stdout_message,
|
145
|
+
"stderr": "",
|
146
|
+
}
|
147
|
+
)
|
148
|
+
else:
|
149
|
+
PrettyOutput.print(
|
150
|
+
f"文件 {file_path} 处理失败", OutputType.ERROR
|
154
151
|
)
|
155
|
-
if not success:
|
156
|
-
PrettyOutput.print(f"文件 {file_path} 处理失败", OutputType.ERROR)
|
157
|
-
file_results.append(
|
158
|
-
{
|
159
|
-
"file": file_path,
|
160
|
-
"success": False,
|
161
|
-
"stdout": "",
|
162
|
-
"stderr": temp_content,
|
163
|
-
}
|
164
|
-
)
|
165
|
-
continue
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
# 只有当所有替换操作都成功时,才写回文件
|
170
|
-
if success and (
|
171
|
-
temp_content != original_content or not file_exists
|
172
|
-
):
|
173
|
-
# 确保目录存在
|
174
|
-
os.makedirs(
|
175
|
-
os.path.dirname(os.path.abspath(file_path)), exist_ok=True
|
176
|
-
)
|
177
|
-
|
178
|
-
with open(file_path, "w", encoding="utf-8") as f:
|
179
|
-
f.write(temp_content)
|
180
|
-
|
181
|
-
processed = True
|
182
|
-
|
183
|
-
action = "创建并写入" if not file_exists else "成功修改"
|
184
|
-
stdout_message = f"文件 {file_path} {action} 完成"
|
185
|
-
stdout_messages.append(stdout_message)
|
186
|
-
|
187
|
-
overall_success = True
|
188
|
-
|
189
|
-
file_results.append(
|
190
|
-
{
|
191
|
-
"file": file_path,
|
192
|
-
"success": True,
|
193
|
-
"stdout": stdout_message,
|
194
|
-
"stderr": "",
|
195
|
-
}
|
196
|
-
)
|
197
|
-
|
198
|
-
except Exception as e:
|
199
|
-
stderr_message = f"处理文件 {file_path} 时出错: {str(e)}"
|
200
|
-
stderr_messages.append(stderr_message)
|
201
|
-
PrettyOutput.print(stderr_message, OutputType.WARNING)
|
202
|
-
file_success = False
|
203
152
|
file_results.append(
|
204
153
|
{
|
205
154
|
"file": file_path,
|
206
155
|
"success": False,
|
207
156
|
"stdout": "",
|
208
|
-
"stderr":
|
157
|
+
"stderr": result,
|
209
158
|
}
|
210
159
|
)
|
211
|
-
|
212
160
|
except Exception as e:
|
213
161
|
error_msg = f"文件搜索替换操作失败: {str(e)}"
|
214
162
|
PrettyOutput.print(error_msg, OutputType.WARNING)
|
215
|
-
|
216
|
-
# 如果有已修改的文件,尝试回滚
|
217
|
-
if processed:
|
218
|
-
rollback_message = "操作失败,正在回滚修改..."
|
219
|
-
stderr_messages.append(rollback_message)
|
220
|
-
PrettyOutput.print(rollback_message, OutputType.WARNING)
|
221
|
-
|
222
|
-
try:
|
223
|
-
if original_content is None:
|
224
|
-
# 如果是新创建的文件,则删除
|
225
|
-
if os.path.exists(file_path):
|
226
|
-
os.remove(file_path)
|
227
|
-
stderr_messages.append(f"已删除新创建的文件: {file_path}")
|
228
|
-
else:
|
229
|
-
# 如果是修改的文件,则恢复原内容
|
230
|
-
with open(file_path, "w", encoding="utf-8") as f:
|
231
|
-
f.write(original_content)
|
232
|
-
stderr_messages.append(f"已回滚文件: {file_path}")
|
233
|
-
except:
|
234
|
-
stderr_messages.append(f"回滚文件失败: {file_path}")
|
235
|
-
|
236
163
|
file_results.append(
|
237
164
|
{
|
238
165
|
"file": file_path,
|
@@ -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
@@ -172,10 +172,14 @@ class ToolRegistry(OutputHandlerProtocol):
|
|
172
172
|
|
173
173
|
def handle(self, response: str, agent_: Any) -> Tuple[bool, Any]:
|
174
174
|
try:
|
175
|
-
tool_call, err_msg = self._extract_tool_calls(response)
|
175
|
+
tool_call, err_msg, auto_completed = self._extract_tool_calls(response)
|
176
176
|
if err_msg:
|
177
177
|
return False, err_msg
|
178
|
-
|
178
|
+
result = self.handle_tool_calls(tool_call, agent_)
|
179
|
+
if auto_completed:
|
180
|
+
# 如果自动补全了结束标签,在结果中添加说明信息
|
181
|
+
result = f"检测到工具调用缺少结束标签,已自动补全{ct('TOOL_CALL')}。请确保后续工具调用包含完整的开始和结束标签。\n\n{result}"
|
182
|
+
return False, result
|
179
183
|
except Exception as e:
|
180
184
|
PrettyOutput.print(f"工具调用处理失败: {str(e)}", OutputType.ERROR)
|
181
185
|
from jarvis.jarvis_agent import Agent
|
@@ -288,7 +292,6 @@ class ToolRegistry(OutputHandlerProtocol):
|
|
288
292
|
if tool_name in self.tools:
|
289
293
|
del self.tools[tool_name]
|
290
294
|
|
291
|
-
|
292
295
|
def _load_mcp_tools(self) -> None:
|
293
296
|
"""加载MCP工具,优先从配置获取,其次从目录扫描"""
|
294
297
|
from jarvis.jarvis_utils.config import get_mcp_config
|
@@ -351,7 +354,6 @@ class ToolRegistry(OutputHandlerProtocol):
|
|
351
354
|
try:
|
352
355
|
import subprocess
|
353
356
|
|
354
|
-
|
355
357
|
subprocess.run(
|
356
358
|
["git", "clone", central_repo, central_repo_path], check=True
|
357
359
|
)
|
@@ -611,16 +613,17 @@ class ToolRegistry(OutputHandlerProtocol):
|
|
611
613
|
)
|
612
614
|
|
613
615
|
@staticmethod
|
614
|
-
def _extract_tool_calls(content: str) -> Tuple[Dict[str, Dict[str, Any]], str]:
|
616
|
+
def _extract_tool_calls(content: str) -> Tuple[Dict[str, Dict[str, Any]], str, bool]:
|
615
617
|
"""从内容中提取工具调用。
|
616
618
|
|
617
619
|
参数:
|
618
620
|
content: 包含工具调用的内容
|
619
621
|
|
620
622
|
返回:
|
621
|
-
Tuple[Dict[str, Dict[str, Any]], str]:
|
623
|
+
Tuple[Dict[str, Dict[str, Any]], str, bool]:
|
622
624
|
- 第一个元素是提取的工具调用字典
|
623
625
|
- 第二个元素是错误消息字符串(成功时为"")
|
626
|
+
- 第三个元素是是否自动补全了结束标签
|
624
627
|
|
625
628
|
异常:
|
626
629
|
Exception: 如果工具调用缺少必要字段
|
@@ -629,6 +632,7 @@ class ToolRegistry(OutputHandlerProtocol):
|
|
629
632
|
data = re.findall(
|
630
633
|
ot("TOOL_CALL") + r"(.*?)" + ct("TOOL_CALL"), content, re.DOTALL
|
631
634
|
)
|
635
|
+
auto_completed = False
|
632
636
|
if not data:
|
633
637
|
# can_handle 确保 ot("TOOL_CALL") 在内容中。
|
634
638
|
# 如果数据为空,则表示 ct("TOOL_CALL") 可能丢失。
|
@@ -649,8 +653,8 @@ class ToolRegistry(OutputHandlerProtocol):
|
|
649
653
|
|
650
654
|
# Ask user for confirmation
|
651
655
|
|
652
|
-
|
653
656
|
data = temp_data
|
657
|
+
auto_completed = True
|
654
658
|
except (yaml.YAMLError, EOFError, KeyboardInterrupt):
|
655
659
|
# Even after fixing, it's not valid YAML, or user cancelled.
|
656
660
|
# Fall through to the original error.
|
@@ -660,6 +664,7 @@ class ToolRegistry(OutputHandlerProtocol):
|
|
660
664
|
return (
|
661
665
|
{},
|
662
666
|
f"只有{ot('TOOL_CALL')}标签,未找到{ct('TOOL_CALL')}标签,调用格式错误,请检查工具调用格式。\n{tool_call_help}",
|
667
|
+
False,
|
663
668
|
)
|
664
669
|
ret = []
|
665
670
|
for item in data:
|
@@ -672,6 +677,7 @@ class ToolRegistry(OutputHandlerProtocol):
|
|
672
677
|
{e}
|
673
678
|
|
674
679
|
{tool_call_help}""",
|
680
|
+
False,
|
675
681
|
)
|
676
682
|
|
677
683
|
if "name" in msg and "arguments" in msg and "want" in msg:
|
@@ -682,10 +688,11 @@ class ToolRegistry(OutputHandlerProtocol):
|
|
682
688
|
f"""工具调用格式错误,请检查工具调用格式(缺少name、arguments、want字段)。
|
683
689
|
|
684
690
|
{tool_call_help}""",
|
691
|
+
False,
|
685
692
|
)
|
686
693
|
if len(ret) > 1:
|
687
|
-
return {}, "检测到多个工具调用,请一次只处理一个工具调用。"
|
688
|
-
return ret[0] if ret else {}, ""
|
694
|
+
return {}, "检测到多个工具调用,请一次只处理一个工具调用。", False
|
695
|
+
return ret[0] if ret else {}, "", auto_completed
|
689
696
|
|
690
697
|
def register_tool(
|
691
698
|
self,
|