mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-28 04:28:58 +02:00
test: share provider catalog fixtures
This commit is contained in:
@@ -2,6 +2,7 @@ import { describe, expect, it } from "vitest";
|
||||
import { resolveProviderPluginChoice } from "../../src/plugins/provider-auth-choice.runtime.js";
|
||||
import { resolveProviderAuthEnvVarCandidates } from "../../src/secrets/provider-env-vars.js";
|
||||
import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js";
|
||||
import { runSingleProviderCatalog } from "../test-support/provider-model-test-helpers.js";
|
||||
import arceePlugin from "./index.js";
|
||||
|
||||
describe("arcee provider plugin", () => {
|
||||
@@ -77,28 +78,14 @@ describe("arcee provider plugin", () => {
|
||||
|
||||
it("builds the direct Arcee AI model catalog", async () => {
|
||||
const provider = await registerSingleProviderPlugin(arceePlugin);
|
||||
expect(provider.catalog).toBeDefined();
|
||||
|
||||
const catalog = await provider.catalog!.run({
|
||||
config: {},
|
||||
env: {},
|
||||
resolveProviderApiKey: (id: string) =>
|
||||
const catalogProvider = await runSingleProviderCatalog(provider, {
|
||||
resolveProviderApiKey: (id?: string) =>
|
||||
id === "arcee" ? { apiKey: "test-key" } : { apiKey: undefined },
|
||||
resolveProviderAuth: () => ({
|
||||
apiKey: "test-key",
|
||||
mode: "api_key",
|
||||
source: "env",
|
||||
}),
|
||||
} as never);
|
||||
});
|
||||
|
||||
expect(catalog && "provider" in catalog).toBe(true);
|
||||
if (!catalog || !("provider" in catalog)) {
|
||||
throw new Error("expected single-provider catalog");
|
||||
}
|
||||
|
||||
expect(catalog.provider.api).toBe("openai-completions");
|
||||
expect(catalog.provider.baseUrl).toBe("https://api.arcee.ai/api/v1");
|
||||
expect(catalog.provider.models?.map((model) => model.id)).toEqual([
|
||||
expect(catalogProvider.api).toBe("openai-completions");
|
||||
expect(catalogProvider.baseUrl).toBe("https://api.arcee.ai/api/v1");
|
||||
expect(catalogProvider.models?.map((model) => model.id)).toEqual([
|
||||
"trinity-mini",
|
||||
"trinity-large-preview",
|
||||
"trinity-large-thinking",
|
||||
@@ -107,26 +94,18 @@ describe("arcee provider plugin", () => {
|
||||
|
||||
it("builds the OpenRouter-backed Arcee AI model catalog", async () => {
|
||||
const provider = await registerSingleProviderPlugin(arceePlugin);
|
||||
|
||||
const catalog = await provider.catalog!.run({
|
||||
config: {},
|
||||
env: {},
|
||||
resolveProviderApiKey: (id: string) =>
|
||||
const catalogProvider = await runSingleProviderCatalog(provider, {
|
||||
resolveProviderApiKey: (id?: string) =>
|
||||
id === "openrouter" ? { apiKey: "sk-or-test" } : { apiKey: undefined },
|
||||
resolveProviderAuth: () => ({
|
||||
apiKey: "sk-or-test",
|
||||
mode: "api_key",
|
||||
source: "env",
|
||||
}),
|
||||
} as never);
|
||||
});
|
||||
|
||||
expect(catalog && "provider" in catalog).toBe(true);
|
||||
if (!catalog || !("provider" in catalog)) {
|
||||
throw new Error("expected single-provider catalog");
|
||||
}
|
||||
|
||||
expect(catalog.provider.baseUrl).toBe("https://openrouter.ai/api/v1");
|
||||
expect(catalog.provider.models?.map((model) => model.id)).toEqual([
|
||||
expect(catalogProvider.baseUrl).toBe("https://openrouter.ai/api/v1");
|
||||
expect(catalogProvider.models?.map((model) => model.id)).toEqual([
|
||||
"arcee/trinity-mini",
|
||||
"arcee/trinity-large-preview",
|
||||
"arcee/trinity-large-thinking",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveProviderPluginChoice } from "../../src/plugins/provider-auth-choice.runtime.js";
|
||||
import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js";
|
||||
import { runSingleProviderCatalog } from "../test-support/provider-model-test-helpers.js";
|
||||
import deepseekPlugin from "./index.js";
|
||||
|
||||
describe("deepseek provider plugin", () => {
|
||||
@@ -22,32 +23,16 @@ describe("deepseek provider plugin", () => {
|
||||
|
||||
it("builds the static DeepSeek model catalog", async () => {
|
||||
const provider = await registerSingleProviderPlugin(deepseekPlugin);
|
||||
expect(provider.catalog).toBeDefined();
|
||||
const catalogProvider = await runSingleProviderCatalog(provider);
|
||||
|
||||
const catalog = await provider.catalog!.run({
|
||||
config: {},
|
||||
env: {},
|
||||
resolveProviderApiKey: () => ({ apiKey: "test-key" }),
|
||||
resolveProviderAuth: () => ({
|
||||
apiKey: "test-key",
|
||||
mode: "api_key",
|
||||
source: "env",
|
||||
}),
|
||||
} as never);
|
||||
|
||||
expect(catalog && "provider" in catalog).toBe(true);
|
||||
if (!catalog || !("provider" in catalog)) {
|
||||
throw new Error("expected single-provider catalog");
|
||||
}
|
||||
|
||||
expect(catalog.provider.api).toBe("openai-completions");
|
||||
expect(catalog.provider.baseUrl).toBe("https://api.deepseek.com");
|
||||
expect(catalog.provider.models?.map((model) => model.id)).toEqual([
|
||||
expect(catalogProvider.api).toBe("openai-completions");
|
||||
expect(catalogProvider.baseUrl).toBe("https://api.deepseek.com");
|
||||
expect(catalogProvider.models?.map((model) => model.id)).toEqual([
|
||||
"deepseek-chat",
|
||||
"deepseek-reasoner",
|
||||
]);
|
||||
expect(
|
||||
catalog.provider.models?.find((model) => model.id === "deepseek-reasoner")?.reasoning,
|
||||
catalogProvider.models?.find((model) => model.id === "deepseek-reasoner")?.reasoning,
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { ModelRegistry } from "@mariozechner/pi-coding-agent";
|
||||
import type {
|
||||
ProviderResolveDynamicModelContext,
|
||||
ProviderRuntimeModel,
|
||||
} from "openclaw/plugin-sdk/plugin-entry";
|
||||
import type { ProviderRuntimeModel } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { resolveProviderPluginChoice } from "../../src/plugins/provider-auth-choice.runtime.js";
|
||||
import { registerSingleProviderPlugin } from "../../test/helpers/plugins/plugin-registration.js";
|
||||
import {
|
||||
createProviderDynamicModelContext,
|
||||
runSingleProviderCatalog,
|
||||
} from "../test-support/provider-model-test-helpers.js";
|
||||
import fireworksPlugin from "./index.js";
|
||||
import {
|
||||
FIREWORKS_BASE_URL,
|
||||
@@ -14,27 +14,6 @@ import {
|
||||
FIREWORKS_DEFAULT_MODEL_ID,
|
||||
} from "./provider-catalog.js";
|
||||
|
||||
function createDynamicContext(params: {
|
||||
provider: string;
|
||||
modelId: string;
|
||||
models: ProviderRuntimeModel[];
|
||||
}): ProviderResolveDynamicModelContext {
|
||||
return {
|
||||
provider: params.provider,
|
||||
modelId: params.modelId,
|
||||
modelRegistry: {
|
||||
find(providerId: string, modelId: string) {
|
||||
return (
|
||||
params.models.find(
|
||||
(model) =>
|
||||
model.provider === providerId && model.id.toLowerCase() === modelId.toLowerCase(),
|
||||
) ?? null
|
||||
);
|
||||
},
|
||||
} as ModelRegistry,
|
||||
};
|
||||
}
|
||||
|
||||
function createFireworksDefaultRuntimeModel(params: { reasoning: boolean }): ProviderRuntimeModel {
|
||||
return {
|
||||
id: FIREWORKS_DEFAULT_MODEL_ID,
|
||||
@@ -69,26 +48,12 @@ describe("fireworks provider plugin", () => {
|
||||
|
||||
it("builds the Fireworks Fire Pass starter catalog", async () => {
|
||||
const provider = await registerSingleProviderPlugin(fireworksPlugin);
|
||||
const catalog = await provider.catalog?.run({
|
||||
config: {},
|
||||
env: {},
|
||||
resolveProviderApiKey: () => ({ apiKey: "test-key" }),
|
||||
resolveProviderAuth: () => ({
|
||||
apiKey: "test-key",
|
||||
mode: "api_key",
|
||||
source: "env",
|
||||
}),
|
||||
} as never);
|
||||
const catalogProvider = await runSingleProviderCatalog(provider);
|
||||
|
||||
expect(catalog && "provider" in catalog).toBe(true);
|
||||
if (!catalog || !("provider" in catalog)) {
|
||||
throw new Error("expected single-provider catalog");
|
||||
}
|
||||
|
||||
expect(catalog.provider.api).toBe("openai-completions");
|
||||
expect(catalog.provider.baseUrl).toBe(FIREWORKS_BASE_URL);
|
||||
expect(catalog.provider.models?.map((model) => model.id)).toEqual([FIREWORKS_DEFAULT_MODEL_ID]);
|
||||
expect(catalog.provider.models?.[0]).toMatchObject({
|
||||
expect(catalogProvider.api).toBe("openai-completions");
|
||||
expect(catalogProvider.baseUrl).toBe(FIREWORKS_BASE_URL);
|
||||
expect(catalogProvider.models?.map((model) => model.id)).toEqual([FIREWORKS_DEFAULT_MODEL_ID]);
|
||||
expect(catalogProvider.models?.[0]).toMatchObject({
|
||||
reasoning: false,
|
||||
input: ["text", "image"],
|
||||
contextWindow: FIREWORKS_DEFAULT_CONTEXT_WINDOW,
|
||||
@@ -99,7 +64,7 @@ describe("fireworks provider plugin", () => {
|
||||
it("resolves forward-compat Fireworks model ids from the default template", async () => {
|
||||
const provider = await registerSingleProviderPlugin(fireworksPlugin);
|
||||
const resolved = provider.resolveDynamicModel?.(
|
||||
createDynamicContext({
|
||||
createProviderDynamicModelContext({
|
||||
provider: "fireworks",
|
||||
modelId: "accounts/fireworks/models/qwen3.6-plus",
|
||||
models: [createFireworksDefaultRuntimeModel({ reasoning: true })],
|
||||
@@ -118,7 +83,7 @@ describe("fireworks provider plugin", () => {
|
||||
it("disables reasoning metadata for Fireworks Kimi dynamic models", async () => {
|
||||
const provider = await registerSingleProviderPlugin(fireworksPlugin);
|
||||
const resolved = provider.resolveDynamicModel?.(
|
||||
createDynamicContext({
|
||||
createProviderDynamicModelContext({
|
||||
provider: "fireworks",
|
||||
modelId: "accounts/fireworks/models/kimi-k2p5",
|
||||
models: [createFireworksDefaultRuntimeModel({ reasoning: false })],
|
||||
@@ -135,7 +100,7 @@ describe("fireworks provider plugin", () => {
|
||||
it("disables reasoning metadata for Fireworks Kimi k2.5 aliases", async () => {
|
||||
const provider = await registerSingleProviderPlugin(fireworksPlugin);
|
||||
const resolved = provider.resolveDynamicModel?.(
|
||||
createDynamicContext({
|
||||
createProviderDynamicModelContext({
|
||||
provider: "fireworks",
|
||||
modelId: "accounts/fireworks/routers/kimi-k2.5-turbo",
|
||||
models: [createFireworksDefaultRuntimeModel({ reasoning: false })],
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import type { ModelRegistry } from "@mariozechner/pi-coding-agent";
|
||||
import type {
|
||||
ProviderResolveDynamicModelContext,
|
||||
ProviderRuntimeModel,
|
||||
} from "openclaw/plugin-sdk/plugin-entry";
|
||||
import type { ProviderRuntimeModel } from "openclaw/plugin-sdk/plugin-entry";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { createProviderDynamicModelContext as createContext } from "../test-support/provider-model-test-helpers.js";
|
||||
import { isModernGoogleModel, resolveGoogleGeminiForwardCompatModel } from "./provider-models.js";
|
||||
|
||||
function createTemplateModel(
|
||||
@@ -29,27 +26,6 @@ function createTemplateModel(
|
||||
} as ProviderRuntimeModel;
|
||||
}
|
||||
|
||||
function createContext(params: {
|
||||
provider: string;
|
||||
modelId: string;
|
||||
models: ProviderRuntimeModel[];
|
||||
}): ProviderResolveDynamicModelContext {
|
||||
return {
|
||||
provider: params.provider,
|
||||
modelId: params.modelId,
|
||||
modelRegistry: {
|
||||
find(providerId: string, modelId: string) {
|
||||
return (
|
||||
params.models.find(
|
||||
(model) =>
|
||||
model.provider === providerId && model.id.toLowerCase() === modelId.toLowerCase(),
|
||||
) ?? null
|
||||
);
|
||||
},
|
||||
} as ModelRegistry,
|
||||
};
|
||||
}
|
||||
|
||||
describe("resolveGoogleGeminiForwardCompatModel", () => {
|
||||
it("resolves stable gemini 2.5 flash-lite from direct google templates for Gemini CLI when available", () => {
|
||||
const model = resolveGoogleGeminiForwardCompatModel({
|
||||
|
||||
58
extensions/test-support/provider-model-test-helpers.ts
Normal file
58
extensions/test-support/provider-model-test-helpers.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import type { ModelRegistry } from "@mariozechner/pi-coding-agent";
|
||||
import type {
|
||||
ProviderCatalogContext,
|
||||
ProviderResolveDynamicModelContext,
|
||||
ProviderRuntimeModel,
|
||||
} from "openclaw/plugin-sdk/plugin-entry";
|
||||
import type { ProviderPlugin } from "openclaw/plugin-sdk/provider-model-shared";
|
||||
|
||||
export function createProviderDynamicModelContext(params: {
|
||||
provider: string;
|
||||
modelId: string;
|
||||
models: ProviderRuntimeModel[];
|
||||
}): ProviderResolveDynamicModelContext {
|
||||
return {
|
||||
provider: params.provider,
|
||||
modelId: params.modelId,
|
||||
modelRegistry: {
|
||||
find(providerId: string, modelId: string) {
|
||||
return (
|
||||
params.models.find(
|
||||
(model) =>
|
||||
model.provider === providerId && model.id.toLowerCase() === modelId.toLowerCase(),
|
||||
) ?? null
|
||||
);
|
||||
},
|
||||
} as ModelRegistry,
|
||||
};
|
||||
}
|
||||
|
||||
export async function runSingleProviderCatalog(
|
||||
provider: Pick<ProviderPlugin, "catalog">,
|
||||
params: {
|
||||
resolveProviderApiKey?: ProviderCatalogContext["resolveProviderApiKey"];
|
||||
resolveProviderAuth?: ProviderCatalogContext["resolveProviderAuth"];
|
||||
} = {},
|
||||
) {
|
||||
if (!provider.catalog) {
|
||||
throw new Error("expected provider catalog");
|
||||
}
|
||||
|
||||
const catalog = await provider.catalog.run({
|
||||
config: {},
|
||||
env: {},
|
||||
resolveProviderApiKey: params.resolveProviderApiKey ?? (() => ({ apiKey: "test-key" })),
|
||||
resolveProviderAuth:
|
||||
params.resolveProviderAuth ??
|
||||
(() => ({
|
||||
apiKey: "test-key",
|
||||
mode: "api_key",
|
||||
source: "env",
|
||||
})),
|
||||
} as ProviderCatalogContext);
|
||||
|
||||
if (!catalog || !("provider" in catalog)) {
|
||||
throw new Error("expected single-provider catalog");
|
||||
}
|
||||
return catalog.provider;
|
||||
}
|
||||
Reference in New Issue
Block a user