瀏覽代碼

refactor(config): migrate model-id and command to Effect Schema (#23175)

Kit Langton 1 天之前
父節點
當前提交
ce69bd97b9

+ 1 - 1
packages/opencode/src/config/agent.ts

@@ -15,7 +15,7 @@ const log = Log.create({ service: "config" })
 
 export const Info = z
   .object({
-    model: ConfigModelID.optional(),
+    model: ConfigModelID.zod.optional(),
     variant: z
       .string()
       .optional()

+ 12 - 10
packages/opencode/src/config/command.ts

@@ -1,10 +1,12 @@
 export * as ConfigCommand from "./command"
 
 import { Log } from "../util"
-import z from "zod"
+import { Schema } from "effect"
 import { NamedError } from "@opencode-ai/shared/util/error"
 import { Glob } from "@opencode-ai/shared/util/glob"
 import { Bus } from "@/bus"
+import { zod } from "@/util/effect-zod"
+import { withStatics } from "@/util/schema"
 import { configEntryNameFromPath } from "./entry-name"
 import { InvalidError } from "./error"
 import * as ConfigMarkdown from "./markdown"
@@ -12,15 +14,15 @@ import { ConfigModelID } from "./model-id"
 
 const log = Log.create({ service: "config" })
 
-export const Info = z.object({
-  template: z.string(),
-  description: z.string().optional(),
-  agent: z.string().optional(),
-  model: ConfigModelID.optional(),
-  subtask: z.boolean().optional(),
-})
+export const Info = Schema.Struct({
+  template: Schema.String,
+  description: Schema.optional(Schema.String),
+  agent: Schema.optional(Schema.String),
+  model: Schema.optional(ConfigModelID),
+  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) {
   const result: Record<string, Info> = {}
@@ -49,7 +51,7 @@ export async function load(dir: string) {
       ...md.data,
       template: md.content.trim(),
     }
-    const parsed = Info.safeParse(config)
+    const parsed = Info.zod.safeParse(config)
     if (parsed.success) {
       result[config.name] = parsed.data
       continue

+ 5 - 3
packages/opencode/src/config/config.ts

@@ -97,7 +97,7 @@ export const Info = z
     logLevel: Log.Level.optional().describe("Log level"),
     server: Server.optional().describe("Server configuration for opencode serve and web commands"),
     command: z
-      .record(z.string(), ConfigCommand.Info)
+      .record(z.string(), ConfigCommand.Info.zod)
       .optional()
       .describe("Command configuration, see https://opencode.ai/docs/commands"),
     skills: ConfigSkills.Info.zod.optional().describe("Additional skill folder paths"),
@@ -135,8 +135,10 @@ export const Info = z
       .array(z.string())
       .optional()
       .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(),
-    small_model: ConfigModelID.describe(
+    model: ConfigModelID.zod
+      .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",
     ).optional(),
     default_agent: z

+ 12 - 1
packages/opencode/src/config/model-id.ts

@@ -1,3 +1,14 @@
+import { Schema } from "effect"
 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>