cloudaxe-opencode/packages/core/test/plugin/models-dev.test.ts

555 lines
21 KiB
TypeScript
Raw Permalink Normal View History

import path from "path"
import { describe, expect } from "bun:test"
import { Money } from "@opencode-ai/schema/money"
import { Effect, Layer } from "effect"
import { Catalog } from "@opencode-ai/core/catalog"
import { Integration } from "@opencode-ai/core/integration"
chore: merge dev into v2 (#34788) Co-authored-by: Brendan Allan <14191578+Brendonovich@users.noreply.github.com> Co-authored-by: Kit Langton <kit.langton@gmail.com> Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com> Co-authored-by: Affan Ali <93028901+affanali2k3@users.noreply.github.com> Co-authored-by: affanali2k3 <affanalikhanxx@gmail.com> Co-authored-by: Frank <frank@anoma.ly> Co-authored-by: opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com> Co-authored-by: 𝓛𝓲𝓽𝓽𝓵𝓮 𝓕𝓻𝓪𝓷𝓴 <little-frank@opencord.local> Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Co-authored-by: Jay V <air@live.ca> Co-authored-by: Dax Raad <d@ironbay.co> Co-authored-by: Aarav Sareen <96787824+arvsrn@users.noreply.github.com> Co-authored-by: OpeOginni <107570612+OpeOginni@users.noreply.github.com> Co-authored-by: Luke Parker <10430890+Hona@users.noreply.github.com> Co-authored-by: Ben Guthrie <benjee.012@gmail.com> Co-authored-by: Dax <mail@thdxr.com> Co-authored-by: Filip <34747899+neriousy@users.noreply.github.com> Co-authored-by: Max Anderson <max.a.anderson95@gmail.com> Co-authored-by: Brendan Allan <git@brendonovich.dev> Co-authored-by: Jack <jack@anoma.ly> Co-authored-by: Shoubhit Dash <shoubhit2005@gmail.com> Co-authored-by: Dustin Deus <deusdustin@gmail.com> Co-authored-by: starptech <starptech@starptechs-MBP.fritz.box> Co-authored-by: Aiden Cline <aidenpcline@gmail.com> Co-authored-by: usrnk1 <7547651+usrnk1@users.noreply.github.com> Co-authored-by: Jay <53023+jayair@users.noreply.github.com> Co-authored-by: runvip <164729189+runvip@users.noreply.github.com> Co-authored-by: opencode <opencode@sst.dev> Co-authored-by: Julian Coy <julian@ex-machina.co> Co-authored-by: Vladimir Glafirov <vglafirov@gitlab.com>
2026-07-01 21:12:00 +00:00
import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder"
import { LayerNode } from "@opencode-ai/util/effect/layer-node"
import { Bus } from "@opencode-ai/core/bus"
import { Location } from "@opencode-ai/core/location"
import { Model } from "@opencode-ai/core/model"
import { ModelsDev } from "@opencode-ai/core/models-dev"
import { ModelsDevPlugin } from "@opencode-ai/core/plugin/models-dev"
import { Provider } from "@opencode-ai/core/provider"
import { AbsolutePath } from "@opencode-ai/core/schema"
import { location } from "../fixture/location"
import { testEffect } from "../lib/effect"
import { catalogHost, host, integrationHost } from "./host"
const locationLayer = Layer.succeed(
Location.Service,
Location.Service.of(location({ directory: AbsolutePath.make(import.meta.dir) })),
)
const layer = AppNodeBuilder.build(LayerNode.group([Catalog.node, Integration.node, Bus.node]), [
chore: merge dev into v2 (#34788) Co-authored-by: Brendan Allan <14191578+Brendonovich@users.noreply.github.com> Co-authored-by: Kit Langton <kit.langton@gmail.com> Co-authored-by: opencode-agent[bot] <opencode-agent[bot]@users.noreply.github.com> Co-authored-by: Affan Ali <93028901+affanali2k3@users.noreply.github.com> Co-authored-by: affanali2k3 <affanalikhanxx@gmail.com> Co-authored-by: Frank <frank@anoma.ly> Co-authored-by: opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com> Co-authored-by: 𝓛𝓲𝓽𝓽𝓵𝓮 𝓕𝓻𝓪𝓷𝓴 <little-frank@opencord.local> Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Co-authored-by: Jay V <air@live.ca> Co-authored-by: Dax Raad <d@ironbay.co> Co-authored-by: Aarav Sareen <96787824+arvsrn@users.noreply.github.com> Co-authored-by: OpeOginni <107570612+OpeOginni@users.noreply.github.com> Co-authored-by: Luke Parker <10430890+Hona@users.noreply.github.com> Co-authored-by: Ben Guthrie <benjee.012@gmail.com> Co-authored-by: Dax <mail@thdxr.com> Co-authored-by: Filip <34747899+neriousy@users.noreply.github.com> Co-authored-by: Max Anderson <max.a.anderson95@gmail.com> Co-authored-by: Brendan Allan <git@brendonovich.dev> Co-authored-by: Jack <jack@anoma.ly> Co-authored-by: Shoubhit Dash <shoubhit2005@gmail.com> Co-authored-by: Dustin Deus <deusdustin@gmail.com> Co-authored-by: starptech <starptech@starptechs-MBP.fritz.box> Co-authored-by: Aiden Cline <aidenpcline@gmail.com> Co-authored-by: usrnk1 <7547651+usrnk1@users.noreply.github.com> Co-authored-by: Jay <53023+jayair@users.noreply.github.com> Co-authored-by: runvip <164729189+runvip@users.noreply.github.com> Co-authored-by: opencode <opencode@sst.dev> Co-authored-by: Julian Coy <julian@ex-machina.co> Co-authored-by: Vladimir Glafirov <vglafirov@gitlab.com>
2026-07-01 21:12:00 +00:00
[Location.node, locationLayer],
])
const it = testEffect(layer)
2026-07-20 19:18:03 +00:00
const models = (file: string) =>
2026-07-21 01:21:36 +00:00
AppNodeBuilder.build(ModelsDev.node, [[ModelsDev.node, ModelsDev.configured({ file, fetch: false })]])
describe("ModelsDevPlugin", () => {
it.effect("projects normalized models.dev snapshots into the catalog", () =>
Effect.gen(function* () {
const integrations = yield* Integration.Service
const catalog = yield* Catalog.Service
const providerID = Provider.ID.make("acme")
const modelID = Model.ID.make("gpt-5.4")
const models = ModelsDev.Service.of({
get: () =>
Effect.succeed([
{
info: {
id: providerID,
name: "Acme",
package: Provider.aisdk("@ai-sdk/openai-compatible"),
settings: { baseURL: "https://api.acme.test/v1" },
},
environment: [],
models: [
{
id: modelID,
modelID,
providerID,
name: "GPT-5.4",
family: Model.Family.make("gpt"),
capabilities: { tools: true, input: [], output: [] },
variants: [],
time: { released: Date.parse("2026-01-01") },
cost: [
{
input: Money.USDPerMillionTokens.make(2.5),
output: Money.USDPerMillionTokens.make(15),
cache: {
read: Money.USDPerMillionTokens.zero,
write: Money.USDPerMillionTokens.zero,
},
},
{
tier: { type: "context", size: 272_000 },
input: Money.USDPerMillionTokens.make(3),
output: Money.USDPerMillionTokens.make(18),
cache: {
read: Money.USDPerMillionTokens.make(0.25),
write: Money.USDPerMillionTokens.zero,
},
},
{
tier: { type: "context", size: 200_000 },
input: Money.USDPerMillionTokens.make(5),
output: Money.USDPerMillionTokens.make(22.5),
cache: {
read: Money.USDPerMillionTokens.make(0.5),
write: Money.USDPerMillionTokens.zero,
},
},
],
status: "active",
enabled: true,
limit: { context: 1_050_000, input: 922_000, output: 128_000 },
},
{
id: Model.ID.make("gpt-5.4-fast"),
modelID,
providerID,
name: "GPT-5.4 Fast",
family: Model.Family.make("gpt"),
package: Provider.aisdk("@ai-sdk/openai-compatible"),
settings: { baseURL: "https://api.acme.test/v1" },
headers: { "x-mode": "fast" },
body: { service_tier: "priority" },
capabilities: { tools: true, input: [], output: [] },
variants: [],
time: { released: Date.parse("2026-01-01") },
cost: [
{
input: Money.USDPerMillionTokens.make(5),
output: Money.USDPerMillionTokens.make(30),
cache: {
read: Money.USDPerMillionTokens.make(0.5),
write: Money.USDPerMillionTokens.zero,
},
},
{
tier: { type: "context", size: 272_000 },
input: Money.USDPerMillionTokens.make(3),
output: Money.USDPerMillionTokens.make(18),
cache: {
read: Money.USDPerMillionTokens.make(0.25),
write: Money.USDPerMillionTokens.zero,
},
},
{
tier: { type: "context", size: 200_000 },
input: Money.USDPerMillionTokens.make(5),
output: Money.USDPerMillionTokens.make(22.5),
cache: {
read: Money.USDPerMillionTokens.make(0.5),
write: Money.USDPerMillionTokens.zero,
},
},
],
status: "active",
enabled: true,
limit: { context: 1_050_000, input: 922_000, output: 128_000 },
},
],
},
] satisfies readonly ModelsDev.Snapshot[]),
refresh: () => Effect.void,
})
yield* ModelsDevPlugin.effect(
host({
catalog: catalogHost(catalog),
integration: integrationHost(integrations),
}),
).pipe(Effect.provideService(ModelsDev.Service, models))
const base = yield* catalog.model.get(providerID, Model.ID.make("gpt-5.4"))
const fast = yield* catalog.model.get(providerID, Model.ID.make("gpt-5.4-fast"))
expect(base?.variants).toEqual([])
expect(base?.body).toBeUndefined()
expect(fast).toMatchObject({
id: "gpt-5.4-fast",
modelID: "gpt-5.4",
providerID: "acme",
name: "GPT-5.4 Fast",
package: Provider.aisdk("@ai-sdk/openai-compatible"),
settings: { baseURL: "https://api.acme.test/v1" },
headers: { "x-mode": "fast" },
body: { service_tier: "priority" },
variants: [],
})
expect(fast?.cost).toEqual([
{
input: Money.USDPerMillionTokens.make(5),
output: Money.USDPerMillionTokens.make(30),
cache: {
read: Money.USDPerMillionTokens.make(0.5),
write: Money.USDPerMillionTokens.zero,
},
},
{
tier: { type: "context", size: 272_000 },
input: Money.USDPerMillionTokens.make(3),
output: Money.USDPerMillionTokens.make(18),
cache: {
read: Money.USDPerMillionTokens.make(0.25),
write: Money.USDPerMillionTokens.zero,
},
},
{
tier: { type: "context", size: 200_000 },
input: Money.USDPerMillionTokens.make(5),
output: Money.USDPerMillionTokens.make(22.5),
cache: {
read: Money.USDPerMillionTokens.make(0.5),
write: Money.USDPerMillionTokens.zero,
},
},
])
}),
)
it.effect("registers key methods for providers with environment variables", () =>
2026-07-20 19:18:03 +00:00
Effect.gen(function* () {
const integrations = yield* Integration.Service
const catalog = yield* Catalog.Service
yield* ModelsDevPlugin.effect(
host({
catalog: catalogHost(catalog),
integration: integrationHost(integrations),
}),
2026-07-20 19:18:03 +00:00
)
expect(yield* integrations.list()).toEqual([
Integration.Info.make({
id: Integration.ID.make("acme"),
name: "Acme",
methods: [
{ type: "key" },
{
type: "env",
names: ["ACME_API_KEY"],
},
],
connections: [],
}),
])
}).pipe(Effect.provide(models(path.join(import.meta.dir, "fixtures", "models-dev.json")))),
)
it.effect("converts reasoning options into settings variants", () =>
2026-07-20 19:18:03 +00:00
Effect.gen(function* () {
const catalog = yield* Catalog.Service
const integrations = yield* Integration.Service
yield* ModelsDevPlugin.effect(
host({
catalog: catalogHost(catalog),
integration: integrationHost(integrations),
}),
)
const model = yield* catalog.model.get(Provider.ID.openai, Model.ID.make("gpt-reasoning"))
2026-07-20 19:18:03 +00:00
expect(model?.variants?.map((variant) => variant.id)).toEqual([
Model.VariantID.make("low"),
Model.VariantID.make("high"),
2026-07-20 19:18:03 +00:00
])
expect(model?.variants).toContainEqual({
id: Model.VariantID.make("low"),
2026-07-20 19:18:03 +00:00
settings: {
reasoningEffort: "low",
reasoningSummary: "auto",
include: ["reasoning.encrypted_content"],
},
})
expect(model?.variants).toContainEqual({
id: Model.VariantID.make("high"),
2026-07-20 19:18:03 +00:00
settings: {
reasoningEffort: "high",
reasoningSummary: "auto",
include: ["reasoning.encrypted_content"],
},
})
const mode = yield* catalog.model.get(Provider.ID.openai, Model.ID.make("gpt-reasoning-high"))
2026-07-20 19:18:03 +00:00
expect(mode).toMatchObject({
id: "gpt-reasoning-high",
name: "GPT Reasoning High",
headers: { "x-mode": "high" },
body: { service_tier: "priority" },
})
expect(mode?.variants?.map((variant) => variant.id)).toEqual([
Model.VariantID.make("low"),
Model.VariantID.make("high"),
2026-07-20 19:18:03 +00:00
])
const pro = yield* catalog.model.get(Provider.ID.openai, Model.ID.make("gpt-reasoning-pro"))
2026-07-20 19:18:03 +00:00
expect(pro).toMatchObject({
id: "gpt-reasoning-pro",
body: { reasoning: { mode: "pro" } },
})
const budgetModel = yield* catalog.model.get(Provider.ID.anthropic, Model.ID.make("claude-budget"))
2026-07-20 19:18:03 +00:00
expect(budgetModel?.variants).toContainEqual({
id: Model.VariantID.make("high"),
2026-07-20 19:18:03 +00:00
settings: { thinking: { type: "enabled", budgetTokens: 16000 } },
})
expect(budgetModel?.variants).toContainEqual({
id: Model.VariantID.make("max"),
2026-07-20 19:18:03 +00:00
settings: { thinking: { type: "enabled", budgetTokens: 31999 } },
})
const anthropicEffortModel = yield* catalog.model.get(Provider.ID.anthropic, Model.ID.make("claude-opus-4.7"))
2026-07-20 19:18:03 +00:00
expect(anthropicEffortModel?.variants).toEqual([
{ id: Model.VariantID.make("none"), settings: { thinking: { type: "disabled" } } },
2026-07-20 19:18:03 +00:00
{
id: Model.VariantID.make("low"),
2026-07-20 19:18:03 +00:00
settings: { thinking: { type: "adaptive", display: "summarized" }, effort: "low" },
},
])
const anthropicToggleModel = yield* catalog.model.get(Provider.ID.anthropic, Model.ID.make("claude-toggle"))
2026-07-20 19:18:03 +00:00
expect(anthropicToggleModel?.variants).toEqual([
{ id: Model.VariantID.make("none"), settings: { thinking: { type: "disabled" } } },
2026-07-20 19:18:03 +00:00
{
id: Model.VariantID.make("thinking"),
2026-07-20 19:18:03 +00:00
settings: { thinking: { type: "adaptive", display: "summarized" } },
},
])
const opus45 = yield* catalog.model.get(Provider.ID.anthropic, Model.ID.make("claude-opus-4-5"))
2026-07-20 19:18:03 +00:00
expect(opus45?.variants).toEqual([
{ id: Model.VariantID.make("low"), settings: { effort: "low" } },
{ id: Model.VariantID.make("high"), settings: { effort: "high" } },
2026-07-20 19:18:03 +00:00
])
const grok = yield* catalog.model.get(Provider.ID.make("xai"), Model.ID.make("grok-4.5"))
2026-07-20 19:18:03 +00:00
expect(grok?.variants).toEqual(
["low", "medium", "high"].map((id) => ({
id: Model.VariantID.make(id),
2026-07-20 19:18:03 +00:00
settings: { reasoningEffort: id },
})),
)
const minimax = yield* catalog.model.get(Provider.ID.make("opencode-go"), Model.ID.make("minimax-m3"))
2026-07-20 19:18:03 +00:00
expect(minimax?.variants).toEqual([
{ id: Model.VariantID.make("none"), settings: { thinking: { type: "disabled" } } },
2026-07-20 19:18:03 +00:00
{
id: Model.VariantID.make("thinking"),
2026-07-20 19:18:03 +00:00
settings: { thinking: { type: "adaptive", display: "summarized" } },
},
])
const toggle = yield* catalog.model.get(Provider.ID.make("alibaba"), Model.ID.make("toggle-only"))
2026-07-20 19:18:03 +00:00
expect(toggle?.variants).toEqual([
{ id: Model.VariantID.make("none"), settings: { enableThinking: false } },
{ id: Model.VariantID.make("thinking"), settings: { enableThinking: true } },
2026-07-20 19:18:03 +00:00
])
const combined = yield* catalog.model.get(Provider.ID.make("alibaba"), Model.ID.make("toggle-budget"))
2026-07-20 19:18:03 +00:00
expect(combined?.variants).toEqual([
{ id: Model.VariantID.make("none"), settings: { enableThinking: false } },
2026-07-20 19:18:03 +00:00
{
id: Model.VariantID.make("high"),
2026-07-20 19:18:03 +00:00
settings: { enableThinking: true, thinkingBudget: 8000 },
},
{
id: Model.VariantID.make("max"),
2026-07-20 19:18:03 +00:00
settings: { enableThinking: true, thinkingBudget: 16000 },
},
])
const gateway = yield* catalog.model.get(Provider.ID.make("vercel"), Model.ID.make("alibaba/qwen-toggle"))
2026-07-20 19:18:03 +00:00
expect(gateway?.variants).toEqual([
{ id: Model.VariantID.make("none"), settings: { enableThinking: false } },
2026-07-20 19:18:03 +00:00
{
id: Model.VariantID.make("high"),
2026-07-20 19:18:03 +00:00
settings: { enableThinking: true, thinkingBudget: 8000 },
},
{
id: Model.VariantID.make("max"),
2026-07-20 19:18:03 +00:00
settings: { enableThinking: true, thinkingBudget: 16000 },
},
])
const gatewayNova = yield* catalog.model.get(Provider.ID.make("vercel"), Model.ID.make("amazon/nova-2-lite"))
2026-07-20 19:18:03 +00:00
expect(gatewayNova?.variants).toEqual([
{
id: Model.VariantID.make("none"),
2026-07-20 19:18:03 +00:00
settings: { additionalModelRequestFields: { reasoningConfig: { type: "disabled" } } },
},
{
id: Model.VariantID.make("low"),
2026-07-20 19:18:03 +00:00
settings: { reasoningConfig: { type: "enabled", maxReasoningEffort: "low" } },
},
{
id: Model.VariantID.make("high"),
2026-07-20 19:18:03 +00:00
settings: { reasoningConfig: { type: "enabled", maxReasoningEffort: "high" } },
},
])
2026-07-20 19:18:03 +00:00
const gatewayFallback = yield* catalog.model.get(
Provider.ID.make("vercel"),
Model.ID.make("deepseek/deepseek-toggle"),
2026-07-20 19:18:03 +00:00
)
expect(gatewayFallback?.variants).toEqual([
{
id: Model.VariantID.make("none"),
2026-07-20 19:18:03 +00:00
settings: { reasoning: { enabled: false } },
},
{
id: Model.VariantID.make("low"),
2026-07-20 19:18:03 +00:00
settings: { reasoningEffort: "low" },
},
{
id: Model.VariantID.make("high"),
2026-07-20 19:18:03 +00:00
settings: { reasoningEffort: "high" },
},
])
2026-07-20 19:18:03 +00:00
const openrouter = yield* catalog.model.get(
Provider.ID.make("openrouter"),
Model.ID.make("openrouter-toggle"),
2026-07-20 19:18:03 +00:00
)
expect(openrouter?.variants).toEqual([
{ id: Model.VariantID.make("none"), settings: { reasoning: { enabled: false } } },
{ id: Model.VariantID.make("thinking"), settings: { reasoning: { enabled: true } } },
2026-07-20 19:18:03 +00:00
])
const google = yield* catalog.model.get(Provider.ID.make("google"), Model.ID.make("gemini-2.5-flash"))
2026-07-20 19:18:03 +00:00
expect(google?.variants).toEqual([
{
id: Model.VariantID.make("none"),
2026-07-20 19:18:03 +00:00
settings: { thinkingConfig: { includeThoughts: false, thinkingBudget: 0 } },
},
{
id: Model.VariantID.make("high"),
2026-07-20 19:18:03 +00:00
settings: { thinkingConfig: { includeThoughts: true, thinkingBudget: 8000 } },
},
{
id: Model.VariantID.make("max"),
2026-07-20 19:18:03 +00:00
settings: { thinkingConfig: { includeThoughts: true, thinkingBudget: 16000 } },
},
])
2026-07-20 19:18:03 +00:00
const vertex = yield* catalog.model.get(
Provider.ID.make("google-vertex"),
Model.ID.make("gemini-2.5-flash-lite"),
2026-07-20 19:18:03 +00:00
)
expect(vertex?.variants).toEqual([
{
id: Model.VariantID.make("none"),
2026-07-20 19:18:03 +00:00
settings: { thinkingConfig: { includeThoughts: false, thinkingBudget: 0 } },
},
{
id: Model.VariantID.make("high"),
2026-07-20 19:18:03 +00:00
settings: { thinkingConfig: { includeThoughts: true, thinkingBudget: 8000 } },
},
{
id: Model.VariantID.make("max"),
2026-07-20 19:18:03 +00:00
settings: { thinkingConfig: { includeThoughts: true, thinkingBudget: 16000 } },
},
])
2026-07-20 19:18:03 +00:00
const bedrock = yield* catalog.model.get(
Provider.ID.make("amazon-bedrock"),
Model.ID.make("amazon.nova-2-lite-v1:0"),
2026-07-20 19:18:03 +00:00
)
expect(bedrock?.variants).toEqual([
{
id: Model.VariantID.make("none"),
2026-07-20 19:18:03 +00:00
settings: { additionalModelRequestFields: { reasoningConfig: { type: "disabled" } } },
},
{
id: Model.VariantID.make("low"),
2026-07-20 19:18:03 +00:00
settings: { reasoningConfig: { type: "enabled", maxReasoningEffort: "low" } },
},
{
id: Model.VariantID.make("high"),
2026-07-20 19:18:03 +00:00
settings: { reasoningConfig: { type: "enabled", maxReasoningEffort: "high" } },
},
])
const sapGemini = yield* catalog.model.get(Provider.ID.make("sap-ai-core"), Model.ID.make("gemini-2.5-flash"))
2026-07-20 19:18:03 +00:00
expect(sapGemini?.variants).toEqual([
{
id: Model.VariantID.make("none"),
2026-07-20 19:18:03 +00:00
settings: { modelParams: { thinkingConfig: { includeThoughts: false, thinkingBudget: 0 } } },
},
{
id: Model.VariantID.make("high"),
2026-07-20 19:18:03 +00:00
settings: { modelParams: { thinkingConfig: { includeThoughts: true, thinkingBudget: 8000 } } },
},
{
id: Model.VariantID.make("max"),
2026-07-20 19:18:03 +00:00
settings: { modelParams: { thinkingConfig: { includeThoughts: true, thinkingBudget: 16000 } } },
},
])
const sapNova = yield* catalog.model.get(Provider.ID.make("sap-ai-core"), Model.ID.make("amazon--nova-lite"))
2026-07-20 19:18:03 +00:00
expect(sapNova?.variants).toEqual([
{
id: Model.VariantID.make("none"),
2026-07-20 19:18:03 +00:00
settings: {
modelParams: { additionalModelRequestFields: { thinking: { type: "disabled" } } },
},
},
{
id: Model.VariantID.make("low"),
2026-07-20 19:18:03 +00:00
settings: {
modelParams: { additionalModelRequestFields: { output_config: { effort: "low" } } },
},
},
{
id: Model.VariantID.make("high"),
2026-07-20 19:18:03 +00:00
settings: {
modelParams: { additionalModelRequestFields: { output_config: { effort: "high" } } },
},
},
])
2026-07-20 19:18:03 +00:00
const sapCohere = yield* catalog.model.get(
Provider.ID.make("sap-ai-core"),
Model.ID.make("cohere--command-a-reasoning"),
2026-07-20 19:18:03 +00:00
)
expect(sapCohere?.variants).toEqual([
{
id: Model.VariantID.make("none"),
2026-07-20 19:18:03 +00:00
settings: { modelParams: { thinking: { type: "disabled" } } },
},
{
id: Model.VariantID.make("low"),
2026-07-20 19:18:03 +00:00
settings: { modelParams: { reasoning_effort: "low" } },
},
{
id: Model.VariantID.make("high"),
2026-07-20 19:18:03 +00:00
settings: { modelParams: { reasoning_effort: "high" } },
},
])
2026-07-20 19:18:03 +00:00
const sapAnthropicEffort = yield* catalog.model.get(
Provider.ID.make("sap-ai-core"),
Model.ID.make("anthropic--claude-4.7-opus"),
2026-07-20 19:18:03 +00:00
)
expect(sapAnthropicEffort?.variants).toEqual([
{
id: Model.VariantID.make("low"),
2026-07-20 19:18:03 +00:00
settings: {
modelParams: {
additionalModelRequestFields: {
thinking: { type: "adaptive", display: "summarized" },
output_config: { effort: "low" },
},
},
2026-07-20 19:18:03 +00:00
},
},
])
2026-07-20 19:18:03 +00:00
const sapAnthropicBudget = yield* catalog.model.get(
Provider.ID.make("sap-ai-core"),
Model.ID.make("anthropic--claude-4-sonnet"),
2026-07-20 19:18:03 +00:00
)
expect(sapAnthropicBudget?.variants).toEqual([
{
id: Model.VariantID.make("high"),
2026-07-20 19:18:03 +00:00
settings: {
modelParams: {
additionalModelRequestFields: { thinking: { type: "enabled", budget_tokens: 8000 } },
},
2026-07-20 19:18:03 +00:00
},
},
{
id: Model.VariantID.make("max"),
2026-07-20 19:18:03 +00:00
settings: {
modelParams: {
additionalModelRequestFields: { thinking: { type: "enabled", budget_tokens: 16000 } },
},
2026-07-20 19:18:03 +00:00
},
},
])
}).pipe(Effect.provide(models(path.join(import.meta.dir, "fixtures", "models-dev-reasoning.json")))),
)
})