@arnilo/prism 0.0.22 → 0.0.24
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 +36 -2
- package/dist/agent-event-source.d.ts +11 -0
- package/dist/agent-event-source.js +512 -0
- package/dist/agent-run-state.js +6 -1
- package/dist/agents.js +7 -2
- package/dist/contracts.d.ts +157 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.js +4 -1
- package/dist/testing/agent-event-source-conformance.d.ts +4 -0
- package/dist/testing/agent-event-source-conformance.js +54 -0
- package/dist/testing/persistence-schema.d.ts +2 -2
- package/dist/testing/persistence-schema.js +58 -21
- package/dist/testing/tool-effect-store-conformance.d.ts +9 -0
- package/dist/testing/tool-effect-store-conformance.js +85 -0
- package/dist/tool-effects.d.ts +15 -0
- package/dist/tool-effects.js +338 -0
- package/dist/tools.d.ts +3 -1
- package/dist/tools.js +204 -9
- package/docs/0.1.0-readiness.md +10 -9
- package/docs/a2a.md +6 -2
- package/docs/ag-ui-adoption.md +77 -0
- package/docs/ag-ui.md +39 -42
- package/docs/agent-events.md +5 -1
- package/docs/browser-automation.md +2 -0
- package/docs/coding-agent-tools.md +2 -0
- package/docs/database-persistence.md +5 -0
- package/docs/enterprise-postgres-state.md +177 -0
- package/docs/evaluations.md +13 -0
- package/docs/host-security.md +11 -1
- package/docs/index.md +17 -14
- package/docs/mcp-tools.md +17 -2
- package/docs/migration.md +41 -0
- package/docs/model-routing.md +17 -8
- package/docs/performance.md +38 -0
- package/docs/policy-and-audit.md +12 -0
- package/docs/postgres-persistence.md +7 -3
- package/docs/public-contracts.md +2 -0
- package/docs/release-and-install.md +67 -680
- package/docs/server.md +9 -6
- package/docs/sqlite-persistence.md +10 -2
- package/docs/supervisors.md +2 -0
- package/docs/tool-effects.md +95 -0
- package/docs/tools.md +4 -0
- package/docs/work-tools.md +21 -1
- package/package.json +11 -2
package/docs/server.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## What it does
|
|
4
4
|
|
|
5
|
-
`@arnilo/prism-server` exposes explicitly selected agents and workflows through one framework-free `(Request) => Promise<Response>` handler. It supports direct agent results, bounded agent/workflow SSE, opt-in durable agent status/resume, durable workflow start/enqueue/status/cancel/resume/replay, ownership-scoped schedules, host authorization, ownership propagation, redaction, resource ceilings, and optional deployment seams (health/readiness, drain, host rate-limit adapter, ownership-scoped event replay, worker/coordinator lease election).
|
|
5
|
+
`@arnilo/prism-server` exposes explicitly selected agents and workflows through one framework-free `(Request) => Promise<Response>` handler. It supports direct agent results, bounded agent/workflow SSE, cross-replica durable agent-event reconnect, opt-in durable agent status/resume, durable workflow start/enqueue/status/cancel/resume/replay, ownership-scoped schedules, host authorization, ownership propagation, redaction, resource ceilings, and optional deployment seams (health/readiness, drain, host rate-limit adapter, ownership-scoped event replay, worker/coordinator lease election).
|
|
6
6
|
|
|
7
7
|
No listener starts on import. Empty `agents`/`workflows` maps expose nothing. Authentication, authorization, route selection, durable stores, TLS, distributed rate limiting, queues, and framework/serverless adaptation remain host-owned.
|
|
8
8
|
|
|
@@ -17,7 +17,7 @@ Use `AgentSession` or workflow APIs directly for in-process applications. Do not
|
|
|
17
17
|
```ts
|
|
18
18
|
const drain = createPrismDrainController({ deadlineMs: 30_000 });
|
|
19
19
|
const handler = createPrismHandler({
|
|
20
|
-
agents?: Record<string, Agent | PrismAgentExposure>,
|
|
20
|
+
agents?: Record<string, Agent | PrismAgentExposure>, // exposure may include events + resolveRun
|
|
21
21
|
agentRuns?: Record<string, PrismAgentRunExposure>, // explicit durable status/resume only
|
|
22
22
|
workflows?: Record<string, PrismWorkflowExposure>,
|
|
23
23
|
schedules?: WorkflowSchedules | ((authorization, signal) => WorkflowSchedules),
|
|
@@ -46,6 +46,7 @@ At least one non-empty ownership field must come from `authorize()`. Request JSO
|
|
|
46
46
|
| `POST /prism/agents/:id/stream` | `agent.stream` | same; SSE response |
|
|
47
47
|
| `GET /prism/agents/:id/runs/:runId` | `agent.status` | none; redacted public state/version only |
|
|
48
48
|
| `POST /prism/agents/:id/runs/:runId/resume` | `agent.resume` | `{ "decision": "approve" | "deny", "expectedVersion": number }` |
|
|
49
|
+
| `GET /prism/agents/:id/runs/:runId/events?cursor=` | `agent.events` | none; durable SSE, also accepts `Last-Event-ID` |
|
|
49
50
|
| `POST /prism/workflows/:id/runs` | `workflow.run` | `{ "input": unknown, "runId"?: string }` |
|
|
50
51
|
| `POST /prism/workflows/:id/stream` | `workflow.stream` | same; SSE response |
|
|
51
52
|
| `POST /prism/workflows/:id/enqueue` | `workflow.enqueue` | `{ "input": unknown, "runId"?: string }`; returns `202` queued handle |
|
|
@@ -64,7 +65,7 @@ POST routes require `Content-Type: application/json`. Capability/run IDs are bou
|
|
|
64
65
|
|
|
65
66
|
## Outputs / response / events
|
|
66
67
|
|
|
67
|
-
Direct routes return bounded JSON.
|
|
68
|
+
Direct routes return bounded JSON. New-run stream routes return `text/event-stream`; every event is one `data: <AgentEvent|WorkflowEvent>` frame. Durable event reconnect frames add `id: <opaque source cursor>` before `data: <AgentEvent>` and resume strictly after either matching `?cursor=` or `Last-Event-ID`. Conflicting header/query cursors fail before source access. Status returns the ownership-scoped durable checkpoint record. Resume uses Phase 8 expected-version CAS. Cancel aborts active work or marks eligible durable checkpoints aborted.
|
|
68
69
|
|
|
69
70
|
Errors use `{ "error": { "code", "message" } }`. Unknown routes/capabilities are `404`, authorization/policy denial `403`, malformed input `400`, unsupported content type `415`, body overflow `413`, concurrency overflow `429`, and result overflow `507`. Unexpected errors are generic and never include stacks.
|
|
70
71
|
|
|
@@ -135,7 +136,8 @@ Compose beside `createPrismHandler` — Prism starts no listener, container orch
|
|
|
135
136
|
| `createPrismHealthHandler` | `GET /health`, `/livez`, `/readyz`. Minimal JSON; `?detail=1` requires `authorizeDetail`. No secrets/tenant payloads by default. Ready fails while draining. |
|
|
136
137
|
| `createPrismDrainController` | `beginDrain()` rejects admit ops (`agent.run`/`stream`/`resume`, workflow run/stream/enqueue/resume/replay, schedule create/trigger) with `503 ERR_PRISM_SERVER_DRAINING`. Status/cancel/list stay open. |
|
|
137
138
|
| `rateLimit` on handler | Host adapter after authorize, before session create. Return denial `{ retryAfterMs, code, message }` → `429` + optional `Retry-After`. `createMemoryRateLimiter` is single-process only. |
|
|
138
|
-
| `
|
|
139
|
+
| `createPrismAgentEventReplay` | Shared `AgentEventSource` page/follow semantics for exact-owned runs. |
|
|
140
|
+
| `createPrismEventReplay` / `createPrismReplayHandler` | Compatible ownership-scoped legacy `queryEvents` pages (`redacted: true`). Does not re-run work. Unauthorized replay denies. |
|
|
139
141
|
| `createPrismDeploymentLease` | Lease election under `prism.server.deployment`. Coordinator replica holds `key: "coordinator"` before schedule ticks; workers run `@arnilo/prism-workflows` `createWorkflowCoordinator` for queued runs (fencing tokens). |
|
|
140
142
|
| `createConversationService` / `createConversationHandler` | Durable user-scoped conversation threads (create/list/continue/branch/archive/export/delete) over session + event-ledger seams, with thread-bound reconnectable replay. Mounts beside the handler; see [Conversations](conversations.md). |
|
|
141
143
|
| `createArtifactService` / `createArtifactHandler` | Durable artifact co-work review (attach/revise/compare/approve/reject/last-validated/delivery-link + authorized download) over the versioned checkpoint store; records persist metadata/revisions/approvals only, never file bodies. Mounts beside the handler; see [Work artifacts and review](work-artifacts-and-review.md). |
|
|
@@ -153,7 +155,7 @@ Network-free demo: [`examples/server-deployment-seams.ts`](../examples/server-de
|
|
|
153
155
|
- Agent tools and workflow tool nodes still need their own `PermissionPolicy`, `ToolValidator`, and `ExecutionPolicy`. HTTP authorization does not replace side-effect policy.
|
|
154
156
|
- Host and origin allow-lists are exact string matches. Configure reverse-proxy normalization, TLS, IP policy, CSRF/cookie policy, and authentication outside Prism. Optional `rateLimit` is an attributable short-circuit only — not a WAF.
|
|
155
157
|
- Health endpoints reveal process/liveness only by default; detail flags require host authorize and must omit secrets/tenant dumps.
|
|
156
|
-
- Drain and event replay require the same ownership/authorize boundary as other routes; replay never invokes providers or tools.
|
|
158
|
+
- Drain and event replay require the same ownership/authorize boundary as other routes; replay never invokes providers or tools. Durable event routes exist only on object `PrismAgentExposure` entries with both `events` and `resolveRun`; every reconnect authorizes again, resolves public run ID to exact internal session/run IDs, and opens the shared source without `sessionFactory`.
|
|
157
159
|
- SSE uses bounded upstream subscriber queues. Consumer cancellation aborts owned work by default and releases concurrency; set `disconnectAborts: false` only when the host deliberately owns background completion.
|
|
158
160
|
- Source inputs/resource URLs remain host responsibilities and use existing resource/media SSRF policies. Server package does not fetch URLs.
|
|
159
161
|
- Schedule routes never accept ownership from JSON. Services carry mandatory ownership and explicit workflow/calculator registries; route authorization cannot broaden either. Replay applies workflow ownership/hash/approval checks.
|
|
@@ -172,5 +174,6 @@ A2A routes are not added to `createPrismHandler()`. Install `@arnilo/prism-super
|
|
|
172
174
|
- [A2A interoperability](a2a.md): separately mounted A2A 1.0 handler/client.
|
|
173
175
|
- [Conversations](conversations.md): durable user-scoped conversation service, replay, branches, export, deletion.
|
|
174
176
|
- [Work artifacts and review](work-artifacts-and-review.md): durable artifact review service, revisions, approvals, authorized expiring delivery links.
|
|
175
|
-
- [Frontend interoperability (AG-UI and ACP)](ag-ui.md): separately installed authorized AG-UI Web handler
|
|
177
|
+
- [Frontend interoperability (AG-UI and ACP)](ag-ui.md): separately installed authorized AG-UI Web handler.
|
|
178
|
+
- [AG-UI adoption evaluation](ag-ui-adoption.md): official 0.0.57 support matrix and MCP/A2A follow-up scope.
|
|
176
179
|
- [Release and install](release-and-install.md): optional package installation and profiles.
|
|
@@ -56,7 +56,7 @@ import { createSqlitePersistence } from "@arnilo/prism-session-store-sqlite";
|
|
|
56
56
|
| `leases` | Atomic `LeaseStore` backed by `prism_leases`; database-clock expiry, opaque renew/release token, monotonic takeover fence. |
|
|
57
57
|
| `close()` | Closes the underlying database when the adapter opened it. |
|
|
58
58
|
|
|
59
|
-
Migrations run automatically on open and are idempotent across reopen. Under the SQLite migration transaction, startup checks ordered contract name/version/SHA-256 rows plus full schema-
|
|
59
|
+
Migrations run automatically on open and are idempotent across reopen. Under the SQLite migration transaction, startup checks ordered contract name/version/SHA-256 rows plus full schema-v6 PRAGMA/catalog shape (all required tables, columns/types/nullability/defaults, PK/unique/FK keys, and named indexes) before any runtime write. A complete legacy 0.0.5 history with all `checksum` values `NULL` is shape-verified then backfilled transactionally once. Unknown, duplicate, out-of-order, partial-legacy, checksum, or shape drift rejects open; restore or apply reviewed DDL rather than editing migration rows.
|
|
60
60
|
|
|
61
61
|
## Request/response example
|
|
62
62
|
|
|
@@ -99,9 +99,17 @@ For resume/timeline flows, use `queryRuns`, `queryEvents`, `queryToolCalls`, and
|
|
|
99
99
|
- The package is optional and workspace-local; `@arnilo/prism` core has no SQLite dependency.
|
|
100
100
|
- Hosts choose the database path and own backup, retention enforcement, and filesystem permissions.
|
|
101
101
|
- `SessionAppendOptions` idempotency rows are durable in `prism_session_append_idempotency` and survive reopen.
|
|
102
|
-
- Schema version **
|
|
102
|
+
- Schema version **6** applies `001_init`, `002_usage_scope`, `003_run_feedback`, `004_session_search`, `005_lifecycle_hold_quota`, and `006_agent_event_source`. Migration 006 backfills `prism_agent_event_streams` and uses it to allocate unique per-run event sequences inside the SQLite append transaction. It is sequence-compatible with PostgreSQL but remains local/file-backed; it does not expose distributed subscriptions. Migration 003 adds immutable `prism_run_feedback` rows with run FK/cascade deletion and owner/run/trace cursor indexes. Migration 004 adds session search FTS (FTS5 virtual table `prism_session_search_fts` dual-written on append) plus `prism_sessions(updated_at, id)` cursor index; existing entries are backfilled once. `persistence.feedback` validates exact run ownership, bounds/redacts through optional `feedbackRedactor`, queries bounded pages, and deletes only exact-owned IDs. Search hits never include credentials; ownership filters apply when present. PostgreSQL shares the same model with dialect-local DDL.
|
|
103
103
|
- Pass an existing `better-sqlite3` `Database` via `database` when your host already manages connections.
|
|
104
104
|
|
|
105
|
+
## Durable events
|
|
106
|
+
|
|
107
|
+
SQLite applies migrations **006**/**007** for per-run event sequence compatibility and the owner retention index. It does **not** provide cross-process subscribe/LISTEN; use PostgreSQL for distributed reconnect.
|
|
108
|
+
|
|
109
|
+
## Durable events
|
|
110
|
+
|
|
111
|
+
SQLite applies migrations **006**/**007** for per-run event sequence compatibility and the owner retention index. It does **not** provide cross-process subscribe/LISTEN; use PostgreSQL for distributed reconnect.
|
|
112
|
+
|
|
105
113
|
## Security and performance notes
|
|
106
114
|
|
|
107
115
|
- **Parameterized SQL only.** Session ids, idempotency keys, tenant ids, and JSON payloads are bound parameters.
|
package/docs/supervisors.md
CHANGED
|
@@ -54,6 +54,8 @@ const result = await supervisor.delegate({ childId: "research", input: "Check so
|
|
|
54
54
|
|
|
55
55
|
Child factories resolve their own providers/credentials and construct context/memory using the supplied IDs. Parent, child, returned-agent, budget, and hook permission policies are AND-composed. Child/request/hook limits can only lower inherited limits. A nested factory can call the supplied `delegate()`; immutable path state rejects cycles and depth overflow.
|
|
56
56
|
|
|
57
|
+
Supervisors propagate parent `identity` and `effectStore` to every child agent/run so delegated tool effects stay under the same ownership scope.
|
|
58
|
+
|
|
57
59
|
## Security and performance notes
|
|
58
60
|
|
|
59
61
|
- Child IDs are explicit; no package/provider discovery occurs.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Recoverable tool effects
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
Optional tool-effect contracts record whether a tool call may mutate state and how Prism recovers after crash or duplicate delivery. When a host supplies `effectStore` and a tool declares `effect`, dispatch claims before side effects, marks dispatched before execute, and completes or marks unknown after. Ambiguous outcomes never auto-replay. This is at-least-once claim coordination, not exactly-once delivery.
|
|
6
|
+
|
|
7
|
+
APIs:
|
|
8
|
+
|
|
9
|
+
- `ToolEffectDeclaration` / `ToolEffectClassifier` on `ToolDefinition.effect`
|
|
10
|
+
- `ToolEffectStore` (`get` / `begin` / `markDispatched` / `complete` / `fail` / `markUnknown` / `resolveUnknown` / `cleanup`)
|
|
11
|
+
- `createMemoryToolEffectStore()` (in-process reference)
|
|
12
|
+
- `deriveToolEffectKey()` / `toolEffectArgumentsHash()` / `canonicalToolEffectJson()`
|
|
13
|
+
- Enterprise: `createPostgresEnterpriseState().toolEffects`
|
|
14
|
+
|
|
15
|
+
## When to use it
|
|
16
|
+
|
|
17
|
+
Use when tools perform local or external mutations and a host needs durable claim/CAS recovery across process restart. Skip for pure observation tools (`kind: "none"`). Keep `session.subscribe()` for live UI; pair durable events with [Agent events](agent-events.md) when reconnecting replicas.
|
|
18
|
+
|
|
19
|
+
## Inputs / request
|
|
20
|
+
|
|
21
|
+
| Field | Values | Meaning |
|
|
22
|
+
| --- | --- | --- |
|
|
23
|
+
| `kind` | `none` / `local_mutation` / `external_mutation` | Observation vs local vs external side effect |
|
|
24
|
+
| `idempotency` | `none` / `optional` / `required` / `tool_managed` / `unsupported` | Whether core claims a key |
|
|
25
|
+
| `effectStore` | on `AgentConfig` / `RunOptions` | Opt-in store; required when idempotency is `required` |
|
|
26
|
+
| `context.idempotencyKey` | core-derived only | Model-supplied keys are ignored |
|
|
27
|
+
|
|
28
|
+
Statuses: `pending` → `dispatched` → `completed` | `failed_retryable` | `failed_terminal` | `unknown`. Expired pending becomes retryable; expired dispatched becomes unknown. Unknown needs operator `resolveUnknown`.
|
|
29
|
+
|
|
30
|
+
## Outputs / response / events
|
|
31
|
+
|
|
32
|
+
| Outcome | Behavior |
|
|
33
|
+
| --- | --- |
|
|
34
|
+
| First claim | `begin` acquires; dispatch marks dispatched then executes |
|
|
35
|
+
| Duplicate completed | returns bounded stored result; tool body does not rerun |
|
|
36
|
+
| Ambiguous crash | `unknown` + `ERR_PRISM_TOOL_EFFECT_UNKNOWN`; never silent replay |
|
|
37
|
+
| Unsupported | no store/identity required; host owns recovery |
|
|
38
|
+
|
|
39
|
+
## Request/response example
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"kind": "external_mutation",
|
|
44
|
+
"idempotency": "required"
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Implementation example
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { createAgent, createMemoryToolEffectStore, dispatchToolCall } from "@arnilo/prism";
|
|
52
|
+
|
|
53
|
+
const effectStore = createMemoryToolEffectStore();
|
|
54
|
+
const tool = {
|
|
55
|
+
name: "mail.send",
|
|
56
|
+
description: "Send mail",
|
|
57
|
+
parameters: { type: "object", properties: {} },
|
|
58
|
+
effect: { kind: "external_mutation", idempotency: "required" },
|
|
59
|
+
execute: async (_args, context) => ({ toolCallId: context.toolCallId, name: "mail.send", value: { sent: true } }),
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const agent = createAgent({ model, provider, tools: [tool], effectStore });
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Runnable demo: `examples/distributed-events-and-tool-effects.ts`.
|
|
66
|
+
|
|
67
|
+
## Extension and configuration notes
|
|
68
|
+
|
|
69
|
+
| Surface | Classification |
|
|
70
|
+
| --- | --- |
|
|
71
|
+
| Coding read/list/search/glob | `none` / `none` |
|
|
72
|
+
| Coding write/edit/delete/move/git commit | `local_mutation` / `optional` |
|
|
73
|
+
| Coding shell / check | `external_mutation` / `unsupported` |
|
|
74
|
+
| Browser observation | `none` / `none` |
|
|
75
|
+
| Browser mutation | `external_mutation` / `unsupported` |
|
|
76
|
+
| Work connector reads | `none` / `none` |
|
|
77
|
+
| Work connector mutations | `external_mutation` / `tool_managed` (core key + store) |
|
|
78
|
+
| MCP remote tools | host `effect` policy; default unsupported |
|
|
79
|
+
| Supervisor children | inherit parent `identity` + `effectStore` |
|
|
80
|
+
|
|
81
|
+
## Security and performance notes
|
|
82
|
+
|
|
83
|
+
- Ownership and verified identity bind every claim key; cursors/keys never select tenants.
|
|
84
|
+
- Results/references are byte-bounded and redacted; oversized writes fail closed.
|
|
85
|
+
- Claim TTL default 15 min (hard 60); attempts default 3 (hard 10); unknown has no auto-expiry.
|
|
86
|
+
- PostgreSQL store uses parameterized CAS; request roles stay `SELECT`/`INSERT`/`UPDATE`/`DELETE` only.
|
|
87
|
+
- Recorded p95 claim/transition ≈ 3.1 ms under Task 0 ceilings — see [performance](performance.md).
|
|
88
|
+
|
|
89
|
+
## Related APIs
|
|
90
|
+
|
|
91
|
+
- [Tools](tools.md): dispatch harness that hosts effect claim/recovery.
|
|
92
|
+
- [Agent events](agent-events.md): durable `AgentEventSource` for replica reconnect (separate from effect claims).
|
|
93
|
+
- [Work tools](work-tools.md): connector `tool_managed` reconciliation.
|
|
94
|
+
- [Enterprise PostgreSQL state](enterprise-postgres-state.md): durable `toolEffects` store.
|
|
95
|
+
- [Host security](host-security.md): unknown-outcome fail-closed guidance.
|
package/docs/tools.md
CHANGED
|
@@ -237,6 +237,8 @@ await session.run(input, {
|
|
|
237
237
|
- Prism does not sandbox host tools and does not include built-in app tools.
|
|
238
238
|
- Contribution registration and registry/filter calls do not perform provider calls, credential resolution, resource loading, network, filesystem discovery, or tool execution.
|
|
239
239
|
- Dispatch performs explicit in-memory checks and executes only the selected host-active tool; it adds no retries, queues, timers, or new dependencies.
|
|
240
|
+
- When `effectStore` is configured, dispatch claims before side effects and never auto-replays `unknown` outcomes (see [tool effects](tool-effects.md)).
|
|
241
|
+
- When `effectStore` is configured, dispatch claims before side effects and never auto-replays `unknown` outcomes (see [tool effects](tool-effects.md)).
|
|
240
242
|
|
|
241
243
|
## JSON Schema validator limits
|
|
242
244
|
|
|
@@ -265,6 +267,8 @@ createJsonSchemaToolArgumentValidator({
|
|
|
265
267
|
- [Observational memory compaction package](compaction-observational-memory.md): optional exact-id recall tool factory.
|
|
266
268
|
- [Tool execution primitives](tool-execution-primitives.md): JSON Schema adapter, parallelism, MCP bridge, and execution-policy designs.
|
|
267
269
|
- [MCP client bridge](mcp-tools.md): optional remote tool mapping plus separate bounded resource/prompt facades; non-tool MCP capabilities never bypass tool dispatch by masquerading as `ToolDefinition`.
|
|
270
|
+
- [Recoverable tool effects](tool-effects.md): optional `tool.effect` + `effectStore` claim/CAS recovery around dispatch.
|
|
271
|
+
- [Recoverable tool effects](tool-effects.md): optional `tool.effect` + `effectStore` claim/CAS recovery around dispatch.
|
|
268
272
|
- [Coding agent tools](coding-agent-tools.md): optional first-party `@arnilo/prism-coding-agent` `shell`/`read`/`write`/`edit` tools a host registers into this harness.
|
|
269
273
|
|
|
270
274
|
`DispatchToolCallOptions.trust` and `.permission` run before validation or `execute()`; denial emits `tool_execution_blocked`. Middleware cannot bypass either guard. `AgentConfig.validator`/`RunOptions.validate` run after these guards; their output is redacted through the active `SecretRedactor`. `createSecureAgent()` requires all three seams plus non-empty schemas and durable pre-tool approval. Prism does not sandbox tools. See [Security/auth/trust](settings-auth-trust-security.md).
|
package/docs/work-tools.md
CHANGED
|
@@ -89,7 +89,22 @@ Startup: M365 `version --output json`; GWS `--version`. Forbidden: `login`, `set
|
|
|
89
89
|
|
|
90
90
|
### Draft → approve → execute
|
|
91
91
|
|
|
92
|
-
Mutation tools (`*_mail_draft_send`, `*_draft_*`) create an in-adapter draft and return `{ status: "pending_approval", draftId }` until `approval.isApproved` is true.
|
|
92
|
+
Mutation tools (`*_mail_draft_send`, `*_draft_*`) create an in-adapter draft and return `{ status: "pending_approval", draftId }` until `approval.isApproved` is true.
|
|
93
|
+
|
|
94
|
+
### Durable idempotency (0.0.23)
|
|
95
|
+
|
|
96
|
+
`createMemoryIdempotencyStore()` remains for tests and a single process. For production replicas, use `createPostgresEnterpriseState({ pool }).workIdempotency`. It changes the old `get`/`put` replay abstraction to explicit async state transitions:
|
|
97
|
+
|
|
98
|
+
| Observable state | Meaning / host action |
|
|
99
|
+
| --- | --- |
|
|
100
|
+
| absent | `begin()` atomically acquires the first claim. |
|
|
101
|
+
| `in_progress` | Another worker owns the claim; do not dispatch a second connector effect. |
|
|
102
|
+
| `completed` | Return the bounded stored `{ draftId, resourceId? }` duplicate summary. |
|
|
103
|
+
| `failed_retryable` | A later `begin()` may reclaim it within the capped attempt policy. |
|
|
104
|
+
| `failed_terminal` | Do not retry; surface the bounded failure. |
|
|
105
|
+
| `unknown` | External result is ambiguous; reconcile with the connector/operator through `resolveUnknown()`. Never auto-replay. |
|
|
106
|
+
|
|
107
|
+
Call `begin({ identity, key, op })` **before** the external effect. After it succeeds, call `complete`, `fail`, or `markUnknown` with the returned claim token and version. The connector effect stays outside the database transaction, so this is claim-before-effect/deduplication—not exactly-once delivery. Claims default to 15 minutes (hard 60 minutes); expired claims transition to `unknown`; attempts default to 3 (hard 5). Stored rows contain no request body, token, raw provider response, or unrestricted payload.
|
|
93
108
|
|
|
94
109
|
## Limits
|
|
95
110
|
|
|
@@ -101,6 +116,10 @@ Mutation tools (`*_mail_draft_send`, `*_draft_*`) create an in-adapter draft and
|
|
|
101
116
|
| Process wall time | 60 s / 10 min |
|
|
102
117
|
| Concurrent CLI / identity | 2 / 8 |
|
|
103
118
|
|
|
119
|
+
## Tool effects
|
|
120
|
+
|
|
121
|
+
Approved mutations require core-derived `context.idempotencyKey` and a configured store (`effect: external_mutation/tool_managed`). Model-supplied idempotency keys are ignored. Ambiguous connector outcomes stay `unknown` — never auto-replayed (not exactly-once). See [tool effects](tool-effects.md).
|
|
122
|
+
|
|
104
123
|
## Security
|
|
105
124
|
|
|
106
125
|
- Require host-verified `AgentIdentity`; no cross-identity configDir reuse.
|
|
@@ -111,6 +130,7 @@ Mutation tools (`*_mail_draft_send`, `*_draft_*`) create an in-adapter draft and
|
|
|
111
130
|
|
|
112
131
|
## Related
|
|
113
132
|
|
|
133
|
+
- [Enterprise PostgreSQL state](enterprise-postgres-state.md): durable claim/CAS store, cleanup, and operator reconciliation.
|
|
114
134
|
- [Work connectors](work-connectors.md)
|
|
115
135
|
- [Agent identity](agent-identity.md)
|
|
116
136
|
- [Host security](host-security.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arnilo/prism",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.24",
|
|
4
4
|
"description": "Agent harness for AI providers, agents, sessions, and tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -30,6 +30,10 @@
|
|
|
30
30
|
"types": "./dist/testing/provider-conformance.d.ts",
|
|
31
31
|
"default": "./dist/testing/provider-conformance.js"
|
|
32
32
|
},
|
|
33
|
+
"./testing/agent-event-source-conformance": {
|
|
34
|
+
"types": "./dist/testing/agent-event-source-conformance.d.ts",
|
|
35
|
+
"default": "./dist/testing/agent-event-source-conformance.js"
|
|
36
|
+
},
|
|
33
37
|
"./testing/session-store-conformance": {
|
|
34
38
|
"types": "./dist/testing/session-store-conformance.d.ts",
|
|
35
39
|
"default": "./dist/testing/session-store-conformance.js"
|
|
@@ -42,6 +46,10 @@
|
|
|
42
46
|
"types": "./dist/testing/tool-conformance.d.ts",
|
|
43
47
|
"default": "./dist/testing/tool-conformance.js"
|
|
44
48
|
},
|
|
49
|
+
"./testing/tool-effect-store-conformance": {
|
|
50
|
+
"types": "./dist/testing/tool-effect-store-conformance.d.ts",
|
|
51
|
+
"default": "./dist/testing/tool-effect-store-conformance.js"
|
|
52
|
+
},
|
|
45
53
|
"./testing/extension-conformance": {
|
|
46
54
|
"types": "./dist/testing/extension-conformance.d.ts",
|
|
47
55
|
"default": "./dist/testing/extension-conformance.js"
|
|
@@ -123,6 +131,7 @@
|
|
|
123
131
|
"packages/work-tools",
|
|
124
132
|
"packages/policy",
|
|
125
133
|
"packages/model-router",
|
|
134
|
+
"packages/enterprise-postgres",
|
|
126
135
|
"packages/browser",
|
|
127
136
|
"packages/ag-ui",
|
|
128
137
|
"packages/prism-*"
|
|
@@ -138,7 +147,7 @@
|
|
|
138
147
|
"format": "biome format --write .",
|
|
139
148
|
"format:check": "biome format .",
|
|
140
149
|
"pack:dry-run": "npm pack --dry-run && npm run pack:dry-run --workspaces --if-present",
|
|
141
|
-
"test:postgres": "npm run test:postgres --workspace @arnilo/prism-session-store-postgres && npm run test:postgres --workspace @arnilo/prism-memory",
|
|
150
|
+
"test:postgres": "node scripts/require-postgres-url.mjs && npm run test:postgres --workspace @arnilo/prism-session-store-postgres && npm run test:postgres --workspace @arnilo/prism-memory && npm run test:postgres --workspace @arnilo/prism-enterprise-postgres && node --test scripts/phase7-conformance.test.mjs",
|
|
142
151
|
"release:dry-run": "npm run sdk:ready",
|
|
143
152
|
"release:check": "node scripts/release.mjs check",
|
|
144
153
|
"release:publish": "node scripts/release.mjs publish",
|