diff --git a/src/commands/doctor/shared/missing-configured-plugin-install.test.ts b/src/commands/doctor/shared/missing-configured-plugin-install.test.ts index 7fd24c67d380..de4138a9bfa8 100644 --- a/src/commands/doctor/shared/missing-configured-plugin-install.test.ts +++ b/src/commands/doctor/shared/missing-configured-plugin-install.test.ts @@ -11,6 +11,7 @@ import { resolveClawHubInstallSpecsForUpdateChannel, resolveNpmInstallSpecsForUpdateChannel, } from "../../../plugins/install-channel-specs.js"; +import type { BundledProviderPolicySurface } from "../../../plugins/provider-policy-surface.js"; import { VERSION } from "../../../version.js"; import { applyLegacyDoctorMigrations } from "./legacy-config-compat.js"; @@ -74,6 +75,27 @@ const mocks = vi.hoisted(() => ({ resolveOfficialExternalProviderPluginIds: vi.fn(), resolveOfficialExternalProviderPluginIdsForEnv: vi.fn(), resolveOfficialExternalWebProviderContractPluginIdsForEnv: vi.fn(), + resolveDirectBundledProviderPolicySurface: vi.fn( + (pluginId: string): BundledProviderPolicySurface | null => + pluginId === "openai" + ? { + normalizeModelCatalogId: ({ modelId }) => modelId, + resolveModelRoutes: ({ requestTransportOverrides }) => ({ + kind: "routes", + routes: [ + { + api: "openai-responses", + baseUrl: "https://api.openai.com/v1", + authRequirement: "api-key", + requestTransportOverrides: requestTransportOverrides ?? "none", + runtimePolicy: { compatibleIds: ["openclaw", "codex"] }, + }, + ], + defaultRuntimeId: "codex", + }), + } + : null, + ), resolveDefaultPluginExtensionsDir: vi.fn(() => "/tmp/openclaw-plugins"), resolveDefaultPluginNpmDir: vi.fn(() => "/tmp/openclaw-npm"), resolvePluginNpmProjectsDir: vi.fn((npmDir = "/tmp/openclaw-npm") => @@ -203,6 +225,13 @@ vi.mock("../../../plugins/provider-install-catalog.js", () => ({ resolveProviderInstallCatalogEntries: mocks.resolveProviderInstallCatalogEntries, })); +vi.mock("../../../plugins/provider-policy-surface.js", async (importOriginal) => ({ + ...(await importOriginal()), + // This suite owns install repair. Provider artifact loading and route policy + // have dedicated tests, so keep the OpenAI runtime-selection seam in memory. + resolveDirectBundledProviderPolicySurface: mocks.resolveDirectBundledProviderPolicySurface, +})); + vi.mock("../../../plugins/doctor-contract-registry.js", async (importOriginal) => { const actual = await importOriginal(); @@ -2524,6 +2553,7 @@ describe("repairMissingConfiguredPluginInstalls", () => { env: {}, }); + expect(mocks.resolveDirectBundledProviderPolicySurface).toHaveBeenCalledWith("openai"); expect(mocks.updateNpmInstalledPlugins).not.toHaveBeenCalled(); expectRecordFields(mockCallArg(mocks.installPluginFromNpmSpec), { spec: expectedNpmInstallSpec("@openclaw/codex"),