@alint-js/plugin-js 0.0.28 → 0.0.30

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.
package/dist/index.mjs CHANGED
@@ -1,6 +1,13 @@
1
- import { definePlugin, defineRule } from "@alint-js/core";
2
- import { formatOutputLanguageInstruction, formatSourceWithLineNumbers, generateStructured, toolParametersFromSchema } from "@alint-js/core/structured-output";
3
- import { array, boolean, description, number, object, picklist, pipe, string } from "valibot";
1
+ import { n as strictJsonSchema } from "./index-DoHiaFQM-9scNuUlY.mjs";
2
+ import { t as __exportAll } from "./esm-F2YJn-T8.mjs";
3
+ //#region ../plugin/dist/index.mjs
4
+ function definePlugin(plugin) {
5
+ return plugin;
6
+ }
7
+ function defineRule(rule) {
8
+ return rule;
9
+ }
10
+ //#endregion
4
11
  //#region src/rules/inline-miniature-normalizer/prompt.ts
5
12
  const inlineMiniatureNormalizerPrompt = `
6
13
  You are reviewing one TypeScript file.
@@ -45,32 +52,1706 @@ Do not report:
45
52
 
46
53
  Return warnings only. If uncertain, use medium or low confidence instead of forcing a finding.
47
54
  `.trim();
55
+ const DEFAULT_CONFIG = {
56
+ lang: void 0,
57
+ message: void 0,
58
+ abortEarly: void 0,
59
+ abortPipeEarly: void 0
60
+ };
61
+ /**
62
+ * Returns the global configuration.
63
+ *
64
+ * @param config The config to merge.
65
+ *
66
+ * @returns The configuration.
67
+ */
68
+ /* @__NO_SIDE_EFFECTS__ */
69
+ function getGlobalConfig(config$1) {
70
+ if (!config$1 && true) return DEFAULT_CONFIG;
71
+ return {
72
+ lang: config$1?.lang ?? void 0,
73
+ message: config$1?.message,
74
+ abortEarly: config$1?.abortEarly ?? void 0,
75
+ abortPipeEarly: config$1?.abortPipeEarly ?? void 0
76
+ };
77
+ }
78
+ /**
79
+ * Stringifies an unknown input to a literal or type string.
80
+ *
81
+ * @param input The unknown input.
82
+ *
83
+ * @returns A literal or type string.
84
+ *
85
+ * @internal
86
+ */
87
+ /* @__NO_SIDE_EFFECTS__ */
88
+ function _stringify(input) {
89
+ const type = typeof input;
90
+ if (type === "string") return `"${input}"`;
91
+ if (type === "number" || type === "bigint" || type === "boolean") return `${input}`;
92
+ if (type === "object" || type === "function") return (input && Object.getPrototypeOf(input)?.constructor?.name) ?? "null";
93
+ return type;
94
+ }
95
+ /**
96
+ * Adds an issue to the dataset.
97
+ *
98
+ * @param context The issue context.
99
+ * @param label The issue label.
100
+ * @param dataset The input dataset.
101
+ * @param config The configuration.
102
+ * @param other The optional props.
103
+ *
104
+ * @internal
105
+ */
106
+ function _addIssue(context, label, dataset, config$1, other) {
107
+ const input = other && "input" in other ? other.input : dataset.value;
108
+ const expected = other?.expected ?? context.expects ?? null;
109
+ const received = other?.received ?? /* @__PURE__ */ _stringify(input);
110
+ const issue = {
111
+ kind: context.kind,
112
+ type: context.type,
113
+ input,
114
+ expected,
115
+ received,
116
+ message: `Invalid ${label}: ${expected ? `Expected ${expected} but r` : "R"}eceived ${received}`,
117
+ requirement: context.requirement,
118
+ path: other?.path,
119
+ issues: other?.issues,
120
+ lang: config$1.lang,
121
+ abortEarly: config$1.abortEarly,
122
+ abortPipeEarly: config$1.abortPipeEarly
123
+ };
124
+ const isSchema = context.kind === "schema";
125
+ const message$1 = other?.message ?? context.message ?? (context.reference, issue.lang, void 0) ?? (isSchema ? (issue.lang, void 0) : null) ?? config$1.message ?? (issue.lang, void 0);
126
+ if (message$1 !== void 0) issue.message = typeof message$1 === "function" ? message$1(issue) : message$1;
127
+ if (isSchema) dataset.typed = false;
128
+ if (dataset.issues) dataset.issues.push(issue);
129
+ else dataset.issues = [issue];
130
+ }
131
+ /**
132
+ * Returns the last top-level value of a given metadata type from a schema
133
+ * using a breadth-first search that starts with the last item in the pipeline.
134
+ *
135
+ * @param schema The schema to search.
136
+ * @param type The metadata type.
137
+ *
138
+ * @returns The value, if any.
139
+ *
140
+ * @internal
141
+ */
142
+ /* @__NO_SIDE_EFFECTS__ */
143
+ function _getLastMetadata(schema, type) {
144
+ if ("pipe" in schema) {
145
+ const nestedSchemas = [];
146
+ for (let index = schema.pipe.length - 1; index >= 0; index--) {
147
+ const item = schema.pipe[index];
148
+ if (item.kind === "schema" && "pipe" in item) nestedSchemas.push(item);
149
+ else if (item.kind === "metadata" && item.type === type) return item[type];
150
+ }
151
+ for (const nestedSchema of nestedSchemas) {
152
+ const result = /* @__PURE__ */ _getLastMetadata(nestedSchema, type);
153
+ if (result !== void 0) return result;
154
+ }
155
+ }
156
+ }
157
+ const _standardCache = /* @__PURE__ */ new WeakMap();
158
+ /**
159
+ * Returns the Standard Schema properties.
160
+ *
161
+ * @param context The schema context.
162
+ *
163
+ * @returns The Standard Schema properties.
164
+ */
165
+ /* @__NO_SIDE_EFFECTS__ */
166
+ function _getStandardProps(context) {
167
+ let cached = _standardCache.get(context);
168
+ if (!cached) {
169
+ cached = {
170
+ version: 1,
171
+ vendor: "valibot",
172
+ validate(value$1) {
173
+ return context["~run"]({ value: value$1 }, /* @__PURE__ */ getGlobalConfig());
174
+ }
175
+ };
176
+ _standardCache.set(context, cached);
177
+ }
178
+ return cached;
179
+ }
180
+ /**
181
+ * Joins multiple `expects` values with the given separator.
182
+ *
183
+ * @param values The `expects` values.
184
+ * @param separator The separator.
185
+ *
186
+ * @returns The joined `expects` property.
187
+ *
188
+ * @internal
189
+ */
190
+ /* @__NO_SIDE_EFFECTS__ */
191
+ function _joinExpects(values$1, separator) {
192
+ const list = [...new Set(values$1)];
193
+ if (list.length > 1) return `(${list.join(` ${separator} `)})`;
194
+ return list[0] ?? "never";
195
+ }
196
+ /**
197
+ * A Valibot error with useful information.
198
+ */
199
+ var ValiError = class extends Error {
200
+ /**
201
+ * Creates a Valibot error with useful information.
202
+ *
203
+ * @param issues The error issues.
204
+ */
205
+ constructor(issues) {
206
+ super(issues[0].message);
207
+ this.name = "ValiError";
208
+ this.issues = issues;
209
+ }
210
+ };
211
+ /**
212
+ * Creates a description metadata action.
213
+ *
214
+ * @param description_ The description text.
215
+ *
216
+ * @returns A description action.
217
+ */
218
+ /* @__NO_SIDE_EFFECTS__ */
219
+ function description(description_) {
220
+ return {
221
+ kind: "metadata",
222
+ type: "description",
223
+ reference: description,
224
+ description: description_
225
+ };
226
+ }
227
+ /**
228
+ * Returns the fallback value of the schema.
229
+ *
230
+ * @param schema The schema to get it from.
231
+ * @param dataset The output dataset if available.
232
+ * @param config The config if available.
233
+ *
234
+ * @returns The fallback value.
235
+ */
236
+ /* @__NO_SIDE_EFFECTS__ */
237
+ function getFallback(schema, dataset, config$1) {
238
+ return typeof schema.fallback === "function" ? schema.fallback(dataset, config$1) : schema.fallback;
239
+ }
240
+ /**
241
+ * Returns the default value of the schema.
242
+ *
243
+ * @param schema The schema to get it from.
244
+ * @param dataset The input dataset if available.
245
+ * @param config The config if available.
246
+ *
247
+ * @returns The default value.
248
+ */
249
+ /* @__NO_SIDE_EFFECTS__ */
250
+ function getDefault(schema, dataset, config$1) {
251
+ return typeof schema.default === "function" ? schema.default(dataset, config$1) : schema.default;
252
+ }
253
+ /**
254
+ * Returns the description of the schema.
255
+ *
256
+ * If multiple descriptions are defined, the last one of the highest level is
257
+ * returned. If no description is defined, `undefined` is returned.
258
+ *
259
+ * @param schema The schema to get the description from.
260
+ *
261
+ * @returns The description, if any.
262
+ *
263
+ * @beta
264
+ */
265
+ /* @__NO_SIDE_EFFECTS__ */
266
+ function getDescription(schema) {
267
+ return /* @__PURE__ */ _getLastMetadata(schema, "description");
268
+ }
269
+ /* @__NO_SIDE_EFFECTS__ */
270
+ function array(item, message$1) {
271
+ return {
272
+ kind: "schema",
273
+ type: "array",
274
+ reference: array,
275
+ expects: "Array",
276
+ async: false,
277
+ item,
278
+ message: message$1,
279
+ get "~standard"() {
280
+ return /* @__PURE__ */ _getStandardProps(this);
281
+ },
282
+ "~run"(dataset, config$1) {
283
+ const input = dataset.value;
284
+ if (Array.isArray(input)) {
285
+ dataset.typed = true;
286
+ dataset.value = [];
287
+ for (let key = 0; key < input.length; key++) {
288
+ const value$1 = input[key];
289
+ const itemDataset = this.item["~run"]({ value: value$1 }, config$1);
290
+ if (itemDataset.issues) {
291
+ const pathItem = {
292
+ type: "array",
293
+ origin: "value",
294
+ input,
295
+ key,
296
+ value: value$1
297
+ };
298
+ for (const issue of itemDataset.issues) {
299
+ if (issue.path) issue.path.unshift(pathItem);
300
+ else issue.path = [pathItem];
301
+ dataset.issues?.push(issue);
302
+ }
303
+ if (!dataset.issues) dataset.issues = itemDataset.issues;
304
+ if (config$1.abortEarly) {
305
+ dataset.typed = false;
306
+ break;
307
+ }
308
+ }
309
+ if (!itemDataset.typed) dataset.typed = false;
310
+ dataset.value.push(itemDataset.value);
311
+ }
312
+ } else _addIssue(this, "type", dataset, config$1);
313
+ return dataset;
314
+ }
315
+ };
316
+ }
317
+ /* @__NO_SIDE_EFFECTS__ */
318
+ function boolean(message$1) {
319
+ return {
320
+ kind: "schema",
321
+ type: "boolean",
322
+ reference: boolean,
323
+ expects: "boolean",
324
+ async: false,
325
+ message: message$1,
326
+ get "~standard"() {
327
+ return /* @__PURE__ */ _getStandardProps(this);
328
+ },
329
+ "~run"(dataset, config$1) {
330
+ if (typeof dataset.value === "boolean") dataset.typed = true;
331
+ else _addIssue(this, "type", dataset, config$1);
332
+ return dataset;
333
+ }
334
+ };
335
+ }
336
+ /* @__NO_SIDE_EFFECTS__ */
337
+ function number(message$1) {
338
+ return {
339
+ kind: "schema",
340
+ type: "number",
341
+ reference: number,
342
+ expects: "number",
343
+ async: false,
344
+ message: message$1,
345
+ get "~standard"() {
346
+ return /* @__PURE__ */ _getStandardProps(this);
347
+ },
348
+ "~run"(dataset, config$1) {
349
+ if (typeof dataset.value === "number" && !isNaN(dataset.value)) dataset.typed = true;
350
+ else _addIssue(this, "type", dataset, config$1);
351
+ return dataset;
352
+ }
353
+ };
354
+ }
355
+ /* @__NO_SIDE_EFFECTS__ */
356
+ function object(entries$1, message$1) {
357
+ return {
358
+ kind: "schema",
359
+ type: "object",
360
+ reference: object,
361
+ expects: "Object",
362
+ async: false,
363
+ entries: entries$1,
364
+ message: message$1,
365
+ get "~standard"() {
366
+ return /* @__PURE__ */ _getStandardProps(this);
367
+ },
368
+ "~run"(dataset, config$1) {
369
+ const input = dataset.value;
370
+ if (input && typeof input === "object") {
371
+ dataset.typed = true;
372
+ dataset.value = {};
373
+ for (const key in this.entries) {
374
+ const valueSchema = this.entries[key];
375
+ if (key in input || (valueSchema.type === "exact_optional" || valueSchema.type === "optional" || valueSchema.type === "nullish") && valueSchema.default !== void 0) {
376
+ const value$1 = key in input ? input[key] : /* @__PURE__ */ getDefault(valueSchema);
377
+ const valueDataset = valueSchema["~run"]({ value: value$1 }, config$1);
378
+ if (valueDataset.issues) {
379
+ const pathItem = {
380
+ type: "object",
381
+ origin: "value",
382
+ input,
383
+ key,
384
+ value: value$1
385
+ };
386
+ for (const issue of valueDataset.issues) {
387
+ if (issue.path) issue.path.unshift(pathItem);
388
+ else issue.path = [pathItem];
389
+ dataset.issues?.push(issue);
390
+ }
391
+ if (!dataset.issues) dataset.issues = valueDataset.issues;
392
+ if (config$1.abortEarly) {
393
+ dataset.typed = false;
394
+ break;
395
+ }
396
+ }
397
+ if (!valueDataset.typed) dataset.typed = false;
398
+ dataset.value[key] = valueDataset.value;
399
+ } else if (valueSchema.fallback !== void 0) dataset.value[key] = /* @__PURE__ */ getFallback(valueSchema);
400
+ else if (valueSchema.type !== "exact_optional" && valueSchema.type !== "optional" && valueSchema.type !== "nullish") {
401
+ _addIssue(this, "key", dataset, config$1, {
402
+ input: void 0,
403
+ expected: `"${key}"`,
404
+ path: [{
405
+ type: "object",
406
+ origin: "key",
407
+ input,
408
+ key,
409
+ value: input[key]
410
+ }]
411
+ });
412
+ if (config$1.abortEarly) break;
413
+ }
414
+ }
415
+ } else _addIssue(this, "type", dataset, config$1);
416
+ return dataset;
417
+ }
418
+ };
419
+ }
420
+ /* @__NO_SIDE_EFFECTS__ */
421
+ function picklist(options, message$1) {
422
+ return {
423
+ kind: "schema",
424
+ type: "picklist",
425
+ reference: picklist,
426
+ expects: /* @__PURE__ */ _joinExpects(options.map(_stringify), "|"),
427
+ async: false,
428
+ options,
429
+ message: message$1,
430
+ get "~standard"() {
431
+ return /* @__PURE__ */ _getStandardProps(this);
432
+ },
433
+ "~run"(dataset, config$1) {
434
+ if (this.options.includes(dataset.value)) dataset.typed = true;
435
+ else _addIssue(this, "type", dataset, config$1);
436
+ return dataset;
437
+ }
438
+ };
439
+ }
440
+ /* @__NO_SIDE_EFFECTS__ */
441
+ function string(message$1) {
442
+ return {
443
+ kind: "schema",
444
+ type: "string",
445
+ reference: string,
446
+ expects: "string",
447
+ async: false,
448
+ message: message$1,
449
+ get "~standard"() {
450
+ return /* @__PURE__ */ _getStandardProps(this);
451
+ },
452
+ "~run"(dataset, config$1) {
453
+ if (typeof dataset.value === "string") dataset.typed = true;
454
+ else _addIssue(this, "type", dataset, config$1);
455
+ return dataset;
456
+ }
457
+ };
458
+ }
459
+ /**
460
+ * Parses an unknown input based on a schema.
461
+ *
462
+ * @param schema The schema to be used.
463
+ * @param input The input to be parsed.
464
+ * @param config The parse configuration.
465
+ *
466
+ * @returns The parsed input.
467
+ */
468
+ function parse(schema, input, config$1) {
469
+ const dataset = schema["~run"]({ value: input }, /* @__PURE__ */ getGlobalConfig(config$1));
470
+ if (dataset.issues) throw new ValiError(dataset.issues);
471
+ return dataset.value;
472
+ }
473
+ /* @__NO_SIDE_EFFECTS__ */
474
+ function pipe(...pipe$1) {
475
+ return {
476
+ ...pipe$1[0],
477
+ pipe: pipe$1,
478
+ get "~standard"() {
479
+ return /* @__PURE__ */ _getStandardProps(this);
480
+ },
481
+ "~run"(dataset, config$1) {
482
+ for (const item of pipe$1) if (item.kind !== "metadata") {
483
+ if (dataset.issues && (item.kind === "schema" || item.kind === "transformation")) {
484
+ dataset.typed = false;
485
+ break;
486
+ }
487
+ if (!dataset.issues || !config$1.abortEarly && !config$1.abortPipeEarly) dataset = item["~run"](dataset, config$1);
488
+ }
489
+ return dataset;
490
+ }
491
+ };
492
+ }
493
+ //#endregion
494
+ //#region ../../node_modules/.pnpm/@moeru+std@0.1.0-beta.20/node_modules/@moeru/std/dist/error/index.js
495
+ const isError = (err) => {
496
+ if ("isError" in Error && Error.isError(new DOMException())) return Error.isError(err);
497
+ if (err === null || typeof err !== "object" && typeof err !== "function") return false;
498
+ if (err instanceof Error) return true;
499
+ const tag = Object.prototype.toString.call(err);
500
+ return tag === "[object DOMException]" || tag === "[object Error]";
501
+ };
502
+ const isErrorLike = (err) => {
503
+ if (isError(err)) return true;
504
+ if (err == null || typeof err !== "object" && typeof err !== "function") return false;
505
+ return "message" in err && typeof err.message === "string" && "name" in err && typeof err.name === "string";
506
+ };
507
+ const errorMessageFrom = (err) => isErrorLike(err) ? err.message : err == null ? void 0 : String(err);
508
+ //#endregion
509
+ //#region ../../node_modules/.pnpm/@moeru+std@0.1.0-beta.20/node_modules/@moeru/std/dist/sleep/index.js
510
+ const sleep = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
511
+ const sleepWithAbort = async (ms, signal) => {
512
+ if (!signal) return sleep(ms);
513
+ return new Promise((resolve, reject) => {
514
+ if (signal.aborted) {
515
+ reject(signal.reason ?? new DOMException("Aborted", "AbortError"));
516
+ return;
517
+ }
518
+ const timer = setTimeout(() => {
519
+ signal.removeEventListener("abort", onAbort);
520
+ resolve();
521
+ }, ms);
522
+ signal.addEventListener("abort", onAbort, { once: true });
523
+ function onAbort() {
524
+ clearTimeout(timer);
525
+ signal?.removeEventListener("abort", onAbort);
526
+ reject(signal?.reason ?? new DOMException("Aborted", "AbortError"));
527
+ }
528
+ });
529
+ };
530
+ //#endregion
531
+ //#region ../../node_modules/.pnpm/@valibot+to-json-schema@1.7.1_valibot@1.4.2_typescript@6.0.3_/node_modules/@valibot/to-json-schema/dist/index.mjs
532
+ var dist_exports = /* @__PURE__ */ __exportAll({
533
+ addGlobalDefs: () => addGlobalDefs,
534
+ getGlobalDefs: () => getGlobalDefs,
535
+ toJsonSchema: () => toJsonSchema,
536
+ toJsonSchemaDefs: () => toJsonSchemaDefs,
537
+ toStandardJsonSchema: () => toStandardJsonSchema
538
+ });
539
+ /**
540
+ * Adds an error message to the errors array.
541
+ *
542
+ * @param errors The array of error messages.
543
+ * @param message The error message to add.
544
+ *
545
+ * @returns The new errors.
546
+ */
547
+ function addError(errors, message) {
548
+ if (errors) {
549
+ errors.push(message);
550
+ return errors;
551
+ }
552
+ return [message];
553
+ }
554
+ const ESCAPE_REGEX = /[.*+?^${}()|[\]\\]/g;
555
+ /**
556
+ * Escapes special regex characters in a string.
557
+ *
558
+ * @param string The string to escape.
559
+ *
560
+ * @returns The escaped string.
561
+ */
562
+ function escapeRegExp(string) {
563
+ return string.replace(ESCAPE_REGEX, "\\$&");
564
+ }
565
+ /**
566
+ * Throws an error or logs a warning based on the configuration.
567
+ *
568
+ * @param message The message to throw or log.
569
+ * @param config The conversion configuration.
570
+ */
571
+ function handleError(message, config) {
572
+ switch (config?.errorMode) {
573
+ case "ignore": break;
574
+ case "warn":
575
+ console.warn(message);
576
+ break;
577
+ default: throw new Error(message);
578
+ }
579
+ }
580
+ /**
581
+ * Whether a value is JSON compatible for a const keyword.
582
+ *
583
+ * @param value The value to check.
584
+ *
585
+ * @returns Whether the value is JSON compatible.
586
+ */
587
+ function isJsonConstValue(value) {
588
+ return typeof value === "boolean" || typeof value === "number" && Number.isFinite(value) || typeof value === "string";
589
+ }
590
+ /**
591
+ * Whether values are JSON compatible for an enum keyword.
592
+ *
593
+ * @param values The values to check.
594
+ *
595
+ * @returns Whether the values are JSON compatible.
596
+ */
597
+ function isJsonEnumValues(values) {
598
+ return values.every(isJsonConstValue);
599
+ }
600
+ /**
601
+ * Converts any supported Valibot action to the JSON Schema format.
602
+ *
603
+ * @param jsonSchema The JSON Schema object.
604
+ * @param valibotAction The Valibot action object.
605
+ * @param config The conversion configuration.
606
+ *
607
+ * @returns The converted JSON Schema.
608
+ */
609
+ function convertAction(jsonSchema, valibotAction, config) {
610
+ if (config?.ignoreActions?.includes(valibotAction.type)) return jsonSchema;
611
+ let errors;
612
+ switch (valibotAction.type) {
613
+ case "base64":
614
+ jsonSchema.contentEncoding = "base64";
615
+ break;
616
+ case "bic":
617
+ case "cuid2":
618
+ case "decimal":
619
+ case "digits":
620
+ case "domain":
621
+ case "emoji":
622
+ case "hash":
623
+ case "hexadecimal":
624
+ case "hex_color":
625
+ case "isrc":
626
+ case "iso_time_second":
627
+ case "iso_week":
628
+ case "mac":
629
+ case "mac48":
630
+ case "mac64":
631
+ case "nanoid":
632
+ case "octal":
633
+ case "slug":
634
+ case "ulid":
635
+ if (jsonSchema.pattern) errors = addError(errors, `The "${valibotAction.type}" action is not supported in combination with another regex action.`);
636
+ else jsonSchema.pattern = valibotAction.requirement.source;
637
+ break;
638
+ case "description":
639
+ jsonSchema.description = valibotAction.description;
640
+ break;
641
+ case "email":
642
+ case "rfc_email":
643
+ jsonSchema.format = "email";
644
+ break;
645
+ case "ends_with":
646
+ if (jsonSchema.pattern) errors = addError(errors, `The "${valibotAction.type}" action is not supported in combination with another regex action.`);
647
+ else jsonSchema.pattern = `${escapeRegExp(valibotAction.requirement)}$`;
648
+ break;
649
+ case "empty":
650
+ if (jsonSchema.type === "array") jsonSchema.maxItems = 0;
651
+ else {
652
+ if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
653
+ jsonSchema.maxLength = 0;
654
+ }
655
+ break;
656
+ case "entries":
657
+ jsonSchema.minProperties = valibotAction.requirement;
658
+ jsonSchema.maxProperties = valibotAction.requirement;
659
+ break;
660
+ case "examples":
661
+ if (Array.isArray(jsonSchema.examples)) jsonSchema.examples = [...jsonSchema.examples, ...valibotAction.examples];
662
+ else jsonSchema.examples = valibotAction.examples;
663
+ break;
664
+ case "gt_value":
665
+ if (jsonSchema.type !== "number" && jsonSchema.type !== "integer") errors = addError(errors, `The "gt_value" action is not supported on type "${jsonSchema.type}".`);
666
+ if (config?.target === "openapi-3.0") {
667
+ errors = addError(errors, "The \"gt_value\" action is not supported for OpenAPI 3.0.");
668
+ break;
669
+ }
670
+ jsonSchema.exclusiveMinimum = valibotAction.requirement;
671
+ break;
672
+ case "includes":
673
+ if (jsonSchema.pattern) errors = addError(errors, `The "${valibotAction.type}" action is not supported in combination with another regex action.`);
674
+ else jsonSchema.pattern = escapeRegExp(valibotAction.requirement);
675
+ break;
676
+ case "integer":
677
+ jsonSchema.type = "integer";
678
+ break;
679
+ case "ipv4":
680
+ jsonSchema.format = "ipv4";
681
+ break;
682
+ case "ipv6":
683
+ jsonSchema.format = "ipv6";
684
+ break;
685
+ case "iso_date":
686
+ jsonSchema.format = "date";
687
+ break;
688
+ case "iso_date_time":
689
+ case "iso_timestamp":
690
+ jsonSchema.format = "date-time";
691
+ break;
692
+ case "iso_time":
693
+ jsonSchema.format = "time";
694
+ break;
695
+ case "jws_compact":
696
+ if (jsonSchema.pattern) errors = addError(errors, `The "${valibotAction.type}" action is not supported in combination with another regex action.`);
697
+ else jsonSchema.pattern = valibotAction.requirement.source;
698
+ break;
699
+ case "length":
700
+ if (jsonSchema.type === "array") {
701
+ jsonSchema.minItems = valibotAction.requirement;
702
+ jsonSchema.maxItems = valibotAction.requirement;
703
+ } else {
704
+ if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
705
+ jsonSchema.minLength = valibotAction.requirement;
706
+ jsonSchema.maxLength = valibotAction.requirement;
707
+ }
708
+ break;
709
+ case "lt_value":
710
+ if (jsonSchema.type !== "number" && jsonSchema.type !== "integer") errors = addError(errors, `The "lt_value" action is not supported on type "${jsonSchema.type}".`);
711
+ if (config?.target === "openapi-3.0") {
712
+ errors = addError(errors, "The \"lt_value\" action is not supported for OpenAPI 3.0.");
713
+ break;
714
+ }
715
+ jsonSchema.exclusiveMaximum = valibotAction.requirement;
716
+ break;
717
+ case "max_entries":
718
+ jsonSchema.maxProperties = valibotAction.requirement;
719
+ break;
720
+ case "max_length":
721
+ if (jsonSchema.type === "array") jsonSchema.maxItems = valibotAction.requirement;
722
+ else {
723
+ if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
724
+ jsonSchema.maxLength = valibotAction.requirement;
725
+ }
726
+ break;
727
+ case "max_value":
728
+ if (jsonSchema.type !== "number" && jsonSchema.type !== "integer") errors = addError(errors, `The "max_value" action is not supported on type "${jsonSchema.type}".`);
729
+ jsonSchema.maximum = valibotAction.requirement;
730
+ break;
731
+ case "metadata":
732
+ if (typeof valibotAction.metadata.title === "string") jsonSchema.title = valibotAction.metadata.title;
733
+ if (typeof valibotAction.metadata.description === "string") jsonSchema.description = valibotAction.metadata.description;
734
+ if (Array.isArray(valibotAction.metadata.examples)) if (Array.isArray(jsonSchema.examples)) jsonSchema.examples = [...jsonSchema.examples, ...valibotAction.metadata.examples];
735
+ else jsonSchema.examples = valibotAction.metadata.examples;
736
+ break;
737
+ case "min_entries":
738
+ jsonSchema.minProperties = valibotAction.requirement;
739
+ break;
740
+ case "min_length":
741
+ if (jsonSchema.type === "array") jsonSchema.minItems = valibotAction.requirement;
742
+ else {
743
+ if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
744
+ jsonSchema.minLength = valibotAction.requirement;
745
+ }
746
+ break;
747
+ case "min_value":
748
+ if (jsonSchema.type !== "number" && jsonSchema.type !== "integer") errors = addError(errors, `The "min_value" action is not supported on type "${jsonSchema.type}".`);
749
+ jsonSchema.minimum = valibotAction.requirement;
750
+ break;
751
+ case "multiple_of":
752
+ jsonSchema.multipleOf = valibotAction.requirement;
753
+ break;
754
+ case "non_empty":
755
+ if (jsonSchema.type === "array") jsonSchema.minItems = 1;
756
+ else {
757
+ if (jsonSchema.type !== "string") errors = addError(errors, `The "${valibotAction.type}" action is not supported on type "${jsonSchema.type}".`);
758
+ jsonSchema.minLength = 1;
759
+ }
760
+ break;
761
+ case "not_value":
762
+ if (!isJsonConstValue(valibotAction.requirement)) {
763
+ errors = addError(errors, "The requirement of the \"not_value\" action is not JSON compatible.");
764
+ break;
765
+ }
766
+ if (config?.target === "openapi-3.0") jsonSchema.not = { enum: [valibotAction.requirement] };
767
+ else jsonSchema.not = { const: valibotAction.requirement };
768
+ break;
769
+ case "not_values":
770
+ if (!isJsonEnumValues(valibotAction.requirement)) {
771
+ errors = addError(errors, "A requirement of the \"not_values\" action is not JSON compatible.");
772
+ break;
773
+ }
774
+ jsonSchema.not = { enum: valibotAction.requirement };
775
+ break;
776
+ case "regex":
777
+ if (valibotAction.requirement.flags) errors = addError(errors, "RegExp flags are not supported by JSON Schema.");
778
+ if (jsonSchema.pattern) errors = addError(errors, `The "${valibotAction.type}" action is not supported in combination with another regex action.`);
779
+ else jsonSchema.pattern = valibotAction.requirement.source;
780
+ break;
781
+ case "safe_integer":
782
+ jsonSchema.type = "integer";
783
+ if (typeof jsonSchema.minimum !== "number" || jsonSchema.minimum < Number.MIN_SAFE_INTEGER) jsonSchema.minimum = Number.MIN_SAFE_INTEGER;
784
+ if (typeof jsonSchema.maximum !== "number" || jsonSchema.maximum > Number.MAX_SAFE_INTEGER) jsonSchema.maximum = Number.MAX_SAFE_INTEGER;
785
+ break;
786
+ case "starts_with":
787
+ if (jsonSchema.pattern) errors = addError(errors, `The "${valibotAction.type}" action is not supported in combination with another regex action.`);
788
+ else jsonSchema.pattern = `^${escapeRegExp(valibotAction.requirement)}`;
789
+ break;
790
+ case "title":
791
+ jsonSchema.title = valibotAction.title;
792
+ break;
793
+ case "url":
794
+ jsonSchema.format = "uri";
795
+ break;
796
+ case "uuid":
797
+ jsonSchema.format = "uuid";
798
+ break;
799
+ case "value":
800
+ if (!isJsonConstValue(valibotAction.requirement)) {
801
+ errors = addError(errors, "The requirement of the \"value\" action is not JSON compatible.");
802
+ break;
803
+ }
804
+ if (config?.target === "openapi-3.0") jsonSchema.enum = [valibotAction.requirement];
805
+ else jsonSchema.const = valibotAction.requirement;
806
+ break;
807
+ case "values":
808
+ if (!isJsonEnumValues(valibotAction.requirement)) {
809
+ errors = addError(errors, "A requirement of the \"values\" action is not JSON compatible.");
810
+ break;
811
+ }
812
+ jsonSchema.enum = valibotAction.requirement;
813
+ break;
814
+ default: errors = addError(errors, `The "${valibotAction.type}" action cannot be converted to JSON Schema.`);
815
+ }
816
+ if (config?.overrideAction) {
817
+ const actionOverride = config.overrideAction({
818
+ valibotAction,
819
+ jsonSchema,
820
+ errors
821
+ });
822
+ if (actionOverride) return { ...actionOverride };
823
+ }
824
+ if (errors) for (const message of errors) handleError(message, config);
825
+ return jsonSchema;
826
+ }
827
+ /**
828
+ * Flattens a Valibot pipe by recursively expanding nested pipes.
829
+ *
830
+ * @param pipe The pipeline to flatten.
831
+ *
832
+ * @returns A flat pipeline.
833
+ */
834
+ function flattenPipe(pipe) {
835
+ return pipe.flatMap((item) => "pipe" in item ? flattenPipe(item.pipe) : item);
836
+ }
837
+ /**
838
+ * Returns the JSON Pointer reference for a definition key.
839
+ *
840
+ * @param referenceId The unescaped definition key.
841
+ *
842
+ * @returns The encoded JSON Pointer fragment.
843
+ */
844
+ function getDefinitionRef(referenceId) {
845
+ return `#/$defs/${referenceId.replaceAll("~", "~0").replaceAll("/", "~1")}`;
846
+ }
847
+ let refCount = 0;
848
+ /**
849
+ * Converts any supported Valibot schema to the JSON Schema format.
850
+ *
851
+ * @param jsonSchema The JSON Schema object.
852
+ * @param valibotSchema The Valibot schema object.
853
+ * @param config The conversion configuration.
854
+ * @param context The conversion context.
855
+ * @param skipRef Whether to skip using a reference.
856
+ *
857
+ * @returns The converted JSON Schema.
858
+ */
859
+ function convertSchema(jsonSchema, valibotSchema, config, context, skipRef = false) {
860
+ if (!skipRef) {
861
+ const referenceId = context.referenceMap.get(valibotSchema);
862
+ if (referenceId) {
863
+ jsonSchema.$ref = getDefinitionRef(referenceId);
864
+ if (config?.overrideRef) {
865
+ const refOverride = config.overrideRef({
866
+ ...context,
867
+ referenceId,
868
+ valibotSchema,
869
+ jsonSchema
870
+ });
871
+ if (refOverride) jsonSchema.$ref = refOverride;
872
+ }
873
+ return jsonSchema;
874
+ }
875
+ }
876
+ if ("pipe" in valibotSchema) {
877
+ const flatPipe = flattenPipe(valibotSchema.pipe);
878
+ let startIndex = 0;
879
+ let stopIndex = flatPipe.length - 1;
880
+ if (config?.typeMode === "input") {
881
+ const inputStopIndex = flatPipe.slice(1).findIndex((item) => item.kind === "schema" || item.kind === "transformation" && (item.type === "find_item" || item.type === "parse_json" || item.type === "raw_transform" || item.type === "reduce_items" || item.type === "stringify_json" || item.type === "to_bigint" || item.type === "to_boolean" || item.type === "to_date" || item.type === "to_number" || item.type === "to_string" || item.type === "transform"));
882
+ if (inputStopIndex !== -1) stopIndex = inputStopIndex;
883
+ } else if (config?.typeMode === "output") {
884
+ const outputStartIndex = flatPipe.findLastIndex((item) => item.kind === "schema");
885
+ if (outputStartIndex !== -1) startIndex = outputStartIndex;
886
+ }
887
+ for (let index = startIndex; index <= stopIndex; index++) {
888
+ const valibotPipeItem = flatPipe[index];
889
+ if (valibotPipeItem.kind === "schema") {
890
+ if (index > startIndex) handleError("Set the \"typeMode\" config to \"input\" or \"output\" to convert pipelines with multiple schemas.", config);
891
+ jsonSchema = convertSchema(jsonSchema, valibotPipeItem, config, context, true);
892
+ } else jsonSchema = convertAction(jsonSchema, valibotPipeItem, config);
893
+ }
894
+ return jsonSchema;
895
+ }
896
+ let errors;
897
+ switch (valibotSchema.type) {
898
+ case "boolean":
899
+ jsonSchema.type = "boolean";
900
+ break;
901
+ case "null":
902
+ if (config?.target === "openapi-3.0") jsonSchema.enum = [null];
903
+ else jsonSchema.type = "null";
904
+ break;
905
+ case "number":
906
+ jsonSchema.type = "number";
907
+ break;
908
+ case "string":
909
+ jsonSchema.type = "string";
910
+ break;
911
+ case "array":
912
+ jsonSchema.type = "array";
913
+ jsonSchema.items = convertSchema({}, valibotSchema.item, config, context);
914
+ break;
915
+ case "tuple":
916
+ case "tuple_with_rest":
917
+ case "loose_tuple":
918
+ case "strict_tuple":
919
+ jsonSchema.type = "array";
920
+ if (config?.target === "openapi-3.0") {
921
+ jsonSchema.items = { anyOf: [] };
922
+ jsonSchema.minItems = valibotSchema.items.length;
923
+ for (const item of valibotSchema.items) jsonSchema.items.anyOf.push(convertSchema({}, item, config, context));
924
+ if (valibotSchema.type === "tuple_with_rest") jsonSchema.items.anyOf.push(convertSchema({}, valibotSchema.rest, config, context));
925
+ else if (valibotSchema.type === "strict_tuple" || valibotSchema.type === "tuple") jsonSchema.maxItems = valibotSchema.items.length;
926
+ } else if (config?.target === "draft-2020-12") {
927
+ jsonSchema.prefixItems = [];
928
+ jsonSchema.minItems = valibotSchema.items.length;
929
+ for (const item of valibotSchema.items) jsonSchema.prefixItems.push(convertSchema({}, item, config, context));
930
+ if (valibotSchema.type === "tuple_with_rest") jsonSchema.items = convertSchema({}, valibotSchema.rest, config, context);
931
+ else if (valibotSchema.type === "strict_tuple") jsonSchema.items = false;
932
+ } else {
933
+ jsonSchema.items = [];
934
+ jsonSchema.minItems = valibotSchema.items.length;
935
+ for (const item of valibotSchema.items) jsonSchema.items.push(convertSchema({}, item, config, context));
936
+ if (valibotSchema.type === "tuple_with_rest") jsonSchema.additionalItems = convertSchema({}, valibotSchema.rest, config, context);
937
+ else if (valibotSchema.type === "strict_tuple") jsonSchema.additionalItems = false;
938
+ }
939
+ break;
940
+ case "object":
941
+ case "object_with_rest":
942
+ case "loose_object":
943
+ case "strict_object":
944
+ jsonSchema.type = "object";
945
+ jsonSchema.properties = {};
946
+ jsonSchema.required = [];
947
+ for (const key in valibotSchema.entries) {
948
+ const entry = valibotSchema.entries[key];
949
+ jsonSchema.properties[key] = convertSchema({}, entry, config, context);
950
+ if (entry.type !== "exact_optional" && entry.type !== "nullish" && entry.type !== "optional") jsonSchema.required.push(key);
951
+ }
952
+ if (valibotSchema.type === "object_with_rest") jsonSchema.additionalProperties = convertSchema({}, valibotSchema.rest, config, context);
953
+ else if (valibotSchema.type === "strict_object") jsonSchema.additionalProperties = false;
954
+ break;
955
+ case "record":
956
+ if (config?.target === "openapi-3.0" && "pipe" in valibotSchema.key) errors = addError(errors, "The \"record\" schema with a schema for the key that contains a \"pipe\" cannot be converted to JSON Schema.");
957
+ if (valibotSchema.key.type !== "string") errors = addError(errors, `The "record" schema with the "${valibotSchema.key.type}" schema for the key cannot be converted to JSON Schema.`);
958
+ jsonSchema.type = "object";
959
+ if (config?.target !== "openapi-3.0") jsonSchema.propertyNames = convertSchema({}, valibotSchema.key, config, context);
960
+ jsonSchema.additionalProperties = convertSchema({}, valibotSchema.value, config, context);
961
+ break;
962
+ case "any":
963
+ case "unknown": break;
964
+ case "never":
965
+ jsonSchema.not = {};
966
+ break;
967
+ case "nullable":
968
+ case "nullish":
969
+ if (config?.target === "openapi-3.0") {
970
+ const innerSchema = convertSchema({}, valibotSchema.wrapped, config, context);
971
+ Object.assign(jsonSchema, innerSchema);
972
+ jsonSchema.nullable = true;
973
+ } else jsonSchema.anyOf = [convertSchema({}, valibotSchema.wrapped, config, context), { type: "null" }];
974
+ if (valibotSchema.default !== void 0) jsonSchema.default = typeof valibotSchema.default === "function" ? valibotSchema.default() : valibotSchema.default;
975
+ break;
976
+ case "exact_optional":
977
+ case "optional":
978
+ case "undefinedable":
979
+ jsonSchema = convertSchema(jsonSchema, valibotSchema.wrapped, config, context);
980
+ if (valibotSchema.default !== void 0) jsonSchema.default = typeof valibotSchema.default === "function" ? valibotSchema.default() : valibotSchema.default;
981
+ break;
982
+ case "literal":
983
+ if (typeof valibotSchema.literal !== "boolean" && typeof valibotSchema.literal !== "number" && typeof valibotSchema.literal !== "string") errors = addError(errors, "The value of the \"literal\" schema is not JSON compatible.");
984
+ if (config?.target === "openapi-3.0") jsonSchema.enum = [valibotSchema.literal];
985
+ else jsonSchema.const = valibotSchema.literal;
986
+ break;
987
+ case "enum":
988
+ jsonSchema.enum = valibotSchema.options;
989
+ if (valibotSchema.options.every((option) => typeof option === "string")) jsonSchema.type = "string";
990
+ else if (valibotSchema.options.every((option) => typeof option === "number")) jsonSchema.type = "number";
991
+ else if (config?.target !== "openapi-3.0") jsonSchema.type = ["string", "number"];
992
+ break;
993
+ case "picklist": {
994
+ const hasInvalidOption = valibotSchema.options.some((option) => typeof option !== "number" && typeof option !== "string");
995
+ if (hasInvalidOption) errors = addError(errors, "An option of the \"picklist\" schema is not JSON compatible.");
996
+ jsonSchema.enum = valibotSchema.options;
997
+ if (valibotSchema.options.every((option) => typeof option === "string")) jsonSchema.type = "string";
998
+ else if (valibotSchema.options.every((option) => typeof option === "number")) jsonSchema.type = "number";
999
+ else if (!hasInvalidOption && config?.target !== "openapi-3.0") jsonSchema.type = ["string", "number"];
1000
+ break;
1001
+ }
1002
+ case "union":
1003
+ jsonSchema.anyOf = valibotSchema.options.map((option) => convertSchema({}, option, config, context));
1004
+ break;
1005
+ case "variant":
1006
+ jsonSchema.oneOf = valibotSchema.options.map((option) => convertSchema({}, option, config, context));
1007
+ break;
1008
+ case "intersect":
1009
+ jsonSchema.allOf = valibotSchema.options.map((option) => convertSchema({}, option, config, context));
1010
+ break;
1011
+ case "lazy": {
1012
+ let wrappedValibotSchema = context.getterMap.get(valibotSchema.getter);
1013
+ if (!wrappedValibotSchema) {
1014
+ wrappedValibotSchema = valibotSchema.getter(void 0);
1015
+ context.getterMap.set(valibotSchema.getter, wrappedValibotSchema);
1016
+ }
1017
+ let referenceId = context.referenceMap.get(wrappedValibotSchema);
1018
+ if (!referenceId) {
1019
+ referenceId = `${refCount++}`;
1020
+ context.referenceMap.set(wrappedValibotSchema, referenceId);
1021
+ context.definitions[referenceId] = convertSchema({}, wrappedValibotSchema, config, context, true);
1022
+ }
1023
+ jsonSchema.$ref = getDefinitionRef(referenceId);
1024
+ if (config?.overrideRef) {
1025
+ const refOverride = config.overrideRef({
1026
+ ...context,
1027
+ referenceId,
1028
+ valibotSchema: wrappedValibotSchema,
1029
+ jsonSchema
1030
+ });
1031
+ if (refOverride) jsonSchema.$ref = refOverride;
1032
+ }
1033
+ break;
1034
+ }
1035
+ default: errors = addError(errors, `The "${valibotSchema.type}" schema cannot be converted to JSON Schema.`);
1036
+ }
1037
+ if (config?.overrideSchema) {
1038
+ const schemaOverride = config.overrideSchema({
1039
+ ...context,
1040
+ referenceId: context.referenceMap.get(valibotSchema),
1041
+ valibotSchema,
1042
+ jsonSchema,
1043
+ errors
1044
+ });
1045
+ if (schemaOverride) return { ...schemaOverride };
1046
+ }
1047
+ if (errors) for (const message of errors) handleError(message, config);
1048
+ return jsonSchema;
1049
+ }
1050
+ let store;
1051
+ /**
1052
+ * Adds new definitions to the global schema definitions.
1053
+ *
1054
+ * @param definitions The schema definitions.
1055
+ *
1056
+ * @beta
1057
+ */
1058
+ function addGlobalDefs(definitions) {
1059
+ store = {
1060
+ ...store ?? {},
1061
+ ...definitions
1062
+ };
1063
+ }
1064
+ /**
1065
+ * Returns the current global schema definitions.
1066
+ *
1067
+ * @returns The schema definitions.
1068
+ *
1069
+ * @beta
1070
+ */
1071
+ function getGlobalDefs() {
1072
+ return store;
1073
+ }
1074
+ /**
1075
+ * Converts a Valibot schema to the JSON Schema format.
1076
+ *
1077
+ * @param schema The Valibot schema object.
1078
+ * @param config The JSON Schema configuration.
1079
+ *
1080
+ * @returns The converted JSON Schema.
1081
+ */
1082
+ function toJsonSchema(schema, config) {
1083
+ const context = {
1084
+ definitions: {},
1085
+ referenceMap: /* @__PURE__ */ new Map(),
1086
+ getterMap: /* @__PURE__ */ new Map()
1087
+ };
1088
+ const definitions = config?.definitions ?? getGlobalDefs();
1089
+ if (definitions) {
1090
+ for (const key in definitions) context.referenceMap.set(definitions[key], key);
1091
+ for (const key in definitions) context.definitions[key] = convertSchema({}, definitions[key], config, context, true);
1092
+ }
1093
+ const jsonSchema = convertSchema({}, schema, config, context);
1094
+ const target = config?.target ?? "draft-07";
1095
+ if (target === "draft-2020-12") jsonSchema.$schema = "https://json-schema.org/draft/2020-12/schema";
1096
+ else if (target === "draft-07") jsonSchema.$schema = "http://json-schema.org/draft-07/schema#";
1097
+ if (context.referenceMap.size) jsonSchema.$defs = context.definitions;
1098
+ return jsonSchema;
1099
+ }
1100
+ /**
1101
+ * Converts Valibot schema definitions to JSON Schema definitions.
1102
+ *
1103
+ * @param definitions The Valibot schema definitions.
1104
+ * @param config The JSON Schema configuration.
1105
+ *
1106
+ * @returns The converted JSON Schema definitions.
1107
+ */
1108
+ function toJsonSchemaDefs(definitions, config) {
1109
+ const context = {
1110
+ definitions: {},
1111
+ referenceMap: /* @__PURE__ */ new Map(),
1112
+ getterMap: /* @__PURE__ */ new Map()
1113
+ };
1114
+ for (const key in definitions) context.referenceMap.set(definitions[key], key);
1115
+ for (const key in definitions) context.definitions[key] = convertSchema({}, definitions[key], config, context, true);
1116
+ return context.definitions;
1117
+ }
1118
+ const SUPPORTED_TARGETS = [
1119
+ "draft-07",
1120
+ "draft-2020-12",
1121
+ "openapi-3.0"
1122
+ ];
1123
+ /**
1124
+ * Converts a Valibot schema to the Standard JSON Schema format.
1125
+ *
1126
+ * @param schema The Valibot schema object.
1127
+ *
1128
+ * @returns The Standard JSON Schema.
1129
+ */
1130
+ function toStandardJsonSchema(schema) {
1131
+ return { "~standard": {
1132
+ ...schema["~standard"],
1133
+ jsonSchema: {
1134
+ input(options) {
1135
+ if (SUPPORTED_TARGETS.includes(options.target)) return toJsonSchema(schema, {
1136
+ typeMode: "input",
1137
+ target: options.target,
1138
+ ...options.libraryOptions
1139
+ });
1140
+ throw new Error(`Unsupported target: ${options.target}`);
1141
+ },
1142
+ output(options) {
1143
+ if (SUPPORTED_TARGETS.includes(options.target)) return toJsonSchema(schema, {
1144
+ typeMode: "output",
1145
+ target: options.target,
1146
+ ...options.libraryOptions
1147
+ });
1148
+ throw new Error(`Unsupported target: ${options.target}`);
1149
+ }
1150
+ }
1151
+ } };
1152
+ }
1153
+ //#endregion
1154
+ //#region ../../node_modules/.pnpm/@xsai+shared@0.5.0-beta.7/node_modules/@xsai/shared/dist/index.js
1155
+ var XSAIError = class extends Error {
1156
+ constructor(message, code, options = {}) {
1157
+ super(message, { cause: options.cause });
1158
+ this.code = code;
1159
+ this.name = new.target.name;
1160
+ }
1161
+ static isInstance(error) {
1162
+ return error instanceof this;
1163
+ }
1164
+ };
1165
+ var APICallError = class extends XSAIError {
1166
+ constructor(message, options) {
1167
+ super(message, "api_call_error", options);
1168
+ this.requestBody = options.requestBody;
1169
+ this.response = options.response;
1170
+ this.responseBody = options.responseBody;
1171
+ this.responseHeaders = Object.fromEntries(options.response.headers.entries());
1172
+ this.statusCode = options.response.status;
1173
+ this.statusText = options.response.statusText;
1174
+ this.url = options.response.url;
1175
+ }
1176
+ };
1177
+ var InvalidResponseError = class extends XSAIError {
1178
+ constructor(message, options) {
1179
+ super(message, "invalid_response", options);
1180
+ Object.assign(this, options);
1181
+ }
1182
+ };
1183
+ var InvalidToolCallError = class extends XSAIError {
1184
+ constructor(message, options) {
1185
+ super(message, "invalid_tool_call", options);
1186
+ Object.assign(this, options);
1187
+ }
1188
+ };
1189
+ var InvalidToolInputError = class extends XSAIError {
1190
+ constructor(message, options) {
1191
+ super(message, "invalid_tool_input", options);
1192
+ Object.assign(this, options);
1193
+ }
1194
+ };
1195
+ var JSONParseError = class extends XSAIError {
1196
+ constructor(message, options) {
1197
+ super(message, "json_parse_error", options);
1198
+ this.text = options.text;
1199
+ }
1200
+ };
1201
+ var ToolExecutionError = class extends XSAIError {
1202
+ constructor(message, options) {
1203
+ super(message, "tool_execution_error", options);
1204
+ Object.assign(this, options);
1205
+ }
1206
+ };
1207
+ const strCamelToSnake = (str) => str.replace(/[A-Z]/g, (s) => `_${s.toLowerCase()}`);
1208
+ const objCamelToSnake = (obj) => Object.fromEntries(Object.entries(obj).map(([k, v]) => [strCamelToSnake(k), v]));
1209
+ const clean = (obj) => Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== void 0));
1210
+ const requestBody = (body) => JSON.stringify(objCamelToSnake(clean({
1211
+ ...body,
1212
+ abortSignal: void 0,
1213
+ apiKey: void 0,
1214
+ baseURL: void 0,
1215
+ fetch: void 0,
1216
+ headers: void 0
1217
+ })));
1218
+ const requestHeaders = (headers, apiKey) => clean({
1219
+ Authorization: apiKey !== void 0 ? `Bearer ${apiKey}` : void 0,
1220
+ ...headers
1221
+ });
1222
+ const requestURL = (path, baseURL) => {
1223
+ const base = baseURL.toString();
1224
+ return new URL(path, base.endsWith("/") ? base : `${base}/`);
1225
+ };
1226
+ const responseCatch = async (res) => {
1227
+ if (!res.ok) {
1228
+ const responseBody = await res.text();
1229
+ throw new APICallError(`Remote sent ${res.status} response: ${responseBody}`, {
1230
+ response: res,
1231
+ responseBody
1232
+ });
1233
+ }
1234
+ if (!res.body) throw new InvalidResponseError("Response body is empty from remote server", {
1235
+ reason: "empty_body",
1236
+ response: res
1237
+ });
1238
+ if (!(res.body instanceof ReadableStream)) {
1239
+ const contentType = res.headers.get("Content-Type");
1240
+ throw new InvalidResponseError(`Expected Response body to be a ReadableStream, but got ${String(res.body)}; Content Type is ${contentType}`, {
1241
+ body: res.body,
1242
+ contentType,
1243
+ reason: "invalid_body",
1244
+ response: res
1245
+ });
1246
+ }
1247
+ return res;
1248
+ };
1249
+ const postJSON = async (path, options) => (options.fetch ?? globalThis.fetch)(requestURL(path, options.baseURL), {
1250
+ body: requestBody(options),
1251
+ headers: requestHeaders({
1252
+ "Content-Type": "application/json",
1253
+ ...options.headers
1254
+ }, options.apiKey),
1255
+ method: "POST",
1256
+ signal: options.abortSignal
1257
+ }).then(responseCatch);
1258
+ const responseJSON = async (res) => {
1259
+ const text = await res.text();
1260
+ try {
1261
+ return JSON.parse(text);
1262
+ } catch (cause) {
1263
+ throw new JSONParseError(`Failed to parse response, response body: ${text}`, {
1264
+ cause,
1265
+ text
1266
+ });
1267
+ }
1268
+ };
1269
+ const trampoline = async (fn) => {
1270
+ let result = await fn();
1271
+ while (result instanceof Function) result = await result();
1272
+ return result;
1273
+ };
1274
+ //#endregion
1275
+ //#region ../../node_modules/.pnpm/@xsai+shared-chat@0.5.0-beta.7/node_modules/@xsai/shared-chat/dist/index.js
1276
+ const chat = async (options) => postJSON("chat/completions", {
1277
+ ...options,
1278
+ maxSteps: void 0,
1279
+ onEvent: void 0,
1280
+ onFinish: void 0,
1281
+ onStepFinish: void 0,
1282
+ postToolCall: void 0,
1283
+ prepareStep: void 0,
1284
+ preToolCall: void 0,
1285
+ stopWhen: void 0,
1286
+ tools: options.tools?.map(({ execute: _execute, ...tool }) => tool)
1287
+ });
1288
+ const toToolMessageContent = (result) => {
1289
+ if (typeof result === "string") return result;
1290
+ if (Array.isArray(result)) {
1291
+ if (result.every((item) => item !== null && typeof item === "object" && "type" in item && [
1292
+ "file",
1293
+ "image_url",
1294
+ "input_audio",
1295
+ "text"
1296
+ ].includes(item.type))) return result;
1297
+ }
1298
+ return JSON.stringify(result);
1299
+ };
1300
+ const isAbortError = (error, abortSignal) => abortSignal?.aborted === true && error === abortSignal.reason || error instanceof Error && error.name === "AbortError";
1301
+ const parseToolInput = async (tool, input) => {
1302
+ let result;
1303
+ try {
1304
+ result = JSON.parse(input.trim() || "{}");
1305
+ } catch (cause) {
1306
+ throw new InvalidToolInputError(`Failed to parse tool input for "${tool.function.name}".`, {
1307
+ cause,
1308
+ toolInput: input,
1309
+ toolName: tool.function.name
1310
+ });
1311
+ }
1312
+ if (tool.validate) {
1313
+ const validated = await tool.validate(result);
1314
+ if (validated.issues) throw new InvalidToolInputError(`Tool input validation failed for "${tool.function.name}".`, {
1315
+ cause: validated.issues,
1316
+ toolInput: result,
1317
+ toolName: tool.function.name
1318
+ });
1319
+ result = validated.value;
1320
+ }
1321
+ return result;
1322
+ };
1323
+ const runTool = async (tool, options) => {
1324
+ try {
1325
+ return await tool.execute(options.args, options.toolExecuteOptions);
1326
+ } catch (cause) {
1327
+ if (isAbortError(cause, options.toolExecuteOptions.abortSignal)) throw cause;
1328
+ throw new ToolExecutionError(`Tool "${tool.function.name}" execution failed.`, {
1329
+ cause,
1330
+ toolCallId: options.toolExecuteOptions.toolCallId,
1331
+ toolInput: options.args,
1332
+ toolName: tool.function.name
1333
+ });
1334
+ }
1335
+ };
1336
+ const assertSameToolCallId = (source, next, label) => {
1337
+ if (source === next.toolCallId) return;
1338
+ throw new InvalidToolCallError(`${label} must preserve toolCallId "${source}".`, {
1339
+ reason: "tool_call_id_mismatch",
1340
+ toolCall: next
1341
+ });
1342
+ };
1343
+ const findTool = (tools, toolName, toolCall) => {
1344
+ const tool = tools?.find((tool2) => tool2.function.name === toolName);
1345
+ if (!tool) {
1346
+ const availableTools = tools?.map((tool2) => tool2.function.name);
1347
+ throw new InvalidToolCallError(`Model tried to call unavailable tool "${toolName}", ${availableTools == null || availableTools.length === 0 ? "No tools are available" : `Available tools: ${availableTools.join(", ")}`}.`, {
1348
+ availableTools,
1349
+ reason: "unknown_tool",
1350
+ toolCall,
1351
+ toolName
1352
+ });
1353
+ }
1354
+ return tool;
1355
+ };
1356
+ const executeTool = async ({ abortSignal, messages, postToolCall, preToolCall, toolCall, tools, wrapResult }) => {
1357
+ const wrap = wrapResult ?? toToolMessageContent;
1358
+ const toolName = toolCall.function.name;
1359
+ const toolArguments = toolCall.function.arguments;
1360
+ if (toolName == null) throw new InvalidToolCallError(`Missing toolCall.function.name: ${JSON.stringify(toolCall)}`, {
1361
+ reason: "missing_name",
1362
+ toolCall
1363
+ });
1364
+ if (toolArguments == null) throw new InvalidToolCallError(`Missing toolCall.function.arguments: ${JSON.stringify(toolCall)}`, {
1365
+ reason: "missing_arguments",
1366
+ toolCall
1367
+ });
1368
+ const toolExecuteOptions = {
1369
+ abortSignal,
1370
+ messages,
1371
+ toolCallId: toolCall.id
1372
+ };
1373
+ let completionToolCall = {
1374
+ args: toolArguments,
1375
+ toolCallId: toolCall.id,
1376
+ toolCallType: "function",
1377
+ toolName
1378
+ };
1379
+ let completionToolResult;
1380
+ const preToolCallResult = await preToolCall?.(completionToolCall, toolExecuteOptions);
1381
+ if (preToolCallResult) {
1382
+ assertSameToolCallId(completionToolCall.toolCallId, preToolCallResult, "preToolCallResult");
1383
+ if ("result" in preToolCallResult) completionToolResult = preToolCallResult;
1384
+ else completionToolCall = preToolCallResult;
1385
+ }
1386
+ if (completionToolResult == null) {
1387
+ const tool = findTool(tools, completionToolCall.toolName, completionToolCall);
1388
+ const args = await parseToolInput(tool, completionToolCall.args);
1389
+ completionToolResult = {
1390
+ args,
1391
+ result: await runTool(tool, {
1392
+ args,
1393
+ toolExecuteOptions
1394
+ }),
1395
+ toolCallId: completionToolCall.toolCallId,
1396
+ toolName: completionToolCall.toolName
1397
+ };
1398
+ }
1399
+ const postToolCallResult = await postToolCall?.(completionToolResult, toolExecuteOptions);
1400
+ if (postToolCallResult) {
1401
+ assertSameToolCallId(completionToolResult.toolCallId, postToolCallResult, "postToolCallResult");
1402
+ completionToolResult = postToolCallResult;
1403
+ }
1404
+ return {
1405
+ completionToolCall,
1406
+ completionToolResult,
1407
+ result: wrap(completionToolResult.result)
1408
+ };
1409
+ };
1410
+ const resolvePrepareStep = async ({ input, model, prepareStep, stepNumber, steps, toolChoice }) => {
1411
+ const prepared = prepareStep == null ? void 0 : await prepareStep({
1412
+ input: structuredClone(input),
1413
+ model,
1414
+ stepNumber,
1415
+ steps: structuredClone(steps)
1416
+ });
1417
+ return {
1418
+ input: prepared?.input != null ? structuredClone(prepared.input) : input,
1419
+ model: prepared?.model ?? model,
1420
+ toolChoice: prepared?.toolChoice ?? toolChoice
1421
+ };
1422
+ };
1423
+ const stepCountAtLeast = (count) => ({ steps }) => steps.length >= count;
1424
+ const shouldStop = (stopWhen, context) => stopWhen(context);
1425
+ const computeTotalUsage = (totalUsage, usage) => totalUsage == null ? usage : {
1426
+ inputTokens: totalUsage.inputTokens + usage.inputTokens,
1427
+ outputTokens: totalUsage.outputTokens + usage.outputTokens,
1428
+ totalTokens: totalUsage.totalTokens + usage.totalTokens
1429
+ };
1430
+ const normalizeChatCompletionUsage = (usage) => ({
1431
+ inputTokens: usage.prompt_tokens,
1432
+ outputTokens: usage.completion_tokens,
1433
+ totalTokens: usage.total_tokens
1434
+ });
1435
+ //#endregion
1436
+ //#region ../../node_modules/.pnpm/@xsai+generate-text@0.5.0-beta.7/node_modules/@xsai/generate-text/dist/index.js
1437
+ const rawGenerateText = async (options) => {
1438
+ const messages = options.steps == null ? structuredClone(options.messages) : options.messages;
1439
+ const steps = options.steps ?? [];
1440
+ const stepOptions = await resolvePrepareStep({
1441
+ input: messages,
1442
+ model: options.model,
1443
+ prepareStep: options.prepareStep,
1444
+ stepNumber: steps.length,
1445
+ steps,
1446
+ toolChoice: options.toolChoice
1447
+ });
1448
+ return chat({
1449
+ ...options,
1450
+ messages: stepOptions.input,
1451
+ model: stepOptions.model,
1452
+ steps: void 0,
1453
+ stream: false,
1454
+ toolChoice: stepOptions.toolChoice,
1455
+ totalUsage: void 0
1456
+ }).then(responseJSON).then(async (res) => {
1457
+ const { choices } = res;
1458
+ const usage = normalizeChatCompletionUsage(res.usage);
1459
+ const totalUsage = computeTotalUsage(options.totalUsage, usage);
1460
+ if (!choices?.length) {
1461
+ const responseBody = JSON.stringify(res);
1462
+ throw new InvalidResponseError(`No choices returned, response body: ${responseBody}`, {
1463
+ reason: "no_choices",
1464
+ responseBody
1465
+ });
1466
+ }
1467
+ const toolCalls = [];
1468
+ const toolResults = [];
1469
+ const { finish_reason: finishReason, message } = choices[0];
1470
+ const msgToolCalls = message?.tool_calls ?? [];
1471
+ const stopWhen = options.stopWhen ?? stepCountAtLeast(1);
1472
+ messages.push(message);
1473
+ if (msgToolCalls.length > 0) {
1474
+ const results = await Promise.all(msgToolCalls.map(async (toolCall) => executeTool({
1475
+ abortSignal: options.abortSignal,
1476
+ messages,
1477
+ postToolCall: options.postToolCall,
1478
+ preToolCall: options.preToolCall,
1479
+ toolCall,
1480
+ tools: options.tools
1481
+ })));
1482
+ for (const { completionToolCall, completionToolResult, result } of results) {
1483
+ toolCalls.push(completionToolCall);
1484
+ toolResults.push(completionToolResult);
1485
+ messages.push({
1486
+ content: result,
1487
+ role: "tool",
1488
+ tool_call_id: completionToolCall.toolCallId
1489
+ });
1490
+ }
1491
+ }
1492
+ const step = {
1493
+ finishReason,
1494
+ text: Array.isArray(message.content) ? message.content.filter((m) => m.type === "text").map((m) => m.text).join("\n") : message.content,
1495
+ toolCalls,
1496
+ toolResults,
1497
+ usage
1498
+ };
1499
+ const stop = shouldStop(stopWhen, {
1500
+ input: messages,
1501
+ step,
1502
+ steps: [...steps, step]
1503
+ });
1504
+ const willContinue = toolCalls.length > 0 && !stop;
1505
+ steps.push(step);
1506
+ if (options.onStepFinish) await options.onStepFinish(step);
1507
+ if (!willContinue) return {
1508
+ finishReason: step.finishReason,
1509
+ messages,
1510
+ reasoningText: message.reasoning ?? message.reasoning_content,
1511
+ steps,
1512
+ text: step.text,
1513
+ toolCalls: step.toolCalls,
1514
+ toolResults: step.toolResults,
1515
+ totalUsage,
1516
+ usage: step.usage
1517
+ };
1518
+ else return async () => rawGenerateText({
1519
+ ...options,
1520
+ messages,
1521
+ steps,
1522
+ totalUsage
1523
+ });
1524
+ });
1525
+ };
1526
+ const generateText = async (options) => trampoline(async () => rawGenerateText(options));
1527
+ //#endregion
1528
+ //#region ../../node_modules/.pnpm/@xsai+tool@0.5.0-beta.7_@valibot+to-json-schema@1.7.1_valibot@1.4.2_typescript@6.0.3____927f6822d23b3a98d537f6f3dbeccc01/node_modules/@xsai/tool/dist/index.js
1529
+ const rawTool = ({ description, execute, name, parameters, strict }) => ({
1530
+ execute,
1531
+ function: {
1532
+ description,
1533
+ name,
1534
+ parameters: strict !== false ? strictJsonSchema(parameters) : parameters,
1535
+ strict: strict ?? true
1536
+ },
1537
+ type: "function"
1538
+ });
1539
+ //#endregion
1540
+ //#region ../core/dist/structured-output.mjs
1541
+ const defaultMaxAttempts = 3;
1542
+ const defaultToolName = "reportFindings";
1543
+ var InvalidStructuredOutputError = class extends Error {
1544
+ constructor(message) {
1545
+ super(message);
1546
+ this.name = "InvalidStructuredOutputError";
1547
+ }
1548
+ };
1549
+ /** Standard instruction line for localized judge findings; undefined when no language is configured. */
1550
+ function formatOutputLanguageInstruction(outputLanguage) {
1551
+ return outputLanguage ? `Write all human-readable finding messages and suggestions in this language: ${outputLanguage}.` : void 0;
1552
+ }
1553
+ /** Prefixes each line with its 1-based number so schemas can ask for "left-column line numbers". */
1554
+ function formatSourceWithLineNumbers(source) {
1555
+ return source.split("\n").map((line, index) => `${index + 1} | ${line}`).join("\n");
1556
+ }
1557
+ /**
1558
+ * Forces the model to call a single reporting tool and returns the validated
1559
+ * tool arguments, so a tool call doubles as structured output. Unlike
1560
+ * `response_format`-based structured output (xsai's `generateObject`), a
1561
+ * forced tool call works on any provider with function calling, and invalid
1562
+ * payloads are retried with validation feedback instead of failing outright.
1563
+ */
1564
+ async function generateStructured(options) {
1565
+ const maxAttempts = options.maxAttempts ?? defaultMaxAttempts;
1566
+ const retryDelay = options.retryDelay ?? exponentialRetryDelay;
1567
+ const toolName = options.toolName ?? defaultToolName;
1568
+ const tool = rawTool({
1569
+ description: options.toolDescription ?? /* @__PURE__ */ getDescription(options.schema),
1570
+ execute: (input) => asRecord(input) ?? {},
1571
+ name: toolName,
1572
+ parameters: toolParametersFromSchema(options.schema),
1573
+ strict: true
1574
+ });
1575
+ let previousError;
1576
+ for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
1577
+ options.signal?.throwIfAborted();
1578
+ let response;
1579
+ try {
1580
+ options.signal?.throwIfAborted();
1581
+ response = await generateText({
1582
+ abortSignal: options.signal,
1583
+ baseURL: options.model.provider.endpoint,
1584
+ headers: options.model.provider.headers,
1585
+ messages: options.createMessages(previousError ? retryFeedbackFrom(toolName, previousError) : void 0),
1586
+ model: options.model.id,
1587
+ parallelToolCalls: false,
1588
+ temperature: options.temperature ?? 0,
1589
+ toolChoice: {
1590
+ function: { name: toolName },
1591
+ type: "function"
1592
+ },
1593
+ tools: [tool]
1594
+ });
1595
+ } catch (error) {
1596
+ options.signal?.throwIfAborted();
1597
+ const callError = `Tool call failed before validation: ${errorMessageFrom(error) ?? String(error)}`;
1598
+ previousError = isRetriableHttpError(error) ? void 0 : callError;
1599
+ options.logger?.debug(`${options.operation} attempt ${attempt} failed while calling the model: ${callError}`);
1600
+ if (!isRetriableCallError(error) || attempt === maxAttempts) throw error;
1601
+ await sleepWithAbort(retryDelay(attempt), options.signal);
1602
+ continue;
1603
+ }
1604
+ recordAttemptUsage(options, response);
1605
+ const result = parseStructuredResponse(options.schema, toolName, response);
1606
+ if (result.ok) return result.value;
1607
+ previousError = result.error;
1608
+ options.logger?.debug(`${options.operation} attempt ${attempt} returned an invalid structured result: ${previousError}`);
1609
+ if (!result.retriable || attempt === maxAttempts) throw new InvalidStructuredOutputError(`Invalid structured model response: ${previousError}`);
1610
+ await sleepWithAbort(retryDelay(attempt), options.signal);
1611
+ }
1612
+ throw new InvalidStructuredOutputError("Model did not return a valid structured result");
1613
+ }
1614
+ function normalizeToolJsonSchema(schema) {
1615
+ const normalized = normalizeJsonSchemaDefinition(schema);
1616
+ return typeof normalized === "boolean" ? {} : normalized;
1617
+ }
1618
+ /** Converts a valibot schema into provider-compliant strict tool parameters. */
1619
+ function toolParametersFromSchema(schema) {
1620
+ return normalizeToolJsonSchema(toJsonSchema(schema));
1621
+ }
1622
+ function asRecord(value) {
1623
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
1624
+ }
1625
+ function exponentialRetryDelay(attempt) {
1626
+ return 500 * 2 ** (attempt - 1);
1627
+ }
1628
+ function isRetriableCallError(error) {
1629
+ if (!(error instanceof Error)) return true;
1630
+ if (isRetriableHttpError(error)) return true;
1631
+ return error.name === "InvalidToolCallError" || error.name === "InvalidToolInputError" || error.name === "ToolExecutionError";
1632
+ }
1633
+ function isRetriableHttpError(error) {
1634
+ if (!(error instanceof Error)) return false;
1635
+ const statusCode = "statusCode" in error && typeof error.statusCode === "number" ? error.statusCode : void 0;
1636
+ return statusCode !== void 0 && (statusCode >= 500 || [408, 429].includes(statusCode));
1637
+ }
1638
+ function normalizeJsonSchemaDefinition(schema) {
1639
+ if (typeof schema === "boolean") return schema;
1640
+ const normalized = { ...schema };
1641
+ delete normalized.$schema;
1642
+ if (normalized.type === "object") normalized.additionalProperties = false;
1643
+ if (normalized.properties) {
1644
+ normalized.properties = Object.fromEntries(Object.entries(normalized.properties).map(([key, propertySchema]) => [key, normalizeJsonSchemaDefinition(propertySchema)]));
1645
+ normalized.required = Object.keys(normalized.properties);
1646
+ }
1647
+ if (normalized.items) normalized.items = Array.isArray(normalized.items) ? normalized.items.map((item) => normalizeJsonSchemaDefinition(item)) : normalizeJsonSchemaDefinition(normalized.items);
1648
+ if (normalized.$defs) normalized.$defs = normalizeJsonSchemaMap(normalized.$defs);
1649
+ if (normalized.definitions) normalized.definitions = normalizeJsonSchemaMap(normalized.definitions);
1650
+ for (const key of [
1651
+ "allOf",
1652
+ "anyOf",
1653
+ "oneOf"
1654
+ ]) if (normalized[key]) normalized[key] = normalized[key].map((item) => normalizeJsonSchemaDefinition(item));
1655
+ if (normalized.not) normalized.not = normalizeJsonSchemaDefinition(normalized.not);
1656
+ return normalized;
1657
+ }
1658
+ function normalizeJsonSchemaMap(map) {
1659
+ return Object.fromEntries(Object.entries(map).map(([key, schema]) => [key, normalizeJsonSchemaDefinition(schema)]));
1660
+ }
1661
+ function normalizeUsage(usage) {
1662
+ const record = asRecord(usage);
1663
+ if (!record) return;
1664
+ const normalized = {
1665
+ inputTokens: numberFromRecord(record, "inputTokens") ?? numberFromRecord(record, "input_tokens") ?? numberFromRecord(record, "prompt_tokens"),
1666
+ outputTokens: numberFromRecord(record, "outputTokens") ?? numberFromRecord(record, "output_tokens") ?? numberFromRecord(record, "completion_tokens"),
1667
+ totalTokens: numberFromRecord(record, "totalTokens") ?? numberFromRecord(record, "total_tokens")
1668
+ };
1669
+ return Object.values(normalized).some((value) => value !== void 0) ? normalized : void 0;
1670
+ }
1671
+ function numberFromRecord(record, key) {
1672
+ const value = record[key];
1673
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1674
+ }
1675
+ function parseStructuredResponse(schema, toolName, response) {
1676
+ if (response.finishReason === "content_filter") return {
1677
+ error: `${toolName} was not returned because the model finished with content_filter`,
1678
+ ok: false,
1679
+ retriable: false
1680
+ };
1681
+ if (response.finishReason === "length") return {
1682
+ error: `${toolName} was not returned completely because the model finished with length`,
1683
+ ok: false,
1684
+ retriable: true
1685
+ };
1686
+ const toolResults = response.toolResults.filter((result) => result.toolName === toolName);
1687
+ if (toolResults.length === 0) return {
1688
+ error: `Missing ${toolName} tool result; finishReason=${response.finishReason}`,
1689
+ ok: false,
1690
+ retriable: true
1691
+ };
1692
+ if (toolResults.length > 1) return {
1693
+ error: `Expected one ${toolName} tool result, received ${toolResults.length}`,
1694
+ ok: false,
1695
+ retriable: true
1696
+ };
1697
+ try {
1698
+ return {
1699
+ ok: true,
1700
+ value: parse(schema, toolResults[0].result)
1701
+ };
1702
+ } catch (error) {
1703
+ return {
1704
+ error: errorMessageFrom(error) ?? String(error),
1705
+ ok: false,
1706
+ retriable: true
1707
+ };
1708
+ }
1709
+ }
1710
+ function recordAttemptUsage(options, response) {
1711
+ const usage = normalizeUsage(response.usage);
1712
+ if (!options.metering || !usage) return;
1713
+ options.metering.recordUsage({
1714
+ inputTokens: usage.inputTokens,
1715
+ metadata: { operation: options.operation },
1716
+ modelId: options.model.id,
1717
+ outputTokens: usage.outputTokens,
1718
+ providerId: options.model.provider.id,
1719
+ totalTokens: usage.totalTokens
1720
+ });
1721
+ }
1722
+ function retryFeedbackFrom(toolName, error) {
1723
+ return [
1724
+ "Your previous tool call could not be validated.",
1725
+ `Validation error: ${error}`,
1726
+ `Call ${toolName} again with arguments that exactly match the tool schema.`
1727
+ ].join("\n");
1728
+ }
48
1729
  //#endregion
