@openclaw/feishu 2026.5.28-beta.2 → 2026.5.28-beta.4
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 +2 -2
- package/dist/{app-registration-BZSSYX1J.js → app-registration-DCy5-X_C.js} +12 -5
- package/dist/{channel-BVSJh3s1.js → channel-BfeesQob.js} +9 -16
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-D6J6otxd.js → channel.runtime-BLnKcmtO.js} +5 -5
- package/dist/{drive-6Ohn34x9.js → drive-USxqssMG.js} +1 -1
- package/dist/legacy-state-migrations-api.js +73 -0
- package/dist/{monitor-1WyqLgPM.js → monitor-CyD0CQxm.js} +2 -2
- package/dist/{monitor.account-DXQXXSzI.js → monitor.account-ByxawtBB.js} +181 -43
- package/dist/{monitor.state-B6SoAUys.js → monitor.state-t4Ae5VIa.js} +1 -1
- package/dist/{probe-RvCg70BY.js → probe-956I34qH.js} +1 -1
- package/dist/runtime-api.js +1 -2
- package/dist/{send-CKZz15KQ.js → send-Djou0Z5a.js} +3 -2
- package/dist/setup-api.js +1 -1
- package/dist/setup-entry.js +5 -0
- package/npm-shrinkwrap.json +3 -3
- package/package.json +8 -5
- package/dist/{client-DcSzLkSX.js → client-BhMNZBJD.js} +1 -1
package/dist/api.js
CHANGED
|
@@ -2,9 +2,9 @@ import { a as parseFeishuTargetId, i as parseFeishuDirectConversationId, n as bu
|
|
|
2
2
|
import { n as getFeishuThreadBindingManager, r as testing, t as createFeishuThreadBindingManager } from "./thread-bindings-D24m3Cjy.js";
|
|
3
3
|
import { n as handleFeishuSubagentEnded, r as handleFeishuSubagentSpawning, t as handleFeishuSubagentDeliveryTarget } from "./subagent-hooks-fuyBHOVu.js";
|
|
4
4
|
import { r as listEnabledFeishuAccounts } from "./accounts-CXnY5H8g.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-BfeesQob.js";
|
|
6
6
|
import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
|
|
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-
|
|
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-USxqssMG.js";
|
|
8
8
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, readStringValue, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
9
9
|
import { optionalPositiveIntegerSchema } from "openclaw/plugin-sdk/channel-actions";
|
|
10
10
|
import { existsSync } from "node:fs";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { finiteSecondsToTimerSafeMilliseconds } from "openclaw/plugin-sdk/number-runtime";
|
|
1
2
|
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
2
3
|
import { renderQrTerminal } from "openclaw/plugin-sdk/media-runtime";
|
|
3
4
|
//#region extensions/feishu/src/app-registration.ts
|
|
@@ -12,6 +13,8 @@ const FEISHU_ACCOUNTS_URL = "https://accounts.feishu.cn";
|
|
|
12
13
|
const LARK_ACCOUNTS_URL = "https://accounts.larksuite.com";
|
|
13
14
|
const REGISTRATION_PATH = "/oauth/v1/app/registration";
|
|
14
15
|
const REQUEST_TIMEOUT_MS = 1e4;
|
|
16
|
+
const DEFAULT_REGISTRATION_POLL_INTERVAL_SECONDS = 5;
|
|
17
|
+
const DEFAULT_REGISTRATION_EXPIRE_SECONDS = 600;
|
|
15
18
|
function accountsBaseUrl(domain) {
|
|
16
19
|
return domain === "lark" ? LARK_ACCOUNTS_URL : FEISHU_ACCOUNTS_URL;
|
|
17
20
|
}
|
|
@@ -67,8 +70,8 @@ async function beginAppRegistration(domain = "feishu") {
|
|
|
67
70
|
deviceCode: res.device_code,
|
|
68
71
|
qrUrl: qrUrl.toString(),
|
|
69
72
|
userCode: res.user_code,
|
|
70
|
-
interval: res.interval
|
|
71
|
-
expireIn: res.expire_in
|
|
73
|
+
interval: finiteSecondsToTimerSafeMilliseconds(res.interval) === void 0 ? DEFAULT_REGISTRATION_POLL_INTERVAL_SECONDS : res.interval,
|
|
74
|
+
expireIn: finiteSecondsToTimerSafeMilliseconds(res.expire_in) === void 0 ? DEFAULT_REGISTRATION_EXPIRE_SECONDS : res.expire_in
|
|
72
75
|
};
|
|
73
76
|
}
|
|
74
77
|
/**
|
|
@@ -81,7 +84,8 @@ async function pollAppRegistration(params) {
|
|
|
81
84
|
let currentInterval = params.interval;
|
|
82
85
|
let domain = initialDomain;
|
|
83
86
|
let domainSwitched = false;
|
|
84
|
-
const
|
|
87
|
+
const expireInMs = finiteSecondsToTimerSafeMilliseconds(expireIn) ?? finiteSecondsToTimerSafeMilliseconds(DEFAULT_REGISTRATION_EXPIRE_SECONDS) ?? REQUEST_TIMEOUT_MS;
|
|
88
|
+
const deadline = Date.now() + expireInMs;
|
|
85
89
|
while (Date.now() < deadline) {
|
|
86
90
|
if (abortSignal?.aborted) return { status: "timeout" };
|
|
87
91
|
const baseUrl = accountsBaseUrl(domain);
|
|
@@ -93,7 +97,7 @@ async function pollAppRegistration(params) {
|
|
|
93
97
|
...tp ? { tp } : {}
|
|
94
98
|
});
|
|
95
99
|
} catch {
|
|
96
|
-
await
|
|
100
|
+
await sleepRegistrationPollInterval(currentInterval);
|
|
97
101
|
continue;
|
|
98
102
|
}
|
|
99
103
|
if (pollRes.user_info?.tenant_brand) {
|
|
@@ -120,7 +124,7 @@ async function pollAppRegistration(params) {
|
|
|
120
124
|
status: "error",
|
|
121
125
|
message: `${pollRes.error}: ${pollRes.error_description ?? "unknown"}`
|
|
122
126
|
};
|
|
123
|
-
await
|
|
127
|
+
await sleepRegistrationPollInterval(currentInterval);
|
|
124
128
|
}
|
|
125
129
|
return { status: "timeout" };
|
|
126
130
|
}
|
|
@@ -180,5 +184,8 @@ async function getAppOwnerOpenId(params) {
|
|
|
180
184
|
function sleep(ms) {
|
|
181
185
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
182
186
|
}
|
|
187
|
+
function sleepRegistrationPollInterval(intervalSeconds) {
|
|
188
|
+
return sleep(finiteSecondsToTimerSafeMilliseconds(intervalSeconds) ?? finiteSecondsToTimerSafeMilliseconds(DEFAULT_REGISTRATION_POLL_INTERVAL_SECONDS) ?? REQUEST_TIMEOUT_MS);
|
|
189
|
+
}
|
|
183
190
|
//#endregion
|
|
184
191
|
export { beginAppRegistration, getAppOwnerOpenId, initAppRegistration, pollAppRegistration, printQrCode };
|
|
@@ -19,6 +19,7 @@ import { createAllowlistProviderGroupPolicyWarningCollector, projectConfigAccoun
|
|
|
19
19
|
import { createChannelDirectoryAdapter, createRuntimeDirectoryLiveAdapter, listDirectoryGroupEntriesFromMapKeysAndAllowFrom, listDirectoryUserEntriesFromAllowFromAndMapKeys } from "openclaw/plugin-sdk/directory-runtime";
|
|
20
20
|
import { normalizeMessagePresentation, renderMessagePresentationFallbackText } from "openclaw/plugin-sdk/interactive-runtime";
|
|
21
21
|
import { createLazyRuntimeNamedExport } from "openclaw/plugin-sdk/lazy-runtime";
|
|
22
|
+
import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
22
23
|
import { buildProbeChannelStatusSummary, createComputedAccountStatusAdapter, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/status-helpers";
|
|
23
24
|
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$2, normalizeAccountId as normalizeAccountId$1, resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution";
|
|
24
25
|
import { createResolvedApproverActionAuthAdapter, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
|
|
@@ -1452,7 +1453,7 @@ async function promptFeishuSetupMethod(prompter) {
|
|
|
1452
1453
|
});
|
|
1453
1454
|
}
|
|
1454
1455
|
async function runScanToCreate(prompter, domain) {
|
|
1455
|
-
const { beginAppRegistration, initAppRegistration, pollAppRegistration, printQrCode } = await import("./app-registration-
|
|
1456
|
+
const { beginAppRegistration, initAppRegistration, pollAppRegistration, printQrCode } = await import("./app-registration-DCy5-X_C.js");
|
|
1456
1457
|
try {
|
|
1457
1458
|
await initAppRegistration(domain);
|
|
1458
1459
|
} catch {
|
|
@@ -1537,7 +1538,7 @@ async function runNewAppFlow(params) {
|
|
|
1537
1538
|
appSecretProbeValue = appSecretResult.resolvedValue;
|
|
1538
1539
|
}
|
|
1539
1540
|
if (appId && appSecretProbeValue) {
|
|
1540
|
-
const { getAppOwnerOpenId } = await import("./app-registration-
|
|
1541
|
+
const { getAppOwnerOpenId } = await import("./app-registration-DCy5-X_C.js");
|
|
1541
1542
|
scanOpenId = await getAppOwnerOpenId({
|
|
1542
1543
|
appId,
|
|
1543
1544
|
appSecret: appSecretProbeValue,
|
|
@@ -1647,7 +1648,7 @@ const feishuSetupWizard = {
|
|
|
1647
1648
|
});
|
|
1648
1649
|
let probeResult = null;
|
|
1649
1650
|
if (configured && account.configured) try {
|
|
1650
|
-
const { probeFeishu } = await import("./probe-
|
|
1651
|
+
const { probeFeishu } = await import("./probe-956I34qH.js").then((n) => n.n);
|
|
1651
1652
|
probeResult = await probeFeishu(account);
|
|
1652
1653
|
} catch {}
|
|
1653
1654
|
if (!configured) return [formatFeishuStatusLine("needs-credentials")];
|
|
@@ -1723,7 +1724,7 @@ const meta = {
|
|
|
1723
1724
|
order: 70,
|
|
1724
1725
|
preferSessionLookupForAnnounceTarget: true
|
|
1725
1726
|
};
|
|
1726
|
-
const loadFeishuChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-
|
|
1727
|
+
const loadFeishuChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-BLnKcmtO.js"), "feishuChannelRuntime");
|
|
1727
1728
|
function toFeishuMessageSendResult(result, kind) {
|
|
1728
1729
|
const receipt = result.receipt ?? createFeishuSendReceipt({
|
|
1729
1730
|
messageId: result.messageId,
|
|
@@ -1755,7 +1756,7 @@ const feishuMessageAdapter = defineChannelMessageAdapter({
|
|
|
1755
1756
|
}
|
|
1756
1757
|
});
|
|
1757
1758
|
async function createFeishuActionClient(account) {
|
|
1758
|
-
const { createFeishuClient } = await import("./client-
|
|
1759
|
+
const { createFeishuClient } = await import("./client-BhMNZBJD.js").then((n) => n.t);
|
|
1759
1760
|
return createFeishuClient(account);
|
|
1760
1761
|
}
|
|
1761
1762
|
const collectFeishuSecurityWarnings = createAllowlistProviderGroupPolicyWarningCollector({
|
|
@@ -1961,18 +1962,10 @@ function readFirstString(params, keys, fallback) {
|
|
|
1961
1962
|
}
|
|
1962
1963
|
if (typeof fallback === "string" && fallback.trim()) return fallback.trim();
|
|
1963
1964
|
}
|
|
1964
|
-
function isPositiveSafeInteger(value) {
|
|
1965
|
-
return Number.isSafeInteger(value) && value > 0;
|
|
1966
|
-
}
|
|
1967
1965
|
function readOptionalPositiveInteger(params, keys) {
|
|
1968
1966
|
for (const key of keys) {
|
|
1969
|
-
const
|
|
1970
|
-
if (
|
|
1971
|
-
if (typeof value === "string" && value.trim()) {
|
|
1972
|
-
const trimmed = value.trim();
|
|
1973
|
-
const parsed = /^\d+$/.test(trimmed) ? Number(trimmed) : NaN;
|
|
1974
|
-
if (isPositiveSafeInteger(parsed)) return parsed;
|
|
1975
|
-
}
|
|
1967
|
+
const parsed = parseStrictPositiveInteger(params[key]);
|
|
1968
|
+
if (parsed !== void 0) return parsed;
|
|
1976
1969
|
}
|
|
1977
1970
|
}
|
|
1978
1971
|
function resolveFeishuActionTarget(ctx) {
|
|
@@ -2547,7 +2540,7 @@ const feishuPlugin = createChatChannelPlugin({
|
|
|
2547
2540
|
})
|
|
2548
2541
|
}),
|
|
2549
2542
|
gateway: { startAccount: async (ctx) => {
|
|
2550
|
-
const { monitorFeishuProvider } = await import("./monitor-
|
|
2543
|
+
const { monitorFeishuProvider } = await import("./monitor-CyD0CQxm.js");
|
|
2551
2544
|
const account = resolveFeishuRuntimeAccount({
|
|
2552
2545
|
cfg: ctx.cfg,
|
|
2553
2546
|
accountId: ctx.accountId
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as feishuPlugin } from "./channel-
|
|
1
|
+
import { t as feishuPlugin } from "./channel-BfeesQob.js";
|
|
2
2
|
export { feishuPlugin };
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { o as resolveFeishuAccount, s as resolveFeishuRuntimeAccount, y as parseFeishuCommentTarget } from "./accounts-CXnY5H8g.js";
|
|
2
|
-
import { h as listFeishuDirectoryPeers, m as listFeishuDirectoryGroups, o as buildFeishuPresentationCardElements } from "./channel-
|
|
3
|
-
import { r as createFeishuClient } from "./client-
|
|
4
|
-
import { c as getChatInfo, l as getChatMembers, r as cleanupAmbientCommentTypingReaction, t as deliverCommentThreadText, u as getFeishuMemberInfo } from "./drive-
|
|
2
|
+
import { h as listFeishuDirectoryPeers, m as listFeishuDirectoryGroups, o as buildFeishuPresentationCardElements } from "./channel-BfeesQob.js";
|
|
3
|
+
import { r as createFeishuClient } from "./client-BhMNZBJD.js";
|
|
4
|
+
import { c as getChatInfo, l as getChatMembers, r as cleanupAmbientCommentTypingReaction, t as deliverCommentThreadText, u as getFeishuMemberInfo } from "./drive-USxqssMG.js";
|
|
5
5
|
import { chunkTextForOutbound } from "./runtime-api.js";
|
|
6
|
-
import { a as sendCardFeishu, c as sendStructuredCardFeishu, g as shouldSuppressFeishuTextForVoiceMedia, h as sendMediaFeishu, i as resolveFeishuCardTemplate, n as getMessageFeishu, o as sendMarkdownCardFeishu, s as sendMessageFeishu, t as editMessageFeishu } from "./send-
|
|
7
|
-
import { t as probeFeishu } from "./probe-
|
|
6
|
+
import { a as sendCardFeishu, c as sendStructuredCardFeishu, g as shouldSuppressFeishuTextForVoiceMedia, h as sendMediaFeishu, i as resolveFeishuCardTemplate, n as getMessageFeishu, o as sendMarkdownCardFeishu, s as sendMessageFeishu, t as editMessageFeishu } from "./send-Djou0Z5a.js";
|
|
7
|
+
import { t as probeFeishu } from "./probe-956I34qH.js";
|
|
8
8
|
import { isRecord, normalizeLowercaseStringOrEmpty, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
9
9
|
import { interactiveReplyToPresentation, normalizeInteractiveReply, normalizeMessagePresentation, renderMessagePresentationFallbackText, resolveInteractiveTextFallback } from "openclaw/plugin-sdk/interactive-runtime";
|
|
10
10
|
import path from "node:path";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { d as formatFeishuApiError, f as isRecord$1, h as readString, i as listFeishuAccountIds, l as encodeQuery, o as resolveFeishuAccount, r as listEnabledFeishuAccounts, s as resolveFeishuRuntimeAccount, u as extractReplyText, y as parseFeishuCommentTarget } from "./accounts-CXnY5H8g.js";
|
|
2
|
-
import { r as createFeishuClient } from "./client-
|
|
2
|
+
import { r as createFeishuClient } from "./client-BhMNZBJD.js";
|
|
3
3
|
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
4
|
import { optionalPositiveIntegerSchema } from "openclaw/plugin-sdk/channel-actions";
|
|
5
5
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
//#region extensions/feishu/src/dedup-migrations.ts
|
|
5
|
+
const DEDUP_TTL_MS = 1440 * 60 * 1e3;
|
|
6
|
+
const STORE_MAX_ENTRIES = 1e4;
|
|
7
|
+
function safeNamespaceFromFileName(fileName) {
|
|
8
|
+
if (!fileName.endsWith(".json")) return null;
|
|
9
|
+
const namespace = fileName.slice(0, -5).trim();
|
|
10
|
+
return namespace ? namespace : null;
|
|
11
|
+
}
|
|
12
|
+
function readLegacyDedupeData(filePath) {
|
|
13
|
+
try {
|
|
14
|
+
const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
15
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
16
|
+
const out = {};
|
|
17
|
+
for (const [messageId, seenAt] of Object.entries(parsed)) if (typeof seenAt === "number" && Number.isFinite(seenAt) && seenAt > 0) out[messageId] = seenAt;
|
|
18
|
+
return out;
|
|
19
|
+
} catch {
|
|
20
|
+
return {};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function dedupeStoreKey(namespace, messageId) {
|
|
24
|
+
return createHash("sha256").update(`${namespace}\0${messageId}`, "utf8").digest("hex").slice(0, 32);
|
|
25
|
+
}
|
|
26
|
+
function remainingTtlMs(seenAt, now) {
|
|
27
|
+
return Math.max(1, DEDUP_TTL_MS - (now - seenAt));
|
|
28
|
+
}
|
|
29
|
+
function buildMigrationEntries(namespace, sourcePath, now) {
|
|
30
|
+
return Object.entries(readLegacyDedupeData(sourcePath)).flatMap(([messageId, seenAt]) => {
|
|
31
|
+
if (now - seenAt >= DEDUP_TTL_MS) return [];
|
|
32
|
+
return [{
|
|
33
|
+
key: dedupeStoreKey(namespace, messageId),
|
|
34
|
+
value: {
|
|
35
|
+
namespace,
|
|
36
|
+
messageId,
|
|
37
|
+
seenAt
|
|
38
|
+
},
|
|
39
|
+
ttlMs: remainingTtlMs(seenAt, now)
|
|
40
|
+
}];
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
const detectFeishuLegacyStateMigrations = ({ stateDir }) => {
|
|
44
|
+
const dedupDir = path.join(stateDir, "feishu", "dedup");
|
|
45
|
+
let entries = [];
|
|
46
|
+
try {
|
|
47
|
+
entries = fs.readdirSync(dedupDir, { withFileTypes: true });
|
|
48
|
+
} catch {
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
const now = Date.now();
|
|
52
|
+
return entries.flatMap((entry) => {
|
|
53
|
+
if (!entry.isFile()) return [];
|
|
54
|
+
const namespace = safeNamespaceFromFileName(entry.name);
|
|
55
|
+
if (!namespace) return [];
|
|
56
|
+
const sourcePath = path.join(dedupDir, entry.name);
|
|
57
|
+
if (buildMigrationEntries(namespace, sourcePath, now).length === 0) return [];
|
|
58
|
+
return [{
|
|
59
|
+
kind: "plugin-state-import",
|
|
60
|
+
label: `Feishu ${namespace} dedupe`,
|
|
61
|
+
sourcePath,
|
|
62
|
+
targetPath: `plugin state:dedup.${namespace}`,
|
|
63
|
+
pluginId: "feishu",
|
|
64
|
+
namespace: `dedup.${namespace}`,
|
|
65
|
+
maxEntries: STORE_MAX_ENTRIES,
|
|
66
|
+
scopeKey: "",
|
|
67
|
+
cleanupSource: "rename",
|
|
68
|
+
readEntries: () => buildMigrationEntries(namespace, sourcePath, now)
|
|
69
|
+
}];
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
//#endregion
|
|
73
|
+
export { detectFeishuLegacyStateMigrations };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { r as listEnabledFeishuAccounts, s as resolveFeishuRuntimeAccount } from "./accounts-CXnY5H8g.js";
|
|
2
|
-
import { l as fetchBotIdentityForMonitor } from "./monitor.state-
|
|
2
|
+
import { l as fetchBotIdentityForMonitor } from "./monitor.state-t4Ae5VIa.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-ByxawtBB.js");
|
|
7
7
|
return await monitorAccountRuntimePromise;
|
|
8
8
|
}
|
|
9
9
|
async function monitorFeishuProvider(opts = {}) {
|
|
@@ -2,34 +2,34 @@ import { t as buildFeishuConversationId } from "./conversation-id-DuL575sn.js";
|
|
|
2
2
|
import { i as resolveReceiveIdType } from "./targets-BUjQ1TcA.js";
|
|
3
3
|
import { t as createFeishuThreadBindingManager } from "./thread-bindings-D24m3Cjy.js";
|
|
4
4
|
import { _ as buildFeishuCommentTarget, f as isRecord$1, h as readString, l as encodeQuery, m as parseCommentContentElements, p as normalizeString, s as resolveFeishuRuntimeAccount, u as extractReplyText, v as normalizeCommentFileType } from "./accounts-CXnY5H8g.js";
|
|
5
|
-
import { c as normalizeFeishuAllowEntry, d as resolveFeishuGroupConversationIngressAccess, f as resolveFeishuGroupSenderActivationIngressAccess, l as resolveFeishuDmIngressAccess, p as resolveFeishuReplyPolicy, s as hasExplicitFeishuGroupConfig, u as resolveFeishuGroupConfig } from "./channel-
|
|
5
|
+
import { c as normalizeFeishuAllowEntry, d as resolveFeishuGroupConversationIngressAccess, f as resolveFeishuGroupSenderActivationIngressAccess, l as resolveFeishuDmIngressAccess, p as resolveFeishuReplyPolicy, s as hasExplicitFeishuGroupConfig, u as resolveFeishuGroupConfig } from "./channel-BfeesQob.js";
|
|
6
6
|
import { c as decodeFeishuCardAction, o as buildFeishuCardActionTextFallback, s as createFeishuCardInteractionEnvelope } from "./send-result-DSTSkRDM.js";
|
|
7
7
|
import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
|
|
8
|
-
import { a as getFeishuUserAgent, i as createFeishuWSClient, n as createEventDispatcher, r as createFeishuClient } from "./client-
|
|
9
|
-
import { c as getChatInfo, i as createCommentTypingReactionLifecycle, t as deliverCommentThreadText } from "./drive-
|
|
8
|
+
import { a as getFeishuUserAgent, i as createFeishuWSClient, n as createEventDispatcher, r as createFeishuClient } from "./client-BhMNZBJD.js";
|
|
9
|
+
import { c as getChatInfo, i as createCommentTypingReactionLifecycle, t as deliverCommentThreadText } from "./drive-USxqssMG.js";
|
|
10
10
|
import { createReplyPrefixContext, evaluateSupplementalContextVisibility, loadSessionStore, normalizeAgentId as normalizeAgentId$2, resolveChannelContextVisibilityMode, resolveSessionStoreEntry } from "./runtime-api.js";
|
|
11
|
-
import { _ as normalizeFeishuExternalKey, a as sendCardFeishu, c as sendStructuredCardFeishu, d as isFeishuBroadcastMention, f as isMentionForwardRequest, g as shouldSuppressFeishuTextForVoiceMedia, h as sendMediaFeishu, i as resolveFeishuCardTemplate, l as parsePostContent, m as saveMessageResourceFeishu, n as getMessageFeishu, p as isFeishuGroupChatType, r as listFeishuThreadMessages, s as sendMessageFeishu, u as extractMentionTargets } from "./send-
|
|
12
|
-
import { i as waitForAbortableDelay, r as raceWithTimeoutAndAbort } from "./probe-
|
|
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-
|
|
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 saveMessageResourceFeishu, n as getMessageFeishu, p as isFeishuGroupChatType, r as listFeishuThreadMessages, s as sendMessageFeishu, u as extractMentionTargets } from "./send-Djou0Z5a.js";
|
|
12
|
+
import { i as waitForAbortableDelay, r as raceWithTimeoutAndAbort } from "./probe-956I34qH.js";
|
|
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-t4Ae5VIa.js";
|
|
14
14
|
import { asBoolean, asNullableRecord, isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, readStringValue, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
15
15
|
import { ensureConfiguredBindingRouteReady, resolveConfiguredBindingRoute, resolveRuntimeConversationBindingRoute } from "openclaw/plugin-sdk/conversation-runtime";
|
|
16
16
|
import { resolveInboundLastRouteSessionKey } from "openclaw/plugin-sdk/routing";
|
|
17
17
|
import { createChannelMessageReplyPipeline, formatChannelProgressDraftLineForEntry, isChannelProgressDraftWorkToolName, resolveAgentOutboundIdentity } from "openclaw/plugin-sdk/channel-outbound";
|
|
18
18
|
import { createChannelPairingController, createChannelPairingController as createChannelPairingController$1 } from "openclaw/plugin-sdk/channel-pairing";
|
|
19
|
+
import { parseStrictNonNegativeInteger, resolveExpiresAtMsFromDurationSeconds } from "openclaw/plugin-sdk/number-runtime";
|
|
19
20
|
import { stripReasoningTagsFromText } from "openclaw/plugin-sdk/text-chunking";
|
|
20
21
|
import fs from "node:fs";
|
|
21
22
|
import os from "node:os";
|
|
22
23
|
import path from "node:path";
|
|
23
24
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
24
25
|
import * as Lark from "@larksuiteoapi/node-sdk";
|
|
25
|
-
import
|
|
26
|
-
import {
|
|
26
|
+
import * as crypto$1 from "node:crypto";
|
|
27
|
+
import crypto, { createHash } from "node:crypto";
|
|
28
|
+
import { loadJsonFile } from "openclaw/plugin-sdk/json-store";
|
|
27
29
|
import { applyBasicWebhookRequestGuards, resolveRequestClientIp } from "openclaw/plugin-sdk/webhook-ingress";
|
|
28
30
|
import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
29
31
|
import { resolveSendableOutboundReplyParts, resolveTextChunksWithFallback, sendMediaWithLeadingCaption } from "openclaw/plugin-sdk/reply-payload";
|
|
30
32
|
import { resolvePinnedMainDmOwnerFromAllowlist, safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
|
|
31
|
-
import * as crypto$1 from "node:crypto";
|
|
32
|
-
import crypto from "node:crypto";
|
|
33
33
|
import { resolveChannelConfigWrites } from "openclaw/plugin-sdk/channel-config-writes";
|
|
34
34
|
import { buildChannelInboundEventContext, toInboundMediaFacts } from "openclaw/plugin-sdk/channel-inbound";
|
|
35
35
|
import { DEFAULT_GROUP_HISTORY_LIMIT, createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
|
|
@@ -161,7 +161,7 @@ function parseMergeForwardContent(params) {
|
|
|
161
161
|
const subMessages = items.filter((item) => item.upper_message_id);
|
|
162
162
|
if (subMessages.length === 0) return "[Merged and Forwarded Message - no sub-messages found]";
|
|
163
163
|
log?.(`feishu: merge_forward contains ${subMessages.length} sub-messages`);
|
|
164
|
-
subMessages.sort((a, b) =>
|
|
164
|
+
subMessages.sort((a, b) => (parseStrictNonNegativeInteger(a.create_time) ?? 0) - (parseStrictNonNegativeInteger(b.create_time) ?? 0));
|
|
165
165
|
const lines = ["[Merged and Forwarded Messages]"];
|
|
166
166
|
for (const item of subMessages.slice(0, maxMessages)) lines.push(`- ${formatSubMessageContent(item.body?.content || "", item.msg_type || "text")}`);
|
|
167
167
|
if (subMessages.length > maxMessages) lines.push(`... and ${subMessages.length - maxMessages} more messages`);
|
|
@@ -447,26 +447,93 @@ function releaseFeishuMessageProcessing(messageId, namespace = "global") {
|
|
|
447
447
|
//#region extensions/feishu/src/dedup.ts
|
|
448
448
|
const DEDUP_TTL_MS = 1440 * 60 * 1e3;
|
|
449
449
|
const MEMORY_MAX_SIZE = 1e3;
|
|
450
|
-
const
|
|
451
|
-
|
|
450
|
+
const STORE_MAX_ENTRIES = 1e4;
|
|
451
|
+
const memory = /* @__PURE__ */ new Map();
|
|
452
|
+
const importedLegacyNamespaces = /* @__PURE__ */ new Set();
|
|
453
|
+
const cachedDedupStores = /* @__PURE__ */ new Map();
|
|
454
|
+
function normalizeMessageId(messageId) {
|
|
455
|
+
const trimmed = messageId?.trim();
|
|
456
|
+
return trimmed ? trimmed : null;
|
|
457
|
+
}
|
|
458
|
+
function normalizeNamespace(namespace) {
|
|
459
|
+
return namespace?.trim() || "global";
|
|
460
|
+
}
|
|
461
|
+
function resolveLegacyStateDir(env = process.env) {
|
|
452
462
|
const stateOverride = env.OPENCLAW_STATE_DIR?.trim();
|
|
453
463
|
if (stateOverride) return stateOverride;
|
|
454
464
|
if (env.VITEST || env.NODE_ENV === "test") return path.join(os.tmpdir(), ["openclaw-vitest", String(process.pid)].join("-"));
|
|
455
465
|
return path.join(os.homedir(), ".openclaw");
|
|
456
466
|
}
|
|
457
|
-
function
|
|
467
|
+
function resolveLegacyNamespaceFilePath(namespace) {
|
|
458
468
|
const safe = namespace.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
459
|
-
return path.join(
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
const
|
|
469
|
-
|
|
469
|
+
return path.join(resolveLegacyStateDir(), "feishu", "dedup", `${safe}.json`);
|
|
470
|
+
}
|
|
471
|
+
function pluginStateNamespace(namespace) {
|
|
472
|
+
return `dedup.${namespace.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
473
|
+
}
|
|
474
|
+
function openDedupStore(namespace) {
|
|
475
|
+
const stateNamespace = pluginStateNamespace(namespace);
|
|
476
|
+
const cached = cachedDedupStores.get(stateNamespace);
|
|
477
|
+
if (cached) return cached;
|
|
478
|
+
const store = getFeishuRuntime().state.openSyncKeyedStore({
|
|
479
|
+
namespace: stateNamespace,
|
|
480
|
+
maxEntries: STORE_MAX_ENTRIES,
|
|
481
|
+
defaultTtlMs: DEDUP_TTL_MS
|
|
482
|
+
});
|
|
483
|
+
cachedDedupStores.set(stateNamespace, store);
|
|
484
|
+
return store;
|
|
485
|
+
}
|
|
486
|
+
function dedupeStoreKey(namespace, messageId) {
|
|
487
|
+
return createHash("sha256").update(`${namespace}\0${messageId}`, "utf8").digest("hex").slice(0, 32);
|
|
488
|
+
}
|
|
489
|
+
function memoryKey(namespace, messageId) {
|
|
490
|
+
return `${namespace}\0${messageId}`;
|
|
491
|
+
}
|
|
492
|
+
function isRecent(seenAt, now = Date.now()) {
|
|
493
|
+
return typeof seenAt === "number" && Number.isFinite(seenAt) && now - seenAt < DEDUP_TTL_MS;
|
|
494
|
+
}
|
|
495
|
+
function pruneMemory(now = Date.now()) {
|
|
496
|
+
for (const [key, seenAt] of memory) if (!isRecent(seenAt, now)) memory.delete(key);
|
|
497
|
+
if (memory.size <= MEMORY_MAX_SIZE) return;
|
|
498
|
+
const toRemove = Array.from(memory.entries()).toSorted(([, left], [, right]) => left - right).slice(0, memory.size - MEMORY_MAX_SIZE);
|
|
499
|
+
for (const [key] of toRemove) memory.delete(key);
|
|
500
|
+
}
|
|
501
|
+
function remember(namespace, messageId, seenAt = Date.now()) {
|
|
502
|
+
memory.set(memoryKey(namespace, messageId), seenAt);
|
|
503
|
+
pruneMemory(seenAt);
|
|
504
|
+
}
|
|
505
|
+
function hasMemory(namespace, messageId, now = Date.now()) {
|
|
506
|
+
const key = memoryKey(namespace, messageId);
|
|
507
|
+
if (isRecent(memory.get(key), now)) return true;
|
|
508
|
+
memory.delete(key);
|
|
509
|
+
return false;
|
|
510
|
+
}
|
|
511
|
+
function sanitizeLegacyDedupeData(value) {
|
|
512
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
513
|
+
const out = {};
|
|
514
|
+
for (const [key, seenAt] of Object.entries(value)) if (typeof seenAt === "number" && Number.isFinite(seenAt) && seenAt > 0) out[key] = seenAt;
|
|
515
|
+
return out;
|
|
516
|
+
}
|
|
517
|
+
function importLegacyDedupNamespace(namespace, now = Date.now(), log) {
|
|
518
|
+
if (importedLegacyNamespaces.has(namespace)) return;
|
|
519
|
+
try {
|
|
520
|
+
const data = sanitizeLegacyDedupeData(loadJsonFile(resolveLegacyNamespaceFilePath(namespace)));
|
|
521
|
+
const store = openDedupStore(namespace);
|
|
522
|
+
for (const [messageId, seenAt] of Object.entries(data)) {
|
|
523
|
+
if (!isRecent(seenAt, now)) continue;
|
|
524
|
+
const key = dedupeStoreKey(namespace, messageId);
|
|
525
|
+
if (store.lookup(key) != null) continue;
|
|
526
|
+
store.register(key, {
|
|
527
|
+
namespace,
|
|
528
|
+
messageId,
|
|
529
|
+
seenAt
|
|
530
|
+
}, { ttlMs: Math.max(1, DEDUP_TTL_MS - (now - seenAt)) });
|
|
531
|
+
}
|
|
532
|
+
importedLegacyNamespaces.add(namespace);
|
|
533
|
+
} catch (error) {
|
|
534
|
+
importedLegacyNamespaces.delete(namespace);
|
|
535
|
+
log?.(`feishu-dedup: legacy state import failed: ${String(error)}`);
|
|
536
|
+
}
|
|
470
537
|
}
|
|
471
538
|
async function claimUnprocessedFeishuMessage(params) {
|
|
472
539
|
const { messageId, namespace = "global", log } = params;
|
|
@@ -492,31 +559,96 @@ async function recordProcessedFeishuMessage(messageId, namespace = "global", log
|
|
|
492
559
|
if (!normalizedMessageId) return false;
|
|
493
560
|
return await tryRecordMessagePersistent(normalizedMessageId, namespace, log);
|
|
494
561
|
}
|
|
562
|
+
async function forgetProcessedFeishuMessage(messageId, namespace = "global", log) {
|
|
563
|
+
const normalizedNamespace = normalizeNamespace(namespace);
|
|
564
|
+
const normalizedMessageId = normalizeMessageId(messageId);
|
|
565
|
+
if (!normalizedMessageId) return false;
|
|
566
|
+
memory.delete(memoryKey(normalizedNamespace, normalizedMessageId));
|
|
567
|
+
const key = dedupeStoreKey(normalizedNamespace, normalizedMessageId);
|
|
568
|
+
try {
|
|
569
|
+
return openDedupStore(normalizedNamespace).delete(key);
|
|
570
|
+
} catch (error) {
|
|
571
|
+
log?.(`feishu-dedup: persistent delete failed: ${String(error)}`);
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
495
575
|
async function hasProcessedFeishuMessage(messageId, namespace = "global", log) {
|
|
496
576
|
const normalizedMessageId = normalizeMessageId(messageId);
|
|
497
577
|
if (!normalizedMessageId) return false;
|
|
498
578
|
return hasRecordedMessagePersistent(normalizedMessageId, namespace, log);
|
|
499
579
|
}
|
|
500
580
|
async function tryRecordMessagePersistent(messageId, namespace = "global", log) {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
581
|
+
const normalizedNamespace = normalizeNamespace(namespace);
|
|
582
|
+
const normalizedMessageId = normalizeMessageId(messageId);
|
|
583
|
+
if (!normalizedMessageId) return true;
|
|
584
|
+
const now = Date.now();
|
|
585
|
+
importLegacyDedupNamespace(normalizedNamespace, now, log);
|
|
586
|
+
if (hasMemory(normalizedNamespace, normalizedMessageId, now)) return false;
|
|
587
|
+
const key = dedupeStoreKey(normalizedNamespace, normalizedMessageId);
|
|
588
|
+
try {
|
|
589
|
+
const store = openDedupStore(normalizedNamespace);
|
|
590
|
+
const existingSeenAt = store.lookup(key)?.seenAt;
|
|
591
|
+
if (isRecent(existingSeenAt, now)) {
|
|
592
|
+
remember(normalizedNamespace, normalizedMessageId, existingSeenAt);
|
|
593
|
+
return false;
|
|
505
594
|
}
|
|
506
|
-
|
|
595
|
+
if (!store.registerIfAbsent(key, {
|
|
596
|
+
namespace: normalizedNamespace,
|
|
597
|
+
messageId: normalizedMessageId,
|
|
598
|
+
seenAt: now
|
|
599
|
+
}, { ttlMs: DEDUP_TTL_MS })) {
|
|
600
|
+
const currentSeenAt = store.lookup(key)?.seenAt;
|
|
601
|
+
if (isRecent(currentSeenAt, now)) {
|
|
602
|
+
remember(normalizedNamespace, normalizedMessageId, currentSeenAt);
|
|
603
|
+
return false;
|
|
604
|
+
}
|
|
605
|
+
store.register(key, {
|
|
606
|
+
namespace: normalizedNamespace,
|
|
607
|
+
messageId: normalizedMessageId,
|
|
608
|
+
seenAt: now
|
|
609
|
+
}, { ttlMs: DEDUP_TTL_MS });
|
|
610
|
+
}
|
|
611
|
+
remember(normalizedNamespace, normalizedMessageId, now);
|
|
612
|
+
return true;
|
|
613
|
+
} catch (error) {
|
|
614
|
+
log?.(`feishu-dedup: persistent state error, falling back to memory: ${String(error)}`);
|
|
615
|
+
remember(normalizedNamespace, normalizedMessageId, now);
|
|
616
|
+
return true;
|
|
617
|
+
}
|
|
507
618
|
}
|
|
508
619
|
async function hasRecordedMessagePersistent(messageId, namespace = "global", log) {
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
620
|
+
const normalizedNamespace = normalizeNamespace(namespace);
|
|
621
|
+
const normalizedMessageId = normalizeMessageId(messageId);
|
|
622
|
+
if (!normalizedMessageId) return false;
|
|
623
|
+
const now = Date.now();
|
|
624
|
+
importLegacyDedupNamespace(normalizedNamespace, now, log);
|
|
625
|
+
if (hasMemory(normalizedNamespace, normalizedMessageId, now)) return true;
|
|
626
|
+
try {
|
|
627
|
+
const existingSeenAt = openDedupStore(normalizedNamespace).lookup(dedupeStoreKey(normalizedNamespace, normalizedMessageId))?.seenAt;
|
|
628
|
+
if (!isRecent(existingSeenAt, now)) return false;
|
|
629
|
+
remember(normalizedNamespace, normalizedMessageId, existingSeenAt);
|
|
630
|
+
return true;
|
|
631
|
+
} catch (error) {
|
|
632
|
+
log?.(`feishu-dedup: persistent peek failed: ${String(error)}`);
|
|
633
|
+
return hasMemory(normalizedNamespace, normalizedMessageId, now);
|
|
634
|
+
}
|
|
515
635
|
}
|
|
516
636
|
async function warmupDedupFromDisk(namespace, log) {
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
637
|
+
const normalizedNamespace = normalizeNamespace(namespace);
|
|
638
|
+
try {
|
|
639
|
+
let loaded = 0;
|
|
640
|
+
const now = Date.now();
|
|
641
|
+
importLegacyDedupNamespace(normalizedNamespace, now, log);
|
|
642
|
+
for (const entry of openDedupStore(normalizedNamespace).entries()) {
|
|
643
|
+
if (entry.value.namespace !== normalizedNamespace || !isRecent(entry.value.seenAt, now)) continue;
|
|
644
|
+
remember(normalizedNamespace, entry.value.messageId, entry.value.seenAt);
|
|
645
|
+
loaded++;
|
|
646
|
+
}
|
|
647
|
+
return loaded;
|
|
648
|
+
} catch (error) {
|
|
649
|
+
log?.(`feishu-dedup: warmup persistent state error: ${String(error)}`);
|
|
650
|
+
return 0;
|
|
651
|
+
}
|
|
520
652
|
}
|
|
521
653
|
//#endregion
|
|
522
654
|
//#region extensions/feishu/src/dedupe-key.ts
|
|
@@ -691,7 +823,12 @@ function resolveFeishuReasoningPreviewEnabled(params) {
|
|
|
691
823
|
//#region extensions/feishu/src/streaming-card.ts
|
|
692
824
|
const STREAMING_UPDATE_THROTTLE_MS = 160;
|
|
693
825
|
const STREAMING_SIGNIFICANT_DELTA_CHARS = 18;
|
|
826
|
+
const FEISHU_STREAMING_TOKEN_DEFAULT_LIFETIME_SECONDS = 7200;
|
|
694
827
|
const tokenCache = /* @__PURE__ */ new Map();
|
|
828
|
+
function resolveStreamingTokenExpiresAt(value) {
|
|
829
|
+
if (typeof value === "number" && Number.isFinite(value) && value <= 0) return Date.now();
|
|
830
|
+
return resolveExpiresAtMsFromDurationSeconds(value) ?? Date.now() + FEISHU_STREAMING_TOKEN_DEFAULT_LIFETIME_SECONDS * 1e3;
|
|
831
|
+
}
|
|
695
832
|
function resolveApiBase(domain) {
|
|
696
833
|
if (domain === "lark") return "https://open.larksuite.com/open-apis";
|
|
697
834
|
if (domain && domain !== "feishu" && domain.startsWith("http")) return `${domain.replace(/\/+$/, "")}/open-apis`;
|
|
@@ -735,7 +872,7 @@ async function getToken(creds) {
|
|
|
735
872
|
if (data.code !== 0 || !data.tenant_access_token) throw new Error(`Token error: ${data.msg}`);
|
|
736
873
|
tokenCache.set(key, {
|
|
737
874
|
token: data.tenant_access_token,
|
|
738
|
-
expiresAt:
|
|
875
|
+
expiresAt: resolveStreamingTokenExpiresAt(data.expire)
|
|
739
876
|
});
|
|
740
877
|
return data.tenant_access_token;
|
|
741
878
|
}
|
|
@@ -1975,7 +2112,7 @@ async function handleFeishuMessage(params) {
|
|
|
1975
2112
|
const configAllowFrom = feishuCfg?.allowFrom ?? [];
|
|
1976
2113
|
const rawBroadcastAgents = isGroup ? resolveBroadcastAgents(cfg, ctx.chatId) : null;
|
|
1977
2114
|
const broadcastAgents = rawBroadcastAgents ? uniqueStrings(rawBroadcastAgents.map((id) => normalizeAgentId$2(id))) : null;
|
|
1978
|
-
const messageCreateTimeMs =
|
|
2115
|
+
const messageCreateTimeMs = parseStrictNonNegativeInteger(event.message.create_time) ?? Date.now();
|
|
1979
2116
|
let requireMention = false;
|
|
1980
2117
|
if (isGroup) {
|
|
1981
2118
|
if (groupConfig?.enabled === false) {
|
|
@@ -3360,14 +3497,15 @@ function createFeishuBotMenuHandler(params) {
|
|
|
3360
3497
|
}).then(async (handledMenu) => {
|
|
3361
3498
|
if (handledMenu) {
|
|
3362
3499
|
await recordProcessedFeishuMessage(syntheticMessageId, accountId, log);
|
|
3363
|
-
releaseFeishuMessageProcessing(syntheticMessageId, accountId);
|
|
3364
3500
|
return;
|
|
3365
3501
|
}
|
|
3366
3502
|
return await handleLegacyMenu();
|
|
3367
3503
|
}).catch(async (err) => {
|
|
3368
|
-
if (isFeishuRetryableSyntheticEventError(err))
|
|
3504
|
+
if (isFeishuRetryableSyntheticEventError(err)) await forgetProcessedFeishuMessage(syntheticMessageId, accountId, log);
|
|
3369
3505
|
else await recordProcessedFeishuMessage(syntheticMessageId, accountId, log);
|
|
3370
3506
|
throw err;
|
|
3507
|
+
}).finally(() => {
|
|
3508
|
+
releaseFeishuMessageProcessing(syntheticMessageId, accountId);
|
|
3371
3509
|
});
|
|
3372
3510
|
if (fireAndForget) {
|
|
3373
3511
|
promise.catch((err) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as probeFeishu } from "./probe-
|
|
1
|
+
import { t as probeFeishu } from "./probe-956I34qH.js";
|
|
2
2
|
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
3
|
import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
4
4
|
import { WEBHOOK_ANOMALY_COUNTER_DEFAULTS, WEBHOOK_RATE_LIMIT_DEFAULTS, createFixedWindowRateLimiter, createWebhookAnomalyTracker } from "openclaw/plugin-sdk/webhook-ingress";
|
|
@@ -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-BhMNZBJD.js";
|
|
3
3
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
4
4
|
//#region extensions/feishu/src/async.ts
|
|
5
5
|
const RACE_TIMEOUT = Symbol("race-timeout");
|
package/dist/runtime-api.js
CHANGED
|
@@ -9,6 +9,5 @@ import { DEFAULT_ACCOUNT_ID, buildChannelConfigSchema, createActionGate, createD
|
|
|
9
9
|
import { buildAgentMediaPayload } from "openclaw/plugin-sdk/agent-media-payload";
|
|
10
10
|
import { evaluateSupplementalContextVisibility, filterSupplementalContextItems, resolveChannelContextVisibilityMode } from "openclaw/plugin-sdk/context-visibility-runtime";
|
|
11
11
|
import { readJsonFileWithFallback } from "openclaw/plugin-sdk/json-store";
|
|
12
|
-
import { createPersistentDedupe } from "openclaw/plugin-sdk/persistent-dedupe";
|
|
13
12
|
import { isRequestBodyLimitError, readRequestBodyWithLimit, requestBodyErrorToText } from "openclaw/plugin-sdk/webhook-ingress";
|
|
14
|
-
export { DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE, buildAgentMediaPayload, buildChannelConfigSchema, buildProbeChannelStatusSummary, chunkTextForOutbound, createActionGate, createChannelPairingController, createDedupeCache, createDefaultChannelRuntimeState,
|
|
13
|
+
export { DEFAULT_ACCOUNT_ID, PAIRING_APPROVED_MESSAGE, buildAgentMediaPayload, buildChannelConfigSchema, buildProbeChannelStatusSummary, chunkTextForOutbound, createActionGate, createChannelPairingController, createDedupeCache, createDefaultChannelRuntimeState, createReplyPrefixContext, evaluateSupplementalContextVisibility, filterSupplementalContextItems, isRequestBodyLimitError, loadSessionStore, normalizeAgentId, readJsonFileWithFallback, readRequestBodyWithLimit, requestBodyErrorToText, resolveChannelContextVisibilityMode, resolveSessionStoreEntry, setFeishuRuntime };
|
|
@@ -2,8 +2,9 @@ import { i as resolveReceiveIdType, r as normalizeFeishuTarget } from "./targets
|
|
|
2
2
|
import { c as createFeishuApiError, f as isRecord$1, g as requestFeishuApi, s as resolveFeishuRuntimeAccount } from "./accounts-CXnY5H8g.js";
|
|
3
3
|
import { i as toFeishuSendResult, r as resolveFeishuReceiptKind, t as assertFeishuMessageApiSuccess } from "./send-result-DSTSkRDM.js";
|
|
4
4
|
import { t as getFeishuRuntime } from "./runtime-C5JxBWZp.js";
|
|
5
|
-
import { r as createFeishuClient } from "./client-
|
|
5
|
+
import { r as createFeishuClient } from "./client-BhMNZBJD.js";
|
|
6
6
|
import { isRecord, normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
7
|
+
import { parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
7
8
|
import { convertMarkdownTables } from "openclaw/plugin-sdk/text-chunking";
|
|
8
9
|
import fs from "node:fs";
|
|
9
10
|
import path from "node:path";
|
|
@@ -953,7 +954,7 @@ function parseFeishuMessageItem(item, fallbackMessageId) {
|
|
|
953
954
|
senderType: item.sender?.sender_type,
|
|
954
955
|
content: parseFeishuMessageContent(rawContent, msgType),
|
|
955
956
|
contentType: msgType,
|
|
956
|
-
createTime:
|
|
957
|
+
createTime: parseStrictNonNegativeInteger(item.create_time),
|
|
957
958
|
threadId: item.thread_id || void 0
|
|
958
959
|
};
|
|
959
960
|
}
|
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-BfeesQob.js";
|
|
2
2
|
export { feishuPlugin, feishuSetupAdapter, feishuSetupWizard };
|
package/dist/setup-entry.js
CHANGED
|
@@ -2,10 +2,15 @@ import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entr
|
|
|
2
2
|
//#region extensions/feishu/setup-entry.ts
|
|
3
3
|
var setup_entry_default = defineBundledChannelSetupEntry({
|
|
4
4
|
importMetaUrl: import.meta.url,
|
|
5
|
+
features: { legacyStateMigrations: true },
|
|
5
6
|
plugin: {
|
|
6
7
|
specifier: "./setup-api.js",
|
|
7
8
|
exportName: "feishuPlugin"
|
|
8
9
|
},
|
|
10
|
+
legacyStateMigrations: {
|
|
11
|
+
specifier: "./legacy-state-migrations-api.js",
|
|
12
|
+
exportName: "detectFeishuLegacyStateMigrations"
|
|
13
|
+
},
|
|
9
14
|
secrets: {
|
|
10
15
|
specifier: "./secret-contract-api.js",
|
|
11
16
|
exportName: "channelSecrets"
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/feishu",
|
|
3
|
-
"version": "2026.5.28-beta.
|
|
3
|
+
"version": "2026.5.28-beta.4",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@openclaw/feishu",
|
|
9
|
-
"version": "2026.5.28-beta.
|
|
9
|
+
"version": "2026.5.28-beta.4",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@larksuiteoapi/node-sdk": "1.66.0",
|
|
12
12
|
"typebox": "1.1.38",
|
|
13
13
|
"zod": "4.4.3"
|
|
14
14
|
},
|
|
15
15
|
"peerDependencies": {
|
|
16
|
-
"openclaw": ">=2026.5.28-beta.
|
|
16
|
+
"openclaw": ">=2026.5.28-beta.4"
|
|
17
17
|
},
|
|
18
18
|
"peerDependenciesMeta": {
|
|
19
19
|
"openclaw": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/feishu",
|
|
3
|
-
"version": "2026.5.28-beta.
|
|
3
|
+
"version": "2026.5.28-beta.4",
|
|
4
4
|
"description": "OpenClaw Feishu/Lark channel plugin for chats and workplace tools (community maintained by @m1heng).",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"zod": "4.4.3"
|
|
14
14
|
},
|
|
15
15
|
"peerDependencies": {
|
|
16
|
-
"openclaw": ">=2026.5.28-beta.
|
|
16
|
+
"openclaw": ">=2026.5.28-beta.4"
|
|
17
17
|
},
|
|
18
18
|
"peerDependenciesMeta": {
|
|
19
19
|
"openclaw": {
|
|
@@ -25,6 +25,9 @@
|
|
|
25
25
|
"./index.ts"
|
|
26
26
|
],
|
|
27
27
|
"setupEntry": "./setup-entry.ts",
|
|
28
|
+
"setupFeatures": {
|
|
29
|
+
"legacyStateMigrations": true
|
|
30
|
+
},
|
|
28
31
|
"channel": {
|
|
29
32
|
"id": "feishu",
|
|
30
33
|
"label": "Feishu",
|
|
@@ -41,13 +44,13 @@
|
|
|
41
44
|
"install": {
|
|
42
45
|
"npmSpec": "@openclaw/feishu",
|
|
43
46
|
"defaultChoice": "npm",
|
|
44
|
-
"minHostVersion": ">=2026.
|
|
47
|
+
"minHostVersion": ">=2026.5.29"
|
|
45
48
|
},
|
|
46
49
|
"compat": {
|
|
47
|
-
"pluginApi": ">=2026.5.28-beta.
|
|
50
|
+
"pluginApi": ">=2026.5.28-beta.4"
|
|
48
51
|
},
|
|
49
52
|
"build": {
|
|
50
|
-
"openclawVersion": "2026.5.28-beta.
|
|
53
|
+
"openclawVersion": "2026.5.28-beta.4"
|
|
51
54
|
},
|
|
52
55
|
"release": {
|
|
53
56
|
"publishToClawHub": true,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
|
|
2
2
|
import { createRequire } from "node:module";
|
|
3
|
+
import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
3
4
|
import * as Lark from "@larksuiteoapi/node-sdk";
|
|
4
5
|
import { readPluginPackageVersion, resolveAmbientNodeProxyAgent } from "openclaw/plugin-sdk/extension-shared";
|
|
5
|
-
import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
6
6
|
//#region extensions/feishu/src/client-timeout.ts
|
|
7
7
|
/** Default HTTP timeout for Feishu API requests (30 seconds). */
|
|
8
8
|
const FEISHU_HTTP_TIMEOUT_MS = 3e4;
|