pi-neo-subagents 0.0.0-stage → 0.1.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 +59 -0
- package/LICENSE +21 -0
- package/README.md +332 -3
- package/index.ts +995 -0
- package/package.json +44 -6
- package/src/agents.ts +518 -0
- package/src/delegate.ts +342 -0
- package/src/dispatch.ts +236 -0
- package/src/ledger.ts +114 -0
- package/src/limits.ts +51 -0
- package/src/runner.ts +334 -0
- package/src/settings.ts +62 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project uses
|
|
5
|
+
[semantic versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [0.1.0] — 2026-10-24
|
|
8
|
+
|
|
9
|
+
First public release. Covers the v1 delegation core and the v2 governance work.
|
|
10
|
+
|
|
11
|
+
### Added — delegation core
|
|
12
|
+
|
|
13
|
+
- Named agent definitions as Markdown + frontmatter in `.pi/agents/` (project)
|
|
14
|
+
and `~/.pi/agent/agents/` (user), with project-over-user precedence.
|
|
15
|
+
- `task` tool for the main agent: isolated nested sessions, self-contained task
|
|
16
|
+
text only, final reply returned as the tool result.
|
|
17
|
+
- `/subagents` listing and detail views, and `/subagents run <name> [--to-context] <task>`
|
|
18
|
+
for user-invoked delegation whose result stays out of the model's context by
|
|
19
|
+
default.
|
|
20
|
+
- Definition enforcement: tool whitelists, model overrides, `systemPrompt: replace`.
|
|
21
|
+
- Result contract: 30,000-character truncation with the full result written to a
|
|
22
|
+
temp file, structured details, merged usage, coarse progress updates.
|
|
23
|
+
- Non-interactive output routing: stdout in print mode, stderr in JSON mode,
|
|
24
|
+
notifications in TUI and RPC.
|
|
25
|
+
- `create_subagent` tool and project-first placement, so a session with no
|
|
26
|
+
definitions is never a dead end.
|
|
27
|
+
|
|
28
|
+
### Added — governance and scale (v2)
|
|
29
|
+
|
|
30
|
+
- Execution controls: `maxTurns`, `timeoutMs`, `maxTokens`, and `thinking` in a
|
|
31
|
+
definition or per call; cut-short work is reported as a budget stop, never as
|
|
32
|
+
a failure.
|
|
33
|
+
- Run ledger with `/subagents stats` and `stats reset`.
|
|
34
|
+
- Fan-out dispatch (`tasks`) with a configurable concurrency cap, submission
|
|
35
|
+
order results, per-task status, and cancellation of everything in flight.
|
|
36
|
+
- Chained dispatch (`chain`) with `{previous}` substitution and stop-at-first-
|
|
37
|
+
unfinished-step semantics.
|
|
38
|
+
- Ad-hoc delegation with inline `instructions`, no definition file, accounted as
|
|
39
|
+
`ad-hoc`.
|
|
40
|
+
- Live TUI widget listing in-flight delegations with turn and current tool.
|
|
41
|
+
- Strict definition validation: non-`replace` `systemPrompt`, unknown tools,
|
|
42
|
+
unresolvable models, and invalid budgets are errors.
|
|
43
|
+
- Discovery from nested working directories; listings show source file and
|
|
44
|
+
modification time.
|
|
45
|
+
- Managed definitions: `/subagents new`, `edit`, `rm`.
|
|
46
|
+
- Authorization: project-level agents require first-use consent, plus settings
|
|
47
|
+
`confirmProjectAgents`, `allowModelCreatedDefinitions`,
|
|
48
|
+
`allowUserScopeCreation`, and `maxDepth`.
|
|
49
|
+
- Controlled recursion: opt-in `allowSubagents`, depth-bounded, with depth
|
|
50
|
+
reported in results and the ledger.
|
|
51
|
+
- Hermetic test suite (112 tests) over a single session seam, plus an
|
|
52
|
+
environment-gated live-model smoke suite (`npm run test:live`).
|
|
53
|
+
|
|
54
|
+
### Notes
|
|
55
|
+
|
|
56
|
+
- Delegation is serial per call unless `tasks` is used; nesting requires an
|
|
57
|
+
explicit opt-in.
|
|
58
|
+
- `@earendil-works/pi-ai` and `@earendil-works/pi-coding-agent` are host-provided
|
|
59
|
+
and declared as `peerDependencies` with a `*` range.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 灰木同学
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,332 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
# pi-neo-subagents
|
|
2
|
+
|
|
3
|
+
Subagents for [Pi](https://github.com/earendil-works/pi): define named specialist
|
|
4
|
+
agents as Markdown files, then let the main agent delegate self-contained tasks
|
|
5
|
+
to them — or run them yourself. Each delegation runs in an isolated nested
|
|
6
|
+
session with its own conversation, so your main context stays small and focused.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pi install npm:pi-neo-subagents
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
- **Delegate**: a `task` tool the main agent calls, single / fan-out / chained,
|
|
13
|
+
with per-run budgets and a run ledger.
|
|
14
|
+
- **Define**: Markdown definitions with tool whitelists, model overrides, and an
|
|
15
|
+
opt-in for controlled recursion — project-first, reviewable in your repo.
|
|
16
|
+
- **Run**: `/subagents list|run|new|edit|rm|stats` for doing it yourself.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
From npm:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pi install npm:pi-neo-subagents # user-level
|
|
24
|
+
pi install npm:pi-neo-subagents -l # project-level (needs project trust)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
From a directory or a single file (TypeScript, no build step):
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pi install /path/to/pi-neo-subagents
|
|
31
|
+
pi --extension /path/to/pi-neo-subagents/index.ts
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Project-level installs land in `.pi/settings.json`, which Pi only honours after
|
|
35
|
+
project trust is granted — start Pi with `--approve` (or trust the project
|
|
36
|
+
interactively) or the package will appear to be ignored. It can also live under
|
|
37
|
+
`~/.pi/agent/extensions/` or `<project>/.pi/extensions/` for discovery.
|
|
38
|
+
|
|
39
|
+
To publish to npm, remove `"private": true` from `package.json` and add the
|
|
40
|
+
`pi-package` keyword; the `pi.extensions` manifest is already declared.
|
|
41
|
+
|
|
42
|
+
## Agent definitions
|
|
43
|
+
|
|
44
|
+
Definitions are Markdown files with YAML-style frontmatter in two resource
|
|
45
|
+
directories:
|
|
46
|
+
|
|
47
|
+
- project-level: `.pi/agents/*.md` (wins on a name collision, labelled in listings).
|
|
48
|
+
Discovery walks up from the working directory to the nearest `.pi/agents`, so
|
|
49
|
+
running Pi inside a subdirectory still finds the repository's agents.
|
|
50
|
+
- user-level: `~/.pi/agent/agents/*.md`
|
|
51
|
+
|
|
52
|
+
```markdown
|
|
53
|
+
---
|
|
54
|
+
description: Reviews code changes
|
|
55
|
+
tools: read, grep
|
|
56
|
+
model: anthropic/claude-sonnet-4-5
|
|
57
|
+
systemPrompt: replace
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
You are a careful code reviewer. Always cite the file you reviewed.
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
| Field | Meaning | Default |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| `name` | Canonical agent name | the file's stem |
|
|
66
|
+
| `description` | One-line description used for delegation discovery | required |
|
|
67
|
+
| `tools` | Whitelist of tool names for the subagent | all default tools |
|
|
68
|
+
| `model` | Model to run on (`provider/id` or bare id) | inherit the host session's model |
|
|
69
|
+
| `systemPrompt` | `replace` makes the body the entire system prompt | append to Pi's default prompt |
|
|
70
|
+
| `maxTurns` | Cap on assistant turns for one delegation | unbounded |
|
|
71
|
+
| `timeoutMs` | Wall-clock cap in milliseconds | unbounded |
|
|
72
|
+
| `maxTokens` | Cap on total tokens for one delegation | unbounded |
|
|
73
|
+
| `thinking` | Thinking level (`minimal`, `low`, `medium`, `high`, `xhigh`, `max`) | inherit |
|
|
74
|
+
| `allowSubagents` | `true` lets this agent delegate further with the `task` tool | `false` |
|
|
75
|
+
|
|
76
|
+
Frontmatter accepts both `tools: read, grep` and YAML block lists:
|
|
77
|
+
|
|
78
|
+
```markdown
|
|
79
|
+
tools:
|
|
80
|
+
- read
|
|
81
|
+
- grep
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Quoted values and trailing `# comments` are handled. Definition mistakes fail
|
|
85
|
+
loudly instead of silently changing behaviour:
|
|
86
|
+
|
|
87
|
+
- `tools:` present but empty → error (it used to mean "all default tools")
|
|
88
|
+
- an unterminated quoted value → error
|
|
89
|
+
- a `systemPrompt` value other than `replace` → error (omitting it still means append)
|
|
90
|
+
- at creation time: an unregistered tool name, an unresolvable model, an
|
|
91
|
+
invalid budget, or the `task` tool (subagents never delegate further) → error
|
|
92
|
+
- two definitions with the same `name` in one directory → the later file is
|
|
93
|
+
rejected with a duplicate-name error
|
|
94
|
+
|
|
95
|
+
The Markdown body is the agent's specialization instructions.
|
|
96
|
+
|
|
97
|
+
## Creating definitions
|
|
98
|
+
|
|
99
|
+
You can write definition files by hand, or let the agent do it. The
|
|
100
|
+
`create_subagent` tool takes `{ name, description, instructions, tools?, model?,
|
|
101
|
+
scope?, overwrite? }` and owns the file format and location:
|
|
102
|
+
|
|
103
|
+
- **`scope: "project"` (default)** → `<cwd>/.pi/agents/<name>.md`, so the
|
|
104
|
+
definition travels with the repository and can be reviewed and committed.
|
|
105
|
+
- `scope: "user"` → `~/.pi/agent/agents/<name>.md`, only when explicitly asked.
|
|
106
|
+
- Existing definitions are never replaced unless `overwrite: true`; names that
|
|
107
|
+
would escape the agents directory are rejected; the generated file is
|
|
108
|
+
validated before it is written.
|
|
109
|
+
- A newly created definition is delegable immediately in the same session.
|
|
110
|
+
|
|
111
|
+
Asking for "one subagent reviews the pending diff, one scans the repo for TODOs"
|
|
112
|
+
in a project with no definitions therefore produces `reviewer.md` and
|
|
113
|
+
`scout.md` **inside the project**, not in your global config.
|
|
114
|
+
|
|
115
|
+
## Budgets
|
|
116
|
+
|
|
117
|
+
A delegation can be capped by turns, wall-clock time, and tokens — in the
|
|
118
|
+
definition, or per call (a per-call value wins):
|
|
119
|
+
|
|
120
|
+
```jsonc
|
|
121
|
+
// task tool call
|
|
122
|
+
{ "agent": "scout", "task": "…", "maxTurns": 3, "timeoutMs": 60000, "thinking": "low" }
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Hitting a cap is a first-class outcome, not a failure: the subagent's reply so
|
|
126
|
+
far comes back with a note naming the budget that tripped, for example
|
|
127
|
+
`[Budget stop: turns limit 1 reached (observed 1). Partial reply above.]`.
|
|
128
|
+
Cut-short work stays distinguishable from a failed delegation, and the usage
|
|
129
|
+
footer still reports what it cost.
|
|
130
|
+
|
|
131
|
+
## Delegate from the main agent
|
|
132
|
+
|
|
133
|
+
The `task` tool lists every available agent in its description, names both
|
|
134
|
+
definition directories, and says project definitions are preferred. The main
|
|
135
|
+
agent delegates with a **self-contained** task description — the subagent sees the task
|
|
136
|
+
text only, never the host conversation. Its final reply comes back as the tool
|
|
137
|
+
result (oversized replies are truncated at 30,000 characters with the full
|
|
138
|
+
result written to a temp file).
|
|
139
|
+
|
|
140
|
+
### Fan-out
|
|
141
|
+
|
|
142
|
+
One call can dispatch several tasks concurrently:
|
|
143
|
+
|
|
144
|
+
```jsonc
|
|
145
|
+
{ "tasks": [
|
|
146
|
+
{ "agent": "reviewer", "task": "Review the diff of src/ for bugs" },
|
|
147
|
+
{ "agent": "scout", "task": "Find every TODO under src/", "maxTurns": 4 }
|
|
148
|
+
] }
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
- Results come back **in submission order**, each as its own block with its
|
|
152
|
+
status (`ok`, `budget stop (…)`, `failed`) and details.
|
|
153
|
+
- One failing task does not cancel its siblings; the call is an error only when
|
|
154
|
+
every task failed.
|
|
155
|
+
- Concurrency is capped at 4 by default; set
|
|
156
|
+
`PI_NEO_SUBAGENTS_MAX_CONCURRENCY=<n>` to change it.
|
|
157
|
+
- Cancelling the call cancels every in-flight task.
|
|
158
|
+
- A single `{ agent, task }` call behaves exactly as before.
|
|
159
|
+
- In the TUI, a widget lists every in-flight delegation with its current turn
|
|
160
|
+
and tool, and clears when the dispatch settles. Other modes never show it.
|
|
161
|
+
|
|
162
|
+
### One-off work, without a definition
|
|
163
|
+
|
|
164
|
+
For work you will not reuse, an entry can carry inline instructions instead of an
|
|
165
|
+
agent name:
|
|
166
|
+
|
|
167
|
+
```jsonc
|
|
168
|
+
{ "instructions": "You read one file and summarize it in three bullets.",
|
|
169
|
+
"tools": ["read"],
|
|
170
|
+
"task": "Summarize docs/specs/subagents.md" }
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
- Nothing is written to disk and nothing appears in `/subagents`; the run is
|
|
174
|
+
still counted in `/subagents stats` under the fixed label `ad-hoc`.
|
|
175
|
+
- Inline entries accept the same `model`, budget, and `tools` options as a
|
|
176
|
+
definition, work in single, fan-out, and chain dispatch, and can never spawn
|
|
177
|
+
further subagents.
|
|
178
|
+
|
|
179
|
+
### Controlled recursion
|
|
180
|
+
|
|
181
|
+
By default a subagent cannot delegate further. A definition can opt in:
|
|
182
|
+
|
|
183
|
+
```markdown
|
|
184
|
+
---
|
|
185
|
+
description: Plans work and delegates the parts
|
|
186
|
+
allowSubagents: true
|
|
187
|
+
tools: read, task
|
|
188
|
+
---
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Opted-in agents receive the `task` tool in their nested session, and a depth
|
|
192
|
+
limit bounds the tree (`subagents.maxDepth`, default 2 — a top-level delegation
|
|
193
|
+
is depth 1). Exceeding it fails that call with the limit and the attempted
|
|
194
|
+
depth. Every result carries `details.depth`, and the ledger shows the deepest
|
|
195
|
+
level each agent ran at.
|
|
196
|
+
|
|
197
|
+
### Chains
|
|
198
|
+
|
|
199
|
+
Steps can run in order, each able to consume the previous reply — a
|
|
200
|
+
review-then-fix pipeline, for example:
|
|
201
|
+
|
|
202
|
+
```jsonc
|
|
203
|
+
{ "chain": [
|
|
204
|
+
{ "agent": "reviewer", "task": "Review src/runner.ts and list the problems" },
|
|
205
|
+
{ "agent": "fixer", "task": "Fix exactly these problems, nothing else: {previous}" }
|
|
206
|
+
] }
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
- `{previous}` is replaced with the previous step's reply; using it in the first
|
|
210
|
+
step is rejected before anything runs.
|
|
211
|
+
- A chain stops at the first step that fails **or is cut short by a budget**;
|
|
212
|
+
remaining steps are reported as `skipped`, and the result names every step's
|
|
213
|
+
status.
|
|
214
|
+
- A chain is strictly sequential, so the fan-out cap does not apply.
|
|
215
|
+
|
|
216
|
+
Delegation is one level deep by default: the `task` tool is never available to
|
|
217
|
+
subagents themselves. Nested sessions also load no extensions, skills, prompt
|
|
218
|
+
templates, or themes, so a subagent's prompt is its definition plus the task —
|
|
219
|
+
never the host's skill index.
|
|
220
|
+
|
|
221
|
+
## Run directly
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
/subagents # list all definitions
|
|
225
|
+
/subagents <name> # show one definition
|
|
226
|
+
/subagents run <name> <task> # run one; result shown to you only
|
|
227
|
+
/subagents run --to-context <name> <task> # also send the result into the model's context
|
|
228
|
+
/subagents run "code review" <task> # quote names that contain spaces
|
|
229
|
+
/subagents run -- <name> <task> # anything after -- is taken literally
|
|
230
|
+
/subagents new <name> [description] [--force] # scaffold a definition in the resolved project dir
|
|
231
|
+
/subagents edit <name> # open the resolved file; invalid edits are not saved
|
|
232
|
+
/subagents rm <name> [--yes] # delete after confirmation (--yes for scripts)
|
|
233
|
+
/subagents stats # per-agent runs, turns, tokens, cost, average time
|
|
234
|
+
/subagents stats reset # clear this session's ledger
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
The ledger is per session and accounts for every delegation — single, fan-out,
|
|
238
|
+
and chain steps — counting successes, failures, and budget stops separately:
|
|
239
|
+
|
|
240
|
+
```
|
|
241
|
+
Delegation ledger (this session):
|
|
242
|
+
- reviewer: 1 run (1 ok, 0 failed, 0 budget stops) · 3 turns · tokens 647 in / 410 out · $0.000718 · avg 4616ms
|
|
243
|
+
- scout: 1 run (1 ok, 0 failed, 0 budget stops) · 2 turns · tokens 421 in / 221 out · $0.000411 · avg 2475ms
|
|
244
|
+
Total: 2 runs · $0.001130
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Options are parsed only before the name, so `--to-context` inside a task stays
|
|
248
|
+
part of the task text. Unknown options are rejected with the usage line.
|
|
249
|
+
|
|
250
|
+
Direct runs report a one-line usage summary (model, turns, tokens, cost). Long
|
|
251
|
+
results are shortened for display and the full text is written to a temp file
|
|
252
|
+
named in the notice.
|
|
253
|
+
|
|
254
|
+
### Output channels
|
|
255
|
+
|
|
256
|
+
| Mode | Where command output goes |
|
|
257
|
+
|---|---|
|
|
258
|
+
| TUI | notification |
|
|
259
|
+
| RPC | `extension_ui_request` notification |
|
|
260
|
+
| `--print` | stdout |
|
|
261
|
+
| `--mode json` | stderr (stdout is the JSON event stream) |
|
|
262
|
+
|
|
263
|
+
Progress for a long direct run appears as a status line (`<agent> · turn N`) and
|
|
264
|
+
is cleared when the run finishes.
|
|
265
|
+
|
|
266
|
+
## Windows / Git Bash
|
|
267
|
+
|
|
268
|
+
MSYS rewrites arguments that start with `/`, so passing a slash command on the
|
|
269
|
+
command line (`pi -p "/subagents"`) reaches Pi as
|
|
270
|
+
`D:/Program Files/Git/subagents`. Quote it differently or disable the rewrite for
|
|
271
|
+
that argument:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
MSYS2_ARG_CONV_EXCL='/subagents' pi -p "/subagents"
|
|
275
|
+
pi -p "//subagents" # MSYS strips one slash
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
This does not affect typing commands inside the Pi TUI, RPC clients, cmd.exe, or
|
|
279
|
+
PowerShell.
|
|
280
|
+
|
|
281
|
+
## Settings
|
|
282
|
+
|
|
283
|
+
Optional settings live under the `subagents` key of Pi's settings (global
|
|
284
|
+
`~/.pi/agent/settings.json` or project `.pi/settings.json`):
|
|
285
|
+
|
|
286
|
+
```json
|
|
287
|
+
{
|
|
288
|
+
"subagents": {
|
|
289
|
+
"confirmProjectAgents": "ask",
|
|
290
|
+
"allowModelCreatedDefinitions": true,
|
|
291
|
+
"allowUserScopeCreation": false,
|
|
292
|
+
"maxDepth": 2
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
| Setting | Meaning | Default |
|
|
298
|
+
|---|---|---|
|
|
299
|
+
| `confirmProjectAgents` | `"ask"`, `"allow"`, or `"deny"`: whether a project-level agent needs consent before its first use in a session | `"ask"` |
|
|
300
|
+
| `allowModelCreatedDefinitions` | whether the model may author definitions with `create_subagent` | `true` |
|
|
301
|
+
| `allowUserScopeCreation` | whether definitions may be written to the user-level directory | `false` |
|
|
302
|
+
| `maxDepth` | delegation depth limit (reserved for controlled recursion) | `2` |
|
|
303
|
+
|
|
304
|
+
Consent is remembered per agent for the session, and a denial runs nothing.
|
|
305
|
+
User-level agents and ad-hoc entries never prompt. In a session without a
|
|
306
|
+
dialog UI, `"ask"` proceeds (automation never hangs) while `"deny"` refuses.
|
|
307
|
+
|
|
308
|
+
## Development
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
npm install
|
|
312
|
+
npm test # vitest, hermetic: scripted fake model, no network
|
|
313
|
+
npm run typecheck
|
|
314
|
+
npm run test:live # live-model smoke suite (real provider, real cost)
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
`npm test` is offline and never needs credentials. The live suite is excluded
|
|
318
|
+
from it and runs only through `npm run test:live`, which enables it with
|
|
319
|
+
`PI_NEO_SUBAGENTS_LIVE=1`:
|
|
320
|
+
|
|
321
|
+
- It uses the credentials Pi already has, so run `pi auth` first if needed.
|
|
322
|
+
- `PI_NEO_SUBAGENTS_LIVE_MODEL=provider/model` picks the model (default
|
|
323
|
+
`deepseek/deepseek-flash`).
|
|
324
|
+
- A missing model or provider fails loudly with instructions instead of
|
|
325
|
+
skipping, so a green run always means the real path worked.
|
|
326
|
+
- A full run costs roughly 25 seconds and a few thousand tokens: it creates two
|
|
327
|
+
definitions in a temp project, fans out to them, checks the files and the
|
|
328
|
+
ledger, and delegates one ad-hoc task to prove no definition is created.
|
|
329
|
+
|
|
330
|
+
Tests drive full in-memory agent sessions through the Pi SDK with pi-ai's
|
|
331
|
+
`fauxProvider` as the scripted model; behaviour is asserted only at the
|
|
332
|
+
session boundary (tool results, visible messages, recorded UI output).
|