@arnilo/prism 0.0.3 → 0.0.4

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 (99) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +32 -20
  3. package/dist/agent-loops.d.ts +8 -1
  4. package/dist/agent-loops.js +57 -11
  5. package/dist/agents.js +70 -17
  6. package/dist/checkpoints.d.ts +11 -0
  7. package/dist/checkpoints.js +144 -0
  8. package/dist/compaction.js +9 -1
  9. package/dist/content.d.ts +102 -0
  10. package/dist/content.js +410 -0
  11. package/dist/contracts.d.ts +142 -2
  12. package/dist/event-multiplexer.d.ts +23 -0
  13. package/dist/event-multiplexer.js +136 -0
  14. package/dist/execution-policy.d.ts +28 -0
  15. package/dist/execution-policy.js +24 -0
  16. package/dist/index.d.ts +17 -5
  17. package/dist/index.js +11 -4
  18. package/dist/input.js +11 -1
  19. package/dist/leases.d.ts +8 -0
  20. package/dist/leases.js +111 -0
  21. package/dist/node/agent-definitions.js +3 -5
  22. package/dist/node/config.d.ts +1 -0
  23. package/dist/node/config.js +5 -3
  24. package/dist/node/contribution-discovery.js +5 -8
  25. package/dist/node/session-store-jsonl.js +8 -5
  26. package/dist/node/settings.js +2 -2
  27. package/dist/node/trust.js +2 -4
  28. package/dist/observability.d.ts +3 -0
  29. package/dist/observability.js +18 -0
  30. package/dist/providers/media.d.ts +42 -0
  31. package/dist/providers/media.js +116 -0
  32. package/dist/providers/openai-compatible.js +18 -119
  33. package/dist/providers/openai-primitives.d.ts +9 -0
  34. package/dist/providers/openai-primitives.js +129 -0
  35. package/dist/providers/transport.d.ts +40 -0
  36. package/dist/providers/transport.js +221 -0
  37. package/dist/redaction.js +40 -13
  38. package/dist/resources.d.ts +5 -0
  39. package/dist/resources.js +4 -0
  40. package/dist/structured-output.d.ts +11 -0
  41. package/dist/structured-output.js +59 -0
  42. package/dist/testing/persistence-schema.d.ts +102 -0
  43. package/dist/testing/persistence-schema.js +457 -0
  44. package/dist/testing/provider-conformance.js +10 -1
  45. package/dist/testing/run-ledger-conformance.d.ts +33 -0
  46. package/dist/testing/run-ledger-conformance.js +172 -0
  47. package/dist/testing/session-store-conformance.d.ts +16 -0
  48. package/dist/testing/session-store-conformance.js +73 -0
  49. package/dist/tools.d.ts +17 -0
  50. package/dist/tools.js +29 -2
  51. package/docs/agent-events.md +13 -4
  52. package/docs/agent-loops.md +10 -4
  53. package/docs/agent-session-runtime.md +1 -0
  54. package/docs/cli-rpc.md +3 -0
  55. package/docs/coding-agent-tools.md +41 -7
  56. package/docs/coding-security.md +84 -0
  57. package/docs/credential-storage.md +177 -0
  58. package/docs/credentials-and-redaction.md +2 -1
  59. package/docs/database-persistence.md +44 -2
  60. package/docs/host-security.md +15 -1
  61. package/docs/index.md +28 -12
  62. package/docs/input-and-prompt-assembly.md +6 -5
  63. package/docs/mcp-tools.md +139 -0
  64. package/docs/middleware-hooks.md +2 -0
  65. package/docs/migration.md +21 -28
  66. package/docs/model-registry.md +5 -3
  67. package/docs/multimodal-content.md +148 -0
  68. package/docs/observability.md +163 -0
  69. package/docs/performance.md +40 -1
  70. package/docs/persistence-credentials-multimodality-primitives.md +303 -0
  71. package/docs/postgres-persistence.md +141 -0
  72. package/docs/provider-conformance.md +17 -0
  73. package/docs/provider-layer.md +1 -1
  74. package/docs/provider-primitives.md +281 -0
  75. package/docs/providers/kimi.md +1 -0
  76. package/docs/providers/neuralwatt.md +1 -0
  77. package/docs/providers/openai-compatible.md +2 -1
  78. package/docs/providers/openai.md +8 -1
  79. package/docs/providers/opencode-go.md +1 -0
  80. package/docs/providers/openrouter.md +1 -0
  81. package/docs/providers/zai.md +1 -0
  82. package/docs/public-contracts.md +9 -2
  83. package/docs/release-and-install.md +209 -25
  84. package/docs/resource-loading.md +14 -4
  85. package/docs/review-coverage-2026-07-14.md +260 -0
  86. package/docs/run-ledger-conformance.md +96 -0
  87. package/docs/runs-and-usage.md +2 -0
  88. package/docs/session-store-conformance.md +16 -0
  89. package/docs/session-stores-and-branching.md +1 -0
  90. package/docs/settings-auth-trust-security.md +2 -1
  91. package/docs/sqlite-persistence.md +122 -0
  92. package/docs/structured-output.md +9 -0
  93. package/docs/tool-conformance.md +1 -0
  94. package/docs/tool-execution-primitives.md +374 -0
  95. package/docs/tools.md +39 -1
  96. package/docs/workflow-orchestration-primitives.md +565 -0
  97. package/docs/workflow-tui-primitives.md +5 -0
  98. package/docs/workflows.md +219 -0
  99. package/package.json +33 -5
