@openclaw/feishu 2026.6.11-beta.2 → 2026.7.1-beta.1

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
@@ -1,5 +1,5 @@
1
1
  import { r as listEnabledFeishuAccounts } from "./accounts-Cfzht2Hc.js";
2
- import { a as setFeishuNamedAccountEnabled, i as feishuSetupAdapter, n as feishuSetupWizard, r as runFeishuLogin, t as feishuPlugin } from "./channel-C1MthXp0.js";
2
+ import { a as setFeishuNamedAccountEnabled, i as feishuSetupAdapter, n as feishuSetupWizard, r as runFeishuLogin, t as feishuPlugin } from "./channel-C1Uun9zo.js";
3
3
  import { a as parseFeishuTargetId, i as parseFeishuDirectConversationId, n as buildFeishuModelOverrideParentCandidates, r as parseFeishuConversationId, t as buildFeishuConversationId } from "./conversation-id-DuL575sn.js";
4
4
  import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
5
5
  import { r as createFeishuClient } from "./client-BwgAJuvo.js";
@@ -135,7 +135,7 @@ async function pollAppRegistration(params) {
135
135
  * otherwise the pattern is corrupted and cannot be scanned.
136
136
  */
137
137
  async function printQrCode(url) {
138
- const output = await renderQrTerminal(url);
138
+ const output = await renderQrTerminal(url, { small: true });
139
139
  process.stdout.write(output.endsWith("\n") ? output : `${output}\n`);
140
140
  }
141
141
  /**
@@ -3,14 +3,14 @@ import { n as looksLikeFeishuId, r as normalizeFeishuTarget, t as detectIdType }
3
3
  import { n as createFeishuSendReceipt, s as createFeishuCardInteractionEnvelope } from "./send-result-DSsIa4-p.js";
4
4
  import { a as parseFeishuTargetId, i as parseFeishuDirectConversationId, n as buildFeishuModelOverrideParentCandidates, r as parseFeishuConversationId, t as buildFeishuConversationId } from "./conversation-id-DuL575sn.js";
5
5
  import { t as messageActionTargetAliases } from "./security-audit-BIeA3W3Q.js";
6
- import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-ChjJKAJ9.js";
6
+ import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-DLaBl9m4.js";
7
7
  import { t as collectFeishuSecurityAuditFindings } from "./security-audit-shared-BIHeF-S_.js";
8
8
  import { t as resolveFeishuSessionConversation } from "./session-conversation-CZSMgac-.js";
9
9
  import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
10
10
  import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
11
11
  import { adaptScopedAccountAccessor, createHybridChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
12
12
  import { buildChannelOutboundSessionRoute, createChatChannelPlugin, stripChannelTargetPrefix } from "openclaw/plugin-sdk/channel-core";
13
- import { createRuntimeOutboundDelegates, defineChannelMessageAdapter } from "openclaw/plugin-sdk/channel-outbound";
13
+ import { createAccountStatusSink, createRuntimeOutboundDelegates, defineChannelMessageAdapter } from "openclaw/plugin-sdk/channel-outbound";
14
14
  import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing";
15
15
  import { createAllowlistProviderGroupPolicyWarningCollector, projectConfigAccountIdWarningCollector } from "openclaw/plugin-sdk/channel-policy";
16
16
  import { getSessionBindingService } from "openclaw/plugin-sdk/conversation-runtime";
@@ -1433,7 +1433,7 @@ function applyNewAppSecurityPolicy(cfg, accountId, openId, groupPolicy) {
1433
1433
  }
1434
1434
  let appRegistrationModulePromise = null;
1435
1435
  const loadAppRegistrationModule = async () => {
1436
- appRegistrationModulePromise ??= import("./app-registration-tgQJUcv3.js");
1436
+ appRegistrationModulePromise ??= import("./app-registration-DapxBG7t.js");
1437
1437
  return await appRegistrationModulePromise;
1438
1438
  };
1439
1439
  async function promptFeishuDomain(params) {
@@ -1659,7 +1659,7 @@ const feishuSetupWizard = {
1659
1659
  });
1660
1660
  let probeResult = null;
1661
1661
  if (configured && account.configured) try {
1662
- const { probeFeishu } = await import("./probe-EyeJQb3C.js").then((n) => n.n);
1662
+ const { probeFeishu } = await import("./probe-Cv2M2Ivr.js").then((n) => n.n);
1663
1663
  probeResult = await probeFeishu(account);
1664
1664
  } catch {}
1665
1665
  if (!configured) return [formatFeishuStatusLine("needs-credentials")];
@@ -1735,7 +1735,7 @@ const meta = {
1735
1735
  order: 70,
1736
1736
  preferSessionLookupForAnnounceTarget: true
1737
1737
  };
1738
- const loadFeishuChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-CiQqumBC.js"), "feishuChannelRuntime");
1738
+ const loadFeishuChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-Cjc4wDNg.js"), "feishuChannelRuntime");
1739
1739
  function toFeishuMessageSendResult(result, kind) {
1740
1740
  const receipt = result.receipt ?? createFeishuSendReceipt({
1741
1741
  messageId: result.messageId,
@@ -2551,7 +2551,7 @@ const feishuPlugin = createChatChannelPlugin({
2551
2551
  })
2552
2552
  }),
2553
2553
  gateway: { startAccount: async (ctx) => {
2554
- const { monitorFeishuProvider } = await import("./monitor-CxUQtU--.js");
2554
+ const { monitorFeishuProvider } = await import("./monitor-CQo4C7q9.js");
2555
2555
  const account = resolveFeishuRuntimeAccount({
2556
2556
  cfg: ctx.cfg,
2557
2557
  accountId: ctx.accountId
@@ -2562,12 +2562,17 @@ const feishuPlugin = createChatChannelPlugin({
2562
2562
  port
2563
2563
  });
2564
2564
  ctx.log?.info(`starting feishu[${ctx.accountId}] (mode: ${account.config?.connectionMode ?? "websocket"})`);
2565
+ const statusSink = createAccountStatusSink({
2566
+ accountId: ctx.accountId,
2567
+ setStatus: ctx.setStatus
2568
+ });
2565
2569
  return monitorFeishuProvider({
2566
2570
  config: ctx.cfg,
2567
2571
  runtime: ctx.runtime,
2568
2572
  channelRuntime: ctx.channelRuntime,
2569
2573
  abortSignal: ctx.abortSignal,
2570
- accountId: ctx.accountId
2574
+ accountId: ctx.accountId,
2575
+ statusSink
2571
2576
  });
2572
2577
  } },
2573
2578
  message: feishuMessageAdapter
@@ -1,2 +1,2 @@
1
- import { t as feishuPlugin } from "./channel-C1MthXp0.js";
1
+ import { t as feishuPlugin } from "./channel-C1Uun9zo.js";
2
2
  export { feishuPlugin };
@@ -1,10 +1,10 @@
1
1
  import { o as resolveFeishuAccount, s as resolveFeishuRuntimeAccount, v as parseFeishuCommentTarget } from "./accounts-Cfzht2Hc.js";
2
- import { h as listFeishuDirectoryPeers, m as listFeishuDirectoryGroups, o as buildFeishuPresentationCardElements } from "./channel-C1MthXp0.js";
2
+ import { h as listFeishuDirectoryPeers, m as listFeishuDirectoryGroups, o as buildFeishuPresentationCardElements } from "./channel-C1Uun9zo.js";
3
3
  import { r as createFeishuClient } from "./client-BwgAJuvo.js";
4
4
  import { c as getChatInfo, l as getChatMembers, r as cleanupAmbientCommentTypingReaction, t as deliverCommentThreadText, u as getFeishuMemberInfo } from "./drive-djUl8IRC.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-B0nDqief.js";
7
- import { t as probeFeishu } from "./probe-EyeJQb3C.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, y as resolveFeishuIdentityHeaderTitle } from "./send-BcPh0I15.js";
7
+ import { t as probeFeishu } from "./probe-Cv2M2Ivr.js";
8
8
  import { interactiveReplyToPresentation, normalizeInteractiveReply, normalizeMessagePresentation, renderMessagePresentationFallbackText, resolveInteractiveTextFallback } from "openclaw/plugin-sdk/interactive-runtime";
9
9
  import { isRecord, normalizeLowercaseStringOrEmpty, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
10
10
  import path from "node:path";
@@ -230,7 +230,7 @@ function buildFeishuPayloadCard(params) {
230
230
  presentation
231
231
  })
232
232
  }];
233
- const identityTitle = params.identity ? params.identity.emoji ? `${params.identity.emoji} ${params.identity.name ?? ""}`.trim() : params.identity.name ?? "" : "";
233
+ const identityTitle = resolveFeishuIdentityHeaderTitle(params.identity);
234
234
  const title = presentation?.title ?? identityTitle;
235
235
  const template = resolveFeishuCardTemplate(presentation?.tone === "danger" ? "red" : presentation?.tone === "warning" ? "orange" : presentation?.tone === "success" ? "green" : "blue");
236
236
  return markRenderedFeishuCard({
@@ -463,7 +463,7 @@ const feishuOutbound = {
463
463
  }).config?.renderMode ?? "auto";
464
464
  if (renderMode === "card" || renderMode === "auto" && shouldUseCard(text)) {
465
465
  const header = identity ? {
466
- title: identity.emoji ? `${identity.emoji} ${identity.name ?? ""}`.trim() : identity.name ?? "",
466
+ title: resolveFeishuIdentityHeaderTitle(identity),
467
467
  template: "blue"
468
468
  } : void 0;
469
469
  return await sendStructuredCardFeishu({
@@ -1,9 +1,9 @@
1
1
  import { r as listEnabledFeishuAccounts, s as resolveFeishuRuntimeAccount } from "./accounts-Cfzht2Hc.js";
2
- import { f as fetchBotIdentityForMonitor } from "./monitor.state-CGL1occz.js";
2
+ import { f as fetchBotIdentityForMonitor } from "./monitor.state-R4ZgNpac.js";
3
3
  //#region extensions/feishu/src/monitor.ts
4
4
  let monitorAccountRuntimePromise;
5
5
  async function loadMonitorAccountRuntime() {
6
- monitorAccountRuntimePromise ??= import("./monitor.account-C3SH96dD.js");
6
+ monitorAccountRuntimePromise ??= import("./monitor.account-08br3nkU.js");
7
7
  return await monitorAccountRuntimePromise;
8
8
  }
9
9
  async function monitorFeishuProvider(opts = {}) {
@@ -22,7 +22,8 @@ async function monitorFeishuProvider(opts = {}) {
22
22
  account,
23
23
  channelRuntime: opts.channelRuntime,
24
24
  runtime: opts.runtime,
25
- abortSignal: opts.abortSignal
25
+ abortSignal: opts.abortSignal,
26
+ ...opts.statusSink ? { statusSink: opts.statusSink } : {}
26
27
  });
27
28
  }
28
29
  const accounts = listEnabledFeishuAccounts(cfg);
@@ -53,7 +54,8 @@ async function monitorFeishuProvider(opts = {}) {
53
54
  kind: "prefetched",
54
55
  botOpenId,
55
56
  botName
56
- }
57
+ },
58
+ ...opts.statusSink ? { statusSink: opts.statusSink } : {}
57
59
  }));
58
60
  }
59
61
  await Promise.all(monitorPromises);
@@ -1,16 +1,16 @@
1
1
  import { _ as normalizeCommentFileType, c as encodeQuery, d as isRecord$1, f as normalizeString, g as buildFeishuCommentTarget, h as requestFeishuApi, l as extractReplyText, m as readString, o as resolveFeishuAccount, p as parseCommentContentElements, s as resolveFeishuRuntimeAccount } from "./accounts-Cfzht2Hc.js";
2
2
  import { i as resolveReceiveIdType } from "./targets-BUjQ1TcA.js";
3
- import { c as normalizeFeishuAllowEntry, d as resolveFeishuGroupConversationIngressAccess, f as resolveFeishuGroupSenderActivationIngressAccess, l as resolveFeishuDmIngressAccess, p as resolveFeishuReplyPolicy, s as hasExplicitFeishuGroupConfig, u as resolveFeishuGroupConfig } from "./channel-C1MthXp0.js";
3
+ import { c as normalizeFeishuAllowEntry, d as resolveFeishuGroupConversationIngressAccess, f as resolveFeishuGroupSenderActivationIngressAccess, l as resolveFeishuDmIngressAccess, p as resolveFeishuReplyPolicy, s as hasExplicitFeishuGroupConfig, u as resolveFeishuGroupConfig } from "./channel-C1Uun9zo.js";
4
4
  import { c as decodeFeishuCardAction, o as buildFeishuCardActionTextFallback, s as createFeishuCardInteractionEnvelope } from "./send-result-DSsIa4-p.js";
5
5
  import { t as buildFeishuConversationId } from "./conversation-id-DuL575sn.js";
6
6
  import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
7
7
  import { a as getFeishuUserAgent, i as createFeishuWSClient, n as createEventDispatcher, r as createFeishuClient } from "./client-BwgAJuvo.js";
8
8
  import { c as getChatInfo, i as createCommentTypingReactionLifecycle, t as deliverCommentThreadText } from "./drive-djUl8IRC.js";
9
9
  import { t as createFeishuThreadBindingManager } from "./thread-bindings-V0bwk0A1.js";
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-B0nDqief.js";
12
- import { i as waitForAbortableDelay, r as raceWithTimeoutAndAbort } from "./probe-EyeJQb3C.js";
13
- import { a as clearFeishuBotIdentityState, c as httpServers, d as wsClients, f as fetchBotIdentityForMonitor, i as botOpenIds, l as recordWebhookStatus, n as FEISHU_WEBHOOK_MAX_BODY_BYTES, o as closeTrackedFeishuHttpServer, r as botNames, s as feishuWebhookRateLimiter, t as FEISHU_WEBHOOK_BODY_TIMEOUT_MS, u as setFeishuBotIdentityState } from "./monitor.state-CGL1occz.js";
10
+ import { createReplyPrefixContext, evaluateSupplementalContextVisibility, getSessionEntry, normalizeAgentId as normalizeAgentId$2, resolveChannelContextVisibilityMode } 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, v as resolveFeishuIdentityEmoji } from "./send-BcPh0I15.js";
12
+ import { i as waitForAbortableDelay, r as raceWithTimeoutAndAbort } from "./probe-Cv2M2Ivr.js";
13
+ import { a as clearFeishuBotIdentityState, c as httpServers, d as wsClients, f as fetchBotIdentityForMonitor, i as botOpenIds, l as recordWebhookStatus, n as FEISHU_WEBHOOK_MAX_BODY_BYTES, o as closeTrackedFeishuHttpServer, r as botNames, s as feishuWebhookRateLimiter, t as FEISHU_WEBHOOK_BODY_TIMEOUT_MS, u as setFeishuBotIdentityState } from "./monitor.state-R4ZgNpac.js";
14
14
  import { createChannelMessageReplyPipeline, formatChannelProgressDraftLineForEntry, isChannelProgressDraftWorkToolName, resolveAgentOutboundIdentity } from "openclaw/plugin-sdk/channel-outbound";
15
15
  import { createChannelPairingController, createChannelPairingController as createChannelPairingController$1 } from "openclaw/plugin-sdk/channel-pairing";
16
16
  import { ensureConfiguredBindingRouteReady, resolveConfiguredBindingRoute, resolveRuntimeConversationBindingRoute } from "openclaw/plugin-sdk/conversation-runtime";
@@ -32,6 +32,7 @@ import { resolvePinnedMainDmOwnerFromAllowlist, safeEqualSecret } from "openclaw
32
32
  import { buildChannelInboundEventContext, toInboundMediaFacts } from "openclaw/plugin-sdk/channel-inbound";
33
33
  import { DEFAULT_GROUP_HISTORY_LIMIT, createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
34
34
  import { resolveDefaultGroupPolicy, resolveOpenProviderRuntimeGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
35
+ import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
35
36
  import { resolveChannelConfigWrites } from "openclaw/plugin-sdk/channel-config-writes";
36
37
  import { formatReasoningMessage } from "openclaw/plugin-sdk/agent-runtime";
37
38
  import { logTypingFailure } from "openclaw/plugin-sdk/channel-feedback";
@@ -844,10 +845,11 @@ function resolveFeishuReasoningPreviewEnabled(params) {
844
845
  const configDefault = resolveFeishuConfigReasoningDefault(params.cfg, params.agentId);
845
846
  if (!params.sessionKey) return configDefault === "stream";
846
847
  try {
847
- const level = resolveSessionStoreEntry({
848
- store: loadSessionStore(params.storePath, { skipCache: true }),
849
- sessionKey: params.sessionKey
850
- }).existing?.reasoningLevel;
848
+ const level = getSessionEntry({
849
+ storePath: params.storePath,
850
+ sessionKey: params.sessionKey,
851
+ readConsistency: "latest"
852
+ })?.reasoningLevel;
851
853
  if (level === "on" || level === "stream" || level === "off") return level === "stream";
852
854
  } catch {
853
855
  return false;
@@ -919,7 +921,7 @@ async function getToken(creds) {
919
921
  function truncateSummary(text, max = 50) {
920
922
  if (!text) return "";
921
923
  const clean = text.replace(/\n/g, " ").trim();
922
- return clean.length <= max ? clean : clean.slice(0, max - 3) + "...";
924
+ return clean.length <= max ? clean : sliceUtf16Safe(clean, 0, max - 3) + "...";
923
925
  }
924
926
  function hasNaturalStreamingBoundary(text) {
925
927
  return /[\n。!?!?;;::]$/.test(text);
@@ -1455,7 +1457,7 @@ function normalizeEpochMs(timestamp) {
1455
1457
  /** Build a card header from agent identity config. */
1456
1458
  function resolveCardHeader(agentId, identity) {
1457
1459
  const name = identity?.name?.trim() || (agentId === "main" ? "" : agentId);
1458
- const emoji = identity?.emoji?.trim();
1460
+ const emoji = resolveFeishuIdentityEmoji(identity?.emoji);
1459
1461
  const title = (emoji ? `${emoji} ${name}` : name).trim();
1460
1462
  if (!title) return;
1461
1463
  return {
@@ -1472,7 +1474,7 @@ function resolveCardNote(agentId, identity, prefixCtx) {
1472
1474
  }
1473
1475
  function createFeishuReplyDispatcher(params) {
1474
1476
  const core = getFeishuRuntime();
1475
- const { cfg, agentId, chatId, replyToMessageId, typingTargetMessageId: explicitTypingTargetMessageId, skipReplyToInMessages, replyInThread, threadReply, rootId, accountId, identity, mentionTargets } = params;
1477
+ const { cfg, agentId, chatId, sendTarget, replyToMessageId, typingTargetMessageId: explicitTypingTargetMessageId, skipReplyToInMessages, replyInThread, threadReply, rootId, accountId, identity, mentionTargets } = params;
1476
1478
  const sendReplyToMessageId = skipReplyToInMessages ? void 0 : replyToMessageId;
1477
1479
  const typingTargetMessageId = explicitTypingTargetMessageId?.trim() || replyToMessageId;
1478
1480
  const threadReplyMode = threadReply === true;
@@ -1549,6 +1551,7 @@ function createFeishuReplyDispatcher(params) {
1549
1551
  let lastSnapshotTextLength = 0;
1550
1552
  let hasStreamingFinalText = false;
1551
1553
  const deliveredFinalTexts = /* @__PURE__ */ new Set();
1554
+ let sentIndependentBlockText = false;
1552
1555
  let partialUpdateQueue = Promise.resolve();
1553
1556
  let streamingStartPromise = null;
1554
1557
  let streamingClosedForReply = false;
@@ -1611,8 +1614,9 @@ function createFeishuReplyDispatcher(params) {
1611
1614
  try {
1612
1615
  const cardHeader = resolveCardHeader(agentId, identity);
1613
1616
  const cardNote = resolveCardNote(agentId, identity, prefixContext.prefixContext);
1614
- await streaming.start(chatId, resolveReceiveIdType(chatId), {
1615
- replyToMessageId,
1617
+ const streamingTarget = sendTarget.replace(/^(feishu|lark):/i, "").replace(/^(chat|user|group|dm|open_id):/i, "").trim();
1618
+ await streaming.start(streamingTarget, resolveReceiveIdType(sendTarget), {
1619
+ replyToMessageId: sendReplyToMessageId,
1616
1620
  replyInThread: effectiveReplyInThread,
1617
1621
  rootId,
1618
1622
  header: cardHeader,
@@ -1694,7 +1698,7 @@ function createFeishuReplyDispatcher(params) {
1694
1698
  send: async ({ mediaUrl }) => {
1695
1699
  const result = await sendMediaFeishu({
1696
1700
  cfg,
1697
- to: chatId,
1701
+ to: sendTarget,
1698
1702
  mediaUrl,
1699
1703
  replyToMessageId: sendReplyToMessageId,
1700
1704
  replyInThread: effectiveReplyInThread,
@@ -1711,7 +1715,7 @@ function createFeishuReplyDispatcher(params) {
1711
1715
  sendChunk: async ({ chunk }) => {
1712
1716
  await sendMessageFeishu({
1713
1717
  cfg,
1714
- to: chatId,
1718
+ to: sendTarget,
1715
1719
  text: chunk,
1716
1720
  replyToMessageId: sendReplyToMessageId,
1717
1721
  replyInThread: effectiveReplyInThread,
@@ -1732,7 +1736,7 @@ function createFeishuReplyDispatcher(params) {
1732
1736
  sendChunk: async ({ chunk }) => {
1733
1737
  await sendMessageFeishu({
1734
1738
  cfg,
1735
- to: chatId,
1739
+ to: sendTarget,
1736
1740
  text: chunk,
1737
1741
  replyToMessageId: sendReplyToMessageId,
1738
1742
  replyInThread: effectiveReplyInThread,
@@ -1753,7 +1757,7 @@ function createFeishuReplyDispatcher(params) {
1753
1757
  }
1754
1758
  await sendMessageFeishu({
1755
1759
  cfg,
1756
- to: chatId,
1760
+ to: sendTarget,
1757
1761
  text: NO_VISIBLE_REPLY_FALLBACK_TEXT,
1758
1762
  replyToMessageId: sendReplyToMessageId,
1759
1763
  replyInThread: effectiveReplyInThread,
@@ -1789,6 +1793,7 @@ function createFeishuReplyDispatcher(params) {
1789
1793
  if (!replyLifecycleStateInitialized) {
1790
1794
  replyLifecycleStateInitialized = true;
1791
1795
  deliveredFinalTexts.clear();
1796
+ sentIndependentBlockText = false;
1792
1797
  streamingClosedForReply = false;
1793
1798
  streamingCloseErroredForReply = false;
1794
1799
  visibleReplySent = false;
@@ -1824,7 +1829,31 @@ function createFeishuReplyDispatcher(params) {
1824
1829
  if (shouldDiscardStreamingPreview) await discardStreamingPreview();
1825
1830
  if (shouldDeliverText) {
1826
1831
  if (info?.kind === "block") {
1827
- if (!useStreamingCard) return;
1832
+ if (!useStreamingCard) {
1833
+ if (coreBlockStreamingEnabled) {
1834
+ const isFirstBlock = !sentIndependentBlockText;
1835
+ await sendChunkedTextReply({
1836
+ text,
1837
+ useCard: false,
1838
+ infoKind: "block",
1839
+ sendChunk: async ({ chunk, isFirst }) => {
1840
+ await sendMessageFeishu({
1841
+ cfg,
1842
+ to: sendTarget,
1843
+ text: chunk,
1844
+ replyToMessageId: sendReplyToMessageId,
1845
+ replyInThread: effectiveReplyInThread,
1846
+ allowTopLevelReplyFallback,
1847
+ accountId,
1848
+ ...isFirstBlock && isFirst && mentionTargets?.length ? { mentions: mentionTargets } : {}
1849
+ });
1850
+ }
1851
+ });
1852
+ sentIndependentBlockText = true;
1853
+ if (hasMedia) await sendMediaReplies(payload);
1854
+ }
1855
+ return;
1856
+ }
1828
1857
  startStreaming();
1829
1858
  if (streamingStartPromise) await streamingStartPromise;
1830
1859
  }
@@ -1858,7 +1887,7 @@ function createFeishuReplyDispatcher(params) {
1858
1887
  sendChunk: async ({ chunk }) => {
1859
1888
  await sendStructuredCardFeishu({
1860
1889
  cfg,
1861
- to: chatId,
1890
+ to: sendTarget,
1862
1891
  text: chunk,
1863
1892
  replyToMessageId: sendReplyToMessageId,
1864
1893
  replyInThread: effectiveReplyInThread,
@@ -1876,7 +1905,7 @@ function createFeishuReplyDispatcher(params) {
1876
1905
  sendChunk: async ({ chunk, isFirst }) => {
1877
1906
  await sendMessageFeishu({
1878
1907
  cfg,
1879
- to: chatId,
1908
+ to: sendTarget,
1880
1909
  text: chunk,
1881
1910
  replyToMessageId: sendReplyToMessageId,
1882
1911
  replyInThread: effectiveReplyInThread,
@@ -2098,7 +2127,7 @@ function formatMentionNameForAgentContext(name) {
2098
2127
  const normalized = Array.from(name, (char) => {
2099
2128
  return char.charCodeAt(0) < 32 || char === "[" || char === "]" ? " " : char;
2100
2129
  }).join("").replace(/\s+/g, " ").trim();
2101
- const bounded = normalized.length > MAX_MENTION_CONTEXT_NAME_LENGTH ? `${normalized.slice(0, MAX_MENTION_CONTEXT_NAME_LENGTH - 3)}...` : normalized;
2130
+ const bounded = normalized.length > MAX_MENTION_CONTEXT_NAME_LENGTH ? `${truncateUtf16Safe(normalized, MAX_MENTION_CONTEXT_NAME_LENGTH - 3)}...` : normalized;
2102
2131
  return JSON.stringify(bounded || "unknown");
2103
2132
  }
2104
2133
  function buildFeishuAgentBody(params) {
@@ -2538,7 +2567,7 @@ async function handleFeishuMessage(params) {
2538
2567
  return;
2539
2568
  }
2540
2569
  }
2541
- const preview = ctx.content.replace(/\s+/g, " ").slice(0, 160);
2570
+ const preview = truncateUtf16Safe(ctx.content.replace(/\s+/g, " "), 160);
2542
2571
  const inboundLabel = isGroup ? `Feishu[${account.accountId}] message in group ${ctx.chatId}` : `Feishu[${account.accountId}] DM from ${ctx.senderOpenId}`;
2543
2572
  const contextVisibilityMode = resolveChannelContextVisibilityMode({
2544
2573
  cfg: effectiveCfg,
@@ -2576,7 +2605,7 @@ async function handleFeishuMessage(params) {
2576
2605
  senderType: quotedMessageInfo.senderType
2577
2606
  })) {
2578
2607
  quotedContent = quotedMessageInfo.content;
2579
- log(`feishu[${account.accountId}]: fetched quoted message: ${quotedContent?.slice(0, 100)}`);
2608
+ log(`feishu[${account.accountId}]: fetched quoted message: ${truncateUtf16Safe(quotedContent, 100)}`);
2580
2609
  } else if (quotedMessageInfo) log(`feishu[${account.accountId}]: skipped quoted message from sender ${quotedMessageInfo.senderId ?? "unknown"} (mode=${contextVisibilityMode})`);
2581
2610
  } catch (err) {
2582
2611
  log(`feishu[${account.accountId}]: failed to fetch quoted message: ${String(err)}`);
@@ -2906,6 +2935,7 @@ async function handleFeishuMessage(params) {
2906
2935
  agentId,
2907
2936
  runtime,
2908
2937
  chatId: ctx.chatId,
2938
+ sendTarget: feishuTo,
2909
2939
  allowReasoningPreview,
2910
2940
  replyToMessageId: replyTargetMessageId,
2911
2941
  typingTargetMessageId,
@@ -3049,6 +3079,7 @@ async function handleFeishuMessage(params) {
3049
3079
  agentId: route.agentId,
3050
3080
  runtime,
3051
3081
  chatId: ctx.chatId,
3082
+ sendTarget: feishuTo,
3052
3083
  allowReasoningPreview,
3053
3084
  replyToMessageId: replyTargetMessageId,
3054
3085
  typingTargetMessageId,
@@ -3901,7 +3932,7 @@ function safeJsonStringify(value) {
3901
3932
  function truncatePromptText(text, maxLength = FEISHU_PROMPT_TEXT_LIMIT) {
3902
3933
  const normalized = normalizeString(text);
3903
3934
  if (!normalized) return "";
3904
- return normalized.length > maxLength ? `${normalized.slice(0, maxLength - 1)}…` : normalized;
3935
+ return normalized.length > maxLength ? `${sliceUtf16Safe(normalized, 0, maxLength - 1)}…` : normalized;
3905
3936
  }
3906
3937
  function formatPromptTextValue(text) {
3907
3938
  return safeJsonStringify(truncatePromptText(text) || "");
@@ -4474,7 +4505,7 @@ async function resolveDriveCommentEventTurn(params) {
4474
4505
  nearestBotWholeCommentAfter: resolved.context.nearestBotWholeCommentAfter,
4475
4506
  nearestBotWholeCommentBefore: resolved.context.nearestBotWholeCommentBefore
4476
4507
  });
4477
- const preview = prompt.replace(/\s+/g, " ").slice(0, 160);
4508
+ const preview = truncateUtf16Safe(prompt.replace(/\s+/g, " "), 160);
4478
4509
  return {
4479
4510
  eventId: resolved.eventId,
4480
4511
  messageId: `drive-comment:${resolved.eventId}`,
@@ -4933,7 +4964,7 @@ function resolveFeishuDebounceMentions(params) {
4933
4964
  const botMentions = merged.filter((mention) => mention.id.open_id?.trim() === normalizedBotOpenId);
4934
4965
  return botMentions.length > 0 ? botMentions : void 0;
4935
4966
  }
4936
- function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, runtime, chatHistories, fireAndForget, handleMessage, resolveDebounceText: resolveText, hasProcessedMessage, recordProcessedMessage, getBotOpenId = () => void 0, getBotName = () => void 0, resolveSequentialKey = ({ accountId: accountIdLocal, event }) => `feishu:${accountIdLocal}:${event.message.chat_id?.trim() || "unknown"}` }) {
4967
+ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, runtime, chatHistories, fireAndForget, handleMessage, resolveDebounceText: resolveText, hasProcessedMessage, recordProcessedMessage, getBotOpenId = () => void 0, getBotName = () => void 0, resolveSequentialKey = ({ accountId: accountIdLocal, event }) => `feishu:${accountIdLocal}:${event.message.chat_id?.trim() || "unknown"}`, statusSink }) {
4937
4968
  const inboundDebounceMs = channelRuntime.debounce.resolveInboundDebounceMs({
4938
4969
  cfg,
4939
4970
  channel: "feishu"
@@ -5034,6 +5065,7 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
5034
5065
  }
5035
5066
  });
5036
5067
  return async (data) => {
5068
+ statusSink?.({ lastEventAt: Date.now() });
5037
5069
  const event = parseFeishuMessageEventPayload(data);
5038
5070
  if (!event) {
5039
5071
  error(`feishu[${accountId}]: ignoring malformed message event payload`);
@@ -5161,7 +5193,7 @@ function waitForFeishuWsCycleEnd(params) {
5161
5193
  params.terminalError.then(finish);
5162
5194
  });
5163
5195
  }
5164
- async function monitorWebSocket({ account, accountId, runtime, abortSignal, eventDispatcher }) {
5196
+ async function monitorWebSocket({ account, accountId, runtime, abortSignal, eventDispatcher, statusSink }) {
5165
5197
  const log = runtime?.log ?? console.log;
5166
5198
  const error = runtime?.error ?? console.error;
5167
5199
  let attempt = 0;
@@ -5180,8 +5212,28 @@ async function monitorWebSocket({ account, accountId, runtime, abortSignal, even
5180
5212
  }
5181
5213
  error(`feishu[${accountId}]: WebSocket SDK reported recoverable error: ${formatFeishuWsErrorForLog(err)}`);
5182
5214
  };
5215
+ const publishWsConnected = () => {
5216
+ const connectedAt = Date.now();
5217
+ statusSink?.({
5218
+ connected: true,
5219
+ lastConnectedAt: connectedAt,
5220
+ lastEventAt: connectedAt,
5221
+ lastError: null
5222
+ });
5223
+ };
5224
+ const publishWsReconnecting = () => {
5225
+ statusSink?.({
5226
+ connected: false,
5227
+ lastEventAt: Date.now()
5228
+ });
5229
+ };
5183
5230
  log(`feishu[${accountId}]: starting WebSocket connection...`);
5184
- wsClient = await createFeishuWSClient(account, { onError: handleWsError });
5231
+ wsClient = await createFeishuWSClient(account, {
5232
+ onError: handleWsError,
5233
+ onReady: publishWsConnected,
5234
+ onReconnected: publishWsConnected,
5235
+ onReconnecting: publishWsReconnecting
5236
+ });
5185
5237
  if (abortSignal?.aborted) {
5186
5238
  cleanupFeishuWsClient({
5187
5239
  accountId,
@@ -5216,6 +5268,10 @@ async function monitorWebSocket({ account, accountId, runtime, abortSignal, even
5216
5268
  clearIdentity: false
5217
5269
  });
5218
5270
  if (abortSignal?.aborted) break;
5271
+ statusSink?.({
5272
+ connected: false,
5273
+ lastEventAt: Date.now()
5274
+ });
5219
5275
  attempt += 1;
5220
5276
  const delayMs = getFeishuWsReconnectDelayMs(attempt);
5221
5277
  error(`feishu[${accountId}]: WebSocket connection ended, recreating client in ${delayMs}ms: ${formatFeishuWsErrorForLog(cycleEnd)}`);
@@ -5228,6 +5284,10 @@ async function monitorWebSocket({ account, accountId, runtime, abortSignal, even
5228
5284
  clearIdentity: false
5229
5285
  });
5230
5286
  if (abortSignal?.aborted) break;
5287
+ statusSink?.({
5288
+ connected: false,
5289
+ lastEventAt: Date.now()
5290
+ });
5231
5291
  attempt += 1;
5232
5292
  const delayMs = getFeishuWsReconnectDelayMs(attempt);
5233
5293
  error(`feishu[${accountId}]: WebSocket start failed, retrying in ${delayMs}ms: ${formatFeishuWsErrorForLog(err)}`);
@@ -5241,7 +5301,7 @@ async function monitorWebSocket({ account, accountId, runtime, abortSignal, even
5241
5301
  clearIdentity: true
5242
5302
  });
5243
5303
  }
5244
- async function monitorWebhook({ account, accountId, runtime, abortSignal, eventDispatcher }) {
5304
+ async function monitorWebhook({ account, accountId, runtime, abortSignal, eventDispatcher, statusSink }) {
5245
5305
  const log = runtime?.log ?? console.log;
5246
5306
  const error = runtime?.error ?? console.error;
5247
5307
  const encryptKey = account.encryptKey?.trim();
@@ -5254,6 +5314,13 @@ async function monitorWebhook({ account, accountId, runtime, abortSignal, eventD
5254
5314
  server.on("request", (req, res) => {
5255
5315
  res.on("finish", () => {
5256
5316
  recordWebhookStatus(runtime, accountId, path, res.statusCode);
5317
+ if (res.statusCode >= 200 && res.statusCode < 300) {
5318
+ const inboundAt = Date.now();
5319
+ statusSink?.({
5320
+ lastEventAt: inboundAt,
5321
+ lastTransportActivityAt: inboundAt
5322
+ });
5323
+ }
5257
5324
  });
5258
5325
  if (!applyBasicWebhookRequestGuards({
5259
5326
  req,
@@ -5338,6 +5405,13 @@ async function monitorWebhook({ account, accountId, runtime, abortSignal, eventD
5338
5405
  abortSignal?.addEventListener("abort", handleAbort, { once: true });
5339
5406
  server.listen(port, host, () => {
5340
5407
  log(`feishu[${accountId}]: Webhook server listening on ${host}:${port}`);
5408
+ const webhookConnectedAt = Date.now();
5409
+ statusSink?.({
5410
+ connected: true,
5411
+ lastConnectedAt: webhookConnectedAt,
5412
+ lastEventAt: webhookConnectedAt,
5413
+ lastError: null
5414
+ });
5341
5415
  });
5342
5416
  server.on("error", (err) => {
5343
5417
  error(`feishu[${accountId}]: Webhook server error: ${err}`);
@@ -5505,7 +5579,8 @@ function registerEventHandlers(eventDispatcher, context) {
5505
5579
  recordProcessedMessage: recordProcessedFeishuMessage,
5506
5580
  getBotOpenId: (id) => botOpenIds.get(id),
5507
5581
  getBotName: (id) => botNames.get(id),
5508
- resolveSequentialKey: getFeishuSequentialKey
5582
+ resolveSequentialKey: getFeishuSequentialKey,
5583
+ ...context.statusSink ? { statusSink: context.statusSink } : {}
5509
5584
  }),
5510
5585
  "im.message.message_read_v1": async () => {},
5511
5586
  "im.chat.access_event.bot_p2p_chat_entered_v1": async () => {},
@@ -5656,24 +5731,27 @@ async function monitorSingleAccount(params) {
5656
5731
  registerEventHandlers(eventDispatcher, {
5657
5732
  cfg,
5658
5733
  accountId,
5659
- channelRuntime: params.channelRuntime ?? getFeishuRuntime().channel,
5734
+ channelRuntime: params.channelRuntime?.inbound ? params.channelRuntime : getFeishuRuntime().channel,
5660
5735
  runtime,
5661
5736
  chatHistories,
5662
- fireAndForget: params.fireAndForget ?? true
5737
+ fireAndForget: params.fireAndForget ?? true,
5738
+ ...params.statusSink ? { statusSink: params.statusSink } : {}
5663
5739
  });
5664
5740
  if (connectionMode === "webhook") return await monitorWebhook({
5665
5741
  account,
5666
5742
  accountId,
5667
5743
  runtime,
5668
5744
  abortSignal,
5669
- eventDispatcher
5745
+ eventDispatcher,
5746
+ ...params.statusSink ? { statusSink: params.statusSink } : {}
5670
5747
  });
5671
5748
  return await monitorWebSocket({
5672
5749
  account,
5673
5750
  accountId,
5674
5751
  runtime,
5675
5752
  abortSignal,
5676
- eventDispatcher
5753
+ eventDispatcher,
5754
+ ...params.statusSink ? { statusSink: params.statusSink } : {}
5677
5755
  });
5678
5756
  } finally {
5679
5757
  threadBindingManager?.stop();
@@ -1,4 +1,4 @@
1
- import { t as probeFeishu } from "./probe-EyeJQb3C.js";
1
+ import { t as probeFeishu } from "./probe-Cv2M2Ivr.js";
2
2
  import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
3
3
  import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  import { WEBHOOK_ANOMALY_COUNTER_DEFAULTS, WEBHOOK_RATE_LIMIT_DEFAULTS, createFixedWindowRateLimiter, createWebhookAnomalyTracker } from "openclaw/plugin-sdk/webhook-ingress";
@@ -41,6 +41,7 @@ function waitForAbortableDelay(delayMs, abortSignal) {
41
41
  if (abortSignal?.aborted) return Promise.resolve(false);
42
42
  return new Promise((resolve) => {
43
43
  let settled = false;
44
+ let timer = void 0;
44
45
  const finish = (value) => {
45
46
  if (settled) return;
46
47
  settled = true;
@@ -56,7 +57,7 @@ function waitForAbortableDelay(delayMs, abortSignal) {
56
57
  finish(false);
57
58
  return;
58
59
  }
59
- const timer = setTimeout(() => finish(true), resolveTimerTimeoutMs(delayMs, 1));
60
+ timer = setTimeout(() => finish(true), resolveTimerTimeoutMs(delayMs, 1));
60
61
  timer.unref?.();
61
62
  });
62
63
  }
@@ -4,10 +4,10 @@ import { createChannelPairingController } from "openclaw/plugin-sdk/channel-pair
4
4
  import { PAIRING_APPROVED_MESSAGE, buildProbeChannelStatusSummary, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/channel-status";
5
5
  import { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
6
6
  import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
7
- import { loadSessionStore, resolveSessionStoreEntry } from "openclaw/plugin-sdk/session-store-runtime";
7
+ import { getSessionEntry } from "openclaw/plugin-sdk/session-store-runtime";
8
8
  import { DEFAULT_ACCOUNT_ID, buildChannelConfigSchema, createActionGate, createDedupeCache } from "openclaw/plugin-sdk/core";
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
12
  import { isRequestBodyLimitError, readRequestBodyWithLimit, requestBodyErrorToText } from "openclaw/plugin-sdk/webhook-ingress";
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 };
13
+ export { DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE, buildAgentMediaPayload, buildChannelConfigSchema, buildProbeChannelStatusSummary, chunkTextForOutbound, createActionGate, createChannelPairingController, createDedupeCache, createDefaultChannelRuntimeState, createReplyPrefixContext, evaluateSupplementalContextVisibility, filterSupplementalContextItems, getSessionEntry, isRequestBodyLimitError, normalizeAgentId, readJsonFileWithFallback, readRequestBodyWithLimit, requestBodyErrorToText, resolveChannelContextVisibilityMode, setFeishuRuntime };
@@ -1,4 +1,4 @@
1
- import { collectConditionalChannelFieldAssignments, collectSimpleChannelFieldAssignments, getChannelSurface, hasOwnProperty, normalizeSecretStringValue } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
1
+ import { collectConditionalChannelFieldAssignments, collectSecretInputAssignment, getChannelSurface, hasConfiguredSecretInputValue, hasOwnProperty, isBaseFieldActiveForChannelSurface, normalizeSecretStringValue } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
2
2
  //#region extensions/feishu/src/secret-contract.ts
3
3
  const secretTargetRegistryEntries = [
4
4
  {
@@ -72,16 +72,34 @@ function collectRuntimeConfigAssignments(params) {
72
72
  const resolved = getChannelSurface(params.config, "feishu");
73
73
  if (!resolved) return;
74
74
  const { channel: feishu, surface } = resolved;
75
- collectSimpleChannelFieldAssignments({
76
- channelKey: "feishu",
77
- field: "appSecret",
78
- channel: feishu,
79
- surface,
75
+ const topLevelAppSecretActive = surface.channelEnabled && hasConfiguredSecretInputValue(feishu.appId, params.defaults) && hasConfiguredSecretInputValue(feishu.appSecret, params.defaults) || isBaseFieldActiveForChannelSurface(surface, "appSecret");
76
+ collectSecretInputAssignment({
77
+ value: feishu.appSecret,
78
+ path: "channels.feishu.appSecret",
79
+ expected: "string",
80
80
  defaults: params.defaults,
81
81
  context: params.context,
82
- topInactiveReason: "no enabled account inherits this top-level Feishu appSecret.",
83
- accountInactiveReason: "Feishu account is disabled."
82
+ active: topLevelAppSecretActive,
83
+ inactiveReason: "no enabled account inherits this top-level Feishu appSecret.",
84
+ apply: (value) => {
85
+ feishu.appSecret = value;
86
+ }
84
87
  });
88
+ if (surface.hasExplicitAccounts) for (const { accountId, account, enabled } of surface.accounts) {
89
+ if (!hasOwnProperty(account, "appSecret")) continue;
90
+ collectSecretInputAssignment({
91
+ value: account.appSecret,
92
+ path: `channels.feishu.accounts.${accountId}.appSecret`,
93
+ expected: "string",
94
+ defaults: params.defaults,
95
+ context: params.context,
96
+ active: enabled,
97
+ inactiveReason: "Feishu account is disabled.",
98
+ apply: (value) => {
99
+ account.appSecret = value;
100
+ }
101
+ });
102
+ }
85
103
  const baseConnectionMode = normalizeSecretStringValue(feishu.connectionMode) === "webhook" ? "webhook" : "websocket";
86
104
  const resolveAccountMode = (account) => hasOwnProperty(account, "connectionMode") ? normalizeSecretStringValue(account.connectionMode) : baseConnectionMode;
87
105
  collectConditionalChannelFieldAssignments({
@@ -1,2 +1,2 @@
1
- import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-ChjJKAJ9.js";
1
+ import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-DLaBl9m4.js";
2
2
  export { channelSecrets, collectRuntimeConfigAssignments, secretTargetRegistryEntries };
@@ -15,6 +15,29 @@ import { Readable } from "node:stream";
15
15
  import { saveMediaBuffer, saveMediaStream } from "openclaw/plugin-sdk/media-store";
16
16
  import { resolvePreferredOpenClawTmpDir, withTempDownloadPath, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
17
17
  import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
18
+ //#region extensions/feishu/src/identity-header.ts
19
+ const emojiSegmenter = typeof Intl !== "undefined" && "Segmenter" in Intl ? new Intl.Segmenter(void 0, { granularity: "grapheme" }) : null;
20
+ const keycapEmojiPattern = /^[0-9#*]\uFE0F?\u20E3$/u;
21
+ const emojiLikeSegmentPattern = /[\p{Emoji_Presentation}\p{Extended_Pictographic}\p{Regional_Indicator}]/u;
22
+ function splitGraphemes(input) {
23
+ if (!emojiSegmenter) return Array.from(input);
24
+ return Array.from(emojiSegmenter.segment(input), (segment) => segment.segment);
25
+ }
26
+ function isEmojiSegment(segment) {
27
+ return keycapEmojiPattern.test(segment) || emojiLikeSegmentPattern.test(segment);
28
+ }
29
+ function resolveFeishuIdentityEmoji(raw) {
30
+ const trimmed = raw?.trim();
31
+ if (!trimmed) return;
32
+ return splitGraphemes(trimmed).filter(isEmojiSegment).join("") || void 0;
33
+ }
34
+ function resolveFeishuIdentityHeaderTitle(identity) {
35
+ if (!identity) return "";
36
+ const name = identity.name?.trim() ?? "";
37
+ const emoji = resolveFeishuIdentityEmoji(identity.emoji);
38
+ return (emoji ? `${emoji} ${name}` : name).trim();
39
+ }
40
+ //#endregion
18
41
  //#region extensions/feishu/src/external-keys.ts
19
42
  const CONTROL_CHARS_RE = /\p{Cc}/u;
20
43
  const MAX_EXTERNAL_KEY_LENGTH = 512;
@@ -1242,4 +1265,4 @@ async function sendMarkdownCardFeishu(params) {
1242
1265
  });
1243
1266
  }
1244
1267
  //#endregion
1245
- export { normalizeFeishuExternalKey as _, sendCardFeishu as a, sendStructuredCardFeishu as c, isFeishuBroadcastMention as d, isMentionForwardRequest as f, shouldSuppressFeishuTextForVoiceMedia as g, sendMediaFeishu as h, resolveFeishuCardTemplate as i, parsePostContent as l, saveMessageResourceFeishu as m, getMessageFeishu as n, sendMarkdownCardFeishu as o, isFeishuGroupChatType as p, listFeishuThreadMessages as r, sendMessageFeishu as s, editMessageFeishu as t, extractMentionTargets as u };
1268
+ export { normalizeFeishuExternalKey as _, sendCardFeishu as a, sendStructuredCardFeishu as c, isFeishuBroadcastMention as d, isMentionForwardRequest as f, shouldSuppressFeishuTextForVoiceMedia as g, sendMediaFeishu as h, resolveFeishuCardTemplate as i, parsePostContent as l, saveMessageResourceFeishu as m, getMessageFeishu as n, sendMarkdownCardFeishu as o, isFeishuGroupChatType as p, listFeishuThreadMessages as r, sendMessageFeishu as s, editMessageFeishu as t, extractMentionTargets as u, resolveFeishuIdentityEmoji as v, resolveFeishuIdentityHeaderTitle 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-C1MthXp0.js";
1
+ import { i as feishuSetupAdapter, n as feishuSetupWizard, t as feishuPlugin } from "./channel-C1Uun9zo.js";
2
2
  export { feishuPlugin, feishuSetupAdapter, feishuSetupWizard };
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "@openclaw/feishu",
3
- "version": "2026.6.11-beta.2",
3
+ "version": "2026.7.1-beta.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/feishu",
9
- "version": "2026.6.11-beta.2",
9
+ "version": "2026.7.1-beta.1",
10
10
  "dependencies": {
11
11
  "@larksuiteoapi/node-sdk": "1.66.0",
12
12
  "typebox": "1.1.39",
13
13
  "zod": "4.4.3"
14
14
  },
15
15
  "peerDependencies": {
16
- "openclaw": ">=2026.6.11-beta.2"
16
+ "openclaw": ">=2026.7.1-beta.1"
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.6.11-beta.2",
3
+ "version": "2026.7.1-beta.1",
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.6.11-beta.2"
16
+ "openclaw": ">=2026.7.1-beta.1"
17
17
  },
18
18
  "peerDependenciesMeta": {
19
19
  "openclaw": {
@@ -47,10 +47,10 @@
47
47
  "minHostVersion": ">=2026.5.29"
48
48
  },
49
49
  "compat": {
50
- "pluginApi": ">=2026.6.11-beta.2"
50
+ "pluginApi": ">=2026.7.1-beta.1"
51
51
  },
52
52
  "build": {
53
- "openclawVersion": "2026.6.11-beta.2"
53
+ "openclawVersion": "2026.7.1-beta.1"
54
54
  },
55
55
  "release": {
56
56
  "publishToClawHub": true,