@tangle-network/agent-runtime 2.3.11 → 3.0.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 (77) hide show
  1. package/dist/{activation-BzNeFJDB.js → activation-BE0duxMf.js} +4 -4
  2. package/dist/{activation-BzNeFJDB.js.map → activation-BE0duxMf.js.map} +1 -1
  3. package/dist/{activation-B8dLwJj6.d.ts → activation-kREPGozZ.d.ts} +2 -2
  4. package/dist/agent.d.ts +1 -1
  5. package/dist/agent.js +3 -3
  6. package/dist/{bundle-DhV73H6U.js → bundle-ZHO7QFZw.js} +2 -2
  7. package/dist/{bundle-DhV73H6U.js.map → bundle-ZHO7QFZw.js.map} +1 -1
  8. package/dist/candidate-execution/index.d.ts +3 -3
  9. package/dist/candidate-execution/index.js +5 -5
  10. package/dist/{coordination-manager-BluavEgY.js → coordination-manager-B9goecNC.js} +4 -4
  11. package/dist/{coordination-manager-BluavEgY.js.map → coordination-manager-B9goecNC.js.map} +1 -1
  12. package/dist/{delegate-CYWL0MrO.js → delegate-C-wmgWCF.js} +2 -2
  13. package/dist/{delegate-CYWL0MrO.js.map → delegate-C-wmgWCF.js.map} +1 -1
  14. package/dist/durable.d.ts +1 -1
  15. package/dist/durable.js +9 -9
  16. package/dist/{graph-ByNMeS0j.js → graph-C_564r0C.js} +7 -7
  17. package/dist/graph-C_564r0C.js.map +1 -0
  18. package/dist/{improve-D9A79N5a.js → improve-BZdFdcUC.js} +7 -7
  19. package/dist/{improve-D9A79N5a.js.map → improve-BZdFdcUC.js.map} +1 -1
  20. package/dist/index.d.ts +4 -4
  21. package/dist/index.js +10 -10
  22. package/dist/intelligence.d.ts +4 -4
  23. package/dist/intelligence.js +7 -7
  24. package/dist/kernel.d.ts +3 -3
  25. package/dist/kernel.js +12 -12
  26. package/dist/{loop-runner-D9fuOb69.d.ts → loop-runner-D8NZLPE5.d.ts} +2 -2
  27. package/dist/{loop-runner-DiMfhI_z.js → loop-runner-_9_GtzO5.js} +2 -2
  28. package/dist/{loop-runner-DiMfhI_z.js.map → loop-runner-_9_GtzO5.js.map} +1 -1
  29. package/dist/loop-runner-bin.d.ts +1 -1
  30. package/dist/loop-runner-bin.js +1 -1
  31. package/dist/mcp/bin.js +3 -3
  32. package/dist/mcp/index.d.ts +1 -1
  33. package/dist/mcp/index.js +6 -6
  34. package/dist/{prepare-DrHOZFJy.js → prepare-CU0LM1_X.js} +3 -3
  35. package/dist/{prepare-DrHOZFJy.js.map → prepare-CU0LM1_X.js.map} +1 -1
  36. package/dist/{profile-BzzmKuIX.js → profile-By6JkIQi.js} +2 -2
  37. package/dist/{profile-BzzmKuIX.js.map → profile-By6JkIQi.js.map} +1 -1
  38. package/dist/profiles.d.ts +1 -1
  39. package/dist/{protected-model-port-IKqhTypD.d.ts → protected-model-port-BBsYuEY0.d.ts} +2 -2
  40. package/dist/{provision-supervisor-DP5U58V4.js → provision-supervisor-DX4fd6Ib.js} +5 -5
  41. package/dist/{provision-supervisor-DP5U58V4.js.map → provision-supervisor-DX4fd6Ib.js.map} +1 -1
  42. package/dist/{run-cancellation-BxoFCpJ_.js → run-cancellation-BTjyVpVW.js} +2 -2
  43. package/dist/{run-cancellation-BxoFCpJ_.js.map → run-cancellation-BTjyVpVW.js.map} +1 -1
  44. package/dist/{runtime-DS5AgACg.js → runtime-DsH0QnW0.js} +54 -30
  45. package/dist/runtime-DsH0QnW0.js.map +1 -0
  46. package/dist/{scope-DRaBilEX.js → scope-BeI3tmVX.js} +2550 -2487
  47. package/dist/scope-BeI3tmVX.js.map +1 -0
  48. package/dist/{search-executor-DLo_9jUv.js → search-executor-C-E-umcI.js} +4 -4
  49. package/dist/{search-executor-DLo_9jUv.js.map → search-executor-C-E-umcI.js.map} +1 -1
  50. package/dist/{server-DfHV4ajw.js → server-DAYqKU6o.js} +4 -4
  51. package/dist/{server-DfHV4ajw.js.map → server-DAYqKU6o.js.map} +1 -1
  52. package/dist/{structural-rollout-BIjjZ_XX.js → structural-rollout-DHdmB9MR.js} +4 -4
  53. package/dist/{structural-rollout-BIjjZ_XX.js.map → structural-rollout-DHdmB9MR.js.map} +1 -1
  54. package/dist/{supervise-6BCQ73Xa.js → supervise-QzwZc6K2.js} +7 -7
  55. package/dist/{supervise-6BCQ73Xa.js.map → supervise-QzwZc6K2.js.map} +1 -1
  56. package/dist/{supervision-discovery-Da5zebY2.js → supervision-discovery-CyvJVbTM.js} +3 -3
  57. package/dist/{supervision-discovery-Da5zebY2.js.map → supervision-discovery-CyvJVbTM.js.map} +1 -1
  58. package/dist/{supervisor-3JHXy3tz.js → supervisor-REUnT7iX.js} +222 -147
  59. package/dist/supervisor-REUnT7iX.js.map +1 -0
  60. package/dist/testing.d.ts +1 -1
  61. package/dist/testing.js +13 -13
  62. package/dist/{top-web-DK6lTMHG.js → top-web-DRfER2jW.js} +551 -149
  63. package/dist/top-web-DRfER2jW.js.map +1 -0
  64. package/dist/tui/bin.js +4 -3
  65. package/dist/tui/bin.js.map +1 -1
  66. package/dist/tui/index.d.ts +203 -3
  67. package/dist/tui/index.js +3 -3
  68. package/dist/{types-S3RbyJ4x.d.ts → types-Bm4xC_e-.d.ts} +151 -21
  69. package/dist/{workspace-streams-Dep2L6XD.js → workspace-streams-BSEkDu3H.js} +69 -69
  70. package/dist/{workspace-streams-Dep2L6XD.js.map → workspace-streams-BSEkDu3H.js.map} +1 -1
  71. package/dist/{workspace-streams-Dq2Fzk3c.d.ts → workspace-streams-BdZsd12p.d.ts} +7 -2
  72. package/package.json +2 -1
  73. package/dist/graph-ByNMeS0j.js.map +0 -1
  74. package/dist/runtime-DS5AgACg.js.map +0 -1
  75. package/dist/scope-DRaBilEX.js.map +0 -1
  76. package/dist/supervisor-3JHXy3tz.js.map +0 -1
  77. package/dist/top-web-DK6lTMHG.js.map +0 -1
