@discomedia/utils 1.0.62 → 1.0.64

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.
@@ -227,7 +227,7 @@ function maybeObj(x) {
227
227
  return x ?? {};
228
228
  }
229
229
  // https://stackoverflow.com/a/34491287
230
- function isEmptyObj(obj) {
230
+ function isEmptyObj$1(obj) {
231
231
  if (!obj)
232
232
  return true;
233
233
  for (const _k in obj)
@@ -262,7 +262,7 @@ const safeJSON = (text) => {
262
262
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
263
263
  const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
264
264
 
265
- const VERSION = '6.27.0'; // x-release-please-version
265
+ const VERSION = '6.31.0'; // x-release-please-version
266
266
 
267
267
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
268
268
  const isRunningInBrowser = () => {
@@ -1966,6 +1966,20 @@ let Messages$1 = class Messages extends APIResource {
1966
1966
  function isChatCompletionFunctionTool(tool) {
1967
1967
  return tool !== undefined && 'function' in tool && tool.function !== undefined;
1968
1968
  }
1969
+ function makeParseableTextFormat(response_format, parser) {
1970
+ const obj = { ...response_format };
1971
+ Object.defineProperties(obj, {
1972
+ $brand: {
1973
+ value: 'auto-parseable-response-format',
1974
+ enumerable: false,
1975
+ },
1976
+ $parseRaw: {
1977
+ value: parser,
1978
+ enumerable: false,
1979
+ },
1980
+ });
1981
+ return obj;
1982
+ }
1969
1983
  function isAutoParsableResponseFormat(response_format) {
1970
1984
  return response_format?.['$brand'] === 'auto-parseable-response-format';
1971
1985
  }
@@ -3492,7 +3506,7 @@ class Speech extends APIResource {
3492
3506
  * const speech = await client.audio.speech.create({
3493
3507
  * input: 'input',
3494
3508
  * model: 'string',
3495
- * voice: 'ash',
3509
+ * voice: 'string',
3496
3510
  * });
3497
3511
  *
3498
3512
  * const content = await speech.blob();
@@ -3978,7 +3992,7 @@ const readEnv = (env) => {
3978
3992
  return undefined;
3979
3993
  };
3980
3994
 
3981
- var _AssistantStream_instances, _a$1, _AssistantStream_events, _AssistantStream_runStepSnapshots, _AssistantStream_messageSnapshots, _AssistantStream_messageSnapshot, _AssistantStream_finalRun, _AssistantStream_currentContentIndex, _AssistantStream_currentContent, _AssistantStream_currentToolCallIndex, _AssistantStream_currentToolCall, _AssistantStream_currentEvent, _AssistantStream_currentRunSnapshot, _AssistantStream_currentRunStepSnapshot, _AssistantStream_addEvent, _AssistantStream_endRequest, _AssistantStream_handleMessage, _AssistantStream_handleRunStep, _AssistantStream_handleEvent, _AssistantStream_accumulateRunStep, _AssistantStream_accumulateMessage, _AssistantStream_accumulateContent, _AssistantStream_handleRun;
3995
+ var _AssistantStream_instances, _a$2, _AssistantStream_events, _AssistantStream_runStepSnapshots, _AssistantStream_messageSnapshots, _AssistantStream_messageSnapshot, _AssistantStream_finalRun, _AssistantStream_currentContentIndex, _AssistantStream_currentContent, _AssistantStream_currentToolCallIndex, _AssistantStream_currentToolCall, _AssistantStream_currentEvent, _AssistantStream_currentRunSnapshot, _AssistantStream_currentRunStepSnapshot, _AssistantStream_addEvent, _AssistantStream_endRequest, _AssistantStream_handleMessage, _AssistantStream_handleRunStep, _AssistantStream_handleEvent, _AssistantStream_accumulateRunStep, _AssistantStream_accumulateMessage, _AssistantStream_accumulateContent, _AssistantStream_handleRun;
3982
3996
  class AssistantStream extends EventStream {
3983
3997
  constructor() {
3984
3998
  super(...arguments);
@@ -4053,7 +4067,7 @@ class AssistantStream extends EventStream {
4053
4067
  };
4054
4068
  }
4055
4069
  static fromReadableStream(stream) {
4056
- const runner = new _a$1();
4070
+ const runner = new _a$2();
4057
4071
  runner._run(() => runner._fromReadableStream(stream));
4058
4072
  return runner;
4059
4073
  }
@@ -4079,7 +4093,7 @@ class AssistantStream extends EventStream {
4079
4093
  return stream.toReadableStream();
4080
4094
  }
4081
4095
  static createToolAssistantStream(runId, runs, params, options) {
4082
- const runner = new _a$1();
4096
+ const runner = new _a$2();
4083
4097
  runner._run(() => runner._runToolAssistantStream(runId, runs, params, {
4084
4098
  ...options,
4085
4099
  headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' },
@@ -4108,7 +4122,7 @@ class AssistantStream extends EventStream {
4108
4122
  return this._addRun(__classPrivateFieldGet(this, _AssistantStream_instances, "m", _AssistantStream_endRequest).call(this));
4109
4123
  }
4110
4124
  static createThreadAssistantStream(params, thread, options) {
4111
- const runner = new _a$1();
4125
+ const runner = new _a$2();
4112
4126
  runner._run(() => runner._threadAssistantStream(params, thread, {
4113
4127
  ...options,
4114
4128
  headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' },
@@ -4116,7 +4130,7 @@ class AssistantStream extends EventStream {
4116
4130
  return runner;
4117
4131
  }
4118
4132
  static createAssistantStream(threadId, runs, params, options) {
4119
- const runner = new _a$1();
4133
+ const runner = new _a$2();
4120
4134
  runner._run(() => runner._runAssistantStream(threadId, runs, params, {
4121
4135
  ...options,
4122
4136
  headers: { ...options?.headers, 'X-Stainless-Helper-Method': 'stream' },
@@ -4258,7 +4272,7 @@ class AssistantStream extends EventStream {
4258
4272
  return await this._createToolAssistantStream(runs, runId, params, options);
4259
4273
  }
4260
4274
  }
4261
- _a$1 = AssistantStream, _AssistantStream_addEvent = function _AssistantStream_addEvent(event) {
4275
+ _a$2 = AssistantStream, _AssistantStream_addEvent = function _AssistantStream_addEvent(event) {
4262
4276
  if (this.ended)
4263
4277
  return;
4264
4278
  __classPrivateFieldSet(this, _AssistantStream_currentEvent, event);
@@ -4436,7 +4450,7 @@ _a$1 = AssistantStream, _AssistantStream_addEvent = function _AssistantStream_ad
4436
4450
  }
4437
4451
  let data = event.data;
4438
4452
  if (data.delta) {
4439
- const accumulated = _a$1.accumulateDelta(snapshot, data.delta);
4453
+ const accumulated = _a$2.accumulateDelta(snapshot, data.delta);
4440
4454
  __classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[event.data.id] = accumulated;
4441
4455
  }
4442
4456
  return __classPrivateFieldGet(this, _AssistantStream_runStepSnapshots, "f")[event.data.id];
@@ -4490,7 +4504,7 @@ _a$1 = AssistantStream, _AssistantStream_addEvent = function _AssistantStream_ad
4490
4504
  }
4491
4505
  throw Error('Tried to accumulate a non-message event');
4492
4506
  }, _AssistantStream_accumulateContent = function _AssistantStream_accumulateContent(contentElement, currentContent) {
4493
- return _a$1.accumulateDelta(currentContent, contentElement);
4507
+ return _a$2.accumulateDelta(currentContent, contentElement);
4494
4508
  }, _AssistantStream_handleRun = function _AssistantStream_handleRun(event) {
4495
4509
  __classPrivateFieldSet(this, _AssistantStream_currentRunSnapshot, event.data);
4496
4510
  switch (event.event) {
@@ -6773,7 +6787,7 @@ class Videos extends APIResource {
6773
6787
  * Create a new video generation job from a prompt and optional reference assets.
6774
6788
  */
6775
6789
  create(body, options) {
6776
- return this._client.post('/videos', maybeMultipartFormRequestOptions({ body, ...options }, this._client));
6790
+ return this._client.post('/videos', multipartFormRequestOptions({ body, ...options }, this._client));
6777
6791
  }
6778
6792
  /**
6779
6793
  * Fetch the latest metadata for a generated video.
@@ -6793,6 +6807,12 @@ class Videos extends APIResource {
6793
6807
  delete(videoID, options) {
6794
6808
  return this._client.delete(path `/videos/${videoID}`, options);
6795
6809
  }
6810
+ /**
6811
+ * Create a character from an uploaded video.
6812
+ */
6813
+ createCharacter(body, options) {
6814
+ return this._client.post('/videos/characters', multipartFormRequestOptions({ body, ...options }, this._client));
6815
+ }
6796
6816
  /**
6797
6817
  * Download the generated video bytes or a derived preview asset.
6798
6818
  *
@@ -6806,6 +6826,25 @@ class Videos extends APIResource {
6806
6826
  __binaryResponse: true,
6807
6827
  });
6808
6828
  }
6829
+ /**
6830
+ * Create a new video generation job by editing a source video or existing
6831
+ * generated video.
6832
+ */
6833
+ edit(body, options) {
6834
+ return this._client.post('/videos/edits', multipartFormRequestOptions({ body, ...options }, this._client));
6835
+ }
6836
+ /**
6837
+ * Create an extension of a completed video.
6838
+ */
6839
+ extend(body, options) {
6840
+ return this._client.post('/videos/extensions', multipartFormRequestOptions({ body, ...options }, this._client));
6841
+ }
6842
+ /**
6843
+ * Fetch a character.
6844
+ */
6845
+ getCharacter(characterID, options) {
6846
+ return this._client.get(path `/videos/characters/${characterID}`, options);
6847
+ }
6809
6848
  /**
6810
6849
  * Create a remix of a completed video using a refreshed prompt.
6811
6850
  */
@@ -6908,7 +6947,7 @@ _Webhooks_instances = new WeakSet(), _Webhooks_validateSecret = function _Webhoo
6908
6947
  };
6909
6948
 
6910
6949
  // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
6911
- var _OpenAI_instances, _a, _OpenAI_encoder, _OpenAI_baseURLOverridden;
6950
+ var _OpenAI_instances, _a$1, _OpenAI_encoder, _OpenAI_baseURLOverridden;
6912
6951
  /**
6913
6952
  * API Client for interfacing with the OpenAI API.
6914
6953
  */
@@ -6999,7 +7038,7 @@ class OpenAI {
6999
7038
  throw new OpenAIError("It looks like you're running in a browser-like environment.\n\nThis is disabled by default, as it risks exposing your secret API credentials to attackers.\nIf you understand the risks and have appropriate mitigations in place,\nyou can set the `dangerouslyAllowBrowser` option to `true`, e.g.,\n\nnew OpenAI({ apiKey, dangerouslyAllowBrowser: true });\n\nhttps://help.openai.com/en/articles/5112595-best-practices-for-api-key-safety\n");
7000
7039
  }
7001
7040
  this.baseURL = options.baseURL;
7002
- this.timeout = options.timeout ?? _a.DEFAULT_TIMEOUT /* 10 minutes */;
7041
+ this.timeout = options.timeout ?? _a$1.DEFAULT_TIMEOUT /* 10 minutes */;
7003
7042
  this.logger = options.logger ?? console;
7004
7043
  const defaultLogLevel = 'warn';
7005
7044
  // Set default logLevel early so that we can log a warning in parseLogLevel.
@@ -7087,8 +7126,9 @@ class OpenAI {
7087
7126
  new URL(path)
7088
7127
  : new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path));
7089
7128
  const defaultQuery = this.defaultQuery();
7090
- if (!isEmptyObj(defaultQuery)) {
7091
- query = { ...defaultQuery, ...query };
7129
+ const pathQuery = Object.fromEntries(url.searchParams);
7130
+ if (!isEmptyObj$1(defaultQuery) || !isEmptyObj$1(pathQuery)) {
7131
+ query = { ...pathQuery, ...defaultQuery, ...query };
7092
7132
  }
7093
7133
  if (typeof query === 'object' && query && !Array.isArray(query)) {
7094
7134
  url.search = this.stringifyQuery(query);
@@ -7429,10 +7469,10 @@ class OpenAI {
7429
7469
  }
7430
7470
  }
7431
7471
  }
7432
- _a = OpenAI, _OpenAI_encoder = new WeakMap(), _OpenAI_instances = new WeakSet(), _OpenAI_baseURLOverridden = function _OpenAI_baseURLOverridden() {
7472
+ _a$1 = OpenAI, _OpenAI_encoder = new WeakMap(), _OpenAI_instances = new WeakSet(), _OpenAI_baseURLOverridden = function _OpenAI_baseURLOverridden() {
7433
7473
  return this.baseURL !== 'https://api.openai.com/v1';
7434
7474
  };
7435
- OpenAI.OpenAI = _a;
7475
+ OpenAI.OpenAI = _a$1;
7436
7476
  OpenAI.DEFAULT_TIMEOUT = 600000; // 10 minutes
7437
7477
  OpenAI.OpenAIError = OpenAIError;
7438
7478
  OpenAI.APIError = APIError;
@@ -7472,233 +7512,3007 @@ OpenAI.Containers = Containers;
7472
7512
  OpenAI.Skills = Skills;
7473
7513
  OpenAI.Videos = Videos;
7474
7514
 
7475
- // llm-openai-config.ts
7476
- const DEFAULT_MODEL = 'gpt-4.1-mini';
7477
- const GPT_5_4_HIGH_CONTEXT_THRESHOLD_TOKENS = 272_000;
7478
- const GPT_5_4_HIGH_CONTEXT_INPUT_MULTIPLIER = 2;
7479
- const GPT_5_4_HIGH_CONTEXT_OUTPUT_MULTIPLIER = 1.5;
7480
- /** Token costs in USD per 1M tokens. Last updated Mar 2026. */
7481
- const openAiModelCosts = {
7482
- 'gpt-4o': {
7483
- inputCost: 2.5 / 1_000_000,
7484
- cacheHitCost: 1.25 / 1_000_000,
7485
- outputCost: 10 / 1_000_000,
7486
- },
7487
- 'gpt-4o-mini': {
7488
- inputCost: 0.15 / 1_000_000,
7489
- cacheHitCost: 0.075 / 1_000_000,
7490
- outputCost: 0.6 / 1_000_000,
7491
- },
7492
- 'o1-mini': {
7493
- inputCost: 1.1 / 1_000_000,
7494
- cacheHitCost: 0.55 / 1_000_000,
7495
- outputCost: 4.4 / 1_000_000,
7496
- },
7497
- 'o1': {
7498
- inputCost: 15 / 1_000_000,
7499
- cacheHitCost: 7.5 / 1_000_000,
7500
- outputCost: 60 / 1_000_000,
7501
- },
7502
- 'o3-mini': {
7503
- inputCost: 1.1 / 1_000_000,
7504
- cacheHitCost: 0.55 / 1_000_000,
7505
- outputCost: 4.4 / 1_000_000,
7506
- },
7507
- 'o3': {
7508
- inputCost: 2 / 1_000_000,
7509
- cacheHitCost: 0.5 / 1_000_000,
7510
- outputCost: 8 / 1_000_000,
7511
- },
7512
- 'gpt-4.1': {
7513
- inputCost: 2 / 1_000_000,
7514
- cacheHitCost: 0.5 / 1_000_000,
7515
- outputCost: 8 / 1_000_000,
7516
- },
7517
- 'gpt-4.1-mini': {
7518
- inputCost: 0.4 / 1_000_000,
7519
- cacheHitCost: 0.1 / 1_000_000,
7520
- outputCost: 1.6 / 1_000_000,
7521
- },
7522
- 'gpt-4.1-nano': {
7523
- inputCost: 0.1 / 1_000_000,
7524
- cacheHitCost: 0.025 / 1_000_000,
7525
- outputCost: 0.4 / 1_000_000,
7526
- },
7527
- 'gpt-5': {
7528
- inputCost: 1.25 / 1_000_000,
7529
- cacheHitCost: 0.125 / 1_000_000,
7530
- outputCost: 10 / 1_000_000,
7531
- },
7532
- 'gpt-5-mini': {
7533
- inputCost: 0.25 / 1_000_000,
7534
- cacheHitCost: 0.025 / 1_000_000,
7535
- outputCost: 2 / 1_000_000,
7536
- },
7537
- 'gpt-5-nano': {
7538
- inputCost: 0.05 / 1_000_000,
7539
- cacheHitCost: 0.005 / 1_000_000,
7540
- outputCost: 0.4 / 1_000_000,
7541
- },
7542
- 'gpt-5.1': {
7543
- inputCost: 1.25 / 1_000_000,
7544
- cacheHitCost: 0.125 / 1_000_000,
7545
- outputCost: 10 / 1_000_000,
7546
- },
7547
- 'gpt-5.4': {
7548
- inputCost: 2.5 / 1_000_000,
7549
- cacheHitCost: 0.25 / 1_000_000,
7550
- outputCost: 15 / 1_000_000,
7551
- },
7552
- 'gpt-5.4-pro': {
7553
- inputCost: 30 / 1_000_000,
7554
- outputCost: 180 / 1_000_000,
7555
- },
7556
- 'gpt-5.2': {
7557
- inputCost: 1.75 / 1_000_000,
7558
- cacheHitCost: 0.175 / 1_000_000,
7559
- outputCost: 14 / 1_000_000,
7560
- },
7561
- 'gpt-5.2-pro': {
7562
- inputCost: 21 / 1_000_000,
7563
- outputCost: 168 / 1_000_000,
7564
- },
7565
- 'gpt-5.1-codex': {
7566
- inputCost: 1.25 / 1_000_000,
7567
- cacheHitCost: 0.125 / 1_000_000,
7568
- outputCost: 10 / 1_000_000,
7569
- },
7570
- 'gpt-5.1-codex-max': {
7571
- inputCost: 1.25 / 1_000_000,
7572
- cacheHitCost: 0.125 / 1_000_000,
7573
- outputCost: 10 / 1_000_000,
7574
- },
7575
- 'o4-mini': {
7576
- inputCost: 1.1 / 1_000_000,
7577
- cacheHitCost: 0.275 / 1_000_000,
7578
- outputCost: 4.4 / 1_000_000,
7579
- },
7580
- };
7581
- const deepseekModelCosts = {
7582
- 'deepseek-chat': {
7583
- inputCost: 0.27 / 1_000_000, // $0.27 per 1M tokens (Cache miss price)
7584
- cacheHitCost: 0.07 / 1_000_000, // $0.07 per 1M tokens (Cache hit price)
7585
- outputCost: 1.1 / 1_000_000, // $1.10 per 1M tokens
7586
- },
7587
- 'deepseek-reasoner': {
7588
- inputCost: 0.55 / 1_000_000, // $0.55 per 1M tokens (Cache miss price)
7589
- cacheHitCost: 0.14 / 1_000_000, // $0.14 per 1M tokens (Cache hit price)
7590
- outputCost: 2.19 / 1_000_000, // $2.19 per 1M tokens
7591
- },
7592
- };
7593
- function shouldUseGPT54HighContextPricing(model, inputTokens) {
7594
- return (model === 'gpt-5.4' || model === 'gpt-5.4-pro') && inputTokens > GPT_5_4_HIGH_CONTEXT_THRESHOLD_TOKENS;
7515
+ // functions
7516
+ function getEnumValues(entries) {
7517
+ const numericValues = Object.values(entries).filter((v) => typeof v === "number");
7518
+ const values = Object.entries(entries)
7519
+ .filter(([k, _]) => numericValues.indexOf(+k) === -1)
7520
+ .map(([_, v]) => v);
7521
+ return values;
7595
7522
  }
7596
- /** Image generation costs in USD per image. Based on OpenAI pricing as of Feb 2025. */
7597
- const openAiImageCosts = {
7598
- 'gpt-image-1': 0.0075, // $0.0075 per image for gpt-image-1
7599
- 'gpt-image-1.5': 0.0075, // Assumes parity pricing with gpt-image-1 until OpenAI publishes updated rates
7600
- };
7601
- /**
7602
- * Calculates the cost of generating images using OpenAI's Images API.
7603
- *
7604
- * @param model The image generation model name.
7605
- * @param imageCount The number of images generated.
7606
- * @returns The cost of generating the images in USD.
7607
- */
7608
- function calculateImageCost(model, imageCount) {
7609
- if (typeof model !== 'string' || typeof imageCount !== 'number' || imageCount <= 0) {
7610
- return 0;
7523
+
7524
+ var _a;
7525
+ class $ZodRegistry {
7526
+ constructor() {
7527
+ this._map = new WeakMap();
7528
+ this._idmap = new Map();
7611
7529
  }
7612
- const costPerImage = openAiImageCosts[model];
7613
- if (!costPerImage)
7614
- return 0;
7615
- return imageCount * costPerImage;
7616
- }
7617
- /**
7618
- * Calculates the cost of calling a language model in USD based on the provider and model, tokens, and given costs per 1M tokens.
7619
- *
7620
- * @param provider The provider of the language model. Supported providers are 'openai' and 'deepseek'.
7621
- * @param model The name of the language model. Supported models are listed in the `openAiModelCosts` and `deepseekModelCosts` objects.
7622
- * @param inputTokens The number of input tokens passed to the language model.
7623
- * @param outputTokens The number of output tokens generated by the language model.
7624
- * @param reasoningTokens The number of output tokens generated by the language model for reasoning.
7625
- * @param cacheHitTokens The number of input tokens billed at cached-input rates.
7626
- * @returns The cost of calling the language model in USD.
7627
- */
7628
- function calculateCost(provider, model, inputTokens, outputTokens, reasoningTokens, cacheHitTokens) {
7629
- if (typeof provider !== 'string' ||
7630
- typeof model !== 'string' ||
7631
- typeof inputTokens !== 'number' ||
7632
- typeof outputTokens !== 'number' ||
7633
- (reasoningTokens !== undefined && typeof reasoningTokens !== 'number') ||
7634
- (cacheHitTokens !== undefined && typeof cacheHitTokens !== 'number')) {
7635
- return 0;
7530
+ add(schema, ..._meta) {
7531
+ const meta = _meta[0];
7532
+ this._map.set(schema, meta);
7533
+ if (meta && typeof meta === "object" && "id" in meta) {
7534
+ this._idmap.set(meta.id, schema);
7535
+ }
7536
+ return this;
7636
7537
  }
7637
- const modelCosts = provider === 'deepseek' ? deepseekModelCosts[model] : openAiModelCosts[model];
7638
- if (!modelCosts)
7639
- return 0;
7640
- const boundedCacheHitTokens = Math.min(Math.max(cacheHitTokens || 0, 0), inputTokens);
7641
- let inputCost = inputTokens * modelCosts.inputCost;
7642
- if (typeof modelCosts.cacheHitCost === 'number' && boundedCacheHitTokens > 0) {
7643
- inputCost = boundedCacheHitTokens * modelCosts.cacheHitCost + (inputTokens - boundedCacheHitTokens) * modelCosts.inputCost;
7538
+ clear() {
7539
+ this._map = new WeakMap();
7540
+ this._idmap = new Map();
7541
+ return this;
7644
7542
  }
7645
- let outputCost = outputTokens * modelCosts.outputCost;
7646
- let reasoningCost = (reasoningTokens || 0) * modelCosts.outputCost;
7647
- if (provider === 'openai' && shouldUseGPT54HighContextPricing(model, inputTokens)) {
7648
- inputCost *= GPT_5_4_HIGH_CONTEXT_INPUT_MULTIPLIER;
7649
- outputCost *= GPT_5_4_HIGH_CONTEXT_OUTPUT_MULTIPLIER;
7650
- reasoningCost *= GPT_5_4_HIGH_CONTEXT_OUTPUT_MULTIPLIER;
7543
+ remove(schema) {
7544
+ const meta = this._map.get(schema);
7545
+ if (meta && typeof meta === "object" && "id" in meta) {
7546
+ this._idmap.delete(meta.id);
7547
+ }
7548
+ this._map.delete(schema);
7549
+ return this;
7550
+ }
7551
+ get(schema) {
7552
+ // return this._map.get(schema) as any;
7553
+ // inherit metadata
7554
+ const p = schema._zod.parent;
7555
+ if (p) {
7556
+ const pm = { ...(this.get(p) ?? {}) };
7557
+ delete pm.id; // do not inherit id
7558
+ const f = { ...pm, ...this._map.get(schema) };
7559
+ return Object.keys(f).length ? f : undefined;
7560
+ }
7561
+ return this._map.get(schema);
7562
+ }
7563
+ has(schema) {
7564
+ return this._map.has(schema);
7651
7565
  }
7652
- return inputCost + outputCost + reasoningCost;
7653
7566
  }
7567
+ // registries
7568
+ function registry() {
7569
+ return new $ZodRegistry();
7570
+ }
7571
+ (_a = globalThis).__zod_globalRegistry ?? (_a.__zod_globalRegistry = registry());
7572
+ const globalRegistry = globalThis.__zod_globalRegistry;
7654
7573
 
7655
- /**
7656
- * Fix a broken JSON string by attempting to extract and parse valid JSON content. This function is very lenient and will attempt to fix many types of JSON errors, including unbalanced brackets, missing or extra commas, improperly escaped $ signs, unquoted strings, trailing commas, missing closing brackets or braces, etc.
7657
- * @param {string} jsonStr - The broken JSON string to fix
7658
- * @returns {JsonValue} - The parsed JSON value
7659
- */
7660
- function fixBrokenJson(jsonStr) {
7661
- // Pre-process: Fix improperly escaped $ signs
7662
- jsonStr = jsonStr.replace(/\\\$/g, '$');
7663
- let index = 0;
7664
- function parse() {
7665
- const results = [];
7666
- while (index < jsonStr.length) {
7667
- skipWhitespace();
7668
- const value = parseValue();
7669
- if (value !== undefined) {
7670
- results.push(value);
7671
- }
7672
- else {
7673
- index++; // Skip invalid character
7674
- }
7675
- }
7676
- return results.length === 1 ? results[0] : results;
7574
+ // function initializeContext<T extends schemas.$ZodType>(inputs: JSONSchemaGeneratorParams<T>): ToJSONSchemaContext<T> {
7575
+ // return {
7576
+ // processor: inputs.processor,
7577
+ // metadataRegistry: inputs.metadata ?? globalRegistry,
7578
+ // target: inputs.target ?? "draft-2020-12",
7579
+ // unrepresentable: inputs.unrepresentable ?? "throw",
7580
+ // };
7581
+ // }
7582
+ function initializeContext(params) {
7583
+ // Normalize target: convert old non-hyphenated versions to hyphenated versions
7584
+ let target = params?.target ?? "draft-2020-12";
7585
+ if (target === "draft-4")
7586
+ target = "draft-04";
7587
+ if (target === "draft-7")
7588
+ target = "draft-07";
7589
+ return {
7590
+ processors: params.processors ?? {},
7591
+ metadataRegistry: params?.metadata ?? globalRegistry,
7592
+ target,
7593
+ unrepresentable: params?.unrepresentable ?? "throw",
7594
+ override: params?.override ?? (() => { }),
7595
+ io: params?.io ?? "output",
7596
+ counter: 0,
7597
+ seen: new Map(),
7598
+ cycles: params?.cycles ?? "ref",
7599
+ reused: params?.reused ?? "inline",
7600
+ external: params?.external ?? undefined,
7601
+ };
7602
+ }
7603
+ function process$1(schema, ctx, _params = { path: [], schemaPath: [] }) {
7604
+ var _a;
7605
+ const def = schema._zod.def;
7606
+ // check for schema in seens
7607
+ const seen = ctx.seen.get(schema);
7608
+ if (seen) {
7609
+ seen.count++;
7610
+ // check if cycle
7611
+ const isCycle = _params.schemaPath.includes(schema);
7612
+ if (isCycle) {
7613
+ seen.cycle = _params.path;
7614
+ }
7615
+ return seen.schema;
7616
+ }
7617
+ // initialize
7618
+ const result = { schema: {}, count: 1, cycle: undefined, path: _params.path };
7619
+ ctx.seen.set(schema, result);
7620
+ // custom method overrides default behavior
7621
+ const overrideSchema = schema._zod.toJSONSchema?.();
7622
+ if (overrideSchema) {
7623
+ result.schema = overrideSchema;
7677
7624
  }
7678
- function parseValue() {
7679
- skipWhitespace();
7680
- const char = getChar();
7681
- if (!char)
7682
- return undefined;
7683
- if (char === '{')
7684
- return parseObject();
7685
- if (char === '[')
7686
- return parseArray();
7687
- if (char === '"' || char === "'")
7688
- return parseString();
7689
- if (char === 't' && jsonStr.slice(index, index + 4).toLowerCase() === 'true') {
7690
- index += 4;
7691
- return true;
7625
+ else {
7626
+ const params = {
7627
+ ..._params,
7628
+ schemaPath: [..._params.schemaPath, schema],
7629
+ path: _params.path,
7630
+ };
7631
+ if (schema._zod.processJSONSchema) {
7632
+ schema._zod.processJSONSchema(ctx, result.schema, params);
7692
7633
  }
7693
- if (char === 'f' && jsonStr.slice(index, index + 5).toLowerCase() === 'false') {
7694
- index += 5;
7695
- return false;
7634
+ else {
7635
+ const _json = result.schema;
7636
+ const processor = ctx.processors[def.type];
7637
+ if (!processor) {
7638
+ throw new Error(`[toJSONSchema]: Non-representable type encountered: ${def.type}`);
7639
+ }
7640
+ processor(schema, ctx, _json, params);
7641
+ }
7642
+ const parent = schema._zod.parent;
7643
+ if (parent) {
7644
+ // Also set ref if processor didn't (for inheritance)
7645
+ if (!result.ref)
7646
+ result.ref = parent;
7647
+ process$1(parent, ctx, params);
7648
+ ctx.seen.get(parent).isParent = true;
7649
+ }
7650
+ }
7651
+ // metadata
7652
+ const meta = ctx.metadataRegistry.get(schema);
7653
+ if (meta)
7654
+ Object.assign(result.schema, meta);
7655
+ if (ctx.io === "input" && isTransforming(schema)) {
7656
+ // examples/defaults only apply to output type of pipe
7657
+ delete result.schema.examples;
7658
+ delete result.schema.default;
7659
+ }
7660
+ // set prefault as default
7661
+ if (ctx.io === "input" && result.schema._prefault)
7662
+ (_a = result.schema).default ?? (_a.default = result.schema._prefault);
7663
+ delete result.schema._prefault;
7664
+ // pulling fresh from ctx.seen in case it was overwritten
7665
+ const _result = ctx.seen.get(schema);
7666
+ return _result.schema;
7667
+ }
7668
+ function extractDefs(ctx, schema
7669
+ // params: EmitParams
7670
+ ) {
7671
+ // iterate over seen map;
7672
+ const root = ctx.seen.get(schema);
7673
+ if (!root)
7674
+ throw new Error("Unprocessed schema. This is a bug in Zod.");
7675
+ // Track ids to detect duplicates across different schemas
7676
+ const idToSchema = new Map();
7677
+ for (const entry of ctx.seen.entries()) {
7678
+ const id = ctx.metadataRegistry.get(entry[0])?.id;
7679
+ if (id) {
7680
+ const existing = idToSchema.get(id);
7681
+ if (existing && existing !== entry[0]) {
7682
+ throw new Error(`Duplicate schema id "${id}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);
7683
+ }
7684
+ idToSchema.set(id, entry[0]);
7685
+ }
7686
+ }
7687
+ // returns a ref to the schema
7688
+ // defId will be empty if the ref points to an external schema (or #)
7689
+ const makeURI = (entry) => {
7690
+ // comparing the seen objects because sometimes
7691
+ // multiple schemas map to the same seen object.
7692
+ // e.g. lazy
7693
+ // external is configured
7694
+ const defsSegment = ctx.target === "draft-2020-12" ? "$defs" : "definitions";
7695
+ if (ctx.external) {
7696
+ const externalId = ctx.external.registry.get(entry[0])?.id; // ?? "__shared";// `__schema${ctx.counter++}`;
7697
+ // check if schema is in the external registry
7698
+ const uriGenerator = ctx.external.uri ?? ((id) => id);
7699
+ if (externalId) {
7700
+ return { ref: uriGenerator(externalId) };
7701
+ }
7702
+ // otherwise, add to __shared
7703
+ const id = entry[1].defId ?? entry[1].schema.id ?? `schema${ctx.counter++}`;
7704
+ entry[1].defId = id; // set defId so it will be reused if needed
7705
+ return { defId: id, ref: `${uriGenerator("__shared")}#/${defsSegment}/${id}` };
7706
+ }
7707
+ if (entry[1] === root) {
7708
+ return { ref: "#" };
7709
+ }
7710
+ // self-contained schema
7711
+ const uriPrefix = `#`;
7712
+ const defUriPrefix = `${uriPrefix}/${defsSegment}/`;
7713
+ const defId = entry[1].schema.id ?? `__schema${ctx.counter++}`;
7714
+ return { defId, ref: defUriPrefix + defId };
7715
+ };
7716
+ // stored cached version in `def` property
7717
+ // remove all properties, set $ref
7718
+ const extractToDef = (entry) => {
7719
+ // if the schema is already a reference, do not extract it
7720
+ if (entry[1].schema.$ref) {
7721
+ return;
7696
7722
  }
7697
- if (char === 'n' && jsonStr.slice(index, index + 4).toLowerCase() === 'null') {
7698
- index += 4;
7699
- return null;
7723
+ const seen = entry[1];
7724
+ const { ref, defId } = makeURI(entry);
7725
+ seen.def = { ...seen.schema };
7726
+ // defId won't be set if the schema is a reference to an external schema
7727
+ // or if the schema is the root schema
7728
+ if (defId)
7729
+ seen.defId = defId;
7730
+ // wipe away all properties except $ref
7731
+ const schema = seen.schema;
7732
+ for (const key in schema) {
7733
+ delete schema[key];
7734
+ }
7735
+ schema.$ref = ref;
7736
+ };
7737
+ // throw on cycles
7738
+ // break cycles
7739
+ if (ctx.cycles === "throw") {
7740
+ for (const entry of ctx.seen.entries()) {
7741
+ const seen = entry[1];
7742
+ if (seen.cycle) {
7743
+ throw new Error("Cycle detected: " +
7744
+ `#/${seen.cycle?.join("/")}/<root>` +
7745
+ '\n\nSet the `cycles` parameter to `"ref"` to resolve cyclical schemas with defs.');
7746
+ }
7747
+ }
7748
+ }
7749
+ // extract schemas into $defs
7750
+ for (const entry of ctx.seen.entries()) {
7751
+ const seen = entry[1];
7752
+ // convert root schema to # $ref
7753
+ if (schema === entry[0]) {
7754
+ extractToDef(entry); // this has special handling for the root schema
7755
+ continue;
7700
7756
  }
7701
- if (/[a-zA-Z]/.test(char))
7757
+ // extract schemas that are in the external registry
7758
+ if (ctx.external) {
7759
+ const ext = ctx.external.registry.get(entry[0])?.id;
7760
+ if (schema !== entry[0] && ext) {
7761
+ extractToDef(entry);
7762
+ continue;
7763
+ }
7764
+ }
7765
+ // extract schemas with `id` meta
7766
+ const id = ctx.metadataRegistry.get(entry[0])?.id;
7767
+ if (id) {
7768
+ extractToDef(entry);
7769
+ continue;
7770
+ }
7771
+ // break cycles
7772
+ if (seen.cycle) {
7773
+ // any
7774
+ extractToDef(entry);
7775
+ continue;
7776
+ }
7777
+ // extract reused schemas
7778
+ if (seen.count > 1) {
7779
+ if (ctx.reused === "ref") {
7780
+ extractToDef(entry);
7781
+ // biome-ignore lint:
7782
+ continue;
7783
+ }
7784
+ }
7785
+ }
7786
+ }
7787
+ function finalize(ctx, schema) {
7788
+ const root = ctx.seen.get(schema);
7789
+ if (!root)
7790
+ throw new Error("Unprocessed schema. This is a bug in Zod.");
7791
+ // flatten refs - inherit properties from parent schemas
7792
+ const flattenRef = (zodSchema) => {
7793
+ const seen = ctx.seen.get(zodSchema);
7794
+ // already processed
7795
+ if (seen.ref === null)
7796
+ return;
7797
+ const schema = seen.def ?? seen.schema;
7798
+ const _cached = { ...schema };
7799
+ const ref = seen.ref;
7800
+ seen.ref = null; // prevent infinite recursion
7801
+ if (ref) {
7802
+ flattenRef(ref);
7803
+ const refSeen = ctx.seen.get(ref);
7804
+ const refSchema = refSeen.schema;
7805
+ // merge referenced schema into current
7806
+ if (refSchema.$ref && (ctx.target === "draft-07" || ctx.target === "draft-04" || ctx.target === "openapi-3.0")) {
7807
+ // older drafts can't combine $ref with other properties
7808
+ schema.allOf = schema.allOf ?? [];
7809
+ schema.allOf.push(refSchema);
7810
+ }
7811
+ else {
7812
+ Object.assign(schema, refSchema);
7813
+ }
7814
+ // restore child's own properties (child wins)
7815
+ Object.assign(schema, _cached);
7816
+ const isParentRef = zodSchema._zod.parent === ref;
7817
+ // For parent chain, child is a refinement - remove parent-only properties
7818
+ if (isParentRef) {
7819
+ for (const key in schema) {
7820
+ if (key === "$ref" || key === "allOf")
7821
+ continue;
7822
+ if (!(key in _cached)) {
7823
+ delete schema[key];
7824
+ }
7825
+ }
7826
+ }
7827
+ // When ref was extracted to $defs, remove properties that match the definition
7828
+ if (refSchema.$ref && refSeen.def) {
7829
+ for (const key in schema) {
7830
+ if (key === "$ref" || key === "allOf")
7831
+ continue;
7832
+ if (key in refSeen.def && JSON.stringify(schema[key]) === JSON.stringify(refSeen.def[key])) {
7833
+ delete schema[key];
7834
+ }
7835
+ }
7836
+ }
7837
+ }
7838
+ // If parent was extracted (has $ref), propagate $ref to this schema
7839
+ // This handles cases like: readonly().meta({id}).describe()
7840
+ // where processor sets ref to innerType but parent should be referenced
7841
+ const parent = zodSchema._zod.parent;
7842
+ if (parent && parent !== ref) {
7843
+ // Ensure parent is processed first so its def has inherited properties
7844
+ flattenRef(parent);
7845
+ const parentSeen = ctx.seen.get(parent);
7846
+ if (parentSeen?.schema.$ref) {
7847
+ schema.$ref = parentSeen.schema.$ref;
7848
+ // De-duplicate with parent's definition
7849
+ if (parentSeen.def) {
7850
+ for (const key in schema) {
7851
+ if (key === "$ref" || key === "allOf")
7852
+ continue;
7853
+ if (key in parentSeen.def && JSON.stringify(schema[key]) === JSON.stringify(parentSeen.def[key])) {
7854
+ delete schema[key];
7855
+ }
7856
+ }
7857
+ }
7858
+ }
7859
+ }
7860
+ // execute overrides
7861
+ ctx.override({
7862
+ zodSchema: zodSchema,
7863
+ jsonSchema: schema,
7864
+ path: seen.path ?? [],
7865
+ });
7866
+ };
7867
+ for (const entry of [...ctx.seen.entries()].reverse()) {
7868
+ flattenRef(entry[0]);
7869
+ }
7870
+ const result = {};
7871
+ if (ctx.target === "draft-2020-12") {
7872
+ result.$schema = "https://json-schema.org/draft/2020-12/schema";
7873
+ }
7874
+ else if (ctx.target === "draft-07") {
7875
+ result.$schema = "http://json-schema.org/draft-07/schema#";
7876
+ }
7877
+ else if (ctx.target === "draft-04") {
7878
+ result.$schema = "http://json-schema.org/draft-04/schema#";
7879
+ }
7880
+ else if (ctx.target === "openapi-3.0") ;
7881
+ else ;
7882
+ if (ctx.external?.uri) {
7883
+ const id = ctx.external.registry.get(schema)?.id;
7884
+ if (!id)
7885
+ throw new Error("Schema is missing an `id` property");
7886
+ result.$id = ctx.external.uri(id);
7887
+ }
7888
+ Object.assign(result, root.def ?? root.schema);
7889
+ // build defs object
7890
+ const defs = ctx.external?.defs ?? {};
7891
+ for (const entry of ctx.seen.entries()) {
7892
+ const seen = entry[1];
7893
+ if (seen.def && seen.defId) {
7894
+ defs[seen.defId] = seen.def;
7895
+ }
7896
+ }
7897
+ // set definitions in result
7898
+ if (ctx.external) ;
7899
+ else {
7900
+ if (Object.keys(defs).length > 0) {
7901
+ if (ctx.target === "draft-2020-12") {
7902
+ result.$defs = defs;
7903
+ }
7904
+ else {
7905
+ result.definitions = defs;
7906
+ }
7907
+ }
7908
+ }
7909
+ try {
7910
+ // this "finalizes" this schema and ensures all cycles are removed
7911
+ // each call to finalize() is functionally independent
7912
+ // though the seen map is shared
7913
+ const finalized = JSON.parse(JSON.stringify(result));
7914
+ Object.defineProperty(finalized, "~standard", {
7915
+ value: {
7916
+ ...schema["~standard"],
7917
+ jsonSchema: {
7918
+ input: createStandardJSONSchemaMethod(schema, "input", ctx.processors),
7919
+ output: createStandardJSONSchemaMethod(schema, "output", ctx.processors),
7920
+ },
7921
+ },
7922
+ enumerable: false,
7923
+ writable: false,
7924
+ });
7925
+ return finalized;
7926
+ }
7927
+ catch (_err) {
7928
+ throw new Error("Error converting schema to JSON.");
7929
+ }
7930
+ }
7931
+ function isTransforming(_schema, _ctx) {
7932
+ const ctx = _ctx ?? { seen: new Set() };
7933
+ if (ctx.seen.has(_schema))
7934
+ return false;
7935
+ ctx.seen.add(_schema);
7936
+ const def = _schema._zod.def;
7937
+ if (def.type === "transform")
7938
+ return true;
7939
+ if (def.type === "array")
7940
+ return isTransforming(def.element, ctx);
7941
+ if (def.type === "set")
7942
+ return isTransforming(def.valueType, ctx);
7943
+ if (def.type === "lazy")
7944
+ return isTransforming(def.getter(), ctx);
7945
+ if (def.type === "promise" ||
7946
+ def.type === "optional" ||
7947
+ def.type === "nonoptional" ||
7948
+ def.type === "nullable" ||
7949
+ def.type === "readonly" ||
7950
+ def.type === "default" ||
7951
+ def.type === "prefault") {
7952
+ return isTransforming(def.innerType, ctx);
7953
+ }
7954
+ if (def.type === "intersection") {
7955
+ return isTransforming(def.left, ctx) || isTransforming(def.right, ctx);
7956
+ }
7957
+ if (def.type === "record" || def.type === "map") {
7958
+ return isTransforming(def.keyType, ctx) || isTransforming(def.valueType, ctx);
7959
+ }
7960
+ if (def.type === "pipe") {
7961
+ return isTransforming(def.in, ctx) || isTransforming(def.out, ctx);
7962
+ }
7963
+ if (def.type === "object") {
7964
+ for (const key in def.shape) {
7965
+ if (isTransforming(def.shape[key], ctx))
7966
+ return true;
7967
+ }
7968
+ return false;
7969
+ }
7970
+ if (def.type === "union") {
7971
+ for (const option of def.options) {
7972
+ if (isTransforming(option, ctx))
7973
+ return true;
7974
+ }
7975
+ return false;
7976
+ }
7977
+ if (def.type === "tuple") {
7978
+ for (const item of def.items) {
7979
+ if (isTransforming(item, ctx))
7980
+ return true;
7981
+ }
7982
+ if (def.rest && isTransforming(def.rest, ctx))
7983
+ return true;
7984
+ return false;
7985
+ }
7986
+ return false;
7987
+ }
7988
+ const createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) => {
7989
+ const { libraryOptions, target } = params ?? {};
7990
+ const ctx = initializeContext({ ...(libraryOptions ?? {}), target, io, processors });
7991
+ process$1(schema, ctx);
7992
+ extractDefs(ctx, schema);
7993
+ return finalize(ctx, schema);
7994
+ };
7995
+
7996
+ const formatMap = {
7997
+ guid: "uuid",
7998
+ url: "uri",
7999
+ datetime: "date-time",
8000
+ json_string: "json-string",
8001
+ regex: "", // do not set
8002
+ };
8003
+ // ==================== SIMPLE TYPE PROCESSORS ====================
8004
+ const stringProcessor = (schema, ctx, _json, _params) => {
8005
+ const json = _json;
8006
+ json.type = "string";
8007
+ const { minimum, maximum, format, patterns, contentEncoding } = schema._zod
8008
+ .bag;
8009
+ if (typeof minimum === "number")
8010
+ json.minLength = minimum;
8011
+ if (typeof maximum === "number")
8012
+ json.maxLength = maximum;
8013
+ // custom pattern overrides format
8014
+ if (format) {
8015
+ json.format = formatMap[format] ?? format;
8016
+ if (json.format === "")
8017
+ delete json.format; // empty format is not valid
8018
+ // JSON Schema format: "time" requires a full time with offset or Z
8019
+ // z.iso.time() does not include timezone information, so format: "time" should never be used
8020
+ if (format === "time") {
8021
+ delete json.format;
8022
+ }
8023
+ }
8024
+ if (contentEncoding)
8025
+ json.contentEncoding = contentEncoding;
8026
+ if (patterns && patterns.size > 0) {
8027
+ const regexes = [...patterns];
8028
+ if (regexes.length === 1)
8029
+ json.pattern = regexes[0].source;
8030
+ else if (regexes.length > 1) {
8031
+ json.allOf = [
8032
+ ...regexes.map((regex) => ({
8033
+ ...(ctx.target === "draft-07" || ctx.target === "draft-04" || ctx.target === "openapi-3.0"
8034
+ ? { type: "string" }
8035
+ : {}),
8036
+ pattern: regex.source,
8037
+ })),
8038
+ ];
8039
+ }
8040
+ }
8041
+ };
8042
+ const numberProcessor = (schema, ctx, _json, _params) => {
8043
+ const json = _json;
8044
+ const { minimum, maximum, format, multipleOf, exclusiveMaximum, exclusiveMinimum } = schema._zod.bag;
8045
+ if (typeof format === "string" && format.includes("int"))
8046
+ json.type = "integer";
8047
+ else
8048
+ json.type = "number";
8049
+ if (typeof exclusiveMinimum === "number") {
8050
+ if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") {
8051
+ json.minimum = exclusiveMinimum;
8052
+ json.exclusiveMinimum = true;
8053
+ }
8054
+ else {
8055
+ json.exclusiveMinimum = exclusiveMinimum;
8056
+ }
8057
+ }
8058
+ if (typeof minimum === "number") {
8059
+ json.minimum = minimum;
8060
+ if (typeof exclusiveMinimum === "number" && ctx.target !== "draft-04") {
8061
+ if (exclusiveMinimum >= minimum)
8062
+ delete json.minimum;
8063
+ else
8064
+ delete json.exclusiveMinimum;
8065
+ }
8066
+ }
8067
+ if (typeof exclusiveMaximum === "number") {
8068
+ if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") {
8069
+ json.maximum = exclusiveMaximum;
8070
+ json.exclusiveMaximum = true;
8071
+ }
8072
+ else {
8073
+ json.exclusiveMaximum = exclusiveMaximum;
8074
+ }
8075
+ }
8076
+ if (typeof maximum === "number") {
8077
+ json.maximum = maximum;
8078
+ if (typeof exclusiveMaximum === "number" && ctx.target !== "draft-04") {
8079
+ if (exclusiveMaximum <= maximum)
8080
+ delete json.maximum;
8081
+ else
8082
+ delete json.exclusiveMaximum;
8083
+ }
8084
+ }
8085
+ if (typeof multipleOf === "number")
8086
+ json.multipleOf = multipleOf;
8087
+ };
8088
+ const booleanProcessor = (_schema, _ctx, json, _params) => {
8089
+ json.type = "boolean";
8090
+ };
8091
+ const bigintProcessor = (_schema, ctx, _json, _params) => {
8092
+ if (ctx.unrepresentable === "throw") {
8093
+ throw new Error("BigInt cannot be represented in JSON Schema");
8094
+ }
8095
+ };
8096
+ const symbolProcessor = (_schema, ctx, _json, _params) => {
8097
+ if (ctx.unrepresentable === "throw") {
8098
+ throw new Error("Symbols cannot be represented in JSON Schema");
8099
+ }
8100
+ };
8101
+ const nullProcessor = (_schema, ctx, json, _params) => {
8102
+ if (ctx.target === "openapi-3.0") {
8103
+ json.type = "string";
8104
+ json.nullable = true;
8105
+ json.enum = [null];
8106
+ }
8107
+ else {
8108
+ json.type = "null";
8109
+ }
8110
+ };
8111
+ const undefinedProcessor = (_schema, ctx, _json, _params) => {
8112
+ if (ctx.unrepresentable === "throw") {
8113
+ throw new Error("Undefined cannot be represented in JSON Schema");
8114
+ }
8115
+ };
8116
+ const voidProcessor = (_schema, ctx, _json, _params) => {
8117
+ if (ctx.unrepresentable === "throw") {
8118
+ throw new Error("Void cannot be represented in JSON Schema");
8119
+ }
8120
+ };
8121
+ const neverProcessor = (_schema, _ctx, json, _params) => {
8122
+ json.not = {};
8123
+ };
8124
+ const anyProcessor = (_schema, _ctx, _json, _params) => {
8125
+ // empty schema accepts anything
8126
+ };
8127
+ const unknownProcessor = (_schema, _ctx, _json, _params) => {
8128
+ // empty schema accepts anything
8129
+ };
8130
+ const dateProcessor = (_schema, ctx, _json, _params) => {
8131
+ if (ctx.unrepresentable === "throw") {
8132
+ throw new Error("Date cannot be represented in JSON Schema");
8133
+ }
8134
+ };
8135
+ const enumProcessor = (schema, _ctx, json, _params) => {
8136
+ const def = schema._zod.def;
8137
+ const values = getEnumValues(def.entries);
8138
+ // Number enums can have both string and number values
8139
+ if (values.every((v) => typeof v === "number"))
8140
+ json.type = "number";
8141
+ if (values.every((v) => typeof v === "string"))
8142
+ json.type = "string";
8143
+ json.enum = values;
8144
+ };
8145
+ const literalProcessor = (schema, ctx, json, _params) => {
8146
+ const def = schema._zod.def;
8147
+ const vals = [];
8148
+ for (const val of def.values) {
8149
+ if (val === undefined) {
8150
+ if (ctx.unrepresentable === "throw") {
8151
+ throw new Error("Literal `undefined` cannot be represented in JSON Schema");
8152
+ }
8153
+ }
8154
+ else if (typeof val === "bigint") {
8155
+ if (ctx.unrepresentable === "throw") {
8156
+ throw new Error("BigInt literals cannot be represented in JSON Schema");
8157
+ }
8158
+ else {
8159
+ vals.push(Number(val));
8160
+ }
8161
+ }
8162
+ else {
8163
+ vals.push(val);
8164
+ }
8165
+ }
8166
+ if (vals.length === 0) ;
8167
+ else if (vals.length === 1) {
8168
+ const val = vals[0];
8169
+ json.type = val === null ? "null" : typeof val;
8170
+ if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") {
8171
+ json.enum = [val];
8172
+ }
8173
+ else {
8174
+ json.const = val;
8175
+ }
8176
+ }
8177
+ else {
8178
+ if (vals.every((v) => typeof v === "number"))
8179
+ json.type = "number";
8180
+ if (vals.every((v) => typeof v === "string"))
8181
+ json.type = "string";
8182
+ if (vals.every((v) => typeof v === "boolean"))
8183
+ json.type = "boolean";
8184
+ if (vals.every((v) => v === null))
8185
+ json.type = "null";
8186
+ json.enum = vals;
8187
+ }
8188
+ };
8189
+ const nanProcessor = (_schema, ctx, _json, _params) => {
8190
+ if (ctx.unrepresentable === "throw") {
8191
+ throw new Error("NaN cannot be represented in JSON Schema");
8192
+ }
8193
+ };
8194
+ const templateLiteralProcessor = (schema, _ctx, json, _params) => {
8195
+ const _json = json;
8196
+ const pattern = schema._zod.pattern;
8197
+ if (!pattern)
8198
+ throw new Error("Pattern not found in template literal");
8199
+ _json.type = "string";
8200
+ _json.pattern = pattern.source;
8201
+ };
8202
+ const fileProcessor = (schema, _ctx, json, _params) => {
8203
+ const _json = json;
8204
+ const file = {
8205
+ type: "string",
8206
+ format: "binary",
8207
+ contentEncoding: "binary",
8208
+ };
8209
+ const { minimum, maximum, mime } = schema._zod.bag;
8210
+ if (minimum !== undefined)
8211
+ file.minLength = minimum;
8212
+ if (maximum !== undefined)
8213
+ file.maxLength = maximum;
8214
+ if (mime) {
8215
+ if (mime.length === 1) {
8216
+ file.contentMediaType = mime[0];
8217
+ Object.assign(_json, file);
8218
+ }
8219
+ else {
8220
+ Object.assign(_json, file); // shared props at root
8221
+ _json.anyOf = mime.map((m) => ({ contentMediaType: m })); // only contentMediaType differs
8222
+ }
8223
+ }
8224
+ else {
8225
+ Object.assign(_json, file);
8226
+ }
8227
+ };
8228
+ const successProcessor = (_schema, _ctx, json, _params) => {
8229
+ json.type = "boolean";
8230
+ };
8231
+ const customProcessor = (_schema, ctx, _json, _params) => {
8232
+ if (ctx.unrepresentable === "throw") {
8233
+ throw new Error("Custom types cannot be represented in JSON Schema");
8234
+ }
8235
+ };
8236
+ const functionProcessor = (_schema, ctx, _json, _params) => {
8237
+ if (ctx.unrepresentable === "throw") {
8238
+ throw new Error("Function types cannot be represented in JSON Schema");
8239
+ }
8240
+ };
8241
+ const transformProcessor = (_schema, ctx, _json, _params) => {
8242
+ if (ctx.unrepresentable === "throw") {
8243
+ throw new Error("Transforms cannot be represented in JSON Schema");
8244
+ }
8245
+ };
8246
+ const mapProcessor = (_schema, ctx, _json, _params) => {
8247
+ if (ctx.unrepresentable === "throw") {
8248
+ throw new Error("Map cannot be represented in JSON Schema");
8249
+ }
8250
+ };
8251
+ const setProcessor = (_schema, ctx, _json, _params) => {
8252
+ if (ctx.unrepresentable === "throw") {
8253
+ throw new Error("Set cannot be represented in JSON Schema");
8254
+ }
8255
+ };
8256
+ // ==================== COMPOSITE TYPE PROCESSORS ====================
8257
+ const arrayProcessor = (schema, ctx, _json, params) => {
8258
+ const json = _json;
8259
+ const def = schema._zod.def;
8260
+ const { minimum, maximum } = schema._zod.bag;
8261
+ if (typeof minimum === "number")
8262
+ json.minItems = minimum;
8263
+ if (typeof maximum === "number")
8264
+ json.maxItems = maximum;
8265
+ json.type = "array";
8266
+ json.items = process$1(def.element, ctx, { ...params, path: [...params.path, "items"] });
8267
+ };
8268
+ const objectProcessor = (schema, ctx, _json, params) => {
8269
+ const json = _json;
8270
+ const def = schema._zod.def;
8271
+ json.type = "object";
8272
+ json.properties = {};
8273
+ const shape = def.shape;
8274
+ for (const key in shape) {
8275
+ json.properties[key] = process$1(shape[key], ctx, {
8276
+ ...params,
8277
+ path: [...params.path, "properties", key],
8278
+ });
8279
+ }
8280
+ // required keys
8281
+ const allKeys = new Set(Object.keys(shape));
8282
+ const requiredKeys = new Set([...allKeys].filter((key) => {
8283
+ const v = def.shape[key]._zod;
8284
+ if (ctx.io === "input") {
8285
+ return v.optin === undefined;
8286
+ }
8287
+ else {
8288
+ return v.optout === undefined;
8289
+ }
8290
+ }));
8291
+ if (requiredKeys.size > 0) {
8292
+ json.required = Array.from(requiredKeys);
8293
+ }
8294
+ // catchall
8295
+ if (def.catchall?._zod.def.type === "never") {
8296
+ // strict
8297
+ json.additionalProperties = false;
8298
+ }
8299
+ else if (!def.catchall) {
8300
+ // regular
8301
+ if (ctx.io === "output")
8302
+ json.additionalProperties = false;
8303
+ }
8304
+ else if (def.catchall) {
8305
+ json.additionalProperties = process$1(def.catchall, ctx, {
8306
+ ...params,
8307
+ path: [...params.path, "additionalProperties"],
8308
+ });
8309
+ }
8310
+ };
8311
+ const unionProcessor = (schema, ctx, json, params) => {
8312
+ const def = schema._zod.def;
8313
+ // Exclusive unions (inclusive === false) use oneOf (exactly one match) instead of anyOf (one or more matches)
8314
+ // This includes both z.xor() and discriminated unions
8315
+ const isExclusive = def.inclusive === false;
8316
+ const options = def.options.map((x, i) => process$1(x, ctx, {
8317
+ ...params,
8318
+ path: [...params.path, isExclusive ? "oneOf" : "anyOf", i],
8319
+ }));
8320
+ if (isExclusive) {
8321
+ json.oneOf = options;
8322
+ }
8323
+ else {
8324
+ json.anyOf = options;
8325
+ }
8326
+ };
8327
+ const intersectionProcessor = (schema, ctx, json, params) => {
8328
+ const def = schema._zod.def;
8329
+ const a = process$1(def.left, ctx, {
8330
+ ...params,
8331
+ path: [...params.path, "allOf", 0],
8332
+ });
8333
+ const b = process$1(def.right, ctx, {
8334
+ ...params,
8335
+ path: [...params.path, "allOf", 1],
8336
+ });
8337
+ const isSimpleIntersection = (val) => "allOf" in val && Object.keys(val).length === 1;
8338
+ const allOf = [
8339
+ ...(isSimpleIntersection(a) ? a.allOf : [a]),
8340
+ ...(isSimpleIntersection(b) ? b.allOf : [b]),
8341
+ ];
8342
+ json.allOf = allOf;
8343
+ };
8344
+ const tupleProcessor = (schema, ctx, _json, params) => {
8345
+ const json = _json;
8346
+ const def = schema._zod.def;
8347
+ json.type = "array";
8348
+ const prefixPath = ctx.target === "draft-2020-12" ? "prefixItems" : "items";
8349
+ const restPath = ctx.target === "draft-2020-12" ? "items" : ctx.target === "openapi-3.0" ? "items" : "additionalItems";
8350
+ const prefixItems = def.items.map((x, i) => process$1(x, ctx, {
8351
+ ...params,
8352
+ path: [...params.path, prefixPath, i],
8353
+ }));
8354
+ const rest = def.rest
8355
+ ? process$1(def.rest, ctx, {
8356
+ ...params,
8357
+ path: [...params.path, restPath, ...(ctx.target === "openapi-3.0" ? [def.items.length] : [])],
8358
+ })
8359
+ : null;
8360
+ if (ctx.target === "draft-2020-12") {
8361
+ json.prefixItems = prefixItems;
8362
+ if (rest) {
8363
+ json.items = rest;
8364
+ }
8365
+ }
8366
+ else if (ctx.target === "openapi-3.0") {
8367
+ json.items = {
8368
+ anyOf: prefixItems,
8369
+ };
8370
+ if (rest) {
8371
+ json.items.anyOf.push(rest);
8372
+ }
8373
+ json.minItems = prefixItems.length;
8374
+ if (!rest) {
8375
+ json.maxItems = prefixItems.length;
8376
+ }
8377
+ }
8378
+ else {
8379
+ json.items = prefixItems;
8380
+ if (rest) {
8381
+ json.additionalItems = rest;
8382
+ }
8383
+ }
8384
+ // length
8385
+ const { minimum, maximum } = schema._zod.bag;
8386
+ if (typeof minimum === "number")
8387
+ json.minItems = minimum;
8388
+ if (typeof maximum === "number")
8389
+ json.maxItems = maximum;
8390
+ };
8391
+ const recordProcessor = (schema, ctx, _json, params) => {
8392
+ const json = _json;
8393
+ const def = schema._zod.def;
8394
+ json.type = "object";
8395
+ // For looseRecord with regex patterns, use patternProperties
8396
+ // This correctly represents "only validate keys matching the pattern" semantics
8397
+ // and composes well with allOf (intersections)
8398
+ const keyType = def.keyType;
8399
+ const keyBag = keyType._zod.bag;
8400
+ const patterns = keyBag?.patterns;
8401
+ if (def.mode === "loose" && patterns && patterns.size > 0) {
8402
+ // Use patternProperties for looseRecord with regex patterns
8403
+ const valueSchema = process$1(def.valueType, ctx, {
8404
+ ...params,
8405
+ path: [...params.path, "patternProperties", "*"],
8406
+ });
8407
+ json.patternProperties = {};
8408
+ for (const pattern of patterns) {
8409
+ json.patternProperties[pattern.source] = valueSchema;
8410
+ }
8411
+ }
8412
+ else {
8413
+ // Default behavior: use propertyNames + additionalProperties
8414
+ if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") {
8415
+ json.propertyNames = process$1(def.keyType, ctx, {
8416
+ ...params,
8417
+ path: [...params.path, "propertyNames"],
8418
+ });
8419
+ }
8420
+ json.additionalProperties = process$1(def.valueType, ctx, {
8421
+ ...params,
8422
+ path: [...params.path, "additionalProperties"],
8423
+ });
8424
+ }
8425
+ // Add required for keys with discrete values (enum, literal, etc.)
8426
+ const keyValues = keyType._zod.values;
8427
+ if (keyValues) {
8428
+ const validKeyValues = [...keyValues].filter((v) => typeof v === "string" || typeof v === "number");
8429
+ if (validKeyValues.length > 0) {
8430
+ json.required = validKeyValues;
8431
+ }
8432
+ }
8433
+ };
8434
+ const nullableProcessor = (schema, ctx, json, params) => {
8435
+ const def = schema._zod.def;
8436
+ const inner = process$1(def.innerType, ctx, params);
8437
+ const seen = ctx.seen.get(schema);
8438
+ if (ctx.target === "openapi-3.0") {
8439
+ seen.ref = def.innerType;
8440
+ json.nullable = true;
8441
+ }
8442
+ else {
8443
+ json.anyOf = [inner, { type: "null" }];
8444
+ }
8445
+ };
8446
+ const nonoptionalProcessor = (schema, ctx, _json, params) => {
8447
+ const def = schema._zod.def;
8448
+ process$1(def.innerType, ctx, params);
8449
+ const seen = ctx.seen.get(schema);
8450
+ seen.ref = def.innerType;
8451
+ };
8452
+ const defaultProcessor = (schema, ctx, json, params) => {
8453
+ const def = schema._zod.def;
8454
+ process$1(def.innerType, ctx, params);
8455
+ const seen = ctx.seen.get(schema);
8456
+ seen.ref = def.innerType;
8457
+ json.default = JSON.parse(JSON.stringify(def.defaultValue));
8458
+ };
8459
+ const prefaultProcessor = (schema, ctx, json, params) => {
8460
+ const def = schema._zod.def;
8461
+ process$1(def.innerType, ctx, params);
8462
+ const seen = ctx.seen.get(schema);
8463
+ seen.ref = def.innerType;
8464
+ if (ctx.io === "input")
8465
+ json._prefault = JSON.parse(JSON.stringify(def.defaultValue));
8466
+ };
8467
+ const catchProcessor = (schema, ctx, json, params) => {
8468
+ const def = schema._zod.def;
8469
+ process$1(def.innerType, ctx, params);
8470
+ const seen = ctx.seen.get(schema);
8471
+ seen.ref = def.innerType;
8472
+ let catchValue;
8473
+ try {
8474
+ catchValue = def.catchValue(undefined);
8475
+ }
8476
+ catch {
8477
+ throw new Error("Dynamic catch values are not supported in JSON Schema");
8478
+ }
8479
+ json.default = catchValue;
8480
+ };
8481
+ const pipeProcessor = (schema, ctx, _json, params) => {
8482
+ const def = schema._zod.def;
8483
+ const innerType = ctx.io === "input" ? (def.in._zod.def.type === "transform" ? def.out : def.in) : def.out;
8484
+ process$1(innerType, ctx, params);
8485
+ const seen = ctx.seen.get(schema);
8486
+ seen.ref = innerType;
8487
+ };
8488
+ const readonlyProcessor = (schema, ctx, json, params) => {
8489
+ const def = schema._zod.def;
8490
+ process$1(def.innerType, ctx, params);
8491
+ const seen = ctx.seen.get(schema);
8492
+ seen.ref = def.innerType;
8493
+ json.readOnly = true;
8494
+ };
8495
+ const promiseProcessor = (schema, ctx, _json, params) => {
8496
+ const def = schema._zod.def;
8497
+ process$1(def.innerType, ctx, params);
8498
+ const seen = ctx.seen.get(schema);
8499
+ seen.ref = def.innerType;
8500
+ };
8501
+ const optionalProcessor = (schema, ctx, _json, params) => {
8502
+ const def = schema._zod.def;
8503
+ process$1(def.innerType, ctx, params);
8504
+ const seen = ctx.seen.get(schema);
8505
+ seen.ref = def.innerType;
8506
+ };
8507
+ const lazyProcessor = (schema, ctx, _json, params) => {
8508
+ const innerType = schema._zod.innerType;
8509
+ process$1(innerType, ctx, params);
8510
+ const seen = ctx.seen.get(schema);
8511
+ seen.ref = innerType;
8512
+ };
8513
+ // ==================== ALL PROCESSORS ====================
8514
+ const allProcessors = {
8515
+ string: stringProcessor,
8516
+ number: numberProcessor,
8517
+ boolean: booleanProcessor,
8518
+ bigint: bigintProcessor,
8519
+ symbol: symbolProcessor,
8520
+ null: nullProcessor,
8521
+ undefined: undefinedProcessor,
8522
+ void: voidProcessor,
8523
+ never: neverProcessor,
8524
+ any: anyProcessor,
8525
+ unknown: unknownProcessor,
8526
+ date: dateProcessor,
8527
+ enum: enumProcessor,
8528
+ literal: literalProcessor,
8529
+ nan: nanProcessor,
8530
+ template_literal: templateLiteralProcessor,
8531
+ file: fileProcessor,
8532
+ success: successProcessor,
8533
+ custom: customProcessor,
8534
+ function: functionProcessor,
8535
+ transform: transformProcessor,
8536
+ map: mapProcessor,
8537
+ set: setProcessor,
8538
+ array: arrayProcessor,
8539
+ object: objectProcessor,
8540
+ union: unionProcessor,
8541
+ intersection: intersectionProcessor,
8542
+ tuple: tupleProcessor,
8543
+ record: recordProcessor,
8544
+ nullable: nullableProcessor,
8545
+ nonoptional: nonoptionalProcessor,
8546
+ default: defaultProcessor,
8547
+ prefault: prefaultProcessor,
8548
+ catch: catchProcessor,
8549
+ pipe: pipeProcessor,
8550
+ readonly: readonlyProcessor,
8551
+ promise: promiseProcessor,
8552
+ optional: optionalProcessor,
8553
+ lazy: lazyProcessor,
8554
+ };
8555
+ function toJSONSchema(input, params) {
8556
+ if ("_idmap" in input) {
8557
+ // Registry case
8558
+ const registry = input;
8559
+ const ctx = initializeContext({ ...params, processors: allProcessors });
8560
+ const defs = {};
8561
+ // First pass: process all schemas to build the seen map
8562
+ for (const entry of registry._idmap.entries()) {
8563
+ const [_, schema] = entry;
8564
+ process$1(schema, ctx);
8565
+ }
8566
+ const schemas = {};
8567
+ const external = {
8568
+ registry,
8569
+ uri: params?.uri,
8570
+ defs,
8571
+ };
8572
+ // Update the context with external configuration
8573
+ ctx.external = external;
8574
+ // Second pass: emit each schema
8575
+ for (const entry of registry._idmap.entries()) {
8576
+ const [key, schema] = entry;
8577
+ extractDefs(ctx, schema);
8578
+ schemas[key] = finalize(ctx, schema);
8579
+ }
8580
+ if (Object.keys(defs).length > 0) {
8581
+ const defsSegment = ctx.target === "draft-2020-12" ? "$defs" : "definitions";
8582
+ schemas.__shared = {
8583
+ [defsSegment]: defs,
8584
+ };
8585
+ }
8586
+ return { schemas };
8587
+ }
8588
+ // Single schema case
8589
+ const ctx = initializeContext({ ...params, processors: allProcessors });
8590
+ process$1(input, ctx);
8591
+ extractDefs(ctx, input);
8592
+ return finalize(ctx, input);
8593
+ }
8594
+
8595
+ const ignoreOverride = Symbol('Let zodToJsonSchema decide on which parser to use');
8596
+ const defaultOptions = {
8597
+ name: undefined,
8598
+ $refStrategy: 'root',
8599
+ effectStrategy: 'input',
8600
+ pipeStrategy: 'all',
8601
+ dateStrategy: 'format:date-time',
8602
+ mapStrategy: 'entries',
8603
+ nullableStrategy: 'from-target',
8604
+ removeAdditionalStrategy: 'passthrough',
8605
+ definitionPath: 'definitions',
8606
+ target: 'jsonSchema7',
8607
+ strictUnions: false,
8608
+ errorMessages: false,
8609
+ markdownDescription: false,
8610
+ patternStrategy: 'escape',
8611
+ applyRegexFlags: false,
8612
+ emailStrategy: 'format:email',
8613
+ base64Strategy: 'contentEncoding:base64',
8614
+ nameStrategy: 'ref',
8615
+ };
8616
+ const getDefaultOptions = (options) => {
8617
+ // We need to add `definitions` here as we may mutate it
8618
+ return (typeof options === 'string' ?
8619
+ {
8620
+ ...defaultOptions,
8621
+ basePath: ['#'],
8622
+ definitions: {},
8623
+ name: options,
8624
+ }
8625
+ : {
8626
+ ...defaultOptions,
8627
+ basePath: ['#'],
8628
+ definitions: {},
8629
+ ...options,
8630
+ });
8631
+ };
8632
+
8633
+ const zodDef = (zodSchema) => {
8634
+ return '_def' in zodSchema ? zodSchema._def : zodSchema;
8635
+ };
8636
+ function isEmptyObj(obj) {
8637
+ if (!obj)
8638
+ return true;
8639
+ for (const _k in obj)
8640
+ return false;
8641
+ return true;
8642
+ }
8643
+
8644
+ const getRefs = (options) => {
8645
+ const _options = getDefaultOptions(options);
8646
+ const currentPath = _options.name !== undefined ?
8647
+ [..._options.basePath, _options.definitionPath, _options.name]
8648
+ : _options.basePath;
8649
+ return {
8650
+ ..._options,
8651
+ currentPath: currentPath,
8652
+ propertyPath: undefined,
8653
+ seenRefs: new Set(),
8654
+ seen: new Map(Object.entries(_options.definitions).map(([name, def]) => [
8655
+ zodDef(def),
8656
+ {
8657
+ def: zodDef(def),
8658
+ path: [..._options.basePath, _options.definitionPath, name],
8659
+ // Resolution of references will be forced even though seen, so it's ok that the schema is undefined here for now.
8660
+ jsonSchema: undefined,
8661
+ },
8662
+ ])),
8663
+ };
8664
+ };
8665
+
8666
+ function addErrorMessage(res, key, errorMessage, refs) {
8667
+ if (!refs?.errorMessages)
8668
+ return;
8669
+ if (errorMessage) {
8670
+ res.errorMessage = {
8671
+ ...res.errorMessage,
8672
+ [key]: errorMessage,
8673
+ };
8674
+ }
8675
+ }
8676
+ function setResponseValueAndErrors(res, key, value, errorMessage, refs) {
8677
+ res[key] = value;
8678
+ addErrorMessage(res, key, errorMessage, refs);
8679
+ }
8680
+
8681
+ var util;
8682
+ (function (util) {
8683
+ util.assertEqual = (_) => { };
8684
+ function assertIs(_arg) { }
8685
+ util.assertIs = assertIs;
8686
+ function assertNever(_x) {
8687
+ throw new Error();
8688
+ }
8689
+ util.assertNever = assertNever;
8690
+ util.arrayToEnum = (items) => {
8691
+ const obj = {};
8692
+ for (const item of items) {
8693
+ obj[item] = item;
8694
+ }
8695
+ return obj;
8696
+ };
8697
+ util.getValidEnumValues = (obj) => {
8698
+ const validKeys = util.objectKeys(obj).filter((k) => typeof obj[obj[k]] !== "number");
8699
+ const filtered = {};
8700
+ for (const k of validKeys) {
8701
+ filtered[k] = obj[k];
8702
+ }
8703
+ return util.objectValues(filtered);
8704
+ };
8705
+ util.objectValues = (obj) => {
8706
+ return util.objectKeys(obj).map(function (e) {
8707
+ return obj[e];
8708
+ });
8709
+ };
8710
+ util.objectKeys = typeof Object.keys === "function" // eslint-disable-line ban/ban
8711
+ ? (obj) => Object.keys(obj) // eslint-disable-line ban/ban
8712
+ : (object) => {
8713
+ const keys = [];
8714
+ for (const key in object) {
8715
+ if (Object.prototype.hasOwnProperty.call(object, key)) {
8716
+ keys.push(key);
8717
+ }
8718
+ }
8719
+ return keys;
8720
+ };
8721
+ util.find = (arr, checker) => {
8722
+ for (const item of arr) {
8723
+ if (checker(item))
8724
+ return item;
8725
+ }
8726
+ return undefined;
8727
+ };
8728
+ util.isInteger = typeof Number.isInteger === "function"
8729
+ ? (val) => Number.isInteger(val) // eslint-disable-line ban/ban
8730
+ : (val) => typeof val === "number" && Number.isFinite(val) && Math.floor(val) === val;
8731
+ function joinValues(array, separator = " | ") {
8732
+ return array.map((val) => (typeof val === "string" ? `'${val}'` : val)).join(separator);
8733
+ }
8734
+ util.joinValues = joinValues;
8735
+ util.jsonStringifyReplacer = (_, value) => {
8736
+ if (typeof value === "bigint") {
8737
+ return value.toString();
8738
+ }
8739
+ return value;
8740
+ };
8741
+ })(util || (util = {}));
8742
+ var objectUtil;
8743
+ (function (objectUtil) {
8744
+ objectUtil.mergeShapes = (first, second) => {
8745
+ return {
8746
+ ...first,
8747
+ ...second, // second overwrites first
8748
+ };
8749
+ };
8750
+ })(objectUtil || (objectUtil = {}));
8751
+ util.arrayToEnum([
8752
+ "string",
8753
+ "nan",
8754
+ "number",
8755
+ "integer",
8756
+ "float",
8757
+ "boolean",
8758
+ "date",
8759
+ "bigint",
8760
+ "symbol",
8761
+ "function",
8762
+ "undefined",
8763
+ "null",
8764
+ "array",
8765
+ "object",
8766
+ "unknown",
8767
+ "promise",
8768
+ "void",
8769
+ "never",
8770
+ "map",
8771
+ "set",
8772
+ ]);
8773
+
8774
+ util.arrayToEnum([
8775
+ "invalid_type",
8776
+ "invalid_literal",
8777
+ "custom",
8778
+ "invalid_union",
8779
+ "invalid_union_discriminator",
8780
+ "invalid_enum_value",
8781
+ "unrecognized_keys",
8782
+ "invalid_arguments",
8783
+ "invalid_return_type",
8784
+ "invalid_date",
8785
+ "invalid_string",
8786
+ "too_small",
8787
+ "too_big",
8788
+ "invalid_intersection_types",
8789
+ "not_multiple_of",
8790
+ "not_finite",
8791
+ ]);
8792
+ class ZodError extends Error {
8793
+ get errors() {
8794
+ return this.issues;
8795
+ }
8796
+ constructor(issues) {
8797
+ super();
8798
+ this.issues = [];
8799
+ this.addIssue = (sub) => {
8800
+ this.issues = [...this.issues, sub];
8801
+ };
8802
+ this.addIssues = (subs = []) => {
8803
+ this.issues = [...this.issues, ...subs];
8804
+ };
8805
+ const actualProto = new.target.prototype;
8806
+ if (Object.setPrototypeOf) {
8807
+ // eslint-disable-next-line ban/ban
8808
+ Object.setPrototypeOf(this, actualProto);
8809
+ }
8810
+ else {
8811
+ this.__proto__ = actualProto;
8812
+ }
8813
+ this.name = "ZodError";
8814
+ this.issues = issues;
8815
+ }
8816
+ format(_mapper) {
8817
+ const mapper = _mapper ||
8818
+ function (issue) {
8819
+ return issue.message;
8820
+ };
8821
+ const fieldErrors = { _errors: [] };
8822
+ const processError = (error) => {
8823
+ for (const issue of error.issues) {
8824
+ if (issue.code === "invalid_union") {
8825
+ issue.unionErrors.map(processError);
8826
+ }
8827
+ else if (issue.code === "invalid_return_type") {
8828
+ processError(issue.returnTypeError);
8829
+ }
8830
+ else if (issue.code === "invalid_arguments") {
8831
+ processError(issue.argumentsError);
8832
+ }
8833
+ else if (issue.path.length === 0) {
8834
+ fieldErrors._errors.push(mapper(issue));
8835
+ }
8836
+ else {
8837
+ let curr = fieldErrors;
8838
+ let i = 0;
8839
+ while (i < issue.path.length) {
8840
+ const el = issue.path[i];
8841
+ const terminal = i === issue.path.length - 1;
8842
+ if (!terminal) {
8843
+ curr[el] = curr[el] || { _errors: [] };
8844
+ // if (typeof el === "string") {
8845
+ // curr[el] = curr[el] || { _errors: [] };
8846
+ // } else if (typeof el === "number") {
8847
+ // const errorArray: any = [];
8848
+ // errorArray._errors = [];
8849
+ // curr[el] = curr[el] || errorArray;
8850
+ // }
8851
+ }
8852
+ else {
8853
+ curr[el] = curr[el] || { _errors: [] };
8854
+ curr[el]._errors.push(mapper(issue));
8855
+ }
8856
+ curr = curr[el];
8857
+ i++;
8858
+ }
8859
+ }
8860
+ }
8861
+ };
8862
+ processError(this);
8863
+ return fieldErrors;
8864
+ }
8865
+ static assert(value) {
8866
+ if (!(value instanceof ZodError)) {
8867
+ throw new Error(`Not a ZodError: ${value}`);
8868
+ }
8869
+ }
8870
+ toString() {
8871
+ return this.message;
8872
+ }
8873
+ get message() {
8874
+ return JSON.stringify(this.issues, util.jsonStringifyReplacer, 2);
8875
+ }
8876
+ get isEmpty() {
8877
+ return this.issues.length === 0;
8878
+ }
8879
+ flatten(mapper = (issue) => issue.message) {
8880
+ const fieldErrors = Object.create(null);
8881
+ const formErrors = [];
8882
+ for (const sub of this.issues) {
8883
+ if (sub.path.length > 0) {
8884
+ const firstEl = sub.path[0];
8885
+ fieldErrors[firstEl] = fieldErrors[firstEl] || [];
8886
+ fieldErrors[firstEl].push(mapper(sub));
8887
+ }
8888
+ else {
8889
+ formErrors.push(mapper(sub));
8890
+ }
8891
+ }
8892
+ return { formErrors, fieldErrors };
8893
+ }
8894
+ get formErrors() {
8895
+ return this.flatten();
8896
+ }
8897
+ }
8898
+ ZodError.create = (issues) => {
8899
+ const error = new ZodError(issues);
8900
+ return error;
8901
+ };
8902
+
8903
+ var errorUtil;
8904
+ (function (errorUtil) {
8905
+ errorUtil.errToObj = (message) => typeof message === "string" ? { message } : message || {};
8906
+ // biome-ignore lint:
8907
+ errorUtil.toString = (message) => typeof message === "string" ? message : message?.message;
8908
+ })(errorUtil || (errorUtil = {}));
8909
+
8910
+ var ZodFirstPartyTypeKind;
8911
+ (function (ZodFirstPartyTypeKind) {
8912
+ ZodFirstPartyTypeKind["ZodString"] = "ZodString";
8913
+ ZodFirstPartyTypeKind["ZodNumber"] = "ZodNumber";
8914
+ ZodFirstPartyTypeKind["ZodNaN"] = "ZodNaN";
8915
+ ZodFirstPartyTypeKind["ZodBigInt"] = "ZodBigInt";
8916
+ ZodFirstPartyTypeKind["ZodBoolean"] = "ZodBoolean";
8917
+ ZodFirstPartyTypeKind["ZodDate"] = "ZodDate";
8918
+ ZodFirstPartyTypeKind["ZodSymbol"] = "ZodSymbol";
8919
+ ZodFirstPartyTypeKind["ZodUndefined"] = "ZodUndefined";
8920
+ ZodFirstPartyTypeKind["ZodNull"] = "ZodNull";
8921
+ ZodFirstPartyTypeKind["ZodAny"] = "ZodAny";
8922
+ ZodFirstPartyTypeKind["ZodUnknown"] = "ZodUnknown";
8923
+ ZodFirstPartyTypeKind["ZodNever"] = "ZodNever";
8924
+ ZodFirstPartyTypeKind["ZodVoid"] = "ZodVoid";
8925
+ ZodFirstPartyTypeKind["ZodArray"] = "ZodArray";
8926
+ ZodFirstPartyTypeKind["ZodObject"] = "ZodObject";
8927
+ ZodFirstPartyTypeKind["ZodUnion"] = "ZodUnion";
8928
+ ZodFirstPartyTypeKind["ZodDiscriminatedUnion"] = "ZodDiscriminatedUnion";
8929
+ ZodFirstPartyTypeKind["ZodIntersection"] = "ZodIntersection";
8930
+ ZodFirstPartyTypeKind["ZodTuple"] = "ZodTuple";
8931
+ ZodFirstPartyTypeKind["ZodRecord"] = "ZodRecord";
8932
+ ZodFirstPartyTypeKind["ZodMap"] = "ZodMap";
8933
+ ZodFirstPartyTypeKind["ZodSet"] = "ZodSet";
8934
+ ZodFirstPartyTypeKind["ZodFunction"] = "ZodFunction";
8935
+ ZodFirstPartyTypeKind["ZodLazy"] = "ZodLazy";
8936
+ ZodFirstPartyTypeKind["ZodLiteral"] = "ZodLiteral";
8937
+ ZodFirstPartyTypeKind["ZodEnum"] = "ZodEnum";
8938
+ ZodFirstPartyTypeKind["ZodEffects"] = "ZodEffects";
8939
+ ZodFirstPartyTypeKind["ZodNativeEnum"] = "ZodNativeEnum";
8940
+ ZodFirstPartyTypeKind["ZodOptional"] = "ZodOptional";
8941
+ ZodFirstPartyTypeKind["ZodNullable"] = "ZodNullable";
8942
+ ZodFirstPartyTypeKind["ZodDefault"] = "ZodDefault";
8943
+ ZodFirstPartyTypeKind["ZodCatch"] = "ZodCatch";
8944
+ ZodFirstPartyTypeKind["ZodPromise"] = "ZodPromise";
8945
+ ZodFirstPartyTypeKind["ZodBranded"] = "ZodBranded";
8946
+ ZodFirstPartyTypeKind["ZodPipeline"] = "ZodPipeline";
8947
+ ZodFirstPartyTypeKind["ZodReadonly"] = "ZodReadonly";
8948
+ })(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));
8949
+
8950
+ function parseAnyDef() {
8951
+ return {};
8952
+ }
8953
+
8954
+ function parseArrayDef(def, refs) {
8955
+ const res = {
8956
+ type: 'array',
8957
+ };
8958
+ if (def.type?._def?.typeName !== ZodFirstPartyTypeKind.ZodAny) {
8959
+ res.items = parseDef(def.type._def, {
8960
+ ...refs,
8961
+ currentPath: [...refs.currentPath, 'items'],
8962
+ });
8963
+ }
8964
+ if (def.minLength) {
8965
+ setResponseValueAndErrors(res, 'minItems', def.minLength.value, def.minLength.message, refs);
8966
+ }
8967
+ if (def.maxLength) {
8968
+ setResponseValueAndErrors(res, 'maxItems', def.maxLength.value, def.maxLength.message, refs);
8969
+ }
8970
+ if (def.exactLength) {
8971
+ setResponseValueAndErrors(res, 'minItems', def.exactLength.value, def.exactLength.message, refs);
8972
+ setResponseValueAndErrors(res, 'maxItems', def.exactLength.value, def.exactLength.message, refs);
8973
+ }
8974
+ return res;
8975
+ }
8976
+
8977
+ function parseBigintDef(def, refs) {
8978
+ const res = {
8979
+ type: 'integer',
8980
+ format: 'int64',
8981
+ };
8982
+ if (!def.checks)
8983
+ return res;
8984
+ for (const check of def.checks) {
8985
+ switch (check.kind) {
8986
+ case 'min':
8987
+ if (refs.target === 'jsonSchema7') {
8988
+ if (check.inclusive) {
8989
+ setResponseValueAndErrors(res, 'minimum', check.value, check.message, refs);
8990
+ }
8991
+ else {
8992
+ setResponseValueAndErrors(res, 'exclusiveMinimum', check.value, check.message, refs);
8993
+ }
8994
+ }
8995
+ else {
8996
+ if (!check.inclusive) {
8997
+ res.exclusiveMinimum = true;
8998
+ }
8999
+ setResponseValueAndErrors(res, 'minimum', check.value, check.message, refs);
9000
+ }
9001
+ break;
9002
+ case 'max':
9003
+ if (refs.target === 'jsonSchema7') {
9004
+ if (check.inclusive) {
9005
+ setResponseValueAndErrors(res, 'maximum', check.value, check.message, refs);
9006
+ }
9007
+ else {
9008
+ setResponseValueAndErrors(res, 'exclusiveMaximum', check.value, check.message, refs);
9009
+ }
9010
+ }
9011
+ else {
9012
+ if (!check.inclusive) {
9013
+ res.exclusiveMaximum = true;
9014
+ }
9015
+ setResponseValueAndErrors(res, 'maximum', check.value, check.message, refs);
9016
+ }
9017
+ break;
9018
+ case 'multipleOf':
9019
+ setResponseValueAndErrors(res, 'multipleOf', check.value, check.message, refs);
9020
+ break;
9021
+ }
9022
+ }
9023
+ return res;
9024
+ }
9025
+
9026
+ function parseBooleanDef() {
9027
+ return {
9028
+ type: 'boolean',
9029
+ };
9030
+ }
9031
+
9032
+ function parseBrandedDef(_def, refs) {
9033
+ return parseDef(_def.type._def, refs);
9034
+ }
9035
+
9036
+ const parseCatchDef = (def, refs) => {
9037
+ return parseDef(def.innerType._def, refs);
9038
+ };
9039
+
9040
+ function parseDateDef(def, refs, overrideDateStrategy) {
9041
+ const strategy = overrideDateStrategy ?? refs.dateStrategy;
9042
+ if (Array.isArray(strategy)) {
9043
+ return {
9044
+ anyOf: strategy.map((item, i) => parseDateDef(def, refs, item)),
9045
+ };
9046
+ }
9047
+ switch (strategy) {
9048
+ case 'string':
9049
+ case 'format:date-time':
9050
+ return {
9051
+ type: 'string',
9052
+ format: 'date-time',
9053
+ };
9054
+ case 'format:date':
9055
+ return {
9056
+ type: 'string',
9057
+ format: 'date',
9058
+ };
9059
+ case 'integer':
9060
+ return integerDateParser(def, refs);
9061
+ }
9062
+ }
9063
+ const integerDateParser = (def, refs) => {
9064
+ const res = {
9065
+ type: 'integer',
9066
+ format: 'unix-time',
9067
+ };
9068
+ if (refs.target === 'openApi3') {
9069
+ return res;
9070
+ }
9071
+ for (const check of def.checks) {
9072
+ switch (check.kind) {
9073
+ case 'min':
9074
+ setResponseValueAndErrors(res, 'minimum', check.value, // This is in milliseconds
9075
+ check.message, refs);
9076
+ break;
9077
+ case 'max':
9078
+ setResponseValueAndErrors(res, 'maximum', check.value, // This is in milliseconds
9079
+ check.message, refs);
9080
+ break;
9081
+ }
9082
+ }
9083
+ return res;
9084
+ };
9085
+
9086
+ function parseDefaultDef(_def, refs) {
9087
+ return {
9088
+ ...parseDef(_def.innerType._def, refs),
9089
+ default: _def.defaultValue(),
9090
+ };
9091
+ }
9092
+
9093
+ function parseEffectsDef(_def, refs, forceResolution) {
9094
+ return refs.effectStrategy === 'input' ? parseDef(_def.schema._def, refs, forceResolution) : {};
9095
+ }
9096
+
9097
+ function parseEnumDef(def) {
9098
+ return {
9099
+ type: 'string',
9100
+ enum: [...def.values],
9101
+ };
9102
+ }
9103
+
9104
+ const isJsonSchema7AllOfType = (type) => {
9105
+ if ('type' in type && type.type === 'string')
9106
+ return false;
9107
+ return 'allOf' in type;
9108
+ };
9109
+ function parseIntersectionDef(def, refs) {
9110
+ const allOf = [
9111
+ parseDef(def.left._def, {
9112
+ ...refs,
9113
+ currentPath: [...refs.currentPath, 'allOf', '0'],
9114
+ }),
9115
+ parseDef(def.right._def, {
9116
+ ...refs,
9117
+ currentPath: [...refs.currentPath, 'allOf', '1'],
9118
+ }),
9119
+ ].filter((x) => !!x);
9120
+ let unevaluatedProperties = refs.target === 'jsonSchema2019-09' ? { unevaluatedProperties: false } : undefined;
9121
+ const mergedAllOf = [];
9122
+ // If either of the schemas is an allOf, merge them into a single allOf
9123
+ allOf.forEach((schema) => {
9124
+ if (isJsonSchema7AllOfType(schema)) {
9125
+ mergedAllOf.push(...schema.allOf);
9126
+ if (schema.unevaluatedProperties === undefined) {
9127
+ // If one of the schemas has no unevaluatedProperties set,
9128
+ // the merged schema should also have no unevaluatedProperties set
9129
+ unevaluatedProperties = undefined;
9130
+ }
9131
+ }
9132
+ else {
9133
+ let nestedSchema = schema;
9134
+ if ('additionalProperties' in schema && schema.additionalProperties === false) {
9135
+ const { additionalProperties, ...rest } = schema;
9136
+ nestedSchema = rest;
9137
+ }
9138
+ else {
9139
+ // As soon as one of the schemas has additionalProperties set not to false, we allow unevaluatedProperties
9140
+ unevaluatedProperties = undefined;
9141
+ }
9142
+ mergedAllOf.push(nestedSchema);
9143
+ }
9144
+ });
9145
+ return mergedAllOf.length ?
9146
+ {
9147
+ allOf: mergedAllOf,
9148
+ ...unevaluatedProperties,
9149
+ }
9150
+ : undefined;
9151
+ }
9152
+
9153
+ function parseLiteralDef(def, refs) {
9154
+ const parsedType = typeof def.value;
9155
+ if (parsedType !== 'bigint' &&
9156
+ parsedType !== 'number' &&
9157
+ parsedType !== 'boolean' &&
9158
+ parsedType !== 'string') {
9159
+ return {
9160
+ type: Array.isArray(def.value) ? 'array' : 'object',
9161
+ };
9162
+ }
9163
+ if (refs.target === 'openApi3') {
9164
+ return {
9165
+ type: parsedType === 'bigint' ? 'integer' : parsedType,
9166
+ enum: [def.value],
9167
+ };
9168
+ }
9169
+ return {
9170
+ type: parsedType === 'bigint' ? 'integer' : parsedType,
9171
+ const: def.value,
9172
+ };
9173
+ }
9174
+
9175
+ let emojiRegex;
9176
+ /**
9177
+ * Generated from the regular expressions found here as of 2024-05-22:
9178
+ * https://github.com/colinhacks/zod/blob/master/src/types.ts.
9179
+ *
9180
+ * Expressions with /i flag have been changed accordingly.
9181
+ */
9182
+ const zodPatterns = {
9183
+ /**
9184
+ * `c` was changed to `[cC]` to replicate /i flag
9185
+ */
9186
+ cuid: /^[cC][^\s-]{8,}$/,
9187
+ cuid2: /^[0-9a-z]+$/,
9188
+ ulid: /^[0-9A-HJKMNP-TV-Z]{26}$/,
9189
+ /**
9190
+ * `a-z` was added to replicate /i flag
9191
+ */
9192
+ email: /^(?!\.)(?!.*\.\.)([a-zA-Z0-9_'+\-\.]*)[a-zA-Z0-9_+-]@([a-zA-Z0-9][a-zA-Z0-9\-]*\.)+[a-zA-Z]{2,}$/,
9193
+ /**
9194
+ * Constructed a valid Unicode RegExp
9195
+ *
9196
+ * Lazily instantiate since this type of regex isn't supported
9197
+ * in all envs (e.g. React Native).
9198
+ *
9199
+ * See:
9200
+ * https://github.com/colinhacks/zod/issues/2433
9201
+ * Fix in Zod:
9202
+ * https://github.com/colinhacks/zod/commit/9340fd51e48576a75adc919bff65dbc4a5d4c99b
9203
+ */
9204
+ emoji: () => {
9205
+ if (emojiRegex === undefined) {
9206
+ emojiRegex = RegExp('^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$', 'u');
9207
+ }
9208
+ return emojiRegex;
9209
+ },
9210
+ base64: /^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$/,
9211
+ nanoid: /^[a-zA-Z0-9_-]{21}$/,
9212
+ };
9213
+ function parseStringDef(def, refs) {
9214
+ const res = {
9215
+ type: 'string',
9216
+ };
9217
+ function processPattern(value) {
9218
+ return refs.patternStrategy === 'escape' ? escapeNonAlphaNumeric(value) : value;
9219
+ }
9220
+ if (def.checks) {
9221
+ for (const check of def.checks) {
9222
+ switch (check.kind) {
9223
+ case 'min':
9224
+ setResponseValueAndErrors(res, 'minLength', typeof res.minLength === 'number' ? Math.max(res.minLength, check.value) : check.value, check.message, refs);
9225
+ break;
9226
+ case 'max':
9227
+ setResponseValueAndErrors(res, 'maxLength', typeof res.maxLength === 'number' ? Math.min(res.maxLength, check.value) : check.value, check.message, refs);
9228
+ break;
9229
+ case 'email':
9230
+ switch (refs.emailStrategy) {
9231
+ case 'format:email':
9232
+ addFormat(res, 'email', check.message, refs);
9233
+ break;
9234
+ case 'format:idn-email':
9235
+ addFormat(res, 'idn-email', check.message, refs);
9236
+ break;
9237
+ case 'pattern:zod':
9238
+ addPattern(res, zodPatterns.email, check.message, refs);
9239
+ break;
9240
+ }
9241
+ break;
9242
+ case 'url':
9243
+ addFormat(res, 'uri', check.message, refs);
9244
+ break;
9245
+ case 'uuid':
9246
+ addFormat(res, 'uuid', check.message, refs);
9247
+ break;
9248
+ case 'regex':
9249
+ addPattern(res, check.regex, check.message, refs);
9250
+ break;
9251
+ case 'cuid':
9252
+ addPattern(res, zodPatterns.cuid, check.message, refs);
9253
+ break;
9254
+ case 'cuid2':
9255
+ addPattern(res, zodPatterns.cuid2, check.message, refs);
9256
+ break;
9257
+ case 'startsWith':
9258
+ addPattern(res, RegExp(`^${processPattern(check.value)}`), check.message, refs);
9259
+ break;
9260
+ case 'endsWith':
9261
+ addPattern(res, RegExp(`${processPattern(check.value)}$`), check.message, refs);
9262
+ break;
9263
+ case 'datetime':
9264
+ addFormat(res, 'date-time', check.message, refs);
9265
+ break;
9266
+ case 'date':
9267
+ addFormat(res, 'date', check.message, refs);
9268
+ break;
9269
+ case 'time':
9270
+ addFormat(res, 'time', check.message, refs);
9271
+ break;
9272
+ case 'duration':
9273
+ addFormat(res, 'duration', check.message, refs);
9274
+ break;
9275
+ case 'length':
9276
+ setResponseValueAndErrors(res, 'minLength', typeof res.minLength === 'number' ? Math.max(res.minLength, check.value) : check.value, check.message, refs);
9277
+ setResponseValueAndErrors(res, 'maxLength', typeof res.maxLength === 'number' ? Math.min(res.maxLength, check.value) : check.value, check.message, refs);
9278
+ break;
9279
+ case 'includes': {
9280
+ addPattern(res, RegExp(processPattern(check.value)), check.message, refs);
9281
+ break;
9282
+ }
9283
+ case 'ip': {
9284
+ if (check.version !== 'v6') {
9285
+ addFormat(res, 'ipv4', check.message, refs);
9286
+ }
9287
+ if (check.version !== 'v4') {
9288
+ addFormat(res, 'ipv6', check.message, refs);
9289
+ }
9290
+ break;
9291
+ }
9292
+ case 'emoji':
9293
+ addPattern(res, zodPatterns.emoji, check.message, refs);
9294
+ break;
9295
+ case 'ulid': {
9296
+ addPattern(res, zodPatterns.ulid, check.message, refs);
9297
+ break;
9298
+ }
9299
+ case 'base64': {
9300
+ switch (refs.base64Strategy) {
9301
+ case 'format:binary': {
9302
+ addFormat(res, 'binary', check.message, refs);
9303
+ break;
9304
+ }
9305
+ case 'contentEncoding:base64': {
9306
+ setResponseValueAndErrors(res, 'contentEncoding', 'base64', check.message, refs);
9307
+ break;
9308
+ }
9309
+ case 'pattern:zod': {
9310
+ addPattern(res, zodPatterns.base64, check.message, refs);
9311
+ break;
9312
+ }
9313
+ }
9314
+ break;
9315
+ }
9316
+ case 'nanoid': {
9317
+ addPattern(res, zodPatterns.nanoid, check.message, refs);
9318
+ }
9319
+ }
9320
+ }
9321
+ }
9322
+ return res;
9323
+ }
9324
+ const escapeNonAlphaNumeric = (value) => Array.from(value)
9325
+ .map((c) => (/[a-zA-Z0-9]/.test(c) ? c : `\\${c}`))
9326
+ .join('');
9327
+ const addFormat = (schema, value, message, refs) => {
9328
+ if (schema.format || schema.anyOf?.some((x) => x.format)) {
9329
+ if (!schema.anyOf) {
9330
+ schema.anyOf = [];
9331
+ }
9332
+ if (schema.format) {
9333
+ schema.anyOf.push({
9334
+ format: schema.format,
9335
+ ...(schema.errorMessage &&
9336
+ refs.errorMessages && {
9337
+ errorMessage: { format: schema.errorMessage.format },
9338
+ }),
9339
+ });
9340
+ delete schema.format;
9341
+ if (schema.errorMessage) {
9342
+ delete schema.errorMessage.format;
9343
+ if (Object.keys(schema.errorMessage).length === 0) {
9344
+ delete schema.errorMessage;
9345
+ }
9346
+ }
9347
+ }
9348
+ schema.anyOf.push({
9349
+ format: value,
9350
+ ...(message && refs.errorMessages && { errorMessage: { format: message } }),
9351
+ });
9352
+ }
9353
+ else {
9354
+ setResponseValueAndErrors(schema, 'format', value, message, refs);
9355
+ }
9356
+ };
9357
+ const addPattern = (schema, regex, message, refs) => {
9358
+ if (schema.pattern || schema.allOf?.some((x) => x.pattern)) {
9359
+ if (!schema.allOf) {
9360
+ schema.allOf = [];
9361
+ }
9362
+ if (schema.pattern) {
9363
+ schema.allOf.push({
9364
+ pattern: schema.pattern,
9365
+ ...(schema.errorMessage &&
9366
+ refs.errorMessages && {
9367
+ errorMessage: { pattern: schema.errorMessage.pattern },
9368
+ }),
9369
+ });
9370
+ delete schema.pattern;
9371
+ if (schema.errorMessage) {
9372
+ delete schema.errorMessage.pattern;
9373
+ if (Object.keys(schema.errorMessage).length === 0) {
9374
+ delete schema.errorMessage;
9375
+ }
9376
+ }
9377
+ }
9378
+ schema.allOf.push({
9379
+ pattern: processRegExp(regex, refs),
9380
+ ...(message && refs.errorMessages && { errorMessage: { pattern: message } }),
9381
+ });
9382
+ }
9383
+ else {
9384
+ setResponseValueAndErrors(schema, 'pattern', processRegExp(regex, refs), message, refs);
9385
+ }
9386
+ };
9387
+ // Mutate z.string.regex() in a best attempt to accommodate for regex flags when applyRegexFlags is true
9388
+ const processRegExp = (regexOrFunction, refs) => {
9389
+ const regex = typeof regexOrFunction === 'function' ? regexOrFunction() : regexOrFunction;
9390
+ if (!refs.applyRegexFlags || !regex.flags)
9391
+ return regex.source;
9392
+ // Currently handled flags
9393
+ const flags = {
9394
+ i: regex.flags.includes('i'), // Case-insensitive
9395
+ m: regex.flags.includes('m'), // `^` and `$` matches adjacent to newline characters
9396
+ s: regex.flags.includes('s'), // `.` matches newlines
9397
+ };
9398
+ // The general principle here is to step through each character, one at a time, applying mutations as flags require. We keep track when the current character is escaped, and when it's inside a group /like [this]/ or (also) a range like /[a-z]/. The following is fairly brittle imperative code; edit at your peril!
9399
+ const source = flags.i ? regex.source.toLowerCase() : regex.source;
9400
+ let pattern = '';
9401
+ let isEscaped = false;
9402
+ let inCharGroup = false;
9403
+ let inCharRange = false;
9404
+ for (let i = 0; i < source.length; i++) {
9405
+ if (isEscaped) {
9406
+ pattern += source[i];
9407
+ isEscaped = false;
9408
+ continue;
9409
+ }
9410
+ if (flags.i) {
9411
+ if (inCharGroup) {
9412
+ if (source[i].match(/[a-z]/)) {
9413
+ if (inCharRange) {
9414
+ pattern += source[i];
9415
+ pattern += `${source[i - 2]}-${source[i]}`.toUpperCase();
9416
+ inCharRange = false;
9417
+ }
9418
+ else if (source[i + 1] === '-' && source[i + 2]?.match(/[a-z]/)) {
9419
+ pattern += source[i];
9420
+ inCharRange = true;
9421
+ }
9422
+ else {
9423
+ pattern += `${source[i]}${source[i].toUpperCase()}`;
9424
+ }
9425
+ continue;
9426
+ }
9427
+ }
9428
+ else if (source[i].match(/[a-z]/)) {
9429
+ pattern += `[${source[i]}${source[i].toUpperCase()}]`;
9430
+ continue;
9431
+ }
9432
+ }
9433
+ if (flags.m) {
9434
+ if (source[i] === '^') {
9435
+ pattern += `(^|(?<=[\r\n]))`;
9436
+ continue;
9437
+ }
9438
+ else if (source[i] === '$') {
9439
+ pattern += `($|(?=[\r\n]))`;
9440
+ continue;
9441
+ }
9442
+ }
9443
+ if (flags.s && source[i] === '.') {
9444
+ pattern += inCharGroup ? `${source[i]}\r\n` : `[${source[i]}\r\n]`;
9445
+ continue;
9446
+ }
9447
+ pattern += source[i];
9448
+ if (source[i] === '\\') {
9449
+ isEscaped = true;
9450
+ }
9451
+ else if (inCharGroup && source[i] === ']') {
9452
+ inCharGroup = false;
9453
+ }
9454
+ else if (!inCharGroup && source[i] === '[') {
9455
+ inCharGroup = true;
9456
+ }
9457
+ }
9458
+ try {
9459
+ const regexTest = new RegExp(pattern);
9460
+ }
9461
+ catch {
9462
+ console.warn(`Could not convert regex pattern at ${refs.currentPath.join('/')} to a flag-independent form! Falling back to the flag-ignorant source`);
9463
+ return regex.source;
9464
+ }
9465
+ return pattern;
9466
+ };
9467
+
9468
+ function parseRecordDef(def, refs) {
9469
+ if (refs.target === 'openApi3' && def.keyType?._def.typeName === ZodFirstPartyTypeKind.ZodEnum) {
9470
+ return {
9471
+ type: 'object',
9472
+ required: def.keyType._def.values,
9473
+ properties: def.keyType._def.values.reduce((acc, key) => ({
9474
+ ...acc,
9475
+ [key]: parseDef(def.valueType._def, {
9476
+ ...refs,
9477
+ currentPath: [...refs.currentPath, 'properties', key],
9478
+ }) ?? {},
9479
+ }), {}),
9480
+ additionalProperties: false,
9481
+ };
9482
+ }
9483
+ const schema = {
9484
+ type: 'object',
9485
+ additionalProperties: parseDef(def.valueType._def, {
9486
+ ...refs,
9487
+ currentPath: [...refs.currentPath, 'additionalProperties'],
9488
+ }) ?? {},
9489
+ };
9490
+ if (refs.target === 'openApi3') {
9491
+ return schema;
9492
+ }
9493
+ if (def.keyType?._def.typeName === ZodFirstPartyTypeKind.ZodString && def.keyType._def.checks?.length) {
9494
+ const keyType = Object.entries(parseStringDef(def.keyType._def, refs)).reduce((acc, [key, value]) => (key === 'type' ? acc : { ...acc, [key]: value }), {});
9495
+ return {
9496
+ ...schema,
9497
+ propertyNames: keyType,
9498
+ };
9499
+ }
9500
+ else if (def.keyType?._def.typeName === ZodFirstPartyTypeKind.ZodEnum) {
9501
+ return {
9502
+ ...schema,
9503
+ propertyNames: {
9504
+ enum: def.keyType._def.values,
9505
+ },
9506
+ };
9507
+ }
9508
+ return schema;
9509
+ }
9510
+
9511
+ function parseMapDef(def, refs) {
9512
+ if (refs.mapStrategy === 'record') {
9513
+ return parseRecordDef(def, refs);
9514
+ }
9515
+ const keys = parseDef(def.keyType._def, {
9516
+ ...refs,
9517
+ currentPath: [...refs.currentPath, 'items', 'items', '0'],
9518
+ }) || {};
9519
+ const values = parseDef(def.valueType._def, {
9520
+ ...refs,
9521
+ currentPath: [...refs.currentPath, 'items', 'items', '1'],
9522
+ }) || {};
9523
+ return {
9524
+ type: 'array',
9525
+ maxItems: 125,
9526
+ items: {
9527
+ type: 'array',
9528
+ items: [keys, values],
9529
+ minItems: 2,
9530
+ maxItems: 2,
9531
+ },
9532
+ };
9533
+ }
9534
+
9535
+ function parseNativeEnumDef(def) {
9536
+ const object = def.values;
9537
+ const actualKeys = Object.keys(def.values).filter((key) => {
9538
+ return typeof object[object[key]] !== 'number';
9539
+ });
9540
+ const actualValues = actualKeys.map((key) => object[key]);
9541
+ const parsedTypes = Array.from(new Set(actualValues.map((values) => typeof values)));
9542
+ return {
9543
+ type: parsedTypes.length === 1 ?
9544
+ parsedTypes[0] === 'string' ?
9545
+ 'string'
9546
+ : 'number'
9547
+ : ['string', 'number'],
9548
+ enum: actualValues,
9549
+ };
9550
+ }
9551
+
9552
+ function parseNeverDef() {
9553
+ return {
9554
+ not: {},
9555
+ };
9556
+ }
9557
+
9558
+ function parseNullDef(refs) {
9559
+ return refs.target === 'openApi3' ?
9560
+ {
9561
+ enum: ['null'],
9562
+ nullable: true,
9563
+ }
9564
+ : {
9565
+ type: 'null',
9566
+ };
9567
+ }
9568
+
9569
+ const primitiveMappings = {
9570
+ ZodString: 'string',
9571
+ ZodNumber: 'number',
9572
+ ZodBigInt: 'integer',
9573
+ ZodBoolean: 'boolean',
9574
+ ZodNull: 'null',
9575
+ };
9576
+ function parseUnionDef(def, refs) {
9577
+ if (refs.target === 'openApi3')
9578
+ return asAnyOf(def, refs);
9579
+ const options = def.options instanceof Map ? Array.from(def.options.values()) : def.options;
9580
+ // This blocks tries to look ahead a bit to produce nicer looking schemas with type array instead of anyOf.
9581
+ if (options.every((x) => x._def.typeName in primitiveMappings && (!x._def.checks || !x._def.checks.length))) {
9582
+ // all types in union are primitive and lack checks, so might as well squash into {type: [...]}
9583
+ const types = options.reduce((types, x) => {
9584
+ const type = primitiveMappings[x._def.typeName]; //Can be safely casted due to row 43
9585
+ return type && !types.includes(type) ? [...types, type] : types;
9586
+ }, []);
9587
+ return {
9588
+ type: types.length > 1 ? types : types[0],
9589
+ };
9590
+ }
9591
+ else if (options.every((x) => x._def.typeName === 'ZodLiteral' && !x.description)) {
9592
+ // all options literals
9593
+ const types = options.reduce((acc, x) => {
9594
+ const type = typeof x._def.value;
9595
+ switch (type) {
9596
+ case 'string':
9597
+ case 'number':
9598
+ case 'boolean':
9599
+ return [...acc, type];
9600
+ case 'bigint':
9601
+ return [...acc, 'integer'];
9602
+ case 'object':
9603
+ if (x._def.value === null)
9604
+ return [...acc, 'null'];
9605
+ case 'symbol':
9606
+ case 'undefined':
9607
+ case 'function':
9608
+ default:
9609
+ return acc;
9610
+ }
9611
+ }, []);
9612
+ if (types.length === options.length) {
9613
+ // all the literals are primitive, as far as null can be considered primitive
9614
+ const uniqueTypes = types.filter((x, i, a) => a.indexOf(x) === i);
9615
+ return {
9616
+ type: uniqueTypes.length > 1 ? uniqueTypes : uniqueTypes[0],
9617
+ enum: options.reduce((acc, x) => {
9618
+ return acc.includes(x._def.value) ? acc : [...acc, x._def.value];
9619
+ }, []),
9620
+ };
9621
+ }
9622
+ }
9623
+ else if (options.every((x) => x._def.typeName === 'ZodEnum')) {
9624
+ return {
9625
+ type: 'string',
9626
+ enum: options.reduce((acc, x) => [...acc, ...x._def.values.filter((x) => !acc.includes(x))], []),
9627
+ };
9628
+ }
9629
+ return asAnyOf(def, refs);
9630
+ }
9631
+ const asAnyOf = (def, refs) => {
9632
+ const anyOf = (def.options instanceof Map ? Array.from(def.options.values()) : def.options)
9633
+ .map((x, i) => parseDef(x._def, {
9634
+ ...refs,
9635
+ currentPath: [...refs.currentPath, 'anyOf', `${i}`],
9636
+ }))
9637
+ .filter((x) => !!x && (!refs.strictUnions || (typeof x === 'object' && Object.keys(x).length > 0)));
9638
+ return anyOf.length ? { anyOf } : undefined;
9639
+ };
9640
+
9641
+ function parseNullableDef(def, refs) {
9642
+ if (['ZodString', 'ZodNumber', 'ZodBigInt', 'ZodBoolean', 'ZodNull'].includes(def.innerType._def.typeName) &&
9643
+ (!def.innerType._def.checks || !def.innerType._def.checks.length)) {
9644
+ if (refs.target === 'openApi3' || refs.nullableStrategy === 'property') {
9645
+ return {
9646
+ type: primitiveMappings[def.innerType._def.typeName],
9647
+ nullable: true,
9648
+ };
9649
+ }
9650
+ return {
9651
+ type: [primitiveMappings[def.innerType._def.typeName], 'null'],
9652
+ };
9653
+ }
9654
+ if (refs.target === 'openApi3') {
9655
+ const base = parseDef(def.innerType._def, {
9656
+ ...refs,
9657
+ currentPath: [...refs.currentPath],
9658
+ });
9659
+ if (base && '$ref' in base)
9660
+ return { allOf: [base], nullable: true };
9661
+ return base && { ...base, nullable: true };
9662
+ }
9663
+ const base = parseDef(def.innerType._def, {
9664
+ ...refs,
9665
+ currentPath: [...refs.currentPath, 'anyOf', '0'],
9666
+ });
9667
+ return base && { anyOf: [base, { type: 'null' }] };
9668
+ }
9669
+
9670
+ function parseNumberDef(def, refs) {
9671
+ const res = {
9672
+ type: 'number',
9673
+ };
9674
+ if (!def.checks)
9675
+ return res;
9676
+ for (const check of def.checks) {
9677
+ switch (check.kind) {
9678
+ case 'int':
9679
+ res.type = 'integer';
9680
+ addErrorMessage(res, 'type', check.message, refs);
9681
+ break;
9682
+ case 'min':
9683
+ if (refs.target === 'jsonSchema7') {
9684
+ if (check.inclusive) {
9685
+ setResponseValueAndErrors(res, 'minimum', check.value, check.message, refs);
9686
+ }
9687
+ else {
9688
+ setResponseValueAndErrors(res, 'exclusiveMinimum', check.value, check.message, refs);
9689
+ }
9690
+ }
9691
+ else {
9692
+ if (!check.inclusive) {
9693
+ res.exclusiveMinimum = true;
9694
+ }
9695
+ setResponseValueAndErrors(res, 'minimum', check.value, check.message, refs);
9696
+ }
9697
+ break;
9698
+ case 'max':
9699
+ if (refs.target === 'jsonSchema7') {
9700
+ if (check.inclusive) {
9701
+ setResponseValueAndErrors(res, 'maximum', check.value, check.message, refs);
9702
+ }
9703
+ else {
9704
+ setResponseValueAndErrors(res, 'exclusiveMaximum', check.value, check.message, refs);
9705
+ }
9706
+ }
9707
+ else {
9708
+ if (!check.inclusive) {
9709
+ res.exclusiveMaximum = true;
9710
+ }
9711
+ setResponseValueAndErrors(res, 'maximum', check.value, check.message, refs);
9712
+ }
9713
+ break;
9714
+ case 'multipleOf':
9715
+ setResponseValueAndErrors(res, 'multipleOf', check.value, check.message, refs);
9716
+ break;
9717
+ }
9718
+ }
9719
+ return res;
9720
+ }
9721
+
9722
+ function decideAdditionalProperties(def, refs) {
9723
+ if (refs.removeAdditionalStrategy === 'strict') {
9724
+ return def.catchall._def.typeName === 'ZodNever' ?
9725
+ def.unknownKeys !== 'strict'
9726
+ : parseDef(def.catchall._def, {
9727
+ ...refs,
9728
+ currentPath: [...refs.currentPath, 'additionalProperties'],
9729
+ }) ?? true;
9730
+ }
9731
+ else {
9732
+ return def.catchall._def.typeName === 'ZodNever' ?
9733
+ def.unknownKeys === 'passthrough'
9734
+ : parseDef(def.catchall._def, {
9735
+ ...refs,
9736
+ currentPath: [...refs.currentPath, 'additionalProperties'],
9737
+ }) ?? true;
9738
+ }
9739
+ }
9740
+ function parseObjectDef(def, refs) {
9741
+ const result = {
9742
+ type: 'object',
9743
+ ...Object.entries(def.shape()).reduce((acc, [propName, propDef]) => {
9744
+ if (propDef === undefined || propDef._def === undefined)
9745
+ return acc;
9746
+ const propertyPath = [...refs.currentPath, 'properties', propName];
9747
+ const parsedDef = parseDef(propDef._def, {
9748
+ ...refs,
9749
+ currentPath: propertyPath,
9750
+ propertyPath,
9751
+ });
9752
+ if (parsedDef === undefined)
9753
+ return acc;
9754
+ if (refs.openaiStrictMode &&
9755
+ propDef.isOptional() &&
9756
+ !propDef.isNullable() &&
9757
+ typeof propDef._def?.defaultValue === 'undefined') {
9758
+ throw new Error(`Zod field at \`${propertyPath.join('/')}\` uses \`.optional()\` without \`.nullable()\` which is not supported by the API. See: https://platform.openai.com/docs/guides/structured-outputs?api-mode=responses#all-fields-must-be-required`);
9759
+ }
9760
+ return {
9761
+ properties: {
9762
+ ...acc.properties,
9763
+ [propName]: parsedDef,
9764
+ },
9765
+ required: propDef.isOptional() && !refs.openaiStrictMode ? acc.required : [...acc.required, propName],
9766
+ };
9767
+ }, { properties: {}, required: [] }),
9768
+ additionalProperties: decideAdditionalProperties(def, refs),
9769
+ };
9770
+ if (!result.required.length)
9771
+ delete result.required;
9772
+ return result;
9773
+ }
9774
+
9775
+ const parseOptionalDef = (def, refs) => {
9776
+ if (refs.propertyPath &&
9777
+ refs.currentPath.slice(0, refs.propertyPath.length).toString() === refs.propertyPath.toString()) {
9778
+ return parseDef(def.innerType._def, { ...refs, currentPath: refs.currentPath });
9779
+ }
9780
+ const innerSchema = parseDef(def.innerType._def, {
9781
+ ...refs,
9782
+ currentPath: [...refs.currentPath, 'anyOf', '1'],
9783
+ });
9784
+ return innerSchema ?
9785
+ {
9786
+ anyOf: [
9787
+ {
9788
+ not: {},
9789
+ },
9790
+ innerSchema,
9791
+ ],
9792
+ }
9793
+ : {};
9794
+ };
9795
+
9796
+ const parsePipelineDef = (def, refs) => {
9797
+ if (refs.pipeStrategy === 'input') {
9798
+ return parseDef(def.in._def, refs);
9799
+ }
9800
+ else if (refs.pipeStrategy === 'output') {
9801
+ return parseDef(def.out._def, refs);
9802
+ }
9803
+ const a = parseDef(def.in._def, {
9804
+ ...refs,
9805
+ currentPath: [...refs.currentPath, 'allOf', '0'],
9806
+ });
9807
+ const b = parseDef(def.out._def, {
9808
+ ...refs,
9809
+ currentPath: [...refs.currentPath, 'allOf', a ? '1' : '0'],
9810
+ });
9811
+ return {
9812
+ allOf: [a, b].filter((x) => x !== undefined),
9813
+ };
9814
+ };
9815
+
9816
+ function parsePromiseDef(def, refs) {
9817
+ return parseDef(def.type._def, refs);
9818
+ }
9819
+
9820
+ function parseSetDef(def, refs) {
9821
+ const items = parseDef(def.valueType._def, {
9822
+ ...refs,
9823
+ currentPath: [...refs.currentPath, 'items'],
9824
+ });
9825
+ const schema = {
9826
+ type: 'array',
9827
+ uniqueItems: true,
9828
+ items,
9829
+ };
9830
+ if (def.minSize) {
9831
+ setResponseValueAndErrors(schema, 'minItems', def.minSize.value, def.minSize.message, refs);
9832
+ }
9833
+ if (def.maxSize) {
9834
+ setResponseValueAndErrors(schema, 'maxItems', def.maxSize.value, def.maxSize.message, refs);
9835
+ }
9836
+ return schema;
9837
+ }
9838
+
9839
+ function parseTupleDef(def, refs) {
9840
+ if (def.rest) {
9841
+ return {
9842
+ type: 'array',
9843
+ minItems: def.items.length,
9844
+ items: def.items
9845
+ .map((x, i) => parseDef(x._def, {
9846
+ ...refs,
9847
+ currentPath: [...refs.currentPath, 'items', `${i}`],
9848
+ }))
9849
+ .reduce((acc, x) => (x === undefined ? acc : [...acc, x]), []),
9850
+ additionalItems: parseDef(def.rest._def, {
9851
+ ...refs,
9852
+ currentPath: [...refs.currentPath, 'additionalItems'],
9853
+ }),
9854
+ };
9855
+ }
9856
+ else {
9857
+ return {
9858
+ type: 'array',
9859
+ minItems: def.items.length,
9860
+ maxItems: def.items.length,
9861
+ items: def.items
9862
+ .map((x, i) => parseDef(x._def, {
9863
+ ...refs,
9864
+ currentPath: [...refs.currentPath, 'items', `${i}`],
9865
+ }))
9866
+ .reduce((acc, x) => (x === undefined ? acc : [...acc, x]), []),
9867
+ };
9868
+ }
9869
+ }
9870
+
9871
+ function parseUndefinedDef() {
9872
+ return {
9873
+ not: {},
9874
+ };
9875
+ }
9876
+
9877
+ function parseUnknownDef() {
9878
+ return {};
9879
+ }
9880
+
9881
+ const parseReadonlyDef = (def, refs) => {
9882
+ return parseDef(def.innerType._def, refs);
9883
+ };
9884
+
9885
+ function parseDef(def, refs, forceResolution = false) {
9886
+ const seenItem = refs.seen.get(def);
9887
+ if (refs.override) {
9888
+ const overrideResult = refs.override?.(def, refs, seenItem, forceResolution);
9889
+ if (overrideResult !== ignoreOverride) {
9890
+ return overrideResult;
9891
+ }
9892
+ }
9893
+ if (seenItem && !forceResolution) {
9894
+ const seenSchema = get$ref(seenItem, refs);
9895
+ if (seenSchema !== undefined) {
9896
+ if ('$ref' in seenSchema) {
9897
+ refs.seenRefs.add(seenSchema.$ref);
9898
+ }
9899
+ return seenSchema;
9900
+ }
9901
+ }
9902
+ const newItem = { def, path: refs.currentPath, jsonSchema: undefined };
9903
+ refs.seen.set(def, newItem);
9904
+ const jsonSchema = selectParser(def, def.typeName, refs, forceResolution);
9905
+ if (jsonSchema) {
9906
+ addMeta(def, refs, jsonSchema);
9907
+ }
9908
+ newItem.jsonSchema = jsonSchema;
9909
+ return jsonSchema;
9910
+ }
9911
+ const get$ref = (item, refs) => {
9912
+ switch (refs.$refStrategy) {
9913
+ case 'root':
9914
+ return { $ref: item.path.join('/') };
9915
+ // this case is needed as OpenAI strict mode doesn't support top-level `$ref`s, i.e.
9916
+ // the top-level schema *must* be `{"type": "object", "properties": {...}}` but if we ever
9917
+ // need to define a `$ref`, relative `$ref`s aren't supported, so we need to extract
9918
+ // the schema to `#/definitions/` and reference that.
9919
+ //
9920
+ // e.g. if we need to reference a schema at
9921
+ // `["#","definitions","contactPerson","properties","person1","properties","name"]`
9922
+ // then we'll extract it out to `contactPerson_properties_person1_properties_name`
9923
+ case 'extract-to-root':
9924
+ const name = item.path.slice(refs.basePath.length + 1).join('_');
9925
+ // we don't need to extract the root schema in this case, as it's already
9926
+ // been added to the definitions
9927
+ if (name !== refs.name && refs.nameStrategy === 'duplicate-ref') {
9928
+ refs.definitions[name] = item.def;
9929
+ }
9930
+ return { $ref: [...refs.basePath, refs.definitionPath, name].join('/') };
9931
+ case 'relative':
9932
+ return { $ref: getRelativePath(refs.currentPath, item.path) };
9933
+ case 'none':
9934
+ case 'seen': {
9935
+ if (item.path.length < refs.currentPath.length &&
9936
+ item.path.every((value, index) => refs.currentPath[index] === value)) {
9937
+ console.warn(`Recursive reference detected at ${refs.currentPath.join('/')}! Defaulting to any`);
9938
+ return {};
9939
+ }
9940
+ return refs.$refStrategy === 'seen' ? {} : undefined;
9941
+ }
9942
+ }
9943
+ };
9944
+ const getRelativePath = (pathA, pathB) => {
9945
+ let i = 0;
9946
+ for (; i < pathA.length && i < pathB.length; i++) {
9947
+ if (pathA[i] !== pathB[i])
9948
+ break;
9949
+ }
9950
+ return [(pathA.length - i).toString(), ...pathB.slice(i)].join('/');
9951
+ };
9952
+ const selectParser = (def, typeName, refs, forceResolution) => {
9953
+ switch (typeName) {
9954
+ case ZodFirstPartyTypeKind.ZodString:
9955
+ return parseStringDef(def, refs);
9956
+ case ZodFirstPartyTypeKind.ZodNumber:
9957
+ return parseNumberDef(def, refs);
9958
+ case ZodFirstPartyTypeKind.ZodObject:
9959
+ return parseObjectDef(def, refs);
9960
+ case ZodFirstPartyTypeKind.ZodBigInt:
9961
+ return parseBigintDef(def, refs);
9962
+ case ZodFirstPartyTypeKind.ZodBoolean:
9963
+ return parseBooleanDef();
9964
+ case ZodFirstPartyTypeKind.ZodDate:
9965
+ return parseDateDef(def, refs);
9966
+ case ZodFirstPartyTypeKind.ZodUndefined:
9967
+ return parseUndefinedDef();
9968
+ case ZodFirstPartyTypeKind.ZodNull:
9969
+ return parseNullDef(refs);
9970
+ case ZodFirstPartyTypeKind.ZodArray:
9971
+ return parseArrayDef(def, refs);
9972
+ case ZodFirstPartyTypeKind.ZodUnion:
9973
+ case ZodFirstPartyTypeKind.ZodDiscriminatedUnion:
9974
+ return parseUnionDef(def, refs);
9975
+ case ZodFirstPartyTypeKind.ZodIntersection:
9976
+ return parseIntersectionDef(def, refs);
9977
+ case ZodFirstPartyTypeKind.ZodTuple:
9978
+ return parseTupleDef(def, refs);
9979
+ case ZodFirstPartyTypeKind.ZodRecord:
9980
+ return parseRecordDef(def, refs);
9981
+ case ZodFirstPartyTypeKind.ZodLiteral:
9982
+ return parseLiteralDef(def, refs);
9983
+ case ZodFirstPartyTypeKind.ZodEnum:
9984
+ return parseEnumDef(def);
9985
+ case ZodFirstPartyTypeKind.ZodNativeEnum:
9986
+ return parseNativeEnumDef(def);
9987
+ case ZodFirstPartyTypeKind.ZodNullable:
9988
+ return parseNullableDef(def, refs);
9989
+ case ZodFirstPartyTypeKind.ZodOptional:
9990
+ return parseOptionalDef(def, refs);
9991
+ case ZodFirstPartyTypeKind.ZodMap:
9992
+ return parseMapDef(def, refs);
9993
+ case ZodFirstPartyTypeKind.ZodSet:
9994
+ return parseSetDef(def, refs);
9995
+ case ZodFirstPartyTypeKind.ZodLazy:
9996
+ return parseDef(def.getter()._def, refs);
9997
+ case ZodFirstPartyTypeKind.ZodPromise:
9998
+ return parsePromiseDef(def, refs);
9999
+ case ZodFirstPartyTypeKind.ZodNaN:
10000
+ case ZodFirstPartyTypeKind.ZodNever:
10001
+ return parseNeverDef();
10002
+ case ZodFirstPartyTypeKind.ZodEffects:
10003
+ return parseEffectsDef(def, refs, forceResolution);
10004
+ case ZodFirstPartyTypeKind.ZodAny:
10005
+ return parseAnyDef();
10006
+ case ZodFirstPartyTypeKind.ZodUnknown:
10007
+ return parseUnknownDef();
10008
+ case ZodFirstPartyTypeKind.ZodDefault:
10009
+ return parseDefaultDef(def, refs);
10010
+ case ZodFirstPartyTypeKind.ZodBranded:
10011
+ return parseBrandedDef(def, refs);
10012
+ case ZodFirstPartyTypeKind.ZodReadonly:
10013
+ return parseReadonlyDef(def, refs);
10014
+ case ZodFirstPartyTypeKind.ZodCatch:
10015
+ return parseCatchDef(def, refs);
10016
+ case ZodFirstPartyTypeKind.ZodPipeline:
10017
+ return parsePipelineDef(def, refs);
10018
+ case ZodFirstPartyTypeKind.ZodFunction:
10019
+ case ZodFirstPartyTypeKind.ZodVoid:
10020
+ case ZodFirstPartyTypeKind.ZodSymbol:
10021
+ return undefined;
10022
+ default:
10023
+ return ((_) => undefined)();
10024
+ }
10025
+ };
10026
+ const addMeta = (def, refs, jsonSchema) => {
10027
+ if (def.description) {
10028
+ jsonSchema.description = def.description;
10029
+ if (refs.markdownDescription) {
10030
+ jsonSchema.markdownDescription = def.description;
10031
+ }
10032
+ }
10033
+ return jsonSchema;
10034
+ };
10035
+
10036
+ const zodToJsonSchema = (schema, options) => {
10037
+ const refs = getRefs(options);
10038
+ const name = typeof options === 'string' ? options
10039
+ : options?.nameStrategy === 'title' ? undefined
10040
+ : options?.name;
10041
+ const main = parseDef(schema._def, name === undefined ? refs : ({
10042
+ ...refs,
10043
+ currentPath: [...refs.basePath, refs.definitionPath, name],
10044
+ }), false) ?? {};
10045
+ const title = typeof options === 'object' && options.name !== undefined && options.nameStrategy === 'title' ?
10046
+ options.name
10047
+ : undefined;
10048
+ if (title !== undefined) {
10049
+ main.title = title;
10050
+ }
10051
+ const definitions = (() => {
10052
+ if (isEmptyObj(refs.definitions)) {
10053
+ return undefined;
10054
+ }
10055
+ const definitions = {};
10056
+ const processedDefinitions = new Set();
10057
+ // the call to `parseDef()` here might itself add more entries to `.definitions`
10058
+ // so we need to continually evaluate definitions until we've resolved all of them
10059
+ //
10060
+ // we have a generous iteration limit here to avoid blowing up the stack if there
10061
+ // are any bugs that would otherwise result in us iterating indefinitely
10062
+ for (let i = 0; i < 500; i++) {
10063
+ const newDefinitions = Object.entries(refs.definitions).filter(([key]) => !processedDefinitions.has(key));
10064
+ if (newDefinitions.length === 0)
10065
+ break;
10066
+ for (const [key, schema] of newDefinitions) {
10067
+ definitions[key] =
10068
+ parseDef(zodDef(schema), { ...refs, currentPath: [...refs.basePath, refs.definitionPath, key] }, true) ?? {};
10069
+ processedDefinitions.add(key);
10070
+ }
10071
+ }
10072
+ return definitions;
10073
+ })();
10074
+ const combined = name === undefined ?
10075
+ definitions ?
10076
+ {
10077
+ ...main,
10078
+ [refs.definitionPath]: definitions,
10079
+ }
10080
+ : main
10081
+ : refs.nameStrategy === 'duplicate-ref' ?
10082
+ {
10083
+ ...main,
10084
+ ...(definitions || refs.seenRefs.size ?
10085
+ {
10086
+ [refs.definitionPath]: {
10087
+ ...definitions,
10088
+ // only actually duplicate the schema definition if it was ever referenced
10089
+ // otherwise the duplication is completely pointless
10090
+ ...(refs.seenRefs.size ? { [name]: main } : undefined),
10091
+ },
10092
+ }
10093
+ : undefined),
10094
+ }
10095
+ : {
10096
+ $ref: [...(refs.$refStrategy === 'relative' ? [] : refs.basePath), refs.definitionPath, name].join('/'),
10097
+ [refs.definitionPath]: {
10098
+ ...definitions,
10099
+ [name]: main,
10100
+ },
10101
+ };
10102
+ if (refs.target === 'jsonSchema7') {
10103
+ combined.$schema = 'http://json-schema.org/draft-07/schema#';
10104
+ }
10105
+ else if (refs.target === 'jsonSchema2019-09') {
10106
+ combined.$schema = 'https://json-schema.org/draft/2019-09/schema#';
10107
+ }
10108
+ return combined;
10109
+ };
10110
+
10111
+ function toStrictJsonSchema(schema) {
10112
+ if (schema.type !== 'object') {
10113
+ throw new Error(`Root schema must have type: 'object' but got type: ${schema.type ? `'${schema.type}'` : 'undefined'}`);
10114
+ }
10115
+ const schemaCopy = structuredClone(schema);
10116
+ return ensureStrictJsonSchema(schemaCopy, [], schemaCopy);
10117
+ }
10118
+ function isNullable(schema) {
10119
+ if (typeof schema === 'boolean') {
10120
+ return false;
10121
+ }
10122
+ if (schema.type === 'null') {
10123
+ return true;
10124
+ }
10125
+ for (const oneOfVariant of schema.oneOf ?? []) {
10126
+ if (isNullable(oneOfVariant)) {
10127
+ return true;
10128
+ }
10129
+ }
10130
+ for (const allOfVariant of schema.anyOf ?? []) {
10131
+ if (isNullable(allOfVariant)) {
10132
+ return true;
10133
+ }
10134
+ }
10135
+ return false;
10136
+ }
10137
+ /**
10138
+ * Mutates the given JSON schema to ensure it conforms to the `strict` standard
10139
+ * that the API expects.
10140
+ */
10141
+ function ensureStrictJsonSchema(jsonSchema, path, root) {
10142
+ if (typeof jsonSchema === 'boolean') {
10143
+ throw new TypeError(`Expected object schema but got boolean; path=${path.join('/')}`);
10144
+ }
10145
+ if (!isObject(jsonSchema)) {
10146
+ throw new TypeError(`Expected ${JSON.stringify(jsonSchema)} to be an object; path=${path.join('/')}`);
10147
+ }
10148
+ // Handle $defs (non-standard but sometimes used)
10149
+ const defs = jsonSchema.$defs;
10150
+ if (isObject(defs)) {
10151
+ for (const [defName, defSchema] of Object.entries(defs)) {
10152
+ ensureStrictJsonSchema(defSchema, [...path, '$defs', defName], root);
10153
+ }
10154
+ }
10155
+ // Handle definitions (draft-04 style, deprecated in draft-07 but still used)
10156
+ const definitions = jsonSchema.definitions;
10157
+ if (isObject(definitions)) {
10158
+ for (const [definitionName, definitionSchema] of Object.entries(definitions)) {
10159
+ ensureStrictJsonSchema(definitionSchema, [...path, 'definitions', definitionName], root);
10160
+ }
10161
+ }
10162
+ // Add additionalProperties: false to object types
10163
+ const typ = jsonSchema.type;
10164
+ if (typ === 'object' && !('additionalProperties' in jsonSchema)) {
10165
+ jsonSchema.additionalProperties = false;
10166
+ }
10167
+ const required = jsonSchema.required ?? [];
10168
+ // Handle object properties
10169
+ const properties = jsonSchema.properties;
10170
+ if (isObject(properties)) {
10171
+ for (const [key, value] of Object.entries(properties)) {
10172
+ if (!isNullable(value) && !required.includes(key)) {
10173
+ throw new Error(`Zod field at \`${[...path, 'properties', key].join('/')}\` uses \`.optional()\` without \`.nullable()\` which is not supported by the API. See: https://platform.openai.com/docs/guides/structured-outputs?api-mode=responses#all-fields-must-be-required`);
10174
+ }
10175
+ }
10176
+ jsonSchema.required = Object.keys(properties);
10177
+ jsonSchema.properties = Object.fromEntries(Object.entries(properties).map(([key, propSchema]) => [
10178
+ key,
10179
+ ensureStrictJsonSchema(propSchema, [...path, 'properties', key], root),
10180
+ ]));
10181
+ }
10182
+ // Handle arrays
10183
+ const items = jsonSchema.items;
10184
+ if (isObject(items)) {
10185
+ jsonSchema.items = ensureStrictJsonSchema(items, [...path, 'items'], root);
10186
+ }
10187
+ // Handle unions (anyOf)
10188
+ const anyOf = jsonSchema.anyOf;
10189
+ if (Array.isArray(anyOf)) {
10190
+ jsonSchema.anyOf = anyOf.map((variant, i) => ensureStrictJsonSchema(variant, [...path, 'anyOf', String(i)], root));
10191
+ }
10192
+ // Handle intersections (allOf)
10193
+ const allOf = jsonSchema.allOf;
10194
+ if (Array.isArray(allOf)) {
10195
+ if (allOf.length === 1) {
10196
+ const resolved = ensureStrictJsonSchema(allOf[0], [...path, 'allOf', '0'], root);
10197
+ Object.assign(jsonSchema, resolved);
10198
+ delete jsonSchema.allOf;
10199
+ }
10200
+ else {
10201
+ jsonSchema.allOf = allOf.map((entry, i) => ensureStrictJsonSchema(entry, [...path, 'allOf', String(i)], root));
10202
+ }
10203
+ }
10204
+ // Strip `null` defaults as there's no meaningful distinction
10205
+ if (jsonSchema.default === null) {
10206
+ delete jsonSchema.default;
10207
+ }
10208
+ // Handle $ref with additional properties
10209
+ const ref = jsonSchema.$ref;
10210
+ if (ref && hasMoreThanNKeys(jsonSchema, 1)) {
10211
+ if (typeof ref !== 'string') {
10212
+ throw new TypeError(`Received non-string $ref - ${ref}; path=${path.join('/')}`);
10213
+ }
10214
+ const resolved = resolveRef(root, ref);
10215
+ if (typeof resolved === 'boolean') {
10216
+ throw new Error(`Expected \`$ref: ${ref}\` to resolve to an object schema but got boolean`);
10217
+ }
10218
+ if (!isObject(resolved)) {
10219
+ throw new Error(`Expected \`$ref: ${ref}\` to resolve to an object but got ${JSON.stringify(resolved)}`);
10220
+ }
10221
+ // Properties from the json schema take priority over the ones on the `$ref`
10222
+ Object.assign(jsonSchema, { ...resolved, ...jsonSchema });
10223
+ delete jsonSchema.$ref;
10224
+ // Since the schema expanded from `$ref` might not have `additionalProperties: false` applied,
10225
+ // we call `ensureStrictJsonSchema` again to fix the inlined schema and ensure it's valid.
10226
+ return ensureStrictJsonSchema(jsonSchema, path, root);
10227
+ }
10228
+ return jsonSchema;
10229
+ }
10230
+ function resolveRef(root, ref) {
10231
+ if (!ref.startsWith('#/')) {
10232
+ throw new Error(`Unexpected $ref format ${JSON.stringify(ref)}; Does not start with #/`);
10233
+ }
10234
+ const pathParts = ref.slice(2).split('/');
10235
+ let resolved = root;
10236
+ for (const key of pathParts) {
10237
+ if (!isObject(resolved)) {
10238
+ throw new Error(`encountered non-object entry while resolving ${ref} - ${JSON.stringify(resolved)}`);
10239
+ }
10240
+ const value = resolved[key];
10241
+ if (value === undefined) {
10242
+ throw new Error(`Key ${key} not found while resolving ${ref}`);
10243
+ }
10244
+ resolved = value;
10245
+ }
10246
+ return resolved;
10247
+ }
10248
+ function isObject(obj) {
10249
+ return typeof obj === 'object' && obj !== null && !Array.isArray(obj);
10250
+ }
10251
+ function hasMoreThanNKeys(obj, n) {
10252
+ let i = 0;
10253
+ for (const _ in obj) {
10254
+ i++;
10255
+ if (i > n) {
10256
+ return true;
10257
+ }
10258
+ }
10259
+ return false;
10260
+ }
10261
+
10262
+ function zodV3ToJsonSchema(schema, options) {
10263
+ return zodToJsonSchema(schema, {
10264
+ openaiStrictMode: true,
10265
+ name: options.name,
10266
+ nameStrategy: 'duplicate-ref',
10267
+ $refStrategy: 'extract-to-root',
10268
+ nullableStrategy: 'property',
10269
+ });
10270
+ }
10271
+ function zodV4ToJsonSchema(schema) {
10272
+ return toStrictJsonSchema(toJSONSchema(schema, {
10273
+ target: 'draft-7',
10274
+ }));
10275
+ }
10276
+ function isZodV4(zodObject) {
10277
+ return '_zod' in zodObject;
10278
+ }
10279
+ function zodTextFormat(zodObject, name, props) {
10280
+ return makeParseableTextFormat({
10281
+ type: 'json_schema',
10282
+ ...props,
10283
+ name,
10284
+ strict: true,
10285
+ schema: isZodV4(zodObject) ? zodV4ToJsonSchema(zodObject) : zodV3ToJsonSchema(zodObject, { name }),
10286
+ }, (content) => zodObject.parse(JSON.parse(content)));
10287
+ }
10288
+
10289
+ // llm-openai-config.ts
10290
+ const DEFAULT_MODEL = 'gpt-4.1-mini';
10291
+ const GPT_5_4_HIGH_CONTEXT_THRESHOLD_TOKENS = 272_000;
10292
+ const GPT_5_4_HIGH_CONTEXT_INPUT_MULTIPLIER = 2;
10293
+ const GPT_5_4_HIGH_CONTEXT_OUTPUT_MULTIPLIER = 1.5;
10294
+ /** Token costs in USD per 1M tokens. Last updated Mar 2026. */
10295
+ const openAiModelCosts = {
10296
+ 'gpt-4o': {
10297
+ inputCost: 2.5 / 1_000_000,
10298
+ cacheHitCost: 1.25 / 1_000_000,
10299
+ outputCost: 10 / 1_000_000,
10300
+ },
10301
+ 'gpt-4o-mini': {
10302
+ inputCost: 0.15 / 1_000_000,
10303
+ cacheHitCost: 0.075 / 1_000_000,
10304
+ outputCost: 0.6 / 1_000_000,
10305
+ },
10306
+ 'o1-mini': {
10307
+ inputCost: 1.1 / 1_000_000,
10308
+ cacheHitCost: 0.55 / 1_000_000,
10309
+ outputCost: 4.4 / 1_000_000,
10310
+ },
10311
+ 'o1': {
10312
+ inputCost: 15 / 1_000_000,
10313
+ cacheHitCost: 7.5 / 1_000_000,
10314
+ outputCost: 60 / 1_000_000,
10315
+ },
10316
+ 'o3-mini': {
10317
+ inputCost: 1.1 / 1_000_000,
10318
+ cacheHitCost: 0.55 / 1_000_000,
10319
+ outputCost: 4.4 / 1_000_000,
10320
+ },
10321
+ 'o3': {
10322
+ inputCost: 2 / 1_000_000,
10323
+ cacheHitCost: 0.5 / 1_000_000,
10324
+ outputCost: 8 / 1_000_000,
10325
+ },
10326
+ 'gpt-4.1': {
10327
+ inputCost: 2 / 1_000_000,
10328
+ cacheHitCost: 0.5 / 1_000_000,
10329
+ outputCost: 8 / 1_000_000,
10330
+ },
10331
+ 'gpt-4.1-mini': {
10332
+ inputCost: 0.4 / 1_000_000,
10333
+ cacheHitCost: 0.1 / 1_000_000,
10334
+ outputCost: 1.6 / 1_000_000,
10335
+ },
10336
+ 'gpt-4.1-nano': {
10337
+ inputCost: 0.1 / 1_000_000,
10338
+ cacheHitCost: 0.025 / 1_000_000,
10339
+ outputCost: 0.4 / 1_000_000,
10340
+ },
10341
+ 'gpt-5': {
10342
+ inputCost: 1.25 / 1_000_000,
10343
+ cacheHitCost: 0.125 / 1_000_000,
10344
+ outputCost: 10 / 1_000_000,
10345
+ },
10346
+ 'gpt-5-mini': {
10347
+ inputCost: 0.25 / 1_000_000,
10348
+ cacheHitCost: 0.025 / 1_000_000,
10349
+ outputCost: 2 / 1_000_000,
10350
+ },
10351
+ 'gpt-5-nano': {
10352
+ inputCost: 0.05 / 1_000_000,
10353
+ cacheHitCost: 0.005 / 1_000_000,
10354
+ outputCost: 0.4 / 1_000_000,
10355
+ },
10356
+ 'gpt-5.1': {
10357
+ inputCost: 1.25 / 1_000_000,
10358
+ cacheHitCost: 0.125 / 1_000_000,
10359
+ outputCost: 10 / 1_000_000,
10360
+ },
10361
+ 'gpt-5.4': {
10362
+ inputCost: 2.5 / 1_000_000,
10363
+ cacheHitCost: 0.25 / 1_000_000,
10364
+ outputCost: 15 / 1_000_000,
10365
+ },
10366
+ 'gpt-5.4-pro': {
10367
+ inputCost: 30 / 1_000_000,
10368
+ outputCost: 180 / 1_000_000,
10369
+ },
10370
+ 'gpt-5.2': {
10371
+ inputCost: 1.75 / 1_000_000,
10372
+ cacheHitCost: 0.175 / 1_000_000,
10373
+ outputCost: 14 / 1_000_000,
10374
+ },
10375
+ 'gpt-5.2-pro': {
10376
+ inputCost: 21 / 1_000_000,
10377
+ outputCost: 168 / 1_000_000,
10378
+ },
10379
+ 'gpt-5.1-codex': {
10380
+ inputCost: 1.25 / 1_000_000,
10381
+ cacheHitCost: 0.125 / 1_000_000,
10382
+ outputCost: 10 / 1_000_000,
10383
+ },
10384
+ 'gpt-5.1-codex-max': {
10385
+ inputCost: 1.25 / 1_000_000,
10386
+ cacheHitCost: 0.125 / 1_000_000,
10387
+ outputCost: 10 / 1_000_000,
10388
+ },
10389
+ 'o4-mini': {
10390
+ inputCost: 1.1 / 1_000_000,
10391
+ cacheHitCost: 0.275 / 1_000_000,
10392
+ outputCost: 4.4 / 1_000_000,
10393
+ },
10394
+ };
10395
+ const deepseekModelCosts = {
10396
+ 'deepseek-chat': {
10397
+ inputCost: 0.27 / 1_000_000, // $0.27 per 1M tokens (Cache miss price)
10398
+ cacheHitCost: 0.07 / 1_000_000, // $0.07 per 1M tokens (Cache hit price)
10399
+ outputCost: 1.1 / 1_000_000, // $1.10 per 1M tokens
10400
+ },
10401
+ 'deepseek-reasoner': {
10402
+ inputCost: 0.55 / 1_000_000, // $0.55 per 1M tokens (Cache miss price)
10403
+ cacheHitCost: 0.14 / 1_000_000, // $0.14 per 1M tokens (Cache hit price)
10404
+ outputCost: 2.19 / 1_000_000, // $2.19 per 1M tokens
10405
+ },
10406
+ };
10407
+ function shouldUseGPT54HighContextPricing(model, inputTokens) {
10408
+ return (model === 'gpt-5.4' || model === 'gpt-5.4-pro') && inputTokens > GPT_5_4_HIGH_CONTEXT_THRESHOLD_TOKENS;
10409
+ }
10410
+ /** Image generation costs in USD per image. Based on OpenAI pricing as of Feb 2025. */
10411
+ const openAiImageCosts = {
10412
+ 'gpt-image-1': 0.0075, // $0.0075 per image for gpt-image-1
10413
+ 'gpt-image-1.5': 0.0075, // Assumes parity pricing with gpt-image-1 until OpenAI publishes updated rates
10414
+ };
10415
+ /**
10416
+ * Calculates the cost of generating images using OpenAI's Images API.
10417
+ *
10418
+ * @param model The image generation model name.
10419
+ * @param imageCount The number of images generated.
10420
+ * @returns The cost of generating the images in USD.
10421
+ */
10422
+ function calculateImageCost(model, imageCount) {
10423
+ if (typeof model !== 'string' || typeof imageCount !== 'number' || imageCount <= 0) {
10424
+ return 0;
10425
+ }
10426
+ const costPerImage = openAiImageCosts[model];
10427
+ if (!costPerImage)
10428
+ return 0;
10429
+ return imageCount * costPerImage;
10430
+ }
10431
+ /**
10432
+ * Calculates the cost of calling a language model in USD based on the provider and model, tokens, and given costs per 1M tokens.
10433
+ *
10434
+ * @param provider The provider of the language model. Supported providers are 'openai' and 'deepseek'.
10435
+ * @param model The name of the language model. Supported models are listed in the `openAiModelCosts` and `deepseekModelCosts` objects.
10436
+ * @param inputTokens The number of input tokens passed to the language model.
10437
+ * @param outputTokens The number of output tokens generated by the language model.
10438
+ * @param reasoningTokens The number of output tokens generated by the language model for reasoning.
10439
+ * @param cacheHitTokens The number of input tokens billed at cached-input rates.
10440
+ * @returns The cost of calling the language model in USD.
10441
+ */
10442
+ function calculateCost(provider, model, inputTokens, outputTokens, reasoningTokens, cacheHitTokens) {
10443
+ if (typeof provider !== 'string' ||
10444
+ typeof model !== 'string' ||
10445
+ typeof inputTokens !== 'number' ||
10446
+ typeof outputTokens !== 'number' ||
10447
+ (reasoningTokens !== undefined && typeof reasoningTokens !== 'number') ||
10448
+ (cacheHitTokens !== undefined && typeof cacheHitTokens !== 'number')) {
10449
+ return 0;
10450
+ }
10451
+ const modelCosts = provider === 'deepseek' ? deepseekModelCosts[model] : openAiModelCosts[model];
10452
+ if (!modelCosts)
10453
+ return 0;
10454
+ const boundedCacheHitTokens = Math.min(Math.max(cacheHitTokens || 0, 0), inputTokens);
10455
+ let inputCost = inputTokens * modelCosts.inputCost;
10456
+ if (typeof modelCosts.cacheHitCost === 'number' && boundedCacheHitTokens > 0) {
10457
+ inputCost = boundedCacheHitTokens * modelCosts.cacheHitCost + (inputTokens - boundedCacheHitTokens) * modelCosts.inputCost;
10458
+ }
10459
+ let outputCost = outputTokens * modelCosts.outputCost;
10460
+ let reasoningCost = (reasoningTokens || 0) * modelCosts.outputCost;
10461
+ if (provider === 'openai' && shouldUseGPT54HighContextPricing(model, inputTokens)) {
10462
+ inputCost *= GPT_5_4_HIGH_CONTEXT_INPUT_MULTIPLIER;
10463
+ outputCost *= GPT_5_4_HIGH_CONTEXT_OUTPUT_MULTIPLIER;
10464
+ reasoningCost *= GPT_5_4_HIGH_CONTEXT_OUTPUT_MULTIPLIER;
10465
+ }
10466
+ return inputCost + outputCost + reasoningCost;
10467
+ }
10468
+
10469
+ /**
10470
+ * Fix a broken JSON string by attempting to extract and parse valid JSON content. This function is very lenient and will attempt to fix many types of JSON errors, including unbalanced brackets, missing or extra commas, improperly escaped $ signs, unquoted strings, trailing commas, missing closing brackets or braces, etc.
10471
+ * @param {string} jsonStr - The broken JSON string to fix
10472
+ * @returns {JsonValue} - The parsed JSON value
10473
+ */
10474
+ function fixBrokenJson(jsonStr) {
10475
+ // Pre-process: Fix improperly escaped $ signs
10476
+ jsonStr = jsonStr.replace(/\\\$/g, '$');
10477
+ let index = 0;
10478
+ function parse() {
10479
+ const results = [];
10480
+ while (index < jsonStr.length) {
10481
+ skipWhitespace();
10482
+ const value = parseValue();
10483
+ if (value !== undefined) {
10484
+ results.push(value);
10485
+ }
10486
+ else {
10487
+ index++; // Skip invalid character
10488
+ }
10489
+ }
10490
+ return results.length === 1 ? results[0] : results;
10491
+ }
10492
+ function parseValue() {
10493
+ skipWhitespace();
10494
+ const char = getChar();
10495
+ if (!char)
10496
+ return undefined;
10497
+ if (char === '{')
10498
+ return parseObject();
10499
+ if (char === '[')
10500
+ return parseArray();
10501
+ if (char === '"' || char === "'")
10502
+ return parseString();
10503
+ if (char === 't' && jsonStr.slice(index, index + 4).toLowerCase() === 'true') {
10504
+ index += 4;
10505
+ return true;
10506
+ }
10507
+ if (char === 'f' && jsonStr.slice(index, index + 5).toLowerCase() === 'false') {
10508
+ index += 5;
10509
+ return false;
10510
+ }
10511
+ if (char === 'n' && jsonStr.slice(index, index + 4).toLowerCase() === 'null') {
10512
+ index += 4;
10513
+ return null;
10514
+ }
10515
+ if (/[a-zA-Z]/.test(char))
7702
10516
  return parseString(); // Unquoted string
7703
10517
  if (char === '-' || char === '.' || /\d/.test(char))
7704
10518
  return parseNumber();
@@ -8118,6 +10932,32 @@ function supportsStructuredOutputs(model) {
8118
10932
  function supportsDistillation(model) {
8119
10933
  return normalizeModelName(model) !== 'gpt-5.4-pro';
8120
10934
  }
10935
+ function isZodSchema(schema) {
10936
+ return typeof schema === 'object' && schema !== null && 'safeParse' in schema;
10937
+ }
10938
+ function buildJsonSchemaFormat(schema, schemaName, schemaDescription, schemaStrict) {
10939
+ if (isZodSchema(schema)) {
10940
+ const zodFormat = zodTextFormat(schema, schemaName, schemaDescription
10941
+ ? {
10942
+ description: schemaDescription,
10943
+ }
10944
+ : undefined);
10945
+ return {
10946
+ type: 'json_schema',
10947
+ name: zodFormat.name,
10948
+ schema: zodFormat.schema,
10949
+ ...(zodFormat.description ? { description: zodFormat.description } : {}),
10950
+ ...(schemaStrict !== undefined ? { strict: schemaStrict } : { strict: zodFormat.strict }),
10951
+ };
10952
+ }
10953
+ return {
10954
+ type: 'json_schema',
10955
+ name: schemaName,
10956
+ schema,
10957
+ ...(schemaDescription ? { description: schemaDescription } : {}),
10958
+ ...(schemaStrict !== undefined ? { strict: schemaStrict } : {}),
10959
+ };
10960
+ }
8121
10961
  /**
8122
10962
  * Makes a call to OpenAI's Responses API for more advanced use cases with built-in tools.
8123
10963
  *
@@ -8225,9 +11065,13 @@ const makeResponsesAPICall = async (input, options = {}) => {
8225
11065
  .join('') || '';
8226
11066
  // Determine the format for parsing the response
8227
11067
  let parsingFormat = 'text';
8228
- if (requestBody.text?.format?.type === 'json_object') {
11068
+ const requestedFormat = requestBody.text?.format;
11069
+ if (requestedFormat?.type === 'json_object') {
8229
11070
  parsingFormat = 'json';
8230
11071
  }
11072
+ else if (requestedFormat?.type === 'json_schema') {
11073
+ parsingFormat = requestedFormat;
11074
+ }
8231
11075
  // Handle regular responses
8232
11076
  const parsedResponse = await parseResponse(textContent, parsingFormat);
8233
11077
  if (parsedResponse === null) {
@@ -8265,7 +11109,7 @@ const makeResponsesAPICall = async (input, options = {}) => {
8265
11109
  * });
8266
11110
  */
8267
11111
  async function makeLLMCall(input, options = {}) {
8268
- const { apiKey, model = DEFAULT_MODEL, responseFormat = 'text', tools, useCodeInterpreter = false, useWebSearch = false, imageBase64, imageDetail = 'high', context, } = options;
11112
+ const { apiKey, model = DEFAULT_MODEL, responseFormat = 'text', schema, schemaName = 'response', schemaDescription, schemaStrict, tools, useCodeInterpreter = false, useWebSearch = false, imageBase64, imageDetail = 'high', context, } = options;
8269
11113
  // Validate model
8270
11114
  const normalizedModel = normalizeModelName(model);
8271
11115
  if (!isSupportedModel(normalizedModel)) {
@@ -8343,9 +11187,17 @@ async function makeLLMCall(input, options = {}) {
8343
11187
  responsesOptions.temperature = 0.2;
8344
11188
  }
8345
11189
  // Configure response format
8346
- if (responseFormat === 'json') {
11190
+ if (schema) {
11191
+ responsesOptions.text = {
11192
+ format: buildJsonSchemaFormat(schema, schemaName, schemaDescription, schemaStrict),
11193
+ };
11194
+ }
11195
+ else if (responseFormat === 'json') {
8347
11196
  responsesOptions.text = { format: { type: 'json_object' } };
8348
11197
  }
11198
+ else if (typeof responseFormat === 'object' && responseFormat.type === 'json_schema') {
11199
+ responsesOptions.text = { format: responseFormat };
11200
+ }
8349
11201
  // Configure built-in tools
8350
11202
  if (useCodeInterpreter) {
8351
11203
  responsesOptions.tools = [{ type: 'code_interpreter', container: { type: 'auto' } }];