@arnilo/prism 0.3.1 → 0.4.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 +58 -0
- package/README.md +34 -57
- package/dist/agent-definitions.js +4 -1
- package/dist/agent-run-lifecycle.js +4 -0
- package/dist/agent-run-state.d.ts +4 -0
- package/dist/agent-run-state.js +18 -5
- package/dist/agent-session/session.d.ts +7 -0
- package/dist/agent-session/session.js +59 -2
- package/dist/cli-dev.d.ts +29 -0
- package/dist/cli-dev.js +52 -0
- package/dist/cli-init.d.ts +17 -2
- package/dist/cli-init.js +194 -21
- package/dist/cli-runner.d.ts +5 -1
- package/dist/cli-runner.js +12 -1
- package/dist/contracts-core/agent.d.ts +29 -2
- package/dist/contracts-protocol.d.ts +18 -0
- package/dist/contracts-run-state.d.ts +1 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/dist/input.d.ts +8 -0
- package/dist/input.js +4 -0
- package/dist/rpc.d.ts +4 -1
- package/dist/rpc.js +5 -1
- package/dist/testing/persistence-schema.d.ts +1 -1
- package/dist/testing/persistence-schema.js +32 -28
- package/dist/testing/tool-conformance.d.ts +25 -0
- package/dist/testing/tool-conformance.js +128 -1
- package/dist/tool-search.d.ts +76 -0
- package/dist/tool-search.js +199 -0
- package/docs/0.1.0-readiness.md +2 -2
- package/docs/acp-agent.md +1 -1
- package/docs/agent-definitions.md +1 -1
- package/docs/antigravity-agent.md +1 -1
- package/docs/browser-automation.md +5 -5
- package/docs/caveman.md +2 -2
- package/docs/cli-rpc.md +26 -3
- package/docs/coding-agent-tools.md +7 -1
- package/docs/coding-security.md +1 -1
- package/docs/coding-tools.md +82 -0
- package/docs/compaction-and-retry.md +5 -2
- package/docs/compaction-llm.md +4 -4
- package/docs/compaction-observational-memory.md +49 -2
- package/docs/context-and-skills.md +2 -0
- package/docs/core.md +85 -0
- package/docs/credential-storage.md +1 -1
- package/docs/database-persistence.md +4 -0
- package/docs/dev-inspector.md +103 -0
- package/docs/diagrams.md +247 -0
- package/docs/documents.md +213 -0
- package/docs/evaluations.md +35 -1
- package/docs/extension-authoring.md +42 -0
- package/docs/graft.md +3 -3
- package/docs/guardrails.md +1 -1
- package/docs/host-security.md +4 -3
- package/docs/impeccable.md +2 -2
- package/docs/index.md +34 -23
- package/docs/mcp-tools.md +1 -1
- package/docs/migrate-to-0.4.md +312 -0
- package/docs/migration.md +22 -0
- package/docs/model-routing.md +1 -1
- package/docs/multi-agent-patterns.md +177 -0
- package/docs/multimodal-content.md +1 -1
- package/docs/obscura.md +10 -10
- package/docs/openapi-tools.md +1 -1
- package/docs/performance.md +23 -3
- package/docs/persistence-credentials-multimodality-primitives.md +1 -1
- package/docs/policy-and-audit.md +1 -1
- package/docs/ponytail.md +2 -2
- package/docs/prompt-registry.md +106 -0
- package/docs/provider-caching.md +32 -32
- package/docs/provider-conformance.md +1 -1
- package/docs/provider-packages.md +19 -19
- package/docs/provider-primitives.md +4 -4
- package/docs/providers/ai-sdk.md +3 -3
- package/docs/providers/alibaba.md +5 -5
- package/docs/providers/anthropic.md +6 -6
- package/docs/providers/azure.md +3 -3
- package/docs/providers/bedrock.md +3 -3
- package/docs/providers/clinepass.md +3 -3
- package/docs/providers/deepseek.md +3 -3
- package/docs/providers/google.md +4 -4
- package/docs/providers/kimi.md +3 -3
- package/docs/providers/neuralwatt.md +8 -8
- package/docs/providers/ollama.md +3 -3
- package/docs/providers/openai-compatible.md +1 -1
- package/docs/providers/openai.md +5 -5
- package/docs/providers/opencode-go.md +4 -4
- package/docs/providers/openrouter.md +3 -3
- package/docs/providers/vertex.md +5 -5
- package/docs/providers/xai.md +3 -3
- package/docs/providers/zai.md +3 -3
- package/docs/public-contracts.md +1 -1
- package/docs/rag.md +5 -5
- package/docs/release-and-install.md +116 -50
- package/docs/runs-and-usage.md +14 -1
- package/docs/server.md +90 -1
- package/docs/sheets.md +229 -0
- package/docs/supervisors.md +9 -1
- package/docs/thinking-and-reasoning.md +10 -10
- package/docs/tool-conformance.md +27 -2
- package/docs/tools.md +29 -2
- package/docs/web-tools.md +2 -2
- package/docs/wiki.md +24 -10
- package/docs/workflow-orchestration-primitives.md +24 -0
- package/docs/workflows.md +102 -8
- package/docs/working-and-semantic-memory.md +53 -5
- package/package.json +10 -30
- package/templates/README.md +23 -0
- package/templates/deep-research/README.md.tmpl +47 -0
- package/templates/deep-research/env.example.tmpl +12 -0
- package/templates/deep-research/gitignore.tmpl +7 -0
- package/templates/deep-research/manifest.json +12 -0
- package/templates/deep-research/package.json.tmpl +23 -0
- package/templates/deep-research/src/agent.ts.tmpl +81 -0
- package/templates/deep-research/src/index.ts.tmpl +53 -0
- package/templates/deep-research/src/tests/research.test.ts.tmpl +114 -0
- package/templates/deep-research/src/tools.ts.tmpl +86 -0
- package/templates/deep-research/src/types.ts.tmpl +45 -0
- package/templates/deep-research/src/workflow.ts.tmpl +156 -0
- package/templates/deep-research/tsconfig.json.tmpl +15 -0
- package/templates/init/manifest.json +5 -0
- package/templates/init/package.json.tmpl +2 -1
- package/templates/init/providers.json +16 -16
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# Migrate legacy 0.3 packages to Prism 0.4
|
|
2
|
+
|
|
3
|
+
> **Status: 0.4 release draft.** Follow this guide only after the 0.4 packages are published.
|
|
4
|
+
> Until then, stay on your current 0.3.x package set. This page is the permanent destination of
|
|
5
|
+
> npm's legacy-package warnings.
|
|
6
|
+
|
|
7
|
+
## What changes
|
|
8
|
+
|
|
9
|
+
Prism 0.4 replaces 62 separate 0.3 package manifests with 11 active packages and explicit
|
|
10
|
+
subpaths. The code and behavior move; this is not a database/data migration. It is a **package
|
|
11
|
+
name and import-specifier migration**.
|
|
12
|
+
|
|
13
|
+
- Existing applications pinned to 0.3.x continue to work.
|
|
14
|
+
- Retired packages are not unpublished. Their final release remains on npm with its `latest`
|
|
15
|
+
tag and gains a `legacy` tag plus an install-time deprecation warning.
|
|
16
|
+
- `npm install` cannot automatically replace one package name with another. Upgrade each package
|
|
17
|
+
dependency and its imports together.
|
|
18
|
+
- There are no 0.4 compatibility wrappers. New packages never import old package names, so the
|
|
19
|
+
package graph cannot form a wrapper cycle.
|
|
20
|
+
- `@arnilo/prism` stays small and dependency-free. Runtime, sessions, governance, and optional
|
|
21
|
+
drivers live in `@arnilo/prism-core`, not root-package subpaths.
|
|
22
|
+
|
|
23
|
+
## Before you start
|
|
24
|
+
|
|
25
|
+
1. Commit or lock your working 0.3.x application.
|
|
26
|
+
2. Record installed Prism packages and direct imports:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm ls --all @arnilo/prism @arnilo/prism-*
|
|
30
|
+
rg -n 'from "@arnilo/prism|import\("@arnilo/prism' src test
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
3. Classify each package using the tables below. Leave unchanged interop packages in place.
|
|
34
|
+
4. Upgrade package dependencies and imports in one pull request; then run your normal typecheck,
|
|
35
|
+
tests, and packed-install smoke test.
|
|
36
|
+
5. Add optional peers only for subpaths you use. Do not add a database, browser, parser, or host
|
|
37
|
+
binary merely because a family package is installed.
|
|
38
|
+
|
|
39
|
+
## Active 0.4 packages
|
|
40
|
+
|
|
41
|
+
| Package | Use it for |
|
|
42
|
+
|---|---|
|
|
43
|
+
| `@arnilo/prism` | Contracts, agent APIs, CLI, root `node/*` and `testing/*` exports. |
|
|
44
|
+
| `@arnilo/prism-core` | Runtime, sessions, governance, credentials, persistence, work integration, JSON Schema validation. |
|
|
45
|
+
| `@arnilo/prism-providers` | All first-party provider adapters as explicit subpaths. |
|
|
46
|
+
| `@arnilo/prism-coding-tools` | Coding agent/security, document reader, OpenAPI, desktop control, Dev inspector, Caveman, Ponytail, Impeccable. |
|
|
47
|
+
| `@arnilo/prism-web-tools` | Generic web tools plus browser and Obscura subpaths. |
|
|
48
|
+
| `@arnilo/prism-memory` | Memory, RAG, compaction, Graft, Wiki. |
|
|
49
|
+
| `@arnilo/prism-office` | Documents, sheets, and diagrams. |
|
|
50
|
+
| `@arnilo/prism-mcp` | MCP interop. |
|
|
51
|
+
| `@arnilo/prism-acp-agent` | ACP interop. |
|
|
52
|
+
| `@arnilo/prism-ag-ui` | AG-UI/A2A/A2UI interop. |
|
|
53
|
+
| `@arnilo/prism-antigravity-agent` | Antigravity interop. |
|
|
54
|
+
|
|
55
|
+
## Package and import mapping
|
|
56
|
+
|
|
57
|
+
Replace the package name in `package.json` and every corresponding source import. The tables map
|
|
58
|
+
root package entrypoints. Any documented non-root entrypoint keeps its feature suffix under the
|
|
59
|
+
new family path; the 0.4 API page for that family is authoritative for exact nested exports.
|
|
60
|
+
|
|
61
|
+
### Providers
|
|
62
|
+
|
|
63
|
+
Install `@arnilo/prism-providers` once, then import only the provider subpath used by the host.
|
|
64
|
+
|
|
65
|
+
| Legacy 0.3 package | 0.4 import |
|
|
66
|
+
|---|---|
|
|
67
|
+
| `@arnilo/prism-provider-ai-sdk` | `@arnilo/prism-providers/ai-sdk` |
|
|
68
|
+
| `@arnilo/prism-provider-alibaba` | `@arnilo/prism-providers/alibaba` |
|
|
69
|
+
| `@arnilo/prism-provider-anthropic` | `@arnilo/prism-providers/anthropic` |
|
|
70
|
+
| `@arnilo/prism-provider-azure` | `@arnilo/prism-providers/azure` |
|
|
71
|
+
| `@arnilo/prism-provider-bedrock` | `@arnilo/prism-providers/bedrock` |
|
|
72
|
+
| `@arnilo/prism-provider-clinepass` | `@arnilo/prism-providers/clinepass` |
|
|
73
|
+
| `@arnilo/prism-provider-deepseek` | `@arnilo/prism-providers/deepseek` |
|
|
74
|
+
| `@arnilo/prism-provider-google` | `@arnilo/prism-providers/google` |
|
|
75
|
+
| `@arnilo/prism-provider-kimi` | `@arnilo/prism-providers/kimi` |
|
|
76
|
+
| `@arnilo/prism-provider-neuralwatt` | `@arnilo/prism-providers/neuralwatt` |
|
|
77
|
+
| `@arnilo/prism-provider-ollama` | `@arnilo/prism-providers/ollama` |
|
|
78
|
+
| `@arnilo/prism-provider-openai` | `@arnilo/prism-providers/openai` |
|
|
79
|
+
| `@arnilo/prism-provider-opencode-go` | `@arnilo/prism-providers/opencode-go` |
|
|
80
|
+
| `@arnilo/prism-provider-openrouter` | `@arnilo/prism-providers/openrouter` |
|
|
81
|
+
| `@arnilo/prism-provider-vertex` | `@arnilo/prism-providers/vertex` |
|
|
82
|
+
| `@arnilo/prism-provider-xai` | `@arnilo/prism-providers/xai` |
|
|
83
|
+
| `@arnilo/prism-provider-zai` | `@arnilo/prism-providers/zai` |
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
// Before
|
|
87
|
+
import * as openai from "@arnilo/prism-provider-openai";
|
|
88
|
+
|
|
89
|
+
// After
|
|
90
|
+
import * as openai from "@arnilo/prism-providers/openai";
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Runtime, sessions, governance, and work integration
|
|
94
|
+
|
|
95
|
+
Install `@arnilo/prism-core`, then choose the specific subpath. This family does not add
|
|
96
|
+
optional drivers to your host automatically.
|
|
97
|
+
|
|
98
|
+
| Legacy 0.3 package | 0.4 import |
|
|
99
|
+
|---|---|
|
|
100
|
+
| `@arnilo/prism-server` | `@arnilo/prism-core/runtime/server` |
|
|
101
|
+
| `@arnilo/prism-supervisor` | `@arnilo/prism-core/runtime/supervisor` |
|
|
102
|
+
| `@arnilo/prism-workflows` | `@arnilo/prism-core/runtime/workflows` |
|
|
103
|
+
| `@arnilo/prism-session-store-codecs` | `@arnilo/prism-core/sessions/codecs` |
|
|
104
|
+
| `@arnilo/prism-session-store-nats` | `@arnilo/prism-core/sessions/nats` |
|
|
105
|
+
| `@arnilo/prism-session-store-postgres` | `@arnilo/prism-core/sessions/postgres` |
|
|
106
|
+
| `@arnilo/prism-session-store-sqlite` | `@arnilo/prism-core/sessions/sqlite` |
|
|
107
|
+
| `@arnilo/prism-policy` | `@arnilo/prism-core/governance/policy` |
|
|
108
|
+
| `@arnilo/prism-evals` | `@arnilo/prism-core/governance/evals` |
|
|
109
|
+
| `@arnilo/prism-prompts` | `@arnilo/prism-core/governance/prompts` |
|
|
110
|
+
| `@arnilo/prism-model-router` | `@arnilo/prism-core/governance/model-router` |
|
|
111
|
+
| `@arnilo/prism-observability-opentelemetry` | `@arnilo/prism-core/governance/observability` |
|
|
112
|
+
| `@arnilo/prism-credentials-node` | `@arnilo/prism-core/credentials/node` |
|
|
113
|
+
| `@arnilo/prism-enterprise-postgres` | `@arnilo/prism-core/enterprise/postgres` |
|
|
114
|
+
| `@arnilo/prism-work-tools` | `@arnilo/prism-core/integrations/work` |
|
|
115
|
+
| `@arnilo/prism-tool-validator-json-schema` | `@arnilo/prism-core/validation/json-schema` |
|
|
116
|
+
|
|
117
|
+
`work-tools` belongs to core because enterprise Postgres composes its work-idempotency store.
|
|
118
|
+
It is not part of coding tools.
|
|
119
|
+
|
|
120
|
+
### Coding tools and personas
|
|
121
|
+
|
|
122
|
+
Install `@arnilo/prism-coding-tools`; import the smallest needed subpath. The `prism-dev` binary
|
|
123
|
+
continues to be named `prism-dev` after migration.
|
|
124
|
+
|
|
125
|
+
| Legacy 0.3 package | 0.4 import |
|
|
126
|
+
|---|---|
|
|
127
|
+
| `@arnilo/prism-coding-agent` | `@arnilo/prism-coding-tools/agent` |
|
|
128
|
+
| `@arnilo/prism-coding-security` | `@arnilo/prism-coding-tools/security` |
|
|
129
|
+
| `@arnilo/prism-document-reader` | `@arnilo/prism-coding-tools/document-reader` |
|
|
130
|
+
| `@arnilo/prism-openapi-tools` | `@arnilo/prism-coding-tools/openapi` |
|
|
131
|
+
| `@arnilo/prism-computer-use-linux` | `@arnilo/prism-coding-tools/computer-use-linux` |
|
|
132
|
+
| `@arnilo/prism-dev` | `@arnilo/prism-coding-tools/dev` |
|
|
133
|
+
| `@arnilo/prism-caveman` | `@arnilo/prism-coding-tools/caveman` |
|
|
134
|
+
| `@arnilo/prism-ponytail` | `@arnilo/prism-coding-tools/ponytail` |
|
|
135
|
+
| `@arnilo/prism-impeccable` | `@arnilo/prism-coding-tools/impeccable` |
|
|
136
|
+
|
|
137
|
+
### Web, browser, and Obscura
|
|
138
|
+
|
|
139
|
+
`@arnilo/prism-web-tools` keeps its root entrypoint for generic research tools. Browser and
|
|
140
|
+
Obscura become explicit subpaths; neither activates a browser or process on import.
|
|
141
|
+
|
|
142
|
+
| Legacy 0.3 package | 0.4 import |
|
|
143
|
+
|---|---|
|
|
144
|
+
| `@arnilo/prism-browser` | `@arnilo/prism-web-tools/browser` |
|
|
145
|
+
| `@arnilo/prism-obscura` | `@arnilo/prism-web-tools/obscura` |
|
|
146
|
+
|
|
147
|
+
### Memory, RAG, compaction, and context
|
|
148
|
+
|
|
149
|
+
`@arnilo/prism-memory` retains its root memory entrypoint and gains explicit subpaths. The
|
|
150
|
+
`prism-wiki` binary remains named `prism-wiki` and continues to ship Wiki skills.
|
|
151
|
+
|
|
152
|
+
| Legacy 0.3 package | 0.4 import or install |
|
|
153
|
+
|---|---|
|
|
154
|
+
| `@arnilo/prism-rag` | `@arnilo/prism-memory/rag` |
|
|
155
|
+
| `@arnilo/prism-compaction-llm` | `@arnilo/prism-memory/compaction/llm` |
|
|
156
|
+
| `@arnilo/prism-compaction-observational-memory` | `@arnilo/prism-memory/compaction/observational-memory` |
|
|
157
|
+
| `@arnilo/prism-graft` | `@arnilo/prism-memory/graft` |
|
|
158
|
+
| `@arnilo/prism-wiki` | `@arnilo/prism-memory/wiki` |
|
|
159
|
+
| `@arnilo/prism-compaction` | Install `@arnilo/prism-memory`; choose one or both compaction subpaths. No direct import replacement: it was a profile-only manifest. |
|
|
160
|
+
|
|
161
|
+
### Office suite
|
|
162
|
+
|
|
163
|
+
Plans 051–053 drafted three separate packages. They were never published to npm.
|
|
164
|
+
Install `@arnilo/prism-office` and import the subpath:
|
|
165
|
+
|
|
166
|
+
| Draft 0.3 name | 0.4 import |
|
|
167
|
+
|---|---|
|
|
168
|
+
| `@arnilo/prism-documents` | `@arnilo/prism-office/documents` |
|
|
169
|
+
| `@arnilo/prism-sheets` | `@arnilo/prism-office/sheets` |
|
|
170
|
+
| `@arnilo/prism-diagrams` | `@arnilo/prism-office/diagrams` |
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
import { generateDocument } from "@arnilo/prism-office/documents";
|
|
174
|
+
import { parseCsv } from "@arnilo/prism-office/sheets";
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
`@office-open/{docx,xlsx,pptx,xml}` are exact-pinned regular dependencies of the
|
|
178
|
+
office tarball. The diagrams live-embed optionally peers `playwright-core`; XML
|
|
179
|
+
canonicalization does not.
|
|
180
|
+
|
|
181
|
+
### Removed profile packages
|
|
182
|
+
|
|
183
|
+
Profiles were dependency lists, not runtime APIs. Choose the families your host uses; do not look
|
|
184
|
+
for a 0.4 profile replacement package.
|
|
185
|
+
|
|
186
|
+
| Legacy 0.3 profile | 0.4 starting recipe |
|
|
187
|
+
|---|---|
|
|
188
|
+
| `@arnilo/prism-base` | `npm i @arnilo/prism@^0.4.0 @arnilo/prism-core@^0.4.0 @arnilo/prism-memory@^0.4.0` |
|
|
189
|
+
| `@arnilo/prism-code` | Base recipe + `@arnilo/prism-coding-tools@^0.4.0 @arnilo/prism-mcp@^0.4.0` |
|
|
190
|
+
| `@arnilo/prism-sdk` | Base recipe + `@arnilo/prism-mcp@^0.4.0`; Core contains credentials, observability, and workflows. |
|
|
191
|
+
| `@arnilo/prism-all` | Select required families explicitly. Begin with Core, Providers, Coding tools, Web tools, Memory, and required interop; add Office only if needed. |
|
|
192
|
+
|
|
193
|
+
### Names that remain
|
|
194
|
+
|
|
195
|
+
These package names remain valid. Review their imports if they now consume one of the new family
|
|
196
|
+
subpaths, but do not rename the dependency merely because of 0.4.
|
|
197
|
+
|
|
198
|
+
| Package | 0.4 status |
|
|
199
|
+
|---|---|
|
|
200
|
+
| `@arnilo/prism` | Unchanged root package; remains dependency-free. |
|
|
201
|
+
| `@arnilo/prism-providers` | Same name, now code family; provider imports use `/provider-name`. |
|
|
202
|
+
| `@arnilo/prism-web-tools` | Same name; root web tools unchanged, browser/Obscura use subpaths. |
|
|
203
|
+
| `@arnilo/prism-memory` | Same name; RAG/compaction/Graft/Wiki use subpaths. |
|
|
204
|
+
| `@arnilo/prism-mcp` | Unchanged interop package. |
|
|
205
|
+
| `@arnilo/prism-acp-agent` | Unchanged interop package. |
|
|
206
|
+
| `@arnilo/prism-ag-ui` | Unchanged interop package. |
|
|
207
|
+
| `@arnilo/prism-antigravity-agent` | Unchanged interop package. |
|
|
208
|
+
|
|
209
|
+
## Optional peers, host binaries, and trust boundaries
|
|
210
|
+
|
|
211
|
+
Installing a family does not install or activate its optional capabilities. Add the peer only for
|
|
212
|
+
the subpath you use and preserve its existing host policy.
|
|
213
|
+
|
|
214
|
+
| Feature | Required host dependency / action | Do not weaken |
|
|
215
|
+
|---|---|---|
|
|
216
|
+
| SQLite sessions or prompt store | Install `better-sqlite3`; use only the selected `prism-core` session/governance subpath. | Database ownership, migration checks, and file permissions. |
|
|
217
|
+
| PostgreSQL sessions, prompts, or enterprise state | Install `pg`; use the selected `prism-core` subpath. | TLS, roles, checksummed migrations, and tenant boundaries. |
|
|
218
|
+
| NATS sessions | Install/configure the NATS client required by the sessions NATS subpath. | Stream/consumer ownership and durable cursor isolation. |
|
|
219
|
+
| Browser tools | Install `playwright-core` and provide the approved host browser/context. | Egress, upload/download, screenshot, and side-effect policies. |
|
|
220
|
+
| Obscura | Install/configure `playwright-core`, `@arnilo/prism-mcp`, and an approved host Obscura binary. | Absolute shell-free command, SSRF controls, process limits, MCP authorization. |
|
|
221
|
+
| Document reader | Install `mammoth` and/or `pdf-parse` for used formats. | Magic-byte format gating, input/page/text caps, and no embedded-content execution. |
|
|
222
|
+
| Graft | Install/configure `@nanonets/graft` or approved host CLI. | Workspace confinement, output/time limits, and no implicit process start. |
|
|
223
|
+
| Wiki | Provide the documented host `qmd`/Context7 setup when using Wiki commands. | Workspace path, process, and untrusted-content limits. |
|
|
224
|
+
| Computer Use Linux | Provide the approved `computer-use-linux` MCP host binary. | Consent, sandbox, approval, serialized input, and redaction. |
|
|
225
|
+
|
|
226
|
+
## Recommended upgrade sequence
|
|
227
|
+
|
|
228
|
+
1. **Move root/version first.** Set `@arnilo/prism` to `^0.4.0`; retain the Node version required
|
|
229
|
+
by the release.
|
|
230
|
+
2. **Replace retired dependency names.** Use the appropriate family package in `package.json`.
|
|
231
|
+
3. **Replace imports.** Apply the tables above. Do not keep both old and new imports in the same
|
|
232
|
+
runtime path.
|
|
233
|
+
4. **Add only needed peers.** Follow the previous table; subpath import failures should name the
|
|
234
|
+
missing peer rather than fall back to an unsafe implementation.
|
|
235
|
+
5. **Recheck host wiring.** Re-register tools/providers/extensions explicitly. Package install
|
|
236
|
+
remains inert; it must not activate providers, listeners, database connections, browsers,
|
|
237
|
+
credentials, or tools.
|
|
238
|
+
6. **Run verification.**
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
npm run typecheck
|
|
242
|
+
npm test
|
|
243
|
+
npm pack --dry-run
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Run protected PostgreSQL, browser, Obscura, MCP, or host-binary checks separately when your
|
|
247
|
+
application uses those integrations.
|
|
248
|
+
|
|
249
|
+
## Legacy warning and lifecycle
|
|
250
|
+
|
|
251
|
+
Each retired package's final 0.3 release is marked with npm's `legacy` dist-tag and a deprecation
|
|
252
|
+
warning like:
|
|
253
|
+
|
|
254
|
+
```text
|
|
255
|
+
npm warn deprecated @arnilo/prism-browser@0.3.x:
|
|
256
|
+
Legacy 0.3 package. Prism 0.4+: @arnilo/prism-web-tools/browser.
|
|
257
|
+
https://github.com/ashiqrniloy/prism/blob/main/docs/migrate-to-0.4.md#web-browser-and-obscura
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
The warning is informational: it does not delete the package or rewrite your dependency. `latest`
|
|
261
|
+
continues to point at the final 0.3 release because npm dist-tags cannot redirect one package name
|
|
262
|
+
to a different package. New 0.4 development must use the successor listed above.
|
|
263
|
+
|
|
264
|
+
The markers are generated and applied from one reviewed registry plan — never hand-copied. Run
|
|
265
|
+
`node scripts/phase54-legacy-registry.mjs --dry-run` to resolve every retired name's final
|
|
266
|
+
published version, verify the anchors above exist in this guide, and print the exact
|
|
267
|
+
`npm dist-tag add ... legacy` and `npm deprecate ..."<0.4.0"` commands without mutating the
|
|
268
|
+
registry. After the 0.4 packages and this guide are public (Task 9 cutover),
|
|
269
|
+
`node scripts/phase54-legacy-registry.mjs --apply --confirm` pre-flights every entry and fails
|
|
270
|
+
closed — zero mutations — on any mismatch, then applies the tags and warnings idempotently:
|
|
271
|
+
already-correct entries are skipped on resume, and per-entry status is written to
|
|
272
|
+
`release-artifacts/legacy-registry-plan.json` for safe resume. Two retired names
|
|
273
|
+
(`@arnilo/prism-prompts`, `@arnilo/prism-dev`) were never published; they are recorded in the
|
|
274
|
+
plan with no registry action.
|
|
275
|
+
|
|
276
|
+
## Rollback
|
|
277
|
+
|
|
278
|
+
If the 0.4 migration fails before deployment:
|
|
279
|
+
|
|
280
|
+
1. Restore the committed 0.3.x `package.json` and lockfile.
|
|
281
|
+
2. Restore old imports from the mapping table.
|
|
282
|
+
3. Reinstall with the lockfile (`npm ci`).
|
|
283
|
+
4. Do not unpublish any package or remove the `legacy` marker; those are registry metadata, not a
|
|
284
|
+
runtime migration.
|
|
285
|
+
|
|
286
|
+
The package reorganization itself does not change persisted store schemas. If the same deployment
|
|
287
|
+
also adopted a separate database/session feature release, follow that feature's migration and
|
|
288
|
+
rollback instructions; do not assume package rollback reverses a forward-only database migration.
|
|
289
|
+
|
|
290
|
+
## FAQ
|
|
291
|
+
|
|
292
|
+
**Can I install `@arnilo/prism-all` in 0.4?** No. It was a pure manifest and is retired. Install
|
|
293
|
+
only the family packages your host needs.
|
|
294
|
+
|
|
295
|
+
**Why is `@arnilo/prism-core` separate from `@arnilo/prism`?** Root Prism remains dependency-free.
|
|
296
|
+
Database drivers, optional Node integrations, and governance/runtime modules must not become
|
|
297
|
+
implicit root dependencies.
|
|
298
|
+
|
|
299
|
+
**Why not keep old packages as wrappers?** Wrappers preserve 54 active manifests and create a
|
|
300
|
+
cycle if a new family imports the old implementation while the old package re-exports the family.
|
|
301
|
+
The direct migration is smaller and unambiguous.
|
|
302
|
+
|
|
303
|
+
**Do unchanged interop packages need changes?** No package-name change. Keep MCP, ACP, AG-UI, or
|
|
304
|
+
Antigravity installed only when your host uses that protocol; update imports only if their own 0.4
|
|
305
|
+
API page says so.
|
|
306
|
+
|
|
307
|
+
## Related APIs
|
|
308
|
+
|
|
309
|
+
- [Release and install](release-and-install.md): package contents, peer rules, and publication.
|
|
310
|
+
- [Migration guide](migration.md): migration history for prior releases.
|
|
311
|
+
- [Provider packages](provider-packages.md): provider adapter behavior.
|
|
312
|
+
- [Host security guide](host-security.md): preserve host trust boundaries while upgrading.
|
package/docs/migration.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Migration guide
|
|
2
2
|
|
|
3
|
+
## 0.3.3 → 0.4.0 package reorganization (breaking)
|
|
4
|
+
|
|
5
|
+
Prism 0.4 consolidates package names into explicit family subpaths. It is a dependency and import-specifier migration, not a persisted-data migration. See the complete [legacy 0.3 → 0.4 guide](migrate-to-0.4.md) for all 54 retired package mappings, profile replacements, optional peers/host binaries, security checks, rollback, and npm legacy-warning behavior.
|
|
6
|
+
|
|
7
|
+
## 0.3.1 → 0.3.2: bounded workflow loop durability (additive, no migration)
|
|
8
|
+
|
|
9
|
+
`@arnilo/prism-workflows@0.3.2` adds the bounded `loopNode` durable extension. It adds optional `WorkflowNodeCheckpoint.iterations` records, each carrying `schemaVersion: 1`, a zero-based `iteration`, stable `iterationId`, and bounded/redacted output. Existing `WorkflowCheckpointValue.schemaVersion` remains `1`; older checkpoints without `iterations` remain readable through the legacy `iteration`/`lastOutput` cursor, and older hosts ignore the additive field. No SQL or generic checkpoint-store migration is required. Replay creates a new run and never mutates source iteration evidence. Hosts using saga compensation keep one saga step/aggregate and register per-iteration compensation by `iterationId` in reverse order.
|
|
10
|
+
|
|
11
|
+
This independent package patch freezes budget accounting: `maxNodes` counts declared DAG nodes once, while loop body executions consume only the required hard-capped `maxIterations` budget. Rollback is package-version rollback; no persisted migration is needed.
|
|
12
|
+
|
|
13
|
+
## 0.3.2 → 0.3.3: run-ledger prompt provenance (additive, schema version 9)
|
|
14
|
+
|
|
15
|
+
Plan 042 adds an optional typed `promptVersion` ref (`{ name, version, hash }`) to `RunOptions` and `RunRecord`. Hosts resolve a prompt from `@arnilo/prism-prompts` and stamp the run: the ref is copied onto the start/finish ledger records and persisted by the first-party SQLite/PostgreSQL stores as a nullable `prompt_version` JSON column (shared schema migration `009_run_prompt_version`, schema version 8 → 9, forward-only and applied automatically by the adapters' checksummed `prism_migrations`). Strictly additive: unset `promptVersion` produces byte-identical rows and records, legacy rows read back without the field, and no exported declaration was removed. The ref carries identity only (`sha256:` body hash) — prompt bodies stay in the separate `@arnilo/prism-prompts` tables and out of run rows, metadata, and telemetry.
|
|
16
|
+
|
|
17
|
+
## 0.3.2 → 0.3.3: tool progressive disclosure (additive, no migration)
|
|
18
|
+
|
|
19
|
+
Plan 041 adds opt-in progressive tool loading to `@arnilo/prism`: `toolsDisclosure` (default `"all"`, byte-identical to previous releases) and `toolsSearch.topK` on `AgentConfig` / `RunOptions`, plus the generated `search_tools` tool in search mode. Strictly additive — no exported declaration removed, no persisted shape repurposed. Durable run state gains an optional `sessionState.activatedToolNames` (names only, capped at 128); stores that ignore it resume exactly as before. Set nothing and behavior is unchanged; see [Tools](tools.md#tool-disclosure-progressive-tool-loading).
|
|
20
|
+
|
|
21
|
+
## 0.3.1 → 0.3.2 memory package: composite recall scoring (additive, no migration)
|
|
22
|
+
|
|
23
|
+
`@arnilo/prism-memory@0.3.2` adds opt-in `RecallOptions.scoring`: sum-normalized similarity/recency/importance blending, with a positive `halfLifeMs` required only when `recencyWeight > 0`. Default recall (no `scoring`) keeps its existing ordering and query count. `MemoryVectorRecord.importance?` persists through an additive nullable `importance REAL` column (`ADD COLUMN IF NOT EXISTS`); legacy NULL rows score neutral `1.0`, so no re-index or data migration is required. At write, hosts may pass a clamped `[0,1]` `entry.importance` or an `importanceFrom` hook over a redacted reflection; it runs once at write, never at recall. Rollback is package-version rollback only: old readers ignore the nullable column, and new readers treat absent values neutrally.
|
|
24
|
+
|
|
3
25
|
## 0.3.0 → 0.3.1 production RAG engine (independent patch)
|
|
4
26
|
|
|
5
27
|
Only `@arnilo/prism-rag`, `@arnilo/prism-memory`, and `@arnilo/prism-observability-opentelemetry` move to `0.3.1`. Keep every other first-party package on `^0.3.0` — those ranges already satisfy `0.3.1`.
|
package/docs/model-routing.md
CHANGED
|
@@ -156,4 +156,4 @@ await router.recordOutcome({ identity, provider, model, success: true, latencyMs
|
|
|
156
156
|
- [Policy and audit](policy-and-audit.md)
|
|
157
157
|
- [Agent identity](agent-identity.md)
|
|
158
158
|
- [Enterprise PostgreSQL state](enterprise-postgres-state.md): durable router state, migration, cleanup, and ownership requirements.
|
|
159
|
-
- Package README: [`@arnilo/prism-
|
|
159
|
+
- Package README: [`@arnilo/prism-core`](../packages/prism-core/README.md)
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Multi-agent patterns: handoff, hierarchical crew, supervisor delegation, A2A
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
Maps the four Prism answers for "more than one agent" onto one decision table. All four compose existing seams — none introduces a new runtime:
|
|
6
|
+
|
|
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
|
+
- **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.
|
|
10
|
+
- **A2A 1.0** — cross-service interop over the JSON-RPC/HTTPS binding; the remote peer's lifecycle is host-owned behind `A2ATaskLifecycle`.
|
|
11
|
+
|
|
12
|
+
## When to use it
|
|
13
|
+
|
|
14
|
+
| Pattern | Use when | Conversation boundary | Ownership / identity | Telemetry |
|
|
15
|
+
| --- | --- | --- | --- | --- |
|
|
16
|
+
| In-session handoff | One host, one ongoing conversation; the model decides **when** to transfer; specialists are alternate definitions of the same app | One continuous transcript chain (same store, session id, `leafId`) | Same session scope; give the specialist its own identity via its definition (`AgentConfig.identity` / `RunOptions.identity`) | Attribution is per-run: each `session.run()`'s events/result belong to the active definition — record the swap in host bookkeeping; no `delegated_agent_step` event exists for in-process swaps |
|
|
17
|
+
| Hierarchical crew | A goal requires dynamic decomposition by a manager LLM, parallel execution by role specialists, host aggregation, and conditional validation/revision loop | Workflow DAG execution — each specialist executes a bounded child task session; final deliverable returns to host | Workflow tenant/ownership scopes propagate; specialists activate only their own narrowed `tools` | Workflow node events (`node_started`/`node_finished`/`agent_event`); task attribution per role in the aggregated deliverable |
|
|
18
|
+
| Supervisor delegation | Parent agent needs a child as a *tool call*: bounded budget, hooks that redact/narrow, nested delegation, durable child approvals | Separate runs; child result returns to the parent transcript | Parent identity/effectStore propagate; child factories receive derived resource/thread ids and AND-composed permission | Dedicated `delegation_started/finished/rejected/error` events, projectable through observability `handleDelegation()`; opt-in `delegation_child_event` passthrough |
|
|
19
|
+
| A2A 1.0 | The other agent is owned by a **different service/deployment**; cross-org or cross-cluster; needs durable task lifecycle, push configs, streaming | Protocol boundary (JSON-RPC/HTTPS agent card); replay/reconnect via host-owned task adapter | Exact-origin verified client, `A2AAuthorization` per operation, principal-scoped push configs | Host-owned task adapter records the remote lifecycle; Prism creates no worker/store |
|
|
20
|
+
|
|
21
|
+
Rule of thumb: same conversation → handoff; dynamic task decomposition + parallel execution → hierarchical crew; same process but a subtask → supervisor delegation; different deployment/trust boundary → A2A.
|
|
22
|
+
|
|
23
|
+
## How in-session handoff works
|
|
24
|
+
|
|
25
|
+
The pattern is a definition swap over existing seams — triage keeps calling `handoff(target)`; the host authorizes, swaps, and continues the same session:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
// Host-built allow-list tool; untrusted target -> fail-closed tool error result.
|
|
29
|
+
const handoffTool: ToolDefinition = {
|
|
30
|
+
name: "handoff",
|
|
31
|
+
description: "Transfer this conversation to a named specialist agent.",
|
|
32
|
+
parameters: { type: "object", required: ["target"], properties: { target: { type: "string" } } },
|
|
33
|
+
execute(args, ctx): ToolResult {
|
|
34
|
+
const target = String((args as { target: string }).target);
|
|
35
|
+
if (!(target in handoffTargets)) {
|
|
36
|
+
return { toolCallId: ctx.toolCallId, name: "handoff", error: { message: `Unknown handoff target: ${target}` } };
|
|
37
|
+
}
|
|
38
|
+
return { toolCallId: ctx.toolCallId, name: "handoff", value: { transferredTo: target } };
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Host authorizes the transfer mid-run: resolve the target definition and
|
|
43
|
+
// continue the SAME session (same store + sessionId). The previous run's
|
|
44
|
+
// leafId carries the transcript pointer; without it the next append forks
|
|
45
|
+
// a sibling branch and the specialist loses the carried context.
|
|
46
|
+
const specialist = await resolveAgentDefinition(handoffTargets[target], {
|
|
47
|
+
tools: [refundTool], // narrowed: no handoff tool unless the host allows it
|
|
48
|
+
overrides: { provider: specialistProvider },
|
|
49
|
+
});
|
|
50
|
+
const specialistSession = createAgentSession({ agent: specialist, store, id: "handoff-demo", leafId: triageRun.leafId });
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Live demo: [`examples/handoff-swarm.ts`](../examples/handoff-swarm.ts) — triage → billing transfer with fail-closed unknown target, a specialist whose re-handoff attempt is blocked (`unknown_tool`), and zero provider calls for the swap (it is a registry-level operation).
|
|
54
|
+
|
|
55
|
+
Two non-obvious details the example encodes:
|
|
56
|
+
|
|
57
|
+
1. **`leafId` carries the transcript pointer.** The specialist session must pass the triage run's `leafId`; creating the session without it appends to a sibling branch and the specialist loses the carried context.
|
|
58
|
+
2. **Carried context is the transcript chain itself.** Handoff is not delegation: there is no input-payload boundary to sanitize; whatever was said to triage is what the specialist reads.
|
|
59
|
+
|
|
60
|
+
## How hierarchical crew orchestration works
|
|
61
|
+
|
|
62
|
+
Hierarchical multi-agent orchestration (the CrewAI "Hierarchical Process" pattern) decomposes a high-level goal into structured tasks, assigns each task to a role specialist agent in parallel, aggregates deliverables, and validates the outcome in a deterministic workflow:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
// 1. Manager produces a typed task plan via structured output.
|
|
66
|
+
// Untrusted model output is validated against the schema before updating state.
|
|
67
|
+
const manager = agentNode({
|
|
68
|
+
agent: "manager",
|
|
69
|
+
input: (ctx) => ({ goal: ctx.workflowInput }),
|
|
70
|
+
output: async (ctx) => {
|
|
71
|
+
const plan = parseTaskPlan(await getSessionOutput(ctx.session));
|
|
72
|
+
if (!plan.ok) throw new Error(`Invalid task plan: ${plan.error}`);
|
|
73
|
+
await ctx.updateState({ plan: plan.value });
|
|
74
|
+
return plan.value;
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// 2. fan_out maps each task item to its corresponding role specialist.
|
|
79
|
+
const fan = fanOutNode({
|
|
80
|
+
items: (ctx) => (ctx.state.plan as TaskPlan).tasks,
|
|
81
|
+
map: async (task, _index, _ctx) => {
|
|
82
|
+
const agent = await resolveAgentDefinition(definitions[task.role], { tools });
|
|
83
|
+
const session = createAgentSession({ agent });
|
|
84
|
+
const result = await session.run(task.instruction);
|
|
85
|
+
return { role: task.role, result: result.text, attribution: { agent: task.role } };
|
|
86
|
+
},
|
|
87
|
+
maxFanOut: 8,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// 3. join aggregates all specialist deliverables and computes per-role attribution.
|
|
91
|
+
const aggregate = joinNode({
|
|
92
|
+
from: "fan",
|
|
93
|
+
reduce: async (items, ctx) => ({
|
|
94
|
+
deliverables: items,
|
|
95
|
+
summary: items.map((d) => `[${d.role}]: ${d.result}`).join("\n"),
|
|
96
|
+
validationPassed: evaluateQuality(items),
|
|
97
|
+
}),
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// 4. conditional validation routes to completion or revision.
|
|
101
|
+
const validate = conditionalNode({
|
|
102
|
+
when: async (ctx) => Boolean((ctx.upstream.aggregate as AggregatedDeliverable).validationPassed),
|
|
103
|
+
then: ["complete"],
|
|
104
|
+
else: ["revise"],
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
const complete = functionNode({ execute: async (ctx) => formatDeliverable(ctx.upstream.aggregate) });
|
|
108
|
+
const revise = functionNode({ execute: async (ctx) => formatRevision(ctx.upstream.aggregate) });
|
|
109
|
+
|
|
110
|
+
// 5. Entire flow is a single defineWorkflow DAG with fixed revision ID.
|
|
111
|
+
const crewWorkflow = defineWorkflow({
|
|
112
|
+
revision: "crew-demo-1",
|
|
113
|
+
id: "hierarchical-crew",
|
|
114
|
+
nodes: { manager, fan, aggregate, validate, complete, revise },
|
|
115
|
+
edges: [
|
|
116
|
+
["manager", "fan"],
|
|
117
|
+
["fan", "aggregate"],
|
|
118
|
+
["aggregate", "validate"],
|
|
119
|
+
["validate", "complete"],
|
|
120
|
+
["validate", "revise"],
|
|
121
|
+
],
|
|
122
|
+
limits: { maxFanOut: 8, maxConcurrency: 4, maxNodes: 32 },
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Live demo: [`examples/crew-hierarchy.ts`](../examples/crew-hierarchy.ts) — manager structured task decomposition, parallel role specialists (`researcher`, `writer`), host reduce aggregation with per-role attribution, and conditional validation/revision routing.
|
|
127
|
+
|
|
128
|
+
## CrewAI to Prism mapping table
|
|
129
|
+
|
|
130
|
+
| CrewAI Concept | Prism Primitive | Notes & Documentation |
|
|
131
|
+
| --- | --- | --- |
|
|
132
|
+
| **Crew** | Workflow ([`defineWorkflow`](workflows.md)) | A deterministic DAG with explicit revision id, node concurrency, and checkpoint persistence. |
|
|
133
|
+
| **Manager Agent** | Agent Node ([`agentNode`](workflows.md)) + Structured Output ([`generateValidateReviseLoop`](structured-output.md)) | Manager emits a typed `{ tasks: [{ role, instruction }] }` schema via `ArtifactValidator`/`ArtifactParser`. |
|
|
134
|
+
| **Task** | Fan-out item ([`fanOutNode`](workflows.md)) | Bounded dynamic fan-out (`maxFanOut`), mapping each decomposed task to a role specialist session. |
|
|
135
|
+
| **Role Agent (Specialist)** | Agent Definition ([`resolveAgentDefinition`](agent-definitions.md)) | Declarative agent with fail-closed tool narrowing; activated per role during `fan_out.map`. |
|
|
136
|
+
| **Process (Sequential / Hierarchical)** | Workflow DAG ([`defineWorkflow`](workflows.md) / Edges) | Edges define data and execution dependencies; no unconstrained agent-to-agent loops. |
|
|
137
|
+
| **Task Output Aggregation** | Join Node ([`joinNode`](workflows.md) + `reduce`) | Host-controlled reduction aggregating specialist outputs and computing per-role attribution. |
|
|
138
|
+
| **Validation & Quality Review** | Conditional Node ([`conditionalNode`](workflows.md)) | Deterministic branch routing to `complete` or `revise` based on validation criteria. |
|
|
139
|
+
| **Process Revision Loop** | Node Retries / DAG Branching / Loop Node ([`loopNode`](workflows.md)) | Bounded retry/revision path or bounded in-graph loop iteration. |
|
|
140
|
+
|
|
141
|
+
## Where Prism is stronger
|
|
142
|
+
|
|
143
|
+
- **Durable Human-in-the-Loop (HITL)**: Prism workflows support durable pause and resume via [`suspend()`](workflows.md#durable-suspension-and-resumption) and [`resumeWorkflow()`](workflows.md) across worker restarts or approval gates ([Agent durable approval](agent-session-runtime.md)).
|
|
144
|
+
- **Strict Budget & Concurrency Caps**: Workflows enforce hard limits on `maxNodes`, `maxFanOut`, `maxConcurrency`, and timeout bounds ([Workflow limits](workflows.md)).
|
|
145
|
+
- **Fail-Closed Capability Narrowing**: Specialists receive only their explicitly authorized `tools` via [`resolveAgentDefinition`](agent-definitions.md); managers cannot invoke specialist tools directly, preventing accidental tool leakage.
|
|
146
|
+
- **Untrusted Model Output Validation**: Manager task plans are treated as untrusted LLM output and validated against a typed schema before triggering fan-out ([Structured output](structured-output.md)).
|
|
147
|
+
- **Durable Audit & Telemetry**: Every node start/finish and agent event is emitted with deterministic sequence numbers and can be persisted to signed audit ledgers ([Policy and audit](policy-and-audit.md), [Observability](observability.md)).
|
|
148
|
+
|
|
149
|
+
## Security and performance notes
|
|
150
|
+
|
|
151
|
+
- **Transfers are explicit model-initiated, host-authorized.** The `handoff` tool exists on the triage agent's allow-list only; the target name is validated against the host-authored targets map before any definition resolves. Unknown names fail closed as a standard tool error (`Unknown handoff target: <name>`).
|
|
152
|
+
- **No permission escalation through handoff or delegation.** The specialist's capabilities come solely from its own `AgentDefinition` as resolved by `resolveAgentDefinition` (fail-closed for omitted capabilities). Handoff or fan-out grants nothing: tools/identity are what the host put on that definition. The specialist cannot invoke manager tools unless its definition explicitly includes them — the standard `unknown_tool` block applies otherwise.
|
|
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
|
+
- **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
|
+
- **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; adapter-owned delegation timelines emit `delegated_agent_step` through `createDelegatedAgentStep` (see [Agent events](agent-events.md)) — an in-process definition swap has no session seam to emit it, which is why the swap records attribution host-side.
|
|
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
|
+
|
|
159
|
+
## Extension and configuration notes
|
|
160
|
+
|
|
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; `delegated_agent_step` remains reserved for adapter-driven delegation loops (`@arnilo/prism-antigravity-agent`).
|
|
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.
|
|
165
|
+
|
|
166
|
+
## Related APIs
|
|
167
|
+
|
|
168
|
+
- [Workflows](workflows.md): `defineWorkflow`, `fanOutNode`, `joinNode`, `conditionalNode`, `runWorkflow`.
|
|
169
|
+
- [Structured output](structured-output.md): `ArtifactParser`, `ArtifactValidator`, `generateValidateReviseLoop`.
|
|
170
|
+
- [Agent definitions](agent-definitions.md): `resolveAgentDefinition` and fail-closed capability activation — the swap seam itself.
|
|
171
|
+
- [Supervisor delegation](supervisors.md): same-process subtasks with budgets, hooks, and durable nested approvals.
|
|
172
|
+
- [A2A interoperability](a2a.md): the cross-service protocol boundary.
|
|
173
|
+
- [Agent identity](agent-identity.md): verified identity propagation and narrowing (`narrowIdentity`, `assertIdentityPropagation`).
|
|
174
|
+
- [Agent events](agent-events.md): `delegated_agent_step` and delegation event surfaces for timelines.
|
|
175
|
+
- [Policy and audit](policy-and-audit.md): decision ledger, approval gates, and signed audit export.
|
|
176
|
+
- [Observability](observability.md): OpenTelemetry agent/provider/tool hierarchy and metrics.
|
|
177
|
+
- [Middleware hooks](middleware-hooks.md): context bridging and redaction without permission grants.
|
|
@@ -136,7 +136,7 @@ try {
|
|
|
136
136
|
- Supplying `fetch` is a trusted compatibility/custom-transport escape hatch: Prism still checks URL literals and host allow-lists, but the host-provided fetch owns DNS resolution, rebinding protection, redirects, proxies, TLS, auth, and logging.
|
|
137
137
|
- `resourceUri` resolution requires a caller-provided `ResourceLoader` and optional `ResourceLoadContext.permission` check.
|
|
138
138
|
- Local filesystem paths should use trust policies such as `createPathTrustPolicy()` before exposing URIs to loaders.
|
|
139
|
-
- Provider upload/create/delete lifecycles are provider-package-local. `@arnilo/prism-
|
|
139
|
+
- Provider upload/create/delete lifecycles are provider-package-local. `@arnilo/prism-providers/openai` inlines files under 4 MiB as `data:<mediaType>;base64,...` `file_data`, otherwise uses a bounded per-run upload cache and best-effort `DELETE /v1/files` cleanup after each stream.
|
|
140
140
|
- Shared wire helpers live in `@arnilo/prism/providers/media` (`resolveProviderMediaMessages`, `serializeOpenAIResponsesInputFile`, `serializePdfDocumentWireBlock`, `createBoundedUploadCache`). OpenAI Responses, Kimi, and OpenCode Go Anthropic routes resolve their complete media collection once before serialization or upload.
|
|
141
141
|
- OpenAI Realtime audio is a bidirectional `RealtimeSession` stream, not a `ContentBlock`: provide host-captured `Uint8Array` chunks with `sendAudio()` and consume untrusted `audio_delta` / transcript events. It has a fixed 256 events/s, 1 MiB/s, and 600 s default ceiling.
|
|
142
142
|
|
package/docs/obscura.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Obscura browser engine
|
|
2
2
|
|
|
3
|
-
Optional `@arnilo/prism-obscura` support for a host-installed
|
|
3
|
+
Optional `@arnilo/prism-web-tools/obscura` support for a host-installed
|
|
4
4
|
[Obscura](https://github.com/h4ckf0r0day/obscura) headless browser. Obscura is never
|
|
5
5
|
bundled — install the binary (or use the `h4ckf0r0day/obscura` Docker image) and point
|
|
6
6
|
the package at it.
|
|
@@ -11,7 +11,7 @@ the package at it.
|
|
|
11
11
|
## Install
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
npm install @arnilo/prism-
|
|
14
|
+
npm install @arnilo/prism-web-tools @arnilo/prism-mcp
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
## Process lifecycle (`spawnObscuraProcess`)
|
|
@@ -23,7 +23,7 @@ environment (`PATH`, `HOME`), and insecure flags (`--allow-private-network`,
|
|
|
23
23
|
is set explicitly.
|
|
24
24
|
|
|
25
25
|
```ts
|
|
26
|
-
import { spawnObscuraProcess } from "@arnilo/prism-obscura";
|
|
26
|
+
import { spawnObscuraProcess } from "@arnilo/prism-web-tools/obscura";
|
|
27
27
|
|
|
28
28
|
const obscura = spawnObscuraProcess({
|
|
29
29
|
command: "/usr/local/bin/obscura",
|
|
@@ -53,7 +53,7 @@ Connects to `obscura mcp` (stdio or Streamable HTTP) through
|
|
|
53
53
|
allow-list, so future Obscura tools keep flowing through.
|
|
54
54
|
|
|
55
55
|
```ts
|
|
56
|
-
import { createObscuraMcpTools } from "@arnilo/prism-obscura";
|
|
56
|
+
import { createObscuraMcpTools } from "@arnilo/prism-web-tools/obscura";
|
|
57
57
|
|
|
58
58
|
const obscura = await createObscuraMcpTools({
|
|
59
59
|
transport: { type: "stdio", command: "/usr/local/bin/obscura", args: ["mcp"] },
|
|
@@ -68,7 +68,7 @@ await obscura.close();
|
|
|
68
68
|
- Effects: read/diagnostic/waiter/capture tools are effect-free; navigation,
|
|
69
69
|
interaction, evaluation, cookie/storage writes, tabs, and any unknown future tool
|
|
70
70
|
are exclusive, serialized external mutations (Obscura keeps one live page).
|
|
71
|
-
- Naming: default `obscura_` prefix coexists with
|
|
71
|
+
- Naming: default `obscura_` prefix coexists with the `browser` subpath;
|
|
72
72
|
`namePrefix: ""` preserves native Obscura names.
|
|
73
73
|
- Transports: stdio configs are validated with the same fail-closed command policy;
|
|
74
74
|
Streamable HTTP endpoints outside loopback require explicit `allowRemoteHttp` and
|
|
@@ -82,8 +82,8 @@ host's Playwright via `chromium.connectOverCDP`. `connect()` and browser launch
|
|
|
82
82
|
never used; Prism never launches browsers.
|
|
83
83
|
|
|
84
84
|
```ts
|
|
85
|
-
import { connectObscuraCdp } from "@arnilo/prism-obscura";
|
|
86
|
-
import { createBrowserTools } from "@arnilo/prism-browser";
|
|
85
|
+
import { connectObscuraCdp } from "@arnilo/prism-web-tools/obscura";
|
|
86
|
+
import { createBrowserTools } from "@arnilo/prism-web-tools/browser";
|
|
87
87
|
|
|
88
88
|
const session = await connectObscuraCdp({
|
|
89
89
|
command: "/usr/local/bin/obscura",
|
|
@@ -107,7 +107,7 @@ await session.close(); // browser first, then the owned process
|
|
|
107
107
|
APIs (`browser.newBrowserCDPSession()`, `context.newCDPSession(page)`); the package
|
|
108
108
|
adds no CDP command allow-list.
|
|
109
109
|
- Concurrency limit: pages served by one Obscura worker share one V8 isolate —
|
|
110
|
-
CPU-bound page JavaScript can delay sibling pages. Keep
|
|
110
|
+
CPU-bound page JavaScript can delay sibling pages. Keep the `browser` subpath
|
|
111
111
|
limits authoritative; size Obscura's `--workers` for the host.
|
|
112
112
|
- Screenshots/PDF require a render-enabled Obscura build and still obey the browser
|
|
113
113
|
package's artifact/byte policy.
|
|
@@ -119,7 +119,7 @@ child processes. Returns standard Prism `web_search`/`web_fetch` tools plus expl
|
|
|
119
119
|
`obscura_fetch`/`obscura_scrape` (disable with `nativeTools: false`).
|
|
120
120
|
|
|
121
121
|
```ts
|
|
122
|
-
import { createObscuraWebTools } from "@arnilo/prism-obscura";
|
|
122
|
+
import { createObscuraWebTools } from "@arnilo/prism-web-tools/obscura";
|
|
123
123
|
|
|
124
124
|
const web = createObscuraWebTools({ command: "/usr/local/bin/obscura" });
|
|
125
125
|
agent.tools = [...agent.tools, ...web.tools];
|
|
@@ -149,7 +149,7 @@ agent.tools = [...agent.tools, ...web.tools];
|
|
|
149
149
|
- Docker-style invocations work through `argsBefore` (e.g.
|
|
150
150
|
`["run", "--rm", "-i", "h4ckf0r0day/obscura"]`).
|
|
151
151
|
- An opt-in live smoke test runs against a real installed binary with
|
|
152
|
-
`npm run test:live -w @arnilo/prism-
|
|
152
|
+
`npm run test:live -w @arnilo/prism-web-tools` plus `PRISM_LIVE_OBSCURA=1` and
|
|
153
153
|
`PRISM_OBSCURA_BIN=/path/to/obscura`.
|
|
154
154
|
|
|
155
155
|
## Host conformance (one generic integration)
|
package/docs/openapi-tools.md
CHANGED
|
@@ -53,4 +53,4 @@ Defaults and hard caps (frozen in `scripts/phase11-freeze-manifest.json`): `maxD
|
|
|
53
53
|
- [Tools](tools.md): registry, dispatch, validation
|
|
54
54
|
- [Recoverable tool effects](tool-effects.md): approval + idempotency contracts
|
|
55
55
|
- [Host security guide](host-security.md): permission, trust, validation checklist
|
|
56
|
-
- Package README: [`@arnilo/prism-
|
|
56
|
+
- Package README: [`@arnilo/prism-coding-tools`](../packages/prism-coding-tools/README.md)
|