@openclaw/feishu 2026.5.14-beta.2 → 2026.5.16-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +1 -1
- package/dist/{channel-1pldyM9r.js → channel-DLhJC9t0.js} +54 -49
- package/dist/channel-plugin-api.js +1 -1
- package/dist/{channel.runtime-BlJ_XJTS.js → channel.runtime-6Ww4ftMP.js} +2 -2
- package/dist/{monitor-Dfy3D2pM.js → monitor-BGTm4U2e.js} +1 -1
- package/dist/{monitor.account-CT3Skl8y.js → monitor.account-Cn20lZwr.js} +90 -38
- package/dist/{send-DsCQVFOE.js → send-Csj0slBG.js} +3 -1
- package/dist/setup-api.js +1 -1
- package/package.json +4 -4
package/dist/api.js
CHANGED
|
@@ -2,7 +2,7 @@ import { a as parseFeishuTargetId, i as parseFeishuDirectConversationId, n as bu
|
|
|
2
2
|
import { n as createFeishuThreadBindingManager, r as getFeishuThreadBindingManager, t as __testing } from "./thread-bindings-D5kDxq_j.js";
|
|
3
3
|
import { n as handleFeishuSubagentEnded, r as handleFeishuSubagentSpawning, t as handleFeishuSubagentDeliveryTarget } from "./subagent-hooks-BUPKo9Al.js";
|
|
4
4
|
import { r as listEnabledFeishuAccounts } from "./accounts-CP4tDW-z.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-DLhJC9t0.js";
|
|
6
6
|
import { t as getFeishuRuntime } from "./runtime-Cc16UY23.js";
|
|
7
7
|
import { a as jsonToolResult, d as registerFeishuChatTools, f as createFeishuToolClient, m as resolveFeishuToolAccount, n as registerFeishuDriveTools, o as toolExecutionErrorResult, p as resolveAnyEnabledFeishuToolsConfig, s as unknownToolActionResult } from "./drive-Av1h_Lwd.js";
|
|
8
8
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, readStringValue } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
@@ -29,7 +29,7 @@ import { normalizeAccountId as normalizeAccountId$1 } from "openclaw/plugin-sdk/
|
|
|
29
29
|
import { z } from "zod";
|
|
30
30
|
import { buildSecretInputSchema, hasConfiguredSecretInput as hasConfiguredSecretInput$2 } from "openclaw/plugin-sdk/secret-input";
|
|
31
31
|
import { createChannelIngressResolver, defineStableChannelIngressIdentity } from "openclaw/plugin-sdk/channel-ingress-runtime";
|
|
32
|
-
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, formatDocsLink, hasConfiguredSecretInput as hasConfiguredSecretInput$1, mergeAllowFromEntries, patchTopLevelChannelConfigSection, promptSingleChannelSecretInput, splitSetupEntries } from "openclaw/plugin-sdk/setup";
|
|
32
|
+
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, createSetupTranslator, formatDocsLink, hasConfiguredSecretInput as hasConfiguredSecretInput$1, mergeAllowFromEntries, patchTopLevelChannelConfigSection, promptSingleChannelSecretInput, splitSetupEntries } from "openclaw/plugin-sdk/setup";
|
|
33
33
|
//#region extensions/feishu/src/approval-auth.ts
|
|
34
34
|
function normalizeFeishuApproverId(value) {
|
|
35
35
|
const trimmed = normalizeOptionalLowercaseString(normalizeFeishuTarget(String(value)));
|
|
@@ -752,6 +752,7 @@ const feishuSetupAdapter = {
|
|
|
752
752
|
};
|
|
753
753
|
//#endregion
|
|
754
754
|
//#region extensions/feishu/src/setup-surface.ts
|
|
755
|
+
const t = createSetupTranslator();
|
|
755
756
|
const channel = "feishu";
|
|
756
757
|
const SCAN_TO_CREATE_TP = "ob_cli_app";
|
|
757
758
|
function normalizeString(value) {
|
|
@@ -780,6 +781,10 @@ function isFeishuConfigured(cfg) {
|
|
|
780
781
|
});
|
|
781
782
|
return topLevelConfigured || accountConfigured;
|
|
782
783
|
}
|
|
784
|
+
function formatFeishuStatusLine(status) {
|
|
785
|
+
if (status === "needs-credentials") return `Feishu: ${t("wizard.channels.statusNeedsAppCredentials")}`;
|
|
786
|
+
return `Feishu: ${t("wizard.channels.statusConfiguredConnectionNotVerified")}`;
|
|
787
|
+
}
|
|
783
788
|
/**
|
|
784
789
|
* Patch feishu config at the correct location based on accountId.
|
|
785
790
|
* - DEFAULT_ACCOUNT_ID → writes to top-level channels.feishu
|
|
@@ -813,14 +818,14 @@ async function promptFeishuAllowFrom(params) {
|
|
|
813
818
|
const resolvedAccountId = params.accountId ?? resolveDefaultFeishuAccountId(params.cfg);
|
|
814
819
|
const existingAllowFrom = (resolvedAccountId !== DEFAULT_ACCOUNT_ID$1 ? feishuCfg?.accounts?.[resolvedAccountId] : void 0)?.allowFrom ?? feishuCfg?.allowFrom ?? [];
|
|
815
820
|
await params.prompter.note([
|
|
816
|
-
"
|
|
817
|
-
"
|
|
818
|
-
"
|
|
821
|
+
t("wizard.feishu.allowlistIntro"),
|
|
822
|
+
t("wizard.feishu.allowlistFindUser"),
|
|
823
|
+
t("wizard.feishu.examples"),
|
|
819
824
|
"- ou_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
|
820
825
|
"- on_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
821
|
-
].join("\n"), "
|
|
826
|
+
].join("\n"), t("wizard.feishu.allowlistTitle"));
|
|
822
827
|
const mergedAllowFrom = mergeAllowFromEntries(existingAllowFrom, splitSetupEntries(await params.prompter.text({
|
|
823
|
-
message: "
|
|
828
|
+
message: t("wizard.feishu.allowFromPrompt"),
|
|
824
829
|
placeholder: "ou_xxxxx, ou_yyyyy",
|
|
825
830
|
initialValue: existingAllowFrom.length > 0 ? existingAllowFrom.map(String).join(", ") : void 0
|
|
826
831
|
})));
|
|
@@ -828,20 +833,20 @@ async function promptFeishuAllowFrom(params) {
|
|
|
828
833
|
}
|
|
829
834
|
async function noteFeishuCredentialHelp(prompter) {
|
|
830
835
|
await prompter.note([
|
|
831
|
-
"
|
|
832
|
-
"
|
|
833
|
-
"
|
|
834
|
-
"
|
|
835
|
-
"
|
|
836
|
-
"
|
|
837
|
-
|
|
838
|
-
].join("\n"), "
|
|
836
|
+
t("wizard.feishu.credentialsStepOpenPlatform"),
|
|
837
|
+
t("wizard.feishu.credentialsStepCreateApp"),
|
|
838
|
+
t("wizard.feishu.credentialsStepGetCredentials"),
|
|
839
|
+
t("wizard.feishu.credentialsStepPermissions"),
|
|
840
|
+
t("wizard.feishu.credentialsStepPublish"),
|
|
841
|
+
t("wizard.feishu.credentialsEnvTip"),
|
|
842
|
+
t("wizard.channels.docs", { link: formatDocsLink("/channels/feishu", "feishu") })
|
|
843
|
+
].join("\n"), t("wizard.feishu.credentialsTitle"));
|
|
839
844
|
}
|
|
840
845
|
async function promptFeishuAppId(params) {
|
|
841
846
|
return (await params.prompter.text({
|
|
842
|
-
message: "
|
|
847
|
+
message: t("wizard.feishu.appIdPrompt"),
|
|
843
848
|
initialValue: params.initialValue,
|
|
844
|
-
validate: (value) => value?.trim() ? void 0 : "
|
|
849
|
+
validate: (value) => value?.trim() ? void 0 : t("common.required")
|
|
845
850
|
})).trim();
|
|
846
851
|
}
|
|
847
852
|
const feishuDmPolicy = {
|
|
@@ -889,26 +894,26 @@ function applyNewAppSecurityPolicy(cfg, accountId, openId, groupPolicy) {
|
|
|
889
894
|
}
|
|
890
895
|
async function promptFeishuDomain(params) {
|
|
891
896
|
return await params.prompter.select({
|
|
892
|
-
message: "
|
|
897
|
+
message: t("wizard.feishu.domainPrompt"),
|
|
893
898
|
options: [{
|
|
894
899
|
value: "feishu",
|
|
895
|
-
label: "
|
|
900
|
+
label: t("wizard.feishu.domainFeishu")
|
|
896
901
|
}, {
|
|
897
902
|
value: "lark",
|
|
898
|
-
label: "
|
|
903
|
+
label: t("wizard.feishu.domainLark")
|
|
899
904
|
}],
|
|
900
905
|
initialValue: params.initialValue ?? "feishu"
|
|
901
906
|
});
|
|
902
907
|
}
|
|
903
908
|
async function promptFeishuSetupMethod(prompter) {
|
|
904
909
|
return await prompter.select({
|
|
905
|
-
message: "
|
|
910
|
+
message: t("wizard.feishu.setupMethodPrompt"),
|
|
906
911
|
options: [{
|
|
907
912
|
value: "manual",
|
|
908
|
-
label: "
|
|
913
|
+
label: t("wizard.feishu.setupMethodManual")
|
|
909
914
|
}, {
|
|
910
915
|
value: "scan",
|
|
911
|
-
label: "
|
|
916
|
+
label: t("wizard.feishu.setupMethodScan")
|
|
912
917
|
}],
|
|
913
918
|
initialValue: "manual"
|
|
914
919
|
});
|
|
@@ -918,13 +923,13 @@ async function runScanToCreate(prompter, domain) {
|
|
|
918
923
|
try {
|
|
919
924
|
await initAppRegistration(domain);
|
|
920
925
|
} catch {
|
|
921
|
-
await prompter.note("
|
|
926
|
+
await prompter.note(t("wizard.feishu.scanUnavailable"), t("wizard.feishu.setupTitle"));
|
|
922
927
|
return null;
|
|
923
928
|
}
|
|
924
929
|
const begin = await beginAppRegistration(domain);
|
|
925
|
-
await prompter.note("
|
|
930
|
+
await prompter.note(t("wizard.feishu.scanQr"), t("wizard.feishu.scanTitle"));
|
|
926
931
|
await printQrCode(begin.qrUrl);
|
|
927
|
-
const progress = prompter.progress("
|
|
932
|
+
const progress = prompter.progress(t("wizard.feishu.fetchingConfig"));
|
|
928
933
|
const outcome = await pollAppRegistration({
|
|
929
934
|
deviceCode: begin.deviceCode,
|
|
930
935
|
interval: begin.interval,
|
|
@@ -934,19 +939,19 @@ async function runScanToCreate(prompter, domain) {
|
|
|
934
939
|
});
|
|
935
940
|
switch (outcome.status) {
|
|
936
941
|
case "success":
|
|
937
|
-
progress.stop("
|
|
942
|
+
progress.stop(t("wizard.feishu.scanCompleted"));
|
|
938
943
|
return outcome.result;
|
|
939
944
|
case "access_denied":
|
|
940
|
-
progress.stop("
|
|
945
|
+
progress.stop(t("wizard.feishu.scanDenied"));
|
|
941
946
|
return null;
|
|
942
947
|
case "expired":
|
|
943
|
-
progress.stop("
|
|
948
|
+
progress.stop(t("wizard.feishu.scanExpired"));
|
|
944
949
|
return null;
|
|
945
950
|
case "timeout":
|
|
946
|
-
progress.stop("
|
|
951
|
+
progress.stop(t("wizard.feishu.scanTimedOut"));
|
|
947
952
|
return null;
|
|
948
953
|
case "error":
|
|
949
|
-
progress.stop(
|
|
954
|
+
progress.stop(t("wizard.feishu.scanError", { error: outcome.message }));
|
|
950
955
|
return null;
|
|
951
956
|
}
|
|
952
957
|
return null;
|
|
@@ -990,8 +995,8 @@ async function runNewAppFlow(params) {
|
|
|
990
995
|
canUseEnv: false,
|
|
991
996
|
hasConfigToken: false,
|
|
992
997
|
envPrompt: "",
|
|
993
|
-
keepPrompt: "
|
|
994
|
-
inputPrompt: "
|
|
998
|
+
keepPrompt: t("wizard.feishu.appSecretKeep"),
|
|
999
|
+
inputPrompt: t("wizard.feishu.appSecretPrompt"),
|
|
995
1000
|
preferredEnvVar: "FEISHU_APP_SECRET"
|
|
996
1001
|
});
|
|
997
1002
|
if (appSecretResult.action === "set") {
|
|
@@ -1008,24 +1013,24 @@ async function runNewAppFlow(params) {
|
|
|
1008
1013
|
}
|
|
1009
1014
|
}
|
|
1010
1015
|
const groupPolicy = await prompter.select({
|
|
1011
|
-
message: "
|
|
1016
|
+
message: t("wizard.feishu.groupPolicyPrompt"),
|
|
1012
1017
|
options: [
|
|
1013
1018
|
{
|
|
1014
1019
|
value: "allowlist",
|
|
1015
|
-
label: "
|
|
1020
|
+
label: t("wizard.feishu.groupPolicyAllowlist")
|
|
1016
1021
|
},
|
|
1017
1022
|
{
|
|
1018
1023
|
value: "open",
|
|
1019
|
-
label: "
|
|
1024
|
+
label: t("wizard.feishu.groupPolicyOpen")
|
|
1020
1025
|
},
|
|
1021
1026
|
{
|
|
1022
1027
|
value: "disabled",
|
|
1023
|
-
label:
|
|
1028
|
+
label: t("wizard.feishu.groupPolicyDisabled")
|
|
1024
1029
|
}
|
|
1025
1030
|
],
|
|
1026
1031
|
initialValue: "allowlist"
|
|
1027
1032
|
});
|
|
1028
|
-
const configProgress = prompter.progress("
|
|
1033
|
+
const configProgress = prompter.progress(t("wizard.feishu.configuring"));
|
|
1029
1034
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
1030
1035
|
if (appId && appSecret) next = patchFeishuConfig(next, targetAccountId, {
|
|
1031
1036
|
appId,
|
|
@@ -1035,7 +1040,7 @@ async function runNewAppFlow(params) {
|
|
|
1035
1040
|
});
|
|
1036
1041
|
else if (scanDomain) next = patchFeishuConfig(next, targetAccountId, { domain: scanDomain });
|
|
1037
1042
|
next = applyNewAppSecurityPolicy(next, targetAccountId, scanOpenId, groupPolicy);
|
|
1038
|
-
configProgress.stop("
|
|
1043
|
+
configProgress.stop(t("wizard.feishu.botConfigured"));
|
|
1039
1044
|
return { cfg: next };
|
|
1040
1045
|
}
|
|
1041
1046
|
async function runEditFlow(params) {
|
|
@@ -1057,7 +1062,7 @@ async function runEditFlow(params) {
|
|
|
1057
1062
|
}, void 0);
|
|
1058
1063
|
if (existingAppId) {
|
|
1059
1064
|
if (!await prompter.confirm({
|
|
1060
|
-
message:
|
|
1065
|
+
message: t("wizard.feishu.existingBotPrompt", { appId: existingAppId }),
|
|
1061
1066
|
initialValue: true
|
|
1062
1067
|
})) return runNewAppFlow({
|
|
1063
1068
|
cfg: next,
|
|
@@ -1069,7 +1074,7 @@ async function runEditFlow(params) {
|
|
|
1069
1074
|
prompter,
|
|
1070
1075
|
options
|
|
1071
1076
|
});
|
|
1072
|
-
await prompter.note("
|
|
1077
|
+
await prompter.note(t("wizard.feishu.botConfigured"), "");
|
|
1073
1078
|
return { cfg: next };
|
|
1074
1079
|
}
|
|
1075
1080
|
async function runFeishuLogin(params) {
|
|
@@ -1095,10 +1100,10 @@ const feishuSetupWizard = {
|
|
|
1095
1100
|
resolveAccountIdForConfigure: ({ accountOverride, defaultAccountId, cfg }) => (typeof accountOverride === "string" && accountOverride.trim() ? accountOverride.trim() : void 0) ?? resolveDefaultFeishuAccountId(cfg) ?? defaultAccountId,
|
|
1096
1101
|
resolveShouldPromptAccountIds: () => false,
|
|
1097
1102
|
status: {
|
|
1098
|
-
configuredLabel: "
|
|
1099
|
-
unconfiguredLabel: "
|
|
1100
|
-
configuredHint: "
|
|
1101
|
-
unconfiguredHint: "
|
|
1103
|
+
configuredLabel: t("wizard.channels.statusConfigured"),
|
|
1104
|
+
unconfiguredLabel: t("wizard.channels.statusNeedsAppCredentials"),
|
|
1105
|
+
configuredHint: t("wizard.channels.statusConfigured"),
|
|
1106
|
+
unconfiguredHint: t("wizard.channels.statusNeedsAppCreds"),
|
|
1102
1107
|
configuredScore: 2,
|
|
1103
1108
|
unconfiguredScore: 0,
|
|
1104
1109
|
resolveConfigured: ({ cfg }) => isFeishuConfigured(cfg),
|
|
@@ -1112,9 +1117,9 @@ const feishuSetupWizard = {
|
|
|
1112
1117
|
const { probeFeishu } = await import("./probe-DpPNslkb.js").then((n) => n.n);
|
|
1113
1118
|
probeResult = await probeFeishu(account);
|
|
1114
1119
|
} catch {}
|
|
1115
|
-
if (!configured) return ["
|
|
1116
|
-
if (probeResult?.ok) return [`Feishu:
|
|
1117
|
-
return ["
|
|
1120
|
+
if (!configured) return [formatFeishuStatusLine("needs-credentials")];
|
|
1121
|
+
if (probeResult?.ok) return [`Feishu: ${t("wizard.channels.statusConnectedAs", { name: probeResult.botName ?? probeResult.botOpenId ?? "bot" })}`];
|
|
1122
|
+
return [formatFeishuStatusLine("configured-unverified")];
|
|
1118
1123
|
}
|
|
1119
1124
|
},
|
|
1120
1125
|
prepare: async ({ cfg, credentialValues }) => {
|
|
@@ -1183,7 +1188,7 @@ const meta = {
|
|
|
1183
1188
|
aliases: ["lark"],
|
|
1184
1189
|
order: 70
|
|
1185
1190
|
};
|
|
1186
|
-
const loadFeishuChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-
|
|
1191
|
+
const loadFeishuChannelRuntime = createLazyRuntimeNamedExport(() => import("./channel.runtime-6Ww4ftMP.js"), "feishuChannelRuntime");
|
|
1187
1192
|
function toFeishuMessageSendResult(result, kind) {
|
|
1188
1193
|
const receipt = result.receipt ?? createFeishuSendReceipt({
|
|
1189
1194
|
messageId: result.messageId,
|
|
@@ -2026,7 +2031,7 @@ const feishuPlugin = createChatChannelPlugin({
|
|
|
2026
2031
|
})
|
|
2027
2032
|
}),
|
|
2028
2033
|
gateway: { startAccount: async (ctx) => {
|
|
2029
|
-
const { monitorFeishuProvider } = await import("./monitor-
|
|
2034
|
+
const { monitorFeishuProvider } = await import("./monitor-BGTm4U2e.js");
|
|
2030
2035
|
const account = resolveFeishuRuntimeAccount({
|
|
2031
2036
|
cfg: ctx.cfg,
|
|
2032
2037
|
accountId: ctx.accountId
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as feishuPlugin } from "./channel-
|
|
1
|
+
import { t as feishuPlugin } from "./channel-DLhJC9t0.js";
|
|
2
2
|
export { feishuPlugin };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { o as resolveFeishuAccount, s as resolveFeishuRuntimeAccount, y as parseFeishuCommentTarget } from "./accounts-CP4tDW-z.js";
|
|
2
|
-
import { g as listFeishuDirectoryPeers, h as listFeishuDirectoryGroups, v as createFeishuCardInteractionEnvelope } from "./channel-
|
|
2
|
+
import { g as listFeishuDirectoryPeers, h as listFeishuDirectoryGroups, v as createFeishuCardInteractionEnvelope } from "./channel-DLhJC9t0.js";
|
|
3
3
|
import { r as createFeishuClient } from "./client-B18oTGHf.js";
|
|
4
4
|
import { c as getChatInfo, l as getChatMembers, r as cleanupAmbientCommentTypingReaction, t as deliverCommentThreadText, u as getFeishuMemberInfo } from "./drive-Av1h_Lwd.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-
|
|
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-Csj0slBG.js";
|
|
7
7
|
import { t as probeFeishu } from "./probe-DpPNslkb.js";
|
|
8
8
|
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
9
9
|
import { interactiveReplyToPresentation, normalizeInteractiveReply, normalizeMessagePresentation, renderMessagePresentationFallbackText, resolveInteractiveTextFallback } from "openclaw/plugin-sdk/interactive-runtime";
|
|
@@ -3,7 +3,7 @@ import { l as fetchBotIdentityForMonitor } from "./monitor.state-D6ByOM5W.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-Cn20lZwr.js");
|
|
7
7
|
return await monitorAccountRuntimePromise;
|
|
8
8
|
}
|
|
9
9
|
async function monitorFeishuProvider(opts = {}) {
|
|
@@ -2,12 +2,12 @@ import { t as buildFeishuConversationId } from "./conversation-id-Byq1c20x.js";
|
|
|
2
2
|
import { i as resolveReceiveIdType } from "./targets-Bb05cFr4.js";
|
|
3
3
|
import { n as createFeishuThreadBindingManager } from "./thread-bindings-D5kDxq_j.js";
|
|
4
4
|
import { _ as buildFeishuCommentTarget, f as isRecord$3, h as readString$2, l as encodeQuery, m as parseCommentContentElements, p as normalizeString, s as resolveFeishuRuntimeAccount, u as extractReplyText, v as normalizeCommentFileType } from "./accounts-CP4tDW-z.js";
|
|
5
|
-
import { _ as buildFeishuCardActionTextFallback, d as resolveFeishuGroupConfig, f as resolveFeishuGroupConversationIngressAccess, l as hasExplicitFeishuGroupConfig, m as resolveFeishuReplyPolicy, p as resolveFeishuGroupSenderActivationIngressAccess, u as resolveFeishuDmIngressAccess, v as createFeishuCardInteractionEnvelope, y as decodeFeishuCardAction } from "./channel-
|
|
5
|
+
import { _ as buildFeishuCardActionTextFallback, d as resolveFeishuGroupConfig, f as resolveFeishuGroupConversationIngressAccess, l as hasExplicitFeishuGroupConfig, m as resolveFeishuReplyPolicy, p as resolveFeishuGroupSenderActivationIngressAccess, u as resolveFeishuDmIngressAccess, v as createFeishuCardInteractionEnvelope, y as decodeFeishuCardAction } from "./channel-DLhJC9t0.js";
|
|
6
6
|
import { t as getFeishuRuntime } from "./runtime-Cc16UY23.js";
|
|
7
7
|
import { a as getFeishuUserAgent, i as createFeishuWSClient, n as createEventDispatcher, r as createFeishuClient } from "./client-B18oTGHf.js";
|
|
8
8
|
import { c as getChatInfo, i as createCommentTypingReactionLifecycle, t as deliverCommentThreadText } from "./drive-Av1h_Lwd.js";
|
|
9
9
|
import { buildAgentMediaPayload, createReplyPrefixContext, evaluateSupplementalContextVisibility, loadSessionStore, normalizeAgentId as normalizeAgentId$1, resolveChannelContextVisibilityMode, resolveSessionStoreEntry } from "./runtime-api.js";
|
|
10
|
-
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-
|
|
10
|
+
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-Csj0slBG.js";
|
|
11
11
|
import { i as waitForAbortableDelay, r as raceWithTimeoutAndAbort } from "./probe-DpPNslkb.js";
|
|
12
12
|
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-D6ByOM5W.js";
|
|
13
13
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
@@ -29,7 +29,7 @@ import { safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
|
|
|
29
29
|
import * as crypto$1 from "node:crypto";
|
|
30
30
|
import crypto from "node:crypto";
|
|
31
31
|
import { resolveChannelConfigWrites } from "openclaw/plugin-sdk/channel-config-writes";
|
|
32
|
-
import { DEFAULT_GROUP_HISTORY_LIMIT,
|
|
32
|
+
import { DEFAULT_GROUP_HISTORY_LIMIT, createChannelHistoryWindow } from "openclaw/plugin-sdk/reply-history";
|
|
33
33
|
import { resolveDefaultGroupPolicy, resolveOpenProviderRuntimeGroupPolicy, warnMissingProviderGroupPolicyFallbackOnce } from "openclaw/plugin-sdk/runtime-group-policy";
|
|
34
34
|
import { formatReasoningMessage } from "openclaw/plugin-sdk/agent-runtime";
|
|
35
35
|
import { logTypingFailure } from "openclaw/plugin-sdk/channel-feedback";
|
|
@@ -753,6 +753,11 @@ function shouldPushStreamingUpdate(previousText, nextText) {
|
|
|
753
753
|
if (hasNaturalStreamingBoundary(nextText)) return true;
|
|
754
754
|
return nextText.length - previousText.length >= STREAMING_SIGNIFICANT_DELTA_CHARS;
|
|
755
755
|
}
|
|
756
|
+
function resolveStreamingCardAppendContent(previousText, nextText) {
|
|
757
|
+
if (!nextText || nextText === previousText) return "";
|
|
758
|
+
if (!previousText) return nextText;
|
|
759
|
+
return nextText.startsWith(previousText) ? nextText.slice(previousText.length) : nextText;
|
|
760
|
+
}
|
|
756
761
|
function mergeStreamingText(previousText, nextText) {
|
|
757
762
|
const previous = typeof previousText === "string" ? previousText : "";
|
|
758
763
|
const next = typeof nextText === "string" ? nextText : "";
|
|
@@ -790,7 +795,7 @@ var FeishuStreamingSession = class {
|
|
|
790
795
|
const apiBase = resolveApiBase(this.creds.domain);
|
|
791
796
|
const elements = [{
|
|
792
797
|
tag: "markdown",
|
|
793
|
-
content: "
|
|
798
|
+
content: "",
|
|
794
799
|
element_id: "content"
|
|
795
800
|
}];
|
|
796
801
|
if (options?.note) {
|
|
@@ -882,34 +887,82 @@ var FeishuStreamingSession = class {
|
|
|
882
887
|
messageId: sendRes.data.message_id,
|
|
883
888
|
sequence: 1,
|
|
884
889
|
currentText: "",
|
|
890
|
+
sentText: "",
|
|
885
891
|
hasNote: !!options?.note
|
|
886
892
|
};
|
|
887
893
|
this.log?.(`Started streaming: cardId=${cardId}, messageId=${sendRes.data.message_id}`);
|
|
888
894
|
}
|
|
889
895
|
async updateCardContent(text, onError) {
|
|
890
|
-
if (!this.state) return;
|
|
896
|
+
if (!this.state) return false;
|
|
891
897
|
const apiBase = resolveApiBase(this.creds.domain);
|
|
892
898
|
this.state.sequence += 1;
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
899
|
+
try {
|
|
900
|
+
const { response, release } = await fetchWithSsrFGuard({
|
|
901
|
+
url: `${apiBase}/cardkit/v1/cards/${this.state.cardId}/elements/content/content`,
|
|
902
|
+
init: {
|
|
903
|
+
method: "PUT",
|
|
904
|
+
headers: {
|
|
905
|
+
Authorization: `Bearer ${await getToken(this.creds)}`,
|
|
906
|
+
"Content-Type": "application/json",
|
|
907
|
+
"User-Agent": getFeishuUserAgent()
|
|
908
|
+
},
|
|
909
|
+
body: JSON.stringify({
|
|
910
|
+
content: text,
|
|
911
|
+
sequence: this.state.sequence,
|
|
912
|
+
uuid: `s_${this.state.cardId}_${this.state.sequence}`
|
|
913
|
+
})
|
|
901
914
|
},
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
uuid: `s_${this.state.cardId}_${this.state.sequence}`
|
|
906
|
-
})
|
|
907
|
-
},
|
|
908
|
-
policy: { allowedHostnames: resolveAllowedHostnames(this.creds.domain) },
|
|
909
|
-
auditContext: "feishu.streaming-card.update"
|
|
910
|
-
}).then(async ({ release }) => {
|
|
915
|
+
policy: { allowedHostnames: resolveAllowedHostnames(this.creds.domain) },
|
|
916
|
+
auditContext: "feishu.streaming-card.update"
|
|
917
|
+
});
|
|
911
918
|
await release();
|
|
912
|
-
|
|
919
|
+
if (!response.ok) {
|
|
920
|
+
onError?.(/* @__PURE__ */ new Error(`Update card content failed with HTTP ${response.status}`));
|
|
921
|
+
return false;
|
|
922
|
+
}
|
|
923
|
+
return true;
|
|
924
|
+
} catch (error) {
|
|
925
|
+
onError?.(error);
|
|
926
|
+
return false;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
async replaceCardContent(text, onError) {
|
|
930
|
+
if (!this.state) return false;
|
|
931
|
+
const apiBase = resolveApiBase(this.creds.domain);
|
|
932
|
+
this.state.sequence += 1;
|
|
933
|
+
try {
|
|
934
|
+
const { response, release } = await fetchWithSsrFGuard({
|
|
935
|
+
url: `${apiBase}/cardkit/v1/cards/${this.state.cardId}/elements/content`,
|
|
936
|
+
init: {
|
|
937
|
+
method: "PUT",
|
|
938
|
+
headers: {
|
|
939
|
+
Authorization: `Bearer ${await getToken(this.creds)}`,
|
|
940
|
+
"Content-Type": "application/json",
|
|
941
|
+
"User-Agent": getFeishuUserAgent()
|
|
942
|
+
},
|
|
943
|
+
body: JSON.stringify({
|
|
944
|
+
element: JSON.stringify({
|
|
945
|
+
tag: "markdown",
|
|
946
|
+
content: text,
|
|
947
|
+
element_id: "content"
|
|
948
|
+
}),
|
|
949
|
+
sequence: this.state.sequence,
|
|
950
|
+
uuid: `r_${this.state.cardId}_${this.state.sequence}`
|
|
951
|
+
})
|
|
952
|
+
},
|
|
953
|
+
policy: { allowedHostnames: resolveAllowedHostnames(this.creds.domain) },
|
|
954
|
+
auditContext: "feishu.streaming-card.replace"
|
|
955
|
+
});
|
|
956
|
+
await release();
|
|
957
|
+
if (!response.ok) {
|
|
958
|
+
onError?.(/* @__PURE__ */ new Error(`Replace card content failed with HTTP ${response.status}`));
|
|
959
|
+
return false;
|
|
960
|
+
}
|
|
961
|
+
return true;
|
|
962
|
+
} catch (error) {
|
|
963
|
+
onError?.(error);
|
|
964
|
+
return false;
|
|
965
|
+
}
|
|
913
966
|
}
|
|
914
967
|
clearFlushTimer() {
|
|
915
968
|
if (this.flushTimer) {
|
|
@@ -945,9 +998,11 @@ var FeishuStreamingSession = class {
|
|
|
945
998
|
const nextText = this.pendingText ?? mergedInput;
|
|
946
999
|
const mergedText = mergeStreamingText(this.state.currentText, nextText);
|
|
947
1000
|
if (!mergedText || mergedText === this.state.currentText) return;
|
|
1001
|
+
const appendContent = resolveStreamingCardAppendContent(this.state.sentText, mergedText);
|
|
1002
|
+
if (!appendContent) return;
|
|
948
1003
|
this.pendingText = null;
|
|
949
1004
|
this.state.currentText = mergedText;
|
|
950
|
-
await this.updateCardContent(
|
|
1005
|
+
if (await this.updateCardContent(appendContent, (e) => this.log?.(`Update failed: ${String(e)}`)) && this.state) this.state.sentText = mergedText;
|
|
951
1006
|
});
|
|
952
1007
|
await this.queue;
|
|
953
1008
|
}
|
|
@@ -982,11 +1037,12 @@ var FeishuStreamingSession = class {
|
|
|
982
1037
|
this.clearFlushTimer();
|
|
983
1038
|
await this.queue;
|
|
984
1039
|
const pendingMerged = mergeStreamingText(this.state.currentText, this.pendingText ?? void 0);
|
|
985
|
-
const text = finalText
|
|
1040
|
+
const text = finalText ?? pendingMerged;
|
|
986
1041
|
const apiBase = resolveApiBase(this.creds.domain);
|
|
987
|
-
if (text && text !== this.state.
|
|
988
|
-
await this.updateCardContent(text);
|
|
1042
|
+
if (text && text !== this.state.sentText) {
|
|
1043
|
+
const sent = text.startsWith(this.state.sentText) ? await this.updateCardContent(resolveStreamingCardAppendContent(this.state.sentText, text), (e) => this.log?.(`Final update failed: ${String(e)}`)) : await this.replaceCardContent(text, (e) => this.log?.(`Final replace failed: ${String(e)}`));
|
|
989
1044
|
this.state.currentText = text;
|
|
1045
|
+
if (sent) this.state.sentText = text;
|
|
990
1046
|
}
|
|
991
1047
|
if (options?.note) await this.updateNoteContent(options.note);
|
|
992
1048
|
this.state.sequence += 1;
|
|
@@ -1978,8 +2034,7 @@ async function handleFeishuMessage(params) {
|
|
|
1978
2034
|
}
|
|
1979
2035
|
if (groupSenderActivationIngress.ingress.admission !== "dispatch") {
|
|
1980
2036
|
log(`feishu[${account.accountId}]: message in group ${ctx.chatId} did not mention bot`);
|
|
1981
|
-
if (!broadcastAgents && chatHistories && groupHistoryKey)
|
|
1982
|
-
historyMap: chatHistories,
|
|
2037
|
+
if (!broadcastAgents && chatHistories && groupHistoryKey) createChannelHistoryWindow({ historyMap: chatHistories }).record({
|
|
1983
2038
|
historyKey: groupHistoryKey,
|
|
1984
2039
|
limit: historyLimit,
|
|
1985
2040
|
entry: {
|
|
@@ -2238,8 +2293,7 @@ async function handleFeishuMessage(params) {
|
|
|
2238
2293
|
body: messageBody
|
|
2239
2294
|
});
|
|
2240
2295
|
const historyKey = groupHistoryKey;
|
|
2241
|
-
if (isGroup && historyKey && chatHistories) combinedBody =
|
|
2242
|
-
historyMap: chatHistories,
|
|
2296
|
+
if (isGroup && historyKey && chatHistories) combinedBody = createChannelHistoryWindow({ historyMap: chatHistories }).buildPendingContext({
|
|
2243
2297
|
historyKey,
|
|
2244
2298
|
limit: historyLimit,
|
|
2245
2299
|
currentMessage: combinedBody,
|
|
@@ -2251,11 +2305,10 @@ async function handleFeishuMessage(params) {
|
|
|
2251
2305
|
envelope: envelopeOptions
|
|
2252
2306
|
})
|
|
2253
2307
|
});
|
|
2254
|
-
const inboundHistory = isGroup && historyKey && historyLimit > 0 && chatHistories ? (chatHistories
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
})) : void 0;
|
|
2308
|
+
const inboundHistory = isGroup && historyKey && historyLimit > 0 && chatHistories ? createChannelHistoryWindow({ historyMap: chatHistories }).buildInboundHistory({
|
|
2309
|
+
historyKey,
|
|
2310
|
+
limit: historyLimit
|
|
2311
|
+
}) : void 0;
|
|
2259
2312
|
const threadContextBySessionKey = /* @__PURE__ */ new Map();
|
|
2260
2313
|
let rootMessageInfo;
|
|
2261
2314
|
let rootMessageThreadId;
|
|
@@ -2559,8 +2612,7 @@ async function handleFeishuMessage(params) {
|
|
|
2559
2612
|
const results = await Promise.allSettled(broadcastAgents.map(dispatchForAgent));
|
|
2560
2613
|
for (let i = 0; i < results.length; i++) if (results[i].status === "rejected") log(`feishu[${account.accountId}]: broadcast dispatch failed for agent=${broadcastAgents[i]}: ${String(results[i].reason)}`);
|
|
2561
2614
|
}
|
|
2562
|
-
if (isGroup && historyKey && chatHistories)
|
|
2563
|
-
historyMap: chatHistories,
|
|
2615
|
+
if (isGroup && historyKey && chatHistories) createChannelHistoryWindow({ historyMap: chatHistories }).clear({
|
|
2564
2616
|
historyKey,
|
|
2565
2617
|
limit: historyLimit
|
|
2566
2618
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as resolveReceiveIdType, r as normalizeFeishuTarget } from "./targets-Bb05cFr4.js";
|
|
2
2
|
import { c as createFeishuApiError, f as isRecord$2, g as requestFeishuApi, s as resolveFeishuRuntimeAccount } from "./accounts-CP4tDW-z.js";
|
|
3
|
-
import { c as toFeishuSendResult, o as assertFeishuMessageApiSuccess, s as resolveFeishuReceiptKind } from "./channel-
|
|
3
|
+
import { c as toFeishuSendResult, o as assertFeishuMessageApiSuccess, s as resolveFeishuReceiptKind } from "./channel-DLhJC9t0.js";
|
|
4
4
|
import { t as getFeishuRuntime } from "./runtime-Cc16UY23.js";
|
|
5
5
|
import { r as createFeishuClient } from "./client-B18oTGHf.js";
|
|
6
6
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
@@ -455,6 +455,8 @@ async function transcodeToFeishuVoiceOpus(params) {
|
|
|
455
455
|
"libopus",
|
|
456
456
|
"-b:a",
|
|
457
457
|
FEISHU_VOICE_BITRATE,
|
|
458
|
+
"-f",
|
|
459
|
+
"ogg",
|
|
458
460
|
outputPath
|
|
459
461
|
]);
|
|
460
462
|
}
|
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-DLhJC9t0.js";
|
|
2
2
|
export { feishuPlugin, feishuSetupAdapter, feishuSetupWizard };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/feishu",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.16-beta.2",
|
|
4
4
|
"description": "OpenClaw Feishu/Lark channel plugin (community maintained by @m1heng)",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"openclaw": "workspace:*"
|
|
18
18
|
},
|
|
19
19
|
"peerDependencies": {
|
|
20
|
-
"openclaw": ">=2026.5.
|
|
20
|
+
"openclaw": ">=2026.5.16-beta.2"
|
|
21
21
|
},
|
|
22
22
|
"peerDependenciesMeta": {
|
|
23
23
|
"openclaw": {
|
|
@@ -48,10 +48,10 @@
|
|
|
48
48
|
"minHostVersion": ">=2026.4.25"
|
|
49
49
|
},
|
|
50
50
|
"compat": {
|
|
51
|
-
"pluginApi": ">=2026.5.
|
|
51
|
+
"pluginApi": ">=2026.5.16-beta.2"
|
|
52
52
|
},
|
|
53
53
|
"build": {
|
|
54
|
-
"openclawVersion": "2026.5.
|
|
54
|
+
"openclawVersion": "2026.5.16-beta.2"
|
|
55
55
|
},
|
|
56
56
|
"release": {
|
|
57
57
|
"publishToClawHub": true,
|