feat(core): migrate native provider config

This commit is contained in:
Shoubhit Dash 2026-06-25 00:17:32 +05:30
commit 62e44a80e7
16 changed files with 358 additions and 99 deletions

View file

@ -213,6 +213,7 @@ describe("CatalogV2", () => {
type: "aisdk",
package: "@ai-sdk/openai-compatible",
url: "https://provider.example.com",
settings: {},
})
}),
)

View file

@ -103,13 +103,10 @@ describe("Config", () => {
},
})
expect(migrated.providers?.bedrock?.api).toEqual({
type: "aisdk",
expect(migrated.providers?.bedrock).toMatchObject({
package: "@ai-sdk/amazon-bedrock",
url: undefined,
aiSDK: true,
settings: { region: "us-east-1", profile: "dev" },
})
expect(migrated.providers?.bedrock?.request).toEqual({
headers: { "x-test": "1" },
body: { trace: true },
})
@ -585,34 +582,34 @@ describe("Config", () => {
})
expect(documents[0]?.info.attachments).toEqual({ image: { auto_resize: false, max_width: 1200 } })
expect(documents[0]?.info.providers?.custom).toMatchObject({
request: { body: { apiKey: "secret" } },
body: { apiKey: "secret" },
models: {
model: {
request: { body: { reasoningEffort: "high" } },
body: { reasoningEffort: "high" },
variants: [{ id: "fast", body: { temperature: 0.2 } }],
},
},
})
expect(documents[0]?.info.providers?.openai).toMatchObject({
api: { settings: {} },
request: { headers: { Authorization: "Bearer secret", "OpenAI-Organization": "org" } },
package: "@ai-sdk/openai",
aiSDK: true,
settings: {},
headers: { Authorization: "Bearer secret", "OpenAI-Organization": "org" },
models: {
model: {
request: {
body: { temperature: 0.3, reasoningEffort: "high", serviceTier: "priority" },
},
body: { temperature: 0.3, reasoningEffort: "high", serviceTier: "priority" },
variants: [{ id: "high", body: { reasoningEffort: "high", reasoningSummary: "auto" } }],
},
},
})
expect(documents[0]?.info.providers?.anthropic).toMatchObject({
package: "@ai-sdk/anthropic",
aiSDK: true,
models: {
model: {
request: {
body: {
output_config: { effort: "high", task_budget: 4096 },
metadata: { user_id: "user-1" },
},
body: {
output_config: { effort: "high", task_budget: 4096 },
metadata: { user_id: "user-1" },
},
},
},

View file

@ -45,16 +45,90 @@ function withEnv<A, E, R>(vars: Record<string, string | undefined>, effect: () =
)
}
function request(headers: Record<string, string>, variant?: string) {
return {
headers,
variant,
}
}
const decode = Schema.decodeUnknownSync(Config.Info)
describe("ConfigProviderPlugin.Plugin", () => {
it.effect("merges flat provider and model overlays", () =>
Effect.gen(function* () {
const catalog = yield* Catalog.Service
const providerID = ProviderV2.ID.make("custom")
const modelID = ModelV2.ID.make("chat")
const config = Config.Service.of({
entries: () =>
Effect.succeed([
new Config.Document({
type: "document",
info: decode({ providers: { custom: { aiSDK: true } } }),
}),
new Config.Document({
type: "document",
info: decode({
providers: {
custom: {
package: "custom-provider",
settings: { auth: { type: "token", region: "us-east-1" } },
headers: { "X-Test": "provider" },
body: { reasoning: { type: "enabled", budget: 8_000 }, tags: ["provider"] },
models: {
chat: {
package: "custom-model-provider",
settings: { auth: { region: "us-west-2" } },
headers: { "x-test": "model" },
body: { reasoning: { budget: 32_000 }, tags: ["model"] },
},
inherit: {
settings: { auth: { region: "eu-west-1" }, baseURL: "https://model.example/v1" },
},
clear: { settings: { baseURL: "https://old.example/v1" } },
},
},
},
}),
}),
new Config.Document({
type: "document",
info: decode({
providers: {
custom: { models: { clear: { package: "custom-provider", settings: { baseURL: null } } } },
},
}),
}),
]),
})
yield* addPlugin(config)
const model = required(yield* catalog.model.get(providerID, modelID))
expect(model.api).toEqual({
id: modelID,
type: "aisdk",
package: "custom-model-provider",
settings: { auth: { type: "token", region: "us-west-2" } },
})
expect(model.request.headers).toEqual({ "x-test": "model" })
expect(model.request.body).toEqual({
reasoning: { type: "enabled", budget: 32_000 },
tags: ["model"],
})
expect(required(yield* catalog.model.get(providerID, ModelV2.ID.make("inherit"))).api).toEqual({
id: ModelV2.ID.make("inherit"),
type: "aisdk",
package: "custom-provider",
url: "https://model.example/v1",
settings: {
auth: { type: "token", region: "eu-west-1" },
baseURL: "https://model.example/v1",
},
})
expect(required(yield* catalog.model.get(providerID, ModelV2.ID.make("clear"))).api).toEqual({
id: ModelV2.ID.make("clear"),
type: "aisdk",
package: "custom-provider",
settings: { auth: { type: "token", region: "us-east-1" }, baseURL: null },
})
}),
)
it.effect("partitions existing model variant bodies without changing config shape", () =>
Effect.gen(function* () {
const catalog = yield* Catalog.Service
@ -68,7 +142,9 @@ describe("ConfigProviderPlugin.Plugin", () => {
info: decode({
providers: {
opencode: {
api: { type: "aisdk", package: "@ai-sdk/openai", url: "https://opencode.test/v1" },
package: "@ai-sdk/openai",
aiSDK: true,
settings: { baseURL: "https://opencode.test/v1" },
models: {
"alpha-gpt-next": {
variants: [
@ -120,7 +196,9 @@ describe("ConfigProviderPlugin.Plugin", () => {
info: decode({
providers: {
opencode: {
api: { type: "aisdk", package: "@ai-sdk/openai", url: "https://opencode.test/v1" },
package: "@ai-sdk/openai",
aiSDK: true,
settings: { baseURL: "https://opencode.test/v1" },
},
},
}),
@ -171,8 +249,8 @@ describe("ConfigProviderPlugin.Plugin", () => {
custom: {
name: "Configured",
env: ["CUSTOM_API_KEY"],
api: { type: "native", settings: {} },
request: request({ first: "first", shared: "first" }),
package: "custom-native",
headers: { first: "first", shared: "first" },
models: {
chat: {
name: "First",
@ -180,7 +258,8 @@ describe("ConfigProviderPlugin.Plugin", () => {
disabled: true,
limit: { context: 100, output: 50 },
cost: { input: 1, output: 2 },
request: request({ first: "first", shared: "first" }, "retained"),
headers: { first: "first", shared: "first" },
variant: "retained",
variants: [
{
id: "fast",
@ -199,17 +278,19 @@ describe("ConfigProviderPlugin.Plugin", () => {
model: "custom/default",
providers: {
custom: {
api: { type: "aisdk", package: "custom-sdk", url: "https://example.test" },
request: request({ last: "last", shared: "last" }),
package: "custom-sdk",
aiSDK: true,
settings: { baseURL: "https://example.test" },
headers: { last: "last", shared: "last" },
models: {
default: {
name: "Default",
},
chat: {
api: { id: "api-chat" },
id: "api-chat",
name: "Last",
limit: { output: 75 },
request: request({ last: "last", shared: "last" }),
headers: { last: "last", shared: "last" },
variants: [
{
id: "fast",
@ -249,7 +330,12 @@ describe("ConfigProviderPlugin.Plugin", () => {
})
expect((yield* integrations.get(Integration.ID.make("custom")))?.name).toBe("Renamed")
expect(provider.disabled).toBeUndefined()
expect(provider.api).toEqual({ type: "aisdk", package: "custom-sdk", url: "https://example.test" })
expect(provider.api).toEqual({
type: "aisdk",
package: "custom-sdk",
url: "https://example.test",
settings: { baseURL: "https://example.test" },
})
expect(provider.request.headers).toEqual({ first: "first", shared: "last", last: "last" })
expect(model.api.id).toBe(ModelV2.ID.make("api-chat"))
expect(model.name).toBe("Last")

View file

@ -148,6 +148,40 @@ describe("SessionRunnerModel", () => {
}),
)
it.effect("applies a selected variant base URL", () =>
Effect.gen(function* () {
const base = model(
{ type: "aisdk", package: "@ai-sdk/openai", url: "https://default.example/v1" },
[
{
id: ModelV2.VariantID.make("regional"),
settings: { baseURL: "https://regional.example/v1" },
headers: {},
body: {},
generation: {},
options: {},
},
],
)
const session = SessionV2.Info.make({
id: SessionV2.ID.make("ses_regional_variant"),
projectID: ProjectV2.ID.global,
title: "test",
model: { id: base.id, providerID: base.providerID, variant: ModelV2.VariantID.make("regional") },
cost: 0,
tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
time: { created: DateTime.makeUnsafe(0), updated: DateTime.makeUnsafe(0) },
location: { directory: AbsolutePath.make("/project") },
})
const resolved = yield* SessionRunnerModel.resolve(
session,
base,
)
expect(resolved.route.endpoint.baseURL).toBe("https://regional.example/v1")
}),
)
it.effect("lowers selected OpenAI-compatible Session variants into Chat options", () =>
Effect.gen(function* () {
const catalog = model(

View file

@ -99,6 +99,7 @@ test("Core reuses the canonical shared schemas", async () => {
[coreLLM.ToolContent, LLM.ToolContent],
[ModelV2.ID, Model.ID],
[ModelV2.VariantID, Model.VariantID],
[ModelV2.Package, Model.Package],
[ModelV2.Ref, Model.Ref],
[ModelV2.Family, Model.Family],
[ModelV2.Capabilities, Model.Capabilities],
@ -106,6 +107,7 @@ test("Core reuses the canonical shared schemas", async () => {
[ModelV2.Api, Model.Api],
[ModelV2.Info, Model.Info],
[ProviderV2.ID, Provider.ID],
[ProviderV2.Package, Provider.Package],
[ProviderV2.AISDK, Provider.AISDK],
[ProviderV2.Native, Provider.Native],
[ProviderV2.Api, Provider.Api],