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.
Files changed (195) hide show
  1. package/README.md +17 -10
  2. package/dist/src-ts/agent.js +35 -0
  3. package/dist/src-ts/channel-sessions.js +3 -2
  4. package/dist/src-ts/cli.js +67 -37
  5. package/dist/src-ts/control-server.js +12 -30
  6. package/dist/src-ts/core-updater.js +141 -33
  7. package/dist/src-ts/daemon-process.js +2 -1
  8. package/dist/src-ts/dsh-agent.js +31 -13
  9. package/dist/src-ts/http-agent.js +36 -0
  10. package/dist/src-ts/plugin-catalog.js +11 -2
  11. package/dist/src-ts/plugin-manager.js +351 -50
  12. package/dist/src-ts/plugins/abweb/index.js +1 -1
  13. package/dist/src-ts/plugins/abweb/public/app.js +73 -5
  14. package/dist/src-ts/plugins/abweb/public/index.html +15 -0
  15. package/dist/src-ts/plugins/abweb/public/style.css +4 -0
  16. package/dist/src-ts/plugins/aun/attachments.js +3 -21
  17. package/dist/src-ts/plugins/aun/index.js +155 -21
  18. package/dist/src-ts/plugins/aun/messages.js +4 -1
  19. package/dist/src-ts/plugins/aun/public/app.js +2 -1
  20. package/dist/src-ts/plugins/aun/public/index.html +1 -1
  21. package/dist/src-ts/plugins/cdp-draft.js +5 -2
  22. package/dist/src-ts/plugins/chatgpt/cdp-client.js +26 -12
  23. package/dist/src-ts/plugins/chatgpt/index.js +80 -19
  24. package/dist/src-ts/plugins/claude-cli/index.js +19 -2
  25. package/dist/src-ts/plugins/codex-cli/index.js +19 -2
  26. package/dist/src-ts/plugins/desktop-launch.js +44 -3
  27. package/dist/src-ts/plugins/doubao/cdp-client.js +234 -45
  28. package/dist/src-ts/plugins/doubao/index.js +152 -8
  29. package/dist/src-ts/plugins/doubao/native-task.js +134 -0
  30. package/dist/src-ts/plugins/dsh/cdp-client.js +334 -0
  31. package/dist/src-ts/plugins/dsh/index.js +172 -21
  32. package/dist/src-ts/plugins/dsh/session-history.js +31 -3
  33. package/dist/src-ts/plugins/feishu/index.js +1 -1
  34. package/dist/src-ts/plugins/local-cli/agent.js +74 -9
  35. package/dist/src-ts/plugins/personal-assistant/claude-cli-model.js +30 -0
  36. package/dist/src-ts/plugins/personal-assistant/coordination.js +57 -0
  37. package/dist/src-ts/plugins/personal-assistant/index.js +263 -0
  38. package/dist/src-ts/plugins/personal-assistant/model-client.js +181 -0
  39. package/dist/src-ts/plugins/personal-assistant/owner-context.js +56 -0
  40. package/dist/src-ts/plugins/personal-assistant/remote-ability.js +176 -0
  41. package/dist/src-ts/plugins/personal-assistant/session-memory.js +124 -0
  42. package/dist/src-ts/plugins/personal-assistant/tools.js +167 -0
  43. package/dist/src-ts/plugins/qwenwork/cdp-client.js +90 -18
  44. package/dist/src-ts/plugins/qwenwork/index.js +139 -24
  45. package/dist/src-ts/plugins/workbuddy/cdp-client.js +353 -82
  46. package/dist/src-ts/plugins/workbuddy/index.js +124 -41
  47. package/dist/src-ts/plugins/zcode/cdp-client.js +500 -0
  48. package/dist/src-ts/plugins/zcode/index.js +97 -0
  49. package/dist/src-ts/session-management.js +132 -14
  50. package/dist/src-ts/version-manager.js +6 -3
  51. package/dist/tests-ts/abweb-cli.test.js +10 -2
  52. package/dist/tests-ts/abweb-model-config.test.js +73 -0
  53. package/dist/tests-ts/agent.test.js +27 -0
  54. package/dist/tests-ts/aun-attachments.test.js +19 -17
  55. package/dist/tests-ts/aun-default-owner-page.test.js +2 -1
  56. package/dist/tests-ts/aun-messages.test.js +20 -0
  57. package/dist/tests-ts/aun-plugin.test.js +292 -19
  58. package/dist/tests-ts/bundled-package.test.js +12 -2
  59. package/dist/tests-ts/cdp-draft-recovery.test.js +182 -3
  60. package/dist/tests-ts/channel-sessions.test.js +27 -0
  61. package/dist/tests-ts/chatgpt-plugin.test.js +118 -0
  62. package/dist/tests-ts/control-server.test.js +56 -0
  63. package/dist/tests-ts/core-updater.test.js +215 -46
  64. package/dist/tests-ts/daemon-process.test.js +126 -1
  65. package/dist/tests-ts/desktop-launch.test.js +73 -0
  66. package/dist/tests-ts/doubao-native-task.test.js +237 -0
  67. package/dist/tests-ts/doubao-plugin.test.js +773 -12
  68. package/dist/tests-ts/dsh-agent.test.js +157 -8
  69. package/dist/tests-ts/dsh-cdp.test.js +148 -0
  70. package/dist/tests-ts/dsh-history.test.js +37 -0
  71. package/dist/tests-ts/feishu-plugin.test.js +1 -1
  72. package/dist/tests-ts/http-agent.test.js +18 -0
  73. package/dist/tests-ts/installer-assets.test.js +1 -1
  74. package/dist/tests-ts/local-cli.test.js +146 -1
  75. package/dist/tests-ts/model-provider-cancellation.test.js +152 -0
  76. package/dist/tests-ts/native-session-management.test.js +8 -7
  77. package/dist/tests-ts/personal-assistant-coordination.test.js +92 -0
  78. package/dist/tests-ts/personal-assistant-extensions.test.js +35 -0
  79. package/dist/tests-ts/personal-assistant-memory.test.js +117 -0
  80. package/dist/tests-ts/personal-assistant-owner-context.test.js +107 -0
  81. package/dist/tests-ts/personal-assistant-remote-ability.test.js +123 -0
  82. package/dist/tests-ts/personal-assistant.test.js +663 -0
  83. package/dist/tests-ts/platform-integration.test.js +183 -1
  84. package/dist/tests-ts/plugin-catalog.test.js +12 -2
  85. package/dist/tests-ts/plugin-manager.test.js +356 -4
  86. package/dist/tests-ts/plugin-upgrade-deadline.test.js +354 -0
  87. package/dist/tests-ts/publish-packages.test.js +42 -0
  88. package/dist/tests-ts/qwenwork-plugin.test.js +135 -1
  89. package/dist/tests-ts/qwenwork-reconnect.test.js +195 -0
  90. package/dist/tests-ts/qwenwork-sse.test.js +33 -0
  91. package/dist/tests-ts/session-access-defaults.test.js +112 -0
  92. package/dist/tests-ts/session-management.test.js +159 -4
  93. package/dist/tests-ts/version-manager.test.js +40 -0
  94. package/dist/tests-ts/workbuddy-cdp-recovery.test.js +311 -0
  95. package/dist/tests-ts/workbuddy-plugin.test.js +499 -4
  96. package/dist/tests-ts/zcode-cdp.test.js +894 -0
  97. package/dist/tests-ts/zcode-plugin.test.js +396 -0
  98. package/package.json +1 -1
  99. package/plugins/abweb/dist/src-ts/agent.js +35 -0
  100. package/plugins/abweb/dist/src-ts/plugins/abweb/index.js +1 -1
  101. package/plugins/abweb/dist/src-ts/plugins/abweb/public/app.js +73 -5
  102. package/plugins/abweb/dist/src-ts/plugins/abweb/public/app.ts +57 -5
  103. package/plugins/abweb/dist/src-ts/plugins/abweb/public/index.html +15 -0
  104. package/plugins/abweb/dist/src-ts/plugins/abweb/public/style.css +4 -0
  105. package/plugins/abweb/package.json +1 -1
  106. package/plugins/abweb/plugin.json +1 -1
  107. package/plugins/aun/config.schema.json +1 -1
  108. package/plugins/aun/dist/src-ts/agent.js +35 -0
  109. package/plugins/aun/dist/src-ts/plugins/aun/attachments.js +3 -21
  110. package/plugins/aun/dist/src-ts/plugins/aun/index.js +155 -21
  111. package/plugins/aun/dist/src-ts/plugins/aun/messages.js +4 -1
  112. package/plugins/aun/dist/src-ts/plugins/aun/public/app.js +2 -1
  113. package/plugins/aun/dist/src-ts/plugins/aun/public/index.html +1 -1
  114. package/plugins/aun/package.json +1 -1
  115. package/plugins/aun/plugin.json +1 -1
  116. package/plugins/chatgpt/dist/src-ts/agent.js +35 -0
  117. package/plugins/chatgpt/dist/src-ts/plugins/cdp-draft.js +5 -2
  118. package/plugins/chatgpt/dist/src-ts/plugins/chatgpt/cdp-client.js +26 -12
  119. package/plugins/chatgpt/dist/src-ts/plugins/chatgpt/index.js +80 -19
  120. package/plugins/chatgpt/dist/src-ts/plugins/desktop-launch.js +44 -3
  121. package/plugins/chatgpt/package.json +1 -1
  122. package/plugins/chatgpt/plugin.json +1 -1
  123. package/plugins/claude-cli/dist/src-ts/agent.js +35 -0
  124. package/plugins/claude-cli/dist/src-ts/plugins/claude-cli/index.js +19 -2
  125. package/plugins/claude-cli/dist/src-ts/plugins/local-cli/agent.js +74 -9
  126. package/plugins/claude-cli/package.json +1 -1
  127. package/plugins/claude-cli/plugin.json +3 -2
  128. package/plugins/codex-cli/dist/src-ts/agent.js +35 -0
  129. package/plugins/codex-cli/dist/src-ts/plugins/codex-cli/index.js +19 -2
  130. package/plugins/codex-cli/dist/src-ts/plugins/local-cli/agent.js +74 -9
  131. package/plugins/codex-cli/package.json +1 -1
  132. package/plugins/codex-cli/plugin.json +3 -2
  133. package/plugins/doubao/config.schema.json +2 -1
  134. package/plugins/doubao/dist/src-ts/agent.js +35 -0
  135. package/plugins/doubao/dist/src-ts/plugins/desktop-launch.js +44 -3
  136. package/plugins/doubao/dist/src-ts/plugins/doubao/cdp-client.js +234 -45
  137. package/plugins/doubao/dist/src-ts/plugins/doubao/index.js +152 -8
  138. package/plugins/doubao/dist/src-ts/plugins/doubao/native-task.js +134 -0
  139. package/plugins/doubao/package.json +1 -1
  140. package/plugins/doubao/plugin.json +3 -2
  141. package/plugins/dsh/config.schema.json +5 -2
  142. package/plugins/dsh/dist/src-ts/agent.js +35 -0
  143. package/plugins/dsh/dist/src-ts/dsh-agent.js +31 -13
  144. package/plugins/dsh/dist/src-ts/plugins/desktop-launch.js +44 -3
  145. package/plugins/dsh/dist/src-ts/plugins/dsh/cdp-client.js +334 -0
  146. package/plugins/dsh/dist/src-ts/plugins/dsh/index.js +172 -21
  147. package/plugins/dsh/dist/src-ts/plugins/dsh/session-history.js +31 -3
  148. package/plugins/dsh/package.json +1 -1
  149. package/plugins/dsh/plugin.json +3 -2
  150. package/plugins/feishu/dist/src-ts/agent.js +35 -0
  151. package/plugins/feishu/dist/src-ts/plugins/feishu/index.js +1 -1
  152. package/plugins/feishu/package.json +1 -1
  153. package/plugins/feishu/plugin.json +1 -1
  154. package/plugins/personal-assistant/config.schema.json +23 -0
  155. package/plugins/personal-assistant/dist/src-ts/agent.js +69 -0
  156. package/plugins/personal-assistant/dist/src-ts/attachments.js +62 -0
  157. package/plugins/personal-assistant/dist/src-ts/plugin.js +13 -0
  158. package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/claude-cli-model.js +30 -0
  159. package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/coordination.js +57 -0
  160. package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/index.js +263 -0
  161. package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/model-client.js +181 -0
  162. package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/owner-context.js +56 -0
  163. package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/remote-ability.js +176 -0
  164. package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/session-memory.js +124 -0
  165. package/plugins/personal-assistant/dist/src-ts/plugins/personal-assistant/tools.js +167 -0
  166. package/plugins/personal-assistant/package.json +39 -0
  167. package/plugins/personal-assistant/plugin.json +15 -0
  168. package/plugins/qwenwork/dist/src-ts/agent.js +35 -0
  169. package/plugins/qwenwork/dist/src-ts/plugins/cdp-draft.js +5 -2
  170. package/plugins/qwenwork/dist/src-ts/plugins/desktop-launch.js +44 -3
  171. package/plugins/qwenwork/dist/src-ts/plugins/qwenwork/cdp-client.js +90 -18
  172. package/plugins/qwenwork/dist/src-ts/plugins/qwenwork/index.js +139 -24
  173. package/plugins/qwenwork/package.json +1 -1
  174. package/plugins/qwenwork/plugin.json +3 -2
  175. package/plugins/workbuddy/config.schema.json +1 -1
  176. package/plugins/workbuddy/dist/src-ts/agent.js +35 -0
  177. package/plugins/workbuddy/dist/src-ts/plugins/desktop-launch.js +44 -3
  178. package/plugins/workbuddy/dist/src-ts/plugins/workbuddy/cdp-client.js +353 -82
  179. package/plugins/workbuddy/dist/src-ts/plugins/workbuddy/index.js +124 -41
  180. package/plugins/workbuddy/package.json +1 -1
  181. package/plugins/workbuddy/plugin.json +3 -2
  182. package/plugins/zcode/config.schema.json +13 -0
  183. package/plugins/zcode/dist/src-ts/agent.js +69 -0
  184. package/plugins/zcode/dist/src-ts/attachments.js +62 -0
  185. package/plugins/zcode/dist/src-ts/plugin.js +13 -0
  186. package/plugins/zcode/dist/src-ts/plugins/desktop-launch.js +238 -0
  187. package/plugins/zcode/dist/src-ts/plugins/workbuddy/cdp-client.js +896 -0
  188. package/plugins/zcode/dist/src-ts/plugins/workbuddy/cli-client.js +39 -0
  189. package/plugins/zcode/dist/src-ts/plugins/workbuddy/desktop-launch.js +10 -0
  190. package/plugins/zcode/dist/src-ts/plugins/workbuddy/index.js +567 -0
  191. package/plugins/zcode/dist/src-ts/plugins/workbuddy/session-history.js +121 -0
  192. package/plugins/zcode/dist/src-ts/plugins/zcode/cdp-client.js +500 -0
  193. package/plugins/zcode/dist/src-ts/plugins/zcode/index.js +97 -0
  194. package/plugins/zcode/package.json +16 -0
  195. package/plugins/zcode/plugin.json +11 -0
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DoubaoPlugin = exports.doubaoManifest = void 0;
4
+ const node_child_process_1 = require("node:child_process");
4
5
  const promises_1 = require("node:fs/promises");
