@openclaw/feishu 2026.5.28-beta.2 → 2026.5.28-beta.4

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.
package/dist/api.js CHANGED
@@ -2,9 +2,9 @@ import { a as parseFeishuTargetId, i as parseFeishuDirectConversationId, n as bu
2
2
  import { n as getFeishuThreadBindingManager, r as testing, t as createFeishuThreadBindingManager } from "./thread-bindings-D24m3Cjy.js";
3
3
  import { n as handleFeishuSubagentEnded, r as handleFeishuSubagentSpawning, t as handleFeishuSubagentDeliveryTarget } from "./subagent-hooks-fuyBHOVu.js";
4
4
  import { r as listEnabledFeishuAccounts } from "./accounts-CXnY5H8g.js";
5
- import { a as setFeishuNamedAccountEnabled, i as feishuSetupAdapter, n as feishuSetupWizard, r as runFeishuLogin, t as feishuPlugin } from "./channel-BVSJh3s1.js";
5
+ import { a as setFeishuNamedAccountEnabled, i as feishuSetupAdapter, n as feishuSetupWizard, r as runFeishuLogin, t as feishuPlugin } from "./channel-BfeesQob.js";
6
6
  import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
7
- import { a as jsonToolResult, d as registerFeishuChatTools, f as createFeishuToolClient, m as resolveFeishuToolAccount, n as registerFeishuDriveTools, o as toolExecutionErrorResult, p as resolveAnyEnabledFeishuToolsConfig, s as unknownToolActionResult } from "./drive-6Ohn34x9.js";
7
+ import { a as jsonToolResult, d as registerFeishuChatTools, f as createFeishuToolClient, m as resolveFeishuToolAccount, n as registerFeishuDriveTools, o as toolExecutionErrorResult, p as resolveAnyEnabledFeishuToolsConfig, s as unknownToolActionResult } from "./drive-USxqssMG.js";
8
8
  import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, readStringValue, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
9
9
  import { optionalPositiveIntegerSchema } from "openclaw/plugin-sdk/channel-actions";
10
10
  import { existsSync } from "node:fs";
@@ -1,3 +1,4 @@
1
+ import { finiteSecondsToTimerSafeMilliseconds } from "openclaw/plugin-sdk/number-runtime";
1
2
  import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
2
3
  import { renderQrTerminal } from "openclaw/plugin-sdk/media-runtime";
3
4
  //#region extensions/feishu/src/app-registration.ts
@@ -12,6 +13,8 @@ const FEISHU_ACCOUNTS_URL = "https://accounts.feishu.cn";
12
13
  const LARK_ACCOUNTS_URL = "https://accounts.larksuite.com";
13
14
  const REGISTRATION_PATH = "/oauth/v1/app/registration";
14
15
  const REQUEST_TIMEOUT_MS = 1e4;
16
+ const DEFAULT_REGISTRATION_POLL_INTERVAL_SECONDS = 5;
17
+ const DEFAULT_REGISTRATION_EXPIRE_SECONDS = 600;
15
18
  function accountsBaseUrl(domain) {
16
19
  return domain === "lark" ? LARK_ACCOUNTS_URL : FEISHU_ACCOUNTS_URL;
17
20
  }
@@ -67,8 +70,8 @@ async function beginAppRegistration(domain = "feishu") {
67
70
  deviceCode: res.device_code,
68
71
  qrUrl: qrUrl.toString(),
69
72
  userCode: res.user_code,
70
- interval: res.interval || 5,
71
- expireIn: res.expire_in || 600
73
+ interval: finiteSecondsToTimerSafeMilliseconds(res.interval) === void 0 ? DEFAULT_REGISTRATION_POLL_INTERVAL_SECONDS : res.interval,
74
+ expireIn: finiteSecondsToTimerSafeMilliseconds(res.expire_in) === void 0 ? DEFAULT_REGISTRATION_EXPIRE_SECONDS : res.expire_in
72
75
  };
73
76
  }
