refactor(schema): flatten provider identity

This commit is contained in:
Shoubhit Dash 2026-06-25 19:49:14 +05:30
commit 1a9bd8c1fd
16 changed files with 262 additions and 436 deletions

View file

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

View file

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

View file

@ -45,90 +45,16 @@ 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("keeps configured model variant bodies unchanged", () =>
Effect.gen(function* () {
const catalog = yield* Catalog.Service
@ -142,9 +68,7 @@ describe("ConfigProviderPlugin.Plugin", () => {
info: decode({
providers: {
opencode: {
package: "@ai-sdk/openai",
aiSDK: true,
settings: { baseURL: "https://opencode.test/v1" },
api: { type: "aisdk", package: "@ai-sdk/openai", url: "https://opencode.test/v1" },
models: {
"alpha-gpt-next": {
variants: [
@ -195,9 +119,7 @@ describe("ConfigProviderPlugin.Plugin", () => {
info: decode({
providers: {
opencode: {
package: "@ai-sdk/openai",
aiSDK: true,
settings: { baseURL: "https://opencode.test/v1" },
api: { type: "aisdk", package: "@ai-sdk/openai", url: "https://opencode.test/v1" },
},
},
}),
@ -247,8 +169,8 @@ describe("ConfigProviderPlugin.Plugin", () => {
custom: {
name: "Configured",
env: ["CUSTOM_API_KEY"],
package: "custom-native",
headers: { first: "first", shared: "first" },
api: { type: "native", settings: {} },
request: request({ first: "first", shared: "first" }),
models: {
chat: {
name: "First",
@ -256,8 +178,7 @@ describe("ConfigProviderPlugin.Plugin", () => {
disabled: true,
limit: { context: 100, output: 50 },
cost: { input: 1, output: 2 },
headers: { first: "first", shared: "first" },
variant: "retained",
request: request({ first: "first", shared: "first" }, "retained"),
variants: [
{
id: "fast",
@ -276,19 +197,17 @@ describe("ConfigProviderPlugin.Plugin", () => {
model: "custom/default",
providers: {
custom: {
package: "custom-sdk",
aiSDK: true,
settings: { baseURL: "https://example.test" },
headers: { last: "last", shared: "last" },
api: { type: "aisdk", package: "custom-sdk", url: "https://example.test" },
request: request({ last: "last", shared: "last" }),
models: {
default: {
name: "Default",
},
chat: {
id: "api-chat",
api: { id: "api-chat" },
name: "Last",
limit: { output: 75 },
headers: { last: "last", shared: "last" },
request: request({ last: "last", shared: "last" }),
variants: [
{
id: "fast",
@ -328,12 +247,7 @@ 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",
settings: { baseURL: "https://example.test" },
})
expect(provider.api).toEqual({ type: "aisdk", package: "custom-sdk", url: "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

@ -141,35 +141,6 @@ 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: {},
},
],
)
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("overlays selected OpenAI-compatible Session variant bodies", () =>
Effect.gen(function* () {
const catalog = model(

View file

@ -96,20 +96,12 @@ 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],
[ModelV2.Cost, Model.Cost],
[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],
[ProviderV2.Request, Provider.Request],
[ProviderV2.Info, Provider.Info],
[corePermission.Effect, Permission.Effect],
[corePermission.Rule, Permission.Rule],
[corePermission.Ruleset, Permission.Ruleset],
@ -157,15 +149,50 @@ test("Core reuses the canonical shared schemas", async () => {
for (const [core, shared] of schemas) expect(core).toBe(shared)
expect(Agent.Info.empty(Agent.ID.make("test"))).toEqual(AgentV2.Info.empty(AgentV2.ID.make("test")))
expect(Model.Info.empty(Provider.ID.make("test"), Model.ID.make("model"))).toEqual(
ModelV2.Info.empty(ProviderV2.ID.make("test"), ModelV2.ID.make("model")),
)
expect(Provider.Info.empty(Provider.ID.make("test"))).toEqual(ProviderV2.Info.empty(ProviderV2.ID.make("test")))
expect(Skill.Source.key(Skill.DirectorySource.make({ type: "directory", path: AbsolutePath.make("/tmp") }))).toBe(
"directory:/tmp",
)
})
test("shared provider schemas use flat package identity", () => {
expect(
Schema.decodeUnknownSync(Provider.Info)({
id: "openai",
name: "OpenAI",
package: "@opencode-ai/llm/providers/openai",
settings: { baseURL: "https://api.openai.com/v1" },
headers: { "x-application": "opencode" },
body: { service_tier: "priority" },
}),
).toMatchObject({ package: "@opencode-ai/llm/providers/openai" })
expect(
Schema.decodeUnknownSync(Provider.Info)({
id: "legacy",
name: "Legacy",
package: "aisdk:@ai-sdk/openai",
}),
).toMatchObject({ package: "aisdk:@ai-sdk/openai" })
expect(
Schema.decodeUnknownSync(Model.Info)({
id: "claude-sonnet",
modelID: "us.anthropic.claude-sonnet-4-6",
providerID: "amazon-bedrock",
name: "Claude Sonnet",
package: "@opencode-ai/llm/providers/amazon-bedrock",
settings: { region: "us-west-2" },
headers: {},
body: { additionalModelRequestFields: { reasoning_config: { type: "enabled" } } },
capabilities: { tools: true, input: ["text"], output: ["text"] },
variants: [{ id: "max", settings: {}, body: { budget_tokens: 31999 } }],
time: { released: 0 },
cost: [],
status: "active",
enabled: true,
limit: { context: 200000, output: 64000 },
}),
).toMatchObject({ id: "claude-sonnet", modelID: "us.anthropic.claude-sonnet-4-6" })
})
test("shared record schemas construct and decode plain objects", () => {
const made = Prompt.make({ text: "hello" })
const decoded = Schema.decodeUnknownSync(Prompt)({ text: "hello" })