@pawastation/wechat-kf 0.1.2 → 0.2.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 (55) hide show
  1. package/README.md +34 -28
  2. package/README.zh-CN.md +34 -28
  3. package/dist/index.d.ts +5 -15
  4. package/dist/index.js +5 -5
  5. package/dist/index.js.map +1 -1
  6. package/dist/src/accounts.d.ts +2 -1
  7. package/dist/src/accounts.js +61 -19
  8. package/dist/src/accounts.js.map +1 -1
  9. package/dist/src/api.d.ts +31 -2
  10. package/dist/src/api.js +41 -13
  11. package/dist/src/api.js.map +1 -1
  12. package/dist/src/bot.d.ts +10 -8
  13. package/dist/src/bot.js +231 -78
  14. package/dist/src/bot.js.map +1 -1
  15. package/dist/src/channel.d.ts +7 -106
  16. package/dist/src/channel.js +208 -71
  17. package/dist/src/channel.js.map +1 -1
  18. package/dist/src/config-schema.d.ts +0 -6
  19. package/dist/src/config-schema.js +2 -7
  20. package/dist/src/config-schema.js.map +1 -1
  21. package/dist/src/constants.d.ts +20 -0
  22. package/dist/src/constants.js +29 -0
  23. package/dist/src/constants.js.map +1 -1
  24. package/dist/src/crypto.js +7 -6
  25. package/dist/src/crypto.js.map +1 -1
  26. package/dist/src/monitor.d.ts +27 -14
  27. package/dist/src/monitor.js +67 -120
  28. package/dist/src/monitor.js.map +1 -1
  29. package/dist/src/outbound.d.ts +10 -44
  30. package/dist/src/outbound.js +277 -92
  31. package/dist/src/outbound.js.map +1 -1
  32. package/dist/src/reply-dispatcher.d.ts +2 -6
  33. package/dist/src/reply-dispatcher.js +131 -32
  34. package/dist/src/reply-dispatcher.js.map +1 -1
  35. package/dist/src/runtime.d.ts +1 -119
  36. package/dist/src/runtime.js +2 -1
  37. package/dist/src/runtime.js.map +1 -1
  38. package/dist/src/send-utils.d.ts +13 -0
  39. package/dist/src/send-utils.js +56 -4
  40. package/dist/src/send-utils.js.map +1 -1
  41. package/dist/src/token.js +7 -3
  42. package/dist/src/token.js.map +1 -1
  43. package/dist/src/types.d.ts +68 -6
  44. package/dist/src/webhook.d.ts +16 -16
  45. package/dist/src/webhook.js +92 -75
  46. package/dist/src/webhook.js.map +1 -1
  47. package/dist/src/wechat-kf-directives.d.ts +132 -9
  48. package/dist/src/wechat-kf-directives.js +535 -24
  49. package/dist/src/wechat-kf-directives.js.map +1 -1
  50. package/index.ts +22 -12
  51. package/openclaw.plugin.json +1 -3
  52. package/package.json +3 -2
  53. package/dist/src/chunk-utils.d.ts +0 -18
  54. package/dist/src/chunk-utils.js +0 -58
  55. package/dist/src/chunk-utils.js.map +0 -1
@@ -3,111 +3,12 @@
3
3
  *
4
4
  * Dynamically discovers kfids from webhook callbacks.
5
5
  * Each kfid = one accountId = one independent session.
6
+ *
7
+ * Architecture:
8
+ * - "default" account: enterprise-level shared infra (loads kfIds, validates token, sets shared context)
9
+ * - Per-kfId accounts: wait for shared context, then start 30s polling loop
10
+ * - Webhook handler: registered on framework's shared gateway server (no self-managed HTTP server)
6
11
  */
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
- };
12
+ import type { ChannelPlugin } from "openclaw/plugin-sdk";
13
+ import type { ResolvedWechatKfAccount } from "./types.js";
112
14
  export declare const wechatKfPlugin: ChannelPlugin<ResolvedWechatKfAccount>;
113
- export {};
@@ -3,24 +3,34 @@
3
3
  *
4
4
  * Dynamically discovers kfids from webhook callbacks.
5
5
  * Each kfid = one accountId = one independent session.
6
+ *
7
+ * Architecture:
8
+ * - "default" account: enterprise-level shared infra (loads kfIds, validates token, sets shared context)
9
+ * - Per-kfId accounts: wait for shared context, then start 30s polling loop
10
+ * - Webhook handler: registered on framework's shared gateway server (no self-managed HTTP server)
6
11
  */
