theorum 1.0.0 → 1.1.3

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 (204) hide show
  1. package/README.md +81 -25
  2. package/esm/mod.d.ts +48 -29
  3. package/esm/mod.js +37 -24
  4. package/esm/src/cli/commands/bench.js +13 -16
  5. package/esm/src/cli/commands/fuzz-canary.js +25 -29
  6. package/esm/src/cli/commands/guardrails-eval.d.ts +14 -0
  7. package/esm/src/cli/commands/guardrails-eval.js +15 -0
  8. package/esm/src/cli/commands/profile.js +12 -3
  9. package/esm/src/cli/commands/run.js +8 -9
  10. package/esm/src/cli/commands/test.js +8 -8
  11. package/esm/src/cli/event-log.d.ts +1 -1
  12. package/esm/src/cli/index.js +12 -0
  13. package/esm/src/cli/matrix/synthesizer.d.ts +6 -6
  14. package/esm/src/cli/matrix/synthesizer.js +23 -22
  15. package/esm/src/guardrails/canary-gate.d.ts +2 -1
  16. package/esm/src/guardrails/canary-gate.js +2 -1
  17. package/esm/src/guardrails/canary.d.ts +9 -1
  18. package/esm/src/guardrails/canary.js +21 -10
  19. package/esm/src/guardrails/corpus/canary-egress-attacks.d.ts +1 -0
  20. package/esm/src/guardrails/corpus/fuzz-inbound.js +12 -15
  21. package/esm/src/guardrails/corpus/inbound-payloads.js +1 -0
  22. package/esm/src/guardrails/corpus/live-attacks.js +0 -1
  23. package/esm/src/guardrails/corpus/mod.d.ts +1 -0
  24. package/esm/src/guardrails/corpus/secrets.d.ts +1 -0
  25. package/esm/src/guardrails/corpus/secrets.js +1 -0
  26. package/esm/src/guardrails/corpus/strings.d.ts +1 -0
  27. package/esm/src/guardrails/corpus/strings.js +1 -0
  28. package/esm/src/guardrails/corpus/types.d.ts +1 -0
  29. package/esm/src/guardrails/egress.d.ts +26 -3
  30. package/esm/src/guardrails/egress.js +69 -18
  31. package/esm/src/guardrails/error.d.ts +14 -23
  32. package/esm/src/guardrails/error.js +86 -77
  33. package/esm/src/guardrails/eval/corpus.d.ts +108 -0
  34. package/esm/src/guardrails/eval/corpus.js +978 -0
  35. package/esm/src/guardrails/eval/mod.d.ts +51 -0
  36. package/esm/src/guardrails/eval/mod.js +133 -0
  37. package/esm/src/guardrails/eval/score.d.ts +66 -0
  38. package/esm/src/guardrails/eval/score.js +114 -0
  39. package/esm/src/guardrails/events.d.ts +25 -0
  40. package/esm/src/guardrails/events.js +56 -0
  41. package/esm/src/guardrails/hits.d.ts +24 -0
  42. package/esm/src/guardrails/hits.js +45 -0
  43. package/esm/src/guardrails/lexicon.d.ts +39 -0
  44. package/esm/src/guardrails/lexicon.js +200 -0
  45. package/esm/src/guardrails/live-outbound-gate.d.ts +15 -13
  46. package/esm/src/guardrails/live-outbound-gate.js +131 -89
  47. package/esm/src/guardrails/mod.d.ts +19 -4
  48. package/esm/src/guardrails/mod.js +12 -3
  49. package/esm/src/guardrails/network.d.ts +19 -0
  50. package/esm/src/guardrails/network.js +234 -0
  51. package/esm/src/guardrails/policy.d.ts +35 -0
  52. package/esm/src/guardrails/policy.js +50 -0
  53. package/esm/src/guardrails/progressive-yield.d.ts +51 -0
  54. package/esm/src/guardrails/progressive-yield.js +98 -0
  55. package/esm/src/guardrails/quota.d.ts +17 -3
  56. package/esm/src/guardrails/quota.js +18 -4
  57. package/esm/src/guardrails/sanitize.d.ts +36 -6
  58. package/esm/src/guardrails/sanitize.js +152 -60
  59. package/esm/src/guardrails/serialize.d.ts +35 -0
  60. package/esm/src/guardrails/serialize.js +58 -0
  61. package/esm/src/guardrails/testing.d.ts +7 -0
  62. package/esm/src/guardrails/testing.js +4 -0
  63. package/esm/src/guardrails/theorum-error.d.ts +12 -0
  64. package/esm/src/guardrails/theorum-error.js +15 -0
  65. package/esm/src/guardrails/tool-directives.d.ts +48 -0
  66. package/esm/src/guardrails/tool-directives.js +124 -0
  67. package/esm/src/guardrails/tool-result.d.ts +93 -0
  68. package/esm/src/guardrails/tool-result.js +276 -0
  69. package/esm/src/guardrails/types.d.ts +291 -0
  70. package/esm/src/guardrails/types.js +72 -0
  71. package/esm/src/host/client-turn.js +4 -0
  72. package/esm/src/host/mint-trace.d.ts +1 -1
  73. package/esm/src/kernel/auth/crypto.d.ts +42 -0
  74. package/esm/src/kernel/auth/crypto.js +106 -0
  75. package/esm/src/kernel/auth/mod.d.ts +11 -0
  76. package/esm/src/kernel/auth/mod.js +11 -0
  77. package/esm/src/kernel/auth/oauth.d.ts +47 -0
  78. package/esm/src/kernel/auth/oauth.js +278 -0
  79. package/esm/src/kernel/auth/types.d.ts +133 -0
  80. package/esm/src/kernel/auth/types.js +13 -0
  81. package/esm/src/kernel/engine/delta.js +43 -2
  82. package/esm/src/kernel/engine/live-inbound.d.ts +15 -3
  83. package/esm/src/kernel/engine/live-inbound.js +22 -8
  84. package/esm/src/kernel/engine/live-ingress.d.ts +19 -0
  85. package/esm/src/kernel/engine/live-ingress.js +47 -0
  86. package/esm/src/kernel/engine/repair.js +13 -12
  87. package/esm/src/kernel/engine/runner/gates.js +127 -40
  88. package/esm/src/kernel/engine/runner/mod.d.ts +6 -4
  89. package/esm/src/kernel/engine/runner/mod.js +182 -43
  90. package/esm/src/kernel/engine/runner/schema-validation.js +3 -3
  91. package/esm/src/kernel/engine/runner/stages.d.ts +39 -0
  92. package/esm/src/kernel/engine/runner/stages.js +89 -0
  93. package/esm/src/kernel/engine/runner/state.d.ts +24 -0
  94. package/esm/src/kernel/engine/runner/steps.js +128 -61
  95. package/esm/src/kernel/engine/runner/stream.d.ts +9 -2
  96. package/esm/src/kernel/engine/runner/stream.js +114 -55
  97. package/esm/src/kernel/engine/session/mod.d.ts +3 -1
  98. package/esm/src/kernel/engine/session/mod.js +386 -34
  99. package/esm/src/kernel/interaction-parts.d.ts +14 -0
  100. package/esm/src/kernel/interaction-parts.js +23 -0
  101. package/esm/src/kernel/mod.d.ts +19 -7
  102. package/esm/src/kernel/mod.js +10 -5
  103. package/esm/src/kernel/profile-graph.d.ts +159 -0
  104. package/esm/src/kernel/profile-graph.js +156 -0
  105. package/esm/src/kernel/registry/attachments.d.ts +10 -10
  106. package/esm/src/kernel/registry/attachments.js +29 -26
  107. package/esm/src/kernel/registry/catalog.d.ts +25 -11
  108. package/esm/src/kernel/registry/catalog.js +59 -24
  109. package/esm/src/kernel/registry/ingress.js +34 -22
  110. package/esm/src/kernel/registry/profile-outputs.d.ts +4 -0
  111. package/esm/src/kernel/registry/profile-outputs.js +8 -0
  112. package/esm/src/kernel/registry/profiles.d.ts +34 -14
  113. package/esm/src/kernel/registry/profiles.js +306 -59
  114. package/esm/src/kernel/registry/provider-request.js +2 -0
  115. package/esm/src/kernel/registry/resolve.d.ts +7 -6
  116. package/esm/src/kernel/registry/resolve.js +102 -117
  117. package/esm/src/kernel/registry/schemas.js +1 -1
  118. package/esm/src/kernel/registry/sole-model.d.ts +8 -0
  119. package/esm/src/kernel/registry/sole-model.js +10 -0
  120. package/esm/src/kernel/registry/system-prompt.d.ts +10 -0
  121. package/esm/src/kernel/registry/system-prompt.js +40 -0
  122. package/esm/src/kernel/registry/system-role.d.ts +8 -0
  123. package/esm/src/kernel/registry/system-role.js +14 -0
  124. package/esm/src/kernel/registry/vault.d.ts +2 -2
  125. package/esm/src/kernel/registry/vault.js +4 -4
  126. package/esm/src/kernel/schema.d.ts +97 -11
  127. package/esm/src/kernel/schema.js +256 -111
  128. package/esm/src/kernel/stages.d.ts +175 -0
  129. package/esm/src/kernel/stages.js +476 -0
  130. package/esm/src/kernel/stop.d.ts +65 -11
  131. package/esm/src/kernel/stop.js +46 -11
  132. package/esm/src/kernel/tools/events.d.ts +41 -0
  133. package/esm/src/kernel/tools/events.js +71 -0
  134. package/esm/src/kernel/tools/execute.d.ts +63 -24
  135. package/esm/src/kernel/tools/execute.js +475 -224
  136. package/esm/src/kernel/tools/harness.js +16 -14
  137. package/esm/src/kernel/tools/invoke.js +26 -8
  138. package/esm/src/kernel/tools/mod.d.ts +3 -1
  139. package/esm/src/kernel/tools/mod.js +2 -1
  140. package/esm/src/kernel/tools/permission.d.ts +15 -0
  141. package/esm/src/kernel/tools/permission.js +47 -0
  142. package/esm/src/kernel/tools/project.js +5 -3
  143. package/esm/src/kernel/tools/registry.js +20 -10
  144. package/esm/src/kernel/tools/remote.d.ts +94 -0
  145. package/esm/src/kernel/tools/remote.js +577 -0
  146. package/esm/src/kernel/tools/resolve.d.ts +17 -7
  147. package/esm/src/kernel/tools/resolve.js +38 -17
  148. package/esm/src/kernel/tools/schema.d.ts +2 -0
  149. package/esm/src/kernel/tools/schema.js +23 -6
  150. package/esm/src/kernel/tools/stage-run.d.ts +105 -0
  151. package/esm/src/kernel/tools/stage-run.js +155 -0
  152. package/esm/src/kernel/tools/types.d.ts +198 -20
  153. package/esm/src/kernel/types.d.ts +253 -114
  154. package/esm/src/kernel/util/find-last.d.ts +2 -0
  155. package/esm/src/kernel/util/find-last.js +10 -0
  156. package/esm/src/observability/destinations.d.ts +31 -0
  157. package/esm/src/observability/destinations.js +67 -0
  158. package/esm/src/observability/mod.d.ts +10 -3
  159. package/esm/src/observability/mod.js +6 -2
  160. package/esm/src/observability/policy.d.ts +27 -0
  161. package/esm/src/observability/policy.js +80 -0
  162. package/esm/src/observability/resolve-policy.d.ts +16 -0
  163. package/esm/src/observability/resolve-policy.js +64 -0
  164. package/esm/src/observability/trace-attach.d.ts +3 -1
  165. package/esm/src/observability/trace-attach.js +17 -10
  166. package/esm/src/observability/trace-record.d.ts +12 -4
  167. package/esm/src/observability/trace-record.js +63 -19
  168. package/esm/src/observability/trace-sink.d.ts +19 -0
  169. package/esm/src/observability/trace-sink.js +10 -0
  170. package/esm/src/observability/trace.d.ts +14 -11
  171. package/esm/src/observability/trace.js +23 -14
  172. package/esm/src/observability/types.d.ts +113 -0
  173. package/esm/src/observability/types.js +11 -0
  174. package/esm/src/providers/create-provider.d.ts +7 -4
  175. package/esm/src/providers/create-provider.js +21 -7
  176. package/esm/src/providers/google/interactions/framing.d.ts +8 -0
  177. package/esm/src/providers/google/interactions/framing.js +74 -13
  178. package/esm/src/providers/google/live/framing.d.ts +5 -2
  179. package/esm/src/providers/google/live/framing.js +49 -12
  180. package/esm/src/providers/google/live/openapi-schema.js +3 -2
  181. package/esm/src/providers/google/live/stream.d.ts +9 -0
  182. package/esm/src/providers/google/live/stream.js +16 -3
  183. package/esm/src/providers/openrouter/cache-control.d.ts +24 -0
  184. package/esm/src/providers/openrouter/cache-control.js +23 -0
  185. package/esm/src/providers/openrouter/chat.d.ts +21 -1
  186. package/esm/src/providers/openrouter/chat.js +51 -6
  187. package/esm/src/providers/openrouter/image.js +8 -19
  188. package/esm/src/providers/openrouter/openai/chat-payload.js +23 -1
  189. package/esm/src/providers/openrouter/openai/compat.d.ts +7 -1
  190. package/esm/src/providers/openrouter/openai/compat.js +23 -4
  191. package/esm/src/providers/openrouter/openai/image-payload.js +8 -2
  192. package/esm/src/providers/openrouter/openai/sdk-messages.d.ts +1 -1
  193. package/esm/src/providers/openrouter/openai/sdk-messages.js +32 -5
  194. package/package.json +1 -1
  195. package/esm/src/interface/blocks.d.ts +0 -20
  196. package/esm/src/interface/blocks.js +0 -180
  197. package/esm/src/interface/from-profile.d.ts +0 -14
  198. package/esm/src/interface/from-profile.js +0 -104
  199. package/esm/src/interface/inputs.d.ts +0 -8
  200. package/esm/src/interface/inputs.js +0 -127
  201. package/esm/src/interface/mod.d.ts +0 -10
  202. package/esm/src/interface/mod.js +0 -9
  203. package/esm/src/interface/types.d.ts +0 -153
  204. package/esm/src/interface/types.js +0 -13
