From e9fcbe1533eebddbbc101632d0d3f105ec66d02f Mon Sep 17 00:00:00 2001 From: "clawsweeper[bot]" <274271284+clawsweeper[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 01:36:59 +0100 Subject: [PATCH] fix: changed explicit-path handling regression (#74672) * fix: changed explicit-path handling regression * fix: preserve unicode adc fallback paths --------- Co-authored-by: openclaw-clawsweeper[bot] <280122609+openclaw-clawsweeper[bot]@users.noreply.github.com> Co-authored-by: Shakker --- src/agents/model-auth-env.ts | 12 +++++- src/agents/model-auth.profiles.test.ts | 54 ++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/agents/model-auth-env.ts b/src/agents/model-auth-env.ts index 850c3d117ff..8f20f4e89e7 100644 --- a/src/agents/model-auth-env.ts +++ b/src/agents/model-auth-env.ts @@ -31,10 +31,18 @@ function expandAuthEvidencePath(rawPath: string, env: NodeJS.ProcessEnv): string if (!trimmed) { return undefined; } - const homeDir = normalizeOptionalSecretInput(env.HOME) ?? os.homedir(); + const homeDir = normalizeOptionalPathInput(env.HOME) ?? os.homedir(); return trimmed.replaceAll("${HOME}", homeDir); } +function normalizeOptionalPathInput(value: unknown): string | undefined { + if (typeof value !== "string") { + return undefined; + } + const trimmed = value.trim(); + return trimmed ? trimmed : undefined; +} + function hasRequiredAuthEvidenceEnv( evidence: ProviderAuthEvidence, env: NodeJS.ProcessEnv, @@ -51,7 +59,7 @@ function hasRequiredAuthEvidenceEnv( function hasLocalFileAuthEvidence(evidence: ProviderAuthEvidence, env: NodeJS.ProcessEnv): boolean { if (evidence.fileEnvVar) { - const explicitPath = normalizeOptionalSecretInput(env[evidence.fileEnvVar]); + const explicitPath = normalizeOptionalPathInput(env[evidence.fileEnvVar]); if (explicitPath) { return fs.existsSync(explicitPath); } diff --git a/src/agents/model-auth.profiles.test.ts b/src/agents/model-auth.profiles.test.ts index 04f357dcadf..c9d9c527bae 100644 --- a/src/agents/model-auth.profiles.test.ts +++ b/src/agents/model-auth.profiles.test.ts @@ -959,6 +959,60 @@ describe("getApiKeyForModel", () => { }); }); + it("resolveEnvApiKey('google-vertex') accepts Unicode explicit ADC credential paths", async () => { + const homeDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-google-adc-unicode-")); + const explicitDir = path.join(homeDir, "認証情報"); + const fallbackDir = path.join(homeDir, ".config", "gcloud"); + const explicitCredentialsPath = path.join(explicitDir, "adc.json"); + await fs.mkdir(explicitDir, { recursive: true }); + await fs.mkdir(fallbackDir, { recursive: true }); + await fs.writeFile(explicitCredentialsPath, "{}", "utf8"); + await fs.writeFile( + path.join(fallbackDir, "application_default_credentials.json"), + "{}", + "utf8", + ); + + try { + const resolved = resolveEnvApiKey("google-vertex", { + GOOGLE_APPLICATION_CREDENTIALS: explicitCredentialsPath, + GOOGLE_CLOUD_LOCATION: "us-central1", + GOOGLE_CLOUD_PROJECT: "vertex-project", + HOME: homeDir, + } as NodeJS.ProcessEnv); + + expect(resolved?.apiKey).toBe("gcp-vertex-credentials"); + expect(resolved?.source).toBe("gcloud adc"); + } finally { + await fs.rm(homeDir, { recursive: true, force: true }); + } + }); + + it("resolveEnvApiKey('google-vertex') accepts Unicode ADC fallback home paths", async () => { + const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-google-adc-home-")); + const homeDir = path.join(tempDir, "認証情報-home"); + const fallbackDir = path.join(homeDir, ".config", "gcloud"); + await fs.mkdir(fallbackDir, { recursive: true }); + await fs.writeFile( + path.join(fallbackDir, "application_default_credentials.json"), + "{}", + "utf8", + ); + + try { + const resolved = resolveEnvApiKey("google-vertex", { + GOOGLE_CLOUD_LOCATION: "us-central1", + GOOGLE_CLOUD_PROJECT: "vertex-project", + HOME: homeDir, + } as NodeJS.ProcessEnv); + + expect(resolved?.apiKey).toBe("gcp-vertex-credentials"); + expect(resolved?.source).toBe("gcloud adc"); + } finally { + await fs.rm(tempDir, { recursive: true, force: true }); + } + }); + it("resolveEnvApiKey('google-vertex') keeps ADC fallback when manifest env candidates are empty", async () => { const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-google-adc-candidates-")); const credentialsPath = path.join(tempDir, "adc.json");