diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 3cae1af4bdb2..b41e5d71c25e 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -730,28 +730,77 @@ export namespace Config { }) export type Layout = z.infer + export const Model = z + .object({ + id: z.string(), + name: z.string(), + family: z.string().optional(), + release_date: z.string(), + attachment: z.boolean(), + reasoning: z.boolean(), + temperature: z.boolean(), + tool_call: z.boolean(), + interleaved: z + .union([ + z.literal(true), + z + .object({ + field: z.enum(["reasoning_content", "reasoning_details"]), + }) + .strict(), + ]) + .optional(), + cost: z + .object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional(), + context_over_200k: z + .object({ + input: z.number(), + output: z.number(), + cache_read: z.number().optional(), + cache_write: z.number().optional(), + }) + .optional(), + }) + .optional(), + limit: z.object({ + context: z.number(), + input: z.number().optional(), + output: z.number(), + }), + modalities: z + .object({ + input: z.array(z.enum(["text", "audio", "image", "video", "pdf"])), + output: z.array(z.enum(["text", "audio", "image", "video", "pdf"])), + }) + .optional(), + experimental: z.boolean().optional(), + status: z.enum(["alpha", "beta", "deprecated"]).optional(), + options: z.record(z.string(), z.any()), + headers: z.record(z.string(), z.string()).optional(), + provider: z.object({ npm: z.string().optional(), api: z.string().optional() }).optional(), + variants: z + .record( + z.string(), + z + .object({ + disabled: z.boolean().optional().describe("Disable this variant for the model"), + }) + .catchall(z.any()), + ) + .optional() + .describe("Variant-specific configuration"), + }) + .partial() + export const Provider = ModelsDev.Provider.partial() .extend({ whitelist: z.array(z.string()).optional(), blacklist: z.array(z.string()).optional(), - models: z - .record( - z.string(), - ModelsDev.Model.partial().extend({ - variants: z - .record( - z.string(), - z - .object({ - disabled: z.boolean().optional().describe("Disable this variant for the model"), - }) - .catchall(z.any()), - ) - .optional() - .describe("Variant-specific configuration"), - }), - ) - .optional(), + models: z.record(z.string(), Model).optional(), options: z .object({ apiKey: z.string().optional(), diff --git a/packages/opencode/src/provider/models.ts b/packages/opencode/src/provider/models.ts index 30901ea74f0e..0e2a26b4d986 100644 --- a/packages/opencode/src/provider/models.ts +++ b/packages/opencode/src/provider/models.ts @@ -61,12 +61,8 @@ export namespace ModelsDev { output: z.array(z.enum(["text", "audio", "image", "video", "pdf"])), }) .optional(), - experimental: z.boolean().optional(), status: z.enum(["alpha", "beta", "deprecated"]).optional(), - options: z.record(z.string(), z.any()), - headers: z.record(z.string(), z.string()).optional(), provider: z.object({ npm: z.string().optional(), api: z.string().optional() }).optional(), - variants: z.record(z.string(), z.record(z.string(), z.any())).optional(), }) export type Model = z.infer diff --git a/packages/opencode/src/provider/provider.ts b/packages/opencode/src/provider/provider.ts index 45fbeb7e025b..ff45e1340760 100644 --- a/packages/opencode/src/provider/provider.ts +++ b/packages/opencode/src/provider/provider.ts @@ -901,8 +901,8 @@ export namespace Provider { npm: model.provider?.npm ?? provider.npm ?? "@ai-sdk/openai-compatible", }, status: model.status ?? "active", - headers: model.headers ?? {}, - options: model.options ?? {}, + headers: {}, + options: {}, cost: { input: model.cost?.input ?? 0, output: model.cost?.output ?? 0, diff --git a/packages/opencode/src/session/llm.ts b/packages/opencode/src/session/llm.ts index dc89db409e87..41f72df06a66 100644 --- a/packages/opencode/src/session/llm.ts +++ b/packages/opencode/src/session/llm.ts @@ -1,7 +1,6 @@ import { Provider } from "@/provider/provider" import { Log } from "@/util/log" -import { Cause, Effect, Layer, Record, ServiceMap } from "effect" -import * as Queue from "effect/Queue" +import { Effect, Layer, Record, ServiceMap } from "effect" import * as Stream from "effect/Stream" import { streamText, wrapLanguageModel, type ModelMessage, type Tool, tool, jsonSchema } from "ai" import { mergeDeep, pipe } from "remeda"