@tangle-network/sandbox-ui 0.2.2 → 0.3.3

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 (67) hide show
  1. package/README.md +201 -10
  2. package/dist/auth.js +2 -2
  3. package/dist/chat-container-C8eHLw8z.d.ts +67 -0
  4. package/dist/chat.d.ts +70 -78
  5. package/dist/chat.js +8 -8
  6. package/dist/chunk-4F2GJRGU.js +756 -0
  7. package/dist/{chunk-HYEAX3DC.js → chunk-5LV6DZZF.js} +445 -114
  8. package/dist/chunk-67C53XVV.js +1106 -0
  9. package/dist/{chunk-QSQBDR3N.js → chunk-BX6AQMUS.js} +5 -2
  10. package/dist/chunk-CCKNIAS7.js +124 -0
  11. package/dist/chunk-CJ2RYVZH.js +128 -0
  12. package/dist/{chunk-KMXV7DDX.js → chunk-CNWVHQFY.js} +1 -1
  13. package/dist/{chunk-OU4TRNQZ.js → chunk-COCSO7FG.js} +3 -3
  14. package/dist/chunk-FJSVPBKY.js +85 -0
  15. package/dist/chunk-FRGMMANX.js +102 -0
  16. package/dist/{chunk-E6FS7R4X.js → chunk-HWLX5NME.js} +1 -1
  17. package/dist/chunk-JF6E2DS5.js +610 -0
  18. package/dist/chunk-MUOL44AE.js +121 -0
  19. package/dist/chunk-MXCSSOGH.js +105 -0
  20. package/dist/{chunk-J4OADEUK.js → chunk-OM6ON27W.js} +24 -9
  21. package/dist/{chunk-NI2EI43H.js → chunk-PDV7W4NY.js} +9 -124
  22. package/dist/chunk-TQN3VR4F.js +92 -0
  23. package/dist/{chunk-SOT2V7TX.js → chunk-TXI4MZAZ.js} +62 -144
  24. package/dist/chunk-WUR652Y3.js +1140 -0
  25. package/dist/chunk-YDBXQQLC.js +336 -0
  26. package/dist/{chunk-4EIWPJMJ.js → chunk-ZP6GSX4D.js} +36 -27
  27. package/dist/dashboard.d.ts +5 -2
  28. package/dist/dashboard.js +5 -4
  29. package/dist/{expanded-tool-detail-OkXGqTHe.d.ts → expanded-tool-detail-BDi_h_dZ.d.ts} +11 -4
  30. package/dist/file-tabs-CmaoDVBI.d.ts +72 -0
  31. package/dist/files.d.ts +25 -44
  32. package/dist/files.js +8 -3
  33. package/{src/styles → dist}/globals.css +16 -67
  34. package/dist/hooks.d.ts +5 -4
  35. package/dist/hooks.js +14 -9
  36. package/dist/index.d.ts +38 -9
  37. package/dist/index.js +100 -126
  38. package/dist/markdown.d.ts +1 -24
  39. package/dist/markdown.js +1 -7
  40. package/dist/openui.d.ts +115 -0
  41. package/dist/openui.js +11 -0
  42. package/dist/pages.d.ts +3 -2
  43. package/dist/pages.js +19 -16
  44. package/dist/primitives.js +25 -19
  45. package/dist/run.d.ts +2 -2
  46. package/dist/run.js +8 -7
  47. package/dist/{use-sidecar-auth-Bb0-w3lX.d.ts → sdk-hooks.d.ts} +61 -72
  48. package/dist/sdk-hooks.js +29 -0
  49. package/dist/styles.css +179 -0
  50. package/dist/tokens.css +165 -0
  51. package/dist/{tool-display-BvsVW_Ur.d.ts → tool-display-Ct9nFAzJ.d.ts} +1 -1
  52. package/dist/types.d.ts +1 -1
  53. package/dist/{usage-chart-DINgSVL5.d.ts → usage-chart-CY9xo3KX.d.ts} +8 -3
  54. package/dist/use-pty-session-DeZSxOCN.d.ts +69 -0
  55. package/dist/utils.d.ts +1 -1
  56. package/dist/utils.js +1 -1
  57. package/dist/workspace.d.ts +171 -33
  58. package/dist/workspace.js +25 -1
  59. package/package.json +10 -3
  60. package/dist/chunk-2UHPE5T7.js +0 -201
  61. package/dist/chunk-6MQIDUPA.js +0 -502
  62. package/dist/chunk-KYY2X6LY.js +0 -318
  63. package/dist/chunk-L6ZDH5F4.js +0 -334
  64. package/dist/chunk-M34OA6PQ.js +0 -233
  65. package/dist/chunk-M6VLC32S.js +0 -219
  66. package/dist/chunk-U62G5TS7.js +0 -472
  67. package/src/styles/tokens.css +0 -73
