@hotwvpyym/openclaw-lark 0.0.0-stage → 2026.9.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.
@@ -0,0 +1,1398 @@
1
+ import * as openclaw_plugin_sdk_core0 from "openclaw/plugin-sdk/core";
2
+ import { ChannelPlugin, OpenClawConfig, OpenClawPluginApi } from "openclaw/plugin-sdk/core";
3
+ import { z } from "zod";
4
+ import { HistoryEntry } from "openclaw/plugin-sdk/reply-history";
5
+ import { RuntimeEnv } from "openclaw/plugin-sdk/runtime-env";
6
+ import { ChannelMessageActionAdapter } from "openclaw/plugin-sdk/channel-contract";
7
+
8
+ //#region src/messaging/inbound/dedup.d.ts
9
+ /**
10
+ * Check whether a message is too old to process.
11
+ *
12
+ * Feishu message `create_time` is a millisecond Unix timestamp encoded
13
+ * as a string. When a WebSocket reconnects after a long outage, stale
14
+ * messages may be redelivered — this function lets callers discard them
15
+ * before entering the full handling pipeline.
16
+ */
17
+ declare function isMessageExpired(createTimeStr: string | undefined, expiryMs?: number): boolean;
18
+ //#endregion
19
+ //#region src/core/config-schema.d.ts
20
+ declare const FeishuConfigSchema: z.ZodObject<{
21
+ appId: z.ZodOptional<z.ZodString>;
22
+ appSecret: z.ZodOptional<z.ZodString>;
23
+ encryptKey: z.ZodOptional<z.ZodString>;
24
+ verificationToken: z.ZodOptional<z.ZodString>;
25
+ name: z.ZodOptional<z.ZodString>;
26
+ enabled: z.ZodOptional<z.ZodBoolean>;
27
+ domain: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"feishu">, z.ZodLiteral<"lark">, z.ZodString]>>;
28
+ connectionMode: z.ZodOptional<z.ZodEnum<{
29
+ websocket: "websocket";
30
+ webhook: "webhook";
31
+ }>>;
32
+ webhookPath: z.ZodOptional<z.ZodString>;
33
+ webhookPort: z.ZodOptional<z.ZodNumber>;
34
+ dmPolicy: z.ZodOptional<z.ZodEnum<{
35
+ open: "open";
36
+ allowlist: "allowlist";
37
+ disabled: "disabled";
38
+ pairing: "pairing";
39
+ }>>;
40
+ allowFrom: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>, z.ZodTransform<string[] | undefined, string | string[] | undefined>>;
41
+ groupPolicy: z.ZodOptional<z.ZodEnum<{
42
+ open: "open";
43
+ allowlist: "allowlist";
44
+ disabled: "disabled";
45
+ }>>;
46
+ groupAllowFrom: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>, z.ZodTransform<string[] | undefined, string | string[] | undefined>>;
47
+ requireMention: z.ZodOptional<z.ZodBoolean>;
48
+ respondToMentionAll: z.ZodOptional<z.ZodBoolean>;
49
+ groups: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
50
+ groupPolicy: z.ZodOptional<z.ZodEnum<{
51
+ open: "open";
52
+ allowlist: "allowlist";
53
+ disabled: "disabled";
54
+ }>>;
55
+ requireMention: z.ZodOptional<z.ZodBoolean>;
56
+ respondToMentionAll: z.ZodOptional<z.ZodBoolean>;
57
+ tools: z.ZodOptional<z.ZodObject<{
58
+ allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
59
+ deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
60
+ }, z.core.$strip>>;
61
+ skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
62
+ enabled: z.ZodOptional<z.ZodBoolean>;
63
+ allowFrom: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>, z.ZodTransform<string[] | undefined, string | string[] | undefined>>;
64
+ systemPrompt: z.ZodOptional<z.ZodString>;
65
+ allowBots: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"mentions">]>>;
66
+ replyInThread: z.ZodOptional<z.ZodBoolean>;
67
+ }, z.core.$strip>>>;
68
+ historyLimit: z.ZodOptional<z.ZodNumber>;
69
+ dmHistoryLimit: z.ZodOptional<z.ZodNumber>;
70
+ dms: z.ZodOptional<z.ZodObject<{
71
+ historyLimit: z.ZodOptional<z.ZodNumber>;
72
+ }, z.core.$strip>>;
73
+ textChunkLimit: z.ZodOptional<z.ZodNumber>;
74
+ chunkMode: z.ZodOptional<z.ZodEnum<{
75
+ newline: "newline";
76
+ paragraph: "paragraph";
77
+ none: "none";
78
+ }>>;
79
+ blockStreamingCoalesce: z.ZodOptional<z.ZodObject<{
80
+ minChars: z.ZodOptional<z.ZodNumber>;
81
+ maxChars: z.ZodOptional<z.ZodNumber>;
82
+ idleMs: z.ZodOptional<z.ZodNumber>;
83
+ }, z.core.$strip>>;
84
+ mediaMaxMb: z.ZodOptional<z.ZodNumber>;
85
+ heartbeat: z.ZodOptional<z.ZodObject<{
86
+ every: z.ZodOptional<z.ZodString>;
87
+ activeHours: z.ZodOptional<z.ZodObject<{
88
+ start: z.ZodOptional<z.ZodString>;
89
+ end: z.ZodOptional<z.ZodString>;
90
+ timezone: z.ZodOptional<z.ZodString>;
91
+ }, z.core.$strip>>;
92
+ target: z.ZodOptional<z.ZodString>;
93
+ to: z.ZodOptional<z.ZodString>;
94
+ prompt: z.ZodOptional<z.ZodString>;
95
+ accountId: z.ZodOptional<z.ZodString>;
96
+ }, z.core.$strip>>;
97
+ replyMode: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
98
+ auto: "auto";
99
+ static: "static";
100
+ streaming: "streaming";
101
+ }>, z.ZodObject<{
102
+ default: z.ZodOptional<z.ZodEnum<{
103
+ auto: "auto";
104
+ static: "static";
105
+ streaming: "streaming";
106
+ }>>;
107
+ group: z.ZodOptional<z.ZodEnum<{
108
+ auto: "auto";
109
+ static: "static";
110
+ streaming: "streaming";
111
+ }>>;
112
+ direct: z.ZodOptional<z.ZodEnum<{
113
+ auto: "auto";
114
+ static: "static";
115
+ streaming: "streaming";
116
+ }>>;
117
+ }, z.core.$strip>]>>;
118
+ streaming: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
119
+ mode: z.ZodOptional<z.ZodEnum<{
120
+ off: "off";
121
+ partial: "partial";
122
+ block: "block";
123
+ progress: "progress";
124
+ }>>;
125
+ block: z.ZodOptional<z.ZodObject<{
126
+ enabled: z.ZodOptional<z.ZodBoolean>;
127
+ }, z.core.$loose>>;
128
+ }, z.core.$loose>]>>;
129
+ blockStreaming: z.ZodOptional<z.ZodBoolean>;
130
+ toolUseDisplay: z.ZodOptional<z.ZodObject<{
131
+ showFullPaths: z.ZodOptional<z.ZodBoolean>;
132
+ }, z.core.$strip>>;
133
+ tools: z.ZodOptional<z.ZodObject<{
134
+ doc: z.ZodOptional<z.ZodBoolean>;
135
+ wiki: z.ZodOptional<z.ZodBoolean>;
136
+ drive: z.ZodOptional<z.ZodBoolean>;
137
+ perm: z.ZodOptional<z.ZodBoolean>;
138
+ scopes: z.ZodOptional<z.ZodBoolean>;
139
+ }, z.core.$strip>>;
140
+ footer: z.ZodOptional<z.ZodObject<{
141
+ status: z.ZodOptional<z.ZodBoolean>;
142
+ elapsed: z.ZodOptional<z.ZodBoolean>;
143
+ tokens: z.ZodOptional<z.ZodBoolean>;
144
+ cache: z.ZodOptional<z.ZodBoolean>;
145
+ context: z.ZodOptional<z.ZodBoolean>;
146
+ model: z.ZodOptional<z.ZodBoolean>;
147
+ }, z.core.$strip>>;
148
+ markdown: z.ZodOptional<z.ZodObject<{
149
+ tables: z.ZodOptional<z.ZodEnum<{
150
+ off: "off";
151
+ bullets: "bullets";
152
+ code: "code";
153
+ }>>;
154
+ }, z.core.$strip>>;
155
+ configWrites: z.ZodOptional<z.ZodBoolean>;
156
+ capabilities: z.ZodOptional<z.ZodObject<{
157
+ image: z.ZodOptional<z.ZodBoolean>;
158
+ audio: z.ZodOptional<z.ZodBoolean>;
159
+ video: z.ZodOptional<z.ZodBoolean>;
160
+ }, z.core.$strip>>;
161
+ dedup: z.ZodOptional<z.ZodObject<{
162
+ ttlMs: z.ZodOptional<z.ZodNumber>;
163
+ maxEntries: z.ZodOptional<z.ZodNumber>;
164
+ }, z.core.$strip>>;
165
+ reactionNotifications: z.ZodOptional<z.ZodEnum<{
166
+ off: "off";
167
+ own: "own";
168
+ all: "all";
169
+ }>>;
170
+ threadSession: z.ZodOptional<z.ZodBoolean>;
171
+ allowBots: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"mentions">]>>;
172
+ replyInThread: z.ZodOptional<z.ZodBoolean>;
173
+ uat: z.ZodOptional<z.ZodObject<{
174
+ enabled: z.ZodOptional<z.ZodBoolean>;
175
+ allowedScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
176
+ blockedScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
177
+ }, z.core.$strip>>;
178
+ accounts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
179
+ appId: z.ZodOptional<z.ZodString>;
180
+ appSecret: z.ZodOptional<z.ZodString>;
181
+ encryptKey: z.ZodOptional<z.ZodString>;
182
+ verificationToken: z.ZodOptional<z.ZodString>;
183
+ name: z.ZodOptional<z.ZodString>;
184
+ enabled: z.ZodOptional<z.ZodBoolean>;
185
+ domain: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"feishu">, z.ZodLiteral<"lark">, z.ZodString]>>;
186
+ connectionMode: z.ZodOptional<z.ZodEnum<{
187
+ websocket: "websocket";
188
+ webhook: "webhook";
189
+ }>>;
190
+ webhookPath: z.ZodOptional<z.ZodString>;
191
+ webhookPort: z.ZodOptional<z.ZodNumber>;
192
+ dmPolicy: z.ZodOptional<z.ZodEnum<{
193
+ open: "open";
194
+ allowlist: "allowlist";
195
+ disabled: "disabled";
196
+ pairing: "pairing";
197
+ }>>;
198
+ allowFrom: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>, z.ZodTransform<string[] | undefined, string | string[] | undefined>>;
199
+ groupPolicy: z.ZodOptional<z.ZodEnum<{
200
+ open: "open";
201
+ allowlist: "allowlist";
202
+ disabled: "disabled";
203
+ }>>;
204
+ groupAllowFrom: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>, z.ZodTransform<string[] | undefined, string | string[] | undefined>>;
205
+ requireMention: z.ZodOptional<z.ZodBoolean>;
206
+ respondToMentionAll: z.ZodOptional<z.ZodBoolean>;
207
+ groups: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
208
+ groupPolicy: z.ZodOptional<z.ZodEnum<{
209
+ open: "open";
210
+ allowlist: "allowlist";
211
+ disabled: "disabled";
212
+ }>>;
213
+ requireMention: z.ZodOptional<z.ZodBoolean>;
214
+ respondToMentionAll: z.ZodOptional<z.ZodBoolean>;
215
+ tools: z.ZodOptional<z.ZodObject<{
216
+ allow: z.ZodOptional<z.ZodArray<z.ZodString>>;
217
+ deny: z.ZodOptional<z.ZodArray<z.ZodString>>;
218
+ }, z.core.$strip>>;
219
+ skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
220
+ enabled: z.ZodOptional<z.ZodBoolean>;
221
+ allowFrom: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>, z.ZodTransform<string[] | undefined, string | string[] | undefined>>;
222
+ systemPrompt: z.ZodOptional<z.ZodString>;
223
+ allowBots: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"mentions">]>>;
224
+ replyInThread: z.ZodOptional<z.ZodBoolean>;
225
+ }, z.core.$strip>>>;
226
+ historyLimit: z.ZodOptional<z.ZodNumber>;
227
+ dmHistoryLimit: z.ZodOptional<z.ZodNumber>;
228
+ dms: z.ZodOptional<z.ZodObject<{
229
+ historyLimit: z.ZodOptional<z.ZodNumber>;
230
+ }, z.core.$strip>>;
231
+ textChunkLimit: z.ZodOptional<z.ZodNumber>;
232
+ chunkMode: z.ZodOptional<z.ZodEnum<{
233
+ newline: "newline";
234
+ paragraph: "paragraph";
235
+ none: "none";
236
+ }>>;
237
+ blockStreamingCoalesce: z.ZodOptional<z.ZodObject<{
238
+ minChars: z.ZodOptional<z.ZodNumber>;
239
+ maxChars: z.ZodOptional<z.ZodNumber>;
240
+ idleMs: z.ZodOptional<z.ZodNumber>;
241
+ }, z.core.$strip>>;
242
+ mediaMaxMb: z.ZodOptional<z.ZodNumber>;
243
+ heartbeat: z.ZodOptional<z.ZodObject<{
244
+ every: z.ZodOptional<z.ZodString>;
245
+ activeHours: z.ZodOptional<z.ZodObject<{
246
+ start: z.ZodOptional<z.ZodString>;
247
+ end: z.ZodOptional<z.ZodString>;
248
+ timezone: z.ZodOptional<z.ZodString>;
249
+ }, z.core.$strip>>;
250
+ target: z.ZodOptional<z.ZodString>;
251
+ to: z.ZodOptional<z.ZodString>;
252
+ prompt: z.ZodOptional<z.ZodString>;
253
+ accountId: z.ZodOptional<z.ZodString>;
254
+ }, z.core.$strip>>;
255
+ replyMode: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
256
+ auto: "auto";
257
+ static: "static";
258
+ streaming: "streaming";
259
+ }>, z.ZodObject<{
260
+ default: z.ZodOptional<z.ZodEnum<{
261
+ auto: "auto";
262
+ static: "static";
263
+ streaming: "streaming";
264
+ }>>;
265
+ group: z.ZodOptional<z.ZodEnum<{
266
+ auto: "auto";
267
+ static: "static";
268
+ streaming: "streaming";
269
+ }>>;
270
+ direct: z.ZodOptional<z.ZodEnum<{
271
+ auto: "auto";
272
+ static: "static";
273
+ streaming: "streaming";
274
+ }>>;
275
+ }, z.core.$strip>]>>;
276
+ streaming: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
277
+ mode: z.ZodOptional<z.ZodEnum<{
278
+ off: "off";
279
+ partial: "partial";
280
+ block: "block";
281
+ progress: "progress";
282
+ }>>;
283
+ block: z.ZodOptional<z.ZodObject<{
284
+ enabled: z.ZodOptional<z.ZodBoolean>;
285
+ }, z.core.$loose>>;
286
+ }, z.core.$loose>]>>;
287
+ blockStreaming: z.ZodOptional<z.ZodBoolean>;
288
+ toolUseDisplay: z.ZodOptional<z.ZodObject<{
289
+ showFullPaths: z.ZodOptional<z.ZodBoolean>;
290
+ }, z.core.$strip>>;
291
+ tools: z.ZodOptional<z.ZodObject<{
292
+ doc: z.ZodOptional<z.ZodBoolean>;
293
+ wiki: z.ZodOptional<z.ZodBoolean>;
294
+ drive: z.ZodOptional<z.ZodBoolean>;
295
+ perm: z.ZodOptional<z.ZodBoolean>;
296
+ scopes: z.ZodOptional<z.ZodBoolean>;
297
+ }, z.core.$strip>>;
298
+ footer: z.ZodOptional<z.ZodObject<{
299
+ status: z.ZodOptional<z.ZodBoolean>;
300
+ elapsed: z.ZodOptional<z.ZodBoolean>;
301
+ tokens: z.ZodOptional<z.ZodBoolean>;
302
+ cache: z.ZodOptional<z.ZodBoolean>;
303
+ context: z.ZodOptional<z.ZodBoolean>;
304
+ model: z.ZodOptional<z.ZodBoolean>;
305
+ }, z.core.$strip>>;
306
+ markdown: z.ZodOptional<z.ZodObject<{
307
+ tables: z.ZodOptional<z.ZodEnum<{
308
+ off: "off";
309
+ bullets: "bullets";
310
+ code: "code";
311
+ }>>;
312
+ }, z.core.$strip>>;
313
+ configWrites: z.ZodOptional<z.ZodBoolean>;
314
+ capabilities: z.ZodOptional<z.ZodObject<{
315
+ image: z.ZodOptional<z.ZodBoolean>;
316
+ audio: z.ZodOptional<z.ZodBoolean>;
317
+ video: z.ZodOptional<z.ZodBoolean>;
318
+ }, z.core.$strip>>;
319
+ dedup: z.ZodOptional<z.ZodObject<{
320
+ ttlMs: z.ZodOptional<z.ZodNumber>;
321
+ maxEntries: z.ZodOptional<z.ZodNumber>;
322
+ }, z.core.$strip>>;
323
+ reactionNotifications: z.ZodOptional<z.ZodEnum<{
324
+ off: "off";
325
+ own: "own";
326
+ all: "all";
327
+ }>>;
328
+ threadSession: z.ZodOptional<z.ZodBoolean>;
329
+ allowBots: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodLiteral<"mentions">]>>;
330
+ replyInThread: z.ZodOptional<z.ZodBoolean>;
331
+ uat: z.ZodOptional<z.ZodObject<{
332
+ enabled: z.ZodOptional<z.ZodBoolean>;
333
+ allowedScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
334
+ blockedScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
335
+ }, z.core.$strip>>;
336
+ }, z.core.$strip>>>;
337
+ }, z.core.$strip>;
338
+ //#endregion
339
+ //#region src/core/types.d.ts
340
+ /** Fully resolved top-level Feishu channel configuration. */
341
+ type FeishuConfig = z.infer<typeof FeishuConfigSchema>;
342
+ /**
343
+ * The Lark platform brand.
344
+ * - `"feishu"` targets the China-mainland Feishu service.
345
+ * - `"lark"` targets the international Lark service.
346
+ * - Any other string is treated as a custom base URL.
347
+ */
348
+ type LarkBrand = 'feishu' | 'lark' | (string & {});
349
+ /** Common fields shared by all resolved account states. */
350
+ interface LarkAccountBase {
351
+ accountId: string;
352
+ enabled: boolean;
353
+ name?: string;
354
+ encryptKey?: string;
355
+ verificationToken?: string;
356
+ brand: LarkBrand;
357
+ config: FeishuConfig;
358
+ }
359
+ /** An account with both `appId` and `appSecret` present. */
360
+ type ConfiguredLarkAccount = LarkAccountBase & {
361
+ configured: true;
362
+ appId: string;
363
+ appSecret: string;
364
+ };
365
+ /** An account that is missing `appId` and/or `appSecret`. */
366
+ type UnconfiguredLarkAccount = LarkAccountBase & {
367
+ configured: false;
368
+ appId?: string;
369
+ appSecret?: string;
370
+ };
371
+ /** A resolved Lark account — either fully configured or not. */
372
+ type LarkAccount = ConfiguredLarkAccount | UnconfiguredLarkAccount;
373
+ /** Result of probing an app's connectivity / permissions. */
374
+ interface FeishuProbeResult {
375
+ ok: boolean;
376
+ error?: string;
377
+ appId?: string;
378
+ botName?: string;
379
+ botOpenId?: string;
380
+ }
381
+ //#endregion
382
+ //#region src/core/lark-client.d.ts
383
+ /** Credential set accepted by the ephemeral `fromCredentials` factory. */
384
+ interface LarkClientCredentials {
385
+ accountId?: string;
386
+ appId?: string;
387
+ appSecret?: string;
388
+ brand?: LarkBrand;
389
+ }
390
+ //#endregion
391
+ //#region src/channel/types.d.ts
392
+ interface MonitorFeishuOpts {
393
+ config?: OpenClawConfig;
394
+ runtime?: RuntimeEnv;
395
+ abortSignal?: AbortSignal;
396
+ accountId?: string;
397
+ }
398
+ //#endregion
399
+ //#region src/channel/monitor.d.ts
400
+ /**
401
+ * Start monitoring for all enabled Feishu accounts (or a single
402
+ * account when `opts.accountId` is specified).
403
+ */
404
+ declare function monitorFeishuProvider(opts?: MonitorFeishuOpts): Promise<void>;
405
+ //#endregion
406
+ //#region src/messaging/types.d.ts
407
+ /**
408
+ * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates
409
+ * SPDX-License-Identifier: MIT
410
+ *
411
+ * Messaging type definitions for the Lark/Feishu channel plugin.
412
+ *
413
+ * Pure shape types for inbound message events, normalised message context,
414
+ * mention targets, and media metadata.
415
+ */
416
+ interface FeishuMessageEvent {
417
+ sender: {
418
+ sender_id: {
419
+ open_id?: string;
420
+ user_id?: string;
421
+ union_id?: string;
422
+ };
423
+ sender_type?: string;
424
+ tenant_key?: string;
425
+ };
426
+ message: {
427
+ message_id: string;
428
+ root_id?: string;
429
+ parent_id?: string;
430
+ create_time?: string;
431
+ update_time?: string;
432
+ chat_id: string;
433
+ thread_id?: string;
434
+ chat_type: 'p2p' | 'group';
435
+ message_type: string;
436
+ content: string;
437
+ mentions?: Array<{
438
+ key: string;
439
+ id: {
440
+ open_id?: string;
441
+ user_id?: string;
442
+ union_id?: string;
443
+ };
444
+ name: string;
445
+ tenant_key?: string;
446
+ }>;
447
+ user_agent?: string;
448
+ };
449
+ }
450
+ interface FeishuReactionCreatedEvent {
451
+ message_id: string;
452
+ chat_id?: string;
453
+ chat_type?: 'p2p' | 'group' | 'private';
454
+ reaction_type?: {
455
+ emoji_type?: string;
456
+ };
457
+ operator_type?: string;
458
+ user_id?: {
459
+ open_id?: string;
460
+ user_id?: string;
461
+ union_id?: string;
462
+ };
463
+ action_time?: string;
464
+ }
465
+ /** Metadata describing a media resource in a message (no binary data). */
466
+ interface ResourceDescriptor {
467
+ type: 'image' | 'file' | 'audio' | 'video' | 'sticker';
468
+ /** image_key or file_key from the raw message content. */
469
+ fileKey: string;
470
+ /** Original file name (file/video messages). */
471
+ fileName?: string;
472
+ /** Duration in milliseconds (audio/video messages). */
473
+ duration?: number;
474
+ /** Video cover image key. */
475
+ coverImageKey?: string;
476
+ }
477
+ /** Structured @mention information from a message. */
478
+ interface MentionInfo {
479
+ /** Placeholder key in raw content (e.g. "@_user_1"). */
480
+ key: string;
481
+ /** Feishu Open ID of the mentioned user. */
482
+ openId: string;
483
+ /** Display name. */
484
+ name: string;
485
+ /** True iff this mention targets the receiving bot itself (openId === botOpenId). */
486
+ isBot: boolean;
487
+ }
488
+ /** Raw message body, directly mapped from FeishuMessageEvent.message. */
489
+ interface RawMessage {
490
+ message_id: string;
491
+ root_id?: string;
492
+ parent_id?: string;
493
+ create_time?: string;
494
+ update_time?: string;
495
+ chat_id: string;
496
+ thread_id?: string;
497
+ chat_type: 'p2p' | 'group';
498
+ message_type: string;
499
+ content: string;
500
+ mentions?: Array<{
501
+ key: string;
502
+ id: {
503
+ open_id?: string;
504
+ user_id?: string;
505
+ union_id?: string;
506
+ };
507
+ name: string;
508
+ tenant_key?: string;
509
+ }>;
510
+ user_agent?: string;
511
+ }
512
+ /** Raw sender data, directly mapped from FeishuMessageEvent.sender. */
513
+ interface RawSender {
514
+ sender_id: {
515
+ open_id?: string;
516
+ user_id?: string;
517
+ union_id?: string;
518
+ };
519
+ sender_type?: string;
520
+ tenant_key?: string;
521
+ }
522
+ /** Normalised representation of an inbound Feishu message. */
523
+ interface MessageContext {
524
+ chatId: string;
525
+ messageId: string;
526
+ senderId: string;
527
+ senderName?: string;
528
+ chatType: 'p2p' | 'group';
529
+ content: string;
530
+ contentType: string;
531
+ /** Media resource descriptors extracted during parsing. */
532
+ resources: ResourceDescriptor[];
533
+ /** All @mentions in the message (including bot). */
534
+ mentions: MentionInfo[];
535
+ /** Whether an @all / @所有人 mention was detected in the message. */
536
+ mentionAll: boolean;
537
+ /**
538
+ * True when the event sender is a bot/app (sender_type === 'app').
539
+ *
540
+ * Set by parseMessageEvent. Optional because synthetic construction sites
541
+ * (comment / reaction / vc-invited handlers) omit it — absence is treated
542
+ * as `false` since those paths only originate from human actors today.
543
+ */
544
+ senderIsBot?: boolean;
545
+ rootId?: string;
546
+ parentId?: string;
547
+ threadId?: string;
548
+ createTime?: number;
549
+ rawMessage: RawMessage;
550
+ rawSender: RawSender;
551
+ }
552
+ /** @deprecated Use {@link MessageContext} instead. */
553
+ type FeishuMessageContext = MessageContext;
554
+ /** Result of sending a message via the Feishu API. */
555
+ interface FeishuSendResult {
556
+ messageId: string;
557
+ chatId: string;
558
+ /**
559
+ * Human-readable warning when the send succeeded but with degradation
560
+ * (e.g. media upload failed, fell back to a text link).
561
+ *
562
+ * Populated so upstream callers (and the AI) can detect that the
563
+ * delivery was not fully as intended and take corrective action.
564
+ */
565
+ warning?: string;
566
+ }
567
+ //#endregion
568
+ //#region src/messaging/outbound/send.d.ts
569
+ /**
570
+ * Parameters for sending a text / post message.
571
+ */
572
+ interface SendFeishuMessageParams {
573
+ cfg: OpenClawConfig;
574
+ /** Target identifier (chat_id, open_id, or user_id). */
575
+ to: string;
576
+ /** Message text content (supports Feishu markdown subset). */
577
+ text: string;
578
+ /** When set, the message is sent as a threaded reply. */
579
+ replyToMessageId?: string;
580
+ /** Optional mention targets to prepend to the message. */
581
+ mentions?: MentionInfo[];
582
+ /** Optional account identifier for multi-account setups. */
583
+ accountId?: string;
584
+ /** When true, the reply appears in the thread instead of main chat. */
585
+ replyInThread?: boolean;
586
+ /** Thread root id when the reply lives inside a thread; used for sentinel keying. */
587
+ threadId?: string;
588
+ /**
589
+ * Optional multi-locale texts for i18n post messages.
590
+ * When provided, builds a multi-locale post structure (e.g. { zh_cn: ..., en_us: ... })
591
+ * and the `text` field is ignored. Feishu client auto-selects locale based on user language.
592
+ */
593
+ i18nTexts?: Record<string, string>;
594
+ }
595
+ /**
596
+ * Parameters for sending an interactive card message.
597
+ */
598
+ interface SendFeishuCardParams {
599
+ cfg: OpenClawConfig;
600
+ /** Target identifier (chat_id, open_id, or user_id). */
601
+ to: string;
602
+ /** The full interactive card JSON payload. */
603
+ card: Record<string, unknown>;
604
+ /** When set, the card is sent as a threaded reply. */
605
+ replyToMessageId?: string;
606
+ /** Optional account identifier for multi-account setups. */
607
+ accountId?: string;
608
+ /** When true, the reply appears in the thread instead of main chat. */
609
+ replyInThread?: boolean;
610
+ }
611
+ /**
612
+ * Send a text message (rendered as a Feishu "post" with markdown support)
613
+ * to a chat or user.
614
+ *
615
+ * The message text is wrapped in Feishu's post format using the `md` tag
616
+ * for rich rendering. If `replyToMessageId` is provided, the message is
617
+ * sent as a threaded reply; otherwise it is sent as a new message using
618
+ * the appropriate `receive_id_type`.
619
+ *
620
+ * Markdown tables and code blocks are sent as-is so Feishu renders them
621
+ * natively in the post(`tag:md`); only `optimizeMarkdownStyle` is applied.
622
+ *
623
+ * @param params - See {@link SendFeishuMessageParams}.
624
+ * @returns The send result containing the new message ID.
625
+ */
626
+ declare function sendMessageFeishu(params: SendFeishuMessageParams): Promise<FeishuSendResult>;
627
+ /**
628
+ * Send an interactive card message to a chat or user.
629
+ *
630
+ * @param params - See {@link SendFeishuCardParams}.
631
+ * @returns The send result containing the new message ID.
632
+ */
633
+ declare function sendCardFeishu(params: SendFeishuCardParams): Promise<FeishuSendResult>;
634
+ /**
635
+ * Update (PATCH) the content of an existing interactive card message.
636
+ *
637
+ * Only messages originally sent by the bot can be updated. The card
638
+ * must have been created with `"update_multi": true` in its config if
639
+ * all recipients should see the update.
640
+ *
641
+ * @param params.cfg - Plugin configuration.
642
+ * @param params.messageId - The card message ID to update.
643
+ * @param params.card - The new card content.
644
+ * @param params.accountId - Optional account identifier.
645
+ */
646
+ declare function updateCardFeishu(params: {
647
+ cfg: OpenClawConfig;
648
+ messageId: string;
649
+ card: Record<string, unknown>;
650
+ accountId?: string;
651
+ }): Promise<void>;
652
+ /**
653
+ * Edit the content of an existing message.
654
+ *
655
+ * Updates the message body via the IM message update API. Only
656
+ * messages sent by the bot can be edited.
657
+ *
658
+ * @param params.cfg - Plugin configuration.
659
+ * @param params.messageId - The message ID to edit.
660
+ * @param params.text - The new message text.
661
+ * @param params.accountId - Optional account identifier.
662
+ */
663
+ declare function editMessageFeishu(params: {
664
+ cfg: OpenClawConfig;
665
+ messageId: string;
666
+ text: string;
667
+ accountId?: string;
668
+ }): Promise<void>;
669
+ //#endregion
670
+ //#region src/messaging/shared/message-lookup.d.ts
671
+ /**
672
+ * Normalised information about a Feishu message, returned by
673
+ * {@link getMessageFeishu}.
674
+ */
675
+ interface FeishuMessageInfo {
676
+ /** Unique Feishu message ID. */
677
+ messageId: string;
678
+ /** Chat ID where the message lives. */
679
+ chatId: string;
680
+ /** Chat type ("p2p" or "group"), when available in the API response. */
681
+ chatType?: string;
682
+ /** Open ID of the sender (if available). */
683
+ senderId?: string;
684
+ /** Display name of the sender (resolved from user-name cache). */
685
+ senderName?: string;
686
+ /** Feishu sender type: "user" for human users, "app" for bots/apps. */
687
+ senderType?: string;
688
+ /** The parsed text / content of the message. */
689
+ content: string;
690
+ /** Feishu content type indicator (text, post, image, interactive, ...). */
691
+ contentType: string;
692
+ /** Unix-millisecond timestamp of when the message was created. */
693
+ createTime?: number;
694
+ /** Thread ID if the message belongs to a thread (omt_xxx format). */
695
+ threadId?: string;
696
+ }
697
+ /**
698
+ * Retrieve a single message by its ID from the Feishu IM API.
699
+ *
700
+ * Returns a normalised {@link FeishuMessageInfo} object, or `null` if the
701
+ * message cannot be found or the API returns an error.
702
+ *
703
+ * @param params.cfg - Plugin configuration with Feishu credentials.
704
+ * @param params.messageId - The message ID to fetch.
705
+ * @param params.accountId - Optional account identifier for multi-account setups.
706
+ */
707
+ declare function getMessageFeishu(params: {
708
+ cfg: OpenClawConfig;
709
+ messageId: string;
710
+ accountId?: string; /** When true, merge_forward content is recursively expanded via API. */
711
+ expandForward?: boolean;
712
+ }): Promise<FeishuMessageInfo | null>;
713
+ //#endregion
714
+ //#region src/messaging/outbound/media.d.ts
715
+ /**
716
+ * Result of uploading an image to Feishu.
717
+ */
718
+ interface UploadImageResult {
719
+ /** The image_key assigned by Feishu, used to reference the image. */
720
+ imageKey: string;
721
+ }
722
+ /**
723
+ * Result of uploading a file to Feishu.
724
+ */
725
+ interface UploadFileResult {
726
+ /** The file_key assigned by Feishu, used to reference the file. */
727
+ fileKey: string;
728
+ }
729
+ /**
730
+ * Result of sending a media (image or file) message.
731
+ */
732
+ interface SendMediaResult {
733
+ /** Platform-assigned message ID. */
734
+ messageId: string;
735
+ /** Chat ID where the media was sent. */
736
+ chatId: string;
737
+ }
738
+ /**
739
+ * Upload an image to Feishu IM storage.
740
+ *
741
+ * Accepts either a Buffer containing the raw image bytes or a file
742
+ * system path to read from.
743
+ *
744
+ * @param params.cfg - Plugin configuration.
745
+ * @param params.image - A Buffer or local file path for the image.
746
+ * @param params.imageType - The image usage type: "message" (default) or "avatar".
747
+ * @param params.accountId - Optional account identifier.
748
+ * @returns The assigned image_key.
749
+ */
750
+ declare function uploadImageLark(params: {
751
+ cfg: OpenClawConfig;
752
+ image: Buffer | string;
753
+ imageType?: 'message' | 'avatar';
754
+ accountId?: string;
755
+ }): Promise<UploadImageResult>;
756
+ /**
757
+ * Upload a file to Feishu IM storage.
758
+ *
759
+ * @param params.cfg - Plugin configuration.
760
+ * @param params.file - A Buffer or local file path.
761
+ * @param params.fileName - The display name of the file.
762
+ * @param params.fileType - Feishu file type: "opus" | "mp4" | "pdf" | "doc" | "xls" | "ppt" | "stream".
763
+ * @param params.duration - Duration in milliseconds (for audio/video files).
764
+ * @param params.accountId - Optional account identifier.
765
+ * @returns The assigned file_key.
766
+ */
767
+ declare function uploadFileLark(params: {
768
+ cfg: OpenClawConfig;
769
+ file: Buffer | string;
770
+ fileName: string;
771
+ fileType: 'opus' | 'mp4' | 'pdf' | 'doc' | 'xls' | 'ppt' | 'stream';
772
+ duration?: number;
773
+ accountId?: string;
774
+ }): Promise<UploadFileResult>;
775
+ /**
776
+ * Send an image message to a chat or user.
777
+ *
778
+ * @param params.cfg - Plugin configuration.
779
+ * @param params.to - Target identifier.
780
+ * @param params.imageKey - The image_key from a previous upload.
781
+ * @param params.replyToMessageId - Optional message ID for threaded reply.
782
+ * @param params.replyInThread - When true, reply appears in thread.
783
+ * @param params.accountId - Optional account identifier.
784
+ * @returns The send result.
785
+ */
786
+ declare function sendImageLark(params: {
787
+ cfg: OpenClawConfig;
788
+ to: string;
789
+ imageKey: string;
790
+ replyToMessageId?: string;
791
+ replyInThread?: boolean;
792
+ accountId?: string;
793
+ }): Promise<SendMediaResult>;
794
+ /**
795
+ * Send a file message to a chat or user.
796
+ *
797
+ * @param params.cfg - Plugin configuration.
798
+ * @param params.to - Target identifier.
799
+ * @param params.fileKey - The file_key from a previous upload.
800
+ * @param params.replyToMessageId - Optional message ID for threaded reply.
801
+ * @param params.replyInThread - When true, reply appears in thread.
802
+ * @param params.accountId - Optional account identifier.
803
+ * @returns The send result.
804
+ */
805
+ declare function sendFileLark(params: {
806
+ cfg: OpenClawConfig;
807
+ to: string;
808
+ fileKey: string;
809
+ replyToMessageId?: string;
810
+ replyInThread?: boolean;
811
+ accountId?: string;
812
+ }): Promise<SendMediaResult>;
813
+ /**
814
+ * Send an audio message to a chat or user.
815
+ *
816
+ * Uses `msg_type: "audio"` so Feishu renders the message as a playable
817
+ * voice bubble instead of a file attachment.
818
+ *
819
+ * @param params.cfg - Plugin configuration.
820
+ * @param params.to - Target identifier.
821
+ * @param params.fileKey - The file_key from a previous upload.
822
+ * @param params.replyToMessageId - Optional message ID for threaded reply.
823
+ * @param params.replyInThread - When true, reply appears in thread.
824
+ * @param params.accountId - Optional account identifier.
825
+ * @returns The send result.
826
+ */
827
+ declare function sendAudioLark(params: {
828
+ cfg: OpenClawConfig;
829
+ to: string;
830
+ fileKey: string;
831
+ replyToMessageId?: string;
832
+ replyInThread?: boolean;
833
+ accountId?: string;
834
+ }): Promise<SendMediaResult>;
835
+ /**
836
+ * Upload and send a media file (image or general file) in one step.
837
+ *
838
+ * Accepts either a URL (remote or local `file://`) or a raw Buffer.
839
+ * The function determines whether the media is an image (by extension)
840
+ * and uses the appropriate upload/send path.
841
+ *
842
+ * @param params.cfg - Plugin configuration.
843
+ * @param params.to - Target identifier.
844
+ * @param params.mediaUrl - URL of the media (http/https or local path).
845
+ * @param params.mediaBuffer - Raw bytes of the media (alternative to URL).
846
+ * @param params.fileName - File name (used for type detection and display).
847
+ * @param params.replyToMessageId - Optional message ID for threaded reply.
848
+ * @param params.accountId - Optional account identifier.
849
+ * @returns The send result.
850
+ */
851
+ declare function uploadAndSendMediaLark(params: {
852
+ cfg: OpenClawConfig;
853
+ to: string;
854
+ mediaUrl?: string;
855
+ mediaBuffer?: Buffer;
856
+ fileName?: string;
857
+ replyToMessageId?: string;
858
+ replyInThread?: boolean;
859
+ accountId?: string; /** Allowed root directories for local file access (SSRF prevention). */
860
+ mediaLocalRoots?: readonly string[];
861
+ }): Promise<SendMediaResult>;
862
+ //#endregion
863
+ //#region src/messaging/outbound/deliver.d.ts
864
+ /**
865
+ * Parameters for sending a text message via Feishu.
866
+ */
867
+ interface SendTextLarkParams {
868
+ /** Plugin configuration. */
869
+ cfg: OpenClawConfig;
870
+ /** Target identifier (chat_id, open_id, or user_id). */
871
+ to: string;
872
+ /** Message text content (supports Feishu markdown subset). */
873
+ text: string;
874
+ /** When set, the message is sent as a threaded reply. */
875
+ replyToMessageId?: string;
876
+ /** When true, the reply appears in the thread instead of main chat. */
877
+ replyInThread?: boolean;
878
+ /** Thread root id when the reply lives inside a thread; used for sentinel keying. */
879
+ threadId?: string;
880
+ /** Optional account identifier for multi-account setups. */
881
+ accountId?: string;
882
+ }
883
+ /**
884
+ * Send a text message to a Feishu chat or user.
885
+ *
886
+ * Standalone implementation that directly operates the Lark SDK.
887
+ * The text is pre-processed (table conversion, style optimization)
888
+ * and sent as a Feishu "post" message with markdown rendering.
889
+ *
890
+ * If the entire text is a valid Feishu card JSON string (v1 or v2),
891
+ * it is automatically detected and routed to {@link sendCardLark}
892
+ * instead of being sent as plain text.
893
+ *
894
+ * @param params - See {@link SendTextLarkParams}.
895
+ * @returns The message ID and chat ID.
896
+ * @throws {Error} When the target is invalid or the API call fails.
897
+ *
898
+ * @example
899
+ * ```ts
900
+ * const result = await sendTextLark({
901
+ * cfg,
902
+ * to: "oc_xxx",
903
+ * text: "Hello from Feishu",
904
+ * });
905
+ * ```
906
+ */
907
+ declare function sendTextLark(params: SendTextLarkParams): Promise<FeishuSendResult>;
908
+ /**
909
+ * Parameters for sending an interactive card message via Feishu.
910
+ */
911
+ interface SendCardLarkParams {
912
+ /** Plugin configuration. */
913
+ cfg: OpenClawConfig;
914
+ /** Target identifier (chat_id, open_id, or user_id). */
915
+ to: string;
916
+ /**
917
+ * Complete card JSON object (v1 Message Card or v2 CardKit).
918
+ *
919
+ * - **v1**: top-level `config`, `header`, `elements`.
920
+ * - **v2**: `schema: "2.0"`, `config`, `header`, `body.elements`.
921
+ *
922
+ * The Feishu server determines the version by the presence of
923
+ * `schema: "2.0"`.
924
+ */
925
+ card: Record<string, unknown>;
926
+ /** When set, the card is sent as a threaded reply. */
927
+ replyToMessageId?: string;
928
+ /** When true, the reply appears in the thread instead of main chat. */
929
+ replyInThread?: boolean;
930
+ /** Optional account identifier for multi-account setups. */
931
+ accountId?: string;
932
+ }
933
+ /**
934
+ * Send an interactive card message to a Feishu chat or user.
935
+ *
936
+ * Supports both v1 (Message Card) and v2 (CardKit) card formats.
937
+ * The card JSON is serialised and sent as `msg_type: "interactive"`.
938
+ *
939
+ * @param params - See {@link SendCardLarkParams}.
940
+ * @returns The message ID and chat ID.
941
+ * @throws {Error} When the target is invalid or the API call fails.
942
+ *
943
+ * @example
944
+ * ```ts
945
+ * // v1 card
946
+ * const result = await sendCardLark({
947
+ * cfg,
948
+ * to: "oc_xxx",
949
+ * card: {
950
+ * config: { wide_screen_mode: true },
951
+ * header: { title: { tag: "plain_text", content: "Hello" }, template: "blue" },
952
+ * elements: [{ tag: "div", text: { tag: "lark_md", content: "world" } }],
953
+ * },
954
+ * });
955
+ *
956
+ * // v2 card
957
+ * const result2 = await sendCardLark({
958
+ * cfg,
959
+ * to: "oc_xxx",
960
+ * card: {
961
+ * schema: "2.0",
962
+ * config: { wide_screen_mode: true },
963
+ * body: { elements: [{ tag: "markdown", content: "Hello **world**" }] },
964
+ * },
965
+ * });
966
+ * ```
967
+ */
968
+ declare function sendCardLark(params: SendCardLarkParams): Promise<FeishuSendResult>;
969
+ /**
970
+ * Parameters for sending a single media message via Feishu.
971
+ */
972
+ interface SendMediaLarkParams {
973
+ /** Plugin configuration. */
974
+ cfg: OpenClawConfig;
975
+ /** Target identifier (chat_id, open_id, or user_id). */
976
+ to: string;
977
+ /** Media URL to upload and send. */
978
+ mediaUrl: string;
979
+ /** When set, the message is sent as a threaded reply. */
980
+ replyToMessageId?: string;
981
+ /** When true, the reply appears in the thread instead of main chat. */
982
+ replyInThread?: boolean;
983
+ /** Optional account identifier for multi-account setups. */
984
+ accountId?: string;
985
+ /** Allowed root directories for local file access (SSRF prevention). */
986
+ mediaLocalRoots?: readonly string[];
987
+ }
988
+ /**
989
+ * Send a single media message to a Feishu chat or user.
990
+ *
991
+ * Pure atomic operation — uploads the media and sends it. On upload
992
+ * failure, falls back to sending the URL as a clickable text link.
993
+ *
994
+ * This function does **not** handle leading text or multi-media
995
+ * orchestration; those concerns belong to the adapter's `sendMedia`
996
+ * and `sendPayload` methods.
997
+ *
998
+ * @param params - See {@link SendMediaLarkParams}.
999
+ * @returns The message ID and chat ID of the sent message.
1000
+ * @throws {Error} When the target is invalid or all send attempts fail.
1001
+ *
1002
+ * @example
1003
+ * ```ts
1004
+ * const result = await sendMediaLark({
1005
+ * cfg,
1006
+ * to: "oc_xxx",
1007
+ * mediaUrl: "https://example.com/image.png",
1008
+ * });
1009
+ * ```
1010
+ */
1011
+ declare function sendMediaLark(params: SendMediaLarkParams): Promise<FeishuSendResult>;
1012
+ //#endregion
1013
+ //#region src/messaging/outbound/outbound.d.ts
1014
+ /**
1015
+ * Channel-specific payload for Feishu, carried in `ReplyPayload.channelData.feishu`.
1016
+ *
1017
+ * Callers (skills, tools, programmatic code) populate this structure to send
1018
+ * Feishu-native content that the standard text/media path cannot express.
1019
+ *
1020
+ * Both card v1 (Message Card) and v2 (CardKit) formats are supported.
1021
+ * The Feishu server distinguishes the version by the presence of `schema: "2.0"`.
1022
+ *
1023
+ * @example
1024
+ * ```ts
1025
+ * // --- v1 Message Card (default) ---
1026
+ * const v1Reply: ReplyPayload = {
1027
+ * channelData: {
1028
+ * feishu: {
1029
+ * card: {
1030
+ * config: { wide_screen_mode: true },
1031
+ * header: {
1032
+ * title: { tag: "plain_text", content: "Task Created" },
1033
+ * template: "green",
1034
+ * },
1035
+ * elements: [
1036
+ * { tag: "div", text: { tag: "lark_md", content: "**Title:** Fix login bug" } },
1037
+ * { tag: "action", actions: [
1038
+ * { tag: "button", text: { tag: "plain_text", content: "View" }, type: "primary", url: "https://..." },
1039
+ * ]},
1040
+ * ],
1041
+ * },
1042
+ * },
1043
+ * },
1044
+ * };
1045
+ *
1046
+ * // --- v2 CardKit ---
1047
+ * const v2Reply: ReplyPayload = {
1048
+ * channelData: {
1049
+ * feishu: {
1050
+ * card: {
1051
+ * schema: "2.0",
1052
+ * config: { wide_screen_mode: true },
1053
+ * header: {
1054
+ * title: { tag: "plain_text", content: "Task Created" },
1055
+ * template: "green",
1056
+ * },
1057
+ * body: {
1058
+ * elements: [
1059
+ * { tag: "markdown", content: "**Title:** Fix login bug" },
1060
+ * ],
1061
+ * },
1062
+ * },
1063
+ * },
1064
+ * },
1065
+ * };
1066
+ * ```
1067
+ */
1068
+ interface FeishuChannelData {
1069
+ /**
1070
+ * A complete Feishu interactive card JSON object (v1 or v2).
1071
+ *
1072
+ * The card is sent as-is via `msg_type: "interactive"`. The Feishu server
1073
+ * uses the presence of `schema: "2.0"` to determine the card version.
1074
+ *
1075
+ * **v1 (Message Card)** — default when no `schema` field is present.
1076
+ * Top-level fields: `config`, `header`, `elements`.
1077
+ * Element tags: `div`, `action`, `button`, `button_group`, `note`,
1078
+ * `img`, `hr`, `column_set`, `markdown` (limited), `lark_md` (in div.text).
1079
+ *
1080
+ * **v2 (CardKit)** — activated by `schema: "2.0"`.
1081
+ * Top-level fields: `schema`, `config`, `header`, `body.elements`.
1082
+ * Element tags: `markdown`, `plain_text`, `hr`, `collapsible_panel`,
1083
+ * `column_set`, `table`, `image`, `button`, `select_static`, `overflow`.
1084
+ * Not supported in v2: `action`, `button_group`, `note`, `div` + `lark_md`.
1085
+ *
1086
+ * @see https://open.larkoffice.com/document/feishu-cards/card-json-v2-structure (v2)
1087
+ * @see https://open.feishu.cn/document/uAjLw4CM/ukzMukzMukzM/feishu-cards/card-components (v1)
1088
+ */
1089
+ card?: Record<string, unknown>;
1090
+ }
1091
+ //#endregion
1092
+ //#region src/channel/probe.d.ts
1093
+ /**
1094
+ * Probe the Feishu bot connection by calling the bot/v3/info API.
1095
+ *
1096
+ * Returns a result indicating whether the bot is reachable and its
1097
+ * basic identity (name, open_id). Used by onboarding and status
1098
+ * checks to verify credentials before committing them to config.
1099
+ */
1100
+ declare function probeFeishu(credentials?: LarkClientCredentials): Promise<FeishuProbeResult>;
1101
+ //#endregion
1102
+ //#region src/messaging/outbound/reactions.d.ts
1103
+ /**
1104
+ * Represents a single reaction on a Feishu message.
1105
+ */
1106
+ interface FeishuReaction {
1107
+ /** Unique reaction ID assigned by the platform. */
1108
+ reactionId: string;
1109
+ /** The emoji type string (e.g. "THUMBSUP", "HEART"). */
1110
+ emojiType: string;
1111
+ /** Whether the reaction was added by an app or a human user. */
1112
+ operatorType: 'app' | 'user';
1113
+ /** Open ID of the operator who added the reaction. */
1114
+ operatorId: string;
1115
+ }
1116
+ /**
1117
+ * Well-known Feishu emoji type strings.
1118
+ *
1119
+ * This is a convenience map so consumers do not need to memorise the
1120
+ * exact string identifiers. It is intentionally non-exhaustive --
1121
+ * Feishu supports many more emoji types. Any valid emoji type string
1122
+ * can be passed directly to the API functions.
1123
+ */
1124
+ declare const FeishuEmoji: {
1125
+ readonly THUMBSUP: "THUMBSUP";
1126
+ readonly THUMBSDOWN: "THUMBSDOWN";
1127
+ readonly HEART: "HEART";
1128
+ readonly SMILE: "SMILE";
1129
+ readonly JOYFUL: "JOYFUL";
1130
+ readonly FROWN: "FROWN";
1131
+ readonly BLUSH: "BLUSH";
1132
+ readonly OK: "OK";
1133
+ readonly CLAP: "CLAP";
1134
+ readonly FIREWORKS: "FIREWORKS";
1135
+ readonly PARTY: "PARTY";
1136
+ readonly MUSCLE: "MUSCLE";
1137
+ readonly FIRE: "FIRE";
1138
+ readonly EYES: "EYES";
1139
+ readonly THINKING: "THINKING";
1140
+ readonly PRAISE: "PRAISE";
1141
+ readonly PRAY: "PRAY";
1142
+ readonly ROCKET: "ROCKET";
1143
+ readonly DONE: "DONE";
1144
+ readonly SKULL: "SKULL";
1145
+ readonly HUNDREDPOINTS: "HUNDREDPOINTS";
1146
+ readonly FACEPALM: "FACEPALM";
1147
+ readonly CHECK: "CHECK";
1148
+ readonly CROSSMARK: "CrossMark";
1149
+ readonly COOL: "COOL";
1150
+ readonly TYPING: "Typing";
1151
+ readonly SPEECHLESS: "SPEECHLESS";
1152
+ };
1153
+ /**
1154
+ * Complete set of valid Feishu emoji type strings for reactions.
1155
+ *
1156
+ * Sourced from the official Feishu emoji documentation.
1157
+ * Unlike `FeishuEmoji` (a convenience subset), this set is exhaustive
1158
+ * and can be used for validation and error reporting.
1159
+ *
1160
+ * @see https://go.feishu.cn/s/670vFWbA804
1161
+ */
1162
+ declare const VALID_FEISHU_EMOJI_TYPES: ReadonlySet<string>;
1163
+ /**
1164
+ * Add an emoji reaction to a Feishu message.
1165
+ *
1166
+ * @param params.cfg - Plugin configuration with Feishu credentials.
1167
+ * @param params.messageId - The message to react to.
1168
+ * @param params.emojiType - The emoji type string (e.g. "THUMBSUP").
1169
+ * @param params.accountId - Optional account identifier for multi-account setups.
1170
+ * @returns An object containing the platform-assigned reaction ID.
1171
+ */
1172
+ declare function addReactionFeishu(params: {
1173
+ cfg: OpenClawConfig;
1174
+ messageId: string;
1175
+ emojiType: string;
1176
+ accountId?: string;
1177
+ }): Promise<{
1178
+ reactionId: string;
1179
+ }>;
1180
+ /**
1181
+ * Remove a specific reaction from a Feishu message by its reaction ID.
1182
+ *
1183
+ * Unlike the outbound module's `removeReaction` (which looks up the
1184
+ * reaction by emoji type), this function takes the exact reaction ID
1185
+ * for direct deletion.
1186
+ *
1187
+ * @param params.cfg - Plugin configuration with Feishu credentials.
1188
+ * @param params.messageId - The message the reaction belongs to.
1189
+ * @param params.reactionId - The platform-assigned reaction ID to delete.
1190
+ * @param params.accountId - Optional account identifier for multi-account setups.
1191
+ */
1192
+ declare function removeReactionFeishu(params: {
1193
+ cfg: OpenClawConfig;
1194
+ messageId: string;
1195
+ reactionId: string;
1196
+ accountId?: string;
1197
+ }): Promise<void>;
1198
+ /**
1199
+ * List reactions on a Feishu message, optionally filtered by emoji type.
1200
+ *
1201
+ * Paginates through all results and returns a flat array of
1202
+ * {@link FeishuReaction} objects.
1203
+ *
1204
+ * @param params.cfg - Plugin configuration with Feishu credentials.
1205
+ * @param params.messageId - The message whose reactions to list.
1206
+ * @param params.emojiType - Optional emoji type filter (e.g. "THUMBSUP").
1207
+ * When omitted, all reaction types are returned.
1208
+ * @param params.accountId - Optional account identifier for multi-account setups.
1209
+ * @returns An array of reactions matching the criteria.
1210
+ */
1211
+ declare function listReactionsFeishu(params: {
1212
+ cfg: OpenClawConfig;
1213
+ messageId: string;
1214
+ emojiType?: string;
1215
+ accountId?: string;
1216
+ }): Promise<FeishuReaction[]>;
1217
+ //#endregion
1218
+ //#region src/messaging/outbound/forward.d.ts
1219
+ /**
1220
+ * Forward an existing message to another chat or user.
1221
+ *
1222
+ * @param params.cfg - Plugin configuration with Feishu credentials.
1223
+ * @param params.messageId - The message ID to forward.
1224
+ * @param params.to - Target identifier (chat_id, open_id, or user_id).
1225
+ * @param params.accountId - Optional account identifier for multi-account setups.
1226
+ * @returns The send result containing the new forwarded message ID.
1227
+ */
1228
+ declare function forwardMessageFeishu(params: {
1229
+ cfg: OpenClawConfig;
1230
+ messageId: string;
1231
+ to: string;
1232
+ accountId?: string;
1233
+ }): Promise<FeishuSendResult>;
1234
+ //#endregion
1235
+ //#region src/messaging/outbound/chat-manage.d.ts
1236
+ interface FeishuChatMember {
1237
+ /** Member ID (open_id by default). */
1238
+ memberId: string;
1239
+ /** Display name of the member. */
1240
+ name: string;
1241
+ /** ID type: "open_id", "union_id", or "user_id". */
1242
+ memberIdType: string;
1243
+ }
1244
+ /**
1245
+ * Update chat settings such as name or avatar.
1246
+ */
1247
+ declare function updateChatFeishu(params: {
1248
+ cfg: OpenClawConfig;
1249
+ chatId: string;
1250
+ name?: string;
1251
+ avatar?: string;
1252
+ accountId?: string;
1253
+ }): Promise<void>;
1254
+ /**
1255
+ * Add members to a chat by their open_id list.
1256
+ */
1257
+ declare function addChatMembersFeishu(params: {
1258
+ cfg: OpenClawConfig;
1259
+ chatId: string;
1260
+ memberIds: string[];
1261
+ accountId?: string;
1262
+ }): Promise<void>;
1263
+ /**
1264
+ * Remove members from a chat by their open_id list.
1265
+ */
1266
+ declare function removeChatMembersFeishu(params: {
1267
+ cfg: OpenClawConfig;
1268
+ chatId: string;
1269
+ memberIds: string[];
1270
+ accountId?: string;
1271
+ }): Promise<void>;
1272
+ /**
1273
+ * List members of a chat.
1274
+ *
1275
+ * Returns a single page (up to 100 members) to avoid unnecessary data
1276
+ * overhead for large groups. Use the returned `pageToken` to fetch
1277
+ * subsequent pages when needed.
1278
+ */
1279
+ declare function listChatMembersFeishu(params: {
1280
+ cfg: OpenClawConfig;
1281
+ chatId: string;
1282
+ accountId?: string; /** Optional page token for pagination. */
1283
+ pageToken?: string;
1284
+ }): Promise<{
1285
+ members: FeishuChatMember[];
1286
+ pageToken?: string;
1287
+ hasMore: boolean;
1288
+ }>;
1289
+ //#endregion
1290
+ //#region src/messaging/outbound/actions.d.ts
1291
+ declare const feishuMessageActions: ChannelMessageActionAdapter;
1292
+ //#endregion
1293
+ //#region src/messaging/inbound/mention.d.ts
1294
+ /** Whether the receiving bot itself was @-mentioned. */
1295
+ declare function mentionedBot(ctx: MessageContext): boolean;
1296
+ /** All mentions excluding the receiving bot itself. */
1297
+ declare function nonBotMentions(ctx: MessageContext): MentionInfo[];
1298
+ /**
1299
+ * Remove all @mention placeholder keys from the message text.
1300
+ */
1301
+ declare function extractMessageBody(text: string, allMentionKeys: string[]): string;
1302
+ /**
1303
+ * Format a mention for a Feishu text / post message.
1304
+ * @returns e.g. `<at user_id="ou_xxx">Alice</at>`
1305
+ */
1306
+ declare function formatMentionForText(target: MentionInfo): string;
1307
+ /** Format an @everyone mention for text / post. */
1308
+ declare function formatMentionAllForText(): string;
1309
+ /**
1310
+ * Format a mention for a Feishu Interactive Card.
1311
+ * @returns e.g. `<at id=ou_xxx></at>`
1312
+ */
1313
+ declare function formatMentionForCard(target: MentionInfo): string;
1314
+ /** Format an @everyone mention for card. */
1315
+ declare function formatMentionAllForCard(): string;
1316
+ /** Prepend @mention tags (text format) to a message body. */
1317
+ declare function buildMentionedMessage(targets: MentionInfo[], message: string): string;
1318
+ /** Prepend @mention tags (card format) to card markdown content. */
1319
+ declare function buildMentionedCardContent(targets: MentionInfo[], message: string): string;
1320
+ //#endregion
1321
+ //#region src/channel/plugin.d.ts
1322
+ declare const feishuPlugin: ChannelPlugin<LarkAccount>;
1323
+ //#endregion
1324
+ //#region src/messaging/inbound/reaction-handler.d.ts
1325
+ interface ReactionContext {
1326
+ /** Real chatId (from message API, or `p2p:${operatorOpenId}` fallback). */
1327
+ chatId: string;
1328
+ /** Resolved chat type. */
1329
+ chatType: 'p2p' | 'group';
1330
+ /** Thread ID from the fetched message, if any. */
1331
+ threadId?: string;
1332
+ /** Whether the chat is thread-capable (topic or thread-mode group). */
1333
+ threadCapable?: boolean;
1334
+ /** Fetched message info used to build the synthetic event. */
1335
+ msg: FeishuMessageInfo;
1336
+ }
1337
+ declare function handleFeishuReaction(params: {
1338
+ cfg: OpenClawConfig;
1339
+ event: FeishuReactionCreatedEvent;
1340
+ botOpenId?: string;
1341
+ runtime?: RuntimeEnv;
1342
+ chatHistories?: Map<string, HistoryEntry[]>;
1343
+ accountId?: string; /** Pre-resolved context from resolveReactionContext(). */
1344
+ preResolved: ReactionContext;
1345
+ }): Promise<void>;
1346
+ //#endregion
1347
+ //#region src/messaging/inbound/parse.d.ts
1348
+ /**
1349
+ * Parse a raw Feishu message event into a normalised MessageContext.
1350
+ *
1351
+ * @param expandCtx When provided, cfg/accountId are used to create
1352
+ * callbacks for async converters (e.g. merge_forward)
1353
+ * to fetch sub-messages and resolve sender names.
1354
+ */
1355
+ declare function parseMessageEvent(event: FeishuMessageEvent, botOpenId?: string, expandCtx?: {
1356
+ /** account 级别的 OpenClawConfig(channels.feishu 已替换为 per-account 合并后的配置) */cfg: OpenClawConfig;
1357
+ accountId?: string;
1358
+ }): Promise<MessageContext>;
1359
+ //#endregion
1360
+ //#region src/messaging/inbound/gate.d.ts
1361
+ interface GateResult {
1362
+ allowed: boolean;
1363
+ reason?: string;
1364
+ /** When a group message is rejected due to missing bot mention, the
1365
+ * caller should record this entry into the chat history map. */
1366
+ historyEntry?: HistoryEntry;
1367
+ }
1368
+ /**
1369
+ * Check whether an inbound message passes all access-control gates.
1370
+ *
1371
+ * The DM gate is async because it may read from the pairing store
1372
+ * and send pairing request messages.
1373
+ */
1374
+ declare function checkMessageGate(params: {
1375
+ ctx: MessageContext;
1376
+ accountFeishuCfg?: FeishuConfig;
1377
+ account: LarkAccount; /** account 级别的 OpenClawConfig(channels.feishu 已替换为 per-account 合并后的配置) */
1378
+ accountScopedCfg?: OpenClawConfig;
1379
+ log: (...args: unknown[]) => void;
1380
+ /**
1381
+ * When true, treat the mention requirement as already satisfied (e.g. a card
1382
+ * click is itself an explicit user action targeting the bot). Group/DM
1383
+ * admission and sender-allowlist checks still run — this only bypasses the
1384
+ * "must @-mention the bot" requirement, not access control.
1385
+ */
1386
+ mentionSatisfied?: boolean;
1387
+ }): Promise<GateResult>;
1388
+ //#endregion
1389
+ //#region index.d.ts
1390
+ declare const plugin: {
1391
+ id: string;
1392
+ name: string;
1393
+ description: string;
1394
+ configSchema: openclaw_plugin_sdk_core0.OpenClawPluginConfigSchema;
1395
+ register(api: OpenClawPluginApi): void;
1396
+ };
1397
+ //#endregion
1398
+ export { type FeishuChannelData, FeishuEmoji, type FeishuMessageContext, type FeishuReactionCreatedEvent, type MentionInfo, type MessageContext, type RawMessage, type RawSender, type SendCardLarkParams, type SendMediaLarkParams, type SendTextLarkParams, VALID_FEISHU_EMOJI_TYPES, addChatMembersFeishu, addReactionFeishu, buildMentionedCardContent, buildMentionedMessage, checkMessageGate, plugin as default, editMessageFeishu, extractMessageBody, feishuMessageActions, feishuPlugin, formatMentionAllForCard, formatMentionAllForText, formatMentionForCard, formatMentionForText, forwardMessageFeishu, getMessageFeishu, handleFeishuReaction, isMessageExpired, listChatMembersFeishu, listReactionsFeishu, mentionedBot, monitorFeishuProvider, nonBotMentions, parseMessageEvent, probeFeishu, removeChatMembersFeishu, removeReactionFeishu, sendAudioLark, sendCardFeishu, sendCardLark, sendFileLark, sendImageLark, sendMediaLark, sendMessageFeishu, sendTextLark, updateCardFeishu, updateChatFeishu, uploadAndSendMediaLark, uploadFileLark, uploadImageLark };