@@ -1,7 +1,7 @@
1
- import { Ki as recordValue, L as FileSpawnJournal, d as legacySupervisorRunsRoot, dn as FileObserverJournal, g as safeWorkerFile, i as nodeStreamFile, n as ROOT_STREAM_FILE, qt as FileResultBlobStore, v as supervisorRunsRoot, z as spawnJournalRecordEvents } from "./scope-DRaBilEX.js";
1
+ import { Jn as harnessTranscriptArtifact, L as FileSpawnJournal, Xi as recordValue, _r as runAbortable, d as legacySupervisorRunsRoot, dn as FileObserverJournal, g as safeWorkerFile, gr as linkAbort, i as nodeStreamFile, n as ROOT_STREAM_FILE, qt as FileResultBlobStore, v as supervisorRunsRoot, z as spawnJournalRecordEvents } from "./scope-BeI3tmVX.js";
2
2
  import { r as parseCommittedJsonLines } from "./jsonl-file-BBP9Dz9w.js";
3
- import { h as rootCoordinationOwner, v as FileCoordinationLog } from "./run-cancellation-BxoFCpJ_.js";
4
- import { d as projectPursuit, o as readFailureRecord, s as readSettleRecord, t as discoverDurableSupervisionRun } from "./supervision-discovery-Da5zebY2.js";
3
+ import { h as rootCoordinationOwner, v as FileCoordinationLog } from "./run-cancellation-BTjyVpVW.js";
4
+ import { d as projectPursuit, o as readFailureRecord, s as readSettleRecord, t as discoverDurableSupervisionRun } from "./supervision-discovery-CyvJVbTM.js";
5
5
  import { createRequire } from "node:module";
6
6
  import { isRecord } from "@tangle-network/agent-core";
7
7
  import { createHash } from "node:crypto";
@@ -10,71 +10,296 @@ import { basename, dirname, extname, join, resolve, sep } from "node:path";
10
10
  import { readFile, realpath, stat } from "node:fs/promises";
11
11
  import { createServer } from "node:http";
12
12
  import { StringDecoder } from "node:string_decoder";
13
+ import { once } from "node:events";
13
14
  // src/tui/top-transcript.ts
14
15
  /** Read selected history on demand, leaving the live topology snapshot bounded and fast. */
15
16
  async function transcriptHistory(worker, runDir, node) {
17
+ return readTopAgentHistory(worker, runDir ? new FileResultBlobStore(join(runDir, "blobs")) : void 0, node);
18
+ }
19
+ /** Task, result and progress use the same projection for file-backed and SQL-backed runs. */
20
+ async function readTopAgentHistory(worker, blobs, node) {
16
21
  const rows = [];
17
- const identity = node?.identity;
18
- if (runDir && typeof identity?.taskDigest === "string" && worker.startedAt) {
19
- const task = await new FileResultBlobStore(join(runDir, "blobs")).get(identity.taskDigest);
20
- if (task !== void 0) rows.unshift({
22
+ const identity = recordValue(node?.identity ?? worker.identity);
23
+ if (blobs && typeof identity?.taskDigest === "string" && worker.startedAt) {
24
+ const task = await blobs.get(identity.taskDigest);
25
+ if (task !== void 0) rows.push({
21
26
  at: worker.startedAt,
22
27
  event: {
23
28
  kind: "notice",
24
29
  provenance: "delegated-input",
25
- source: `parent ${node?.parentId ?? "run caller"}; task ${identity.taskDigest}${typeof identity.profileDigest === "string" ? `; profile ${identity.profileDigest}` : ""}; Runtime FileResultBlobStore`,
26
- text: typeof task === "string" ? task : JSON.stringify(task, null, 2)
30
+ source: `parent ${worker.parent ?? node?.parentId ?? "run caller"}; task ${identity.taskDigest}; profile ${identity.profileDigest}`,
31
+ text: `Request from ${worker.parent ?? node?.parentId ?? "run caller"}\n${typeof task === "string" ? task : JSON.stringify(task, null, 2)}`
27
32
  }
28
33
  });
29
34
  }
30
- if (!worker.eventFile) {
31
- const retained = runDir ? await retainedTranscriptLines(worker, runDir) : [];
32
- const native = transcriptRows(retained.length ? {
33
- ...worker,
34
- liveTail: retained
35
- } : worker);
36
- if (!native.length && worker.startedAt) rows.push({
37
- at: worker.startedAt,
38
- event: {
39
- kind: "notice",
40
- provenance: "capture-unavailable",
41
- text: "Native conversation was not captured for this agent.",
42
- source: "Runtime recorded capture"
35
+ const progress = transcriptTail(worker);
36
+ if (worker.startedAt) rows.push({
37
+ at: worker.startedAt,
38
+ event: {
39
+ kind: "notice",
40
+ provenance: "capture-unavailable",
41
+ text: "Full conversation capture has not been verified in this progress tail.",
42
+ source: "Runtime progress evidence"
43
+ }
44
+ });
45
+ const outRef = node?.outRef ?? worker.outRef;
46
+ const result = blobs && outRef && worker.endedAt ? await blobs.get(outRef) : void 0;
47
+ if (result !== void 0) progress.push({
48
+ at: worker.endedAt,
49
+ event: {
50
+ kind: "notice",
51
+ provenance: "recorded-result",
52
+ source: `result ${outRef}; Runtime ResultBlobStore`,
53
+ text: typeof result === "string" ? result : JSON.stringify(result, null, 2)
54
+ }
55
+ });
56
+ return [...rows, ...progress];
57
+ }
58
+ /** Resolve ordinary Runtime transcript evidence, never a product-specific capture registry. */
59
+ async function readTopAgentInspection({ worker, runId, blobs, readSessions, artifacts, signal }) {
60
+ const evidence = worker.harnessTranscript;
61
+ const files = {
62
+ scope: "none",
63
+ complete: true,
64
+ reason: "Transcript evidence does not include a workspace inventory",
65
+ entries: []
66
+ };
67
+ if (!evidence || evidence.status !== "available") return {
68
+ coverage: {
69
+ status: "missing",
70
+ source: "Runtime transcript receipt",
71
+ reason: evidence?.reason ?? "No transcript receipt was recorded"
72
+ },
73
+ files
74
+ };
75
+ const metadata = await harnessTranscriptArtifact(evidence, blobs, {
76
+ content: false,
77
+ signal
78
+ });
79
+ if (!metadata) throw new Error("Available transcript receipt has no metadata");
80
+ const binding = inspectionBinding(metadata, worker, runId);
81
+ if (binding.mismatch.length) return {
82
+ coverage: {
83
+ status: "missing",
84
+ source: "Runtime transcript receipt",
85
+ code: "source-mismatch",
86
+ reason: binding.mismatch.join("; ")
87
+ },
88
+ files
89
+ };
90
+ const artifact = await harnessTranscriptArtifact(evidence, blobs, {
91
+ artifacts,
92
+ signal
93
+ });
94
+ if (!artifact) throw new Error("Available transcript receipt has no artifact");
95
+ const projection = harnessSessionRows(await readSessions(artifact, signal));
96
+ const reasons = [
97
+ ...binding.missing,
98
+ ...evidence.missing ?? [],
99
+ ...artifact.skipped.map((file) => `${file.path}: ${file.reason}`),
100
+ ...projection.gaps.map((gap) => `${gap.sessionId}/${gap.recordId}: ${gap.reason}`)
101
+ ];
102
+ const complete = evidence.coverageComplete === true && reasons.length === 0 && projection.rows.length > 0;
103
+ return {
104
+ coverage: {
105
+ status: complete ? "complete" : "partial",
106
+ source: `${artifact.harness} Runtime transcript`,
107
+ ref: `urn:${evidence.transcriptRef}`,
108
+ ...binding.missing.length ? { code: "source-unbound" } : {},
109
+ ...!complete ? { reason: reasons.join("; ") || "Source completeness was not attested" } : {}
110
+ },
111
+ rows: projection.rows,
112
+ files
113
+ };
114
+ }
115
+ /** Verify the receipt belongs to the selected node before resolving any native/archive bytes. */
116
+ function inspectionBinding(metadata, worker, runId) {
117
+ const mismatch = [], missing = [];
118
+ if (metadata.binding !== void 0 && !recordValue(metadata.binding)) mismatch.push("Capture Bridge binding is malformed");
119
+ if (metadata.source && metadata.binding) mismatch.push("Capture has conflicting source bindings");
120
+ const source = metadata.source ?? metadata.binding;
121
+ if (!source) return {
122
+ mismatch,
123
+ missing: ["Capture has no recorded node binding"]
124
+ };
125
+ const node = recordValue(source.node);
126
+ if (!node) {
127
+ if (source.node !== void 0) mismatch.push("Capture node binding is malformed");
128
+ else missing.push("Capture has no recorded node identity");
129
+ } else {
130
+ for (const [key, expected] of [
131
+ ["rootId", runId],
132
+ ["nodeId", worker.id],
133
+ ["parentId", worker.parent]
134
+ ]) if (expected !== void 0 && node[key] !== expected) mismatch.push(`Capture ${key} does not match selected node`);
135
+ const attempt = worker.executionBindings?.at(-1)?.attemptId;
136
+ if (typeof node.attemptId !== "string" || !node.attemptId) mismatch.push("Capture attempt identity is malformed");
137
+ else if (attempt && node.attemptId !== attempt) mismatch.push("Capture attempt does not match selected node");
138
+ else if (!attempt) missing.push("Selected node has no recorded execution attempt");
139
+ const identity = recordValue(node.identity);
140
+ for (const key of ["profileDigest", "taskDigest"]) {
141
+ const expected = worker.identity?.[key];
142
+ if (expected && identity?.[key] === void 0) missing.push(`Capture has no recorded ${key}`);
143
+ else if (expected && identity?.[key] !== expected) mismatch.push(`Capture ${key} does not match selected node`);
144
+ }
145
+ }
146
+ const materialization = worker.materialization;
147
+ if (materialization?.status !== "known") missing.push("Selected node has no known materialization");
148
+ else {
149
+ if (source.profileDigest !== materialization.effectiveProfileDigest) mismatch.push("Capture profile does not match selected materialization");
150
+ const execution = materialization.execution;
151
+ const kind = metadata.source ? "environment" : "session";
152
+ const id = metadata.source?.environmentId ?? metadata.binding?.sessionId;
153
+ if (execution.kind !== kind || execution.id !== id) mismatch.push("Capture execution does not match selected materialization");
154
+ }
155
+ if (metadata.binding && (metadata.binding.kind !== "bridge" || !metadata.binding.nativeSessionId || !metadata.binding.sessionId)) mismatch.push("Capture Bridge binding is malformed");
156
+ return {
157
+ mismatch,
158
+ missing
159
+ };
160
+ }
161
+ /** One selected-agent mapping for filesystem and API transports; no execution or I/O. */
162
+ function topAgentWorker(run, workerId) {
163
+ const child = run.workers.find((worker) => worker.id === workerId);
164
+ if (child || run.id !== workerId) return child;
165
+ return {
166
+ id: run.id,
167
+ label: "root",
168
+ status: run.status === "cancelled" ? "cancelled" : ["done", "succeeded"].includes(run.status) ? "done" : ["down", "failed"].includes(run.status) ? "down" : "running",
169
+ startedAt: run.startedAt,
170
+ endedAt: run.completedAt,
171
+ latencyMs: run.totals.latencyMs,
172
+ spend: run.driverSpend,
173
+ metered: {
174
+ iterations: 0,
175
+ tokensInput: 0,
176
+ tokensOutput: 0,
177
+ usd: 0,
178
+ ms: 0
179
+ },
180
+ liveTail: run.progressTail
181
+ };
182
+ }
183
+ /** Metadata keeps full recorded context while the conversation can show compact attribution. */
184
+ function topAgentMetadata(inspection, recorded) {
185
+ const { rows, ...metadata } = inspection ?? { coverage: {
186
+ status: "missing",
187
+ source: "Runtime",
188
+ reason: "Verified conversation inspection was not provided"
189
+ } };
190
+ return {
191
+ ...metadata,
192
+ context: [
193
+ ...metadata.context ?? [],
194
+ ...recorded.filter((row) => row.event.provenance === "delegated-input"),
195
+ ...(rows ?? []).filter((row) => row.event.provenance === "system-instructions")
196
+ ]
197
+ };
198
+ }
199
+ /** Project selected conversation rows into ordered reset and row frames. */
200
+ function createTopAgentStream(generation) {
201
+ let representation;
202
+ let initiatingInput;
203
+ const seen = /* @__PURE__ */ new Set();
204
+ let lastSeq = 0;
205
+ return {
206
+ reset: { generation },
207
+ frame({ recorded, inspection, alive, includeContext }) {
208
+ initiatingInput = recorded.find((row) => row.event.provenance === "delegated-input") ?? initiatingInput;
209
+ const input = initiatingInput?.event.text;
210
+ const task = input?.includes("\n") ? input.slice(input.indexOf("\n") + 1) : void 0;
211
+ const hasNativePrompt = !!task && !!inspection?.rows?.some((row) => row.event.kind === "user" && row.event.actor !== "injected" && row.event.text === task);
212
+ const shownInput = initiatingInput && hasNativePrompt && !includeContext ? {
213
+ ...initiatingInput,
214
+ event: {
215
+ ...initiatingInput.event,
216
+ text: input.slice(0, input.indexOf("\n")),
217
+ provenance: "recorded-sender"
218
+ }
219
+ } : initiatingInput;
220
+ const next = inspection?.rows?.length ? `capture:${inspection.coverage.ref ?? inspection.coverage.source}:${hasNativePrompt}` : "progress";
221
+ const frames = [];
222
+ if (representation !== void 0 && representation !== next) {
223
+ seen.clear();
224
+ lastSeq = 0;
225
+ generation += 1;
226
+ frames.push({
227
+ event: "reset",
228
+ data: { generation }
229
+ });
43
230
  }
44
- });
45
- const result = runDir && node?.outRef && worker.endedAt ? await new FileResultBlobStore(join(runDir, "blobs")).get(node.outRef) : void 0;
46
- if (result !== void 0) native.push({
47
- at: worker.endedAt,
48
- event: {
49
- kind: "notice",
50
- provenance: "recorded-result",
51
- source: `result ${node.outRef}; Runtime FileResultBlobStore`,
52
- text: typeof result === "string" ? result : JSON.stringify(result, null, 2)
231
+ representation = next;
232
+ const events = (inspection?.rows?.length ? [
233
+ ...shownInput ? [shownInput] : [],
234
+ ...recorded.filter((row) => inspection.coverage.status !== "complete" && row.event.provenance === "recorded-result"),
235
+ ...inspection.rows.filter((row) => includeContext || row.event.provenance !== "system-instructions")
236
+ ] : recorded).flatMap((row) => {
237
+ const key = "id" in row && typeof row.id === "string" ? row.id : createHash("sha256").update(JSON.stringify(row)).digest("hex");
238
+ if (seen.has(key)) return [];
239
+ seen.add(key);
240
+ if (next === "progress" && seen.size > 2e3) seen.delete(seen.values().next().value);
241
+ return [{
242
+ ...row,
243
+ seq: ++lastSeq
244
+ }];
245
+ });
246
+ for (let offset = 0; offset < Math.max(events.length, 1); offset += 100) {
247
+ const batch = events.slice(offset, offset + 100);
248
+ frames.push({
249
+ event: "rows",
250
+ data: {
251
+ generation,
252
+ events: batch,
253
+ lastSeq: batch.at(-1)?.seq ?? lastSeq,
254
+ alive,
255
+ window: inspection?.coverage.status === "complete" ? "verified-native" : "recorded-tail",
256
+ ...inspection ? { coverage: inspection.coverage } : {}
257
+ }
258
+ });
53
259
  }
54
- });
55
- return [...rows, ...native];
56
- }
57
- return [...rows, ...transcriptRows({ liveTail: readTranscriptTail(worker.eventFile) })];
260
+ return frames;
261
+ }
262
+ };
58
263
  }
59
- /**
60
- * A settled worker's retained Router conversation as progress lines, for an executor that ran its
61
- * tool loop in process and so streamed nothing. The messages carry no times; each takes the
62
- * worker's settlement time. Other harnesses' session files have their own formats and stay unread.
63
- */
64
- async function retainedTranscriptLines(worker, runDir) {
65
- const at = worker.endedAt;
66
- if (worker.transcript?.harness !== "router" || at === void 0) return [];
67
- return ((await new FileResultBlobStore(join(runDir, "blobs")).get(worker.transcript.ref))?.files ?? []).flatMap((file) => (typeof file.content === "string" ? file.content.split("\n") : []).flatMap((text) => {
68
- try {
69
- const message = recordValue(JSON.parse(text));
70
- return message?.role === "assistant" || message?.role === "tool" ? [JSON.stringify({
71
- at,
72
- message
73
- })] : [];
74
- } catch {
75
- return [];
264
+ /** Router records are Runtime's canonical ToolLoopMessageRecord, not a native file heuristic. */
265
+ async function retainedRouterInspection(worker, runDir) {
266
+ const evidence = worker.harnessTranscript;
267
+ if (!runDir || evidence?.status !== "available" || evidence.harness !== "router" || !worker.endedAt) return void 0;
268
+ const artifact = await harnessTranscriptArtifact(evidence, new FileResultBlobStore(join(runDir, "blobs")));
269
+ if (!artifact || !("files" in artifact)) return void 0;
270
+ const rows = artifact.files.flatMap((file) => "content" in file ? file.content.split("\n").filter(Boolean).map((line) => recordValue(JSON.parse(line))).filter((row) => row && typeof row.role === "string") : []).flatMap((message, index) => transcriptRows({ liveTail: [JSON.stringify({
271
+ at: worker.endedAt,
272
+ message
273
+ })] }).map((row, part) => ({
274
+ ...row,
275
+ id: JSON.stringify([
276
+ evidence.transcriptRef,
277
+ index,
278
+ part
279
+ ]),
280
+ sessionId: `router:${worker.id}`,
281
+ part,
282
+ event: {
283
+ ...row.event,
284
+ provenance: "router-transcript",
285
+ source: "Message time unknown; shown at captured settlement time"
286
+ }
287
+ })));
288
+ return {
289
+ coverage: {
290
+ status: "partial",
291
+ source: "Runtime Router conversation, displayed at recorded settlement time",
292
+ reason: "Per-message times were not captured",
293
+ ref: `urn:${evidence.transcriptRef}`
294
+ },
295
+ rows,
296
+ files: {
297
+ scope: "none",
298
+ complete: true,
299
+ reason: "This in-process conversation has no sandbox workspace inventory",
300
+ entries: []
76
301
  }
77
- }));
302
+ };
78
303
  }
79
304
  /** Present the recorded tail through sandbox-ui's existing agent-stream contract. */
80
305
  function transcriptRows(worker) {
@@ -106,12 +331,17 @@ function transcriptRows(worker) {
106
331
  ...event,
107
332
  kind
108
333
  });
109
- continue;
110
334
  }
335
+ if (event?.kind) continue;
336
+ const legacy = (event) => push({
337
+ ...event,
338
+ provenance: "unverified-progress",
339
+ source: "Legacy progress only; full capture is unverified"
340
+ });
111
341
  const message = recordValue(value?.message);
112
342
  if (!message) continue;
113
343
  if (message.role === "tool") {
114
- push({
344
+ legacy({
115
345
  kind: "tool-result",
116
346
  toolCallId: String(message.tool_call_id),
117
347
  result: message.content
@@ -120,7 +350,7 @@ function transcriptRows(worker) {
120
350
  }
121
351
  for (const item of Array.isArray(message.tool_calls) ? message.tool_calls : []) {
122
352
  const call = recordValue(item), fn = recordValue(call?.function);
123
- if (call && fn) push({
353
+ if (call && fn) legacy({
124
354
  kind: "tool-call",
125
355
  toolCallId: String(call.id),
126
356
  toolName: String(fn.name),
@@ -133,21 +363,21 @@ function transcriptRows(worker) {
133
363
  }] : Array.isArray(message.content) ? message.content : [];
134
364
  for (const part of parts) {
135
365
  if (!recordValue(part)) continue;
136
- if (part.type === "text" && typeof part.text === "string") push({
366
+ if (part.type === "text" && typeof part.text === "string" && part.text.length > 0) legacy({
137
367
  kind: message.role === "user" ? "user" : "text",
138
368
  text: part.text
139
369
  });
140
- else if (part.type === "thinking" && typeof part.thinking === "string") push({
370
+ else if (part.type === "thinking" && typeof part.thinking === "string") legacy({
141
371
  kind: "reasoning",
142
372
  text: part.thinking
143
373
  });
144
- else if (part.type === "tool_use") push({
374
+ else if (part.type === "tool_use") legacy({
145
375
  kind: "tool-call",
146
376
  toolCallId: String(part.id),
147
377
  toolName: String(part.name),
148
378
  args: part.input
149
379
  });
150
- else if (part.type === "tool_result") push({
380
+ else if (part.type === "tool_result") legacy({
151
381
  kind: "tool-result",
152
382
  toolCallId: String(part.tool_use_id),
153
383
  result: part.content
@@ -176,6 +406,9 @@ const activityKinds = /* @__PURE__ */ new Set([
176
406
  "interaction",
177
407
  "child_task"
178
408
  ]);
409
+ function recordedActivity(line) {
410
+ return transcriptRows({ liveTail: [line] }).find((row) => activityKinds.has(row.event.kind));
411
+ }
179
412
  /** Read appended UTF-8 bytes once; complete EOF JSON follows the durable reader contract. */
180
413
  function readRecordedEvents(file, maxLines = 8) {
181
414
  const fd = openSync(file, "r");
@@ -215,7 +448,7 @@ function readRecordedEvents(file, maxLines = 8) {
215
448
  if (!line.trim()) continue;
216
449
  lines.push(line);
217
450
  if (lines.length > 200) lines.shift();
218
- const activity = transcriptRows({ liveTail: [line] }).find((row) => activityKinds.has(row.event.kind));
451
+ const activity = recordedActivity(line);
219
452
  if (activity) cursor.times.push(Date.parse(activity.at));
220
453
  }
221
454
  }
@@ -225,7 +458,7 @@ function readRecordedEvents(file, maxLines = 8) {
225
458
  JSON.parse(cursor.pending);
226
459
  pending = [cursor.pending];
227
460
  } catch {}
228
- const final = transcriptRows({ liveTail: pending }).find((row) => activityKinds.has(row.event.kind));
461
+ const final = pending.length ? recordedActivity(pending[0]) : void 0;
229
462
  const times = (final ? [...cursor.times, Date.parse(final.at)] : cursor.times).sort((a, b) => a - b);
230
463
  const gaps = times.slice(1).map((at, i) => at - times[i]).sort((a, b) => a - b);
231
464
  const mid = Math.floor(gaps.length / 2);
@@ -283,6 +516,110 @@ function readWorkerEventTails(dir) {
283
516
  diagnostics
284
517
  };
285
518
  }
519
+ /** One ordered projection for every strict native reader, with explicit unrenderable evidence. */
520
+ function harnessSessionRows(sessions) {
521
+ const rows = [];
522
+ const gaps = [];
523
+ for (const session of sessions) {
524
+ const emitted = /* @__PURE__ */ new Set();
525
+ const push = (recordId, part, value, event) => {
526
+ if (!value || !Number.isFinite(Date.parse(value))) {
527
+ gaps.push({
528
+ sessionId: session.nativeSessionId,
529
+ recordId,
530
+ reason: "Native record has no valid recorded time"
531
+ });
532
+ return;
533
+ }
534
+ rows.push({
535
+ id: JSON.stringify([
536
+ session.nativeSessionId,
537
+ event.kind,
538
+ recordId,
539
+ part
540
+ ]),
541
+ sessionId: session.nativeSessionId,
542
+ part,
543
+ at: new Date(value).toISOString(),
544
+ event: event.actor === "injected" ? {
545
+ ...event,
546
+ provenance: "system-instructions"
547
+ } : event
548
+ });
549
+ };
550
+ const tool = (id, result, at, recordId = id, part = 0, actor) => {
551
+ const call = session.toolCalls.find((item) => item.id === id);
552
+ if (!call || result && !call.result) {
553
+ gaps.push({
554
+ sessionId: session.nativeSessionId,
555
+ recordId: id,
556
+ reason: "Referenced tool evidence is missing"
557
+ });
558
+ return;
559
+ }
560
+ const key = `${result ? "result" : "call"}:${id}`;
561
+ if (emitted.has(key)) return;
562
+ emitted.add(key);
563
+ const toolCallId = `${session.nativeSessionId}:${id}`;
564
+ push(recordId, part, at ?? (result ? call.endedAt : call.startedAt), result ? {
565
+ kind: "tool-result",
566
+ toolCallId,
567
+ result: call.result?.output ?? call.result?.text,
568
+ actor,
569
+ ...actor ? { source: `Native actor ${actor}` } : {}
570
+ } : {
571
+ kind: "tool-call",
572
+ toolCallId,
573
+ toolName: call.name,
574
+ args: call.input ?? call.inputText,
575
+ actor,
576
+ ...actor ? { source: `Native actor ${actor}` } : {}
577
+ });
578
+ };
579
+ for (const message of session.messages) for (const [part, value] of message.parts.entries()) if (value.type === "tool-call" || value.type === "tool-result") tool(value.toolCallId ?? "", value.type === "tool-result", message.at, message.id, part, message.actor);
580
+ else if ((value.type === "text" || value.type === "reasoning") && value.text) push(message.id, part, message.at, {
581
+ kind: value.type === "reasoning" ? "reasoning" : message.role === "user" ? "user" : message.role === "assistant" ? "text" : "notice",
582
+ text: value.text,
583
+ actor: message.actor,
584
+ ...message.actor ? { source: `Native actor ${message.actor}` } : {},
585
+ ...![
586
+ "user",
587
+ "assistant",
588
+ "tool"
589
+ ].includes(message.role) ? {
590
+ provenance: "system-instructions",
591
+ source: message.role
592
+ } : {}
593
+ });
594
+ else if (value.type !== "text" && value.type !== "reasoning") gaps.push({
595
+ sessionId: session.nativeSessionId,
596
+ recordId: message.id,
597
+ reason: `Native ${value.type} content is retained but not projected inline`
598
+ });
599
+ for (const call of session.toolCalls) {
600
+ if (!emitted.has(`call:${call.id}`)) {
601
+ gaps.push({
602
+ sessionId: session.nativeSessionId,
603
+ recordId: call.id,
604
+ reason: "Tool call has no ordered message-part reference"
605
+ });
606
+ tool(call.id, false);
607
+ }
608
+ if (call.result && !emitted.has(`result:${call.id}`)) {
609
+ gaps.push({
610
+ sessionId: session.nativeSessionId,
611
+ recordId: call.id,
612
+ reason: "Tool result has no ordered message-part reference"
613
+ });
614
+ tool(call.id, true);
615
+ }
616
+ }
617
+ }
618
+ return {
619
+ rows: rows.sort((a, b) => a.at.localeCompare(b.at)),
620
+ gaps
621
+ };
622
+ }
286
623
  // src/tui/workflow-journal.ts
287
624
  /** Native workflows have no Runtime accounting. Translate recorded lifecycle only. */
288
625
  function workflowJournal(runDir, text) {
@@ -437,6 +774,7 @@ function loadTopSnapshot(rootDir, input = Date.now()) {
437
774
  supervisors.sort((a, b) => String(b.startedAt ?? "").localeCompare(String(a.startedAt ?? "")));
438
775
  return topSnapshot(root, now, supervisors, diagnostics, discovered);
439
776
  }
777
+ /** Combine supervisor projections and source diagnostics into one snapshot. */
440
778
  function topSnapshot(root, now, supervisors, diagnostics = [], discovered = 1, pursuit) {
441
779
  return {
442
780
  root,
@@ -602,13 +940,14 @@ function retainedTranscript(event) {
602
940
  function recordedReason(event) {
603
941
  return isRecord(event) && typeof event.reason === "string" ? event.reason : void 0;
604
942
  }
943
+ /** Project committed lifecycle and spend evidence into one supervisor view. */
605
944
  function buildSupervisorView(state, stateDir, events, progressTail, now, workerEventTails = /* @__PURE__ */ new Map(), accounting) {
606
945
  const workers = /* @__PURE__ */ new Map();
607
946
  let driverSpend = emptySpend;
608
947
  const journalRootId = events.find((event) => event.kind === "spawned" && !event.parent && event.label === "root")?.id;
609
948
  const isRoot = (id) => id === state.id || id === journalRootId;
610
949
  const terminal = accounting ? void 0 : events.filter((event) => isRoot(event.id) && (event.kind === "settled" || event.kind === "cancelled")).at(-1);
611
- const rootReason = recordedReason(terminal);
950
+ const rootReason = recordedReason(terminal) ?? state.reason;
612
951
  for (const event of events) {
613
952
  if (isRoot(event.id) || event.kind === "spawned" && !event.parent && event.label === "root") {
614
953
  if (event.kind === "metered" && event.accountingOnly !== true) driverSpend = addSpend(driverSpend, parseSpend(event.spend));
@@ -616,20 +955,33 @@ function buildSupervisorView(state, stateDir, events, progressTail, now, workerE
616
955
  }
617
956
  const worker = ensureWorker(workers, event.id);
618
957
  if (event.kind === "spawned") {
958
+ for (const key of [
959
+ "endedAt",
960
+ "outRef",
961
+ "harnessTranscript",
962
+ "transcript",
963
+ "reason",
964
+ "infra",
965
+ "verdict"
966
+ ]) delete worker[key];
619
967
  worker.label = event.label ?? worker.label;
968
+ if (event.identity) worker.identity = event.identity;
620
969
  if (event.parent) worker.parent = event.parent;
621
970
  if (event.runtime) worker.runtime = event.runtime;
622
971
  worker.status = "running";
623
972
  if (event.at) worker.startedAt = event.at;
624
973
  const budget = parseBudget(event.budget);
625
974
  if (budget) worker.budget = budget;
626
- } else if (event.kind === "settled" || event.kind === "cancelled") {
975
+ } else if (event.kind === "materialized" || event.kind === "seat-materialized") worker.materialization = event.receipt;
976
+ else if (event.kind === "execution-bound") worker.executionBindings = [...worker.executionBindings ?? [], event.binding];
977
+ else if (event.kind === "settled" || event.kind === "cancelled") {
627
978
  if (event.at) worker.endedAt = event.at;
628
979
  const reason = recordedReason(event);
629
980
  if (reason !== void 0) worker.reason = reason;
630
981
  if (event.kind === "settled") {
631
982
  worker.status = event.status === "down" ? "down" : "done";
632
983
  if (event.outRef) worker.outRef = event.outRef;
984
+ if (event.harnessTranscript) worker.harnessTranscript = event.harnessTranscript;
633
985
  const transcript = retainedTranscript(event);
634
986
  if (transcript) worker.transcript = transcript;
635
987
  if (event.infra !== void 0) worker.infra = event.infra;
@@ -641,7 +993,7 @@ function buildSupervisorView(state, stateDir, events, progressTail, now, workerE
641
993
  worker.metered = emptySpend;
642
994
  }
643
995
  } else if (event.kind === "progress") worker.metered = parseSpend(event.spend);
644
- else if (event.accountingOnly !== true) worker.metered = addSpend(worker.metered, parseSpend(event.spend));
996
+ else if (event.kind === "metered" && event.accountingOnly !== true) worker.metered = addSpend(worker.metered, parseSpend(event.spend));
645
997
  }
646
998
  if (accounting) {
647
999
  driverSpend = observerSpend(accounting.totals.exclusiveByNode[accounting.runId]);
@@ -892,13 +1244,17 @@ function isSupervisorState(value) {
892
1244
  "workspaceDir"
893
1245
  ].every((key) => typeof value[key] === "string") && typeof value.budget === "number";
894
1246
  }
1247
+ /** Validate supported journal lifecycle and accounting event shapes. */
895
1248
  function isSpawnEvent(value) {
896
1249
  return isRecord(value) && typeof value.id === "string" && typeof value.kind === "string" && [
897
1250
  "spawned",
898
1251
  "settled",
899
1252
  "cancelled",
900
1253
  "metered",
901
- "progress"
1254
+ "progress",
1255
+ "materialized",
1256
+ "seat-materialized",
1257
+ "execution-bound"
902
1258
  ].includes(value.kind);
903
1259
  }
904
1260
  function isDirectory(path) {
@@ -919,7 +1275,122 @@ function parseTime(value) {
919
1275
  function sum(values) {
920
1276
  return values.reduce((total, value) => total + value, 0);
921
1277
  }
1278
+ // src/tui/top-web-agent.ts
1279
+ const SOURCE_READ_TIMEOUT_MS = 3e4;
1280
+ /** Selected reads share the web server's origin, method and lifecycle boundary. */
1281
+ async function serveTopAgent({ request, response, path, base, roots, snapshots, transcripts, source, readSessions }) {
1282
+ const [, , , , rootIndex, runId, workerId] = path.split("/").map(decodeURIComponent);
1283
+ const root = roots[Number(rootIndex)];
1284
+ const run = root && snapshots.get(root)?.supervisors.find((entry) => entry.id === runId);
1285
+ const safeId = (id) => !!id && /^[a-z0-9_.:-]+$/i.test(id) && id !== "." && id !== "..";
1286
+ if (!safeId(runId) || !safeId(workerId) || !run || !run.workers.some((entry) => entry.id === workerId) && run.id !== workerId) {
1287
+ response.writeHead(404).end();
1288
+ return;
1289
+ }
1290
+ const own = root && existsSync(resolve(root, runId, "observer.jsonl")) ? resolve(root, runId) : void 0;
1291
+ const runDir = own ?? root;
1292
+ const pursuit = own ? (await loadTopSnapshot(root, { runDir: own })).pursuit : root ? snapshots.get(root)?.pursuit : void 0;
1293
+ const worker = () => {
1294
+ const run = root ? snapshots.get(root)?.supervisors.find((run) => run.id === runId) : void 0;
1295
+ const node = run && topAgentWorker(run, workerId);
1296
+ return node && node.id === run?.id && existsSync(resolve(runDir, "root-stream.jsonl")) ? {
1297
+ ...node,
1298
+ eventFile: resolve(runDir, "root-stream.jsonl")
1299
+ } : node;
1300
+ };
1301
+ if (!worker()) {
1302
+ response.writeHead(404).end();
1303
+ return;
1304
+ }
1305
+ const controller = new AbortController();
1306
+ response.on("close", () => controller.abort());
1307
+ const readSource = async () => {
1308
+ const deadline = new AbortController();
1309
+ const linked = linkAbort(controller.signal, deadline.signal);
1310
+ const timer = setTimeout(() => deadline.abort("Inspection source read exceeded its deadline"), SOURCE_READ_TIMEOUT_MS);
1311
+ timer.unref();
1312
+ try {
1313
+ const result = await runAbortable(() => source ? source({
1314
+ root: runDir,
1315
+ runId,
1316
+ workerId,
1317
+ signal: linked.signal
1318
+ }) : readSessions ? readTopAgentInspection({
1319
+ worker: worker(),
1320
+ runId,
1321
+ blobs: new FileResultBlobStore(join(runDir, "blobs")),
1322
+ readSessions,
1323
+ signal: linked.signal
1324
+ }) : retainedRouterInspection(worker(), runDir), linked.signal, "Inspection read stopped");
1325
+ return result?.coverage.status === "complete" && !result.rows?.length ? {
1326
+ ...result,
1327
+ coverage: {
1328
+ ...result.coverage,
1329
+ status: "partial",
1330
+ reason: "No verified native conversation rows were supplied"
1331
+ }
1332
+ } : result;
1333
+ } finally {
1334
+ clearTimeout(timer);
1335
+ linked.release();
1336
+ }
1337
+ };
1338
+ let history = await transcriptHistory(worker(), runDir, pursuit?.nodes.find((node) => node.runId === runId && node.id === workerId));
1339
+ if (!path.endsWith("/stream")) {
1340
+ const inspection = await readSource();
1341
+ response.writeHead(200, { "Content-Type": "application/json" });
1342
+ response.end(request.method === "HEAD" ? void 0 : JSON.stringify(topAgentMetadata(inspection, history ?? [])));
1343
+ return;
1344
+ }
1345
+ response.writeHead(200, {
1346
+ "Content-Type": "text/event-stream",
1347
+ "X-Accel-Buffering": "no"
1348
+ });
1349
+ response.flushHeaders();
1350
+ if (request.method === "HEAD") {
1351
+ response.end();
1352
+ return;
1353
+ }
1354
+ const stream = createTopAgentStream(Date.now());
1355
+ response.write(`event: reset\ndata: ${JSON.stringify(stream.reset)}\n\n`);
1356
+ let updating = false;
1357
+ const update = () => {
1358
+ if (updating || response.destroyed || response.writableEnded) return;
1359
+ updating = true;
1360
+ (async () => {
1361
+ const node = worker();
1362
+ if (!node || response.writableLength > 1048576) {
1363
+ response.destroy();
1364
+ return;
1365
+ }
1366
+ const inspection = await readSource();
1367
+ const recorded = history ?? transcriptTail(node);
1368
+ history = void 0;
1369
+ const alive = node.status === "running";
1370
+ const frames = stream.frame({
1371
+ recorded,
1372
+ inspection,
1373
+ alive,
1374
+ includeContext: new URL(request.url ?? "/", base).searchParams.get("context") === "1"
1375
+ });
1376
+ for (const frame of frames) if (!response.write(`event: ${frame.event}\ndata: ${JSON.stringify(frame.data)}\n\n`)) await once(response, "drain", { signal: controller.signal });
1377
+ if (!alive) {
1378
+ response.write("event: end\ndata: {}\n\n");
1379
+ response.end();
1380
+ }
1381
+ })().catch(() => {
1382
+ if (!response.destroyed) response.end("event: unavailable\ndata: {}\n\n");
1383
+ }).finally(() => {
1384
+ updating = false;
1385
+ });
1386
+ };
1387
+ transcripts.add(update);
1388
+ response.on("close", () => transcripts.delete(update));
1389
+ update();
1390
+ }
922
1391
  // src/tui/top-web.ts
1392
+ /** Interval for reconciling missed filesystem notifications in the live viewer. */
1393
+ const TOP_SNAPSHOT_RECONCILE_MS = 500;
923
1394
  /** Read-only web transport over the same snapshots as the terminal. No execution or writes. */
924
1395
  async function serveTopWeb(options) {
925
1396
  if (!options.roots.length) throw new Error("At least one --root is required");
@@ -1035,87 +1506,18 @@ async function serveTopWeb(options) {
1035
1506
  snapshots: [...snapshots.values()]
1036
1507
  });
1037
1508
  response.on("close", () => clients.delete(response));
1038
- } else if (/^\/api\/top\/agents\/\d+\/[^/]+\/[^/]+\/stream$/.test(path)) {
1039
- const [, , , , rootIndex, runId, workerId] = path.split("/").map(decodeURIComponent);
1040
- const root = roots[Number(rootIndex)];
1041
- const own = root && existsSync(resolve(root, runId, "observer.jsonl")) ? resolve(root, runId) : void 0;
1042
- const runDir = own ?? root;
1043
- const pursuit = own ? (await loadTopSnapshot(root, { runDir: own })).pursuit : root ? snapshots.get(root)?.pursuit : void 0;
1044
- const worker = () => {
1045
- const run = root ? snapshots.get(root)?.supervisors.find((run) => run.id === runId) : void 0;
1046
- const node = run?.workers.find((node) => node.id === workerId);
1047
- if (node || !run || run.id !== workerId) return node;
1048
- return {
1049
- id: run.id,
1050
- label: "root",
1051
- ...runDir && existsSync(resolve(runDir, "root-stream.jsonl")) ? { eventFile: resolve(runDir, "root-stream.jsonl") } : {},
1052
- status: run.status === "cancelled" ? "cancelled" : run.status === "done" ? "done" : run.status === "down" ? "down" : "running",
1053
- startedAt: run.startedAt,
1054
- endedAt: run.completedAt,
1055
- latencyMs: run.totals.latencyMs,
1056
- spend: run.driverSpend,
1057
- metered: {
1058
- iterations: 0,
1059
- tokensInput: 0,
1060
- tokensOutput: 0,
1061
- usd: 0,
1062
- ms: 0
1063
- },
1064
- liveTail: run.progressTail
1065
- };
1066
- };
1067
- if (!worker()) {
1068
- response.writeHead(404).end();
1069
- return;
1070
- }
1071
- let history = await transcriptHistory(worker(), runDir, pursuit?.nodes.find((node) => node.runId === runId && node.id === workerId));
1072
- response.writeHead(200, {
1073
- "Content-Type": "text/event-stream",
1074
- "X-Accel-Buffering": "no"
1075
- });
1076
- response.flushHeaders();
1077
- if (request.method === "HEAD") {
1078
- response.end();
1079
- return;
1080
- }
1081
- const generation = Date.now();
1082
- response.write(`event: reset\ndata: ${JSON.stringify({ generation })}\n\n`);
1083
- const seen = /* @__PURE__ */ new Set();
1084
- let lastSeq = 0;
1085
- const update = () => {
1086
- const node = worker();
1087
- if (!node || response.writableLength > 1048576) {
1088
- response.destroy();
1089
- return;
1090
- }
1091
- const events = (history ?? transcriptTail(node)).flatMap((row) => {
1092
- const key = createHash("sha256").update(JSON.stringify(row)).digest("hex");
1093
- if (seen.has(key)) return [];
1094
- seen.add(key);
1095
- if (seen.size > 2e3) seen.delete(seen.values().next().value);
1096
- return [{
1097
- ...row,
1098
- seq: ++lastSeq
1099
- }];
1100
- });
1101
- history = void 0;
1102
- const alive = node.status === "running";
1103
- response.write(`event: rows\ndata: ${JSON.stringify({
1104
- generation,
1105
- events,
1106
- lastSeq,
1107
- alive,
1108
- window: "recorded-tail"
1109
- })}\n\n`);
1110
- if (!alive) {
1111
- response.write("event: end\ndata: {}\n\n");
1112
- response.end();
1113
- }
1114
- };
1115
- transcripts.add(update);
1116
- response.on("close", () => transcripts.delete(update));
1117
- update();
1118
- } else if (path === "/api/top") {
1509
+ } else if (/^\/api\/top\/agents\/\d+\/[^/]+\/[^/]+(?:\/stream)?$/.test(path)) await serveTopAgent({
1510
+ request,
1511
+ response,
1512
+ path,
1513
+ base,
1514
+ roots,
1515
+ snapshots,
1516
+ transcripts,
1517
+ source: options.source,
1518
+ readSessions: options.readSessions
1519
+ });
1520
+ else if (path === "/api/top") {
1119
1521
  response.writeHead(200, { "Content-Type": "application/json" });
1120
1522
  response.end(JSON.stringify({
1121
1523
  sequence,
@@ -1230,6 +1632,6 @@ async function loadRunsRoot(root) {
1230
1632
  loaded: supervisors.length
1231
1633
  };
1232
1634
  }
1233
- export { numberValue as a, totalSpend as c, loadTopSnapshot as i, serveTopWeb as n, parseSpend as o, aggregateSnapshot as r, parseTime as s, runTopWeb as t };
1635
+ export { topAgentMetadata as _, buildSupervisorView as a, numberValue as c, topSnapshot as d, totalSpend as f, readTopAgentInspection as g, readTopAgentHistory as h, aggregateSnapshot as i, parseSpend as l, harnessSessionRows as m, runTopWeb as n, isSpawnEvent as o, createTopAgentStream as p, serveTopWeb as r, loadTopSnapshot as s, TOP_SNAPSHOT_RECONCILE_MS as t, parseTime as u, topAgentWorker as v };
1234
1636
 
1235
- //# sourceMappingURL=top-web-DK6lTMHG.js.map
1637
+ //# sourceMappingURL=top-web-DRfER2jW.js.map