@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.
- package/CHANGELOG.md +44 -5
- package/README.md +10 -10
- package/dist/agent-definitions.js +1 -0
- package/dist/agent-run-lifecycle.js +11 -0
- package/dist/agent-run-state.d.ts +6 -0
- package/dist/agent-run-state.js +29 -9
- package/dist/agent-session/session/assemble.js +33 -2
- package/dist/agent-session/session/persist.js +6 -2
- package/dist/agent-session/session/tool-round.js +1 -0
- package/dist/agent-session/session/types.d.ts +10 -0
- package/dist/agent-session/session.d.ts +14 -0
- package/dist/agent-session/session.js +40 -3
- package/dist/artifacts.d.ts +39 -1
- package/dist/artifacts.js +73 -0
- package/dist/attention-compiler.d.ts +121 -0
- package/dist/attention-compiler.js +479 -0
- package/dist/cli-init.js +20 -6
- package/dist/context-budget.d.ts +20 -1
- package/dist/context-budget.js +10 -1
- package/dist/contracts-core/agent.d.ts +7 -0
- package/dist/contracts-core/attention.d.ts +66 -0
- package/dist/contracts-core/attention.js +2 -0
- package/dist/contracts-core/compaction.d.ts +59 -0
- package/dist/contracts-core/compaction.js +77 -1
- package/dist/contracts-core/provider.d.ts +4 -0
- package/dist/contracts-core.d.ts +1 -0
- package/dist/contracts-core.js +1 -0
- package/dist/contracts-protocol.d.ts +29 -0
- package/dist/contracts-run-state.d.ts +6 -0
- package/dist/host-composition.d.ts +78 -0
- package/dist/host-composition.js +248 -0
- package/dist/index.d.ts +9 -6
- package/dist/index.js +5 -4
- package/dist/input.d.ts +13 -1
- package/dist/input.js +40 -1
- package/dist/secure-agent.d.ts +2 -0
- package/dist/secure-agent.js +6 -1
- package/dist/tool-result-fold.d.ts +12 -0
- package/dist/tool-result-fold.js +13 -6
- package/dist/tools.d.ts +10 -0
- package/dist/tools.js +41 -0
- package/docs/acp-agent.md +42 -11
- package/docs/acp.md +2 -1
- package/docs/ag-ui.md +5 -3
- package/docs/agent-definitions.md +9 -1
- package/docs/agent-events.md +4 -1
- package/docs/agent-session-runtime.md +6 -6
- package/docs/attention-compiler.md +272 -0
- package/docs/cli-rpc.md +4 -2
- package/docs/coding-agent-tools.md +1 -1
- package/docs/coding-security.md +5 -3
- package/docs/coding-tools.md +1 -1
- package/docs/coding-workspaces.md +22 -0
- package/docs/compaction-and-retry.md +36 -4
- package/docs/compaction-observational-memory.md +62 -9
- package/docs/context-and-skills.md +4 -2
- package/docs/conversations.md +1 -1
- package/docs/dev-inspector.md +4 -0
- package/docs/device-adapters.md +1 -0
- package/docs/document-reader.md +11 -3
- package/docs/documents.md +10 -2
- package/docs/enterprise-postgres-state.md +2 -2
- package/docs/evaluations.md +168 -4
- package/docs/execution-timeline.md +180 -0
- package/docs/history/0.7.0-primitive-review.md +254 -0
- package/docs/history/migration-0.0.md +2 -2
- package/docs/history/release-handoffs.md +37 -1
- package/docs/host-compositions.md +147 -0
- package/docs/hosted-sandboxes.md +94 -0
- package/docs/index.md +58 -39
- package/docs/input-and-prompt-assembly.md +1 -0
- package/docs/knowledge-sync.md +84 -0
- package/docs/language-intelligence.md +1 -1
- package/docs/live-testing.md +4 -1
- package/docs/mcp-tools.md +2 -1
- package/docs/memory-fabric.md +416 -0
- package/docs/migrate-to-0.5.md +1 -1
- package/docs/migrate-to-0.6.md +1 -0
- package/docs/migrate-to-0.7.md +345 -0
- package/docs/migration.md +13 -1
- package/docs/model-routing.md +79 -4
- package/docs/multi-agent-patterns.md +20 -6
- package/docs/observability.md +52 -1
- package/docs/operations.md +13 -1
- package/docs/options-index.md +13 -1
- package/docs/peer-dependencies.md +6 -4
- package/docs/process-sessions.md +3 -1
- package/docs/prompt-registry.md +1 -1
- package/docs/provider-caching.md +4 -2
- package/docs/provider-conformance.md +1 -1
- package/docs/provider-packages.md +22 -22
- package/docs/providers/bedrock.md +71 -7
- package/docs/providers/openai.md +1 -1
- package/docs/rag.md +24 -8
- package/docs/realtime-voice.md +87 -0
- package/docs/release-and-install.md +36 -34
- package/docs/runs-and-usage.md +3 -2
- package/docs/server.md +5 -3
- package/docs/speech.md +2 -0
- package/docs/supervisors.md +33 -5
- package/docs/testing.md +1 -1
- package/docs/thinking-and-reasoning.md +3 -1
- package/docs/tools.md +6 -5
- package/docs/web-tools.md +2 -1
- package/docs/work-artifacts-and-review.md +14 -4
- package/docs/work-connectors.md +3 -1
- package/docs/work-tools.md +14 -4
- package/docs/workflows.md +69 -1
- package/docs/working-and-semantic-memory.md +25 -14
- package/package.json +1 -1
- package/templates/README.md +2 -0
- package/templates/business-worker/README.md.tmpl +19 -0
- package/templates/business-worker/env.example.tmpl +1 -0
- package/templates/business-worker/gitignore.tmpl +11 -0
- package/templates/business-worker/manifest.json +11 -0
- package/templates/business-worker/package.json.tmpl +23 -0
- package/templates/business-worker/src/agent.ts.tmpl +92 -0
- package/templates/business-worker/src/index.ts.tmpl +13 -0
- package/templates/business-worker/src/tests/agent.test.ts.tmpl +77 -0
- package/templates/business-worker/tsconfig.json.tmpl +15 -0
- package/templates/personal-assistant/README.md.tmpl +18 -0
- package/templates/personal-assistant/env.example.tmpl +1 -0
- package/templates/personal-assistant/gitignore.tmpl +11 -0
- package/templates/personal-assistant/manifest.json +11 -0
- package/templates/personal-assistant/package.json.tmpl +23 -0
- package/templates/personal-assistant/src/agent.ts.tmpl +65 -0
- package/templates/personal-assistant/src/index.ts.tmpl +13 -0
- package/templates/personal-assistant/src/tests/agent.test.ts.tmpl +28 -0
- package/templates/personal-assistant/tsconfig.json.tmpl +15 -0
package/docs/observability.md
CHANGED
|
@@ -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
|
|
package/docs/operations.md
CHANGED
|
@@ -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 `
|
|
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.
|
package/docs/options-index.md
CHANGED
|
@@ -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 **
|
|
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`,
|
|
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
|
|
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
|
package/docs/process-sessions.md
CHANGED
|
@@ -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
|
|
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`.
|
package/docs/prompt-registry.md
CHANGED
|
@@ -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
|
|
package/docs/provider-caching.md
CHANGED
|
@@ -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
|
|
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.
|
|
29
|
-
| `@arnilo/prism-providers/alibaba` | 0.
|
|
30
|
-
| `@arnilo/prism-providers/anthropic` | 0.
|
|
31
|
-
| `@arnilo/prism-providers/azure` | 0.
|
|
32
|
-
| `@arnilo/prism-providers/bedrock` | 0.
|
|
33
|
-
| `@arnilo/prism-providers/clinepass` | 0.
|
|
34
|
-
| `@arnilo/prism-providers/commandcode` | 0.
|
|
35
|
-
| `@arnilo/prism-providers/deepseek` | 0.
|
|
36
|
-
| `@arnilo/prism-providers/google` | 0.
|
|
37
|
-
| `@arnilo/prism-providers/hyper` | 0.
|
|
38
|
-
| `@arnilo/prism-providers/kimi` | 0.
|
|
39
|
-
| `@arnilo/prism-providers/model-discovery` | 0.
|
|
40
|
-
| `@arnilo/prism-providers/neuralwatt` | 0.
|
|
41
|
-
| `@arnilo/prism-providers/ollama` | 0.
|
|
42
|
-
| `@arnilo/prism-providers/openai` | 0.
|
|
43
|
-
| `@arnilo/prism-providers/opencode-go` | 0.
|
|
44
|
-
| `@arnilo/prism-providers/openrouter` | 0.
|
|
45
|
-
| `@arnilo/prism-providers/vertex` | 0.
|
|
46
|
-
| `@arnilo/prism-providers/xai` | 0.
|
|
47
|
-
| `@arnilo/prism-providers/zai` | 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
|
|
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
|
-
|
|
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.
|
|
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
|
|
package/docs/providers/openai.md
CHANGED
|
@@ -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
|
|