diff --git a/extensions/minimax/provider-http.test-helpers.ts b/extensions/minimax/provider-http.test-helpers.ts index 47ec8672a46..e4e2f3c533c 100644 --- a/extensions/minimax/provider-http.test-helpers.ts +++ b/extensions/minimax/provider-http.test-helpers.ts @@ -1,46 +1,14 @@ -import type { resolveProviderHttpRequestConfig } from "openclaw/plugin-sdk/provider-http"; -import { afterEach, vi } from "vitest"; - -type ResolveProviderHttpRequestConfigParams = Parameters< - typeof resolveProviderHttpRequestConfig ->[0]; - -const providerHttpMocks = vi.hoisted(() => ({ - resolveApiKeyForProviderMock: vi.fn(async () => ({ apiKey: "provider-key" })), - postJsonRequestMock: vi.fn(), - fetchWithTimeoutMock: vi.fn(), - assertOkOrThrowHttpErrorMock: vi.fn(async () => {}), - resolveProviderHttpRequestConfigMock: vi.fn((params: ResolveProviderHttpRequestConfigParams) => ({ - baseUrl: params.baseUrl ?? params.defaultBaseUrl, - allowPrivateNetwork: false, - headers: new Headers(params.defaultHeaders), - dispatcherPolicy: undefined, - })), -})); - -vi.mock("openclaw/plugin-sdk/provider-auth-runtime", () => ({ - resolveApiKeyForProvider: providerHttpMocks.resolveApiKeyForProviderMock, -})); - -vi.mock("openclaw/plugin-sdk/provider-http", () => ({ - assertOkOrThrowHttpError: providerHttpMocks.assertOkOrThrowHttpErrorMock, - fetchWithTimeout: providerHttpMocks.fetchWithTimeoutMock, - postJsonRequest: providerHttpMocks.postJsonRequestMock, - resolveProviderHttpRequestConfig: providerHttpMocks.resolveProviderHttpRequestConfigMock, -})); +import { + getProviderHttpMocks, + installProviderHttpMockCleanup, +} from "../../test/helpers/media-generation/provider-http-mocks.js"; export function getMinimaxProviderHttpMocks() { - return providerHttpMocks; + return getProviderHttpMocks(); } export function installMinimaxProviderHttpMockCleanup(): void { - afterEach(() => { - providerHttpMocks.resolveApiKeyForProviderMock.mockClear(); - providerHttpMocks.postJsonRequestMock.mockReset(); - providerHttpMocks.fetchWithTimeoutMock.mockReset(); - providerHttpMocks.assertOkOrThrowHttpErrorMock.mockClear(); - providerHttpMocks.resolveProviderHttpRequestConfigMock.mockClear(); - }); + installProviderHttpMockCleanup(); } export function loadMinimaxMusicGenerationProviderModule() { diff --git a/src/plugins/bundled-capability-metadata.test.ts b/src/plugins/bundled-capability-metadata.test.ts index 6d8abac247f..1a5cff4a428 100644 --- a/src/plugins/bundled-capability-metadata.test.ts +++ b/src/plugins/bundled-capability-metadata.test.ts @@ -6,8 +6,9 @@ import { BUNDLED_AUTO_ENABLE_PROVIDER_PLUGIN_IDS, BUNDLED_LEGACY_PLUGIN_ID_ALIASES, BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS, + buildBundledPluginContractSnapshot, + hasBundledPluginContractSnapshotCapabilities, } from "./contracts/inventory/bundled-capability-metadata.js"; -import { uniqueStrings } from "./contracts/shared.js"; import { pluginTestRepoRoot as repoRoot } from "./generated-plugin-test-helpers.js"; import type { PluginManifest } from "./manifest.js"; @@ -39,60 +40,8 @@ function readManifestRecords(): PluginManifest[] { describe("bundled capability metadata", () => { it("keeps contract snapshots aligned with bundled plugin manifests", () => { const expected = readManifestRecords() - .map((manifest) => ({ - pluginId: manifest.id, - cliBackendIds: uniqueStrings(manifest.cliBackends, (value) => value.trim()), - providerIds: uniqueStrings(manifest.providers, (value) => value.trim()), - speechProviderIds: uniqueStrings(manifest.contracts?.speechProviders, (value) => - value.trim(), - ), - realtimeTranscriptionProviderIds: uniqueStrings( - manifest.contracts?.realtimeTranscriptionProviders, - (value) => value.trim(), - ), - realtimeVoiceProviderIds: uniqueStrings( - manifest.contracts?.realtimeVoiceProviders, - (value) => value.trim(), - ), - mediaUnderstandingProviderIds: uniqueStrings( - manifest.contracts?.mediaUnderstandingProviders, - (value) => value.trim(), - ), - imageGenerationProviderIds: uniqueStrings( - manifest.contracts?.imageGenerationProviders, - (value) => value.trim(), - ), - videoGenerationProviderIds: uniqueStrings( - manifest.contracts?.videoGenerationProviders, - (value) => value.trim(), - ), - musicGenerationProviderIds: uniqueStrings( - manifest.contracts?.musicGenerationProviders, - (value) => value.trim(), - ), - webFetchProviderIds: uniqueStrings(manifest.contracts?.webFetchProviders, (value) => - value.trim(), - ), - webSearchProviderIds: uniqueStrings(manifest.contracts?.webSearchProviders, (value) => - value.trim(), - ), - toolNames: uniqueStrings(manifest.contracts?.tools, (value) => value.trim()), - })) - .filter( - (entry) => - entry.cliBackendIds.length > 0 || - entry.providerIds.length > 0 || - entry.speechProviderIds.length > 0 || - entry.realtimeTranscriptionProviderIds.length > 0 || - entry.realtimeVoiceProviderIds.length > 0 || - entry.mediaUnderstandingProviderIds.length > 0 || - entry.imageGenerationProviderIds.length > 0 || - entry.videoGenerationProviderIds.length > 0 || - entry.musicGenerationProviderIds.length > 0 || - entry.webFetchProviderIds.length > 0 || - entry.webSearchProviderIds.length > 0 || - entry.toolNames.length > 0, - ) + .map(buildBundledPluginContractSnapshot) + .filter(hasBundledPluginContractSnapshotCapabilities) .toSorted((left, right) => left.pluginId.localeCompare(right.pluginId)); expect(BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS).toEqual(expected); diff --git a/src/plugins/contracts/inventory/bundled-capability-metadata.ts b/src/plugins/contracts/inventory/bundled-capability-metadata.ts index 553a9653354..7f8ad900300 100644 --- a/src/plugins/contracts/inventory/bundled-capability-metadata.ts +++ b/src/plugins/contracts/inventory/bundled-capability-metadata.ts @@ -38,7 +38,7 @@ const RUNNING_FROM_BUILT_ARTIFACT = CURRENT_MODULE_PATH.includes(`${path.sep}dist${path.sep}`) || CURRENT_MODULE_PATH.includes(`${path.sep}dist-runtime${path.sep}`); -type BundledCapabilityManifest = Pick< +export type BundledCapabilityManifest = Pick< PluginManifest, | "id" | "autoEnableWhenConfiguredProviders" @@ -96,8 +96,10 @@ function listBundledCapabilityManifests(): readonly BundledCapabilityManifest[] const BUNDLED_CAPABILITY_MANIFESTS = listBundledCapabilityManifests(); -export const BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS: readonly BundledPluginContractSnapshot[] = - BUNDLED_CAPABILITY_MANIFESTS.map((manifest) => ({ +export function buildBundledPluginContractSnapshot( + manifest: BundledCapabilityManifest, +): BundledPluginContractSnapshot { + return { pluginId: manifest.id, cliBackendIds: uniqueStrings(manifest.cliBackends, (value) => value.trim()), providerIds: uniqueStrings(manifest.providers, (value) => value.trim()), @@ -132,22 +134,31 @@ export const BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS: readonly BundledPluginContractSn value.trim(), ), toolNames: uniqueStrings(manifest.contracts?.tools, (value) => value.trim()), - })) - .filter( - (entry) => - entry.cliBackendIds.length > 0 || - entry.providerIds.length > 0 || - entry.speechProviderIds.length > 0 || - entry.realtimeTranscriptionProviderIds.length > 0 || - entry.realtimeVoiceProviderIds.length > 0 || - entry.mediaUnderstandingProviderIds.length > 0 || - entry.imageGenerationProviderIds.length > 0 || - entry.videoGenerationProviderIds.length > 0 || - entry.musicGenerationProviderIds.length > 0 || - entry.webFetchProviderIds.length > 0 || - entry.webSearchProviderIds.length > 0 || - entry.toolNames.length > 0, - ) + }; +} + +export function hasBundledPluginContractSnapshotCapabilities( + entry: BundledPluginContractSnapshot, +): boolean { + return ( + entry.cliBackendIds.length > 0 || + entry.providerIds.length > 0 || + entry.speechProviderIds.length > 0 || + entry.realtimeTranscriptionProviderIds.length > 0 || + entry.realtimeVoiceProviderIds.length > 0 || + entry.mediaUnderstandingProviderIds.length > 0 || + entry.imageGenerationProviderIds.length > 0 || + entry.videoGenerationProviderIds.length > 0 || + entry.musicGenerationProviderIds.length > 0 || + entry.webFetchProviderIds.length > 0 || + entry.webSearchProviderIds.length > 0 || + entry.toolNames.length > 0 + ); +} + +export const BUNDLED_PLUGIN_CONTRACT_SNAPSHOTS: readonly BundledPluginContractSnapshot[] = + BUNDLED_CAPABILITY_MANIFESTS.map(buildBundledPluginContractSnapshot) + .filter(hasBundledPluginContractSnapshotCapabilities) .toSorted((left, right) => left.pluginId.localeCompare(right.pluginId)); export const BUNDLED_LEGACY_PLUGIN_ID_ALIASES = Object.fromEntries(