@@ -0,0 +1,219 @@
1
+ # Workflows
2
+
3
+ ## What it does
4
+
5
+ `@arnilo/prism-workflows` is an optional package for typed, bounded DAG orchestration over Prism sessions, tools, events, and persistence seams. Hosts define acyclic workflows with agent/function/tool/conditional/fan-out/join nodes; the package runs a Kahn-style scheduler with a bounded worker pool, emits package-local `WorkflowEvent`s, checkpoints progress, and can coordinate queued runs across multiple host processes using durable leases and fencing.
6
+
7
+ Primary exports:
8
+
9
+ | Export | Purpose |
10
+ | --- | --- |
11
+ | `defineWorkflow` / `buildGraph` | Validate definitions (acyclicity, edge refs, limits) and build deterministic successor/indegree maps |
12
+ | `agentNode`, `functionNode`, `toolNode`, `conditionalNode`, `fanOutNode`, `joinNode` | Typed node factories |
13
+ | `runWorkflow` / `resumeWorkflow` | Execute or resume a run with concurrency, abort, redaction, and optional checkpoints |
14
+ | `createMemoryWorkflowCheckpoints` | In-process `WorkflowCheckpointAdapter` over core `createMemoryCheckpointStore()` |
15
+ | `createWorkflowCheckpoints` | Adapt core `CheckpointStore` (including SQLite/PostgreSQL persistence capabilities) to workflow checkpoint shapes |
16
+ | `createWorkflowEventBus` | Bounded pub/sub for `WorkflowEvent` with overflow policy |
17
+ | `getWorkflowRun` / `listWorkflowRuns` / `cancelWorkflowRun` | Status, paginated list, and cancel helpers |
18
+ | `createWorkflowCommands` | Optional `CommandDefinition[]` for `runRpcServer` (`workflow.start` / `status` / `list` / `cancel` / `resume`) |
19
+ | `enqueueWorkflow` / `createWorkflowCoordinator` | Persist queued work and atomically claim/renew/execute it across processes using `LeaseStore` |
20
+
21
+ Included through `@arnilo/prism-sdk` and `@arnilo/prism-all`; installing either profile does not start workflows. Interactive TUI is out of scope (C-012 deferred).
22
+
23
+ ## When to use it
24
+
25
+ Use this package when a host needs multi-node dependency scheduling, conditionals, bounded fan-out/join, retries/timeouts, workflow events, or checkpoint/resume — without putting graph vocabulary into core.
26
+
27
+ Use `createWorkflowCoordinator()` when multiple processes share SQLite/PostgreSQL persistence and must claim queued work exclusively. It is a database-backed coordinator, not a separate broker, DSL parser, provider abstraction, or terminal UI. Agent nodes call public `AgentSession.run()` only; tool nodes go through ordinary `ToolDefinition` dispatch and optional `ExecutionPolicy`.
28
+
29
+ ## Inputs / request
30
+
31
+ `defineWorkflow({ id, nodes, edges, limits? })`:
32
+
33
+ | Field | Notes |
34
+ | --- | --- |
35
+ | `id` | Stable workflow id (required) |
36
+ | `nodes` | Record of node definitions (`kind` + typed fields) |
37
+ | `edges` | `[from, to]` pairs; must be acyclic; unknown ids rejected |
38
+ | `limits.maxNodes` | Default 1000 |
39
+ | `limits.maxFanOut` | Default 64 |
40
+ | `limits.maxConcurrency` | Default 8 |
41
+ | `limits.maxNodeOutputBytes` | Default 4 MiB |
42
+ | `limits.maxCheckpointBytes` | Default 1 MiB |
43
+
44
+ `runWorkflow(workflow, input, options?)`:
45
+
46
+ | Option | Notes |
47
+ | --- | --- |
48
+ | `concurrency` | Worker pool size (capped by workflow/global limits) |
49
+ | `checkpoints` | `WorkflowCheckpointAdapter` for save/load/list |
50
+ | `agentFactory` | `(agentName) => AgentSession` for agent nodes |
51
+ | `tools` | Tool registry/lookup for tool nodes |
52
+ | `executionPolicy` | Optional `ExecutionPolicy`; tool actions include `workflowId`/`nodeId` metadata |
53
+ | `runLedger` | Optional `RunLedger` for agent-event bridging |
54
+ | `ownership` | Tenant/account/user scope copied into checkpoints |
55
+ | `redactor` / `secrets` | Redaction before checkpoint persistence and event emission |
56
+ | `signal` | Cancels the run and in-flight agent sessions |
57
+ | `onEvent` | Synchronous `WorkflowEvent` sink |
58
+ | `runId` | Caller-supplied id; otherwise generated (`wfr_…`) |
59
+
60
+ `resumeWorkflow(workflow, { runId }, options)` loads the checkpoint, validates schema/version/tenant/`definitionHash`, and continues pending/ready nodes only.
61
+
62
+ `createWorkflowCoordinator({ coordinatorId, workflows, checkpoints, leases, ... })` polls queued/running checkpoints with bounded pages, atomically claims each run, renews its lease, and aborts/fences work after lease loss. Key controls: `leaseTtlMs` (default 30s), `renewalIntervalMs` (default TTL/3), `pollIntervalMs` (default 1s), `maxConcurrentRuns` (default 4), and `pageSize` (default 100, maximum 500).
63
+
64
+ ## Outputs / response / events
65
+
66
+ `runWorkflow` / `resumeWorkflow` resolve to `WorkflowRunResult`:
67
+
68
+ | Field | Notes |
69
+ | --- | --- |
70
+ | `runId`, `workflowId`, `status` | `succeeded` / `failed` / `aborted` |
71
+ | `outputs` | Map of succeeded node outputs |
72
+ | `error` | First fail-fast error when status is `failed` |
73
+ | `version`, `definitionHash`, `createdAt`, `updatedAt` | Checkpoint identity |
74
+
75
+ Package-local `WorkflowEvent` types: `workflow_started`, `workflow_finished`, `node_started`, `node_finished`, `node_failed`, `node_skipped`, `checkpoint_saved`, `agent_event` (wraps a redacted `AgentEvent`), `workflow_event_overflow`. Sequences are monotonic; drain/order is deterministic by `(sequence, nodeId)`.
76
+
77
+ ## Request/response example
78
+
79
+ ```json
80
+ {
81
+ "id": "research-draft",
82
+ "nodes": ["research", "draft"],
83
+ "edges": [["research", "draft"]],
84
+ "limits": { "maxNodes": 256, "maxFanOut": 32, "maxConcurrency": 4 }
85
+ }
86
+ ```
87
+
88
+ Successful run shape:
89
+
90
+ ```json
91
+ {
92
+ "runId": "wfr_01HZX…",
93
+ "workflowId": "research-draft",
94
+ "status": "succeeded",
95
+ "outputs": { "research": "…", "draft": "…" },
96
+ "version": 3
97
+ }
98
+ ```
99
+
100
+ ## Implementation example
101
+
102
+ ```ts
103
+ import {
104
+ defineWorkflow,
105
+ runWorkflow,
106
+ resumeWorkflow,
107
+ functionNode,
108
+ agentNode,
109
+ createWorkflowCheckpoints,
110
+ createWorkflowCommands,
111
+ cancelWorkflowRun,
112
+ enqueueWorkflow,
113
+ createWorkflowCoordinator,
114
+ } from "@arnilo/prism-workflows";
115
+ import { runRpcServer } from "@arnilo/prism";
116
+ import { createSqlitePersistence } from "@arnilo/prism-session-store-sqlite";
117
+
118
+ const research = agentNode({
119
+ agent: "researcher",
120
+ input: (ctx) => ctx.workflowInput,
121
+ });
122
+ const draft = functionNode({
123
+ execute: async (ctx) => `Draft from ${String(ctx.upstream.research)}`,
124
+ });
125
+
126
+ const workflow = defineWorkflow({
127
+ id: "research-draft",
128
+ nodes: { research, draft },
129
+ edges: [["research", "draft"]],
130
+ limits: { maxNodes: 256, maxFanOut: 32, maxConcurrency: 4 },
131
+ });
132
+
133
+ const persistence = createSqlitePersistence({ filename: "prism.db" });
134
+ const checkpoints = createWorkflowCheckpoints({ store: persistence.checkpoints });
135
+
136
+ const queued = await enqueueWorkflow(workflow, { topic: "hooks" }, {
137
+ checkpoints,
138
+ ownership: { tenantId: "t1" },
139
+ });
140
+ const coordinator = createWorkflowCoordinator({
141
+ coordinatorId: process.env.HOSTNAME ?? "worker-1",
142
+ workflows: { [workflow.id]: workflow },
143
+ checkpoints,
144
+ leases: persistence.leases,
145
+ ownership: { tenantId: "t1" },
146
+ runOptions: { agentFactory: (name) => agents.resolve(name).createSession() },
147
+ maxConcurrentRuns: 4,
148
+ });
149
+ await coordinator.run({ signal: shutdownSignal });
150
+
151
+ // Direct single-process execution remains available:
152
+ const result = await runWorkflow(workflow, { topic: "hooks" }, {
153
+ agentFactory: (name) => agents.resolve(name).createSession(),
154
+ checkpoints,
155
+ ownership: { tenantId: "t1" },
156
+ signal: AbortSignal.timeout(60_000),
157
+ onEvent: (event) => sink.push(event),
158
+ });
159
+
160
+ // Durable resume after process restart (reopen persistence, then adapt its store):
161
+ await resumeWorkflow(workflow, { runId: result.runId }, {
162
+ checkpoints,
163
+ agentFactory: (name) => agents.resolve(name).createSession(),
164
+ ownership: { tenantId: "t1" },
165
+ });
166
+
167
+ await cancelWorkflowRun({
168
+ workflowId: workflow.id,
169
+ runId: result.runId,
170
+ checkpoints,
171
+ ownership: { tenantId: "t1" },
172
+ });
173
+
174
+ // Optional host control via existing CLI/RPC CommandDefinition seam:
175
+ runRpcServer({
176
+ createSession,
177
+ commands: createWorkflowCommands({
178
+ workflows: { [workflow.id]: workflow },
179
+ checkpoints,
180
+ runOptions: { ownership: { tenantId: "t1" }, agentFactory },
181
+ }),
182
+ });
183
+ ```
184
+
185
+ ## Extension and configuration notes
186
+
187
+ - Workflow semantics stay in this optional package; generic checkpoint persistence and bounded event fan-in live in core.
188
+ - `ProductionPersistenceStore.checkpoints` and `.leases` are optional generic capabilities. First-party SQLite/PostgreSQL adapters own `prism_checkpoints` / `prism_leases`; workflows only adapt them.
189
+ - `createWorkflowEventBus()` delegates queueing, source fan-in, overflow, abort, and close behavior to core `createEventMultiplexer()`.
190
+ - `createWorkflowCommands()` is optional; hosts that already use `runRpcServer({ commands })` can drive start/status/list/cancel/resume without a TUI.
191
+ - Hosts may bridge `WorkflowEvent` into OpenTelemetry or custom sinks; there is no built-in TUI.
192
+ - Agent exclusivity is per session: one active `run()` at a time, same as core.
193
+
194
+ ## Security and performance notes
195
+
196
+ - Definitions fail closed on cycles, unknown edges, self-edges, and `maxNodes` overflow.
197
+ - Fan-out length is bounded by `maxFanOut`; concurrency by `maxConcurrency`.
198
+ - Node outputs and checkpoints are byte-bounded (`maxNodeOutputBytes`, `maxCheckpointBytes`).
199
+ - Event buses use a bounded buffer (default 2048) with `close` / `drop_oldest` / `drop_newest` overflow.
200
+ - Checkpoints redact via `SecretRedactor` / `secrets` before save; resume rejects tenant, schema, and definition-hash mismatch.
201
+ - `cancelWorkflowRun` aborts local runs immediately and writes a durable cancellation request for a remotely leased run; workers check it during lease renewal.
202
+ - Tool nodes attach `workflowId` / `nodeId` on `ExecutionAction.metadata` for approval/audit context.
203
+ - Scheduler stores O(nodes + active outputs); ready-node work uses indegree maps, not repeated full scans.
204
+ - Lease acquisition is atomic; opaque tokens protect renew/release; monotonically increasing fencing tokens plus checkpoint compare-and-swap prevent expired workers from committing after takeover. Node functions must honor `ctx.signal` for prompt cooperative cancellation.
205
+
206
+ ## Related APIs
207
+
208
+ - Examples: `examples/workflow-research-and-review.ts`, `examples/workflow-parallel-research.ts`, `examples/workflow-tool-approval.ts`, `examples/workflow-multimodal-document.ts`, `examples/workflow-sqlite-resume.ts`, `examples/workflow-postgres-resume.ts`, `examples/workflow-event-sink.ts`, `examples/workflow-rpc-cancel.ts`, `examples/workflow-distributed-coordinator.ts` — offline runnable demos; PostgreSQL safely skips unless `PRISM_TEST_POSTGRES_URL` is set.
209
+ - [Workflow orchestration primitives](workflow-orchestration-primitives.md): Task 0–1 inventory and locked adapter contracts
210
+ - [Agent/session runtime](agent-session-runtime.md): `AgentSession.run()`, abort, subscribe
211
+ - [Agent events](agent-events.md): core `AgentEvent` wrapped by `agent_event`
212
+ - [Session stores and branching](session-stores-and-branching.md): session `leafId` reuse on resume
213
+ - [CLI/RPC](cli-rpc.md): host control seam; wire `createWorkflowCommands()` into `runRpcServer`
214
+ - [Database persistence](database-persistence.md): generic `CheckpointStore` and `LeaseStore` capabilities
215
+ - [SQLite persistence](sqlite-persistence.md): durable `persistence.checkpoints`
216
+ - [PostgreSQL persistence](postgres-persistence.md): durable `persistence.checkpoints`
217
+ - [Observability](observability.md): exporting workflow/agent events
218
+ - [Coding execution approval and sandboxing](coding-security.md): `ExecutionPolicy` for tool nodes
219
+ - [Release and install](release-and-install.md): atomic and profile installs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arnilo/prism",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "Agent harness for AI providers, agents, sessions, and tools.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -14,6 +14,18 @@
14
14
  "types": "./dist/providers/openai-compatible.d.ts",
