@erichll/pi-sandbox 0.19.0 → 0.20.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 +48 -0
- package/README.md +5 -4
- package/package.json +9 -7
- package/src/pi-subagents-native.ts +69 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,53 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.20.0 - 2026-09-23
|
|
4
|
+
|
|
5
|
+
- Require Pi `^0.87.1` (development and peer) for `@earendil-works/
|
|
6
|
+
pi-coding-agent`, and upgrade the development `@earendil-works/pi-ai` and
|
|
7
|
+
`@earendil-works/pi-server` baselines to 0.87.1 (validated against the
|
|
8
|
+
published packages; type surface unchanged from 0.86.x).
|
|
9
|
+
- Pin the development `pi-subagents` baseline to `^0.71.0`; the runtime peer
|
|
10
|
+
stays `>=0.66.0`. Revalidated protected native mode against published
|
|
11
|
+
0.71.0: the ceiling implementation (`SUBAGENT_CAPABILITY_CEILING_VERSION` 1)
|
|
12
|
+
and the config loader are byte-identical to 0.70.0, and `discoverAgents` /
|
|
13
|
+
`resolveAgentName` keep their signatures (the new `applyRuntimeAgentSettings`
|
|
14
|
+
and `completionGuard` removal do not touch validated agent fields). The
|
|
15
|
+
package test suite passes (89 pass, 1 skipped) and the deterministic
|
|
16
|
+
`gate:pi-subagents` preflight passes with `piSubagentsModuleExtension
|
|
17
|
+
".js"`; the model-backed gate phase was skipped locally for lack of a
|
|
18
|
+
model credential.
|
|
19
|
+
- Upgrade `@anthropic-ai/sandbox-runtime` from the exact `0.0.75` pin to
|
|
20
|
+
`^0.0.77` (adds `LinuxSandboxProfileError` exports and an `address` module;
|
|
21
|
+
`NetworkConfigSchema` surface unchanged).
|
|
22
|
+
- Move the development `typebox` to `^1.3.34` (peer stays `>=1.0.0`).
|
|
23
|
+
- Type checking and the full test suite pass on Pi 0.87.1; the development
|
|
24
|
+
`typescript` stays 6.0.3 (TS7 was evaluated and rejected, see the
|
|
25
|
+
pi-auto-review 0.20.0 notes).
|
|
26
|
+
|
|
27
|
+
## 0.19.1 - 2026-09-20
|
|
28
|
+
|
|
29
|
+
- Pin the development `pi-subagents` baseline to `^0.70.0`. The runtime peer
|
|
30
|
+
stays `>=0.66.0`.
|
|
31
|
+
- Accept the compiled module layout introduced in 0.70.0: the npm package now
|
|
32
|
+
ships `src/**/*.js` plus `.d.ts` and publishes `./capability-ceiling` as a
|
|
33
|
+
`{ types, default }` condition map instead of the 0.69.0 bare
|
|
34
|
+
`./src/api/capability-ceiling.ts` string. The loader derives the module
|
|
35
|
+
extension and internal module paths from that export, so the source
|
|
36
|
+
(0.66.0-0.69.0) and compiled (0.70.0+) layouts share one validated code path;
|
|
37
|
+
unknown export targets still fail closed.
|
|
38
|
+
- Revalidated protected native mode against published pi-subagents 0.70.0:
|
|
39
|
+
`SUBAGENT_CAPABILITY_CEILING_VERSION` 1, `registerSubagentCapabilityCeiling`,
|
|
40
|
+
discovery/canonical resolution, and the config loader with `scheduledRuns`
|
|
41
|
+
are unchanged. The package test suite passes (89 pass, 1 skipped) and the
|
|
42
|
+
deterministic `gate:pi-subagents` preflight passes with
|
|
43
|
+
`piSubagentsModuleExtension: ".js"`. The model-backed gate phase was skipped
|
|
44
|
+
locally because no model credential was exported.
|
|
45
|
+
- Record in `docs/compat-notes.md` that 0.70.0 makes the root
|
|
46
|
+
`PI_SUBAGENT_PARENT_SESSION` marker self-deleting while detached runners keep
|
|
47
|
+
receiving it from their exact launch. Protected mode requires `async: true`
|
|
48
|
+
children, so forwarded-permission routing is unaffected; the gate's
|
|
49
|
+
parent-forwarding adapter is now a no-op shim for 0.69.0 and earlier.
|
|
50
|
+
|
|
3
51
|
## 0.19.0 - 2026-09-20
|
|
4
52
|
|
|
5
53
|
- Require Pi `^0.86.0` for both the development and peer dependency of
|
package/README.md
CHANGED
|
@@ -97,9 +97,9 @@ Supported modes:
|
|
|
97
97
|
### `pi-subagents` native-background tool boundary
|
|
98
98
|
|
|
99
99
|
This provider supports the `pi-subagents >=0.66.0` line (validated through
|
|
100
|
-
0.
|
|
101
|
-
drifts. The peer dependency is a floor with no upper pin; the
|
|
102
|
-
export and layout checks are the real gate.
|
|
100
|
+
0.71.0) and fails closed if its public ceiling API, module layout, or internal
|
|
101
|
+
discovery layout drifts. The peer dependency is a floor with no upper pin; the
|
|
102
|
+
loader's explicit export and layout checks are the real gate.
|
|
103
103
|
Configure both the protection mode and a non-empty canonical whitelist:
|
|
104
104
|
|
|
105
105
|
```json
|
|
@@ -284,7 +284,8 @@ capability ceiling, and protected launch policy in an isolated temporary agent
|
|
|
284
284
|
directory. It never reads or updates production Pi configuration. Model-backed
|
|
285
285
|
acceptance requires `PI_SUBAGENTS_GATE_MODEL` and an already-exported matching
|
|
286
286
|
credential; missing prerequisites are reported as `SKIP`. Protected mode with
|
|
287
|
-
pi-subagents 0.68.0 or newer needs Pi 0.86.0 or newer.
|
|
287
|
+
pi-subagents 0.68.0 or newer needs Pi 0.86.0 or newer. The development
|
|
288
|
+
baseline is validated against Pi 0.87.1.
|
|
288
289
|
|
|
289
290
|
The test suite covers real Linux Sandbox Runtime enforcement when its native
|
|
290
291
|
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.20.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",
|
|
@@ -50,12 +50,11 @@
|
|
|
50
50
|
"test": "node --experimental-strip-types --test test/*.test.ts"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@
|
|
54
|
-
"@erichll/pi-auto-review": "^0.19.0",
|
|
53
|
+
"@erichll/pi-auto-review": "^0.20.0",
|
|
55
54
|
"jiti": "2.7.0"
|
|
56
55
|
},
|
|
57
56
|
"peerDependencies": {
|
|
58
|
-
"@earendil-works/pi-coding-agent": "^0.
|
|
57
|
+
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
59
58
|
"pi-subagents": ">=0.66.0",
|
|
60
59
|
"typebox": ">=1.0.0"
|
|
61
60
|
},
|
|
@@ -65,10 +64,13 @@
|
|
|
65
64
|
}
|
|
66
65
|
},
|
|
67
66
|
"devDependencies": {
|
|
68
|
-
"@
|
|
69
|
-
"@earendil-works/pi-
|
|
67
|
+
"@anthropic-ai/sandbox-runtime": "^0.0.77",
|
|
68
|
+
"@earendil-works/pi-ai": "^0.87.1",
|
|
69
|
+
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
70
|
+
"@earendil-works/pi-server": "^0.87.1",
|
|
70
71
|
"@types/node": "^26.2.0",
|
|
71
|
-
"pi-subagents": "^0.
|
|
72
|
+
"pi-subagents": "^0.71.0",
|
|
73
|
+
"typebox": "^1.3.34",
|
|
72
74
|
"typescript": "^6.0.3"
|
|
73
75
|
}
|
|
74
76
|
}
|
|
@@ -7,18 +7,31 @@ import { createJiti } from "jiti";
|
|
|
7
7
|
* Compatible pi-subagents line: 0.66.0 and above (no upper pin). Any new minor
|
|
8
8
|
* is accepted, so the exports/ceiling checks below are the real compatibility
|
|
9
9
|
* gate; this range only rejects old lines and guards against blind
|
|
10
|
-
* accept-on-drift. Revalidated against 0.
|
|
11
|
-
* (`SUBAGENT_CAPABILITY_CEILING_VERSION` 1), the `./capability-ceiling` export
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
10
|
+
* accept-on-drift. Revalidated against 0.70.0: ceiling registry
|
|
11
|
+
* (`SUBAGENT_CAPABILITY_CEILING_VERSION` 1), the `./capability-ceiling` export,
|
|
12
|
+
* discovery/canonical resolution, and the config loader with `scheduledRuns`
|
|
13
|
+
* are unchanged since 0.66.0, and the published package now ships compiled
|
|
14
|
+
* `.js`/`.d.ts` modules instead of the TypeScript source layout (revalidated
|
|
15
|
+
* 2026-09-23 against the published 0.71.0 package: the ceiling implementation
|
|
16
|
+
* and the config loader are byte-identical to 0.70.0, `discoverAgents` and
|
|
17
|
+
* `resolveAgentName` keep their signatures, and the `./capability-ceiling`
|
|
18
|
+
* export still resolves to `.js`). Protected mode needs Pi 0.86.0 or newer
|
|
19
|
+
* (the pi-subagents 0.68.0+ floor): 0.85.0 does not ship
|
|
16
20
|
* `@earendil-works/pi-server`, so background children fail to launch there.
|
|
21
|
+
* This package's own peer floor is Pi 0.87.1 (validated 2026-09-23).
|
|
17
22
|
*/
|
|
18
23
|
export const PI_SUBAGENTS_COMPAT_RANGE = ">=0.66.0";
|
|
19
24
|
export const NATIVE_CHILD_TOOLS = ["bash", "read", "grep", "find", "ls"] as const;
|
|
20
25
|
export const PI_SANDBOX_ACKNOWLEDGEMENT = "@erichll:pi-sandbox";
|
|
21
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Module extension of the installed pi-subagents layout. Source checkouts (and
|
|
29
|
+
* the 0.66.0-0.69.0 npm line) ship `.ts` modules that need a TypeScript loader;
|
|
30
|
+
* the 0.70.0+ npm package ships compiled `.js` plus `.d.ts` declarations. Both
|
|
31
|
+
* layouts keep the same package-relative module paths.
|
|
32
|
+
*/
|
|
33
|
+
export type PiSubagentsModuleExtension = ".ts" | ".js";
|
|
34
|
+
|
|
22
35
|
type Agent = {
|
|
23
36
|
name: string;
|
|
24
37
|
localName?: string;
|
|
@@ -85,6 +98,50 @@ export function isCompatiblePiSubagentsVersion(version: unknown): boolean {
|
|
|
85
98
|
return Number(match[1] ?? "") === 0 && Number(match[2] ?? "") >= 66;
|
|
86
99
|
}
|
|
87
100
|
|
|
101
|
+
function capabilityCeilingExportTarget(value: unknown): string | undefined {
|
|
102
|
+
if (typeof value === "string") return value;
|
|
103
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
|
|
104
|
+
const conditions = value as Record<string, unknown>;
|
|
105
|
+
for (const condition of ["default", "import", "require", "types"]) {
|
|
106
|
+
const candidate = conditions[condition];
|
|
107
|
+
if (typeof candidate === "string") return candidate;
|
|
108
|
+
}
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Resolve the installed module extension from the `./capability-ceiling`
|
|
114
|
+
* export, which every supported line publishes: a bare `.ts`/`.js` path before
|
|
115
|
+
* 0.70.0, a `{ types, default }` condition map from 0.70.0 on. Only the known
|
|
116
|
+
* `./src/api/capability-ceiling.<ext>` target is accepted; anything else fails
|
|
117
|
+
* closed instead of guessing a layout.
|
|
118
|
+
*/
|
|
119
|
+
export function resolvePiSubagentsModuleExtension(
|
|
120
|
+
exportsField: Record<string, unknown> | undefined,
|
|
121
|
+
): PiSubagentsModuleExtension {
|
|
122
|
+
const target = capabilityCeilingExportTarget(exportsField?.["./capability-ceiling"]);
|
|
123
|
+
const match = typeof target === "string"
|
|
124
|
+
? /^\.\/src\/api\/capability-ceiling(?:\.d)?\.(ts|js)$/u.exec(target)
|
|
125
|
+
: null;
|
|
126
|
+
if (!match) {
|
|
127
|
+
throw new Error(
|
|
128
|
+
"pi-subagents compatibility failure: capability-ceiling export changed",
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
return match[1] === "js" ? ".js" : ".ts";
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Resolve a package-relative internal module path for the installed layout,
|
|
136
|
+
* for example `src/agents/agents` on the compiled 0.70.0 line.
|
|
137
|
+
*/
|
|
138
|
+
export function piSubagentsInternalModulePath(
|
|
139
|
+
relativePath: string,
|
|
140
|
+
extension: PiSubagentsModuleExtension,
|
|
141
|
+
): string {
|
|
142
|
+
return `${relativePath.replace(/\.(?:ts|js)$/u, "")}${extension}`;
|
|
143
|
+
}
|
|
144
|
+
|
|
88
145
|
/** Load the public ceiling API and the discovery/config internals.
|
|
89
146
|
* This intentionally fails closed on package version, export, or layout drift.
|
|
90
147
|
*/
|
|
@@ -101,20 +158,18 @@ export async function loadPiSubagentsNativeRuntime(
|
|
|
101
158
|
`pi-subagents protected mode requires ${PI_SUBAGENTS_COMPAT_RANGE}; found ${String(packageJson.version)}`,
|
|
102
159
|
);
|
|
103
160
|
}
|
|
104
|
-
|
|
105
|
-
throw new Error(
|
|
106
|
-
"pi-subagents compatibility failure: capability-ceiling export changed",
|
|
107
|
-
);
|
|
108
|
-
}
|
|
161
|
+
const extension = resolvePiSubagentsModuleExtension(packageJson.exports);
|
|
109
162
|
|
|
110
163
|
const jiti = createJiti(import.meta.url, {
|
|
111
164
|
interopDefault: false,
|
|
112
165
|
fsCache: false,
|
|
113
166
|
});
|
|
167
|
+
const internal = (relative: string): string =>
|
|
168
|
+
pathToFileURL(join(root, piSubagentsInternalModulePath(relative, extension))).href;
|
|
114
169
|
const [ceiling, discovery, config] = await Promise.all([
|
|
115
|
-
jiti.import(
|
|
116
|
-
jiti.import(
|
|
117
|
-
jiti.import(
|
|
170
|
+
jiti.import(internal("src/api/capability-ceiling")) as Promise<CeilingModule>,
|
|
171
|
+
jiti.import(internal("src/agents/agents")) as Promise<DiscoveryModule>,
|
|
172
|
+
jiti.import(internal("src/extension/config")) as Promise<ConfigModule>,
|
|
118
173
|
]).catch((error) => {
|
|
119
174
|
throw new Error(
|
|
120
175
|
`pi-subagents compatibility failure: ${error instanceof Error ? error.message : String(error)}`,
|