package/README.md CHANGED
@@ -10,7 +10,14 @@
10
10
 
11
11
  # THEORUM: The Flat Agent Kernel
12
12
 
13
- **Current release: `1.0.0`** (`jsr:@theorum/core` / npm `theorum`).
13
+ **Current release: `1.1.3`** (`jsr:@theorum/core` / npm `theorum`).
14
+
15
+ > ⚠️ **Package Migration Notice:**
16
+ > Starting with version 2.0, the package and scope are officially rebranded from `theorum` / `@theorum/core` to **`@theoremai/agents`** on both **npm** and **JSR**.
17
+ > - **npm**: `npm install @theoremai/agents` (deprecating `theorum`)
18
+ > - **JSR**: `deno add jsr:@theoremai/agents` (deprecating `jsr:@theorum/core`)
19
+ >
20
+ > All legacy `theorum` / `jsr:@theorum/core` v1.x releases are deprecated in favor of `@theoremai/agents`.
14
21
 
15
22
  > **"Profiles describe the contract. Providers move bytes. The runner enforces the turn."**
16
23
 
@@ -31,7 +38,7 @@ runner = "Single deterministic execution path for one agent turn"
31
38
  providers = "createProvider routes protocol/provider; adapters stay internal"
32
39
  tools = "Profile allowlist ceiling plus per-turn opt-in gates"
33
40
  egress = "Typed host hook for outbound disclosure checks and repair loops"
34
- traces = "Host-injected sinks; no environment variables or bundled destinations"
41
+ traces = "Profile observability + host-registered destinations; no env vars or bundled DB"
35
42
 
36
43
  [non_goals]
37
44
  app_profiles = "No bundled assistants, demos, product personas, or business tasks"
@@ -40,6 +47,10 @@ realtime_voice = "Not included yet; persistent duplex sessions stay host-owned"
40
47
  product_copy = "No channel wording, refusal copy, iMessage/Alexa/Web policy, or UX defaults"
41
48
  ```
42
49
 
50
+ React UI and the headless interface projection remain repo-private under [`react/`](./react/)
51
+ and `src/interface/` while their public contracts are being designed. They are excluded from
52
+ the JSR and npm packages.
53
+
43
54
  ---
44
55
 
45
56
  ## Architecture
@@ -245,8 +256,8 @@ THEORUM separates tool concerns into four layers.
245
256
  | Layer | Owner | Purpose |
246
257
  | :--- | :--- | :--- |
247
258
  | **Catalog** | Host (startup) | `registerTool` — schema, handler, access, loadTier, permission |
248
- | **Allow** | Profile | Custom: `tools.allow`. Builtins: `model.config.*.builtInTools` |
249
- | **Visibility** | Registry + profile | `loadTier` on tool; T1 via `tools.t1Policy`; T2 via `tools.t2Loader` |
259
+ | **Allow** | Profile | Custom: `tools.allow`. Builtins: `models.*.builtInTools` |
260
+ | **Visibility** | Registry + profile | `loadTier` on tool; T1 via `tools.t1Policy`; T2 via `tools.t2Loader`. Live (`runSession`) wires every allowed tool at setup; `host` profiles execute every allowed tool via `invokeTool`. |
250
261
  | **Permission** | Host app | `auto`, `session_consent`, and `always_confirm` determine whether execution pauses |
251
262
 
252
263
  ```ts
@@ -274,8 +285,8 @@ tools: { allow: ['lookup_order', 'load_tools'] }
274
285
 
275
286
  runTurn({ profile, input: { text: '…' } }, provider);
276
287
 
