@unigent/cli 0.1.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 (110) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +470 -0
  3. package/dist/cli.js +132 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/command.js +44 -0
  6. package/dist/command.js.map +1 -0
  7. package/dist/environment.js +20 -0
  8. package/dist/environment.js.map +1 -0
  9. package/dist/error_message.js +59 -0
  10. package/dist/error_message.js.map +1 -0
  11. package/dist/format.js +38 -0
  12. package/dist/format.js.map +1 -0
  13. package/dist/node_version.js +9 -0
  14. package/dist/node_version.js.map +1 -0
  15. package/dist/protocol.js +72 -0
  16. package/dist/protocol.js.map +1 -0
  17. package/dist/register.js +78 -0
  18. package/dist/register.js.map +1 -0
  19. package/dist/script_runtime.js +29 -0
  20. package/dist/script_runtime.js.map +1 -0
  21. package/dist/tui/app.js +453 -0
  22. package/dist/tui/app.js.map +1 -0
  23. package/dist/tui/clipboard.js +31 -0
  24. package/dist/tui/clipboard.js.map +1 -0
  25. package/dist/tui/runner.js +116 -0
  26. package/dist/tui/runner.js.map +1 -0
  27. package/dist/tui/scroll.js +33 -0
  28. package/dist/tui/scroll.js.map +1 -0
  29. package/dist/tui/store.js +99 -0
  30. package/dist/tui/store.js.map +1 -0
  31. package/dist/tui/theme.js +35 -0
  32. package/dist/tui/theme.js.map +1 -0
  33. package/dist/tui/tree.js +267 -0
  34. package/dist/tui/tree.js.map +1 -0
  35. package/dist/tui.js +63 -0
  36. package/dist/tui.js.map +1 -0
  37. package/node_modules/@unigent/core/dist/adapter_process.d.ts +25 -0
  38. package/node_modules/@unigent/core/dist/adapter_process.d.ts.map +1 -0
  39. package/node_modules/@unigent/core/dist/adapter_process.js +46 -0
  40. package/node_modules/@unigent/core/dist/adapter_process.js.map +1 -0
  41. package/node_modules/@unigent/core/dist/args.d.ts +17 -0
  42. package/node_modules/@unigent/core/dist/args.d.ts.map +1 -0
  43. package/node_modules/@unigent/core/dist/args.js +233 -0
  44. package/node_modules/@unigent/core/dist/args.js.map +1 -0
  45. package/node_modules/@unigent/core/dist/backend.d.ts +83 -0
  46. package/node_modules/@unigent/core/dist/backend.d.ts.map +1 -0
  47. package/node_modules/@unigent/core/dist/backend.js +2 -0
  48. package/node_modules/@unigent/core/dist/backend.js.map +1 -0
  49. package/node_modules/@unigent/core/dist/checkpoint.d.ts +26 -0
  50. package/node_modules/@unigent/core/dist/checkpoint.d.ts.map +1 -0
  51. package/node_modules/@unigent/core/dist/checkpoint.js +107 -0
  52. package/node_modules/@unigent/core/dist/checkpoint.js.map +1 -0
  53. package/node_modules/@unigent/core/dist/checkpoint_fingerprint.d.ts +4 -0
  54. package/node_modules/@unigent/core/dist/checkpoint_fingerprint.d.ts.map +1 -0
  55. package/node_modules/@unigent/core/dist/checkpoint_fingerprint.js +41 -0
  56. package/node_modules/@unigent/core/dist/checkpoint_fingerprint.js.map +1 -0
  57. package/node_modules/@unigent/core/dist/completion.d.ts +9 -0
  58. package/node_modules/@unigent/core/dist/completion.d.ts.map +1 -0
  59. package/node_modules/@unigent/core/dist/completion.js +4 -0
  60. package/node_modules/@unigent/core/dist/completion.js.map +1 -0
  61. package/node_modules/@unigent/core/dist/errors.d.ts +43 -0
  62. package/node_modules/@unigent/core/dist/errors.d.ts.map +1 -0
  63. package/node_modules/@unigent/core/dist/errors.js +48 -0
  64. package/node_modules/@unigent/core/dist/errors.js.map +1 -0
  65. package/node_modules/@unigent/core/dist/events.d.ts +101 -0
  66. package/node_modules/@unigent/core/dist/events.d.ts.map +1 -0
  67. package/node_modules/@unigent/core/dist/events.js +105 -0
  68. package/node_modules/@unigent/core/dist/events.js.map +1 -0
  69. package/node_modules/@unigent/core/dist/index.d.ts +19 -0
  70. package/node_modules/@unigent/core/dist/index.d.ts.map +1 -0
  71. package/node_modules/@unigent/core/dist/index.js +10 -0
  72. package/node_modules/@unigent/core/dist/index.js.map +1 -0
  73. package/node_modules/@unigent/core/dist/json_schema_validator.d.ts +8 -0
  74. package/node_modules/@unigent/core/dist/json_schema_validator.d.ts.map +1 -0
  75. package/node_modules/@unigent/core/dist/json_schema_validator.js +27 -0
  76. package/node_modules/@unigent/core/dist/json_schema_validator.js.map +1 -0
  77. package/node_modules/@unigent/core/dist/mcp.d.ts +12 -0
  78. package/node_modules/@unigent/core/dist/mcp.d.ts.map +1 -0
  79. package/node_modules/@unigent/core/dist/mcp.js +117 -0
  80. package/node_modules/@unigent/core/dist/mcp.js.map +1 -0
  81. package/node_modules/@unigent/core/dist/runtime.d.ts +109 -0
  82. package/node_modules/@unigent/core/dist/runtime.d.ts.map +1 -0
  83. package/node_modules/@unigent/core/dist/runtime.js +976 -0
  84. package/node_modules/@unigent/core/dist/runtime.js.map +1 -0
  85. package/node_modules/@unigent/core/dist/schema.d.ts +15 -0
  86. package/node_modules/@unigent/core/dist/schema.d.ts.map +1 -0
  87. package/node_modules/@unigent/core/dist/schema.js +71 -0
  88. package/node_modules/@unigent/core/dist/schema.js.map +1 -0
  89. package/node_modules/@unigent/core/dist/source_tools.d.ts +7 -0
  90. package/node_modules/@unigent/core/dist/source_tools.d.ts.map +1 -0
  91. package/node_modules/@unigent/core/dist/source_tools.js +450 -0
  92. package/node_modules/@unigent/core/dist/source_tools.js.map +1 -0
  93. package/node_modules/@unigent/core/dist/tool.d.ts +41 -0
  94. package/node_modules/@unigent/core/dist/tool.d.ts.map +1 -0
  95. package/node_modules/@unigent/core/dist/tool.js +43 -0
  96. package/node_modules/@unigent/core/dist/tool.js.map +1 -0
  97. package/node_modules/@unigent/core/dist/tools.d.ts +7 -0
  98. package/node_modules/@unigent/core/dist/tools.d.ts.map +1 -0
  99. package/node_modules/@unigent/core/dist/tools.js +3 -0
  100. package/node_modules/@unigent/core/dist/tools.js.map +1 -0
  101. package/node_modules/@unigent/core/dist/trace.d.ts +82 -0
  102. package/node_modules/@unigent/core/dist/trace.d.ts.map +1 -0
  103. package/node_modules/@unigent/core/dist/trace.js +235 -0
  104. package/node_modules/@unigent/core/dist/trace.js.map +1 -0
  105. package/node_modules/@unigent/core/dist/usage.d.ts +26 -0
  106. package/node_modules/@unigent/core/dist/usage.d.ts.map +1 -0
  107. package/node_modules/@unigent/core/dist/usage.js +47 -0
  108. package/node_modules/@unigent/core/dist/usage.js.map +1 -0
  109. package/node_modules/@unigent/core/package.json +68 -0
  110. package/package.json +68 -0
