@openclaw/feishu 2026.7.2-beta.1 → 2026.7.2-beta.3

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.
@@ -1,4 +1,4 @@
1
- import { t as probeFeishu } from "./probe-CAloGqgG.js";
1
+ import { t as probeFeishu } from "./probe-BgboTHIn.js";
2
2
  import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
3
3
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  //#region extensions/feishu/src/monitor-startup-timeout.ts
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
- import { r as createFeishuClient } from "./client-BUC-R2Wi.js";
2
+ import { r as createFeishuClient } from "./client-87BmeMpj.js";
3
3
  import { asDateTimestampMs, resolveExpiresAtMsFromDurationMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
4
4
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
5
5
  //#region extensions/feishu/src/async.ts
@@ -1,4 +1,5 @@
1
- import { collectConditionalChannelFieldAssignments, collectSecretInputAssignment, createChannelSecretTargetRegistryEntries, getChannelSurface, hasConfiguredSecretInputValue, hasOwnProperty, isBaseFieldActiveForChannelSurface, normalizeSecretStringValue } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
1
+ import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
2
+ import { collectConditionalChannelFieldAssignments, createChannelSecretTargetRegistryEntries, getChannelSurface, hasConfiguredSecretInputValue, hasOwnProperty, normalizeSecretStringValue } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
2
3
  //#region extensions/feishu/src/secret-contract.ts
3
4
  const secretTargetRegistryEntries = createChannelSecretTargetRegistryEntries({
4
5
  channelKey: "feishu",
@@ -17,34 +18,24 @@ function collectRuntimeConfigAssignments(params) {
17
18
  const resolved = getChannelSurface(params.config, "feishu");
18
19
  if (!resolved) return;
19
20
  const { channel: feishu, surface } = resolved;
20
- const topLevelAppSecretActive = surface.channelEnabled && hasConfiguredSecretInputValue(feishu.appId, params.defaults) && hasConfiguredSecretInputValue(feishu.appSecret, params.defaults) || isBaseFieldActiveForChannelSurface(surface, "appSecret");
21
- collectSecretInputAssignment({
22
- value: feishu.appSecret,
23
- path: "channels.feishu.appSecret",
24
- expected: "string",
21
+ if (surface.channelEnabled && hasConfiguredSecretInputValue(feishu.appId, params.defaults) && hasConfiguredSecretInputValue(feishu.appSecret, params.defaults) && surface.hasExplicitAccounts && !surface.accounts.some(({ accountId }) => normalizeAccountId(accountId) === DEFAULT_ACCOUNT_ID)) surface.accounts.push({
22
+ accountId: "default",
23
+ account: {},
24
+ enabled: true
25
+ });
26
+ collectConditionalChannelFieldAssignments({
27
+ channelKey: "feishu",
28
+ field: "appSecret",
29
+ channel: feishu,
30
+ surface,
25
31
  defaults: params.defaults,
26
32
  context: params.context,
27
- active: topLevelAppSecretActive,
28
- inactiveReason: "no enabled account inherits this top-level Feishu appSecret.",
29
- apply: (value) => {
30
- feishu.appSecret = value;
31
- }
33
+ topLevelActiveWithoutAccounts: surface.channelEnabled,
34
+ topLevelInheritedAccountActive: ({ account, enabled }) => enabled && !hasOwnProperty(account, "appSecret"),
35
+ accountActive: ({ enabled }) => enabled,
36
+ topInactiveReason: "no enabled account inherits this top-level Feishu appSecret.",
37
+ accountInactiveReason: "Feishu account is disabled."
32
38
  });
33
- if (surface.hasExplicitAccounts) for (const { accountId, account, enabled } of surface.accounts) {
34
- if (!hasOwnProperty(account, "appSecret")) continue;
35
- collectSecretInputAssignment({
36
- value: account.appSecret,
37
- path: `channels.feishu.accounts.${accountId}.appSecret`,
38
- expected: "string",
39
- defaults: params.defaults,
40
- context: params.context,
41
- active: enabled,
42
- inactiveReason: "Feishu account is disabled.",
43
- apply: (value) => {
44
- account.appSecret = value;
45
- }
46
- });
47
- }
48
39
  const baseConnectionMode = normalizeSecretStringValue(feishu.connectionMode) === "webhook" ? "webhook" : "websocket";
49
40
  const resolveAccountMode = (account) => hasOwnProperty(account, "connectionMode") ? normalizeSecretStringValue(account.connectionMode) : baseConnectionMode;
50
41
  collectConditionalChannelFieldAssignments({
@@ -1,2 +1,2 @@
1
- import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-DnlMcrn5.js";
1
+ import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-BCpDLdg9.js";
2
2
  export { channelSecrets, collectRuntimeConfigAssignments, secretTargetRegistryEntries };
@@ -1,18 +1,19 @@
1
1
  import { d as isRecord$1, h as requestFeishuApi, s as resolveFeishuRuntimeAccount } from "./accounts-BDoGHJDk.js";
2
2
  import { i as resolveReceiveIdType, r as normalizeFeishuTarget } from "./targets-BUjQ1TcA.js";
3
- import { c as assertFeishuPostWithinEnvelope, f as materializeFeishuPostMarkdownSoftBreaks, i as toFeishuSendResult, l as buildFeishuPostMessageContent, o as resolveFeishuCardTemplate, r as resolveFeishuReceiptKind, t as assertFeishuMessageApiSuccess } from "./send-result-CPS7AozW.js";
3
+ import { c as assertFeishuPostWithinEnvelope, f as materializeFeishuPostMarkdownSoftBreaks, i as toFeishuSendResult, l as buildFeishuPostMessageContent, o as resolveFeishuCardTemplate, r as resolveFeishuReceiptKind, t as assertFeishuMessageApiSuccess } from "./send-result-DfE5Fhz6.js";
4
+ import { r as createFeishuClient } from "./client-87BmeMpj.js";
4
5
  import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
5
- import { r as createFeishuClient } from "./client-BUC-R2Wi.js";
6
6
  import { parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
7
7
  import { isRecord, normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
8
8
  import { convertMarkdownTables } from "openclaw/plugin-sdk/text-chunking";
9
9
  import fs from "node:fs";
10
10
  import path from "node:path";
11
- import { mediaKindFromMime } from "openclaw/plugin-sdk/media-mime";
12
11
  import { MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS, runFfmpeg, runFfprobe } from "openclaw/plugin-sdk/media-runtime";
12
+ import { isBlockedHostnameOrIp, resolvePinnedHostnameWithPolicy } from "openclaw/plugin-sdk/ssrf-runtime";
13
13
  import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
14
14
  import { readRegularFile, writeExternalFileWithinRoot } from "openclaw/plugin-sdk/security-runtime";
15
15
  import { Readable } from "node:stream";
16
+ import { mediaKindFromMime } from "openclaw/plugin-sdk/media-mime";
16
17
  import { saveMediaBuffer, saveMediaStream } from "openclaw/plugin-sdk/media-store";
17
18
  import { resolvePreferredOpenClawTmpDir, withTempDownloadPath, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
18
19
  //#region extensions/feishu/src/identity-header.ts
@@ -38,6 +39,33 @@ function resolveFeishuIdentityHeaderTitle(identity) {
38
39
  return (emoji ? `${emoji} ${name}` : name).trim();
39
40
  }
40
41
  //#endregion
42
+ //#region extensions/feishu/src/media-fallback.ts
43
+ const FEISHU_MEDIA_UPLOAD_FAILURE_FALLBACK_TEXT = "Media upload failed. Please try again.";
44
+ function hasAsciiControlCharacter(value) {
45
+ return Array.from(value).some((character) => {
46
+ const code = character.charCodeAt(0);
47
+ return code <= 31 || code === 127;
48
+ });
49
+ }
50
+ async function resolvePublicFeishuMediaReference(value) {
51
+ const raw = value?.trim();
52
+ if (!raw || hasAsciiControlCharacter(raw)) return;
53
+ try {
54
+ const parsed = new URL(raw);
55
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return;
56
+ if (parsed.username || parsed.password || isBlockedHostnameOrIp(parsed.hostname)) return;
57
+ await resolvePinnedHostnameWithPolicy(parsed.hostname);
58
+ return parsed.href;
59
+ } catch {
60
+ return;
61
+ }
62
+ }
63
+ async function buildFeishuMediaFallbackText(params) {
64
+ const mediaUrl = await resolvePublicFeishuMediaReference(params.mediaUrl);
65
+ const attachmentText = mediaUrl ? `${params.mediaLinkStyle === "plain" ? "" : "📎 "}${mediaUrl}` : FEISHU_MEDIA_UPLOAD_FAILURE_FALLBACK_TEXT;
66
+ return [params.text?.trim(), attachmentText].filter(Boolean).join("\n\n");
67
+ }
68
+ //#endregion
41
69
  //#region extensions/feishu/src/external-keys.ts
42
70
  const CONTROL_CHARS_RE = /\p{Cc}/u;
43
71
  const MAX_EXTERNAL_KEY_LENGTH = 512;
@@ -50,6 +78,55 @@ function normalizeFeishuExternalKey(value) {
50
78
  return normalized;
51
79
  }
52
80
  //#endregion
81
+ //#region extensions/feishu/src/media-chunk-idle.ts
82
+ var FeishuInboundMediaTimeoutError = class extends Error {
83
+ constructor(chunkTimeoutMs) {
84
+ super(`Feishu media download stalled: no data received for ${chunkTimeoutMs}ms`);
85
+ this.name = "FeishuInboundMediaTimeoutError";
86
+ this.chunkTimeoutMs = chunkTimeoutMs;
87
+ }
88
+ };
89
+ function destroySource(source) {
90
+ const s = source;
91
+ if (typeof s.destroy === "function") s.destroy();
92
+ }
93
+ function withChunkIdleTimeout(source, chunkTimeoutMs) {
94
+ return { async *[Symbol.asyncIterator]() {
95
+ const iterator = source[Symbol.asyncIterator]();
96
+ let exhausted = false;
97
+ try {
98
+ while (true) {
99
+ const nextPromise = iterator.next();
100
+ let timeoutHandle;
101
+ const timeoutPromise = new Promise((_, reject) => {
102
+ timeoutHandle = setTimeout(() => {
103
+ reject(new FeishuInboundMediaTimeoutError(chunkTimeoutMs));
104
+ try {
105
+ destroySource(source);
106
+ } catch {}
107
+ }, chunkTimeoutMs);
108
+ });
109
+ let result;
110
+ try {
111
+ result = await Promise.race([nextPromise, timeoutPromise]);
112
+ } finally {
113
+ if (timeoutHandle !== void 0) clearTimeout(timeoutHandle);
114
+ }
115
+ if (result.done) {
116
+ exhausted = true;
117
+ return;
118
+ }
119
+ yield result.value;
120
+ }
121
+ } finally {
122
+ if (!exhausted && typeof iterator.return === "function") iterator.return().catch(() => void 0);
123
+ }
124
+ } };
125
+ }
126
+ function saveMediaStreamWithIdleTimeout(stream, contentType, maxBytes, fileName, chunkTimeoutMs) {
127
+ return saveMediaStream(withChunkIdleTimeout(stream, chunkTimeoutMs), contentType, "inbound", maxBytes, fileName);
128
+ }
129
+ //#endregion
53
130
  //#region extensions/feishu/src/send-target.ts
54
131
  function resolveFeishuSendTarget(params) {
55
132
  const target = params.to.trim();
@@ -177,14 +254,15 @@ async function saveFeishuResponseMedia(params) {
177
254
  if (responseWithOptionalFields.code !== void 0 && responseWithOptionalFields.code !== 0) throw new Error(`${params.errorPrefix}: ${responseWithOptionalFields.msg || `code ${responseWithOptionalFields.code}`}`);
178
255
  if (responseWithOptionalFields.data && Buffer.isBuffer(responseWithOptionalFields.data)) return saveMediaBuffer(responseWithOptionalFields.data, contentType, "inbound", maxBytes, fileName);
179
256
  if (responseWithOptionalFields.data instanceof ArrayBuffer) return saveMediaBuffer(Buffer.from(responseWithOptionalFields.data), contentType, "inbound", maxBytes, fileName);
180
- if (typeof response.getReadableStream === "function") return saveMediaStream(response.getReadableStream(), contentType, "inbound", maxBytes, fileName);
257
+ const save = (stream, ct = contentType, mb = maxBytes, fn = fileName) => saveMediaStreamWithIdleTimeout(stream, ct, mb, fn, FEISHU_MEDIA_HTTP_TIMEOUT_MS);
258
+ if (typeof response.getReadableStream === "function") return save(response.getReadableStream());
181
259
  if (typeof response.writeFile === "function") return await withTempDownloadPath({ prefix: params.tmpDirPrefix }, async (tmpPath) => {
182
260
  await response.writeFile(tmpPath);
183
261
  if ((await fs.promises.stat(tmpPath)).size > maxBytes) throw mediaLimitError(maxBytes);
184
- return await saveMediaStream(fs.createReadStream(tmpPath), contentType, "inbound", maxBytes, fileName);
262
+ return await save(fs.createReadStream(tmpPath));
185
263
  });
186
- if (responseWithOptionalFields[Symbol.asyncIterator]) return saveMediaStream(responseWithOptionalFields, contentType, "inbound", maxBytes, fileName);
187
- if (response instanceof Readable) return saveMediaStream(response, contentType, "inbound", maxBytes, fileName);
264
+ if (responseWithOptionalFields[Symbol.asyncIterator]) return save(responseWithOptionalFields);
265
+ if (response instanceof Readable) return save(response);
188
266
  const keys = Object.keys(response);
189
267
  throw new Error(`${params.errorPrefix}: unexpected response format. Keys: [${keys.join(", ")}]`);
190
268
  }
@@ -430,6 +508,7 @@ function normalizeMediaNameForExtension(raw) {
430
508
  }
431
509
  }
432
510
  function shouldSuppressFeishuTextForVoiceMedia(params) {
511
+ if (params.ttsSupplement) return params.ttsSupplement.visibleTextAlreadyDelivered === true;
433
512
  if (params.audioAsVoice === true) return true;
434
513
  if (params.fileName && isFeishuNativeVoiceAudio({
435
514
  fileName: params.fileName,
@@ -1235,4 +1314,4 @@ async function sendMarkdownCardFeishu(params) {
1235
1314
  });
1236
1315
  }
1237
1316
  //#endregion
1238
- export { resolveFeishuIdentityEmoji as _, sendMarkdownCardFeishu as a, parsePostContent as c, isMentionForwardRequest as d, isFeishuGroupChatType as f, normalizeFeishuExternalKey as g, shouldSuppressFeishuTextForVoiceMedia as h, sendCardFeishu as i, extractMentionTargets as l, sendMediaFeishu as m, getMessageFeishu as n, sendMessageFeishu as o, saveMessageResourceFeishu as p, listFeishuThreadMessages as r, sendStructuredCardFeishu as s, editMessageFeishu as t, isFeishuBroadcastMention as u, resolveFeishuIdentityHeaderTitle as v };
1317
+ export { buildFeishuMediaFallbackText as _, sendMarkdownCardFeishu as a, parsePostContent as c, isMentionForwardRequest as d, isFeishuGroupChatType as f, normalizeFeishuExternalKey as g, shouldSuppressFeishuTextForVoiceMedia as h, sendCardFeishu as i, extractMentionTargets as l, sendMediaFeishu as m, getMessageFeishu as n, sendMessageFeishu as o, saveMessageResourceFeishu as p, listFeishuThreadMessages as r, sendStructuredCardFeishu as s, editMessageFeishu as t, isFeishuBroadcastMention as u, resolveFeishuIdentityEmoji as v, resolveFeishuIdentityHeaderTitle as y };
@@ -1,5 +1,6 @@
1
1
  import { d as isRecord$1 } from "./accounts-BDoGHJDk.js";
2
2
  import { r as normalizeFeishuTarget, t as detectIdType } from "./targets-BUjQ1TcA.js";
3
+ import { compileAllowlist, resolveAllowlistMatchByCandidates } from "openclaw/plugin-sdk/allow-from";
3
4
  import { ToolAuthorizationError } from "openclaw/plugin-sdk/channel-actions";
4
5
  import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
5
6
  import { resolveScopeKeyCaseInsensitive, resolveScopeToolsPolicy } from "openclaw/plugin-sdk/channel-policy";
@@ -307,6 +308,9 @@ function normalizeChatId(raw) {
307
308
  if (!raw) return "";
308
309
  return normalizeFeishuTarget(raw) ?? raw.trim();
309
310
  }
311
+ function normalizeFeishuAllowlist(entries) {
312
+ return (entries ?? []).map((entry) => normalizeFeishuAllowEntry(String(entry))).filter(Boolean);
313
+ }
310
314
  function readContextFields(ctx) {
311
315
  if (isActionContext(ctx)) return {
312
316
  accountId: normalizeOptionalString(ctx.accountId),
@@ -350,10 +354,13 @@ function isFeishuGroupReadAllowed(cfg, account, chatId, current) {
350
354
  groupId: chatId
351
355
  });
352
356
  const normalizedChatId = normalizeFeishuAllowEntry(chatId);
353
- return explicitlyConfigured || (account.config.groupAllowFrom ?? []).some((entry) => {
354
- const normalized = normalizeFeishuAllowEntry(String(entry));
355
- return normalized === "*" || normalized === normalizedChatId;
356
- });
357
+ return explicitlyConfigured || resolveAllowlistMatchByCandidates({
358
+ allowList: normalizeFeishuAllowlist(account.config.groupAllowFrom),
359
+ candidates: [{
360
+ value: normalizedChatId,
361
+ source: "id"
362
+ }]
363
+ }).allowed;
357
364
  }
358
365
  function isFeishuGroupReadEnabled(cfg, account, chatId) {
359
366
  if (resolveFeishuReadGroupPolicy(cfg, account) === "disabled") return false;
@@ -363,7 +370,7 @@ function isFeishuGroupReadEnabled(cfg, account, chatId) {
363
370
  })?.enabled !== false;
364
371
  }
365
372
  function isDmUniversallyAllowed(account) {
366
- return (account.config.allowFrom ?? []).some((entry) => normalizeFeishuAllowEntry(String(entry)) === "*");
373
+ return compileAllowlist(normalizeFeishuAllowlist(account.config.allowFrom)).wildcard;
367
374
  }
368
375
  function assertFeishuChatReadAllowed(params) {
369
376
  const authorization = resolveFeishuChatReadPreliminaryAuthorization(params);
@@ -431,7 +438,7 @@ function authorizeFeishuChatMemberRead(params) {
431
438
  }
432
439
  function canEnumerateAllFeishuGroups(cfg, account) {
433
440
  const policy = resolveFeishuReadGroupPolicy(cfg, account);
434
- return policy === "open" || policy === "allowlist" && (account.config.groupAllowFrom ?? []).some((entry) => normalizeFeishuAllowEntry(String(entry)) === "*");
441
+ return policy === "open" || policy === "allowlist" && compileAllowlist(normalizeFeishuAllowlist(account.config.groupAllowFrom)).wildcard;
435
442
  }
436
443
  function canEnumerateAllFeishuPeers(account) {
437
444
  return isDmUniversallyAllowed(account);
@@ -439,6 +446,13 @@ function canEnumerateAllFeishuPeers(account) {
439
446
  //#endregion
440
447
  //#region extensions/feishu/src/markdown.ts
441
448
  const FEISHU_POST_MAX_BYTES = 30 * 1024;
449
+ /** One parser contract for Feishu message and document Markdown decisions. */
450
+ function parseFeishuMarkdown(text) {
451
+ return fromMarkdown(text, {
452
+ extensions: [gfmTable()],
453
+ mdastExtensions: [gfmTableFromMarkdown()]
454
+ });
455
+ }
442
456
  function buildFeishuPostMentionElements(mentions) {
443
457
  if (!mentions?.length) return [];
444
458
  const elements = [];
@@ -465,10 +479,7 @@ function assertFeishuPostWithinEnvelope(content, label) {
465
479
  if (Buffer.byteLength(content, "utf8") > FEISHU_POST_MAX_BYTES) throw new Error(`${label} exceeds the 30 KB rich-post API limit`);
466
480
  }
467
481
  function collectSoftBreakOffsets(text) {
468
- const root = fromMarkdown(text, {
469
- extensions: [gfmTable()],
470
- mdastExtensions: [gfmTableFromMarkdown()]
471
- });
482
+ const root = parseFeishuMarkdown(text);
472
483
  const offsets = [];
473
484
  const pending = [root];
474
485
  while (pending.length > 0) {
@@ -532,13 +543,17 @@ function postContentBytes(messageText, mentions) {
532
543
  * Markdown wrappers and first-chunk mentions count toward the byte budget.
533
544
  */
534
545
  function chunkFeishuPostMarkdown(params) {
535
- const { text, firstChunkMentions } = params;
546
+ const { text, firstChunkMentions, chunkMentions } = params;
536
547
  if (!text) return [];
537
548
  const requestedLimit = Number.isFinite(params.limit) && params.limit > 0 ? Math.floor(params.limit) : text.length;
538
549
  const initialChunks = params.initialChunks ?? chunkFeishuMarkdownWithMode(text, requestedLimit, params.mode ?? "length");
539
550
  const output = [];
551
+ const resolveMentions = (isFirst) => {
552
+ const mentions = [...chunkMentions ?? [], ...isFirst ? firstChunkMentions ?? [] : []];
553
+ return mentions.length > 0 ? mentions : void 0;
554
+ };
540
555
  for (const initialChunk of initialChunks) {
541
- if (postContentBytes(initialChunk, output.length === 0 ? firstChunkMentions : void 0) <= FEISHU_POST_MAX_BYTES) {
556
+ if (postContentBytes(initialChunk, resolveMentions(output.length === 0)) <= FEISHU_POST_MAX_BYTES) {
542
557
  output.push(initialChunk);
543
558
  continue;
544
559
  }
@@ -549,12 +564,12 @@ function chunkFeishuPostMarkdown(params) {
549
564
  let oversizedChunk;
550
565
  let oversizedMentions;
551
566
  for (const [index, chunk] of chunks.entries()) {
552
- const chunkMentions = output.length === 0 && index === 0 ? firstChunkMentions : void 0;
553
- const contentBytes = postContentBytes(chunk, chunkMentions);
567
+ const mentionsForChunk = resolveMentions(output.length === 0 && index === 0);
568
+ const contentBytes = postContentBytes(chunk, mentionsForChunk);
554
569
  largestContentBytes = Math.max(largestContentBytes, contentBytes);
555
570
  if (contentBytes > FEISHU_POST_MAX_BYTES && oversizedChunk === void 0) {
556
571
  oversizedChunk = chunk;
557
- oversizedMentions = chunkMentions;
572
+ oversizedMentions = mentionsForChunk;
558
573
  }
559
574
  }
560
575
  if (oversizedChunk === void 0) {
@@ -763,4 +778,4 @@ function toFeishuSendResult(response, chatId, kind) {
763
778
  };
764
779
  }
765
780
  //#endregion
766
- export { FEISHU_CARD_INTERACTION_VERSION as A, resolveFeishuGroupConfig as C, resolveFeishuReplyPolicy as D, resolveFeishuGroupToolPolicy as E, createFeishuCardInteractionEnvelope as M, decodeFeishuCardAction as N, normalizeFeishuChatType as O, resolveFeishuDmIngressAccess as S, resolveFeishuGroupSenderActivationIngressAccess as T, isFeishuGroupReadAllowed as _, readNativeFeishuCardJson as a, hasExplicitFeishuGroupConfig as b, assertFeishuPostWithinEnvelope as c, chunkFeishuPostMarkdown as d, materializeFeishuPostMarkdownSoftBreaks as f, canEnumerateAllFeishuPeers as g, canEnumerateAllFeishuGroups as h, toFeishuSendResult as i, buildFeishuCardActionTextFallback as j, resolveFeishuChatType as k, buildFeishuPostMessageContent as l, authorizeFeishuChatMemberRead as m, createFeishuSendReceipt as n, resolveFeishuCardTemplate as o, assertFeishuChatReadAllowed as p, resolveFeishuReceiptKind as r, sanitizeNativeFeishuCard as s, assertFeishuMessageApiSuccess as t, chunkFeishuMarkdown as u, isFeishuGroupReadEnabled as v, resolveFeishuGroupConversationIngressAccess as w, normalizeFeishuAllowEntry as x, resolveFeishuChatReadPreliminaryAuthorization as y };
781
+ export { resolveFeishuChatType as A, resolveFeishuDmIngressAccess as C, resolveFeishuGroupToolPolicy as D, resolveFeishuGroupSenderActivationIngressAccess as E, buildFeishuCardActionTextFallback as M, createFeishuCardInteractionEnvelope as N, resolveFeishuReplyPolicy as O, decodeFeishuCardAction as P, normalizeFeishuAllowEntry as S, resolveFeishuGroupConversationIngressAccess as T, canEnumerateAllFeishuPeers as _, readNativeFeishuCardJson as a, resolveFeishuChatReadPreliminaryAuthorization as b, assertFeishuPostWithinEnvelope as c, chunkFeishuPostMarkdown as d, materializeFeishuPostMarkdownSoftBreaks as f, canEnumerateAllFeishuGroups as g, authorizeFeishuChatMemberRead as h, toFeishuSendResult as i, FEISHU_CARD_INTERACTION_VERSION as j, normalizeFeishuChatType as k, buildFeishuPostMessageContent as l, assertFeishuChatReadAllowed as m, createFeishuSendReceipt as n, resolveFeishuCardTemplate as o, parseFeishuMarkdown as p, resolveFeishuReceiptKind as r, sanitizeNativeFeishuCard as s, assertFeishuMessageApiSuccess as t, chunkFeishuMarkdown as u, isFeishuGroupReadAllowed as v, resolveFeishuGroupConfig as w, hasExplicitFeishuGroupConfig as x, isFeishuGroupReadEnabled as y };
package/dist/setup-api.js CHANGED
@@ -1,2 +1,2 @@
1
- import { i as feishuSetupAdapter, n as feishuSetupWizard, t as feishuPlugin } from "./channel-DdPQ2HGh.js";
1
+ import { i as feishuSetupAdapter, n as feishuSetupWizard, t as feishuPlugin } from "./channel-BdnXYU6g.js";
2
2
  export { feishuPlugin, feishuSetupAdapter, feishuSetupWizard };
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@openclaw/feishu",
3
- "version": "2026.7.2-beta.1",
3
+ "version": "2026.7.2-beta.3",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/feishu",
9
- "version": "2026.7.2-beta.1",
9
+ "version": "2026.7.2-beta.3",
10
10
  "dependencies": {
11
11
  "@larksuiteoapi/node-sdk": "1.68.0",
12
12
  "mdast-util-from-markdown": "2.0.3",
@@ -16,7 +16,7 @@
16
16
  "zod": "4.4.3"
17
17
  },
18
18
  "peerDependencies": {
19
- "openclaw": ">=2026.7.2-beta.1"
19
+ "openclaw": ">=2026.7.2-beta.3"
20
20
  },
21
21
  "peerDependenciesMeta": {
22
22
  "openclaw": {
@@ -455,6 +455,12 @@
455
455
  "enabled"
456
456
  ]
457
457
  },
458
+ "allowBots": {
459
+ "type": "boolean"
460
+ },
461
+ "vcAutoJoin": {
462
+ "type": "boolean"
463
+ },
458
464
  "typingIndicator": {
459
465
  "type": "boolean"
460
466
  }
@@ -520,6 +526,12 @@
520
526
  "enabled"
521
527
  ]
522
528
  },
529
+ "allowBots": {
530
+ "type": "boolean"
531
+ },
532
+ "vcAutoJoin": {
533
+ "type": "boolean"
534
+ },
523
535
  "typingIndicator": {
524
536
  "type": "boolean"
525
537
  },
@@ -852,9 +864,10 @@
852
864
  "default": "pairing",
853
865
  "type": "string",
854
866
  "enum": [
855
- "open",
856
867
  "pairing",
857
- "allowlist"
868
+ "allowlist",
869
+ "open",
870
+ "disabled"
858
871
  ]
859
872
  },
860
873
  "allowFrom": {
@@ -876,8 +889,8 @@
876
889
  "type": "string",
877
890
  "enum": [
878
891
  "open",
879
- "allowlist",
880
- "disabled"
892
+ "disabled",
893
+ "allowlist"
881
894
  ]
882
895
  },
883
896
  {
@@ -1177,6 +1190,12 @@
1177
1190
  "default": true,
1178
1191
  "type": "boolean"
1179
1192
  },
1193
+ "allowBots": {
1194
+ "type": "boolean"
1195
+ },
1196
+ "vcAutoJoin": {
1197
+ "type": "boolean"
1198
+ },
1180
1199
  "tts": {
1181
1200
  "type": "object",
1182
1201
  "properties": {
@@ -1612,9 +1631,10 @@
1612
1631
  "dmPolicy": {
1613
1632
  "type": "string",
1614
1633
  "enum": [
1615
- "open",
1616
1634
  "pairing",
1617
- "allowlist"
1635
+ "allowlist",
1636
+ "open",
1637
+ "disabled"
1618
1638
  ]
1619
1639
  },
1620
1640
  "allowFrom": {
@@ -1636,8 +1656,8 @@
1636
1656
  "type": "string",
1637
1657
  "enum": [
1638
1658
  "open",
1639
- "allowlist",
1640
- "disabled"
1659
+ "disabled",
1660
+ "allowlist"
1641
1661
  ]
1642
1662
  },
1643
1663
  {
@@ -1934,6 +1954,12 @@
1934
1954
  "resolveSenderNames": {
1935
1955
  "type": "boolean"
1936
1956
  },
1957
+ "allowBots": {
1958
+ "type": "boolean"
1959
+ },
1960
+ "vcAutoJoin": {
1961
+ "type": "boolean"
1962
+ },
1937
1963
  "tts": {
1938
1964
  "type": "object",
1939
1965
  "properties": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/feishu",
3
- "version": "2026.7.2-beta.1",
3
+ "version": "2026.7.2-beta.3",
4
4
  "description": "OpenClaw Feishu/Lark channel plugin for chats and workplace tools (community maintained by @m1heng).",
5
5
  "repository": {
6
6
  "type": "git",
@@ -16,7 +16,7 @@
16
16
  "zod": "4.4.3"
17
17
  },
18
18
  "peerDependencies": {
19
- "openclaw": ">=2026.7.2-beta.1"
19
+ "openclaw": ">=2026.7.2-beta.3"
20
20
  },
21
21
  "peerDependenciesMeta": {
22
22
  "openclaw": {
@@ -47,10 +47,10 @@
47
47
  "minHostVersion": ">=2026.5.29"
48
48
  },
49
49
  "compat": {
50
- "pluginApi": ">=2026.7.2-beta.1"
50
+ "pluginApi": ">=2026.7.2-beta.3"
51
51
  },
52
52
  "build": {
53
- "openclawVersion": "2026.7.2-beta.1"
53
+ "openclawVersion": "2026.7.2-beta.3"
54
54
  },
55
55
  "release": {
56
56
  "publishToClawHub": true,