@tencent-weixin/openclaw-weixin 2.4.1 → 2.4.2

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 (41) hide show
  1. package/dist/index.js +0 -4
  2. package/dist/index.js.map +1 -1
  3. package/dist/src/api/api.js +1 -2
  4. package/dist/src/api/api.js.map +1 -1
  5. package/dist/src/auth/accounts.js.map +1 -1
  6. package/dist/src/channel.js +11 -0
  7. package/dist/src/channel.js.map +1 -1
  8. package/dist/src/media/voice-outbound.js +177 -0
  9. package/dist/src/media/voice-outbound.js.map +1 -0
  10. package/dist/src/messaging/abort-fence.js +70 -0
  11. package/dist/src/messaging/abort-fence.js.map +1 -0
  12. package/dist/src/messaging/buttons.js +117 -0
  13. package/dist/src/messaging/buttons.js.map +1 -0
  14. package/dist/src/messaging/lane-key.js +66 -0
  15. package/dist/src/messaging/lane-key.js.map +1 -0
  16. package/dist/src/messaging/merged-record.js +149 -0
  17. package/dist/src/messaging/merged-record.js.map +1 -0
  18. package/dist/src/messaging/model-buttons.js +182 -0
  19. package/dist/src/messaging/model-buttons.js.map +1 -0
  20. package/dist/src/messaging/model-callback-handler.js +133 -0
  21. package/dist/src/messaging/model-callback-handler.js.map +1 -0
  22. package/dist/src/monitor/lane-scheduler.js +46 -0
  23. package/dist/src/monitor/lane-scheduler.js.map +1 -0
  24. package/dist/src/monitor/monitor.js +5 -12
  25. package/dist/src/monitor/monitor.js.map +1 -1
  26. package/dist/src/streaming/stream-pipeline.js +431 -0
  27. package/dist/src/streaming/stream-pipeline.js.map +1 -0
  28. package/dist/src/streaming/stream-session.js +260 -0
  29. package/dist/src/streaming/stream-session.js.map +1 -0
  30. package/dist/src/streaming/stream.js +239 -0
  31. package/dist/src/streaming/stream.js.map +1 -0
  32. package/dist/src/util/markdown-fences.js +54 -0
  33. package/dist/src/util/markdown-fences.js.map +1 -0
  34. package/index.ts +0 -5
  35. package/openclaw.plugin.json +1 -1
  36. package/package.json +1 -1
  37. package/src/api/api.ts +2 -3
  38. package/src/auth/accounts.ts +0 -1
  39. package/src/channel.ts +13 -1
  40. package/src/monitor/monitor.ts +11 -10
  41. package/src/runtime.ts +0 -70
package/src/channel.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import path from "node:path";
2
2
 
3
- import type { ChannelPlugin, OpenClawConfig } from "openclaw/plugin-sdk/core";
3
+ import type { ChannelPlugin, OpenClawConfig, PluginRuntime } from "openclaw/plugin-sdk/core";
4
4
  import { normalizeAccountId } from "openclaw/plugin-sdk/account-id";
5
5
  import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/infra-runtime";
6
6
 
