myagent-ai 1.23.25 → 1.23.27
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.
- package/core/tool_dispatcher.py +9 -4
- package/package.json +1 -1
- package/skills/registry.py +40 -21
- package/web/api_server.py +67 -55
package/core/tool_dispatcher.py
CHANGED
|
@@ -76,7 +76,9 @@ class ToolDispatcher:
|
|
|
76
76
|
if stream_callback is None:
|
|
77
77
|
return
|
|
78
78
|
import asyncio
|
|
79
|
-
|
|
79
|
+
# [v1.23.25] 用 "data" 键包裹 payload,与 file_send.py 的格式一致
|
|
80
|
+
# 前端 flow_engine.js 通过 evt.data 访问 payload
|
|
81
|
+
event = {"type": event_type, "data": data}
|
|
80
82
|
try:
|
|
81
83
|
if asyncio.iscoroutinefunction(stream_callback):
|
|
82
84
|
await stream_callback(event)
|
|
@@ -117,8 +119,13 @@ class ToolDispatcher:
|
|
|
117
119
|
# ── [v1.23.0] 已迁移为内部服务/CLI 子命令的工具 ──
|
|
118
120
|
elif tool_name == "recall_memory":
|
|
119
121
|
return {"success": False, "error": "'recall_memory' 已迁移,请通过 <recall> 标签或 CLI 调用: command {\"command\": \"myagent-ai memory --keyword xxx\"}"}
|
|
122
|
+
|
|
123
|
+
# ── [v1.23.25] 恢复 playaudio/playvideo/file_send 直接工具调用 ──
|
|
124
|
+
# 原因: CLI 迁移后 LLM 不稳定地使用 command 包裹,导致工具经常失败
|
|
120
125
|
elif tool_name in ("playaudio", "playvideo"):
|
|
121
|
-
return
|
|
126
|
+
return await self._exec_media(tool_name, params, task_id, stream_callback, sent_files)
|
|
127
|
+
elif tool_name == "file_send":
|
|
128
|
+
return await self._exec_file_send(params, task_id, stream_callback, sent_files)
|
|
122
129
|
|
|
123
130
|
# ── [v1.23.0] 已迁移为 CLI 子命令的工具 — 提示使用 command 调用 ──
|
|
124
131
|
elif tool_name in ("image_ocr", "ocr"):
|
|
@@ -127,8 +134,6 @@ class ToolDispatcher:
|
|
|
127
134
|
return {"success": False, "error": f"'{tool_name}' 已迁移为 CLI 命令,请使用: command {{\"command\": \"myagent-ai analyze-image <image_path>\"}}"}
|
|
128
135
|
elif tool_name in ("audio_transcribe", "transcribe"):
|
|
129
136
|
return {"success": False, "error": f"'{tool_name}' 已迁移为 CLI 命令,请使用: command {{\"command\": \"myagent-ai transcribe <audio_path>\"}}"}
|
|
130
|
-
elif tool_name == "file_send":
|
|
131
|
-
return {"success": False, "error": "'file_send' 已迁移为 CLI 命令,请使用: command {\"command\": \"myagent-ai send-file <path>\"}"}
|
|
132
137
|
|
|
133
138
|
# ── 兜底: SkillRegistry ──
|
|
134
139
|
if self.skills:
|
package/package.json
CHANGED
package/skills/registry.py
CHANGED
|
@@ -25,17 +25,15 @@ logger = get_logger("myagent.skills")
|
|
|
25
25
|
# ==============================================================================
|
|
26
26
|
# 内置平台工具 — LLM 直接调用的工具
|
|
27
27
|
# ==============================================================================
|
|
28
|
-
# [v1.23.0] 单工具架构: LLM
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
# - file_send: 由 CLI __SEND_FILE__ 标记自动触发
|
|
33
|
-
# - playaudio/playvideo: 已迁移为 CLI 子命令(通过 __EMBED_AUDIO__/__EMBED_VIDEO__ 标记)
|
|
28
|
+
# [v1.23.0] 单工具架构: LLM 核心工具为 command 和 web_control。
|
|
29
|
+
# [v1.23.26] 恢复 file_send / playaudio / playvideo 直接工具调用。
|
|
30
|
+
# 原因: CLI 迁移后 LLM 不稳定地使用 command 包裹,导致工具经常失败。
|
|
31
|
+
# 这些工具需要同时存在于 BUILTIN_TOOLS(暴露给 LLM)和 dispatch()(执行处理)。
|
|
34
32
|
|
|
35
33
|
BUILTIN_TOOLS: List[Dict[str, Any]] = [
|
|
36
34
|
{
|
|
37
35
|
"name": "command",
|
|
38
|
-
"description": "执行 Shell 命令 —
|
|
36
|
+
"description": "执行 Shell 命令 — 所有操作(文件、搜索、文档生成、系统管理等)均通过此工具完成。LLM 通过 myagent-ai CLI 子命令调用各项能力。",
|
|
39
37
|
"category": "platform",
|
|
40
38
|
"handler": "ToolDispatcher._exec_command",
|
|
41
39
|
"parameters": [
|
|
@@ -59,6 +57,39 @@ BUILTIN_TOOLS: List[Dict[str, Any]] = [
|
|
|
59
57
|
{"name": "value", "type": "string", "description": "输入值", "required": False},
|
|
60
58
|
],
|
|
61
59
|
},
|
|
60
|
+
# [v1.23.26] 恢复直接工具调用 — LLM 可直接调用 file_send/playaudio/playvideo
|
|
61
|
+
{
|
|
62
|
+
"name": "file_send",
|
|
63
|
+
"description": "向用户发送文件 — 将已存在的文件(图片、PDF、文档等)发送给用户,在聊天中显示文件卡片供下载/预览。",
|
|
64
|
+
"category": "media",
|
|
65
|
+
"handler": "ToolDispatcher._exec_file_send",
|
|
66
|
+
"parameters": [
|
|
67
|
+
{"name": "file_path", "type": "string", "description": "要发送的文件路径(绝对路径或相对路径)", "required": True},
|
|
68
|
+
{"name": "description", "type": "string", "description": "文件描述(可选)", "required": False},
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "playaudio",
|
|
73
|
+
"description": "在聊天中内嵌播放音频 — 支持 YouTube Music、网易云音乐、QQ音乐、B站等在线平台,也可播放本地音频文件。",
|
|
74
|
+
"category": "media",
|
|
75
|
+
"handler": "ToolDispatcher._exec_media",
|
|
76
|
+
"parameters": [
|
|
77
|
+
{"name": "url", "type": "string", "description": "在线音频链接(YouTube Music / 网易云音乐 / QQ音乐 / B站等)", "required": False},
|
|
78
|
+
{"name": "file_path", "type": "string", "description": "本地音频文件路径", "required": False},
|
|
79
|
+
{"name": "title", "type": "string", "description": "音频标题(可选,用于嵌入播放器标题)", "required": False},
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"name": "playvideo",
|
|
84
|
+
"description": "在聊天中内嵌播放视频 — 支持 YouTube、B站、抖音等在线平台,也可播放本地视频文件。",
|
|
85
|
+
"category": "media",
|
|
86
|
+
"handler": "ToolDispatcher._exec_media",
|
|
87
|
+
"parameters": [
|
|
88
|
+
{"name": "url", "type": "string", "description": "在线视频链接(YouTube / B站 / 抖音等)", "required": False},
|
|
89
|
+
{"name": "file_path", "type": "string", "description": "本地视频文件路径", "required": False},
|
|
90
|
+
{"name": "title", "type": "string", "description": "视频标题(可选,用于嵌入播放器标题)", "required": False},
|
|
91
|
+
],
|
|
92
|
+
},
|
|
62
93
|
]
|
|
63
94
|
|
|
64
95
|
# ==============================================================================
|
|
@@ -76,20 +107,8 @@ INTERNAL_SERVICES: List[Dict[str, Any]] = [
|
|
|
76
107
|
"handler": "ToolDispatcher._exec_recall_memory",
|
|
77
108
|
"note": "已迁移: 通过 <recall> 标签或 myagent-ai memory CLI 调用",
|
|
78
109
|
},
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
"description": "在聊天中内嵌播放音频 — 已迁移为 CLI 子命令",
|
|
82
|
-
"category": "media",
|
|
83
|
-
"handler": "ToolDispatcher._exec_media",
|
|
84
|
-
"note": "已迁移: 通过 myagent-ai playaudio CLI 调用",
|
|
85
|
-
},
|
|
86
|
-
{
|
|
87
|
-
"name": "playvideo",
|
|
88
|
-
"description": "在聊天中内嵌播放视频 — 已迁移为 CLI 子命令",
|
|
89
|
-
"category": "media",
|
|
90
|
-
"handler": "ToolDispatcher._exec_media",
|
|
91
|
-
"note": "已迁移: 通过 myagent-ai playvideo CLI 调用",
|
|
92
|
-
},
|
|
110
|
+
# [v1.23.26] playaudio/playvideo 已恢复到 BUILTIN_TOOLS,但 CLI 子命令仍可用
|
|
111
|
+
# 作为 command 工具的备用调用方式。
|
|
93
112
|
]
|
|
94
113
|
|
|
95
114
|
|
package/web/api_server.py
CHANGED
|
@@ -1033,10 +1033,14 @@ async function loadLocalNoVNC() {{
|
|
|
1033
1033
|
function stripJs(p) {{ return p.endsWith('.js') ? p.slice(0, -3) : p; }}
|
|
1034
1034
|
|
|
1035
1035
|
// 加载并注册单个模块
|
|
1036
|
+
// [v1.23.26] modId 使用完整路径(含 lib/ 前缀)保证 Babel 相对路径解析正确,
|
|
1037
|
+
// fetchPath 剥离 lib/ 前缀用于 URL 请求(basePath 已含 /vnc/lib/)
|
|
1036
1038
|
async function loadModule(filePath) {{
|
|
1037
|
-
const modId = stripJs(filePath);
|
|
1039
|
+
const modId = stripJs(filePath); // e.g. "lib/deflator" or "lib/vendor/pako/lib/zlib/zstream"
|
|
1038
1040
|
if (_modules[modId]) return _modules[modId]; // 已加载
|
|
1039
|
-
|
|
1041
|
+
// strip leading "lib/" for fetch URL since basePath is already "/vnc/lib/"
|
|
1042
|
+
const fetchPath = filePath.startsWith('lib/') ? filePath.slice(4) : filePath;
|
|
1043
|
+
const resp = await fetch(basePath + fetchPath);
|
|
1040
1044
|
if (!resp.ok) throw new Error('Failed to fetch ' + filePath + ': ' + resp.status);
|
|
1041
1045
|
const code = await resp.text();
|
|
1042
1046
|
const modExports = {{}};
|
|
@@ -1054,66 +1058,74 @@ async function loadLocalNoVNC() {{
|
|
|
1054
1058
|
}}
|
|
1055
1059
|
|
|
1056
1060
|
// 按依赖顺序加载所有 noVNC 模块
|
|
1061
|
+
// [v1.23.25] 模块 ID 必须保留完整目录路径(lib/ 前缀),
|
|
1062
|
+
// 因为 Babel 编译的 require() 使用相对于原始 lib/ 目录的相对路径。
|
|
1063
|
+
// 例如 deflator.js 中 require("../lib/vendor/pako/...") 需要模块 ID 为 "lib/deflator"
|
|
1064
|
+
// 才能正确解析为 "vendor/pako/..." 而非 "lib/vendor/pako/..."。
|
|
1057
1065
|
const depFiles = [
|
|
1058
|
-
// pako vendor (zlib 依赖)
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
'vendor/pako/lib/
|
|
1064
|
-
'vendor/pako/lib/zlib/
|
|
1065
|
-
'vendor/pako/lib/zlib/
|
|
1066
|
-
'vendor/pako/lib/zlib/
|
|
1067
|
-
'vendor/pako/lib/zlib/
|
|
1068
|
-
'vendor/pako/lib/zlib/
|
|
1069
|
-
'vendor/pako/lib/zlib/
|
|
1070
|
-
|
|
1071
|
-
'
|
|
1072
|
-
'
|
|
1073
|
-
'
|
|
1074
|
-
|
|
1075
|
-
'util/
|
|
1076
|
-
'util/
|
|
1077
|
-
'util/
|
|
1078
|
-
'util/
|
|
1079
|
-
'
|
|
1080
|
-
'
|
|
1081
|
-
'
|
|
1082
|
-
'
|
|
1083
|
-
'
|
|
1084
|
-
'
|
|
1085
|
-
'
|
|
1086
|
-
'
|
|
1087
|
-
'
|
|
1088
|
-
'decoders/
|
|
1089
|
-
'decoders/
|
|
1090
|
-
'decoders/
|
|
1091
|
-
'decoders/
|
|
1092
|
-
'
|
|
1093
|
-
'
|
|
1094
|
-
'
|
|
1095
|
-
'
|
|
1096
|
-
'
|
|
1097
|
-
'input/
|
|
1098
|
-
'input/
|
|
1099
|
-
'input/
|
|
1100
|
-
'input/
|
|
1101
|
-
'input/
|
|
1066
|
+
// [v1.23.26] pako vendor (zlib 依赖) — 必须使用 lib/ 前缀
|
|
1067
|
+
// 因为 Babel 编译的 inflator.js/deflator.js 使用 require("../lib/vendor/pako/..."),
|
|
1068
|
+
// 从 modId "lib/inflator" 解析后得到 "lib/vendor/pako/...",
|
|
1069
|
+
// 如果 vendor 文件注册为 "vendor/..."(无 lib/ 前缀) 则匹配失败,
|
|
1070
|
+
// 导致 _zstream.default is not a constructor 错误。
|
|
1071
|
+
'lib/vendor/pako/lib/utils/common.js',
|
|
1072
|
+
'lib/vendor/pako/lib/zlib/adler32.js',
|
|
1073
|
+
'lib/vendor/pako/lib/zlib/crc32.js',
|
|
1074
|
+
'lib/vendor/pako/lib/zlib/messages.js',
|
|
1075
|
+
'lib/vendor/pako/lib/zlib/inffast.js',
|
|
1076
|
+
'lib/vendor/pako/lib/zlib/inftrees.js',
|
|
1077
|
+
'lib/vendor/pako/lib/zlib/trees.js',
|
|
1078
|
+
'lib/vendor/pako/lib/zlib/inflate.js',
|
|
1079
|
+
'lib/vendor/pako/lib/zlib/deflate.js',
|
|
1080
|
+
'lib/vendor/pako/lib/zlib/gzheader.js',
|
|
1081
|
+
'lib/vendor/pako/lib/zlib/zstream.js',
|
|
1082
|
+
// noVNC core — 使用 lib/ 前缀保持目录结构
|
|
1083
|
+
'lib/util/logging.js',
|
|
1084
|
+
'lib/util/events.js',
|
|
1085
|
+
'lib/util/eventtarget.js',
|
|
1086
|
+
'lib/util/strings.js',
|
|
1087
|
+
'lib/util/browser.js',
|
|
1088
|
+
'lib/util/int.js',
|
|
1089
|
+
'lib/util/element.js',
|
|
1090
|
+
'lib/util/cursor.js',
|
|
1091
|
+
'lib/base64.js',
|
|
1092
|
+
'lib/websock.js',
|
|
1093
|
+
'lib/display.js',
|
|
1094
|
+
'lib/inflator.js',
|
|
1095
|
+
'lib/deflator.js',
|
|
1096
|
+
'lib/decoders/copyrect.js',
|
|
1097
|
+
'lib/decoders/raw.js',
|
|
1098
|
+
'lib/decoders/rre.js',
|
|
1099
|
+
'lib/decoders/hextile.js',
|
|
1100
|
+
'lib/decoders/tight.js',
|
|
1101
|
+
'lib/decoders/tightpng.js',
|
|
1102
|
+
'lib/decoders/zrle.js',
|
|
1103
|
+
'lib/decoders/jpeg.js',
|
|
1104
|
+
'lib/encodings.js',
|
|
1105
|
+
'lib/input/keysymdef.js',
|
|
1106
|
+
'lib/input/keysym.js',
|
|
1107
|
+
'lib/input/xtscancodes.js',
|
|
1108
|
+
'lib/input/vkeys.js',
|
|
1109
|
+
'lib/input/fixedkeys.js',
|
|
1110
|
+
'lib/input/domkeytable.js',
|
|
1111
|
+
'lib/input/util.js',
|
|
1112
|
+
'lib/input/keyboard.js',
|
|
1113
|
+
'lib/input/gesturehandler.js',
|
|
1102
1114
|
// crypto (rfb.js → ra2.js → crypto/)
|
|
1103
|
-
'crypto/bigint.js',
|
|
1104
|
-
'crypto/dh.js',
|
|
1105
|
-
'crypto/md5.js',
|
|
1106
|
-
'crypto/des.js',
|
|
1107
|
-
'crypto/aes.js',
|
|
1108
|
-
'crypto/rsa.js',
|
|
1109
|
-
'crypto/crypto.js',
|
|
1110
|
-
'ra2.js',
|
|
1115
|
+
'lib/crypto/bigint.js',
|
|
1116
|
+
'lib/crypto/dh.js',
|
|
1117
|
+
'lib/crypto/md5.js',
|
|
1118
|
+
'lib/crypto/des.js',
|
|
1119
|
+
'lib/crypto/aes.js',
|
|
1120
|
+
'lib/crypto/rsa.js',
|
|
1121
|
+
'lib/crypto/crypto.js',
|
|
1122
|
+
'lib/ra2.js',
|
|
1111
1123
|
];
|
|
1112
1124
|
for (const file of depFiles) {{
|
|
1113
1125
|
await loadModule(file);
|
|
1114
1126
|
}}
|
|
1115
1127
|
// 最后加载 rfb.js
|
|
1116
|
-
const rfbExports = await loadModule('rfb.js');
|
|
1128
|
+
const rfbExports = await loadModule('lib/rfb.js');
|
|
1117
1129
|
return rfbExports.default || rfbExports;
|
|
1118
1130
|
}}
|
|
1119
1131
|
</script>
|