diff --git a/packages/core/src/plugin/provider/cloudflare-ai-gateway.ts b/packages/core/src/plugin/provider/cloudflare-ai-gateway.ts index 9e5d64a0461..ac7cc168efd 100644 --- a/packages/core/src/plugin/provider/cloudflare-ai-gateway.ts +++ b/packages/core/src/plugin/provider/cloudflare-ai-gateway.ts @@ -58,10 +58,8 @@ export const CloudflareAIGatewayPlugin = define({ const config = gatewayConfig(evt.options) if (!config) return const metadata = gatewayMetadata(evt.options) - const { createAiGateway } = yield* Effect.promise(() => import("ai-gateway-provider")).pipe(Effect.orDie) - const { createUnified } = yield* Effect.promise(() => import("ai-gateway-provider/providers/unified")).pipe( - Effect.orDie, - ) + const { createAiGateway } = yield* Effect.promise(() => import("ai-gateway-provider")) + const { createUnified } = yield* Effect.promise(() => import("ai-gateway-provider/providers/unified")) const gateway = createAiGateway({ accountId: config.accountId, gateway: config.gatewayId, diff --git a/packages/core/src/plugin/provider/dynamic.ts b/packages/core/src/plugin/provider/dynamic.ts index aea911363cb..e7bab3777b2 100644 --- a/packages/core/src/plugin/provider/dynamic.ts +++ b/packages/core/src/plugin/provider/dynamic.ts @@ -1,8 +1,7 @@ import { Effect } from "effect" -import { pathToFileURL } from "url" import { define } from "@opencode-ai/plugin/effect/plugin" import { Npm } from "@opencode-ai/util/npm" -import { importModule } from "@opencode-ai/util/runtime-import" +import { loadSDKFactory } from "./sdk-factory.js" export const DynamicProviderPlugin = define({ id: "opencode.provider.dynamic", @@ -13,18 +12,7 @@ export const DynamicProviderPlugin = define({ Effect.fn(function* (evt) { if (evt.sdk) return - const installedPath = evt.package.startsWith("file://") - ? evt.package - : (yield* npm.add(evt.package).pipe(Effect.orDie)).entrypoint - if (!installedPath) throw new Error(`Package ${evt.package} has no import entrypoint`) - - const mod = (yield* Effect.promise(() => - importModule(installedPath.startsWith("file://") ? installedPath : pathToFileURL(installedPath).href), - ).pipe(Effect.orDie)) as Record any> - const match = Object.keys(mod).find((name) => name.startsWith("create")) - if (!match) throw new Error(`Package ${evt.package} has no provider factory export`) - - evt.sdk = mod[match](evt.options) + evt.sdk = ((yield* loadSDKFactory(npm, evt.package)) as (options: any) => any)(evt.options) }), ) }), diff --git a/packages/core/src/plugin/provider/gitlab.ts b/packages/core/src/plugin/provider/gitlab.ts index c3cd205cf56..1ef6218f8d7 100644 --- a/packages/core/src/plugin/provider/gitlab.ts +++ b/packages/core/src/plugin/provider/gitlab.ts @@ -40,7 +40,7 @@ export const GitLabPlugin = define({ typeof evt.options.featureFlags === "object" && evt.options.featureFlags ? evt.options.featureFlags : {} const id = evt.model.modelID ?? evt.model.id if (id.startsWith("duo-workflow-")) { - const gitlab = yield* Effect.promise(() => import("gitlab-ai-provider")).pipe(Effect.orDie) + const gitlab = yield* Effect.promise(() => import("gitlab-ai-provider")) const workflowRef = typeof evt.model.settings?.workflowRef === "string" ? evt.model.settings.workflowRef : undefined const workflowDefinition = diff --git a/packages/core/src/plugin/provider/sap-ai-core.ts b/packages/core/src/plugin/provider/sap-ai-core.ts index ba9211227c7..f07babc2c29 100644 --- a/packages/core/src/plugin/provider/sap-ai-core.ts +++ b/packages/core/src/plugin/provider/sap-ai-core.ts @@ -1,9 +1,8 @@ import { Effect } from "effect" -import { pathToFileURL } from "url" import { define } from "@opencode-ai/plugin/effect/plugin" import { Npm } from "@opencode-ai/util/npm" import { Provider } from "../../provider.js" -import { importModule } from "@opencode-ai/util/runtime-import" +import { loadSDKFactory } from "./sdk-factory.js" export const SapAICorePlugin = define({ id: "opencode.provider.sap.ai.core", @@ -18,17 +17,7 @@ export const SapAICorePlugin = define({ (typeof evt.options.serviceKey === "string" ? evt.options.serviceKey : undefined) if (serviceKey && !process.env.AICORE_SERVICE_KEY) process.env.AICORE_SERVICE_KEY = serviceKey - const installedPath = evt.package.startsWith("file://") - ? evt.package - : (yield* npm.add(evt.package).pipe(Effect.orDie)).entrypoint - if (!installedPath) return yield* Effect.die(new Error(`Package ${evt.package} has no import entrypoint`)) - - const mod = (yield* Effect.promise(() => - importModule(installedPath.startsWith("file://") ? installedPath : pathToFileURL(installedPath).href), - )) as Record - const match = Object.keys(mod).find((name) => name.startsWith("create")) - if (!match) return yield* Effect.die(new Error(`Package ${evt.package} has no provider factory export`)) - const factory = mod[match] + const factory = yield* loadSDKFactory(npm, evt.package) if (typeof factory !== "function") return yield* Effect.die(new Error(`Package ${evt.package} provider factory export is not callable`)) diff --git a/packages/core/src/plugin/provider/sdk-factory.ts b/packages/core/src/plugin/provider/sdk-factory.ts new file mode 100644 index 00000000000..43db572c27e --- /dev/null +++ b/packages/core/src/plugin/provider/sdk-factory.ts @@ -0,0 +1,18 @@ +import { Effect } from "effect" +import { pathToFileURL } from "url" +import { Npm } from "@opencode-ai/util/npm" +import { importModule } from "@opencode-ai/util/runtime-import" + +export const loadSDKFactory = Effect.fnUntraced(function* (npm: Npm.Interface, packageName: string) { + const installedPath = packageName.startsWith("file://") + ? packageName + : (yield* npm.add(packageName).pipe(Effect.orDie)).entrypoint + if (!installedPath) return yield* Effect.die(new Error(`Package ${packageName} has no import entrypoint`)) + + const mod = (yield* Effect.promise(() => + importModule(installedPath.startsWith("file://") ? installedPath : pathToFileURL(installedPath).href), + )) as Record + const match = Object.keys(mod).find((name) => name.startsWith("create")) + if (!match) return yield* Effect.die(new Error(`Package ${packageName} has no provider factory export`)) + return mod[match] +})