* Convert a Standard Schema to JSON Schema for the Claude API. * Tries vendor-specific toJSONSchema first (Zod v4), then falls back * to a basic introspection of the schema shape.
( schema: StandardSchemaV1, _description?: string, )
| 225 | * to a basic introspection of the schema shape. |
| 226 | */ |
| 227 | function schemaToJsonSchema( |
| 228 | schema: StandardSchemaV1, |
| 229 | _description?: string, |
| 230 | ): ActionTool["parameters"] { |
| 231 | const s = schema as any; |
| 232 | |
| 233 | // Prefer Zod's own JSON Schema output — it handles descriptions, |
| 234 | // enums, coerce, and all type wrappers correctly. |
| 235 | if (s["~standard"]?.jsonSchema?.input) { |
| 236 | try { |
| 237 | const result = s["~standard"].jsonSchema.input({ |
| 238 | target: "draft-07", |
| 239 | }) as any; |
| 240 | // Strip $schema — the Claude API validates against draft 2020-12 |
| 241 | // and a mismatched $schema declaration can cause rejections. |
| 242 | if (result && typeof result === "object") { |
| 243 | delete result.$schema; |
| 244 | } |
| 245 | return result as ActionTool["parameters"]; |
| 246 | } catch { |
| 247 | // Fall through to manual converter |
| 248 | } |
| 249 | } |
| 250 | |
| 251 | // Fallback: manual conversion from Zod v4 internal defs |
| 252 | if (s._zod?.def) { |
| 253 | return zodDefToJsonSchema(s._zod.def); |
| 254 | } |
| 255 | |
| 256 | // Last resort: empty object schema |
| 257 | return { type: "object" as const, properties: {} }; |
| 258 | } |
| 259 | |
| 260 | /** |
| 261 | * Convert a Zod v4 internal def to JSON Schema. |
no test coverage detected