ylib-wecom-openclaw-plugin 2026.4.29

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 (180) hide show
  1. package/README.md +596 -0
  2. package/dist/index.d.ts +10 -0
  3. package/dist/index.js +99 -0
  4. package/dist/src/accounts.d.ts +57 -0
  5. package/dist/src/accounts.js +247 -0
  6. package/dist/src/agent/api-client.d.ts +95 -0
  7. package/dist/src/agent/api-client.js +425 -0
  8. package/dist/src/agent/handler.d.ts +64 -0
  9. package/dist/src/agent/handler.js +731 -0
  10. package/dist/src/agent/index.d.ts +5 -0
  11. package/dist/src/agent/index.js +21 -0
  12. package/dist/src/agent/webhook.d.ts +25 -0
  13. package/dist/src/agent/webhook.js +294 -0
  14. package/dist/src/agent/xml.d.ts +21 -0
  15. package/dist/src/agent/xml.js +43 -0
  16. package/dist/src/channel.d.ts +5 -0
  17. package/dist/src/channel.js +815 -0
  18. package/dist/src/chat-queue.d.ts +31 -0
  19. package/dist/src/chat-queue.js +53 -0
  20. package/dist/src/config-schema.d.ts +587 -0
  21. package/dist/src/config-schema.js +146 -0
  22. package/dist/src/const.d.ts +128 -0
  23. package/dist/src/const.js +168 -0
  24. package/dist/src/dm-policy.d.ts +29 -0
  25. package/dist/src/dm-policy.js +146 -0
  26. package/dist/src/dynamic-agent.d.ts +37 -0
  27. package/dist/src/dynamic-agent.js +67 -0
  28. package/dist/src/dynamic-routing.d.ts +65 -0
  29. package/dist/src/dynamic-routing.js +62 -0
  30. package/dist/src/endpoint-dispatch.d.ts +54 -0
  31. package/dist/src/endpoint-dispatch.js +967 -0
  32. package/dist/src/endpoint-event-adapter.d.ts +15 -0
  33. package/dist/src/endpoint-event-adapter.js +427 -0
  34. package/dist/src/group-policy.d.ts +30 -0
  35. package/dist/src/group-policy.js +126 -0
  36. package/dist/src/http.d.ts +27 -0
  37. package/dist/src/http.js +168 -0
  38. package/dist/src/im-runtime-telemetry.d.ts +25 -0
  39. package/dist/src/im-runtime-telemetry.js +68 -0
  40. package/dist/src/interface.d.ts +192 -0
  41. package/dist/src/interface.js +5 -0
  42. package/dist/src/markdown-chunk.d.ts +1 -0
  43. package/dist/src/markdown-chunk.js +396 -0
  44. package/dist/src/mcp/index.d.ts +6 -0
  45. package/dist/src/mcp/index.js +28 -0
  46. package/dist/src/mcp/interceptors/biz-error.d.ts +11 -0
  47. package/dist/src/mcp/interceptors/biz-error.js +73 -0
  48. package/dist/src/mcp/interceptors/doc-auth-error.d.ts +10 -0
  49. package/dist/src/mcp/interceptors/doc-auth-error.js +235 -0
  50. package/dist/src/mcp/interceptors/index.d.ts +35 -0
  51. package/dist/src/mcp/interceptors/index.js +143 -0
  52. package/dist/src/mcp/interceptors/msg-media.d.ts +11 -0
  53. package/dist/src/mcp/interceptors/msg-media.js +201 -0
  54. package/dist/src/mcp/interceptors/smartpage-create.d.ts +30 -0
  55. package/dist/src/mcp/interceptors/smartpage-create.js +252 -0
  56. package/dist/src/mcp/interceptors/smartpage-export.d.ts +17 -0
  57. package/dist/src/mcp/interceptors/smartpage-export.js +135 -0
  58. package/dist/src/mcp/interceptors/smartsheet-upload.d.ts +22 -0
  59. package/dist/src/mcp/interceptors/smartsheet-upload.js +388 -0
  60. package/dist/src/mcp/interceptors/types.d.ts +64 -0
  61. package/dist/src/mcp/interceptors/types.js +8 -0
  62. package/dist/src/mcp/schema.d.ts +11 -0
  63. package/dist/src/mcp/schema.js +115 -0
  64. package/dist/src/mcp/tool.d.ts +63 -0
  65. package/dist/src/mcp/tool.js +318 -0
  66. package/dist/src/mcp/transport.d.ts +94 -0
  67. package/dist/src/mcp/transport.js +702 -0
  68. package/dist/src/media-handler.d.ts +55 -0
  69. package/dist/src/media-handler.js +306 -0
  70. package/dist/src/media-uploader.d.ts +142 -0
  71. package/dist/src/media-uploader.js +446 -0
  72. package/dist/src/message-parser.d.ts +104 -0
  73. package/dist/src/message-parser.js +232 -0
  74. package/dist/src/message-sender.d.ts +54 -0
  75. package/dist/src/message-sender.js +210 -0
  76. package/dist/src/monitor.d.ts +69 -0
  77. package/dist/src/monitor.js +1846 -0
  78. package/dist/src/onboarding.d.ts +8 -0
  79. package/dist/src/onboarding.js +248 -0
  80. package/dist/src/openclaw-compat.d.ts +148 -0
  81. package/dist/src/openclaw-compat.js +839 -0
  82. package/dist/src/proactive-markdown-send.d.ts +14 -0
  83. package/dist/src/proactive-markdown-send.js +205 -0
  84. package/dist/src/reqid-store.d.ts +23 -0
  85. package/dist/src/reqid-store.js +136 -0
  86. package/dist/src/runtime.d.ts +2 -0
  87. package/dist/src/runtime.js +7 -0
  88. package/dist/src/shared/command-auth.d.ts +23 -0
  89. package/dist/src/shared/command-auth.js +112 -0
  90. package/dist/src/shared/xml-parser.d.ts +46 -0
  91. package/dist/src/shared/xml-parser.js +228 -0
  92. package/dist/src/state-dir-resolve.d.ts +2 -0
  93. package/dist/src/state-dir-resolve.js +33 -0
  94. package/dist/src/state-manager.d.ts +115 -0
  95. package/dist/src/state-manager.js +413 -0
  96. package/dist/src/target.d.ts +35 -0
  97. package/dist/src/target.js +71 -0
  98. package/dist/src/template-card-manager.d.ts +55 -0
  99. package/dist/src/template-card-manager.js +316 -0
  100. package/dist/src/template-card-parser.d.ts +37 -0
  101. package/dist/src/template-card-parser.js +672 -0
  102. package/dist/src/timeout.d.ts +20 -0
  103. package/dist/src/timeout.js +57 -0
  104. package/dist/src/types/account.d.ts +29 -0
  105. package/dist/src/types/account.js +5 -0
  106. package/dist/src/types/config.d.ts +98 -0
  107. package/dist/src/types/config.js +8 -0
  108. package/dist/src/types/constants.d.ts +42 -0
  109. package/dist/src/types/constants.js +45 -0
  110. package/dist/src/types/index.d.ts +7 -0
  111. package/dist/src/types/index.js +17 -0
  112. package/dist/src/types/message.d.ts +238 -0
  113. package/dist/src/types/message.js +6 -0
  114. package/dist/src/utils.d.ts +148 -0
  115. package/dist/src/utils.js +92 -0
  116. package/dist/src/version.d.ts +2 -0
  117. package/dist/src/version.js +28 -0
  118. package/dist/src/webhook/command-auth.d.ts +47 -0
  119. package/dist/src/webhook/command-auth.js +137 -0
  120. package/dist/src/webhook/gateway.d.ts +36 -0
  121. package/dist/src/webhook/gateway.js +297 -0
  122. package/dist/src/webhook/handler.d.ts +19 -0
  123. package/dist/src/webhook/handler.js +481 -0
  124. package/dist/src/webhook/helpers.d.ts +157 -0
  125. package/dist/src/webhook/helpers.js +936 -0
  126. package/dist/src/webhook/http.d.ts +27 -0
  127. package/dist/src/webhook/http.js +168 -0
  128. package/dist/src/webhook/index.d.ts +11 -0
  129. package/dist/src/webhook/index.js +43 -0
  130. package/dist/src/webhook/media.d.ts +30 -0
  131. package/dist/src/webhook/media.js +152 -0
  132. package/dist/src/webhook/monitor.d.ts +59 -0
  133. package/dist/src/webhook/monitor.js +1672 -0
  134. package/dist/src/webhook/state.d.ts +220 -0
  135. package/dist/src/webhook/state.js +568 -0
  136. package/dist/src/webhook/target.d.ts +41 -0
  137. package/dist/src/webhook/target.js +165 -0
  138. package/dist/src/webhook/types.d.ts +348 -0
  139. package/dist/src/webhook/types.js +36 -0
  140. package/dist/src/webhook/video-frame.d.ts +13 -0
  141. package/dist/src/webhook/video-frame.js +108 -0
  142. package/openclaw.plugin.json +19 -0
  143. package/package.json +96 -0
  144. package/schema.json +534 -0
  145. package/scripts/generate-schema.mjs +33 -0
  146. package/skills/wecom-contact/SKILL.md +162 -0
  147. package/skills/wecom-doc/SKILL.md +162 -0
  148. package/skills/wecom-doc/references/create-doc.md +56 -0
  149. package/skills/wecom-doc/references/edit-doc-content.md +68 -0
  150. package/skills/wecom-doc/references/get-doc-content.md +88 -0
  151. package/skills/wecom-doc/references/smartpage-create.md +125 -0
  152. package/skills/wecom-doc/references/smartpage-export.md +160 -0
  153. package/skills/wecom-meeting/SKILL.md +441 -0
  154. package/skills/wecom-meeting/references/example-full.md +30 -0
  155. package/skills/wecom-meeting/references/example-reminder.md +46 -0
  156. package/skills/wecom-meeting/references/example-security.md +22 -0
  157. package/skills/wecom-meeting/references/response-get-meeting-info.md +148 -0
  158. package/skills/wecom-msg/SKILL.md +157 -0
  159. package/skills/wecom-msg/references/api-get-messages.md +93 -0
  160. package/skills/wecom-msg/references/api-get-msg-chat-list.md +58 -0
  161. package/skills/wecom-msg/references/api-get-msg-media.md +44 -0
  162. package/skills/wecom-msg/references/api-send-message.md +39 -0
  163. package/skills/wecom-preflight/SKILL.md +141 -0
  164. package/skills/wecom-schedule/SKILL.md +161 -0
  165. package/skills/wecom-schedule/references/api-check-availability.md +56 -0
  166. package/skills/wecom-schedule/references/api-create-schedule.md +38 -0
  167. package/skills/wecom-schedule/references/api-get-schedule-detail.md +81 -0
  168. package/skills/wecom-schedule/references/api-update-schedule.md +32 -0
  169. package/skills/wecom-schedule/references/ref-reminders.md +24 -0
  170. package/skills/wecom-send-media/SKILL.md +68 -0
  171. package/skills/wecom-send-template-card/SKILL.md +157 -0
  172. package/skills/wecom-send-template-card/references/api-template-card-types.md +358 -0
  173. package/skills/wecom-smartsheet/SKILL.md +164 -0
  174. package/skills/wecom-smartsheet/references/smartsheet-cell-value-formats.md +163 -0
  175. package/skills/wecom-smartsheet/references/smartsheet-field-types.md +44 -0
  176. package/skills/wecom-smartsheet/references/smartsheet-get-records.md +96 -0
  177. package/skills/wecom-smartsheet/references/webhook-examples.md +185 -0
  178. package/skills/wecom-smartsheet/references/webhook-fallback.md +184 -0
  179. package/skills/wecom-todo/SKILL.md +392 -0
  180. package/skills/wecom-todo/examples/workflows.md +163 -0
