@wecom/wecom-openclaw-plugin 2026.3.30-beta.2 → 2026.3.31-beta.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 (99) hide show
  1. package/README.md +251 -4
  2. package/dist/index.d.ts +2 -4
  3. package/dist/index.js +113 -0
  4. package/dist/src/accounts.d.ts +57 -0
  5. package/dist/src/accounts.js +222 -0
  6. package/dist/src/agent/api-client.d.ts +94 -0
  7. package/dist/src/agent/api-client.js +292 -0
  8. package/dist/src/agent/handler.d.ts +63 -0
  9. package/dist/src/agent/handler.js +532 -0
  10. package/dist/src/agent/index.d.ts +5 -0
  11. package/dist/src/agent/index.js +5 -0
  12. package/dist/src/agent/webhook.d.ts +23 -0
  13. package/dist/src/agent/webhook.js +226 -0
  14. package/dist/src/agent/xml.d.ts +21 -0
  15. package/dist/src/agent/xml.js +41 -0
  16. package/dist/src/channel.js +564 -0
  17. package/dist/src/chat-queue.d.ts +31 -0
  18. package/dist/src/chat-queue.js +45 -0
  19. package/dist/src/const.d.ts +46 -0
  20. package/dist/src/const.js +157 -0
  21. package/dist/src/dm-policy.js +84 -0
  22. package/dist/src/group-policy.js +126 -0
  23. package/dist/src/http.d.ts +26 -0
  24. package/dist/src/http.js +93 -0
  25. package/dist/src/interface.d.ts +0 -2
  26. package/dist/src/interface.js +4 -0
  27. package/dist/src/mcp/index.js +6 -0
  28. package/dist/src/mcp/interceptors/biz-error.js +64 -0
  29. package/dist/src/mcp/interceptors/index.js +66 -0
  30. package/dist/src/mcp/interceptors/msg-media.js +133 -0
  31. package/dist/src/mcp/interceptors/smartpage-create.js +132 -0
  32. package/dist/src/mcp/interceptors/smartpage-export.js +87 -0
  33. package/dist/src/mcp/interceptors/types.js +7 -0
  34. package/dist/src/mcp/schema.js +99 -0
  35. package/dist/src/mcp/tool.js +202 -0
  36. package/dist/src/mcp/transport.js +410 -0
  37. package/dist/src/media-handler.js +122 -0
  38. package/dist/src/media-uploader.js +333 -0
  39. package/dist/src/message-parser.js +129 -0
  40. package/dist/src/message-sender.d.ts +18 -0
  41. package/dist/src/message-sender.js +120 -0
  42. package/dist/src/monitor.js +832 -0
  43. package/dist/src/onboarding.js +175 -0
  44. package/dist/src/openclaw-compat.d.ts +49 -0
  45. package/dist/src/openclaw-compat.js +487 -0
  46. package/dist/src/reqid-store.js +83 -0
  47. package/dist/src/runtime.js +10 -0
  48. package/dist/src/shared/command-auth.d.ts +23 -0
  49. package/dist/src/shared/command-auth.js +73 -0
  50. package/dist/src/shared/xml-parser.d.ts +46 -0
  51. package/dist/src/shared/xml-parser.js +210 -0
  52. package/dist/src/state-manager.js +216 -0
  53. package/dist/src/target.d.ts +35 -0
  54. package/dist/src/target.js +67 -0
  55. package/dist/src/template-card-manager.d.ts +55 -0
  56. package/dist/src/template-card-manager.js +205 -0
  57. package/dist/src/template-card-parser.js +647 -0
  58. package/dist/src/timeout.js +36 -0
  59. package/dist/src/types/account.d.ts +29 -0
  60. package/dist/src/types/account.js +4 -0
  61. package/dist/src/types/config.d.ts +80 -0
  62. package/dist/src/types/config.js +7 -0
  63. package/dist/src/types/constants.d.ts +42 -0
  64. package/dist/src/types/constants.js +42 -0
  65. package/dist/src/types/index.d.ts +7 -0
  66. package/dist/src/types/index.js +5 -0
  67. package/dist/src/types/message.d.ts +238 -0
  68. package/dist/src/types/message.js +5 -0
  69. package/dist/src/utils.d.ts +39 -0
  70. package/dist/src/utils.js +70 -0
  71. package/dist/src/version.d.ts +1 -1
  72. package/dist/src/version.js +24 -0
  73. package/dist/src/webhook/command-auth.d.ts +47 -0
  74. package/dist/src/webhook/command-auth.js +96 -0
  75. package/dist/src/webhook/gateway.d.ts +36 -0
  76. package/dist/src/webhook/gateway.js +227 -0
  77. package/dist/src/webhook/handler.d.ts +18 -0
  78. package/dist/src/webhook/handler.js +420 -0
  79. package/dist/src/webhook/helpers.d.ts +156 -0
  80. package/dist/src/webhook/helpers.js +833 -0
  81. package/dist/src/webhook/http.d.ts +26 -0
  82. package/dist/src/webhook/http.js +94 -0
  83. package/dist/src/webhook/index.d.ts +11 -0
  84. package/dist/src/webhook/index.js +14 -0
  85. package/dist/src/webhook/media.d.ts +29 -0
  86. package/dist/src/webhook/media.js +88 -0
  87. package/dist/src/webhook/monitor.d.ts +59 -0
  88. package/dist/src/webhook/monitor.js +1147 -0
  89. package/dist/src/webhook/state.d.ts +220 -0
  90. package/dist/src/webhook/state.js +491 -0
  91. package/dist/src/webhook/target.d.ts +41 -0
  92. package/dist/src/webhook/target.js +132 -0
  93. package/dist/src/webhook/types.d.ts +347 -0
  94. package/dist/src/webhook/types.js +33 -0
  95. package/package.json +15 -7
  96. package/dist/index.cjs.js +0 -4953
  97. package/dist/index.cjs.js.map +0 -1
  98. package/dist/index.esm.js +0 -4926
  99. package/dist/index.esm.js.map +0 -1
