@pawastation/wechat-kf 0.1.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.
- package/LICENSE +21 -0
- package/README.md +291 -0
- package/README.zh-CN.md +401 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/src/accounts.d.ts +37 -0
- package/dist/src/accounts.js +205 -0
- package/dist/src/accounts.js.map +1 -0
- package/dist/src/api.d.ts +29 -0
- package/dist/src/api.js +172 -0
- package/dist/src/api.js.map +1 -0
- package/dist/src/bot.d.ts +35 -0
- package/dist/src/bot.js +379 -0
- package/dist/src/bot.js.map +1 -0
- package/dist/src/channel.d.ts +113 -0
- package/dist/src/channel.js +183 -0
- package/dist/src/channel.js.map +1 -0
- package/dist/src/chunk-utils.d.ts +18 -0
- package/dist/src/chunk-utils.js +58 -0
- package/dist/src/chunk-utils.js.map +1 -0
- package/dist/src/config-schema.d.ts +56 -0
- package/dist/src/config-schema.js +38 -0
- package/dist/src/config-schema.js.map +1 -0
- package/dist/src/constants.d.ts +19 -0
- package/dist/src/constants.js +20 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/crypto.d.ts +18 -0
- package/dist/src/crypto.js +80 -0
- package/dist/src/crypto.js.map +1 -0
- package/dist/src/fs-utils.d.ts +7 -0
- package/dist/src/fs-utils.js +13 -0
- package/dist/src/fs-utils.js.map +1 -0
- package/dist/src/monitor.d.ts +18 -0
- package/dist/src/monitor.js +131 -0
- package/dist/src/monitor.js.map +1 -0
- package/dist/src/outbound.d.ts +66 -0
- package/dist/src/outbound.js +234 -0
- package/dist/src/outbound.js.map +1 -0
- package/dist/src/reply-dispatcher.d.ts +40 -0
- package/dist/src/reply-dispatcher.js +120 -0
- package/dist/src/reply-dispatcher.js.map +1 -0
- package/dist/src/runtime.d.ts +130 -0
- package/dist/src/runtime.js +22 -0
- package/dist/src/runtime.js.map +1 -0
- package/dist/src/send-utils.d.ts +30 -0
- package/dist/src/send-utils.js +89 -0
- package/dist/src/send-utils.js.map +1 -0
- package/dist/src/send.d.ts +7 -0
- package/dist/src/send.js +13 -0
- package/dist/src/send.js.map +1 -0
- package/dist/src/token.d.ts +8 -0
- package/dist/src/token.js +57 -0
- package/dist/src/token.js.map +1 -0
- package/dist/src/types.d.ts +173 -0
- package/dist/src/types.js +3 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/unicode-format.d.ts +26 -0
- package/dist/src/unicode-format.js +157 -0
- package/dist/src/unicode-format.js.map +1 -0
- package/dist/src/webhook.d.ts +22 -0
- package/dist/src/webhook.js +138 -0
- package/dist/src/webhook.js.map +1 -0
- package/dist/src/wechat-kf-directives.d.ts +34 -0
- package/dist/src/wechat-kf-directives.js +65 -0
- package/dist/src/wechat-kf-directives.js.map +1 -0
- package/index.ts +32 -0
- package/openclaw.plugin.json +31 -0
- package/package.json +91 -0
package/dist/src/bot.js
ADDED
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message processing — pull messages via sync_msg and dispatch to OpenClaw agent.
|
|
3
|
+
*
|
|
4
|
+
* Architecture:
|
|
5
|
+
* - Each openKfId is an independent account with its own cursor and session
|
|
6
|
+
* - sync_msg is called with open_kfid filter to only pull messages for that kf account
|
|
7
|
+
* - Plugin layer: download media, save via MediaPaths/MediaTypes
|
|
8
|
+
* - OpenClaw runner: handles media understanding (transcription, vision, etc.)
|
|
9
|
+
*/
|
|
10
|
+
import { mkdir, readFile } from "node:fs/promises";
|
|
11
|
+
import { join } from "node:path";
|
|
12
|
+
import { getChannelConfig, registerKfId, resolveAccount } from "./accounts.js";
|
|
13
|
+
import { downloadMedia, syncMessages } from "./api.js";
|
|
14
|
+
import { atomicWriteFile } from "./fs-utils.js";
|
|
15
|
+
import { createReplyDispatcher } from "./reply-dispatcher.js";
|
|
16
|
+
import { getRuntime } from "./runtime.js";
|
|
17
|
+
// ── Per-kfId async mutex ──
|
|
18
|
+
// Ensures that concurrent calls to handleWebhookEvent for the same openKfId
|
|
19
|
+
// (e.g. from webhook + polling simultaneously) are serialized.
|
|
20
|
+
const kfLocks = new Map();
|
|
21
|
+
// ── Message deduplication ──
|
|
22
|
+
// Tracks recently-processed msgids to avoid dispatching the same message twice,
|
|
23
|
+
// even if sync_msg returns overlapping batches from concurrent paths.
|
|
24
|
+
const processedMsgIds = new Set();
|
|
25
|
+
const DEDUP_MAX_SIZE = 10_000;
|
|
26
|
+
function isDuplicate(msgid) {
|
|
27
|
+
if (processedMsgIds.has(msgid))
|
|
28
|
+
return true;
|
|
29
|
+
if (processedMsgIds.size >= DEDUP_MAX_SIZE) {
|
|
30
|
+
// Evict the oldest half (Set preserves insertion order)
|
|
31
|
+
const entries = [...processedMsgIds];
|
|
32
|
+
processedMsgIds.clear();
|
|
33
|
+
for (const id of entries.slice(entries.length >>> 1)) {
|
|
34
|
+
processedMsgIds.add(id);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
processedMsgIds.add(msgid);
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
/** Exposed for testing only — do not use in production code. */
|
|
41
|
+
export const _testing = {
|
|
42
|
+
kfLocks,
|
|
43
|
+
processedMsgIds,
|
|
44
|
+
isDuplicate,
|
|
45
|
+
DEDUP_MAX_SIZE,
|
|
46
|
+
handleEvent,
|
|
47
|
+
resetState() {
|
|
48
|
+
kfLocks.clear();
|
|
49
|
+
processedMsgIds.clear();
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
// ── Cursor persistence (per kfid) ──
|
|
53
|
+
async function loadCursor(stateDir, kfId) {
|
|
54
|
+
try {
|
|
55
|
+
return (await readFile(join(stateDir, `wechat-kf-cursor-${kfId}.txt`), "utf8")).trim();
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return "";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
let dirCreated = false;
|
|
62
|
+
async function saveCursor(stateDir, kfId, cursor) {
|
|
63
|
+
if (!dirCreated) {
|
|
64
|
+
await mkdir(stateDir, { recursive: true });
|
|
65
|
+
dirCreated = true;
|
|
66
|
+
}
|
|
67
|
+
await atomicWriteFile(join(stateDir, `wechat-kf-cursor-${kfId}.txt`), cursor);
|
|
68
|
+
}
|
|
69
|
+
// ── Message text extraction ──
|
|
70
|
+
// Descriptions of non-text messages injected into the AI agent's context.
|
|
71
|
+
// Kept in Chinese because end-users are Chinese WeChat users and the agent
|
|
72
|
+
// replies in Chinese. These are NOT displayed to end-users directly.
|
|
73
|
+
function extractText(msg) {
|
|
74
|
+
switch (msg.msgtype) {
|
|
75
|
+
case "text":
|
|
76
|
+
return msg.text?.content ?? "";
|
|
77
|
+
case "image":
|
|
78
|
+
return "[用户发送了一张图片]";
|
|
79
|
+
case "voice":
|
|
80
|
+
return "[用户发送了一段语音]";
|
|
81
|
+
case "video":
|
|
82
|
+
return "[用户发送了一段视频]";
|
|
83
|
+
case "file":
|
|
84
|
+
return "[用户发送了一个文件]";
|
|
85
|
+
case "location": {
|
|
86
|
+
const locDetail = [msg.location?.name, msg.location?.address].filter(Boolean).join(" ");
|
|
87
|
+
return locDetail ? `[位置: ${locDetail}]` : "[位置]";
|
|
88
|
+
}
|
|
89
|
+
case "link":
|
|
90
|
+
return `[链接: ${msg.link?.title ?? ""} ${msg.link?.url ?? ""}]`;
|
|
91
|
+
case "merged_msg": {
|
|
92
|
+
const merged = msg.merged_msg;
|
|
93
|
+
if (!merged)
|
|
94
|
+
return "[转发的聊天记录]";
|
|
95
|
+
const title = merged.title ?? "聊天记录";
|
|
96
|
+
const items = Array.isArray(merged.item) ? merged.item : [];
|
|
97
|
+
const lines = items.map((item) => {
|
|
98
|
+
const sender = item.sender_name ?? "未知";
|
|
99
|
+
let content = "";
|
|
100
|
+
try {
|
|
101
|
+
const parsed = JSON.parse(item.msg_content ?? "{}");
|
|
102
|
+
const parsedText = parsed.text;
|
|
103
|
+
if (parsedText?.content)
|
|
104
|
+
content = parsedText.content;
|
|
105
|
+
else if (parsed.image)
|
|
106
|
+
content = "[图片]";
|
|
107
|
+
else if (parsed.voice)
|
|
108
|
+
content = "[语音]";
|
|
109
|
+
else if (parsed.video)
|
|
110
|
+
content = "[视频]";
|
|
111
|
+
else if (parsed.file)
|
|
112
|
+
content = "[文件]";
|
|
113
|
+
else if (parsed.link)
|
|
114
|
+
content = `[链接: ${parsed.link?.title ?? ""}]`;
|
|
115
|
+
else
|
|
116
|
+
content = `[${parsed.msgtype ?? "未知类型"}]`;
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
content = item.msg_content ?? "";
|
|
120
|
+
}
|
|
121
|
+
return `${sender}: ${content}`;
|
|
122
|
+
});
|
|
123
|
+
return `[转发的聊天记录: ${title}]\n${lines.join("\n")}`;
|
|
124
|
+
}
|
|
125
|
+
case "channels": {
|
|
126
|
+
const ch = msg.channels;
|
|
127
|
+
const typeMap = { 1: "视频号动态", 2: "视频号直播", 3: "视频号名片" };
|
|
128
|
+
const typeName = ch?.sub_type != null ? (typeMap[ch.sub_type] ?? "视频号消息") : "视频号消息";
|
|
129
|
+
return `[${typeName}] ${ch?.nickname ?? ""}: ${ch?.title ?? ""}`;
|
|
130
|
+
}
|
|
131
|
+
case "miniprogram": {
|
|
132
|
+
const mp = msg.miniprogram;
|
|
133
|
+
return `[小程序] ${mp?.title ?? ""} (appid: ${mp?.appid ?? ""})`;
|
|
134
|
+
}
|
|
135
|
+
case "msgmenu": {
|
|
136
|
+
const menu = msg.msgmenu;
|
|
137
|
+
const head = menu?.head_content ?? "";
|
|
138
|
+
const items = Array.isArray(menu?.list) ? menu.list.map((item) => item.content ?? item.id).join(", ") : "";
|
|
139
|
+
return head ? `${head} [选项: ${items}]` : `[菜单消息: ${items}]`;
|
|
140
|
+
}
|
|
141
|
+
case "business_card":
|
|
142
|
+
return `[名片] userid: ${msg.business_card?.userid ?? ""}`;
|
|
143
|
+
case "event":
|
|
144
|
+
return null;
|
|
145
|
+
default:
|
|
146
|
+
return `[未支持的消息类型: ${msg.msgtype}]`;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// ── Event handling ──
|
|
150
|
+
async function handleEvent(ctx, _account, msg) {
|
|
151
|
+
const event = msg.event;
|
|
152
|
+
const { log } = ctx;
|
|
153
|
+
const kfId = msg.open_kfid;
|
|
154
|
+
switch (event?.event_type) {
|
|
155
|
+
case "enter_session":
|
|
156
|
+
log?.info(`[wechat-kf:${kfId}] user ${msg.external_userid} entered session` +
|
|
157
|
+
(event.welcome_code ? `, welcome_code=${event.welcome_code}` : "") +
|
|
158
|
+
(event.scene ? `, scene=${event.scene}` : ""));
|
|
159
|
+
break;
|
|
160
|
+
case "msg_send_fail":
|
|
161
|
+
log?.error(`[wechat-kf:${kfId}] message send failed: msgid=${event.fail_msgid}, type=${event.fail_type}`);
|
|
162
|
+
break;
|
|
163
|
+
case "servicer_status_change":
|
|
164
|
+
log?.info(`[wechat-kf:${kfId}] servicer status changed: ${event.servicer_userid} -> ${event.status}`);
|
|
165
|
+
break;
|
|
166
|
+
default:
|
|
167
|
+
log?.info(`[wechat-kf:${kfId}] unhandled event: ${event?.event_type}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// ── Core message handler (per kfid) ──
|
|
171
|
+
export async function handleWebhookEvent(ctx, openKfId, syncToken) {
|
|
172
|
+
// Acquire per-kfId mutex — chains onto any in-flight processing for this kfId
|
|
173
|
+
const prev = kfLocks.get(openKfId) ?? Promise.resolve();
|
|
174
|
+
let release;
|
|
175
|
+
const current = new Promise((r) => {
|
|
176
|
+
release = r;
|
|
177
|
+
});
|
|
178
|
+
kfLocks.set(openKfId, current);
|
|
179
|
+
try {
|
|
180
|
+
await prev;
|
|
181
|
+
await _handleWebhookEventInner(ctx, openKfId, syncToken);
|
|
182
|
+
}
|
|
183
|
+
finally {
|
|
184
|
+
release();
|
|
185
|
+
// Clean up map entry only if no newer caller has replaced it
|
|
186
|
+
if (kfLocks.get(openKfId) === current) {
|
|
187
|
+
kfLocks.delete(openKfId);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
async function _handleWebhookEventInner(ctx, openKfId, syncToken) {
|
|
192
|
+
const { cfg, stateDir, log } = ctx;
|
|
193
|
+
const account = resolveAccount(cfg, openKfId); // kfid as accountId
|
|
194
|
+
const { corpId, appSecret } = account;
|
|
195
|
+
if (!corpId || !appSecret) {
|
|
196
|
+
log?.error("[wechat-kf] missing corpId/appSecret");
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
// Register this kfid as discovered
|
|
200
|
+
await registerKfId(openKfId);
|
|
201
|
+
let cursor = await loadCursor(stateDir, openKfId);
|
|
202
|
+
let hasMore = true;
|
|
203
|
+
while (hasMore) {
|
|
204
|
+
const syncReq = {
|
|
205
|
+
limit: 1000,
|
|
206
|
+
open_kfid: openKfId, // Only pull messages for this kf account
|
|
207
|
+
};
|
|
208
|
+
if (cursor) {
|
|
209
|
+
// Have a persisted cursor — use it for incremental fetch (token is ignored)
|
|
210
|
+
syncReq.cursor = cursor;
|
|
211
|
+
}
|
|
212
|
+
else if (syncToken) {
|
|
213
|
+
// No cursor but webhook provided a token — use it for the first fetch
|
|
214
|
+
syncReq.token = syncToken;
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
// Neither cursor nor token — will fetch the initial batch (up to 3 days history)
|
|
218
|
+
log?.info(`[wechat-kf:${openKfId}] no cursor or token, fetching initial batch`);
|
|
219
|
+
}
|
|
220
|
+
let resp;
|
|
221
|
+
try {
|
|
222
|
+
resp = await syncMessages(corpId, appSecret, syncReq);
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
log?.error(`[wechat-kf:${openKfId}] sync_msg failed: ${err instanceof Error ? err.message : err}`);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
for (const msg of resp.msg_list ?? []) {
|
|
229
|
+
// Handle event messages (any origin) before normal message processing
|
|
230
|
+
if (msg.msgtype === "event") {
|
|
231
|
+
await handleEvent(ctx, account, msg);
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
if (msg.origin !== 3)
|
|
235
|
+
continue; // Only customer messages
|
|
236
|
+
// Dedup: skip messages we have already processed
|
|
237
|
+
if (isDuplicate(msg.msgid)) {
|
|
238
|
+
log?.info(`[wechat-kf:${openKfId}] skipping duplicate msg ${msg.msgid}`);
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
const text = extractText(msg);
|
|
242
|
+
if (text === null || text === "")
|
|
243
|
+
continue;
|
|
244
|
+
try {
|
|
245
|
+
await dispatchMessage(ctx, account, msg, text);
|
|
246
|
+
}
|
|
247
|
+
catch (err) {
|
|
248
|
+
log?.error(`[wechat-kf:${openKfId}] dispatch error for msg ${msg.msgid}: ${err instanceof Error ? err.stack || err.message : err}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// P1-02: Save cursor AFTER all messages in the batch are processed
|
|
252
|
+
// (at-least-once delivery). If the process crashes mid-batch, the
|
|
253
|
+
// cursor has not advanced and the batch will be re-fetched on restart.
|
|
254
|
+
// P1-01 msgid dedup ensures replayed messages are not dispatched twice.
|
|
255
|
+
if (resp.next_cursor) {
|
|
256
|
+
cursor = resp.next_cursor;
|
|
257
|
+
await saveCursor(stateDir, openKfId, cursor);
|
|
258
|
+
}
|
|
259
|
+
hasMore = resp.has_more === 1;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// ── Dispatch message to agent ──
|
|
263
|
+
async function dispatchMessage(ctx, account, msg, text) {
|
|
264
|
+
const { cfg, runtime, log } = ctx;
|
|
265
|
+
// ── DM policy check ──
|
|
266
|
+
const channelConfig = getChannelConfig(cfg);
|
|
267
|
+
const dmPolicy = channelConfig.dmPolicy ?? "open";
|
|
268
|
+
const externalUserId = msg.external_userid;
|
|
269
|
+
if (dmPolicy === "disabled") {
|
|
270
|
+
log?.info?.(`[wechat-kf] drop DM (dmPolicy: disabled)`);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
if (dmPolicy === "allowlist") {
|
|
274
|
+
const allowFrom = channelConfig.allowFrom ?? [];
|
|
275
|
+
if (!allowFrom.includes(externalUserId)) {
|
|
276
|
+
log?.info?.(`[wechat-kf] blocked sender ${externalUserId} (dmPolicy: allowlist)`);
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// "open" and "pairing" modes: allow message through
|
|
281
|
+
// Note: full pairing flow requires runtime API support, deferred to P2
|
|
282
|
+
const core = getRuntime();
|
|
283
|
+
const kfId = msg.open_kfid;
|
|
284
|
+
const from = `wechat-kf:${msg.external_userid}`;
|
|
285
|
+
const to = `user:${msg.external_userid}`;
|
|
286
|
+
// Download media
|
|
287
|
+
const mediaPaths = [];
|
|
288
|
+
const mediaTypes = [];
|
|
289
|
+
async function saveMedia(mediaId, mimeType, filename) {
|
|
290
|
+
try {
|
|
291
|
+
const buffer = await downloadMedia(account.corpId, account.appSecret, mediaId);
|
|
292
|
+
const saved = await core.channel.media.saveMediaBuffer(buffer, mimeType, "inbound", undefined, filename);
|
|
293
|
+
mediaPaths.push(saved.path);
|
|
294
|
+
mediaTypes.push(mimeType);
|
|
295
|
+
log?.info(`[wechat-kf:${kfId}] saved media: ${saved.path} (${mimeType})`);
|
|
296
|
+
}
|
|
297
|
+
catch (err) {
|
|
298
|
+
log?.error(`[wechat-kf:${kfId}] failed to save media ${mediaId}: ${err instanceof Error ? err.message : err}`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if (account.corpId && account.appSecret) {
|
|
302
|
+
const mediaId = msg.image?.media_id || msg.voice?.media_id || msg.video?.media_id || msg.file?.media_id;
|
|
303
|
+
if (mediaId) {
|
|
304
|
+
const mimeMap = {
|
|
305
|
+
image: ["image/jpeg", `wechat_image_${msg.msgid}.jpg`],
|
|
306
|
+
voice: ["audio/amr", `wechat_voice_${msg.msgid}.amr`],
|
|
307
|
+
video: ["video/mp4", `wechat_video_${msg.msgid}.mp4`],
|
|
308
|
+
file: ["application/octet-stream", `wechat_file_${msg.msgid}`],
|
|
309
|
+
};
|
|
310
|
+
const [mime, filename] = mimeMap[msg.msgtype] ?? ["application/octet-stream", `wechat_media_${msg.msgid}`];
|
|
311
|
+
await saveMedia(mediaId, mime, filename);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
// Route using kfid as accountId — each kfid gets its own session
|
|
315
|
+
// peer id includes kfid so different kf accounts get isolated sessions
|
|
316
|
+
const route = core.channel.routing.resolveAgentRoute({
|
|
317
|
+
cfg,
|
|
318
|
+
channel: "wechat-kf",
|
|
319
|
+
accountId: kfId,
|
|
320
|
+
peer: { kind: "direct", id: `${kfId}:${msg.external_userid}` },
|
|
321
|
+
});
|
|
322
|
+
// System event
|
|
323
|
+
const preview = text.replace(/\s+/g, " ").slice(0, 160);
|
|
324
|
+
core.system.enqueueSystemEvent(`WeChat-KF[${kfId}] DM from ${msg.external_userid}: ${preview}`, {
|
|
325
|
+
sessionKey: route.sessionKey,
|
|
326
|
+
contextKey: `wechat-kf:message:${msg.msgid}`,
|
|
327
|
+
});
|
|
328
|
+
// Format envelope
|
|
329
|
+
const envelopeOptions = core.channel.reply.resolveEnvelopeFormatOptions(cfg);
|
|
330
|
+
const body = core.channel.reply.formatAgentEnvelope({
|
|
331
|
+
channel: "WeChat-KF",
|
|
332
|
+
from: msg.external_userid,
|
|
333
|
+
timestamp: new Date(msg.send_time * 1000),
|
|
334
|
+
envelope: envelopeOptions,
|
|
335
|
+
body: text,
|
|
336
|
+
});
|
|
337
|
+
// Build inbound context
|
|
338
|
+
const inboundCtx = core.channel.reply.finalizeInboundContext({
|
|
339
|
+
Body: body,
|
|
340
|
+
RawBody: text,
|
|
341
|
+
CommandBody: text,
|
|
342
|
+
From: from,
|
|
343
|
+
To: to,
|
|
344
|
+
SessionKey: route.sessionKey,
|
|
345
|
+
AccountId: kfId,
|
|
346
|
+
ChatType: "direct",
|
|
347
|
+
SenderName: msg.external_userid,
|
|
348
|
+
SenderId: msg.external_userid,
|
|
349
|
+
Provider: "wechat-kf",
|
|
350
|
+
Surface: "wechat-kf",
|
|
351
|
+
MessageSid: msg.msgid,
|
|
352
|
+
Timestamp: msg.send_time * 1000,
|
|
353
|
+
WasMentioned: false,
|
|
354
|
+
CommandAuthorized: true,
|
|
355
|
+
OriginatingChannel: "wechat-kf",
|
|
356
|
+
OriginatingTo: to,
|
|
357
|
+
MediaPaths: mediaPaths.length > 0 ? mediaPaths : undefined,
|
|
358
|
+
MediaTypes: mediaTypes.length > 0 ? mediaTypes : undefined,
|
|
359
|
+
});
|
|
360
|
+
// Dispatch to agent
|
|
361
|
+
const { dispatcher, replyOptions, markDispatchIdle } = createReplyDispatcher({
|
|
362
|
+
cfg,
|
|
363
|
+
agentId: route.agentId,
|
|
364
|
+
runtime: runtime ?? {},
|
|
365
|
+
externalUserId: msg.external_userid,
|
|
366
|
+
openKfId: kfId,
|
|
367
|
+
accountId: kfId,
|
|
368
|
+
});
|
|
369
|
+
log?.info(`[wechat-kf:${kfId}] dispatching to agent (session=${route.sessionKey})`);
|
|
370
|
+
const { queuedFinal, counts } = await core.channel.reply.dispatchReplyFromConfig({
|
|
371
|
+
ctx: inboundCtx,
|
|
372
|
+
cfg,
|
|
373
|
+
dispatcher,
|
|
374
|
+
replyOptions,
|
|
375
|
+
});
|
|
376
|
+
markDispatchIdle?.();
|
|
377
|
+
log?.info(`[wechat-kf:${kfId}] dispatch complete (queuedFinal=${queuedFinal}, replies=${counts?.final})`);
|
|
378
|
+
}
|
|
379
|
+
//# sourceMappingURL=bot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot.js","sourceRoot":"","sources":["../../src/bot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WeChat KF ChannelPlugin implementation
|
|
3
|
+
*
|
|
4
|
+
* Dynamically discovers kfids from webhook callbacks.
|
|
5
|
+
* Each kfid = one accountId = one independent session.
|
|
6
|
+
*/
|
|
7
|
+
import type { Logger } from "./bot.js";
|
|
8
|
+
import { wechatKfOutbound } from "./outbound.js";
|
|
9
|
+
import type { PluginRuntime } from "./runtime.js";
|
|
10
|
+
import type { OpenClawConfig, ResolvedWechatKfAccount } from "./types.js";
|
|
11
|
+
type ChannelMeta = {
|
|
12
|
+
id: string;
|
|
13
|
+
label: string;
|
|
14
|
+
selectionLabel: string;
|
|
15
|
+
docsPath: string;
|
|
16
|
+
docsLabel: string;
|
|
17
|
+
blurb: string;
|
|
18
|
+
aliases?: string[];
|
|
19
|
+
order?: number;
|
|
20
|
+
};
|
|
21
|
+
type ChannelCapabilities = {
|
|
22
|
+
chatTypes: string[];
|
|
23
|
+
media: boolean;
|
|
24
|
+
reactions: boolean;
|
|
25
|
+
threads: boolean;
|
|
26
|
+
polls: boolean;
|
|
27
|
+
nativeCommands: boolean;
|
|
28
|
+
blockStreaming: boolean;
|
|
29
|
+
};
|
|
30
|
+
type AccountRuntimeStatus = {
|
|
31
|
+
accountId: string;
|
|
32
|
+
running: boolean;
|
|
33
|
+
lastStartAt: string | null;
|
|
34
|
+
lastStopAt: string | null;
|
|
35
|
+
lastError: string | null;
|
|
36
|
+
port: number | null;
|
|
37
|
+
};
|
|
38
|
+
type GatewayContext = {
|
|
39
|
+
cfg: OpenClawConfig;
|
|
40
|
+
runtime?: PluginRuntime;
|
|
41
|
+
abortSignal?: AbortSignal;
|
|
42
|
+
accountId: string;
|
|
43
|
+
log?: Logger;
|
|
44
|
+
setStatus?: (status: Partial<AccountRuntimeStatus>) => void;
|
|
45
|
+
};
|
|
46
|
+
type ChannelPlugin<T = unknown> = {
|
|
47
|
+
id: string;
|
|
48
|
+
meta: ChannelMeta;
|
|
49
|
+
capabilities: ChannelCapabilities;
|
|
50
|
+
agentPrompt: {
|
|
51
|
+
messageToolHints: () => string[];
|
|
52
|
+
};
|
|
53
|
+
reload: {
|
|
54
|
+
configPrefixes: string[];
|
|
55
|
+
};
|
|
56
|
+
configSchema: {
|
|
57
|
+
schema: unknown;
|
|
58
|
+
};
|
|
59
|
+
config: {
|
|
60
|
+
listAccountIds: (cfg: OpenClawConfig) => string[];
|
|
61
|
+
resolveAccount: (cfg: OpenClawConfig, accountId?: string) => T;
|
|
62
|
+
defaultAccountId: (cfg: OpenClawConfig) => string;
|
|
63
|
+
setAccountEnabled: (opts: {
|
|
64
|
+
cfg: OpenClawConfig;
|
|
65
|
+
accountId: string;
|
|
66
|
+
enabled: boolean;
|
|
67
|
+
}) => OpenClawConfig;
|
|
68
|
+
deleteAccount: (opts: {
|
|
69
|
+
cfg: OpenClawConfig;
|
|
70
|
+
accountId: string;
|
|
71
|
+
}) => OpenClawConfig;
|
|
72
|
+
isConfigured: (account: T) => boolean;
|
|
73
|
+
describeAccount: (account: T) => Record<string, unknown>;
|
|
74
|
+
resolveAllowFrom: (opts: {
|
|
75
|
+
cfg: OpenClawConfig;
|
|
76
|
+
}) => string[];
|
|
77
|
+
formatAllowFrom: (opts: {
|
|
78
|
+
allowFrom: string[];
|
|
79
|
+
}) => string[];
|
|
80
|
+
};
|
|
81
|
+
security: {
|
|
82
|
+
resolveDmPolicy: (opts: {
|
|
83
|
+
cfg: OpenClawConfig;
|
|
84
|
+
}) => Record<string, unknown>;
|
|
85
|
+
collectWarnings: (opts: {
|
|
86
|
+
cfg: OpenClawConfig;
|
|
87
|
+
}) => string[];
|
|
88
|
+
};
|
|
89
|
+
setup: {
|
|
90
|
+
resolveAccountId: (cfg: OpenClawConfig, accountId?: string) => string;
|
|
91
|
+
applyAccountConfig: (opts: {
|
|
92
|
+
cfg: OpenClawConfig;
|
|
93
|
+
accountId: string;
|
|
94
|
+
}) => OpenClawConfig;
|
|
95
|
+
};
|
|
96
|
+
outbound: typeof wechatKfOutbound;
|
|
97
|
+
status: {
|
|
98
|
+
defaultRuntime: AccountRuntimeStatus;
|
|
99
|
+
buildChannelSummary: (opts: {
|
|
100
|
+
snapshot: Record<string, unknown>;
|
|
101
|
+
}) => Record<string, unknown>;
|
|
102
|
+
buildAccountSnapshot: (opts: {
|
|
103
|
+
account: T;
|
|
104
|
+
runtime: Partial<AccountRuntimeStatus> | null;
|
|
105
|
+
}) => Record<string, unknown>;
|
|
106
|
+
};
|
|
107
|
+
gateway: {
|
|
108
|
+
_started: boolean;
|
|
109
|
+
startAccount: (ctx: GatewayContext) => Promise<void>;
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
export declare const wechatKfPlugin: ChannelPlugin<ResolvedWechatKfAccount>;
|
|
113
|
+
export {};
|