@@ -0,0 +1,413 @@
1
+ "use strict";
2
+ /**
3
+ * 企业微信全局状态管理模块
4
+ *
5
+ * 负责管理 WSClient 实例、消息状态(带 TTL 清理)、ReqId 存储
6
+ * 解决全局 Map 的内存泄漏问题
7
+ */
8
+ var __assign = (this && this.__assign) || function () {
9
+ __assign = Object.assign || function(t) {
10
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
11
+ s = arguments[i];
12
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
13
+ t[p] = s[p];
14
+ }
15
+ return t;
16
+ };
17
+ return __assign.apply(this, arguments);
18
+ };
19
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
20
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
21
+ return new (P || (P = Promise))(function (resolve, reject) {
22
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
23
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
24
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
25
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
26
+ });
27
+ };
28
+ var __generator = (this && this.__generator) || function (thisArg, body) {
29
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
30
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
31
+ function verb(n) { return function (v) { return step([n, v]); }; }
32
+ function step(op) {
33
+ if (f) throw new TypeError("Generator is already executing.");
34
+ while (_) try {
35
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
36
+ if (y = 0, t) op = [op[0] & 2, t.value];
37
+ switch (op[0]) {
38
+ case 0: case 1: t = op; break;
39
+ case 4: _.label++; return { value: op[1], done: false };
40
+ case 5: _.label++; y = op[1]; op = [0]; continue;
41
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
42
+ default:
43
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
44
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
45
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
46
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
47
+ if (t[2]) _.ops.pop();
48
+ _.trys.pop(); continue;
49
+ }
50
+ op = body.call(thisArg, _);
51
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
52
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
53
+ }
54
+ };
55
+ var __spreadArrays = (this && this.__spreadArrays) || function () {
56
+ for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
57
+ for (var r = Array(s), k = 0, i = 0; i < il; i++)
58
+ for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
59
+ r[k] = a[j];
60
+ return r;
61
+ };
62
+ var _a;
63
+ exports.__esModule = true;
64
+ exports.cleanupAll = exports.cleanupAccount = exports.deleteSessionChatInfo = exports.getSessionChatInfo = exports.setSessionChatInfo = exports.flushReqIdStore = exports.warmupReqIdStore = exports.deleteReqIdForChat = exports.getReqIdForChat = exports.getReqIdForChatAsync = exports.setReqIdForChat = exports.clearAllMessageStates = exports.deleteMessageState = exports.getMessageState = exports.setMessageState = exports.stopMessageStateCleanup = exports.startMessageStateCleanup = exports.deleteWeComConnectionSnapshot = exports.getWeComConnectionSnapshot = exports.updateWeComConnectionSnapshot = exports.deleteWeComWebSocket = exports.setWeComWebSocket = exports.getWeComWebSocket = void 0;
65
+ var reqid_store_js_1 = require("./reqid-store.js");
66
+ var const_js_1 = require("./const.js");
67
+ // ============================================================================
68
+ // 全局单例状态(通过 globalThis + Symbol.for 确保跨 jiti loader 实例共享)
69
+ //
70
+ // 问题背景:openclaw 框架在不同阶段(主加载、configSchema 加载等)会创建
71
+ // 多个独立的 jiti loader 实例,每个实例有独立的模块缓存(parentCache),
72
+ // 导致本模块被多次实例化,模块级变量不共享。
73
+ // 使用 globalThis + Symbol.for 可以确保同一进程内只有一份状态。
74
+ // ============================================================================
75
+ /** 全局共享状态的唯一键 */
76
+ var SHARED_STATE_KEY = Symbol["for"]("wecom-openclaw-plugin:shared-state:v1");
77
+ /**
78
+ * 获取或创建全局共享状态(进程内单例)
79
+ */
80
+ function getSharedState() {
81
+ var existing = globalThis[SHARED_STATE_KEY];
82
+ if (existing)
83
+ return existing;
84
+ var state = {
85
+ wsClientInstances: new Map(),
86
+ messageStates: new Map(),
87
+ cleanupTimer: null,
88
+ reqIdStores: new Map(),
89
+ connectionSnapshots: new Map()
90
+ };
91
+ globalThis[SHARED_STATE_KEY] = state;
92
+ return state;
93
+ }
94
+ /** 进程内唯一的共享状态 */
95
+ var shared = getSharedState();
96
+ // ============================================================================
97
+ // WSClient 实例管理
98
+ // ============================================================================
99
+ /** WSClient 实例管理 */
100
+ var wsClientInstances = ((_a = globalThis[const_js_1.GLOBAL_WS_CLIENT_KEY]) !== null && _a !== void 0 ? _a : (globalThis[const_js_1.GLOBAL_WS_CLIENT_KEY] = new Map()));
101
+ /**
102
+ * 获取指定账户的 WSClient 实例
103
+ */
104
+ function getWeComWebSocket(accountId) {
105
+ var _a;
106
+ return (_a = shared.wsClientInstances.get(accountId)) !== null && _a !== void 0 ? _a : null;
107
+ }
108
+ exports.getWeComWebSocket = getWeComWebSocket;
109
+ /**
110
+ * 设置指定账户的 WSClient 实例
111
+ */
112
+ function setWeComWebSocket(accountId, client) {
113
+ shared.wsClientInstances.set(accountId, client);
114
+ }
115
+ exports.setWeComWebSocket = setWeComWebSocket;
116
+ /**
117
+ * 删除指定账户的 WSClient 实例
118
+ */
119
+ function deleteWeComWebSocket(accountId) {
120
+ shared.wsClientInstances["delete"](accountId);
121
+ }
122
+ exports.deleteWeComWebSocket = deleteWeComWebSocket;
123
+ function updateWeComConnectionSnapshot(accountId, patch) {
124
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
125
+ var id = String(accountId || "").trim();
126
+ var previous = shared.connectionSnapshots.get(id);
127
+ var next = __assign({ accountId: id, connected: (_a = previous === null || previous === void 0 ? void 0 : previous.connected) !== null && _a !== void 0 ? _a : false, authenticated: (_b = previous === null || previous === void 0 ? void 0 : previous.authenticated) !== null && _b !== void 0 ? _b : false, running: (_c = previous === null || previous === void 0 ? void 0 : previous.running) !== null && _c !== void 0 ? _c : false, restartPending: (_d = previous === null || previous === void 0 ? void 0 : previous.restartPending) !== null && _d !== void 0 ? _d : false, lastEvent: (_e = previous === null || previous === void 0 ? void 0 : previous.lastEvent) !== null && _e !== void 0 ? _e : null, lastEventAt: (_f = previous === null || previous === void 0 ? void 0 : previous.lastEventAt) !== null && _f !== void 0 ? _f : null, lastStartAt: (_g = previous === null || previous === void 0 ? void 0 : previous.lastStartAt) !== null && _g !== void 0 ? _g : null, lastStopAt: (_h = previous === null || previous === void 0 ? void 0 : previous.lastStopAt) !== null && _h !== void 0 ? _h : null, lastError: (_j = previous === null || previous === void 0 ? void 0 : previous.lastError) !== null && _j !== void 0 ? _j : null, reconnectAttempts: (_k = previous === null || previous === void 0 ? void 0 : previous.reconnectAttempts) !== null && _k !== void 0 ? _k : 0 }, patch);
128
+ if (id) {
129
+ shared.connectionSnapshots.set(id, next);
130
+ }
131
+ return next;
132
+ }
133
+ exports.updateWeComConnectionSnapshot = updateWeComConnectionSnapshot;
134
+ function getWeComConnectionSnapshot(accountId) {
135
+ var _a;
136
+ var id = String(accountId || "").trim();
137
+ if (!id)
138
+ return null;
139
+ return (_a = shared.connectionSnapshots.get(id)) !== null && _a !== void 0 ? _a : null;
140
+ }
141
+ exports.getWeComConnectionSnapshot = getWeComConnectionSnapshot;
142
+ function deleteWeComConnectionSnapshot(accountId) {
143
+ var id = String(accountId || "").trim();
144
+ if (!id)
145
+ return;
146
+ shared.connectionSnapshots["delete"](id);
147
+ }
148
+ exports.deleteWeComConnectionSnapshot = deleteWeComConnectionSnapshot;
149
+ // ============================================================================
150
+ // 消息状态管理(带 TTL 清理,防止内存泄漏)
151
+ // ============================================================================
152
+ // MessageStateEntry 接口已在上方 SharedState 定义处声明
153
+ /**
154
+ * 启动消息状态定期清理(自动 TTL 清理 + 容量限制)
155
+ */
156
+ function startMessageStateCleanup() {
157
+ if (shared.cleanupTimer)
158
+ return;
159
+ shared.cleanupTimer = setInterval(function () {
160
+ pruneMessageStates();
161
+ }, const_js_1.MESSAGE_STATE_CLEANUP_INTERVAL_MS);
162
+ // 允许进程退出时不阻塞
163
+ if (shared.cleanupTimer && typeof shared.cleanupTimer === "object" && "unref" in shared.cleanupTimer) {
164
+ shared.cleanupTimer.unref();
165
+ }
166
+ }
167
+ exports.startMessageStateCleanup = startMessageStateCleanup;
168
+ /**
169
+ * 停止消息状态定期清理
170
+ */
171
+ function stopMessageStateCleanup() {
172
+ if (shared.cleanupTimer) {
173
+ clearInterval(shared.cleanupTimer);
174
+ shared.cleanupTimer = null;
175
+ }
176
+ }
177
+ exports.stopMessageStateCleanup = stopMessageStateCleanup;
178
+ /**
179
+ * 清理过期和超量的消息状态条目
180
+ */
181
+ function pruneMessageStates() {
182
+ var now = Date.now();
183
+ // 1. 清理过期条目
184
+ for (var _i = 0, _a = shared.messageStates; _i < _a.length; _i++) {
185
+ var _b = _a[_i], key = _b[0], entry = _b[1];
186
+ if (now - entry.createdAt >= const_js_1.MESSAGE_STATE_TTL_MS) {
187
+ shared.messageStates["delete"](key);
188
+ }
189
+ }
190
+ // 2. 容量限制:如果仍超过最大条目数,按时间淘汰最旧的
191
+ if (shared.messageStates.size > const_js_1.MESSAGE_STATE_MAX_SIZE) {
192
+ var sorted = __spreadArrays(shared.messageStates.entries()).sort(function (a, b) { return a[1].createdAt - b[1].createdAt; });
193
+ var toRemove = sorted.slice(0, shared.messageStates.size - const_js_1.MESSAGE_STATE_MAX_SIZE);
194
+ for (var _c = 0, toRemove_1 = toRemove; _c < toRemove_1.length; _c++) {
195
+ var key = toRemove_1[_c][0];
196
+ shared.messageStates["delete"](key);
197
+ }
198
+ }
199
+ }
200
+ /**
201
+ * 设置消息状态
202
+ */
203
+ function setMessageState(messageId, state) {
204
+ shared.messageStates.set(messageId, {
205
+ state: state,
206
+ createdAt: Date.now()
207
+ });
208
+ }
209
+ exports.setMessageState = setMessageState;
210
+ /**
211
+ * 获取消息状态
212
+ */
213
+ function getMessageState(messageId) {
214
+ var entry = shared.messageStates.get(messageId);
215
+ if (!entry)
216
+ return undefined;
217
+ // 检查 TTL
218
+ if (Date.now() - entry.createdAt >= const_js_1.MESSAGE_STATE_TTL_MS) {
219
+ shared.messageStates["delete"](messageId);
220
+ return undefined;
221
+ }
222
+ return entry.state;
223
+ }
224
+ exports.getMessageState = getMessageState;
225
+ /**
226
+ * 删除消息状态
227
+ */
228
+ function deleteMessageState(messageId) {
229
+ shared.messageStates["delete"](messageId);
230
+ }
231
+ exports.deleteMessageState = deleteMessageState;
232
+ /**
233
+ * 清空所有消息状态
234
+ */
235
+ function clearAllMessageStates() {
236
+ shared.messageStates.clear();
237
+ }
238
+ exports.clearAllMessageStates = clearAllMessageStates;
239
+ // ============================================================================
240
+ // ReqId 持久化存储管理(按 accountId 隔离)
241
+ // ============================================================================
242
+ /**
243
+ * ReqId 持久化存储管理
244
+ * 参考 createPersistentDedupe 模式:内存 + 磁盘双层、文件锁、原子写入、TTL 过期、防抖写入
245
+ * 重启后可从磁盘恢复,确保主动推送消息时能获取到 reqId
246
+ */
247
+ function getOrCreateReqIdStore(accountId) {
248
+ var store = shared.reqIdStores.get(accountId);
249
+ if (!store) {
250
+ store = reqid_store_js_1.createPersistentReqIdStore(accountId);
251
+ shared.reqIdStores.set(accountId, store);
252
+ }
253
+ return store;
254
+ }
255
+ // ============================================================================
256
+ // ReqId 操作函数
257
+ // ============================================================================
258
+ /**
259
+ * 设置 chatId 对应的 reqId(写入内存 + 防抖写磁盘)
260
+ */
261
+ function setReqIdForChat(chatId, reqId, accountId) {
262
+ if (accountId === void 0) { accountId = "default"; }
263
+ getOrCreateReqIdStore(accountId).set(chatId, reqId);
264
+ }
265
+ exports.setReqIdForChat = setReqIdForChat;
266
+ /**
267
+ * 获取 chatId 对应的 reqId(异步:优先内存,miss 时查磁盘并回填内存)
268
+ */
269
+ function getReqIdForChatAsync(chatId, accountId) {
270
+ if (accountId === void 0) { accountId = "default"; }
271
+ return __awaiter(this, void 0, void 0, function () {
272
+ return __generator(this, function (_a) {
273
+ return [2 /*return*/, getOrCreateReqIdStore(accountId).get(chatId)];
274
+ });
275
+ });
276
+ }
277
+ exports.getReqIdForChatAsync = getReqIdForChatAsync;
278
+ /**
279
+ * 获取 chatId 对应的 reqId(同步:仅内存,保留向后兼容)
280
+ */
281
+ function getReqIdForChat(chatId, accountId) {
282
+ if (accountId === void 0) { accountId = "default"; }
283
+ return getOrCreateReqIdStore(accountId).getSync(chatId);
284
+ }
285
+ exports.getReqIdForChat = getReqIdForChat;
286
+ /**
287
+ * 删除 chatId 对应的 reqId
288
+ */
289
+ function deleteReqIdForChat(chatId, accountId) {
290
+ if (accountId === void 0) { accountId = "default"; }
291
+ getOrCreateReqIdStore(accountId)["delete"](chatId);
292
+ }
293
+ exports.deleteReqIdForChat = deleteReqIdForChat;
294
+ /**
295
+ * 启动时预热 reqId 缓存(从磁盘加载到内存)
296
+ *
297
+ * 注意:由于移除了磁盘存储,此函数现在只返回 0(无预热条目)
298
+ */
299
+ function warmupReqIdStore(accountId, log) {
300
+ if (accountId === void 0) { accountId = "default"; }
301
+ return __awaiter(this, void 0, void 0, function () {
302
+ return __generator(this, function (_a) {
303
+ // 由于移除了磁盘存储,不再需要预热过程
304
+ log === null || log === void 0 ? void 0 : log("[WeCom] reqid-store warmup: no-op (disk storage removed)");
305
+ return [2 /*return*/, 0];
306
+ });
307
+ });
308
+ }
309
+ exports.warmupReqIdStore = warmupReqIdStore;
310
+ /**
311
+ * 立即将 reqId 数据刷写到磁盘(用于优雅退出)
312
+ *
313
+ * 注意:由于移除了磁盘存储,此函数现在是无操作
314
+ */
315
+ function flushReqIdStore(accountId) {
316
+ if (accountId === void 0) { accountId = "default"; }
317
+ return __awaiter(this, void 0, void 0, function () {
318
+ return __generator(this, function (_a) {
319
+ return [2 /*return*/];
320
+ });
321
+ });
322
+ }
323
+ exports.flushReqIdStore = flushReqIdStore;
324
+ /** sessionKey → SessionChatInfo 映射 */
325
+ var sessionChatInfoMap = new Map();
326
+ /** 容量上限,超出按插入顺序淘汰最旧项,避免长时间运行内存增长 */
327
+ var SESSION_CHAT_INFO_MAX_SIZE = 5000;
328
+ /**
329
+ * 记录 sessionKey 对应的原始会话信息(由 monitor.ts 在消息入站时调用)
330
+ */
331
+ function setSessionChatInfo(sessionKey, info) {
332
+ if (!sessionKey)
333
+ return;
334
+ // 容量控制:超限时淘汰最早插入的条目(Map 保留插入顺序)
335
+ if (sessionChatInfoMap.size >= SESSION_CHAT_INFO_MAX_SIZE && !sessionChatInfoMap.has(sessionKey)) {
336
+ var oldestKey = sessionChatInfoMap.keys().next().value;
337
+ if (oldestKey !== undefined) {
338
+ sessionChatInfoMap["delete"](oldestKey);
339
+ }
340
+ }
341
+ sessionChatInfoMap.set(sessionKey, info);
342
+ }
343
+ exports.setSessionChatInfo = setSessionChatInfo;
344
+ /**
345
+ * 获取 sessionKey 对应的原始会话信息(由 registerTool 闭包调用)
346
+ */
347
+ function getSessionChatInfo(sessionKey) {
348
+ if (!sessionKey)
349
+ return undefined;
350
+ return sessionChatInfoMap.get(sessionKey);
351
+ }
352
+ exports.getSessionChatInfo = getSessionChatInfo;
353
+ /**
354
+ * 删除 sessionKey 对应的会话信息(会话结束时可选调用)
355
+ */
356
+ function deleteSessionChatInfo(sessionKey) {
357
+ sessionChatInfoMap["delete"](sessionKey);
358
+ }
359
+ exports.deleteSessionChatInfo = deleteSessionChatInfo;
360
+ // ============================================================================
361
+ // 全局 cleanup 原始位置
362
+ // ============================================================================
363
+ /**
364
+ * 清理指定账户的所有资源
365
+ */
366
+ function cleanupAccount(accountId) {
367
+ return __awaiter(this, void 0, void 0, function () {
368
+ var wsClient;
369
+ return __generator(this, function (_a) {
370
+ wsClient = shared.wsClientInstances.get(accountId);
371
+ if (wsClient) {
372
+ try {
373
+ wsClient.disconnect();
374
+ }
375
+ catch (_b) {
376
+ // 忽略断开连接时的错误
377
+ }
378
+ shared.wsClientInstances["delete"](accountId);
379
+ }
380
+ return [2 /*return*/];
381
+ });
382
+ });
383
+ }
384
+ exports.cleanupAccount = cleanupAccount;
385
+ /**
386
+ * 清理所有资源(用于进程退出)
387
+ */
388
+ function cleanupAll() {
389
+ return __awaiter(this, void 0, void 0, function () {
390
+ var _i, _a, _b, accountId, wsClient;
391
+ return __generator(this, function (_c) {
392
+ // 停止定期清理
393
+ stopMessageStateCleanup();
394
+ // 清理所有 WSClient
395
+ for (_i = 0, _a = shared.wsClientInstances; _i < _a.length; _i++) {
396
+ _b = _a[_i], accountId = _b[0], wsClient = _b[1];
397
+ try {
398
+ wsClient.disconnect();
399
+ }
400
+ catch (_d) {
401
+ // 忽略
402
+ }
403
+ }
404
+ shared.wsClientInstances.clear();
405
+ shared.connectionSnapshots.clear();
406
+ // 由于移除了磁盘存储,不再需要 flush 所有 reqId 存储
407
+ // 清空消息状态
408
+ clearAllMessageStates();
409
+ return [2 /*return*/];
410
+ });
411
+ });
412
+ }
413
+ exports.cleanupAll = cleanupAll;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * WeCom Target Resolver (企业微信目标解析器)
3
+ *
4
+ * 解析 OpenClaw 的 `to` 字段(原始目标字符串),将其转换为企业微信支持的具体接收对象。
5
+ * 支持显式前缀 (party:, tag: 等) 和基于规则的启发式推断。
6
+ *
7
+ * **关于“目标发送”与“消息记录”的对应关系 (Target vs Inbound):**
8
+ * - **发送 (Outbound)**: 支持一对多广播 (Party/Tag)。
9
+ * 例如发送给 `party:1`,消息会触达该部门下所有成员。
10
+ * - **接收 (Inbound)**: 总是来自具体的 **用户 (User)** 或 **群聊 (Chat)**。
11
+ * 当成员回复部门广播消息时,可以视为一个新的单聊会话或在该成员的现有单聊中回复。
12
+ * 因此,Outbound Target (如 Party) 与 Inbound Source (User) 不需要也不可能 1:1 强匹配。
13
+ * 广播是“发后即忘” (Fire-and-Forget) 的通知模式,而回复是具体的会话模式。
14
+ */
15
+ export interface WecomTarget {
16
+ touser?: string;
17
+ toparty?: string;
18
+ totag?: string;
19
+ chatid?: string;
20
+ }
21
+ /**
22
+ * Parses a raw target string into a WeComTarget object.
23
+ * 解析原始目标字符串为 WeComTarget 对象。
24
+ *
25
+ * 逻辑:
26
+ * 1. 移除标准命名空间前缀 (wecom:, qywx: 等)。
27
+ * 2. 检查显式类型前缀 (party:, tag:, group:, user:)。
28
+ * 3. 启发式回退 (无前缀时):
29
+ * - 以 "wr" 或 "wc" 开头 -> Chat ID (群聊)
30
+ * - 纯数字 -> Party ID (部门)
31
+ * - 其他 -> User ID (用户)
32
+ *
33
+ * @param raw - The raw target string (e.g. "party:1", "zhangsan", "wecom:wr123")
34
+ */
35
+ export declare function resolveWecomTarget(raw: string | undefined): WecomTarget | undefined;
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ /**
3
+ * WeCom Target Resolver (企业微信目标解析器)
4
+ *
5
+ * 解析 OpenClaw 的 `to` 字段(原始目标字符串),将其转换为企业微信支持的具体接收对象。
6
+ * 支持显式前缀 (party:, tag: 等) 和基于规则的启发式推断。
7
+ *
8
+ * **关于“目标发送”与“消息记录”的对应关系 (Target vs Inbound):**
9
+ * - **发送 (Outbound)**: 支持一对多广播 (Party/Tag)。
10
+ * 例如发送给 `party:1`,消息会触达该部门下所有成员。
11
+ * - **接收 (Inbound)**: 总是来自具体的 **用户 (User)** 或 **群聊 (Chat)**。
12
+ * 当成员回复部门广播消息时,可以视为一个新的单聊会话或在该成员的现有单聊中回复。
13
+ * 因此,Outbound Target (如 Party) 与 Inbound Source (User) 不需要也不可能 1:1 强匹配。
14
+ * 广播是“发后即忘” (Fire-and-Forget) 的通知模式,而回复是具体的会话模式。
15
+ */
16
+ exports.__esModule = true;
17
+ exports.resolveWecomTarget = void 0;
18
+ /**
19
+ * Parses a raw target string into a WeComTarget object.
20
+ * 解析原始目标字符串为 WeComTarget 对象。
21
+ *
22
+ * 逻辑:
23
+ * 1. 移除标准命名空间前缀 (wecom:, qywx: 等)。
24
+ * 2. 检查显式类型前缀 (party:, tag:, group:, user:)。
25
+ * 3. 启发式回退 (无前缀时):
26
+ * - 以 "wr" 或 "wc" 开头 -> Chat ID (群聊)
27
+ * - 纯数字 -> Party ID (部门)
28
+ * - 其他 -> User ID (用户)
29
+ *
30
+ * @param raw - The raw target string (e.g. "party:1", "zhangsan", "wecom:wr123")
31
+ */
32
+ function resolveWecomTarget(raw) {
33
+ if (!(raw === null || raw === void 0 ? void 0 : raw.trim()))
34
+ return undefined;
35
+ // 1. Remove standard namespace prefixes (移除标准命名空间前缀)
36
+ var clean = raw.trim().replace(/^(wecom-agent|wecom|wechatwork|wework|qywx):/i, "");
37
+ // 2. Explicit Type Prefixes (显式类型前缀)
38
+ if (/^party:/i.test(clean)) {
39
+ return { toparty: clean.replace(/^party:/i, "").trim() };
40
+ }
41
+ if (/^dept:/i.test(clean)) {
42
+ return { toparty: clean.replace(/^dept:/i, "").trim() };
43
+ }
44
+ if (/^tag:/i.test(clean)) {
45
+ return { totag: clean.replace(/^tag:/i, "").trim() };
46
+ }
47
+ if (/^group:/i.test(clean)) {
48
+ return { chatid: clean.replace(/^group:/i, "").trim() };
49
+ }
50
+ if (/^chat:/i.test(clean)) {
51
+ return { chatid: clean.replace(/^chat:/i, "").trim() };
52
+ }
53
+ if (/^user:/i.test(clean)) {
54
+ return { touser: clean.replace(/^user:/i, "").trim() };
55
+ }
56
+ // 3. Heuristics (启发式规则)
57
+ // Chat ID typically starts with 'wr' or 'wc'
58
+ // 群聊 ID 通常以 'wr' (外部群) 或 'wc' 开头
59
+ if (/^(wr|wc)/i.test(clean)) {
60
+ return { chatid: clean };
61
+ }
62
+ // Pure digits are likely Department IDs (Parties)
63
+ // 纯数字优先被视为部门 ID (Parties),方便运维配置 (如 "1" 代表根部门)
64
+ // 如果必须要发送给纯数字 ID 的用户,请使用显式前缀 "user:1001"
65
+ if (/^\d+$/.test(clean)) {
66
+ return { toparty: clean };
67
+ }
68
+ // Default to User (默认为用户)
69
+ return { touser: clean };
70
+ }
71
+ exports.resolveWecomTarget = resolveWecomTarget;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * 模板卡片管理器
3
+ *
4
+ * 负责:
5
+ * - 模板卡片缓存管理(内存级,带 TTL 和大小限制)
6
+ * - 卡片交互事件处理(更新卡片 UI 状态)
7
+ * - 模板卡片发送(通过 wsClient.sendMessage 主动推送)
8
+ * - 从 LLM 回复中检测并处理模板卡片
9
+ */
10
+ import type { RuntimeEnv } from "ylib-openclaw/plugin-sdk";
11
+ import type { WSClient, WsFrame, TemplateCard } from "@wecom/aibot-node-sdk";
12
+ import type { ResolvedWeComAccount } from "./utils.js";
13
+ import type { MessageState, ExtractedTemplateCard } from "./interface.js";
14
+ export declare function saveTemplateCardToCache(params: {
15
+ accountId: string;
16
+ templateCard: TemplateCard;
17
+ runtime: RuntimeEnv;
18
+ }): void;
19
+ export declare function getTemplateCardFromCache(accountId: string, taskId: string): TemplateCard | undefined;
20
+ export declare function updateTemplateCardOnEvent(params: {
21
+ frame: WsFrame;
22
+ accountId: string;
23
+ runtime: RuntimeEnv;
24
+ wsClient: WSClient;
25
+ }): Promise<void>;
26
+ /**
27
+ * 逐个发送已提取的模板卡片(通过 wsClient.sendMessage 主动推送)
28
+ *
29
+ * 发送失败不阻塞流程,仅记录错误日志。
30
+ */
31
+ export declare function sendTemplateCards(params: {
32
+ wsClient: WSClient;
33
+ frame: WsFrame;
34
+ state: MessageState;
35
+ account: ResolvedWeComAccount;
36
+ runtime: RuntimeEnv;
37
+ cards: ExtractedTemplateCard[];
38
+ }): Promise<void>;
39
+ /**
40
+ * 从累积文本中检测并发送模板卡片。
41
+ *
42
+ * 在 finishThinkingStream 之前调用,将卡片处理和流关闭解耦。
43
+ *
44
+ * @returns 移除卡片代码块后的剩余文本(如果没有卡片则返回 null,表示无需修改)
45
+ */
46
+ export declare function processTemplateCardsIfNeeded(params: {
47
+ wsClient: WSClient;
48
+ frame: WsFrame;
49
+ state: MessageState;
50
+ account: ResolvedWeComAccount;
51
+ runtime: RuntimeEnv;
52
+ }): Promise<{
53
+ remainingText: string;
54
+ cardsDetected: boolean;
55
+ } | null>;