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
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Emitted (as a stream-wide `provider_diagnostic`, no `callRef`) by a
3
+ * provider adapter when the underlying provider reports that generation was
4
+ * stopped by a content-safety/policy filter, as opposed to a generic
5
+ * cancellation. The execution gate matches on this to return a distinct
6
+ * `reason: "content_filtered"` rather than lumping it in with ordinary
7
+ * incomplete-stream retries - a policy termination should not be retried
8
+ * blindly.
9
+ */
10
+ export declare const CONTENT_FILTERED_DIAGNOSTIC_CODE = "E_CONTENT_FILTERED";
11
+ /**
12
+ * Emitted (as a `provider_diagnostic` carrying the call's own `callRef`) by
13
+ * the AI SDK adapter when a `tool-result` part is observed: direct proof
14
+ * that the Vercel AI SDK's own tool-calling loop already invoked this call's
15
+ * `execute` callback and it returned successfully - independent of, and
16
+ * almost always before, this library's own decision is ever computed. See
17
+ * `SDK_EXECUTION_ERROR_DIAGNOSTIC_CODE` for the failed-attempt counterpart;
18
+ * the coordinator treats both identically (see `coordinator.ts`'s
19
+ * `handleProviderDiagnostic`), poisoning the call to `status:
20
+ * "sdk_execution_observed"` so the gate can never later report `execute` for
21
+ * it - re-running (or, for the error case, retrying) a call the SDK already
22
+ * attempted would risk a second/duplicate invocation of the same
23
+ * irreversible side effect.
24
+ */
25
+ export declare const SDK_EXECUTION_OBSERVED_DIAGNOSTIC_CODE = "E_SDK_EXECUTION_OBSERVED";
26
+ /**
27
+ * Emitted (as a `provider_diagnostic` carrying the call's own `callRef`, when
28
+ * a `callRef` could be determined) by the AI SDK adapter when a `tool-error`
29
+ * part is observed: proof that the Vercel AI SDK's own tool-calling loop
30
+ * already invoked this call's `execute` callback and it threw. This does NOT
31
+ * prove no partial irreversible side effect occurred before the throw, so it
32
+ * receives the exact same fail-closed treatment as
33
+ * `SDK_EXECUTION_OBSERVED_DIAGNOSTIC_CODE` - success and failure are not
34
+ * distinguished into safe/unsafe here, both must fail closed.
35
+ */
36
+ export declare const SDK_EXECUTION_ERROR_DIAGNOSTIC_CODE = "E_PROVIDER_TOOL_ERROR";
37
+ //# sourceMappingURL=diagnostic-codes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostic-codes.d.ts","sourceRoot":"","sources":["../../src/coordinator/diagnostic-codes.ts"],"names":[],"mappings":"AAYA;;;;;;;;GAQG;AACH,eAAO,MAAM,gCAAgC,uBAAuB,CAAC;AAErE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,sCAAsC,6BAA6B,CAAC;AAEjF;;;;;;;;;GASG;AACH,eAAO,MAAM,mCAAmC,0BAA0B,CAAC"}
@@ -0,0 +1,48 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Cross-module coordinator-level diagnostic codes.
3
+ //
4
+ // Most coordinator diagnostics (see coordinator.ts) are inline string
5
+ // literals local to wherever they're raised - there's no central registry,
6
+ // unlike the parser-level `DiagnosticCode` in diagnostics/codes.ts. This
7
+ // file exists only for the handful of codes that a provider adapter raises
8
+ // and something *outside* that adapter (e.g. the execution gate) needs to
9
+ // recognize by exact code, where a shared constant is safer than either
10
+ // module guessing the other's string literal.
11
+ // ---------------------------------------------------------------------------
12
+ /**
13
+ * Emitted (as a stream-wide `provider_diagnostic`, no `callRef`) by a
14
+ * provider adapter when the underlying provider reports that generation was
15
+ * stopped by a content-safety/policy filter, as opposed to a generic
16
+ * cancellation. The execution gate matches on this to return a distinct
17
+ * `reason: "content_filtered"` rather than lumping it in with ordinary
18
+ * incomplete-stream retries - a policy termination should not be retried
19
+ * blindly.
20
+ */
21
+ export const CONTENT_FILTERED_DIAGNOSTIC_CODE = "E_CONTENT_FILTERED";
22
+ /**
23
+ * Emitted (as a `provider_diagnostic` carrying the call's own `callRef`) by
24
+ * the AI SDK adapter when a `tool-result` part is observed: direct proof
25
+ * that the Vercel AI SDK's own tool-calling loop already invoked this call's
26
+ * `execute` callback and it returned successfully - independent of, and
27
+ * almost always before, this library's own decision is ever computed. See
28
+ * `SDK_EXECUTION_ERROR_DIAGNOSTIC_CODE` for the failed-attempt counterpart;
29
+ * the coordinator treats both identically (see `coordinator.ts`'s
30
+ * `handleProviderDiagnostic`), poisoning the call to `status:
31
+ * "sdk_execution_observed"` so the gate can never later report `execute` for
32
+ * it - re-running (or, for the error case, retrying) a call the SDK already
33
+ * attempted would risk a second/duplicate invocation of the same
34
+ * irreversible side effect.
35
+ */
36
+ export const SDK_EXECUTION_OBSERVED_DIAGNOSTIC_CODE = "E_SDK_EXECUTION_OBSERVED";
37
+ /**
38
+ * Emitted (as a `provider_diagnostic` carrying the call's own `callRef`, when
39
+ * a `callRef` could be determined) by the AI SDK adapter when a `tool-error`
40
+ * part is observed: proof that the Vercel AI SDK's own tool-calling loop
41
+ * already invoked this call's `execute` callback and it threw. This does NOT
42
+ * prove no partial irreversible side effect occurred before the throw, so it
43
+ * receives the exact same fail-closed treatment as
44
+ * `SDK_EXECUTION_OBSERVED_DIAGNOSTIC_CODE` - success and failure are not
45
+ * distinguished into safe/unsafe here, both must fail closed.
46
+ */
47
+ export const SDK_EXECUTION_ERROR_DIAGNOSTIC_CODE = "E_PROVIDER_TOOL_ERROR";
48
+ //# sourceMappingURL=diagnostic-codes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostic-codes.js","sourceRoot":"","sources":["../../src/coordinator/diagnostic-codes.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,mDAAmD;AACnD,EAAE;AACF,sEAAsE;AACtE,2EAA2E;AAC3E,yEAAyE;AACzE,2EAA2E;AAC3E,0EAA0E;AAC1E,wEAAwE;AACxE,8CAA8C;AAC9C,8EAA8E;AAE9E;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAG,oBAAoB,CAAC;AAErE;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,sCAAsC,GAAG,0BAA0B,CAAC;AAEjF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAG,uBAAuB,CAAC"}
@@ -0,0 +1,62 @@
1
+ import type { StreamEndReason } from "../types.js";
2
+ export type { StreamEndReason };
3
+ export type ProviderName = "openai" | "anthropic" | "gemini" | "openrouter" | "openai-compatible" | "ai-sdk" | "unknown";
4
+ export interface NormalizedEventBase {
5
+ /**
6
+ * Deterministic sequence number assigned by the stream coordinator.
7
+ */
8
+ readonly sequence: number;
9
+ readonly provider: ProviderName;
10
+ readonly rawEventType?: string;
11
+ readonly providerRequestId?: string;
12
+ }
13
+ export type NormalizedToolStreamEvent = ToolCallStartEvent | ToolCallIdentityEvent | ToolCallNameDeltaEvent | ToolCallArgumentsDeltaEvent | ToolCallEndEvent | ProviderDiagnosticEvent | ProviderStreamEndEvent;
14
+ export interface ToolCallStartEvent extends NormalizedEventBase {
15
+ readonly type: "tool_call_start";
16
+ readonly callRef: ProviderCallRef;
17
+ readonly toolCallId?: string;
18
+ readonly toolIndex?: number;
19
+ readonly name?: string;
20
+ }
21
+ export interface ToolCallIdentityEvent extends NormalizedEventBase {
22
+ readonly type: "tool_call_identity";
23
+ readonly callRef: ProviderCallRef;
24
+ readonly toolCallId?: string;
25
+ readonly toolIndex?: number;
26
+ }
27
+ export interface ToolCallNameDeltaEvent extends NormalizedEventBase {
28
+ readonly type: "tool_call_name_delta";
29
+ readonly callRef: ProviderCallRef;
30
+ readonly delta: string;
31
+ }
32
+ export interface ToolCallArgumentsDeltaEvent extends NormalizedEventBase {
33
+ readonly type: "tool_call_arguments_delta";
34
+ readonly callRef: ProviderCallRef;
35
+ readonly delta: string | Uint8Array;
36
+ }
37
+ export interface ToolCallEndEvent extends NormalizedEventBase {
38
+ readonly type: "tool_call_end";
39
+ readonly callRef: ProviderCallRef;
40
+ readonly reason: StreamEndReason;
41
+ readonly providerReason?: string;
42
+ }
43
+ export interface ProviderDiagnosticEvent extends NormalizedEventBase {
44
+ readonly type: "provider_diagnostic";
45
+ readonly code: string;
46
+ readonly severity: "info" | "warning" | "error" | "fatal";
47
+ readonly message: string;
48
+ readonly callRef?: ProviderCallRef;
49
+ }
50
+ export interface ProviderStreamEndEvent extends NormalizedEventBase {
51
+ readonly type: "provider_stream_end";
52
+ readonly reason: StreamEndReason;
53
+ readonly providerReason?: string;
54
+ }
55
+ export interface ProviderCallRef {
56
+ /**
57
+ * Deterministic provider-local identity.
58
+ * e.g. "content-block:0"
59
+ */
60
+ readonly sourceKey: string;
61
+ }
62
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/coordinator/protocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,YAAY,EAAE,eAAe,EAAE,CAAC;AAEhC,MAAM,MAAM,YAAY,GACpB,QAAQ,GACR,WAAW,GACX,QAAQ,GACR,YAAY,GACZ,mBAAmB,GACnB,QAAQ,GACR,SAAS,CAAC;AAEd,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CACrC;AAED,MAAM,MAAM,yBAAyB,GACjC,kBAAkB,GAClB,qBAAqB,GACrB,sBAAsB,GACtB,2BAA2B,GAC3B,gBAAgB,GAChB,uBAAuB,GACvB,sBAAsB,CAAC;AAE3B,MAAM,WAAW,kBAAmB,SAAQ,mBAAmB;IAC7D,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAElC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,qBAAsB,SAAQ,mBAAmB;IAChE,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAElC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,sBAAuB,SAAQ,mBAAmB;IACjE,QAAQ,CAAC,IAAI,EAAE,sBAAsB,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,2BAA4B,SAAQ,mBAAmB;IACtE,QAAQ,CAAC,IAAI,EAAE,2BAA2B,CAAC;IAC3C,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAAC;CACrC;AAED,MAAM,WAAW,gBAAiB,SAAQ,mBAAmB;IAC3D,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,uBAAwB,SAAQ,mBAAmB;IAClE,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;IAC1D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,eAAe,CAAC;CACpC;AAED,MAAM,WAAW,sBAAuB,SAAQ,mBAAmB;IACjE,QAAQ,CAAC,IAAI,EAAE,qBAAqB,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/coordinator/protocol.ts"],"names":[],"mappings":""}
@@ -0,0 +1,104 @@
1
+ import { ParserSnapshot, ParserEvent } from "../types.js";
2
+ import { NormalizedToolStreamEvent, ProviderName, StreamEndReason } from "./protocol.js";
3
+ export interface CoordinatorLimits {
4
+ readonly maxToolCalls: number;
5
+ readonly maxToolNameBytes: number;
6
+ readonly maxTrailingDataBytes: number;
7
+ readonly maxNormalizedEvents: number;
8
+ }
9
+ export declare const DEFAULT_COORDINATOR_LIMITS: CoordinatorLimits;
10
+ export interface ToolCallState {
11
+ readonly internalId: string;
12
+ readonly provider: ProviderName;
13
+ readonly toolCallId?: string;
14
+ readonly toolIndex?: number;
15
+ readonly name?: string;
16
+ readonly nameComplete: boolean;
17
+ readonly parser: ParserSnapshot;
18
+ readonly status: "collecting" | "complete" | "truncated" | "salvaged" | "invalid" | "cancelled" | "sdk_execution_observed";
19
+ /**
20
+ * Result of validating `parser.stableValue` against the JSON Schema
21
+ * registered for this call's tool name (see `toolSchemas` on
22
+ * `createToolCallStreamCoordinator`). `undefined` when no schema was
23
+ * registered for this tool, or the call never reached a "complete"
24
+ * outcome (there's nothing meaningful to validate). This is a *separate*
25
+ * concern from `parser.executable` — that flag means "the data is
26
+ * structurally complete and wasn't fabricated by truncation"; this one
27
+ * means "the data matches the shape the tool declared it needs." Both
28
+ * must hold for the coordinator's own `executable` (on the
29
+ * `tool_call_finished` event) to be true.
30
+ */
31
+ readonly schemaValid?: boolean;
32
+ }
33
+ /**
34
+ * A JSON Schema object (draft-07, matching ajv's default). Kept as `object`
35
+ * rather than a specific type-checked shape so callers can pass whatever
36
+ * JSON Schema library/types they already have without a forced dependency
37
+ * on this package's own schema typings.
38
+ */
39
+ export type JsonSchemaLike = object;
40
+ export interface ToolCallCoordinatorSnapshot {
41
+ readonly calls: readonly ToolCallState[];
42
+ readonly diagnostics: readonly CoordinatorDiagnostic[];
43
+ readonly eventsProcessed: number;
44
+ readonly isFinished: boolean;
45
+ }
46
+ export type ToolCallCoordinatorEvent = {
47
+ readonly type: "tool_call_discovered";
48
+ readonly sequence: number;
49
+ readonly internalId: string;
50
+ readonly provider: ProviderName;
51
+ } | {
52
+ readonly type: "tool_call_identity_updated";
53
+ readonly sequence: number;
54
+ readonly internalId: string;
55
+ readonly toolCallId?: string;
56
+ readonly toolIndex?: number;
57
+ } | {
58
+ readonly type: "tool_name_updated";
59
+ readonly sequence: number;
60
+ readonly internalId: string;
61
+ readonly name: string;
62
+ readonly complete: boolean;
63
+ } | {
64
+ readonly type: "tool_argument_event";
65
+ readonly sequence: number;
66
+ readonly internalId: string;
67
+ readonly event: ParserEvent;
68
+ } | {
69
+ readonly type: "tool_call_finished";
70
+ readonly sequence: number;
71
+ readonly internalId: string;
72
+ readonly outcome: "complete" | "truncated" | "salvaged" | "invalid" | "cancelled";
73
+ readonly executable: boolean;
74
+ } | {
75
+ readonly type: "coordinator_diagnostic";
76
+ readonly sequence: number;
77
+ readonly diagnostic: CoordinatorDiagnostic;
78
+ } | {
79
+ readonly type: "provider_stream_finished";
80
+ readonly sequence: number;
81
+ readonly reason: StreamEndReason;
82
+ };
83
+ export interface CoordinatorDiagnostic {
84
+ readonly code: string;
85
+ readonly severity: "info" | "warning" | "error" | "fatal";
86
+ readonly message: string;
87
+ readonly internalId?: string;
88
+ }
89
+ export interface CoordinatorPushResult {
90
+ readonly accepted: boolean;
91
+ }
92
+ export interface ToolCallCoordinatorFinalResult {
93
+ readonly calls: readonly ToolCallState[];
94
+ }
95
+ export interface ToolCallStreamCoordinator {
96
+ push(event: NormalizedToolStreamEvent): CoordinatorPushResult;
97
+ snapshot(): ToolCallCoordinatorSnapshot;
98
+ drainEvents(): readonly ToolCallCoordinatorEvent[];
99
+ finish(meta?: {
100
+ reason?: StreamEndReason;
101
+ providerReason?: string;
102
+ }): ToolCallCoordinatorFinalResult;
103
+ }
104
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/coordinator/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export const DEFAULT_COORDINATOR_LIMITS = {
2
+ maxToolCalls: 128,
3
+ maxToolNameBytes: 1024,
4
+ maxTrailingDataBytes: 65536,
5
+ maxNormalizedEvents: 100000,
6
+ };
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/coordinator/types.ts"],"names":[],"mappings":"AAUA,MAAM,CAAC,MAAM,0BAA0B,GAAsB;IAC3D,YAAY,EAAE,GAAG;IACjB,gBAAgB,EAAE,IAAI;IACtB,oBAAoB,EAAE,KAAK;IAC3B,mBAAmB,EAAE,MAAM;CAC5B,CAAC"}
@@ -0,0 +1,24 @@
1
+ /** All known diagnostic codes. */
2
+ export declare const DiagnosticCode: {
3
+ readonly E_UNEXPECTED_TOKEN: "E_UNEXPECTED_TOKEN";
4
+ readonly E_DUPLICATE_KEY: "E_DUPLICATE_KEY";
5
+ readonly E_INCOMPLETE_UTF8: "E_INCOMPLETE_UTF8";
6
+ readonly E_INVALID_UTF8: "E_INVALID_UTF8";
7
+ readonly E_INCOMPLETE_UNICODE_ESCAPE: "E_INCOMPLETE_UNICODE_ESCAPE";
8
+ readonly E_INVALID_UNICODE_ESCAPE: "E_INVALID_UNICODE_ESCAPE";
9
+ readonly E_UNPAIRED_SURROGATE: "E_UNPAIRED_SURROGATE";
10
+ readonly E_UNTERMINATED_STRING: "E_UNTERMINATED_STRING";
11
+ readonly E_INCOMPLETE_NUMBER: "E_INCOMPLETE_NUMBER";
12
+ readonly E_INCOMPLETE_LITERAL: "E_INCOMPLETE_LITERAL";
13
+ readonly E_TRAILING_DATA: "E_TRAILING_DATA";
14
+ readonly E_STREAM_TRUNCATED: "E_STREAM_TRUNCATED";
15
+ readonly E_LIMIT_DEPTH: "E_LIMIT_DEPTH";
16
+ readonly E_LIMIT_INPUT_BYTES: "E_LIMIT_INPUT_BYTES";
17
+ readonly E_LIMIT_STRING_BYTES: "E_LIMIT_STRING_BYTES";
18
+ readonly E_LIMIT_EVENT_QUEUE: "E_LIMIT_EVENT_QUEUE";
19
+ readonly E_PUSH_AFTER_FINISH: "E_PUSH_AFTER_FINISH";
20
+ readonly W_RAW_CONTROL_CHARACTER: "W_RAW_CONTROL_CHARACTER";
21
+ readonly W_TRAILING_TEXT_ISOLATED: "W_TRAILING_TEXT_ISOLATED";
22
+ };
23
+ export type DiagnosticCodeValue = (typeof DiagnosticCode)[keyof typeof DiagnosticCode];
24
+ //# sourceMappingURL=codes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codes.d.ts","sourceRoot":"","sources":["../../src/diagnostics/codes.ts"],"names":[],"mappings":"AAIA,kCAAkC;AAClC,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;CAuBjB,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAC7B,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,OAAO,cAAc,CAAC,CAAC"}
@@ -0,0 +1,28 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Diagnostic codes
3
+ // ---------------------------------------------------------------------------
4
+ /** All known diagnostic codes. */
5
+ export const DiagnosticCode = {
6
+ // --- Errors ---
7
+ E_UNEXPECTED_TOKEN: "E_UNEXPECTED_TOKEN",
8
+ E_DUPLICATE_KEY: "E_DUPLICATE_KEY",
9
+ E_INCOMPLETE_UTF8: "E_INCOMPLETE_UTF8",
10
+ E_INVALID_UTF8: "E_INVALID_UTF8",
11
+ E_INCOMPLETE_UNICODE_ESCAPE: "E_INCOMPLETE_UNICODE_ESCAPE",
12
+ E_INVALID_UNICODE_ESCAPE: "E_INVALID_UNICODE_ESCAPE",
13
+ E_UNPAIRED_SURROGATE: "E_UNPAIRED_SURROGATE",
14
+ E_UNTERMINATED_STRING: "E_UNTERMINATED_STRING",
15
+ E_INCOMPLETE_NUMBER: "E_INCOMPLETE_NUMBER",
16
+ E_INCOMPLETE_LITERAL: "E_INCOMPLETE_LITERAL",
17
+ E_TRAILING_DATA: "E_TRAILING_DATA",
18
+ E_STREAM_TRUNCATED: "E_STREAM_TRUNCATED",
19
+ E_LIMIT_DEPTH: "E_LIMIT_DEPTH",
20
+ E_LIMIT_INPUT_BYTES: "E_LIMIT_INPUT_BYTES",
21
+ E_LIMIT_STRING_BYTES: "E_LIMIT_STRING_BYTES",
22
+ E_LIMIT_EVENT_QUEUE: "E_LIMIT_EVENT_QUEUE",
23
+ E_PUSH_AFTER_FINISH: "E_PUSH_AFTER_FINISH",
24
+ // --- Warnings ---
25
+ W_RAW_CONTROL_CHARACTER: "W_RAW_CONTROL_CHARACTER",
26
+ W_TRAILING_TEXT_ISOLATED: "W_TRAILING_TEXT_ISOLATED",
27
+ };
28
+ //# sourceMappingURL=codes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codes.js","sourceRoot":"","sources":["../../src/diagnostics/codes.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E,kCAAkC;AAClC,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,iBAAiB;IACjB,kBAAkB,EAAE,oBAAoB;IACxC,eAAe,EAAE,iBAAiB;IAClC,iBAAiB,EAAE,mBAAmB;IACtC,cAAc,EAAE,gBAAgB;IAChC,2BAA2B,EAAE,6BAA6B;IAC1D,wBAAwB,EAAE,0BAA0B;IACpD,oBAAoB,EAAE,sBAAsB;IAC5C,qBAAqB,EAAE,uBAAuB;IAC9C,mBAAmB,EAAE,qBAAqB;IAC1C,oBAAoB,EAAE,sBAAsB;IAC5C,eAAe,EAAE,iBAAiB;IAClC,kBAAkB,EAAE,oBAAoB;IACxC,aAAa,EAAE,eAAe;IAC9B,mBAAmB,EAAE,qBAAqB;IAC1C,oBAAoB,EAAE,sBAAsB;IAC5C,mBAAmB,EAAE,qBAAqB;IAC1C,mBAAmB,EAAE,qBAAqB;IAE1C,mBAAmB;IACnB,uBAAuB,EAAE,yBAAyB;IAClD,wBAAwB,EAAE,0BAA0B;CAC5C,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { Diagnostic } from "../types.js";
2
+ type Severity = Diagnostic["severity"];
3
+ /**
4
+ * Creates a Diagnostic object.
5
+ */
6
+ export declare function createDiagnostic(code: string, severity: Severity, byteOffset: number, message: string, recoverable: boolean, path?: string): Diagnostic;
7
+ export {};
8
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/diagnostics/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,KAAK,QAAQ,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;AAEvC;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,OAAO,EACpB,IAAI,CAAC,EAAE,MAAM,GACZ,UAAU,CAYZ"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Creates a Diagnostic object.
3
+ */
4
+ export function createDiagnostic(code, severity, byteOffset, message, recoverable, path) {
5
+ const diag = {
6
+ code,
7
+ severity,
8
+ byteOffset,
9
+ message,
10
+ recoverable,
11
+ };
12
+ if (path !== undefined) {
13
+ diag.path = path;
14
+ }
15
+ return diag;
16
+ }
17
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/diagnostics/factory.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,QAAkB,EAClB,UAAkB,EAClB,OAAe,EACf,WAAoB,EACpB,IAAa;IAEb,MAAM,IAAI,GAAe;QACvB,IAAI;QACJ,QAAQ;QACR,UAAU;QACV,OAAO;QACP,WAAW;KACZ,CAAC;IACF,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { CoordinatorDiagnostic, ToolCallState } from "../coordinator/types.js";
2
+ import { StreamEndReason } from "../coordinator/protocol.js";
3
+ import { ExecuteDecision, NonExecutableDecision } from "./types.js";
4
+ export interface DecisionContext {
5
+ /**
6
+ * The stream-level end reason - what actually happened to the underlying
7
+ * provider stream, not any single call's own (possibly still-"collecting")
8
+ * status. Stream-wide fail-closed conditions (provider_error) key off this
9
+ * rather than per-call state.
10
+ */
11
+ readonly streamEndReason: StreamEndReason;
12
+ /**
13
+ * The provider's own pre-normalization reason string for the stream-end
14
+ * event, when one was given (`ProviderStreamEndEvent.providerReason`).
15
+ * Observability only, mirrored onto `DecisionEvidence.providerReason` -
16
+ * never consulted by the decision logic itself.
17
+ */
18
+ readonly streamEndProviderReason?: string;
19
+ /**
20
+ * The coordinator's full, unfiltered diagnostics list (`snapshot().diagnostics`).
21
+ * `decideExecution` splits this into per-call (`internalId` matches) and
22
+ * global (`internalId` undefined) subsets itself.
23
+ */
24
+ readonly diagnostics: readonly CoordinatorDiagnostic[];
25
+ }
26
+ export declare function decideExecution(call: ToolCallState, ctx: DecisionContext): ExecuteDecision | NonExecutableDecision;
27
+ //# sourceMappingURL=decide.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decide.d.ts","sourceRoot":"","sources":["../../src/gate/decide.ts"],"names":[],"mappings":"AA8BA,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAM7D,OAAO,EAAoB,eAAe,EAAmB,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEvG,MAAM,WAAW,eAAe;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAE1C;;;;;OAKG;IACH,QAAQ,CAAC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IAE1C;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,SAAS,qBAAqB,EAAE,CAAC;CACxD;AAoBD,wBAAgB,eAAe,CAC7B,IAAI,EAAE,aAAa,EACnB,GAAG,EAAE,eAAe,GACnB,eAAe,GAAG,qBAAqB,CA4JzC"}
@@ -0,0 +1,179 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Pure execution-decision mapping.
3
+ //
4
+ // Deliberately a standalone function (no coordinator/adapter dependency) so
5
+ // the entire decision table can be unit-tested directly against hand-built
6
+ // ToolCallState fixtures, without spinning up a full push()/finish()
7
+ // pipeline for every row of the table.
8
+ //
9
+ // Priority order matters and is intentional. SDK-execution-ownership
10
+ // evidence (attributed to this call, or stream-wide/unattributable) is
11
+ // checked FIRST, before every other disqualifier - it is a statement that
12
+ // execution authority already left this library's hands, categorically
13
+ // different from every other check below, which are all statements about
14
+ // the ARGUMENTS/STREAM being unusable. A caller's higher-level logic might
15
+ // reasonably retry a whole request on resource_limit/provider_error/
16
+ // content_filtered; retrying is never safe once SDK execution was observed,
17
+ // since a fresh generation could trigger the SDK's own execute() again for
18
+ // whatever already (partially) ran. That distinction would be lost if a
19
+ // data-quality reason could mask it, so it always wins regardless of what
20
+ // else is also true about the call. Every other fail-closed disqualifier
21
+ // (resource limits, provider errors, content-policy terminations, schema
22
+ // mismatches, malformed content, positively-observed truncation) is then
23
+ // checked before the single positive "execute" branch. "execute" is reached
24
+ // only once nothing above has disqualified the call - it is the last
25
+ // positive case, never the first check made, so a future status value that
26
+ // happens to superficially resemble "complete" still can't skip the checks
27
+ // ahead of it.
28
+ // ---------------------------------------------------------------------------
29
+ import { DiagnosticCode } from "../diagnostics/codes.js";
30
+ import { CONTENT_FILTERED_DIAGNOSTIC_CODE, SDK_EXECUTION_OBSERVED_DIAGNOSTIC_CODE, SDK_EXECUTION_ERROR_DIAGNOSTIC_CODE, } from "../coordinator/diagnostic-codes.js";
31
+ const PARSER_RESOURCE_LIMIT_CODES = new Set([
32
+ DiagnosticCode.E_LIMIT_DEPTH,
33
+ DiagnosticCode.E_LIMIT_INPUT_BYTES,
34
+ DiagnosticCode.E_LIMIT_STRING_BYTES,
35
+ DiagnosticCode.E_LIMIT_EVENT_QUEUE,
36
+ ]);
37
+ const COORDINATOR_RESOURCE_LIMIT_CODES = new Set([
38
+ "E_COORDINATOR_LIMIT_CALLS",
39
+ "E_COORDINATOR_LIMIT_EVENTS",
40
+ "E_TOOL_NAME_LIMIT",
41
+ ]);
42
+ const SDK_EXECUTION_OBSERVED_CODES = new Set([
43
+ SDK_EXECUTION_OBSERVED_DIAGNOSTIC_CODE,
44
+ SDK_EXECUTION_ERROR_DIAGNOSTIC_CODE,
45
+ ]);
46
+ export function decideExecution(call, ctx) {
47
+ const parserDiagnostics = call.parser.diagnostics;
48
+ const callCoordinatorDiagnostics = ctx.diagnostics.filter((d) => d.internalId === call.internalId);
49
+ const globalCoordinatorDiagnostics = ctx.diagnostics.filter((d) => d.internalId === undefined);
50
+ const coordinatorDiagnostics = [
51
+ ...globalCoordinatorDiagnostics,
52
+ ...callCoordinatorDiagnostics,
53
+ ];
54
+ const evidence = {
55
+ provider: call.provider,
56
+ providerReason: ctx.streamEndProviderReason,
57
+ streamEndReason: ctx.streamEndReason,
58
+ terminalConfirmed: ctx.streamEndReason !== "unknown",
59
+ structurallyComplete: call.parser.rootComplete,
60
+ parserExecutable: call.parser.executable,
61
+ schemaValid: call.schemaValid,
62
+ receivedBytes: call.parser.receivedBytes,
63
+ };
64
+ const common = {
65
+ internalId: call.internalId,
66
+ toolCallId: call.toolCallId,
67
+ toolIndex: call.toolIndex,
68
+ name: call.name,
69
+ stableValue: call.parser.stableValue,
70
+ parserDiagnostics,
71
+ coordinatorDiagnostics,
72
+ evidence,
73
+ };
74
+ function reject(reason) {
75
+ return { ...common, action: "reject", executable: false, reason };
76
+ }
77
+ function retry(reason) {
78
+ return { ...common, action: "retry", executable: false, reason };
79
+ }
80
+ // --- SDK execution ownership (highest priority - see file header) -------
81
+ // Two evidence shapes, identical outcome:
82
+ // - attributed: `call.status` was poisoned the moment the coordinator
83
+ // resolved a tool-result/tool-error to this exact call - see
84
+ // DefaultToolCallStreamCoordinator.handleProviderDiagnostic. One-way,
85
+ // call-scoped.
86
+ // - unattributable: a tool-result/tool-error arrived with no resolvable
87
+ // call identity at all, recorded as a stream-wide diagnostic
88
+ // (`internalId: undefined`) instead of guessing which call it meant.
89
+ // With no way to rule any call in this stream out - including one
90
+ // whose `tool_call_start` arrives after this point - as the one the
91
+ // SDK already executed, EVERY call decided against this same
92
+ // `ctx.diagnostics` list must fail closed, not just the one that
93
+ // happens to look safest. `globalCoordinatorDiagnostics` is re-derived
94
+ // fresh from the full, append-only diagnostics list on every call to
95
+ // this function, so this is automatic for calls that exist now and
96
+ // calls the coordinator hasn't created yet.
97
+ if (call.status === "sdk_execution_observed" ||
98
+ globalCoordinatorDiagnostics.some((d) => SDK_EXECUTION_OBSERVED_CODES.has(d.code))) {
99
+ return reject("sdk_execution_observed");
100
+ }
101
+ // --- Universal fail-closed checks ---------------------------------------
102
+ // Evaluated first and unconditionally, regardless of call.status, so a
103
+ // resource limit, a provider-side failure, or a content-policy
104
+ // termination always wins over whatever the structural status looks like.
105
+ const hasResourceLimit = parserDiagnostics.some((d) => PARSER_RESOURCE_LIMIT_CODES.has(d.code)) ||
106
+ callCoordinatorDiagnostics.some((d) => COORDINATOR_RESOURCE_LIMIT_CODES.has(d.code)) ||
107
+ globalCoordinatorDiagnostics.some((d) => d.code === "E_COORDINATOR_LIMIT_EVENTS");
108
+ if (hasResourceLimit) {
109
+ return reject("resource_limit");
110
+ }
111
+ if (ctx.streamEndReason === "provider_error") {
112
+ return reject("provider_error");
113
+ }
114
+ const isContentFiltered = globalCoordinatorDiagnostics.some((d) => d.code === CONTENT_FILTERED_DIAGNOSTIC_CODE);
115
+ if (isContentFiltered) {
116
+ return reject("content_filtered");
117
+ }
118
+ // --- Status-specific handling --------------------------------------------
119
+ // Exhaustive over ToolCallState["status"] with no `default`: if a future
120
+ // coordinator version adds a new status literal without a matching case
121
+ // here, `noImplicitReturns` fails the build - not a silent runtime gap.
122
+ // "sdk_execution_observed" has no case here at all: the check above
123
+ // already returned for it, and TypeScript's own control-flow narrowing
124
+ // has removed that literal from `call.status`'s type by this point - the
125
+ // compiler itself now rejects a case for it as unreachable, a stronger
126
+ // guarantee than a runtime-only "this shouldn't happen" comment could give.
127
+ switch (call.status) {
128
+ case "complete": {
129
+ if (call.schemaValid === false) {
130
+ return reject("schema_invalid");
131
+ }
132
+ // The ONLY positive branch in this entire function, reached only
133
+ // after every disqualifying check above has already passed. The
134
+ // `call.name !== undefined` check is defensive/redundant with the
135
+ // coordinator's own invariant (a call only reaches status "complete"
136
+ // when its name is known) - narrowing on it here is what lets
137
+ // `ExecuteDecision.name` be typed as a required `string` instead of
138
+ // `string | undefined`, so it never needs re-checking at every call
139
+ // site. If the invariant were ever violated, this still fails closed
140
+ // to "stream_incomplete" rather than fabricating a name.
141
+ if (call.parser.executable === true &&
142
+ call.parser.stableValue !== undefined &&
143
+ call.name !== undefined) {
144
+ const decision = {
145
+ ...common,
146
+ name: call.name,
147
+ action: "execute",
148
+ executable: true,
149
+ reason: "complete",
150
+ value: call.parser.stableValue,
151
+ };
152
+ return decision;
153
+ }
154
+ // Root closed, syntactically valid, but not trusted: the parser's
155
+ // own executable contract failed it (stream-end-reason mismatch or
156
+ // trailing data), even though nothing here required a repair.
157
+ return retry("stream_incomplete");
158
+ }
159
+ case "truncated":
160
+ // The parser positively observed an open string/number/literal or an
161
+ // unclosed container - a real, raw mid-value cut, not a matter of
162
+ // interpretation.
163
+ return retry("truncated");
164
+ case "invalid":
165
+ // Duplicate key, unexpected token, or a missing/conflicting tool
166
+ // identity - a genuine content defect, independent of how the stream
167
+ // ended.
168
+ return reject("malformed");
169
+ case "salvaged":
170
+ // Root only closed via a safe-container-closing repair; the JSON
171
+ // *looks* complete, but provider metadata never confirmed genuine
172
+ // completion. This is the container-level truncation case.
173
+ return retry("stream_incomplete");
174
+ case "cancelled":
175
+ case "collecting":
176
+ return retry("stream_incomplete");
177
+ }
178
+ }
179
+ //# sourceMappingURL=decide.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decide.js","sourceRoot":"","sources":["../../src/gate/decide.ts"],"names":[],"mappings":"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"}