@netcat-ai/openclaw-weixin 2.4.7

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 (116) hide show
  1. package/CHANGELOG.md +156 -0
  2. package/CHANGELOG.zh_CN.md +156 -0
  3. package/LICENSE +27 -0
  4. package/README.md +355 -0
  5. package/README.zh_CN.md +351 -0
  6. package/dist/index.js +16 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/src/api/api.js +484 -0
  9. package/dist/src/api/api.js.map +1 -0
  10. package/dist/src/api/config-cache.js +64 -0
  11. package/dist/src/api/config-cache.js.map +1 -0
  12. package/dist/src/api/session-guard.js +49 -0
  13. package/dist/src/api/session-guard.js.map +1 -0
  14. package/dist/src/api/types.js +37 -0
  15. package/dist/src/api/types.js.map +1 -0
  16. package/dist/src/auth/accounts.js +328 -0
  17. package/dist/src/auth/accounts.js.map +1 -0
  18. package/dist/src/auth/login-qr.js +331 -0
  19. package/dist/src/auth/login-qr.js.map +1 -0
  20. package/dist/src/auth/pairing.js +104 -0
  21. package/dist/src/auth/pairing.js.map +1 -0
  22. package/dist/src/cdn/aes-ecb.js +19 -0
  23. package/dist/src/cdn/aes-ecb.js.map +1 -0
  24. package/dist/src/cdn/cdn-upload.js +74 -0
  25. package/dist/src/cdn/cdn-upload.js.map +1 -0
  26. package/dist/src/cdn/cdn-url.js +14 -0
  27. package/dist/src/cdn/cdn-url.js.map +1 -0
  28. package/dist/src/cdn/pic-decrypt.js +89 -0
  29. package/dist/src/cdn/pic-decrypt.js.map +1 -0
  30. package/dist/src/cdn/upload.js +115 -0
  31. package/dist/src/cdn/upload.js.map +1 -0
  32. package/dist/src/channel.js +478 -0
  33. package/dist/src/channel.js.map +1 -0
  34. package/dist/src/compat.js +67 -0
  35. package/dist/src/compat.js.map +1 -0
  36. package/dist/src/config/config-schema.js +20 -0
  37. package/dist/src/config/config-schema.js.map +1 -0
  38. package/dist/src/config/reply-progress.js +5 -0
  39. package/dist/src/config/reply-progress.js.map +1 -0
  40. package/dist/src/media/media-download.js +95 -0
  41. package/dist/src/media/media-download.js.map +1 -0
  42. package/dist/src/media/mime.js +73 -0
  43. package/dist/src/media/mime.js.map +1 -0
  44. package/dist/src/media/silk-transcode.js +64 -0
  45. package/dist/src/media/silk-transcode.js.map +1 -0
  46. package/dist/src/messaging/debug-mode.js +63 -0
  47. package/dist/src/messaging/debug-mode.js.map +1 -0
  48. package/dist/src/messaging/error-notice.js +25 -0
  49. package/dist/src/messaging/error-notice.js.map +1 -0
  50. package/dist/src/messaging/inbound.js +201 -0
  51. package/dist/src/messaging/inbound.js.map +1 -0
  52. package/dist/src/messaging/markdown-filter.js +368 -0
  53. package/dist/src/messaging/markdown-filter.js.map +1 -0
  54. package/dist/src/messaging/outbound-hooks.js +58 -0
  55. package/dist/src/messaging/outbound-hooks.js.map +1 -0
  56. package/dist/src/messaging/process-message.js +406 -0
  57. package/dist/src/messaging/process-message.js.map +1 -0
  58. package/dist/src/messaging/reply-progress-sender.js +93 -0
  59. package/dist/src/messaging/reply-progress-sender.js.map +1 -0
  60. package/dist/src/messaging/send-media.js +54 -0
  61. package/dist/src/messaging/send-media.js.map +1 -0
  62. package/dist/src/messaging/send.js +220 -0
  63. package/dist/src/messaging/send.js.map +1 -0
  64. package/dist/src/messaging/slash-commands.js +70 -0
  65. package/dist/src/messaging/slash-commands.js.map +1 -0
  66. package/dist/src/monitor/monitor.js +146 -0
  67. package/dist/src/monitor/monitor.js.map +1 -0
  68. package/dist/src/storage/state-dir.js +9 -0
  69. package/dist/src/storage/state-dir.js.map +1 -0
  70. package/dist/src/storage/sync-buf.js +64 -0
  71. package/dist/src/storage/sync-buf.js.map +1 -0
  72. package/dist/src/util/logger.js +120 -0
  73. package/dist/src/util/logger.js.map +1 -0
  74. package/dist/src/util/random.js +16 -0
  75. package/dist/src/util/random.js.map +1 -0
  76. package/dist/src/util/redact.js +54 -0
  77. package/dist/src/util/redact.js.map +1 -0
  78. package/index.ts +19 -0
  79. package/openclaw.plugin.json +22 -0
  80. package/package.json +75 -0
  81. package/src/api/api.ts +586 -0
  82. package/src/api/config-cache.ts +79 -0
  83. package/src/api/session-guard.ts +58 -0
  84. package/src/api/types.ts +278 -0
  85. package/src/auth/accounts.ts +394 -0
  86. package/src/auth/login-qr.ts +458 -0
  87. package/src/auth/pairing.ts +120 -0
  88. package/src/cdn/aes-ecb.ts +21 -0
  89. package/src/cdn/cdn-upload.ts +93 -0
  90. package/src/cdn/cdn-url.ts +20 -0
  91. package/src/cdn/pic-decrypt.ts +101 -0
  92. package/src/cdn/upload.ts +168 -0
  93. package/src/channel.ts +548 -0
  94. package/src/compat.ts +77 -0
  95. package/src/config/config-schema.ts +23 -0
  96. package/src/config/reply-progress.ts +10 -0
  97. package/src/media/media-download.ts +149 -0
  98. package/src/media/mime.ts +76 -0
  99. package/src/media/silk-transcode.ts +74 -0
  100. package/src/messaging/debug-mode.ts +69 -0
  101. package/src/messaging/error-notice.ts +32 -0
  102. package/src/messaging/inbound.ts +262 -0
  103. package/src/messaging/markdown-filter.ts +361 -0
  104. package/src/messaging/outbound-hooks.ts +88 -0
  105. package/src/messaging/process-message.ts +525 -0
  106. package/src/messaging/reply-progress-sender.ts +122 -0
  107. package/src/messaging/send-media.ts +72 -0
  108. package/src/messaging/send.ts +294 -0
  109. package/src/messaging/slash-commands.ts +110 -0
  110. package/src/monitor/monitor.ts +224 -0
  111. package/src/storage/state-dir.ts +11 -0
  112. package/src/storage/sync-buf.ts +81 -0
  113. package/src/util/logger.ts +145 -0
  114. package/src/util/random.ts +17 -0
  115. package/src/util/redact.ts +54 -0
  116. package/src/vendor.d.ts +25 -0
