prefix-safe-json 0.1.0 → 0.2.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 (134) hide show
  1. package/README.md +57 -3
  2. package/dist/coordinator/coordinator.d.ts +53 -0
  3. package/dist/coordinator/coordinator.d.ts.map +1 -0
  4. package/dist/coordinator/coordinator.js +477 -0
  5. package/dist/coordinator/coordinator.js.map +1 -0
  6. package/dist/coordinator/diagnostic-codes.d.ts +37 -0
  7. package/dist/coordinator/diagnostic-codes.d.ts.map +1 -0
  8. package/dist/coordinator/diagnostic-codes.js +48 -0
  9. package/dist/coordinator/diagnostic-codes.js.map +1 -0
  10. package/dist/coordinator/protocol.d.ts +62 -0
  11. package/dist/coordinator/protocol.d.ts.map +1 -0
  12. package/dist/coordinator/protocol.js +2 -0
  13. package/dist/coordinator/protocol.js.map +1 -0
  14. package/dist/coordinator/types.d.ts +104 -0
  15. package/dist/coordinator/types.d.ts.map +1 -0
  16. package/dist/coordinator/types.js +7 -0
  17. package/dist/coordinator/types.js.map +1 -0
  18. package/dist/diagnostics/codes.d.ts +24 -0
  19. package/dist/diagnostics/codes.d.ts.map +1 -0
  20. package/dist/diagnostics/codes.js +28 -0
  21. package/dist/diagnostics/codes.js.map +1 -0
  22. package/dist/diagnostics/factory.d.ts +8 -0
  23. package/dist/diagnostics/factory.d.ts.map +1 -0
  24. package/dist/diagnostics/factory.js +17 -0
  25. package/dist/diagnostics/factory.js.map +1 -0
  26. package/dist/gate/decide.d.ts +27 -0
  27. package/dist/gate/decide.d.ts.map +1 -0
  28. package/dist/gate/decide.js +179 -0
  29. package/dist/gate/decide.js.map +1 -0
  30. package/dist/gate/gate.d.ts +25 -0
  31. package/dist/gate/gate.d.ts.map +1 -0
  32. package/dist/gate/gate.js +96 -0
  33. package/dist/gate/gate.js.map +1 -0
  34. package/dist/gate/types.d.ts +184 -0
  35. package/dist/gate/types.d.ts.map +1 -0
  36. package/dist/gate/types.js +2 -0
  37. package/dist/gate/types.js.map +1 -0
  38. package/dist/grammar/frame.d.ts +58 -0
  39. package/dist/grammar/frame.d.ts.map +1 -0
  40. package/dist/grammar/frame.js +87 -0
  41. package/dist/grammar/frame.js.map +1 -0
  42. package/dist/grammar/pointer.d.ts +10 -0
  43. package/dist/grammar/pointer.d.ts.map +1 -0
  44. package/dist/grammar/pointer.js +20 -0
  45. package/dist/grammar/pointer.js.map +1 -0
  46. package/dist/grammar/stack.d.ts +73 -0
  47. package/dist/grammar/stack.d.ts.map +1 -0
  48. package/dist/grammar/stack.js +168 -0
  49. package/dist/grammar/stack.js.map +1 -0
  50. package/dist/guard/ai-sdk.d.ts +48 -0
  51. package/dist/guard/ai-sdk.d.ts.map +1 -0
  52. package/dist/guard/ai-sdk.js +51 -0
  53. package/dist/guard/ai-sdk.js.map +1 -0
  54. package/dist/guard/provider-guard.d.ts +4 -0
  55. package/dist/guard/provider-guard.d.ts.map +1 -0
  56. package/dist/guard/provider-guard.js +38 -0
  57. package/dist/guard/provider-guard.js.map +1 -0
  58. package/dist/guard/types.d.ts +48 -0
  59. package/dist/guard/types.d.ts.map +1 -0
  60. package/dist/guard/types.js +2 -0
  61. package/dist/guard/types.js.map +1 -0
  62. package/dist/index.d.ts +85 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +99 -0
  65. package/dist/index.js.map +1 -0
  66. package/dist/lexer/scanner.d.ts +106 -0
  67. package/dist/lexer/scanner.d.ts.map +1 -0
  68. package/dist/lexer/scanner.js +658 -0
  69. package/dist/lexer/scanner.js.map +1 -0
  70. package/dist/lexer/states.d.ts +31 -0
  71. package/dist/lexer/states.d.ts.map +1 -0
  72. package/dist/lexer/states.js +35 -0
  73. package/dist/lexer/states.js.map +1 -0
  74. package/dist/lexer/tokens.d.ts +22 -0
  75. package/dist/lexer/tokens.d.ts.map +1 -0
  76. package/dist/lexer/tokens.js +22 -0
  77. package/dist/lexer/tokens.js.map +1 -0
  78. package/dist/limits.d.ts +14 -0
  79. package/dist/limits.d.ts.map +1 -0
  80. package/dist/limits.js +23 -0
  81. package/dist/limits.js.map +1 -0
  82. package/dist/parser.d.ts +6 -0
  83. package/dist/parser.d.ts.map +1 -0
  84. package/dist/parser.js +922 -0
  85. package/dist/parser.js.map +1 -0
  86. package/dist/providers/adapter.d.ts +10 -0
  87. package/dist/providers/adapter.d.ts.map +1 -0
  88. package/dist/providers/adapter.js +2 -0
  89. package/dist/providers/adapter.js.map +1 -0
  90. package/dist/providers/ai-sdk.d.ts +63 -0
  91. package/dist/providers/ai-sdk.d.ts.map +1 -0
  92. package/dist/providers/ai-sdk.js +240 -0
  93. package/dist/providers/ai-sdk.js.map +1 -0
  94. package/dist/providers/anthropic.d.ts +45 -0
  95. package/dist/providers/anthropic.d.ts.map +1 -0
  96. package/dist/providers/anthropic.js +112 -0
  97. package/dist/providers/anthropic.js.map +1 -0
  98. package/dist/providers/gemini.d.ts +31 -0
  99. package/dist/providers/gemini.d.ts.map +1 -0
  100. package/dist/providers/gemini.js +94 -0
  101. package/dist/providers/gemini.js.map +1 -0
  102. package/dist/providers/openai-compatible.d.ts +33 -0
  103. package/dist/providers/openai-compatible.d.ts.map +1 -0
  104. package/dist/providers/openai-compatible.js +160 -0
  105. package/dist/providers/openai-compatible.js.map +1 -0
  106. package/dist/providers/openai.d.ts +55 -0
  107. package/dist/providers/openai.d.ts.map +1 -0
  108. package/dist/providers/openai.js +263 -0
  109. package/dist/providers/openai.js.map +1 -0
  110. package/dist/providers/openrouter.d.ts +35 -0
  111. package/dist/providers/openrouter.d.ts.map +1 -0
  112. package/dist/providers/openrouter.js +55 -0
  113. package/dist/providers/openrouter.js.map +1 -0
  114. package/dist/semantic/builder.d.ts +55 -0
  115. package/dist/semantic/builder.d.ts.map +1 -0
  116. package/dist/semantic/builder.js +140 -0
  117. package/dist/semantic/builder.js.map +1 -0
  118. package/dist/semantic/events.d.ts +2 -0
  119. package/dist/semantic/events.d.ts.map +1 -0
  120. package/dist/semantic/events.js +5 -0
  121. package/dist/semantic/events.js.map +1 -0
  122. package/dist/semantic/snapshot.d.ts +56 -0
  123. package/dist/semantic/snapshot.d.ts.map +1 -0
  124. package/dist/semantic/snapshot.js +230 -0
  125. package/dist/semantic/snapshot.js.map +1 -0
  126. package/dist/types.d.ts +156 -0
  127. package/dist/types.d.ts.map +1 -0
  128. package/dist/types.js +5 -0
  129. package/dist/types.js.map +1 -0
  130. package/dist/utf8/decoder.d.ts +53 -0
  131. package/dist/utf8/decoder.d.ts.map +1 -0
  132. package/dist/utf8/decoder.js +323 -0
  133. package/dist/utf8/decoder.js.map +1 -0
  134. package/package.json +2 -1
