mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-21 12:00:15 +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
|
- 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))
|
- 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.3] - 2026-01-13
|
||||||
|
|
||||||
## [0.45.2] - 2026-01-13
|
## [0.45.2] - 2026-01-13
|
||||||
|
|
|
||||||
|
|
@ -628,14 +628,16 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
||||||
steeringMode: settingsManager.getSteeringMode(),
|
steeringMode: settingsManager.getSteeringMode(),
|
||||||
followUpMode: settingsManager.getFollowUpMode(),
|
followUpMode: settingsManager.getFollowUpMode(),
|
||||||
thinkingBudgets: settingsManager.getThinkingBudgets(),
|
thinkingBudgets: settingsManager.getThinkingBudgets(),
|
||||||
getApiKey: async () => {
|
getApiKey: async (provider) => {
|
||||||
const currentModel = agent.state.model;
|
// Use the provider argument from the in-flight request;
|
||||||
if (!currentModel) {
|
// agent.state.model may already be switched mid-turn.
|
||||||
|
const resolvedProvider = provider || agent.state.model?.provider;
|
||||||
|
if (!resolvedProvider) {
|
||||||
throw new Error("No model selected");
|
throw new Error("No model selected");
|
||||||
}
|
}
|
||||||
const key = await modelRegistry.getApiKey(currentModel);
|
const key = await modelRegistry.authStorage.getApiKey(resolvedProvider);
|
||||||
if (!key) {
|
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;
|
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