fix(ai): honor scoped env in compat API key injection
This commit is contained in:
@@ -100,7 +100,7 @@ function withEnvApiKey<TOptions extends StreamOptions>(
|
||||
options: TOptions | undefined,
|
||||
): TOptions | undefined {
|
||||
if (hasExplicitApiKey(options?.apiKey)) return options;
|
||||
const apiKey = getEnvApiKey(model.provider);
|
||||
const apiKey = getEnvApiKey(model.provider, options?.env);
|
||||
if (!apiKey) return options;
|
||||
return { ...options, apiKey } as TOptions;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { complete, registerApiProvider, resetApiProviders } from "../src/compat.ts";
|
||||
import type { AssistantMessage, Context, Model } from "../src/types.ts";
|
||||
import { AssistantMessageEventStream } from "../src/utils/event-stream.ts";
|
||||
|
||||
const context: Context = { messages: [{ role: "user", content: "hi", timestamp: Date.now() }] };
|
||||
|
||||
const model: Model<"openai-responses"> = {
|
||||
id: "test-model",
|
||||
name: "Test Model",
|
||||
api: "openai-responses",
|
||||
provider: "openai",
|
||||
baseUrl: "https://example.test/v1",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
||||
contextWindow: 128000,
|
||||
maxTokens: 4096,
|
||||
};
|
||||
|
||||
function message(): AssistantMessage {
|
||||
return {
|
||||
role: "assistant",
|
||||
content: [{ type: "text", text: "ok" }],
|
||||
api: model.api,
|
||||
provider: model.provider,
|
||||
model: model.id,
|
||||
usage: {
|
||||
input: 0,
|
||||
output: 0,
|
||||
cacheRead: 0,
|
||||
cacheWrite: 0,
|
||||
totalTokens: 0,
|
||||
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
||||
},
|
||||
stopReason: "stop",
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
}
|
||||
|
||||
describe("compat env API key injection", () => {
|
||||
afterEach(() => {
|
||||
resetApiProviders();
|
||||
});
|
||||
|
||||
it("uses request-scoped env when injecting provider API keys", async () => {
|
||||
let capturedApiKey: string | undefined;
|
||||
registerApiProvider({
|
||||
api: "openai-responses",
|
||||
stream: (_model, _context, options) => {
|
||||
capturedApiKey = options?.apiKey;
|
||||
const stream = new AssistantMessageEventStream();
|
||||
const output = message();
|
||||
stream.push({ type: "start", partial: output });
|
||||
stream.push({ type: "done", reason: "stop", message: output });
|
||||
stream.end(output);
|
||||
return stream;
|
||||
},
|
||||
streamSimple: (_model, _context, options) => {
|
||||
capturedApiKey = options?.apiKey;
|
||||
const stream = new AssistantMessageEventStream();
|
||||
const output = message();
|
||||
stream.push({ type: "start", partial: output });
|
||||
stream.push({ type: "done", reason: "stop", message: output });
|
||||
stream.end(output);
|
||||
return stream;
|
||||
},
|
||||
});
|
||||
|
||||
await complete(model, context, { env: { OPENAI_API_KEY: "scoped-key" } });
|
||||
|
||||
expect(capturedApiKey).toBe("scoped-key");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user