refactor(config): migrate provider (Model + Info) to Effect Schema (#23197)
This commit is contained in:
parent
8d2d871a58
commit
0c1ffc6fa9
2 changed files with 109 additions and 113 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue