pi-subagents 0.81.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 +38 -0
- package/bundle/agents.js +3 -3
- package/bundle/child-tool-plan.js +2 -2
- package/bundle/{chunk-LSRUTHT7.js → chunk-43SCHIMD.js} +1 -1
- package/bundle/{chunk-G5DKFLLI.js → chunk-4SDU2BZX.js} +15 -10
- package/bundle/{chunk-V2JWDB5U.js → chunk-52UBALJL.js} +2 -2
- package/bundle/{chunk-3DC5KBVP.js → chunk-5TYMSZX3.js} +1 -1
- package/bundle/{chunk-CEKS3TFO.js → chunk-7IVSUMQQ.js} +6 -6
- package/bundle/{chunk-KSWQVGDW.js → chunk-7PCKZHR5.js} +225 -18
- package/bundle/{chunk-563BHAZ5.js → chunk-7YMXOYEU.js} +33 -25
- package/bundle/{chunk-XMFLCKMQ.js → chunk-B5EKXDHE.js} +336 -130
- package/bundle/{chunk-ZBC44JJ3.js → chunk-CIZQXJ5Q.js} +22 -9
- package/bundle/{chunk-L5ZHE4L4.js → chunk-GC4DSPMH.js} +4 -4
- package/bundle/{chunk-ARRKBB2B.js → chunk-GJECHSAR.js} +2 -2
- package/bundle/{chunk-2ZSNH26H.js → chunk-M2CTFYT3.js} +7 -7
- package/bundle/{chunk-TUWLXTAM.js → chunk-MHZ4G23A.js} +681 -320
- package/bundle/{chunk-WSBNENFS.js → chunk-NGGAFDL6.js} +14 -4
- package/bundle/{chunk-VJHOELQP.js → chunk-NRQ75MGH.js} +160 -78
- package/bundle/{chunk-BJN5LUQY.js → chunk-OYF6AFDY.js} +1 -1
- package/bundle/{chunk-EYNJ6VL6.js → chunk-PLCCBLPY.js} +2 -2
- package/bundle/{chunk-74RT5YQE.js → chunk-RMQFMMAT.js} +123 -33
- package/bundle/{chunk-V6MR5TOQ.js → chunk-SIJ4S3EN.js} +25 -19
- package/bundle/{chunk-NNLASTQE.js → chunk-VH5OAWVG.js} +19 -5
- package/bundle/{chunk-BPS2AGBZ.js → chunk-W2SZ22EM.js} +93 -52
- package/bundle/{chunk-V3BIUPLU.js → chunk-WVD4UEL4.js} +256 -52
- package/bundle/{chunk-ZP3HODFH.js → chunk-XSWOTIA3.js} +1 -1
- package/bundle/{chunk-3IF2PGW7.js → chunk-YKEWIB4M.js} +1 -1
- package/bundle/{chunk-26C3WLYQ.js → chunk-ZLINIYTP.js} +497 -272
- package/bundle/{chunk-2XYWN7QJ.js → chunk-ZQGSDHL6.js} +2 -2
- package/bundle/control-channel.js +2 -2
- package/bundle/index.js +1 -1
- package/bundle/intercom-bridge.js +2 -2
- package/bundle/preflight.js +8 -8
- package/bundle/project-panes.js +3 -3
- package/docs/agents.md +31 -0
- package/docs/configuration.md +9 -1
- package/docs/tool-reference.md +3 -1
- package/docs/workflows.md +16 -0
- package/package.json +2 -2
- 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 +2 -0
- package/src/agents/frontmatter.js +15 -1
- package/src/agents/skills.js +2 -1
- package/src/extension/config.js +3 -0
- package/src/extension/herdr-pi-bridge.js +17 -10
- package/src/extension/index.js +82 -2
- 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 +1 -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 +52 -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 +6 -3
- 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/shared/completion-owner.d.ts +5 -0
- package/src/shared/completion-owner.js +5 -0
- package/src/shared/session-identity.d.ts +2 -0
- package/src/shared/session-identity.js +26 -0
- package/src/shared/types.d.ts +45 -6
- package/src/tui/fleet.d.ts +1 -0
- package/src/tui/fleet.js +24 -15
- 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/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-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
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
projectTimeoutRecovery,
|
|
12
12
|
readAsyncRecoveryDescriptor,
|
|
13
13
|
utf8Tail
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-VH5OAWVG.js";
|
|
15
15
|
import {
|
|
16
16
|
MAX_ARGS_BYTES,
|
|
17
17
|
MAX_ARGS_DEPTH,
|
|
@@ -24,13 +24,13 @@ import {
|
|
|
24
24
|
resultFilePath,
|
|
25
25
|
resultPayloadMatchesSessionRun,
|
|
26
26
|
resultPayloadPathForSessionRun
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-NRQ75MGH.js";
|
|
28
28
|
import {
|
|
29
29
|
shouldUseNativeFsWatch
|
|
30
30
|
} from "./chunk-NIXWDZZV.js";
|
|
31
31
|
import {
|
|
32
32
|
PROJECT_SUBAGENTS_RELATIVE_DIR
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-5TYMSZX3.js";
|
|
34
34
|
import {
|
|
35
35
|
listBackgroundWorkWakeChannels,
|
|
36
36
|
snapshotBackgroundWork
|
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
withSettingsFileLease,
|
|
56
56
|
writeAtomicJson,
|
|
57
57
|
writePrivateAtomicJson
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-CIZQXJ5Q.js";
|
|
59
59
|
import {
|
|
60
60
|
ASYNC_DIR,
|
|
61
61
|
DIRS,
|
|
@@ -213,6 +213,7 @@ async function waitForReply(channelDir, requestId, initialDeadline, signal) {
|
|
|
213
213
|
if (fs.existsSync(file)) {
|
|
214
214
|
const parsed = JSON.parse(fs.readFileSync(file, "utf-8"));
|
|
215
215
|
if (parsed.type === "subagent.supervisor.reply" && parsed.requestId === requestId && typeof parsed.message === "string") {
|
|
216
|
+
if (typeof parsed.error === "string") throw new Error(parsed.error);
|
|
216
217
|
return parsed;
|
|
217
218
|
}
|
|
218
219
|
}
|
|
@@ -748,6 +749,24 @@ function createNativeSupervisorChannel(pi, state, deps = {}) {
|
|
|
748
749
|
cleanupRequestLifecycle(request, lifecycle);
|
|
749
750
|
continue;
|
|
750
751
|
}
|
|
752
|
+
if (request.expectsReply && runState(request).blockingWorkflowChildren?.has(request.runId)) {
|
|
753
|
+
try {
|
|
754
|
+
writePrivateAtomicJson(replyPath(channelDir, request.id), {
|
|
755
|
+
type: "subagent.supervisor.reply",
|
|
756
|
+
requestId: request.id,
|
|
757
|
+
createdAt: now,
|
|
758
|
+
message: "",
|
|
759
|
+
error: "Supervisor unavailable: the parent is blocked in an async:false workflow and cannot answer this request. Report the blocker and any partial results, then stop. Relaunch the workflow with async:true to allow supervisor replies."
|
|
760
|
+
});
|
|
761
|
+
} catch (error) {
|
|
762
|
+
console.error(`Failed to report unreachable supervisor request ${request.id}; will retry:`, error);
|
|
763
|
+
continue;
|
|
764
|
+
}
|
|
765
|
+
seenFiles.add(file);
|
|
766
|
+
observeRequestLifecycle(request, "resolved");
|
|
767
|
+
cleanupRequestLifecycle(request, "resolved");
|
|
768
|
+
continue;
|
|
769
|
+
}
|
|
751
770
|
seenFiles.add(file);
|
|
752
771
|
if (!request.expectsReply) {
|
|
753
772
|
removeRequestFile(request.requestFile);
|
|
@@ -1037,14 +1056,34 @@ function createNativeSupervisorChannel(pi, state, deps = {}) {
|
|
|
1037
1056
|
}
|
|
1038
1057
|
|
|
1039
1058
|
// src/shared/session-identity.ts
|
|
1059
|
+
import * as fs2 from "node:fs";
|
|
1040
1060
|
function resolveCurrentSessionId(sessionManager) {
|
|
1041
1061
|
const sessionId = sessionManager.getSessionFile() ?? sessionManager.getSessionId();
|
|
1042
1062
|
if (!sessionId) throw new Error("Current session identity is unavailable.");
|
|
1043
1063
|
return sessionId;
|
|
1044
1064
|
}
|
|
1065
|
+
function resolvePiSessionId(sessionFile) {
|
|
1066
|
+
if (!sessionFile) return void 0;
|
|
1067
|
+
try {
|
|
1068
|
+
const fd = fs2.openSync(sessionFile, "r");
|
|
1069
|
+
try {
|
|
1070
|
+
const buffer = Buffer.alloc(16 * 1024);
|
|
1071
|
+
const bytes = fs2.readSync(fd, buffer, 0, buffer.length, 0);
|
|
1072
|
+
const line = buffer.toString("utf-8", 0, bytes).split("\n", 1)[0];
|
|
1073
|
+
if (!line) return void 0;
|
|
1074
|
+
const header = JSON.parse(line);
|
|
1075
|
+
if (header.type === "session" && typeof header.id === "string" && /^[A-Za-z0-9-]{8,}$/.test(header.id)) return header.id;
|
|
1076
|
+
return void 0;
|
|
1077
|
+
} finally {
|
|
1078
|
+
fs2.closeSync(fd);
|
|
1079
|
+
}
|
|
1080
|
+
} catch {
|
|
1081
|
+
return void 0;
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1045
1084
|
|
|
1046
1085
|
// src/watchdog/settings.ts
|
|
1047
|
-
import * as
|
|
1086
|
+
import * as fs3 from "node:fs";
|
|
1048
1087
|
import * as path2 from "node:path";
|
|
1049
1088
|
var DEFAULT_WATCHDOG_CONFIG = {
|
|
1050
1089
|
enabled: false,
|
|
@@ -1294,10 +1333,10 @@ function parseSettingsObject(settings, meta) {
|
|
|
1294
1333
|
return parseWatchdogPatch(subagents.watchdog, "subagents.watchdog", meta);
|
|
1295
1334
|
}
|
|
1296
1335
|
function readSettingsFileStrict(filePath) {
|
|
1297
|
-
if (!
|
|
1336
|
+
if (!fs3.existsSync(filePath)) return {};
|
|
1298
1337
|
let raw;
|
|
1299
1338
|
try {
|
|
1300
|
-
raw =
|
|
1339
|
+
raw = fs3.readFileSync(filePath, "utf-8");
|
|
1301
1340
|
} catch (error) {
|
|
1302
1341
|
const message2 = error instanceof Error ? error.message : String(error);
|
|
1303
1342
|
throw new Error(`Failed to read settings file '${filePath}': ${message2}`, { cause: error });
|
|
@@ -1316,7 +1355,7 @@ function readSettingsFileStrict(filePath) {
|
|
|
1316
1355
|
}
|
|
1317
1356
|
function isDirectory(dir) {
|
|
1318
1357
|
try {
|
|
1319
|
-
return
|
|
1358
|
+
return fs3.statSync(dir).isDirectory();
|
|
1320
1359
|
} catch {
|
|
1321
1360
|
return false;
|
|
1322
1361
|
}
|
|
@@ -1383,8 +1422,8 @@ function targetSettingsObject(watchdog, target, meta) {
|
|
|
1383
1422
|
return ensureObjectField(overrides, target.agent.trim(), `subagents.watchdog.children.overrides.${target.agent.trim()}`, meta);
|
|
1384
1423
|
}
|
|
1385
1424
|
function writeSettingsFile(settingsPath, settings) {
|
|
1386
|
-
|
|
1387
|
-
|
|
1425
|
+
fs3.mkdirSync(path2.dirname(settingsPath), { recursive: true });
|
|
1426
|
+
fs3.writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}
|
|
1388
1427
|
`, "utf-8");
|
|
1389
1428
|
return settingsPath;
|
|
1390
1429
|
}
|
|
@@ -1423,7 +1462,7 @@ function resolveWatchdogConfig(cwd2, options = {}) {
|
|
|
1423
1462
|
];
|
|
1424
1463
|
for (const source of sourceSpecs) {
|
|
1425
1464
|
if (!source.path) continue;
|
|
1426
|
-
sources.push({ scope: source.scope, path: source.path, exists:
|
|
1465
|
+
sources.push({ scope: source.scope, path: source.path, exists: fs3.existsSync(source.path) });
|
|
1427
1466
|
try {
|
|
1428
1467
|
patch = deepMerge(patch, parseSourceFile(source.path, source.scope));
|
|
1429
1468
|
} catch (error) {
|
|
@@ -1747,7 +1786,7 @@ var SubagentParamProperties = {
|
|
|
1747
1786
|
description: "true: run the one ```js workflow block written in this same reply (false invalid). String with '/': script file read from request cwd. Other string: named workflow resource. Raw scripts (true or path) have no runs.host."
|
|
1748
1787
|
})),
|
|
1749
1788
|
args: Type2.Optional(Type2.Unsafe({ type: "object", maxProperties: MAX_ARGS_FIELDS, additionalProperties: true, description: `Plain-JSON args for workflow; ${MAX_ARGS_FIELDS} fields/object, ${MAX_ARGS_ITEMS} items/array, depth ${MAX_ARGS_DEPTH}, ${MAX_ARGS_BYTES / 1024} KiB total; raw-script args are exposed deeply frozen and persisted, so do not include secrets.` })),
|
|
1750
|
-
reuseFrom: Type2.Optional(Type2.String({ minLength: 1, description: "Exact id of a workflow run
|
|
1789
|
+
reuseFrom: Type2.Optional(Type2.String({ minLength: 1, description: "Exact id of a workflow run ended by a reload, handoff or Pi exit; this async workflow reuses its finished children and re-attaches to its running ones." })),
|
|
1751
1790
|
globalConcurrencyLimit: Type2.Optional(Type2.Integer({ minimum: 1 })),
|
|
1752
1791
|
maxSubagentSpawnsPerRun: Type2.Optional(Type2.Integer({ minimum: 1 })),
|
|
1753
1792
|
preflight: Type2.Optional(WorkflowPreflightOverride),
|
|
@@ -1769,7 +1808,7 @@ var SubagentParamProperties = {
|
|
|
1769
1808
|
usageBudget: Type2.Optional(UsageBudgetOverride),
|
|
1770
1809
|
agentScope: Type2.Optional(Type2.String({ description: "user/project/both (default); project wins collisions." })),
|
|
1771
1810
|
cwd: Type2.Optional(Type2.String({ description: "Execution/project-pane directory." })),
|
|
1772
|
-
machine: Type2.Optional(Type2.String({ minLength: 1, maxLength: 128, description:
|
|
1811
|
+
machine: Type2.Optional(Type2.String({ minLength: 1, maxLength: 128, description: 'Herdr saved machine id or label (runs an external CLI agent), a Rex host named in settings (runs a Pi child), or "local" (a Pi child in a Rex pane here). On another machine, cwd is a directory there.' })),
|
|
1773
1812
|
artifacts: Type2.Optional(Type2.Boolean({ description: "Debug artifacts; default true." })),
|
|
1774
1813
|
includeProgress: Type2.Optional(Type2.Boolean({ description: "Full result progress; default false." })),
|
|
1775
1814
|
share: Type2.Optional(Type2.Boolean({ description: "Upload session to GitHub Gist; default false." })),
|
|
@@ -1851,7 +1890,7 @@ var SubagentWaitParamsSchema = Type2.Object({
|
|
|
1851
1890
|
nonBlocking: Type2.Optional(Type2.Boolean({ description: "Subscribe to id's wake and return immediately; requires id, not with all." })),
|
|
1852
1891
|
all: Type2.Optional(Type2.Boolean({ description: "Wait for all work active at call time." })),
|
|
1853
1892
|
timeoutMs: Type2.Optional(Type2.Integer({ minimum: 1, description: "Max wait; default waitTool.defaultTimeoutMs, then 30 min." })),
|
|
1854
|
-
stopOnAttention: Type2.Optional(Type2.Boolean({ description: "false: keep waiting through
|
|
1893
|
+
stopOnAttention: Type2.Optional(Type2.Boolean({ description: "false: keep waiting through all attention except supervisor requests." }))
|
|
1855
1894
|
});
|
|
1856
1895
|
var SubagentWaitParams = keepTopLevelParameterDescriptions(SubagentWaitParamsSchema);
|
|
1857
1896
|
|
|
@@ -1896,14 +1935,14 @@ function resolveWaitToolConfig(config, env = process.env) {
|
|
|
1896
1935
|
}
|
|
1897
1936
|
|
|
1898
1937
|
// src/runs/background/subagent-wait.ts
|
|
1899
|
-
import * as
|
|
1938
|
+
import * as fs7 from "node:fs";
|
|
1900
1939
|
import * as path4 from "node:path";
|
|
1901
1940
|
|
|
1902
1941
|
// src/runs/background/wait-completions.ts
|
|
1903
|
-
import * as
|
|
1942
|
+
import * as fs5 from "node:fs";
|
|
1904
1943
|
|
|
1905
1944
|
// src/runs/background/completion-replay.ts
|
|
1906
|
-
import * as
|
|
1945
|
+
import * as fs4 from "node:fs";
|
|
1907
1946
|
import * as path3 from "node:path";
|
|
1908
1947
|
var REPLAY_VERSION = 1;
|
|
1909
1948
|
var ARCHIVE_VERSION = 1;
|
|
@@ -1928,7 +1967,7 @@ function existingFile(value) {
|
|
|
1928
1967
|
const filePath = nonEmptyString(value);
|
|
1929
1968
|
if (!filePath) return void 0;
|
|
1930
1969
|
try {
|
|
1931
|
-
return
|
|
1970
|
+
return fs4.statSync(filePath).isFile() ? filePath : void 0;
|
|
1932
1971
|
} catch {
|
|
1933
1972
|
return void 0;
|
|
1934
1973
|
}
|
|
@@ -2013,7 +2052,7 @@ function runIdFromReplayFile(file) {
|
|
|
2013
2052
|
}
|
|
2014
2053
|
function removeBestEffort(filePath) {
|
|
2015
2054
|
try {
|
|
2016
|
-
|
|
2055
|
+
fs4.rmSync(filePath, { force: true });
|
|
2017
2056
|
} catch {
|
|
2018
2057
|
}
|
|
2019
2058
|
}
|
|
@@ -2056,7 +2095,7 @@ function readCompletionReplay(resultsDir, runId, options = {}) {
|
|
|
2056
2095
|
const replayPath = completionReplayPath(resultsDir, runId);
|
|
2057
2096
|
let parsed;
|
|
2058
2097
|
try {
|
|
2059
|
-
parsed = parseReplay(JSON.parse(
|
|
2098
|
+
parsed = parseReplay(JSON.parse(fs4.readFileSync(replayPath, "utf-8")));
|
|
2060
2099
|
} catch (error) {
|
|
2061
2100
|
if (error.code === "ENOENT") return void 0;
|
|
2062
2101
|
throw error;
|
|
@@ -2078,7 +2117,7 @@ function readCompletionReplay(resultsDir, runId, options = {}) {
|
|
|
2078
2117
|
}
|
|
2079
2118
|
function readCompletionArchive(archivePath) {
|
|
2080
2119
|
try {
|
|
2081
|
-
const archive = parseArchive(JSON.parse(
|
|
2120
|
+
const archive = parseArchive(JSON.parse(fs4.readFileSync(archivePath, "utf-8")));
|
|
2082
2121
|
if (!archive) throw new Error("Completion archive is malformed.");
|
|
2083
2122
|
return archive;
|
|
2084
2123
|
} catch (error) {
|
|
@@ -2096,20 +2135,20 @@ function cleanupCompletionReplayIfDue(resultsDir, now, maxAgeMs, intervalMs = CL
|
|
|
2096
2135
|
function cleanupCompletionReplay(resultsDir, now, maxAgeMs) {
|
|
2097
2136
|
const replayDir = path3.join(resultsDir, REPLAY_DIR_NAME);
|
|
2098
2137
|
try {
|
|
2099
|
-
for (const file of
|
|
2138
|
+
for (const file of fs4.readdirSync(replayDir)) {
|
|
2100
2139
|
const runId = runIdFromReplayFile(file);
|
|
2101
2140
|
if (!runId) continue;
|
|
2102
2141
|
const filePath = path3.join(replayDir, file);
|
|
2103
2142
|
try {
|
|
2104
|
-
const record = parseReplay(JSON.parse(
|
|
2143
|
+
const record = parseReplay(JSON.parse(fs4.readFileSync(filePath, "utf-8")));
|
|
2105
2144
|
const safeRecord = record ? validateReplayRecord(resultsDir, runId, record) : void 0;
|
|
2106
2145
|
if (record && !safeRecord) {
|
|
2107
|
-
|
|
2146
|
+
fs4.rmSync(filePath, { force: true });
|
|
2108
2147
|
} else if (safeRecord && safeRecord.expiresAt <= now) {
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
} else if (!record && now -
|
|
2112
|
-
|
|
2148
|
+
fs4.rmSync(filePath, { force: true });
|
|
2149
|
+
fs4.rmSync(safeRecord.archivePath, { force: true });
|
|
2150
|
+
} else if (!record && now - fs4.statSync(filePath).mtimeMs > maxAgeMs) {
|
|
2151
|
+
fs4.rmSync(filePath, { force: true });
|
|
2113
2152
|
}
|
|
2114
2153
|
} catch {
|
|
2115
2154
|
}
|
|
@@ -2118,10 +2157,10 @@ function cleanupCompletionReplay(resultsDir, now, maxAgeMs) {
|
|
|
2118
2157
|
}
|
|
2119
2158
|
const archiveDir = path3.join(resultsDir, ARCHIVE_DIR_NAME);
|
|
2120
2159
|
try {
|
|
2121
|
-
for (const file of
|
|
2160
|
+
for (const file of fs4.readdirSync(archiveDir)) {
|
|
2122
2161
|
const filePath = path3.join(archiveDir, file);
|
|
2123
2162
|
try {
|
|
2124
|
-
if (now -
|
|
2163
|
+
if (now - fs4.statSync(filePath).mtimeMs > maxAgeMs) fs4.rmSync(filePath, { force: true });
|
|
2125
2164
|
} catch {
|
|
2126
2165
|
}
|
|
2127
2166
|
}
|
|
@@ -2173,7 +2212,7 @@ function waitResultPayloadCandidate(resultsDir, run) {
|
|
|
2173
2212
|
}
|
|
2174
2213
|
function readWaitResultPayload(candidatePath, run) {
|
|
2175
2214
|
if (!run.sessionId) return void 0;
|
|
2176
|
-
const payload = JSON.parse(
|
|
2215
|
+
const payload = JSON.parse(fs5.readFileSync(candidatePath, "utf-8"));
|
|
2177
2216
|
if (!resultPayloadMatchesSessionRun(payload, run.sessionId, run.id)) return void 0;
|
|
2178
2217
|
return payload;
|
|
2179
2218
|
}
|
|
@@ -2333,7 +2372,7 @@ function collectWaitCompletions(terminal, state, resultsDir, onReference) {
|
|
|
2333
2372
|
}
|
|
2334
2373
|
|
|
2335
2374
|
// src/runs/background/resume-guidance.ts
|
|
2336
|
-
import * as
|
|
2375
|
+
import * as fs6 from "node:fs";
|
|
2337
2376
|
var INTERCOM_DETACH_ERROR = "detached for intercom coordination";
|
|
2338
2377
|
function isIntercomDetached(run) {
|
|
2339
2378
|
return run.steps.some((step) => step.execution?.status === "detached" || errorWithoutReplyText(step.error)?.toLowerCase().includes(INTERCOM_DETACH_ERROR) === true) || errorWithoutReplyText(run.error)?.toLowerCase().includes(INTERCOM_DETACH_ERROR) === true;
|
|
@@ -2345,7 +2384,7 @@ function formatIntercomDetachGuidance(run) {
|
|
|
2345
2384
|
function formatAsyncReviveCommand(run) {
|
|
2346
2385
|
const step = run.steps.find((candidate) => candidate.status === "failed");
|
|
2347
2386
|
const sessionFile = step?.sessionFile ?? (run.steps.length === 1 ? run.sessionFile : void 0);
|
|
2348
|
-
if (!step || !sessionFile || !
|
|
2387
|
+
if (!step || !sessionFile || !fs6.existsSync(sessionFile)) return void 0;
|
|
2349
2388
|
try {
|
|
2350
2389
|
const descriptor = readAsyncRecoveryDescriptor(run.asyncDir);
|
|
2351
2390
|
if (!descriptor || descriptor.sourceRunId !== run.id || descriptor.agent !== step.agent) return void 0;
|
|
@@ -2670,13 +2709,13 @@ function readTranscriptActivity(transcriptPath) {
|
|
|
2670
2709
|
if (!transcriptPath) return void 0;
|
|
2671
2710
|
let fd;
|
|
2672
2711
|
try {
|
|
2673
|
-
const stat =
|
|
2712
|
+
const stat = fs7.statSync(transcriptPath);
|
|
2674
2713
|
if (!stat.isFile() || stat.size <= 0) return void 0;
|
|
2675
2714
|
const start = Math.max(0, stat.size - TRANSCRIPT_TAIL_BYTES);
|
|
2676
2715
|
const length = stat.size - start;
|
|
2677
2716
|
const buffer = Buffer.allocUnsafe(length);
|
|
2678
|
-
fd =
|
|
2679
|
-
const bytesRead =
|
|
2717
|
+
fd = fs7.openSync(transcriptPath, "r");
|
|
2718
|
+
const bytesRead = fs7.readSync(fd, buffer, 0, length, start);
|
|
2680
2719
|
let lines = buffer.subarray(0, bytesRead).toString("utf-8").split(/\r?\n/);
|
|
2681
2720
|
if (start > 0) lines = lines.slice(1);
|
|
2682
2721
|
let currentTool;
|
|
@@ -2721,7 +2760,7 @@ function readTranscriptActivity(transcriptPath) {
|
|
|
2721
2760
|
} finally {
|
|
2722
2761
|
if (fd !== void 0) {
|
|
2723
2762
|
try {
|
|
2724
|
-
|
|
2763
|
+
fs7.closeSync(fd);
|
|
2725
2764
|
} catch {
|
|
2726
2765
|
}
|
|
2727
2766
|
}
|
|
@@ -2974,7 +3013,8 @@ ${references2.join("\n")}` : ""}`,
|
|
|
2974
3013
|
}
|
|
2975
3014
|
const relevantAttention = attention.filter((run) => initialAsyncIds.has(run.id));
|
|
2976
3015
|
const supervisorAttentionHint = relevantAttention.some(hasSupervisorTool) ? ' Reply to any pending supervisor request. If subagent_supervisor({ action: "pending" }) is empty, check intercom({ action: "pending" }) because an external intercom tool may own the request.' : "";
|
|
2977
|
-
const
|
|
3016
|
+
const keepWaitingHint = stopOnAttention && supervisorAttentionHint === "" && (waitForAll || finishedAsyncCount + providerFinishedCount === 0) ? " These runs are still running and none is waiting on a supervisor reply. To keep waiting through this kind of attention, call bg_wait again with stopOnAttention: false; supervisor requests still end that wait." : "";
|
|
3017
|
+
const attentionNote = relevantAttention.length > 0 ? ` ${relevantAttention.length} run(s) need attention: ${relevantAttention.map((run) => run.id).join(", ")} \u2014${supervisorAttentionHint} inspect with subagent({ action: "status" }) then steer a top-level live async child, resume a paused/completed/failed child, or interrupt explicitly.${keepWaitingHint}` : "";
|
|
2978
3018
|
const stillRunning = active.filter((run) => initialAsyncIds.has(run.id)).length + providerActive.filter((item) => initialProviderIds.has(backgroundWorkIdentity(item))).length;
|
|
2979
3019
|
const elapsed = formatDuration(now() - startedAt);
|
|
2980
3020
|
const outcome = terminalSummary ? ` Outcome: ${terminalSummary}.` : "";
|
|
@@ -3368,7 +3408,7 @@ import { createHash as createHash3 } from "node:crypto";
|
|
|
3368
3408
|
// src/watchdog/change-signature.ts
|
|
3369
3409
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
3370
3410
|
import { createHash } from "node:crypto";
|
|
3371
|
-
import * as
|
|
3411
|
+
import * as fs8 from "node:fs";
|
|
3372
3412
|
import * as os from "node:os";
|
|
3373
3413
|
import * as path6 from "node:path";
|
|
3374
3414
|
var IGNORED_CHANGE_PREFIXES = [`${PROJECT_SUBAGENTS_RELATIVE_DIR}/`, "tmp/", "node_modules/"];
|
|
@@ -3399,7 +3439,7 @@ function git(cwd2, args2) {
|
|
|
3399
3439
|
function comparablePath(value) {
|
|
3400
3440
|
let resolved = path6.resolve(value);
|
|
3401
3441
|
try {
|
|
3402
|
-
resolved =
|
|
3442
|
+
resolved = fs8.realpathSync.native(resolved);
|
|
3403
3443
|
} catch {
|
|
3404
3444
|
}
|
|
3405
3445
|
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
@@ -3431,7 +3471,7 @@ function useHashEntryBudget(budget) {
|
|
|
3431
3471
|
return true;
|
|
3432
3472
|
}
|
|
3433
3473
|
function hashFile(filePath) {
|
|
3434
|
-
return createHash("sha256").update(
|
|
3474
|
+
return createHash("sha256").update(fs8.readFileSync(filePath)).digest("hex");
|
|
3435
3475
|
}
|
|
3436
3476
|
function largeFileHash(stat) {
|
|
3437
3477
|
return "large:" + stat.size + ":" + Math.floor(stat.mtimeMs);
|
|
@@ -3471,17 +3511,17 @@ function hashPath(root, relPath, budget) {
|
|
|
3471
3511
|
const fullPath = path6.join(root, normalized);
|
|
3472
3512
|
let stat;
|
|
3473
3513
|
try {
|
|
3474
|
-
stat =
|
|
3514
|
+
stat = fs8.lstatSync(fullPath);
|
|
3475
3515
|
} catch (error) {
|
|
3476
3516
|
if (error.code === "ENOENT") return { path: normalized, state: "deleted" };
|
|
3477
3517
|
throw error;
|
|
3478
3518
|
}
|
|
3479
3519
|
if (stat.isSymbolicLink()) {
|
|
3480
|
-
return { path: normalized, state: "symlink", target:
|
|
3520
|
+
return { path: normalized, state: "symlink", target: fs8.readlinkSync(fullPath) };
|
|
3481
3521
|
}
|
|
3482
3522
|
if (stat.isDirectory()) {
|
|
3483
|
-
if (
|
|
3484
|
-
const entries =
|
|
3523
|
+
if (fs8.existsSync(path6.join(fullPath, ".git"))) return gitWorktreeEntry(normalized, fullPath);
|
|
3524
|
+
const entries = fs8.readdirSync(fullPath).map((entry) => normalizeRelPath(path6.posix.join(normalized, entry))).filter((entry) => !ignoredRelPath(entry)).sort();
|
|
3485
3525
|
const remainingEntries = Math.max(0, budget.maxEntries - budget.entries);
|
|
3486
3526
|
const selectedEntries = entries.slice(0, remainingEntries);
|
|
3487
3527
|
const childEntries = selectedEntries.map((entry) => hashPath(root, entry, budget));
|
|
@@ -3659,7 +3699,7 @@ var WatchdogEmissionGuard = class {
|
|
|
3659
3699
|
// src/watchdog/lsp-diagnostics.ts
|
|
3660
3700
|
import { spawn } from "node:child_process";
|
|
3661
3701
|
import { createHash as createHash2 } from "node:crypto";
|
|
3662
|
-
import * as
|
|
3702
|
+
import * as fs9 from "node:fs";
|
|
3663
3703
|
import * as path7 from "node:path";
|
|
3664
3704
|
import { pathToFileURL } from "node:url";
|
|
3665
3705
|
var TS_JS_EXTENSIONS = /* @__PURE__ */ new Map([
|
|
@@ -3698,10 +3738,10 @@ function severityFromLsp(value) {
|
|
|
3698
3738
|
}
|
|
3699
3739
|
function pathExecutable(filePath) {
|
|
3700
3740
|
try {
|
|
3701
|
-
const stat =
|
|
3741
|
+
const stat = fs9.statSync(filePath);
|
|
3702
3742
|
if (!stat.isFile()) return false;
|
|
3703
3743
|
if (process.platform === "win32") return true;
|
|
3704
|
-
|
|
3744
|
+
fs9.accessSync(filePath, fs9.constants.X_OK);
|
|
3705
3745
|
return true;
|
|
3706
3746
|
} catch {
|
|
3707
3747
|
return false;
|
|
@@ -3738,7 +3778,7 @@ function collectTargetFiles(root, changedPaths, maxFiles) {
|
|
|
3738
3778
|
}
|
|
3739
3779
|
let stat;
|
|
3740
3780
|
try {
|
|
3741
|
-
stat =
|
|
3781
|
+
stat = fs9.statSync(absPath);
|
|
3742
3782
|
} catch (error) {
|
|
3743
3783
|
if (error.code === "ENOENT") {
|
|
3744
3784
|
skippedPaths.push(relPath);
|
|
@@ -4032,7 +4072,7 @@ async function collectWithTypeScriptLanguageServer(input) {
|
|
|
4032
4072
|
await client.request("initialize", initializeParams(input.root), remaining(), input.signal);
|
|
4033
4073
|
client.notify("initialized", {});
|
|
4034
4074
|
for (const target of input.targets) {
|
|
4035
|
-
const text =
|
|
4075
|
+
const text = fs9.readFileSync(target.absPath, "utf-8");
|
|
4036
4076
|
client.notify("textDocument/didOpen", {
|
|
4037
4077
|
textDocument: { uri: target.uri, languageId: target.languageId, version: 1, text }
|
|
4038
4078
|
});
|
|
@@ -5069,12 +5109,12 @@ import { createReadOnlyTools, convertToLlm } from "@earendil-works/pi-coding-age
|
|
|
5069
5109
|
import { Type as Type4 } from "typebox";
|
|
5070
5110
|
|
|
5071
5111
|
// src/watchdog/guidance.ts
|
|
5072
|
-
import * as
|
|
5112
|
+
import * as fs10 from "node:fs";
|
|
5073
5113
|
import * as path8 from "node:path";
|
|
5074
5114
|
var WATCHDOG_GUIDANCE_MAX_CHARS = 8e3;
|
|
5075
5115
|
function readOptional(filePath) {
|
|
5076
5116
|
try {
|
|
5077
|
-
return
|
|
5117
|
+
return fs10.readFileSync(filePath, "utf-8").trim();
|
|
5078
5118
|
} catch {
|
|
5079
5119
|
return "";
|
|
5080
5120
|
}
|
|
@@ -5381,6 +5421,7 @@ export {
|
|
|
5381
5421
|
registerNativeSupervisorClient,
|
|
5382
5422
|
createNativeSupervisorChannel,
|
|
5383
5423
|
resolveCurrentSessionId,
|
|
5424
|
+
resolvePiSessionId,
|
|
5384
5425
|
WATCHDOG_DIFF_TOOL_NAME,
|
|
5385
5426
|
captureWatchdogDiffBaseline,
|
|
5386
5427
|
startWatchdogDiffBaselineCapture,
|