mu-agent-bridge 1.0.65 → 1.0.66
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/dist/src-ts/plugins/abweb/public/app.js +1 -1
- package/dist/src-ts/plugins/desktop-launch.js +10 -4
- package/dist/src-ts/plugins/workbuddy/index.js +14 -2
- package/dist/tests-ts/abweb-cli.test.js +29 -0
- package/dist/tests-ts/desktop-launch.test.js +14 -0
- package/dist/tests-ts/installer-assets.test.js +14 -0
- package/dist/tests-ts/workbuddy-plugin.test.js +13 -16
- package/package.json +1 -1
- package/plugins/abweb/dist/src-ts/plugins/abweb/public/app.js +1 -1
- package/plugins/abweb/dist/src-ts/plugins/abweb/public/app.ts +1 -1
- package/plugins/chatgpt/dist/src-ts/plugins/desktop-launch.js +10 -4
- package/plugins/doubao/dist/src-ts/plugins/desktop-launch.js +10 -4
- package/plugins/qwenwork/dist/src-ts/plugins/desktop-launch.js +10 -4
- package/plugins/workbuddy/dist/src-ts/plugins/desktop-launch.js +10 -4
- package/plugins/workbuddy/dist/src-ts/plugins/workbuddy/index.js +14 -2
- package/plugins/workbuddy/package.json +1 -1
- package/plugins/workbuddy/plugin.json +1 -1
|
@@ -331,7 +331,7 @@
|
|
|
331
331
|
state.append(detail);
|
|
332
332
|
}
|
|
333
333
|
// 插件未就绪且声明了客户端下载地址时,给出获取桌面客户端的入口
|
|
334
|
-
if (plugin.manifest?.clientDownloadUrl && plugin.
|
|
334
|
+
if (plugin.manifest?.clientDownloadUrl && plugin.error?.includes("未找到") && plugin.error.includes(".exe")) {
|
|
335
335
|
const link = document.createElement("a");
|
|
336
336
|
link.className = "plugin-id";
|
|
337
337
|
link.href = plugin.manifest.clientDownloadUrl;
|
|
@@ -22,8 +22,11 @@ async function findWindowsExecutable(fileName, configured) {
|
|
|
22
22
|
const configuredPath = (0, node_path_1.resolve)(configured);
|
|
23
23
|
if (fileName.toLowerCase() === "doubao.exe") {
|
|
24
24
|
let root = (0, node_path_1.dirname)(configuredPath);
|
|
25
|
-
while (/^app$/i.test((0, node_path_1.basename)(root)) || versionDirectory.test((0, node_path_1.basename)(root)))
|
|
25
|
+
while (/^(?:app|launcher|doubao_update)$/i.test((0, node_path_1.basename)(root)) || versionDirectory.test((0, node_path_1.basename)(root)))
|
|
26
26
|
root = (0, node_path_1.dirname)(root);
|
|
27
|
+
const updated = (0, node_path_1.join)(root, "Doubao_update", fileName);
|
|
28
|
+
if ((0, node_fs_1.existsSync)(updated))
|
|
29
|
+
return updated;
|
|
27
30
|
const latest = await findExecutableInTree(root, fileName, /^/, 3);
|
|
28
31
|
if (latest)
|
|
29
32
|
return latest;
|
|
@@ -64,8 +67,11 @@ async function search(directory, fileName, pattern, depth, insideProduct) {
|
|
|
64
67
|
const entries = await (0, promises_1.readdir)(directory, { withFileTypes: true });
|
|
65
68
|
// 豆包上层文件是启动器,优先查找新版目录或 app 中的实际程序。
|
|
66
69
|
if (insideProduct && depth > 0 && fileName.toLowerCase() === "doubao.exe") {
|
|
67
|
-
const versions = entries.filter(entry => entry.isDirectory() && (versionDirectory.test(entry.name) || /^app$/i.test(entry.name)));
|
|
68
|
-
versions.sort((left, right) =>
|
|
70
|
+
const versions = entries.filter(entry => entry.isDirectory() && (versionDirectory.test(entry.name) || /^(?:app|doubao_update)$/i.test(entry.name)));
|
|
71
|
+
versions.sort((left, right) => {
|
|
72
|
+
const rank = (name) => /^doubao_update$/i.test(name) ? 2 : /^app$/i.test(name) ? 0 : 1;
|
|
73
|
+
return rank(right.name) - rank(left.name) || right.name.replace(/^\D+/, "").localeCompare(left.name.replace(/^\D+/, ""), "en", { numeric: true });
|
|
74
|
+
});
|
|
69
75
|
for (const entry of versions) {
|
|
70
76
|
const found = await search((0, node_path_1.join)(directory, entry.name), fileName, pattern, depth - 1, true);
|
|
71
77
|
if (found)
|
|
@@ -73,7 +79,7 @@ async function search(directory, fileName, pattern, depth, insideProduct) {
|
|
|
73
79
|
}
|
|
74
80
|
}
|
|
75
81
|
for (const entry of entries)
|
|
76
|
-
if (entry.isFile() && insideProduct && entry.name.toLowerCase() === fileName.toLowerCase())
|
|
82
|
+
if (entry.isFile() && insideProduct && entry.name.toLowerCase() === fileName.toLowerCase() && !(fileName.toLowerCase() === "doubao.exe" && /^(?:launcher|doubao)$/i.test((0, node_path_1.basename)(directory))))
|
|
77
83
|
return (0, node_path_1.join)(directory, entry.name);
|
|
78
84
|
if (depth <= 0)
|
|
79
85
|
return undefined;
|
|
@@ -16,7 +16,7 @@ const session_history_1 = require("./session-history");
|
|
|
16
16
|
const desktop_launch_1 = require("../desktop-launch");
|
|
17
17
|
const desktop_launch_2 = require("./desktop-launch");
|
|
18
18
|
exports.workbuddyManifest = {
|
|
19
|
-
id: "workbuddy", version: "1.1.
|
|
19
|
+
id: "workbuddy", version: "1.1.29", displayName: "WorkBuddy", type: "agent",
|
|
20
20
|
entry: "dist/index.js", apiVersion: "1", process: "in-process",
|
|
21
21
|
capabilities: ["chat", "health"], configSchema: "config.schema.json",
|
|
22
22
|
};
|
|
@@ -384,7 +384,19 @@ class WorkbuddyPlugin {
|
|
|
384
384
|
this.activeDesktopConversationId = undefined;
|
|
385
385
|
this.knownSessions.add(sessionId);
|
|
386
386
|
await this.persistKnownSessions();
|
|
387
|
-
|
|
387
|
+
try {
|
|
388
|
+
await this.client.createTask(name);
|
|
389
|
+
}
|
|
390
|
+
catch (error) {
|
|
391
|
+
this.knownSessions.delete(sessionId);
|
|
392
|
+
try {
|
|
393
|
+
await this.persistKnownSessions();
|
|
394
|
+
}
|
|
395
|
+
catch (rollbackError) {
|
|
396
|
+
throw new AggregateError([error, rollbackError], "WorkBuddy 新任务失败且会话记录回滚失败", { cause: error });
|
|
397
|
+
}
|
|
398
|
+
throw error;
|
|
399
|
+
}
|
|
388
400
|
this.desktopSessionValid = true;
|
|
389
401
|
this.expertSession = false;
|
|
390
402
|
this.activeExpert = undefined;
|
|
@@ -63,3 +63,32 @@ class Element {
|
|
|
63
63
|
strict_1.default.equal(saved.aid, undefined, "通过 PATCH 合并配置,不能改写通道关联 AID");
|
|
64
64
|
strict_1.default.equal(node("#cli-config-dialog").open, false);
|
|
65
65
|
});
|
|
66
|
+
(0, node_test_1.default)("客户端下载入口只在客户端可执行文件确实缺失时显示", async () => {
|
|
67
|
+
const script = await (0, promises_1.readFile)("src-ts/plugins/abweb/public/app.js", "utf8");
|
|
68
|
+
const render = async (error) => {
|
|
69
|
+
const nodes = new Map();
|
|
70
|
+
const node = (selector) => { if (!nodes.has(selector))
|
|
71
|
+
nodes.set(selector, new Element()); return nodes.get(selector); };
|
|
72
|
+
(0, node_vm_1.runInNewContext)(script, {
|
|
73
|
+
document: { querySelector: node, createElement: () => new Element(), hidden: false },
|
|
74
|
+
localStorage: { getItem: () => null, removeItem() { } }, window: { addEventListener() { } },
|
|
75
|
+
structuredClone, setInterval() { }, confirm: () => false,
|
|
76
|
+
fetch: async (path) => {
|
|
77
|
+
const values = {
|
|
78
|
+
"/api/health": { plugins: 1 },
|
|
79
|
+
"/api/plugins": { plugins: [{ id: "doubao", displayName: "豆包", type: "agent", version: "1.0.21", status: "failed", error, path: "plugins/doubao", manifest: { clientDownloadUrl: "https://www.doubao.com/chat/" } }] },
|
|
80
|
+
"/api/messages": { messages: [] }, "/api/versions": { plugins: [] },
|
|
81
|
+
"/api/update-policy": { mode: "auto-install" }, "/api/sessions": { sessions: [] },
|
|
82
|
+
"/api/plugin-trust": { config: { providers: {}, plugins: {} }, providers: [], entries: [] },
|
|
83
|
+
"/api/plugins/catalog?q=": { plugins: [] },
|
|
84
|
+
};
|
|
85
|
+
return { ok: true, status: 200, json: async () => values[path] ?? {} };
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
await new Promise(resolve => setImmediate(resolve));
|
|
89
|
+
const state = node("#plugins").children[0].children[3];
|
|
90
|
+
return state.children.some(child => child.textContent === "下载客户端");
|
|
91
|
+
};
|
|
92
|
+
strict_1.default.equal(await render("已启动豆包,但 CDP 9227 未就绪:fetch failed"), false);
|
|
93
|
+
strict_1.default.equal(await render("未找到 Doubao.exe,请配置 executablePath"), true);
|
|
94
|
+
});
|
|
@@ -216,3 +216,17 @@ const desktop_launch_1 = require("../src-ts/plugins/desktop-launch");
|
|
|
216
216
|
await (0, promises_1.rm)(root, { recursive: true, force: true });
|
|
217
217
|
}
|
|
218
218
|
});
|
|
219
|
+
(0, node_test_1.default)("豆包配置指向 launcher 时改用同级实际客户端", async () => {
|
|
220
|
+
const root = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "doubao-launcher-upgrade-"));
|
|
221
|
+
try {
|
|
222
|
+
const launcher = (0, node_path_1.join)(root, "Doubao_update", "launcher", "Doubao.exe");
|
|
223
|
+
const client = (0, node_path_1.join)(root, "Doubao_update", "Doubao.exe");
|
|
224
|
+
await (0, promises_1.mkdir)((0, node_path_1.join)(root, "Doubao_update", "launcher"), { recursive: true });
|
|
225
|
+
await (0, promises_1.writeFile)(launcher, "");
|
|
226
|
+
await (0, promises_1.writeFile)(client, "");
|
|
227
|
+
strict_1.default.equal(await (0, desktop_launch_1.findWindowsExecutable)("Doubao.exe", launcher), client);
|
|
228
|
+
}
|
|
229
|
+
finally {
|
|
230
|
+
await (0, promises_1.rm)(root, { recursive: true, force: true });
|
|
231
|
+
}
|
|
232
|
+
});
|
|
@@ -8,6 +8,11 @@ const promises_1 = require("node:fs/promises");
|
|
|
8
8
|
const node_test_1 = __importDefault(require("node:test"));
|
|
9
9
|
const node_child_process_1 = require("node:child_process");
|
|
10
10
|
const node_util_1 = require("node:util");
|
|
11
|
+
(0, node_test_1.default)("Windows 向导识别自定义安装目录并跳过 DSH 不支持的配置", { skip: process.platform !== "win32" }, async () => {
|
|
12
|
+
const { stdout } = await (0, node_util_1.promisify)(node_child_process_1.execFile)("powershell.exe", ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "tests/windows-installer-detection.test.ps1"]);
|
|
13
|
+
strict_1.default.match(stdout, /自定义安装目录检测验证通过/);
|
|
14
|
+
strict_1.default.match(stdout, /DSH GUI 配置验证通过/);
|
|
15
|
+
});
|
|
11
16
|
(0, node_test_1.default)("Windows 安装向导隔离旧后台并固定 AUN 请求端口", { skip: process.platform !== "win32" }, async () => {
|
|
12
17
|
const { stdout } = await (0, node_util_1.promisify)(node_child_process_1.execFile)("powershell.exe", ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "tests/windows-installer.test.ps1"]);
|
|
13
18
|
strict_1.default.match(stdout, /验证通过/);
|
|
@@ -49,6 +54,15 @@ const node_util_1 = require("node:util");
|
|
|
49
54
|
strict_1.default.doesNotMatch(setup, /mu-agent-bridge@\d+\.\d+\.\d+/);
|
|
50
55
|
strict_1.default.match(setup, /api\/agents\/availability/);
|
|
51
56
|
strict_1.default.match(setup, /function Find-AgentExecutable/);
|
|
57
|
+
strict_1.default.match(setup, /function Update-MabScheduledTask/);
|
|
58
|
+
strict_1.default.match(setup, /function Remove-OldBridgeInstallations/);
|
|
59
|
+
strict_1.default.match(setup, /function Read-SetupJsonFile/);
|
|
60
|
+
strict_1.default.match(setup, /ConvertFrom-Json -InputObject \$json/);
|
|
61
|
+
strict_1.default.doesNotMatch(setup, /Get-Content[^\n]*ConvertFrom-Json/);
|
|
62
|
+
strict_1.default.match(setup, /schtasks\.exe \/End \/TN mab/);
|
|
63
|
+
strict_1.default.doesNotMatch(setup, /Disable-ScheduledTask -TaskName 'mab'/);
|
|
64
|
+
strict_1.default.match(setup, /\.mab[\\\\]paths\.json/);
|
|
65
|
+
strict_1.default.match(setup, /清理旧 mab 目录/);
|
|
52
66
|
strict_1.default.match(setup, /CheckedListBox/);
|
|
53
67
|
strict_1.default.match(setup, /DataGridViewComboBoxColumn/);
|
|
54
68
|
strict_1.default.match(setup, /\[void\]\$grid\.EndEdit\(\)/);
|
|
@@ -890,25 +890,22 @@ const cdp_client_1 = require("../src-ts/plugins/workbuddy/cdp-client");
|
|
|
890
890
|
await plugin.handle({ task: "新会话", sessionId: "session-b" });
|
|
891
891
|
strict_1.default.deepEqual(created, ["", ""]);
|
|
892
892
|
});
|
|
893
|
-
(0, node_test_1.default)("workbuddy
|
|
894
|
-
let shouldFail =
|
|
893
|
+
(0, node_test_1.default)("workbuddy 新建任务失败后同一会话可重试并恢复普通对话", async () => {
|
|
894
|
+
let shouldFail = true;
|
|
895
895
|
let creates = 0;
|
|
896
|
+
const calls = [];
|
|
896
897
|
const plugin = new workbuddy_1.WorkbuddyPlugin({ client: {
|
|
897
898
|
connect: async () => undefined, close() { }, connected: () => true,
|
|
898
899
|
createTask: async () => { creates++; if (shouldFail)
|
|
899
900
|
throw new Error("创建失败"); },
|
|
900
|
-
direct: async (task) => task,
|
|
901
|
+
direct: async (task) => { calls.push(task); return `回复:${task}`; },
|
|
901
902
|
} });
|
|
902
903
|
await plugin.activate({ config: { transport: "cdp" }, logger: { info() { }, warn() { }, error() { } } });
|
|
903
|
-
await plugin.handle({ task: "
|
|
904
|
-
shouldFail = true;
|
|
905
|
-
await strict_1.default.rejects(() => plugin.handle({ task: "b", sessionId: "session-b" }), /创建失败/);
|
|
906
|
-
await strict_1.default.rejects(() => plugin.handle({ task: "继续", sessionId: "session-a" }), /不支持恢复旧 WorkBuddy 会话/);
|
|
904
|
+
await strict_1.default.rejects(() => plugin.handle({ task: "首次消息", sessionId: "session-b" }), /创建失败/);
|
|
907
905
|
shouldFail = false;
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
strict_1.default.
|
|
911
|
-
await strict_1.default.rejects(() => plugin.handle({ task: "旧会话", sessionId: "session-a" }), /不支持恢复旧 WorkBuddy 会话/);
|
|
906
|
+
strict_1.default.equal((await plugin.handle({ task: "重试普通对话", sessionId: "session-b" })).text, "回复:重试普通对话");
|
|
907
|
+
strict_1.default.equal(creates, 2);
|
|
908
|
+
strict_1.default.deepEqual(calls, ["重试普通对话"]);
|
|
912
909
|
});
|
|
913
910
|
(0, node_test_1.default)("workbuddy 执行中拒绝会话控制", async () => {
|
|
914
911
|
let release;
|
|
@@ -1257,15 +1254,15 @@ const cdp_client_1 = require("../src-ts/plugins/workbuddy/cdp-client");
|
|
|
1257
1254
|
await (0, promises_1.rm)(dataDir, { recursive: true, force: true });
|
|
1258
1255
|
}
|
|
1259
1256
|
});
|
|
1260
|
-
(0, node_test_1.default)("workbuddy 新建失败的会话 ID
|
|
1257
|
+
(0, node_test_1.default)("workbuddy 新建失败的会话 ID 重启后仍可重试", async () => {
|
|
1261
1258
|
const dataDir = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "wb-failed-session-"));
|
|
1262
1259
|
let creates = 0;
|
|
1263
1260
|
let fail = true;
|
|
1264
1261
|
const client = {
|
|
1265
1262
|
connect: async () => undefined, close() { }, connected: () => true,
|
|
1266
1263
|
createTask: async () => {
|
|
1267
|
-
const stored =
|
|
1268
|
-
strict_1.default.
|
|
1264
|
+
const stored = await (0, promises_1.readFile)((0, node_path_1.join)(dataDir, "known-sessions.json"), "utf8").then(JSON.parse).catch(() => ({ sessionIds: [] }));
|
|
1265
|
+
strict_1.default.equal(stored.sessionIds.includes("failed-session"), true);
|
|
1269
1266
|
creates++;
|
|
1270
1267
|
if (fail)
|
|
1271
1268
|
throw new Error("创建失败");
|
|
@@ -1281,8 +1278,8 @@ const cdp_client_1 = require("../src-ts/plugins/workbuddy/cdp-client");
|
|
|
1281
1278
|
fail = false;
|
|
1282
1279
|
const second = new workbuddy_1.WorkbuddyPlugin({ client });
|
|
1283
1280
|
await second.activate(context);
|
|
1284
|
-
|
|
1285
|
-
strict_1.default.equal(creates,
|
|
1281
|
+
strict_1.default.equal((await second.handle({ task: "重试", sessionId: "failed-session" })).text, "重试");
|
|
1282
|
+
strict_1.default.equal(creates, 2);
|
|
1286
1283
|
await second.deactivate("stop");
|
|
1287
1284
|
}
|
|
1288
1285
|
finally {
|
package/package.json
CHANGED
|
@@ -331,7 +331,7 @@
|
|
|
331
331
|
state.append(detail);
|
|
332
332
|
}
|
|
333
333
|
// 插件未就绪且声明了客户端下载地址时,给出获取桌面客户端的入口
|
|
334
|
-
if (plugin.manifest?.clientDownloadUrl && plugin.
|
|
334
|
+
if (plugin.manifest?.clientDownloadUrl && plugin.error?.includes("未找到") && plugin.error.includes(".exe")) {
|
|
335
335
|
const link = document.createElement("a");
|
|
336
336
|
link.className = "plugin-id";
|
|
337
337
|
link.href = plugin.manifest.clientDownloadUrl;
|
|
@@ -201,7 +201,7 @@
|
|
|
201
201
|
if (plugin.error) { const detail = document.createElement("small"); detail.className = "error-text plugin-id"; detail.textContent = plugin.error; state.append(detail); }
|
|
202
202
|
if (plugin.dependencyStatus?.length) { const detail = document.createElement("small"); detail.className = "error-text plugin-id"; detail.textContent = `依赖:${plugin.dependencyStatus.join(";")}`; state.append(detail); }
|
|
203
203
|
// 插件未就绪且声明了客户端下载地址时,给出获取桌面客户端的入口
|
|
204
|
-
if (plugin.manifest?.clientDownloadUrl && plugin.
|
|
204
|
+
if (plugin.manifest?.clientDownloadUrl && plugin.error?.includes("未找到") && plugin.error.includes(".exe")) {
|
|
205
205
|
const link = document.createElement("a"); link.className = "plugin-id"; link.href = plugin.manifest.clientDownloadUrl; link.target = "_blank"; link.rel = "noreferrer noopener";
|
|
206
206
|
link.textContent = "下载客户端"; state.append(link);
|
|
207
207
|
}
|
|
@@ -22,8 +22,11 @@ async function findWindowsExecutable(fileName, configured) {
|
|
|
22
22
|
const configuredPath = (0, node_path_1.resolve)(configured);
|
|
23
23
|
if (fileName.toLowerCase() === "doubao.exe") {
|
|
24
24
|
let root = (0, node_path_1.dirname)(configuredPath);
|
|
25
|
-
while (/^app$/i.test((0, node_path_1.basename)(root)) || versionDirectory.test((0, node_path_1.basename)(root)))
|
|
25
|
+
while (/^(?:app|launcher|doubao_update)$/i.test((0, node_path_1.basename)(root)) || versionDirectory.test((0, node_path_1.basename)(root)))
|
|
26
26
|
root = (0, node_path_1.dirname)(root);
|
|
27
|
+
const updated = (0, node_path_1.join)(root, "Doubao_update", fileName);
|
|
28
|
+
if ((0, node_fs_1.existsSync)(updated))
|
|
29
|
+
return updated;
|
|
27
30
|
const latest = await findExecutableInTree(root, fileName, /^/, 3);
|
|
28
31
|
if (latest)
|
|
29
32
|
return latest;
|
|
@@ -64,8 +67,11 @@ async function search(directory, fileName, pattern, depth, insideProduct) {
|
|
|
64
67
|
const entries = await (0, promises_1.readdir)(directory, { withFileTypes: true });
|
|
65
68
|
// 豆包上层文件是启动器,优先查找新版目录或 app 中的实际程序。
|
|
66
69
|
if (insideProduct && depth > 0 && fileName.toLowerCase() === "doubao.exe") {
|
|
67
|
-
const versions = entries.filter(entry => entry.isDirectory() && (versionDirectory.test(entry.name) || /^app$/i.test(entry.name)));
|
|
68
|
-
versions.sort((left, right) =>
|
|
70
|
+
const versions = entries.filter(entry => entry.isDirectory() && (versionDirectory.test(entry.name) || /^(?:app|doubao_update)$/i.test(entry.name)));
|
|
71
|
+
versions.sort((left, right) => {
|
|
72
|
+
const rank = (name) => /^doubao_update$/i.test(name) ? 2 : /^app$/i.test(name) ? 0 : 1;
|
|
73
|
+
return rank(right.name) - rank(left.name) || right.name.replace(/^\D+/, "").localeCompare(left.name.replace(/^\D+/, ""), "en", { numeric: true });
|
|
74
|
+
});
|
|
69
75
|
for (const entry of versions) {
|
|
70
76
|
const found = await search((0, node_path_1.join)(directory, entry.name), fileName, pattern, depth - 1, true);
|
|
71
77
|
if (found)
|
|
@@ -73,7 +79,7 @@ async function search(directory, fileName, pattern, depth, insideProduct) {
|
|
|
73
79
|
}
|
|
74
80
|
}
|
|
75
81
|
for (const entry of entries)
|
|
76
|
-
if (entry.isFile() && insideProduct && entry.name.toLowerCase() === fileName.toLowerCase())
|
|
82
|
+
if (entry.isFile() && insideProduct && entry.name.toLowerCase() === fileName.toLowerCase() && !(fileName.toLowerCase() === "doubao.exe" && /^(?:launcher|doubao)$/i.test((0, node_path_1.basename)(directory))))
|
|
77
83
|
return (0, node_path_1.join)(directory, entry.name);
|
|
78
84
|
if (depth <= 0)
|
|
79
85
|
return undefined;
|
|
@@ -22,8 +22,11 @@ async function findWindowsExecutable(fileName, configured) {
|
|
|
22
22
|
const configuredPath = (0, node_path_1.resolve)(configured);
|
|
23
23
|
if (fileName.toLowerCase() === "doubao.exe") {
|
|
24
24
|
let root = (0, node_path_1.dirname)(configuredPath);
|
|
25
|
-
while (/^app$/i.test((0, node_path_1.basename)(root)) || versionDirectory.test((0, node_path_1.basename)(root)))
|
|
25
|
+
while (/^(?:app|launcher|doubao_update)$/i.test((0, node_path_1.basename)(root)) || versionDirectory.test((0, node_path_1.basename)(root)))
|
|
26
26
|
root = (0, node_path_1.dirname)(root);
|
|
27
|
+
const updated = (0, node_path_1.join)(root, "Doubao_update", fileName);
|
|
28
|
+
if ((0, node_fs_1.existsSync)(updated))
|
|
29
|
+
return updated;
|
|
27
30
|
const latest = await findExecutableInTree(root, fileName, /^/, 3);
|
|
28
31
|
if (latest)
|
|
29
32
|
return latest;
|
|
@@ -64,8 +67,11 @@ async function search(directory, fileName, pattern, depth, insideProduct) {
|
|
|
64
67
|
const entries = await (0, promises_1.readdir)(directory, { withFileTypes: true });
|
|
65
68
|
// 豆包上层文件是启动器,优先查找新版目录或 app 中的实际程序。
|
|
66
69
|
if (insideProduct && depth > 0 && fileName.toLowerCase() === "doubao.exe") {
|
|
67
|
-
const versions = entries.filter(entry => entry.isDirectory() && (versionDirectory.test(entry.name) || /^app$/i.test(entry.name)));
|
|
68
|
-
versions.sort((left, right) =>
|
|
70
|
+
const versions = entries.filter(entry => entry.isDirectory() && (versionDirectory.test(entry.name) || /^(?:app|doubao_update)$/i.test(entry.name)));
|
|
71
|
+
versions.sort((left, right) => {
|
|
72
|
+
const rank = (name) => /^doubao_update$/i.test(name) ? 2 : /^app$/i.test(name) ? 0 : 1;
|
|
73
|
+
return rank(right.name) - rank(left.name) || right.name.replace(/^\D+/, "").localeCompare(left.name.replace(/^\D+/, ""), "en", { numeric: true });
|
|
74
|
+
});
|
|
69
75
|
for (const entry of versions) {
|
|
70
76
|
const found = await search((0, node_path_1.join)(directory, entry.name), fileName, pattern, depth - 1, true);
|
|
71
77
|
if (found)
|
|
@@ -73,7 +79,7 @@ async function search(directory, fileName, pattern, depth, insideProduct) {
|
|
|
73
79
|
}
|
|
74
80
|
}
|
|
75
81
|
for (const entry of entries)
|
|
76
|
-
if (entry.isFile() && insideProduct && entry.name.toLowerCase() === fileName.toLowerCase())
|
|
82
|
+
if (entry.isFile() && insideProduct && entry.name.toLowerCase() === fileName.toLowerCase() && !(fileName.toLowerCase() === "doubao.exe" && /^(?:launcher|doubao)$/i.test((0, node_path_1.basename)(directory))))
|
|
77
83
|
return (0, node_path_1.join)(directory, entry.name);
|
|
78
84
|
if (depth <= 0)
|
|
79
85
|
return undefined;
|
|
@@ -22,8 +22,11 @@ async function findWindowsExecutable(fileName, configured) {
|
|
|
22
22
|
const configuredPath = (0, node_path_1.resolve)(configured);
|
|
23
23
|
if (fileName.toLowerCase() === "doubao.exe") {
|
|
24
24
|
let root = (0, node_path_1.dirname)(configuredPath);
|
|
25
|
-
while (/^app$/i.test((0, node_path_1.basename)(root)) || versionDirectory.test((0, node_path_1.basename)(root)))
|
|
25
|
+
while (/^(?:app|launcher|doubao_update)$/i.test((0, node_path_1.basename)(root)) || versionDirectory.test((0, node_path_1.basename)(root)))
|
|
26
26
|
root = (0, node_path_1.dirname)(root);
|
|
27
|
+
const updated = (0, node_path_1.join)(root, "Doubao_update", fileName);
|
|
28
|
+
if ((0, node_fs_1.existsSync)(updated))
|
|
29
|
+
return updated;
|
|
27
30
|
const latest = await findExecutableInTree(root, fileName, /^/, 3);
|
|
28
31
|
if (latest)
|
|
29
32
|
return latest;
|
|
@@ -64,8 +67,11 @@ async function search(directory, fileName, pattern, depth, insideProduct) {
|
|
|
64
67
|
const entries = await (0, promises_1.readdir)(directory, { withFileTypes: true });
|
|
65
68
|
// 豆包上层文件是启动器,优先查找新版目录或 app 中的实际程序。
|
|
66
69
|
if (insideProduct && depth > 0 && fileName.toLowerCase() === "doubao.exe") {
|
|
67
|
-
const versions = entries.filter(entry => entry.isDirectory() && (versionDirectory.test(entry.name) || /^app$/i.test(entry.name)));
|
|
68
|
-
versions.sort((left, right) =>
|
|
70
|
+
const versions = entries.filter(entry => entry.isDirectory() && (versionDirectory.test(entry.name) || /^(?:app|doubao_update)$/i.test(entry.name)));
|
|
71
|
+
versions.sort((left, right) => {
|
|
72
|
+
const rank = (name) => /^doubao_update$/i.test(name) ? 2 : /^app$/i.test(name) ? 0 : 1;
|
|
73
|
+
return rank(right.name) - rank(left.name) || right.name.replace(/^\D+/, "").localeCompare(left.name.replace(/^\D+/, ""), "en", { numeric: true });
|
|
74
|
+
});
|
|
69
75
|
for (const entry of versions) {
|
|
70
76
|
const found = await search((0, node_path_1.join)(directory, entry.name), fileName, pattern, depth - 1, true);
|
|
71
77
|
if (found)
|
|
@@ -73,7 +79,7 @@ async function search(directory, fileName, pattern, depth, insideProduct) {
|
|
|
73
79
|
}
|
|
74
80
|
}
|
|
75
81
|
for (const entry of entries)
|
|
76
|
-
if (entry.isFile() && insideProduct && entry.name.toLowerCase() === fileName.toLowerCase())
|
|
82
|
+
if (entry.isFile() && insideProduct && entry.name.toLowerCase() === fileName.toLowerCase() && !(fileName.toLowerCase() === "doubao.exe" && /^(?:launcher|doubao)$/i.test((0, node_path_1.basename)(directory))))
|
|
77
83
|
return (0, node_path_1.join)(directory, entry.name);
|
|
78
84
|
if (depth <= 0)
|
|
79
85
|
return undefined;
|
|
@@ -22,8 +22,11 @@ async function findWindowsExecutable(fileName, configured) {
|
|
|
22
22
|
const configuredPath = (0, node_path_1.resolve)(configured);
|
|
23
23
|
if (fileName.toLowerCase() === "doubao.exe") {
|
|
24
24
|
let root = (0, node_path_1.dirname)(configuredPath);
|
|
25
|
-
while (/^app$/i.test((0, node_path_1.basename)(root)) || versionDirectory.test((0, node_path_1.basename)(root)))
|
|
25
|
+
while (/^(?:app|launcher|doubao_update)$/i.test((0, node_path_1.basename)(root)) || versionDirectory.test((0, node_path_1.basename)(root)))
|
|
26
26
|
root = (0, node_path_1.dirname)(root);
|
|
27
|
+
const updated = (0, node_path_1.join)(root, "Doubao_update", fileName);
|
|
28
|
+
if ((0, node_fs_1.existsSync)(updated))
|
|
29
|
+
return updated;
|
|
27
30
|
const latest = await findExecutableInTree(root, fileName, /^/, 3);
|
|
28
31
|
if (latest)
|
|
29
32
|
return latest;
|
|
@@ -64,8 +67,11 @@ async function search(directory, fileName, pattern, depth, insideProduct) {
|
|
|
64
67
|
const entries = await (0, promises_1.readdir)(directory, { withFileTypes: true });
|
|
65
68
|
// 豆包上层文件是启动器,优先查找新版目录或 app 中的实际程序。
|
|
66
69
|
if (insideProduct && depth > 0 && fileName.toLowerCase() === "doubao.exe") {
|
|
67
|
-
const versions = entries.filter(entry => entry.isDirectory() && (versionDirectory.test(entry.name) || /^app$/i.test(entry.name)));
|
|
68
|
-
versions.sort((left, right) =>
|
|
70
|
+
const versions = entries.filter(entry => entry.isDirectory() && (versionDirectory.test(entry.name) || /^(?:app|doubao_update)$/i.test(entry.name)));
|
|
71
|
+
versions.sort((left, right) => {
|
|
72
|
+
const rank = (name) => /^doubao_update$/i.test(name) ? 2 : /^app$/i.test(name) ? 0 : 1;
|
|
73
|
+
return rank(right.name) - rank(left.name) || right.name.replace(/^\D+/, "").localeCompare(left.name.replace(/^\D+/, ""), "en", { numeric: true });
|
|
74
|
+
});
|
|
69
75
|
for (const entry of versions) {
|
|
70
76
|
const found = await search((0, node_path_1.join)(directory, entry.name), fileName, pattern, depth - 1, true);
|
|
71
77
|
if (found)
|
|
@@ -73,7 +79,7 @@ async function search(directory, fileName, pattern, depth, insideProduct) {
|
|
|
73
79
|
}
|
|
74
80
|
}
|
|
75
81
|
for (const entry of entries)
|
|
76
|
-
if (entry.isFile() && insideProduct && entry.name.toLowerCase() === fileName.toLowerCase())
|
|
82
|
+
if (entry.isFile() && insideProduct && entry.name.toLowerCase() === fileName.toLowerCase() && !(fileName.toLowerCase() === "doubao.exe" && /^(?:launcher|doubao)$/i.test((0, node_path_1.basename)(directory))))
|
|
77
83
|
return (0, node_path_1.join)(directory, entry.name);
|
|
78
84
|
if (depth <= 0)
|
|
79
85
|
return undefined;
|
|
@@ -16,7 +16,7 @@ const session_history_1 = require("./session-history");
|
|
|
16
16
|
const desktop_launch_1 = require("../desktop-launch");
|
|
17
17
|
const desktop_launch_2 = require("./desktop-launch");
|
|
18
18
|
exports.workbuddyManifest = {
|
|
19
|
-
id: "workbuddy", version: "1.1.
|
|
19
|
+
id: "workbuddy", version: "1.1.29", displayName: "WorkBuddy", type: "agent",
|
|
20
20
|
entry: "dist/index.js", apiVersion: "1", process: "in-process",
|
|
21
21
|
capabilities: ["chat", "health"], configSchema: "config.schema.json",
|
|
22
22
|
};
|
|
@@ -384,7 +384,19 @@ class WorkbuddyPlugin {
|
|
|
384
384
|
this.activeDesktopConversationId = undefined;
|
|
385
385
|
this.knownSessions.add(sessionId);
|
|
386
386
|
await this.persistKnownSessions();
|
|
387
|
-
|
|
387
|
+
try {
|
|
388
|
+
await this.client.createTask(name);
|
|
389
|
+
}
|
|
390
|
+
catch (error) {
|
|
391
|
+
this.knownSessions.delete(sessionId);
|
|
392
|
+
try {
|
|
393
|
+
await this.persistKnownSessions();
|
|
394
|
+
}
|
|
395
|
+
catch (rollbackError) {
|
|
396
|
+
throw new AggregateError([error, rollbackError], "WorkBuddy 新任务失败且会话记录回滚失败", { cause: error });
|
|
397
|
+
}
|
|
398
|
+
throw error;
|
|
399
|
+
}
|
|
388
400
|
this.desktopSessionValid = true;
|
|
389
401
|
this.expertSession = false;
|
|
390
402
|
this.activeExpert = undefined;
|