@@ -428,6 +428,17 @@ export const weixinPlugin: ChannelPlugin<ResolvedWeixinAccount> = {
428
428
  const logPath = aLog.getLogFilePath();
429
429
  ctx.log?.info?.(`[${account.accountId}] weixin logs: ${logPath}`);
430
430
 
431
+ // The gateway injects the channel runtime surface per-call (task-scoped). We require it:
432
+ // it carries reply/routing/session/media/commands helpers used by processOneMessage.
433
+ // Available on hosts >= 2026.2.19 (our peerDependency is >= 2026.3.22).
434
+ if (!ctx.channelRuntime) {
435
+ const msg = `ctx.channelRuntime missing — host too old or plugin SDK contract violated`;
436
+ aLog.error(msg);
437
+ ctx.log?.error?.(`[${account.accountId}] ${msg}`);
438
+ ctx.setStatus?.({ accountId: account.accountId, running: false });
439
+ throw new Error(msg);
440
+ }
441
+
431
442
  const { monitorWeixinProvider } = await import("./monitor/monitor.js");
432
443
  return monitorWeixinProvider({
433
444
  baseUrl: account.baseUrl,
@@ -436,6 +447,7 @@ export const weixinPlugin: ChannelPlugin<ResolvedWeixinAccount> = {
436
447
  accountId: account.accountId,
437
448
  config: ctx.cfg,
438
449
  runtime: ctx.runtime,
450
+ channelRuntime: ctx.channelRuntime as unknown as PluginRuntime["channel"],
439
451
  abortSignal: ctx.abortSignal,
440
452
  setStatus: ctx.setStatus,
441
453
  });
@@ -5,7 +5,6 @@ import { getUpdates } from "../api/api.js";
5
5
  import { WeixinConfigManager } from "../api/config-cache.js";
6
6
  import { SESSION_EXPIRED_ERRCODE, pauseSession, getRemainingPauseMs } from "../api/session-guard.js";
7
7
  import { processOneMessage } from "../messaging/process-message.js";
8
- import { getWeixinRuntime, waitForWeixinRuntime } from "../runtime.js";
9
8
  import { getSyncBufFilePath, loadGetUpdatesBuf, saveGetUpdatesBuf } from "../storage/sync-buf.js";
10
9
  import { logger } from "../util/logger.js";
11
10
  import type { Logger } from "../util/logger.js";
@@ -25,6 +24,11 @@ export type MonitorWeixinOpts = {
25
24
  allowFrom?: string[];
26
25
  config: import("openclaw/plugin-sdk/core").OpenClawConfig;
27
26
  runtime?: { log?: (msg: string) => void; error?: (msg: string) => void };
27
+ /**
28
+ * Gateway-injected channel runtime surface (reply/routing/session/media/commands/...).
29
+ * Required for inbound message processing; provided by `ChannelGatewayContext.channelRuntime`.
30
+ */
31
+ channelRuntime: PluginRuntime["channel"];
28
32
  abortSignal?: AbortSignal;
29
33
  longPollTimeoutMs?: number;
30
34
  /** Gateway status callback — called on each successful poll and inbound message. */
@@ -42,6 +46,7 @@ export async function monitorWeixinProvider(opts: MonitorWeixinOpts): Promise<vo
42
46
  token,
43
47
  accountId,
44
48
  config,
49
+ channelRuntime,
45
50
  abortSignal,
46
51
  longPollTimeoutMs,
47
52
  setStatus,
@@ -50,15 +55,11 @@ export async function monitorWeixinProvider(opts: MonitorWeixinOpts): Promise<vo
50
55
  const errLog = opts.runtime?.error ?? ((m: string) => log(m));
51
56
  const aLog: Logger = logger.withAccount(accountId);
52
57
 
53
- aLog.info(`waiting for Weixin runtime...`);
54
- let channelRuntime: PluginRuntime["channel"];
55
- try {
56
- const pluginRuntime = await waitForWeixinRuntime();
57
- channelRuntime = pluginRuntime.channel;
58
- aLog.info(`Weixin runtime acquired, channelRuntime type: ${typeof channelRuntime}`);
59
- } catch (err) {
60
- aLog.error(`waitForWeixinRuntime() failed: ${String(err)}`);
61
- throw err;
58
+ if (!channelRuntime) {
59
+ const msg =
60
+ "channelRuntime missing on monitor opts; gateway must inject ChannelGatewayContext.channelRuntime";
61
+ aLog.error(msg);
62
+ throw new Error(msg);
62
63
  }
63
64
 
64
65
  log(`weixin monitor started (${baseUrl}, account=${accountId})`);
package/src/runtime.ts DELETED
@@ -1,70 +0,0 @@
1
- import type { PluginRuntime } from "openclaw/plugin-sdk/core";
2
-
3
- import { logger } from "./util/logger.js";
4
-
5
- let pluginRuntime: PluginRuntime | null = null;
6
-
7
- export type PluginChannelRuntime = PluginRuntime["channel"];
8
-
9
- /**
10
- * Sets the global Weixin runtime (called from plugin register).
11
- */
12
- export function setWeixinRuntime(next: PluginRuntime): void {
13
- pluginRuntime = next;
14
- logger.info(`[runtime] setWeixinRuntime called, runtime set successfully`);
15
- }
16
-
17
- /**
18
- * Gets the global Weixin runtime (throws if not initialized).
19
- */
20
- export function getWeixinRuntime(): PluginRuntime {
21
- if (!pluginRuntime) {
22
- throw new Error("Weixin runtime not initialized");
23
- }
24
- return pluginRuntime;
25
- }
26
-
27
- const WAIT_INTERVAL_MS = 100;
28
- const DEFAULT_TIMEOUT_MS = 10_000;
29
-
30
- /**
31
- * Waits for the Weixin runtime to be initialized (async polling).
32
- */
33
- export async function waitForWeixinRuntime(
34
- timeoutMs = DEFAULT_TIMEOUT_MS,
35
- ): Promise<PluginRuntime> {
36
- const start = Date.now();
37
- while (!pluginRuntime) {
38
- if (Date.now() - start > timeoutMs) {
39
- throw new Error("Weixin runtime initialization timeout");
40
- }
41
- await new Promise((resolve) => setTimeout(resolve, WAIT_INTERVAL_MS));
42
- }
43
- return pluginRuntime;
44
- }
45
-
46
- /**
47
- * Resolves `PluginRuntime["channel"]` for the long-poll monitor.
48
- *
49
- * Prefer the gateway-injected `channelRuntime` on `ChannelGatewayContext` when present (avoids
50
- * races with the module-global from `register()`). Fall back to the global set by `setWeixinRuntime()`,
51
- * then to a short wait for legacy hosts.
52
- */
53
- export async function resolveWeixinChannelRuntime(params: {
54
- channelRuntime?: PluginChannelRuntime;
55
- waitTimeoutMs?: number;
56
- }): Promise<PluginChannelRuntime> {
57
- if (params.channelRuntime) {
58
- logger.debug("[runtime] channelRuntime from gateway context");
59
- return params.channelRuntime;
60
- }
61
- if (pluginRuntime) {
62
- logger.debug("[runtime] channelRuntime from register() global");
63
- return pluginRuntime.channel;
64
- }
65
- logger.warn(
66
- "[runtime] no channelRuntime on ctx and no global runtime yet; waiting for register()",
67
- );
68
- const pr = await waitForWeixinRuntime(params.waitTimeoutMs ?? DEFAULT_TIMEOUT_MS);
69
- return pr.channel;
70
- }