277
- // Host resume (interactive, confirmation, permission)
278
- invokeTool({ profile, name: 'ask_user', input: { kind: 'confirm', prompt: 'Proceed?' }, resume: { value: true } });
288
+ // Gate resume (permission / confirm / auth) — ask_user completes awaiting; answer is a new user turn
289
+ invokeTool({ profile, name: 'risky_tool', input: {}, resume: { granted: true }, snapshot, turnInput });
279
290
  ```
280
291
 
281
292
  The host owns handlers and authorization state. The kernel enforces the declared contract
@@ -386,8 +397,8 @@ stay internal to the providers package.
386
397
 
387
398
  | Entrypoint | Purpose |
388
399
  | :--- | :--- |
389
- | `jsr:@theorum/core` / `theorum` | Main kernel API: profiles, schemas, runner, core types, provider constructors. |
390
- | `jsr:@theorum/core/kernel` / `theorum/kernel` | Profile/turn types, tool catalog, `requireModelSpec`, thinking clamps over host model maps. |
400
+ | `jsr:@theorum/core` / `theorum` | Main kernel API: profiles, schemas, runner, core types, provider constructors, declarative HTTP/MCP tool execution. |
401
+ | `jsr:@theorum/core/kernel` / `theorum/kernel` | Profile/turn types, tool catalog, `requireModelBinding`, thinking clamps over host model maps. |
391
402
  | `jsr:@theorum/core/providers` / `theorum/providers` | `createProvider` + Gemini vault types + host option bags. |
392
403
  | `jsr:@theorum/core/providers/local` / `theorum/providers/local` | Direct local OpenAI-compat adapter (`createLocalProvider`, `DEFAULT_LOCAL_BASE_URL`). |
393
404
  | `jsr:@theorum/core/guardrails` / `theorum/guardrails` | Sanitization, canary/egress gates, public error mapping, inbound injection/sensitive-data primitives. |
@@ -397,7 +408,10 @@ stay internal to the providers package.
397
408
  | `jsr:@theorum/core/cli` / `theorum/cli` | Profile inspection and stress-test CLI (`theorum` binary on npm). |
398
409
  | `jsr:@theorum/core/presets` / `theorum/presets` | Optional convenience packs (`registerGooglePreset`, …). |
399
410
  | `jsr:@theorum/core/presets/google` / `theorum/presets/google` | Google builtins (search/maps/urlContext/codeExecution) + Interactions/OpenRouter wire metadata. |
400
- | `jsr:@theorum/core/interface` / `theorum/interface` | Headless profile-driven runtime UI spec (`interfaceFromProfile`, `foldTurnEvents`, input validation). |
411
+
412
+ Demo fixtures (travel concierge seeds, local handlers) live in the **repo-private**
413
+ `@theorum/playground` package under `playground/` — never published with the kernel.
414
+ Hosts that need them link `file:../theorum/playground`.
401
415
 
402
416
  Internal files remain present in source for maintainability, but package consumers should use the public entrypoints above.
403
417
 
@@ -409,20 +423,25 @@ Named exports from the root barrel (same symbols hosts get from `theorum` /
409
423
  | Group | Symbols |
410
424
  | --- | --- |
411
425
  | Guardrails errors | `describeError`, `isAbortError`, `publicError`, `TheorumError`, `throwIfAborted`, `toErrorEvent`, `PUBLIC_CANARY` |
412
- | Quota | `QuotaSlotStatus`, `clientIp`, `quotaMessage`, `releaseSlot`, `resetSlots`, `skipQuota`, `takeSlot` |
413
- | Sanitize | `PROJECT_ID_MAX`, `sanitizeProjectId`, `sanitizeText`, `sanitizeTurnRequest`, `sanitizeTurnRequestForTrace`, `redactSensitiveOnly` |
414
- | Canary / egress | `mintCanary`, `bindCanary`, `wrapUserData`, `scanTextForCanaryLeak`, `redactCanary`, `OMIT_CANARY`, `createCanaryStreamGate`, `eventHasCanary`, `createCanaryGateSession`, `filterCanaryGatedEvents`, `CanaryGateResult`, `CanaryGateSession`, `CanaryStreamGate`, `standardEgressEnforce`, `createLiveOutboundGateSession`, `processLiveOutboundBatch`, `finalizeLiveOutboundTurn`, `LiveOutboundBatchResult`, `LiveOutboundGateSession` |
426
+ | Network guardrails | `assertSafeUrl`, `isLocalhostName`, `isPrivateOrLocalAddress` |
427
+ | Guardrail vocabulary | `AdvisoryLevel`, `TrustLevel`, `GuardrailStage`, `Severity`, `GuardrailHit`, `Verdict`, `GuardrailAction`, `GuardrailContext`, `GuardrailEvent`, `OutboundPayload`, `Provenance`, `ToolOrigin`, `ScanText`, `EgressEnforcer`, `EgressOnBlock`, `ProfileEgressSpec`, `ProfileGuardrailsSpec`, `HostGuardrailsSpec`, `NetworkGuardrailSpec`, `CanaryGuardrailSpec`, `QuotaGuardrailSpec`, `ResolvedGuardrailPolicy`, `DetectionOptions`, `GuardedToolText`, `TurnTaint`, `TaintGate`, `TaintGuardrailSpec`, `TRUST_LEVELS`, `GUARDRAIL_STAGES`, `SEVERITIES`, `TOOL_ORIGINS`, `EGRESS_ON_BLOCK` |
428
+ | Guardrail policy | `resolveGuardrailPolicy`, `detectionForTrust`, `detectionForProfile`, `collectEgressHits`, `hitRules`, `EGRESS_RULES`, `runEnforcer` |
429
+ | Tool boundary | `guardToolResult`, `guardToolFailureText`, `inspectToolArguments`, `toolCallEvent`, `wrapToolData`, `isRemoteOrigin`, `composeToolText`, `checkTaintGate`, `recordTaint`, `isTainted`, `isSuspicious`, `directiveHits`, `looksDirective`, `advisoryLevel`, `DIRECTIVE_RULES`, `ADVISORY_LEVELS`, `TOOL_CLOSE`, `TOOL_ORIGINS`, `TAINT_GATES`, `textForScan`, `scanTextOf` |
430
+ | Quota | `QuotaSlotStatus`, `QuotaExhausted`, `clientIp`, `quotaExhausted`, `releaseSlot`, `resetSlots`, `skipQuota`, `takeSlot` |
431
+ | Lexicon | `LEXICON_KEYS`, `LexiconKey`, `LexiconOverrides`, `LexiconParams`, `lexiconDefault`, `lexiconText`, `overrideLexicon`, `resetLexicon` |
432
+ | Sanitize | `PROJECT_ID_MAX`, `sanitizeProjectId`, `sanitizeText`, `detectText`, `sanitizeTurnRequest`, `sanitizeTurnRequestWithEvents`, `sanitizeTurnRequestForTrace`, `redactSensitiveOnly`, `guardrailFromHits`, `guardrailFromVerdict`, `guardrailTurnEvent`, `projectGuardrailTurnEvent`, `hitFromSpan`, `matchPreview`, `projectGuardrailEvent`, `GUARDRAIL_MATCH_PREVIEW_MAX` |
433
+ | Canary / egress | `mintCanary`, `bindCanary`, `wrapUserData`, `scanTextForCanaryLeak`, `redactCanary`, `OMIT_CANARY`, `createCanaryStreamGate`, `eventHasCanary`, `createCanaryGateSession`, `filterCanaryGatedEvents`, `CanaryGateResult`, `CanaryGateSession`, `CanaryStreamGate`, `standardEgressEnforce`, `createOutboundProgressiveGate`, `createProgressiveYieldGate`, `DEFAULT_HOLDBACK`, `createLiveOutboundGateSession`, `processLiveOutboundBatch`, `finalizeLiveOutboundTurn`, `LiveOutboundBatchResult`, `LiveOutboundGateSession`, `ProgressiveYieldGate`, `ProgressiveYieldGateOptions`, `ProgressiveYieldResult` |
415
434
  | Compaction | `CompactionSplit`, `CompactionTokens`, `compactionMeter`, `compactionNeeded`, `estimateHistoryTokens`, `HISTORY_MEDIA_TOKENS`, `HISTORY_TEXT_ENCODING`, `resolveCompactionTokens`, `resolveHistoryTokens`, `shouldCompact`, `splitForCompaction` |
416
- | Runner | `runTurn`, `runSession`, `RunSessionOptions`, `prepareLiveInboundText` |
417
- | Attachments | `assertAttachmentLimits`, `fileTooLargeMessage`, `maxBytesForMime`, `requireMediaLimits`, `resolveMediaLimits`, `sanitizeCsvText`, `sanitizeTurnBlobs`, `sanitizeTurnBlobsForProfile`, `tooManyFilesMessage`, `turnTooLargeMessage` |
418
- | Interface (headless) | `interfaceFrom`, `interfaceFromProfile`, `interfaceFromProjected`, `inputsFromSpec`, `attachmentAcceptAttr`, `validateProfileInputs`, `pickMediaRecorderMime`, `buildUserTurnBlocks`, `foldTurnEvents`, `foldConversationTurn`, `resetBlockIds`, `streamThoughtsEnabled`, `AttachmentValidationCode`, `AttachmentValidationIssue`, `AttachmentValidationResult`, `FoldTurnEventsOptions`, `ImageProfileInterface`, `LiveProfileInterface`, `NormalizeModel`, `NormalizedModel`, `PendingAttachment`, `ProfileGuardrailsView`, `ProfileInputsInterface`, `ProfileInterface`, `ProfileInterfaceSource`, `ResolvedTools`, `SpeechProfileInterface`, `TextProfileInterface`, `TranscriptBlock`, `TranscriptBlockKind`, `UserTurnDraft` |
419
- | Catalog | `clampThinkingLevel`, `clampThinkingLevelForApiId`, `mediaKindForMime`, `mimeAllowed`, `mimeEssence`, `modelEntryByApiId`, `requireModelSpec` |
420
- | Schema | `PROFILE_FIELDS`, `PROFILE_TYPES`, `PROFILE_TYPE_PROTOCOLS`, `protocolsForProfileType`, `isValidProfileProtocol`, `EXTRA_FIELDS`, `fieldMeta`, `catalogPathFor`, `DYNAMIC_FIELD_PARENTS`, `PROTOCOLS`, `PROVIDERS`, `PROTOCOL_PROVIDERS`, `providersFor`, `protocolsFor`, `isValidPair`, `coerceProvider`, `coerceProtocol`, `THINKING_LEVELS`, `CONTROL_IDS`, `KEY_SLOTS`, `OVERFLOW_KEY_SLOTS`, `MEDIA_INPUT_KINDS`, `MEDIA_INPUT_KIND_VALUES`, `MEDIA_WILDCARDS`, `ATTACHMENT_ACCEPT_MIMES`, `VOICE_ACCEPT_MIMES`, `SUMMARY_MODES`, `STREAM_MODES`, `SPEECH_AUDIO_FORMATS`, `SCHEMA_ENFORCEMENTS`, `COMPACTION_METERS`, `COMPACTION_TIMINGS`, `EGRESS_ON_BLOCK`, `TURN_STOP_KINDS`, `TOOL_LOAD_TIERS`, `TOOL_ACCESS`, `TOOL_PERMISSION`, `TOOL_TYPES`, `LIVE_ACTIVITY_HANDLINGS`, `LIVE_CONTEXT_COMPRESSIONS`, `LIVE_SPEECH_SENSITIVITIES` |
421
- | Profiles | `ProfileDefinition`, `ProfileDefinitionBase`, `TextProfileDefinition`, `ImageProfileDefinition`, `SpeechProfileDefinition`, `LiveProfileDefinition`, `clearProfiles`, `defineProfile`, `getProfile`, `hasProfile`, `listProfiles`, `registerProfile`, `registerProfiles`, `projectProfile`, `resolveTurn`, `pickModel` |
422
- | Tools | `registerTool`, `registerTools`, `invokeTool`, `registerHarnessTools`, `getTool`, `hasTool`, `requireTool`, `listTools`, `listBuiltinIds`, `listFunctionIds`, `resetTools`, `formatToolResult`, `prepareTurnToolSnapshot` |
435
+ | Runner | `runTurn`, `runSession`, `RunSessionOptions`, `prepareLiveInboundText`, `liveIngressEnabled`, `liveIngressEnabledFromSpec`, `liveIngressChannelDefault`, `hasAnyLiveIngress`, `assertLiveIngress`, `assertLiveIngressConfigured`, `LiveIngressChannel` |
436
+ | Attachments | `assertAttachmentLimits`, `maxBytesForMime`, `requireMediaLimits`, `resolveMediaLimits`, `sanitizeCsvText`, `sanitizeTurnBlobs`, `sanitizeTurnBlobsForProfile` |
437
+ | Catalog | `clampThinkingLevel`, `clampThinkingLevelForApiId`, `mediaChannelForMime`, `MediaInputChannel`, `mediaKindForMime`, `mimeAllowed`, `mimeEssence`, `modelEntryByApiId`, `requireModelBinding` |
438
+ | Schema | `PROFILE_FIELDS`, `PROFILE_GRAPH`, `PROFILE_TYPES`, `PROFILE_TYPE_PROTOCOLS`, `protocolsForProfileType`, `isValidProfileProtocol`, `EXTRA_FIELDS`, `fieldMeta`, `catalogPathFor`, `DYNAMIC_FIELD_PARENTS`, `spineFacetsForProfileType`, `profileGraphFacet`, `ProfileGraphFacet`, `ProfileGraphFacetId`, `ProfileGraphEditor`, `ProfileGraphRole`, `PROTOCOLS`, `PROVIDERS`, `PROTOCOL_PROVIDERS`, `providersFor`, `protocolsFor`, `isValidPair`, `coerceProvider`, `coerceProtocol`, `coerceSpeechFormat`, `isSpeechFormatAllowedForProtocol`, `speechFormatsForProtocol`, `THINKING_LEVELS`, `KEY_SLOTS`, `OVERFLOW_KEY_SLOTS`, `MEDIA_INPUT_KINDS`, `MEDIA_INPUT_KIND_VALUES`, `MEDIA_WILDCARDS`, `ATTACHMENT_ACCEPT_MIMES`, `VOICE_ACCEPT_MIMES`, `SUMMARY_MODES`, `STREAM_MODES`, `SPEECH_AUDIO_FORMATS`, `SCHEMA_ENFORCEMENTS`, `COMPACTION_METERS`, `COMPACTION_TIMINGS`, `CACHE_MODES`, `CACHE_TTLS`, `TURN_STAGES`, `TURN_INJECT_STAGES`, `TURN_STOP_KINDS`, `CONTINUE_STOP_KINDS`, `TOOL_GATE_KINDS`, `AWAITING_USER_INPUT_KINDS`, `AWAITING_USER_INPUT_STATUS`, `TOOL_LOAD_TIERS`, `TOOL_ACCESS`, `TOOL_PERMISSION`, `TOOL_TYPES`, `AUTH_UNAUTHENTICATED_POLICIES`, `HTTP_METHODS`, `PLAYGROUND_AUTH_TYPES`, `TOOL_AUTH_TYPES`, `AuthUnauthenticatedPolicy`, `CustomToolType`, `HttpMethod`, `PlaygroundAuthType`, `ToolAccess`, `ToolAuthType`, `ToolPermission`, `ToolType`, `LIVE_ACTIVITY_HANDLINGS`, `LIVE_CONTEXT_COMPRESSIONS`, `LIVE_SPEECH_SENSITIVITIES`, `EGRESS_ON_BLOCK`, `EgressOnBlock` |
439
+ | Profiles | `ProfileDefinition`, `ProfileDefinitionBase`, `TextProfileDefinition`, `ImageProfileDefinition`, `SpeechProfileDefinition`, `LiveProfileDefinition`, `HostProfileDefinition`, `clearProfiles`, `defineProfile`, `getProfile`, `hasProfile`, `listProfiles`, `registerProfile`, `registerProfiles`, `projectProfile`, `resolveTurn`, `pickModel` |
440
+ | Tools | `registerTool`, `registerTools`, `invokeTool`, `registerHarnessTools`, `getTool`, `hasTool`, `requireTool`, `listTools`, `listBuiltinIds`, `listFunctionIds`, `resetTools`, `formatToolResult`, `prepareTurnToolSnapshot`, `buildHttpToolTarget`, `executeHttpTool`, `executeMcpTool`, `parseMcpRpcResponse`, `isUnsupportedMcpProtocolError`, `MCP_PROTOCOL_VERSIONS`, `McpProtocolVersion`, `resolveToolAuth` |
423
441
  | Structured | `getStructured`, `registerStructured` |
424
- | Stop / resume | `ProfileTurnResumptionSpec`, `TurnContinueFrom`, `TurnStop`, `TurnStopKind`, `AUTO_CONTINUE_DELAY_MS`, `CONTINUE_INSTRUCTION`, `DEFAULT_AUTO_CONTINUE`, `GenerationStopError`, `isGenerationStopError`, `isResumeableStop`, `isUserCancelledStop`, `shouldAutoContinue`, `turnStopFromClientStreamEnd`, `turnStopFromInteractionStatus`, `turnStopFromOpenAiFinishReason` |
425
- | Observability | `jsonlSink`, `memorySink`, `noopSink`, `resolveTraceDir`, `sinkFromDir`, `writeTrace`, `TraceRecord` |
442
+ | Stop / resume | `ProfileTurnBehaviourSpec`, `ProfileTurnResumptionSpec`, `TurnContinueFrom`, `TurnStop`, `TurnStopKind`, `ContinueStopKind`, `CONTINUE_STOP_KINDS`, `AUTO_CONTINUE_DELAY_MS`, `CONTINUE_INSTRUCTION`, `DEFAULT_ALLOW_CONTINUE`, `DEFAULT_AUTO_CONTINUE`, `GenerationStopError`, `isContinueStopKind`, `isGenerationStopError`, `isResumeableStop`, `isUserCancelledStop`, `profileAllowsSteering`, `profileAllowsInject`, `profileTurnResumption`, `shouldAutoContinue`, `turnStopFromClientStreamEnd`, `turnStopFromInteractionStatus`, `turnStopFromOpenAiFinishReason` |
443
+ | Stages (target foundation) | `TURN_STAGES`, `TURN_INJECT_STAGES`, `STAGE_AFFORDANCES`, `STAGE_AFFORDANCE_MATRIX`, `TOOL_GATE_KINDS`, `AWAITING_USER_INPUT_KINDS`, `AWAITING_USER_INPUT_STATUS`, `applyStageResult`, `parseAwaitingUserInput`, `parseToolGate`, `isTurnStage`, `isTurnInjectStage`, `isToolGateKind`, `isAwaitingUserInput`, `stageAllowsAffordance`, `stageEventFields`, `profileAllowsInject`, `StageAffordance`, `StageContext`, `StageResult`, `StageMutate`, `StageHandler`, `StageApplyInput`, `StageApplyOutput`, `StageApplyWarning`, `StageApplyWarningCode`, `StageEventExtra`, `AwaitingUserInput`, `ToolGate` — contract [`docs/contracts/stages.md`](docs/contracts/stages.md) |
444
+ | Observability | `jsonlSink`, `memorySink`, `noopSink`, `resolveTraceDir`, `sinkFromDir`, `writeTrace`, `registerTraceDestination`, `jsonlDestination`, `requireTraceDestination`, `getTraceDestination`, `listTraceDestinationIds`, `clearTraceDestinations`, `isJsonlTraceDestination`, `isTraceSink`, `resolveTraceWriter`, `resolveObservabilityPolicy`, `TraceRecord`, `TraceSink`, `JsonlSinkOptions`, `JsonlTraceDestination`, `TraceDestination`, `ProfileObservabilitySpec`, `ResolvedObservabilityPolicy`, `ResolvedTraceInclude`, `ResolvedTraceScrub`, `TraceIncludeSpec`, `TraceScrubSpec` |
426
445
  | Providers | `CreateProviderOptions`, `GeminiTransport`, `KeyVault`, `LocalProviderConfig`, `OpenAiGatewayConfig`, `createProvider` (local: `theorum/providers/local` → `createLocalProvider`, `DEFAULT_LOCAL_BASE_URL`) |
427
446
 
428
447
  Kernel types re-exported through this barrel follow `export type *` from
@@ -446,17 +465,20 @@ On GitHub, module contracts:
446
465
  | Doc (repo only) | Export |
447
466
  | :--- | :--- |
448
467
  | [`docs/contracts/kernel.md`](docs/contracts/kernel.md) | `theorum/kernel` |
468
+ | [`docs/contracts/stages.md`](docs/contracts/stages.md) | Turn stages — slices 1–3 landed on branch; release cut when docs match product |
449
469
  | [`docs/contracts/providers.md`](docs/contracts/providers.md) | `theorum/providers` |
450
470
  | [`docs/contracts/guardrails.md`](docs/contracts/guardrails.md) | `theorum/guardrails` |
451
471
  | [`docs/contracts/observability.md`](docs/contracts/observability.md) | `theorum/observability` |
452
472
  | [`docs/contracts/host.md`](docs/contracts/host.md) | `theorum/host` |
453
- | [`docs/contracts/kernel.md`](docs/contracts/kernel.md) (Headless interface) | `theorum/interface` |
473
+ | [`docs/contracts/kernel.md`](docs/contracts/kernel.md) (repo-private headless interface) | `src/interface/` |
454
474
  | [`docs/contracts/cli.md`](docs/contracts/cli.md) | `theorum/cli` |
455
475
  | [`docs/contracts/presets.md`](docs/contracts/presets.md) | `theorum/presets` |
456
476
  | [`docs/contracts/presets-google.md`](docs/contracts/presets-google.md) | `theorum/presets/google` |
457
477
 
458
478
  Migrating from per-turn `dynamicTools`? See
459
479
  [`docs/MIGRATION-tool-system.md`](docs/MIGRATION-tool-system.md).
480
+ Ownership-boundary cut (playground out of package, quota/lexicon/composer)? See
481
+ [`docs/MIGRATION-boundary.md`](docs/MIGRATION-boundary.md).
460
482
 
461
483
  Document health is enforced by `npm run lint:docs` — the **first** step of
462
484
  `npm run lint` / `deno task lint` (`docs/_map.mjs`):
@@ -478,9 +500,22 @@ Document health is enforced by `npm run lint:docs` — the **first** step of
478
500
  npm install
479
501
  npm run test
480
502
  npm run lint
481
- deno publish --dry-run --allow-dirty
503
+ deno install
504
+ deno publish --dry-run
505
+ npm run build:npm
506
+ cd npm && npm pack
507
+ ```
508
+
509
+ To dry-run npm publish when the current version is already on the registry, bump to an ephemeral prerelease first (CI does this automatically):
510
+
511
+ ```bash
512
+ cd npm
513
+ npm version 0.0.0-pr.local --no-git-tag-version
514
+ npm publish --dry-run --access public --tag ci-validate
482
515
  ```
