@arnilo/prism 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/README.md +3 -1
  3. package/dist/agent-loops.js +45 -8
  4. package/dist/agent-session/helpers.js +2 -2
  5. package/dist/cache-helpers.d.ts +11 -0
  6. package/dist/cache-helpers.js +29 -5
  7. package/dist/cli-provider-add.js +2 -1
  8. package/dist/context-budget.js +9 -6
  9. package/dist/contracts-core/agent.d.ts +2 -0
  10. package/dist/contracts-core/provider.d.ts +2 -0
  11. package/dist/event-multiplexer.js +0 -4
  12. package/dist/index.d.ts +6 -4
  13. package/dist/index.js +5 -3
  14. package/dist/input.js +19 -11
  15. package/dist/node/session-store-jsonl.js +7 -3
  16. package/dist/providers/openai-compatible.js +2 -1
  17. package/dist/providers/openai-primitives.js +2 -1
  18. package/dist/providers/schema.d.ts +7 -0
  19. package/dist/providers/schema.js +25 -0
  20. package/dist/testing/provider-conformance.d.ts +10 -0
  21. package/dist/testing/provider-conformance.js +37 -0
  22. package/dist/trim-trailing-slashes.d.ts +8 -0
  23. package/dist/trim-trailing-slashes.js +14 -0
  24. package/docs/0.1.0-readiness.md +1 -1
  25. package/docs/acp.md +1 -0
  26. package/docs/ag-ui.md +1 -0
  27. package/docs/agent-loops.md +3 -0
  28. package/docs/agent-session-runtime.md +1 -0
  29. package/docs/browser-automation.md +1 -0
  30. package/docs/database-persistence.md +1 -1
  31. package/docs/graft.md +125 -0
  32. package/docs/host-security.md +3 -1
  33. package/docs/index.md +11 -9
  34. package/docs/input-and-prompt-assembly.md +11 -6
  35. package/docs/instruction-injection.md +1 -1
  36. package/docs/mcp-tools.md +1 -0
  37. package/docs/migration.md +10 -0
  38. package/docs/node-jsonl-session-store.md +1 -1
  39. package/docs/obscura.md +175 -0
  40. package/docs/observability.md +21 -1
  41. package/docs/performance.md +58 -4
  42. package/docs/ponytail.md +1 -1
  43. package/docs/provider-caching.md +13 -11
  44. package/docs/provider-conformance.md +6 -0
  45. package/docs/provider-packages.md +1 -1
  46. package/docs/provider-primitives.md +15 -2
  47. package/docs/providers/ai-sdk.md +1 -1
  48. package/docs/providers/anthropic.md +1 -1
  49. package/docs/providers/azure.md +1 -0
  50. package/docs/providers/bedrock.md +1 -0
  51. package/docs/providers/kimi.md +2 -1
  52. package/docs/providers/openai.md +19 -7
  53. package/docs/providers/opencode-go.md +3 -1
  54. package/docs/providers/openrouter.md +4 -3
  55. package/docs/providers/vertex.md +1 -0
  56. package/docs/public-contracts.md +2 -1
  57. package/docs/rag.md +55 -8
  58. package/docs/release-and-install.md +45 -7
  59. package/docs/server.md +1 -0
  60. package/docs/supervisors.md +3 -2
  61. package/docs/system-prompts.md +1 -1
  62. package/docs/tools.md +1 -1
  63. package/docs/web-tools.md +2 -0
  64. package/docs/wiki.md +140 -0
  65. package/docs/workflows.md +4 -3
  66. package/docs/working-and-semantic-memory.md +20 -0
  67. package/package.json +12 -5
  68. package/docs/api-page-template.md +0 -32
  69. package/docs/release-0.2.7-evidence.md +0 -514
