@tangle-network/sandbox-ui 2.0.21 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +23 -0
  2. package/dist/{record-CnxPRyxC.js → AgentTree-CJRVpgPq.js} +196 -83
  3. package/dist/ResearchReport-CSNpZ-pj.js +2063 -0
  4. package/dist/ResearchReport-CmFYqNVY.d.ts +36 -0
  5. package/dist/{WorkflowGraph-CADReIDl.js → WorkflowGraph-B8cRtVaw.js} +2 -2
  6. package/dist/{chat-BU39pb2j.js → chat-BrlLa4rg.js} +2 -2
  7. package/dist/chat.d.ts +1 -1
  8. package/dist/chat.js +1 -1
  9. package/dist/globals.css +5837 -419
  10. package/dist/hooks.d.ts +2 -2
  11. package/dist/hooks.js +2 -2
  12. package/dist/{index-Due7tY0w.d.ts → index-5zOVKgDT.d.ts} +2 -2
  13. package/dist/{index-DxMX-DlX.d.ts → index-YU_b9xCK.d.ts} +3 -3
  14. package/dist/{index-1qlc9-S2.d.ts → index-gXcuwPOX.d.ts} +5 -6
  15. package/dist/index.d.ts +5 -5
  16. package/dist/index.js +7 -6
  17. package/dist/record/ResearchReport.d.ts +2 -0
  18. package/dist/record/ResearchReport.js +1 -0
  19. package/dist/record-Ct_MZeZC.js +47 -0
  20. package/dist/record.d.ts +33 -0
  21. package/dist/record.js +270 -0
  22. package/dist/report-viewer.js +554 -0
  23. package/dist/run/live.js +14 -33
  24. package/dist/run/record.d.ts +2 -2
  25. package/dist/run/record.js +3 -2
  26. package/dist/run.d.ts +3 -3
  27. package/dist/run.js +5 -4
  28. package/dist/runtime-viewer/{AgentGraphCanvas-B74GN1o6-DC3EH_ss.js → AgentGraphCanvas-CcBWMidO-DIW8tof6.js} +1366 -1348
  29. package/dist/runtime-viewer/{latest-events-iiWwpIck-BTK0vSlR.js → latest-events-BfRc-7l9-QhJD89rn.js} +899 -748
  30. package/dist/runtime-viewer/sandbox-ui-CUj4Q1P_.css +2 -0
  31. package/dist/styles.css +5838 -420
  32. package/dist/tailwind.css +5677 -5
  33. package/dist/tokens.css +7 -1
  34. package/dist/{trace-workspace-DkakKRLV.js → trace-workspace-BiJbv9WQ.js} +2 -2
  35. package/dist/use-follow-tail-Ht7fZGQQ.js +1 -0
  36. package/dist/workflows.js +1 -1
  37. package/dist/workspace-viewer.js +8785 -11045
  38. package/package.json +30 -12
  39. package/dist/runtime-viewer/sandbox-ui-z5RGk327.css +0 -2
  40. package/dist/use-follow-tail-Ckx5ZSV2.js +0 -1
