@erichll/pi-sandbox 0.18.2 → 0.19.1
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 +39 -0
- package/README.md +4 -4
- package/package.json +6 -6
- package/src/pi-subagents-native.ts +67 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.19.1 - 2026-09-20
|
|
4
|
+
|
|
5
|
+
- Pin the development `pi-subagents` baseline to `^0.70.0`. The runtime peer
|
|
6
|
+
stays `>=0.66.0`.
|
|
7
|
+
- Accept the compiled module layout introduced in 0.70.0: the npm package now
|
|
8
|
+
ships `src/**/*.js` plus `.d.ts` and publishes `./capability-ceiling` as a
|
|
9
|
+
`{ types, default }` condition map instead of the 0.69.0 bare
|
|
10
|
+
`./src/api/capability-ceiling.ts` string. The loader derives the module
|
|
11
|
+
extension and internal module paths from that export, so the source
|
|
12
|
+
(0.66.0-0.69.0) and compiled (0.70.0+) layouts share one validated code path;
|
|
13
|
+
unknown export targets still fail closed.
|
|
14
|
+
- Revalidated protected native mode against published pi-subagents 0.70.0:
|
|
15
|
+
`SUBAGENT_CAPABILITY_CEILING_VERSION` 1, `registerSubagentCapabilityCeiling`,
|
|
16
|
+
discovery/canonical resolution, and the config loader with `scheduledRuns`
|
|
17
|
+
are unchanged. The package test suite passes (89 pass, 1 skipped) and the
|
|
18
|
+
deterministic `gate:pi-subagents` preflight passes with
|
|
19
|
+
`piSubagentsModuleExtension: ".js"`. The model-backed gate phase was skipped
|
|
20
|
+
locally because no model credential was exported.
|
|
21
|
+
- Record in `docs/compat-notes.md` that 0.70.0 makes the root
|
|
22
|
+
`PI_SUBAGENT_PARENT_SESSION` marker self-deleting while detached runners keep
|
|
23
|
+
receiving it from their exact launch. Protected mode requires `async: true`
|
|
24
|
+
children, so forwarded-permission routing is unaffected; the gate's
|
|
25
|
+
parent-forwarding adapter is now a no-op shim for 0.69.0 and earlier.
|
|
26
|
+
|
|
27
|
+
## 0.19.0 - 2026-09-20
|
|
28
|
+
|
|
29
|
+
- Require Pi `^0.86.0` for both the development and peer dependency of
|
|
30
|
+
`@earendil-works/pi-coding-agent`, and depend on `@erichll/pi-auto-review`
|
|
31
|
+
`^0.19.0` so the pair shares the same Pi floor. The `pi-subagents` runtime
|
|
32
|
+
peer stays `>=0.66.0`.
|
|
33
|
+
- Revalidated against Pi 0.86.0: the package test suite passes (88 pass, 1
|
|
34
|
+
skipped), the deterministic `gate:pi-subagents` preflight passes, and the
|
|
35
|
+
model-backed gate passes both phases (native baseline host-readable,
|
|
36
|
+
protected sandboxed Bash blocked from the host read) with native
|
|
37
|
+
acknowledgement `@erichll:pi-sandbox`.
|
|
38
|
+
- Recorded the Pi 0.86.0 floor in `README.md`, `docs/compat-notes.md`, and the
|
|
39
|
+
`pi-subagents-native.ts` compatibility notes: protected mode with
|
|
40
|
+
pi-subagents 0.68.0+ needs Pi 0.86.0 or newer.
|
|
41
|
+
|
|
3
42
|
## 0.18.2 - 2026-09-20
|
|
4
43
|
|
|
5
44
|
- Pin the development `pi-subagents` baseline to `^0.69.0` and Pi to
|
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.70.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,7 @@ 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.
|
|
287
|
+
pi-subagents 0.68.0 or newer needs Pi 0.86.0 or newer.
|
|
288
288
|
|
|
289
289
|
The test suite covers real Linux Sandbox Runtime enforcement when its native
|
|
290
290
|
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.19.1",
|
|
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,11 +51,11 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@anthropic-ai/sandbox-runtime": "0.0.75",
|
|
54
|
-
"@erichll/pi-auto-review": "^0.
|
|
54
|
+
"@erichll/pi-auto-review": "^0.19.0",
|
|
55
55
|
"jiti": "2.7.0"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
|
-
"@earendil-works/pi-coding-agent": "^0.
|
|
58
|
+
"@earendil-works/pi-coding-agent": "^0.86.0",
|
|
59
59
|
"pi-subagents": ">=0.66.0",
|
|
60
60
|
"typebox": ">=1.0.0"
|
|
61
61
|
},
|
|
@@ -65,10 +65,10 @@
|
|
|
65
65
|
}
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
|
-
"@earendil-works/pi-coding-agent": "^0.
|
|
69
|
-
"@earendil-works/pi-server": "^0.
|
|
68
|
+
"@earendil-works/pi-coding-agent": "^0.86.0",
|
|
69
|
+
"@earendil-works/pi-server": "^0.86.0",
|
|
70
70
|
"@types/node": "^26.2.0",
|
|
71
|
-
"pi-subagents": "^0.
|
|
71
|
+
"pi-subagents": "^0.70.0",
|
|
72
72
|
"typescript": "^6.0.3"
|
|
73
73
|
}
|
|
74
74
|
}
|
|
@@ -7,18 +7,28 @@ 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
|
-
*
|
|
16
|
-
*
|
|
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 (verified
|
|
15
|
+
* 2026-09-20 against the published 0.70.0 package). Protected mode needs Pi
|
|
16
|
+
* 0.86.0 or newer (the package peer floor) with pi-subagents 0.68.0+: 0.85.0
|
|
17
|
+
* does not ship `@earendil-works/pi-server`, so background children fail to
|
|
18
|
+
* launch there.
|
|
17
19
|
*/
|
|
18
20
|
export const PI_SUBAGENTS_COMPAT_RANGE = ">=0.66.0";
|
|
19
21
|
export const NATIVE_CHILD_TOOLS = ["bash", "read", "grep", "find", "ls"] as const;
|
|
20
22
|
export const PI_SANDBOX_ACKNOWLEDGEMENT = "@erichll:pi-sandbox";
|
|
21
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Module extension of the installed pi-subagents layout. Source checkouts (and
|
|
26
|
+
* the 0.66.0-0.69.0 npm line) ship `.ts` modules that need a TypeScript loader;
|
|
27
|
+
* the 0.70.0+ npm package ships compiled `.js` plus `.d.ts` declarations. Both
|
|
28
|
+
* layouts keep the same package-relative module paths.
|
|
29
|
+
*/
|
|
30
|
+
export type PiSubagentsModuleExtension = ".ts" | ".js";
|
|
31
|
+
|
|
22
32
|
type Agent = {
|
|
23
33
|
name: string;
|
|
24
34
|
localName?: string;
|
|
@@ -85,6 +95,50 @@ export function isCompatiblePiSubagentsVersion(version: unknown): boolean {
|
|
|
85
95
|
return Number(match[1] ?? "") === 0 && Number(match[2] ?? "") >= 66;
|
|
86
96
|
}
|
|
87
97
|
|
|
98
|
+
function capabilityCeilingExportTarget(value: unknown): string | undefined {
|
|
99
|
+
if (typeof value === "string") return value;
|
|
100
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
|
|
101
|
+
const conditions = value as Record<string, unknown>;
|
|
102
|
+
for (const condition of ["default", "import", "require", "types"]) {
|
|
103
|
+
const candidate = conditions[condition];
|
|
104
|
+
if (typeof candidate === "string") return candidate;
|
|
105
|
+
}
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Resolve the installed module extension from the `./capability-ceiling`
|
|
111
|
+
* export, which every supported line publishes: a bare `.ts`/`.js` path before
|
|
112
|
+
* 0.70.0, a `{ types, default }` condition map from 0.70.0 on. Only the known
|
|
113
|
+
* `./src/api/capability-ceiling.<ext>` target is accepted; anything else fails
|
|
114
|
+
* closed instead of guessing a layout.
|
|
115
|
+
*/
|
|
116
|
+
export function resolvePiSubagentsModuleExtension(
|
|
117
|
+
exportsField: Record<string, unknown> | undefined,
|
|
118
|
+
): PiSubagentsModuleExtension {
|
|
119
|
+
const target = capabilityCeilingExportTarget(exportsField?.["./capability-ceiling"]);
|
|
120
|
+
const match = typeof target === "string"
|
|
121
|
+
? /^\.\/src\/api\/capability-ceiling(?:\.d)?\.(ts|js)$/u.exec(target)
|
|
122
|
+
: null;
|
|
123
|
+
if (!match) {
|
|
124
|
+
throw new Error(
|
|
125
|
+
"pi-subagents compatibility failure: capability-ceiling export changed",
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
return match[1] === "js" ? ".js" : ".ts";
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Resolve a package-relative internal module path for the installed layout,
|
|
133
|
+
* for example `src/agents/agents` on the compiled 0.70.0 line.
|
|
134
|
+
*/
|
|
135
|
+
export function piSubagentsInternalModulePath(
|
|
136
|
+
relativePath: string,
|
|
137
|
+
extension: PiSubagentsModuleExtension,
|
|
138
|
+
): string {
|
|
139
|
+
return `${relativePath.replace(/\.(?:ts|js)$/u, "")}${extension}`;
|
|
140
|
+
}
|
|
141
|
+
|
|
88
142
|
/** Load the public ceiling API and the discovery/config internals.
|
|
89
143
|
* This intentionally fails closed on package version, export, or layout drift.
|
|
90
144
|
*/
|
|
@@ -101,20 +155,18 @@ export async function loadPiSubagentsNativeRuntime(
|
|
|
101
155
|
`pi-subagents protected mode requires ${PI_SUBAGENTS_COMPAT_RANGE}; found ${String(packageJson.version)}`,
|
|
102
156
|
);
|
|
103
157
|
}
|
|
104
|
-
|
|
105
|
-
throw new Error(
|
|
106
|
-
"pi-subagents compatibility failure: capability-ceiling export changed",
|
|
107
|
-
);
|
|
108
|
-
}
|
|
158
|
+
const extension = resolvePiSubagentsModuleExtension(packageJson.exports);
|
|
109
159
|
|
|
110
160
|
const jiti = createJiti(import.meta.url, {
|
|
111
161
|
interopDefault: false,
|
|
112
162
|
fsCache: false,
|
|
113
163
|
});
|
|
164
|
+
const internal = (relative: string): string =>
|
|
165
|
+
pathToFileURL(join(root, piSubagentsInternalModulePath(relative, extension))).href;
|
|
114
166
|
const [ceiling, discovery, config] = await Promise.all([
|
|
115
|
-
jiti.import(
|
|
116
|
-
jiti.import(
|
|
117
|
-
jiti.import(
|
|
167
|
+
jiti.import(internal("src/api/capability-ceiling")) as Promise<CeilingModule>,
|
|
168
|
+
jiti.import(internal("src/agents/agents")) as Promise<DiscoveryModule>,
|
|
169
|
+
jiti.import(internal("src/extension/config")) as Promise<ConfigModule>,
|
|
118
170
|
]).catch((error) => {
|
|
119
171
|
throw new Error(
|
|
120
172
|
`pi-subagents compatibility failure: ${error instanceof Error ? error.message : String(error)}`,
|