@@ -0,0 +1,220 @@
1
+ import { sendMessage as sendMessageApi } from "../api/api.js";
2
+ import { logger } from "../util/logger.js";
3
+ import { generateId } from "../util/random.js";
4
+ import { MessageItemType, MessageState, MessageType } from "../api/types.js";
5
+ export { StreamingMarkdownFilter } from "./markdown-filter.js";
6
+ function generateClientId() {
7
+ return generateId("openclaw-weixin");
8
+ }
9
+ /** Build a SendMessageReq containing a single text message. */
10
+ function buildTextMessageReq(params) {
11
+ const { to, text, contextToken, runId, clientId } = params;
12
+ const item_list = text
13
+ ? [{ type: MessageItemType.TEXT, text_item: { text } }]
14
+ : [];
15
+ return {
16
+ msg: {
17
+ from_user_id: "",
18
+ to_user_id: to,
19
+ client_id: clientId,
20
+ message_type: MessageType.BOT,
21
+ message_state: MessageState.FINISH,
22
+ item_list: item_list.length ? item_list : undefined,
23
+ context_token: contextToken ?? undefined,
24
+ run_id: runId ?? undefined,
25
+ },
26
+ };
27
+ }
28
+ /** Build a SendMessageReq from a reply payload (text only; image send uses sendImageMessageWeixin). */
29
+ function buildSendMessageReq(params) {
30
+ const { to, contextToken, runId, payload, clientId } = params;
31
+ return buildTextMessageReq({
32
+ to,
33
+ text: payload.text ?? "",
34
+ contextToken,
35
+ runId,
36
+ clientId,
37
+ });
38
+ }
39
+ /**
40
+ * Send a plain text message downstream.
41
+ */
42
+ export async function sendMessageWeixin(params) {
43
+ const { to, text, opts } = params;
44
+ if (!opts.contextToken) {
45
+ logger.warn(`sendMessageWeixin: contextToken missing for to=${to}, sending without context`);
46
+ }
47
+ const clientId = generateClientId();
48
+ const req = buildSendMessageReq({
49
+ to,
50
+ contextToken: opts.contextToken,
51
+ runId: opts.runId,
52
+ payload: { text },
53
+ clientId,
54
+ });
55
+ try {
56
+ await sendMessageApi({
57
+ baseUrl: opts.baseUrl,
58
+ token: opts.token,
59
+ timeoutMs: opts.timeoutMs,
60
+ body: req,
61
+ });
62
+ }
63
+ catch (err) {
64
+ logger.error(`sendMessageWeixin: failed to=${to} clientId=${clientId} err=${String(err)}`);
65
+ throw err;
66
+ }
67
+ return { messageId: clientId };
68
+ }
69
+ /** Send a single structured MessageItem downstream. */
70
+ export async function sendMessageItemWeixin(params) {
71
+ const { to, item, opts } = params;
72
+ if (!opts.contextToken) {
73
+ logger.warn(`sendMessageItemWeixin: contextToken missing for to=${to}, sending without context`);
74
+ }
75
+ const clientId = params.clientId ?? generateClientId();
76
+ const req = {
77
+ msg: {
78
+ from_user_id: "",
79
+ to_user_id: to,
80
+ client_id: clientId,
81
+ message_type: MessageType.BOT,
82
+ message_state: MessageState.FINISH,
83
+ item_list: [item],
84
+ context_token: opts.contextToken ?? undefined,
85
+ run_id: opts.runId,
86
+ },
87
+ };
88
+ try {
89
+ await sendMessageApi({
90
+ baseUrl: opts.baseUrl,
91
+ token: opts.token,
92
+ timeoutMs: opts.timeoutMs,
93
+ body: req,
94
+ });
95
+ }
96
+ catch (err) {
97
+ logger.error(`${params.label ?? "sendMessageItemWeixin"}: failed to=${to} clientId=${clientId} err=${String(err)}`);
98
+ throw err;
99
+ }
100
+ return { messageId: clientId };
101
+ }
102
+ /**
103
+ * Send one or more MessageItems (optionally preceded by a text caption) downstream.
104
+ * Each item is sent as its own request so that item_list always has exactly one entry.
105
+ */
106
+ async function sendMediaItems(params) {
107
+ const { to, text, mediaItem, opts, label } = params;
108
+ const runId = opts.runId;
109
+ const items = [];
110
+ if (text) {
111
+ items.push({ type: MessageItemType.TEXT, text_item: { text } });
112
+ }
113
+ items.push(mediaItem);
114
+ let lastClientId = "";
115
+ for (const item of items) {
116
+ lastClientId = generateClientId();
117
+ const req = {
118
+ msg: {
119
+ from_user_id: "",
120
+ to_user_id: to,
121
+ client_id: lastClientId,
122
+ message_type: MessageType.BOT,
123
+ message_state: MessageState.FINISH,
124
+ item_list: [item],
125
+ context_token: opts.contextToken ?? undefined,
126
+ run_id: runId,
127
+ },
128
+ };
129
+ try {
130
+ await sendMessageApi({
131
+ baseUrl: opts.baseUrl,
132
+ token: opts.token,
133
+ timeoutMs: opts.timeoutMs,
134
+ body: req,
135
+ });
136
+ }
137
+ catch (err) {
138
+ logger.error(`${label}: failed to=${to} clientId=${lastClientId} err=${String(err)}`);
139
+ throw err;
140
+ }
141
+ }
142
+ logger.info(`${label}: success to=${to} clientId=${lastClientId}`);
143
+ return { messageId: lastClientId };
144
+ }
145
+ /**
146
+ * Send an image message downstream using a previously uploaded file.
147
+ * Optionally include a text caption as a separate TEXT item before the image.
148
+ *
149
+ * ImageItem fields:
150
+ * - media.encrypt_query_param: CDN download param
151
+ * - media.aes_key: AES key, base64-encoded
152
+ * - mid_size: original ciphertext file size
153
+ */
154
+ export async function sendImageMessageWeixin(params) {
155
+ const { to, text, uploaded, opts } = params;
156
+ if (!opts.contextToken) {
157
+ logger.warn(`sendImageMessageWeixin: contextToken missing for to=${to}, sending without context`);
158
+ }
159
+ logger.info(`sendImageMessageWeixin: to=${to} filekey=${uploaded.filekey} fileSize=${uploaded.fileSize} aeskey=present`);
160
+ const imageItem = {
161
+ type: MessageItemType.IMAGE,
162
+ image_item: {
163
+ media: {
164
+ encrypt_query_param: uploaded.downloadEncryptedQueryParam,
165
+ aes_key: Buffer.from(uploaded.aeskey).toString("base64"),
166
+ encrypt_type: 1,
167
+ },
168
+ mid_size: uploaded.fileSizeCiphertext,
169
+ },
170
+ };
171
+ return sendMediaItems({ to, text, mediaItem: imageItem, opts, label: "sendImageMessageWeixin" });
172
+ }
173
+ /**
174
+ * Send a video message downstream using a previously uploaded file.
175
+ * VideoItem: media (CDN ref), video_size (ciphertext bytes).
176
+ * Includes an optional text caption sent as a separate TEXT item first.
177
+ */
178
+ export async function sendVideoMessageWeixin(params) {
179
+ const { to, text, uploaded, opts } = params;
180
+ if (!opts.contextToken) {
181
+ logger.warn(`sendVideoMessageWeixin: contextToken missing for to=${to}, sending without context`);
182
+ }
183
+ const videoItem = {
184
+ type: MessageItemType.VIDEO,
185
+ video_item: {
186
+ media: {
187
+ encrypt_query_param: uploaded.downloadEncryptedQueryParam,
188
+ aes_key: Buffer.from(uploaded.aeskey).toString("base64"),
189
+ encrypt_type: 1,
190
+ },
191
+ video_size: uploaded.fileSizeCiphertext,
192
+ },
193
+ };
194
+ return sendMediaItems({ to, text, mediaItem: videoItem, opts, label: "sendVideoMessageWeixin" });
195
+ }
196
+ /**
197
+ * Send a file attachment downstream using a previously uploaded file.
198
+ * FileItem: media (CDN ref), file_name, len (plaintext bytes as string).
199
+ * Includes an optional text caption sent as a separate TEXT item first.
200
+ */
201
+ export async function sendFileMessageWeixin(params) {
202
+ const { to, text, fileName, uploaded, opts } = params;
203
+ if (!opts.contextToken) {
204
+ logger.warn(`sendFileMessageWeixin: contextToken missing for to=${to}, sending without context`);
205
+ }
206
+ const fileItem = {
207
+ type: MessageItemType.FILE,
208
+ file_item: {
209
+ media: {
210
+ encrypt_query_param: uploaded.downloadEncryptedQueryParam,
211
+ aes_key: Buffer.from(uploaded.aeskey).toString("base64"),
212
+ encrypt_type: 1,
213
+ },
214
+ file_name: fileName,
215
+ len: String(uploaded.fileSize),
216
+ },
217
+ };
218
+ return sendMediaItems({ to, text, mediaItem: fileItem, opts, label: "sendFileMessageWeixin" });
219
+ }
220
+ //# sourceMappingURL=send.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send.js","sourceRoot":"","sources":["../../../src/messaging/send.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ import { logger } from "../util/logger.js";
2
+ import { toggleDebugMode } from "./debug-mode.js";
3
+ import { sendMessageWeixin } from "./send.js";
4
+ /** 发送回复消息 */
5
+ async function sendReply(ctx, text) {
6
+ const opts = {
7
+ baseUrl: ctx.baseUrl,
8
+ token: ctx.token,
9
+ contextToken: ctx.contextToken,
10
+ };
11
+ await sendMessageWeixin({ to: ctx.to, text, opts });
12
+ }
13
+ /** 处理 /echo 指令 */
14
+ async function handleEcho(ctx, args, receivedAt, eventTimestamp) {
15
+ const message = args.trim();
16
+ if (message) {
17
+ await sendReply(ctx, message);
18
+ }
19
+ const eventTs = eventTimestamp ?? 0;
20
+ const platformDelay = eventTs > 0 ? `${receivedAt - eventTs}ms` : "N/A";
21
+ const timing = [
22
+ "⏱ 通道耗时",
23
+ `├ 事件时间: ${eventTs > 0 ? new Date(eventTs).toISOString() : "N/A"}`,
24
+ `├ 平台→插件: ${platformDelay}`,
25
+ `└ 插件处理: ${Date.now() - receivedAt}ms`,
26
+ ].join("\n");
27
+ await sendReply(ctx, timing);
28
+ }
29
+ /**
30
+ * 尝试处理斜杠指令
31
+ *
32
+ * @returns handled=true 表示该消息已作为指令处理,不需要继续走 AI 管道
33
+ */
34
+ export async function handleSlashCommand(content, ctx, receivedAt, eventTimestamp) {
35
+ const trimmed = content.trim();
36
+ if (!trimmed.startsWith("/")) {
37
+ return { handled: false };
38
+ }
39
+ const spaceIdx = trimmed.indexOf(" ");
40
+ const command = spaceIdx === -1 ? trimmed.toLowerCase() : trimmed.slice(0, spaceIdx).toLowerCase();
41
+ const args = spaceIdx === -1 ? "" : trimmed.slice(spaceIdx + 1);
42
+ logger.info(`[weixin] Slash command: ${command}, args: ${args.slice(0, 50)}`);
43
+ try {
44
+ switch (command) {
45
+ case "/echo":
46
+ await handleEcho(ctx, args, receivedAt, eventTimestamp);
47
+ return { handled: true };
48
+ case "/toggle-debug": {
49
+ const enabled = toggleDebugMode(ctx.accountId);
50
+ await sendReply(ctx, enabled
51
+ ? "Debug 模式已开启"
52
+ : "Debug 模式已关闭");
53
+ return { handled: true };
54
+ }
55
+ default:
56
+ return { handled: false };
57
+ }
58
+ }
59
+ catch (err) {
60
+ logger.error(`[weixin] Slash command error: ${String(err)}`);
61
+ try {
62
+ await sendReply(ctx, `❌ 指令执行失败: ${String(err).slice(0, 200)}`);
63
+ }
64
+ catch {
65
+ // 发送错误消息也失败了,只能记日志
66
+ }
67
+ return { handled: true };
68
+ }
69
+ }
70
+ //# sourceMappingURL=slash-commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slash-commands.js","sourceRoot":"","sources":["../../../src/messaging/slash-commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,146 @@
1
+ import { getUpdates, classifyFetchError } from "../api/api.js";
2
+ import { WeixinConfigManager } from "../api/config-cache.js";
3
+ import { STALE_TOKEN_ERRCODE, pauseSession, getRemainingPauseMs } from "../api/session-guard.js";
4
+ import { processOneMessage } from "../messaging/process-message.js";
5
+ import { getSyncBufFilePath, loadGetUpdatesBuf, saveGetUpdatesBuf } from "../storage/sync-buf.js";
6
+ import { logger } from "../util/logger.js";
7
+ import { redactBody } from "../util/redact.js";
8
+ const DEFAULT_LONG_POLL_TIMEOUT_MS = 35_000;
9
+ const MAX_CONSECUTIVE_FAILURES = 3;
10
+ const BACKOFF_DELAY_MS = 30_000;
11
+ const RETRY_DELAY_MS = 2_000;
12
+ /**
13
+ * Long-poll loop: getUpdates -> normalize -> recordInboundSession -> dispatchReplyFromConfig.
14
+ * Runs until abort.
15
+ */
16
+ export async function monitorWeixinProvider(opts) {
17
+ const { baseUrl, cdnBaseUrl, token, accountId, config, channelRuntime, abortSignal, longPollTimeoutMs, setStatus, } = opts;
18
+ const log = opts.runtime?.log ?? (() => { });
19
+ const errLog = opts.runtime?.error ?? ((m) => log(m));
20
+ const aLog = logger.withAccount(accountId);
21
+ if (!channelRuntime) {
22
+ const msg = "channelRuntime missing on monitor opts; gateway must inject ChannelGatewayContext.channelRuntime";
23
+ aLog.error(msg);
24
+ throw new Error(msg);
25
+ }
26
+ log(`weixin monitor started (${baseUrl}, account=${accountId})`);
27
+ aLog.info(`Monitor started: baseUrl=${baseUrl} timeoutMs=${longPollTimeoutMs ?? DEFAULT_LONG_POLL_TIMEOUT_MS}`);
28
+ const syncFilePath = getSyncBufFilePath(accountId);
29
+ aLog.debug(`syncFilePath: ${syncFilePath}`);
30
+ const previousGetUpdatesBuf = loadGetUpdatesBuf(syncFilePath);
31
+ let getUpdatesBuf = previousGetUpdatesBuf ?? "";
32
+ if (previousGetUpdatesBuf) {
33
+ log(`[weixin] resuming from previous sync buf (${getUpdatesBuf.length} bytes)`);
34
+ aLog.debug(`Using previous get_updates_buf (${getUpdatesBuf.length} bytes)`);
35
+ }
36
+ else {
37
+ log(`[weixin] no previous sync buf, starting fresh`);
38
+ aLog.info(`No previous get_updates_buf found, starting fresh`);
39
+ }
40
+ const configManager = new WeixinConfigManager({ baseUrl, token }, log);
41
+ let nextTimeoutMs = longPollTimeoutMs ?? DEFAULT_LONG_POLL_TIMEOUT_MS;
42
+ let consecutiveFailures = 0;
43
+ while (!abortSignal?.aborted) {
44
+ try {
45
+ aLog.debug(`getUpdates: get_updates_buf=${getUpdatesBuf.substring(0, 50)}..., timeoutMs=${nextTimeoutMs}`);
46
+ const resp = await getUpdates({
47
+ baseUrl,
48
+ token,
49
+ get_updates_buf: getUpdatesBuf,
50
+ timeoutMs: nextTimeoutMs,
51
+ // Stop/hot-reload should cancel the in-flight long-poll immediately
52
+ // instead of waiting for the server-side long-poll timeout.
53
+ abortSignal,
54
+ });
55
+ aLog.debug(`getUpdates response: ret=${resp.ret}, msgs=${resp.msgs?.length ?? 0}, get_updates_buf_length=${resp.get_updates_buf?.length ?? 0}`);
56
+ if (resp.longpolling_timeout_ms != null && resp.longpolling_timeout_ms > 0) {
57
+ nextTimeoutMs = resp.longpolling_timeout_ms;
58
+ aLog.debug(`Updated next poll timeout: ${nextTimeoutMs}ms`);
59
+ }
60
+ const isApiError = (resp.ret !== undefined && resp.ret !== 0) ||
61
+ (resp.errcode !== undefined && resp.errcode !== 0);
62
+ if (isApiError) {
63
+ const isStaleToken = resp.errcode === STALE_TOKEN_ERRCODE || resp.ret === STALE_TOKEN_ERRCODE;
64
+ if (isStaleToken) {
65
+ pauseSession(accountId);
66
+ const pauseMs = getRemainingPauseMs(accountId);
67
+ aLog.error(`getUpdates: token for ${accountId} is stale, pausing all requests for ${Math.ceil(pauseMs / 60_000)} min`);
68
+ consecutiveFailures = 0;
69
+ await sleep(pauseMs, abortSignal);
70
+ continue;
71
+ }
72
+ consecutiveFailures += 1;
73
+ errLog(`weixin getUpdates failed: ret=${resp.ret} errcode=${resp.errcode} errmsg=${resp.errmsg ?? ""} (${consecutiveFailures}/${MAX_CONSECUTIVE_FAILURES})`);
74
+ aLog.error(`getUpdates failed: ret=${resp.ret} errcode=${resp.errcode} errmsg=${resp.errmsg} response=${redactBody(JSON.stringify(resp))}`);
75
+ if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
76
+ errLog(`weixin getUpdates: ${MAX_CONSECUTIVE_FAILURES} consecutive failures, backing off 30s`);
77
+ aLog.error(`getUpdates: ${MAX_CONSECUTIVE_FAILURES} consecutive failures, backing off 30s`);
78
+ consecutiveFailures = 0;
79
+ await sleep(BACKOFF_DELAY_MS, abortSignal);
80
+ }
81
+ else {
82
+ await sleep(RETRY_DELAY_MS, abortSignal);
83
+ }
84
+ continue;
85
+ }
86
+ consecutiveFailures = 0;
87
+ setStatus?.({ accountId, lastEventAt: Date.now() });
88
+ if (resp.get_updates_buf != null && resp.get_updates_buf !== "") {
89
+ saveGetUpdatesBuf(syncFilePath, resp.get_updates_buf);
90
+ getUpdatesBuf = resp.get_updates_buf;
91
+ aLog.debug(`Saved new get_updates_buf (${getUpdatesBuf.length} bytes)`);
92
+ }
93
+ const list = resp.msgs ?? [];
94
+ for (const full of list) {
95
+ aLog.info(`inbound message: from=${full.from_user_id} types=${full.item_list?.map((i) => i.type).join(",") ?? "none"}`);
96
+ const now = Date.now();
97
+ setStatus?.({ accountId, lastEventAt: now, lastInboundAt: now });
98
+ // allowFrom filtering is delegated to processOneMessage via the framework
99
+ // authorization pipeline (resolveSenderCommandAuthorizationWithRuntime).
100
+ const fromUserId = full.from_user_id ?? "";
101
+ const cachedConfig = await configManager.getForUser(fromUserId, full.context_token);
102
+ await processOneMessage(full, {
103
+ accountId,
104
+ config,
105
+ channelRuntime,
106
+ baseUrl,
107
+ cdnBaseUrl,
108
+ token,
109
+ typingTicket: cachedConfig.typingTicket,
110
+ log: opts.runtime?.log ?? (() => { }),
111
+ errLog,
112
+ });
113
+ }
114
+ }
115
+ catch (err) {
116
+ if (abortSignal?.aborted) {
117
+ aLog.info(`Monitor stopped (aborted)`);
118
+ return;
119
+ }
120
+ consecutiveFailures += 1;
121
+ const classified = classifyFetchError(err);
122
+ errLog(`weixin getUpdates error (${consecutiveFailures}/${MAX_CONSECUTIVE_FAILURES}): ${String(err)} type=${classified.type} description=${classified.description}${classified.code ? ` code=${classified.code}` : ""}`);
123
+ aLog.error(`getUpdates error: ${String(err)}, type=${classified.type} code=${classified.code ?? "none"}, stack=${err.stack}`);
124
+ if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
125
+ errLog(`weixin getUpdates: ${MAX_CONSECUTIVE_FAILURES} consecutive failures, backing off 30s`);
126
+ aLog.error(`getUpdates: ${MAX_CONSECUTIVE_FAILURES} consecutive failures, backing off 30s`);
127
+ consecutiveFailures = 0;
128
+ await sleep(30_000, abortSignal);
129
+ }
130
+ else {
131
+ await sleep(2000, abortSignal);
132
+ }
133
+ }
134
+ }
135
+ aLog.info(`Monitor ended`);
136
+ }
137
+ function sleep(ms, signal) {
138
+ return new Promise((resolve, reject) => {
139
+ const t = setTimeout(resolve, ms);
140
+ signal?.addEventListener("abort", () => {
141
+ clearTimeout(t);
142
+ reject(new Error("aborted"));
143
+ }, { once: true });
144
+ });
145
+ }
146
+ //# sourceMappingURL=monitor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monitor.js","sourceRoot":"","sources":["../../../src/monitor/monitor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACjG,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAClG,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE3C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,MAAM,4BAA4B,GAAG,MAAM,CAAC;AAC5C,MAAM,wBAAwB,GAAG,CAAC,CAAC;AACnC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAChC,MAAM,cAAc,GAAG,KAAK,CAAC;AAsB7B;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,IAAuB;IACjE,MAAM,EACJ,OAAO,EACP,UAAU,EACV,KAAK,EACL,SAAS,EACT,MAAM,EACN,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,SAAS,GACV,GAAG,IAAI,CAAC;IACT,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9D,MAAM,IAAI,GAAW,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;IAEnD,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,GAAG,GACP,kGAAkG,CAAC;QACrG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;IACvB,CAAC;IAED,GAAG,CAAC,2BAA2B,OAAO,aAAa,SAAS,GAAG,CAAC,CAAC;IACjE,IAAI,CAAC,IAAI,CACP,4BAA4B,OAAO,cAAc,iBAAiB,IAAI,4BAA4B,EAAE,CACrG,CAAC;IAEF,MAAM,YAAY,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IACnD,IAAI,CAAC,KAAK,CAAC,iBAAiB,YAAY,EAAE,CAAC,CAAC;IAE5C,MAAM,qBAAqB,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;IAC9D,IAAI,aAAa,GAAG,qBAAqB,IAAI,EAAE,CAAC;IAEhD,IAAI,qBAAqB,EAAE,CAAC;QAC1B,GAAG,CAAC,6CAA6C,aAAa,CAAC,MAAM,SAAS,CAAC,CAAC;QAChF,IAAI,CAAC,KAAK,CAAC,mCAAmC,aAAa,CAAC,MAAM,SAAS,CAAC,CAAC;IAC/E,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,+CAA+C,CAAC,CAAC;QACrD,IAAI,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,aAAa,GAAG,IAAI,mBAAmB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,GAAG,CAAC,CAAC;IAEvE,IAAI,aAAa,GAAG,iBAAiB,IAAI,4BAA4B,CAAC;IACtE,IAAI,mBAAmB,GAAG,CAAC,CAAC;IAE5B,OAAO,CAAC,WAAW,EAAE,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,CACR,+BAA+B,aAAa,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,aAAa,EAAE,CAC/F,CAAC;YACF,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC;gBAC5B,OAAO;gBACP,KAAK;gBACL,eAAe,EAAE,aAAa;gBAC9B,SAAS,EAAE,aAAa;gBACxB,oEAAoE;gBACpE,4DAA4D;gBAC5D,WAAW;aACZ,CAAC,CAAC;YACH,IAAI,CAAC,KAAK,CACR,4BAA4B,IAAI,CAAC,GAAG,UAAU,IAAI,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,4BAA4B,IAAI,CAAC,eAAe,EAAE,MAAM,IAAI,CAAC,EAAE,CACpI,CAAC;YAEF,IAAI,IAAI,CAAC,sBAAsB,IAAI,IAAI,IAAI,IAAI,CAAC,sBAAsB,GAAG,CAAC,EAAE,CAAC;gBAC3E,aAAa,GAAG,IAAI,CAAC,sBAAsB,CAAC;gBAC5C,IAAI,CAAC,KAAK,CAAC,8BAA8B,aAAa,IAAI,CAAC,CAAC;YAC9D,CAAC;YACD,MAAM,UAAU,GACd,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;gBAC1C,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC;YACrD,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,YAAY,GAChB,IAAI,CAAC,OAAO,KAAK,mBAAmB,IAAI,IAAI,CAAC,GAAG,KAAK,mBAAmB,CAAC;gBAE3E,IAAI,YAAY,EAAE,CAAC;oBACjB,YAAY,CAAC,SAAS,CAAC,CAAC;oBACxB,MAAM,OAAO,GAAG,mBAAmB,CAAC,SAAS,CAAC,CAAC;oBAC/C,IAAI,CAAC,KAAK,CACR,yBAAyB,SAAS,uCAAuC,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,CAC3G,CAAC;oBACF,mBAAmB,GAAG,CAAC,CAAC;oBACxB,MAAM,KAAK,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;oBAClC,SAAS;gBACX,CAAC;gBAED,mBAAmB,IAAI,CAAC,CAAC;gBACzB,MAAM,CACJ,iCAAiC,IAAI,CAAC,GAAG,YAAY,IAAI,CAAC,OAAO,WAAW,IAAI,CAAC,MAAM,IAAI,EAAE,KAAK,mBAAmB,IAAI,wBAAwB,GAAG,CACrJ,CAAC;gBACF,IAAI,CAAC,KAAK,CACR,0BAA0B,IAAI,CAAC,GAAG,YAAY,IAAI,CAAC,OAAO,WAAW,IAAI,CAAC,MAAM,aAAa,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,EAAE,CAChI,CAAC;gBACF,IAAI,mBAAmB,IAAI,wBAAwB,EAAE,CAAC;oBACpD,MAAM,CACJ,sBAAsB,wBAAwB,wCAAwC,CACvF,CAAC;oBACF,IAAI,CAAC,KAAK,CACR,eAAe,wBAAwB,wCAAwC,CAChF,CAAC;oBACF,mBAAmB,GAAG,CAAC,CAAC;oBACxB,MAAM,KAAK,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;gBAC7C,CAAC;qBAAM,CAAC;oBACN,MAAM,KAAK,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;gBAC3C,CAAC;gBACD,SAAS;YACX,CAAC;YACD,mBAAmB,GAAG,CAAC,CAAC;YACxB,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACpD,IAAI,IAAI,CAAC,eAAe,IAAI,IAAI,IAAI,IAAI,CAAC,eAAe,KAAK,EAAE,EAAE,CAAC;gBAChE,iBAAiB,CAAC,YAAY,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC;gBACtD,aAAa,GAAG,IAAI,CAAC,eAAe,CAAC;gBACrC,IAAI,CAAC,KAAK,CAAC,8BAA8B,aAAa,CAAC,MAAM,SAAS,CAAC,CAAC;YAC1E,CAAC;YACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;YAC7B,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;gBACxB,IAAI,CAAC,IAAI,CACP,yBAAyB,IAAI,CAAC,YAAY,UAAU,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,MAAM,EAAE,CAC7G,CAAC;gBAEF,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBACvB,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,CAAC;gBAEjE,0EAA0E;gBAC1E,yEAAyE;gBAEzE,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC;gBAC3C,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC,UAAU,CAAC,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;gBAEpF,MAAM,iBAAiB,CAAC,IAAI,EAAE;oBAC5B,SAAS;oBACT,MAAM;oBACN,cAAc;oBACd,OAAO;oBACP,UAAU;oBACV,KAAK;oBACL,YAAY,EAAE,YAAY,CAAC,YAAY;oBACvC,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC;oBACpC,MAAM;iBACP,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,WAAW,EAAE,OAAO,EAAE,CAAC;gBACzB,IAAI,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;gBACvC,OAAO;YACT,CAAC;YACD,mBAAmB,IAAI,CAAC,CAAC;YACzB,MAAM,UAAU,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;YAC3C,MAAM,CACJ,4BAA4B,mBAAmB,IAAI,wBAAwB,MAAM,MAAM,CAAC,GAAG,CAAC,SAAS,UAAU,CAAC,IAAI,gBAAgB,UAAU,CAAC,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACjN,CAAC;YACF,IAAI,CAAC,KAAK,CAAC,qBAAqB,MAAM,CAAC,GAAG,CAAC,UAAU,UAAU,CAAC,IAAI,SAAS,UAAU,CAAC,IAAI,IAAI,MAAM,WAAY,GAAa,CAAC,KAAK,EAAE,CAAC,CAAC;YACzI,IAAI,mBAAmB,IAAI,wBAAwB,EAAE,CAAC;gBACpD,MAAM,CACJ,sBAAsB,wBAAwB,wCAAwC,CACvF,CAAC;gBACF,IAAI,CAAC,KAAK,CACR,eAAe,wBAAwB,wCAAwC,CAChF,CAAC;gBACF,mBAAmB,GAAG,CAAC,CAAC;gBACxB,MAAM,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;YACnC,CAAC;iBAAM,CAAC;gBACN,MAAM,KAAK,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;IACH,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,KAAK,CAAC,EAAU,EAAE,MAAoB;IAC7C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,CAAC,GAAG,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAClC,MAAM,EAAE,gBAAgB,CACtB,OAAO,EACP,GAAG,EAAE;YACH,YAAY,CAAC,CAAC,CAAC,CAAC;YAChB,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;QAC/B,CAAC,EACD,EAAE,IAAI,EAAE,IAAI,EAAE,CACf,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,9 @@
1
+ import os from "node:os";
2
+ import path from "node:path";
3
+ /** Resolve the OpenClaw state directory (mirrors core logic in src/infra). */
4
+ export function resolveStateDir() {
5
+ return (process.env.OPENCLAW_STATE_DIR?.trim() ||
6
+ process.env.CLAWDBOT_STATE_DIR?.trim() ||
7
+ path.join(os.homedir(), ".openclaw"));
8
+ }
9
+ //# sourceMappingURL=state-dir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-dir.js","sourceRoot":"","sources":["../../../src/storage/state-dir.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,8EAA8E;AAC9E,MAAM,UAAU,eAAe;IAC7B,OAAO,CACL,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE;QACtC,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE;QACtC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CACrC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,64 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { deriveRawAccountId } from "../auth/accounts.js";
4
+ import { resolveStateDir } from "./state-dir.js";
5
+ function resolveAccountsDir() {
6
+ return path.join(resolveStateDir(), "openclaw-weixin", "accounts");
7
+ }
8
+ /**
9
+ * Path to the persistent get_updates_buf file for an account.
10
+ * Stored alongside account data: ~/.openclaw/openclaw-weixin/accounts/{accountId}.sync.json
11
+ */
12
+ export function getSyncBufFilePath(accountId) {
13
+ return path.join(resolveAccountsDir(), `${accountId}.sync.json`);
14
+ }
15
+ /** Legacy single-account syncbuf (pre multi-account): `.openclaw-weixin-sync/default.json`. */
16
+ function getLegacySyncBufDefaultJsonPath() {
17
+ return path.join(resolveStateDir(), "agents", "default", "sessions", ".openclaw-weixin-sync", "default.json");
18
+ }
19
+ function readSyncBufFile(filePath) {
20
+ try {
21
+ const raw = fs.readFileSync(filePath, "utf-8");
22
+ const data = JSON.parse(raw);
23
+ if (typeof data.get_updates_buf === "string") {
24
+ return data.get_updates_buf;
25
+ }
26
+ }
27
+ catch {
28
+ // file not found or invalid
29
+ }
30
+ return undefined;
31
+ }
32
+ /**
33
+ * Load persisted get_updates_buf.
34
+ * Falls back in order:
35
+ * 1. Primary path (normalized accountId, new installs)
36
+ * 2. Compat path (raw accountId derived from pattern, old installs)
37
+ * 3. Legacy single-account path (very old installs without multi-account support)
38
+ */
39
+ export function loadGetUpdatesBuf(filePath) {
40
+ const value = readSyncBufFile(filePath);
41
+ if (value !== undefined)
42
+ return value;
43
+ // Compat: if given path uses a normalized accountId (e.g. "b0f5860fdecb-im-bot.sync.json"),
44
+ // also try the old raw-ID filename (e.g. "b0f5860fdecb@im.bot.sync.json").
45
+ const accountId = path.basename(filePath, ".sync.json");
46
+ const rawId = deriveRawAccountId(accountId);
47
+ if (rawId) {
48
+ const compatPath = path.join(resolveAccountsDir(), `${rawId}.sync.json`);
49
+ const compatValue = readSyncBufFile(compatPath);
50
+ if (compatValue !== undefined)
51
+ return compatValue;
52
+ }
53
+ // Legacy fallback: old single-account installs stored syncbuf without accountId.
54
+ return readSyncBufFile(getLegacySyncBufDefaultJsonPath());
55
+ }
56
+ /**
57
+ * Persist get_updates_buf. Creates parent dir if needed.
58
+ */
59
+ export function saveGetUpdatesBuf(filePath, getUpdatesBuf) {
60
+ const dir = path.dirname(filePath);
61
+ fs.mkdirSync(dir, { recursive: true });
62
+ fs.writeFileSync(filePath, JSON.stringify({ get_updates_buf: getUpdatesBuf }, null, 0), "utf-8");
63
+ }
64
+ //# sourceMappingURL=sync-buf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-buf.js","sourceRoot":"","sources":["../../../src/storage/sync-buf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,SAAS,kBAAkB;IACzB,OAAO,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,iBAAiB,EAAE,UAAU,CAAC,CAAC;AACrE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,OAAO,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,GAAG,SAAS,YAAY,CAAC,CAAC;AACnE,CAAC;AAED,+FAA+F;AAC/F,SAAS,+BAA+B;IACtC,OAAO,IAAI,CAAC,IAAI,CACd,eAAe,EAAE,EACjB,QAAQ,EACR,SAAS,EACT,UAAU,EACV,uBAAuB,EACvB,cAAc,CACf,CAAC;AACJ,CAAC;AAMD,SAAS,eAAe,CAAC,QAAgB;IACvC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAiC,CAAC;QAC7D,IAAI,OAAO,IAAI,CAAC,eAAe,KAAK,QAAQ,EAAE,CAAC;YAC7C,OAAO,IAAI,CAAC,eAAe,CAAC;QAC9B,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,4BAA4B;IAC9B,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,MAAM,KAAK,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IACxC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAEtC,4FAA4F;IAC5F,2EAA2E;IAC3E,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IACxD,MAAM,KAAK,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC;IAC5C,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAAE,GAAG,KAAK,YAAY,CAAC,CAAC;QACzE,MAAM,WAAW,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;QAChD,IAAI,WAAW,KAAK,SAAS;YAAE,OAAO,WAAW,CAAC;IACpD,CAAC;IAED,iFAAiF;IACjF,OAAO,eAAe,CAAC,+BAA+B,EAAE,CAAC,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,aAAqB;IACvE,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,eAAe,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACnG,CAAC"}