mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-04-28 03:49:31 +00:00
fix: check saved OpenRouter key and return empty list when cloud config exists (#2640)
collectMissingCredentials() was incorrectly reporting saved credentials as missing in two ways: 1. It only checked process.env.OPENROUTER_API_KEY, ignoring keys saved via OAuth flow to ~/.config/spawn/openrouter.json 2. When hasCloudConfigCredentials() returned true, it filtered to keep OPENROUTER_API_KEY in the missing list instead of returning [] Fix: also call hasSavedOpenRouterKey() before marking OPENROUTER_API_KEY as missing, and return [] (not a filtered list) when cloud config exists. Fixes #2639 Agent: issue-fixer Co-authored-by: B <6723574+louisgv@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
245a2a46f9
commit
f03e5683c1
2 changed files with 58 additions and 3 deletions
|
|
@ -1,6 +1,8 @@
|
|||
import type { Manifest } from "../manifest";
|
||||
|
||||
import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test";
|
||||
import * as fs from "node:fs";
|
||||
import * as path from "node:path";
|
||||
import { preflightCredentialCheck } from "../commands/index.js";
|
||||
import { mockClackPrompts } from "./test-helpers";
|
||||
|
||||
|
|
@ -173,4 +175,56 @@ describe("preflightCredentialCheck", () => {
|
|||
const warnMsg = String(mockLog.warn.mock.calls[0][0]);
|
||||
expect(warnMsg).toContain("OPENROUTER_API_KEY");
|
||||
});
|
||||
|
||||
it("should not warn when OPENROUTER_API_KEY is saved in config file", async () => {
|
||||
clearEnv("OPENROUTER_API_KEY");
|
||||
setEnv("HCLOUD_TOKEN", "test-token");
|
||||
|
||||
const spawnConfigDir = path.join(process.env.HOME ?? "", ".config", "spawn");
|
||||
fs.mkdirSync(spawnConfigDir, {
|
||||
recursive: true,
|
||||
});
|
||||
const keyPath = path.join(spawnConfigDir, "openrouter.json");
|
||||
fs.writeFileSync(
|
||||
keyPath,
|
||||
JSON.stringify({
|
||||
api_key: "sk-or-v1-" + "a".repeat(64),
|
||||
}),
|
||||
);
|
||||
|
||||
const manifest = makeManifest("HCLOUD_TOKEN");
|
||||
await preflightCredentialCheck(manifest, "testcloud");
|
||||
fs.rmSync(keyPath, {
|
||||
force: true,
|
||||
});
|
||||
|
||||
expect(mockLog.warn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should not warn when cloud config file has saved credentials", async () => {
|
||||
clearEnv("OPENROUTER_API_KEY");
|
||||
clearEnv("HCLOUD_TOKEN");
|
||||
|
||||
const spawnConfigDir = path.join(process.env.HOME ?? "", ".config", "spawn");
|
||||
fs.mkdirSync(spawnConfigDir, {
|
||||
recursive: true,
|
||||
});
|
||||
const cloudConfigPath = path.join(spawnConfigDir, "testcloud.json");
|
||||
fs.writeFileSync(
|
||||
cloudConfigPath,
|
||||
JSON.stringify({
|
||||
token: "saved-cloud-token",
|
||||
}),
|
||||
);
|
||||
|
||||
const manifest = makeManifest("HCLOUD_TOKEN");
|
||||
await preflightCredentialCheck(manifest, "testcloud");
|
||||
fs.rmSync(cloudConfigPath, {
|
||||
force: true,
|
||||
});
|
||||
|
||||
// Both OPENROUTER_API_KEY and HCLOUD_TOKEN should be considered satisfied
|
||||
// because the cloud config file exists with credentials
|
||||
expect(mockLog.warn).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import pc from "picocolors";
|
|||
import pkg from "../../package.json" with { type: "json" };
|
||||
import { agentKeys, cloudKeys, isStaleCache, loadManifest, matrixStatus } from "../manifest.js";
|
||||
import { validateIdentifier, validatePrompt } from "../security.js";
|
||||
import { hasSavedOpenRouterKey } from "../shared/oauth.js";
|
||||
import { PkgVersionSchema, parseJsonObj } from "../shared/parse.js";
|
||||
import { getSpawnCloudConfigPath } from "../shared/paths.js";
|
||||
import { asyncTryCatch, isFileError, tryCatch, tryCatchIf, unwrapOr } from "../shared/result.js";
|
||||
|
|
@ -525,7 +526,7 @@ function hasCloudConfigCredentials(cloud: string): boolean {
|
|||
|
||||
export function collectMissingCredentials(authVars: string[], cloud?: string): string[] {
|
||||
const missing: string[] = [];
|
||||
if (!process.env.OPENROUTER_API_KEY) {
|
||||
if (!process.env.OPENROUTER_API_KEY && !hasSavedOpenRouterKey()) {
|
||||
missing.push("OPENROUTER_API_KEY");
|
||||
}
|
||||
for (const v of authVars) {
|
||||
|
|
@ -534,9 +535,9 @@ export function collectMissingCredentials(authVars: string[], cloud?: string): s
|
|||
}
|
||||
}
|
||||
|
||||
// If there are missing credentials but the cloud has saved config, don't report them as missing
|
||||
// If the cloud has saved config credentials, all vars (including cloud-specific ones) are covered
|
||||
if (missing.length > 0 && cloud && hasCloudConfigCredentials(cloud)) {
|
||||
return missing.filter((v) => v === "OPENROUTER_API_KEY");
|
||||
return [];
|
||||
}
|
||||
|
||||
return missing;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue