@arnilo/prism 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -1
- package/README.md +23 -20
- package/dist/agent-run-state.d.ts +1 -2
- package/dist/agent-run-state.js +0 -3
- package/dist/agent-session/session/assemble.d.ts +6 -0
- package/dist/agent-session/session/assemble.js +391 -0
- package/dist/agent-session/session/persist.d.ts +28 -0
- package/dist/agent-session/session/persist.js +166 -0
- package/dist/agent-session/session/provider-round.d.ts +6 -0
- package/dist/agent-session/session/provider-round.js +231 -0
- package/dist/agent-session/session/tool-round.d.ts +31 -0
- package/dist/agent-session/session/tool-round.js +473 -0
- package/dist/agent-session/session/types.d.ts +115 -0
- package/dist/agent-session/session/types.js +5 -0
- package/dist/agent-session/session.d.ts +49 -43
- package/dist/agent-session/session.js +11 -1177
- package/dist/capture.d.ts +63 -0
- package/dist/capture.js +67 -0
- package/dist/cli-init.d.ts +18 -2
- package/dist/cli-init.js +2 -7
- package/dist/cli-runner.d.ts +2 -2
- package/dist/cli-runner.js +45 -9
- package/dist/content.d.ts +3 -3
- package/dist/content.js +3 -1
- package/dist/contracts-core/agent.d.ts +2 -0
- package/dist/contracts-core/batch.d.ts +97 -0
- package/dist/contracts-core/batch.js +65 -0
- package/dist/contracts-core/content.d.ts +72 -1
- package/dist/contracts-core/embeddings.d.ts +30 -0
- package/dist/contracts-core/embeddings.js +17 -0
- package/dist/contracts-core/images.d.ts +60 -0
- package/dist/contracts-core/images.js +17 -0
- package/dist/contracts-core/moderation.d.ts +46 -0
- package/dist/contracts-core/moderation.js +34 -0
- package/dist/contracts-core/speech.d.ts +39 -0
- package/dist/contracts-core/speech.js +17 -0
- package/dist/contracts-core/transcription.d.ts +48 -0
- package/dist/contracts-core/transcription.js +17 -0
- package/dist/contracts-core/video.d.ts +61 -0
- package/dist/contracts-core/video.js +17 -0
- package/dist/contracts-core.d.ts +7 -0
- package/dist/contracts-core.js +7 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +4 -3
- package/dist/node/agent-definitions.d.ts +1 -8
- package/dist/node/agent-definitions.js +0 -34
- package/dist/node/settings.d.ts +0 -1
- package/dist/node/settings.js +0 -5
- package/dist/pinned-fetch.js +29 -3
- package/dist/provider-events.js +3 -4
- package/dist/providers/media.d.ts +1 -2
- package/dist/providers/media.js +1 -4
- package/dist/rpc.d.ts +1 -1
- package/dist/rpc.js +4 -4
- package/dist/testing/provider-conformance.d.ts +114 -5
- package/dist/testing/provider-conformance.js +342 -0
- package/dist/testing/tool-effect-store-conformance.d.ts +0 -1
- package/dist/testing/tool-effect-store-conformance.js +0 -3
- package/dist/thinking.d.ts +48 -9
- package/dist/thinking.js +134 -8
- package/docs/0.1.0-readiness.md +3 -3
- package/docs/a2a.md +2 -2
- package/docs/acp.md +3 -3
- package/docs/ag-ui-adoption.md +1 -1
- package/docs/ag-ui.md +1 -2
- package/docs/agent-definitions.md +1 -1
- package/docs/agent-events.md +5 -5
- package/docs/agent-identity.md +13 -2
- package/docs/audit-export.md +3 -3
- package/docs/batch-jobs.md +120 -0
- package/docs/cli-rpc.md +20 -9
- package/docs/coding-agent-tools.md +19 -19
- package/docs/coding-review-and-diagnostics.md +2 -2
- package/docs/coding-security.md +4 -4
- package/docs/coding-workspaces.md +2 -2
- package/docs/computer-use-linux.md +13 -2
- package/docs/context-and-skills.md +1 -1
- package/docs/conversations.md +4 -4
- package/docs/credential-storage.md +11 -7
- package/docs/credentials-and-redaction.md +1 -1
- package/docs/data-classification.md +1 -1
- package/docs/database-persistence.md +4 -4
- package/docs/dev-inspector.md +6 -6
- package/docs/device-adapters.md +2 -2
- package/docs/diagrams.md +1 -1
- package/docs/document-reader.md +6 -6
- package/docs/documents.md +5 -4
- package/docs/embeddings.md +112 -0
- package/docs/enterprise-postgres-state.md +7 -7
- package/docs/evaluations.md +8 -8
- package/docs/extensions.md +3 -3
- package/docs/forge-integration.md +3 -3
- package/docs/graft.md +2 -2
- package/docs/guardrails.md +1 -1
- package/docs/host-security.md +15 -15
- package/docs/image-generation.md +129 -0
- package/docs/impeccable.md +5 -3
- package/docs/index.md +60 -33
- package/docs/indexed-code-search.md +2 -2
- package/docs/language-intelligence.md +4 -4
- package/docs/live-testing.md +126 -0
- package/docs/mcp-tools.md +43 -12
- package/docs/middleware-hooks.md +1 -1
- package/docs/migrate-to-0.4.md +3 -3
- package/docs/migrate-to-0.5.md +122 -0
- package/docs/migration.md +29 -1
- package/docs/model-registry.md +38 -0
- package/docs/model-routing.md +5 -5
- package/docs/moderation.md +117 -0
- package/docs/multi-agent-patterns.md +4 -4
- package/docs/multimodal-content.md +26 -2
- package/docs/obscura.md +2 -2
- package/docs/observability.md +32 -7
- package/docs/openapi-tools.md +13 -3
- package/docs/operations.md +11 -0
- package/docs/performance.md +7 -7
- package/docs/persistence-credentials-multimodality-primitives.md +6 -6
- package/docs/policy-and-audit.md +17 -7
- package/docs/ponytail.md +1 -1
- package/docs/postgres-persistence.md +5 -5
- package/docs/process-sessions.md +2 -2
- package/docs/prompt-registry.md +7 -7
- package/docs/provider-caching.md +4 -0
- package/docs/provider-conformance.md +23 -1
- package/docs/provider-packages.md +39 -3
- package/docs/provider-primitives.md +1 -1
- package/docs/provider-request-policies.md +1 -1
- package/docs/providers/ai-sdk.md +15 -3
- package/docs/providers/alibaba.md +5 -1
- package/docs/providers/anthropic.md +4 -0
- package/docs/providers/azure.md +17 -1
- package/docs/providers/bedrock.md +15 -0
- package/docs/providers/clinepass.md +4 -0
- package/docs/providers/commandcode.md +253 -0
- package/docs/providers/deepseek.md +4 -0
- package/docs/providers/google.md +4 -0
- package/docs/providers/hyper.md +284 -0
- package/docs/providers/kimi.md +4 -0
- package/docs/providers/neuralwatt.md +4 -0
- package/docs/providers/ollama.md +15 -0
- package/docs/providers/openai-compatible.md +4 -0
- package/docs/providers/openai.md +4 -0
- package/docs/providers/opencode-go.md +4 -0
- package/docs/providers/openrouter.md +5 -1
- package/docs/providers/vertex.md +16 -0
- package/docs/providers/xai.md +4 -0
- package/docs/providers/zai.md +4 -0
- package/docs/rag.md +26 -4
- package/docs/release-and-install.md +103 -46
- package/docs/resource-loading.md +1 -1
- package/docs/runs-and-usage.md +14 -2
- package/docs/server.md +5 -5
- package/docs/settings-auth-trust-security.md +7 -5
- package/docs/sheets.md +2 -2
- package/docs/speech.md +126 -0
- package/docs/sqlite-persistence.md +4 -4
- package/docs/supervisors.md +3 -3
- package/docs/thinking-and-reasoning.md +93 -60
- package/docs/tool-conformance.md +1 -1
- package/docs/tool-execution-primitives.md +8 -8
- package/docs/tools.md +4 -4
- package/docs/web-tools.md +1 -1
- package/docs/wiki.md +1 -1
- package/docs/work-artifacts-and-review.md +17 -6
- package/docs/work-connectors.md +4 -4
- package/docs/work-tools.md +5 -5
- package/docs/workflow-orchestration-primitives.md +11 -11
- package/docs/workflows.md +5 -5
- package/package.json +11 -8
- package/templates/init/providers.json +24 -8
- package/docs/antigravity-agent.md +0 -207
package/docs/model-routing.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## What it does
|
|
4
4
|
|
|
5
|
-
`@arnilo/prism-model-router` is an optional governance facade over an existing `ProviderResolver`. It enforces allow-lists, residency, token/cost budgets, rate limits, circuit breaking, and bounded fallbacks before provider selection, and emits redacted selection diagnostics. It does not implement a second provider runtime.
|
|
5
|
+
`@arnilo/prism-core/governance/model-router` is an optional governance facade over an existing `ProviderResolver`. It enforces allow-lists, residency, token/cost budgets, rate limits, circuit breaking, and bounded fallbacks before provider selection, and emits redacted selection diagnostics. It does not implement a second provider runtime.
|
|
6
6
|
|
|
7
7
|
## When to use it
|
|
8
8
|
|
|
@@ -57,8 +57,8 @@ Frozen caps (default / hard): attempts `3 / 8`, circuit keys `1,024 / 16,384`, d
|
|
|
57
57
|
|
|
58
58
|
```ts
|
|
59
59
|
import { createAgent, createProviderResolver } from "@arnilo/prism";
|
|
60
|
-
import { createModelRouter } from "@arnilo/prism-model-router";
|
|
61
|
-
import { createPostgresEnterpriseState } from "@arnilo/prism-enterprise
|
|
60
|
+
import { createModelRouter } from "@arnilo/prism-core/governance/model-router";
|
|
61
|
+
import { createPostgresEnterpriseState } from "@arnilo/prism-core/enterprise/postgres";
|
|
62
62
|
|
|
63
63
|
const enterprise = await createPostgresEnterpriseState({ pool, schema: "prism" });
|
|
64
64
|
const router = createModelRouter({
|
|
@@ -91,7 +91,7 @@ await enterprise.close();
|
|
|
91
91
|
|
|
92
92
|
## Extension and configuration notes
|
|
93
93
|
|
|
94
|
-
Router is optional. Chain returned `providerRequestPolicy` with other `ProviderRequestPolicy` values. Wire `onDiagnostics` to `@arnilo/prism-policy` when audit export is required. OpenRouter package behavior is unchanged; routing metadata participates only when this gate allows it.
|
|
94
|
+
Router is optional. Chain returned `providerRequestPolicy` with other `ProviderRequestPolicy` values. Wire `onDiagnostics` to `@arnilo/prism-core/governance/policy` when audit export is required. OpenRouter package behavior is unchanged; routing metadata participates only when this gate allows it.
|
|
95
95
|
|
|
96
96
|
### Selection policies (0.1.7)
|
|
97
97
|
|
|
@@ -100,7 +100,7 @@ By default the router tries candidates in input order: the primary model, then
|
|
|
100
100
|
`createModelRouter` to rank the candidates before the governance checks run:
|
|
101
101
|
|
|
102
102
|
```ts
|
|
103
|
-
import { createCostLatencySelection, createModelRouter } from "@arnilo/prism-model-router";
|
|
103
|
+
import { createCostLatencySelection, createModelRouter } from "@arnilo/prism-core/governance/model-router";
|
|
104
104
|
|
|
105
105
|
const router = createModelRouter({
|
|
106
106
|
resolver,
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Moderation
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
`ModerationProvider` is the provider-neutral content-classification contract:
|
|
6
|
+
`moderate({ input })` sends text to a provider classifier and returns per-category
|
|
7
|
+
`{ score, flagged }` verdicts keyed by a provider-neutral vocabulary (plan 061
|
|
8
|
+
Task 6). Raw provider category/score fields ride along unmodified as `raw` for
|
|
9
|
+
host-side audits. Scores and flagged booleans are **provider output** — core
|
|
10
|
+
bakes in no policy: thresholds, blocking, and routing stay host-owned
|
|
11
|
+
([host security](host-security.md)). The first-party adapter is
|
|
12
|
+
[`createOpenAIModerationProvider`](providers/openai.md) (`POST /v1/moderations`,
|
|
13
|
+
`omni-moderation-latest`); offline conformance runs via
|
|
14
|
+
`runModerationConformance` from `@arnilo/prism/testing/provider-conformance`.
|
|
15
|
+
|
|
16
|
+
## When to use it
|
|
17
|
+
|
|
18
|
+
Use it when a host or guardrail seam wants pre-flight or post-hoc text
|
|
19
|
+
classification from a vendor classifier with portable category names. Do not use
|
|
20
|
+
it for local policy enforcement — Prism core never decides what is blocked;
|
|
21
|
+
hosts read `flagged`/`score` and apply their own thresholds.
|
|
22
|
+
|
|
23
|
+
## Inputs / request
|
|
24
|
+
|
|
25
|
+
| Field | Type | Meaning |
|
|
26
|
+
| --- | --- | --- |
|
|
27
|
+
| `input` | `string \| readonly string[]` | One input per call, or a batch (results match input arity and order). |
|
|
28
|
+
| `model` | `string?` | Classification model; adapter default `omni-moderation-latest`. |
|
|
29
|
+
| `signal` | `AbortSignal?` | Cancellation. |
|
|
30
|
+
|
|
31
|
+
Adapter options: `apiKey` (`CredentialValueSource` — resolved per call, redacted
|
|
32
|
+
from errors), `baseUrl`, `fetch` (fake transport for offline tests), `headers`,
|
|
33
|
+
`model`. Input caps reject typed before network I/O
|
|
34
|
+
(`OPENAI_MODERATION_INPUT_MAX_CHARS`, 100,000 chars — no provider-documented limit,
|
|
35
|
+
conservative ceiling).
|
|
36
|
+
|
|
37
|
+
## Outputs / response / events
|
|
38
|
+
|
|
39
|
+
| Field | Type | Meaning |
|
|
40
|
+
| --- | --- | --- |
|
|
41
|
+
| `flagged` | `boolean` | Provider's own top-level decision, verbatim. |
|
|
42
|
+
| `categories` | `Record<string, { score, flagged }>` | Verdicts keyed by the neutral vocabulary (see below); unknown raw categories pass through untouched. |
|
|
43
|
+
| `categories[k].score` | `number` | Provider-reported score in [0,1] — never locally recomputed. |
|
|
44
|
+
| `raw` | `JsonObject?` | Provider-native response fields for audits. |
|
|
45
|
+
|
|
46
|
+
Neutral category vocabulary (`MODERATION_CATEGORIES`): `harassment`,
|
|
47
|
+
`harassment/threatening`, `hate`, `hate/threatening`, `illicit`,
|
|
48
|
+
`illicit/violent`, `self-harm`, `self-harm/instructions`, `self-harm/intent`,
|
|
49
|
+
`sexual`, `sexual/minors`, `violence`, `violence/graphic`. The OpenAI adapter
|
|
50
|
+
maps via a data-driven table; vendor categories missing from the table surface
|
|
51
|
+
under their raw names so no provider signal is dropped.
|
|
52
|
+
|
|
53
|
+
Failures throw `ModerationError` with a stable `code`: `empty_input`,
|
|
54
|
+
`input_too_large`, `unsupported_model` (via `assertModerationSupported` when the
|
|
55
|
+
host checks `ModelCapabilities.moderation`), `request_failed` (non-2xx,
|
|
56
|
+
secret-redacted), `response_malformed` (missing `results`, non-numeric scores
|
|
57
|
+
downstream).
|
|
58
|
+
|
|
59
|
+
## Request/response example
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{ "model": "omni-moderation-latest", "input": "text to classify" }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Implementation example
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { createOpenAIModerationProvider } from "@arnilo/prism-providers/openai";
|
|
69
|
+
import { runModerationConformance } from "@arnilo/prism/testing/provider-conformance";
|
|
70
|
+
|
|
71
|
+
const moderation = createOpenAIModerationProvider({ apiKey: process.env.OPENAI_API_KEY });
|
|
72
|
+
const result = await moderation.moderate({ input: text });
|
|
73
|
+
// Host-owned policy — Prism applies no thresholds:
|
|
74
|
+
if (result.categories.violence?.score ?? 0 > myPolicy.violenceCutoff) { ... }
|
|
75
|
+
|
|
76
|
+
// Batch where the provider allows it (arity- and order-preserving):
|
|
77
|
+
const batch = await moderation.moderate({ input: ["first", "second"] });
|
|
78
|
+
|
|
79
|
+
// Offline conformance (fake transport, no network):
|
|
80
|
+
await runModerationConformance({
|
|
81
|
+
provider: createOpenAIModerationProvider({ apiKey: "sk-test", fetch: fakeFetch }),
|
|
82
|
+
model: "omni-moderation-latest",
|
|
83
|
+
maxInputChars: 100_000,
|
|
84
|
+
sample: { input: "conformance probe" },
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Extension and configuration notes
|
|
89
|
+
|
|
90
|
+
- Implement `ModerationProvider` for other vendors; the contract is structural —
|
|
91
|
+
no base class, no registry. Keep the data-driven category table per provider;
|
|
92
|
+
never hard-code category logic in call paths.
|
|
93
|
+
- Models declare support with `capabilities.moderation`; hosts gate with
|
|
94
|
+
`modelSupportsModeration` / `assertModerationSupported`, mirroring the
|
|
95
|
+
embeddings/speech/image/video guard pattern.
|
|
96
|
+
- Guardrail seams consume the contract at the host layer: wire `moderate()`
|
|
97
|
+
into request/output inspection stages; core stays policy-free by design.
|
|
98
|
+
|
|
99
|
+
## Security and performance notes
|
|
100
|
+
|
|
101
|
+
- API keys resolve through the existing `CredentialValueSource` seam and are
|
|
102
|
+
redacted from every thrown error; no new secret paths.
|
|
103
|
+
- Classification responses are read through the bounded JSON reader
|
|
104
|
+
(`OPENAI_MODERATION_MAX_RESPONSE_BYTES`, 8 MiB) — oversized payloads reject
|
|
105
|
+
instead of buffering.
|
|
106
|
+
- One provider request per input; batch inputs loop the same bounded path.
|
|
107
|
+
- Inputs, verdicts, and raw payloads are never logged by core; error messages
|
|
108
|
+
carry status and a redacted body only.
|
|
109
|
+
|
|
110
|
+
## Related APIs
|
|
111
|
+
|
|
112
|
+
- [Host security](host-security.md): policy ownership — thresholds and blocking
|
|
113
|
+
stay host-side.
|
|
114
|
+
- [Provider conformance](provider-conformance.md): `runModerationConformance`
|
|
115
|
+
and the offline conformance matrix.
|
|
116
|
+
- [Provider packages](provider-packages.md): subpath import rules for
|
|
117
|
+
`@arnilo/prism-providers/openai`.
|
|
@@ -6,7 +6,7 @@ Maps the four Prism answers for "more than one agent" onto one decision table. A
|
|
|
6
6
|
|
|
7
7
|
- **In-session handoff (swarm)** — agent A transfers control of the ongoing conversation to agent B by calling a host-built `handoff` tool; the host resolves the target `AgentDefinition` with `resolveAgentDefinition` and opens the specialist against the same session (same store + session id, previous run's `leafId`). One transcript, no new session. No helper primitive ships; the tool factory lives in [`examples/handoff-swarm.ts`](../examples/handoff-swarm.ts).
|
|
8
8
|
- **Hierarchical crew** — a manager agent decomposes a goal into typed tasks (`{ tasks: [{ role, instruction }] }`) via structured output ([`Artifact*`](structured-output.md)), fans out to parallel role specialists with bounded `maxFanOut` ([`fanOutNode`](workflows.md)), aggregates deliverables with host reduce ([`joinNode`](workflows.md)), and validates outputs with conditional routing to completion or revision ([`conditionalNode`](workflows.md)). The entire process is a deterministic DAG workflow with zero new runtime primitives. Live demo in [`examples/crew-hierarchy.ts`](../examples/crew-hierarchy.ts).
|
|
9
|
-
- **Supervisor delegation** — `@arnilo/prism-supervisor` `delegate()` invokes allow-listed child agents as bounded runs and returns their result to the parent. Separate child transcripts, hooks, budgets, narrowing.
|
|
9
|
+
- **Supervisor delegation** — `@arnilo/prism-core/runtime/supervisor` `delegate()` invokes allow-listed child agents as bounded runs and returns their result to the parent. Separate child transcripts, hooks, budgets, narrowing.
|
|
10
10
|
- **A2A 1.0** — cross-service interop over the JSON-RPC/HTTPS binding; the remote peer's lifecycle is host-owned behind `A2ATaskLifecycle`.
|
|
11
11
|
|
|
12
12
|
## When to use it
|
|
@@ -153,15 +153,15 @@ Live demo: [`examples/crew-hierarchy.ts`](../examples/crew-hierarchy.ts) — man
|
|
|
153
153
|
- **Narrowing on transfer, never widening.** If the specialist needs the caller's verified identity, project it through `narrowIdentity` / `assertIdentityPropagation` ([Agent identity](agent-identity.md)) so scopes and tenant cannot widen across the swap. For delegation the same discipline is built in (`narrowIdentity`, AND-composed policies); for A2A the exact-origin client plus per-operation authorization is the boundary.
|
|
154
154
|
- **Manager-generated task plans are untrusted model output.** Manager plan outputs are validated against the typed schema via `ArtifactValidator` before being persisted to workflow state or dispatched to `fan_out`. Malformed or invalid plans trigger the artifact repair loop or fail closed before any specialist is invoked.
|
|
155
155
|
- **Redaction of carried context.** Handoff carries the raw transcript by design — same rows a human replay would read. Apply the session egress seams on the way out: `redactSessionEntry` / `redactMessage` with a host field policy (see [Data classification](data-classification.md)) and `AgentConfig.redactor`; for durable replay across tenants reuse the redacted transcript seam discipline used by ACP `sessions.transcript` ([ACP interop](acp.md)).
|
|
156
|
-
- **Telemetry attribution.** Which agent produced which turn is not stored on message entries; the host knows (it performed the swap or aggregated fan-out results) and should pin it per run via `RunOptions.identity` (principal kind `agent`) so `identityTelemetryAttributes` (`prism.identity.*`) carries redacted attribution on telemetry, or via observability metadata. Supervisor runs emit dedicated `delegation_*` events;
|
|
156
|
+
- **Telemetry attribution.** Which agent produced which turn is not stored on message entries; the host knows (it performed the swap or aggregated fan-out results) and should pin it per run via `RunOptions.identity` (principal kind `agent`) so `identityTelemetryAttributes` (`prism.identity.*`) carries redacted attribution on telemetry, or via observability metadata. Supervisor runs emit dedicated `delegation_*` events; an in-process definition swap has no session seam to emit one, so the host records attribution.
|
|
157
157
|
- **Performance.** The swap performs zero provider calls; it costs one registry resolution plus one session open (~sub-millisecond in the example fixture). The transferred turn costs what any tool round costs.
|
|
158
158
|
|
|
159
159
|
## Extension and configuration notes
|
|
160
160
|
|
|
161
161
|
- Handoff targets may be code-defined `AgentDefinition` objects or `<configRoot>/agents/<name>/AGENT.md` bundles resolved via `resolveAgentBundle` — the allow-list maps names to either.
|
|
162
|
-
- Hosts wanting the pattern behind a UI timeline can emit their own step events from the swap
|
|
162
|
+
- Hosts wanting the pattern behind a UI timeline can emit their own step events from the swap.
|
|
163
163
|
- A reusable in-session handoff helper was evaluated and **not** shipped in 0.3.x: the unavoidable boilerplate is a ~20-line allow-list tool plus one `createAgentSession` call. Revisit only if multiple hosts show materially different swap semantics.
|
|
164
|
-
- Hierarchical crew patterns compose entirely on existing `@arnilo/prism-workflows` and `@arnilo/prism` primitives (`agentNode`, `fanOutNode`, `joinNode`, `conditionalNode`, `ArtifactValidator`, `resolveAgentDefinition`); no separate helper package is needed.
|
|
164
|
+
- Hierarchical crew patterns compose entirely on existing `@arnilo/prism-core/runtime/workflows` and `@arnilo/prism` primitives (`agentNode`, `fanOutNode`, `joinNode`, `conditionalNode`, `ArtifactValidator`, `resolveAgentDefinition`); no separate helper package is needed.
|
|
165
165
|
|
|
166
166
|
## Related APIs
|
|
167
167
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## What it does
|
|
4
4
|
|
|
5
|
-
Prism core ships generic `audio`, `file`, and `
|
|
5
|
+
Prism core ships generic `audio`, `file`, `document`, and `video` `ContentBlock` types plus bounded media resolution helpers. Blocks carry MIME type, optional name, and exactly one source: inline base64 `data`, remote `url`, or host `resourceUri`. Optional `transcript` metadata can accompany audio/document blocks.
|
|
6
6
|
|
|
7
7
|
`assembleProviderInput()` calls `assertMessagesSupportModelCapabilities()` so declared `ModelCapabilities.input` tags are enforced before provider calls. First-party provider packages map supported blocks locally; unsupported combinations fail closed with `UnsupportedModalityError` or an explicit provider error.
|
|
8
8
|
|
|
@@ -10,7 +10,7 @@ Prism core ships generic `audio`, `file`, and `document` `ContentBlock` types pl
|
|
|
10
10
|
|
|
11
11
|
- **Host apps** attaching PDFs, audio clips, or generic files to user messages before a provider turn.
|
|
12
12
|
- **Resource loaders** returning binary payloads for `resourceUri` references under trust/permission policy.
|
|
13
|
-
- **Provider authors** reading truthful `ModelCapabilities.input` tags (`text`, `image`, `audio`, `file`, `document`) before mapping wire formats.
|
|
13
|
+
- **Provider authors** reading truthful `ModelCapabilities.input` tags (`text`, `image`, `audio`, `file`, `document`, `video`) before mapping wire formats.
|
|
14
14
|
|
|
15
15
|
Do not embed provider upload IDs, tenant-scoped remote file IDs, or API-specific handles in core content blocks.
|
|
16
16
|
|
|
@@ -54,6 +54,7 @@ Known `ModelCapabilities.input` tags are exported as `MODEL_INPUT_CAPABILITIES`:
|
|
|
54
54
|
| `audio` | `audio` | OpenAI Responses (`input_audio`) and Google `generateContent` inline data. OpenAI Realtime instead receives `RealtimeSession.sendAudio()` chunks, not an `audio` `ContentBlock`. |
|
|
55
55
|
| `file` | `file` | OpenAI Responses (`input_file`); Anthropic/Kimi/OpenCode Go Anthropic route accept PDF file/document forms; Google maps inline file data. |
|
|
56
56
|
| `document` | `document` | OpenAI Responses (`input_file`); Anthropic/Kimi/OpenCode Go Anthropic route map PDF; Google maps inline document data. |
|
|
57
|
+
| `video` | `video` | Alibaba (Qwen-VL compatible mode maps to `video_url`, plan 061 Task 5); other providers reject with `UnsupportedModalityError` until they declare and map the tag. Optional `fps` frame-sampling hint and `durationMs` ride on the block. |
|
|
57
58
|
|
|
58
59
|
The AI SDK adapter maps declared user text/image/audio/file/document blocks (and assistant text/image/file/document) to AI SDK file parts; `resourceUri` remains host-resolved before `doStream`. Its output `file`, `reasoning-file`, and `source` parts are deliberately rejected as `unsupported_mapping`, not converted to trusted Prism content. Provider capability metadata is the gate—this matrix never upgrades a model that does not declare the matching input tag.
|
|
59
60
|
|
|
@@ -130,6 +131,29 @@ try {
|
|
|
130
131
|
}
|
|
131
132
|
```
|
|
132
133
|
|
|
134
|
+
## Video generation (output)
|
|
135
|
+
|
|
136
|
+
Video generation is a separate, deliberately minimal contract — jobs run minutes,
|
|
137
|
+
not seconds, so there is no synchronous `generate`. `VideoGenerationProvider`
|
|
138
|
+
(plan 061 Task 5, from `@arnilo/prism`) has two methods:
|
|
139
|
+
|
|
140
|
+
- `submit(request)` → `{ jobId }`; the request carries `model`, `prompt`, optional
|
|
141
|
+
`images` (first entry wins, image-to-video), `size`, `durationSeconds`, `fps`, and
|
|
142
|
+
an `AbortSignal`. Providers without image-to-video reject with a typed
|
|
143
|
+
`VideoGenerationError("unsupported_operation")`-shaped error path.
|
|
144
|
+
- `status(jobId, signal?)` → point-in-time `VideoGenerationJob` with `state`
|
|
145
|
+
(`queued` / `running` / `succeeded` / `failed`), a `video` (with `provider`/`model`
|
|
146
|
+
provenance and `bytes` or `url`) on success, and an `error` message on failure.
|
|
147
|
+
Hosts own the polling loop.
|
|
148
|
+
|
|
149
|
+
Models declare the `capabilities.videoGeneration` flag; hosts gate with
|
|
150
|
+
`modelSupportsVideoGeneration()` / `assertVideoGenerationSupported()`. The Alibaba
|
|
151
|
+
adapter (`createAlibabaVideoGenerationProvider` from
|
|
152
|
+
`@arnilo/prism-providers/alibaba`) runs the DashScope wanx async-task lifecycle
|
|
153
|
+
(text-to-video and image-to-video routes) with an adapter-local `waitFor()`
|
|
154
|
+
convenience poller; conformance runs offline via `runVideoGenerationConformance()`
|
|
155
|
+
from `@arnilo/prism/testing/provider-conformance`.
|
|
156
|
+
|
|
133
157
|
## Extension and configuration notes
|
|
134
158
|
|
|
135
159
|
- URL fetches use the DNS-classifying, address-pinned Node transport by default. `resolveHostname` and `requestUrl` are paired test/custom seams; `requestUrl` must connect to the supplied validated address while preserving the original URL hostname for HTTP Host/TLS verification.
|
package/docs/obscura.md
CHANGED
|
@@ -158,8 +158,8 @@ agent.tools = [...agent.tools, ...web.tools];
|
|
|
158
158
|
the same `ToolDefinition[]` with one read tool (`web_fetch`) and one mutating tool
|
|
159
159
|
(`obscura_scrape`) — through every Prism host's public API: core agent/session
|
|
160
160
|
execution, the Prism MCP server, the `createPrismHandler` server lifecycle, AG-UI
|
|
161
|
-
MCP-tool injection, ACP fronting, workflow `toolNode`/`agentNode`s, supervisor
|
|
162
|
-
children
|
|
161
|
+
MCP-tool injection, ACP fronting, workflow `toolNode`/`agentNode`s, and supervisor
|
|
162
|
+
children. It verifies host authorization
|
|
163
163
|
and selection deny before execution, that no host needs an Obscura-specific branch,
|
|
164
164
|
and that an aborted in-flight call settles and kills the owned child. Composition
|
|
165
165
|
walkthrough: [`examples/obscura.ts`](../examples/obscura.ts).
|
package/docs/observability.md
CHANGED
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
Prism exposes provider and tool timing through stable, metadata-only `AgentEvent` variants. Hosts subscribe via `session.subscribe()` or persist events through `RunLedger`. Core helpers build `ProviderTurnMetadata` and classify HTTP failures without echoing prompts, tool arguments, or credentials.
|
|
6
6
|
|
|
7
|
-
Optional package `@arnilo/prism-observability
|
|
7
|
+
Optional package `@arnilo/prism-core/governance/observability` maps those events to OpenTelemetry spans and low-cardinality metrics, and adapts `@arnilo/prism-memory/rag`'s dependency-free telemetry seam (`createRagTelemetry()`) onto the same tracer. OpenTelemetry is **not** a dependency of `@arnilo/prism`.
|
|
8
8
|
|
|
9
9
|
APIs:
|
|
10
10
|
|
|
11
11
|
- `ProviderTurnMetadata`, `ToolExecutionMetadata` on `AgentEvent`
|
|
12
12
|
- `createProviderTurnMetadata()`, `readProviderHttpStatus()` in `@arnilo/prism`
|
|
13
|
-
- `createOpenTelemetryInstrumentation()`, `wrapOpenTelemetryApi()`, `createInMemoryTelemetry()` in `@arnilo/prism-observability
|
|
14
|
-
- `createRagTelemetry()` in `@arnilo/prism-observability
|
|
13
|
+
- `createOpenTelemetryInstrumentation()`, `wrapOpenTelemetryApi()`, `createInMemoryTelemetry()` in `@arnilo/prism-core/governance/observability`
|
|
14
|
+
- `createRagTelemetry()` in `@arnilo/prism-core/governance/observability` (RAG spans/events; see span tree below)
|
|
15
15
|
- `handleRunFeedback()` / `handleEvaluation()` for explicit safe post-run projection
|
|
16
16
|
|
|
17
17
|
## When to use it
|
|
@@ -51,7 +51,7 @@ OpenTelemetry adapter:
|
|
|
51
51
|
|
|
52
52
|
```ts
|
|
53
53
|
import { trace, metrics } from "@opentelemetry/api";
|
|
54
|
-
import { createOpenTelemetryInstrumentation, wrapOpenTelemetryApi } from "@arnilo/prism-observability
|
|
54
|
+
import { createOpenTelemetryInstrumentation, wrapOpenTelemetryApi } from "@arnilo/prism-core/governance/observability";
|
|
55
55
|
|
|
56
56
|
const { tracer, meter } = wrapOpenTelemetryApi(
|
|
57
57
|
trace.getTracer("app"),
|
|
@@ -97,7 +97,7 @@ OpenTelemetry mapping (when enabled):
|
|
|
97
97
|
| `handleRunFeedback` | active-run `prism.run.feedback` event or ended-run span | `prism.run.feedback` |
|
|
98
98
|
| `handleEvaluation` | active-run `gen_ai.evaluation.result` event or ended-run span | `prism.run.evaluation` (`status`) |
|
|
99
99
|
|
|
100
|
-
RAG span tree (`@arnilo/prism-rag` + `createRagTelemetry()`):
|
|
100
|
+
RAG span tree (`@arnilo/prism-memory/rag` + `createRagTelemetry()`):
|
|
101
101
|
|
|
102
102
|
| Span | Parent | Notes |
|
|
103
103
|
| --- | --- | --- |
|
|
@@ -148,7 +148,7 @@ High-cardinality identifiers (`sessionId`, `runId`, `requestId`, `toolCallId`) a
|
|
|
148
148
|
|
|
149
149
|
```ts
|
|
150
150
|
import { createAgent, createMockProvider, providerDone, providerTextDelta } from "@arnilo/prism";
|
|
151
|
-
import { createInMemoryTelemetry, createOpenTelemetryInstrumentation } from "@arnilo/prism-observability
|
|
151
|
+
import { createInMemoryTelemetry, createOpenTelemetryInstrumentation } from "@arnilo/prism-core/governance/observability";
|
|
152
152
|
|
|
153
153
|
const memory = createInMemoryTelemetry();
|
|
154
154
|
const telemetry = createOpenTelemetryInstrumentation({ tracer: memory.tracer, meter: memory.meter });
|
|
@@ -176,17 +176,42 @@ const found = await retrieveContext("policy", { embedder, store, scope, telemetr
|
|
|
176
176
|
- Events flow through `redactAgentEvent` before subscribers and ledger writes — configure `createSecretRedactor` on the agent/run.
|
|
177
177
|
- `retry_scheduled` still signals backoff; each retry attempt emits its own `provider_turn_*` pair with `metadata.attempt`.
|
|
178
178
|
- NeuralWatt `neuralwatt:telemetry` provider events remain package-local; hosts may forward numeric cost/energy into custom metrics.
|
|
179
|
-
- `@arnilo/prism-observability
|
|
179
|
+
- `@arnilo/prism-core/governance/observability` is optional and included through `@arnilo/prism-core` family installs; instrumentation remains disabled until a host configures it.
|
|
180
180
|
- Exporter failures are isolated: instrumentation catches tracer/meter errors and invokes `onExporterError` without affecting the run, feedback persistence, or evaluation scoring.
|
|
181
181
|
- Trace grading uses `createPersistenceTraceResolver()` with explicit session/run/ownership and finite pages/bytes. Judge reasons remain evaluation data; `gen_ai.evaluation.result` receives only name, finite score, controlled status, and reason-presence.
|
|
182
182
|
- Run spans parent provider, tool, guardrail, and explicit delegation spans. Pass `{ context, trace }` to `wrapOpenTelemetryApi()` for native parent context creation; `parentContext` can attach the run to host ambient/remote context.
|
|
183
183
|
- `onTraceReference` receives `{ runId, traceId }` when a run starts. `traceId(runId)` keeps only the newest 1,024 mappings by default (`maxTraceReferences`, hard cap 10,000); durable linkage remains host-owned.
|
|
184
184
|
- Run `error`, suspension, denial, and detach close every attributable span. Repeated terminal events are idempotent and cannot end a span twice.
|
|
185
185
|
- Disabled instrumentation performs no per-delta span work (`enabled: false` or missing tracer/meter).
|
|
186
|
+
- `createProviderCapture()` (plan 062) is the opt-in request/response capture middleware: register `capture.middleware()` on the existing `provider_request` hook and feed `provider_turn_finished` events from the session subscriber loop into `capture.observeEvent()`. Entries land in a capped FIFO ring buffer (`policy.maxEvents`, default 100) exposed via `capture.events()`.
|
|
187
|
+
|
|
188
|
+
### Provider request/response capture middleware
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
import { createProviderCapture, createMiddlewareRegistry } from "@arnilo/prism";
|
|
192
|
+
|
|
193
|
+
const capture = createProviderCapture({
|
|
194
|
+
secrets, // same redactor seam as the logging paths
|
|
195
|
+
policy: { redact: "secrets", maxEvents: 100 },
|
|
196
|
+
});
|
|
197
|
+
const middleware = createMiddlewareRegistry({ secrets });
|
|
198
|
+
middleware.use("provider_request", capture.middleware()); // request entries, pass-through
|
|
199
|
+
|
|
200
|
+
for await (const event of session.subscribe()) {
|
|
201
|
+
if (event.type === "provider_turn_finished") capture.observeEvent(event); // response entries
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const entries = capture.events(); // oldest-first snapshot; capture.clear() resets
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
- The `policy.redact` field governs content retention: `"all"` keeps structure only, `"secrets"` (default) also drops message content, `"none"` retains message content for replay debugging. Secret redaction through the shared logging helpers is unconditional in every mode — captured buffers are replay-safe by construction.
|
|
208
|
+
- Captured shapes are already-normalized (`ProviderRequest` on the request side, `provider_turn_finished` metadata/usage on the response side) — never raw HTTP. Request/response `options` and headers are never captured at all (headers are where credentials ride).
|
|
209
|
+
- Disabled by default with zero overhead: an unregistered capture performs no work; the enabled path adds one entry per round plus the pass-through.
|
|
186
210
|
|
|
187
211
|
## Security and performance notes
|
|
188
212
|
|
|
189
213
|
- Default events are metadata-only — no prompts, streamed deltas, tool arguments, or credentials.
|
|
214
|
+
- Capture middleware follows the same default: `redact: "secrets"` drops message content; buffers are capped and secrets are redacted unconditionally, so a captured buffer can be persisted or replayed without leaking credentials.
|
|
190
215
|
- Use `identityTelemetryAttributes(identity)` when attaching enterprise identity to run metadata or OTel attributes; it emits `prism.identity.*` refs only (tenant/principal/scope counts), never credential secrets or raw tokens.
|
|
191
216
|
- Opt-in content in other event types (`message_delta`, tool `result`) is still subject to `redactAgentEvent`.
|
|
192
217
|
- Metric labels stay low-cardinality (`gen_ai.operation.name`, `gen_ai.provider.name`, token type, controlled outcome/status, feedback rating bucket/link presence); never use session/run/request/call IDs, model output, comments, tag values, scorer/evaluation IDs, or arbitrary metadata as labels. Token usage is recorded once at provider operation scope.
|
package/docs/openapi-tools.md
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
# OpenAPI tools adapter (`@arnilo/prism-
|
|
1
|
+
# OpenAPI tools adapter (`@arnilo/prism-coding-tools/openapi`)
|
|
2
2
|
|
|
3
3
|
Optional `createOpenApiTools` compiles host-selected OpenAPI 3.1 operations into bounded Prism `ToolDefinition`s. Zero dependencies (native fetch + WebCrypto-free); the compile step is pure and separated from the runtime executor.
|
|
4
4
|
|
|
5
5
|
## When to use it
|
|
6
6
|
|
|
7
|
-
Hosts that already expose a JSON API with an OpenAPI 3.1 document and want the agent to call a **fixed, host-chosen subset** of it — never model-driven discovery, never a raw method/path passthrough. For vendor web search/extraction use `@arnilo/prism-web-tools`; for M365/GWS use `@arnilo/prism-work
|
|
7
|
+
Hosts that already expose a JSON API with an OpenAPI 3.1 document and want the agent to call a **fixed, host-chosen subset** of it — never model-driven discovery, never a raw method/path passthrough. For vendor web search/extraction use `@arnilo/prism-web-tools`; for M365/GWS use `@arnilo/prism-core/integrations/work`; this adapter is for arbitrary host APIs.
|
|
8
8
|
|
|
9
9
|
## Usage
|
|
10
10
|
|
|
11
11
|
```ts
|
|
12
|
-
import { createOpenApiTools } from "@arnilo/prism-
|
|
12
|
+
import { createOpenApiTools } from "@arnilo/prism-coding-tools/openapi";
|
|
13
13
|
|
|
14
14
|
const tools = createOpenApiTools({
|
|
15
15
|
document, // OpenAPI 3.1 document (JSON string or parsed object)
|
|
@@ -48,6 +48,16 @@ Register the returned tools with `createToolRegistry` (or pass them to the MCP b
|
|
|
48
48
|
|
|
49
49
|
Defaults and hard caps (frozen in `scripts/phase11-freeze-manifest.json`): `maxDocumentBytes` 2 MiB/16 MiB, `maxOperations` 256/1024, `maxSchemaDepth` 32/128, `maxRefs` 1024/8192, `maxBodyBytes` 1 MiB/16 MiB, `maxResponseBytes` 1 MiB/16 MiB, `maxPages` 20/100, `maxPaginationItems` 1000/10000, `maxRetries` 0/3. Invalid limits throw `ERR_PRISM_OPENAPI_DOCUMENT_BOUNDS`.
|
|
50
50
|
|
|
51
|
+
## Live probe (plans/064 Task 7)
|
|
52
|
+
|
|
53
|
+
A live wire probe compiles the real public Warnely OpenAPI 3.1 spec (petstore serves 3.0 — the compiler requires 3.1) and drives real GET operations against it:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
PRISM_LIVE_OPENAPI_TOOLS=1 node --test packages/prism-coding-tools/dist/openapi/__tests__/live.test.js
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
3 requests total against the allow-listed public host: spec compile, a real 200 tool call, and a real 404 mapped to a status-carrying untrusted result; a missing-argument case proves validation fails closed locally (zero wire calls). Skips (never fails) when `PRISM_LIVE_OPENAPI_TOOLS` is unset. Registered in `scripts/live-matrix.json` as `coding-tools/openapi-live`.
|
|
60
|
+
|
|
51
61
|
## Related
|
|
52
62
|
|
|
53
63
|
- [Tools](tools.md): registry, dispatch, validation
|
package/docs/operations.md
CHANGED
|
@@ -94,6 +94,17 @@ tenant's reads, writes, and lease takeover all fail closed.
|
|
|
94
94
|
with bounded, jittered acquisition polls (no hot loops) and reports the
|
|
95
95
|
measured numbers in the evidence JSON.
|
|
96
96
|
|
|
97
|
+
## Live probe (plans/064 Task 9)
|
|
98
|
+
|
|
99
|
+
The outbound webhook notifier has an operator-gated live probe against a receiver you own:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
PRISM_TEST_WEBHOOK_URL=https://ops.example.com/hooks/prism \
|
|
103
|
+
PRISM_TEST_WEBHOOK_SECRET=<at-least-32-byte-shared-key> npm test -w @arnilo/prism-core -- webhooks-live
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Probes: one signed delivery to your receiver (verify `x-prism-signature: sha256=<hex>` over the raw body) and a retry-after-5xx leg over a local loopback receiver (500 then 200, signature verified, retries recorded). Bounded to 1 real request + ≤ 2 loopback requests. Registered in `scripts/live-matrix.json` as `core/webhooks-live`.
|
|
107
|
+
|
|
97
108
|
## Related APIs
|
|
98
109
|
|
|
99
110
|
- `LeaseStore` / `CheckpointStore` — the durable contracts this runbook relies on.
|
package/docs/performance.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Performance limits
|
|
2
2
|
|
|
3
|
-
Evaluation defaults are finite: 100 trace rows × 20 pages and 4 MiB aggregate trace data; one model-judge attempt with 30-second/16-KiB bounds; 8 comparison candidates, 1-MiB candidate results, 10,000 dataset items, and 4-MiB serialized reports. Hard caps are exported by `@arnilo/prism-evals`; overflow fails rather than truncating grading evidence.
|
|
3
|
+
Evaluation defaults are finite: 100 trace rows × 20 pages and 4 MiB aggregate trace data; one model-judge attempt with 30-second/16-KiB bounds; 8 comparison candidates, 1-MiB candidate results, 10,000 dataset items, and 4-MiB serialized reports. Hard caps are exported by `@arnilo/prism-core/governance/evals`; overflow fails rather than truncating grading evidence.
|
|
4
4
|
|
|
5
5
|
## What it does
|
|
6
6
|
|
|
@@ -377,9 +377,9 @@ Security automation is isolated from `npm test`: CodeQL/supply-chain jobs have 1
|
|
|
377
377
|
|
|
378
378
|
Web tools default/hard ceilings are query 4/16 KiB, results 10/20, URLs 5/20, request 256 KiB/1 MiB, response/aggregate 2/16 MiB, Markdown 1/8 MiB, extraction 256 KiB/1 MiB, schema 64/256 KiB, concurrency 4/16, retries 2/4, polling 20/100, and wall time 60 seconds/30 minutes. Bounds charge before request, retention, retry, or polling; overflow fails rather than truncating citation/extraction evidence.
|
|
379
379
|
|
|
380
|
-
Docker sandbox defaults/hard caps from `@arnilo/prism-coding-security`: startup 30 s/120 s; wall 20 min/30 min; idle 5 min/15 min; CPUs 2/8; memory 2 GiB/16 GiB (swap equal to memory); PIDs 256/1,024; FDs 1,024/8,192; workspace/tmp/download tmpfs 1 GiB/8 GiB, 256 MiB/2 GiB, 64 MiB/512 MiB; commands 100/256 with concurrent execs 1/8; env 64/256 names and 64 KiB/256 KiB values; export 50,000/250,000 entries and 256 MiB/2 GiB bytes with 16/64 retained artifacts; stop grace 5 s/30 s and cleanup 30 s/120 s. Caps validate before `docker create`/exec/export; overflow aborts and cleans the recorded container. Output still streams into the coding-agent `OutputAccumulator` ceilings (64 MiB/1 GiB).
|
|
380
|
+
Docker sandbox defaults/hard caps from `@arnilo/prism-coding-tools/security`: startup 30 s/120 s; wall 20 min/30 min; idle 5 min/15 min; CPUs 2/8; memory 2 GiB/16 GiB (swap equal to memory); PIDs 256/1,024; FDs 1,024/8,192; workspace/tmp/download tmpfs 1 GiB/8 GiB, 256 MiB/2 GiB, 64 MiB/512 MiB; commands 100/256 with concurrent execs 1/8; env 64/256 names and 64 KiB/256 KiB values; export 50,000/250,000 entries and 256 MiB/2 GiB bytes with 16/64 retained artifacts; stop grace 5 s/30 s and cleanup 30 s/120 s. Caps validate before `docker create`/exec/export; overflow aborts and cleans the recorded container. Output still streams into the coding-agent `OutputAccumulator` ceilings (64 MiB/1 GiB).
|
|
381
381
|
|
|
382
|
-
Repository list/search defaults/hard caps from `@arnilo/prism-coding-agent`: depth 32/128; entries/files 10,000/100,000; page/results 1,000/10,000; search scan 64 MiB/1 GiB aggregate and 8 MiB/64 MiB per file; matches 1,000/10,000; pattern 512 B/4 KiB; line 50 KiB/1 MiB; context 5/20; wall 30 s/300 s; concurrency config 8/32. Walks stream via `opendir`/`lstat`, never follow symlink escapes, and stop immediately on aggregate limits or abort.
|
|
382
|
+
Repository list/search defaults/hard caps from `@arnilo/prism-coding-tools/agent`: depth 32/128; entries/files 10,000/100,000; page/results 1,000/10,000; search scan 64 MiB/1 GiB aggregate and 8 MiB/64 MiB per file; matches 1,000/10,000; pattern 512 B/4 KiB; line 50 KiB/1 MiB; context 5/20; wall 30 s/300 s; concurrency config 8/32. Walks stream via `opendir`/`lstat`, never follow symlink escapes, and stop immediately on aggregate limits or abort.
|
|
383
383
|
|
|
384
384
|
Structured Git/check/handoff defaults/hard caps: paths 1,000/10,000; refs 1 KiB/4 KiB; commit message 64 KiB/256 KiB; inline Git output 4 MiB/64 MiB; diff lines 10,000/100,000; changed files 1,000/10,000; patch input 16 MiB/64 MiB; worktrees 4/16; named checks 8/32 names, concurrency 1/4, timeout 10 min/60 min, diagnostic lines 2,000/100,000, output 4 MiB/64 MiB; PR handoff JSON 256 KiB/1 MiB with 100/1,000 commits. Git tools use typed argument arrays (never shell), disable hooks/credential prompts/external diff by default, and emit host-owned PR handoff data only — no push/network/PR client.
|
|
385
385
|
|
|
@@ -557,7 +557,7 @@ Scope froze at commit `f5128a816ae204c52f3e2f089de71c99bd5de6d4`. Measurement ho
|
|
|
557
557
|
| Root artifact | `@arnilo/prism@0.0.4` dry-run tarball | 346.0 kB packed; 1.3 MB unpacked; 196 files |
|
|
558
558
|
| Installed workspace | Current root `node_modules` | 72 MiB |
|
|
559
559
|
|
|
560
|
-
Synthetic stream/tool/workflow values are medians of seven measured runs after one warm-up and contain no network, database, or exporter I/O. The temporary benchmark reused public `AgentSession`, `dispatchToolCallsInOrder`, and `@arnilo/prism-workflows` APIs; it was not added to CI because this phase records a baseline rather than creating hardware-sensitive tests.
|
|
560
|
+
Synthetic stream/tool/workflow values are medians of seven measured runs after one warm-up and contain no network, database, or exporter I/O. The temporary benchmark reused public `AgentSession`, `dispatchToolCallsInOrder`, and `@arnilo/prism-core/runtime/workflows` APIs; it was not added to CI because this phase records a baseline rather than creating hardware-sensitive tests.
|
|
561
561
|
|
|
562
562
|
Repository size at the same commit, counted from `src/` and `packages/` while excluding `dist/`:
|
|
563
563
|
|
|
@@ -590,7 +590,7 @@ Usage aggregation performs one constant-size accumulator update per terminal pro
|
|
|
590
590
|
|
|
591
591
|
### 0.0.5 Phase 4 verification (2026-07-15)
|
|
592
592
|
|
|
593
|
-
Optional `@arnilo/prism-evals` adds package-local scoring without changing core run latency. Validation stayed within the frozen release gate:
|
|
593
|
+
Optional `@arnilo/prism-core/governance/evals` adds package-local scoring without changing core run latency. Validation stayed within the frozen release gate:
|
|
594
594
|
|
|
595
595
|
| Surface | Result |
|
|
596
596
|
| --- | --- |
|
|
@@ -671,7 +671,7 @@ Optional `@arnilo/prism-rag` reuses Phase 7 vector contracts and adds no core pa
|
|
|
671
671
|
|
|
672
672
|
### 0.0.5 Phase 10 verification (2026-07-16)
|
|
673
673
|
|
|
674
|
-
Optional `@arnilo/prism-server` and MCP server-direction APIs compose existing agent/workflow/tool/SDK primitives; no core path, framework/listener, auth provider, database, or profile activation was added.
|
|
674
|
+
Optional `@arnilo/prism-core/runtime/server` and MCP server-direction APIs compose existing agent/workflow/tool/SDK primitives; no core path, framework/listener, auth provider, database, or profile activation was added.
|
|
675
675
|
|
|
676
676
|
| Surface | Result |
|
|
677
677
|
| --- | --- |
|
|
@@ -752,7 +752,7 @@ No performance ceiling was raised. Core grew from Phase 0's 346.0 kB packed base
|
|
|
752
752
|
|
|
753
753
|
### 0.0.13 Phase 8 server deployment seams (2026-07-23)
|
|
754
754
|
|
|
755
|
-
Optional health/drain/rate-limit/replay/deployment-lease helpers on `@arnilo/prism-server`. No listener, queue adapter, or concurrency hard-cap raise.
|
|
755
|
+
Optional health/drain/rate-limit/replay/deployment-lease helpers on `@arnilo/prism-core/runtime/server`. No listener, queue adapter, or concurrency hard-cap raise.
|
|
756
756
|
|
|
757
757
|
| Surface | Result |
|
|
758
758
|
| --- | --- |
|
|
@@ -9,7 +9,7 @@ Implementation is **shipped and phase-verified** (Tasks 0–7). Optional package
|
|
|
9
9
|
## When to use it
|
|
10
10
|
|
|
11
11
|
- **Adapter authors** implementing SQLite/PostgreSQL `SessionStore` + `RunLedger` should start here, then follow [Database persistence](database-persistence.md) and [Session store conformance](session-store-conformance.md).
|
|
12
|
-
- **Host apps** wiring CLI/desktop credential persistence should use the credential seams and package matrix here before choosing `@arnilo/prism-credentials
|
|
12
|
+
- **Host apps** wiring CLI/desktop credential persistence should use the credential seams and package matrix here before choosing `@arnilo/prism-core/credentials/node` backends.
|
|
13
13
|
- **Provider and core authors** extending multimodal input should use the content/resource/capability designs here instead of embedding provider upload IDs in core contracts.
|
|
14
14
|
- **Security reviewers** use the threat model and conformance matrix on this page as the acceptance baseline for Plan 056 Tasks 1–7.
|
|
15
15
|
|
|
@@ -108,10 +108,10 @@ Prism `engines.node` is `>=20`. Optional packages stay package-local; core adds
|
|
|
108
108
|
|
|
109
109
|
| Package (planned) | Driver / backend | Pinned version | Node support | Rationale |
|
|
110
110
|
| --- | --- | --- | --- | --- |
|
|
111
|
-
| `@arnilo/prism-
|
|
112
|
-
| `@arnilo/prism-
|
|
113
|
-
| `@arnilo/prism-credentials
|
|
114
|
-
| `@arnilo/prism-credentials
|
|
111
|
+
| `@arnilo/prism-core/sessions/sqlite` | `better-sqlite3` | `^12.11.1` | 20.x–26.x per upstream engines | Synchronous API, WAL/busy_timeout, mature Node 20 baseline; `node:sqlite` rejected — requires Node ≥22.5 and is still experimental vs declared `>=20` baseline |
|
|
112
|
+
| `@arnilo/prism-core/sessions/postgres` | `pg` | `^8.22.0` | ≥16 (satisfies 20+) | Standard pool + parameterized queries; TLS/credentials host-owned |
|
|
113
|
+
| `@arnilo/prism-core/credentials/node` encrypted file | Node `crypto` (AES-256-GCM + scrypt) | built-in | 20+ | No extra deps for AEAD/KDF; atomic rename writes |
|
|
114
|
+
| `@arnilo/prism-core/credentials/node` keychain | `@napi-rs/keyring` | `^1.3.0` | ≥10 (satisfies 20+) | Cross-platform, actively maintained (2026); `keytar@7.9.0` rejected — last release 2022, heavier native rebuild friction |
|
|
115
115
|
|
|
116
116
|
**Rejected options:**
|
|
117
117
|
|
|
@@ -131,7 +131,7 @@ Prism `engines.node` is `>=20`. Optional packages stay package-local; core adds
|
|
|
131
131
|
| Persistence location | Core built-in DB | Optional packages over contracts | **Optional packages** | Matches Plan 053 JSONL boundary and `ProductionPersistenceStore` extension point |
|
|
132
132
|
| Schema/migrations | Core DDL generator | Shared fixture model + dialect-local SQL | **Shared fixtures + local SQL** | Two adapters without ORM |
|
|
133
133
|
| Run ledger conformance | Per-package tests only | Shared conformance module (Task 1) | **Shared module** | Parity with session-store conformance |
|
|
134
|
-
| Credential persistence | Core global store | `@arnilo/prism-credentials
|
|
134
|
+
| Credential persistence | Core global store | `@arnilo/prism-core/credentials/node` | **Optional package** | Host selects file vs keychain |
|
|
135
135
|
| KDF | PBKDF2 default | scrypt with documented minimums | **scrypt** (configurable N/r/p) | Node built-in; calibrate in Task 4 tests |
|
|
136
136
|
| Multimodal content | Provider-specific options only | Generic `ContentBlock` + capability tags | **Generic blocks + capabilities** | Portable input; provider maps/uploads locally |
|
|
137
137
|
| URL/file sources | Loader reads anything | Bounded loader policy + trust integration | **Bounded + trust** | Reuse `createPathTrustPolicy` patterns; SSRF deny-by-default for URLs |
|
package/docs/policy-and-audit.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## What it does
|
|
4
4
|
|
|
5
|
-
`@arnilo/prism-policy` records redacted allow/deny/modify/approval decisions with policy version, actor refs from verified `AgentIdentity`, target, reason, expiry, and evidence references. Hosts export cursor-paginated pages to append-only/WORM sinks. The package does not embed a mandatory global policy engine, KMS, or cloud WORM SDK.
|
|
5
|
+
`@arnilo/prism-core/governance/policy` records redacted allow/deny/modify/approval decisions with policy version, actor refs from verified `AgentIdentity`, target, reason, expiry, and evidence references. Hosts export cursor-paginated pages to append-only/WORM sinks. The package does not embed a mandatory global policy engine, KMS, or cloud WORM SDK.
|
|
6
6
|
|
|
7
7
|
## When to use it
|
|
8
8
|
|
|
@@ -64,7 +64,7 @@ import {
|
|
|
64
64
|
evaluateAndAppend,
|
|
65
65
|
exportPolicyDecisions,
|
|
66
66
|
recordToolApprovalDecision,
|
|
67
|
-
} from "@arnilo/prism-policy";
|
|
67
|
+
} from "@arnilo/prism-core/governance/policy";
|
|
68
68
|
|
|
69
69
|
const evaluator = createPolicyEvaluator({
|
|
70
70
|
policyId: "mail",
|
|
@@ -129,7 +129,7 @@ Immutable approval requests carry an action digest, requester, and required role
|
|
|
129
129
|
| `ApprovalRecord` | Request + `status` (`pending/approved/rejected/revoked/consumed`) + `revision` + immutable `decisions` + `policyRevision` |
|
|
130
130
|
| `ApprovalStore.create/decide/revoke/consume/get/query` | Durable transitions; every transition records an `auditRef` |
|
|
131
131
|
| `createMemoryApprovalStore({ authority })` | Single-process reference adapter sharing the pure transition logic |
|
|
132
|
-
| `createPostgresApprovalStore({ pool, schema, authority })` | Cross-replica storage (migration `005_erp_approvals`, `@arnilo/prism-enterprise
|
|
132
|
+
| `createPostgresApprovalStore({ pool, schema, authority })` | Cross-replica storage (migration `005_erp_approvals`, `@arnilo/prism-core/enterprise/postgres`) |
|
|
133
133
|
|
|
134
134
|
Quorum rules:
|
|
135
135
|
|
|
@@ -152,7 +152,7 @@ WHERE status = 'pending' AND expires_at < now();
|
|
|
152
152
|
|
|
153
153
|
Hosts own identity verification and the role source; Prism does not certify NIST compliance. NIST SP 800-53 AC-5 (separation of duties) and AC-6 (least privilege) are control guidance only, not certification claims.
|
|
154
154
|
|
|
155
|
-
## OPA external policy adapter (`@arnilo/prism-policy/opa`, 0.0.28)
|
|
155
|
+
## OPA external policy adapter (`@arnilo/prism-core/governance/policy/opa`, 0.0.28)
|
|
156
156
|
|
|
157
157
|
Optional `createOpaPolicyEvaluator` evaluates `PolicyEvaluateRequest`s against a host-pinned OPA REST endpoint (`POST /v1/data/<path>` with `{"input": <document>}`) and returns a core `PolicyEvaluator` for `evaluateAndAppend`. Native `fetch` only; no OPA SDK dependency.
|
|
158
158
|
|
|
@@ -168,9 +168,9 @@ Optional `createOpaPolicyEvaluator` evaluates `PolicyEvaluateRequest`s against a
|
|
|
168
168
|
| `ssrf` | `SsrfPolicy` for the endpoint; denials surface `MediaContentError` (`ssrf_denied`) |
|
|
169
169
|
|
|
170
170
|
```ts
|
|
171
|
-
import { createOpaPolicyEvaluator } from "@arnilo/prism-policy/opa";
|
|
172
|
-
import { createPostgresEnterpriseState } from "@arnilo/prism-enterprise
|
|
173
|
-
import { evaluateAndAppend } from "@arnilo/prism-policy";
|
|
171
|
+
import { createOpaPolicyEvaluator } from "@arnilo/prism-core/governance/policy/opa";
|
|
172
|
+
import { createPostgresEnterpriseState } from "@arnilo/prism-core/enterprise/postgres";
|
|
173
|
+
import { evaluateAndAppend } from "@arnilo/prism-core/governance/policy";
|
|
174
174
|
|
|
175
175
|
const evaluator = createOpaPolicyEvaluator({
|
|
176
176
|
url: "https://opa.internal:8181/v1/data/prism/allow",
|
|
@@ -194,6 +194,16 @@ await evaluateAndAppend(request, { store: state.policy, evaluator, id: crypto.ra
|
|
|
194
194
|
|
|
195
195
|
`state.close()` leaves a caller-owned pool open. Run `state.cleanup(...)` from an authorized host schedule only when expiration cleanup is needed; it does not run in the background.
|
|
196
196
|
|
|
197
|
+
## Live probe (plans/064 Task 9)
|
|
198
|
+
|
|
199
|
+
The OPA policy evaluator has an operator-gated live probe against a real decision endpoint:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
PRISM_TEST_OPA_URL=https://opa:8181/v1/data/prism/allow npm test -w @arnilo/prism-core -- opa-live
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Probes: two real decision evaluations (any valid outcome) and one fail-closed probe (unroutable endpoint ⇒ `deny` with `OPA endpoint unavailable`). Bounded to ≤ 2 real requests. Registered in `scripts/live-matrix.json` as `core/opa-live`.
|
|
206
|
+
|
|
197
207
|
## Related APIs
|
|
198
208
|
|
|
199
209
|
- [Model routing](model-routing.md)
|
package/docs/ponytail.md
CHANGED
|
@@ -108,7 +108,7 @@ See `examples/caveman-ponytail.ts` for combined Caveman + Ponytail progressive d
|
|
|
108
108
|
- Mode restore scans `getEntries()` for latest `data.type === "ponytail-mode"` (OM attach pattern).
|
|
109
109
|
- `ponytail-subagent` hook is not wired; nested-agent behavior is host responsibility. When hosts wire the upstream hook, `PONYTAIL_SUBAGENT_MATCHER` accepts only the documented safe subset — `"explore|general"` (any literal substring) or `"^general$"` (exact), case-insensitive, max 256 chars. No `RegExp` is compiled from the environment, so arbitrary regex (including catastrophic nested quantifiers) is never evaluated; unset/invalid patterns inject into every subagent.
|
|
110
110
|
- No TUI statusline scripts; use `ponytail status` command or extension events.
|
|
111
|
-
- Not included in `@arnilo/prism-
|
|
111
|
+
- Not included in `@arnilo/prism-coding-tools` or `@arnilo/prism-core` profiles — opt-in install only.
|
|
112
112
|
|
|
113
113
|
## Security and performance notes
|
|
114
114
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## What it does
|
|
4
4
|
|
|
5
|
-
The optional `@arnilo/prism-
|
|
5
|
+
The optional `@arnilo/prism-core/sessions/postgres` package ships a production-oriented PostgreSQL adapter that implements:
|
|
6
6
|
|
|
7
7
|
- `SessionStore` — atomic `append` / `list` / `get` / `readBranchPath` / bounded `searchSessions` / bounded `searchSessions`
|
|
8
8
|
- `RunLedger` — durable run, event, tool-call, and usage rows
|
|
@@ -24,13 +24,13 @@ Use this package when you need server-backed persistence with pooled connections
|
|
|
24
24
|
- managed cloud databases (RDS, Cloud SQL, Neon, Supabase, etc.)
|
|
25
25
|
- CI integration tests against a real PostgreSQL service
|
|
26
26
|
|
|
27
|
-
Prefer [`@arnilo/prism-
|
|
27
|
+
Prefer [`@arnilo/prism-core/sessions/sqlite`](sqlite-persistence.md) for local CLI tools, single-writer workloads, and network-free default tests. This adapter stores sessions/runs, not semantic vectors; use the separate [`@arnilo/prism-memory` pgvector path](working-and-semantic-memory.md), which rejects non-finite vectors before SQL, when vector recall is needed. For durable policy decisions, evaluations, work mutation idempotency, and model-router state, use the separate [`@arnilo/prism-core/enterprise/postgres`](enterprise-postgres-state.md) composition; it has its own migration history and does not replace session/run persistence.
|
|
28
28
|
|
|
29
29
|
## Inputs / request
|
|
30
30
|
|
|
31
31
|
```ts
|
|
32
32
|
import { Pool } from "pg";
|
|
33
|
-
import { createPostgresPersistence } from "@arnilo/prism-
|
|
33
|
+
import { createPostgresPersistence } from "@arnilo/prism-core/sessions/postgres";
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
| Field | Type | Purpose |
|
|
@@ -82,7 +82,7 @@ Migrations run automatically on open and are idempotent across reopen. Concurren
|
|
|
82
82
|
```ts
|
|
83
83
|
import { Pool } from "pg";
|
|
84
84
|
import { createAgentSession } from "@arnilo/prism";
|
|
85
|
-
import { createPostgresPersistence } from "@arnilo/prism-
|
|
85
|
+
import { createPostgresPersistence } from "@arnilo/prism-core/sessions/postgres";
|
|
86
86
|
import { runSessionStoreConformance } from "@arnilo/prism/testing/session-store-conformance";
|
|
87
87
|
|
|
88
88
|
const pool = new Pool({
|
|
@@ -111,7 +111,7 @@ await pool.end();
|
|
|
111
111
|
Live conformance and integration tests:
|
|
112
112
|
|
|
113
113
|
```bash
|
|
114
|
-
PRISM_TEST_POSTGRES_URL="$DATABASE_URL" npm run test:postgres --workspace @arnilo/prism-
|
|
114
|
+
PRISM_TEST_POSTGRES_URL="$DATABASE_URL" npm run test:postgres --workspace @arnilo/prism-core/sessions/postgres
|
|
115
115
|
```
|
|
116
116
|
|
|
117
117
|
## Extension and configuration notes
|