@arnilo/prism 0.6.0 → 0.7.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 (129) hide show
  1. package/CHANGELOG.md +44 -5
  2. package/README.md +10 -10
  3. package/dist/agent-definitions.js +1 -0
  4. package/dist/agent-run-lifecycle.js +11 -0
  5. package/dist/agent-run-state.d.ts +6 -0
  6. package/dist/agent-run-state.js +29 -9
  7. package/dist/agent-session/session/assemble.js +33 -2
  8. package/dist/agent-session/session/persist.js +6 -2
  9. package/dist/agent-session/session/tool-round.js +1 -0
  10. package/dist/agent-session/session/types.d.ts +10 -0
  11. package/dist/agent-session/session.d.ts +14 -0
  12. package/dist/agent-session/session.js +40 -3
  13. package/dist/artifacts.d.ts +39 -1
  14. package/dist/artifacts.js +73 -0
  15. package/dist/attention-compiler.d.ts +121 -0
  16. package/dist/attention-compiler.js +479 -0
  17. package/dist/cli-init.js +20 -6
  18. package/dist/context-budget.d.ts +20 -1
  19. package/dist/context-budget.js +10 -1
  20. package/dist/contracts-core/agent.d.ts +7 -0
  21. package/dist/contracts-core/attention.d.ts +66 -0
  22. package/dist/contracts-core/attention.js +2 -0
  23. package/dist/contracts-core/compaction.d.ts +59 -0
  24. package/dist/contracts-core/compaction.js +77 -1
  25. package/dist/contracts-core/provider.d.ts +4 -0
  26. package/dist/contracts-core.d.ts +1 -0
  27. package/dist/contracts-core.js +1 -0
  28. package/dist/contracts-protocol.d.ts +29 -0
  29. package/dist/contracts-run-state.d.ts +6 -0
  30. package/dist/host-composition.d.ts +78 -0
  31. package/dist/host-composition.js +248 -0
  32. package/dist/index.d.ts +9 -6
  33. package/dist/index.js +5 -4
  34. package/dist/input.d.ts +13 -1
  35. package/dist/input.js +40 -1
  36. package/dist/secure-agent.d.ts +2 -0
  37. package/dist/secure-agent.js +6 -1
  38. package/dist/tool-result-fold.d.ts +12 -0
  39. package/dist/tool-result-fold.js +13 -6
  40. package/dist/tools.d.ts +10 -0
  41. package/dist/tools.js +41 -0
  42. package/docs/acp-agent.md +42 -11
  43. package/docs/acp.md +2 -1
  44. package/docs/ag-ui.md +5 -3
  45. package/docs/agent-definitions.md +9 -1
  46. package/docs/agent-events.md +4 -1
  47. package/docs/agent-session-runtime.md +6 -6
  48. package/docs/attention-compiler.md +272 -0
  49. package/docs/cli-rpc.md +4 -2
  50. package/docs/coding-agent-tools.md +1 -1
  51. package/docs/coding-security.md +5 -3
  52. package/docs/coding-tools.md +1 -1
  53. package/docs/coding-workspaces.md +22 -0
  54. package/docs/compaction-and-retry.md +36 -4
  55. package/docs/compaction-observational-memory.md +62 -9
  56. package/docs/context-and-skills.md +4 -2
  57. package/docs/conversations.md +1 -1
  58. package/docs/dev-inspector.md +4 -0
  59. package/docs/device-adapters.md +1 -0
  60. package/docs/document-reader.md +11 -3
  61. package/docs/documents.md +10 -2
  62. package/docs/enterprise-postgres-state.md +2 -2
  63. package/docs/evaluations.md +168 -4
  64. package/docs/execution-timeline.md +180 -0
  65. package/docs/history/0.7.0-primitive-review.md +254 -0
  66. package/docs/history/migration-0.0.md +2 -2
  67. package/docs/history/release-handoffs.md +37 -1
  68. package/docs/host-compositions.md +147 -0
  69. package/docs/hosted-sandboxes.md +94 -0
  70. package/docs/index.md +58 -39
  71. package/docs/input-and-prompt-assembly.md +1 -0
  72. package/docs/knowledge-sync.md +84 -0
  73. package/docs/language-intelligence.md +1 -1
  74. package/docs/live-testing.md +4 -1
  75. package/docs/mcp-tools.md +2 -1
  76. package/docs/memory-fabric.md +416 -0
  77. package/docs/migrate-to-0.5.md +1 -1
  78. package/docs/migrate-to-0.6.md +1 -0
  79. package/docs/migrate-to-0.7.md +345 -0
  80. package/docs/migration.md +13 -1
  81. package/docs/model-routing.md +79 -4
  82. package/docs/multi-agent-patterns.md +20 -6
  83. package/docs/observability.md +52 -1
  84. package/docs/operations.md +13 -1
  85. package/docs/options-index.md +13 -1
  86. package/docs/peer-dependencies.md +6 -4
  87. package/docs/process-sessions.md +3 -1
  88. package/docs/prompt-registry.md +1 -1
  89. package/docs/provider-caching.md +4 -2
  90. package/docs/provider-conformance.md +1 -1
  91. package/docs/provider-packages.md +22 -22
  92. package/docs/providers/bedrock.md +71 -7
  93. package/docs/providers/openai.md +1 -1
  94. package/docs/rag.md +24 -8
  95. package/docs/realtime-voice.md +87 -0
  96. package/docs/release-and-install.md +36 -34
  97. package/docs/runs-and-usage.md +3 -2
  98. package/docs/server.md +5 -3
  99. package/docs/speech.md +2 -0
  100. package/docs/supervisors.md +33 -5
  101. package/docs/testing.md +1 -1
  102. package/docs/thinking-and-reasoning.md +3 -1
  103. package/docs/tools.md +6 -5
  104. package/docs/web-tools.md +2 -1
  105. package/docs/work-artifacts-and-review.md +14 -4
  106. package/docs/work-connectors.md +3 -1
  107. package/docs/work-tools.md +14 -4
  108. package/docs/workflows.md +69 -1
  109. package/docs/working-and-semantic-memory.md +25 -14
  110. package/package.json +1 -1
  111. package/templates/README.md +2 -0
  112. package/templates/business-worker/README.md.tmpl +19 -0
  113. package/templates/business-worker/env.example.tmpl +1 -0
  114. package/templates/business-worker/gitignore.tmpl +11 -0
  115. package/templates/business-worker/manifest.json +11 -0
  116. package/templates/business-worker/package.json.tmpl +23 -0
  117. package/templates/business-worker/src/agent.ts.tmpl +92 -0
  118. package/templates/business-worker/src/index.ts.tmpl +13 -0
  119. package/templates/business-worker/src/tests/agent.test.ts.tmpl +77 -0
  120. package/templates/business-worker/tsconfig.json.tmpl +15 -0
  121. package/templates/personal-assistant/README.md.tmpl +18 -0
  122. package/templates/personal-assistant/env.example.tmpl +1 -0
  123. package/templates/personal-assistant/gitignore.tmpl +11 -0
  124. package/templates/personal-assistant/manifest.json +11 -0
  125. package/templates/personal-assistant/package.json.tmpl +23 -0
  126. package/templates/personal-assistant/src/agent.ts.tmpl +65 -0
  127. package/templates/personal-assistant/src/index.ts.tmpl +13 -0
  128. package/templates/personal-assistant/src/tests/agent.test.ts.tmpl +28 -0
  129. package/templates/personal-assistant/tsconfig.json.tmpl +15 -0
