@arnilo/prism 0.0.16 → 0.0.18
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 +33 -0
- package/README.md +9 -2
- package/dist/agent-run-state.js +13 -1
- package/dist/agents.js +42 -10
- package/dist/checkpoints.d.ts +4 -0
- package/dist/checkpoints.js +12 -0
- package/dist/cli-runner.d.ts +1 -5
- package/dist/cli-runner.js +5 -28
- package/dist/context-budget.js +10 -7
- package/dist/contracts.d.ts +13 -0
- package/dist/contributions.d.ts +2 -0
- package/dist/contributions.js +3 -0
- package/dist/credentials.d.ts +7 -1
- package/dist/credentials.js +6 -2
- package/dist/event-multiplexer.js +17 -1
- package/dist/extensions.d.ts +7 -1
- package/dist/extensions.js +64 -6
- package/dist/feedback.js +1 -1
- package/dist/guardrails.js +9 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/input.js +12 -5
- package/dist/middleware.js +9 -1
- package/dist/models.d.ts +2 -0
- package/dist/models.js +3 -0
- package/dist/providers/openai-compatible.d.ts +42 -1
- package/dist/providers/openai-compatible.js +109 -47
- package/dist/providers/transport.d.ts +6 -0
- package/dist/providers/transport.js +21 -0
- package/dist/providers.d.ts +2 -0
- package/dist/providers.js +3 -0
- package/dist/redaction.js +21 -7
- package/dist/retry.d.ts +5 -0
- package/dist/retry.js +8 -1
- package/dist/run-ledger.d.ts +6 -0
- package/dist/run-ledger.js +3 -9
- package/dist/session-stores.js +15 -11
- package/docs/0.1.0-readiness.md +35 -21
- package/docs/agent-events.md +2 -1
- package/docs/agent-session-runtime.md +3 -3
- package/docs/cli-rpc.md +1 -5
- package/docs/coding-agent-tools.md +10 -6
- package/docs/compaction-and-retry.md +3 -1
- package/docs/contribution-registries.md +1 -0
- package/docs/credentials-and-redaction.md +1 -1
- package/docs/extensions.md +1 -1
- package/docs/guardrails.md +13 -2
- package/docs/index.md +4 -4
- package/docs/input-and-prompt-assembly.md +6 -8
- package/docs/mcp-tools.md +3 -3
- package/docs/middleware-hooks.md +2 -2
- package/docs/migration.md +24 -1
- package/docs/provider-caching.md +1 -1
- package/docs/provider-conformance.md +1 -1
- package/docs/provider-packages.md +1 -1
- package/docs/providers/ai-sdk.md +2 -1
- package/docs/providers/openai-compatible.md +28 -1
- package/docs/public-contracts.md +2 -2
- package/docs/release-and-install.md +59 -17
- package/docs/session-stores.md +1 -1
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## What it does
|
|
4
4
|
|
|
5
|
-
`createDefaultInputBuilder()` turns common host input into Prism `Message[]` without starting an agent loop or calling a provider. It accepts strings, `Message`, or `Message[]`, and can add host-supplied instructions, history, summaries, attachments, explicit text resources, tool results, metadata
|
|
5
|
+
`createDefaultInputBuilder()` turns common host input into Prism `Message[]` without starting an agent loop or calling a provider. It accepts strings, `Message`, or `Message[]`, and can add host-supplied instructions, history, summaries, attachments, explicit text resources, tool results, and metadata. It never applies `input_assembly` middleware itself: `assembleProviderInput()` owns that hook and runs it exactly once after whichever `InputBuilder` is installed returns, so a custom builder cannot bypass it.
|
|
6
6
|
|
|
7
|
-
`createDefaultPromptBuilder()` composes messages, context blocks, selected skills, and host-supplied active tools into provider-ready messages. `assembleProviderInput()` wires input assembly, ordered context resolution, prompt middleware, and prompt composition into a `ProviderRequest` without calling a provider. Layered system prompts are composed before this helper and passed as `systemInstructions`. `renderPromptTemplate()` expands tiny `{{name}}` variables for CLI/RPC prompt strings before input assembly.
|
|
7
|
+
`createDefaultPromptBuilder()` composes messages, context blocks, selected skills, and host-supplied active tools into provider-ready messages. The `Available tools:` text listing is emitted only for models without declared tool support (`model.capabilities.tools !== true` — unknown capability keeps it, fail-safe for text-only providers); tool-capable models receive schemas via `request.tools` and skip the duplicated text. `assembleProviderInput()` wires input assembly, ordered context resolution, prompt middleware, and prompt composition into a `ProviderRequest` without calling a provider. Layered system prompts are composed before this helper and passed as `systemInstructions`. `renderPromptTemplate()` expands tiny `{{name}}` variables for CLI/RPC prompt strings before input assembly.
|
|
8
8
|
|
|
9
9
|
## When to use it
|
|
10
10
|
|
|
@@ -18,7 +18,6 @@ Do not use it for tool execution, provider calls, file discovery, credential loo
|
|
|
18
18
|
import { createDefaultInputBuilder } from "@arnilo/prism";
|
|
19
19
|
|
|
20
20
|
const messages = await createDefaultInputBuilder().build("Summarize", {
|
|
21
|
-
inputLayout: "legacy", // default; "cache_aware" passes the cache-aware layout preference
|
|
22
21
|
systemInstructions: "Be accurate.",
|
|
23
22
|
developerInstructions: "Cite supplied context only.",
|
|
24
23
|
history,
|
|
@@ -58,7 +57,7 @@ Useful exported types:
|
|
|
58
57
|
|
|
59
58
|
- `AgentInput`: `string | Message | readonly Message[]`.
|
|
60
59
|
- `DefaultInputBuilder`: the default `InputBuilder` with typed default context.
|
|
61
|
-
- `InputAssemblyLayout`: `"legacy" | "cache_aware"`;
|
|
60
|
+
- `InputAssemblyLayout`: `"legacy" | "cache_aware"`; `cache_aware` is default.
|
|
62
61
|
- `DefaultInputBuildContext`: optional input layout, instructions, history, summaries, attachments, resource loader/URIs, tool results, middleware, ids, metadata, and abort signal.
|
|
63
62
|
- `InputAttachment`: already-loaded text/content blocks (including `audio`, `file`, and `document`) or an explicit URI loaded through a caller-provided `ResourceLoader`.
|
|
64
63
|
- `PromptInstruction`: labeled system instruction text.
|
|
@@ -73,7 +72,7 @@ The builder returns `readonly Message[]`.
|
|
|
73
72
|
|
|
74
73
|
- String input becomes one user text message.
|
|
75
74
|
- `Message` and `Message[]` input are preserved.
|
|
76
|
-
-
|
|
75
|
+
- `cache_aware` layout is the default. Set `inputLayout: "legacy"` on the default builder, `assembleProviderInput()`, `AgentConfig`, or `RunOptions` to restore the prior order.
|
|
77
76
|
|
|
78
77
|
| Layout | Input message order |
|
|
79
78
|
| --- | --- |
|
|
@@ -87,8 +86,7 @@ The default prompt builder still prepends context, selected skills, and tool dec
|
|
|
87
86
|
- Tool results are tool messages containing `tool_result` content; the agent/session runtime uses this to feed dispatched tool results into the next provider turn, placing the assistant `tool_call` and the matching role `tool` `tool_result` before any final assistant content. Cache-aware layout keeps tool results before the current user suffix so it does not split tool transcripts.
|
|
88
87
|
- Middleware runs only when `middleware` is supplied in the context.
|
|
89
88
|
- `assembleProviderInput()` returns a `ProviderRequest` with the caller's model/tools/provider options/metadata/signal and composed messages/context. It also calls `assertMessagesSupportModelCapabilities()` so unsupported `audio`/`file`/`document`/`image` blocks fail with `UnsupportedModalityError` when the model declares `capabilities.input`.
|
|
90
|
-
- Optional `contextBudget` (at least one of `maxInputTokens` / `maxInputBytes`) runs after default message groups are built and before final flatten. Eviction drops droppable sections first (toolResults → history → summaries → context → skills → attachments; layout-aware). Protected instructions + current user `input` (+ tools catalog) fail closed with `ContextBudgetError` if they alone exceed the budget. When `reportOmissions: true`, attach `ProviderRequest.metadata[CONTEXT_BUDGET_REPORT_METADATA_KEY]` and read via `getContextBudgetReport(request)` (kinds/ids/sizes only — no secrets). Raw session store entries are never deleted.
|
|
91
|
-
- Optional `contextBudget` (at least one of `maxInputTokens` / `maxInputBytes`) runs after default message groups are built and before final flatten. Eviction drops droppable sections first (toolResults → history → summaries → context → skills → attachments; layout-aware). Protected instructions + current user `input` (+ tools catalog) fail closed with `ContextBudgetError` if they alone exceed the budget. When `reportOmissions: true`, attach `ProviderRequest.metadata[CONTEXT_BUDGET_REPORT_METADATA_KEY]` and read via `getContextBudgetReport(request)` (kinds/ids/sizes only — no secrets). Raw session store entries are never deleted.
|
|
89
|
+
- Optional `contextBudget` (at least one of `maxInputTokens` / `maxInputBytes`) runs after default message groups are built and before final flatten. Eviction drops droppable sections first (toolResults → history → summaries → context → skills → attachments; layout-aware). Within `history`, oldest messages drop first. Protected instructions + current user `input` (+ tools catalog) fail closed with `ContextBudgetError` if they alone exceed the budget. When `reportOmissions: true`, attach `ProviderRequest.metadata[CONTEXT_BUDGET_REPORT_METADATA_KEY]` and read via `getContextBudgetReport(request)` (kinds/ids/sizes only — no secrets). Raw session store entries are never deleted.
|
|
92
90
|
- `renderPromptTemplate()` replaces top-level `{{name}}` variables with caller-supplied JSON-compatible values. Strings are inserted directly; numbers, booleans, `null`, arrays, and objects are stringified deterministically with sorted object keys. Missing variables throw by default or stay unchanged with `{ missing: "preserve" }`.
|
|
93
91
|
|
|
94
92
|
## Request/response example
|
|
@@ -161,7 +159,7 @@ const request = await assembleProviderInput({
|
|
|
161
159
|
});
|
|
162
160
|
```
|
|
163
161
|
|
|
164
|
-
`input_assembly`, `context`, and `prompt_build` middleware are not global. They run only for helper calls that receive a `MiddlewareRegistry`, in that assembly order. `assembleProviderInput()` keeps provider `tools` equal to the host-supplied active tool list after prompt middleware.
|
|
162
|
+
`input_assembly`, `context`, and `prompt_build` middleware are not global. They run only for helper calls that receive a `MiddlewareRegistry`, in that assembly order. Inside `assembleProviderInput()`, `input_assembly` always runs — for both the default and any custom `InputBuilder`, and on both the plain and context-budget paths. `assembleProviderInput()` keeps provider `tools` equal to the host-supplied active tool list after prompt middleware.
|
|
165
163
|
|
|
166
164
|
## Security and performance notes
|
|
167
165
|
|
package/docs/mcp-tools.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## What it does
|
|
4
4
|
|
|
5
|
-
`@arnilo/prism-mcp` has two explicit directions. Its client bridge connects hosts to remote [Model Context Protocol](https://modelcontextprotocol.io) servers and maps discovered tools to ordinary `ToolDefinition`s. Its server API registers selected Prism `ToolDefinition` and `CommandDefinition` values on the official SDK `McpServer`, with required authorization and a bounded optional Web-standard Streamable HTTP handler. The package pins `@modelcontextprotocol/sdk` **1.
|
|
5
|
+
`@arnilo/prism-mcp` has two explicit directions. Its client bridge connects hosts to remote [Model Context Protocol](https://modelcontextprotocol.io) servers and maps discovered tools to ordinary `ToolDefinition`s. Its server API registers selected Prism `ToolDefinition` and `CommandDefinition` values on the official SDK `McpServer`, with required authorization and a bounded optional Web-standard Streamable HTTP handler. The package pins `@modelcontextprotocol/sdk` **1.30.0** (MCP protocol negotiation remains SDK-owned) and adds no MCP branch to core Prism.
|
|
6
6
|
|
|
7
7
|
Primary API:
|
|
8
8
|
|
|
@@ -33,7 +33,7 @@ await bridge.listResources();
|
|
|
33
33
|
await bridge.getPrompt("review", { topic: "security" });
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
Server capability matrix for SDK 1.
|
|
36
|
+
Server capability matrix for SDK 1.30.0: tools/resources/prompts and their list-change notifications are supported through official registrations; roots/sampling/form+URL elicitation are supported as explicit client callbacks. Missing server resources/prompts throw `McpUnsupportedCapabilityError` with `ERR_PRISM_MCP_UNSUPPORTED_CAPABILITY`. Resource/prompt results and sampling/elicitation inputs/results are bounded JSON. Accepted form/URL elicitation requires host-only `humanInteraction: true`; bridge strips marker before protocol output and fails closed when absent. Automatic root discovery/consent, model selection, credential resolution, URL navigation, generic command proxying, and custom JSON-RPC are unsupported.
|
|
37
37
|
|
|
38
38
|
Server direction:
|
|
39
39
|
|
|
@@ -61,7 +61,7 @@ const handleMcp = await createPrismMcpWebHandler(server, {
|
|
|
61
61
|
});
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
-
`McpServer.connect(transport)` remains available for SDK stdio or in-memory transports. The helper uses SDK `WebStandardStreamableHTTPServerTransport`; it does not start a listener. Default remains bounded stateless JSON-response mode. Supplying `sessionIdGenerator` enables SDK `MCP-Session-Id` POST/GET/DELETE/SSE lifecycle and requires exact `allowedOrigins` plus host `resolveIdentity`. Every request re-authenticates, and a different principal receives non-disclosing 404. SDK owns protocol-version/session headers and SSE semantics. SDK 1.
|
|
64
|
+
`McpServer.connect(transport)` remains available for SDK stdio or in-memory transports. The helper uses SDK `WebStandardStreamableHTTPServerTransport`; it does not start a listener. Default remains bounded stateless JSON-response mode. Supplying `sessionIdGenerator` enables SDK `MCP-Session-Id` POST/GET/DELETE/SSE lifecycle and requires exact `allowedOrigins` plus host `resolveIdentity`. Every request re-authenticates, and a different principal receives non-disclosing 404. SDK owns protocol-version/session headers and SSE semantics. SDK 1.30.0's in-memory event store is not enabled, so `Last-Event-ID` replay is explicitly unsupported; reconnect starts only through SDK-supported active session GET.
|
|
65
65
|
|
|
66
66
|
## When to use it
|
|
67
67
|
|
package/docs/middleware-hooks.md
CHANGED
|
@@ -43,11 +43,11 @@ Built-in hook names:
|
|
|
43
43
|
| `run(hook, value)` | hook name and payload | Runs registered middleware and returns the final payload. |
|
|
44
44
|
| `list(hook)` | hook name | Returns registered middleware for inspection. |
|
|
45
45
|
|
|
46
|
-
`Middleware<T>` receives `(value, next)` and returns a value or promise. Calling `next(updatedValue)` passes an updated value to later middleware.
|
|
46
|
+
`Middleware<T>` receives `(value, next)` and returns a value or promise. Calling `next(updatedValue)` passes an updated value to later middleware. Two rules are enforced: call `next()` **at most once** — a second call throws (routed through the registry `errorPolicy`) naming hook and index; and **either** `return next(v)` **or** return a new value, never both — when `next(v)` was already called, a conflicting return is discarded and diagnosed via `onError` (the `next()` value wins).
|
|
47
47
|
|
|
48
48
|
## Outputs / response / events
|
|
49
49
|
|
|
50
|
-
`run()` returns the transformed value. If no middleware is registered for a hook, `run()` returns the original value. `assembleProviderInput()` calls Phase 5 hooks in this order when middleware is supplied: `input_assembly`, then `context`, then `prompt_build`. The agent/session runtime applies configured provider request policies, then invokes `provider_request` once with the `ProviderRequest` before `AIProvider.generate()`, invokes `tool_call` and `tool_result` through `dispatchToolCall()` for complete provider tool calls, invokes `compaction` with `{ context, result }` after a compaction strategy returns and before the runtime appends its standard compaction entry, and invokes `retry` with `{ context, decision }` before scheduling a provider-turn retry. There is no `provider_response` hook; observing provider output belongs to the provider adapter or subscriber events.
|
|
50
|
+
`run()` returns the transformed value. If no middleware is registered for a hook, `run()` returns the original value. `assembleProviderInput()` calls Phase 5 hooks in this order when middleware is supplied: `input_assembly`, then `context`, then `prompt_build`. The `input_assembly` call is unconditional — it runs after whatever `InputBuilder` produced the messages, so host middleware at that hook cannot be skipped by a custom builder. The agent/session runtime applies configured provider request policies, then invokes `provider_request` once with the `ProviderRequest` before `AIProvider.generate()`, invokes `tool_call` and `tool_result` through `dispatchToolCall()` for complete provider tool calls, invokes `compaction` with `{ context, result }` after a compaction strategy returns and before the runtime appends its standard compaction entry, and invokes `retry` with `{ context, decision }` before scheduling a provider-turn retry. There is no `provider_response` hook; observing provider output belongs to the provider adapter or subscriber events.
|
|
51
51
|
|
|
52
52
|
With default `errorPolicy: "event"`, middleware errors become `extension_error` events when `onError` is provided, and later middleware still runs with the current value. With `errorPolicy: "throw"`, `run()` rejects on the first middleware error.
|
|
53
53
|
|
package/docs/migration.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Migration guide
|
|
2
2
|
|
|
3
|
+
## 0.0.17 → 0.0.18 restore integrity (small intentional break)
|
|
4
|
+
|
|
5
|
+
Release **0.0.18** removes model-facing regex from `repo_search`:
|
|
6
|
+
|
|
7
|
+
1. **`repo_search` literal only.** The tool schema no longer advertises `mode: "regex"`. Passing `mode: "regex"` returns a bounded tool error. `compileSearchPattern(query, caseSensitive, maxPatternBytes)` dropped the `mode` argument; hosts calling it with the old signature must update imports. Use literal substring search or a host-owned search backend for regex needs.
|
|
8
|
+
2. **`write` / `edit` crash-safe replace.** Default local operations write to a same-directory `.prism-write-*` temp file then `rename` onto the target, so a crash mid-write cannot truncate the original. Happy-path ToolResult shape unchanged. Custom `WriteOperations` / `EditOperations` should provide equivalent durability.
|
|
9
|
+
3. **`contextBudget` history eviction.** Under pressure, `applyContextBudget` drops oldest history messages first (not newest). Hosts that relied on newest-first history retention under budget should revisit eviction expectations.
|
|
10
|
+
4. **Default `inputLayout` is `cache_aware`.** Unset `AgentConfig.inputLayout` / `RunOptions.inputLayout` now use cache-stable ordering (attachments/resources and tool results before current input). Set `inputLayout: "legacy"` to restore the prior order.
|
|
11
|
+
5. **`@arnilo/prism-mcp` SDK bump.** `@modelcontextprotocol/sdk` is pinned to **1.30.0** (from 1.29.0), clearing the moderate `@hono/node-server` path-traversal advisory on the MCP HTTP transport. No Prism MCP public API signature changes; hosts pinning the SDK independently should align to 1.30.0+.
|
|
12
|
+
|
|
13
|
+
Docs-only: README provider inventory (14 adapters), optional `@arnilo/prism-browser` wording, and `docs/0.1.0-readiness.md` current-line status were corrected; no runtime behavior change beyond the items above.
|
|
14
|
+
|
|
15
|
+
## 0.0.16 → 0.0.17 code-review hardening (small intentional breaks)
|
|
16
|
+
|
|
17
|
+
Release **0.0.17** implements the 2026-07-29 full implementation review (plan 081): twenty fixes across durable runs, guardrails, retry, extension lifecycle, CLI, and provider plumbing. Most changes are additive or internal; four intentionally change existing behavior:
|
|
18
|
+
|
|
19
|
+
1. **CLI: inert flags now rejected.** `--config`, `--resource`, `--extension`, and `--tool` were parsed-and-recorded without effect; `parseCliArgs` now throws `CliUsageError("<flag> is not supported in this build")`. The dead `config` / `resources` / `extensions` / `tools` fields were removed from `CliOptions`. Hosts passing those flags must drop them until a CLI-harness plan wires them.
|
|
20
|
+
2. **`ExtensionKernel.load()` returns handles.** `load(extensions)` now resolves to `LoadedExtension[]` (`{ name, dispose() }`) instead of `void`; callers ignoring the return value are unaffected. A failed `setup` now unwinds that extension's partial registrations. Contribution registries, `ProviderRegistry`, and `ModelRegistry` gain `unregister(...)` (additive).
|
|
21
|
+
3. **Default prompt builder omits the tool text list for tool-capable models.** When `model.capabilities.tools === true`, the `Available tools:` system message is no longer emitted (schemas already travel via `request.tools`); unknown/`false` capability keeps it. Saves duplicated tokens per turn; observable only in prompt text.
|
|
22
|
+
4. **Default retry policy applies jitter and honors Retry-After.** `createDefaultRetryPolicy` now applies ±25% jitter (`jitter`/`random` options) and honors `error.retryAfterMs` (populated from provider `Retry-After` headers), capped by `maxDelayMs`. Delays are no longer deterministic unless `random` is injected.
|
|
23
|
+
|
|
24
|
+
Additive-only highlights: `MemoryCredentialStoreOptions.allowProviderFallback` (strict provider scoping opt-in), `createMemoryCheckpointStore` `maxRecords`/`maxValueBytes` bounds, `ShellToolOptions.envAllowlist`, guardrail `steer_rejected` event, `ErrorInfo.retryAfterMs`, agent fingerprint now covers instructions/system prompt/skills (existing durable runs resume or fail fingerprint exactly as before — the fingerprint only got stricter).
|
|
25
|
+
|
|
3
26
|
## What it does
|
|
4
27
|
|
|
5
28
|
Prism 0.0.6 preserves documented 0.0.3 agent construction except for two intentional Phase 3 public-API cleanups:
|
|
@@ -44,7 +67,7 @@ Realtime is opt-in through `createOpenAIRealtimeSession({ model, ownerId, apiKey
|
|
|
44
67
|
|
|
45
68
|
## 0.0.14 → 0.0.15 AI SDK adapter matrix (additive, pre-release)
|
|
46
69
|
|
|
47
|
-
`@arnilo/prism-provider-ai-sdk` now pins and verifies `@ai-sdk/provider@4.0.
|
|
70
|
+
`@arnilo/prism-provider-ai-sdk` now pins and verifies `@ai-sdk/provider@4.0.4` at setup (matrix also lists `4.0.3`) rather than accepting any v4 minor. Upgrade the peer package to the documented matrix entry. An unlisted installed version fails with typed `AiSdkProviderError` code `unsupported_version`; add a tested matrix row before changing it.
|
|
48
71
|
|
|
49
72
|
Stream output now maps `response-metadata.id` to `message_start`, preserves `providerExecuted` tool authority as `"provider-hosted"`, and rejects unsupported output parts or `structuredOutput.strict` with `unsupported_mapping` rather than dropping them. Pass `redactor` when using the adapter directly; agents retain their existing active-redactor behavior.
|
|
50
73
|
|
package/docs/provider-caching.md
CHANGED
|
@@ -66,7 +66,7 @@ Cache helpers return plain data:
|
|
|
66
66
|
|
|
67
67
|
Provider events do not change. Cache accounting stays in normalized `Usage.cacheReadTokens` and `Usage.cacheWriteTokens`.
|
|
68
68
|
|
|
69
|
-
For stable-prefix payloads,
|
|
69
|
+
For stable-prefix payloads, `inputLayout: "cache_aware"` is the default on the default input builder, `assembleProviderInput()`, `AgentConfig`, and `RunOptions`; set `inputLayout: "legacy"` to restore the prior order. The default prompt builder already places context, selected skills, and tool declarations before input messages; cache-aware input ordering then places attachments/resources, summaries, prior history, and pending tool results before the current user suffix. The prefix is byte-stable only when those stable inputs are unchanged; Prism still does not guarantee provider cache hits.
|
|
70
70
|
|
|
71
71
|
## Request/response example
|
|
72
72
|
|
|
@@ -28,7 +28,7 @@ Offline conformance is mandatory for every package; credentialed probes are not
|
|
|
28
28
|
| Package | Required offline evidence | Restricted live evidence |
|
|
29
29
|
| --- | --- | --- |
|
|
30
30
|
| OpenAI | Responses serialization/stream ordering, provider-hosted authority, continuation cap/cursor, Realtime fake WebSocket caps | Standard API-key smoke; separate protected hosted-tool/Realtime entitlement probe |
|
|
31
|
-
| AI SDK | Exact 4.0.
|
|
31
|
+
| AI SDK | Exact 4.0.4/V4 gate (`4.0.3` also listed); every mapped stream part; authority, cache usage, redaction, unsupported mapping | Host-created V4 model only; no Prism credential fixture |
|
|
32
32
|
| Anthropic | Messages serialization, cache/thinking/tools, header/redaction/abort assertions | Protected `ANTHROPIC_API_KEY` smoke |
|
|
33
33
|
| Google | `generateContent` serialization, complete tool calls, media/abort/redaction assertions | Protected `GOOGLE_API_KEY` or `GEMINI_API_KEY` smoke |
|
|
34
34
|
| Kimi | Coding/Moonshot route fixtures, thinking/tool reconstruction, headers/redaction | Protected `KIMI_API_KEY` smoke |
|
|
@@ -89,7 +89,7 @@ Every package remains explicit, setup-zero-fetch, and late-credential-bound. `Mo
|
|
|
89
89
|
| Package | Protocol / model source | Content mapping | Stream, tools, and reasoning | Cache / canary |
|
|
90
90
|
| --- | --- | --- | --- | --- |
|
|
91
91
|
| OpenAI | Responses; featured or caller-gated `listOpenAIModels` | text, image, audio, file, document | Host and provider-hosted tools; 8-hop continuation; Realtime seam; Responses reasoning | `openai_key`; checked-in standard smoke + protected hosted/Realtime probe |
|
|
92
|
-
| AI SDK | Host `LanguageModelV4`; no Prism catalog | declared text/image/audio/file/document prompt parts (role-limited) | v4 mapping; provider-executed tool authority; host-owned reasoning | host-owned; exact 4.0.3
|
|
92
|
+
| AI SDK | Host `LanguageModelV4`; no Prism catalog | declared text/image/audio/file/document prompt parts (role-limited) | v4 mapping; provider-executed tool authority; host-owned reasoning | host-owned; exact 4.0.4 matrix (`4.0.3` also listed); protected host integration |
|
|
93
93
|
| Anthropic | Messages; caller-gated list | text, image, PDF document/file | tool deltas, thinking | `cache_control`; protected API-key smoke |
|
|
94
94
|
| Google | Gemini `generateContent`; caller-gated list | text, image, audio, document/file | complete tool calls, thinking | no Prism cache marker; protected API-key smoke |
|
|
95
95
|
| Kimi | Coding Messages or opt-in Moonshot; caller-gated list | text, image, PDF document/file by route/model | tool deltas, route-native thinking replay | implicit / optional Anthropic markers; protected API-key smoke |
|
package/docs/providers/ai-sdk.md
CHANGED
|
@@ -11,6 +11,7 @@ Core `@arnilo/prism` does not depend on the AI SDK.
|
|
|
11
11
|
| `@ai-sdk/provider` | `LanguageModel` ABI | Status |
|
|
12
12
|
| --- | --- | --- |
|
|
13
13
|
| `4.0.3` | `LanguageModelV4`, `specificationVersion: "v4"` | Supported and offline-tested |
|
|
14
|
+
| `4.0.4` | `LanguageModelV4`, `specificationVersion: "v4"` | Supported and offline-tested |
|
|
14
15
|
|
|
15
16
|
The peer dependency is intentionally exact. `createAiSdkProvider()` reads its resolved `@ai-sdk/provider/package.json` version during setup and throws typed `AiSdkProviderError { code: "unsupported_version" }` for an unlisted version; it does not infer compatibility from a matching `"v4"` string.
|
|
16
17
|
|
|
@@ -143,7 +144,7 @@ Official evidence: [Custom providers / LanguageModelV4](https://ai-sdk.dev/provi
|
|
|
143
144
|
|
|
144
145
|
## Extension and configuration notes
|
|
145
146
|
|
|
146
|
-
- Peer dependency: `@ai-sdk/provider@4.0.3
|
|
147
|
+
- Peer dependency: `@ai-sdk/provider@4.0.4` (matrix also lists `4.0.3`). Upgrade policy adds a matrix row and offline conformance fixture before accepting any new version.
|
|
147
148
|
- First-party HTTP providers remain independent; this adapter is available directly, through `@arnilo/prism-providers`, or through `@arnilo/prism-all`. Installation does not select a model or invoke AI SDK.
|
|
148
149
|
- `options.compat` / `options.extra` pass through as AI SDK `providerOptions.prism`.
|
|
149
150
|
- Export helpers `toAiSdkCallOptions`, `toAiSdkPrompt`, and `mapAiSdkStream` for tests and custom hosts.
|
|
@@ -32,6 +32,22 @@ Options:
|
|
|
32
32
|
| `fetch` | `typeof fetch` | Optional fetch implementation for tests or custom hosts. |
|
|
33
33
|
| `chatCompletionsUrl` | `string \| ((request) => string)` | Optional full chat-completions URL override (Azure deployment paths). |
|
|
34
34
|
| `authStyle` | `"bearer" \| "api-key" \| "none"` | Auth header style. Default `bearer`. |
|
|
35
|
+
| `buildBodyExtra` | `(request) => JsonObject \| undefined` | Optional provider-specific body fields (thinking/reasoning/cache); merged over the base body. |
|
|
36
|
+
| `mapMessages` | `(request) => readonly Message[]` | Optional message transform before serialization (e.g. cache-control markers). Defaults to `request.messages`. |
|
|
37
|
+
| `mapUsage` | `(usage: unknown) => Usage \| undefined` | Optional usage mapping override (e.g. OpenRouter cost fields). Defaults to `mapOpenAIChatUsage`. |
|
|
38
|
+
| `serializeMessage` | `(message, request) => JsonObject` | Optional custom message serializer (e.g. Z.AI `reasoning_content` replay). Defaults to assert + `serializeOpenAIChatMessage`. |
|
|
39
|
+
| `doneUsage` | `boolean` | Emit the final stream usage on the `done` event (without strict completion checks). |
|
|
40
|
+
| `mapHttpError` | `(response, bodyText, secrets) => Error` | Custom HTTP error mapping (e.g. NeuralWatt retry classification). Receives the response and redacted body text. |
|
|
41
|
+
| `onComment` | `(text) => ProviderEvent \| undefined` | Handle SSE comment lines (text after `:`), e.g. NeuralWatt `: energy` / `: cost` telemetry. Returned events are yielded in stream order. |
|
|
42
|
+
| `extraHeaders` | `(request) => Record<string, string>` | Optional extra request headers; provider auth and `content-type` still win. |
|
|
43
|
+
| `transformBody` | `(body, request) => JsonObject` | Optional final body transform, applied last (token limits, compat stripping); wins over everything. |
|
|
44
|
+
| `strictCompletion` | `boolean` | Require `[DONE]` and a `finish_reason`; truncated streams yield an `error` and `done` carries the final usage. |
|
|
45
|
+
| `requestFailedPrefix` | `string` | Prefix for HTTP error messages. Default `OpenAI-compatible request failed`. |
|
|
46
|
+
|
|
47
|
+
The subpath also exports the building blocks for provider packages that keep public body/stream helpers:
|
|
48
|
+
|
|
49
|
+
- `openAIChatEvents(body, { signal, strictCompletion, doneUsage, mapUsage, onComment })`: the shared SSE stream loop as an `AsyncIterable<ProviderEvent>`.
|
|
50
|
+
- `buildOpenAIChatBody(request, { mapMessages, serializeMessage, buildBodyExtra, transformBody })`: the base Chat Completions request body builder.
|
|
35
51
|
|
|
36
52
|
Provider requests use the standard `ProviderRequest` shape: `model`, `messages`, optional `tools`, `metadata`, and `signal`.
|
|
37
53
|
|
|
@@ -49,7 +65,7 @@ The returned provider emits normalized `ProviderEvent` values:
|
|
|
49
65
|
| `[DONE]` or stream end | `done` event. |
|
|
50
66
|
| HTTP/stream/parsing error | `error` event with redacted `ErrorInfo`. |
|
|
51
67
|
|
|
52
|
-
The adapter passes `request.signal` to `fetch` for abort propagation.
|
|
68
|
+
The adapter passes `request.signal` to `fetch` for abort propagation; an already-aborted signal throws before fetch.
|
|
53
69
|
|
|
54
70
|
## Request/response example
|
|
55
71
|
|
|
@@ -110,6 +126,17 @@ const provider = createOpenAICompatibleProvider({
|
|
|
110
126
|
- The adapter resolves `apiKey` per request through `resolveCredentialValue()`.
|
|
111
127
|
- This adapter currently targets Chat Completions streaming only.
|
|
112
128
|
- The serializer preserves text, thinking (downgraded to text), assistant `tool_call` blocks as `tool_calls`, `tool_result` blocks as role `tool` messages, and image blocks when the model declares `capabilities.input` includes `"image"`. Unsupported block placements or unclaimed images fail before fetch.
|
|
129
|
+
- Vendor-specific OpenAI-compatible endpoints (cache markers, thinking bodies, reasoning fields, custom usage) plug in through `buildBodyExtra`/`mapMessages`/`mapUsage`/`extraHeaders` instead of duplicating the stream loop:
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
const provider = createOpenAICompatibleProvider({
|
|
133
|
+
baseUrl: "https://vendor.example/v1",
|
|
134
|
+
apiKey: () => process.env.VENDOR_API_KEY,
|
|
135
|
+
buildBodyExtra: (request) => ({ thinking: { type: "enabled" } }),
|
|
136
|
+
extraHeaders: () => ({ "x-vendor-app": "my-app" }),
|
|
137
|
+
});
|
|
138
|
+
```
|
|
139
|
+
|
|
113
140
|
- Cache behavior is intentionally minimal: this Chat Completions adapter sends no `prompt_cache_key`, `prompt_cache_retention`, or `cache_control` fields. Endpoints that cache implicitly do so automatically; hosts needing OpenAI `prompt_cache_key`/`prompt_cache_retention` should use the [`@arnilo/prism-provider-openai`](openai.md) Responses package. The adapter still normalizes cache usage from `prompt_tokens_details.cached_tokens` (and `prompt_cache_hit_tokens`) into `Usage.cacheReadTokens`.
|
|
114
141
|
|
|
115
142
|
## Security and performance notes
|
package/docs/public-contracts.md
CHANGED
|
@@ -122,7 +122,7 @@ Important request shapes:
|
|
|
122
122
|
| `ToolRegistry` | Host active tool registry shape: `register()`, `get()`, `resolve()`, and `list()`. |
|
|
123
123
|
| `ToolExecutionContext` | Host tool execution context: session/run ids, tool call id, optional abort signal, metadata, and progress callback. |
|
|
124
124
|
| `ContextResolutionContext` | Context provider input: messages plus optional session/run ids, metadata, and signal. |
|
|
125
|
-
| `InputAssemblyLayout` | Default input layout selector: `"
|
|
125
|
+
| `InputAssemblyLayout` | Default input layout selector: `"cache_aware"` (default) or opt-in `"legacy"`. |
|
|
126
126
|
| `DefaultInputBuildContext` | Optional default input assembly context: input layout, instructions, history, summaries, attachments, explicit resources, tool results, middleware, ids, metadata, and signal. |
|
|
127
127
|
| `ResolveContextOptions` | Ordered context resolution input: selected providers, messages, ids, metadata, signal, and optional middleware. |
|
|
128
128
|
| `AssembleProviderInputOptions` | Provider input assembly input: model, input, optional builders, selected context providers/skills, active tools, metadata, and signal. |
|
|
@@ -145,7 +145,7 @@ Important request shapes:
|
|
|
145
145
|
| `ConfigLayer` | Named JSON config layer consumed by `mergeConfigLayers()`. |
|
|
146
146
|
| `PrismManifest` | Data-only package manifest with config defaults, contribution declarations, and resource declarations. |
|
|
147
147
|
| `ProductionPersistenceStore` | Adapter-facing interface for durable, paginated, multi-tenant storage plus optional `checkpoints?: CheckpointStore`, `leases?: LeaseStore`, and `feedback?: RunFeedbackStore`. No SQL/ORM/host file storage/network dependency. |
|
|
148
|
-
| `CheckpointStore` | Generic versioned checkpoint capability: save/load/bounded-list/delete by namespace and key, with ownership, exact-version CAS, and lease fencing. `createMemoryCheckpointStore()` is the reference implementation. |
|
|
148
|
+
| `CheckpointStore` | Generic versioned checkpoint capability: save/load/bounded-list/delete by namespace and key, with ownership, exact-version CAS, and lease fencing. `createMemoryCheckpointStore()` is the reference implementation; it is bounded — `maxRecords` (default 10,000, evicts least-recently-saved) and `maxValueBytes` (default 1 MiB per JSON value). |
|
|
149
149
|
| `LeaseStore` | Atomic acquire/renew/release/get by namespace and key, with opaque claim tokens, expiry, ownership scope, and monotonically increasing takeover fences. `createMemoryLeaseStore()` is the reference implementation. |
|
|
150
150
|
| `RunFeedbackStore` | Immutable append, bounded owned query, and owned deletion for ratings/comments/tags linked to existing run/trace/evaluation IDs. `createMemoryRunFeedbackStore()` is the reference implementation. |
|
|
151
151
|
| `EventMultiplexer<T>` | Generic bounded fan-in from async sources. `createEventMultiplexer()` owns queue limits, overflow policy, abort, source teardown, and close behavior. |
|
|
@@ -8,7 +8,7 @@ Core package:
|
|
|
8
8
|
|
|
9
9
|
- `@arnilo/prism` — the runtime, contracts, registries, streaming events, CLI (including `prism init`), and the `/docs` hub. `files`: `dist` (with `!dist/__tests__` and `!dist/**/*.map` negations), `docs`, `templates`, `CHANGELOG.md`. `bin`: `prism` -> `dist/cli.js`. `sideEffects`: `["dist/cli.js"]`.
|
|
10
10
|
|
|
11
|
-
First-party workspace packages (each has non-optional `@arnilo/prism@0.0.
|
|
11
|
+
First-party workspace packages (each has non-optional `@arnilo/prism@0.0.18` peer and `sideEffects: false`; RAG also peers on memory, and server also peers on workflows):
|
|
12
12
|
|
|
13
13
|
- `@arnilo/prism-provider-anthropic`, `@arnilo/prism-provider-google`, `@arnilo/prism-provider-openai`, `@arnilo/prism-provider-openrouter`, `@arnilo/prism-provider-kimi`, `@arnilo/prism-provider-zai`, `@arnilo/prism-provider-opencode-go`, `@arnilo/prism-provider-neuralwatt` — provider adapters.
|
|
14
14
|
- `@arnilo/prism-provider-azure`, `@arnilo/prism-provider-bedrock`, `@arnilo/prism-provider-vertex` — optional enterprise-cloud adapters (Entra/IAM/ADC; separate from consumer Anthropic/Google).
|
|
@@ -36,7 +36,7 @@ First-party workspace packages (each has non-optional `@arnilo/prism@0.0.16` pee
|
|
|
36
36
|
|
|
37
37
|
### 0.0.12 AG-UI package boundary
|
|
38
38
|
|
|
39
|
-
`@arnilo/prism-ag-ui` is a publishable optional code package with root AG-UI exports and stable `./acp` sibling, peer `@arnilo/prism@0.0.
|
|
39
|
+
`@arnilo/prism-ag-ui` is a publishable optional code package with root AG-UI exports and stable `./acp` sibling, peer `@arnilo/prism@0.0.18`, pinned `@ag-ui/core@0.0.57` / `@agentclientprotocol/sdk@1.3.0`, and no import-time network/listener/run. It is included by `@arnilo/prism-all` only—not `@arnilo/prism-code` or `@arnilo/prism-sdk`—so coding and SDK profiles stay free of UI protocol dependencies.
|
|
40
40
|
|
|
41
41
|
Family/profile packages (pure manifests, no code or `dist`; ship `README.md` and `CHANGELOG.md`; use exact hard `dependencies`):
|
|
42
42
|
|
|
@@ -78,9 +78,9 @@ Consumers install the core package for the runtime and add first-party packages
|
|
|
78
78
|
| Run the default (network-free) test suite | `npm test` |
|
|
79
79
|
| Dry-run pack core + every package | `npm run pack:dry-run` |
|
|
80
80
|
| Local mirror of the release verify gate | `npm run release:dry-run` |
|
|
81
|
-
| Validate clean tag/version/ranges and reject registry collisions | `npm run release:check -- --version 0.0.
|
|
82
|
-
| Preview deterministic publish order | `npm run release:publish -- --version 0.0.
|
|
83
|
-
| Resume interrupted tagged publication | `npm run release:publish -- --version 0.0.
|
|
81
|
+
| Validate clean tag/version/ranges and reject registry collisions | `npm run release:check -- --version 0.0.18` |
|
|
82
|
+
| Preview deterministic publish order | `npm run release:publish -- --version 0.0.18 --dry-run --allow-dirty --allow-untagged` |
|
|
83
|
+
| Resume interrupted tagged publication | `npm run release:publish -- --version 0.0.18 --resume --report release-artifacts/publish-report.json` |
|
|
84
84
|
| Full SDK readiness gate (typecheck + offline tests + pack) | `npm run sdk:ready` |
|
|
85
85
|
|
|
86
86
|
Public core import specifiers (from the root `exports` map):
|
|
@@ -117,7 +117,7 @@ A packed tarball contains only public compiled output and release files:
|
|
|
117
117
|
- Code packages ship `README.md`, `LICENSE`, and `CHANGELOG.md`; family/profile packages ship `README.md` and `CHANGELOG.md`.
|
|
118
118
|
- The core tarball additionally ships the full `docs/` directory (the docs hub) and `templates/init/` used by `prism init`.
|
|
119
119
|
- `dist/cli.js` and the `bin` link in core.
|
|
120
|
-
- **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.0.
|
|
120
|
+
- **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.0.18.tgz`; first-party packages produce `arnilo-prism-provider-<name>-0.0.18.tgz` / `arnilo-prism-compaction-<name>-0.0.18.tgz` / `arnilo-prism-coding-agent-0.0.18.tgz`; family/profile packages produce `arnilo-prism-{providers,compaction,base,code,sdk,all}-0.0.18.tgz`. The CLI bin name `prism` is unaffected by the package name (`npx prism` still works; npm allows the bin field to differ from the package name).
|
|
121
121
|
|
|
122
122
|
Excluded from every tarball by `files` negation:
|
|
123
123
|
|
|
@@ -136,9 +136,9 @@ Excluded from every tarball by `files` negation:
|
|
|
136
136
|
"name": "host-app",
|
|
137
137
|
"type": "module",
|
|
138
138
|
"dependencies": {
|
|
139
|
-
"@arnilo/prism": "0.0.
|
|
140
|
-
"@arnilo/prism-provider-openai": "0.0.
|
|
141
|
-
"@arnilo/prism-compaction-observational-memory": "0.0.
|
|
139
|
+
"@arnilo/prism": "0.0.18",
|
|
140
|
+
"@arnilo/prism-provider-openai": "0.0.18",
|
|
141
|
+
"@arnilo/prism-compaction-observational-memory": "0.0.18"
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
144
|
```
|
|
@@ -148,7 +148,7 @@ Installing the provider/compaction packages without `@arnilo/prism` present prod
|
|
|
148
148
|
```text
|
|
149
149
|
npm error code ERESOLVE
|
|
150
150
|
npm error Could not resolve dependency:
|
|
151
|
-
npm error peer @arnilo/prism@"0.0.
|
|
151
|
+
npm error peer @arnilo/prism@"0.0.17" from @arnilo/prism-provider-openai@0.0.17
|
|
152
152
|
```
|
|
153
153
|
|
|
154
154
|
## Implementation example
|
|
@@ -181,11 +181,11 @@ For SDK readiness, run the same one-command gate directly. It composes existing
|
|
|
181
181
|
npm run sdk:ready
|
|
182
182
|
```
|
|
183
183
|
|
|
184
|
-
Release publication derives all **44** manifests from the workspace once, validates exact `0.0.
|
|
184
|
+
Release publication derives all **44** manifests from the workspace once, validates exact `0.0.18` manifest/lockfile/internal ranges, then uses deterministic dependency order. `release:check` requires a clean commit tagged `v0.0.18` and rejects any existing registry version. `release:publish --resume` skips only registry versions whose internal dependency fingerprint matches the local manifest; conflicting versions fail closed. Each attempted package is written immediately to the JSON report, so a failed job can rerun safely. `--dry-run` performs registry availability checks and invokes `npm publish --dry-run` with explicit public access, provenance, and `latest` tag, but does not publish.
|
|
185
185
|
|
|
186
186
|
```bash
|
|
187
|
-
npm run release:check -- --version 0.0.
|
|
188
|
-
npm run release:publish -- --version 0.0.
|
|
187
|
+
npm run release:check -- --version 0.0.18
|
|
188
|
+
npm run release:publish -- --version 0.0.18 --dry-run --allow-dirty --allow-untagged
|
|
189
189
|
```
|
|
190
190
|
|
|
191
191
|
`--allow-dirty` and `--allow-untagged` exist only for local preview; real publication and CI never pass them. npm registry calls occur only in these release preflight/publication commands, never build/test/package discovery.
|
|
@@ -196,6 +196,48 @@ Optional live smoke tests stay separate from SDK readiness because they require
|
|
|
196
196
|
PRISM_LIVE_PROVIDER_TESTS=1 npm run test --workspaces --if-present
|
|
197
197
|
```
|
|
198
198
|
|
|
199
|
+
### 0.0.18 publish handoff
|
|
200
|
+
|
|
201
|
+
**Decision: GO after protected operator prerequisites below.** Release **0.0.18** (Phase 1 restore integrity, plan 001) hardens coding tools and release trust without adding packages: `repo_search` is literal-only (ReDoS mitigation), default `write`/`edit` use temp+`rename`, `applyContextBudget` evicts oldest history first, default `inputLayout` is `cache_aware`, `@arnilo/prism-mcp` pins `@modelcontextprotocol/sdk` **1.30.0** (clears moderate `@hono/node-server` advisory), and README/readiness docs match the 14-adapter / optional-browser inventory. The exact graph stays **44 publishable manifests**; no package added or retired. Intentional pre-1.0 breaks are documented in [migration](migration.md) under `0.0.17 → 0.0.18 restore integrity`.
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
git diff --check
|
|
205
|
+
npm ci
|
|
206
|
+
npm run sdk:ready
|
|
207
|
+
node --test scripts/budget-gate.test.mjs
|
|
208
|
+
node scripts/scan-secrets.mjs && node scripts/verify-sbom.mjs
|
|
209
|
+
npm audit --audit-level=moderate
|
|
210
|
+
npm run release:gate
|
|
211
|
+
npm run release:check -- --version 0.0.18 --allow-dirty --allow-untagged --report /tmp/prism-0.0.18-preflight.json
|
|
212
|
+
npm run release:publish -- --version 0.0.18 --dry-run --allow-dirty --allow-untagged --report /tmp/prism-0.0.18-dry-run.json
|
|
213
|
+
git tag -s v0.0.18 -m "Prism 0.0.18"
|
|
214
|
+
git verify-tag v0.0.18
|
|
215
|
+
git push origin v0.0.18
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
The dry-run checks every registry collision and executes npm's non-publishing tarball validation for each dependency-ordered manifest. The protected tag workflow alone publishes through `npm run release:publish -- --version "${GITHUB_REF_NAME#v}" --resume --report release-artifacts/publish-report.json`; re-run a failed job for the same tag. `npm audit signatures --json --include-attestations` and artifact checksums remain post-publish checks.
|
|
219
|
+
|
|
220
|
+
### 0.0.17 publish handoff
|
|
221
|
+
|
|
222
|
+
**Decision: GO after protected operator prerequisites below.** Release 0.0.17 implements the 2026-07-29 full implementation review (plan 081, twenty fixes): durable run-state load bound, explicit resume-as-approval, unconditional `input_assembly` middleware, same-session parent enforcement, jitter + `Retry-After`-aware retries with provider error wiring, O(n) context-budget eviction, fingerprint coverage of instructions/system prompt/skills, stage-named guardrail interrupts with `metadata.error`, `steer_rejected`, middleware double-`next()` detection, parked-consumer sorted multiplexer delivery, checkpoint-store bounds, strict credential opt-in, extension `unregister`/dispose handles with failed-setup unwind, loud CLI rejection of inert flags, capability-conditional tool listing, and the C8 nit bundle. The exact graph stays **44 publishable manifests**; no package added or retired. Intentional pre-1.0 breaks are documented in [migration](migration.md): inert CLI flags rejected (`CliOptions` dead fields removed) and `ExtensionKernel.load()` now resolves to `LoadedExtension[]`. The compat baseline was refreshed with `--allow-break` + migration note. Provider HTTP errors now carry numeric codes and `Retry-After` hints across anthropic/google/kimi/openai/opencode-go and the shared OpenAI-compatible transport — wire behavior is additive (more retries of genuinely transient failures), so the 0.0.15 protected live-canary matrix below still applies and no new live row is introduced.
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
git diff --check
|
|
226
|
+
npm ci
|
|
227
|
+
npm run sdk:ready
|
|
228
|
+
node --test scripts/budget-gate.test.mjs
|
|
229
|
+
node scripts/scan-secrets.mjs && node scripts/verify-sbom.mjs
|
|
230
|
+
npm audit --audit-level=high
|
|
231
|
+
npm run release:gate
|
|
232
|
+
npm run release:check -- --version 0.0.17 --allow-dirty --allow-untagged --report /tmp/prism-0.0.17-preflight.json
|
|
233
|
+
npm run release:publish -- --version 0.0.17 --dry-run --allow-dirty --allow-untagged --report /tmp/prism-0.0.17-dry-run.json
|
|
234
|
+
git tag -s v0.0.17 -m "Prism 0.0.17"
|
|
235
|
+
git verify-tag v0.0.17
|
|
236
|
+
git push origin v0.0.17
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
The dry-run checks every registry collision and executes npm's non-publishing tarball validation for each dependency-ordered manifest. The protected tag workflow alone publishes through `npm run release:publish -- --version "${GITHUB_REF_NAME#v}" --resume --report release-artifacts/publish-report.json`; re-run a failed job for the same tag. `npm audit signatures --json --include-attestations` and artifact checksums remain post-publish checks.
|
|
240
|
+
|
|
199
241
|
### 0.0.16 publish handoff
|
|
200
242
|
|
|
201
243
|
**Decision: GO after protected operator prerequisites below.** Phase 11 (plan 079) is a simplification/readiness release: no runtime behavior changes and no package retired. The exact graph is **44 publishable manifests** — Phase 11 Task 3 added one internal implementation package, `@arnilo/prism-session-store-codecs` (shared SQLite/Postgres row codecs, not enrolled in any profile family). The only public-surface change is the additive `resolveRedactor` export from `@arnilo/prism`; provider `cleanJson` was deliberately left per-package (wire-shape variants). All six profiles (`prism-all`, `prism-base`, `prism-code`, `prism-compaction`, `prism-providers`, `prism-sdk`) are retained on adoption evidence (zero retirements). The root tarball dropped the historical `docs/review-coverage-*.md` (659,478 → ≈575,680 packed bytes, 281 → 270 files). New offline release gates (`npm run release:gate`: API-surface `.d.ts` diff, tarball deny-list, exact ranges) run inside `sdk:ready`, and performance budgets (`scripts/budgets.json`) are enforced by `scripts/budget-gate.test.mjs` + `scripts/benchmark-0.0.16.mjs`. No Studio, Office, remote-browser vendor, additional vector-store, Slack/Teams, voice/desktop-control, internal-auth, or queue package ships. Protected CI, signed tag, npm authentication, OIDC attestation, and protected live-canary evidence remain operator/workflow prerequisites; no package is published by this handoff.
|
|
@@ -209,8 +251,8 @@ node --test scripts/budget-gate.test.mjs
|
|
|
209
251
|
node scripts/scan-secrets.mjs && node scripts/verify-sbom.mjs
|
|
210
252
|
npm audit --audit-level=high
|
|
211
253
|
npm run release:gate
|
|
212
|
-
npm run release:check -- --version 0.0.
|
|
213
|
-
npm run release:publish -- --version 0.0.
|
|
254
|
+
npm run release:check -- --version 0.0.17 --allow-dirty --allow-untagged --report /tmp/prism-0.0.16-preflight.json
|
|
255
|
+
npm run release:publish -- --version 0.0.17 --dry-run --allow-dirty --allow-untagged --report /tmp/prism-0.0.16-dry-run.json
|
|
214
256
|
git tag -s v0.0.16 -m "Prism 0.0.16"
|
|
215
257
|
git verify-tag v0.0.16
|
|
216
258
|
git push origin v0.0.16
|
|
@@ -232,7 +274,7 @@ Default `npm test`, `npm run sdk:ready`, and `benchmark-0.0.15` are network-free
|
|
|
232
274
|
| --- | --- | --- | --- |
|
|
233
275
|
| OpenAI Responses baseline | `PRISM_LIVE_PROVIDER_TESTS=1` + `OPENAI_API_KEY` | `npm test -w @arnilo/prism-provider-openai` | Bounded text/tool/abort smoke; key never enters events. |
|
|
234
276
|
| OpenAI hosted tools + Realtime | `OPENAI_API_KEY`; protected release harness additionally supplies host-owned safety identifier and hosted-tool entitlement | No generic fixture; record result with the release evidence | Provider-hosted `web_search`/similar execution and Realtime audio/interruption need account-specific availability, so fake transport coverage remains default gate. |
|
|
235
|
-
| AI SDK adapter | Host-selected AI SDK v4 model factory plus its provider credential | No generic fixture; run host integration in protected release environment | Exact `@ai-sdk/provider@4.0.
|
|
277
|
+
| AI SDK adapter | Host-selected AI SDK v4 model factory plus its provider credential | No generic fixture; run host integration in protected release environment | Exact `@ai-sdk/provider@4.0.4` mapping/version check; Prism does not own upstream model credentials. |
|
|
236
278
|
| Kimi / Moonshot | `PRISM_LIVE_PROVIDER_TESTS=1` + `KIMI_API_KEY` | `npm test -w @arnilo/prism-provider-kimi` | Coding route; Moonshot entitlement is account-specific. |
|
|
237
279
|
| Z.AI | `PRISM_LIVE_PROVIDER_TESTS=1` + `ZAI_API_KEY` | `npm test -w @arnilo/prism-provider-zai` | GLM stream/tool/reasoning smoke. |
|
|
238
280
|
| OpenRouter | `PRISM_LIVE_PROVIDER_TESTS=1` + `OPENROUTER_API_KEY` | `npm test -w @arnilo/prism-provider-openrouter` | Routed stream/model metadata smoke; host chooses permitted route. |
|
|
@@ -751,7 +793,7 @@ npm publication is not transactional and published versions are immutable. Parti
|
|
|
751
793
|
|
|
752
794
|
## Extension and configuration notes
|
|
753
795
|
|
|
754
|
-
- **Required `@arnilo/prism` peer.** Every first-party code package declares a non-optional `@arnilo/prism@0.0.
|
|
796
|
+
- **Required `@arnilo/prism` peer.** Every first-party code package declares a non-optional `@arnilo/prism@0.0.18` peer (`peerDependenciesMeta` must not mark `@arnilo/prism` optional; other peers such as `playwright-core` may be optional). The range stays pinned to `0.0.18` for the current 0.x release and will widen to `^1.0.0` at the 1.x stable release. Inside the workspace each package also declares `"@arnilo/prism": "file:../.."` in `devDependencies` so `npm install` resolves the peer locally; that devDependency is stripped from consumer installs and is not a runtime dependency.
|
|
755
797
|
- **Public access.** All 43 manifests (37 code packages + 6 family/profile packages) declare `"publishConfig": { "access": "public" }`; the publisher also passes `--access public` explicitly because scoped packages otherwise default to restricted on first publish.
|
|
756
798
|
- **Map retention knob.** Source maps are emitted locally but stripped from tarballs by `!dist/**/*.map`. Removing that `files` negation ships maps in releases (larger tarballs, better consumer stack traces).
|
|
757
799
|
- **Release workflow.** `.github/workflows/release.yml` has six jobs. `verify` runs network-free SDK readiness on Node 24; `node20-compat` builds/imports every public root `exports` default target on Node 20 for declared `engines.node >=20` (docs examples need Node >=22.6 native TypeScript stripping); `postgres-integration` uses `pgvector/pgvector:pg16`; `supply-chain` runs high-severity audit, SPDX/license policy, and tracked-source secret scanning; and tag-only `codeql-release` runs SAST. Tag-only `publish` needs all five gates, preserves clean exact-tag/version/topological publication, and alone receives `NPM_TOKEN`, `id-token: write`, and `attestations: write`. Before npm publish it packs all current tarballs, generates checksums plus SPDX, scans unpacked public artifacts, creates GitHub attestations for tarballs and SBOM, then retains artifacts for 30 days. Registry state remains the resumable journal. Local `npm run release:dry-run` remains network-free SDK readiness; local PostgreSQL coverage is `PRISM_TEST_POSTGRES_URL=... npm run test:postgres`.
|
package/docs/session-stores.md
CHANGED
|
@@ -100,7 +100,7 @@ await store.append(entry, options);
|
|
|
100
100
|
}
|
|
101
101
|
```
|
|
102
102
|
|
|
103
|
-
Recognize it with `isSessionAppendConflict(error)`, not message text. Built-in stores reject duplicate entry ids, dangling `expectedParentId` values, and exact idempotency retries. They allow two distinct children of the same existing parent because that is a branch/fork, not parent-order corruption. Production stores may add a stricter branch-tip compare-and-swap when a host wants one-writer linear branches.
|
|
103
|
+
Recognize it with `isSessionAppendConflict(error)`, not message text. Built-in stores reject duplicate entry ids, dangling `expectedParentId` values, and `expectedParentId` pointing at another session's entry (the parent must exist in the same session — a cross-session parent would be a write no per-session branch walk could read back), and exact idempotency retries. They allow two distinct children of the same existing parent because that is a branch/fork, not parent-order corruption. Production stores may add a stricter branch-tip compare-and-swap when a host wants one-writer linear branches.
|
|
104
104
|
|
|
105
105
|
## Extension and configuration notes
|
|
106
106
|
|