74
77
  /**
@@ -81,7 +84,8 @@ async function pollAppRegistration(params) {
81
84
  let currentInterval = params.interval;
82
85
  let domain = initialDomain;
83
86
  let domainSwitched = false;
84
- const deadline = Date.now() + expireIn * 1e3;
87
+ const expireInMs = finiteSecondsToTimerSafeMilliseconds(expireIn) ?? finiteSecondsToTimerSafeMilliseconds(DEFAULT_REGISTRATION_EXPIRE_SECONDS) ?? REQUEST_TIMEOUT_MS;
88
+ const deadline = Date.now() + expireInMs;
85
89
  while (Date.now() < deadline) {
86
90
  if (abortSignal?.aborted) return { status: "timeout" };
87
91
  const baseUrl = accountsBaseUrl(domain);
@@ -93,7 +97,7 @@ async function pollAppRegistration(params) {
93
97
  ...tp ? { tp } : {}
94
98
  });
95
99
  } catch {
96
- await sleep(currentInterval * 1e3);
100
+ await sleepRegistrationPollInterval(currentInterval);
97
101
  continue;
98
102
  }
99
103
  if (pollRes.user_info?.tenant_brand) {
@@ -120,7 +124,7 @@ async function pollAppRegistration(params) {
120
124
  status: "error",
121
125
  message: `${pollRes.error}: ${pollRes.error_description ?? "unknown"}`
122
126
  };
123
- await sleep(currentInterval * 1e3);
127
+ await sleepRegistrationPollInterval(currentInterval);
124
128
  }
125
129
  return { status: "timeout" };
126
130
  }
@@ -180,5 +184,8 @@ async function getAppOwnerOpenId(params) {
180
184
  function sleep(ms) {
181
185
  return new Promise((resolve) => setTimeout(resolve, ms));
182
186
  }
187
+ function sleepRegistrationPollInterval(intervalSeconds) {
188
+ return sleep(finiteSecondsToTimerSafeMilliseconds(intervalSeconds) ?? finiteSecondsToTimerSafeMilliseconds(DEFAULT_REGISTRATION_POLL_INTERVAL_SECONDS) ?? REQUEST_TIMEOUT_MS);
189
+ }
183
190
  //#endregion
184
191
  export { beginAppRegistration, getAppOwnerOpenId, initAppRegistration, pollAppRegistration, printQrCode };
@@ -19,6 +19,7 @@ import { createAllowlistProviderGroupPolicyWarningCollector, projectConfigAccoun
19
19
  import { createChannelDirectoryAdapter, createRuntimeDirectoryLiveAdapter, listDirectoryGroupEntriesFromMapKeysAndAllowFrom, listDirectoryUserEntriesFromAllowFromAndMapKeys } from "openclaw/plugin-sdk/directory-runtime";
20
20
  import { normalizeMessagePresentation, renderMessagePresentationFallbackText } from "openclaw/plugin-sdk/interactive-runtime";
21
21
  import { createLazyRuntimeNamedExport } from "openclaw/plugin-sdk/lazy-runtime";
22
+ import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
22
23
  import { buildProbeChannelStatusSummary, createComputedAccountStatusAdapter, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/status-helpers";
23
24
  import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$2, normalizeAccountId as normalizeAccountId$1, resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution";
24
25
  import { createResolvedApproverActionAuthAdapter, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
@@ -1452,7 +1453,7 @@ async function promptFeishuSetupMethod(prompter) {
1452
1453
  });
1453
1454
  }
1454
1455
  async function runScanToCreate(prompter, domain) {
1455
- const { beginAppRegistration, initAppRegistration, pollAppRegistration, printQrCode } = await import("./app-registration-BZSSYX1J.js");
1456
+ const { beginAppRegistration, initAppRegistration, pollAppRegistration, printQrCode } = await import("./app-registration-DCy5-X_C.js");
1456
1457
  try {
1457
1458
  await initAppRegistration(domain);
1458
1459
  } catch {
@@ -1537,7 +1538,7 @@ async function runNewAppFlow(params) {
1537
1538
  appSecretProbeValue = appSecretResult.resolvedValue;
1538
1539
  }
1539
1540
  if (appId && appSecretProbeValue) {
1540
- const { getAppOwnerOpenId } = await import("./app-registration-BZSSYX1J.js");
1541
+ const { getAppOwnerOpenId } = await import("./app-registration-DCy5-X_C.js");
1541
1542
  scanOpenId = await getAppOwnerOpenId({
1542
1543
  appId,
1543
1544
  appSecret: appSecretProbeValue,
@@ -1647,7 +1648,7 @@ const feishuSetupWizard = {
1647
1648
  });
1648
1649
  let probeResult = null;
1649
1650
  if (configured && account.configured) try {
1650
- const { probeFeishu } = await import("./probe-RvCg70BY.js").then((n) => n.n);
1651
+ const { probeFeishu } = await import("./probe-956I34qH.js").then((n) => n.n);
1651
1652
  probeResult = await probeFeishu(account);
1652
1653
  } catch {}
1653
1654
  if (!configured) return [formatFeishuStatusLine("needs-credentials")];
@@ -1723,7 +1724,7 @@ const meta = {
1723
1724
  order: 70,
1724
1725
  preferSessionLookupForAnnounceTarget: true
1725
1726
  };
1726
- const loadFeishuChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-D6J6otxd.js"), "feishuChannelRuntime");
1727
+ const loadFeishuChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-BLnKcmtO.js"), "feishuChannelRuntime");
1727
1728
  function toFeishuMessageSendResult(result, kind) {
1728
1729
  const receipt = result.receipt ?? createFeishuSendReceipt({
1729
1730
  messageId: result.messageId,
@@ -1755,7 +1756,7 @@ const feishuMessageAdapter = defineChannelMessageAdapter({
1755
1756
  }
1756
1757
  });
1757
1758
  async function createFeishuActionClient(account) {
1758
- const { createFeishuClient } = await import("./client-DcSzLkSX.js").then((n) => n.t);
1759
+ const { createFeishuClient } = await import("./client-BhMNZBJD.js").then((n) => n.t);
1759
1760
  return createFeishuClient(account);
1760
1761
  }
1761
1762
  const collectFeishuSecurityWarnings = createAllowlistProviderGroupPolicyWarningCollector({
@@ -1961,18 +1962,10 @@ function readFirstString(params, keys, fallback) {
1961
1962
  }
1962
1963
  if (typeof fallback === "string" && fallback.trim()) return fallback.trim();
1963
1964
  }
1964
- function isPositiveSafeInteger(value) {
1965
- return Number.isSafeInteger(value) && value > 0;
1966
- }
1967
1965
  function readOptionalPositiveInteger(params, keys) {
1968
1966
  for (const key of keys) {
1969
- const value = params[key];
1970
- if (typeof value === "number" && isPositiveSafeInteger(value)) return value;
1971
- if (typeof value === "string" && value.trim()) {
1972
- const trimmed = value.trim();
1973
- const parsed = /^\d+$/.test(trimmed) ? Number(trimmed) : NaN;
1974
- if (isPositiveSafeInteger(parsed)) return parsed;
1975
- }
1967
+ const parsed = parseStrictPositiveInteger(params[key]);
1968
+ if (parsed !== void 0) return parsed;
1976
1969
  }
1977
1970
  }
1978
1971
  function resolveFeishuActionTarget(ctx) {
@@ -2547,7 +2540,7 @@ const feishuPlugin = createChatChannelPlugin({
2547
2540
  })
2548
2541
  }),
2549
2542
  gateway: { startAccount: async (ctx) => {
2550
- const { monitorFeishuProvider } = await import("./monitor-1WyqLgPM.js");
2543
+ const { monitorFeishuProvider } = await import("./monitor-CyD0CQxm.js");
2551
2544
  const account = resolveFeishuRuntimeAccount({
2552
2545
  cfg: ctx.cfg,
2553
2546
  accountId: ctx.accountId
@@ -1,2 +1,2 @@
1
- import { t as feishuPlugin } from "./channel-BVSJh3s1.js";
1
+ import { t as feishuPlugin } from "./channel-BfeesQob.js";
2
2
  export { feishuPlugin };
@@ -1,10 +1,10 @@
1
1
  import { o as resolveFeishuAccount, s as resolveFeishuRuntimeAccount, y as parseFeishuCommentTarget } from "./accounts-CXnY5H8g.js";
2
- import { h as listFeishuDirectoryPeers, m as listFeishuDirectoryGroups, o as buildFeishuPresentationCardElements } from "./channel-BVSJh3s1.js";
3
- import { r as createFeishuClient } from "./client-DcSzLkSX.js";
4
- import { c as getChatInfo, l as getChatMembers, r as cleanupAmbientCommentTypingReaction, t as deliverCommentThreadText, u as getFeishuMemberInfo } from "./drive-6Ohn34x9.js";
2
+ import { h as listFeishuDirectoryPeers, m as listFeishuDirectoryGroups, o as buildFeishuPresentationCardElements } from "./channel-BfeesQob.js";
3
+ import { r as createFeishuClient } from "./client-BhMNZBJD.js";
4
+ import { c as getChatInfo, l as getChatMembers, r as cleanupAmbientCommentTypingReaction, t as deliverCommentThreadText, u as getFeishuMemberInfo } from "./drive-USxqssMG.js";
5
5
  import { chunkTextForOutbound } from "./runtime-api.js";
6
- import { a as sendCardFeishu, c as sendStructuredCardFeishu, g as shouldSuppressFeishuTextForVoiceMedia, h as sendMediaFeishu, i as resolveFeishuCardTemplate, n as getMessageFeishu, o as sendMarkdownCardFeishu, s as sendMessageFeishu, t as editMessageFeishu } from "./send-CKZz15KQ.js";
7
- import { t as probeFeishu } from "./probe-RvCg70BY.js";
6
+ import { a as sendCardFeishu, c as sendStructuredCardFeishu, g as shouldSuppressFeishuTextForVoiceMedia, h as sendMediaFeishu, i as resolveFeishuCardTemplate, n as getMessageFeishu, o as sendMarkdownCardFeishu, s as sendMessageFeishu, t as editMessageFeishu } from "./send-Djou0Z5a.js";
7
+ import { t as probeFeishu } from "./probe-956I34qH.js";
8
8
  import { isRecord, normalizeLowercaseStringOrEmpty, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
9
9
  import { interactiveReplyToPresentation, normalizeInteractiveReply, normalizeMessagePresentation, renderMessagePresentationFallbackText, resolveInteractiveTextFallback } from "openclaw/plugin-sdk/interactive-runtime";
10
10
  import path from "node:path";
@@ -1,5 +1,5 @@
1
1
  import { d as formatFeishuApiError, f as isRecord$1, h as readString, i as listFeishuAccountIds, l as encodeQuery, o as resolveFeishuAccount, r as listEnabledFeishuAccounts, s as resolveFeishuRuntimeAccount, u as extractReplyText, y as parseFeishuCommentTarget } from "./accounts-CXnY5H8g.js";
2
- import { r as createFeishuClient } from "./client-DcSzLkSX.js";
2
+ import { r as createFeishuClient } from "./client-BhMNZBJD.js";
3
3
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  import { optionalPositiveIntegerSchema } from "openclaw/plugin-sdk/channel-actions";
5
5
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
@@ -0,0 +1,73 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { createHash } from "node:crypto";
4
+ //#region extensions/feishu/src/dedup-migrations.ts
5
+ const DEDUP_TTL_MS = 1440 * 60 * 1e3;
6
+ const STORE_MAX_ENTRIES = 1e4;
7
+ function safeNamespaceFromFileName(fileName) {
8
+ if (!fileName.endsWith(".json")) return null;
9
+ const namespace = fileName.slice(0, -5).trim();
10
+ return namespace ? namespace : null;
11
+ }
12
+ function readLegacyDedupeData(filePath) {
13
+ try {
14
+ const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
15
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
16
+ const out = {};
17
+ for (const [messageId, seenAt] of Object.entries(parsed)) if (typeof seenAt === "number" && Number.isFinite(seenAt) && seenAt > 0) out[messageId] = seenAt;
18
+ return out;
19
+ } catch {
20
+ return {};
21
+ }
22
+ }
23
+ function dedupeStoreKey(namespace, messageId) {
24
+ return createHash("sha256").update(`${namespace}\0${messageId}`, "utf8").digest("hex").slice(0, 32);
25
+ }
26
+ function remainingTtlMs(seenAt, now) {
27
+ return Math.max(1, DEDUP_TTL_MS - (now - seenAt));
28
+ }
29
+ function buildMigrationEntries(namespace, sourcePath, now) {
30
+ return Object.entries(readLegacyDedupeData(sourcePath)).flatMap(([messageId, seenAt]) => {
31
+ if (now - seenAt >= DEDUP_TTL_MS) return [];
32
+ return [{
33
+ key: dedupeStoreKey(namespace, messageId),
34
+ value: {
35
+ namespace,
36
+ messageId,
37
+ seenAt
38
+ },
39
+ ttlMs: remainingTtlMs(seenAt, now)
40
+ }];
41
+ });
42
+ }
43
+ const detectFeishuLegacyStateMigrations = ({ stateDir }) => {
44
+ const dedupDir = path.join(stateDir, "feishu", "dedup");
45
+ let entries = [];
46
+ try {
47
+ entries = fs.readdirSync(dedupDir, { withFileTypes: true });
48
+ } catch {
49
+ return [];
50
+ }
51
+ const now = Date.now();
52
+ return entries.flatMap((entry) => {
53
+ if (!entry.isFile()) return [];
54
+ const namespace = safeNamespaceFromFileName(entry.name);
55
+ if (!namespace) return [];
56
+ const sourcePath = path.join(dedupDir, entry.name);
57
+ if (buildMigrationEntries(namespace, sourcePath, now).length === 0) return [];
58
+ return [{
59
+ kind: "plugin-state-import",
60
+ label: `Feishu ${namespace} dedupe`,
61
+ sourcePath,
62
+ targetPath: `plugin state:dedup.${namespace}`,
63
+ pluginId: "feishu",
64
+ namespace: `dedup.${namespace}`,
65
+ maxEntries: STORE_MAX_ENTRIES,
66
+ scopeKey: "",
67
+ cleanupSource: "rename",
68
+ readEntries: () => buildMigrationEntries(namespace, sourcePath, now)
69
+ }];
70
+ });
71
+ };
72
+ //#endregion
73
+ export { detectFeishuLegacyStateMigrations };
@@ -1,9 +1,9 @@
1
1
  import { r as listEnabledFeishuAccounts, s as resolveFeishuRuntimeAccount } from "./accounts-CXnY5H8g.js";
2
- import { l as fetchBotIdentityForMonitor } from "./monitor.state-B6SoAUys.js";
2
+ import { l as fetchBotIdentityForMonitor } from "./monitor.state-t4Ae5VIa.js";
3
3
  //#region extensions/feishu/src/monitor.ts
4
4
  let monitorAccountRuntimePromise;
5
5
  async function loadMonitorAccountRuntime() {
6
- monitorAccountRuntimePromise ??= import("./monitor.account-DXQXXSzI.js");
6
+ monitorAccountRuntimePromise ??= import("./monitor.account-ByxawtBB.js");
7
7
  return await monitorAccountRuntimePromise;
8
8
  }
9
9
  async function monitorFeishuProvider(opts = {}) {
@@ -2,34 +2,34 @@ import { t as buildFeishuConversationId } from "./conversation-id-DuL575sn.js";
2
2
  import { i as resolveReceiveIdType } from "./targets-BUjQ1TcA.js";
3
3
  import { t as createFeishuThreadBindingManager } from "./thread-bindings-D24m3Cjy.js";
4
4
  import { _ as buildFeishuCommentTarget, f as isRecord$1, h as readString, l as encodeQuery, m as parseCommentContentElements, p as normalizeString, s as resolveFeishuRuntimeAccount, u as extractReplyText, v as normalizeCommentFileType } from "./accounts-CXnY5H8g.js";
5
- import { c as normalizeFeishuAllowEntry, d as resolveFeishuGroupConversationIngressAccess, f as resolveFeishuGroupSenderActivationIngressAccess, l as resolveFeishuDmIngressAccess, p as resolveFeishuReplyPolicy, s as hasExplicitFeishuGroupConfig, u as resolveFeishuGroupConfig } from "./channel-BVSJh3s1.js";
5
+ import { c as normalizeFeishuAllowEntry, d as resolveFeishuGroupConversationIngressAccess, f as resolveFeishuGroupSenderActivationIngressAccess, l as resolveFeishuDmIngressAccess, p as resolveFeishuReplyPolicy, s as hasExplicitFeishuGroupConfig, u as resolveFeishuGroupConfig } from "./channel-BfeesQob.js";
6
6
  import { c as decodeFeishuCardAction, o as buildFeishuCardActionTextFallback, s as createFeishuCardInteractionEnvelope } from "./send-result-DSTSkRDM.js";
7
7
  import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
8
- import { a as getFeishuUserAgent, i as createFeishuWSClient, n as createEventDispatcher, r as createFeishuClient } from "./client-DcSzLkSX.js";
9
- import { c as getChatInfo, i as createCommentTypingReactionLifecycle, t as deliverCommentThreadText } from "./drive-6Ohn34x9.js";
8
+ import { a as getFeishuUserAgent, i as createFeishuWSClient, n as createEventDispatcher, r as createFeishuClient } from "./client-BhMNZBJD.js";
9
+ import { c as getChatInfo, i as createCommentTypingReactionLifecycle, t as deliverCommentThreadText } from "./drive-USxqssMG.js";
10
10
  import { createReplyPrefixContext, evaluateSupplementalContextVisibility, loadSessionStore, normalizeAgentId as normalizeAgentId$2, resolveChannelContextVisibilityMode, resolveSessionStoreEntry } from "./runtime-api.js";
11
- import { _ as normalizeFeishuExternalKey, a as sendCardFeishu, c as sendStructuredCardFeishu, d as isFeishuBroadcastMention, f as isMentionForwardRequest, g as shouldSuppressFeishuTextForVoiceMedia, h as sendMediaFeishu, i as resolveFeishuCardTemplate, l as parsePostContent, m as saveMessageResourceFeishu, n as getMessageFeishu, p as isFeishuGroupChatType, r as listFeishuThreadMessages, s as sendMessageFeishu, u as extractMentionTargets } from "./send-CKZz15KQ.js";
12
- import { i as waitForAbortableDelay, r as raceWithTimeoutAndAbort } from "./probe-RvCg70BY.js";
13
- import { a as feishuWebhookRateLimiter, c as wsClients, i as botOpenIds, l as fetchBotIdentityForMonitor, n as FEISHU_WEBHOOK_MAX_BODY_BYTES, o as httpServers, r as botNames, s as recordWebhookStatus, t as FEISHU_WEBHOOK_BODY_TIMEOUT_MS } from "./monitor.state-B6SoAUys.js";
11
+ import { _ as normalizeFeishuExternalKey, a as sendCardFeishu, c as sendStructuredCardFeishu, d as isFeishuBroadcastMention, f as isMentionForwardRequest, g as shouldSuppressFeishuTextForVoiceMedia, h as sendMediaFeishu, i as resolveFeishuCardTemplate, l as parsePostContent, m as saveMessageResourceFeishu, n as getMessageFeishu, p as isFeishuGroupChatType, r as listFeishuThreadMessages, s as sendMessageFeishu, u as extractMentionTargets } from "./send-Djou0Z5a.js";
12
+ import { i as waitForAbortableDelay, r as raceWithTimeoutAndAbort } from "./probe-956I34qH.js";
13
+ import { a as feishuWebhookRateLimiter, c as wsClients, i as botOpenIds, l as fetchBotIdentityForMonitor, n as FEISHU_WEBHOOK_MAX_BODY_BYTES, o as httpServers, r as botNames, s as recordWebhookStatus, t as FEISHU_WEBHOOK_BODY_TIMEOUT_MS } from "./monitor.state-t4Ae5VIa.js";
14
14
  import { asBoolean, asNullableRecord, isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, readStringValue, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
15
15
  import { ensureConfiguredBindingRouteReady, resolveConfiguredBindingRoute, resolveRuntimeConversationBindingRoute } from "openclaw/plugin-sdk/conversation-runtime";
16
16
  import { resolveInboundLastRouteSessionKey } from "openclaw/plugin-sdk/routing";
17
17
  import { createChannelMessageReplyPipeline, formatChannelProgressDraftLineForEntry, isChannelProgressDraftWorkToolName, resolveAgentOutboundIdentity } from "openclaw/plugin-sdk/channel-outbound";
18
18
  import { createChannelPairingController, createChannelPairingController as createChannelPairingController$1 } from "openclaw/plugin-sdk/channel-pairing";
19
+ import { parseStrictNonNegativeInteger, resolveExpiresAtMsFromDurationSeconds } from "openclaw/plugin-sdk/number-runtime";
19
20
  import { stripReasoningTagsFromText } from "openclaw/plugin-sdk/text-chunking";
20
21
  import fs from "node:fs";
21
22
  import os from "node:os";
22
23
  import path from "node:path";
23
24
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
24
25
  import * as Lark from "@larksuiteoapi/node-sdk";
25
- import { parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
26
- import { createPersistentDedupe } from "openclaw/plugin-sdk/persistent-dedupe";
26
+ import * as crypto$1 from "node:crypto";
27
+ import crypto, { createHash } from "node:crypto";
28
+ import { loadJsonFile } from "openclaw/plugin-sdk/json-store";
27
29
  import { applyBasicWebhookRequestGuards, resolveRequestClientIp } from "openclaw/plugin-sdk/webhook-ingress";
28
30
  import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
29
31
  import { resolveSendableOutboundReplyParts, resolveTextChunksWithFallback, sendMediaWithLeadingCaption } from "openclaw/plugin-sdk/reply-payload";
30
32
  import { resolvePinnedMainDmOwnerFromAllowlist, safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
31
- import * as crypto$1 from "node:crypto";
32
- import crypto from "node:crypto";
33
33
  import { resolveChannelConfigWrites } from "openclaw/plugin-sdk/channel-config-writes";
34
34
  import { buildChannelInboundEventContext, toInboundMediaFacts } from "openclaw/plugin-sdk/channel-inbound";
35
35
  import { DEFAULT_GROUP_HISTORY_LIMIT, createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
@@ -161,7 +161,7 @@ function parseMergeForwardContent(params) {
161
161
  const subMessages = items.filter((item) => item.upper_message_id);
162
162
  if (subMessages.length === 0) return "[Merged and Forwarded Message - no sub-messages found]";
163
163
  log?.(`feishu: merge_forward contains ${subMessages.length} sub-messages`);
164
- subMessages.sort((a, b) => Number.parseInt(a.create_time || "0", 10) - Number.parseInt(b.create_time || "0", 10));
164
+ subMessages.sort((a, b) => (parseStrictNonNegativeInteger(a.create_time) ?? 0) - (parseStrictNonNegativeInteger(b.create_time) ?? 0));
165
165
  const lines = ["[Merged and Forwarded Messages]"];
166
166
  for (const item of subMessages.slice(0, maxMessages)) lines.push(`- ${formatSubMessageContent(item.body?.content || "", item.msg_type || "text")}`);
167
167
  if (subMessages.length > maxMessages) lines.push(`... and ${subMessages.length - maxMessages} more messages`);
@@ -447,26 +447,93 @@ function releaseFeishuMessageProcessing(messageId, namespace = "global") {
447
447
  //#region extensions/feishu/src/dedup.ts
448
448
  const DEDUP_TTL_MS = 1440 * 60 * 1e3;
449
449
  const MEMORY_MAX_SIZE = 1e3;
450
- const FILE_MAX_ENTRIES = 1e4;
451
- function resolveStateDirFromEnv(env = process.env) {
450
+ const STORE_MAX_ENTRIES = 1e4;
451
+ const memory = /* @__PURE__ */ new Map();
452
+ const importedLegacyNamespaces = /* @__PURE__ */ new Set();
453
+ const cachedDedupStores = /* @__PURE__ */ new Map();
454
+ function normalizeMessageId(messageId) {
455
+ const trimmed = messageId?.trim();
456
+ return trimmed ? trimmed : null;
457
+ }
458
+ function normalizeNamespace(namespace) {
459
+ return namespace?.trim() || "global";
460
+ }
461
+ function resolveLegacyStateDir(env = process.env) {
452
462
  const stateOverride = env.OPENCLAW_STATE_DIR?.trim();
453
463
  if (stateOverride) return stateOverride;
454
464
  if (env.VITEST || env.NODE_ENV === "test") return path.join(os.tmpdir(), ["openclaw-vitest", String(process.pid)].join("-"));
455
465
  return path.join(os.homedir(), ".openclaw");
456
466
  }
