@arnilo/prism 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +10 -10
  3. package/dist/agent-session/session/provider-round.js +17 -1
  4. package/dist/agent-session/session.js +13 -3
  5. package/dist/contracts-core/agent.d.ts +2 -0
  6. package/dist/contracts-protocol.d.ts +2 -0
  7. package/dist/index.d.ts +3 -3
  8. package/dist/index.js +2 -2
  9. package/dist/input.js +3 -2
  10. package/dist/provider-request-policy.d.ts +15 -0
  11. package/dist/provider-request-policy.js +52 -0
  12. package/dist/providers/openai-primitives.js +1 -1
  13. package/docs/0.1.0-readiness.md +2 -2
  14. package/docs/agent-session-runtime.md +2 -1
  15. package/docs/compaction-llm.md +2 -0
  16. package/docs/compaction-observational-memory.md +3 -0
  17. package/docs/index.md +21 -19
  18. package/docs/input-and-prompt-assembly.md +1 -1
  19. package/docs/migrate-to-0.5.md +25 -3
  20. package/docs/migration.md +8 -0
  21. package/docs/provider-caching.md +4 -2
  22. package/docs/provider-packages.md +30 -34
  23. package/docs/provider-request-policies.md +18 -5
  24. package/docs/providers/ai-sdk.md +12 -0
  25. package/docs/providers/alibaba.md +12 -0
  26. package/docs/providers/anthropic.md +12 -0
  27. package/docs/providers/azure.md +12 -0
  28. package/docs/providers/bedrock.md +12 -0
  29. package/docs/providers/clinepass.md +12 -0
  30. package/docs/providers/commandcode.md +12 -0
  31. package/docs/providers/deepseek.md +12 -0
  32. package/docs/providers/google.md +12 -0
  33. package/docs/providers/hyper.md +12 -0
  34. package/docs/providers/kimi.md +12 -0
  35. package/docs/providers/neuralwatt.md +12 -0
  36. package/docs/providers/ollama.md +12 -0
  37. package/docs/providers/openai-compatible.md +12 -0
  38. package/docs/providers/openai.md +12 -0
  39. package/docs/providers/opencode-go.md +12 -0
  40. package/docs/providers/openrouter.md +12 -0
  41. package/docs/providers/vertex.md +12 -0
  42. package/docs/providers/xai.md +12 -0
  43. package/docs/providers/zai.md +12 -0
  44. package/docs/public-contracts.md +1 -1
  45. package/docs/release-and-install.md +37 -37
  46. package/docs/thinking-and-reasoning.md +13 -8
  47. package/docs/use-case-model-selection.md +1 -1
  48. package/package.json +1 -1
package/docs/migration.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Migration guide
2
2
 
3
+ ## 0.5.1 → 0.5.2 (additive)
4
+
5
+ Stream tokens coalesce on persist (adjacent `text`/`thinking` deltas merge). Replay serializers join those parts with an empty string instead of a newline. No import, store, or peer-range break; bump `@arnilo/prism*` to `^0.5.2`.
6
+
7
+ ## 0.5.0 → 0.5.1 (additive)
8
+
9
+ Kernel constructs valid provider requests: session correlation, default cache breakpoints, and `thinkingLevel` on `AgentConfig` / `RunOptions`. Clay may drop host-only `createSessionCachePolicy`. OpenCode Go raw `generate` without `sessionId` throws `ProviderRequirementError` (`ERR_PRISM_PROVIDER_REQUIREMENT`) before fetch instead of an upstream 400. Observational memory uses derived `om:{session.id}`; LLM compaction uses the agent session id. See [migrate-to-0.5.md](migrate-to-0.5.md#8-provider-request-construction--additive-plan-066--051).
10
+
3
11
  ## 0.4.x → 0.5.0 lockstep cut (breaking)
4
12
 
5
13
  Prism 0.5 (plans 055–065) ships four breaking surfaces: the 27 removed unused exports from the plan 058 sweep (symbol-surface only), the MCP TypeScript SDK v2 module move (plan 063 — hosts importing `@modelcontextprotocol/sdk` directly must move to the modular `client`/`server` 2.0.0 packages), the thinking-effort wire moves (plan 065 — Anthropic `effort` → `output_config.effort`, xAI `reasoning_effort` now sent, snap-on-declared semantics), and the plan 056 hardening behavior changes (tenant-scoped store factories, child env allow-list). Dependency majors (plan 062: pdf-parse 2.4 with Node ≥ 20.16, better-sqlite3 13, keyring 2 with typed locked-store errors) and the CLI real-provider contract (plan 064: explicit `--provider` required, exit 2 when omitted) are behavior changes without import impact. See the complete guide with per-symbol replacements and upgrade steps in [migrate-to-0.5.md](migrate-to-0.5.md). All 10 publishable manifests bump to `0.5.0` lockstep; internal first-party ranges move `^0.4.0` → `^0.5.0`. Security keeper surface (ownership/checkpoint guards, `secureCompare`, `zeroBuffer`, sandbox path-escape guard, RAG scope guard, MCP content-bounds guard, secret-leak conformance assert) is unchanged.
@@ -12,6 +12,8 @@ Provider caching documents Prism's cache intent surface:
12
12
 
13
13
  Cache hints are best-effort. They describe intent; providers decide whether their native API can use them. Prism does not guarantee cache hits.
14
14
 
15
+ **Kernel defaults (0.5.1).** `applyDefaultProviderRequestOptions` fills `cache.breakpoints` with `{ location: "system_prompt" }` and `{ location: "last_stable_message" }` plus `cacheRetention: "short"` when `model.cache.kind === "cache_control"` or `model.cache.explicitBreakpoints === true`, unless the host set `cache.mode: "off"`, `cacheRetention: "none"`, or a non-empty breakpoint list. Implicit / `none` / host-owned (Azure, Bedrock, Vertex, AI SDK) models get no Prism markers. Session and cache keys are correlation ids — Cache keys must never be credentials.
16
+
15
17
  ## When to use it
16
18
 
17
19
  Use this page when a host or provider package needs to:
@@ -150,7 +152,7 @@ Provider request policies can set `ProviderRequestOptions.cache` or the legacy `
150
152
  | `@arnilo/prism-providers/openai` | `openai_key` | Sends sanitized `prompt_cache_key`; pre-5.6 models emit `prompt_cache_retention: "24h"` when `longRetention`; GPT-5.6+ models (`explicitBreakpoints`) map `cache.breakpoints`/`cache.mode: "on"` to `prompt_cache_options: { mode: "explicit" }` + `prompt_cache_breakpoint` markers (≤4 writes). | Stable cache key + stable prefix can improve reuse; keep selected anchors stable. | Best-effort only; `"short"`/`"none"` omit retention; `"30m"` TTL is the default and never emitted. |
151
153
  | `@arnilo/prism-providers/anthropic` | `cache_control` | Marks only selected Anthropic message anchors; `system_prompt` breakpoints emit native `system` text blocks with the marker; `"long"` maps to documented `ttl: "1h"`. | Keep selected anchors stable. | Best-effort; never stamp every block. |
152
154
  | `@arnilo/prism-providers/google` | none | Sends no Prism cache marker. | Host/model may have upstream behavior. | Gemini cache controls are not mapped in this package. |
153
- | `@arnilo/prism-providers/openrouter` | `cache_control` | Top-level automatic `cache_control` when enabled without breakpoints; otherwise markers only on caller-selected `cache.breakpoints`; `"long"` may add `ttl: "1h"`. Sticky `session_id` routing. | Breakpoint-stable / automatic prefixes can be reused by upstream providers. | Best-effort only; top-level automatic may exclude some backends from routing. |
155
+ | `@arnilo/prism-providers/openrouter` | `cache_control` | Kernel defaults (agent session / helper) emit **per-message** `cache_control` on `system_prompt` + `last_stable_message`. Raw `generate` with empty breakpoints may still send top-level automatic `cache_control`. `"long"` may add `ttl: "1h"`. Sticky `session_id` routing. | Breakpoint-stable prefixes can be reused by upstream providers. | Best-effort only; top-level automatic may exclude some backends from routing. |
154
156
  | `@arnilo/prism-providers/opencode-go` | route-specific | Sends sanitized `x-opencode-session`; Anthropic route applies selected `cache_control` breakpoints; OpenAI route sends none. | Session id + unchanged selected anchors can help route-native caches. | Best-effort and route-dependent. |
155
157
  | `@arnilo/prism-providers/hyper` | route-specific implicit / `cache_control` | Chat route sends no markers (implicit prefix caching); `qwen3.6-*` messages route applies `cache_control` only to caller-selected `cache.breakpoints` (max 4); **no `ttl`** (undocumented). Opt-in responses route emits OpenAI-standard `prompt_cache_key` from hints only, never retention/options. | Keep selected Anthropic anchors and prior history stable. | Best-effort only; `402 billing_error` when Hypercredits run out. |
156
158
  | `@arnilo/prism-providers/commandcode` | route-specific implicit / `cache_control` | Chat route sends no markers (implicit prefix caching); `claude-*` messages route applies `cache_control` only to caller-selected `cache.breakpoints` (max 4); **no `ttl`** (undocumented). GPT-5.6 tiers keep docs `cacheWrite` prices in `cost` but stay implicit until the live probe verifies `prompt_cache_key`. | Keep selected Anthropic anchors and prior history stable. | Best-effort only; GPT-5.6 explicit `prompt_cache_key` upgrade pending probe (plan 055 Task 9); OSS models bill at mean per-provider price; DeepSeek off-peak 17h/day, peak 2×. |
@@ -173,7 +175,7 @@ Detailed first-party provider notes:
173
175
  - OpenAI-compatible Chat Completions adapter: minimal scope, sends no cache payload; see [OpenAI-compatible provider](providers/openai-compatible.md).
174
176
  - Anthropic (`@arnilo/prism-providers/anthropic`): `kind: "cache_control"`; selected Anthropic message anchors receive `cache_control` and eligible long retention maps to `ttl: "1h"`. A `system_prompt` breakpoint serializes `system` as native text blocks carrying the marker (shared `systemCacheControlField()` helper; plain joined string when unmarked). Cache read/create usage maps to normalized cache read/write tokens.
175
177
  - Google (`@arnilo/prism-providers/google`): sends no Prism cache-control payload. Do not infer cache hits or cache token counts from absent Gemini fields.
176
- - OpenRouter (`@arnilo/prism-providers/openrouter`): `kind: "cache_control"`. Sanitizes/clamps `session_id`/`X-Session-Id` to 256 chars for sticky routing (from `cache.key` ?? legacy `cacheKey` ?? `sessionId`); with no breakpoints emits top-level automatic `cache_control: { type: "ephemeral" }`; with breakpoints applies Anthropic-style markers only to caller-selected locations (last content block of each selected message); `"long"` retention adds `ttl: "1h"` when the model allows it. `prompt_tokens_details.cached_tokens`/`cache_write_tokens` map to `Usage.cacheReadTokens`/`cacheWriteTokens`. Optional `listOpenRouterModels()` may populate `ModelConfig.cache`/`cost` from live pricing.
178
+ - OpenRouter (`@arnilo/prism-providers/openrouter`): `kind: "cache_control"`. Sanitizes/clamps `session_id`/`X-Session-Id` to 256 chars for sticky routing (from `cache.key` ?? legacy `cacheKey` ?? `sessionId`); kernel defaults supply `system_prompt` + `last_stable_message` breakpoints so agent-session requests use per-message markers (not top-level automatic). Raw `generate` with empty breakpoints still emits top-level automatic `cache_control: { type: "ephemeral" }`; `"long"` retention adds `ttl: "1h"` when the model allows it. `prompt_tokens_details.cached_tokens`/`cache_write_tokens` map to `Usage.cacheReadTokens`/`cacheWriteTokens`. Optional `listOpenRouterModels()` may populate `ModelConfig.cache`/`cost` from live pricing.
177
179
  - OpenCode Go (`@arnilo/prism-providers/opencode-go`): default base `https://opencode.ai/zen/go/v1`; `x-opencode-session` from `cacheKey ?? sessionId`, sanitized to 128 chars; the Anthropic route (MiniMax/Qwen) applies `cache_control` markers only to selected breakpoints (`"long"` → `ttl: "1h"`), the OpenAI route (Grok/GLM/Kimi/MiMo/DeepSeek) sends none and preserves `reasoning_content`. OpenAI route maps `prompt_tokens_details.cached_tokens`/`cache_write_tokens`; Anthropic route maps `cache_read_input_tokens`/`cache_creation_input_tokens`. Caller-gated `listOpenCodeGoModels` against official `GET /zen/go/v1/models`.
178
180
  - Hyper (`@arnilo/prism-providers/hyper`): `kind: "implicit"` on the chat route, `kind: "cache_control"` on the messages route. Model route selection follows the live catalog's pricing shape: models with explicit cache-write pricing (qwen3.6-*) default to the Anthropic route; the rest stay chat-route implicit with the write fee recorded in `cost.cacheWrite`. The messages route applies `cache_control: { type: "ephemeral" }` only to caller-selected `cache.breakpoints` (shared `applyCacheControl`, max 4) — never every block, and **never a `ttl`** (Hyper documents no TTL values). Chat route maps `prompt_tokens_details.cached_tokens`/`cache_write_tokens` (and `prompt_cache_hit_tokens`); messages route maps `cache_read_input_tokens`/`cache_creation_input_tokens`. `parseHyperUsageCost` surfaces USD/cost/remaining Hypercredits from the OpenAI usage chunk for cost telemetry; `402 billing_error` is the drained-balance signal. Caller-gated `listHyperModels`; operator-gated `getHyperCredits`.
179
181
  - Command Code (`@arnilo/prism-providers/commandcode`): `kind: "implicit"` on the chat route, `kind: "cache_control"` on the messages route. `claude-*` tiers (the only Anthropic-route models by server-enforced routing) default to `cache_control` with markers only on caller-selected `cache.breakpoints` max 4 — never every block, and **never a `ttl`** (the upstream TTL window is undocumented). GPT-5.6 sol/terra/luna keep the docs cache-write price in `cost.cacheWrite` but stay `implicit` until the live `prompt_cache_key` probe passes (plan 055 Task 9); all other chat-route models are implicit with `prompt_cache_hit_tokens`/`cached_tokens` mapped by the shared OpenAI usage mapping. Messages route maps `cache_read_input_tokens`/`cache_creation_input_tokens`. Billing caveats: OSS models bill at the mean per-provider price; DeepSeek off-peak rates (17h/day) with ~2× peak 01–04 & 06–10 UTC; deals (MiniMax M3, MiMo) auto-applied. Caller-gated `listCommandCodeModels`; optional ZDR (`zdr: true`) adds `x-cmd-zdr: 1` and may route to costlier upstreams or fail `422 cmd_zdr_no_providers`.
@@ -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.5.0 |
29
- | `@arnilo/prism-providers/alibaba` | 0.5.0 |
30
- | `@arnilo/prism-providers/anthropic` | 0.5.0 |
31
- | `@arnilo/prism-providers/azure` | 0.5.0 |
32
- | `@arnilo/prism-providers/bedrock` | 0.5.0 |
33
- | `@arnilo/prism-providers/clinepass` | 0.5.0 |
34
- | `@arnilo/prism-providers/commandcode` | 0.5.0 |
35
- | `@arnilo/prism-providers/deepseek` | 0.5.0 |
36
- | `@arnilo/prism-providers/google` | 0.5.0 |
37
- | `@arnilo/prism-providers/hyper` | 0.5.0 |
38
- | `@arnilo/prism-providers/kimi` | 0.5.0 |
39
- | `@arnilo/prism-providers/model-discovery` | 0.5.0 |
40
- | `@arnilo/prism-providers/neuralwatt` | 0.5.0 |
41
- | `@arnilo/prism-providers/ollama` | 0.5.0 |
42
- | `@arnilo/prism-providers/openai` | 0.5.0 |
43
- | `@arnilo/prism-providers/opencode-go` | 0.5.0 |
44
- | `@arnilo/prism-providers/openrouter` | 0.5.0 |
45
- | `@arnilo/prism-providers/vertex` | 0.5.0 |
46
- | `@arnilo/prism-providers/xai` | 0.5.0 |
47
- | `@arnilo/prism-providers/zai` | 0.5.0 |
28
+ | `@arnilo/prism-providers/ai-sdk` | 0.5.2 |
29
+ | `@arnilo/prism-providers/alibaba` | 0.5.2 |
30
+ | `@arnilo/prism-providers/anthropic` | 0.5.2 |
31
+ | `@arnilo/prism-providers/azure` | 0.5.2 |
32
+ | `@arnilo/prism-providers/bedrock` | 0.5.2 |
33
+ | `@arnilo/prism-providers/clinepass` | 0.5.2 |
34
+ | `@arnilo/prism-providers/commandcode` | 0.5.2 |
35
+ | `@arnilo/prism-providers/deepseek` | 0.5.2 |
36
+ | `@arnilo/prism-providers/google` | 0.5.2 |
37
+ | `@arnilo/prism-providers/hyper` | 0.5.2 |
38
+ | `@arnilo/prism-providers/kimi` | 0.5.2 |
39
+ | `@arnilo/prism-providers/model-discovery` | 0.5.2 |
40
+ | `@arnilo/prism-providers/neuralwatt` | 0.5.2 |
41
+ | `@arnilo/prism-providers/ollama` | 0.5.2 |
42
+ | `@arnilo/prism-providers/openai` | 0.5.2 |
43
+ | `@arnilo/prism-providers/opencode-go` | 0.5.2 |
44
+ | `@arnilo/prism-providers/openrouter` | 0.5.2 |
45
+ | `@arnilo/prism-providers/vertex` | 0.5.2 |
46
+ | `@arnilo/prism-providers/xai` | 0.5.2 |
47
+ | `@arnilo/prism-providers/zai` | 0.5.2 |
48
48
  <!-- generated:package-truth:providers end -->
49
49
 
50
50
 
@@ -90,18 +90,15 @@ export default defineProviderPackage({
90
90
 
91
91
  `compat` is provider-owned inert JSON. Core does not branch on provider names or interpret vendor-specific fields.
92
92
 
93
- Provider packages can also contribute auth descriptors and request policies without resolving credentials:
93
+ Provider packages can also contribute auth descriptors and prompt layers without resolving credentials:
94
94
 
95
95
  ```ts
96
- import { createSessionCachePolicy } from "@arnilo/prism";
97
-
98
96
  api.registerAuthMethod({ provider: "demo", kind: "api_key", credentialName: "apiKey" });
99
97
  api.registerAuthMethod({ provider: "demo", kind: "oauth", oauth: demoOAuthProvider });
100
- api.registerProviderRequestPolicy(createSessionCachePolicy({ retention: "short" }));
101
98
  api.registerSystemPromptContribution({ id: "demo-prompt", source: "package", mode: "append", text: "Use demo provider rules." });
102
99
  ```
103
100
 
104
- Hosts decide which credential resolvers, env objects, OAuth stores, request policies, and prompt contributions become active. Request policies can set generic `ProviderRequest.options` such as `sessionId`, `cacheRetention`, `headers`, `compat`, and opaque `extra`; provider adapters decide how to map those options to provider payloads. Caller headers are extension headers only: provider adapters must apply provider-owned headers (auth, content type, session/cache/security, attribution) after caller headers so requests cannot override credentials or provider policy.
101
+ Host picks provider + model + intent (messages, tools, optional `thinkingLevel` / cache retention). Prism constructs a valid wire request for every generate site it owns. Host request policies are overlays — they are never required for success. Hosts still own credentials, env objects, OAuth stores, extra headers, custom `cacheKey`, `compat`/`extra` overlays, and which prompt contributions become active. Request policies can overlay generic `ProviderRequest.options` such as `sessionId`, `cacheRetention`, `headers`, `compat`, and opaque `extra`; provider adapters map those options to provider payloads. Caller headers are extension headers only: provider adapters must apply provider-owned headers (auth, content type, session/cache/security, attribution) after caller headers so requests cannot override credentials or provider policy.
105
102
 
106
103
  Provider request options: `ProviderRequestOptions` carries session/cache/header/compat/extra hints only. Timeouts are host-owned (`RunOptions.signal`/host abort controllers); retries are runtime-owned (`AgentConfig.retry`/`RunOptions.retry`). Provider-level timeout/retry hints were removed in 0.1.5. Provider packages should not add provider-specific retry loops unless the vendor protocol requires it and runtime retry cannot cover the failure mode.
107
104
 
@@ -294,10 +291,10 @@ Provider package manifest contribution and the generic request options a provide
294
291
 
295
292
  ## Implementation example
296
293
 
297
- Wire a provider package with model metadata plus a session cache policy through the extension kernel:
294
+ Wire a provider package with model metadata through the extension kernel. Session correlation and cache defaults are kernel-constructed — do not register `createSessionCachePolicy` for request success:
298
295
 
299
296
  ```ts
300
- import { createExtensionKernel, defineProviderPackage, createSessionCachePolicy } from "@arnilo/prism";
297
+ import { createExtensionKernel, defineProviderPackage } from "@arnilo/prism";
301
298
 
302
299
  const pkg = defineProviderPackage({
303
300
  name: "demo-provider",
@@ -312,7 +309,6 @@ const pkg = defineProviderPackage({
312
309
  cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, currency: "USD" },
313
310
  compat: { vendorSpecific: true },
314
311
  });
315
- api.registerProviderRequestPolicy(createSessionCachePolicy({ retention: "short" }));
316
312
  },
317
313
  });
318
314
 
@@ -322,13 +318,13 @@ await kernel.load([pkg]);
322
318
 
323
319
  ## Extension and configuration notes
324
320
 
325
- - Hosts decide which credential resolvers, env objects, OAuth stores, request
326
- policies, and prompt contributions become active; the package only *declares*
327
- them.
328
- - `createSessionCachePolicy()` acts as a concrete cache policy hook
329
- (`provider_request`) that sets generic `ProviderRequest.options`
321
+ - Hosts own credentials, env objects, OAuth stores, extra headers, custom `cacheKey`,
322
+ `compat`/`extra`, and which prompt contributions become active; the package only *declares*
323
+ them. Prism constructs session/cache/thinking options for owned generate sites.
324
+ - `createSessionCachePolicy()` is an optional host overlay (`provider_request` cache policy hook)
325
+ that sets generic `ProviderRequest.options`
330
326
  (`sessionId`, `cacheKey`, `cacheRetention`, `headers`, opaque `extra`) before
331
- `AIProvider.generate()`; provider adapters map those options to provider payloads.
327
+ `AIProvider.generate()`; provider adapters map those options to provider payloads. Not required for request success.
332
328
  - `ModelConfig.cache` is the generic cache capability metadata documented in [Model registry](model-registry.md); `ModelConfig.compat` remains provider-owned inert JSON for behavior that has no generic field yet.
333
329
  - `ModelConfig.compat` is provider-owned inert JSON: cache policy overrides,
334
330
  reasoning/thinking formats, and provider-specific usage mapping live there
@@ -6,15 +6,17 @@ Provider request policies are small host/package hooks that can adjust `Provider
6
6
 
7
7
  Public helpers:
8
8
 
9
+ - `applyDefaultProviderRequestOptions(request, { sessionId, thinkingLevel })` is the kernel constructor. Fill-if-missing `sessionId` / `cacheKey`; default cache breakpoints + `cacheRetention: "short"` when `model.cache.kind` is `cache_control` or `explicitBreakpoints` is true; optional `thinkingLevel` patches via `applyThinkingLevelForModel` after those fills. Host values win. Agent sessions, observational-memory workers, and LLM compaction already call it.
10
+ - `ProviderRequirementError` (`ERR_PRISM_PROVIDER_REQUIREMENT`) is the fail-fast typed error adapters throw when a mandatory option is still missing (OpenCode Go `sessionId` → `x-opencode-session`). Thrown before fetch; messages contain no request bodies or secrets.
9
11
  - `createProviderRequestPolicyChain(policies)` runs policies in order.
10
- - `createSessionCachePolicy(options)` sets legacy `cacheKey` / `cacheRetention` aliases from `sessionId`.
12
+ - `createSessionCachePolicy(options)` is a host overlay that sets legacy `cacheKey` / `cacheRetention` aliases from `sessionId`. Not required for request success.
11
13
  - `mergeProviderRequestOptions(base, patch)` merges request options, including structured `cache` hints.
12
14
 
13
15
  ## When to use it
14
16
 
15
- Use provider request policies when an app or provider package needs to set generic per-request options such as cache hints, caller-owned headers, `compat`, or `extra` without changing every provider call site.
17
+ Use `createAgent({ thinkingLevel })` / `session.run(input, { thinkingLevel })` for session intent. Use `applyDefaultProviderRequestOptions` on custom `provider.generate` sites. Use provider request policies only as overlays (custom `cacheKey`, extra headers, `compat`/`extra`) — never to make a request valid.
16
18
 
17
- Do not use request policies to resolve credentials, read env vars, perform OAuth refresh, fetch model lists, or override provider-owned auth/session/security headers.
19
+ Do not use request policies to resolve credentials, read env vars, perform OAuth refresh, fetch model lists, or override provider-owned auth/session/security headers. Session and cache keys are correlation ids, never secrets.
18
20
 
19
21
  ## Inputs / request
20
22
 
@@ -24,9 +26,11 @@ import type { ProviderRequestPolicy, ProviderRequestPolicyContext, ProviderReque
24
26
 
25
27
  | API | Input | Purpose |
26
28
  | --- | --- | --- |
29
+ | `applyDefaultProviderRequestOptions(request, ctx)` | `{ sessionId?, thinkingLevel? }` | Fill-if-missing `sessionId` / `cacheKey`; cache defaults from `model.cache`; thinking patch. |
30
+ | `ProviderRequirementError` | `message`, `{ requirement, providerId? }` | Typed missing-requirement error. |
27
31
  | `ProviderRequestPolicy.apply(context)` | `{ sessionId?, request, options? }` | Returns a patched request or options. |
28
32
  | `createProviderRequestPolicyChain(policies)` | ordered policies | Applies patches in order. |
29
- | `createSessionCachePolicy({ retention?, cacheKey? })` | optional cache defaults | Sets legacy aliases. |
33
+ | `createSessionCachePolicy({ retention?, cacheKey? })` | optional cache overlay | Sets legacy aliases after kernel defaults. |
30
34
  | `mergeProviderRequestOptions(base, patch)` | two option bags | Shallow merges scalars and structurally merges `cache`. |
31
35
 
32
36
  `mergeProviderRequestOptions()` behavior:
@@ -62,12 +66,21 @@ No agent events are emitted by the policy chain itself.
62
66
 
63
67
  ```ts
64
68
  import {
69
+ applyDefaultProviderRequestOptions,
65
70
  createProviderRequestPolicyChain,
66
71
  createSessionCachePolicy,
67
72
  mergeProviderRequestOptions,
73
+ ProviderRequirementError,
68
74
  type ProviderRequestPolicy,
69
75
  } from "@arnilo/prism";
70
76
 
77
+ const stamped = applyDefaultProviderRequestOptions(request, {
78
+ sessionId: session.id,
79
+ thinkingLevel: "low",
80
+ });
81
+ // stamped.options.sessionId === request.options?.sessionId ?? session.id
82
+ // cache_control models also get default cache.breakpoints unless the host set mode/off / retention/none / explicit breakpoints
83
+
71
84
  const structuredCache: ProviderRequestPolicy = {
72
85
  name: "demo.structured-cache",
73
86
  apply({ request }) {
@@ -93,7 +106,7 @@ const chain = createProviderRequestPolicyChain([
93
106
 
94
107
  ## Extension and configuration notes
95
108
 
96
- Provider packages can register request policies during `defineProviderPackage().setup(api)`. Hosts decide which packages/policies load and in which order. Prism has no hidden provider request policy registry and no automatic provider-specific cache behavior in core.
109
+ Provider packages can register request policies during `defineProviderPackage().setup(api)`. Hosts decide which overlay policies load and in which order. Prism has no hidden provider request policy registry. Kernel construction (`applyDefaultProviderRequestOptions`) already fills session/cache/thinking from `model.cache` and run intent — package-registered policies are never auto-activated and never required for success.
97
110
 
98
111
  Policy output should stay generic: use `ProviderRequestOptions.cache`, `headers`, `compat`, and `extra` instead of provider-name branches in core.
99
112
 
@@ -150,6 +150,18 @@ Official evidence: [Custom providers / LanguageModelV4](https://ai-sdk.dev/provi
150
150
  - `options.compat` / `options.extra` pass through as AI SDK `providerOptions.prism`.
151
151
  - Export helpers `toAiSdkCallOptions`, `toAiSdkPrompt`, and `mapAiSdkStream` for tests and custom hosts.
152
152
 
153
+ ## Request construction (0.5.1)
154
+
155
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
156
+
157
+ | | |
158
+ | --- | --- |
159
+ | P1 session wire | none |
160
+ | Mandatory | no |
161
+ | P2 default cache | host-owned, no Prism cache fields |
162
+
163
+ See [Provider request policies](../provider-request-policies.md).
164
+
153
165
  ## Security and performance notes
154
166
 
155
167
  - Host credentials stay inside the supplied AI SDK model. The adapter never reads env keys or credential stores.
@@ -245,6 +245,18 @@ await kernel.load([
245
245
  - Usage accounting: `cached_tokens` → `Usage.cacheReadTokens`,
246
246
  `cache_creation_input_tokens` → `Usage.cacheWriteTokens`.
247
247
 
248
+ ## Request construction (0.5.1)
249
+
250
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
251
+
252
+ | | |
253
+ | --- | --- |
254
+ | P1 session wire | none |
255
+ | Mandatory | no |
256
+ | P2 default cache | only if `model.cache.kind === "cache_control"` |
257
+
258
+ See [Provider request policies](../provider-request-policies.md).
259
+
248
260
  ## Security and performance notes
249
261
 
250
262
  - SSE streams and HTTP error bodies use bounded `@arnilo/prism/providers/transport`
@@ -77,6 +77,18 @@ api.registerProviderPackage(createAnthropicProviderPackage({ apiKey: hostKey, mo
77
77
  - Live smoke: `PRISM_LIVE_PROVIDER_TESTS=1` + `ANTHROPIC_API_KEY`.
78
78
  - Anthropic says OAuth is for purchasers' ordinary Claude Code/native-app use; developers building products must use Claude Console API keys or a supported cloud provider and may not offer Claude.ai login or route Free/Pro/Max credentials ([legal and compliance](https://docs.anthropic.com/en/docs/claude-code/legal-and-compliance)). Prism therefore has no Anthropic subscription OAuth API or token-import shortcut.
79
79
 
80
+ ## Request construction (0.5.1)
81
+
82
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
83
+
84
+ | | |
85
+ | --- | --- |
86
+ | P1 session wire | `x-client-request-id` from `sessionId` |
87
+ | Mandatory | no |
88
+ | P2 default cache | `cache_control` on `system_prompt` + `last_stable_message`; `cacheRetention: "short"` |
89
+
90
+ See [Provider request policies](../provider-request-policies.md).
91
+
80
92
  ## Security and performance notes
81
93
 
82
94
  - No network during import/setup/default tests; credentials host-owned and late-bound.
@@ -58,6 +58,18 @@ Opt-in live canaries: inject real `fetch` + host credential behind host CI secre
58
58
 
59
59
  Register via `createExtensionKernel().load([createAzureOpenAIProviderPackage(...)])`. Pair with `@arnilo/prism-core/governance/model-router` for residency allow-lists on Azure regions/endpoints.
60
60
 
61
+ ## Request construction (0.5.1)
62
+
63
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
64
+
65
+ | | |
66
+ | --- | --- |
67
+ | P1 session wire | none |
68
+ | Mandatory | no |
69
+ | P2 default cache | host-owned, no Prism cache fields |
70
+
71
+ See [Provider request policies](../provider-request-policies.md).
72
+
61
73
  ## Security and performance notes
62
74
 
63
75
  - No credential prefetch at import; the credential is resolved exactly once per request (a rotating `CredentialValueSource` is never consumed twice — the same resolved token drives the wrapper check and the inner auth header).
@@ -57,6 +57,18 @@ Live canaries stay opt-in behind host credentials; default tests are network-fre
57
57
 
58
58
  Uses Bedrock’s OpenAI-compatible runtime route (not Converse eventstream). Hosts needing Converse-only models should supply a custom provider or AI SDK bridge.
59
59
 
60
+ ## Request construction (0.5.1)
61
+
62
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
63
+
64
+ | | |
65
+ | --- | --- |
66
+ | P1 session wire | none |
67
+ | Mandatory | no |
68
+ | P2 default cache | host-owned, no Prism cache fields |
69
+
70
+ See [Provider request policies](../provider-request-policies.md).
71
+
60
72
  ## Security and performance notes
61
73
 
62
74
  - No AWS SDK; package-local SigV4 only for `bedrock` service.
@@ -98,6 +98,18 @@ await session.prompt("Plan the refactor", {
98
98
  - Multi-backend gateway: key compat off `api.cline.bot`, not the upstream vendor.
99
99
  - Reference USD-per-million costs are catalog metadata; ClinePass itself is a subscription.
100
100
 
101
+ ## Request construction (0.5.1)
102
+
103
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
104
+
105
+ | | |
106
+ | --- | --- |
107
+ | P1 session wire | none; strips `cache_control` |
108
+ | Mandatory | no |
109
+ | P2 default cache | implicit, no markers |
110
+
111
+ See [Provider request policies](../provider-request-policies.md).
112
+
101
113
  ## Security and performance notes
102
114
 
103
115
  - No network on import, setup, build, or default tests.
@@ -212,6 +212,18 @@ PRISM_LIVE_PROVIDER_TESTS=1 COMMAND_CODE_API_KEY=cmd_... \
212
212
  npm run test --workspace=@arnilo/prism-providers/commandcode
213
213
  ```
214
214
 
215
+ ## Request construction (0.5.1)
216
+
217
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
218
+
219
+ | | |
220
+ | --- | --- |
221
+ | P1 session wire | none |
222
+ | Mandatory | no |
223
+ | P2 default cache | Anthropic: `cache_control`; OpenAI: implicit (no `prompt_cache_key`) |
224
+
225
+ See [Provider request policies](../provider-request-policies.md).
226
+
215
227
  ## Security and performance notes
216
228
 
217
229
  - SSE streams and HTTP error bodies use bounded `@arnilo/prism/providers/transport` helpers.
@@ -119,6 +119,18 @@ await session.prompt("Plan the refactor", {
119
119
  - Tool-turn assistants must replay `reasoning_content` or the API returns 400.
120
120
  Non-tool multi-turn may omit it (the API ignores it).
121
121
 
122
+ ## Request construction (0.5.1)
123
+
124
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
125
+
126
+ | | |
127
+ | --- | --- |
128
+ | P1 session wire | none |
129
+ | Mandatory | no |
130
+ | P2 default cache | implicit, no markers |
131
+
132
+ See [Provider request policies](../provider-request-policies.md).
133
+
122
134
  ## Security and performance notes
123
135
 
124
136
  - SSE streams and HTTP error bodies use bounded transport helpers.
@@ -73,6 +73,18 @@ api.registerProviderPackage(createGoogleProviderPackage({ apiKey: hostKey, model
73
73
  - Vertex / enterprise identity stays out of 0.0.11.
74
74
  - Gemini CLI says third-party software accessing its backend through Gemini CLI OAuth violates applicable terms, and its FAQ directs third-party coding agents to Vertex AI or Google AI Studio API keys ([terms](https://github.com/google-gemini/gemini-cli/blob/main/docs/resources/tos-privacy.md), [FAQ](https://github.com/google-gemini/gemini-cli/blob/main/docs/resources/faq.md)). Prism therefore has no Gemini CLI OAuth API or token-import shortcut.
75
75
 
76
+ ## Request construction (0.5.1)
77
+
78
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
79
+
80
+ | | |
81
+ | --- | --- |
82
+ | P1 session wire | `x-client-request-id` from `sessionId` |
83
+ | Mandatory | no |
84
+ | P2 default cache | none (no Prism cache markers) |
85
+
86
+ See [Provider request policies](../provider-request-policies.md).
87
+
76
88
  ## Security and performance notes
77
89
 
78
90
  - No network during import/setup/default tests; credentials host-owned and late-bound.
@@ -245,6 +245,18 @@ PRISM_LIVE_PROVIDER_TESTS=1 HYPER_API_KEY=sk-hyper-... \
245
245
  npm run test --workspace=@arnilo/prism-providers/hyper
246
246
  ```
247
247
 
248
+ ## Request construction (0.5.1)
249
+
250
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
251
+
252
+ | | |
253
+ | --- | --- |
254
+ | P1 session wire | Responses: `prompt_cache_key`; chat/Anthropic: no session header |
255
+ | Mandatory | no |
256
+ | P2 default cache | Anthropic: `cache_control`; Responses: openai_key rules; chat: implicit |
257
+
258
+ See [Provider request policies](../provider-request-policies.md).
259
+
248
260
  ## Security and performance notes
249
261
 
250
262
  - SSE streams and HTTP error bodies use bounded `@arnilo/prism/providers/transport` helpers.
@@ -185,6 +185,18 @@ await kernel.load([
185
185
  - Coding usage: `cache_read_input_tokens` → `Usage.cacheReadTokens`,
186
186
  `cache_creation_input_tokens` → `Usage.cacheWriteTokens`.
187
187
 
188
+ ## Request construction (0.5.1)
189
+
190
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
191
+
192
+ | | |
193
+ | --- | --- |
194
+ | P1 session wire | none extra |
195
+ | Mandatory | no |
196
+ | P2 default cache | Anthropic/Coding: `cache_control`; Moonshot: none |
197
+
198
+ See [Provider request policies](../provider-request-policies.md).
199
+
188
200
  ## Security and performance notes
189
201
 
190
202
  - SSE streams and HTTP error bodies use bounded `@arnilo/prism/providers/transport`
@@ -360,6 +360,18 @@ const decision = classifyNeuralWattError({ status: 429, headers: { "retry-after"
360
360
  // { retryable: true, code: 429, retryAfterMs: 1000, errorCode: "concurrent_budget_exceeded", strategy: undefined }
361
361
  ```
362
362
 
363
+ ## Request construction (0.5.1)
364
+
365
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
366
+
367
+ | | |
368
+ | --- | --- |
369
+ | P1 session wire | none |
370
+ | Mandatory | no |
371
+ | P2 default cache | implicit, no markers |
372
+
373
+ See [Provider request policies](../provider-request-policies.md).
374
+
363
375
  ## Security and performance notes
364
376
 
365
377
  - SSE streams, HTTP error bodies, and quota/model-discovery failures use bounded `@arnilo/prism/providers/transport` helpers (`readSseEvents`, `readBoundedResponseText`). NeuralWatt `: energy` / `: cost` comment frames are surfaced via `readSseEvents` `comments` and mapped locally.
@@ -139,6 +139,18 @@ await kernel.load([
139
139
  `Usage.cacheReadTokens` is intentionally left `undefined` (not `0`). If a future
140
140
  Ollama release reports cached tokens, map them in `mapOllamaModel`/usage handling.
141
141
 
142
+ ## Request construction (0.5.1)
143
+
144
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
145
+
146
+ | | |
147
+ | --- | --- |
148
+ | P1 session wire | none |
149
+ | Mandatory | no |
150
+ | P2 default cache | implicit, no markers |
151
+
152
+ See [Provider request policies](../provider-request-policies.md).
153
+
142
154
  ## Security and performance notes
143
155
 
144
156
  - SSE streams and HTTP error bodies use bounded `@arnilo/prism/providers/transport`
@@ -139,6 +139,18 @@ const provider = createOpenAICompatibleProvider({
139
139
 
140
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-providers/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`.
141
141
 
142
+ ## Request construction (0.5.1)
143
+
144
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
145
+
146
+ | | |
147
+ | --- | --- |
148
+ | P1 session wire | none (factory sends no session/cache wire) |
149
+ | Mandatory | no |
150
+ | P2 default cache | none unless the vendor adapter maps options |
151
+
152
+ See [Provider request policies](../provider-request-policies.md).
153
+
142
154
  ## Security and performance notes
143
155
 
144
156
  - Credentials are host-owned and resolved only when `generate()` runs.
@@ -207,6 +207,18 @@ Official: [Reasoning models](https://developers.openai.com/api/docs/guides/reaso
207
207
  `response.output_item.added` + `response.function_call_arguments.delta`
208
208
  (string `delta`), not Chat Completions object deltas.
209
209
 
210
+ ## Request construction (0.5.1)
211
+
212
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
213
+
214
+ | | |
215
+ | --- | --- |
216
+ | P1 session wire | `prompt_cache_key` from `cacheKey??sessionId`; `x-client-request-id` from `sessionId` |
217
+ | Mandatory | no |
218
+ | P2 default cache | GPT-5.6+ `explicitBreakpoints` → `prompt_cache_breakpoint` + `cacheRetention: "short"`; older families none |
219
+
220
+ See [Provider request policies](../provider-request-policies.md).
221
+
210
222
  ## Security and performance notes
211
223
 
212
224
  - SSE streams and HTTP error bodies use bounded `@arnilo/prism/providers/transport` helpers (`readSseData`, `readBoundedResponseText`).
@@ -233,6 +233,18 @@ Owned compat keys (`route`, `thinking`, `reasoning`, `reasoning_effort`,
233
233
  `Usage.cacheReadTokens`/`cacheWriteTokens`; the Anthropic route maps
234
234
  `cache_read_input_tokens`/`cache_creation_input_tokens`.
235
235
 
236
+ ## Request construction (0.5.1)
237
+
238
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
239
+
240
+ | | |
241
+ | --- | --- |
242
+ | P1 session wire | `x-opencode-session` from `cacheKey??sessionId` |
243
+ | Mandatory | **yes** — missing id throws `ProviderRequirementError` (`ERR_PRISM_PROVIDER_REQUIREMENT`) before fetch; message has no request body |
244
+ | P2 default cache | Anthropic route: `cache_control` markers; OpenAI route: none |
245
+
246
+ See [Provider request policies](../provider-request-policies.md).
247
+
236
248
  ## Security and performance notes
237
249
 
238
250
  - SSE streams and HTTP error bodies use bounded `@arnilo/prism/providers/transport` helpers (`readSseData`, `readBoundedResponseText`).
@@ -174,6 +174,18 @@ for Anthropic/Qwen/Gemini families with cache pricing; otherwise `implicit` when
174
174
  cache-read pricing exists), and seeds `compat.reasoning.effort` from
175
175
  `reasoning.default_effort` when present.
176
176
 
177
+ ## Request construction (0.5.1)
178
+
179
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
180
+
181
+ | | |
182
+ | --- | --- |
183
+ | P1 session wire | `x-session-id` + body `session_id` |
184
+ | Mandatory | no |
185
+ | P2 default cache | kernel defaults → per-message `cache_control` (not top-level automatic) |
186
+
187
+ See [Provider request policies](../provider-request-policies.md).
188
+
177
189
  ## Security and performance notes
178
190
 
179
191
  - SSE streams and HTTP error bodies use bounded `@arnilo/prism/providers/transport` helpers (`readSseData`, `readBoundedResponseText`).
@@ -55,6 +55,18 @@ const provider = createVertexProvider({
55
55
 
56
56
  `@arnilo/prism-providers/google` remains API-key Gemini (`generativelanguage.googleapis.com`) and must not register Vertex OAuth/ADC. Load this package explicitly for Vertex.
57
57
 
58
+ ## Request construction (0.5.1)
59
+
60
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
61
+
62
+ | | |
63
+ | --- | --- |
64
+ | P1 session wire | none |
65
+ | Mandatory | no |
66
+ | P2 default cache | host-owned, no Prism cache fields |
67
+
68
+ See [Provider request policies](../provider-request-policies.md).
69
+
58
70
  ## Security and performance notes
59
71
 
60
72
  - No Google Cloud SDK dependency in the package.
@@ -115,6 +115,18 @@ await kernel.load([
115
115
  - Reasoning models replay `reasoning_content` and do not flatten thinking into text.
116
116
  - Generate always hits `https://api.x.ai/v1/chat/completions` (same backend for API key and SuperGrok access).
117
117
 
118
+ ## Request construction (0.5.1)
119
+
120
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
121
+
122
+ | | |
123
+ | --- | --- |
124
+ | P1 session wire | `x-grok-conv-id` from `cache.key??cacheKey??sessionId` |
125
+ | Mandatory | no |
126
+ | P2 default cache | implicit; header is the correlation |
127
+
128
+ See [Provider request policies](../provider-request-policies.md).
129
+
118
130
  ## Security and performance notes
119
131
 
120
132
  - Public client id is documented as not a secret. Device/user/access/refresh codes are redacted.
@@ -139,6 +139,18 @@ await session.prompt("Plan the refactor", {
139
139
  and `prompt_tokens_details.cache_write_tokens` → `Usage.cacheWriteTokens` when
140
140
  the server reports them.
141
141
 
142
+ ## Request construction (0.5.1)
143
+
144
+ Agent sessions stamp `sessionId`/`cacheKey` without a host policy. Session/cache keys are correlation ids, never secrets.
145
+
146
+ | | |
147
+ | --- | --- |
148
+ | P1 session wire | none |
149
+ | Mandatory | no |
150
+ | P2 default cache | implicit, no markers |
151
+
152
+ See [Provider request policies](../provider-request-policies.md).
153
+
142
154
  ## Security and performance notes
143
155
 
144
156
  - SSE streams and HTTP error bodies use bounded `@arnilo/prism/providers/transport`