@@ -0,0 +1,120 @@
1
+ /**
2
+ * 企业微信消息发送模块
3
+ *
4
+ * 负责通过 WSClient 发送回复消息,包含超时保护
5
+ */
6
+ import { generateReqId } from "@wecom/aibot-node-sdk";
7
+ import { REPLY_SEND_TIMEOUT_MS } from "./const.js";
8
+ import { withTimeout } from "./timeout.js";
9
+ // ============================================================================
10
+ // 流式过期错误(errcode 846608)
11
+ // ============================================================================
12
+ /** 流式回复超时错误码(>6分钟未更新,服务端拒绝继续流式更新) */
13
+ export const STREAM_EXPIRED_ERRCODE = 846608;
14
+ /**
15
+ * 流式回复过期错误
16
+ * 当服务端返回 errcode=846608 时抛出,表示流式消息已超过6分钟无法更新,
17
+ * 调用方需降级为主动发送(sendMessage)方式回复。
18
+ */
19
+ export class StreamExpiredError extends Error {
20
+ errcode = STREAM_EXPIRED_ERRCODE;
21
+ constructor(message) {
22
+ super(message ?? `Stream message update expired (errcode=${STREAM_EXPIRED_ERRCODE})`);
23
+ this.name = "StreamExpiredError";
24
+ }
25
+ }
26
+ // ============================================================================
27
+ // 消息发送
28
+ // ============================================================================
29
+ /**
30
+ * 发送企业微信回复消息
31
+ * 供 monitor 内部和 channel outbound 使用
32
+ *
33
+ * @returns messageId (streamId)
34
+ */
35
+ export async function sendWeComReply(params) {
36
+ const { wsClient, frame, text, runtime, finish = true, streamId: existingStreamId } = params;
37
+ if (!text) {
38
+ return "";
39
+ }
40
+ const streamId = existingStreamId || generateReqId("stream");
41
+ if (!wsClient.isConnected) {
42
+ runtime.error?.(`[wecom] WSClient not connected, cannot send reply`);
43
+ throw new Error("WSClient not connected");
44
+ }
45
+ const body = frame.body;
46
+ // 事件回调(aibot_event_callback)没有可用于 replyStream 的有效 req_id,
47
+ // 对该场景改用主动发送 sendMessage,避免 846605 invalid req_id。
48
+ if (body.msgtype === "event") {
49
+ // 中间帧(thinking / 流式增量)直接跳过,仅在最终帧主动发一次文本。
50
+ if (!finish) {
51
+ runtime.log?.(`[plugin -> server] skip non-final stream for event callback, streamId=${streamId}`);
52
+ return streamId;
53
+ }
54
+ const chatId = body.chatid || body.from?.userid;
55
+ if (!chatId) {
56
+ throw new Error("Missing chatId for event callback reply");
57
+ }
58
+ await withTimeout(wsClient.sendMessage(chatId, {
59
+ msgtype: "markdown",
60
+ markdown: { content: text },
61
+ }), REPLY_SEND_TIMEOUT_MS, `Event reply send timed out (streamId=${streamId})`);
62
+ runtime.log?.(`[plugin -> server] event-active-send chatId=${chatId}, finish=${finish}`);
63
+ return streamId;
64
+ }
65
+ // 非事件消息,继续使用 replyStream(被动回复)
66
+ // 使用 SDK 的 replyStream 方法发送消息,带超时保护
67
+ try {
68
+ await withTimeout(wsClient.replyStream(frame, streamId, text, finish), REPLY_SEND_TIMEOUT_MS, `Reply send timed out (streamId=${streamId})`);
69
+ }
70
+ catch (err) {
71
+ // 服务端返回 846608:流式消息超过6分钟无法更新,需降级为主动发送
72
+ const errMsg = err?.errmsg || err?.message || String(err);
73
+ if (err?.errcode === STREAM_EXPIRED_ERRCODE ||
74
+ errMsg.includes(String(STREAM_EXPIRED_ERRCODE))) {
75
+ throw new StreamExpiredError(errMsg);
76
+ }
77
+ throw err;
78
+ }
79
+ runtime.log?.(`[plugin -> server] streamId=${streamId}, finish=${finish}`);
80
+ return streamId;
81
+ }
82
+ // ============================================================================
83
+ // 非阻塞流式发送(用于 onPartialReply 场景)
84
+ // ============================================================================
85
+ /**
86
+ * 非阻塞流式文本回复
87
+ *
88
+ * 基于 SDK 的 replyStreamNonBlocking 方法:
89
+ * - 如果上一条同 reqId 的消息尚未收到 ack,则跳过本次发送(返回 'skipped'),
90
+ * 避免流式中间帧排队积压导致延迟。
91
+ * - finish=true 的最终帧不受此限制,始终保证发送。
92
+ *
93
+ * @returns 'skipped' 表示被跳过,否则返回 streamId
94
+ */
95
+ export async function sendWeComReplyNonBlocking(params) {
96
+ const { wsClient, frame, text, runtime, streamId, finish = false } = params;
97
+ if (!text) {
98
+ return 'skipped';
99
+ }
100
+ if (!wsClient.isConnected) {
101
+ return 'skipped';
102
+ }
103
+ try {
104
+ // @ts-expect-error -- replyStreamNonBlocking exists at runtime but is missing from SDK type declarations
105
+ const result = await wsClient.replyStreamNonBlocking(frame, streamId, text, finish);
106
+ if (result === 'skipped') {
107
+ return 'skipped';
108
+ }
109
+ return streamId;
110
+ }
111
+ catch (err) {
112
+ // 服务端返回 846608:流式消息超过6分钟无法更新,需降级为主动发送
113
+ const errMsg = err?.errmsg || err?.message || String(err);
114
+ if (err?.errcode === STREAM_EXPIRED_ERRCODE ||
115
+ errMsg.includes(String(STREAM_EXPIRED_ERRCODE))) {
116
+ throw new StreamExpiredError(errMsg);
117
+ }
118
+ throw err;
119
+ }
120
+ }