@tangle-network/agent-runtime 0.142.3 → 0.153.1

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 (117) hide show
  1. package/README.md +32 -0
  2. package/dist/{activation-o7JKmtxi.js → activation-DKxQsHiO.js} +3 -3
  3. package/dist/{activation-o7JKmtxi.js.map → activation-DKxQsHiO.js.map} +1 -1
  4. package/dist/agent.d.ts +2 -2
  5. package/dist/agent.js +3 -3
  6. package/dist/{analyst-loop-GcX0BY75.js → analyst-loop-B2kTHKNh.js} +2 -2
  7. package/dist/{analyst-loop-GcX0BY75.js.map → analyst-loop-B2kTHKNh.js.map} +1 -1
  8. package/dist/analyst-loop.d.ts +1 -1
  9. package/dist/analyst-loop.js +1 -1
  10. package/dist/{authoring-Bm1WlGPv.js → authoring-Tk2xFys0.js} +2 -2
  11. package/dist/{authoring-Bm1WlGPv.js.map → authoring-Tk2xFys0.js.map} +1 -1
  12. package/dist/candidate-execution/index.js +4 -4
  13. package/dist/{candidate-execution-CD5PoNmC.js → candidate-execution-CB9RJbbJ.js} +4 -4
  14. package/dist/{candidate-execution-CD5PoNmC.js.map → candidate-execution-CB9RJbbJ.js.map} +1 -1
  15. package/dist/{conversation-DXKJHyqB.js → conversation-D64WyWrK.js} +4 -4
  16. package/dist/{conversation-DXKJHyqB.js.map → conversation-D64WyWrK.js.map} +1 -1
  17. package/dist/conversation.d.ts +1 -1
  18. package/dist/conversation.js +1 -1
  19. package/dist/durable.d.ts +102 -4
  20. package/dist/durable.js +259 -10
  21. package/dist/durable.js.map +1 -1
  22. package/dist/{environment-provider-BicwCDK5.d.ts → environment-provider-DJG0yIYl.d.ts} +3 -3
  23. package/dist/{environment-provider-DCEACNt9.js → environment-provider-D_MXw3jK.js} +88 -9
  24. package/dist/environment-provider-D_MXw3jK.js.map +1 -0
  25. package/dist/environment-provider.d.ts +1 -1
  26. package/dist/environment-provider.js +1 -1
  27. package/dist/executable-spec-BUcUcEPk.js +73 -0
  28. package/dist/executable-spec-BUcUcEPk.js.map +1 -0
  29. package/dist/{graph-DhrLuLOS.js → graph-M0Qr4863.js} +4 -4
  30. package/dist/{graph-DhrLuLOS.js.map → graph-M0Qr4863.js.map} +1 -1
  31. package/dist/{improvement-cycle-lcwlR6E2.js → improvement-cycle-CDxlGQGE.js} +7 -7
  32. package/dist/{improvement-cycle-lcwlR6E2.js.map → improvement-cycle-CDxlGQGE.js.map} +1 -1
  33. package/dist/{index-Bx3-tqG-.d.ts → index-BihHgUAI.d.ts} +4 -4
  34. package/dist/{index-D_aH0F4C.d.ts → index-Dlz7ejRx.d.ts} +342 -521
  35. package/dist/{index-CV1xRWy2.d.ts → index-LQfgFJoX.d.ts} +3 -3
  36. package/dist/index.d.ts +9 -9
  37. package/dist/index.js +13 -13
  38. package/dist/intelligence.d.ts +5 -5
  39. package/dist/intelligence.js +6 -6
  40. package/dist/kernel.d.ts +7 -7
  41. package/dist/kernel.js +13 -13
  42. package/dist/{knowledge-C9LlSJAR.js → knowledge-DM-i40b9.js} +10 -7
  43. package/dist/{knowledge-C9LlSJAR.js.map → knowledge-DM-i40b9.js.map} +1 -1
  44. package/dist/knowledge.d.ts +1 -1
  45. package/dist/knowledge.js +1 -1
  46. package/dist/{loop-runner-bin-CctBy5-X.d.ts → loop-runner-bin-D-BW51yr.d.ts} +3 -3
  47. package/dist/{loop-runner-bin-DFo6Ss-1.js → loop-runner-bin-pD5WJuqJ.js} +4 -4
  48. package/dist/{loop-runner-bin-DFo6Ss-1.js.map → loop-runner-bin-pD5WJuqJ.js.map} +1 -1
  49. package/dist/loop-runner-bin.d.ts +1 -1
  50. package/dist/loop-runner-bin.js +1 -1
  51. package/dist/{materialization-CrdcfWXp.js → materialization-Bo6j3Hg9.js} +261 -24
  52. package/dist/materialization-Bo6j3Hg9.js.map +1 -0
  53. package/dist/mcp/bin.js +3 -3
  54. package/dist/mcp/index.d.ts +5 -5
  55. package/dist/mcp/index.js +6 -6
  56. package/dist/{model-policy-DgRJIJse.js → model-policy-Sw4ywhtL.js} +68 -6
  57. package/dist/model-policy-Sw4ywhtL.js.map +1 -0
  58. package/dist/{openai-tools-CSm460sC.js → openai-tools-CWBywy-e.js} +2 -2
  59. package/dist/{openai-tools-CSm460sC.js.map → openai-tools-CWBywy-e.js.map} +1 -1
  60. package/dist/{openai-tools-t5-6h5bj.d.ts → openai-tools-z-whdYNC.d.ts} +2 -2
  61. package/dist/{prepare-D3n7cA39.js → prepare-C3eFd3UA.js} +2 -2
  62. package/dist/{prepare-D3n7cA39.js.map → prepare-C3eFd3UA.js.map} +1 -1
  63. package/dist/primeintellect/index.d.ts +1 -1
  64. package/dist/profiles.d.ts +1 -1
  65. package/dist/profiles.js +1 -1
  66. package/dist/{protected-model-port-bq6bD9YX.js → protected-model-port-Dn2b6peS.js} +2 -2
  67. package/dist/{protected-model-port-bq6bD9YX.js.map → protected-model-port-Dn2b6peS.js.map} +1 -1
  68. package/dist/{redact-B0gDSTZO.d.ts → redact-NAptmqKw.d.ts} +3 -3
  69. package/dist/{researcher-CiSY6Wzb.js → researcher-BMFFPwKb.js} +2 -2
  70. package/dist/{researcher-CiSY6Wzb.js.map → researcher-BMFFPwKb.js.map} +1 -1
  71. package/dist/{run-layout-Be_Z0dF8.js → run-layout-C2jgwsCq.js} +111 -6
  72. package/dist/run-layout-C2jgwsCq.js.map +1 -0
  73. package/dist/{runtime-htqI3fKL.d.ts → runtime-B-5dp5Iz.d.ts} +223 -11
  74. package/dist/{runtime-DQs5xHdt.js → runtime-RY_rvv7t.js} +93 -84
  75. package/dist/runtime-RY_rvv7t.js.map +1 -0
  76. package/dist/{sandbox-events-BK-g19wx.js → sandbox-events-DMijDq2p.js} +53 -49
  77. package/dist/sandbox-events-DMijDq2p.js.map +1 -0
  78. package/dist/{spawn-journal-D2HKUImC.js → spawn-journal-CLguaA2A.js} +8 -43
  79. package/dist/spawn-journal-CLguaA2A.js.map +1 -0
  80. package/dist/{stream-agent-turn-Dfy12OjG.d.ts → stream-agent-turn-BGyszuPH.d.ts} +6 -3
  81. package/dist/{stream-agent-turn-BMHUIuQS.js → stream-agent-turn-D6HoaRPV.js} +140 -23
  82. package/dist/stream-agent-turn-D6HoaRPV.js.map +1 -0
  83. package/dist/{structural-rollout-CzZKDkmA.js → structural-rollout-P1YxFRfl.js} +11 -8
  84. package/dist/structural-rollout-P1YxFRfl.js.map +1 -0
  85. package/dist/{supervise-BEs5MB91.js → supervise-BezbzKiJ.js} +1550 -1186
  86. package/dist/supervise-BezbzKiJ.js.map +1 -0
  87. package/dist/{supervisor-B_0ISTFG.js → supervisor-DBVlPONC.js} +697 -230
  88. package/dist/supervisor-DBVlPONC.js.map +1 -0
  89. package/dist/testing.d.ts +2 -2
  90. package/dist/testing.js +12 -12
  91. package/dist/{top-app-BMOSKK06.js → top-app-tKo9OrON.js} +189 -86
  92. package/dist/top-app-tKo9OrON.js.map +1 -0
  93. package/dist/tui/bin.js +1 -1
  94. package/dist/tui/index.d.ts +32 -4
  95. package/dist/tui/index.js +1 -1
  96. package/dist/{types-_7w24mMg.d.ts → types-BPQhQRrC.d.ts} +508 -11
  97. package/dist/{types-DZrBoBpN.d.ts → types-DeX8ibLc.d.ts} +4 -1
  98. package/dist/{util-C1bv6yog.js → util-Bncw0o_F.js} +41 -2
  99. package/dist/util-Bncw0o_F.js.map +1 -0
  100. package/dist/{workspace-archive-C52LjkeN.js → workspace-archive-Dm73lTfB.js} +2 -2
  101. package/dist/{workspace-archive-C52LjkeN.js.map → workspace-archive-Dm73lTfB.js.map} +1 -1
  102. package/package.json +6 -6
  103. package/dist/environment-provider-DCEACNt9.js.map +0 -1
  104. package/dist/materialization-CrdcfWXp.js.map +0 -1
  105. package/dist/model-policy-DgRJIJse.js.map +0 -1
  106. package/dist/retained-run-binding-Dp2e8xne.js +0 -268
  107. package/dist/retained-run-binding-Dp2e8xne.js.map +0 -1
  108. package/dist/run-layout-Be_Z0dF8.js.map +0 -1
  109. package/dist/runtime-DQs5xHdt.js.map +0 -1
  110. package/dist/sandbox-events-BK-g19wx.js.map +0 -1
  111. package/dist/spawn-journal-D2HKUImC.js.map +0 -1
  112. package/dist/stream-agent-turn-BMHUIuQS.js.map +0 -1
  113. package/dist/structural-rollout-CzZKDkmA.js.map +0 -1
  114. package/dist/supervise-BEs5MB91.js.map +0 -1
  115. package/dist/supervisor-B_0ISTFG.js.map +0 -1
  116. package/dist/top-app-BMOSKK06.js.map +0 -1
  117. package/dist/util-C1bv6yog.js.map +0 -1
