refactor(config): migrate model-id and command to Effect Schema (#23175)
This commit is contained in:
@@ -15,7 +15,7 @@ const log = Log.create({ service: "config" })
|
|||||||
|
|
||||||
export const Info = z
|
export const Info = z
|
||||||
.object({
|
.object({
|
||||||
model: ConfigModelID.optional(),
|
model: ConfigModelID.zod.optional(),
|
||||||
variant: z
|
variant: z
|
||||||
.string()
|
.string()
|
||||||
.optional()
|
.optional()
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
export * as ConfigCommand from "./command"
|
export * as ConfigCommand from "./command"
|
||||||
|
|
||||||
import { Log } from "../util"
|
import { Log } from "../util"
|
||||||
import z from "zod"
|
import { Schema } from "effect"
|
||||||
import { NamedError } from "@opencode-ai/shared/util/error"
|
import { NamedError } from "@opencode-ai/shared/util/error"
|
||||||
import { Glob } from "@opencode-ai/shared/util/glob"
|
import { Glob } from "@opencode-ai/shared/util/glob"
|
||||||
import { Bus } from "@/bus"
|
import { Bus } from "@/bus"
|
||||||
|
import { zod } from "@/util/effect-zod"
|
||||||
|
import { withStatics } from "@/util/schema"
|
||||||
import { configEntryNameFromPath } from "./entry-name"
|
import { configEntryNameFromPath } from "./entry-name"
|
||||||
import { InvalidError } from "./error"
|
import { InvalidError } from "./error"
|
||||||
import * as ConfigMarkdown from "./markdown"
|
import * as ConfigMarkdown from "./markdown"
|
||||||
@@ -12,15 +14,15 @@ import { ConfigModelID } from "./model-id"
|
|||||||
|
|
||||||
const log = Log.create({ service: "config" })
|
const log = Log.create({ service: "config" })
|
||||||
|
|
||||||
export const Info = z.object({
|
export const Info = Schema.Struct({
|
||||||
template: z.string(),
|
template: Schema.String,
|
||||||
description: z.string().optional(),
|
description: Schema.optional(Schema.String),
|
||||||
agent: z.string().optional(),
|
agent: Schema.optional(Schema.String),
|
||||||
model: ConfigModelID.optional(),
|
model: Schema.optional(ConfigModelID),
|
||||||
subtask: z.boolean().optional(),
|
subtask: Schema.optional(Schema.Boolean),
|
||||||
})
|
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||||
|
|
||||||
export type Info = z.infer<typeof Info>
|
export type Info = Schema.Schema.Type<typeof Info>
|
||||||
|
|
||||||
export async function load(dir: string) {
|
export async function load(dir: string) {
|
||||||
const result: Record<string, Info> = {}
|
const result: Record<string, Info> = {}
|
||||||
@@ -49,7 +51,7 @@ export async function load(dir: string) {
|
|||||||
...md.data,
|
...md.data,
|
||||||
template: md.content.trim(),
|
template: md.content.trim(),
|
||||||
}
|
}
|
||||||
const parsed = Info.safeParse(config)
|
const parsed = Info.zod.safeParse(config)
|
||||||
if (parsed.success) {
|
if (parsed.success) {
|
||||||
result[config.name] = parsed.data
|
result[config.name] = parsed.data
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export const Info = z
|
|||||||
logLevel: Log.Level.optional().describe("Log level"),
|
logLevel: Log.Level.optional().describe("Log level"),
|
||||||
server: Server.optional().describe("Server configuration for opencode serve and web commands"),
|
server: Server.optional().describe("Server configuration for opencode serve and web commands"),
|
||||||
command: z
|
command: z
|
||||||
.record(z.string(), ConfigCommand.Info)
|
.record(z.string(), ConfigCommand.Info.zod)
|
||||||
.optional()
|
.optional()
|
||||||
.describe("Command configuration, see https://opencode.ai/docs/commands"),
|
.describe("Command configuration, see https://opencode.ai/docs/commands"),
|
||||||
skills: ConfigSkills.Info.zod.optional().describe("Additional skill folder paths"),
|
skills: ConfigSkills.Info.zod.optional().describe("Additional skill folder paths"),
|
||||||
@@ -135,8 +135,10 @@ export const Info = z
|
|||||||
.array(z.string())
|
.array(z.string())
|
||||||
.optional()
|
.optional()
|
||||||
.describe("When set, ONLY these providers will be enabled. All other providers will be ignored"),
|
.describe("When set, ONLY these providers will be enabled. All other providers will be ignored"),
|
||||||
model: ConfigModelID.describe("Model to use in the format of provider/model, eg anthropic/claude-2").optional(),
|
model: ConfigModelID.zod
|
||||||
small_model: ConfigModelID.describe(
|
.describe("Model to use in the format of provider/model, eg anthropic/claude-2")
|
||||||
|
.optional(),
|
||||||
|
small_model: ConfigModelID.zod.describe(
|
||||||
"Small model to use for tasks like title generation in the format of provider/model",
|
"Small model to use for tasks like title generation in the format of provider/model",
|
||||||
).optional(),
|
).optional(),
|
||||||
default_agent: z
|
default_agent: z
|
||||||
|
|||||||
@@ -1,3 +1,14 @@
|
|||||||
|
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 ConfigModelID = z.string().meta({ $ref: "https://models.dev/model-schema.json#/$defs/Model" })
|
// The original Zod schema carried an external $ref pointing at the models.dev
|
||||||
|
// JSON schema. That external reference is not a named SDK component — it is a
|
||||||
|
// literal pointer to an outside schema — so the walker cannot re-derive it
|
||||||
|
// from AST metadata. Preserve the exact original Zod via ZodOverride.
|
||||||
|
export const ConfigModelID = Schema.String.annotate({
|
||||||
|
[ZodOverride]: z.string().meta({ $ref: "https://models.dev/model-schema.json#/$defs/Model" }),
|
||||||
|
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||||
|
|
||||||
|
export type ConfigModelID = Schema.Schema.Type<typeof ConfigModelID>
|
||||||
|
|||||||
Reference in New Issue
Block a user