5
6
  const node_path_1 = require("node:path");
7
+ const agent_1 = require("../../agent");
6
8
  const cdp_client_1 = require("./cdp-client");
7
9
  const session_history_1 = require("./session-history");
8
10
  const plugin_1 = require("../../plugin");
@@ -10,17 +12,111 @@ const desktop_launch_1 = require("../desktop-launch");
10
12
  const node_os_1 = require("node:os");
11
13
  exports.doubaoManifest = {
12
14
  id: "doubao",
13
- version: "1.0.23",
15
+ version: "1.0.35",
14
16
  displayName: "豆包",
15
17
  entry: "dist/index.js",
16
18
  apiVersion: "1",
17
19
  process: "in-process",
18
- capabilities: ["chat", "health"],
20
+ capabilities: ["chat", "health", "model-provider"],
19
21
  configSchema: "config.schema.json",
20
22
  };
23
+ const doubaoLoginEntries = [
24
+ "Local State",
25
+ "saman_app_state",
26
+ "saman_shell_db_storage",
27
+ "saman_shell_persistent_storage_v1",
28
+ "Default/Network",
29
+ "Default/Local Storage",
30
+ "Default/IndexedDB",
31
+ "Default/Session Storage",
32
+ "Default/WebStorage",
33
+ "Default/DoubaoStorage",
34
+ "Default/Preferences",
35
+ "Default/Secure Preferences",
36
+ "Default/Remote_State",
37
+ "Default/Remote_State_Aha_Chromium",
38
+ ];
39
+ function runRobocopy(args) {
40
+ return new Promise((resolve, reject) => (0, node_child_process_1.execFile)("robocopy.exe", args, { windowsHide: true }, error => {
41
+ if (!error)
42
+ return resolve();
43
+ const rawCode = error.code;
44
+ const code = typeof rawCode === "number" ? rawCode : Number(rawCode);
45
+ if (Number.isFinite(code) && code <= 7)
46
+ resolve();
47
+ else
48
+ reject(error);
49
+ }));
50
+ }
51
+ async function copyWithWindowsBackup(from, staged) {
52
+ const sourceInfo = await (0, promises_1.stat)(from);
53
+ const robocopyTarget = `${staged}.robocopy`;
54
+ await (0, promises_1.rm)(robocopyTarget, { recursive: true, force: true });
55
+ await (0, promises_1.mkdir)(robocopyTarget, { recursive: true });
56
+ const args = [
57
+ sourceInfo.isDirectory() ? from : (0, node_path_1.dirname)(from),
58
+ robocopyTarget,
59
+ sourceInfo.isDirectory() ? "*" : (0, node_path_1.basename)(from),
60
+ ...(sourceInfo.isDirectory() ? ["/E"] : []),
61
+ "/B", "/COPY:DAT", "/DCOPY:DAT", "/R:0", "/W:0", "/NFL", "/NDL", "/NJH", "/NJS", "/NP", "/XF", "LOCK", "LOG", "LOG.old", "lockfile",
62
+ ];
63
+ try {
64
+ await runRobocopy(args);
65
+ const copied = sourceInfo.isDirectory() ? robocopyTarget : (0, node_path_1.join)(robocopyTarget, (0, node_path_1.basename)(from));
66
+ await (0, promises_1.rm)(staged, { recursive: true, force: true });
67
+ await (0, promises_1.rename)(copied, staged);
68
+ }
69
+ finally {
70
+ await (0, promises_1.rm)(robocopyTarget, { recursive: true, force: true }).catch(() => undefined);
71
+ }
72
+ }
73
+ async function copyDoubaoLoginState(target) {
74
+ const source = (0, node_path_1.join)(process.env.LOCALAPPDATA ?? (0, node_path_1.join)((0, node_os_1.homedir)(), "AppData", "Local"), "Doubao", "User Data");
75
+ await (0, promises_1.mkdir)(target, { recursive: true });
76
+ for (const entry of doubaoLoginEntries) {
77
+ const from = (0, node_path_1.join)(source, entry);
78
+ const to = (0, node_path_1.join)(target, entry);
79
+ const staged = `${to}.mab-copy`;
80
+ try {
81
+ await (0, promises_1.rm)(staged, { recursive: true, force: true });
82
+ await (0, promises_1.mkdir)((0, node_path_1.dirname)(staged), { recursive: true });
83
+ try {
84
+ await (0, promises_1.cp)(from, staged, {
85
+ recursive: true,
86
+ force: true,
87
+ filter: value => !new Set(["LOCK", "LOG", "LOG.old", "lockfile"]).has(value.split(/[\\/]/).at(-1) ?? ""),
88
+ });
89
+ }
90
+ catch (error) {
91
+ if (error.code !== "EBUSY")
92
+ throw error;
93
+ try {
94
+ await copyWithWindowsBackup(from, staged);
95
+ }
96
+ catch {
97
+ await (0, promises_1.rm)(staged, { recursive: true, force: true }).catch(() => undefined);
98
+ continue;
99
+ }
100
+ }
101
+ await (0, promises_1.rm)(to, { recursive: true, force: true });
102
+ await (0, promises_1.rename)(staged, to);
103
+ }
104
+ catch (error) {
105
+ await (0, promises_1.rm)(staged, { recursive: true, force: true }).catch(() => undefined);
106
+ const code = error.code;
107
+ if (code !== "ENOENT" && code !== "EBUSY")
108
+ throw error;
109
+ }
110
+ }
111
+ }
21
112
  class DoubaoPlugin {
22
113
  injectedClient;
23
114
  manifest = exports.doubaoManifest;
115
+ get modelProvider() {
116
+ if (!this.client?.complete || !this.client.createSession)
117
+ return undefined;
118
+ return { complete: (request) => this.completeModelProvider(request) };
119
+ }
24
120
  attachmentInput = true;
25
121
  sessionOperations = [];
26
122
  sessionHistory;
@@ -57,7 +153,14 @@ class DoubaoPlugin {
57
153
  conversationId: typeof context.config.conversationId === "string" ? context.config.conversationId : undefined,
58
154
  botId: typeof context.config.botId === "string" ? context.config.botId : undefined,
59
155
  pluginList: Array.isArray(context.config.pluginList) ? context.config.pluginList.filter((value) => typeof value === "string") : undefined,
156
+ mode: context.config.mode === "chat" ? "chat" : "local-computer",
60
157
  timeoutMs: typeof context.config.timeoutMs === "number" ? context.config.timeoutMs : undefined,
158
+ logger: { warn: message => context.logger?.warn?.(message) },
159
+ recoverCdp: async () => {
160
+ if (!this.reconnect)
161
+ throw new Error("豆包插件尚未配置 CDP 恢复流程");
162
+ await this.reconnect();
163
+ },
61
164
  });
