mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:20:43 +00:00
test(extensions): move provider contracts to owners
This commit is contained in:
3
extensions/anthropic/provider-runtime.contract.test.ts
Normal file
3
extensions/anthropic/provider-runtime.contract.test.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { describeAnthropicProviderRuntimeContract } from "../../test/helpers/plugins/provider-runtime-contract.js";
|
||||
|
||||
describeAnthropicProviderRuntimeContract(() => import("./index.js"));
|
||||
@@ -0,0 +1,3 @@
|
||||
import { describeCloudflareAiGatewayProviderDiscoveryContract } from "../../test/helpers/plugins/provider-discovery-contract.js";
|
||||
|
||||
describeCloudflareAiGatewayProviderDiscoveryContract(() => import("./index.js"));
|
||||
3
extensions/github-copilot/provider-auth.contract.test.ts
Normal file
3
extensions/github-copilot/provider-auth.contract.test.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { describeGithubCopilotProviderAuthContract } from "../../test/helpers/plugins/provider-auth-contract.js";
|
||||
|
||||
describeGithubCopilotProviderAuthContract(() => import("./index.js"));
|
||||
@@ -0,0 +1,7 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { describeGithubCopilotProviderDiscoveryContract } from "../../test/helpers/plugins/provider-discovery-contract.js";
|
||||
|
||||
describeGithubCopilotProviderDiscoveryContract({
|
||||
load: () => import("./index.js"),
|
||||
registerRuntimeModuleId: fileURLToPath(new URL("./register.runtime.js", import.meta.url)),
|
||||
});
|
||||
@@ -0,0 +1,3 @@
|
||||
import { describeGithubCopilotProviderRuntimeContract } from "../../test/helpers/plugins/provider-runtime-contract.js";
|
||||
|
||||
describeGithubCopilotProviderRuntimeContract(() => import("./index.js"));
|
||||
3
extensions/google/provider-runtime.contract.test.ts
Normal file
3
extensions/google/provider-runtime.contract.test.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { describeGoogleProviderRuntimeContract } from "../../test/helpers/plugins/provider-runtime-contract.js";
|
||||
|
||||
describeGoogleProviderRuntimeContract(() => import("./index.js"));
|
||||
3
extensions/minimax/provider-discovery.contract.test.ts
Normal file
3
extensions/minimax/provider-discovery.contract.test.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { describeMinimaxProviderDiscoveryContract } from "../../test/helpers/plugins/provider-discovery-contract.js";
|
||||
|
||||
describeMinimaxProviderDiscoveryContract(() => import("./index.js"));
|
||||
3
extensions/openai/provider-auth.contract.test.ts
Normal file
3
extensions/openai/provider-auth.contract.test.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { describeOpenAICodexProviderAuthContract } from "../../test/helpers/plugins/provider-auth-contract.js";
|
||||
|
||||
describeOpenAICodexProviderAuthContract(() => import("./index.js"));
|
||||
3
extensions/openai/provider-runtime.contract.test.ts
Normal file
3
extensions/openai/provider-runtime.contract.test.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { describeOpenAIProviderRuntimeContract } from "../../test/helpers/plugins/provider-runtime-contract.js";
|
||||
|
||||
describeOpenAIProviderRuntimeContract(() => import("./index.js"));
|
||||
3
extensions/openrouter/provider-runtime.contract.test.ts
Normal file
3
extensions/openrouter/provider-runtime.contract.test.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { describeOpenRouterProviderRuntimeContract } from "../../test/helpers/plugins/provider-runtime-contract.js";
|
||||
|
||||
describeOpenRouterProviderRuntimeContract(() => import("./index.js"));
|
||||
3
extensions/qwen/provider-discovery.contract.test.ts
Normal file
3
extensions/qwen/provider-discovery.contract.test.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { describeModelStudioProviderDiscoveryContract } from "../../test/helpers/plugins/provider-discovery-contract.js";
|
||||
|
||||
describeModelStudioProviderDiscoveryContract(() => import("./index.js"));
|
||||
7
extensions/sglang/provider-discovery.contract.test.ts
Normal file
7
extensions/sglang/provider-discovery.contract.test.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { describeSglangProviderDiscoveryContract } from "../../test/helpers/plugins/provider-discovery-contract.js";
|
||||
|
||||
describeSglangProviderDiscoveryContract({
|
||||
load: () => import("./index.js"),
|
||||
apiModuleId: fileURLToPath(new URL("./api.js", import.meta.url)),
|
||||
});
|
||||
3
extensions/venice/provider-runtime.contract.test.ts
Normal file
3
extensions/venice/provider-runtime.contract.test.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { describeVeniceProviderRuntimeContract } from "../../test/helpers/plugins/provider-runtime-contract.js";
|
||||
|
||||
describeVeniceProviderRuntimeContract(() => import("./index.js"));
|
||||
7
extensions/vllm/provider-discovery.contract.test.ts
Normal file
7
extensions/vllm/provider-discovery.contract.test.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { describeVllmProviderDiscoveryContract } from "../../test/helpers/plugins/provider-discovery-contract.js";
|
||||
|
||||
describeVllmProviderDiscoveryContract({
|
||||
load: () => import("./index.js"),
|
||||
apiModuleId: fileURLToPath(new URL("./api.js", import.meta.url)),
|
||||
});
|
||||
3
extensions/zai/provider-runtime.contract.test.ts
Normal file
3
extensions/zai/provider-runtime.contract.test.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { describeZAIProviderRuntimeContract } from "../../test/helpers/plugins/provider-runtime-contract.js";
|
||||
|
||||
describeZAIProviderRuntimeContract(() => import("./index.js"));
|
||||
@@ -1,7 +0,0 @@
|
||||
import {
|
||||
describeGithubCopilotProviderAuthContract,
|
||||
describeOpenAICodexProviderAuthContract,
|
||||
} from "../../../test/helpers/plugins/provider-auth-contract.js";
|
||||
|
||||
describeOpenAICodexProviderAuthContract();
|
||||
describeGithubCopilotProviderAuthContract();
|
||||
@@ -1,15 +0,0 @@
|
||||
import {
|
||||
describeCloudflareAiGatewayProviderDiscoveryContract,
|
||||
describeGithubCopilotProviderDiscoveryContract,
|
||||
describeMinimaxProviderDiscoveryContract,
|
||||
describeModelStudioProviderDiscoveryContract,
|
||||
describeSglangProviderDiscoveryContract,
|
||||
describeVllmProviderDiscoveryContract,
|
||||
} from "../../../test/helpers/plugins/provider-discovery-contract.js";
|
||||
|
||||
describeCloudflareAiGatewayProviderDiscoveryContract();
|
||||
describeGithubCopilotProviderDiscoveryContract();
|
||||
describeMinimaxProviderDiscoveryContract();
|
||||
describeModelStudioProviderDiscoveryContract();
|
||||
describeSglangProviderDiscoveryContract();
|
||||
describeVllmProviderDiscoveryContract();
|
||||
@@ -1,17 +0,0 @@
|
||||
import {
|
||||
describeAnthropicProviderRuntimeContract,
|
||||
describeGithubCopilotProviderRuntimeContract,
|
||||
describeGoogleProviderRuntimeContract,
|
||||
describeOpenAIProviderRuntimeContract,
|
||||
describeOpenRouterProviderRuntimeContract,
|
||||
describeVeniceProviderRuntimeContract,
|
||||
describeZAIProviderRuntimeContract,
|
||||
} from "../../../test/helpers/plugins/provider-runtime-contract.js";
|
||||
|
||||
describeAnthropicProviderRuntimeContract();
|
||||
describeGithubCopilotProviderRuntimeContract();
|
||||
describeGoogleProviderRuntimeContract();
|
||||
describeOpenAIProviderRuntimeContract();
|
||||
describeOpenRouterProviderRuntimeContract();
|
||||
describeVeniceProviderRuntimeContract();
|
||||
describeZAIProviderRuntimeContract();
|
||||
@@ -2,7 +2,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { clearRuntimeAuthProfileStoreSnapshots } from "../../../src/agents/auth-profiles/store.js";
|
||||
import type { AuthProfileStore } from "../../../src/agents/auth-profiles/types.js";
|
||||
import { createNonExitingRuntime } from "../../../src/runtime.js";
|
||||
import { resolveRelativeBundledPluginPublicModuleId } from "../../../src/test-utils/bundled-plugin-public-surface.js";
|
||||
import type {
|
||||
WizardMultiSelectParams,
|
||||
WizardPrompter,
|
||||
@@ -26,18 +25,10 @@ const loginOpenAICodexOAuthMock = vi.hoisted(() => vi.fn<LoginOpenAICodexOAuth>(
|
||||
const githubCopilotLoginCommandMock = vi.hoisted(() => vi.fn<GithubCopilotLoginCommand>());
|
||||
const ensureAuthProfileStoreMock = vi.hoisted(() => vi.fn<EnsureAuthProfileStore>());
|
||||
const listProfilesForProviderMock = vi.hoisted(() => vi.fn<ListProfilesForProvider>());
|
||||
const providerAuthContractModules = {
|
||||
githubCopilotIndexModuleUrl: resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "github-copilot",
|
||||
artifactBasename: "index.js",
|
||||
}),
|
||||
openAIIndexModuleUrl: resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "openai",
|
||||
artifactBasename: "index.js",
|
||||
}),
|
||||
};
|
||||
|
||||
export type ProviderAuthContractPluginLoader = () => Promise<{
|
||||
default: Parameters<typeof registerProviders>[0];
|
||||
}>;
|
||||
|
||||
vi.mock("openclaw/plugin-sdk/provider-auth-login", async () => {
|
||||
const actual = await vi.importActual<typeof import("openclaw/plugin-sdk/provider-auth-login")>(
|
||||
@@ -61,10 +52,6 @@ vi.mock("openclaw/plugin-sdk/provider-auth", async () => {
|
||||
};
|
||||
});
|
||||
|
||||
async function importBundledProviderPlugin<T>(moduleUrl: string): Promise<T> {
|
||||
return (await import(`${moduleUrl}?t=${Date.now()}`)) as T;
|
||||
}
|
||||
|
||||
function buildPrompter(): WizardPrompter {
|
||||
const progress: WizardProgress = {
|
||||
update() {},
|
||||
@@ -164,7 +151,7 @@ function installSharedAuthProfileStoreHooks(state: { authStore: AuthProfileStore
|
||||
});
|
||||
}
|
||||
|
||||
export function describeOpenAICodexProviderAuthContract() {
|
||||
export function describeOpenAICodexProviderAuthContract(load: ProviderAuthContractPluginLoader) {
|
||||
const state = {
|
||||
authStore: { version: 1, profiles: {} } as AuthProfileStore,
|
||||
};
|
||||
@@ -173,9 +160,7 @@ export function describeOpenAICodexProviderAuthContract() {
|
||||
installSharedAuthProfileStoreHooks(state);
|
||||
|
||||
async function expectStableFallbackProfile(params: { access: string; profileId: string }) {
|
||||
const { default: openAIPlugin } = await importBundledProviderPlugin<{
|
||||
default: Parameters<typeof registerProviders>[0];
|
||||
}>(providerAuthContractModules.openAIIndexModuleUrl);
|
||||
const { default: openAIPlugin } = await load();
|
||||
const provider = requireProvider(await registerProviders(openAIPlugin), "openai-codex");
|
||||
loginOpenAICodexOAuthMock.mockResolvedValueOnce({
|
||||
refresh: "refresh-token",
|
||||
@@ -194,9 +179,7 @@ export function describeOpenAICodexProviderAuthContract() {
|
||||
}
|
||||
|
||||
async function getProvider() {
|
||||
const { default: openAIPlugin } = await importBundledProviderPlugin<{
|
||||
default: Parameters<typeof registerProviders>[0];
|
||||
}>(providerAuthContractModules.openAIIndexModuleUrl);
|
||||
const { default: openAIPlugin } = await load();
|
||||
return requireProvider(await registerProviders(openAIPlugin), "openai-codex");
|
||||
}
|
||||
|
||||
@@ -317,7 +300,7 @@ export function describeOpenAICodexProviderAuthContract() {
|
||||
});
|
||||
}
|
||||
|
||||
export function describeGithubCopilotProviderAuthContract() {
|
||||
export function describeGithubCopilotProviderAuthContract(load: ProviderAuthContractPluginLoader) {
|
||||
const state = {
|
||||
authStore: { version: 1, profiles: {} } as AuthProfileStore,
|
||||
};
|
||||
@@ -326,9 +309,7 @@ export function describeGithubCopilotProviderAuthContract() {
|
||||
installSharedAuthProfileStoreHooks(state);
|
||||
|
||||
async function getProvider() {
|
||||
const { default: githubCopilotPlugin } = await importBundledProviderPlugin<{
|
||||
default: Parameters<typeof registerProviders>[0];
|
||||
}>(providerAuthContractModules.githubCopilotIndexModuleUrl);
|
||||
const { default: githubCopilotPlugin } = await load();
|
||||
return requireProvider(await registerProviders(githubCopilotPlugin), "github-copilot");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { AuthProfileStore } from "../../../src/agents/auth-profiles/types.js";
|
||||
import type { OpenClawConfig } from "../../../src/config/config.js";
|
||||
import {
|
||||
resolveBundledPluginPublicModulePath,
|
||||
resolveRelativeBundledPluginPublicModuleId,
|
||||
} from "../../../src/test-utils/bundled-plugin-public-surface.js";
|
||||
import { registerProviders, requireProvider } from "./contracts-testkit.js";
|
||||
|
||||
const resolveCopilotApiTokenMock = vi.hoisted(() => vi.fn());
|
||||
@@ -12,50 +8,10 @@ const buildVllmProviderMock = vi.hoisted(() => vi.fn());
|
||||
const buildSglangProviderMock = vi.hoisted(() => vi.fn());
|
||||
const ensureAuthProfileStoreMock = vi.hoisted(() => vi.fn());
|
||||
const listProfilesForProviderMock = vi.hoisted(() => vi.fn());
|
||||
const bundledProviderModules = {
|
||||
cloudflareAiGatewayIndexModuleUrl: resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "cloudflare-ai-gateway",
|
||||
artifactBasename: "index.js",
|
||||
}),
|
||||
githubCopilotIndexModuleUrl: resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "github-copilot",
|
||||
artifactBasename: "index.js",
|
||||
}),
|
||||
githubCopilotRegisterRuntimeModuleId: resolveBundledPluginPublicModulePath({
|
||||
pluginId: "github-copilot",
|
||||
artifactBasename: "register.runtime.js",
|
||||
}),
|
||||
minimaxIndexModuleUrl: resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "minimax",
|
||||
artifactBasename: "index.js",
|
||||
}),
|
||||
qwenIndexModuleUrl: resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "qwen",
|
||||
artifactBasename: "index.js",
|
||||
}),
|
||||
sglangApiModuleId: resolveBundledPluginPublicModulePath({
|
||||
pluginId: "sglang",
|
||||
artifactBasename: "api.js",
|
||||
}),
|
||||
sglangIndexModuleUrl: resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "sglang",
|
||||
artifactBasename: "index.js",
|
||||
}),
|
||||
vllmApiModuleId: resolveBundledPluginPublicModulePath({
|
||||
pluginId: "vllm",
|
||||
artifactBasename: "api.js",
|
||||
}),
|
||||
vllmIndexModuleUrl: resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "vllm",
|
||||
artifactBasename: "index.js",
|
||||
}),
|
||||
};
|
||||
|
||||
export type ProviderDiscoveryContractPluginLoader = () => Promise<{
|
||||
default: Parameters<typeof registerProviders>[0];
|
||||
}>;
|
||||
|
||||
type ProviderHandle = Awaited<ReturnType<typeof requireProvider>>;
|
||||
|
||||
@@ -78,6 +34,19 @@ type BundledProviderUnderTest =
|
||||
| "modelstudio"
|
||||
| "cloudflare-ai-gateway";
|
||||
|
||||
type DiscoveryContractOptions = {
|
||||
providerIds: readonly BundledProviderUnderTest[];
|
||||
loadGithubCopilot?: ProviderDiscoveryContractPluginLoader;
|
||||
loadVllm?: ProviderDiscoveryContractPluginLoader;
|
||||
loadSglang?: ProviderDiscoveryContractPluginLoader;
|
||||
loadMinimax?: ProviderDiscoveryContractPluginLoader;
|
||||
loadModelStudio?: ProviderDiscoveryContractPluginLoader;
|
||||
loadCloudflareAiGateway?: ProviderDiscoveryContractPluginLoader;
|
||||
githubCopilotRegisterRuntimeModuleId?: string;
|
||||
vllmApiModuleId?: string;
|
||||
sglangApiModuleId?: string;
|
||||
};
|
||||
|
||||
function setRuntimeAuthStore(store?: AuthProfileStore) {
|
||||
const resolvedStore = store ?? {
|
||||
version: 1,
|
||||
@@ -140,14 +109,7 @@ function runCatalog(
|
||||
});
|
||||
}
|
||||
|
||||
async function importBundledProviderPlugin<T>(moduleUrl: string): Promise<T> {
|
||||
return (await import(moduleUrl)) as T;
|
||||
}
|
||||
|
||||
function installDiscoveryHooks(
|
||||
state: DiscoveryState,
|
||||
providerIds: readonly BundledProviderUnderTest[],
|
||||
) {
|
||||
function installDiscoveryHooks(state: DiscoveryState, options: DiscoveryContractOptions) {
|
||||
beforeAll(async () => {
|
||||
vi.resetModules();
|
||||
vi.doMock("openclaw/plugin-sdk/agent-runtime", () => {
|
||||
@@ -187,80 +149,72 @@ function installDiscoveryHooks(
|
||||
validateApiKeyInput: () => undefined,
|
||||
};
|
||||
});
|
||||
vi.doMock(bundledProviderModules.githubCopilotRegisterRuntimeModuleId, async () => {
|
||||
const actual = await vi.importActual<object>(
|
||||
bundledProviderModules.githubCopilotRegisterRuntimeModuleId,
|
||||
);
|
||||
return {
|
||||
...actual,
|
||||
resolveCopilotApiToken: resolveCopilotApiTokenMock,
|
||||
};
|
||||
});
|
||||
vi.doMock(bundledProviderModules.vllmApiModuleId, async () => {
|
||||
return {
|
||||
VLLM_DEFAULT_API_KEY_ENV_VAR: "VLLM_API_KEY",
|
||||
VLLM_DEFAULT_BASE_URL: "http://127.0.0.1:8000/v1",
|
||||
VLLM_MODEL_PLACEHOLDER: "meta-llama/Meta-Llama-3-8B-Instruct",
|
||||
VLLM_PROVIDER_LABEL: "vLLM",
|
||||
buildVllmProvider: (...args: unknown[]) => buildVllmProviderMock(...args),
|
||||
};
|
||||
});
|
||||
vi.doMock(bundledProviderModules.sglangApiModuleId, async () => {
|
||||
return {
|
||||
SGLANG_DEFAULT_API_KEY_ENV_VAR: "SGLANG_API_KEY",
|
||||
SGLANG_DEFAULT_BASE_URL: "http://127.0.0.1:30000/v1",
|
||||
SGLANG_MODEL_PLACEHOLDER: "Qwen/Qwen3-8B",
|
||||
SGLANG_PROVIDER_LABEL: "SGLang",
|
||||
buildSglangProvider: (...args: unknown[]) => buildSglangProviderMock(...args),
|
||||
};
|
||||
});
|
||||
if (options.githubCopilotRegisterRuntimeModuleId) {
|
||||
vi.doMock(options.githubCopilotRegisterRuntimeModuleId, async () => {
|
||||
const actual = await vi.importActual<object>(options.githubCopilotRegisterRuntimeModuleId!);
|
||||
return {
|
||||
...actual,
|
||||
resolveCopilotApiToken: resolveCopilotApiTokenMock,
|
||||
};
|
||||
});
|
||||
}
|
||||
if (options.vllmApiModuleId) {
|
||||
vi.doMock(options.vllmApiModuleId, async () => {
|
||||
return {
|
||||
VLLM_DEFAULT_API_KEY_ENV_VAR: "VLLM_API_KEY",
|
||||
VLLM_DEFAULT_BASE_URL: "http://127.0.0.1:8000/v1",
|
||||
VLLM_MODEL_PLACEHOLDER: "meta-llama/Meta-Llama-3-8B-Instruct",
|
||||
VLLM_PROVIDER_LABEL: "vLLM",
|
||||
buildVllmProvider: (...args: unknown[]) => buildVllmProviderMock(...args),
|
||||
};
|
||||
});
|
||||
}
|
||||
if (options.sglangApiModuleId) {
|
||||
vi.doMock(options.sglangApiModuleId, async () => {
|
||||
return {
|
||||
SGLANG_DEFAULT_API_KEY_ENV_VAR: "SGLANG_API_KEY",
|
||||
SGLANG_DEFAULT_BASE_URL: "http://127.0.0.1:30000/v1",
|
||||
SGLANG_MODEL_PLACEHOLDER: "Qwen/Qwen3-8B",
|
||||
SGLANG_PROVIDER_LABEL: "SGLang",
|
||||
buildSglangProvider: (...args: unknown[]) => buildSglangProviderMock(...args),
|
||||
};
|
||||
});
|
||||
}
|
||||
({ runProviderCatalog: state.runProviderCatalog } =
|
||||
await import("../../../src/plugins/provider-discovery.js"));
|
||||
|
||||
if (providerIds.includes("github-copilot")) {
|
||||
const { default: githubCopilotPlugin } = await importBundledProviderPlugin<{
|
||||
default: Parameters<typeof registerProviders>[0];
|
||||
}>(bundledProviderModules.githubCopilotIndexModuleUrl);
|
||||
if (options.providerIds.includes("github-copilot")) {
|
||||
const { default: githubCopilotPlugin } = await options.loadGithubCopilot!();
|
||||
state.githubCopilotProvider = requireProvider(
|
||||
await registerProviders(githubCopilotPlugin),
|
||||
"github-copilot",
|
||||
);
|
||||
}
|
||||
|
||||
if (providerIds.includes("vllm")) {
|
||||
const { default: vllmPlugin } = await importBundledProviderPlugin<{
|
||||
default: Parameters<typeof registerProviders>[0];
|
||||
}>(bundledProviderModules.vllmIndexModuleUrl);
|
||||
if (options.providerIds.includes("vllm")) {
|
||||
const { default: vllmPlugin } = await options.loadVllm!();
|
||||
state.vllmProvider = requireProvider(await registerProviders(vllmPlugin), "vllm");
|
||||
}
|
||||
|
||||
if (providerIds.includes("sglang")) {
|
||||
const { default: sglangPlugin } = await importBundledProviderPlugin<{
|
||||
default: Parameters<typeof registerProviders>[0];
|
||||
}>(bundledProviderModules.sglangIndexModuleUrl);
|
||||
if (options.providerIds.includes("sglang")) {
|
||||
const { default: sglangPlugin } = await options.loadSglang!();
|
||||
state.sglangProvider = requireProvider(await registerProviders(sglangPlugin), "sglang");
|
||||
}
|
||||
|
||||
if (providerIds.includes("minimax")) {
|
||||
const { default: minimaxPlugin } = await importBundledProviderPlugin<{
|
||||
default: Parameters<typeof registerProviders>[0];
|
||||
}>(bundledProviderModules.minimaxIndexModuleUrl);
|
||||
if (options.providerIds.includes("minimax")) {
|
||||
const { default: minimaxPlugin } = await options.loadMinimax!();
|
||||
const registeredProviders = await registerProviders(minimaxPlugin);
|
||||
state.minimaxProvider = requireProvider(registeredProviders, "minimax");
|
||||
state.minimaxPortalProvider = requireProvider(registeredProviders, "minimax-portal");
|
||||
}
|
||||
|
||||
if (providerIds.includes("modelstudio")) {
|
||||
const { default: qwenPlugin } = await importBundledProviderPlugin<{
|
||||
default: Parameters<typeof registerProviders>[0];
|
||||
}>(bundledProviderModules.qwenIndexModuleUrl);
|
||||
if (options.providerIds.includes("modelstudio")) {
|
||||
const { default: qwenPlugin } = await options.loadModelStudio!();
|
||||
state.modelStudioProvider = requireProvider(await registerProviders(qwenPlugin), "qwen");
|
||||
}
|
||||
|
||||
if (providerIds.includes("cloudflare-ai-gateway")) {
|
||||
const { default: cloudflareAiGatewayPlugin } = await importBundledProviderPlugin<{
|
||||
default: Parameters<typeof registerProviders>[0];
|
||||
}>(bundledProviderModules.cloudflareAiGatewayIndexModuleUrl);
|
||||
if (options.providerIds.includes("cloudflare-ai-gateway")) {
|
||||
const { default: cloudflareAiGatewayPlugin } = await options.loadCloudflareAiGateway!();
|
||||
state.cloudflareAiGatewayProvider = requireProvider(
|
||||
await registerProviders(cloudflareAiGatewayPlugin),
|
||||
"cloudflare-ai-gateway",
|
||||
@@ -283,11 +237,18 @@ function installDiscoveryHooks(
|
||||
});
|
||||
}
|
||||
|
||||
export function describeGithubCopilotProviderDiscoveryContract() {
|
||||
export function describeGithubCopilotProviderDiscoveryContract(params: {
|
||||
load: ProviderDiscoveryContractPluginLoader;
|
||||
registerRuntimeModuleId: string;
|
||||
}) {
|
||||
const state = {} as DiscoveryState;
|
||||
|
||||
describe("github-copilot provider discovery contract", () => {
|
||||
installDiscoveryHooks(state, ["github-copilot"]);
|
||||
installDiscoveryHooks(state, {
|
||||
providerIds: ["github-copilot"],
|
||||
loadGithubCopilot: params.load,
|
||||
githubCopilotRegisterRuntimeModuleId: params.registerRuntimeModuleId,
|
||||
});
|
||||
|
||||
it("keeps catalog disabled without env tokens or profiles", async () => {
|
||||
await expect(
|
||||
@@ -341,11 +302,18 @@ export function describeGithubCopilotProviderDiscoveryContract() {
|
||||
});
|
||||
}
|
||||
|
||||
export function describeVllmProviderDiscoveryContract() {
|
||||
export function describeVllmProviderDiscoveryContract(params: {
|
||||
load: ProviderDiscoveryContractPluginLoader;
|
||||
apiModuleId: string;
|
||||
}) {
|
||||
const state = {} as DiscoveryState;
|
||||
|
||||
describe("vllm provider discovery contract", () => {
|
||||
installDiscoveryHooks(state, ["vllm"]);
|
||||
installDiscoveryHooks(state, {
|
||||
providerIds: ["vllm"],
|
||||
loadVllm: params.load,
|
||||
vllmApiModuleId: params.apiModuleId,
|
||||
});
|
||||
|
||||
it("keeps self-hosted discovery provider-owned", async () => {
|
||||
buildVllmProviderMock.mockResolvedValueOnce({
|
||||
@@ -387,11 +355,18 @@ export function describeVllmProviderDiscoveryContract() {
|
||||
});
|
||||
}
|
||||
|
||||
export function describeSglangProviderDiscoveryContract() {
|
||||
export function describeSglangProviderDiscoveryContract(params: {
|
||||
load: ProviderDiscoveryContractPluginLoader;
|
||||
apiModuleId: string;
|
||||
}) {
|
||||
const state = {} as DiscoveryState;
|
||||
|
||||
describe("sglang provider discovery contract", () => {
|
||||
installDiscoveryHooks(state, ["sglang"]);
|
||||
installDiscoveryHooks(state, {
|
||||
providerIds: ["sglang"],
|
||||
loadSglang: params.load,
|
||||
sglangApiModuleId: params.apiModuleId,
|
||||
});
|
||||
|
||||
it("keeps self-hosted discovery provider-owned", async () => {
|
||||
buildSglangProviderMock.mockResolvedValueOnce({
|
||||
@@ -433,11 +408,13 @@ export function describeSglangProviderDiscoveryContract() {
|
||||
});
|
||||
}
|
||||
|
||||
export function describeMinimaxProviderDiscoveryContract() {
|
||||
export function describeMinimaxProviderDiscoveryContract(
|
||||
load: ProviderDiscoveryContractPluginLoader,
|
||||
) {
|
||||
const state = {} as DiscoveryState;
|
||||
|
||||
describe("minimax provider discovery contract", () => {
|
||||
installDiscoveryHooks(state, ["minimax"]);
|
||||
installDiscoveryHooks(state, { providerIds: ["minimax"], loadMinimax: load });
|
||||
|
||||
it("keeps API catalog provider-owned", async () => {
|
||||
await expect(
|
||||
@@ -542,11 +519,13 @@ export function describeMinimaxProviderDiscoveryContract() {
|
||||
});
|
||||
}
|
||||
|
||||
export function describeModelStudioProviderDiscoveryContract() {
|
||||
export function describeModelStudioProviderDiscoveryContract(
|
||||
load: ProviderDiscoveryContractPluginLoader,
|
||||
) {
|
||||
const state = {} as DiscoveryState;
|
||||
|
||||
describe("modelstudio provider discovery contract", () => {
|
||||
installDiscoveryHooks(state, ["modelstudio"]);
|
||||
installDiscoveryHooks(state, { providerIds: ["modelstudio"], loadModelStudio: load });
|
||||
|
||||
it("keeps catalog provider-owned", async () => {
|
||||
await expect(
|
||||
@@ -589,11 +568,16 @@ export function describeModelStudioProviderDiscoveryContract() {
|
||||
});
|
||||
}
|
||||
|
||||
export function describeCloudflareAiGatewayProviderDiscoveryContract() {
|
||||
export function describeCloudflareAiGatewayProviderDiscoveryContract(
|
||||
load: ProviderDiscoveryContractPluginLoader,
|
||||
) {
|
||||
const state = {} as DiscoveryState;
|
||||
|
||||
describe("cloudflare-ai-gateway provider discovery contract", () => {
|
||||
installDiscoveryHooks(state, ["cloudflare-ai-gateway"]);
|
||||
installDiscoveryHooks(state, {
|
||||
providerIds: ["cloudflare-ai-gateway"],
|
||||
loadCloudflareAiGateway: load,
|
||||
});
|
||||
|
||||
it("keeps catalog disabled without stored metadata", async () => {
|
||||
await expect(
|
||||
|
||||
@@ -3,7 +3,6 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { ProviderPlugin, ProviderRuntimeModel } from "../../../src/plugins/types.js";
|
||||
import { resolveRelativeBundledPluginPublicModuleId } from "../../../src/test-utils/bundled-plugin-public-surface.js";
|
||||
import {
|
||||
createProviderUsageFetch,
|
||||
makeResponse,
|
||||
@@ -20,43 +19,6 @@ const getOAuthProvidersMock = vi.hoisted(() =>
|
||||
{ id: "openai-codex", envApiKey: "OPENAI_API_KEY", oauthTokenEnv: "OPENAI_OAUTH_TOKEN" },
|
||||
]),
|
||||
);
|
||||
const providerRuntimeContractModules = {
|
||||
anthropicIndexModuleId: resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "anthropic",
|
||||
artifactBasename: "index.js",
|
||||
}),
|
||||
githubCopilotIndexModuleId: resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "github-copilot",
|
||||
artifactBasename: "index.js",
|
||||
}),
|
||||
googleIndexModuleId: resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "google",
|
||||
artifactBasename: "index.js",
|
||||
}),
|
||||
openAIIndexModuleId: resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "openai",
|
||||
artifactBasename: "index.js",
|
||||
}),
|
||||
openRouterIndexModuleId: resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "openrouter",
|
||||
artifactBasename: "index.js",
|
||||
}),
|
||||
veniceIndexModuleId: resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "venice",
|
||||
artifactBasename: "index.js",
|
||||
}),
|
||||
zaiIndexModuleId: resolveRelativeBundledPluginPublicModuleId({
|
||||
fromModuleUrl: import.meta.url,
|
||||
pluginId: "zai",
|
||||
artifactBasename: "index.js",
|
||||
}),
|
||||
};
|
||||
|
||||
vi.mock("@mariozechner/pi-ai/oauth", async () => {
|
||||
const actual = await vi.importActual<typeof import("@mariozechner/pi-ai/oauth")>(
|
||||
@@ -69,10 +31,6 @@ vi.mock("@mariozechner/pi-ai/oauth", async () => {
|
||||
};
|
||||
});
|
||||
|
||||
async function importBundledProviderPlugin<T>(moduleUrl: string): Promise<T> {
|
||||
return (await import(moduleUrl)) as T;
|
||||
}
|
||||
|
||||
function createModel(overrides: Partial<ProviderRuntimeModel> & Pick<ProviderRuntimeModel, "id">) {
|
||||
return {
|
||||
id: overrides.id,
|
||||
@@ -92,133 +50,77 @@ type ProviderRuntimeContractFixture = {
|
||||
providerIds: string[];
|
||||
pluginId: string;
|
||||
name: string;
|
||||
load: () => Promise<{ default: Parameters<typeof registerProviderPlugin>[0]["plugin"] }>;
|
||||
load: ProviderRuntimeContractPluginLoader;
|
||||
};
|
||||
|
||||
const PROVIDER_RUNTIME_CONTRACT_FIXTURES: readonly ProviderRuntimeContractFixture[] = [
|
||||
{
|
||||
providerIds: ["anthropic"],
|
||||
pluginId: "anthropic",
|
||||
name: "Anthropic",
|
||||
load: async () =>
|
||||
await importBundledProviderPlugin<{
|
||||
default: Parameters<typeof registerProviderPlugin>[0]["plugin"];
|
||||
}>(providerRuntimeContractModules.anthropicIndexModuleId),
|
||||
},
|
||||
{
|
||||
providerIds: ["github-copilot"],
|
||||
pluginId: "github-copilot",
|
||||
name: "GitHub Copilot",
|
||||
load: async () =>
|
||||
await importBundledProviderPlugin<{
|
||||
default: Parameters<typeof registerProviderPlugin>[0]["plugin"];
|
||||
}>(providerRuntimeContractModules.githubCopilotIndexModuleId),
|
||||
},
|
||||
{
|
||||
providerIds: ["google", "google-gemini-cli"],
|
||||
pluginId: "google",
|
||||
name: "Google",
|
||||
load: async () =>
|
||||
await importBundledProviderPlugin<{
|
||||
default: Parameters<typeof registerProviderPlugin>[0]["plugin"];
|
||||
}>(providerRuntimeContractModules.googleIndexModuleId),
|
||||
},
|
||||
{
|
||||
providerIds: ["openai", "openai-codex"],
|
||||
pluginId: "openai",
|
||||
name: "OpenAI",
|
||||
load: async () =>
|
||||
await importBundledProviderPlugin<{
|
||||
default: Parameters<typeof registerProviderPlugin>[0]["plugin"];
|
||||
}>(providerRuntimeContractModules.openAIIndexModuleId),
|
||||
},
|
||||
{
|
||||
providerIds: ["openrouter"],
|
||||
pluginId: "openrouter",
|
||||
name: "OpenRouter",
|
||||
load: async () =>
|
||||
await importBundledProviderPlugin<{
|
||||
default: Parameters<typeof registerProviderPlugin>[0]["plugin"];
|
||||
}>(providerRuntimeContractModules.openRouterIndexModuleId),
|
||||
},
|
||||
{
|
||||
providerIds: ["venice"],
|
||||
pluginId: "venice",
|
||||
name: "Venice",
|
||||
load: async () =>
|
||||
await importBundledProviderPlugin<{
|
||||
default: Parameters<typeof registerProviderPlugin>[0]["plugin"];
|
||||
}>(providerRuntimeContractModules.veniceIndexModuleId),
|
||||
},
|
||||
{
|
||||
providerIds: ["zai"],
|
||||
pluginId: "zai",
|
||||
name: "Z.AI",
|
||||
load: async () =>
|
||||
await importBundledProviderPlugin<{
|
||||
default: Parameters<typeof registerProviderPlugin>[0]["plugin"];
|
||||
}>(providerRuntimeContractModules.zaiIndexModuleId),
|
||||
},
|
||||
] as const;
|
||||
export type ProviderRuntimeContractPluginLoader = () => Promise<{
|
||||
default: Parameters<typeof registerProviderPlugin>[0]["plugin"];
|
||||
}>;
|
||||
|
||||
const providerRuntimeContractProviders = new Map<string, ProviderPlugin>();
|
||||
let providerRuntimeContractLoadPromise: Promise<void> | null = null;
|
||||
function installRuntimeHooks(fixtures: readonly ProviderRuntimeContractFixture[]) {
|
||||
const providers = new Map<string, ProviderPlugin>();
|
||||
let loadPromise: Promise<void> | null = null;
|
||||
|
||||
function requireProviderContractProvider(providerId: string): ProviderPlugin {
|
||||
const provider = providerRuntimeContractProviders.get(providerId);
|
||||
if (!provider) {
|
||||
throw new Error(`provider runtime contract fixture missing for ${providerId}`);
|
||||
function requireProviderContractProvider(providerId: string): ProviderPlugin {
|
||||
const provider = providers.get(providerId);
|
||||
if (!provider) {
|
||||
throw new Error(`provider runtime contract fixture missing for ${providerId}`);
|
||||
}
|
||||
return provider;
|
||||
}
|
||||
return provider;
|
||||
}
|
||||
|
||||
async function ensureProviderRuntimeContractProvidersLoaded() {
|
||||
if (!providerRuntimeContractLoadPromise) {
|
||||
providerRuntimeContractLoadPromise = (async () => {
|
||||
providerRuntimeContractProviders.clear();
|
||||
const registeredFixtures = await Promise.all(
|
||||
PROVIDER_RUNTIME_CONTRACT_FIXTURES.map(async (fixture) => {
|
||||
const plugin = await fixture.load();
|
||||
return {
|
||||
fixture,
|
||||
providers: (
|
||||
await registerProviderPlugin({
|
||||
plugin: plugin.default,
|
||||
id: fixture.pluginId,
|
||||
name: fixture.name,
|
||||
})
|
||||
).providers,
|
||||
};
|
||||
}),
|
||||
);
|
||||
for (const { fixture, providers } of registeredFixtures) {
|
||||
for (const providerId of fixture.providerIds) {
|
||||
providerRuntimeContractProviders.set(
|
||||
providerId,
|
||||
requireRegisteredProvider(providers, providerId, "provider"),
|
||||
);
|
||||
async function ensureProvidersLoaded() {
|
||||
if (!loadPromise) {
|
||||
loadPromise = (async () => {
|
||||
providers.clear();
|
||||
const registeredFixtures = await Promise.all(
|
||||
fixtures.map(async (fixture) => {
|
||||
const plugin = await fixture.load();
|
||||
return {
|
||||
fixture,
|
||||
providers: (
|
||||
await registerProviderPlugin({
|
||||
plugin: plugin.default,
|
||||
id: fixture.pluginId,
|
||||
name: fixture.name,
|
||||
})
|
||||
).providers,
|
||||
};
|
||||
}),
|
||||
);
|
||||
for (const { fixture, providers: registeredProviders } of registeredFixtures) {
|
||||
for (const providerId of fixture.providerIds) {
|
||||
providers.set(
|
||||
providerId,
|
||||
requireRegisteredProvider(registeredProviders, providerId, "provider"),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
})();
|
||||
}
|
||||
|
||||
await loadPromise;
|
||||
}
|
||||
|
||||
await providerRuntimeContractLoadPromise;
|
||||
}
|
||||
|
||||
function installRuntimeHooks() {
|
||||
beforeAll(async () => {
|
||||
await ensureProviderRuntimeContractProvidersLoaded();
|
||||
await ensureProvidersLoaded();
|
||||
}, CONTRACT_SETUP_TIMEOUT_MS);
|
||||
|
||||
beforeEach(() => {
|
||||
refreshOpenAICodexTokenMock.mockReset();
|
||||
getOAuthProvidersMock.mockClear();
|
||||
}, CONTRACT_SETUP_TIMEOUT_MS);
|
||||
|
||||
return requireProviderContractProvider;
|
||||
}
|
||||
|
||||
export function describeAnthropicProviderRuntimeContract() {
|
||||
export function describeAnthropicProviderRuntimeContract(
|
||||
load: ProviderRuntimeContractPluginLoader,
|
||||
) {
|
||||
describe("anthropic provider runtime contract", { timeout: CONTRACT_SETUP_TIMEOUT_MS }, () => {
|
||||
installRuntimeHooks();
|
||||
const requireProviderContractProvider = installRuntimeHooks([
|
||||
{ providerIds: ["anthropic"], pluginId: "anthropic", name: "Anthropic", load },
|
||||
]);
|
||||
|
||||
it("owns anthropic 4.6 forward-compat resolution", () => {
|
||||
const provider = requireProviderContractProvider("anthropic");
|
||||
@@ -329,12 +231,21 @@ export function describeAnthropicProviderRuntimeContract() {
|
||||
});
|
||||
}
|
||||
|
||||
export function describeGithubCopilotProviderRuntimeContract() {
|
||||
export function describeGithubCopilotProviderRuntimeContract(
|
||||
load: ProviderRuntimeContractPluginLoader,
|
||||
) {
|
||||
describe(
|
||||
"github-copilot provider runtime contract",
|
||||
{ timeout: CONTRACT_SETUP_TIMEOUT_MS },
|
||||
() => {
|
||||
installRuntimeHooks();
|
||||
const requireProviderContractProvider = installRuntimeHooks([
|
||||
{
|
||||
providerIds: ["github-copilot"],
|
||||
pluginId: "github-copilot",
|
||||
name: "GitHub Copilot",
|
||||
load,
|
||||
},
|
||||
]);
|
||||
|
||||
it("owns Copilot-specific forward-compat fallbacks", () => {
|
||||
const provider = requireProviderContractProvider("github-copilot");
|
||||
@@ -364,9 +275,11 @@ export function describeGithubCopilotProviderRuntimeContract() {
|
||||
);
|
||||
}
|
||||
|
||||
export function describeGoogleProviderRuntimeContract() {
|
||||
export function describeGoogleProviderRuntimeContract(load: ProviderRuntimeContractPluginLoader) {
|
||||
describe("google provider runtime contract", { timeout: CONTRACT_SETUP_TIMEOUT_MS }, () => {
|
||||
installRuntimeHooks();
|
||||
const requireProviderContractProvider = installRuntimeHooks([
|
||||
{ providerIds: ["google", "google-gemini-cli"], pluginId: "google", name: "Google", load },
|
||||
]);
|
||||
|
||||
it("owns google direct gemini 3.1 forward-compat resolution", () => {
|
||||
const provider = requireProviderContractProvider("google");
|
||||
@@ -494,9 +407,11 @@ export function describeGoogleProviderRuntimeContract() {
|
||||
});
|
||||
}
|
||||
|
||||
export function describeOpenAIProviderRuntimeContract() {
|
||||
export function describeOpenAIProviderRuntimeContract(load: ProviderRuntimeContractPluginLoader) {
|
||||
describe("openai provider runtime contract", { timeout: CONTRACT_SETUP_TIMEOUT_MS }, () => {
|
||||
installRuntimeHooks();
|
||||
const requireProviderContractProvider = installRuntimeHooks([
|
||||
{ providerIds: ["openai", "openai-codex"], pluginId: "openai", name: "OpenAI", load },
|
||||
]);
|
||||
|
||||
it("owns openai gpt-5.4 forward-compat resolution", () => {
|
||||
const provider = requireProviderContractProvider("openai");
|
||||
@@ -702,9 +617,13 @@ export function describeOpenAIProviderRuntimeContract() {
|
||||
});
|
||||
}
|
||||
|
||||
export function describeOpenRouterProviderRuntimeContract() {
|
||||
export function describeOpenRouterProviderRuntimeContract(
|
||||
load: ProviderRuntimeContractPluginLoader,
|
||||
) {
|
||||
describe("openrouter provider runtime contract", { timeout: CONTRACT_SETUP_TIMEOUT_MS }, () => {
|
||||
installRuntimeHooks();
|
||||
const requireProviderContractProvider = installRuntimeHooks([
|
||||
{ providerIds: ["openrouter"], pluginId: "openrouter", name: "OpenRouter", load },
|
||||
]);
|
||||
|
||||
it("owns dynamic OpenRouter model defaults", () => {
|
||||
const provider = requireProviderContractProvider("openrouter");
|
||||
@@ -727,9 +646,11 @@ export function describeOpenRouterProviderRuntimeContract() {
|
||||
});
|
||||
}
|
||||
|
||||
export function describeVeniceProviderRuntimeContract() {
|
||||
export function describeVeniceProviderRuntimeContract(load: ProviderRuntimeContractPluginLoader) {
|
||||
describe("venice provider runtime contract", { timeout: CONTRACT_SETUP_TIMEOUT_MS }, () => {
|
||||
installRuntimeHooks();
|
||||
const requireProviderContractProvider = installRuntimeHooks([
|
||||
{ providerIds: ["venice"], pluginId: "venice", name: "Venice", load },
|
||||
]);
|
||||
|
||||
it("owns xai downstream compat flags for grok-backed Venice models", () => {
|
||||
const provider = requireProviderContractProvider("venice");
|
||||
@@ -755,9 +676,11 @@ export function describeVeniceProviderRuntimeContract() {
|
||||
});
|
||||
}
|
||||
|
||||
export function describeZAIProviderRuntimeContract() {
|
||||
export function describeZAIProviderRuntimeContract(load: ProviderRuntimeContractPluginLoader) {
|
||||
describe("zai provider runtime contract", { timeout: CONTRACT_SETUP_TIMEOUT_MS }, () => {
|
||||
installRuntimeHooks();
|
||||
const requireProviderContractProvider = installRuntimeHooks([
|
||||
{ providerIds: ["zai"], pluginId: "zai", name: "Z.AI", load },
|
||||
]);
|
||||
|
||||
it("owns glm-5 forward-compat resolution", () => {
|
||||
const provider = requireProviderContractProvider("zai");
|
||||
|
||||
Reference in New Issue
Block a user