@clowder-ai/connector-wecom-agent 0.0.0-stage → 0.1.0-alpha.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 (58) hide show
  1. package/README.en.md +56 -0
  2. package/README.md +24 -2
  3. package/assets/icon.svg +6 -0
  4. package/dist/WeComAgentAdapter.d.ts +149 -0
  5. package/dist/WeComAgentAdapter.d.ts.map +1 -0
  6. package/dist/WeComAgentAdapter.js +525 -0
  7. package/dist/WeComAgentAdapter.js.map +1 -0
  8. package/dist/collect-media.d.ts +12 -0
  9. package/dist/collect-media.d.ts.map +1 -0
  10. package/dist/collect-media.js +27 -0
  11. package/dist/collect-media.js.map +1 -0
  12. package/dist/command-ingress.d.ts +10 -0
  13. package/dist/command-ingress.d.ts.map +1 -0
  14. package/dist/command-ingress.js +13 -0
  15. package/dist/command-ingress.js.map +1 -0
  16. package/dist/inbound-download.d.ts +13 -0
  17. package/dist/inbound-download.d.ts.map +1 -0
  18. package/dist/inbound-download.js +70 -0
  19. package/dist/inbound-download.js.map +1 -0
  20. package/dist/inbound-media-source.d.ts +25 -0
  21. package/dist/inbound-media-source.d.ts.map +1 -0
  22. package/dist/inbound-media-source.js +111 -0
  23. package/dist/inbound-media-source.js.map +1 -0
  24. package/dist/index.d.ts +4 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +2 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/media-notice.d.ts +6 -0
  29. package/dist/media-notice.d.ts.map +1 -0
  30. package/dist/media-notice.js +50 -0
  31. package/dist/media-notice.js.map +1 -0
  32. package/dist/plugin-entrypoint.d.ts +7 -0
  33. package/dist/plugin-entrypoint.d.ts.map +1 -0
  34. package/dist/plugin-entrypoint.js +292 -0
  35. package/dist/plugin-entrypoint.js.map +1 -0
  36. package/dist/reply-sender-map.d.ts +10 -0
  37. package/dist/reply-sender-map.d.ts.map +1 -0
  38. package/dist/reply-sender-map.js +123 -0
  39. package/dist/reply-sender-map.js.map +1 -0
  40. package/dist/rich-block-plaintext.d.ts +5 -0
  41. package/dist/rich-block-plaintext.d.ts.map +1 -0
  42. package/dist/rich-block-plaintext.js +45 -0
  43. package/dist/rich-block-plaintext.js.map +1 -0
  44. package/dist/runtime.d.ts +65 -0
  45. package/dist/runtime.d.ts.map +1 -0
  46. package/dist/runtime.js +84 -0
  47. package/dist/runtime.js.map +1 -0
  48. package/dist/thread-mappings.d.ts +46 -0
  49. package/dist/thread-mappings.d.ts.map +1 -0
  50. package/dist/thread-mappings.js +62 -0
  51. package/dist/thread-mappings.js.map +1 -0
  52. package/dist/types.d.ts +15 -0
  53. package/dist/types.d.ts.map +1 -0
  54. package/dist/types.js +2 -0
  55. package/dist/types.js.map +1 -0
  56. package/npm-shrinkwrap.json +215 -0
  57. package/package.json +55 -4
  58. package/plugin.yaml +83 -0
