@erichll/pi-sandbox 0.24.0 → 0.26.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 +33 -0
- package/README.md +7 -6
- package/package.json +10 -10
- package/src/pi-subagents-native.ts +9 -2
- package/src/subagent.ts +20 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.26.0 - 2026-10-08
|
|
4
|
+
|
|
5
|
+
- Require `@erichll/pi-auto-review ^0.26.0` so sandbox approvals use the
|
|
6
|
+
coordinated Pi 1.1.0 reviewer and cancellation fixes.
|
|
7
|
+
- Upgrade Pi development dependencies and the coding-agent peer floor to
|
|
8
|
+
`^1.1.0`; move pi-subagents to development `^0.76.1` / peer `>=0.76.1` and
|
|
9
|
+
typebox to development `^1.3.36` / peer `>=1.3.36`. Keep pi-subagents optional
|
|
10
|
+
and leave the sandbox-runtime and jiti dependency declarations unchanged.
|
|
11
|
+
- Revalidate the deterministic 0.76.1 compatibility gate and isolated Node,
|
|
12
|
+
Bun, and compiled-Bun host-peer loading on Pi 1.1.0. Fix the copied-package
|
|
13
|
+
test for dependencies that do not export package.json, including the new
|
|
14
|
+
Temporal polyfill. Revalidate model-backed acceptance with the native host
|
|
15
|
+
read baseline and the protected child blocking that read, including the
|
|
16
|
+
required sandbox runtime acknowledgement.
|
|
17
|
+
- Reject settlement waiters for RPC runs cancelled with Pi 1.1.0
|
|
18
|
+
`agent_settled.aborted: true`
|
|
19
|
+
([#10607](https://github.com/earendil-works/pi/issues/10607)), including
|
|
20
|
+
waiters registered after the event or after subsequent successful runs.
|
|
21
|
+
Keep the persistent child idle and available for follow-up instead of
|
|
22
|
+
reporting a successful result or terminating the session. Legacy events
|
|
23
|
+
without the field retain their existing behavior.
|
|
24
|
+
- Ignore buffered lifecycle events after an RPC session stops or fails so
|
|
25
|
+
cancellation and shutdown cannot resurrect a terminal session.
|
|
26
|
+
|
|
27
|
+
## 0.25.0 - 2026-10-07
|
|
28
|
+
|
|
29
|
+
- Align the `@erichll/pi-auto-review` dependency with `^0.25.0` so the
|
|
30
|
+
workspace and sandbox use the same broker implementation and include the
|
|
31
|
+
permission-system 40.0.2 integration baseline.
|
|
32
|
+
- Revalidate the deterministic and model-backed pi-subagents 0.75.0 gate:
|
|
33
|
+
the native baseline reads the host probe, while the protected native
|
|
34
|
+
background child blocks that read and acknowledges the sandbox extension.
|
|
35
|
+
|
|
3
36
|
## 0.24.0 - 2026-10-03
|
|
4
37
|
|
|
5
38
|
- Raise the `@earendil-works/pi-coding-agent` peer floor to `^1.0.0` and the
|
package/README.md
CHANGED
|
@@ -91,14 +91,14 @@ Supported modes:
|
|
|
91
91
|
|
|
92
92
|
- `builtin` (default): register the process-backed `subagent` tool and sandbox
|
|
93
93
|
each complete worker process tree.
|
|
94
|
-
- `pi-subagents`: let `pi-subagents >=0.
|
|
94
|
+
- `pi-subagents`: let `pi-subagents >=0.76.1` own orchestration under the required
|
|
95
95
|
native-background tool boundary described below.
|
|
96
96
|
- `off`: protect Bash only.
|
|
97
97
|
|
|
98
98
|
### `pi-subagents` native-background tool boundary
|
|
99
99
|
|
|
100
|
-
This provider
|
|
101
|
-
0.
|
|
100
|
+
This provider requires `pi-subagents >=0.76.1` (deterministically validated on
|
|
101
|
+
0.76.1) and fails closed if its public ceiling API, module layout, or internal
|
|
102
102
|
discovery layout drifts. The peer dependency is a floor with no upper pin; the
|
|
103
103
|
loader's explicit export and layout checks are the real gate. On Node, the
|
|
104
104
|
loader aliases the `@earendil-works/pi-tui` host peer to the running Pi package.
|
|
@@ -342,9 +342,10 @@ discovery behavior,
|
|
|
342
342
|
capability ceiling, and protected launch policy in an isolated temporary agent
|
|
343
343
|
directory. It never reads or updates production Pi configuration. Model-backed
|
|
344
344
|
acceptance requires `PI_SUBAGENTS_GATE_MODEL` and an already-exported matching
|
|
345
|
-
credential; missing prerequisites are reported as `SKIP`.
|
|
346
|
-
|
|
347
|
-
|
|
345
|
+
credential; missing prerequisites are reported as `SKIP`. The current peer
|
|
346
|
+
floor and development baseline are Pi 1.1.0, with pi-subagents 0.76.1 and
|
|
347
|
+
`typebox >=1.3.36`. The deterministic and model-backed native-baseline /
|
|
348
|
+
protected-child gates pass on this baseline.
|
|
348
349
|
|
|
349
350
|
The test suite covers real Linux Sandbox Runtime enforcement when its native
|
|
350
351
|
dependencies are installed, plus deterministic broker, network approval,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@erichll/pi-sandbox",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.0",
|
|
4
4
|
"description": "Linux (bubblewrap) and macOS (Seatbelt) process sandbox for Pi backed by Anthropic's @anthropic-ai/sandbox-runtime. Fail-closed static filesystem policy plus per-connection network approval from pi-auto-review; sandboxes main-agent Bash and built-in subagent process trees.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -51,13 +51,13 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@anthropic-ai/sandbox-runtime": "^0.0.78",
|
|
54
|
-
"@erichll/pi-auto-review": "^0.
|
|
54
|
+
"@erichll/pi-auto-review": "^0.26.0",
|
|
55
55
|
"jiti": "2.7.0"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
|
-
"@earendil-works/pi-coding-agent": "^1.
|
|
59
|
-
"pi-subagents": ">=0.
|
|
60
|
-
"typebox": ">=1.
|
|
58
|
+
"@earendil-works/pi-coding-agent": "^1.1.0",
|
|
59
|
+
"pi-subagents": ">=0.76.1",
|
|
60
|
+
"typebox": ">=1.3.36"
|
|
61
61
|
},
|
|
62
62
|
"peerDependenciesMeta": {
|
|
63
63
|
"pi-subagents": {
|
|
@@ -65,12 +65,12 @@
|
|
|
65
65
|
}
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
|
-
"@earendil-works/pi-ai": "^1.
|
|
69
|
-
"@earendil-works/pi-coding-agent": "^1.
|
|
70
|
-
"@earendil-works/pi-server": "^1.
|
|
68
|
+
"@earendil-works/pi-ai": "^1.1.0",
|
|
69
|
+
"@earendil-works/pi-coding-agent": "^1.1.0",
|
|
70
|
+
"@earendil-works/pi-server": "^1.1.0",
|
|
71
71
|
"@types/node": "^26.6.4",
|
|
72
|
-
"pi-subagents": "^0.
|
|
73
|
-
"typebox": "^1.3.
|
|
72
|
+
"pi-subagents": "^0.76.1",
|
|
73
|
+
"typebox": "^1.3.36",
|
|
74
74
|
"typescript": "^7.0.2"
|
|
75
75
|
}
|
|
76
76
|
}
|
|
@@ -7,7 +7,8 @@ import * as hostPiTui from "@earendil-works/pi-tui";
|
|
|
7
7
|
import * as hostTypebox from "typebox";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Structural loader compatibility: 0.66.0 and above; the package peer floor
|
|
11
|
+
* is >=0.76.1 (no upper pin). Any new minor
|
|
11
12
|
* is accepted, so the exports/ceiling checks below are the real compatibility
|
|
12
13
|
* gate; this range only rejects old lines and guards against blind
|
|
13
14
|
* accept-on-drift. Revalidated against 0.70.0: ceiling registry
|
|
@@ -35,7 +36,13 @@ import * as hostTypebox from "typebox";
|
|
|
35
36
|
* mode needs Pi 0.86.0 or newer
|
|
36
37
|
* (the pi-subagents 0.68.0+ floor): 0.85.0 does not ship
|
|
37
38
|
* `@earendil-works/pi-server`, so background children fail to launch there.
|
|
38
|
-
*
|
|
39
|
+
* Revalidated 2026-10-08 against 0.76.1 / Pi 1.1.0: capability-ceiling and
|
|
40
|
+
* config modules are byte-identical to 0.75.0; discovery changes add settings
|
|
41
|
+
* write leases without changing the loader seams. The deterministic gate and
|
|
42
|
+
* isolated Node/Bun/compiled-Bun host-peer tests pass. Model-backed native
|
|
43
|
+
* baseline / protected child acceptance also passes, with the host read
|
|
44
|
+
* blocked by sandboxed Bash and the runtime acknowledgement verified. This
|
|
45
|
+
* package's own peer floor is Pi 1.1.0.
|
|
39
46
|
*/
|
|
40
47
|
export const PI_SUBAGENTS_COMPAT_RANGE = ">=0.66.0";
|
|
41
48
|
export const NATIVE_CHILD_TOOLS = ["bash", "read", "grep", "find", "ls"] as const;
|
package/src/subagent.ts
CHANGED
|
@@ -294,6 +294,9 @@ export class ProcessBackedSubagentSession {
|
|
|
294
294
|
private stdin: Writable | undefined;
|
|
295
295
|
private rpcSequence = 0;
|
|
296
296
|
private settledCount = 0;
|
|
297
|
+
// Keep cancellation tied to its run even when settlement beats the RPC
|
|
298
|
+
// response/waiter registration or later follow-ups complete successfully.
|
|
299
|
+
private readonly abortedSettlements = new Set<number>();
|
|
297
300
|
private requestedSettlements = 0;
|
|
298
301
|
private activePrompt:
|
|
299
302
|
| {
|
|
@@ -421,6 +424,8 @@ export class ProcessBackedSubagentSession {
|
|
|
421
424
|
if (this.stateValue === "stopped") {
|
|
422
425
|
return Promise.reject(new Error(`subagent session ${this.id} is stopped`));
|
|
423
426
|
}
|
|
427
|
+
const aborted = this.settlementAbortError(target);
|
|
428
|
+
if (aborted) return Promise.reject(aborted);
|
|
424
429
|
if (this.settledCount >= target) {
|
|
425
430
|
return Promise.resolve(sessionResult(this.textValue, this.rawOutput));
|
|
426
431
|
}
|
|
@@ -531,12 +536,20 @@ export class ProcessBackedSubagentSession {
|
|
|
531
536
|
this.startReady = undefined;
|
|
532
537
|
}
|
|
533
538
|
|
|
539
|
+
private settlementAbortError(target: number): Error | undefined {
|
|
540
|
+
return this.abortedSettlements.has(target)
|
|
541
|
+
? new Error(`subagent session ${this.id} run ${target} aborted`)
|
|
542
|
+
: undefined;
|
|
543
|
+
}
|
|
544
|
+
|
|
534
545
|
private resolveSettledWaiters(): void {
|
|
535
546
|
const result = sessionResult(this.textValue, this.rawOutput);
|
|
536
547
|
for (const waiter of [...this.waiters]) {
|
|
537
548
|
if (waiter.target <= this.settledCount) {
|
|
538
549
|
waiter.cleanup();
|
|
539
|
-
waiter.
|
|
550
|
+
const aborted = this.settlementAbortError(waiter.target);
|
|
551
|
+
if (aborted) waiter.reject(aborted);
|
|
552
|
+
else waiter.resolve(result);
|
|
540
553
|
}
|
|
541
554
|
}
|
|
542
555
|
}
|
|
@@ -573,6 +586,9 @@ export class ProcessBackedSubagentSession {
|
|
|
573
586
|
pending.resolve(event as RpcResponse);
|
|
574
587
|
return;
|
|
575
588
|
}
|
|
589
|
+
// Buffered lifecycle records after shutdown/failure must not resurrect a
|
|
590
|
+
// terminal session or resolve a waiter already rejected by that path.
|
|
591
|
+
if (this.stateValue === "stopped" || this.stateValue === "failed") return;
|
|
576
592
|
const text = rpcAssistantText(event);
|
|
577
593
|
if (text) {
|
|
578
594
|
this.textValue = text;
|
|
@@ -584,6 +600,9 @@ export class ProcessBackedSubagentSession {
|
|
|
584
600
|
if (event.type === "agent_settled") {
|
|
585
601
|
this.stateValue = "idle";
|
|
586
602
|
this.settledCount++;
|
|
603
|
+
// Pi 1.1.0 distinguishes an aborted run from a completed one. The child
|
|
604
|
+
// process is still alive/idle; cancel its result, not the whole session.
|
|
605
|
+
if (event.aborted === true) this.abortedSettlements.add(this.settledCount);
|
|
587
606
|
if (
|
|
588
607
|
this.activePrompt &&
|
|
589
608
|
this.activePrompt.target <= this.settledCount
|