@arnilo/prism 0.0.14 → 0.0.15
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 +11 -2
- package/README.md +5 -4
- package/dist/agent-loops.d.ts +4 -0
- package/dist/agent-loops.js +16 -3
- package/dist/contracts.d.ts +76 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/provider-events.d.ts +1 -0
- package/dist/provider-events.js +3 -0
- package/docs/host-security.md +4 -1
- package/docs/index.md +12 -11
- package/docs/migration.md +29 -1
- package/docs/multimodal-content.md +8 -5
- package/docs/performance.md +34 -0
- package/docs/provider-caching.md +8 -0
- package/docs/provider-conformance.md +29 -5
- package/docs/provider-packages.md +22 -1
- package/docs/providers/ai-sdk.md +23 -7
- package/docs/providers/openai.md +22 -3
- package/docs/rag.md +41 -12
- package/docs/release-and-install.md +62 -14
- package/docs/resource-loading.md +3 -0
- package/docs/review-coverage-2026-07-26-phase-10.md +132 -0
- package/docs/working-and-semantic-memory.md +22 -4
- package/package.json +1 -1
|
@@ -21,7 +21,28 @@ Use these helpers in provider package tests to check event order, terminal event
|
|
|
21
21
|
|
|
22
22
|
Do not use them as a live integration runner, provider simulator, retry framework, credential loader, or test framework replacement.
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
Offline conformance is mandatory for every package; credentialed probes are not uniform. Packages with a checked-in `live.test.ts` use `PRISM_LIVE_PROVIDER_TESTS=1` plus their provider key. Realtime, hosted tools, AI SDK host models, Alibaba/Ollama account or daemon paths, and enterprise workload identities need host-owned protected probes instead of a generic fixture. The default `npm test` never sets these gates and stays network-free; see [Release and install](release-and-install.md#015-protected-live-canary-matrix) for the exact environment/key boundary.
|
|
25
|
+
|
|
26
|
+
## Phase 10 provider conformance matrix
|
|
27
|
+
|
|
28
|
+
| Package | Required offline evidence | Restricted live evidence |
|
|
29
|
+
| --- | --- | --- |
|
|
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.3/V4 gate; every mapped stream part; authority, cache usage, redaction, unsupported mapping | Host-created V4 model only; no Prism credential fixture |
|
|
32
|
+
| Anthropic | Messages serialization, cache/thinking/tools, header/redaction/abort assertions | Protected `ANTHROPIC_API_KEY` smoke |
|
|
33
|
+
| Google | `generateContent` serialization, complete tool calls, media/abort/redaction assertions | Protected `GOOGLE_API_KEY` or `GEMINI_API_KEY` smoke |
|
|
34
|
+
| Kimi | Coding/Moonshot route fixtures, thinking/tool reconstruction, headers/redaction | Protected `KIMI_API_KEY` smoke |
|
|
35
|
+
| Z.AI | GLM thinking/tool-stream fixtures, implicit-cache usage, headers/redaction | Protected `ZAI_API_KEY` smoke |
|
|
36
|
+
| OpenRouter | routing/reasoning/cache-control fixture, stream/tool reconstruction, headers/redaction | Protected `OPENROUTER_API_KEY` smoke |
|
|
37
|
+
| OpenCode Go | OpenAI/Anthropic route fixture, completion proof, PDF/media boundary, headers/redaction | Protected `OPENCODE_API_KEY` smoke |
|
|
38
|
+
| Alibaba | DashScope presets, Qwen thinking, image rejection/mapping, cache/usage fixture | Protected account/region host probe; no generic key fixture |
|
|
39
|
+
| Ollama | cloud/local preset, reasoning/image mapping, implicit-cache fixture | Protected cloud or host-local authenticated daemon probe; no daemon starts in tests |
|
|
40
|
+
| NeuralWatt | stream/retry/quota/telemetry fixtures, implicit-cache usage, headers/redaction | Protected `NEURALWATT_API_KEY` smoke |
|
|
41
|
+
| Azure | endpoint preservation, Entra/resource-key header and OpenAI-compatible stream fixture | Protected host workload-identity probe |
|
|
42
|
+
| Bedrock | SigV4/region/PrivateLink and OpenAI-compatible stream fixture | Protected host IAM/IRSA probe |
|
|
43
|
+
| Vertex | location/endpoint preservation, ADC header and OpenAI-compatible stream fixture | Protected host ADC/WIF probe |
|
|
44
|
+
|
|
45
|
+
All rows must retain bounded request/response fixtures, abort propagation, provider-owned-header precedence, and fake-secret leak assertions where the package surfaces those values. A successful fake transport proves Prism mapping, not account entitlement or vendor availability.
|
|
25
46
|
|
|
26
47
|
## Inputs / request
|
|
27
48
|
|
|
@@ -50,6 +71,7 @@ Helpers accept normal `AIProvider`, `ProviderRequest`, `ProviderEvent`, `Usage`,
|
|
|
50
71
|
- `assertSerializedRequestCoversContent()` scans a serialized provider request body for primitive canaries from each Prism content block and fails if any supported block type is silently dropped. Provider-valid transcripts place assistant `tool_call` messages before matching role `tool` `tool_result` messages; runtime, cache-aware input layout, and observational-memory worker loops preserve that order before serialization.
|
|
51
72
|
- `assertProviderOwnedHeadersWin()` compares captured request headers against the provider's authoritative owned header values and a caller-supplied header bag; it fails if any owned header (`authorization`, `content-type`, session/security headers) was overridden by caller headers, and also fails if a non-owned caller header was dropped. This is the provider-neutral check that caller `ProviderRequest.options.headers` cannot hijack provider credentials or sessions; every first-party provider package exercises it.
|
|
52
73
|
- `assertNoSecretLeak()` stringifies all collected events and fails if any known secret string is present.
|
|
74
|
+
- Provider-hosted calls must surface as `tool_call` with `authority: "provider-hosted"`; loops record them but never dispatch them or append a host `tool_result`. Bounded continuations must emit an opaque cursor event and end in `done` or redacted `error`, never silent truncation.
|
|
53
75
|
|
|
54
76
|
## Request/response example
|
|
55
77
|
|
|
@@ -164,10 +186,12 @@ Canonical contract: [Thinking and reasoning](thinking-and-reasoning.md).
|
|
|
164
186
|
`@arnilo/prism-provider-ai-sdk` is a host-owned `LanguageModelV4` bridge. It does not participate in the discovery or thinking/reasoning checklists above. Cover instead:
|
|
165
187
|
|
|
166
188
|
1. **No catalog / no setup fetch** — package exports no `list*Models()`; `createAiSdkProvider` wraps a host model only.
|
|
167
|
-
2. **
|
|
168
|
-
3. **
|
|
169
|
-
4. **
|
|
170
|
-
5. **
|
|
189
|
+
2. **Version + specification gate** — exact `@ai-sdk/provider` matrix version is verified at setup; rejects version skew, non-v4 models (`specificationVersion !== "v4"`), or missing `doStream`.
|
|
190
|
+
3. **Mapping table** — fixture covers every supported matrix row: response metadata id, text/reasoning/tool deltas, client/provider-hosted tool authority, structured output, cache usage, finish/error/abort; unmappable stream parts and `structuredOutput.strict` fail typed instead of dropping.
|
|
191
|
+
4. **Cache usage mapping** — `finish.usage.inputTokens.cacheRead`/`cacheWrite` map to `Usage.cacheReadTokens`/`cacheWriteTokens`; adapter does not emit cache request fields.
|
|
192
|
+
5. **Reasoning stream mapping** — `reasoning-delta` → thinking deltas; assistant `thinking` blocks replay as AI SDK `reasoning` prompt parts.
|
|
193
|
+
6. **Redaction** — direct adapter errors use its supplied `SecretRedactor`; agent runs use their active redactor; opaque provider metadata is never emitted.
|
|
194
|
+
7. **Host-owned controls** — `options.compat` / `options.extra` forward as `providerOptions.prism`; reasoning effort stays on the host model.
|
|
171
195
|
|
|
172
196
|
Canonical contract: [AI SDK provider adapter](providers/ai-sdk.md).
|
|
173
197
|
|
|
@@ -80,7 +80,28 @@ Phase 6 also adds optional [`@arnilo/prism-provider-ai-sdk`](providers/ai-sdk.md
|
|
|
80
80
|
|
|
81
81
|
Provider live tests are real smoke tests gated by `PRISM_LIVE_PROVIDER_TESTS=1` plus the provider-specific API key (`OPENAI_API_KEY`, `OPENROUTER_API_KEY`, `KIMI_API_KEY`, `ZAI_API_KEY`, `NEURALWATT_API_KEY`, or `OPENCODE_API_KEY`). They cover text generation, tool-call loop behavior, abort/error paths where supported, and no-secret-leak assertions; they skip by default and never run in release verification.
|
|
82
82
|
|
|
83
|
-
These workspaces still follow the same rule as external packages: no provider SDK dependency, catalog fetch, env scan, keychain/file credential lookup, shell auth command, OAuth login, or live provider call runs by default. `@arnilo/prism-provider-openai` now registers OpenAI Responses and OpenAI Codex providers from caller-supplied credentials only, with optional `models`/`codexModels` overrides and an opt-in `listOpenAIModels()` helper for official `GET /models` discovery. `@arnilo/prism-provider-opencode-go` now registers docs-verified OpenCode Go open coding models with dual OpenAI/Anthropic routes (`compat.route`), official default base `https://opencode.ai/zen/go/v1`, `reasoning_content`/thinking preserve, and an opt-in `listOpenCodeGoModels()` helper for official `GET /zen/go/v1/models`. `@arnilo/prism-provider-openrouter` now registers an app-controlled OpenRouter catalog with routing/`reasoning`/cache passthrough, assistant `reasoning` replay, optional top-level automatic `cache_control`, and an opt-in `listOpenRouterModels()` helper for official `GET /api/v1/models` (setup still never fetches). `@arnilo/prism-provider-zai` now registers featured GLM-5.x/4.x metadata with official `thinking`/`reasoning_effort`/`tool_stream`/`clear_thinking` mapping, Preserved Thinking `reasoning_content` replay, implicit context caching, and an opt-in `listZaiModels()` helper for OpenAI-compatible `GET /models`. `@arnilo/prism-provider-kimi` now registers Kimi Coding Anthropic-compatible behavior by default, optional callable Moonshot Open Platform Chat Completions when `includeMoonshotModels` is requested, official Coding/Open Platform featured ids, thinking/`reasoning_effort` compat mapping, and an opt-in `listKimiModels()` helper for Moonshot `GET /v1/models`. `@arnilo/prism-provider-neuralwatt` now registers static featured model metadata with NeuralWatt reasoning_effort/thinking_token_budget/chat_template_kwargs request mapping, SSE comment tolerance, an opt-in `listNeuralWattModels()` helper for explicit `/v1/models` discovery, `getNeuralWattQuota()` for on-demand account balance/usage/energy, `neuralWattEventsWithTelemetry()`/`mapNeuralWattTelemetry()` for `: energy`/`: cost` telemetry, and `classifyNeuralWattError()` for retry classification. None of these helpers run during package setup or generation. `@arnilo/prism-provider-anthropic` registers native Anthropic Messages (`createAnthropicProviderPackage` / `listAnthropicModels`). `@arnilo/prism-provider-google` registers native Gemini `generateContent` streaming (`createGoogleProviderPackage` / `listGoogleModels`; Vertex identity
|
|
83
|
+
These workspaces still follow the same rule as external packages: no provider SDK dependency, catalog fetch, env scan, keychain/file credential lookup, shell auth command, OAuth login, or live provider call runs by default. `@arnilo/prism-provider-openai` now registers OpenAI Responses and OpenAI Codex providers from caller-supplied credentials only, with optional `models`/`codexModels` overrides and an opt-in `listOpenAIModels()` helper for official `GET /models` discovery. `@arnilo/prism-provider-opencode-go` now registers docs-verified OpenCode Go open coding models with dual OpenAI/Anthropic routes (`compat.route`), official default base `https://opencode.ai/zen/go/v1`, `reasoning_content`/thinking preserve, and an opt-in `listOpenCodeGoModels()` helper for official `GET /zen/go/v1/models`. `@arnilo/prism-provider-openrouter` now registers an app-controlled OpenRouter catalog with routing/`reasoning`/cache passthrough, assistant `reasoning` replay, optional top-level automatic `cache_control`, and an opt-in `listOpenRouterModels()` helper for official `GET /api/v1/models` (setup still never fetches). `@arnilo/prism-provider-zai` now registers featured GLM-5.x/4.x metadata with official `thinking`/`reasoning_effort`/`tool_stream`/`clear_thinking` mapping, Preserved Thinking `reasoning_content` replay, implicit context caching, and an opt-in `listZaiModels()` helper for OpenAI-compatible `GET /models`. `@arnilo/prism-provider-kimi` now registers Kimi Coding Anthropic-compatible behavior by default, optional callable Moonshot Open Platform Chat Completions when `includeMoonshotModels` is requested, official Coding/Open Platform featured ids, thinking/`reasoning_effort` compat mapping, and an opt-in `listKimiModels()` helper for Moonshot `GET /v1/models`. `@arnilo/prism-provider-neuralwatt` now registers static featured model metadata with NeuralWatt reasoning_effort/thinking_token_budget/chat_template_kwargs request mapping, SSE comment tolerance, an opt-in `listNeuralWattModels()` helper for explicit `/v1/models` discovery, `getNeuralWattQuota()` for on-demand account balance/usage/energy, `neuralWattEventsWithTelemetry()`/`mapNeuralWattTelemetry()` for `: energy`/`: cost` telemetry, and `classifyNeuralWattError()` for retry classification. None of these helpers run during package setup or generation. `@arnilo/prism-provider-anthropic` registers native Anthropic Messages (`createAnthropicProviderPackage` / `listAnthropicModels`). `@arnilo/prism-provider-google` registers native Gemini `generateContent` streaming (`createGoogleProviderPackage` / `listGoogleModels`; Vertex identity stays in the separate package). Both follow the same zero-setup-network / host-owned credential / provider-owned-header rules; see [`docs/providers/anthropic.md`](providers/anthropic.md) and [`docs/providers/google.md`](providers/google.md).
|
|
84
|
+
|
|
85
|
+
### Phase 10 compatibility matrix
|
|
86
|
+
|
|
87
|
+
Every package remains explicit, setup-zero-fetch, and late-credential-bound. `ModelConfig.capabilities.input` is authoritative: a listed wire mapping is usable only when the selected model declares that tag; unsupported blocks reject before provider I/O. “Protected” means an operator/release-environment probe, never default CI; its exact key/command boundary is in [Release and install](release-and-install.md#015-protected-live-canary-matrix).
|
|
88
|
+
|
|
89
|
+
| Package | Protocol / model source | Content mapping | Stream, tools, and reasoning | Cache / canary |
|
|
90
|
+
| --- | --- | --- | --- | --- |
|
|
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 matrix; protected host integration |
|
|
93
|
+
| Anthropic | Messages; caller-gated list | text, image, PDF document/file | tool deltas, thinking | `cache_control`; protected API-key smoke |
|
|
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
|
+
| 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 |
|
|
96
|
+
| Z.AI | OpenAI-compatible; caller-gated list | text, image | tool deltas, `reasoning_content` | implicit; protected API-key smoke |
|
|
97
|
+
| OpenRouter | OpenAI-compatible; host catalog + caller-gated list | text, image | tool deltas, reasoning replay/routing metadata | `cache_control`; protected API-key smoke |
|
|
98
|
+
| OpenCode Go | OpenAI or Anthropic route; caller-gated list | text/image OpenAI route; PDF document/file Anthropic route | tool deltas, route-native thinking | route-specific; protected API-key smoke |
|
|
99
|
+
| Alibaba | DashScope OpenAI-compatible; caller-gated list | text, image | tool deltas, Qwen thinking | implicit / optional markers; protected host probe |
|
|
100
|
+
| Ollama | Cloud/local OpenAI-compatible; caller-gated list | text, image | tool deltas, reasoning effort | implicit only; protected host/daemon probe |
|
|
101
|
+
| NeuralWatt | OpenAI-compatible; caller-gated list | text, image | tool deltas, reasoning and telemetry | implicit; protected API-key smoke |
|
|
102
|
+
| Azure | Azure/Foundry OpenAI-compatible; host models | selected endpoint/model capability | normalized OpenAI-compatible tools | no Prism cache mapping; protected host workload-identity probe |
|
|
103
|
+
| Bedrock | Bedrock OpenAI-compatible; host models | selected endpoint/model capability | normalized OpenAI-compatible tools | no Prism cache mapping; protected host IAM/IRSA probe |
|
|
104
|
+
| Vertex | Vertex OpenAPI-compatible; host models | selected endpoint/model capability | normalized OpenAI-compatible tools | no Prism cache mapping; protected host ADC/WIF probe |
|
|
84
105
|
|
|
85
106
|
### First-party cache behavior
|
|
86
107
|
|
package/docs/providers/ai-sdk.md
CHANGED
|
@@ -4,7 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
`@arnilo/prism-provider-ai-sdk` adapts a host-supplied AI SDK `LanguageModelV4` into a Prism `AIProvider`. It maps Prism messages, tools, and structured-output options into `doStream` call options, then translates stream parts into Prism provider events incrementally.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Core `@arnilo/prism` does not depend on the AI SDK.
|
|
8
|
+
|
|
9
|
+
### Supported-version matrix
|
|
10
|
+
|
|
11
|
+
| `@ai-sdk/provider` | `LanguageModel` ABI | Status |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| `4.0.3` | `LanguageModelV4`, `specificationVersion: "v4"` | Supported and offline-tested |
|
|
14
|
+
|
|
15
|
+
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.
|
|
8
16
|
|
|
9
17
|
## When to use it
|
|
10
18
|
|
|
@@ -19,6 +27,7 @@ import { createAiSdkProvider } from "@arnilo/prism-provider-ai-sdk";
|
|
|
19
27
|
|
|
20
28
|
createAiSdkProvider(options: {
|
|
21
29
|
model: LanguageModelV4;
|
|
30
|
+
redactor?: SecretRedactor;
|
|
22
31
|
id?: string;
|
|
23
32
|
}): AIProvider
|
|
24
33
|
```
|
|
@@ -26,6 +35,7 @@ createAiSdkProvider(options: {
|
|
|
26
35
|
| Field | Type | Purpose |
|
|
27
36
|
| --- | --- | --- |
|
|
28
37
|
| `model` | `LanguageModelV4` | Host-owned AI SDK language model. |
|
|
38
|
+
| `redactor` | `SecretRedactor` | Optional direct-provider error redactor; agent runs use their active redactor. |
|
|
29
39
|
| `id` | `string` | Prism provider id. Defaults to `ai-sdk:<model.provider>` or `ai-sdk`. |
|
|
30
40
|
|
|
31
41
|
Mapped request surfaces:
|
|
@@ -34,7 +44,7 @@ Mapped request surfaces:
|
|
|
34
44
|
| --- | --- |
|
|
35
45
|
| `messages` | `LanguageModelV4Prompt` |
|
|
36
46
|
| `tools` | `LanguageModelV4FunctionTool[]` with JSON Schema `inputSchema` |
|
|
37
|
-
| `options.structuredOutput` | `responseFormat: { type: "json", name, schema }` |
|
|
47
|
+
| `options.structuredOutput` | `responseFormat: { type: "json", name, schema }`; `strict` fails explicitly (V4 has no equivalent) |
|
|
38
48
|
| `model.parameters` | `maxOutputTokens`, `temperature`, `topP`, `topK`, penalties, `seed`, `stopSequences` |
|
|
39
49
|
| `request.signal` | `abortSignal` (always wins over adapter options) |
|
|
40
50
|
| `options.headers` | extension headers only; model owns auth |
|
|
@@ -45,16 +55,22 @@ Unsupported content fails before `doStream` (for example unresolved `resourceUri
|
|
|
45
55
|
|
|
46
56
|
| AI SDK stream part | Prism event |
|
|
47
57
|
| --- | --- |
|
|
58
|
+
| `response-metadata.id` | `message_start.messageId` |
|
|
48
59
|
| `text-delta` | `content_delta` text |
|
|
49
60
|
| `reasoning-delta` | `content_delta` thinking |
|
|
50
61
|
| `tool-input-start` / `tool-input-delta` | `tool_call_delta` |
|
|
51
|
-
| `tool-call`
|
|
62
|
+
| `tool-call` | `tool_call`; `providerExecuted` becomes `authority: "provider-hosted"` |
|
|
52
63
|
| `finish` usage | `usage` then `done` |
|
|
53
64
|
| `error` / thrown / abort | redacted `error` |
|
|
65
|
+
| `stream-start`, boundaries, raw diagnostics | intentionally not emitted: no normalized safe payload |
|
|
66
|
+
| provider-executed `tool-result` | remains provider-side; no host result or dispatch |
|
|
67
|
+
| file / reasoning-file / source / custom / approval request | typed `unsupported_mapping` error |
|
|
68
|
+
|
|
69
|
+
`response-metadata.modelId`/timestamp and opaque `providerMetadata` have no normalized Prism counterpart and are not emitted, preventing provider-private metadata from entering prompt, event, or telemetry paths.
|
|
54
70
|
|
|
55
71
|
`finish.usage.inputTokens.cacheRead` / `cacheWrite` map to Prism `Usage.cacheReadTokens` / `cacheWriteTokens`. The adapter does not invent cache request fields; prompt caching is owned by the host `LanguageModelV4` and its upstream provider.
|
|
56
72
|
|
|
57
|
-
|
|
73
|
+
No AI SDK stream part is silently coerced into Prism content: the table above maps safe normalized semantics, deliberately withholds provider-private diagnostics/results, and fails unsupported output types explicitly.
|
|
58
74
|
|
|
59
75
|
## Request/response example
|
|
60
76
|
|
|
@@ -127,7 +143,7 @@ Official evidence: [Custom providers / LanguageModelV4](https://ai-sdk.dev/provi
|
|
|
127
143
|
|
|
128
144
|
## Extension and configuration notes
|
|
129
145
|
|
|
130
|
-
- Peer dependency: `@ai-sdk/provider
|
|
146
|
+
- Peer dependency: `@ai-sdk/provider@4.0.3`. Upgrade policy adds a matrix row and offline conformance fixture before accepting any new version.
|
|
131
147
|
- 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.
|
|
132
148
|
- `options.compat` / `options.extra` pass through as AI SDK `providerOptions.prism`.
|
|
133
149
|
- Export helpers `toAiSdkCallOptions`, `toAiSdkPrompt`, and `mapAiSdkStream` for tests and custom hosts.
|
|
@@ -137,8 +153,8 @@ Official evidence: [Custom providers / LanguageModelV4](https://ai-sdk.dev/provi
|
|
|
137
153
|
- Host credentials stay inside the supplied AI SDK model. The adapter never reads env keys or credential stores.
|
|
138
154
|
- Abort and resource limits come from Prism `request.signal`; adapter options cannot replace that bound.
|
|
139
155
|
- Stream parts are translated incrementally with no full-response buffering and no duplicate model call.
|
|
140
|
-
- Unsupported content
|
|
141
|
-
- Provider metadata/warnings
|
|
156
|
+
- Unsupported content and stream parts fail closed before/at mapping; `structuredOutput.strict` is rejected because V4 cannot carry it.
|
|
157
|
+
- Pass `redactor` for direct use; agent runs apply their active redactor. Provider metadata/warnings never become prompt, tool, event, or telemetry content.
|
|
142
158
|
|
|
143
159
|
## Related APIs
|
|
144
160
|
|
package/docs/providers/openai.md
CHANGED
|
@@ -50,11 +50,13 @@ uses official Responses `reasoning: { effort, summary? }` via
|
|
|
50
50
|
|
|
51
51
|
| Surface | Behavior |
|
|
52
52
|
| --- | --- |
|
|
53
|
-
| Provider stream | Prism text, thinking (downgraded to text), `tool_call` deltas/finals, `usage`, `done`, redacted `error` events. |
|
|
54
|
-
|
|
|
53
|
+
| Provider stream | Prism text, thinking (downgraded to text), host `tool_call` deltas/finals, provider-hosted `tool_call` events (`authority: "provider-hosted"`), `continuation_required`, `usage`, `done`, and redacted `error` events. |
|
|
54
|
+
| Continuation | An incomplete Responses stream self-resumes at most eight HTTP hops using opaque `previous_response_id`; a cursor is at most 4 KiB, is never replayed, and is observable as `continuation_required`. |
|
|
55
|
+
| Realtime | `createOpenAIRealtimeSession()` exposes server-session creation, audio in/out, transcript deltas, provider-hosted calls, interrupt, and idempotent close through the neutral `RealtimeSession` seam. |
|
|
56
|
+
| Block preservation | User/system text → `input_text`; assistant text → `output_text`; assistant host `tool_call` → top-level `function_call` with `call_id`; provider-hosted calls are not replayed; `tool_result` → top-level `function_call_output`; images/files/audio when declared on the model. Bare thinking without an encrypted Responses reasoning item is omitted on replay. |
|
|
55
57
|
| Auth methods | `api_key` for `openai`; host-invoked subscription `oauth` for `openai-codex`. This is Prism's only first-party subscription OAuth flow in 0.0.12. |
|
|
56
58
|
|
|
57
|
-
Unsupported block placements or unclaimed images fail before `fetch`.
|
|
59
|
+
Unsupported block placements or unclaimed images fail before `fetch`. Provider-hosted calls are telemetry only: Prism never dispatches them as host tools or sends a `tool_result`.
|
|
58
60
|
|
|
59
61
|
## Request/response example
|
|
60
62
|
|
|
@@ -76,6 +78,21 @@ Responses request body (Codex subscription shape, abbreviated):
|
|
|
76
78
|
}
|
|
77
79
|
```
|
|
78
80
|
|
|
81
|
+
Realtime session (OpenAI session creation, abbreviated):
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import { createOpenAIRealtimeSession } from "@arnilo/prism-provider-openai";
|
|
85
|
+
|
|
86
|
+
const session = createOpenAIRealtimeSession({
|
|
87
|
+
model: { provider: "openai", model: "gpt-realtime-2.1" },
|
|
88
|
+
ownerId: "hashed-host-user-id",
|
|
89
|
+
apiKey,
|
|
90
|
+
});
|
|
91
|
+
for await (const event of session.events()) {
|
|
92
|
+
if (event.type === "audio_delta") play(event.audio);
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
79
96
|
OAuth authorize URL (PKCE, `S256`):
|
|
80
97
|
|
|
81
98
|
```
|
|
@@ -125,6 +142,7 @@ const challenge = computeS256Challenge(verifier);
|
|
|
125
142
|
`expires_in`, honors RFC 8628 `authorization_pending` / `slow_down`, and stops
|
|
126
143
|
on terminal errors or expiry. Pass `signal` on `OAuthLoginCallbacks` to abort
|
|
127
144
|
polling promptly.
|
|
145
|
+
- `createOpenAIRealtimeSession` requires a stable host `ownerId`; it sends that value as OpenAI's safety identifier and binds the stream to the server `session.created` id. An injected `webSocket(url, { headers })` factory supports Node 22 hosts whose global WebSocket does not expose header options.
|
|
128
146
|
|
|
129
147
|
### Cache behavior
|
|
130
148
|
|
|
@@ -189,6 +207,7 @@ Official: [Reasoning models](https://developers.openai.com/api/docs/guides/reaso
|
|
|
189
207
|
access/refresh tokens echoed in token-endpoint failures.
|
|
190
208
|
- The PKCE verifier is exchanged at the token endpoint, never sent on the authorize
|
|
191
209
|
URL.
|
|
210
|
+
- Realtime uses the documented WebSocket `Authorization` header, never a credential query parameter. API keys are redacted from transcript/error events; audio/transcript input is untrusted, realtime queues are bounded, and disconnect, abort, malformed session identity, or audio/byte/wall-time cap breach closes the session.
|
|
192
211
|
- Live tests stay opt-in behind `PRISM_LIVE_PROVIDER_TESTS=1` plus fake-safe
|
|
193
212
|
provider-specific env names; default `npm test` is network-free.
|
|
194
213
|
|
package/docs/rag.md
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
## What it does
|
|
4
4
|
|
|
5
|
-
`@arnilo/prism-rag` is an optional package for deterministic
|
|
5
|
+
`@arnilo/prism-rag` is an optional package for deterministic text/Markdown chunking, bounded embedding/vector indexing, atomic scoped source replacement/deletion, focused text/Markdown/HTML/PDF parsing, bounded reranking, ingestion status, attributable citations, content-trust metadata, and explicit `ContextProvider` injection. It reuses `Embedder` and `VectorStore` from `@arnilo/prism-memory`; Prism core input assembly is unchanged.
|
|
6
6
|
|
|
7
7
|
## When to use it
|
|
8
8
|
|
|
9
|
-
Use it when a host
|
|
9
|
+
Use it when a host needs bounded replacement of one owned source, focused parsing after a host-authorized resource or host-selected web fetch, or a host-selected reranker over a finite candidate set. Do not use it for LaTeX parsing, semantic chunking, metadata extraction agents, a hosted reranker implementation, GraphRAG, crawling, URL fetching outside `@arnilo/prism-web-tools`, or filesystem discovery.
|
|
10
10
|
|
|
11
11
|
## Inputs / request
|
|
12
12
|
|
|
@@ -20,6 +20,16 @@ Chunking:
|
|
|
20
20
|
| `size` / `overlap` | Character ceiling and repeated context |
|
|
21
21
|
| `metadata` | JSON metadata copied to every chunk |
|
|
22
22
|
|
|
23
|
+
Document lifecycle:
|
|
24
|
+
|
|
25
|
+
| API/field | Meaning |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| `replaceSource({ sourceId, chunks, store, scope, ... })` | Atomically replaces one source after all bounded embedding succeeds; the store must implement scoped `getBySource()` and `transaction()`. |
|
|
28
|
+
| `deleteSource({ sourceId, store, scope })` | Deletes only matching IDs under exact tenant/resource/corpus scope. |
|
|
29
|
+
| `replaceDocument({ uri, loader, parser, store, scope, ... })` | Loads through a host seam, parses, chunks, and atomically replaces. `sourceId` is required unless loader supplies one. |
|
|
30
|
+
| `DocumentLoader` / `Parser` | Small host-replaceable seams. Root and `@arnilo/prism-rag/loaders` / `@arnilo/prism-rag/parsers` export reference adapters. |
|
|
31
|
+
| `textParser` / `markdownParser` / `htmlParser` / `pdfParser` | UTF-8 text, Markdown, script/style-stripping HTML, and uncompressed-text PDF parsers. |
|
|
32
|
+
|
|
23
33
|
Index/retrieve:
|
|
24
34
|
|
|
25
35
|
| Field | Required | Meaning |
|
|
@@ -29,18 +39,24 @@ Index/retrieve:
|
|
|
29
39
|
| `chunks` | indexing | `RagChunk[]` from package chunkers or compatible host parser |
|
|
30
40
|
| `topK` / `queryCandidates` | retrieval | Returned result count and bounded pre-filter candidates |
|
|
31
41
|
| `filter` | no | Shallow JSON metadata equality filter |
|
|
32
|
-
| `
|
|
33
|
-
| `
|
|
42
|
+
| `reranker` | no | Host-owned `Reranker` receives redacted bounded `RagHit[]` and must return the same IDs once each, in preferred order. |
|
|
43
|
+
| `maxRerankBytes` / `maxRerankMs` / `rerankConcurrency` | no | Reranker caps; defaults/hard limits are 64/256 KiB, 2/10 s, and 2/8 active calls per reranker object. |
|
|
44
|
+
| `statusStore` | no | `IngestionStatusStore` records per-source pending/indexed/failed/partial byte/chunk progress; use `listIngestionStatus()` for capped exact-scope pages. |
|
|
45
|
+
| `redactor` / `secrets` | no | Redact before embedding, persistence, reranking, and injection |
|
|
46
|
+
| `signal` | no | Abort embedding, vector operations, reranking, and batch progression |
|
|
34
47
|
|
|
35
48
|
## Outputs / response / events
|
|
36
49
|
|
|
37
50
|
- `chunkText()` / `chunkMarkdown()` return frozen `RagChunk[]` with `sourceId`, zero-based index, offsets, and stable IDs such as `guide#0001`.
|
|
38
51
|
- `indexChunks()` returns `{ indexed, sourceIds }` after bounded batch upserts.
|
|
39
|
-
- `
|
|
52
|
+
- `replaceSource()` / `deleteSource()` return `{ sourceId, deleted, indexed }`.
|
|
53
|
+
- `replaceDocument()` carries loader parser metadata into chunk metadata; the web loader preserves web-tools citation ID and `untrusted: true`.
|
|
54
|
+
- `retrieveContext()` returns `{ query, trust, text, hits, citations, truncated }`. Every hit/citation carries `{ provenance: { sourceId, chunkId, citationId, provider, retrieval: "vector", retrievedAt }, trust: { untrusted: true, inert: true, injectionCapable: true } }`; `retrievalRank` preserves pre-rerank order. Rendered text uses `[citation-id] text` blocks.
|
|
55
|
+
- `createMemoryIngestionStatusStore()` is a bounded in-memory reference adapter. `listIngestionStatus({ store, scope, limit, cursor })` returns capped status pages; hosts supply durable stores when status must survive process restart.
|
|
40
56
|
- `createRagContextProvider()` returns one ordinary context provider. Empty queries/results contribute no block.
|
|
41
57
|
- No events, tools, permissions, provider calls, loaders, or network requests are added.
|
|
42
58
|
|
|
43
|
-
Default
|
|
59
|
+
Default/hard ceilings include 1,000/16,384 chunk characters, 100/4,096 overlap, 1,048,576/8,388,608 document bytes/chars, 30 s parsing, 256 PDF pages, 2,048/8,192 chunks, 32/128 embed batch, top-K 5/32, candidates 20/128, result 64/512 KiB, context 2,000/8,000 estimated tokens, reranker input 64/256 KiB, reranker wall time 2/10 s, reranker active calls 2/8, and status pages 50/200.
|
|
44
60
|
|
|
45
61
|
## Request/response example
|
|
46
62
|
|
|
@@ -51,7 +67,8 @@ Default hard ceilings include 1,000/16,384 chunk characters, 100/4,096 overlap,
|
|
|
51
67
|
"topK": 1,
|
|
52
68
|
"result": {
|
|
53
69
|
"text": "[security-guide#0001] Recheck policy before side effects.",
|
|
54
|
-
"
|
|
70
|
+
"trust": { "untrusted": true, "inert": true, "injectionCapable": true },
|
|
71
|
+
"citations": [{ "id": "security-guide#0001", "sourceId": "security-guide", "provenance": { "provider": "host", "retrieval": "vector" } }]
|
|
55
72
|
}
|
|
56
73
|
}
|
|
57
74
|
```
|
|
@@ -61,7 +78,7 @@ Default hard ceilings include 1,000/16,384 chunk characters, 100/4,096 overlap,
|
|
|
61
78
|
```ts
|
|
62
79
|
import { createAgent, createMockProvider, providerDone, providerTextDelta } from "@arnilo/prism";
|
|
63
80
|
import { createHashEmbedder, createMemoryVectorStore } from "@arnilo/prism-memory";
|
|
64
|
-
import { chunkMarkdown, createRagContextProvider, indexChunks, retrieveContext } from "@arnilo/prism-rag";
|
|
81
|
+
import { chunkMarkdown, createMemoryIngestionStatusStore, createRagContextProvider, indexChunks, listIngestionStatus, retrieveContext } from "@arnilo/prism-rag";
|
|
65
82
|
|
|
66
83
|
const embedder = createHashEmbedder(); // deterministic demo/test helper, not production semantic quality
|
|
67
84
|
const store = createMemoryVectorStore();
|
|
@@ -70,7 +87,9 @@ const chunks = chunkMarkdown("# Approval\n\nRecheck current policy before side e
|
|
|
70
87
|
sourceId: "security-guide",
|
|
71
88
|
metadata: { category: "security" },
|
|
72
89
|
});
|
|
73
|
-
|
|
90
|
+
const statusStore = createMemoryIngestionStatusStore();
|
|
91
|
+
await indexChunks({ chunks, embedder, store, scope, statusStore });
|
|
92
|
+
// For a replaceable source use `replaceSource`; it keeps previous chunks until embedding succeeds.
|
|
74
93
|
|
|
75
94
|
const found = await retrieveContext("approval policy", {
|
|
76
95
|
embedder,
|
|
@@ -78,7 +97,9 @@ const found = await retrieveContext("approval policy", {
|
|
|
78
97
|
scope,
|
|
79
98
|
topK: 4,
|
|
80
99
|
filter: { category: "security" },
|
|
100
|
+
reranker: { rerank: async ({ hits }) => [...hits].sort((a, b) => b.score - a.score) },
|
|
81
101
|
});
|
|
102
|
+
console.log(await listIngestionStatus({ store: statusStore, scope }));
|
|
82
103
|
|
|
83
104
|
const agent = createAgent({
|
|
84
105
|
model: { provider: "mock", model: "demo" },
|
|
@@ -92,9 +113,13 @@ console.log(found.text, await agent.createSession().run("How do approvals work?"
|
|
|
92
113
|
|
|
93
114
|
- Supply any Phase 7-conforming embedder/vector store, including the in-memory reference or PostgreSQL/pgvector adapter.
|
|
94
115
|
- Metadata filtering is package-local after a bounded candidate query so existing vector contracts/adapters remain unchanged. Increase `queryCandidates` only when selective filters measurably need it.
|
|
116
|
+
- `Reranker` is a host seam, not a provider integration. Return each redacted candidate ID exactly once; Prism retains canonical hit/provenance/trust fields and exposes `retrievalRank` for diagnostics. Add a hosted reranker only when a host owns its credentials, quota, and retry policy.
|
|
117
|
+
- `IngestionStatusStore` is optional observability storage. It is keyed by exact scope and source ID; use `listIngestionStatus()` rather than an unbounded corpus scan. The reference memory store is process-local; implement the same capped scope behavior for durable status.
|
|
95
118
|
- `createRagContextProvider()` derives its query from latest user text by default; pass a fixed string or callback for host-controlled query generation.
|
|
96
|
-
-
|
|
97
|
-
-
|
|
119
|
+
- `createResourceDocumentLoader({ loader })` calls one host-owned `ResourceLoader`; it scans nothing and performs no filesystem or network I/O itself. Pass the host's permission/trust context to that loader.
|
|
120
|
+
- `createWebFetchDocumentLoader({ fetcher })` accepts an already-configured `@arnilo/prism-web-tools` fetch adapter. It never opens a socket, rejects file/local/private/IP-literal URLs, and carries normalized citation/trust metadata forward. The fetch adapter still owns DNS/SSRF policy.
|
|
121
|
+
- `pdfParser` is deliberately limited to bounded, uncompressed PDF text. Provide a host parser through `Parser` for compressed, scanned, or complex PDFs; do not silently index partial text.
|
|
122
|
+
- Package is available directly or through `@arnilo/prism-all`; installation does not create an embedder, vector store, loader, parser, or context provider.
|
|
98
123
|
|
|
99
124
|
## Security and performance notes
|
|
100
125
|
|
|
@@ -102,7 +127,11 @@ console.log(found.text, await agent.createSession().run("How do approvals work?"
|
|
|
102
127
|
- Source IDs become citation/storage IDs and must be stable non-secret identifiers. Text and user metadata can be redacted before external embedding and persistence.
|
|
103
128
|
- Retrieved documents are untrusted inert context. Prompt-injection text cannot activate tools, skills, credentials, permissions, or extensions.
|
|
104
129
|
- Remote sources must pass existing resource/media trust, SSRF, MIME, and byte policies before their decoded text reaches this package.
|
|
105
|
-
-
|
|
130
|
+
- `replaceSource()` stages every bounded embedding before opening the store transaction. It requires a source-aware transactional store and fails closed rather than pretending generic upserts are atomic. `createMemoryVectorStore()` supplies the reference `getBySource()` / transaction capability; durable stores must implement equivalent exact-scope behavior.
|
|
131
|
+
- `deleteSource()` rechecks every returned record's tenant/resource/corpus and source metadata before delete. Same source IDs in another corpus remain untouched.
|
|
132
|
+
- Parsers enforce byte/page/time caps, abort before and after parsing, decode UTF-8 strictly, and strip HTML script/style content. Parsed and retrieved text remains untrusted inert context; it never gains tool authority.
|
|
133
|
+
- Rerankers receive redacted input under byte/time/concurrency caps. Timeout, abort, unknown/duplicate/missing IDs, oversized input, and reranker failures fail closed; returned objects cannot overwrite Prism provenance/trust fields.
|
|
134
|
+
- Ingestion failure errors are redacted before status storage. Status reads reject foreign scope entries and page-limit violations; status itself creates no permission or tool authority.
|
|
106
135
|
- Filtering scans at most `queryCandidates` hits; rendering stops at top-K, UTF-8 result bytes, or estimated context-token ceiling.
|
|
107
136
|
|
|
108
137
|
## Related APIs
|
|
@@ -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.15` 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.14` 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.15`, 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
|
|
|
@@ -77,9 +77,9 @@ Consumers install the core package for the runtime and add first-party packages
|
|
|
77
77
|
| Run the default (network-free) test suite | `npm test` |
|
|
78
78
|
| Dry-run pack core + every package | `npm run pack:dry-run` |
|
|
79
79
|
| Local mirror of the release verify gate | `npm run release:dry-run` |
|
|
80
|
-
| Validate clean tag/version/ranges and reject registry collisions | `npm run release:check -- --version 0.0.
|
|
81
|
-
| Preview deterministic publish order | `npm run release:publish -- --version 0.0.
|
|
82
|
-
| Resume interrupted tagged publication | `npm run release:publish -- --version 0.0.
|
|
80
|
+
| Validate clean tag/version/ranges and reject registry collisions | `npm run release:check -- --version 0.0.15` |
|
|
81
|
+
| Preview deterministic publish order | `npm run release:publish -- --version 0.0.15 --dry-run --allow-dirty --allow-untagged` |
|
|
82
|
+
| Resume interrupted tagged publication | `npm run release:publish -- --version 0.0.15 --resume --report release-artifacts/publish-report.json` |
|
|
83
83
|
| Full SDK readiness gate (typecheck + offline tests + pack) | `npm run sdk:ready` |
|
|
84
84
|
|
|
85
85
|
Public core import specifiers (from the root `exports` map):
|
|
@@ -116,7 +116,7 @@ A packed tarball contains only public compiled output and release files:
|
|
|
116
116
|
- Code packages ship `README.md`, `LICENSE`, and `CHANGELOG.md`; family/profile packages ship `README.md` and `CHANGELOG.md`.
|
|
117
117
|
- The core tarball additionally ships the full `docs/` directory (the docs hub) and `templates/init/` used by `prism init`.
|
|
118
118
|
- `dist/cli.js` and the `bin` link in core.
|
|
119
|
-
- **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.0.
|
|
119
|
+
- **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.0.15.tgz`; first-party packages produce `arnilo-prism-provider-<name>-0.0.15.tgz` / `arnilo-prism-compaction-<name>-0.0.15.tgz` / `arnilo-prism-coding-agent-0.0.15.tgz`; family/profile packages produce `arnilo-prism-{providers,compaction,base,code,sdk,all}-0.0.15.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).
|
|
120
120
|
|
|
121
121
|
Excluded from every tarball by `files` negation:
|
|
122
122
|
|
|
@@ -135,9 +135,9 @@ Excluded from every tarball by `files` negation:
|
|
|
135
135
|
"name": "host-app",
|
|
136
136
|
"type": "module",
|
|
137
137
|
"dependencies": {
|
|
138
|
-
"@arnilo/prism": "0.0.
|
|
139
|
-
"@arnilo/prism-provider-openai": "0.0.
|
|
140
|
-
"@arnilo/prism-compaction-observational-memory": "0.0.
|
|
138
|
+
"@arnilo/prism": "0.0.15",
|
|
139
|
+
"@arnilo/prism-provider-openai": "0.0.15",
|
|
140
|
+
"@arnilo/prism-compaction-observational-memory": "0.0.15"
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
```
|
|
@@ -147,7 +147,7 @@ Installing the provider/compaction packages without `@arnilo/prism` present prod
|
|
|
147
147
|
```text
|
|
148
148
|
npm error code ERESOLVE
|
|
149
149
|
npm error Could not resolve dependency:
|
|
150
|
-
npm error peer @arnilo/prism@"0.0.
|
|
150
|
+
npm error peer @arnilo/prism@"0.0.15" from @arnilo/prism-provider-openai@0.0.15
|
|
151
151
|
```
|
|
152
152
|
|
|
153
153
|
## Implementation example
|
|
@@ -180,11 +180,11 @@ For SDK readiness, run the same one-command gate directly. It composes existing
|
|
|
180
180
|
npm run sdk:ready
|
|
181
181
|
```
|
|
182
182
|
|
|
183
|
-
Release publication derives all
|
|
183
|
+
Release publication derives all **43** manifests from the workspace once, validates exact `0.0.15` manifest/lockfile/internal ranges, then uses deterministic dependency order. `release:check` requires a clean commit tagged `v0.0.15` 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.
|
|
184
184
|
|
|
185
185
|
```bash
|
|
186
|
-
npm run release:check -- --version 0.0.
|
|
187
|
-
npm run release:publish -- --version 0.0.
|
|
186
|
+
npm run release:check -- --version 0.0.15
|
|
187
|
+
npm run release:publish -- --version 0.0.15 --dry-run --allow-dirty --allow-untagged
|
|
188
188
|
```
|
|
189
189
|
|
|
190
190
|
`--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.
|
|
@@ -195,6 +195,54 @@ Optional live smoke tests stay separate from SDK readiness because they require
|
|
|
195
195
|
PRISM_LIVE_PROVIDER_TESTS=1 npm run test --workspaces --if-present
|
|
196
196
|
```
|
|
197
197
|
|
|
198
|
+
### 0.0.15 protected live-canary matrix
|
|
199
|
+
|
|
200
|
+
Default `npm test`, `npm run sdk:ready`, and `benchmark-0.0.15` are network-free. Run live rows only from a protected scheduled/release environment (or an explicitly authorized operator workstation); never place credentials in fixtures, benchmark JSON, pull-request jobs, or package scripts. Use least-privilege keys, one bounded request, and retain only redacted aggregate status. A blank **checked-in gate** means Prism deliberately has no generic credential fixture: host owns that provider/account compatibility probe.
|
|
201
|
+
|
|
202
|
+
| Surface | Gate and credential | Checked-in/protected command | Canary scope |
|
|
203
|
+
| --- | --- | --- | --- |
|
|
204
|
+
| 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. |
|
|
205
|
+
| 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. |
|
|
206
|
+
| 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.3` mapping/version check; Prism does not own upstream model credentials. |
|
|
207
|
+
| Kimi / Moonshot | `PRISM_LIVE_PROVIDER_TESTS=1` + `KIMI_API_KEY` | `npm test -w @arnilo/prism-provider-kimi` | Coding route; Moonshot entitlement is account-specific. |
|
|
208
|
+
| Z.AI | `PRISM_LIVE_PROVIDER_TESTS=1` + `ZAI_API_KEY` | `npm test -w @arnilo/prism-provider-zai` | GLM stream/tool/reasoning smoke. |
|
|
209
|
+
| 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. |
|
|
210
|
+
| OpenCode Go | `PRISM_LIVE_PROVIDER_TESTS=1` + `OPENCODE_API_KEY` | `npm test -w @arnilo/prism-provider-opencode-go` | OpenAI/Anthropic route selection smoke. |
|
|
211
|
+
| Alibaba DashScope | Alibaba least-privilege API key | No generic fixture; host compatibility probe in protected release environment | Region/preset/catalog entitlement varies; offline serializer and catalog tests remain default gate. |
|
|
212
|
+
| Ollama Cloud/local | Cloud API key or host-local authenticated endpoint | No generic fixture; host compatibility probe in protected release environment | Cloud account and local daemon/model availability are host-owned; no daemon starts during Prism tests. |
|
|
213
|
+
| NeuralWatt | `PRISM_LIVE_PROVIDER_TESTS=1` + `NEURALWATT_API_KEY` | `npm test -w @arnilo/prism-provider-neuralwatt` | Stream/retry/quota telemetry smoke. |
|
|
214
|
+
| Anthropic | `PRISM_LIVE_PROVIDER_TESTS=1` + `ANTHROPIC_API_KEY` | `npm test -w @arnilo/prism-provider-anthropic` | Restricted one-turn provider smoke. |
|
|
215
|
+
| Google | `PRISM_LIVE_PROVIDER_TESTS=1` + `GOOGLE_API_KEY` or `GEMINI_API_KEY` | `npm test -w @arnilo/prism-provider-google` | Restricted one-turn provider smoke. |
|
|
216
|
+
| Memory PostgreSQL/pgvector | `PRISM_TEST_POSTGRES_URL` with `vector` extension | `npm run test:postgres -w @arnilo/prism-memory` | Shared memory conformance, export/rebuild pagination, and finite-vector boundary. |
|
|
217
|
+
|
|
218
|
+
The scheduled/manual `live-canaries` workflow uses protected environment `live-canaries`; release validation uses its protected release environment. Neither workflow receives a broad workspace key. A successful offline benchmark is never evidence that a live row ran; each protected invocation must record its enabled matrix rows and skipped/missing prerequisites.
|
|
219
|
+
|
|
220
|
+
### 0.0.15 publish handoff
|
|
221
|
+
|
|
222
|
+
**Decision: GO after protected operator prerequisites below.** Phase 10 closes provider, memory, and RAG ecosystem parity without changing the Task 0 package freeze: the exact graph remains **43 publishable manifests**. It adds OpenAI hosted-tool attribution, bounded Responses continuation and Realtime; exact AI SDK V4 mapping; bounded RAG source lifecycle/document adapters/reranking/provenance/trust/status; and memory export/rebuild production conformance. 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.
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
git diff --check
|
|
226
|
+
npm ci
|
|
227
|
+
npm run sdk:ready
|
|
228
|
+
node scripts/benchmark-0.0.15.mjs
|
|
229
|
+
node --test scripts/benchmark-0.0.15.test.mjs
|
|
230
|
+
npm audit --audit-level=high
|
|
231
|
+
npm run release:check -- --version 0.0.15 --allow-dirty --allow-untagged --report /tmp/prism-0.0.15-preflight.json
|
|
232
|
+
npm run release:publish -- --version 0.0.15 --dry-run --allow-dirty --allow-untagged --report /tmp/prism-0.0.15-dry-run.json
|
|
233
|
+
git tag -s v0.0.15 -m "Prism 0.0.15"
|
|
234
|
+
git verify-tag v0.0.15
|
|
235
|
+
git push origin v0.0.15
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
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.
|
|
239
|
+
|
|
240
|
+
#### Rollback limitations
|
|
241
|
+
|
|
242
|
+
npm publication is immutable: partial publication is a resume case, and a confirmed defect requires deprecation plus a fixed version rather than rollback.
|
|
243
|
+
|
|
244
|
+
The 0.0.15 package set is unchanged from the canonical **43-package** list below; `release:check` derives it from the workspace and rejects missing, private, version-skewed, or internally mismatched manifests.
|
|
245
|
+
|
|
198
246
|
### 0.0.14 publish handoff
|
|
199
247
|
|
|
200
248
|
**Decision: GO after operator prerequisites below.** Phase 9 personal/work-agent conversations, memory consent/lifecycle, durable artifact review + authorized delivery, AG-UI co-work events, scoped M365/GWS OAuth connectors, browser verified-state checkpoints, a deny-by-default device adapter contract, and two new optional provider packages (`@arnilo/prism-provider-alibaba`, `@arnilo/prism-provider-ollama`). The exact 0.0.14 graph has **43 manifests** (41 → 43; only the two provider packages are new, enrolled via `@arnilo/prism-providers`). `@arnilo/prism-code` and `@arnilo/prism-sdk` stay lean; browser/ag-ui/work-tools remain optional. no Office package, Slack/Teams channel package, voice/desktop-control vendor package, internal auth DB, or Redis/SQS queue adapter ships. Clean protected-branch CI, signed commit/tag, npm authentication, OIDC attestation, protected live canaries, and actual publication remain operator/workflow prerequisites.
|
|
@@ -673,7 +721,7 @@ npm publication is not transactional and published versions are immutable. Parti
|
|
|
673
721
|
|
|
674
722
|
## Extension and configuration notes
|
|
675
723
|
|
|
676
|
-
- **Required `@arnilo/prism` peer.** Every first-party code package declares a non-optional `@arnilo/prism@0.0.
|
|
724
|
+
- **Required `@arnilo/prism` peer.** Every first-party code package declares a non-optional `@arnilo/prism@0.0.15` peer (`peerDependenciesMeta` must not mark `@arnilo/prism` optional; other peers such as `playwright-core` may be optional). The range stays pinned to `0.0.15` 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.
|
|
677
725
|
- **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.
|
|
678
726
|
- **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).
|
|
679
727
|
- **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/resource-loading.md
CHANGED
|
@@ -87,6 +87,8 @@ console.log(bytes.byteLength, manifest.name, prompt);
|
|
|
87
87
|
- Helpers do not choose a loader by URI scheme. Hosts can use contribution registries or their own routing when they need that.
|
|
88
88
|
- Helpers do not execute loaded text or imported modules. Package activation remains a host decision.
|
|
89
89
|
- `loadManifestResource()` only validates manifest data; it does not register manifest contributions.
|
|
90
|
+
- `@arnilo/prism-rag` `createResourceDocumentLoader({ loader, context? })` is the RAG bridge for an already-authorized artifact. It calls the supplied `ResourceLoader` once for a caller-selected URI, preserves text/binary media type, and adds no URI routing, local-file discovery, or network fallback. Pair it with a bounded RAG `Parser`; `replaceDocument()` then chunks and atomically replaces one exact RAG source.
|
|
91
|
+
- For public web documents, use `createWebFetchDocumentLoader({ fetcher })` with a host-configured `@arnilo/prism-web-tools` fetch adapter instead of adding web I/O to a `ResourceLoader`. It reuses normalized citation/trust data; the web adapter retains DNS/SSRF policy ownership.
|
|
90
92
|
|
|
91
93
|
## Security and performance notes
|
|
92
94
|
|
|
@@ -96,6 +98,7 @@ console.log(bytes.byteLength, manifest.name, prompt);
|
|
|
96
98
|
- Helpers call `loader.load()` once per helper call and do not cache, scan, list, watch, poll, or discover packages.
|
|
97
99
|
- JSON parsing fails closed for invalid JSON or non-object JSON.
|
|
98
100
|
- Do not put resolved credential values, tokens, headers, or executable code in loaded config, manifests, prompts, skills, or metadata.
|
|
101
|
+
- A RAG resource loader is not permission escalation: pass the same host-owned trust/permission context used for any resource load. HTML/PDF parser output and web content are untrusted inert text; compressed/scanned PDFs require a host parser rather than partial fallback.
|
|
99
102
|
|
|
100
103
|
## MCP resources
|
|
101
104
|
|