package/dist/testing.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { Ao as SupervisorAgentTestDeps, Cn as DriverAgentOptions, Gt as RunGraphTestOptions, Yt as runGraphWithTestBrain, bo as superviseWithTestBrain, vo as SuperviseTestOptions, wn as driverAgent, zo as supervisorAgentWithTestBrain } from "./index-D_aH0F4C.js";
2
- import { at as ToolLoopCallContext, ot as ToolLoopChat } from "./runtime-htqI3fKL.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-Dlz7ejRx.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-lcwlR6E2.js";
3
- import { c as supervisorAgentWithTestBrain, dt as driverAgent, r as superviseWithTestBrain } from "./supervise-BEs5MB91.js";
4
- import { i as runGraphWithTestBrain } from "./graph-DhrLuLOS.js";
1
+ import { $ as parseExactAgentProfile, K as applyExactAgentProfileDiff, rt as canonicalCandidateDigest$1, st as immutableCandidateValue } from "./prepare-C3eFd3UA.js";
2
+ import { f as verifyAgentImprovementProposal } from "./improvement-cycle-CDxlGQGE.js";
3
+ import { c as supervisorAgentWithTestBrain, dt as driverAgent, r as superviseWithTestBrain } from "./supervise-BezbzKiJ.js";
4
+ import { i as runGraphWithTestBrain } from "./graph-M0Qr4863.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:b7013ba46d2e69b918f5b68fdb9598677be93996e65d59c7b5c8c55eb16e444a",
9
+ digest: "sha256:9c01cbf061f96086a1bade76c930341bcc2e74b97879ef8e603ad3fd9d24c147",
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.142.3"
4580
+ "runtimeVersion": "0.153.1"
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:67fda76a6a9508fc1573c8f00d215051bd4be078ac85db538530e0d20411680b",
4692
- "runId": "agent-runtime-0.142.3-proposal-fixture",
4691
+ "recordDigest": "sha256:989ec9947e8d97a7c207a415c556f236068c7ca12a527e7f1ffda9f0267ffc53",
4692
+ "runId": "agent-runtime-0.153.1-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.142.3-proposal-fixture"
4715
+ runId: "agent-runtime-0.153.1-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:dd890bcb652aa108a8f0954fe0016853274cf96821f29dda07173738d1232d66",
4721
+ digest: "sha256:a043d1c6bc786ed49ab8d7d8c8823709c7633342a8573ad5aa9645ade11efab0",
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.142.3"
6355
+ "runtimeVersion": "0.153.1"
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:b1c860be2dbc9e3a73bb296d76429f2554843a65d9c2e3c56a0072860e662de7",
6466
+ "recordDigest": "sha256:bb4d87a014e57f0d47c1be60f140000c083d0b9a3e5051ed43056aa05559e3b3",
6467
6467
  "runId": "profile-improvement-1",