457
- function resolveNamespaceFilePath(namespace) {
467
+ function resolveLegacyNamespaceFilePath(namespace) {
458
468
  const safe = namespace.replace(/[^a-zA-Z0-9_-]/g, "_");
459
- return path.join(resolveStateDirFromEnv(), "feishu", "dedup", `${safe}.json`);
460
- }
461
- const persistentDedupe = createPersistentDedupe({
462
- ttlMs: DEDUP_TTL_MS,
463
- memoryMaxSize: MEMORY_MAX_SIZE,
464
- fileMaxEntries: FILE_MAX_ENTRIES,
465
- resolveFilePath: resolveNamespaceFilePath
466
- });
467
- function normalizeMessageId(messageId) {
468
- const trimmed = messageId?.trim();
469
- return trimmed ? trimmed : null;
469
+ return path.join(resolveLegacyStateDir(), "feishu", "dedup", `${safe}.json`);
470
+ }
471
+ function pluginStateNamespace(namespace) {
472
+ return `dedup.${namespace.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
473
+ }
474
+ function openDedupStore(namespace) {
475
+ const stateNamespace = pluginStateNamespace(namespace);
476
+ const cached = cachedDedupStores.get(stateNamespace);
477
+ if (cached) return cached;
478
+ const store = getFeishuRuntime().state.openSyncKeyedStore({
479
+ namespace: stateNamespace,
480
+ maxEntries: STORE_MAX_ENTRIES,
481
+ defaultTtlMs: DEDUP_TTL_MS
482
+ });
483
+ cachedDedupStores.set(stateNamespace, store);
484
+ return store;
485
+ }
486
+ function dedupeStoreKey(namespace, messageId) {
487
+ return createHash("sha256").update(`${namespace}\0${messageId}`, "utf8").digest("hex").slice(0, 32);
488
+ }
489
+ function memoryKey(namespace, messageId) {
490
+ return `${namespace}\0${messageId}`;
491
+ }
492
+ function isRecent(seenAt, now = Date.now()) {
493
+ return typeof seenAt === "number" && Number.isFinite(seenAt) && now - seenAt < DEDUP_TTL_MS;
494
+ }
495
+ function pruneMemory(now = Date.now()) {
496
+ for (const [key, seenAt] of memory) if (!isRecent(seenAt, now)) memory.delete(key);
497
+ if (memory.size <= MEMORY_MAX_SIZE) return;
498
+ const toRemove = Array.from(memory.entries()).toSorted(([, left], [, right]) => left - right).slice(0, memory.size - MEMORY_MAX_SIZE);
499
+ for (const [key] of toRemove) memory.delete(key);
500
+ }
501
+ function remember(namespace, messageId, seenAt = Date.now()) {
502
+ memory.set(memoryKey(namespace, messageId), seenAt);
503
+ pruneMemory(seenAt);
504
+ }
505
+ function hasMemory(namespace, messageId, now = Date.now()) {
506
+ const key = memoryKey(namespace, messageId);
507
+ if (isRecent(memory.get(key), now)) return true;
508
+ memory.delete(key);
509
+ return false;
510
+ }
511
+ function sanitizeLegacyDedupeData(value) {
512
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
513
+ const out = {};
514
+ for (const [key, seenAt] of Object.entries(value)) if (typeof seenAt === "number" && Number.isFinite(seenAt) && seenAt > 0) out[key] = seenAt;
515
+ return out;
516
+ }
517
+ function importLegacyDedupNamespace(namespace, now = Date.now(), log) {
518
+ if (importedLegacyNamespaces.has(namespace)) return;
519
+ try {
520
+ const data = sanitizeLegacyDedupeData(loadJsonFile(resolveLegacyNamespaceFilePath(namespace)));
521
+ const store = openDedupStore(namespace);
522
+ for (const [messageId, seenAt] of Object.entries(data)) {
523
+ if (!isRecent(seenAt, now)) continue;
524
+ const key = dedupeStoreKey(namespace, messageId);
525
+ if (store.lookup(key) != null) continue;
526
+ store.register(key, {
527
+ namespace,
528
+ messageId,
529
+ seenAt
530
+ }, { ttlMs: Math.max(1, DEDUP_TTL_MS - (now - seenAt)) });
531
+ }
532
+ importedLegacyNamespaces.add(namespace);
533
+ } catch (error) {
534
+ importedLegacyNamespaces.delete(namespace);
535
+ log?.(`feishu-dedup: legacy state import failed: ${String(error)}`);
536
+ }
470
537
  }
471
538
  async function claimUnprocessedFeishuMessage(params) {
472
539
  const { messageId, namespace = "global", log } = params;
@@ -492,31 +559,96 @@ async function recordProcessedFeishuMessage(messageId, namespace = "global", log
492
559
  if (!normalizedMessageId) return false;
493
560
  return await tryRecordMessagePersistent(normalizedMessageId, namespace, log);
494
561
  }
562
+ async function forgetProcessedFeishuMessage(messageId, namespace = "global", log) {
563
+ const normalizedNamespace = normalizeNamespace(namespace);
564
+ const normalizedMessageId = normalizeMessageId(messageId);
565
+ if (!normalizedMessageId) return false;
566
+ memory.delete(memoryKey(normalizedNamespace, normalizedMessageId));
567
+ const key = dedupeStoreKey(normalizedNamespace, normalizedMessageId);
568
+ try {
569
+ return openDedupStore(normalizedNamespace).delete(key);
570
+ } catch (error) {
571
+ log?.(`feishu-dedup: persistent delete failed: ${String(error)}`);
572
+ return false;
573
+ }
574
+ }
495
575
  async function hasProcessedFeishuMessage(messageId, namespace = "global", log) {
496
576
  const normalizedMessageId = normalizeMessageId(messageId);
497
577
  if (!normalizedMessageId) return false;
498
578
  return hasRecordedMessagePersistent(normalizedMessageId, namespace, log);
499
579
  }
500
580
  async function tryRecordMessagePersistent(messageId, namespace = "global", log) {
501
- return persistentDedupe.checkAndRecord(messageId, {
502
- namespace,
503
- onDiskError: (error) => {
504
- log?.(`feishu-dedup: disk error, falling back to memory: ${String(error)}`);
581
+ const normalizedNamespace = normalizeNamespace(namespace);
582
+ const normalizedMessageId = normalizeMessageId(messageId);
583
+ if (!normalizedMessageId) return true;
584
+ const now = Date.now();
585
+ importLegacyDedupNamespace(normalizedNamespace, now, log);
586
+ if (hasMemory(normalizedNamespace, normalizedMessageId, now)) return false;
587
+ const key = dedupeStoreKey(normalizedNamespace, normalizedMessageId);
588
+ try {
589
+ const store = openDedupStore(normalizedNamespace);
590
+ const existingSeenAt = store.lookup(key)?.seenAt;
591
+ if (isRecent(existingSeenAt, now)) {
592
+ remember(normalizedNamespace, normalizedMessageId, existingSeenAt);
593
+ return false;
505
594
  }
506
- });
595
+ if (!store.registerIfAbsent(key, {
596
+ namespace: normalizedNamespace,
597
+ messageId: normalizedMessageId,
598
+ seenAt: now
599
+ }, { ttlMs: DEDUP_TTL_MS })) {
600
+ const currentSeenAt = store.lookup(key)?.seenAt;
601
+ if (isRecent(currentSeenAt, now)) {
602
+ remember(normalizedNamespace, normalizedMessageId, currentSeenAt);
603
+ return false;
604
+ }
605
+ store.register(key, {
606
+ namespace: normalizedNamespace,
607
+ messageId: normalizedMessageId,
608
+ seenAt: now
609
+ }, { ttlMs: DEDUP_TTL_MS });
610
+ }
611
+ remember(normalizedNamespace, normalizedMessageId, now);
612
+ return true;
613
+ } catch (error) {
614
+ log?.(`feishu-dedup: persistent state error, falling back to memory: ${String(error)}`);
615
+ remember(normalizedNamespace, normalizedMessageId, now);
616
+ return true;
617
+ }
507
618
  }
508
619
  async function hasRecordedMessagePersistent(messageId, namespace = "global", log) {
509
- return persistentDedupe.hasRecent(messageId, {
510
- namespace,
511
- onDiskError: (error) => {
512
- log?.(`feishu-dedup: persistent peek failed: ${String(error)}`);
513
- }
514
- });
620
+ const normalizedNamespace = normalizeNamespace(namespace);
621
+ const normalizedMessageId = normalizeMessageId(messageId);
622
+ if (!normalizedMessageId) return false;
623
+ const now = Date.now();
624
+ importLegacyDedupNamespace(normalizedNamespace, now, log);
625
+ if (hasMemory(normalizedNamespace, normalizedMessageId, now)) return true;
626
+ try {
627
+ const existingSeenAt = openDedupStore(normalizedNamespace).lookup(dedupeStoreKey(normalizedNamespace, normalizedMessageId))?.seenAt;
628
+ if (!isRecent(existingSeenAt, now)) return false;
629
+ remember(normalizedNamespace, normalizedMessageId, existingSeenAt);
630
+ return true;
631
+ } catch (error) {
632
+ log?.(`feishu-dedup: persistent peek failed: ${String(error)}`);
633
+ return hasMemory(normalizedNamespace, normalizedMessageId, now);
634
+ }
515
635
  }
516
636
  async function warmupDedupFromDisk(namespace, log) {
517
- return persistentDedupe.warmup(namespace, (error) => {
518
- log?.(`feishu-dedup: warmup disk error: ${String(error)}`);
519
- });
637
+ const normalizedNamespace = normalizeNamespace(namespace);
638
+ try {
639
+ let loaded = 0;
640
+ const now = Date.now();
641
+ importLegacyDedupNamespace(normalizedNamespace, now, log);
642
+ for (const entry of openDedupStore(normalizedNamespace).entries()) {
643
+ if (entry.value.namespace !== normalizedNamespace || !isRecent(entry.value.seenAt, now)) continue;
644
+ remember(normalizedNamespace, entry.value.messageId, entry.value.seenAt);
645
+ loaded++;
646
+ }
647
+ return loaded;
648
+ } catch (error) {
649
+ log?.(`feishu-dedup: warmup persistent state error: ${String(error)}`);
650
+ return 0;
651
+ }
520
652
  }
521
653
  //#endregion
522
654
  //#region extensions/feishu/src/dedupe-key.ts
@@ -691,7 +823,12 @@ function resolveFeishuReasoningPreviewEnabled(params) {
691
823
  //#region extensions/feishu/src/streaming-card.ts
692
824
  const STREAMING_UPDATE_THROTTLE_MS = 160;
693
825
  const STREAMING_SIGNIFICANT_DELTA_CHARS = 18;
826
+ const FEISHU_STREAMING_TOKEN_DEFAULT_LIFETIME_SECONDS = 7200;
694
827
  const tokenCache = /* @__PURE__ */ new Map();
828
+ function resolveStreamingTokenExpiresAt(value) {
829
+ if (typeof value === "number" && Number.isFinite(value) && value <= 0) return Date.now();
830
+ return resolveExpiresAtMsFromDurationSeconds(value) ?? Date.now() + FEISHU_STREAMING_TOKEN_DEFAULT_LIFETIME_SECONDS * 1e3;
831
+ }
695
832
  function resolveApiBase(domain) {
696
833
  if (domain === "lark") return "https://open.larksuite.com/open-apis";
697
834
  if (domain && domain !== "feishu" && domain.startsWith("http")) return `${domain.replace(/\/+$/, "")}/open-apis`;
@@ -735,7 +872,7 @@ async function getToken(creds) {
735
872
  if (data.code !== 0 || !data.tenant_access_token) throw new Error(`Token error: ${data.msg}`);
736
873
  tokenCache.set(key, {
737
874
  token: data.tenant_access_token,
738
- expiresAt: Date.now() + (data.expire ?? 7200) * 1e3
875
+ expiresAt: resolveStreamingTokenExpiresAt(data.expire)
739
876
  });
740
877
  return data.tenant_access_token;
741
878
  }
@@ -1975,7 +2112,7 @@ async function handleFeishuMessage(params) {
1975
2112
  const configAllowFrom = feishuCfg?.allowFrom ?? [];
1976
2113
  const rawBroadcastAgents = isGroup ? resolveBroadcastAgents(cfg, ctx.chatId) : null;
1977
2114
  const broadcastAgents = rawBroadcastAgents ? uniqueStrings(rawBroadcastAgents.map((id) => normalizeAgentId$2(id))) : null;
1978
- const messageCreateTimeMs = event.message.create_time ? Number.parseInt(event.message.create_time, 10) : Date.now();
2115
+ const messageCreateTimeMs = parseStrictNonNegativeInteger(event.message.create_time) ?? Date.now();
1979
2116
  let requireMention = false;
1980
2117
  if (isGroup) {
1981
2118
  if (groupConfig?.enabled === false) {
@@ -3360,14 +3497,15 @@ function createFeishuBotMenuHandler(params) {
3360
3497
  }).then(async (handledMenu) => {
3361
3498
  if (handledMenu) {
3362
3499
  await recordProcessedFeishuMessage(syntheticMessageId, accountId, log);
3363
- releaseFeishuMessageProcessing(syntheticMessageId, accountId);
3364
3500
  return;
3365
3501
  }
3366
3502
  return await handleLegacyMenu();
3367
3503
  }).catch(async (err) => {
3368
- if (isFeishuRetryableSyntheticEventError(err)) releaseFeishuMessageProcessing(syntheticMessageId, accountId);
3504
+ if (isFeishuRetryableSyntheticEventError(err)) await forgetProcessedFeishuMessage(syntheticMessageId, accountId, log);
3369
3505
  else await recordProcessedFeishuMessage(syntheticMessageId, accountId, log);
3370
3506
  throw err;
3507
+ }).finally(() => {
3508
+ releaseFeishuMessageProcessing(syntheticMessageId, accountId);
3371
3509
  });
3372
3510
  if (fireAndForget) {
3373
3511
  promise.catch((err) => {
@@ -1,4 +1,4 @@
1
- import { t as probeFeishu } from "./probe-RvCg70BY.js";
1
+ import { t as probeFeishu } from "./probe-956I34qH.js";
2
2
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
4
4
  import { WEBHOOK_ANOMALY_COUNTER_DEFAULTS, WEBHOOK_RATE_LIMIT_DEFAULTS, createFixedWindowRateLimiter, createWebhookAnomalyTracker } from "openclaw/plugin-sdk/webhook-ingress";
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
- import { r as createFeishuClient } from "./client-DcSzLkSX.js";
2
+ import { r as createFeishuClient } from "./client-BhMNZBJD.js";
3
3
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
4
4
  //#region extensions/feishu/src/async.ts
5
5
  const RACE_TIMEOUT = Symbol("race-timeout");
@@ -9,6 +9,5 @@ import { DEFAULT_ACCOUNT_ID, buildChannelConfigSchema, createActionGate, createD
9
9
  import { buildAgentMediaPayload } from "openclaw/plugin-sdk/agent-media-payload";
10
10
  import { evaluateSupplementalContextVisibility, filterSupplementalContextItems, resolveChannelContextVisibilityMode } from "openclaw/plugin-sdk/context-visibility-runtime";
11
11
  import { readJsonFileWithFallback } from "openclaw/plugin-sdk/json-store";
12
- import { createPersistentDedupe } from "openclaw/plugin-sdk/persistent-dedupe";
13
12
  import { isRequestBodyLimitError, readRequestBodyWithLimit, requestBodyErrorToText } from "openclaw/plugin-sdk/webhook-ingress";
14
- export { DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE, buildAgentMediaPayload, buildChannelConfigSchema, buildProbeChannelStatusSummary, chunkTextForOutbound, createActionGate, createChannelPairingController, createDedupeCache, createDefaultChannelRuntimeState, createPersistentDedupe, createReplyPrefixContext, evaluateSupplementalContextVisibility, filterSupplementalContextItems, isRequestBodyLimitError, loadSessionStore, normalizeAgentId, readJsonFileWithFallback, readRequestBodyWithLimit, requestBodyErrorToText, resolveChannelContextVisibilityMode, resolveSessionStoreEntry, setFeishuRuntime };
13
+ export { DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE, buildAgentMediaPayload, buildChannelConfigSchema, buildProbeChannelStatusSummary, chunkTextForOutbound, createActionGate, createChannelPairingController, createDedupeCache, createDefaultChannelRuntimeState, createReplyPrefixContext, evaluateSupplementalContextVisibility, filterSupplementalContextItems, isRequestBodyLimitError, loadSessionStore, normalizeAgentId, readJsonFileWithFallback, readRequestBodyWithLimit, requestBodyErrorToText, resolveChannelContextVisibilityMode, resolveSessionStoreEntry, setFeishuRuntime };
@@ -2,8 +2,9 @@ import { i as resolveReceiveIdType, r as normalizeFeishuTarget } from "./targets
2
2
  import { c as createFeishuApiError, f as isRecord$1, g as requestFeishuApi, s as resolveFeishuRuntimeAccount } from "./accounts-CXnY5H8g.js";
3
3
  import { i as toFeishuSendResult, r as resolveFeishuReceiptKind, t as assertFeishuMessageApiSuccess } from "./send-result-DSTSkRDM.js";
4
4
  import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
5
- import { r as createFeishuClient } from "./client-DcSzLkSX.js";
5
+ import { r as createFeishuClient } from "./client-BhMNZBJD.js";
6
6
  import { isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
7
+ import { parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
7
8
  import { convertMarkdownTables } from "openclaw/plugin-sdk/text-chunking";
8
9
  import fs from "node:fs";
9
10
  import path from "node:path";
@@ -953,7 +954,7 @@ function parseFeishuMessageItem(item, fallbackMessageId) {
953
954
  senderType: item.sender?.sender_type,
954
955
  content: parseFeishuMessageContent(rawContent, msgType),
955
956
  contentType: msgType,
956
- createTime: item.create_time ? Number.parseInt(item.create_time, 10) : void 0,
957
+ createTime: parseStrictNonNegativeInteger(item.create_time),
957
958
  threadId: item.thread_id || void 0
958
959
  };
959
960
  }
package/dist/setup-api.js CHANGED
@@ -1,2 +1,2 @@
1
- import { i as feishuSetupAdapter, n as feishuSetupWizard, t as feishuPlugin } from "./channel-BVSJh3s1.js";
1
+ import { i as feishuSetupAdapter, n as feishuSetupWizard, t as feishuPlugin } from "./channel-BfeesQob.js";
2
2
  export { feishuPlugin, feishuSetupAdapter, feishuSetupWizard };
@@ -2,10 +2,15 @@ import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entr
2
2
  //#region extensions/feishu/setup-entry.ts
3
3
  var setup_entry_default = defineBundledChannelSetupEntry({
4
4
  importMetaUrl: import.meta.url,
5
+ features: { legacyStateMigrations: true },
5
6
  plugin: {
6
7
  specifier: "./setup-api.js",
7
8
  exportName: "feishuPlugin"
8
9
  },
10
+ legacyStateMigrations: {
11
+ specifier: "./legacy-state-migrations-api.js",
12
+ exportName: "detectFeishuLegacyStateMigrations"
13
+ },
9
14
  secrets: {
10
15
  specifier: "./secret-contract-api.js",
11
16
  exportName: "channelSecrets"
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "@openclaw/feishu",
3
- "version": "2026.5.28-beta.2",
3
+ "version": "2026.5.28-beta.4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/feishu",
9
- "version": "2026.5.28-beta.2",
9
+ "version": "2026.5.28-beta.4",
10
10
  "dependencies": {
11
11
  "@larksuiteoapi/node-sdk": "1.66.0",
12
12
  "typebox": "1.1.38",
13
13
  "zod": "4.4.3"
14
14
  },
15
15
  "peerDependencies": {
16
- "openclaw": ">=2026.5.28-beta.2"
16
+ "openclaw": ">=2026.5.28-beta.4"
17
17
  },
18
18
  "peerDependenciesMeta": {
19
19
  "openclaw": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/feishu",
3
- "version": "2026.5.28-beta.2",
3
+ "version": "2026.5.28-beta.4",
4
4
  "description": "OpenClaw Feishu/Lark channel plugin for chats and workplace tools (community maintained by @m1heng).",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,7 +13,7 @@
13
13
  "zod": "4.4.3"
14
14
  },
15
15
  "peerDependencies": {
16
- "openclaw": ">=2026.5.28-beta.2"
16
+ "openclaw": ">=2026.5.28-beta.4"
17
17
  },
18
18
  "peerDependenciesMeta": {
19
19
  "openclaw": {
@@ -25,6 +25,9 @@
25
25
  "./index.ts"
26
26
  ],
27
27
  "setupEntry": "./setup-entry.ts",
28
+ "setupFeatures": {
29
+ "legacyStateMigrations": true
30
+ },
28
31
  "channel": {
29
32
  "id": "feishu",
30
33
  "label": "Feishu",
@@ -41,13 +44,13 @@
41
44
  "install": {
42
45
  "npmSpec": "@openclaw/feishu",
43
46
  "defaultChoice": "npm",
44
- "minHostVersion": ">=2026.4.25"
47
+ "minHostVersion": ">=2026.5.29"
45
48
  },
46
49
  "compat": {
47
- "pluginApi": ">=2026.5.28-beta.2"
50
+ "pluginApi": ">=2026.5.28-beta.4"
48
51
  },
49
52
  "build": {
50
- "openclawVersion": "2026.5.28-beta.2"
53
+ "openclawVersion": "2026.5.28-beta.4"
51
54
  },
52
55
  "release": {
53
56
  "publishToClawHub": true,
@@ -1,8 +1,8 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
2
  import { createRequire } from "node:module";
3
+ import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
3
4
  import * as Lark from "@larksuiteoapi/node-sdk";
4
5
  import { readPluginPackageVersion, resolveAmbientNodeProxyAgent } from "openclaw/plugin-sdk/extension-shared";
5
- import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
6
6
  //#region extensions/feishu/src/client-timeout.ts
7
7
  /** Default HTTP timeout for Feishu API requests (30 seconds). */
8
8
  const FEISHU_HTTP_TIMEOUT_MS = 3e4;