7
- import { homedir } from "node:os";
8
- import { deleteKfId, disableKfId, enableKfId, getChannelConfig, listAccountIds, resolveAccount } from "./accounts.js";
12
+ import { formatPairingApproveHint, PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk";
13
+ import { deleteKfId, disableKfId, enableKfId, getChannelConfig, listAccountIds, loadKfIds, resolveAccount, } from "./accounts.js";
14
+ import { sendTextMessage } from "./api.js";
15
+ import { handleWebhookEvent } from "./bot.js";
9
16
  import { wechatKfConfigSchema } from "./config-schema.js";
10
- import { startMonitor } from "./monitor.js";
17
+ import { CHANNEL_ID, CONFIG_KEY, DEFAULT_WEBHOOK_PATH, defaultStateDir, formatError, logTag } from "./constants.js";
18
+ import { clearSharedContext, getPairingKfId, getSharedContext, setSharedContext, waitForSharedContext, } from "./monitor.js";
11
19
  import { wechatKfOutbound } from "./outbound.js";
20
+ import { getRuntime } from "./runtime.js";
21
+ import { getAccessToken } from "./token.js";
12
22
  const meta = {
13
- id: "wechat-kf",
23
+ id: CHANNEL_ID,
14
24
  label: "WeChat KF",
15
25
  selectionLabel: "WeChat Customer Service (微信客服)",
16
- docsPath: "/channels/wechat-kf",
17
- docsLabel: "wechat-kf",
26
+ docsPath: `/channels/${CHANNEL_ID}`,
27
+ docsLabel: CHANNEL_ID,
18
28
  blurb: "WeCom Customer Service (企业微信客服) API channel — let WeChat users chat with your agent.",
19
29
  aliases: ["wxkf"],
20
30
  order: 80,
21
31
  };
22
32
  export const wechatKfPlugin = {
23
- id: "wechat-kf",
33
+ id: CHANNEL_ID,
24
34
  meta: { ...meta },
25
35
  capabilities: {
26
36
  chatTypes: ["direct"],
@@ -33,22 +43,51 @@ export const wechatKfPlugin = {
33
43
  },
34
44
  agentPrompt: {
35
45
  messageToolHints: () => [
36
- "- WeChat KF: omit `target` to reply to current conversation.",
37
- "- Supports text and media messages (image, voice, video, file).",
38
- "- 48h reply window, max 5 replies per window.",
39
- "- To send a rich link card, include `[[wechat_link: title | desc | url | thumbUrl]]` in your reply. Fields: title (required), desc (optional), url (required, must be https://), thumbUrl (optional, thumbnail image URL). Example: `[[wechat_link: Article Title | Brief description | https://example.com/article | https://example.com/thumb.jpg]]`",
46
+ "- WeChat KF is direct-message only (1:1). Omit `target` to reply to current conversation.",
47
+ "- Markdown (bold, italic, headings, lists, code blocks) is auto-converted to Unicode-styled plain text.",
48
+ "- Long replies are auto-chunked at ~2000 chars; write naturally without manually splitting.",
49
+ "- WeChat content security may block messages that combine numbered lists (1. 2. 3.) with security/credential topics (passwords, API keys, secrets). Use bullet points or conversational prose for such topics.",
50
+ "- Outbound media: can send image (jpg/png/gif/bmp), video (mp4), and file attachments.",
51
+ "- Voice messages require AMR format (\u22642MB, \u226460s). Other audio formats (mp3, wav, ogg) are sent as file attachments, not playable voice.",
52
+ "- When generating or saving files for sending, prefer the agent workspace directory over /tmp.",
53
+ "- Users may send: text, images, voice, video, files, locations, links, mini-programs, menu selections, forwarded chat history, \u89c6\u9891\u53f7 content, business cards, \u89c6\u9891\u53f7\u5546\u54c1, \u89c6\u9891\u53f7\u8ba2\u5355, or \u7b14\u8bb0.",
54
+ "",
55
+ "### WeChat Rich Messages",
56
+ "Embed directives in your reply to send rich messages (one per message). Text around the directive is sent as separate text messages.",
57
+ "Thumbnail fields: pass an image URL or file path (auto-uploaded to WeChat), or a media_id from a prior message (used as-is).",
58
+ "",
59
+ "**Link Card**: `[[wechat_link: Title | Description | https://url | thumbnail]]`",
60
+ " title + url required; desc + thumbnail optional. Thumbnail needed for rich card; without one, sent as plain text.",
61
+ "",
62
+ "**Location**: `[[wechat_location: Place Name | Address | latitude | longitude]]`",
63
+ " name + coordinates required; address optional (omit for 3-field format: `name | lat | lng`).",
64
+ "",
65
+ "**Mini Program**: `[[wechat_miniprogram: appid | Title | pages/path | thumbnail]]`",
66
+ " appid + title + pagepath required; thumbnail recommended. Without one, falls back to plain text.",
67
+ "",
68
+ "**Menu**: `[[wechat_menu: Question text | Option1, Option2, Option3 | Footer text]]`",
69
+ " Presents clickable options to the user. Options required (comma-separated); header and footer both optional.",
70
+ " Advanced item types: `view(url, label)` = URL link, `mini(appid, pagepath, label)` = mini program,",
71
+ " `text(content)` = plain text row, `click(id, label)` = click with explicit ID.",
72
+ "",
73
+ "**Business Card**: `[[wechat_business_card: USERID]]`",
74
+ " Sends a WeCom member's contact card. Requires \u300c\u5ba2\u6237\u8054\u7cfb\u300d permission. Customer must have actively messaged within 48h (menu clicks don't count). Max 1 card per 48h window.",
75
+ "",
76
+ "**Acquisition Link (\u83b7\u5ba2\u94fe\u63a5)**: `[[wechat_ca_link: https://work.weixin.qq.com/ca/...]]`",
77
+ " Sends a \u83b7\u5ba2\u94fe\u63a5 as a rich card. The URL must be a valid acquisition link.",
78
+ "",
79
+ '**Raw Message (experimental)**: `[[wechat_raw: {"msgtype":"xxx", "xxx": {...}}]]`',
80
+ " Sends an arbitrary message via the WeChat KF API. The JSON must include a `msgtype` field plus the type-specific payload.",
81
+ " Use this to echo back or test undocumented message types. Check the raw JSON shown for unknown inbound types.",
40
82
  ],
41
83
  },
42
- reload: { configPrefixes: ["channels.wechat-kf"] },
84
+ reload: { configPrefixes: [CONFIG_KEY] },
43
85
  configSchema: { schema: wechatKfConfigSchema },
44
86
  config: {
45
87
  listAccountIds: (cfg) => listAccountIds(cfg),
46
- resolveAccount: (cfg, accountId) => resolveAccount(cfg, accountId),
88
+ resolveAccount: (cfg, accountId) => resolveAccount(cfg, accountId ?? undefined),
47
89
  defaultAccountId: (cfg) => listAccountIds(cfg)[0] ?? "default",
48
90
  setAccountEnabled: ({ cfg, accountId, enabled }) => {
49
- // Dynamic accounts — toggle via in-memory disabled set (persisted to disk).
50
- // Fire-and-forget: the async persist is best-effort; the in-memory state
51
- // takes effect immediately so the framework sees the change right away.
52
91
  if (enabled) {
53
92
  void enableKfId(accountId);
54
93
  }
@@ -58,41 +97,34 @@ export const wechatKfPlugin = {
58
97
  return cfg;
59
98
  },
60
99
  deleteAccount: ({ cfg, accountId }) => {
61
- // Remove from discovered set and add to disabled set so it won't come
62
- // back from future webhook callbacks. Fire-and-forget for persistence.
63
100
  void deleteKfId(accountId);
64
101
  return cfg;
65
102
  },
66
- isConfigured: (account) => account.configured,
67
- describeAccount: (account) => ({
103
+ isConfigured: (account, _cfg) => account.configured,
104
+ describeAccount: (account, _cfg) => ({
68
105
  accountId: account.accountId,
69
106
  enabled: account.enabled,
70
107
  configured: account.configured,
71
- corpId: account.corpId,
72
- openKfId: account.openKfId,
73
108
  }),
74
109
  resolveAllowFrom: ({ cfg }) => {
75
110
  const config = getChannelConfig(cfg);
76
111
  return (config.allowFrom ?? []).map(String);
77
112
  },
78
- formatAllowFrom: ({ allowFrom }) => allowFrom.map((e) => e.trim()).filter(Boolean),
113
+ formatAllowFrom: ({ allowFrom, }) => allowFrom.map((e) => String(e).trim()).filter(Boolean),
79
114
  },
80
115
  security: {
81
- resolveDmPolicy: ({ cfg }) => {
116
+ resolveDmPolicy: ({ cfg, }) => {
82
117
  const config = getChannelConfig(cfg);
83
118
  const policy = config.dmPolicy ?? "open";
84
119
  return {
85
120
  policy,
86
121
  allowFrom: config.allowFrom ?? [],
87
- allowFromPath: "channels.wechat-kf.allowFrom",
88
- approveHint: [
89
- "To approve a WeChat KF user, add their external_userid to the allowlist:",
90
- " openclaw config set channels.wechat-kf.allowFrom '[\"{userid}\"]'",
91
- ].join("\n"),
122
+ allowFromPath: `${CONFIG_KEY}.allowFrom`,
123
+ approveHint: formatPairingApproveHint(CHANNEL_ID),
92
124
  normalizeEntry: (raw) => raw.replace(/^user:/i, "").trim(),
93
125
  };
94
126
  },
95
- collectWarnings: ({ cfg }) => {
127
+ collectWarnings: ({ cfg, }) => {
96
128
  const config = getChannelConfig(cfg);
97
129
  const policy = config.dmPolicy ?? "open";
98
130
  if (policy === "open") {
@@ -101,13 +133,29 @@ export const wechatKfPlugin = {
101
133
  return [];
102
134
  },
103
135
  },
136
+ pairing: {
137
+ idLabel: "wechatKfExternalUserId",
138
+ normalizeAllowEntry: (entry) => entry.replace(/^(wechat-kf|user):/i, "").trim(),
139
+ notifyApproval: async ({ id }) => {
140
+ const shared = getSharedContext();
141
+ if (!shared)
142
+ return;
143
+ const { corpId, appSecret } = shared;
144
+ if (!corpId || !appSecret)
145
+ return;
146
+ const kfId = getPairingKfId(id) ?? listAccountIds(shared.botCtx.cfg).find((a) => a !== "default");
147
+ if (!kfId)
148
+ return;
149
+ await sendTextMessage(corpId, appSecret, id, kfId, PAIRING_APPROVED_MESSAGE);
150
+ },
151
+ },
104
152
  setup: {
105
- resolveAccountId: (_cfg, accountId) => accountId ?? "default",
106
- applyAccountConfig: ({ cfg }) => {
153
+ resolveAccountId: ({ accountId }) => accountId ?? "default",
154
+ applyAccountConfig: ({ cfg, accountId: _accountId, input: _input, }) => {
107
155
  const config = getChannelConfig(cfg);
108
156
  return {
109
157
  ...cfg,
110
- channels: { ...(cfg.channels ?? {}), "wechat-kf": { ...config, enabled: true } },
158
+ channels: { ...(cfg.channels ?? {}), [CHANNEL_ID]: { ...config, enabled: true } },
111
159
  };
112
160
  },
113
161
  },
@@ -119,63 +167,152 @@ export const wechatKfPlugin = {
119
167
  lastStartAt: null,
120
168
  lastStopAt: null,
121
169
  lastError: null,
122
- port: null,
123
170
  },
124
- buildChannelSummary: ({ snapshot }) => ({
171
+ buildChannelSummary: ({ snapshot, }) => ({
125
172
  configured: snapshot.configured ?? false,
126
173
  running: snapshot.running ?? false,
127
174
  lastStartAt: snapshot.lastStartAt ?? null,
128
175
  lastError: snapshot.lastError ?? null,
129
- port: snapshot.port ?? null,
130
176
  }),
131
177
  buildAccountSnapshot: ({ account, runtime, }) => ({
132
178
  accountId: account.accountId,
133
179
  enabled: account.enabled,
134
180
  configured: account.configured,
135
- corpId: account.corpId,
136
181
  running: runtime?.running ?? false,
137
182
  lastStartAt: runtime?.lastStartAt ?? null,
138
183
  lastError: runtime?.lastError ?? null,
139
- port: runtime?.port ?? null,
140
184
  }),
141
185
  },
142
186
  gateway: {
143
- /** Track whether the account is currently started to prevent duplicate launches. */
144
- _started: false,
145
187
  startAccount: async (ctx) => {
146
- const self = wechatKfPlugin.gateway;
147
- // Idempotency guard — skip if already started
148
- if (self._started) {
149
- ctx.log?.info("[wechat-kf] startAccount: already running, skipping duplicate call");
150
- return;
151
- }
152
188
  const config = getChannelConfig(ctx.cfg);
153
- const port = config.webhookPort ?? 9999;
154
- const path = config.webhookPath ?? "/wechat-kf";
155
- try {
156
- self._started = true;
157
- ctx.setStatus?.({ accountId: ctx.accountId, port, running: true, lastStartAt: new Date().toISOString() });
158
- ctx.log?.info(`[wechat-kf] starting on :${port}${path}`);
159
- const stateDir = ctx.runtime?.state?.resolveStateDir?.() ?? `${homedir()}/.openclaw/state/wechat-kf`;
160
- await startMonitor({
161
- cfg: ctx.cfg,
162
- runtime: ctx.runtime,
163
- abortSignal: ctx.abortSignal,
164
- stateDir,
165
- log: ctx.log,
166
- });
189
+ const pluginRuntime = getRuntime();
190
+ const stateDir = pluginRuntime.state?.resolveStateDir?.() ?? defaultStateDir();
191
+ if (ctx.accountId === "default") {
192
+ // ── "default" account: enterprise-level shared infrastructure ──
193
+ try {
194
+ const { corpId, appSecret, token, encodingAESKey } = config;
195
+ const webhookPath = config.webhookPath ?? DEFAULT_WEBHOOK_PATH;
196
+ if (!corpId || !appSecret || !token || !encodingAESKey) {
197
+ throw new Error(`${logTag()} missing required config fields (corpId, appSecret, token, encodingAESKey)`);
198
+ }
199
+ // Load previously discovered kfids
200
+ await loadKfIds(stateDir);
201
+ // Validate access token on startup (best-effort)
202
+ try {
203
+ await getAccessToken(corpId, appSecret);
204
+ ctx.log?.info(`${logTag()} access_token validated`);
205
+ }
206
+ catch (err) {
207
+ ctx.log?.warn(`${logTag()} access_token validation failed (will retry on first message): ${err}`);
208
+ }
209
+ const botCtx = { cfg: ctx.cfg, runtime: ctx.runtime, stateDir, log: ctx.log };
210
+ setSharedContext({
211
+ callbackToken: token,
212
+ encodingAESKey,
213
+ corpId,
214
+ appSecret,
215
+ webhookPath,
216
+ botCtx,
217
+ });
218
+ ctx.setStatus({ accountId: ctx.accountId, running: true, lastStartAt: Date.now() });
219
+ ctx.log?.info(`${logTag()} shared context ready (webhook path: ${webhookPath})`);
220
+ // Block until abort — framework expects long-lived promise
221
+ await new Promise((resolve) => {
222
+ if (ctx.abortSignal.aborted) {
223
+ resolve();
224
+ return;
225
+ }
226
+ ctx.abortSignal.addEventListener("abort", () => resolve(), { once: true });
227
+ });
228
+ // Shutdown
229
+ clearSharedContext();
230
+ ctx.setStatus({
231
+ accountId: ctx.accountId,
232
+ running: false,
233
+ lastStopAt: Date.now(),
234
+ });
235
+ ctx.log?.info(`${logTag()} shared context cleared, default account stopped`);
236
+ }
237
+ catch (err) {
238
+ clearSharedContext();
239
+ ctx.setStatus({
240
+ accountId: ctx.accountId,
241
+ running: false,
242
+ lastError: formatError(err),
243
+ lastStopAt: Date.now(),
244
+ });
245
+ ctx.log?.error(`${logTag()} default account failed: ${formatError(err)}`);
246
+ throw err;
247
+ }
167
248
  }
168
- catch (err) {
169
- self._started = false;
170
- ctx.setStatus?.({
171
- accountId: ctx.accountId,
172
- port,
173
- running: false,
174
- lastError: err instanceof Error ? err.message : String(err),
175
- lastStopAt: new Date().toISOString(),
176
- });
177
- ctx.log?.error?.(`[wechat-kf] startAccount failed: ${err instanceof Error ? err.message : String(err)}`);
178
- throw err;
249
+ else {
250
+ // ── Per-kfId account: polling loop ──
251
+ let pollTimer = null;
252
+ try {
253
+ // Wait for the "default" account to set shared context
254
+ const shared = await waitForSharedContext(ctx.abortSignal);
255
+ ctx.setStatus({ accountId: ctx.accountId, running: true, lastStartAt: Date.now() });
256
+ ctx.log?.info(`${logTag(ctx.accountId)} polling started`);
257
+ // Start 30s polling loop
258
+ const POLL_INTERVAL_MS = 30_000;
259
+ let polling = false;
260
+ pollTimer = setInterval(async () => {
261
+ if (ctx.abortSignal.aborted)
262
+ return;
263
+ if (polling)
264
+ return;
265
+ polling = true;
266
+ try {
267
+ ctx.log?.debug?.(`${logTag(ctx.accountId)} polling sync_msg...`);
268
+ await handleWebhookEvent(shared.botCtx, ctx.accountId, "");
269
+ }
270
+ catch (err) {
271
+ ctx.log?.error(`${logTag(ctx.accountId)} poll error: ${formatError(err)}`);
272
+ }
273
+ finally {
274
+ polling = false;
275
+ }
276
+ }, POLL_INTERVAL_MS);
277
+ // Block until abort
278
+ await new Promise((resolve) => {
279
+ if (ctx.abortSignal.aborted) {
280
+ resolve();
281
+ return;
282
+ }
283
+ ctx.abortSignal.addEventListener("abort", () => resolve(), { once: true });
284
+ });
285
+ // Cleanup
286
+ if (pollTimer) {
287
+ clearInterval(pollTimer);
288
+ pollTimer = null;
289
+ }
290
+ ctx.setStatus({
291
+ accountId: ctx.accountId,
292
+ running: false,
293
+ lastStopAt: Date.now(),
294
+ });
295
+ ctx.log?.info(`${logTag(ctx.accountId)} polling stopped`);
296
+ }
297
+ catch (err) {
298
+ if (pollTimer) {
299
+ clearInterval(pollTimer);
300
+ pollTimer = null;
301
+ }
302
+ ctx.setStatus({
303
+ accountId: ctx.accountId,
304
+ running: false,
305
+ lastError: formatError(err),
306
+ lastStopAt: Date.now(),
307
+ });
308
+ // AbortError is expected when the signal fires before shared context is ready
309
+ if (err instanceof DOMException && err.name === "AbortError") {
310
+ ctx.log?.info(`${logTag(ctx.accountId)} aborted before shared context ready`);
311
+ return;
312
+ }
313
+ ctx.log?.error(`${logTag(ctx.accountId)} startAccount failed: ${formatError(err)}`);
314
+ throw err;
315
+ }
179
316
  }
180
317
  },
181
318
  },
@@ -1 +1 @@
1
- {"version":3,"file":"channel.js","sourceRoot":"","sources":["../../src/channel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"channel.js","sourceRoot":"","sources":["../../src/channel.ts"],"names":[],"mappings":"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"}
@@ -31,12 +31,6 @@ export declare const wechatKfConfigSchema: {
31
31
  minLength: number;
32
32
  maxLength: number;
33
33
  };
34
- webhookPort: {
35
- type: "integer";
36
- minimum: number;
37
- maximum: number;
38
- default: number;
39
- };
40
34
  webhookPath: {
41
35
  type: "string";
42
36
  default: string;
@@ -7,6 +7,7 @@
7
7
  * Flat enterprise-level credentials. No per-account config needed —
8
8
  * kfids are discovered dynamically from webhook callbacks.
9
9
  */
10
+ import { DEFAULT_WEBHOOK_PATH } from "./constants.js";
10
11
  export const wechatKfConfigSchema = {
11
12
  type: "object",
12
13
  properties: {
@@ -20,13 +21,7 @@ export const wechatKfConfigSchema = {
20
21
  minLength: 43,
21
22
  maxLength: 43,
22
23
  },
23
- webhookPort: {
24
- type: "integer",
25
- minimum: 1,
26
- maximum: 65535,
27
- default: 9999,
28
- },
29
- webhookPath: { type: "string", default: "/wechat-kf" },
24
+ webhookPath: { type: "string", default: DEFAULT_WEBHOOK_PATH },
30
25
  dmPolicy: {
31
26
  type: "string",
32
27
  enum: ["open", "pairing", "allowlist", "disabled"],
@@ -1 +1 @@
1
- {"version":3,"file":"config-schema.js","sourceRoot":"","sources":["../../src/config-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,IAAI,EAAE,QAAiB;IACvB,UAAU,EAAE;QACV,OAAO,EAAE,EAAE,IAAI,EAAE,SAAkB,EAAE;QACrC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,sBAAsB,EAAE;QACxE,SAAS,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,8BAA8B,EAAE;QACnF,KAAK,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,wBAAwB,EAAE;QACzE,cAAc,EAAE;YACd,IAAI,EAAE,QAAiB;YACvB,WAAW,EAAE,6BAA6B;YAC1C,SAAS,EAAE,EAAE;YACb,SAAS,EAAE,EAAE;SACd;QACD,WAAW,EAAE;YACX,IAAI,EAAE,SAAkB;YACxB,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,IAAI;SACd;QACD,WAAW,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,OAAO,EAAE,YAAY,EAAE;QAC/D,QAAQ,EAAE;YACR,IAAI,EAAE,QAAiB;YACvB,IAAI,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,CAAU;YAC3D,OAAO,EAAE,MAAM;SAChB;QACD,SAAS,EAAE,EAAE,IAAI,EAAE,OAAgB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,EAAE;KAC1E;CACF,CAAC"}
1
+ {"version":3,"file":"config-schema.js","sourceRoot":"","sources":["../../src/config-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAEtD,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,IAAI,EAAE,QAAiB;IACvB,UAAU,EAAE;QACV,OAAO,EAAE,EAAE,IAAI,EAAE,SAAkB,EAAE;QACrC,MAAM,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,sBAAsB,EAAE;QACxE,SAAS,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,8BAA8B,EAAE;QACnF,KAAK,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,WAAW,EAAE,wBAAwB,EAAE;QACzE,cAAc,EAAE;YACd,IAAI,EAAE,QAAiB;YACvB,WAAW,EAAE,6BAA6B;YAC1C,SAAS,EAAE,EAAE;YACb,SAAS,EAAE,EAAE;SACd;QACD,WAAW,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,OAAO,EAAE,oBAAoB,EAAE;QACvE,QAAQ,EAAE;YACR,IAAI,EAAE,QAAiB;YACvB,IAAI,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,CAAU;YAC3D,OAAO,EAAE,MAAM;SAChB;QACD,SAAS,EAAE,EAAE,IAAI,EAAE,OAAgB,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAiB,EAAE,EAAE;KAC1E;CACF,CAAC"}
@@ -1,3 +1,19 @@
1
+ /** Channel identifier — single source of truth for the plugin ID string. */
2
+ export declare const CHANNEL_ID: "wechat-kf";
3
+ /** Default webhook path registered on the framework's shared gateway. */
4
+ export declare const DEFAULT_WEBHOOK_PATH: string;
5
+ /** Config key prefix for this channel in OpenClaw config. */
6
+ export declare const CONFIG_KEY: string;
7
+ /** Build a log-tag prefix: `[wechat-kf]` or `[wechat-kf:kfId]`. */
8
+ export declare function logTag(kfId?: string): string;
9
+ /** Default state directory for cursor and kfid persistence. */
10
+ export declare function defaultStateDir(): string;
11
+ /** Cursor file name for a given kfId. */
12
+ export declare function cursorFileName(kfId: string): string;
13
+ /** Persisted file name for discovered kfids. */
14
+ export declare const KFIDS_FILE: string;
15
+ /** Persisted file name for disabled kfids. */
16
+ export declare const DISABLED_KFIDS_FILE: string;
1
17
  /** WeChat KF text message character limit */
2
18
  export declare const WECHAT_TEXT_CHUNK_LIMIT = 2000;
3
19
  /** Timeout for token fetch requests (ms) */
@@ -17,3 +33,7 @@ export declare const TOKEN_EXPIRED_CODES: Set<number>;
17
33
  export declare const WECHAT_MSG_LIMIT_ERRCODE = 95026;
18
34
  /** Timeout for downloading media from external HTTP URLs (ms) */
19
35
  export declare const MEDIA_DOWNLOAD_TIMEOUT_MS = 60000;
36
+ /** Max age (seconds) for inbound messages. Messages older than this are skipped. */
37
+ export declare const MAX_MESSAGE_AGE_S = 300;
38
+ /** Format an unknown caught value for log messages (no stack traces). */
39
+ export declare function formatError(err: unknown): string;