@openclaw/feishu 2026.5.7-beta.1 → 2026.5.9-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 +3 -2
- package/dist/{channel-BegH3cJm.js → channel-C5kY2KFE.js} +36 -4
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-DYsXcD36.js → channel.runtime-BK6_CcZk.js} +4 -5
- package/dist/{monitor-BVR-x39Q.js → monitor-YkqtEXDP.js} +1 -1
- package/dist/{monitor.account-CUZxYkjE.js → monitor.account-BRSlHEbU.js} +72 -31
- package/dist/runtime-api.js +1 -1
- package/dist/{send-DowxxbpH.js → send-DKHEQrzH.js} +48 -61
- package/dist/{card-interaction-BfRLgvw_.js → send-result-BVFTskB_.js} +45 -1
- package/dist/setup-api.js +1 -1
- package/package.json +5 -5
package/dist/api.js
CHANGED
|
@@ -2,7 +2,7 @@ import { a as parseFeishuTargetId, i as parseFeishuDirectConversationId, n as bu
|
|
|
2
2
|
import { n as createFeishuThreadBindingManager, r as getFeishuThreadBindingManager, t as __testing } from "./thread-bindings-BmS6TLes.js";
|
|
3
3
|
import { n as handleFeishuSubagentEnded, r as handleFeishuSubagentSpawning, t as handleFeishuSubagentDeliveryTarget } from "./subagent-hooks-C3UhPVLV.js";
|
|
4
4
|
import { r as listEnabledFeishuAccounts } from "./accounts-Ba3-WP1z.js";
|
|
5
|
-
import { a as setFeishuNamedAccountEnabled, i as feishuSetupAdapter, n as feishuSetupWizard, r as runFeishuLogin, t as feishuPlugin } from "./channel-
|
|
5
|
+
import { a as setFeishuNamedAccountEnabled, i as feishuSetupAdapter, n as feishuSetupWizard, r as runFeishuLogin, t as feishuPlugin } from "./channel-C5kY2KFE.js";
|
|
6
6
|
import { t as getFeishuRuntime } from "./runtime-CG0DuRCy.js";
|
|
7
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-C5eJLJr7.js";
|
|
8
8
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, readStringValue } from "openclaw/plugin-sdk/text-runtime";
|
|
@@ -10,6 +10,7 @@ import { existsSync } from "node:fs";
|
|
|
10
10
|
import { homedir } from "node:os";
|
|
11
11
|
import { basename, isAbsolute, resolve } from "node:path";
|
|
12
12
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
13
|
+
import { extensionForMime } from "openclaw/plugin-sdk/media-mime";
|
|
13
14
|
import { Type } from "typebox";
|
|
14
15
|
import { createClackPrompter } from "openclaw/plugin-sdk/setup-runtime";
|
|
15
16
|
//#region extensions/feishu/src/doc-schema.ts
|
|
@@ -879,7 +880,7 @@ async function resolveUploadInput(url, filePath, maxBytes, localRoots, explicitF
|
|
|
879
880
|
if (!header.includes(";base64")) throw new Error("Invalid data URI: missing ';base64' marker. Expected format: data:image/png;base64,<base64data>");
|
|
880
881
|
const trimmedData = data.trim();
|
|
881
882
|
if (trimmedData.length === 0 || !/^[A-Za-z0-9+/]+=*$/.test(trimmedData)) throw new Error(`Invalid data URI: base64 payload contains characters outside the standard alphabet.`);
|
|
882
|
-
const ext = header.match(/data:([^;]+)/)?.[1]?.
|
|
883
|
+
const ext = extensionForMime(header.match(/data:([^;]+)/)?.[1])?.slice(1) ?? "png";
|
|
883
884
|
const estimatedBytes = Math.ceil(trimmedData.length * 3 / 4);
|
|
884
885
|
if (estimatedBytes > maxBytes) throw new Error(`Image data URI exceeds limit: estimated ${estimatedBytes} bytes > ${maxBytes} bytes`);
|
|
885
886
|
return {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as parseFeishuTargetId, i as parseFeishuDirectConversationId, n as buildFeishuModelOverrideParentCandidates, r as parseFeishuConversationId, t as buildFeishuConversationId } from "./conversation-id-DWS3Ep2A.js";
|
|
2
2
|
import { n as looksLikeFeishuId, r as normalizeFeishuTarget } from "./targets-JMFJRKSe.js";
|
|
3
3
|
import { a as resolveDefaultFeishuAccountId, f as isRecord$1, i as listFeishuAccountIds, n as inspectFeishuCredentials, o as resolveFeishuAccount, r as listEnabledFeishuAccounts, s as resolveFeishuRuntimeAccount } from "./accounts-Ba3-WP1z.js";
|
|
4
|
-
import "./
|
|
4
|
+
import { n as createFeishuSendReceipt } from "./send-result-BVFTskB_.js";
|
|
5
5
|
import { n as listFeishuDirectoryPeers, t as listFeishuDirectoryGroups } from "./directory.static-f3EeoRJd.js";
|
|
6
6
|
import { t as messageActionTargetAliases } from "./security-audit-DqJdocrN.js";
|
|
7
7
|
import { a as resolveFeishuGroupToolPolicy } from "./policy-D6c-wMPl.js";
|
|
@@ -14,6 +14,7 @@ import { describeAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
|
|
|
14
14
|
import { formatAllowFromLowercase } from "openclaw/plugin-sdk/allow-from";
|
|
15
15
|
import { adaptScopedAccountAccessor, createHybridChannelConfigAdapter } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
16
16
|
import { buildChannelOutboundSessionRoute, createChatChannelPlugin, stripChannelTargetPrefix } from "openclaw/plugin-sdk/channel-core";
|
|
17
|
+
import { defineChannelMessageAdapter } from "openclaw/plugin-sdk/channel-message";
|
|
17
18
|
import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing";
|
|
18
19
|
import { createAllowlistProviderGroupPolicyWarningCollector, projectConfigAccountIdWarningCollector } from "openclaw/plugin-sdk/channel-policy";
|
|
19
20
|
import { createChannelDirectoryAdapter, createRuntimeDirectoryLiveAdapter } from "openclaw/plugin-sdk/directory-runtime";
|
|
@@ -810,7 +811,37 @@ const meta = {
|
|
|
810
811
|
aliases: ["lark"],
|
|
811
812
|
order: 70
|
|
812
813
|
};
|
|
813
|
-
const loadFeishuChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-
|
|
814
|
+
const loadFeishuChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-BK6_CcZk.js"), "feishuChannelRuntime");
|
|
815
|
+
function toFeishuMessageSendResult(result, kind) {
|
|
816
|
+
const receipt = result.receipt ?? createFeishuSendReceipt({
|
|
817
|
+
messageId: result.messageId,
|
|
818
|
+
chatId: result.chatId ?? "",
|
|
819
|
+
kind
|
|
820
|
+
});
|
|
821
|
+
return {
|
|
822
|
+
messageId: result.messageId || receipt.primaryPlatformMessageId,
|
|
823
|
+
receipt
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
const feishuMessageAdapter = defineChannelMessageAdapter({
|
|
827
|
+
id: "feishu",
|
|
828
|
+
durableFinal: { capabilities: {
|
|
829
|
+
text: true,
|
|
830
|
+
media: true
|
|
831
|
+
} },
|
|
832
|
+
send: {
|
|
833
|
+
text: async (ctx) => {
|
|
834
|
+
const sendText = (await loadFeishuChannelRuntime()).feishuOutbound.sendText;
|
|
835
|
+
if (!sendText) throw new Error("Feishu text sending is not available.");
|
|
836
|
+
return toFeishuMessageSendResult(await sendText(ctx), "text");
|
|
837
|
+
},
|
|
838
|
+
media: async (ctx) => {
|
|
839
|
+
const sendMedia = (await loadFeishuChannelRuntime()).feishuOutbound.sendMedia;
|
|
840
|
+
if (!sendMedia) throw new Error("Feishu media sending is not available.");
|
|
841
|
+
return toFeishuMessageSendResult(await sendMedia(ctx), "media");
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
});
|
|
814
845
|
function buildFeishuPresentationCard(params) {
|
|
815
846
|
const fallbackPresentation = {
|
|
816
847
|
...params.presentation.tone ? { tone: params.presentation.tone } : {},
|
|
@@ -1601,7 +1632,7 @@ const feishuPlugin = createChatChannelPlugin({
|
|
|
1601
1632
|
})
|
|
1602
1633
|
}),
|
|
1603
1634
|
gateway: { startAccount: async (ctx) => {
|
|
1604
|
-
const { monitorFeishuProvider } = await import("./monitor-
|
|
1635
|
+
const { monitorFeishuProvider } = await import("./monitor-YkqtEXDP.js");
|
|
1605
1636
|
const account = resolveFeishuRuntimeAccount({
|
|
1606
1637
|
cfg: ctx.cfg,
|
|
1607
1638
|
accountId: ctx.accountId
|
|
@@ -1618,7 +1649,8 @@ const feishuPlugin = createChatChannelPlugin({
|
|
|
1618
1649
|
abortSignal: ctx.abortSignal,
|
|
1619
1650
|
accountId: ctx.accountId
|
|
1620
1651
|
});
|
|
1621
|
-
} }
|
|
1652
|
+
} },
|
|
1653
|
+
message: feishuMessageAdapter
|
|
1622
1654
|
},
|
|
1623
1655
|
security: {
|
|
1624
1656
|
collectWarnings: projectConfigAccountIdWarningCollector(collectFeishuSecurityWarnings),
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as feishuPlugin } from "./channel-
|
|
1
|
+
import { t as feishuPlugin } from "./channel-C5kY2KFE.js";
|
|
2
2
|
export { feishuPlugin };
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { o as resolveFeishuAccount, s as resolveFeishuRuntimeAccount, y as parseFeishuCommentTarget } from "./accounts-Ba3-WP1z.js";
|
|
2
|
-
import {
|
|
2
|
+
import { s as createFeishuCardInteractionEnvelope } from "./send-result-BVFTskB_.js";
|
|
3
3
|
import { n as listFeishuDirectoryPeers, t as listFeishuDirectoryGroups } from "./directory.static-f3EeoRJd.js";
|
|
4
4
|
import { r as createFeishuClient } from "./client-DBVoQL5w.js";
|
|
5
5
|
import { c as getChatInfo, l as getChatMembers, r as cleanupAmbientCommentTypingReaction, t as deliverCommentThreadText, u as getFeishuMemberInfo } from "./drive-C5eJLJr7.js";
|
|
6
6
|
import { chunkTextForOutbound } from "./runtime-api.js";
|
|
7
|
-
import {
|
|
7
|
+
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-DKHEQrzH.js";
|
|
8
8
|
import { t as probeFeishu } from "./probe-BNzzU_uR.js";
|
|
9
9
|
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
|
10
10
|
import { interactiveReplyToPresentation, normalizeInteractiveReply, normalizeMessagePresentation, renderMessagePresentationFallbackText, resolveInteractiveTextFallback } from "openclaw/plugin-sdk/interactive-runtime";
|
|
11
|
-
import fs from "node:fs";
|
|
12
11
|
import path from "node:path";
|
|
13
12
|
import { attachChannelToResult, createAttachedChannelResultAdapter } from "openclaw/plugin-sdk/channel-send-result";
|
|
14
13
|
import { resolvePayloadMediaUrls, sendPayloadMediaSequenceAndFinalize, sendTextMediaPayload } from "openclaw/plugin-sdk/reply-payload";
|
|
14
|
+
import { statRegularFileSync } from "openclaw/plugin-sdk/security-runtime";
|
|
15
15
|
//#region extensions/feishu/src/directory.ts
|
|
16
16
|
async function listFeishuDirectoryPeersLive(params) {
|
|
17
17
|
const account = resolveFeishuAccount({
|
|
@@ -93,9 +93,8 @@ function normalizePossibleLocalImagePath(text) {
|
|
|
93
93
|
".tiff"
|
|
94
94
|
].includes(ext)) return null;
|
|
95
95
|
if (!path.isAbsolute(raw)) return null;
|
|
96
|
-
if (!fs.existsSync(raw)) return null;
|
|
97
96
|
try {
|
|
98
|
-
if (
|
|
97
|
+
if (statRegularFileSync(raw).missing) return null;
|
|
99
98
|
} catch {
|
|
100
99
|
return null;
|
|
101
100
|
}
|
|
@@ -3,7 +3,7 @@ import { l as fetchBotIdentityForMonitor } from "./monitor.state-DYM02ipp.js";
|
|
|
3
3
|
//#region extensions/feishu/src/monitor.ts
|
|
4
4
|
let monitorAccountRuntimePromise;
|
|
5
5
|
async function loadMonitorAccountRuntime() {
|
|
6
|
-
monitorAccountRuntimePromise ??= import("./monitor.account-
|
|
6
|
+
monitorAccountRuntimePromise ??= import("./monitor.account-BRSlHEbU.js");
|
|
7
7
|
return await monitorAccountRuntimePromise;
|
|
8
8
|
}
|
|
9
9
|
async function monitorFeishuProvider(opts = {}) {
|
|
@@ -2,17 +2,18 @@ import { t as buildFeishuConversationId } from "./conversation-id-DWS3Ep2A.js";
|
|
|
2
2
|
import { i as resolveReceiveIdType } from "./targets-JMFJRKSe.js";
|
|
3
3
|
import { n as createFeishuThreadBindingManager } from "./thread-bindings-BmS6TLes.js";
|
|
4
4
|
import { _ as buildFeishuCommentTarget, f as isRecord$3, h as readString$2, l as encodeQuery, m as parseCommentContentElements, p as normalizeString, s as resolveFeishuRuntimeAccount, u as extractReplyText, v as normalizeCommentFileType } from "./accounts-Ba3-WP1z.js";
|
|
5
|
-
import {
|
|
5
|
+
import { c as decodeFeishuCardAction, o as buildFeishuCardActionTextFallback, s as createFeishuCardInteractionEnvelope } from "./send-result-BVFTskB_.js";
|
|
6
6
|
import { i as resolveFeishuGroupConfig, n as isFeishuGroupAllowed, o as resolveFeishuReplyPolicy, r as resolveFeishuAllowlistMatch, t as hasExplicitFeishuGroupConfig } from "./policy-D6c-wMPl.js";
|
|
7
7
|
import { t as getFeishuRuntime } from "./runtime-CG0DuRCy.js";
|
|
8
8
|
import { a as getFeishuUserAgent, i as createFeishuWSClient, n as createEventDispatcher, r as createFeishuClient } from "./client-DBVoQL5w.js";
|
|
9
9
|
import { c as getChatInfo, i as createCommentTypingReactionLifecycle, t as deliverCommentThreadText } from "./drive-C5eJLJr7.js";
|
|
10
|
-
import { buildAgentMediaPayload, createReplyPrefixContext, evaluateSupplementalContextVisibility, filterSupplementalContextItems, loadSessionStore, normalizeAgentId, resolveChannelContextVisibilityMode, resolveSessionStoreEntry } from "./runtime-api.js";
|
|
11
|
-
import { _ as
|
|
10
|
+
import { buildAgentMediaPayload, createReplyPrefixContext, evaluateSupplementalContextVisibility, filterSupplementalContextItems, loadSessionStore, normalizeAgentId as normalizeAgentId$1, 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 downloadMessageResourceFeishu, n as getMessageFeishu, p as isFeishuGroupChatType, r as listFeishuThreadMessages, s as sendMessageFeishu, u as extractMentionTargets } from "./send-DKHEQrzH.js";
|
|
12
12
|
import { i as waitForAbortableDelay, r as raceWithTimeoutAndAbort } from "./probe-BNzzU_uR.js";
|
|
13
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-DYM02ipp.js";
|
|
14
14
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, stripReasoningTagsFromText } from "openclaw/plugin-sdk/text-runtime";
|
|
15
15
|
import { ensureConfiguredBindingRouteReady, resolveConfiguredBindingRoute, resolveRuntimeConversationBindingRoute } from "openclaw/plugin-sdk/conversation-runtime";
|
|
16
|
+
import { createChannelMessageReplyPipeline } from "openclaw/plugin-sdk/channel-message";
|
|
16
17
|
import { createChannelPairingController, createChannelPairingController as createChannelPairingController$1 } from "openclaw/plugin-sdk/channel-pairing";
|
|
17
18
|
import { resolveAgentOutboundIdentity } from "openclaw/plugin-sdk/outbound-runtime";
|
|
18
19
|
import fs from "node:fs";
|
|
@@ -20,16 +21,17 @@ import os from "node:os";
|
|
|
20
21
|
import path from "node:path";
|
|
21
22
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
22
23
|
import * as Lark from "@larksuiteoapi/node-sdk";
|
|
23
|
-
import { createChannelReplyPipeline } from "openclaw/plugin-sdk/channel-reply-pipeline";
|
|
24
24
|
import { createPersistentDedupe } from "openclaw/plugin-sdk/persistent-dedupe";
|
|
25
25
|
import { applyBasicWebhookRequestGuards } from "openclaw/plugin-sdk/webhook-ingress";
|
|
26
26
|
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
27
27
|
import { resolveSendableOutboundReplyParts, resolveTextChunksWithFallback, sendMediaWithLeadingCaption } from "openclaw/plugin-sdk/reply-payload";
|
|
28
|
+
import { resolveOpenDmAllowlistAccess, safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
|
|
28
29
|
import * as crypto$1 from "node:crypto";
|
|
29
30
|
import crypto from "node:crypto";
|
|
31
|
+
import { resolveChannelConfigWrites } from "openclaw/plugin-sdk/channel-config-writes";
|
|
30
32
|
import { DEFAULT_GROUP_HISTORY_LIMIT, buildPendingHistoryContextFromMap, clearHistoryEntriesIfEnabled, recordPendingHistoryEntryIfEnabled } from "openclaw/plugin-sdk/reply-history";
|
|
31
33
|
import { resolveDefaultGroupPolicy, resolveOpenProviderRuntimeGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
|
|
32
|
-
import {
|
|
34
|
+
import { formatReasoningMessage } from "openclaw/plugin-sdk/agent-runtime";
|
|
33
35
|
import { logTypingFailure } from "openclaw/plugin-sdk/channel-feedback";
|
|
34
36
|
import { formatChannelProgressDraftLineForEntry, isChannelProgressDraftWorkToolName } from "openclaw/plugin-sdk/channel-streaming";
|
|
35
37
|
import * as http from "node:http";
|
|
@@ -550,7 +552,14 @@ function resolveFeishuMessageDedupeKey(event) {
|
|
|
550
552
|
* This creates a unique agent instance with its own workspace for each DM user.
|
|
551
553
|
*/
|
|
552
554
|
async function maybeCreateDynamicAgent(params) {
|
|
553
|
-
const { cfg, runtime, senderOpenId, dynamicCfg, log } = params;
|
|
555
|
+
const { cfg, runtime, senderOpenId, dynamicCfg, configWritesAllowed, log } = params;
|
|
556
|
+
if (!configWritesAllowed) {
|
|
557
|
+
log(`feishu: config writes disabled, not creating agent for ${senderOpenId}`);
|
|
558
|
+
return {
|
|
559
|
+
created: false,
|
|
560
|
+
updatedCfg: cfg
|
|
561
|
+
};
|
|
562
|
+
}
|
|
554
563
|
const existingBindings = cfg.bindings ?? [];
|
|
555
564
|
if (existingBindings.some((b) => b.match?.channel === "feishu" && b.match?.peer?.kind === "direct" && b.match?.peer?.id === senderOpenId)) return {
|
|
556
565
|
created: false,
|
|
@@ -639,17 +648,30 @@ function resolveUserPath(p) {
|
|
|
639
648
|
return p;
|
|
640
649
|
}
|
|
641
650
|
//#endregion
|
|
651
|
+
//#region extensions/feishu/src/agent-config.ts
|
|
652
|
+
const DEFAULT_AGENT_ID = "main";
|
|
653
|
+
function normalizeAgentId(value) {
|
|
654
|
+
return (value ?? "").trim().toLowerCase() || DEFAULT_AGENT_ID;
|
|
655
|
+
}
|
|
656
|
+
function resolveFeishuConfigReasoningDefault(cfg, agentId) {
|
|
657
|
+
const id = normalizeAgentId(agentId);
|
|
658
|
+
return cfg.agents?.list?.find((entry) => normalizeAgentId(entry?.id) === id)?.reasoningDefault ?? cfg.agents?.defaults?.reasoningDefault ?? "off";
|
|
659
|
+
}
|
|
660
|
+
//#endregion
|
|
642
661
|
//#region extensions/feishu/src/reasoning-preview.ts
|
|
643
662
|
function resolveFeishuReasoningPreviewEnabled(params) {
|
|
644
|
-
|
|
663
|
+
const configDefault = resolveFeishuConfigReasoningDefault(params.cfg, params.agentId);
|
|
664
|
+
if (!params.sessionKey) return configDefault === "stream";
|
|
645
665
|
try {
|
|
646
|
-
|
|
666
|
+
const level = resolveSessionStoreEntry({
|
|
647
667
|
store: loadSessionStore(params.storePath, { skipCache: true }),
|
|
648
668
|
sessionKey: params.sessionKey
|
|
649
|
-
}).existing?.reasoningLevel
|
|
669
|
+
}).existing?.reasoningLevel;
|
|
670
|
+
if (level === "on" || level === "stream" || level === "off") return level === "stream";
|
|
650
671
|
} catch {
|
|
651
672
|
return false;
|
|
652
673
|
}
|
|
674
|
+
return configDefault === "stream";
|
|
653
675
|
}
|
|
654
676
|
//#endregion
|
|
655
677
|
//#region extensions/feishu/src/streaming-card.ts
|
|
@@ -1179,7 +1201,7 @@ function resolveCardNote(agentId, identity, prefixCtx) {
|
|
|
1179
1201
|
}
|
|
1180
1202
|
function createFeishuReplyDispatcher(params) {
|
|
1181
1203
|
const core = getFeishuRuntime();
|
|
1182
|
-
const { cfg, agentId, chatId, replyToMessageId, skipReplyToInMessages, replyInThread, threadReply, rootId,
|
|
1204
|
+
const { cfg, agentId, chatId, replyToMessageId, skipReplyToInMessages, replyInThread, threadReply, rootId, accountId, identity } = params;
|
|
1183
1205
|
const sendReplyToMessageId = skipReplyToInMessages ? void 0 : replyToMessageId;
|
|
1184
1206
|
const effectiveReplyInThread = threadReply === true ? true : replyInThread;
|
|
1185
1207
|
const account = resolveFeishuRuntimeAccount({
|
|
@@ -1191,7 +1213,7 @@ function createFeishuReplyDispatcher(params) {
|
|
|
1191
1213
|
agentId
|
|
1192
1214
|
});
|
|
1193
1215
|
let typingState = null;
|
|
1194
|
-
const { typingCallbacks } =
|
|
1216
|
+
const { typingCallbacks } = createChannelMessageReplyPipeline({
|
|
1195
1217
|
cfg,
|
|
1196
1218
|
agentId,
|
|
1197
1219
|
channel: "feishu",
|
|
@@ -1329,8 +1351,7 @@ function createFeishuReplyDispatcher(params) {
|
|
|
1329
1351
|
await partialUpdateQueue;
|
|
1330
1352
|
if (streaming?.isActive()) {
|
|
1331
1353
|
statusLine = "";
|
|
1332
|
-
|
|
1333
|
-
if (mentionTargets?.length) text = buildMentionedCardContent(mentionTargets, text);
|
|
1354
|
+
const text = buildCombinedStreamText(reasoningText, streamText);
|
|
1334
1355
|
const finalNote = resolveCardNote(agentId, identity, prefixContext.prefixContext);
|
|
1335
1356
|
await streaming.close(text, { note: finalNote });
|
|
1336
1357
|
if (streamText) {
|
|
@@ -1386,14 +1407,13 @@ function createFeishuReplyDispatcher(params) {
|
|
|
1386
1407
|
text: options.fallbackText,
|
|
1387
1408
|
useCard: false,
|
|
1388
1409
|
infoKind: "final",
|
|
1389
|
-
sendChunk: async ({ chunk
|
|
1410
|
+
sendChunk: async ({ chunk }) => {
|
|
1390
1411
|
await sendMessageFeishu({
|
|
1391
1412
|
cfg,
|
|
1392
1413
|
to: chatId,
|
|
1393
1414
|
text: chunk,
|
|
1394
1415
|
replyToMessageId: sendReplyToMessageId,
|
|
1395
1416
|
replyInThread: effectiveReplyInThread,
|
|
1396
|
-
mentions: isFirst ? mentionTargets : void 0,
|
|
1397
1417
|
accountId
|
|
1398
1418
|
});
|
|
1399
1419
|
}
|
|
@@ -1407,14 +1427,13 @@ function createFeishuReplyDispatcher(params) {
|
|
|
1407
1427
|
text: fallbackText,
|
|
1408
1428
|
useCard: false,
|
|
1409
1429
|
infoKind: "final",
|
|
1410
|
-
sendChunk: async ({ chunk
|
|
1430
|
+
sendChunk: async ({ chunk }) => {
|
|
1411
1431
|
await sendMessageFeishu({
|
|
1412
1432
|
cfg,
|
|
1413
1433
|
to: chatId,
|
|
1414
1434
|
text: chunk,
|
|
1415
1435
|
replyToMessageId: sendReplyToMessageId,
|
|
1416
1436
|
replyInThread: effectiveReplyInThread,
|
|
1417
|
-
mentions: isFirst ? mentionTargets : void 0,
|
|
1418
1437
|
accountId
|
|
1419
1438
|
});
|
|
1420
1439
|
}
|
|
@@ -1434,7 +1453,11 @@ function createFeishuReplyDispatcher(params) {
|
|
|
1434
1453
|
await typingCallbacks?.onReplyStart?.();
|
|
1435
1454
|
},
|
|
1436
1455
|
deliver: async (payload, info) => {
|
|
1437
|
-
const
|
|
1456
|
+
const payloadText = payload.isReasoning && payload.text ? formatReasoningMessage(payload.text) : payload.text;
|
|
1457
|
+
const reply = resolveSendableOutboundReplyParts({
|
|
1458
|
+
...payload,
|
|
1459
|
+
text: payloadText
|
|
1460
|
+
});
|
|
1438
1461
|
const text = reply.text;
|
|
1439
1462
|
const hasText = reply.hasText;
|
|
1440
1463
|
const hasMedia = reply.hasMedia;
|
|
@@ -1478,14 +1501,13 @@ function createFeishuReplyDispatcher(params) {
|
|
|
1478
1501
|
text,
|
|
1479
1502
|
useCard: true,
|
|
1480
1503
|
infoKind: info?.kind,
|
|
1481
|
-
sendChunk: async ({ chunk
|
|
1504
|
+
sendChunk: async ({ chunk }) => {
|
|
1482
1505
|
await sendStructuredCardFeishu({
|
|
1483
1506
|
cfg,
|
|
1484
1507
|
to: chatId,
|
|
1485
1508
|
text: chunk,
|
|
1486
1509
|
replyToMessageId: sendReplyToMessageId,
|
|
1487
1510
|
replyInThread: effectiveReplyInThread,
|
|
1488
|
-
mentions: isFirst ? mentionTargets : void 0,
|
|
1489
1511
|
accountId,
|
|
1490
1512
|
header: cardHeader,
|
|
1491
1513
|
note: cardNote
|
|
@@ -1496,14 +1518,13 @@ function createFeishuReplyDispatcher(params) {
|
|
|
1496
1518
|
text,
|
|
1497
1519
|
useCard: false,
|
|
1498
1520
|
infoKind: info?.kind,
|
|
1499
|
-
sendChunk: async ({ chunk
|
|
1521
|
+
sendChunk: async ({ chunk }) => {
|
|
1500
1522
|
await sendMessageFeishu({
|
|
1501
1523
|
cfg,
|
|
1502
1524
|
to: chatId,
|
|
1503
1525
|
text: chunk,
|
|
1504
1526
|
replyToMessageId: sendReplyToMessageId,
|
|
1505
1527
|
replyInThread: effectiveReplyInThread,
|
|
1506
|
-
mentions: isFirst ? mentionTargets : void 0,
|
|
1507
1528
|
accountId
|
|
1508
1529
|
});
|
|
1509
1530
|
}
|
|
@@ -1547,7 +1568,7 @@ function createFeishuReplyDispatcher(params) {
|
|
|
1547
1568
|
onReasoningStream: reasoningPreviewEnabled ? (payload) => {
|
|
1548
1569
|
if (!payload.text) return;
|
|
1549
1570
|
startStreaming();
|
|
1550
|
-
queueReasoningUpdate(payload.text);
|
|
1571
|
+
queueReasoningUpdate(formatReasoningMessage(payload.text));
|
|
1551
1572
|
} : void 0,
|
|
1552
1573
|
onReasoningEnd: reasoningPreviewEnabled ? () => {} : void 0,
|
|
1553
1574
|
onToolStart: streamingEnabled ? (payload) => {
|
|
@@ -1696,6 +1717,14 @@ function parseFeishuMessageEvent(event, botOpenId, _botName) {
|
|
|
1696
1717
|
}
|
|
1697
1718
|
return ctx;
|
|
1698
1719
|
}
|
|
1720
|
+
const MAX_MENTION_CONTEXT_NAME_LENGTH = 80;
|
|
1721
|
+
function formatMentionNameForAgentContext(name) {
|
|
1722
|
+
const normalized = Array.from(name, (char) => {
|
|
1723
|
+
return char.charCodeAt(0) < 32 || char === "[" || char === "]" ? " " : char;
|
|
1724
|
+
}).join("").replace(/\s+/g, " ").trim();
|
|
1725
|
+
const bounded = normalized.length > MAX_MENTION_CONTEXT_NAME_LENGTH ? `${normalized.slice(0, MAX_MENTION_CONTEXT_NAME_LENGTH - 3)}...` : normalized;
|
|
1726
|
+
return JSON.stringify(bounded || "unknown");
|
|
1727
|
+
}
|
|
1699
1728
|
function buildFeishuAgentBody(params) {
|
|
1700
1729
|
const { ctx, quotedContent, permissionErrorForAgent, botOpenId } = params;
|
|
1701
1730
|
let messageBody = ctx.content;
|
|
@@ -1707,8 +1736,8 @@ function buildFeishuAgentBody(params) {
|
|
|
1707
1736
|
if (botIdHint) messageBody += `\n[System: If user_id is "${botIdHint}", that mention refers to you.]`;
|
|
1708
1737
|
}
|
|
1709
1738
|
if (ctx.mentionTargets && ctx.mentionTargets.length > 0) {
|
|
1710
|
-
const targetNames = ctx.mentionTargets.map((t) => t.name).join(", ");
|
|
1711
|
-
messageBody += `\n\n[System:
|
|
1739
|
+
const targetNames = ctx.mentionTargets.map((t) => formatMentionNameForAgentContext(t.name)).join(", ");
|
|
1740
|
+
messageBody += `\n\n[System: Feishu users mentioned in the incoming message, for context only: ${targetNames}. Do not notify or mention these users solely because they are listed here.]`;
|
|
1712
1741
|
}
|
|
1713
1742
|
messageBody = `[message_id: ${ctx.messageId}]\n${messageBody}`;
|
|
1714
1743
|
if (permissionErrorForAgent) {
|
|
@@ -1875,7 +1904,7 @@ async function handleFeishuMessage(params) {
|
|
|
1875
1904
|
const configAllowFrom = feishuCfg?.allowFrom ?? [];
|
|
1876
1905
|
const useAccessGroups = cfg.commands?.useAccessGroups !== false;
|
|
1877
1906
|
const rawBroadcastAgents = isGroup ? resolveBroadcastAgents(cfg, ctx.chatId) : null;
|
|
1878
|
-
const broadcastAgents = rawBroadcastAgents ? [...new Set(rawBroadcastAgents.map((id) => normalizeAgentId(id)))] : null;
|
|
1907
|
+
const broadcastAgents = rawBroadcastAgents ? [...new Set(rawBroadcastAgents.map((id) => normalizeAgentId$1(id)))] : null;
|
|
1879
1908
|
const messageCreateTimeMs = event.message.create_time ? Number.parseInt(event.message.create_time, 10) : Date.now();
|
|
1880
1909
|
let requireMention = false;
|
|
1881
1910
|
if (isGroup) {
|
|
@@ -2026,6 +2055,11 @@ async function handleFeishuMessage(params) {
|
|
|
2026
2055
|
runtime: getFeishuRuntime(),
|
|
2027
2056
|
senderOpenId: ctx.senderOpenId,
|
|
2028
2057
|
dynamicCfg,
|
|
2058
|
+
configWritesAllowed: resolveChannelConfigWrites({
|
|
2059
|
+
cfg,
|
|
2060
|
+
channelId: "feishu",
|
|
2061
|
+
accountId: account.accountId
|
|
2062
|
+
}),
|
|
2029
2063
|
log: (msg) => log(msg)
|
|
2030
2064
|
});
|
|
2031
2065
|
if (result.created) {
|
|
@@ -2353,12 +2387,12 @@ async function handleFeishuMessage(params) {
|
|
|
2353
2387
|
return;
|
|
2354
2388
|
}
|
|
2355
2389
|
const strategy = cfg.broadcast?.strategy === "sequential" ? "sequential" : "parallel";
|
|
2356
|
-
const activeAgentId = ctx.mentionedBot || !requireMention ? normalizeAgentId(route.agentId) : null;
|
|
2357
|
-
const agentIds = (cfg.agents?.list ?? []).map((a) => normalizeAgentId(a.id));
|
|
2390
|
+
const activeAgentId = ctx.mentionedBot || !requireMention ? normalizeAgentId$1(route.agentId) : null;
|
|
2391
|
+
const agentIds = (cfg.agents?.list ?? []).map((a) => normalizeAgentId$1(a.id));
|
|
2358
2392
|
const hasKnownAgents = agentIds.length > 0;
|
|
2359
2393
|
log(`feishu[${account.accountId}]: broadcasting to ${broadcastAgents.length} agents (strategy=${strategy}, active=${activeAgentId ?? "none"})`);
|
|
2360
2394
|
const dispatchForAgent = async (agentId) => {
|
|
2361
|
-
if (hasKnownAgents && !agentIds.includes(normalizeAgentId(agentId))) {
|
|
2395
|
+
if (hasKnownAgents && !agentIds.includes(normalizeAgentId$1(agentId))) {
|
|
2362
2396
|
log(`feishu[${account.accountId}]: broadcast agent ${agentId} not found in agents.list; skipping`);
|
|
2363
2397
|
return;
|
|
2364
2398
|
}
|
|
@@ -2368,6 +2402,8 @@ async function handleFeishuMessage(params) {
|
|
|
2368
2402
|
log(`feishu[${account.accountId}]: failed to record broadcast inbound session ${agentSessionKey}: ${String(err)}`);
|
|
2369
2403
|
} };
|
|
2370
2404
|
const allowReasoningPreview = resolveFeishuReasoningPreviewEnabled({
|
|
2405
|
+
cfg,
|
|
2406
|
+
agentId,
|
|
2371
2407
|
storePath: agentStorePath,
|
|
2372
2408
|
sessionKey: agentSessionKey
|
|
2373
2409
|
});
|
|
@@ -2385,7 +2421,6 @@ async function handleFeishuMessage(params) {
|
|
|
2385
2421
|
replyInThread,
|
|
2386
2422
|
rootId: ctx.rootId,
|
|
2387
2423
|
threadReply,
|
|
2388
|
-
mentionTargets: ctx.mentionTargets,
|
|
2389
2424
|
accountId: account.accountId,
|
|
2390
2425
|
identity,
|
|
2391
2426
|
messageCreateTimeMs
|
|
@@ -2503,6 +2538,8 @@ async function handleFeishuMessage(params) {
|
|
|
2503
2538
|
const identity = resolveAgentOutboundIdentity(cfg, route.agentId);
|
|
2504
2539
|
const storePath = core.channel.session.resolveStorePath(cfg.session?.store, { agentId: route.agentId });
|
|
2505
2540
|
const allowReasoningPreview = resolveFeishuReasoningPreviewEnabled({
|
|
2541
|
+
cfg,
|
|
2542
|
+
agentId: route.agentId,
|
|
2506
2543
|
storePath,
|
|
2507
2544
|
sessionKey: route.sessionKey
|
|
2508
2545
|
});
|
|
@@ -2517,7 +2554,6 @@ async function handleFeishuMessage(params) {
|
|
|
2517
2554
|
replyInThread,
|
|
2518
2555
|
rootId: ctx.rootId,
|
|
2519
2556
|
threadReply,
|
|
2520
|
-
mentionTargets: ctx.mentionTargets,
|
|
2521
2557
|
accountId: account.accountId,
|
|
2522
2558
|
identity,
|
|
2523
2559
|
messageCreateTimeMs
|
|
@@ -3999,6 +4035,11 @@ async function handleFeishuCommentEvent(params) {
|
|
|
3999
4035
|
runtime: core,
|
|
4000
4036
|
senderOpenId: turn.senderId,
|
|
4001
4037
|
dynamicCfg,
|
|
4038
|
+
configWritesAllowed: resolveChannelConfigWrites({
|
|
4039
|
+
cfg: params.cfg,
|
|
4040
|
+
channelId: "feishu",
|
|
4041
|
+
accountId: account.accountId
|
|
4042
|
+
}),
|
|
4002
4043
|
log: (message) => log(message)
|
|
4003
4044
|
});
|
|
4004
4045
|
if (dynamicResult.created) {
|
package/dist/runtime-api.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { n as setFeishuRuntime } from "./runtime-CG0DuRCy.js";
|
|
2
2
|
import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
|
|
3
|
+
import { createReplyPrefixContext } from "openclaw/plugin-sdk/channel-message";
|
|
3
4
|
import { createChannelPairingController } from "openclaw/plugin-sdk/channel-pairing";
|
|
4
5
|
import { PAIRING_APPROVED_MESSAGE, buildProbeChannelStatusSummary, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/channel-status";
|
|
5
6
|
import { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
|
|
6
7
|
import { DEFAULT_ACCOUNT_ID, buildChannelConfigSchema, createActionGate, createDedupeCache } from "openclaw/plugin-sdk/core";
|
|
7
8
|
import { buildAgentMediaPayload } from "openclaw/plugin-sdk/agent-media-payload";
|
|
8
|
-
import { createReplyPrefixContext } from "openclaw/plugin-sdk/channel-reply-pipeline";
|
|
9
9
|
import { evaluateSupplementalContextVisibility, filterSupplementalContextItems, resolveChannelContextVisibilityMode } from "openclaw/plugin-sdk/context-visibility-runtime";
|
|
10
10
|
import { loadSessionStore, resolveSessionStoreEntry } from "openclaw/plugin-sdk/session-store-runtime";
|
|
11
11
|
import { readJsonFileWithFallback } from "openclaw/plugin-sdk/json-store";
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { i as resolveReceiveIdType, r as normalizeFeishuTarget } from "./targets-JMFJRKSe.js";
|
|
2
2
|
import { c as createFeishuApiError, f as isRecord$2, g as requestFeishuApi, s as resolveFeishuRuntimeAccount } from "./accounts-Ba3-WP1z.js";
|
|
3
|
+
import { i as toFeishuSendResult, r as resolveFeishuReceiptKind, t as assertFeishuMessageApiSuccess } from "./send-result-BVFTskB_.js";
|
|
3
4
|
import { t as getFeishuRuntime } from "./runtime-CG0DuRCy.js";
|
|
4
5
|
import { r as createFeishuClient } from "./client-DBVoQL5w.js";
|
|
5
6
|
import { convertMarkdownTables, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime";
|
|
6
7
|
import fs from "node:fs";
|
|
7
8
|
import path from "node:path";
|
|
9
|
+
import { mediaKindFromMime } from "openclaw/plugin-sdk/media-mime";
|
|
8
10
|
import { MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS, runFfmpeg } from "openclaw/plugin-sdk/media-runtime";
|
|
11
|
+
import { readRegularFile, writeExternalFileWithinRoot } from "openclaw/plugin-sdk/security-runtime";
|
|
9
12
|
import { Readable } from "node:stream";
|
|
10
|
-
import {
|
|
11
|
-
import { resolvePreferredOpenClawTmpDir, withTempDownloadPath } from "openclaw/plugin-sdk/temp-path";
|
|
13
|
+
import { resolvePreferredOpenClawTmpDir, withTempDownloadPath, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
|
|
12
14
|
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
13
15
|
//#region extensions/feishu/src/external-keys.ts
|
|
14
16
|
const CONTROL_CHARS_RE = /\p{Cc}/u;
|
|
@@ -22,17 +24,6 @@ function normalizeFeishuExternalKey(value) {
|
|
|
22
24
|
return normalized;
|
|
23
25
|
}
|
|
24
26
|
//#endregion
|
|
25
|
-
//#region extensions/feishu/src/send-result.ts
|
|
26
|
-
function assertFeishuMessageApiSuccess(response, errorPrefix) {
|
|
27
|
-
if (response.code !== 0) throw new Error(`${errorPrefix}: ${response.msg || `code ${response.code}`}`);
|
|
28
|
-
}
|
|
29
|
-
function toFeishuSendResult(response, chatId) {
|
|
30
|
-
return {
|
|
31
|
-
messageId: response.data?.message_id ?? "unknown",
|
|
32
|
-
chatId
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
//#endregion
|
|
36
27
|
//#region extensions/feishu/src/send-target.ts
|
|
37
28
|
function resolveFeishuSendTarget(params) {
|
|
38
29
|
const target = params.to.trim();
|
|
@@ -237,7 +228,7 @@ async function uploadImageFeishu(params) {
|
|
|
237
228
|
cfg,
|
|
238
229
|
accountId
|
|
239
230
|
});
|
|
240
|
-
const imageData = typeof image === "string" ?
|
|
231
|
+
const imageData = typeof image === "string" ? (await readRegularFile({ filePath: image })).buffer : image;
|
|
241
232
|
return { imageKey: extractFeishuUploadKey(await requestFeishuApi(() => client.im.image.create({ data: {
|
|
242
233
|
image_type: imageType,
|
|
243
234
|
image: imageData
|
|
@@ -269,7 +260,7 @@ async function uploadFileFeishu(params) {
|
|
|
269
260
|
cfg,
|
|
270
261
|
accountId
|
|
271
262
|
});
|
|
272
|
-
const fileData = typeof file === "string" ?
|
|
263
|
+
const fileData = typeof file === "string" ? (await readRegularFile({ filePath: file })).buffer : file;
|
|
273
264
|
const safeFileName = sanitizeFileNameForUpload(fileName);
|
|
274
265
|
return { fileKey: extractFeishuUploadKey(await requestFeishuApi(() => client.im.file.create({ data: {
|
|
275
266
|
file_type: fileType,
|
|
@@ -302,7 +293,7 @@ async function sendImageFeishu(params) {
|
|
|
302
293
|
}
|
|
303
294
|
}), "Feishu image reply failed", { includeNestedErrorLogId: true });
|
|
304
295
|
assertFeishuMessageApiSuccess(response, "Feishu image reply failed");
|
|
305
|
-
return toFeishuSendResult(response, receiveId);
|
|
296
|
+
return toFeishuSendResult(response, receiveId, "media");
|
|
306
297
|
}
|
|
307
298
|
const response = await requestFeishuApi(() => client.im.message.create({
|
|
308
299
|
params: { receive_id_type: receiveIdType },
|
|
@@ -313,7 +304,7 @@ async function sendImageFeishu(params) {
|
|
|
313
304
|
}
|
|
314
305
|
}), "Feishu image send failed", { includeNestedErrorLogId: true });
|
|
315
306
|
assertFeishuMessageApiSuccess(response, "Feishu image send failed");
|
|
316
|
-
return toFeishuSendResult(response, receiveId);
|
|
307
|
+
return toFeishuSendResult(response, receiveId, "media");
|
|
317
308
|
}
|
|
318
309
|
/**
|
|
319
310
|
* Send a file message using a file_key
|
|
@@ -337,7 +328,7 @@ async function sendFileFeishu(params) {
|
|
|
337
328
|
}
|
|
338
329
|
}), "Feishu file reply failed", { includeNestedErrorLogId: true });
|
|
339
330
|
assertFeishuMessageApiSuccess(response, "Feishu file reply failed");
|
|
340
|
-
return toFeishuSendResult(response, receiveId);
|
|
331
|
+
return toFeishuSendResult(response, receiveId, resolveFeishuReceiptKind(msgType));
|
|
341
332
|
}
|
|
342
333
|
const response = await requestFeishuApi(() => client.im.message.create({
|
|
343
334
|
params: { receive_id_type: receiveIdType },
|
|
@@ -348,7 +339,7 @@ async function sendFileFeishu(params) {
|
|
|
348
339
|
}
|
|
349
340
|
}), "Feishu file send failed", { includeNestedErrorLogId: true });
|
|
350
341
|
assertFeishuMessageApiSuccess(response, "Feishu file send failed");
|
|
351
|
-
return toFeishuSendResult(response, receiveId);
|
|
342
|
+
return toFeishuSendResult(response, receiveId, resolveFeishuReceiptKind(msgType));
|
|
352
343
|
}
|
|
353
344
|
/**
|
|
354
345
|
* Helper to detect file type from extension
|
|
@@ -432,51 +423,47 @@ function isLikelyTranscodableAudio(params) {
|
|
|
432
423
|
return FEISHU_TRANSCODABLE_AUDIO_EXTS.has(ext) || mediaKindFromMime(contentType) === "audio";
|
|
433
424
|
}
|
|
434
425
|
async function transcodeToFeishuVoiceOpus(params) {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
});
|
|
440
|
-
const tempDir = await fs.promises.mkdtemp(path.join(tempRoot, "feishu-voice-"));
|
|
441
|
-
try {
|
|
426
|
+
return await withTempWorkspace({
|
|
427
|
+
rootDir: resolvePreferredOpenClawTmpDir(),
|
|
428
|
+
prefix: "feishu-voice-"
|
|
429
|
+
}, async (workspace) => {
|
|
442
430
|
const ext = normalizeLowercaseStringOrEmpty(path.extname(params.fileName));
|
|
443
431
|
const inputExt = ext && ext.length <= 12 ? ext : ".audio";
|
|
444
|
-
const inputPath =
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
432
|
+
const inputPath = await workspace.write(`input${inputExt}`, params.buffer);
|
|
433
|
+
await writeExternalFileWithinRoot({
|
|
434
|
+
rootDir: workspace.dir,
|
|
435
|
+
path: FEISHU_VOICE_FILE_NAME,
|
|
436
|
+
write: async (outputPath) => {
|
|
437
|
+
await runFfmpeg([
|
|
438
|
+
"-hide_banner",
|
|
439
|
+
"-loglevel",
|
|
440
|
+
"error",
|
|
441
|
+
"-y",
|
|
442
|
+
"-i",
|
|
443
|
+
inputPath,
|
|
444
|
+
"-vn",
|
|
445
|
+
"-sn",
|
|
446
|
+
"-dn",
|
|
447
|
+
"-t",
|
|
448
|
+
String(MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS),
|
|
449
|
+
"-ar",
|
|
450
|
+
String(FEISHU_VOICE_SAMPLE_RATE_HZ),
|
|
451
|
+
"-ac",
|
|
452
|
+
"1",
|
|
453
|
+
"-c:a",
|
|
454
|
+
"libopus",
|
|
455
|
+
"-b:a",
|
|
456
|
+
FEISHU_VOICE_BITRATE,
|
|
457
|
+
outputPath
|
|
458
|
+
]);
|
|
459
|
+
}
|
|
460
|
+
});
|
|
469
461
|
return {
|
|
470
|
-
buffer: await
|
|
462
|
+
buffer: await workspace.read(FEISHU_VOICE_FILE_NAME),
|
|
471
463
|
fileName: FEISHU_VOICE_FILE_NAME,
|
|
472
464
|
contentType: "audio/ogg"
|
|
473
465
|
};
|
|
474
|
-
}
|
|
475
|
-
await fs.promises.rm(tempDir, {
|
|
476
|
-
recursive: true,
|
|
477
|
-
force: true
|
|
478
|
-
});
|
|
479
|
-
}
|
|
466
|
+
});
|
|
480
467
|
}
|
|
481
468
|
async function prepareFeishuVoiceMedia(params) {
|
|
482
469
|
if (isFeishuNativeVoiceAudio(params)) return params;
|
|
@@ -845,7 +832,7 @@ async function sendFallbackDirect(client, params, errorPrefix) {
|
|
|
845
832
|
}
|
|
846
833
|
}), errorPrefix, { includeNestedErrorLogId: true });
|
|
847
834
|
assertFeishuMessageApiSuccess(response, errorPrefix);
|
|
848
|
-
return toFeishuSendResult(response, params.receiveId);
|
|
835
|
+
return toFeishuSendResult(response, params.receiveId, resolveFeishuReceiptKind(params.msgType));
|
|
849
836
|
}
|
|
850
837
|
async function sendReplyOrFallbackDirect(client, params) {
|
|
851
838
|
if (!params.replyToMessageId) return sendFallbackDirect(client, params.directParams, params.directErrorPrefix);
|
|
@@ -870,7 +857,7 @@ async function sendReplyOrFallbackDirect(client, params) {
|
|
|
870
857
|
return sendFallbackDirect(client, params.directParams, params.directErrorPrefix);
|
|
871
858
|
}
|
|
872
859
|
assertFeishuMessageApiSuccess(response, params.replyErrorPrefix);
|
|
873
|
-
return toFeishuSendResult(response, params.directParams.receiveId);
|
|
860
|
+
return toFeishuSendResult(response, params.directParams.receiveId, resolveFeishuReceiptKind(params.msgType));
|
|
874
861
|
}
|
|
875
862
|
function normalizeCardTemplateVariable(value) {
|
|
876
863
|
if (typeof value === "string") return value;
|
|
@@ -1215,4 +1202,4 @@ async function sendMarkdownCardFeishu(params) {
|
|
|
1215
1202
|
});
|
|
1216
1203
|
}
|
|
1217
1204
|
//#endregion
|
|
1218
|
-
export {
|
|
1205
|
+
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, downloadMessageResourceFeishu as m, getMessageFeishu as n, sendMarkdownCardFeishu as o, isFeishuGroupChatType as p, listFeishuThreadMessages as r, sendMessageFeishu as s, editMessageFeishu as t, extractMentionTargets as u };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { f as isRecord } from "./accounts-Ba3-WP1z.js";
|
|
2
|
+
import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-message";
|
|
2
3
|
//#region extensions/feishu/src/card-interaction.ts
|
|
3
4
|
const FEISHU_CARD_INTERACTION_VERSION = "ocf1";
|
|
4
5
|
function isInteractionKind(value) {
|
|
@@ -93,4 +94,47 @@ function decodeFeishuCardAction(params) {
|
|
|
93
94
|
};
|
|
94
95
|
}
|
|
95
96
|
//#endregion
|
|
96
|
-
|
|
97
|
+
//#region extensions/feishu/src/send-result.ts
|
|
98
|
+
function resolveFeishuReceiptKind(msgType) {
|
|
99
|
+
switch (msgType) {
|
|
100
|
+
case "audio": return "voice";
|
|
101
|
+
case "image":
|
|
102
|
+
case "media":
|
|
103
|
+
case "file": return "media";
|
|
104
|
+
case "interactive": return "card";
|
|
105
|
+
case "post":
|
|
106
|
+
case "text": return "text";
|
|
107
|
+
default: return "unknown";
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function createFeishuSendReceipt(params) {
|
|
111
|
+
const messageId = params.messageId?.trim();
|
|
112
|
+
const chatId = params.chatId.trim();
|
|
113
|
+
return createMessageReceiptFromOutboundResults({
|
|
114
|
+
results: messageId ? [{
|
|
115
|
+
channel: "feishu",
|
|
116
|
+
messageId,
|
|
117
|
+
chatId,
|
|
118
|
+
conversationId: chatId
|
|
119
|
+
}] : [],
|
|
120
|
+
...chatId ? { threadId: chatId } : {},
|
|
121
|
+
kind: params.kind ?? "unknown"
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
function assertFeishuMessageApiSuccess(response, errorPrefix) {
|
|
125
|
+
if (response.code !== 0) throw new Error(`${errorPrefix}: ${response.msg || `code ${response.code}`}`);
|
|
126
|
+
}
|
|
127
|
+
function toFeishuSendResult(response, chatId, kind) {
|
|
128
|
+
const messageId = response.data?.message_id ?? "unknown";
|
|
129
|
+
return {
|
|
130
|
+
messageId,
|
|
131
|
+
chatId,
|
|
132
|
+
receipt: createFeishuSendReceipt({
|
|
133
|
+
messageId,
|
|
134
|
+
chatId,
|
|
135
|
+
kind
|
|
136
|
+
})
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
//#endregion
|
|
140
|
+
export { FEISHU_CARD_INTERACTION_VERSION as a, decodeFeishuCardAction as c, toFeishuSendResult as i, createFeishuSendReceipt as n, buildFeishuCardActionTextFallback as o, resolveFeishuReceiptKind as r, createFeishuCardInteractionEnvelope as s, assertFeishuMessageApiSuccess as t };
|
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-C5kY2KFE.js";
|
|
2
2
|
export { feishuPlugin, feishuSetupAdapter, feishuSetupWizard };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/feishu",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.9-beta.1",
|
|
4
4
|
"description": "OpenClaw Feishu/Lark channel plugin (community maintained by @m1heng)",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -9,14 +9,14 @@
|
|
|
9
9
|
"type": "module",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@larksuiteoapi/node-sdk": "^1.62.1",
|
|
12
|
-
"typebox": "1.1.
|
|
12
|
+
"typebox": "1.1.38"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"@openclaw/plugin-sdk": "workspace:*",
|
|
16
16
|
"openclaw": "workspace:*"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
|
-
"openclaw": ">=2026.5.
|
|
19
|
+
"openclaw": ">=2026.5.9-beta.1"
|
|
20
20
|
},
|
|
21
21
|
"peerDependenciesMeta": {
|
|
22
22
|
"openclaw": {
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"minHostVersion": ">=2026.4.25"
|
|
48
48
|
},
|
|
49
49
|
"compat": {
|
|
50
|
-
"pluginApi": ">=2026.5.
|
|
50
|
+
"pluginApi": ">=2026.5.9-beta.1"
|
|
51
51
|
},
|
|
52
52
|
"build": {
|
|
53
|
-
"openclawVersion": "2026.5.
|
|
53
|
+
"openclawVersion": "2026.5.9-beta.1"
|
|
54
54
|
},
|
|
55
55
|
"release": {
|
|
56
56
|
"publishToClawHub": true,
|