@aeye/core 0.5.3 → 0.6.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.
- package/README.md +51 -4
- package/aeye-core-schema.md +11 -7
- package/dist/common.d.ts +30 -5
- package/dist/common.d.ts.map +1 -1
- package/dist/common.js +134 -129
- package/dist/common.js.map +1 -1
- package/dist/delivery.d.ts +39 -0
- package/dist/delivery.d.ts.map +1 -0
- package/dist/delivery.js +127 -0
- package/dist/delivery.js.map +1 -0
- package/dist/errors.d.ts +60 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +84 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/prompt.d.ts +101 -9
- package/dist/prompt.d.ts.map +1 -1
- package/dist/prompt.js +163 -141
- package/dist/prompt.js.map +1 -1
- package/dist/schema/analyze.d.ts +94 -0
- package/dist/schema/analyze.d.ts.map +1 -0
- package/dist/schema/analyze.js +221 -0
- package/dist/schema/analyze.js.map +1 -0
- package/dist/schema/any-value.d.ts +32 -0
- package/dist/schema/any-value.d.ts.map +1 -0
- package/dist/schema/any-value.js +77 -0
- package/dist/schema/any-value.js.map +1 -0
- package/dist/schema/budget.d.ts +114 -0
- package/dist/schema/budget.d.ts.map +1 -0
- package/dist/schema/budget.js +223 -0
- package/dist/schema/budget.js.map +1 -0
- package/dist/schema/consistency.d.ts +27 -0
- package/dist/schema/consistency.d.ts.map +1 -0
- package/dist/schema/consistency.js +110 -0
- package/dist/schema/consistency.js.map +1 -0
- package/dist/schema/cycle-breaker.d.ts +14 -0
- package/dist/schema/cycle-breaker.d.ts.map +1 -0
- package/dist/schema/cycle-breaker.js +157 -0
- package/dist/schema/cycle-breaker.js.map +1 -0
- package/dist/schema/decode.d.ts +31 -0
- package/dist/schema/decode.d.ts.map +1 -0
- package/dist/schema/decode.js +207 -0
- package/dist/schema/decode.js.map +1 -0
- package/dist/schema/descriptor.d.ts +300 -0
- package/dist/schema/descriptor.d.ts.map +1 -0
- package/dist/schema/descriptor.js +15 -0
- package/dist/schema/descriptor.js.map +1 -0
- package/dist/schema/dialects/anthropic.d.ts +34 -0
- package/dist/schema/dialects/anthropic.d.ts.map +1 -0
- package/dist/schema/dialects/anthropic.js +77 -0
- package/dist/schema/dialects/anthropic.js.map +1 -0
- package/dist/schema/dialects/google.d.ts +47 -0
- package/dist/schema/dialects/google.d.ts.map +1 -0
- package/dist/schema/dialects/google.js +91 -0
- package/dist/schema/dialects/google.js.map +1 -0
- package/dist/schema/dialects/lenient.d.ts +4 -0
- package/dist/schema/dialects/lenient.d.ts.map +1 -0
- package/dist/schema/dialects/lenient.js +26 -0
- package/dist/schema/dialects/lenient.js.map +1 -0
- package/dist/schema/dialects/openai.d.ts +40 -0
- package/dist/schema/dialects/openai.d.ts.map +1 -0
- package/dist/schema/dialects/openai.js +81 -0
- package/dist/schema/dialects/openai.js.map +1 -0
- package/dist/schema/dialects/xai.d.ts +23 -0
- package/dist/schema/dialects/xai.d.ts.map +1 -0
- package/dist/schema/dialects/xai.js +53 -0
- package/dist/schema/dialects/xai.js.map +1 -0
- package/dist/schema/enum-values.d.ts +44 -0
- package/dist/schema/enum-values.d.ts.map +1 -0
- package/dist/schema/enum-values.js +56 -0
- package/dist/schema/enum-values.js.map +1 -0
- package/dist/schema/expressible.d.ts +59 -0
- package/dist/schema/expressible.d.ts.map +1 -0
- package/dist/schema/expressible.js +161 -0
- package/dist/schema/expressible.js.map +1 -0
- package/dist/schema/index.d.ts +20 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +20 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/json-schema.d.ts +64 -0
- package/dist/schema/json-schema.d.ts.map +1 -0
- package/dist/schema/json-schema.js +2 -0
- package/dist/schema/json-schema.js.map +1 -0
- package/dist/schema/registry.d.ts +73 -0
- package/dist/schema/registry.d.ts.map +1 -0
- package/dist/schema/registry.js +135 -0
- package/dist/schema/registry.js.map +1 -0
- package/dist/schema/strictify.d.ts +19 -0
- package/dist/schema/strictify.d.ts.map +1 -0
- package/dist/schema/strictify.js +237 -0
- package/dist/schema/strictify.js.map +1 -0
- package/dist/schema/to-json-schema.d.ts +29 -0
- package/dist/schema/to-json-schema.d.ts.map +1 -0
- package/dist/schema/to-json-schema.js +691 -0
- package/dist/schema/to-json-schema.js.map +1 -0
- package/dist/schema/walk-key.d.ts +24 -0
- package/dist/schema/walk-key.d.ts.map +1 -0
- package/dist/schema/walk-key.js +33 -0
- package/dist/schema/walk-key.js.map +1 -0
- package/dist/to.js +1 -1
- package/dist/to.js.map +1 -1
- package/dist/tool.d.ts +32 -3
- package/dist/tool.d.ts.map +1 -1
- package/dist/tool.js +41 -0
- package/dist/tool.js.map +1 -1
- package/dist/types.d.ts +265 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -1
- package/dist/types.js.map +1 -1
- package/package.json +72 -72
- package/dist/schema.d.ts +0 -837
- package/dist/schema.d.ts.map +0 -1
- package/dist/schema.js +0 -2472
- package/dist/schema.js.map +0 -1
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { FormatDescriptor } from '../descriptor';
|
|
2
|
+
/**
|
|
3
|
+
* OpenAI strict. Records→pairs, tuples→numeric-keys, optional→nullable.
|
|
4
|
+
*
|
|
5
|
+
* Numeric bounds (`minimum`/`maximum`/`exclusive*`/`multipleOf`) and array
|
|
6
|
+
* sizes (`minItems`/`maxItems`) are in the documented supported list
|
|
7
|
+
* (developers.openai.com/api/docs/guides/structured-outputs, "Supported
|
|
8
|
+
* properties", read 2026-10-30). `minLength`/`maxLength` are listed as
|
|
9
|
+
* unsupported only for fine-tuned models; a strict `json_schema` carrying them
|
|
10
|
+
* was accepted and honored by gpt-5.4-mini on 2026-10-30, as were the
|
|
11
|
+
* numeric and array bounds, so all three are emitted.
|
|
12
|
+
*
|
|
13
|
+
* No documented per-request slot limit (max strict tools / optional params /
|
|
14
|
+
* union types) — the SchemaBudget treats those caps as `undefined` for OpenAI.
|
|
15
|
+
*
|
|
16
|
+
* OpenAI DOES document per-SCHEMA size limits for Structured Outputs, and they
|
|
17
|
+
* are declared below (`schemaSizeLimits`). Verified against
|
|
18
|
+
* developers.openai.com/api/docs/guides/structured-outputs on 2026-08-23,
|
|
19
|
+
* section "Supported schemas": *"A schema may have up to 5000 object
|
|
20
|
+
* properties total, with up to 10 levels of nesting"*, *"total string length of
|
|
21
|
+
* all property names, definition names, enum values, and const values cannot
|
|
22
|
+
* exceed 120,000 characters"*, *"A schema may have up to 1000 enum values
|
|
23
|
+
* across all enum properties"*, and *"For a single enum property with string
|
|
24
|
+
* values, the total string length of all enum values cannot exceed 15,000
|
|
25
|
+
* characters when there are more than 250 enum values"*. Every one of those
|
|
26
|
+
* numbers was raised in July 2025 (100→5000 properties, 15,000→120,000
|
|
27
|
+
* characters, 500→1000 enum values, 7,500→15,000 for the >250-value enum) —
|
|
28
|
+
* the pre-raise figures are still widely quoted secondhand, so they are named
|
|
29
|
+
* here to keep a future reader from "correcting" these downward.
|
|
30
|
+
*
|
|
31
|
+
* Scope is Structured Outputs, i.e. a tool carrying `strict: true` or a
|
|
32
|
+
* `json_schema` response format — the function-calling guide defines strict
|
|
33
|
+
* mode as "leveraging our structured outputs feature", and non-strict function
|
|
34
|
+
* calling is best-effort with no compiled decoder. That is exactly why
|
|
35
|
+
* degrading the over-size item to `OPENAI_NON_STRICT` is a complete answer.
|
|
36
|
+
*/
|
|
37
|
+
export declare const OPENAI_STRICT: FormatDescriptor;
|
|
38
|
+
/** OpenAI non-strict — alias of LENIENT but tagged with the openai family. */
|
|
39
|
+
export declare const OPENAI_NON_STRICT: FormatDescriptor;
|
|
40
|
+
//# sourceMappingURL=openai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../src/schema/dialects/openai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAOtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,aAAa,EAAE,gBAkC1B,CAAC;AAEH,8EAA8E;AAC9E,eAAO,MAAM,iBAAiB,EAAE,gBAI9B,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { LENIENT } from './lenient';
|
|
2
|
+
const OPENAI_STRICT_FORMATS = new Set([
|
|
3
|
+
'date-time', 'time', 'date', 'duration', 'email', 'hostname', 'ipv4', 'ipv6', 'uuid',
|
|
4
|
+
]);
|
|
5
|
+
/**
|
|
6
|
+
* OpenAI strict. Records→pairs, tuples→numeric-keys, optional→nullable.
|
|
7
|
+
*
|
|
8
|
+
* Numeric bounds (`minimum`/`maximum`/`exclusive*`/`multipleOf`) and array
|
|
9
|
+
* sizes (`minItems`/`maxItems`) are in the documented supported list
|
|
10
|
+
* (developers.openai.com/api/docs/guides/structured-outputs, "Supported
|
|
11
|
+
* properties", read 2026-10-30). `minLength`/`maxLength` are listed as
|
|
12
|
+
* unsupported only for fine-tuned models; a strict `json_schema` carrying them
|
|
13
|
+
* was accepted and honored by gpt-5.4-mini on 2026-10-30, as were the
|
|
14
|
+
* numeric and array bounds, so all three are emitted.
|
|
15
|
+
*
|
|
16
|
+
* No documented per-request slot limit (max strict tools / optional params /
|
|
17
|
+
* union types) — the SchemaBudget treats those caps as `undefined` for OpenAI.
|
|
18
|
+
*
|
|
19
|
+
* OpenAI DOES document per-SCHEMA size limits for Structured Outputs, and they
|
|
20
|
+
* are declared below (`schemaSizeLimits`). Verified against
|
|
21
|
+
* developers.openai.com/api/docs/guides/structured-outputs on 2026-08-23,
|
|
22
|
+
* section "Supported schemas": *"A schema may have up to 5000 object
|
|
23
|
+
* properties total, with up to 10 levels of nesting"*, *"total string length of
|
|
24
|
+
* all property names, definition names, enum values, and const values cannot
|
|
25
|
+
* exceed 120,000 characters"*, *"A schema may have up to 1000 enum values
|
|
26
|
+
* across all enum properties"*, and *"For a single enum property with string
|
|
27
|
+
* values, the total string length of all enum values cannot exceed 15,000
|
|
28
|
+
* characters when there are more than 250 enum values"*. Every one of those
|
|
29
|
+
* numbers was raised in July 2025 (100→5000 properties, 15,000→120,000
|
|
30
|
+
* characters, 500→1000 enum values, 7,500→15,000 for the >250-value enum) —
|
|
31
|
+
* the pre-raise figures are still widely quoted secondhand, so they are named
|
|
32
|
+
* here to keep a future reader from "correcting" these downward.
|
|
33
|
+
*
|
|
34
|
+
* Scope is Structured Outputs, i.e. a tool carrying `strict: true` or a
|
|
35
|
+
* `json_schema` response format — the function-calling guide defines strict
|
|
36
|
+
* mode as "leveraging our structured outputs feature", and non-strict function
|
|
37
|
+
* calling is best-effort with no compiled decoder. That is exactly why
|
|
38
|
+
* degrading the over-size item to `OPENAI_NON_STRICT` is a complete answer.
|
|
39
|
+
*/
|
|
40
|
+
export const OPENAI_STRICT = Object.freeze({
|
|
41
|
+
id: 'openai-strict',
|
|
42
|
+
family: 'openai',
|
|
43
|
+
strict: true,
|
|
44
|
+
objectAllFieldsRequired: true,
|
|
45
|
+
objectClosedByDefault: true,
|
|
46
|
+
recordEncoding: 'array-of-pairs',
|
|
47
|
+
tupleEncoding: 'object-numeric-keys',
|
|
48
|
+
allowAllOf: false,
|
|
49
|
+
allowAnyOf: true,
|
|
50
|
+
allowOneOf: false,
|
|
51
|
+
allowRootRef: true,
|
|
52
|
+
allowDefsRef: true,
|
|
53
|
+
emitPropertyOrdering: false,
|
|
54
|
+
supportedStringFormats: OPENAI_STRICT_FORMATS,
|
|
55
|
+
allowPattern: true,
|
|
56
|
+
allowMultiplePatterns: false,
|
|
57
|
+
allowMinMaxLength: true,
|
|
58
|
+
allowMinMaxItems: true,
|
|
59
|
+
allowMinimumMaximum: true,
|
|
60
|
+
optionalAsNullable: true,
|
|
61
|
+
anyEncoding: 'recursive-strict',
|
|
62
|
+
supportsRecursion: true,
|
|
63
|
+
// Every number is quoted from OpenAI's own "Supported schemas" section — see
|
|
64
|
+
// the descriptor doc above for the exact sentences and the date they were
|
|
65
|
+
// read. Frozen because `Object.freeze` on the descriptor is shallow.
|
|
66
|
+
schemaSizeLimits: Object.freeze({
|
|
67
|
+
maxObjectProperties: 5000,
|
|
68
|
+
maxNestingDepth: 10,
|
|
69
|
+
maxTotalStringChars: 120_000,
|
|
70
|
+
maxTotalEnumValues: 1000,
|
|
71
|
+
largeEnumValueCount: 250,
|
|
72
|
+
maxLargeEnumStringChars: 15_000,
|
|
73
|
+
}),
|
|
74
|
+
});
|
|
75
|
+
/** OpenAI non-strict — alias of LENIENT but tagged with the openai family. */
|
|
76
|
+
export const OPENAI_NON_STRICT = Object.freeze({
|
|
77
|
+
...LENIENT,
|
|
78
|
+
id: 'openai-non-strict',
|
|
79
|
+
family: 'openai',
|
|
80
|
+
});
|
|
81
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/schema/dialects/openai.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC;IACpC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CACrF,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;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,IAAI;IAC7B,qBAAqB,EAAE,IAAI;IAC3B,cAAc,EAAE,gBAAgB;IAChC,aAAa,EAAE,qBAAqB;IACpC,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,KAAK;IACjB,YAAY,EAAE,IAAI;IAClB,YAAY,EAAE,IAAI;IAClB,oBAAoB,EAAE,KAAK;IAC3B,sBAAsB,EAAE,qBAAqB;IAC7C,YAAY,EAAE,IAAI;IAClB,qBAAqB,EAAE,KAAK;IAC5B,iBAAiB,EAAE,IAAI;IACvB,gBAAgB,EAAE,IAAI;IACtB,mBAAmB,EAAE,IAAI;IACzB,kBAAkB,EAAE,IAAI;IACxB,WAAW,EAAE,kBAAkB;IAC/B,iBAAiB,EAAE,IAAI;IACvB,6EAA6E;IAC7E,0EAA0E;IAC1E,qEAAqE;IACrE,gBAAgB,EAAE,MAAM,CAAC,MAAM,CAAC;QAC9B,mBAAmB,EAAE,IAAI;QACzB,eAAe,EAAE,EAAE;QACnB,mBAAmB,EAAE,OAAO;QAC5B,kBAAkB,EAAE,IAAI;QACxB,mBAAmB,EAAE,GAAG;QACxB,uBAAuB,EAAE,MAAM;KAChC,CAAC;CACH,CAAC,CAAC;AAEH,8EAA8E;AAC9E,MAAM,CAAC,MAAM,iBAAiB,GAAqB,MAAM,CAAC,MAAM,CAAC;IAC/D,GAAG,OAAO;IACV,EAAE,EAAE,mBAAmB;IACvB,MAAM,EAAE,QAAQ;CACjB,CAAC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { FormatDescriptor } from '../descriptor';
|
|
2
|
+
/**
|
|
3
|
+
* xAI (Grok) strict — per `docs.x.ai/docs/guides/structured-outputs`
|
|
4
|
+
* (read 2026-10-30). Tool calls are always strict on Grok 4 models.
|
|
5
|
+
*
|
|
6
|
+
* - Supported (re-read 2026-11-04): `anyOf`, `oneOf`, non-circular `$ref` /
|
|
7
|
+
* `$defs`, `prefixItems` for tuples (array-form `items` is rejected),
|
|
8
|
+
* `enum`, `const`, string formats (below), `pattern` without
|
|
9
|
+
* backreferences or lookaround, and length / item / numeric bounds.
|
|
10
|
+
* - `allOf` is enforced only with a single subschema (more are best-effort),
|
|
11
|
+
* so it stays off.
|
|
12
|
+
* - Array-form `items`, boolean property schemas, empty `enum`/`anyOf` and
|
|
13
|
+
* `minContains`/`maxContains` are rejected; the emitter produces none.
|
|
14
|
+
* - Optional properties stay optional; `additionalProperties` defaults to
|
|
15
|
+
* `false`, and schema-valued records were accepted live.
|
|
16
|
+
* - Circular references are documented as unsupported, so recursion goes
|
|
17
|
+
* through the cycle breaker. Every other keyword above was accepted live
|
|
18
|
+
* on `x-ai/grok-4.3` via OpenRouter on 2026-10-30.
|
|
19
|
+
*/
|
|
20
|
+
export declare const XAI_STRICT: FormatDescriptor;
|
|
21
|
+
/** xAI non-strict — alias of LENIENT but tagged with the xai family. */
|
|
22
|
+
export declare const XAI_NON_STRICT: FormatDescriptor;
|
|
23
|
+
//# sourceMappingURL=xai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xai.d.ts","sourceRoot":"","sources":["../../../src/schema/dialects/xai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAOtD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,EAAE,gBAuBvB,CAAC;AAEH,wEAAwE;AACxE,eAAO,MAAM,cAAc,EAAE,gBAI3B,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { LENIENT } from './lenient';
|
|
2
|
+
const XAI_STRICT_FORMATS = new Set([
|
|
3
|
+
'date', 'time', 'date-time', 'email', 'uuid', 'ipv4', 'ipv6', 'uri',
|
|
4
|
+
]);
|
|
5
|
+
/**
|
|
6
|
+
* xAI (Grok) strict — per `docs.x.ai/docs/guides/structured-outputs`
|
|
7
|
+
* (read 2026-10-30). Tool calls are always strict on Grok 4 models.
|
|
8
|
+
*
|
|
9
|
+
* - Supported (re-read 2026-11-04): `anyOf`, `oneOf`, non-circular `$ref` /
|
|
10
|
+
* `$defs`, `prefixItems` for tuples (array-form `items` is rejected),
|
|
11
|
+
* `enum`, `const`, string formats (below), `pattern` without
|
|
12
|
+
* backreferences or lookaround, and length / item / numeric bounds.
|
|
13
|
+
* - `allOf` is enforced only with a single subschema (more are best-effort),
|
|
14
|
+
* so it stays off.
|
|
15
|
+
* - Array-form `items`, boolean property schemas, empty `enum`/`anyOf` and
|
|
16
|
+
* `minContains`/`maxContains` are rejected; the emitter produces none.
|
|
17
|
+
* - Optional properties stay optional; `additionalProperties` defaults to
|
|
18
|
+
* `false`, and schema-valued records were accepted live.
|
|
19
|
+
* - Circular references are documented as unsupported, so recursion goes
|
|
20
|
+
* through the cycle breaker. Every other keyword above was accepted live
|
|
21
|
+
* on `x-ai/grok-4.3` via OpenRouter on 2026-10-30.
|
|
22
|
+
*/
|
|
23
|
+
export const XAI_STRICT = Object.freeze({
|
|
24
|
+
id: 'xai-strict',
|
|
25
|
+
family: 'xai',
|
|
26
|
+
strict: true,
|
|
27
|
+
objectAllFieldsRequired: false,
|
|
28
|
+
objectClosedByDefault: true,
|
|
29
|
+
recordEncoding: 'open-record',
|
|
30
|
+
tupleEncoding: 'prefix-items',
|
|
31
|
+
allowAllOf: false,
|
|
32
|
+
allowAnyOf: true,
|
|
33
|
+
allowOneOf: true,
|
|
34
|
+
allowRootRef: false,
|
|
35
|
+
allowDefsRef: true,
|
|
36
|
+
emitPropertyOrdering: false,
|
|
37
|
+
supportedStringFormats: XAI_STRICT_FORMATS,
|
|
38
|
+
allowPattern: true,
|
|
39
|
+
allowMultiplePatterns: false,
|
|
40
|
+
allowMinMaxLength: true,
|
|
41
|
+
allowMinMaxItems: true,
|
|
42
|
+
allowMinimumMaximum: true,
|
|
43
|
+
optionalAsNullable: false,
|
|
44
|
+
anyEncoding: 'flat',
|
|
45
|
+
supportsRecursion: false,
|
|
46
|
+
});
|
|
47
|
+
/** xAI non-strict — alias of LENIENT but tagged with the xai family. */
|
|
48
|
+
export const XAI_NON_STRICT = Object.freeze({
|
|
49
|
+
...LENIENT,
|
|
50
|
+
id: 'xai-non-strict',
|
|
51
|
+
family: 'xai',
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=xai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xai.js","sourceRoot":"","sources":["../../../src/schema/dialects/xai.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACjC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK;CACpE,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,UAAU,GAAqB,MAAM,CAAC,MAAM,CAAC;IACxD,EAAE,EAAE,YAAY;IAChB,MAAM,EAAE,KAAK;IACb,MAAM,EAAE,IAAI;IACZ,uBAAuB,EAAE,KAAK;IAC9B,qBAAqB,EAAE,IAAI;IAC3B,cAAc,EAAE,aAAa;IAC7B,aAAa,EAAE,cAAc;IAC7B,UAAU,EAAE,KAAK;IACjB,UAAU,EAAE,IAAI;IAChB,UAAU,EAAE,IAAI;IAChB,YAAY,EAAE,KAAK;IACnB,YAAY,EAAE,IAAI;IAClB,oBAAoB,EAAE,KAAK;IAC3B,sBAAsB,EAAE,kBAAkB;IAC1C,YAAY,EAAE,IAAI;IAClB,qBAAqB,EAAE,KAAK;IAC5B,iBAAiB,EAAE,IAAI;IACvB,gBAAgB,EAAE,IAAI;IACtB,mBAAmB,EAAE,IAAI;IACzB,kBAAkB,EAAE,KAAK;IACzB,WAAW,EAAE,MAAM;IACnB,iBAAiB,EAAE,KAAK;CACzB,CAAC,CAAC;AAEH,wEAAwE;AACxE,MAAM,CAAC,MAAM,cAAc,GAAqB,MAAM,CAAC,MAAM,CAAC;IAC5D,GAAG,OAAO;IACV,EAAE,EAAE,gBAAgB;IACpB,MAAM,EAAE,KAAK;CACd,CAAC,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
import type { FormatDescriptor } from './descriptor';
|
|
3
|
+
/**
|
|
4
|
+
* The values a `z.enum` actually EMITS as JSON-Schema `enum` members.
|
|
5
|
+
*
|
|
6
|
+
* A numeric TypeScript enum compiles to a two-way map (`{A: 0, 0: 'A'}`), so
|
|
7
|
+
* the reverse-mapping keys have to be dropped or every value appears twice.
|
|
8
|
+
* Shared with `analyzeSchema` deliberately: the size budget counts what goes on
|
|
9
|
+
* the wire, and "what goes on the wire" must have ONE definition (a second
|
|
10
|
+
* copy of this filter would drift from the emitter it is supposed to measure).
|
|
11
|
+
*/
|
|
12
|
+
export declare function enumEmittedValues(schema: z.ZodEnum): unknown[];
|
|
13
|
+
/**
|
|
14
|
+
* The values a `z.literal` emits — one for the `const` form, several for the
|
|
15
|
+
* multi-value form that emits `enum`. Types JSON Schema cannot carry
|
|
16
|
+
* (functions, symbols, bigints, `undefined`) are dropped, matching the
|
|
17
|
+
* emitter. Shared with `analyzeSchema` for the same reason as above.
|
|
18
|
+
*/
|
|
19
|
+
export declare function literalEmittedValues(schema: z.ZodLiteral): unknown[];
|
|
20
|
+
/**
|
|
21
|
+
* Decide whether a set of values may be emitted as a JSON-Schema `enum` under
|
|
22
|
+
* this descriptor, per `maxEnumValues`.
|
|
23
|
+
*
|
|
24
|
+
* Under the cap (or with no cap declared) the caller emits its `enum` as
|
|
25
|
+
* normal. Over it, the caller emits NO `enum` — just the widened `type` — and
|
|
26
|
+
* attaches `note`, which lists EVERY value in prose.
|
|
27
|
+
*
|
|
28
|
+
* Widening rather than truncating is the deliberate choice, and the two differ
|
|
29
|
+
* in what the model can still say. A truncated `enum` makes the values past the
|
|
30
|
+
* cap **unreachable**: the wire schema constrains them away, so a caller whose
|
|
31
|
+
* 96 values are all legitimately selectable loses 56 of them. Widening removes
|
|
32
|
+
* the wire-level constraint that the dialect can't compile in the first place
|
|
33
|
+
* and moves the full list into the `description`, so the model retains complete
|
|
34
|
+
* information and can name any of the 96. Nothing is hidden — it is described
|
|
35
|
+
* instead of enforced, and enforcement moves to whatever validates the value
|
|
36
|
+
* afterwards (`Tool.parse` against the ORIGINAL zod schema still rejects a name
|
|
37
|
+
* that was never in the enum, with a message the model can act on).
|
|
38
|
+
*
|
|
39
|
+
* The note is deliberately DOMAIN-NEUTRAL. This library has no idea what the
|
|
40
|
+
* values mean; whichever caller relies on the cap (a session's known-name enum,
|
|
41
|
+
* a country list, anything) reads its own semantics into them.
|
|
42
|
+
*/
|
|
43
|
+
export declare function describeOversizeEnum(values: readonly unknown[], descriptor: FormatDescriptor): string | undefined;
|
|
44
|
+
//# sourceMappingURL=enum-values.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enum-values.d.ts","sourceRoot":"","sources":["../../src/schema/enum-values.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,KAAK,CAAC;AACpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,OAAO,EAAE,CAK9D;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,GAAG,OAAO,EAAE,CAIpE;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,EAAE,UAAU,EAAE,gBAAgB,GAAG,MAAM,GAAG,SAAS,CAMjH"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The values a `z.enum` actually EMITS as JSON-Schema `enum` members.
|
|
3
|
+
*
|
|
4
|
+
* A numeric TypeScript enum compiles to a two-way map (`{A: 0, 0: 'A'}`), so
|
|
5
|
+
* the reverse-mapping keys have to be dropped or every value appears twice.
|
|
6
|
+
* Shared with `analyzeSchema` deliberately: the size budget counts what goes on
|
|
7
|
+
* the wire, and "what goes on the wire" must have ONE definition (a second
|
|
8
|
+
* copy of this filter would drift from the emitter it is supposed to measure).
|
|
9
|
+
*/
|
|
10
|
+
export function enumEmittedValues(schema) {
|
|
11
|
+
const numericValues = Object.values(schema.def.entries).filter((v) => typeof v === 'number');
|
|
12
|
+
return Object.entries(schema.def.entries)
|
|
13
|
+
.filter(([k]) => numericValues.indexOf(+k) === -1)
|
|
14
|
+
.map(([, v]) => v);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The values a `z.literal` emits — one for the `const` form, several for the
|
|
18
|
+
* multi-value form that emits `enum`. Types JSON Schema cannot carry
|
|
19
|
+
* (functions, symbols, bigints, `undefined`) are dropped, matching the
|
|
20
|
+
* emitter. Shared with `analyzeSchema` for the same reason as above.
|
|
21
|
+
*/
|
|
22
|
+
export function literalEmittedValues(schema) {
|
|
23
|
+
return Array.from(schema.values).filter((v) => v !== undefined && typeof v !== 'function' && typeof v !== 'symbol' && typeof v !== 'bigint');
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Decide whether a set of values may be emitted as a JSON-Schema `enum` under
|
|
27
|
+
* this descriptor, per `maxEnumValues`.
|
|
28
|
+
*
|
|
29
|
+
* Under the cap (or with no cap declared) the caller emits its `enum` as
|
|
30
|
+
* normal. Over it, the caller emits NO `enum` — just the widened `type` — and
|
|
31
|
+
* attaches `note`, which lists EVERY value in prose.
|
|
32
|
+
*
|
|
33
|
+
* Widening rather than truncating is the deliberate choice, and the two differ
|
|
34
|
+
* in what the model can still say. A truncated `enum` makes the values past the
|
|
35
|
+
* cap **unreachable**: the wire schema constrains them away, so a caller whose
|
|
36
|
+
* 96 values are all legitimately selectable loses 56 of them. Widening removes
|
|
37
|
+
* the wire-level constraint that the dialect can't compile in the first place
|
|
38
|
+
* and moves the full list into the `description`, so the model retains complete
|
|
39
|
+
* information and can name any of the 96. Nothing is hidden — it is described
|
|
40
|
+
* instead of enforced, and enforcement moves to whatever validates the value
|
|
41
|
+
* afterwards (`Tool.parse` against the ORIGINAL zod schema still rejects a name
|
|
42
|
+
* that was never in the enum, with a message the model can act on).
|
|
43
|
+
*
|
|
44
|
+
* The note is deliberately DOMAIN-NEUTRAL. This library has no idea what the
|
|
45
|
+
* values mean; whichever caller relies on the cap (a session's known-name enum,
|
|
46
|
+
* a country list, anything) reads its own semantics into them.
|
|
47
|
+
*/
|
|
48
|
+
export function describeOversizeEnum(values, descriptor) {
|
|
49
|
+
const cap = descriptor.maxEnumValues;
|
|
50
|
+
if (cap === undefined || values.length <= cap)
|
|
51
|
+
return undefined;
|
|
52
|
+
// A flat comma-separated list: it is how an enum reads in prose anyway, and
|
|
53
|
+
// the values are single tokens by construction (they were `enum` members).
|
|
54
|
+
return `One of these ${values.length} values: ${values.map((v) => String(v)).join(', ')}`;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=enum-values.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enum-values.js","sourceRoot":"","sources":["../../src/schema/enum-values.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;IAC7F,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;SACtC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;SACjD,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AACvB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAoB;IACvD,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CACrC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,SAAS,IAAI,OAAO,CAAC,KAAK,UAAU,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ,CACpG,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAA0B,EAAE,UAA4B;IAC3F,MAAM,GAAG,GAAG,UAAU,CAAC,aAAa,CAAC;IACrC,IAAI,GAAG,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,SAAS,CAAC;IAChE,4EAA4E;IAC5E,2EAA2E;IAC3E,OAAO,gBAAgB,MAAM,CAAC,MAAM,YAAY,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC5F,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
import type { FormatDescriptor } from './descriptor';
|
|
3
|
+
/**
|
|
4
|
+
* Decide whether `schema` can be expressed as structured output under
|
|
5
|
+
* `descriptor`'s JSON-Schema dialect. Returns `false` when the schema uses a
|
|
6
|
+
* construct the descriptor forbids, so the caller can DROP the wire schema and
|
|
7
|
+
* deliver it as prompt text instead (see the ai-layer
|
|
8
|
+
* `applySchemaDeliveryFallback`).
|
|
9
|
+
*
|
|
10
|
+
* Walks the Zod schema in the same style as `strictify`/`convert`, honoring:
|
|
11
|
+
* - **unions** (`z.union` / `z.discriminatedUnion` → `anyOf`) when
|
|
12
|
+
* `!descriptor.allowAnyOf` (e.g. Gemini strict rejects `anyOf`);
|
|
13
|
+
* - **intersections** (`z.intersection` → `allOf`) when `!descriptor.allowAllOf`;
|
|
14
|
+
* - **recursion** (a self-referential `z.lazy` cycle → `$ref`): a cycle back to
|
|
15
|
+
* the ROOT is fine when `descriptor.allowRootRef && descriptor.supportsRecursion`
|
|
16
|
+
* (Gemini supports `$ref: '#'`); a non-root cycle needs
|
|
17
|
+
* `descriptor.allowDefsRef && descriptor.supportsRecursion`.
|
|
18
|
+
*
|
|
19
|
+
* `ZodNullable` / `ZodOptional` are transparent wrappers here (nullability is
|
|
20
|
+
* NOT treated as a union), so only genuine `z.union(...)` trips `allowAnyOf`.
|
|
21
|
+
* Non-combinator, non-recursive schemas (plain objects, arrays, primitives)
|
|
22
|
+
* are always expressible. The structure mirrors the descriptor flags so more
|
|
23
|
+
* feasibility checks are easy to add.
|
|
24
|
+
*
|
|
25
|
+
* Under a descriptor with `structuredOutputAlwaysStrict` the schema must also
|
|
26
|
+
* fit the strict limits on its own — the per-schema size limits and the
|
|
27
|
+
* per-request optional-parameter and union budgets — because that family has
|
|
28
|
+
* no non-strict structured output to degrade to.
|
|
29
|
+
*/
|
|
30
|
+
export declare function canExpress(schema: z.ZodType | z.core.$ZodType, descriptor: FormatDescriptor): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Whether `schema`, as the only strict schema in a request, stays inside the
|
|
33
|
+
* descriptor's size limits and per-request budgets.
|
|
34
|
+
*/
|
|
35
|
+
export declare function fitsStrictAlone(schema: z.ZodType | z.core.$ZodType, descriptor: FormatDescriptor): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* `canExpress`, except that a cycle counts as EXPRESSIBLE whatever the
|
|
38
|
+
* descriptor's ref flags say, because `emitCachedRef` replaces any back-edge
|
|
39
|
+
* the descriptor cannot spell with the bounded `buildCycleBreakerSchema`
|
|
40
|
+
* placeholder. The emitted schema is therefore always *sendable*; it is only
|
|
41
|
+
* *looser* than the source at the back-edge.
|
|
42
|
+
*
|
|
43
|
+
* That distinction is the whole reason there are two predicates:
|
|
44
|
+
* - `canExpress` answers "will the model be properly CONSTRAINED by this?",
|
|
45
|
+
* which is what a structured-OUTPUT delivery decision needs — a back-edge
|
|
46
|
+
* silently widened to "any" is a good reason to deliver the schema as prompt
|
|
47
|
+
* text instead (`applySchemaDeliveryFallback`), and
|
|
48
|
+
* `ANTHROPIC_STRICT`'s `supportsRecursion: false` is exactly that case.
|
|
49
|
+
* - this one answers "will the provider REJECT this?", which is what a TOOL's
|
|
50
|
+
* strict allocation needs. A tool has no prompt-text fallback, so degrading a
|
|
51
|
+
* merely-loose schema to LENIENT would trade a real strict guarantee for
|
|
52
|
+
* nothing.
|
|
53
|
+
*
|
|
54
|
+
* The combinator half is shared and is the half that actually bites: nothing
|
|
55
|
+
* rewrites a forbidden `anyOf`/`allOf` away, so a schema carrying one is a
|
|
56
|
+
* provider 400 under a descriptor that forbids it.
|
|
57
|
+
*/
|
|
58
|
+
export declare function sendableUnder(schema: z.ZodType | z.core.$ZodType, descriptor: FormatDescriptor): boolean;
|
|
59
|
+
//# sourceMappingURL=expressible.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expressible.d.ts","sourceRoot":"","sources":["../../src/schema/expressible.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,KAAK,CAAC;AACpB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAIrD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,UAAU,CACxB,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,EACnC,UAAU,EAAE,gBAAgB,GAC3B,OAAO,CAGT;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,gBAAgB,GAAG,OAAO,CAK1G;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,EACnC,UAAU,EAAE,gBAAgB,GAC3B,OAAO,CAET"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
import { walkKey } from './walk-key';
|
|
3
|
+
import { analyzeSchema, checkSchemaSizeLimits } from './analyze';
|
|
4
|
+
/**
|
|
5
|
+
* Decide whether `schema` can be expressed as structured output under
|
|
6
|
+
* `descriptor`'s JSON-Schema dialect. Returns `false` when the schema uses a
|
|
7
|
+
* construct the descriptor forbids, so the caller can DROP the wire schema and
|
|
8
|
+
* deliver it as prompt text instead (see the ai-layer
|
|
9
|
+
* `applySchemaDeliveryFallback`).
|
|
10
|
+
*
|
|
11
|
+
* Walks the Zod schema in the same style as `strictify`/`convert`, honoring:
|
|
12
|
+
* - **unions** (`z.union` / `z.discriminatedUnion` → `anyOf`) when
|
|
13
|
+
* `!descriptor.allowAnyOf` (e.g. Gemini strict rejects `anyOf`);
|
|
14
|
+
* - **intersections** (`z.intersection` → `allOf`) when `!descriptor.allowAllOf`;
|
|
15
|
+
* - **recursion** (a self-referential `z.lazy` cycle → `$ref`): a cycle back to
|
|
16
|
+
* the ROOT is fine when `descriptor.allowRootRef && descriptor.supportsRecursion`
|
|
17
|
+
* (Gemini supports `$ref: '#'`); a non-root cycle needs
|
|
18
|
+
* `descriptor.allowDefsRef && descriptor.supportsRecursion`.
|
|
19
|
+
*
|
|
20
|
+
* `ZodNullable` / `ZodOptional` are transparent wrappers here (nullability is
|
|
21
|
+
* NOT treated as a union), so only genuine `z.union(...)` trips `allowAnyOf`.
|
|
22
|
+
* Non-combinator, non-recursive schemas (plain objects, arrays, primitives)
|
|
23
|
+
* are always expressible. The structure mirrors the descriptor flags so more
|
|
24
|
+
* feasibility checks are easy to add.
|
|
25
|
+
*
|
|
26
|
+
* Under a descriptor with `structuredOutputAlwaysStrict` the schema must also
|
|
27
|
+
* fit the strict limits on its own — the per-schema size limits and the
|
|
28
|
+
* per-request optional-parameter and union budgets — because that family has
|
|
29
|
+
* no non-strict structured output to degrade to.
|
|
30
|
+
*/
|
|
31
|
+
export function canExpress(schema, descriptor) {
|
|
32
|
+
return expressible(schema, descriptor, /* cycleBreakerCounts */ false)
|
|
33
|
+
&& (!descriptor.structuredOutputAlwaysStrict || fitsStrictAlone(schema, descriptor));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Whether `schema`, as the only strict schema in a request, stays inside the
|
|
37
|
+
* descriptor's size limits and per-request budgets.
|
|
38
|
+
*/
|
|
39
|
+
export function fitsStrictAlone(schema, descriptor) {
|
|
40
|
+
const features = analyzeSchema(schema);
|
|
41
|
+
return checkSchemaSizeLimits(schema, descriptor).length === 0
|
|
42
|
+
&& features.optionalParameterCount <= (descriptor.maxStrictOptionalParams ?? Infinity)
|
|
43
|
+
&& features.unionTypeCount <= (descriptor.maxStrictUnionTypes ?? Infinity);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* `canExpress`, except that a cycle counts as EXPRESSIBLE whatever the
|
|
47
|
+
* descriptor's ref flags say, because `emitCachedRef` replaces any back-edge
|
|
48
|
+
* the descriptor cannot spell with the bounded `buildCycleBreakerSchema`
|
|
49
|
+
* placeholder. The emitted schema is therefore always *sendable*; it is only
|
|
50
|
+
* *looser* than the source at the back-edge.
|
|
51
|
+
*
|
|
52
|
+
* That distinction is the whole reason there are two predicates:
|
|
53
|
+
* - `canExpress` answers "will the model be properly CONSTRAINED by this?",
|
|
54
|
+
* which is what a structured-OUTPUT delivery decision needs — a back-edge
|
|
55
|
+
* silently widened to "any" is a good reason to deliver the schema as prompt
|
|
56
|
+
* text instead (`applySchemaDeliveryFallback`), and
|
|
57
|
+
* `ANTHROPIC_STRICT`'s `supportsRecursion: false` is exactly that case.
|
|
58
|
+
* - this one answers "will the provider REJECT this?", which is what a TOOL's
|
|
59
|
+
* strict allocation needs. A tool has no prompt-text fallback, so degrading a
|
|
60
|
+
* merely-loose schema to LENIENT would trade a real strict guarantee for
|
|
61
|
+
* nothing.
|
|
62
|
+
*
|
|
63
|
+
* The combinator half is shared and is the half that actually bites: nothing
|
|
64
|
+
* rewrites a forbidden `anyOf`/`allOf` away, so a schema carrying one is a
|
|
65
|
+
* provider 400 under a descriptor that forbids it.
|
|
66
|
+
*/
|
|
67
|
+
export function sendableUnder(schema, descriptor) {
|
|
68
|
+
return expressible(schema, descriptor, /* cycleBreakerCounts */ true);
|
|
69
|
+
}
|
|
70
|
+
function expressible(schema, descriptor, cycleBreakerCounts) {
|
|
71
|
+
// Keys, not objects — a rebuilt `z.lazy` getter defeats identity (see `walkKey`).
|
|
72
|
+
const rootKey = walkKey(schema);
|
|
73
|
+
// Nodes currently on the DFS stack — a re-encounter is a recursion cycle.
|
|
74
|
+
const inProgress = new Set();
|
|
75
|
+
// Completed nodes with their result, so shared (non-cyclic) sub-schemas
|
|
76
|
+
// aren't re-walked (guards against exponential blow-up on DAG-shaped schemas).
|
|
77
|
+
const completed = new Map();
|
|
78
|
+
const walk = (s) => {
|
|
79
|
+
const key = walkKey(s);
|
|
80
|
+
if (inProgress.has(key)) {
|
|
81
|
+
// Recursion cycle detected at `s`. The placeholder that makes a cycle
|
|
82
|
+
// sendable bottoms out at "any", which a `none` dialect cannot spell.
|
|
83
|
+
if (cycleBreakerCounts)
|
|
84
|
+
return descriptor.anyEncoding !== 'none';
|
|
85
|
+
if (key === rootKey)
|
|
86
|
+
return descriptor.allowRootRef && descriptor.supportsRecursion;
|
|
87
|
+
return descriptor.allowDefsRef && descriptor.supportsRecursion;
|
|
88
|
+
}
|
|
89
|
+
const cached = completed.get(key);
|
|
90
|
+
if (cached !== undefined)
|
|
91
|
+
return cached;
|
|
92
|
+
inProgress.add(key);
|
|
93
|
+
const result = walkNode(s);
|
|
94
|
+
inProgress.delete(key);
|
|
95
|
+
completed.set(key, result);
|
|
96
|
+
return result;
|
|
97
|
+
};
|
|
98
|
+
const walkNode = (s) => {
|
|
99
|
+
// ---- Transparent wrappers: recurse into the inner type ----
|
|
100
|
+
if (s instanceof z.ZodOptional || s instanceof z.ZodNullable)
|
|
101
|
+
return walk(s.unwrap());
|
|
102
|
+
if (s instanceof z.ZodDefault)
|
|
103
|
+
return walk(s._zod.def.innerType);
|
|
104
|
+
if (s instanceof z.ZodPrefault)
|
|
105
|
+
return walk(s._zod.def.innerType);
|
|
106
|
+
if (s instanceof z.ZodCatch)
|
|
107
|
+
return walk(s._zod.def.innerType);
|
|
108
|
+
if (s instanceof z.ZodReadonly)
|
|
109
|
+
return walk(s._zod.def.innerType);
|
|
110
|
+
if (s instanceof z.ZodNonOptional)
|
|
111
|
+
return walk(s._zod.def.innerType);
|
|
112
|
+
if (s instanceof z.ZodLazy)
|
|
113
|
+
return walk(s._zod.def.getter());
|
|
114
|
+
// ZodCodec must be checked before ZodPipe (it's a ZodPipe subclass in v4).
|
|
115
|
+
if (s instanceof z.ZodCodec)
|
|
116
|
+
return walk(s._zod.def.in) && walk(s._zod.def.out);
|
|
117
|
+
if (s instanceof z.ZodPipe)
|
|
118
|
+
return walk(s._zod.def.in) && walk(s._zod.def.out);
|
|
119
|
+
// ---- Combinators (the ones that actually bite) ----
|
|
120
|
+
// ZodDiscriminatedUnion is a ZodUnion subclass in v4, so this covers both.
|
|
121
|
+
if (s instanceof z.ZodUnion) {
|
|
122
|
+
if (!descriptor.allowAnyOf)
|
|
123
|
+
return false;
|
|
124
|
+
return s.options.every(walk);
|
|
125
|
+
}
|
|
126
|
+
if (s instanceof z.ZodIntersection) {
|
|
127
|
+
if (!descriptor.allowAllOf)
|
|
128
|
+
return false;
|
|
129
|
+
return walk(s._zod.def.left) && walk(s._zod.def.right);
|
|
130
|
+
}
|
|
131
|
+
// ---- Containers: recurse so nested combinators/cycles are reached ----
|
|
132
|
+
if (s instanceof z.ZodObject) {
|
|
133
|
+
for (const key in s.shape) {
|
|
134
|
+
if (!walk(s.shape[key]))
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
if (s instanceof z.ZodArray)
|
|
140
|
+
return walk(s._zod.def.element);
|
|
141
|
+
if (s instanceof z.ZodTuple) {
|
|
142
|
+
for (const item of s._zod.def.items) {
|
|
143
|
+
if (!walk(item))
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
return s._zod.def.rest ? walk(s._zod.def.rest) : true;
|
|
147
|
+
}
|
|
148
|
+
if (s instanceof z.ZodRecord)
|
|
149
|
+
return walk(s._zod.def.valueType);
|
|
150
|
+
if (s instanceof z.ZodMap)
|
|
151
|
+
return walk(s._zod.def.keyType) && walk(s._zod.def.valueType);
|
|
152
|
+
if (s instanceof z.ZodSet)
|
|
153
|
+
return walk(s._zod.def.valueType);
|
|
154
|
+
if (s instanceof z.ZodAny || s instanceof z.ZodUnknown)
|
|
155
|
+
return descriptor.anyEncoding !== 'none';
|
|
156
|
+
// ---- Leaves / anything without forbidden substructure ----
|
|
157
|
+
return true;
|
|
158
|
+
};
|
|
159
|
+
return walk(schema);
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=expressible.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expressible.js","sourceRoot":"","sources":["../../src/schema/expressible.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod → provider JSON Schema: dialect descriptors, the strictify / decode
|
|
3
|
+
* round trip, the emitter, and the per-request strict budget.
|
|
4
|
+
*/
|
|
5
|
+
export * from './descriptor';
|
|
6
|
+
export * from './dialects/lenient';
|
|
7
|
+
export * from './dialects/openai';
|
|
8
|
+
export * from './dialects/anthropic';
|
|
9
|
+
export * from './dialects/google';
|
|
10
|
+
export * from './dialects/xai';
|
|
11
|
+
export * from './consistency';
|
|
12
|
+
export * from './registry';
|
|
13
|
+
export { canExpress } from './expressible';
|
|
14
|
+
export * from './strictify';
|
|
15
|
+
export * from './decode';
|
|
16
|
+
export * from './json-schema';
|
|
17
|
+
export * from './to-json-schema';
|
|
18
|
+
export * from './analyze';
|
|
19
|
+
export * from './budget';
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod → provider JSON Schema: dialect descriptors, the strictify / decode
|
|
3
|
+
* round trip, the emitter, and the per-request strict budget.
|
|
4
|
+
*/
|
|
5
|
+
export * from './descriptor';
|
|
6
|
+
export * from './dialects/lenient';
|
|
7
|
+
export * from './dialects/openai';
|
|
8
|
+
export * from './dialects/anthropic';
|
|
9
|
+
export * from './dialects/google';
|
|
10
|
+
export * from './dialects/xai';
|
|
11
|
+
export * from './consistency';
|
|
12
|
+
export * from './registry';
|
|
13
|
+
export { canExpress } from './expressible';
|
|
14
|
+
export * from './strictify';
|
|
15
|
+
export * from './decode';
|
|
16
|
+
export * from './json-schema';
|
|
17
|
+
export * from './to-json-schema';
|
|
18
|
+
export * from './analyze';
|
|
19
|
+
export * from './budget';
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC"}
|