@vectoriox/iox-ui 5.61.0 → 5.62.1

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.
@@ -9,12 +9,26 @@ import type { JsonSchema } from './json-schema';
9
9
  * The limits are per REQUEST — every strict schema in it together. The ONE counter: the specs hold every schema iox-cms
10
10
  * sends to it, and the fake Claude API refuses with it exactly as Claude does — the plan stage once sent 213 optional
11
11
  * parameters and every suite stayed green because the fake accepted anything (vectoriox/iox-cms#45).
12
+ *
13
+ * Beyond those, Claude refuses a grammar it compiles too large — a limit the docs name ("additional internal limits on
14
+ * the compiled grammar size") without a number. MEASURED against the API on 2026-10-27 (vectoriox/iox-cms#47): the
15
+ * total number of properties decides it, not enums or descriptions — 64 and 61 properties refused, 53 and fewer
16
+ * accepted (53 already took ~9 s to compile). So 60 is the line we refuse above, and 40 is what we send.
12
17
  */
13
18
 
14
- export const STRICT_SCHEMA_LIMITS = { strictTools: 20, optional: 24, unions: 16 } as const;
19
+ export const STRICT_SCHEMA_LIMITS = {
20
+ strictTools: 20,
21
+ optional: 24,
22
+ unions: 16,
23
+ /** MEASURED, not documented (2026-10-27): the smallest refused request held 61 properties, the largest accepted 53. */
24
+ properties: 60,
25
+ } as const;
15
26
 
16
- /** What a schema iox-cms sends may use — half of each limit, so a step can gain a field (or a strict tool) without a 400. */
17
- export const STRICT_SCHEMA_BUDGET = { optional: 12, unions: 8 } as const;
27
+ /**
28
+ * What one request iox-cms sends may use: half of each documented limit, so a step can gain a field (or a strict tool)
29
+ * without a 400 — and 40 properties, a third under the measured grammar line, where compiling stays a few seconds.
30
+ */
31
+ export const STRICT_SCHEMA_BUDGET = { optional: 12, unions: 8, properties: 40 } as const;
18
32
 
19
33
  export interface StrictSchemaComplexity {
20
34
  /** Properties not listed in their object's `required`, every object of every schema. */
@@ -23,6 +37,10 @@ export interface StrictSchemaComplexity {
23
37
  unions: number;
24
38
  /** Tools with `strict: true` (a JSON output format is not a tool). */
25
39
  strictTools: number;
40
+ /** Every key of every object's `properties`, at every depth — what the compiled grammar's size follows. */
41
+ properties: number;
42
+ /** Objects that declare `properties`. */
43
+ objects: number;
26
44
  /** What the strict mode does not support, each with its path (`pages.items.properties.route: minLength`). */
27
45
  unsupported: string[];
28
46
  }
@@ -45,6 +63,8 @@ function count(node: unknown, path: string, out: StrictSchemaComplexity): void {
45
63
  if (node['type'] === 'object' || properties) {
46
64
  const required = new Set(Array.isArray(node['required']) ? (node['required'] as string[]) : []);
47
65
  out.optional += Object.keys(properties ?? {}).filter(key => !required.has(key)).length;
66
+ out.properties += Object.keys(properties ?? {}).length;
67
+ if (properties) out.objects++;
48
68
  if (node['additionalProperties'] !== false) out.unsupported.push(`${at('additionalProperties')}: must be false`);
49
69
  }
50
70
  for (const key of UNSUPPORTED_KEYWORDS) if (key in node) out.unsupported.push(`${at(key)}: not supported`);
@@ -63,7 +83,7 @@ function count(node: unknown, path: string, out: StrictSchemaComplexity): void {
63
83
 
64
84
  /** The cost of ONE request's strict schemas together: its JSON output format and its strict tools' input schemas. */
65
85
  export function strictSchemaComplexity(schemas: ReadonlyArray<JsonSchema>, strictTools = 0): StrictSchemaComplexity {
66
- const out: StrictSchemaComplexity = { optional: 0, unions: 0, strictTools, unsupported: [] };
86
+ const out: StrictSchemaComplexity = { optional: 0, unions: 0, strictTools, properties: 0, objects: 0, unsupported: [] };
67
87
  schemas.forEach((schema, i) => count(schema, schemas.length > 1 ? `[${i}]` : '', out));
68
88
  return out;
69
89
  }
@@ -75,10 +95,14 @@ export interface StrictSchemaRefusal {
75
95
  message: string;
76
96
  }
77
97
 
98
+ /** Claude's words for a grammar it compiles too large (2026-10-27, the plan stage — vectoriox/iox-cms#47), verbatim. */
99
+ export const GRAMMAR_TOO_LARGE_MESSAGE = 'The compiled grammar is too large, which would cause performance issues. Simplify your tool schemas or reduce the number of strict tools.';
100
+
78
101
  /**
79
- * The 400 the Claude API answers a request over its limits with, or null. The optional-parameter message is the one
80
- * Claude answered on 2026-10-27, verbatim; the union, strict-tool and unsupported messages follow its shape (not yet
81
- * captured).
102
+ * The 400 the Claude API answers a request over its limits with, or null. The optional-parameter and the grammar-size
103
+ * messages are the ones Claude answered on 2026-10-27, verbatim; the union, strict-tool and unsupported messages follow
104
+ * their shape (not yet captured). The documented limits are checked first: a request over one of them never reaches the
105
+ * grammar compiler.
82
106
  */
83
107
  export function strictSchemaRefusal(complexity: StrictSchemaComplexity): StrictSchemaRefusal | null {
84
108
  const refuse = (message: string): StrictSchemaRefusal => ({ status: 400, type: 'invalid_request_error', message });
@@ -92,5 +116,6 @@ export function strictSchemaRefusal(complexity: StrictSchemaComplexity): StrictS
92
116
  if (complexity.unions > STRICT_SCHEMA_LIMITS.unions) {
93
117
  return refuse(`Schemas contains too many parameters with union types (${complexity.unions}), which would make grammar compilation inefficient. Reduce the number of parameters with union types in your tool schemas (limit: ${STRICT_SCHEMA_LIMITS.unions}).`);
94
118
  }
119
+ if (complexity.properties > STRICT_SCHEMA_LIMITS.properties) return refuse(GRAMMAR_TOO_LARGE_MESSAGE);
95
120
  return null;
96
121
  }