mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-16 04:01:56 +00:00
fix(coding-agent): resolve api keys by provider
What: - resolve API keys using provider argument - add regression test for model-switch key resolution - update coding-agent changelog - document provider lookup in SDK Why: - prevent model-switch 401s from provider mismatch Tests: - npm run check - npm run test -w @mariozechner/pi-coding-agent -- sdk-api-key.test.ts
This commit is contained in:
parent
1c58db5e23
commit
8936c5d136
3 changed files with 67 additions and 5 deletions
|
|
@ -11,6 +11,10 @@
|
|||
- Extension example: `summarize.ts` for summarizing conversations using custom UI and an external model
|
||||
- Vercel AI Gateway provider support: set `AI_GATEWAY_API_KEY` and use `--provider vercel-ai-gateway` ([#689](https://github.com/badlogic/pi-mono/pull/689) by [@timolins](https://github.com/timolins))
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix API key resolution after model switches by using provider argument ([#691](https://github.com/badlogic/pi-mono/pull/691) by [@joshp123](https://github.com/joshp123))
|
||||
|
||||
## [0.45.3] - 2026-01-13
|
||||
|
||||
## [0.45.2] - 2026-01-13
|
||||
|
|
|
|||
|
|
@ -628,14 +628,16 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|||
steeringMode: settingsManager.getSteeringMode(),
|
||||
followUpMode: settingsManager.getFollowUpMode(),
|
||||
thinkingBudgets: settingsManager.getThinkingBudgets(),
|
||||
getApiKey: async () => {
|
||||
const currentModel = agent.state.model;
|
||||
if (!currentModel) {
|
||||
getApiKey: async (provider) => {
|
||||
// Use the provider argument from the in-flight request;
|
||||
// agent.state.model may already be switched mid-turn.
|
||||
const resolvedProvider = provider || agent.state.model?.provider;
|
||||
if (!resolvedProvider) {
|
||||
throw new Error("No model selected");
|
||||
}
|
||||
const key = await modelRegistry.getApiKey(currentModel);
|
||||
const key = await modelRegistry.authStorage.getApiKey(resolvedProvider);
|
||||
if (!key) {
|
||||
throw new Error(`No API key found for provider "${currentModel.provider}"`);
|
||||
throw new Error(`No API key found for provider "${resolvedProvider}"`);
|
||||
}
|
||||
return key;
|
||||
},
|
||||
|
|
|
|||
56
packages/coding-agent/test/sdk-api-key.test.ts
Normal file
56
packages/coding-agent/test/sdk-api-key.test.ts
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import { mkdirSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { getModel } from "@mariozechner/pi-ai";
|
||||
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
||||
import { AuthStorage } from "../src/core/auth-storage.js";
|
||||
import { ModelRegistry } from "../src/core/model-registry.js";
|
||||
import { createAgentSession } from "../src/core/sdk.js";
|
||||
import { SessionManager } from "../src/core/session-manager.js";
|
||||
import { SettingsManager } from "../src/core/settings-manager.js";
|
||||
|
||||
describe("createAgentSession getApiKey", () => {
|
||||
let tempDir: string;
|
||||
let agentDir: string;
|
||||
let projectDir: string;
|
||||
|
||||
beforeEach(() => {
|
||||
tempDir = join(tmpdir(), `pi-test-sdk-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
||||
agentDir = join(tempDir, "agent");
|
||||
projectDir = join(tempDir, "project");
|
||||
mkdirSync(agentDir, { recursive: true });
|
||||
mkdirSync(join(projectDir, ".pi"), { recursive: true });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
rmSync(tempDir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it("uses the provider argument after model switches", async () => {
|
||||
const authStorage = new AuthStorage(join(agentDir, "auth.json"));
|
||||
authStorage.set("anthropic", { type: "api_key", key: "anthropic-key" });
|
||||
authStorage.set("openai-codex", { type: "api_key", key: "codex-key" });
|
||||
|
||||
const modelRegistry = new ModelRegistry(authStorage, join(agentDir, "models.json"));
|
||||
const settingsManager = SettingsManager.create(projectDir, agentDir);
|
||||
const sessionManager = SessionManager.inMemory(projectDir);
|
||||
|
||||
const anthropicModel = getModel("anthropic", "claude-opus-4-5");
|
||||
const codexModel = getModel("openai-codex", "gpt-5.2-codex");
|
||||
|
||||
const { session } = await createAgentSession({
|
||||
cwd: projectDir,
|
||||
agentDir,
|
||||
authStorage,
|
||||
modelRegistry,
|
||||
settingsManager,
|
||||
sessionManager,
|
||||
model: anthropicModel,
|
||||
});
|
||||
|
||||
await session.setModel(codexModel);
|
||||
|
||||
const key = await session.agent.getApiKey?.("anthropic");
|
||||
expect(key).toBe("anthropic-key");
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue