pi-subagents 0.80.0 → 0.82.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 +66 -0
- package/bundle/agents.js +18 -0
- package/bundle/background-work.js +16 -0
- package/bundle/capability-ceiling.js +22 -0
- package/bundle/child-tool-plan.js +11 -0
- package/bundle/chunk-43SCHIMD.js +57 -0
- package/bundle/chunk-4QFZZV3O.js +57 -0
- package/bundle/chunk-4SDU2BZX.js +1190 -0
- package/bundle/chunk-52UBALJL.js +753 -0
- package/bundle/chunk-5LFLVSTM.js +260 -0
- package/bundle/chunk-5TYMSZX3.js +235 -0
- package/bundle/chunk-62OCY2S4.js +14 -0
- package/bundle/chunk-7F6RKT6W.js +132 -0
- package/bundle/chunk-7IVSUMQQ.js +1337 -0
- package/bundle/chunk-7J4ZXMY7.js +18 -0
- package/bundle/chunk-7PCKZHR5.js +1234 -0
- package/bundle/chunk-7YMXOYEU.js +1373 -0
- package/bundle/chunk-B5EKXDHE.js +16870 -0
- package/bundle/chunk-CIZQXJ5Q.js +8619 -0
- package/bundle/chunk-CTPAE36Y.js +94 -0
- package/bundle/chunk-D4EHT5SJ.js +14 -0
- package/bundle/chunk-GC4DSPMH.js +946 -0
- package/bundle/chunk-GJECHSAR.js +179 -0
- package/bundle/chunk-M2CTFYT3.js +4164 -0
- package/bundle/chunk-MHZ4G23A.js +1296 -0
- package/bundle/chunk-N2BN7BF5.js +159 -0
- package/bundle/chunk-NF7IEKBH.js +490 -0
- package/bundle/chunk-NGGAFDL6.js +742 -0
- package/bundle/chunk-NIXWDZZV.js +9 -0
- package/bundle/chunk-NRQ75MGH.js +8327 -0
- package/bundle/chunk-OYF6AFDY.js +458 -0
- package/bundle/chunk-PLCCBLPY.js +526 -0
- package/bundle/chunk-RMQFMMAT.js +416 -0
- package/bundle/chunk-SIJ4S3EN.js +276 -0
- package/bundle/chunk-UKG4V45O.js +228 -0
- package/bundle/chunk-VH5OAWVG.js +4096 -0
- package/bundle/chunk-W2SZ22EM.js +5462 -0
- package/bundle/chunk-WVD4UEL4.js +9367 -0
- package/bundle/chunk-XSWOTIA3.js +175 -0
- package/bundle/chunk-YFCK7H2S.js +129 -0
- package/bundle/chunk-YKEWIB4M.js +380 -0
- package/bundle/chunk-YYREO77V.js +137 -0
- package/bundle/chunk-Z7KVHQHL.js +173 -0
- package/bundle/chunk-ZLINIYTP.js +8613 -0
- package/bundle/chunk-ZQGSDHL6.js +128 -0
- package/bundle/control-channel.js +11 -0
- package/bundle/delegation.js +14 -0
- package/bundle/external-job-provider.js +20 -0
- package/bundle/external-runs.js +21 -0
- package/bundle/index.js +30 -0
- package/bundle/inspectors.js +8 -0
- package/bundle/intercom-bridge.js +11 -0
- package/bundle/preflight.js +425 -0
- package/bundle/project-panes.js +28 -0
- package/bundle/required-child-extensions.js +6 -0
- package/bundle/shared-types.js +8 -0
- package/bundle/workflow-resources.js +7 -0
- package/docs/agents.md +31 -0
- package/docs/configuration.md +9 -1
- package/docs/extension-api.md +27 -0
- package/docs/observability.md +6 -2
- package/docs/tool-reference.md +3 -1
- package/docs/workflows.md +16 -0
- package/package.json +19 -19
- package/skills/pi-subagents/references/execution-controls.md +5 -4
- package/src/agents/agent-management.js +3 -3
- package/src/agents/agent-memory.js +3 -1
- package/src/agents/agents.js +6 -6
- package/src/agents/frontmatter.d.ts +4 -0
- package/src/agents/frontmatter.js +24 -3
- package/src/agents/skills.js +2 -1
- package/src/api/delegation.d.ts +20 -0
- package/src/extension/config.js +3 -0
- package/src/extension/herdr-pi-bridge.js +17 -10
- package/src/extension/index.js +109 -9
- package/src/extension/schemas.js +3 -3
- package/src/intercom/native-supervisor-channel.js +20 -0
- package/src/missions/lifecycle.js +7 -1
- package/src/runs/background/active-async-capacity.d.ts +1 -0
- package/src/runs/background/active-async-capacity.js +9 -3
- package/src/runs/background/async-execution.js +20 -10
- package/src/runs/background/async-job-tracker.d.ts +6 -1
- package/src/runs/background/async-job-tracker.js +9 -4
- package/src/runs/background/async-status.d.ts +2 -0
- package/src/runs/background/async-status.js +21 -2
- package/src/runs/background/await-async-run.js +3 -7
- package/src/runs/background/boot-id.d.ts +12 -0
- package/src/runs/background/boot-id.js +47 -0
- package/src/runs/background/interrupted-elsewhere.d.ts +22 -0
- package/src/runs/background/interrupted-elsewhere.js +68 -0
- package/src/runs/background/notify.d.ts +2 -0
- package/src/runs/background/notify.js +13 -0
- package/src/runs/background/result-delivery-ownership.d.ts +6 -0
- package/src/runs/background/result-delivery-ownership.js +19 -1
- package/src/runs/background/result-watcher.d.ts +3 -1
- package/src/runs/background/result-watcher.js +24 -8
- package/src/runs/background/run-child-session.d.ts +1 -6
- package/src/runs/background/run-child-session.js +19 -1
- package/src/runs/background/run-status.js +2 -1
- package/src/runs/background/stale-run-reconciler.d.ts +25 -0
- package/src/runs/background/stale-run-reconciler.js +54 -13
- package/src/runs/background/subagent-runner-bootstrap.js +3 -0
- package/src/runs/background/subagent-runner.d.ts +4 -0
- package/src/runs/background/subagent-runner.js +13 -5
- package/src/runs/background/subagent-wait.d.ts +1 -1
- package/src/runs/background/subagent-wait.js +6 -1
- package/src/runs/background/terminal-run-index.d.ts +1 -0
- package/src/runs/background/terminal-run-index.js +4 -2
- package/src/runs/foreground/async-stop-action.js +3 -1
- package/src/runs/foreground/execution.js +45 -5
- package/src/runs/foreground/foreground-history.d.ts +16 -2
- package/src/runs/foreground/foreground-history.js +133 -31
- package/src/runs/foreground/subagent-executor.d.ts +11 -0
- package/src/runs/foreground/subagent-executor.js +277 -74
- package/src/runs/shared/child-launch.d.ts +2 -2
- package/src/runs/shared/child-session.d.ts +3 -2
- package/src/runs/shared/child-session.js +51 -8
- package/src/runs/shared/child-tool-plan.d.ts +7 -0
- package/src/runs/shared/child-tool-plan.js +21 -6
- package/src/runs/shared/herdr-connection.d.ts +17 -8
- package/src/runs/shared/herdr-connection.js +19 -7
- package/src/runs/shared/herdr-external-adapters.d.ts +3 -2
- package/src/runs/shared/herdr-external-adapters.js +1 -1
- package/src/runs/shared/herdr-machine.d.ts +12 -2
- package/src/runs/shared/herdr-machine.js +55 -9
- package/src/runs/shared/herdr-pane-host.d.ts +88 -0
- package/src/runs/shared/herdr-pane-host.js +155 -0
- package/src/runs/shared/herdr-placed-run.d.ts +27 -150
- package/src/runs/shared/herdr-placed-run.js +48 -395
- package/src/runs/shared/local-machine-access.d.ts +5 -0
- package/src/runs/shared/local-machine-access.js +28 -0
- package/src/runs/shared/orca-progress-tabs.d.ts +0 -1
- package/src/runs/shared/orca-progress-tabs.js +1 -24
- package/src/runs/shared/parallel-utils.d.ts +1 -1
- package/src/runs/shared/placed-run-owner.d.ts +49 -0
- package/src/runs/shared/placed-run-owner.js +93 -0
- package/src/runs/shared/placement-host.d.ts +99 -0
- package/src/runs/shared/placement-host.js +157 -0
- package/src/runs/shared/rex-machine.d.ts +25 -0
- package/src/runs/shared/rex-machine.js +83 -0
- package/src/runs/shared/rex-pane-host.d.ts +62 -0
- package/src/runs/shared/rex-pane-host.js +327 -0
- package/src/runs/shared/structured-output.d.ts +1 -0
- package/src/runs/shared/structured-output.js +1 -0
- package/src/shared/accessible-dir.js +4 -1
- package/src/shared/completion-owner.d.ts +5 -0
- package/src/shared/completion-owner.js +5 -0
- package/src/shared/provider-diagnostics.d.ts +9 -0
- package/src/shared/provider-diagnostics.js +75 -0
- package/src/shared/session-identity.d.ts +2 -0
- package/src/shared/session-identity.js +26 -0
- package/src/shared/types.d.ts +48 -6
- package/src/slash/delegation-adapters.d.ts +3 -1
- package/src/slash/delegation-adapters.js +7 -0
- package/src/slash/prompt-template-bridge.js +3 -1
- package/src/slash/subagents-admin.d.ts +1 -0
- package/src/slash/subagents-admin.js +1 -1
- package/src/tui/fleet-layout.d.ts +20 -0
- package/src/tui/fleet-layout.js +17 -0
- package/src/tui/fleet-viewport.d.ts +12 -0
- package/src/tui/fleet-viewport.js +35 -0
- package/src/tui/fleet.d.ts +6 -6
- package/src/tui/fleet.js +93 -66
- package/src/tui/render.d.ts +6 -0
- package/src/tui/render.js +3 -3
- package/src/tui/subagent-messages.js +1 -0
- package/src/workflows/scripted-workflow.d.ts +1 -1
- package/src/workflows/structured-workflow-scripts.d.ts +1 -0
- package/src/workflows/structured-workflow-scripts.js +5 -4
- package/src/workflows/workflow-auto-resume.d.ts +32 -0
- package/src/workflows/workflow-auto-resume.js +102 -0
- package/src/workflows/workflow-launch-record.d.ts +27 -0
- package/src/workflows/workflow-launch-record.js +48 -0
- package/src/workflows/workflow-resources.js +2 -2
- package/src/workflows/workflow-resume-claim.d.ts +82 -0
- package/src/workflows/workflow-resume-claim.js +210 -0
- package/src/workflows/workflow-resume.d.ts +56 -0
- package/src/workflows/workflow-resume.js +106 -0
- package/src/workflows/workflow-reuse.d.ts +15 -9
- package/src/workflows/workflow-reuse.js +77 -14
- package/src/workflows/workflow-revival.d.ts +2 -0
- package/src/workflows/workflow-revival.js +2 -1
- package/src/workflows/workflow-stop-cause.d.ts +6 -0
- package/src/workflows/workflow-stop-cause.js +8 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { connectHerdrMachine, sshMachineAccess } from "./herdr-connection.js";
|
|
3
|
+
import { HERDR_PI_MODE_ENV, HERDR_PI_RUN_ENV, HERDR_PI_RUNTIME_DIR_ENV } from "./herdr-pi-protocol.js";
|
|
4
|
+
import { createPlacedRuntimeDir, discoverPlacedBridgeManifest, PlacedRunOwner, removePlacedRuntimeDir } from "./placed-run-owner.js";
|
|
5
|
+
import { herdrPaneAllocationKey, withHerdrPaneAllocationLock } from "./placement-host.js";
|
|
6
|
+
function herdrRunState(status, fallback = "unknown") {
|
|
7
|
+
return status === "working" ? "working" : status === "blocked" ? "blocked" : status === "idle" || status === "done" ? "settled" : status === "unknown" ? "unknown" : fallback;
|
|
8
|
+
}
|
|
9
|
+
export function herdrStatusSubscriptions(paneId) {
|
|
10
|
+
return [{ type: "pane.agent_status_changed", pane_id: paneId }, { type: "pane.closed" }, { type: "pane.moved" }];
|
|
11
|
+
}
|
|
12
|
+
export function reconcileHerdrPlacedRun(identity, candidate, proveEvidence) {
|
|
13
|
+
if (candidate.endpoint.session !== identity.session)
|
|
14
|
+
return { ok: false, reason: "Herdr session changed during reconnect." };
|
|
15
|
+
const matches = candidate.agents.filter((agent) => agent.terminal_id === identity.terminalId);
|
|
16
|
+
if (matches.length !== 1 || typeof matches[0].pane_id !== "string")
|
|
17
|
+
return { ok: false, reason: matches.length ? "Terminal identity is ambiguous." : "Owned terminal is missing." };
|
|
18
|
+
const proof = proveEvidence();
|
|
19
|
+
if (!proof.ok)
|
|
20
|
+
return proof;
|
|
21
|
+
return { ok: true, state: herdrRunState(matches[0].agent_status), paneId: matches[0].pane_id, cursor: proof.cursor };
|
|
22
|
+
}
|
|
23
|
+
function idOf(value, key) { const found = value && typeof value === "object" ? value[key] : undefined; if (typeof found !== "string" || !found)
|
|
24
|
+
throw new Error(`Herdr did not return ${key}.`); return found; }
|
|
25
|
+
function list(value, key) { if (Array.isArray(value))
|
|
26
|
+
return value; const found = value && typeof value === "object" ? value[key] : undefined; return Array.isArray(found) ? found : []; }
|
|
27
|
+
function tagged(value, type, key) { if (!value || typeof value !== "object" || value.type !== type || !(key in value) || typeof value[key] !== "object")
|
|
28
|
+
throw new Error(`Herdr returned an invalid ${type} envelope.`); return value[key]; }
|
|
29
|
+
export function parseHerdrCreated(value, type) { const envelope = value; if (envelope?.type !== type)
|
|
30
|
+
throw new Error(`Herdr returned an invalid ${type} envelope.`); const tab = envelope.tab; const pane = envelope.root_pane; return { ...(type === "workspace_created" ? { workspaceId: idOf(envelope.workspace, "workspace_id") } : {}), tabId: idOf(tab, "tab_id"), paneId: idOf(pane, "pane_id") }; }
|
|
31
|
+
export function parseHerdrAgent(value, type) { return tagged(value, type, "agent"); }
|
|
32
|
+
export function parseHerdrSessionSnapshot(value) { return tagged(value, "session_snapshot", "snapshot"); }
|
|
33
|
+
export function ownsHerdrPane(agent, terminalId, paneId) { return agent.terminal_id === terminalId && agent.pane_id === paneId; }
|
|
34
|
+
function snapshotAgents(snapshot) { return list(snapshot, "agents").filter((agent) => Boolean(agent && typeof agent === "object")).map((agent) => ({ terminal_id: typeof agent.terminal_id === "string" ? agent.terminal_id : undefined, pane_id: typeof agent.pane_id === "string" ? agent.pane_id : undefined, agent_status: typeof agent.agent_status === "string" ? agent.agent_status : undefined })); }
|
|
35
|
+
export const HERDR_MAX_OWNED_PANES = 20;
|
|
36
|
+
export async function provisionHerdrPane(client, cwd, runId, runtimeDir, environment, allocationKey = cwd) {
|
|
37
|
+
return withHerdrPaneAllocationLock(allocationKey, async () => {
|
|
38
|
+
const snapshot = parseHerdrSessionSnapshot(await client.call("session.snapshot"));
|
|
39
|
+
const panes = list(snapshot, "panes").filter((item) => Boolean(item && typeof item === "object")), workspaces = list(snapshot, "workspaces").filter((item) => Boolean(item && typeof item === "object"));
|
|
40
|
+
const ownedLabel = `pi-subagents-${createHash("sha256").update(cwd).digest("hex").slice(0, 10)}`, owned = workspaces.filter((item) => item.label === ownedLabel);
|
|
41
|
+
if (owned.length > 1)
|
|
42
|
+
throw new Error("Herdr deterministic owned workspace identity is ambiguous.");
|
|
43
|
+
const cwdWorkspaceIds = new Set(panes.filter((item) => item.cwd === cwd || item.foreground_cwd === cwd).map((item) => item.workspace_id).filter((id) => typeof id === "string")), cwdWorkspaces = workspaces.filter((item) => typeof item.workspace_id === "string" && cwdWorkspaceIds.has(item.workspace_id));
|
|
44
|
+
const selected = owned[0] ?? (cwdWorkspaces.length === 1 ? cwdWorkspaces[0] : undefined), selectedId = selected ? idOf(selected, "workspace_id") : undefined, actual = selectedId ? panes.filter((pane) => pane.workspace_id === selectedId).length : 0;
|
|
45
|
+
if (actual >= HERDR_MAX_OWNED_PANES)
|
|
46
|
+
throw new Error(`Herdr workspace pane limit of ${HERDR_MAX_OWNED_PANES} is reached; close an existing pane before launching another placed run.`);
|
|
47
|
+
const env = environment ?? { [HERDR_PI_MODE_ENV]: "1", [HERDR_PI_RUN_ENV]: runId, [HERDR_PI_RUNTIME_DIR_ENV]: runtimeDir };
|
|
48
|
+
if (selectedId) {
|
|
49
|
+
const tab = parseHerdrCreated(await client.call("tab.create", { workspace_id: selectedId, cwd, label: `subagent-${runId.slice(-8)}`, env, focus: false }), "tab_created");
|
|
50
|
+
return { workspaceId: selectedId, tabId: tab.tabId, paneId: tab.paneId };
|
|
51
|
+
}
|
|
52
|
+
const workspace = parseHerdrCreated(await client.call("workspace.create", { cwd, label: ownedLabel, env, focus: false }), "workspace_created");
|
|
53
|
+
return { workspaceId: workspace.workspaceId, tabId: workspace.tabId, paneId: workspace.paneId };
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function provisionHerdrOwnedPane(connection, machine, runId, runtimeDir, environment) { return provisionHerdrPane(connection.client, machine.cwd, runId, runtimeDir, environment, herdrPaneAllocationKey(machine.target, connection.endpoint.session, machine.cwd)); }
|
|
57
|
+
function asHerdrMachine(machine) { if (machine.provider !== "herdr")
|
|
58
|
+
throw new Error("The Herdr pane host only places runs on Herdr saved machines."); return machine; }
|
|
59
|
+
async function startHerdrAgent(connection, owned, kind, name, args, options = {}) {
|
|
60
|
+
const clock = options.clock ?? { now: () => Date.now(), wait: (ms) => new Promise((resolve) => setTimeout(resolve, ms)) }, deadline = clock.now() + (options.timeoutMs ?? 5_000), pollMs = options.pollMs ?? 50;
|
|
61
|
+
let response;
|
|
62
|
+
for (;;) {
|
|
63
|
+
try {
|
|
64
|
+
response = await connection.client.call("agent.start", { name, kind, pane_id: owned.paneId, args, timeout_ms: 45_000 }, 60_000);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
if (!(error instanceof Error) || !error.message.includes("is not an available shell"))
|
|
69
|
+
throw error;
|
|
70
|
+
const pane = tagged(await connection.client.call("pane.get", { pane_id: owned.paneId }), "pane_info", "pane");
|
|
71
|
+
if (pane.pane_id !== owned.paneId || pane.workspace_id !== owned.workspaceId || pane.tab_id !== owned.tabId)
|
|
72
|
+
throw new Error("Herdr startup pane identity changed after a transient start rejection.", { cause: error });
|
|
73
|
+
if (pane.agent != null || pane.agent_session != null)
|
|
74
|
+
throw new Error("Herdr startup pane became occupied after a transient start rejection.", { cause: error });
|
|
75
|
+
if (clock.now() >= deadline)
|
|
76
|
+
throw new Error("Herdr owned pane remained unavailable until the startup deadline.", { cause: error });
|
|
77
|
+
await clock.wait(Math.min(pollMs, deadline - clock.now()));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
const started = parseHerdrAgent(response, "agent_started"), terminalId = idOf(started, "terminal_id"), paneId = idOf(started, "pane_id");
|
|
81
|
+
if (paneId !== owned.paneId)
|
|
82
|
+
throw new Error("Herdr started the native agent in an unexpected pane.");
|
|
83
|
+
return { terminalId, paneId };
|
|
84
|
+
}
|
|
85
|
+
async function closeOwnedHerdrPane(connection, owned, terminalId, agentName) {
|
|
86
|
+
let closed = false;
|
|
87
|
+
if (terminalId && agentName) {
|
|
88
|
+
const current = parseHerdrAgent(await connection.client.call("agent.get", { target: agentName }), "agent_info");
|
|
89
|
+
if (ownsHerdrPane(current, terminalId, owned.paneId)) {
|
|
90
|
+
await connection.client.call("pane.close", { pane_id: owned.paneId });
|
|
91
|
+
closed = true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (!closed) {
|
|
95
|
+
const snapshot = parseHerdrSessionSnapshot(await connection.client.call("session.snapshot"));
|
|
96
|
+
const occupants = snapshotAgents(snapshot).filter((agent) => agent.pane_id === owned.paneId);
|
|
97
|
+
if (occupants.length !== 0)
|
|
98
|
+
throw new Error("Refusing cleanup because startup pane ownership is uncertain.");
|
|
99
|
+
await connection.client.call("pane.close", { pane_id: owned.paneId });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** Herdr pane host: Herdr RPC over the SSH-forwarded Herdr socket. Ownership is the Herdr terminal_id/pane_id pair; run state comes from agent_status. */
|
|
103
|
+
export const herdrPaneHost = {
|
|
104
|
+
connect(machine) { return connectHerdrMachine(asHerdrMachine(machine)); },
|
|
105
|
+
sessionOf(connection) { return connection.endpoint.session; },
|
|
106
|
+
async launch(connection, machine, runId, runtimeDir, request, onPane, options) { const owned = await provisionHerdrOwnedPane(connection, asHerdrMachine(machine), runId, runtimeDir, request.environment); await onPane(owned); const { terminalId } = await startHerdrAgent(connection, owned, request.kind, request.name, request.args, options); return { owned, terminalId }; },
|
|
107
|
+
async prompt(connection, identity, text) { await connection.client.call("agent.prompt", { target: identity.agentName, text }); },
|
|
108
|
+
subscribe(connection, paneId, listener, onDisconnect) { return connection.client.subscribe(herdrStatusSubscriptions(paneId), listener, onDisconnect); },
|
|
109
|
+
paneEvent(event, fallback) { const data = event && typeof event === "object" ? event.data : undefined; return data ? { terminalId: data.terminal_id, paneId: data.pane_id, state: herdrRunState(data.agent_status, fallback) } : undefined; },
|
|
110
|
+
async panes(connection) { return { endpoint: connection.endpoint, agents: snapshotAgents(parseHerdrSessionSnapshot(await connection.client.call("session.snapshot"))) }; },
|
|
111
|
+
reconcile: reconcileHerdrPlacedRun,
|
|
112
|
+
closeOwnedPane: closeOwnedHerdrPane,
|
|
113
|
+
};
|
|
114
|
+
/** SSH entry points for the host-neutral runtime-dir and manifest helpers. */
|
|
115
|
+
export function discoverBridgeManifest(machine, runId, runtimeDir, options = {}) { return discoverPlacedBridgeManifest(sshMachineAccess(machine, options), runId, runtimeDir); }
|
|
116
|
+
export function createRemoteRuntimeDir(machine, runId, options = {}) { return createPlacedRuntimeDir(sshMachineAccess(machine, options), runId); }
|
|
117
|
+
export function removeRemoteRuntimeDir(machine, runtimeDir, options = {}) { removePlacedRuntimeDir(sshMachineAccess(machine, options), runtimeDir); }
|
|
118
|
+
/** The placed-run owner bound to Herdr and SSH access, plus the separate provision and start steps the external CLI adapters use. */
|
|
119
|
+
export class HerdrPlacedRunOwner extends PlacedRunOwner {
|
|
120
|
+
constructor(machine, runId, runtimeDir, connection, removeRuntime) { super(machine, runId, runtimeDir, connection, herdrPaneHost, sshMachineAccess(machine), removeRuntime); }
|
|
121
|
+
static async create(machine, runId, beforePane) { const runtimeDir = await createRemoteRuntimeDir(machine, runId); let connection; try {
|
|
122
|
+
connection = await herdrPaneHost.connect(machine);
|
|
123
|
+
const owner = new HerdrPlacedRunOwner(machine, runId, runtimeDir, connection);
|
|
124
|
+
await beforePane?.(owner);
|
|
125
|
+
return owner;
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
const cleanupErrors = [];
|
|
129
|
+
try {
|
|
130
|
+
await connection?.close();
|
|
131
|
+
}
|
|
132
|
+
catch (cleanupError) {
|
|
133
|
+
cleanupErrors.push(cleanupError);
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
removeRemoteRuntimeDir(machine, runtimeDir);
|
|
137
|
+
}
|
|
138
|
+
catch (cleanupError) {
|
|
139
|
+
cleanupErrors.push(cleanupError);
|
|
140
|
+
}
|
|
141
|
+
if (cleanupErrors.length)
|
|
142
|
+
throw new AggregateError([error, ...cleanupErrors], "Herdr owner creation failed and cleanup also failed.", { cause: error });
|
|
143
|
+
throw error;
|
|
144
|
+
} }
|
|
145
|
+
async provision(environment) { this.owned = await provisionHerdrOwnedPane(this.connection, this.machine, this.runId, this.runtimeDir, environment); return this.owned; }
|
|
146
|
+
async start(kind, name, args, options = {}) {
|
|
147
|
+
if (!this.owned)
|
|
148
|
+
throw new Error("Herdr placement owner has not provisioned its pane.");
|
|
149
|
+
const { terminalId, paneId } = await startHerdrAgent(this.connection, this.owned, kind, name, args, options), argv = [kind, ...args];
|
|
150
|
+
this.agentName = name;
|
|
151
|
+
this.terminalId = terminalId;
|
|
152
|
+
this.startedArgv = argv;
|
|
153
|
+
return { terminalId, paneId, argv };
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import * as net from "node:net";
|
|
2
2
|
import type { AgentMessage } from "@earendil-works/pi-agent-core";
|
|
3
|
-
import type {
|
|
3
|
+
import type { HerdrRemoteGitStatus, PlacementMachineReference } from "../../shared/types.ts";
|
|
4
4
|
import type { ChildSession, ChildSessionEvent, ChildSessionFactory, ChildSessionLaunch } from "./child-session.ts";
|
|
5
5
|
import type { ChildRuntimeConfig } from "./child-runtime-config.ts";
|
|
6
|
-
import { connectHerdrMachine, type HerdrForwardedConnection, type HerdrRpcClient } from "./herdr-connection.ts";
|
|
7
6
|
import { HerdrPiFrameDecoder, type HerdrPiFrame } from "./herdr-pi-protocol.ts";
|
|
7
|
+
import { type PlacedBridgeManifest, type PlacedRunOwner } from "./placed-run-owner.ts";
|
|
8
|
+
import type { PlacementBridgeIdentity, PlacementPaneHost, PlacementReconnectCheck, PlacementRunState, PlacementSockets } from "./placement-host.ts";
|
|
8
9
|
export interface HerdrRunIdentity {
|
|
9
10
|
runId: string;
|
|
10
11
|
machineId: string;
|
|
@@ -21,82 +22,30 @@ export interface HerdrRunIdentity {
|
|
|
21
22
|
}
|
|
22
23
|
export interface HerdrRunSnapshot {
|
|
23
24
|
connection: "connected" | "unknown" | "closed";
|
|
24
|
-
state:
|
|
25
|
+
state: PlacementRunState;
|
|
25
26
|
identity?: HerdrRunIdentity;
|
|
26
27
|
revision: number;
|
|
27
28
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
terminal_id?: string;
|
|
36
|
-
pane_id?: string;
|
|
37
|
-
agent_status?: string;
|
|
38
|
-
}>;
|
|
39
|
-
bridge: {
|
|
40
|
-
runId?: string;
|
|
41
|
-
nativeSessionId?: string;
|
|
42
|
-
packageVersion?: string;
|
|
43
|
-
protocol?: number;
|
|
44
|
-
evidenceCursor?: number;
|
|
45
|
-
evidenceFloor?: number;
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
export declare function herdrStatusSubscriptions(paneId: string): unknown[];
|
|
49
|
-
export declare function reconcileHerdrPlacedRun(identity: HerdrRunIdentity, candidate: HerdrReconnectCandidate, proveEvidence: () => {
|
|
50
|
-
ok: true;
|
|
51
|
-
cursor: number;
|
|
52
|
-
} | {
|
|
53
|
-
ok: false;
|
|
54
|
-
reason: string;
|
|
55
|
-
}): {
|
|
56
|
-
ok: true;
|
|
57
|
-
state: HerdrRunSnapshot["state"];
|
|
58
|
-
paneId: string;
|
|
59
|
-
cursor: number;
|
|
60
|
-
} | {
|
|
61
|
-
ok: false;
|
|
62
|
-
reason: string;
|
|
63
|
-
};
|
|
64
|
-
export declare function reconcileHerdrReconnect(identity: HerdrRunIdentity, candidate: HerdrReconnectCandidate, lastEvidenceCursor: number): {
|
|
65
|
-
ok: true;
|
|
66
|
-
state: HerdrRunSnapshot["state"];
|
|
67
|
-
paneId: string;
|
|
68
|
-
cursor: number;
|
|
69
|
-
} | {
|
|
70
|
-
ok: false;
|
|
71
|
-
reason: string;
|
|
72
|
-
};
|
|
73
|
-
export declare function boundedHerdrReconnect(identity: HerdrRunIdentity, lastEvidenceCursor: number, attempt: (number: number) => Promise<HerdrReconnectCandidate>, options?: {
|
|
29
|
+
/** The pane half comes from the host; the bridge half (run, package, protocol, native session, evidence cursor) is host-neutral. */
|
|
30
|
+
export declare function reconcileHerdrReconnect(identity: HerdrRunIdentity, candidate: {
|
|
31
|
+
bridge: PlacementBridgeIdentity;
|
|
32
|
+
}, lastEvidenceCursor: number, host?: Pick<PlacementPaneHost, "reconcile">): PlacementReconnectCheck;
|
|
33
|
+
export declare function boundedHerdrReconnect(identity: HerdrRunIdentity, lastEvidenceCursor: number, attempt: (number: number) => Promise<{
|
|
34
|
+
bridge: PlacementBridgeIdentity;
|
|
35
|
+
}>, options?: {
|
|
74
36
|
attempts?: number;
|
|
75
37
|
deadlineMs?: number;
|
|
76
38
|
disposed?: () => boolean;
|
|
39
|
+
host?: Pick<PlacementPaneHost, "reconcile">;
|
|
77
40
|
}): Promise<{
|
|
78
41
|
ok: true;
|
|
79
|
-
state:
|
|
42
|
+
state: PlacementRunState;
|
|
80
43
|
paneId: string;
|
|
81
44
|
cursor: number;
|
|
82
45
|
} | {
|
|
83
46
|
ok: false;
|
|
84
47
|
reason: string;
|
|
85
48
|
}>;
|
|
86
|
-
export declare function parseHerdrCreated(value: unknown, type: "workspace_created" | "tab_created"): {
|
|
87
|
-
workspaceId?: string;
|
|
88
|
-
tabId: string;
|
|
89
|
-
paneId: string;
|
|
90
|
-
};
|
|
91
|
-
export declare function parseHerdrAgent(value: unknown, type: "agent_started" | "agent_info" | "agent_prompted"): Record<string, unknown>;
|
|
92
|
-
export declare function parseHerdrSessionSnapshot(value: unknown): Record<string, unknown>;
|
|
93
|
-
export declare function ownsHerdrPane(agent: Record<string, unknown>, terminalId: string, paneId: string): boolean;
|
|
94
|
-
export declare const HERDR_MAX_OWNED_PANES = 20;
|
|
95
|
-
export declare function herdrPaneAllocationKey(target: string, session: string | null, cwd: string): string;
|
|
96
|
-
export declare function withHerdrPaneAllocationLock<T>(key: string, action: () => Promise<T>, options?: {
|
|
97
|
-
timeoutMs?: number;
|
|
98
|
-
pollMs?: number;
|
|
99
|
-
}): Promise<T>;
|
|
100
49
|
export declare function serializeHerdrPiLaunch(launch: ChildSessionLaunch): {
|
|
101
50
|
args: string[];
|
|
102
51
|
resources: {
|
|
@@ -106,81 +55,6 @@ export declare function serializeHerdrPiLaunch(launch: ChildSessionLaunch): {
|
|
|
106
55
|
reads?: string[] | false;
|
|
107
56
|
};
|
|
108
57
|
};
|
|
109
|
-
export declare function provisionHerdrPane(client: HerdrRpcClient, cwd: string, runId: string, runtimeDir: string, environment?: Record<string, string>, allocationKey?: string): Promise<{
|
|
110
|
-
workspaceId: string;
|
|
111
|
-
tabId: string;
|
|
112
|
-
paneId: string;
|
|
113
|
-
}>;
|
|
114
|
-
export declare function discoverBridgeManifest(machine: HerdrMachineReference, runId: string, runtimeDir: string, options?: {
|
|
115
|
-
sshBin?: string;
|
|
116
|
-
env?: NodeJS.ProcessEnv;
|
|
117
|
-
}): Promise<{
|
|
118
|
-
socketPath: string;
|
|
119
|
-
nativeSessionId: string;
|
|
120
|
-
packageVersion: string;
|
|
121
|
-
protocol: number;
|
|
122
|
-
}>;
|
|
123
|
-
export declare function createRemoteRuntimeDir(machine: HerdrMachineReference, runId: string, options?: {
|
|
124
|
-
sshBin?: string;
|
|
125
|
-
env?: NodeJS.ProcessEnv;
|
|
126
|
-
}): Promise<string>;
|
|
127
|
-
export declare function removeRemoteRuntimeDir(machine: HerdrMachineReference, runtimeDir: string, options?: {
|
|
128
|
-
sshBin?: string;
|
|
129
|
-
env?: NodeJS.ProcessEnv;
|
|
130
|
-
}): void;
|
|
131
|
-
/** The single private owner for allocation shared by every pane-native backend projection. */
|
|
132
|
-
export declare class HerdrPlacedRunOwner {
|
|
133
|
-
#private;
|
|
134
|
-
readonly machine: HerdrMachineReference;
|
|
135
|
-
readonly runId: string;
|
|
136
|
-
readonly runtimeDir: string;
|
|
137
|
-
connection: HerdrForwardedConnection;
|
|
138
|
-
owned?: {
|
|
139
|
-
workspaceId: string;
|
|
140
|
-
tabId: string;
|
|
141
|
-
paneId: string;
|
|
142
|
-
};
|
|
143
|
-
terminalId?: string;
|
|
144
|
-
agentName?: string;
|
|
145
|
-
startedArgv?: string[];
|
|
146
|
-
identity?: HerdrRunIdentity;
|
|
147
|
-
private constructor();
|
|
148
|
-
static create(machine: HerdrMachineReference, runId: string, beforePane?: (owner: HerdrPlacedRunOwner) => void | Promise<void>): Promise<HerdrPlacedRunOwner>;
|
|
149
|
-
observeEvent(event: unknown): void;
|
|
150
|
-
markConnectionUnknown(observed: HerdrForwardedConnection): boolean;
|
|
151
|
-
statusSubscriptions(paneId?: string | undefined): unknown[];
|
|
152
|
-
subscribe(listener: (event: unknown) => void, disconnected: (error: Error) => void): Promise<void>;
|
|
153
|
-
provision(environment?: Record<string, string>): Promise<{
|
|
154
|
-
workspaceId: string;
|
|
155
|
-
tabId: string;
|
|
156
|
-
paneId: string;
|
|
157
|
-
}>;
|
|
158
|
-
start(kind: "pi" | "claude" | "cursor" | "codex", name: string, args: string[], options?: {
|
|
159
|
-
timeoutMs?: number;
|
|
160
|
-
pollMs?: number;
|
|
161
|
-
clock?: {
|
|
162
|
-
now(): number;
|
|
163
|
-
wait(ms: number): Promise<void>;
|
|
164
|
-
};
|
|
165
|
-
}): Promise<{
|
|
166
|
-
terminalId: string;
|
|
167
|
-
paneId: string;
|
|
168
|
-
argv: string[];
|
|
169
|
-
}>;
|
|
170
|
-
journal(identity: HerdrRunIdentity): void;
|
|
171
|
-
get snapshot(): HerdrRunSnapshot;
|
|
172
|
-
runRemote(command: string, options?: {
|
|
173
|
-
timeout?: number;
|
|
174
|
-
maxBuffer?: number;
|
|
175
|
-
}): import("child_process").SpawnSyncReturns<string>;
|
|
176
|
-
replaceConnection(input: {
|
|
177
|
-
connection: HerdrForwardedConnection;
|
|
178
|
-
unsubscribe: () => void;
|
|
179
|
-
paneId: string;
|
|
180
|
-
state: HerdrRunSnapshot["state"];
|
|
181
|
-
}): Promise<void>;
|
|
182
|
-
cleanup(closeStartedPane?: boolean): Promise<void>;
|
|
183
|
-
}
|
|
184
58
|
export declare class BridgeChannel {
|
|
185
59
|
#private;
|
|
186
60
|
readonly socket: net.Socket;
|
|
@@ -205,10 +79,10 @@ export declare class BridgeChannel {
|
|
|
205
79
|
reads?: string[] | false;
|
|
206
80
|
}): Promise<HerdrPiFrame>;
|
|
207
81
|
supervisorDelivered(requestId: string): void;
|
|
208
|
-
prepare(requestId: string, operation: string, text?: string, supervisorId?: string): Promise<HerdrPiFrame>;
|
|
82
|
+
prepare(requestId: string, operation: string, text?: string, supervisorId?: string, supervisorError?: string): Promise<HerdrPiFrame>;
|
|
209
83
|
close(): void;
|
|
210
84
|
}
|
|
211
|
-
export declare class HerdrPiSession implements ChildSession {
|
|
85
|
+
export declare class HerdrPiSession<C extends PlacementSockets = PlacementSockets> implements ChildSession {
|
|
212
86
|
#private;
|
|
213
87
|
bridgeForward: {
|
|
214
88
|
close(): Promise<void>;
|
|
@@ -218,19 +92,20 @@ export declare class HerdrPiSession implements ChildSession {
|
|
|
218
92
|
readonly model: string | undefined;
|
|
219
93
|
readonly supervisorDir: string | undefined;
|
|
220
94
|
readonly runtime: ChildRuntimeConfig;
|
|
221
|
-
readonly owner:
|
|
222
|
-
constructor(owner:
|
|
95
|
+
readonly owner: PlacedRunOwner<C>;
|
|
96
|
+
constructor(owner: PlacedRunOwner<C>, bridgeForward: {
|
|
223
97
|
close(): Promise<void>;
|
|
224
98
|
}, bridge: BridgeChannel, requestedTools: string[] | undefined, model: string | undefined, runtime: ChildRuntimeConfig, initialGit?: HerdrRemoteGitStatus);
|
|
99
|
+
get host(): PlacementPaneHost<C>;
|
|
225
100
|
get identity(): HerdrRunIdentity;
|
|
226
101
|
set identity(value: HerdrRunIdentity);
|
|
227
|
-
get connection():
|
|
228
|
-
set connection(value:
|
|
102
|
+
get connection(): C;
|
|
103
|
+
set connection(value: C);
|
|
229
104
|
armReconnect(factory: () => Promise<void>): void;
|
|
230
105
|
get evidenceCursor(): number;
|
|
231
106
|
reconnect(): Promise<void>;
|
|
232
107
|
replaceTransport(input: {
|
|
233
|
-
connection:
|
|
108
|
+
connection: C;
|
|
234
109
|
bridgeForward: {
|
|
235
110
|
close(): Promise<void>;
|
|
236
111
|
};
|
|
@@ -240,7 +115,6 @@ export declare class HerdrPiSession implements ChildSession {
|
|
|
240
115
|
cursor: number;
|
|
241
116
|
state: HerdrRunSnapshot["state"];
|
|
242
117
|
}): Promise<void>;
|
|
243
|
-
observeHerdr(value: unknown): void;
|
|
244
118
|
subscribe(listener: (event: ChildSessionEvent) => void): () => boolean;
|
|
245
119
|
prompt(text: string): Promise<void>;
|
|
246
120
|
steer(text: string): Promise<void>;
|
|
@@ -254,14 +128,17 @@ export declare class HerdrPiSession implements ChildSession {
|
|
|
254
128
|
get machineEvidence(): {
|
|
255
129
|
final?: HerdrRemoteGitStatus | undefined;
|
|
256
130
|
initial?: HerdrRemoteGitStatus | undefined;
|
|
131
|
+
provider: "herdr" | "rex";
|
|
257
132
|
machineId: string;
|
|
258
133
|
};
|
|
259
134
|
get placementSnapshot(): HerdrRunSnapshot;
|
|
260
135
|
}
|
|
261
|
-
export declare function reconnectHerdrPiSession(session: HerdrPiSession
|
|
262
|
-
connect?:
|
|
263
|
-
discoverManifest?:
|
|
136
|
+
export declare function reconnectHerdrPiSession<C extends PlacementSockets>(session: HerdrPiSession<C>, launch: ChildSessionLaunch, dependencies?: {
|
|
137
|
+
connect?: (machine: PlacementMachineReference) => Promise<C>;
|
|
138
|
+
discoverManifest?: (runId: string, runtimeDir: string) => Promise<PlacedBridgeManifest>;
|
|
264
139
|
createBridge?: (socketPath: string, runId: string) => BridgeChannel;
|
|
265
140
|
}): Promise<void>;
|
|
266
141
|
export declare function createHerdrPiSession(launch: ChildSessionLaunch): Promise<ChildSession>;
|
|
142
|
+
/** A Rex machine: the same bridge session, with the Rex pane host and local (`machine: "local"`) or SSH machine access. */
|
|
143
|
+
export declare function createRexPiSession(launch: ChildSessionLaunch): Promise<ChildSession>;
|
|
267
144
|
export declare function createPlacementAwareChildSessionFactory(local: ChildSessionFactory, createRemote?: (launch: ChildSessionLaunch) => Promise<ChildSession>): ChildSessionFactory;
|