6468
6468
  "schema": "agent-profile-improvement-experiment"
6469
6469
  }
@@ -1,7 +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";
3
+ import { basename, join, resolve } from "node:path";
4
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
5
5
  import { spawnSync } from "node:child_process";
6
6
  import { emitKeypressEvents } from "node:readline";
7
7
  //#region src/tui/top-model.ts
@@ -16,6 +16,11 @@ import { emitKeypressEvents } from "node:readline";
16
16
  * Extracted from the `loops` repo (`src/top-model.ts`), which held a hand-joined copy of the
17
17
  * layout. Rendering is deliberately unchanged: raw ANSI, zero dependencies.
18
18
  *
19
+ * This is the OPERATOR view: what is on disk right now, for a human watching a workspace. It
20
+ * carries no model-call identity, so its per-supervisor totals cannot be joined with root stream
21
+ * events without double counting. A client that needs one execution's totals reads
22
+ * `projectPursuit` from `../durable` instead.
23
+ *
19
24
  * @experimental
20
25
  */
21
26
  const emptySpend = {
@@ -42,21 +47,52 @@ const colors = {
42
47
  /**
43
48
  * Read every supervisor run under one workspace into a single point-in-time snapshot.
44
49
  *
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.
50
+ * Pure with respect to the process: it only reads, and it never throws for a writer mid-append.
51
+ * An unreadable or half-written source is still skipped — an operator view must survive a live
52
+ * writer but every skip is reported as one bounded `TopSnapshotDiagnostic`, so a client can
53
+ * tell a removed run from a partial read. `now` is injectable so elapsed time is deterministic
54
+ * under test.
48
55
  */
49
56
  function loadTopSnapshot(rootDir, now = Date.now()) {
50
57
  const root = resolve(rootDir);
58
+ const supervisors = [];
59
+ const diagnostics = [];
60
+ let discovered = 0;
61
+ const report = (runId, sources) => {
62
+ for (const source of sources) diagnostics.push({
63
+ ...source,
64
+ runId
65
+ });
66
+ };
67
+ for (const runsRoot of [supervisorRunsRoot(root), legacySupervisorRunsRoot(root)]) {
68
+ if (!existsSync(runsRoot)) continue;
69
+ for (const entry of readdirSync(runsRoot)) {
70
+ const dir = join(runsRoot, entry);
71
+ if (!isDirectory(dir)) continue;
72
+ discovered += 1;
73
+ const state = readSupervisorState(dir);
74
+ report(entry, state.diagnostics);
75
+ if (!state.value) continue;
76
+ const journal = readJournal(dir);
77
+ const progress = readProgressTail(dir, 8);
78
+ const workerEvents = readWorkerEventTails(supervisorWorkersDir(dir), 8);
79
+ report(entry, [
80
+ ...journal.diagnostics,
81
+ ...progress.diagnostics,
82
+ ...workerEvents.diagnostics
83
+ ]);
84
+ supervisors.push(buildSupervisorView(state.value, dir, journal.value, progress.value, now, workerEvents.value));
85
+ }
86
+ }
87
+ supervisors.sort((a, b) => String(b.startedAt ?? "").localeCompare(String(a.startedAt ?? "")));
51
88
  return {
52
89
  root,
53
90
  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 ?? "")))
91
+ supervisors,
92
+ completeness: diagnostics.length === 0 ? "complete" : "partial",
93
+ diagnostics,
94
+ discovered,
95
+ loaded: supervisors.length
60
96
  };
