wezard 2.4.0 → 2.5.0

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 (101) hide show
  1. package/CLAUDE.md +1 -1
  2. package/README.md +113 -57
  3. package/cli/wezard.sh +2 -0
  4. package/config.example.jsonc +7 -4
  5. package/dist/cli/wx.js +78 -0
  6. package/dist/cli/wx.js.map +1 -0
  7. package/dist/daemon/aibot-media.js +62 -0
  8. package/dist/daemon/aibot-media.js.map +1 -0
  9. package/dist/daemon/approval.js +30 -20
  10. package/dist/daemon/approval.js.map +1 -1
  11. package/dist/daemon/ask.js +3 -2
  12. package/dist/daemon/ask.js.map +1 -1
  13. package/dist/daemon/cc-session.js +27 -4
  14. package/dist/daemon/cc-session.js.map +1 -1
  15. package/dist/daemon/chat-log.js +2 -2
  16. package/dist/daemon/chat-log.js.map +1 -1
  17. package/dist/daemon/chat-name.js +6 -2
  18. package/dist/daemon/chat-name.js.map +1 -1
  19. package/dist/daemon/config-api.js +25 -10
  20. package/dist/daemon/config-api.js.map +1 -1
  21. package/dist/daemon/direction.js +53 -0
  22. package/dist/daemon/direction.js.map +1 -0
  23. package/dist/daemon/ilink.js +162 -0
  24. package/dist/daemon/ilink.js.map +1 -0
  25. package/dist/daemon/inbound.js +64 -18
  26. package/dist/daemon/inbound.js.map +1 -1
  27. package/dist/daemon/index.js +415 -109
  28. package/dist/daemon/index.js.map +1 -1
  29. package/dist/daemon/jobs.js +4 -3
  30. package/dist/daemon/jobs.js.map +1 -1
  31. package/dist/daemon/last-response.js +6 -3
  32. package/dist/daemon/last-response.js.map +1 -1
  33. package/dist/daemon/media.js +108 -0
  34. package/dist/daemon/media.js.map +1 -0
  35. package/dist/daemon/mirror-bridge.js +111 -93
  36. package/dist/daemon/mirror-bridge.js.map +1 -1
  37. package/dist/daemon/model-select.js +159 -54
  38. package/dist/daemon/model-select.js.map +1 -1
  39. package/dist/daemon/notices.js +59 -12
  40. package/dist/daemon/notices.js.map +1 -1
  41. package/dist/daemon/outbound.js +2 -1
  42. package/dist/daemon/outbound.js.map +1 -1
  43. package/dist/daemon/peers.js +46 -27
  44. package/dist/daemon/peers.js.map +1 -1
  45. package/dist/daemon/pending-items.js +1 -1
  46. package/dist/daemon/pending-items.js.map +1 -1
  47. package/dist/daemon/reach.js +6 -0
  48. package/dist/daemon/reach.js.map +1 -0
  49. package/dist/daemon/receipts.js +149 -7
  50. package/dist/daemon/receipts.js.map +1 -1
  51. package/dist/daemon/route.js +11 -4
  52. package/dist/daemon/route.js.map +1 -1
  53. package/dist/daemon/spawn-tmux.js +157 -60
  54. package/dist/daemon/spawn-tmux.js.map +1 -1
  55. package/dist/daemon/steward-guard.js +48 -7
  56. package/dist/daemon/steward-guard.js.map +1 -1
  57. package/dist/daemon/top-only-nudge.js +29 -0
  58. package/dist/daemon/top-only-nudge.js.map +1 -0
  59. package/dist/daemon/weixin-cmd.js +268 -0
  60. package/dist/daemon/weixin-cmd.js.map +1 -0
  61. package/dist/daemon/weixin-port.js +226 -0
  62. package/dist/daemon/weixin-port.js.map +1 -0
  63. package/dist/daemon/weixin.js +772 -0
  64. package/dist/daemon/weixin.js.map +1 -0
  65. package/dist/daemon/wizard.js +56 -18
  66. package/dist/daemon/wizard.js.map +1 -1
  67. package/dist/mcp/server.js +43 -23
  68. package/dist/mcp/server.js.map +1 -1
  69. package/dist/shared/chat-http.js +61 -20
  70. package/dist/shared/chat-http.js.map +1 -1
  71. package/dist/shared/chat-render.js +9 -1
  72. package/dist/shared/chat-render.js.map +1 -1
  73. package/dist/shared/chat-view.js +16 -2
  74. package/dist/shared/chat-view.js.map +1 -1
  75. package/dist/shared/cli-backends.js +3 -0
  76. package/dist/shared/cli-backends.js.map +1 -1
  77. package/dist/shared/config.js +45 -10
  78. package/dist/shared/config.js.map +1 -1
  79. package/dist/shared/json-map-store.js +1 -0
  80. package/dist/shared/json-map-store.js.map +1 -1
  81. package/dist/shared/reminder.js +1 -0
  82. package/dist/shared/reminder.js.map +1 -1
  83. package/dist/shared/role-render.js +7 -4
  84. package/dist/shared/role-render.js.map +1 -1
  85. package/dist/shared/role-view.js +116 -37
  86. package/dist/shared/role-view.js.map +1 -1
  87. package/dist/shared/seen-log.js +26 -0
  88. package/dist/shared/seen-log.js.map +1 -0
  89. package/dist/shared/session-label.js +84 -31
  90. package/dist/shared/session-label.js.map +1 -1
  91. package/dist/shared/turn-state.js +1 -1
  92. package/dist/shared/turn-state.js.map +1 -1
  93. package/dist/shared/world.js.map +1 -1
  94. package/dist/shared/wx-text.js +101 -0
  95. package/dist/shared/wx-text.js.map +1 -0
  96. package/dist/svr/index.js +5 -2
  97. package/dist/svr/index.js.map +1 -1
  98. package/hooks/pre-tool-use.sh +9 -6
  99. package/package.json +6 -2
  100. package/web/chat.css +32 -5
  101. package/web/chat.js +160 -92
