@arnilo/prism 0.0.2 → 0.0.3

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 CHANGED
@@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.0.3] - 2026-07-08
11
+
12
+ ### Added
13
+
14
+ - New first-party workspace package `@arnilo/prism-coding-agent` providing optional host coding tools (`shell`, `read`, `write`, `edit`) as Prism `ToolDefinition` objects. The package is opt-in and is **not** included in `@arnilo/prism-all` because the tools perform host shell/filesystem operations.
15
+ - `createCodingTools`, `createReadOnlyTools`, and `createAllTools` aggregator factories for importing/registering coding tools.
16
+ - Documentation: `docs/coding-agent-tools.md`, updated `docs/index.md` and `docs/tools.md`, and expanded `packages/coding-agent/README.md`.
17
+
18
+ ### Changed
19
+
20
+ - Bumped all package versions from `0.0.2` to `0.0.3` (core, first-party workspace packages, and umbrella packages).
21
+ - Updated `@arnilo/prism` peer dependency range in every first-party workspace package to `0.0.3`.
22
+ - Updated umbrella package dependency pins to `0.0.3`.
23
+ - `docs/release-and-install.md` now documents nine first-party workspace packages, thirteen total manifests, and the explicit install command for `@arnilo/prism-coding-agent`.
24
+
10
25
  ## [0.0.2] - 2026-07-05
11
26
 
12
27
  ### Added
