@cr1ms0n/pi-subagent 0.8.9 → 0.9.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 +11 -1
- package/README.md +218 -115
- package/docs/ARCHITECTURE.md +56 -13
- package/docs/COST-ACCOUNTING.md +116 -66
- package/docs/RELEASING.md +32 -32
- package/docs/SECURITY.md +42 -5
- package/docs/UX.md +158 -141
- package/package.json +2 -2
- package/skills/subagent/SKILL.md +78 -49
- package/src/backends/pi.ts +164 -94
- package/src/child-preflight.ts +166 -0
- package/src/config.ts +254 -252
- package/src/dispatch-preflight.ts +87 -0
- package/src/dispatch-routing.ts +56 -0
- package/src/extension.ts +366 -158
- package/src/format.ts +436 -365
- package/src/jev-router.ts +1036 -0
- package/src/orchestrator.ts +75 -19
- package/src/persistence.ts +643 -335
- package/src/policy.ts +120 -89
- package/src/process-lock.ts +730 -687
- package/src/protocol.ts +320 -290
- package/src/registry.ts +730 -632
- package/src/routing-policy.ts +268 -0
- package/src/routing-types.ts +217 -0
- package/src/runner.ts +1299 -850
- package/src/schema.ts +10 -10
- package/src/startup-check.ts +481 -0
- package/src/types.ts +208 -198
- package/src/usage.ts +316 -274
- package/src/model-policy.ts +0 -169
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -12,9 +12,10 @@
|
|
|
12
12
|
after a second window so retry can take over. Group kills verify process start-time
|
|
13
13
|
identity (Linux `/proc`, macOS/BSD `ps lstart`) before signalling a possibly-recycled
|
|
14
14
|
PID; transcript joins happen only on message boundaries, not per-chunk ticks.
|
|
15
|
-
- Retry
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
- Retry lives in `orchestrator.ts` (`isTransientFailure`): queue timeouts, stalls, spawn
|
|
16
|
+
errors, and provider errors re-run the same already-selected spec (model and tool set)
|
|
17
|
+
with accumulated usage; there is no fallback-model escalation, and task-quality failures
|
|
18
|
+
never retry.
|
|
18
19
|
- `context: "fork"` spawns the child with `--fork <parent session file>` so it starts
|
|
19
20
|
from a real branched copy of the parent conversation. Fail-fast when the parent
|
|
20
21
|
session is not persisted; single-task only.
|
|
@@ -26,10 +27,20 @@
|
|
|
26
27
|
identity records for orphan reconcile.
|
|
27
28
|
- `launch.ts`: resolve the child `pi` invocation via `PI_SUBAGENT_BIN` or
|
|
28
29
|
`process.execPath` + CLI entry (bare PATH name only as last-resort fallback).
|
|
29
|
-
- `persistence.ts`: versioned active-branch event folding
|
|
30
|
+
- `persistence.ts`: versioned active-branch event folding, the bounded routing-event decoder
|
|
31
|
+
(`subagent-routing-v1`), and bounded child transcript metadata.
|
|
30
32
|
- `maintenance.ts`: filesystem GC (session files) and abort-race helpers; kept out of persistence.
|
|
31
|
-
- `usage.ts`: provider-reported root/subagent/combined accounting
|
|
33
|
+
- `usage.ts`: provider-reported root/subagent/combined accounting, plus a separate
|
|
34
|
+
once-per-request routing-token category whose currency is reported as unreported.
|
|
32
35
|
- `policy.ts` / `schema.ts`: discriminated request validation and safe capability profiles. `schema.ts` retains the canonical TypeBox validators and derives provider-safe tool-schema projections; `extension.ts` registers those projections while validating calls with the originals. Pi context-management control-plane tools remain available to child allowlists without granting project-file write access.
|
|
36
|
+
- `routing-types.ts` / `routing-policy.ts` / `jev-router.ts` / `dispatch-routing.ts`:
|
|
37
|
+
the mandatory Jev route. `routing-types.ts` owns the selector DTOs, decision/receipt
|
|
38
|
+
shapes and local resource limits; `routing-policy.ts` owns the strict `jevRouting`
|
|
39
|
+
parser, the candidate intersection with locally available models, and the injected
|
|
40
|
+
model-facing guidance; `jev-router.ts` owns the injectable TypeSafe transport,
|
|
41
|
+
response validation, deadlines and per-request receipts; `dispatch-routing.ts`
|
|
42
|
+
resolves every worker before any launch and refuses a partially selected fanout. The
|
|
43
|
+
router has no engine imports and makes no parent UI calls.
|
|
33
44
|
- `config.ts`: defaults ← `~/.pi/subagent.json` ← `PI_SUBAGENT_*` env overrides.
|
|
34
45
|
- `structured.ts`: structured-output contract (dependency-free JSON-Schema subset
|
|
35
46
|
validation, fenced json:result extraction, contract/repair prompts) and
|
|
@@ -65,7 +76,9 @@ Invariants:
|
|
|
65
76
|
9. On startup, orphan process groups recorded under `lockDir` are reaped (SIGTERM then SIGKILL)
|
|
66
77
|
before any matching child session is eligible for resume. `$state: "lost"` is a labeling
|
|
67
78
|
that keeps `resumeBlocked` until reconciliation proves death.
|
|
68
|
-
10. Billed usage is folded once per root message and once per full child run UUID.
|
|
79
|
+
10. Billed execution usage is folded once per root message and once per full child run UUID.
|
|
80
|
+
Selector usage is a separate category folded once per selector request ID, with currency
|
|
81
|
+
reported as unreported rather than inferred.
|
|
69
82
|
11. Checkpoint persistence events are lightweight (state, usage, process identity, pointers).
|
|
70
83
|
Full transcripts and final output are persisted exactly once, in the terminal event.
|
|
71
84
|
12. High-frequency registry "changed" events coalesce (trailing window); state transitions,
|
|
@@ -96,10 +109,10 @@ Invariants:
|
|
|
96
109
|
turns before SIGTERM; a child that concludes within grace ends `partial` with
|
|
97
110
|
`wrappedUp: true`. `graceTurns: 0` restores immediate stops.
|
|
98
111
|
21. Transient failures (queued timeout, stall, spawn error, provider error, protocol
|
|
99
|
-
truncation) retry up to `maxRetries` extra attempts
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
budget stop, running timeout) never retry.
|
|
112
|
+
truncation) retry up to `maxRetries` extra attempts on the already selected model and
|
|
113
|
+
tool set; there is no fallback-model escalation and no reselection. Usage accumulates
|
|
114
|
+
across attempts. Task-quality failures (nonzero exit with complete protocol,
|
|
115
|
+
cancellation, budget stop, running timeout) never retry.
|
|
103
116
|
22. The stall watchdog treats protocol silence as suspect, not fatal: after
|
|
104
117
|
`stallAfterMs` the task is flagged and probed via `get_state` (a live child's
|
|
105
118
|
answer clears the flag); only continued silence for `stallKillAfterMs` more kills
|
|
@@ -120,6 +133,36 @@ Invariants:
|
|
|
120
133
|
`activeAtOrBelowDepth(depth) < maxGlobalActive - reservedFor(depth)`, holding slots
|
|
121
134
|
back for deeper tiers so a full-width spawn tree cannot deadlock on its own children.
|
|
122
135
|
Slot records without a `depth` field count as depth 0.
|
|
123
|
-
28. `action: "plan"` is a truth oracle: it runs the exact validation
|
|
124
|
-
real spawn and returns the resolved plan
|
|
125
|
-
|
|
136
|
+
28. `action: "plan"` is a truth oracle: it runs the exact validation, Jev selection and
|
|
137
|
+
local preflights of a real spawn and returns the resolved plan and its selector usage
|
|
138
|
+
without spawning. It creates no registry entry, and its fee-bearing selection is not
|
|
139
|
+
cached for a later dispatch.
|
|
140
|
+
29. Every new extension-managed launch (`task`/`tasks[]`, `action:"plan"`, `/btw`,
|
|
141
|
+
resume, fork, nested dispatch and the optional synthesis child) crosses one selector
|
|
142
|
+
interface before any child starts. The dedicated candidate list intersected with
|
|
143
|
+
locally available models is the only source of execution models; the full locally
|
|
144
|
+
permitted tool catalog is the only candidate source. Legacy `model`/`fallback_models`
|
|
145
|
+
fields are rejected on new work, and an empty selected tool set never becomes
|
|
146
|
+
inheritance or "all tools".
|
|
147
|
+
30. The finalized tool subset is passed to the child as Pi's `--tools` allowlist
|
|
148
|
+
(`--no-tools` when empty). Pi 0.86.0 is the verified baseline for built-in, extension
|
|
149
|
+
and late-registered tool enforcement; a host that cannot honor the allowlist is
|
|
150
|
+
refused rather than silently weakened, and no older release is advertised as
|
|
151
|
+
equivalent.
|
|
152
|
+
Startup verification is the enforcement companion: the Pi adapter supplies a
|
|
153
|
+
package-local preflight extension plus a bounded non-secret expectation, verifies that
|
|
154
|
+
the nonce-specific bootstrap command exists from the expected package source, then
|
|
155
|
+
requires the child to acknowledge the exact selected model and finalized tool names
|
|
156
|
+
(including nested-tool source) before the real task prompt is sent. Missing or
|
|
157
|
+
mismatched acknowledgement is a capability/startup diagnostic, never compensated by
|
|
158
|
+
broadening tools or choosing another model.
|
|
159
|
+
31. An absolute task deadline is created before preflight/selection, and routing, setup,
|
|
160
|
+
queue and retries all count against it. Pending selector work is tracked per session
|
|
161
|
+
runtime, aborted on cancellation, shutdown or session switch, and every post-await
|
|
162
|
+
transition re-checks captured runtime/session ownership so a late response cannot
|
|
163
|
+
launch into a replaced session.
|
|
164
|
+
32. Before any paid selection, plan and dispatch share a side-effect-free direct-resume
|
|
165
|
+
availability check (in-memory owner, `resumeBlocked`, durable lock ownership and
|
|
166
|
+
staleness) that acquires, renews or reaps nothing. Dispatch still takes the
|
|
167
|
+
authoritative lock atomically at the existing launch point, and forked resumes skip
|
|
168
|
+
the exclusive direct-resume check.
|
package/docs/COST-ACCOUNTING.md
CHANGED
|
@@ -1,66 +1,116 @@
|
|
|
1
|
-
# Cost accounting
|
|
2
|
-
|
|
3
|
-
`pi-subagent` reports
|
|
4
|
-
|
|
5
|
-
- **root** — provider-reported usage from assistant messages on the active parent-session branch.
|
|
6
|
-
- **subagents** — provider-reported cumulative usage from child-run checkpoints and terminal events on that same branch.
|
|
7
|
-
- **
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
- `
|
|
65
|
-
-
|
|
66
|
-
|
|
1
|
+
# Cost accounting
|
|
2
|
+
|
|
3
|
+
`pi-subagent` reports four independent ledgers:
|
|
4
|
+
|
|
5
|
+
- **root** — provider-reported usage from assistant messages on the active parent-session branch.
|
|
6
|
+
- **subagents** — provider-reported cumulative usage from child-run checkpoints and terminal events on that same branch.
|
|
7
|
+
- **routing**: usage reported by the Jev/TypeSafe selector, one record per selector HTTP request.
|
|
8
|
+
- **combined**: root + subagents + routing.
|
|
9
|
+
|
|
10
|
+
These totals appear in `subagent { action: "status" }`, per-run status, the
|
|
11
|
+
`/subagent-cost` command, and the `/subagents` overlay header. The footer stays
|
|
12
|
+
terse (running/ready counts only) because Pi's native footer already shows
|
|
13
|
+
session cost, including subagent spend, on Pi builds with native tool-result
|
|
14
|
+
usage accounting (see below).
|
|
15
|
+
|
|
16
|
+
## Source of truth
|
|
17
|
+
|
|
18
|
+
The extension does not estimate prices. It uses Pi's normalized provider response:
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
message.usage.cost.total
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
It also retains provider-reported input/output/cache category costs, token counts, reasoning tokens, context size, and completed turn count when supplied.
|
|
25
|
+
|
|
26
|
+
## Routing (selector) accounting
|
|
27
|
+
|
|
28
|
+
Jev selection is billed separately from child execution:
|
|
29
|
+
|
|
30
|
+
- TypeSafe reports input and output **tokens**, not billed currency. The routing
|
|
31
|
+
ledger therefore reports tokens and marks its currency as **unreported**. Do not
|
|
32
|
+
read the numeric `0` currency placeholder in the native usage schema as the
|
|
33
|
+
selector being free: it is the API-required number for an unreported value.
|
|
34
|
+
- Numeric dollar totals for root/subagent/combined exclude unreported routing
|
|
35
|
+
spend. The status line says so explicitly rather than silently omitting it.
|
|
36
|
+
- `max_cost` remains the provider-reported execution ceiling for the child and
|
|
37
|
+
its subtree. It cannot cap TypeSafe charges, so a run can stay under `max_cost`
|
|
38
|
+
while still incurring selector fees.
|
|
39
|
+
- No selector price is inferred from a public price page or a local model table.
|
|
40
|
+
|
|
41
|
+
A routing record exists per selector HTTP request, not per logical selection: a
|
|
42
|
+
model question plus one or more packed tool-question requests each produce their
|
|
43
|
+
own record, and all of them count once by full request ID. Plan selections and
|
|
44
|
+
pre-spawn failures are included, because no child run exists to carry them.
|
|
45
|
+
|
|
46
|
+
Successful route metadata (decision ID, selector model and reported version(s),
|
|
47
|
+
selected execution model/tools, locally added control-plane tools, confidence,
|
|
48
|
+
success outcome, latency and receipt IDs) travels with the run and both registry
|
|
49
|
+
projections. Per-request failure outcomes and safe error codes stay in selector receipts. It carries no descriptions, raw request bodies, headers,
|
|
50
|
+
credentials or invented rationale.
|
|
51
|
+
|
|
52
|
+
Receipts pending append visibility remain in a bounded session-local overlay until the
|
|
53
|
+
active branch exposes the matching record. Persistence retries reuse the receipt ID,
|
|
54
|
+
not the paid selector request. If persistence cannot be confirmed, new child launch is
|
|
55
|
+
blocked and a branch change is cancelled; a forced shutdown reports that durable usage
|
|
56
|
+
may be incomplete. This cannot repair an unavailable storage adapter after process exit.
|
|
57
|
+
|
|
58
|
+
## Native Pi usage accounting
|
|
59
|
+
|
|
60
|
+
Pi builds after v0.80.10 persist an optional `usage` field on tool-result messages ([pi#6671](https://github.com/earendil-works/pi/pull/6671)) and fold it into the native footer total, `/session` statistics (as `Tools/summaries`), and RPC `get_state` totals.
|
|
61
|
+
|
|
62
|
+
The extension participates in both directions:
|
|
63
|
+
|
|
64
|
+
- **Upward**: the tool result that *delivers* a run (foreground completion, or the first `wait`) carries the run's total provider usage as native `usage`. Attachment is gated on the same delivered-flag transition as output delivery, so it happens exactly once per run UUID. Status, replayed waits, steer, diff/apply/discard, and plan responses never attach run execution usage; plan may report its own selector usage through its result instead (rule 10). Older Pi hosts copy only `content`/`details` from tool results and silently ignore the field; that is safe on every version this package supports.
|
|
65
|
+
- **Downward**: a child's event stream may contain tool-result messages that themselves carry nested usage (for example, a grandchild subagent on a new-Pi child). The parent folds that into the run's cumulative usage, so `max_cost` budgets and the execution/routing ledgers see true subtree spend. Pre-#6671 children simply never emit the field.
|
|
66
|
+
|
|
67
|
+
Known undercounts in the **native** total (the extension ledger still counts these from persisted entries):
|
|
68
|
+
|
|
69
|
+
- A background run dismissed in the overlay (or via status) without a delivering `wait` never produces a tool result, so its spend reaches only the extension ledger.
|
|
70
|
+
- A failed or lost run raises an error instead of returning a tool result; any pre-failure usage likewise reaches only the extension ledger. The same native limitation applies to selector usage on a thrown error: the extension ledger retains it, but a thrown tool call cannot attach a native usage object. This is documented rather than converted into a success.
|
|
71
|
+
|
|
72
|
+
Because the native footer counts parent assistant messages plus delivered tool-result usage, and the extension's **combined** counts the same runs by UUID, the reported token totals agree when every run and selector receipt was successfully delivered as native usage. Thrown errors and undelivered plan/dispatch failures can leave selector usage only in the extension ledger; currency totals never include unreported selector fees.
|
|
73
|
+
|
|
74
|
+
## Deduplication rules
|
|
75
|
+
|
|
76
|
+
1. Root assistant messages are counted once by session-entry ID.
|
|
77
|
+
2. Each subagent run is counted once by full run UUID; the newest live/checkpoint/terminal cumulative value replaces older values.
|
|
78
|
+
3. Delivery, dismissal, status, and checkpoint events never add cost.
|
|
79
|
+
4. If an old run is evicted from in-memory UI history, its latest persisted usage still contributes to the session ledger.
|
|
80
|
+
5. Active and immediately completed runs supplement or replace stale persisted checkpoints until newer session entries become visible; the full run UUID prevents double counting afterward.
|
|
81
|
+
6. Resumed and forked invocations are distinct billed runs. Their new provider usage is counted once, even though they reuse prior context.
|
|
82
|
+
7. Retry attempts (transient-failure retries on the already selected model and tool set)
|
|
83
|
+
accumulate into their run's single usage record: every attempt's billed usage counts once
|
|
84
|
+
under one run UUID. There is no fallback-model escalation, so `attemptedModels` repeats the
|
|
85
|
+
selected model rather than recording a route change.
|
|
86
|
+
8. The optional parallel `synthesis` child bills into the same run as an extra result.
|
|
87
|
+
9. Selector requests are counted once by full selector request ID, including plan
|
|
88
|
+
requests and pre-spawn rejected decisions. Route references inside task results
|
|
89
|
+
never add selector usage again, and each receipt is folded once across
|
|
90
|
+
replay/status/repeated wait.
|
|
91
|
+
10. Native `usage` on the delivering tool result mirrors rule 2's run totals and is attached at most once per run (delivered-flag gated), so Pi-side totals cannot double count a run either. Worker pre-spawn routing tokens attach once at async start; the first delivery/wait attaches child execution usage plus any deferred-synthesis routing tokens not yet delivered; foreground completion attaches all invocation routing tokens plus execution tokens. Plan attaches only its own routing usage. Missing usage on an interrupted or invalid response stays **unknown**, never an invented zero. A partial or malformed token report retains individually validated counts while marking completeness unknown; for example, valid input with invalid output is not a complete report.
|
|
92
|
+
|
|
93
|
+
Native routing attachment commits atomically: foreground/wait use the run's single
|
|
94
|
+
`delivered` event for linked receipts; plan and async-start use one `native-delivery`
|
|
95
|
+
request-ID batch on the routing event stream. A throwing append does not consume a
|
|
96
|
+
prefix or set the in-memory run delivered flag. Transient persistence failures retry
|
|
97
|
+
without another selector call. A batch holds at most 1024 receipt IDs; larger plan or
|
|
98
|
+
background requests must be split. Background requests check this bound before any
|
|
99
|
+
child/run registration. Already incurred selector usage stays in the ledger.
|
|
100
|
+
|
|
101
|
+
## Branch semantics
|
|
102
|
+
|
|
103
|
+
Only `sessionManager.getBranch()` is used. Costs from abandoned sibling branches are excluded. When a parent session is forked, its inherited active-branch terminal entries remain part of that fork's historical total; new runs are added to the fork independently.
|
|
104
|
+
|
|
105
|
+
## Failure and cancellation
|
|
106
|
+
|
|
107
|
+
Any usage reported before a failure, timeout, budget stop, cancellation, or parent crash is retained in a cumulative checkpoint/terminal record. A run with no provider response contributes zero rather than an estimate.
|
|
108
|
+
|
|
109
|
+
## Provider limitations
|
|
110
|
+
|
|
111
|
+
Accounting is only as precise as the provider data normalized by Pi:
|
|
112
|
+
|
|
113
|
+
- Some providers may report zero or incomplete costs.
|
|
114
|
+
- `reasoning` is a subset of output tokens and is not added to output again.
|
|
115
|
+
- `contextTokens` is the latest turn's context size, not an additive billed-token field.
|
|
116
|
+
- The extension deliberately does not infer missing prices from a local model table, and TypeSafe's token-only reports are never converted into a dollar estimate.
|
package/docs/RELEASING.md
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
# Releasing @cr1ms0n/pi-subagent
|
|
2
|
-
|
|
3
|
-
This is an independent community fork of `@parke.dev/pi-subagent` by Luke Parke. Preserve the MIT license and copyright, and do not publish this fork under the upstream scope. The upstream monorepo's tag automation does not publish this package.
|
|
4
|
-
|
|
5
|
-
## Prepare
|
|
6
|
-
|
|
7
|
-
1. Update `package.json` and `CHANGELOG.md`; use an unpublished version.
|
|
8
|
-
2. Run strict type checking against the installed Pi version and offline fake-runner/extension tests. Do not run real provider calls without permission.
|
|
9
|
-
3. Run `npm pack --dry-run --json` and review the file list. Do not include authentication, user settings, machine-specific paths, local backups, session transcripts or generated test bundles.
|
|
10
|
-
4. Run `npm pack --ignore-scripts`, install the resulting tarball into an isolated prefix with `--ignore-scripts --legacy-peer-deps`, then repeat the offline checks against the packed source.
|
|
11
|
-
|
|
12
|
-
## Publish
|
|
13
|
-
|
|
14
|
-
Use an existing npm login or a securely supplied environment-based credential. Never put tokens in command text, source files, or a committed `.npmrc`. Enable TLS verification.
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
npm whoami --strict-ssl=true --registry=https://registry.npmjs.org/
|
|
18
|
-
npm publish ./cr1ms0n-pi-subagent-<version>.tgz --access public --ignore-scripts --strict-ssl=true --registry=https://registry.npmjs.org/
|
|
19
|
-
npm view @cr1ms0n/pi-subagent@<version> name version dist.integrity --strict-ssl=true --registry=https://registry.npmjs.org/
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
A successful public release makes every file in the tarball public. Verify the package metadata and registry integrity before replacing an existing installation.
|
|
23
|
-
|
|
24
|
-
## Install and replace
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
pi install npm:@cr1ms0n/pi-subagent@<version>
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
Do not enable this package and `@parke.dev/pi-subagent` at the same time: both register the same tool names. Back up the old package selection, activate only the new package after verification, and keep the old source for rollback. Reload or restart Pi after changing packages. Configure `~/.pi/subagent.json`
|
|
31
|
-
|
|
32
|
-
This fork uses the same config and persisted state paths as upstream. Switching packages is not a data migration. Upgrading must not overwrite user model choices or credentials.
|
|
1
|
+
# Releasing @cr1ms0n/pi-subagent
|
|
2
|
+
|
|
3
|
+
This is an independent community fork of `@parke.dev/pi-subagent` by Luke Parke. Preserve the MIT license and copyright, and do not publish this fork under the upstream scope. The upstream monorepo's tag automation does not publish this package.
|
|
4
|
+
|
|
5
|
+
## Prepare
|
|
6
|
+
|
|
7
|
+
1. Update `package.json` and `CHANGELOG.md`; use an unpublished version.
|
|
8
|
+
2. Run strict type checking against the installed Pi version and offline fake-runner/extension tests. Do not run real provider calls without permission.
|
|
9
|
+
3. Run `npm pack --dry-run --json` and review the file list. Do not include authentication, user settings, machine-specific paths, local backups, session transcripts or generated test bundles.
|
|
10
|
+
4. Run `npm pack --ignore-scripts`, install the resulting tarball into an isolated prefix with `--ignore-scripts --legacy-peer-deps`, then repeat the offline checks against the packed source.
|
|
11
|
+
|
|
12
|
+
## Publish
|
|
13
|
+
|
|
14
|
+
Use an existing npm login or a securely supplied environment-based credential. Never put tokens in command text, source files, or a committed `.npmrc`. Enable TLS verification.
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm whoami --strict-ssl=true --registry=https://registry.npmjs.org/
|
|
18
|
+
npm publish ./cr1ms0n-pi-subagent-<version>.tgz --access public --ignore-scripts --strict-ssl=true --registry=https://registry.npmjs.org/
|
|
19
|
+
npm view @cr1ms0n/pi-subagent@<version> name version dist.integrity --strict-ssl=true --registry=https://registry.npmjs.org/
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
A successful public release makes every file in the tarball public. Verify the package metadata and registry integrity before replacing an existing installation.
|
|
23
|
+
|
|
24
|
+
## Install and replace
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pi install npm:@cr1ms0n/pi-subagent@<version>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Do not enable this package and `@parke.dev/pi-subagent` at the same time: both register the same tool names. Back up the old package selection, activate only the new package after verification, and keep the old source for rollback. Reload or restart Pi after changing packages. Configure `~/.pi/subagent.json` `jevRouting` (candidate models plus the credential environment variable) before spawning tasks.
|
|
31
|
+
|
|
32
|
+
This fork uses the same config and persisted state paths as upstream. Switching packages is not a data migration. Upgrading must not overwrite user model choices or credentials.
|
package/docs/SECURITY.md
CHANGED
|
@@ -10,7 +10,7 @@ and can use tools according to their capability profile.
|
|
|
10
10
|
|---------|---------------|---------|
|
|
11
11
|
| `explore` | `read`, `grep`, `find`, `ls` (+ safe extras and Pi context tools) | No project-file writes |
|
|
12
12
|
| `review` | same as explore | No project-file writes |
|
|
13
|
-
| `general` |
|
|
13
|
+
| `general` | Jev-chosen subset of the full available locally permitted catalog (+ Pi context tools) | Yes if the selected tools include `bash`/`edit`/`write` |
|
|
14
14
|
|
|
15
15
|
Parallel mode defaults to `explore` to avoid concurrent shared writes.
|
|
16
16
|
|
|
@@ -20,7 +20,16 @@ Parallel mode defaults to `explore` to avoid concurrent shared writes.
|
|
|
20
20
|
an explore/review profile. Pi context-management tools (`new_context`,
|
|
21
21
|
`get_context_remaining`, `history`, `notes`) are an explicit control-plane
|
|
22
22
|
exception: they may update continuity notes/window state but cannot access
|
|
23
|
-
the project write tools.
|
|
23
|
+
the project write tools. The finalized tools reach the child as Pi's `--tools`
|
|
24
|
+
allowlist (`--no-tools` when empty), and the selector's answer is re-validated
|
|
25
|
+
locally: unknown, unavailable or unsafe choices cannot launch broader
|
|
26
|
+
capability, and an empty selection never becomes "all tools". Pi 0.86.0 is the
|
|
27
|
+
verified baseline for built-in, extension and late-registered tool enforcement;
|
|
28
|
+
a host that cannot honor the allowlist is refused rather than silently weakened.
|
|
29
|
+
Before the real task prompt, a package-local startup check verifies the routing
|
|
30
|
+
bootstrap command source and has the child acknowledge the exact selected model
|
|
31
|
+
and tool names; a mismatch aborts as a capability diagnostic and is never fixed
|
|
32
|
+
by widening tools, switching models or approving project trust.
|
|
24
33
|
2. **Parallel writers** require `isolation: "worktree"`, distinct `cwd` values,
|
|
25
34
|
or an explicit `allow_shared_writes: true` opt-in.
|
|
26
35
|
3. **Depth is capped** (`maxDepth`, default 2). Nested children at the ceiling do
|
|
@@ -55,8 +64,34 @@ Parallel mode defaults to `explore` to avoid concurrent shared writes.
|
|
|
55
64
|
Git worktrees only isolate the checkout. For untrusted tasks, use an outer
|
|
56
65
|
container/cgroup/network policy.
|
|
57
66
|
10. **`max_cost` is accounting, not a hard provider gate.** Usage arrives after a
|
|
58
|
-
turn; orphans may spend money the ledger never sees.
|
|
59
|
-
|
|
67
|
+
turn; orphans may spend money the ledger never sees. It caps provider-reported
|
|
68
|
+
execution cost only: TypeSafe reports routing tokens, not currency, so selector
|
|
69
|
+
cost is unreported and outside `max_cost`. Combine with provider account
|
|
70
|
+
budgets for hard spend limits.
|
|
71
|
+
|
|
72
|
+
## Routing disclosure and credentials
|
|
73
|
+
|
|
74
|
+
Jev routing sends a minimal projection to TypeSafe: the current delegated task
|
|
75
|
+
text, the configured candidate model IDs and your per-model descriptions,
|
|
76
|
+
eligible candidate tool names and descriptions, and necessary constraints
|
|
77
|
+
(profile, requested thinking, whether structured output is needed). It does not
|
|
78
|
+
upload repository files, conversation history, full system prompts, persona text
|
|
79
|
+
or tool parameter schemas, and does not read them in the background. Resume, fork
|
|
80
|
+
and synthesis select from the new task instruction rather than the assembled
|
|
81
|
+
transcript. Task text and model descriptions are user content and can themselves
|
|
82
|
+
contain secrets; there is no guaranteed redaction.
|
|
83
|
+
|
|
84
|
+
The TypeSafe credential is read from the environment variable named by
|
|
85
|
+
`jevRouting.apiKeyEnv` (default `TYPESAFE_API_KEY`) and sent only as an
|
|
86
|
+
`Authorization` header to the fixed official HTTPS endpoint, with redirects
|
|
87
|
+
disabled. It is never stored in the config file, prompts, argv, logs or results.
|
|
88
|
+
Rotate any credential that has been pasted into a transcript or shared in
|
|
89
|
+
conversation.
|
|
90
|
+
|
|
91
|
+
New extension-managed dispatch is Pi-only. A `backend: "codex"` or
|
|
92
|
+
`backend: "claude"` new task is rejected before any selector or provider work,
|
|
93
|
+
including a backend inherited from agent frontmatter, rather than silently
|
|
94
|
+
switched to Pi. Existing native-backend runs stay manageable.
|
|
60
95
|
|
|
61
96
|
## Trust and project cwd
|
|
62
97
|
|
|
@@ -72,7 +107,9 @@ duplicate output paths across parallel workers.
|
|
|
72
107
|
## Named agent files
|
|
73
108
|
|
|
74
109
|
Agent files (`.pi/agents/`, `.agents/agents/`, global agent dir) inject their
|
|
75
|
-
body into the child's system prompt and set
|
|
110
|
+
body into the child's system prompt and set persona, thinking and budget
|
|
111
|
+
defaults. Model and tool selection come from Jev routing; a legacy
|
|
112
|
+
`model`/`fallback_models` in frontmatter is ignored. A
|
|
76
113
|
project-level agent file shapes subagent behavior the same way project
|
|
77
114
|
extensions and skills do — review them like code when working in untrusted
|
|
78
115
|
repositories. Mitigations: capability profiles still fail closed (an agent
|