From 935bd6de7fcb34bf5a057312d0910ccb5f718fa4 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sat, 11 Apr 2026 14:14:53 +0100 Subject: [PATCH] fix(gateway): split credential secret input runtime --- src/channels/plugins/setup-wizard-helpers.ts | 8 +- src/gateway/auth-config-utils.ts | 3 +- src/gateway/call.ts | 279 +---------------- src/gateway/connection-auth.ts | 4 +- src/gateway/credentials-secret-inputs.ts | 295 ++++++++++++++++++ src/gateway/probe-auth.ts | 17 +- .../resolve-configured-secret-input-string.ts | 2 +- 7 files changed, 318 insertions(+), 290 deletions(-) create mode 100644 src/gateway/credentials-secret-inputs.ts diff --git a/src/channels/plugins/setup-wizard-helpers.ts b/src/channels/plugins/setup-wizard-helpers.ts index e35088636ba..44f03a3d8f7 100644 --- a/src/channels/plugins/setup-wizard-helpers.ts +++ b/src/channels/plugins/setup-wizard-helpers.ts @@ -1,4 +1,4 @@ -import type { DmPolicy, GroupPolicy } from "../../config/types.js"; +import type { DmPolicy, GroupPolicy } from "../../config/types.base.js"; import type { OpenClawConfig } from "../../config/types.openclaw.js"; import type { SecretInput } from "../../config/types.secrets.js"; import { resolveSecretInputModeForEnvSelection } from "../../plugins/provider-auth-mode.js"; @@ -1377,9 +1377,9 @@ export function createNestedChannelParsedAllowFromPrompt(params: { getExistingAllowFrom: ({ cfg }: { cfg: OpenClawConfig }) => params.getExistingAllowFrom?.(cfg) ?? ( - (cfg.channels?.[params.channel] as Record | undefined)?.[params.section] as - | { allowFrom?: Array } - | undefined + (cfg.channels?.[params.channel] as Record | undefined)?.[ + params.section + ] as { allowFrom?: Array } | undefined )?.allowFrom ?? [], ...(params.mergeEntries ? { mergeEntries: params.mergeEntries } : {}), diff --git a/src/gateway/auth-config-utils.ts b/src/gateway/auth-config-utils.ts index 1c66a2e42e5..ad048fd6a37 100644 --- a/src/gateway/auth-config-utils.ts +++ b/src/gateway/auth-config-utils.ts @@ -1,4 +1,5 @@ -import type { GatewayAuthConfig, OpenClawConfig } from "../config/config.js"; +import type { GatewayAuthConfig } from "../config/types.gateway.js"; +import type { OpenClawConfig } from "../config/types.openclaw.js"; import { hasConfiguredSecretInput } from "../config/types.secrets.js"; import { resolveRequiredConfiguredSecretRefInputString } from "./resolve-configured-secret-input-string.js"; import { diff --git a/src/gateway/call.ts b/src/gateway/call.ts index 35ab8b34b98..a31d7c328f5 100644 --- a/src/gateway/call.ts +++ b/src/gateway/call.ts @@ -6,10 +6,8 @@ import { resolveStateDir as resolveStateDirFromPaths, } from "../config/paths.js"; import type { OpenClawConfig } from "../config/types.openclaw.js"; -import { resolveSecretInputRef } from "../config/types.secrets.js"; import { loadOrCreateDeviceIdentity } from "../infra/device-identity.js"; import { loadGatewayTlsRuntime } from "../infra/tls/gateway.js"; -import { resolveSecretInputString } from "../secrets/resolve-secret-input-string.js"; import { normalizeOptionalString } from "../shared/string-coerce.js"; import { GATEWAY_CLIENT_MODES, @@ -23,9 +21,8 @@ import { buildGatewayConnectionDetailsWithResolvers, type GatewayConnectionDetails, } from "./connection-details.js"; +import { resolveGatewayCredentialsWithSecretInputs } from "./credentials-secret-inputs.js"; import { - GatewaySecretRefUnavailableError, - resolveGatewayCredentialsFromConfig, trimToUndefined, type ExplicitGatewayAuth, type GatewayCredentialMode, @@ -40,14 +37,6 @@ import { type OperatorScope, } from "./method-scopes.js"; import { PROTOCOL_VERSION } from "./protocol/index.js"; -import { - ALL_GATEWAY_SECRET_INPUT_PATHS, - assignResolvedGatewaySecretInput, - isSupportedGatewaySecretInputPath, - isTokenGatewaySecretInputPath, - readGatewaySecretInputValue, - type SupportedGatewaySecretInputPath, -} from "./secret-input-paths.js"; export type { GatewayConnectionDetails }; type CallGatewayBaseOptions = { @@ -340,27 +329,6 @@ function ensureRemoteModeUrlConfigured(context: ResolvedGatewayCallContext): voi ); } -async function resolveGatewaySecretInputString(params: { - config: OpenClawConfig; - value: unknown; - path: string; - env: NodeJS.ProcessEnv; -}): Promise { - const value = await resolveSecretInputString({ - config: params.config, - value: params.value, - env: params.env, - normalize: trimToUndefined, - onResolveRefError: () => { - throw new GatewaySecretRefUnavailableError(params.path); - }, - }); - if (!value) { - throw new Error(`${params.path} resolved to an empty or non-string value.`); - } - return value; -} - async function resolveGatewayCredentials(context: ResolvedGatewayCallContext): Promise<{ token?: string; password?: string; @@ -381,258 +349,23 @@ async function resolveGatewayCredentialsWithEnv( password: context.explicitAuth.password, }; } - return resolveGatewayCredentialsFromConfigWithSecretInputs({ context, env }); -} - -function hasConfiguredGatewaySecretRef( - config: OpenClawConfig, - path: SupportedGatewaySecretInputPath, -): boolean { - return Boolean( - resolveSecretInputRef({ - value: readGatewaySecretInputValue(config, path), - defaults: config.secrets?.defaults, - }).ref, - ); -} - -function resolveGatewayCredentialsFromConfigOptions(params: { - context: ResolvedGatewayCallContext; - env: NodeJS.ProcessEnv; - cfg: OpenClawConfig; -}) { - const { context, env, cfg } = params; - return { - cfg, - env, + return resolveGatewayCredentialsWithSecretInputs({ + config: context.config, explicitAuth: context.explicitAuth, urlOverride: context.urlOverride, urlOverrideSource: context.urlOverrideSource, + env, modeOverride: context.modeOverride, localTokenPrecedence: context.localTokenPrecedence, localPasswordPrecedence: context.localPasswordPrecedence, remoteTokenPrecedence: context.remoteTokenPrecedence, - remotePasswordPrecedence: context.remotePasswordPrecedence ?? "env-first", // pragma: allowlist secret + remotePasswordPrecedence: context.remotePasswordPrecedence, remoteTokenFallback: context.remoteTokenFallback, remotePasswordFallback: context.remotePasswordFallback, - } as const; -} - -function localAuthModeAllowsGatewaySecretInputPath(params: { - authMode: string | undefined; - path: SupportedGatewaySecretInputPath; -}): boolean { - const { authMode, path } = params; - if (authMode === "none" || authMode === "trusted-proxy") { - return false; - } - if (authMode === "token") { - return isTokenGatewaySecretInputPath(path); - } - if (authMode === "password") { - return !isTokenGatewaySecretInputPath(path); - } - return true; -} - -function gatewaySecretInputPathCanWin(params: { - context: ResolvedGatewayCallContext; - env: NodeJS.ProcessEnv; - config: OpenClawConfig; - path: SupportedGatewaySecretInputPath; -}): boolean { - if (!hasConfiguredGatewaySecretRef(params.config, params.path)) { - return false; - } - const mode: GatewayCredentialMode = - params.context.modeOverride ?? (params.config.gateway?.mode === "remote" ? "remote" : "local"); - if ( - mode === "local" && - !localAuthModeAllowsGatewaySecretInputPath({ - authMode: params.config.gateway?.auth?.mode, - path: params.path, - }) - ) { - return false; - } - const sentinel = `__OPENCLAW_GATEWAY_SECRET_REF_PROBE_${params.path.replaceAll(".", "_")}__`; - const probeConfig = structuredClone(params.config); - for (const candidatePath of ALL_GATEWAY_SECRET_INPUT_PATHS) { - if (!hasConfiguredGatewaySecretRef(probeConfig, candidatePath)) { - continue; - } - assignResolvedGatewaySecretInput({ - config: probeConfig, - path: candidatePath, - value: undefined, - }); - } - assignResolvedGatewaySecretInput({ - config: probeConfig, - path: params.path, - value: sentinel, - }); - try { - const resolved = resolveGatewayCredentialsFromConfig( - resolveGatewayCredentialsFromConfigOptions({ - context: params.context, - env: params.env, - cfg: probeConfig, - }), - ); - const tokenCanWin = resolved.token === sentinel && !resolved.password; - const passwordCanWin = resolved.password === sentinel && !resolved.token; - return tokenCanWin || passwordCanWin; - } catch { - return false; - } -} - -async function resolveConfiguredGatewaySecretInput(params: { - config: OpenClawConfig; - path: SupportedGatewaySecretInputPath; - env: NodeJS.ProcessEnv; -}): Promise { - return resolveGatewaySecretInputString({ - config: params.config, - value: readGatewaySecretInputValue(params.config, params.path), - path: params.path, - env: params.env, }); } -async function resolvePreferredGatewaySecretInputs(params: { - context: ResolvedGatewayCallContext; - env: NodeJS.ProcessEnv; - config: OpenClawConfig; -}): Promise { - let nextConfig = params.config; - for (const path of ALL_GATEWAY_SECRET_INPUT_PATHS) { - if ( - !gatewaySecretInputPathCanWin({ - context: params.context, - env: params.env, - config: nextConfig, - path, - }) - ) { - continue; - } - if (nextConfig === params.config) { - nextConfig = structuredClone(params.config); - } - try { - const resolvedValue = await resolveConfiguredGatewaySecretInput({ - config: nextConfig, - path, - env: params.env, - }); - assignResolvedGatewaySecretInput({ - config: nextConfig, - path, - value: resolvedValue, - }); - } catch { - // Keep scanning candidate paths so unresolved higher-priority refs do not - // prevent valid fallback refs from being considered. - continue; - } - } - return nextConfig; -} - -async function resolveGatewayCredentialsFromConfigWithSecretInputs(params: { - context: ResolvedGatewayCallContext; - env: NodeJS.ProcessEnv; -}): Promise<{ token?: string; password?: string }> { - let resolvedConfig = await resolvePreferredGatewaySecretInputs({ - context: params.context, - env: params.env, - config: params.context.config, - }); - const resolvedPaths = new Set(); - for (;;) { - try { - return resolveGatewayCredentialsFromConfig( - resolveGatewayCredentialsFromConfigOptions({ - context: params.context, - env: params.env, - cfg: resolvedConfig, - }), - ); - } catch (error) { - if (!(error instanceof GatewaySecretRefUnavailableError)) { - throw error; - } - const path = error.path; - if (!isSupportedGatewaySecretInputPath(path) || resolvedPaths.has(path)) { - throw error; - } - if (resolvedConfig === params.context.config) { - resolvedConfig = structuredClone(params.context.config); - } - const resolvedValue = await resolveConfiguredGatewaySecretInput({ - config: resolvedConfig, - path, - env: params.env, - }); - assignResolvedGatewaySecretInput({ - config: resolvedConfig, - path, - value: resolvedValue, - }); - resolvedPaths.add(path); - } - } -} - -export async function resolveGatewayCredentialsWithSecretInputs(params: { - config: OpenClawConfig; - explicitAuth?: ExplicitGatewayAuth; - urlOverride?: string; - urlOverrideSource?: "cli" | "env"; - env?: NodeJS.ProcessEnv; - modeOverride?: GatewayCredentialMode; - localTokenPrecedence?: GatewayCredentialPrecedence; - localPasswordPrecedence?: GatewayCredentialPrecedence; - remoteTokenPrecedence?: GatewayRemoteCredentialPrecedence; - remotePasswordPrecedence?: GatewayRemoteCredentialPrecedence; - remoteTokenFallback?: GatewayRemoteCredentialFallback; - remotePasswordFallback?: GatewayRemoteCredentialFallback; -}): Promise<{ token?: string; password?: string }> { - const modeOverride = params.modeOverride; - const isRemoteMode = modeOverride - ? modeOverride === "remote" - : params.config.gateway?.mode === "remote"; - const remoteFromConfig = - params.config.gateway?.mode === "remote" - ? (params.config.gateway?.remote as GatewayRemoteSettings | undefined) - : undefined; - const remoteFromOverride = - modeOverride === "remote" - ? (params.config.gateway?.remote as GatewayRemoteSettings | undefined) - : undefined; - const context: ResolvedGatewayCallContext = { - config: params.config, - configPath: resolveGatewayConfigPath(process.env), - isRemoteMode, - remote: remoteFromOverride ?? remoteFromConfig, - urlOverride: trimToUndefined(params.urlOverride), - urlOverrideSource: params.urlOverrideSource, - remoteUrl: isRemoteMode - ? trimToUndefined((params.config.gateway?.remote as GatewayRemoteSettings | undefined)?.url) - : undefined, - explicitAuth: resolveExplicitGatewayAuth(params.explicitAuth), - modeOverride, - localTokenPrecedence: params.localTokenPrecedence, - localPasswordPrecedence: params.localPasswordPrecedence, - remoteTokenPrecedence: params.remoteTokenPrecedence, - remotePasswordPrecedence: params.remotePasswordPrecedence, - remoteTokenFallback: params.remoteTokenFallback, - remotePasswordFallback: params.remotePasswordFallback, - }; - return resolveGatewayCredentialsWithEnv(context, params.env ?? process.env); -} +export { resolveGatewayCredentialsWithSecretInputs }; async function resolveGatewayTlsFingerprint(params: { opts: CallGatewayBaseOptions; diff --git a/src/gateway/connection-auth.ts b/src/gateway/connection-auth.ts index 4e477cc51e1..7d49dc53a5a 100644 --- a/src/gateway/connection-auth.ts +++ b/src/gateway/connection-auth.ts @@ -1,7 +1,7 @@ import type { OpenClawConfig } from "../config/types.openclaw.js"; -import type { ExplicitGatewayAuth } from "./call.js"; -import { resolveGatewayCredentialsWithSecretInputs } from "./call.js"; +import { resolveGatewayCredentialsWithSecretInputs } from "./credentials-secret-inputs.js"; import type { + ExplicitGatewayAuth, GatewayCredentialMode, GatewayCredentialPrecedence, GatewayRemoteCredentialFallback, diff --git a/src/gateway/credentials-secret-inputs.ts b/src/gateway/credentials-secret-inputs.ts new file mode 100644 index 00000000000..37eb002674d --- /dev/null +++ b/src/gateway/credentials-secret-inputs.ts @@ -0,0 +1,295 @@ +import type { OpenClawConfig } from "../config/types.openclaw.js"; +import { resolveSecretInputRef } from "../config/types.secrets.js"; +import { resolveSecretInputString } from "../secrets/resolve-secret-input-string.js"; +import { + GatewaySecretRefUnavailableError, + resolveGatewayCredentialsFromConfig, + trimToUndefined, + type ExplicitGatewayAuth, + type GatewayCredentialMode, + type GatewayCredentialPrecedence, + type GatewayRemoteCredentialFallback, + type GatewayRemoteCredentialPrecedence, +} from "./credentials.js"; +import { + ALL_GATEWAY_SECRET_INPUT_PATHS, + assignResolvedGatewaySecretInput, + isSupportedGatewaySecretInputPath, + isTokenGatewaySecretInputPath, + readGatewaySecretInputValue, + type SupportedGatewaySecretInputPath, +} from "./secret-input-paths.js"; + +export type GatewayCredentialSecretInputOptions = { + config: OpenClawConfig; + explicitAuth?: ExplicitGatewayAuth; + urlOverride?: string; + urlOverrideSource?: "cli" | "env"; + env?: NodeJS.ProcessEnv; + modeOverride?: GatewayCredentialMode; + localTokenPrecedence?: GatewayCredentialPrecedence; + localPasswordPrecedence?: GatewayCredentialPrecedence; + remoteTokenPrecedence?: GatewayRemoteCredentialPrecedence; + remotePasswordPrecedence?: GatewayRemoteCredentialPrecedence; + remoteTokenFallback?: GatewayRemoteCredentialFallback; + remotePasswordFallback?: GatewayRemoteCredentialFallback; +}; + +type NormalizedGatewayCredentialSecretInputOptions = Omit< + GatewayCredentialSecretInputOptions, + "explicitAuth" +> & { + explicitAuth: ExplicitGatewayAuth; +}; + +function resolveExplicitGatewayAuth(opts?: ExplicitGatewayAuth): ExplicitGatewayAuth { + const token = + typeof opts?.token === "string" && opts.token.trim().length > 0 ? opts.token.trim() : undefined; + const password = + typeof opts?.password === "string" && opts.password.trim().length > 0 + ? opts.password.trim() + : undefined; + return { token, password }; +} + +async function resolveGatewaySecretInputString(params: { + config: OpenClawConfig; + value: unknown; + path: string; + env: NodeJS.ProcessEnv; +}): Promise { + const value = await resolveSecretInputString({ + config: params.config, + value: params.value, + env: params.env, + normalize: trimToUndefined, + onResolveRefError: () => { + throw new GatewaySecretRefUnavailableError(params.path); + }, + }); + if (!value) { + throw new Error(`${params.path} resolved to an empty or non-string value.`); + } + return value; +} + +function hasConfiguredGatewaySecretRef( + config: OpenClawConfig, + path: SupportedGatewaySecretInputPath, +): boolean { + return Boolean( + resolveSecretInputRef({ + value: readGatewaySecretInputValue(config, path), + defaults: config.secrets?.defaults, + }).ref, + ); +} + +function resolveGatewayCredentialsFromConfigOptions(params: { + cfg: OpenClawConfig; + env: NodeJS.ProcessEnv; + options: NormalizedGatewayCredentialSecretInputOptions; +}) { + const { cfg, env, options } = params; + return { + cfg, + env, + explicitAuth: options.explicitAuth, + urlOverride: options.urlOverride, + urlOverrideSource: options.urlOverrideSource, + modeOverride: options.modeOverride, + localTokenPrecedence: options.localTokenPrecedence, + localPasswordPrecedence: options.localPasswordPrecedence, + remoteTokenPrecedence: options.remoteTokenPrecedence, + remotePasswordPrecedence: options.remotePasswordPrecedence ?? "env-first", // pragma: allowlist secret + remoteTokenFallback: options.remoteTokenFallback, + remotePasswordFallback: options.remotePasswordFallback, + } as const; +} + +function localAuthModeAllowsGatewaySecretInputPath(params: { + authMode: string | undefined; + path: SupportedGatewaySecretInputPath; +}): boolean { + const { authMode, path } = params; + if (authMode === "none" || authMode === "trusted-proxy") { + return false; + } + if (authMode === "token") { + return isTokenGatewaySecretInputPath(path); + } + if (authMode === "password") { + return !isTokenGatewaySecretInputPath(path); + } + return true; +} + +function gatewaySecretInputPathCanWin(params: { + options: NormalizedGatewayCredentialSecretInputOptions; + env: NodeJS.ProcessEnv; + config: OpenClawConfig; + path: SupportedGatewaySecretInputPath; +}): boolean { + if (!hasConfiguredGatewaySecretRef(params.config, params.path)) { + return false; + } + const mode: GatewayCredentialMode = + params.options.modeOverride ?? (params.config.gateway?.mode === "remote" ? "remote" : "local"); + if ( + mode === "local" && + !localAuthModeAllowsGatewaySecretInputPath({ + authMode: params.config.gateway?.auth?.mode, + path: params.path, + }) + ) { + return false; + } + const sentinel = `__OPENCLAW_GATEWAY_SECRET_REF_PROBE_${params.path.replaceAll(".", "_")}__`; + const probeConfig = structuredClone(params.config); + for (const candidatePath of ALL_GATEWAY_SECRET_INPUT_PATHS) { + if (!hasConfiguredGatewaySecretRef(probeConfig, candidatePath)) { + continue; + } + assignResolvedGatewaySecretInput({ + config: probeConfig, + path: candidatePath, + value: undefined, + }); + } + assignResolvedGatewaySecretInput({ + config: probeConfig, + path: params.path, + value: sentinel, + }); + try { + const resolved = resolveGatewayCredentialsFromConfig( + resolveGatewayCredentialsFromConfigOptions({ + cfg: probeConfig, + env: params.env, + options: params.options, + }), + ); + const tokenCanWin = resolved.token === sentinel && !resolved.password; + const passwordCanWin = resolved.password === sentinel && !resolved.token; + return tokenCanWin || passwordCanWin; + } catch { + return false; + } +} + +async function resolveConfiguredGatewaySecretInput(params: { + config: OpenClawConfig; + path: SupportedGatewaySecretInputPath; + env: NodeJS.ProcessEnv; +}): Promise { + return resolveGatewaySecretInputString({ + config: params.config, + value: readGatewaySecretInputValue(params.config, params.path), + path: params.path, + env: params.env, + }); +} + +async function resolvePreferredGatewaySecretInputs(params: { + options: NormalizedGatewayCredentialSecretInputOptions; + env: NodeJS.ProcessEnv; + config: OpenClawConfig; +}): Promise { + let nextConfig = params.config; + for (const path of ALL_GATEWAY_SECRET_INPUT_PATHS) { + if ( + !gatewaySecretInputPathCanWin({ + options: params.options, + env: params.env, + config: nextConfig, + path, + }) + ) { + continue; + } + if (nextConfig === params.config) { + nextConfig = structuredClone(params.config); + } + try { + const resolvedValue = await resolveConfiguredGatewaySecretInput({ + config: nextConfig, + path, + env: params.env, + }); + assignResolvedGatewaySecretInput({ + config: nextConfig, + path, + value: resolvedValue, + }); + } catch { + // Keep scanning candidate paths so unresolved higher-priority refs do not + // prevent valid fallback refs from being considered. + continue; + } + } + return nextConfig; +} + +async function resolveGatewayCredentialsFromConfigWithSecretInputs(params: { + options: NormalizedGatewayCredentialSecretInputOptions; + env: NodeJS.ProcessEnv; +}): Promise<{ token?: string; password?: string }> { + let resolvedConfig = await resolvePreferredGatewaySecretInputs({ + options: params.options, + env: params.env, + config: params.options.config, + }); + const resolvedPaths = new Set(); + for (;;) { + try { + return resolveGatewayCredentialsFromConfig( + resolveGatewayCredentialsFromConfigOptions({ + cfg: resolvedConfig, + env: params.env, + options: params.options, + }), + ); + } catch (error) { + if (!(error instanceof GatewaySecretRefUnavailableError)) { + throw error; + } + const path = error.path; + if (!isSupportedGatewaySecretInputPath(path) || resolvedPaths.has(path)) { + throw error; + } + if (resolvedConfig === params.options.config) { + resolvedConfig = structuredClone(params.options.config); + } + const resolvedValue = await resolveConfiguredGatewaySecretInput({ + config: resolvedConfig, + path, + env: params.env, + }); + assignResolvedGatewaySecretInput({ + config: resolvedConfig, + path, + value: resolvedValue, + }); + resolvedPaths.add(path); + } + } +} + +export async function resolveGatewayCredentialsWithSecretInputs( + params: GatewayCredentialSecretInputOptions, +): Promise<{ token?: string; password?: string }> { + const options: NormalizedGatewayCredentialSecretInputOptions = { + ...params, + explicitAuth: resolveExplicitGatewayAuth(params.explicitAuth), + }; + if (options.explicitAuth.token || options.explicitAuth.password) { + return { + token: options.explicitAuth.token, + password: options.explicitAuth.password, + }; + } + return await resolveGatewayCredentialsFromConfigWithSecretInputs({ + options, + env: params.env ?? process.env, + }); +} diff --git a/src/gateway/probe-auth.ts b/src/gateway/probe-auth.ts index a8bfe5f5704..2b61f8e84aa 100644 --- a/src/gateway/probe-auth.ts +++ b/src/gateway/probe-auth.ts @@ -1,5 +1,6 @@ import type { OpenClawConfig } from "../config/types.openclaw.js"; import { normalizeOptionalString } from "../shared/string-coerce.js"; +import { resolveGatewayCredentialsWithSecretInputs } from "./credentials-secret-inputs.js"; import { type ExplicitGatewayAuth, isGatewaySecretRefUnavailableError, @@ -65,15 +66,13 @@ export async function resolveGatewayProbeAuthWithSecretInputs(params: { explicitAuth?: ExplicitGatewayAuth; }): Promise<{ token?: string; password?: string }> { const policy = buildGatewayProbeCredentialPolicy(params); - return await import("./call.js").then(({ resolveGatewayCredentialsWithSecretInputs }) => - resolveGatewayCredentialsWithSecretInputs({ - config: policy.config, - env: policy.env, - explicitAuth: policy.explicitAuth, - modeOverride: policy.modeOverride, - remoteTokenFallback: policy.remoteTokenFallback, - }), - ); + return await resolveGatewayCredentialsWithSecretInputs({ + config: policy.config, + env: policy.env, + explicitAuth: policy.explicitAuth, + modeOverride: policy.modeOverride, + remoteTokenFallback: policy.remoteTokenFallback, + }); } export async function resolveGatewayProbeAuthSafeWithSecretInputs(params: { diff --git a/src/gateway/resolve-configured-secret-input-string.ts b/src/gateway/resolve-configured-secret-input-string.ts index 8ca3de10569..929955607ba 100644 --- a/src/gateway/resolve-configured-secret-input-string.ts +++ b/src/gateway/resolve-configured-secret-input-string.ts @@ -1,4 +1,4 @@ -import type { OpenClawConfig } from "../config/types.js"; +import type { OpenClawConfig } from "../config/types.openclaw.js"; import { resolveSecretInputRef } from "../config/types.secrets.js"; import { secretRefKey } from "../secrets/ref-contract.js"; import { resolveSecretRefValues } from "../secrets/resolve.js";