mu-agent-bridge 1.0.44 → 1.0.45

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 CHANGED
@@ -77,7 +77,7 @@ mab start
77
77
  abweb 插件目录从 npm 搜索带 `mu-agent-bridge-plugin` 关键词的包,按包元数据中的
78
78
  `agentBridge.type` 展示 Agent、Channel 和管理插件;安装后以 `plugin.json` 的类型和能力
79
79
  再次校验,不根据包名推断类型。搜索结果有收录延迟,可在页面直接输入 `agent-bridge-*`
80
- 包名安装。已安装插件按清单能力兼容旧版分类。AUN 通道插件包名为 `agent-bridge-aun`,安装后配置 AID 并启动即可;来信默认交给千问办公,也可通过 `agent_plugin` 指定其他已安装 Agent。`workbuddy` 插件包名为 `agent-bridge-workbuddy`,将 AUN 的 `agent_plugin` 设为 `workbuddy` 即可按对端保持 CodeBuddy 会话。默认问答使用独立的 `@tencent-ai/codebuddy-code` CLI,须单独登录;没有 CLI 时使用 WorkBuddy 桌面端 CDP,并默认自动启动桌面应用。CLI 未登录时不会自动切换到桌面端账号;可设置 `transport` 为 `cdp` 显式使用桌面端。
80
+ 包名安装。已安装插件按清单能力兼容旧版分类。AUN 通道插件包名为 `agent-bridge-aun`,安装后在 AUN 身份页手动关联每个 AID;未关联的 AID 不会自动投递,关联操作只修改指定 AID,不影响其它身份。`workbuddy` 插件包名为 `agent-bridge-workbuddy`,显式关联到 WorkBuddy 后即可按对端保持 CodeBuddy 会话。默认问答使用独立的 `@tencent-ai/codebuddy-code` CLI,须单独登录;没有 CLI 时使用 WorkBuddy 桌面端 CDP,并默认自动启动桌面应用。CLI 未登录时不会自动切换到桌面端账号;可设置 `transport` 为 `cdp` 显式使用桌面端。
81
81
 
82
82
  插件仍在 daemon 的同一个 Node.js 进程内运行。修改插件入口依赖后应重启 daemon,避免模块缓存
83
83
  影响新代码。
@@ -48,6 +48,8 @@ const bridge_1 = require("./bridge");
48
48
  const plugin_manager_1 = require("./plugin-manager");
49
49
  const daemon_process_1 = require("./daemon-process");
50
50
  const cli_commands_1 = require("./cli-commands");
51
+ const core_updater_1 = require("./core-updater");
52
+ const log_store_1 = require("./log-store");
51
53
  const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
52
54
  let activeManager;
