@openclaw/feishu 2026.7.2-beta.1 → 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 +322 -176
- package/dist/{app-registration-BwQ-aGTe.js → app-registration-BzkyrVZu.js} +11 -11
- package/dist/{channel-DdPQ2HGh.js → channel-BdnXYU6g.js} +36 -50
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-DJ_B-bpG.js → channel.runtime-CVIzo2dV.js} +102 -17
- package/dist/{client-BUC-R2Wi.js → client-87BmeMpj.js} +51 -16
- package/dist/{drive-Bpe8ONK_.js → drive-BHv8WW9i.js} +2 -2
- package/dist/{monitor-M3iYtoh4.js → monitor-BVQf7-Bl.js} +2 -2
- package/dist/{monitor.account-F99J862T.js → monitor.account-Blbf2T6J.js} +752 -423
- package/dist/{monitor.startup-DpZzunQn.js → monitor.startup-Cy8NPGAX.js} +1 -1
- package/dist/{probe-CAloGqgG.js → probe-BgboTHIn.js} +1 -1
- package/dist/{secret-contract-DnlMcrn5.js → secret-contract-BCpDLdg9.js} +17 -26
- package/dist/secret-contract-api.js +1 -1
- package/dist/{send-CpnLYueT.js → send-DcrXbqqA.js} +87 -8
- package/dist/{send-result-CPS7AozW.js → send-result-DfE5Fhz6.js} +31 -16
- package/dist/setup-api.js +1 -1
- package/npm-shrinkwrap.json +3 -3
- package/openclaw.plugin.json +34 -8
- package/package.json +4 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as probeFeishu } from "./probe-
|
|
1
|
+
import { t as probeFeishu } from "./probe-BgboTHIn.js";
|
|
2
2
|
import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
3
3
|
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
4
|
//#region extensions/feishu/src/monitor-startup-timeout.ts
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
|
|
2
|
-
import { r as createFeishuClient } from "./client-
|
|
2
|
+
import { r as createFeishuClient } from "./client-87BmeMpj.js";
|
|
3
3
|
import { asDateTimestampMs, resolveExpiresAtMsFromDurationMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
4
4
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
5
5
|
//#region extensions/feishu/src/async.ts
|
|
@@ -1,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,18 +1,19 @@
|
|
|
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
|
+
import { r as createFeishuClient } from "./client-87BmeMpj.js";
|
|
4
5
|
import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
|
|
5
|
-
import { r as createFeishuClient } from "./client-BUC-R2Wi.js";
|
|
6
6
|
import { parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
7
7
|
import { isRecord, normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
8
8
|
import { convertMarkdownTables } from "openclaw/plugin-sdk/text-chunking";
|
|
9
9
|
import fs from "node:fs";
|
|
10
10
|
import path from "node:path";
|
|
11
|
-
import { mediaKindFromMime } from "openclaw/plugin-sdk/media-mime";
|
|
12
11
|
import { MEDIA_FFMPEG_MAX_AUDIO_DURATION_SECS, runFfmpeg, runFfprobe } from "openclaw/plugin-sdk/media-runtime";
|
|
12
|
+
import { isBlockedHostnameOrIp, resolvePinnedHostnameWithPolicy } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
13
13
|
import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
|
|
14
14
|
import { readRegularFile, writeExternalFileWithinRoot } from "openclaw/plugin-sdk/security-runtime";
|
|
15
15
|
import { Readable } from "node:stream";
|
|
16
|
+
import { mediaKindFromMime } from "openclaw/plugin-sdk/media-mime";
|
|
16
17
|
import { saveMediaBuffer, saveMediaStream } from "openclaw/plugin-sdk/media-store";
|
|
17
18
|
import { resolvePreferredOpenClawTmpDir, withTempDownloadPath, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
|
|
18
19
|
//#region extensions/feishu/src/identity-header.ts
|
|
@@ -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;
|
|
@@ -50,6 +78,55 @@ function normalizeFeishuExternalKey(value) {
|
|
|
50
78
|
return normalized;
|
|
51
79
|
}
|
|
52
80
|
//#endregion
|
|
81
|
+
//#region extensions/feishu/src/media-chunk-idle.ts
|
|
82
|
+
var FeishuInboundMediaTimeoutError = class extends Error {
|
|
83
|
+
constructor(chunkTimeoutMs) {
|
|
84
|
+
super(`Feishu media download stalled: no data received for ${chunkTimeoutMs}ms`);
|
|
85
|
+
this.name = "FeishuInboundMediaTimeoutError";
|
|
86
|
+
this.chunkTimeoutMs = chunkTimeoutMs;
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
function destroySource(source) {
|
|
90
|
+
const s = source;
|
|
91
|
+
if (typeof s.destroy === "function") s.destroy();
|
|
92
|
+
}
|
|
93
|
+
function withChunkIdleTimeout(source, chunkTimeoutMs) {
|
|
94
|
+
return { async *[Symbol.asyncIterator]() {
|
|
95
|
+
const iterator = source[Symbol.asyncIterator]();
|
|
96
|
+
let exhausted = false;
|
|
97
|
+
try {
|
|
98
|
+
while (true) {
|
|
99
|
+
const nextPromise = iterator.next();
|
|
100
|
+
let timeoutHandle;
|
|
101
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
102
|
+
timeoutHandle = setTimeout(() => {
|
|
103
|
+
reject(new FeishuInboundMediaTimeoutError(chunkTimeoutMs));
|
|
104
|
+
try {
|
|
105
|
+
destroySource(source);
|
|
106
|
+
} catch {}
|
|
107
|
+
}, chunkTimeoutMs);
|
|
108
|
+
});
|
|
109
|
+
let result;
|
|
110
|
+
try {
|
|
111
|
+
result = await Promise.race([nextPromise, timeoutPromise]);
|
|
112
|
+
} finally {
|
|
113
|
+
if (timeoutHandle !== void 0) clearTimeout(timeoutHandle);
|
|
114
|
+
}
|
|
115
|
+
if (result.done) {
|
|
116
|
+
exhausted = true;
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
yield result.value;
|
|
120
|
+
}
|
|
121
|
+
} finally {
|
|
122
|
+
if (!exhausted && typeof iterator.return === "function") iterator.return().catch(() => void 0);
|
|
123
|
+
}
|
|
124
|
+
} };
|
|
125
|
+
}
|
|
126
|
+
function saveMediaStreamWithIdleTimeout(stream, contentType, maxBytes, fileName, chunkTimeoutMs) {
|
|
127
|
+
return saveMediaStream(withChunkIdleTimeout(stream, chunkTimeoutMs), contentType, "inbound", maxBytes, fileName);
|
|
128
|
+
}
|
|
129
|
+
//#endregion
|
|
53
130
|
//#region extensions/feishu/src/send-target.ts
|
|
54
131
|
function resolveFeishuSendTarget(params) {
|
|
55
132
|
const target = params.to.trim();
|
|
@@ -177,14 +254,15 @@ async function saveFeishuResponseMedia(params) {
|
|
|
177
254
|
if (responseWithOptionalFields.code !== void 0 && responseWithOptionalFields.code !== 0) throw new Error(`${params.errorPrefix}: ${responseWithOptionalFields.msg || `code ${responseWithOptionalFields.code}`}`);
|
|
178
255
|
if (responseWithOptionalFields.data && Buffer.isBuffer(responseWithOptionalFields.data)) return saveMediaBuffer(responseWithOptionalFields.data, contentType, "inbound", maxBytes, fileName);
|
|
179
256
|
if (responseWithOptionalFields.data instanceof ArrayBuffer) return saveMediaBuffer(Buffer.from(responseWithOptionalFields.data), contentType, "inbound", maxBytes, fileName);
|
|
180
|
-
|
|
257
|
+
const save = (stream, ct = contentType, mb = maxBytes, fn = fileName) => saveMediaStreamWithIdleTimeout(stream, ct, mb, fn, FEISHU_MEDIA_HTTP_TIMEOUT_MS);
|
|
258
|
+
if (typeof response.getReadableStream === "function") return save(response.getReadableStream());
|
|
181
259
|
if (typeof response.writeFile === "function") return await withTempDownloadPath({ prefix: params.tmpDirPrefix }, async (tmpPath) => {
|
|
182
260
|
await response.writeFile(tmpPath);
|
|
183
261
|
if ((await fs.promises.stat(tmpPath)).size > maxBytes) throw mediaLimitError(maxBytes);
|
|
184
|
-
return await
|
|
262
|
+
return await save(fs.createReadStream(tmpPath));
|
|
185
263
|
});
|
|
186
|
-
if (responseWithOptionalFields[Symbol.asyncIterator]) return
|
|
187
|
-
if (response instanceof Readable) return
|
|
264
|
+
if (responseWithOptionalFields[Symbol.asyncIterator]) return save(responseWithOptionalFields);
|
|
265
|
+
if (response instanceof Readable) return save(response);
|
|
188
266
|
const keys = Object.keys(response);
|
|
189
267
|
throw new Error(`${params.errorPrefix}: unexpected response format. Keys: [${keys.join(", ")}]`);
|
|
190
268
|
}
|
|
@@ -430,6 +508,7 @@ function normalizeMediaNameForExtension(raw) {
|
|
|
430
508
|
}
|
|
431
509
|
}
|
|
432
510
|
function shouldSuppressFeishuTextForVoiceMedia(params) {
|
|
511
|
+
if (params.ttsSupplement) return params.ttsSupplement.visibleTextAlreadyDelivered === true;
|
|
433
512
|
if (params.audioAsVoice === true) return true;
|
|
434
513
|
if (params.fileName && isFeishuNativeVoiceAudio({
|
|
435
514
|
fileName: params.fileName,
|
|
@@ -1235,4 +1314,4 @@ async function sendMarkdownCardFeishu(params) {
|
|
|
1235
1314
|
});
|
|
1236
1315
|
}
|
|
1237
1316
|
//#endregion
|
|
1238
|
-
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);
|
|
@@ -439,6 +446,13 @@ function canEnumerateAllFeishuPeers(account) {
|
|
|
439
446
|
//#endregion
|
|
440
447
|
//#region extensions/feishu/src/markdown.ts
|
|
441
448
|
const FEISHU_POST_MAX_BYTES = 30 * 1024;
|
|
449
|
+
/** One parser contract for Feishu message and document Markdown decisions. */
|
|
450
|
+
function parseFeishuMarkdown(text) {
|
|
451
|
+
return fromMarkdown(text, {
|
|
452
|
+
extensions: [gfmTable()],
|
|
453
|
+
mdastExtensions: [gfmTableFromMarkdown()]
|
|
454
|
+
});
|
|
455
|
+
}
|
|
442
456
|
function buildFeishuPostMentionElements(mentions) {
|
|
443
457
|
if (!mentions?.length) return [];
|
|
444
458
|
const elements = [];
|
|
@@ -465,10 +479,7 @@ function assertFeishuPostWithinEnvelope(content, label) {
|
|
|
465
479
|
if (Buffer.byteLength(content, "utf8") > FEISHU_POST_MAX_BYTES) throw new Error(`${label} exceeds the 30 KB rich-post API limit`);
|
|
466
480
|
}
|
|
467
481
|
function collectSoftBreakOffsets(text) {
|
|
468
|
-
const root =
|
|
469
|
-
extensions: [gfmTable()],
|
|
470
|
-
mdastExtensions: [gfmTableFromMarkdown()]
|
|
471
|
-
});
|
|
482
|
+
const root = parseFeishuMarkdown(text);
|
|
472
483
|
const offsets = [];
|
|
473
484
|
const pending = [root];
|
|
474
485
|
while (pending.length > 0) {
|
|
@@ -532,13 +543,17 @@ function postContentBytes(messageText, mentions) {
|
|
|
532
543
|
* Markdown wrappers and first-chunk mentions count toward the byte budget.
|
|
533
544
|
*/
|
|
534
545
|
function chunkFeishuPostMarkdown(params) {
|
|
535
|
-
const { text, firstChunkMentions } = params;
|
|
546
|
+
const { text, firstChunkMentions, chunkMentions } = params;
|
|
536
547
|
if (!text) return [];
|
|
537
548
|
const requestedLimit = Number.isFinite(params.limit) && params.limit > 0 ? Math.floor(params.limit) : text.length;
|
|
538
549
|
const initialChunks = params.initialChunks ?? chunkFeishuMarkdownWithMode(text, requestedLimit, params.mode ?? "length");
|
|
539
550
|
const output = [];
|
|
551
|
+
const resolveMentions = (isFirst) => {
|
|
552
|
+
const mentions = [...chunkMentions ?? [], ...isFirst ? firstChunkMentions ?? [] : []];
|
|
553
|
+
return mentions.length > 0 ? mentions : void 0;
|
|
554
|
+
};
|
|
540
555
|
for (const initialChunk of initialChunks) {
|
|
541
|
-
if (postContentBytes(initialChunk, output.length === 0
|
|
556
|
+
if (postContentBytes(initialChunk, resolveMentions(output.length === 0)) <= FEISHU_POST_MAX_BYTES) {
|
|
542
557
|
output.push(initialChunk);
|
|
543
558
|
continue;
|
|
544
559
|
}
|
|
@@ -549,12 +564,12 @@ function chunkFeishuPostMarkdown(params) {
|
|
|
549
564
|
let oversizedChunk;
|
|
550
565
|
let oversizedMentions;
|
|
551
566
|
for (const [index, chunk] of chunks.entries()) {
|
|
552
|
-
const
|
|
553
|
-
const contentBytes = postContentBytes(chunk,
|
|
567
|
+
const mentionsForChunk = resolveMentions(output.length === 0 && index === 0);
|
|
568
|
+
const contentBytes = postContentBytes(chunk, mentionsForChunk);
|
|
554
569
|
largestContentBytes = Math.max(largestContentBytes, contentBytes);
|
|
555
570
|
if (contentBytes > FEISHU_POST_MAX_BYTES && oversizedChunk === void 0) {
|
|
556
571
|
oversizedChunk = chunk;
|
|
557
|
-
oversizedMentions =
|
|
572
|
+
oversizedMentions = mentionsForChunk;
|
|
558
573
|
}
|
|
559
574
|
}
|
|
560
575
|
if (oversizedChunk === void 0) {
|
|
@@ -763,4 +778,4 @@ function toFeishuSendResult(response, chatId, kind) {
|
|
|
763
778
|
};
|
|
764
779
|
}
|
|
765
780
|
//#endregion
|
|
766
|
-
export {
|
|
781
|
+
export { resolveFeishuChatType as A, resolveFeishuDmIngressAccess as C, resolveFeishuGroupToolPolicy as D, resolveFeishuGroupSenderActivationIngressAccess as E, buildFeishuCardActionTextFallback as M, createFeishuCardInteractionEnvelope as N, resolveFeishuReplyPolicy as O, decodeFeishuCardAction as P, normalizeFeishuAllowEntry as S, resolveFeishuGroupConversationIngressAccess as T, canEnumerateAllFeishuPeers as _, readNativeFeishuCardJson as a, resolveFeishuChatReadPreliminaryAuthorization as b, assertFeishuPostWithinEnvelope as c, chunkFeishuPostMarkdown as d, materializeFeishuPostMarkdownSoftBreaks as f, canEnumerateAllFeishuGroups as g, authorizeFeishuChatMemberRead as h, toFeishuSendResult as i, FEISHU_CARD_INTERACTION_VERSION as j, normalizeFeishuChatType as k, buildFeishuPostMessageContent as l, assertFeishuChatReadAllowed as m, createFeishuSendReceipt as n, resolveFeishuCardTemplate as o, parseFeishuMarkdown as p, resolveFeishuReceiptKind as r, sanitizeNativeFeishuCard as s, assertFeishuMessageApiSuccess as t, chunkFeishuMarkdown as u, isFeishuGroupReadAllowed as v, resolveFeishuGroupConfig as w, hasExplicitFeishuGroupConfig as x, isFeishuGroupReadEnabled as y };
|
package/dist/setup-api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as feishuSetupAdapter, n as feishuSetupWizard, t as feishuPlugin } from "./channel-
|
|
1
|
+
import { i as feishuSetupAdapter, n as feishuSetupWizard, t as feishuPlugin } from "./channel-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
|
},
|
|
@@ -852,9 +864,10 @@
|
|
|
852
864
|
"default": "pairing",
|
|
853
865
|
"type": "string",
|
|
854
866
|
"enum": [
|
|
855
|
-
"open",
|
|
856
867
|
"pairing",
|
|
857
|
-
"allowlist"
|
|
868
|
+
"allowlist",
|
|
869
|
+
"open",
|
|
870
|
+
"disabled"
|
|
858
871
|
]
|
|
859
872
|
},
|
|
860
873
|
"allowFrom": {
|
|
@@ -876,8 +889,8 @@
|
|
|
876
889
|
"type": "string",
|
|
877
890
|
"enum": [
|
|
878
891
|
"open",
|
|
879
|
-
"
|
|
880
|
-
"
|
|
892
|
+
"disabled",
|
|
893
|
+
"allowlist"
|
|
881
894
|
]
|
|
882
895
|
},
|
|
883
896
|
{
|
|
@@ -1177,6 +1190,12 @@
|
|
|
1177
1190
|
"default": true,
|
|
1178
1191
|
"type": "boolean"
|
|
1179
1192
|
},
|
|
1193
|
+
"allowBots": {
|
|
1194
|
+
"type": "boolean"
|
|
1195
|
+
},
|
|
1196
|
+
"vcAutoJoin": {
|
|
1197
|
+
"type": "boolean"
|
|
1198
|
+
},
|
|
1180
1199
|
"tts": {
|
|
1181
1200
|
"type": "object",
|
|
1182
1201
|
"properties": {
|
|
@@ -1612,9 +1631,10 @@
|
|
|
1612
1631
|
"dmPolicy": {
|
|
1613
1632
|
"type": "string",
|
|
1614
1633
|
"enum": [
|
|
1615
|
-
"open",
|
|
1616
1634
|
"pairing",
|
|
1617
|
-
"allowlist"
|
|
1635
|
+
"allowlist",
|
|
1636
|
+
"open",
|
|
1637
|
+
"disabled"
|
|
1618
1638
|
]
|
|
1619
1639
|
},
|
|
1620
1640
|
"allowFrom": {
|
|
@@ -1636,8 +1656,8 @@
|
|
|
1636
1656
|
"type": "string",
|
|
1637
1657
|
"enum": [
|
|
1638
1658
|
"open",
|
|
1639
|
-
"
|
|
1640
|
-
"
|
|
1659
|
+
"disabled",
|
|
1660
|
+
"allowlist"
|
|
1641
1661
|
]
|
|
1642
1662
|
},
|
|
1643
1663
|
{
|
|
@@ -1934,6 +1954,12 @@
|
|
|
1934
1954
|
"resolveSenderNames": {
|
|
1935
1955
|
"type": "boolean"
|
|
1936
1956
|
},
|
|
1957
|
+
"allowBots": {
|
|
1958
|
+
"type": "boolean"
|
|
1959
|
+
},
|
|
1960
|
+
"vcAutoJoin": {
|
|
1961
|
+
"type": "boolean"
|
|
1962
|
+
},
|
|
1937
1963
|
"tts": {
|
|
1938
1964
|
"type": "object",
|
|
1939
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,
|