@@ -0,0 +1,525 @@
1
+ /**
2
+ * WeCom Agent (企微自建应用) Adapter
3
+ * Inbound: HTTP callback with AES-256-CBC encrypted XML → parse text/image/voice/video/file
4
+ * Outbound: message/send API (text/markdown/textcard) — final-only, no streaming
5
+ *
6
+ * F132 DingTalk + WeCom Chat Gateway — Phase C
7
+ */
8
+ import crypto from 'node:crypto';
9
+ import { collectProviderMedia } from './collect-media.js';
10
+ import { fetchBoundedInboundMedia } from './inbound-download.js';
11
+ import { XMLParser } from 'fast-xml-parser';
12
+ // ── Constants ──
13
+ const WECOM_API_BASE = 'https://qyapi.weixin.qq.com/cgi-bin';
14
+ /** WeCom text message body limit in bytes */
15
+ const TEXT_BODY_LIMIT_BYTES = 2048;
16
+ /** Access token cache TTL: refresh 5 min before expiry (7200s → use 7080s) */
17
+ const TOKEN_REFRESH_MARGIN_MS = 120_000;
18
+ // ── Crypto helpers (AC-C2) ──
19
+ /**
20
+ * Derive AES key and IV from EncodingAESKey.
21
+ * EncodingAESKey is 43 chars; append '=' for valid Base64 → 32-byte key.
22
+ * IV = first 16 bytes of key.
23
+ */
24
+ function deriveAesKeyIv(encodingAesKey) {
25
+ const key = Buffer.from(encodingAesKey + '=', 'base64');
26
+ if (key.length !== 32) {
27
+ throw new Error(`[WeComAgentAdapter] Invalid EncodingAESKey: expected 32 bytes, got ${key.length}`);
28
+ }
29
+ return { key, iv: key.subarray(0, 16) };
30
+ }
31
+ /**
32
+ * Compute SHA1 signature for WeCom callback verification.
33
+ * sig = sha1(sort([token, timestamp, nonce, encrypt]).join(''))
34
+ */
35
+ export function computeSignature(token, timestamp, nonce, encrypt) {
36
+ const params = [token, timestamp, nonce, encrypt].sort();
37
+ return crypto.createHash('sha1').update(params.join('')).digest('hex');
38
+ }
39
+ /**
40
+ * Decrypt an AES-256-CBC encrypted WeCom message.
41
+ * Returns { message, corpId } after PKCS7 unpadding.
42
+ *
43
+ * Layout after decryption:
44
+ * [16 bytes random] [4 bytes msg_len BE] [msg_len bytes XML] [corpId bytes]
45
+ */
46
+ export function decryptMessage(encryptedBase64, aesKey, iv) {
47
+ const decipher = crypto.createDecipheriv('aes-256-cbc', aesKey, iv);
48
+ decipher.setAutoPadding(false);
49
+ const decrypted = Buffer.concat([decipher.update(encryptedBase64, 'base64'), decipher.final()]);
50
+ // PKCS7 unpadding
51
+ const padLen = decrypted[decrypted.length - 1];
52
+ const raw = decrypted.subarray(0, decrypted.length - padLen);
53
+ // Skip 16-byte random prefix
54
+ const msgLenBuf = raw.subarray(16, 20);
55
+ const msgLen = msgLenBuf.readUInt32BE(0);
56
+ const message = raw.subarray(20, 20 + msgLen).toString('utf-8');
57
+ const receivedCorpId = raw.subarray(20 + msgLen).toString('utf-8');
58
+ return { message, receivedCorpId };
59
+ }
60
+ /**
61
+ * Encrypt a plaintext message for WeCom callback response.
62
+ * Used for echostr challenge response.
63
+ */
64
+ export function encryptMessage(plaintext, aesKey, iv, corpId) {
65
+ const randomBytes = crypto.randomBytes(16);
66
+ const msgBuf = Buffer.from(plaintext, 'utf-8');
67
+ const corpIdBuf = Buffer.from(corpId, 'utf-8');
68
+ const msgLenBuf = Buffer.alloc(4);
69
+ msgLenBuf.writeUInt32BE(msgBuf.length, 0);
70
+ const payload = Buffer.concat([randomBytes, msgLenBuf, msgBuf, corpIdBuf]);
71
+ // PKCS7 padding to AES block size (16)
72
+ const blockSize = 16;
73
+ const padLen = blockSize - (payload.length % blockSize);
74
+ const padding = Buffer.alloc(padLen, padLen);
75
+ const padded = Buffer.concat([payload, padding]);
76
+ const cipher = crypto.createCipheriv('aes-256-cbc', aesKey, iv);
77
+ cipher.setAutoPadding(false);
78
+ return Buffer.concat([cipher.update(padded), cipher.final()]).toString('base64');
79
+ }
80
+ // ── XML Parser (AC-C3) ──
81
+ const xmlParser = new XMLParser({
82
+ ignoreAttributes: false,
83
+ trimValues: true,
84
+ });
85
+ // ── Adapter ──
86
+ export class WeComAgentAdapter {
87
+ connectorId = 'wecom-agent';
88
+ log;
89
+ corpId;
90
+ agentId;
91
+ agentSecret;
92
+ token;
93
+ aesKey;
94
+ iv;
95
+ // Access token cache
96
+ accessToken = '';
97
+ tokenExpiresAt = 0;
98
+ // DI injection points
99
+ fetchFn = globalThis.fetch;
100
+ constructor(log, options) {
101
+ this.log = log;
102
+ this.corpId = options.corpId;
103
+ this.agentId = options.agentId;
104
+ this.agentSecret = options.agentSecret;
105
+ this.token = options.token;
106
+ const { key, iv } = deriveAesKeyIv(options.encodingAesKey);
107
+ this.aesKey = key;
108
+ this.iv = iv;
109
+ }
110
+ // ── Callback Verification (AC-C1) ──
111
+ /**
112
+ * Handle GET echostr challenge for URL verification.
113
+ * WeCom sends: ?msg_signature=X&timestamp=T&nonce=N&echostr=E
114
+ * We decrypt echostr and return plaintext if signature matches.
115
+ */
116
+ verifyCallback(query) {
117
+ const { msg_signature, timestamp, nonce, echostr } = query;
118
+ const expectedSig = computeSignature(this.token, timestamp, nonce, echostr);
119
+ if (expectedSig !== msg_signature) {
120
+ this.log.warn({ expected: expectedSig, got: msg_signature }, '[WeComAgentAdapter] echostr signature mismatch');
121
+ return null;
122
+ }
123
+ try {
124
+ const { message, receivedCorpId } = decryptMessage(echostr, this.aesKey, this.iv);
125
+ if (receivedCorpId !== this.corpId) {
126
+ this.log.warn({ expected: this.corpId, got: receivedCorpId }, '[WeComAgentAdapter] echostr corpId mismatch');
127
+ return null;
128
+ }
129
+ return message;
130
+ }
131
+ catch (err) {
132
+ this.log.error({ err }, '[WeComAgentAdapter] echostr decryption failed');
133
+ return null;
134
+ }
135
+ }
136
+ // ── Inbound: Parse encrypted XML (AC-C2, AC-C3) ──
137
+ /**
138
+ * Verify signature and decrypt an incoming POST body (encrypted XML).
139
+ * Returns the decrypted XML string, or null if verification fails.
140
+ */
141
+ decryptInbound(body, query) {
142
+ // Parse outer XML to extract <Encrypt>
143
+ const outer = xmlParser.parse(body);
144
+ const encrypt = outer?.xml?.Encrypt ?? outer?.Encrypt ?? null;
145
+ if (!encrypt) {
146
+ this.log.warn('[WeComAgentAdapter] No <Encrypt> in POST body');
147
+ return null;
148
+ }
149
+ // Verify signature
150
+ const expectedSig = computeSignature(this.token, query.timestamp, query.nonce, encrypt);
151
+ if (expectedSig !== query.msg_signature) {
152
+ this.log.warn({ expected: expectedSig, got: query.msg_signature }, '[WeComAgentAdapter] POST signature mismatch');
153
+ return null;
154
+ }
155
+ // Decrypt
156
+ try {
157
+ const { message, receivedCorpId } = decryptMessage(encrypt, this.aesKey, this.iv);
158
+ if (receivedCorpId !== this.corpId) {
159
+ this.log.warn({ expected: this.corpId, got: receivedCorpId }, '[WeComAgentAdapter] POST corpId mismatch');
160
+ return null;
161
+ }
162
+ return message;
163
+ }
164
+ catch (err) {
165
+ this.log.error({ err }, '[WeComAgentAdapter] POST decryption failed');
166
+ return null;
167
+ }
168
+ }
169
+ /**
170
+ * Parse decrypted XML into a normalized inbound message.
171
+ * Supports text, image, voice, video, file (location is logged and skipped).
172
+ */
173
+ parseEvent(decryptedXml) {
174
+ const parsed = xmlParser.parse(decryptedXml);
175
+ const root = parsed?.xml ?? parsed;
176
+ if (!root)
177
+ return null;
178
+ const msgType = root.MsgType;
179
+ const fromUser = root.FromUserName;
180
+ if (!msgType || !fromUser)
181
+ return null;
182
+ if (msgType === 'event') {
183
+ this.log.debug({ eventType: root.Event }, '[WeComAgentAdapter] Event message skipped');
184
+ return null;
185
+ }
186
+ // Every supported ordinary message has a provider MsgId. A local clock
187
+ // fallback would turn a malformed redelivery into a new Host source.
188
+ const msgId = root.MsgId != null ? String(root.MsgId) : undefined;
189
+ if (msgId === undefined || msgId.trim() === '') {
190
+ this.log.warn({ type: msgType }, '[WeComAgentAdapter] Ordinary message missing MsgId');
191
+ return null;
192
+ }
193
+ const base = {
194
+ chatId: fromUser,
195
+ messageId: msgId,
196
+ senderId: fromUser,
197
+ };
198
+ switch (msgType) {
199
+ case 'text': {
200
+ const content = root.Content;
201
+ if (!content)
202
+ return null;
203
+ return { ...base, text: content.trim() };
204
+ }
205
+ case 'image': {
206
+ const mediaId = root.MediaId;
207
+ return {
208
+ ...base,
209
+ text: '[图片]',
210
+ attachments: mediaId ? [{ type: 'image', mediaId }] : undefined,
211
+ };
212
+ }
213
+ case 'voice': {
214
+ const mediaId = root.MediaId;
215
+ // WeCom voice may include Recognition (speech-to-text)
216
+ const recognition = root.Recognition;
217
+ return {
218
+ ...base,
219
+ text: recognition || '[语音]',
220
+ attachments: mediaId ? [{ type: 'audio', mediaId }] : undefined,
221
+ };
222
+ }
223
+ case 'video':
224
+ case 'shortvideo': {
225
+ const mediaId = root.MediaId;
226
+ return {
227
+ ...base,
228
+ text: '[视频]',
229
+ attachments: mediaId ? [{ type: 'video', mediaId }] : undefined,
230
+ };
231
+ }
232
+ case 'file': {
233
+ const mediaId = root.MediaId;
234
+ const title = root.Title;
235
+ return {
236
+ ...base,
237
+ text: `[文件] ${title ?? ''}`.trim(),
238
+ attachments: mediaId
239
+ ? [
240
+ {
241
+ type: 'file',
242
+ mediaId,
243
+ ...(title ? { fileName: title } : {}),
244
+ },
245
+ ]
246
+ : undefined,
247
+ };
248
+ }
249
+ case 'location': {
250
+ const label = root.Label ?? `${root.Location_X ?? ''},${root.Location_Y ?? ''}`;
251
+ return { ...base, text: `[位置] ${label}` };
252
+ }
253
+ default:
254
+ this.log.debug({ msgType }, '[WeComAgentAdapter] Unsupported message type');
255
+ return null;
256
+ }
257
+ }
258
+ // ── Access Token Management ──
259
+ /**
260
+ * Get a valid access_token, refreshing if expired.
261
+ * WeCom access_token has 7200s (2h) TTL.
262
+ */
263
+ async getAccessToken() {
264
+ if (this.accessToken && Date.now() < this.tokenExpiresAt) {
265
+ return this.accessToken;
266
+ }
267
+ const url = `${WECOM_API_BASE}/gettoken?corpid=${encodeURIComponent(this.corpId)}&corpsecret=${encodeURIComponent(this.agentSecret)}`;
268
+ const res = await this.fetchFn(url, {
269
+ signal: AbortSignal.timeout(10_000),
270
+ });
271
+ if (!res.ok) {
272
+ throw new Error(`[WeComAgentAdapter] gettoken HTTP ${res.status}: ${res.statusText}`);
273
+ }
274
+ const data = (await res.json());
275
+ if (data.errcode && data.errcode !== 0) {
276
+ throw new Error(`[WeComAgentAdapter] gettoken errcode ${data.errcode}: ${data.errmsg ?? 'unknown'}`);
277
+ }
278
+ if (!data.access_token) {
279
+ throw new Error('[WeComAgentAdapter] gettoken: no access_token in response');
280
+ }
281
+ this.accessToken = data.access_token;
282
+ const expiresIn = data.expires_in ?? 7200;
283
+ this.tokenExpiresAt = Date.now() + expiresIn * 1000 - TOKEN_REFRESH_MARGIN_MS;
284
+ this.log.info({ expiresIn }, '[WeComAgentAdapter] Access token refreshed');
285
+ return this.accessToken;
286
+ }
287
+ /** Force token refresh on next call (e.g., after 401/40001 error). */
288
+ invalidateToken() {
289
+ this.accessToken = '';
290
+ this.tokenExpiresAt = 0;
291
+ }
292
+ // ── Outbound: Send Messages (AC-C4) ──
293
+ /**
294
+ * Send a text reply via message/send API.
295
+ * Long messages are chunked at TEXT_BODY_LIMIT_BYTES (2048 bytes).
296
+ * AC-C6: final-only mode, long reply chunking.
297
+ */
298
+ async sendReply(externalChatId, content, _metadata) {
299
+ const chunks = this.chunkMessage(content, TEXT_BODY_LIMIT_BYTES);
300
+ for (const chunk of chunks) {
301
+ await this.messageSend(externalChatId, {
302
+ msgtype: 'text',
303
+ agentid: Number(this.agentId),
304
+ text: { content: chunk },
305
+ });
306
+ }
307
+ }
308
+ /**
309
+ * Send a formatted reply as markdown (body) or textcard (with link).
310
+ * AC-C4: markdown + textcard + 图文卡片
311
+ */
312
+ async sendFormattedReply(externalChatId, envelope, _metadata) {
313
+ const isCallback = envelope.origin === 'callback';
314
+ const headerTitle = isCallback ? `📨 ${envelope.header} · 传话` : envelope.header;
315
+ // If we have a deep link URL, use textcard format
316
+ if (envelope.footer?.includes('http')) {
317
+ // Extract URL from footer
318
+ const urlMatch = envelope.footer.match(/(https?:\/\/[^\s)]+)/);
319
+ const url = urlMatch ? urlMatch[1] : '';
320
+ await this.messageSend(externalChatId, {
321
+ msgtype: 'textcard',
322
+ agentid: Number(this.agentId),
323
+ textcard: {
324
+ title: headerTitle,
325
+ description: envelope.body.slice(0, 512),
326
+ url,
327
+ btntxt: '查看详情',
328
+ },
329
+ });
330
+ return;
331
+ }
332
+ // Default: markdown format
333
+ let mdContent = `**${headerTitle}**\n\n`;
334
+ if (envelope.subtitle) {
335
+ mdContent += `**${envelope.subtitle}**\n\n`;
336
+ }
337
+ mdContent += envelope.body;
338
+ if (envelope.footer) {
339
+ mdContent += `\n\n---\n${envelope.footer}`;
340
+ }
341
+ const chunks = this.chunkMessage(mdContent, TEXT_BODY_LIMIT_BYTES);
342
+ for (const chunk of chunks) {
343
+ await this.messageSend(externalChatId, {
344
+ msgtype: 'markdown',
345
+ agentid: Number(this.agentId),
346
+ markdown: { content: chunk },
347
+ });
348
+ }
349
+ }
350
+ // ── Media (AC-C5) ──
351
+ /**
352
+ * Send a media message (image/file/audio) via temporary material upload.
353
+ * AC-C5: 临时素材 API 收发
354
+ */
355
+ async sendMedia(externalChatId, payload) {
356
+ // Map 'audio' → 'voice' for WeCom API
357
+ const wecomMediaType = payload.type === 'audio' ? 'voice' : payload.type;
358
+ const fileBuffer = await collectProviderMedia(payload.type, payload.content);
359
+ const fileName = payload.fileName ?? `media.${payload.type === 'audio' ? 'amr' : payload.type === 'image' ? 'png' : 'bin'}`;
360
+ const mediaId = await this.uploadMedia(fileBuffer, wecomMediaType, fileName);
361
+ if (!mediaId)
362
+ throw new Error('WeCom agent media upload returned no media id');
363
+ await this.messageSend(externalChatId, {
364
+ msgtype: wecomMediaType,
365
+ agentid: Number(this.agentId),
366
+ [wecomMediaType]: { media_id: mediaId },
367
+ });
368
+ }
369
+ /**
370
+ * Download a media file by media_id via /media/get API.
371
+ * AC-C5: inbound media download
372
+ */
373
+ async downloadMedia(mediaId) {
374
+ const token = await this.getAccessToken();
375
+ const url = `${WECOM_API_BASE}/media/get?access_token=${encodeURIComponent(token)}&media_id=${encodeURIComponent(mediaId)}`;
376
+ const { response: res, bytes } = await fetchBoundedInboundMedia(this.fetchFn, url);
377
+ if (!res.ok) {
378
+ throw new Error(`[WeComAgentAdapter] media/get HTTP ${res.status}: ${res.statusText}`);
379
+ }
380
+ return bytes;
381
+ }
382
+ // ── Private: API Calls ──
383
+ /**
384
+ * Upload a temporary material via /media/upload.
385
+ * Returns media_id on success, null on failure.
386
+ */
387
+ async uploadMedia(fileBuffer, mediaType, filename) {
388
+ try {
389
+ const token = await this.getAccessToken();
390
+ const url = `${WECOM_API_BASE}/media/upload?access_token=${encodeURIComponent(token)}&type=${encodeURIComponent(mediaType)}`;
391
+ // Build multipart form data
392
+ const boundary = `----WeComAgent${Date.now()}`;
393
+ const header = Buffer.from(`--${boundary}\r\nContent-Disposition: form-data; name="media"; filename="${filename}"\r\nContent-Type: application/octet-stream\r\n\r\n`);
394
+ const footer = Buffer.from(`\r\n--${boundary}--\r\n`);
395
+ const body = Buffer.concat([header, fileBuffer, footer]);
396
+ const res = await this.fetchFn(url, {
397
+ method: 'POST',
398
+ headers: {
399
+ 'Content-Type': `multipart/form-data; boundary=${boundary}`,
400
+ },
401
+ body,
402
+ signal: AbortSignal.timeout(30_000),
403
+ });
404
+ if (!res.ok) {
405
+ this.log.warn({ status: res.status }, '[WeComAgentAdapter] media/upload HTTP error');
406
+ return null;
407
+ }
408
+ const data = (await res.json());
409
+ if (data.errcode && data.errcode !== 0) {
410
+ this.log.warn({ errcode: data.errcode, errmsg: data.errmsg }, '[WeComAgentAdapter] media/upload errcode');
411
+ return null;
412
+ }
413
+ return data.media_id ?? null;
414
+ }
415
+ catch (err) {
416
+ this.log.warn({ err, mediaType, filename }, '[WeComAgentAdapter] uploadMedia failed');
417
+ return null;
418
+ }
419
+ }
420
+ /**
421
+ * Send a message via /message/send API.
422
+ * Handles token refresh on 40001/42001 errors.
423
+ */
424
+ async messageSend(toUser, body) {
425
+ const token = await this.getAccessToken();
426
+ const url = `${WECOM_API_BASE}/message/send?access_token=${encodeURIComponent(token)}`;
427
+ const payload = {
428
+ touser: toUser,
429
+ ...body,
430
+ };
431
+ const res = await this.fetchFn(url, {
432
+ method: 'POST',
433
+ headers: { 'Content-Type': 'application/json' },
434
+ body: JSON.stringify(payload),
435
+ signal: AbortSignal.timeout(10_000),
436
+ });
437
+ if (!res.ok) {
438
+ throw new Error(`[WeComAgentAdapter] message/send HTTP ${res.status}: ${res.statusText}`);
439
+ }
440
+ const data = (await res.json());
441
+ // Token expired — refresh and retry once
442
+ if (data.errcode === 40001 || data.errcode === 42001) {
443
+ this.log.warn({ errcode: data.errcode }, '[WeComAgentAdapter] Token expired, refreshing and retrying');
444
+ this.invalidateToken();
445
+ const newToken = await this.getAccessToken();
446
+ const retryUrl = `${WECOM_API_BASE}/message/send?access_token=${encodeURIComponent(newToken)}`;
447
+ const retryRes = await this.fetchFn(retryUrl, {
448
+ method: 'POST',
449
+ headers: { 'Content-Type': 'application/json' },
450
+ body: JSON.stringify(payload),
451
+ signal: AbortSignal.timeout(10_000),
452
+ });
453
+ if (!retryRes.ok) {
454
+ throw new Error(`[WeComAgentAdapter] message/send retry HTTP ${retryRes.status}`);
455
+ }
456
+ const retryData = (await retryRes.json());
457
+ if (retryData.errcode && retryData.errcode !== 0) {
458
+ throw new Error(`[WeComAgentAdapter] message/send retry errcode ${retryData.errcode}: ${retryData.errmsg ?? 'unknown'}`);
459
+ }
460
+ return;
461
+ }
462
+ if (data.errcode && data.errcode !== 0) {
463
+ throw new Error(`[WeComAgentAdapter] message/send errcode ${data.errcode}: ${data.errmsg ?? 'unknown'}`);
464
+ }
465
+ }
466
+ // ── Helpers ──
467
+ /**
468
+ * Split text into chunks respecting byte limit, breaking at newlines/spaces.
469
+ * AC-C6: long reply chunking at 2048 bytes.
470
+ */
471
+ chunkMessage(text, maxBytes) {
472
+ const totalBytes = Buffer.byteLength(text, 'utf-8');
473
+ if (totalBytes <= maxBytes)
474
+ return [text];
475
+ const chunks = [];
476
+ let remaining = text;
477
+ while (remaining.length > 0) {
478
+ if (Buffer.byteLength(remaining, 'utf-8') <= maxBytes) {
479
+ chunks.push(remaining);
480
+ break;
481
+ }
482
+ // Binary search for the max char index that fits in maxBytes
483
+ let lo = 0;
484
+ let hi = remaining.length;
485
+ while (lo < hi) {
486
+ const mid = (lo + hi + 1) >> 1;
487
+ if (Buffer.byteLength(remaining.slice(0, mid), 'utf-8') <= maxBytes) {
488
+ lo = mid;
489
+ }
490
+ else {
491
+ hi = mid - 1;
492
+ }
493
+ }
494
+ // Try to break at newline or space
495
+ let breakAt = remaining.lastIndexOf('\n', lo);
496
+ if (breakAt <= 0)
497
+ breakAt = remaining.lastIndexOf(' ', lo);
498
+ if (breakAt <= 0)
499
+ breakAt = lo;
500
+ if (breakAt > 0 &&
501
+ /[\uD800-\uDBFF]/u.test(remaining[breakAt - 1] ?? '') &&
502
+ /[\uDC00-\uDFFF]/u.test(remaining[breakAt] ?? '')) {
503
+ breakAt--;
504
+ }
505
+ chunks.push(remaining.slice(0, breakAt));
506
+ remaining = remaining.slice(breakAt).trimStart();
507
+ }
508
+ return chunks;
509
+ }
510
+ // ── Test Helpers ──
511
+ /** @internal */
512
+ _injectFetch(fn) {
513
+ this.fetchFn = fn;
514
+ }
515
+ /** @internal */
516
+ _injectAccessToken(token, expiresAt) {
517
+ this.accessToken = token;
518
+ this.tokenExpiresAt = expiresAt ?? Date.now() + 7200_000;
519
+ }
520
+ /** @internal — expose crypto params for testing */
521
+ _getCryptoParams() {
522
+ return { aesKey: this.aesKey, iv: this.iv, token: this.token };
523
+ }
524
+ }
525
+ //# sourceMappingURL=WeComAgentAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WeComAgentAdapter.js","sourceRoot":"","sources":["../src/WeComAgentAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,kBAAkB;AAElB,MAAM,cAAc,GAAG,qCAAqC,CAAC;AAC7D,6CAA6C;AAC7C,MAAM,qBAAqB,GAAG,IAAI,CAAC;AACnC,8EAA8E;AAC9E,MAAM,uBAAuB,GAAG,OAAO,CAAC;AA8BxC,+BAA+B;AAE/B;;;;GAIG;AACH,SAAS,cAAc,CAAC,cAAsB;IAC5C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,GAAG,GAAG,EAAE,QAAQ,CAAC,CAAC;IACxD,IAAI,GAAG,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,sEAAsE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IACtG,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AAC1C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,SAAiB,EAAE,KAAa,EAAE,OAAe;IAC/F,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IACzD,OAAO,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACzE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,eAAuB,EACvB,MAAc,EACd,EAAU;IAEV,MAAM,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;IACpE,QAAQ,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAC/B,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,eAAe,EAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAEhG,kBAAkB;IAClB,MAAM,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IAE7D,6BAA6B;IAC7B,MAAM,SAAS,GAAG,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAChE,MAAM,cAAc,GAAG,GAAG,CAAC,QAAQ,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAEnE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,SAAiB,EAAE,MAAc,EAAE,EAAU,EAAE,MAAc;IAC1F,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;IAC3C,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/C,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAClC,SAAS,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAE1C,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IAE3E,uCAAuC;IACvC,MAAM,SAAS,GAAG,EAAE,CAAC;IACrB,MAAM,MAAM,GAAG,SAAS,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACxD,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAEjD,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;IAChE,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AACnF,CAAC;AAED,2BAA2B;AAE3B,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC;IAC9B,gBAAgB,EAAE,KAAK;IACvB,UAAU,EAAE,IAAI;CACjB,CAAC,CAAC;AAEH,gBAAgB;AAEhB,MAAM,OAAO,iBAAiB;IACnB,WAAW,GAAG,aAAa,CAAC;IACpB,GAAG,CAAkB;IACrB,MAAM,CAAS;IACf,OAAO,CAAS;IAChB,WAAW,CAAS;IACpB,KAAK,CAAS;IACd,MAAM,CAAS;IACf,EAAE,CAAS;IAE5B,qBAAqB;IACb,WAAW,GAAG,EAAE,CAAC;IACjB,cAAc,GAAG,CAAC,CAAC;IAE3B,sBAAsB;IACd,OAAO,GAAiB,UAAU,CAAC,KAAK,CAAC;IAEjD,YAAY,GAAoB,EAAE,OAAiC;QACjE,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;QAC/B,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QACvC,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC3B,MAAM,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,cAAc,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC;QAClB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACf,CAAC;IAED,sCAAsC;IAEtC;;;;OAIG;IACH,cAAc,CAAC,KAAmF;QAChG,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;QAE3D,MAAM,WAAW,GAAG,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QAC5E,IAAI,WAAW,KAAK,aAAa,EAAE,CAAC;YAClC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,EAAE,aAAa,EAAE,EAAE,gDAAgD,CAAC,CAAC;YAC/G,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;YAClF,IAAI,cAAc,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gBACnC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,EAAE,6CAA6C,CAAC,CAAC;gBAC7G,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,+CAA+C,CAAC,CAAC;YACzE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,oDAAoD;IAEpD;;;OAGG;IACH,cAAc,CAAC,IAAY,EAAE,KAAkE;QAC7F,uCAAuC;QACvC,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,OAAO,GAAG,KAAK,EAAE,GAAG,EAAE,OAAO,IAAI,KAAK,EAAE,OAAO,IAAI,IAAI,CAAC;QAC9D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAC;YAC/D,OAAO,IAAI,CAAC;QACd,CAAC;QAED,mBAAmB;QACnB,MAAM,WAAW,GAAG,gBAAgB,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACxF,IAAI,WAAW,KAAK,KAAK,CAAC,aAAa,EAAE,CAAC;YACxC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,EAAE,KAAK,CAAC,aAAa,EAAE,EAAE,6CAA6C,CAAC,CAAC;YAClH,OAAO,IAAI,CAAC;QACd,CAAC;QAED,UAAU;QACV,IAAI,CAAC;YACH,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;YAClF,IAAI,cAAc,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;gBACnC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,EAAE,0CAA0C,CAAC,CAAC;gBAC1G,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,4CAA4C,CAAC,CAAC;YACtE,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,YAAoB;QAC7B,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAG,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC;QACnC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QAEvB,MAAM,OAAO,GAAG,IAAI,CAAC,OAA6B,CAAC;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAkC,CAAC;QACzD,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QACvC,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,2CAA2C,CAAC,CAAC;YACvF,OAAO,IAAI,CAAC;QACd,CAAC;QACD,uEAAuE;QACvE,qEAAqE;QACrE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAClE,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC/C,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,oDAAoD,CAAC,CAAC;YACvF,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,IAAI,GAAG;YACX,MAAM,EAAE,QAAQ;YAChB,SAAS,EAAE,KAAK;YAChB,QAAQ,EAAE,QAAQ;SACnB,CAAC;QAEF,QAAQ,OAAO,EAAE,CAAC;YAChB,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,MAAM,OAAO,GAAG,IAAI,CAAC,OAA6B,CAAC;gBACnD,IAAI,CAAC,OAAO;oBAAE,OAAO,IAAI,CAAC;gBAC1B,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;YAC3C,CAAC;YACD,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,MAAM,OAAO,GAAG,IAAI,CAAC,OAA6B,CAAC;gBACnD,OAAO;oBACL,GAAG,IAAI;oBACP,IAAI,EAAE,MAAM;oBACZ,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAgB,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;iBACzE,CAAC;YACJ,CAAC;YACD,KAAK,OAAO,CAAC,CAAC,CAAC;gBACb,MAAM,OAAO,GAAG,IAAI,CAAC,OAA6B,CAAC;gBACnD,uDAAuD;gBACvD,MAAM,WAAW,GAAG,IAAI,CAAC,WAAiC,CAAC;gBAC3D,OAAO;oBACL,GAAG,IAAI;oBACP,IAAI,EAAE,WAAW,IAAI,MAAM;oBAC3B,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAgB,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;iBACzE,CAAC;YACJ,CAAC;YACD,KAAK,OAAO,CAAC;YACb,KAAK,YAAY,CAAC,CAAC,CAAC;gBAClB,MAAM,OAAO,GAAG,IAAI,CAAC,OAA6B,CAAC;gBACnD,OAAO;oBACL,GAAG,IAAI;oBACP,IAAI,EAAE,MAAM;oBACZ,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAgB,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;iBACzE,CAAC;YACJ,CAAC;YACD,KAAK,MAAM,CAAC,CAAC,CAAC;gBACZ,MAAM,OAAO,GAAG,IAAI,CAAC,OAA6B,CAAC;gBACnD,MAAM,KAAK,GAAG,IAAI,CAAC,KAA2B,CAAC;gBAC/C,OAAO;oBACL,GAAG,IAAI;oBACP,IAAI,EAAE,QAAQ,KAAK,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE;oBAClC,WAAW,EAAE,OAAO;wBAClB,CAAC,CAAC;4BACE;gCACE,IAAI,EAAE,MAAe;gCACrB,OAAO;gCACP,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;6BACtC;yBACF;wBACH,CAAC,CAAC,SAAS;iBACd,CAAC;YACJ,CAAC;YACD,KAAK,UAAU,CAAC,CAAC,CAAC;gBAChB,MAAM,KAAK,GAAI,IAAI,CAAC,KAAgB,IAAI,GAAG,IAAI,CAAC,UAAU,IAAI,EAAE,IAAI,IAAI,CAAC,UAAU,IAAI,EAAE,EAAE,CAAC;gBAC5F,OAAO,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,QAAQ,KAAK,EAAE,EAAE,CAAC;YAC5C,CAAC;YACD;gBACE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,8CAA8C,CAAC,CAAC;gBAC5E,OAAO,IAAI,CAAC;QAChB,CAAC;IACH,CAAC;IAED,gCAAgC;IAEhC;;;OAGG;IACH,KAAK,CAAC,cAAc;QAClB,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;YACzD,OAAO,IAAI,CAAC,WAAW,CAAC;QAC1B,CAAC;QAED,MAAM,GAAG,GAAG,GAAG,cAAc,oBAAoB,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QACtI,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE;YAClC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;SACpC,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,qCAAqC,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QACxF,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAK7B,CAAC;QAEF,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC,CAAC;QACvG,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;QAC/E,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC;QACrC,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC;QAC1C,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,IAAI,GAAG,uBAAuB,CAAC;QAE9E,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,EAAE,4CAA4C,CAAC,CAAC;QAC3E,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,sEAAsE;IACtE,eAAe;QACb,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED,wCAAwC;IAExC;;;;OAIG;IACH,KAAK,CAAC,SAAS,CAAC,cAAsB,EAAE,OAAe,EAAE,SAAmC;QAC1F,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;QACjE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE;gBACrC,OAAO,EAAE,MAAM;gBACf,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;gBAC7B,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE;aACzB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,kBAAkB,CACtB,cAAsB,EACtB,QAAyB,EACzB,SAAmC;QAEnC,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,KAAK,UAAU,CAAC;QAClD,MAAM,WAAW,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,QAAQ,CAAC,MAAM,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;QAEhF,kDAAkD;QAClD,IAAI,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACtC,0BAA0B;YAC1B,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;YAC/D,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE;gBACrC,OAAO,EAAE,UAAU;gBACnB,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;gBAC7B,QAAQ,EAAE;oBACR,KAAK,EAAE,WAAW;oBAClB,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;oBACxC,GAAG;oBACH,MAAM,EAAE,MAAM;iBACf;aACF,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,2BAA2B;QAC3B,IAAI,SAAS,GAAG,KAAK,WAAW,QAAQ,CAAC;QACzC,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACtB,SAAS,IAAI,KAAK,QAAQ,CAAC,QAAQ,QAAQ,CAAC;QAC9C,CAAC;QACD,SAAS,IAAI,QAAQ,CAAC,IAAI,CAAC;QAC3B,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YACpB,SAAS,IAAI,YAAY,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC7C,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;QACnE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE;gBACrC,OAAO,EAAE,UAAU;gBACnB,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;gBAC7B,QAAQ,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE;aAC7B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,sBAAsB;IAEtB;;;OAGG;IACH,KAAK,CAAC,SAAS,CACb,cAAsB,EACtB,OAIC;QAED,sCAAsC;QACtC,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;QACzE,MAAM,UAAU,GAAG,MAAM,oBAAoB,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7E,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,SAAS,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC;QAC5H,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,EAAE,cAAc,EAAE,QAAQ,CAAC,CAAC;QAC7E,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QAC/E,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE;YACrC,OAAO,EAAE,cAAc;YACvB,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;YAC7B,CAAC,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE;SACxC,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,aAAa,CAAC,OAAe;QACjC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAC1C,MAAM,GAAG,GAAG,GAAG,cAAc,2BAA2B,kBAAkB,CAAC,KAAK,CAAC,aAAa,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC;QAE5H,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,MAAM,wBAAwB,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAEnF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,sCAAsC,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QACzF,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED,2BAA2B;IAE3B;;;OAGG;IACK,KAAK,CAAC,WAAW,CAAC,UAAkB,EAAE,SAAiB,EAAE,QAAgB;QAC/E,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAC1C,MAAM,GAAG,GAAG,GAAG,cAAc,8BAA8B,kBAAkB,CAAC,KAAK,CAAC,SAAS,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC;YAE7H,4BAA4B;YAC5B,MAAM,QAAQ,GAAG,iBAAiB,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAC/C,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CACxB,KAAK,QAAQ,+DAA+D,QAAQ,qDAAqD,CAC1I,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,QAAQ,QAAQ,CAAC,CAAC;YACtD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;YAEzD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE;gBAClC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,iCAAiC,QAAQ,EAAE;iBAC5D;gBACD,IAAI;gBACJ,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;aACpC,CAAC,CAAC;YAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACZ,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,EAAE,6CAA6C,CAAC,CAAC;gBACrF,OAAO,IAAI,CAAC;YACd,CAAC;YAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAI7B,CAAC;YACF,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;gBACvC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,0CAA0C,CAAC,CAAC;gBAC1G,OAAO,IAAI,CAAC;YACd,CAAC;YAED,OAAO,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,wCAAwC,CAAC,CAAC;YACtF,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,WAAW,CAAC,MAAc,EAAE,IAA6B;QACrE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAC1C,MAAM,GAAG,GAAG,GAAG,cAAc,8BAA8B,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;QAEvF,MAAM,OAAO,GAAG;YACd,MAAM,EAAE,MAAM;YACd,GAAG,IAAI;SACR,CAAC;QAEF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE;YAClC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;YAC7B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;SACpC,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,yCAAyC,GAAG,CAAC,MAAM,KAAK,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QAC5F,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAG7B,CAAC;QAEF,yCAAyC;QACzC,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YACrD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,4DAA4D,CAAC,CAAC;YACvG,IAAI,CAAC,eAAe,EAAE,CAAC;YACvB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;YAC7C,MAAM,QAAQ,GAAG,GAAG,cAAc,8BAA8B,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/F,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE;gBAC5C,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;gBAC7B,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;aACpC,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,+CAA+C,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YACpF,CAAC;YACD,MAAM,SAAS,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAGvC,CAAC;YACF,IAAI,SAAS,CAAC,OAAO,IAAI,SAAS,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;gBACjD,MAAM,IAAI,KAAK,CACb,kDAAkD,SAAS,CAAC,OAAO,KAAK,SAAS,CAAC,MAAM,IAAI,SAAS,EAAE,CACxG,CAAC;YACJ,CAAC;YACD,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,4CAA4C,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC,CAAC;QAC3G,CAAC;IACH,CAAC;IAED,gBAAgB;IAEhB;;;OAGG;IACH,YAAY,CAAC,IAAY,EAAE,QAAgB;QACzC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACpD,IAAI,UAAU,IAAI,QAAQ;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAE1C,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,SAAS,GAAG,IAAI,CAAC;QAErB,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,QAAQ,EAAE,CAAC;gBACtD,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACvB,MAAM;YACR,CAAC;YAED,6DAA6D;YAC7D,IAAI,EAAE,GAAG,CAAC,CAAC;YACX,IAAI,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC;YAC1B,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC;gBACf,MAAM,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;gBAC/B,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,IAAI,QAAQ,EAAE,CAAC;oBACpE,EAAE,GAAG,GAAG,CAAC;gBACX,CAAC;qBAAM,CAAC;oBACN,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;gBACf,CAAC;YACH,CAAC;YAED,mCAAmC;YACnC,IAAI,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAC9C,IAAI,OAAO,IAAI,CAAC;gBAAE,OAAO,GAAG,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAC3D,IAAI,OAAO,IAAI,CAAC;gBAAE,OAAO,GAAG,EAAE,CAAC;YAC/B,IACE,OAAO,GAAG,CAAC;gBACX,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;gBACrD,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,EACjD,CAAC;gBACD,OAAO,EAAE,CAAC;YACZ,CAAC;YAED,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;YACzC,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC;QACnD,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,qBAAqB;IAErB,gBAAgB;IAChB,YAAY,CAAC,EAAgB;QAC3B,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACpB,CAAC;IAED,gBAAgB;IAChB,kBAAkB,CAAC,KAAa,EAAE,SAAkB;QAClD,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QACzB,IAAI,CAAC,cAAc,GAAG,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC;IAC3D,CAAC;IAED,mDAAmD;IACnD,gBAAgB;QACd,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;IACjE,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ declare const MAX_MEDIA_BYTES: {
2
+ readonly image: number;
3
+ readonly audio: number;
4
+ readonly file: number;
5
+ };
6
+ export declare class ProviderMediaLimitError extends RangeError {
7
+ constructor(type: keyof typeof MAX_MEDIA_BYTES);
8
+ }
9
+ /** Collect only for provider SDKs whose upload API requires one Buffer. */
10
+ export declare function collectProviderMedia(type: keyof typeof MAX_MEDIA_BYTES, content: AsyncIterable<Uint8Array>): Promise<Buffer>;
11
+ export {};
12
+ //# sourceMappingURL=collect-media.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect-media.d.ts","sourceRoot":"","sources":["../src/collect-media.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,eAAe;;;;CAIX,CAAC;AAEX,qBAAa,uBAAwB,SAAQ,UAAU;gBACzC,IAAI,EAAE,MAAM,OAAO,eAAe;CAI/C;AAED,2EAA2E;AAC3E,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,OAAO,eAAe,EAClC,OAAO,EAAE,aAAa,CAAC,UAAU,CAAC,GACjC,OAAO,CAAC,MAAM,CAAC,CASjB"}
@@ -0,0 +1,27 @@
1
+ const MEBIBYTE = 1024 * 1024;
2
+ // WeCom temporary-media upload (`media/upload`, document 90253):
3
+ // image 10 MiB, voice 2 MiB, ordinary file 20 MiB.
4
+ const MAX_MEDIA_BYTES = {
5
+ image: 10 * MEBIBYTE,
6
+ audio: 2 * MEBIBYTE,
7
+ file: 20 * MEBIBYTE,
8
+ };
9
+ export class ProviderMediaLimitError extends RangeError {
10
+ constructor(type) {
11
+ super(`${type} media exceeds the provider upload limit`);
12
+ this.name = 'ProviderMediaLimitError';
13
+ }
14
+ }
15
+ /** Collect only for provider SDKs whose upload API requires one Buffer. */
16
+ export async function collectProviderMedia(type, content) {
17
+ const chunks = [];
18
+ let total = 0;
19
+ for await (const chunk of content) {
20
+ total += chunk.byteLength;
21
+ if (total > MAX_MEDIA_BYTES[type])
22
+ throw new ProviderMediaLimitError(type);
23
+ chunks.push(Buffer.from(chunk));
24
+ }
25
+ return Buffer.concat(chunks, total);
26
+ }
27
+ //# sourceMappingURL=collect-media.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect-media.js","sourceRoot":"","sources":["../src/collect-media.ts"],"names":[],"mappings":"AAAA,MAAM,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAC;AAE7B,iEAAiE;AACjE,mDAAmD;AACnD,MAAM,eAAe,GAAG;IACtB,KAAK,EAAE,EAAE,GAAG,QAAQ;IACpB,KAAK,EAAE,CAAC,GAAG,QAAQ;IACnB,IAAI,EAAE,EAAE,GAAG,QAAQ;CACX,CAAC;AAEX,MAAM,OAAO,uBAAwB,SAAQ,UAAU;IACrD,YAAY,IAAkC;QAC5C,KAAK,CAAC,GAAG,IAAI,0CAA0C,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;IACxC,CAAC;CACF;AAED,2EAA2E;AAC3E,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,IAAkC,EAClC,OAAkC;IAElC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAClC,KAAK,IAAI,KAAK,CAAC,UAAU,CAAC;QAC1B,IAAI,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,uBAAuB,CAAC,IAAI,CAAC,CAAC;QAC3E,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { WeComAgentHostInboundMessage } from './runtime.js';
2
+ /** Provider facts only; no chat-id heuristics or payload owner authority. */
3
+ export declare function connectorCommandFacts(message: WeComAgentHostInboundMessage): {
4
+ chatId: string;
5
+ providerMessageId: string;
6
+ text: string;
7
+ group: boolean;
8
+ senderId: string | undefined;
9
+ };
10
+ //# sourceMappingURL=command-ingress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-ingress.d.ts","sourceRoot":"","sources":["../src/command-ingress.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,cAAc,CAAC;AAEjE,6EAA6E;AAC7E,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B;;;;;;EAU1E"}
@@ -0,0 +1,13 @@
1
+ /** Provider facts only; no chat-id heuristics or payload owner authority. */
2
+ export function connectorCommandFacts(message) {
3
+ const sender = message.externalSenderId;
4
+ return {
5
+ chatId: message.externalConversationId,
6
+ providerMessageId: message.providerMessageId,
7
+ text: message.text,
8
+ // The existing adapter supports direct conversations only; this does not enable groups.
9
+ group: false,
10
+ senderId: sender === 'unknown' || sender === '' ? undefined : sender,
11
+ };
12
+ }
13
+ //# sourceMappingURL=command-ingress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-ingress.js","sourceRoot":"","sources":["../src/command-ingress.ts"],"names":[],"mappings":"AAEA,6EAA6E;AAC7E,MAAM,UAAU,qBAAqB,CAAC,OAAqC;IACzE,MAAM,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IACxC,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,sBAAsB;QACtC,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;QAC5C,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,wFAAwF;QACxF,KAAK,EAAE,KAAK;QACZ,QAAQ,EAAE,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM;KACrE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,13 @@
1
+ /** Host import is capped at 64 MiB; reject before an adapter buffers beyond it. */
2
+ export declare const INBOUND_MEDIA_MAX_BYTES: number;
3
+ export declare const INBOUND_MEDIA_TIMEOUT_MS = 30000;
4
+ export declare class InboundMediaLimitError extends Error {
5
+ readonly maxBytes: number;
6
+ constructor(maxBytes: number);
7
+ }
8
+ export declare function collectBoundedInboundMedia(content: AsyncIterable<Uint8Array>, maxBytes?: number): Promise<Buffer>;
9
+ export declare function fetchBoundedInboundMedia(fetchFn: typeof fetch, input: string | URL, init?: RequestInit, maxBytes?: number, timeoutMs?: number): Promise<{
10
+ readonly response: Response;
11
+ readonly bytes: Buffer;
12
+ }>;
13
+ //# sourceMappingURL=inbound-download.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound-download.d.ts","sourceRoot":"","sources":["../src/inbound-download.ts"],"names":[],"mappings":"AAEA,mFAAmF;AACnF,eAAO,MAAM,uBAAuB,QAAgB,CAAC;AACrD,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAE/C,qBAAa,sBAAuB,SAAQ,KAAK;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM;gBAAhB,QAAQ,EAAE,MAAM;CAItC;AAED,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,aAAa,CAAC,UAAU,CAAC,EAClC,QAAQ,SAA0B,GACjC,OAAO,CAAC,MAAM,CAAC,CASjB;AAED,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,OAAO,KAAK,EACrB,KAAK,EAAE,MAAM,GAAG,GAAG,EACnB,IAAI,GAAE,WAAgB,EACtB,QAAQ,SAA0B,EAClC,SAAS,SAA2B,GACnC,OAAO,CAAC;IAAE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAyClE"}