@@ -13,6 +13,9 @@ APIs:
13
13
  - `createOpenTelemetryInstrumentation()`, `wrapOpenTelemetryApi()`, `createInMemoryTelemetry()` in `@arnilo/prism-core/governance/observability`
14
14
  - `createRagTelemetry()` in `@arnilo/prism-core/governance/observability` (RAG spans/events; see span tree below)
15
15
  - `handleRunFeedback()` / `handleEvaluation()` for explicit safe post-run projection
16
+ - `projectAgentTimeline()`, `projectTraceTimeline()`, `projectWorkflowTimeline()`, `createTimelineFolder()` — [execution timeline projection](execution-timeline.md) for host cockpits and trajectory evals
17
+ - `summarizeTimeline()`, `summarizeSession()` — [cockpit aggregations](#cockpit-aggregations-and-session-summaries) (bounded tool counts, token and cost rollups without double counting)
18
+ - `attachWorkflow()`, `handleWorkflowEvent()` on `OpenTelemetryInstrumentation` for workflow DAG spans and metrics
16
19
 
17
20
  ## When to use it
18
21
 
@@ -67,6 +70,10 @@ const telemetry = createOpenTelemetryInstrumentation({
67
70
 
68
71
  const detach = telemetry.attachSession(session);
69
72
  // or: for await (const event of session.subscribe()) telemetry.handleAgentEvent(event);
73
+
74
+ // Workflows:
75
+ const detachWorkflow = telemetry.attachWorkflow(eventBus);
76
+ // or: eventBus.subscribe((event) => telemetry.handleWorkflowEvent(event));
70
77
  ```
71
78
 
72
79
  Set `enabled: false` or omit `tracer`/`meter` for a no-op adapter. Feedback handlers accept only `runId`, rating/score, booleans, bounded counts, and fixed status — never comment, tag values, scorer/evaluation IDs, or arbitrary metadata.
@@ -97,6 +104,14 @@ OpenTelemetry mapping (when enabled):
97
104
  | `handleRunFeedback` | active-run `prism.run.feedback` event or ended-run span | `prism.run.feedback` |
98
105
  | `handleEvaluation` | active-run `gen_ai.evaluation.result` event or ended-run span | `prism.run.evaluation` (`status`) |
99
106
 
107
+ Workflow mapping (when enabled via `attachWorkflow` or `handleWorkflowEvent`):
108
+
109
+ | Workflow event | Span | Metric labels |
110
+ | --- | --- | --- |
111
+ | `workflow_started` / `workflow_finished` | `invoke_workflow {workflowId}` (`INTERNAL`) | `prism.workflow.duration` (`prism.workflow.id`, `prism.workflow.status`) |
112
+ | `node_started` / `node_finished` / `node_failed` / `node_skipped` | `prism.workflow.node {nodeId}` child (`INTERNAL`) | none (span attributes: `prism.node.kind`, `prism.node.status`) |
113
+ | `node_iteration_started` / `finished` | `prism.workflow.iteration` events on node span | none |
114
+
100
115
  RAG span tree (`@arnilo/prism-memory/rag` + `createRagTelemetry()`):
101
116
 
102
117
  | Span | Parent | Notes |
@@ -171,6 +186,41 @@ const ragTelemetry = createRagTelemetry({ tracer: memory.tracer, meter: memory.m
171
186
  const found = await retrieveContext("policy", { embedder, store, scope, telemetry: ragTelemetry }); // rag_request tree
172
187
  ```
173
188
 
189
+ ## Cockpit aggregations and session summaries
190
+
191
+ Host cockpits and dashboard cards need fast aggregate summaries of an execution without re-walking every raw event or risking prompt/secret leaks:
192
+
193
+ - `summarizeTimeline(timeline)`: rolls up an `ExecutionTimeline` into a `TimelineSummary` containing duration, turn count, tool call counts, provider attempts, total tokens, cost, error counts, and suspension state.
194
+ - `summarizeSession(timelines)`: rolls up an array of `ExecutionTimeline`s for a session/conversation into a `SessionSummary` with aggregated tokens, costs, run counts, and duration.
195
+
196
+ ```ts
197
+ import { summarizeTimeline, summarizeSession } from "@arnilo/prism-core/governance/observability";
198
+
199
+ const summary = summarizeTimeline(timeline);
200
+ // summary: TimelineSummary
201
+ // {
202
+ // durationMs: 1250,
203
+ // turnCount: 2,
204
+ // toolCallCount: 3,
205
+ // toolCounts: { search: 2, lookup: 1 },
206
+ // providerAttempts: 2,
207
+ // usage: { totalTokens: 450, promptTokens: 300, completionTokens: 150 },
208
+ // cost: { amount: 0.0012, currency: "USD" },
209
+ // errorCount: 0,
210
+ // blockedToolCount: 0,
211
+ // suspended: false,
212
+ // status: "succeeded",
213
+ // }
214
+
215
+ const sessionSummary = summarizeSession([run1Timeline, run2Timeline]);
216
+ // sessionSummary: SessionSummary
217
+ ```
218
+
219
+ Cardinality and correctness guarantees:
220
+ - **Bounded cardinality**: `toolCounts` is capped to `MAX_SUMMARY_DISTINCT_TOOLS = 64` distinct tool names. If more tools are invoked, lowest-frequency tool names overflow into an `"other"` bucket.
221
+ - **No double counting**: Token usage is derived from the root run's `run_total` (or aggregated across `turn` / `provider` steps if no run-level total exists), avoiding double counting between provider turn steps and run totals. Costs are rounded to 6 decimal places to prevent floating-point drift.
222
+ - **Payload-free**: Summaries contain counts, durations, status codes, and usage metrics only — zero prompt text, tool arguments, or credentials.
223
+
174
224
  ## Extension and configuration notes
175
225
 
176
226
  - Events flow through `redactAgentEvent` before subscribers and ledger writes — configure `createSecretRedactor` on the agent/run.
@@ -214,11 +264,12 @@ const entries = capture.events(); // oldest-first snapshot; capture.clear() rese
214
264
  - Capture middleware follows the same default: `redact: "secrets"` drops message content; buffers are capped and secrets are redacted unconditionally, so a captured buffer can be persisted or replayed without leaking credentials.
215
265
  - Use `identityTelemetryAttributes(identity)` when attaching enterprise identity to run metadata or OTel attributes; it emits `prism.identity.*` refs only (tenant/principal/scope counts), never credential secrets or raw tokens.
216
266
  - Opt-in content in other event types (`message_delta`, tool `result`) is still subject to `redactAgentEvent`.
217
- - Metric labels stay low-cardinality (`gen_ai.operation.name`, `gen_ai.provider.name`, token type, controlled outcome/status, feedback rating bucket/link presence); never use session/run/request/call IDs, model output, comments, tag values, scorer/evaluation IDs, or arbitrary metadata as labels. Token usage is recorded once at provider operation scope.
267
+ - Metric labels stay low-cardinality (`gen_ai.operation.name`, `gen_ai.provider.name`, token type, controlled outcome/status, feedback rating bucket/link presence, controlled `prism.workflow.id` names); never use session/run/request/call IDs, dynamic run IDs, model output, comments, tag values, scorer/evaluation IDs, or arbitrary metadata as labels. Token usage is recorded once at provider operation scope.
218
268
  - Target overhead when enabled is under 5% excluding exporter I/O; disabled hooks allocate no spans.
219
269
  - Provider transport limits and redaction order are documented in [Provider primitives](provider-primitives.md).
220
270
 
221
271
  ## Related APIs
272
+ - [Execution timeline](execution-timeline.md): cockpit projection — fold `AgentEvent` or `WorkflowEvent` into `ExecutionTimeline`.
222
273
  - [Agent identity](agent-identity.md): redacted identity attribute helper for telemetry.
223
274
  - [Evaluations](evaluations.md): optional scorers can link scores to run/session/trace IDs from agent events.
224
275
 
@@ -8,6 +8,7 @@ This page is the operator runbook for the high-availability story proven by plan
8
8
 
9
9
  - Before running any multi-replica deployment of the server, workflow coordinator, saga runner, ACP host, or enterprise dispatcher — read the local-registry limitations and the lease/fence model.
10
10
  - When an operator or on-call engineer sees a hung lease, an uncertain commit, or a split-brain suspicion: follow "Failover procedure" and "Uncertain commits" below before touching anything.
11
+ - When background workers share a checkpoint queue across tenants: use `admission` on `createWorkflowCoordinator` and `createPrismOperatorHandler` for inspect/cancel/reconcile. Do not add a second job broker.
11
12
  - When sizing leases: the failover ceiling is lease TTL plus the peer's acquisition poll interval; the drill asserts `failoverMs <= ttlMs + 5000`.
12
13
 
13
14
  ## Inputs / request
@@ -94,6 +95,16 @@ tenant's reads, writes, and lease takeover all fail closed.
94
95
  with bounded, jittered acquisition polls (no hot loops) and reports the
95
96
  measured numbers in the evidence JSON.
96
97
 
98
+ ## Fair worker admission and operator intervention
99
+
100
+ `createWorkflowCoordinator({ admission })` is still checkpoint+lease polling — not a job DSL. Each `pollOnce` walks at most `maxPagesPerPoll` list pages from a wrap cursor so a saturated first page cannot hide later tenants. `perTenant` / `perClass` cap **this worker's** concurrent claims. `deadlineMs` skips (does not auto-fail) stale `createdAt`. While `drain.isDraining`, no new claims; after `snapshot().expired`, in-flight work is aborted if the node honors the run signal. Leases are released only via the holder token — never deleted by hand.
101
+
102
+ `createPrismOperatorHandler({ authorize, checkpoints, workflows, unknownEffects? })` mounts `/ops/queue|suspended|failed|unknown` and `POST /ops/cancel|reconcile`. `authorize` is required and fail-closed; lists are ownership-scoped; bodies omit workflow input/state. Reconcile accepts only `completed` or `failed_terminal` plus optional evidence. Unknown effects are never retried from this route.
103
+
104
+ Metric hook labels: `outcome` and allowlisted `class` only.
105
+
106
+ Network-free composition: [`examples/server-deployment-seams.ts`](../examples/server-deployment-seams.ts).
107
+
97
108
  ## Live probe (plans/064 Task 9)
98
109
 
99
110
  The outbound webhook notifier has an operator-gated live probe against a receiver you own:
@@ -110,6 +121,7 @@ Probes: one signed delivery to your receiver (verify `x-prism-signature: sha256=
110
121
  - `LeaseStore` / `CheckpointStore` — the durable contracts this runbook relies on.
111
122
  - `createPostgresPersistence` — the PostgreSQL adapter used by the drill.
112
123
  - `ErpOutboxStore` — the idempotent side-effect carrier used to make replay safe.
113
- - `createWorkflowCoordinator` and `defineSaga`/`runSaga`/`resumeSaga` — higher-level consumers with the same fencing/cursor semantics.
124
+ - `createWorkflowCoordinator` (`admission`) and `createPrismOperatorHandler` — fair claim policy and ownership-scoped cancel/reconcile.
125
+ - `defineSaga`/`runSaga`/`resumeSaga` — higher-level consumers with the same fencing/cursor semantics.
114
126
  - `scripts/phase27-ha-worker.mjs` / `scripts/phase27-ha.test.mjs` — the reproducible drill; `docs/_evidence/phase27-ha-evidence.json` — the recorded run.
115
127
  - [Signed, hash-chained audit export](audit-export.md) — the cursor/CAS pattern applied to audit exports.
@@ -41,7 +41,7 @@ Field-level detail (defaults, bounds, failure modes) lives on the owning page
41
41
  `AgentLoopOptions`
42
42
 
43
43
  **Agent/session runtime** — [`agent-session-runtime.md`](agent-session-runtime.md)
44
- `AgentConfig`, `AgentRunResumeStreamOptions`, `AgentSessionCloneOptions`, `AgentSessionConfig`, `AgentSessionForkOptions`, `RunOptions`, `SteerOptions`
44
+ `AgentConfig`, `AgentRunResumeOptions`, `AgentRunResumeStreamOptions`, `AgentSessionCloneOptions`, `AgentSessionConfig`, `AgentSessionForkOptions`, `RunOptions`, `SteerOptions`
45
45
 
46
46
  **Evaluations** — [`evaluations.md`](evaluations.md)
47
47
  `ScoreRunOptions`
@@ -78,6 +78,12 @@ Field-level detail (defaults, bounds, failure modes) lives on the owning page
78
78
  **Working and semantic memory** — [`working-and-semantic-memory.md`](working-and-semantic-memory.md)
79
79
  `PostgresVectorStoreOptions`, `RecallScoringOptions`
80
80
 
81
+ **Memory fabric** — [`memory-fabric.md`](memory-fabric.md)
82
+ `CreateMemoryFabricOptions`, `MemoryFabricAttachOptions`, `MemoryFabricToolsOptions`, `MemoryFabricWriteOptions`, `MemoryFabricRecallOptions`, `MemoryFabricConsolidationOptions`, `MemoryFabricLinkerOptions`, `MemoryFabricEvolutionOptions`, `MemoryFabricConversationSearchOptions`, `CreateFabricFileJailOptions`
83
+
84
+ **Observational memory** — [`compaction-observational-memory.md`](compaction-observational-memory.md)
85
+ `ObservationalMemoryAppendOptions`, `WorkScopeControllerOptions`
86
+
81
87
  ## Provider and model connection
82
88
 
83
89
  **Model registry** — [`model-registry.md`](model-registry.md)
@@ -142,6 +148,9 @@ Field-level detail (defaults, bounds, failure modes) lives on the owning page
142
148
  **Context and skills** — [`context-and-skills.md`](context-and-skills.md)
143
149
  `ResolveActiveSkillsOptions`, `ResolveContextOptions`
144
150
 
151
+ **Attention compiler** — [`attention-compiler.md`](attention-compiler.md)
152
+ `AttentionCompilerOptions`, `AttentionInputCapOptions`, `AttentionCompileOptions`, `AttentionTruncationTriggerOptions`
153
+
145
154
  **Input and prompt assembly** — [`input-and-prompt-assembly.md`](input-and-prompt-assembly.md)
146
155
  `AssembleProviderInputOptions`, `PromptTemplateOptions`
147
156
 
@@ -223,6 +232,9 @@ Field-level detail (defaults, bounds, failure modes) lives on the owning page
223
232
  **Frontend interoperability (AG-UI and ACP)** — [`ag-ui.md`](ag-ui.md)
224
233
  `AgUiLimitOptions`
225
234
 
235
+ **Supervisors and subagents** — [`supervisors.md`](supervisors.md)
236
+ `CreateSupervisorOptions`, `SupervisorLimits`, `ResolvedSupervisorLimits`, `DelegationWaitOptions`, `CreateSpawnAgentToolOptions`, `CreateDelegationControlToolOptions`, `WorktreeChildFactoryOptions`, `ObserveSupervisorLifecycleOptions`
237
+
226
238
  ## CLI/RPC
227
239
 
228
240
  **Workflows** — [`workflows.md`](workflows.md)
@@ -11,7 +11,7 @@ Lists every third-party peer a Prism package declares, what importing that peer
11
11
  - Debugging a "peer not installed" error from a gated subpath.
12
12
  - Auditing which of your already-installed packages a Prism surface will reuse.
13
13
 
14
- Internal `@arnilo/*` peers are not listed here: every first-party package declares a required `@arnilo/prism` peer, and the release gate keeps all internal ranges locked to the cut version. This page covers the **11 third-party declarations across 6 packages**.
14
+ Internal `@arnilo/*` peers are not listed here: every first-party package declares a required `@arnilo/prism` peer, and the release gate keeps all internal ranges locked to the cut version. This page covers the **12 third-party declarations across 6 packages**.
15
15
 
16
16
  ## Matrix
17
17
 
@@ -24,6 +24,7 @@ One row per declaration. `Unlocks` names the subpath whose import reaches the pe
24
24
  | `@dietrichgebert/ponytail` | `^4.9.0` | yes | `@arnilo/prism-coding-tools` | `./ponytail` | `npm i @dietrichgebert/ponytail` | no |
25
25
  | `mammoth` | `^1.8.0` | yes | `@arnilo/prism-coding-tools` | `./document-reader` | `npm i mammoth` | no |
26
26
  | `pdf-parse` | `^2.4.5` | yes | `@arnilo/prism-coding-tools` | `./document-reader` | `npm i pdf-parse` | no |
27
+ | `e2b` | `2.49.1` | yes | `@arnilo/prism-coding-tools` | `./security` | `npm i e2b@2.49.1` | yes |
27
28
  | `better-sqlite3` | `^13.0.3` | yes | `@arnilo/prism-core` | `./sessions/sqlite`, `./governance/prompts` | `npm i better-sqlite3` | no |
28
29
  | `pg` | `^8.23.0` | yes | `@arnilo/prism-core` | `./sessions/postgres`, `./enterprise/postgres`, `./governance/prompts` | `npm i pg` | yes |
29
30
  | `@nats-io/jetstream` | `^3.4.0` | yes | `@arnilo/prism-core` | `./sessions/nats` | `npm i @nats-io/jetstream @nats-io/transport-node` | yes |
@@ -37,14 +38,15 @@ Two peers are pinned to an exact version instead of a range, because the pin is
37
38
 
38
39
  - **`playwright-core@1.63.0`** (`@arnilo/prism-web-tools/browser`, `/obscura`). Browser automation rides Playwright's CDP transport and accessibility snapshot shapes, which move between minors. Prism never launches, downloads, or bundles a browser: the host supplies the binary, the image, and the cache, and must match the pinned client. See [Browser automation](browser-automation.md).
39
40
  - **`@ai-sdk/provider@4.0.13`** (`@arnilo/prism-providers/ai-sdk`). The adapter consumes deterministic specification-versioned types (`LanguageModelV4`) and gates on an exact supported-version matrix at construction, so an unlisted version fails closed instead of silently mis-mapping. See [AI SDK provider](providers/ai-sdk.md).
41
+ - **`e2b@2.49.1`** (`@arnilo/prism-coding-tools/security`). Pause `keepMemory`, `Sandbox.connect` auto-resume, and `ServiceBusyError` 503 semantics are version-specific. Hosts may inject `{ client }` instead of installing the peer. See [Hosted sandboxes](hosted-sandboxes.md).
40
42
 
41
43
  `zod` is the only **required** third-party peer. `@agentclientprotocol/sdk` — a hard dependency of `@arnilo/prism-ag-ui` — declares `zod: ^3.25.0 || ^4.0.0` as its own peer, so `@arnilo/prism-ag-ui` re-declares the same range to keep the install tree satisfiable; the range is deliberately identical to the SDK's. Nothing in Prism imports zod directly.
42
44
 
43
45
  ## Peers that touch the network
44
46
 
45
- `pg`, `@nats-io/jetstream`, `@nats-io/transport-node`, and `playwright-core` open sockets. For a supply-chain review of those four:
47
+ `pg`, `@nats-io/jetstream`, `@nats-io/transport-node`, `playwright-core`, and `e2b` open sockets. For a supply-chain review of those five:
46
48
 
47
- - **Connection targets are host-owned.** Every one of them is passed a host-supplied connection string, endpoint list, browser instance, or service URL. Prism holds no default endpoint, and no peer is reachable from the root import.
49
+ - **Connection targets are host-owned.** Every one of them is passed a host-supplied connection string, endpoint list, browser instance, API key, or service URL. Prism holds no default endpoint, and no peer is reachable from the root import.
48
50
  - **Bytes stay local otherwise.** `better-sqlite3`, `mammoth`, `pdf-parse`, `@nanonets/graft`, and `@dietrichgebert/ponytail` are filesystem/process peers; the remaining two (`zod`, `@ai-sdk/provider`) are pure types/schemas.
49
51
  - **No secrets are read by the peers.** Prism resolves credentials through host providers and redacts them at the boundary; peers only ever receive a resolved connection string or model object. See [Credentials and redaction](credentials-and-redaction.md) and [Host security guide](host-security.md).
50
52
  - **Nothing is installed implicitly.** Optional peers are never auto-installed by npm; a missing one fails closed at the call site with a typed error naming the peer and the subpath. Required peers (today only `zod`) are installed by npm with the package.
@@ -84,7 +86,7 @@ const tools = await createBrowserTools({ browser });
84
86
  ## Security and performance notes
85
87
 
86
88
  - Pinned peers must be updated through the release process, not by a host override: an unpinned browser client or AI SDK type surface is a silent behavior change.
87
- - Peer installs are host-visible supply-chain additions. Prefer one peer per capability, keep them out of the root import, and audit transitive dependencies of the four network-touching peers in your own policy.
89
+ - Peer installs are host-visible supply-chain additions. Prefer one peer per capability, keep them out of the root import, and audit transitive dependencies of the five network-touching peers in your own policy.
88
90
  - Prism adds no runtime cost for an uninstalled peer; the failure is a typed error at first use.
89
91
 
90
92
  ## Related APIs
@@ -136,7 +136,8 @@ await sessions.dispose();
136
136
  - Host restart: call `reconcile()` on a new registry for in-memory orphans, or listen for `process_unknown` and wire Phase 7 `ToolEffectStore.markUnknown` in the host.
137
137
  - Expiry sweep runs on registry/handle access — no timers at import.
138
138
  - Command fingerprint is SHA-256 of `[command, ...args]` only (no env).
139
- - Docker reference adapter does not implement `startProcess` yet — fail closed until a capable runtime is wired.
139
+ - Docker sandbox (`createDockerSandbox`) implements `startProcess` returning a compliant `SandboxProcessHandle` with durable `ref` for attested reconnect. Process operations (`write`, bounded `onData` output, `wait`, `signal`, `kill`, `release`) compose with `ProcessSessions`. The sandbox `attachProcess(ref)` resolves an opaque `prism-docker-proc:` ref to a live in-memory handle with fail-closed validation (container ID, workspace, command fingerprint). `createDockerProcessRecoveryBackend(sandbox, options?)` provides a ready-made `ProcessRecoveryBackend` with optional `expectedContainerId`, `expectedWorkspace`, and `expectedLabels` assertions. When a sandbox is passed to `createProcessSessions` and has `attachProcess`, the recovery backend is wired automatically.
140
+ - Hosted E2B sandbox (`createE2BSandbox`) also implements `startProcess` / `attachProcess` with opaque `prism-e2b-proc:` refs (sandbox id, pid, command fingerprint, workspace). `createE2BProcessRecoveryBackend` mirrors the Docker backend (`expectedSandboxId` / `expectedWorkspace` / `expectedLabels`). Filesystem-only `pause({ keepMemory: false })` reports process loss: `attachProcess` returns null after that snapshot. `connectE2BSandbox` reconnects by sandbox id without auto-resume; call `resume()` explicitly. See [Hosted sandboxes](hosted-sandboxes.md).
140
141
 
141
142
  ## Durable process recovery (plan 026 Task 5)
142
143
 
@@ -199,4 +200,5 @@ optionally `recoveryBackend` + `recoveryLimits`. With durability configured:
199
200
  - [Coding agent tools](coding-agent-tools.md): one-shot `shell` vs long-running sessions.
200
201
  - [Language intelligence](language-intelligence.md): LSP servers may later register as managed sessions.
201
202
  - [Coding security](coding-security.md): `SandboxProcessHandle` / optional `DisposableSandbox.startProcess`.
203
+ - [Hosted sandboxes](hosted-sandboxes.md): E2B `pause`/`resume` and `prism-e2b-proc:` reconnect refs.
202
204
  - [Tool effects](tool-effects.md): unknown-outcome vocabulary mirrored by `markUnknown` / `process_unknown` / `reconcile`.
@@ -90,7 +90,7 @@ const v = await assertPromptPromotion({
90
90
  if (v.verdict === "promote") await store.put({ ...hostInput, body: v.candidate.body, labels: ["production"] });
91
91
  ```
92
92
 
93
- The verdict carries `promote`/`hold`, per-scorer `wins/losses/ties/failures`, `winRate`, the raw `ComparisonReport`, a redacted bounded `reportJson` (`serializeEvaluationReport`), and `reasons` on hold. The default gate holds unless the candidate wins strictly more scored comparisons than the baseline; `minimumWinRate` and `thresholds` add stricter gates, and threshold equality passes. Requires the optional peer `@arnilo/prism-core/governance/evals` (install it or the helper fails closed with `ERR_PRISM_PROMPT_EVALS_PEER`). Promotion itself stays a host decision: applying the verdict means `put`-ing a new version with labels — the helper never does.
93
+ The verdict carries `promote`/`hold`, per-scorer `wins/losses/ties/failures`, `winRate`, the raw `ComparisonReport`, a redacted bounded `reportJson` (`serializeEvaluationReport`), and `reasons` on hold. The default gate holds unless the candidate wins strictly more scored comparisons than the baseline; `minimumWinRate` and `thresholds` add stricter gates, and threshold equality passes. Requires the optional peer `@arnilo/prism-core/governance/evals` (install it or the helper fails closed with `ERR_PRISM_PROMPT_EVALS_PEER`). Promotion itself stays a host decision: applying the verdict means `put`-ing a new version with labels — the helper never does. When provenance tracking is required, evaluation experiments bind candidate prompt versions via `EvalManifest.promptId` and `promptVersion`; release evidence also calls `validateReleaseEvalManifest` (see [Evaluations](evaluations.md#repeated-trials-and-manifests)).
94
94
 
95
95
  ## Limits and security
96
96
 
@@ -166,7 +166,8 @@ Provider request policies can set `ProviderRequestOptions.cache` or the legacy `
166
166
  | `@arnilo/prism-providers/xai` | `implicit` | No `prompt_cache_key`. Package-local `x-grok-conv-id` is `sanitizeCacheKey(cache.key ?? cacheKey ?? sessionId, 128)`. | Same server + unchanged message prefix. Replay `reasoning_content` on reasoning models or the prefix breaks. | Conv-id is never a credential or SuperGrok token. Omitted when `cache.mode` is `off` or `cacheRetention` is `none`. `cached_tokens` → `cacheReadTokens` (inclusive or exclusive reports kept as-is). |
167
167
  | `@arnilo/prism-providers/clinepass` | `implicit` | No `cache_control` / `prompt_cache_key`. Gateway-owned prefix cache. | Resend unchanged prior history. Stream only. | Best-effort and backend-dependent (`cline-pass/*` slugs). `cached_tokens` / `prompt_cache_hit_tokens` map when present. |
168
168
  | `@arnilo/prism-providers/azure` | none | No Prism cache mapping. | Endpoint/model-specific. | Host owns Azure cache policy. |
169
- | `@arnilo/prism-providers/bedrock` | none | No Prism cache mapping. | Endpoint/model-specific. | Host owns Bedrock cache policy. |
169
+ | `@arnilo/prism-providers/bedrock` (`compatible`) | none | No Prism cache mapping. | Endpoint/model-specific. | Host owns Bedrock cache policy. |
170
+ | `@arnilo/prism-providers/bedrock` (`converse`) | `cache_control` | Prism breakpoints become standalone `cachePoint` blocks in `system`/message content; long retention adds `ttl: "1h"` when the model allows it. `tools` caching stays host-owned. | Stable prefix in the documented order `tools → system → messages`; changing an earlier section invalidates later ones. | `cacheReadInputTokens`/`cacheWriteInputTokens` map to `Usage.cacheReadTokens`/`Usage.cacheWriteTokens`; `inputTokens` is the non-cached remainder and is never folded. |
170
171
  | `@arnilo/prism-providers/vertex` | none | No Prism cache mapping. | Endpoint/model-specific. | Host owns Vertex cache policy. |
171
172
 
172
173
  Detailed first-party provider notes:
@@ -188,7 +189,7 @@ Detailed first-party provider notes:
188
189
  - DeepSeek (`@arnilo/prism-providers/deepseek`): `kind: "implicit"`. Official disk prefix cache is automatic (byte-identical prefix from token 0). Adapter sends no cache payload; tool `parameters` use shared `canonicalizeJsonSchema` (object keys + unordered `required` only; `enum`/`prefixItems`/`examples` keep caller order). `prompt_cache_hit_tokens` maps to `Usage.cacheReadTokens`. Caller-gated `listDeepSeekModels`.
189
190
  - xAI (`@arnilo/prism-providers/xai`): `kind: "implicit"`. Automatic prefix cache. Sticky `x-grok-conv-id` is a sanitized session/cache key (128 chars), never an OAuth access token. Reasoning models must replay `reasoning_content`. `prompt_tokens_details.cached_tokens` maps to `Usage.cacheReadTokens`. Caller-gated `listXaiModels`.
190
191
  - ClinePass (`@arnilo/prism-providers/clinepass`): `kind: "implicit"`. No explicit cache payload; multi-backend gateway may report `cached_tokens` or `prompt_cache_hit_tokens`. Static `cline-pass/*` catalog only — no `listClinePassModels`.
191
- - Azure, Bedrock, and Vertex: their OpenAI-compatible packages intentionally emit no Prism cache fields. Endpoint/model-specific cache controls remain host-owned rather than guessed from another provider family.
192
+ - Azure, Bedrock, and Vertex: their OpenAI-compatible packages intentionally emit no Prism cache fields. Endpoint/model-specific cache controls remain host-owned rather than guessed from another provider family. Bedrock's native `converse` route is the exception: it is a documented cache-control surface (`cachePoint`, shared `applyCacheControl` markers) and maps cache usage fields instead of leaving them host-owned.
192
193
 
193
194
  ### NeuralWatt cache-aware limiter
194
195
 
@@ -303,6 +304,7 @@ for (const sample of report.samples) {
303
304
  ## Related APIs
304
305
 
305
306
  - [Input and prompt assembly](input-and-prompt-assembly.md): opt-in cache-aware ordering for stable provider payload prefixes.
307
+ - [Attention compiler](attention-compiler.md): opt-in per-turn shrink that only rewrites rows *behind* the stable prefix, so cache hits survive.
306
308
  - [Provider request policies](provider-request-policies.md): set cache hints before provider calls.
307
309
  - [Model registry](model-registry.md): register `ModelConfig.cache` capability metadata.
308
310
  - [Provider layer](provider-layer.md): provider/model registries and provider events.
@@ -44,7 +44,7 @@ Offline conformance is mandatory for every package; credentialed probes are not
44
44
  | Ollama | cloud/local preset, reasoning/image mapping, implicit-cache fixture | Protected cloud or host-local authenticated daemon probe; no daemon starts in tests |
45
45
  | NeuralWatt | stream/retry/quota/telemetry fixtures, implicit-cache usage, headers/redaction | Protected `NEURALWATT_API_KEY` smoke |
46
46
  | Azure | endpoint preservation, Entra/resource-key header and OpenAI-compatible stream fixture | Protected host workload-identity probe |
47
- | Bedrock | SigV4/region/PrivateLink and OpenAI-compatible stream fixture | Protected host IAM/IRSA probe |
47
+ | Bedrock | SigV4/region/PrivateLink, OpenAI-compatible stream fixture, and native Converse fixtures: body mapping (messages/system/tools/media/reasoning/structured output/cachePoint), canonical event-stream frame bytes with CRC/limit/truncation refusals, capability refusals before network I/O | Protected host IAM/IRSA probe for both routes |
48
48
  | Vertex | location/endpoint preservation, ADC header and OpenAI-compatible stream fixture | Protected host ADC/WIF probe |
49
49
 
50
50
  All rows must retain bounded request/response fixtures, abort propagation, provider-owned-header precedence, and fake-secret leak assertions where the package surfaces those values. A successful fake transport proves Prism mapping, not account entitlement or vendor availability.
@@ -25,26 +25,26 @@ Do not use provider packages as a package manager, credential store, env loader,
25
25
 
26
26
  | adapter package | version |
27
27
  | --- | --- |
28
- | `@arnilo/prism-providers/ai-sdk` | 0.6.0 |
29
- | `@arnilo/prism-providers/alibaba` | 0.6.0 |
30
- | `@arnilo/prism-providers/anthropic` | 0.6.0 |
31
- | `@arnilo/prism-providers/azure` | 0.6.0 |
32
- | `@arnilo/prism-providers/bedrock` | 0.6.0 |
33
- | `@arnilo/prism-providers/clinepass` | 0.6.0 |
34
- | `@arnilo/prism-providers/commandcode` | 0.6.0 |
35
- | `@arnilo/prism-providers/deepseek` | 0.6.0 |
36
- | `@arnilo/prism-providers/google` | 0.6.0 |
37
- | `@arnilo/prism-providers/hyper` | 0.6.0 |
38
- | `@arnilo/prism-providers/kimi` | 0.6.0 |
39
- | `@arnilo/prism-providers/model-discovery` | 0.6.0 |
40
- | `@arnilo/prism-providers/neuralwatt` | 0.6.0 |
41
- | `@arnilo/prism-providers/ollama` | 0.6.0 |
42
- | `@arnilo/prism-providers/openai` | 0.6.0 |
43
- | `@arnilo/prism-providers/opencode-go` | 0.6.0 |
44
- | `@arnilo/prism-providers/openrouter` | 0.6.0 |
45
- | `@arnilo/prism-providers/vertex` | 0.6.0 |
46
- | `@arnilo/prism-providers/xai` | 0.6.0 |
47
- | `@arnilo/prism-providers/zai` | 0.6.0 |
28
+ | `@arnilo/prism-providers/ai-sdk` | 0.7.0 |
29
+ | `@arnilo/prism-providers/alibaba` | 0.7.0 |
30
+ | `@arnilo/prism-providers/anthropic` | 0.7.0 |
31
+ | `@arnilo/prism-providers/azure` | 0.7.0 |
32
+ | `@arnilo/prism-providers/bedrock` | 0.7.0 |
33
+ | `@arnilo/prism-providers/clinepass` | 0.7.0 |
34
+ | `@arnilo/prism-providers/commandcode` | 0.7.0 |
35
+ | `@arnilo/prism-providers/deepseek` | 0.7.0 |
36
+ | `@arnilo/prism-providers/google` | 0.7.0 |
37
+ | `@arnilo/prism-providers/hyper` | 0.7.0 |
38
+ | `@arnilo/prism-providers/kimi` | 0.7.0 |
39
+ | `@arnilo/prism-providers/model-discovery` | 0.7.0 |
40
+ | `@arnilo/prism-providers/neuralwatt` | 0.7.0 |
41
+ | `@arnilo/prism-providers/ollama` | 0.7.0 |
42
+ | `@arnilo/prism-providers/openai` | 0.7.0 |
43
+ | `@arnilo/prism-providers/opencode-go` | 0.7.0 |
44
+ | `@arnilo/prism-providers/openrouter` | 0.7.0 |
45
+ | `@arnilo/prism-providers/vertex` | 0.7.0 |
46
+ | `@arnilo/prism-providers/xai` | 0.7.0 |
47
+ | `@arnilo/prism-providers/zai` | 0.7.0 |
48
48
  <!-- generated:package-truth:providers end -->
49
49
 
50
50
 
@@ -61,7 +61,7 @@ Do not use provider packages as a package manager, credential store, env loader,
61
61
  | `@arnilo/prism-providers/hyper` | `api_key` only | No subscription OAuth — Charm Hyper is pay-per-use Hypercredits; host supplies `HYPER_API_KEY` (keys start `sk-hyper-`). |
62
62
  | `@arnilo/prism-providers/commandcode` | `api_key` only | No subscription OAuth — Command Code Go/GOAT/Pro/Max coding plans and the Provider plan all authenticate with the same Studio API key; host supplies `COMMAND_CODE_API_KEY`. |
63
63
  | `@arnilo/prism-providers/azure` | host Entra token or Azure resource key | Workload identity via `credential` callback; endpoint host preserved ([docs](providers/azure.md)). |
64
- | `@arnilo/prism-providers/bedrock` | host IAM/IRSA credentials | SigV4 over OpenAI-compatible Bedrock Runtime; region/PrivateLink preserved ([docs](providers/bedrock.md)). |
64
+ | `@arnilo/prism-providers/bedrock` | host IAM/IRSA credentials | SigV4 over either the OpenAI-compatible Bedrock Runtime route (default) or the native model-agnostic Converse/ConverseStream route (`api: "converse"`); region/PrivateLink preserved ([docs](providers/bedrock.md)). |
65
65
  | `@arnilo/prism-providers/vertex` | host ADC / workload token | OpenAPI-compatible Vertex endpoint; separate from consumer Google package ([docs](providers/vertex.md)). |
66
66
 
67
67
  A future provider-local OAuth package must first have explicit third-party permission and documented authorize/token/refresh flow. Before it registers an OAuth descriptor, it must add bounded request/response, abort, PKCE/state where required, expiry/refresh, secret-redaction, durable-store round-trip, and offline protocol tests. Do not add a generic OAuth framework, CLI credential scanner, automatic refresh timer, or success stub.
@@ -139,7 +139,7 @@ Every package remains explicit, setup-zero-fetch, and late-credential-bound. `Mo
139
139
  | xAI | OpenAI-compatible Completions; caller-gated list | text, image | tool deltas, `reasoning_content` replay | implicit + `x-grok-conv-id`; protected API-key smoke; SuperGrok login operator-only |
140
140
  | ClinePass | OpenAI-compatible stream-only; static `cline-pass/*` catalog | text | tool deltas, per-model `reasoning_effort` | implicit; protected API-key smoke |
141
141
  | Azure | Azure/Foundry OpenAI-compatible; host models | selected endpoint/model capability | normalized OpenAI-compatible tools | no Prism cache mapping; protected host workload-identity probe |
142
- | Bedrock | Bedrock OpenAI-compatible; host models | selected endpoint/model capability | normalized OpenAI-compatible tools | no Prism cache mapping; protected host IAM/IRSA probe |
142
+ | Bedrock | Bedrock OpenAI-compatible (default) or native Converse/ConverseStream; host models | selected endpoint/model capability; native route refuses denied/unknown capabilities before request | normalized OpenAI-compatible tools or Converse `toolSpec`/`toolUse` deltas | compatible route: no Prism cache mapping; native route maps `cachePoint` breakpoints; protected host IAM/IRSA probe |
143
143
  | Vertex | Vertex OpenAPI-compatible; host models | selected endpoint/model capability | normalized OpenAI-compatible tools | no Prism cache mapping; protected host ADC/WIF probe |
144
144
 
145
145
  ### First-party cache behavior
@@ -2,11 +2,54 @@
2
2
 
3
3
  ## What it does
4
4
 
5
- `@arnilo/prism-providers/bedrock` registers an Amazon Bedrock Runtime OpenAI-compatible Chat Completions provider. Hosts supply IAM/IRSA/assumed-role credentials; the package signs requests with SigV4 (no AWS SDK). Region and optional PrivateLink endpoint URLs are preserved.
5
+ `@arnilo/prism-providers/bedrock` registers an Amazon Bedrock Runtime provider with two explicit routes:
6
+
7
+ | Route | Wire API | Select with |
8
+ | --- | --- | --- |
9
+ | `compatible` (default) | OpenAI-compatible Chat Completions at `/openai/v1/chat/completions` | `createBedrockProvider` / `api: "compatible"` |
10
+ | `converse` | Native model-agnostic `Converse` and `ConverseStream` | `createBedrockConverseProvider` / `api: "converse"` |
11
+
12
+ Hosts supply IAM/IRSA/assumed-role credentials; the package signs requests with SigV4 (no AWS SDK). Region and optional PrivateLink endpoint URLs are preserved.
6
13
 
7
14
  ## When to use it
8
15
 
9
- Use it for enterprise Bedrock access under workload identity. Do not embed long-lived keys in fixtures. Use model-router residency policy to deny disallowed regions.
16
+ Use it for enterprise Bedrock access under workload identity. Do not embed long-lived keys in fixtures. Use model-router residency policy to deny disallowed regions. Use the `converse` route when the model only exists on Converse (tool use, reasoning, prompt caching, and structured output for Anthropic/Nova/OpenAI families), and keep `compatible` when an OpenAI-shaped gateway is what the deployment standardizes on.
17
+
18
+ ## Route selection
19
+
20
+ ```ts
21
+ import { createBedrockConverseProvider, createBedrockProviderPackage } from "@arnilo/prism-providers/bedrock";
22
+
23
+ // Package form: one provider id, selected route, optional non-streaming mode.
24
+ createBedrockProviderPackage({
25
+ region: "eu-west-1",
26
+ credential: () => hostAwsCredentials(),
27
+ api: "converse", // or "compatible" (default)
28
+ stream: true, // native route only: ConverseStream (default) vs one Converse call
29
+ models: [{ provider: "bedrock", model: "eu.anthropic.claude-haiku-4-5-20251001-v1:0" }],
30
+ });
31
+
32
+ // Factory form (same options, no registry wiring):
33
+ const provider = createBedrockConverseProvider({ region: "us-east-1", credential });
34
+ ```
35
+
36
+ Routes are mutually exclusive per provider id, so a host that needs both registers the second provider under a different `id` and model bindings. The package records the selected route in `ProviderPackage.metadata.route` and in the registered auth method metadata.
37
+
38
+ ## Capability matrix
39
+
40
+ | Capability | `compatible` | `converse` |
41
+ | --- | --- | --- |
42
+ | Text streaming | yes (OpenAI SSE) | yes (`ConverseStream` event stream) |
43
+ | Non-streaming | n/a (always streams) | yes (`stream: false`, one `Converse` response mapped to deltas + done) |
44
+ | Images | model-dependent OpenAI image parts | `image` blocks (`png`/`jpeg`/`gif`/`webp`); unknown media types refuse before the request |
45
+ | PDF documents | n/a | `document` blocks (`format` from media type); non-PDF files refuse |
46
+ | Tools | OpenAI `tools` | `toolConfig.tools[].toolSpec`, streamed `toolUse` deltas, `toolResult` in the following user turn |
47
+ | Reasoning/thinking | sanitized `reasoning_effort` / `reasoning` object | Anthropic-family `thinking` (`enabled`/`disabled`/`adaptive`, budget validated) and OpenAI-family `reasoning_effort` in `additionalModelRequestFields`; reasoning deltas map to Prism thinking blocks with signatures |
48
+ | Prompt caching | none (no Prism cache fields emitted) | `cachePoint` blocks from Prism cache breakpoints, `ttl: "1h"` for long retention; usage reports `cacheReadTokens` / `cacheWriteTokens` |
49
+ | Structured output | body passthrough only | `outputConfig.textFormat` JSON schema (requires `capabilities.structuredOutput`) |
50
+ | Usage | OpenAI usage | `inputTokens`/`outputTokens`/`totalTokens` + cache read/write |
51
+
52
+ Every feature above is tested offline against recorded frame/body fixtures; the live probe below covers text, tools, and usage. Features are not inferred from compatible endpoints.
10
53
 
11
54
  ## Inputs / request
12
55
 
@@ -34,6 +77,8 @@ Default public base: `https://bedrock-runtime.{region}.amazonaws.com` → `/open
34
77
 
35
78
  OpenAI-compatible SSE mapped to Prism provider events. Missing credentials fail closed before network I/O.
36
79
 
80
+ Native route: `ConverseStream` frames are decoded from `application/vnd.amazon.eventstream` (prelude/header lengths and both CRC32 checksums validated, 1 MiB default frame ceiling, 24 MiB hard spec ceiling) and mapped to Prism provider events. `:message-type: exception` frames become `error` events with the exception name and message; a stream that ends without `messageStop` or with an incomplete tool block fails loudly instead of returning partial output as success. Credentials are resolved once per request and redacted from provider errors.
81
+
37
82
  ## Request/response example
38
83
 
39
84
  ```http
@@ -51,11 +96,26 @@ const provider = createBedrockProvider({
51
96
  });
52
97
  ```
53
98
 
99
+ Native route request:
100
+
101
+ ```http
102
+ POST https://bedrock-runtime.eu-west-1.amazonaws.com/model/eu.anthropic.claude-haiku-4-5-20251001-v1%3A0/converse-stream
103
+ Accept: application/vnd.amazon.eventstream
104
+ Authorization: AWS4-HMAC-SHA256 Credential=…/eu-west-1/bedrock/aws4_request, …
105
+
106
+ { "messages": [{ "role": "user", "content": [{ "text": "hi" }] }],
107
+ "inferenceConfig": { "maxTokens": 4096 } }
108
+ ```
109
+
110
+ The `Converse` and `ConverseStream` operations share one request body; `accept` and the URL suffix select the operation. Inference-profile model ids (`eu.`/`us.` prefixes) are percent-encoded into the path, and region/endpoint policy is unchanged from the compatible route.
111
+
54
112
  Live canaries stay opt-in behind host credentials; default tests are network-free.
55
113
 
56
114
  ## Extension and configuration notes
57
115
 
58
- Uses Bedrock’s OpenAI-compatible runtime route (not Converse eventstream). Hosts needing Converse-only models should supply a custom provider or AI SDK bridge.
116
+ The compatible route uses Bedrock’s OpenAI-compatible runtime route (not Converse eventstream). The native route (`api: "converse"`) covers Converse-only models and features; both stay explicit, and neither silently falls back to the other.
117
+
118
+ Model-specific fields (for example `top_k`) come from `ModelConfig.parameters` leftovers plus the sanitized `compat.thinking` / `compat.reasoning_effort` keys; opaque `compat` keys are not spread onto the Converse body, and `toolChoice` is only forwarded when it is `auto`/`any`/`required` or `{ tool: { name } }`.
59
119
 
60
120
  ## Request construction (0.5.1)
61
121
 
@@ -71,12 +131,14 @@ See [Provider request policies](../provider-request-policies.md).
71
131
 
72
132
  ## Security and performance notes
73
133
 
74
- - No AWS SDK; package-local SigV4 only for `bedrock` service.
134
+ - No AWS SDK; package-local SigV4 only for `bedrock` service on both routes.
75
135
  - Input headers are normalized once before signing: names are lowercased and duplicate-case keys merge last-wins, so the canonical request always matches the signed header list (no duplicate-case mismatch); query parameters are canonicalized sorted by encoded key then value.
76
136
  - Private endpoint hosts are not rewritten to public DNS.
77
137
  - Conformance-proven (Task 6): package `setup()` performs zero fetch and zero credential resolution; an already-aborted signal fails fast; a truncated SSE stream (no `data: [DONE]`) ends in an `error` event; native Bedrock caching (`Converse cachePoint`) is intentionally unsupported on the OpenAI-compatible route — no cache wire fields are emitted even when the request carries Prism cache hints.
138
+ - Native route: `ConverseStream` frames are capped at 1 MiB (24 MiB hard spec ceiling) and a non-streaming `Converse` body is read under a 4 MiB ceiling (`BEDROCK_CONVERSE_RESPONSE_MAX_BYTES`), so a hostile or runaway response cannot exhaust memory.
139
+ - Native route: denied/unknown capabilities (`streaming: false` with the streaming route, `tools: false` with tools, `structuredOutput` undeclared, `reasoning: false` with a thinking/effort request, unsupported media types) refuse before any request is sent; corrupt or oversized event-stream frames terminate the stream rather than resyncing.
78
140
  - Credential secrets are redacted from provider errors.
79
- - No credential prefetch at import.
141
+ - No credential prefetch at import on either route.
80
142
 
81
143
  ## Live probe
82
144
 
@@ -87,11 +149,13 @@ PRISM_LIVE_PROVIDER_TESTS=1 AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... AWS_
87
149
  node --test packages/prism-providers/dist/bedrock/__tests__/live.test.js
88
150
  ```
89
151
 
90
- `PRISM_LIVE_BEDROCK_MODEL` overrides the probed model (default `us.anthropic.claude-haiku-4-5-20251001-v1:0`). Without credentials the suite skips.
152
+ `PRISM_LIVE_BEDROCK_MODEL` overrides the probed model (default `us.anthropic.claude-haiku-4-5-20251001-v1:0`). The same suite also probes the native route (streaming text/tools/usage and one non-streaming `Converse` call). Without credentials the suite skips.
91
153
 
92
154
  ## Thinking and reasoning
93
155
 
94
- Bedrock OpenAI-compat chat expects snake_case `reasoning_effort` (with `effort`/`reasoningEffort` aliases) or a sanitized `reasoning` object. OpenAI-family models on Bedrock snap effort to their declared levels (gpt-5.1 → `none/low/medium/high`); non-OpenAI models pass through untouched. See [Thinking and reasoning](../thinking-and-reasoning.md).
156
+ Compatible route: Bedrock OpenAI-compat chat expects snake_case `reasoning_effort` (with `effort`/`reasoningEffort` aliases) or a sanitized `reasoning` object. OpenAI-family models on Bedrock snap effort to their declared levels (gpt-5.1 → `none/low/medium/high`); non-OpenAI models pass through untouched.
157
+
158
+ Native route: Anthropic-family models take `additionalModelRequestFields.thinking` (`{type: "enabled"|"disabled"|"adaptive", budget_tokens?}`); a bare `enabled` gets a default budget so it can never reach the wire without one, and historical thinking blocks replay with signatures when `compat.preserveThinking` is on (default: when the model declares `capabilities.reasoning`). OpenAI-family models take `additionalModelRequestFields.reasoning_effort`, snapped to declared levels. See [Thinking and reasoning](../thinking-and-reasoning.md).
95
159
 
96
160
  ## Related APIs
97
161
 
@@ -52,7 +52,7 @@ uses official Responses `reasoning: { effort, summary? }` via
52
52
  | --- | --- |
53
53
  | Provider stream | Prism text, thinking (downgraded to text), host `tool_call` deltas/finals, provider-hosted `tool_call` events (`authority: "provider-hosted"`), `continuation_required`, `usage`, `done`, and redacted `error` events. |
54
54
  | Continuation | An incomplete Responses stream self-resumes at most eight HTTP hops using opaque `previous_response_id`; a cursor is at most 4 KiB, is never replayed, and is observable as `continuation_required`. |
55
- | Realtime | `createOpenAIRealtimeSession()` exposes server-session creation, audio in/out, transcript deltas, provider-hosted calls, interrupt, and idempotent close through the neutral `RealtimeSession` seam. |
55
+ | Realtime | `createOpenAIRealtimeSession()` exposes server-session creation, audio in/out, transcript deltas, host `function_call` items, provider-hosted calls, `usage`, `completeTool`, interrupt, and idempotent close through the neutral `RealtimeSession` seam. Host orchestration is [Realtime voice](../realtime-voice.md). |
56
56
  | Block preservation | User/system text → `input_text`; assistant text → `output_text`; assistant host `tool_call` → top-level `function_call` with `call_id`; provider-hosted calls are not replayed; `tool_result` → top-level `function_call_output`; images/files/audio when declared on the model. Bare thinking without an encrypted Responses reasoning item is omitted on replay. |
57
57
  | Auth methods | `api_key` for `openai`; host-invoked subscription `oauth` for `openai-codex`. xAI SuperGrok is the other first-party subscription OAuth flow ([xAI](xai.md)). |
58
58