@@ -0,0 +1,1140 @@
1
+ import {
2
+ formatDuration,
3
+ truncateText
4
+ } from "./chunk-HRMUF35V.js";
5
+ import {
6
+ getToolCategory,
7
+ getToolDisplayMetadata,
8
+ getToolErrorText
9
+ } from "./chunk-BX6AQMUS.js";
10
+ import {
11
+ CodeBlock,
12
+ CopyButton,
13
+ Markdown
14
+ } from "./chunk-LTFK464G.js";
15
+ import {
16
+ cn
17
+ } from "./chunk-RQHJBTEU.js";
18
+
19
+ // src/tool-previews/command-preview.tsx
20
+ import { memo, useState } from "react";
21
+ import {
22
+ Terminal,
23
+ ChevronDown,
24
+ ChevronRight
25
+ } from "lucide-react";
26
+
27
+ // src/tool-previews/preview-primitives.tsx
28
+ import { Loader2 } from "lucide-react";
29
+ import { jsx, jsxs } from "react/jsx-runtime";
30
+ function PreviewCard({
31
+ icon,
32
+ title,
33
+ description,
34
+ meta,
35
+ children,
36
+ className
37
+ }) {
38
+ return /* @__PURE__ */ jsxs(
39
+ "div",
40
+ {
41
+ className: cn(
42
+ "overflow-hidden rounded-[var(--radius-lg)] border border-[var(--border-subtle)] bg-[var(--bg-card)] shadow-[var(--shadow-card)]",
43
+ className
44
+ ),
45
+ children: [
46
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 border-b border-[var(--border-subtle)] bg-[var(--bg-elevated)]/70 px-4 py-3", children: [
47
+ /* @__PURE__ */ jsx("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-[var(--radius-md)] border border-[var(--border-accent)] bg-[var(--bg-section)] text-[var(--brand-cool)]", children: icon }),
48
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
49
+ /* @__PURE__ */ jsx("div", { className: "text-sm font-semibold text-[var(--text-primary)]", children: title }),
50
+ description ? /* @__PURE__ */ jsx("div", { className: "mt-1 text-xs text-[var(--text-muted)]", children: description }) : null
51
+ ] }),
52
+ meta ? /* @__PURE__ */ jsx("div", { className: "shrink-0 text-xs text-[var(--text-muted)]", children: meta }) : null
53
+ ] }),
54
+ children ? /* @__PURE__ */ jsx("div", { className: "space-y-3 px-4 py-4", children }) : null
55
+ ]
56
+ }
57
+ );
58
+ }
59
+ function PreviewEmpty({
60
+ label,
61
+ className
62
+ }) {
63
+ return /* @__PURE__ */ jsx(
64
+ "div",
65
+ {
66
+ className: cn(
67
+ "rounded-[var(--radius-md)] border border-dashed border-[var(--border-subtle)] bg-[var(--bg-section)]/60 px-3 py-4 text-sm text-[var(--text-muted)]",
68
+ className
69
+ ),
70
+ children: label
71
+ }
72
+ );
73
+ }
74
+ function PreviewError({ error }) {
75
+ return /* @__PURE__ */ jsx("div", { className: "rounded-[var(--radius-md)] border border-red-500/30 bg-red-500/8 px-3 py-3 text-sm text-red-200", children: error });
76
+ }
77
+ function PreviewLoading({ label = "Running\u2026" }) {
78
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-[var(--radius-md)] border border-[var(--border-subtle)] bg-[var(--bg-section)]/60 px-3 py-3 text-sm text-[var(--text-muted)]", children: [
79
+ /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin text-[var(--brand-cool)]" }),
80
+ /* @__PURE__ */ jsx("span", { children: label })
81
+ ] });
82
+ }
83
+
84
+ // src/tool-previews/command-preview.tsx
85
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
86
+ function extractCommandOutput(output) {
87
+ if (!output) return { stdout: "", stderr: "", exitCode: 0 };
88
+ if (typeof output === "string") return { stdout: output, stderr: "", exitCode: 0 };
89
+ if (typeof output === "object" && output !== null) {
90
+ const obj = output;
91
+ return {
92
+ stdout: String(obj.stdout ?? obj.output ?? ""),
93
+ stderr: String(obj.stderr ?? ""),
94
+ exitCode: Number(obj.exitCode ?? obj.exit_code ?? obj.code ?? 0)
95
+ };
96
+ }
97
+ return { stdout: String(output), stderr: "", exitCode: 0 };
98
+ }
99
+ var CommandPreview = memo(({ part }) => {
100
+ const [expanded, setExpanded] = useState(true);
101
+ const input = part.state.input;
102
+ const command = typeof input?.command === "string" ? input.command : String(input ?? "");
103
+ const output = part.state.status === "completed" ? extractCommandOutput(part.state.output) : null;
104
+ const isError = output ? output.exitCode !== 0 : part.state.status === "error";
105
+ const errorText = part.state.error;
106
+ const lineCount = output?.stdout ? output.stdout.split("\n").length : 0;
107
+ return /* @__PURE__ */ jsxs2(
108
+ PreviewCard,
109
+ {
110
+ icon: /* @__PURE__ */ jsx2(Terminal, { className: "h-4 w-4" }),
111
+ title: "Command",
112
+ description: command,
113
+ meta: output ? /* @__PURE__ */ jsxs2(
114
+ "span",
115
+ {
116
+ className: cn(
117
+ "inline-flex items-center rounded-full border px-2 py-0.5 font-[var(--font-mono)]",
118
+ isError ? "border-red-500/30 bg-red-500/10 text-red-200" : "border-emerald-500/30 bg-emerald-500/10 text-emerald-200"
119
+ ),
120
+ children: [
121
+ "exit ",
122
+ output.exitCode
123
+ ]
124
+ }
125
+ ) : null,
126
+ children: [
127
+ /* @__PURE__ */ jsxs2(
128
+ "button",
129
+ {
130
+ onClick: () => setExpanded((value) => !value),
131
+ className: "flex w-full items-center gap-2 rounded-[var(--radius-md)] border border-[var(--border-subtle)] bg-[var(--bg-section)]/60 px-3 py-2 text-left transition-colors hover:border-[var(--border-accent-hover)] hover:bg-[var(--bg-hover)]/45",
132
+ children: [
133
+ /* @__PURE__ */ jsx2("code", { className: "min-w-0 flex-1 truncate text-xs font-[var(--font-mono)] text-[var(--text-secondary)]", children: command }),
134
+ lineCount > 0 ? /* @__PURE__ */ jsxs2("span", { className: "shrink-0 text-xs text-[var(--text-muted)]", children: [
135
+ lineCount,
136
+ " line",
137
+ lineCount === 1 ? "" : "s"
138
+ ] }) : null,
139
+ expanded ? /* @__PURE__ */ jsx2(ChevronDown, { className: "h-3.5 w-3.5 text-[var(--text-muted)]" }) : /* @__PURE__ */ jsx2(ChevronRight, { className: "h-3.5 w-3.5 text-[var(--text-muted)]" })
140
+ ]
141
+ }
142
+ ),
143
+ part.state.status === "running" ? /* @__PURE__ */ jsx2(PreviewLoading, {}) : null,
144
+ errorText ? /* @__PURE__ */ jsx2(PreviewError, { error: errorText }) : null,
145
+ expanded && output ? /* @__PURE__ */ jsxs2("div", { className: "overflow-hidden rounded-[var(--radius-md)] border border-[var(--border-subtle)] bg-[var(--bg-section)]/55", children: [
146
+ output.stdout ? /* @__PURE__ */ jsx2("pre", { className: "max-h-80 overflow-auto px-3 py-3 text-xs font-[var(--font-mono)] whitespace-pre-wrap break-all text-[var(--text-secondary)]", children: output.stdout }) : null,
147
+ output.stderr ? /* @__PURE__ */ jsx2("pre", { className: "max-h-80 overflow-auto border-t border-[var(--border-subtle)] px-3 py-3 text-xs font-[var(--font-mono)] whitespace-pre-wrap break-all text-red-200", children: output.stderr }) : null
148
+ ] }) : null
149
+ ]
150
+ }
151
+ );
152
+ });
153
+ CommandPreview.displayName = "CommandPreview";
154
+
155
+ // src/tool-previews/write-file-preview.tsx
156
+ import { memo as memo2 } from "react";
157
+ import { FileEdit } from "lucide-react";
158
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
159
+ function extractWriteContent(input) {
160
+ if (!input || typeof input !== "object") return null;
161
+ const obj = input;
162
+ const path = String(obj.file_path ?? obj.path ?? obj.filePath ?? "unknown");
163
+ const content = String(obj.content ?? obj.contents ?? obj.data ?? "");
164
+ return { path, content };
165
+ }
166
+ function getLanguageFromPath(path) {
167
+ const ext = path.split(".").pop()?.toLowerCase();
168
+ const map = {
169
+ ts: "typescript",
170
+ tsx: "tsx",
171
+ js: "javascript",
172
+ jsx: "jsx",
173
+ rs: "rust",
174
+ py: "python",
175
+ go: "go",
176
+ rb: "ruby",
177
+ json: "json",
178
+ yaml: "yaml",
179
+ yml: "yaml",
180
+ toml: "toml",
181
+ md: "markdown",
182
+ css: "css",
183
+ scss: "scss",
184
+ html: "html",
185
+ sh: "bash",
186
+ bash: "bash",
187
+ zsh: "bash",
188
+ sql: "sql",
189
+ sol: "solidity",
190
+ proto: "protobuf"
191
+ };
192
+ return ext ? map[ext] : void 0;
193
+ }
194
+ var WriteFilePreview = memo2(({ part }) => {
195
+ const write = extractWriteContent(part.state.input);
196
+ if (!write) return null;
197
+ const lineCount = write.content.split("\n").length;
198
+ const language = getLanguageFromPath(write.path);
199
+ return /* @__PURE__ */ jsxs3(
200
+ PreviewCard,
201
+ {
202
+ icon: /* @__PURE__ */ jsx3(FileEdit, { className: "h-4 w-4" }),
203
+ title: "Write file",
204
+ description: write.path,
205
+ meta: /* @__PURE__ */ jsxs3("span", { className: "text-xs text-[var(--text-muted)]", children: [
206
+ "+",
207
+ lineCount,
208
+ " line",
209
+ lineCount !== 1 ? "s" : ""
210
+ ] }),
211
+ children: [
212
+ part.state.status === "running" ? /* @__PURE__ */ jsx3(PreviewLoading, { label: "Writing file\u2026" }) : null,
213
+ part.state.error ? /* @__PURE__ */ jsx3(PreviewError, { error: part.state.error }) : null,
214
+ /* @__PURE__ */ jsx3(CodeBlock, { code: write.content, language, className: "rounded-[var(--radius-md)]", children: /* @__PURE__ */ jsx3(CopyButton, { text: write.content }) })
215
+ ]
216
+ }
217
+ );
218
+ });
219
+ WriteFilePreview.displayName = "WriteFilePreview";
220
+
221
+ // src/tool-previews/grep-results-preview.tsx
222
+ import { memo as memo3, useMemo } from "react";
223
+ import { Search } from "lucide-react";
224
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
225
+ function coerceString(value) {
226
+ return typeof value === "string" && value.trim() ? value : void 0;
227
+ }
228
+ function parseMatch(value) {
229
+ if (typeof value === "string") {
230
+ const [path2, maybeLine, ...rest] = value.split(":");
231
+ const line2 = Number(maybeLine);
232
+ if (rest.length > 0 && Number.isFinite(line2)) {
233
+ return {
234
+ path: path2,
235
+ line: line2,
236
+ text: rest.join(":").trim()
237
+ };
238
+ }
239
+ return {
240
+ path: "match",
241
+ text: value
242
+ };
243
+ }
244
+ if (!value || typeof value !== "object") {
245
+ return null;
246
+ }
247
+ const record = value;
248
+ const path = coerceString(record.path) ?? coerceString(record.file) ?? coerceString(record.filePath) ?? "match";
249
+ const lineValue = record.line ?? record.lineNumber ?? record.line_number;
250
+ const line = typeof lineValue === "number" ? lineValue : Number(lineValue);
251
+ const text = coerceString(record.text) ?? coerceString(record.content) ?? coerceString(record.lineText) ?? coerceString(record.preview);
252
+ if (!text) {
253
+ return null;
254
+ }
255
+ return {
256
+ path,
257
+ line: Number.isFinite(line) ? line : void 0,
258
+ text
259
+ };
260
+ }
261
+ function extractPattern(input) {
262
+ if (!input || typeof input !== "object") {
263
+ return void 0;
264
+ }
265
+ const record = input;
266
+ return coerceString(record.pattern) ?? coerceString(record.query);
267
+ }
268
+ function extractMatches(output) {
269
+ if (Array.isArray(output)) {
270
+ return output.map(parseMatch).filter((value) => value !== null);
271
+ }
272
+ if (output && typeof output === "object") {
273
+ const record = output;
274
+ const candidates = [record.matches, record.results, record.output];
275
+ for (const candidate of candidates) {
276
+ if (Array.isArray(candidate)) {
277
+ return candidate.map(parseMatch).filter((value) => value !== null);
278
+ }
279
+ }
280
+ }
281
+ if (typeof output === "string") {
282
+ return output.split("\n").map((line) => line.trim()).filter(Boolean).map(parseMatch).filter((value) => value !== null);
283
+ }
284
+ return [];
285
+ }
286
+ var GrepResultsPreview = memo3(({ part }) => {
287
+ const pattern = extractPattern(part.state.input);
288
+ const matches = useMemo(() => extractMatches(part.state.output), [part.state.output]);
289
+ const groupedMatches = useMemo(() => {
290
+ const groups = /* @__PURE__ */ new Map();
291
+ for (const match of matches) {
292
+ const list = groups.get(match.path) ?? [];
293
+ list.push(match);
294
+ groups.set(match.path, list);
295
+ }
296
+ return [...groups.entries()];
297
+ }, [matches]);
298
+ return /* @__PURE__ */ jsxs4(
299
+ PreviewCard,
300
+ {
301
+ icon: /* @__PURE__ */ jsx4(Search, { className: "h-4 w-4" }),
302
+ title: pattern ? `Search results for "${pattern}"` : "Search results",
303
+ description: matches.length > 0 ? `${matches.length} match${matches.length === 1 ? "" : "es"}` : void 0,
304
+ children: [
305
+ part.state.status === "running" ? /* @__PURE__ */ jsx4(PreviewLoading, { label: "Searching files\u2026" }) : null,
306
+ part.state.error ? /* @__PURE__ */ jsx4(PreviewError, { error: part.state.error }) : null,
307
+ part.state.status === "completed" && matches.length === 0 ? /* @__PURE__ */ jsx4(PreviewEmpty, { label: "No matching files or lines were returned." }) : null,
308
+ groupedMatches.map(([path, pathMatches]) => /* @__PURE__ */ jsxs4(
309
+ "div",
310
+ {
311
+ className: "rounded-[var(--radius-md)] border border-[var(--border-subtle)] bg-[var(--bg-section)]/55",
312
+ children: [
313
+ /* @__PURE__ */ jsx4("div", { className: "border-b border-[var(--border-subtle)] px-3 py-2 text-xs font-medium text-[var(--text-secondary)]", children: path }),
314
+ /* @__PURE__ */ jsx4("div", { className: "divide-y divide-[var(--border-subtle)]", children: pathMatches.map((match, index) => /* @__PURE__ */ jsxs4("div", { className: "grid grid-cols-[auto_minmax(0,1fr)] gap-3 px-3 py-2", children: [
315
+ /* @__PURE__ */ jsx4("div", { className: "pt-0.5 text-xs font-mono text-[var(--text-muted)]", children: match.line ?? "\xB7" }),
316
+ /* @__PURE__ */ jsx4("pre", { className: "overflow-x-auto whitespace-pre-wrap break-words text-xs font-[var(--font-mono)] text-[var(--text-secondary)]", children: match.text })
317
+ ] }, `${path}-${match.line ?? index}-${index}`)) })
318
+ ]
319
+ },
320
+ path
321
+ ))
322
+ ]
323
+ }
324
+ );
325
+ });
326
+ GrepResultsPreview.displayName = "GrepResultsPreview";
327
+
328
+ // src/tool-previews/glob-results-preview.tsx
329
+ import { memo as memo4, useMemo as useMemo2 } from "react";
330
+ import { FileText, FolderOpen } from "lucide-react";
331
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
332
+ function coerceString2(value) {
333
+ return typeof value === "string" && value.trim() ? value : void 0;
334
+ }
335
+ function extractPattern2(input) {
336
+ if (!input || typeof input !== "object") {
337
+ return void 0;
338
+ }
339
+ const record = input;
340
+ return coerceString2(record.pattern) ?? coerceString2(record.path);
341
+ }
342
+ function extractFiles(output) {
343
+ if (Array.isArray(output)) {
344
+ return output.map((item) => String(item)).filter(Boolean);
345
+ }
346
+ if (output && typeof output === "object") {
347
+ const record = output;
348
+ const candidate = record.files ?? record.matches ?? record.paths ?? record.results;
349
+ if (Array.isArray(candidate)) {
350
+ return candidate.map(
351
+ (item) => typeof item === "string" ? item : item && typeof item === "object" ? String(
352
+ item.path ?? item.file ?? ""
353
+ ) : ""
354
+ ).filter(Boolean);
355
+ }
356
+ }
357
+ if (typeof output === "string") {
358
+ return output.split("\n").map((line) => line.trim()).filter(Boolean);
359
+ }
360
+ return [];
361
+ }
362
+ var GlobResultsPreview = memo4(({ part }) => {
363
+ const pattern = extractPattern2(part.state.input);
364
+ const files = useMemo2(() => extractFiles(part.state.output), [part.state.output]);
365
+ return /* @__PURE__ */ jsxs5(
366
+ PreviewCard,
367
+ {
368
+ icon: /* @__PURE__ */ jsx5(FolderOpen, { className: "h-4 w-4" }),
369
+ title: pattern ? `Files for ${pattern}` : "File results",
370
+ description: files.length > 0 ? `${files.length} path${files.length === 1 ? "" : "s"}` : void 0,
371
+ children: [
372
+ part.state.status === "running" ? /* @__PURE__ */ jsx5(PreviewLoading, { label: "Collecting files\u2026" }) : null,
373
+ part.state.error ? /* @__PURE__ */ jsx5(PreviewError, { error: part.state.error }) : null,
374
+ part.state.status === "completed" && files.length === 0 ? /* @__PURE__ */ jsx5(PreviewEmpty, { label: "No matching files were returned." }) : null,
375
+ files.length > 0 ? /* @__PURE__ */ jsx5("div", { className: "grid gap-2 sm:grid-cols-2", children: files.map((file) => {
376
+ const isDirectory = file.endsWith("/");
377
+ const Icon = isDirectory ? FolderOpen : FileText;
378
+ return /* @__PURE__ */ jsxs5(
379
+ "div",
380
+ {
381
+ className: "flex items-center gap-2 rounded-[var(--radius-md)] border border-[var(--border-subtle)] bg-[var(--bg-section)]/55 px-3 py-2",
382
+ children: [
383
+ /* @__PURE__ */ jsx5(Icon, { className: "h-4 w-4 shrink-0 text-[var(--brand-cool)]" }),
384
+ /* @__PURE__ */ jsx5("span", { className: "min-w-0 truncate text-xs font-[var(--font-mono)] text-[var(--text-secondary)]", children: file })
385
+ ]
386
+ },
387
+ file
388
+ );
389
+ }) }) : null
390
+ ]
391
+ }
392
+ );
393
+ });
394
+ GlobResultsPreview.displayName = "GlobResultsPreview";
395
+
396
+ // src/tool-previews/web-search-preview.tsx
397
+ import { memo as memo5, useMemo as useMemo3 } from "react";
398
+ import { Globe } from "lucide-react";
399
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
400
+ function coerceString3(value) {
401
+ return typeof value === "string" && value.trim() ? value : void 0;
402
+ }
403
+ function extractQuery(input, output) {
404
+ if (input && typeof input === "object") {
405
+ const record = input;
406
+ const query = coerceString3(record.query) ?? coerceString3(record.url);
407
+ if (query) return query;
408
+ }
409
+ if (output && typeof output === "object") {
410
+ const record = output;
411
+ return coerceString3(record.query);
412
+ }
413
+ return void 0;
414
+ }
415
+ function parseResult(value) {
416
+ if (!value || typeof value !== "object") {
417
+ return null;
418
+ }
419
+ const record = value;
420
+ const title = coerceString3(record.title) ?? coerceString3(record.name) ?? "Untitled result";
421
+ const url = coerceString3(record.url) ?? coerceString3(record.link);
422
+ if (!url) {
423
+ return null;
424
+ }
425
+ return {
426
+ title,
427
+ url,
428
+ snippet: coerceString3(record.snippet) ?? coerceString3(record.description) ?? coerceString3(record.text)
429
+ };
430
+ }
431
+ function extractResults(output) {
432
+ if (output && typeof output === "object") {
433
+ const record = output;
434
+ const candidate = record.results ?? record.items ?? record.output;
435
+ if (Array.isArray(candidate)) {
436
+ return candidate.map(parseResult).filter((value) => value !== null);
437
+ }
438
+ }
439
+ if (Array.isArray(output)) {
440
+ return output.map(parseResult).filter((value) => value !== null);
441
+ }
442
+ return [];
443
+ }
444
+ var WebSearchPreview = memo5(({ part }) => {
445
+ const query = extractQuery(part.state.input, part.state.output);
446
+ const results = useMemo3(() => extractResults(part.state.output), [part.state.output]);
447
+ return /* @__PURE__ */ jsxs6(
448
+ PreviewCard,
449
+ {
450
+ icon: /* @__PURE__ */ jsx6(Globe, { className: "h-4 w-4" }),
451
+ title: query ? `Web results for ${query}` : "Web results",
452
+ description: results.length > 0 ? `${results.length} result${results.length === 1 ? "" : "s"}` : void 0,
453
+ children: [
454
+ part.state.status === "running" ? /* @__PURE__ */ jsx6(PreviewLoading, { label: "Searching the web\u2026" }) : null,
455
+ part.state.error ? /* @__PURE__ */ jsx6(PreviewError, { error: part.state.error }) : null,
456
+ part.state.status === "completed" && results.length === 0 ? /* @__PURE__ */ jsx6(PreviewEmpty, { label: "No web results were returned." }) : null,
457
+ /* @__PURE__ */ jsx6("div", { className: "space-y-2", children: results.map((result) => /* @__PURE__ */ jsxs6(
458
+ "a",
459
+ {
460
+ href: result.url,
461
+ target: "_blank",
462
+ rel: "noreferrer",
463
+ className: "block rounded-[var(--radius-md)] border border-[var(--border-subtle)] bg-[var(--bg-section)]/55 px-3 py-3 transition-colors hover:border-[var(--border-accent-hover)] hover:bg-[var(--bg-hover)]/50",
464
+ children: [
465
+ /* @__PURE__ */ jsx6("div", { className: "text-sm font-medium text-[var(--text-primary)]", children: result.title }),
466
+ /* @__PURE__ */ jsx6("div", { className: "mt-1 truncate text-xs text-[var(--brand-cool)]", children: result.url }),
467
+ result.snippet ? /* @__PURE__ */ jsx6("p", { className: "mt-2 text-sm leading-relaxed text-[var(--text-muted)]", children: result.snippet }) : null
468
+ ]
469
+ },
470
+ result.url
471
+ )) })
472
+ ]
473
+ }
474
+ );
475
+ });
476
+ WebSearchPreview.displayName = "WebSearchPreview";
477
+
478
+ // src/tool-previews/question-preview.tsx
479
+ import { memo as memo6, useMemo as useMemo4 } from "react";
480
+ import { MessageSquareQuote } from "lucide-react";
481
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
482
+ function toQuestionList(input) {
483
+ if (!input) {
484
+ return [];
485
+ }
486
+ if (typeof input === "string") {
487
+ return [input];
488
+ }
489
+ if (Array.isArray(input)) {
490
+ return input.map((item) => String(item)).filter(Boolean);
491
+ }
492
+ if (typeof input === "object") {
493
+ const record = input;
494
+ const value = record.questions ?? record.question ?? record.prompt;
495
+ if (Array.isArray(value)) {
496
+ return value.map((item) => String(item)).filter(Boolean);
497
+ }
498
+ if (typeof value === "string") {
499
+ return [value];
500
+ }
501
+ }
502
+ return [];
503
+ }
504
+ function toAnswerList(output) {
505
+ if (!output) {
506
+ return [];
507
+ }
508
+ if (typeof output === "string") {
509
+ return [output];
510
+ }
511
+ if (Array.isArray(output)) {
512
+ return output.map((item) => String(item)).filter(Boolean);
513
+ }
514
+ if (typeof output === "object") {
515
+ const record = output;
516
+ const value = record.answers ?? record.answer ?? record.response;
517
+ if (Array.isArray(value)) {
518
+ return value.map((item) => String(item)).filter(Boolean);
519
+ }
520
+ if (typeof value === "string") {
521
+ return [value];
522
+ }
523
+ }
524
+ return [];
525
+ }
526
+ var QuestionPreview = memo6(({ part }) => {
527
+ const questions = useMemo4(() => toQuestionList(part.state.input), [part.state.input]);
528
+ const answers = useMemo4(() => toAnswerList(part.state.output), [part.state.output]);
529
+ return /* @__PURE__ */ jsxs7(
530
+ PreviewCard,
531
+ {
532
+ icon: /* @__PURE__ */ jsx7(MessageSquareQuote, { className: "h-4 w-4" }),
533
+ title: "Agent question",
534
+ description: questions.length > 1 ? `${questions.length} questions require attention` : void 0,
535
+ children: [
536
+ part.state.status === "running" ? /* @__PURE__ */ jsx7(PreviewLoading, { label: "Waiting for an answer\u2026" }) : null,
537
+ part.state.error ? /* @__PURE__ */ jsx7(PreviewError, { error: part.state.error }) : null,
538
+ questions.length === 0 ? /* @__PURE__ */ jsx7(PreviewEmpty, { label: "No question text was provided." }) : null,
539
+ questions.map((question, index) => /* @__PURE__ */ jsxs7(
540
+ "div",
541
+ {
542
+ className: "rounded-[var(--radius-md)] border border-[var(--border-subtle)] bg-[var(--bg-section)]/55 px-3 py-3",
543
+ children: [
544
+ /* @__PURE__ */ jsxs7("div", { className: "text-xs font-semibold uppercase tracking-[0.08em] text-[var(--text-muted)]", children: [
545
+ "Question ",
546
+ index + 1
547
+ ] }),
548
+ /* @__PURE__ */ jsx7("div", { className: "mt-2 text-sm leading-relaxed text-[var(--text-primary)]", children: question }),
549
+ /* @__PURE__ */ jsx7("div", { className: "mt-3 rounded-[var(--radius-sm)] border border-[var(--border-subtle)] bg-[var(--bg-card)] px-3 py-2 text-sm text-[var(--text-secondary)]", children: answers[index] ?? (part.state.status === "completed" ? "No answer recorded." : "Awaiting answer") })
550
+ ]
551
+ },
552
+ `${question}-${index}`
553
+ ))
554
+ ]
555
+ }
556
+ );
557
+ });
558
+ QuestionPreview.displayName = "QuestionPreview";
559
+
560
+ // src/tool-previews/diff-preview.tsx
561
+ import { memo as memo7 } from "react";
562
+ import { GitCompareArrows } from "lucide-react";
563
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
564
+ function extractString(record, ...keys) {
565
+ for (const key of keys) {
566
+ const value = record[key];
567
+ if (typeof value === "string" && value.length > 0) {
568
+ return value;
569
+ }
570
+ }
571
+ return void 0;
572
+ }
573
+ function extractDiffPayload(part) {
574
+ const sources = [part.state.input, part.state.output, part.state.metadata];
575
+ for (const source of sources) {
576
+ if (!source || typeof source !== "object") {
577
+ continue;
578
+ }
579
+ const record = source;
580
+ const diff = extractString(record, "diff", "patch", "unifiedDiff", "unified_diff");
581
+ const before = extractString(record, "oldString", "old_string", "before", "previous");
582
+ const after = extractString(record, "newString", "new_string", "after", "updated");
583
+ const path = extractString(record, "file_path", "filePath", "path");
584
+ if (diff || before || after) {
585
+ return { path, diff, before, after };
586
+ }
587
+ }
588
+ return {};
589
+ }
590
+ var DiffPreview = memo7(({ part }) => {
591
+ const payload = extractDiffPayload(part);
592
+ return /* @__PURE__ */ jsxs8(
593
+ PreviewCard,
594
+ {
595
+ icon: /* @__PURE__ */ jsx8(GitCompareArrows, { className: "h-4 w-4" }),
596
+ title: payload.path ? `Changes for ${payload.path}` : "File changes",
597
+ children: [
598
+ part.state.status === "running" ? /* @__PURE__ */ jsx8(PreviewLoading, { label: "Computing changes\u2026" }) : null,
599
+ part.state.error ? /* @__PURE__ */ jsx8(PreviewError, { error: part.state.error }) : null,
600
+ !payload.diff && !payload.before && !payload.after ? /* @__PURE__ */ jsx8(PreviewEmpty, { label: "No structured diff payload was provided." }) : null,
601
+ payload.diff ? /* @__PURE__ */ jsx8(CodeBlock, { code: payload.diff, language: "diff", className: "rounded-[var(--radius-md)]" }) : null,
602
+ !payload.diff && payload.before ? /* @__PURE__ */ jsxs8("div", { className: "space-y-2", children: [
603
+ /* @__PURE__ */ jsx8("div", { className: "text-xs font-semibold uppercase tracking-[0.08em] text-[var(--text-muted)]", children: "Before" }),
604
+ /* @__PURE__ */ jsx8(CodeBlock, { code: payload.before, language: "text", className: "rounded-[var(--radius-md)]" })
605
+ ] }) : null,
606
+ !payload.diff && payload.after ? /* @__PURE__ */ jsxs8("div", { className: "space-y-2", children: [
607
+ /* @__PURE__ */ jsx8("div", { className: "text-xs font-semibold uppercase tracking-[0.08em] text-[var(--text-muted)]", children: "After" }),
608
+ /* @__PURE__ */ jsx8(CodeBlock, { code: payload.after, language: "text", className: "rounded-[var(--radius-md)]" })
609
+ ] }) : null
610
+ ]
611
+ }
612
+ );
613
+ });
614
+ DiffPreview.displayName = "DiffPreview";
615
+
616
+ // src/run/expanded-tool-detail.tsx
617
+ import { memo as memo8 } from "react";
618
+ import {
619
+ ArrowRight,
620
+ ArrowLeft,
621
+ AlertCircle,
622
+ Loader2 as Loader23,
623
+ FileText as FileText2
624
+ } from "lucide-react";
625
+ import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
626
+ function formatOutput(value) {
627
+ if (value == null) return "";
628
+ if (typeof value === "string") return value;
629
+ try {
630
+ return JSON.stringify(value, null, 2);
631
+ } catch {
632
+ return String(value);
633
+ }
634
+ }
635
+ var ExpandedToolDetail = memo8(({ part }) => {
636
+ const meta = getToolDisplayMetadata(part);
637
+ const { status, input, output, error } = part.state;
638
+ if (meta.displayVariant === "command") {
639
+ return /* @__PURE__ */ jsx9(CommandPreview, { part });
640
+ }
641
+ if (meta.displayVariant === "write-file") {
642
+ return /* @__PURE__ */ jsx9(WriteFilePreview, { part });
643
+ }
644
+ if (meta.displayVariant === "grep") {
645
+ return /* @__PURE__ */ jsx9(GrepResultsPreview, { part });
646
+ }
647
+ if (meta.displayVariant === "glob") {
648
+ return /* @__PURE__ */ jsx9(GlobResultsPreview, { part });
649
+ }
650
+ if (meta.displayVariant === "web-search") {
651
+ return /* @__PURE__ */ jsx9(WebSearchPreview, { part });
652
+ }
653
+ if (meta.displayVariant === "question") {
654
+ return /* @__PURE__ */ jsx9(QuestionPreview, { part });
655
+ }
656
+ if (meta.displayVariant === "diff") {
657
+ return /* @__PURE__ */ jsx9(DiffPreview, { part });
658
+ }
659
+ if (meta.displayVariant === "read-file") {
660
+ return /* @__PURE__ */ jsxs9("div", { className: "overflow-hidden rounded-[var(--radius-lg)] border border-[var(--border-subtle)] bg-[var(--bg-card)] shadow-[var(--shadow-card)]", children: [
661
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3 border-b border-[var(--border-subtle)] bg-[var(--bg-elevated)]/70 px-4 py-3", children: [
662
+ /* @__PURE__ */ jsx9("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-[var(--radius-md)] border border-[var(--border-accent)] bg-[var(--bg-section)] text-[var(--brand-cool)]", children: /* @__PURE__ */ jsx9(FileText2, { className: "h-4 w-4" }) }),
663
+ /* @__PURE__ */ jsxs9("div", { className: "min-w-0", children: [
664
+ /* @__PURE__ */ jsx9("div", { className: "text-sm font-semibold text-[var(--text-primary)]", children: "Read file" }),
665
+ meta.targetPath ? /* @__PURE__ */ jsx9("div", { className: "mt-1 text-xs text-[var(--text-muted)]", children: meta.targetPath }) : null
666
+ ] })
667
+ ] }),
668
+ /* @__PURE__ */ jsxs9("div", { className: "space-y-3 px-4 py-4", children: [
669
+ typeof output === "string" ? /* @__PURE__ */ jsx9(CodeBlock, { code: output, language: "text", className: "rounded-[var(--radius-md)]" }) : /* @__PURE__ */ jsx9("div", { className: "rounded-[var(--radius-md)] border border-dashed border-[var(--border-subtle)] bg-[var(--bg-section)]/60 px-3 py-4 text-sm text-[var(--text-muted)]", children: "No readable file content was returned." }),
670
+ error ? /* @__PURE__ */ jsx9("div", { className: "rounded-[var(--radius-md)] border border-red-500/30 bg-red-500/8 px-3 py-3 text-sm text-red-200", children: error }) : null
671
+ ] })
672
+ ] });
673
+ }
674
+ const inputStr = formatOutput(input);
675
+ const outputStr = formatOutput(output);
676
+ return /* @__PURE__ */ jsxs9("div", { className: "space-y-3", children: [
677
+ inputStr && /* @__PURE__ */ jsxs9("div", { className: "overflow-hidden rounded-[var(--radius-lg)] border border-[var(--border-subtle)] bg-[var(--bg-card)]", children: [
678
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2 border-b border-[var(--border-subtle)] bg-[var(--bg-elevated)]/70 px-3 py-2", children: [
679
+ /* @__PURE__ */ jsx9(ArrowRight, { className: "h-3 w-3 text-[var(--brand-cool)]" }),
680
+ /* @__PURE__ */ jsx9("span", { className: "text-xs font-medium uppercase tracking-[0.08em] text-[var(--text-muted)]", children: "Input" })
681
+ ] }),
682
+ /* @__PURE__ */ jsx9(CodeBlock, { code: inputStr, language: "json", className: "rounded-none border-0" })
683
+ ] }),
684
+ status === "completed" && outputStr && /* @__PURE__ */ jsxs9("div", { className: "overflow-hidden rounded-[var(--radius-lg)] border border-[var(--border-subtle)] bg-[var(--bg-card)]", children: [
685
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2 border-b border-[var(--border-subtle)] bg-[var(--bg-elevated)]/70 px-3 py-2", children: [
686
+ /* @__PURE__ */ jsx9(ArrowLeft, { className: "h-3 w-3 text-[var(--brand-cool)]" }),
687
+ /* @__PURE__ */ jsx9("span", { className: "text-xs font-medium uppercase tracking-[0.08em] text-[var(--text-muted)]", children: "Output" })
688
+ ] }),
689
+ /* @__PURE__ */ jsx9(
690
+ CodeBlock,
691
+ {
692
+ code: outputStr.length > 2e3 ? outputStr.slice(0, 2e3) + "\n...(truncated)" : outputStr,
693
+ language: "json",
694
+ className: "rounded-none border-0"
695
+ }
696
+ )
697
+ ] }),
698
+ error && /* @__PURE__ */ jsxs9("div", { className: "overflow-hidden rounded-[var(--radius-lg)] border border-red-500/30", children: [
699
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2 border-b border-red-500/20 bg-red-500/10 px-3 py-2", children: [
700
+ /* @__PURE__ */ jsx9(AlertCircle, { className: "h-3 w-3 text-red-300" }),
701
+ /* @__PURE__ */ jsx9("span", { className: "text-xs font-medium uppercase tracking-[0.08em] text-red-200", children: "Error" })
702
+ ] }),
703
+ /* @__PURE__ */ jsx9("pre", { className: "bg-red-500/6 p-3 text-xs font-[var(--font-mono)] whitespace-pre-wrap break-all text-red-100", children: error })
704
+ ] }),
705
+ (status === "pending" || status === "running") && /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2 rounded-[var(--radius-md)] border border-[var(--border-subtle)] bg-[var(--bg-section)]/60 px-3 py-3 text-xs text-[var(--text-muted)]", children: [
706
+ /* @__PURE__ */ jsx9(Loader23, { className: cn("h-3 w-3 animate-spin text-[var(--brand-cool)]") }),
707
+ "Running\u2026"
708
+ ] })
709
+ ] });
710
+ });
711
+ ExpandedToolDetail.displayName = "ExpandedToolDetail";
712
+
713
+ // src/run/run-item-primitives.tsx
714
+ import { useEffect, useState as useState2 } from "react";
715
+ import { jsx as jsx10 } from "react/jsx-runtime";
716
+ function LiveDuration({ startTime }) {
717
+ const [elapsed, setElapsed] = useState2(Date.now() - startTime);
718
+ useEffect(() => {
719
+ const id = setInterval(() => setElapsed(Date.now() - startTime), 100);
720
+ return () => clearInterval(id);
721
+ }, [startTime]);
722
+ return /* @__PURE__ */ jsx10("span", { className: "text-xs font-mono text-neutral-400 dark:text-neutral-500 tabular-nums", children: formatDuration(elapsed) });
723
+ }
724
+
725
+ // src/run/inline-tool-item.tsx
726
+ import { memo as memo9, useState as useState3 } from "react";
727
+ import * as Collapsible from "@radix-ui/react-collapsible";
728
+ import {
729
+ Loader2 as Loader24,
730
+ CheckCircle2,
731
+ AlertCircle as AlertCircle2,
732
+ ChevronDown as ChevronDown2,
733
+ ChevronRight as ChevronRight2,
734
+ Terminal as Terminal2,
735
+ FileEdit as FileEdit2,
736
+ FileSearch,
737
+ Search as Search2,
738
+ PencilLine,
739
+ Bot,
740
+ Globe as Globe2,
741
+ ClipboardList,
742
+ Settings
743
+ } from "lucide-react";
744
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
745
+ var TOOL_CATEGORY_ICON_MAP = {
746
+ command: Terminal2,
747
+ write: FileEdit2,
748
+ read: FileSearch,
749
+ search: Search2,
750
+ edit: PencilLine,
751
+ task: Bot,
752
+ web: Globe2,
753
+ todo: ClipboardList,
754
+ other: Settings
755
+ };
756
+ var InlineToolItem = memo9(
757
+ ({
758
+ part,
759
+ renderToolDetail,
760
+ groupPosition = "single",
761
+ className,
762
+ contentClassName
763
+ }) => {
764
+ const [open, setOpen] = useState3(false);
765
+ const meta = getToolDisplayMetadata(part);
766
+ const { status } = part.state;
767
+ const errorText = getToolErrorText(part);
768
+ const isRunning = status === "pending" || status === "running";
769
+ const isError = status === "error";
770
+ const isComplete = status === "completed";
771
+ const startTime = part.state.time?.start;
772
+ const endTime = part.state.time?.end;
773
+ const durationMs = startTime && endTime ? endTime - startTime : void 0;
774
+ const category = getToolCategory(part.tool);
775
+ const DefaultIcon = TOOL_CATEGORY_ICON_MAP[category] ?? Settings;
776
+ const shapeClass = {
777
+ single: "rounded-[var(--radius-lg)]",
778
+ first: "rounded-t-[var(--radius-lg)] rounded-b-[var(--radius-sm)]",
779
+ middle: "rounded-[var(--radius-sm)]",
780
+ last: "rounded-t-[var(--radius-sm)] rounded-b-[var(--radius-lg)]"
781
+ }[groupPosition];
782
+ return /* @__PURE__ */ jsxs10(Collapsible.Root, { open, onOpenChange: setOpen, children: [
783
+ /* @__PURE__ */ jsx11(Collapsible.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs10(
784
+ "button",
785
+ {
786
+ className: cn(
787
+ "w-full border text-left transition-colors",
788
+ "border-[var(--border-subtle)] bg-[var(--bg-card)] hover:border-[var(--border-accent-hover)] hover:bg-[var(--bg-hover)]/35",
789
+ open && "border-[var(--border-accent)] bg-[var(--bg-hover)]/30",
790
+ shapeClass,
791
+ className
792
+ ),
793
+ children: [
794
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-3 px-3 py-3", children: [
795
+ /* @__PURE__ */ jsx11(
796
+ "div",
797
+ {
798
+ className: cn(
799
+ "flex h-8 w-8 shrink-0 items-center justify-center rounded-[var(--radius-md)] border",
800
+ isRunning && "border-[var(--border-accent)] bg-[var(--brand-cool)]/12 text-[var(--brand-cool)]",
801
+ isComplete && "border-emerald-500/30 bg-emerald-500/12 text-emerald-200",
802
+ isError && "border-red-500/30 bg-red-500/10 text-red-200",
803
+ !isRunning && !isComplete && !isError && "border-[var(--border-subtle)] bg-[var(--bg-section)] text-[var(--text-muted)]"
804
+ ),
805
+ children: isRunning ? /* @__PURE__ */ jsx11(Loader24, { className: "h-4 w-4 animate-spin" }) : isComplete ? /* @__PURE__ */ jsx11(CheckCircle2, { className: "h-4 w-4" }) : isError ? /* @__PURE__ */ jsx11(AlertCircle2, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx11(DefaultIcon, { className: "h-4 w-4" })
806
+ }
807
+ ),
808
+ /* @__PURE__ */ jsxs10("div", { className: "min-w-0 flex-1", children: [
809
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2", children: [
810
+ /* @__PURE__ */ jsx11("span", { className: "truncate text-sm font-medium text-[var(--text-primary)]", children: meta.title }),
811
+ isError ? /* @__PURE__ */ jsx11("span", { className: "rounded-full border border-red-500/30 bg-red-500/10 px-2 py-0.5 text-[11px] font-semibold uppercase tracking-[0.06em] text-red-200", children: "Failed" }) : null,
812
+ isRunning ? /* @__PURE__ */ jsx11("span", { className: "rounded-full border border-[var(--border-accent)] bg-[var(--brand-cool)]/10 px-2 py-0.5 text-[11px] font-semibold uppercase tracking-[0.06em] text-[var(--brand-cool)]", children: "Running" }) : null
813
+ ] }),
814
+ meta.description ? /* @__PURE__ */ jsx11("div", { className: "mt-1 truncate text-xs font-[var(--font-mono)] text-[var(--text-muted)]", children: meta.description }) : null
815
+ ] }),
816
+ /* @__PURE__ */ jsxs10("div", { className: "flex shrink-0 items-center gap-2", children: [
817
+ isRunning && startTime ? /* @__PURE__ */ jsx11(LiveDuration, { startTime }) : null,
818
+ !isRunning && durationMs != null ? /* @__PURE__ */ jsx11("span", { className: "rounded-full border border-[var(--border-subtle)] bg-[var(--bg-section)] px-2 py-0.5 text-[11px] font-[var(--font-mono)] text-[var(--text-muted)]", children: formatDuration(durationMs) }) : null,
819
+ open ? /* @__PURE__ */ jsx11(ChevronDown2, { className: "h-3.5 w-3.5 text-[var(--text-muted)]" }) : /* @__PURE__ */ jsx11(ChevronRight2, { className: "h-3.5 w-3.5 text-[var(--text-muted)]" })
820
+ ] })
821
+ ] }),
822
+ errorText && !open ? /* @__PURE__ */ jsx11("div", { className: "border-t border-[var(--border-subtle)] px-3 py-2 text-xs text-red-200", children: errorText }) : null
823
+ ]
824
+ }
825
+ ) }),
826
+ /* @__PURE__ */ jsx11(Collapsible.Content, { className: "overflow-hidden data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp", children: /* @__PURE__ */ jsx11("div", { className: cn("mt-2 pl-4", contentClassName), children: renderToolDetail?.(part) ?? /* @__PURE__ */ jsx11(ExpandedToolDetail, { part }) }) })
827
+ ] });
828
+ }
829
+ );
830
+ InlineToolItem.displayName = "InlineToolItem";
831
+
832
+ // src/run/inline-thinking-item.tsx
833
+ import { memo as memo10, useEffect as useEffect2, useRef, useState as useState4 } from "react";
834
+ import * as Collapsible2 from "@radix-ui/react-collapsible";
835
+ import { Brain, ChevronDown as ChevronDown3, ChevronRight as ChevronRight3 } from "lucide-react";
836
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
837
+ var InlineThinkingItem = memo10(
838
+ ({
839
+ part,
840
+ defaultOpen = false,
841
+ autoCollapse = true,
842
+ className,
843
+ contentClassName
844
+ }) => {
845
+ const [open, setOpen] = useState4(defaultOpen);
846
+ const autoCollapsedRef = useRef(false);
847
+ const startTime = part.time?.start;
848
+ const endTime = part.time?.end;
849
+ const durationMs = startTime && endTime ? endTime - startTime : void 0;
850
+ const isActive = startTime != null && endTime == null;
851
+ const preview = part.text ? truncateText(part.text, 120) : void 0;
852
+ useEffect2(() => {
853
+ if (isActive) {
854
+ autoCollapsedRef.current = false;
855
+ setOpen(true);
856
+ return;
857
+ }
858
+ if (autoCollapse && !autoCollapsedRef.current && durationMs != null) {
859
+ const timer = window.setTimeout(() => {
860
+ setOpen(false);
861
+ autoCollapsedRef.current = true;
862
+ }, 900);
863
+ return () => window.clearTimeout(timer);
864
+ }
865
+ }, [autoCollapse, durationMs, isActive]);
866
+ return /* @__PURE__ */ jsxs11(Collapsible2.Root, { open, onOpenChange: setOpen, children: [
867
+ /* @__PURE__ */ jsx12(Collapsible2.Trigger, { asChild: true, children: /* @__PURE__ */ jsx12(
868
+ "button",
869
+ {
870
+ className: cn(
871
+ "w-full rounded-[var(--radius-lg)] border border-[var(--border-subtle)] bg-[var(--bg-card)] text-left transition-colors",
872
+ "hover:border-[var(--border-accent-hover)] hover:bg-[var(--bg-hover)]/35",
873
+ open && "border-[var(--border-accent)] bg-[var(--bg-hover)]/30",
874
+ className
875
+ ),
876
+ children: /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-3 px-3 py-3", children: [
877
+ /* @__PURE__ */ jsx12(
878
+ "div",
879
+ {
880
+ className: cn(
881
+ "flex h-8 w-8 shrink-0 items-center justify-center rounded-[var(--radius-md)] border",
882
+ isActive ? "border-[var(--border-accent)] bg-[var(--accent-surface-soft)] text-[var(--accent-text)] shadow-[var(--shadow-glow)]" : "border-[var(--border-subtle)] bg-[var(--bg-section)] text-[var(--text-muted)]"
883
+ ),
884
+ children: /* @__PURE__ */ jsx12(Brain, { className: cn("h-4 w-4", isActive && "animate-pulse") })
885
+ }
886
+ ),
887
+ /* @__PURE__ */ jsxs11("div", { className: "min-w-0 flex-1", children: [
888
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
889
+ /* @__PURE__ */ jsx12("span", { className: "text-sm font-medium text-[var(--text-primary)]", children: isActive ? "Thinking\u2026" : "Reasoning" }),
890
+ !isActive && durationMs != null ? /* @__PURE__ */ jsx12("span", { className: "rounded-full border border-[var(--border-subtle)] bg-[var(--bg-section)] px-2 py-0.5 text-[11px] font-[var(--font-mono)] text-[var(--text-muted)]", children: formatDuration(durationMs) }) : null,
891
+ isActive && startTime ? /* @__PURE__ */ jsx12(LiveDuration, { startTime }) : null
892
+ ] }),
893
+ preview && !open ? /* @__PURE__ */ jsx12("div", { className: "mt-1 truncate text-xs text-[var(--text-muted)]", children: preview }) : null
894
+ ] }),
895
+ open ? /* @__PURE__ */ jsx12(ChevronDown3, { className: "h-3.5 w-3.5 shrink-0 text-[var(--text-muted)]" }) : /* @__PURE__ */ jsx12(ChevronRight3, { className: "h-3.5 w-3.5 shrink-0 text-[var(--text-muted)]" })
896
+ ] })
897
+ }
898
+ ) }),
899
+ /* @__PURE__ */ jsx12(Collapsible2.Content, { className: "overflow-hidden data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp", children: part.text ? /* @__PURE__ */ jsx12(
900
+ "div",
901
+ {
902
+ className: cn(
903
+ "border-t border-[var(--border-subtle)] px-4 py-4 text-sm text-[var(--text-secondary)]",
904
+ contentClassName
905
+ ),
906
+ children: /* @__PURE__ */ jsx12(Markdown, { children: part.text })
907
+ }
908
+ ) : /* @__PURE__ */ jsx12("div", { className: "border-t border-[var(--border-subtle)] px-4 py-3 text-sm text-[var(--text-muted)]", children: "No reasoning text was provided." }) })
909
+ ] });
910
+ }
911
+ );
912
+ InlineThinkingItem.displayName = "InlineThinkingItem";
913
+
914
+ // src/run/run-group.tsx
915
+ import { memo as memo11, useMemo as useMemo5 } from "react";
916
+ import * as Collapsible3 from "@radix-ui/react-collapsible";
917
+ import {
918
+ Bot as Bot2,
919
+ Loader2 as Loader25,
920
+ ChevronDown as ChevronDown4,
921
+ ChevronRight as ChevronRight4,
922
+ Terminal as Terminal3,
923
+ FileEdit as FileEdit3,
924
+ FileSearch as FileSearch2,
925
+ Search as Search3,
926
+ PencilLine as PencilLine2,
927
+ Globe as Globe3,
928
+ ClipboardList as ClipboardList2,
929
+ Settings as Settings2,
930
+ Sparkles
931
+ } from "lucide-react";
932
+ import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
933
+ var DEFAULT_BRANDING = {
934
+ label: "Agent",
935
+ accentClass: "text-[var(--brand-cool)]",
936
+ bgClass: "bg-[var(--brand-cool)]/8",
937
+ containerBgClass: "bg-[var(--bg-section)]/60",
938
+ borderClass: "border-[var(--border-accent)]",
939
+ iconClass: "",
940
+ textClass: "text-[var(--brand-cool)]"
941
+ };
942
+ var CATEGORY_ICON_MAP = {
943
+ command: Terminal3,
944
+ write: FileEdit3,
945
+ read: FileSearch2,
946
+ search: Search3,
947
+ edit: PencilLine2,
948
+ task: Bot2,
949
+ web: Globe3,
950
+ todo: ClipboardList2,
951
+ other: Settings2
952
+ };
953
+ var CATEGORY_ORDER = [
954
+ "command",
955
+ "write",
956
+ "edit",
957
+ "read",
958
+ "search",
959
+ "web",
960
+ "task",
961
+ "todo",
962
+ "other"
963
+ ];
964
+ function CategoryBadges({ categories }) {
965
+ const sorted = useMemo5(
966
+ () => CATEGORY_ORDER.filter((category) => categories.has(category)),
967
+ [categories]
968
+ );
969
+ if (sorted.length === 0) return null;
970
+ return /* @__PURE__ */ jsx13("div", { className: "flex items-center gap-1", children: sorted.map((cat) => {
971
+ const Icon = CATEGORY_ICON_MAP[cat] ?? Settings2;
972
+ return /* @__PURE__ */ jsx13(
973
+ "span",
974
+ {
975
+ title: cat,
976
+ className: "flex h-6 w-6 items-center justify-center rounded-full border border-[var(--border-subtle)] bg-[var(--bg-section)] text-[var(--text-muted)]",
977
+ children: /* @__PURE__ */ jsx13(Icon, { className: "h-3.5 w-3.5" })
978
+ },
979
+ cat
980
+ );
981
+ }) });
982
+ }
983
+ function renderSummary(run) {
984
+ const parts = [];
985
+ if (run.stats.toolCount > 0) {
986
+ parts.push(`${run.stats.toolCount} tool${run.stats.toolCount === 1 ? "" : "s"}`);
987
+ }
988
+ if (run.stats.textPartCount > 0) {
989
+ parts.push(`${run.stats.textPartCount} response${run.stats.textPartCount === 1 ? "" : "s"}`);
990
+ }
991
+ if (run.stats.thinkingDurationMs > 0) {
992
+ parts.push(`${formatDuration(run.stats.thinkingDurationMs)} thinking`);
993
+ }
994
+ return parts.join(", ");
995
+ }
996
+ function getToolGroupPosition(currentIndex, parts) {
997
+ const previous = parts[currentIndex - 1]?.part;
998
+ const next = parts[currentIndex + 1]?.part;
999
+ const previousIsTool = previous?.type === "tool";
1000
+ const nextIsTool = next?.type === "tool";
1001
+ if (previousIsTool && nextIsTool) return "middle";
1002
+ if (previousIsTool) return "last";
1003
+ if (nextIsTool) return "first";
1004
+ return "single";
1005
+ }
1006
+ var RunGroup = memo11(
1007
+ ({
1008
+ run,
1009
+ partMap,
1010
+ collapsed,
1011
+ onToggle,
1012
+ branding = DEFAULT_BRANDING,
1013
+ renderToolDetail
1014
+ }) => {
1015
+ const allParts = useMemo5(() => {
1016
+ const parts = [];
1017
+ for (const msg of run.messages) {
1018
+ const msgParts = partMap[msg.id] ?? [];
1019
+ msgParts.forEach((part, index) => {
1020
+ parts.push({ part, msgId: msg.id, index });
1021
+ });
1022
+ }
1023
+ return parts;
1024
+ }, [run.messages, partMap]);
1025
+ const { stats, isStreaming } = run;
1026
+ const hasRenderableParts = allParts.some(({ part }) => {
1027
+ if (part.type === "tool" || part.type === "reasoning") {
1028
+ return true;
1029
+ }
1030
+ return part.type === "text" && !part.synthetic && part.text.trim().length > 0;
1031
+ });
1032
+ if (!hasRenderableParts) {
1033
+ return null;
1034
+ }
1035
+ return /* @__PURE__ */ jsxs12(Collapsible3.Root, { open: !collapsed, onOpenChange: () => onToggle(), children: [
1036
+ /* @__PURE__ */ jsx13(Collapsible3.Trigger, { asChild: true, children: /* @__PURE__ */ jsx13(
1037
+ "button",
1038
+ {
1039
+ className: cn(
1040
+ "w-full rounded-[var(--radius-xl)] border px-4 py-3 text-left transition-colors",
1041
+ "bg-[var(--bg-card)] hover:bg-[var(--bg-hover)]/28",
1042
+ collapsed ? branding.borderClass : "border-[var(--border-subtle)]",
1043
+ branding.bgClass
1044
+ ),
1045
+ children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-3", children: [
1046
+ /* @__PURE__ */ jsx13(
1047
+ "div",
1048
+ {
1049
+ className: cn(
1050
+ "flex h-10 w-10 shrink-0 items-center justify-center rounded-[var(--radius-lg)] border bg-[var(--bg-section)]",
1051
+ branding.borderClass
1052
+ ),
1053
+ children: /* @__PURE__ */ jsx13(Bot2, { className: cn("h-4 w-4", branding.accentClass) })
1054
+ }
1055
+ ),
1056
+ /* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1", children: [
1057
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
1058
+ /* @__PURE__ */ jsx13("span", { className: cn("text-sm font-semibold", branding.textClass), children: branding.label }),
1059
+ isStreaming ? /* @__PURE__ */ jsxs12("span", { className: "inline-flex items-center gap-1 rounded-full border border-[var(--border-accent)] bg-[var(--brand-cool)]/10 px-2 py-0.5 text-[11px] font-semibold uppercase tracking-[0.08em] text-[var(--brand-cool)]", children: [
1060
+ /* @__PURE__ */ jsx13(Loader25, { className: "h-3 w-3 animate-spin" }),
1061
+ "Running"
1062
+ ] }) : /* @__PURE__ */ jsxs12("span", { className: "inline-flex items-center gap-1 rounded-full border border-[var(--border-subtle)] bg-[var(--bg-section)] px-2 py-0.5 text-[11px] font-semibold uppercase tracking-[0.08em] text-[var(--text-muted)]", children: [
1063
+ /* @__PURE__ */ jsx13(Sparkles, { className: "h-3 w-3" }),
1064
+ "Complete"
1065
+ ] })
1066
+ ] }),
1067
+ /* @__PURE__ */ jsxs12("div", { className: "mt-1 flex flex-wrap items-center gap-2 text-xs text-[var(--text-muted)]", children: [
1068
+ renderSummary(run) ? /* @__PURE__ */ jsx13("span", { children: renderSummary(run) }) : null,
1069
+ collapsed && run.summaryText ? /* @__PURE__ */ jsx13("span", { className: "min-w-0 truncate text-[var(--text-secondary)]", children: run.summaryText }) : null
1070
+ ] })
1071
+ ] }),
1072
+ /* @__PURE__ */ jsx13(CategoryBadges, { categories: stats.toolCategories }),
1073
+ !collapsed ? /* @__PURE__ */ jsx13(ChevronDown4, { className: "h-4 w-4 shrink-0 text-[var(--text-muted)]" }) : /* @__PURE__ */ jsx13(ChevronRight4, { className: "h-4 w-4 shrink-0 text-[var(--text-muted)]" })
1074
+ ] })
1075
+ }
1076
+ ) }),
1077
+ collapsed && run.summaryText && /* @__PURE__ */ jsx13("div", { className: "px-4 py-2 text-sm text-[var(--text-muted)] line-clamp-2", children: run.summaryText }),
1078
+ /* @__PURE__ */ jsx13(Collapsible3.Content, { className: "overflow-hidden data-[state=open]:animate-slideDown data-[state=closed]:animate-slideUp", children: /* @__PURE__ */ jsx13(
1079
+ "div",
1080
+ {
1081
+ className: cn(
1082
+ "mt-2 space-y-2 rounded-[var(--radius-xl)] border border-[var(--border-subtle)] p-3",
1083
+ branding.containerBgClass
1084
+ ),
1085
+ children: allParts.map(({ part, msgId, index }, partIndex) => {
1086
+ const key = `${msgId}-${index}`;
1087
+ if (part.type === "tool") {
1088
+ return /* @__PURE__ */ jsx13(
1089
+ InlineToolItem,
1090
+ {
1091
+ part,
1092
+ renderToolDetail,
1093
+ groupPosition: getToolGroupPosition(partIndex, allParts)
1094
+ },
1095
+ key
1096
+ );
1097
+ }
1098
+ if (part.type === "reasoning") {
1099
+ return /* @__PURE__ */ jsx13(
1100
+ InlineThinkingItem,
1101
+ {
1102
+ part,
1103
+ defaultOpen: isStreaming
1104
+ },
1105
+ key
1106
+ );
1107
+ }
1108
+ if (part.type === "text" && !part.synthetic && part.text.trim()) {
1109
+ return /* @__PURE__ */ jsx13(
1110
+ "div",
1111
+ {
1112
+ className: "rounded-[var(--radius-lg)] border border-[var(--border-subtle)] bg-[var(--bg-card)] px-4 py-4",
1113
+ children: /* @__PURE__ */ jsx13(Markdown, { children: part.text })
1114
+ },
1115
+ key
1116
+ );
1117
+ }
1118
+ return null;
1119
+ })
1120
+ }
1121
+ ) })
1122
+ ] });
1123
+ }
1124
+ );
1125
+ RunGroup.displayName = "RunGroup";
1126
+
1127
+ export {
1128
+ CommandPreview,
1129
+ WriteFilePreview,
1130
+ GrepResultsPreview,
1131
+ GlobResultsPreview,
1132
+ WebSearchPreview,
1133
+ QuestionPreview,
1134
+ DiffPreview,
1135
+ ExpandedToolDetail,
1136
+ LiveDuration,
1137
+ InlineToolItem,
1138
+ InlineThinkingItem,
1139
+ RunGroup
1140
+ };