package/docs/workflows.md CHANGED
@@ -78,7 +78,7 @@ A function node returns `suspend({ reason, data?, resumeSchema? })` to persist `
78
78
 
79
79
  Coding-agent ask-user glue (opt-in, no Goal DB): `suspendAskUserDecision(request)` wraps `suspend` with durable question/options/`selectionMode`/`allowCustom` data + resume schema; resume with `createAskUserDecisionResumeValidator()` or `validateAskUserDecisionResume`. Goal→verify: `runCodingGoalVerify` / `createCodingGoalVerifyWorkflow` compose plan Markdown → named checks → approve suspend → bounded handoff over the same primitives (`examples/coding-goal-verify.ts`). When a workflow node wraps a durable agent run, that run's shared pending-decision batch (Task 2) is the approval authority — workflow `suspend`/`resume` stay workflow-scoped and do not mint a parallel decision store.
80
80
 
81
- Every node receives bounded `ctx.state`, `ctx.stateVersion`, and async `ctx.updateState(patch, { mode: "merge" | "replace" })`. Updates serialize, validate, redact, and snapshot before checkpoint save. `workflowNode({ workflow })` runs its child with the same ownership, agent/tool registries, execution policy, redactor, signal, checkpoints, and event bus; child state replaces parent state after success.
81
+ Every node receives bounded `ctx.state`, `ctx.stateVersion`, and async `ctx.updateState(patch, { mode: "merge" | "replace" })`. Updates serialize, validate, redact, and snapshot before checkpoint save. A rejected state or checkpoint write stays rejected (nothing committed) and recovers the per-run chain so a later valid write can run. `workflowNode({ workflow })` runs its child with the same ownership, agent/tool registries, execution policy, redactor, signal, checkpoints, and event bus; child state replaces parent state after success.
82
82
 
83
83
  `replayWorkflow(workflow, { sourceRunId, fromNodeId, runId? }, options)` requires a succeeded source/node, creates a new checkpoint, copies terminal evidence outside the selected node's downstream closure, restores selected-node pre-state, and records `{ sourceRunId, fromNodeId, rootRunId, depth }`. Source evidence is untouched. Copying any prior nested/tool approval is rejected; replay from that approval node or earlier so Phase 8 approval executes again.
84
84
 
@@ -304,7 +304,7 @@ runRpcServer({
304
304
 
305
305
  - Workflow semantics stay in this optional package; generic checkpoint persistence and bounded event fan-in live in core.
306
306
  - `ProductionPersistenceStore.checkpoints` and `.leases` are optional generic capabilities. First-party SQLite/PostgreSQL adapters own `prism_checkpoints` / `prism_leases`; workflows only adapt them. Sagas use the same `WorkflowCheckpointAdapter` and `LeaseStore`; they add no SQL table or scheduler.
307
- - `createWorkflowEventBus()` delegates queueing, source fan-in, overflow, abort, and close behavior to core `createEventMultiplexer()`, including its single-consumer contract: a second concurrent `subscribe()` is rejected with `EventMultiplexerError` (`ERR_PRISM_EVENT_MULTIPLEXER_SINGLE_CONSUMER`) instead of silently splitting the stream.
307
+ - `createWorkflowEventBus()` delegates queueing, source fan-in, overflow, abort, and close behavior to core `createEventMultiplexer()`, including its single-consumer contract: a second concurrent `subscribe()` is rejected with `EventMultiplexerError` (`ERR_PRISM_EVENT_MULTIPLEXER_SINGLE_CONSUMER`) instead of silently splitting the stream. Graceful `close()` stops new emits/sources and drains already-queued events (in `(sequence, nodeId)` order) before the subscriber completes; overflow `close` still emits one `workflow_event_overflow` notice and terminates.
308
308
  - The in-process active-run registry (`registerActiveWorkflowRun` / `getActiveWorkflowRun` / `abortActiveWorkflowRun`) is **non-durable, in-process only — it does not survive restart**; durable active-run recovery is a later milestone. It is bounded: every register sweeps aborted/leaked entries (runs whose promise never settled) and the registry fails closed at `MAX_ACTIVE_WORKFLOW_RUNS` (512) rather than evicting a live run; `sweepActiveWorkflowRuns()` is available for hosts. Cross-tenant lookups stay ownership-isolated.
309
309
  - `createWorkflowCommands()` is optional; hosts can drive `workflow.start` / `enqueue` / `replay` / `status` / `list` / `cancel` / `resume`. The six `schedule.*` commands appear only when a scoped `schedules` service is supplied.
310
310
  - Hosts may bridge `WorkflowEvent` into OpenTelemetry or custom sinks; there is no built-in TUI.
@@ -314,7 +314,7 @@ runRpcServer({
314
314
  ## Security and performance notes
315
315
 
316
316
  - Definitions require a non-empty host-authored `revision` and fail closed on cycles, unknown edges, self-edges, invalid limits, and `maxNodes` overflow. Revision and every nested revision enter the deterministic definition hash; hosts must bump revision when function/tool behavior changes.
317
- - Fan-out length is bounded by `maxFanOut`; concurrency by `maxConcurrency`; every count/byte/runtime option has a finite hard cap.
317
+ - Fan-out length is bounded by `maxFanOut`. Independent `map` items run in a local worker pool capped by the resolved workflow `maxConcurrency` (and `options.concurrency`); output stays in input order. Abort or the first map failure stops further items. There is no extra global admission service.
318
318
  - Node outputs, shared state/history, schedule input/records, and checkpoints are byte/count/depth bounded. Checkpoint size remains the final aggregate ceiling.
319
319
  - Event buses use a bounded buffer (default 2048) with `close` / `drop_oldest` / `drop_newest` overflow.
320
320
  - Checkpoints redact suspension/resume payloads via `SecretRedactor` / `secrets` before save; resume rejects tenant, schema, definition-hash, and expected-version mismatch.
@@ -342,6 +342,7 @@ Use workflows for known, durable, replayable graphs. Use optional supervisor del
342
342
  - [Agent/session runtime](agent-session-runtime.md): `AgentSession.run()`/`stream()`, abort, subscribe
343
343
  - [Guardrails](guardrails.md): `RunWorkflowOptions.guardrails` routes tool nodes through core dispatch before policy and side effects.
344
344
  - [Supervisor delegation](supervisors.md): bounded dynamic child selection.
345
+ - [Obscura browser engine](obscura.md): optional binary-backed generic tools for `toolNode`/`agentNode` composition.
345
346
  - [A2A interoperability](a2a.md): hosts may adapt existing exact-owner workflow status/list/cancel/checkpoint/event surfaces to `A2ATaskLifecycle`; A2A package adds no workflow worker, queue, or schema.
346
347
  - [Agent events](agent-events.md): core `AgentEvent` wrapped by `agent_event`
347
348
  - [Session stores and branching](session-stores-and-branching.md): session `leafId` reuse on resume
@@ -155,6 +155,24 @@ const memory = createMemory({
155
155
  });
156
156
  ```