15
15
  "default": "./dist/providers/openai-compatible.js"
16
16
  },
17
+ "./providers/transport": {
18
+ "types": "./dist/providers/transport.d.ts",
19
+ "default": "./dist/providers/transport.js"
20
+ },
21
+ "./providers/openai": {
22
+ "types": "./dist/providers/openai-primitives.d.ts",
23
+ "default": "./dist/providers/openai-primitives.js"
24
+ },
25
+ "./providers/media": {
26
+ "types": "./dist/providers/media.d.ts",
27
+ "default": "./dist/providers/media.js"
28
+ },
17
29
  "./testing/provider-conformance": {
18
30
  "types": "./dist/testing/provider-conformance.d.ts",
19
31
  "default": "./dist/testing/provider-conformance.js"
@@ -34,6 +46,14 @@
34
46
  "types": "./dist/testing/extension-conformance.d.ts",
35
47
  "default": "./dist/testing/extension-conformance.js"
36
48
  },
49
+ "./testing/persistence-schema": {
50
+ "types": "./dist/testing/persistence-schema.d.ts",
51
+ "default": "./dist/testing/persistence-schema.js"
52
+ },
53
+ "./testing/run-ledger-conformance": {
54
+ "types": "./dist/testing/run-ledger-conformance.d.ts",
55
+ "default": "./dist/testing/run-ledger-conformance.js"
56
+ },
37
57
  "./node/config": {
38
58
  "types": "./dist/node/config.d.ts",
39
59
  "default": "./dist/node/config.js"
@@ -80,18 +100,26 @@
80
100
  "workspaces": [
81
101
  "packages/provider-*",
82
102
  "packages/compaction-*",
103
+ "packages/observability-*",
104
+ "packages/tool-validator-*",
105
+ "packages/session-store-*",
106
+ "packages/credentials-node",
107
+ "packages/mcp",
83
108
  "packages/coding-agent",
84
- "packages/prism-providers",
85
- "packages/prism-compaction",
86
- "packages/prism-all"
109
+ "packages/coding-security",
110
+ "packages/workflows",
111
+ "packages/prism-*"
87
112
  ],
88
113
  "scripts": {
89
114
  "build:core": "tsc",
90
115
  "build": "npm run build:core && npm run build --workspaces --if-present",
91
- "typecheck": "npm run build:core && npm run typecheck --workspaces --if-present && tsc -p examples --noEmit",
116
+ "typecheck": "npm run build && npm run typecheck --workspaces --if-present && tsc -p examples --noEmit",
92
117
  "test": "npm run build && node --test dist/__tests__/*.test.js && npm run test --workspaces --if-present",
93
118
  "pack:dry-run": "npm pack --dry-run && npm run pack:dry-run --workspaces --if-present",
119
+ "test:postgres": "npm run test:postgres --workspace @arnilo/prism-session-store-postgres",
94
120
  "release:dry-run": "npm run sdk:ready",
121
+ "release:check": "node scripts/release.mjs check",
122
+ "release:publish": "node scripts/release.mjs publish",
95
123
  "sdk:ready": "npm run typecheck && npm test && npm run pack:dry-run"
96
124
  },
97
125
  "devDependencies": {