mu-agent-bridge 1.0.55 → 1.0.56
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/workbuddy/cdp-client.js +13 -1
- package/dist/src-ts/plugins/workbuddy/index.js +6 -6
- package/dist/tests-ts/workbuddy-plugin.test.js +19 -0
- package/package.json +1 -1
- package/plugins/workbuddy/dist/src-ts/plugins/workbuddy/cdp-client.js +13 -1
- package/plugins/workbuddy/dist/src-ts/plugins/workbuddy/index.js +6 -6
- package/plugins/workbuddy/package.json +1 -1
- package/plugins/workbuddy/plugin.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.WorkbuddyCdpClient = exports.assistantSelector = exports.editorSelector = void 0;
|
|
3
|
+
exports.WorkbuddyCdpClient = exports.chineseLocaleScript = exports.assistantSelector = exports.editorSelector = void 0;
|
|
4
4
|
const node_crypto_1 = require("node:crypto");
|
|
5
5
|
const attachments_1 = require("../../attachments");
|
|
6
6
|
function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); }
|
|
@@ -17,6 +17,16 @@ function interactionChoice(value, options) {
|
|
|
17
17
|
}
|
|
18
18
|
exports.editorSelector = '[data-slate-editor][contenteditable="true"]';
|
|
19
19
|
exports.assistantSelector = '.cr-agent[data-message-id] [data-assistant-content]';
|
|
20
|
+
exports.chineseLocaleScript = `(() => {
|
|
21
|
+
const key = 'CODEBUDDY_IDE_STORAGE_LANG';
|
|
22
|
+
const legacyKey = 'workbuddy-language';
|
|
23
|
+
const locale = 'zh-CN';
|
|
24
|
+
const changed = localStorage.getItem(key) !== locale || localStorage.getItem(legacyKey) !== locale || /[?&]locale=en-US(?:&|$)/i.test(location.search);
|
|
25
|
+
localStorage.setItem(key, locale);
|
|
26
|
+
localStorage.setItem(legacyKey, locale);
|
|
27
|
+
if (changed) setTimeout(() => location.reload(), 0);
|
|
28
|
+
return changed;
|
|
29
|
+
})()`;
|
|
20
30
|
class WorkbuddyCdpClient {
|
|
21
31
|
attachmentInput = true;
|
|
22
32
|
socket;
|
|
@@ -95,6 +105,8 @@ class WorkbuddyCdpClient {
|
|
|
95
105
|
this.socket.onmessage = (event) => this.onMessage(String(event.data));
|
|
96
106
|
try {
|
|
97
107
|
await new Promise((resolve, reject) => { const socket = this.socket; socket.onopen = () => resolve(); socket.onerror = () => reject(new Error("WorkBuddy CDP WebSocket 连接失败")); });
|
|
108
|
+
if (await this.evaluate(exports.chineseLocaleScript))
|
|
109
|
+
await this.waitFor("!/[?&]locale=en-US(?:&|$)/i.test(location.search)", "WorkBuddy 中文界面切换超时");
|
|
98
110
|
}
|
|
99
111
|
catch (error) {
|
|
100
112
|
this.close();
|
|
@@ -15,7 +15,7 @@ const session_history_1 = require("./session-history");
|
|
|
15
15
|
const desktop_launch_1 = require("../desktop-launch");
|
|
16
16
|
const desktop_launch_2 = require("./desktop-launch");
|
|
17
17
|
exports.workbuddyManifest = {
|
|
18
|
-
id: "workbuddy", version: "1.1.
|
|
18
|
+
id: "workbuddy", version: "1.1.18", displayName: "WorkBuddy", type: "agent",
|
|
19
19
|
entry: "dist/index.js", apiVersion: "1", process: "in-process",
|
|
20
20
|
capabilities: ["chat", "health"], configSchema: "config.schema.json",
|
|
21
21
|
};
|
|
@@ -265,22 +265,22 @@ class WorkbuddyPlugin {
|
|
|
265
265
|
const timeout = request.timeoutMs ?? this.timeoutMs;
|
|
266
266
|
const expert = extractExpertQuery(request.task);
|
|
267
267
|
const usesCli = Boolean(this.cliPath && this.transport !== "cdp" && !expert);
|
|
268
|
+
// 内部恢复消息可能没有 sessionId,沿用当前桌面会话,避免恢复任务被会话保护拒绝。
|
|
269
|
+
const sessionId = request.sessionId ?? this.activeSessionId;
|
|
268
270
|
const hasAttachments = Array.isArray(request.attachments) && request.attachments.length > 0;
|
|
269
271
|
if (hasAttachments && !this.attachmentInput)
|
|
270
272
|
throw new Error("WorkBuddy 当前传输不支持附件输入");
|
|
271
273
|
if (!usesCli && !this.client?.connected())
|
|
272
274
|
await this.reconnect?.();
|
|
273
275
|
const pendingInteractionSessionId = this.client?.pendingInteractionSessionId?.();
|
|
274
|
-
if (!usesCli && pendingInteractionSessionId && pendingInteractionSessionId !==
|
|
276
|
+
if (!usesCli && pendingInteractionSessionId && pendingInteractionSessionId !== sessionId)
|
|
275
277
|
throw new Error("WorkBuddy 正在等待另一个会话的选择");
|
|
276
278
|
if (usesCli && request.sessionId)
|
|
277
279
|
throw new Error("CodeBuddy CLI 会话隔离未验证,不能处理带 sessionId 的请求");
|
|
278
|
-
if (!usesCli && !
|
|
279
|
-
throw new Error("WorkBuddy 已绑定逻辑会话,请使用相同 sessionId 或先执行 /new");
|
|
280
|
-
if (!usesCli && !request.sessionId && !this.desktopSessionValid)
|
|
280
|
+
if (!usesCli && !sessionId && !this.desktopSessionValid)
|
|
281
281
|
throw new Error("WorkBuddy 桌面任务状态未知,请先创建新会话");
|
|
282
282
|
if (!usesCli)
|
|
283
|
-
await this.ensureSession(
|
|
283
|
+
await this.ensureSession(sessionId);
|
|
284
284
|
if (expert) {
|
|
285
285
|
if (!this.client?.connected())
|
|
286
286
|
throw new Error(`专家请求需要已连接的 WorkBuddy 桌面端:${expert}`);
|
|
@@ -51,6 +51,12 @@ const node_test_1 = __importDefault(require("node:test"));
|
|
|
51
51
|
const node_vm_1 = require("node:vm");
|
|
52
52
|
const workbuddy_1 = require("../src-ts/plugins/workbuddy");
|
|
53
53
|
const cdp_client_1 = require("../src-ts/plugins/workbuddy/cdp-client");
|
|
54
|
+
(0, node_test_1.default)("WorkBuddy CDP 启动后固定中文语言偏好", () => {
|
|
55
|
+
strict_1.default.match(cdp_client_1.chineseLocaleScript, /CODEBUDDY_IDE_STORAGE_LANG/);
|
|
56
|
+
strict_1.default.match(cdp_client_1.chineseLocaleScript, /workbuddy-language/);
|
|
57
|
+
strict_1.default.match(cdp_client_1.chineseLocaleScript, /zh-CN/);
|
|
58
|
+
strict_1.default.match(cdp_client_1.chineseLocaleScript, /location\.reload/);
|
|
59
|
+
});
|
|
54
60
|
(0, node_test_1.default)("workbuddy CDP 拒绝连接其他应用的调试页面", async () => {
|
|
55
61
|
const client = new cdp_client_1.WorkbuddyCdpClient({ fetchImpl: async () => new Response(JSON.stringify([{ type: "page", title: "Other App", webSocketDebuggerUrl: "ws://127.0.0.1:9229/devtools/page/1" }])) });
|
|
56
62
|
await strict_1.default.rejects(() => client.connect(), /未找到 WorkBuddy 页面 target/);
|
|
@@ -203,6 +209,19 @@ const cdp_client_1 = require("../src-ts/plugins/workbuddy/cdp-client");
|
|
|
203
209
|
strict_1.default.equal((await plugin.health()).status, "ready");
|
|
204
210
|
await plugin.deactivate("stop");
|
|
205
211
|
});
|
|
212
|
+
(0, node_test_1.default)("workbuddy 内部恢复消息无 sessionId 时沿用当前桌面会话", async () => {
|
|
213
|
+
const calls = [];
|
|
214
|
+
const client = {
|
|
215
|
+
connect: async () => undefined, close() { }, connected: () => true,
|
|
216
|
+
direct: async (task) => { calls.push(task); return "恢复成功"; },
|
|
217
|
+
};
|
|
218
|
+
const plugin = new workbuddy_1.WorkbuddyPlugin({ client });
|
|
219
|
+
await plugin.activate({ config: { transport: "cdp" }, logger: { info() { }, warn() { }, error() { } } });
|
|
220
|
+
plugin.activeSessionId = "session-active";
|
|
221
|
+
await strict_1.default.doesNotReject(() => plugin.handle({ task: "继续当前任务" }));
|
|
222
|
+
strict_1.default.deepEqual(calls, ["继续当前任务"]);
|
|
223
|
+
await plugin.deactivate("stop");
|
|
224
|
+
});
|
|
206
225
|
(0, node_test_1.default)("workbuddy 结构化客户端接收附件并保留附件响应和逻辑会话", async () => {
|
|
207
226
|
const attachment = { kind: "file", data: new Uint8Array([1, 2]), filename: "输入.txt", contentType: "text/plain" };
|
|
208
227
|
const output = { kind: "file", data: new Uint8Array([3]), filename: "输出.txt", contentType: "text/plain" };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.WorkbuddyCdpClient = exports.assistantSelector = exports.editorSelector = void 0;
|
|
3
|
+
exports.WorkbuddyCdpClient = exports.chineseLocaleScript = exports.assistantSelector = exports.editorSelector = void 0;
|
|
4
4
|
const node_crypto_1 = require("node:crypto");
|
|
5
5
|
const attachments_1 = require("../../attachments");
|
|
6
6
|
function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); }
|
|
@@ -17,6 +17,16 @@ function interactionChoice(value, options) {
|
|
|
17
17
|
}
|
|
18
18
|
exports.editorSelector = '[data-slate-editor][contenteditable="true"]';
|
|
19
19
|
exports.assistantSelector = '.cr-agent[data-message-id] [data-assistant-content]';
|
|
20
|
+
exports.chineseLocaleScript = `(() => {
|
|
21
|
+
const key = 'CODEBUDDY_IDE_STORAGE_LANG';
|
|
22
|
+
const legacyKey = 'workbuddy-language';
|
|
23
|
+
const locale = 'zh-CN';
|
|
24
|
+
const changed = localStorage.getItem(key) !== locale || localStorage.getItem(legacyKey) !== locale || /[?&]locale=en-US(?:&|$)/i.test(location.search);
|
|
25
|
+
localStorage.setItem(key, locale);
|
|
26
|
+
localStorage.setItem(legacyKey, locale);
|
|
27
|
+
if (changed) setTimeout(() => location.reload(), 0);
|
|
28
|
+
return changed;
|
|
29
|
+
})()`;
|
|
20
30
|
class WorkbuddyCdpClient {
|
|
21
31
|
attachmentInput = true;
|
|
22
32
|
socket;
|
|
@@ -95,6 +105,8 @@ class WorkbuddyCdpClient {
|
|
|
95
105
|
this.socket.onmessage = (event) => this.onMessage(String(event.data));
|
|
96
106
|
try {
|
|
97
107
|
await new Promise((resolve, reject) => { const socket = this.socket; socket.onopen = () => resolve(); socket.onerror = () => reject(new Error("WorkBuddy CDP WebSocket 连接失败")); });
|
|
108
|
+
if (await this.evaluate(exports.chineseLocaleScript))
|
|
109
|
+
await this.waitFor("!/[?&]locale=en-US(?:&|$)/i.test(location.search)", "WorkBuddy 中文界面切换超时");
|
|
98
110
|
}
|
|
99
111
|
catch (error) {
|
|
100
112
|
this.close();
|
|
@@ -15,7 +15,7 @@ const session_history_1 = require("./session-history");
|
|
|
15
15
|
const desktop_launch_1 = require("../desktop-launch");
|
|
16
16
|
const desktop_launch_2 = require("./desktop-launch");
|
|
17
17
|
exports.workbuddyManifest = {
|
|
18
|
-
id: "workbuddy", version: "1.1.
|
|
18
|
+
id: "workbuddy", version: "1.1.18", displayName: "WorkBuddy", type: "agent",
|
|
19
19
|
entry: "dist/index.js", apiVersion: "1", process: "in-process",
|
|
20
20
|
capabilities: ["chat", "health"], configSchema: "config.schema.json",
|
|
21
21
|
};
|
|
@@ -265,22 +265,22 @@ class WorkbuddyPlugin {
|
|
|
265
265
|
const timeout = request.timeoutMs ?? this.timeoutMs;
|
|
266
266
|
const expert = extractExpertQuery(request.task);
|
|
267
267
|
const usesCli = Boolean(this.cliPath && this.transport !== "cdp" && !expert);
|
|
268
|
+
// 内部恢复消息可能没有 sessionId,沿用当前桌面会话,避免恢复任务被会话保护拒绝。
|
|
269
|
+
const sessionId = request.sessionId ?? this.activeSessionId;
|
|
268
270
|
const hasAttachments = Array.isArray(request.attachments) && request.attachments.length > 0;
|
|
269
271
|
if (hasAttachments && !this.attachmentInput)
|
|
270
272
|
throw new Error("WorkBuddy 当前传输不支持附件输入");
|
|
271
273
|
if (!usesCli && !this.client?.connected())
|
|
272
274
|
await this.reconnect?.();
|
|
273
275
|
const pendingInteractionSessionId = this.client?.pendingInteractionSessionId?.();
|
|
274
|
-
if (!usesCli && pendingInteractionSessionId && pendingInteractionSessionId !==
|
|
276
|
+
if (!usesCli && pendingInteractionSessionId && pendingInteractionSessionId !== sessionId)
|
|
275
277
|
throw new Error("WorkBuddy 正在等待另一个会话的选择");
|
|
276
278
|
if (usesCli && request.sessionId)
|
|
277
279
|
throw new Error("CodeBuddy CLI 会话隔离未验证,不能处理带 sessionId 的请求");
|
|
278
|
-
if (!usesCli && !
|
|
279
|
-
throw new Error("WorkBuddy 已绑定逻辑会话,请使用相同 sessionId 或先执行 /new");
|
|
280
|
-
if (!usesCli && !request.sessionId && !this.desktopSessionValid)
|
|
280
|
+
if (!usesCli && !sessionId && !this.desktopSessionValid)
|
|
281
281
|
throw new Error("WorkBuddy 桌面任务状态未知,请先创建新会话");
|
|
282
282
|
if (!usesCli)
|
|
283
|
-
await this.ensureSession(
|
|
283
|
+
await this.ensureSession(sessionId);
|
|
284
284
|
if (expert) {
|
|
285
285
|
if (!this.client?.connected())
|
|
286
286
|
throw new Error(`专家请求需要已连接的 WorkBuddy 桌面端:${expert}`);
|