pi-subagents 0.65.0 → 0.66.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 +87 -0
- package/README.md +1 -1
- package/agents/researcher.md +23 -13
- package/docs/agents.md +17 -3
- package/docs/configuration.md +34 -0
- package/docs/extension-api.md +94 -0
- package/docs/models.md +58 -1
- package/docs/observability.md +42 -2
- package/docs/tool-reference.md +11 -5
- package/docs/workflows.md +22 -7
- package/package.json +4 -1
- package/runner-server-preload.mjs +13 -0
- package/skills/pi-subagents/SKILL.md +2 -1
- package/skills/pi-subagents/references/execution-controls.md +19 -2
- package/skills/pi-subagents/references/management-authoring-rpc.md +2 -1
- package/skills/pi-subagents/references/multi-lane-orchestration.md +2 -0
- package/src/agents/advertised-agent-prompt.ts +63 -0
- package/src/agents/agent-management.ts +14 -1
- package/src/agents/agent-serializer.ts +2 -0
- package/src/agents/agents.ts +8 -0
- package/src/api/preflight.ts +5 -1
- package/src/api/shared-types.ts +1 -1
- package/src/api/workflow-resources.ts +6 -0
- package/src/extension/config.ts +4 -2
- package/src/extension/index.ts +71 -4
- package/src/extension/public-execution.ts +0 -1
- package/src/extension/rpc.ts +4 -21
- package/src/extension/schemas.ts +9 -7
- package/src/extension/tool-description.ts +10 -5
- package/src/integrations/pi-web-session-liveness.ts +73 -0
- package/src/intercom/native-supervisor-channel.ts +102 -88
- package/src/intercom/supervisor-ui.ts +3 -2
- package/src/missions/workflow-state.ts +37 -16
- package/src/runs/background/active-async-capacity.ts +18 -18
- package/src/runs/background/async-execution.ts +8 -1
- package/src/runs/background/async-job-tracker.ts +35 -3
- package/src/runs/background/async-resume.ts +3 -1
- package/src/runs/background/async-retention.ts +9 -0
- package/src/runs/background/async-status-snapshot.ts +10 -12
- package/src/runs/background/async-status.ts +17 -9
- package/src/runs/background/auto-drain.ts +40 -29
- package/src/runs/background/chain-root-attachment.ts +8 -0
- package/src/runs/background/control-channel.ts +78 -44
- package/src/runs/background/notify.ts +88 -12
- package/src/runs/background/owned-process-tree.ts +6 -6
- package/src/runs/background/process-terminal.ts +23 -23
- package/src/runs/background/retained-nested-route-tracker.ts +96 -0
- package/src/runs/background/run-child-session.ts +62 -33
- package/src/runs/background/run-status.ts +75 -5
- package/src/runs/background/runner-aliases.ts +46 -8
- package/src/runs/background/runner-child-launch.ts +86 -0
- package/src/runs/background/stale-run-reconciler.ts +3 -1
- package/src/runs/background/subagent-runner.ts +430 -208
- package/src/runs/background/subagent-wait.ts +3 -0
- package/src/runs/background/wait-completions.ts +4 -0
- package/src/runs/foreground/async-steering-action.ts +19 -0
- package/src/runs/foreground/execution.ts +116 -26
- package/src/runs/foreground/foreground-history.ts +3 -1
- package/src/runs/foreground/prompt-audit.ts +9 -5
- package/src/runs/foreground/subagent-executor.ts +531 -227
- package/src/runs/foreground/workflow-detach-reconcile.ts +8 -5
- package/src/runs/foreground/workflow-foreground-steering.ts +56 -2
- package/src/runs/shared/acceptance.ts +16 -3
- package/src/runs/shared/agent-contract.ts +1 -1
- package/src/runs/shared/async-status-projection.ts +47 -47
- package/src/runs/shared/child-hooks.ts +151 -2
- package/src/runs/shared/child-launch.ts +18 -13
- package/src/runs/shared/child-session.ts +55 -24
- package/src/runs/shared/child-tool-plan.ts +2 -2
- package/src/runs/shared/completion-evidence.ts +2 -2
- package/src/runs/shared/completion-guard.ts +1 -0
- package/src/runs/shared/host-step-status.ts +11 -11
- package/src/runs/shared/llm-intent-arbiter.ts +30 -20
- package/src/runs/shared/model-exclusions.ts +2 -1
- package/src/runs/shared/model-fallback.ts +41 -8
- package/src/runs/shared/nested-events.ts +8 -8
- package/src/runs/shared/orca-progress-tabs.ts +6 -0
- package/src/runs/shared/parallel-handoff.ts +57 -12
- package/src/runs/shared/parallel-utils.ts +3 -2
- package/src/runs/shared/readonly-drain-observation.ts +42 -0
- package/src/runs/shared/readonly-model-continuation.ts +69 -0
- package/src/runs/shared/readonly-session-evidence.ts +307 -0
- package/src/runs/shared/run-fanout-budget.ts +8 -8
- package/src/runs/shared/runtime-acknowledged-extensions.ts +3 -3
- package/src/runs/shared/subagent-prompt-runtime.ts +13 -3
- package/src/runs/shared/worktree-cleanup-plan.ts +6 -3
- package/src/runs/shared/worktree-setup-command.ts +190 -0
- package/src/runs/shared/worktree.ts +403 -210
- package/src/shared/model-response-aliases.ts +13 -0
- package/src/shared/types.ts +89 -60
- package/src/shared/utils.ts +10 -2
- package/src/shared/watch-strategy.ts +2 -0
- package/src/shared/workflow-child-permit.ts +18 -13
- package/src/tui/fleet-status.ts +1 -1
- package/src/tui/fleet.ts +11 -5
- package/src/tui/render.ts +44 -15
- package/src/workflows/chat-progress.ts +3 -3
- package/src/workflows/scripted-workflow.ts +70 -16
- package/src/workflows/workflow-checklist.ts +15 -18
- package/src/workflows/workflow-child-summary.ts +57 -8
- package/src/workflows/workflow-preflight.ts +19 -19
- package/src/workflows/workflow-receipt.ts +3 -3
- package/src/workflows/workflow-resources.ts +96 -21
- package/src/workflows/workflow-settlement.ts +3 -0
|
@@ -7,11 +7,12 @@
|
|
|
7
7
|
* this extension and are not installed next to it. pi's own extension loader
|
|
8
8
|
* aliases those specifiers to the copies shipped inside the installed pi
|
|
9
9
|
* package; the parent computes the same map and hands it to the runner
|
|
10
|
-
* through `JITI_ALIAS`, so
|
|
11
|
-
*
|
|
10
|
+
* through `JITI_ALIAS`, so child sessions and hooks retain host API identity.
|
|
11
|
+
* Only Pi 0.85.0's missing server exports may come from this extension.
|
|
12
12
|
*/
|
|
13
13
|
import * as fs from "node:fs";
|
|
14
14
|
import * as path from "node:path";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
15
16
|
|
|
16
17
|
export const JITI_ALIAS_ENV = "JITI_ALIAS";
|
|
17
18
|
|
|
@@ -19,6 +20,9 @@ export const JITI_ALIAS_ENV = "JITI_ALIAS";
|
|
|
19
20
|
export const HOST_PEER_ALIASES: ReadonlyArray<{ specifier: string; pkg: string; subpath: string }> = [
|
|
20
21
|
{ specifier: "@earendil-works/pi-coding-agent", pkg: "@earendil-works/pi-coding-agent", subpath: "." },
|
|
21
22
|
{ specifier: "@earendil-works/pi-agent-core", pkg: "@earendil-works/pi-agent-core", subpath: "." },
|
|
23
|
+
{ specifier: "@earendil-works/pi-agent-core/node", pkg: "@earendil-works/pi-agent-core", subpath: "./node" },
|
|
24
|
+
{ specifier: "@earendil-works/chord", pkg: "@earendil-works/chord", subpath: "." },
|
|
25
|
+
{ specifier: "@earendil-works/chord/context", pkg: "@earendil-works/chord", subpath: "./context" },
|
|
22
26
|
{ specifier: "@earendil-works/pi-tui", pkg: "@earendil-works/pi-tui", subpath: "." },
|
|
23
27
|
{ specifier: "@earendil-works/pi-ai", pkg: "@earendil-works/pi-ai", subpath: "./compat" },
|
|
24
28
|
{ specifier: "@earendil-works/pi-ai/compat", pkg: "@earendil-works/pi-ai", subpath: "./compat" },
|
|
@@ -29,8 +33,16 @@ export const HOST_PEER_ALIASES: ReadonlyArray<{ specifier: string; pkg: string;
|
|
|
29
33
|
{ specifier: "typebox/value", pkg: "typebox", subpath: "./value" },
|
|
30
34
|
];
|
|
31
35
|
|
|
36
|
+
/** Experimental dependencies accidentally published in exactly Pi 0.85.0. */
|
|
37
|
+
const PI0850_PEER_ALIASES = [
|
|
38
|
+
{ specifier: "@earendil-works/pi-server", pkg: "@earendil-works/pi-server", subpath: "." },
|
|
39
|
+
{ specifier: "@earendil-works/pi-server/unix", pkg: "@earendil-works/pi-server", subpath: "./unix" },
|
|
40
|
+
{ specifier: "@earendil-works/pi-client/unix", pkg: "@earendil-works/pi-client", subpath: "./unix" },
|
|
41
|
+
];
|
|
42
|
+
|
|
32
43
|
interface PackageManifest {
|
|
33
44
|
name?: unknown;
|
|
45
|
+
version?: unknown;
|
|
34
46
|
main?: unknown;
|
|
35
47
|
exports?: unknown;
|
|
36
48
|
}
|
|
@@ -95,7 +107,11 @@ export function resolvePackageSubpath(packageDir: string, subpath: string): stri
|
|
|
95
107
|
|
|
96
108
|
/** Find `pkg` as the pi package itself, one of its dependencies, or a sibling in a hoisted install. */
|
|
97
109
|
export function findHostPeerPackageDir(piPackageRoot: string, pkg: string): string | undefined {
|
|
98
|
-
|
|
110
|
+
return findPeerPackageDir(piPackageRoot, pkg, readManifest(piPackageRoot)?.name);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function findPeerPackageDir(piPackageRoot: string, pkg: string, hostName: unknown): string | undefined {
|
|
114
|
+
if (hostName === pkg) return piPackageRoot;
|
|
99
115
|
const candidates = [path.join(piPackageRoot, "node_modules", pkg)];
|
|
100
116
|
let dir = piPackageRoot;
|
|
101
117
|
for (;;) {
|
|
@@ -112,14 +128,36 @@ export function findHostPeerPackageDir(piPackageRoot: string, pkg: string): stri
|
|
|
112
128
|
}
|
|
113
129
|
|
|
114
130
|
/** The alias map the runner needs, or the specifiers that could not be resolved. */
|
|
115
|
-
export function resolveHostPeerAliases(
|
|
131
|
+
export function resolveHostPeerAliases(
|
|
132
|
+
piPackageRoot: string,
|
|
133
|
+
extensionRoot = fileURLToPath(new URL("../../../", import.meta.url)),
|
|
134
|
+
): { aliases: Record<string, string>; missing: string[]; supplemental: string[] } {
|
|
116
135
|
const aliases: Record<string, string> = {};
|
|
117
136
|
const missing: string[] = [];
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
137
|
+
const supplemental: string[] = [];
|
|
138
|
+
const hostManifest = readManifest(piPackageRoot);
|
|
139
|
+
const isPi0850 = hostManifest?.version === "0.85.0";
|
|
140
|
+
const required = isPi0850 ? [...HOST_PEER_ALIASES, ...PI0850_PEER_ALIASES] : HOST_PEER_ALIASES;
|
|
141
|
+
for (const { specifier, pkg, subpath } of required) {
|
|
142
|
+
const packageDir = findPeerPackageDir(piPackageRoot, pkg, hostManifest?.name);
|
|
143
|
+
let target = packageDir ? resolvePackageSubpath(packageDir, subpath) : undefined;
|
|
144
|
+
// Pi 0.85.0 omitted this runtime dependency. Never replace working host
|
|
145
|
+
// exports or extend this exact version contract to other peers/hosts.
|
|
146
|
+
if ((!target || !fs.existsSync(target))
|
|
147
|
+
&& (specifier === "@earendil-works/pi-server" || specifier === "@earendil-works/pi-server/unix")
|
|
148
|
+
&& isPi0850
|
|
149
|
+
&& (!packageDir || readManifest(packageDir)?.version === "0.85.0")) {
|
|
150
|
+
const localDir = findHostPeerPackageDir(extensionRoot, pkg);
|
|
151
|
+
if (localDir && readManifest(localDir)?.version === "0.85.0") {
|
|
152
|
+
const localTarget = resolvePackageSubpath(localDir, subpath);
|
|
153
|
+
if (localTarget && fs.existsSync(localTarget)) {
|
|
154
|
+
target = localTarget;
|
|
155
|
+
supplemental.push(specifier);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
121
159
|
if (target && fs.existsSync(target)) aliases[specifier] = target;
|
|
122
160
|
else missing.push(specifier);
|
|
123
161
|
}
|
|
124
|
-
return { aliases, missing };
|
|
162
|
+
return { aliases, missing, supplemental };
|
|
125
163
|
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/** Native runner construction, separate from its executable entrypoint and attempt loop. */
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { buildInProcessChildLaunch, type BuildInProcessChildLaunchInput, type InheritedChildRuntime } from "../shared/child-launch.ts";
|
|
4
|
+
import { deriveForkPromptCacheKey } from "../shared/child-tool-plan.ts";
|
|
5
|
+
import { normalizeExtensionBindings } from "../shared/extension-bindings.ts";
|
|
6
|
+
import type { RunnerSubagentStep } from "../shared/parallel-utils.ts";
|
|
7
|
+
import { formatAcceptancePrompt } from "../shared/acceptance.ts";
|
|
8
|
+
import { isAgentContract } from "../shared/agent-contract.ts";
|
|
9
|
+
|
|
10
|
+
export interface RunnerChildLaunchContext {
|
|
11
|
+
cwd: string;
|
|
12
|
+
id: string;
|
|
13
|
+
flatIndex: number;
|
|
14
|
+
artifactsDir?: string;
|
|
15
|
+
childIntercomTarget?: string;
|
|
16
|
+
orchestratorIntercomTarget?: string;
|
|
17
|
+
nestedRoute?: BuildInProcessChildLaunchInput["nestedRoute"];
|
|
18
|
+
runFanoutBudget?: BuildInProcessChildLaunchInput["runFanoutBudget"];
|
|
19
|
+
capabilityCeiling?: BuildInProcessChildLaunchInput["capabilityCeiling"];
|
|
20
|
+
inheritedChildRuntime?: InheritedChildRuntime;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function buildRunnerChildLaunch(step: RunnerSubagentStep, ctx: RunnerChildLaunchContext, attempt: {
|
|
24
|
+
model?: string;
|
|
25
|
+
sessionEnabled: boolean;
|
|
26
|
+
sessionDir?: string;
|
|
27
|
+
sessionName?: string;
|
|
28
|
+
structuredOutput?: BuildInProcessChildLaunchInput["structuredOutput"];
|
|
29
|
+
childWatchdog?: BuildInProcessChildLaunchInput["childWatchdog"];
|
|
30
|
+
watchdogStatus: NonNullable<BuildInProcessChildLaunchInput["watchdogStatus"]>;
|
|
31
|
+
}) {
|
|
32
|
+
// Resource-backed system instructions survive SDK split-turn compaction verbatim.
|
|
33
|
+
const acceptancePrompt = step.effectiveAcceptance
|
|
34
|
+
? formatAcceptancePrompt(step.effectiveAcceptance, { reportOptional: isAgentContract(step.agentContract), structuredOutput: Boolean(step.structuredOutput?.acceptanceReportPath) })
|
|
35
|
+
: "";
|
|
36
|
+
return buildInProcessChildLaunch({
|
|
37
|
+
parentSessionId: step.parentSessionId,
|
|
38
|
+
forkCacheKey: step.context === "fork" ? deriveForkPromptCacheKey(step.parentSessionId) : undefined,
|
|
39
|
+
sessionEnabled: attempt.sessionEnabled,
|
|
40
|
+
sessionDir: attempt.sessionDir,
|
|
41
|
+
sessionFile: step.sessionFile,
|
|
42
|
+
model: attempt.model,
|
|
43
|
+
inheritProjectContext: step.inheritProjectContext,
|
|
44
|
+
inheritGlobalContext: step.inheritGlobalContext,
|
|
45
|
+
inheritSkills: step.inheritSkills,
|
|
46
|
+
requireReadTool: Boolean(step.skills?.length),
|
|
47
|
+
tools: step.tools,
|
|
48
|
+
excludeTools: step.excludeTools,
|
|
49
|
+
allowNestedSubagents: step.allowNestedSubagents,
|
|
50
|
+
extensions: step.extensions,
|
|
51
|
+
subagentOnlyExtensions: step.subagentOnlyExtensions,
|
|
52
|
+
fast: step.fast,
|
|
53
|
+
modelCandidates: step.modelCandidates,
|
|
54
|
+
systemPrompt: acceptancePrompt ? `${step.systemPrompt ?? ""}\n${acceptancePrompt}` : step.systemPrompt ?? "",
|
|
55
|
+
systemPromptMode: step.systemPromptMode,
|
|
56
|
+
mcpDirectTools: step.mcpDirectTools,
|
|
57
|
+
extensionBindings: normalizeExtensionBindings(step.extensionBindings)?.value,
|
|
58
|
+
capabilityCeiling: step.capabilityCeiling ?? ctx.capabilityCeiling,
|
|
59
|
+
cwd: step.cwd ?? ctx.cwd,
|
|
60
|
+
intercomSessionName: ctx.childIntercomTarget,
|
|
61
|
+
sessionName: attempt.sessionName,
|
|
62
|
+
orchestratorIntercomTarget: ctx.orchestratorIntercomTarget,
|
|
63
|
+
runId: ctx.id,
|
|
64
|
+
childAgentName: step.agent,
|
|
65
|
+
childIndex: ctx.flatIndex,
|
|
66
|
+
nestedRoute: ctx.nestedRoute,
|
|
67
|
+
runFanoutBudget: ctx.runFanoutBudget ? {
|
|
68
|
+
...ctx.runFanoutBudget,
|
|
69
|
+
...(step.runFanoutPath ? { parentPath: `${ctx.runFanoutBudget.parentPath ? `${ctx.runFanoutBudget.parentPath}/` : ""}${step.runFanoutPath}` } : {}),
|
|
70
|
+
} : undefined,
|
|
71
|
+
structuredOutput: attempt.structuredOutput,
|
|
72
|
+
toolBudget: step.toolBudget,
|
|
73
|
+
permissionRules: step.permissionRules,
|
|
74
|
+
permissionAuditPath: step.permissionRules && ctx.artifactsDir
|
|
75
|
+
? path.join(ctx.artifactsDir, "permission-audit", `${ctx.id}-${ctx.flatIndex}.jsonl`) : undefined,
|
|
76
|
+
childWatchdog: attempt.childWatchdog,
|
|
77
|
+
// registerChildWatchdog returns before reading the sink when unconfigured.
|
|
78
|
+
...(attempt.childWatchdog ? { watchdogStatus: attempt.watchdogStatus } : {}),
|
|
79
|
+
waitToolEnabled: step.waitToolEnabled,
|
|
80
|
+
waitToolDefaultTimeoutMs: step.waitToolDefaultTimeoutMs,
|
|
81
|
+
thinkingCeiling: step.thinkingCeiling,
|
|
82
|
+
maxSubagentDepth: step.maxSubagentDepth,
|
|
83
|
+
inherited: ctx.inheritedChildRuntime,
|
|
84
|
+
host: "runner",
|
|
85
|
+
});
|
|
86
|
+
}
|
|
@@ -9,6 +9,7 @@ import { resolveEffectiveThinking } from "../../shared/model-info.ts";
|
|
|
9
9
|
import { normalizeParallelGroups } from "./parallel-groups.ts";
|
|
10
10
|
import { nestedSummaryFromAsyncStatus, projectNestedEvents, resolveNestedAsyncDir, writeNestedEvent, type NestedRoute } from "../shared/nested-events.ts";
|
|
11
11
|
import { assertWorkflowGraphHostSteps } from "../shared/host-step-status.ts";
|
|
12
|
+
import type { RawDrainStatusObserver } from "../shared/readonly-drain-observation.ts";
|
|
12
13
|
|
|
13
14
|
export type PidLiveness = "alive" | "dead" | "unknown";
|
|
14
15
|
|
|
@@ -352,9 +353,10 @@ export function checkPidLiveness(pid: number, kill: KillFn = process.kill): PidL
|
|
|
352
353
|
}
|
|
353
354
|
}
|
|
354
355
|
|
|
355
|
-
export function reconcileAsyncRun(asyncDir: string, options: ReconcileAsyncRunOptions = {}): ReconcileAsyncRunResult {
|
|
356
|
+
export function reconcileAsyncRun(asyncDir: string, options: ReconcileAsyncRunOptions = {}, observeStatus?: RawDrainStatusObserver): ReconcileAsyncRunResult {
|
|
356
357
|
const now = options.now?.() ?? Date.now();
|
|
357
358
|
const status = readStatus(asyncDir);
|
|
359
|
+
observeStatus?.(status);
|
|
358
360
|
const startedStatus = !status && options.startedRun ? buildStartedStatus(asyncDir, options.startedRun, now) : undefined;
|
|
359
361
|
const effectiveStatus = status ?? startedStatus;
|
|
360
362
|
if (!effectiveStatus) return { status: null, repaired: false };
|