mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-15 03:10:44 +00:00
206 lines
6.2 KiB
TypeScript
206 lines
6.2 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { buildInlineProviderModels } from "./model.inline-provider.js";
|
|
import { makeModel } from "./model.test-harness.js";
|
|
|
|
describe("buildInlineProviderModels", () => {
|
|
it("attaches provider ids to inline models", () => {
|
|
const providers: Parameters<typeof buildInlineProviderModels>[0] = {
|
|
" alpha ": { baseUrl: "http://alpha.local", models: [makeModel("alpha-model")] },
|
|
beta: { baseUrl: "http://beta.local", models: [makeModel("beta-model")] },
|
|
};
|
|
|
|
const result = buildInlineProviderModels(providers);
|
|
|
|
expect(result).toEqual([
|
|
{
|
|
...makeModel("alpha-model"),
|
|
provider: "alpha",
|
|
baseUrl: "http://alpha.local",
|
|
api: undefined,
|
|
},
|
|
{
|
|
...makeModel("beta-model"),
|
|
provider: "beta",
|
|
baseUrl: "http://beta.local",
|
|
api: undefined,
|
|
},
|
|
]);
|
|
});
|
|
|
|
it("inherits baseUrl from provider when model does not specify it", () => {
|
|
const providers: Parameters<typeof buildInlineProviderModels>[0] = {
|
|
custom: {
|
|
baseUrl: "http://localhost:8000",
|
|
models: [makeModel("custom-model")],
|
|
},
|
|
};
|
|
|
|
const result = buildInlineProviderModels(providers);
|
|
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0].baseUrl).toBe("http://localhost:8000");
|
|
});
|
|
|
|
it("inherits api from provider when model does not specify it", () => {
|
|
const providers: Parameters<typeof buildInlineProviderModels>[0] = {
|
|
custom: {
|
|
baseUrl: "http://localhost:8000",
|
|
api: "anthropic-messages",
|
|
models: [makeModel("custom-model")],
|
|
},
|
|
};
|
|
|
|
const result = buildInlineProviderModels(providers);
|
|
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0].api).toBe("anthropic-messages");
|
|
});
|
|
|
|
it("model-level api takes precedence over provider-level api", () => {
|
|
const providers: Parameters<typeof buildInlineProviderModels>[0] = {
|
|
custom: {
|
|
baseUrl: "http://localhost:8000",
|
|
api: "openai-responses",
|
|
models: [{ ...makeModel("custom-model"), api: "anthropic-messages" as const }],
|
|
},
|
|
};
|
|
|
|
const result = buildInlineProviderModels(providers);
|
|
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0].api).toBe("anthropic-messages");
|
|
});
|
|
|
|
it("inherits both baseUrl and api from provider config", () => {
|
|
const providers: Parameters<typeof buildInlineProviderModels>[0] = {
|
|
custom: {
|
|
baseUrl: "http://localhost:10000",
|
|
api: "anthropic-messages",
|
|
models: [makeModel("claude-opus-4.5")],
|
|
},
|
|
};
|
|
|
|
const result = buildInlineProviderModels(providers);
|
|
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0]).toMatchObject({
|
|
provider: "custom",
|
|
baseUrl: "http://localhost:10000",
|
|
api: "anthropic-messages",
|
|
name: "claude-opus-4.5",
|
|
});
|
|
});
|
|
|
|
it("normalizes bare Google API hosts for custom Google Generative AI providers", () => {
|
|
const providers: Parameters<typeof buildInlineProviderModels>[0] = {
|
|
"google-paid ": {
|
|
baseUrl: "https://generativelanguage.googleapis.com",
|
|
api: "google-generative-ai",
|
|
models: [makeModel("gemini-2.5-pro")],
|
|
},
|
|
};
|
|
|
|
const result = buildInlineProviderModels(providers);
|
|
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0]).toMatchObject({
|
|
provider: "google-paid",
|
|
api: "google-generative-ai",
|
|
baseUrl: "https://generativelanguage.googleapis.com/v1beta",
|
|
});
|
|
});
|
|
|
|
it("merges provider-level headers into inline models", () => {
|
|
const providers: Parameters<typeof buildInlineProviderModels>[0] = {
|
|
proxy: {
|
|
baseUrl: "https://proxy.example.com",
|
|
api: "anthropic-messages",
|
|
headers: { "User-Agent": "custom-agent/1.0" },
|
|
models: [makeModel("claude-sonnet-4-6")],
|
|
},
|
|
};
|
|
|
|
const result = buildInlineProviderModels(providers);
|
|
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0].headers).toEqual({ "User-Agent": "custom-agent/1.0" });
|
|
});
|
|
|
|
it("merges provider request headers into inline models", () => {
|
|
const providers: Parameters<typeof buildInlineProviderModels>[0] = {
|
|
proxy: {
|
|
baseUrl: "https://proxy.example.com/v1",
|
|
api: "openai-completions",
|
|
request: {
|
|
headers: {
|
|
"X-Tenant": "acme",
|
|
},
|
|
},
|
|
models: [makeModel("proxy-model")],
|
|
},
|
|
};
|
|
|
|
const result = buildInlineProviderModels(providers);
|
|
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0].headers).toEqual({ "X-Tenant": "acme" });
|
|
});
|
|
|
|
it("keeps inline provider transport overrides once the llm transport adapter is available", () => {
|
|
const result = buildInlineProviderModels({
|
|
proxy: {
|
|
baseUrl: "https://proxy.example.com/v1",
|
|
api: "openai-completions",
|
|
request: {
|
|
proxy: {
|
|
mode: "explicit-proxy",
|
|
url: "http://proxy.internal:8443",
|
|
},
|
|
},
|
|
models: [makeModel("proxy-model")],
|
|
},
|
|
} as unknown as Parameters<typeof buildInlineProviderModels>[0]);
|
|
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0]).toMatchObject({
|
|
provider: "proxy",
|
|
api: "openai-completions",
|
|
baseUrl: "https://proxy.example.com/v1",
|
|
});
|
|
});
|
|
|
|
it("omits headers when neither provider nor model specifies them", () => {
|
|
const providers: Parameters<typeof buildInlineProviderModels>[0] = {
|
|
plain: {
|
|
baseUrl: "http://localhost:8000",
|
|
models: [makeModel("some-model")],
|
|
},
|
|
};
|
|
|
|
const result = buildInlineProviderModels(providers);
|
|
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0].headers).toBeUndefined();
|
|
});
|
|
|
|
it("drops SecretRef marker headers in inline provider models", () => {
|
|
const providers: Parameters<typeof buildInlineProviderModels>[0] = {
|
|
custom: {
|
|
headers: {
|
|
Authorization: "secretref-env:OPENAI_HEADER_TOKEN",
|
|
"X-Managed": "secretref-managed",
|
|
"X-Static": "tenant-a",
|
|
},
|
|
models: [makeModel("custom-model")],
|
|
},
|
|
};
|
|
|
|
const result = buildInlineProviderModels(providers);
|
|
|
|
expect(result).toHaveLength(1);
|
|
expect(result[0].headers).toEqual({
|
|
"X-Static": "tenant-a",
|
|
});
|
|
});
|
|
});
|