49
1730
  //#region src/agents/judge/agent.ts
50
- const judgeFindingSchema = pipe(object({
51
- confidence: pipe(picklist([
1731
+ const judgeFindingSchema = /* @__PURE__ */ pipe(/* @__PURE__ */ object({
1732
+ confidence: /* @__PURE__ */ pipe(/* @__PURE__ */ picklist([
52
1733
  "high",
53
1734
  "medium",
54
1735
  "low"
55
- ]), description("Confidence in this finding. Use exactly \"low\", \"medium\", or \"high\" without punctuation.")),
56
- line: pipe(number(), description([
1736
+ ]), /* @__PURE__ */ description("Confidence in this finding. Use exactly \"low\", \"medium\", or \"high\" without punctuation.")),
1737
+ line: /* @__PURE__ */ pipe(/* @__PURE__ */ number(), /* @__PURE__ */ description([
57
1738
  "Use the declaration line of the specific symbol being reported.",
58
1739
  "Use the left-column line number from the numbered code block.",
59
1740
  "Do not use a nearby caller line unless that caller is the symbol being reported."
60
1741
  ].join(" "))),
61
- message: pipe(string(), description([
1742
+ message: /* @__PURE__ */ pipe(/* @__PURE__ */ string(), /* @__PURE__ */ description([
62
1743
  "Mention the specific symbol being reported.",
63
1744
  "Explain the rule-specific design or readability smell.",
64
1745
  "Do not list unrelated symbol names in the message.",
65
1746
  "Keep the message short."
66
1747
  ].join(" "))),
67
- suggestion: pipe(string(), description([
1748
+ suggestion: /* @__PURE__ */ pipe(/* @__PURE__ */ string(), /* @__PURE__ */ description([
68
1749
  "Provide one concrete remediation direction.",
69
1750
  "Do not propose a code patch.",
70
1751
  "Keep the suggestion under 35 words."
71
1752
  ].join(" ")))
72
- }), description("One warning-level report for a rule-specific design or readability smell."));
73
- const judgeResponseSchema = pipe(object({ findings: pipe(array(judgeFindingSchema), description("All warning-level findings. Return an empty array when there is no qualifying issue for the current rule.")) }), description("Report findings for this TypeScript file."));
1753
+ }), /* @__PURE__ */ description("One warning-level report for a rule-specific design or readability smell."));
1754
+ const judgeResponseSchema = /* @__PURE__ */ pipe(/* @__PURE__ */ object({ findings: /* @__PURE__ */ pipe(/* @__PURE__ */ array(judgeFindingSchema), /* @__PURE__ */ description("All warning-level findings. Return an empty array when there is no qualifying issue for the current rule.")) }), /* @__PURE__ */ description("Report findings for this TypeScript file."));
74
1755
  function createJudgeMessages(source, retryFeedback, outputLanguage, prompt) {
75
1756
  return [
76
1757
  {
@@ -309,8 +1990,8 @@ function createRedundantBindingVerificationPrompt(candidates) {
309
1990
  "</discovery-data>"
310
1991
  ].join("\n");
311
1992
  }
312
- const verificationResponseSchema = pipe(object({ decisions: pipe(array(object({
313
- boundary: pipe(picklist([
1993
+ const verificationResponseSchema = /* @__PURE__ */ pipe(/* @__PURE__ */ object({ decisions: /* @__PURE__ */ pipe(/* @__PURE__ */ array(/* @__PURE__ */ object({
1994
+ boundary: /* @__PURE__ */ pipe(/* @__PURE__ */ picklist([
314
1995
  "none",
315
1996
  "snapshot-or-restoration",
316
1997
  "receiver",
@@ -319,24 +2000,24 @@ const verificationResponseSchema = pipe(object({ decisions: pipe(array(object({
319
2000
  "mutable-work-state",
320
2001
  "type-or-domain",
321
2002
  "uncertain"
322
- ]), description("The concrete semantic boundary, or \"none\" only when no boundary exists.")),
323
- confidence: pipe(picklist([
2003
+ ]), /* @__PURE__ */ description("The concrete semantic boundary, or \"none\" only when no boundary exists.")),
2004
+ confidence: /* @__PURE__ */ pipe(/* @__PURE__ */ picklist([
324
2005
  "high",
325
2006
  "medium",
326
2007
  "low"
327
- ]), description("Confidence in this verification decision.")),
328
- initializer: pipe(picklist([
2008
+ ]), /* @__PURE__ */ description("Confidence in this verification decision.")),
2009
+ initializer: /* @__PURE__ */ pipe(/* @__PURE__ */ picklist([
329
2010
  "identifier",
330
2011
  "static-member-access",
331
2012
  "indexed-or-dynamic",
332
2013
  "computed-or-constructed",
333
2014
  "uncertain"
334
- ]), description("Classify the complete initializer. Bracket access belongs to \"indexed-or-dynamic\", never \"static-member-access\".")),
335
- line: pipe(number(), description("One candidate declaration line supplied by discovery. Never add another line.")),
336
- message: pipe(string(), description("Explain why the candidate qualifies or which exclusion rejects it.")),
337
- safeSubstitution: pipe(boolean(), description("True only when every use can be replaced by the exact initializer without semantic change.")),
338
- suggestion: pipe(string(), description("For accepted candidates, give a direct-use remediation under 35 words; otherwise briefly state the preserved boundary."))
339
- })), description("One verification decision per supplied candidate line. Omit no candidate and add no line.")) }), description("Strict verification decisions for discovered rebinding candidates."));
2015
+ ]), /* @__PURE__ */ description("Classify the complete initializer. Bracket access belongs to \"indexed-or-dynamic\", never \"static-member-access\".")),
2016
+ line: /* @__PURE__ */ pipe(/* @__PURE__ */ number(), /* @__PURE__ */ description("One candidate declaration line supplied by discovery. Never add another line.")),
2017
+ message: /* @__PURE__ */ pipe(/* @__PURE__ */ string(), /* @__PURE__ */ description("Explain why the candidate qualifies or which exclusion rejects it.")),
2018
+ safeSubstitution: /* @__PURE__ */ pipe(/* @__PURE__ */ boolean(), /* @__PURE__ */ description("True only when every use can be replaced by the exact initializer without semantic change.")),
2019
+ suggestion: /* @__PURE__ */ pipe(/* @__PURE__ */ string(), /* @__PURE__ */ description("For accepted candidates, give a direct-use remediation under 35 words; otherwise briefly state the preserved boundary."))
2020
+ })), /* @__PURE__ */ description("One verification decision per supplied candidate line. Omit no candidate and add no line.")) }), /* @__PURE__ */ description("Strict verification decisions for discovered rebinding candidates."));
340
2021
  function acceptedVerificationDecisions(decisions) {
341
2022
  return decisions.filter((decision) => (decision.initializer === "identifier" || decision.initializer === "static-member-access") && decision.boundary === "none" && decision.safeSubstitution).map((decision) => ({
342
2023
  confidence: decision.confidence,
@@ -654,4 +2335,4 @@ const examplePlugin = definePlugin({
654
2335
  }
655
2336
  });
656
2337
  //#endregion
657
- export { createJudgeMessages, createReportFindingsToolParameters, examplePlugin as default, examplePlugin, inlineMiniatureNormalizerPrompt, inlineMiniatureNormalizerRule, judgeFindingSchema, judgeResponseSchema, privateSchemaToolkitPrompt, privateSchemaToolkitRule, redundantBindingPrompt, redundantBindingRule, redundantJsdocPrompt, redundantJsdocRule, trivialWrapperStackPrompt, trivialWrapperStackRule, vacuousFunctionPrompt, vacuousFunctionRule };
2338
+ export { createJudgeMessages, createReportFindingsToolParameters, examplePlugin as default, examplePlugin, inlineMiniatureNormalizerPrompt, inlineMiniatureNormalizerRule, judgeFindingSchema, judgeResponseSchema, privateSchemaToolkitPrompt, privateSchemaToolkitRule, redundantBindingPrompt, redundantBindingRule, redundantJsdocPrompt, redundantJsdocRule, dist_exports as t, trivialWrapperStackPrompt, trivialWrapperStackRule, vacuousFunctionPrompt, vacuousFunctionRule };