483
516
 
517
+ PR CI runs JSR and npm dry-run checks in the required `publish-dry-run` job.
518
+
484
519
  Run the packaged CLI locally:
485
520
 
486
521
  ```bash
@@ -520,16 +555,36 @@ THEORUM is ready for host applications when these statements stay true:
520
555
 
521
556
  ```toml
522
557
  [boundary]
558
+ # Rule: "Host decides, Theorum runs."
523
559
  profiles_in_package = false
560
+ demos_in_package = false
524
561
  env_files_in_package = false
525
562
  ambient_secret_reads = false
526
563
  business_logic_in_kernel = false
564
+ unownable_user_or_model_copy = false
527
565
  provider_keys_host_owned = true
528
566
  provider_adapters_lazy = true
529
567
  trace_sinks_host_injected = true
530
568
  realtime_duplex_voice = "out of scope"
531
569
  ```
532
570
 
571
+ **Facts vs policy.** Provider facts may ship (model capabilities, wire shapes,
572
+ protocol metadata — e.g. `theorum/presets/google`). Product policy may not
573
+ (prompts, personas, end-user copy, demo apps, channel behavior). Every
574
+ user- or model-visible string is either host-supplied or an overridable
575
+ registered default in the kernel lexicon (`overrideLexicon`). Behavioral
576
+ defaults live as typed profile-schema fields. Optional packages
577
+ (`playground/`) are inert extras: deleting them changes no kernel behavior.
578
+
579
+ Invariant properties (machine-checked where noted):
580
+
581
+ | Id | Property | Check |
582
+ | --- | --- | --- |
583
+ | P1 | No ambient authority — construct with every Deno permission denied | `tests/kernel/zero-permission-import.test.ts` |
584
+ | P2 | No unownable words — user/model-visible strings are host-suppliable or lexicon defaults | lexicon + full-tree `scripts/docs-truth/copy-lint.mjs` + two-hosts test |
585
+ | P3 | No buried policy — behavioral defaults are declared profile-schema fields | `PROFILE_FIELDS` / schema |
586
+ | P4 | Inert extras — optional entrypoints removable without behavior change | publish-bundle gate excludes `playground/` |
587
+
533
588
  Provider adapters load **lazily** on the first `complete` for that transport —
534
589
  `createProvider` and `theorum/providers` stay a thin barrel (`src/providers/mod.ts`);
535
590
  implementation modules (e.g. `google/interactions/`, `openrouter/`, `local/`) are
@@ -574,8 +629,9 @@ MIT License. Copyright (c) ORCHID AI LLC.
574
629
  "Package Boundary": {
575
630
  "supports": [
576
631
  { "kind": "source", "path": "src/providers/mod.ts" },
577
- { "kind": "source", "path": "src/providers/create-provider.ts" },
578
- { "kind": "contract_test", "path": "tests/providers/create-provider.test.ts" }
632
+ { "kind": "source", "path": "src/guardrails/lexicon.ts" },
633
+ { "kind": "contract_test", "path": "tests/kernel/two-hosts-boundary.test.ts" },
634
+ { "kind": "contract_test", "path": "tests/kernel/zero-permission-import.test.ts" }
579
635
  ]
580
636
  }
581
637
  }
package/esm/mod.d.ts CHANGED
@@ -11,24 +11,31 @@
11
11
  *
12
12
  * const profile = defineProfile({
13
13
  * id: "assistant.basic",
14
- * model: {
15
- * allow: ["gemini35FlashLite"],
16
- * config: {
17
- * gemini35FlashLite: {
18
- * apiId: "gemini-3.5-flash-lite",
19
- * thinking: { on: "high", off: "minimal" },
20
- * thinkingLevels: ["minimal", "low", "medium", "high"],
21
- * summaries: { on: "auto", off: "none" },
22
- * maxOutputTokens: 8192,
23
- * temperature: 1,
24
- * builtInTools: [],
25
- * },
14
+ * type: "text",
15
+ * identity: {
16
+ * handle: "assistant",
17
+ * system: "Answer plainly.",
18
+ * },
19
+ * models: {
20
+ * default: {
21
+ * protocol: "openAi",
22
+ * provider: "openrouter",
23
+ * apiId: "perplexity/sonar",
24
+ * efforts: { normal: "minimal" },
25
+ * summaries: false,
26
+ * maxOutputTokens: 8192,
27
+ * temperature: 1,
26
28
  * },
27
29
  * },
30
+ * maxSteps: 1,
28
31
  * tools: { allow: [] },
29
32
  * inputs: { text: true },
30
- * outputs: {},
31
- * guardrails: { quota: { perDay: 100 } },
33
+ * outputs: {
34
+ * streaming: { streamThoughts: false },
35
+ * },
36
+ * guardrails: {
37
+ * quota: { perDay: 100 },
38
+ * },
32
39
  * });
33
40
  *
34
41
  * registerProfile(profile);
@@ -38,32 +45,44 @@
38
45
  */
39
46
  import "./_dnt.polyfills.js";
40
47
  export { describeError, isAbortError, PUBLIC_CANARY, publicError, TheorumError, throwIfAborted, toErrorEvent, } from './src/guardrails/error.js';
41
- export type { CanaryGateResult, CanaryGateSession, CanaryStreamGate, LiveOutboundBatchResult, LiveOutboundGateSession, } from './src/guardrails/mod.js';
42
- export { bindCanary, createCanaryGateSession, createCanaryStreamGate, createLiveOutboundGateSession, eventHasCanary, filterCanaryGatedEvents, finalizeLiveOutboundTurn, mintCanary, OMIT_CANARY, processLiveOutboundBatch, redactCanary, scanTextForCanaryLeak, standardEgressEnforce, wrapUserData, } from './src/guardrails/mod.js';
43
- export type { QuotaSlotStatus } from './src/guardrails/quota.js';
44
- export { clientIp, quotaMessage, releaseSlot, resetSlots, skipQuota, takeSlot, } from './src/guardrails/quota.js';
45
- export { PROJECT_ID_MAX, redactSensitiveOnly, sanitizeProjectId, sanitizeText, sanitizeTurnRequest, sanitizeTurnRequestForTrace, } from './src/guardrails/sanitize.js';
48
+ export { guardrailFromHits, guardrailFromVerdict, guardrailTurnEvent, projectGuardrailTurnEvent, } from './src/guardrails/events.js';
49
+ export { GUARDRAIL_MATCH_PREVIEW_MAX, hitFromSpan, matchPreview, projectGuardrailEvent, } from './src/guardrails/hits.js';
50
+ export type { LexiconKey, LexiconOverrides, LexiconParams } from './src/guardrails/lexicon.js';
51
+ export { LEXICON_KEYS, lexiconDefault, lexiconText, overrideLexicon, resetLexicon, } from './src/guardrails/lexicon.js';
52
+ export type { AdvisoryLevel, CanaryGateResult, CanaryGateSession, CanaryGuardrailSpec, CanaryStreamGate, DetectionOptions, EgressEnforcer, EgressOnBlock, GuardedToolText, GuardrailAction, GuardrailContext, GuardrailEvent, GuardrailHit, GuardrailStage, HostGuardrailsSpec, LiveOutboundBatchResult, LiveOutboundGateSession, NetworkGuardrailSpec, OutboundPayload, ProfileEgressSpec, ProfileGuardrailsSpec, ProgressiveYieldGate, ProgressiveYieldGateOptions, ProgressiveYieldResult, Provenance, QuotaGuardrailSpec, ResolvedGuardrailPolicy, ScanText, Severity, TaintGate, TaintGuardrailSpec, ToolOrigin, TrustLevel, TurnTaint, Verdict, } from './src/guardrails/mod.js';
53
+ export { ADVISORY_LEVELS, bindCanary, checkTaintGate, collectEgressHits, composeToolText, createCanaryGateSession, createCanaryStreamGate, createLiveOutboundGateSession, createOutboundProgressiveGate, createProgressiveYieldGate, DEFAULT_HOLDBACK, DIRECTIVE_RULES, detectionForTrust, directiveHits, EGRESS_ON_BLOCK, EGRESS_RULES, eventHasCanary, filterCanaryGatedEvents, finalizeLiveOutboundTurn, GUARDRAIL_STAGES, guardToolFailureText, guardToolResult, hitRules, inspectToolArguments, isRemoteOrigin, isSuspicious, isTainted, looksDirective, mintCanary, OMIT_CANARY, processLiveOutboundBatch, recordTaint, redactCanary, resolveGuardrailPolicy, runEnforcer, SEVERITIES, scanTextForCanaryLeak, scanTextOf, standardEgressEnforce, TAINT_GATES, TOOL_CLOSE, TOOL_ORIGINS, TRUST_LEVELS, textForScan, toolCallEvent, wrapToolData, wrapUserData, } from './src/guardrails/mod.js';
54
+ export { assertSafeUrl, isLocalhostName, isPrivateOrLocalAddress, } from './src/guardrails/network.js';
55
+ export type { QuotaExhausted, QuotaSlotStatus } from './src/guardrails/quota.js';
56
+ export { clientIp, quotaExhausted, releaseSlot, resetSlots, skipQuota, takeSlot, } from './src/guardrails/quota.js';
57
+ export { detectionForProfile, detectText, PROJECT_ID_MAX, redactSensitiveOnly, sanitizeProjectId, sanitizeText, sanitizeTurnRequest, sanitizeTurnRequestForTrace, sanitizeTurnRequestWithEvents, } from './src/guardrails/sanitize.js';
46
58
  export type { CompactionSplit, CompactionTokens } from './src/kernel/engine/compaction.js';
47
59
  export { compactionMeter, compactionNeeded, estimateHistoryTokens, HISTORY_MEDIA_TOKENS, HISTORY_TEXT_ENCODING, resolveCompactionTokens, resolveHistoryTokens, shouldCompact, splitForCompaction, } from './src/kernel/engine/compaction.js';
48
60
  export { prepareLiveInboundText } from './src/kernel/engine/live-inbound.js';
61
+ export type { LiveIngressChannel } from './src/kernel/engine/live-ingress.js';
62
+ export { assertLiveIngress, assertLiveIngressConfigured, hasAnyLiveIngress, liveIngressChannelDefault, liveIngressEnabled, liveIngressEnabledFromSpec, } from './src/kernel/engine/live-ingress.js';
49
63
  export { runTurn } from './src/kernel/engine/runner.js';
50
64
  export type { RunSessionOptions } from './src/kernel/engine/session/mod.js';
51
65
  export { runSession } from './src/kernel/engine/session/mod.js';
52
- export { assertAttachmentLimits, fileTooLargeMessage, maxBytesForMime, requireMediaLimits, resolveMediaLimits, sanitizeCsvText, sanitizeTurnBlobs, sanitizeTurnBlobsForProfile, tooManyFilesMessage, turnTooLargeMessage, } from './src/kernel/registry/attachments.js';
53
- export { clampThinkingLevel, clampThinkingLevelForApiId, mediaKindForMime, mimeAllowed, mimeEssence, modelEntryByApiId, requireModelSpec, } from './src/kernel/registry/catalog.js';
66
+ export type { ProfileGraphEditor, ProfileGraphFacet, ProfileGraphFacetId, ProfileGraphRole, } from './src/kernel/profile-graph.js';
67
+ export { PROFILE_GRAPH, profileGraphFacet, spineFacetsForProfileType, } from './src/kernel/profile-graph.js';
68
+ export { assertAttachmentLimits, maxBytesForMime, requireMediaLimits, resolveMediaLimits, sanitizeCsvText, sanitizeTurnBlobs, sanitizeTurnBlobsForProfile, } from './src/kernel/registry/attachments.js';
69
+ export type { MediaInputChannel } from './src/kernel/registry/catalog.js';
70
+ export { clampThinkingLevel, clampThinkingLevelForApiId, mediaChannelForMime, mediaKindForMime, mimeAllowed, mimeEssence, modelEntryByApiId, requireModelBinding, } from './src/kernel/registry/catalog.js';
54
71
  export type { ImageProfileDefinition, LiveProfileDefinition, ProfileDefinition, ProfileDefinitionBase, SpeechProfileDefinition, TextProfileDefinition, } from './src/kernel/registry/profiles.js';
55
72
  export { clearProfiles, defineProfile, getProfile, hasProfile, listProfiles, registerProfile, registerProfiles, } from './src/kernel/registry/profiles.js';
56
73
  export { pickModel, projectProfile, resolveTurn } from './src/kernel/registry/resolve.js';
57
74
  export { getStructured, registerStructured } from './src/kernel/registry/schemas.js';
58
- export type { TurnStopKind } from './src/kernel/schema.js';
59
- export { ATTACHMENT_ACCEPT_MIMES, COMPACTION_METERS, COMPACTION_TIMINGS, CONTROL_IDS, catalogPathFor, coerceProtocol, coerceProvider, DYNAMIC_FIELD_PARENTS, EGRESS_ON_BLOCK, EXTRA_FIELDS, fieldMeta, isValidPair, isValidProfileProtocol, KEY_SLOTS, LIVE_ACTIVITY_HANDLINGS, LIVE_CONTEXT_COMPRESSIONS, LIVE_SPEECH_SENSITIVITIES, MEDIA_INPUT_KIND_VALUES, MEDIA_INPUT_KINDS, MEDIA_WILDCARDS, OVERFLOW_KEY_SLOTS, PROFILE_FIELDS, PROFILE_TYPE_PROTOCOLS, PROFILE_TYPES, PROTOCOL_PROVIDERS, PROTOCOLS, PROVIDERS, protocolsFor, protocolsForProfileType, providersFor, SCHEMA_ENFORCEMENTS, SPEECH_AUDIO_FORMATS, STREAM_MODES, SUMMARY_MODES, THINKING_LEVELS, TOOL_ACCESS, TOOL_LOAD_TIERS, TOOL_PERMISSION, TOOL_TYPES, TURN_STOP_KINDS, VOICE_ACCEPT_MIMES, } from './src/kernel/schema.js';
60
- export type { ProfileTurnResumptionSpec, TurnContinueFrom, TurnStop, } from './src/kernel/stop.js';
61
- export { AUTO_CONTINUE_DELAY_MS, CONTINUE_INSTRUCTION, DEFAULT_AUTO_CONTINUE, GenerationStopError, isGenerationStopError, isResumeableStop, isUserCancelledStop, shouldAutoContinue, turnStopFromClientStreamEnd, turnStopFromInteractionStatus, turnStopFromOpenAiFinishReason, } from './src/kernel/stop.js';
62
- export { formatToolResult, getTool, hasTool, invokeTool, listBuiltinIds, listFunctionIds, listTools, prepareTurnToolSnapshot, registerHarnessTools, registerTool, registerTools, requireTool, resetTools, } from './src/kernel/tools/mod.js';
75
+ export type { AuthUnauthenticatedPolicy, ContinueStopKind, CustomToolType, HttpMethod, PlaygroundAuthType, ToolAccess, ToolAuthType, ToolPermission, ToolType, TurnStopKind, } from './src/kernel/schema.js';
76
+ export { ATTACHMENT_ACCEPT_MIMES, AUTH_UNAUTHENTICATED_POLICIES, AWAITING_USER_INPUT_KINDS, AWAITING_USER_INPUT_STATUS, COMPACTION_METERS, COMPACTION_TIMINGS, CONTINUE_STOP_KINDS, catalogPathFor, coerceProtocol, coerceProvider, coerceSpeechFormat, DYNAMIC_FIELD_PARENTS, EXTRA_FIELDS, fieldMeta, HTTP_METHODS, isSpeechFormatAllowedForProtocol, isToolGateKind, isTurnInjectStage, isTurnStage, isValidPair, isValidProfileProtocol, KEY_SLOTS, LIVE_ACTIVITY_HANDLINGS, LIVE_CONTEXT_COMPRESSIONS, LIVE_SPEECH_SENSITIVITIES, MEDIA_INPUT_KIND_VALUES, MEDIA_INPUT_KINDS, MEDIA_WILDCARDS, OVERFLOW_KEY_SLOTS, PLAYGROUND_AUTH_TYPES, PROFILE_FIELDS, PROFILE_TYPE_PROTOCOLS, PROFILE_TYPES, PROTOCOL_PROVIDERS, PROTOCOLS, PROVIDERS, protocolsFor, protocolsForProfileType, providersFor, SCHEMA_ENFORCEMENTS, SPEECH_AUDIO_FORMATS, STREAM_MODES, SUMMARY_MODES, speechFormatsForProtocol, THINKING_LEVELS, TOOL_ACCESS, TOOL_AUTH_TYPES, TOOL_GATE_KINDS, TOOL_LOAD_TIERS, TOOL_PERMISSION, TOOL_TYPES, TURN_INJECT_STAGES, TURN_STAGES, TURN_STOP_KINDS, VOICE_ACCEPT_MIMES, } from './src/kernel/schema.js';
77
+ export type { AwaitingUserInput, StageAffordance, StageApplyInput, StageApplyOutput, StageApplyWarning, StageApplyWarningCode, StageContext, StageEventExtra, StageHandler, StageMutate, StageResult, } from './src/kernel/stages.js';
78
+ export { applyStageResult, isAwaitingUserInput, parseAwaitingUserInput, parseToolGate, STAGE_AFFORDANCE_MATRIX, STAGE_AFFORDANCES, stageAllowsAffordance, stageEventFields, } from './src/kernel/stages.js';
79
+ export type { ProfileTurnBehaviourSpec, ProfileTurnResumptionSpec, TurnContinueFrom, TurnStop, } from './src/kernel/stop.js';
80
+ export { AUTO_CONTINUE_DELAY_MS, CONTINUE_INSTRUCTION, DEFAULT_ALLOW_CONTINUE, DEFAULT_AUTO_CONTINUE, GenerationStopError, isContinueStopKind, isGenerationStopError, isResumeableStop, isUserCancelledStop, profileAllowsInject, profileAllowsSteering, profileTurnResumption, shouldAutoContinue, turnStopFromClientStreamEnd, turnStopFromInteractionStatus, turnStopFromOpenAiFinishReason, } from './src/kernel/stop.js';
81
+ export type { McpProtocolVersion, McpRpcResponse } from './src/kernel/tools/mod.js';
82
+ export { buildHttpToolTarget, executeHttpTool, executeMcpTool, formatToolResult, getTool, hasTool, invokeTool, isUnsupportedMcpProtocolError, listBuiltinIds, listFunctionIds, listTools, MCP_PROTOCOL_VERSIONS, parseMcpRpcResponse, prepareTurnToolSnapshot, registerHarnessTools, registerTool, registerTools, requireTool, resetTools, resolveToolAuth, } from './src/kernel/tools/mod.js';
63
83
  export type * from './src/kernel/types.js';
64
- export { jsonlSink, memorySink, noopSink, resolveTraceDir, sinkFromDir, writeTrace, } from './src/observability/trace.js';
65
- export type { TraceRecord } from './src/observability/trace-record.js';
84
+ export type { JsonlSinkOptions, JsonlTraceDestination, ProfileObservabilitySpec, ResolvedObservabilityPolicy, ResolvedTraceInclude, ResolvedTraceScrub, TraceDestination, TraceIncludeSpec, TraceRecord, TraceScrubSpec, TraceSink, } from './src/observability/mod.js';
85
+ export { clearTraceDestinations, getTraceDestination, isJsonlTraceDestination, isTraceSink, jsonlDestination, jsonlSink, listTraceDestinationIds, memorySink, noopSink, registerTraceDestination, requireTraceDestination, resolveObservabilityPolicy, resolveTraceDir, resolveTraceWriter, sinkFromDir, writeTrace, } from './src/observability/mod.js';
66
86
  export * from './src/presets/mod.js';
67
87
  export type { CreateProviderOptions, GeminiTransport, KeyVault, LocalProviderConfig, OpenAiGatewayConfig, } from './src/providers/mod.js';
68
88
  export { createProvider } from './src/providers/mod.js';
69
- export * from './src/interface/mod.js';
package/esm/mod.js CHANGED
@@ -11,24 +11,31 @@
11
11
  *
12
12
  * const profile = defineProfile({
13
13
  * id: "assistant.basic",
14
- * model: {
15
- * allow: ["gemini35FlashLite"],
16
- * config: {
17
- * gemini35FlashLite: {
18
- * apiId: "gemini-3.5-flash-lite",
19
- * thinking: { on: "high", off: "minimal" },
20
- * thinkingLevels: ["minimal", "low", "medium", "high"],
21
- * summaries: { on: "auto", off: "none" },
22
- * maxOutputTokens: 8192,
23
- * temperature: 1,
24
- * builtInTools: [],
25
- * },
14
+ * type: "text",
15
+ * identity: {
16
+ * handle: "assistant",
17
+ * system: "Answer plainly.",
18
+ * },
19
+ * models: {
20
+ * default: {
21
+ * protocol: "openAi",
22
+ * provider: "openrouter",
23
+ * apiId: "perplexity/sonar",
24
+ * efforts: { normal: "minimal" },
25
+ * summaries: false,
26
+ * maxOutputTokens: 8192,
27
+ * temperature: 1,
26
28
  * },
27
29
  * },
30
+ * maxSteps: 1,
28
31
  * tools: { allow: [] },
29
32
  * inputs: { text: true },
30
- * outputs: {},
31
- * guardrails: { quota: { perDay: 100 } },
33
+ * outputs: {
34
+ * streaming: { streamThoughts: false },
35
+ * },
36
+ * guardrails: {
37
+ * quota: { perDay: 100 },
38
+ * },
32
39
  * });
33
40
  *
34
41
  * registerProfile(profile);
@@ -38,22 +45,28 @@
38
45
  */
39
46
  import "./_dnt.polyfills.js";
40
47
  export { describeError, isAbortError, PUBLIC_CANARY, publicError, TheorumError, throwIfAborted, toErrorEvent, } from './src/guardrails/error.js';
41
- export { bindCanary, createCanaryGateSession, createCanaryStreamGate, createLiveOutboundGateSession, eventHasCanary, filterCanaryGatedEvents, finalizeLiveOutboundTurn, mintCanary, OMIT_CANARY, processLiveOutboundBatch, redactCanary, scanTextForCanaryLeak, standardEgressEnforce, wrapUserData, } from './src/guardrails/mod.js';
42
- export { clientIp, quotaMessage, releaseSlot, resetSlots, skipQuota, takeSlot, } from './src/guardrails/quota.js';
43
- export { PROJECT_ID_MAX, redactSensitiveOnly, sanitizeProjectId, sanitizeText, sanitizeTurnRequest, sanitizeTurnRequestForTrace, } from './src/guardrails/sanitize.js';
48
+ export { guardrailFromHits, guardrailFromVerdict, guardrailTurnEvent, projectGuardrailTurnEvent, } from './src/guardrails/events.js';
49
+ export { GUARDRAIL_MATCH_PREVIEW_MAX, hitFromSpan, matchPreview, projectGuardrailEvent, } from './src/guardrails/hits.js';
50
+ export { LEXICON_KEYS, lexiconDefault, lexiconText, overrideLexicon, resetLexicon, } from './src/guardrails/lexicon.js';
51
+ export { ADVISORY_LEVELS, bindCanary, checkTaintGate, collectEgressHits, composeToolText, createCanaryGateSession, createCanaryStreamGate, createLiveOutboundGateSession, createOutboundProgressiveGate, createProgressiveYieldGate, DEFAULT_HOLDBACK, DIRECTIVE_RULES, detectionForTrust, directiveHits, EGRESS_ON_BLOCK, EGRESS_RULES, eventHasCanary, filterCanaryGatedEvents, finalizeLiveOutboundTurn, GUARDRAIL_STAGES, guardToolFailureText, guardToolResult, hitRules, inspectToolArguments, isRemoteOrigin, isSuspicious, isTainted, looksDirective, mintCanary, OMIT_CANARY, processLiveOutboundBatch, recordTaint, redactCanary, resolveGuardrailPolicy, runEnforcer, SEVERITIES, scanTextForCanaryLeak, scanTextOf, standardEgressEnforce, TAINT_GATES, TOOL_CLOSE, TOOL_ORIGINS, TRUST_LEVELS, textForScan, toolCallEvent, wrapToolData, wrapUserData, } from './src/guardrails/mod.js';
52
+ export { assertSafeUrl, isLocalhostName, isPrivateOrLocalAddress, } from './src/guardrails/network.js';
53
+ export { clientIp, quotaExhausted, releaseSlot, resetSlots, skipQuota, takeSlot, } from './src/guardrails/quota.js';
54
+ export { detectionForProfile, detectText, PROJECT_ID_MAX, redactSensitiveOnly, sanitizeProjectId, sanitizeText, sanitizeTurnRequest, sanitizeTurnRequestForTrace, sanitizeTurnRequestWithEvents, } from './src/guardrails/sanitize.js';
44
55
  export { compactionMeter, compactionNeeded, estimateHistoryTokens, HISTORY_MEDIA_TOKENS, HISTORY_TEXT_ENCODING, resolveCompactionTokens, resolveHistoryTokens, shouldCompact, splitForCompaction, } from './src/kernel/engine/compaction.js';
45
56
  export { prepareLiveInboundText } from './src/kernel/engine/live-inbound.js';
57
+ export { assertLiveIngress, assertLiveIngressConfigured, hasAnyLiveIngress, liveIngressChannelDefault, liveIngressEnabled, liveIngressEnabledFromSpec, } from './src/kernel/engine/live-ingress.js';
46
58
  export { runTurn } from './src/kernel/engine/runner.js';
47
59
  export { runSession } from './src/kernel/engine/session/mod.js';
48
- export { assertAttachmentLimits, fileTooLargeMessage, maxBytesForMime, requireMediaLimits, resolveMediaLimits, sanitizeCsvText, sanitizeTurnBlobs, sanitizeTurnBlobsForProfile, tooManyFilesMessage, turnTooLargeMessage, } from './src/kernel/registry/attachments.js';
49
- export { clampThinkingLevel, clampThinkingLevelForApiId, mediaKindForMime, mimeAllowed, mimeEssence, modelEntryByApiId, requireModelSpec, } from './src/kernel/registry/catalog.js';
60
+ export { PROFILE_GRAPH, profileGraphFacet, spineFacetsForProfileType, } from './src/kernel/profile-graph.js';
61
+ export { assertAttachmentLimits, maxBytesForMime, requireMediaLimits, resolveMediaLimits, sanitizeCsvText, sanitizeTurnBlobs, sanitizeTurnBlobsForProfile, } from './src/kernel/registry/attachments.js';
62
+ export { clampThinkingLevel, clampThinkingLevelForApiId, mediaChannelForMime, mediaKindForMime, mimeAllowed, mimeEssence, modelEntryByApiId, requireModelBinding, } from './src/kernel/registry/catalog.js';
50
63
  export { clearProfiles, defineProfile, getProfile, hasProfile, listProfiles, registerProfile, registerProfiles, } from './src/kernel/registry/profiles.js';
51
64
  export { pickModel, projectProfile, resolveTurn } from './src/kernel/registry/resolve.js';
52
65
  export { getStructured, registerStructured } from './src/kernel/registry/schemas.js';
53
- export { ATTACHMENT_ACCEPT_MIMES, COMPACTION_METERS, COMPACTION_TIMINGS, CONTROL_IDS, catalogPathFor, coerceProtocol, coerceProvider, DYNAMIC_FIELD_PARENTS, EGRESS_ON_BLOCK, EXTRA_FIELDS, fieldMeta, isValidPair, isValidProfileProtocol, KEY_SLOTS, LIVE_ACTIVITY_HANDLINGS, LIVE_CONTEXT_COMPRESSIONS, LIVE_SPEECH_SENSITIVITIES, MEDIA_INPUT_KIND_VALUES, MEDIA_INPUT_KINDS, MEDIA_WILDCARDS, OVERFLOW_KEY_SLOTS, PROFILE_FIELDS, PROFILE_TYPE_PROTOCOLS, PROFILE_TYPES, PROTOCOL_PROVIDERS, PROTOCOLS, PROVIDERS, protocolsFor, protocolsForProfileType, providersFor, SCHEMA_ENFORCEMENTS, SPEECH_AUDIO_FORMATS, STREAM_MODES, SUMMARY_MODES, THINKING_LEVELS, TOOL_ACCESS, TOOL_LOAD_TIERS, TOOL_PERMISSION, TOOL_TYPES, TURN_STOP_KINDS, VOICE_ACCEPT_MIMES, } from './src/kernel/schema.js';
54
- export { AUTO_CONTINUE_DELAY_MS, CONTINUE_INSTRUCTION, DEFAULT_AUTO_CONTINUE, GenerationStopError, isGenerationStopError, isResumeableStop, isUserCancelledStop, shouldAutoContinue, turnStopFromClientStreamEnd, turnStopFromInteractionStatus, turnStopFromOpenAiFinishReason, } from './src/kernel/stop.js';
55
- export { formatToolResult, getTool, hasTool, invokeTool, listBuiltinIds, listFunctionIds, listTools, prepareTurnToolSnapshot, registerHarnessTools, registerTool, registerTools, requireTool, resetTools, } from './src/kernel/tools/mod.js';
56
- export { jsonlSink, memorySink, noopSink, resolveTraceDir, sinkFromDir, writeTrace, } from './src/observability/trace.js';
66
+ export { ATTACHMENT_ACCEPT_MIMES, AUTH_UNAUTHENTICATED_POLICIES, AWAITING_USER_INPUT_KINDS, AWAITING_USER_INPUT_STATUS, COMPACTION_METERS, COMPACTION_TIMINGS, CONTINUE_STOP_KINDS, catalogPathFor, coerceProtocol, coerceProvider, coerceSpeechFormat, DYNAMIC_FIELD_PARENTS, EXTRA_FIELDS, fieldMeta, HTTP_METHODS, isSpeechFormatAllowedForProtocol, isToolGateKind, isTurnInjectStage, isTurnStage, isValidPair, isValidProfileProtocol, KEY_SLOTS, LIVE_ACTIVITY_HANDLINGS, LIVE_CONTEXT_COMPRESSIONS, LIVE_SPEECH_SENSITIVITIES, MEDIA_INPUT_KIND_VALUES, MEDIA_INPUT_KINDS, MEDIA_WILDCARDS, OVERFLOW_KEY_SLOTS, PLAYGROUND_AUTH_TYPES, PROFILE_FIELDS, PROFILE_TYPE_PROTOCOLS, PROFILE_TYPES, PROTOCOL_PROVIDERS, PROTOCOLS, PROVIDERS, protocolsFor, protocolsForProfileType, providersFor, SCHEMA_ENFORCEMENTS, SPEECH_AUDIO_FORMATS, STREAM_MODES, SUMMARY_MODES, speechFormatsForProtocol, THINKING_LEVELS, TOOL_ACCESS, TOOL_AUTH_TYPES, TOOL_GATE_KINDS, TOOL_LOAD_TIERS, TOOL_PERMISSION, TOOL_TYPES, TURN_INJECT_STAGES, TURN_STAGES, TURN_STOP_KINDS, VOICE_ACCEPT_MIMES, } from './src/kernel/schema.js';
67
+ export { applyStageResult, isAwaitingUserInput, parseAwaitingUserInput, parseToolGate, STAGE_AFFORDANCE_MATRIX, STAGE_AFFORDANCES, stageAllowsAffordance, stageEventFields, } from './src/kernel/stages.js';
68
+ export { AUTO_CONTINUE_DELAY_MS, CONTINUE_INSTRUCTION, DEFAULT_ALLOW_CONTINUE, DEFAULT_AUTO_CONTINUE, GenerationStopError, isContinueStopKind, isGenerationStopError, isResumeableStop, isUserCancelledStop, profileAllowsInject, profileAllowsSteering, profileTurnResumption, shouldAutoContinue, turnStopFromClientStreamEnd, turnStopFromInteractionStatus, turnStopFromOpenAiFinishReason, } from './src/kernel/stop.js';
69
+ export { buildHttpToolTarget, executeHttpTool, executeMcpTool, formatToolResult, getTool, hasTool, invokeTool, isUnsupportedMcpProtocolError, listBuiltinIds, listFunctionIds, listTools, MCP_PROTOCOL_VERSIONS, parseMcpRpcResponse, prepareTurnToolSnapshot, registerHarnessTools, registerTool, registerTools, requireTool, resetTools, resolveToolAuth, } from './src/kernel/tools/mod.js';
70
+ export { clearTraceDestinations, getTraceDestination, isJsonlTraceDestination, isTraceSink, jsonlDestination, jsonlSink, listTraceDestinationIds, memorySink, noopSink, registerTraceDestination, requireTraceDestination, resolveObservabilityPolicy, resolveTraceDir, resolveTraceWriter, sinkFromDir, writeTrace, } from './src/observability/mod.js';
57
71
  export * from './src/presets/mod.js';
58
72
  export { createProvider } from './src/providers/mod.js';
59
- export * from './src/interface/mod.js';
@@ -16,7 +16,8 @@ import { bindCanary, eventHasCanary, mintCanary } from '../../guardrails/canary.
16
16
  import { sanitizeTurnRequest } from '../../guardrails/sanitize.js';
17
17
  import { runTurn } from '../../kernel/engine/runner.js';
18
18
  import { clearProfiles, registerProfile } from '../../kernel/registry/profiles.js';
19
- import { pickSystemRole, resolveTurn } from '../../kernel/registry/resolve.js';
19
+ import { resolveTurn } from '../../kernel/registry/resolve.js';
20
+ import { pickSystemRole } from '../../kernel/registry/system-role.js';
20
21
  import { buildRecord } from '../../observability/trace-record.js';
21
22
  const DEFAULT_CHUNKS = 200;
22
23
  const DEFAULT_ITERATIONS = 50;
@@ -31,23 +32,19 @@ function registerBenchProfile() {
31
32
  handle: 'bench',
32
33
  system: 'You are a benchmark stub.',
33
34
  },
34
- model: {
35
- protocol: 'openAi',
36
- provider: 'openrouter',
37
- allow: ['bench-model'],
38
- config: {
39
- 'bench-model': {
40
- apiId: 'bench-model',
41
- thinking: { on: 'none', off: 'none' },
42
- thinkingLevels: ['none'],
43
- summaries: { on: 'none', off: 'none' },
44
- maxOutputTokens: 4096,
45
- temperature: 0,
46
- builtInTools: [],
47
- },
35
+ models: {
36
+ 'bench-model': {
37
+ protocol: 'openAi',
38
+ provider: 'openrouter',
39
+ apiId: 'bench-model',
40
+ efforts: { normal: 'none' },
41
+ summaries: false,
42
+ maxOutputTokens: 4096,
43
+ temperature: 0,
44
+ builtInTools: [],
48
45
  },
49
- thinking: 'none',
50
46
  },
47
+ defaultModel: 'bench-model',
51
48
  tools: { allow: [] },
52
49
  inputs: { text: true },
53
50
  guardrails: {
@@ -8,10 +8,10 @@
8
8
  * @module
9
9
  */
10
10
  import { bindCanary, mintCanary, scanTextForCanaryLeak } from '../../guardrails/canary.js';
11
- import { createCanaryGateSession, filterCanaryGatedEvents } from '../../guardrails/canary-gate.js';
12
11
  import { buildCanaryEgressAttacks, FIXED_CANARY, } from '../../guardrails/corpus/canary-egress-attacks.js';
12
+ import { createLiveOutboundGateSession, finalizeLiveOutboundTurn, processLiveOutboundBatch, } from '../../guardrails/live-outbound-gate.js';
13
13
  import { yieldProviderEvents } from '../../kernel/engine/runner/stream.js';
14
- import { clearProfiles, registerProfile } from '../../kernel/registry/profiles.js';
14
+ import { clearProfiles, getProfile, registerProfile } from '../../kernel/registry/profiles.js';
15
15
  import { resolveTurn } from '../../kernel/registry/resolve.js';
16
16
  const FUZZ_PROFILE_ID = '__fuzz_canary__';
17
17
  function registerFuzzCanaryProfile() {
@@ -19,23 +19,19 @@ function registerFuzzCanaryProfile() {
19
19
  type: 'text',
20
20
  id: FUZZ_PROFILE_ID,
21
21
  identity: { handle: 'fuzz-canary', system: 'Canary fuzz profile.' },
22
- model: {
23
- protocol: 'openAi',
24
- provider: 'openrouter',
25
- allow: ['fuzz-model'],
26
- config: {
27
- 'fuzz-model': {
28
- apiId: 'fuzz-model',
29
- thinking: { on: 'none', off: 'none' },
30
- thinkingLevels: ['none'],
31
- summaries: { on: 'none', off: 'none' },
32
- maxOutputTokens: 4096,
33
- temperature: 0,
34
- builtInTools: [],
35
- },
22
+ models: {
23
+ 'fuzz-model': {
24
+ protocol: 'openAi',
25
+ provider: 'openrouter',
26
+ apiId: 'fuzz-model',
27
+ efforts: { normal: 'none' },
28
+ summaries: false,
29
+ maxOutputTokens: 4096,
30
+ temperature: 0,
31
+ builtInTools: [],
36
32
  },
37
- thinking: 'none',
38
33
  },
34
+ defaultModel: 'fuzz-model',
39
35
  tools: { allow: [] },
40
36
  inputs: { text: true },
41
37
  guardrails: { canary: true },
@@ -72,6 +68,7 @@ async function runStreamChannel(attack, generation, canary) {
72
68
  }
73
69
  }
74
70
  const events = await collectEvents(yieldProviderEvents({
71
+ profile: getProfile(FUZZ_PROFILE_ID),
75
72
  generation,
76
73
  system: bindCanary('fuzz system', canary),
77
74
  provider: { complete: mockProvider },
@@ -89,10 +86,10 @@ async function runStreamChannel(attack, generation, canary) {
89
86
  clientWire: clientVisibleWire(events),
90
87
  };
91
88
  }
92
- function runLiveBatchChannel(attack, canary) {
93
- const session = createCanaryGateSession(canary);
94
- const filtered = filterCanaryGatedEvents(session, attack.events);
95
- if (filtered.leaked) {
89
+ async function runLiveBatchChannel(attack, canary) {
90
+ const session = createLiveOutboundGateSession(getProfile(FUZZ_PROFILE_ID), canary);
91
+ const batch = await processLiveOutboundBatch(session, attack.events);
92
+ if (batch.action === 'withhold') {
96
93
  return {
97
94
  attack,
98
95
  channel: 'live.batch',
@@ -102,9 +99,9 @@ function runLiveBatchChannel(attack, canary) {
102
99
  clientWire: '',
103
100
  };
104
101
  }
105
- const emitted = [...filtered.events];
106
- const tail = session.gate.flush();
107
- if (tail.leak) {
102
+ const emitted = batch.action === 'emit' ? [...batch.events] : [];
103
+ const finalized = await finalizeLiveOutboundTurn(session);
104
+ if (finalized.action === 'withhold') {
108
105
  return {
109
106
  attack,
110
107
  channel: 'live.batch',
@@ -114,18 +111,17 @@ function runLiveBatchChannel(attack, canary) {
114
111
  clientWire: clientVisibleWire(emitted),
115
112
  };
116
113
  }
117
- if (tail.emit) {
118
- emitted.push({ type: session.lastStreamType ?? 'text', text: tail.emit });
114
+ if (finalized.action === 'emit') {
115
+ emitted.push(...finalized.events);
119
116
  }
120
117
  const bypassed = attack.shouldBlock && literalCanaryReachedClient(emitted, canary);
121
118
  const blocked = attack.shouldBlock && !bypassed;
122
- const falseAlarm = !attack.shouldBlock && filtered.leaked;
123
119
  return {
124
120
  attack,
125
121
  channel: 'live.batch',
126
122
  blocked,
127
123
  bypassed,
128
- falseAlarm,
124
+ falseAlarm: false,
129
125
  clientWire: clientVisibleWire(emitted),
130
126
  };
131
127
  }
@@ -181,7 +177,7 @@ export async function fuzzCanaryCommand(options) {
181
177
  const results = [];
182
178
  for (const attack of attacks) {
183
179
  results.push(await runStreamChannel(attack, generation, canary));
184
- results.push(runLiveBatchChannel(attack, canary));
180
+ results.push(await runLiveBatchChannel(attack, canary));
185
181
  }
186
182
  // Spot-check scan helper matches expectations
187
183
  if (!scanTextForCanaryLeak(canary, canary)) {