refactor(config): migrate provider (Model + Info) to Effect Schema (#23197)

This commit is contained in:
Kit Langton 2026-04-17 19:29:53 -04:00 committed by GitHub
commit 0c1ffc6fa9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 109 additions and 113 deletions

View file

@ -171,7 +171,7 @@ export const Info = z
.optional() .optional()
.describe("Agent configuration, see https://opencode.ai/docs/agents"), .describe("Agent configuration, see https://opencode.ai/docs/agents"),
provider: z provider: z
.record(z.string(), ConfigProvider.Info) .record(z.string(), ConfigProvider.Info.zod)
.optional() .optional()
.describe("Custom provider configurations and model overrides"), .describe("Custom provider configurations and model overrides"),
mcp: z mcp: z

View file

@ -1,120 +1,116 @@
import { Schema } from "effect"
import z from "zod" import z from "zod"
import { zod, ZodOverride } from "@/util/effect-zod"
import { withStatics } from "@/util/schema"
export const Model = z // Positive integer preserving exact Zod JSON Schema (type: integer, exclusiveMinimum: 0).
.object({ const PositiveInt = Schema.Number.annotate({
id: z.string(), [ZodOverride]: z.number().int().positive(),
name: z.string(), })
family: z.string().optional(),
release_date: z.string(), export const Model = Schema.Struct({
attachment: z.boolean(), id: Schema.optional(Schema.String),
reasoning: z.boolean(), name: Schema.optional(Schema.String),
temperature: z.boolean(), family: Schema.optional(Schema.String),
tool_call: z.boolean(), release_date: Schema.optional(Schema.String),
interleaved: z attachment: Schema.optional(Schema.Boolean),
.union([ reasoning: Schema.optional(Schema.Boolean),
z.literal(true), temperature: Schema.optional(Schema.Boolean),
z tool_call: Schema.optional(Schema.Boolean),
.object({ interleaved: Schema.optional(
field: z.enum(["reasoning_content", "reasoning_details"]), Schema.Union([
}) Schema.Literal(true),
.strict(), Schema.Struct({
]) field: Schema.Literals(["reasoning_content", "reasoning_details"]),
.optional(), }),
cost: z ]),
.object({ ),
input: z.number(), cost: Schema.optional(
output: z.number(), Schema.Struct({
cache_read: z.number().optional(), input: Schema.Number,
cache_write: z.number().optional(), output: Schema.Number,
context_over_200k: z cache_read: Schema.optional(Schema.Number),
.object({ cache_write: Schema.optional(Schema.Number),
input: z.number(), context_over_200k: Schema.optional(
output: z.number(), Schema.Struct({
cache_read: z.number().optional(), input: Schema.Number,
cache_write: z.number().optional(), output: Schema.Number,
}) cache_read: Schema.optional(Schema.Number),
.optional(), cache_write: Schema.optional(Schema.Number),
}) }),
.optional(), ),
limit: z.object({
context: z.number(),
input: z.number().optional(),
output: z.number(),
}), }),
modalities: z ),
.object({ limit: Schema.optional(
input: z.array(z.enum(["text", "audio", "image", "video", "pdf"])), Schema.Struct({
output: z.array(z.enum(["text", "audio", "image", "video", "pdf"])), context: Schema.Number,
}) input: Schema.optional(Schema.Number),
.optional(), output: Schema.Number,
experimental: z.boolean().optional(), }),
status: z.enum(["alpha", "beta", "deprecated"]).optional(), ),
provider: z.object({ npm: z.string().optional(), api: z.string().optional() }).optional(), modalities: Schema.optional(
options: z.record(z.string(), z.any()), Schema.Struct({
headers: z.record(z.string(), z.string()).optional(), input: Schema.mutable(Schema.Array(Schema.Literals(["text", "audio", "image", "video", "pdf"]))),
variants: z output: Schema.mutable(Schema.Array(Schema.Literals(["text", "audio", "image", "video", "pdf"]))),
.record( }),
z.string(), ),
z experimental: Schema.optional(Schema.Boolean),
.object({ status: Schema.optional(Schema.Literals(["alpha", "beta", "deprecated"])),
disabled: z.boolean().optional().describe("Disable this variant for the model"), provider: Schema.optional(Schema.Struct({ npm: Schema.optional(Schema.String), api: Schema.optional(Schema.String) })),
}) options: Schema.optional(Schema.Record(Schema.String, Schema.Any)),
.catchall(z.any()), headers: Schema.optional(Schema.Record(Schema.String, Schema.String)),
) variants: Schema.optional(
.optional() Schema.Record(
.describe("Variant-specific configuration"), Schema.String,
}) Schema.StructWithRest(
.partial() Schema.Struct({
disabled: Schema.optional(Schema.Boolean).annotate({ description: "Disable this variant for the model" }),
}),
[Schema.Record(Schema.String, Schema.Any)],
),
).annotate({ description: "Variant-specific configuration" }),
),
}).pipe(withStatics((s) => ({ zod: zod(s) })))
export const Info = z export class Info extends Schema.Class<Info>("ProviderConfig")({
.object({ api: Schema.optional(Schema.String),
api: z.string().optional(), name: Schema.optional(Schema.String),
name: z.string(), env: Schema.optional(Schema.mutable(Schema.Array(Schema.String))),
env: z.array(z.string()), id: Schema.optional(Schema.String),
id: z.string(), npm: Schema.optional(Schema.String),
npm: z.string().optional(), whitelist: Schema.optional(Schema.mutable(Schema.Array(Schema.String))),
whitelist: z.array(z.string()).optional(), blacklist: Schema.optional(Schema.mutable(Schema.Array(Schema.String))),
blacklist: z.array(z.string()).optional(), options: Schema.optional(
options: z Schema.StructWithRest(
.object({ Schema.Struct({
apiKey: z.string().optional(), apiKey: Schema.optional(Schema.String),
baseURL: z.string().optional(), baseURL: Schema.optional(Schema.String),
enterpriseUrl: z.string().optional().describe("GitHub Enterprise URL for copilot authentication"), enterpriseUrl: Schema.optional(Schema.String).annotate({
setCacheKey: z.boolean().optional().describe("Enable promptCacheKey for this provider (default false)"), description: "GitHub Enterprise URL for copilot authentication",
timeout: z }),
.union([ setCacheKey: Schema.optional(Schema.Boolean).annotate({
z description: "Enable promptCacheKey for this provider (default false)",
.number() }),
.int() timeout: Schema.optional(
.positive() Schema.Union([PositiveInt, Schema.Literal(false)]).annotate({
.describe( description:
"Timeout in milliseconds for requests to this provider. Default is 300000 (5 minutes). Set to false to disable timeout.", "Timeout in milliseconds for requests to this provider. Default is 300000 (5 minutes). Set to false to disable timeout.",
), }),
z.literal(false).describe("Disable timeout for this provider entirely."), ).annotate({
]) description:
.optional()
.describe(
"Timeout in milliseconds for requests to this provider. Default is 300000 (5 minutes). Set to false to disable timeout.", "Timeout in milliseconds for requests to this provider. Default is 300000 (5 minutes). Set to false to disable timeout.",
), }),
chunkTimeout: z chunkTimeout: Schema.optional(PositiveInt).annotate({
.number() description:
.int()
.positive()
.optional()
.describe(
"Timeout in milliseconds between streamed SSE chunks for this provider. If no chunk arrives within this window, the request is aborted.", "Timeout in milliseconds between streamed SSE chunks for this provider. If no chunk arrives within this window, the request is aborted.",
), }),
}) }),
.catchall(z.any()) [Schema.Record(Schema.String, Schema.Any)],
.optional(), ),
models: z.record(z.string(), Model).optional(), ),
}) models: Schema.optional(Schema.Record(Schema.String, Model)),
.partial() }) {
.strict() static readonly zod = zod(this)
.meta({ }
ref: "ProviderConfig",
})
export type Info = z.infer<typeof Info>
export * as ConfigProvider from "./provider" export * as ConfigProvider from "./provider"