53
55
  const logger = {
@@ -170,6 +172,31 @@ async function startDaemon() {
170
172
  const child = (0, node_child_process_1.spawn)(process.execPath, [(0, node_path_1.resolve)(__dirname, "cli.js"), "start"], { detached: true, stdio: "ignore", windowsHide: true });
171
173
  child.unref();
172
174
  }
175
+ async function startUpdatedDaemon() {
176
+ const child = (0, node_child_process_1.spawn)(process.execPath, [(0, node_path_1.resolve)(__dirname, "cli.js"), "start"], { detached: true, stdio: "ignore", windowsHide: true });
177
+ let launchFailed = false;
178
+ child.once("error", () => { launchFailed = true; });
179
+ child.unref();
180
+ const healthy = async () => {
181
+ for (let attempt = 0; attempt < 30; attempt++) {
182
+ if (launchFailed || child.exitCode !== null || child.signalCode !== null)
183
+ return false;
184
+ const address = await daemonAddress();
185
+ try {
186
+ const response = await fetch(`http://127.0.0.1:${address.port}/api/health`, {
187
+ headers: process.env.AGENT_BRIDGE_TOKEN ? { authorization: `Bearer ${process.env.AGENT_BRIDGE_TOKEN}` } : undefined,
188
+ signal: AbortSignal.timeout(1000),
189
+ });
190
+ if (response.ok && (await response.json()).status === "ok")
191
+ return true;
192
+ }
193
+ catch { /* daemon 尚未就绪 */ }
194
+ await new Promise((done) => setTimeout(done, 1000));
195
+ }
196
+ return false;
197
+ };
198
+ return { child, healthy };
199
+ }
173
200
  async function stop() {
174
201
  await stopDaemon();
175
202
  console.log("旧 daemon 已停止");
@@ -344,6 +371,20 @@ async function main() {
344
371
  if (args[0] === "--self-test")
345
372
  return selfTest(args[1] ?? "hi");
346
373
  if (args[0] === "--serve" || args[0] === "start") {
374
+ const logs = new log_store_1.LogStore((0, node_path_1.resolve)(stateDirectory(), "logs"));
375
+ let launched;
376
+ const updated = await (0, core_updater_1.updateCoreAtStartup)({
377
+ packageRoot: (0, node_path_1.resolve)(__dirname, "..", ".."),
378
+ stateDir: stateDirectory(),
379
+ stopDaemon: () => stopDaemon(false),
380
+ startDaemon: async () => { launched = await startUpdatedDaemon(); },
381
+ waitForHealth: async () => launched?.healthy() ?? false,
382
+ log: (level, message, fields) => logs.append({ time: new Date().toISOString(), level, source: "核心升级", message, fields }),
383
+ });
384
+ if (updated) {
385
+ await logs.flush();
386
+ return 0;
387
+ }
347
388
  await stopDaemon(false);
348
389
  return serve();
349
390
  }
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.updateCoreAtStartup = updateCoreAtStartup;
4
+ const promises_1 = require("node:fs/promises");
5
+ const node_path_1 = require("node:path");
6
+ const node_child_process_1 = require("node:child_process");
7
+ const node_util_1 = require("node:util");
8
+ const version_manager_1 = require("./version-manager");
9
+ const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
10
+ function normalizePath(value) {
11
+ const path = (0, node_path_1.resolve)(value).replace(/[\\/]+$/, "");
12
+ return process.platform === "win32" ? path.toLowerCase() : path;
13
+ }
14
+ async function sameDirectory(left, right) {
15
+ try {
16
+ return normalizePath(await (0, promises_1.realpath)(left)) === normalizePath(await (0, promises_1.realpath)(right));
17
+ }
18
+ catch {
19
+ return normalizePath(left) === normalizePath(right);
20
+ }
21
+ }
22
+ async function runNpm(args) {
23
+ const command = process.platform === "win32" ? "npm.cmd" : "npm";
24
+ const { stdout } = await execFileAsync(command, args, { timeout: 180_000, maxBuffer: 4 * 1024 * 1024, ...(process.platform === "win32" ? { shell: true } : {}) });
25
+ return stdout.trim();
26
+ }
27
+ async function updateCoreAtStartup(options) {
28
+ const npm = options.npm ?? runNpm;
29
+ try {
30
+ const globalRoot = options.globalRoot ?? await npm(["root", "-g"]);
31
+ const packageRoot = (0, node_path_1.resolve)(options.packageRoot);
32
+ if (!await sameDirectory(packageRoot, (0, node_path_1.join)(globalRoot, "mu-agent-bridge")))
33
+ return false;
34
+ const metadata = JSON.parse(await (0, promises_1.readFile)((0, node_path_1.join)(packageRoot, "package.json"), "utf8"));
35
+ if (metadata.name !== "mu-agent-bridge" || !metadata.version)
36
+ throw new Error("当前全局核心包信息无效");
37
+ const rawVersion = await npm(["view", "mu-agent-bridge", "version", "--json"]);
38
+ const latestVersion = (() => { try {
39
+ return String(JSON.parse(rawVersion));
40
+ }
41
+ catch {
42
+ return rawVersion.replace(/^['\"]|['\"]$/g, "");
43
+ } })();
44
+ if ((0, version_manager_1.compareVersions)(latestVersion, metadata.version) <= 0)
45
+ return false;
46
+ options.log?.("info", "发现 daemon 新版本,开始自动升级", { currentVersion: metadata.version, latestVersion });
47
+ await (0, promises_1.mkdir)(options.stateDir, { recursive: true });
48
+ const backupRoot = await (0, promises_1.mkdtemp)((0, node_path_1.join)(options.stateDir, "mab-core-update-"));
49
+ const backup = (0, node_path_1.join)(backupRoot, "package");
50
+ await (0, promises_1.cp)(packageRoot, backup, { recursive: true });
51
+ try {
52
+ await options.stopDaemon();
53
+ await npm(["install", "-g", `mu-agent-bridge@${latestVersion}`, "--no-fund", "--no-audit"]);
54
+ const installed = JSON.parse(await (0, promises_1.readFile)((0, node_path_1.join)(packageRoot, "package.json"), "utf8"));
55
+ if (installed.name !== "mu-agent-bridge" || installed.version !== latestVersion)
56
+ throw new Error(`核心安装结果不匹配:${installed.version ?? "未知版本"}`);
57
+ await options.startDaemon();
58
+ if (!await options.waitForHealth())
59
+ throw new Error("新 daemon 健康检查失败");
60
+ options.log?.("info", "daemon 自动升级成功", { version: latestVersion });
61
+ await (0, promises_1.rm)(backupRoot, { recursive: true, force: true });
62
+ return true;
63
+ }
64
+ catch (error) {
65
+ await options.stopDaemon().catch(() => undefined);
66
+ await (0, promises_1.rm)(packageRoot, { recursive: true, force: true });
67
+ await (0, promises_1.cp)(backup, packageRoot, { recursive: true });
68
+ options.log?.("error", "daemon 自动升级失败,已恢复旧版本", { error: error instanceof Error ? error.message : String(error), version: metadata.version });
69
+ await (0, promises_1.rm)(backupRoot, { recursive: true, force: true });
70
+ return false;
71
+ }
72
+ }
73
+ catch (error) {
74
+ options.log?.("warn", "daemon 自动升级检查失败,继续使用当前版本", { error: error instanceof Error ? error.message : String(error) });
75
+ return false;
76
+ }
77
+ }
@@ -462,13 +462,13 @@ async function withAunAttachmentPlugin(run, publish, config = { allow_from: "pee
462
462
  strict_1.default.match(bound.body.message, /AID 不在本地密钥库中/);
463
463
  strict_1.default.deepEqual(bound.body.data, { aid: "missing.agentid.cn", agent: "qwenwork", bindingState: { aunAids: [], agentAid: "old.agentid.cn" } });
464
464
  const created = await runAunCommand(routes, commandResponse(), ["create", "new.agentid.cn", "--owner", "owner.agentid.cn", "--agent", "qwenwork"]);
465
- strict_1.default.equal(created.statusCode, 502);
465
+ strict_1.default.equal(created.statusCode, 200);
466
466
  strict_1.default.equal(created.body.data.created, true);
467
- strict_1.default.deepEqual(created.body.data.bindingState, { aunAids: ["new.agentid.cn"], agentAid: "old.agentid.cn" });
468
- const unbound = await runAunCommand(routes, commandResponse(), ["unbind", "qwenwork"]);
469
- strict_1.default.equal(unbound.statusCode, 400);
470
- strict_1.default.equal(unbound.body.ok, false);
471
- strict_1.default.deepEqual(unbound.body.data.bindingState, { aunAids: [], agentAid: "old.agentid.cn" });
467
+ strict_1.default.equal(created.body.data.agent, "qwenwork");
468
+ strict_1.default.equal((await plugin.health()).details?.bindings?.["new.agentid.cn"], "qwenwork");
469
+ const unbound = await runAunCommand(routes, commandResponse(), ["unbind", "new.agentid.cn"]);
470
+ strict_1.default.equal(unbound.statusCode, 200);
471
+ strict_1.default.deepEqual((await plugin.health()).details?.bindings, {});
472
472
  }
473
473
  finally {
474
474
  await server.stop();
@@ -636,8 +636,13 @@ async function withAunAttachmentPlugin(run, publish, config = { allow_from: "pee
636
636
  return new Response(JSON.stringify({ ok: true, bindings: currentAid ? { [currentAid]: "qwenwork" } : {} }), { status: 200 });
637
637
  if (url.endsWith("/config"))
638
638
  return new Response(JSON.stringify({ aid: currentAid }), { status: 200 });
639
- if (init?.method === "PATCH")
639
+ if (init?.method === "PATCH") {
640
640
  currentAid = JSON.parse(String(init.body)).aid;
641
+ if (currentAid)
642
+ plugin.bindings[currentAid] = "qwenwork";
643
+ }
644
+ if (init?.method === "POST" && url.endsWith("/api/plugins/aun/unbind"))
645
+ delete plugin.bindings[JSON.parse(String(init.body)).aid];
641
646
  return new Response(JSON.stringify({ ok: true }), { status: 200 });
642
647
  });
643
648
  await plugin.activate({ dataDir: root, config: {}, logger: { info(message, fields) { logs.push(JSON.stringify([message, fields])); }, warn(message, fields) { logs.push(JSON.stringify([message, fields])); }, error(message, fields) { logs.push(JSON.stringify([message, fields])); } }, callPlugin: async () => ({ text: "" }), pluginStatus: () => "ready", http: {
@@ -650,19 +655,18 @@ async function withAunAttachmentPlugin(run, publish, config = { allow_from: "pee
650
655
  const created = await runAunCommand(routes, commandResponse(), ["create", "new.agentid.cn", "--owner", "owner.agentid.cn", "--agent", "qwenwork"]);
651
656
  strict_1.default.equal(created.body.ok, true);
652
657
  strict_1.default.equal(created.body.data.created, true);
653
- strict_1.default.deepEqual(created.body.data.replacedAids, ["old.agentid.cn"]);
654
- strict_1.default.match(created.body.message, /old\.agentid\.cn.*new\.agentid\.cn/);
658
+ strict_1.default.equal(created.body.data.agent, "qwenwork");
659
+ strict_1.default.doesNotMatch(created.body.message, /old\.agentid\.cn/);
655
660
  const bound = await runAunCommand(routes, commandResponse(), ["bind", "new.agentid.cn", "qwenwork"]);
656
661
  strict_1.default.equal(bound.body.ok, true);
657
- strict_1.default.deepEqual(bound.body.data.replacedAids, []);
658
- const unbound = await runAunCommand(routes, commandResponse(), ["unbind", "qwenwork"]);
662
+ strict_1.default.deepEqual(bound.body.data, { aid: "new.agentid.cn", agent: "qwenwork" });
663
+ const unbound = await runAunCommand(routes, commandResponse(), ["unbind", "new.agentid.cn"]);
659
664
  strict_1.default.equal(unbound.body.ok, true);
660
- strict_1.default.deepEqual(unbound.body.data.unboundAids, ["new.agentid.cn"]);
665
+ strict_1.default.deepEqual(unbound.body.data, { aid: "new.agentid.cn", agent: "qwenwork" });
661
666
  const patches = requests.filter((request) => request.method === "PATCH");
662
667
  strict_1.default.deepEqual(patches.map(({ url, body }) => [url, JSON.parse(body)]), [
663
668
  ["http://127.0.0.1:3021/api/plugins/qwenwork/aid", { aid: "new.agentid.cn" }],
664
669
  ["http://127.0.0.1:3021/api/plugins/qwenwork/aid", { aid: "new.agentid.cn" }],
665
- ["http://127.0.0.1:3021/api/plugins/qwenwork/aid", { aid: "" }],
666
670
  ]);
667
671
  strict_1.default.ok(requests.every(({ url }) => new URL(url).hostname === "127.0.0.1"));
668
672
  strict_1.default.ok(requests.every(({ signal }) => signal instanceof AbortSignal));
@@ -730,10 +734,11 @@ async function withAunAttachmentPlugin(run, publish, config = { allow_from: "pee
730
734
  const failedBind = await runAunCommand(routes, commandResponse(), ["bind", "existing.agentid.cn", "qwenwork"]);
731
735
  strict_1.default.equal(failedBind.statusCode, 502);
732
736
  strict_1.default.deepEqual(failedBind.body.data.bindingState, { aunAids: ["new.agentid.cn"], agentAid: "old.agentid.cn" });
733
- const failedUnbind = await runAunCommand(routes, commandResponse(), ["unbind", "qwenwork"]);
734
- strict_1.default.equal(failedUnbind.statusCode, 502);
735
- strict_1.default.deepEqual(failedUnbind.body.data.bindingState, { aunAids: ["new.agentid.cn"], agentAid: "old.agentid.cn" });
736
- strict_1.default.equal(patchCalls, 3);
737
+ plugin.bindings["new.agentid.cn"] = "qwenwork";
738
+ const unbound = await runAunCommand(routes, commandResponse(), ["unbind", "new.agentid.cn"]);
739
+ strict_1.default.equal(unbound.statusCode, 200);
740
+ strict_1.default.deepEqual((await plugin.health()).details?.bindings, {});
741
+ strict_1.default.equal(patchCalls, 2, "解绑 AUN 映射不得改写 Agent 全局配置");
737
742
  const malformed = await runAunCommand(routes, commandResponse(), ["unknown"]);
738
743
  strict_1.default.equal(malformed.statusCode, 400);
739
744
  strict_1.default.equal(malformed.body.ok, false);
@@ -768,7 +773,7 @@ async function withAunAttachmentPlugin(run, publish, config = { allow_from: "pee
768
773
  const plugin = new aun_1.AunPlugin({ sdk, ingress: { publish: async () => undefined } });
769
774
  try {
770
775
  await plugin.activate({ dataDir: root, config: {}, logger: { info() { }, warn() { }, error() { } }, callPlugin: async () => ({ text: "" }), pluginStatus: () => "ready", http: { register(route) { routes.set(`${route.method} ${route.path}`, route.handler); return () => undefined; }, unregister() { } } });
771
- for (const argv of [["agents"], ["bind", "valid.agentid.cn", "qwenwork"], ["unbind", "qwenwork"]]) {
776
+ for (const argv of [["agents"], ["bind", "valid.agentid.cn", "qwenwork"]]) {
772
777
  const result = await runAunCommand(routes, commandResponse(), argv);
773
778
  strict_1.default.equal(result.statusCode, 502);
774
779
  strict_1.default.equal(result.body.ok, false);
@@ -852,7 +857,7 @@ async function withAunAttachmentPlugin(run, publish, config = { allow_from: "pee
852
857
  fetch: async (path) => ({ ok: true, json: async () => path.endsWith("/identities") ? identities : path === "/api/plugins" ? { plugins: agents } : path.includes("qwenwork") ? { aid: "external.agentid.cn" } : {} }),
853
858
  });
854
859
  await new Promise((resolve) => setImmediate(resolve));
855
- strict_1.default.deepEqual(elements.get("#identities").children.map((row) => row.children[0].textContent), ["new.agentid.cn", "old.agentid.cn", "unknown.agentid.cn", "external.agentid.cn", "offline-order.agentid.cn"]);
860
+ strict_1.default.deepEqual(elements.get("#identities").children.map((row) => row.children[0].textContent), ["new.agentid.cn", "old.agentid.cn", "unknown.agentid.cn", "offline-order.agentid.cn", "external.agentid.cn"]);
856
861
  });
857
862
  (0, node_test_1.default)("AUN 页面跨来源重复 AID 只显示本工程归属", async () => {
858
863
  const node = () => ({ children: [], elements: new Proxy({}, { get: () => ({ value: "", replaceChildren() { } }) }), append(...items) { this.children.push(...items); }, replaceChildren(...items) { this.children = items; }, setAttribute() { } });
@@ -281,7 +281,9 @@ const plugin_manager_1 = require("../src-ts/plugin-manager");
281
281
  const bound = await fetch(`${base}/api/plugins/dsh/aid`, { method: "PATCH", headers: { "content-type": "application/json" }, body: JSON.stringify({ aid: "new.agentid.cn" }) });
282
282
  strict_1.default.equal(bound.status, 200);
283
283
  strict_1.default.deepEqual(calls[1], ["dsh", "new.agentid.cn", address.port]);
284
- strict_1.default.deepEqual(calls[2], ["dsh", "new.agentid.cn"]);
284
+ strict_1.default.equal(calls.length, 2, "AUN 关联不得改写 Agent 插件的全局 AID 配置");
285
+ const broadUnbind = await fetch(`${base}/api/plugins/dsh/aid`, { method: "PATCH", headers: { "content-type": "application/json" }, body: JSON.stringify({ aid: "" }) });
286
+ strict_1.default.equal(broadUnbind.status, 400, "解绑必须指定 AID");
285
287
  }
286
288
  finally {
287
289
  await server.stop();
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const strict_1 = __importDefault(require("node:assert/strict"));
7
+ const promises_1 = require("node:fs/promises");
8
+ const node_os_1 = require("node:os");
9
+ const node_path_1 = require("node:path");
10
+ const node_test_1 = __importDefault(require("node:test"));
11
+ const core_updater_1 = require("../src-ts/core-updater");
12
+ async function fixture() {
13
+ const root = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "mab-core-update-"));
14
+ const packageRoot = (0, node_path_1.join)(root, "node_modules", "mu-agent-bridge");
15
+ const globalRoot = (0, node_path_1.join)(root, "node_modules");
16
+ await (0, promises_1.mkdir)((0, node_path_1.join)(packageRoot, "dist", "src-ts"), { recursive: true });
17
+ await (0, promises_1.writeFile)((0, node_path_1.join)(packageRoot, "package.json"), JSON.stringify({ name: "mu-agent-bridge", version: "1.0.0" }));
18
+ await (0, promises_1.writeFile)((0, node_path_1.join)(packageRoot, "dist", "src-ts", "cli.js"), "old");
19
+ return { root, packageRoot, globalRoot };
20
+ }
21
+ (0, node_test_1.default)("mab start 在核心有新版本时安装、启动并等待健康检查", async () => {
22
+ const value = await fixture();
23
+ const events = [];
24
+ try {
25
+ const updated = await (0, core_updater_1.updateCoreAtStartup)({
26
+ packageRoot: value.packageRoot,
27
+ globalRoot: value.globalRoot,
28
+ stateDir: (0, node_path_1.join)(value.root, "state"),
29
+ npm: async (args) => {
30
+ events.push(args.join(" "));
31
+ if (args[0] === "view")
32
+ return '"1.1.0"';
33
+ await (0, promises_1.writeFile)((0, node_path_1.join)(value.packageRoot, "package.json"), JSON.stringify({ name: "mu-agent-bridge", version: "1.1.0" }));
34
+ await (0, promises_1.writeFile)((0, node_path_1.join)(value.packageRoot, "dist", "src-ts", "cli.js"), "new");
35
+ return "";
36
+ },
37
+ stopDaemon: async () => { events.push("stop"); },
38
+ startDaemon: async () => { events.push("start"); },
39
+ waitForHealth: async () => true,
40
+ });
41
+ strict_1.default.equal(updated, true);
42
+ strict_1.default.equal(JSON.parse(await (0, promises_1.readFile)((0, node_path_1.join)(value.packageRoot, "package.json"), "utf8")).version, "1.1.0");
43
+ strict_1.default.deepEqual(events, ["view mu-agent-bridge version --json", "stop", "install -g mu-agent-bridge@1.1.0 --no-fund --no-audit", "start"]);
44
+ }
45
+ finally {
46
+ await (0, promises_1.rm)(value.root, { recursive: true, force: true });
47
+ }
48
+ });
49
+ (0, node_test_1.default)("新 daemon 健康检查失败时恢复旧核心包并继续旧进程", async () => {
50
+ const value = await fixture();
51
+ try {
52
+ const updated = await (0, core_updater_1.updateCoreAtStartup)({
53
+ packageRoot: value.packageRoot,
54
+ globalRoot: value.globalRoot,
55
+ stateDir: (0, node_path_1.join)(value.root, "state"),
56
+ npm: async (args) => {
57
+ if (args[0] === "view")
58
+ return '"1.1.0"';
59
+ await (0, promises_1.writeFile)((0, node_path_1.join)(value.packageRoot, "package.json"), JSON.stringify({ name: "mu-agent-bridge", version: "1.1.0" }));
60
+ return "";
61
+ },
62
+ stopDaemon: async () => undefined,
63
+ startDaemon: async () => undefined,
64
+ waitForHealth: async () => false,
65
+ });
66
+ strict_1.default.equal(updated, false);
67
+ strict_1.default.equal(JSON.parse(await (0, promises_1.readFile)((0, node_path_1.join)(value.packageRoot, "package.json"), "utf8")).version, "1.0.0");
68
+ }
69
+ finally {
70
+ await (0, promises_1.rm)(value.root, { recursive: true, force: true });
71
+ }
72
+ });
73
+ (0, node_test_1.default)("核心已是最新或不是 npm 全局安装时不停止 daemon", async () => {
74
+ const value = await fixture();
75
+ let stops = 0;
76
+ try {
77
+ const current = await (0, core_updater_1.updateCoreAtStartup)({ packageRoot: value.packageRoot, globalRoot: value.globalRoot, stateDir: (0, node_path_1.join)(value.root, "state"), npm: async () => '"1.0.0"', stopDaemon: async () => { stops++; }, startDaemon: async () => undefined, waitForHealth: async () => true });
78
+ const local = await (0, core_updater_1.updateCoreAtStartup)({ packageRoot: value.packageRoot, globalRoot: value.root, stateDir: (0, node_path_1.join)(value.root, "state"), npm: async () => '"2.0.0"', stopDaemon: async () => { stops++; }, startDaemon: async () => undefined, waitForHealth: async () => true });
79
+ strict_1.default.equal(current, false);
80
+ strict_1.default.equal(local, false);
81
+ strict_1.default.equal(stops, 0);
82
+ }
83
+ finally {
84
+ await (0, promises_1.rm)(value.root, { recursive: true, force: true });
85
+ }
86
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mu-agent-bridge",
3
- "version": "1.0.44",
3
+ "version": "1.0.45",
4
4
  "description": "将 AUN Agent 连接到本地桌面 AI 客户端的插件平台。",
5
5
  "main": "dist/src-ts/cli.js",
6
6
  "bin": {