feat(sessions): add tracked subsessions behind a beta flag

Add spawn_subsession / list_subsessions / read_subsession tools that let an
agent start child sessions it stays attached to: the child records its parent
in the session tree, the parent is notified (as a system-authored custom
message that wakes an idle parent and queues behind in-flight work) when the
child stops working, and the parent can inspect children's status and result.

Gated behind a beta flag, off by default, mirroring spawnSessions: enable via
PI_WEB_SUBSESSIONS, the subsessions config key, or the Settings toggle. Also
requires spawnSessions.

Also fix the release skill so the version step resyncs package-lock.json
(npm install --package-lock-only) and the commit step refuses a release where
package.json and package-lock.json versions disagree.
This commit is contained in:
Federico Jaramillo Martinez
2026-06-17 12:13:23 +02:00
parent ef454f2b65
commit 355ebe8cf8
17 changed files with 658 additions and 13 deletions
+16 -1
View File
@@ -2,7 +2,7 @@ import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { afterEach, beforeEach, describe, expect, it } from "vitest";
import { DEFAULT_MAX_UPLOAD_BYTES, loadPiWebConfig, maxUploadBytes, savePiWebConfig, spawnSessionsEnabled } from "./config.js";
import { DEFAULT_MAX_UPLOAD_BYTES, loadPiWebConfig, maxUploadBytes, savePiWebConfig, spawnSessionsEnabled, subsessionsEnabled } from "./config.js";
let tempDir: string;
let configPath: string;
@@ -73,6 +73,21 @@ describe("spawnSessionsEnabled", () => {
});
});
describe("subsessionsEnabled", () => {
it("is off by default while the capability is in beta", () => {
expect(subsessionsEnabled({}, {})).toBe(false);
});
it("honors an explicit config opt-in", () => {
expect(subsessionsEnabled({}, { subsessions: true })).toBe(true);
});
it("lets the env var override the config in both directions", () => {
expect(subsessionsEnabled({ PI_WEB_SUBSESSIONS: "1" }, { subsessions: false })).toBe(true);
expect(subsessionsEnabled({ PI_WEB_SUBSESSIONS: "0" }, { subsessions: true })).toBe(false);
});
});
function testOptions(): { env: NodeJS.ProcessEnv } {
return { env: { PI_WEB_CONFIG: configPath } };
}