@tangle-network/agent-runtime 0.143.0 → 0.153.2

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.
Files changed (115) hide show
  1. package/README.md +32 -0
  2. package/dist/{activation-mi8TgSLM.js → activation-Bbic0THc.js} +3 -3
  3. package/dist/{activation-mi8TgSLM.js.map → activation-Bbic0THc.js.map} +1 -1
  4. package/dist/agent.d.ts +1 -1
  5. package/dist/agent.js +3 -3
  6. package/dist/{analyst-loop-CvkmfhUB.js → analyst-loop-Bouu53-l.js} +2 -2
  7. package/dist/{analyst-loop-CvkmfhUB.js.map → analyst-loop-Bouu53-l.js.map} +1 -1
  8. package/dist/analyst-loop.js +1 -1
  9. package/dist/{authoring-DuyShLdw.js → authoring-CcVhJ1lP.js} +2 -2
  10. package/dist/{authoring-DuyShLdw.js.map → authoring-CcVhJ1lP.js.map} +1 -1
  11. package/dist/candidate-execution/index.js +4 -4
  12. package/dist/{candidate-execution-CD5PoNmC.js → candidate-execution-DYOB1juU.js} +4 -4
  13. package/dist/{candidate-execution-CD5PoNmC.js.map → candidate-execution-DYOB1juU.js.map} +1 -1
  14. package/dist/{conversation-1hNtDeMM.js → conversation-BHMwAiMo.js} +28 -13
  15. package/dist/{conversation-1hNtDeMM.js.map → conversation-BHMwAiMo.js.map} +1 -1
  16. package/dist/conversation.d.ts +1 -1
  17. package/dist/conversation.js +1 -1
  18. package/dist/durable.d.ts +102 -4
  19. package/dist/durable.js +259 -13
  20. package/dist/durable.js.map +1 -1
  21. package/dist/{environment-provider-DCBJ13VP.js → environment-provider-3eCszBEm.js} +218 -34
  22. package/dist/environment-provider-3eCszBEm.js.map +1 -0
  23. package/dist/{environment-provider-B8eZ85Ga.d.ts → environment-provider-DJG0yIYl.d.ts} +2 -2
  24. package/dist/environment-provider.d.ts +1 -1
  25. package/dist/environment-provider.js +1 -1
  26. package/dist/executable-spec-BUcUcEPk.js +73 -0
  27. package/dist/executable-spec-BUcUcEPk.js.map +1 -0
  28. package/dist/{graph-De_XEsfH.js → graph-CIh2HDmH.js} +4 -4
  29. package/dist/{graph-De_XEsfH.js.map → graph-CIh2HDmH.js.map} +1 -1
  30. package/dist/{improvement-cycle-Bi-Tf4QF.js → improvement-cycle-GCDSsTN6.js} +7 -7
  31. package/dist/{improvement-cycle-Bi-Tf4QF.js.map → improvement-cycle-GCDSsTN6.js.map} +1 -1
  32. package/dist/{index-C2caGomG.d.ts → index-DLn9WI-f.d.ts} +342 -505
  33. package/dist/{index-B8rKtH3U.d.ts → index-lMADJLfq.d.ts} +4 -4
  34. package/dist/{index-D4sLkOPY.d.ts → index-rxVSm9-z.d.ts} +6 -4
  35. package/dist/index.d.ts +7 -7
  36. package/dist/index.js +13 -13
  37. package/dist/intelligence.d.ts +4 -4
  38. package/dist/intelligence.js +6 -6
  39. package/dist/jsonl-file-CDfsCI5s.js +59 -0
  40. package/dist/jsonl-file-CDfsCI5s.js.map +1 -0
  41. package/dist/kernel.d.ts +6 -6
  42. package/dist/kernel.js +13 -13
  43. package/dist/{knowledge-CVE6Wk1i.js → knowledge-CaY53BW2.js} +10 -7
  44. package/dist/{knowledge-CVE6Wk1i.js.map → knowledge-CaY53BW2.js.map} +1 -1
  45. package/dist/knowledge.d.ts +1 -1
  46. package/dist/knowledge.js +1 -1
  47. package/dist/{loop-runner-bin-BoHdQqLm.d.ts → loop-runner-bin-BwPqxKhR.d.ts} +3 -3
  48. package/dist/{loop-runner-bin-DdaI1nLL.js → loop-runner-bin-Dw43kB_-.js} +4 -4
  49. package/dist/{loop-runner-bin-DdaI1nLL.js.map → loop-runner-bin-Dw43kB_-.js.map} +1 -1
  50. package/dist/loop-runner-bin.d.ts +1 -1
  51. package/dist/loop-runner-bin.js +1 -1
  52. package/dist/{materialization-P86EciBw.js → materialization-Dl9J8ek4.js} +279 -58
  53. package/dist/materialization-Dl9J8ek4.js.map +1 -0
  54. package/dist/mcp/bin.js +3 -3
  55. package/dist/mcp/index.d.ts +3 -3
  56. package/dist/mcp/index.js +6 -6
  57. package/dist/{model-policy-DgRJIJse.js → model-policy-Sw4ywhtL.js} +68 -6
  58. package/dist/model-policy-Sw4ywhtL.js.map +1 -0
  59. package/dist/{openai-tools-BiAWKjh6.js → openai-tools-C4XKuK4t.js} +2 -2
  60. package/dist/{openai-tools-BiAWKjh6.js.map → openai-tools-C4XKuK4t.js.map} +1 -1
  61. package/dist/{prepare-D3n7cA39.js → prepare-C5tI-H4o.js} +2 -2
  62. package/dist/{prepare-D3n7cA39.js.map → prepare-C5tI-H4o.js.map} +1 -1
  63. package/dist/primeintellect/index.d.ts +1 -1
  64. package/dist/profiles.js +1 -1
  65. package/dist/{protected-model-port-bq6bD9YX.js → protected-model-port-DHDKNeY7.js} +2 -2
  66. package/dist/{protected-model-port-bq6bD9YX.js.map → protected-model-port-DHDKNeY7.js.map} +1 -1
  67. package/dist/{redact-DexTuAiX.d.ts → redact-NAptmqKw.d.ts} +3 -3
  68. package/dist/{researcher-CiSY6Wzb.js → researcher-BMFFPwKb.js} +2 -2
  69. package/dist/{researcher-CiSY6Wzb.js.map → researcher-BMFFPwKb.js.map} +1 -1
  70. package/dist/{run-layout-Be_Z0dF8.js → run-layout-C2jgwsCq.js} +111 -6
  71. package/dist/run-layout-C2jgwsCq.js.map +1 -0
  72. package/dist/{runtime-BnqjbOGX.js → runtime--Jsq8JCC.js} +118 -97
  73. package/dist/runtime--Jsq8JCC.js.map +1 -0
  74. package/dist/{runtime-J6Toky8K.d.ts → runtime-B-5dp5Iz.d.ts} +214 -14
  75. package/dist/{sandbox-events-COwCWUVB.js → sandbox-events-BVjstFgb.js} +70 -3
  76. package/dist/sandbox-events-BVjstFgb.js.map +1 -0
  77. package/dist/{spawn-journal-D2HKUImC.js → spawn-journal-BLnveCRS.js} +34 -104
  78. package/dist/spawn-journal-BLnveCRS.js.map +1 -0
  79. package/dist/{stream-agent-turn-C1Vs_3B9.d.ts → stream-agent-turn-BGyszuPH.d.ts} +2 -2
  80. package/dist/{stream-agent-turn-CXRugSGO.js → stream-agent-turn-DYi8ymsU.js} +91 -16
  81. package/dist/stream-agent-turn-DYi8ymsU.js.map +1 -0
  82. package/dist/{structural-rollout-CJgj9YXH.js → structural-rollout-D7V-HgXJ.js} +30 -13
  83. package/dist/structural-rollout-D7V-HgXJ.js.map +1 -0
  84. package/dist/{supervise-hCgG6ROJ.js → supervise-k_8VOASb.js} +2499 -2171
  85. package/dist/supervise-k_8VOASb.js.map +1 -0
  86. package/dist/{supervisor-s8SfZYbW.js → supervisor-CMZsJ7Wn.js} +673 -446
  87. package/dist/supervisor-CMZsJ7Wn.js.map +1 -0
  88. package/dist/testing.d.ts +2 -2
  89. package/dist/testing.js +12 -12
  90. package/dist/{top-app-BMOSKK06.js → top-app-3rYfFPTW.js} +192 -147
  91. package/dist/top-app-3rYfFPTW.js.map +1 -0
  92. package/dist/tui/bin.js +1 -1
  93. package/dist/tui/index.d.ts +32 -5
  94. package/dist/tui/index.js +1 -1
  95. package/dist/{types-Df9vulGc.d.ts → types-BPQhQRrC.d.ts} +507 -10
  96. package/dist/{util-C1bv6yog.js → util-D6ZEuBMi.js} +71 -2
  97. package/dist/util-D6ZEuBMi.js.map +1 -0
  98. package/dist/{workspace-archive-C52LjkeN.js → workspace-archive-B9ui4rrR.js} +2 -2
  99. package/dist/{workspace-archive-C52LjkeN.js.map → workspace-archive-B9ui4rrR.js.map} +1 -1
  100. package/package.json +7 -7
  101. package/dist/environment-provider-DCBJ13VP.js.map +0 -1
  102. package/dist/materialization-P86EciBw.js.map +0 -1
  103. package/dist/model-policy-DgRJIJse.js.map +0 -1
  104. package/dist/retained-run-binding-Dp2e8xne.js +0 -268
  105. package/dist/retained-run-binding-Dp2e8xne.js.map +0 -1
  106. package/dist/run-layout-Be_Z0dF8.js.map +0 -1
  107. package/dist/runtime-BnqjbOGX.js.map +0 -1
  108. package/dist/sandbox-events-COwCWUVB.js.map +0 -1
  109. package/dist/spawn-journal-D2HKUImC.js.map +0 -1
  110. package/dist/stream-agent-turn-CXRugSGO.js.map +0 -1
  111. package/dist/structural-rollout-CJgj9YXH.js.map +0 -1
  112. package/dist/supervise-hCgG6ROJ.js.map +0 -1
  113. package/dist/supervisor-s8SfZYbW.js.map +0 -1
  114. package/dist/top-app-BMOSKK06.js.map +0 -1
  115. package/dist/util-C1bv6yog.js.map +0 -1
package/dist/testing.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Cn as DriverAgentOptions, Gt as RunGraphTestOptions, Lo as supervisorAgentWithTestBrain, Oo as SupervisorAgentTestDeps, Yt as runGraphWithTestBrain, go as SuperviseTestOptions, vo as superviseWithTestBrain, wn as driverAgent } from "./index-C2caGomG.js";
2
- import { ot as ToolLoopCallContext, st as ToolLoopChat } from "./runtime-J6Toky8K.js";
1
+ import { $t as RunGraphTestOptions, Ao as supervisorAgentWithTestBrain, Mn as driverAgent, co as SuperviseTestOptions, jn as DriverAgentOptions, rn as runGraphWithTestBrain, uo as superviseWithTestBrain, xo as SupervisorAgentTestDeps } from "./index-DLn9WI-f.js";
2
+ import { _t as ToolLoopChat, gt as ToolLoopCallContext } from "./runtime-B-5dp5Iz.js";
3
3
  import { AgentImprovementProposal, AgentProfile, AgentProfileImprovementMeasuredComparison, SandboxSizePreset } from "@tangle-network/agent-interface";
4
4
  //#region src/testing/index.d.ts
5
5
  /** A proposal produced by Runtime's opaque profile-improvement path. */
package/dist/testing.js CHANGED
@@ -1,12 +1,12 @@
1
- import { $ as parseExactAgentProfile, K as applyExactAgentProfileDiff, rt as canonicalCandidateDigest$1, st as immutableCandidateValue } from "./prepare-D3n7cA39.js";
2
- import { f as verifyAgentImprovementProposal } from "./improvement-cycle-Bi-Tf4QF.js";
3
- import { c as supervisorAgentWithTestBrain, dt as driverAgent, r as superviseWithTestBrain } from "./supervise-hCgG6ROJ.js";
4
- import { i as runGraphWithTestBrain } from "./graph-De_XEsfH.js";
1
+ import { $ as parseExactAgentProfile, K as applyExactAgentProfileDiff, rt as canonicalCandidateDigest$1, st as immutableCandidateValue } from "./prepare-C5tI-H4o.js";
2
+ import { f as verifyAgentImprovementProposal } from "./improvement-cycle-GCDSsTN6.js";
3
+ import { c as supervisorAgentWithTestBrain, dt as driverAgent, r as superviseWithTestBrain } from "./supervise-k_8VOASb.js";
4
+ import { i as runGraphWithTestBrain } from "./graph-CIh2HDmH.js";
5
5
  import { SANDBOX_SIZE_PRESET_NAMES } from "@tangle-network/agent-interface";
