test(boundary): route helper imports through bundled plugin surfaces

This commit is contained in:
Vincent Koc
2026-04-10 08:03:42 +01:00
parent 50f5091979
commit 3cea11d3b6
18 changed files with 516 additions and 153 deletions

View File

@@ -1,5 +1,15 @@
import { loadBundledPluginContractApiSync } from "../../../src/test-utils/bundled-plugin-public-surface.js";
type IMessageContractSurface = typeof import("@openclaw/imessage/contract-api.js");
const {
DEFAULT_IMESSAGE_ATTACHMENT_ROOTS,
resolveIMessageAttachmentRoots,
resolveIMessageRemoteAttachmentRoots,
} = loadBundledPluginContractApiSync<IMessageContractSurface>("imessage");
export {
DEFAULT_IMESSAGE_ATTACHMENT_ROOTS,
resolveIMessageAttachmentRoots,
resolveIMessageRemoteAttachmentRoots,
} from "../../../extensions/imessage/contract-api.js";
};

View File

@@ -1,6 +1,22 @@
export { buildTelegramModelsProviderChannelData } from "../../../extensions/telegram/contract-api.js";
export { whatsappCommandPolicy } from "../../../extensions/whatsapp/contract-api.js";
import {
loadBundledPluginApiSync,
loadBundledPluginContractApiSync,
} from "../../../src/test-utils/bundled-plugin-public-surface.js";
type TelegramContractSurface = typeof import("@openclaw/telegram/contract-api.js");
type WhatsAppApiSurface = Pick<
typeof import("@openclaw/whatsapp/api.js"),
"isWhatsAppGroupJid" | "normalizeWhatsAppTarget" | "whatsappCommandPolicy"
>;
const { buildTelegramModelsProviderChannelData } =
loadBundledPluginContractApiSync<TelegramContractSurface>("telegram");
const { isWhatsAppGroupJid, normalizeWhatsAppTarget, whatsappCommandPolicy } =
loadBundledPluginApiSync<WhatsAppApiSurface>("whatsapp");
export {
buildTelegramModelsProviderChannelData,
isWhatsAppGroupJid,
normalizeWhatsAppTarget,
} from "../../../extensions/whatsapp/contract-api.js";
whatsappCommandPolicy,
};

View File

@@ -1,4 +1,13 @@
export {
isSignalSenderAllowed,
type SignalSender,
} from "../../../extensions/signal/contract-api.js";
import type { SignalSender } from "@openclaw/signal/contract-api.js";
import { loadBundledPluginContractApiSync } from "../../../src/test-utils/bundled-plugin-public-surface.js";
type SignalContractApiSurface = Pick<
typeof import("@openclaw/signal/contract-api.js"),
"isSignalSenderAllowed"
>;
const { isSignalSenderAllowed } =
loadBundledPluginContractApiSync<SignalContractApiSurface>("signal");
export { isSignalSenderAllowed };
export type { SignalSender };

View File

@@ -1,5 +1,15 @@
export { resolveWhatsAppRuntimeGroupPolicy } from "../../../extensions/whatsapp/test-api.js";
import { loadBundledPluginTestApiSync } from "../../../src/test-utils/bundled-plugin-public-surface.js";
type WhatsAppTestSurface = typeof import("@openclaw/whatsapp/test-api.js");
type ZaloTestSurface = typeof import("@openclaw/zalo/test-api.js");
const { resolveWhatsAppRuntimeGroupPolicy } =
loadBundledPluginTestApiSync<WhatsAppTestSurface>("whatsapp");
const { evaluateZaloGroupAccess, resolveZaloRuntimeGroupPolicy } =
loadBundledPluginTestApiSync<ZaloTestSurface>("zalo");
export {
evaluateZaloGroupAccess,
resolveWhatsAppRuntimeGroupPolicy,
resolveZaloRuntimeGroupPolicy,
} from "../../../extensions/zalo/test-api.js";
};

View File

