pi-subagents 0.74.0 → 0.75.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 +46 -0
- package/docs/agents.md +15 -5
- package/docs/configuration.md +10 -0
- package/docs/extension-api.md +1 -1
- package/docs/missions.md +15 -1
- package/docs/models.md +6 -2
- package/docs/observability.md +8 -3
- package/docs/tool-reference.md +28 -3
- package/docs/workflows.md +2 -2
- package/package.json +1 -1
- package/src/agents/agents.d.ts +1 -0
- package/src/agents/agents.d.ts.map +1 -1
- package/src/agents/agents.js +65 -3
- package/src/agents/agents.js.map +1 -1
- package/src/api/preflight.d.ts +1 -1
- package/src/api/preflight.d.ts.map +1 -1
- package/src/api/preflight.js +44 -1
- package/src/api/preflight.js.map +1 -1
- package/src/extension/config.d.ts.map +1 -1
- package/src/extension/config.js +4 -1
- package/src/extension/config.js.map +1 -1
- package/src/extension/index.d.ts.map +1 -1
- package/src/extension/index.js +26 -19
- package/src/extension/index.js.map +1 -1
- package/src/extension/public-execution.d.ts.map +1 -1
- package/src/extension/public-execution.js +4 -0
- package/src/extension/public-execution.js.map +1 -1
- package/src/extension/reply-workflow-script.js +1 -1
- package/src/extension/reply-workflow-script.js.map +1 -1
- package/src/extension/rpc.js +1 -1
- package/src/extension/rpc.js.map +1 -1
- package/src/extension/schemas.d.ts +1 -0
- package/src/extension/schemas.d.ts.map +1 -1
- package/src/extension/schemas.js +5 -3
- package/src/extension/schemas.js.map +1 -1
- package/src/extension/tool-description.js +1 -1
- package/src/extension/tool-description.js.map +1 -1
- package/src/missions/goal-driver.d.ts +1 -0
- package/src/missions/goal-driver.d.ts.map +1 -1
- package/src/missions/goal-driver.js +49 -34
- package/src/missions/goal-driver.js.map +1 -1
- package/src/missions/store.d.ts.map +1 -1
- package/src/missions/store.js +11 -1
- package/src/missions/store.js.map +1 -1
- package/src/profiles/profiles.d.ts +1 -1
- package/src/profiles/profiles.d.ts.map +1 -1
- package/src/profiles/profiles.js +4 -0
- package/src/profiles/profiles.js.map +1 -1
- package/src/runs/background/async-execution.d.ts +13 -0
- package/src/runs/background/async-execution.d.ts.map +1 -1
- package/src/runs/background/async-execution.js +89 -6
- package/src/runs/background/async-execution.js.map +1 -1
- package/src/runs/background/async-job-tracker.d.ts +1 -0
- package/src/runs/background/async-job-tracker.d.ts.map +1 -1
- package/src/runs/background/async-job-tracker.js +2 -2
- package/src/runs/background/async-job-tracker.js.map +1 -1
- package/src/runs/background/await-async-run.d.ts.map +1 -1
- package/src/runs/background/await-async-run.js +4 -2
- package/src/runs/background/await-async-run.js.map +1 -1
- package/src/runs/background/control-channel.d.ts +10 -0
- package/src/runs/background/control-channel.d.ts.map +1 -1
- package/src/runs/background/control-channel.js +51 -0
- package/src/runs/background/control-channel.js.map +1 -1
- package/src/runs/background/run-child-session.d.ts.map +1 -1
- package/src/runs/background/run-child-session.js +20 -6
- package/src/runs/background/run-child-session.js.map +1 -1
- package/src/runs/background/runner-aliases.d.ts +1 -0
- package/src/runs/background/runner-aliases.d.ts.map +1 -1
- package/src/runs/background/runner-aliases.js +6 -2
- package/src/runs/background/runner-aliases.js.map +1 -1
- package/src/runs/background/scheduled-runs.d.ts +2 -1
- package/src/runs/background/scheduled-runs.d.ts.map +1 -1
- package/src/runs/background/scheduled-runs.js +28 -11
- package/src/runs/background/scheduled-runs.js.map +1 -1
- package/src/runs/background/stale-run-reconciler.d.ts +1 -1
- package/src/runs/background/stale-run-reconciler.d.ts.map +1 -1
- package/src/runs/background/stale-run-reconciler.js +15 -2
- package/src/runs/background/stale-run-reconciler.js.map +1 -1
- package/src/runs/background/subagent-runner.d.ts.map +1 -1
- package/src/runs/background/subagent-runner.js +44 -3
- package/src/runs/background/subagent-runner.js.map +1 -1
- package/src/runs/foreground/command-action.d.ts +13 -0
- package/src/runs/foreground/command-action.d.ts.map +1 -0
- package/src/runs/foreground/command-action.js +38 -0
- package/src/runs/foreground/command-action.js.map +1 -0
- package/src/runs/foreground/execution.d.ts.map +1 -1
- package/src/runs/foreground/execution.js +19 -5
- package/src/runs/foreground/execution.js.map +1 -1
- package/src/runs/foreground/subagent-executor.d.ts +1 -0
- package/src/runs/foreground/subagent-executor.d.ts.map +1 -1
- package/src/runs/foreground/subagent-executor.js +64 -11
- package/src/runs/foreground/subagent-executor.js.map +1 -1
- package/src/runs/shared/child-commands.d.ts +28 -0
- package/src/runs/shared/child-commands.d.ts.map +1 -0
- package/src/runs/shared/child-commands.js +250 -0
- package/src/runs/shared/child-commands.js.map +1 -0
- package/src/runs/shared/child-session.d.ts +4 -0
- package/src/runs/shared/child-session.d.ts.map +1 -1
- package/src/runs/shared/child-session.js +97 -20
- package/src/runs/shared/child-session.js.map +1 -1
- package/src/runs/shared/child-tool-plan.js +1 -1
- package/src/runs/shared/child-tool-plan.js.map +1 -1
- package/src/runs/shared/claude-code-adapter.d.ts +56 -0
- package/src/runs/shared/claude-code-adapter.d.ts.map +1 -1
- package/src/runs/shared/claude-code-adapter.js +138 -2
- package/src/runs/shared/claude-code-adapter.js.map +1 -1
- package/src/runs/shared/dynamic-fanout.js +1 -1
- package/src/runs/shared/dynamic-fanout.js.map +1 -1
- package/src/runs/shared/external-cli-preflight.d.ts +10 -0
- package/src/runs/shared/external-cli-preflight.d.ts.map +1 -1
- package/src/runs/shared/external-cli-preflight.js +50 -6
- package/src/runs/shared/external-cli-preflight.js.map +1 -1
- package/src/runs/shared/external-cli-runner.d.ts.map +1 -1
- package/src/runs/shared/external-cli-runner.js +4 -2
- package/src/runs/shared/external-cli-runner.js.map +1 -1
- package/src/runs/shared/mcp-direct-tool-allowlist.d.ts.map +1 -1
- package/src/runs/shared/mcp-direct-tool-allowlist.js +5 -4
- package/src/runs/shared/mcp-direct-tool-allowlist.js.map +1 -1
- package/src/runs/shared/model-resolution.d.ts +6 -2
- package/src/runs/shared/model-resolution.d.ts.map +1 -1
- package/src/runs/shared/model-resolution.js +9 -2
- package/src/runs/shared/model-resolution.js.map +1 -1
- package/src/runs/shared/parallel-utils.d.ts +2 -0
- package/src/runs/shared/parallel-utils.d.ts.map +1 -1
- package/src/runs/shared/parallel-utils.js.map +1 -1
- package/src/runs/shared/run-history.d.ts +47 -0
- package/src/runs/shared/run-history.d.ts.map +1 -1
- package/src/runs/shared/run-history.js +70 -0
- package/src/runs/shared/run-history.js.map +1 -1
- package/src/runs/shared/subagent-control.d.ts.map +1 -1
- package/src/runs/shared/subagent-control.js +30 -17
- package/src/runs/shared/subagent-control.js.map +1 -1
- package/src/runs/shared/subagent-prompt-runtime.d.ts +1 -0
- package/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
- package/src/runs/shared/subagent-prompt-runtime.js +12 -5
- package/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
- package/src/shared/required-child-extensions.d.ts +16 -1
- package/src/shared/required-child-extensions.d.ts.map +1 -1
- package/src/shared/required-child-extensions.js +37 -5
- package/src/shared/required-child-extensions.js.map +1 -1
- package/src/shared/types.d.ts +6 -1
- package/src/shared/types.d.ts.map +1 -1
- package/src/shared/types.js +1 -1
- package/src/shared/types.js.map +1 -1
- package/src/slash/subagent-cost.d.ts.map +1 -1
- package/src/slash/subagent-cost.js +8 -4
- package/src/slash/subagent-cost.js.map +1 -1
- package/src/tui/render.d.ts +1 -1
- package/src/tui/render.d.ts.map +1 -1
- package/src/tui/render.js +4 -4
- package/src/tui/render.js.map +1 -1
- package/src/workflows/workflow-receipt.js +2 -2
- package/src/workflows/workflow-receipt.js.map +1 -1
- package/src/workflows/workflow-resources.d.ts +4 -0
- package/src/workflows/workflow-resources.d.ts.map +1 -1
- package/src/workflows/workflow-resources.js +7 -4
- package/src/workflows/workflow-resources.js.map +1 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
export declare const CHILD_COMMAND_TOOL = "subagent_command";
|
|
3
|
+
export type CommandOperation = "status" | "yield" | "cancel";
|
|
4
|
+
export interface ChildCommandSnapshot {
|
|
5
|
+
toolCallId: string;
|
|
6
|
+
state: "running" | "yielded" | "cancel_requested" | "completed" | "failed" | "cancelled";
|
|
7
|
+
startedAt: number;
|
|
8
|
+
endedAt?: number;
|
|
9
|
+
output: string;
|
|
10
|
+
fullOutputPath?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ChildCommandState {
|
|
13
|
+
ownerId: string;
|
|
14
|
+
closed: boolean;
|
|
15
|
+
commands: ChildCommandSnapshot[];
|
|
16
|
+
}
|
|
17
|
+
export declare function readChildCommandState(channelDir: string): ChildCommandState | undefined;
|
|
18
|
+
/** Owns command lifetimes, not shell execution. The supplied Pi tool still executes the command. */
|
|
19
|
+
export declare function createChildCommandRuntime(channelDir: string): {
|
|
20
|
+
state: () => ChildCommandState;
|
|
21
|
+
operate: (operation: CommandOperation, toolCallId?: string) => ChildCommandState;
|
|
22
|
+
shutdown: () => Promise<void>;
|
|
23
|
+
finish(): Promise<void>;
|
|
24
|
+
wrap(tool: ToolDefinition): ToolDefinition;
|
|
25
|
+
tool(): ToolDefinition;
|
|
26
|
+
};
|
|
27
|
+
export declare function controlChildCommand(channelDir: string, operation: CommandOperation, toolCallId?: string, signal?: AbortSignal): Promise<ChildCommandState>;
|
|
28
|
+
//# sourceMappingURL=child-commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"child-commands.d.ts","sourceRoot":"","sources":["../../../../src/runs/shared/child-commands.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAItE,eAAO,MAAM,kBAAkB,qBAAqB,CAAC;AACrD,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAC7D,MAAM,WAAW,oBAAoB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,kBAAkB,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;IACzF,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAQD,MAAM,WAAW,iBAAiB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,oBAAoB,EAAE,CAAC;CACjC;AAQD,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAGvF;AAMD,oGAAoG;AACpG,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM;iBAMzC,iBAAiB;yBAKP,gBAAgB,eAAe,MAAM,KAAG,iBAAiB;;;eAsDzE,cAAc,GAAG,cAAc;YAmDlC,cAAc;EAgBvB;AAiBD,wBAAsB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,gBAAgB,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CA8BhK"}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { Type } from "typebox";
|
|
5
|
+
import { createAtomicJsonWriter } from "../../shared/atomic-json.js";
|
|
6
|
+
import { watchAsyncControlInbox, requestAsyncCommand } from "../background/control-channel.js";
|
|
7
|
+
export const CHILD_COMMAND_TOOL = "subagent_command";
|
|
8
|
+
const writeAtomicJson = createAtomicJsonWriter({ mode: 0o600 });
|
|
9
|
+
const MAX_OUTPUT_BYTES = 8 * 1024;
|
|
10
|
+
const RECENT_COMMANDS = 20;
|
|
11
|
+
function childCommandStatePath(channelDir) {
|
|
12
|
+
return path.join(channelDir, "commands.json");
|
|
13
|
+
}
|
|
14
|
+
export function readChildCommandState(channelDir) {
|
|
15
|
+
try {
|
|
16
|
+
return JSON.parse(fs.readFileSync(childCommandStatePath(channelDir), "utf8"));
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
if (error.code === "ENOENT")
|
|
20
|
+
return undefined;
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function active(job) { return job.snapshot.endedAt === undefined; }
|
|
25
|
+
function text(result) {
|
|
26
|
+
return Buffer.from(result.content.filter((part) => part.type === "text").map((part) => part.text).join("\n")).subarray(-MAX_OUTPUT_BYTES).toString("utf8");
|
|
27
|
+
}
|
|
28
|
+
/** Owns command lifetimes, not shell execution. The supplied Pi tool still executes the command. */
|
|
29
|
+
export function createChildCommandRuntime(channelDir) {
|
|
30
|
+
const ownerId = randomUUID();
|
|
31
|
+
const jobs = new Map();
|
|
32
|
+
const usedIds = new Set();
|
|
33
|
+
let closed = false;
|
|
34
|
+
let disposeInbox;
|
|
35
|
+
const state = () => ({ ownerId, closed, commands: [...jobs.values()].map((job) => ({ ...job.snapshot })) });
|
|
36
|
+
const persist = () => writeAtomicJson(childCommandStatePath(channelDir), {
|
|
37
|
+
ownerId, closed,
|
|
38
|
+
commands: [...jobs.values()].map((job) => ({ ...job.snapshot, output: job.yielded ? job.snapshot.output : "" })),
|
|
39
|
+
});
|
|
40
|
+
const operate = (operation, toolCallId) => {
|
|
41
|
+
if (operation === "status" && toolCallId === undefined)
|
|
42
|
+
return state();
|
|
43
|
+
const job = toolCallId ? jobs.get(toolCallId) : undefined;
|
|
44
|
+
if (!job)
|
|
45
|
+
throw new Error(`No retained command '${toolCallId ?? ""}' in this child session.`);
|
|
46
|
+
if (operation !== "status" && closed)
|
|
47
|
+
throw new Error("Child command controller is closed.");
|
|
48
|
+
const before = job.snapshot.state;
|
|
49
|
+
if (active(job)) {
|
|
50
|
+
if (operation === "yield" && job.snapshot.state === "running") {
|
|
51
|
+
job.yielded = true;
|
|
52
|
+
job.snapshot.state = "yielded";
|
|
53
|
+
job.yieldResult();
|
|
54
|
+
}
|
|
55
|
+
else if (operation === "cancel") {
|
|
56
|
+
job.snapshot.state = "cancel_requested";
|
|
57
|
+
job.controller.abort();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (job.snapshot.state !== before)
|
|
61
|
+
persist();
|
|
62
|
+
return { ownerId, closed, commands: [{ ...job.snapshot }] };
|
|
63
|
+
};
|
|
64
|
+
const startInbox = () => {
|
|
65
|
+
if (disposeInbox)
|
|
66
|
+
return;
|
|
67
|
+
disposeInbox = watchAsyncControlInbox(channelDir, {
|
|
68
|
+
onCommand(request) {
|
|
69
|
+
const replyPath = commandReplyPath(channelDir, request.id);
|
|
70
|
+
try {
|
|
71
|
+
if (request.ownerId !== ownerId)
|
|
72
|
+
throw new Error("Command request belongs to another child session.");
|
|
73
|
+
if (Date.now() > request.deadlineAt)
|
|
74
|
+
throw new Error("Command request expired before delivery.");
|
|
75
|
+
writeAtomicJson(replyPath, { state: operate(request.operation, request.toolCallId) });
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
writeAtomicJson(replyPath, { error: error instanceof Error ? error.message : String(error) });
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
const stop = async () => {
|
|
84
|
+
closed = true;
|
|
85
|
+
disposeInbox?.();
|
|
86
|
+
for (const job of jobs.values())
|
|
87
|
+
if (active(job)) {
|
|
88
|
+
job.snapshot.state = "cancel_requested";
|
|
89
|
+
job.controller.abort();
|
|
90
|
+
}
|
|
91
|
+
await Promise.all([...jobs.values()].map((job) => job.settled));
|
|
92
|
+
if (jobs.size)
|
|
93
|
+
persist();
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
96
|
+
state,
|
|
97
|
+
operate,
|
|
98
|
+
shutdown: stop,
|
|
99
|
+
async finish() {
|
|
100
|
+
const pending = [...jobs.values()].filter(active);
|
|
101
|
+
if (!pending.length)
|
|
102
|
+
return;
|
|
103
|
+
await stop();
|
|
104
|
+
throw new Error(`Child finished with unfinished commands: ${pending.map((job) => job.snapshot.toolCallId).join(", ")}. Commands were cancelled; query or cancel background commands before finishing.`);
|
|
105
|
+
},
|
|
106
|
+
wrap(tool) {
|
|
107
|
+
return {
|
|
108
|
+
...tool,
|
|
109
|
+
parameters: Type.Unsafe({ ...tool.parameters, properties: {
|
|
110
|
+
...tool.parameters.properties,
|
|
111
|
+
yieldTimeMs: Type.Optional(Type.Integer({ minimum: 0, maximum: 30_000, description: "Return a managed command handle after this wait; does not terminate the command. Omit to wait for completion." })),
|
|
112
|
+
} }),
|
|
113
|
+
description: `${tool.description}\nOptional yieldTimeMs returns a command handle without stopping execution. Use subagent_command to query or cancel it. Finish or cancel every command before completing the task.`,
|
|
114
|
+
async execute(toolCallId, params, signal, onUpdate, ctx) {
|
|
115
|
+
if (closed)
|
|
116
|
+
throw new Error("Child command controller is closed.");
|
|
117
|
+
if (usedIds.has(toolCallId))
|
|
118
|
+
throw new Error(`Command id '${toolCallId}' was already used in this child session.`);
|
|
119
|
+
usedIds.add(toolCallId);
|
|
120
|
+
const { yieldTimeMs, ...args } = params;
|
|
121
|
+
const controller = new AbortController();
|
|
122
|
+
const commandSignal = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;
|
|
123
|
+
let yieldResult;
|
|
124
|
+
const yielded = new Promise((resolve) => { yieldResult = resolve; });
|
|
125
|
+
const job = { snapshot: { toolCallId, state: "running", startedAt: Date.now(), output: "" }, controller, yieldResult, settled: Promise.resolve() };
|
|
126
|
+
// Keep active commands and a bounded recent history; never retain full outputs.
|
|
127
|
+
const completed = [...jobs].filter(([, candidate]) => !active(candidate));
|
|
128
|
+
for (const [id] of completed.slice(0, Math.max(0, completed.length - RECENT_COMMANDS + 1)))
|
|
129
|
+
jobs.delete(id);
|
|
130
|
+
jobs.set(toolCallId, job);
|
|
131
|
+
persist();
|
|
132
|
+
startInbox();
|
|
133
|
+
let timer;
|
|
134
|
+
if (typeof yieldTimeMs === "number")
|
|
135
|
+
timer = setTimeout(() => operate("yield", toolCallId), yieldTimeMs);
|
|
136
|
+
const execution = Promise.resolve().then(() => tool.execute(toolCallId, args, commandSignal, (update) => {
|
|
137
|
+
job.snapshot.output = text(update);
|
|
138
|
+
if (job.snapshot.state === "running")
|
|
139
|
+
onUpdate?.(update);
|
|
140
|
+
}, ctx)).then((result) => {
|
|
141
|
+
job.snapshot.output = text(result);
|
|
142
|
+
job.snapshot.state = "completed";
|
|
143
|
+
const fullOutputPath = result.details?.fullOutputPath;
|
|
144
|
+
if (fullOutputPath)
|
|
145
|
+
job.snapshot.fullOutputPath = fullOutputPath;
|
|
146
|
+
return result;
|
|
147
|
+
}, (error) => {
|
|
148
|
+
job.snapshot.state = controller.signal.aborted ? "cancelled" : "failed";
|
|
149
|
+
job.snapshot.output = String(error).slice(-MAX_OUTPUT_BYTES);
|
|
150
|
+
throw error;
|
|
151
|
+
}).finally(() => {
|
|
152
|
+
if (timer)
|
|
153
|
+
clearTimeout(timer);
|
|
154
|
+
job.snapshot.endedAt = Date.now();
|
|
155
|
+
persist();
|
|
156
|
+
});
|
|
157
|
+
job.settled = execution.then(() => { }, () => { });
|
|
158
|
+
const result = await Promise.race([execution.then((value) => ({ value })), yielded.then(() => undefined)]);
|
|
159
|
+
if (result)
|
|
160
|
+
return result.value;
|
|
161
|
+
return { content: [{ type: "text", text: `Command is still running (toolCallId: ${toolCallId}). This is not a successful exit. Use subagent_command({ action: "status", toolCallId: ${JSON.stringify(toolCallId)} }) to inspect or wait, or action: "cancel" to stop it.\n${job.snapshot.output}` }], details: { command: { ...job.snapshot } } };
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
},
|
|
165
|
+
tool() {
|
|
166
|
+
return {
|
|
167
|
+
name: CHILD_COMMAND_TOOL, label: "Child command",
|
|
168
|
+
description: "Inspect or cancel bash commands owned by this child. Cancellation stops only the selected command, not the agent. Check terminal state before finishing.",
|
|
169
|
+
parameters: Type.Object({ action: Type.String({ enum: ["status", "cancel"] }), toolCallId: Type.Optional(Type.String()), waitMs: Type.Optional(Type.Integer({ minimum: 0, maximum: 30_000 })) }),
|
|
170
|
+
async execute(_id, params, signal) {
|
|
171
|
+
const { action, toolCallId, waitMs = 0 } = params;
|
|
172
|
+
operate(action, toolCallId);
|
|
173
|
+
const job = toolCallId ? jobs.get(toolCallId) : undefined;
|
|
174
|
+
if (job && active(job) && waitMs > 0)
|
|
175
|
+
await waitForCommand(job.settled, waitMs, signal);
|
|
176
|
+
const snapshot = operate("status", toolCallId);
|
|
177
|
+
return { content: [{ type: "text", text: JSON.stringify(snapshot) }], details: snapshot };
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
async function waitForCommand(settled, waitMs, signal) {
|
|
184
|
+
let timer;
|
|
185
|
+
let abort;
|
|
186
|
+
const wait = new Promise((resolve, reject) => {
|
|
187
|
+
timer = setTimeout(resolve, waitMs);
|
|
188
|
+
abort = () => reject(new Error("Command wait aborted; command remains managed by the child."));
|
|
189
|
+
if (signal?.aborted)
|
|
190
|
+
abort();
|
|
191
|
+
else
|
|
192
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
193
|
+
});
|
|
194
|
+
try {
|
|
195
|
+
await Promise.race([settled, wait]);
|
|
196
|
+
}
|
|
197
|
+
finally {
|
|
198
|
+
clearTimeout(timer);
|
|
199
|
+
signal?.removeEventListener("abort", abort);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function commandReplyPath(channelDir, id) {
|
|
203
|
+
return path.join(channelDir, "command-replies", `${id}.json`);
|
|
204
|
+
}
|
|
205
|
+
export async function controlChildCommand(channelDir, operation, toolCallId, signal) {
|
|
206
|
+
const current = readChildCommandState(channelDir);
|
|
207
|
+
if (!current)
|
|
208
|
+
throw new Error("No command controller is available for this child. Command controls require a local native Pi child with bash.");
|
|
209
|
+
if (current.closed) {
|
|
210
|
+
if (operation === "status") {
|
|
211
|
+
if (toolCallId === undefined)
|
|
212
|
+
return current;
|
|
213
|
+
const command = current.commands.find((entry) => entry.toolCallId === toolCallId);
|
|
214
|
+
if (!command)
|
|
215
|
+
throw new Error(`No retained command '${toolCallId}' in this child session.`);
|
|
216
|
+
return { ...current, commands: [command] };
|
|
217
|
+
}
|
|
218
|
+
throw new Error("Child command controller is closed.");
|
|
219
|
+
}
|
|
220
|
+
if (operation !== "status" && !toolCallId)
|
|
221
|
+
throw new Error("An exact toolCallId is required; command controls never target the next command.");
|
|
222
|
+
const id = randomUUID();
|
|
223
|
+
const deadlineAt = Date.now() + 5_000;
|
|
224
|
+
const request = { type: "command", id, ownerId: current.ownerId, operation, ...(toolCallId ? { toolCallId } : {}), deadlineAt };
|
|
225
|
+
requestAsyncCommand(channelDir, request);
|
|
226
|
+
const replyPath = commandReplyPath(channelDir, id);
|
|
227
|
+
try {
|
|
228
|
+
while (Date.now() < deadlineAt) {
|
|
229
|
+
if (signal?.aborted)
|
|
230
|
+
throw new Error("Command control wait aborted; delivery may still be pending.");
|
|
231
|
+
try {
|
|
232
|
+
const reply = JSON.parse(fs.readFileSync(replyPath, "utf8"));
|
|
233
|
+
if (reply.error)
|
|
234
|
+
throw new Error(reply.error);
|
|
235
|
+
if (reply.state)
|
|
236
|
+
return reply.state;
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
if (error.code !== "ENOENT")
|
|
240
|
+
throw error;
|
|
241
|
+
}
|
|
242
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
243
|
+
}
|
|
244
|
+
throw new Error("Command control acknowledgement timed out. Inspect command status; cancellation is not confirmed.");
|
|
245
|
+
}
|
|
246
|
+
finally {
|
|
247
|
+
fs.rmSync(replyPath, { force: true });
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
//# sourceMappingURL=child-commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"child-commands.js","sourceRoot":"","sources":["../../../../src/runs/shared/child-commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG/B,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAuB,MAAM,kCAAkC,CAAC;AAEpH,MAAM,CAAC,MAAM,kBAAkB,GAAG,kBAAkB,CAAC;AAsBrD,MAAM,eAAe,GAAG,sBAAsB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAChE,MAAM,gBAAgB,GAAG,CAAC,GAAG,IAAI,CAAC;AAClC,MAAM,eAAe,GAAG,EAAE,CAAC;AAE3B,SAAS,qBAAqB,CAAC,UAAkB;IAChD,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;AAC/C,CAAC;AACD,MAAM,UAAU,qBAAqB,CAAC,UAAkB;IACvD,IAAI,CAAC;QAAC,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,qBAAqB,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,CAAsB,CAAC;IAAC,CAAC;IAC3G,OAAO,KAAK,EAAE,CAAC;QAAC,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QAAC,MAAM,KAAK,CAAC;IAAC,CAAC;AACzG,CAAC;AACD,SAAS,MAAM,CAAC,GAAe,IAAa,OAAO,GAAG,CAAC,QAAQ,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC;AACxF,SAAS,IAAI,CAAC,MAAgC;IAC7C,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,gBAAgB,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC5J,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,yBAAyB,CAAC,UAAkB;IAC3D,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC3C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,YAAsC,CAAC;IAC3C,MAAM,KAAK,GAAG,GAAsB,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAC/H,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,eAAe,CAAC,qBAAqB,CAAC,UAAU,CAAC,EAAE;QACxE,OAAO,EAAE,MAAM;QACf,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;KAChH,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,CAAC,SAA2B,EAAE,UAAmB,EAAqB,EAAE;QACvF,IAAI,SAAS,KAAK,QAAQ,IAAI,UAAU,KAAK,SAAS;YAAE,OAAO,KAAK,EAAE,CAAC;QACvE,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1D,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,UAAU,IAAI,EAAE,0BAA0B,CAAC,CAAC;QAC9F,IAAI,SAAS,KAAK,QAAQ,IAAI,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAC7F,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QAClC,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YACjB,IAAI,SAAS,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;gBAC/D,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC;gBACnB,GAAG,CAAC,QAAQ,CAAC,KAAK,GAAG,SAAS,CAAC;gBAC/B,GAAG,CAAC,WAAW,EAAE,CAAC;YACnB,CAAC;iBAAM,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;gBACnC,GAAG,CAAC,QAAQ,CAAC,KAAK,GAAG,kBAAkB,CAAC;gBACxC,GAAG,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;YACxB,CAAC;QACF,CAAC;QACD,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,KAAK,MAAM;YAAE,OAAO,EAAE,CAAC;QAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC;IAC7D,CAAC,CAAC;IACF,MAAM,UAAU,GAAG,GAAG,EAAE;QACvB,IAAI,YAAY;YAAE,OAAO;QACzB,YAAY,GAAG,sBAAsB,CAAC,UAAU,EAAE;YACjD,SAAS,CAAC,OAAO;gBAChB,MAAM,SAAS,GAAG,gBAAgB,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;gBAC3D,IAAI,CAAC;oBACJ,IAAI,OAAO,CAAC,OAAO,KAAK,OAAO;wBAAE,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;oBACtG,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,UAAU;wBAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;oBACjG,eAAe,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;gBACvF,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAChB,eAAe,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;gBAC/F,CAAC;YACF,CAAC;SACD,CAAC,CAAC;IACJ,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE;QACvB,MAAM,GAAG,IAAI,CAAC;QACd,YAAY,EAAE,EAAE,CAAC;QACjB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,EAAE;YAAE,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClD,GAAG,CAAC,QAAQ,CAAC,KAAK,GAAG,kBAAkB,CAAC;gBACxC,GAAG,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;YACxB,CAAC;QACD,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QAChE,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,CAAC;IAC1B,CAAC,CAAC;IACF,OAAO;QACN,KAAK;QACL,OAAO;QACP,QAAQ,EAAE,IAAI;QACd,KAAK,CAAC,MAAM;YACX,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAClD,IAAI,CAAC,OAAO,CAAC,MAAM;gBAAE,OAAO;YAC5B,MAAM,IAAI,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,4CAA4C,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,kFAAkF,CAAC,CAAC;QACzM,CAAC;QACD,IAAI,CAAC,IAAoB;YACxB,OAAO;gBACN,GAAG,IAAI;gBACP,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE;wBACzD,GAAI,IAAI,CAAC,UAAsC,CAAC,UAAU;wBAC1D,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,+GAA+G,EAAE,CAAC,CAAC;qBACvM,EAAE,CAAC;gBACJ,WAAW,EAAE,GAAG,IAAI,CAAC,WAAW,oLAAoL;gBACpN,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG;oBACtD,IAAI,MAAM;wBAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;oBACnE,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;wBAAE,MAAM,IAAI,KAAK,CAAC,eAAe,UAAU,2CAA2C,CAAC,CAAC;oBACnH,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;oBACxB,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,EAAE,GAAG,MAAiC,CAAC;oBACnE,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;oBACzC,MAAM,aAAa,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC;oBAChG,IAAI,WAAwB,CAAC;oBAC7B,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,GAAG,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC3E,MAAM,GAAG,GAAe,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;oBAC/J,gFAAgF;oBAChF,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;oBAC1E,KAAK,MAAM,CAAC,EAAE,CAAC,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,eAAe,GAAG,CAAC,CAAC,CAAC;wBAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;oBAC5G,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;oBAC1B,OAAO,EAAE,CAAC;oBACV,UAAU,EAAE,CAAC;oBACb,IAAI,KAAgD,CAAC;oBACrD,IAAI,OAAO,WAAW,KAAK,QAAQ;wBAAE,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,WAAW,CAAC,CAAC;oBACzG,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,MAAM,EAAE,EAAE;wBACvG,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;wBACnC,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,KAAK,SAAS;4BAAE,QAAQ,EAAE,CAAC,MAAM,CAAC,CAAC;oBAC1D,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;wBACxB,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;wBACnC,GAAG,CAAC,QAAQ,CAAC,KAAK,GAAG,WAAW,CAAC;wBACjC,MAAM,cAAc,GAAI,MAAM,CAAC,OAAmD,EAAE,cAAc,CAAC;wBACnG,IAAI,cAAc;4BAAE,GAAG,CAAC,QAAQ,CAAC,cAAc,GAAG,cAAc,CAAC;wBACjE,OAAO,MAAM,CAAC;oBACf,CAAC,EAAE,CAAC,KAAc,EAAE,EAAE;wBACrB,GAAG,CAAC,QAAQ,CAAC,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC;wBACxE,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,gBAAgB,CAAC,CAAC;wBAC7D,MAAM,KAAK,CAAC;oBACb,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;wBACf,IAAI,KAAK;4BAAE,YAAY,CAAC,KAAK,CAAC,CAAC;wBAC/B,GAAG,CAAC,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;wBAClC,OAAO,EAAE,CAAC;oBACX,CAAC,CAAC,CAAC;oBACH,GAAG,CAAC,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;oBACjD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;oBAC3G,IAAI,MAAM;wBAAE,OAAO,MAAM,CAAC,KAAK,CAAC;oBAChC,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,yCAAyC,UAAU,0FAA0F,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,4DAA4D,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,GAAG,GAAG,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC;gBACnV,CAAC;aACD,CAAC;QACH,CAAC;QACD,IAAI;YACH,OAAO;gBACN,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,eAAe;gBAChD,WAAW,EAAE,0JAA0J;gBACvK,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC;gBAChM,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM;oBAChC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,EAAE,GAAG,MAA+E,CAAC;oBAC3H,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;oBAC5B,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;oBAC1D,IAAI,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC;wBAAE,MAAM,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;oBACxF,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;oBAC/C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;gBAC3F,CAAC;aACD,CAAC;QACH,CAAC;KACD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,OAAsB,EAAE,MAAc,EAAE,MAAoB;IACzF,IAAI,KAAoC,CAAC;IACzC,IAAI,KAAkB,CAAC;IACvB,MAAM,IAAI,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAClD,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACpC,KAAK,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC,CAAC;QAC/F,IAAI,MAAM,EAAE,OAAO;YAAE,KAAK,EAAE,CAAC;;YACxB,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IACH,IAAI,CAAC;QAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;IAAC,CAAC;YACpC,CAAC;QAAC,YAAY,CAAC,KAAM,CAAC,CAAC;QAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAAC,CAAC;AAC/E,CAAC;AACD,SAAS,gBAAgB,CAAC,UAAkB,EAAE,EAAU;IACvD,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,iBAAiB,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;AAC/D,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,UAAkB,EAAE,SAA2B,EAAE,UAAmB,EAAE,MAAoB;IACnI,MAAM,OAAO,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;IAClD,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,gHAAgH,CAAC,CAAC;IAChJ,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACpB,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC5B,IAAI,UAAU,KAAK,SAAS;gBAAE,OAAO,OAAO,CAAC;YAC7C,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;YAClF,IAAI,CAAC,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,UAAU,0BAA0B,CAAC,CAAC;YAC5F,OAAO,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5C,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,SAAS,KAAK,QAAQ,IAAI,CAAC,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,kFAAkF,CAAC,CAAC;IAC/I,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;IACxB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;IACtC,MAAM,OAAO,GAAmB,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC;IAChJ,mBAAmB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACzC,MAAM,SAAS,GAAG,gBAAgB,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IACnD,IAAI,CAAC;QACJ,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,EAAE,CAAC;YAChC,IAAI,MAAM,EAAE,OAAO;gBAAE,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAC;YACrG,IAAI,CAAC;gBACJ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAkD,CAAC;gBAC9G,IAAI,KAAK,CAAC,KAAK;oBAAE,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBAC9C,IAAI,KAAK,CAAC,KAAK;oBAAE,OAAO,KAAK,CAAC,KAAK,CAAC;YACrC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAAC,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;oBAAE,MAAM,KAAK,CAAC;YAAC,CAAC;YACxF,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;QACzD,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,mGAAmG,CAAC,CAAC;IACtH,CAAC;YAAS,CAAC;QAAC,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAAC,CAAC;AACrD,CAAC"}
|
|
@@ -89,12 +89,16 @@ export interface ChildSession {
|
|
|
89
89
|
abort(): Promise<void>;
|
|
90
90
|
/** Emits `session_shutdown` to the child's extensions and disposes the session; resolves once that shutdown work is done. */
|
|
91
91
|
dispose(): Promise<void>;
|
|
92
|
+
/** Final settlement check for commands owned by this child; unfinished commands are cancelled and reject completion. */
|
|
93
|
+
finishCommands?(): Promise<void>;
|
|
92
94
|
/** True while Pi still has steering or follow-up input that has not started a turn. */
|
|
93
95
|
hasQueuedMessages?(): boolean;
|
|
94
96
|
readonly messages: readonly AgentMessage[];
|
|
95
97
|
readonly sessionFile: string | undefined;
|
|
96
98
|
readonly sessionId: string;
|
|
97
99
|
readonly modelId: string | undefined;
|
|
100
|
+
/** Live provider/id of the selected model when Pi marks it virtual (`api === "pi-virtual"`); assistant messages then name the dispatched physical model. */
|
|
101
|
+
readonly virtualModelId?: string;
|
|
98
102
|
readonly contextWindow?: number;
|
|
99
103
|
readonly machineEvidence?: {
|
|
100
104
|
machineId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"child-session.d.ts","sourceRoot":"","sources":["../../../../src/runs/shared/child-session.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"child-session.d.ts","sourceRoot":"","sources":["../../../../src/runs/shared/child-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,6 +18,8 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
|
|
|
18
18
|
import * as fs from "node:fs";
|
|
19
19
|
import * as path from "node:path";
|
|
20
20
|
import { pathToFileURL } from "node:url";
|
|
21
|
+
import { CHILD_COMMAND_TOOL, createChildCommandRuntime } from "./child-commands.js";
|
|
22
|
+
import { supervisorChannelDir } from "./child-tool-plan.js";
|
|
21
23
|
import { pinChildCacheRetention } from "../../shared/child-cache-retention.js";
|
|
22
24
|
import { getAgentDir, PI_CODING_AGENT_PACKAGE_ROOT_ENV } from "../../shared/utils.js";
|
|
23
25
|
import { resolvePackageSubpath } from "../background/runner-aliases.js";
|
|
@@ -86,6 +88,31 @@ function prioritizeChildPromptRuntime(result) {
|
|
|
86
88
|
extensions.unshift(promptRuntime);
|
|
87
89
|
return { ...result, extensions };
|
|
88
90
|
}
|
|
91
|
+
/** Ambient bash overrides keep their original backend and priority. */
|
|
92
|
+
function prioritizeChildCommandRuntime(result) {
|
|
93
|
+
const index = result.extensions.findIndex(({ path }) => path === "<inline:pi-subagents:commands>");
|
|
94
|
+
if (index < 0)
|
|
95
|
+
return result;
|
|
96
|
+
if (result.extensions.some((extension, otherIndex) => otherIndex !== index && extension.tools?.has("bash"))) {
|
|
97
|
+
const extensions = result.extensions.filter((_, otherIndex) => otherIndex !== index);
|
|
98
|
+
if (!extensions.some((extension) => extension.tools?.has(CHILD_COMMAND_TOOL))) {
|
|
99
|
+
const commands = result.extensions[index];
|
|
100
|
+
const registered = commands.tools.get(CHILD_COMMAND_TOOL);
|
|
101
|
+
const reason = "Native command controls are unavailable with the active custom bash backend. Use that backend's own command controls.";
|
|
102
|
+
extensions.push({ ...commands, tools: new Map([[CHILD_COMMAND_TOOL, { ...registered, definition: {
|
|
103
|
+
...registered.definition, description: reason,
|
|
104
|
+
execute: async () => { throw new Error(reason); },
|
|
105
|
+
} }]]) });
|
|
106
|
+
}
|
|
107
|
+
return { ...result, extensions };
|
|
108
|
+
}
|
|
109
|
+
if (index === 0)
|
|
110
|
+
return result;
|
|
111
|
+
const extensions = [...result.extensions];
|
|
112
|
+
const [commands] = extensions.splice(index, 1);
|
|
113
|
+
extensions.unshift(commands);
|
|
114
|
+
return { ...result, extensions };
|
|
115
|
+
}
|
|
89
116
|
/** One launch at a time from env application through `session_start`, so parallel launches never observe each other's `processEnv` while their extensions load and start. */
|
|
90
117
|
let loading = Promise.resolve();
|
|
91
118
|
/**
|
|
@@ -192,6 +219,29 @@ function flushQueuedProviderRegistrations(loader, modelRuntime, onError, require
|
|
|
192
219
|
}
|
|
193
220
|
if (Array.isArray(runtime.pendingNativeProviderRegistrations))
|
|
194
221
|
runtime.pendingNativeProviderRegistrations = [];
|
|
222
|
+
// Pi core flushes pendingVirtualModelRegistrations when a session binds extensions
|
|
223
|
+
// (agent-session-services), but this factory resolves the requested model before that
|
|
224
|
+
// binding, so an extension-registered virtual model never resolves for the child. The
|
|
225
|
+
// structural cast keeps compiling against SDK versions that predate virtual models;
|
|
226
|
+
// there the queue is absent and the loop is a no-op.
|
|
227
|
+
const virtualModelRuntime = modelRuntime;
|
|
228
|
+
const virtualModelQueue = runtime;
|
|
229
|
+
const pendingVirtualModelRegistrations = virtualModelQueue.pendingVirtualModelRegistrations ?? [];
|
|
230
|
+
for (const { definition, extensionPath } of pendingVirtualModelRegistrations) {
|
|
231
|
+
if (typeof virtualModelRuntime.registerVirtualModel !== "function")
|
|
232
|
+
break;
|
|
233
|
+
try {
|
|
234
|
+
virtualModelRuntime.registerVirtualModel(definition);
|
|
235
|
+
registered = true;
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
onError?.({ extensionPath, event: "register_virtual_model", error });
|
|
239
|
+
if (requiredPaths.has(extensionPath))
|
|
240
|
+
throw new Error(`Required child extension virtual model registration failed for '${extensionPath}': ${error instanceof Error ? error.message : String(error)}`);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
if (Array.isArray(virtualModelQueue.pendingVirtualModelRegistrations))
|
|
244
|
+
virtualModelQueue.pendingVirtualModelRegistrations = [];
|
|
195
245
|
return { claimedProviderIds, registered };
|
|
196
246
|
}
|
|
197
247
|
/**
|
|
@@ -269,6 +319,11 @@ export function createDefaultChildSessionFactory(options = {}) {
|
|
|
269
319
|
? await pi.ModelRuntime.create()
|
|
270
320
|
: await sharedRuntime(pi);
|
|
271
321
|
const agentDir = getAgentDir();
|
|
322
|
+
const commands = launch.runtime.runId && launch.runtime.agent && launch.runtime.childIndex !== undefined
|
|
323
|
+
&& launch.tools?.includes("bash") && launch.tools.includes(CHILD_COMMAND_TOOL)
|
|
324
|
+
&& !launch.excludeTools?.includes("bash") && !launch.excludeTools?.includes(CHILD_COMMAND_TOOL)
|
|
325
|
+
&& typeof pi.createBashTool === "function"
|
|
326
|
+
? createChildCommandRuntime(supervisorChannelDir(launch.runtime.runId, launch.runtime.agent, launch.runtime.childIndex)) : undefined;
|
|
272
327
|
const settingsManager = pi.SettingsManager.create(launch.cwd, agentDir, { projectTrusted: launch.projectTrusted });
|
|
273
328
|
// Foreground children share Pi's global theme with the parent, so reinitializing it
|
|
274
329
|
// would overwrite the parent's active light/dark appearance. Detached runners have
|
|
@@ -299,11 +354,32 @@ export function createDefaultChildSessionFactory(options = {}) {
|
|
|
299
354
|
noThemes: true,
|
|
300
355
|
noContextFiles: launch.noContextFiles,
|
|
301
356
|
additionalExtensionPaths: builtinMcp ? [...launch.extensionPaths, "builtin:mcp"] : launch.extensionPaths,
|
|
302
|
-
extensionFactories: [...launch.hooks, ...
|
|
303
|
-
|
|
357
|
+
extensionFactories: [...launch.hooks, ...(commands ? [{ name: "pi-subagents:commands", factory: (api) => {
|
|
358
|
+
api.registerTool(commands.wrap(pi.createBashTool(launch.cwd, { commandPrefix: settingsManager.getShellCommandPrefix(), shellPath: settingsManager.getShellPath() })));
|
|
359
|
+
api.registerTool(commands.tool());
|
|
360
|
+
} }] : []), ...codemode, ...(builtinMcp ? [builtinMcp] : [])],
|
|
361
|
+
extensionsOverride: (result) => prioritizeChildPromptRuntime(prioritizeChildCommandRuntime(result)),
|
|
304
362
|
...(launch.systemPrompt !== undefined ? { systemPrompt: launch.systemPrompt } : {}),
|
|
305
363
|
...(launch.appendSystemPrompt !== undefined ? { appendSystemPrompt: [launch.appendSystemPrompt] } : {}),
|
|
306
364
|
});
|
|
365
|
+
// pi's own hosts emit `session_shutdown` before disposing a session so the
|
|
366
|
+
// extensions loaded into it (ambient extensions included) release their
|
|
367
|
+
// watchers, servers, and timers. Do the same, then dispose.
|
|
368
|
+
const shutdownSession = async (session) => {
|
|
369
|
+
try {
|
|
370
|
+
await commands?.shutdown();
|
|
371
|
+
const runner = session.extensionRunner;
|
|
372
|
+
if (runner.hasHandlers("session_shutdown")) {
|
|
373
|
+
await Promise.race([runner.emit({ type: "session_shutdown", reason: "quit" }), new Promise((resolve) => setTimeout(resolve, shutdownTimeoutMs).unref?.())]);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
catch (error) {
|
|
377
|
+
launch.onExtensionError?.({ extensionPath: "<session>", event: "session_shutdown", error });
|
|
378
|
+
}
|
|
379
|
+
finally {
|
|
380
|
+
session.dispose();
|
|
381
|
+
}
|
|
382
|
+
};
|
|
307
383
|
const open = async () => {
|
|
308
384
|
const requiredPaths = new Set((launch.requiredExtensions ?? []).map(({ path }) => path));
|
|
309
385
|
applyProcessEnv(launch.processEnv);
|
|
@@ -353,39 +429,38 @@ export function createDefaultChildSessionFactory(options = {}) {
|
|
|
353
429
|
sessionStartEvent: { type: "session_start", reason: "startup" },
|
|
354
430
|
});
|
|
355
431
|
pinChildCacheRetention(session.agent);
|
|
432
|
+
// Pi reports handler failures through onError instead of throwing, so required startup failures must be collected here.
|
|
433
|
+
const requiredStartupErrors = [];
|
|
434
|
+
let binding = true;
|
|
356
435
|
try {
|
|
357
436
|
await session.bindExtensions({
|
|
358
437
|
mode: "print",
|
|
359
|
-
onError: (error) =>
|
|
438
|
+
onError: (error) => {
|
|
439
|
+
if (binding && requiredPaths.has(error.extensionPath))
|
|
440
|
+
requiredStartupErrors.push(`${error.extensionPath} (${error.event}): ${error.error}`);
|
|
441
|
+
launch.onExtensionError?.({ extensionPath: error.extensionPath, event: error.event, error: error.error });
|
|
442
|
+
},
|
|
360
443
|
});
|
|
361
444
|
}
|
|
362
445
|
catch (error) {
|
|
363
446
|
session.dispose();
|
|
364
447
|
throw error;
|
|
365
448
|
}
|
|
449
|
+
finally {
|
|
450
|
+
binding = false;
|
|
451
|
+
}
|
|
452
|
+
if (requiredStartupErrors.length > 0) {
|
|
453
|
+
// Binding finished, so the other extensions' session_start handlers ran and may hold resources.
|
|
454
|
+
await shutdownSession(session);
|
|
455
|
+
throw new Error(`Required child extension failed during startup: ${requiredStartupErrors.join("; ")}`);
|
|
456
|
+
}
|
|
366
457
|
return session;
|
|
367
458
|
};
|
|
368
459
|
const opened = loading.catch(() => { }).then(open);
|
|
369
460
|
loading = opened;
|
|
370
461
|
const session = await opened;
|
|
371
462
|
let pending;
|
|
372
|
-
|
|
373
|
-
// extensions loaded into it (ambient extensions included) release their
|
|
374
|
-
// watchers, servers, and timers. Do the same, then dispose.
|
|
375
|
-
const shutdown = async () => {
|
|
376
|
-
try {
|
|
377
|
-
const runner = session.extensionRunner;
|
|
378
|
-
if (runner.hasHandlers("session_shutdown")) {
|
|
379
|
-
await Promise.race([runner.emit({ type: "session_shutdown", reason: "quit" }), new Promise((resolve) => setTimeout(resolve, shutdownTimeoutMs).unref?.())]);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
catch (error) {
|
|
383
|
-
launch.onExtensionError?.({ extensionPath: "<session>", event: "session_shutdown", error });
|
|
384
|
-
}
|
|
385
|
-
finally {
|
|
386
|
-
session.dispose();
|
|
387
|
-
}
|
|
388
|
-
};
|
|
463
|
+
const shutdown = () => shutdownSession(session);
|
|
389
464
|
// Outside the launch lock: MCP servers connect after `session_start` without reading the per-launch env.
|
|
390
465
|
if (builtinMcpTools.length) {
|
|
391
466
|
const disposed = () => disposals !== disposalsAtStart;
|
|
@@ -408,6 +483,7 @@ export function createDefaultChildSessionFactory(options = {}) {
|
|
|
408
483
|
const child = {
|
|
409
484
|
subscribe: (listener) => session.subscribe((event) => listener(event)),
|
|
410
485
|
prompt: (text) => session.prompt(text),
|
|
486
|
+
...(commands ? { finishCommands: () => commands.finish() } : {}),
|
|
411
487
|
steer: (text) => session.steer(text),
|
|
412
488
|
followUp: (text) => session.followUp(text),
|
|
413
489
|
abort: () => session.abort(),
|
|
@@ -426,6 +502,7 @@ export function createDefaultChildSessionFactory(options = {}) {
|
|
|
426
502
|
get sessionFile() { return session.sessionFile; },
|
|
427
503
|
get sessionId() { return session.sessionId; },
|
|
428
504
|
get modelId() { return session.model ? `${session.model.provider}/${session.model.id}` : undefined; },
|
|
505
|
+
get virtualModelId() { return session.model?.api === "pi-virtual" ? `${session.model.provider}/${session.model.id}` : undefined; },
|
|
429
506
|
get contextWindow() { return session.model?.contextWindow; },
|
|
430
507
|
};
|
|
431
508
|
live.add(child);
|