diff --git a/packages/core/src/catalog.ts b/packages/core/src/catalog.ts index 1945024b54..a98902f01d 100644 --- a/packages/core/src/catalog.ts +++ b/packages/core/src/catalog.ts @@ -77,7 +77,12 @@ const layer = Layer.effect( const projectModel = (model: ModelV2.Info, provider: ProviderV2.Info) => { const api = - model.api.type === "native" && !model.api.url && Object.keys(model.api.settings).length === 0 + // A native api with a package is explicitly targeted; only package-less, + // settings-less native apis are placeholders that inherit the provider api. + model.api.type === "native" && + model.api.package === undefined && + !model.api.url && + Object.keys(model.api.settings).length === 0 ? { ...provider.api, id: model.api.id } : model.api.type === "aisdk" && provider.api.type === "aisdk" && !model.api.url ? { ...model.api, url: provider.api.url, settings: { ...provider.api.settings, ...model.api.settings } } diff --git a/packages/core/test/catalog.test.ts b/packages/core/test/catalog.test.ts index 6c736cde1e..8444bec813 100644 --- a/packages/core/test/catalog.test.ts +++ b/packages/core/test/catalog.test.ts @@ -213,6 +213,40 @@ describe("CatalogV2", () => { }), ) + it.effect("keeps an explicit native package api over the provider api", () => + Effect.gen(function* () { + const catalog = yield* Catalog.Service + const providerID = ProviderV2.ID.make("test") + const modelID = ModelV2.ID.make("model") + yield* catalog.transform((catalog) => { + catalog.provider.update(providerID, (provider) => { + provider.api = { + type: "aisdk", + package: "@ai-sdk/openai", + } + }) + catalog.model.update(providerID, modelID, (model) => { + // Plugins retarget models at explicit native packages (e.g. ChatGPT + // subscription models at the codex package); empty settings must not + // demote the api back to the provider placeholder rule. + model.api = { + type: "native", + id: model.api.id, + package: "@opencode-ai/llm/providers/openai/codex", + settings: {}, + } + }) + }) + + expect(required(yield* catalog.model.get(providerID, modelID)).api).toEqual({ + id: modelID, + type: "native", + package: "@opencode-ai/llm/providers/openai/codex", + settings: {}, + }) + }), + ) + it.effect("resolves provider and model request merges", () => Effect.gen(function* () { const catalog = yield* Catalog.Service