@@ -0,0 +1,2063 @@
1
+ import { a as fmt, c as modelIdentity, d as recordFlowTrace, f as roleOf, h as utcTime, i as eventSource, m as toolKey, n as Conversation, o as indexRecord, p as textOf, r as eventMatches, s as interval, t as AgentTree, u as ms } from "./AgentTree-CJRVpgPq.js";
2
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@tangle-network/ui/primitives";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
+ import { createContext, memo, useCallback, useContext, useEffect, useId, useMemo, useRef, useState } from "react";
5
+ import { FigureView, FlowWaterfall } from "@tangle-network/charts/react";
6
+ import { OUTCOME_ORDER, timeSeries } from "@tangle-network/charts";
7
+ import { runStatus, statusMeta } from "@tangle-network/ui/run/status-meta";
8
+ import Markdown from "react-markdown";
9
+ import remarkGfm from "remark-gfm";
10
+ import remarkMath from "remark-math";
11
+ import rehypeKatex from "rehype-katex";
12
+ import { parseReportOptions, reportToLatex } from "@drewstone/agent-record/report";
13
+ // src/record/StructuredContent.tsx
14
+ /** Decode display wrappers only. Original text remains available separately. */
15
+ function displayValue(text) {
16
+ try {
17
+ return JSON.parse(text);
18
+ } catch {
19
+ return text;
20
+ }
21
+ }
22
+ function MessageText({ text, resolveHref }) {
23
+ return /* @__PURE__ */ jsx("div", {
24
+ className: "activity-prose",
25
+ children: /* @__PURE__ */ jsx(Markdown, {
26
+ skipHtml: true,
27
+ remarkPlugins: [remarkGfm],
28
+ components: {
29
+ a: ({ href, children }) => {
30
+ const target = /^https?:\/\//i.test(href ?? "") ? href : resolveHref?.(href ?? "");
31
+ return target && (/^https?:\/\//i.test(target) || /^\/(?!\/)/.test(target)) ? /* @__PURE__ */ jsx("a", {
32
+ href: target,
33
+ target: "_blank",
34
+ rel: "noreferrer",
35
+ children
36
+ }) : /* @__PURE__ */ jsx("span", { children });
37
+ },
38
+ img: ({ alt }) => /* @__PURE__ */ jsx("span", { children: alt || "Image omitted" }),
39
+ table: ({ children }) => /* @__PURE__ */ jsx("div", {
40
+ className: "rr-table-scroll",
41
+ children: /* @__PURE__ */ jsx("table", { children })
42
+ })
43
+ },
44
+ children: text
45
+ })
46
+ });
47
+ }
48
+ function Value({ value, depth = 0, field }) {
49
+ const [expanded, setExpanded] = useState(false);
50
+ if (value === null || value === void 0) return /* @__PURE__ */ jsx("span", {
51
+ className: "small",
52
+ children: "Not supplied"
53
+ });
54
+ if (typeof value === "string") {
55
+ if (field && /^(command|cmd|code|script|stdout|stderr)$/i.test(field)) return /* @__PURE__ */ jsx("pre", {
56
+ className: "activity-code",
57
+ children: /* @__PURE__ */ jsx("code", { children: value })
58
+ });
59
+ const decoded = depth < 3 ? displayValue(value) : value;
60
+ return typeof decoded === "string" ? /* @__PURE__ */ jsx(MessageText, { text: value }) : /* @__PURE__ */ jsx(Value, {
61
+ value: decoded,
62
+ depth: depth + 1
63
+ });
64
+ }
65
+ if (typeof value !== "object") return /* @__PURE__ */ jsx("span", { children: String(value) });
66
+ if (Array.isArray(value)) {
67
+ const shown = expanded ? value : value.slice(0, 12);
68
+ return /* @__PURE__ */ jsxs("div", {
69
+ className: "structured-items",
70
+ children: [shown.map((item, i) => /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Value, {
71
+ value: item,
72
+ depth: depth + 1
73
+ }) }, i)), value.length > shown.length && /* @__PURE__ */ jsxs("button", {
74
+ className: "ui-button",
75
+ onClick: () => setExpanded(true),
76
+ children: [
77
+ "Show all ",
78
+ value.length,
79
+ " items"
80
+ ]
81
+ })]
82
+ });
83
+ }
84
+ const data = value;
85
+ if (data.type === "text" && typeof data.text === "string") return /* @__PURE__ */ jsx(Value, {
86
+ value: data.text,
87
+ depth: depth + 1
88
+ });
89
+ const entries = Object.entries(data);
90
+ const shown = expanded ? entries : entries.slice(0, 16);
91
+ if (depth > 4) return /* @__PURE__ */ jsxs("details", { children: [/* @__PURE__ */ jsx("summary", { children: "Nested data" }), /* @__PURE__ */ jsx("pre", { children: JSON.stringify(value, null, 2) })] });
92
+ return /* @__PURE__ */ jsxs("dl", {
93
+ className: "structured-fields",
94
+ children: [shown.map(([key, item]) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("dt", { children: key.replace(/([a-z])([A-Z])/g, "$1 $2").replaceAll("_", " ") }), /* @__PURE__ */ jsx("dd", { children: /* @__PURE__ */ jsx(Value, {
95
+ value: item,
96
+ depth: depth + 1,
97
+ field: key
98
+ }) })] }, key)), entries.length > shown.length && /* @__PURE__ */ jsxs("button", {
99
+ className: "ui-button",
100
+ onClick: () => setExpanded(true),
101
+ children: [
102
+ "Show all ",
103
+ entries.length,
104
+ " fields"
105
+ ]
106
+ })]
107
+ });
108
+ }
109
+ function StructuredContent({ text, rawLabel = "Raw data" }) {
110
+ const value = displayValue(text);
111
+ return /* @__PURE__ */ jsxs("div", {
112
+ className: "structured-content",
113
+ children: [/* @__PURE__ */ jsx(Value, { value }), typeof value !== "string" && /* @__PURE__ */ jsxs("details", {
114
+ className: "raw-data",
115
+ children: [/* @__PURE__ */ jsx("summary", { children: rawLabel }), /* @__PURE__ */ jsx("pre", { children: text })]
116
+ })]
117
+ });
118
+ }
119
+ // src/record/RecordUsage.tsx
120
+ const categories = [
121
+ "coordination",
122
+ "compute",
123
+ "computation",
124
+ "verification",
125
+ "literature",
126
+ "writing",
127
+ "setup",
128
+ "infrastructure",
129
+ "waiting",
130
+ "reasoning",
131
+ "lifecycle",
132
+ "other"
133
+ ];
134
+ const channels = [
135
+ "input",
136
+ "output",
137
+ "cacheRead",
138
+ "cacheWrite"
139
+ ];
140
+ const channelLabels = {
141
+ input: "Input",
142
+ output: "Output",
143
+ cacheRead: "Cache read",
144
+ cacheWrite: "Cache write"
145
+ };
146
+ function RecordUsage({ index, cutoff, inspect, navigate, actor, metric, axis }) {
147
+ const [hidden, setHidden] = useState(() => /* @__PURE__ */ new Set());
148
+ const visible = useMemo(() => channels.filter((channel) => !hidden.has(channel)), [hidden]);
149
+ const measured = useMemo(() => {
150
+ const points = [];
151
+ const totals = {
152
+ input: 0,
153
+ output: 0,
154
+ cacheRead: 0,
155
+ cacheWrite: 0
156
+ };
157
+ const counts = {
158
+ input: 0,
159
+ output: 0,
160
+ cacheRead: 0,
161
+ cacheWrite: 0
162
+ };
163
+ let incomplete = 0, ambiguous = 0, invalidTiming = 0;
164
+ const chronological = index.byActor.get(actor) ?? [];
165
+ const order = index.recordedOrder;
166
+ const events = axis === "order" ? [...chronological].sort((a, b) => (order.get(a.id) ?? 0) - (order.get(b.id) ?? 0)) : chronological;
167
+ for (const event of events) {
168
+ if (ms(event.at) > cutoff) continue;
169
+ if (metric === "tool-time") {
170
+ if (event.detail.toolCallId === void 0) continue;
171
+ const calls = index.calls.get(toolKey(event.node, event.detail.toolCallId)) ?? [];
172
+ if (calls.length !== 1 || index.results.get(toolKey(event.node, event.detail.toolCallId))?.length !== 1) {
173
+ ambiguous++;
174
+ continue;
175
+ }
176
+ const call = calls[0].event;
177
+ if (ms(call.at) > cutoff || ms(event.at) < ms(call.at)) {
178
+ invalidTiming++;
179
+ continue;
180
+ }
181
+ points.push({
182
+ event,
183
+ at: ms(event.at),
184
+ values: {},
185
+ elapsed: (ms(event.at) - ms(call.at)) / 1e3
186
+ });
187
+ continue;
188
+ }
189
+ const usage = event.detail.usage;
190
+ if (!usage) continue;
191
+ const scoped = event.detail.usageScope !== void 0;
192
+ if (metric !== "cumulative" && scoped) continue;
193
+ if (channels.some((channel) => usage[channel] === void 0)) incomplete++;
194
+ const values = {};
195
+ for (const channel of channels) {
196
+ const value = usage[channel];
197
+ if (value === void 0) continue;
198
+ if (!scoped) {
199
+ totals[channel] += value;
200
+ counts[channel]++;
201
+ }
202
+ values[channel] = metric === "cumulative" ? scoped ? value : totals[channel] : value;
203
+ }
204
+ if (Object.keys(values).length) points.push({
205
+ event,
206
+ at: ms(event.at),
207
+ values,
208
+ scoped
209
+ });
210
+ }
211
+ return {
212
+ points,
213
+ totals,
214
+ counts,
215
+ incomplete,
216
+ ambiguous,
217
+ invalidTiming
218
+ };
219
+ }, [
220
+ index,
221
+ cutoff,
222
+ actor,
223
+ metric,
224
+ axis
225
+ ]);
226
+ const { points, totals, counts } = measured;
227
+ const plotted = useMemo(() => {
228
+ const sourceEvents = [];
229
+ const position = new Map(points.map((point, i) => [point, i + 1]));
230
+ const series = (id, label, colorIndex, scoped, channel) => ({
231
+ id,
232
+ label,
233
+ colorIndex,
234
+ secondary: scoped,
235
+ points: points.filter((point) => !!point.scoped === scoped).map((point) => {
236
+ const y = metric === "tool-time" ? point.elapsed : point.values[channel] ?? null;
237
+ if (y !== null) sourceEvents.push(point.event);
238
+ return {
239
+ x: axis === "time" ? point.at : position.get(point),
240
+ y,
241
+ ...point.event.detail.isError ? { marker: "triangle" } : {},
242
+ annotation: [
243
+ point.event.label,
244
+ point.event.detail.isError ? "The tool reported an error." : "",
245
+ scoped ? "Metered window or execution-to-date; not a per-response measurement." : ""
246
+ ].filter(Boolean).join(" ") || void 0
247
+ };
248
+ })
249
+ });
250
+ return {
251
+ rows: metric === "tool-time" ? [series("tool-return", "Observed call → result interval", 0, false)] : visible.flatMap((channel) => [series(channel, channelLabels[channel], channels.indexOf(channel), false, channel), ...points.some((point) => point.scoped) ? [series(`scoped:${channel}`, `${channelLabels[channel]} · metered windows`, channels.indexOf(channel), true, channel)] : []]),
252
+ sourceEvents
253
+ };
254
+ }, [
255
+ points,
256
+ visible,
257
+ metric,
258
+ axis
259
+ ]);
260
+ const figure = useMemo(() => (width) => timeSeries(plotted.rows, {
261
+ id: "record-usage",
262
+ width,
263
+ selectable: true,
264
+ x: {
265
+ label: axis === "time" ? "Recorded elapsed time" : "Recorded event order",
266
+ domain: axis === "time" ? [index.start, Math.max(index.start + 1, cutoff)] : [1, Math.max(2, points.length)]
267
+ },
268
+ y: {
269
+ label: metric === "tool-time" ? "Observed call → result interval" : metric === "cumulative" ? "Cumulative measured tokens" : "Measured tokens per response",
270
+ unit: metric === "tool-time" ? "seconds" : "tokens",
271
+ domain: [0, Math.max(1, ...plotted.rows.flatMap((row) => row.points.map((point) => point.y ?? 0)))]
272
+ },
273
+ formatX: axis === "time" ? (value) => interval(value - index.start) : String,
274
+ formatY: metric === "tool-time" ? (value) => value.toFixed(3) : fmt
275
+ }), [
276
+ plotted,
277
+ axis,
278
+ metric,
279
+ index.start,
280
+ cutoff,
281
+ points.length
282
+ ]);
283
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
284
+ /* @__PURE__ */ jsx("div", {
285
+ "data-tokens": true,
286
+ onKeyDown: (event) => {
287
+ if ((event.key === "ArrowLeft" || event.key === "ArrowRight") && event.target instanceof Element && event.target.closest("svg")) {
288
+ event.preventDefault();
289
+ navigate(event.key === "ArrowLeft" ? -1 : 1);
290
+ }
291
+ },
292
+ children: points.length ? metric !== "tool-time" && !visible.length ? /* @__PURE__ */ jsx("p", {
293
+ className: "chat-empty",
294
+ children: "All token channels are hidden. Select a channel to show its recorded values."
295
+ }) : /* @__PURE__ */ jsx(FigureView, {
296
+ figure,
297
+ onPointSelect: (point) => {
298
+ const event = plotted.sourceEvents[point];
299
+ if (event) inspect(event, true);
300
+ }
301
+ }) : /* @__PURE__ */ jsx("p", {
302
+ className: "chat-empty",
303
+ children: metric === "tool-time" ? "No matched tool timing at this time" : "No measured usage at this time"
304
+ })
305
+ }),
306
+ metric !== "tool-time" && /* @__PURE__ */ jsxs("div", {
307
+ className: "usage-legend",
308
+ children: [channels.map((channel) => /* @__PURE__ */ jsx("button", {
309
+ type: "button",
310
+ className: "legend-toggle",
311
+ "aria-pressed": !hidden.has(channel),
312
+ title: hidden.has(channel) ? `Show ${channelLabels[channel]}` : `Hide ${channelLabels[channel]}`,
313
+ onClick: () => setHidden((current) => {
314
+ const next = new Set(current);
315
+ if (next.has(channel)) next.delete(channel);
316
+ else next.add(channel);
317
+ return next;
318
+ }),
319
+ children: channelLabels[channel]
320
+ }, channel)), points.some((point) => point.scoped) && /* @__PURE__ */ jsx("span", {
321
+ className: "scoped-key",
322
+ children: "metered windows · execution-to-date"
323
+ })]
324
+ }),
325
+ /* @__PURE__ */ jsx("p", {
326
+ className: "small",
327
+ "data-token-caption": true,
328
+ children: metric === "tool-time" ? `Observed tool return time, not model latency.${measured.ambiguous || measured.invalidTiming ? " Unmatched, ambiguous and out-of-order results are omitted." : ""}` : `${channels.map((channel) => `${channelLabels[channel]} ${counts[channel] ? fmt(totals[channel]) : "unknown"}`).join(" · ")}.${measured.incomplete ? " Some responses lack counters, so these totals are lower bounds." : ""} Context repeated across responses is counted each time; tokens are not billed cost.`
329
+ })
330
+ ] });
331
+ }
332
+ // src/record/useDownload.ts
333
+ function useDownload() {
334
+ const pending = useRef(/* @__PURE__ */ new Map());
335
+ useEffect(() => {
336
+ const urls = pending.current;
337
+ return () => {
338
+ for (const [url, timer] of urls) {
339
+ window.clearTimeout(timer);
340
+ URL.revokeObjectURL(url);
341
+ }
342
+ urls.clear();
343
+ };
344
+ }, []);
345
+ return (content, name, type) => {
346
+ const url = URL.createObjectURL(new Blob([content], { type }));
347
+ const link = document.createElement("a");
348
+ link.href = url;
349
+ link.download = name.replace(/[^a-zA-Z0-9._-]/g, "_");
350
+ link.click();
351
+ pending.current.set(url, window.setTimeout(() => {
352
+ URL.revokeObjectURL(url);
353
+ pending.current.delete(url);
354
+ }, 1e3));
355
+ };
356
+ }
357
+ // src/record/AgentRecord.tsx
358
+ function Select$1({ label, value, onChange, children, field }) {
359
+ return /* @__PURE__ */ jsxs("label", {
360
+ className: "ui-field ar-select",
361
+ children: [/* @__PURE__ */ jsx("span", {
362
+ className: "ui-label",
363
+ children: label
364
+ }), /* @__PURE__ */ jsx("select", {
365
+ value,
366
+ onChange: (event) => onChange(event.target.value),
367
+ [`data-${field}`]: "",
368
+ children
369
+ })]
370
+ });
371
+ }
372
+ /** Normalized retained data only. Producers retain parsing and publication authority. */
373
+ function AgentRecord({ records, selection, defaultSelection, onSelectionChange, theme = "auto", className = "", behaviors }) {
374
+ const [own, setOwn] = useState(defaultSelection);
375
+ const chosen = selection ?? own;
376
+ const record = records.find((item) => item.runId === chosen?.runId) ?? records[0];
377
+ const change = useCallback((next) => {
378
+ if (selection === void 0) setOwn(next);
379
+ onSelectionChange?.(next);
380
+ }, [selection, onSelectionChange]);
381
+ return /* @__PURE__ */ jsx("div", {
382
+ className: `agent-record ${className}`,
383
+ "data-theme": theme === "auto" ? void 0 : theme,
384
+ children: record ? /* @__PURE__ */ jsx(RecordView, {
385
+ records,
386
+ record,
387
+ selection: chosen?.runId === record.runId ? chosen : { runId: record.runId },
388
+ onChange: change,
389
+ behaviors
390
+ }, record.runId) : /* @__PURE__ */ jsx("p", {
391
+ className: "chat-empty",
392
+ children: "No records supplied."
393
+ })
394
+ });
395
+ }
396
+ /** One retained record keeps its selection across timeline, transcript, source and measured usage. */
397
+ function RecordView({ records, record, selection, onChange, behaviors }) {
398
+ const index = useMemo(() => indexRecord(record), [record]);
399
+ const trace = useMemo(() => recordFlowTrace(record), [record]);
400
+ const [category, setCategory] = useState("all"), [search, setSearch] = useState("");
401
+ const [metric, setMetric] = useState("cumulative"), [axis, setAxis] = useState("time");
402
+ const download = useDownload();
403
+ const explicit = selection.eventId ? index.byEvent.get(selection.eventId) : void 0;
404
+ const requested = selection.nodeId ? index.canonical(selection.nodeId) : void 0;
405
+ const actor = explicit ? index.canonical(explicit.node) : requested && index.nodes.has(requested) ? requested : index.actors[0]?.id ?? "";
406
+ const event = explicit ?? index.byActor.get(actor)?.[0], node = index.nodes.get(actor);
407
+ const selectedAt = selection.at ? ms(selection.at) : index.end;
408
+ const cutoff = Number.isFinite(selectedAt) ? Math.max(index.start, Math.min(index.end, selectedAt)) : index.end;
409
+ const query = search.trim().toLowerCase(), view = selection.view ?? "chat";
410
+ const visible = useMemo(() => index.events.filter((item) => eventMatches(item, index, query, category)), [
411
+ index,
412
+ query,
413
+ category
414
+ ]);
415
+ const options = [.../* @__PURE__ */ new Set([...categories, ...record.events.map((item) => item.category)])].filter((item) => item !== "all" && item !== "findings");
416
+ const marks = (behaviors?.find((item) => item.runId === record.runId)?.verdicts ?? []).filter((item) => item.verdict === "yes").flatMap((item) => (item.evidence ?? []).flatMap((evidence) => {
417
+ const event = index.byEvent.get(evidence.eventId);
418
+ return event ? [{
419
+ ...item,
420
+ event,
421
+ quote: evidence.quote
422
+ }] : [];
423
+ }));
424
+ const update = useCallback((patch) => onChange({
425
+ ...selection,
426
+ runId: record.runId,
427
+ nodeId: actor,
428
+ eventId: event?.id,
429
+ ...patch
430
+ }), [
431
+ selection,
432
+ record.runId,
433
+ actor,
434
+ event?.id,
435
+ onChange
436
+ ]);
437
+ const inspect = (item, source = false) => onChange({
438
+ runId: record.runId,
439
+ nodeId: index.canonical(item.node),
440
+ eventId: item.id,
441
+ at: item.at,
442
+ view: source ? "source" : "chat"
443
+ });
444
+ const selectActor = (id) => {
445
+ const first = index.byActor.get(id)?.find((item) => item.detail.role || item.detail.publicText || item.detail.publicToolCalls?.length) ?? index.byActor.get(id)?.[0];
446
+ onChange({
447
+ runId: record.runId,
448
+ nodeId: id,
449
+ eventId: first?.id,
450
+ view: "chat",
451
+ at: first && ms(first.at) > cutoff ? first.at : selection.at
452
+ });
453
+ };
454
+ const selectSpan = (span) => {
455
+ const item = index.byEvent.get(typeof span.meta?.eventId === "string" ? span.meta.eventId : span.id ?? "");
456
+ if (item) inspect(item);
457
+ else if (span.id !== void 0 && index.nodes.has(span.id)) selectActor(span.id);
458
+ };
459
+ const navigate = (direction) => {
460
+ if (!visible.length) return;
461
+ const at = visible.findIndex((item) => item.id === event?.id);
462
+ inspect(visible[at < 0 ? direction > 0 ? 0 : visible.length - 1 : (at + direction + visible.length) % visible.length]);
463
+ };
464
+ const position = visible.findIndex((item) => item.id === event?.id);
465
+ return /* @__PURE__ */ jsxs("div", {
466
+ className: "ar-view",
467
+ children: [
468
+ /* @__PURE__ */ jsxs("div", {
469
+ className: "controls",
470
+ children: [
471
+ records.length > 1 && /* @__PURE__ */ jsx(Select$1, {
472
+ label: "Run",
473
+ field: "run",
474
+ value: record.runId,
475
+ onChange: (runId) => onChange({ runId }),
476
+ children: records.map((item) => /* @__PURE__ */ jsx("option", {
477
+ value: item.runId,
478
+ children: item.title
479
+ }, item.runId))
480
+ }),
481
+ /* @__PURE__ */ jsxs(Select$1, {
482
+ label: "Activity type",
483
+ field: "category",
484
+ value: category,
485
+ onChange: setCategory,
486
+ children: [
487
+ /* @__PURE__ */ jsx("option", {
488
+ value: "all",
489
+ children: "All activity"
490
+ }),
491
+ /* @__PURE__ */ jsx("option", {
492
+ value: "findings",
493
+ children: "Recorded findings"
494
+ }),
495
+ options.map((item) => /* @__PURE__ */ jsx("option", {
496
+ value: item,
497
+ children: item
498
+ }, item))
499
+ ]
500
+ }),
501
+ /* @__PURE__ */ jsxs("label", {
502
+ className: "ui-field",
503
+ children: [/* @__PURE__ */ jsx("span", {
504
+ className: "ui-label",
505
+ children: "Search all agents"
506
+ }), /* @__PURE__ */ jsx("input", {
507
+ "data-search": true,
508
+ type: "search",
509
+ value: search,
510
+ onChange: (event) => setSearch(event.target.value),
511
+ placeholder: "Message, tool, agent…"
512
+ })]
513
+ })
514
+ ]
515
+ }),
516
+ /* @__PURE__ */ jsxs("details", {
517
+ className: "activity-replay",
518
+ open: true,
519
+ children: [
520
+ /* @__PURE__ */ jsx("summary", { children: "Timeline and replay" }),
521
+ /* @__PURE__ */ jsx(FlowWaterfall, {
522
+ trace,
523
+ live: false,
524
+ label: "Recorded activity",
525
+ defaultView: "agents",
526
+ selectedId: actor,
527
+ position: selection.at ? cutoff - index.start : null,
528
+ onTimeChange: (time) => {
529
+ const at = time === null ? void 0 : new Date(index.start + time).toISOString();
530
+ if (at !== selection.at) update({ at });
531
+ },
532
+ onSelect: selectSpan,
533
+ query: search,
534
+ onQueryChange: setSearch,
535
+ matchSpan: (span) => {
536
+ const item = index.byEvent.get(typeof span.meta?.eventId === "string" ? span.meta.eventId : span.id ?? "");
537
+ return item ? eventMatches(item, index, query, category) : !query && category === "all";
538
+ },
539
+ markers: marks.map((mark) => ({
540
+ at: ms(mark.event.at) - index.start,
541
+ label: `${mark.behavior} · ${Math.round(mark.confidence * 100)}%`
542
+ }))
543
+ }),
544
+ marks.length > 0 && /* @__PURE__ */ jsx("ul", {
545
+ "aria-label": "Recorded behavior verdicts",
546
+ children: marks.map((mark, i) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs("button", {
547
+ type: "button",
548
+ onClick: () => inspect(mark.event, true),
549
+ children: [
550
+ mark.behavior,
551
+ " · ",
552
+ Math.round(mark.confidence * 100),
553
+ "%",
554
+ mark.quote ? ` · ${mark.quote}` : ""
555
+ ]
556
+ }) }, i))
557
+ })
558
+ ]
559
+ }),
560
+ query && /* @__PURE__ */ jsxs("section", {
561
+ className: "activity-search-results",
562
+ "aria-label": "Matching activity",
563
+ children: [
564
+ /* @__PURE__ */ jsxs("p", {
565
+ role: "status",
566
+ children: [visible.length, " matching events"]
567
+ }),
568
+ visible.slice(0, 100).map((item) => /* @__PURE__ */ jsxs("button", {
569
+ onClick: () => {
570
+ setSearch("");
571
+ inspect(item);
572
+ },
573
+ children: [
574
+ /* @__PURE__ */ jsx("span", { children: index.nodes.get(index.canonical(item.node))?.label ?? item.node }),
575
+ /* @__PURE__ */ jsx("time", { children: utcTime(item.at) }),
576
+ /* @__PURE__ */ jsx("strong", { children: item.label }),
577
+ /* @__PURE__ */ jsx("small", { children: (textOf(item) || item.detail.publicToolCalls?.map((call) => `${call.name} ${call.input}`).join(" ") || "Recorded event").replace(/\s+/g, " ").slice(0, 240) })
578
+ ]
579
+ }, item.id)),
580
+ visible.length > 100 && /* @__PURE__ */ jsx("p", {
581
+ className: "small",
582
+ children: "Showing the first 100 matches. Narrow the search to find a particular event."
583
+ }),
584
+ !visible.length && /* @__PURE__ */ jsx("p", {
585
+ className: "chat-empty",
586
+ children: "No retained activity matches. Missing captures are not searched."
587
+ })
588
+ ]
589
+ }),
590
+ /* @__PURE__ */ jsxs("div", {
591
+ className: "workspace flat-activity",
592
+ hidden: !!query,
593
+ children: [/* @__PURE__ */ jsxs("details", {
594
+ className: "topology",
595
+ children: [
596
+ /* @__PURE__ */ jsxs("summary", { children: ["Agents ", /* @__PURE__ */ jsx("span", {
597
+ "data-agent-count": true,
598
+ children: index.actors.filter((item) => item.kind !== "finding").length
599
+ })] }),
600
+ record.nodes.some((item) => item.kind === "session" && !item.agentId) && /* @__PURE__ */ jsxs("p", {
601
+ className: "small",
602
+ "data-graph-caption": true,
603
+ children: ["Not linked to an agent: ", record.nodes.filter((item) => item.kind === "session" && !item.agentId).map((item) => item.label).join(", ")]
604
+ }),
605
+ /* @__PURE__ */ jsx(AgentTree, {
606
+ index,
607
+ actor,
608
+ cutoff,
609
+ select: selectActor
610
+ })
611
+ ]
612
+ }), /* @__PURE__ */ jsxs("section", {
613
+ className: "conversation-panel",
614
+ "aria-label": "Agent record details",
615
+ children: [
616
+ /* @__PURE__ */ jsxs("div", {
617
+ className: "conversation-head",
618
+ children: [/* @__PURE__ */ jsxs("div", {
619
+ className: "agent-identity",
620
+ children: [/* @__PURE__ */ jsx("span", {
621
+ className: "agent-avatar",
622
+ "data-agent-avatar": true,
623
+ "aria-hidden": true,
624
+ children: roleOf(node).slice(0, 1).toUpperCase()
625
+ }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", {
626
+ "data-agent-title": true,
627
+ children: node?.label ?? "Messages"
628
+ }), /* @__PURE__ */ jsx("p", {
629
+ "data-agent-role": true,
630
+ children: [
631
+ roleOf(node),
632
+ modelIdentity(node, record),
633
+ statusMeta(runStatus(node?.status ?? "unknown")).label
634
+ ].filter(Boolean).join(" · ")
635
+ })] })]
636
+ }), /* @__PURE__ */ jsx(Select$1, {
637
+ label: "Agent",
638
+ field: "agent",
639
+ value: actor,
640
+ onChange: selectActor,
641
+ children: index.actors.map((item) => /* @__PURE__ */ jsxs("option", {
642
+ value: item.id,
643
+ children: [
644
+ item.label,
645
+ " · ",
646
+ roleOf(item)
647
+ ]
648
+ }, item.id))
649
+ })]
650
+ }),
651
+ /* @__PURE__ */ jsx(Capture, {
652
+ record,
653
+ index,
654
+ actor
655
+ }),
656
+ /* @__PURE__ */ jsxs(Tabs, {
657
+ value: view,
658
+ onValueChange: (view) => update({ view }),
659
+ children: [
660
+ /* @__PURE__ */ jsx(TabsList, {
661
+ "aria-label": "Agent evidence",
662
+ children: [
663
+ "chat",
664
+ "source",
665
+ "usage"
666
+ ].map((tab) => /* @__PURE__ */ jsx(TabsTrigger, {
667
+ value: tab,
668
+ "data-view": tab,
669
+ children: tab === "chat" ? "Messages" : tab === "source" ? "Event details" : "Usage"
670
+ }, tab))
671
+ }),
672
+ /* @__PURE__ */ jsx(TabsContent, {
673
+ value: "chat",
674
+ forceMount: true,
675
+ hidden: view !== "chat",
676
+ "data-panel": "chat",
677
+ children: /* @__PURE__ */ jsx(Conversation, {
678
+ index,
679
+ actor,
680
+ cutoff,
681
+ query,
682
+ category,
683
+ selected: event?.id
684
+ })
685
+ }),
686
+ /* @__PURE__ */ jsx(TabsContent, {
687
+ value: "source",
688
+ forceMount: true,
689
+ hidden: view !== "source",
690
+ "data-panel": "source",
691
+ children: /* @__PURE__ */ jsx(EventDetails, {
692
+ event,
693
+ record,
694
+ index,
695
+ cutoff
696
+ })
697
+ }),
698
+ /* @__PURE__ */ jsxs(TabsContent, {
699
+ value: "usage",
700
+ forceMount: true,
701
+ hidden: view !== "usage",
702
+ "data-panel": "usage",
703
+ children: [/* @__PURE__ */ jsxs("div", {
704
+ className: "metric-controls",
705
+ children: [/* @__PURE__ */ jsxs(Select$1, {
706
+ label: "Measure",
707
+ field: "metric",
708
+ value: metric,
709
+ onChange: (value) => setMetric(value),
710
+ children: [
711
+ /* @__PURE__ */ jsx("option", {
712
+ value: "cumulative",
713
+ children: "Cumulative tokens"
714
+ }),
715
+ /* @__PURE__ */ jsx("option", {
716
+ value: "response",
717
+ children: "Tokens per response"
718
+ }),
719
+ /* @__PURE__ */ jsx("option", {
720
+ value: "tool-time",
721
+ children: "Tool return time"
722
+ })
723
+ ]
724
+ }), /* @__PURE__ */ jsxs(Select$1, {
725
+ label: "Horizontal axis",
726
+ field: "axis",
727
+ value: axis,
728
+ onChange: (value) => setAxis(value),
729
+ children: [/* @__PURE__ */ jsx("option", {
730
+ value: "time",
731
+ children: "Elapsed time"
732
+ }), /* @__PURE__ */ jsx("option", {
733
+ value: "order",
734
+ children: "Recorded order"
735
+ })]
736
+ })]
737
+ }), /* @__PURE__ */ jsx(RecordUsage, {
738
+ index,
739
+ cutoff,
740
+ actor,
741
+ metric,
742
+ axis,
743
+ inspect,
744
+ navigate
745
+ })]
746
+ })
747
+ ]
748
+ })
749
+ ]
750
+ })]
751
+ }),
752
+ /* @__PURE__ */ jsxs("div", {
753
+ className: "navigation",
754
+ children: [
755
+ /* @__PURE__ */ jsxs(Select$1, {
756
+ label: "Jump to a moment",
757
+ field: "moment",
758
+ value: event?.id ?? "",
759
+ onChange: (id) => {
760
+ const item = index.byEvent.get(id);
761
+ if (item) inspect(item);
762
+ },
763
+ children: [!visible.some((item) => item.id === event?.id) && /* @__PURE__ */ jsx("option", {
764
+ value: event?.id ?? "",
765
+ children: event ? "Selected event is outside this filter" : "Select an event"
766
+ }), visible.map((item) => /* @__PURE__ */ jsxs("option", {
767
+ value: item.id,
768
+ children: [
769
+ utcTime(item.at),
770
+ " · ",
771
+ item.label
772
+ ]
773
+ }, item.id))]
774
+ }),
775
+ /* @__PURE__ */ jsx("button", {
776
+ className: "ui-button",
777
+ "data-prev": true,
778
+ disabled: !visible.length,
779
+ onClick: () => navigate(-1),
780
+ children: "Previous"
781
+ }),
782
+ /* @__PURE__ */ jsx("button", {
783
+ className: "ui-button",
784
+ "data-next": true,
785
+ disabled: !visible.length,
786
+ onClick: () => navigate(1),
787
+ children: "Next"
788
+ }),
789
+ /* @__PURE__ */ jsxs("span", {
790
+ "data-position": true,
791
+ children: [
792
+ position >= 0 ? position + 1 : "—",
793
+ " / ",
794
+ visible.length
795
+ ]
796
+ }),
797
+ /* @__PURE__ */ jsx("button", {
798
+ className: "download-record",
799
+ "data-download": true,
800
+ onClick: () => download(JSON.stringify(record, null, 2), record.runId + ".json", "application/json"),
801
+ children: "Download record"
802
+ })
803
+ ]
804
+ }),
805
+ /* @__PURE__ */ jsxs("details", {
806
+ className: "assignment",
807
+ children: [
808
+ /* @__PURE__ */ jsx("summary", { children: "Original assignment" }),
809
+ /* @__PURE__ */ jsx("dl", {
810
+ "data-assignment": true,
811
+ children: Object.entries(record.assignment).filter(([key]) => key !== "source").map(([key, value]) => /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("dt", { children: key.replace(/([a-z])([A-Z])/g, "$1 $2") }), /* @__PURE__ */ jsx("dd", { children: typeof value === "string" ? value : JSON.stringify(value, null, 2) })] }, key))
812
+ }),
813
+ record.assignment.source && /* @__PURE__ */ jsxs("details", {
814
+ className: "assignment-source",
815
+ children: [/* @__PURE__ */ jsx("summary", { children: "Provenance" }), /* @__PURE__ */ jsx("pre", { children: JSON.stringify(record.assignment.source, null, 2) })]
816
+ })
817
+ ]
818
+ }),
819
+ /* @__PURE__ */ jsxs("details", {
820
+ className: "coverage",
821
+ children: [/* @__PURE__ */ jsx("summary", { children: "Sources, redactions & capture gaps" }), /* @__PURE__ */ jsxs("div", {
822
+ "data-coverage": true,
823
+ children: [
824
+ record.coverage.publicContent && /* @__PURE__ */ jsx("p", { children: record.coverage.publicContent }),
825
+ record.coverage.categoryMethod && /* @__PURE__ */ jsx("p", { children: record.coverage.categoryMethod }),
826
+ record.coverage.cost && record.coverage.cost !== "Not recorded" && /* @__PURE__ */ jsxs("p", { children: ["Cost: ", record.coverage.cost] }),
827
+ record.terminal && /* @__PURE__ */ jsxs("p", { children: [
828
+ "Recorded terminal: ",
829
+ record.terminal.kind ?? "unknown",
830
+ record.terminal.reason ? ` · ${record.terminal.reason}` : ""
831
+ ] }),
832
+ /* @__PURE__ */ jsx("pre", { children: JSON.stringify({
833
+ coverage: record.coverage,
834
+ sources: record.sources
835
+ }, null, 2) })
836
+ ]
837
+ })]
838
+ })
839
+ ]
840
+ });
841
+ }
842
+ function Capture({ record, index, actor }) {
843
+ const node = index.nodes.get(actor), capture = node?.metadata && typeof node.metadata === "object" ? node.metadata : void 0;
844
+ const retained = index.byActor.get(actor)?.length ?? 0;
845
+ const note = typeof node?.captureNote === "string" ? node.captureNote : typeof capture?.captureReason === "string" ? capture.captureReason : node?.capture && node.capture.status !== "complete" ? (record.coverage?.gaps ?? []).filter((gap) => gap.nodeId === actor).map((gap) => gap.detail).join(" ") : null;
846
+ const label = capture?.captureStatus === "retained-partial" || node?.capture?.status === "lossy" ? "Partial capture" : capture?.captureStatus === "missing-source" || node?.capture?.status === "absent" || !retained ? "Conversation unavailable" : capture?.captureStatus === "retained" ? "Retained capture" : null;
847
+ return label || note || node?.assignment ? /* @__PURE__ */ jsxs("div", {
848
+ className: "agent-capture-summary",
849
+ role: "status",
850
+ children: [
851
+ label,
852
+ note && /* @__PURE__ */ jsxs("details", { children: [/* @__PURE__ */ jsx("summary", { children: "Capture details" }), /* @__PURE__ */ jsx("p", { children: note })] }),
853
+ node?.assignment && /* @__PURE__ */ jsxs("details", { children: [/* @__PURE__ */ jsx("summary", { children: "What this agent did" }), /* @__PURE__ */ jsx("p", { children: node.assignment })] })
854
+ ]
855
+ }) : null;
856
+ }
857
+ function EventDetails({ event, record, index, cutoff }) {
858
+ if (!event) return /* @__PURE__ */ jsx("p", {
859
+ className: "chat-empty",
860
+ children: "No source event selected."
861
+ });
862
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
863
+ /* @__PURE__ */ jsx("h4", {
864
+ "data-event-title": true,
865
+ children: event.label
866
+ }),
867
+ /* @__PURE__ */ jsxs("p", {
868
+ className: "small",
869
+ "data-event-meta": true,
870
+ children: [
871
+ utcTime(event.at, true),
872
+ " · ",
873
+ index.nodes.get(index.canonical(event.node))?.label ?? event.node
874
+ ]
875
+ }),
876
+ ms(event.at) > cutoff ? /* @__PURE__ */ jsx("p", { children: "This event occurs after the selected time. Advance the timeline to read it." }) : /* @__PURE__ */ jsxs(Fragment, { children: [
877
+ textOf(event) && /* @__PURE__ */ jsx(StructuredContent, { text: textOf(event) }),
878
+ event.detail.publicToolCalls?.map((call) => /* @__PURE__ */ jsxs("section", {
879
+ className: "event-tool",
880
+ children: [/* @__PURE__ */ jsx("h4", { children: call.name }), call.input === void 0 ? /* @__PURE__ */ jsx("p", {
881
+ className: "publication-note",
882
+ children: "Args not captured."
883
+ }) : /* @__PURE__ */ jsx(StructuredContent, {
884
+ text: call.input,
885
+ rawLabel: "Raw input"
886
+ })]
887
+ }, call.id)),
888
+ !textOf(event) && !event.detail.publicToolCalls?.length && /* @__PURE__ */ jsx("p", { children: event.detail.contentOmitted ?? event.detail.publicationNote ?? "No visible message or tool payload was retained for this event." }),
889
+ /* @__PURE__ */ jsxs("details", {
890
+ className: "raw-data",
891
+ children: [
892
+ /* @__PURE__ */ jsx("summary", { children: "Raw event and source" }),
893
+ /* @__PURE__ */ jsx("pre", {
894
+ "data-event-detail": true,
895
+ children: JSON.stringify(event.detail, null, 2)
896
+ }),
897
+ /* @__PURE__ */ jsx("pre", {
898
+ "data-event-source": true,
899
+ children: JSON.stringify(eventSource(event, record, index), null, 2)
900
+ })
901
+ ]
902
+ })
903
+ ] })
904
+ ] });
905
+ }
906
+ // src/record/source-search.ts
907
+ /** Render only source IDs and bytes already supplied in the selected play. */
908
+ function readSourceSearch(value, playId, documents, revision) {
909
+ if (!value || typeof value !== "object") throw new Error("Source response unavailable");
910
+ const result = value;
911
+ if (result.scopeId !== playId || typeof result.revision !== "string" || revision !== void 0 && result.revision !== revision || !Array.isArray(result.hits)) throw new Error("Source response does not match this play");
912
+ const excerpts = /* @__PURE__ */ new Map();
913
+ return {
914
+ documents: result.hits.map((hit) => {
915
+ if (!hit || typeof hit !== "object") throw new Error("Invalid source response");
916
+ const source = hit.source;
917
+ if (!source || typeof source !== "object") throw new Error("Invalid source response");
918
+ const item = source;
919
+ const document = documents.find((doc) => doc.id === item.id);
920
+ if (!document || document.sha256 !== item.contentHash || document.content !== item.text) throw new Error("Source bytes do not match this retained play");
921
+ excerpts.set(document.id, document.content);
922
+ return document;
923
+ }),
924
+ indexedAt: typeof result.indexedAt === "string" ? result.indexedAt : null,
925
+ revision: result.revision,
926
+ excerpts
927
+ };
928
+ }
929
+ // src/record/KnowledgeBrowser.tsx
930
+ /** Only exact retained paths resolve. This never reads the host filesystem. */
931
+ function resolveDocument(documents, href, from) {
932
+ if (/^[a-z][a-z\d+.-]*:/i.test(href) || href.startsWith("//")) return void 0;
933
+ let path = href.split("#")[0] ?? "";
934
+ try {
935
+ path = decodeURIComponent(path);
936
+ } catch {
937
+ return;
938
+ }
939
+ if (!path) return documents.find((item) => item.path === from);
940
+ const alias = (item, value) => item.sourcePath === value || Array.isArray(item.aliases) && item.aliases.includes(value);
941
+ const unique = (matches) => matches.length === 1 ? matches[0] : void 0;
942
+ if (!from || path.startsWith("/")) {
943
+ const exact = unique(documents.filter((item) => item.path === path || alias(item, path)));
944
+ if (exact) return exact;
945
+ }
946
+ const segments = (path.startsWith("/") ? path : (from?.split("/").slice(0, -1).join("/") ?? "") + "/" + path).split("/");
947
+ const normalized = [];
948
+ for (const segment of segments) if (segment === "..") normalized.pop();
949
+ else if (segment && segment !== ".") normalized.push(segment);
950
+ return unique(documents.filter((item) => item.path.replace(/^\//, "") === normalized.join("/"))) ?? unique(documents.filter((item) => alias(item, path)));
951
+ }
952
+ function snippet(content, words) {
953
+ const lower = content.toLowerCase();
954
+ const positions = words.map((word) => lower.indexOf(word)).filter((index) => index >= 0);
955
+ const start = positions.length ? Math.max(0, Math.min(...positions) - 45) : 0;
956
+ return (start ? "…" : "") + content.slice(start, start + 160).replace(/\s+/g, " ") + (content.length > start + 160 ? "…" : "");
957
+ }
958
+ function KnowledgeBrowser({ documents, selection, onSelect, onClear, reportsOnly = false, playId, sourceSearchEndpoint }) {
959
+ const [query, setQuery] = useState("");
960
+ const [kind, setKind] = useState("all");
961
+ const [submittedQuery, setSubmittedQuery] = useState("");
962
+ const [result, setResult] = useState();
963
+ const [busy, setBusy] = useState(false);
964
+ const [error, setError] = useState("");
965
+ const request = useRef(void 0);
966
+ useEffect(() => {
967
+ request.current?.abort();
968
+ setResult(void 0);
969
+ setError("");
970
+ setBusy(false);
971
+ return () => request.current?.abort();
972
+ }, [
973
+ documents,
974
+ playId,
975
+ sourceSearchEndpoint
976
+ ]);
977
+ const index = useMemo(() => documents.map((document) => ({
978
+ document,
979
+ text: [
980
+ document.title,
981
+ document.path,
982
+ document.content
983
+ ].join("\n").toLowerCase()
984
+ })), [documents]);
985
+ const words = (result ? submittedQuery : query).toLowerCase().trim().split(/\s+/).filter(Boolean);
986
+ const selected = documents.find((document) => document.path === selection?.path);
987
+ const visible = (result ? result.documents.map((document) => ({
988
+ document,
989
+ text: document.content.toLowerCase()
990
+ })) : index).filter(({ document, text }) => (!reportsOnly || document.kind === "report") && (kind === "all" || document.kind === kind) && (sourceSearchEndpoint || words.every((word) => text.includes(word))));
991
+ async function search() {
992
+ if (!sourceSearchEndpoint || !playId || !query.trim()) return;
993
+ request.current?.abort();
994
+ const controller = new AbortController();
995
+ request.current = controller;
996
+ setBusy(true);
997
+ setError("");
998
+ setResult(void 0);
999
+ setSubmittedQuery(query.trim());
1000
+ try {
1001
+ const params = new URLSearchParams({
1002
+ play: playId,
1003
+ q: query.trim(),
1004
+ limit: "10"
1005
+ });
1006
+ const response = await fetch(sourceSearchEndpoint + "?" + params, {
1007
+ signal: controller.signal,
1008
+ credentials: "same-origin"
1009
+ });
1010
+ if (!response.ok) throw new Error("Source index unavailable");
1011
+ const next = readSourceSearch(await response.json(), playId, documents, sourceSearchEndpoint.match(/\/revisions\/([^/]+)\//)?.[1]);
1012
+ if (!controller.signal.aborted) setResult(next);
1013
+ } catch {
1014
+ if (!controller.signal.aborted) setError("Source search failed or returned text that does not match these sources.");
1015
+ } finally {
1016
+ if (!controller.signal.aborted) setBusy(false);
1017
+ }
1018
+ }
1019
+ if (selected) return /* @__PURE__ */ jsxs("section", {
1020
+ className: "research-source-reader",
1021
+ "aria-label": "Selected source",
1022
+ children: [/* @__PURE__ */ jsx("button", {
1023
+ className: "ui-button source-back",
1024
+ onClick: onClear,
1025
+ children: "← All sources"
1026
+ }), /* @__PURE__ */ jsx(DocumentReader, {
1027
+ document: selected,
1028
+ documents,
1029
+ selection,
1030
+ onSelect
1031
+ }, selected.id)]
1032
+ });
1033
+ return /* @__PURE__ */ jsxs("section", {
1034
+ className: "rr-knowledge flat-sources",
1035
+ "aria-label": "Sources",
1036
+ children: [
1037
+ /* @__PURE__ */ jsxs("form", {
1038
+ className: "rr-knowledge-controls",
1039
+ onSubmit: (event) => {
1040
+ event.preventDefault();
1041
+ search();
1042
+ },
1043
+ children: [
1044
+ /* @__PURE__ */ jsxs("label", {
1045
+ className: "ui-field",
1046
+ children: [/* @__PURE__ */ jsx("span", {
1047
+ className: "ui-label",
1048
+ children: sourceSearchEndpoint ? "Search this play’s sources" : "Search retained sources"
1049
+ }), /* @__PURE__ */ jsx("input", {
1050
+ type: "search",
1051
+ value: query,
1052
+ maxLength: 500,
1053
+ placeholder: "Question keywords, result, or source…",
1054
+ onChange: (event) => setQuery(event.target.value)
1055
+ })]
1056
+ }),
1057
+ sourceSearchEndpoint && /* @__PURE__ */ jsx("button", {
1058
+ className: "ui-button",
1059
+ disabled: busy || !query.trim(),
1060
+ children: busy ? "Searching…" : "Search"
1061
+ }),
1062
+ /* @__PURE__ */ jsxs("label", {
1063
+ className: "ui-field",
1064
+ children: [/* @__PURE__ */ jsx("span", {
1065
+ className: "ui-label",
1066
+ children: "File kind"
1067
+ }), /* @__PURE__ */ jsxs("select", {
1068
+ value: kind,
1069
+ onChange: (event) => setKind(event.target.value),
1070
+ children: [
1071
+ /* @__PURE__ */ jsx("option", {
1072
+ value: "all",
1073
+ children: "All files"
1074
+ }),
1075
+ /* @__PURE__ */ jsx("option", {
1076
+ value: "report",
1077
+ children: "Reports"
1078
+ }),
1079
+ /* @__PURE__ */ jsx("option", {
1080
+ value: "knowledge",
1081
+ children: "Research notes"
1082
+ }),
1083
+ /* @__PURE__ */ jsx("option", {
1084
+ value: "code",
1085
+ children: "Code"
1086
+ }),
1087
+ /* @__PURE__ */ jsx("option", {
1088
+ value: "data",
1089
+ children: "Data"
1090
+ })
1091
+ ]
1092
+ })]
1093
+ }),
1094
+ result && /* @__PURE__ */ jsx("button", {
1095
+ type: "button",
1096
+ className: "ui-button",
1097
+ onClick: () => {
1098
+ setResult(void 0);
1099
+ setQuery("");
1100
+ setKind("all");
1101
+ },
1102
+ children: "Browse all"
1103
+ })
1104
+ ]
1105
+ }),
1106
+ (busy || result) && /* @__PURE__ */ jsx("p", {
1107
+ className: "small",
1108
+ role: "status",
1109
+ children: busy ? "Searching…" : result?.indexedAt ? `Indexed ${result.indexedAt}` : "Index time unknown"
1110
+ }),
1111
+ error && /* @__PURE__ */ jsx("p", {
1112
+ role: "alert",
1113
+ className: "chat-empty",
1114
+ children: error
1115
+ }),
1116
+ !busy && !error && /* @__PURE__ */ jsx("nav", {
1117
+ className: "source-results",
1118
+ "aria-label": "Retained documents",
1119
+ children: visible.map(({ document }) => /* @__PURE__ */ jsxs("button", {
1120
+ type: "button",
1121
+ onClick: () => {
1122
+ const found = words.map((word) => document.content.toLowerCase().indexOf(word)).filter((index) => index >= 0);
1123
+ onSelect({
1124
+ path: document.path,
1125
+ ...result && found.length ? { line: document.content.slice(0, Math.min(...found)).split("\n").length } : {}
1126
+ });
1127
+ },
1128
+ children: [
1129
+ /* @__PURE__ */ jsx("span", {
1130
+ className: "source-kind",
1131
+ children: document.kind
1132
+ }),
1133
+ /* @__PURE__ */ jsx("strong", { children: document.title }),
1134
+ /* @__PURE__ */ jsx("small", { children: document.path }),
1135
+ words.length > 0 && /* @__PURE__ */ jsx("span", {
1136
+ className: "rr-search-excerpt",
1137
+ children: snippet(document.content, words)
1138
+ })
1139
+ ]
1140
+ }, document.id))
1141
+ }),
1142
+ !busy && !error && !visible.length && /* @__PURE__ */ jsx("p", {
1143
+ className: "chat-empty",
1144
+ children: "No matching sources. Only retained files are searched."
1145
+ })
1146
+ ]
1147
+ });
1148
+ }
1149
+ function DocumentReader({ document, documents, selection, onSelect }) {
1150
+ const [source, setSource] = useState(document.kind === "code" || document.kind === "data");
1151
+ const reader = useRef(null);
1152
+ const download = useDownload();
1153
+ const requestedLine = selection?.line;
1154
+ const anchor = selection?.anchor;
1155
+ useEffect(() => {
1156
+ if (requestedLine && source) reader.current?.querySelector(`[data-line="${requestedLine}"]`)?.scrollIntoView({ block: "center" });
1157
+ if (anchor && !source) {
1158
+ let decoded = anchor;
1159
+ try {
1160
+ decoded = decodeURIComponent(anchor);
1161
+ } catch {}
1162
+ Array.from(reader.current?.querySelectorAll("h1,h2,h3,h4,h5,h6,[id]") ?? []).find((node) => node.id === decoded || node.textContent?.toLowerCase().replace(/[^\p{L}\p{N}\s-]/gu, "").replace(/\s+/g, "-") === decoded)?.scrollIntoView({ block: "start" });
1163
+ }
1164
+ }, [selection, source]);
1165
+ return /* @__PURE__ */ jsxs("article", {
1166
+ className: "rr-document",
1167
+ children: [
1168
+ /* @__PURE__ */ jsxs("header", {
1169
+ className: "rr-document-header",
1170
+ children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h3", { children: document.title }), /* @__PURE__ */ jsx("p", {
1171
+ className: "rr-document-path",
1172
+ children: document.path
1173
+ })] }), /* @__PURE__ */ jsxs("div", {
1174
+ className: "rr-document-actions",
1175
+ children: [/* @__PURE__ */ jsx("button", {
1176
+ className: "ui-button",
1177
+ type: "button",
1178
+ "aria-pressed": source,
1179
+ onClick: () => setSource(!source),
1180
+ children: source ? "Read document" : requestedLine ? "View cited line" : "View source"
1181
+ }), /* @__PURE__ */ jsx("button", {
1182
+ className: "ui-button",
1183
+ type: "button",
1184
+ onClick: () => download(document.content, document.path.split("/").pop() || "document.txt", "text/plain;charset=utf-8"),
1185
+ children: "Download original"
1186
+ })]
1187
+ })]
1188
+ }),
1189
+ document.sha256 && /* @__PURE__ */ jsxs("details", {
1190
+ className: "rr-document-provenance",
1191
+ children: [
1192
+ /* @__PURE__ */ jsx("summary", { children: "Source fingerprint" }),
1193
+ /* @__PURE__ */ jsxs("code", { children: ["SHA-256 ", document.sha256] }),
1194
+ /* @__PURE__ */ jsx("p", { children: "Supplied with the report; not checked against the archive." })
1195
+ ]
1196
+ }),
1197
+ requestedLine && /* @__PURE__ */ jsx("p", {
1198
+ className: "rr-meta",
1199
+ children: requestedLine > document.content.split("\n").length ? `Referenced line ${requestedLine} is outside this document.` : `Cited line ${requestedLine}${source ? " · source view" : ""}`
1200
+ }),
1201
+ /* @__PURE__ */ jsx("div", {
1202
+ className: "rr-document-content",
1203
+ ref: reader,
1204
+ children: source ? /* @__PURE__ */ jsx("pre", {
1205
+ className: "rr-document-source",
1206
+ children: /* @__PURE__ */ jsx("code", { children: document.content.split("\n").map((line, i) => /* @__PURE__ */ jsxs("span", {
1207
+ "data-line": i + 1,
1208
+ "data-highlight": i + 1 === requestedLine || void 0,
1209
+ children: [/* @__PURE__ */ jsx("span", {
1210
+ "aria-hidden": "true",
1211
+ children: i + 1
1212
+ }), line || "\n"]
1213
+ }, i)) })
1214
+ }) : /* @__PURE__ */ jsx(ResearchMarkdown, {
1215
+ document,
1216
+ documents,
1217
+ onSelect
1218
+ })
1219
+ })
1220
+ ]
1221
+ });
1222
+ }
1223
+ const ResearchMarkdown = memo(function ResearchMarkdown({ document, documents, onSelect }) {
1224
+ return /* @__PURE__ */ jsx("div", {
1225
+ className: "rr-markdown",
1226
+ children: /* @__PURE__ */ jsx(Markdown, {
1227
+ skipHtml: true,
1228
+ remarkPlugins: [remarkGfm, [remarkMath, { singleDollarTextMath: false }]],
1229
+ rehypePlugins: [[rehypeKatex, {
1230
+ output: "mathml",
1231
+ trust: false,
1232
+ strict: "warn",
1233
+ maxExpand: 1e3,
1234
+ maxSize: 20
1235
+ }]],
1236
+ urlTransform: (url) => url,
1237
+ components: {
1238
+ a: ({ href = "", children }) => {
1239
+ const target = resolveDocument(documents, href, document.path);
1240
+ if (target) return /* @__PURE__ */ jsx("button", {
1241
+ type: "button",
1242
+ className: "rr-inline-link",
1243
+ onClick: () => onSelect({
1244
+ path: target.path,
1245
+ anchor: href.split("#")[1]
1246
+ }),
1247
+ children
1248
+ });
1249
+ if (/^https?:\/\/[^\s]+$/i.test(href)) return /* @__PURE__ */ jsx("a", {
1250
+ href,
1251
+ target: "_blank",
1252
+ rel: "noopener noreferrer",
1253
+ children
1254
+ });
1255
+ return /* @__PURE__ */ jsx("span", {
1256
+ title: href ? `Source not included: ${href}` : void 0,
1257
+ children
1258
+ });
1259
+ },
1260
+ img: ({ alt, src }) => /* @__PURE__ */ jsxs("span", {
1261
+ className: "rr-media-reference",
1262
+ children: [alt || "Image", src ? ` (${src})` : ""]
1263
+ }),
1264
+ table: ({ children }) => /* @__PURE__ */ jsx("div", {
1265
+ className: "rr-table-scroll",
1266
+ children: /* @__PURE__ */ jsx("table", { children })
1267
+ })
1268
+ },
1269
+ children: document.content
1270
+ })
1271
+ });
1272
+ });
1273
+ // src/record/OutcomeBar.tsx
1274
+ const WORD = {
1275
+ ok: "ok",
1276
+ quota: "quota",
1277
+ lost: "lost",
1278
+ "rate-limit": "rate limit",
1279
+ oom: "OOM",
1280
+ refused: "refused",
1281
+ aborted: "aborted",
1282
+ other: "other"
1283
+ };
1284
+ const STATE = {
1285
+ ok: "ok",
1286
+ quota: "failed",
1287
+ lost: "failed",
1288
+ "rate-limit": "failed",
1289
+ oom: "failed",
1290
+ refused: "failed",
1291
+ aborted: "other",
1292
+ other: "other"
1293
+ };
1294
+ const COLOR = {
1295
+ ok: "var(--ar-c-ok)",
1296
+ failed: "var(--ar-c-fail)",
1297
+ other: "var(--ar-c-neutral)"
1298
+ };
1299
+ function OutcomeLegend({ outcomes }) {
1300
+ return /* @__PURE__ */ jsx("ul", {
1301
+ className: "outcome-legend",
1302
+ "aria-label": "Attempt outcomes",
1303
+ children: [
1304
+ "ok",
1305
+ "failed",
1306
+ "other"
1307
+ ].filter((state) => outcomes.some((outcome) => STATE[outcome] === state)).map((state) => /* @__PURE__ */ jsxs("li", { children: [/* @__PURE__ */ jsx("i", { style: { background: COLOR[state] } }), state] }, state))
1308
+ });
1309
+ }
1310
+ /** Recorded agent-hours share the report's axis; absent hours remain unknown. */
1311
+ function OutcomeBar({ row, max }) {
1312
+ const by = row.hoursByOutcome, total = Object.values(by ?? {}).reduce((sum, value) => sum + value, 0);
1313
+ if (!total) return /* @__PURE__ */ jsx("span", {
1314
+ className: "faint",
1315
+ title: "attempts not recorded",
1316
+ children: "—"
1317
+ });
1318
+ const parts = OUTCOME_ORDER.filter((outcome) => (by?.[outcome] ?? 0) > 0);
1319
+ const label = (outcome) => `${WORD[outcome]} ${by[outcome].toFixed(2)} h${row.triesByOutcome?.[outcome] !== void 0 ? ` · ${row.triesByOutcome[outcome]} tries` : ""}`;
1320
+ return /* @__PURE__ */ jsxs("span", {
1321
+ className: "outcome-bar",
1322
+ title: parts.map(label).join("\n"),
1323
+ children: [/* @__PURE__ */ jsx("span", {
1324
+ className: "outcome-track",
1325
+ style: { width: `${Math.max(2, total / max * 100)}%` },
1326
+ children: parts.map((outcome) => /* @__PURE__ */ jsx("i", {
1327
+ "data-outcome": outcome,
1328
+ title: label(outcome),
1329
+ style: {
1330
+ flexGrow: by[outcome],
1331
+ background: COLOR[STATE[outcome] ?? "other"]
1332
+ }
1333
+ }, outcome))
1334
+ }), /* @__PURE__ */ jsxs("span", {
1335
+ className: "outcome-total num",
1336
+ children: [total.toFixed(1), " h"]
1337
+ })]
1338
+ });
1339
+ }
1340
+ // src/record/ResearchReport.tsx
1341
+ const DocumentContext = createContext({
1342
+ documents: [],
1343
+ open: () => {}
1344
+ });
1345
+ function ResearchReport({ report, theme = "auto", defaultPlayId, onPlayChange, defaultView, onViewChange, defaultActivitySelection, onActivityChange, defaultDocumentSelection, onDocumentChange, sourceSearchEndpoint, figures, className = "" }) {
1346
+ sourceSearchEndpoint = parseReportOptions({ sourceSearchEndpoint }).sourceSearchEndpoint;
1347
+ const [selected, setSelected] = useState(defaultDocumentSelection?.playId ?? defaultPlayId ?? report.plays[0]?.id);
1348
+ const [query, setQuery] = useState("");
1349
+ const download = useDownload();
1350
+ const plays = report.plays.filter((play) => [play.title, play.id].join(" ").toLowerCase().includes(query.trim().toLowerCase()));
1351
+ const play = report.plays.find((item) => item.id === selected) ?? report.plays[0];
1352
+ function choose(id) {
1353
+ setSelected(id);
1354
+ onPlayChange?.(id);
1355
+ }
1356
+ return /* @__PURE__ */ jsxs("article", {
1357
+ className: "agent-record research-report research-workspace " + className,
1358
+ "data-theme": theme,
1359
+ children: [
1360
+ /* @__PURE__ */ jsxs("aside", {
1361
+ className: "research-rail",
1362
+ children: [
1363
+ /* @__PURE__ */ jsx("h1", { children: report.title }),
1364
+ /* @__PURE__ */ jsxs("label", {
1365
+ className: "ui-field",
1366
+ children: [/* @__PURE__ */ jsx("span", {
1367
+ className: "ui-label",
1368
+ children: "Find a play"
1369
+ }), /* @__PURE__ */ jsx("input", {
1370
+ type: "search",
1371
+ value: query,
1372
+ onChange: (event) => setQuery(event.target.value),
1373
+ placeholder: "Name…"
1374
+ })]
1375
+ }),
1376
+ /* @__PURE__ */ jsxs("nav", {
1377
+ className: "research-play-list",
1378
+ "aria-label": "Research plays",
1379
+ children: [plays.map((item) => /* @__PURE__ */ jsxs("button", {
1380
+ "aria-current": item.id === play?.id ? "page" : void 0,
1381
+ onClick: () => choose(item.id),
1382
+ children: [/* @__PURE__ */ jsx("span", { children: item.title }), /* @__PURE__ */ jsxs("small", { children: [
1383
+ item.claims.length,
1384
+ " results · ",
1385
+ item.documents.length,
1386
+ " sources"
1387
+ ] })]
1388
+ }, item.id)), !plays.length && /* @__PURE__ */ jsx("p", {
1389
+ className: "small",
1390
+ children: "No matching play."
1391
+ })]
1392
+ }),
1393
+ /* @__PURE__ */ jsxs("details", {
1394
+ className: "research-info",
1395
+ children: [
1396
+ /* @__PURE__ */ jsx("summary", { children: "Report summary and exports" }),
1397
+ /* @__PURE__ */ jsx("p", {
1398
+ className: "small",
1399
+ children: report.summary
1400
+ }),
1401
+ /* @__PURE__ */ jsxs("p", {
1402
+ className: "small",
1403
+ children: ["Authored ", utcTime(report.generatedAt, true)]
1404
+ }),
1405
+ report.freshness && /* @__PURE__ */ jsx("p", {
1406
+ className: "small",
1407
+ children: report.freshness.message
1408
+ }),
1409
+ /* @__PURE__ */ jsxs("p", {
1410
+ className: "small",
1411
+ children: [
1412
+ "Assessed by ",
1413
+ report.assessmentBy ?? "the report author",
1414
+ "; assessment labels are judgments, not independent verification."
1415
+ ]
1416
+ }),
1417
+ report.limitations.length > 0 && /* @__PURE__ */ jsx("ul", { children: report.limitations.map((item, i) => /* @__PURE__ */ jsx("li", { children: item }, i)) }),
1418
+ report.questionCoverage.length > 0 && /* @__PURE__ */ jsx(Questions, {
1419
+ questions: report.questionCoverage,
1420
+ inspect: () => {},
1421
+ printOnly: false
1422
+ }),
1423
+ /* @__PURE__ */ jsxs("div", {
1424
+ className: "research-exports",
1425
+ children: [
1426
+ /* @__PURE__ */ jsx("button", {
1427
+ className: "ui-button",
1428
+ onClick: () => download(reportToLatex(report), report.id + ".tex", "application/x-tex"),
1429
+ children: "Export LaTeX"
1430
+ }),
1431
+ /* @__PURE__ */ jsx("button", {
1432
+ className: "ui-button",
1433
+ onClick: () => download(JSON.stringify(report, null, 2), report.id + ".json", "application/json"),
1434
+ children: "Download data"
1435
+ }),
1436
+ /* @__PURE__ */ jsx("button", {
1437
+ className: "ui-button",
1438
+ onClick: () => window.print(),
1439
+ children: "Print results"
1440
+ })
1441
+ ]
1442
+ })
1443
+ ]
1444
+ })
1445
+ ]
1446
+ }),
1447
+ play ? /* @__PURE__ */ jsx(PlayReport, {
1448
+ play,
1449
+ report,
1450
+ theme,
1451
+ initialView: defaultView,
1452
+ initialActivity: defaultActivitySelection,
1453
+ onActivityChange,
1454
+ initialDocument: defaultDocumentSelection?.playId === play.id ? defaultDocumentSelection : void 0,
1455
+ onDocumentChange,
1456
+ onViewChange,
1457
+ sourceSearchEndpoint,
1458
+ figures
1459
+ }, play.id) : /* @__PURE__ */ jsx("p", {
1460
+ className: "chat-empty",
1461
+ children: "No plays were included."
1462
+ }),
1463
+ /* @__PURE__ */ jsx("div", {
1464
+ className: "rr-print",
1465
+ children: report.plays.map((item) => /* @__PURE__ */ jsx(PlayReport, {
1466
+ play: item,
1467
+ report,
1468
+ theme,
1469
+ printOnly: true
1470
+ }, item.id))
1471
+ })
1472
+ ]
1473
+ });
1474
+ }
1475
+ function PlayReport({ play, report, theme, printOnly = false, initialDocument, initialView, initialActivity, onActivityChange, onDocumentChange, onViewChange, sourceSearchEndpoint, figures }) {
1476
+ const [view, setView] = useState(initialDocument ? "sources" : initialView ?? "results");
1477
+ const [selection, setSelection] = useState(initialActivity);
1478
+ const [documentSelection, setDocumentSelection] = useState(initialDocument);
1479
+ const uid = useId();
1480
+ const download = useDownload();
1481
+ const anchor = (id) => printOnly ? void 0 : id;
1482
+ function show(next) {
1483
+ if (next === "sources") setDocumentSelection(void 0);
1484
+ setView(next);
1485
+ onViewChange?.(next);
1486
+ }
1487
+ function inspect(eventId) {
1488
+ if (!play.record?.events.find((item) => item.id === eventId) || !play.record) return;
1489
+ setSelection({
1490
+ runId: play.record.runId,
1491
+ eventId,
1492
+ view: "source"
1493
+ });
1494
+ show("activity");
1495
+ onActivityChange?.(play.id, {
1496
+ runId: play.record.runId,
1497
+ eventId,
1498
+ view: "source"
1499
+ });
1500
+ }
1501
+ function openDocument(next) {
1502
+ setDocumentSelection(next);
1503
+ setView("sources");
1504
+ onDocumentChange?.({
1505
+ playId: play.id,
1506
+ ...next
1507
+ });
1508
+ }
1509
+ return /* @__PURE__ */ jsx(DocumentContext.Provider, {
1510
+ value: {
1511
+ documents: play.documents,
1512
+ open: openDocument
1513
+ },
1514
+ children: /* @__PURE__ */ jsxs("section", {
1515
+ className: "research-main",
1516
+ "aria-labelledby": uid,
1517
+ children: [
1518
+ /* @__PURE__ */ jsxs("header", {
1519
+ className: "research-heading",
1520
+ children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h2", {
1521
+ id: uid,
1522
+ children: play.title
1523
+ }), /* @__PURE__ */ jsxs("p", {
1524
+ className: "small",
1525
+ children: [
1526
+ play.updatedAt ? `Updated ${utcTime(play.updatedAt, true)}` : "Update time unknown",
1527
+ " · ",
1528
+ play.status ?? "State unknown",
1529
+ play.href && /* @__PURE__ */ jsxs(Fragment, { children: [" · ", /* @__PURE__ */ jsx("a", {
1530
+ href: play.href,
1531
+ children: "Play page"
1532
+ })] })
1533
+ ]
1534
+ })] }), !printOnly && /* @__PURE__ */ jsx("button", {
1535
+ className: "ui-button",
1536
+ onClick: () => download(reportToLatex(report, play.id), play.id + ".tex", "application/x-tex"),
1537
+ children: "Export"
1538
+ })]
1539
+ }),
1540
+ !printOnly && /* @__PURE__ */ jsx("nav", {
1541
+ className: "research-sections",
1542
+ "aria-label": "Play sections",
1543
+ children: [
1544
+ "results",
1545
+ "activity",
1546
+ "sources"
1547
+ ].map((section) => /* @__PURE__ */ jsxs("button", {
1548
+ "aria-current": view === section ? "page" : void 0,
1549
+ onClick: () => show(section),
1550
+ children: [section[0].toUpperCase() + section.slice(1), section === "sources" ? ` · ${play.documents.length}` : ""]
1551
+ }, section))
1552
+ }),
1553
+ (printOnly || view === "results") && /* @__PURE__ */ jsxs("div", {
1554
+ className: "research-results",
1555
+ children: [
1556
+ play.verdict ? /* @__PURE__ */ jsxs("section", {
1557
+ className: "rr-section rr-lead-verdict",
1558
+ id: anchor("verdict"),
1559
+ "data-section": "verdict",
1560
+ "aria-label": "Verdict",
1561
+ children: [
1562
+ /* @__PURE__ */ jsx("h3", { children: "Verdict" }),
1563
+ play.verdict.status && /* @__PURE__ */ jsx("p", {
1564
+ className: "rr-assessment",
1565
+ "data-assessment": play.verdict.status,
1566
+ children: play.verdict.status.replace(/-/g, " ")
1567
+ }),
1568
+ /* @__PURE__ */ jsx("p", {
1569
+ className: "research-summary",
1570
+ children: play.verdict.sentence
1571
+ }),
1572
+ /* @__PURE__ */ jsx(Sources, {
1573
+ sources: play.verdict.evidence,
1574
+ inspect,
1575
+ printOnly,
1576
+ inline: true
1577
+ })
1578
+ ]
1579
+ }) : /* @__PURE__ */ jsx("p", {
1580
+ className: "research-summary",
1581
+ children: play.summary
1582
+ }),
1583
+ /* @__PURE__ */ jsx("div", {
1584
+ className: "research-result-list",
1585
+ children: play.claims.map((claim) => /* @__PURE__ */ jsxs("article", {
1586
+ className: "research-result",
1587
+ children: [
1588
+ /* @__PURE__ */ jsx("p", {
1589
+ className: "rr-assessment",
1590
+ "data-assessment": claim.status,
1591
+ children: claim.status[0].toUpperCase() + claim.status.slice(1)
1592
+ }),
1593
+ /* @__PURE__ */ jsx("h3", { children: typeof claim.title === "string" ? claim.title : claim.statement }),
1594
+ typeof claim.title === "string" && /* @__PURE__ */ jsx("p", { children: claim.statement }),
1595
+ claim.method && /* @__PURE__ */ jsx("p", {
1596
+ className: "small",
1597
+ children: claim.method
1598
+ }),
1599
+ claim.limitations.length > 0 && /* @__PURE__ */ jsx("ul", {
1600
+ className: "rr-limitations",
1601
+ children: claim.limitations.map((item, i) => /* @__PURE__ */ jsx("li", { children: item }, i))
1602
+ }),
1603
+ claim.evidence.length > 0 ? /* @__PURE__ */ jsx(Sources, {
1604
+ sources: claim.evidence,
1605
+ inspect,
1606
+ printOnly
1607
+ }) : /* @__PURE__ */ jsx("p", {
1608
+ className: "small",
1609
+ children: "Supporting sources not supplied."
1610
+ })
1611
+ ]
1612
+ }, claim.id))
1613
+ }),
1614
+ !play.claims.length && !play.questionCoverage.length && /* @__PURE__ */ jsx("p", {
1615
+ className: "chat-empty",
1616
+ children: "No assessed results supplied."
1617
+ }),
1618
+ play.questionCoverage.length > 0 && /* @__PURE__ */ jsx(Questions, {
1619
+ questions: play.questionCoverage,
1620
+ inspect,
1621
+ printOnly,
1622
+ open: !play.claims.length,
1623
+ id: anchor("questions")
1624
+ }),
1625
+ play.sections?.map((section) => /* @__PURE__ */ jsxs("section", {
1626
+ className: "rr-section",
1627
+ id: anchor(section.id),
1628
+ "data-section": section.id,
1629
+ "aria-label": section.title,
1630
+ children: [
1631
+ /* @__PURE__ */ jsx("h3", { children: section.title }),
1632
+ section.summary && /* @__PURE__ */ jsx("p", { children: section.summary }),
1633
+ !printOnly && figures?.[section.id],
1634
+ play.metrics.some((metric) => metric.section === section.id) && /* @__PURE__ */ jsx("dl", {
1635
+ className: "rr-metrics rr-fact-grid",
1636
+ children: play.metrics.filter((metric) => metric.section === section.id).map((metric) => /* @__PURE__ */ jsx(Fact, {
1637
+ metric,
1638
+ inspect,
1639
+ printOnly
1640
+ }, metric.id))
1641
+ }),
1642
+ play.tables?.filter((table) => table.section === section.id).map((table) => /* @__PURE__ */ jsx(Table, {
1643
+ table,
1644
+ inspect,
1645
+ printOnly
1646
+ }, table.id))
1647
+ ]
1648
+ }, section.id)),
1649
+ play.runs && play.runs.length > 0 && /* @__PURE__ */ jsx(Runs, {
1650
+ runs: play.runs,
1651
+ inspect,
1652
+ printOnly,
1653
+ id: anchor("runs")
1654
+ }),
1655
+ play.rules && /* @__PURE__ */ jsx(Rules, {
1656
+ rules: play.rules,
1657
+ inspect,
1658
+ printOnly,
1659
+ id: anchor("anomalies")
1660
+ }),
1661
+ play.unknowns && /* @__PURE__ */ jsx(Unknowns, {
1662
+ unknowns: play.unknowns,
1663
+ id: anchor("unknowns")
1664
+ }),
1665
+ play.observations.length > 0 && /* @__PURE__ */ jsxs("details", {
1666
+ className: "research-observations",
1667
+ open: printOnly || void 0,
1668
+ children: [/* @__PURE__ */ jsx("summary", { children: "Checks and next steps" }), play.observations.map((item) => /* @__PURE__ */ jsxs("article", { children: [
1669
+ /* @__PURE__ */ jsx("h3", { children: item.title }),
1670
+ /* @__PURE__ */ jsx("p", { children: item.body }),
1671
+ item.evidence.length > 0 && /* @__PURE__ */ jsx(Sources, {
1672
+ sources: item.evidence,
1673
+ inspect,
1674
+ printOnly
1675
+ })
1676
+ ] }, item.id))]
1677
+ }),
1678
+ /* @__PURE__ */ jsxs("details", {
1679
+ className: "research-measurements",
1680
+ open: printOnly || void 0,
1681
+ children: [
1682
+ /* @__PURE__ */ jsx("summary", { children: "Measurements and coverage" }),
1683
+ play.metrics.some((metric) => !metric.section) && /* @__PURE__ */ jsx("dl", {
1684
+ className: "rr-metrics",
1685
+ "aria-label": "Recorded measurements",
1686
+ children: play.metrics.filter((metric) => !metric.section).map((metric) => /* @__PURE__ */ jsx(Fact, {
1687
+ metric,
1688
+ inspect,
1689
+ printOnly
1690
+ }, metric.id))
1691
+ }),
1692
+ play.limitations.length > 0 && /* @__PURE__ */ jsx("ul", { children: play.limitations.map((item, i) => /* @__PURE__ */ jsx("li", { children: item }, i)) }),
1693
+ !play.record && /* @__PURE__ */ jsx("p", { children: "No event record was supplied for this play. Activity and topology are unavailable." }),
1694
+ play.sources.length > 0 && /* @__PURE__ */ jsx(Sources, {
1695
+ sources: play.sources,
1696
+ inspect,
1697
+ printOnly
1698
+ })
1699
+ ]
1700
+ })
1701
+ ]
1702
+ }),
1703
+ !printOnly && view === "sources" && /* @__PURE__ */ jsx(KnowledgeBrowser, {
1704
+ documents: play.documents,
1705
+ selection: documentSelection,
1706
+ onSelect: openDocument,
1707
+ onClear: () => {
1708
+ setDocumentSelection(void 0);
1709
+ show("sources");
1710
+ },
1711
+ playId: play.id,
1712
+ sourceSearchEndpoint
1713
+ }),
1714
+ !printOnly && view === "activity" && (play.record ? /* @__PURE__ */ jsx(AgentRecord, {
1715
+ records: [play.record],
1716
+ theme,
1717
+ selection,
1718
+ onSelectionChange: (next) => {
1719
+ setSelection(next);
1720
+ onActivityChange?.(play.id, next);
1721
+ }
1722
+ }) : /* @__PURE__ */ jsx("p", {
1723
+ className: "chat-empty",
1724
+ children: "No event record was supplied for this play. Its activity and topology are unavailable."
1725
+ }))
1726
+ ]
1727
+ })
1728
+ });
1729
+ }
1730
+ function Questions({ questions, inspect, printOnly, open = false, id }) {
1731
+ return /* @__PURE__ */ jsxs("details", {
1732
+ className: "rr-questions",
1733
+ id,
1734
+ open: printOnly || open || void 0,
1735
+ children: [/* @__PURE__ */ jsx("summary", { children: "Questions and answers" }), /* @__PURE__ */ jsx("dl", { children: questions.map((item) => /* @__PURE__ */ jsxs("div", {
1736
+ className: "rr-question",
1737
+ children: [
1738
+ /* @__PURE__ */ jsx("dt", { children: item.question }),
1739
+ /* @__PURE__ */ jsx("dd", {
1740
+ className: "rr-meta",
1741
+ children: item.status.replace(/_/g, " ")
1742
+ }),
1743
+ item.answer ? /* @__PURE__ */ jsx("dd", { children: item.answer }) : item.status !== "observed" && /* @__PURE__ */ jsx("dd", {
1744
+ className: "rr-unknown",
1745
+ children: "Unknown"
1746
+ }),
1747
+ item.why && /* @__PURE__ */ jsxs("dd", {
1748
+ className: "rr-meta",
1749
+ children: [item.status === "observed" ? "Not known: " : "Why: ", item.why]
1750
+ }),
1751
+ item.record && /* @__PURE__ */ jsxs("dd", {
1752
+ className: "rr-meta",
1753
+ children: ["Would be answered by: ", item.record]
1754
+ }),
1755
+ item.evidence.length > 0 && /* @__PURE__ */ jsx("dd", { children: /* @__PURE__ */ jsx(Sources, {
1756
+ sources: item.evidence,
1757
+ inspect,
1758
+ printOnly,
1759
+ inline: true
1760
+ }) })
1761
+ ]
1762
+ }, item.id)) })]
1763
+ });
1764
+ }
1765
+ function Sources({ sources, inspect, printOnly, inline = false }) {
1766
+ const documents = useContext(DocumentContext);
1767
+ if (inline && sources.every((source) => !source.excerpt && !source.eventId)) return /* @__PURE__ */ jsx("ul", {
1768
+ className: "rr-source-line",
1769
+ children: sources.map((source, i) => /* @__PURE__ */ jsxs("li", { children: [
1770
+ /* @__PURE__ */ jsx("span", { children: "Source " }),
1771
+ source.label && /* @__PURE__ */ jsxs("strong", { children: [source.label, " "] }),
1772
+ source.url && /* @__PURE__ */ jsx("a", {
1773
+ href: source.url,
1774
+ target: "_blank",
1775
+ rel: "noreferrer",
1776
+ children: source.url
1777
+ }),
1778
+ source.path && /* @__PURE__ */ jsxs("code", { children: [source.path, source.line ? ":" + source.line : ""] }),
1779
+ source.asOf ? /* @__PURE__ */ jsxs("span", { children: [" · as of ", utcTime(source.asOf, true)] }) : /* @__PURE__ */ jsx("span", { children: " · as-of time not recorded" })
1780
+ ] }, i))
1781
+ });
1782
+ return /* @__PURE__ */ jsxs("details", {
1783
+ className: "rr-sources",
1784
+ open: printOnly || void 0,
1785
+ children: [/* @__PURE__ */ jsxs("summary", { children: [
1786
+ sources.length,
1787
+ " ",
1788
+ sources.length === 1 ? "source" : "sources"
1789
+ ] }), /* @__PURE__ */ jsx("ol", { children: sources.map((source, i) => /* @__PURE__ */ jsxs("li", { children: [
1790
+ source.label && /* @__PURE__ */ jsx("strong", { children: source.label }),
1791
+ source.url && /* @__PURE__ */ jsx("a", {
1792
+ href: source.url,
1793
+ target: "_blank",
1794
+ rel: "noreferrer",
1795
+ children: source.url
1796
+ }),
1797
+ source.path && /* @__PURE__ */ jsxs("code", { children: [source.path, source.line ? ":" + source.line : ""] }),
1798
+ !printOnly && source.path && resolveDocument(documents.documents, source.path) && /* @__PURE__ */ jsx("button", {
1799
+ className: "ui-button",
1800
+ type: "button",
1801
+ onClick: () => documents.open({
1802
+ path: resolveDocument(documents.documents, source.path).path,
1803
+ line: source.line
1804
+ }),
1805
+ children: "Read retained document"
1806
+ }),
1807
+ source.sha256 && /* @__PURE__ */ jsxs("small", { children: ["SHA-256 ", /* @__PURE__ */ jsx("code", { children: source.sha256 })] }),
1808
+ source.asOf && /* @__PURE__ */ jsxs("small", { children: ["As of ", utcTime(source.asOf, true)] }),
1809
+ source.excerpt && /* @__PURE__ */ jsx("blockquote", { children: source.excerpt }),
1810
+ source.eventId && (printOnly ? /* @__PURE__ */ jsxs("code", { children: ["Event: ", source.eventId] }) : /* @__PURE__ */ jsx("button", {
1811
+ className: "ui-button",
1812
+ type: "button",
1813
+ onClick: () => inspect(source.eventId),
1814
+ children: "Open recorded event"
1815
+ }))
1816
+ ] }, i)) })]
1817
+ });
1818
+ }
1819
+ /** One fact: its value with unit, or Unknown with why and the record that would answer it, then its source. */
1820
+ function Fact({ metric, inspect, printOnly }) {
1821
+ const mark = metric.comparable === false ? "not comparable" : metric.comparable === true ? "comparable" : null;
1822
+ const note = mark && metric.note ? metric.note.replace(/^not comparable:\s*/i, "") : metric.note;
1823
+ return /* @__PURE__ */ jsxs("div", {
1824
+ "data-fact": metric.id,
1825
+ "data-unknown": metric.value === null || void 0,
1826
+ children: [
1827
+ /* @__PURE__ */ jsx("dt", { children: metric.label }),
1828
+ /* @__PURE__ */ jsxs("dd", {
1829
+ className: metric.value === null ? "rr-unknown" : void 0,
1830
+ children: [metric.value ?? "Unknown", metric.value !== null && metric.unit ? ` ${metric.unit}` : ""]
1831
+ }),
1832
+ mark && /* @__PURE__ */ jsx("small", {
1833
+ className: "rr-comparable",
1834
+ "data-comparable": String(metric.comparable),
1835
+ children: mark
1836
+ }),
1837
+ note && /* @__PURE__ */ jsx("small", { children: note }),
1838
+ metric.coverage && /* @__PURE__ */ jsx("small", { children: metric.coverage }),
1839
+ metric.value === null && metric.why && /* @__PURE__ */ jsxs("small", { children: ["Why: ", metric.why] }),
1840
+ metric.value === null && metric.record && /* @__PURE__ */ jsxs("small", { children: ["Would be answered by: ", metric.record] }),
1841
+ metric.source && /* @__PURE__ */ jsx(Sources, {
1842
+ sources: [metric.source],
1843
+ inspect,
1844
+ printOnly,
1845
+ inline: true
1846
+ })
1847
+ ]
1848
+ });
1849
+ }
1850
+ function Table({ table, inspect, printOnly }) {
1851
+ const marked = table.rows.some((row) => row.some((cell) => cell.comparable === false));
1852
+ return /* @__PURE__ */ jsxs("figure", {
1853
+ className: "rr-data-table",
1854
+ "data-table": table.id,
1855
+ children: [
1856
+ /* @__PURE__ */ jsxs("figcaption", { children: [table.title, marked && /* @__PURE__ */ jsx("span", {
1857
+ className: "small",
1858
+ children: " · * not comparable with the bar"
1859
+ })] }),
1860
+ /* @__PURE__ */ jsx("div", {
1861
+ className: "rr-table-scroll",
1862
+ children: /* @__PURE__ */ jsxs("table", { children: [/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: table.columns.map((column) => /* @__PURE__ */ jsx("th", {
1863
+ scope: "col",
1864
+ children: column
1865
+ }, column)) }) }), /* @__PURE__ */ jsx("tbody", { children: table.rows.map((row, i) => /* @__PURE__ */ jsx("tr", { children: row.map((cell, j) => /* @__PURE__ */ jsxs("td", {
1866
+ className: cell.text === null ? "rr-unknown" : void 0,
1867
+ title: cell.note,
1868
+ children: [
1869
+ cell.text === null ? "unknown" : cell.href ? /* @__PURE__ */ jsx("a", {
1870
+ href: cell.href,
1871
+ children: cell.text
1872
+ }) : cell.text,
1873
+ cell.comparable === false && /* @__PURE__ */ jsx("span", {
1874
+ className: "rr-comparable",
1875
+ "data-comparable": "false",
1876
+ children: "*"
1877
+ }),
1878
+ cell.note && /* @__PURE__ */ jsx("small", { children: cell.note })
1879
+ ]
1880
+ }, j)) }, i)) })] })
1881
+ }),
1882
+ table.source && /* @__PURE__ */ jsx(Sources, {
1883
+ sources: [table.source],
1884
+ inspect,
1885
+ printOnly,
1886
+ inline: true
1887
+ })
1888
+ ]
1889
+ });
1890
+ }
1891
+ /** Each run: its ending, agent-hours stacked by attempt outcome on one shared axis (the play ledger's bar), and its page. */
1892
+ function Runs({ runs, inspect, printOnly, id }) {
1893
+ const total = (run) => Object.values(run.hoursByOutcome ?? {}).reduce((sum, value) => sum + value, 0);
1894
+ const max = Math.max(1, ...runs.map(total));
1895
+ const present = OUTCOME_ORDER.filter((outcome) => runs.some((run) => (run.hoursByOutcome?.[outcome] ?? 0) > 0));
1896
+ return /* @__PURE__ */ jsxs("section", {
1897
+ className: "rr-section",
1898
+ id,
1899
+ "data-section": "runs",
1900
+ "aria-label": "Runs",
1901
+ children: [
1902
+ /* @__PURE__ */ jsx("h3", { children: "Runs" }),
1903
+ present.length > 0 && /* @__PURE__ */ jsx(OutcomeLegend, { outcomes: present }),
1904
+ /* @__PURE__ */ jsx("ol", {
1905
+ className: "rr-runs",
1906
+ children: runs.map((run) => /* @__PURE__ */ jsxs("li", {
1907
+ className: "rr-run",
1908
+ "data-run": run.id,
1909
+ children: [
1910
+ /* @__PURE__ */ jsxs("p", {
1911
+ className: "rr-run-head",
1912
+ children: [
1913
+ run.href ? /* @__PURE__ */ jsx("a", {
1914
+ href: run.href,
1915
+ children: run.label
1916
+ }) : /* @__PURE__ */ jsx("strong", { children: run.label }),
1917
+ /* @__PURE__ */ jsx("span", { children: run.ending ?? "ending unknown" }),
1918
+ run.best && /* @__PURE__ */ jsxs("span", { children: ["best ", run.best] }),
1919
+ /* @__PURE__ */ jsx("span", { children: run.cost ?? "cost unknown" }),
1920
+ /* @__PURE__ */ jsx("span", { children: run.wallHours === null ? "wall time unknown" : `${run.wallHours} h wall` })
1921
+ ]
1922
+ }),
1923
+ run.hoursByOutcome && total(run) > 0 ? /* @__PURE__ */ jsx(OutcomeBar, {
1924
+ row: {
1925
+ hoursByOutcome: run.hoursByOutcome,
1926
+ triesByOutcome: run.triesByOutcome ?? null
1927
+ },
1928
+ max
1929
+ }) : /* @__PURE__ */ jsx("dl", {
1930
+ className: "rr-metrics rr-fact-grid",
1931
+ children: /* @__PURE__ */ jsx(Fact, {
1932
+ metric: run.agentHours,
1933
+ inspect,
1934
+ printOnly
1935
+ })
1936
+ }),
1937
+ run.hoursByOutcome && total(run) > 0 && run.agentHours.source && /* @__PURE__ */ jsx(Sources, {
1938
+ sources: [run.agentHours.source],
1939
+ inspect,
1940
+ printOnly,
1941
+ inline: true
1942
+ }),
1943
+ run.reason && /* @__PURE__ */ jsx("p", {
1944
+ className: "small",
1945
+ children: run.reason
1946
+ })
1947
+ ]
1948
+ }, run.id))
1949
+ })
1950
+ ]
1951
+ });
1952
+ }
1953
+ const RULE_STATE = {
1954
+ fired: "fired",
1955
+ quiet: "quiet",
1956
+ "could-not-evaluate": "could not evaluate"
1957
+ };
1958
+ /** What looks wrong: every rule with its state, and each instance it fired on with the sentence and source that say why. */
1959
+ function Rules({ rules, inspect, printOnly, id }) {
1960
+ const fired = rules.reduce((sum, rule) => sum + rule.instances.length, 0);
1961
+ return /* @__PURE__ */ jsxs("section", {
1962
+ className: "rr-section",
1963
+ id,
1964
+ "data-section": "anomalies",
1965
+ "aria-label": "Anomalies",
1966
+ children: [
1967
+ /* @__PURE__ */ jsx("h3", { children: "Anomalies" }),
1968
+ /* @__PURE__ */ jsxs("p", { children: [
1969
+ fired,
1970
+ " ",
1971
+ fired === 1 ? "anomaly" : "anomalies",
1972
+ " from ",
1973
+ rules.filter((rule) => rule.instances.length).length,
1974
+ " of ",
1975
+ rules.length,
1976
+ " rules."
1977
+ ] }),
1978
+ !rules.length && /* @__PURE__ */ jsx("p", {
1979
+ className: "chat-empty",
1980
+ children: "No rule was evaluated."
1981
+ }),
1982
+ /* @__PURE__ */ jsx("ol", {
1983
+ className: "rr-rules",
1984
+ children: rules.map((rule) => /* @__PURE__ */ jsxs("li", {
1985
+ className: "rr-rule",
1986
+ "data-rule": rule.id,
1987
+ "data-state": rule.state,
1988
+ children: [
1989
+ /* @__PURE__ */ jsxs("p", {
1990
+ className: "rr-rule-head",
1991
+ children: [
1992
+ /* @__PURE__ */ jsx("span", {
1993
+ className: "rr-assessment",
1994
+ "data-rule-state": RULE_STATE[rule.state] ? rule.state : "unrecognised",
1995
+ children: RULE_STATE[rule.state] ?? `unrecognised state: ${rule.state}`
1996
+ }),
1997
+ " ",
1998
+ /* @__PURE__ */ jsx("strong", { children: rule.question })
1999
+ ]
2000
+ }),
2001
+ /* @__PURE__ */ jsxs("p", {
2002
+ className: "rr-meta",
2003
+ children: [
2004
+ /* @__PURE__ */ jsx("code", { children: rule.id }),
2005
+ rule.threshold && /* @__PURE__ */ jsxs(Fragment, { children: [" · threshold ", rule.threshold] }),
2006
+ " · ",
2007
+ rule.instances.length,
2008
+ " fired"
2009
+ ]
2010
+ }),
2011
+ rule.instances.length > 0 && /* @__PURE__ */ jsx("ul", { children: rule.instances.map((instance, i) => /* @__PURE__ */ jsxs("li", { children: [/* @__PURE__ */ jsxs("p", { children: [instance.sentence, instance.value && /* @__PURE__ */ jsxs("span", {
2012
+ className: "rr-meta",
2013
+ children: [
2014
+ " (",
2015
+ instance.value,
2016
+ ")"
2017
+ ]
2018
+ })] }), instance.evidence.length ? /* @__PURE__ */ jsx(Sources, {
2019
+ sources: instance.evidence,
2020
+ inspect,
2021
+ printOnly,
2022
+ inline: true
2023
+ }) : /* @__PURE__ */ jsx("p", {
2024
+ className: "rr-meta",
2025
+ children: "Source not recorded."
2026
+ })] }, i)) })
2027
+ ]
2028
+ }, rule.id))
2029
+ })
2030
+ ]
2031
+ });
2032
+ }
2033
+ function Unknowns({ unknowns, id }) {
2034
+ return /* @__PURE__ */ jsxs("section", {
2035
+ className: "rr-section",
2036
+ id,
2037
+ "data-section": "unknowns",
2038
+ "aria-label": "Unknowns",
2039
+ children: [/* @__PURE__ */ jsx("h3", { children: "Unknowns" }), !unknowns.length ? /* @__PURE__ */ jsx("p", { children: "The report lists no unknown field." }) : /* @__PURE__ */ jsx("ul", {
2040
+ className: "rr-unknowns",
2041
+ children: unknowns.map((item, i) => /* @__PURE__ */ jsxs("li", {
2042
+ "data-unknown-field": item.field,
2043
+ children: [
2044
+ /* @__PURE__ */ jsx("code", { children: item.field }),
2045
+ " ",
2046
+ /* @__PURE__ */ jsx("span", {
2047
+ className: "rr-unknown",
2048
+ children: "unknown"
2049
+ }),
2050
+ /* @__PURE__ */ jsxs("p", {
2051
+ className: "rr-meta",
2052
+ children: ["Why: ", item.why]
2053
+ }),
2054
+ /* @__PURE__ */ jsxs("p", {
2055
+ className: "rr-meta",
2056
+ children: ["Would be answered by: ", item.record]
2057
+ })
2058
+ ]
2059
+ }, i))
2060
+ })]
2061
+ });
2062
+ }
2063
+ export { AgentRecord as n, ResearchReport as t };