@@ -0,0 +1,268 @@
1
+ // `/wx` 命令、`/wx/*` 路由、绑定落定后的那几件事、微信侧的 SendMedia。
2
+ //
3
+ // 门槛: 二维码就是授权凭据 —— 谁扫了谁就能驱动本机。所以只有审批人 (wxAdmins) 能发起; 判据只有
4
+ // 发话人, 不看在哪个聊天 (对 wezard 单聊群聊都是 chat), 码与进度回发起的那个聊天。本机终端 (`wezard wx bind`) 发起的
5
+ // 要先给审批人推一张确认卡, 点了才出码 —— 口令每个 wizard 都读得到, 光凭口令等于任何 wizard 都能
6
+ // 给本机多开一个微信入口。
7
+ import { mkdirSync, statSync, writeFileSync } from "node:fs";
8
+ import { tmpdir } from "node:os";
9
+ import { basename, join } from "node:path";
10
+ import QRCode from "qrcode";
11
+ import { appendUnique, patchJsonc } from "../shared/config-writer.js";
12
+ import { baseOfKey } from "../shared/session-label.js";
13
+ import { shortNameOf } from "../shared/wx-text.js";
14
+ import { applyChatNames, chatNameOf, listChatNames, normChatName, uniqueChatName } from "./chat-name.js";
15
+ import { json, readBody } from "./http.js";
16
+ import { planMedia, kindOf } from "./media.js";
17
+ import { settleName, wizardStore } from "./wizard.js";
18
+ import { WX_MEDIA_MAX } from "./weixin.js";
19
+ export const parseWxCommand = (text) => {
20
+ const m = /^\/wx(?:\s+(\S+))?(?:\s+([\s\S]*))?$/i.exec((text ?? "").trim());
21
+ if (!m)
22
+ return undefined;
23
+ const verb = (m[1] ?? "").toLowerCase();
24
+ const arg = (m[2] ?? "").trim();
25
+ return verb === "" || verb === "list" ? { verb: "list" }
26
+ : verb === "bind" ? { verb: "bind", name: arg }
27
+ : verb === "code" ? { verb: "code", code: arg }
28
+ : verb === "unbind" ? { verb: "unbind", arg }
29
+ : { verb: "help" };
30
+ };
31
+ /** 能发起绑定的人: 审批人名单; 名单空 → defaultChat (是个人的话) 并上 allowFrom 里的人。
32
+ * allowFrom 里的人本就能驱动本机 (所发起的轮次的审批卡也是他点), 绑一个微信号给他不是放出新权限;
33
+ * 只认 defaultChat 会把「defaultChat 指着别人、自己在 allowFrom」的部署里的唯一使用者挡在外面。 */
34
+ export const wxAdmins = (cfg) => cfg.approval.approvers.length ? cfg.approval.approvers
35
+ : [...new Set([...(cfg.defaultChat?.startsWith("user:") ? [cfg.defaultChat] : []), ...cfg.wrc.allowFrom.filter((p) => p.startsWith("user:"))])];
36
+ export const isWxAdmin = (cfg, userPrincipal) => wxAdmins(cfg).includes(userPrincipal);
37
+ const ago = (t) => {
38
+ if (!t)
39
+ return "—";
40
+ const s = Math.round((Date.now() - t) / 1000);
41
+ return s < 90 ? `${s}s 前` : s < 5400 ? `${Math.round(s / 60)} 分钟前` : s < 172800 ? `${Math.round(s / 3600)} 小时前` : `${Math.round(s / 86400)} 天前`;
42
+ };
43
+ export const renderAccounts = (cfg, xs) => xs.length === 0
44
+ ? "[wezard] 还没有绑定微信。发 `/wx bind [群名]` 扫码绑定 (仅审批人)。"
45
+ : [
46
+ `*微信 ClawBot* (${xs.length}/${cfg.weixin.maxAccounts}${cfg.weixin.enabled ? "" : " · ⚠️ 通道未开启"})`,
47
+ ...xs.map((a, i) => {
48
+ const name = chatNameOf(cfg, `chat:${a.chatId}`) || a.chatId;
49
+ const ctx = a.ctx ? `额度 ${Math.max(0, cfg.weixin.sendCap - a.ctx.used)}/${cfg.weixin.sendCap}` : "无 token";
50
+ return `${i + 1}. \`${name}\` ${a.state === "live" ? "🟢" : "🔴 掉线"} · 上次说话 ${ago(a.lastInAt)} · ${ctx}${a.outbox.length ? ` · 📬 压着 ${a.outbox.length}` : ""} · 发 ${a.sent ?? 0} / 败 ${a.failed ?? 0}`;
51
+ }),
52
+ "",
53
+ "`/wx bind [群名]` 绑新号 · `/wx unbind <序号|群名>` 解绑",
54
+ ].join("\n");
55
+ const HELP = [
56
+ "*/wx* 微信 ClawBot (仅审批人; 二维码与进度回发起的这个聊天)",
57
+ "`/wx` 列出已绑定的微信",
58
+ "`/wx bind [群名]` 出二维码, 用要绑定的那个微信扫 (约 2 分钟有效)",
59
+ "`/wx code <配对码>` 微信上显示配对码时回填",
60
+ "`/wx unbind <序号|群名>` 解绑 (群聊与 wizard 保留)",
61
+ ].join("\n");
62
+ const viewLine = (v) => v.status === "qr" ? `📱 ${v.message}`
63
+ : v.status === "scaned" ? "👀 已扫码, 请在微信里点「确认」"
64
+ : v.status === "need_code" ? `🔢 ${v.message}: 发 \`/wx code <配对码>\``
65
+ : v.status === "done" ? `✅ 微信已绑定为群聊 \`${v.name}\` —— 去微信里先给「微信 ClawBot」发一句话 (机器人在你开口前不能说话); 之后像企微群一样用, \`.名字\` 点名 wizard`
66
+ : v.status === "already" ? `ℹ️ ${v.message}`
67
+ : `❌ 绑定失败: ${v.message}`;
68
+ /** 起群名 (只填空)、进 allowFrom、生默认 wizard —— 与企微群聊首条消息走的是同一套。 */
69
+ export const makeOnBound = ({ cfg, sourcePath, log, hasSession, newSession }) => async (acct, wantName) => {
70
+ const base = `chat:${acct.chatId}`;
71
+ const have = chatNameOf(cfg, base);
72
+ const name = have || (() => {
73
+ const want = normChatName(wantName).replace(/[^\p{L}\p{N}_-]+/gu, "-").replace(/^-+|-+$/g, "").slice(0, 32) || shortNameOf(acct.userId);
74
+ const taken = new Set(listChatNames(cfg).map((c) => c.name.toLowerCase()));
75
+ const picked = uniqueChatName(want, taken);
76
+ applyChatNames(cfg, sourcePath, { [base]: picked });
77
+ return picked;
78
+ })();
79
+ if (!cfg.wrc.allowFrom.includes(base)) {
80
+ cfg.wrc.allowFrom.push(base);
81
+ try {
82
+ appendUnique(sourcePath, ["wrc", "allowFrom"], base);
83
+ }
84
+ catch (e) {
85
+ log.error({ err: e.message }, "weixin allowFrom write failed");
86
+ }
87
+ }
88
+ if (!hasSession(base)) {
89
+ const wiz = settleName(wizardStore(), name, base);
90
+ const r = await newSession(base, wiz || name);
91
+ if (!r.ok)
92
+ log.warn({ base, reason: r.reason }, "weixin default wizard spawn failed (首条消息时会再开)");
93
+ }
94
+ return name;
95
+ };
96
+ /** 解绑时撤销授权 (群名与 wizard 留着 —— 历史还在 rolepage 上)。 */
97
+ export const revokeAllow = (cfg, sourcePath, chatId) => {
98
+ const base = `chat:${chatId}`;
99
+ if (!cfg.wrc.allowFrom.includes(base))
100
+ return;
101
+ cfg.wrc.allowFrom = cfg.wrc.allowFrom.filter((x) => x !== base);
102
+ patchJsonc(sourcePath, [{ path: ["wrc", "allowFrom"], value: cfg.wrc.allowFrom }]);
103
+ };
104
+ // ── 二维码 ───────────────────────────────────────────────────────────
105
+ export const qrPng = async (content) => {
106
+ const dir = join(tmpdir(), "wezard-wx");
107
+ mkdirSync(dir, { recursive: true });
108
+ const path = join(dir, `qr-${Date.now().toString(36)}.png`);
109
+ writeFileSync(path, await QRCode.toBuffer(content, { type: "png", width: 420, margin: 2 }));
110
+ return path;
111
+ };
112
+ /** 解绑参数: 序号 / 群名 / chat:wx_… / wx_… → chatId。 */
113
+ const pickAccount = (cfg, xs, arg) => {
114
+ const n = Number(arg);
115
+ if (Number.isInteger(n) && n >= 1)
116
+ return xs[n - 1];
117
+ const a = arg.replace(/^chat:/, "").toLowerCase();
118
+ return xs.find((x) => x.chatId.toLowerCase() === a || chatNameOf(cfg, `chat:${x.chatId}`).toLowerCase() === a);
119
+ };
120
+ /** 企微侧一次绑定的进度推送: 新码发图, 关键状态各一句。 */
121
+ export const wecomBindSink = (d, to) => {
122
+ let lastQr = "";
123
+ let last = "";
124
+ return (v) => {
125
+ if (v.status === "qr" && v.qrUrl && v.qrUrl !== lastQr) {
126
+ lastQr = v.qrUrl;
127
+ void (async () => {
128
+ try {
129
+ const r = await d.sendWecomMedia(to, { path: await qrPng(v.qrUrl), kind: "image", name: "weixin-bind.png" });
130
+ if (!r.ok)
131
+ d.log.warn({ reason: r.reason }, "weixin qr image failed");
132
+ }
133
+ catch (e) {
134
+ d.log.warn({ err: e.message }, "weixin qr render failed");
135
+ }
136
+ d.sendWecom(to, `📱 ${v.refresh ? `二维码已换新 (${v.refresh}/3)。` : ""}用**要绑定的那个人的微信**扫上图 (约 2 分钟有效)。手机上只有这一台时: 长按图片存到相册, 微信「扫一扫」右上角选相册。\n\n扫不了也可以在微信里打开: ${v.qrUrl}`);
137
+ })();
138
+ return;
139
+ }
140
+ const line = v.status === "qr" ? "" : viewLine(v);
141
+ if (line && line !== last) {
142
+ last = line;
143
+ d.sendWecom(to, line);
144
+ }
145
+ };
146
+ };
147
+ export const makeWxCommands = (d) => async (ctx, cmd) => {
148
+ const { cfg, wx } = d;
149
+ if (!isWxAdmin(cfg, ctx.sender)) {
150
+ d.log.info({ sender: ctx.sender, chat: ctx.chat, admins: wxAdmins(cfg) }, "/wx rejected: not an admin");
151
+ return ctx.reply(`[wezard] \`/wx\` 只有审批人能用 (approval.approvers; 空则 defaultChat 与 allowFrom 里的人), 你是 \`${ctx.sender}\``);
152
+ }
153
+ if (cmd.verb === "help")
154
+ return ctx.reply(HELP);
155
+ if (cmd.verb === "list")
156
+ return ctx.reply(renderAccounts(cfg, wx.list()));
157
+ if (cmd.verb === "bind") {
158
+ if (!cfg.weixin.enabled)
159
+ return ctx.reply("[wezard] 微信通道未开启: 先 `config_set weixin.enabled=true` (放权项, 会推卡确认), reload 后再 `/wx bind`");
160
+ const r = wx.startBind(ctx.sender, cmd.name, wecomBindSink(d, ctx.chat), ctx.chat);
161
+ return r.ok ? undefined : ctx.reply(`[wezard] ${r.reason}`);
162
+ }
163
+ if (cmd.verb === "code") {
164
+ const r = wx.submitCode(ctx.sender, cmd.code);
165
+ return ctx.reply(r.ok ? "🔢 配对码已提交, 校验中…" : `[wezard] ${r.reason}`);
166
+ }
167
+ const a = pickAccount(cfg, wx.list(), cmd.arg);
168
+ if (!a)
169
+ return ctx.reply(`[wezard] 认不出要解绑哪个: \`${cmd.arg || "(空)"}\`\n\n${renderAccounts(cfg, wx.list())}`);
170
+ const r = wx.unbind(a.chatId);
171
+ if (r.ok)
172
+ revokeAllow(cfg, d.sourcePath, a.chatId);
173
+ return ctx.reply(r.ok ? `🗑️ 已解绑 \`${chatNameOf(cfg, `chat:${a.chatId}`) || a.chatId}\` (群聊、wizard 与记录保留; 微信客户端里那个对话可能还在, 但已无人应答)` : `[wezard] ${r.reason}`);
174
+ };
175
+ // inbound 的 gate 只认这一个钩子, 不改 installInboundRouter 的签名。
176
+ let handler;
177
+ export const bindWxCommands = (fn) => { handler = fn; };
178
+ export const wxCommandHandler = () => handler;
179
+ /** 全部要出示 daemon 口令 (index.ts 套 guarded); rolepage 读的是推送的 facts, 不走这里。 */
180
+ export const wxRoutes = (d) => ({
181
+ "GET /wx/list": (_req, res) => json(res, 200, {
182
+ ok: true,
183
+ enabled: d.cfg.weixin.enabled,
184
+ max: d.cfg.weixin.maxAccounts,
185
+ accounts: d.wx.list().map((a) => ({
186
+ chatId: a.chatId, name: chatNameOf(d.cfg, `chat:${a.chatId}`), state: a.state, boundBy: a.boundBy, boundAt: a.boundAt,
187
+ lastInAt: a.lastInAt ?? 0, lastOutAt: a.lastOutAt ?? 0, held: a.outbox.length,
188
+ budget: a.ctx ? Math.max(0, d.cfg.weixin.sendCap - a.ctx.used) : 0, sent: a.sent ?? 0, failed: a.failed ?? 0,
189
+ pausedUntil: a.pausedUntil ?? 0,
190
+ })),
191
+ }),
192
+ "POST /wx/bind": async (req, res) => {
193
+ const b = (await readBody(req));
194
+ const name = (b.name ?? "").trim();
195
+ if (!d.cfg.weixin.enabled) {
196
+ json(res, 400, { ok: false, reason: "微信通道未开启 (weixin.enabled=false)" });
197
+ return;
198
+ }
199
+ const yes = await d.confirmBind(name).catch((e) => { json(res, 503, { ok: false, reason: `确认卡发不出去: ${e.message}` }); return undefined; });
200
+ if (yes === undefined)
201
+ return;
202
+ if (!yes) {
203
+ json(res, 403, { ok: false, reason: "审批人没有同意 (拒绝或超时)" });
204
+ return;
205
+ }
206
+ const r = d.wx.startBind("cli", name, () => undefined, "cli");
207
+ json(res, r.ok ? 200 : 400, r);
208
+ },
209
+ "GET /wx/bind/status": (_req, res, url) => {
210
+ const v = d.wx.bindOf(url.searchParams.get("id") || "cli");
211
+ json(res, v ? 200 : 404, v ? { ok: true, view: v } : { ok: false, reason: "no such bind" });
212
+ },
213
+ "POST /wx/bind/code": async (req, res) => {
214
+ const b = (await readBody(req));
215
+ const r = d.wx.submitCode("cli", (b.code ?? "").trim());
216
+ json(res, r.ok ? 200 : 400, r);
217
+ },
218
+ "POST /wx/unbind": async (req, res) => {
219
+ const b = (await readBody(req));
220
+ const a = pickAccount(d.cfg, d.wx.list(), (b.chat ?? "").trim());
221
+ if (!a) {
222
+ json(res, 404, { ok: false, reason: "no such account" });
223
+ return;
224
+ }
225
+ const r = d.wx.unbind(a.chatId);
226
+ if (r.ok)
227
+ revokeAllow(d.cfg, d.sourcePath, a.chatId);
228
+ json(res, r.ok ? 200 : 400, r);
229
+ },
230
+ });
231
+ // ── 微信侧 SendMedia ─────────────────────────────────────────────────
232
+ const WX_KIND = { image: "image", video: "video", file: "file", voice: "file" };
233
+ /** 微信不发语音条 (官方插件也不发, 社区: 发出后客户端不显示) → 当文件; 上限 WX_MEDIA_MAX。 */
234
+ export const planWxMedia = (spec) => {
235
+ if (!spec.path.startsWith("/"))
236
+ return { ok: false, reason: `path 要写绝对路径: ${spec.path}` };
237
+ const st = (() => { try {
238
+ return statSync(spec.path);
239
+ }
240
+ catch {
241
+ return undefined;
242
+ } })();
243
+ if (!st?.isFile())
244
+ return { ok: false, reason: `文件不存在或不是普通文件: ${spec.path}` };
245
+ const name = spec.name?.trim() || basename(spec.path);
246
+ const bytes = Number(st.size);
247
+ if (bytes > WX_MEDIA_MAX)
248
+ return { ok: false, reason: `微信侧单文件上限 ${WX_MEDIA_MAX / 1024 / 1024}MB, 「${name}」有 ${(bytes / 1024 / 1024).toFixed(1)}MB` };
249
+ const kind = spec.kind ?? kindOf(name);
250
+ return { ok: true, kind: kind === "voice" ? "file" : kind, name, bytes };
251
+ };
252
+ export const weixinSendMedia = (wx) => async (target, spec) => {
253
+ const chatId = baseOfKey(target).replace(/^chat:/, "");
254
+ const plan = planWxMedia(spec);
255
+ if (!plan.ok)
256
+ return plan;
257
+ const r = await wx.sendMedia(chatId, { path: spec.path, kind: WX_KIND[plan.kind], name: plan.name });
258
+ return r.ok ? plan : r;
259
+ };
260
+ /** 按收件聊天分流: 绑定过的微信群聊走微信, 其余企微。 */
261
+ export const routeSendMedia = (wx, wxSend, aibot) => {
262
+ const isWx = (t) => wx.owns(baseOfKey(t).replace(/^chat:/, ""));
263
+ return {
264
+ send: (t, s) => (isWx(t) ? wxSend(t, s) : aibot(t, s)),
265
+ plan: (t, s) => (isWx(t) ? planWxMedia(s) : planMedia(s)),
266
+ };
267
+ };
268
+ //# sourceMappingURL=weixin-cmd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weixin-cmd.js","sourceRoot":"","sources":["../../daemon/weixin-cmd.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,226 @@
1
+ import { renderCard, renderAck, choicesOf, parseMenuReply, clickOf, mintCode, wxMarkdown, WX_REQ as REQ } from "../shared/wx-text.js";
2
+ import { getPending } from "./pending.js";
3
+ const CARD_TTL_MS = 24 * 3600_000;
4
+ /** `wx:<chatId>:<n>` → chatId; 不是微信帧返回 undefined。 */
5
+ const chatOfFrame = (frame) => {
6
+ const id = frame?.headers?.req_id;
7
+ return typeof id === "string" && id.startsWith(REQ) ? id.slice(REQ.length).split(":")[0] : undefined;
8
+ };
9
+ const ack = (reqId) => ({ headers: { req_id: reqId }, errcode: 0, errmsg: "ok" });
10
+ export const installWeixinPort = (client, wx, log) => {
11
+ const cards = new Map();
12
+ const live = (chatId) => {
13
+ const now = Date.now();
14
+ const xs = (cards.get(chatId) ?? []).filter((c) => now - c.at < CARD_TTL_MS && (!c.tracked || !!getPending(c.taskId)));
15
+ cards.set(chatId, xs);
16
+ return xs;
17
+ };
18
+ let seq = 0;
19
+ const reqId = (chatId) => `${REQ}${chatId}:${Date.now().toString(36)}${(seq++).toString(36)}`;
20
+ const isWx = (chatId) => !!chatId && wx.owns(chatId);
21
+ // ── 出站 ──
22
+ const text = (chatId, md) => {
23
+ const out = wxMarkdown(md);
24
+ if (out)
25
+ wx.send(chatId, out);
26
+ };
27
+ const card = (chatId, c) => {
28
+ const choices = choicesOf(c);
29
+ const taskId = c.task_id ?? "";
30
+ // 同一 task_id 重发 (reload 续接、改卡重推) 顶替旧条目, 沿用旧短码 —— 人手里那张菜单仍然作数。
31
+ const open = live(chatId);
32
+ const prev = taskId ? open.find((x) => x.taskId === taskId) : undefined;
33
+ const code = prev?.code ?? mintCode(new Set(open.map((x) => x.code)));
34
+ if (choices.kind !== "none") {
35
+ cards.set(chatId, [...open.filter((x) => x !== prev), { code, taskId, choices, cardType: c.card_type, at: Date.now(), tracked: !!taskId && !!getPending(taskId) }]);
36
+ }
37
+ wx.send(chatId, renderCard(c, code), { card: true });
38
+ };
39
+ const body = (chatId, b) => {
40
+ const t = b.msgtype;
41
+ if (t === "markdown")
42
+ return text(chatId, String(b.markdown?.content ?? ""));
43
+ if (t === "template_card")
44
+ return card(chatId, b.template_card);
45
+ if (t === "stream") {
46
+ const st = b.stream;
47
+ return st.finish ? (wx.typing(chatId, false), text(chatId, st.content ?? "")) : wx.typing(chatId, true);
48
+ }
49
+ log.warn({ chatId, msgtype: t }, "weixin port: unsupported outbound msgtype — dropped");
50
+ };
51
+ const orig = {
52
+ sendMessage: client.sendMessage.bind(client),
53
+ reply: client.reply.bind(client),
54
+ replyStream: client.replyStream.bind(client),
55
+ replyStreamNonBlocking: client.replyStreamNonBlocking.bind(client),
56
+ replyStreamWithCard: client.replyStreamWithCard.bind(client),
57
+ replyTemplateCard: client.replyTemplateCard.bind(client),
58
+ updateTemplateCard: client.updateTemplateCard.bind(client),
59
+ replyWelcome: client.replyWelcome.bind(client),
60
+ replyMedia: client.replyMedia.bind(client),
61
+ sendMediaMessage: client.sendMediaMessage.bind(client),
62
+ hasPendingReplyAck: client.hasPendingReplyAck.bind(client),
63
+ downloadFile: client.downloadFile.bind(client),
64
+ };
65
+ client.sendMessage = async (chatid, b) => (isWx(chatid) ? (body(chatid, b), ack(reqId(chatid))) : orig.sendMessage(chatid, b));
66
+ client.reply = async (frame, b, cmd) => {
67
+ const c = chatOfFrame(frame);
68
+ return isWx(c) ? (body(c, b), ack(frame.headers.req_id)) : orig.reply(frame, b, cmd);
69
+ };
70
+ const stream = (c, content, finish) => {
71
+ if (finish) {
72
+ wx.typing(c, false);
73
+ text(c, content);
74
+ }
75
+ else
76
+ wx.typing(c, true);
77
+ };
78
+ client.replyStream = async (frame, id, content, finish, msgItem, feedback) => {
79
+ const c = chatOfFrame(frame);
80
+ return isWx(c) ? (stream(c, content, finish), ack(frame.headers.req_id)) : orig.replyStream(frame, id, content, finish, msgItem, feedback);
81
+ };
82
+ client.replyStreamNonBlocking = async (frame, id, content, finish, msgItem, feedback) => {
83
+ const c = chatOfFrame(frame);
84
+ return isWx(c) ? (stream(c, content, finish), ack(frame.headers.req_id)) : orig.replyStreamNonBlocking(frame, id, content, finish, msgItem, feedback);
85
+ };
86
+ client.replyStreamWithCard = async (frame, id, content, finish, options) => {
87
+ const c = chatOfFrame(frame);
88
+ if (!isWx(c))
89
+ return orig.replyStreamWithCard(frame, id, content, finish, options);
90
+ stream(c, content, finish);
91
+ if (options?.templateCard)
92
+ card(c, options.templateCard);
93
+ return ack(frame.headers.req_id);
94
+ };
95
+ client.replyTemplateCard = async (frame, c0, feedback) => {
96
+ const c = chatOfFrame(frame);
97
+ return isWx(c) ? (card(c, c0), ack(frame.headers.req_id)) : orig.replyTemplateCard(frame, c0, feedback);
98
+ };
99
+ // 点击 (数字回复) 之后的改卡 → 一行回执, 并把这张卡从待答表里摘掉。
100
+ client.updateTemplateCard = async (frame, c0, userids) => {
101
+ const c = chatOfFrame(frame);
102
+ if (!isWx(c))
103
+ return orig.updateTemplateCard(frame, c0, userids);
104
+ // 查原表而不是 live(): 点击一 resolve, 这张卡就已不在待决表里了, 回执还要用它的短码。
105
+ const open = cards.get(c) ?? [];
106
+ const hit = open.find((x) => x.taskId && x.taskId === c0.task_id);
107
+ if (hit)
108
+ cards.set(c, open.filter((x) => x !== hit));
109
+ wx.send(c, renderAck(c0, hit?.code ?? "卡片"), { card: true });
110
+ return ack(frame.headers.req_id);
111
+ };
112
+ client.replyWelcome = async (frame, b) => (isWx(chatOfFrame(frame)) ? ack(frame.headers.req_id) : orig.replyWelcome(frame, b));
113
+ // 媒体走 SendMedia (index.ts 按聊天分流), 不经这两个口; 走到这里说明有人绕过了它。
114
+ client.replyMedia = async (frame, kind, mediaId, video) => {
115
+ const c = chatOfFrame(frame);
116
+ if (!isWx(c))
117
+ return orig.replyMedia(frame, kind, mediaId, video);
118
+ log.warn({ chatId: c, kind }, "weixin port: replyMedia bypassed SendMedia — dropped");
119
+ return ack(frame.headers.req_id);
120
+ };
121
+ client.sendMediaMessage = async (chatid, kind, mediaId, video) => {
122
+ if (!isWx(chatid))
123
+ return orig.sendMediaMessage(chatid, kind, mediaId, video);
124
+ log.warn({ chatId: chatid, kind }, "weixin port: sendMediaMessage bypassed SendMedia — dropped");
125
+ return ack(reqId(chatid));
126
+ };
127
+ client.hasPendingReplyAck = (frame) => (isWx(chatOfFrame(frame)) ? false : orig.hasPendingReplyAck(frame));
128
+ client.downloadFile = async (url, aesKey) => (url.startsWith("wxcdn:") ? wx.download(url) : orig.downloadFile(url, aesKey));
129
+ // ── 入站 ──
130
+ const frameOf = (m, extra) => ({
131
+ cmd: "aibot_msg_callback",
132
+ headers: { req_id: reqId(m.chatId) },
133
+ body: {
134
+ msgid: m.msgId,
135
+ aibotid: "weixin",
136
+ chatid: m.chatId,
137
+ chattype: "group",
138
+ from: { userid: m.chatId },
139
+ create_time: Math.floor(m.at / 1000),
140
+ ...(m.quote ? { quote: { msgtype: "text", text: { content: m.quote } } } : {}),
141
+ ...extra,
142
+ },
143
+ });
144
+ const emit = (name, f) => {
145
+ try {
146
+ const e = client.emit.bind(client);
147
+ e("message", f);
148
+ e(name, f);
149
+ }
150
+ catch (e) {
151
+ log.error({ name, err: e.message }, "weixin port: inbound listener threw");
152
+ }
153
+ };
154
+ // 人回的是菜单数字 → 合成点击; 返回 true = 已消费, 不再当普通消息派给 wizard。
155
+ // 拿不准是在答哪张卡 (短码对不上、多张待答又没带短码) 就不吞: 照常交给 wizard ——
156
+ // 「k7q 1」「top 3」也可能就是一句话。
157
+ const answerCard = (m) => {
158
+ if (m.images.length || m.files.length)
159
+ return false;
160
+ const r = parseMenuReply(m.text);
161
+ const open = live(m.chatId);
162
+ if (!r || open.length === 0)
163
+ return false;
164
+ const target = r.code ? open.find((x) => x.code === r.code) : open.length === 1 ? open[0] : undefined;
165
+ if (!target) {
166
+ if (!r.code)
167
+ wx.send(m.chatId, `有 ${open.length} 张待答卡 (${open.map((x) => x.code).join(" / ")}), 要作答请带短码, 如 "${open[0].code} 1" —— 刚才那句已照常转给 wizard`);
168
+ return false;
169
+ }
170
+ const click = clickOf(target.choices, r.picks);
171
+ if (!click) {
172
+ wx.send(m.chatId, `${target.code}: 选项不对, 请回菜单里的编号${target.choices.kind === "vote" && target.choices.multi ? " (可多个, 空格隔开)" : ""}`);
173
+ return true;
174
+ }
175
+ // 投票卡提交后企微不改卡 —— 这里先摘; 按钮卡等 updateTemplateCard 回执时摘。
176
+ if (target.choices.kind === "vote")
177
+ cards.set(m.chatId, open.filter((x) => x !== target));
178
+ const tce = { card_type: target.cardType, event_key: click.eventKey, task_id: target.taskId, ...(click.selected ? { selected_items: click.selected } : {}) };
179
+ const f = {
180
+ cmd: "aibot_event_callback",
181
+ headers: { req_id: reqId(m.chatId) },
182
+ body: {
183
+ msgid: m.msgId, aibotid: "weixin", chatid: m.chatId, chattype: "group", from: { userid: m.chatId },
184
+ create_time: Math.floor(m.at / 1000), msgtype: "event",
185
+ event: { eventtype: "template_card_event", ...tce, template_card_event: tce },
186
+ },
187
+ };
188
+ log.info({ chatId: m.chatId, code: target.code, eventKey: click.eventKey }, "weixin menu reply → card event");
189
+ try {
190
+ const e = client.emit.bind(client);
191
+ e("event", f);
192
+ e("event.template_card_event", f);
193
+ }
194
+ catch (e) {
195
+ log.error({ err: e.message }, "weixin port: card listener threw");
196
+ }
197
+ return true;
198
+ };
199
+ wx.onInbound((m) => {
200
+ if (answerCard(m))
201
+ return;
202
+ const [file] = m.files;
203
+ if (file) {
204
+ emit(`message.${file.kind}`, frameOf(m, { msgtype: file.kind, [file.kind]: { url: file.ref } }));
205
+ // 文件之外同一条里还有字 / 图: 照常再走一遍 (微信一条消息通常只有一项, 这是兜底)。
206
+ if (!m.text && !m.images.length)
207
+ return;
208
+ }
209
+ if (m.images.length && !m.text && m.images.length === 1) {
210
+ emit("message.image", frameOf(m, { msgtype: "image", image: { url: m.images[0] } }));
211
+ return;
212
+ }
213
+ if (m.images.length) {
214
+ const items = [
215
+ ...(m.text ? [{ msgtype: "text", text: { content: m.text } }] : []),
216
+ ...m.images.map((u) => ({ msgtype: "image", image: { url: u } })),
217
+ ];
218
+ emit("message.mixed", frameOf(m, { msgtype: "mixed", mixed: { msg_item: items } }));
219
+ return;
220
+ }
221
+ if (m.text)
222
+ emit("message.text", frameOf(m, { msgtype: "text", text: { content: m.text } }));
223
+ });
224
+ return { openCards: (chatId) => live(chatId) };
225
+ };
226
+ //# sourceMappingURL=weixin-port.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weixin-port.js","sourceRoot":"","sources":["../../daemon/weixin-port.ts"],"names":[],"mappings":"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"}