refactor(core): simplify provider helpers

This commit is contained in:
Shoubhit Dash
2026-06-29 22:47:08 +05:30
parent 3b63568da2
commit 9ad7612ff4
3 changed files with 66 additions and 50 deletions
+3 -2
View File
@@ -15,11 +15,12 @@ export const Plugin = define({
const generated = generate(draft, record.provider)
if (generated.length === 0) return
const explicit = new Map((draft.variants ?? []).map((variant) => [variant.id, variant]))
const variants = draft.variants ?? []
const explicit = new Map(variants.map((variant) => [variant.id, variant]))
const generatedIDs = new Set<string>(generated.map((variant) => variant.id))
draft.variants = [
...generated.map((variant) => explicit.get(variant.id) ?? variant),
...(draft.variants ?? []).filter((variant) => !generatedIDs.has(variant.id)),
...variants.filter((variant) => !generatedIDs.has(variant.id)),
]
})
}
+19 -28
View File
@@ -11,10 +11,12 @@ export const ID = Provider.ID
export type ID = typeof ID.Type
export const AISDK_PREFIX = "aisdk:"
export const isAISDK = (packageName: string | undefined) => packageName?.startsWith(AISDK_PREFIX) ?? false
export const aisdk = (packageName: string) => (isAISDK(packageName) ? packageName : `${AISDK_PREFIX}${packageName}`)
export const packageName = (packageName: string | undefined) =>
isAISDK(packageName) ? packageName!.slice(AISDK_PREFIX.length) : packageName
export const isAISDK = (value: string | undefined) => value?.startsWith(AISDK_PREFIX) ?? false
export const aisdk = (value: string) => (isAISDK(value) ? value : `${AISDK_PREFIX}${value}`)
export const packageName = (value: string | undefined) => {
if (value === undefined || !isAISDK(value)) return value
return value.slice(AISDK_PREFIX.length)
}
export class LoadError extends Schema.TaggedErrorClass<LoadError>()("ProviderV2.LoadError", {
package: Schema.String,
@@ -25,7 +27,14 @@ export type ProviderPackage = ProviderPackageDefinition
const packages = new Map<string, Promise<unknown>>()
export const loadPackage = Effect.fn("ProviderV2.loadPackage")(function* (specifier: string, npm?: Npm.Interface) {
const resolved = yield* resolvePackage(specifier)
const resolved = yield* Effect.sync(() => {
if (specifier.startsWith("file://") || specifier.startsWith("@opencode-ai/llm/")) return specifier
try {
return import.meta.resolve(specifier)
} catch {
return undefined
}
})
if (resolved) return yield* importPackage(specifier, resolved)
if (!npm) {
return yield* new LoadError({
@@ -33,8 +42,10 @@ export const loadPackage = Effect.fn("ProviderV2.loadPackage")(function* (specif
cause: new Error(`Provider package ${specifier} is not installed`),
})
}
const parts = specifier.split("/")
const root = specifier.startsWith("@") ? parts.slice(0, 2).join("/") : (parts[0] ?? specifier)
const installed = yield* npm
.add(rootPackage(specifier))
.add(root)
.pipe(Effect.mapError((cause) => new LoadError({ package: specifier, cause })))
const entrypoint = yield* Effect.try({
try: () => import.meta.resolve(specifier, pathToFileURL(`${installed.directory}/`).href),
@@ -95,16 +106,6 @@ export type Info = Provider.Info
export type MutableInfo = DeepMutable<Info>
const resolvePackage = (specifier: string) =>
Effect.sync(() => {
if (specifier.startsWith("file://") || specifier.startsWith("@opencode-ai/llm/")) return specifier
try {
return import.meta.resolve(specifier)
} catch {
return undefined
}
})
const importPackage = Effect.fn("ProviderV2.importPackage")(function* (specifier: string, entrypoint: string) {
const module = yield* Effect.tryPromise({
try: () => {
@@ -116,21 +117,11 @@ const importPackage = Effect.fn("ProviderV2.importPackage")(function* (specifier
},
catch: (cause) => new LoadError({ package: specifier, cause }),
})
if (!isProviderPackage(module)) {
if (typeof module !== "object" || module === null || typeof (module as { model?: unknown }).model !== "function") {
return yield* new LoadError({
package: specifier,
cause: new Error(`Provider package ${specifier} does not export model(modelID, settings)`),
})
}
return module
return module as ProviderPackageDefinition
})
function isProviderPackage(input: unknown): input is ProviderPackageDefinition {
return typeof input === "object" && input !== null && "model" in input && typeof input.model === "function"
}
function rootPackage(specifier: string) {
const parts = specifier.split("/")
if (specifier.startsWith("@")) return parts.slice(0, 2).join("/")
return parts[0]
}
+44 -20
View File
@@ -108,19 +108,6 @@ export interface Dependencies {
readonly loadAISDK?: (model: ModelV2.Info) => Effect.Effect<Model, AISDK.InitError>
}
const unsupported = (model: ModelV2.Info, packageName = model.package ?? "unknown") =>
new UnsupportedPackageError({
providerID: model.providerID,
modelID: model.id,
package: packageName,
})
const credentialSettings = (credential: Credential.Value | undefined) => ({
...(credential?.type === "key" ? { apiKey: credential.key } : {}),
...(credential?.type === "oauth" ? { apiKey: credential.access } : {}),
...credential?.metadata,
})
export const fromCatalogModel = (
model: ModelV2.Info,
credential?: Credential.Value,
@@ -134,35 +121,72 @@ export const fromCatalogModel = (
})
if (ProviderV2.isAISDK(resolved.package)) {
if (!dependencies.loadAISDK) {
return Effect.fail(unsupported(resolved))
return Effect.fail(
new UnsupportedPackageError({
providerID: resolved.providerID,
modelID: resolved.id,
package: resolved.package ?? "unknown",
}),
)
}
const runtime = produce(resolved, (draft) => {
draft.settings = ProviderV2.mergeOverlay(draft.settings, credentialSettings(credential))
draft.settings = ProviderV2.mergeOverlay(draft.settings, {
...(credential?.type === "key" ? { apiKey: credential.key } : {}),
...(credential?.type === "oauth" ? { apiKey: credential.access } : {}),
...credential?.metadata,
})
})
return dependencies.loadAISDK(runtime).pipe(
Effect.mapError(() => unsupported(resolved)),
Effect.mapError(
() =>
new UnsupportedPackageError({
providerID: resolved.providerID,
modelID: resolved.id,
package: resolved.package ?? "unknown",
}),
),
)
}
if (resolved.package) {
const specifier = resolved.package
return Effect.gen(function* () {
const module = yield* (dependencies.loadPackage ?? ProviderV2.loadPackage)(specifier).pipe(
Effect.mapError(() => unsupported(resolved, specifier)),
Effect.mapError(
() =>
new UnsupportedPackageError({
providerID: resolved.providerID,
modelID: resolved.id,
package: specifier,
}),
),
)
const settings = {
...resolved.settings,
...credentialSettings(credential),
...(credential?.type === "key" ? { apiKey: credential.key } : {}),
...(credential?.type === "oauth" ? { apiKey: credential.access } : {}),
...credential?.metadata,
headers: resolved.headers,
body: resolved.body,
limits: { context: resolved.limit.context, output: resolved.limit.output },
}
return yield* Effect.try({
try: () => Model.update(module.model(resolved.modelID ?? resolved.id, settings), { provider: resolved.providerID }),
catch: () => unsupported(resolved, specifier),
catch: () =>
new UnsupportedPackageError({
providerID: resolved.providerID,
modelID: resolved.id,
package: specifier,
}),
})
})
}
return Effect.fail(unsupported(resolved))
return Effect.fail(
new UnsupportedPackageError({
providerID: resolved.providerID,
modelID: resolved.id,
package: resolved.package ?? "unknown",
}),
)
}
export const resolve = (