package/dist/index.d.ts CHANGED
@@ -53,5 +53,5 @@ export type { DispatchToolCallOptions, ToolFilter, ToolFilterInput, ToolRegistry
53
53
  export type { DuplicateRegistrationOptions, DuplicateRegistrationPolicy } from "./registry-options.js";
54
54
  export { generateValidateReviseLoop, isAgentLoopOptions, resolveLoop, singleShotLoop } from "./agent-loops.js";
55
55
  export declare const name = "prism";
56
- export declare const version = "0.0.2";
56
+ export declare const version = "0.0.3";
57
57
  export declare const description = "Agent harness for AI providers, agents, sessions, and tools.";
package/dist/index.js CHANGED
@@ -29,6 +29,6 @@ export { resolveInstructionInjectors, runInstructionInjectors } from "./instruct
29
29
  export { createToolRegistry, dispatchToolCall, filterTools } from "./tools.js";
30
30
  export { generateValidateReviseLoop, isAgentLoopOptions, resolveLoop, singleShotLoop } from "./agent-loops.js";
31
31
  export const name = "prism";
32
- export const version = "0.0.2";
32
+ export const version = "0.0.3";
33
33
  export const description = "Agent harness for AI providers, agents, sessions, and tools.";
34
34
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,208 @@
1
+ # Coding agent tools (first-party package)
2
+
3
+ ## What it does
4
+
5
+ `@arnilo/prism-coding-agent` is an optional first-party package that provides host shell/filesystem tools as Prism `ToolDefinition` objects. It ships four tools — `shell`, `read`, `write`, `edit` — plus aggregator factories. The tools are **inert** until a host imports them and registers them into a `ToolRegistry`. Behavior is a behavioral port of the pi coding agent's `bash`/`read`/`write`/`edit` tools, adapted to Prism's `ToolDefinition` / `ToolResult` contracts (no `@earendil-works/*` or `typebox` dependencies; only `diff` plus the Node standard library).
6
+
7
+ | Export | Purpose |
8
+ | --- | --- |
9
+ | `createShellTool(cwd, options?)` | `shell` tool: run a shell command and return combined output + exit code. |
10
+ | `createReadTool(cwd, options?)` | `read` tool: read a text or image file into `TextContent` / `ImageContent`. |
11
+ | `createWriteTool(cwd, options?)` | `write` tool: create or overwrite a file, creating parent directories. |
12
+ | `createEditTool(cwd, options?)` | `edit` tool: precise exact-then-fuzzy text replacement in an existing file. |
13
+ | `createCodingTools(cwd, options?)` | All four tools (`shell`, `read`, `write`, `edit`). |
14
+ | `createReadOnlyTools(cwd, options?)` | Read-only subset: `read` only. |
15
+ | `createAllTools(cwd, options?)` | Every tool the package provides (currently identical to `createCodingTools`). |
16
+ | `detectSupportedImageMimeType(buf)` / `detectSupportedImageMimeTypeFromFile(path)` | Magic-byte image MIME detection (PNG/JPEG/GIF/WebP/BMP) used by `read`. |
17
+ | `withFileMutationQueue(path, fn)` | Per-path serialization primitive re-exported for hosts. |
18
+
19
+ Each factory returns a plain `ToolDefinition` (no auto-registration). Register what you need:
20
+
21
+ ```ts
22
+ import { createToolRegistry } from "@arnilo/prism";
23
+ import { createCodingTools } from "@arnilo/prism-coding-agent";
24
+
25
+ const tools = createToolRegistry(createCodingTools(process.cwd()));
26
+ ```
27
+
28
+ ## When to use it
29
+
30
+ Use this package when a host wants ready-made coding tools for an agent, session, or run, registered explicitly into a `ToolRegistry` and dispatched through the normal Prism tool harness. The tools perform **real** shell and filesystem operations on the host — they are not mocked or sandboxed. Use the individual factories when you need per-tool options or custom operation backends; use the aggregators when you want the default set.
31
+
32
+ Do not use this package as a sandbox, permission policy, secret store, or provider loop. Prism gates tool dispatch with `PermissionPolicy` / `ToolValidator` / trust policies; the package performs no gating of its own. Do not register these tools for an untrusted provider.
33
+
34
+ ### pi name mapping
35
+
36
+ | Prism (`@arnilo/prism-coding-agent`) | pi coding agent |
37
+ | --- | --- |
38
+ | `shell` | `bash` |
39
+ | `read` | `read` |
40
+ | `write` | `write` |
41
+ | `edit` | `edit` |
42
+
43
+ ## Tools
44
+
45
+ ### `shell`
46
+
47
+ Run a shell command and return combined stdout+stderr.
48
+
49
+ **Inputs:**
50
+
51
+ | Field | Type | Purpose |
52
+ | --- | --- | --- |
53
+ | `command` | `string` | Shell command to execute (required). |
54
+ | `timeout` | `number` | Timeout in **seconds** (optional; no default). |
55
+
56
+ **Outputs:** a `ToolResult` whose `content[0]` is a `TextContent` with the combined output. Non-zero exit is **not** a tool error: it is returned as a normal result with `[Command exited with code N]` appended to the content and `exitCode` in metadata. Timeout and abort are error results that still carry the partial output captured so far.
57
+
58
+ `shell` result `metadata`:
59
+
60
+ | Field | Present when | Purpose |
61
+ | --- | --- | --- |
62
+ | `exitCode` | always | Process exit code, or `null` when the process was killed by timeout/abort. |
63
+ | `truncation` | always | `TruncationResult` from the bounded output accumulator. |
64
+ | `fullOutputPath?` | truncated only | Path to the spilled temp file holding the full output. |
65
+
66
+ Shell resolution honors `options.shellPath` → `SHELL` env → `/bin/bash` → `sh`, and the process group is killed on timeout/abort (`process.kill(-pid)` on Unix, `taskkill /F /T` on Windows).
67
+
68
+ ### `read`
69
+
70
+ Read a text or image file.
71
+
72
+ **Inputs:**
73
+
74
+ | Field | Type | Purpose |
75
+ | --- | --- | --- |
76
+ | `path` | `string` | Path to the file (relative or absolute; `~` and `file://` expanded). Required. |
77
+ | `offset` | `number` | Line to start reading from (1-indexed). |
78
+ | `limit` | `number` | Maximum number of lines to read. |
79
+
80
+ **Outputs:** text files become a single `TextContent`, truncated to `maxLines`/`maxBytes` (defaults 2000 lines / 50 KB) with a `Use offset=N to continue` footer when more remains. Image files (PNG/JPEG/GIF/WebP/BMP by magic bytes) become `[TextContent note, ImageContent]` with base64 `data` and `mimeType`. Read failures (missing file, offset beyond end, abort) are error results.
81
+
82
+ `read` result `metadata`:
83
+
84
+ | Field | Present when | Purpose |
85
+ | --- | --- | --- |
86
+ | `truncation` | text reads | `TruncationResult`. |
87
+ | `image` | image reads | `{ mimeType, resized: false }`. |
88
+
89
+ > `autoResizeImages` is accepted but is currently a documented no-op (deferred); images are returned at their original size with `image.resized = false`.
90
+
91
+ ### `write`
92
+
93
+ Create or overwrite a file, creating parent directories as needed.
94
+
95
+ **Inputs:**
96
+
97
+ | Field | Type | Purpose |
98
+ | --- | --- | --- |
99
+ | `path` | `string` | Path to the file to write (relative or absolute). Required. |
100
+ | `content` | `string` | Content to write (empty string creates an empty file). Required. |
101
+
102
+ **Outputs:** a `TextContent` confirmation naming the **absolute path** with UTF-8 byte and line counts (e.g. `Successfully wrote 42 bytes (3 lines) to /abs/path.txt`). Write failures and abort are error results. Empty `content` is valid.
103
+
104
+ `write` result `metadata`: `{ bytes, lines, path }` (absolute path). Concurrent writes to the same path serialize through `withFileMutationQueue`; writes to different paths run in parallel.
105
+
106
+ ### `edit`
107
+
108
+ Precise text replacement in an existing file via exact-then-fuzzy matching.
109
+
110
+ **Inputs:**
111
+
112
+ | Field | Type | Purpose |
113
+ | --- | --- | --- |
114
+ | `path` | `string` | Path to the file to edit. Required. |
115
+ | `edits` | `Array<{ oldText: string, newText: string }>` | Targeted replacements, each matched against the **original** file (not incrementally). No overlapping/nested edits. Required, non-empty. |
116
+
117
+ Each `edits[].oldText` must match a unique, non-overlapping region of the original file. Matching is exact first, then fuzzy (unicode normalization / whitespace collapse). A BOM is stripped before matching and re-prepended on write; original line endings are restored.
118
+
119
+ **Outputs:** a `TextContent` confirmation (`Successfully replaced N block(s) in {path}.`) plus `metadata`. Any failure — missing/unreadable file, no match, duplicate (non-unique) match, overlap, empty `oldText`, no-op edit, or abort — is an error result, and the file is left **unchanged** (the match runs before the write).
120
+
121
+ `edit` result `metadata`: `{ diff, patch, firstChangedLine }` — a display-oriented diff, a standard unified patch, and the first changed line in the new file. These are host-readable; the model only sees the short confirmation (keeps model context small).
122
+
123
+ ## Outputs / response / events
124
+
125
+ Every tool returns a `ToolResult` with `toolCallId`, `name`, `content` (`readonly ContentBlock[]`), optional `error`, and optional `metadata`. Mutating tools (`shell` with same cwd, `write`, `edit`) serialize per realpath through `withFileMutationQueue` so concurrent calls targeting one file do not interleave. The package emits no events of its own; hosts observe tool execution through the normal Prism `AgentEvent` stream via `dispatchToolCall`.
126
+
127
+ ## Request/response example
128
+
129
+ ```json
130
+ // edit request
131
+ { "path": "src/app.ts", "edits": [{ "oldText": "const x = 1;", "newText": "const x = 2;" }] }
132
+ ```
133
+
134
+ ```json
135
+ // edit success result
136
+ {
137
+ "toolCallId": "call_1",
138
+ "name": "edit",
139
+ "content": [{ "type": "text", "text": "Successfully replaced 1 block(s) in src/app.ts." }],
140
+ "metadata": { "diff": "...", "patch": "--- src/app.ts\n+++ src/app.ts\n...", "firstChangedLine": 3 }
141
+ }
142
+ ```
143
+
144
+ ```json
145
+ // edit no-match result (file unchanged)
146
+ {
147
+ "toolCallId": "call_2",
148
+ "name": "edit",
149
+ "error": { "message": "Could not find edits[0] in src/app.ts. The oldText must match exactly including all whitespace and newlines." }
150
+ }
151
+ ```
152
+
153
+ ## Implementation example
154
+
155
+ Minimal drop-in for any Prism app:
156
+
157
+ ```ts
158
+ import { createToolRegistry } from "@arnilo/prism";
159
+ import { createCodingTools, createReadOnlyTools } from "@arnilo/prism-coding-agent";
160
+
161
+ // Full coding set (shell + read + write + edit) against the project root:
162
+ const tools = createToolRegistry(createCodingTools(process.cwd()));
163
+
164
+ // Or a read-only set for inspection-only agents:
165
+ const ro = createToolRegistry(createReadOnlyTools(process.cwd()));
166
+ ```
167
+
168
+ Customizing a single tool (force bash, cap output, delegate writes to a remote backend):
169
+
170
+ ```ts
171
+ import { createShellTool, createWriteTool } from "@arnilo/prism-coding-agent";
172
+
173
+ const shell = createShellTool("/repo", {
174
+ shellPath: "/bin/bash",
175
+ commandPrefix: "set -euo pipefail",
176
+ maxLines: 500,
177
+ });
178
+
179
+ const remoteWrite = createWriteTool("/repo", {
180
+ operations: {
181
+ writeFile: async (abs, content) => { /* ship to remote */ },
182
+ mkdir: async (dir) => { /* mkdir -p remotely */ },
183
+ },
184
+ });
185
+ ```
186
+
187
+ ## Extension and configuration notes
188
+
189
+ - **Pluggable operation backends.** Every tool accepts an `operations` seam so a host can delegate to a remote system (e.g. SSH) while keeping the tool's matching/serialization behavior: `BashOperations` (`shell`), `ReadOperations` (`read`), `WriteOperations` (`write`), `EditOperations` (`edit`).
190
+ - **Per-tool options.** `ShellToolOptions` (`shellPath`, `commandPrefix`, `maxLines`, `maxBytes`, `tempFilePrefix`, `operations`, `spawnHook`); `ReadToolOptions` (`operations`, `autoResizeImages`, `maxLines`, `maxBytes`); `WriteToolOptions` (`operations`); `EditToolOptions` (`operations`).
191
+ - **Aggregator options.** `ToolsOptions` (`{ shell?, read?, write?, edit? }`) threads each sub-object to the matching tool.
192
+ - **`ToolsOptions`** and the per-tool option types are exported from the package barrel for host configuration.
193
+ - No auto-discovery or manifest registration: import and register explicitly. This package registers no extensions and owns no globals (the mutation queue is a process-wide per-path map — see `ponytail:` note in the source).
194
+
195
+ ## Security and performance notes
196
+
197
+ - **Host shell/filesystem access.** These tools run real commands and read/write real files. They provide **no sandbox**. Gate them with Prism `PermissionPolicy` / `ToolValidator` / trust policies before registering them for any provider turn. See [Host security guide](host-security.md) and [Security/auth/trust](settings-auth-trust-security.md).
198
+ - **Non-zero exit is not an error.** A failing command is a normal `shell` result (exit code in metadata); only timeout/abort/spawn failures are error results. Do not assume `error == undefined` means the command succeeded.
199
+ - **Bounded output.** `shell`/`read` accumulate output into a rolling tail bounded by `maxLines`/`maxBytes`; oversized output spills to a temp file (`fullOutputPath`), so memory use is bounded regardless of command output size.
200
+ - **Per-path serialization.** Concurrent mutations to the same file serialize; concurrent mutations to different files do not block each other. The queue is a process-wide map — across sessions in one process, same-path writes still serialize (upgrade path: scope per registry if throughput matters).
201
+ - **Single runtime dependency.** `diff` (for `edit` unified patch/diff generation) plus the Node standard library. No native modules; no image-processing native dependency (image auto-resize is deferred, so no `sharp`/WASM dependency).
202
+
203
+ ## Related APIs
204
+
205
+ - [Tools](tools.md): the host-owned tool harness — `createToolRegistry`, `dispatchToolCall`, filtering, and the `ToolDefinition` contract these factories satisfy.
206
+ - [Public contracts](public-contracts.md): `ToolDefinition`, `ToolResult`, `ToolExecutionContext`, `ContentBlock`, and `JsonObject` shapes.
207
+ - [Host security guide](host-security.md): fail-closed checklist for permission policies, tool validation, and trust boundaries that must gate these tools.
208
+ - [Tool conformance](tool-conformance.md): assertions for the tool-dispatch blocked-reason matrix these tools participate in.
package/docs/index.md CHANGED
@@ -42,6 +42,7 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
42
42
 
43
43
  ## Tools
44
44
  - [Tools](tools.md): register host-owned active tools with replace-or-error duplicate policy, apply exact allow/deny filtering, and dispatch tool calls.
45
+ - [Coding agent tools](coding-agent-tools.md): optional first-party package `@arnilo/prism-coding-agent` providing `shell`, `read`, `write`, and `edit` tools (ported from pi) as `ToolDefinition`s a host registers; pluggable operation backends, per-path mutation serialization, and read-only/coding aggregators. Host shell/filesystem access — gate with permission/trust policies.
45
46
 
46
47
  ## Extensions/plugins
47
48
  - [Contribution discovery (workspace)](contribution-discovery.md): opt-in, realpath-contained directory scanner turning `SKILL.md`/`manifest.json` into inert `DiscoveredContribution` envelopes the host registers — no `import()`, no auto-activate, no provider scanning. (Per-agent `AGENT.md` bundles live under an app-controlled `configRoot`; see [Agent definitions](agent-definitions.md).)
@@ -2,23 +2,24 @@
2
2
 
3
3
  ## What it does
4
4
 
5
- Prism is published as one core package plus eight first-party workspace packages and three umbrella convenience packages. This page describes how they are packed, what each tarball contains, how to install them, the required `@arnilo/prism` peer dependency, the release workflow, and the offline test budget.
5
+ Prism is published as one core package plus nine first-party workspace packages and three umbrella convenience packages. This page describes how they are packed, what each tarball contains, how to install them, the required `@arnilo/prism` peer dependency, the release workflow, and the offline test budget.
6
6
 
7
7
  Core package:
8
8
 
9
9
  - `@arnilo/prism` — the runtime, contracts, registries, streaming events, CLI, and the `/docs` hub. `files`: `dist` (with `!dist/__tests__` and `!dist/**/*.map` negations), `docs`, `CHANGELOG.md`. `bin`: `prism` -> `./dist/cli.js`. `sideEffects`: `["dist/cli.js"]`.
10
10
 
11
- First-party workspace packages (each `peerDependencies: { "@arnilo/prism": "0.0.2" }`, non-optional; `sideEffects: false`):
11
+ First-party workspace packages (each `peerDependencies: { "@arnilo/prism": "0.0.3" }`, non-optional; `sideEffects: false`):
12
12
 
13
13
  - `@arnilo/prism-provider-openai`, `@arnilo/prism-provider-openrouter`, `@arnilo/prism-provider-kimi`, `@arnilo/prism-provider-zai`, `@arnilo/prism-provider-opencode-go`, `@arnilo/prism-provider-neuralwatt` — provider adapters.
14
14
  - `@arnilo/prism-compaction-llm` — optional LLM-backed compaction strategy.
15
15
  - `@arnilo/prism-compaction-observational-memory` — optional source-backed observational memory.
16
+ - `@arnilo/prism-coding-agent` — optional host shell/filesystem coding tools (`shell`, `read`, `write`, `edit`). **Not included in `@arnilo/prism-all`** because these tools perform real host operations and must be opted into explicitly.
16
17
 
17
18
  Umbrella packages (pure manifests, no code, no `dist`; ship only `README.md`; use hard `dependencies` to transitively install their family):
18
19
 
19
20
  - `@arnilo/prism-providers` — depends on all 6 `@arnilo/prism-provider-*` packages.
20
21
  - `@arnilo/prism-compaction` — depends on both `@arnilo/prism-compaction-*` packages.
21
- - `@arnilo/prism-all` — depends on `@arnilo/prism` + `@arnilo/prism-providers` + `@arnilo/prism-compaction` (the full kit in one install).
22
+ - `@arnilo/prism-all` — depends on `@arnilo/prism` + `@arnilo/prism-providers` + `@arnilo/prism-compaction` (the full runtime/provider/compaction kit in one install). Does **not** include `@arnilo/prism-coding-agent`; install that separately.
22
23
 
23
24
  Each code package's `files` array is `["dist", "!dist/__tests__", "!dist/**/*.map", "README.md", "CHANGELOG.md"]`; `README.md`, `LICENSE`, and `CHANGELOG.md` ship in every code-package tarball, the core tarball also ships the `docs/` directory, and umbrella tarballs ship only `README.md` + `package.json`.
24
25
 
@@ -35,6 +36,7 @@ Consumers install the core package for the runtime and add first-party packages
35
36
  | Install core only | `npm install @arnilo/prism` |
36
37
  | Install core + all providers | `npm install @arnilo/prism @arnilo/prism-providers` |
37
38
  | Install core + compaction | `npm install @arnilo/prism @arnilo/prism-compaction` |
39
+ | Install core + coding tools (opt-in) | `npm install @arnilo/prism @arnilo/prism-coding-agent` |
38
40
  | Install everything (core + providers + compaction) | `npm install @arnilo/prism-all` |
39
41
  | Install core + a single provider | `npm install @arnilo/prism @arnilo/prism-provider-openai` |
40
42
  | Build everything (core + workspaces) | `npm run build` |
@@ -71,7 +73,7 @@ A packed tarball contains only public compiled output and release files:
71
73
  - `README.md`, `LICENSE`, `CHANGELOG.md` in every package.
72
74
  - The core tarball additionally ships the full `docs/` directory (the docs hub).
73
75
  - `dist/cli.js` and the `bin` link in core.
74
- - **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.0.2.tgz`; first-party packages produce `arnilo-prism-provider-<name>-0.0.2.tgz` / `arnilo-prism-compaction-<name>-0.0.2.tgz`; umbrella packages produce `arnilo-prism-providers-0.0.2.tgz` / `arnilo-prism-compaction-0.0.2.tgz` / `arnilo-prism-all-0.0.2.tgz`. The CLI bin name `prism` is unaffected by the package name (`npx prism` still works; npm allows the bin field to differ from the package name).
76
+ - **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.0.3.tgz`; first-party packages produce `arnilo-prism-provider-<name>-0.0.3.tgz` / `arnilo-prism-compaction-<name>-0.0.3.tgz` / `arnilo-prism-coding-agent-0.0.3.tgz`; umbrella packages produce `arnilo-prism-providers-0.0.3.tgz` / `arnilo-prism-compaction-0.0.3.tgz` / `arnilo-prism-all-0.0.3.tgz`. The CLI bin name `prism` is unaffected by the package name (`npx prism` still works; npm allows the bin field to differ from the package name).
75
77
 
76
78
  Excluded from every tarball by `files` negation:
77
79
 
@@ -88,9 +90,9 @@ Excluded from every tarball by `files` negation:
88
90
  "name": "host-app",
89
91
  "type": "module",
90
92
  "dependencies": {
91
- "@arnilo/prism": "0.0.2",
92
- "@arnilo/prism-provider-openai": "0.0.2",
93
- "@arnilo/prism-compaction-observational-memory": "0.0.2"
93
+ "@arnilo/prism": "0.0.3",
94
+ "@arnilo/prism-provider-openai": "0.0.3",
95
+ "@arnilo/prism-compaction-observational-memory": "0.0.3"
94
96
  }
95
97
  }
