@openclaw/feishu 2026.3.12 → 2026.5.1-beta.1
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/api.ts +31 -0
- package/channel-entry.ts +20 -0
- package/channel-plugin-api.ts +1 -0
- package/contract-api.ts +16 -0
- package/index.ts +70 -53
- package/openclaw.plugin.json +1653 -4
- package/package.json +32 -7
- package/runtime-api.ts +55 -0
- package/secret-contract-api.ts +5 -0
- package/security-contract-api.ts +1 -0
- package/session-key-api.ts +1 -0
- package/setup-api.ts +3 -0
- package/setup-entry.test.ts +14 -0
- package/setup-entry.ts +13 -0
- package/src/accounts.test.ts +115 -22
- package/src/accounts.ts +199 -117
- package/src/app-registration.ts +331 -0
- package/src/approval-auth.test.ts +24 -0
- package/src/approval-auth.ts +25 -0
- package/src/async.test.ts +35 -0
- package/src/async.ts +43 -1
- package/src/audio-preflight.runtime.ts +9 -0
- package/src/bitable.test.ts +131 -0
- package/src/bitable.ts +59 -22
- package/src/bot-content.ts +474 -0
- package/src/bot-group-name.test.ts +108 -0
- package/src/bot-runtime-api.ts +12 -0
- package/src/bot-sender-name.ts +125 -0
- package/src/bot.broadcast.test.ts +463 -0
- package/src/bot.card-action.test.ts +519 -5
- package/src/bot.checkBotMentioned.test.ts +92 -20
- package/src/bot.helpers.test.ts +118 -0
- package/src/bot.stripBotMention.test.ts +13 -21
- package/src/bot.test.ts +1334 -401
- package/src/bot.ts +798 -786
- package/src/card-action.ts +408 -40
- package/src/card-interaction.test.ts +129 -0
- package/src/card-interaction.ts +159 -0
- package/src/card-test-helpers.ts +47 -0
- package/src/card-ux-approval.ts +65 -0
- package/src/card-ux-launcher.test.ts +99 -0
- package/src/card-ux-launcher.ts +121 -0
- package/src/card-ux-shared.ts +33 -0
- package/src/channel-runtime-api.ts +16 -0
- package/src/channel.runtime.ts +47 -0
- package/src/channel.test.ts +914 -3
- package/src/channel.ts +1252 -309
- package/src/chat-schema.ts +5 -4
- package/src/chat.test.ts +84 -28
- package/src/chat.ts +68 -10
- package/src/client.test.ts +212 -103
- package/src/client.ts +115 -21
- package/src/comment-dispatcher-runtime-api.ts +6 -0
- package/src/comment-dispatcher.test.ts +169 -0
- package/src/comment-dispatcher.ts +107 -0
- package/src/comment-handler-runtime-api.ts +3 -0
- package/src/comment-handler.test.ts +486 -0
- package/src/comment-handler.ts +309 -0
- package/src/comment-reaction.test.ts +166 -0
- package/src/comment-reaction.ts +259 -0
- package/src/comment-shared.test.ts +182 -0
- package/src/comment-shared.ts +365 -0
- package/src/comment-target.ts +44 -0
- package/src/config-schema.test.ts +77 -25
- package/src/config-schema.ts +31 -4
- package/src/conversation-id.test.ts +18 -0
- package/src/conversation-id.ts +199 -0
- package/src/dedup-runtime-api.ts +1 -0
- package/src/dedup.ts +76 -35
- package/src/directory.static.ts +61 -0
- package/src/directory.test.ts +119 -20
- package/src/directory.ts +61 -91
- package/src/doc-schema.ts +1 -1
- package/src/docx-batch-insert.test.ts +39 -38
- package/src/docx-batch-insert.ts +55 -19
- package/src/docx-color-text.ts +9 -4
- package/src/docx-table-ops.test.ts +53 -0
- package/src/docx-table-ops.ts +52 -34
- package/src/docx-types.ts +38 -0
- package/src/docx.account-selection.test.ts +12 -3
- package/src/docx.test.ts +314 -74
- package/src/docx.ts +278 -122
- package/src/drive-schema.ts +47 -1
- package/src/drive.test.ts +1219 -0
- package/src/drive.ts +614 -13
- package/src/dynamic-agent.ts +10 -4
- package/src/event-types.ts +45 -0
- package/src/external-keys.ts +1 -1
- package/src/lifecycle.test-support.ts +220 -0
- package/src/media.test.ts +413 -87
- package/src/media.ts +488 -154
- package/src/mention-target.types.ts +5 -0
- package/src/mention.ts +32 -51
- package/src/message-action-contract.ts +13 -0
- package/src/monitor-state-runtime-api.ts +7 -0
- package/src/monitor-transport-runtime-api.ts +7 -0
- package/src/monitor.account.ts +220 -313
- package/src/monitor.acp-init-failure.lifecycle.test-support.ts +219 -0
- package/src/monitor.bot-identity.ts +86 -0
- package/src/monitor.bot-menu-handler.ts +165 -0
- package/src/monitor.bot-menu.lifecycle.test-support.ts +224 -0
- package/src/monitor.bot-menu.test.ts +178 -0
- package/src/monitor.broadcast.reply-once.lifecycle.test-support.ts +264 -0
- package/src/monitor.card-action.lifecycle.test-support.ts +373 -0
- package/src/monitor.cleanup.test.ts +376 -0
- package/src/monitor.comment-notice-handler.ts +105 -0
- package/src/monitor.comment.test.ts +937 -0
- package/src/monitor.comment.ts +1386 -0
- package/src/monitor.lifecycle.test.ts +4 -0
- package/src/monitor.message-handler.ts +339 -0
- package/src/monitor.reaction.lifecycle.test-support.ts +68 -0
- package/src/monitor.reaction.test.ts +194 -92
- package/src/monitor.reply-once.lifecycle.test-support.ts +190 -0
- package/src/monitor.startup.test.ts +24 -36
- package/src/monitor.startup.ts +26 -16
- package/src/monitor.state.ts +20 -5
- package/src/monitor.synthetic-error.ts +18 -0
- package/src/monitor.test-mocks.ts +2 -2
- package/src/monitor.transport.ts +297 -39
- package/src/monitor.ts +15 -10
- package/src/monitor.webhook-e2e.test.ts +272 -0
- package/src/monitor.webhook-security.test.ts +125 -91
- package/src/monitor.webhook.test-helpers.ts +116 -0
- package/src/outbound-runtime-api.ts +1 -0
- package/src/outbound.test.ts +627 -53
- package/src/outbound.ts +623 -81
- package/src/perm-schema.ts +1 -1
- package/src/perm.ts +1 -7
- package/src/pins.ts +108 -0
- package/src/policy.test.ts +297 -117
- package/src/policy.ts +142 -29
- package/src/post.ts +7 -6
- package/src/probe.test.ts +122 -118
- package/src/probe.ts +26 -16
- package/src/processing-claims.ts +59 -0
- package/src/qr-terminal.ts +1 -0
- package/src/reactions.ts +23 -60
- package/src/reasoning-preview.test.ts +59 -0
- package/src/reasoning-preview.ts +20 -0
- package/src/reply-dispatcher-runtime-api.ts +7 -0
- package/src/reply-dispatcher.test.ts +721 -168
- package/src/reply-dispatcher.ts +422 -172
- package/src/runtime.ts +6 -3
- package/src/secret-contract.ts +145 -0
- package/src/secret-input.ts +1 -13
- package/src/security-audit-shared.ts +69 -0
- package/src/security-audit.test.ts +61 -0
- package/src/security-audit.ts +1 -0
- package/src/send-result.ts +1 -1
- package/src/send-target.test.ts +9 -3
- package/src/send-target.ts +10 -4
- package/src/send.reply-fallback.test.ts +127 -42
- package/src/send.test.ts +386 -4
- package/src/send.ts +486 -164
- package/src/sequential-key.test.ts +72 -0
- package/src/sequential-key.ts +28 -0
- package/src/sequential-queue.test.ts +92 -0
- package/src/sequential-queue.ts +16 -0
- package/src/session-conversation.ts +42 -0
- package/src/session-route.ts +48 -0
- package/src/setup-core.ts +51 -0
- package/src/{onboarding.test.ts → setup-surface.test.ts} +52 -21
- package/src/setup-surface.ts +581 -0
- package/src/streaming-card.test.ts +138 -2
- package/src/streaming-card.ts +134 -18
- package/src/subagent-hooks.test.ts +603 -0
- package/src/subagent-hooks.ts +397 -0
- package/src/targets.ts +3 -13
- package/src/test-support/lifecycle-test-support.ts +479 -0
- package/src/thread-bindings.test.ts +143 -0
- package/src/thread-bindings.ts +330 -0
- package/src/tool-account-routing.test.ts +66 -8
- package/src/tool-account.test.ts +44 -0
- package/src/tool-account.ts +40 -17
- package/src/tool-factory-test-harness.ts +11 -8
- package/src/tool-result.ts +3 -1
- package/src/tools-config.ts +1 -1
- package/src/types.ts +16 -15
- package/src/typing.ts +10 -6
- package/src/wiki-schema.ts +1 -1
- package/src/wiki.ts +1 -7
- package/subagent-hooks-api.ts +31 -0
- package/tsconfig.json +16 -0
- package/src/feishu-command-handler.ts +0 -59
- package/src/onboarding.status.test.ts +0 -25
- package/src/onboarding.ts +0 -489
- package/src/send-message.ts +0 -71
- package/src/targets.test.ts +0 -70
package/package.json
CHANGED
|
@@ -1,18 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/feishu",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.5.1-beta.1",
|
|
4
4
|
"description": "OpenClaw Feishu/Lark channel plugin (community maintained by @m1heng)",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/openclaw/openclaw"
|
|
8
|
+
},
|
|
5
9
|
"type": "module",
|
|
6
10
|
"dependencies": {
|
|
7
|
-
"@larksuiteoapi/node-sdk": "^1.
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
"@larksuiteoapi/node-sdk": "^1.62.1",
|
|
12
|
+
"typebox": "1.1.37"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@openclaw/plugin-sdk": "workspace:*",
|
|
16
|
+
"openclaw": "workspace:*"
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"openclaw": ">=2026.4.25"
|
|
20
|
+
},
|
|
21
|
+
"peerDependenciesMeta": {
|
|
22
|
+
"openclaw": {
|
|
23
|
+
"optional": true
|
|
24
|
+
}
|
|
11
25
|
},
|
|
12
26
|
"openclaw": {
|
|
13
27
|
"extensions": [
|
|
14
28
|
"./index.ts"
|
|
15
29
|
],
|
|
30
|
+
"setupEntry": "./setup-entry.ts",
|
|
16
31
|
"channel": {
|
|
17
32
|
"id": "feishu",
|
|
18
33
|
"label": "Feishu",
|
|
@@ -28,8 +43,18 @@
|
|
|
28
43
|
},
|
|
29
44
|
"install": {
|
|
30
45
|
"npmSpec": "@openclaw/feishu",
|
|
31
|
-
"
|
|
32
|
-
"
|
|
46
|
+
"defaultChoice": "npm",
|
|
47
|
+
"minHostVersion": ">=2026.4.25"
|
|
48
|
+
},
|
|
49
|
+
"compat": {
|
|
50
|
+
"pluginApi": ">=2026.4.25"
|
|
51
|
+
},
|
|
52
|
+
"build": {
|
|
53
|
+
"openclawVersion": "2026.5.1-beta.1"
|
|
54
|
+
},
|
|
55
|
+
"release": {
|
|
56
|
+
"publishToClawHub": true,
|
|
57
|
+
"publishToNpm": true
|
|
33
58
|
}
|
|
34
59
|
}
|
|
35
60
|
}
|
package/runtime-api.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
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";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { collectFeishuSecurityAuditFindings } from "./src/security-audit-shared.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { resolveFeishuSessionConversation as resolveSessionConversation } from "./src/session-conversation.js";
|
package/setup-api.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
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
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
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
CHANGED
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
import { describe, expect, it } from "vitest";
|
|
2
2
|
import {
|
|
3
|
+
FeishuSecretRefUnavailableError,
|
|
4
|
+
inspectFeishuCredentials,
|
|
3
5
|
resolveDefaultFeishuAccountId,
|
|
4
6
|
resolveDefaultFeishuAccountSelection,
|
|
5
7
|
resolveFeishuAccount,
|
|
6
8
|
resolveFeishuCredentials,
|
|
9
|
+
resolveFeishuRuntimeAccount,
|
|
7
10
|
} from "./accounts.js";
|
|
8
11
|
import type { FeishuConfig } from "./types.js";
|
|
9
12
|
|
|
10
|
-
|
|
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
|
+
}
|
|
11
29
|
|
|
12
30
|
function withEnvVar(key: string, value: string | undefined, run: () => void) {
|
|
13
31
|
const prev = process.env[key];
|
|
@@ -27,6 +45,10 @@ function withEnvVar(key: string, value: string | undefined, run: () => void) {
|
|
|
27
45
|
}
|
|
28
46
|
}
|
|
29
47
|
|
|
48
|
+
function asConfig(config: Partial<FeishuConfig>): FeishuConfig {
|
|
49
|
+
return config as unknown as FeishuConfig;
|
|
50
|
+
}
|
|
51
|
+
|
|
30
52
|
function expectUnresolvedEnvSecretRefError(key: string) {
|
|
31
53
|
expect(() =>
|
|
32
54
|
resolveFeishuCredentials(
|
|
@@ -44,10 +66,7 @@ describe("resolveDefaultFeishuAccountId", () => {
|
|
|
44
66
|
channels: {
|
|
45
67
|
feishu: {
|
|
46
68
|
defaultAccount: "router-d",
|
|
47
|
-
accounts:
|
|
48
|
-
default: { appId: "cli_default", appSecret: "secret_default" }, // pragma: allowlist secret
|
|
49
|
-
"router-d": { appId: "cli_router", appSecret: "secret_router" }, // pragma: allowlist secret
|
|
50
|
-
},
|
|
69
|
+
accounts: makeDefaultAndRouterAccounts(),
|
|
51
70
|
},
|
|
52
71
|
},
|
|
53
72
|
};
|
|
@@ -155,6 +174,18 @@ describe("resolveFeishuCredentials", () => {
|
|
|
155
174
|
expect(creds).toBeNull();
|
|
156
175
|
});
|
|
157
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
|
+
|
|
158
189
|
it("throws unresolved SecretRef error when env SecretRef points to missing env var", () => {
|
|
159
190
|
const key = "FEISHU_APP_SECRET_MISSING_TEST";
|
|
160
191
|
withEnvVar(key, undefined, () => {
|
|
@@ -260,6 +291,24 @@ describe("resolveFeishuCredentials", () => {
|
|
|
260
291
|
domain: "feishu",
|
|
261
292
|
});
|
|
262
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
|
+
});
|
|
263
312
|
});
|
|
264
313
|
|
|
265
314
|
describe("resolveFeishuAccount", () => {
|
|
@@ -278,10 +327,7 @@ describe("resolveFeishuAccount", () => {
|
|
|
278
327
|
};
|
|
279
328
|
|
|
280
329
|
const account = resolveFeishuAccount({ cfg: cfg as never, accountId: undefined });
|
|
281
|
-
|
|
282
|
-
expect(account.selectionSource).toBe("explicit-default");
|
|
283
|
-
expect(account.configured).toBe(true);
|
|
284
|
-
expect(account.appId).toBe("top_level_app");
|
|
330
|
+
expectExplicitDefaultAccountSelection(account, "top_level_app");
|
|
285
331
|
});
|
|
286
332
|
|
|
287
333
|
it("uses configured default account when accountId is omitted", () => {
|
|
@@ -298,10 +344,7 @@ describe("resolveFeishuAccount", () => {
|
|
|
298
344
|
};
|
|
299
345
|
|
|
300
346
|
const account = resolveFeishuAccount({ cfg: cfg as never, accountId: undefined });
|
|
301
|
-
|
|
302
|
-
expect(account.selectionSource).toBe("explicit-default");
|
|
303
|
-
expect(account.configured).toBe(true);
|
|
304
|
-
expect(account.appId).toBe("cli_router");
|
|
347
|
+
expectExplicitDefaultAccountSelection(account, "cli_router");
|
|
305
348
|
});
|
|
306
349
|
|
|
307
350
|
it("keeps explicit accountId selection", () => {
|
|
@@ -309,10 +352,7 @@ describe("resolveFeishuAccount", () => {
|
|
|
309
352
|
channels: {
|
|
310
353
|
feishu: {
|
|
311
354
|
defaultAccount: "router-d",
|
|
312
|
-
accounts:
|
|
313
|
-
default: { appId: "cli_default", appSecret: "secret_default" }, // pragma: allowlist secret
|
|
314
|
-
"router-d": { appId: "cli_router", appSecret: "secret_router" }, // pragma: allowlist secret
|
|
315
|
-
},
|
|
355
|
+
accounts: makeDefaultAndRouterAccounts(),
|
|
316
356
|
},
|
|
317
357
|
},
|
|
318
358
|
};
|
|
@@ -323,9 +363,57 @@ describe("resolveFeishuAccount", () => {
|
|
|
323
363
|
expect(account.appId).toBe("cli_default");
|
|
324
364
|
});
|
|
325
365
|
|
|
326
|
-
it("
|
|
327
|
-
|
|
328
|
-
|
|
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({
|
|
329
417
|
cfg: {
|
|
330
418
|
channels: {
|
|
331
419
|
feishu: {
|
|
@@ -339,8 +427,13 @@ describe("resolveFeishuAccount", () => {
|
|
|
339
427
|
},
|
|
340
428
|
} as never,
|
|
341
429
|
accountId: "main",
|
|
342
|
-
})
|
|
343
|
-
)
|
|
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);
|
|
344
437
|
});
|
|
345
438
|
|
|
346
439
|
it("does not throw when account name is non-string", () => {
|