@@ -0,0 +1,453 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
2
+ import { basename } from "node:path";
3
+ import { useKeyboard, useRenderer, useSelectionHandler, useTerminalDimensions, } from "@opentui/react";
4
+ import { useEffect, useMemo, useState, useSyncExternalStore } from "react";
5
+ import { formatDuration, formatUsage } from "../format.js";
6
+ import { copyToClipboard } from "./clipboard.js";
7
+ import { NaturalScrollAcceleration } from "./scroll.js";
8
+ import { paletteFor } from "./theme.js";
9
+ import { diagnosticsForRow, environmentLabel, flattenTraceTree, focusLabel, } from "./tree.js";
10
+ const CLOCK_INTERVAL_MILLISECONDS = 250;
11
+ const COPY_NOTICE_MILLISECONDS = 1400;
12
+ const MINIMUM_WIDTH = 68;
13
+ const MINIMUM_HEIGHT = 12;
14
+ const TRACE_WIDTH_RATIO = 0.36;
15
+ const TRACE_MINIMUM_WIDTH = 27;
16
+ const ENTRY_CHARACTER_LIMIT = 8000;
17
+ const TRACE_PAGE_SIZE = 250;
18
+ const ACTIVITY_ENTRY_LIMIT = 250;
19
+ const DIAGNOSTIC_ENTRY_LIMIT = 20;
20
+ const TREE_BRANCH_LENGTH = 3;
21
+ function statusAppearance(status, palette) {
22
+ switch (status) {
23
+ case "running":
24
+ return { color: palette.accent, label: "● running" };
25
+ case "succeeded":
26
+ return { color: palette.success, label: "● complete" };
27
+ case "cancelled":
28
+ return { color: palette.warning, label: "● stopped" };
29
+ case "failed":
30
+ return { color: palette.error, label: "● failed" };
31
+ }
32
+ }
33
+ function usePalette(initialTheme) {
34
+ const renderer = useRenderer();
35
+ const [theme, setTheme] = useState(initialTheme);
36
+ const palette = useMemo(() => paletteFor(theme), [theme]);
37
+ useEffect(() => {
38
+ const synchronize = () => {
39
+ if (renderer.themeMode !== null) {
40
+ setTheme(renderer.themeMode);
41
+ }
42
+ };
43
+ renderer.on("theme_mode", synchronize);
44
+ return () => {
45
+ renderer.off("theme_mode", synchronize);
46
+ };
47
+ }, [renderer]);
48
+ useEffect(() => {
49
+ renderer.setBackgroundColor(palette.background);
50
+ }, [palette.background, renderer]);
51
+ return palette;
52
+ }
53
+ function useCurrentTime(running) {
54
+ const [now, setNow] = useState(Date.now());
55
+ useEffect(() => {
56
+ if (!running) {
57
+ return;
58
+ }
59
+ const timer = setInterval(() => setNow(Date.now()), CLOCK_INTERVAL_MILLISECONDS);
60
+ return () => clearInterval(timer);
61
+ }, [running]);
62
+ return now;
63
+ }
64
+ function useCopyNotice() {
65
+ const [copiedCharacters, setCopiedCharacters] = useState();
66
+ useSelectionHandler((selection) => {
67
+ const text = selection.getSelectedText();
68
+ if (copyToClipboard(text)) {
69
+ setCopiedCharacters(text.length);
70
+ }
71
+ });
72
+ useEffect(() => {
73
+ if (copiedCharacters === undefined) {
74
+ return;
75
+ }
76
+ const timer = setTimeout(() => setCopiedCharacters(undefined), COPY_NOTICE_MILLISECONDS);
77
+ return () => clearTimeout(timer);
78
+ }, [copiedCharacters]);
79
+ return copiedCharacters;
80
+ }
81
+ function nextSelection(rows, selectedSpanId, direction) {
82
+ const selectableRows = rows.filter((row) => row.selectable);
83
+ if (selectableRows.length === 0) {
84
+ return;
85
+ }
86
+ const selectedIndex = selectableRows.findIndex((row) => row.spanId === selectedSpanId);
87
+ const initialIndex = direction === 1 ? 0 : selectableRows.length - 1;
88
+ const nextIndex = selectedIndex < 0 ? initialIndex : selectedIndex + direction;
89
+ return selectableRows[Math.max(0, Math.min(selectableRows.length - 1, nextIndex))]?.spanId;
90
+ }
91
+ const KEYBOARD_ACTIONS = {
92
+ q: "quit",
93
+ s: "system",
94
+ escape: "clearFocus",
95
+ o: "toggleOutput",
96
+ enter: "toggleTools",
97
+ return: "toggleTools",
98
+ "[": "older",
99
+ leftbracket: "older",
100
+ "]": "newer",
101
+ rightbracket: "newer",
102
+ up: "up",
103
+ k: "up",
104
+ down: "down",
105
+ j: "down",
106
+ };
107
+ function keyboardAction(key, running) {
108
+ if (key.ctrl === true && key.name === "c") {
109
+ return "quit";
110
+ }
111
+ if (key.ctrl === true && key.name === "r") {
112
+ return running ? "abort" : undefined;
113
+ }
114
+ if (key.name === "r") {
115
+ return running ? undefined : "rerun";
116
+ }
117
+ return key.name === undefined ? undefined : KEYBOARD_ACTIONS[key.name];
118
+ }
119
+ function useAppKeyboard(bindings) {
120
+ useKeyboard((key) => {
121
+ switch (keyboardAction(key, bindings.running)) {
122
+ case "quit":
123
+ bindings.onQuit();
124
+ break;
125
+ case "abort":
126
+ bindings.onAbort();
127
+ break;
128
+ case "rerun":
129
+ bindings.onRerun();
130
+ break;
131
+ case "system":
132
+ bindings.toggleSystemPrompt();
133
+ break;
134
+ case "clearFocus":
135
+ bindings.setSelectedSpanId(undefined);
136
+ break;
137
+ case "toggleOutput":
138
+ bindings.toggleOutput();
139
+ break;
140
+ case "toggleTools":
141
+ bindings.toggleSelectedTools();
142
+ break;
143
+ case "older":
144
+ bindings.showOlderTraces();
145
+ break;
146
+ case "newer":
147
+ bindings.showNewerTraces();
148
+ break;
149
+ case "up":
150
+ bindings.setSelectedSpanId(nextSelection(bindings.rows, bindings.selectedSpanId, -1));
151
+ break;
152
+ case "down":
153
+ bindings.setSelectedSpanId(nextSelection(bindings.rows, bindings.selectedSpanId, 1));
154
+ break;
155
+ case undefined:
156
+ break;
157
+ }
158
+ });
159
+ }
160
+ function trimBlock(value) {
161
+ let text;
162
+ if (typeof value === "string") {
163
+ text = value;
164
+ }
165
+ else {
166
+ try {
167
+ text = JSON.stringify(value, null, 2);
168
+ }
169
+ catch {
170
+ text = String(value);
171
+ }
172
+ }
173
+ return text.length <= ENTRY_CHARACTER_LIMIT
174
+ ? text
175
+ : `${text.slice(0, ENTRY_CHARACTER_LIMIT)}\n… ${text.length - ENTRY_CHARACTER_LIMIT} more characters`;
176
+ }
177
+ function rowKindAppearance(row, palette) {
178
+ if (row.kind === "scope") {
179
+ return { color: palette.success, glyph: "▪" };
180
+ }
181
+ if (row.kind === "run") {
182
+ return { color: palette.accent, glyph: "◆" };
183
+ }
184
+ return { color: palette.tool, glyph: "◇" };
185
+ }
186
+ function nestedSummaryPrefix(prefix) {
187
+ if (prefix.endsWith("├─ ")) {
188
+ return `${prefix.slice(0, -TREE_BRANCH_LENGTH)}│ └─ `;
189
+ }
190
+ if (prefix.endsWith("└─ ")) {
191
+ return `${prefix.slice(0, -TREE_BRANCH_LENGTH)} └─ `;
192
+ }
193
+ return "└─ ";
194
+ }
195
+ function TraceRow(props) {
196
+ const { row, selected, palette, onSelect } = props;
197
+ const kind = rowKindAppearance(row, palette);
198
+ let outcomeGlyph = "·";
199
+ let outcomeColor = palette.muted;
200
+ if (row.outcome === "running") {
201
+ outcomeGlyph = "◌";
202
+ outcomeColor = palette.accent;
203
+ }
204
+ else if (row.outcome === "succeeded") {
205
+ outcomeGlyph = "✓";
206
+ outcomeColor = palette.success;
207
+ }
208
+ else if (row.outcome === "failed") {
209
+ outcomeGlyph = "×";
210
+ outcomeColor = palette.error;
211
+ }
212
+ else {
213
+ outcomeGlyph = "■";
214
+ outcomeColor = palette.warning;
215
+ }
216
+ return (_jsxs("box", { flexDirection: "column", paddingLeft: 1, paddingRight: 1, backgroundColor: selected ? palette.selected : palette.surface, onMouseDown: onSelect, children: [_jsxs("box", { flexDirection: "row", children: [_jsx("text", { fg: palette.accent, children: selected ? "▌ " : " " }), _jsx("text", { fg: palette.muted, children: row.prefix }), _jsx("text", { fg: kind.color, children: `${kind.glyph} ${row.name}` }), _jsx("box", { flexGrow: 1 }), _jsx("text", { fg: palette.muted, children: row.metrics.length > 0 ? `${row.metrics} ` : "" }), _jsx("text", { fg: outcomeColor, children: outcomeGlyph })] }), row.toolSummary === undefined || row.toolsExpanded ? null : (_jsx("text", { fg: palette.muted, children: ` ${nestedSummaryPrefix(row.prefix)}${row.toolSummary}` }))] }));
217
+ }
218
+ function diagnosticColor(diagnostic, palette) {
219
+ switch (diagnostic.kind) {
220
+ case "error":
221
+ return palette.error;
222
+ case "repair":
223
+ return palette.warning;
224
+ case "checkpoint":
225
+ return palette.tool;
226
+ case "annotation":
227
+ return palette.reasoning;
228
+ case "log":
229
+ return palette.success;
230
+ }
231
+ }
232
+ function SelectionDetails(props) {
233
+ if (props.row === undefined) {
234
+ return null;
235
+ }
236
+ const { row, palette } = props;
237
+ const diagnostics = diagnosticsForRow(row);
238
+ if (diagnostics.length === 0) {
239
+ return null;
240
+ }
241
+ const hidden = Math.max(0, diagnostics.length - DIAGNOSTIC_ENTRY_LIMIT);
242
+ const visible = diagnostics.slice(-DIAGNOSTIC_ENTRY_LIMIT);
243
+ return (_jsxs("box", { flexDirection: "column", paddingLeft: 1, paddingRight: 1, paddingTop: 1, paddingBottom: 1, marginBottom: 1, backgroundColor: palette.surface, children: [hidden > 0 ? _jsx("text", { fg: palette.muted, children: `${hidden} older diagnostics hidden` }) : null, visible.map((diagnostic, index) => (_jsxs("box", { flexDirection: "column", paddingTop: 1, children: [_jsx("text", { fg: diagnosticColor(diagnostic, palette), children: diagnostic.label }), _jsx("text", { fg: palette.foreground, wrapMode: "word", children: trimBlock(diagnostic.value) })] }, `${diagnostic.label}-${index}`)))] }));
244
+ }
245
+ function Entry(props) {
246
+ const { entry, palette } = props;
247
+ let header;
248
+ let color;
249
+ let body;
250
+ switch (entry.kind) {
251
+ case "system":
252
+ header = "✦ system";
253
+ color = palette.muted;
254
+ body = entry.text;
255
+ break;
256
+ case "user":
257
+ header = "▸ prompt";
258
+ color = palette.success;
259
+ body = entry.text;
260
+ break;
261
+ case "assistant":
262
+ header = "● assistant";
263
+ color = palette.accent;
264
+ body = entry.text;
265
+ break;
266
+ case "reasoning":
267
+ header = "✻ reasoning";
268
+ color = palette.reasoning;
269
+ body = entry.text;
270
+ break;
271
+ case "tool_call":
272
+ header = `⚙ ${entry.name}`;
273
+ color = palette.tool;
274
+ body = entry.input;
275
+ break;
276
+ case "tool_result":
277
+ header = entry.isError ? `× ${entry.name}` : `✓ ${entry.name}`;
278
+ color = entry.isError ? palette.error : palette.success;
279
+ body = entry.output;
280
+ break;
281
+ }
282
+ const userEntry = entry.kind === "user";
283
+ return (_jsxs("box", { flexDirection: "column", paddingLeft: 1, paddingRight: 1, marginBottom: 1, ...(userEntry ? { backgroundColor: palette.userSurface } : {}), children: [_jsx("text", { fg: color, children: header }), _jsx("text", { fg: entry.kind === "reasoning" ? palette.muted : palette.foreground, wrapMode: "word", children: trimBlock(body) })] }));
284
+ }
285
+ function OutputBlock(props) {
286
+ if (props.content.trim().length === 0) {
287
+ return null;
288
+ }
289
+ return (_jsxs("box", { flexDirection: "column", paddingLeft: 1, paddingRight: 1, marginBottom: 1, children: [_jsx("text", { fg: props.color, children: props.title }), _jsx("text", { fg: props.color, wrapMode: "word", children: trimBlock(props.content.trimEnd()) })] }));
290
+ }
291
+ function CompactFallback(props) {
292
+ return (_jsxs("box", { width: props.width, height: props.height, backgroundColor: props.palette.background, flexDirection: "column", padding: 1, children: [_jsx("text", { fg: props.palette.accent, children: "unigent" }), _jsx("text", { fg: props.palette.foreground, children: "Terminal too small for the inspector." }), _jsx("text", { fg: props.palette.muted, children: `Current ${props.width}×${props.height} · need ${MINIMUM_WIDTH}×${MINIMUM_HEIGHT}` }), _jsx("text", { fg: props.palette.muted, children: "q quit" })] }));
293
+ }
294
+ function Header(props) {
295
+ const appearance = statusAppearance(props.snapshot.status, props.palette);
296
+ return (_jsxs("box", { height: 1, flexDirection: "row", backgroundColor: props.palette.surface, paddingLeft: 1, paddingRight: 1, children: [_jsxs("text", { children: [_jsx("span", { fg: props.palette.accent, children: "unigent" }), _jsx("span", { fg: props.palette.muted, children: ` ${basename(props.snapshot.sourceFile)} · ${props.environment}` })] }), _jsx("box", { flexGrow: 1 }), _jsx("text", { fg: props.palette.muted, children: `${formatDuration(props.duration)} ` }), _jsx("text", { fg: appearance.color, children: appearance.label })] }));
297
+ }
298
+ function TracePane(props) {
299
+ const rangeEnd = props.rangeStart + props.rows.length;
300
+ return (_jsxs("scrollbox", { width: props.width, scrollY: true, scrollAcceleration: props.scrollAcceleration, viewportCulling: true, backgroundColor: props.palette.surface, border: true, borderColor: props.selectedSpanId === undefined ? props.palette.border : props.palette.accent, title: " TRACE ", titleColor: props.palette.muted, children: [props.totalRows <= props.rows.length ? null : (_jsx("box", { paddingLeft: 1, paddingRight: 1, marginBottom: 1, children: _jsx("text", { fg: props.palette.muted, children: `Showing ${props.rangeStart + 1}–${rangeEnd} of ${props.totalRows} rows · [ older · ] newer` }) })), props.rows.length === 0 ? (_jsx("box", { padding: 1, children: _jsx("text", { fg: props.palette.muted, children: props.running ? "Waiting for first agent run…" : "No Unigent traces" }) })) : (props.rows.map((row) => (_jsx(TraceRow, { row: row, selected: row.spanId === props.selectedSpanId, palette: props.palette, onSelect: () => {
301
+ if (row.selectable) {
302
+ props.onSelect(row.spanId);
303
+ }
304
+ } }, row.spanId))))] }));
305
+ }
306
+ function ActivityContent(props) {
307
+ return (_jsxs("box", { flexDirection: "column", children: [props.transcript.length === 0 ? (_jsx("box", { paddingTop: 2, alignItems: "center", children: _jsx("text", { fg: props.palette.muted, children: props.running ? "Listening for activity…" : "This selection emitted no activity" }) })) : null, props.hiddenEntryCount > 0 ? (_jsx("box", { paddingLeft: 1, paddingRight: 1, marginBottom: 1, children: _jsx("text", { fg: props.palette.muted, children: `Showing latest ${props.transcript.length} entries · ${props.hiddenEntryCount} older entries retained` }) })) : null, props.transcript.map((entry, index) => (_jsx(Entry, { entry: entry, palette: props.palette }, index))), _jsx(SelectionDetails, { row: props.selectedRow, palette: props.palette })] }));
308
+ }
309
+ function OutputContent(props) {
310
+ const empty = props.snapshot.stdout.length === 0 &&
311
+ props.snapshot.stderr.length === 0 &&
312
+ props.snapshot.error === undefined;
313
+ if (empty) {
314
+ return (_jsx("box", { paddingTop: 2, alignItems: "center", children: _jsx("text", { fg: props.palette.muted, children: "This script emitted no process output" }) }));
315
+ }
316
+ return (_jsxs("box", { flexDirection: "column", children: [_jsx(OutputBlock, { title: "\u25A3 stdout", content: props.snapshot.stdout, color: props.palette.foreground }), _jsx(OutputBlock, { title: "\u25A3 stderr", content: props.snapshot.stderr, color: props.palette.warning }), props.snapshot.error === undefined ? null : (_jsx(OutputBlock, { title: "\u00D7 process", content: props.snapshot.error, color: props.palette.error }))] }));
317
+ }
318
+ function rightPaneTitle(view, selectedLabel) {
319
+ if (view === "output") {
320
+ return " OUTPUT ";
321
+ }
322
+ return selectedLabel === undefined ? " ACTIVITY " : ` ACTIVITY · ${selectedLabel} `;
323
+ }
324
+ function ActivityPane(props) {
325
+ return (_jsx("scrollbox", { flexGrow: 1, scrollY: true, scrollAcceleration: props.scrollAcceleration, viewportCulling: true, stickyScroll: true, stickyStart: "bottom", backgroundColor: props.palette.background, border: true, borderColor: props.palette.border, title: rightPaneTitle(props.view, props.focusLabel), titleColor: props.palette.muted, children: props.view === "activity" ? (_jsx(ActivityContent, { transcript: props.transcript, hiddenEntryCount: props.hiddenEntryCount, running: props.snapshot.status === "running", selectedRow: props.selectedRow, palette: props.palette })) : (_jsx(OutputContent, { snapshot: props.snapshot, palette: props.palette })) }));
326
+ }
327
+ function Footer(props) {
328
+ return (_jsxs("box", { height: 1, flexDirection: "row", backgroundColor: props.palette.surface, paddingLeft: 1, paddingRight: 1, children: [_jsxs("text", { fg: props.palette.muted, children: [props.running ? (_jsx("span", { fg: props.palette.warning, children: "^R stop" })) : (_jsx("span", { fg: props.palette.accent, children: "r rerun" })), " · ↑↓ trace", props.selectedRow === undefined ? null : " · esc show all", props.selectedRow?.hasTools === true ? (_jsx("span", { fg: props.palette.accent, children: props.selectedRow.toolsExpanded ? " · enter hide tools" : " · enter show tools" })) : null, props.hasTraceHistory ? " · [ ] history" : null, " · ", _jsx("span", { fg: props.view === "output" ? props.palette.accent : props.palette.muted, children: props.view === "output"
329
+ ? "o activity"
330
+ : `o output${props.outputCount > 0 ? ` (${props.outputCount})` : ""}` }), props.view === "activity" ? " · " : null, props.view === "activity" ? (_jsx("span", { fg: props.showSystemPrompt ? props.palette.accent : props.palette.muted, children: "s sys prompt" })) : null, " · drag copy · q quit"] }), _jsx("box", { flexGrow: 1 }), props.copiedCharacters === undefined ? null : (_jsx("text", { fg: props.palette.success, children: `✓ ${props.copiedCharacters} copied ` })), _jsx("text", { fg: props.palette.muted, children: formatUsage(props.tree.usage) })] }));
331
+ }
332
+ function useTranscriptView(snapshot, showSystemPrompt, selectedRow) {
333
+ const selectedSpanIds = useMemo(() => (selectedRow === undefined ? undefined : new Set(selectedRow.selectedSpanIds)), [selectedRow]);
334
+ const filtered = useMemo(() => snapshot.eventCount === 0
335
+ ? []
336
+ : snapshot.transcript.filter((entry) => (showSystemPrompt || entry.kind !== "system") &&
337
+ (selectedSpanIds === undefined || selectedSpanIds.has(entry.spanId))), [selectedSpanIds, showSystemPrompt, snapshot.eventCount, snapshot.transcript]);
338
+ const visible = useMemo(() => filtered.slice(-ACTIVITY_ENTRY_LIMIT), [filtered]);
339
+ return {
340
+ visible,
341
+ hiddenCount: Math.max(0, filtered.length - ACTIVITY_ENTRY_LIMIT),
342
+ };
343
+ }
344
+ function useAppView(args) {
345
+ const snapshot = useSyncExternalStore(args.store.subscribe, args.store.getSnapshot);
346
+ const { width, height } = useTerminalDimensions();
347
+ const palette = usePalette(args.initialTheme);
348
+ const running = snapshot.status === "running";
349
+ const currentTime = useCurrentTime(running);
350
+ const copiedCharacters = useCopyNotice();
351
+ const { tree } = snapshot;
352
+ const allRows = useMemo(() => flattenTraceTree(tree, args.expandedRunSpanIds), [args.expandedRunSpanIds, tree]);
353
+ const maximumTracePage = Math.max(0, Math.ceil(allRows.length / TRACE_PAGE_SIZE) - 1);
354
+ const activeTracePage = Math.min(args.tracePage, maximumTracePage);
355
+ const traceRangeEnd = Math.max(0, allRows.length - activeTracePage * TRACE_PAGE_SIZE);
356
+ const traceRangeStart = Math.max(0, traceRangeEnd - TRACE_PAGE_SIZE);
357
+ const rows = useMemo(() => allRows.slice(traceRangeStart, traceRangeEnd), [allRows, traceRangeEnd, traceRangeStart]);
358
+ const selectedRow = useMemo(() => allRows.find((row) => row.spanId === args.selectedSpanId), [allRows, args.selectedSpanId]);
359
+ const transcript = useTranscriptView(snapshot, args.showSystemPrompt, selectedRow);
360
+ const environment = useMemo(() => environmentLabel(tree, selectedRow), [selectedRow, tree]);
361
+ return {
362
+ snapshot,
363
+ width,
364
+ height,
365
+ palette,
366
+ running,
367
+ copiedCharacters,
368
+ tree,
369
+ rows,
370
+ totalRows: allRows.length,
371
+ traceRangeStart,
372
+ maximumTracePage,
373
+ activeTracePage,
374
+ selectedRow,
375
+ environment,
376
+ visibleTranscript: transcript.visible,
377
+ hiddenActivityEntries: transcript.hiddenCount,
378
+ duration: running ? currentTime - snapshot.startedAt : tree.durationMs,
379
+ traceWidth: Math.max(TRACE_MINIMUM_WIDTH, Math.floor(width * TRACE_WIDTH_RATIO)),
380
+ traceScrollAcceleration: useMemo(() => new NaturalScrollAcceleration({ base: 1, maximum: 8 }), []),
381
+ activityScrollAcceleration: useMemo(() => new NaturalScrollAcceleration(), []),
382
+ outputCount: Number(snapshot.stdout.length > 0) +
383
+ Number(snapshot.stderr.length > 0) +
384
+ Number(snapshot.error !== undefined),
385
+ };
386
+ }
387
+ function toggleExpandedRun(selectedRow, setExpandedRunSpanIds) {
388
+ if (selectedRow?.hasTools !== true) {
389
+ return;
390
+ }
391
+ setExpandedRunSpanIds((expanded) => {
392
+ const next = new Set(expanded);
393
+ if (next.has(selectedRow.spanId)) {
394
+ next.delete(selectedRow.spanId);
395
+ }
396
+ else {
397
+ next.add(selectedRow.spanId);
398
+ }
399
+ return next;
400
+ });
401
+ }
402
+ function AppLayout(props) {
403
+ const { view } = props;
404
+ if (view.width < MINIMUM_WIDTH || view.height < MINIMUM_HEIGHT) {
405
+ return _jsx(CompactFallback, { width: view.width, height: view.height, palette: view.palette });
406
+ }
407
+ return (_jsxs("box", { width: view.width, height: view.height, backgroundColor: view.palette.background, flexDirection: "column", children: [_jsx(Header, { snapshot: view.snapshot, environment: view.environment, duration: view.duration, palette: view.palette }), _jsxs("box", { flexGrow: 1, flexDirection: "row", children: [_jsx(TracePane, { rows: view.rows, totalRows: view.totalRows, rangeStart: view.traceRangeStart, width: view.traceWidth, running: view.running, selectedSpanId: props.selectedSpanId, palette: view.palette, scrollAcceleration: view.traceScrollAcceleration, onSelect: props.onSelectSpan }), _jsx(ActivityPane, { snapshot: view.snapshot, transcript: view.visibleTranscript, hiddenEntryCount: view.hiddenActivityEntries, focusLabel: focusLabel(view.selectedRow), selectedRow: view.selectedRow, view: props.rightPaneView, palette: view.palette, scrollAcceleration: view.activityScrollAcceleration })] }), _jsx(Footer, { running: view.running, showSystemPrompt: props.showSystemPrompt, selectedRow: view.selectedRow, view: props.rightPaneView, outputCount: view.outputCount, hasTraceHistory: view.maximumTracePage > 0, copiedCharacters: view.copiedCharacters, tree: view.tree, palette: view.palette })] }));
408
+ }
409
+ function App(props) {
410
+ const { store, initialTheme, onAbort, onRerun, onQuit } = props;
411
+ const [selectedSpanId, setSelectedSpanId] = useState();
412
+ const [showSystemPrompt, setShowSystemPrompt] = useState(false);
413
+ const [expandedRunSpanIds, setExpandedRunSpanIds] = useState(new Set());
414
+ const [rightPaneView, setRightPaneView] = useState("activity");
415
+ const [tracePage, setTracePage] = useState(0);
416
+ const view = useAppView({
417
+ store,
418
+ initialTheme,
419
+ selectedSpanId,
420
+ showSystemPrompt,
421
+ expandedRunSpanIds,
422
+ tracePage,
423
+ });
424
+ useEffect(() => {
425
+ if (view.snapshot.status === "failed" && view.totalRows === 0 && view.outputCount > 0) {
426
+ setRightPaneView("output");
427
+ }
428
+ }, [view.snapshot.status, view.totalRows, view.outputCount]);
429
+ const rerun = () => {
430
+ setSelectedSpanId(undefined);
431
+ setExpandedRunSpanIds(new Set());
432
+ setTracePage(0);
433
+ setRightPaneView("activity");
434
+ onRerun();
435
+ };
436
+ useAppKeyboard({
437
+ running: view.running,
438
+ rows: view.rows,
439
+ selectedSpanId,
440
+ setSelectedSpanId,
441
+ toggleSystemPrompt: () => setShowSystemPrompt((visible) => !visible),
442
+ toggleOutput: () => setRightPaneView((current) => (current === "activity" ? "output" : "activity")),
443
+ toggleSelectedTools: () => toggleExpandedRun(view.selectedRow, setExpandedRunSpanIds),
444
+ showOlderTraces: () => setTracePage(Math.min(view.activeTracePage + 1, view.maximumTracePage)),
445
+ showNewerTraces: () => setTracePage(Math.max(0, view.activeTracePage - 1)),
446
+ onAbort,
447
+ onRerun: rerun,
448
+ onQuit,
449
+ });
450
+ return (_jsx(AppLayout, { view: view, selectedSpanId: selectedSpanId, showSystemPrompt: showSystemPrompt, rightPaneView: rightPaneView, onSelectSpan: setSelectedSpanId }));
451
+ }
452
+ export { App };
453
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/tui/app.tsx"],"names":[],"mappings":"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","sourcesContent":["import { basename } from \"node:path\";\nimport {\n useKeyboard,\n useRenderer,\n useSelectionHandler,\n useTerminalDimensions,\n} from \"@opentui/react\";\nimport type { TraceTree, TranscriptEntry } from \"@unigent/core/trace\";\nimport { useEffect, useMemo, useState, useSyncExternalStore } from \"react\";\nimport { formatDuration, formatUsage } from \"../format.js\";\nimport { copyToClipboard } from \"./clipboard.js\";\nimport { NaturalScrollAcceleration } from \"./scroll.js\";\nimport type { TuiSnapshot, TuiStore } from \"./store.js\";\nimport { type Palette, paletteFor, type ThemeMode } from \"./theme.js\";\nimport {\n diagnosticsForRow,\n environmentLabel,\n flattenTraceTree,\n focusLabel,\n type TreeDiagnostic,\n type TreeRow,\n} from \"./tree.js\";\n\ninterface AppProps {\n readonly store: TuiStore;\n readonly initialTheme: ThemeMode;\n readonly onAbort: () => void;\n readonly onRerun: () => void;\n readonly onQuit: () => void;\n}\n\nconst CLOCK_INTERVAL_MILLISECONDS = 250;\nconst COPY_NOTICE_MILLISECONDS = 1400;\nconst MINIMUM_WIDTH = 68;\nconst MINIMUM_HEIGHT = 12;\nconst TRACE_WIDTH_RATIO = 0.36;\nconst TRACE_MINIMUM_WIDTH = 27;\nconst ENTRY_CHARACTER_LIMIT = 8000;\nconst TRACE_PAGE_SIZE = 250;\nconst ACTIVITY_ENTRY_LIMIT = 250;\nconst DIAGNOSTIC_ENTRY_LIMIT = 20;\nconst TREE_BRANCH_LENGTH = 3;\n\nfunction statusAppearance(\n status: ReturnType<TuiStore[\"getSnapshot\"]>[\"status\"],\n palette: Palette,\n): {\n readonly color: string;\n readonly label: string;\n} {\n switch (status) {\n case \"running\":\n return { color: palette.accent, label: \"● running\" };\n case \"succeeded\":\n return { color: palette.success, label: \"● complete\" };\n case \"cancelled\":\n return { color: palette.warning, label: \"● stopped\" };\n case \"failed\":\n return { color: palette.error, label: \"● failed\" };\n }\n}\n\nfunction usePalette(initialTheme: ThemeMode): Palette {\n const renderer = useRenderer();\n const [theme, setTheme] = useState(initialTheme);\n const palette = useMemo(() => paletteFor(theme), [theme]);\n useEffect(() => {\n const synchronize = (): void => {\n if (renderer.themeMode !== null) {\n setTheme(renderer.themeMode);\n }\n };\n renderer.on(\"theme_mode\", synchronize);\n return (): void => {\n renderer.off(\"theme_mode\", synchronize);\n };\n }, [renderer]);\n useEffect(() => {\n renderer.setBackgroundColor(palette.background);\n }, [palette.background, renderer]);\n return palette;\n}\n\nfunction useCurrentTime(running: boolean): number {\n const [now, setNow] = useState(Date.now());\n useEffect(() => {\n if (!running) {\n return;\n }\n const timer = setInterval(() => setNow(Date.now()), CLOCK_INTERVAL_MILLISECONDS);\n return (): void => clearInterval(timer);\n }, [running]);\n return now;\n}\n\nfunction useCopyNotice(): number | undefined {\n const [copiedCharacters, setCopiedCharacters] = useState<number | undefined>();\n useSelectionHandler((selection) => {\n const text = selection.getSelectedText();\n if (copyToClipboard(text)) {\n setCopiedCharacters(text.length);\n }\n });\n useEffect(() => {\n if (copiedCharacters === undefined) {\n return;\n }\n const timer = setTimeout(() => setCopiedCharacters(undefined), COPY_NOTICE_MILLISECONDS);\n return (): void => clearTimeout(timer);\n }, [copiedCharacters]);\n return copiedCharacters;\n}\n\nfunction nextSelection(\n rows: readonly TreeRow[],\n selectedSpanId: string | undefined,\n direction: -1 | 1,\n): string | undefined {\n const selectableRows = rows.filter((row) => row.selectable);\n if (selectableRows.length === 0) {\n return;\n }\n const selectedIndex = selectableRows.findIndex((row) => row.spanId === selectedSpanId);\n const initialIndex = direction === 1 ? 0 : selectableRows.length - 1;\n const nextIndex = selectedIndex < 0 ? initialIndex : selectedIndex + direction;\n return selectableRows[Math.max(0, Math.min(selectableRows.length - 1, nextIndex))]?.spanId;\n}\n\ntype KeyboardAction =\n | \"quit\"\n | \"abort\"\n | \"rerun\"\n | \"system\"\n | \"clearFocus\"\n | \"toggleOutput\"\n | \"toggleTools\"\n | \"older\"\n | \"newer\"\n | \"up\"\n | \"down\"\n | undefined;\n\nconst KEYBOARD_ACTIONS: Readonly<Record<string, KeyboardAction>> = {\n q: \"quit\",\n s: \"system\",\n escape: \"clearFocus\",\n o: \"toggleOutput\",\n enter: \"toggleTools\",\n return: \"toggleTools\",\n \"[\": \"older\",\n leftbracket: \"older\",\n \"]\": \"newer\",\n rightbracket: \"newer\",\n up: \"up\",\n k: \"up\",\n down: \"down\",\n j: \"down\",\n};\n\nfunction keyboardAction(\n key: { readonly name?: string; readonly ctrl?: boolean },\n running: boolean,\n): KeyboardAction {\n if (key.ctrl === true && key.name === \"c\") {\n return \"quit\";\n }\n if (key.ctrl === true && key.name === \"r\") {\n return running ? \"abort\" : undefined;\n }\n if (key.name === \"r\") {\n return running ? undefined : \"rerun\";\n }\n return key.name === undefined ? undefined : KEYBOARD_ACTIONS[key.name];\n}\n\ninterface KeyboardBindings {\n readonly running: boolean;\n readonly rows: readonly TreeRow[];\n readonly selectedSpanId: string | undefined;\n readonly setSelectedSpanId: (spanId: string | undefined) => void;\n readonly toggleSystemPrompt: () => void;\n readonly toggleOutput: () => void;\n readonly toggleSelectedTools: () => void;\n readonly showOlderTraces: () => void;\n readonly showNewerTraces: () => void;\n readonly onAbort: () => void;\n readonly onRerun: () => void;\n readonly onQuit: () => void;\n}\n\nfunction useAppKeyboard(bindings: KeyboardBindings): void {\n useKeyboard((key) => {\n switch (keyboardAction(key, bindings.running)) {\n case \"quit\":\n bindings.onQuit();\n break;\n case \"abort\":\n bindings.onAbort();\n break;\n case \"rerun\":\n bindings.onRerun();\n break;\n case \"system\":\n bindings.toggleSystemPrompt();\n break;\n case \"clearFocus\":\n bindings.setSelectedSpanId(undefined);\n break;\n case \"toggleOutput\":\n bindings.toggleOutput();\n break;\n case \"toggleTools\":\n bindings.toggleSelectedTools();\n break;\n case \"older\":\n bindings.showOlderTraces();\n break;\n case \"newer\":\n bindings.showNewerTraces();\n break;\n case \"up\":\n bindings.setSelectedSpanId(nextSelection(bindings.rows, bindings.selectedSpanId, -1));\n break;\n case \"down\":\n bindings.setSelectedSpanId(nextSelection(bindings.rows, bindings.selectedSpanId, 1));\n break;\n case undefined:\n break;\n }\n });\n}\n\nfunction trimBlock(value: unknown): string {\n let text: string;\n if (typeof value === \"string\") {\n text = value;\n } else {\n try {\n text = JSON.stringify(value, null, 2);\n } catch {\n text = String(value);\n }\n }\n return text.length <= ENTRY_CHARACTER_LIMIT\n ? text\n : `${text.slice(0, ENTRY_CHARACTER_LIMIT)}\\n… ${text.length - ENTRY_CHARACTER_LIMIT} more characters`;\n}\n\nfunction rowKindAppearance(row: TreeRow, palette: Palette): { color: string; glyph: string } {\n if (row.kind === \"scope\") {\n return { color: palette.success, glyph: \"▪\" };\n }\n if (row.kind === \"run\") {\n return { color: palette.accent, glyph: \"◆\" };\n }\n return { color: palette.tool, glyph: \"◇\" };\n}\n\nfunction nestedSummaryPrefix(prefix: string): string {\n if (prefix.endsWith(\"├─ \")) {\n return `${prefix.slice(0, -TREE_BRANCH_LENGTH)}│ └─ `;\n }\n if (prefix.endsWith(\"└─ \")) {\n return `${prefix.slice(0, -TREE_BRANCH_LENGTH)} └─ `;\n }\n return \"└─ \";\n}\n\nfunction TraceRow(props: {\n readonly row: TreeRow;\n readonly selected: boolean;\n readonly palette: Palette;\n readonly onSelect: () => void;\n}): React.ReactNode {\n const { row, selected, palette, onSelect } = props;\n const kind = rowKindAppearance(row, palette);\n let outcomeGlyph = \"·\";\n let outcomeColor = palette.muted;\n if (row.outcome === \"running\") {\n outcomeGlyph = \"◌\";\n outcomeColor = palette.accent;\n } else if (row.outcome === \"succeeded\") {\n outcomeGlyph = \"✓\";\n outcomeColor = palette.success;\n } else if (row.outcome === \"failed\") {\n outcomeGlyph = \"×\";\n outcomeColor = palette.error;\n } else {\n outcomeGlyph = \"■\";\n outcomeColor = palette.warning;\n }\n return (\n <box\n flexDirection=\"column\"\n paddingLeft={1}\n paddingRight={1}\n backgroundColor={selected ? palette.selected : palette.surface}\n onMouseDown={onSelect}\n >\n <box flexDirection=\"row\">\n <text fg={palette.accent}>{selected ? \"▌ \" : \" \"}</text>\n <text fg={palette.muted}>{row.prefix}</text>\n <text fg={kind.color}>{`${kind.glyph} ${row.name}`}</text>\n <box flexGrow={1} />\n <text fg={palette.muted}>{row.metrics.length > 0 ? `${row.metrics} ` : \"\"}</text>\n <text fg={outcomeColor}>{outcomeGlyph}</text>\n </box>\n {row.toolSummary === undefined || row.toolsExpanded ? null : (\n <text fg={palette.muted}>{` ${nestedSummaryPrefix(row.prefix)}${row.toolSummary}`}</text>\n )}\n </box>\n );\n}\n\nfunction diagnosticColor(diagnostic: TreeDiagnostic, palette: Palette): string {\n switch (diagnostic.kind) {\n case \"error\":\n return palette.error;\n case \"repair\":\n return palette.warning;\n case \"checkpoint\":\n return palette.tool;\n case \"annotation\":\n return palette.reasoning;\n case \"log\":\n return palette.success;\n }\n}\n\nfunction SelectionDetails(props: {\n readonly row: TreeRow | undefined;\n readonly palette: Palette;\n}): React.ReactNode {\n if (props.row === undefined) {\n return null;\n }\n const { row, palette } = props;\n const diagnostics = diagnosticsForRow(row);\n if (diagnostics.length === 0) {\n return null;\n }\n const hidden = Math.max(0, diagnostics.length - DIAGNOSTIC_ENTRY_LIMIT);\n const visible = diagnostics.slice(-DIAGNOSTIC_ENTRY_LIMIT);\n return (\n <box\n flexDirection=\"column\"\n paddingLeft={1}\n paddingRight={1}\n paddingTop={1}\n paddingBottom={1}\n marginBottom={1}\n backgroundColor={palette.surface}\n >\n {hidden > 0 ? <text fg={palette.muted}>{`${hidden} older diagnostics hidden`}</text> : null}\n {visible.map(\n (diagnostic, index): React.ReactNode => (\n <box key={`${diagnostic.label}-${index}`} flexDirection=\"column\" paddingTop={1}>\n <text fg={diagnosticColor(diagnostic, palette)}>{diagnostic.label}</text>\n <text fg={palette.foreground} wrapMode=\"word\">\n {trimBlock(diagnostic.value)}\n </text>\n </box>\n ),\n )}\n </box>\n );\n}\n\nfunction Entry(props: {\n readonly entry: TranscriptEntry;\n readonly palette: Palette;\n}): React.ReactNode {\n const { entry, palette } = props;\n let header: string;\n let color: string;\n let body: unknown;\n switch (entry.kind) {\n case \"system\":\n header = \"✦ system\";\n color = palette.muted;\n body = entry.text;\n break;\n case \"user\":\n header = \"▸ prompt\";\n color = palette.success;\n body = entry.text;\n break;\n case \"assistant\":\n header = \"● assistant\";\n color = palette.accent;\n body = entry.text;\n break;\n case \"reasoning\":\n header = \"✻ reasoning\";\n color = palette.reasoning;\n body = entry.text;\n break;\n case \"tool_call\":\n header = `⚙ ${entry.name}`;\n color = palette.tool;\n body = entry.input;\n break;\n case \"tool_result\":\n header = entry.isError ? `× ${entry.name}` : `✓ ${entry.name}`;\n color = entry.isError ? palette.error : palette.success;\n body = entry.output;\n break;\n }\n const userEntry = entry.kind === \"user\";\n return (\n <box\n flexDirection=\"column\"\n paddingLeft={1}\n paddingRight={1}\n marginBottom={1}\n {...(userEntry ? { backgroundColor: palette.userSurface } : {})}\n >\n <text fg={color}>{header}</text>\n <text fg={entry.kind === \"reasoning\" ? palette.muted : palette.foreground} wrapMode=\"word\">\n {trimBlock(body)}\n </text>\n </box>\n );\n}\n\nfunction OutputBlock(props: {\n readonly title: string;\n readonly content: string;\n readonly color: string;\n}): React.ReactNode {\n if (props.content.trim().length === 0) {\n return null;\n }\n return (\n <box flexDirection=\"column\" paddingLeft={1} paddingRight={1} marginBottom={1}>\n <text fg={props.color}>{props.title}</text>\n <text fg={props.color} wrapMode=\"word\">\n {trimBlock(props.content.trimEnd())}\n </text>\n </box>\n );\n}\n\nfunction CompactFallback(props: {\n readonly width: number;\n readonly height: number;\n readonly palette: Palette;\n}): React.ReactNode {\n return (\n <box\n width={props.width}\n height={props.height}\n backgroundColor={props.palette.background}\n flexDirection=\"column\"\n padding={1}\n >\n <text fg={props.palette.accent}>unigent</text>\n <text fg={props.palette.foreground}>Terminal too small for the inspector.</text>\n <text\n fg={props.palette.muted}\n >{`Current ${props.width}×${props.height} · need ${MINIMUM_WIDTH}×${MINIMUM_HEIGHT}`}</text>\n <text fg={props.palette.muted}>q quit</text>\n </box>\n );\n}\n\nfunction Header(props: {\n readonly snapshot: TuiSnapshot;\n readonly environment: string;\n readonly duration: number | undefined;\n readonly palette: Palette;\n}): React.ReactNode {\n const appearance = statusAppearance(props.snapshot.status, props.palette);\n return (\n <box\n height={1}\n flexDirection=\"row\"\n backgroundColor={props.palette.surface}\n paddingLeft={1}\n paddingRight={1}\n >\n <text>\n <span fg={props.palette.accent}>unigent</span>\n <span fg={props.palette.muted}>{` ${basename(props.snapshot.sourceFile)} · ${\n props.environment\n }`}</span>\n </text>\n <box flexGrow={1} />\n <text fg={props.palette.muted}>{`${formatDuration(props.duration)} `}</text>\n <text fg={appearance.color}>{appearance.label}</text>\n </box>\n );\n}\n\nfunction TracePane(props: {\n readonly rows: readonly TreeRow[];\n readonly totalRows: number;\n readonly rangeStart: number;\n readonly width: number;\n readonly running: boolean;\n readonly selectedSpanId: string | undefined;\n readonly palette: Palette;\n readonly scrollAcceleration: NaturalScrollAcceleration;\n readonly onSelect: (spanId: string) => void;\n}): React.ReactNode {\n const rangeEnd = props.rangeStart + props.rows.length;\n return (\n <scrollbox\n width={props.width}\n scrollY={true}\n scrollAcceleration={props.scrollAcceleration}\n viewportCulling={true}\n backgroundColor={props.palette.surface}\n border={true}\n borderColor={props.selectedSpanId === undefined ? props.palette.border : props.palette.accent}\n title=\" TRACE \"\n titleColor={props.palette.muted}\n >\n {props.totalRows <= props.rows.length ? null : (\n <box paddingLeft={1} paddingRight={1} marginBottom={1}>\n <text\n fg={props.palette.muted}\n >{`Showing ${props.rangeStart + 1}–${rangeEnd} of ${props.totalRows} rows · [ older · ] newer`}</text>\n </box>\n )}\n {props.rows.length === 0 ? (\n <box padding={1}>\n <text fg={props.palette.muted}>\n {props.running ? \"Waiting for first agent run…\" : \"No Unigent traces\"}\n </text>\n </box>\n ) : (\n props.rows.map(\n (row): React.ReactNode => (\n <TraceRow\n key={row.spanId}\n row={row}\n selected={row.spanId === props.selectedSpanId}\n palette={props.palette}\n onSelect={() => {\n if (row.selectable) {\n props.onSelect(row.spanId);\n }\n }}\n />\n ),\n )\n )}\n </scrollbox>\n );\n}\n\nfunction ActivityContent(props: {\n readonly transcript: readonly TranscriptEntry[];\n readonly hiddenEntryCount: number;\n readonly running: boolean;\n readonly selectedRow: TreeRow | undefined;\n readonly palette: Palette;\n}): React.ReactNode {\n return (\n <box flexDirection=\"column\">\n {props.transcript.length === 0 ? (\n <box paddingTop={2} alignItems=\"center\">\n <text fg={props.palette.muted}>\n {props.running ? \"Listening for activity…\" : \"This selection emitted no activity\"}\n </text>\n </box>\n ) : null}\n {props.hiddenEntryCount > 0 ? (\n <box paddingLeft={1} paddingRight={1} marginBottom={1}>\n <text\n fg={props.palette.muted}\n >{`Showing latest ${props.transcript.length} entries · ${props.hiddenEntryCount} older entries retained`}</text>\n </box>\n ) : null}\n {props.transcript.map(\n (entry, index): React.ReactNode => (\n <Entry key={index} entry={entry} palette={props.palette} />\n ),\n )}\n <SelectionDetails row={props.selectedRow} palette={props.palette} />\n </box>\n );\n}\n\nfunction OutputContent(props: {\n readonly snapshot: TuiSnapshot;\n readonly palette: Palette;\n}): React.ReactNode {\n const empty =\n props.snapshot.stdout.length === 0 &&\n props.snapshot.stderr.length === 0 &&\n props.snapshot.error === undefined;\n if (empty) {\n return (\n <box paddingTop={2} alignItems=\"center\">\n <text fg={props.palette.muted}>This script emitted no process output</text>\n </box>\n );\n }\n return (\n <box flexDirection=\"column\">\n <OutputBlock\n title=\"▣ stdout\"\n content={props.snapshot.stdout}\n color={props.palette.foreground}\n />\n <OutputBlock title=\"▣ stderr\" content={props.snapshot.stderr} color={props.palette.warning} />\n {props.snapshot.error === undefined ? null : (\n <OutputBlock title=\"× process\" content={props.snapshot.error} color={props.palette.error} />\n )}\n </box>\n );\n}\n\nfunction rightPaneTitle(view: \"activity\" | \"output\", selectedLabel: string | undefined): string {\n if (view === \"output\") {\n return \" OUTPUT \";\n }\n return selectedLabel === undefined ? \" ACTIVITY \" : ` ACTIVITY · ${selectedLabel} `;\n}\n\nfunction ActivityPane(props: {\n readonly snapshot: TuiSnapshot;\n readonly transcript: readonly TranscriptEntry[];\n readonly hiddenEntryCount: number;\n readonly focusLabel: string | undefined;\n readonly selectedRow: TreeRow | undefined;\n readonly view: \"activity\" | \"output\";\n readonly palette: Palette;\n readonly scrollAcceleration: NaturalScrollAcceleration;\n}): React.ReactNode {\n return (\n <scrollbox\n flexGrow={1}\n scrollY={true}\n scrollAcceleration={props.scrollAcceleration}\n viewportCulling={true}\n stickyScroll={true}\n stickyStart=\"bottom\"\n backgroundColor={props.palette.background}\n border={true}\n borderColor={props.palette.border}\n title={rightPaneTitle(props.view, props.focusLabel)}\n titleColor={props.palette.muted}\n >\n {props.view === \"activity\" ? (\n <ActivityContent\n transcript={props.transcript}\n hiddenEntryCount={props.hiddenEntryCount}\n running={props.snapshot.status === \"running\"}\n selectedRow={props.selectedRow}\n palette={props.palette}\n />\n ) : (\n <OutputContent snapshot={props.snapshot} palette={props.palette} />\n )}\n </scrollbox>\n );\n}\n\nfunction Footer(props: {\n readonly running: boolean;\n readonly showSystemPrompt: boolean;\n readonly selectedRow: TreeRow | undefined;\n readonly view: \"activity\" | \"output\";\n readonly outputCount: number;\n readonly hasTraceHistory: boolean;\n readonly copiedCharacters: number | undefined;\n readonly tree: TraceTree;\n readonly palette: Palette;\n}): React.ReactNode {\n return (\n <box\n height={1}\n flexDirection=\"row\"\n backgroundColor={props.palette.surface}\n paddingLeft={1}\n paddingRight={1}\n >\n <text fg={props.palette.muted}>\n {props.running ? (\n <span fg={props.palette.warning}>^R stop</span>\n ) : (\n <span fg={props.palette.accent}>r rerun</span>\n )}\n {\" · ↑↓ trace\"}\n {props.selectedRow === undefined ? null : \" · esc show all\"}\n {props.selectedRow?.hasTools === true ? (\n <span fg={props.palette.accent}>\n {props.selectedRow.toolsExpanded ? \" · enter hide tools\" : \" · enter show tools\"}\n </span>\n ) : null}\n {props.hasTraceHistory ? \" · [ ] history\" : null}\n {\" · \"}\n <span fg={props.view === \"output\" ? props.palette.accent : props.palette.muted}>\n {props.view === \"output\"\n ? \"o activity\"\n : `o output${props.outputCount > 0 ? ` (${props.outputCount})` : \"\"}`}\n </span>\n {props.view === \"activity\" ? \" · \" : null}\n {props.view === \"activity\" ? (\n <span fg={props.showSystemPrompt ? props.palette.accent : props.palette.muted}>\n s sys prompt\n </span>\n ) : null}\n {\" · drag copy · q quit\"}\n </text>\n <box flexGrow={1} />\n {props.copiedCharacters === undefined ? null : (\n <text fg={props.palette.success}>{`✓ ${props.copiedCharacters} copied `}</text>\n )}\n <text fg={props.palette.muted}>{formatUsage(props.tree.usage)}</text>\n </box>\n );\n}\n\ninterface AppView {\n readonly snapshot: TuiSnapshot;\n readonly width: number;\n readonly height: number;\n readonly palette: Palette;\n readonly running: boolean;\n readonly copiedCharacters: number | undefined;\n readonly tree: TraceTree;\n readonly rows: readonly TreeRow[];\n readonly totalRows: number;\n readonly traceRangeStart: number;\n readonly maximumTracePage: number;\n readonly activeTracePage: number;\n readonly selectedRow: TreeRow | undefined;\n readonly environment: string;\n readonly visibleTranscript: readonly TranscriptEntry[];\n readonly hiddenActivityEntries: number;\n readonly duration: number | undefined;\n readonly traceWidth: number;\n readonly traceScrollAcceleration: NaturalScrollAcceleration;\n readonly activityScrollAcceleration: NaturalScrollAcceleration;\n readonly outputCount: number;\n}\n\ninterface TranscriptView {\n readonly visible: readonly TranscriptEntry[];\n readonly hiddenCount: number;\n}\n\nfunction useTranscriptView(\n snapshot: TuiSnapshot,\n showSystemPrompt: boolean,\n selectedRow: TreeRow | undefined,\n): TranscriptView {\n const selectedSpanIds = useMemo(\n () => (selectedRow === undefined ? undefined : new Set(selectedRow.selectedSpanIds)),\n [selectedRow],\n );\n const filtered = useMemo(\n () =>\n snapshot.eventCount === 0\n ? []\n : snapshot.transcript.filter(\n (entry) =>\n (showSystemPrompt || entry.kind !== \"system\") &&\n (selectedSpanIds === undefined || selectedSpanIds.has(entry.spanId)),\n ),\n [selectedSpanIds, showSystemPrompt, snapshot.eventCount, snapshot.transcript],\n );\n const visible = useMemo(() => filtered.slice(-ACTIVITY_ENTRY_LIMIT), [filtered]);\n return {\n visible,\n hiddenCount: Math.max(0, filtered.length - ACTIVITY_ENTRY_LIMIT),\n };\n}\n\nfunction useAppView(args: {\n readonly store: TuiStore;\n readonly initialTheme: ThemeMode;\n readonly selectedSpanId: string | undefined;\n readonly showSystemPrompt: boolean;\n readonly expandedRunSpanIds: ReadonlySet<string>;\n readonly tracePage: number;\n}): AppView {\n const snapshot = useSyncExternalStore(args.store.subscribe, args.store.getSnapshot);\n const { width, height } = useTerminalDimensions();\n const palette = usePalette(args.initialTheme);\n const running = snapshot.status === \"running\";\n const currentTime = useCurrentTime(running);\n const copiedCharacters = useCopyNotice();\n const { tree } = snapshot;\n const allRows = useMemo(\n () => flattenTraceTree(tree, args.expandedRunSpanIds),\n [args.expandedRunSpanIds, tree],\n );\n const maximumTracePage = Math.max(0, Math.ceil(allRows.length / TRACE_PAGE_SIZE) - 1);\n const activeTracePage = Math.min(args.tracePage, maximumTracePage);\n const traceRangeEnd = Math.max(0, allRows.length - activeTracePage * TRACE_PAGE_SIZE);\n const traceRangeStart = Math.max(0, traceRangeEnd - TRACE_PAGE_SIZE);\n const rows = useMemo(\n () => allRows.slice(traceRangeStart, traceRangeEnd),\n [allRows, traceRangeEnd, traceRangeStart],\n );\n const selectedRow = useMemo(\n () => allRows.find((row) => row.spanId === args.selectedSpanId),\n [allRows, args.selectedSpanId],\n );\n const transcript = useTranscriptView(snapshot, args.showSystemPrompt, selectedRow);\n const environment = useMemo(() => environmentLabel(tree, selectedRow), [selectedRow, tree]);\n return {\n snapshot,\n width,\n height,\n palette,\n running,\n copiedCharacters,\n tree,\n rows,\n totalRows: allRows.length,\n traceRangeStart,\n maximumTracePage,\n activeTracePage,\n selectedRow,\n environment,\n visibleTranscript: transcript.visible,\n hiddenActivityEntries: transcript.hiddenCount,\n duration: running ? currentTime - snapshot.startedAt : tree.durationMs,\n traceWidth: Math.max(TRACE_MINIMUM_WIDTH, Math.floor(width * TRACE_WIDTH_RATIO)),\n traceScrollAcceleration: useMemo(\n () => new NaturalScrollAcceleration({ base: 1, maximum: 8 }),\n [],\n ),\n activityScrollAcceleration: useMemo(() => new NaturalScrollAcceleration(), []),\n outputCount:\n Number(snapshot.stdout.length > 0) +\n Number(snapshot.stderr.length > 0) +\n Number(snapshot.error !== undefined),\n };\n}\n\nfunction toggleExpandedRun(\n selectedRow: TreeRow | undefined,\n setExpandedRunSpanIds: React.Dispatch<React.SetStateAction<ReadonlySet<string>>>,\n): void {\n if (selectedRow?.hasTools !== true) {\n return;\n }\n setExpandedRunSpanIds((expanded) => {\n const next = new Set(expanded);\n if (next.has(selectedRow.spanId)) {\n next.delete(selectedRow.spanId);\n } else {\n next.add(selectedRow.spanId);\n }\n return next;\n });\n}\n\nfunction AppLayout(props: {\n readonly view: AppView;\n readonly selectedSpanId: string | undefined;\n readonly showSystemPrompt: boolean;\n readonly rightPaneView: \"activity\" | \"output\";\n readonly onSelectSpan: (spanId: string) => void;\n}): React.ReactNode {\n const { view } = props;\n if (view.width < MINIMUM_WIDTH || view.height < MINIMUM_HEIGHT) {\n return <CompactFallback width={view.width} height={view.height} palette={view.palette} />;\n }\n return (\n <box\n width={view.width}\n height={view.height}\n backgroundColor={view.palette.background}\n flexDirection=\"column\"\n >\n <Header\n snapshot={view.snapshot}\n environment={view.environment}\n duration={view.duration}\n palette={view.palette}\n />\n <box flexGrow={1} flexDirection=\"row\">\n <TracePane\n rows={view.rows}\n totalRows={view.totalRows}\n rangeStart={view.traceRangeStart}\n width={view.traceWidth}\n running={view.running}\n selectedSpanId={props.selectedSpanId}\n palette={view.palette}\n scrollAcceleration={view.traceScrollAcceleration}\n onSelect={props.onSelectSpan}\n />\n <ActivityPane\n snapshot={view.snapshot}\n transcript={view.visibleTranscript}\n hiddenEntryCount={view.hiddenActivityEntries}\n focusLabel={focusLabel(view.selectedRow)}\n selectedRow={view.selectedRow}\n view={props.rightPaneView}\n palette={view.palette}\n scrollAcceleration={view.activityScrollAcceleration}\n />\n </box>\n <Footer\n running={view.running}\n showSystemPrompt={props.showSystemPrompt}\n selectedRow={view.selectedRow}\n view={props.rightPaneView}\n outputCount={view.outputCount}\n hasTraceHistory={view.maximumTracePage > 0}\n copiedCharacters={view.copiedCharacters}\n tree={view.tree}\n palette={view.palette}\n />\n </box>\n );\n}\n\nfunction App(props: AppProps): React.ReactNode {\n const { store, initialTheme, onAbort, onRerun, onQuit } = props;\n const [selectedSpanId, setSelectedSpanId] = useState<string | undefined>();\n const [showSystemPrompt, setShowSystemPrompt] = useState(false);\n const [expandedRunSpanIds, setExpandedRunSpanIds] = useState<ReadonlySet<string>>(new Set());\n const [rightPaneView, setRightPaneView] = useState<\"activity\" | \"output\">(\"activity\");\n const [tracePage, setTracePage] = useState(0);\n const view = useAppView({\n store,\n initialTheme,\n selectedSpanId,\n showSystemPrompt,\n expandedRunSpanIds,\n tracePage,\n });\n useEffect(() => {\n if (view.snapshot.status === \"failed\" && view.totalRows === 0 && view.outputCount > 0) {\n setRightPaneView(\"output\");\n }\n }, [view.snapshot.status, view.totalRows, view.outputCount]);\n const rerun = (): void => {\n setSelectedSpanId(undefined);\n setExpandedRunSpanIds(new Set());\n setTracePage(0);\n setRightPaneView(\"activity\");\n onRerun();\n };\n\n useAppKeyboard({\n running: view.running,\n rows: view.rows,\n selectedSpanId,\n setSelectedSpanId,\n toggleSystemPrompt: () => setShowSystemPrompt((visible) => !visible),\n toggleOutput: () =>\n setRightPaneView((current) => (current === \"activity\" ? \"output\" : \"activity\")),\n toggleSelectedTools: () => toggleExpandedRun(view.selectedRow, setExpandedRunSpanIds),\n showOlderTraces: () => setTracePage(Math.min(view.activeTracePage + 1, view.maximumTracePage)),\n showNewerTraces: () => setTracePage(Math.max(0, view.activeTracePage - 1)),\n onAbort,\n onRerun: rerun,\n onQuit,\n });\n\n return (\n <AppLayout\n view={view}\n selectedSpanId={selectedSpanId}\n showSystemPrompt={showSystemPrompt}\n rightPaneView={rightPaneView}\n onSelectSpan={setSelectedSpanId}\n />\n );\n}\n\nexport { App };\n"]}
@@ -0,0 +1,31 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import process from "node:process";
3
+ function clipboardCommands(platform) {
4
+ if (platform === "darwin") {
5
+ return [{ executable: "pbcopy", arguments: [] }];
6
+ }
7
+ if (platform === "win32") {
8
+ return [{ executable: "clip.exe", arguments: [] }];
9
+ }
10
+ return [
11
+ { executable: "wl-copy", arguments: [] },
12
+ { executable: "xclip", arguments: ["-selection", "clipboard"] },
13
+ { executable: "xsel", arguments: ["--clipboard", "--input"] },
14
+ ];
15
+ }
16
+ function copyWithCommand(text, command) {
17
+ const result = spawnSync(command.executable, command.arguments, {
18
+ encoding: "utf8",
19
+ input: text,
20
+ stdio: ["pipe", "ignore", "ignore"],
21
+ });
22
+ return result.error === undefined && result.status === 0;
23
+ }
24
+ function copyToClipboard(text) {
25
+ if (text.length === 0) {
26
+ return false;
27
+ }
28
+ return clipboardCommands(process.platform).some((command) => copyWithCommand(text, command));
29
+ }
30
+ export { clipboardCommands, copyToClipboard, copyWithCommand };
31
+ //# sourceMappingURL=clipboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/tui/clipboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,OAAO,MAAM,cAAc,CAAC;AAOnC,SAAS,iBAAiB,CAAC,QAAyB;IAClD,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,OAAO,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACzB,OAAO,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;IACrD,CAAC;IACD,OAAO;QACL,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,EAAE;QACxC,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,YAAY,EAAE,WAAW,CAAC,EAAE;QAC/D,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,aAAa,EAAE,SAAS,CAAC,EAAE;KAC9D,CAAC;AACJ,CAAC;AAED,SAAS,eAAe,CAAC,IAAY,EAAE,OAAyB;IAC9D,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,SAAS,EAAE;QAC9D,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,IAAI;QACX,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC;KACpC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,eAAe,CAAC,IAAY;IACnC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,iBAAiB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;AAC/F,CAAC;AAED,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,EAAE,CAAC","sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport process from \"node:process\";\n\ninterface ClipboardCommand {\n readonly executable: string;\n readonly arguments: readonly string[];\n}\n\nfunction clipboardCommands(platform: NodeJS.Platform): readonly ClipboardCommand[] {\n if (platform === \"darwin\") {\n return [{ executable: \"pbcopy\", arguments: [] }];\n }\n if (platform === \"win32\") {\n return [{ executable: \"clip.exe\", arguments: [] }];\n }\n return [\n { executable: \"wl-copy\", arguments: [] },\n { executable: \"xclip\", arguments: [\"-selection\", \"clipboard\"] },\n { executable: \"xsel\", arguments: [\"--clipboard\", \"--input\"] },\n ];\n}\n\nfunction copyWithCommand(text: string, command: ClipboardCommand): boolean {\n const result = spawnSync(command.executable, command.arguments, {\n encoding: \"utf8\",\n input: text,\n stdio: [\"pipe\", \"ignore\", \"ignore\"],\n });\n return result.error === undefined && result.status === 0;\n}\n\nfunction copyToClipboard(text: string): boolean {\n if (text.length === 0) {\n return false;\n }\n return clipboardCommands(process.platform).some((command) => copyWithCommand(text, command));\n}\n\nexport { clipboardCommands, copyToClipboard, copyWithCommand };\n"]}