This repository has been archived on 2026-08-23. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
pi-web/src/server/sessions/spawnSessionTool.ts
T

64 lines
2.6 KiB
TypeScript

import { Type } from "typebox";
import { defineTool, type ExtensionContext } from "@earendil-works/pi-coding-agent";
export interface SpawnSessionResult {
sessionId: string;
cwd: string;
}
export type SpawnSessionModel = NonNullable<ExtensionContext["model"]>;
export interface SpawnSessionInvocation {
spawningCwd: string;
prompt: string;
cwd: string | undefined;
/** Current model from the dispatching session, used as the spawned session's default. */
model?: SpawnSessionModel;
}
export interface SpawnSessionToolDeps {
spawn(input: SpawnSessionInvocation): Promise<SpawnSessionResult>;
}
type SpawnSessionToolDetails = SpawnSessionResult;
const SpawnSessionParams = Type.Object({
prompt: Type.String({
description: "The first instruction to send to the newly created session. The new session runs independently; you do not receive its output.",
}),
cwd: Type.Optional(Type.String({
description: "Working directory for the new session. Must be a workspace (worktree, or root) of the same project as this session. Defaults to this session's working directory.",
})),
});
/**
* Custom tool that lets the LLM start a new, independent pi-web session and
* deliver an initial prompt to it. The spawned session is a normal pi-web session
* a human can open and interact with. The tool is constructed per-session, so it
* carries the spawning session's cwd for project-scope validation.
*/
export function createSpawnSessionToolDefinition(spawningCwd: string, deps: SpawnSessionToolDeps) {
return defineTool<typeof SpawnSessionParams, SpawnSessionToolDetails>({
name: "spawn_session",
label: "Spawn session",
description: "Start a new independent pi-web session and send it an initial prompt. The session is not tracked by the caller, can be opened by a human, and runs without returning its later output to the caller.",
promptSnippet: "spawn_session: start a new independent session with a first prompt",
parameters: SpawnSessionParams,
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
// Failures throw: the agent loop turns the thrown message into an error
// tool result the model sees, so the spawning agent can adapt (e.g. pick a
// valid workspace) rather than crash.
const result = await deps.spawn({
spawningCwd,
prompt: params.prompt,
cwd: params.cwd,
...(ctx.model === undefined ? {} : { model: ctx.model }),
});
return {
content: [{ type: "text", text: `Started independent session ${result.sessionId} in ${result.cwd}.` }],
details: result,
};
},
});
}