157
157
 
158
+ Standalone durable vector store for RAG:
159
+
160
+ ```ts
161
+ import { createPostgresVectorStore, createHashEmbedder } from "@arnilo/prism-memory";
162
+
163
+ const store = await createPostgresVectorStore({
164
+ connectionString: process.env.DATABASE_URL!,
165
+ schema: "prism_memory", // default
166
+ table: "semantic_memory", // default
167
+ dimension: 32, // optional; pins the embedding column width (HNSW + drift guard)
168
+ }); // PostgresVectorStoreOptions; dimension must match the embedder's dimensions
169
+ // store implements rag's VectorStore/TransactionalVectorStore contract: upsert,
170
+ // query, getBySource, transaction, lexicalQuery (fts, when available), and
171
+ // getCurrentGeneration/setCurrentGeneration. close() ends adapter-owned pools.
172
+ ```
173
+
174
+ `createPostgresVectorStore()` is the production counterpart to `createMemoryVectorStore()` used by `@arnilo/prism-rag`; `createPostgresMemoryStores()` reuses the same vector implementation internally.
175
+
158
176
  ## Extension and configuration notes
159
177
 
160
178
  - Hosts wire the context provider into `AgentConfig.context` or `resolveContextProviders()`.
@@ -162,6 +180,8 @@ const memory = createMemory({
162
180
  - `createHashEmbedder()` is for tests/demos only; production hosts supply a real `Embedder`.
163
181
  - Observational memory (`@arnilo/prism-compaction-observational-memory`) remains unchanged and composable.
164
182
  - Consent is enforced at the single `recall()` gate, so both direct recall and `createContextProvider()` injection honor it; `visible: false` (or a revoked grant) keeps an entry out of prompts, events, exports, and telemetry. `setConsent`/`correct` re-upsert in place (consent change does not re-embed); `forget`/`applyRetention` are real deletes, not tombstones. Retention uses indexed oldest-first pages plus a scoped count, deleting one default-500/hard-5000 batch without reading a corpus into memory. The PostgreSQL adapter persists consent in a `consent JSONB` column added by `buildMemoryDdl`.
183
+ - The PostgreSQL vector path owns its DDL in Prism (`buildMemoryDdl`/`buildVectorSearchDdl` exported): the `<table>_rag_scope_generations` per-scope generation pointer table, `text_tsv` tsvector column + GIN index for the lexical RAG leg, and an HNSW index when the embedding dimension is pinned. DDL runs against the host's **knowledge database** — the host names `schema`/`table` (defaults `prism_memory`/`semantic_memory`), owns backup/retention of that database, and can run migrations manually with `skipMigrations: true`. Identifiers are validated/quoted; values stay parameterized.
184
+ - `createPostgresVectorStore({ dimension })` pins the embedding column width before building indexes: pgvector can only build HNSW over `vector(N)` columns, and dimension mismatch fails closed instead of drifting.
165
185
  - `exportMemory()` requires an exact `{ tenantId, resourceId, threadId }` identity equal to its `createMemory()` scope. It excludes legacy consent-less, invisible, and revoked records even when normal recall allows legacy entries. It returns a stable sequence cursor page, redacted before response, with defaults/hard caps of 100/200 entries, 4/32 MiB, and 10/60 seconds. `rebuildIndex()` uses the same stable cursor shape to re-embed one 32/128-record page under a 10/60-second cap; save the cursor durably to resume. Both APIs require a store implementing bounded `listByThread()`; retention also requires `countByThread()`. PostgreSQL/pgvector and the in-memory reference adapter conform; SQLite persistence stores sessions, not semantic vectors.
166
186
  - Profile bundles do not include this package yet.
167
187
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arnilo/prism",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Agent harness for AI providers, agents, sessions, and tools.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -22,6 +22,10 @@
22
22
  "types": "./dist/providers/openai-primitives.d.ts",
23
23
  "default": "./dist/providers/openai-primitives.js"
24
24
  },
25
+ "./providers/schema": {
26
+ "types": "./dist/providers/schema.d.ts",
27
+ "default": "./dist/providers/schema.js"
28
+ },
25
29
  "./providers/media": {
26
30
  "types": "./dist/providers/media.d.ts",
27
31
  "default": "./dist/providers/media.js"
@@ -112,11 +116,15 @@
112
116
  "!dist/**/*.map",
113
117
  "docs",
114
118
  "!docs/_evidence",
119
+ "!docs/release-*-evidence.md",
120
+ "!docs/api-page-template.md",
115
121
  "templates",
116
122
  "CHANGELOG.md"
117
123
  ],
118
124
  "workspaces": [
119
125
  "packages/provider-*",
126
+ "packages/memory",
127
+ "packages/rag",
120
128
  "packages/compaction-*",
121
129
  "packages/observability-*",
122
130
  "packages/tool-validator-*",
@@ -127,8 +135,6 @@
127
135
  "packages/workflows",
128
136
  "packages/coding-agent",
129
137
  "packages/coding-security",
130
- "packages/memory",
131
- "packages/rag",
132
138
  "packages/server",
133
139
  "packages/supervisor",
134
140
  "packages/web-tools",
@@ -137,6 +143,7 @@
137
143
  "packages/model-router",
138
144
  "packages/enterprise-postgres",
139
145
  "packages/browser",
146
+ "packages/obscura",
140
147
  "packages/ag-ui",
141
148
  "packages/acp-agent",
142
149
  "packages/computer-use-linux",
@@ -150,7 +157,7 @@
150
157
  "build": "npm run build:core && npm run build --workspaces --if-present",
151
158
  "typecheck": "npm run build && npm run typecheck --workspaces --if-present && tsc -p examples --noEmit",
152
159
  "sweep:unused": "node scripts/sweep-unused.mjs --json",
153
- "test": "npm run build && node scripts/with-build-lock.mjs node --test dist/__tests__/*.test.js && node scripts/with-build-lock.mjs node --test scripts/release-gate.test.mjs scripts/tooling-gate.test.mjs scripts/budget-gate.test.mjs scripts/phase8-conformance.test.mjs scripts/phase9-conformance.test.mjs scripts/phase10-conformance.test.mjs scripts/phase11-conformance.test.mjs scripts/phase11-freeze.test.mjs scripts/phase12-freeze.test.mjs scripts/phase13-freeze.test.mjs scripts/phase14-freeze.test.mjs scripts/phase15-freeze.test.mjs scripts/phase16-freeze.test.mjs scripts/phase17-freeze.test.mjs scripts/phase18-freeze.test.mjs scripts/phase19-freeze.test.mjs scripts/phase20-freeze.test.mjs scripts/phase21-freeze.test.mjs scripts/benchmark-0.1.0.test.mjs scripts/sweep-unused.test.mjs scripts/e2e-enterprise-journey.test.mjs scripts/e2e-coding-journey.test.mjs scripts/phase23-quality-gates.test.mjs scripts/phase24-truth.test.mjs scripts/phase25-bounded-accumulation.test.mjs scripts/phase26-freeze.test.mjs scripts/phase27-freeze.test.mjs scripts/phase27-ha.test.mjs scripts/phase27-erp-journey.test.mjs scripts/phase27-release.test.mjs scripts/phase29-freeze.test.mjs scripts/phase30-freeze.test.mjs scripts/phase30-release.test.mjs scripts/phase26-index-benchmark.test.mjs && node --test scripts/phase23-build-race.test.mjs && npm run test --workspaces --if-present",
160
+ "test": "npm run build && node scripts/with-build-lock.mjs node --test dist/__tests__/*.test.js && node scripts/with-build-lock.mjs node --test scripts/release-gate.test.mjs scripts/tooling-gate.test.mjs scripts/budget-gate.test.mjs scripts/phase8-conformance.test.mjs scripts/phase9-conformance.test.mjs scripts/phase10-conformance.test.mjs scripts/phase11-conformance.test.mjs scripts/phase11-freeze.test.mjs scripts/phase12-freeze.test.mjs scripts/phase13-freeze.test.mjs scripts/phase14-freeze.test.mjs scripts/phase15-freeze.test.mjs scripts/phase16-freeze.test.mjs scripts/phase17-freeze.test.mjs scripts/phase18-freeze.test.mjs scripts/phase19-freeze.test.mjs scripts/phase20-freeze.test.mjs scripts/phase21-freeze.test.mjs scripts/benchmark-0.1.0.test.mjs scripts/benchmark-multi-agent.test.mjs scripts/sweep-unused.test.mjs scripts/e2e-enterprise-journey.test.mjs scripts/e2e-coding-journey.test.mjs scripts/phase23-quality-gates.test.mjs scripts/phase24-truth.test.mjs scripts/phase25-bounded-accumulation.test.mjs scripts/phase26-freeze.test.mjs scripts/phase27-freeze.test.mjs scripts/phase27-ha.test.mjs scripts/phase27-erp-journey.test.mjs scripts/phase27-release.test.mjs scripts/phase29-freeze.test.mjs scripts/phase30-freeze.test.mjs scripts/phase30-release.test.mjs scripts/phase34-freeze.test.mjs scripts/phase37-provider-matrix.test.mjs scripts/phase26-index-benchmark.test.mjs scripts/obscura-host-conformance.test.mjs && node --test scripts/phase23-build-race.test.mjs && npm run test --workspaces --if-present",
154
161
  "test:coverage": "node scripts/with-build-lock.mjs node --test --experimental-test-coverage --test-coverage-lines=60 --test-coverage-functions=70 --test-coverage-branches=75 --test-coverage-exclude='**/__tests__/**' --test-coverage-exclude='**/node_modules/**' --test-coverage-exclude='**/scripts/**' --test-coverage-exclude='**/packages/**' --test-coverage-exclude='**/examples/**' dist/__tests__/*.test.js && node scripts/with-build-lock.mjs node scripts/coverage-summary.mjs && node --test scripts/phase23-coverage.test.mjs && node --test scripts/phase23-skip-manifest.test.mjs",
155
162
  "coverage:summary": "node scripts/with-build-lock.mjs node scripts/coverage-summary.mjs",
156
163
  "lint": "biome lint . --reporter=sarif --reporter-file=scripts/lint-report.sarif",
@@ -164,7 +171,7 @@
164
171
  "release:evidence": "node scripts/release-skip-manifest.mjs",
165
172
  "sdk:ready": "npm run typecheck && npm run lint && npm run format:check && npm test && npm run test:coverage && npm run pack:dry-run && npm run release:gate",
166
173
  "release:gate": "node scripts/release-skip-manifest.mjs && node scripts/check-client-neutrality.mjs && node scripts/release.mjs gate",
167
- "security:threat-suites": "node --test scripts/phase8-conformance.test.mjs scripts/phase9-conformance.test.mjs scripts/phase10-conformance.test.mjs scripts/phase11-conformance.test.mjs scripts/phase20-security.test.mjs scripts/phase21-security.test.mjs scripts/phase22-security.test.mjs scripts/phase23-security.test.mjs"
174
+ "security:threat-suites": "node --test scripts/phase8-conformance.test.mjs scripts/phase9-conformance.test.mjs scripts/phase10-conformance.test.mjs scripts/phase11-conformance.test.mjs scripts/phase20-security.test.mjs scripts/phase21-security.test.mjs scripts/phase22-security.test.mjs scripts/phase23-security.test.mjs scripts/phase38-codeql-regression.test.mjs"
168
175
  },
169
176
  "devDependencies": {
170
177
  "@biomejs/biome": "^2.5.5",
@@ -1,32 +0,0 @@
1
- # <API name>
2
-
3
- ## What it does
4
- <Small description of what the API does.>
5
-
6
- ## When to use it
7
- <When an app/package/extension should use this API.>
8
-
9
- ## Inputs / request
10
- <Field table or typed shape.>
11
-
12
- ## Outputs / response / events
13
- <Field table, return type, events, or side effects.>
14
-
15
- ## Request/response example
16
- ```json
17
- <minimal example payload or config>
18
- ```
19
-
20
- ## Implementation example
21
- ```ts
22
- <minimal working TypeScript example>
23
- ```
24
-
25
- ## Extension and configuration notes
26
- <How extensions/plugins/config can replace or contribute behavior.>
27
-
28
- ## Security and performance notes
29
- <Secrets, permissions, trust boundaries, resource use, latency, limits.>
30
-
31
- ## Related APIs
32
- - `<API or page>`: <relationship>