mu-agent-bridge 1.0.64 → 1.0.65

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.
@@ -802,7 +802,8 @@ class PluginManager {
802
802
  async discoverDirectory(directory, label, manifestFile = (0, node_path_1.join)(directory, "plugin.json")) {
803
803
  try {
804
804
  const manifest = (0, plugin_manifest_1.validateManifest)(JSON.parse(await (0, promises_1.readFile)(manifestFile, "utf8")), directory);
805
- if (this.plugins.has(manifest.id))
805
+ const existing = this.plugins.get(manifest.id);
806
+ if (existing && (existing.instance || (0, node_path_1.resolve)(existing.record.path) === (0, node_path_1.resolve)(directory)))
806
807
  return;
807
808
  let packageName;
808
809
  let coreConstraint;
@@ -821,6 +822,20 @@ class PluginManager {
821
822
  const coreVersion = require((0, node_path_1.resolve)(__dirname, "../../package.json")).version;
822
823
  const error = coreConstraint && !(0, version_manager_1.satisfiesVersion)(coreVersion, coreConstraint) ? `核心版本 ${coreVersion} 不满足插件要求 ${coreConstraint}` : undefined;
823
824
  const record = { id: manifest.id, version: manifest.version, type: manifest.type ?? "other", displayName: manifest.displayName ?? manifest.id, status: error ? "failed" : "discovered", capabilities: manifest.capabilities, manifest, path: directory, ...(packageName ? { packageName } : {}), ...(coreConstraint ? { coreConstraint } : {}), ...(error ? { error } : {}) };
825
+ if (existing) {
826
+ const versionOrder = (0, version_manager_1.compareVersions)(record.version, existing.record.version);
827
+ const candidateManaged = (0, node_path_1.resolve)(directory).startsWith(`${(0, node_path_1.resolve)(this.options.stateDir, "npm")}${node_path_1.sep}`);
828
+ const existingManaged = (0, node_path_1.resolve)(existing.record.path).startsWith(`${(0, node_path_1.resolve)(this.options.stateDir, "npm")}${node_path_1.sep}`);
829
+ // 新版本优先;同版本保留托管包,避免核心内置旧副本遮蔽显式安装包。
830
+ const existingFailed = existing.record.status === "failed";
831
+ const candidateFailed = record.status === "failed";
832
+ const keepExisting = candidateFailed !== existingFailed ? candidateFailed : versionOrder < 0 || (versionOrder === 0 && (!candidateManaged || existingManaged));
833
+ if (keepExisting) {
834
+ this.log("info", "忽略插件候选,保留当前可用版本", { id: manifest.id, ignoredPath: directory, ignoredVersion: record.version, selectedVersion: existing.record.version, reason: record.error }, "插件发现");
835
+ return;
836
+ }
837
+ this.log("info", "插件候选已替换", { id: manifest.id, ignoredPath: existing.record.path, ignoredVersion: existing.record.version, selectedVersion: record.version }, "插件发现");
838
+ }
824
839
  this.applyPluginTrust(record);
825
840
  this.plugins.set(manifest.id, { record });
826
841
  if (packageName && /^agent-bridge-[a-z0-9-]+$/.test(packageName)) {
@@ -12,7 +12,7 @@ const agent_1 = require("../../agent");
12
12
  const messages_1 = require("./messages");
13
13
  const attachments_1 = require("./attachments");
14
14
  const manifest = {
15
- id: "aun", version: "1.0.33", type: "channel", displayName: "AUN 通道",
15
+ id: "aun", version: "1.0.34", type: "channel", displayName: "AUN 通道",
16
16
  entry: "dist/src-ts/plugins/aun/index.js", apiVersion: "1", process: "in-process",
17
17
  capabilities: ["channel", "channel.identity.create", "channel.receive", "channel.send", "health", "cli"],
18
18
  configSchema: "config.schema.json",
@@ -86,7 +86,7 @@ class AunPlugin {
86
86
  const known = new Set([...this.clients.keys(), ...this.listStoreAids()]);
87
87
  return {
88
88
  evolcore: [...known].filter((aid) => !own.has(aid)).sort(),
89
- muAgentBridge: [...this.clients.keys()].filter((aid) => own.has(aid)).sort(),
89
+ muAgentBridge: [...known].filter((aid) => own.has(aid)).sort(),
90
90
  localMuAgentBridge: [...own].filter((aid) => !known.has(aid)).sort(),
91
91
  };
92
92
  },
@@ -125,42 +125,29 @@ class AunPlugin {
125
125
  }
126
126
  },
127
127
  bind: async (pluginId, aid, _port) => {
128
+ if (!aid || !aidPattern.test(aid))
129
+ throw new Error("AID 格式无效,必须指定要关联的 AID");
128
130
  if (pluginId === "aun" || pluginId === "abweb")
129
131
  throw new Error("只能关联 Agent 插件");
132
+ if (this.context?.pluginStatus(pluginId) !== "ready")
133
+ throw new Error("目标 Agent 插件未启动");
130
134
  const previous = this.bindings;
131
135
  const previousTimes = this.bindingTimes;
132
- this.bindings = { ...previous };
133
- this.bindingTimes = { ...previousTimes };
136
+ const connection = this.clients.get(aid);
137
+ const hadIdentity = this.identities.has(aid);
138
+ const hadSubscription = Boolean(connection?.subscription);
134
139
  try {
135
- if (aid) {
136
- if (!aidPattern.test(aid))
137
- throw new Error("AID 格式无效");
138
- if (this.context?.pluginStatus(pluginId) !== "ready")
139
- throw new Error("目标 Agent 插件未启动");
140
- if (this.identities.has(aid) || this.legacyCreatedAids.has(aid)) {
141
- if (!this.clients.has(aid))
142
- await this.connectAid(aid);
143
- if (!this.clients.has(aid))
144
- throw new Error("AID 当前未连接");
145
- this.bindings[aid] = pluginId;
146
- }
147
- else {
148
- // 本地身份由插件直接接管,不再通过 ec 配置路由。
149
- const loaded = this.store.load(aid);
150
- if (!loaded.ok || !loaded.data)
151
- throw new Error("AID 不在本地密钥库中,无法关联");
152
- this.identities.add(aid);
153
- if (!this.clients.has(aid))
154
- await this.connectAid(aid);
155
- if (!this.clients.has(aid))
156
- throw new Error("AID 当前未连接");
157
- this.bindings[aid] = pluginId;
158
- }
159
- }
160
- else
161
- throw new Error("必须指定要关联的 AID");
162
- if (aid)
163
- this.bindingTimes[aid] = new Date().toISOString();
140
+ const loaded = this.store.load(aid);
141
+ if (!loaded.ok || !loaded.data)
142
+ throw new Error("AID 不在本地密钥库中,无法关联");
143
+ this.identities.add(aid);
144
+ if (!connection)
145
+ await this.connectAid(aid);
146
+ if (!this.clients.has(aid))
147
+ throw new Error("AID 当前未连接");
148
+ this.bindings = { ...previous, [aid]: pluginId };
149
+ this.bindingTimes = { ...previousTimes, [aid]: new Date().toISOString() };
150
+ this.subscribeAid(aid);
164
151
  await this.persist();
165
152
  }
166
153
  catch (error) {
@@ -168,6 +155,29 @@ class AunPlugin {
168
155
  this.bindingTimes = previousTimes;
169
156
  this.config.bindings = previous;
170
157
  this.config.binding_times = previousTimes;
158
+ if (!hadIdentity)
159
+ this.identities.delete(aid);
160
+ this.config.identities = [...this.identities].sort();
161
+ if (!hadSubscription) {
162
+ this.clients.get(aid)?.subscription?.unsubscribe();
163
+ if (connection)
164
+ connection.subscription = undefined;
165
+ }
166
+ if (!connection) {
167
+ try {
168
+ await this.clients.get(aid)?.client.close();
169
+ }
170
+ catch (closeError) {
171
+ this.context?.logger.warn("AUN 关联回滚关闭连接失败", { aid, error: safeError(closeError) });
172
+ }
173
+ finally {
174
+ this.clients.delete(aid);
175
+ if (!this.clients.size) {
176
+ this.status = "degraded";
177
+ this.healthMessage = "暂无已连接 AID";
178
+ }
179
+ }
180
+ }
171
181
  this.context?.logger.error("AUN 身份关联失败", { aid, pluginId, error: safeError(error) });
172
182
  throw error;
173
183
  }
@@ -178,6 +188,8 @@ class AunPlugin {
178
188
  throw new Error("AID 格式无效");
179
189
  if (this.bindings[aid] !== pluginId)
180
190
  throw new Error("指定 AID 当前未关联到该 Agent");
191
+ if ([...this.pendingMessages.keys()].some(key => JSON.parse(key)[0] === aid))
192
+ throw new Error("该 AID 正在处理消息,请等待任务完成后再解绑");
181
193
  const previous = this.bindings;
182
194
  const previousTimes = this.bindingTimes;
183
195
  this.bindings = { ...previous };
@@ -194,6 +206,21 @@ class AunPlugin {
194
206
  this.config.binding_times = previousTimes;
195
207
  throw error;
196
208
  }
209
+ const connection = this.clients.get(aid);
210
+ connection?.subscription?.unsubscribe();
211
+ try {
212
+ await connection?.client.close();
213
+ }
214
+ catch (error) {
215
+ this.context?.logger.warn("AUN 解绑已完成,关闭连接失败", { aid, pluginId, error: safeError(error) });
216
+ }
217
+ finally {
218
+ this.clients.delete(aid);
219
+ if (!this.clients.size) {
220
+ this.status = "degraded";
221
+ this.healthMessage = "暂无已连接 AID";
222
+ }
223
+ }
197
224
  this.context?.logger.info("AUN 单个身份关联已解除", { aid, pluginId });
198
225
  },
199
226
  };
@@ -207,6 +234,7 @@ class AunPlugin {
207
234
  async activate(context) {
208
235
  this.context = context;
209
236
  this.config = { ...context.config };
237
+ this.identities.clear();
210
238
  this.legacyCreatedAids.clear();
211
239
  this.createdAids.clear();
212
240
  try {
@@ -266,15 +294,25 @@ class AunPlugin {
266
294
  if (this.aid)
267
295
  this.identities.add(this.aid);
268
296
  this.acceptingMessages = true;
269
- for (const aid of this.identities)
270
- await this.connectAid(aid);
271
- // 密钥库中的其余 AID 也自动连接:不再依赖 ec 或 EvolCore 进程
272
- for (const aid of this.listStoreAids()) {
273
- this.identities.add(aid);
274
- if (!this.clients.has(aid))
297
+ // 只订阅明确关联 Agent 的身份,避免接管 EvolCore 或其它 AID 的消息。
298
+ for (const aid of Object.keys(this.bindings)) {
299
+ const target = this.bindings[aid];
300
+ if (!target || !context.pluginStatus(target)) {
301
+ context.logger.warn("AUN 跳过目标插件不存在的旧绑定,未连接身份", { aid, agentPlugin: target });
302
+ continue;
303
+ }
304
+ if (context.pluginStatus(target) !== "ready")
305
+ context.logger.warn("AUN 恢复已有显式绑定,目标插件尚未就绪;关联保持不变", { aid, agentPlugin: target, status: context.pluginStatus(target) });
306
+ if (aidPattern.test(aid))
275
307
  await this.connectAid(aid);
276
308
  }
277
309
  }
310
+ subscribeAid(aid) {
311
+ const connection = this.clients.get(aid);
312
+ if (!connection || connection.subscription || !this.bindings[aid])
313
+ return;
314
+ connection.subscription = connection.client.on("message.received", (payload) => this.onMessage(payload, aid));
315
+ }
278
316
  async connectAid(aid) {
279
317
  try {
280
318
  await this.prepareTrustRoots(aid);
@@ -282,7 +320,7 @@ class AunPlugin {
282
320
  if (!loaded.ok || !loaded.data)
283
321
  throw new Error(loaded.error?.message ?? "本地密钥库中不存在该 AID");
284
322
  const client = new this.sdk.AUNClient(loaded.data.aid);
285
- const subscription = this.identities.has(aid) || this.legacyCreatedAids.has(aid)
323
+ const subscription = this.bindings[aid]
286
324
  ? client.on("message.received", (payload) => this.onMessage(payload, aid))
287
325
  : undefined;
288
326
  try {
@@ -86,9 +86,14 @@ async function runAunCommand(routes, response, argv) {
86
86
  close() { }
87
87
  },
88
88
  AUNClient: class {
89
+ aid;
89
90
  async connect() { }
90
91
  async close() { }
91
- on(_event, handler) { receive = handler; return { unsubscribe() { } }; }
92
+ constructor(aid) {
93
+ this.aid = aid;
94
+ }
95
+ on(_event, handler) { if (this.aid === "selected.agentid.cn")
96
+ receive = handler; return { unsubscribe() { } }; }
92
97
  async call(_method, params) { sent.push(params); }
93
98
  },
94
99
  };
@@ -142,7 +147,10 @@ async function withAunAttachmentPlugin(run, publish, config = { allow_from: "pee
142
147
  const plugin = new aun_1.AunPlugin({ sdk, ingress: { publish } });
143
148
  try {
144
149
  await plugin.activate({ dataDir: root, config, logger, callPlugin: async () => ({ text: "" }), pluginStatus: () => "ready", http: { register() { }, unregister() { } } });
145
- await run(async (payload) => { await handler(payload); }, sent, storage, logs);
150
+ if (!Object.keys(config.bindings ?? {}).length)
151
+ strict_1.default.equal(handler, undefined);
152
+ await run(async (payload) => { if (handler)
153
+ await handler(payload); }, sent, storage, logs, plugin);
146
154
  }
147
155
  finally {
148
156
  await plugin.deactivate("stop");
@@ -361,7 +369,7 @@ async function withAunAttachmentPlugin(run, publish, config = { allow_from: "pee
361
369
  await plugin.activate({ dataDir: root, config: { identities: [aids[0]] }, logger: { info() { }, warn() { }, error() { } }, callPlugin: async () => ({ text: "" }), pluginStatus: () => "ready", http: {
362
370
  register(route) { routes.set(`${route.method} ${route.path}`, route.handler); return () => undefined; }, unregister() { },
363
371
  } });
364
- strict_1.default.deepEqual(connects, aids);
372
+ strict_1.default.deepEqual(connects, []);
365
373
  for (const aid of aids) {
366
374
  const result = await runAunCommand(routes, commandResponse(), ["create", aid, "--owner", "owner.agentid.cn"]);
367
375
  strict_1.default.equal(result.statusCode, 200);
@@ -937,7 +945,7 @@ async function withAunAttachmentPlugin(run, publish, config = { allow_from: "pee
937
945
  const plugin = new aun_1.AunPlugin({ sdk, ingress: { publish: async () => undefined } });
938
946
  try {
939
947
  process.env.EVOLCORE_HOME = aunPath;
940
- await plugin.activate({ dataDir, config: {}, logger: { info() { }, warn() { }, error() { } }, callPlugin: async () => ({ text: "" }), pluginStatus: () => "ready", http: { register() { }, unregister() { } } });
948
+ await plugin.activate({ dataDir, config: { bindings: { "existing.agentid.cn": "workbuddy" } }, logger: { info() { }, warn() { }, error() { } }, callPlugin: async () => ({ text: "" }), pluginStatus: () => "ready", http: { register() { }, unregister() { } } });
941
949
  strict_1.default.deepEqual(connects, ["existing.agentid.cn"]);
942
950
  strict_1.default.deepEqual(subscriptions, ["existing.agentid.cn"]);
943
951
  strict_1.default.deepEqual(await plugin.identity.list(), { evolcore: ["existing.agentid.cn"], muAgentBridge: [], localMuAgentBridge: [] });
@@ -991,7 +999,41 @@ async function withAunAttachmentPlugin(run, publish, config = { allow_from: "pee
991
999
  await (0, promises_1.rm)(root, { recursive: true, force: true });
992
1000
  }
993
1001
  });
994
- (0, node_test_1.default)("共享密钥库中的 AID 自动连接并保留 EvolCore 来源", async () => {
1002
+ (0, node_test_1.default)("AUN 启动只连接显式绑定身份,旧 identities 不接管共享密钥库", async () => {
1003
+ const root = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "aun-explicit-only-"));
1004
+ const connected = [];
1005
+ const closed = [];
1006
+ const sdk = {
1007
+ AIDStore: class {
1008
+ list() { return { ok: true, data: { identities: ["selected.agentid.cn", "external.agentid.cn"].map(aid => ({ aid })) } }; }
1009
+ load(aid) { return { ok: true, data: { aid } }; }
1010
+ close() { }
1011
+ },
1012
+ AUNClient: class {
1013
+ aid;
1014
+ constructor(aid) {
1015
+ this.aid = aid;
1016
+ }
1017
+ on() { return { unsubscribe() { } }; }
1018
+ async connect() { connected.push(this.aid); }
1019
+ async close() { closed.push(this.aid); }
1020
+ },
1021
+ };
1022
+ const plugin = new aun_1.AunPlugin({ sdk, ingress: { publish: async () => undefined } });
1023
+ try {
1024
+ await plugin.activate({ dataDir: root, config: { aid: "external.agentid.cn", identities: ["external.agentid.cn"], bindings: { "selected.agentid.cn": "workbuddy" } }, logger: { info() { }, warn() { }, error() { } }, callPlugin: async () => ({ text: "" }), pluginStatus: () => "ready", http: { register() { }, unregister() { } } });
1025
+ strict_1.default.deepEqual(connected, ["selected.agentid.cn"]);
1026
+ strict_1.default.ok((await plugin.identity.list()).evolcore.includes("external.agentid.cn"));
1027
+ await plugin.identity.unbind("workbuddy", "selected.agentid.cn", 26107);
1028
+ strict_1.default.deepEqual(closed, ["selected.agentid.cn"]);
1029
+ strict_1.default.deepEqual((await plugin.health()).details?.bindings, {});
1030
+ }
1031
+ finally {
1032
+ await plugin.deactivate("stop");
1033
+ await (0, promises_1.rm)(root, { recursive: true, force: true });
1034
+ }
1035
+ });
1036
+ (0, node_test_1.default)("共享密钥库中的 AID 仅列出并保留 EvolCore 来源", async () => {
995
1037
  const root = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "aun-origin-"));
996
1038
  const dataDir = (0, node_path_1.join)(root, "aun");
997
1039
  await (0, promises_1.mkdir)(dataDir);
@@ -1046,14 +1088,14 @@ async function withAunAttachmentPlugin(run, publish, config = { allow_from: "pee
1046
1088
  try {
1047
1089
  await plugin.activate({ dataDir, config: { created_aids: ["created.agentid.cn"] }, logger: { info() { }, warn() { }, error() { } }, callPlugin: async () => ({ text: "" }), pluginStatus: () => "ready", http: { register() { }, unregister() { } } });
1048
1090
  strict_1.default.deepEqual(await plugin.identity.list(), { evolcore: ["shared.agentid.cn"], muAgentBridge: ["created.agentid.cn", "legacy.agentid.cn"], localMuAgentBridge: [] });
1049
- strict_1.default.deepEqual(subscriptions, storeIds);
1091
+ strict_1.default.deepEqual(subscriptions, []);
1050
1092
  await plugin.deactivate("stop");
1051
1093
  }
1052
1094
  finally {
1053
1095
  await (0, promises_1.rm)(root, { recursive: true, force: true });
1054
1096
  }
1055
1097
  });
1056
- (0, node_test_1.default)("默认密钥库指向共享 AUN 目录并自动连接其中全部 AID", async () => {
1098
+ (0, node_test_1.default)("默认共享 AUN 密钥库可列出全部 AID 但不自动连接", async () => {
1057
1099
  const root = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "aun-keystore-"));
1058
1100
  const dataDir = (0, node_path_1.join)(root, "aun");
1059
1101
  await (0, promises_1.mkdir)(dataDir);
@@ -1078,9 +1120,9 @@ async function withAunAttachmentPlugin(run, publish, config = { allow_from: "pee
1078
1120
  try {
1079
1121
  await plugin.activate({ dataDir, config: {}, logger: { info() { }, warn() { }, error() { } }, callPlugin: async () => ({ text: "" }), pluginStatus: () => "ready", http: { register() { }, unregister() { } } });
1080
1122
  strict_1.default.equal(plugin.path(), root);
1081
- // 密钥库中的全部 AID 在启动时自动连接,无需 ec 或手动关联
1123
+ // 共享密钥库中的身份可见,但未手动绑定时不建立连接。
1082
1124
  strict_1.default.deepEqual((await plugin.identity.list()).evolcore, ["devwin.agentid.cn", "qwenwork.agentid.cn"]);
1083
- strict_1.default.equal(clients.length, 2);
1125
+ strict_1.default.equal(clients.length, 0);
1084
1126
  }
1085
1127
  finally {
1086
1128
  delete process.env.AUN_HOME;
@@ -1137,18 +1179,18 @@ async function withAunAttachmentPlugin(run, publish, config = { allow_from: "pee
1137
1179
  const second = (async function* () { yield Buffer.from('{"aid":"second.agentid.pub","owner_aid":"owner.agentid.pub"}'); })();
1138
1180
  await route.handler(second, response);
1139
1181
  strict_1.default.equal(response.statusCode, 201);
1140
- // bridge、second 已连接;offline-store 在首次 activate 时即自动连接
1141
- strict_1.default.equal(clients.length, 3);
1182
+ // 只有显式创建的 bridge、second 建立连接,尚未订阅消息。
1183
+ strict_1.default.equal(clients.length, 2);
1142
1184
  // 关联不再调用 ec:AID 在本地密钥库即可直接绑定
1143
1185
  await plugin.identity.bind("dsh", "bridge.agentid.pub", 26107);
1144
1186
  const boundAt = JSON.parse(await (0, promises_1.readFile)((0, node_path_1.join)(root, "config.json"), "utf8")).binding_times["bridge.agentid.pub"];
1145
1187
  strict_1.default.ok(Number.isFinite(Date.parse(boundAt)));
1146
- // 密钥库中的 offline-store 已自动连接,绑定只更新关联记录
1188
+ // 首次绑定共享身份时才建立连接并订阅消息。
1147
1189
  await plugin.identity.bind("doubao", "offline-store.agentid.cn", 26107);
1148
1190
  strict_1.default.ok(JSON.parse(await (0, promises_1.readFile)((0, node_path_1.join)(root, "config.json"), "utf8")).bindings["offline-store.agentid.cn"]);
1149
1191
  strict_1.default.equal(clients.length, 3);
1150
- // 自动连接时 offline-store 先建立连接,bridge 是第二个客户端
1151
- const bridgeClient = clients[1];
1192
+ // bridge 是本次显式创建的第一个客户端。
1193
+ const bridgeClient = clients[0];
1152
1194
  await bridgeClient.emit({ from: "peer.agentid.pub", message_id: "m1", payload: { text: "你好" } });
1153
1195
  strict_1.default.equal(received[0].agentPlugin, "dsh");
1154
1196
  await received[0].reply("收到");
@@ -1162,11 +1204,11 @@ async function withAunAttachmentPlugin(run, publish, config = { allow_from: "pee
1162
1204
  strict_1.default.equal(calls.filter((call) => call === "client.close").length, 3);
1163
1205
  strict_1.default.equal(calls.at(-1), "store.close");
1164
1206
  await plugin.activate({ dataDir: root, config: JSON.parse(await (0, promises_1.readFile)((0, node_path_1.join)(root, "config.json"), "utf8")), logger: { info() { }, warn() { }, error() { } }, callPlugin: async () => ({ text: "" }), pluginStatus: () => "ready", http: { register() { }, unregister() { } } });
1165
- // 重启后 identities 已含全部三个 AID,各自恢复连接
1166
- strict_1.default.equal(clients.length, 6);
1207
+ // 重启后只恢复两个显式绑定的身份。
1208
+ strict_1.default.equal(clients.length, 5);
1167
1209
  const health = await plugin.health();
1168
- // 自动连接时 offline-store 先建链,顺序与其余 AID 不同
1169
- strict_1.default.deepEqual([...health.details?.aids].sort(), ["bridge.agentid.pub", "offline-store.agentid.cn", "second.agentid.pub"]);
1210
+ // 未绑定的 second 不恢复连接。
1211
+ strict_1.default.deepEqual([...health.details?.aids].sort(), ["bridge.agentid.pub", "offline-store.agentid.cn"]);
1170
1212
  strict_1.default.deepEqual(health.details?.bindings, { "bridge.agentid.pub": "dsh", "offline-store.agentid.cn": "doubao" });
1171
1213
  await routes.find((entry) => entry.path === "/api/plugins/aun/identities").handler({}, response);
1172
1214
  strict_1.default.equal(response.body.bindingTimes["bridge.agentid.pub"], boundAt);
@@ -1306,7 +1348,7 @@ async function withAunAttachmentPlugin(run, publish, config = { allow_from: "pee
1306
1348
  const plugin = new aun_1.AunPlugin({ sdk, ingress: { publish: async () => undefined } });
1307
1349
  try {
1308
1350
  globalThis.fetch = (async () => { fetchCalls++; throw new Error("不应从 Gateway 下载信任根"); });
1309
- await plugin.activate({ dataDir, config: { aid: "previous.agentid.cn", identities: ["previous.agentid.cn"], aun_path: aunPath }, logger: { info() { }, warn() { }, error() { } }, callPlugin: async () => ({ text: "" }), pluginStatus: () => "ready", http: { register() { }, unregister() { } } });
1351
+ await plugin.activate({ dataDir, config: { aid: "previous.agentid.cn", identities: ["previous.agentid.cn"], bindings: { "previous.agentid.cn": "workbuddy" }, aun_path: aunPath }, logger: { info() { }, warn() { }, error() { } }, callPlugin: async () => ({ text: "" }), pluginStatus: () => "ready", http: { register() { }, unregister() { } } });
1310
1352
  strict_1.default.equal(storeOptions.length, 2);
1311
1353
  strict_1.default.equal(storeOptions[1].rootCaPath, (0, node_path_1.join)(dataDir, "CA", "root", "root.crt"));
1312
1354
  strict_1.default.deepEqual(events, ["store.close", "client.connect"]);
@@ -1351,3 +1393,107 @@ async function withAunAttachmentPlugin(run, publish, config = { allow_from: "pee
1351
1393
  }
1352
1394
  }, async () => { throw new Error(`WORKBUDDY_ARTIFACT_READ_FAILED:读取文件 ${"目录/".repeat(120)};原因:ENOENT:产物文件已经删除;token=private-token`); });
1353
1395
  });
1396
+ (0, node_test_1.default)("AUN 绑定写盘失败清理新连接,解绑关闭失败仍删除连接并更新健康状态", async () => {
1397
+ for (const existingConnection of [false, true]) {
1398
+ const root = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "aun-binding-cleanup-"));
1399
+ const aid = "cleanup.agentid.cn";
1400
+ let closed = 0;
1401
+ let subscriptions = 0;
1402
+ let closeFails = false;
1403
+ const warnings = [];
1404
+ const sdk = {
1405
+ AIDStore: class {
1406
+ list() { return { ok: true, data: { identities: [{ aid }] } }; }
1407
+ load() { return { ok: true, data: { aid } }; }
1408
+ close() { }
1409
+ },
1410
+ AUNClient: class {
1411
+ on() { subscriptions++; return { unsubscribe() { subscriptions--; } }; }
1412
+ async connect() { }
1413
+ async close() { closed++; if (closeFails)
1414
+ throw new Error("关闭失败"); }
1415
+ },
1416
+ };
1417
+ const plugin = new aun_1.AunPlugin({ sdk, ingress: { publish: async () => undefined } });
1418
+ try {
1419
+ await plugin.activate({ dataDir: root, config: {}, logger: { info() { }, warn(message, fields) { warnings.push(JSON.stringify([message, fields])); }, error() { } }, callPlugin: async () => ({ text: "" }), pluginStatus: () => "ready", http: { register() { }, unregister() { } } });
1420
+ if (existingConnection)
1421
+ await plugin.identity.create(aid, "owner.agentid.cn");
1422
+ await (0, promises_1.rm)((0, node_path_1.join)(root, "config.json"), { force: true });
1423
+ await (0, promises_1.mkdir)((0, node_path_1.join)(root, "config.json"));
1424
+ await strict_1.default.rejects(plugin.identity.bind("workbuddy", aid, 26107));
1425
+ strict_1.default.deepEqual((await plugin.health()).details?.bindings, {});
1426
+ strict_1.default.deepEqual((await plugin.health()).details?.aids, existingConnection ? [aid] : []);
1427
+ strict_1.default.equal(subscriptions, 0);
1428
+ strict_1.default.equal(closed, existingConnection ? 0 : 1);
1429
+ await (0, promises_1.rm)((0, node_path_1.join)(root, "config.json"), { recursive: true });
1430
+ await plugin.identity.bind("workbuddy", aid, 26107);
1431
+ strict_1.default.equal(subscriptions, 1);
1432
+ closeFails = true;
1433
+ await plugin.identity.unbind("workbuddy", aid, 26107);
1434
+ strict_1.default.match(warnings.join("\n"), /AUN.*关闭.*cleanup.agentid.cn.*关闭失败/);
1435
+ const health = await plugin.health();
1436
+ strict_1.default.deepEqual(health.details?.aids, []);
1437
+ strict_1.default.deepEqual(health.details?.bindings, {});
1438
+ strict_1.default.equal(health.details?.connected, false);
1439
+ strict_1.default.equal(health.message, "暂无已连接 AID");
1440
+ strict_1.default.equal(subscriptions, 0);
1441
+ }
1442
+ finally {
1443
+ await plugin.deactivate("stop");
1444
+ await (0, promises_1.rm)(root, { recursive: true, force: true });
1445
+ }
1446
+ }
1447
+ });
1448
+ (0, node_test_1.default)("AUN 旧绑定目标不存在时保留配置并跳过连接,记录具体身份", async () => {
1449
+ const root = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "aun-missing-target-"));
1450
+ const logs = [];
1451
+ let connects = 0;
1452
+ const sdk = {
1453
+ AIDStore: class {
1454
+ list() { return { ok: true, data: { identities: [{ aid: "external.agentid.cn" }] } }; }
1455
+ close() { }
1456
+ },
1457
+ AUNClient: class {
1458
+ async connect() { connects++; }
1459
+ },
1460
+ };
1461
+ const plugin = new aun_1.AunPlugin({ sdk, ingress: { publish: async () => undefined } });
1462
+ try {
1463
+ await plugin.activate({ dataDir: root, config: { bindings: { "external.agentid.cn": "qwenwork" } }, logger: { info() { }, warn(message, fields) { logs.push(JSON.stringify([message, fields])); }, error() { } }, callPlugin: async () => ({ text: "" }), pluginStatus: () => undefined, http: { register() { }, unregister() { } } });
1464
+ strict_1.default.equal(connects, 0);
1465
+ strict_1.default.deepEqual((await plugin.health()).details?.bindings, { "external.agentid.cn": "qwenwork" });
1466
+ strict_1.default.match(logs.join("\n"), /external.agentid.cn.*qwenwork/);
1467
+ }
1468
+ finally {
1469
+ await plugin.deactivate("stop");
1470
+ await (0, promises_1.rm)(root, { recursive: true, force: true });
1471
+ }
1472
+ });
1473
+ (0, node_test_1.default)("AUN 有在途消息时拒绝解绑,最终回复完成后才能解除关联", async () => {
1474
+ let started;
1475
+ let release;
1476
+ const taskStarted = new Promise(resolve => { started = resolve; });
1477
+ const taskGate = new Promise(resolve => { release = resolve; });
1478
+ await withAunAttachmentPlugin(async (receive, sent, _storage, _logs, plugin) => {
1479
+ const task = receive({ from: "peer.agentid.cn", message_id: "unbind-busy", payload: { text: "执行任务" } });
1480
+ try {
1481
+ await taskStarted;
1482
+ await strict_1.default.rejects(plugin.identity.unbind("qwenwork", "local.agentid.cn", 26107), /正在处理消息.*完成后.*解绑/);
1483
+ strict_1.default.deepEqual((await plugin.health()).details?.bindings, { "local.agentid.cn": "qwenwork" });
1484
+ strict_1.default.equal((await plugin.health()).details?.connected, true);
1485
+ }
1486
+ finally {
1487
+ release();
1488
+ await task;
1489
+ }
1490
+ strict_1.default.equal(sent.at(-1).payload.text, "任务最终回复");
1491
+ await plugin.identity.unbind("qwenwork", "local.agentid.cn", 26107);
1492
+ strict_1.default.deepEqual((await plugin.health()).details?.bindings, {});
1493
+ strict_1.default.equal((await plugin.health()).details?.connected, false);
1494
+ }, async (message) => {
1495
+ started();
1496
+ await taskGate;
1497
+ await message.reply("任务最终回复");
1498
+ });
1499
+ });
@@ -67,6 +67,8 @@ const node_util_1 = require("node:util");
67
67
  strict_1.default.match(setup, /TopMost = \$true/);
68
68
  strict_1.default.match(setup, /BringToFront\(\)/);
69
69
  strict_1.default.match(setup, /Invoke-AunCommand @\('list'\)/);
70
+ strict_1.default.match(setup, /自动解除未安装千问办公的残留绑定/);
71
+ strict_1.default.match(setup, /Invoke-AunCommand @\('unbind', \[string\]\$binding\.Name\)/);
70
72
  for (const id of ["qwenwork", "doubao", "workbuddy", "dsh"])
71
73
  strict_1.default.ok(setup.includes(id), "缺少 Agent " + id);
72
74
  strict_1.default.match(setup, /choices\[0\]\.message\.content/);
@@ -45,6 +45,35 @@ const node_http_1 = require("node:http");
45
45
  const plugin_manager_1 = require("../src-ts/plugin-manager");
46
46
  const version_manager_1 = require("../src-ts/version-manager");
47
47
  const channel_sessions_1 = require("../src-ts/channel-sessions");
48
+ (0, node_test_1.default)("启动时内置新版替代状态目录旧插件,保留较新及同版托管插件", async () => {
49
+ for (const [bundled, managed, expectedManaged] of [["1.0.31", "1.0.29", false], ["1.0.31", "1.0.32", true], ["1.0.31", "1.0.31", true], ["1.0.10", "1.0.9", false], ["1.0.9", "1.0.10", true]]) {
50
+ const root = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "mab-plugin-precedence-"));
51
+ const bundledDir = (0, node_path_1.join)(root, "plugins", "aun");
52
+ const managedDir = (0, node_path_1.join)(root, "state", "npm", "agent-bridge-aun", "node_modules", "agent-bridge-aun");
53
+ try {
54
+ for (const [dir, version] of [[bundledDir, bundled], [managedDir, managed]]) {
55
+ await (0, promises_1.mkdir)(dir, { recursive: true });
56
+ await (0, promises_1.writeFile)((0, node_path_1.join)(dir, "package.json"), JSON.stringify({ name: "agent-bridge-aun", version, agentBridge: { plugin: "./plugin.json" } }));
57
+ await (0, promises_1.writeFile)((0, node_path_1.join)(dir, "plugin.json"), JSON.stringify({ id: "aun", version, entry: "index.js", apiVersion: "1", capabilities: [] }));
58
+ await (0, promises_1.writeFile)((0, node_path_1.join)(dir, "index.js"), "module.exports={activate:async()=>{},deactivate:async()=>{},health:async()=>({status:'ready'})};");
59
+ }
60
+ const manager = new plugin_manager_1.PluginManager({ pluginsDir: (0, node_path_1.join)(root, "plugins"), stateDir: (0, node_path_1.join)(root, "state"), publisherResolver: async () => "m2lihui" });
61
+ await manager.discover();
62
+ strict_1.default.equal(manager.list()[0].path, expectedManaged ? managedDir : bundledDir);
63
+ strict_1.default.equal(manager.list()[0].version, expectedManaged ? managed : bundled);
64
+ strict_1.default.equal(manager.packageInfo("aun").managed, expectedManaged);
65
+ await manager.start("aun");
66
+ const instance = manager.get("aun").instance;
67
+ await manager.discover();
68
+ strict_1.default.equal(manager.get("aun").instance, instance);
69
+ strict_1.default.equal(manager.get("aun").record.status, "ready");
70
+ await manager.stop("aun", "stop");
71
+ }
72
+ finally {
73
+ await (0, promises_1.rm)(root, { recursive: true, force: true });
74
+ }
75
+ }
76
+ });
48
77
  (0, node_test_1.default)("后台桌面重启先停止插件再启动,拒绝无关插件", { skip: process.platform === "win32" }, async () => {
49
78
  const root = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "mab-desktop-restart-"));
50
79
  const manager = new plugin_manager_1.PluginManager({ pluginsDir: (0, node_path_1.join)(root, "plugins"), stateDir: (0, node_path_1.join)(root, "state") });
@@ -1157,3 +1186,25 @@ const channel_sessions_1 = require("../src-ts/channel-sessions");
1157
1186
  await (0, promises_1.rm)(root, { recursive: true, force: true });
1158
1187
  }
1159
1188
  });
1189
+ (0, node_test_1.default)("不兼容的新托管候选不遮蔽可用内置插件", async () => {
1190
+ for (const managedFirst of [true, false]) {
1191
+ const root = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), "mab-compatible-choice-"));
1192
+ const manager = new plugin_manager_1.PluginManager({ pluginsDir: (0, node_path_1.join)(root, "plugins"), stateDir: (0, node_path_1.join)(root, "state"), publisherResolver: async () => "m2lihui" });
1193
+ try {
1194
+ const bundled = (0, node_path_1.join)(root, "plugins", "demo");
1195
+ const managed = (0, node_path_1.join)(root, "state", "npm", "agent-bridge-demo", "node_modules", "agent-bridge-demo");
1196
+ for (const [dir, version, requires] of [[bundled, "1.0.0", "*"], [managed, "2.0.0", ">=999.0.0"]]) {
1197
+ await (0, promises_1.mkdir)(dir, { recursive: true });
1198
+ await (0, promises_1.writeFile)((0, node_path_1.join)(dir, "plugin.json"), JSON.stringify({ id: "demo", version, entry: "index.js", apiVersion: "1", capabilities: [] }));
1199
+ await (0, promises_1.writeFile)((0, node_path_1.join)(dir, "package.json"), JSON.stringify({ name: "agent-bridge-demo", agentBridge: { requires: { "mu-agent-bridge": requires } } }));
1200
+ }
1201
+ for (const dir of managedFirst ? [managed, bundled] : [bundled, managed])
1202
+ await manager.discoverDirectory(dir, "demo");
1203
+ strict_1.default.equal(manager.get("demo").record.path, bundled);
1204
+ strict_1.default.equal(manager.get("demo").record.status, "discovered");
1205
+ }
1206
+ finally {
1207
+ await (0, promises_1.rm)(root, { recursive: true, force: true });
1208
+ }
1209
+ }
1210
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mu-agent-bridge",
3
- "version": "1.0.64",
3
+ "version": "1.0.65",
4
4
  "description": "将 AUN Agent 连接到本地桌面 AI 客户端的插件平台。",
5
5
  "main": "dist/src-ts/cli.js",
6
6
  "bin": {
@@ -12,7 +12,7 @@ const agent_1 = require("../../agent");
12
12
  const messages_1 = require("./messages");
13
13
  const attachments_1 = require("./attachments");
14
14
  const manifest = {
15
- id: "aun", version: "1.0.33", type: "channel", displayName: "AUN 通道",
15
+ id: "aun", version: "1.0.34", type: "channel", displayName: "AUN 通道",
16
16
  entry: "dist/src-ts/plugins/aun/index.js", apiVersion: "1", process: "in-process",
17
17
  capabilities: ["channel", "channel.identity.create", "channel.receive", "channel.send", "health", "cli"],
18
18
  configSchema: "config.schema.json",
@@ -86,7 +86,7 @@ class AunPlugin {
86
86
  const known = new Set([...this.clients.keys(), ...this.listStoreAids()]);
87
87
  return {
88
88
  evolcore: [...known].filter((aid) => !own.has(aid)).sort(),
89
- muAgentBridge: [...this.clients.keys()].filter((aid) => own.has(aid)).sort(),
89
+ muAgentBridge: [...known].filter((aid) => own.has(aid)).sort(),
90
90
  localMuAgentBridge: [...own].filter((aid) => !known.has(aid)).sort(),
91
91
  };
92
92
  },
@@ -125,42 +125,29 @@ class AunPlugin {
125
125
  }
126
126
  },
127
127
  bind: async (pluginId, aid, _port) => {
128
+ if (!aid || !aidPattern.test(aid))
129
+ throw new Error("AID 格式无效,必须指定要关联的 AID");
128
130
  if (pluginId === "aun" || pluginId === "abweb")
129
131
  throw new Error("只能关联 Agent 插件");
132
+ if (this.context?.pluginStatus(pluginId) !== "ready")
133
+ throw new Error("目标 Agent 插件未启动");
130
134
  const previous = this.bindings;
131
135
  const previousTimes = this.bindingTimes;
132
- this.bindings = { ...previous };
133
- this.bindingTimes = { ...previousTimes };
136
+ const connection = this.clients.get(aid);
137
+ const hadIdentity = this.identities.has(aid);
138
+ const hadSubscription = Boolean(connection?.subscription);
134
139
  try {
135
- if (aid) {
136
- if (!aidPattern.test(aid))
137
- throw new Error("AID 格式无效");
138
- if (this.context?.pluginStatus(pluginId) !== "ready")
139
- throw new Error("目标 Agent 插件未启动");
140
- if (this.identities.has(aid) || this.legacyCreatedAids.has(aid)) {
141
- if (!this.clients.has(aid))
142
- await this.connectAid(aid);
143
- if (!this.clients.has(aid))
144
- throw new Error("AID 当前未连接");
145
- this.bindings[aid] = pluginId;
146
- }
147
- else {
148
- // 本地身份由插件直接接管,不再通过 ec 配置路由。
149
- const loaded = this.store.load(aid);
150
- if (!loaded.ok || !loaded.data)
151
- throw new Error("AID 不在本地密钥库中,无法关联");
152
- this.identities.add(aid);
153
- if (!this.clients.has(aid))
154
- await this.connectAid(aid);
155
- if (!this.clients.has(aid))
156
- throw new Error("AID 当前未连接");
157
- this.bindings[aid] = pluginId;
158
- }
159
- }
160
- else
161
- throw new Error("必须指定要关联的 AID");
162
- if (aid)
163
- this.bindingTimes[aid] = new Date().toISOString();
140
+ const loaded = this.store.load(aid);
141
+ if (!loaded.ok || !loaded.data)
142
+ throw new Error("AID 不在本地密钥库中,无法关联");
143
+ this.identities.add(aid);
144
+ if (!connection)
145
+ await this.connectAid(aid);
146
+ if (!this.clients.has(aid))
147
+ throw new Error("AID 当前未连接");
148
+ this.bindings = { ...previous, [aid]: pluginId };
149
+ this.bindingTimes = { ...previousTimes, [aid]: new Date().toISOString() };
150
+ this.subscribeAid(aid);
164
151
  await this.persist();
165
152
  }
166
153
  catch (error) {
@@ -168,6 +155,29 @@ class AunPlugin {
168
155
  this.bindingTimes = previousTimes;
169
156
  this.config.bindings = previous;
170
157
  this.config.binding_times = previousTimes;
158
+ if (!hadIdentity)
159
+ this.identities.delete(aid);
160
+ this.config.identities = [...this.identities].sort();
161
+ if (!hadSubscription) {
162
+ this.clients.get(aid)?.subscription?.unsubscribe();
163
+ if (connection)
164
+ connection.subscription = undefined;
165
+ }
166
+ if (!connection) {
167
+ try {
168
+ await this.clients.get(aid)?.client.close();
169
+ }
170
+ catch (closeError) {
171
+ this.context?.logger.warn("AUN 关联回滚关闭连接失败", { aid, error: safeError(closeError) });
172
+ }
173
+ finally {
174
+ this.clients.delete(aid);
175
+ if (!this.clients.size) {
176
+ this.status = "degraded";
177
+ this.healthMessage = "暂无已连接 AID";
178
+ }
179
+ }
180
+ }
171
181
  this.context?.logger.error("AUN 身份关联失败", { aid, pluginId, error: safeError(error) });
172
182
  throw error;
173
183
  }
@@ -178,6 +188,8 @@ class AunPlugin {
178
188
  throw new Error("AID 格式无效");
179
189
  if (this.bindings[aid] !== pluginId)
180
190
  throw new Error("指定 AID 当前未关联到该 Agent");
191
+ if ([...this.pendingMessages.keys()].some(key => JSON.parse(key)[0] === aid))
192
+ throw new Error("该 AID 正在处理消息,请等待任务完成后再解绑");
181
193
  const previous = this.bindings;
182
194
  const previousTimes = this.bindingTimes;
183
195
  this.bindings = { ...previous };
@@ -194,6 +206,21 @@ class AunPlugin {
194
206
  this.config.binding_times = previousTimes;
195
207
  throw error;
196
208
  }
209
+ const connection = this.clients.get(aid);
210
+ connection?.subscription?.unsubscribe();
211
+ try {
212
+ await connection?.client.close();
213
+ }
214
+ catch (error) {
215
+ this.context?.logger.warn("AUN 解绑已完成,关闭连接失败", { aid, pluginId, error: safeError(error) });
216
+ }
217
+ finally {
218
+ this.clients.delete(aid);
219
+ if (!this.clients.size) {
220
+ this.status = "degraded";
221
+ this.healthMessage = "暂无已连接 AID";
222
+ }
223
+ }
197
224
  this.context?.logger.info("AUN 单个身份关联已解除", { aid, pluginId });
198
225
  },
199
226
  };
@@ -207,6 +234,7 @@ class AunPlugin {
207
234
  async activate(context) {
208
235
  this.context = context;
209
236
  this.config = { ...context.config };
237
+ this.identities.clear();
210
238
  this.legacyCreatedAids.clear();
211
239
  this.createdAids.clear();
212
240
  try {
@@ -266,15 +294,25 @@ class AunPlugin {
266
294
  if (this.aid)
267
295
  this.identities.add(this.aid);
268
296
  this.acceptingMessages = true;
269
- for (const aid of this.identities)
270
- await this.connectAid(aid);
271
- // 密钥库中的其余 AID 也自动连接:不再依赖 ec 或 EvolCore 进程
272
- for (const aid of this.listStoreAids()) {
273
- this.identities.add(aid);
274
- if (!this.clients.has(aid))
297
+ // 只订阅明确关联 Agent 的身份,避免接管 EvolCore 或其它 AID 的消息。
298
+ for (const aid of Object.keys(this.bindings)) {
299
+ const target = this.bindings[aid];
300
+ if (!target || !context.pluginStatus(target)) {
301
+ context.logger.warn("AUN 跳过目标插件不存在的旧绑定,未连接身份", { aid, agentPlugin: target });
302
+ continue;
303
+ }
304
+ if (context.pluginStatus(target) !== "ready")
305
+ context.logger.warn("AUN 恢复已有显式绑定,目标插件尚未就绪;关联保持不变", { aid, agentPlugin: target, status: context.pluginStatus(target) });
306
+ if (aidPattern.test(aid))
275
307
  await this.connectAid(aid);
276
308
  }
277
309
  }
310
+ subscribeAid(aid) {
311
+ const connection = this.clients.get(aid);
312
+ if (!connection || connection.subscription || !this.bindings[aid])
313
+ return;
314
+ connection.subscription = connection.client.on("message.received", (payload) => this.onMessage(payload, aid));
315
+ }
278
316
  async connectAid(aid) {
279
317
  try {
280
318
  await this.prepareTrustRoots(aid);
@@ -282,7 +320,7 @@ class AunPlugin {
282
320
  if (!loaded.ok || !loaded.data)
283
321
  throw new Error(loaded.error?.message ?? "本地密钥库中不存在该 AID");
284
322
  const client = new this.sdk.AUNClient(loaded.data.aid);
285
- const subscription = this.identities.has(aid) || this.legacyCreatedAids.has(aid)
323
+ const subscription = this.bindings[aid]
286
324
  ? client.on("message.received", (payload) => this.onMessage(payload, aid))
287
325
  : undefined;
288
326
  try {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-bridge-aun",
3
- "version": "1.0.33",
3
+ "version": "1.0.34",
4
4
  "description": "mu-agent-bridge 的 AUN 通道插件。",
5
5
  "keywords": [
6
6
  "mu-agent-bridge-plugin",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "aun",
3
- "version": "1.0.33",
3
+ "version": "1.0.34",
4
4
  "type": "channel",
5
5
  "displayName": "AUN 通道",
6
6
  "entry": "dist/src-ts/plugins/aun/index.js",