package/README.md CHANGED
@@ -4,8 +4,8 @@
4
4
 
5
5
  **Don't execute incomplete AI tool calls.**
6
6
 
7
- `prefix-safe-json` is a fail-closed integrity layer for streamed LLM tool
8
- calls. It distinguishes complete, unfabricated arguments from truncated
7
+ `prefix-safe-json` is a fail-closed execution-integrity layer for streamed
8
+ LLM tool calls. It distinguishes complete, unfabricated arguments from truncated
9
9
  ones — including ones a syntax-level JSON repairer can make *look* complete
10
10
  — before they reach a tool with real side effects (writing a file, running a
11
11
  command, sending a request).
@@ -94,12 +94,56 @@ provider, or framework hands it the data. See
94
94
  `test/guard/ai-sdk-compatibility.test.ts` for the cross-version test
95
95
  evidence.
96
96
 
97
+ **Execution ownership: what must never also happen**
98
+
99
+ The guard's decisions only mean something if it's the sole thing deciding
100
+ whether your tool function runs. The pattern above works because it never
101
+ gives the AI SDK's own tool-calling loop a chance to run your tool itself:
102
+
103
+ - **Safe, supported pattern** — define your tools *without* an AI SDK-native
104
+ `execute` callback at all. Not even a no-op one: the guard treats any
105
+ `tool-result`/`tool-error` it observes as proof the SDK's tool loop
106
+ already invoked that call, and a no-op callback still produces one —
107
+ omitting `execute` entirely is what keeps the SDK from running the tool
108
+ itself in the first place. Consume `fullStream` yourself, and dispatch
109
+ manually — only for `action === "execute"` — after `guard.finish()`,
110
+ exactly as shown above.
111
+ - **Unprotected / misuse pattern** — attach the real, irreversible operation
112
+ (or any `execute` implementation at all, no-op included) as the tool's own
113
+ AI SDK-native callback, *and* separately run the guard on the same
114
+ stream. The SDK can invoke `execute` as soon as it resolves that call's
115
+ input, independent of and often before this guard ever reaches a
116
+ decision. If that happens, the side effect has already run —
117
+ `prefix-safe-json` cannot retroactively undo it.
118
+
119
+ The guard does defend against the second pattern in one specific way: a
120
+ `tool-result` or `tool-error` part on `fullStream` is direct evidence the
121
+ SDK's own loop already invoked *some* call. When it names a specific call
122
+ (a real `toolCallId`), only that call is disqualified; when it doesn't, the
123
+ guard cannot tell which in-flight call was affected and fails closed for
124
+ **every** call in that stream rather than guess. Either way the guard never
125
+ again reports `action: "execute"` for the affected call(s)
126
+ (`reason: "sdk_execution_observed"`, which takes priority over every other
127
+ rejection reason), so a caller who also runs the documented manual-dispatch
128
+ loop will not invoke the tool function a *second* time. It does not undo
129
+ whatever the SDK's own callback already did. See
130
+ [`docs/EXECUTION_GATE.md`](docs/EXECUTION_GATE.md#execution-ownership-tool-resulttool-error-as-evidence)
131
+ for the full behavior and test matrix.
132
+
97
133
  **Supported providers**: OpenAI (legacy `function_call` and Responses API),
98
134
  Anthropic, Gemini, OpenRouter, generic OpenAI-compatible endpoints, and the
99
135
  Vercel AI SDK. High-level guards currently ship for the AI SDK; every
100
136
  provider has a public low-level adapter (see below) that composes with
101
137
  `createToolCallExecutionGate()` the same way.
102
138
 
139
+ `AiSdkStreamAdapter`/`createAiSdkExecutionGuard()` target the public
140
+ `streamText()`/`generateText()` `fullStream` surface, whose `finishReason`
141
+ is a plain unified string (`"stop"`, `"length"`, ...). They are not
142
+ currently an adapter for the lower-level `@ai-sdk/provider` `doStream()`
143
+ boundary (`LanguageModelV3`/`V4`), where finish reason is
144
+ `{ unified, raw }`-object-shaped — building your own provider against that
145
+ interface directly needs different handling of that field.
146
+
103
147
  Full semantics, the decision table, provider finish-reason mapping, and the
104
148
  high-level guard API: [`docs/EXECUTION_GATE.md`](docs/EXECUTION_GATE.md).
105
149
 
@@ -120,6 +164,8 @@ This library parses each chunk incrementally and provides:
120
164
 
121
165
  > The parser never fabricates missing data. It clearly distinguishes what is definite, what is pending, what was deterministically repaired, and what is lost.
122
166
 
167
+ > **Valid JSON is not safe generation completion. Safe generation completion is not permission to execute a side effect.** Structural validity, confirmed completeness, and execution authority are three separate questions — the gate layer (below) answers all three before ever returning `execute`, not just the first. See [`docs/THREAT_MODEL.md`](docs/THREAT_MODEL.md) for the full guarantee/non-guarantee list.
168
+
123
169
  ## Why not a general "partial JSON" parser?
124
170
 
125
171
  Most streaming JSON helpers (including ones already used in the wild for
@@ -210,7 +256,9 @@ It does **not**:
210
256
  with complete, schema-valid arguments is still reported `execute`)
211
257
 
212
258
  See [`docs/EXECUTION_GATE.md`](docs/EXECUTION_GATE.md#limitations---what-this-does-not-protect-against)
213
- for the full list, including known internal limitations.
259
+ for the full list, including known internal limitations, and
260
+ [`docs/THREAT_MODEL.md`](docs/THREAT_MODEL.md) for the complete security
261
+ objective, trust boundaries, and guarantee/non-guarantee list.
214
262
 
215
263
  ## Current Status
216
264
 
@@ -229,6 +277,7 @@ for the full list, including known internal limitations.
229
277
  - Optional per-tool JSON Schema validation on the coordinator (see below) — a value can be structurally complete and still not match what a tool declared it needs
230
278
  - `createToolCallExecutionGate()` — a fail-closed `execute` / `retry` / `reject` decision per tool call, built on top of the coordinator (see [`docs/EXECUTION_GATE.md`](docs/EXECUTION_GATE.md))
231
279
  - `createAiSdkExecutionGuard()` — a drop-in high-level guard for the Vercel AI SDK's `fullStream`, composing a provider adapter with the execution gate; every `ExecutionDecision` also carries an `evidence` object explaining why (see [`docs/EXECUTION_GATE.md`](docs/EXECUTION_GATE.md#high-level-guards))
280
+ - SDK execution-ownership detection — direct evidence that the AI SDK's own tool loop already invoked a call (attributed or, when it can't be, stream-wide) permanently blocks this library from also authorizing it, with the highest rejection-reason priority of any disqualifier (see [`docs/EXECUTION_GATE.md`](docs/EXECUTION_GATE.md#execution-ownership-tool-resulttool-error-as-evidence))
232
281
 
233
282
  ### Not Yet Implemented
234
283
 
@@ -271,6 +320,11 @@ A schema mismatch also surfaces as a coordinator diagnostic (`E_SCHEMA_VALIDATIO
271
320
  npm install prefix-safe-json
272
321
  ```
273
322
 
323
+ ESM only — `import`, not `require`. There is currently no CommonJS build.
324
+ Node `>=18.0.0`. See [`docs/COMPATIBILITY.md`](docs/COMPATIBILITY.md) for
325
+ the full ESM/Node/SemVer/Stable-vs-Experimental policy and the per-provider
326
+ compatibility matrix.
327
+
274
328
  ## Low-level API: Quick Start
275
329
 
276
330
  The AI SDK guard (above) covers the common case. For other providers, or
@@ -0,0 +1,53 @@
1
+ import { ParserOptions } from "../types.js";
2
+ import { NormalizedToolStreamEvent, StreamEndReason } from "./protocol.js";
3
+ import { ToolCallStreamCoordinator, ToolCallCoordinatorSnapshot, ToolCallCoordinatorEvent, ToolCallCoordinatorFinalResult, CoordinatorPushResult, CoordinatorLimits, JsonSchemaLike } from "./types.js";
4
+ export declare class DefaultToolCallStreamCoordinator implements ToolCallStreamCoordinator {
5
+ private readonly limits;
6
+ private readonly parserOptions;
7
+ private readonly toolValidators;
8
+ private calls;
9
+ private sourceKeyToInternalId;
10
+ private callCounter;
11
+ private eventQueue;
12
+ private diagnostics;
13
+ private eventsProcessed;
14
+ private globalSequence;
15
+ private isFinished;
16
+ /**
17
+ * @param limits Coordinator-level limits (concurrent tool calls, tool name
18
+ * size, etc.) — distinct from `parserOptions`, which configures each
19
+ * underlying per-call IncrementalJsonParser (limits, repairs). Previously
20
+ * there was no way to pass the latter through at all; every parser the
21
+ * coordinator created was hardcoded to library defaults.
22
+ * @param toolSchemas Optional JSON Schema (draft-07) per tool name. When a
23
+ * call for a registered tool reaches outcome "complete", its
24
+ * `stableValue` is validated against the schema. Structural
25
+ * prefix-safety (no truncated/fabricated values) and schema validity
26
+ * are independent concerns — a value can be genuinely complete and
27
+ * still not match what the tool declared it needs (wrong type, missing
28
+ * required field the model never provided at all). Both must hold for
29
+ * `executable` to be true. Schemas are compiled eagerly here so a
30
+ * malformed schema fails fast at construction, not mid-stream.
31
+ */
32
+ constructor(limits?: Partial<CoordinatorLimits>, parserOptions?: ParserOptions, toolSchemas?: Record<string, JsonSchemaLike>);
33
+ push(event: NormalizedToolStreamEvent): CoordinatorPushResult;
34
+ private handleStart;
35
+ private handleIdentity;
36
+ private handleNameDelta;
37
+ private handleArgumentsDelta;
38
+ private handleCallEnd;
39
+ private finishCall;
40
+ private hasCallConflict;
41
+ private handleProviderDiagnostic;
42
+ private handleStreamEnd;
43
+ private getCall;
44
+ private addDiagnostic;
45
+ snapshot(): ToolCallCoordinatorSnapshot;
46
+ drainEvents(): readonly ToolCallCoordinatorEvent[];
47
+ finish(meta?: {
48
+ reason?: StreamEndReason;
49
+ providerReason?: string;
50
+ }): ToolCallCoordinatorFinalResult;
51
+ }
52
+ export declare function createToolCallStreamCoordinator(limits?: Partial<CoordinatorLimits>, parserOptions?: ParserOptions, toolSchemas?: Record<string, JsonSchemaLike>): ToolCallStreamCoordinator;
53
+ //# sourceMappingURL=coordinator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinator.d.ts","sourceRoot":"","sources":["../../src/coordinator/coordinator.ts"],"names":[],"mappings":"AACA,OAAO,EAAyB,aAAa,EAAE,MAAM,aAAa,CAAC;AAEnE,OAAO,EAAE,yBAAyB,EAAgB,eAAe,EAAE,MAAM,eAAe,CAAC;AACzF,OAAO,EACL,yBAAyB,EACzB,2BAA2B,EAC3B,wBAAwB,EACxB,8BAA8B,EAC9B,qBAAqB,EACrB,iBAAiB,EAIjB,cAAc,EACf,MAAM,YAAY,CAAC;AAwCpB,qBAAa,gCAAiC,YAAW,yBAAyB;IAChF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAC3C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA4B;IAC1D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgC;IAC/D,OAAO,CAAC,KAAK,CAAgD;IAC7D,OAAO,CAAC,qBAAqB,CAAkC;IAC/D,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,UAAU,CAAkC;IACpD,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,UAAU,CAAS;IAE3B;;;;;;;;;;;;;;;OAeG;gBAED,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,EACnC,aAAa,CAAC,EAAE,aAAa,EAC7B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC;IAa9C,IAAI,CAAC,KAAK,EAAE,yBAAyB,GAAG,qBAAqB;IAgD7D,OAAO,CAAC,WAAW;IAqDnB,OAAO,CAAC,cAAc;IAgDtB,OAAO,CAAC,eAAe;IAqCvB,OAAO,CAAC,oBAAoB;IA8B5B,OAAO,CAAC,aAAa;IA6BrB,OAAO,CAAC,UAAU;IAoElB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,wBAAwB;IA6BhC,OAAO,CAAC,eAAe;IAyBvB,OAAO,CAAC,OAAO;IAcf,OAAO,CAAC,aAAa;IASrB,QAAQ,IAAI,2BAA2B;IAmBvC,WAAW,IAAI,SAAS,wBAAwB,EAAE;IAMlD,MAAM,CAAC,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,eAAe,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,8BAA8B;CAcrG;AAED,wBAAgB,+BAA+B,CAC7C,MAAM,CAAC,EAAE,OAAO,CAAC,iBAAiB,CAAC,EACnC,aAAa,CAAC,EAAE,aAAa,EAC7B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GAC3C,yBAAyB,CAE3B"}
@@ -0,0 +1,477 @@
1
+ import { Ajv } from "ajv";
2
+ import { createParser } from "../parser.js";
3
+ import { DEFAULT_COORDINATOR_LIMITS } from "./types.js";
4
+ import { SDK_EXECUTION_OBSERVED_DIAGNOSTIC_CODE, SDK_EXECUTION_ERROR_DIAGNOSTIC_CODE, } from "./diagnostic-codes.js";
5
+ // A `provider_diagnostic` carrying either code is proof that a provider SDK's
6
+ // own tool loop already invoked this call's `execute` callback (see the two
7
+ // constants' own docs in diagnostic-codes.ts) - success and failure get
8
+ // identical treatment here, since neither proves the absence of a partial
9
+ // irreversible side effect, and this library only needs to know that
10
+ // execution authority already left its hands.
11
+ const SDK_EXECUTION_OBSERVED_CODES = new Set([
12
+ SDK_EXECUTION_OBSERVED_DIAGNOSTIC_CODE,
13
+ SDK_EXECUTION_ERROR_DIAGNOSTIC_CODE,
14
+ ]);
15
+ class CoordinatorCallState {
16
+ internalId;
17
+ provider;
18
+ toolCallId;
19
+ toolIndex;
20
+ name;
21
+ nameComplete = false;
22
+ argumentStreamClosed = false;
23
+ parser;
24
+ status = "collecting";
25
+ schemaValid;
26
+ constructor(internalId, provider, parser) {
27
+ this.internalId = internalId;
28
+ this.provider = provider;
29
+ this.parser = parser;
30
+ }
31
+ }
32
+ export class DefaultToolCallStreamCoordinator {
33
+ limits;
34
+ parserOptions;
35
+ toolValidators;
36
+ calls = new Map();
37
+ sourceKeyToInternalId = new Map();
38
+ callCounter = 0;
39
+ eventQueue = [];
40
+ diagnostics = [];
41
+ eventsProcessed = 0;
42
+ globalSequence = 0;
43
+ isFinished = false;
44
+ /**
45
+ * @param limits Coordinator-level limits (concurrent tool calls, tool name
46
+ * size, etc.) — distinct from `parserOptions`, which configures each
47
+ * underlying per-call IncrementalJsonParser (limits, repairs). Previously
48
+ * there was no way to pass the latter through at all; every parser the
49
+ * coordinator created was hardcoded to library defaults.
50
+ * @param toolSchemas Optional JSON Schema (draft-07) per tool name. When a
51
+ * call for a registered tool reaches outcome "complete", its
52
+ * `stableValue` is validated against the schema. Structural
53
+ * prefix-safety (no truncated/fabricated values) and schema validity
54
+ * are independent concerns — a value can be genuinely complete and
55
+ * still not match what the tool declared it needs (wrong type, missing
56
+ * required field the model never provided at all). Both must hold for
57
+ * `executable` to be true. Schemas are compiled eagerly here so a
58
+ * malformed schema fails fast at construction, not mid-stream.
59
+ */
60
+ constructor(limits, parserOptions, toolSchemas) {
61
+ this.limits = { ...DEFAULT_COORDINATOR_LIMITS, ...limits };
62
+ this.parserOptions = parserOptions;
63
+ this.toolValidators = new Map();
64
+ if (toolSchemas) {
65
+ const ajv = new Ajv({ allErrors: true, strict: false });
66
+ for (const [toolName, schema] of Object.entries(toolSchemas)) {
67
+ this.toolValidators.set(toolName, ajv.compile(schema));
68
+ }
69
+ }
70
+ }
71
+ push(event) {
72
+ if (this.isFinished) {
73
+ this.addDiagnostic({
74
+ code: "E_EVENT_AFTER_STREAM_END",
75
+ severity: "error",
76
+ message: "Event pushed after stream end",
77
+ });
78
+ return { accepted: false };
79
+ }
80
+ if (this.eventsProcessed >= this.limits.maxNormalizedEvents) {
81
+ this.addDiagnostic({
82
+ code: "E_COORDINATOR_LIMIT_EVENTS",
83
+ severity: "fatal",
84
+ message: "Maximum normalized events exceeded",
85
+ });
86
+ return { accepted: false };
87
+ }
88
+ this.eventsProcessed++;
89
+ switch (event.type) {
90
+ case "tool_call_start":
91
+ this.handleStart(event);
92
+ break;
93
+ case "tool_call_identity":
94
+ this.handleIdentity(event);
95
+ break;
96
+ case "tool_call_name_delta":
97
+ this.handleNameDelta(event);
98
+ break;
99
+ case "tool_call_arguments_delta":
100
+ this.handleArgumentsDelta(event);
101
+ break;
102
+ case "tool_call_end":
103
+ this.handleCallEnd(event);
104
+ break;
105
+ case "provider_diagnostic":
106
+ this.handleProviderDiagnostic(event);
107
+ break;
108
+ case "provider_stream_end":
109
+ this.handleStreamEnd(event);
110
+ break;
111
+ }
112
+ return { accepted: true };
113
+ }
114
+ handleStart(event) {
115
+ const sourceKey = event.callRef.sourceKey;
116
+ const existingId = this.sourceKeyToInternalId.get(sourceKey);
117
+ if (existingId !== undefined) {
118
+ this.addDiagnostic({
119
+ code: "E_DUPLICATE_TOOL_CALL_START",
120
+ severity: "error",
121
+ internalId: existingId,
122
+ message: `Duplicate start for tool call sourceKey: ${sourceKey}`,
123
+ });
124
+ return;
125
+ }
126
+ if (this.calls.size >= this.limits.maxToolCalls) {
127
+ this.addDiagnostic({
128
+ code: "E_COORDINATOR_LIMIT_CALLS",
129
+ severity: "error",
130
+ message: "Maximum tool calls exceeded",
131
+ });
132
+ return;
133
+ }
134
+ const internalId = `call-${this.callCounter++}`;
135
+ this.sourceKeyToInternalId.set(sourceKey, internalId);
136
+ const parser = createParser(this.parserOptions);
137
+ const call = new CoordinatorCallState(internalId, event.provider, parser);
138
+ if (event.toolCallId !== undefined)
139
+ call.toolCallId = event.toolCallId;
140
+ if (event.toolIndex !== undefined)
141
+ call.toolIndex = event.toolIndex;
142
+ if (event.name !== undefined)
143
+ call.name = event.name;
144
+ this.calls.set(internalId, call);
145
+ this.eventQueue.push({
146
+ type: "tool_call_discovered",
147
+ sequence: this.globalSequence++,
148
+ internalId,
149
+ provider: event.provider,
150
+ });
151
+ if (event.toolCallId !== undefined || event.toolIndex !== undefined) {
152
+ this.eventQueue.push({
153
+ type: "tool_call_identity_updated",
154
+ sequence: this.globalSequence++,
155
+ internalId,
156
+ toolCallId: event.toolCallId,
157
+ toolIndex: event.toolIndex,
158
+ });
159
+ }
160
+ }
161
+ handleIdentity(event) {
162
+ const internalId = this.sourceKeyToInternalId.get(event.callRef.sourceKey);
163
+ if (!internalId)
164
+ return;
165
+ const call = this.getCall(internalId);
166
+ if (!call)
167
+ return;
168
+ let changed = false;
169
+ if (event.toolCallId !== undefined) {
170
+ if (call.toolCallId !== undefined && call.toolCallId !== event.toolCallId) {
171
+ this.addDiagnostic({
172
+ code: "E_PROVIDER_IDENTITY_CONFLICT",
173
+ severity: "error",
174
+ internalId: call.internalId,
175
+ message: `Conflicting ID: had ${call.toolCallId}, got ${event.toolCallId}`,
176
+ });
177
+ call.status = "invalid";
178
+ }
179
+ else if (call.toolCallId === undefined) {
180
+ call.toolCallId = event.toolCallId;
181
+ changed = true;
182
+ }
183
+ }
184
+ if (event.toolIndex !== undefined) {
185
+ if (call.toolIndex !== undefined && call.toolIndex !== event.toolIndex) {
186
+ this.addDiagnostic({
187
+ code: "E_PROVIDER_INDEX_CONFLICT",
188
+ severity: "error",
189
+ internalId: call.internalId,
190
+ message: `Conflicting index: had ${call.toolIndex}, got ${event.toolIndex}`,
191
+ });
192
+ call.status = "invalid";
193
+ }
194
+ else if (call.toolIndex === undefined) {
195
+ call.toolIndex = event.toolIndex;
196
+ changed = true;
197
+ }
198
+ }
199
+ if (changed) {
200
+ this.eventQueue.push({
201
+ type: "tool_call_identity_updated",
202
+ sequence: this.globalSequence++,
203
+ internalId: call.internalId,
204
+ toolCallId: call.toolCallId,
205
+ toolIndex: call.toolIndex,
206
+ });
207
+ }
208
+ }
209
+ handleNameDelta(event) {
210
+ const internalId = this.sourceKeyToInternalId.get(event.callRef.sourceKey);
211
+ if (!internalId)
212
+ return;
213
+ const call = this.getCall(internalId);
214
+ if (!call)
215
+ return;
216
+ if (call.status !== "collecting") {
217
+ this.addDiagnostic({
218
+ code: "E_NAME_DELTA_AFTER_END",
219
+ severity: "error",
220
+ internalId: call.internalId,
221
+ message: "Name delta after call ended",
222
+ });
223
+ return;
224
+ }
225
+ call.name = (call.name ?? "") + event.delta;
226
+ if (call.name.length > this.limits.maxToolNameBytes) {
227
+ this.addDiagnostic({
228
+ code: "E_TOOL_NAME_LIMIT",
229
+ severity: "error",
230
+ internalId: call.internalId,
231
+ message: "Tool name exceeded maximum length",
232
+ });
233
+ call.status = "invalid";
234
+ }
235
+ this.eventQueue.push({
236
+ type: "tool_name_updated",
237
+ sequence: event.sequence,
238
+ internalId: call.internalId,
239
+ name: call.name,
240
+ complete: false,
241
+ });
242
+ }
243
+ handleArgumentsDelta(event) {
244
+ const internalId = this.sourceKeyToInternalId.get(event.callRef.sourceKey);
245
+ if (!internalId)
246
+ return;
247
+ const call = this.getCall(internalId);
248
+ if (!call)
249
+ return;
250
+ if (call.status !== "collecting") {
251
+ this.addDiagnostic({
252
+ code: "E_ARGUMENT_DELTA_AFTER_END",
253
+ severity: "error",
254
+ internalId: call.internalId,
255
+ message: "Argument delta after call ended",
256
+ });
257
+ return;
258
+ }
259
+ call.parser.push(event.delta);
260
+ // Drain parser events and map them to coordinator events
261
+ const parserEvents = call.parser.drainEvents();
262
+ for (const pe of parserEvents) {
263
+ this.eventQueue.push({
264
+ type: "tool_argument_event",
265
+ sequence: this.globalSequence++,
266
+ internalId: call.internalId,
267
+ event: pe,
268
+ });
269
+ }
270
+ }
271
+ handleCallEnd(event) {
272
+ const internalId = this.sourceKeyToInternalId.get(event.callRef.sourceKey);
273
+ if (!internalId)
274
+ return;
275
+ const call = this.getCall(internalId);
276
+ if (!call)
277
+ return;
278
+ if (call.status !== "collecting")
279
+ return;
280
+ call.nameComplete = true;
281
+ call.argumentStreamClosed = true;
282
+ if (call.name !== undefined) {
283
+ this.eventQueue.push({
284
+ type: "tool_name_updated",
285
+ sequence: this.globalSequence++,
286
+ internalId: call.internalId,
287
+ name: call.name,
288
+ complete: true,
289
+ });
290
+ }
291
+ else {
292
+ this.addDiagnostic({
293
+ code: "E_TOOL_NAME_MISSING",
294
+ severity: "error",
295
+ internalId: call.internalId,
296
+ message: "Tool name missing at end",
297
+ });
298
+ }
299
+ }
300
+ finishCall(call, reason) {
301
+ if (call.status !== "collecting")
302
+ return;
303
+ // For individual call end, we pass reason to the internal parser
304
+ const res = call.parser.finish({ reason });
305
+ // Determine the mapped coordinator outcome
306
+ let outcome = "invalid";
307
+ if (res.outcome === "valid") {
308
+ outcome = "complete";
309
+ if (call.name === undefined || this.hasCallConflict(call)) {
310
+ outcome = "invalid";
311
+ }
312
+ }
313
+ else if (res.outcome === "truncated") {
314
+ outcome = "truncated";
315
+ }
316
+ else if (res.outcome === "salvaged") {
317
+ outcome = "salvaged";
318
+ }
319
+ if (reason === "cancelled")
320
+ outcome = "cancelled";
321
+ call.status = outcome;
322
+ // Drain remaining parser events
323
+ const parserEvents = call.parser.drainEvents();
324
+ for (const pe of parserEvents) {
325
+ this.eventQueue.push({
326
+ type: "tool_argument_event",
327
+ sequence: this.globalSequence++,
328
+ internalId: call.internalId,
329
+ event: pe,
330
+ });
331
+ }
332
+ // Schema validation is a separate concern from structural
333
+ // prefix-safety: only meaningful once the value is genuinely complete,
334
+ // and only for tools with a registered schema.
335
+ if (outcome === "complete" && call.name !== undefined) {
336
+ const validator = this.toolValidators.get(call.name);
337
+ if (validator) {
338
+ call.schemaValid = validator(res.stableValue) === true;
339
+ if (!call.schemaValid) {
340
+ const errors = (validator.errors ?? [])
341
+ .map((e) => `${e.instancePath || "<root>"} ${e.message ?? ""}`.trim())
342
+ .join("; ");
343
+ this.addDiagnostic({
344
+ code: "E_SCHEMA_VALIDATION_FAILED",
345
+ severity: "error",
346
+ internalId: call.internalId,
347
+ message: `Tool call arguments for "${call.name}" do not match its schema: ${errors || "unknown validation error"}`,
348
+ });
349
+ }
350
+ }
351
+ }
352
+ // Determine executable according to Executable Policy — structural
353
+ // completeness AND (if a schema is registered) schema validity.
354
+ const executable = outcome === "complete" && res.executable && call.schemaValid !== false;
355
+ this.eventQueue.push({
356
+ type: "tool_call_finished",
357
+ sequence: this.globalSequence++,
358
+ internalId: call.internalId,
359
+ outcome,
360
+ executable,
361
+ });
362
+ }
363
+ hasCallConflict(call) {
364
+ return this.diagnostics.some(d => d.internalId === call.internalId && (d.severity === "error" || d.severity === "fatal"));
365
+ }
366
+ handleProviderDiagnostic(event) {
367
+ const internalId = event.callRef ? this.sourceKeyToInternalId.get(event.callRef.sourceKey) : undefined;
368
+ this.addDiagnostic({
369
+ code: event.code,
370
+ severity: event.severity,
371
+ message: event.message,
372
+ internalId,
373
+ });
374
+ // Mirrors handleIdentity()'s existing "mutate call.status mid-stream, not
375
+ // only at finishCall() time" pattern for identity conflicts - this is
376
+ // the same kind of call-scoped fact that can be known before the stream
377
+ // ends and must not wait for it. Gated on "collecting" (first write
378
+ // wins, matching finishCall()'s own `if (call.status !== "collecting")
379
+ // return` guard) so this is a one-way transition: once set, no later
380
+ // event of any kind - including a duplicate of this same diagnostic -
381
+ // can move the call off "sdk_execution_observed". An unattributable
382
+ // diagnostic (no callRef, e.g. a malformed provider event with no
383
+ // correlatable ID) intentionally poisons nothing - there is no specific
384
+ // call to hold ineligible, and guessing one would be worse than leaving
385
+ // it to decide normally.
386
+ if (internalId !== undefined && SDK_EXECUTION_OBSERVED_CODES.has(event.code)) {
387
+ const call = this.calls.get(internalId);
388
+ if (call && call.status === "collecting") {
389
+ call.status = "sdk_execution_observed";
390
+ }
391
+ }
392
+ }
393
+ handleStreamEnd(event) {
394
+ this.isFinished = true;
395
+ // Close all open calls
396
+ for (const call of this.calls.values()) {
397
+ if (call.status === "collecting") {
398
+ if (!call.argumentStreamClosed) {
399
+ this.addDiagnostic({
400
+ code: "E_STREAM_ENDED_WITH_OPEN_CALL",
401
+ severity: "error",
402
+ internalId: call.internalId,
403
+ message: "Stream ended with open call",
404
+ });
405
+ }
406
+ this.finishCall(call, event.reason);
407
+ }
408
+ }
409
+ this.eventQueue.push({
410
+ type: "provider_stream_finished",
411
+ sequence: this.globalSequence++,
412
+ reason: event.reason,
413
+ });
414
+ }
415
+ getCall(internalId) {
416
+ const call = this.calls.get(internalId);
417
+ if (!call) {
418
+ this.addDiagnostic({
419
+ code: "E_TOOL_CALL_NOT_FOUND",
420
+ severity: "error",
421
+ internalId,
422
+ message: `Tool call ${internalId} not found`,
423
+ });
424
+ return undefined;
425
+ }
426
+ return call;
427
+ }
428
+ addDiagnostic(diag) {
429
+ this.diagnostics.push(diag);
430
+ this.eventQueue.push({
431
+ type: "coordinator_diagnostic",
432
+ sequence: this.globalSequence++,
433
+ diagnostic: diag,
434
+ });
435
+ }
436
+ snapshot() {
437
+ return {
438
+ calls: Array.from(this.calls.values()).map((c) => ({
439
+ internalId: c.internalId,
440
+ provider: c.provider,
441
+ toolCallId: c.toolCallId,
442
+ toolIndex: c.toolIndex,
443
+ name: c.name,
444
+ nameComplete: c.nameComplete,
445
+ parser: c.parser.snapshot(),
446
+ status: c.status,
447
+ schemaValid: c.schemaValid,
448
+ })),
449
+ diagnostics: [...this.diagnostics],
450
+ eventsProcessed: this.eventsProcessed,
451
+ isFinished: this.isFinished,
452
+ };
453
+ }
454
+ drainEvents() {
455
+ const events = this.eventQueue;
456
+ this.eventQueue = [];
457
+ return events;
458
+ }
459
+ finish(meta) {
460
+ if (!this.isFinished) {
461
+ this.handleStreamEnd({
462
+ type: "provider_stream_end",
463
+ sequence: this.eventsProcessed + 1,
464
+ provider: "unknown",
465
+ reason: meta?.reason ?? "unknown",
466
+ providerReason: meta?.providerReason,
467
+ });
468
+ }
469
+ return {
470
+ calls: this.snapshot().calls,
471
+ };
472
+ }
473
+ }
474
+ export function createToolCallStreamCoordinator(limits, parserOptions, toolSchemas) {
475
+ return new DefaultToolCallStreamCoordinator(limits, parserOptions, toolSchemas);
476
+ }
477
+ //# sourceMappingURL=coordinator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinator.js","sourceRoot":"","sources":["../../src/coordinator/coordinator.ts"],"names":[],"mappings":"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"}