@mendable/firecrawl 4.11.2 → 4.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,7 +8,7 @@ var require_package = __commonJS({
8
8
  "package.json"(exports, module) {
9
9
  module.exports = {
10
10
  name: "@mendable/firecrawl-js",
11
- version: "4.11.2",
11
+ version: "4.11.3",
12
12
  description: "JavaScript SDK for Firecrawl API",
13
13
  main: "dist/index.js",
14
14
  types: "dist/index.d.ts",
package/dist/index.cjs CHANGED
@@ -35,7 +35,7 @@ var require_package = __commonJS({
35
35
  "package.json"(exports2, module2) {
36
36
  module2.exports = {
37
37
  name: "@mendable/firecrawl-js",
38
- version: "4.11.2",
38
+ version: "4.11.3",
39
39
  description: "JavaScript SDK for Firecrawl API",
40
40
  main: "dist/index.js",
41
41
  types: "dist/index.d.ts",
@@ -249,14 +249,54 @@ var JobTimeoutError = class extends SdkError {
249
249
  }
250
250
  };
251
251
 
252
- // src/v2/utils/validation.ts
252
+ // src/utils/zodSchemaToJson.ts
253
253
  var import_zod_to_json_schema = require("zod-to-json-schema");
254
+ function isZodSchema(value) {
255
+ if (!value || typeof value !== "object") return false;
256
+ const schema = value;
257
+ const hasV3Markers = "_def" in schema && (typeof schema.safeParse === "function" || typeof schema.parse === "function");
258
+ const hasV4Markers = "_zod" in schema && typeof schema._zod === "object";
259
+ return hasV3Markers || hasV4Markers;
260
+ }
261
+ function isZodV4Schema(schema) {
262
+ if (!schema || typeof schema !== "object") return false;
263
+ return "_zod" in schema && typeof schema._zod === "object";
264
+ }
265
+ function tryZodV4Conversion(schema) {
266
+ if (!isZodV4Schema(schema)) return null;
267
+ try {
268
+ const zodModule = schema.constructor?.prototype?.constructor;
269
+ if (zodModule && typeof zodModule.toJSONSchema === "function") {
270
+ return zodModule.toJSONSchema(schema);
271
+ }
272
+ } catch {
273
+ }
274
+ return null;
275
+ }
276
+ function zodSchemaToJsonSchema(schema) {
277
+ if (!isZodSchema(schema)) {
278
+ return schema;
279
+ }
280
+ const v4Result = tryZodV4Conversion(schema);
281
+ if (v4Result) {
282
+ return v4Result;
283
+ }
284
+ try {
285
+ return (0, import_zod_to_json_schema.zodToJsonSchema)(schema);
286
+ } catch {
287
+ return schema;
288
+ }
289
+ }
254
290
  function looksLikeZodShape(obj) {
255
291
  if (!obj || typeof obj !== "object" || Array.isArray(obj)) return false;
256
292
  const values = Object.values(obj);
257
293
  if (values.length === 0) return false;
258
- return values.some((v) => v && typeof v === "object" && v._def && typeof v.safeParse === "function");
294
+ return values.some(
295
+ (v) => v && typeof v === "object" && v._def && typeof v.safeParse === "function"
296
+ );
259
297
  }
298
+
299
+ // src/v2/utils/validation.ts
260
300
  function ensureValidFormats(formats) {
261
301
  if (!formats) return;
262
302
  for (const fmt of formats) {
@@ -272,12 +312,8 @@ function ensureValidFormats(formats) {
272
312
  throw new Error("json format requires either 'prompt' or 'schema' (or both)");
273
313
  }
274
314
  const maybeSchema = j.schema;
275
- const isZod = !!maybeSchema && (typeof maybeSchema.safeParse === "function" || typeof maybeSchema.parse === "function") && !!maybeSchema._def;
276
- if (isZod) {
277
- try {
278
- j.schema = (0, import_zod_to_json_schema.zodToJsonSchema)(maybeSchema);
279
- } catch {
280
- }
315
+ if (isZodSchema(maybeSchema)) {
316
+ j.schema = zodSchemaToJsonSchema(maybeSchema);
281
317
  } else if (looksLikeZodShape(maybeSchema)) {
282
318
  throw new Error(
283
319
  "json format schema appears to be a Zod schema's .shape property. Pass the Zod schema directly (e.g., `schema: MySchema`) instead of `schema: MySchema.shape`. The SDK will automatically convert Zod schemas to JSON Schema format."
@@ -288,12 +324,8 @@ function ensureValidFormats(formats) {
288
324
  if (fmt.type === "changeTracking") {
289
325
  const ct = fmt;
290
326
  const maybeSchema = ct.schema;
291
- const isZod = !!maybeSchema && (typeof maybeSchema.safeParse === "function" || typeof maybeSchema.parse === "function") && !!maybeSchema._def;
292
- if (isZod) {
293
- try {
294
- ct.schema = (0, import_zod_to_json_schema.zodToJsonSchema)(maybeSchema);
295
- } catch {
296
- }
327
+ if (isZodSchema(maybeSchema)) {
328
+ ct.schema = zodSchemaToJsonSchema(maybeSchema);
297
329
  } else if (looksLikeZodShape(maybeSchema)) {
298
330
  throw new Error(
299
331
  "changeTracking format schema appears to be a Zod schema's .shape property. Pass the Zod schema directly (e.g., `schema: MySchema`) instead of `schema: MySchema.shape`. The SDK will automatically convert Zod schemas to JSON Schema format."
@@ -780,15 +812,12 @@ async function batchScrape(http, urls, opts = {}) {
780
812
  }
781
813
 
782
814
  // src/v2/methods/extract.ts
783
- var import_zod_to_json_schema2 = require("zod-to-json-schema");
784
815
  function prepareExtractPayload(args) {
785
816
  const body = {};
786
817
  if (args.urls) body.urls = args.urls;
787
818
  if (args.prompt != null) body.prompt = args.prompt;
788
819
  if (args.schema != null) {
789
- const s = args.schema;
790
- const isZod = s && (typeof s.safeParse === "function" || typeof s.parse === "function") && s._def;
791
- body.schema = isZod ? (0, import_zod_to_json_schema2.zodToJsonSchema)(s) : args.schema;
820
+ body.schema = isZodSchema(args.schema) ? zodSchemaToJsonSchema(args.schema) : args.schema;
792
821
  }
793
822
  if (args.systemPrompt != null) body.systemPrompt = args.systemPrompt;
794
823
  if (args.allowExternalLinks != null) body.allowExternalLinks = args.allowExternalLinks;
@@ -841,15 +870,12 @@ async function extract(http, args) {
841
870
  }
842
871
 
843
872
  // src/v2/methods/agent.ts
844
- var import_zod_to_json_schema3 = require("zod-to-json-schema");
845
873
  function prepareAgentPayload(args) {
846
874
  const body = {};
847
875
  if (args.urls) body.urls = args.urls;
848
876
  body.prompt = args.prompt;
849
877
  if (args.schema != null) {
850
- const s = args.schema;
851
- const isZod = s && (typeof s.safeParse === "function" || typeof s.parse === "function") && s._def;
852
- body.schema = isZod ? (0, import_zod_to_json_schema3.zodToJsonSchema)(s) : args.schema;
878
+ body.schema = isZodSchema(args.schema) ? zodSchemaToJsonSchema(args.schema) : args.schema;
853
879
  }
854
880
  if (args.integration && args.integration.trim()) body.integration = args.integration.trim();
855
881
  if (args.maxCredits !== null && args.maxCredits !== void 0) body.maxCredits = args.maxCredits;
@@ -1437,7 +1463,6 @@ var FirecrawlClient = class {
1437
1463
  // src/v1/index.ts
1438
1464
  var import_axios3 = __toESM(require("axios"), 1);
1439
1465
  var zt2 = require("zod");
1440
- var import_zod_to_json_schema4 = require("zod-to-json-schema");
1441
1466
 
1442
1467
  // node_modules/.pnpm/typescript-event-target@1.1.1/node_modules/typescript-event-target/dist/index.mjs
1443
1468
  var e = class extends EventTarget {
@@ -1507,30 +1532,20 @@ var FirecrawlApp = class {
1507
1532
  };
1508
1533
  let jsonData = { url, ...params, origin: typeof params.origin === "string" && params.origin.includes("mcp") ? params.origin : `js-sdk@${this.version}` };
1509
1534
  if (jsonData?.extract?.schema) {
1510
- let schema = jsonData.extract.schema;
1511
- try {
1512
- schema = (0, import_zod_to_json_schema4.zodToJsonSchema)(schema);
1513
- } catch (error) {
1514
- }
1515
1535
  jsonData = {
1516
1536
  ...jsonData,
1517
1537
  extract: {
1518
1538
  ...jsonData.extract,
1519
- schema
1539
+ schema: zodSchemaToJsonSchema(jsonData.extract.schema)
1520
1540
  }
1521
1541
  };
1522
1542
  }
1523
1543
  if (jsonData?.jsonOptions?.schema) {
1524
- let schema = jsonData.jsonOptions.schema;
1525
- try {
1526
- schema = (0, import_zod_to_json_schema4.zodToJsonSchema)(schema);
1527
- } catch (error) {
1528
- }
1529
1544
  jsonData = {
1530
1545
  ...jsonData,
1531
1546
  jsonOptions: {
1532
1547
  ...jsonData.jsonOptions,
1533
- schema
1548
+ schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema)
1534
1549
  }
1535
1550
  };
1536
1551
  }
@@ -1584,18 +1599,13 @@ var FirecrawlApp = class {
1584
1599
  scrapeOptions: params?.scrapeOptions ?? { formats: [] }
1585
1600
  };
1586
1601
  if (jsonData?.scrapeOptions?.extract?.schema) {
1587
- let schema = jsonData.scrapeOptions.extract.schema;
1588
- try {
1589
- schema = (0, import_zod_to_json_schema4.zodToJsonSchema)(schema);
1590
- } catch (error) {
1591
- }
1592
1602
  jsonData = {
1593
1603
  ...jsonData,
1594
1604
  scrapeOptions: {
1595
1605
  ...jsonData.scrapeOptions,
1596
1606
  extract: {
1597
1607
  ...jsonData.scrapeOptions.extract,
1598
- schema
1608
+ schema: zodSchemaToJsonSchema(jsonData.scrapeOptions.extract.schema)
1599
1609
  }
1600
1610
  }
1601
1611
  };
@@ -1853,30 +1863,20 @@ var FirecrawlApp = class {
1853
1863
  const headers = this.prepareHeaders(idempotencyKey);
1854
1864
  let jsonData = { urls, webhook, ignoreInvalidURLs, maxConcurrency, ...params, origin: typeof params.origin === "string" && params.origin.includes("mcp") ? params.origin : `js-sdk@${this.version}` };
1855
1865
  if (jsonData?.extract?.schema) {
1856
- let schema = jsonData.extract.schema;
1857
- try {
1858
- schema = (0, import_zod_to_json_schema4.zodToJsonSchema)(schema);
1859
- } catch (error) {
1860
- }
1861
1866
  jsonData = {
1862
1867
  ...jsonData,
1863
1868
  extract: {
1864
1869
  ...jsonData.extract,
1865
- schema
1870
+ schema: zodSchemaToJsonSchema(jsonData.extract.schema)
1866
1871
  }
1867
1872
  };
1868
1873
  }
1869
1874
  if (jsonData?.jsonOptions?.schema) {
1870
- let schema = jsonData.jsonOptions.schema;
1871
- try {
1872
- schema = (0, import_zod_to_json_schema4.zodToJsonSchema)(schema);
1873
- } catch (error) {
1874
- }
1875
1875
  jsonData = {
1876
1876
  ...jsonData,
1877
1877
  jsonOptions: {
1878
1878
  ...jsonData.jsonOptions,
1879
- schema
1879
+ schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema)
1880
1880
  }
1881
1881
  };
1882
1882
  }
@@ -2042,20 +2042,7 @@ var FirecrawlApp = class {
2042
2042
  async extract(urls, params) {
2043
2043
  const headers = this.prepareHeaders();
2044
2044
  let jsonData = { urls, ...params };
2045
- let jsonSchema;
2046
- try {
2047
- if (!params?.schema) {
2048
- jsonSchema = void 0;
2049
- } else {
2050
- try {
2051
- jsonSchema = (0, import_zod_to_json_schema4.zodToJsonSchema)(params.schema);
2052
- } catch (_) {
2053
- jsonSchema = params.schema;
2054
- }
2055
- }
2056
- } catch (error) {
2057
- throw new FirecrawlError("Invalid schema. Schema must be either a valid Zod schema or JSON schema object.", 400);
2058
- }
2045
+ const jsonSchema = params?.schema ? zodSchemaToJsonSchema(params.schema) : void 0;
2059
2046
  try {
2060
2047
  const response = await this.postRequest(
2061
2048
  this.apiUrl + `/v1/extract`,
@@ -2105,21 +2092,8 @@ var FirecrawlApp = class {
2105
2092
  */
2106
2093
  async asyncExtract(urls, params, idempotencyKey) {
2107
2094
  const headers = this.prepareHeaders(idempotencyKey);
2108
- let jsonData = { urls, ...params };
2109
- let jsonSchema;
2110
- try {
2111
- if (!params?.schema) {
2112
- jsonSchema = void 0;
2113
- } else {
2114
- try {
2115
- jsonSchema = (0, import_zod_to_json_schema4.zodToJsonSchema)(params.schema);
2116
- } catch (_) {
2117
- jsonSchema = params.schema;
2118
- }
2119
- }
2120
- } catch (error) {
2121
- throw new FirecrawlError("Invalid schema. Schema must be either a valid Zod schema or JSON schema object.", 400);
2122
- }
2095
+ const jsonData = { urls, ...params };
2096
+ const jsonSchema = params?.schema ? zodSchemaToJsonSchema(params.schema) : void 0;
2123
2097
  try {
2124
2098
  const response = await this.postRequest(
2125
2099
  this.apiUrl + `/v1/extract`,
@@ -2401,16 +2375,11 @@ var FirecrawlApp = class {
2401
2375
  const headers = this.prepareHeaders();
2402
2376
  let jsonData = { query, ...params, origin: typeof params.origin === "string" && params.origin.includes("mcp") ? params.origin : `js-sdk@${this.version}` };
2403
2377
  if (jsonData?.jsonOptions?.schema) {
2404
- let schema = jsonData.jsonOptions.schema;
2405
- try {
2406
- schema = (0, import_zod_to_json_schema4.zodToJsonSchema)(schema);
2407
- } catch (error) {
2408
- }
2409
2378
  jsonData = {
2410
2379
  ...jsonData,
2411
2380
  jsonOptions: {
2412
2381
  ...jsonData.jsonOptions,
2413
- schema
2382
+ schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema)
2414
2383
  }
2415
2384
  };
2416
2385
  }
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  require_package
3
- } from "./chunk-GVCNL5KA.js";
3
+ } from "./chunk-TLAC3APA.js";
4
4
 
5
5
  // src/v2/utils/httpClient.ts
6
6
  import axios from "axios";
@@ -130,14 +130,54 @@ var JobTimeoutError = class extends SdkError {
130
130
  }
131
131
  };
132
132
 
133
- // src/v2/utils/validation.ts
134
- import { zodToJsonSchema } from "zod-to-json-schema";
133
+ // src/utils/zodSchemaToJson.ts
134
+ import { zodToJsonSchema as zodToJsonSchemaLib } from "zod-to-json-schema";
135
+ function isZodSchema(value) {
136
+ if (!value || typeof value !== "object") return false;
137
+ const schema = value;
138
+ const hasV3Markers = "_def" in schema && (typeof schema.safeParse === "function" || typeof schema.parse === "function");
139
+ const hasV4Markers = "_zod" in schema && typeof schema._zod === "object";
140
+ return hasV3Markers || hasV4Markers;
141
+ }
142
+ function isZodV4Schema(schema) {
143
+ if (!schema || typeof schema !== "object") return false;
144
+ return "_zod" in schema && typeof schema._zod === "object";
145
+ }
146
+ function tryZodV4Conversion(schema) {
147
+ if (!isZodV4Schema(schema)) return null;
148
+ try {
149
+ const zodModule = schema.constructor?.prototype?.constructor;
150
+ if (zodModule && typeof zodModule.toJSONSchema === "function") {
151
+ return zodModule.toJSONSchema(schema);
152
+ }
153
+ } catch {
154
+ }
155
+ return null;
156
+ }
157
+ function zodSchemaToJsonSchema(schema) {
158
+ if (!isZodSchema(schema)) {
159
+ return schema;
160
+ }
161
+ const v4Result = tryZodV4Conversion(schema);
162
+ if (v4Result) {
163
+ return v4Result;
164
+ }
165
+ try {
166
+ return zodToJsonSchemaLib(schema);
167
+ } catch {
168
+ return schema;
169
+ }
170
+ }
135
171
  function looksLikeZodShape(obj) {
136
172
  if (!obj || typeof obj !== "object" || Array.isArray(obj)) return false;
137
173
  const values = Object.values(obj);
138
174
  if (values.length === 0) return false;
139
- return values.some((v) => v && typeof v === "object" && v._def && typeof v.safeParse === "function");
175
+ return values.some(
176
+ (v) => v && typeof v === "object" && v._def && typeof v.safeParse === "function"
177
+ );
140
178
  }
179
+
180
+ // src/v2/utils/validation.ts
141
181
  function ensureValidFormats(formats) {
142
182
  if (!formats) return;
143
183
  for (const fmt of formats) {
@@ -153,12 +193,8 @@ function ensureValidFormats(formats) {
153
193
  throw new Error("json format requires either 'prompt' or 'schema' (or both)");
154
194
  }
155
195
  const maybeSchema = j.schema;
156
- const isZod = !!maybeSchema && (typeof maybeSchema.safeParse === "function" || typeof maybeSchema.parse === "function") && !!maybeSchema._def;
157
- if (isZod) {
158
- try {
159
- j.schema = zodToJsonSchema(maybeSchema);
160
- } catch {
161
- }
196
+ if (isZodSchema(maybeSchema)) {
197
+ j.schema = zodSchemaToJsonSchema(maybeSchema);
162
198
  } else if (looksLikeZodShape(maybeSchema)) {
163
199
  throw new Error(
164
200
  "json format schema appears to be a Zod schema's .shape property. Pass the Zod schema directly (e.g., `schema: MySchema`) instead of `schema: MySchema.shape`. The SDK will automatically convert Zod schemas to JSON Schema format."
@@ -169,12 +205,8 @@ function ensureValidFormats(formats) {
169
205
  if (fmt.type === "changeTracking") {
170
206
  const ct = fmt;
171
207
  const maybeSchema = ct.schema;
172
- const isZod = !!maybeSchema && (typeof maybeSchema.safeParse === "function" || typeof maybeSchema.parse === "function") && !!maybeSchema._def;
173
- if (isZod) {
174
- try {
175
- ct.schema = zodToJsonSchema(maybeSchema);
176
- } catch {
177
- }
208
+ if (isZodSchema(maybeSchema)) {
209
+ ct.schema = zodSchemaToJsonSchema(maybeSchema);
178
210
  } else if (looksLikeZodShape(maybeSchema)) {
179
211
  throw new Error(
180
212
  "changeTracking format schema appears to be a Zod schema's .shape property. Pass the Zod schema directly (e.g., `schema: MySchema`) instead of `schema: MySchema.shape`. The SDK will automatically convert Zod schemas to JSON Schema format."
@@ -661,15 +693,12 @@ async function batchScrape(http, urls, opts = {}) {
661
693
  }
662
694
 
663
695
  // src/v2/methods/extract.ts
664
- import { zodToJsonSchema as zodToJsonSchema2 } from "zod-to-json-schema";
665
696
  function prepareExtractPayload(args) {
666
697
  const body = {};
667
698
  if (args.urls) body.urls = args.urls;
668
699
  if (args.prompt != null) body.prompt = args.prompt;
669
700
  if (args.schema != null) {
670
- const s = args.schema;
671
- const isZod = s && (typeof s.safeParse === "function" || typeof s.parse === "function") && s._def;
672
- body.schema = isZod ? zodToJsonSchema2(s) : args.schema;
701
+ body.schema = isZodSchema(args.schema) ? zodSchemaToJsonSchema(args.schema) : args.schema;
673
702
  }
674
703
  if (args.systemPrompt != null) body.systemPrompt = args.systemPrompt;
675
704
  if (args.allowExternalLinks != null) body.allowExternalLinks = args.allowExternalLinks;
@@ -722,15 +751,12 @@ async function extract(http, args) {
722
751
  }
723
752
 
724
753
  // src/v2/methods/agent.ts
725
- import { zodToJsonSchema as zodToJsonSchema3 } from "zod-to-json-schema";
726
754
  function prepareAgentPayload(args) {
727
755
  const body = {};
728
756
  if (args.urls) body.urls = args.urls;
729
757
  body.prompt = args.prompt;
730
758
  if (args.schema != null) {
731
- const s = args.schema;
732
- const isZod = s && (typeof s.safeParse === "function" || typeof s.parse === "function") && s._def;
733
- body.schema = isZod ? zodToJsonSchema3(s) : args.schema;
759
+ body.schema = isZodSchema(args.schema) ? zodSchemaToJsonSchema(args.schema) : args.schema;
734
760
  }
735
761
  if (args.integration && args.integration.trim()) body.integration = args.integration.trim();
736
762
  if (args.maxCredits !== null && args.maxCredits !== void 0) body.maxCredits = args.maxCredits;
@@ -1318,7 +1344,6 @@ var FirecrawlClient = class {
1318
1344
  // src/v1/index.ts
1319
1345
  import axios2, { AxiosError } from "axios";
1320
1346
  import "zod";
1321
- import { zodToJsonSchema as zodToJsonSchema4 } from "zod-to-json-schema";
1322
1347
 
1323
1348
  // node_modules/.pnpm/typescript-event-target@1.1.1/node_modules/typescript-event-target/dist/index.mjs
1324
1349
  var e = class extends EventTarget {
@@ -1349,7 +1374,7 @@ var FirecrawlApp = class {
1349
1374
  if (typeof process !== "undefined" && process.env && process.env.npm_package_version) {
1350
1375
  return process.env.npm_package_version;
1351
1376
  }
1352
- const packageJson = await import("./package-LU5XQZAL.js");
1377
+ const packageJson = await import("./package-3BZQ6TAW.js");
1353
1378
  return packageJson.default.version;
1354
1379
  } catch (error) {
1355
1380
  const isTest = typeof process !== "undefined" && (process.env.JEST_WORKER_ID != null || false);
@@ -1388,30 +1413,20 @@ var FirecrawlApp = class {
1388
1413
  };
1389
1414
  let jsonData = { url, ...params, origin: typeof params.origin === "string" && params.origin.includes("mcp") ? params.origin : `js-sdk@${this.version}` };
1390
1415
  if (jsonData?.extract?.schema) {
1391
- let schema = jsonData.extract.schema;
1392
- try {
1393
- schema = zodToJsonSchema4(schema);
1394
- } catch (error) {
1395
- }
1396
1416
  jsonData = {
1397
1417
  ...jsonData,
1398
1418
  extract: {
1399
1419
  ...jsonData.extract,
1400
- schema
1420
+ schema: zodSchemaToJsonSchema(jsonData.extract.schema)
1401
1421
  }
1402
1422
  };
1403
1423
  }
1404
1424
  if (jsonData?.jsonOptions?.schema) {
1405
- let schema = jsonData.jsonOptions.schema;
1406
- try {
1407
- schema = zodToJsonSchema4(schema);
1408
- } catch (error) {
1409
- }
1410
1425
  jsonData = {
1411
1426
  ...jsonData,
1412
1427
  jsonOptions: {
1413
1428
  ...jsonData.jsonOptions,
1414
- schema
1429
+ schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema)
1415
1430
  }
1416
1431
  };
1417
1432
  }
@@ -1465,18 +1480,13 @@ var FirecrawlApp = class {
1465
1480
  scrapeOptions: params?.scrapeOptions ?? { formats: [] }
1466
1481
  };
1467
1482
  if (jsonData?.scrapeOptions?.extract?.schema) {
1468
- let schema = jsonData.scrapeOptions.extract.schema;
1469
- try {
1470
- schema = zodToJsonSchema4(schema);
1471
- } catch (error) {
1472
- }
1473
1483
  jsonData = {
1474
1484
  ...jsonData,
1475
1485
  scrapeOptions: {
1476
1486
  ...jsonData.scrapeOptions,
1477
1487
  extract: {
1478
1488
  ...jsonData.scrapeOptions.extract,
1479
- schema
1489
+ schema: zodSchemaToJsonSchema(jsonData.scrapeOptions.extract.schema)
1480
1490
  }
1481
1491
  }
1482
1492
  };
@@ -1734,30 +1744,20 @@ var FirecrawlApp = class {
1734
1744
  const headers = this.prepareHeaders(idempotencyKey);
1735
1745
  let jsonData = { urls, webhook, ignoreInvalidURLs, maxConcurrency, ...params, origin: typeof params.origin === "string" && params.origin.includes("mcp") ? params.origin : `js-sdk@${this.version}` };
1736
1746
  if (jsonData?.extract?.schema) {
1737
- let schema = jsonData.extract.schema;
1738
- try {
1739
- schema = zodToJsonSchema4(schema);
1740
- } catch (error) {
1741
- }
1742
1747
  jsonData = {
1743
1748
  ...jsonData,
1744
1749
  extract: {
1745
1750
  ...jsonData.extract,
1746
- schema
1751
+ schema: zodSchemaToJsonSchema(jsonData.extract.schema)
1747
1752
  }
1748
1753
  };
1749
1754
  }
1750
1755
  if (jsonData?.jsonOptions?.schema) {
1751
- let schema = jsonData.jsonOptions.schema;
1752
- try {
1753
- schema = zodToJsonSchema4(schema);
1754
- } catch (error) {
1755
- }
1756
1756
  jsonData = {
1757
1757
  ...jsonData,
1758
1758
  jsonOptions: {
1759
1759
  ...jsonData.jsonOptions,
1760
- schema
1760
+ schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema)
1761
1761
  }
1762
1762
  };
1763
1763
  }
@@ -1923,20 +1923,7 @@ var FirecrawlApp = class {
1923
1923
  async extract(urls, params) {
1924
1924
  const headers = this.prepareHeaders();
1925
1925
  let jsonData = { urls, ...params };
1926
- let jsonSchema;
1927
- try {
1928
- if (!params?.schema) {
1929
- jsonSchema = void 0;
1930
- } else {
1931
- try {
1932
- jsonSchema = zodToJsonSchema4(params.schema);
1933
- } catch (_) {
1934
- jsonSchema = params.schema;
1935
- }
1936
- }
1937
- } catch (error) {
1938
- throw new FirecrawlError("Invalid schema. Schema must be either a valid Zod schema or JSON schema object.", 400);
1939
- }
1926
+ const jsonSchema = params?.schema ? zodSchemaToJsonSchema(params.schema) : void 0;
1940
1927
  try {
1941
1928
  const response = await this.postRequest(
1942
1929
  this.apiUrl + `/v1/extract`,
@@ -1986,21 +1973,8 @@ var FirecrawlApp = class {
1986
1973
  */
1987
1974
  async asyncExtract(urls, params, idempotencyKey) {
1988
1975
  const headers = this.prepareHeaders(idempotencyKey);
1989
- let jsonData = { urls, ...params };
1990
- let jsonSchema;
1991
- try {
1992
- if (!params?.schema) {
1993
- jsonSchema = void 0;
1994
- } else {
1995
- try {
1996
- jsonSchema = zodToJsonSchema4(params.schema);
1997
- } catch (_) {
1998
- jsonSchema = params.schema;
1999
- }
2000
- }
2001
- } catch (error) {
2002
- throw new FirecrawlError("Invalid schema. Schema must be either a valid Zod schema or JSON schema object.", 400);
2003
- }
1976
+ const jsonData = { urls, ...params };
1977
+ const jsonSchema = params?.schema ? zodSchemaToJsonSchema(params.schema) : void 0;
2004
1978
  try {
2005
1979
  const response = await this.postRequest(
2006
1980
  this.apiUrl + `/v1/extract`,
@@ -2282,16 +2256,11 @@ var FirecrawlApp = class {
2282
2256
  const headers = this.prepareHeaders();
2283
2257
  let jsonData = { query, ...params, origin: typeof params.origin === "string" && params.origin.includes("mcp") ? params.origin : `js-sdk@${this.version}` };
2284
2258
  if (jsonData?.jsonOptions?.schema) {
2285
- let schema = jsonData.jsonOptions.schema;
2286
- try {
2287
- schema = zodToJsonSchema4(schema);
2288
- } catch (error) {
2289
- }
2290
2259
  jsonData = {
2291
2260
  ...jsonData,
2292
2261
  jsonOptions: {
2293
2262
  ...jsonData.jsonOptions,
2294
- schema
2263
+ schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema)
2295
2264
  }
2296
2265
  };
2297
2266
  }
@@ -1,4 +1,4 @@
1
1
  import {
2
2
  require_package
3
- } from "./chunk-GVCNL5KA.js";
3
+ } from "./chunk-TLAC3APA.js";
4
4
  export default require_package();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mendable/firecrawl",
3
- "version": "4.11.2",
3
+ "version": "4.11.3",
4
4
  "description": "JavaScript SDK for Firecrawl API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -0,0 +1,107 @@
1
+ import { describe, test, expect } from "@jest/globals";
2
+ import { z } from "zod";
3
+ import {
4
+ isZodSchema,
5
+ zodSchemaToJsonSchema,
6
+ looksLikeZodShape,
7
+ } from "../../../utils/zodSchemaToJson";
8
+
9
+ describe("zodSchemaToJson utility", () => {
10
+ test("isZodSchema detects Zod schemas and rejects non-Zod values", () => {
11
+ expect(isZodSchema(z.object({ name: z.string() }))).toBe(true);
12
+ expect(isZodSchema(z.string())).toBe(true);
13
+ expect(isZodSchema(z.number())).toBe(true);
14
+ expect(isZodSchema(z.array(z.string()))).toBe(true);
15
+ expect(isZodSchema(z.enum(["A", "B"]))).toBe(true);
16
+ expect(isZodSchema(z.union([z.string(), z.number()]))).toBe(true);
17
+ expect(isZodSchema(z.string().optional())).toBe(true);
18
+ expect(isZodSchema(z.string().nullable())).toBe(true);
19
+
20
+ expect(isZodSchema(null)).toBe(false);
21
+ expect(isZodSchema(undefined)).toBe(false);
22
+ expect(isZodSchema({ name: "test" })).toBe(false);
23
+ expect(isZodSchema({ type: "object", properties: {} })).toBe(false);
24
+ expect(isZodSchema("string")).toBe(false);
25
+ expect(isZodSchema(42)).toBe(false);
26
+ expect(isZodSchema([1, 2, 3])).toBe(false);
27
+ });
28
+
29
+ test("zodSchemaToJsonSchema converts Zod schemas to JSON Schema", () => {
30
+ const simpleSchema = z.object({ name: z.string() });
31
+ const simpleResult = zodSchemaToJsonSchema(simpleSchema) as Record<string, unknown>;
32
+ expect(simpleResult.type).toBe("object");
33
+ expect(simpleResult.properties).toBeDefined();
34
+ expect((simpleResult.properties as Record<string, unknown>).name).toBeDefined();
35
+
36
+ const complexSchema = z.object({
37
+ id: z.string().uuid(),
38
+ name: z.string().min(1).max(100),
39
+ age: z.number().min(0).max(150).optional(),
40
+ tags: z.array(z.string()),
41
+ status: z.enum(["active", "inactive"]),
42
+ metadata: z.object({
43
+ createdAt: z.string(),
44
+ nested: z.object({ value: z.number() }),
45
+ }),
46
+ });
47
+ const complexResult = zodSchemaToJsonSchema(complexSchema) as Record<string, unknown>;
48
+ expect(complexResult.type).toBe("object");
49
+ expect(complexResult.properties).toBeDefined();
50
+ expect(complexResult.required).toContain("id");
51
+ expect(complexResult.required).not.toContain("age");
52
+
53
+ const enumResult = zodSchemaToJsonSchema(z.enum(["a", "b", "c"])) as Record<string, unknown>;
54
+ expect(enumResult.enum).toEqual(["a", "b", "c"]);
55
+
56
+ const arrayResult = zodSchemaToJsonSchema(z.array(z.number())) as Record<string, unknown>;
57
+ expect(arrayResult.type).toBe("array");
58
+ expect(arrayResult.items).toBeDefined();
59
+ });
60
+
61
+ test("zodSchemaToJsonSchema passes through non-Zod values unchanged", () => {
62
+ const jsonSchema = { type: "object", properties: { name: { type: "string" } } };
63
+ expect(zodSchemaToJsonSchema(jsonSchema)).toEqual(jsonSchema);
64
+ expect(zodSchemaToJsonSchema(null)).toBe(null);
65
+ expect(zodSchemaToJsonSchema(undefined)).toBe(undefined);
66
+ expect(zodSchemaToJsonSchema("string")).toBe("string");
67
+ expect(zodSchemaToJsonSchema(42)).toBe(42);
68
+ expect(zodSchemaToJsonSchema({ foo: "bar" })).toEqual({ foo: "bar" });
69
+ });
70
+
71
+ test("looksLikeZodShape detects .shape property misuse", () => {
72
+ const schema = z.object({ title: z.string(), count: z.number() });
73
+ expect(looksLikeZodShape(schema.shape)).toBe(true);
74
+ expect(looksLikeZodShape(schema)).toBe(false);
75
+ expect(looksLikeZodShape(null)).toBe(false);
76
+ expect(looksLikeZodShape(undefined)).toBe(false);
77
+ expect(looksLikeZodShape({ name: "test" })).toBe(false);
78
+ expect(looksLikeZodShape({})).toBe(false);
79
+ expect(looksLikeZodShape([1, 2, 3])).toBe(false);
80
+ expect(looksLikeZodShape({ type: "object", properties: {} })).toBe(false);
81
+ });
82
+
83
+ test("SDK-like usage: convert Zod schema or pass through JSON schema", () => {
84
+ const zodSchema = z.object({
85
+ name: z.string(),
86
+ email: z.string().email(),
87
+ age: z.number().min(0),
88
+ });
89
+
90
+ if (isZodSchema(zodSchema)) {
91
+ const result = zodSchemaToJsonSchema(zodSchema) as Record<string, unknown>;
92
+ expect(result.type).toBe("object");
93
+ expect(result.properties).toBeDefined();
94
+ } else {
95
+ throw new Error("Should detect Zod schema");
96
+ }
97
+
98
+ const existingJsonSchema = {
99
+ type: "object" as const,
100
+ properties: { title: { type: "string" as const } },
101
+ required: ["title"] as string[],
102
+ };
103
+
104
+ expect(isZodSchema(existingJsonSchema)).toBe(false);
105
+ expect(zodSchemaToJsonSchema(existingJsonSchema)).toEqual(existingJsonSchema);
106
+ });
107
+ });
@@ -0,0 +1,67 @@
1
+ import { zodToJsonSchema as zodToJsonSchemaLib } from "zod-to-json-schema";
2
+
3
+ type SchemaConverter = (schema: unknown) => unknown;
4
+
5
+ export function isZodSchema(value: unknown): boolean {
6
+ if (!value || typeof value !== "object") return false;
7
+ const schema = value as Record<string, unknown>;
8
+
9
+ const hasV3Markers =
10
+ "_def" in schema &&
11
+ (typeof schema.safeParse === "function" ||
12
+ typeof schema.parse === "function");
13
+
14
+ const hasV4Markers = "_zod" in schema && typeof schema._zod === "object";
15
+
16
+ return hasV3Markers || hasV4Markers;
17
+ }
18
+
19
+ function isZodV4Schema(schema: unknown): boolean {
20
+ if (!schema || typeof schema !== "object") return false;
21
+ return "_zod" in schema && typeof (schema as Record<string, unknown>)._zod === "object";
22
+ }
23
+
24
+ function tryZodV4Conversion(schema: unknown): Record<string, unknown> | null {
25
+ if (!isZodV4Schema(schema)) return null;
26
+
27
+ try {
28
+ const zodModule = (schema as Record<string, unknown>).constructor?.prototype?.constructor;
29
+ if (zodModule && typeof (zodModule as Record<string, unknown>).toJSONSchema === "function") {
30
+ return (zodModule as { toJSONSchema: SchemaConverter }).toJSONSchema(schema) as Record<string, unknown>;
31
+ }
32
+ } catch {
33
+ // V4 conversion not available
34
+ }
35
+
36
+ return null;
37
+ }
38
+
39
+ export function zodSchemaToJsonSchema(schema: unknown): Record<string, unknown> | unknown {
40
+ if (!isZodSchema(schema)) {
41
+ return schema;
42
+ }
43
+
44
+ const v4Result = tryZodV4Conversion(schema);
45
+ if (v4Result) {
46
+ return v4Result;
47
+ }
48
+
49
+ try {
50
+ return zodToJsonSchemaLib(schema as Parameters<typeof zodToJsonSchemaLib>[0]) as Record<string, unknown>;
51
+ } catch {
52
+ return schema;
53
+ }
54
+ }
55
+
56
+ export function looksLikeZodShape(obj: unknown): boolean {
57
+ if (!obj || typeof obj !== "object" || Array.isArray(obj)) return false;
58
+ const values = Object.values(obj);
59
+ if (values.length === 0) return false;
60
+ return values.some(
61
+ (v) =>
62
+ v &&
63
+ typeof v === "object" &&
64
+ (v as Record<string, unknown>)._def &&
65
+ typeof (v as Record<string, unknown>).safeParse === "function"
66
+ );
67
+ }
package/src/v1/index.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import axios, { type AxiosResponse, type AxiosRequestHeaders, AxiosError } from "axios";
2
2
  import * as zt from "zod";
3
- import { zodToJsonSchema } from "zod-to-json-schema";
3
+ import { zodSchemaToJsonSchema } from "../utils/zodSchemaToJson";
4
4
  import { TypedEventTarget } from "typescript-event-target";
5
5
 
6
6
  /**
@@ -707,36 +707,21 @@ export default class FirecrawlApp {
707
707
  } as AxiosRequestHeaders;
708
708
  let jsonData: any = { url, ...params, origin: typeof (params as any).origin === "string" && (params as any).origin.includes("mcp") ? (params as any).origin : `js-sdk@${this.version}` };
709
709
  if (jsonData?.extract?.schema) {
710
- let schema = jsonData.extract.schema;
711
-
712
- // Try parsing the schema as a Zod schema
713
- try {
714
- schema = zodToJsonSchema(schema);
715
- } catch (error) {
716
-
717
- }
718
710
  jsonData = {
719
711
  ...jsonData,
720
712
  extract: {
721
713
  ...jsonData.extract,
722
- schema: schema,
714
+ schema: zodSchemaToJsonSchema(jsonData.extract.schema),
723
715
  },
724
716
  };
725
717
  }
726
718
 
727
719
  if (jsonData?.jsonOptions?.schema) {
728
- let schema = jsonData.jsonOptions.schema;
729
- // Try parsing the schema as a Zod schema
730
- try {
731
- schema = zodToJsonSchema(schema);
732
- } catch (error) {
733
-
734
- }
735
720
  jsonData = {
736
721
  ...jsonData,
737
722
  jsonOptions: {
738
723
  ...jsonData.jsonOptions,
739
- schema: schema,
724
+ schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema),
740
725
  },
741
726
  };
742
727
  }
@@ -793,21 +778,13 @@ export default class FirecrawlApp {
793
778
  };
794
779
 
795
780
  if (jsonData?.scrapeOptions?.extract?.schema) {
796
- let schema = jsonData.scrapeOptions.extract.schema;
797
-
798
- // Try parsing the schema as a Zod schema
799
- try {
800
- schema = zodToJsonSchema(schema);
801
- } catch (error) {
802
-
803
- }
804
781
  jsonData = {
805
782
  ...jsonData,
806
783
  scrapeOptions: {
807
784
  ...jsonData.scrapeOptions,
808
785
  extract: {
809
786
  ...jsonData.scrapeOptions.extract,
810
- schema: schema,
787
+ schema: zodSchemaToJsonSchema(jsonData.scrapeOptions.extract.schema),
811
788
  },
812
789
  },
813
790
  };
@@ -1105,36 +1082,20 @@ export default class FirecrawlApp {
1105
1082
  const headers = this.prepareHeaders(idempotencyKey);
1106
1083
  let jsonData: any = { urls, webhook, ignoreInvalidURLs, maxConcurrency, ...params, origin: typeof (params as any).origin === "string" && (params as any).origin.includes("mcp") ? (params as any).origin : `js-sdk@${this.version}` };
1107
1084
  if (jsonData?.extract?.schema) {
1108
- let schema = jsonData.extract.schema;
1109
-
1110
- // Try parsing the schema as a Zod schema
1111
- try {
1112
- schema = zodToJsonSchema(schema);
1113
- } catch (error) {
1114
-
1115
- }
1116
1085
  jsonData = {
1117
1086
  ...jsonData,
1118
1087
  extract: {
1119
1088
  ...jsonData.extract,
1120
- schema: schema,
1089
+ schema: zodSchemaToJsonSchema(jsonData.extract.schema),
1121
1090
  },
1122
1091
  };
1123
1092
  }
1124
1093
  if (jsonData?.jsonOptions?.schema) {
1125
- let schema = jsonData.jsonOptions.schema;
1126
-
1127
- // Try parsing the schema as a Zod schema
1128
- try {
1129
- schema = zodToJsonSchema(schema);
1130
- } catch (error) {
1131
-
1132
- }
1133
1094
  jsonData = {
1134
1095
  ...jsonData,
1135
1096
  jsonOptions: {
1136
1097
  ...jsonData.jsonOptions,
1137
- schema: schema,
1098
+ schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema),
1138
1099
  },
1139
1100
  };
1140
1101
  }
@@ -1326,20 +1287,7 @@ export default class FirecrawlApp {
1326
1287
  const headers = this.prepareHeaders();
1327
1288
 
1328
1289
  let jsonData: { urls?: string[] } & ExtractParams<T> = { urls: urls, ...params };
1329
- let jsonSchema: any;
1330
- try {
1331
- if (!params?.schema) {
1332
- jsonSchema = undefined;
1333
- } else {
1334
- try {
1335
- jsonSchema = zodToJsonSchema(params.schema as zt.ZodType);
1336
- } catch (_) {
1337
- jsonSchema = params.schema;
1338
- }
1339
- }
1340
- } catch (error: any) {
1341
- throw new FirecrawlError("Invalid schema. Schema must be either a valid Zod schema or JSON schema object.", 400);
1342
- }
1290
+ const jsonSchema = params?.schema ? zodSchemaToJsonSchema(params.schema) : undefined;
1343
1291
 
1344
1292
  try {
1345
1293
  const response: AxiosResponse = await this.postRequest(
@@ -1396,22 +1344,8 @@ export default class FirecrawlApp {
1396
1344
  idempotencyKey?: string
1397
1345
  ): Promise<ExtractResponse | ErrorResponse> {
1398
1346
  const headers = this.prepareHeaders(idempotencyKey);
1399
- let jsonData: any = { urls, ...params };
1400
- let jsonSchema: any;
1401
-
1402
- try {
1403
- if (!params?.schema) {
1404
- jsonSchema = undefined;
1405
- } else {
1406
- try {
1407
- jsonSchema = zodToJsonSchema(params.schema as zt.ZodType);
1408
- } catch (_) {
1409
- jsonSchema = params.schema;
1410
- }
1411
- }
1412
- } catch (error: any) {
1413
- throw new FirecrawlError("Invalid schema. Schema must be either a valid Zod schema or JSON schema object.", 400);
1414
- }
1347
+ const jsonData: any = { urls, ...params };
1348
+ const jsonSchema = params?.schema ? zodSchemaToJsonSchema(params.schema) : undefined;
1415
1349
 
1416
1350
  try {
1417
1351
  const response: AxiosResponse = await this.postRequest(
@@ -1780,18 +1714,11 @@ export default class FirecrawlApp {
1780
1714
  let jsonData: any = { query, ...params, origin: typeof (params as any).origin === "string" && (params as any).origin.includes("mcp") ? (params as any).origin : `js-sdk@${this.version}` };
1781
1715
 
1782
1716
  if (jsonData?.jsonOptions?.schema) {
1783
- let schema = jsonData.jsonOptions.schema;
1784
- // Try parsing the schema as a Zod schema
1785
- try {
1786
- schema = zodToJsonSchema(schema);
1787
- } catch (error) {
1788
- // Ignore error if schema can't be parsed as Zod
1789
- }
1790
1717
  jsonData = {
1791
1718
  ...jsonData,
1792
1719
  jsonOptions: {
1793
1720
  ...jsonData.jsonOptions,
1794
- schema: schema,
1721
+ schema: zodSchemaToJsonSchema(jsonData.jsonOptions.schema),
1795
1722
  },
1796
1723
  };
1797
1724
  }
@@ -1,7 +1,7 @@
1
1
  import { type AgentResponse, type AgentStatusResponse, type AgentWebhookConfig } from "../types";
2
2
  import { HttpClient } from "../utils/httpClient";
3
3
  import { normalizeAxiosError, throwForBadResponse } from "../utils/errorHandler";
4
- import { zodToJsonSchema } from "zod-to-json-schema";
4
+ import { isZodSchema, zodSchemaToJsonSchema } from "../../utils/zodSchemaToJson";
5
5
  import type { ZodTypeAny } from "zod";
6
6
 
7
7
  function prepareAgentPayload(args: {
@@ -18,9 +18,7 @@ function prepareAgentPayload(args: {
18
18
  if (args.urls) body.urls = args.urls;
19
19
  body.prompt = args.prompt;
20
20
  if (args.schema != null) {
21
- const s: any = args.schema;
22
- const isZod = s && (typeof s.safeParse === "function" || typeof s.parse === "function") && s._def;
23
- body.schema = isZod ? zodToJsonSchema(s) : args.schema;
21
+ body.schema = isZodSchema(args.schema) ? zodSchemaToJsonSchema(args.schema) : args.schema;
24
22
  }
25
23
  if (args.integration && args.integration.trim()) body.integration = args.integration.trim();
26
24
  if (args.maxCredits !== null && args.maxCredits !== undefined) body.maxCredits = args.maxCredits;
@@ -2,7 +2,7 @@ import { type ExtractResponse, type ScrapeOptions, type AgentOptions } from "../
2
2
  import { HttpClient } from "../utils/httpClient";
3
3
  import { ensureValidScrapeOptions } from "../utils/validation";
4
4
  import { normalizeAxiosError, throwForBadResponse } from "../utils/errorHandler";
5
- import { zodToJsonSchema } from "zod-to-json-schema";
5
+ import { isZodSchema, zodSchemaToJsonSchema } from "../../utils/zodSchemaToJson";
6
6
  import type { ZodTypeAny } from "zod";
7
7
 
8
8
  function prepareExtractPayload(args: {
@@ -22,9 +22,7 @@ function prepareExtractPayload(args: {
22
22
  if (args.urls) body.urls = args.urls;
23
23
  if (args.prompt != null) body.prompt = args.prompt;
24
24
  if (args.schema != null) {
25
- const s: any = args.schema;
26
- const isZod = s && (typeof s.safeParse === "function" || typeof s.parse === "function") && s._def;
27
- body.schema = isZod ? zodToJsonSchema(s) : args.schema;
25
+ body.schema = isZodSchema(args.schema) ? zodSchemaToJsonSchema(args.schema) : args.schema;
28
26
  }
29
27
  if (args.systemPrompt != null) body.systemPrompt = args.systemPrompt;
30
28
  if (args.allowExternalLinks != null) body.allowExternalLinks = args.allowExternalLinks;
@@ -1,18 +1,5 @@
1
1
  import { type FormatOption, type JsonFormat, type ScrapeOptions, type ScreenshotFormat, type ChangeTrackingFormat } from "../types";
2
- import { zodToJsonSchema } from "zod-to-json-schema";
3
-
4
- /**
5
- * Detects if an object looks like a Zod schema's `.shape` property.
6
- * When users mistakenly pass `schema.shape` instead of `schema`, the object
7
- * will have Zod types as values but won't be a Zod schema itself.
8
- */
9
- function looksLikeZodShape(obj: unknown): boolean {
10
- if (!obj || typeof obj !== "object" || Array.isArray(obj)) return false;
11
- const values = Object.values(obj);
12
- if (values.length === 0) return false;
13
- // Check if at least one value looks like a Zod type
14
- return values.some((v: any) => v && typeof v === "object" && v._def && typeof v.safeParse === "function");
15
- }
2
+ import { isZodSchema, zodSchemaToJsonSchema, looksLikeZodShape } from "../../utils/zodSchemaToJson";
16
3
 
17
4
  export function ensureValidFormats(formats?: FormatOption[]): void {
18
5
  if (!formats) return;
@@ -28,17 +15,10 @@ export function ensureValidFormats(formats?: FormatOption[]): void {
28
15
  if (!j.prompt && !j.schema) {
29
16
  throw new Error("json format requires either 'prompt' or 'schema' (or both)");
30
17
  }
31
- // Flexibility: allow passing a Zod schema. Convert to JSON schema internally.
32
- const maybeSchema: any = j.schema as any;
33
- const isZod = !!maybeSchema && (typeof maybeSchema.safeParse === "function" || typeof maybeSchema.parse === "function") && !!maybeSchema._def;
34
- if (isZod) {
35
- try {
36
- (j as any).schema = zodToJsonSchema(maybeSchema);
37
- } catch {
38
- // If conversion fails, leave as-is; server-side may still handle, or request will fail explicitly
39
- }
18
+ const maybeSchema = j.schema;
19
+ if (isZodSchema(maybeSchema)) {
20
+ (j as any).schema = zodSchemaToJsonSchema(maybeSchema);
40
21
  } else if (looksLikeZodShape(maybeSchema)) {
41
- // User likely passed schema.shape instead of the schema itself
42
22
  throw new Error(
43
23
  "json format schema appears to be a Zod schema's .shape property. " +
44
24
  "Pass the Zod schema directly (e.g., `schema: MySchema`) instead of `schema: MySchema.shape`. " +
@@ -49,14 +29,9 @@ export function ensureValidFormats(formats?: FormatOption[]): void {
49
29
  }
50
30
  if ((fmt as ChangeTrackingFormat).type === "changeTracking") {
51
31
  const ct = fmt as ChangeTrackingFormat;
52
- const maybeSchema: any = ct.schema as any;
53
- const isZod = !!maybeSchema && (typeof maybeSchema.safeParse === "function" || typeof maybeSchema.parse === "function") && !!maybeSchema._def;
54
- if (isZod) {
55
- try {
56
- (ct as any).schema = zodToJsonSchema(maybeSchema);
57
- } catch {
58
- // Best-effort conversion; if it fails, leave original value
59
- }
32
+ const maybeSchema = ct.schema;
33
+ if (isZodSchema(maybeSchema)) {
34
+ (ct as any).schema = zodSchemaToJsonSchema(maybeSchema);
60
35
  } else if (looksLikeZodShape(maybeSchema)) {
61
36
  throw new Error(
62
37
  "changeTracking format schema appears to be a Zod schema's .shape property. " +