mu-agent-bridge 1.0.71 → 1.0.78
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 +17 -10
- package/dist/src-ts/agent.js +35 -0
- package/dist/src-ts/channel-sessions.js +3 -2
- package/dist/src-ts/cli.js +67 -37
- package/dist/src-ts/control-server.js +12 -30
- package/dist/src-ts/core-updater.js +141 -33
- package/dist/src-ts/daemon-process.js +2 -1
- package/dist/src-ts/dsh-agent.js +31 -13
- package/dist/src-ts/http-agent.js +36 -0
- package/dist/src-ts/plugin-catalog.js +11 -2
- package/dist/src-ts/plugin-manager.js +351 -50
- package/dist/src-ts/plugins/abweb/index.js +1 -1
- package/dist/src-ts/plugins/abweb/public/app.js +73 -5
- package/dist/src-ts/plugins/abweb/public/index.html +15 -0
- package/dist/src-ts/plugins/abweb/public/style.css +4 -0
- package/dist/src-ts/plugins/aun/attachments.js +3 -21
- package/dist/src-ts/plugins/aun/index.js +155 -21
- package/dist/src-ts/plugins/aun/messages.js +4 -1
- package/dist/src-ts/plugins/aun/public/app.js +2 -1
- package/dist/src-ts/plugins/aun/public/index.html +1 -1
- package/dist/src-ts/plugins/cdp-draft.js +5 -2
- package/dist/src-ts/plugins/chatgpt/cdp-client.js +26 -12
- package/dist/src-ts/plugins/chatgpt/index.js +80 -19
- package/dist/src-ts/plugins/claude-cli/index.js +19 -2
- package/dist/src-ts/plugins/codex-cli/index.js +19 -2
- package/dist/src-ts/plugins/desktop-launch.js +44 -3
- package/dist/src-ts/plugins/doubao/cdp-client.js +234 -45
- package/dist/src-ts/plugins/doubao/index.js +152 -8
- package/dist/src-ts/plugins/doubao/native-task.js +134 -0
- package/dist/src-ts/plugins/dsh/cdp-client.js +334 -0
- package/dist/src-ts/plugins/dsh/index.js +172 -21
- package/dist/src-ts/plugins/dsh/session-history.js +31 -3
- package/dist/src-ts/plugins/feishu/index.js +1 -1
- package/dist/src-ts/plugins/local-cli/agent.js +74 -9
- package/dist/src-ts/plugins/personal-assistant/claude-cli-model.js +30 -0
- package/dist/src-ts/plugins/personal-assistant/coordination.js +57 -0
- package/dist/src-ts/plugins/personal-assistant/index.js +263 -0
- package/dist/src-ts/plugins/personal-assistant/model-client.js +181 -0
- package/dist/src-ts/plugins/personal-assistant/owner-context.js +56 -0
- package/dist/src-ts/plugins/personal-assistant/remote-ability.js +176 -0
- package/dist/src-ts/plugins/personal-assistant/session-memory.js +124 -0
- package/dist/src-ts/plugins/personal-assistant/tools.js +167 -0
- package/dist/src-ts/plugins/qwenwork/cdp-client.js +90 -18
- package/dist/src-ts/plugins/qwenwork/index.js +139 -24
- package/dist/src-ts/plugins/workbuddy/cdp-client.js +353 -82
- package/dist/src-ts/plugins/workbuddy/index.js +124 -41
- package/dist/src-ts/plugins/zcode/cdp-client.js +500 -0
- package/dist/src-ts/plugins/zcode/index.js +97 -0
- package/dist/src-ts/session-management.js +132 -14
- package/dist/src-ts/version-manager.js +6 -3
- package/dist/tests-ts/abweb-cli.test.js +10 -2
- package/dist/tests-ts/abweb-model-config.test.js +73 -0
- package/dist/tests-ts/agent.test.js +27 -0
- package/dist/tests-ts/aun-attachments.test.js +19 -17
- package/dist/tests-ts/aun-default-owner-page.test.js +2 -1
- package/dist/tests-ts/aun-messages.test.js +20 -0
- package/dist/tests-ts/aun-plugin.test.js +292 -19
- package/dist/tests-ts/bundled-package.test.js +12 -2
- package/dist/tests-ts/cdp-draft-recovery.test.js +182 -3
- package/dist/tests-ts/channel-sessions.test.js +27 -0
- package/dist/tests-ts/chatgpt-plugin.test.js +118 -0
- package/dist/tests-ts/control-server.test.js +56 -0
- package/dist/tests-ts/core-updater.test.js +215 -46
- package/dist/tests-ts/daemon-process.test.js +126 -1
- package/dist/tests-ts/desktop-launch.test.js +73 -0
- package/dist/tests-ts/doubao-native-task.test.js +237 -0
- package/dist/tests-ts/doubao-plugin.test.js +773 -12
- package/dist/tests-ts/dsh-agent.test.js +157 -8
- package/dist/tests-ts/dsh-cdp.test.js +148 -0
- package/dist/tests-ts/dsh-history.test.js +37 -0
- package/dist/tests-ts/feishu-plugin.test.js +1 -1
- package/dist/tests-ts/http-agent.test.js +18 -0
- package/dist/tests-ts/installer-assets.test.js +1 -1
- package/dist/tests-ts/local-cli.test.js +146 -1
- package/dist/tests-ts/model-provider-cancellation.test.js +152 -0
- package/dist/tests-ts/native-session-management.test.js +8 -7
- package/dist/tests-ts/personal-assistant-coordination.test.js +92 -0
- package/dist/tests-ts/personal-assistant-extensions.test.js +35 -0
- package/dist/tests-ts/personal-assistant-memory.test.js +117 -0
- package/dist/tests-ts/personal-assistant-owner-context.test.js +107 -0
- package/dist/tests-ts/personal-assistant-remote-ability.test.js +123 -0
- package/dist/tests-ts/personal-assistant.test.js +663 -0
- package/dist/tests-ts/platform-integration.test.js +183 -1
- package/dist/tests-ts/plugin-catalog.test.js +12 -2
- package/dist/tests-ts/plugin-manager.test.js +356 -4
- package/dist/tests-ts/plugin-upgrade-deadline.test.js +354 -0
- package/dist/tests-ts/publish-packages.test.js +42 -0
- package/dist/tests-ts/qwenwork-plugin.test.js +135 -1
- package/dist/tests-ts/qwenwork-reconnect.test.js +195 -0
- package/dist/tests-ts/qwenwork-sse.test.js +33 -0
- package/dist/tests-ts/session-access-defaults.test.js +112 -0
- package/dist/tests-ts/session-management.test.js +159 -4
- package/dist/tests-ts/version-manager.test.js +40 -0
- package/dist/tests-ts/workbuddy-cdp-recovery.test.js +311 -0
- package/dist/tests-ts/workbuddy-plugin.test.js +499 -4
- package/dist/tests-ts/zcode-cdp.test.js +894 -0
- package/dist/tests-ts/zcode-plugin.test.js +396 -0
- package/package.json +1 -1
- package/plugins/abweb/dist/src-ts/agent.js +35 -0
- package/plugins/abweb/dist/src-ts/plugins/abweb/index.js +1 -1
- package/plugins/abweb/dist/src-ts/plugins/abweb/public/app.js +73 -5
- package/plugins/abweb/dist/src-ts/plugins/abweb/public/app.ts +57 -5
- package/plugins/abweb/dist/src-ts/plugins/abweb/public/index.html +15 -0
- package/plugins/abweb/dist/src-ts/plugins/abweb/public/style.css +4 -0
- package/plugins/abweb/package.json +1 -1
- package/plugins/abweb/plugin.json +1 -1
- package/plugins/aun/config.schema.json +1 -1
- package/plugins/aun/dist/src-ts/agent.js +35 -0
- package/plugins/aun/dist/src-ts/plugins/aun/attachments.js +3 -21
- package/plugins/aun/dist/src-ts/plugins/aun/index.js +155 -21
- package/plugins/aun/dist/src-ts/plugins/aun/messages.js +4 -1
- package/plugins/aun/dist/src-ts/plugins/aun/public/app.js +2 -1
- package/plugins/aun/dist/src-ts/plugins/aun/public/index.html +1 -1
- package/plugins/aun/package.json +1 -1
- package/plugins/aun/plugin.json +1 -1
- package/plugins/chatgpt/dist/src-ts/agent.js +35 -0
- package/plugins/chatgpt/dist/src-ts/plugins/cdp-draft.js +5 -2
- package/plugins/chatgpt/dist/src-ts/plugins/chatgpt/cdp-client.js +26 -12
- package/plugins/chatgpt/dist/src-ts/plugins/chatgpt/index.js +80 -19
- package/plugins/chatgpt/dist/src-ts/plugins/desktop-launch.js +44 -3
- package/plugins/chatgpt/package.json +1 -1
- package/plugins/chatgpt/plugin.json +1 -1
- package/plugins/claude-cli/dist/src-ts/agent.js +35 -0
- package/plugins/claude-cli/dist/src-ts/plugins/claude-cli/index.js +19 -2
- package/plugins/claude-cli/dist/src-ts/plugins/local-cli/agent.js +74 -9
- package/plugins/claude-cli/package.json +1 -1
- package/plugins/claude-cli/plugin.json +3 -2
- package/plugins/codex-cli/dist/src-ts/agent.js +35 -0
- package/plugins/codex-cli/dist/src-ts/plugins/codex-cli/index.js +19 -2
- package/plugins/codex-cli/dist/src-ts/plugins/local-cli/agent.js +74 -9
- package/plugins/codex-cli/package.json +1 -1
- package/plugins/codex-cli/plugin.json +3 -2
- package/plugins/doubao/config.schema.json +2 -1
- package/plugins/doubao/dist/src-ts/agent.js +35 -0
- package/plugins/doubao/dist/src-ts/plugins/desktop-launch.js +44 -3
- package/plugins/doubao/dist/src-ts/plugins/doubao/cdp-client.js +234 -45
- package/plugins/doubao/dist/src-ts/plugins/doubao/index.js +152 -8
- package/plugins/doubao/dist/src-ts/plugins/doubao/native-task.js +134 -0
- package/plugins/doubao/package.json +1 -1
- package/plugins/doubao/plugin.json +3 -2
- package/plugins/dsh/config.schema.json +5 -2
- package/plugins/dsh/dist/src-ts/agent.js +35 -0
- package/plugins/dsh/dist/src-ts/dsh-agent.js +31 -13
- package/plugins/dsh/dist/src-ts/plugins/desktop-launch.js +44 -3
- package/plugins/dsh/dist/src-ts/plugins/dsh/cdp-client.js +334 -0
- package/plugins/dsh/dist/src-ts/plugins/dsh/index.js +172 -21
- package/plugins/dsh/dist/src-ts/plugins/dsh/session-history.js +31 -3
- package/plugins/dsh/package.json +1 -1
- package/plugins/dsh/plugin.json +3 -2
- package/plugins/feishu/dist/src-ts/agent.js +35 -0
- package/plugins/feishu/dist/src-ts/plugins/feishu/index.js +1 -1
- package/plugins/feishu/package.json +1 -1
- package/plugins/feishu/plugin.json +1 -1
- package/plugins/personal-assistant/config.schema.json +23 -0
- package/plugins/personal-assistant/dist/src-ts/agent.js +69 -0
- package/plugins/personal-assistant/dist/src-ts/attachments.js +62 -0
- package/plugins/personal-assistant/dist/src-ts/plugin.js +13 -0
- package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/claude-cli-model.js +30 -0
- package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/coordination.js +57 -0
- package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/index.js +263 -0
- package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/model-client.js +181 -0
- package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/owner-context.js +56 -0
- package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/remote-ability.js +176 -0
- package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/session-memory.js +124 -0
- package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/tools.js +167 -0
- package/plugins/personal-assistant/package.json +39 -0
- package/plugins/personal-assistant/plugin.json +15 -0
- package/plugins/qwenwork/dist/src-ts/agent.js +35 -0
- package/plugins/qwenwork/dist/src-ts/plugins/cdp-draft.js +5 -2
- package/plugins/qwenwork/dist/src-ts/plugins/desktop-launch.js +44 -3
- package/plugins/qwenwork/dist/src-ts/plugins/qwenwork/cdp-client.js +90 -18
- package/plugins/qwenwork/dist/src-ts/plugins/qwenwork/index.js +139 -24
- package/plugins/qwenwork/package.json +1 -1
- package/plugins/qwenwork/plugin.json +3 -2
- package/plugins/workbuddy/config.schema.json +1 -1
- package/plugins/workbuddy/dist/src-ts/agent.js +35 -0
- package/plugins/workbuddy/dist/src-ts/plugins/desktop-launch.js +44 -3
- package/plugins/workbuddy/dist/src-ts/plugins/workbuddy/cdp-client.js +353 -82
- package/plugins/workbuddy/dist/src-ts/plugins/workbuddy/index.js +124 -41
- package/plugins/workbuddy/package.json +1 -1
- package/plugins/workbuddy/plugin.json +3 -2
- package/plugins/zcode/config.schema.json +13 -0
- package/plugins/zcode/dist/src-ts/agent.js +69 -0
- package/plugins/zcode/dist/src-ts/attachments.js +62 -0
- package/plugins/zcode/dist/src-ts/plugin.js +13 -0
- package/plugins/zcode/dist/src-ts/plugins/desktop-launch.js +238 -0
- package/plugins/zcode/dist/src-ts/plugins/workbuddy/cdp-client.js +896 -0
- package/plugins/zcode/dist/src-ts/plugins/workbuddy/cli-client.js +39 -0
- package/plugins/zcode/dist/src-ts/plugins/workbuddy/desktop-launch.js +10 -0
- package/plugins/zcode/dist/src-ts/plugins/workbuddy/index.js +567 -0
- package/plugins/zcode/dist/src-ts/plugins/workbuddy/session-history.js +121 -0
- package/plugins/zcode/dist/src-ts/plugins/zcode/cdp-client.js +500 -0
- package/plugins/zcode/dist/src-ts/plugins/zcode/index.js +97 -0
- package/plugins/zcode/package.json +16 -0
- package/plugins/zcode/plugin.json +11 -0
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.QwenworkPlugin = exports.qwenworkManifest = void 0;
|
|
4
4
|
exports.createQwenworkPlugin = createQwenworkPlugin;
|
|
5
|
+
const promises_1 = require("node:fs/promises");
|
|
6
|
+
const node_path_1 = require("node:path");
|
|
5
7
|
const agent_1 = require("../../agent");
|
|
6
8
|
const openai_adapter_1 = require("./openai-adapter");
|
|
7
9
|
const cdp_client_1 = require("./cdp-client");
|
|
@@ -10,21 +12,29 @@ const desktop_launch_1 = require("../desktop-launch");
|
|
|
10
12
|
const session_history_1 = require("./session-history");
|
|
11
13
|
exports.qwenworkManifest = {
|
|
12
14
|
id: "qwenwork",
|
|
13
|
-
version: "1.0.
|
|
15
|
+
version: "1.0.28",
|
|
14
16
|
displayName: "千问办公",
|
|
15
17
|
entry: "dist/index.js",
|
|
16
18
|
apiVersion: "1",
|
|
17
19
|
process: "in-process",
|
|
18
|
-
capabilities: ["chat", "openai-compatible", "health"],
|
|
20
|
+
capabilities: ["chat", "openai-compatible", "health", "model-provider"],
|
|
19
21
|
configSchema: "config.schema.json",
|
|
20
22
|
defaults: { cdpPort: 9228, httpPort: 17893 },
|
|
21
23
|
};
|
|
22
24
|
function asNumber(value, fallback) {
|
|
23
25
|
return typeof value === "number" && Number.isFinite(value) ? value : fallback;
|
|
24
26
|
}
|
|
27
|
+
function validModelSessionId(value) {
|
|
28
|
+
return typeof value === "string" && Boolean(value.trim()) && value.length <= 512 && !/[\u0000-\u001f]/.test(value);
|
|
29
|
+
}
|
|
25
30
|
/** 千问插件由后台守护,所有通道共用请求队列和恢复流程。 */
|
|
26
31
|
class QwenworkPlugin {
|
|
27
32
|
manifest = exports.qwenworkManifest;
|
|
33
|
+
get modelProvider() {
|
|
34
|
+
if (this.relayTarget || !this.client?.complete || !this.client.createSession || !this.client.activateSession)
|
|
35
|
+
return undefined;
|
|
36
|
+
return { complete: (request) => this.completeModelProvider(request) };
|
|
37
|
+
}
|
|
28
38
|
sessionHistory;
|
|
29
39
|
get attachmentInput() { return Boolean(this.relayTarget || this.client?.attachmentInput); }
|
|
30
40
|
sessionOperations = [];
|
|
@@ -42,6 +52,7 @@ class QwenworkPlugin {
|
|
|
42
52
|
state = "stopped";
|
|
43
53
|
message = "";
|
|
44
54
|
healthIntervalMs;
|
|
55
|
+
restartDesktopHook;
|
|
45
56
|
healthTimer;
|
|
46
57
|
recovery;
|
|
47
58
|
context;
|
|
@@ -53,11 +64,14 @@ class QwenworkPlugin {
|
|
|
53
64
|
busy = false;
|
|
54
65
|
taskCount = 0;
|
|
55
66
|
stopped = true;
|
|
67
|
+
modelSessions = new Map();
|
|
68
|
+
modelSessionsPath;
|
|
56
69
|
constructor(options = {}) {
|
|
57
70
|
this.injectedClient = options.client;
|
|
58
71
|
this.configuredCdpPort = options.cdpPort;
|
|
59
72
|
this.configuredHttpPort = options.httpPort;
|
|
60
73
|
this.healthIntervalMs = options.healthIntervalMs ?? 30_000;
|
|
74
|
+
this.restartDesktopHook = options.restartDesktop;
|
|
61
75
|
}
|
|
62
76
|
async activate(context) {
|
|
63
77
|
if (this.state === "ready")
|
|
@@ -68,6 +82,21 @@ class QwenworkPlugin {
|
|
|
68
82
|
this.lastHeartbeat = undefined;
|
|
69
83
|
this.context = context;
|
|
70
84
|
try {
|
|
85
|
+
this.modelSessions.clear();
|
|
86
|
+
this.modelSessionsPath = typeof context.dataDir === "string" && context.dataDir ? (0, node_path_1.join)(context.dataDir, "model-provider-sessions.json") : undefined;
|
|
87
|
+
try {
|
|
88
|
+
if (!this.modelSessionsPath)
|
|
89
|
+
throw Object.assign(new Error("无持久化目录"), { code: "ENOENT" });
|
|
90
|
+
const saved = JSON.parse(await (0, promises_1.readFile)(this.modelSessionsPath, "utf8"));
|
|
91
|
+
if (!saved || typeof saved !== "object" || Array.isArray(saved) || Object.entries(saved).some(([key, value]) => !validModelSessionId(key) || !validModelSessionId(value)))
|
|
92
|
+
throw new Error("千问个人助理模型会话记录无效");
|
|
93
|
+
for (const [key, value] of Object.entries(saved))
|
|
94
|
+
this.modelSessions.set(key, value);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
if (error.code !== "ENOENT")
|
|
98
|
+
throw error;
|
|
99
|
+
}
|
|
71
100
|
const config = context.config;
|
|
72
101
|
const relayTarget = config.relayTarget;
|
|
73
102
|
if (relayTarget !== undefined && relayTarget !== "dsh")
|
|
@@ -106,6 +135,7 @@ class QwenworkPlugin {
|
|
|
106
135
|
if (!executable)
|
|
107
136
|
throw new Error("未找到 QwenWorkCN.exe,请配置 executablePath");
|
|
108
137
|
context.logger?.info(`正在启动千问办公,等待 CDP ${this.activeCdpPort}`, { executablePath: executable });
|
|
138
|
+
await this.restartDesktopProcess(executable);
|
|
109
139
|
try {
|
|
110
140
|
await (0, desktop_launch_1.launchAndWait)(executable, [`--remote-debugging-port=${this.activeCdpPort}`], () => client.connect(), typeof config.startupTimeoutMs === "number" ? config.startupTimeoutMs : 30_000);
|
|
111
141
|
}
|
|
@@ -140,8 +170,15 @@ class QwenworkPlugin {
|
|
|
140
170
|
throw error;
|
|
141
171
|
}
|
|
142
172
|
}
|
|
143
|
-
async deactivate(
|
|
173
|
+
async deactivate(reason, options) {
|
|
174
|
+
const reloadDesktop = !options?.preserveDesktop && reason === "reload" && Boolean(this.client) && !this.relayTarget;
|
|
144
175
|
await this.cleanup();
|
|
176
|
+
if (reloadDesktop) {
|
|
177
|
+
if (this.restartDesktopHook)
|
|
178
|
+
await this.restartDesktopHook();
|
|
179
|
+
else if (!this.injectedClient && process.platform === "win32")
|
|
180
|
+
await this.restartDesktopProcess();
|
|
181
|
+
}
|
|
145
182
|
this.state = "stopped";
|
|
146
183
|
this.stopped = true;
|
|
147
184
|
}
|
|
@@ -154,8 +191,6 @@ class QwenworkPlugin {
|
|
|
154
191
|
return { status: this.state, ...(this.message ? { message: this.message } : {}), details };
|
|
155
192
|
}
|
|
156
193
|
async handle(request) {
|
|
157
|
-
if (this.recovery)
|
|
158
|
-
await this.recovery;
|
|
159
194
|
if (this.state === "stopped" || (!this.relayTarget && !this.client))
|
|
160
195
|
throw new Error("qwenwork 插件未就绪");
|
|
161
196
|
return this.enqueueTask(() => this.completeRequest(request));
|
|
@@ -170,9 +205,8 @@ class QwenworkPlugin {
|
|
|
170
205
|
throw new Error("千问办公当前忙,无法创建新会话");
|
|
171
206
|
if (!this.client?.createSession)
|
|
172
207
|
throw new Error("千问办公当前传输不支持新建会话");
|
|
173
|
-
if (!this.client.connected())
|
|
174
|
-
throw new Error("千问办公 CDP 未连接");
|
|
175
208
|
return this.enqueueTask(async () => {
|
|
209
|
+
await this.ensureConnected();
|
|
176
210
|
await this.client.createSession(request.name);
|
|
177
211
|
return { text: "千问办公已创建新会话", sessionId };
|
|
178
212
|
});
|
|
@@ -185,8 +219,7 @@ class QwenworkPlugin {
|
|
|
185
219
|
if (!this.client)
|
|
186
220
|
throw new Error("qwenwork 插件未就绪");
|
|
187
221
|
try {
|
|
188
|
-
|
|
189
|
-
throw new Error("千问 CDP 已断开,等待空闲后自动恢复");
|
|
222
|
+
await this.ensureConnected(signal);
|
|
190
223
|
const reply = this.client.complete ? (await this.client.complete(prompt, timeoutMs, signal, undefined, undefined, onMessage)).text : await this.client.direct(prompt, timeoutMs, signal);
|
|
191
224
|
if ((0, cdp_client_1.isQwenApiUnavailableReply)(reply))
|
|
192
225
|
throw new agent_1.AgentOperationError("QWEN_REMOTE_ERROR", "等待千问办公回复", new Error("千问生成接口不可用;桌面未提供具体服务端错误码,CDP 仍连接,未重启或重新提交任务"));
|
|
@@ -196,7 +229,7 @@ class QwenworkPlugin {
|
|
|
196
229
|
return reply;
|
|
197
230
|
}
|
|
198
231
|
catch (error) {
|
|
199
|
-
if (!signal?.aborted) {
|
|
232
|
+
if (!this.stopped && !signal?.aborted) {
|
|
200
233
|
this.message = error instanceof Error ? error.message : String(error);
|
|
201
234
|
this.failures = this.client.connected() ? 0 : 2;
|
|
202
235
|
this.state = "degraded";
|
|
@@ -204,21 +237,23 @@ class QwenworkPlugin {
|
|
|
204
237
|
throw error;
|
|
205
238
|
}
|
|
206
239
|
}
|
|
207
|
-
async completeRequest(request) {
|
|
240
|
+
async completeRequest(request, modelRequest = false) {
|
|
208
241
|
if (this.relayTarget) {
|
|
209
242
|
return this.callPlugin(this.relayTarget, request);
|
|
210
243
|
}
|
|
211
244
|
if (!this.client)
|
|
212
245
|
throw new Error("qwenwork 插件未就绪");
|
|
213
246
|
try {
|
|
214
|
-
if (!this.client.connected())
|
|
215
|
-
throw new Error("千问 CDP
|
|
247
|
+
if (modelRequest && !this.client.connected())
|
|
248
|
+
throw new Error("千问 CDP 已断开,模型请求不会启动或重启桌面");
|
|
249
|
+
if (!modelRequest)
|
|
250
|
+
await this.ensureConnected(request.signal);
|
|
216
251
|
if (request.attachments?.length && (!this.client.attachmentInput || !this.client.complete))
|
|
217
252
|
throw new Error("千问当前客户端不支持附件输入");
|
|
218
253
|
const timeoutMs = request.timeoutMs ?? asNumber(this.context?.config.timeoutMs, 240_000);
|
|
219
254
|
const response = this.client.complete
|
|
220
|
-
? await this.client.complete(request.task, timeoutMs,
|
|
221
|
-
: { text: await this.complete(request.task, timeoutMs) };
|
|
255
|
+
? await this.client.complete(request.task, timeoutMs, request.signal, undefined, request.attachments, request.onMessage, modelRequest)
|
|
256
|
+
: { text: await this.complete(request.task, timeoutMs, request.signal) };
|
|
222
257
|
if ((0, cdp_client_1.isQwenApiUnavailableReply)(response.text))
|
|
223
258
|
throw new agent_1.AgentOperationError("QWEN_REMOTE_ERROR", "等待千问办公回复", new Error("千问生成接口不可用;桌面未提供具体服务端错误码,CDP 仍连接,未重启或重新提交任务"));
|
|
224
259
|
this.failures = 0;
|
|
@@ -227,12 +262,66 @@ class QwenworkPlugin {
|
|
|
227
262
|
return response;
|
|
228
263
|
}
|
|
229
264
|
catch (error) {
|
|
230
|
-
this.
|
|
231
|
-
|
|
232
|
-
|
|
265
|
+
if (!this.stopped && !request.signal?.aborted && !modelRequest) {
|
|
266
|
+
this.message = error instanceof Error ? error.message : String(error);
|
|
267
|
+
this.failures = this.client.connected() ? 0 : 2;
|
|
268
|
+
this.state = "degraded";
|
|
269
|
+
}
|
|
233
270
|
throw error;
|
|
234
271
|
}
|
|
235
272
|
}
|
|
273
|
+
async completeModelProvider(request) {
|
|
274
|
+
let stage = "千问办公模型排队(queue)";
|
|
275
|
+
try {
|
|
276
|
+
request.signal.throwIfAborted();
|
|
277
|
+
const run = this.enqueueTask(async () => {
|
|
278
|
+
request.signal.throwIfAborted();
|
|
279
|
+
stage = "连接千问办公模型(connect)";
|
|
280
|
+
const client = this.client;
|
|
281
|
+
if (this.state !== "ready" || !client?.connected() || !client.createSession || !client.activateSession || !client.complete)
|
|
282
|
+
throw new Error("千问办公未连接或不支持隔离模型会话,模型请求不会启动或重启桌面");
|
|
283
|
+
const previousSessionId = await client.currentSessionId?.();
|
|
284
|
+
try {
|
|
285
|
+
stage = "准备千问办公模型会话(submit)";
|
|
286
|
+
const desktopSessionId = this.modelSessions.get(request.sessionId);
|
|
287
|
+
if (desktopSessionId)
|
|
288
|
+
await client.activateSession(desktopSessionId);
|
|
289
|
+
else
|
|
290
|
+
await client.createSession(undefined, true, true);
|
|
291
|
+
request.signal.throwIfAborted();
|
|
292
|
+
stage = "等待千问办公模型生成(generate)";
|
|
293
|
+
const response = await this.completeRequest({ task: request.prompt, sessionId: request.sessionId, timeoutMs: request.timeoutMs, signal: request.signal }, true);
|
|
294
|
+
const actualSessionId = response.sessionId ?? await client.currentSessionId?.();
|
|
295
|
+
if (!validModelSessionId(actualSessionId))
|
|
296
|
+
throw new Error("千问未返回可恢复的个人助理模型会话标识");
|
|
297
|
+
if (actualSessionId !== desktopSessionId) {
|
|
298
|
+
this.modelSessions.set(request.sessionId, actualSessionId);
|
|
299
|
+
const path = this.modelSessionsPath;
|
|
300
|
+
if (path) {
|
|
301
|
+
await (0, promises_1.mkdir)(this.context.dataDir ?? ".", { recursive: true });
|
|
302
|
+
await (0, promises_1.writeFile)(`${path}.tmp`, JSON.stringify(Object.fromEntries(this.modelSessions)), { mode: 0o600 });
|
|
303
|
+
await (0, promises_1.rename)(`${path}.tmp`, path);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return { text: response.text };
|
|
307
|
+
}
|
|
308
|
+
finally {
|
|
309
|
+
if (client.connected()) {
|
|
310
|
+
if (previousSessionId)
|
|
311
|
+
await client.activateSession(previousSessionId);
|
|
312
|
+
else
|
|
313
|
+
await client.createSession(undefined, false, true);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
return await (0, agent_1.abortable)(run, request.signal);
|
|
318
|
+
}
|
|
319
|
+
catch (error) {
|
|
320
|
+
if (error instanceof agent_1.AgentOperationError)
|
|
321
|
+
throw error;
|
|
322
|
+
throw new agent_1.AgentOperationError("QWEN_MODEL_FAILED", stage, error);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
236
325
|
registerRoutes(http) {
|
|
237
326
|
if (!this.adapter)
|
|
238
327
|
return;
|
|
@@ -262,6 +351,14 @@ class QwenworkPlugin {
|
|
|
262
351
|
this.callPlugin = undefined;
|
|
263
352
|
this.pluginStatus = undefined;
|
|
264
353
|
}
|
|
354
|
+
async restartDesktopProcess(configuredExecutable) {
|
|
355
|
+
const config = this.context?.config;
|
|
356
|
+
const executable = configuredExecutable ?? await (0, desktop_launch_1.findWindowsExecutable)("QwenWorkCN.exe", typeof config?.executablePath === "string" ? config.executablePath : undefined);
|
|
357
|
+
if (!executable)
|
|
358
|
+
throw new Error("未找到 QwenWorkCN.exe,请配置 executablePath");
|
|
359
|
+
const processIds = await (0, desktop_launch_1.terminateWindowsDesktop)(executable);
|
|
360
|
+
this.context?.logger?.info("千问办公重载前已清理旧进程,将以 CDP 模式启动", { processIds, executable });
|
|
361
|
+
}
|
|
265
362
|
startHealthWatch() {
|
|
266
363
|
if (this.relayTarget || !this.client || this.healthTimer)
|
|
267
364
|
return;
|
|
@@ -284,9 +381,26 @@ class QwenworkPlugin {
|
|
|
284
381
|
});
|
|
285
382
|
}
|
|
286
383
|
async recover() {
|
|
384
|
+
if (this.stopped || this.busy)
|
|
385
|
+
return;
|
|
386
|
+
try {
|
|
387
|
+
await this.reconnect();
|
|
388
|
+
}
|
|
389
|
+
catch { /* 失败已记录,留待下次空闲检查。 */ }
|
|
390
|
+
}
|
|
391
|
+
async ensureConnected(signal) {
|
|
392
|
+
signal?.throwIfAborted();
|
|
393
|
+
if (this.stopped || !this.client)
|
|
394
|
+
throw new Error("qwenwork 插件未就绪");
|
|
395
|
+
await this.reconnect();
|
|
396
|
+
signal?.throwIfAborted();
|
|
397
|
+
if (this.stopped)
|
|
398
|
+
throw new Error("qwenwork 插件未就绪");
|
|
399
|
+
}
|
|
400
|
+
async reconnect() {
|
|
287
401
|
if (this.recovery)
|
|
288
402
|
return this.recovery;
|
|
289
|
-
if (this.stopped
|
|
403
|
+
if (this.stopped)
|
|
290
404
|
return;
|
|
291
405
|
const client = this.client;
|
|
292
406
|
if (!client || client.connected())
|
|
@@ -307,11 +421,12 @@ class QwenworkPlugin {
|
|
|
307
421
|
this.restarts += 1;
|
|
308
422
|
this.context?.logger?.info("千问 CDP 自动重连成功", { restarts: this.restarts });
|
|
309
423
|
})().catch((error) => {
|
|
310
|
-
if (this.stopped)
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
424
|
+
if (!this.stopped) {
|
|
425
|
+
this.state = "failed";
|
|
426
|
+
this.message = error instanceof Error ? error.message : String(error);
|
|
427
|
+
this.context?.logger?.error(`千问 CDP 重连失败,桌面未重启,下次空闲检查重试:${this.message}`);
|
|
428
|
+
}
|
|
429
|
+
throw error;
|
|
315
430
|
}).finally(() => { this.recovery = undefined; });
|
|
316
431
|
return this.recovery;
|
|
317
432
|
}
|