|
|
@@ -145,14 +145,7 @@ export const layer: Layer.Layer<
|
|
|
const entries = Object.entries(def.args)
|
|
|
const allZod = entries.every((entry) => isZodType(entry[1]))
|
|
|
const zodParams = allZod ? z.object(def.args) : undefined
|
|
|
- // Newer @opencode-ai/plugin versions precompute JSON Schema with the
|
|
|
- // Zod instance that owns arg metadata. Fall back for older/manual
|
|
|
- // custom tools that only expose raw Zod args.
|
|
|
- const jsonSchema = zodParams
|
|
|
- ? isJsonSchemaDefinition(def.jsonSchema)
|
|
|
- ? (def.jsonSchema as JSONSchema7)
|
|
|
- : zodJsonSchema(zodParams)
|
|
|
- : legacyJsonSchema(entries)
|
|
|
+ const jsonSchema = zodParams ? zodJsonSchema(zodParams) : legacyJsonSchema(entries)
|
|
|
const parameters = zodParams
|
|
|
? Schema.declare<unknown>((u): u is unknown => zodParams.safeParse(u).success)
|
|
|
: Schema.Unknown
|
|
|
@@ -424,7 +417,7 @@ function legacyJsonSchema(entries: [string, unknown][]): JSONSchema7 {
|
|
|
}
|
|
|
|
|
|
function zodJsonSchema(schema: z.ZodType): JSONSchema7 {
|
|
|
- const result = normalizeZodJsonSchema(z.toJSONSchema(schema, { io: "input" }))
|
|
|
+ const result = normalizeZodJsonSchema(z.toJSONSchema(schema, { io: "input", metadata: zodMetadataRegistry(schema) }))
|
|
|
if (!isJsonSchemaObject(result)) throw new Error("plugin tool Zod schema produced a non-object JSON Schema")
|
|
|
const { $defs, ...rest } = result
|
|
|
return (
|
|
|
@@ -432,6 +425,32 @@ function zodJsonSchema(schema: z.ZodType): JSONSchema7 {
|
|
|
) as JSONSchema7
|
|
|
}
|
|
|
|
|
|
+function zodMetadataRegistry(schema: z.ZodType) {
|
|
|
+ const registry = z.registry<Record<string, unknown>>()
|
|
|
+ const seen = new WeakSet<object>()
|
|
|
+ const collect = (value: unknown) => {
|
|
|
+ if (typeof value !== "object" || value === null) return
|
|
|
+ if (seen.has(value)) return
|
|
|
+ seen.add(value)
|
|
|
+
|
|
|
+ if (isZodType(value)) {
|
|
|
+ const metadata = typeof value.meta === "function" ? value.meta() : undefined
|
|
|
+ const description = typeof value.description === "string" ? value.description : undefined
|
|
|
+ const merged = {
|
|
|
+ ...(metadata && typeof metadata === "object" ? metadata : {}),
|
|
|
+ ...(description ? { description } : {}),
|
|
|
+ }
|
|
|
+ if (Object.keys(merged).length) registry.add(value, merged)
|
|
|
+ collect(value._zod.def)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for (const item of Object.values(value)) collect(item)
|
|
|
+ }
|
|
|
+ collect(schema)
|
|
|
+ return registry
|
|
|
+}
|
|
|
+
|
|
|
function normalizeZodJsonSchema(value: unknown): unknown {
|
|
|
if (Array.isArray(value)) return value.map((item) => normalizeZodJsonSchema(item))
|
|
|
if (typeof value !== "object" || value === null) return value
|