Skip to content

Commit 91e427e

Browse files
committed
update zod to schema
1 parent 8f001bc commit 91e427e

File tree

3 files changed

+31
-119
lines changed

3 files changed

+31
-119
lines changed

packages/core/lib/v3/zodCompat.ts

Lines changed: 3 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type {
44
ZodRawShape as Zod4RawShape,
55
ZodTypeAny as Zod4TypeAny,
66
} from "zod";
7+
import zodToJsonSchema from "zod-to-json-schema";
78
import type * as z3 from "zod/v3";
89
export type StagehandZodSchema = Zod4TypeAny | z3.ZodTypeAny;
910

@@ -29,118 +30,12 @@ export const isZod3Schema = (
2930

3031
export type JsonSchemaDocument = Record<string, unknown>;
3132

32-
// Manual converter for zod/v3 schemas to JSON Schema
33-
function ZodToJsonSchema(schema: z3.ZodTypeAny): JsonSchemaDocument {
34-
const _def = (schema as unknown as { _def?: Record<string, unknown> })._def;
3533

36-
if (!_def) {
37-
return { type: "null" };
38-
}
39-
40-
const typeName = _def.typeName;
41-
42-
switch (typeName) {
43-
case "ZodObject": {
44-
const shape =
45-
typeof _def.shape === "function" ? _def.shape() : _def.shape;
46-
const properties: Record<string, JsonSchemaDocument> = {};
47-
const required: string[] = [];
48-
49-
for (const [key, value] of Object.entries(
50-
shape as Record<string, z3.ZodTypeAny>,
51-
)) {
52-
properties[key] = ZodToJsonSchema(value);
53-
// Check if field is not optional
54-
const valueDef = (value as unknown as { _def?: { typeName?: string } })
55-
._def;
56-
if (valueDef?.typeName !== "ZodOptional") {
57-
required.push(key);
58-
}
59-
}
60-
61-
return {
62-
type: "object",
63-
properties,
64-
required,
65-
additionalProperties: _def.unknownKeys === "passthrough",
66-
};
67-
}
68-
69-
case "ZodArray": {
70-
const itemType = _def.type as z3.ZodTypeAny;
71-
return {
72-
type: "array",
73-
items: ZodToJsonSchema(itemType),
74-
};
75-
}
76-
77-
case "ZodString": {
78-
const result: JsonSchemaDocument = { type: "string" };
79-
// Check for URL validation
80-
const checks = _def.checks as Array<{ kind?: string }> | undefined;
81-
if (checks) {
82-
for (const check of checks) {
83-
if (check.kind === "url") {
84-
result.format = "url";
85-
break;
86-
}
87-
}
88-
}
89-
return result;
90-
}
91-
92-
case "ZodNumber":
93-
return { type: "number" };
94-
95-
case "ZodBoolean":
96-
return { type: "boolean" };
97-
98-
case "ZodOptional":
99-
return ZodToJsonSchema(_def.innerType as z3.ZodTypeAny);
100-
101-
case "ZodNullable": {
102-
const innerSchema = ZodToJsonSchema(_def.innerType as z3.ZodTypeAny);
103-
return {
104-
...innerSchema,
105-
nullable: true,
106-
};
107-
}
108-
109-
case "ZodEnum":
110-
return {
111-
type: "string",
112-
enum: _def.values,
113-
};
114-
115-
case "ZodLiteral":
116-
return {
117-
type: typeof _def.value,
118-
const: _def.value,
119-
};
120-
121-
case "ZodUnion":
122-
return {
123-
anyOf: (_def.options as z3.ZodTypeAny[]).map((opt) =>
124-
ZodToJsonSchema(opt),
125-
),
126-
};
127-
128-
default:
129-
console.warn(`Unknown Zod type: ${typeName}`);
130-
return { type: "null" };
131-
}
132-
}
13334

13435
export function toJsonSchema(schema: StagehandZodSchema): JsonSchemaDocument {
135-
// For v3 schemas, use manual converter
136-
// Note: We can't use zod-to-json-schema for v3 schemas when zod v4 is installed
137-
// because the library imports 'zod' (v4) and tries to access ZodFirstPartyTypeKind which doesn't exist in v4
36+
13837
if (!isZod4Schema(schema)) {
139-
const result = {
140-
$schema: "http://json-schema.org/draft-07/schema#",
141-
...ZodToJsonSchema(schema),
142-
};
143-
return result;
38+
return zodToJsonSchema(schema);
14439
}
14540

14641
// For v4 schemas, use built-in z.toJSONSchema() method

packages/core/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@
5656
"pino": "^9.6.0",
5757
"pino-pretty": "^13.0.0",
5858
"playwright": "^1.52.0",
59-
"ws": "^8.18.0"
59+
"ws": "^8.18.0",
60+
"zod-to-json-schema": "^3.25.0"
6061
},
6162
"optionalDependencies": {
6263
"@ai-sdk/anthropic": "^2.0.34",

pnpm-lock.yaml

Lines changed: 26 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)