61
97
  }
62
98
  /**
@@ -67,25 +103,37 @@ function loadTopSnapshot(rootDir, now = Date.now()) {
67
103
  */
68
104
  const journalFileNames = ["spawn-journal.jsonl", "journal.jsonl"];
69
105
  function readJournal(eventDir) {
70
- const file = journalFileNames.map((name) => join(eventDir, name)).find((candidate) => existsSync(candidate));
71
- if (!file) return [];
106
+ const path = journalFileNames.find((candidate) => existsSync(join(eventDir, candidate)));
107
+ if (!path) return {
108
+ value: [],
109
+ diagnostics: []
110
+ };
111
+ const read = readSourceFile(join(eventDir, path), "journal", path);
112
+ if (read.value === void 0) return {
113
+ value: [],
114
+ diagnostics: read.diagnostics
115
+ };
72
116
  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")) {
117
+ let partial = false;
118
+ for (const line of read.value.split("\n")) {
80
119
  const trimmed = line.trim();
81
120
  if (!trimmed) continue;
82
121
  try {
83
122
  const parsed = JSON.parse(trimmed);
84
123
  const event = parsed.event ?? parsed;
85
124
  if (isSpawnEvent(event)) out.push(event);
86
- } catch {}
125
+ } catch {
126
+ partial = true;
127
+ }
87
128
  }
