mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-16 08:02:17 +00:00
Enhance provider override to support baseUrl-only mode
Builds on #406 to support simpler proxy use case: - Override just baseUrl to route built-in provider through proxy - All built-in models preserved, no need to redefine them - Full replacement still works when models array is provided
This commit is contained in:
parent
243104fa18
commit
d747ec6e23
4 changed files with 238 additions and 25 deletions
|
|
@ -53,7 +53,116 @@ describe("ModelRegistry", () => {
|
|||
return registry.getAll().filter((m) => m.provider === provider);
|
||||
}
|
||||
|
||||
describe("provider override", () => {
|
||||
/** Create a baseUrl-only override (no custom models) */
|
||||
function overrideConfig(baseUrl: string, headers?: Record<string, string>) {
|
||||
return { baseUrl, ...(headers && { headers }) };
|
||||
}
|
||||
|
||||
/** Write raw providers config (for mixed override/replacement scenarios) */
|
||||
function writeRawModelsJson(providers: Record<string, unknown>) {
|
||||
writeFileSync(modelsJsonPath, JSON.stringify({ providers }));
|
||||
}
|
||||
|
||||
describe("baseUrl override (no custom models)", () => {
|
||||
test("overriding baseUrl keeps all built-in models", () => {
|
||||
writeRawModelsJson({
|
||||
anthropic: overrideConfig("https://my-proxy.example.com/v1"),
|
||||
});
|
||||
|
||||
const registry = new ModelRegistry(authStorage, modelsJsonPath);
|
||||
const anthropicModels = getModelsForProvider(registry, "anthropic");
|
||||
|
||||
// Should have multiple built-in models, not just one
|
||||
expect(anthropicModels.length).toBeGreaterThan(1);
|
||||
expect(anthropicModels.some((m) => m.id.includes("claude"))).toBe(true);
|
||||
});
|
||||
|
||||
test("overriding baseUrl changes URL on all built-in models", () => {
|
||||
writeRawModelsJson({
|
||||
anthropic: overrideConfig("https://my-proxy.example.com/v1"),
|
||||
});
|
||||
|
||||
const registry = new ModelRegistry(authStorage, modelsJsonPath);
|
||||
const anthropicModels = getModelsForProvider(registry, "anthropic");
|
||||
|
||||
// All models should have the new baseUrl
|
||||
for (const model of anthropicModels) {
|
||||
expect(model.baseUrl).toBe("https://my-proxy.example.com/v1");
|
||||
}
|
||||
});
|
||||
|
||||
test("overriding headers merges with model headers", () => {
|
||||
writeRawModelsJson({
|
||||
anthropic: overrideConfig("https://my-proxy.example.com/v1", {
|
||||
"X-Custom-Header": "custom-value",
|
||||
}),
|
||||
});
|
||||
|
||||
const registry = new ModelRegistry(authStorage, modelsJsonPath);
|
||||
const anthropicModels = getModelsForProvider(registry, "anthropic");
|
||||
|
||||
for (const model of anthropicModels) {
|
||||
expect(model.headers?.["X-Custom-Header"]).toBe("custom-value");
|
||||
}
|
||||
});
|
||||
|
||||
test("baseUrl-only override does not affect other providers", () => {
|
||||
writeRawModelsJson({
|
||||
anthropic: overrideConfig("https://my-proxy.example.com/v1"),
|
||||
});
|
||||
|
||||
const registry = new ModelRegistry(authStorage, modelsJsonPath);
|
||||
const googleModels = getModelsForProvider(registry, "google");
|
||||
|
||||
// Google models should still have their original baseUrl
|
||||
expect(googleModels.length).toBeGreaterThan(0);
|
||||
expect(googleModels[0].baseUrl).not.toBe("https://my-proxy.example.com/v1");
|
||||
});
|
||||
|
||||
test("can mix baseUrl override and full replacement", () => {
|
||||
writeRawModelsJson({
|
||||
// baseUrl-only for anthropic
|
||||
anthropic: overrideConfig("https://anthropic-proxy.example.com/v1"),
|
||||
// Full replacement for google
|
||||
google: providerConfig(
|
||||
"https://google-proxy.example.com/v1",
|
||||
[{ id: "gemini-custom" }],
|
||||
"google-generative-ai",
|
||||
),
|
||||
});
|
||||
|
||||
const registry = new ModelRegistry(authStorage, modelsJsonPath);
|
||||
|
||||
// Anthropic: multiple built-in models with new baseUrl
|
||||
const anthropicModels = getModelsForProvider(registry, "anthropic");
|
||||
expect(anthropicModels.length).toBeGreaterThan(1);
|
||||
expect(anthropicModels[0].baseUrl).toBe("https://anthropic-proxy.example.com/v1");
|
||||
|
||||
// Google: single custom model
|
||||
const googleModels = getModelsForProvider(registry, "google");
|
||||
expect(googleModels).toHaveLength(1);
|
||||
expect(googleModels[0].id).toBe("gemini-custom");
|
||||
});
|
||||
|
||||
test("refresh() picks up baseUrl override changes", () => {
|
||||
writeRawModelsJson({
|
||||
anthropic: overrideConfig("https://first-proxy.example.com/v1"),
|
||||
});
|
||||
const registry = new ModelRegistry(authStorage, modelsJsonPath);
|
||||
|
||||
expect(getModelsForProvider(registry, "anthropic")[0].baseUrl).toBe("https://first-proxy.example.com/v1");
|
||||
|
||||
// Update and refresh
|
||||
writeRawModelsJson({
|
||||
anthropic: overrideConfig("https://second-proxy.example.com/v1"),
|
||||
});
|
||||
registry.refresh();
|
||||
|
||||
expect(getModelsForProvider(registry, "anthropic")[0].baseUrl).toBe("https://second-proxy.example.com/v1");
|
||||
});
|
||||
});
|
||||
|
||||
describe("provider replacement (with custom models)", () => {
|
||||
test("custom provider with same name as built-in replaces built-in models", () => {
|
||||
writeModelsJson({
|
||||
anthropic: providerConfig("https://my-proxy.example.com/v1", [{ id: "claude-custom" }]),
|
||||
|
|
@ -81,7 +190,11 @@ describe("ModelRegistry", () => {
|
|||
test("multiple built-in providers can be overridden", () => {
|
||||
writeModelsJson({
|
||||
anthropic: providerConfig("https://anthropic-proxy.example.com/v1", [{ id: "claude-proxy" }]),
|
||||
google: providerConfig("https://google-proxy.example.com/v1", [{ id: "gemini-proxy" }], "google-generative-ai"),
|
||||
google: providerConfig(
|
||||
"https://google-proxy.example.com/v1",
|
||||
[{ id: "gemini-proxy" }],
|
||||
"google-generative-ai",
|
||||
),
|
||||
});
|
||||
|
||||
const registry = new ModelRegistry(authStorage, modelsJsonPath);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue