@aeye/core 0.5.4 → 0.7.0

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.
Files changed (124) hide show
  1. package/README.md +790 -724
  2. package/aeye-core-prompts.md +179 -178
  3. package/aeye-core-schema.md +43 -16
  4. package/aeye-core-tools.md +179 -177
  5. package/aeye-core-types.md +1 -0
  6. package/dist/common.d.ts +30 -5
  7. package/dist/common.d.ts.map +1 -1
  8. package/dist/common.js +134 -129
  9. package/dist/common.js.map +1 -1
  10. package/dist/delivery.d.ts +39 -0
  11. package/dist/delivery.d.ts.map +1 -0
  12. package/dist/delivery.js +127 -0
  13. package/dist/delivery.js.map +1 -0
  14. package/dist/errors.d.ts +60 -0
  15. package/dist/errors.d.ts.map +1 -0
  16. package/dist/errors.js +84 -0
  17. package/dist/errors.js.map +1 -0
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +2 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/prompt.d.ts +134 -15
  23. package/dist/prompt.d.ts.map +1 -1
  24. package/dist/prompt.js +220 -164
  25. package/dist/prompt.js.map +1 -1
  26. package/dist/schema/analyze.d.ts +94 -0
  27. package/dist/schema/analyze.d.ts.map +1 -0
  28. package/dist/schema/analyze.js +221 -0
  29. package/dist/schema/analyze.js.map +1 -0
  30. package/dist/schema/any-value.d.ts +32 -0
  31. package/dist/schema/any-value.d.ts.map +1 -0
  32. package/dist/schema/any-value.js +77 -0
  33. package/dist/schema/any-value.js.map +1 -0
  34. package/dist/schema/budget.d.ts +114 -0
  35. package/dist/schema/budget.d.ts.map +1 -0
  36. package/dist/schema/budget.js +223 -0
  37. package/dist/schema/budget.js.map +1 -0
  38. package/dist/schema/check-bag.d.ts +28 -0
  39. package/dist/schema/check-bag.d.ts.map +1 -0
  40. package/dist/schema/check-bag.js +129 -0
  41. package/dist/schema/check-bag.js.map +1 -0
  42. package/dist/schema/consistency.d.ts +27 -0
  43. package/dist/schema/consistency.d.ts.map +1 -0
  44. package/dist/schema/consistency.js +110 -0
  45. package/dist/schema/consistency.js.map +1 -0
  46. package/dist/schema/cycle-breaker.d.ts +14 -0
  47. package/dist/schema/cycle-breaker.d.ts.map +1 -0
  48. package/dist/schema/cycle-breaker.js +157 -0
  49. package/dist/schema/cycle-breaker.js.map +1 -0
  50. package/dist/schema/decode.d.ts +31 -0
  51. package/dist/schema/decode.d.ts.map +1 -0
  52. package/dist/schema/decode.js +207 -0
  53. package/dist/schema/decode.js.map +1 -0
  54. package/dist/schema/descriptor.d.ts +300 -0
  55. package/dist/schema/descriptor.d.ts.map +1 -0
  56. package/dist/schema/descriptor.js +15 -0
  57. package/dist/schema/descriptor.js.map +1 -0
  58. package/dist/schema/dialects/anthropic.d.ts +34 -0
  59. package/dist/schema/dialects/anthropic.d.ts.map +1 -0
  60. package/dist/schema/dialects/anthropic.js +77 -0
  61. package/dist/schema/dialects/anthropic.js.map +1 -0
  62. package/dist/schema/dialects/google.d.ts +47 -0
  63. package/dist/schema/dialects/google.d.ts.map +1 -0
  64. package/dist/schema/dialects/google.js +91 -0
  65. package/dist/schema/dialects/google.js.map +1 -0
  66. package/dist/schema/dialects/lenient.d.ts +4 -0
  67. package/dist/schema/dialects/lenient.d.ts.map +1 -0
  68. package/dist/schema/dialects/lenient.js +26 -0
  69. package/dist/schema/dialects/lenient.js.map +1 -0
  70. package/dist/schema/dialects/openai.d.ts +40 -0
  71. package/dist/schema/dialects/openai.d.ts.map +1 -0
  72. package/dist/schema/dialects/openai.js +81 -0
  73. package/dist/schema/dialects/openai.js.map +1 -0
  74. package/dist/schema/dialects/xai.d.ts +23 -0
  75. package/dist/schema/dialects/xai.d.ts.map +1 -0
  76. package/dist/schema/dialects/xai.js +53 -0
  77. package/dist/schema/dialects/xai.js.map +1 -0
  78. package/dist/schema/enum-values.d.ts +44 -0
  79. package/dist/schema/enum-values.d.ts.map +1 -0
  80. package/dist/schema/enum-values.js +56 -0
  81. package/dist/schema/enum-values.js.map +1 -0
  82. package/dist/schema/expressible.d.ts +59 -0
  83. package/dist/schema/expressible.d.ts.map +1 -0
  84. package/dist/schema/expressible.js +161 -0
  85. package/dist/schema/expressible.js.map +1 -0
  86. package/dist/schema/index.d.ts +20 -0
  87. package/dist/schema/index.d.ts.map +1 -0
  88. package/dist/schema/index.js +20 -0
  89. package/dist/schema/index.js.map +1 -0
  90. package/dist/schema/json-schema.d.ts +64 -0
  91. package/dist/schema/json-schema.d.ts.map +1 -0
  92. package/dist/schema/json-schema.js +2 -0
  93. package/dist/schema/json-schema.js.map +1 -0
  94. package/dist/schema/registry.d.ts +73 -0
  95. package/dist/schema/registry.d.ts.map +1 -0
  96. package/dist/schema/registry.js +135 -0
  97. package/dist/schema/registry.js.map +1 -0
  98. package/dist/schema/strictify.d.ts +19 -0
  99. package/dist/schema/strictify.d.ts.map +1 -0
  100. package/dist/schema/strictify.js +237 -0
  101. package/dist/schema/strictify.js.map +1 -0
  102. package/dist/schema/to-json-schema.d.ts +29 -0
  103. package/dist/schema/to-json-schema.d.ts.map +1 -0
  104. package/dist/schema/to-json-schema.js +692 -0
  105. package/dist/schema/to-json-schema.js.map +1 -0
  106. package/dist/schema/walk-key.d.ts +24 -0
  107. package/dist/schema/walk-key.d.ts.map +1 -0
  108. package/dist/schema/walk-key.js +33 -0
  109. package/dist/schema/walk-key.js.map +1 -0
  110. package/dist/to.js +1 -1
  111. package/dist/to.js.map +1 -1
  112. package/dist/tool.d.ts +38 -4
  113. package/dist/tool.d.ts.map +1 -1
  114. package/dist/tool.js +52 -8
  115. package/dist/tool.js.map +1 -1
  116. package/dist/types.d.ts +265 -8
  117. package/dist/types.d.ts.map +1 -1
  118. package/dist/types.js +4 -1
  119. package/dist/types.js.map +1 -1
  120. package/package.json +2 -2
  121. package/dist/schema.d.ts +0 -840
  122. package/dist/schema.d.ts.map +0 -1
  123. package/dist/schema.js +0 -2478
  124. package/dist/schema.js.map +0 -1
@@ -0,0 +1,300 @@
1
+ /**
2
+ * Provider family for a `FormatDescriptor`. The three known wire dialects
3
+ * (`'openai'`, `'anthropic'`, `'google'`) are autocomplete hints; any string
4
+ * is accepted so users can register custom descriptors via
5
+ * `registerDescriptor` and reference them by family name in
6
+ * `ModelInfo.strictFormat`. `'lenient'` is the no-rewrite catch-all and is
7
+ * not registerable as a custom family.
8
+ *
9
+ * Use this type wherever you need to talk about a descriptor family —
10
+ * registry functions, model declarations, etc.
11
+ */
12
+ export type DescriptorFamily = 'openai' | 'anthropic' | 'google' | 'xai' | (string & {});
13
+ /**
14
+ * Documented ceilings on how BIG one strict schema may be, as opposed to which
15
+ * keywords it may use. Every limit here is a SUM taken over a single schema —
16
+ * one tool's `parameters`, or one structured-output schema — not a per-request
17
+ * allowance shared between them (that is `maxStrictTools` and friends, which
18
+ * the `SchemaBudget` spends across the whole request).
19
+ *
20
+ * A schema that exceeds one of these is a guaranteed provider rejection under
21
+ * strict mode, so `SchemaBudget.allocate` treats it like any other
22
+ * infeasibility and degrades that ONE item to the family's non-strict
23
+ * descriptor, where no size rule applies. The rest of the request is
24
+ * unaffected.
25
+ *
26
+ * Declared as one object rather than six optional fields on purpose: a
27
+ * provider documents these together, and the object being present is what says
28
+ * "this dialect publishes size limits". Adding a rule here is then a compile
29
+ * error at every descriptor that declares the group, which is the point
30
+ * (a missed limit is invisible until a 400).
31
+ */
32
+ export interface SchemaSizeLimits {
33
+ /** Maximum object properties in one schema, summed over every nesting level. */
34
+ readonly maxObjectProperties: number;
35
+ /** Maximum levels of nested containers below the schema root. */
36
+ readonly maxNestingDepth: number;
37
+ /**
38
+ * Maximum total characters over the schema's property names, `enum` values
39
+ * and `const` values together.
40
+ */
41
+ readonly maxTotalStringChars: number;
42
+ /** Maximum `enum` values summed across every enum property in one schema. */
43
+ readonly maxTotalEnumValues: number;
44
+ /**
45
+ * The single-enum value count above which `maxLargeEnumStringChars` starts
46
+ * to apply. A smaller enum is bounded only by the two totals above.
47
+ */
48
+ readonly largeEnumValueCount: number;
49
+ /**
50
+ * Maximum total characters of ONE enum's string values, applied only to an
51
+ * enum carrying more than `largeEnumValueCount` values.
52
+ */
53
+ readonly maxLargeEnumStringChars: number;
54
+ }
55
+ /**
56
+ * Format descriptor — describes the JSON Schema dialect of a target.
57
+ *
58
+ * Each provider/strict combination is represented by one descriptor. The
59
+ * descriptor controls both how `strictify` rewrites a Zod schema (preprocesses
60
+ * for record-as-array, tuple-as-object, etc.) and how `toJSONSchema` emits the
61
+ * matching JSON Schema. Every `if (strict)` decision in the conversion
62
+ * pipeline dispatches off a descriptor field, so adding a new dialect is a
63
+ * matter of declaring a new `FormatDescriptor` and registering it.
64
+ */
65
+ export interface FormatDescriptor {
66
+ /** Stable id used as the cache key inside `strictify`. */
67
+ readonly id: string;
68
+ /**
69
+ * Provider family for this descriptor. The three built-in wire dialects
70
+ * are `'openai'` / `'anthropic'` / `'google'`; `'lenient'` is the
71
+ * no-rewrite catch-all. Custom descriptors registered via
72
+ * `registerDescriptor` may use any string here — the family is the
73
+ * lookup key used by `getDescriptor(family, strict)`.
74
+ */
75
+ readonly family: DescriptorFamily | 'lenient';
76
+ /** True if this descriptor represents the strict variant for its family. */
77
+ readonly strict: boolean;
78
+ /** When true, every object field appears in `required[]` (OpenAI strict). */
79
+ readonly objectAllFieldsRequired: boolean;
80
+ /** When true, every object emits `additionalProperties: false`. */
81
+ readonly objectClosedByDefault: boolean;
82
+ /** How to encode `z.record(K, V)`. */
83
+ readonly recordEncoding: 'array-of-pairs' | 'open-record';
84
+ /**
85
+ * How to encode `z.tuple([...])`.
86
+ * - `object-numeric-keys`: OpenAI-strict workaround (`{ "0": A, "1": B, ... }`)
87
+ * - `prefix-items`: standard JSON Schema `prefixItems` (Anthropic / Google)
88
+ * - `items-union`: collapse to homogeneous `items: { anyOf: [...] }` (last-resort)
89
+ */
90
+ readonly tupleEncoding: 'object-numeric-keys' | 'prefix-items' | 'items-union';
91
+ readonly allowAllOf: boolean;
92
+ readonly allowAnyOf: boolean;
93
+ readonly allowOneOf: boolean;
94
+ /** Whether `{ $ref: '#' }` self-reference is permitted. */
95
+ readonly allowRootRef: boolean;
96
+ readonly allowDefsRef: boolean;
97
+ /** Reserved: emit Google-style `propertyOrdering` hints. */
98
+ readonly emitPropertyOrdering: boolean;
99
+ /** Whitelist of `format:` values to emit, or `'all'` for every format JSON Schema defines. */
100
+ readonly supportedStringFormats: ReadonlySet<string> | 'all';
101
+ readonly allowPattern: boolean;
102
+ readonly allowMultiplePatterns: boolean;
103
+ readonly allowMinMaxLength: boolean;
104
+ readonly allowMinMaxItems: boolean;
105
+ readonly allowMinimumMaximum: boolean;
106
+ /** When true, `optional` becomes `T|null` (because every prop must be required). */
107
+ readonly optionalAsNullable: boolean;
108
+ /**
109
+ * How `z.any()` / `z.unknown()` is encoded.
110
+ * - `recursive-strict`: self-referencing $defs/Any with array-of-pairs records
111
+ * (OpenAI strict has no open-object support). REQUIRES `allowAnyOf` and
112
+ * `allowDefsRef`.
113
+ * - `recursive-open`: $defs/Any with `additionalProperties: <self>` records.
114
+ * REQUIRES `allowAnyOf` and `allowDefsRef`.
115
+ * - `flat`: a non-recursive `anyOf` over the JSON value types
116
+ * (`string`/`number`/`boolean`/`null`/`array`/open-`object`). Used by
117
+ * descriptors that reject recursive `$defs/Any` definitions (xAI strict).
118
+ * Equivalent to TypeScript `any` — accepts every JSON value without
119
+ * imposing any structural constraints. REQUIRES `allowAnyOf` (no `$defs`
120
+ * needed).
121
+ * - `unconstrained`: the empty schema `{}` (plus any `description`). Per
122
+ * JSON Schema, a schema with no assertion keywords validates EVERY
123
+ * instance — which is exactly what "any JSON value" means — and it
124
+ * introduces no keyword a restrictive dialect could reject. REQUIRES
125
+ * NOTHING, so it's the only encoding available to a dialect that forbids
126
+ * both combinators and named `$defs`/`$ref` (Google — see `GOOGLE_STRICT`).
127
+ * - `none`: the dialect has no spelling for "any JSON value" (Anthropic
128
+ * strict rejects `{}`, a typeless schema, an open object and a recursive
129
+ * `$defs/Any`). A schema containing one — or a recursion cycle, whose
130
+ * placeholder bottoms out at "any" — is not sendable, so the budget
131
+ * degrades the tool and `canExpress` sends an output as prompt text.
132
+ *
133
+ * The `REQUIRES` notes above are enforced by `checkDescriptorConsistency`,
134
+ * which `registerDescriptor` runs so a self-contradictory descriptor is
135
+ * caught at declaration time rather than as a provider HTTP 400.
136
+ */
137
+ readonly anyEncoding: 'recursive-strict' | 'recursive-open' | 'flat' | 'unconstrained' | 'none';
138
+ /** Maximum number of tools that can carry `strict: true` in one request. */
139
+ readonly maxStrictTools?: number;
140
+ /** Maximum total optional parameters across all strict schemas in one request. */
141
+ readonly maxStrictOptionalParams?: number;
142
+ /** Maximum total union-type parameters across all strict schemas in one request. */
143
+ readonly maxStrictUnionTypes?: number;
144
+ /**
145
+ * Documented ceilings on the SIZE of one strict schema (properties, nesting,
146
+ * total string bytes, enum values), or `undefined` when the dialect
147
+ * publishes none. See {@link SchemaSizeLimits} for what each bound counts and
148
+ * why it is per-schema rather than per-request.
149
+ *
150
+ * Only a STRICT descriptor declares these: they are Structured-Outputs rules
151
+ * — the API compiles the schema into a decoder and rejects one it cannot —
152
+ * and a non-strict schema is a best-effort hint the API does not compile. So
153
+ * degrading the offending item to the family's non-strict descriptor is both
154
+ * the fix and the reason the limits stop applying to it
155
+ * (`SchemaBudget.allocate`, `checkSchemaSizeLimits`).
156
+ *
157
+ * The measurement is taken from the ZOD schema, not from the emitted JSON,
158
+ * so it is deliberately CONSERVATIVE where an encoding is descriptor-
159
+ * dependent (a record counts as its widest encoding, a tuple as its
160
+ * numeric-key one). Over-counting costs strictness on a schema that would
161
+ * have fit; under-counting costs an HTTP 400, so the round goes up.
162
+ */
163
+ readonly schemaSizeLimits?: SchemaSizeLimits;
164
+ /**
165
+ * Maximum number of values ONE emitted `enum` may carry, or `undefined`
166
+ * (the default) for no cap.
167
+ *
168
+ * This is deliberately NOT one of the per-request budget fields above. Those
169
+ * are strict-mode allowances the SchemaBudget spends across a whole request,
170
+ * degrading an item that no longer fits to the family's non-strict
171
+ * descriptor; this one is a property of the dialect itself — it fires whatever the strictness — so it is enforced
172
+ * structurally at the point an `enum` is emitted (`convertSchema`), where
173
+ * the cardinality is actually known.
174
+ *
175
+ * Over the cap the emitter **widens** rather than truncates: it drops the
176
+ * `enum` keyword entirely, emits the node's plain scalar `type`
177
+ * (`{type: 'string'}` for a string enum), and puts EVERY value into the
178
+ * node's `description`. Nothing becomes unreachable — the model still has
179
+ * the complete list and can name any member — and the cardinality the
180
+ * dialect could not compile is simply no longer on the wire.
181
+ *
182
+ * The trade this makes is enforcement: a widened node no longer rejects a
183
+ * value structurally, so whatever validates the model's output afterwards
184
+ * has to. `Tool.parse` does, against the ORIGINAL zod schema — the enum is
185
+ * still there, only the emitted JSON Schema widened — so a hallucinated
186
+ * member comes back as a normal, re-promptable validation error.
187
+ *
188
+ * **`GOOGLE_STRICT`/`GOOGLE_NON_STRICT` declare 40. Every other built-in
189
+ * declares no cap.** Two earlier rounds of live measurement against
190
+ * `google/gemini-3-flash-preview` through OpenRouter (2026-08-23) — single
191
+ * enums up to 2048 SYNTHETIC values, 20 tools each with a 96-value enum, and
192
+ * an eleven-tool roster modelled on a real kind-authoring agent — all
193
+ * returned HTTP 200 and concluded there was no reproducible limit. **That
194
+ * conclusion was wrong, because none of those enums used the CONTENT of a
195
+ * real session.** A third round replayed the exact wire bytes of a real
196
+ * product request — `fn_load`'s `names` array, enum-constrained to the
197
+ * session's actual 98 known component/fn names (`default_renderer`,
198
+ * `QueryWidget`, `ConfirmPrompt`, `list_widget_types`, …) — and it 400'd,
199
+ * reproducibly, twice, byte-for-byte identical to what the provider was
200
+ * actually sent. Bisecting that same real value list: 90 values passes, 93
201
+ * fails. Bisecting what changes between the passing synthetic probes and the
202
+ * failing real one: 98 SHORT synthetic values (`n0`..`n97`, 284 chars) pass;
203
+ * 206 short values matching the REAL list's total character count (714
204
+ * chars) also pass; only the REAL, longer, dictionary-like/identifier-shaped
205
+ * values fail, and only past ~92 of them. So the limit tracks neither raw
206
+ * member count nor total character/byte budget — most likely actual
207
+ * tokenized grammar-state count, which short repetitive synthetic strings
208
+ * compress far below what real identifier text does at the same count or
209
+ * character budget. This is why the first two rounds' synthetic and
210
+ * lightly-realistic probes never tripped it.
211
+ *
212
+ * **The widen-to-string fallback this field triggers was verified against
213
+ * the exact failing real schema**: dropping `enum` and putting the same 98
214
+ * values into the `description` of a plain string field returned HTTP 200
215
+ * with the expected tool call — confirming the fallback mechanism actually
216
+ * fixes the failure it exists for, not just a synthetic stand-in.
217
+ *
218
+ * **40 is not a measured edge — it is a conservative floor with roughly 2x
219
+ * margin under the real one (90 passes / 93 fails) measured on this one real
220
+ * value set.** Given the failure tracks content, not just count, a different
221
+ * session's actual name list could plausibly fail at a different count; 40
222
+ * was also the cap this exact product ran under in production for months
223
+ * before a since-reverted attempt to remove it, which is corroborating
224
+ * evidence it holds in practice, not just in this one measurement.
225
+ *
226
+ * The reliability comparison from the earlier rounds still stands and is
227
+ * why a cap is preferable to leaving every enum uncapped "to be safe" at a
228
+ * much lower number: `enum` vs plain-string-with-full-list, 10 trials each
229
+ * over confusable near-duplicate names at 96 and 512 values, scored 10/10
230
+ * on-target with zero off-list answers for BOTH encodings. So there is no
231
+ * reliability cost to raising this cap later if a higher safe value is
232
+ * measured — only downside risk to leaving it too high.
233
+ *
234
+ * One trap for whoever measures this next: with `max_tokens` at 64, a
235
+ * forced-tool probe can come back `finish_reason: 'length'` with no tool
236
+ * call and empty content, which reads exactly like a grammar that produced
237
+ * nothing. It usually is not — this model spends reasoning tokens first.
238
+ * Give a forced-tool probe room before calling an empty completion a
239
+ * failure.
240
+ *
241
+ * So: set this only where a provider is MEASURED to reject a large enum
242
+ * using the SESSION'S OWN real content, not synthetic stand-ins, and set it
243
+ * conservatively below the measured edge until more value sets are tested.
244
+ * An `enum` that fits is the more correct encoding, because it is the one
245
+ * the model cannot answer outside of.
246
+ */
247
+ readonly maxEnumValues?: number;
248
+ /**
249
+ * Whether the descriptor can express recursive `$ref` schemas (`$ref: '#'`
250
+ * to root, or any `$ref: '#/$defs/X'` whose target transitively references
251
+ * itself). OpenAI / Google strict / Lenient: true. Anthropic strict: false
252
+ * — Anthropic's tool `input_schema` validator explicitly rejects circular
253
+ * `$defs` graphs.
254
+ *
255
+ * When `false`, the JSON-Schema emitter detects cycles in the source
256
+ * schema and replaces the offending back-edge with the descriptor's flat
257
+ * "any" shape (see `anyEncoding`) carrying a description that names the
258
+ * `$defs` entry it would otherwise have referenced. Non-cyclic shared
259
+ * `$ref` reuse is unaffected — those still emit as a `$ref` to a `$defs`
260
+ * entry.
261
+ */
262
+ readonly supportsRecursion: boolean;
263
+ /**
264
+ * True when the family's structured output is always compiled to a grammar,
265
+ * so there is no non-strict `json_schema` to degrade an output to. Anthropic:
266
+ * `output_config.format` is strict by definition, and OpenRouter adds the
267
+ * structured-outputs flag to every `json_schema` bound for Claude — a
268
+ * "non-strict" output with 30 optional fields still earns "Schemas contains
269
+ * too many optional parameters (30) … (limit: 24)" (measured 2026-11-04).
270
+ *
271
+ * A schema over the strict limits then cannot go out as structured output at
272
+ * all: `canExpress` answers `false`, so it is delivered as prompt text, and
273
+ * `SchemaBudget` never degrades an output to the non-strict variant.
274
+ */
275
+ readonly structuredOutputAlwaysStrict?: boolean;
276
+ /**
277
+ * Instruction appended after the schema text when a Prompt's/Tool's schema
278
+ * can't be expressed as this descriptor's structured output and is instead
279
+ * delivered to the model as PROMPT TEXT (see `canExpress` and the ai-layer
280
+ * `applySchemaDeliveryFallback`). Steers the model to emit a single raw JSON
281
+ * object rather than echoing the schema or wrapping it in prose/fences.
282
+ *
283
+ * Optional — descriptors that omit it fall back to
284
+ * `DEFAULT_JSON_FALLBACK_INSTRUCTION` via `getJsonFallbackInstruction`.
285
+ */
286
+ readonly jsonFallbackInstruction?: string;
287
+ }
288
+ /**
289
+ * Default instruction used when a `FormatDescriptor` omits
290
+ * `jsonFallbackInstruction`. Appended after the schema text when a schema is
291
+ * delivered as prompt text instead of as structured output.
292
+ */
293
+ export declare const DEFAULT_JSON_FALLBACK_INSTRUCTION = "Return ONLY a single raw JSON object conforming to the schema above \u2014 no markdown code fences, no prose, and do NOT echo the schema itself.";
294
+ /**
295
+ * Resolve the prompt-text fallback instruction for a descriptor, falling back
296
+ * to `DEFAULT_JSON_FALLBACK_INSTRUCTION` when the descriptor doesn't declare
297
+ * one of its own.
298
+ */
299
+ export declare function getJsonFallbackInstruction(descriptor: FormatDescriptor): string;
300
+ //# sourceMappingURL=descriptor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"descriptor.d.ts","sourceRoot":"","sources":["../../src/schema/descriptor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Default instruction used when a `FormatDescriptor` omits
3
+ * `jsonFallbackInstruction`. Appended after the schema text when a schema is
4
+ * delivered as prompt text instead of as structured output.
5
+ */
6
+ export const DEFAULT_JSON_FALLBACK_INSTRUCTION = 'Return ONLY a single raw JSON object conforming to the schema above — no markdown code fences, no prose, and do NOT echo the schema itself.';
7
+ /**
8
+ * Resolve the prompt-text fallback instruction for a descriptor, falling back
9
+ * to `DEFAULT_JSON_FALLBACK_INSTRUCTION` when the descriptor doesn't declare
10
+ * one of its own.
11
+ */
12
+ export function getJsonFallbackInstruction(descriptor) {
13
+ return descriptor.jsonFallbackInstruction ?? DEFAULT_JSON_FALLBACK_INSTRUCTION;
14
+ }
15
+ //# sourceMappingURL=descriptor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"descriptor.js","sourceRoot":"","sources":["../../src/schema/descriptor.ts"],"names":[],"mappings":"AAmUA;;;;GAIG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAC5C,6IAA6I,CAAC;AAEhJ;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CAAC,UAA4B;IACrE,OAAO,UAAU,CAAC,uBAAuB,IAAI,iCAAiC,CAAC;AACjF,CAAC"}
@@ -0,0 +1,34 @@
1
+ import type { FormatDescriptor } from '../descriptor';
2
+ /**
3
+ * Anthropic strict — Claude 4.5 and later (Opus 4.5–4.8, Sonnet 4.5/4.6,
4
+ * Haiku 4.5, and the 5.x Opus, Sonnet, Haiku, Fable, and Mythos models). Strict
5
+ * tools and `output_config.format` are GA with no beta header (re-read
6
+ * 2026-10-30). Per Anthropic's structured-outputs docs:
7
+ *
8
+ * - `additionalProperties` may **only** be `false` (no schema-valued open
9
+ * records), so `z.record(...)` falls back to the OpenAI-style
10
+ * array-of-pairs workaround.
11
+ * - Non-cyclic `$ref` / `$defs` reuse is supported and used freely — only
12
+ * *circular* `$defs` graphs are rejected by the API
13
+ * (`Circular reference detected in schema definitions: …`). The emitter
14
+ * sets `supportsRecursion: false`; shared non-cyclic `$ref`s are emitted
15
+ * normally, and a cycle makes the schema unsendable (see `anyEncoding`).
16
+ * Root self-reference (`$ref: '#'`) is always cyclic by definition, so
17
+ * `allowRootRef` stays `false`.
18
+ * - Numerical (`minimum`/`maximum`/`multipleOf`) and string-length
19
+ * (`minLength`/`maxLength`) constraints are not supported and are dropped,
20
+ * as are array sizes (only `minItems` of 0 or 1 is accepted).
21
+ * - `allOf` is supported except around a `$ref`.
22
+ * - `pattern` may not use backreferences, lookaround, `\b` or large `{n,m}`
23
+ * ranges; a schema that compiles too big is rejected with "Schema is too
24
+ * complex for compilation".
25
+ * - `prefixItems` and other positional tuple keywords are not in the
26
+ * supported list, so tuples collapse to a homogeneous `items: anyOf`.
27
+ * - Formats are a closed list (re-read 2026-11-04): OpenAI strict's nine plus
28
+ * `uri`. Anything else is dropped rather than risk a 400.
29
+ *
30
+ * See docs/plans/schema-dialects-2026.md for sources.
31
+ */
32
+ export declare const ANTHROPIC_STRICT: FormatDescriptor;
33
+ export declare const ANTHROPIC_NON_STRICT: FormatDescriptor;
34
+ //# sourceMappingURL=anthropic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/schema/dialects/anthropic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAOtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,gBAAgB,EAAE,gBAoC7B,CAAC;AAEH,eAAO,MAAM,oBAAoB,EAAE,gBAIjC,CAAC"}
@@ -0,0 +1,77 @@
1
+ import { LENIENT } from './lenient';
2
+ const ANTHROPIC_STRICT_FORMATS = new Set([
3
+ 'date-time', 'time', 'date', 'duration', 'email', 'hostname', 'uri', 'ipv4', 'ipv6', 'uuid',
4
+ ]);
5
+ /**
6
+ * Anthropic strict — Claude 4.5 and later (Opus 4.5–4.8, Sonnet 4.5/4.6,
7
+ * Haiku 4.5, and the 5.x Opus, Sonnet, Haiku, Fable, and Mythos models). Strict
8
+ * tools and `output_config.format` are GA with no beta header (re-read
9
+ * 2026-10-30). Per Anthropic's structured-outputs docs:
10
+ *
11
+ * - `additionalProperties` may **only** be `false` (no schema-valued open
12
+ * records), so `z.record(...)` falls back to the OpenAI-style
13
+ * array-of-pairs workaround.
14
+ * - Non-cyclic `$ref` / `$defs` reuse is supported and used freely — only
15
+ * *circular* `$defs` graphs are rejected by the API
16
+ * (`Circular reference detected in schema definitions: …`). The emitter
17
+ * sets `supportsRecursion: false`; shared non-cyclic `$ref`s are emitted
18
+ * normally, and a cycle makes the schema unsendable (see `anyEncoding`).
19
+ * Root self-reference (`$ref: '#'`) is always cyclic by definition, so
20
+ * `allowRootRef` stays `false`.
21
+ * - Numerical (`minimum`/`maximum`/`multipleOf`) and string-length
22
+ * (`minLength`/`maxLength`) constraints are not supported and are dropped,
23
+ * as are array sizes (only `minItems` of 0 or 1 is accepted).
24
+ * - `allOf` is supported except around a `$ref`.
25
+ * - `pattern` may not use backreferences, lookaround, `\b` or large `{n,m}`
26
+ * ranges; a schema that compiles too big is rejected with "Schema is too
27
+ * complex for compilation".
28
+ * - `prefixItems` and other positional tuple keywords are not in the
29
+ * supported list, so tuples collapse to a homogeneous `items: anyOf`.
30
+ * - Formats are a closed list (re-read 2026-11-04): OpenAI strict's nine plus
31
+ * `uri`. Anything else is dropped rather than risk a 400.
32
+ *
33
+ * See docs/plans/schema-dialects-2026.md for sources.
34
+ */
35
+ export const ANTHROPIC_STRICT = Object.freeze({
36
+ id: 'anthropic-strict',
37
+ family: 'anthropic',
38
+ strict: true,
39
+ objectAllFieldsRequired: false,
40
+ objectClosedByDefault: true,
41
+ recordEncoding: 'array-of-pairs',
42
+ tupleEncoding: 'items-union',
43
+ allowAllOf: true,
44
+ allowAnyOf: true,
45
+ allowOneOf: false,
46
+ allowRootRef: false,
47
+ allowDefsRef: true,
48
+ emitPropertyOrdering: false,
49
+ supportedStringFormats: ANTHROPIC_STRICT_FORMATS,
50
+ allowPattern: true,
51
+ allowMultiplePatterns: false,
52
+ allowMinMaxLength: false,
53
+ allowMinMaxItems: false,
54
+ allowMinimumMaximum: false,
55
+ optionalAsNullable: false,
56
+ // No spelling for "any JSON value": `{}` ("Empty schema … is not
57
+ // supported"), a typeless schema, `additionalProperties: true` and a
58
+ // recursive `$defs/Any` are all rejected (measured 2026-11-04).
59
+ anyEncoding: 'none',
60
+ // Anthropic-documented per-request limits (apply across ALL strict tool
61
+ // schemas + JSON output schemas in one request).
62
+ // Source: https://platform.claude.com/docs/en/build-with-claude/structured-outputs
63
+ maxStrictTools: 20,
64
+ maxStrictOptionalParams: 24,
65
+ maxStrictUnionTypes: 16,
66
+ // Recursive `$ref` graphs are rejected by Anthropic's tool input_schema
67
+ // validator, and the cycle-breaker's placeholder needs "any", so a cyclic
68
+ // schema is not sent strict.
69
+ supportsRecursion: false,
70
+ structuredOutputAlwaysStrict: true,
71
+ });
72
+ export const ANTHROPIC_NON_STRICT = Object.freeze({
73
+ ...LENIENT,
74
+ id: 'anthropic-non-strict',
75
+ family: 'anthropic',
76
+ });
77
+ //# sourceMappingURL=anthropic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/schema/dialects/anthropic.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,wBAAwB,GAAG,IAAI,GAAG,CAAC;IACvC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAC5F,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAqB,MAAM,CAAC,MAAM,CAAC;IAC9D,EAAE,EAAE,kBAAkB;IACtB,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,IAAI;IACZ,uBAAuB,EAAE,KAAK;IAC9B,qBAAqB,EAAE,IAAI;IAC3B,cAAc,EAAE,gBAAgB;IAChC,aAAa,EAAE,aAAa;IAC5B,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,KAAK;IACjB,YAAY,EAAE,KAAK;IACnB,YAAY,EAAE,IAAI;IAClB,oBAAoB,EAAE,KAAK;IAC3B,sBAAsB,EAAE,wBAAwB;IAChD,YAAY,EAAE,IAAI;IAClB,qBAAqB,EAAE,KAAK;IAC5B,iBAAiB,EAAE,KAAK;IACxB,gBAAgB,EAAE,KAAK;IACvB,mBAAmB,EAAE,KAAK;IAC1B,kBAAkB,EAAE,KAAK;IACzB,iEAAiE;IACjE,qEAAqE;IACrE,gEAAgE;IAChE,WAAW,EAAE,MAAM;IACnB,wEAAwE;IACxE,iDAAiD;IACjD,mFAAmF;IACnF,cAAc,EAAE,EAAE;IAClB,uBAAuB,EAAE,EAAE;IAC3B,mBAAmB,EAAE,EAAE;IACvB,wEAAwE;IACxE,0EAA0E;IAC1E,6BAA6B;IAC7B,iBAAiB,EAAE,KAAK;IACxB,4BAA4B,EAAE,IAAI;CACnC,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,oBAAoB,GAAqB,MAAM,CAAC,MAAM,CAAC;IAClE,GAAG,OAAO;IACV,EAAE,EAAE,sBAAsB;IAC1B,MAAM,EAAE,WAAW;CACpB,CAAC,CAAC"}
@@ -0,0 +1,47 @@
1
+ import type { FormatDescriptor } from '../descriptor';
2
+ /**
3
+ * Google Gemini strict — per `ai.google.dev/gemini-api/docs/structured-output`
4
+ * (re-read 2026-10-30, after Google's November 2025 JSON Schema expansion):
5
+ *
6
+ * - Supported keywords: types (including `["T", "null"]` arrays),
7
+ * `properties`, `required`, `additionalProperties`, `enum`, `format`
8
+ * (date-time/date/time), `minimum`, `maximum`, `items`, `prefixItems`,
9
+ * `minItems`, `maxItems`, `anyOf` (`oneOf` is read as `anyOf`), `$defs`,
10
+ * `$ref`, `title`, `description`, `propertyOrdering`.
11
+ * - `allOf` is not supported and `pattern` is not listed; both stay off.
12
+ * Live on `google/gemini-3-flash-preview` via OpenRouter (2026-10-30) an
13
+ * `allOf` tool was accepted but not enforced and a `pattern` tool timed out,
14
+ * while `anyOf`, shared `$defs`, `prefixItems`, nullable type arrays, closed
15
+ * objects, and recursion through array items or optional properties all
16
+ * answered with valid tool calls.
17
+ * - `minLength`/`maxLength` are stripped by the API, so they are not emitted.
18
+ * - Key order is preserved from the schema on Gemini 2.5+, so
19
+ * `propertyOrdering` is only needed by older models; it is still emitted.
20
+ * - `z.any()` / `z.unknown()` uses the `unconstrained` encoding. Gemini
21
+ * rejects ref loops through REQUIRED values: a self-referencing `$defs/Any`
22
+ * that recurses through `additionalProperties` fails with "ref loops are
23
+ * only supported if they include optional or nullable property values, or
24
+ * a potentially-zero-length array items" (reproduced 2026-10-30 after an
25
+ * interval in August 2026 when it was accepted), so the empty schema stays.
26
+ * Ordinary recursive models recurse through optional fields or arrays,
27
+ * which Gemini accepts.
28
+ */
29
+ export declare const GOOGLE_STRICT: FormatDescriptor;
30
+ /**
31
+ * Google Gemini non-strict — LENIENT's permissive rules EXCEPT for the "any"
32
+ * encoding.
33
+ *
34
+ * Gemini rejects a self-referencing `$defs/Any` when it has to build a
35
+ * decoding grammar, and it builds one whenever a tool call is forced —
36
+ * independent of any per-tool `strict` flag, which Google's function-calling
37
+ * API doesn't even have. So the `unconstrained` encoding is a property of the
38
+ * DIALECT, not of strict mode, and belongs on both Google descriptors.
39
+ *
40
+ * Everything else stays LENIENT deliberately: the restrictions on
41
+ * `GOOGLE_STRICT` come from the documented structured-output keyword list,
42
+ * which is a grammar-mode concern, and tightening them here would push
43
+ * ordinary Gemini schemas onto the prompt-text delivery fallback for no
44
+ * measured reason.
45
+ */
46
+ export declare const GOOGLE_NON_STRICT: FormatDescriptor;
47
+ //# sourceMappingURL=google.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google.d.ts","sourceRoot":"","sources":["../../../src/schema/dialects/google.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGtD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,aAAa,EAAE,gBAmC1B,CAAC;AAEH;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,iBAAiB,EAAE,gBAW9B,CAAC"}
@@ -0,0 +1,91 @@
1
+ import { LENIENT } from './lenient';
2
+ /**
3
+ * Google Gemini strict — per `ai.google.dev/gemini-api/docs/structured-output`
4
+ * (re-read 2026-10-30, after Google's November 2025 JSON Schema expansion):
5
+ *
6
+ * - Supported keywords: types (including `["T", "null"]` arrays),
7
+ * `properties`, `required`, `additionalProperties`, `enum`, `format`
8
+ * (date-time/date/time), `minimum`, `maximum`, `items`, `prefixItems`,
9
+ * `minItems`, `maxItems`, `anyOf` (`oneOf` is read as `anyOf`), `$defs`,
10
+ * `$ref`, `title`, `description`, `propertyOrdering`.
11
+ * - `allOf` is not supported and `pattern` is not listed; both stay off.
12
+ * Live on `google/gemini-3-flash-preview` via OpenRouter (2026-10-30) an
13
+ * `allOf` tool was accepted but not enforced and a `pattern` tool timed out,
14
+ * while `anyOf`, shared `$defs`, `prefixItems`, nullable type arrays, closed
15
+ * objects, and recursion through array items or optional properties all
16
+ * answered with valid tool calls.
17
+ * - `minLength`/`maxLength` are stripped by the API, so they are not emitted.
18
+ * - Key order is preserved from the schema on Gemini 2.5+, so
19
+ * `propertyOrdering` is only needed by older models; it is still emitted.
20
+ * - `z.any()` / `z.unknown()` uses the `unconstrained` encoding. Gemini
21
+ * rejects ref loops through REQUIRED values: a self-referencing `$defs/Any`
22
+ * that recurses through `additionalProperties` fails with "ref loops are
23
+ * only supported if they include optional or nullable property values, or
24
+ * a potentially-zero-length array items" (reproduced 2026-10-30 after an
25
+ * interval in August 2026 when it was accepted), so the empty schema stays.
26
+ * Ordinary recursive models recurse through optional fields or arrays,
27
+ * which Gemini accepts.
28
+ */
29
+ export const GOOGLE_STRICT = Object.freeze({
30
+ id: 'google-strict',
31
+ family: 'google',
32
+ strict: true,
33
+ objectAllFieldsRequired: false,
34
+ objectClosedByDefault: false,
35
+ recordEncoding: 'open-record',
36
+ tupleEncoding: 'prefix-items',
37
+ allowAllOf: false,
38
+ allowAnyOf: true,
39
+ allowOneOf: false,
40
+ allowRootRef: true,
41
+ allowDefsRef: true,
42
+ emitPropertyOrdering: true,
43
+ supportedStringFormats: new Set(['date-time', 'date', 'time']),
44
+ allowPattern: false,
45
+ allowMultiplePatterns: false,
46
+ allowMinMaxLength: false,
47
+ allowMinMaxItems: true,
48
+ allowMinimumMaximum: true,
49
+ optionalAsNullable: false,
50
+ // Not a recursive $defs/Any: Gemini rejects ref loops through required
51
+ // values — see the descriptor doc above.
52
+ anyEncoding: 'unconstrained',
53
+ // No documented per-request slot limits. `maxEnumValues: 40` IS a measured
54
+ // response to a real `400 INVALID_ARGUMENT` on this exact product's live
55
+ // fn-catalog enum — see `FormatDescriptor.maxEnumValues` for the numbers,
56
+ // the bisection, and why 40 is conservative rather than the measured edge.
57
+ maxEnumValues: 40,
58
+ supportsRecursion: true,
59
+ // When a schema can't be expressed here (e.g. it needs `allOf`) it's
60
+ // delivered as prompt text instead; this hint keeps the reply a single raw
61
+ // JSON object.
62
+ jsonFallbackInstruction: 'Return ONLY a single raw JSON object that conforms to the schema above. Do NOT wrap it in markdown code fences, do NOT add any prose before or after it, and do NOT echo the schema itself — emit only the JSON instance.',
63
+ });
64
+ /**
65
+ * Google Gemini non-strict — LENIENT's permissive rules EXCEPT for the "any"
66
+ * encoding.
67
+ *
68
+ * Gemini rejects a self-referencing `$defs/Any` when it has to build a
69
+ * decoding grammar, and it builds one whenever a tool call is forced —
70
+ * independent of any per-tool `strict` flag, which Google's function-calling
71
+ * API doesn't even have. So the `unconstrained` encoding is a property of the
72
+ * DIALECT, not of strict mode, and belongs on both Google descriptors.
73
+ *
74
+ * Everything else stays LENIENT deliberately: the restrictions on
75
+ * `GOOGLE_STRICT` come from the documented structured-output keyword list,
76
+ * which is a grammar-mode concern, and tightening them here would push
77
+ * ordinary Gemini schemas onto the prompt-text delivery fallback for no
78
+ * measured reason.
79
+ */
80
+ export const GOOGLE_NON_STRICT = Object.freeze({
81
+ ...LENIENT,
82
+ id: 'google-non-strict',
83
+ family: 'google',
84
+ anyEncoding: 'unconstrained',
85
+ // Same measured enum-cardinality limit as GOOGLE_STRICT — it fires whatever
86
+ // the strictness (see FormatDescriptor.maxEnumValues), so a tool degraded
87
+ // to this descriptor still needs it.
88
+ maxEnumValues: 40,
89
+ jsonFallbackInstruction: 'Return ONLY a single raw JSON object that conforms to the schema above. Do NOT wrap it in markdown code fences, do NOT add any prose before or after it, and do NOT echo the schema itself — emit only the JSON instance.',
90
+ });
91
+ //# sourceMappingURL=google.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"google.js","sourceRoot":"","sources":["../../../src/schema/dialects/google.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,MAAM,aAAa,GAAqB,MAAM,CAAC,MAAM,CAAC;IAC3D,EAAE,EAAE,eAAe;IACnB,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,IAAI;IACZ,uBAAuB,EAAE,KAAK;IAC9B,qBAAqB,EAAE,KAAK;IAC5B,cAAc,EAAE,aAAa;IAC7B,aAAa,EAAE,cAAc;IAC7B,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,KAAK;IACjB,YAAY,EAAE,IAAI;IAClB,YAAY,EAAE,IAAI;IAClB,oBAAoB,EAAE,IAAI;IAC1B,sBAAsB,EAAE,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9D,YAAY,EAAE,KAAK;IACnB,qBAAqB,EAAE,KAAK;IAC5B,iBAAiB,EAAE,KAAK;IACxB,gBAAgB,EAAE,IAAI;IACtB,mBAAmB,EAAE,IAAI;IACzB,kBAAkB,EAAE,KAAK;IACzB,uEAAuE;IACvE,yCAAyC;IACzC,WAAW,EAAE,eAAe;IAC5B,2EAA2E;IAC3E,yEAAyE;IACzE,0EAA0E;IAC1E,2EAA2E;IAC3E,aAAa,EAAE,EAAE;IACjB,iBAAiB,EAAE,IAAI;IACvB,qEAAqE;IACrE,2EAA2E;IAC3E,eAAe;IACf,uBAAuB,EACrB,2NAA2N;CAC9N,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAqB,MAAM,CAAC,MAAM,CAAC;IAC/D,GAAG,OAAO;IACV,EAAE,EAAE,mBAAmB;IACvB,MAAM,EAAE,QAAQ;IAChB,WAAW,EAAE,eAAe;IAC5B,4EAA4E;IAC5E,0EAA0E;IAC1E,qCAAqC;IACrC,aAAa,EAAE,EAAE;IACjB,uBAAuB,EACrB,2NAA2N;CAC9N,CAAC,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { FormatDescriptor } from '../descriptor';
2
+ /** Lenient descriptor — no rewrites, no closure, formats pass through. Default for unsupported models. */
3
+ export declare const LENIENT: FormatDescriptor;
4
+ //# sourceMappingURL=lenient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lenient.d.ts","sourceRoot":"","sources":["../../../src/schema/dialects/lenient.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD,0GAA0G;AAC1G,eAAO,MAAM,OAAO,EAAE,gBAuBpB,CAAC"}
@@ -0,0 +1,26 @@
1
+ /** Lenient descriptor — no rewrites, no closure, formats pass through. Default for unsupported models. */
2
+ export const LENIENT = Object.freeze({
3
+ id: 'lenient',
4
+ family: 'lenient',
5
+ strict: false,
6
+ objectAllFieldsRequired: false,
7
+ objectClosedByDefault: false,
8
+ recordEncoding: 'open-record',
9
+ tupleEncoding: 'prefix-items',
10
+ allowAllOf: true,
11
+ allowAnyOf: true,
12
+ allowOneOf: true,
13
+ allowRootRef: true,
14
+ allowDefsRef: true,
15
+ emitPropertyOrdering: false,
16
+ supportedStringFormats: 'all',
17
+ allowPattern: true,
18
+ allowMultiplePatterns: true,
19
+ allowMinMaxLength: true,
20
+ allowMinMaxItems: true,
21
+ allowMinimumMaximum: true,
22
+ optionalAsNullable: false,
23
+ anyEncoding: 'recursive-open',
24
+ supportsRecursion: true,
25
+ });
26
+ //# sourceMappingURL=lenient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lenient.js","sourceRoot":"","sources":["../../../src/schema/dialects/lenient.ts"],"names":[],"mappings":"AAEA,0GAA0G;AAC1G,MAAM,CAAC,MAAM,OAAO,GAAqB,MAAM,CAAC,MAAM,CAAC;IACrD,EAAE,EAAE,SAAS;IACb,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,KAAK;IACb,uBAAuB,EAAE,KAAK;IAC9B,qBAAqB,EAAE,KAAK;IAC5B,cAAc,EAAE,aAAa;IAC7B,aAAa,EAAE,cAAc;IAC7B,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,IAAI;IAChB,YAAY,EAAE,IAAI;IAClB,YAAY,EAAE,IAAI;IAClB,oBAAoB,EAAE,KAAK;IAC3B,sBAAsB,EAAE,KAAK;IAC7B,YAAY,EAAE,IAAI;IAClB,qBAAqB,EAAE,IAAI;IAC3B,iBAAiB,EAAE,IAAI;IACvB,gBAAgB,EAAE,IAAI;IACtB,mBAAmB,EAAE,IAAI;IACzB,kBAAkB,EAAE,KAAK;IACzB,WAAW,EAAE,gBAAgB;IAC7B,iBAAiB,EAAE,IAAI;CACxB,CAAC,CAAC"}