@openclaw/feishu 2026.5.2 → 2026.5.3-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/accounts-Ba3-WP1z.js +423 -0
- package/dist/api.js +2280 -0
- package/dist/app-registration-B8qc1MCM.js +184 -0
- package/dist/audio-preflight.runtime-BPlzkO3l.js +7 -0
- package/dist/card-interaction-BfRLgvw_.js +96 -0
- package/dist/channel-CSD_Jt8I.js +1668 -0
- package/dist/channel-entry.js +22 -0
- package/dist/channel-plugin-api.js +2 -0
- package/dist/channel.runtime-DYsXcD36.js +700 -0
- package/dist/client-DBVoQL5w.js +157 -0
- package/dist/contract-api.js +9 -0
- package/dist/conversation-id-DWS3Ep2A.js +139 -0
- package/dist/directory.static-f3EeoRJd.js +44 -0
- package/dist/drive-C5eJLJr7.js +883 -0
- package/dist/index.js +68 -0
- package/dist/monitor-CT189QfR.js +60 -0
- package/dist/monitor.account-dJV2jO8C.js +4990 -0
- package/dist/monitor.state-DYM02ipp.js +100 -0
- package/dist/policy-D6c-wMPl.js +118 -0
- package/dist/probe-BNzzU_uR.js +149 -0
- package/dist/rolldown-runtime-DUslC3ob.js +14 -0
- package/dist/runtime-CG0DuRCy.js +8 -0
- package/dist/runtime-api.js +14 -0
- package/dist/secret-contract-Dm4Z_zQN.js +119 -0
- package/dist/secret-contract-api.js +2 -0
- package/dist/security-audit-DqJdocrN.js +11 -0
- package/dist/security-audit-shared-ByuMx9cJ.js +38 -0
- package/dist/security-contract-api.js +2 -0
- package/dist/send-DowxxbpH.js +1218 -0
- package/dist/session-conversation-B4nrW-vo.js +27 -0
- package/dist/session-key-api.js +2 -0
- package/dist/setup-api.js +2 -0
- package/dist/setup-entry.js +15 -0
- package/dist/subagent-hooks-C3UhPVLV.js +227 -0
- package/dist/subagent-hooks-api.js +23 -0
- package/dist/targets-JMFJRKSe.js +48 -0
- package/dist/thread-bindings-BmS6TLes.js +222 -0
- package/package.json +15 -6
- package/api.ts +0 -31
- package/channel-entry.ts +0 -20
- package/channel-plugin-api.ts +0 -1
- package/contract-api.ts +0 -16
- package/index.ts +0 -82
- package/runtime-api.ts +0 -55
- package/secret-contract-api.ts +0 -5
- package/security-contract-api.ts +0 -1
- package/session-key-api.ts +0 -1
- package/setup-api.ts +0 -3
- package/setup-entry.test.ts +0 -14
- package/setup-entry.ts +0 -13
- package/src/accounts.test.ts +0 -459
- package/src/accounts.ts +0 -326
- package/src/app-registration.ts +0 -331
- package/src/approval-auth.test.ts +0 -24
- package/src/approval-auth.ts +0 -25
- package/src/async.test.ts +0 -35
- package/src/async.ts +0 -104
- package/src/audio-preflight.runtime.ts +0 -9
- package/src/bitable.test.ts +0 -131
- package/src/bitable.ts +0 -762
- package/src/bot-content.ts +0 -474
- package/src/bot-group-name.test.ts +0 -108
- package/src/bot-runtime-api.ts +0 -12
- package/src/bot-sender-name.ts +0 -125
- package/src/bot.broadcast.test.ts +0 -463
- package/src/bot.card-action.test.ts +0 -577
- package/src/bot.checkBotMentioned.test.ts +0 -265
- package/src/bot.helpers.test.ts +0 -118
- package/src/bot.stripBotMention.test.ts +0 -126
- package/src/bot.test.ts +0 -3040
- package/src/bot.ts +0 -1559
- package/src/card-action.ts +0 -447
- package/src/card-interaction.test.ts +0 -129
- package/src/card-interaction.ts +0 -159
- package/src/card-test-helpers.ts +0 -47
- package/src/card-ux-approval.ts +0 -65
- package/src/card-ux-launcher.test.ts +0 -99
- package/src/card-ux-launcher.ts +0 -121
- package/src/card-ux-shared.ts +0 -33
- package/src/channel-runtime-api.ts +0 -16
- package/src/channel.runtime.ts +0 -47
- package/src/channel.test.ts +0 -959
- package/src/channel.ts +0 -1313
- package/src/chat-schema.ts +0 -25
- package/src/chat.test.ts +0 -196
- package/src/chat.ts +0 -188
- package/src/client.test.ts +0 -433
- package/src/client.ts +0 -290
- package/src/comment-dispatcher-runtime-api.ts +0 -6
- package/src/comment-dispatcher.test.ts +0 -169
- package/src/comment-dispatcher.ts +0 -107
- package/src/comment-handler-runtime-api.ts +0 -3
- package/src/comment-handler.test.ts +0 -486
- package/src/comment-handler.ts +0 -309
- package/src/comment-reaction.test.ts +0 -166
- package/src/comment-reaction.ts +0 -259
- package/src/comment-shared.test.ts +0 -182
- package/src/comment-shared.ts +0 -406
- package/src/comment-target.ts +0 -44
- package/src/config-schema.test.ts +0 -309
- package/src/config-schema.ts +0 -333
- package/src/conversation-id.test.ts +0 -18
- package/src/conversation-id.ts +0 -199
- package/src/dedup-runtime-api.ts +0 -1
- package/src/dedup.ts +0 -141
- package/src/directory.static.ts +0 -61
- package/src/directory.test.ts +0 -136
- package/src/directory.ts +0 -124
- package/src/doc-schema.ts +0 -182
- package/src/docx-batch-insert.test.ts +0 -91
- package/src/docx-batch-insert.ts +0 -223
- package/src/docx-color-text.ts +0 -154
- package/src/docx-table-ops.test.ts +0 -53
- package/src/docx-table-ops.ts +0 -316
- package/src/docx-types.ts +0 -38
- package/src/docx.account-selection.test.ts +0 -79
- package/src/docx.test.ts +0 -685
- package/src/docx.ts +0 -1616
- package/src/drive-schema.ts +0 -92
- package/src/drive.test.ts +0 -1219
- package/src/drive.ts +0 -829
- package/src/dynamic-agent.ts +0 -137
- package/src/event-types.ts +0 -45
- package/src/external-keys.test.ts +0 -20
- package/src/external-keys.ts +0 -19
- package/src/lifecycle.test-support.ts +0 -220
- package/src/media.test.ts +0 -900
- package/src/media.ts +0 -861
- package/src/mention-target.types.ts +0 -5
- package/src/mention.ts +0 -114
- package/src/message-action-contract.ts +0 -13
- package/src/monitor-state-runtime-api.ts +0 -7
- package/src/monitor-transport-runtime-api.ts +0 -7
- package/src/monitor.account.ts +0 -468
- package/src/monitor.acp-init-failure.lifecycle.test-support.ts +0 -219
- package/src/monitor.bot-identity.ts +0 -86
- package/src/monitor.bot-menu-handler.ts +0 -165
- package/src/monitor.bot-menu.lifecycle.test-support.ts +0 -224
- package/src/monitor.bot-menu.test.ts +0 -178
- package/src/monitor.broadcast.reply-once.lifecycle.test-support.ts +0 -264
- package/src/monitor.card-action.lifecycle.test-support.ts +0 -373
- package/src/monitor.cleanup.test.ts +0 -376
- package/src/monitor.comment-notice-handler.ts +0 -105
- package/src/monitor.comment.test.ts +0 -937
- package/src/monitor.comment.ts +0 -1386
- package/src/monitor.lifecycle.test.ts +0 -4
- package/src/monitor.message-handler.ts +0 -339
- package/src/monitor.reaction.lifecycle.test-support.ts +0 -68
- package/src/monitor.reaction.test.ts +0 -713
- package/src/monitor.startup.test.ts +0 -192
- package/src/monitor.startup.ts +0 -74
- package/src/monitor.state.defaults.test.ts +0 -46
- package/src/monitor.state.ts +0 -170
- package/src/monitor.synthetic-error.ts +0 -18
- package/src/monitor.test-mocks.ts +0 -45
- package/src/monitor.transport.ts +0 -424
- package/src/monitor.ts +0 -100
- package/src/monitor.webhook-e2e.test.ts +0 -272
- package/src/monitor.webhook-security.test.ts +0 -264
- package/src/monitor.webhook.test-helpers.ts +0 -116
- package/src/outbound-runtime-api.ts +0 -1
- package/src/outbound.test.ts +0 -935
- package/src/outbound.ts +0 -718
- package/src/perm-schema.ts +0 -52
- package/src/perm.ts +0 -170
- package/src/pins.ts +0 -108
- package/src/policy.test.ts +0 -334
- package/src/policy.ts +0 -236
- package/src/post.test.ts +0 -105
- package/src/post.ts +0 -275
- package/src/probe.test.ts +0 -275
- package/src/probe.ts +0 -166
- package/src/processing-claims.ts +0 -59
- package/src/qr-terminal.ts +0 -1
- package/src/reactions.ts +0 -123
- package/src/reasoning-preview.test.ts +0 -59
- package/src/reasoning-preview.ts +0 -20
- package/src/reply-dispatcher-runtime-api.ts +0 -7
- package/src/reply-dispatcher.test.ts +0 -1144
- package/src/reply-dispatcher.ts +0 -650
- package/src/runtime.ts +0 -9
- package/src/secret-contract.ts +0 -145
- package/src/secret-input.ts +0 -1
- package/src/security-audit-shared.ts +0 -69
- package/src/security-audit.test.ts +0 -61
- package/src/security-audit.ts +0 -1
- package/src/send-result.ts +0 -29
- package/src/send-target.test.ts +0 -80
- package/src/send-target.ts +0 -35
- package/src/send.reply-fallback.test.ts +0 -292
- package/src/send.test.ts +0 -550
- package/src/send.ts +0 -800
- package/src/sequential-key.test.ts +0 -72
- package/src/sequential-key.ts +0 -28
- package/src/sequential-queue.test.ts +0 -92
- package/src/sequential-queue.ts +0 -16
- package/src/session-conversation.ts +0 -42
- package/src/session-route.ts +0 -48
- package/src/setup-core.ts +0 -51
- package/src/setup-surface.test.ts +0 -174
- package/src/setup-surface.ts +0 -581
- package/src/streaming-card.test.ts +0 -190
- package/src/streaming-card.ts +0 -490
- package/src/subagent-hooks.test.ts +0 -603
- package/src/subagent-hooks.ts +0 -397
- package/src/targets.ts +0 -97
- package/src/test-support/lifecycle-test-support.ts +0 -453
- package/src/thread-bindings.test.ts +0 -143
- package/src/thread-bindings.ts +0 -330
- package/src/tool-account-routing.test.ts +0 -187
- package/src/tool-account.test.ts +0 -44
- package/src/tool-account.ts +0 -93
- package/src/tool-factory-test-harness.ts +0 -79
- package/src/tool-result.test.ts +0 -32
- package/src/tool-result.ts +0 -16
- package/src/tools-config.test.ts +0 -21
- package/src/tools-config.ts +0 -22
- package/src/types.ts +0 -104
- package/src/typing.test.ts +0 -144
- package/src/typing.ts +0 -214
- package/src/wiki-schema.ts +0 -55
- package/src/wiki.ts +0 -227
- package/subagent-hooks-api.ts +0 -31
- package/tsconfig.json +0 -16
package/contract-api.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export { createFeishuThreadBindingManager } from "./src/thread-bindings.js";
|
|
2
|
-
export { __testing as feishuThreadBindingTesting } from "./src/thread-bindings.js";
|
|
3
|
-
export {
|
|
4
|
-
collectRuntimeConfigAssignments,
|
|
5
|
-
secretTargetRegistryEntries,
|
|
6
|
-
} from "./src/secret-contract.js";
|
|
7
|
-
export { collectFeishuSecurityAuditFindings } from "./src/security-audit.js";
|
|
8
|
-
export { messageActionTargetAliases } from "./src/message-action-contract.js";
|
|
9
|
-
export {
|
|
10
|
-
buildFeishuConversationId,
|
|
11
|
-
parseFeishuConversationId,
|
|
12
|
-
parseFeishuDirectConversationId,
|
|
13
|
-
parseFeishuTargetId,
|
|
14
|
-
} from "./src/conversation-id.js";
|
|
15
|
-
|
|
16
|
-
export const feishuSessionBindingAdapterChannels = ["feishu"] as const;
|
package/index.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
defineBundledChannelEntry,
|
|
3
|
-
loadBundledEntryExportSync,
|
|
4
|
-
} from "openclaw/plugin-sdk/channel-entry-contract";
|
|
5
|
-
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/channel-entry-contract";
|
|
6
|
-
import { registerFeishuSubagentHooks } from "./subagent-hooks-api.js";
|
|
7
|
-
|
|
8
|
-
function registerFeishuDocTools(api: OpenClawPluginApi) {
|
|
9
|
-
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
|
10
|
-
specifier: "./api.js",
|
|
11
|
-
exportName: "registerFeishuDocTools",
|
|
12
|
-
});
|
|
13
|
-
register(api);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function registerFeishuChatTools(api: OpenClawPluginApi) {
|
|
17
|
-
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
|
18
|
-
specifier: "./api.js",
|
|
19
|
-
exportName: "registerFeishuChatTools",
|
|
20
|
-
});
|
|
21
|
-
register(api);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function registerFeishuWikiTools(api: OpenClawPluginApi) {
|
|
25
|
-
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
|
26
|
-
specifier: "./api.js",
|
|
27
|
-
exportName: "registerFeishuWikiTools",
|
|
28
|
-
});
|
|
29
|
-
register(api);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function registerFeishuDriveTools(api: OpenClawPluginApi) {
|
|
33
|
-
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
|
34
|
-
specifier: "./api.js",
|
|
35
|
-
exportName: "registerFeishuDriveTools",
|
|
36
|
-
});
|
|
37
|
-
register(api);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function registerFeishuPermTools(api: OpenClawPluginApi) {
|
|
41
|
-
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
|
42
|
-
specifier: "./api.js",
|
|
43
|
-
exportName: "registerFeishuPermTools",
|
|
44
|
-
});
|
|
45
|
-
register(api);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function registerFeishuBitableTools(api: OpenClawPluginApi) {
|
|
49
|
-
const register = loadBundledEntryExportSync<(api: OpenClawPluginApi) => void>(import.meta.url, {
|
|
50
|
-
specifier: "./api.js",
|
|
51
|
-
exportName: "registerFeishuBitableTools",
|
|
52
|
-
});
|
|
53
|
-
register(api);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export default defineBundledChannelEntry({
|
|
57
|
-
id: "feishu",
|
|
58
|
-
name: "Feishu",
|
|
59
|
-
description: "Feishu/Lark channel plugin",
|
|
60
|
-
importMetaUrl: import.meta.url,
|
|
61
|
-
plugin: {
|
|
62
|
-
specifier: "./channel-plugin-api.js",
|
|
63
|
-
exportName: "feishuPlugin",
|
|
64
|
-
},
|
|
65
|
-
secrets: {
|
|
66
|
-
specifier: "./secret-contract-api.js",
|
|
67
|
-
exportName: "channelSecrets",
|
|
68
|
-
},
|
|
69
|
-
runtime: {
|
|
70
|
-
specifier: "./runtime-api.js",
|
|
71
|
-
exportName: "setFeishuRuntime",
|
|
72
|
-
},
|
|
73
|
-
registerFull(api) {
|
|
74
|
-
registerFeishuSubagentHooks(api);
|
|
75
|
-
registerFeishuDocTools(api);
|
|
76
|
-
registerFeishuChatTools(api);
|
|
77
|
-
registerFeishuWikiTools(api);
|
|
78
|
-
registerFeishuDriveTools(api);
|
|
79
|
-
registerFeishuPermTools(api);
|
|
80
|
-
registerFeishuBitableTools(api);
|
|
81
|
-
},
|
|
82
|
-
});
|
package/runtime-api.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
// Private runtime barrel for the bundled Feishu extension.
|
|
2
|
-
// Keep this barrel thin and generic-only.
|
|
3
|
-
|
|
4
|
-
export type {
|
|
5
|
-
AllowlistMatch,
|
|
6
|
-
AnyAgentTool,
|
|
7
|
-
BaseProbeResult,
|
|
8
|
-
ChannelGroupContext,
|
|
9
|
-
ChannelMessageActionName,
|
|
10
|
-
ChannelMeta,
|
|
11
|
-
ChannelOutboundAdapter,
|
|
12
|
-
ChannelPlugin,
|
|
13
|
-
HistoryEntry,
|
|
14
|
-
OpenClawConfig,
|
|
15
|
-
OpenClawPluginApi,
|
|
16
|
-
OutboundIdentity,
|
|
17
|
-
PluginRuntime,
|
|
18
|
-
ReplyPayload,
|
|
19
|
-
} from "openclaw/plugin-sdk/core";
|
|
20
|
-
export type { OpenClawConfig as ClawdbotConfig } from "openclaw/plugin-sdk/core";
|
|
21
|
-
export type { RuntimeEnv } from "openclaw/plugin-sdk/runtime";
|
|
22
|
-
export type { GroupToolPolicyConfig } from "openclaw/plugin-sdk/config-types";
|
|
23
|
-
export {
|
|
24
|
-
DEFAULT_ACCOUNT_ID,
|
|
25
|
-
buildChannelConfigSchema,
|
|
26
|
-
createActionGate,
|
|
27
|
-
createDedupeCache,
|
|
28
|
-
} from "openclaw/plugin-sdk/core";
|
|
29
|
-
export {
|
|
30
|
-
PAIRING_APPROVED_MESSAGE,
|
|
31
|
-
buildProbeChannelStatusSummary,
|
|
32
|
-
createDefaultChannelRuntimeState,
|
|
33
|
-
} from "openclaw/plugin-sdk/channel-status";
|
|
34
|
-
export { buildAgentMediaPayload } from "openclaw/plugin-sdk/agent-media-payload";
|
|
35
|
-
export { createChannelPairingController } from "openclaw/plugin-sdk/channel-pairing";
|
|
36
|
-
export { createReplyPrefixContext } from "openclaw/plugin-sdk/channel-reply-pipeline";
|
|
37
|
-
export {
|
|
38
|
-
evaluateSupplementalContextVisibility,
|
|
39
|
-
filterSupplementalContextItems,
|
|
40
|
-
resolveChannelContextVisibilityMode,
|
|
41
|
-
} from "openclaw/plugin-sdk/context-visibility-runtime";
|
|
42
|
-
export {
|
|
43
|
-
loadSessionStore,
|
|
44
|
-
resolveSessionStoreEntry,
|
|
45
|
-
} from "openclaw/plugin-sdk/session-store-runtime";
|
|
46
|
-
export { readJsonFileWithFallback } from "openclaw/plugin-sdk/json-store";
|
|
47
|
-
export { createPersistentDedupe } from "openclaw/plugin-sdk/persistent-dedupe";
|
|
48
|
-
export { normalizeAgentId } from "openclaw/plugin-sdk/routing";
|
|
49
|
-
export { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking";
|
|
50
|
-
export {
|
|
51
|
-
isRequestBodyLimitError,
|
|
52
|
-
readRequestBodyWithLimit,
|
|
53
|
-
requestBodyErrorToText,
|
|
54
|
-
} from "openclaw/plugin-sdk/webhook-ingress";
|
|
55
|
-
export { setFeishuRuntime } from "./src/runtime.js";
|
package/secret-contract-api.ts
DELETED
package/security-contract-api.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { collectFeishuSecurityAuditFindings } from "./src/security-audit-shared.js";
|
package/session-key-api.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { resolveFeishuSessionConversation as resolveSessionConversation } from "./src/session-conversation.js";
|
package/setup-api.ts
DELETED
package/setup-entry.test.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from "vitest";
|
|
2
|
-
|
|
3
|
-
vi.mock("@larksuiteoapi/node-sdk", () => {
|
|
4
|
-
throw new Error("setup entry must not load the Feishu SDK");
|
|
5
|
-
});
|
|
6
|
-
|
|
7
|
-
describe("feishu setup entry", () => {
|
|
8
|
-
it("declares the setup entry without importing Feishu runtime dependencies", async () => {
|
|
9
|
-
const { default: setupEntry } = await import("./setup-entry.js");
|
|
10
|
-
|
|
11
|
-
expect(setupEntry.kind).toBe("bundled-channel-setup-entry");
|
|
12
|
-
expect(typeof setupEntry.loadSetupPlugin).toBe("function");
|
|
13
|
-
});
|
|
14
|
-
});
|
package/setup-entry.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { defineBundledChannelSetupEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
|
2
|
-
|
|
3
|
-
export default defineBundledChannelSetupEntry({
|
|
4
|
-
importMetaUrl: import.meta.url,
|
|
5
|
-
plugin: {
|
|
6
|
-
specifier: "./setup-api.js",
|
|
7
|
-
exportName: "feishuPlugin",
|
|
8
|
-
},
|
|
9
|
-
secrets: {
|
|
10
|
-
specifier: "./secret-contract-api.js",
|
|
11
|
-
exportName: "channelSecrets",
|
|
12
|
-
},
|
|
13
|
-
});
|
package/src/accounts.test.ts
DELETED
|
@@ -1,459 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
FeishuSecretRefUnavailableError,
|
|
4
|
-
inspectFeishuCredentials,
|
|
5
|
-
resolveDefaultFeishuAccountId,
|
|
6
|
-
resolveDefaultFeishuAccountSelection,
|
|
7
|
-
resolveFeishuAccount,
|
|
8
|
-
resolveFeishuCredentials,
|
|
9
|
-
resolveFeishuRuntimeAccount,
|
|
10
|
-
} from "./accounts.js";
|
|
11
|
-
import type { FeishuConfig } from "./types.js";
|
|
12
|
-
|
|
13
|
-
function makeDefaultAndRouterAccounts() {
|
|
14
|
-
return {
|
|
15
|
-
default: { appId: "cli_default", appSecret: "secret_default" }, // pragma: allowlist secret
|
|
16
|
-
"router-d": { appId: "cli_router", appSecret: "secret_router" }, // pragma: allowlist secret
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function expectExplicitDefaultAccountSelection(
|
|
21
|
-
account: ReturnType<typeof resolveFeishuAccount>,
|
|
22
|
-
appId: string,
|
|
23
|
-
) {
|
|
24
|
-
expect(account.accountId).toBe("router-d");
|
|
25
|
-
expect(account.selectionSource).toBe("explicit-default");
|
|
26
|
-
expect(account.configured).toBe(true);
|
|
27
|
-
expect(account.appId).toBe(appId);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function withEnvVar(key: string, value: string | undefined, run: () => void) {
|
|
31
|
-
const prev = process.env[key];
|
|
32
|
-
if (value === undefined) {
|
|
33
|
-
delete process.env[key];
|
|
34
|
-
} else {
|
|
35
|
-
process.env[key] = value;
|
|
36
|
-
}
|
|
37
|
-
try {
|
|
38
|
-
run();
|
|
39
|
-
} finally {
|
|
40
|
-
if (prev === undefined) {
|
|
41
|
-
delete process.env[key];
|
|
42
|
-
} else {
|
|
43
|
-
process.env[key] = prev;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function asConfig(config: Partial<FeishuConfig>): FeishuConfig {
|
|
49
|
-
return config as unknown as FeishuConfig;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function expectUnresolvedEnvSecretRefError(key: string) {
|
|
53
|
-
expect(() =>
|
|
54
|
-
resolveFeishuCredentials(
|
|
55
|
-
asConfig({
|
|
56
|
-
appId: "cli_123",
|
|
57
|
-
appSecret: { source: "env", provider: "default", id: key } as never,
|
|
58
|
-
}),
|
|
59
|
-
),
|
|
60
|
-
).toThrow(/unresolved SecretRef/i);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
describe("resolveDefaultFeishuAccountId", () => {
|
|
64
|
-
it("prefers channels.feishu.defaultAccount when configured", () => {
|
|
65
|
-
const cfg = {
|
|
66
|
-
channels: {
|
|
67
|
-
feishu: {
|
|
68
|
-
defaultAccount: "router-d",
|
|
69
|
-
accounts: makeDefaultAndRouterAccounts(),
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
expect(resolveDefaultFeishuAccountId(cfg as never)).toBe("router-d");
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it("normalizes configured defaultAccount before lookup", () => {
|
|
78
|
-
const cfg = {
|
|
79
|
-
channels: {
|
|
80
|
-
feishu: {
|
|
81
|
-
defaultAccount: "Router D",
|
|
82
|
-
accounts: {
|
|
83
|
-
"router-d": { appId: "cli_router", appSecret: "secret_router" }, // pragma: allowlist secret
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
},
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
expect(resolveDefaultFeishuAccountId(cfg as never)).toBe("router-d");
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
it("keeps configured defaultAccount even when not present in accounts map", () => {
|
|
93
|
-
const cfg = {
|
|
94
|
-
channels: {
|
|
95
|
-
feishu: {
|
|
96
|
-
defaultAccount: "router-d",
|
|
97
|
-
accounts: {
|
|
98
|
-
default: { appId: "cli_default", appSecret: "secret_default" }, // pragma: allowlist secret
|
|
99
|
-
zeta: { appId: "cli_zeta", appSecret: "secret_zeta" }, // pragma: allowlist secret
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
expect(resolveDefaultFeishuAccountId(cfg as never)).toBe("router-d");
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it("falls back to literal default account id when present", () => {
|
|
109
|
-
const cfg = {
|
|
110
|
-
channels: {
|
|
111
|
-
feishu: {
|
|
112
|
-
accounts: {
|
|
113
|
-
default: { appId: "cli_default", appSecret: "secret_default" }, // pragma: allowlist secret
|
|
114
|
-
zeta: { appId: "cli_zeta", appSecret: "secret_zeta" }, // pragma: allowlist secret
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
},
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
expect(resolveDefaultFeishuAccountId(cfg as never)).toBe("default");
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it("reports selection source for configured defaults and mapped defaults", () => {
|
|
124
|
-
const explicitDefaultCfg = {
|
|
125
|
-
channels: {
|
|
126
|
-
feishu: {
|
|
127
|
-
defaultAccount: "router-d",
|
|
128
|
-
accounts: {},
|
|
129
|
-
},
|
|
130
|
-
},
|
|
131
|
-
};
|
|
132
|
-
expect(resolveDefaultFeishuAccountSelection(explicitDefaultCfg as never)).toEqual({
|
|
133
|
-
accountId: "router-d",
|
|
134
|
-
source: "explicit-default",
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
const mappedDefaultCfg = {
|
|
138
|
-
channels: {
|
|
139
|
-
feishu: {
|
|
140
|
-
accounts: {
|
|
141
|
-
default: { appId: "cli_default", appSecret: "secret_default" }, // pragma: allowlist secret
|
|
142
|
-
},
|
|
143
|
-
},
|
|
144
|
-
},
|
|
145
|
-
};
|
|
146
|
-
expect(resolveDefaultFeishuAccountSelection(mappedDefaultCfg as never)).toEqual({
|
|
147
|
-
accountId: "default",
|
|
148
|
-
source: "mapped-default",
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
describe("resolveFeishuCredentials", () => {
|
|
154
|
-
it("throws unresolved SecretRef errors by default for unsupported secret sources", () => {
|
|
155
|
-
expect(() =>
|
|
156
|
-
resolveFeishuCredentials(
|
|
157
|
-
asConfig({
|
|
158
|
-
appId: "cli_123",
|
|
159
|
-
appSecret: { source: "file", provider: "default", id: "path/to/secret" } as never,
|
|
160
|
-
}),
|
|
161
|
-
),
|
|
162
|
-
).toThrow(/unresolved SecretRef/i);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it("returns null (without throwing) when unresolved SecretRef is allowed", () => {
|
|
166
|
-
const creds = resolveFeishuCredentials(
|
|
167
|
-
asConfig({
|
|
168
|
-
appId: "cli_123",
|
|
169
|
-
appSecret: { source: "file", provider: "default", id: "path/to/secret" } as never,
|
|
170
|
-
}),
|
|
171
|
-
{ allowUnresolvedSecretRef: true },
|
|
172
|
-
);
|
|
173
|
-
|
|
174
|
-
expect(creds).toBeNull();
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
it("supports explicit inspect mode for unresolved SecretRefs", () => {
|
|
178
|
-
const creds = resolveFeishuCredentials(
|
|
179
|
-
asConfig({
|
|
180
|
-
appId: "cli_123",
|
|
181
|
-
appSecret: { source: "file", provider: "default", id: "path/to/secret" } as never,
|
|
182
|
-
}),
|
|
183
|
-
{ mode: "inspect" },
|
|
184
|
-
);
|
|
185
|
-
|
|
186
|
-
expect(creds).toBeNull();
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
it("throws unresolved SecretRef error when env SecretRef points to missing env var", () => {
|
|
190
|
-
const key = "FEISHU_APP_SECRET_MISSING_TEST";
|
|
191
|
-
withEnvVar(key, undefined, () => {
|
|
192
|
-
expectUnresolvedEnvSecretRefError(key);
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
it("resolves env SecretRef objects when unresolved refs are allowed", () => {
|
|
197
|
-
const key = "FEISHU_APP_SECRET_TEST";
|
|
198
|
-
const prev = process.env[key];
|
|
199
|
-
process.env[key] = " secret_from_env ";
|
|
200
|
-
|
|
201
|
-
try {
|
|
202
|
-
const creds = resolveFeishuCredentials(
|
|
203
|
-
asConfig({
|
|
204
|
-
appId: "cli_123",
|
|
205
|
-
appSecret: { source: "env", provider: "default", id: key } as never,
|
|
206
|
-
}),
|
|
207
|
-
{ allowUnresolvedSecretRef: true },
|
|
208
|
-
);
|
|
209
|
-
|
|
210
|
-
expect(creds).toEqual({
|
|
211
|
-
appId: "cli_123",
|
|
212
|
-
appSecret: "secret_from_env", // pragma: allowlist secret
|
|
213
|
-
encryptKey: undefined,
|
|
214
|
-
verificationToken: undefined,
|
|
215
|
-
domain: "feishu",
|
|
216
|
-
});
|
|
217
|
-
} finally {
|
|
218
|
-
if (prev === undefined) {
|
|
219
|
-
delete process.env[key];
|
|
220
|
-
} else {
|
|
221
|
-
process.env[key] = prev;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
it("resolves env SecretRef with custom provider alias when unresolved refs are allowed", () => {
|
|
227
|
-
const key = "FEISHU_APP_SECRET_CUSTOM_PROVIDER_TEST";
|
|
228
|
-
const prev = process.env[key];
|
|
229
|
-
process.env[key] = " secret_from_env_alias ";
|
|
230
|
-
|
|
231
|
-
try {
|
|
232
|
-
const creds = resolveFeishuCredentials(
|
|
233
|
-
asConfig({
|
|
234
|
-
appId: "cli_123",
|
|
235
|
-
appSecret: { source: "env", provider: "corp-env", id: key } as never,
|
|
236
|
-
}),
|
|
237
|
-
{ allowUnresolvedSecretRef: true },
|
|
238
|
-
);
|
|
239
|
-
|
|
240
|
-
expect(creds?.appSecret).toBe("secret_from_env_alias");
|
|
241
|
-
} finally {
|
|
242
|
-
if (prev === undefined) {
|
|
243
|
-
delete process.env[key];
|
|
244
|
-
} else {
|
|
245
|
-
process.env[key] = prev;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it("preserves unresolved SecretRef diagnostics for env refs in default mode", () => {
|
|
251
|
-
const key = "FEISHU_APP_SECRET_POLICY_TEST";
|
|
252
|
-
withEnvVar(key, "secret_from_env", () => {
|
|
253
|
-
expectUnresolvedEnvSecretRefError(key);
|
|
254
|
-
});
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
it("trims and returns credentials when values are valid strings", () => {
|
|
258
|
-
const creds = resolveFeishuCredentials(
|
|
259
|
-
asConfig({
|
|
260
|
-
appId: " cli_123 ",
|
|
261
|
-
appSecret: " secret_456 ",
|
|
262
|
-
encryptKey: " enc ",
|
|
263
|
-
verificationToken: " vt ",
|
|
264
|
-
}),
|
|
265
|
-
);
|
|
266
|
-
|
|
267
|
-
expect(creds).toEqual({
|
|
268
|
-
appId: "cli_123",
|
|
269
|
-
appSecret: "secret_456", // pragma: allowlist secret
|
|
270
|
-
encryptKey: "enc",
|
|
271
|
-
verificationToken: "vt",
|
|
272
|
-
domain: "feishu",
|
|
273
|
-
});
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
it("does not resolve encryptKey SecretRefs outside webhook mode", () => {
|
|
277
|
-
const creds = resolveFeishuCredentials(
|
|
278
|
-
asConfig({
|
|
279
|
-
connectionMode: "websocket",
|
|
280
|
-
appId: "cli_123",
|
|
281
|
-
appSecret: "secret_456",
|
|
282
|
-
encryptKey: { source: "file", provider: "default", id: "path/to/secret" } as never,
|
|
283
|
-
}),
|
|
284
|
-
);
|
|
285
|
-
|
|
286
|
-
expect(creds).toEqual({
|
|
287
|
-
appId: "cli_123",
|
|
288
|
-
appSecret: "secret_456", // pragma: allowlist secret
|
|
289
|
-
encryptKey: undefined,
|
|
290
|
-
verificationToken: undefined,
|
|
291
|
-
domain: "feishu",
|
|
292
|
-
});
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
it("keeps required credentials when optional event SecretRefs are unresolved in inspect mode", () => {
|
|
296
|
-
const creds = inspectFeishuCredentials(
|
|
297
|
-
asConfig({
|
|
298
|
-
appId: "cli_123",
|
|
299
|
-
appSecret: "secret_456",
|
|
300
|
-
verificationToken: { source: "file", provider: "default", id: "path/to/token" } as never,
|
|
301
|
-
}),
|
|
302
|
-
);
|
|
303
|
-
|
|
304
|
-
expect(creds).toEqual({
|
|
305
|
-
appId: "cli_123",
|
|
306
|
-
appSecret: "secret_456", // pragma: allowlist secret
|
|
307
|
-
encryptKey: undefined,
|
|
308
|
-
verificationToken: undefined,
|
|
309
|
-
domain: "feishu",
|
|
310
|
-
});
|
|
311
|
-
});
|
|
312
|
-
});
|
|
313
|
-
|
|
314
|
-
describe("resolveFeishuAccount", () => {
|
|
315
|
-
it("uses top-level credentials with configured default account id even without account map entry", () => {
|
|
316
|
-
const cfg = {
|
|
317
|
-
channels: {
|
|
318
|
-
feishu: {
|
|
319
|
-
defaultAccount: "router-d",
|
|
320
|
-
appId: "top_level_app",
|
|
321
|
-
appSecret: "top_level_secret", // pragma: allowlist secret
|
|
322
|
-
accounts: {
|
|
323
|
-
default: { appId: "cli_default", appSecret: "secret_default" }, // pragma: allowlist secret
|
|
324
|
-
},
|
|
325
|
-
},
|
|
326
|
-
},
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
const account = resolveFeishuAccount({ cfg: cfg as never, accountId: undefined });
|
|
330
|
-
expectExplicitDefaultAccountSelection(account, "top_level_app");
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
it("uses configured default account when accountId is omitted", () => {
|
|
334
|
-
const cfg = {
|
|
335
|
-
channels: {
|
|
336
|
-
feishu: {
|
|
337
|
-
defaultAccount: "router-d",
|
|
338
|
-
accounts: {
|
|
339
|
-
default: { enabled: true },
|
|
340
|
-
"router-d": { appId: "cli_router", appSecret: "secret_router", enabled: true }, // pragma: allowlist secret
|
|
341
|
-
},
|
|
342
|
-
},
|
|
343
|
-
},
|
|
344
|
-
};
|
|
345
|
-
|
|
346
|
-
const account = resolveFeishuAccount({ cfg: cfg as never, accountId: undefined });
|
|
347
|
-
expectExplicitDefaultAccountSelection(account, "cli_router");
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
it("keeps explicit accountId selection", () => {
|
|
351
|
-
const cfg = {
|
|
352
|
-
channels: {
|
|
353
|
-
feishu: {
|
|
354
|
-
defaultAccount: "router-d",
|
|
355
|
-
accounts: makeDefaultAndRouterAccounts(),
|
|
356
|
-
},
|
|
357
|
-
},
|
|
358
|
-
};
|
|
359
|
-
|
|
360
|
-
const account = resolveFeishuAccount({ cfg: cfg as never, accountId: "default" });
|
|
361
|
-
expect(account.accountId).toBe("default");
|
|
362
|
-
expect(account.selectionSource).toBe("explicit");
|
|
363
|
-
expect(account.appId).toBe("cli_default");
|
|
364
|
-
});
|
|
365
|
-
|
|
366
|
-
it("treats unresolved SecretRef as not configured in account resolution", () => {
|
|
367
|
-
const account = resolveFeishuAccount({
|
|
368
|
-
cfg: {
|
|
369
|
-
channels: {
|
|
370
|
-
feishu: {
|
|
371
|
-
accounts: {
|
|
372
|
-
main: {
|
|
373
|
-
appId: "cli_123",
|
|
374
|
-
appSecret: { source: "file", provider: "default", id: "path/to/secret" },
|
|
375
|
-
} as never,
|
|
376
|
-
},
|
|
377
|
-
},
|
|
378
|
-
},
|
|
379
|
-
} as never,
|
|
380
|
-
accountId: "main",
|
|
381
|
-
});
|
|
382
|
-
expect(account.configured).toBe(false);
|
|
383
|
-
expect(account.appSecret).toBeUndefined();
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
it("keeps account configured when optional event SecretRefs are unresolved in inspect mode", () => {
|
|
387
|
-
const account = resolveFeishuAccount({
|
|
388
|
-
cfg: {
|
|
389
|
-
channels: {
|
|
390
|
-
feishu: {
|
|
391
|
-
accounts: {
|
|
392
|
-
main: {
|
|
393
|
-
appId: "cli_123",
|
|
394
|
-
appSecret: "secret_456",
|
|
395
|
-
verificationToken: {
|
|
396
|
-
source: "file",
|
|
397
|
-
provider: "default",
|
|
398
|
-
id: "path/to/token",
|
|
399
|
-
},
|
|
400
|
-
} as never,
|
|
401
|
-
},
|
|
402
|
-
},
|
|
403
|
-
},
|
|
404
|
-
} as never,
|
|
405
|
-
accountId: "main",
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
expect(account.configured).toBe(true);
|
|
409
|
-
expect(account.appSecret).toBe("secret_456");
|
|
410
|
-
expect(account.verificationToken).toBeUndefined();
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
it("throws typed SecretRef errors in runtime account resolution", () => {
|
|
414
|
-
let caught: unknown;
|
|
415
|
-
try {
|
|
416
|
-
resolveFeishuRuntimeAccount({
|
|
417
|
-
cfg: {
|
|
418
|
-
channels: {
|
|
419
|
-
feishu: {
|
|
420
|
-
accounts: {
|
|
421
|
-
main: {
|
|
422
|
-
appId: "cli_123",
|
|
423
|
-
appSecret: { source: "file", provider: "default", id: "path/to/secret" },
|
|
424
|
-
} as never,
|
|
425
|
-
},
|
|
426
|
-
},
|
|
427
|
-
},
|
|
428
|
-
} as never,
|
|
429
|
-
accountId: "main",
|
|
430
|
-
});
|
|
431
|
-
} catch (error) {
|
|
432
|
-
caught = error;
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
expect(caught).toBeInstanceOf(FeishuSecretRefUnavailableError);
|
|
436
|
-
expect((caught as Error).message).toMatch(/channels\.feishu\.appSecret: unresolved SecretRef/i);
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
it("does not throw when account name is non-string", () => {
|
|
440
|
-
expect(() =>
|
|
441
|
-
resolveFeishuAccount({
|
|
442
|
-
cfg: {
|
|
443
|
-
channels: {
|
|
444
|
-
feishu: {
|
|
445
|
-
accounts: {
|
|
446
|
-
main: {
|
|
447
|
-
name: { bad: true },
|
|
448
|
-
appId: "cli_123",
|
|
449
|
-
appSecret: "secret_456", // pragma: allowlist secret
|
|
450
|
-
} as never,
|
|
451
|
-
},
|
|
452
|
-
},
|
|
453
|
-
},
|
|
454
|
-
} as never,
|
|
455
|
-
accountId: "main",
|
|
456
|
-
}),
|
|
457
|
-
).not.toThrow();
|
|
458
|
-
});
|
|
459
|
-
});
|