88
- return out;
129
+ return {
130
+ value: out,
131
+ diagnostics: partial ? [{
132
+ source: "journal",
133
+ path,
134
+ reason: "partial-json"
135
+ }] : []
136
+ };
89
137
  }
90
138
  function buildSupervisorView(state, stateDir, events, progressTail, now, workerEventTails = /* @__PURE__ */ new Map()) {
91
139
  const workers = /* @__PURE__ */ new Map();
@@ -170,40 +218,6 @@ function buildSupervisorView(state, stateDir, events, progressTail, now, workerE
170
218
  totals
171
219
  };
172
220
  }
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
221
  /** Render one snapshot to an ANSI frame. Use this when nothing needs to be clickable. */
208
222
  function renderTopFrame(snapshot, options = {}) {
209
223
  return renderTopFrameWithLayout(snapshot, options).frame;
@@ -235,11 +249,17 @@ function renderTopFrameWithLayout(snapshot, options = {}) {
235
249
  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
250
  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`);
237
251
  if (options.notice) push(paint(options.notice, "yellow", color));
252
+ 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
253
  if (options.steerInput?.active) push(renderSteerInput(options.steerInput, width, color));
239
254
  push(rule(width, color));
240
255
  if (snapshot.supervisors.length === 0) {
241
- push(paint("NO SUPERVISORS", "yellow", color));
242
- push(`No run state under ${supervisorRunsRoot(snapshot.root)}`);
256
+ if (snapshot.discovered > 0) {
257
+ push(paint("NO READABLE SUPERVISORS", "yellow", color));
258
+ push(`${snapshot.discovered} run director${snapshot.discovered === 1 ? "y" : "ies"} found under ${supervisorRunsRoot(snapshot.root)}, none readable`);
259
+ } else {
260
+ push(paint("NO SUPERVISORS", "yellow", color));
261
+ push(`No run state under ${supervisorRunsRoot(snapshot.root)}`);
262
+ }
243
263
  push(`A run appears here once its driver writes state.json; re-point with: agent-runtime-top <root>`);
244
264
  return {
245
265
  frame: `${lines.join("\n")}\n`,
@@ -645,30 +665,82 @@ function selectWorker(supervisor, requested) {
645
665
  }
646
666
  return supervisor.workers[0];
647
667
  }
648
- function readTail(file, maxLines) {
649
- if (!existsSync(file)) return [];
668
+ /**
669
+ * Read one source file under a run directory. An absent file is not a defect on its own — the
670
+ * writer may not have reached it yet — so it reads as `undefined` with no diagnostic; only a
671
+ * failed read raises one. `path` stays run-relative and never carries file contents.
672
+ */
673
+ function readSourceFile(file, source, path) {
674
+ if (!existsSync(file)) return {
675
+ value: void 0,
676
+ diagnostics: []
677
+ };
650
678
  try {
651
- return readFileSync(file, "utf8").trim().split("\n").filter(Boolean).slice(-maxLines);
679
+ return {
680
+ value: readFileSync(file, "utf8"),
681
+ diagnostics: []
682
+ };
652
683
  } catch {
653
- return [];
684
+ return {
685
+ value: void 0,
686
+ diagnostics: [{
687
+ source,
688
+ path,
689
+ reason: "unreadable"
690
+ }]
691
+ };
654
692
  }
655
693
  }
694
+ function tailLines(raw, maxLines) {
695
+ if (raw === void 0) return [];
696
+ return raw.trim().split("\n").filter(Boolean).slice(-maxLines);
697
+ }
698
+ function readProgressTail(dir, maxLines) {
699
+ const path = "progress.ndjson";
700
+ const read = readSourceFile(join(dir, path), "progress", path);
701
+ return {
702
+ value: tailLines(read.value, maxLines),
703
+ diagnostics: read.diagnostics
704
+ };
705
+ }
656
706
  function readWorkerEventTails(dir, maxLines) {
657
707
  const out = /* @__PURE__ */ new Map();
658
- if (!existsSync(dir)) return out;
659
- for (const entry of readdirSync(dir)) {
708
+ if (!existsSync(dir)) return {
709
+ value: out,
710
+ diagnostics: []
711
+ };
712
+ const workersDir = basename(dir);
713
+ let entries;
714
+ try {
715
+ entries = readdirSync(dir);
716
+ } catch {
717
+ return {
718
+ value: out,
719
+ diagnostics: [{
720
+ source: "worker-tail",
721
+ path: workersDir,
722
+ reason: "unreadable"
723
+ }]
724
+ };
725
+ }
726
+ const diagnostics = [];
727
+ for (const entry of entries) {
660
728
  if (!entry.endsWith(".ndjson") || entry.endsWith(".inbox.ndjson")) continue;
661
- const label = entry.slice(0, -7);
662
729
  const file = join(dir, entry);
663
- const lines = readTail(file, maxLines);
730
+ const read = readSourceFile(file, "worker-tail", join(workersDir, entry));
731
+ diagnostics.push(...read.diagnostics);
732
+ const lines = tailLines(read.value, maxLines);
664
733
  const cwd = workerCwd(lines);
665
- out.set(label, {
734
+ out.set(entry.slice(0, -7), {
666
735
  file,
667
736
  lines,
668
737
  ...cwd ? { cwd } : {}
669
738
  });
670
739
  }
671
- return out;
740
+ return {
741
+ value: out,
742
+ diagnostics
743
+ };
672
744
  }
673
745
  function workerCwd(lines) {
674
746
  for (const line of [...lines].reverse()) try {
@@ -676,12 +748,46 @@ function workerCwd(lines) {
676
748
  if (parsed.kind === "started" && typeof parsed.cwd === "string" && parsed.cwd.trim()) return parsed.cwd;
677
749
  } catch {}
678
750
  }
679
- function readJson(file) {
751
+ function readSupervisorState(dir) {
752
+ const path = "state.json";
753
+ const read = readSourceFile(join(dir, path), "supervisor-state", path);
754
+ if (read.diagnostics.length > 0) return {
755
+ value: void 0,
756
+ diagnostics: read.diagnostics
757
+ };
758
+ if (read.value === void 0) return {
759
+ value: void 0,
760
+ diagnostics: [{
761
+ source: "supervisor-state",
762
+ path,
763
+ reason: "missing"
764
+ }]
765
+ };
766
+ let parsed;
680
767
  try {
681
- return JSON.parse(readFileSync(file, "utf8"));
768
+ parsed = JSON.parse(read.value);
682
769
  } catch {
683
- return;
770
+ return {
771
+ value: void 0,
772
+ diagnostics: [{
773
+ source: "supervisor-state",
774
+ path,
775
+ reason: "partial-json"
776
+ }]
777
+ };
684
778
  }
779
+ if (!isSupervisorState(parsed)) return {
780
+ value: void 0,
781
+ diagnostics: [{
782
+ source: "supervisor-state",
783
+ path,
784
+ reason: "invalid-state"
785
+ }]
786
+ };
787
+ return {
788
+ value: parsed,
789
+ diagnostics: []
790
+ };
685
791
  }
686
792
  function isSupervisorState(value) {
687
793
  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 +910,11 @@ let state = initialState([], process.cwd());
804
910
  let snapshot = {
805
911
  root: state.root,
806
912
  generatedAt: 0,
807
- supervisors: []
913
+ supervisors: [],
914
+ completeness: "complete",
915
+ diagnostics: [],
916
+ discovered: 0,
917
+ loaded: 0
808
918
  };
809
919
  let targets = [];
810
920
  let timer;
@@ -1110,11 +1220,6 @@ function requestCancel() {
1110
1220
  state.notice = `${worker.label} is ${worker.status}; nothing to cancel`;
1111
1221
  return;
1112
1222
  }
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
1223
  try {
1119
1224
  const record = cancelWorker(supervisor.stateDir, worker.id, randomUUID(), {
1120
1225
  reason: "operator requested cancel from TUI",
@@ -1127,13 +1232,11 @@ function requestCancel() {
1127
1232
  return;
1128
1233
  }
1129
1234
  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)`;
1235
+ const record = cancelRun(supervisor.stateDir, randomUUID(), {
1236
+ reason: "operator requested cancel from TUI",
1237
+ source: "agent-runtime-top"
1238
+ });
1239
+ 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
1240
  } catch (err) {
1138
1241
  state.notice = `cancel request failed: ${err instanceof Error ? err.message : String(err)}`;
1139
1242
  }
@@ -1144,4 +1247,4 @@ function wrap(value, size) {
1144
1247
  //#endregion
1145
1248
  export { renderTopFrameWithLayout as a, renderTopFrame as i, runTopApp as n, loadTopSnapshot as r, renderTopOnce as t };
1146
1249
 
1147
- //# sourceMappingURL=top-app-BMOSKK06.js.map
1250
+ //# sourceMappingURL=top-app-tKo9OrON.js.map