@openclaw/feishu 2026.7.2-beta.1 → 2026.7.2-beta.2
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 +322 -176
- package/dist/{app-registration-BwQ-aGTe.js → app-registration-BzkyrVZu.js} +11 -11
- package/dist/{channel-DdPQ2HGh.js → channel-X30GQVwc.js} +20 -36
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-DJ_B-bpG.js → channel.runtime-By2uqa3Q.js} +6 -6
- package/dist/{client-BUC-R2Wi.js → client-87BmeMpj.js} +51 -16
- package/dist/{drive-Bpe8ONK_.js → drive-B4E8OXZ0.js} +2 -2
- package/dist/{monitor-M3iYtoh4.js → monitor-CHl0bWzb.js} +2 -2
- package/dist/{monitor.account-F99J862T.js → monitor.account-BSRV2hIF.js} +90 -91
- package/dist/{monitor.startup-DpZzunQn.js → monitor.startup-Cy8NPGAX.js} +1 -1
- package/dist/{probe-CAloGqgG.js → probe-BgboTHIn.js} +1 -1
- package/dist/{send-CpnLYueT.js → send-DrWM_Ilf.js} +57 -7
- package/dist/{send-result-CPS7AozW.js → send-result-DsqTk27v.js} +9 -5
- package/dist/setup-api.js +1 -1
- package/npm-shrinkwrap.json +3 -3
- package/openclaw.plugin.json +10 -8
- package/package.json +4 -4
|
@@ -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-BDoGHJDk.js";
|
|
2
2
|
import { i as resolveReceiveIdType } from "./targets-BUjQ1TcA.js";
|
|
3
|
-
import { C as
|
|
3
|
+
import { A as resolveFeishuChatType, C as resolveFeishuDmIngressAccess, E as resolveFeishuGroupSenderActivationIngressAccess, M as buildFeishuCardActionTextFallback, N as createFeishuCardInteractionEnvelope, O as resolveFeishuReplyPolicy, P as decodeFeishuCardAction, S as normalizeFeishuAllowEntry, T as resolveFeishuGroupConversationIngressAccess, d as chunkFeishuPostMarkdown, f as materializeFeishuPostMarkdownSoftBreaks, k as normalizeFeishuChatType$2, o as resolveFeishuCardTemplate, w as resolveFeishuGroupConfig, x as hasExplicitFeishuGroupConfig } from "./send-result-DsqTk27v.js";
|
|
4
4
|
import { o as resolveConfiguredFeishuGroupSessionScope, t as buildFeishuConversationId } from "./conversation-id-BeJL-wq7.js";
|
|
5
|
+
import { a as getFeishuUserAgent, i as createFeishuWSClient, n as createEventDispatcher, r as createFeishuClient, s as resolveConfiguredHttpTimeoutMs } from "./client-87BmeMpj.js";
|
|
5
6
|
import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
|
|
6
|
-
import {
|
|
7
|
-
import { i as createCommentTypingReactionLifecycle, l as getChatInfo, t as deliverCommentThreadText } from "./drive-Bpe8ONK_.js";
|
|
7
|
+
import { i as createCommentTypingReactionLifecycle, l as getChatInfo, t as deliverCommentThreadText } from "./drive-B4E8OXZ0.js";
|
|
8
8
|
import { t as createFeishuThreadBindingManager } from "./thread-bindings-V0bwk0A1.js";
|
|
9
9
|
import { createReplyPrefixContext, evaluateSupplementalContextVisibility, getSessionEntry, normalizeAgentId as normalizeAgentId$2, resolveChannelContextVisibilityMode } from "./runtime-api.js";
|
|
10
10
|
import { t as readFeishuJsonResponse } from "./json-response-CheljwGr.js";
|
|
11
|
-
import { _ as resolveFeishuIdentityEmoji, c as parsePostContent, d as isMentionForwardRequest, f as isFeishuGroupChatType, g as normalizeFeishuExternalKey, h as shouldSuppressFeishuTextForVoiceMedia, i as sendCardFeishu, l as extractMentionTargets, m as sendMediaFeishu, n as getMessageFeishu, o as sendMessageFeishu, p as saveMessageResourceFeishu, r as listFeishuThreadMessages, s as sendStructuredCardFeishu, u as isFeishuBroadcastMention } from "./send-
|
|
12
|
-
import { i as waitForAbortableDelay, r as raceWithTimeoutAndAbort } from "./probe-
|
|
13
|
-
import { t as fetchBotIdentityForMonitor } from "./monitor.startup-
|
|
11
|
+
import { _ as resolveFeishuIdentityEmoji, c as parsePostContent, d as isMentionForwardRequest, f as isFeishuGroupChatType, g as normalizeFeishuExternalKey, h as shouldSuppressFeishuTextForVoiceMedia, i as sendCardFeishu, l as extractMentionTargets, m as sendMediaFeishu, n as getMessageFeishu, o as sendMessageFeishu, p as saveMessageResourceFeishu, r as listFeishuThreadMessages, s as sendStructuredCardFeishu, u as isFeishuBroadcastMention } from "./send-DrWM_Ilf.js";
|
|
12
|
+
import { i as waitForAbortableDelay, r as raceWithTimeoutAndAbort } from "./probe-BgboTHIn.js";
|
|
13
|
+
import { t as fetchBotIdentityForMonitor } from "./monitor.startup-Cy8NPGAX.js";
|
|
14
14
|
import { createChannelMessageReplyPipeline, formatChannelProgressDraftLineForEntry, isChannelProgressDraftWorkToolName, resolveAgentOutboundIdentity, resolveChannelPreviewStreamMode, resolveChannelStreamingBlockEnabled } 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";
|
|
@@ -33,7 +33,7 @@ import crypto, { createHash } from "node:crypto";
|
|
|
33
33
|
import { buildChannelInboundEventContext, formatInboundMediaUnavailableText, toInboundMediaFacts } from "openclaw/plugin-sdk/channel-inbound";
|
|
34
34
|
import { DEFAULT_GROUP_HISTORY_LIMIT, createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
|
|
35
35
|
import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
36
|
-
import {
|
|
36
|
+
import { createChannelReplayGuard } from "openclaw/plugin-sdk/persistent-dedupe";
|
|
37
37
|
import { resolveChannelConfigWrites } from "openclaw/plugin-sdk/channel-config-writes";
|
|
38
38
|
import { formatReasoningMessage } from "openclaw/plugin-sdk/agent-runtime";
|
|
39
39
|
import { logTypingFailure } from "openclaw/plugin-sdk/channel-feedback";
|
|
@@ -563,12 +563,15 @@ const DEDUP_TTL_MS = 1440 * 60 * 1e3;
|
|
|
563
563
|
const MEMORY_MAX_SIZE = 1e3;
|
|
564
564
|
const STORE_MAX_ENTRIES = 1e4;
|
|
565
565
|
function createFeishuDedupeGuard() {
|
|
566
|
-
return
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
566
|
+
return createChannelReplayGuard({
|
|
567
|
+
dedupe: {
|
|
568
|
+
pluginId: "feishu",
|
|
569
|
+
namespacePrefix: DEDUPE_NAMESPACE_PREFIX,
|
|
570
|
+
ttlMs: DEDUP_TTL_MS,
|
|
571
|
+
memoryMaxSize: MEMORY_MAX_SIZE,
|
|
572
|
+
stateMaxEntries: STORE_MAX_ENTRIES
|
|
573
|
+
},
|
|
574
|
+
buildReplayKey: (messageId) => messageId
|
|
572
575
|
});
|
|
573
576
|
}
|
|
574
577
|
const feishuDedupeState = {
|
|
@@ -590,18 +593,13 @@ function dedupeOptions(namespace, log) {
|
|
|
590
593
|
}
|
|
591
594
|
/**
|
|
592
595
|
* Claims a dedupe key for exclusive handling. Duplicate (already committed)
|
|
593
|
-
* and in-flight keys are reported; blank keys fail open as
|
|
596
|
+
* and in-flight keys are reported; blank keys fail open as invalid so an
|
|
594
597
|
* unidentifiable event is never suppressed.
|
|
595
598
|
*/
|
|
596
599
|
async function claimUnprocessedFeishuMessage(params) {
|
|
597
|
-
const
|
|
598
|
-
if (
|
|
599
|
-
return
|
|
600
|
-
}
|
|
601
|
-
/** Drops an uncommitted claim so a failed handler can retry the message. */
|
|
602
|
-
function releaseFeishuMessageProcessing(messageId, namespace = "global") {
|
|
603
|
-
const key = dedupeKey(messageId);
|
|
604
|
-
if (key) feishuDedupeState.guard.release(key, { namespace });
|
|
600
|
+
const claim = await feishuDedupeState.guard.claim(params.messageId, dedupeOptions(params.namespace, params.log));
|
|
601
|
+
if (claim.kind === "inflight") return { kind: "inflight" };
|
|
602
|
+
return claim;
|
|
605
603
|
}
|
|
606
604
|
/**
|
|
607
605
|
* Claims (unless the caller already holds the claim) and commits a message.
|
|
@@ -612,26 +610,22 @@ async function finalizeFeishuMessageProcessing(params) {
|
|
|
612
610
|
const key = dedupeKey(params.messageId);
|
|
613
611
|
if (!key) return false;
|
|
614
612
|
const options = dedupeOptions(params.namespace, params.log);
|
|
615
|
-
|
|
616
|
-
|
|
613
|
+
const claim = params.processingClaim ?? await feishuDedupeState.guard.claim(key, options);
|
|
614
|
+
if ("kind" in claim && claim.kind !== "claimed") return false;
|
|
615
|
+
return await ("kind" in claim ? claim.handle : claim).commit();
|
|
617
616
|
}
|
|
618
617
|
/** Records a handled message so restart/replay cannot dispatch it again; false when already recorded. */
|
|
619
618
|
async function recordProcessedFeishuMessage(messageId, namespace = "global", log) {
|
|
620
|
-
const
|
|
621
|
-
|
|
622
|
-
return await feishuDedupeState.guard.commit(key, dedupeOptions(namespace, log));
|
|
619
|
+
const claim = await feishuDedupeState.guard.claim(messageId, dedupeOptions(namespace, log));
|
|
620
|
+
return claim.kind === "claimed" ? await claim.handle.commit() : false;
|
|
623
621
|
}
|
|
624
622
|
/** Forgets a recorded message so a retryable synthetic event can be handled on redelivery. */
|
|
625
623
|
async function forgetProcessedFeishuMessage(messageId, namespace = "global", log) {
|
|
626
|
-
|
|
627
|
-
if (!key) return false;
|
|
628
|
-
return await feishuDedupeState.guard.forget(key, dedupeOptions(namespace, log));
|
|
624
|
+
return await feishuDedupeState.guard.forget(messageId, dedupeOptions(namespace, log));
|
|
629
625
|
}
|
|
630
626
|
/** Checks recency without claiming or recording. */
|
|
631
627
|
async function hasProcessedFeishuMessage(messageId, namespace = "global", log) {
|
|
632
|
-
|
|
633
|
-
if (!key) return false;
|
|
634
|
-
return await feishuDedupeState.guard.hasRecent(key, dedupeOptions(namespace, log));
|
|
628
|
+
return await feishuDedupeState.guard.hasRecent(messageId, dedupeOptions(namespace, log));
|
|
635
629
|
}
|
|
636
630
|
/** Loads recent persisted entries into memory at account start; returns the loaded count. */
|
|
637
631
|
async function warmupDedupFromPluginState(namespace, log) {
|
|
@@ -2148,7 +2142,7 @@ async function filterFetchedGroupContextMessages(messages, params) {
|
|
|
2148
2142
|
}) ? message : void 0))).filter((message) => message !== void 0);
|
|
2149
2143
|
}
|
|
2150
2144
|
async function handleFeishuMessage(params) {
|
|
2151
|
-
const { cfg, event, botOpenId, botName, runtime, channelRuntime, chatHistories, accountId,
|
|
2145
|
+
const { cfg, event, botOpenId, botName, runtime, channelRuntime, chatHistories, accountId, processingClaim, messageDedupeKey: messageDedupeKeyOverride } = params;
|
|
2152
2146
|
const account = resolveFeishuRuntimeAccount({
|
|
2153
2147
|
cfg,
|
|
2154
2148
|
accountId
|
|
@@ -2162,7 +2156,7 @@ async function handleFeishuMessage(params) {
|
|
|
2162
2156
|
messageId: messageDedupeKey,
|
|
2163
2157
|
namespace: account.accountId,
|
|
2164
2158
|
log,
|
|
2165
|
-
|
|
2159
|
+
processingClaim
|
|
2166
2160
|
})) {
|
|
2167
2161
|
log(`feishu: skipping duplicate message ${messageId}`);
|
|
2168
2162
|
return;
|
|
@@ -2827,7 +2821,7 @@ async function handleFeishuMessage(params) {
|
|
|
2827
2821
|
wasMentioned,
|
|
2828
2822
|
requireMention
|
|
2829
2823
|
},
|
|
2830
|
-
commands: { authorized: commandAuthorized }
|
|
2824
|
+
commands: { authorized: commandAuthorized === true }
|
|
2831
2825
|
},
|
|
2832
2826
|
extra: {
|
|
2833
2827
|
RootMessageId: ctx.rootId,
|
|
@@ -3863,11 +3857,11 @@ function createFeishuBotMenuHandler(params) {
|
|
|
3863
3857
|
namespace: accountId,
|
|
3864
3858
|
log
|
|
3865
3859
|
});
|
|
3866
|
-
if (claim === "duplicate") {
|
|
3860
|
+
if (claim.kind === "duplicate") {
|
|
3867
3861
|
log(`feishu[${accountId}]: dropping duplicate bot-menu event for ${syntheticMessageId}`);
|
|
3868
3862
|
return;
|
|
3869
3863
|
}
|
|
3870
|
-
if (claim === "inflight") {
|
|
3864
|
+
if (claim.kind === "inflight") {
|
|
3871
3865
|
log(`feishu[${accountId}]: dropping in-flight bot-menu event for ${syntheticMessageId}`);
|
|
3872
3866
|
return;
|
|
3873
3867
|
}
|
|
@@ -3880,7 +3874,7 @@ function createFeishuBotMenuHandler(params) {
|
|
|
3880
3874
|
channelRuntime: params.channelRuntime,
|
|
3881
3875
|
chatHistories,
|
|
3882
3876
|
accountId,
|
|
3883
|
-
|
|
3877
|
+
processingClaim: claim.kind === "claimed" ? claim.handle : void 0
|
|
3884
3878
|
});
|
|
3885
3879
|
const promise = maybeHandleFeishuQuickActionMenu({
|
|
3886
3880
|
cfg,
|
|
@@ -3890,16 +3884,16 @@ function createFeishuBotMenuHandler(params) {
|
|
|
3890
3884
|
accountId
|
|
3891
3885
|
}).then(async (handledMenu) => {
|
|
3892
3886
|
if (handledMenu) {
|
|
3893
|
-
|
|
3887
|
+
if (claim.kind === "claimed") await claim.handle.commit();
|
|
3894
3888
|
return;
|
|
3895
3889
|
}
|
|
3896
3890
|
return await handleLegacyMenu();
|
|
3897
3891
|
}).catch(async (err) => {
|
|
3898
|
-
if (isFeishuRetryableSyntheticEventError(err))
|
|
3899
|
-
|
|
3892
|
+
if (isFeishuRetryableSyntheticEventError(err)) {
|
|
3893
|
+
await forgetProcessedFeishuMessage(syntheticMessageId, accountId, log);
|
|
3894
|
+
if (claim.kind === "claimed") claim.handle.release({ error: err });
|
|
3895
|
+
} else if (claim.kind === "claimed") await claim.handle.commit();
|
|
3900
3896
|
throw err;
|
|
3901
|
-
}).finally(() => {
|
|
3902
|
-
releaseFeishuMessageProcessing(syntheticMessageId, accountId);
|
|
3903
3897
|
});
|
|
3904
3898
|
if (fireAndForget) {
|
|
3905
3899
|
promise.catch((err) => {
|
|
@@ -4088,11 +4082,6 @@ async function resolveParsedCommentContent(params) {
|
|
|
4088
4082
|
linkedDocuments: resolvedLinkedDocuments
|
|
4089
4083
|
};
|
|
4090
4084
|
}
|
|
4091
|
-
async function delayMs(ms) {
|
|
4092
|
-
await new Promise((resolve) => {
|
|
4093
|
-
setTimeout(resolve, ms);
|
|
4094
|
-
});
|
|
4095
|
-
}
|
|
4096
4085
|
function buildDriveCommentTargetUrl(params) {
|
|
4097
4086
|
return `/open-apis/drive/v1/files/${encodeURIComponent(params.fileToken)}/comments/batch_query` + encodeQuery({
|
|
4098
4087
|
file_type: params.fileType,
|
|
@@ -4315,8 +4304,9 @@ async function fetchDriveCommentContext(params) {
|
|
|
4315
4304
|
fetchedMatchedReply = params.replyId ? replies.find((reply) => reply.reply_id?.trim() === params.replyId?.trim()) : void 0;
|
|
4316
4305
|
}
|
|
4317
4306
|
if (params.replyId && !embeddedTargetReply && !fetchedMatchedReply) for (let attempt = 1; attempt <= FEISHU_COMMENT_REPLY_MISS_RETRY_LIMIT; attempt += 1) {
|
|
4307
|
+
if (params.abortSignal?.aborted) break;
|
|
4318
4308
|
params.logger?.(`feishu[${params.accountId}]: retrying comment reply lookup comment=${params.commentId} requested_reply=${params.replyId} attempt=${attempt}/${FEISHU_COMMENT_REPLY_MISS_RETRY_LIMIT} delay_ms=${FEISHU_COMMENT_REPLY_MISS_RETRY_DELAY_MS}`);
|
|
4319
|
-
await params.
|
|
4309
|
+
if (!await waitForAbortableDelay(FEISHU_COMMENT_REPLY_MISS_RETRY_DELAY_MS, params.abortSignal)) break;
|
|
4320
4310
|
const retried = await fetchDriveCommentReplies(params);
|
|
4321
4311
|
if (retried.replies.length > 0) {
|
|
4322
4312
|
params.logger?.(`feishu[${params.accountId}]: fetched retried comment replies comment=${params.commentId} attempt=${attempt} count=${retried.replies.length} log_ids=${safeJsonStringify(retried.logIds)} summary=${summarizeCommentRepliesForLog(retried.replies)}`);
|
|
@@ -4464,7 +4454,7 @@ function buildDriveCommentSurfacePrompt(params) {
|
|
|
4464
4454
|
return lines.join("\n");
|
|
4465
4455
|
}
|
|
4466
4456
|
async function resolveDriveCommentEventCore(params) {
|
|
4467
|
-
const { cfg, accountId, event, account, botOpenId, createClient, verificationTimeoutMs = FEISHU_COMMENT_VERIFY_TIMEOUT_MS, logger,
|
|
4457
|
+
const { cfg, accountId, event, account, botOpenId, createClient, verificationTimeoutMs = FEISHU_COMMENT_VERIFY_TIMEOUT_MS, logger, abortSignal } = params;
|
|
4468
4458
|
const eventId = event.event_id?.trim();
|
|
4469
4459
|
const commentId = event.comment_id?.trim();
|
|
4470
4460
|
const replyId = event.reply_id?.trim();
|
|
@@ -4502,7 +4492,7 @@ async function resolveDriveCommentEventCore(params) {
|
|
|
4502
4492
|
timeoutMs: verificationTimeoutMs,
|
|
4503
4493
|
logger,
|
|
4504
4494
|
accountId,
|
|
4505
|
-
|
|
4495
|
+
abortSignal
|
|
4506
4496
|
});
|
|
4507
4497
|
return {
|
|
4508
4498
|
eventId,
|
|
@@ -4628,7 +4618,8 @@ async function handleFeishuCommentEvent(params) {
|
|
|
4628
4618
|
accountId: account.accountId,
|
|
4629
4619
|
event: params.event,
|
|
4630
4620
|
botOpenId: params.botOpenId,
|
|
4631
|
-
logger: log
|
|
4621
|
+
logger: log,
|
|
4622
|
+
abortSignal: params.abortSignal
|
|
4632
4623
|
});
|
|
4633
4624
|
if (!turn) {
|
|
4634
4625
|
log(`feishu[${account.accountId}]: drive comment notice skipped event=${params.event.event_id ?? "unknown"} comment=${params.event.comment_id ?? "unknown"}`);
|
|
@@ -4912,7 +4903,7 @@ function buildCommentNoticeQueueKey(event) {
|
|
|
4912
4903
|
return `comment-doc:${event.notice_meta?.file_type?.trim() || "unknown"}:${event.notice_meta?.file_token?.trim() || "unknown"}`;
|
|
4913
4904
|
}
|
|
4914
4905
|
function createFeishuDriveCommentNoticeHandler(params) {
|
|
4915
|
-
const { cfg, accountId, runtime, fireAndForget } = params;
|
|
4906
|
+
const { cfg, accountId, runtime, fireAndForget, abortSignal } = params;
|
|
4916
4907
|
const log = runtime?.log ?? console.log;
|
|
4917
4908
|
const error = runtime?.error ?? console.error;
|
|
4918
4909
|
const enqueue = createSequentialQueue();
|
|
@@ -4932,20 +4923,22 @@ function createFeishuDriveCommentNoticeHandler(params) {
|
|
|
4932
4923
|
}
|
|
4933
4924
|
const eventId = event.event_id?.trim();
|
|
4934
4925
|
const syntheticMessageId = eventId ? `drive-comment:${eventId}` : void 0;
|
|
4926
|
+
let processingClaim;
|
|
4935
4927
|
if (syntheticMessageId) {
|
|
4936
4928
|
const claim = await claimUnprocessedFeishuMessage({
|
|
4937
4929
|
messageId: syntheticMessageId,
|
|
4938
4930
|
namespace: accountId,
|
|
4939
4931
|
log
|
|
4940
4932
|
});
|
|
4941
|
-
if (claim === "duplicate") {
|
|
4933
|
+
if (claim.kind === "duplicate") {
|
|
4942
4934
|
log(`feishu[${accountId}]: dropping duplicate comment event ${syntheticMessageId}`);
|
|
4943
4935
|
return;
|
|
4944
4936
|
}
|
|
4945
|
-
if (claim === "inflight") {
|
|
4937
|
+
if (claim.kind === "inflight") {
|
|
4946
4938
|
log(`feishu[${accountId}]: dropping in-flight comment event ${syntheticMessageId}`);
|
|
4947
4939
|
return;
|
|
4948
4940
|
}
|
|
4941
|
+
processingClaim = claim.kind === "claimed" ? claim.handle : void 0;
|
|
4949
4942
|
}
|
|
4950
4943
|
log(`feishu[${accountId}]: received drive comment notice event=${event.event_id ?? "unknown"} type=${event.notice_meta?.notice_type ?? "unknown"} file=${event.notice_meta?.file_type ?? "unknown"}:${event.notice_meta?.file_token ?? "unknown"} comment=${event.comment_id ?? "unknown"} reply=${event.reply_id ?? "none"} from=${event.notice_meta?.from_user_id?.open_id ?? "unknown"} mentioned=${event.is_mentioned === true ? "yes" : "no"}`);
|
|
4951
4944
|
try {
|
|
@@ -4955,15 +4948,15 @@ function createFeishuDriveCommentNoticeHandler(params) {
|
|
|
4955
4948
|
accountId,
|
|
4956
4949
|
event,
|
|
4957
4950
|
botOpenId: getBotOpenId(accountId),
|
|
4958
|
-
runtime
|
|
4951
|
+
runtime,
|
|
4952
|
+
abortSignal
|
|
4959
4953
|
});
|
|
4960
4954
|
});
|
|
4961
|
-
|
|
4955
|
+
await processingClaim?.commit();
|
|
4962
4956
|
} catch (err) {
|
|
4963
|
-
if (
|
|
4957
|
+
if (isFeishuRetryableSyntheticEventError(err)) processingClaim?.release({ error: err });
|
|
4958
|
+
else await processingClaim?.commit();
|
|
4964
4959
|
throw err;
|
|
4965
|
-
} finally {
|
|
4966
|
-
if (syntheticMessageId) releaseFeishuMessageProcessing(syntheticMessageId, accountId);
|
|
4967
4960
|
}
|
|
4968
4961
|
});
|
|
4969
4962
|
};
|
|
@@ -5005,7 +4998,7 @@ function dedupeFeishuDebounceEntriesByDedupeKey(entries) {
|
|
|
5005
4998
|
const seen = /* @__PURE__ */ new Set();
|
|
5006
4999
|
const deduped = [];
|
|
5007
5000
|
for (const entry of entries) {
|
|
5008
|
-
const dedupeKey = resolveFeishuMessageDedupeKey(entry);
|
|
5001
|
+
const dedupeKey = resolveFeishuMessageDedupeKey(entry.event);
|
|
5009
5002
|
if (!dedupeKey) {
|
|
5010
5003
|
deduped.push(entry);
|
|
5011
5004
|
continue;
|
|
@@ -5027,7 +5020,7 @@ function resolveFeishuDebounceMentions(params) {
|
|
|
5027
5020
|
const botMentions = merged.filter((mention) => mention.id.open_id?.trim() === normalizedBotOpenId);
|
|
5028
5021
|
return botMentions.length > 0 ? botMentions : void 0;
|
|
5029
5022
|
}
|
|
5030
|
-
function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, runtime, chatHistories, fireAndForget, handleMessage, resolveDebounceText: resolveText, hasProcessedMessage,
|
|
5023
|
+
function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, runtime, chatHistories, fireAndForget, handleMessage, resolveDebounceText: resolveText, hasProcessedMessage, getBotOpenId = () => void 0, getBotName = () => void 0, resolveSequentialKey = ({ accountId: accountIdLocal, event }) => `feishu:${accountIdLocal}:${event.message.chat_id?.trim() || "unknown"}`, statusSink }) {
|
|
5031
5024
|
const inboundDebounceMs = channelRuntime.debounce.resolveInboundDebounceMs({
|
|
5032
5025
|
cfg,
|
|
5033
5026
|
channel: "feishu"
|
|
@@ -5037,7 +5030,7 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
|
|
|
5037
5030
|
const enqueue = createSequentialQueue({ onTaskTimeout: (key, timeoutMs) => {
|
|
5038
5031
|
log(`feishu[${accountId}]: per-chat task exceeded ${timeoutMs}ms cap (key=${key}); evicting from queue so later same-key messages can proceed (#70133)`);
|
|
5039
5032
|
} });
|
|
5040
|
-
const dispatchFeishuMessage = async (event, messageDedupeKey) => {
|
|
5033
|
+
const dispatchFeishuMessage = async (event, messageDedupeKey, processingClaim) => {
|
|
5041
5034
|
const sequentialKey = resolveSequentialKey({
|
|
5042
5035
|
accountId,
|
|
5043
5036
|
event,
|
|
@@ -5053,7 +5046,7 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
|
|
|
5053
5046
|
channelRuntime,
|
|
5054
5047
|
chatHistories,
|
|
5055
5048
|
accountId,
|
|
5056
|
-
|
|
5049
|
+
processingClaim,
|
|
5057
5050
|
messageDedupeKey
|
|
5058
5051
|
});
|
|
5059
5052
|
await enqueue(sequentialKey, task);
|
|
@@ -5070,23 +5063,26 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
|
|
|
5070
5063
|
};
|
|
5071
5064
|
const recordSuppressedMessageIds = async (entries, dispatchDedupeKey) => {
|
|
5072
5065
|
const keepDedupeKey = dispatchDedupeKey?.trim();
|
|
5073
|
-
const suppressedIds = new Set(entries.map((entry) =>
|
|
5074
|
-
|
|
5075
|
-
|
|
5066
|
+
const suppressedIds = new Set(entries.map((entry) => ({
|
|
5067
|
+
id: resolveFeishuMessageDedupeKey(entry.event),
|
|
5068
|
+
claim: entry.processingClaim
|
|
5069
|
+
})).filter(({ id }) => Boolean(id) && (!keepDedupeKey || id !== keepDedupeKey)));
|
|
5070
|
+
for (const suppressed of suppressedIds) try {
|
|
5071
|
+
await suppressed.claim?.commit();
|
|
5076
5072
|
} catch (err) {
|
|
5077
|
-
error(`feishu[${accountId}]: failed to record merged dedupe id ${
|
|
5073
|
+
error(`feishu[${accountId}]: failed to record merged dedupe id ${suppressed.id}: ${String(err)}`);
|
|
5078
5074
|
}
|
|
5079
5075
|
};
|
|
5080
5076
|
const inboundDebouncer = channelRuntime.debounce.createInboundDebouncer({
|
|
5081
5077
|
debounceMs: inboundDebounceMs,
|
|
5082
|
-
buildKey: (event) => {
|
|
5078
|
+
buildKey: ({ event }) => {
|
|
5083
5079
|
const chatId = event.message.chat_id?.trim();
|
|
5084
5080
|
const senderId = resolveSenderDebounceId(event);
|
|
5085
5081
|
if (!chatId || !senderId) return null;
|
|
5086
5082
|
const rootId = event.message.root_id?.trim();
|
|
5087
5083
|
return `feishu:${accountId}:${chatId}:${rootId ? `thread:${rootId}` : "chat"}:${senderId}`;
|
|
5088
5084
|
},
|
|
5089
|
-
shouldDebounce: (event) => {
|
|
5085
|
+
shouldDebounce: ({ event }) => {
|
|
5090
5086
|
if (event.message.message_type !== "text") return false;
|
|
5091
5087
|
const text = resolveDebounceText(event);
|
|
5092
5088
|
return Boolean(text) && !channelRuntime.commands.isControlCommandMessage(text, cfg);
|
|
@@ -5095,35 +5091,35 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
|
|
|
5095
5091
|
const last = entries.at(-1);
|
|
5096
5092
|
if (!last) return;
|
|
5097
5093
|
if (entries.length === 1) {
|
|
5098
|
-
await dispatchFeishuMessage(last, resolveFeishuMessageDedupeKey(last));
|
|
5094
|
+
await dispatchFeishuMessage(last.event, resolveFeishuMessageDedupeKey(last.event), last.processingClaim);
|
|
5099
5095
|
return;
|
|
5100
5096
|
}
|
|
5101
5097
|
const dedupedEntries = dedupeFeishuDebounceEntriesByDedupeKey(entries);
|
|
5102
5098
|
const freshEntries = [];
|
|
5103
|
-
for (const entry of dedupedEntries) if (!await hasProcessedMessage(resolveFeishuMessageDedupeKey(entry), accountId, log)) freshEntries.push(entry);
|
|
5099
|
+
for (const entry of dedupedEntries) if (!await hasProcessedMessage(resolveFeishuMessageDedupeKey(entry.event), accountId, log)) freshEntries.push(entry);
|
|
5104
5100
|
const dispatchEntry = freshEntries.at(-1);
|
|
5105
5101
|
if (!dispatchEntry) return;
|
|
5106
|
-
const dispatchDedupeKey = resolveFeishuMessageDedupeKey(dispatchEntry);
|
|
5102
|
+
const dispatchDedupeKey = resolveFeishuMessageDedupeKey(dispatchEntry.event);
|
|
5107
5103
|
await recordSuppressedMessageIds(dedupedEntries, dispatchDedupeKey);
|
|
5108
|
-
const combinedText = freshEntries.map((entry) => resolveDebounceText(entry)).filter(Boolean).join("\n");
|
|
5104
|
+
const combinedText = freshEntries.map((entry) => resolveDebounceText(entry.event)).filter(Boolean).join("\n");
|
|
5109
5105
|
const mergedMentions = resolveFeishuDebounceMentions({
|
|
5110
|
-
entries: freshEntries,
|
|
5106
|
+
entries: freshEntries.map((entry) => entry.event),
|
|
5111
5107
|
botOpenId: getBotOpenId(accountId)
|
|
5112
5108
|
});
|
|
5113
5109
|
await dispatchFeishuMessage({
|
|
5114
|
-
...dispatchEntry,
|
|
5110
|
+
...dispatchEntry.event,
|
|
5115
5111
|
message: {
|
|
5116
|
-
...dispatchEntry.message,
|
|
5112
|
+
...dispatchEntry.event.message,
|
|
5117
5113
|
...combinedText.trim() ? {
|
|
5118
5114
|
message_type: "text",
|
|
5119
5115
|
content: JSON.stringify({ text: combinedText })
|
|
5120
5116
|
} : {},
|
|
5121
|
-
mentions: mergedMentions ?? dispatchEntry.message.mentions
|
|
5117
|
+
mentions: mergedMentions ?? dispatchEntry.event.message.mentions
|
|
5122
5118
|
}
|
|
5123
|
-
}, dispatchDedupeKey);
|
|
5119
|
+
}, dispatchDedupeKey, dispatchEntry.processingClaim);
|
|
5124
5120
|
},
|
|
5125
5121
|
onError: (err, entries) => {
|
|
5126
|
-
for (const entry of entries)
|
|
5122
|
+
for (const entry of entries) entry.processingClaim?.release({ error: err });
|
|
5127
5123
|
error(`feishu[${accountId}]: inbound debounce flush failed: ${String(err)}`);
|
|
5128
5124
|
}
|
|
5129
5125
|
});
|
|
@@ -5141,22 +5137,24 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
|
|
|
5141
5137
|
log(`feishu[${accountId}]: dropping self-authored message ${messageId ?? "unknown"}`);
|
|
5142
5138
|
return;
|
|
5143
5139
|
}
|
|
5144
|
-
const messageDedupeKey = resolveFeishuMessageDedupeKey(event);
|
|
5145
5140
|
const claim = await claimUnprocessedFeishuMessage({
|
|
5146
|
-
messageId:
|
|
5141
|
+
messageId: resolveFeishuMessageDedupeKey(event),
|
|
5147
5142
|
namespace: accountId,
|
|
5148
5143
|
log
|
|
5149
5144
|
});
|
|
5150
|
-
if (claim
|
|
5151
|
-
log(`feishu[${accountId}]: dropping ${claim} event for message ${messageId}`);
|
|
5145
|
+
if (claim.kind === "duplicate" || claim.kind === "inflight") {
|
|
5146
|
+
log(`feishu[${accountId}]: dropping ${claim.kind} event for message ${messageId}`);
|
|
5152
5147
|
return;
|
|
5153
5148
|
}
|
|
5154
5149
|
const processMessage = async () => {
|
|
5155
|
-
await inboundDebouncer.enqueue(
|
|
5150
|
+
await inboundDebouncer.enqueue({
|
|
5151
|
+
event,
|
|
5152
|
+
...claim.kind === "claimed" ? { processingClaim: claim.handle } : {}
|
|
5153
|
+
});
|
|
5156
5154
|
};
|
|
5157
5155
|
if (fireAndForget) {
|
|
5158
5156
|
processMessage().catch((err) => {
|
|
5159
|
-
|
|
5157
|
+
if (claim.kind === "claimed") claim.handle.release({ error: err });
|
|
5160
5158
|
error(`feishu[${accountId}]: error handling message: ${String(err)}`);
|
|
5161
5159
|
});
|
|
5162
5160
|
return;
|
|
@@ -5164,7 +5162,7 @@ function createFeishuMessageReceiveHandler({ cfg, channelRuntime, accountId, run
|
|
|
5164
5162
|
try {
|
|
5165
5163
|
await processMessage();
|
|
5166
5164
|
} catch (err) {
|
|
5167
|
-
|
|
5165
|
+
if (claim.kind === "claimed") claim.handle.release({ error: err });
|
|
5168
5166
|
error(`feishu[${accountId}]: error handling message: ${String(err)}`);
|
|
5169
5167
|
}
|
|
5170
5168
|
};
|
|
@@ -5619,7 +5617,7 @@ function parseFeishuCardActionEventPayload(value) {
|
|
|
5619
5617
|
};
|
|
5620
5618
|
}
|
|
5621
5619
|
function registerEventHandlers(eventDispatcher, context) {
|
|
5622
|
-
const { cfg, accountId, channelRuntime, runtime, chatHistories, fireAndForget } = context;
|
|
5620
|
+
const { cfg, accountId, channelRuntime, runtime, chatHistories, fireAndForget, abortSignal } = context;
|
|
5623
5621
|
const log = runtime?.log ?? console.log;
|
|
5624
5622
|
const error = runtime?.error ?? console.error;
|
|
5625
5623
|
const runFeishuHandler = async (params) => {
|
|
@@ -5646,7 +5644,6 @@ function registerEventHandlers(eventDispatcher, context) {
|
|
|
5646
5644
|
handleMessage: handleFeishuMessage,
|
|
5647
5645
|
resolveDebounceText: ({ event, botOpenId, botName }) => parseFeishuMessageEvent(event, botOpenId, botName).content,
|
|
5648
5646
|
hasProcessedMessage: hasProcessedFeishuMessage,
|
|
5649
|
-
recordProcessedMessage: recordProcessedFeishuMessage,
|
|
5650
5647
|
getBotOpenId: (id) => botOpenIds.get(id),
|
|
5651
5648
|
getBotName: (id) => botNames.get(id),
|
|
5652
5649
|
resolveSequentialKey: getFeishuSequentialKey,
|
|
@@ -5676,7 +5673,8 @@ function registerEventHandlers(eventDispatcher, context) {
|
|
|
5676
5673
|
cfg,
|
|
5677
5674
|
accountId,
|
|
5678
5675
|
runtime,
|
|
5679
|
-
fireAndForget
|
|
5676
|
+
fireAndForget,
|
|
5677
|
+
abortSignal
|
|
5680
5678
|
}),
|
|
5681
5679
|
"im.message.reaction.created_v1": async (data) => {
|
|
5682
5680
|
await runFeishuHandler({
|
|
@@ -5805,6 +5803,7 @@ async function monitorSingleAccount(params) {
|
|
|
5805
5803
|
runtime,
|
|
5806
5804
|
chatHistories,
|
|
5807
5805
|
fireAndForget: params.fireAndForget ?? true,
|
|
5806
|
+
abortSignal,
|
|
5808
5807
|
...params.statusSink ? { statusSink: params.statusSink } : {}
|
|
5809
5808
|
});
|
|
5810
5809
|
if (connectionMode === "webhook") return await monitorWebhook({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as probeFeishu } from "./probe-
|
|
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-
|
|
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,18 +1,18 @@
|
|
|
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-
|
|
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-DsqTk27v.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";
|
|
13
12
|
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
14
13
|
import { readRegularFile, writeExternalFileWithinRoot } from "openclaw/plugin-sdk/security-runtime";
|
|
15
14
|
import { Readable } from "node:stream";
|
|
15
|
+
import { mediaKindFromMime } from "openclaw/plugin-sdk/media-mime";
|
|
16
16
|
import { saveMediaBuffer, saveMediaStream } from "openclaw/plugin-sdk/media-store";
|
|
17
17
|
import { resolvePreferredOpenClawTmpDir, withTempDownloadPath, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
|
|
18
18
|
//#region extensions/feishu/src/identity-header.ts
|
|
@@ -50,6 +50,55 @@ function normalizeFeishuExternalKey(value) {
|
|
|
50
50
|
return normalized;
|
|
51
51
|
}
|
|
52
52
|
//#endregion
|
|
53
|
+
//#region extensions/feishu/src/media-chunk-idle.ts
|
|
54
|
+
var FeishuInboundMediaTimeoutError = class extends Error {
|
|
55
|
+
constructor(chunkTimeoutMs) {
|
|
56
|
+
super(`Feishu media download stalled: no data received for ${chunkTimeoutMs}ms`);
|
|
57
|
+
this.name = "FeishuInboundMediaTimeoutError";
|
|
58
|
+
this.chunkTimeoutMs = chunkTimeoutMs;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
function destroySource(source) {
|
|
62
|
+
const s = source;
|
|
63
|
+
if (typeof s.destroy === "function") s.destroy();
|
|
64
|
+
}
|
|
65
|
+
function withChunkIdleTimeout(source, chunkTimeoutMs) {
|
|
66
|
+
return { async *[Symbol.asyncIterator]() {
|
|
67
|
+
const iterator = source[Symbol.asyncIterator]();
|
|
68
|
+
let exhausted = false;
|
|
69
|
+
try {
|
|
70
|
+
while (true) {
|
|
71
|
+
const nextPromise = iterator.next();
|
|
72
|
+
let timeoutHandle;
|
|
73
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
74
|
+
timeoutHandle = setTimeout(() => {
|
|
75
|
+
reject(new FeishuInboundMediaTimeoutError(chunkTimeoutMs));
|
|
76
|
+
try {
|
|
77
|
+
destroySource(source);
|
|
78
|
+
} catch {}
|
|
79
|
+
}, chunkTimeoutMs);
|
|
80
|
+
});
|
|
81
|
+
let result;
|
|
82
|
+
try {
|
|
83
|
+
result = await Promise.race([nextPromise, timeoutPromise]);
|
|
84
|
+
} finally {
|
|
85
|
+
if (timeoutHandle !== void 0) clearTimeout(timeoutHandle);
|
|
86
|
+
}
|
|
87
|
+
if (result.done) {
|
|
88
|
+
exhausted = true;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
yield result.value;
|
|
92
|
+
}
|
|
93
|
+
} finally {
|
|
94
|
+
if (!exhausted && typeof iterator.return === "function") iterator.return().catch(() => void 0);
|
|
95
|
+
}
|
|
96
|
+
} };
|
|
97
|
+
}
|
|
98
|
+
function saveMediaStreamWithIdleTimeout(stream, contentType, maxBytes, fileName, chunkTimeoutMs) {
|
|
99
|
+
return saveMediaStream(withChunkIdleTimeout(stream, chunkTimeoutMs), contentType, "inbound", maxBytes, fileName);
|
|
100
|
+
}
|
|
101
|
+
//#endregion
|
|
53
102
|
//#region extensions/feishu/src/send-target.ts
|
|
54
103
|
function resolveFeishuSendTarget(params) {
|
|
55
104
|
const target = params.to.trim();
|
|
@@ -177,14 +226,15 @@ async function saveFeishuResponseMedia(params) {
|
|
|
177
226
|
if (responseWithOptionalFields.code !== void 0 && responseWithOptionalFields.code !== 0) throw new Error(`${params.errorPrefix}: ${responseWithOptionalFields.msg || `code ${responseWithOptionalFields.code}`}`);
|
|
178
227
|
if (responseWithOptionalFields.data && Buffer.isBuffer(responseWithOptionalFields.data)) return saveMediaBuffer(responseWithOptionalFields.data, contentType, "inbound", maxBytes, fileName);
|
|
179
228
|
if (responseWithOptionalFields.data instanceof ArrayBuffer) return saveMediaBuffer(Buffer.from(responseWithOptionalFields.data), contentType, "inbound", maxBytes, fileName);
|
|
180
|
-
|
|
229
|
+
const save = (stream, ct = contentType, mb = maxBytes, fn = fileName) => saveMediaStreamWithIdleTimeout(stream, ct, mb, fn, FEISHU_MEDIA_HTTP_TIMEOUT_MS);
|
|
230
|
+
if (typeof response.getReadableStream === "function") return save(response.getReadableStream());
|
|
181
231
|
if (typeof response.writeFile === "function") return await withTempDownloadPath({ prefix: params.tmpDirPrefix }, async (tmpPath) => {
|
|
182
232
|
await response.writeFile(tmpPath);
|
|
183
233
|
if ((await fs.promises.stat(tmpPath)).size > maxBytes) throw mediaLimitError(maxBytes);
|
|
184
|
-
return await
|
|
234
|
+
return await save(fs.createReadStream(tmpPath));
|
|
185
235
|
});
|
|
186
|
-
if (responseWithOptionalFields[Symbol.asyncIterator]) return
|
|
187
|
-
if (response instanceof Readable) return
|
|
236
|
+
if (responseWithOptionalFields[Symbol.asyncIterator]) return save(responseWithOptionalFields);
|
|
237
|
+
if (response instanceof Readable) return save(response);
|
|
188
238
|
const keys = Object.keys(response);
|
|
189
239
|
throw new Error(`${params.errorPrefix}: unexpected response format. Keys: [${keys.join(", ")}]`);
|
|
190
240
|
}
|
|
@@ -439,6 +439,13 @@ function canEnumerateAllFeishuPeers(account) {
|
|
|
439
439
|
//#endregion
|
|
440
440
|
//#region extensions/feishu/src/markdown.ts
|
|
441
441
|
const FEISHU_POST_MAX_BYTES = 30 * 1024;
|
|
442
|
+
/** One parser contract for Feishu message and document Markdown decisions. */
|
|
443
|
+
function parseFeishuMarkdown(text) {
|
|
444
|
+
return fromMarkdown(text, {
|
|
445
|
+
extensions: [gfmTable()],
|
|
446
|
+
mdastExtensions: [gfmTableFromMarkdown()]
|
|
447
|
+
});
|
|
448
|
+
}
|
|
442
449
|
function buildFeishuPostMentionElements(mentions) {
|
|
443
450
|
if (!mentions?.length) return [];
|
|
444
451
|
const elements = [];
|
|
@@ -465,10 +472,7 @@ function assertFeishuPostWithinEnvelope(content, label) {
|
|
|
465
472
|
if (Buffer.byteLength(content, "utf8") > FEISHU_POST_MAX_BYTES) throw new Error(`${label} exceeds the 30 KB rich-post API limit`);
|
|
466
473
|
}
|
|
467
474
|
function collectSoftBreakOffsets(text) {
|
|
468
|
-
const root =
|
|
469
|
-
extensions: [gfmTable()],
|
|
470
|
-
mdastExtensions: [gfmTableFromMarkdown()]
|
|
471
|
-
});
|
|
475
|
+
const root = parseFeishuMarkdown(text);
|
|
472
476
|
const offsets = [];
|
|
473
477
|
const pending = [root];
|
|
474
478
|
while (pending.length > 0) {
|
|
@@ -763,4 +767,4 @@ function toFeishuSendResult(response, chatId, kind) {
|
|
|
763
767
|
};
|
|
764
768
|
}
|
|
765
769
|
//#endregion
|
|
766
|
-
export {
|
|
770
|
+
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-
|
|
1
|
+
import { i as feishuSetupAdapter, n as feishuSetupWizard, t as feishuPlugin } from "./channel-X30GQVwc.js";
|
|
2
2
|
export { feishuPlugin, feishuSetupAdapter, feishuSetupWizard };
|