mu-agent-bridge 1.0.34 → 1.0.39
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/README.md +4 -2
- package/dist/src-ts/channel-sessions.js +90 -24
- package/dist/src-ts/control-server.js +48 -7
- package/dist/src-ts/dsh-agent.js +141 -46
- package/dist/src-ts/headless-account.patch.yml +8 -1
- package/dist/src-ts/plugin-manager.js +69 -3
- package/dist/src-ts/plugins/aun/attachments.js +44 -13
- package/dist/src-ts/plugins/aun/index.js +5 -6
- package/dist/src-ts/plugins/chatgpt/cdp-client.js +342 -9
- package/dist/src-ts/plugins/chatgpt/index.js +127 -7
- package/dist/src-ts/plugins/desktop-launch.js +19 -0
- package/dist/src-ts/plugins/doubao/attachments.js +42 -0
- package/dist/src-ts/plugins/doubao/cdp-client.js +530 -48
- package/dist/src-ts/plugins/doubao/index.js +114 -25
- package/dist/src-ts/plugins/doubao/session-history.js +123 -0
- package/dist/src-ts/plugins/dsh/index.js +18 -2
- package/dist/src-ts/plugins/dsh/session-history.js +371 -0
- package/dist/src-ts/plugins/qwenwork/cdp-client.js +271 -10
- package/dist/src-ts/plugins/qwenwork/index.js +42 -3
- package/dist/src-ts/plugins/qwenwork/session-history.js +245 -0
- package/dist/src-ts/plugins/workbuddy/cdp-client.js +42 -2
- package/dist/src-ts/plugins/workbuddy/index.js +23 -3
- package/dist/src-ts/plugins/workbuddy/session-history.js +121 -0
- package/dist/src-ts/session-archive.js +509 -0
- package/dist/src-ts/session-history.js +2 -0
- package/dist/src-ts/session-management.js +665 -0
- package/dist/src-ts/session-summary.js +171 -0
- package/dist/tests-ts/aun-attachments.test.js +41 -3
- package/dist/tests-ts/aun-plugin.test.js +28 -5
- package/dist/tests-ts/bundled-package.test.js +3 -1
- package/dist/tests-ts/channel-sessions.test.js +255 -2
- package/dist/tests-ts/chatgpt-history.test.js +197 -0
- package/dist/tests-ts/chatgpt-plugin.test.js +279 -2
- package/dist/tests-ts/control-server.test.js +39 -0
- package/dist/tests-ts/desktop-launch.test.js +41 -0
- package/dist/tests-ts/doubao-history.test.js +172 -0
- package/dist/tests-ts/doubao-plugin.test.js +549 -2
- package/dist/tests-ts/dsh-agent.test.js +199 -0
- package/dist/tests-ts/dsh-history.test.js +165 -0
- package/dist/tests-ts/native-session-management.test.js +195 -0
- package/dist/tests-ts/plugin-manager.test.js +354 -4
- package/dist/tests-ts/qwenwork-history.test.js +339 -0
- package/dist/tests-ts/qwenwork-images.test.js +166 -0
- package/dist/tests-ts/qwenwork-plugin.test.js +40 -1
- package/dist/tests-ts/session-archive.test.js +422 -0
- package/dist/tests-ts/session-management.test.js +323 -0
- package/dist/tests-ts/session-summary.test.js +199 -0
- package/dist/tests-ts/workbuddy-history.test.js +256 -0
- package/dist/tests-ts/workbuddy-plugin.test.js +43 -0
- package/package.json +1 -1
- package/plugins/aun/dist/src-ts/plugins/aun/attachments.js +44 -13
- package/plugins/aun/dist/src-ts/plugins/aun/index.js +5 -6
- package/plugins/aun/package.json +1 -1
- package/plugins/aun/plugin.json +1 -1
- package/plugins/chatgpt/dist/src-ts/attachments.js +62 -0
- package/plugins/chatgpt/dist/src-ts/plugins/chatgpt/cdp-client.js +342 -9
- package/plugins/chatgpt/dist/src-ts/plugins/chatgpt/index.js +127 -7
- package/plugins/chatgpt/package.json +1 -1
- package/plugins/chatgpt/plugin.json +14 -1
- package/plugins/doubao/config.schema.json +3 -0
- package/plugins/doubao/dist/src-ts/attachments.js +62 -0
- package/plugins/doubao/dist/src-ts/plugins/desktop-launch.js +19 -0
- package/plugins/doubao/dist/src-ts/plugins/doubao/attachments.js +42 -0
- package/plugins/doubao/dist/src-ts/plugins/doubao/cdp-client.js +530 -48
- package/plugins/doubao/dist/src-ts/plugins/doubao/index.js +114 -25
- package/plugins/doubao/dist/src-ts/plugins/doubao/session-history.js +123 -0
- package/plugins/doubao/package.json +1 -1
- package/plugins/doubao/plugin.json +1 -1
- package/plugins/dsh/config.schema.json +2 -1
- package/plugins/dsh/dist/src-ts/attachments.js +62 -0
- package/plugins/dsh/dist/src-ts/dsh-agent.js +141 -46
- package/plugins/dsh/dist/src-ts/headless-account.patch.yml +8 -1
- package/plugins/dsh/dist/src-ts/plugins/dsh/index.js +18 -2
- package/plugins/dsh/dist/src-ts/plugins/dsh/session-history.js +371 -0
- package/plugins/dsh/package.json +5 -2
- package/plugins/dsh/plugin.json +1 -1
- package/plugins/qwenwork/dist/src-ts/attachments.js +62 -0
- package/plugins/qwenwork/dist/src-ts/plugins/desktop-launch.js +19 -0
- package/plugins/qwenwork/dist/src-ts/plugins/qwenwork/cdp-client.js +271 -10
- package/plugins/qwenwork/dist/src-ts/plugins/qwenwork/index.js +42 -3
- package/plugins/qwenwork/dist/src-ts/plugins/qwenwork/session-history.js +245 -0
- package/plugins/qwenwork/package.json +1 -1
- package/plugins/qwenwork/plugin.json +1 -1
- package/plugins/workbuddy/config.schema.json +1 -1
- package/plugins/workbuddy/dist/src-ts/plugins/workbuddy/cdp-client.js +42 -2
- package/plugins/workbuddy/dist/src-ts/plugins/workbuddy/index.js +23 -3
- package/plugins/workbuddy/dist/src-ts/plugins/workbuddy/session-history.js +121 -0
- package/plugins/workbuddy/package.json +1 -1
- package/plugins/workbuddy/plugin.json +1 -1
|
@@ -1 +1,14 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"id": "chatgpt",
|
|
3
|
+
"version": "1.0.9",
|
|
4
|
+
"type": "agent",
|
|
5
|
+
"displayName": "ChatGPT(Codex)",
|
|
6
|
+
"entry": "dist/src-ts/plugins/chatgpt/index.js",
|
|
7
|
+
"apiVersion": "1",
|
|
8
|
+
"process": "in-process",
|
|
9
|
+
"capabilities": [
|
|
10
|
+
"chat",
|
|
11
|
+
"health"
|
|
12
|
+
],
|
|
13
|
+
"configSchema": "config.schema.json"
|
|
14
|
+
}
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
"properties": {
|
|
4
4
|
"aid": { "type": "string", "description": "复用的 EvolCore 已有 AID" },
|
|
5
5
|
"cdpPort": { "type": "integer", "minimum": 1, "description": "豆包桌面端 CDP 调试端口,默认 9227" },
|
|
6
|
+
"executablePath": { "type": "string", "description": "Doubao.exe 安装路径,自动查找同一安装位置的最新版本,省略时扫描常见安装目录" },
|
|
7
|
+
"autoStart": { "type": "boolean", "default": true, "description": "CDP 未连接时自动查找并启动豆包" },
|
|
8
|
+
"startupTimeoutMs": { "type": "integer", "minimum": 1000, "default": 30000, "description": "等待豆包启动的超时时间(毫秒)" },
|
|
6
9
|
"conversationId": { "type": "string", "description": "豆包会话 ID" },
|
|
7
10
|
"botId": { "type": "string", "description": "豆包 bot ID" },
|
|
8
11
|
"pluginList": { "type": "array", "items": { "type": "string" }, "description": "请求时显式启用的豆包伙伴标识,例如飞书伙伴" },
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MAX_TOTAL_ATTACHMENT_BYTES = exports.MAX_ATTACHMENTS = exports.MAX_ATTACHMENT_BYTES = void 0;
|
|
4
|
+
exports.detectImageContentType = detectImageContentType;
|
|
5
|
+
exports.attachmentFilename = attachmentFilename;
|
|
6
|
+
exports.validateAttachment = validateAttachment;
|
|
7
|
+
exports.validateAttachments = validateAttachments;
|
|
8
|
+
exports.asAttachments = asAttachments;
|
|
9
|
+
exports.MAX_ATTACHMENT_BYTES = 32 * 1024 * 1024;
|
|
10
|
+
exports.MAX_ATTACHMENTS = 8;
|
|
11
|
+
exports.MAX_TOTAL_ATTACHMENT_BYTES = 64 * 1024 * 1024;
|
|
12
|
+
function detectImageContentType(data) {
|
|
13
|
+
if (data.length >= 8 && data.slice(0, 8).every((value, index) => value === [137, 80, 78, 71, 13, 10, 26, 10][index]))
|
|
14
|
+
return "image/png";
|
|
15
|
+
if (data.length >= 3 && data[0] === 0xff && data[1] === 0xd8 && data[2] === 0xff)
|
|
16
|
+
return "image/jpeg";
|
|
17
|
+
if (data.length >= 12 && String.fromCharCode(...data.slice(0, 4)) === "RIFF" && String.fromCharCode(...data.slice(8, 12)) === "WEBP")
|
|
18
|
+
return "image/webp";
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
function attachmentFilename(filename) {
|
|
22
|
+
if (typeof filename !== "string" || /[\u0000-\u001f\u007f]/.test(filename))
|
|
23
|
+
throw new Error("附件文件名无效");
|
|
24
|
+
const name = filename.split(/[\\/]/).pop() ?? "";
|
|
25
|
+
if (!name.trim() || name === "." || name === "..")
|
|
26
|
+
throw new Error("附件文件名无效");
|
|
27
|
+
return name;
|
|
28
|
+
}
|
|
29
|
+
function validateAttachment(item) {
|
|
30
|
+
if (!item || !(item.data instanceof Uint8Array) || item.data.byteLength === 0)
|
|
31
|
+
throw new Error("附件内容不能为空");
|
|
32
|
+
if (item.data.byteLength > exports.MAX_ATTACHMENT_BYTES)
|
|
33
|
+
throw new Error("单个附件不能超过 32 MiB");
|
|
34
|
+
attachmentFilename(item.filename);
|
|
35
|
+
if (item.kind !== "image" && item.kind !== "file")
|
|
36
|
+
throw new Error("附件类型无效");
|
|
37
|
+
if (typeof item.contentType !== "string" || !/^[A-Za-z0-9!#$&^_.+-]+\/[A-Za-z0-9!#$&^_.+-]+$/.test(item.contentType))
|
|
38
|
+
throw new Error("附件 MIME 类型无效");
|
|
39
|
+
if (item.kind === "image") {
|
|
40
|
+
const detected = detectImageContentType(item.data);
|
|
41
|
+
if (!detected || detected !== item.contentType.toLowerCase())
|
|
42
|
+
throw new Error("图片内容与 MIME 类型不一致");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function validateAttachments(items) {
|
|
46
|
+
if (!items)
|
|
47
|
+
return;
|
|
48
|
+
if (!Array.isArray(items))
|
|
49
|
+
throw new Error("附件列表无效");
|
|
50
|
+
if (items.length > exports.MAX_ATTACHMENTS)
|
|
51
|
+
throw new Error("单条消息最多包含 8 个附件");
|
|
52
|
+
let total = 0;
|
|
53
|
+
for (const item of items) {
|
|
54
|
+
validateAttachment(item);
|
|
55
|
+
total += item.data.byteLength;
|
|
56
|
+
}
|
|
57
|
+
if (total > exports.MAX_TOTAL_ATTACHMENT_BYTES)
|
|
58
|
+
throw new Error("单条消息附件总大小不能超过 64 MiB");
|
|
59
|
+
}
|
|
60
|
+
function asAttachments(images) {
|
|
61
|
+
return (images ?? []).map((image) => ({ ...image, kind: "image" }));
|
|
62
|
+
}
|
|
@@ -7,10 +7,19 @@ exports.waitFor = waitFor;
|
|
|
7
7
|
const promises_1 = require("node:fs/promises");
|
|
8
8
|
const node_fs_1 = require("node:fs");
|
|
9
9
|
const node_path_1 = require("node:path");
|
|
10
|
+
const versionDirectory = /^(?:app[-_ ]?)?v?\d+(?:[.-]\d+)+$/i;
|
|
10
11
|
/** 在 Windows 常见安装目录中查找桌面程序,避免依赖单一盘符。 */
|
|
11
12
|
async function findWindowsExecutable(fileName, configured) {
|
|
12
13
|
if (configured?.trim()) {
|
|
13
14
|
const configuredPath = (0, node_path_1.resolve)(configured);
|
|
15
|
+
if (fileName.toLowerCase() === "doubao.exe") {
|
|
16
|
+
let root = (0, node_path_1.dirname)(configuredPath);
|
|
17
|
+
while (/^app$/i.test((0, node_path_1.basename)(root)) || versionDirectory.test((0, node_path_1.basename)(root)))
|
|
18
|
+
root = (0, node_path_1.dirname)(root);
|
|
19
|
+
const latest = await findExecutableInTree(root, fileName, /^/, 3);
|
|
20
|
+
if (latest)
|
|
21
|
+
return latest;
|
|
22
|
+
}
|
|
14
23
|
// 千问升级会保留或删除旧版本目录,从同一安装位置重新定位新版。
|
|
15
24
|
if (fileName.toLowerCase() === "qwenworkcn.exe" && /^v?\d+(?:[.-]\d+)+$/i.test((0, node_path_1.basename)((0, node_path_1.dirname)(configuredPath)))) {
|
|
16
25
|
const latest = await findExecutableInTree((0, node_path_1.dirname)((0, node_path_1.dirname)(configuredPath)), fileName, /^/, 1);
|
|
@@ -42,6 +51,16 @@ async function findExecutableInTree(directory, fileName, pattern, depth) {
|
|
|
42
51
|
async function search(directory, fileName, pattern, depth, insideProduct) {
|
|
43
52
|
try {
|
|
44
53
|
const entries = await (0, promises_1.readdir)(directory, { withFileTypes: true });
|
|
54
|
+
// 豆包上层文件是启动器,优先查找新版目录或 app 中的实际程序。
|
|
55
|
+
if (insideProduct && depth > 0 && fileName.toLowerCase() === "doubao.exe") {
|
|
56
|
+
const versions = entries.filter(entry => entry.isDirectory() && (versionDirectory.test(entry.name) || /^app$/i.test(entry.name)));
|
|
57
|
+
versions.sort((left, right) => right.name.replace(/^\D+/, "").localeCompare(left.name.replace(/^\D+/, ""), "en", { numeric: true }));
|
|
58
|
+
for (const entry of versions) {
|
|
59
|
+
const found = await search((0, node_path_1.join)(directory, entry.name), fileName, pattern, depth - 1, true);
|
|
60
|
+
if (found)
|
|
61
|
+
return found;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
45
64
|
for (const entry of entries)
|
|
46
65
|
if (entry.isFile() && insideProduct && entry.name.toLowerCase() === fileName.toLowerCase())
|
|
47
66
|
return (0, node_path_1.join)(directory, entry.name);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cleanupUploadScript = exports.uploadStateScript = void 0;
|
|
4
|
+
exports.buildUploadInjection = buildUploadInjection;
|
|
5
|
+
// 原生上传状态保存在附件区的 React 属性中,避免复刻平台私有上传签名。
|
|
6
|
+
exports.uploadStateScript = `() => {
|
|
7
|
+
const area = document.querySelector('[data-testid=attachment_area]');
|
|
8
|
+
let fiber = area?.[Object.keys(area).find(key => key.startsWith('__reactFiber'))];
|
|
9
|
+
while (fiber) {
|
|
10
|
+
if (Array.isArray(fiber.memoizedProps?.attachmentStates)) return fiber.memoizedProps.attachmentStates;
|
|
11
|
+
fiber = fiber.return;
|
|
12
|
+
}
|
|
13
|
+
return [];
|
|
14
|
+
}`;
|
|
15
|
+
function buildUploadInjection(items) {
|
|
16
|
+
return `(() => {
|
|
17
|
+
const editor = document.querySelector('[contenteditable=true]');
|
|
18
|
+
if (!editor) return '未找到豆包输入区';
|
|
19
|
+
if (editor.textContent.trim() || document.querySelector('[data-testid=attachment_area]')) return '豆包存在未发送草稿,请先处理草稿';
|
|
20
|
+
const input = document.querySelector('input[type=file][data-testid=upload-file-input]');
|
|
21
|
+
if (!input) return '未找到豆包原生附件上传入口';
|
|
22
|
+
const transfer = new DataTransfer();
|
|
23
|
+
for (const item of ${JSON.stringify(items)}) {
|
|
24
|
+
const bytes = Uint8Array.from(atob(item.base64), char => char.charCodeAt(0));
|
|
25
|
+
transfer.items.add(new File([bytes], item.uploadName, { type: item.type }));
|
|
26
|
+
}
|
|
27
|
+
Object.defineProperty(input, 'files', { value: transfer.files, configurable: true });
|
|
28
|
+
try { input.dispatchEvent(new Event('change', { bubbles: true })); }
|
|
29
|
+
finally { delete input.files; }
|
|
30
|
+
return 'started';
|
|
31
|
+
})()`;
|
|
32
|
+
}
|
|
33
|
+
// 唯一文件名前缀限定清理范围,用户上传的新附件不会被删除。
|
|
34
|
+
exports.cleanupUploadScript = `(names) => {
|
|
35
|
+
const states = (${exports.uploadStateScript})();
|
|
36
|
+
const area = document.querySelector('[data-testid=attachment_area]');
|
|
37
|
+
const buttons = area?.querySelectorAll('[data-testid=attachment-delete-btn], [data-testid=message_nested_content_file_delete]') || [];
|
|
38
|
+
for (let index = states.length - 1; index >= 0; index--) {
|
|
39
|
+
if (names.includes(states[index].fileName)) buttons[index]?.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
|
40
|
+
}
|
|
41
|
+
return 'cleaned';
|
|
42
|
+
}`;
|