@openclaw/feishu 2026.7.2-beta.2 → 2026.7.2-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/api.js +3 -3
- package/dist/{channel-X30GQVwc.js → channel-BdnXYU6g.js} +20 -18
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-By2uqa3Q.js → channel.runtime-CVIzo2dV.js} +100 -15
- package/dist/{drive-B4E8OXZ0.js → drive-BHv8WW9i.js} +1 -1
- package/dist/{monitor-CHl0bWzb.js → monitor-BVQf7-Bl.js} +1 -1
- package/dist/{monitor.account-BSRV2hIF.js → monitor.account-Blbf2T6J.js} +665 -335
- package/dist/{secret-contract-DnlMcrn5.js → secret-contract-BCpDLdg9.js} +17 -26
- package/dist/secret-contract-api.js +1 -1
- package/dist/{send-DrWM_Ilf.js → send-DcrXbqqA.js} +31 -2
- package/dist/{send-result-DsqTk27v.js → send-result-DfE5Fhz6.js} +22 -11
- package/dist/setup-api.js +1 -1
- package/npm-shrinkwrap.json +3 -3
- package/openclaw.plugin.json +24 -0
- package/package.json +4 -4
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "openclaw/plugin-sdk/account-id";
|
|
2
|
+
import { collectConditionalChannelFieldAssignments, createChannelSecretTargetRegistryEntries, getChannelSurface, hasConfiguredSecretInputValue, hasOwnProperty, normalizeSecretStringValue } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
|
|
2
3
|
//#region extensions/feishu/src/secret-contract.ts
|
|
3
4
|
const secretTargetRegistryEntries = createChannelSecretTargetRegistryEntries({
|
|
4
5
|
channelKey: "feishu",
|
|
@@ -17,34 +18,24 @@ function collectRuntimeConfigAssignments(params) {
|
|
|
17
18
|
const resolved = getChannelSurface(params.config, "feishu");
|
|
18
19
|
if (!resolved) return;
|
|
19
20
|
const { channel: feishu, surface } = resolved;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
if (surface.channelEnabled && hasConfiguredSecretInputValue(feishu.appId, params.defaults) && hasConfiguredSecretInputValue(feishu.appSecret, params.defaults) && surface.hasExplicitAccounts && !surface.accounts.some(({ accountId }) => normalizeAccountId(accountId) === DEFAULT_ACCOUNT_ID)) surface.accounts.push({
|
|
22
|
+
accountId: "default",
|
|
23
|
+
account: {},
|
|
24
|
+
enabled: true
|
|
25
|
+
});
|
|
26
|
+
collectConditionalChannelFieldAssignments({
|
|
27
|
+
channelKey: "feishu",
|
|
28
|
+
field: "appSecret",
|
|
29
|
+
channel: feishu,
|
|
30
|
+
surface,
|
|
25
31
|
defaults: params.defaults,
|
|
26
32
|
context: params.context,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
topLevelActiveWithoutAccounts: surface.channelEnabled,
|
|
34
|
+
topLevelInheritedAccountActive: ({ account, enabled }) => enabled && !hasOwnProperty(account, "appSecret"),
|
|
35
|
+
accountActive: ({ enabled }) => enabled,
|
|
36
|
+
topInactiveReason: "no enabled account inherits this top-level Feishu appSecret.",
|
|
37
|
+
accountInactiveReason: "Feishu account is disabled."
|
|
32
38
|
});
|
|
33
|
-
if (surface.hasExplicitAccounts) for (const { accountId, account, enabled } of surface.accounts) {
|
|
34
|
-
if (!hasOwnProperty(account, "appSecret")) continue;
|
|
35
|
-
collectSecretInputAssignment({
|
|
36
|
-
value: account.appSecret,
|
|
37
|
-
path: `channels.feishu.accounts.${accountId}.appSecret`,
|
|
38
|
-
expected: "string",
|
|
39
|
-
defaults: params.defaults,
|
|
40
|
-
context: params.context,
|
|
41
|
-
active: enabled,
|
|
42
|
-
inactiveReason: "Feishu account is disabled.",
|
|
43
|
-
apply: (value) => {
|
|
44
|
-
account.appSecret = value;
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
39
|
const baseConnectionMode = normalizeSecretStringValue(feishu.connectionMode) === "webhook" ? "webhook" : "websocket";
|
|
49
40
|
const resolveAccountMode = (account) => hasOwnProperty(account, "connectionMode") ? normalizeSecretStringValue(account.connectionMode) : baseConnectionMode;
|
|
50
41
|
collectConditionalChannelFieldAssignments({
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-
|
|
1
|
+
import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-BCpDLdg9.js";
|
|
2
2
|
export { channelSecrets, collectRuntimeConfigAssignments, secretTargetRegistryEntries };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { d as isRecord$1, h as requestFeishuApi, s as resolveFeishuRuntimeAccount } from "./accounts-BDoGHJDk.js";
|
|
2
2
|
import { i as resolveReceiveIdType, r as normalizeFeishuTarget } from "./targets-BUjQ1TcA.js";
|
|
3
|
-
import { c as assertFeishuPostWithinEnvelope, f as materializeFeishuPostMarkdownSoftBreaks, i as toFeishuSendResult, l as buildFeishuPostMessageContent, o as resolveFeishuCardTemplate, r as resolveFeishuReceiptKind, t as assertFeishuMessageApiSuccess } from "./send-result-
|
|
3
|
+
import { c as assertFeishuPostWithinEnvelope, f as materializeFeishuPostMarkdownSoftBreaks, i as toFeishuSendResult, l as buildFeishuPostMessageContent, o as resolveFeishuCardTemplate, r as resolveFeishuReceiptKind, t as assertFeishuMessageApiSuccess } from "./send-result-DfE5Fhz6.js";
|
|
4
4
|
import { r as createFeishuClient } from "./client-87BmeMpj.js";
|
|
5
5
|
import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
|
|
6
6
|
import { parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
@@ -9,6 +9,7 @@ import { convertMarkdownTables } from "openclaw/plugin-sdk/text-chunking";
|
|
|
9
9
|
import fs from "node:fs";
|
|
10
10
|
import path from "node:path";
|
|
11
11
|
import { MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS, runFfmpeg, runFfprobe } from "openclaw/plugin-sdk/media-runtime";
|
|
12
|
+
import { isBlockedHostnameOrIp, resolvePinnedHostnameWithPolicy } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
12
13
|
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
13
14
|
import { readRegularFile, writeExternalFileWithinRoot } from "openclaw/plugin-sdk/security-runtime";
|
|
14
15
|
import { Readable } from "node:stream";
|
|
@@ -38,6 +39,33 @@ function resolveFeishuIdentityHeaderTitle(identity) {
|
|
|
38
39
|
return (emoji ? `${emoji} ${name}` : name).trim();
|
|
39
40
|
}
|
|
40
41
|
//#endregion
|
|
42
|
+
//#region extensions/feishu/src/media-fallback.ts
|
|
43
|
+
const FEISHU_MEDIA_UPLOAD_FAILURE_FALLBACK_TEXT = "Media upload failed. Please try again.";
|
|
44
|
+
function hasAsciiControlCharacter(value) {
|
|
45
|
+
return Array.from(value).some((character) => {
|
|
46
|
+
const code = character.charCodeAt(0);
|
|
47
|
+
return code <= 31 || code === 127;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
async function resolvePublicFeishuMediaReference(value) {
|
|
51
|
+
const raw = value?.trim();
|
|
52
|
+
if (!raw || hasAsciiControlCharacter(raw)) return;
|
|
53
|
+
try {
|
|
54
|
+
const parsed = new URL(raw);
|
|
55
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return;
|
|
56
|
+
if (parsed.username || parsed.password || isBlockedHostnameOrIp(parsed.hostname)) return;
|
|
57
|
+
await resolvePinnedHostnameWithPolicy(parsed.hostname);
|
|
58
|
+
return parsed.href;
|
|
59
|
+
} catch {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function buildFeishuMediaFallbackText(params) {
|
|
64
|
+
const mediaUrl = await resolvePublicFeishuMediaReference(params.mediaUrl);
|
|
65
|
+
const attachmentText = mediaUrl ? `${params.mediaLinkStyle === "plain" ? "" : "📎 "}${mediaUrl}` : FEISHU_MEDIA_UPLOAD_FAILURE_FALLBACK_TEXT;
|
|
66
|
+
return [params.text?.trim(), attachmentText].filter(Boolean).join("\n\n");
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
41
69
|
//#region extensions/feishu/src/external-keys.ts
|
|
42
70
|
const CONTROL_CHARS_RE = /\p{Cc}/u;
|
|
43
71
|
const MAX_EXTERNAL_KEY_LENGTH = 512;
|
|
@@ -480,6 +508,7 @@ function normalizeMediaNameForExtension(raw) {
|
|
|
480
508
|
}
|
|
481
509
|
}
|
|
482
510
|
function shouldSuppressFeishuTextForVoiceMedia(params) {
|
|
511
|
+
if (params.ttsSupplement) return params.ttsSupplement.visibleTextAlreadyDelivered === true;
|
|
483
512
|
if (params.audioAsVoice === true) return true;
|
|
484
513
|
if (params.fileName && isFeishuNativeVoiceAudio({
|
|
485
514
|
fileName: params.fileName,
|
|
@@ -1285,4 +1314,4 @@ async function sendMarkdownCardFeishu(params) {
|
|
|
1285
1314
|
});
|
|
1286
1315
|
}
|
|
1287
1316
|
//#endregion
|
|
1288
|
-
export {
|
|
1317
|
+
export { buildFeishuMediaFallbackText as _, sendMarkdownCardFeishu as a, parsePostContent as c, isMentionForwardRequest as d, isFeishuGroupChatType as f, normalizeFeishuExternalKey as g, shouldSuppressFeishuTextForVoiceMedia as h, sendCardFeishu as i, extractMentionTargets as l, sendMediaFeishu as m, getMessageFeishu as n, sendMessageFeishu as o, saveMessageResourceFeishu as p, listFeishuThreadMessages as r, sendStructuredCardFeishu as s, editMessageFeishu as t, isFeishuBroadcastMention as u, resolveFeishuIdentityEmoji as v, resolveFeishuIdentityHeaderTitle as y };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { d as isRecord$1 } from "./accounts-BDoGHJDk.js";
|
|
2
2
|
import { r as normalizeFeishuTarget, t as detectIdType } from "./targets-BUjQ1TcA.js";
|
|
3
|
+
import { compileAllowlist, resolveAllowlistMatchByCandidates } from "openclaw/plugin-sdk/allow-from";
|
|
3
4
|
import { ToolAuthorizationError } from "openclaw/plugin-sdk/channel-actions";
|
|
4
5
|
import { createMessageReceiptFromOutboundResults } from "openclaw/plugin-sdk/channel-outbound";
|
|
5
6
|
import { resolveScopeKeyCaseInsensitive, resolveScopeToolsPolicy } from "openclaw/plugin-sdk/channel-policy";
|
|
@@ -307,6 +308,9 @@ function normalizeChatId(raw) {
|
|
|
307
308
|
if (!raw) return "";
|
|
308
309
|
return normalizeFeishuTarget(raw) ?? raw.trim();
|
|
309
310
|
}
|
|
311
|
+
function normalizeFeishuAllowlist(entries) {
|
|
312
|
+
return (entries ?? []).map((entry) => normalizeFeishuAllowEntry(String(entry))).filter(Boolean);
|
|
313
|
+
}
|
|
310
314
|
function readContextFields(ctx) {
|
|
311
315
|
if (isActionContext(ctx)) return {
|
|
312
316
|
accountId: normalizeOptionalString(ctx.accountId),
|
|
@@ -350,10 +354,13 @@ function isFeishuGroupReadAllowed(cfg, account, chatId, current) {
|
|
|
350
354
|
groupId: chatId
|
|
351
355
|
});
|
|
352
356
|
const normalizedChatId = normalizeFeishuAllowEntry(chatId);
|
|
353
|
-
return explicitlyConfigured || (
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
+
return explicitlyConfigured || resolveAllowlistMatchByCandidates({
|
|
358
|
+
allowList: normalizeFeishuAllowlist(account.config.groupAllowFrom),
|
|
359
|
+
candidates: [{
|
|
360
|
+
value: normalizedChatId,
|
|
361
|
+
source: "id"
|
|
362
|
+
}]
|
|
363
|
+
}).allowed;
|
|
357
364
|
}
|
|
358
365
|
function isFeishuGroupReadEnabled(cfg, account, chatId) {
|
|
359
366
|
if (resolveFeishuReadGroupPolicy(cfg, account) === "disabled") return false;
|
|
@@ -363,7 +370,7 @@ function isFeishuGroupReadEnabled(cfg, account, chatId) {
|
|
|
363
370
|
})?.enabled !== false;
|
|
364
371
|
}
|
|
365
372
|
function isDmUniversallyAllowed(account) {
|
|
366
|
-
return (account.config.allowFrom
|
|
373
|
+
return compileAllowlist(normalizeFeishuAllowlist(account.config.allowFrom)).wildcard;
|
|
367
374
|
}
|
|
368
375
|
function assertFeishuChatReadAllowed(params) {
|
|
369
376
|
const authorization = resolveFeishuChatReadPreliminaryAuthorization(params);
|
|
@@ -431,7 +438,7 @@ function authorizeFeishuChatMemberRead(params) {
|
|
|
431
438
|
}
|
|
432
439
|
function canEnumerateAllFeishuGroups(cfg, account) {
|
|
433
440
|
const policy = resolveFeishuReadGroupPolicy(cfg, account);
|
|
434
|
-
return policy === "open" || policy === "allowlist" && (account.config.groupAllowFrom
|
|
441
|
+
return policy === "open" || policy === "allowlist" && compileAllowlist(normalizeFeishuAllowlist(account.config.groupAllowFrom)).wildcard;
|
|
435
442
|
}
|
|
436
443
|
function canEnumerateAllFeishuPeers(account) {
|
|
437
444
|
return isDmUniversallyAllowed(account);
|
|
@@ -536,13 +543,17 @@ function postContentBytes(messageText, mentions) {
|
|
|
536
543
|
* Markdown wrappers and first-chunk mentions count toward the byte budget.
|
|
537
544
|
*/
|
|
538
545
|
function chunkFeishuPostMarkdown(params) {
|
|
539
|
-
const { text, firstChunkMentions } = params;
|
|
546
|
+
const { text, firstChunkMentions, chunkMentions } = params;
|
|
540
547
|
if (!text) return [];
|
|
541
548
|
const requestedLimit = Number.isFinite(params.limit) && params.limit > 0 ? Math.floor(params.limit) : text.length;
|
|
542
549
|
const initialChunks = params.initialChunks ?? chunkFeishuMarkdownWithMode(text, requestedLimit, params.mode ?? "length");
|
|
543
550
|
const output = [];
|
|
551
|
+
const resolveMentions = (isFirst) => {
|
|
552
|
+
const mentions = [...chunkMentions ?? [], ...isFirst ? firstChunkMentions ?? [] : []];
|
|
553
|
+
return mentions.length > 0 ? mentions : void 0;
|
|
554
|
+
};
|
|
544
555
|
for (const initialChunk of initialChunks) {
|
|
545
|
-
if (postContentBytes(initialChunk, output.length === 0
|
|
556
|
+
if (postContentBytes(initialChunk, resolveMentions(output.length === 0)) <= FEISHU_POST_MAX_BYTES) {
|
|
546
557
|
output.push(initialChunk);
|
|
547
558
|
continue;
|
|
548
559
|
}
|
|
@@ -553,12 +564,12 @@ function chunkFeishuPostMarkdown(params) {
|
|
|
553
564
|
let oversizedChunk;
|
|
554
565
|
let oversizedMentions;
|
|
555
566
|
for (const [index, chunk] of chunks.entries()) {
|
|
556
|
-
const
|
|
557
|
-
const contentBytes = postContentBytes(chunk,
|
|
567
|
+
const mentionsForChunk = resolveMentions(output.length === 0 && index === 0);
|
|
568
|
+
const contentBytes = postContentBytes(chunk, mentionsForChunk);
|
|
558
569
|
largestContentBytes = Math.max(largestContentBytes, contentBytes);
|
|
559
570
|
if (contentBytes > FEISHU_POST_MAX_BYTES && oversizedChunk === void 0) {
|
|
560
571
|
oversizedChunk = chunk;
|
|
561
|
-
oversizedMentions =
|
|
572
|
+
oversizedMentions = mentionsForChunk;
|
|
562
573
|
}
|
|
563
574
|
}
|
|
564
575
|
if (oversizedChunk === void 0) {
|
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-BdnXYU6g.js";
|
|
2
2
|
export { feishuPlugin, feishuSetupAdapter, feishuSetupWizard };
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/feishu",
|
|
3
|
-
"version": "2026.7.2-beta.
|
|
3
|
+
"version": "2026.7.2-beta.3",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@openclaw/feishu",
|
|
9
|
-
"version": "2026.7.2-beta.
|
|
9
|
+
"version": "2026.7.2-beta.3",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@larksuiteoapi/node-sdk": "1.68.0",
|
|
12
12
|
"mdast-util-from-markdown": "2.0.3",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"zod": "4.4.3"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
|
-
"openclaw": ">=2026.7.2-beta.
|
|
19
|
+
"openclaw": ">=2026.7.2-beta.3"
|
|
20
20
|
},
|
|
21
21
|
"peerDependenciesMeta": {
|
|
22
22
|
"openclaw": {
|
package/openclaw.plugin.json
CHANGED
|
@@ -455,6 +455,12 @@
|
|
|
455
455
|
"enabled"
|
|
456
456
|
]
|
|
457
457
|
},
|
|
458
|
+
"allowBots": {
|
|
459
|
+
"type": "boolean"
|
|
460
|
+
},
|
|
461
|
+
"vcAutoJoin": {
|
|
462
|
+
"type": "boolean"
|
|
463
|
+
},
|
|
458
464
|
"typingIndicator": {
|
|
459
465
|
"type": "boolean"
|
|
460
466
|
}
|
|
@@ -520,6 +526,12 @@
|
|
|
520
526
|
"enabled"
|
|
521
527
|
]
|
|
522
528
|
},
|
|
529
|
+
"allowBots": {
|
|
530
|
+
"type": "boolean"
|
|
531
|
+
},
|
|
532
|
+
"vcAutoJoin": {
|
|
533
|
+
"type": "boolean"
|
|
534
|
+
},
|
|
523
535
|
"typingIndicator": {
|
|
524
536
|
"type": "boolean"
|
|
525
537
|
},
|
|
@@ -1178,6 +1190,12 @@
|
|
|
1178
1190
|
"default": true,
|
|
1179
1191
|
"type": "boolean"
|
|
1180
1192
|
},
|
|
1193
|
+
"allowBots": {
|
|
1194
|
+
"type": "boolean"
|
|
1195
|
+
},
|
|
1196
|
+
"vcAutoJoin": {
|
|
1197
|
+
"type": "boolean"
|
|
1198
|
+
},
|
|
1181
1199
|
"tts": {
|
|
1182
1200
|
"type": "object",
|
|
1183
1201
|
"properties": {
|
|
@@ -1936,6 +1954,12 @@
|
|
|
1936
1954
|
"resolveSenderNames": {
|
|
1937
1955
|
"type": "boolean"
|
|
1938
1956
|
},
|
|
1957
|
+
"allowBots": {
|
|
1958
|
+
"type": "boolean"
|
|
1959
|
+
},
|
|
1960
|
+
"vcAutoJoin": {
|
|
1961
|
+
"type": "boolean"
|
|
1962
|
+
},
|
|
1939
1963
|
"tts": {
|
|
1940
1964
|
"type": "object",
|
|
1941
1965
|
"properties": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/feishu",
|
|
3
|
-
"version": "2026.7.2-beta.
|
|
3
|
+
"version": "2026.7.2-beta.3",
|
|
4
4
|
"description": "OpenClaw Feishu/Lark channel plugin for chats and workplace tools (community maintained by @m1heng).",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"zod": "4.4.3"
|
|
17
17
|
},
|
|
18
18
|
"peerDependencies": {
|
|
19
|
-
"openclaw": ">=2026.7.2-beta.
|
|
19
|
+
"openclaw": ">=2026.7.2-beta.3"
|
|
20
20
|
},
|
|
21
21
|
"peerDependenciesMeta": {
|
|
22
22
|
"openclaw": {
|
|
@@ -47,10 +47,10 @@
|
|
|
47
47
|
"minHostVersion": ">=2026.5.29"
|
|
48
48
|
},
|
|
49
49
|
"compat": {
|
|
50
|
-
"pluginApi": ">=2026.7.2-beta.
|
|
50
|
+
"pluginApi": ">=2026.7.2-beta.3"
|
|
51
51
|
},
|
|
52
52
|
"build": {
|
|
53
|
-
"openclawVersion": "2026.7.2-beta.
|
|
53
|
+
"openclawVersion": "2026.7.2-beta.3"
|
|
54
54
|
},
|
|
55
55
|
"release": {
|
|
56
56
|
"publishToClawHub": true,
|