@openclaw/feishu 2026.5.9-beta.1 → 2026.5.10-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 +1 -1
- package/dist/{channel-C5kY2KFE.js → channel-DCSECj4a.js} +29 -7
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-BK6_CcZk.js → channel.runtime-BlDkd6xR.js} +31 -13
- package/dist/{monitor-YkqtEXDP.js → monitor-BnbCJWIU.js} +1 -1
- package/dist/{monitor.account-BRSlHEbU.js → monitor.account-88yMtLAU.js} +108 -100
- package/dist/policy-DrLgxWF_.js +181 -0
- package/dist/setup-api.js +1 -1
- package/package.json +5 -5
- package/dist/policy-D6c-wMPl.js +0 -118
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-DCSECj4a.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";
|
|
@@ -4,7 +4,7 @@ import { a as resolveDefaultFeishuAccountId, f as isRecord$1, i as listFeishuAcc
|
|
|
4
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
|
-
import {
|
|
7
|
+
import { o as resolveFeishuGroupToolPolicy } from "./policy-DrLgxWF_.js";
|
|
8
8
|
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-Dm4Z_zQN.js";
|
|
9
9
|
import { t as collectFeishuSecurityAuditFindings } from "./security-audit-shared-ByuMx9cJ.js";
|
|
10
10
|
import { t as resolveFeishuSessionConversation } from "./session-conversation-B4nrW-vo.js";
|
|
@@ -811,7 +811,7 @@ const meta = {
|
|
|
811
811
|
aliases: ["lark"],
|
|
812
812
|
order: 70
|
|
813
813
|
};
|
|
814
|
-
const loadFeishuChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-
|
|
814
|
+
const loadFeishuChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-BlDkd6xR.js"), "feishuChannelRuntime");
|
|
815
815
|
function toFeishuMessageSendResult(result, kind) {
|
|
816
816
|
const receipt = result.receipt ?? createFeishuSendReceipt({
|
|
817
817
|
messageId: result.messageId,
|
|
@@ -957,6 +957,28 @@ function areAnyFeishuReactionActionsEnabled(cfg) {
|
|
|
957
957
|
})) return true;
|
|
958
958
|
return false;
|
|
959
959
|
}
|
|
960
|
+
function isFeishuGroupTopicSessionKey(sessionKey) {
|
|
961
|
+
if (typeof sessionKey !== "string" || !sessionKey) return false;
|
|
962
|
+
const parsed = parseFeishuConversationId({ conversationId: sessionKey });
|
|
963
|
+
return parsed?.scope === "group_topic" || parsed?.scope === "group_topic_sender";
|
|
964
|
+
}
|
|
965
|
+
function resolveFeishuTopicAutoThreadAnchor(ctx) {
|
|
966
|
+
if (ctx.action !== "send") return;
|
|
967
|
+
if (!isFeishuGroupTopicSessionKey(ctx.sessionKey)) return;
|
|
968
|
+
const inbound = ctx.toolContext?.currentMessageId;
|
|
969
|
+
return typeof inbound === "string" && inbound.length > 0 ? inbound : void 0;
|
|
970
|
+
}
|
|
971
|
+
function buildFeishuSendReplyAnchor(ctx) {
|
|
972
|
+
if (ctx.action === "thread-reply") return {
|
|
973
|
+
replyToMessageId: resolveFeishuMessageId(ctx.params),
|
|
974
|
+
replyInThread: true
|
|
975
|
+
};
|
|
976
|
+
const autoThreadId = resolveFeishuTopicAutoThreadAnchor(ctx);
|
|
977
|
+
return {
|
|
978
|
+
replyToMessageId: autoThreadId,
|
|
979
|
+
replyInThread: autoThreadId !== void 0
|
|
980
|
+
};
|
|
981
|
+
}
|
|
960
982
|
function isSupportedFeishuDirectConversationId(conversationId) {
|
|
961
983
|
const trimmed = conversationId.trim();
|
|
962
984
|
if (!trimmed || trimmed.includes(":")) return false;
|
|
@@ -1213,7 +1235,7 @@ const feishuPlugin = createChatChannelPlugin({
|
|
|
1213
1235
|
if (ctx.action === "send" || ctx.action === "thread-reply") {
|
|
1214
1236
|
const to = resolveFeishuActionTarget(ctx);
|
|
1215
1237
|
if (!to) throw new Error(`Feishu ${ctx.action} requires a target (to).`);
|
|
1216
|
-
const replyToMessageId
|
|
1238
|
+
const { replyToMessageId, replyInThread } = buildFeishuSendReplyAnchor(ctx);
|
|
1217
1239
|
if (ctx.action === "thread-reply" && !replyToMessageId) throw new Error("Feishu thread-reply requires messageId.");
|
|
1218
1240
|
const presentation = normalizeMessagePresentation(ctx.params.presentation);
|
|
1219
1241
|
const text = readFirstString(ctx.params, ["text", "message"]);
|
|
@@ -1238,7 +1260,7 @@ const feishuPlugin = createChatChannelPlugin({
|
|
|
1238
1260
|
card,
|
|
1239
1261
|
accountId: ctx.accountId ?? void 0,
|
|
1240
1262
|
replyToMessageId,
|
|
1241
|
-
replyInThread
|
|
1263
|
+
replyInThread
|
|
1242
1264
|
});
|
|
1243
1265
|
} else if (mediaUrl) result = await sendMedia({
|
|
1244
1266
|
cfg: ctx.cfg,
|
|
@@ -1247,7 +1269,7 @@ const feishuPlugin = createChatChannelPlugin({
|
|
|
1247
1269
|
mediaUrl,
|
|
1248
1270
|
accountId: ctx.accountId ?? void 0,
|
|
1249
1271
|
mediaLocalRoots: ctx.mediaLocalRoots,
|
|
1250
|
-
replyToId: replyToMessageId,
|
|
1272
|
+
...replyInThread ? { threadId: replyToMessageId } : { replyToId: replyToMessageId },
|
|
1251
1273
|
...audioAsVoice === true ? { audioAsVoice: true } : {}
|
|
1252
1274
|
});
|
|
1253
1275
|
else result = await runtime.sendMessageFeishu({
|
|
@@ -1256,7 +1278,7 @@ const feishuPlugin = createChatChannelPlugin({
|
|
|
1256
1278
|
text,
|
|
1257
1279
|
accountId: ctx.accountId ?? void 0,
|
|
1258
1280
|
replyToMessageId,
|
|
1259
|
-
replyInThread
|
|
1281
|
+
replyInThread
|
|
1260
1282
|
});
|
|
1261
1283
|
return jsonActionResult({
|
|
1262
1284
|
ok: true,
|
|
@@ -1632,7 +1654,7 @@ const feishuPlugin = createChatChannelPlugin({
|
|
|
1632
1654
|
})
|
|
1633
1655
|
}),
|
|
1634
1656
|
gateway: { startAccount: async (ctx) => {
|
|
1635
|
-
const { monitorFeishuProvider } = await import("./monitor-
|
|
1657
|
+
const { monitorFeishuProvider } = await import("./monitor-BnbCJWIU.js");
|
|
1636
1658
|
const account = resolveFeishuRuntimeAccount({
|
|
1637
1659
|
cfg: ctx.cfg,
|
|
1638
1660
|
accountId: ctx.accountId
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as feishuPlugin } from "./channel-
|
|
1
|
+
import { t as feishuPlugin } from "./channel-DCSECj4a.js";
|
|
2
2
|
export { feishuPlugin };
|
|
@@ -313,6 +313,13 @@ function resolveReplyToMessageId(params) {
|
|
|
313
313
|
if (params.threadId == null) return;
|
|
314
314
|
return String(params.threadId).trim() || void 0;
|
|
315
315
|
}
|
|
316
|
+
function resolveFeishuMediaReplyMode(params) {
|
|
317
|
+
const trimmedReplyToId = params.replyToId?.trim() || void 0;
|
|
318
|
+
return {
|
|
319
|
+
replyToMessageId: resolveReplyToMessageId(params),
|
|
320
|
+
replyInThread: params.threadId != null && !trimmedReplyToId
|
|
321
|
+
};
|
|
322
|
+
}
|
|
316
323
|
async function sendCommentThreadReply(params) {
|
|
317
324
|
const target = parseFeishuCommentTarget(params.to);
|
|
318
325
|
if (!target) return null;
|
|
@@ -345,7 +352,7 @@ async function sendCommentThreadReply(params) {
|
|
|
345
352
|
}
|
|
346
353
|
}
|
|
347
354
|
async function sendOutboundText(params) {
|
|
348
|
-
const { cfg, to, text, accountId, replyToMessageId } = params;
|
|
355
|
+
const { cfg, to, text, accountId, replyToMessageId, replyInThread } = params;
|
|
349
356
|
const commentResult = await sendCommentThreadReply({
|
|
350
357
|
cfg,
|
|
351
358
|
to,
|
|
@@ -363,14 +370,16 @@ async function sendOutboundText(params) {
|
|
|
363
370
|
to,
|
|
364
371
|
text,
|
|
365
372
|
accountId,
|
|
366
|
-
replyToMessageId
|
|
373
|
+
replyToMessageId,
|
|
374
|
+
replyInThread
|
|
367
375
|
});
|
|
368
376
|
return sendMessageFeishu({
|
|
369
377
|
cfg,
|
|
370
378
|
to,
|
|
371
379
|
text,
|
|
372
380
|
accountId,
|
|
373
|
-
replyToMessageId
|
|
381
|
+
replyToMessageId,
|
|
382
|
+
replyInThread
|
|
374
383
|
});
|
|
375
384
|
}
|
|
376
385
|
const feishuOutbound = {
|
|
@@ -447,7 +456,7 @@ const feishuOutbound = {
|
|
|
447
456
|
...createAttachedChannelResultAdapter({
|
|
448
457
|
channel: "feishu",
|
|
449
458
|
sendText: async ({ cfg, to, text, accountId, replyToId, threadId, mediaLocalRoots, identity }) => {
|
|
450
|
-
const replyToMessageId =
|
|
459
|
+
const { replyToMessageId, replyInThread } = resolveFeishuMediaReplyMode({
|
|
451
460
|
replyToId,
|
|
452
461
|
threadId
|
|
453
462
|
});
|
|
@@ -459,6 +468,7 @@ const feishuOutbound = {
|
|
|
459
468
|
mediaUrl: localImagePath,
|
|
460
469
|
accountId: accountId ?? void 0,
|
|
461
470
|
replyToMessageId,
|
|
471
|
+
replyInThread,
|
|
462
472
|
mediaLocalRoots
|
|
463
473
|
});
|
|
464
474
|
} catch (err) {
|
|
@@ -469,7 +479,8 @@ const feishuOutbound = {
|
|
|
469
479
|
to,
|
|
470
480
|
text,
|
|
471
481
|
accountId: accountId ?? void 0,
|
|
472
|
-
replyToMessageId
|
|
482
|
+
replyToMessageId,
|
|
483
|
+
replyInThread
|
|
473
484
|
});
|
|
474
485
|
const renderMode = resolveFeishuAccount({
|
|
475
486
|
cfg,
|
|
@@ -485,7 +496,7 @@ const feishuOutbound = {
|
|
|
485
496
|
to,
|
|
486
497
|
text,
|
|
487
498
|
replyToMessageId,
|
|
488
|
-
replyInThread
|
|
499
|
+
replyInThread,
|
|
489
500
|
accountId: accountId ?? void 0,
|
|
490
501
|
header: header?.title ? header : void 0
|
|
491
502
|
});
|
|
@@ -495,11 +506,12 @@ const feishuOutbound = {
|
|
|
495
506
|
to,
|
|
496
507
|
text,
|
|
497
508
|
accountId: accountId ?? void 0,
|
|
498
|
-
replyToMessageId
|
|
509
|
+
replyToMessageId,
|
|
510
|
+
replyInThread
|
|
499
511
|
});
|
|
500
512
|
},
|
|
501
513
|
sendMedia: async ({ cfg, to, text, mediaUrl, audioAsVoice, accountId, mediaLocalRoots, replyToId, threadId }) => {
|
|
502
|
-
const replyToMessageId =
|
|
514
|
+
const { replyToMessageId, replyInThread } = resolveFeishuMediaReplyMode({
|
|
503
515
|
replyToId,
|
|
504
516
|
threadId
|
|
505
517
|
});
|
|
@@ -508,7 +520,8 @@ const feishuOutbound = {
|
|
|
508
520
|
to,
|
|
509
521
|
text: [text?.trim(), mediaUrl?.trim()].filter(Boolean).join("\n\n") || mediaUrl || text || "",
|
|
510
522
|
accountId: accountId ?? void 0,
|
|
511
|
-
replyToMessageId
|
|
523
|
+
replyToMessageId,
|
|
524
|
+
replyInThread
|
|
512
525
|
});
|
|
513
526
|
const suppressTextForVoiceMedia = mediaUrl !== void 0 && shouldSuppressFeishuTextForVoiceMedia({
|
|
514
527
|
mediaUrl,
|
|
@@ -519,7 +532,8 @@ const feishuOutbound = {
|
|
|
519
532
|
to,
|
|
520
533
|
text,
|
|
521
534
|
accountId: accountId ?? void 0,
|
|
522
|
-
replyToMessageId
|
|
535
|
+
replyToMessageId,
|
|
536
|
+
replyInThread
|
|
523
537
|
});
|
|
524
538
|
if (mediaUrl) try {
|
|
525
539
|
const result = await sendMediaFeishu({
|
|
@@ -529,6 +543,7 @@ const feishuOutbound = {
|
|
|
529
543
|
accountId: accountId ?? void 0,
|
|
530
544
|
mediaLocalRoots,
|
|
531
545
|
replyToMessageId,
|
|
546
|
+
replyInThread,
|
|
532
547
|
...audioAsVoice === true ? { audioAsVoice: true } : {}
|
|
533
548
|
});
|
|
534
549
|
if (result.voiceIntentDegradedToFile && text?.trim()) await sendOutboundText({
|
|
@@ -536,7 +551,8 @@ const feishuOutbound = {
|
|
|
536
551
|
to,
|
|
537
552
|
text,
|
|
538
553
|
accountId: accountId ?? void 0,
|
|
539
|
-
replyToMessageId
|
|
554
|
+
replyToMessageId,
|
|
555
|
+
replyInThread
|
|
540
556
|
});
|
|
541
557
|
return result;
|
|
542
558
|
} catch (err) {
|
|
@@ -546,7 +562,8 @@ const feishuOutbound = {
|
|
|
546
562
|
to,
|
|
547
563
|
text: [text?.trim(), `📎 ${mediaUrl}`].filter(Boolean).join("\n\n"),
|
|
548
564
|
accountId: accountId ?? void 0,
|
|
549
|
-
replyToMessageId
|
|
565
|
+
replyToMessageId,
|
|
566
|
+
replyInThread
|
|
550
567
|
});
|
|
551
568
|
}
|
|
552
569
|
return await sendOutboundText({
|
|
@@ -554,7 +571,8 @@ const feishuOutbound = {
|
|
|
554
571
|
to,
|
|
555
572
|
text: text ?? "",
|
|
556
573
|
accountId: accountId ?? void 0,
|
|
557
|
-
replyToMessageId
|
|
574
|
+
replyToMessageId,
|
|
575
|
+
replyInThread
|
|
558
576
|
});
|
|
559
577
|
}
|
|
560
578
|
})
|
|
@@ -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-88yMtLAU.js");
|
|
7
7
|
return await monitorAccountRuntimePromise;
|
|
8
8
|
}
|
|
9
9
|
async function monitorFeishuProvider(opts = {}) {
|
|
@@ -3,11 +3,11 @@ 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
5
|
import { c as decodeFeishuCardAction, o as buildFeishuCardActionTextFallback, s as createFeishuCardInteractionEnvelope } from "./send-result-BVFTskB_.js";
|
|
6
|
-
import { i as
|
|
6
|
+
import { a as resolveFeishuGroupSenderActivationIngressAccess, i as resolveFeishuGroupConversationIngressAccess, n as resolveFeishuDmIngressAccess, r as resolveFeishuGroupConfig, s as resolveFeishuReplyPolicy, t as hasExplicitFeishuGroupConfig } from "./policy-DrLgxWF_.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,
|
|
10
|
+
import { buildAgentMediaPayload, createReplyPrefixContext, evaluateSupplementalContextVisibility, loadSessionStore, normalizeAgentId as normalizeAgentId$1, resolveChannelContextVisibilityMode, resolveSessionStoreEntry } from "./runtime-api.js";
|
|
11
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";
|
|
@@ -25,7 +25,7 @@ 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 {
|
|
28
|
+
import { safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
|
|
29
29
|
import * as crypto$1 from "node:crypto";
|
|
30
30
|
import crypto from "node:crypto";
|
|
31
31
|
import { resolveChannelConfigWrites } from "openclaw/plugin-sdk/channel-config-writes";
|
|
@@ -1746,42 +1746,37 @@ function buildFeishuAgentBody(params) {
|
|
|
1746
1746
|
}
|
|
1747
1747
|
return messageBody;
|
|
1748
1748
|
}
|
|
1749
|
-
function
|
|
1750
|
-
|
|
1751
|
-
if (params.senderType === "app") return true;
|
|
1749
|
+
async function shouldIncludeFetchedGroupContextMessage(params) {
|
|
1750
|
+
let senderAllowed = !params.isGroup || params.allowFrom.length === 0 || params.senderType === "app";
|
|
1752
1751
|
const senderId = params.senderId?.trim();
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
senderName: void 0
|
|
1758
|
-
});
|
|
1759
|
-
}
|
|
1760
|
-
function shouldIncludeFetchedGroupContextMessage(params) {
|
|
1761
|
-
const senderAllowed = isFetchedGroupContextSenderAllowed({
|
|
1762
|
-
isGroup: params.isGroup,
|
|
1752
|
+
if (!senderAllowed && senderId) senderAllowed = (await resolveFeishuGroupSenderActivationIngressAccess({
|
|
1753
|
+
cfg: params.cfg,
|
|
1754
|
+
accountId: params.accountId,
|
|
1755
|
+
chatId: params.chatId,
|
|
1763
1756
|
allowFrom: params.allowFrom,
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1757
|
+
senderOpenId: senderId,
|
|
1758
|
+
senderUserId: senderId,
|
|
1759
|
+
requireMention: false,
|
|
1760
|
+
mentionedBot: true
|
|
1761
|
+
})).senderAccess.decision === "allow";
|
|
1767
1762
|
return evaluateSupplementalContextVisibility({
|
|
1768
1763
|
mode: params.mode,
|
|
1769
1764
|
kind: params.kind,
|
|
1770
1765
|
senderAllowed
|
|
1771
1766
|
}).include;
|
|
1772
1767
|
}
|
|
1773
|
-
function filterFetchedGroupContextMessages(messages, params) {
|
|
1774
|
-
return
|
|
1775
|
-
|
|
1768
|
+
async function filterFetchedGroupContextMessages(messages, params) {
|
|
1769
|
+
return (await Promise.all(messages.map(async (message) => await shouldIncludeFetchedGroupContextMessage({
|
|
1770
|
+
cfg: params.cfg,
|
|
1771
|
+
accountId: params.accountId,
|
|
1772
|
+
chatId: params.chatId,
|
|
1773
|
+
isGroup: params.isGroup,
|
|
1774
|
+
allowFrom: params.allowFrom,
|
|
1776
1775
|
mode: params.mode,
|
|
1777
1776
|
kind: params.kind,
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
senderId: message.senderId,
|
|
1782
|
-
senderType: message.senderType
|
|
1783
|
-
})
|
|
1784
|
-
}).items;
|
|
1777
|
+
senderId: message.senderId,
|
|
1778
|
+
senderType: message.senderType
|
|
1779
|
+
}) ? message : void 0))).filter((message) => message !== void 0);
|
|
1785
1780
|
}
|
|
1786
1781
|
async function handleFeishuMessage(params) {
|
|
1787
1782
|
const { cfg, event, botOpenId, botName, runtime, chatHistories, accountId, processingClaimHeld = false } = params;
|
|
@@ -1902,7 +1897,6 @@ async function handleFeishuMessage(params) {
|
|
|
1902
1897
|
const groupHistoryKey = isGroup ? groupSession?.peerId ?? ctx.chatId : void 0;
|
|
1903
1898
|
const dmPolicy = feishuCfg?.dmPolicy ?? "pairing";
|
|
1904
1899
|
const configAllowFrom = feishuCfg?.allowFrom ?? [];
|
|
1905
|
-
const useAccessGroups = cfg.commands?.useAccessGroups !== false;
|
|
1906
1900
|
const rawBroadcastAgents = isGroup ? resolveBroadcastAgents(cfg, ctx.chatId) : null;
|
|
1907
1901
|
const broadcastAgents = rawBroadcastAgents ? [...new Set(rawBroadcastAgents.map((id) => normalizeAgentId$1(id)))] : null;
|
|
1908
1902
|
const messageCreateTimeMs = event.message.create_time ? Number.parseInt(event.message.create_time, 10) : Date.now();
|
|
@@ -1929,27 +1923,17 @@ async function handleFeishuMessage(params) {
|
|
|
1929
1923
|
cfg: feishuCfg,
|
|
1930
1924
|
groupId: ctx.chatId
|
|
1931
1925
|
});
|
|
1932
|
-
if (
|
|
1926
|
+
if ((await resolveFeishuGroupConversationIngressAccess({
|
|
1927
|
+
cfg,
|
|
1928
|
+
accountId: account.accountId,
|
|
1929
|
+
chatId: ctx.chatId,
|
|
1933
1930
|
groupPolicy,
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
})))) {
|
|
1931
|
+
groupAllowFrom,
|
|
1932
|
+
groupExplicitlyConfigured
|
|
1933
|
+
})).ingress.admission !== "dispatch") {
|
|
1938
1934
|
log(`feishu[${account.accountId}]: group ${ctx.chatId} not in groupAllowFrom (groupPolicy=${groupPolicy})`);
|
|
1939
1935
|
return;
|
|
1940
1936
|
}
|
|
1941
|
-
if (effectiveGroupSenderAllowFrom.length > 0) {
|
|
1942
|
-
if (!isFeishuGroupAllowed({
|
|
1943
|
-
groupPolicy: "allowlist",
|
|
1944
|
-
allowFrom: effectiveGroupSenderAllowFrom,
|
|
1945
|
-
senderId: ctx.senderOpenId,
|
|
1946
|
-
senderIds: [senderUserId],
|
|
1947
|
-
senderName: ctx.senderName
|
|
1948
|
-
})) {
|
|
1949
|
-
log(`feishu: sender ${ctx.senderOpenId} not in group ${ctx.chatId} sender allowlist`);
|
|
1950
|
-
return;
|
|
1951
|
-
}
|
|
1952
|
-
}
|
|
1953
1937
|
({requireMention} = resolveFeishuReplyPolicy({
|
|
1954
1938
|
isDirectMessage: false,
|
|
1955
1939
|
cfg,
|
|
@@ -1957,7 +1941,21 @@ async function handleFeishuMessage(params) {
|
|
|
1957
1941
|
groupId: ctx.chatId,
|
|
1958
1942
|
groupPolicy
|
|
1959
1943
|
}));
|
|
1960
|
-
|
|
1944
|
+
const groupSenderActivationIngress = await resolveFeishuGroupSenderActivationIngressAccess({
|
|
1945
|
+
cfg,
|
|
1946
|
+
accountId: account.accountId,
|
|
1947
|
+
chatId: ctx.chatId,
|
|
1948
|
+
allowFrom: effectiveGroupSenderAllowFrom,
|
|
1949
|
+
senderOpenId: ctx.senderOpenId,
|
|
1950
|
+
senderUserId,
|
|
1951
|
+
requireMention,
|
|
1952
|
+
mentionedBot: ctx.mentionedBot
|
|
1953
|
+
});
|
|
1954
|
+
if (groupSenderActivationIngress.senderAccess.decision !== "allow") {
|
|
1955
|
+
log(`feishu: sender ${ctx.senderOpenId} not in group ${ctx.chatId} sender allowlist`);
|
|
1956
|
+
return;
|
|
1957
|
+
}
|
|
1958
|
+
if (groupSenderActivationIngress.ingress.admission !== "dispatch") {
|
|
1961
1959
|
log(`feishu[${account.accountId}]: message in group ${ctx.chatId} did not mention bot`);
|
|
1962
1960
|
if (!broadcastAgents && chatHistories && groupHistoryKey) recordPendingHistoryEntryIfEnabled({
|
|
1963
1961
|
historyMap: chatHistories,
|
|
@@ -1982,25 +1980,20 @@ async function handleFeishuMessage(params) {
|
|
|
1982
1980
|
});
|
|
1983
1981
|
const commandProbeBody = isGroup ? normalizeFeishuCommandProbeBody(ctx.content) : ctx.content;
|
|
1984
1982
|
const shouldComputeCommandAuthorized = core.channel.commands.shouldComputeCommandAuthorized(commandProbeBody, cfg);
|
|
1985
|
-
const
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
senderName: ctx.senderName
|
|
2000
|
-
}).allowed
|
|
2001
|
-
}).decision === "allow" : dmAllowed;
|
|
2002
|
-
if (isDirect && !dmAccessAllowed) {
|
|
2003
|
-
if (dmPolicy === "pairing") await pairing.issueChallenge({
|
|
1983
|
+
const dmIngress = isDirect ? await resolveFeishuDmIngressAccess({
|
|
1984
|
+
cfg,
|
|
1985
|
+
accountId: account.accountId,
|
|
1986
|
+
dmPolicy,
|
|
1987
|
+
allowFrom: configAllowFrom,
|
|
1988
|
+
readAllowFromStore: pairing.readAllowFromStore,
|
|
1989
|
+
senderOpenId: ctx.senderOpenId,
|
|
1990
|
+
senderUserId,
|
|
1991
|
+
conversationId: ctx.senderOpenId,
|
|
1992
|
+
mayPair: true,
|
|
1993
|
+
...shouldComputeCommandAuthorized ? { command: { hasControlCommand: true } } : {}
|
|
1994
|
+
}) : null;
|
|
1995
|
+
if (isDirect && dmIngress?.ingress.admission !== "dispatch") {
|
|
1996
|
+
if (dmIngress?.ingress.admission === "pairing-required") await pairing.issueChallenge({
|
|
2004
1997
|
senderId: ctx.senderOpenId,
|
|
2005
1998
|
senderIdLine: `Your Feishu user id: ${ctx.senderOpenId}`,
|
|
2006
1999
|
meta: { name: ctx.senderName },
|
|
@@ -2022,13 +2015,7 @@ async function handleFeishuMessage(params) {
|
|
|
2022
2015
|
else log(`feishu[${account.accountId}]: blocked unauthorized sender ${ctx.senderOpenId} (dmPolicy=${dmPolicy})`);
|
|
2023
2016
|
return;
|
|
2024
2017
|
}
|
|
2025
|
-
const commandAllowFrom = isGroup ? groupConfig?.allowFrom ?? configAllowFrom :
|
|
2026
|
-
const senderAllowedForCommands = resolveFeishuAllowlistMatch({
|
|
2027
|
-
allowFrom: commandAllowFrom,
|
|
2028
|
-
senderId: ctx.senderOpenId,
|
|
2029
|
-
senderIds: [senderUserId],
|
|
2030
|
-
senderName: ctx.senderName
|
|
2031
|
-
}).allowed;
|
|
2018
|
+
const commandAllowFrom = isGroup ? groupConfig?.allowFrom ?? configAllowFrom : dmIngress?.senderAccess.effectiveAllowFrom ?? configAllowFrom;
|
|
2032
2019
|
const feishuFrom = `feishu:${ctx.senderOpenId}`;
|
|
2033
2020
|
const feishuTo = isGroup ? `chat:${ctx.chatId}` : `user:${ctx.senderOpenId}`;
|
|
2034
2021
|
const peerId = isGroup ? groupSession?.peerId ?? ctx.chatId : ctx.senderOpenId;
|
|
@@ -2165,13 +2152,28 @@ async function handleFeishuMessage(params) {
|
|
|
2165
2152
|
content: audioTranscript
|
|
2166
2153
|
};
|
|
2167
2154
|
const effectiveCommandProbeBody = audioTranscript === void 0 ? commandProbeBody : isGroup ? normalizeFeishuCommandProbeBody(audioTranscript) : audioTranscript;
|
|
2168
|
-
const commandAuthorized = (audioTranscript === void 0 ? shouldComputeCommandAuthorized : core.channel.commands.shouldComputeCommandAuthorized(effectiveCommandProbeBody, cfg)) ?
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2155
|
+
const commandAuthorized = (audioTranscript === void 0 ? shouldComputeCommandAuthorized : core.channel.commands.shouldComputeCommandAuthorized(effectiveCommandProbeBody, cfg)) ? isDirect && audioTranscript === void 0 && dmIngress ? dmIngress.commandAccess.authorized : isGroup ? (await resolveFeishuGroupSenderActivationIngressAccess({
|
|
2156
|
+
cfg,
|
|
2157
|
+
accountId: account.accountId,
|
|
2158
|
+
chatId: ctx.chatId,
|
|
2159
|
+
allowFrom: commandAllowFrom,
|
|
2160
|
+
senderOpenId: ctx.senderOpenId,
|
|
2161
|
+
senderUserId,
|
|
2162
|
+
requireMention: false,
|
|
2163
|
+
mentionedBot: true,
|
|
2164
|
+
command: { hasControlCommand: true }
|
|
2165
|
+
})).commandAccess.authorized : (await resolveFeishuDmIngressAccess({
|
|
2166
|
+
cfg,
|
|
2167
|
+
accountId: account.accountId,
|
|
2168
|
+
dmPolicy,
|
|
2169
|
+
allowFrom: configAllowFrom,
|
|
2170
|
+
readAllowFromStore: pairing.readAllowFromStore,
|
|
2171
|
+
senderOpenId: ctx.senderOpenId,
|
|
2172
|
+
senderUserId,
|
|
2173
|
+
conversationId: ctx.senderOpenId,
|
|
2174
|
+
mayPair: false,
|
|
2175
|
+
command: { hasControlCommand: true }
|
|
2176
|
+
})).commandAccess.authorized : void 0;
|
|
2175
2177
|
let quotedMessageInfo = null;
|
|
2176
2178
|
let quotedContent;
|
|
2177
2179
|
if (ctx.parentId) try {
|
|
@@ -2180,7 +2182,10 @@ async function handleFeishuMessage(params) {
|
|
|
2180
2182
|
messageId: ctx.parentId,
|
|
2181
2183
|
accountId: account.accountId
|
|
2182
2184
|
});
|
|
2183
|
-
if (quotedMessageInfo && shouldIncludeFetchedGroupContextMessage({
|
|
2185
|
+
if (quotedMessageInfo && await shouldIncludeFetchedGroupContextMessage({
|
|
2186
|
+
cfg,
|
|
2187
|
+
accountId: account.accountId,
|
|
2188
|
+
chatId: ctx.chatId,
|
|
2184
2189
|
isGroup,
|
|
2185
2190
|
allowFrom: effectiveGroupSenderAllowFrom,
|
|
2186
2191
|
mode: contextVisibilityMode,
|
|
@@ -2250,7 +2255,10 @@ async function handleFeishuMessage(params) {
|
|
|
2250
2255
|
rootMessageInfo = null;
|
|
2251
2256
|
}
|
|
2252
2257
|
rootMessageThreadId = rootMessageInfo?.threadId;
|
|
2253
|
-
if (rootMessageInfo && !shouldIncludeFetchedGroupContextMessage({
|
|
2258
|
+
if (rootMessageInfo && !await shouldIncludeFetchedGroupContextMessage({
|
|
2259
|
+
cfg,
|
|
2260
|
+
accountId: account.accountId,
|
|
2261
|
+
chatId: ctx.chatId,
|
|
2254
2262
|
isGroup,
|
|
2255
2263
|
allowFrom: effectiveGroupSenderAllowFrom,
|
|
2256
2264
|
mode: contextVisibilityMode,
|
|
@@ -2310,7 +2318,10 @@ async function handleFeishuMessage(params) {
|
|
|
2310
2318
|
});
|
|
2311
2319
|
const senderScoped = groupSession?.groupSessionScope === "group_topic_sender";
|
|
2312
2320
|
const senderIds = new Set([ctx.senderOpenId, senderUserId].map((id) => id?.trim()).filter((id) => id !== void 0 && id.length > 0));
|
|
2313
|
-
const allowlistedMessages = filterFetchedGroupContextMessages(threadMessages, {
|
|
2321
|
+
const allowlistedMessages = await filterFetchedGroupContextMessages(threadMessages, {
|
|
2322
|
+
cfg,
|
|
2323
|
+
accountId: account.accountId,
|
|
2324
|
+
chatId: ctx.chatId,
|
|
2314
2325
|
isGroup,
|
|
2315
2326
|
allowFrom: effectiveGroupSenderAllowFrom,
|
|
2316
2327
|
mode: contextVisibilityMode,
|
|
@@ -3977,22 +3988,19 @@ async function handleFeishuCommentEvent(params) {
|
|
|
3977
3988
|
channel: "feishu",
|
|
3978
3989
|
accountId: account.accountId
|
|
3979
3990
|
});
|
|
3980
|
-
const
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
}).allowed
|
|
3994
|
-
}).decision === "allow" : senderAllowed)) {
|
|
3995
|
-
if (dmPolicy === "pairing") {
|
|
3991
|
+
const dmIngress = await resolveFeishuDmIngressAccess({
|
|
3992
|
+
cfg: params.cfg,
|
|
3993
|
+
accountId: account.accountId,
|
|
3994
|
+
dmPolicy,
|
|
3995
|
+
allowFrom: configAllowFrom,
|
|
3996
|
+
readAllowFromStore: pairing.readAllowFromStore,
|
|
3997
|
+
senderOpenId: turn.senderId,
|
|
3998
|
+
senderUserId: turn.senderUserId,
|
|
3999
|
+
conversationId: turn.senderId,
|
|
4000
|
+
mayPair: true
|
|
4001
|
+
});
|
|
4002
|
+
if (dmIngress.ingress.admission !== "dispatch") {
|
|
4003
|
+
if (dmIngress.ingress.admission === "pairing-required") {
|
|
3996
4004
|
const client = createFeishuClient(account);
|
|
3997
4005
|
await pairing.issueChallenge({
|
|
3998
4006
|
senderId: turn.senderId,
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { t as detectIdType } from "./targets-JMFJRKSe.js";
|
|
2
|
+
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime";
|
|
3
|
+
import { normalizeAccountId, resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution";
|
|
4
|
+
import { createChannelIngressResolver, defineStableChannelIngressIdentity } from "openclaw/plugin-sdk/channel-ingress-runtime";
|
|
5
|
+
//#region extensions/feishu/src/policy.ts
|
|
6
|
+
const FEISHU_PROVIDER_PREFIX_RE = /^(feishu|lark):/i;
|
|
7
|
+
const FEISHU_TYPED_PREFIX_RE = /^(chat|group|channel|user|dm|open_id):/i;
|
|
8
|
+
const FEISHU_ID_KIND = "plugin:feishu-id";
|
|
9
|
+
const feishuIngressIdentity = defineStableChannelIngressIdentity({
|
|
10
|
+
key: "feishu-id",
|
|
11
|
+
kind: FEISHU_ID_KIND,
|
|
12
|
+
normalize: normalizeFeishuAllowEntry,
|
|
13
|
+
sensitivity: "pii",
|
|
14
|
+
aliases: [{
|
|
15
|
+
key: "feishu-alt-id",
|
|
16
|
+
kind: FEISHU_ID_KIND,
|
|
17
|
+
normalizeEntry: () => null,
|
|
18
|
+
normalizeSubject: normalizeFeishuAllowEntry,
|
|
19
|
+
sensitivity: "pii"
|
|
20
|
+
}],
|
|
21
|
+
isWildcardEntry: (entry) => normalizeFeishuAllowEntry(entry) === "*",
|
|
22
|
+
resolveEntryId: ({ entryIndex }) => `feishu-entry-${entryIndex + 1}`
|
|
23
|
+
});
|
|
24
|
+
function normalizeFeishuAllowEntry(raw) {
|
|
25
|
+
const trimmed = raw.trim();
|
|
26
|
+
if (!trimmed) return "";
|
|
27
|
+
if (trimmed === "*") return "*";
|
|
28
|
+
let withoutProviderPrefix = trimmed;
|
|
29
|
+
while (FEISHU_PROVIDER_PREFIX_RE.test(withoutProviderPrefix)) withoutProviderPrefix = withoutProviderPrefix.replace(FEISHU_PROVIDER_PREFIX_RE, "").trim();
|
|
30
|
+
if (withoutProviderPrefix === "*") return "*";
|
|
31
|
+
const lowered = normalizeOptionalLowercaseString(withoutProviderPrefix) ?? "";
|
|
32
|
+
if (!lowered) return "";
|
|
33
|
+
const prefixed = lowered.match(FEISHU_TYPED_PREFIX_RE);
|
|
34
|
+
if (prefixed?.[1]) {
|
|
35
|
+
const kind = [
|
|
36
|
+
"chat",
|
|
37
|
+
"group",
|
|
38
|
+
"channel"
|
|
39
|
+
].includes(prefixed[1]) ? "chat" : "user";
|
|
40
|
+
const value = withoutProviderPrefix.slice(prefixed[0].length).trim();
|
|
41
|
+
return value === "*" ? "*" : value ? `${kind}:${value}` : "";
|
|
42
|
+
}
|
|
43
|
+
const detectedType = detectIdType(withoutProviderPrefix);
|
|
44
|
+
if (detectedType === "chat_id") return `chat:${withoutProviderPrefix}`;
|
|
45
|
+
if (detectedType === "open_id" || detectedType === "user_id") return `user:${withoutProviderPrefix}`;
|
|
46
|
+
return "";
|
|
47
|
+
}
|
|
48
|
+
function normalizeFeishuDmPolicy(policy) {
|
|
49
|
+
return policy === "open" || policy === "pairing" || policy === "allowlist" || policy === "disabled" ? policy : "pairing";
|
|
50
|
+
}
|
|
51
|
+
function normalizeFeishuGroupPolicy(policy) {
|
|
52
|
+
return policy === "allowall" ? "open" : policy;
|
|
53
|
+
}
|
|
54
|
+
function createFeishuIngressSubject(params) {
|
|
55
|
+
const ids = [params.primaryId, ...params.alternateIds ?? []].map((value) => value?.trim()).filter((value) => Boolean(value));
|
|
56
|
+
return {
|
|
57
|
+
stableId: ids[0],
|
|
58
|
+
aliases: { "feishu-alt-id": ids[1] }
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function createFeishuIngressResolver(params) {
|
|
62
|
+
return createChannelIngressResolver({
|
|
63
|
+
channelId: "feishu",
|
|
64
|
+
accountId: normalizeAccountId(params.accountId) ?? "default",
|
|
65
|
+
identity: feishuIngressIdentity,
|
|
66
|
+
cfg: params.cfg,
|
|
67
|
+
...params.readAllowFromStore ? { readStoreAllowFrom: params.readAllowFromStore } : {}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
async function resolveFeishuDmIngressAccess(params) {
|
|
71
|
+
return await createFeishuIngressResolver({
|
|
72
|
+
cfg: params.cfg,
|
|
73
|
+
accountId: params.accountId,
|
|
74
|
+
readAllowFromStore: params.readAllowFromStore
|
|
75
|
+
}).message({
|
|
76
|
+
subject: createFeishuIngressSubject({
|
|
77
|
+
primaryId: params.senderOpenId,
|
|
78
|
+
alternateIds: [params.senderUserId]
|
|
79
|
+
}),
|
|
80
|
+
conversation: {
|
|
81
|
+
kind: "direct",
|
|
82
|
+
id: params.conversationId
|
|
83
|
+
},
|
|
84
|
+
event: { mayPair: params.mayPair },
|
|
85
|
+
dmPolicy: normalizeFeishuDmPolicy(params.dmPolicy),
|
|
86
|
+
groupPolicy: "disabled",
|
|
87
|
+
allowFrom: params.allowFrom ?? [],
|
|
88
|
+
...params.command ? { command: params.command } : {}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
async function resolveFeishuGroupConversationIngressAccess(params) {
|
|
92
|
+
const groupPolicy = normalizeFeishuGroupPolicy(params.groupPolicy);
|
|
93
|
+
const groupAllowFrom = groupPolicy === "allowlist" && params.groupExplicitlyConfigured ? [...params.groupAllowFrom ?? [], params.chatId] : params.groupAllowFrom ?? [];
|
|
94
|
+
return await createFeishuIngressResolver({
|
|
95
|
+
cfg: params.cfg,
|
|
96
|
+
accountId: params.accountId
|
|
97
|
+
}).message({
|
|
98
|
+
subject: createFeishuIngressSubject({ primaryId: params.chatId }),
|
|
99
|
+
conversation: {
|
|
100
|
+
kind: "group",
|
|
101
|
+
id: params.chatId
|
|
102
|
+
},
|
|
103
|
+
dmPolicy: "disabled",
|
|
104
|
+
groupPolicy,
|
|
105
|
+
groupAllowFrom
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
async function resolveFeishuGroupSenderActivationIngressAccess(params) {
|
|
109
|
+
const groupAllowFrom = params.allowFrom ?? [];
|
|
110
|
+
return await createFeishuIngressResolver({
|
|
111
|
+
cfg: params.cfg,
|
|
112
|
+
accountId: params.accountId
|
|
113
|
+
}).message({
|
|
114
|
+
subject: createFeishuIngressSubject({
|
|
115
|
+
primaryId: params.senderOpenId,
|
|
116
|
+
alternateIds: [params.senderUserId]
|
|
117
|
+
}),
|
|
118
|
+
conversation: {
|
|
119
|
+
kind: "group",
|
|
120
|
+
id: params.chatId
|
|
121
|
+
},
|
|
122
|
+
dmPolicy: "disabled",
|
|
123
|
+
groupPolicy: groupAllowFrom.length > 0 ? "allowlist" : "open",
|
|
124
|
+
groupAllowFrom,
|
|
125
|
+
mentionFacts: {
|
|
126
|
+
canDetectMention: true,
|
|
127
|
+
wasMentioned: params.mentionedBot
|
|
128
|
+
},
|
|
129
|
+
policy: { activation: {
|
|
130
|
+
requireMention: params.requireMention,
|
|
131
|
+
allowTextCommands: false
|
|
132
|
+
} },
|
|
133
|
+
...params.command ? { command: params.command } : {}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function resolveFeishuGroupConfig(params) {
|
|
137
|
+
const groups = params.cfg?.groups ?? {};
|
|
138
|
+
const wildcard = groups["*"];
|
|
139
|
+
const groupId = params.groupId?.trim();
|
|
140
|
+
if (!groupId) return;
|
|
141
|
+
const direct = groups[groupId];
|
|
142
|
+
if (direct) return direct;
|
|
143
|
+
const lowered = normalizeOptionalLowercaseString(groupId) ?? "";
|
|
144
|
+
const matchKey = Object.keys(groups).find((key) => normalizeOptionalLowercaseString(key) === lowered);
|
|
145
|
+
if (matchKey) return groups[matchKey];
|
|
146
|
+
return wildcard;
|
|
147
|
+
}
|
|
148
|
+
function hasExplicitFeishuGroupConfig(params) {
|
|
149
|
+
const groups = params.cfg?.groups ?? {};
|
|
150
|
+
const groupId = params.groupId?.trim();
|
|
151
|
+
if (!groupId) return false;
|
|
152
|
+
if (Object.prototype.hasOwnProperty.call(groups, groupId) && groupId !== "*") return true;
|
|
153
|
+
const lowered = normalizeOptionalLowercaseString(groupId) ?? "";
|
|
154
|
+
return Object.keys(groups).some((key) => key !== "*" && normalizeOptionalLowercaseString(key) === lowered);
|
|
155
|
+
}
|
|
156
|
+
function resolveFeishuGroupToolPolicy(params) {
|
|
157
|
+
const cfg = params.cfg.channels?.feishu;
|
|
158
|
+
if (!cfg) return;
|
|
159
|
+
return resolveFeishuGroupConfig({
|
|
160
|
+
cfg,
|
|
161
|
+
groupId: params.groupId
|
|
162
|
+
})?.tools;
|
|
163
|
+
}
|
|
164
|
+
function resolveFeishuReplyPolicy(params) {
|
|
165
|
+
if (params.isDirectMessage) return { requireMention: false };
|
|
166
|
+
const feishuCfg = params.cfg.channels?.feishu;
|
|
167
|
+
const resolvedCfg = resolveMergedAccountConfig({
|
|
168
|
+
channelConfig: feishuCfg,
|
|
169
|
+
accounts: feishuCfg?.accounts,
|
|
170
|
+
accountId: normalizeAccountId(params.accountId),
|
|
171
|
+
normalizeAccountId,
|
|
172
|
+
omitKeys: ["defaultAccount"]
|
|
173
|
+
});
|
|
174
|
+
const groupRequireMention = resolveFeishuGroupConfig({
|
|
175
|
+
cfg: resolvedCfg,
|
|
176
|
+
groupId: params.groupId
|
|
177
|
+
})?.requireMention;
|
|
178
|
+
return { requireMention: typeof groupRequireMention === "boolean" ? groupRequireMention : typeof resolvedCfg.requireMention === "boolean" ? resolvedCfg.requireMention : params.groupPolicy !== "open" };
|
|
179
|
+
}
|
|
180
|
+
//#endregion
|
|
181
|
+
export { resolveFeishuGroupSenderActivationIngressAccess as a, resolveFeishuGroupConversationIngressAccess as i, resolveFeishuDmIngressAccess as n, resolveFeishuGroupToolPolicy as o, resolveFeishuGroupConfig as r, resolveFeishuReplyPolicy as s, hasExplicitFeishuGroupConfig 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-DCSECj4a.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.10-beta.1",
|
|
4
4
|
"description": "OpenClaw Feishu/Lark channel plugin (community maintained by @m1heng)",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@larksuiteoapi/node-sdk": "^1.
|
|
11
|
+
"@larksuiteoapi/node-sdk": "^1.63.1",
|
|
12
12
|
"typebox": "1.1.38"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"openclaw": "workspace:*"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
|
-
"openclaw": ">=2026.5.
|
|
19
|
+
"openclaw": ">=2026.5.10-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.10-beta.1"
|
|
51
51
|
},
|
|
52
52
|
"build": {
|
|
53
|
-
"openclawVersion": "2026.5.
|
|
53
|
+
"openclawVersion": "2026.5.10-beta.1"
|
|
54
54
|
},
|
|
55
55
|
"release": {
|
|
56
56
|
"publishToClawHub": true,
|
package/dist/policy-D6c-wMPl.js
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import { t as detectIdType } from "./targets-JMFJRKSe.js";
|
|
2
|
-
import { normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/text-runtime";
|
|
3
|
-
import { normalizeAccountId, resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution";
|
|
4
|
-
import { evaluateSenderGroupAccessForPolicy } from "openclaw/plugin-sdk/group-access";
|
|
5
|
-
//#region extensions/feishu/src/policy.ts
|
|
6
|
-
const FEISHU_PROVIDER_PREFIX_RE = /^(feishu|lark):/i;
|
|
7
|
-
function stripRepeatedFeishuProviderPrefixes(raw) {
|
|
8
|
-
let normalized = raw.trim();
|
|
9
|
-
while (FEISHU_PROVIDER_PREFIX_RE.test(normalized)) normalized = normalized.replace(FEISHU_PROVIDER_PREFIX_RE, "").trim();
|
|
10
|
-
return normalized;
|
|
11
|
-
}
|
|
12
|
-
function canonicalizeFeishuAllowlistKey(params) {
|
|
13
|
-
const value = params.value.trim();
|
|
14
|
-
if (!value) return "";
|
|
15
|
-
if (value === "*") return "*";
|
|
16
|
-
return `${params.kind}:${value}`;
|
|
17
|
-
}
|
|
18
|
-
function normalizeFeishuAllowEntry(raw) {
|
|
19
|
-
const trimmed = raw.trim();
|
|
20
|
-
if (!trimmed) return "";
|
|
21
|
-
if (trimmed === "*") return "*";
|
|
22
|
-
const withoutProviderPrefix = stripRepeatedFeishuProviderPrefixes(trimmed);
|
|
23
|
-
if (withoutProviderPrefix === "*") return "*";
|
|
24
|
-
const lowered = normalizeOptionalLowercaseString(withoutProviderPrefix) ?? "";
|
|
25
|
-
if (!lowered) return "";
|
|
26
|
-
if (lowered.startsWith("chat:") || lowered.startsWith("group:") || lowered.startsWith("channel:")) return canonicalizeFeishuAllowlistKey({
|
|
27
|
-
kind: "chat",
|
|
28
|
-
value: withoutProviderPrefix.slice(withoutProviderPrefix.indexOf(":") + 1)
|
|
29
|
-
});
|
|
30
|
-
if (lowered.startsWith("user:") || lowered.startsWith("dm:")) return canonicalizeFeishuAllowlistKey({
|
|
31
|
-
kind: "user",
|
|
32
|
-
value: withoutProviderPrefix.slice(withoutProviderPrefix.indexOf(":") + 1)
|
|
33
|
-
});
|
|
34
|
-
if (lowered.startsWith("open_id:")) return canonicalizeFeishuAllowlistKey({
|
|
35
|
-
kind: "user",
|
|
36
|
-
value: withoutProviderPrefix.slice(withoutProviderPrefix.indexOf(":") + 1)
|
|
37
|
-
});
|
|
38
|
-
const detectedType = detectIdType(withoutProviderPrefix);
|
|
39
|
-
if (detectedType === "chat_id") return canonicalizeFeishuAllowlistKey({
|
|
40
|
-
kind: "chat",
|
|
41
|
-
value: withoutProviderPrefix
|
|
42
|
-
});
|
|
43
|
-
if (detectedType === "open_id" || detectedType === "user_id") return canonicalizeFeishuAllowlistKey({
|
|
44
|
-
kind: "user",
|
|
45
|
-
value: withoutProviderPrefix
|
|
46
|
-
});
|
|
47
|
-
return "";
|
|
48
|
-
}
|
|
49
|
-
function resolveFeishuAllowlistMatch(params) {
|
|
50
|
-
const allowFrom = params.allowFrom.map((entry) => normalizeFeishuAllowEntry(String(entry))).filter(Boolean);
|
|
51
|
-
if (allowFrom.length === 0) return { allowed: false };
|
|
52
|
-
if (allowFrom.includes("*")) return {
|
|
53
|
-
allowed: true,
|
|
54
|
-
matchKey: "*",
|
|
55
|
-
matchSource: "wildcard"
|
|
56
|
-
};
|
|
57
|
-
const senderCandidates = [params.senderId, ...params.senderIds ?? []].map((entry) => normalizeFeishuAllowEntry(entry ?? "")).filter(Boolean);
|
|
58
|
-
for (const senderId of senderCandidates) if (allowFrom.includes(senderId)) return {
|
|
59
|
-
allowed: true,
|
|
60
|
-
matchKey: senderId,
|
|
61
|
-
matchSource: "id"
|
|
62
|
-
};
|
|
63
|
-
return { allowed: false };
|
|
64
|
-
}
|
|
65
|
-
function resolveFeishuGroupConfig(params) {
|
|
66
|
-
const groups = params.cfg?.groups ?? {};
|
|
67
|
-
const wildcard = groups["*"];
|
|
68
|
-
const groupId = params.groupId?.trim();
|
|
69
|
-
if (!groupId) return;
|
|
70
|
-
const direct = groups[groupId];
|
|
71
|
-
if (direct) return direct;
|
|
72
|
-
const lowered = normalizeOptionalLowercaseString(groupId) ?? "";
|
|
73
|
-
const matchKey = Object.keys(groups).find((key) => normalizeOptionalLowercaseString(key) === lowered);
|
|
74
|
-
if (matchKey) return groups[matchKey];
|
|
75
|
-
return wildcard;
|
|
76
|
-
}
|
|
77
|
-
function hasExplicitFeishuGroupConfig(params) {
|
|
78
|
-
const groups = params.cfg?.groups ?? {};
|
|
79
|
-
const groupId = params.groupId?.trim();
|
|
80
|
-
if (!groupId) return false;
|
|
81
|
-
if (Object.prototype.hasOwnProperty.call(groups, groupId) && groupId !== "*") return true;
|
|
82
|
-
const lowered = normalizeOptionalLowercaseString(groupId) ?? "";
|
|
83
|
-
return Object.keys(groups).some((key) => key !== "*" && normalizeOptionalLowercaseString(key) === lowered);
|
|
84
|
-
}
|
|
85
|
-
function resolveFeishuGroupToolPolicy(params) {
|
|
86
|
-
const cfg = params.cfg.channels?.feishu;
|
|
87
|
-
if (!cfg) return;
|
|
88
|
-
return resolveFeishuGroupConfig({
|
|
89
|
-
cfg,
|
|
90
|
-
groupId: params.groupId
|
|
91
|
-
})?.tools;
|
|
92
|
-
}
|
|
93
|
-
function isFeishuGroupAllowed(params) {
|
|
94
|
-
return evaluateSenderGroupAccessForPolicy({
|
|
95
|
-
groupPolicy: params.groupPolicy === "allowall" ? "open" : params.groupPolicy,
|
|
96
|
-
groupAllowFrom: params.allowFrom.map((entry) => String(entry)),
|
|
97
|
-
senderId: params.senderId,
|
|
98
|
-
isSenderAllowed: () => resolveFeishuAllowlistMatch(params).allowed
|
|
99
|
-
}).allowed;
|
|
100
|
-
}
|
|
101
|
-
function resolveFeishuReplyPolicy(params) {
|
|
102
|
-
if (params.isDirectMessage) return { requireMention: false };
|
|
103
|
-
const feishuCfg = params.cfg.channels?.feishu;
|
|
104
|
-
const resolvedCfg = resolveMergedAccountConfig({
|
|
105
|
-
channelConfig: feishuCfg,
|
|
106
|
-
accounts: feishuCfg?.accounts,
|
|
107
|
-
accountId: normalizeAccountId(params.accountId),
|
|
108
|
-
normalizeAccountId,
|
|
109
|
-
omitKeys: ["defaultAccount"]
|
|
110
|
-
});
|
|
111
|
-
const groupRequireMention = resolveFeishuGroupConfig({
|
|
112
|
-
cfg: resolvedCfg,
|
|
113
|
-
groupId: params.groupId
|
|
114
|
-
})?.requireMention;
|
|
115
|
-
return { requireMention: typeof groupRequireMention === "boolean" ? groupRequireMention : typeof resolvedCfg.requireMention === "boolean" ? resolvedCfg.requireMention : params.groupPolicy !== "open" };
|
|
116
|
-
}
|
|
117
|
-
//#endregion
|
|
118
|
-
export { resolveFeishuGroupToolPolicy as a, resolveFeishuGroupConfig as i, isFeishuGroupAllowed as n, resolveFeishuReplyPolicy as o, resolveFeishuAllowlistMatch as r, hasExplicitFeishuGroupConfig as t };
|