96
98
  ```
@@ -100,7 +102,7 @@ Installing the provider/compaction packages without `@arnilo/prism` present prod
100
102
  ```text
101
103
  npm error code ERESOLVE
102
104
  npm error Could not resolve dependency:
103
- npm error peer @arnilo/prism@"0.0.2" from @arnilo/prism-provider-openai@0.0.2
105
+ npm error peer @arnilo/prism@"0.0.3" from @arnilo/prism-provider-openai@0.0.3
104
106
  ```
105
107
 
106
108
  ## Implementation example
@@ -141,8 +143,8 @@ PRISM_LIVE_PROVIDER_TESTS=1 npm run test --workspaces --if-present
141
143
 
142
144
  ## Extension and configuration notes
143
145
 
144
- - **Required `@arnilo/prism` peer.** Every first-party package declares `peerDependencies: { "@arnilo/prism": "0.0.2" }` with no `peerDependenciesMeta` (non-optional). The range stays pinned to `0.0.2` for the 0.x series and will widen to `^1.0.0` at the 1.x stable release. Inside the workspace each package also declares `"@arnilo/prism": "file:../.."` in `devDependencies` so `npm install` resolves the peer locally; that devDependency is stripped from consumer installs and is not a runtime dependency.
145
- - **Public access.** All 12 manifests (9 code packages + 3 umbrellas) declare `"publishConfig": { "access": "public" }` so a manual `npm publish` of a scoped `@arnilo/prism-*` package defaults to public rather than `restricted` (paid). The `release.yml` flags (`npm publish --access public` + `npm publish --workspaces --access public`) are belt-and-suspenders backups.
146
+ - **Required `@arnilo/prism` peer.** Every first-party package declares `peerDependencies: { "@arnilo/prism": "0.0.3" }` with no `peerDependenciesMeta` (non-optional). The range stays pinned to `0.0.3` for the 0.x series and will widen to `^1.0.0` at the 1.x stable release. Inside the workspace each package also declares `"@arnilo/prism": "file:../.."` in `devDependencies` so `npm install` resolves the peer locally; that devDependency is stripped from consumer installs and is not a runtime dependency.
147
+ - **Public access.** All 13 manifests (10 code packages + 3 umbrellas) declare `"publishConfig": { "access": "public" }` so a manual `npm publish` of a scoped `@arnilo/prism-*` package defaults to public rather than `restricted` (paid). The `release.yml` flags (`npm publish --access public` + `npm publish --workspaces --access public`) are belt-and-suspenders backups.
146
148
  - **Map retention knob.** Source maps are emitted locally but stripped from tarballs by `!dist/**/*.map`. Removing that `files` negation ships maps in releases (larger tarballs, better consumer stack traces).
147
149
  - **Release workflow.** `.github/workflows/release.yml` has three jobs. `verify` runs the full SDK readiness gate on Node 24: `npm ci`, then `npm run sdk:ready` (`npm run typecheck`, network-free `npm test`, and `npm run pack:dry-run`). `node20-compat` runs on Node 20: `npm ci`, `npm run build`, then imports every public root `exports` default target from `dist/`. This proves the published package basics under the declared `engines.node >=20` without running docs examples, which require Node >=22.6 native TypeScript stripping. `publish` runs only on `refs/tags/v*` after both `verify` and `node20-compat` succeed: `npm run build`, then `npm publish --access public` for core (first, because packages require the `@arnilo/prism` peer on the registry) and `npm publish --workspaces --access public`. With no `NPM_TOKEN` secret it runs `--dry-run` instead of a real publish. `permissions.id-token: write` is set so `--provenance` can be added later without re-architecting permissions. Local `npm run release:dry-run` delegates to the same `npm run sdk:ready` gate.
148
150
  - **Adding a package.** New workspace packages are picked up automatically by `npm run build --workspaces`, `npm test --workspaces`, `npm run pack:dry-run`, the packaging guard (`src/__tests__/packaging.test.ts`), and the install-smoke test (`src/__tests__/install-smoke.test.ts`) via the workspace glob; add the package to both tests' config arrays for explicit per-package assertions.
package/docs/tools.md CHANGED
@@ -203,5 +203,6 @@ await session.run(input, { validate: (_t, args) => args.dry ? "dry-run blocked"
203
203
  - [Middleware hooks](middleware-hooks.md): `tool_call` and `tool_result` middleware used during dispatch.
204
204
  - [Credentials and redaction](credentials-and-redaction.md): redaction helpers used for tool execution errors.
205
205
  - [Observational memory compaction package](compaction-observational-memory.md): optional exact-id recall tool factory.
206
+ - [Coding agent tools](coding-agent-tools.md): optional first-party `@arnilo/prism-coding-agent` `shell`/`read`/`write`/`edit` tools a host registers into this harness.
206
207
 
207
208
  `DispatchToolCallOptions.permission` can provide a `PermissionPolicy`; denial emits `tool_execution_blocked` before validation or `execute()`. Middleware cannot bypass this guard. `AgentConfig.validator`/`RunOptions.validate` run after this guard; their output is redacted through the active `SecretRedactor`. Prism does not sandbox tools. See [Security/auth/trust](settings-auth-trust-security.md).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arnilo/prism",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Agent harness for AI providers, agents, sessions, and tools.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -80,6 +80,7 @@
80
80
  "workspaces": [
81
81
  "packages/provider-*",
82
82
  "packages/compaction-*",
83
+ "packages/coding-agent",
83
84
  "packages/prism-providers",
84
85
  "packages/prism-compaction",
85
86
  "packages/prism-all"