@@ -1,11 +1,12 @@
import { expect, it } from "vitest";
import type { ResolvedSlackAccount } from "../../../extensions/slack/api.js";
import type { MsgContext } from "../../../src/auto-reply/templating.js";
import { expectChannelInboundContextContract } from "../../../src/channels/plugins/contracts/test-helpers.js";
import type { OpenClawConfig } from "../../../src/config/config.js";
import { resolveRelativeBundledPluginPublicModuleId } from "../../../src/test-utils/bundled-plugin-public-surface.js";
import { withTempHome } from "../temp-home.js";
type ResolvedSlackAccount = import("@openclaw/slack/api.js").ResolvedSlackAccount;
type SlackMessageEvent = {
channel: string;
channel_type?: string;

View File

@@ -1,12 +1,12 @@
export type {
DiscordInteractiveHandlerContext,
DiscordInteractiveHandlerRegistration,
} from "../../../extensions/discord/contract-api.js";
} from "@openclaw/discord/contract-api.js";
export type {
SlackInteractiveHandlerContext,
SlackInteractiveHandlerRegistration,
} from "../../../extensions/slack/contract-api.js";
} from "@openclaw/slack/contract-api.js";
export type {
TelegramInteractiveHandlerContext,
TelegramInteractiveHandlerRegistration,
} from "../../../extensions/telegram/contract-api.js";
} from "@openclaw/telegram/contract-api.js";

View File

@@ -1 +1,8 @@
export { matrixSetupAdapter, matrixSetupWizard } from "../../../extensions/matrix/contract-api.js";
import { loadBundledPluginContractApiSync } from "../../../src/test-utils/bundled-plugin-public-surface.js";
type MatrixContractSurface = typeof import("@openclaw/matrix/contract-api.js");
const { matrixSetupAdapter, matrixSetupWizard } =
loadBundledPluginContractApiSync<MatrixContractSurface>("matrix");
export { matrixSetupAdapter, matrixSetupWizard };

View File

