@harrylabsj/kiwi 0.6.0 → 0.6.1

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 (64) hide show
  1. package/dist/a2a/node.d.ts +3 -1
  2. package/dist/a2a/node.js +1 -0
  3. package/dist/a2a/node.js.map +1 -1
  4. package/dist/agent/buyer/types.d.ts +0 -25
  5. package/dist/agent/buyer/types.js.map +1 -1
  6. package/dist/agent/kernel-builder.d.ts +27 -0
  7. package/dist/agent/kernel-builder.js +180 -0
  8. package/dist/agent/kernel-builder.js.map +1 -0
  9. package/dist/cli.js +98 -154
  10. package/dist/cli.js.map +1 -1
  11. package/dist/commerce/data-source.d.ts +4 -3
  12. package/dist/commerce/data-source.js.map +1 -1
  13. package/dist/commerce/shopping-cli-source.js +3 -2
  14. package/dist/commerce/shopping-cli-source.js.map +1 -1
  15. package/dist/config/profile.d.ts +7 -0
  16. package/dist/config/profile.js +23 -0
  17. package/dist/config/profile.js.map +1 -1
  18. package/dist/discovery/catalog-source/kiwi-record.d.ts +3 -0
  19. package/dist/discovery/catalog-source/kiwi-record.js.map +1 -1
  20. package/dist/discovery/catalog-source/kiwi-source.js +7 -1
  21. package/dist/discovery/catalog-source/kiwi-source.js.map +1 -1
  22. package/dist/discovery/catalog-source/register.d.ts +6 -0
  23. package/dist/discovery/catalog-source/register.js +15 -7
  24. package/dist/discovery/catalog-source/register.js.map +1 -1
  25. package/dist/handoff/errors.d.ts +1 -1
  26. package/dist/handoff/errors.js +1 -0
  27. package/dist/handoff/errors.js.map +1 -1
  28. package/dist/handoff/idempotency.d.ts +10 -1
  29. package/dist/handoff/idempotency.js +13 -3
  30. package/dist/handoff/idempotency.js.map +1 -1
  31. package/dist/handoff/transaction.js +13 -6
  32. package/dist/handoff/transaction.js.map +1 -1
  33. package/dist/negotiation/state/phase.js +12 -4
  34. package/dist/negotiation/state/phase.js.map +1 -1
  35. package/dist/product-catalog.d.ts +43 -0
  36. package/dist/product-catalog.js +60 -0
  37. package/dist/product-catalog.js.map +1 -0
  38. package/dist/product-cli.d.ts +1 -1
  39. package/dist/product-cli.js +1 -1
  40. package/dist/product-publish.d.ts +10 -17
  41. package/dist/product-publish.js +177 -41
  42. package/dist/product-publish.js.map +1 -1
  43. package/dist/weixin/channel.d.ts +87 -0
  44. package/dist/weixin/channel.js +356 -0
  45. package/dist/weixin/channel.js.map +1 -0
  46. package/dist/weixin/cli-weixin.d.ts +29 -0
  47. package/dist/weixin/cli-weixin.js +128 -0
  48. package/dist/weixin/cli-weixin.js.map +1 -0
  49. package/dist/weixin/credentials.d.ts +33 -0
  50. package/dist/weixin/credentials.js +107 -0
  51. package/dist/weixin/credentials.js.map +1 -0
  52. package/dist/weixin/ilink-client.d.ts +44 -0
  53. package/dist/weixin/ilink-client.js +262 -0
  54. package/dist/weixin/ilink-client.js.map +1 -0
  55. package/dist/weixin/login.d.ts +34 -0
  56. package/dist/weixin/login.js +93 -0
  57. package/dist/weixin/login.js.map +1 -0
  58. package/dist/weixin/qr.d.ts +26 -0
  59. package/dist/weixin/qr.js +525 -0
  60. package/dist/weixin/qr.js.map +1 -0
  61. package/dist/weixin/types.d.ts +114 -0
  62. package/dist/weixin/types.js +48 -0
  63. package/dist/weixin/types.js.map +1 -0
  64. package/package.json +4 -1
