diff --git a/extensions/feishu/src/setup-surface.test.ts b/extensions/feishu/src/setup-surface.test.ts index d68ee795abc..cf5891eec5e 100644 --- a/extensions/feishu/src/setup-surface.test.ts +++ b/extensions/feishu/src/setup-surface.test.ts @@ -318,6 +318,34 @@ describe("feishu setup wizard status", () => { expect(status.statusLines).toEqual(["Feishu: needs app credentials"]); }); + it("uses configured defaultAccount for omitted setup configured state", async () => { + const status = await feishuGetStatus({ + cfg: { + channels: { + feishu: { + defaultAccount: "work", + appId: "top_level_app", + appSecret: "top-level-secret", // pragma: allowlist secret + accounts: { + alerts: { + appId: "alerts-app", + appSecret: "alerts-secret", // pragma: allowlist secret + }, + work: { + appId: "", + appSecret: "work-secret", // pragma: allowlist secret + }, + }, + }, + }, + } as never, + accountOverrides: {}, + }); + + expect(status.configured).toBe(false); + expect(status.statusLines).toEqual(["Feishu: needs app credentials"]); + }); + it("uses configured defaultAccount for omitted DM policy account context", async () => { const { feishuSetupWizard } = await import("./setup-surface.js"); const cfg = { diff --git a/extensions/feishu/src/setup-surface.ts b/extensions/feishu/src/setup-surface.ts index 959b1f0b0cc..21b811b3b2c 100644 --- a/extensions/feishu/src/setup-surface.ts +++ b/extensions/feishu/src/setup-surface.ts @@ -98,8 +98,9 @@ function setFeishuGroupAllowFrom( return patchFeishuConfig(cfg, accountId, { groupAllowFrom }); } -function isFeishuConfigured(cfg: OpenClawConfig): boolean { +function isFeishuConfigured(cfg: OpenClawConfig, accountId?: string | null): boolean { const feishuCfg = ((cfg.channels?.feishu as FeishuConfig | undefined) ?? {}) as FeishuConfig; + const resolvedAccountId = normalizeString(accountId) ?? resolveDefaultFeishuAccountId(cfg); const isAppIdConfigured = (value: unknown): boolean => { const asString = normalizeString(value); @@ -122,22 +123,25 @@ function isFeishuConfigured(cfg: OpenClawConfig): boolean { isAppIdConfigured(feishuCfg?.appId) && hasConfiguredSecretInput(feishuCfg?.appSecret), ); - const accountConfigured = Object.values(feishuCfg.accounts ?? {}).some((account) => { - if (!account || typeof account !== "object") { - return false; - } - const hasOwnAppId = Object.prototype.hasOwnProperty.call(account, "appId"); - const hasOwnAppSecret = Object.prototype.hasOwnProperty.call(account, "appSecret"); - const accountAppIdConfigured = hasOwnAppId - ? isAppIdConfigured((account as Record).appId) - : isAppIdConfigured(feishuCfg?.appId); - const accountSecretConfigured = hasOwnAppSecret - ? hasConfiguredSecretInput((account as Record).appSecret) - : hasConfiguredSecretInput(feishuCfg?.appSecret); - return Boolean(accountAppIdConfigured && accountSecretConfigured); - }); + if (resolvedAccountId === DEFAULT_ACCOUNT_ID) { + return topLevelConfigured; + } - return topLevelConfigured || accountConfigured; + const account = feishuCfg.accounts?.[resolvedAccountId]; + if (!account || typeof account !== "object") { + return topLevelConfigured; + } + + const hasOwnAppId = Object.prototype.hasOwnProperty.call(account, "appId"); + const hasOwnAppSecret = Object.prototype.hasOwnProperty.call(account, "appSecret"); + const accountAppIdConfigured = hasOwnAppId + ? isAppIdConfigured((account as Record).appId) + : isAppIdConfigured(feishuCfg?.appId); + const accountSecretConfigured = hasOwnAppSecret + ? hasConfiguredSecretInput((account as Record).appSecret) + : hasConfiguredSecretInput(feishuCfg?.appSecret); + + return Boolean(accountAppIdConfigured && accountSecretConfigured); } async function promptFeishuAllowFrom(params: { @@ -258,8 +262,7 @@ export const feishuSetupWizard: ChannelSetupWizard = { unconfiguredHint: "needs app creds", configuredScore: 2, unconfiguredScore: 0, - resolveConfigured: ({ cfg, accountId }) => - accountId ? resolveFeishuAccount({ cfg, accountId }).configured : isFeishuConfigured(cfg), + resolveConfigured: ({ cfg, accountId }) => isFeishuConfigured(cfg, accountId), resolveStatusLines: async ({ cfg, accountId, configured }) => { const resolvedCredentials = accountId ? (() => {