6
6
  //#region src/testing/fixtures/agent-improvement-proposal.json
7
7
  var agent_improvement_proposal_default = {
8
8
  changedSurfaces: ["prompt"],
9
- digest: "sha256:48c661298166f66507443e0eec2f7eb29606502ecf140f0f53711eb4575bd831",
9
+ digest: "sha256:6af30ed1418652d00082d07f90766d0ee30681db2d13322885972ea6d732b3c0",
10
10
  evaluation: {
11
11
  "decision": {
12
12
  "contributingChecks": [
@@ -4577,7 +4577,7 @@ var agent_improvement_proposal_default = {
4577
4577
  ],
4578
4578
  "metadata": {
4579
4579
  "fixture": "agent-improvement-proposal",
4580
- "runtimeVersion": "0.143.0"
4580
+ "runtimeVersion": "0.153.2"
4581
4581
  },
4582
4582
  "objectives": [
4583
4583
  {
@@ -4688,8 +4688,8 @@ var agent_improvement_proposal_default = {
4688
4688
  "baselineContentHash": "sha256:5c21ee53e513fc604cb09754e21c392b24a424da0ef37dbf8f1ee4a8a0b08f09",
4689
4689
  "candidateContentHash": "sha256:60fcbb1c728194bd51d7d19cb732d1c3f1881dce7e0a6266b41c8b98cfd65693",
4690
4690
  "kind": "agent-eval-loop",
4691
- "recordDigest": "sha256:37417d66cd978183738751bf0ba0bd7ccd05c69ac9e3ad9050e228681b488f9e",
4692
- "runId": "agent-runtime-0.143.0-proposal-fixture",
4691
+ "recordDigest": "sha256:2cbc803968b26ba66887d9c096a5d5383d416b32990997d89c763a1e13503241",
4692
+ "runId": "agent-runtime-0.153.2-proposal-fixture",
4693
4693
  "schema": "agent-candidate-experiment"
4694
4694
  }
4695
4695
  },
@@ -4712,13 +4712,13 @@ var agent_improvement_proposal_default = {
4712
4712
  }],
4713
4713
  kind: "agent-improvement-proposal",
4714
4714
  proposedAt: "2026-07-10T01:00:00.000Z",
4715
- runId: "agent-runtime-0.143.0-proposal-fixture"
4715
+ runId: "agent-runtime-0.153.2-proposal-fixture"
4716
4716
  };
4717
4717
  //#endregion
4718
4718
  //#region src/testing/fixtures/agent-profile-improvement-proposal.json
4719
4719
  var agent_profile_improvement_proposal_default = {
4720
4720
  changedSurfaces: ["prompt", "skills"],
4721
- digest: "sha256:ac51cf5857d66e96b6cbdd2c9746ae1a44c95310bb89fb40cb947ebf0f8a0220",
4721
+ digest: "sha256:731dab22aaa07732a81639375387cf9ed15bfe3547601925ee51f2e629da5154",
4722
4722
  evaluation: {
4723
4723
  "decision": {
4724
4724
  "contributingChecks": [
@@ -6352,7 +6352,7 @@ var agent_profile_improvement_proposal_default = {
6352
6352
  ],
6353
6353
  "metadata": {
6354
6354
  "fixture": "agent-profile-improvement-proposal",
6355
- "runtimeVersion": "0.143.0"
6355
+ "runtimeVersion": "0.153.2"
6356
6356
  },
6357
6357
  "objectives": [
6358
6358
  {
@@ -6463,7 +6463,7 @@ var agent_profile_improvement_proposal_default = {
6463
6463
  "baselineContentHash": "sha256:21c495a37c418c10bde64fbaa188beddeed31f1f051ea60a6a6582a9ee0db704",
6464
6464
  "candidateContentHash": "sha256:103f77bc8481601eef1ad5fe6ba84a40dffabc3a44f421f8c8559121edab84e9",
6465
6465
  "kind": "agent-eval-loop",
6466
- "recordDigest": "sha256:45a87e9da971b040445440e2daf2a2cac7aff32ab3b4fc828dd93a1d5a9a4fbf",
6466
+ "recordDigest": "sha256:f50ab9d3e539e3a9c7a10964d69250a5ea719eeb9cebe4099086a9cdc7d4505f",
6467
6467
  "runId": "profile-improvement-1",
6468
6468
  "schema": "agent-profile-improvement-experiment"
6469
6469
  }
@@ -1,8 +1,7 @@
1
- import { l as supervisorRunsRoot, r as legacySupervisorRunsRoot, s as safeWorkerFile, t as cancelWorker, u as supervisorWorkersDir, v as writeWorkerSteer } from "./run-layout-Be_Z0dF8.js";
1
+ import { f as safeWorkerFile, h as supervisorWorkersDir, i as legacySupervisorRunsRoot, m as supervisorRunsRoot, n as cancelWorker, t as cancelRun, w as writeWorkerSteer } from "./run-layout-C2jgwsCq.js";
2
2
  import { randomUUID } from "node:crypto";
3
- import { join, resolve } from "node:path";
4
- import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
5
- import { spawnSync } from "node:child_process";
3
+ import { basename, join, resolve } from "node:path";
4
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
6
5
  import { emitKeypressEvents } from "node:readline";
7
6
  //#region src/tui/top-model.ts
8
7
  /**
@@ -16,6 +15,11 @@ import { emitKeypressEvents } from "node:readline";
16
15
  * Extracted from the `loops` repo (`src/top-model.ts`), which held a hand-joined copy of the
17
16
  * layout. Rendering is deliberately unchanged: raw ANSI, zero dependencies.
18
17
  *
18
+ * This is the OPERATOR view: what is on disk right now, for a human watching a workspace. It
19
+ * carries no model-call identity, so its per-supervisor totals cannot be joined with root stream
20
+ * events without double counting. A client that needs one execution's totals reads
21
+ * `projectPursuit` from `../durable` instead.
22
+ *
19
23
  * @experimental
20
24
  */
21
25
  const emptySpend = {
@@ -42,21 +46,52 @@ const colors = {
42
46
  /**
43
47
  * Read every supervisor run under one workspace into a single point-in-time snapshot.
44
48
  *
45
- * Pure with respect to the process: it only reads, and every unreadable or half-written file is
46
- * skipped rather than thrown on — an operator view must survive a writer mid-append. `now` is
47
- * injectable so elapsed time is deterministic under test.
49
+ * Pure with respect to the process: it only reads, and it never throws for a writer mid-append.
50
+ * An unreadable or half-written source is still skipped — an operator view must survive a live
51
+ * writer but every skip is reported as one bounded `TopSnapshotDiagnostic`, so a client can
52
+ * tell a removed run from a partial read. `now` is injectable so elapsed time is deterministic
53
+ * under test.
48
54
  */
49
55
  function loadTopSnapshot(rootDir, now = Date.now()) {
50
56
  const root = resolve(rootDir);
57
+ const supervisors = [];
58
+ const diagnostics = [];
59
+ let discovered = 0;
60
+ const report = (runId, sources) => {
61
+ for (const source of sources) diagnostics.push({
62
+ ...source,
63
+ runId
64
+ });
65
+ };
66
+ for (const runsRoot of [supervisorRunsRoot(root), legacySupervisorRunsRoot(root)]) {
67
+ if (!existsSync(runsRoot)) continue;
68
+ for (const entry of readdirSync(runsRoot)) {
69
+ const dir = join(runsRoot, entry);
70
+ if (!isDirectory(dir)) continue;
71
+ discovered += 1;
72
+ const state = readSupervisorState(dir);
73
+ report(entry, state.diagnostics);
74
+ if (!state.value) continue;
75
+ const journal = readJournal(dir);
76
+ const progress = readProgressTail(dir, 8);
77
+ const workerEvents = readWorkerEventTails(supervisorWorkersDir(dir), 8);
78
+ report(entry, [
79
+ ...journal.diagnostics,
80
+ ...progress.diagnostics,
81
+ ...workerEvents.diagnostics
82
+ ]);
83
+ supervisors.push(buildSupervisorView(state.value, dir, journal.value, progress.value, now, workerEvents.value));
84
+ }
85
+ }
86
+ supervisors.sort((a, b) => String(b.startedAt ?? "").localeCompare(String(a.startedAt ?? "")));
51
87
  return {
52
88
  root,
53
89
  generatedAt: now,
54
- supervisors: [supervisorRunsRoot(root), legacySupervisorRunsRoot(root)].filter((runsRoot) => existsSync(runsRoot)).flatMap((runsRoot) => readdirSync(runsRoot).filter((entry) => isDirectory(join(runsRoot, entry))).map((entry) => {
55
- const dir = join(runsRoot, entry);
56
- const state = readJson(join(dir, "state.json"));
57
- if (!isSupervisorState(state)) return void 0;
58
- return buildSupervisorView(state, dir, readJournal(dir), readTail(join(dir, "progress.ndjson"), 8), now, readWorkerEventTails(supervisorWorkersDir(dir), 8));
59
- })).filter((view) => view !== void 0).sort((a, b) => String(b.startedAt ?? "").localeCompare(String(a.startedAt ?? "")))
90
+ supervisors,
91
+ completeness: diagnostics.length === 0 ? "complete" : "partial",
92
+ diagnostics,
93
+ discovered,
94
+ loaded: supervisors.length
60
95
  };
61
96
  }
62
97
  /**
@@ -67,25 +102,37 @@ function loadTopSnapshot(rootDir, now = Date.now()) {
67
102
  */
68
103
  const journalFileNames = ["spawn-journal.jsonl", "journal.jsonl"];
69
104
  function readJournal(eventDir) {
70
- const file = journalFileNames.map((name) => join(eventDir, name)).find((candidate) => existsSync(candidate));
71
- if (!file) return [];
105
+ const path = journalFileNames.find((candidate) => existsSync(join(eventDir, candidate)));
106
+ if (!path) return {
107
+ value: [],
108
+ diagnostics: []
109
+ };
110
+ const read = readSourceFile(join(eventDir, path), "journal", path);
111
+ if (read.value === void 0) return {
112
+ value: [],
113
+ diagnostics: read.diagnostics
114
+ };
72
115
  const out = [];
73
- let raw = "";
74
- try {
75
- raw = readFileSync(file, "utf8");
76
- } catch {
77
- return out;
78
- }
79
- for (const line of raw.split("\n")) {
116
+ let partial = false;
117
+ for (const line of read.value.split("\n")) {
80
118
  const trimmed = line.trim();
81
119
  if (!trimmed) continue;
82
120
  try {
83
121
  const parsed = JSON.parse(trimmed);
84
122
  const event = parsed.event ?? parsed;
85
123
  if (isSpawnEvent(event)) out.push(event);
86
- } catch {}
124
+ } catch {
125
+ partial = true;
126
+ }
87
127
  }
88
- return out;
128
+ return {
129
+ value: out,
130
+ diagnostics: partial ? [{
131
+ source: "journal",
132
+ path,
133
+ reason: "partial-json"
134
+ }] : []
135
+ };
89
136
  }
90
137
  function buildSupervisorView(state, stateDir, events, progressTail, now, workerEventTails = /* @__PURE__ */ new Map()) {
91
138
  const workers = /* @__PURE__ */ new Map();
@@ -137,7 +184,6 @@ function buildSupervisorView(state, stateDir, events, progressTail, now, workerE
137
184
  const workerViews = [...workers.values()].map((worker) => {
138
185
  const tail = workerEventTails.get(worker.label) ?? workerEventTails.get(safeWorkerFile(worker.label)) ?? workerEventTails.get(worker.id);
139
186
  worker.liveTail = tail?.lines ?? [];
140
- if (tail?.cwd) worker.cwd = tail.cwd;
141
187
  if (tail?.file) worker.eventFile = tail.file;
142
188
  return finalizeWorker(worker, now);
143
189
  }).sort((a, b) => compareWorker(a, b));
@@ -170,40 +216,6 @@ function buildSupervisorView(state, stateDir, events, progressTail, now, workerE
170
216
  totals
171
217
  };
172
218
  }
173
- /**
174
- * Where a worker-scoped cancel for `workerId` must go.
175
- *
176
- * The runtime's cancel acknowledger runs in the ROOT manager's turn loop and resolves references
177
- * against its DIRECT children only; a request naming a deeper descendant stays pending forever
178
- * (`cancelWorker` keeps answering `unknown`). See `DriverAgentOptions.controlDir`. So a cancel is
179
- * routable only for a top-level worker; for a nested one the operator must cancel its top-level
180
- * LEAD, which cancels that lead's whole subtree.
181
- *
182
- * The worker list never contains the root itself, so the top-level ancestor is the highest node
183
- * in the parent chain that is still a listed worker. A `parent` that matches no listed worker is
184
- * the root (or missing journal data) — both mean the worker is treated as top-level.
185
- */
186
- function workerCancelRoute(workers, workerId) {
187
- const byId = new Map(workers.map((worker) => [worker.id, worker]));
188
- const worker = byId.get(workerId);
189
- if (worker === void 0) return { kind: "unknown" };
190
- let lead = worker;
191
- const seen = /* @__PURE__ */ new Set([lead.id]);
192
- while (lead.parent !== void 0) {
193
- const parent = byId.get(lead.parent);
194
- if (parent === void 0 || seen.has(parent.id)) break;
195
- seen.add(parent.id);
196
- lead = parent;
197
- }
198
- return lead.id === worker.id ? {
199
- kind: "direct",
200
- worker
201
- } : {
202
- kind: "nested",
203
- worker,
204
- lead
205
- };
206
- }
207
219
  /** Render one snapshot to an ANSI frame. Use this when nothing needs to be clickable. */
208
220
  function renderTopFrame(snapshot, options = {}) {
209
221
  return renderTopFrameWithLayout(snapshot, options).frame;
@@ -233,13 +245,19 @@ function renderTopFrameWithLayout(snapshot, options = {}) {
233
245
  };
234
246
  const aggregate = aggregateSnapshot(snapshot);
235
247
  push(`${paint("SUPERVISOR TOP", "bold", color)} ${paint(snapshot.root, "dim", color)} runs ${aggregate.supervisors} workers ${aggregate.workers} live ${aggregate.running} done ${aggregate.done} down ${aggregate.down} ${formatMoney(aggregate.usd)} tok ${formatTokens(aggregate.tokensInput)}/${formatTokens(aggregate.tokensOutput)}`);
236
- push(`${paint("keys", "dim", color)} up/down select left/right run tab focus enter detail o overview l log s steer a shell c cancel mouse q quit`);
248
+ push(`${paint("keys", "dim", color)} up/down select left/right run tab focus enter detail o overview l log s steer c cancel mouse q quit`);
237
249
  if (options.notice) push(paint(options.notice, "yellow", color));
250
+ if (snapshot.completeness === "partial") push(paint(`partial snapshot: ${snapshot.diagnostics.length} source${snapshot.diagnostics.length === 1 ? "" : "s"} skipped or truncated; runs loaded ${snapshot.loaded}/${snapshot.discovered}`, "yellow", color));
238
251
  if (options.steerInput?.active) push(renderSteerInput(options.steerInput, width, color));
239
252
  push(rule(width, color));
240
253
  if (snapshot.supervisors.length === 0) {
241
- push(paint("NO SUPERVISORS", "yellow", color));
242
- push(`No run state under ${supervisorRunsRoot(snapshot.root)}`);
254
+ if (snapshot.discovered > 0) {
255
+ push(paint("NO READABLE SUPERVISORS", "yellow", color));
256
+ push(`${snapshot.discovered} run director${snapshot.discovered === 1 ? "y" : "ies"} found under ${supervisorRunsRoot(snapshot.root)}, none readable`);
257
+ } else {
258
+ push(paint("NO SUPERVISORS", "yellow", color));
259
+ push(`No run state under ${supervisorRunsRoot(snapshot.root)}`);
260
+ }
243
261
  push(`A run appears here once its driver writes state.json; re-point with: agent-runtime-top <root>`);
244
262
  return {
245
263
  frame: `${lines.join("\n")}\n`,
@@ -326,7 +344,6 @@ function finalizeWorker(worker, now) {
326
344
  return {
327
345
  id: worker.id,
328
346
  label: worker.label,
329
- ...worker.cwd ? { cwd: worker.cwd } : {},
330
347
  ...worker.eventFile ? { eventFile: worker.eventFile } : {},
331
348
  ...worker.parent ? { parent: worker.parent } : {},
332
349
  ...worker.runtime ? { runtime: worker.runtime } : {},
@@ -498,7 +515,6 @@ function renderDetail(supervisor, worker, mode, width, color) {
498
515
  `worker ${paint(worker.label, "bold", color)} (${worker.id}) ${statusText(worker.status, color)} latency ${formatDuration(worker.latencyMs)}`,
499
516
  `tokens in/out ${formatTokens(spend.tokensInput)}/${formatTokens(spend.tokensOutput)} cost ${formatMoney(spend.usd)} iterations ${spend.iterations}`,
500
517
  `parent ${worker.parent ?? "-"} runtime ${worker.runtime ?? "-"} out ${worker.outRef ?? "-"}${worker.infra ? " infra" : ""}`,
501
- `cwd ${compact(worker.cwd ?? "-", width - 5)}`,
502
518
  `events ${compact(worker.eventFile ?? "-", width - 8)}`,
503
519
  ...worker.reason ? [`reason ${compact(worker.reason, width - 7)}`] : [],
504
520
  ...renderWorkerTail(worker, width, color)
@@ -549,7 +565,6 @@ function formatWorkerEvent(line) {
549
565
  const at = typeof parsed.at === "string" ? formatClock(parsed.at) : "--:--:--";
550
566
  const kind = typeof parsed.kind === "string" ? parsed.kind : "event";
551
567
  if (kind === "progress") return `${at} progress iter ${numberValue(parsed.iteration)} ${String(parsed.phase ?? "")}`;
552
- if (kind === "started") return `${at} started ${String(parsed.cwd ?? "")}`;
553
568
  if (kind === "message") {
554
569
  const state = parsed.queued === true ? "queued" : "sent";
555
570
  const source = typeof parsed.source === "string" && parsed.source.length > 0 ? `${parsed.source} ` : "";
@@ -645,43 +660,121 @@ function selectWorker(supervisor, requested) {
645
660
  }
646
661
  return supervisor.workers[0];
647
662
  }
648
- function readTail(file, maxLines) {
649
- if (!existsSync(file)) return [];
663
+ /**
664
+ * Read one source file under a run directory. An absent file is not a defect on its own — the
665
+ * writer may not have reached it yet — so it reads as `undefined` with no diagnostic; only a
666
+ * failed read raises one. `path` stays run-relative and never carries file contents.
667
+ */
668
+ function readSourceFile(file, source, path) {
669
+ if (!existsSync(file)) return {
670
+ value: void 0,
671
+ diagnostics: []
672
+ };
650
673
  try {
651
- return readFileSync(file, "utf8").trim().split("\n").filter(Boolean).slice(-maxLines);
674
+ return {
675
+ value: readFileSync(file, "utf8"),
676
+ diagnostics: []
677
+ };
652
678
  } catch {
653
- return [];
679
+ return {
680
+ value: void 0,
681
+ diagnostics: [{
682
+ source,
683
+ path,
684
+ reason: "unreadable"
685
+ }]
686
+ };
654
687
  }
655
688
  }
689
+ function tailLines(raw, maxLines) {
690
+ if (raw === void 0) return [];
691
+ return raw.trim().split("\n").filter(Boolean).slice(-maxLines);
692
+ }
693
+ function readProgressTail(dir, maxLines) {
694
+ const path = "progress.ndjson";
695
+ const read = readSourceFile(join(dir, path), "progress", path);
696
+ return {
697
+ value: tailLines(read.value, maxLines),
698
+ diagnostics: read.diagnostics
699
+ };
700
+ }
656
701
  function readWorkerEventTails(dir, maxLines) {
657
702
  const out = /* @__PURE__ */ new Map();
658
- if (!existsSync(dir)) return out;
659
- for (const entry of readdirSync(dir)) {
703
+ if (!existsSync(dir)) return {
704
+ value: out,
705
+ diagnostics: []
706
+ };
707
+ const workersDir = basename(dir);
708
+ let entries;
709
+ try {
710
+ entries = readdirSync(dir);
711
+ } catch {
712
+ return {
713
+ value: out,
714
+ diagnostics: [{
715
+ source: "worker-tail",
716
+ path: workersDir,
717
+ reason: "unreadable"
718
+ }]
719
+ };
720
+ }
721
+ const diagnostics = [];
722
+ for (const entry of entries) {
660
723
  if (!entry.endsWith(".ndjson") || entry.endsWith(".inbox.ndjson")) continue;
661
- const label = entry.slice(0, -7);
662
724
  const file = join(dir, entry);
663
- const lines = readTail(file, maxLines);
664
- const cwd = workerCwd(lines);
665
- out.set(label, {
725
+ const read = readSourceFile(file, "worker-tail", join(workersDir, entry));
726
+ diagnostics.push(...read.diagnostics);
727
+ const lines = tailLines(read.value, maxLines);
728
+ out.set(entry.slice(0, -7), {
666
729
  file,
667
- lines,
668
- ...cwd ? { cwd } : {}
730
+ lines
669
731
  });
670
732
  }
671
- return out;
672
- }
673
- function workerCwd(lines) {
674
- for (const line of [...lines].reverse()) try {
675
- const parsed = JSON.parse(line);
676
- if (parsed.kind === "started" && typeof parsed.cwd === "string" && parsed.cwd.trim()) return parsed.cwd;
677
- } catch {}
733
+ return {
734
+ value: out,
735
+ diagnostics
736
+ };
678
737
  }
679
- function readJson(file) {
738
+ function readSupervisorState(dir) {
739
+ const path = "state.json";
740
+ const read = readSourceFile(join(dir, path), "supervisor-state", path);
741
+ if (read.diagnostics.length > 0) return {
742
+ value: void 0,
743
+ diagnostics: read.diagnostics
744
+ };
745
+ if (read.value === void 0) return {
746
+ value: void 0,
747
+ diagnostics: [{
748
+ source: "supervisor-state",
749
+ path,
750
+ reason: "missing"
751
+ }]
752
+ };
753
+ let parsed;
680
754
  try {
681
- return JSON.parse(readFileSync(file, "utf8"));
755
+ parsed = JSON.parse(read.value);
682
756
  } catch {
683
- return;
757
+ return {
758
+ value: void 0,
759
+ diagnostics: [{
760
+ source: "supervisor-state",
761
+ path,
762
+ reason: "partial-json"
763
+ }]
764
+ };
684
765
  }
766
+ if (!isSupervisorState(parsed)) return {
767
+ value: void 0,
768
+ diagnostics: [{
769
+ source: "supervisor-state",
770
+ path,
771
+ reason: "invalid-state"
772
+ }]
773
+ };
774
+ return {
775
+ value: parsed,
776
+ diagnostics: []
777
+ };
685
778
  }
686
779
  function isSupervisorState(value) {
687
780
  return value !== void 0 && typeof value.id === "string" && typeof value.status === "string" && typeof value.task === "string" && typeof value.workspaceDir === "string" && typeof value.budget === "number";
@@ -804,7 +897,11 @@ let state = initialState([], process.cwd());
804
897
  let snapshot = {
805
898
  root: state.root,
806
899
  generatedAt: 0,
807
- supervisors: []
900
+ supervisors: [],
901
+ completeness: "complete",
902
+ diagnostics: [],
903
+ discovered: 0,
904
+ loaded: 0
808
905
  };
809
906
  let targets = [];
810
907
  let timer;
@@ -872,22 +969,6 @@ function stop() {
872
969
  process.stdout.write("\x1B[?1000l\x1B[?1006l\x1B[?25h\x1B[?1049l");
873
970
  process.exit(0);
874
971
  }
875
- function pauseUi() {
876
- if (timer) {
877
- clearInterval(timer);
878
- timer = void 0;
879
- }
880
- process.stdin.setRawMode(false);
881
- process.stdin.pause();
882
- process.stdout.write("\x1B[?1000l\x1B[?1006l\x1B[?25h\x1B[?1049l");
883
- }
884
- function resumeUi() {
885
- process.stdout.write("\x1B[?1049h\x1B[?25l\x1B[?1000h\x1B[?1006h");
886
- process.stdin.setRawMode(true);
887
- process.stdin.resume();
888
- draw();
889
- timer = setInterval(draw, 1e3);
890
- }
891
972
  function draw() {
892
973
  snapshot = loadTopSnapshot(state.root);
893
974
  clampSelection();
@@ -925,10 +1006,7 @@ function onKey(str, key) {
925
1006
  } else if (key.name === "o") state.mode = "overview";
926
1007
  else if (key.name === "l") state.mode = "log";
927
1008
  else if (key.name === "s") startSteerInput();
928
- else if (key.name === "a") {
929
- state.mode = "detail";
930
- openWorkerShell();
931
- } else if (key.name === "c") requestCancel();
1009
+ else if (key.name === "c") requestCancel();
932
1010
  draw();
933
1011
  }
934
1012
  function handleSteerInput(str, key) {
@@ -1068,32 +1146,6 @@ function renderSteerInputState() {
1068
1146
  ...worker?.label ? { workerLabel: worker.label } : {}
1069
1147
  };
1070
1148
  }
1071
- function openWorkerShell() {
1072
- const worker = selectedWorker();
1073
- if (!worker?.cwd) {
1074
- state.notice = "no worker worktree recorded yet";
1075
- return;
1076
- }
1077
- if (!existsSync(worker.cwd)) {
1078
- state.notice = `worker worktree is gone: ${worker.cwd}`;
1079
- return;
1080
- }
1081
- const shell = process.env.SHELL ?? "/bin/bash";
1082
- state.notice = `returned from ${worker.label}`;
1083
- pauseUi();
1084
- spawnSync(shell, [], {
1085
- cwd: worker.cwd,
1086
- stdio: "inherit",
1087
- env: {
1088
- ...process.env,
1089
- AGENT_SUPERVISOR_ROOT: state.root,
1090
- AGENT_SUPERVISOR_ID: state.selectedSupervisorId ?? "",
1091
- AGENT_WORKER_ID: worker.id,
1092
- AGENT_WORKER_LABEL: worker.label
1093
- }
1094
- });
1095
- resumeUi();
1096
- }
1097
1149
  function requestCancel() {
1098
1150
  const supervisor = selectedSupervisor();
1099
1151
  if (!supervisor) {
@@ -1110,11 +1162,6 @@ function requestCancel() {
1110
1162
  state.notice = `${worker.label} is ${worker.status}; nothing to cancel`;
1111
1163
  return;
1112
1164
  }
1113
- const route = workerCancelRoute(supervisor.workers, worker.id);
1114
- if (route.kind === "nested") {
1115
- state.notice = `${worker.label} is nested under lead ${route.lead.label}; cancel ${route.lead.label} to cancel its whole subtree`;
1116
- return;
1117
- }
1118
1165
  try {
1119
1166
  const record = cancelWorker(supervisor.stateDir, worker.id, randomUUID(), {
1120
1167
  reason: "operator requested cancel from TUI",
@@ -1127,13 +1174,11 @@ function requestCancel() {
1127
1174
  return;
1128
1175
  }
1129
1176
  try {
1130
- mkdirSync(supervisor.stateDir, { recursive: true });
1131
- writeFileSync(join(supervisor.stateDir, "cancel.request.json"), `${JSON.stringify({
1132
- at: (/* @__PURE__ */ new Date()).toISOString(),
1133
- source: "agent-runtime-top",
1134
- reason: "operator requested cancel from TUI"
1135
- }, null, 2)}\n`, "utf8");
1136
- state.notice = `run cancel requested for ${supervisor.id} (host-honored; not runtime-acknowledged)`;
1177
+ const record = cancelRun(supervisor.stateDir, randomUUID(), {
1178
+ reason: "operator requested cancel from TUI",
1179
+ source: "agent-runtime-top"
1180
+ });
1181
+ state.notice = record.effect === "unknown" ? `run cancel queued for ${supervisor.id} (op ${record.operationId}); awaiting runtime acknowledgement` : `run cancel ${record.effect} for ${supervisor.id} (op ${record.operationId})`;
1137
1182
  } catch (err) {
1138
1183
  state.notice = `cancel request failed: ${err instanceof Error ? err.message : String(err)}`;
1139
1184
  }
@@ -1144,4 +1189,4 @@ function wrap(value, size) {
1144
1189
  //#endregion
1145
1190
  export { renderTopFrameWithLayout as a, renderTopFrame as i, runTopApp as n, loadTopSnapshot as r, renderTopOnce as t };
1146
1191
 
1147
- //# sourceMappingURL=top-app-BMOSKK06.js.map
1192
+ //# sourceMappingURL=top-app-3rYfFPTW.js.map