Archived
fix(sessions): clarify subsession join guidance
This commit is contained in:
@@ -2,4 +2,4 @@
|
||||
"@jmfederico/pi-web": patch
|
||||
---
|
||||
|
||||
Keep delegation tools available to human-created and independently spawned sessions, remove them from tracked child sessions, and make delegation tool contracts capability-focused.
|
||||
Keep delegation tools available to human-created and independently spawned sessions, remove them from tracked child sessions, and guide parent agents to track required subsessions and yield at a join point instead of polling.
|
||||
|
||||
+13
-2
@@ -513,8 +513,19 @@
|
||||
to be enabled.
|
||||
</p>
|
||||
<p>
|
||||
Tracked subsessions let an agent delegate work to child sessions, get notified when children stop
|
||||
working, and inspect their transcripts. Restart the session daemon after changing this setting.
|
||||
Tracked subsessions let an agent delegate work to child sessions, receive a notification when each child
|
||||
stops working, and inspect their status and transcripts. Calling <code>spawn_subsession</code> returns
|
||||
immediately. The parent can continue independent work while treating every child whose result it needs
|
||||
as pending. Before producing work that depends on those results, the parent reaches a join point and
|
||||
yields until every required child has sent a completion notice.
|
||||
</p>
|
||||
<p>
|
||||
A completion notice wakes an idle parent. If the parent is busy, the notice queues until the current
|
||||
turn ends rather than interrupting in-flight work. For multiple required children, each notice resolves
|
||||
one pending child; after processing it, the parent yields again if another required child is pending.
|
||||
<code>list_subsessions</code>, <code>check_subsession</code>, and <code>read_subsession</code> provide
|
||||
on-demand status and transcript inspection for deliberate progress checks or recovery. Completion
|
||||
notifications, rather than polling these tools, are the normal synchronization mechanism.
|
||||
</p>
|
||||
<p>
|
||||
In <strong>Settings → Session daemon</strong>, these keys are saved on the selected machine. Restart the
|
||||
|
||||
+3
-1
@@ -171,7 +171,9 @@ The per-request size limit is still controlled by `maxUploadBytes` / `PI_WEB_MAX
|
||||
|
||||
`subsessions` is beta and controls whether agents receive the tracked-subsession tools: `spawn_subsession`, `list_subsessions`, `check_subsession`, and `read_subsession`. It defaults to `false` and also requires `spawnSessions` to be enabled.
|
||||
|
||||
Tracked subsessions let an agent delegate work to child sessions, get notified when children stop working, and inspect their transcripts.
|
||||
Tracked subsessions let an agent delegate work to child sessions, receive a notification when each child stops working, and inspect their status and transcripts. Calling `spawn_subsession` returns immediately. The parent can continue independent work while treating every child whose result it needs as pending. Before producing work that depends on those results, the parent reaches a join point and yields until every required child has sent a completion notice.
|
||||
|
||||
A completion notice wakes an idle parent. If the parent is busy, the notice queues until the current turn ends rather than interrupting in-flight work. For multiple required children, each notice resolves one pending child; after processing it, the parent yields again if another required child is pending. `list_subsessions`, `check_subsession`, and `read_subsession` provide on-demand status and transcript inspection for deliberate progress checks or recovery. Completion notifications, rather than polling these tools, are the normal synchronization mechanism.
|
||||
|
||||
In **Settings → Session daemon**, these keys are saved on the selected machine. Restart the session daemon on that machine after changing them.
|
||||
|
||||
|
||||
@@ -52,26 +52,25 @@ describe("createSubsessionToolDefinitions", () => {
|
||||
expect(firstText(result.content)).toContain("Started tracked subsession child-1");
|
||||
});
|
||||
|
||||
it("describes tracked dispatch and notification without workflow policy", async () => {
|
||||
it("guides the parent to join all required subsessions without polling", async () => {
|
||||
const { spawn: spawnTool } = tools({
|
||||
spawn: vi.fn(() => Promise.resolve({ sessionId: "child-1", cwd: "/repos/a-feature" })),
|
||||
});
|
||||
|
||||
expect(spawnTool.description).toBe("Start a tracked child session and send it an initial prompt. The call returns after dispatch; the parent is notified when the child stops working and can inspect its status, latest output, and transcript.");
|
||||
expect(spawnTool.description).toBe("Start a tracked child and return after dispatch. Track required children as pending: continue independent work, then yield at a join point until all have notified completion. Notifications queue while the parent is busy; do not poll for completion.");
|
||||
expect(spawnTool.promptSnippet).toBe("spawn_subsession: delegate parallel work; yield at a join point until all required children complete.");
|
||||
|
||||
const result = await spawnTool.execute("call-contract", { prompt: "do it" }, undefined, undefined, ctxFor("parent-1", undefined));
|
||||
const message = firstText(result.content);
|
||||
expect(message).toBe("Started tracked subsession child-1 in /repos/a-feature. The parent will be notified when it stops working.");
|
||||
expect(`${spawnTool.description}\n${message}`).not.toMatch(/do not poll|continue (?:useful|independent) work|end (?:this|the) turn|relay/i);
|
||||
expect(firstText(result.content)).toBe("Started tracked subsession child-1 in /repos/a-feature. Track it as pending and, before finalizing dependent work, yield until all required children have notified completion.");
|
||||
});
|
||||
|
||||
it("keeps all subsession tool descriptions capability-oriented", () => {
|
||||
it("keeps subsession inspection tool descriptions capability-oriented", () => {
|
||||
const definitions = tools({});
|
||||
|
||||
expect(definitions.list.description).toBe("List tracked child sessions owned by the calling session, with each child's current status (working, idle, error, or unknown).");
|
||||
expect(definitions.check.description).toBe("Return a tracked subsession's current status, message count, and most recent assistant output.");
|
||||
expect(definitions.read.description).toBe("Return a filtered, paginated transcript of a tracked subsession. Filters select message roles and content kinds, search full message content, optionally include raw tool arguments, and cap or page the returned entries.");
|
||||
for (const definition of Object.values(definitions)) {
|
||||
for (const definition of [definitions.list, definitions.check, definitions.read]) {
|
||||
expect(definition.description).not.toMatch(/use this|do not poll|continue working|start narrow|for just the final|relay/i);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -178,8 +178,8 @@ export function createSubsessionToolDefinitions(spawningCwd: string, deps: Subse
|
||||
const spawnTool = defineTool<typeof SpawnSubsessionParams, SpawnSubsessionResult>({
|
||||
name: "spawn_subsession",
|
||||
label: "Spawn subsession",
|
||||
description: "Start a tracked child session and send it an initial prompt. The call returns after dispatch; the parent is notified when the child stops working and can inspect its status, latest output, and transcript.",
|
||||
promptSnippet: "spawn_subsession: start a tracked child session you will be notified about",
|
||||
description: "Start a tracked child and return after dispatch. Track required children as pending: continue independent work, then yield at a join point until all have notified completion. Notifications queue while the parent is busy; do not poll for completion.",
|
||||
promptSnippet: "spawn_subsession: delegate parallel work; yield at a join point until all required children complete.",
|
||||
parameters: SpawnSubsessionParams,
|
||||
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
||||
const parentSessionId = ctx.sessionManager.getSessionId();
|
||||
@@ -193,7 +193,7 @@ export function createSubsessionToolDefinitions(spawningCwd: string, deps: Subse
|
||||
...(ctx.model === undefined ? {} : { model: ctx.model }),
|
||||
});
|
||||
return {
|
||||
content: [{ type: "text", text: `Started tracked subsession ${result.sessionId} in ${result.cwd}. The parent will be notified when it stops working.` }],
|
||||
content: [{ type: "text", text: `Started tracked subsession ${result.sessionId} in ${result.cwd}. Track it as pending and, before finalizing dependent work, yield until all required children have notified completion.` }],
|
||||
details: result,
|
||||
};
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user