@openclaw/feishu 2026.7.2-beta.7 → 2026.8.1-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accounts-CCCdMen2.js +203 -0
- package/dist/api.js +61 -60
- package/dist/{channel-CScE82zY.js → channel-Ceq80_zP.js} +71 -42
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-B21e1E0r.js → channel.runtime-DnRyzGoU.js} +201 -152
- package/dist/{client-Dcbs6vml.js → client-Hp7uo_cl.js} +27 -16
- package/dist/contract-api.js +2 -2
- package/dist/{conversation-id-BeJL-wq7.js → conversation-id-VYgGQ-GX.js} +11 -15
- package/dist/doctor-contract-api.js +1 -1
- package/dist/doctor-contract-bEQXIXyP.js +158 -0
- package/dist/{drive-hSi_Utp0.js → drive-BVYM_Y4k.js} +325 -44
- package/dist/{media-CEUraFOR.js → media-BDouVaaM.js} +298 -182
- package/dist/{monitor-DngbaA6a.js → monitor-CZ8cDXrq.js} +3 -3
- package/dist/{monitor.account-BnTWCw55.js → monitor.account-Dq_voVMB.js} +263 -179
- package/dist/{monitor.startup-CqH2tiJq.js → monitor.startup-BGErejNH.js} +1 -1
- package/dist/{probe-p3POS2RN.js → probe-DVpy58s0.js} +2 -2
- package/dist/security-audit-D6Fz2h6p.js +23 -0
- package/dist/{send-result-B9_BpUPx.js → send-result-DEAycmOk.js} +18 -9
- package/dist/session-binding-contract-api.js +2 -2
- package/dist/{session-conversation-BksWrfzm.js → session-conversation-DFCIvQK-.js} +1 -1
- package/dist/session-key-api.js +1 -1
- package/dist/setup-api.js +1 -1
- package/dist/{subagent-hooks-Cx1cX7rW.js → subagent-hooks-KUi-7vUy.js} +4 -64
- package/dist/subagent-hooks-api.js +1 -1
- package/dist/{thread-bindings-N3wkgkIN.js → thread-bindings-CptM_YU6.js} +7 -9
- package/openclaw.plugin.json +143 -1
- package/package.json +4 -4
- package/skills/feishu-doc/SKILL.md +20 -195
- package/skills/feishu-doc/references/block-types.md +9 -14
- package/skills/feishu-drive/SKILL.md +16 -102
- package/skills/feishu-perm/SKILL.md +10 -110
- package/skills/feishu-wiki/SKILL.md +13 -109
- package/dist/accounts-u9X5Wsan.js +0 -469
- package/dist/doctor-contract-BiD9tyIv.js +0 -102
- package/dist/security-audit-D7WK_BHh.js +0 -11
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
import { o as resolveFeishuAccount, s as resolveFeishuRuntimeAccount
|
|
2
|
-
import { c as isFeishuCardWithinEnvelope, l as listFeishuDirectoryGroups, o as assertFeishuCardWithinEnvelope, s as buildFeishuPresentationCardElements, u as listFeishuDirectoryPeers } from "./channel-
|
|
3
|
-
import { a as readNativeFeishuCardJson, d as chunkFeishuPostMarkdown, f as materializeFeishuPostMarkdownSoftBreaks, o as resolveFeishuCardTemplate, s as sanitizeNativeFeishuCard, u as chunkFeishuMarkdown } from "./send-result-
|
|
4
|
-
import { r as createFeishuClient } from "./client-
|
|
5
|
-
import { c as
|
|
6
|
-
import {
|
|
7
|
-
import { t as probeFeishu } from "./probe-
|
|
1
|
+
import { o as resolveFeishuAccount, s as resolveFeishuRuntimeAccount } from "./accounts-CCCdMen2.js";
|
|
2
|
+
import { c as isFeishuCardWithinEnvelope, l as listFeishuDirectoryGroups, o as assertFeishuCardWithinEnvelope, s as buildFeishuPresentationCardElements, u as listFeishuDirectoryPeers } from "./channel-Ceq80_zP.js";
|
|
3
|
+
import { a as readNativeFeishuCardJson, d as chunkFeishuPostMarkdown, f as materializeFeishuPostMarkdownSoftBreaks, o as resolveFeishuCardTemplate, s as sanitizeNativeFeishuCard, u as chunkFeishuMarkdown } from "./send-result-DEAycmOk.js";
|
|
4
|
+
import { r as createFeishuClient } from "./client-Hp7uo_cl.js";
|
|
5
|
+
import { _ as parseFeishuCommentTarget, a as assertFeishuChatMember, c as getChatMembers, l as getFeishuMemberInfo, o as buildFeishuDirectChatMembers, r as cleanupAmbientCommentTypingReaction, s as getChatInfo, t as deliverCommentThreadText } from "./drive-BVYM_Y4k.js";
|
|
6
|
+
import { a as getMessageFeishu, b as resolveFeishuIdentityHeaderTitle, c as sendMarkdownCardFeishu, i as editMessageFeishu, l as sendMessageFeishu, n as sendMediaFeishu, r as shouldSuppressFeishuTextForVoiceMedia, s as sendCardFeishu, u as sendStructuredCardFeishu, v as buildFeishuMediaFallbackText } from "./media-BDouVaaM.js";
|
|
7
|
+
import { t as probeFeishu } from "./probe-DVpy58s0.js";
|
|
8
8
|
import { createReplyToFanout } from "openclaw/plugin-sdk/channel-outbound";
|
|
9
9
|
import { legacyInteractiveReplyToPresentation, normalizeLegacyInteractiveReply, normalizeMessagePresentation, renderMessagePresentationFallbackText, resolveLegacyInteractiveTextFallback } from "openclaw/plugin-sdk/interactive-runtime";
|
|
10
10
|
import { isRecord, normalizeLowercaseStringOrEmpty, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
11
11
|
import { convertMarkdownTables } from "openclaw/plugin-sdk/text-chunking";
|
|
12
12
|
import path from "node:path";
|
|
13
13
|
import { resolveChunkMode, resolveTextChunkLimit } from "openclaw/plugin-sdk/reply-chunking";
|
|
14
|
+
import { isChannelPartialDeliveryError } from "openclaw/plugin-sdk/channel-inbound";
|
|
15
|
+
import { statRegularFileSync } from "openclaw/plugin-sdk/security-runtime";
|
|
14
16
|
import { attachChannelToResult, createAttachedChannelResultAdapter } from "openclaw/plugin-sdk/channel-send-result";
|
|
15
17
|
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
16
18
|
import { getReplyPayloadTtsSupplement, resolvePayloadMediaUrls, sendPayloadMediaSequenceAndFinalize, sendTextMediaPayload } from "openclaw/plugin-sdk/reply-payload";
|
|
17
|
-
import { statRegularFileSync } from "openclaw/plugin-sdk/security-runtime";
|
|
18
19
|
//#region extensions/feishu/src/directory.ts
|
|
19
20
|
const MAX_FEISHU_DIRECTORY_PAGES = 100;
|
|
20
21
|
async function listFeishuDirectoryPeersLive(params) {
|
|
@@ -111,6 +112,8 @@ function normalizePossibleLocalImagePath(text) {
|
|
|
111
112
|
".webp",
|
|
112
113
|
".bmp",
|
|
113
114
|
".ico",
|
|
115
|
+
".heic",
|
|
116
|
+
".tif",
|
|
114
117
|
".tiff"
|
|
115
118
|
].includes(ext)) return null;
|
|
116
119
|
if (!path.isAbsolute(raw)) return null;
|
|
@@ -140,6 +143,20 @@ function readNativeFeishuCard(payload) {
|
|
|
140
143
|
const sanitizedCard = sanitizeNativeFeishuCard(card);
|
|
141
144
|
return sanitizedCard ? markRenderedFeishuCard(sanitizedCard) : void 0;
|
|
142
145
|
}
|
|
146
|
+
function toFeishuOutboundResult(result) {
|
|
147
|
+
const { chatId, ...delivery } = result;
|
|
148
|
+
return {
|
|
149
|
+
...delivery,
|
|
150
|
+
target: {
|
|
151
|
+
kind: "chat",
|
|
152
|
+
id: chatId
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
async function reportFeishuOutboundDelivery(result, onDeliveryResult) {
|
|
157
|
+
await onDeliveryResult?.(attachChannelToResult("feishu", toFeishuOutboundResult(result)));
|
|
158
|
+
return result;
|
|
159
|
+
}
|
|
143
160
|
function consumeFeishuPresentationFallbackMarker(payload) {
|
|
144
161
|
const feishuData = isRecord(payload.channelData?.feishu) ? payload.channelData.feishu : void 0;
|
|
145
162
|
if (feishuData?.[FEISHU_PRESENTATION_FALLBACK_MARKER] !== true) return {
|
|
@@ -295,7 +312,7 @@ async function sendCommentThreadReply(params) {
|
|
|
295
312
|
}
|
|
296
313
|
}
|
|
297
314
|
async function sendOutboundText(params) {
|
|
298
|
-
const { cfg, to, text, accountId, replyToMessageId, replyInThread } = params;
|
|
315
|
+
const { cfg, to, text, accountId, replyToMessageId, replyInThread, onDeliveryResult } = params;
|
|
299
316
|
const commentResult = await sendCommentThreadReply({
|
|
300
317
|
cfg,
|
|
301
318
|
to,
|
|
@@ -303,19 +320,19 @@ async function sendOutboundText(params) {
|
|
|
303
320
|
replyId: replyToMessageId,
|
|
304
321
|
accountId
|
|
305
322
|
});
|
|
306
|
-
if (commentResult) return commentResult;
|
|
323
|
+
if (commentResult) return await reportFeishuOutboundDelivery(commentResult, onDeliveryResult);
|
|
307
324
|
const renderMode = resolveFeishuAccount({
|
|
308
325
|
cfg,
|
|
309
326
|
accountId
|
|
310
327
|
}).config?.renderMode ?? "auto";
|
|
311
|
-
if (renderMode === "card" || renderMode === "auto" && shouldUseCard(text)) return sendMarkdownCardFeishu({
|
|
328
|
+
if (renderMode === "card" || renderMode === "auto" && shouldUseCard(text)) return await reportFeishuOutboundDelivery(await sendMarkdownCardFeishu({
|
|
312
329
|
cfg,
|
|
313
330
|
to,
|
|
314
331
|
text,
|
|
315
332
|
accountId,
|
|
316
333
|
replyToMessageId,
|
|
317
334
|
replyInThread
|
|
318
|
-
});
|
|
335
|
+
}), onDeliveryResult);
|
|
319
336
|
const normalizedText = materializeFeishuPostMarkdownSoftBreaks(convertMarkdownTables(text, resolveMarkdownTableMode({
|
|
320
337
|
cfg,
|
|
321
338
|
channel: "feishu"
|
|
@@ -325,24 +342,21 @@ async function sendOutboundText(params) {
|
|
|
325
342
|
limit: resolveTextChunkLimit(cfg, "feishu", accountId, { fallbackLimit: FEISHU_TEXT_CHUNK_LIMIT }),
|
|
326
343
|
mode: resolveChunkMode(cfg, "feishu", accountId)
|
|
327
344
|
});
|
|
328
|
-
if (subChunks.length <= 1) return sendMessageFeishu({
|
|
329
|
-
cfg,
|
|
330
|
-
to,
|
|
331
|
-
text: subChunks[0] ?? normalizedText,
|
|
332
|
-
accountId,
|
|
333
|
-
replyToMessageId,
|
|
334
|
-
replyInThread
|
|
335
|
-
});
|
|
336
345
|
let lastResult;
|
|
337
346
|
const preserveThread = replyInThread === true;
|
|
338
|
-
|
|
347
|
+
const nextReplyToMessageId = createReplyToFanout({
|
|
348
|
+
replyToId: replyToMessageId,
|
|
349
|
+
replyToIdSource: params.replyToIdSource,
|
|
350
|
+
replyToMode: params.replyToMode ?? "first"
|
|
351
|
+
});
|
|
352
|
+
for (const [i, chunk] of (subChunks.length ? subChunks : [normalizedText]).entries()) lastResult = await reportFeishuOutboundDelivery(await sendMessageFeishu({
|
|
339
353
|
cfg,
|
|
340
354
|
to,
|
|
341
355
|
text: chunk,
|
|
342
356
|
accountId,
|
|
343
|
-
replyToMessageId: preserveThread
|
|
357
|
+
replyToMessageId: preserveThread ? replyToMessageId : nextReplyToMessageId(),
|
|
344
358
|
replyInThread: preserveThread ? true : i === 0 ? replyInThread : void 0
|
|
345
|
-
});
|
|
359
|
+
}), onDeliveryResult);
|
|
346
360
|
return lastResult;
|
|
347
361
|
}
|
|
348
362
|
async function sendFeishuFallbackPayload(params) {
|
|
@@ -371,26 +385,18 @@ async function sendFeishuFallbackPayload(params) {
|
|
|
371
385
|
const sendText = feishuOutbound.sendText;
|
|
372
386
|
if (!sendMedia || !sendText) throw new Error("Feishu fallback delivery is not available.");
|
|
373
387
|
let lastResult;
|
|
374
|
-
for (const mediaUrl of mediaUrls) {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
lastResult = await sendText({
|
|
387
|
-
...ctx,
|
|
388
|
-
text: chunk,
|
|
389
|
-
replyToId: nextReplyToId(),
|
|
390
|
-
onDeliveryResult: void 0
|
|
391
|
-
});
|
|
392
|
-
await ctx.onDeliveryResult?.(lastResult);
|
|
393
|
-
}
|
|
388
|
+
for (const mediaUrl of mediaUrls) lastResult = await sendMedia({
|
|
389
|
+
...ctx,
|
|
390
|
+
text: "",
|
|
391
|
+
mediaUrl,
|
|
392
|
+
replyToId: nextReplyToId(),
|
|
393
|
+
audioAsVoice: params.payload.audioAsVoice ?? ctx.audioAsVoice
|
|
394
|
+
});
|
|
395
|
+
for (const chunk of textChunks) lastResult = await sendText({
|
|
396
|
+
...ctx,
|
|
397
|
+
text: chunk,
|
|
398
|
+
replyToId: nextReplyToId()
|
|
399
|
+
});
|
|
394
400
|
return lastResult;
|
|
395
401
|
}
|
|
396
402
|
async function sendFeishuTtsSupplementPayload(params) {
|
|
@@ -416,15 +422,11 @@ async function sendFeishuTtsSupplementPayload(params) {
|
|
|
416
422
|
await ctx.onDeliveryResult?.(lastResult);
|
|
417
423
|
} else if (params.supplement.visibleTextAlreadyDelivered !== true) {
|
|
418
424
|
const text = params.payload.text?.trim() ? params.payload.text : params.supplement.spokenText;
|
|
419
|
-
for (const chunk of chunkFeishuMarkdown(text, FEISHU_TEXT_CHUNK_LIMIT)) {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
onDeliveryResult: void 0
|
|
425
|
-
});
|
|
426
|
-
await ctx.onDeliveryResult?.(lastResult);
|
|
427
|
-
}
|
|
425
|
+
for (const chunk of chunkFeishuMarkdown(text, FEISHU_TEXT_CHUNK_LIMIT)) lastResult = await sendText({
|
|
426
|
+
...ctx,
|
|
427
|
+
text: chunk,
|
|
428
|
+
replyToId: nextReplyToId()
|
|
429
|
+
});
|
|
428
430
|
}
|
|
429
431
|
for (const mediaUrl of normalizeStringEntries(resolvePayloadMediaUrls(params.payload))) lastResult = await sendMedia({
|
|
430
432
|
...ctx,
|
|
@@ -526,14 +528,14 @@ const feishuOutbound = {
|
|
|
526
528
|
replyToId,
|
|
527
529
|
threadId: ctx.threadId
|
|
528
530
|
});
|
|
529
|
-
return attachChannelToResult("feishu", await sendCardFeishu({
|
|
531
|
+
return attachChannelToResult("feishu", toFeishuOutboundResult(await sendCardFeishu({
|
|
530
532
|
cfg: ctx.cfg,
|
|
531
533
|
to: ctx.to,
|
|
532
534
|
card,
|
|
533
535
|
replyToMessageId,
|
|
534
536
|
replyInThread,
|
|
535
537
|
accountId: ctx.accountId ?? void 0
|
|
536
|
-
}));
|
|
538
|
+
})));
|
|
537
539
|
}
|
|
538
540
|
});
|
|
539
541
|
const { normalizedReplyToId } = resolveFeishuReplyMode({
|
|
@@ -550,11 +552,11 @@ const feishuOutbound = {
|
|
|
550
552
|
threadId: ctx.threadId
|
|
551
553
|
});
|
|
552
554
|
const mediaUrls = normalizeStringEntries(resolvePayloadMediaUrls(payload));
|
|
553
|
-
return attachChannelToResult("feishu", await sendPayloadMediaSequenceAndFinalize({
|
|
555
|
+
return attachChannelToResult("feishu", toFeishuOutboundResult(await sendPayloadMediaSequenceAndFinalize({
|
|
554
556
|
text: payload.text ?? "",
|
|
555
557
|
mediaUrls,
|
|
556
558
|
onResult: async (deliveryResult) => {
|
|
557
|
-
await ctx.onDeliveryResult?.(attachChannelToResult("feishu", deliveryResult));
|
|
559
|
+
await ctx.onDeliveryResult?.(attachChannelToResult("feishu", toFeishuOutboundResult(deliveryResult)));
|
|
558
560
|
},
|
|
559
561
|
send: async ({ mediaUrl }) => {
|
|
560
562
|
const { replyToMessageId, replyInThread } = nextReplyMode();
|
|
@@ -563,7 +565,9 @@ const feishuOutbound = {
|
|
|
563
565
|
to: ctx.to,
|
|
564
566
|
mediaUrl,
|
|
565
567
|
accountId: ctx.accountId ?? void 0,
|
|
568
|
+
mediaAccess: ctx.mediaAccess,
|
|
566
569
|
mediaLocalRoots: ctx.mediaLocalRoots,
|
|
570
|
+
mediaReadFile: ctx.mediaReadFile,
|
|
567
571
|
replyToMessageId,
|
|
568
572
|
replyInThread,
|
|
569
573
|
...payload.audioAsVoice === true || ctx.audioAsVoice === true ? { audioAsVoice: true } : {}
|
|
@@ -580,56 +584,70 @@ const feishuOutbound = {
|
|
|
580
584
|
accountId: ctx.accountId ?? void 0
|
|
581
585
|
});
|
|
582
586
|
}
|
|
583
|
-
}));
|
|
587
|
+
})));
|
|
584
588
|
},
|
|
585
589
|
...createAttachedChannelResultAdapter({
|
|
586
590
|
channel: "feishu",
|
|
587
|
-
sendText: async ({ cfg, to, text, accountId, replyToId, threadId, mediaLocalRoots, identity }) => {
|
|
591
|
+
sendText: async ({ cfg, to, text, accountId, replyToId, replyToIdSource, replyToMode, threadId, mediaAccess, mediaLocalRoots, mediaReadFile, identity, onDeliveryResult }) => {
|
|
588
592
|
const { replyToMessageId, replyInThread } = resolveFeishuReplyMode({
|
|
589
593
|
replyToId,
|
|
590
594
|
threadId
|
|
591
595
|
});
|
|
596
|
+
const deliveryOptions = {
|
|
597
|
+
replyToIdSource,
|
|
598
|
+
replyToMode,
|
|
599
|
+
onDeliveryResult
|
|
600
|
+
};
|
|
592
601
|
const localImagePath = normalizePossibleLocalImagePath(text);
|
|
593
|
-
if (localImagePath)
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
602
|
+
if (localImagePath) {
|
|
603
|
+
let mediaResult;
|
|
604
|
+
try {
|
|
605
|
+
mediaResult = await sendMediaFeishu({
|
|
606
|
+
cfg,
|
|
607
|
+
to,
|
|
608
|
+
mediaUrl: localImagePath,
|
|
609
|
+
accountId: accountId ?? void 0,
|
|
610
|
+
replyToMessageId,
|
|
611
|
+
replyInThread,
|
|
612
|
+
mediaAccess,
|
|
613
|
+
mediaLocalRoots,
|
|
614
|
+
mediaReadFile
|
|
615
|
+
});
|
|
616
|
+
} catch (err) {
|
|
617
|
+
if (isChannelPartialDeliveryError(err)) throw err;
|
|
618
|
+
console.error(`[feishu] local image path auto-send failed:`, err);
|
|
619
|
+
return toFeishuOutboundResult(await sendOutboundText({
|
|
620
|
+
cfg,
|
|
621
|
+
to,
|
|
622
|
+
text: await buildFeishuMediaFallbackText({}),
|
|
623
|
+
accountId: accountId ?? void 0,
|
|
624
|
+
replyToMessageId,
|
|
625
|
+
replyInThread,
|
|
626
|
+
...deliveryOptions
|
|
627
|
+
}));
|
|
628
|
+
}
|
|
629
|
+
return toFeishuOutboundResult(await reportFeishuOutboundDelivery(mediaResult, onDeliveryResult));
|
|
613
630
|
}
|
|
614
|
-
if (parseFeishuCommentTarget(to)) return await sendOutboundText({
|
|
631
|
+
if (parseFeishuCommentTarget(to)) return toFeishuOutboundResult(await sendOutboundText({
|
|
615
632
|
cfg,
|
|
616
633
|
to,
|
|
617
634
|
text,
|
|
618
635
|
accountId: accountId ?? void 0,
|
|
619
636
|
replyToMessageId,
|
|
620
|
-
replyInThread
|
|
621
|
-
|
|
637
|
+
replyInThread,
|
|
638
|
+
...deliveryOptions
|
|
639
|
+
}));
|
|
622
640
|
const card = readNativeFeishuCardJson(text);
|
|
623
641
|
if (card) {
|
|
624
642
|
assertFeishuCardWithinEnvelope(card, "Feishu native card");
|
|
625
|
-
return await sendCardFeishu({
|
|
643
|
+
return toFeishuOutboundResult(await reportFeishuOutboundDelivery(await sendCardFeishu({
|
|
626
644
|
cfg,
|
|
627
645
|
to,
|
|
628
646
|
card: markRenderedFeishuCard(card),
|
|
629
647
|
accountId: accountId ?? void 0,
|
|
630
648
|
replyToMessageId,
|
|
631
649
|
replyInThread
|
|
632
|
-
});
|
|
650
|
+
}), onDeliveryResult));
|
|
633
651
|
}
|
|
634
652
|
const renderMode = resolveFeishuAccount({
|
|
635
653
|
cfg,
|
|
@@ -640,7 +658,7 @@ const feishuOutbound = {
|
|
|
640
658
|
title: resolveFeishuIdentityHeaderTitle(identity),
|
|
641
659
|
template: "blue"
|
|
642
660
|
} : void 0;
|
|
643
|
-
return await sendStructuredCardFeishu({
|
|
661
|
+
return toFeishuOutboundResult(await reportFeishuOutboundDelivery(await sendStructuredCardFeishu({
|
|
644
662
|
cfg,
|
|
645
663
|
to,
|
|
646
664
|
text,
|
|
@@ -648,23 +666,44 @@ const feishuOutbound = {
|
|
|
648
666
|
replyInThread,
|
|
649
667
|
accountId: accountId ?? void 0,
|
|
650
668
|
header: header?.title ? header : void 0
|
|
651
|
-
});
|
|
669
|
+
}), onDeliveryResult));
|
|
652
670
|
}
|
|
653
|
-
return await sendOutboundText({
|
|
671
|
+
return toFeishuOutboundResult(await sendOutboundText({
|
|
654
672
|
cfg,
|
|
655
673
|
to,
|
|
656
674
|
text,
|
|
657
675
|
accountId: accountId ?? void 0,
|
|
658
676
|
replyToMessageId,
|
|
659
|
-
replyInThread
|
|
660
|
-
|
|
677
|
+
replyInThread,
|
|
678
|
+
...deliveryOptions
|
|
679
|
+
}));
|
|
661
680
|
},
|
|
662
|
-
sendMedia: async ({ cfg, to, text, mediaUrl, audioAsVoice, accountId, mediaLocalRoots, replyToId, threadId, onDeliveryResult }) => {
|
|
663
|
-
const {
|
|
681
|
+
sendMedia: async ({ cfg, to, text, mediaUrl, audioAsVoice, accountId, mediaAccess, mediaLocalRoots, mediaReadFile, replyToId, replyToIdSource, replyToMode, threadId, onDeliveryResult }) => {
|
|
682
|
+
const { normalizedReplyToId } = resolveFeishuReplyMode({
|
|
664
683
|
replyToId,
|
|
665
684
|
threadId
|
|
666
685
|
});
|
|
667
|
-
|
|
686
|
+
const nextReplyToId = createReplyToFanout({
|
|
687
|
+
replyToId: normalizedReplyToId,
|
|
688
|
+
replyToIdSource,
|
|
689
|
+
replyToMode
|
|
690
|
+
});
|
|
691
|
+
const nextReplyMode = () => {
|
|
692
|
+
const { replyToMessageId, replyInThread } = resolveFeishuReplyMode({
|
|
693
|
+
replyToId: nextReplyToId(),
|
|
694
|
+
threadId
|
|
695
|
+
});
|
|
696
|
+
return {
|
|
697
|
+
replyToMessageId,
|
|
698
|
+
replyInThread
|
|
699
|
+
};
|
|
700
|
+
};
|
|
701
|
+
const deliveryOptions = {
|
|
702
|
+
replyToIdSource,
|
|
703
|
+
replyToMode,
|
|
704
|
+
onDeliveryResult
|
|
705
|
+
};
|
|
706
|
+
if (parseFeishuCommentTarget(to)) return toFeishuOutboundResult(await sendOutboundText({
|
|
668
707
|
cfg,
|
|
669
708
|
to,
|
|
670
709
|
text: mediaUrl?.trim() ? await buildFeishuMediaFallbackText({
|
|
@@ -673,77 +712,72 @@ const feishuOutbound = {
|
|
|
673
712
|
mediaLinkStyle: "plain"
|
|
674
713
|
}) : text?.trim() ?? "",
|
|
675
714
|
accountId: accountId ?? void 0,
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
});
|
|
679
|
-
|
|
715
|
+
...nextReplyMode(),
|
|
716
|
+
...deliveryOptions
|
|
717
|
+
}));
|
|
718
|
+
if (!mediaUrl) return toFeishuOutboundResult(await sendOutboundText({
|
|
719
|
+
cfg,
|
|
720
|
+
to,
|
|
721
|
+
text: text ?? "",
|
|
722
|
+
accountId: accountId ?? void 0,
|
|
723
|
+
...nextReplyMode(),
|
|
724
|
+
...deliveryOptions
|
|
725
|
+
}));
|
|
726
|
+
const suppressTextForVoiceMedia = shouldSuppressFeishuTextForVoiceMedia({
|
|
680
727
|
mediaUrl,
|
|
681
728
|
audioAsVoice
|
|
682
729
|
});
|
|
683
|
-
const reportDelivery = async (result) => {
|
|
684
|
-
await onDeliveryResult?.(attachChannelToResult("feishu", result));
|
|
685
|
-
};
|
|
686
730
|
let textSent = false;
|
|
687
731
|
if (text?.trim() && !suppressTextForVoiceMedia) {
|
|
688
|
-
|
|
732
|
+
await sendOutboundText({
|
|
689
733
|
cfg,
|
|
690
734
|
to,
|
|
691
735
|
text,
|
|
692
736
|
accountId: accountId ?? void 0,
|
|
693
|
-
|
|
694
|
-
|
|
737
|
+
...nextReplyMode(),
|
|
738
|
+
...deliveryOptions
|
|
695
739
|
});
|
|
696
740
|
textSent = true;
|
|
697
|
-
await reportDelivery(textResult);
|
|
698
741
|
}
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
cfg,
|
|
704
|
-
to,
|
|
705
|
-
mediaUrl,
|
|
706
|
-
accountId: accountId ?? void 0,
|
|
707
|
-
mediaLocalRoots,
|
|
708
|
-
replyToMessageId,
|
|
709
|
-
replyInThread,
|
|
710
|
-
...audioAsVoice === true ? { audioAsVoice: true } : {}
|
|
711
|
-
});
|
|
712
|
-
} catch (err) {
|
|
713
|
-
console.error(`[feishu] sendMediaFeishu failed:`, err);
|
|
714
|
-
const fallbackResult = await sendOutboundText({
|
|
715
|
-
cfg,
|
|
716
|
-
to,
|
|
717
|
-
text: await buildFeishuMediaFallbackText({
|
|
718
|
-
text: textSent ? void 0 : text,
|
|
719
|
-
mediaUrl
|
|
720
|
-
}),
|
|
721
|
-
accountId: accountId ?? void 0,
|
|
722
|
-
replyToMessageId,
|
|
723
|
-
replyInThread
|
|
724
|
-
});
|
|
725
|
-
await reportDelivery(fallbackResult);
|
|
726
|
-
return fallbackResult;
|
|
727
|
-
}
|
|
728
|
-
await onDeliveryResult?.(attachChannelToResult("feishu", mediaResult));
|
|
729
|
-
if (mediaResult.voiceIntentDegradedToFile && text?.trim()) await reportDelivery(await sendOutboundText({
|
|
742
|
+
let mediaResult;
|
|
743
|
+
const mediaReplyMode = nextReplyMode();
|
|
744
|
+
try {
|
|
745
|
+
mediaResult = await sendMediaFeishu({
|
|
730
746
|
cfg,
|
|
731
747
|
to,
|
|
732
|
-
|
|
748
|
+
mediaUrl,
|
|
733
749
|
accountId: accountId ?? void 0,
|
|
734
|
-
|
|
735
|
-
|
|
750
|
+
mediaAccess,
|
|
751
|
+
mediaLocalRoots,
|
|
752
|
+
mediaReadFile,
|
|
753
|
+
...mediaReplyMode,
|
|
754
|
+
...audioAsVoice === true ? { audioAsVoice: true } : {}
|
|
755
|
+
});
|
|
756
|
+
} catch (err) {
|
|
757
|
+
if (isChannelPartialDeliveryError(err)) throw err;
|
|
758
|
+
console.error(`[feishu] sendMediaFeishu failed:`, err);
|
|
759
|
+
return toFeishuOutboundResult(await sendOutboundText({
|
|
760
|
+
cfg,
|
|
761
|
+
to,
|
|
762
|
+
text: await buildFeishuMediaFallbackText({
|
|
763
|
+
text: textSent ? void 0 : text,
|
|
764
|
+
mediaUrl
|
|
765
|
+
}),
|
|
766
|
+
accountId: accountId ?? void 0,
|
|
767
|
+
...textSent ? nextReplyMode() : mediaReplyMode,
|
|
768
|
+
...deliveryOptions
|
|
736
769
|
}));
|
|
737
|
-
return mediaResult;
|
|
738
770
|
}
|
|
739
|
-
|
|
771
|
+
await reportFeishuOutboundDelivery(mediaResult, onDeliveryResult);
|
|
772
|
+
if (mediaResult.voiceIntentDegradedToFile && text?.trim()) await sendOutboundText({
|
|
740
773
|
cfg,
|
|
741
774
|
to,
|
|
742
|
-
text
|
|
775
|
+
text,
|
|
743
776
|
accountId: accountId ?? void 0,
|
|
744
|
-
|
|
745
|
-
|
|
777
|
+
...nextReplyMode(),
|
|
778
|
+
...deliveryOptions
|
|
746
779
|
});
|
|
780
|
+
return toFeishuOutboundResult(mediaResult);
|
|
747
781
|
}
|
|
748
782
|
})
|
|
749
783
|
};
|
|
@@ -847,20 +881,35 @@ async function removeReactionFeishu(params) {
|
|
|
847
881
|
*/
|
|
848
882
|
async function listReactionsFeishu(params) {
|
|
849
883
|
const { cfg, messageId, emojiType, accountId } = params;
|
|
850
|
-
const
|
|
884
|
+
const client = resolveConfiguredFeishuClient({
|
|
851
885
|
cfg,
|
|
852
886
|
accountId
|
|
853
|
-
}).im.messageReaction.list({
|
|
854
|
-
path: { message_id: messageId },
|
|
855
|
-
params: emojiType ? { reaction_type: emojiType } : void 0
|
|
856
887
|
});
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
888
|
+
const reactions = [];
|
|
889
|
+
const seenPageTokens = /* @__PURE__ */ new Set();
|
|
890
|
+
let pageToken;
|
|
891
|
+
while (true) {
|
|
892
|
+
const response = await client.im.messageReaction.list({
|
|
893
|
+
path: { message_id: messageId },
|
|
894
|
+
params: emojiType || pageToken ? {
|
|
895
|
+
...emojiType ? { reaction_type: emojiType } : {},
|
|
896
|
+
...pageToken ? { page_token: pageToken } : {}
|
|
897
|
+
} : void 0
|
|
898
|
+
});
|
|
899
|
+
assertFeishuReactionApiSuccess(response, "list reactions");
|
|
900
|
+
for (const item of response.data?.items ?? []) reactions.push({
|
|
901
|
+
reactionId: item.reaction_id ?? "",
|
|
902
|
+
emojiType: item.reaction_type?.emoji_type ?? "",
|
|
903
|
+
operatorType: item.operator?.operator_type === "app" ? "app" : item.operator?.operator_type === "user" ? "user" : "unknown",
|
|
904
|
+
operatorId: item.operator?.operator_id ?? ""
|
|
905
|
+
});
|
|
906
|
+
if (response.data?.has_more !== true) return reactions;
|
|
907
|
+
const nextPageToken = response.data.page_token?.trim();
|
|
908
|
+
if (!nextPageToken) throw new Error("Feishu reaction pagination is missing its next page token");
|
|
909
|
+
if (seenPageTokens.has(nextPageToken)) throw new Error("Feishu reaction pagination returned a repeated page token");
|
|
910
|
+
seenPageTokens.add(nextPageToken);
|
|
911
|
+
pageToken = nextPageToken;
|
|
912
|
+
}
|
|
864
913
|
}
|
|
865
914
|
//#endregion
|
|
866
915
|
//#region extensions/feishu/src/channel.runtime.ts
|
|
@@ -33,6 +33,7 @@ var client_exports = /* @__PURE__ */ __exportAll({
|
|
|
33
33
|
getFeishuUserAgent: () => getFeishuUserAgent
|
|
34
34
|
});
|
|
35
35
|
const FEISHU_USER_AGENT = `openclaw-feishu-builtin/${readPluginPackageVersion({ require: createRequire(import.meta.url) })}/${process.platform}`;
|
|
36
|
+
const FEISHU_SDK_ORIGIN = "https://open.feishu.cn";
|
|
36
37
|
const FEISHU_WS_CONFIG = { pingTimeout: 3 };
|
|
37
38
|
/** User-Agent header value for all Feishu API requests. */
|
|
38
39
|
function getFeishuUserAgent() {
|
|
@@ -145,10 +146,8 @@ async function getFeishuProxyAgent() {
|
|
|
145
146
|
}
|
|
146
147
|
}
|
|
147
148
|
const clientCache = /* @__PURE__ */ new Map();
|
|
148
|
-
function
|
|
149
|
-
|
|
150
|
-
if (domain === "feishu" || !domain) return feishuClientSdk.Domain.Feishu;
|
|
151
|
-
return domain.replace(/\/+$/, "");
|
|
149
|
+
function resolveSdkDomain(domain) {
|
|
150
|
+
return domain === "lark" ? feishuClientSdk.Domain.Lark : feishuClientSdk.Domain.Feishu;
|
|
152
151
|
}
|
|
153
152
|
/**
|
|
154
153
|
* Create an HTTP instance that delegates to the Lark SDK's default instance
|
|
@@ -156,13 +155,25 @@ function resolveDomain(domain) {
|
|
|
156
155
|
* indefinite hangs, set a standardized User-Agent per OAPI best practices, and
|
|
157
156
|
* keep axios from taking a separate ambient proxy path for HTTPS requests.
|
|
158
157
|
*/
|
|
159
|
-
function createFeishuHttpInstance(defaultTimeoutMs) {
|
|
158
|
+
function createFeishuHttpInstance(defaultTimeoutMs, configuredDomain) {
|
|
160
159
|
const base = feishuClientSdk.defaultHttpInstance;
|
|
160
|
+
const customDomain = configuredDomain && configuredDomain !== "feishu" && configuredDomain !== "lark" ? new URL(configuredDomain) : void 0;
|
|
161
|
+
function resolveRequestUrl(url) {
|
|
162
|
+
if (!customDomain) return url;
|
|
163
|
+
const requestUrl = new URL(url);
|
|
164
|
+
if (requestUrl.origin !== FEISHU_SDK_ORIGIN) return url;
|
|
165
|
+
const destination = new URL(customDomain);
|
|
166
|
+
destination.pathname = `${destination.pathname.replace(/\/+$/, "")}${requestUrl.pathname}`;
|
|
167
|
+
destination.search = requestUrl.search;
|
|
168
|
+
destination.hash = requestUrl.hash;
|
|
169
|
+
return destination.toString();
|
|
170
|
+
}
|
|
161
171
|
async function injectRequestOptions(opts) {
|
|
162
172
|
const next = {
|
|
163
173
|
timeout: defaultTimeoutMs,
|
|
164
174
|
...opts
|
|
165
175
|
};
|
|
176
|
+
if (typeof next.url === "string") next.url = resolveRequestUrl(next.url);
|
|
166
177
|
const agent = await getFeishuProxyAgent();
|
|
167
178
|
if (agent) {
|
|
168
179
|
if (isManagedProxyActive()) {
|
|
@@ -178,13 +189,13 @@ function createFeishuHttpInstance(defaultTimeoutMs) {
|
|
|
178
189
|
}
|
|
179
190
|
return {
|
|
180
191
|
request: async (opts) => base.request(await injectRequestOptions(normalizeMultipartUploadData(opts))),
|
|
181
|
-
get: async (url, opts) => base.get(url, await injectRequestOptions(opts)),
|
|
182
|
-
post: async (url, data, opts) => base.post(url, data, await injectRequestOptions(opts)),
|
|
183
|
-
put: async (url, data, opts) => base.put(url, data, await injectRequestOptions(opts)),
|
|
184
|
-
patch: async (url, data, opts) => base.patch(url, data, await injectRequestOptions(opts)),
|
|
185
|
-
delete: async (url, opts) => base.delete(url, await injectRequestOptions(opts)),
|
|
186
|
-
head: async (url, opts) => base.head(url, await injectRequestOptions(opts)),
|
|
187
|
-
options: async (url, opts) => base.options(url, await injectRequestOptions(opts))
|
|
192
|
+
get: async (url, opts) => base.get(resolveRequestUrl(url), await injectRequestOptions(opts)),
|
|
193
|
+
post: async (url, data, opts) => base.post(resolveRequestUrl(url), data, await injectRequestOptions(opts)),
|
|
194
|
+
put: async (url, data, opts) => base.put(resolveRequestUrl(url), data, await injectRequestOptions(opts)),
|
|
195
|
+
patch: async (url, data, opts) => base.patch(resolveRequestUrl(url), data, await injectRequestOptions(opts)),
|
|
196
|
+
delete: async (url, opts) => base.delete(resolveRequestUrl(url), await injectRequestOptions(opts)),
|
|
197
|
+
head: async (url, opts) => base.head(resolveRequestUrl(url), await injectRequestOptions(opts)),
|
|
198
|
+
options: async (url, opts) => base.options(resolveRequestUrl(url), await injectRequestOptions(opts))
|
|
188
199
|
};
|
|
189
200
|
}
|
|
190
201
|
/**
|
|
@@ -201,8 +212,8 @@ function createFeishuClient(creds) {
|
|
|
201
212
|
appId,
|
|
202
213
|
appSecret,
|
|
203
214
|
appType: feishuClientSdk.AppType.SelfBuild,
|
|
204
|
-
domain:
|
|
205
|
-
httpInstance: createFeishuHttpInstance(defaultHttpTimeoutMs)
|
|
215
|
+
domain: resolveSdkDomain(domain),
|
|
216
|
+
httpInstance: createFeishuHttpInstance(defaultHttpTimeoutMs, domain)
|
|
206
217
|
});
|
|
207
218
|
clientCache.set(accountId, {
|
|
208
219
|
client,
|
|
@@ -227,8 +238,8 @@ async function createFeishuWSClient(account, callbacks = {}) {
|
|
|
227
238
|
return new feishuClientSdk.WSClient({
|
|
228
239
|
appId,
|
|
229
240
|
appSecret,
|
|
230
|
-
domain:
|
|
231
|
-
httpInstance: createFeishuHttpInstance(defaultHttpTimeoutMs),
|
|
241
|
+
domain: resolveSdkDomain(domain),
|
|
242
|
+
httpInstance: createFeishuHttpInstance(defaultHttpTimeoutMs, domain),
|
|
232
243
|
...callbacks,
|
|
233
244
|
loggerLevel: feishuClientSdk.LoggerLevel.info,
|
|
234
245
|
wsConfig: FEISHU_WS_CONFIG,
|
package/dist/contract-api.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as parseFeishuTargetId, i as parseFeishuDirectConversationId, r as parseFeishuConversationId, t as buildFeishuConversationId } from "./conversation-id-
|
|
2
|
-
import { t as messageActionTargetAliases } from "./security-audit-
|
|
1
|
+
import { a as parseFeishuTargetId, i as parseFeishuDirectConversationId, r as parseFeishuConversationId, t as buildFeishuConversationId } from "./conversation-id-VYgGQ-GX.js";
|
|
2
|
+
import { t as messageActionTargetAliases } from "./security-audit-D6Fz2h6p.js";
|
|
3
3
|
import { t as collectFeishuSecurityAuditFindings } from "./security-audit-shared-BgpY7AiJ.js";
|
|
4
4
|
export { buildFeishuConversationId, collectFeishuSecurityAuditFindings, messageActionTargetAliases, parseFeishuConversationId, parseFeishuDirectConversationId, parseFeishuTargetId };
|