@bacnh85/pi-subagent 0.15.2 → 0.16.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 +31 -0
- package/README.md +53 -14
- package/agent-format.md +22 -6
- package/agents/general-purpose.md +1 -5
- package/agents/planner.md +1 -4
- package/agents/reviewer.md +1 -4
- package/agents/scout.md +1 -4
- package/agents/tester.md +1 -4
- package/agents/worker.md +1 -5
- package/extensions/agents.ts +2 -0
- package/extensions/background.ts +13 -0
- package/extensions/history.ts +5 -2
- package/extensions/index.ts +214 -125
- package/extensions/model.ts +94 -8
- package/extensions/roles-panel.ts +154 -0
- package/extensions/roles.ts +263 -0
- package/extensions/runner.ts +9 -3
- package/extensions/security.ts +87 -3
- package/extensions/service.ts +56 -71
- package/package.json +13 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.16.0 (2026-08-23)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- **Role-based model routing** — select models by *function* instead of fixed
|
|
8
|
+
per-agent chains, inspired by oh-my-pi's `modelRoles`. Roles (`@fast`,
|
|
9
|
+
`@coder`, `@smart`, or custom) map functions to ordered fallback chains via
|
|
10
|
+
`subagent.roles` in `~/.pi/agent/settings.json`; bundled agents now reference
|
|
11
|
+
roles instead of hardcoding chains. Without settings, defaults reproduce the
|
|
12
|
+
previous chains exactly.
|
|
13
|
+
- `subagent.agentModels` per-agent overrides — remap a bundled agent's models
|
|
14
|
+
(e.g. `{ "reviewer": "@smart:high" }`) without editing its file. Repo
|
|
15
|
+
`.pi/settings.json` overlays the mapping for trusted projects (read-only).
|
|
16
|
+
- `:thinking` suffix support on any role/model entry (`"@smart:high"`);
|
|
17
|
+
openrouter `:free` ids are preserved.
|
|
18
|
+
- `/subagent roles` — interactive role editor (TUI panel via the shared
|
|
19
|
+
`@bacnh85/pi-config-panel` kernel, saves to global settings.json) or plain
|
|
20
|
+
text mapping in headless mode.
|
|
21
|
+
- Bare `/subagent` now opens the roles view directly (the agent list moved to
|
|
22
|
+
`/subagent list`); `/subagent <role>` / `/subagent @role` shows a role's
|
|
23
|
+
chain, default, and the agents using it instead of erroring.
|
|
24
|
+
- `/subagent <name>` and the system-prompt catalog now show each agent's
|
|
25
|
+
*resolved* chain (role → models → parent fallback) plus unresolved-role
|
|
26
|
+
warnings.
|
|
27
|
+
|
|
28
|
+
## 0.15.3 (2026-08-20)
|
|
29
|
+
### Improvements
|
|
30
|
+
- Timeouts have been extracted as Environment Variables enabling overriding.
|
|
31
|
+
- `PI_SUBAGENT_INACTIVITY_TIMEOUT_MINS` default : 3 Mins
|
|
32
|
+
- `PI_SUBAGENT_HARD_TIMEOUT_MINS` default: 20 Mins
|
|
33
|
+
|
|
3
34
|
## 0.15.2 (2026-08-18)
|
|
4
35
|
|
|
5
36
|
### Improvements
|
package/README.md
CHANGED
|
@@ -2,6 +2,42 @@
|
|
|
2
2
|
|
|
3
3
|
Isolated in-process subagents for Pi. The `subagent` tool supports single, parallel (8 tasks, 4 concurrent), and chained execution; `/agent` opens inspectable child threads. A live progress widget shows running tasks above the editor; `background: true` runs detached with follow-up-turn completion.
|
|
4
4
|
|
|
5
|
+
## Role-based model routing
|
|
6
|
+
|
|
7
|
+
Models are selected **by function**, not fixed per agent. A *role* maps a
|
|
8
|
+
function (`fast`, `coder`, `smart`, or your own) to an ordered fallback chain
|
|
9
|
+
in `~/.pi/agent/settings.json` under `subagent.roles`:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"subagent": {
|
|
14
|
+
"roles": {
|
|
15
|
+
"fast": ["zai-coding-cn/glm-5-turbo", "nvidia/openai/gpt-oss-20b", "opencode-go/deepseek-v4-flash"],
|
|
16
|
+
"coder": "zai-coding-cn/glm-5.1, opencode-go/deepseek-v4-flash",
|
|
17
|
+
"smart": "*"
|
|
18
|
+
},
|
|
19
|
+
"agentModels": { "reviewer": "@smart:high" }
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- Bundled agents reference roles in frontmatter (`model: "@fast"`) — remap a
|
|
25
|
+
function once and every agent using it follows.
|
|
26
|
+
- Role values: string (comma chain) or array. `*` / `@default` = parent model.
|
|
27
|
+
- A trailing `:level` (`off|minimal|low|medium|high|xhigh|max`) on any entry
|
|
28
|
+
overrides the agent's thinking for that match (`"@smart:high"`); openrouter
|
|
29
|
+
`:free` ids are left intact.
|
|
30
|
+
- `subagent.agentModels` overrides a single agent's models without editing its
|
|
31
|
+
file. Repo `.pi/settings.json` overlays the global mapping when the project
|
|
32
|
+
is trusted (read-only; saves go to the global file).
|
|
33
|
+
- Without any settings, bundled defaults reproduce today's chains exactly.
|
|
34
|
+
|
|
35
|
+
`/subagent` opens the interactive role editor (TUI panel via the shared
|
|
36
|
+
`@bacnh85/pi-config-panel` kernel; prints the effective mapping headless).
|
|
37
|
+
`/subagent list` lists agents, `/subagent <name>` shows an agent's resolved
|
|
38
|
+
chain, and `/subagent @role` (or `/subagent fast`) shows a role's chain and
|
|
39
|
+
the agents using it.
|
|
40
|
+
|
|
5
41
|
## Live progress widget
|
|
6
42
|
|
|
7
43
|
When subagents run, a persistent widget appears above the editor showing each
|
|
@@ -45,14 +81,16 @@ Requires Node.js >= 20.18.
|
|
|
45
81
|
|
|
46
82
|
## Bundled roles
|
|
47
83
|
|
|
48
|
-
| Role |
|
|
84
|
+
| Role | Model role | Thinking | Tools |
|
|
49
85
|
| --- | --- | --- | --- |
|
|
50
|
-
| `scout` | `
|
|
51
|
-
| `tester` | `
|
|
52
|
-
| `worker` | `
|
|
53
|
-
| `general-purpose` | `
|
|
54
|
-
| `planner` | `
|
|
55
|
-
| `reviewer` | `
|
|
86
|
+
| `scout` | `@fast` | off | read, grep, find, ls |
|
|
87
|
+
| `tester` | `@fast` | off | read, bash, grep, find, ls |
|
|
88
|
+
| `worker` | `@coder` | medium | **inherits all parent tools** |
|
|
89
|
+
| `general-purpose` | `@coder` | medium | **inherits all parent tools** |
|
|
90
|
+
| `planner` | `@smart` | high | read, grep, find, ls |
|
|
91
|
+
| `reviewer` | `@smart` | high | read, grep, find, ls |
|
|
92
|
+
|
|
93
|
+
Default role chains (overridable via `subagent.roles` in settings.json — see above):
|
|
56
94
|
|
|
57
95
|
Each role uses the first authenticated preference available through Pi's model registry, then falls back to the authenticated parent model. Chains are **free-first** to conserve the metered opencode-go budget: **zai-coding-cn** (free GLM, primary) → free **nvidia** NIM and **openrouter** `:free` models → **opencode-go** (paid DeepSeek, last resort — one per role: `deepseek-v4-flash` for fast/strong-coding, `deepseek-v4-pro` for deep reasoning). opencode-go's GLM models cost ~$1.40/$4.40 per M versus zai-coding-cn's free GLM, so GLM stays on zai-coding-cn. Fallback models were live-verified on 2026-07-24; `nvidia/moonshotai/kimi-k2.6` and `nvidia/z-ai/glm-5.2` return 404/timeout on the user's account and were removed — non-rate-limit failures kill the subagent instead of advancing the chain. User/project agent files remain stronger overrides and may set legacy `model`, ordered `models`, and `thinking`.
|
|
58
96
|
|
|
@@ -140,8 +178,8 @@ each writes into its own checkout.
|
|
|
140
178
|
|
|
141
179
|
Every child execution receives a timeout:
|
|
142
180
|
|
|
143
|
-
- **Default inactivity window:** 3 minutes (`DEFAULT_TIMEOUT_MS`); real SDK lifecycle activity resets it.
|
|
144
|
-
- **Absolute cap:** 20 minutes for every child, even when active.
|
|
181
|
+
- **Default inactivity window:** 3 minutes (`DEFAULT_TIMEOUT_MS`); real SDK lifecycle activity resets it. Overridable with Environment Variable `PI_SUBAGENT_INACTIVITY_TIMEOUT_MINS`
|
|
182
|
+
- **Absolute cap:** Default 20 minutes for every child, even when active. Overridable with Environment variable `PI_SUBAGENT_HARD_TIMEOUT_MINS`
|
|
145
183
|
- **Maximum requested inactivity window:** 60 minutes (`MAX_TIMEOUT_MS`); values must be positive integers.
|
|
146
184
|
- Timeout diagnostics distinguish `Idle timeout` from `Hard timeout` and parent cancellation.
|
|
147
185
|
- 30-second progress heartbeats only keep the parent transport alive; they never reset inactivity.
|
|
@@ -211,7 +249,8 @@ The raw `stopReason` from the Pi SDK is preserved in the result.
|
|
|
211
249
|
|
|
212
250
|
## Timeout and cancellation
|
|
213
251
|
|
|
214
|
-
- **Default
|
|
252
|
+
- **Default inactivity window:** 3 minutes per child (`PI_SUBAGENT_INACTIVITY_TIMEOUT_MINS`, range 1–60).
|
|
253
|
+
- **Absolute cap:** 20 minutes per child, even when active (`PI_SUBAGENT_HARD_TIMEOUT_MINS`, range 1–60). See *Timeouts* above.
|
|
215
254
|
- **Per-task/step override:** Use `timeout` in task/step params.
|
|
216
255
|
- **Parent cancellation:** Aborting the parent tool call cancels all children.
|
|
217
256
|
- **Sibling cancellation:** In parallel mode with `abortOnFailure: true`, the first failed task cancels running siblings.
|
|
@@ -229,10 +268,10 @@ See [CHANGELOG.md](CHANGELOG.md) for release history.
|
|
|
229
268
|
|
|
230
269
|
## Compatibility
|
|
231
270
|
|
|
232
|
-
- Requires `@earendil-works/pi-coding-agent >=0.80.0 <0.
|
|
233
|
-
- Requires `@earendil-works/pi-ai >=0.80.0 <0.
|
|
234
|
-
- Requires `@earendil-works/pi-agent-core >=0.80.0 <0.
|
|
235
|
-
- Requires `@earendil-works/pi-tui >=0.80.0 <0.
|
|
271
|
+
- Requires `@earendil-works/pi-coding-agent >=0.80.0 <0.85.0`
|
|
272
|
+
- Requires `@earendil-works/pi-ai >=0.80.0 <0.85.0`
|
|
273
|
+
- Requires `@earendil-works/pi-agent-core >=0.80.0 <0.85.0`
|
|
274
|
+
- Requires `@earendil-works/pi-tui >=0.80.0 <0.85.0`
|
|
236
275
|
- Requires `typebox >=1.3.0 <2.0.0`
|
|
237
276
|
- Requires Node.js >= 20.18
|
|
238
277
|
|
package/agent-format.md
CHANGED
|
@@ -19,9 +19,9 @@ Project agents override user agents with the same name when `agentScope: "both"`
|
|
|
19
19
|
name: my-agent # Required. Unique identifier (kebab-case).
|
|
20
20
|
description: ... # Required. When to use this agent.
|
|
21
21
|
tools: read, grep, ... # Optional. Comma-separated tool names. Defaults to all.
|
|
22
|
-
model:
|
|
22
|
+
model: "@fast" # Optional. Role alias (quoted — @ is YAML-reserved) or provider/model.
|
|
23
23
|
models: # Optional ordered fallbacks; comma form also accepted.
|
|
24
|
-
-
|
|
24
|
+
- "@fast"
|
|
25
25
|
- provider/backup-model
|
|
26
26
|
thinking: low # Optional: off|minimal|low|medium|high|xhigh|max.
|
|
27
27
|
sandbox: read-only # Optional: read-only | workspace-write | worktree. Auto-derives tool restrictions.
|
|
@@ -29,9 +29,18 @@ color: cyan # Optional: red|blue|green|yellow|purple|orange|pink|c
|
|
|
29
29
|
---
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
+
### Model roles
|
|
33
|
+
|
|
34
|
+
`model`/`models` entries may reference *roles* instead of concrete models:
|
|
35
|
+
`"@fast"`, `"@coder"`, `"@smart"`, or any role defined under
|
|
36
|
+
`subagent.roles` in `~/.pi/agent/settings.json`. A role expands to an ordered
|
|
37
|
+
fallback chain (string with commas, or array). `"*"` / `"@default"` mean
|
|
38
|
+
"use the parent model". A trailing `:level` (`"@smart:high"`) overrides the
|
|
39
|
+
agent's `thinking` for that match. See README → *Role-based model routing*.
|
|
40
|
+
|
|
32
41
|
### `sandbox`
|
|
33
42
|
|
|
34
|
-
- `read-only`: Restricts tools to `read`, `grep`, `find`, `ls
|
|
43
|
+
- `read-only`: Restricts tools to the read-only allowlist (`read`, `grep`, `find`, `ls` plus read-only extension tools when inherited — `web_*`, `serena_*`, `munin_*`, `fff*`, …). Overrides any `tools` field.
|
|
35
44
|
- `workspace-write` (default): Uses the agent's `tools` list or defaults to all tools.
|
|
36
45
|
- `worktree`: Runs the agent in an isolated git worktree (`.pi-worktrees/<id>` under the repo root). All file mutations land in the worktree; the main checkout is untouched. On completion, a unified diff of the changes is returned in the result (visible in the thread viewer as a `🌿 worktree` badge) — the parent merges explicitly via `apply_patch`/cherry-pick; nothing is applied automatically. Falls back to in-process execution when the cwd is not a git repo (with a warning). Requires git.
|
|
37
46
|
|
|
@@ -60,9 +69,16 @@ The `subagent` tool is always rejected to prevent recursive delegation.
|
|
|
60
69
|
Unknown or misspelled tool names produce a clear error.
|
|
61
70
|
Duplicate names are deduplicated automatically.
|
|
62
71
|
|
|
63
|
-
|
|
72
|
+
**Tool inheritance:** an agent WITHOUT an explicit `tools:` line inherits every
|
|
73
|
+
tool the parent session has (minus `subagent`), including extension tools like
|
|
74
|
+
`web_search`, `serena_*`, `munin_*`, `obsidian`, and `notebooklm`, and runs with
|
|
75
|
+
the parent's extensions loaded. An agent WITH an explicit `tools:` list is
|
|
76
|
+
validated against built-ins ∪ the inherited set and, when the list contains
|
|
77
|
+
only built-ins, runs in a lean loader with no extensions/skills loaded. To
|
|
78
|
+
force an inheriting agent lean, set `tools: read, bash, edit, write, grep, find, ls`.
|
|
64
79
|
|
|
65
|
-
Read-only service execution (used by `pi-review`) restricts tools to the
|
|
80
|
+
Read-only service execution (used by `pi-review`) restricts tools to the
|
|
81
|
+
read-only allowlist (including read-only extension tools when inherited).
|
|
66
82
|
|
|
67
83
|
## Model Resolution
|
|
68
84
|
|
|
@@ -86,7 +102,7 @@ Children do not automatically load repository instructions. Callers may pass an
|
|
|
86
102
|
Each sub-agent runs with:
|
|
87
103
|
- **System prompt**: agent body only (~200-1K tokens typical)
|
|
88
104
|
- **No AGENTS.md**: saves 500-5K tokens
|
|
89
|
-
- **No extensions/skills loaded**: saves 200-1K tokens
|
|
105
|
+
- **No extensions/skills loaded**: saves 200-1K tokens — but only for agents whose effective tool set is built-in only (explicit `tools:` line). Agents that inherit parent tools load the parent's extensions into the child (higher token cost, full toolset).
|
|
90
106
|
- **Thinking per role**: defaults off; bundled scout/reviewer/worker choose low/high/medium
|
|
91
107
|
- **No compaction**: avoids compaction token cost
|
|
92
108
|
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: general-purpose
|
|
3
3
|
description: General-purpose sub-agent for any delegated task. Use when no specialized agent fits. Good for complex research, multi-step operations, and code modifications.
|
|
4
|
-
|
|
5
|
-
- zai-coding-cn/glm-5.1
|
|
6
|
-
- nvidia/mistralai/mistral-small-4-119b-2603
|
|
7
|
-
- openrouter/nvidia/nemotron-3-super-120b-a12b:free
|
|
8
|
-
- opencode-go/deepseek-v4-flash
|
|
4
|
+
model: "@coder"
|
|
9
5
|
thinking: medium
|
|
10
6
|
color: yellow
|
|
11
7
|
---
|
package/agents/planner.md
CHANGED
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
name: planner
|
|
3
3
|
description: Read-only planning and architecture specialist. Use for consequential design, tradeoff analysis, and implementation plans.
|
|
4
4
|
tools: read, grep, find, ls
|
|
5
|
-
|
|
6
|
-
- zai-coding-cn/glm-5.3
|
|
7
|
-
- openrouter/nvidia/nemotron-3-ultra-550b-a55b:free
|
|
8
|
-
- opencode-go/deepseek-v4-pro
|
|
5
|
+
model: "@smart"
|
|
9
6
|
thinking: high
|
|
10
7
|
color: blue
|
|
11
8
|
sandbox: read-only
|
package/agents/reviewer.md
CHANGED
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
name: reviewer
|
|
3
3
|
description: Code review specialist. Use for correctness, security, regression, and meaningful test-gap review.
|
|
4
4
|
tools: read, grep, find, ls
|
|
5
|
-
|
|
6
|
-
- zai-coding-cn/glm-5.3
|
|
7
|
-
- openrouter/nvidia/nemotron-3-ultra-550b-a55b:free
|
|
8
|
-
- opencode-go/deepseek-v4-pro
|
|
5
|
+
model: "@smart"
|
|
9
6
|
thinking: high
|
|
10
7
|
color: purple
|
|
11
8
|
sandbox: read-only
|
package/agents/scout.md
CHANGED
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
name: scout
|
|
3
3
|
description: Fast codebase recon that returns compressed context for handoff. Use for finding files, understanding structure, locating symbols.
|
|
4
4
|
tools: read, grep, find, ls
|
|
5
|
-
|
|
6
|
-
- zai-coding-cn/glm-5-turbo
|
|
7
|
-
- nvidia/openai/gpt-oss-20b
|
|
8
|
-
- opencode-go/deepseek-v4-flash
|
|
5
|
+
model: "@fast"
|
|
9
6
|
thinking: off
|
|
10
7
|
color: cyan
|
|
11
8
|
sandbox: read-only
|
package/agents/tester.md
CHANGED
|
@@ -2,10 +2,7 @@
|
|
|
2
2
|
name: tester
|
|
3
3
|
description: Focused verification agent. Use for cheap routine test, typecheck, lint, build, and regression checks without editing files.
|
|
4
4
|
tools: read, bash, grep, find, ls
|
|
5
|
-
|
|
6
|
-
- zai-coding-cn/glm-5-turbo
|
|
7
|
-
- nvidia/openai/gpt-oss-20b
|
|
8
|
-
- opencode-go/deepseek-v4-flash
|
|
5
|
+
model: "@fast"
|
|
9
6
|
thinking: off
|
|
10
7
|
color: orange
|
|
11
8
|
---
|
package/agents/worker.md
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: worker
|
|
3
3
|
description: General-purpose coding agent with full tool access. Use only when explicitly requested for isolated implementation.
|
|
4
|
-
|
|
5
|
-
- zai-coding-cn/glm-5.1
|
|
6
|
-
- nvidia/mistralai/mistral-small-4-119b-2603
|
|
7
|
-
- openrouter/nvidia/nemotron-3-super-120b-a12b:free
|
|
8
|
-
- opencode-go/deepseek-v4-flash
|
|
4
|
+
model: "@coder"
|
|
9
5
|
thinking: medium
|
|
10
6
|
color: green
|
|
11
7
|
---
|
package/extensions/agents.ts
CHANGED
|
@@ -184,6 +184,8 @@ function loadAgentsFromDir(
|
|
|
184
184
|
}
|
|
185
185
|
for (const modelName of getModelCandidates({ model, models })) {
|
|
186
186
|
if (modelName.includes("/")) continue;
|
|
187
|
+
// @role aliases and `*` (parent) are resolved at dispatch — not model ids.
|
|
188
|
+
if (modelName.startsWith("@") || modelName === "*") continue;
|
|
187
189
|
diagnostics.push({
|
|
188
190
|
filePath,
|
|
189
191
|
issue: `Model "${modelName}" does not include a provider prefix (e.g., "anthropic/claude-sonnet-4-20250514"). Resolution may fail.`,
|
package/extensions/background.ts
CHANGED
|
@@ -166,6 +166,19 @@ export function startBackgroundTask(input: StartBackgroundInput): StartBackgroun
|
|
|
166
166
|
};
|
|
167
167
|
backgroundTasks.set(taskId, bgTask);
|
|
168
168
|
|
|
169
|
+
// Record a running entry so a crash mid-run shows as "interrupted" after
|
|
170
|
+
// restart (recordHistory at completion upserts by id and replaces it).
|
|
171
|
+
try {
|
|
172
|
+
appendHistory(join(deps.ctx.cwd, CONFIG_DIR_NAME), {
|
|
173
|
+
id: taskId,
|
|
174
|
+
agent,
|
|
175
|
+
task,
|
|
176
|
+
status: "running",
|
|
177
|
+
startedAt,
|
|
178
|
+
background: true,
|
|
179
|
+
});
|
|
180
|
+
} catch { /* history file not writable — non-fatal */ }
|
|
181
|
+
|
|
169
182
|
// Run detached — the parent does NOT await this.
|
|
170
183
|
void deps
|
|
171
184
|
.runOne(
|
package/extensions/history.ts
CHANGED
|
@@ -89,12 +89,15 @@ export function findHistory(piDir: string, id: string): HistoryEntry | undefined
|
|
|
89
89
|
* On session start, mark any `running` entries from a prior session as
|
|
90
90
|
* `interrupted`. We cannot resume them (in-process SDK sessions don't survive
|
|
91
91
|
* a restart). Honest about the architectural ceiling.
|
|
92
|
+
*
|
|
93
|
+
* `excludeIds` skips entries still live in this process (e.g. background tasks
|
|
94
|
+
* that keep running across a session reload — only shutdown aborts them).
|
|
92
95
|
*/
|
|
93
|
-
export function markInterruptedOnRestart(piDir: string): number {
|
|
96
|
+
export function markInterruptedOnRestart(piDir: string, excludeIds: ReadonlySet<string> = new Set()): number {
|
|
94
97
|
const entries = readHistory(piDir);
|
|
95
98
|
let changed = 0;
|
|
96
99
|
for (const e of entries) {
|
|
97
|
-
if (e.status === "running") {
|
|
100
|
+
if (e.status === "running" && !excludeIds.has(e.id)) {
|
|
98
101
|
e.status = "interrupted";
|
|
99
102
|
changed++;
|
|
100
103
|
}
|