62
165
  this.sessionHistory = new session_history_1.DoubaoSessionHistoryProvider({
63
166
  scope: `doubao:${(0, plugin_1.resolveRuntimePort)(context.config, context.runtime, "doubao", "DOUBAO_CDP_PORT", 9227)}`,
@@ -70,17 +173,30 @@ class DoubaoPlugin {
70
173
  }
71
174
  catch (first) {
72
175
  if (context.config.autoStart !== false && !this.injectedClient && process.platform === "win32") {
176
+ if (!(0, agent_1.errorDetails)(first).includes("ECONNREFUSED"))
177
+ throw first;
73
178
  const executable = await (0, desktop_launch_1.findWindowsExecutable)("Doubao.exe", typeof context.config.executablePath === "string" ? context.config.executablePath : undefined);
74
179
  if (!executable)
75
180
  throw new Error("未找到 Doubao.exe,请配置 executablePath");
76
181
  const port = (0, plugin_1.resolveRuntimePort)(context.config, context.runtime, "doubao", "DOUBAO_CDP_PORT", 9227);
77
182
  context.logger?.warn?.(`正在恢复豆包:${executable},等待 CDP ${port}`);
78
183
  try {
79
- await (0, desktop_launch_1.restartOwnedAndWait)(this.ownedProcess, executable, [`--remote-debugging-port=${port}`], (0, node_path_1.join)(this.dataDir ?? (0, node_path_1.join)((0, node_os_1.homedir)(), ".agent-bridge", "doubao"), "desktop-profile"), () => this.client.connect(), typeof context.config.startupTimeoutMs === "number" ? context.config.startupTimeoutMs : 30_000, child => { this.ownedProcess = child; });
184
+ // 只重启桥接持有的进程;人工实例占用默认目录时使用下方独立目录。
185
+ await (0, desktop_launch_1.restartOwnedAndWait)(this.ownedProcess, executable, [`--remote-debugging-port=${port}`], undefined, () => this.client.connect(), typeof context.config.startupTimeoutMs === "number" ? context.config.startupTimeoutMs : 30_000, child => { this.ownedProcess = child; });
80
186
  return;
81
187
  }
82
188
  catch (error) {
83
189
  first = new Error(`已启动豆包,但 CDP ${port} 未就绪:${error instanceof Error ? error.message : String(error)}`);
190
+ const profile = (0, node_path_1.join)(this.dataDir ?? (0, node_path_1.join)((0, node_os_1.homedir)(), ".agent-bridge", "doubao"), "desktop-profile");
191
+ try {
192
+ await copyDoubaoLoginState(profile);
193
+ context.logger?.warn?.(`默认豆包用户目录不可用,改用登录状态副本:${profile}`);
194
+ await (0, desktop_launch_1.restartOwnedAndWait)(this.ownedProcess, executable, [`--remote-debugging-port=${port}`], profile, () => this.client.connect(), typeof context.config.startupTimeoutMs === "number" ? context.config.startupTimeoutMs : 30_000, child => { this.ownedProcess = child; });
195
+ return;
196
+ }
197
+ catch (fallbackError) {
198
+ first = new Error(`已启动豆包,但 CDP ${port} 未就绪:${fallbackError instanceof Error ? fallbackError.message : String(fallbackError)}`);
199
+ }
84
200
  }
85
201
  }
86
202
  throw first;
@@ -100,13 +216,14 @@ class DoubaoPlugin {
100
216
  throw error;
101
217
  }
102
218
  }
103
- async deactivate() {
219
+ async deactivate(_reason = "stop", options) {
104
220
  await this.queue;
105
221
  this.disposer?.();
106
222
  this.disposer = undefined;
107
223
  this.reconnect = undefined;
108
224
  await this.client?.close();
109
- await (0, desktop_launch_1.terminateOwnedProcess)(this.ownedProcess).catch(() => undefined);
225
+ if (!options?.preserveDesktop)
226
+ await (0, desktop_launch_1.terminateOwnedProcess)(this.ownedProcess).catch(() => undefined);
110
227
  this.ownedProcess = undefined;
111
228
  this.client = undefined;
112
229
  this.state = "stopped";
@@ -136,7 +253,7 @@ class DoubaoPlugin {
136
253
  if (this.state !== "ready" || !this.client)
137
254
  throw new Error("豆包插件未就绪");
138
255
  if (!this.client.connected())
139
- await this.reconnect?.();
256
+ await this.reconnect();
140
257
  }
141
258
  async handle(request) {
142
259
  return this.enqueue(async () => {
@@ -145,9 +262,9 @@ class DoubaoPlugin {
145
262
  if (request.attachments?.length && !client.complete)
146
263
  throw new Error("当前豆包客户端不支持附件输入");
147
264
  if (!client.complete)
148
- return { text: await client.direct(request.task) };
265
+ return { text: await client.direct(request.task, request.signal) };
149
266
  const conversationId = request.sessionId ? this.bindings.get(request.sessionId) ?? "" : undefined;
150
- const response = await client.complete(request.task, undefined, request.attachments, conversationId);
267
+ const response = await client.complete(request.task, request.signal, request.attachments, conversationId);
151
268
  if (!request.sessionId)
152
269
  return response;
153
270
  if (!response.sessionId || !/^\d+$/.test(response.sessionId))
@@ -156,6 +273,33 @@ class DoubaoPlugin {
156
273
  return { ...response, sessionId: request.sessionId };
157
274
  });
158
275
  }
276
+ async completeModelProvider(request) {
277
+ let stage = "豆包模型排队(queue)";
278
+ try {
279
+ request.signal.throwIfAborted();
280
+ const run = this.enqueue(async () => {
281
+ request.signal.throwIfAborted();
282
+ stage = "连接豆包模型(connect)";
283
+ await this.ensureConnected();
284
+ const client = this.client;
285
+ if (!client?.complete)
286
+ throw new Error("豆包客户端不支持模型调用");
287
+ stage = "等待豆包模型生成(generate)";
288
+ // 空服务端标识会原子创建独立会话,无需切换用户桌面页面。
289
+ const response = await client.complete(request.prompt, request.signal, undefined, this.bindings.get(request.sessionId) ?? "");
290
+ if (!response.sessionId || !/^\d+$/.test(response.sessionId))
291
+ throw new Error("豆包未返回有效的服务端会话标识");
292
+ await this.remember(request.sessionId, response.sessionId);
293
+ return { text: response.text };
294
+ });
295
+ return await (0, agent_1.abortable)(run, request.signal);
296
+ }
297
+ catch (error) {
298
+ if (error instanceof agent_1.AgentOperationError)
299
+ throw error;
300
+ throw new agent_1.AgentOperationError("DOUBAO_MODEL_FAILED", stage, error);
301
+ }
302
+ }
159
303
  enqueue(task) {
160
304
  this.pending++;
161
305
  const run = this.queue.then(task);
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.nativeTaskScript = void 0;
4
+ // shortcut: 依赖桌面端原生模块导出,豆包升级接口后需重新校验;接口缺失时拒绝发送。
5
+ exports.nativeTaskScript = String.raw `(body, readTexts, readArtifacts, getRequestUrl) => {
6
+ window.__mab_doubao_controller?.abort();
7
+ const controller = new AbortController();
8
+ window.__mab_doubao_controller = controller;
9
+ window.__mab_doubao_read_artifacts = undefined;
10
+ window.__mab_doubao_request_id = body.option.unique_key;
11
+ let progressSequence = 0;
12
+ window.__mab_doubao_progress = { requestId: body.option.unique_key, sequence: progressSequence };
13
+ window.__mab_doubao_result = null;
14
+ const finish = result => {
15
+ if (window.__mab_doubao_controller === controller) window.__mab_doubao_result = JSON.stringify(result);
16
+ };
17
+ (async () => {
18
+ window.__mab_doubao_request_url = getRequestUrl().href;
19
+ const chunks = window['@flow-web/desktop:stable'];
20
+ if (!Array.isArray(chunks)) throw Error('豆包本地电脑原生接口不可用,请检查桌面端版本');
21
+ let requireNative;
22
+ chunks.push([['mab_task_' + body.option.unique_key], {}, value => { requireNative = value; }]);
23
+ const factories = new Map(chunks.flatMap(chunk => Object.entries(chunk[1] || {})));
24
+ const load = (marker, extra = '') => {
25
+ for (const [id, factory] of factories) if (String(factory).includes(marker) && String(factory).includes(extra)) return requireNative(id);
26
+ throw Error('豆包本地电脑接口缺失:' + marker);
27
+ };
28
+ const named = name => load(name + ':()=>')[name];
29
+ const only = (module, predicate) => {
30
+ const matches = Object.values(module).filter(value => typeof value === 'function' && predicate(value));
31
+ if (matches.length !== 1) throw Error('豆包本地电脑原生接口不兼容');
32
+ return matches[0];
33
+ };
34
+ const environment = await named('sandboxEnvironmentController').query();
35
+ if (!environment.isReady || !environment.environmentId) throw Error('豆包本地电脑环境未就绪,请在当前桌面登录态中检查本地电脑功能');
36
+ const getStore = only(load('chat-ioc-manager: cannot bind empty store'), value => String(value).includes('it is async store'));
37
+ const state = getStore('chatInputStore').getState();
38
+ const agentMode = named('AgentMode').MOA;
39
+ const mode = state.modeSelectConfigs?.menu_item_list?.find(item => Number(item.agent_mode) === agentMode);
40
+ if (!mode) throw Error('当前豆包登录态未提供任务模式,不能使用本地电脑');
41
+ const modeId = state.modeSelectConfigsV2?.mode_list?.item_list?.find(item => Number(item.agent_mode) === agentMode)?.mode_id || mode.default_mode;
42
+ if (!modeId) throw Error('豆包本地电脑任务模式标识缺失');
43
+ const getAuthorization = only(load('new WeakMap', 'sandboxAuthType:'), value => value.length === 0);
44
+ const authorization = getAuthorization();
45
+ if (!authorization || typeof authorization.sandboxAuthType !== 'number') throw Error('无法读取豆包本地电脑授权设置');
46
+ const getService = only(load('chat-ioc-manager: cannot bind empty service'), value => value.constructor.name === 'AsyncFunction');
47
+ const service = await getService('chatIMService');
48
+ const messageService = await service?.getMessageService();
49
+ if (!messageService?.sendMessage) throw Error('豆包本地电脑消息服务未就绪');
50
+ const scope = body.client_meta.conversation_id || body.client_meta.local_conversation_id;
51
+ const taskApi = load('buildGeneralAgentCompletionTaskParam:()=>');
52
+ const clientOption = await taskApi.buildGeneralAgentCompletionTaskParam(scope);
53
+ if (!clientOption.sandbox_id || !clientOption.workspace) throw Error('豆包本地电脑工作区或运行环境不可用');
54
+ const workspace = clientOption.workspace;
55
+ const runtimeType = taskApi.GeneralAgentRuntimeType.LocalPC;
56
+ const modify = only(load('general_agent_conversation_modify_params'), value => value.constructor.name === 'AsyncFunction');
57
+ const changes = await modify({ completionTaskParam: clientOption, messageConversationId: scope, primaryWorkspace: clientOption.workspace, runtimeType, sandboxAuthType: authorization.sandboxAuthType });
58
+ const general = { ...changes, runtime_type: runtimeType, server_do_compare: true, client_option: {
59
+ ...clientOption, sandbox_id: undefined, sandbox_env_id: clientOption.sandbox_id,
60
+ shared_folder_path: [clientOption.workspace], sandbox_auth_type: authorization.sandboxAuthType,
61
+ } };
62
+ const connector = await named('getFeishuConnectorEnabledForConversation')(scope);
63
+ const connectorInfo = only(load('connector_info_list', 'wrapped:!0'), value => {
64
+ const source = String(value); return source.includes('connector_id:') && source.includes('switch:') && source.includes('connector_vendor:');
65
+ });
66
+ const extra = {
67
+ agent_mode: String(agentMode), use_deep_think: String(mode.menu_type ?? mode.item_id), mode_id: String(modeId),
68
+ model_item_key: mode.model_item_key, model_extra_params: JSON.stringify(mode.model_extra_params || {}),
69
+ reasoning_effort: String(mode.reasoning_effort_config?.default_level ?? body.option.model_config.reasoning_effort),
70
+ general_task_param: JSON.stringify(general), mention_plugin_list: body.option.aggregate_params.mention_plugin_list,
71
+ ...(connector ? { connector_info_list: JSON.stringify([connectorInfo(connector.enabled, connector.id)]) } : {}),
72
+ ...(!body.client_meta.conversation_id ? {
73
+ conversation_init_option: JSON.stringify({ need_ack_conversation: true }),
74
+ conversation_init_ext: JSON.stringify({ mode_id: String(modeId), agent_task_param: JSON.stringify(changes.agent_task_param) }),
75
+ } : {}),
76
+ };
77
+ const create = named('createSendMessage');
78
+ const messages = body.messages.map(item => create({ conversationContext: {
79
+ conversation_id: body.client_meta.conversation_id || undefined,
80
+ local_conversation_id: body.client_meta.conversation_id ? undefined : scope, bot_id: body.client_meta.bot_id,
81
+ }, message: { content_blocks_v2: item.content_block, unique_id: item.local_message_id, ext: extra } }));
82
+ controller.signal.throwIfAborted();
83
+ const handle = messageService.sendMessage({ messages, sessionId: body.option.unique_key, session: { reportParams: { is_local_computer_on: 1 } }, sendMode: 'normal' });
84
+ controller.signal.addEventListener('abort', () => { Promise.resolve().then(() => handle.cancel()).catch(() => {}); }, { once: true });
85
+ const localIds = new Set(body.messages.map(item => item.local_message_id)), replies = new Map();
86
+ const questionIds = new Set(), messageIds = new Set();
87
+ let expectVideo = false, conversationId = body.client_meta.conversation_id;
88
+ const collect = message => {
89
+ const statuses = Object.values(message.final_status || {});
90
+ if (statuses.some(status => ['Broken', 'CancelError', 'Cancelled', 'Canceled'].includes(status))) throw Error('豆包本地电脑任务已中止');
91
+ if (message.error_details?.has_error || statuses.some(status => ['Error', 'PanicError', 'ExpectError'].includes(status))) throw Error(message.error_details?.error_msg || '豆包本地电脑任务执行失败');
92
+ if (message.ext?.has_video_gen === '1' || message.ext?.has_video_gen === 1) expectVideo = true;
93
+ if (message.message_id) {
94
+ messageIds.add(message.message_id);
95
+ replies.set(message.message_id, message.content_blocks_v2 || message.content_blocks || message.content_block || []);
96
+ }
97
+ };
98
+ for await (const message of handle.subscribe()) {
99
+ if (window.__mab_doubao_controller === controller) window.__mab_doubao_progress = { requestId: body.option.unique_key, sequence: ++progressSequence };
100
+ if (message.conversation_id) conversationId = message.conversation_id;
101
+ if (localIds.has(message.local_message_id) || localIds.has(message.unique_id)) {
102
+ if (message.error_details?.has_error) throw Error('豆包本地电脑任务发送失败');
103
+ if (message.message_id) questionIds.add(message.message_id);
104
+ continue;
105
+ }
106
+ if (message.reply_id) questionIds.add(message.reply_id);
107
+ collect(message);
108
+ }
109
+ const mediaSnapshot = () => {
110
+ const media = readArtifacts([...replies.values()], workspace);
111
+ return { ...media, pending: media.pending || (expectVideo && !media.artifacts.some(item => item.kind === 'video')) };
112
+ };
113
+ // 异步媒体按本轮引用读取原生消息列表,不依赖人工当前打开的会话。
114
+ if (window.__mab_doubao_controller !== controller) throw Error('豆包本地电脑原任务上下文已变化');
115
+ window.__mab_doubao_read_artifacts = async requestId => {
116
+ if (requestId !== body.option.unique_key || window.__mab_doubao_controller !== controller) throw Error('豆包本地电脑原任务上下文已变化');
117
+ controller.signal.throwIfAborted();
118
+ if (typeof messageService.fetchAndUpdateMessageList !== 'function') throw Error('豆包本地电脑异步产物读取接口不可用');
119
+ const page = await messageService.fetchAndUpdateMessageList({ conversationId, options: { limit: 50 } });
120
+ for (const message of page?.messages || []) {
121
+ if (message.conversation_id !== conversationId) continue;
122
+ const reference = message.ext?.reference_info;
123
+ const match = typeof reference === 'string' ? reference.match(/"referenced_message_id"\s*:\s*(?:"([^"\n]+)"|(\d+))/) : null;
124
+ const referenceId = match?.[1] || match?.[2];
125
+ if (messageIds.has(message.message_id) || questionIds.has(message.reply_id) || questionIds.has(referenceId)) collect(message);
126
+ }
127
+ return mediaSnapshot();
128
+ };
129
+ const media = mediaSnapshot();
130
+ const reply = readTexts([...replies.values()].map(blocks => blocks.filter(block => !block.parent_id && block.control_info?.is_visible !== false))).join('\n').trim();
131
+ if (!reply && !media.artifacts.length && !media.pending) throw Error('豆包本地电脑任务未返回结果');
132
+ finish({ ok: true, reply, conversationId, ...media, requestId: body.option.unique_key, questionIds: [...questionIds], messageIds: [...messageIds] });
133
+ })().catch(error => { finish({ failed: true, requestId: body.option.unique_key, reason: error?.message || String(error) }); });
134
+ }`;