@@ -1,27 +1,4 @@
import { describe, expect, expectTypeOf, it } from "vitest";
import {
listDiscordDirectoryGroupsFromConfig,
listDiscordDirectoryPeersFromConfig,
type DiscordProbe,
type DiscordTokenResolution,
} from "../../../extensions/discord/api.js";
import type { IMessageProbe } from "../../../extensions/imessage/runtime-api.js";
import type { SignalProbe } from "../../../extensions/signal/api.js";
import {
listSlackDirectoryGroupsFromConfig,
listSlackDirectoryPeersFromConfig,
type SlackProbe,
} from "../../../extensions/slack/api.js";
import {
listTelegramDirectoryGroupsFromConfig,
listTelegramDirectoryPeersFromConfig,
type TelegramProbe,
type TelegramTokenResolution,
} from "../../../extensions/telegram/api.js";
import {
listWhatsAppDirectoryGroupsFromConfig,
listWhatsAppDirectoryPeersFromConfig,
} from "../../../extensions/whatsapp/api.js";
import type {
BaseProbeResult,
BaseTokenResolution,
@@ -29,8 +6,30 @@ import type {
} from "../../../src/channels/plugins/types.js";
import type { OpenClawConfig } from "../../../src/config/config.js";
import type { LineProbeResult } from "../../../src/plugin-sdk/line.js";
import { loadBundledPluginApiSync } from "../../../src/test-utils/bundled-plugin-public-surface.js";
import { withEnvAsync } from "../../../src/test-utils/env.js";
type DiscordApiSurface = typeof import("@openclaw/discord/api.js");
type DiscordProbe = import("@openclaw/discord/api.js").DiscordProbe;
type DiscordTokenResolution = import("@openclaw/discord/api.js").DiscordTokenResolution;
type IMessageProbe = import("@openclaw/imessage/runtime-api.js").IMessageProbe;
type SignalProbe = import("@openclaw/signal/api.js").SignalProbe;
type SlackApiSurface = typeof import("@openclaw/slack/api.js");
type SlackProbe = import("@openclaw/slack/api.js").SlackProbe;
type TelegramApiSurface = typeof import("@openclaw/telegram/api.js");
type TelegramProbe = import("@openclaw/telegram/api.js").TelegramProbe;
type TelegramTokenResolution = import("@openclaw/telegram/api.js").TelegramTokenResolution;
type WhatsAppApiSurface = typeof import("@openclaw/whatsapp/api.js");
const { listDiscordDirectoryGroupsFromConfig, listDiscordDirectoryPeersFromConfig } =
loadBundledPluginApiSync<DiscordApiSurface>("discord");
const { listSlackDirectoryGroupsFromConfig, listSlackDirectoryPeersFromConfig } =
loadBundledPluginApiSync<SlackApiSurface>("slack");
const { listTelegramDirectoryGroupsFromConfig, listTelegramDirectoryPeersFromConfig } =
loadBundledPluginApiSync<TelegramApiSurface>("telegram");
const { listWhatsAppDirectoryGroupsFromConfig, listWhatsAppDirectoryPeersFromConfig } =
loadBundledPluginApiSync<WhatsAppApiSurface>("whatsapp");
type DirectoryListFn = (params: {
cfg: OpenClawConfig;
accountId?: string;

View File

@@ -1,14 +1,4 @@
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { bluebubblesPlugin } from "../../../extensions/bluebubbles/api.js";
import {
discordPlugin,
discordThreadBindingTesting,
} from "../../../extensions/discord/test-api.js";
import { feishuPlugin, feishuThreadBindingTesting } from "../../../extensions/feishu/api.js";
import { imessagePlugin } from "../../../extensions/imessage/api.js";
import { matrixPlugin, setMatrixRuntime } from "../../../extensions/matrix/test-api.js";
import { telegramPlugin } from "../../../extensions/telegram/api.js";
import { resetTelegramThreadBindingsForTests } from "../../../extensions/telegram/test-api.js";
import type { ChannelPlugin } from "../../../src/channels/plugins/types.js";
import {
clearRuntimeConfigSnapshot,
@@ -22,9 +12,35 @@ import {
import { resetPluginRuntimeStateForTest } from "../../../src/plugins/runtime.js";
import { setActivePluginRegistry } from "../../../src/plugins/runtime.js";
import type { PluginRuntime } from "../../../src/plugins/runtime/index.js";
import {
loadBundledPluginApiSync,
loadBundledPluginTestApiSync,
} from "../../../src/test-utils/bundled-plugin-public-surface.js";
import { createTestRegistry } from "../../../src/test-utils/channel-plugins.js";
import { getSessionBindingContractRegistry } from "./registry-session-binding.js";
type BluebubblesApiSurface = typeof import("@openclaw/bluebubbles/api.js");
type DiscordTestApiSurface = typeof import("@openclaw/discord/test-api.js");
type FeishuApiSurface = typeof import("@openclaw/feishu/api.js");
type IMessageApiSurface = typeof import("@openclaw/imessage/api.js");
type MatrixApiSurface = typeof import("@openclaw/matrix/api.js");
type MatrixTestApiSurface = typeof import("@openclaw/matrix/test-api.js");
type TelegramApiSurface = typeof import("@openclaw/telegram/api.js");
type TelegramTestApiSurface = typeof import("@openclaw/telegram/test-api.js");
const { bluebubblesPlugin } = loadBundledPluginApiSync<BluebubblesApiSurface>("bluebubbles");
const { discordPlugin, discordThreadBindingTesting } =
loadBundledPluginTestApiSync<DiscordTestApiSurface>("discord");
const { feishuPlugin, feishuThreadBindingTesting } =
loadBundledPluginApiSync<FeishuApiSurface>("feishu");
const { imessagePlugin } = loadBundledPluginApiSync<IMessageApiSurface>("imessage");
const { resetMatrixThreadBindingsForTests } = loadBundledPluginApiSync<MatrixApiSurface>("matrix");
const { matrixPlugin, setMatrixRuntime } =
loadBundledPluginTestApiSync<MatrixTestApiSurface>("matrix");
const { telegramPlugin } = loadBundledPluginApiSync<TelegramApiSurface>("telegram");
const { resetTelegramThreadBindingsForTests } =
loadBundledPluginTestApiSync<TelegramTestApiSurface>("telegram");
type DiscordThreadBindingTesting = {
resetThreadBindingsForTests: () => void;
};
@@ -72,8 +88,7 @@ async function getFeishuThreadBindingTesting() {
}
async function getResetMatrixThreadBindingsForTests() {
const matrixApi = await import("../../../extensions/matrix/api.js");
return matrixApi.resetMatrixThreadBindingsForTests;
return resetMatrixThreadBindingsForTests;
}
function resolveSessionBindingContractRuntimeConfig(id: string) {

View File

@@ -1,52 +1,78 @@
import { buildAlibabaVideoGenerationProvider } from "../../../extensions/alibaba/video-generation-provider.js";
import { buildBytePlusVideoGenerationProvider } from "../../../extensions/byteplus/video-generation-provider.js";
import { buildComfyMusicGenerationProvider } from "../../../extensions/comfy/music-generation-provider.js";
import { buildComfyVideoGenerationProvider } from "../../../extensions/comfy/video-generation-provider.js";
import { buildFalVideoGenerationProvider } from "../../../extensions/fal/video-generation-provider.js";
import { buildGoogleMusicGenerationProvider } from "../../../extensions/google/music-generation-provider.js";
import { buildGoogleVideoGenerationProvider } from "../../../extensions/google/video-generation-provider.js";
import { buildMinimaxMusicGenerationProvider } from "../../../extensions/minimax/music-generation-provider.js";
import { buildMinimaxVideoGenerationProvider } from "../../../extensions/minimax/video-generation-provider.js";
import { buildOpenAIVideoGenerationProvider } from "../../../extensions/openai/video-generation-provider.js";
import { buildQwenVideoGenerationProvider } from "../../../extensions/qwen/video-generation-provider.js";
import { buildRunwayVideoGenerationProvider } from "../../../extensions/runway/video-generation-provider.js";
import { buildTogetherVideoGenerationProvider } from "../../../extensions/together/video-generation-provider.js";
import { buildVydraVideoGenerationProvider } from "../../../extensions/vydra/video-generation-provider.js";
import { buildXaiVideoGenerationProvider } from "../../../extensions/xai/video-generation-provider.js";
import type { MusicGenerationProvider } from "../../../src/music-generation/types.js";
import type { VideoGenerationProvider } from "../../../src/video-generation/types.js";
import type {
MusicGenerationProviderPlugin,
OpenClawPluginApi,
VideoGenerationProviderPlugin,
} from "../../../src/plugins/types.js";
import { loadBundledPluginPublicSurfaceSync } from "../../../src/test-utils/bundled-plugin-public-surface.js";
import { registerProviderPlugin } from "../plugins/provider-registration.js";
type BundledPluginEntryModule = {
default: {
register(api: OpenClawPluginApi): void | Promise<void>;
};
};
export type BundledVideoProviderEntry = {
pluginId: string;
provider: VideoGenerationProvider;
provider: VideoGenerationProviderPlugin;
};
export type BundledMusicProviderEntry = {
pluginId: string;
provider: MusicGenerationProvider;
provider: MusicGenerationProviderPlugin;
};
export function loadBundledVideoGenerationProviders(): BundledVideoProviderEntry[] {
return [
{ pluginId: "alibaba", provider: buildAlibabaVideoGenerationProvider() },
{ pluginId: "byteplus", provider: buildBytePlusVideoGenerationProvider() },
{ pluginId: "comfy", provider: buildComfyVideoGenerationProvider() },
{ pluginId: "fal", provider: buildFalVideoGenerationProvider() },
{ pluginId: "google", provider: buildGoogleVideoGenerationProvider() },
{ pluginId: "minimax", provider: buildMinimaxVideoGenerationProvider() },
{ pluginId: "openai", provider: buildOpenAIVideoGenerationProvider() },
{ pluginId: "qwen", provider: buildQwenVideoGenerationProvider() },
{ pluginId: "runway", provider: buildRunwayVideoGenerationProvider() },
{ pluginId: "together", provider: buildTogetherVideoGenerationProvider() },
{ pluginId: "vydra", provider: buildVydraVideoGenerationProvider() },
{ pluginId: "xai", provider: buildXaiVideoGenerationProvider() },
];
const BUNDLED_VIDEO_PROVIDER_PLUGIN_IDS = [
"alibaba",
"byteplus",
"comfy",
"fal",
"google",
"minimax",
"openai",
"qwen",
"runway",
"together",
"vydra",
"xai",
] as const;
const BUNDLED_MUSIC_PROVIDER_PLUGIN_IDS = ["comfy", "google", "minimax"] as const;
function loadBundledPluginEntry(pluginId: string): BundledPluginEntryModule {
return loadBundledPluginPublicSurfaceSync<BundledPluginEntryModule>({
pluginId,
artifactBasename: "index.js",
});
}
export function loadBundledMusicGenerationProviders(): BundledMusicProviderEntry[] {
return [
{ pluginId: "comfy", provider: buildComfyMusicGenerationProvider() },
{ pluginId: "google", provider: buildGoogleMusicGenerationProvider() },
{ pluginId: "minimax", provider: buildMinimaxMusicGenerationProvider() },
];
async function registerBundledMediaPlugin(pluginId: string) {
const { default: plugin } = loadBundledPluginEntry(pluginId);
return await registerProviderPlugin({
plugin,
id: pluginId,
name: pluginId,
});
}
export async function loadBundledVideoGenerationProviders(): Promise<BundledVideoProviderEntry[]> {
return (
await Promise.all(
BUNDLED_VIDEO_PROVIDER_PLUGIN_IDS.map(async (pluginId) => {
const { videoProviders } = await registerBundledMediaPlugin(pluginId);
return videoProviders.map((provider) => ({ pluginId, provider }));
}),
)
).flat();
}
export async function loadBundledMusicGenerationProviders(): Promise<BundledMusicProviderEntry[]> {
return (
await Promise.all(
BUNDLED_MUSIC_PROVIDER_PLUGIN_IDS.map(async (pluginId) => {
const { musicProviders } = await registerBundledMediaPlugin(pluginId);
return musicProviders.map((provider) => ({ pluginId, provider }));
}),
)
).flat();
}

View File

@@ -2,6 +2,7 @@ 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,
@@ -25,13 +26,18 @@ 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 = vi.hoisted(() => ({
githubCopilotIndexModuleUrl: new URL(
"../../../extensions/github-copilot/index.ts",
import.meta.url,
).href,
openAIIndexModuleUrl: new URL("../../../extensions/openai/index.ts", import.meta.url).href,
}));
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",
}),
};
vi.mock("openclaw/plugin-sdk/provider-auth-login", async () => {
const actual = await vi.importActual<typeof import("openclaw/plugin-sdk/provider-auth-login")>(

View File

@@ -2,6 +2,10 @@ import { afterEach, 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 type { ModelDefinitionConfig } from "../../../src/config/types.models.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());
@@ -10,32 +14,59 @@ 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 = vi.hoisted(() => ({
cloudflareAiGatewayIndexModuleUrl: new URL(
"../../../extensions/cloudflare-ai-gateway/index.ts",
import.meta.url,
).href,
cloudflareAiGatewayIndexModuleId: new URL(
"../../../extensions/cloudflare-ai-gateway/index.js",
import.meta.url,
).pathname,
githubCopilotIndexModuleUrl: new URL(
"../../../extensions/github-copilot/index.ts",
import.meta.url,
).href,
githubCopilotTokenModuleId: new URL(
"../../../extensions/github-copilot/token.js",
import.meta.url,
).pathname,
minimaxIndexModuleUrl: new URL("../../../extensions/minimax/index.ts", import.meta.url).href,
qwenIndexModuleUrl: new URL("../../../extensions/qwen/index.ts", import.meta.url).href,
ollamaApiModuleId: new URL("../../../extensions/ollama/api.js", import.meta.url).pathname,
ollamaIndexModuleUrl: new URL("../../../extensions/ollama/index.ts", import.meta.url).href,
sglangApiModuleId: new URL("../../../extensions/sglang/api.js", import.meta.url).pathname,
sglangIndexModuleUrl: new URL("../../../extensions/sglang/index.ts", import.meta.url).href,
vllmApiModuleId: new URL("../../../extensions/vllm/api.js", import.meta.url).pathname,
vllmIndexModuleUrl: new URL("../../../extensions/vllm/index.ts", import.meta.url).href,
}));
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",
}),
ollamaApiModuleId: resolveBundledPluginPublicModulePath({
pluginId: "ollama",
artifactBasename: "api.js",
}),
ollamaIndexModuleUrl: resolveRelativeBundledPluginPublicModuleId({
fromModuleUrl: import.meta.url,
pluginId: "ollama",
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",
}),
};
type ProviderHandle = Awaited<ReturnType<typeof requireProvider>>;
@@ -186,9 +217,9 @@ function installDiscoveryHooks(
validateApiKeyInput: () => undefined,
};
});
vi.doMock(bundledProviderModules.githubCopilotTokenModuleId, async () => {
vi.doMock(bundledProviderModules.githubCopilotRegisterRuntimeModuleId, async () => {
const actual = await vi.importActual<object>(
bundledProviderModules.githubCopilotTokenModuleId,
bundledProviderModules.githubCopilotRegisterRuntimeModuleId,
);
return {
...actual,

View File

@@ -4,6 +4,7 @@ import path from "node:path";
import type { StreamFn } from "@mariozechner/pi-agent-core";
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,17 +21,48 @@ const getOAuthProvidersMock = vi.hoisted(() =>
{ id: "openai-codex", envApiKey: "OPENAI_API_KEY", oauthTokenEnv: "OPENAI_OAUTH_TOKEN" },
]),
);
const providerRuntimeContractModules = vi.hoisted(() => ({
anthropicIndexModuleId: "../../../extensions/anthropic/index.ts",
githubCopilotIndexModuleId: "../../../extensions/github-copilot/index.ts",
googleIndexModuleId: "../../../extensions/google/index.ts",
openAIIndexModuleId: "../../../extensions/openai/index.ts",
openAICodexProviderRuntimeModuleId: "../../../extensions/openai/openai-codex-provider.runtime.js",
openRouterIndexModuleId: "../../../extensions/openrouter/index.ts",
veniceIndexModuleId: "../../../extensions/venice/index.ts",
xAIIndexModuleId: "../../../extensions/xai/index.ts",
zaiIndexModuleId: "../../../extensions/zai/index.ts",
}));
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",
}),
xAIIndexModuleId: resolveRelativeBundledPluginPublicModuleId({
fromModuleUrl: import.meta.url,
pluginId: "xai",
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")>(
@@ -43,10 +75,6 @@ vi.mock("@mariozechner/pi-ai/oauth", async () => {
};
});
vi.mock(providerRuntimeContractModules.openAICodexProviderRuntimeModuleId, () => ({
refreshOpenAICodexToken: refreshOpenAICodexTokenMock,
}));
async function importBundledProviderPlugin<T>(moduleUrl: string): Promise<T> {
return (await import(moduleUrl)) as T;
}

View File

@@ -1,3 +1,16 @@
import { loadBundledPluginContractApiSync } from "../../../src/test-utils/bundled-plugin-public-surface.js";
type AnthropicContractSurface = typeof import("@openclaw/anthropic/contract-api.js");
const {
createAnthropicBetaHeadersWrapper,
createAnthropicFastModeWrapper,
createAnthropicServiceTierWrapper,
resolveAnthropicBetas,
resolveAnthropicFastMode,
resolveAnthropicServiceTier,
} = loadBundledPluginContractApiSync<AnthropicContractSurface>("anthropic");
export {
createAnthropicBetaHeadersWrapper,
createAnthropicFastModeWrapper,
@@ -5,4 +18,4 @@ export {
resolveAnthropicBetas,
resolveAnthropicFastMode,
resolveAnthropicServiceTier,
} from "../../../extensions/anthropic/contract-api.js";
};