fix: honor feishu default setup status

This commit is contained in:
Tak Hoffman
2026-04-03 15:44:43 -05:00
parent 0204b8dd28
commit cfef9bf856
2 changed files with 49 additions and 18 deletions

View File

@@ -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 = {

View File

@@ -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<string, unknown>).appId)
: isAppIdConfigured(feishuCfg?.appId);
const accountSecretConfigured = hasOwnAppSecret
? hasConfiguredSecretInput((account as Record<string, unknown>).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<string, unknown>).appId)
: isAppIdConfigured(feishuCfg?.appId);
const accountSecretConfigured = hasOwnAppSecret
? hasConfiguredSecretInput((account as Record<string, unknown>).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
? (() => {