@@ -0,0 +1,356 @@
1
+ /**
2
+ * Copyright 2026 harrylabsj
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /**
17
+ * 微信远程控制通道——长轮询收消息 → AgentKernel.handleUserText →
18
+ * sendMessage 回显(含 context_token)。白名单 fail-closed、去重、
19
+ * 定时任务(schedulerTick / negotiationAutoTick)转发、优雅关闭。
20
+ *
21
+ * 对齐 runChatTui 语义:每条微信文本 = 一次 handleUserText;/slash 命令
22
+ * 经微信可远程控制(/mode /approve /reject /quit 等);通知/磋商前缀
23
+ * 转发给所有已授权用户。
24
+ */
25
+ import { createHash } from "node:crypto";
26
+ import { loadCredentials, loadSyncState, saveCredentials, saveSyncState } from "./credentials.js";
27
+ import { IlinkClient } from "./ilink-client.js";
28
+ import { loginWithQrcode } from "./login.js";
29
+ import { DEFAULT_WEIXIN_TIMINGS, WeixinError } from "./types.js";
30
+ /** 回复文本上限(微信单条消息长度约束)。 */
31
+ const MAX_REPLY_LENGTH = 2000;
32
+ /** 单条消息日志长度(不落 context_token/凭证)。 */
33
+ const LOG_TEXT_LENGTH = 40;
34
+ /**
35
+ * 微信通道:open() 登录或加载凭证,run() 阻塞直到 /quit/致命错误/stop()。
36
+ * kernel 生命周期归 CLI 所有(对齐 cmdChat:CLI finally 里 kernel.close())。
37
+ */
38
+ export class WeixinChannel {
39
+ kernel;
40
+ credentialsPath;
41
+ syncBufPath;
42
+ allowUsers;
43
+ timings;
44
+ log;
45
+ now;
46
+ client;
47
+ credentials = null;
48
+ /** context_token 缓存(key = user_id;协议要求回复回显)。 */
49
+ contextTokens = new Map();
50
+ /** 去重指纹(message_id:text MD5;LRU FIFO 裁剪)。 */
51
+ seen = new Set();
52
+ stopped = false;
53
+ runPromise = null;
54
+ pollAbort = null;
55
+ timers = [];
56
+ noticeFn;
57
+ constructor(options) {
58
+ this.kernel = options.kernel;
59
+ this.credentialsPath = options.credentialsPath;
60
+ this.syncBufPath = options.syncBufPath;
61
+ this.allowUsers = new Set(options.allowUsers ?? []);
62
+ this.timings = { ...DEFAULT_WEIXIN_TIMINGS, ...options.timings };
63
+ this.log = options.log ?? ((line) => process.stderr.write(`${line}\n`));
64
+ this.now = options.now ?? (() => new Date().toISOString());
65
+ this.noticeFn = options.notice ?? ((line) => process.stderr.write(`${line}\n`));
66
+ this.client = new IlinkClient({ baseUrl: options.apiBaseUrl });
67
+ }
68
+ static async open(options) {
69
+ const channel = new WeixinChannel(options);
70
+ if (options.forceRelogin) {
71
+ channel.credentials = await channel.loginAndSave(options);
72
+ }
73
+ else {
74
+ try {
75
+ channel.credentials = loadCredentials(options.credentialsPath);
76
+ // 凭证 base_url 可能为空(首次 confirmed 前未持久化)——缺省用 apiBaseUrl/默认。
77
+ if (channel.credentials.base_url !== "") {
78
+ channel.client.setBaseUrl(channel.credentials.base_url);
79
+ }
80
+ channel.log(`[weixin] 已加载凭证 bot=${channel.credentials.ilink_bot_id}`);
81
+ }
82
+ catch (err) {
83
+ if (err instanceof WeixinError && err.code === "not_configured") {
84
+ channel.credentials = await channel.loginAndSave(options);
85
+ }
86
+ else {
87
+ throw err;
88
+ }
89
+ }
90
+ }
91
+ return channel;
92
+ }
93
+ /** 扫码登录并持久化凭证。 */
94
+ async loginAndSave(options) {
95
+ const credentials = await loginWithQrcode(this.client, {
96
+ render: options.renderQr,
97
+ notice: options.notice,
98
+ qrPollMs: this.timings.qrPollMs,
99
+ qrRefreshCap: this.timings.qrRefreshCap,
100
+ now: this.now,
101
+ });
102
+ saveCredentials(this.credentialsPath, credentials);
103
+ this.client.setBaseUrl(credentials.base_url);
104
+ this.log(`[weixin] 登录成功 bot=${credentials.ilink_bot_id} paired=${credentials.ilink_user_id}`);
105
+ return credentials;
106
+ }
107
+ get status() {
108
+ return {
109
+ loggedIn: this.credentials !== null,
110
+ pairedUser: this.credentials?.ilink_user_id || undefined,
111
+ allowCount: this.allowUsers.size,
112
+ };
113
+ }
114
+ /** 阻塞直到 /quit、致命错误或 stop();返回进程退出码。 */
115
+ async run() {
116
+ if (this.credentials === null) {
117
+ throw new WeixinError("not_configured", "微信通道未登录");
118
+ }
119
+ this.runPromise = this.runLoop();
120
+ return this.runPromise;
121
+ }
122
+ /** 优雅关闭:置 stopped → abort 在飞长轮询 → 写穿 sync state → 清定时器。 */
123
+ async stop() {
124
+ if (this.stopped)
125
+ return;
126
+ this.stopped = true;
127
+ this.pollAbort?.abort();
128
+ for (const t of this.timers.splice(0))
129
+ clearInterval(t);
130
+ if (this.runPromise !== null) {
131
+ try {
132
+ await this.runPromise;
133
+ }
134
+ catch {
135
+ // stop 后的轮询异常被 stopped 分支吞掉
136
+ }
137
+ }
138
+ }
139
+ // ── 主循环 ──────────────────────────────────────────────────────────
140
+ async runLoop() {
141
+ const creds = this.credentials;
142
+ // 定时任务(对齐 runChatTui:首 tick 立即跑,后续 interval unref)
143
+ await this.schedulerTickOnce();
144
+ this.startTimer(this.timings.schedulerTickMs, () => void this.schedulerTickOnce());
145
+ await this.negotiateOnce();
146
+ this.startTimer(this.timings.negotiateTickMs, () => void this.negotiateOnce());
147
+ // 恢复游标 + 去重指纹
148
+ let syncBuf = "";
149
+ try {
150
+ const state = loadSyncState(this.syncBufPath);
151
+ syncBuf = state.get_updates_buf;
152
+ for (const fp of state.seen)
153
+ this.seen.add(fp);
154
+ }
155
+ catch (err) {
156
+ this.log(`[weixin] 同步状态损坏,从头轮询:${err instanceof Error ? err.message : String(err)}`);
157
+ syncBuf = "";
158
+ }
159
+ let consecutiveProtocolErrors = 0;
160
+ let fatalCount = 0;
161
+ while (!this.stopped) {
162
+ try {
163
+ const result = await this.client.getUpdates(syncBuf, creds);
164
+ consecutiveProtocolErrors = 0;
165
+ fatalCount = 0;
166
+ syncBuf = result.next_sync_buf;
167
+ for (const msg of result.messages) {
168
+ await this.processMessage(msg);
169
+ if (this.stopped)
170
+ return 0;
171
+ }
172
+ // 每轮写穿游标 + 去重(重启零丢失)
173
+ saveSyncState(this.syncBufPath, { get_updates_buf: syncBuf, seen: [...this.seen] });
174
+ }
175
+ catch (err) {
176
+ if (this.stopped)
177
+ return 0;
178
+ if (err instanceof WeixinError) {
179
+ switch (err.code) {
180
+ case "session_stale":
181
+ this.log(`[weixin] 会话过期:${err.message}。${this.timings.sessionStaleCooldownMs / 1000}s 后重试(可 kill 后 kiwi weixin --relogin 重扫)`);
182
+ await this.sleep(this.timings.sessionStaleCooldownMs);
183
+ consecutiveProtocolErrors = 0;
184
+ continue;
185
+ case "protocol":
186
+ consecutiveProtocolErrors++;
187
+ if (consecutiveProtocolErrors >= 3) {
188
+ this.log(`[weixin] 连续协议错误 ${consecutiveProtocolErrors} 次,退避 ${this.timings.protocolBackoffMs / 1000}s`);
189
+ await this.sleep(this.timings.protocolBackoffMs);
190
+ consecutiveProtocolErrors = 0;
191
+ }
192
+ continue;
193
+ case "timeout":
194
+ case "network":
195
+ case "http":
196
+ case "redirect":
197
+ case "response_too_large":
198
+ case "invalid_json": {
199
+ // 指数退避(2s/5s/15s/60s 封顶)
200
+ const backoff = this.timings.httpBackoffMs[Math.min(fatalCount, this.timings.httpBackoffMs.length - 1)];
201
+ fatalCount++;
202
+ this.log(`[weixin] ${err.code}:${err.message}。${backoff / 1000}s 后重试`);
203
+ await this.sleep(backoff);
204
+ continue;
205
+ }
206
+ case "auth":
207
+ this.log(`[weixin] 凭证被拒:${err.message}。请 kill 后 kiwi weixin --relogin 重扫`);
208
+ return 3; // EXIT.AUTH
209
+ default:
210
+ fatalCount++;
211
+ if (fatalCount >= 5) {
212
+ this.log(`[weixin] 连续致命错误 ${fatalCount} 次,退出`);
213
+ return 10; // EXIT.TRANSIENT
214
+ }
215
+ this.log(`[weixin] ${err.message}`);
216
+ await this.sleep(2_000);
217
+ continue;
218
+ }
219
+ }
220
+ fatalCount++;
221
+ if (fatalCount >= 5) {
222
+ this.log(`[weixin] 连续致命错误 ${fatalCount} 次,退出`);
223
+ return 10;
224
+ }
225
+ this.log(`[weixin] ${err instanceof Error ? err.message : String(err)}`);
226
+ await this.sleep(2_000);
227
+ }
228
+ }
229
+ return 0;
230
+ }
231
+ // ── 消息处理 ────────────────────────────────────────────────────────
232
+ async processMessage(msg) {
233
+ if (msg.text === "") {
234
+ this.log(`[weixin] 跳过非文本消息 from=${shortId(msg.from_user_id)}`);
235
+ return;
236
+ }
237
+ // 去重(message_id + 内容指纹)
238
+ const fingerprint = createHash("md5").update(`${msg.message_id}:${msg.text}`).digest("hex");
239
+ if (this.seen.has(fingerprint)) {
240
+ this.log(`[weixin] 去重跳过 from=${shortId(msg.from_user_id)}`);
241
+ return;
242
+ }
243
+ this.seen.add(fingerprint);
244
+ this.trimSeen();
245
+ // 白名单:配对扫描者自动授权 + 配置 allowUsers;未授权不回复(不确认 bot 存在)
246
+ const paired = this.credentials?.ilink_user_id ?? "";
247
+ const authorized = msg.from_user_id === paired || this.allowUsers.has(msg.from_user_id);
248
+ if (!authorized) {
249
+ this.log(`[weixin] 拒绝未授权用户 ${shortId(msg.from_user_id)}(不回复)`);
250
+ return;
251
+ }
252
+ // 缓存 context_token(回复必须回显)
253
+ if (msg.context_token !== "") {
254
+ this.contextTokens.set(msg.from_user_id, msg.context_token);
255
+ this.trimContextTokens();
256
+ }
257
+ const contextToken = this.contextTokens.get(msg.from_user_id);
258
+ this.log(`[weixin] ${shortId(msg.from_user_id)} → ${truncate(msg.text, LOG_TEXT_LENGTH)}`);
259
+ const reply = await this.kernel.handleUserText(msg.text);
260
+ if (reply.text !== "") {
261
+ await this.trySend(msg.from_user_id, reply.text, contextToken);
262
+ }
263
+ if (reply.quit) {
264
+ this.log("[weixin] 收到 /quit,通道退出");
265
+ this.stopped = true;
266
+ }
267
+ }
268
+ /** 发送消息(失败仅日志,不重试——模型回合昂贵,重试只覆盖轮询层)。 */
269
+ async trySend(toUserId, text, contextToken) {
270
+ if (this.credentials === null)
271
+ return;
272
+ const clipped = text.length > MAX_REPLY_LENGTH ? `${text.slice(0, MAX_REPLY_LENGTH)}…(已截断)` : text;
273
+ try {
274
+ await this.client.sendMessage({ to_user_id: toUserId, text: clipped, context_token: contextToken }, this.credentials);
275
+ }
276
+ catch (err) {
277
+ this.log(`[weixin] 回复发送失败:${err instanceof Error ? err.message : String(err)}`);
278
+ }
279
+ }
280
+ // ── 定时任务(对齐 runChatTui)──────────────────────────────────────
281
+ async schedulerTickOnce() {
282
+ if (this.timings.schedulerTickMs === 0)
283
+ return;
284
+ try {
285
+ const result = await this.kernel.schedulerTick();
286
+ for (const n of result.notifications) {
287
+ await this.broadcast(`[通知] ${n.summary}(任务 ${n.task_id})`);
288
+ }
289
+ for (const e of result.errors) {
290
+ await this.broadcast(`[任务] ${e}`);
291
+ }
292
+ }
293
+ catch (err) {
294
+ this.log(`[weixin] schedulerTick 失败:${err instanceof Error ? err.message : String(err)}`);
295
+ }
296
+ }
297
+ async negotiateOnce() {
298
+ if (this.timings.negotiateTickMs === 0)
299
+ return;
300
+ try {
301
+ const text = await this.kernel.negotiationAutoTick();
302
+ if (text !== undefined && text !== "") {
303
+ await this.broadcast(`[磋商] ${text}`);
304
+ }
305
+ }
306
+ catch (err) {
307
+ this.log(`[weixin] negotiationAutoTick 失败:${err instanceof Error ? err.message : String(err)}`);
308
+ }
309
+ }
310
+ /** 转发给所有已授权用户(有 context_token 的优先;无 token 的首次可能不可达)。 */
311
+ async broadcast(text) {
312
+ const targets = new Set();
313
+ if (this.credentials !== null && this.credentials.ilink_user_id !== "") {
314
+ targets.add(this.credentials.ilink_user_id);
315
+ }
316
+ for (const u of this.allowUsers)
317
+ targets.add(u);
318
+ for (const to of targets) {
319
+ await this.trySend(to, text, this.contextTokens.get(to));
320
+ }
321
+ }
322
+ // ── 工具 ────────────────────────────────────────────────────────────
323
+ startTimer(ms, fn) {
324
+ if (ms === 0)
325
+ return;
326
+ const t = setInterval(fn, ms);
327
+ t.unref();
328
+ this.timers.push(t);
329
+ }
330
+ trimSeen() {
331
+ while (this.seen.size > this.timings.dedupCap) {
332
+ const first = this.seen.values().next().value;
333
+ if (first === undefined)
334
+ break;
335
+ this.seen.delete(first);
336
+ }
337
+ }
338
+ trimContextTokens() {
339
+ while (this.contextTokens.size > this.timings.dedupCap) {
340
+ const first = this.contextTokens.keys().next().value;
341
+ if (first === undefined)
342
+ break;
343
+ this.contextTokens.delete(first);
344
+ }
345
+ }
346
+ sleep(ms) {
347
+ return new Promise((resolve) => setTimeout(resolve, ms));
348
+ }
349
+ }
350
+ function shortId(id) {
351
+ return id.length > 12 ? `${id.slice(0, 6)}…${id.slice(-4)}` : id;
352
+ }
353
+ function truncate(text, max) {
354
+ return text.length > max ? `${text.slice(0, max)}…` : text;
355
+ }
356
+ //# sourceMappingURL=channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.js","sourceRoot":"","sources":["../../src/weixin/channel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Copyright 2026 harrylabsj
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ export declare function weixinUsage(): string;
17
+ export interface WeixinCliArgs {
18
+ profile?: string;
19
+ dataDir?: string;
20
+ allow?: string;
21
+ relogin: boolean;
22
+ a2a: boolean;
23
+ port?: number;
24
+ qrScale: number;
25
+ noQr: boolean;
26
+ catalog?: string;
27
+ }
28
+ /** `kiwi weixin` 主入口。返回进程退出码(0 OK / 2 CONFIG / 3 AUTH / 10 TRANSIENT)。 */
29
+ export declare function cmdWeixin(args: WeixinCliArgs): Promise<number>;
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Copyright 2026 harrylabsj
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /**
17
+ * `kiwi weixin` 命令——微信远程控制通道入口。
18
+ *
19
+ * 接线对齐 cmdChat:profile 加载 → buildChatKernel → (可选 --a2a 节点)→
20
+ * WeixinChannel.open(登录或加载凭证)→ run();SIGINT/SIGTERM 优雅关闭。
21
+ * A2A 节点默认关(headless 控制面收窄攻击面),--a2a 开启。
22
+ */
23
+ import { buildChatKernel, defaultChatProfile } from "../agent/kernel-builder.js";
24
+ import { startA2aNode } from "../a2a/node.js";
25
+ import { loadProfile } from "../config/profile.js";
26
+ import { EXIT } from "../exit-codes.js";
27
+ import { DEFAULT_CATALOG_URL } from "../product-cli.js";
28
+ import { agentDataDir, ensurePathsForDir } from "../agent/agent-db.js";
29
+ import { WeixinChannel } from "./channel.js";
30
+ import { credentialsPathFor, syncStatePathFor } from "./credentials.js";
31
+ import { ILINK_DEFAULT_BASE_URL } from "./types.js";
32
+ export function weixinUsage() {
33
+ return `kiwi weixin — 微信远程控制通道(iLink Bot)
34
+
35
+ Usage:
36
+ kiwi weixin [--profile FILE] [--data-dir DIR] [--allow id1,id2] [--relogin]
37
+ [--a2a] [--port N] [--qr-scale 1|2] [--no-qr]
38
+
39
+ --profile FILE profile(缺省 defaultChatProfile,同裸 kiwi)
40
+ --data-dir DIR kernel 数据目录 + 微信凭证/游标(缺省 agentDataDir)
41
+ --allow id,… 额外授权微信用户(配对扫描者始终自动授权)
42
+ --relogin 丢弃已存凭证重新扫码(会话过期/换设备时)
43
+ --a2a 同时启动 A2A 节点(默认关;port 复用 --port)
44
+ --qr-scale N 终端二维码每模块列数(1 或 2;默认 1)
45
+ --no-qr 仅打印 URL + 提示(兜底;默认渲染二维码)
46
+
47
+ 扫码登录后微信发消息即远程控制 kiwi(对话 + /slash 命令:
48
+ /mode /approve /reject /status /quit 等)。首次请先发一句任意消息唤醒通道。
49
+ `;
50
+ }
51
+ /** `kiwi weixin` 主入口。返回进程退出码(0 OK / 2 CONFIG / 3 AUTH / 10 TRANSIENT)。 */
52
+ export async function cmdWeixin(args) {
53
+ const profile = args.profile !== undefined ? loadProfile(args.profile) : defaultChatProfile();
54
+ const catalog = args.catalog ?? process.env.KIWI_CATALOG_URL ?? DEFAULT_CATALOG_URL;
55
+ const dataDir = args.dataDir ?? agentDataDir(profile.agent_id);
56
+ ensurePathsForDir(dataDir);
57
+ const kernel = await buildChatKernel(profile, dataDir, catalog);
58
+ let node = null;
59
+ if (args.a2a) {
60
+ try {
61
+ node = await startA2aNode({
62
+ profile,
63
+ catalog,
64
+ preferredPort: args.port,
65
+ ownerTokenSecret: process.env.KIWI_CATALOG_OWNER_TOKEN_SECRET,
66
+ });
67
+ process.stderr.write(`[a2a] ${node.role}@${node.url}${node.catalogAgentId !== undefined ? ` registered ${node.catalogAgentId}` : ""}\n`);
68
+ }
69
+ catch (err) {
70
+ process.stderr.write(`[a2a] 节点启动失败(微信通道继续):${err instanceof Error ? err.message : String(err)}\n`);
71
+ }
72
+ }
73
+ // 白名单:--allow > KIWI_WEIXIN_ALLOW_USERS > profile weixin.allow_users
74
+ const allowUsers = resolveAllowUsers(args.allow, profile.weixin?.allow_users);
75
+ // base URL:KIWI_WEIXIN_BASE_URL > profile weixin.base_url > 默认
76
+ const apiBaseUrl = process.env.KIWI_WEIXIN_BASE_URL ?? profile.weixin?.base_url ?? ILINK_DEFAULT_BASE_URL;
77
+ let channel = null;
78
+ const shutdown = async (code) => {
79
+ await channel?.stop().catch(() => undefined);
80
+ await node?.stop().catch(() => undefined);
81
+ await kernel.close().catch(() => undefined);
82
+ process.exit(code);
83
+ };
84
+ process.on("SIGINT", () => void shutdown(0));
85
+ process.on("SIGTERM", () => void shutdown(0));
86
+ try {
87
+ channel = await WeixinChannel.open({
88
+ kernel,
89
+ apiBaseUrl,
90
+ credentialsPath: credentialsPathFor(dataDir),
91
+ syncBufPath: syncStatePathFor(dataDir),
92
+ allowUsers,
93
+ forceRelogin: args.relogin,
94
+ renderQr: args.noQr
95
+ ? undefined
96
+ : (qr) => {
97
+ for (const line of qr)
98
+ process.stdout.write(`${line}\n`);
99
+ },
100
+ notice: (line) => process.stderr.write(`${line}\n`),
101
+ });
102
+ const exitCode = await channel.run();
103
+ return exitCode;
104
+ }
105
+ catch (err) {
106
+ process.stderr.write(`[weixin] ${err instanceof Error ? err.message : String(err)}\n`);
107
+ return EXIT.CONFIG;
108
+ }
109
+ finally {
110
+ process.removeListener("SIGINT", shutdown);
111
+ process.removeListener("SIGTERM", shutdown);
112
+ await channel?.stop().catch(() => undefined);
113
+ await node?.stop().catch(() => undefined);
114
+ await kernel.close().catch(() => undefined);
115
+ }
116
+ }
117
+ /** 白名单合并:--allow(逗号分隔)> env > profile。 */
118
+ function resolveAllowUsers(cliAllow, profileAllow) {
119
+ const env = process.env.KIWI_WEIXIN_ALLOW_USERS;
120
+ const source = cliAllow ?? env ?? (profileAllow !== undefined ? profileAllow.join(",") : undefined);
121
+ if (source === undefined || source === "")
122
+ return [];
123
+ return source
124
+ .split(",")
125
+ .map((s) => s.trim())
126
+ .filter((s) => s !== "");
127
+ }
128
+ //# sourceMappingURL=cli-weixin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-weixin.js","sourceRoot":"","sources":["../../src/weixin/cli-weixin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEjF,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,UAAU,WAAW;IACzB,OAAO;;;;;;;;;;;;;;;;CAgBR,CAAC;AACF,CAAC;AAcD,0EAA0E;AAC1E,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAmB;IACjD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC;IAC9F,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,mBAAmB,CAAC;IACpF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC/D,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAE3B,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAEhE,IAAI,IAAI,GAAyB,IAAI,CAAC;IACtC,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACb,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,YAAY,CAAC;gBACxB,OAAO;gBACP,OAAO;gBACP,aAAa,EAAE,IAAI,CAAC,IAAI;gBACxB,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,+BAA+B;aAC9D,CAAC,CAAC;YACH,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,SAAS,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CACnH,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrG,CAAC;IACH,CAAC;IAED,qEAAqE;IACrE,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IAE9E,+DAA+D;IAC/D,MAAM,UAAU,GACd,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,OAAO,CAAC,MAAM,EAAE,QAAQ,IAAI,sBAAsB,CAAC;IAEzF,IAAI,OAAO,GAAyB,IAAI,CAAC;IACzC,MAAM,QAAQ,GAAG,KAAK,EAAE,IAAY,EAAkB,EAAE;QACtD,MAAM,OAAO,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC7C,MAAM,IAAI,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC5C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAE9C,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC;YACjC,MAAM;YACN,UAAU;YACV,eAAe,EAAE,kBAAkB,CAAC,OAAO,CAAC;YAC5C,WAAW,EAAE,gBAAgB,CAAC,OAAO,CAAC;YACtC,UAAU;YACV,YAAY,EAAE,IAAI,CAAC,OAAO;YAC1B,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACjB,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE;oBACL,KAAK,MAAM,IAAI,IAAI,EAAE;wBAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;gBAC3D,CAAC;YACL,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC;SACpD,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,CAAC;QACrC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,YAAY,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CACjE,CAAC;QACF,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;YAAS,CAAC;QACT,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC3C,OAAO,CAAC,cAAc,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC5C,MAAM,OAAO,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC7C,MAAM,IAAI,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC;AAED,0CAA0C;AAC1C,SAAS,iBAAiB,CAAC,QAA4B,EAAE,YAAkC;IACzF,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;IAChD,MAAM,MAAM,GAAG,QAAQ,IAAI,GAAG,IAAI,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACpG,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC;IACrD,OAAO,MAAM;SACV,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Copyright 2026 harrylabsj
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import type { BotCredentials } from "./types.js";
17
+ /** 同步游标 + 去重指纹(seen = MD5 指纹 LRU,cap 由调用方裁剪)。 */
18
+ export interface StoredSyncState {
19
+ get_updates_buf: string;
20
+ seen: string[];
21
+ }
22
+ /** 保存凭证(0600 + 原子写)。 */
23
+ export declare function saveCredentials(pathName: string, creds: BotCredentials): void;
24
+ /** 加载凭证;缺失 → not_configured;损坏/缺字段 → validation(fail-closed)。 */
25
+ export declare function loadCredentials(pathName: string): BotCredentials;
26
+ /** 保存同步游标 + 去重指纹(0600 + 原子写)。 */
27
+ export declare function saveSyncState(pathName: string, state: StoredSyncState): void;
28
+ /** 加载同步游标;缺失 → 默认(空游标);损坏 → validation(fail-closed)。 */
29
+ export declare function loadSyncState(pathName: string): StoredSyncState;
30
+ /** 便捷:凭证文件路径(dataDir 下)。 */
31
+ export declare function credentialsPathFor(dataDir: string): string;
32
+ /** 便捷:同步状态文件路径(dataDir 下)。 */
33
+ export declare function syncStatePathFor(dataDir: string): string;