fleetlens 0.2.9 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/app/apps/web/.next/BUILD_ID +1 -1
  2. package/app/apps/web/.next/build-manifest.json +3 -3
  3. package/app/apps/web/.next/prerender-manifest.json +3 -3
  4. package/app/apps/web/.next/server/app/_global-error.html +1 -1
  5. package/app/apps/web/.next/server/app/_global-error.rsc +1 -1
  6. package/app/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  7. package/app/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  8. package/app/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  9. package/app/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  10. package/app/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  11. package/app/apps/web/.next/server/app/_not-found/page.js +1 -1
  12. package/app/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  13. package/app/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  14. package/app/apps/web/.next/server/app/page.js +3 -3
  15. package/app/apps/web/.next/server/app/page.js.nft.json +1 -1
  16. package/app/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  17. package/app/apps/web/.next/server/app/parallelism/page.js +1 -1
  18. package/app/apps/web/.next/server/app/parallelism/page.js.nft.json +1 -1
  19. package/app/apps/web/.next/server/app/parallelism/page_client-reference-manifest.js +1 -1
  20. package/app/apps/web/.next/server/app/projects/[slug]/page.js +3 -3
  21. package/app/apps/web/.next/server/app/projects/[slug]/page.js.nft.json +1 -1
  22. package/app/apps/web/.next/server/app/projects/[slug]/page_client-reference-manifest.js +1 -1
  23. package/app/apps/web/.next/server/app/projects/page.js +1 -1
  24. package/app/apps/web/.next/server/app/projects/page.js.nft.json +1 -1
  25. package/app/apps/web/.next/server/app/projects/page_client-reference-manifest.js +1 -1
  26. package/app/apps/web/.next/server/app/sessions/[id]/page.js +3 -2
  27. package/app/apps/web/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
  28. package/app/apps/web/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
  29. package/app/apps/web/.next/server/app/sessions/page.js +1 -1
  30. package/app/apps/web/.next/server/app/sessions/page.js.nft.json +1 -1
  31. package/app/apps/web/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
  32. package/app/apps/web/.next/server/app/usage/page.js +1 -1
  33. package/app/apps/web/.next/server/app/usage/page.js.nft.json +1 -1
  34. package/app/apps/web/.next/server/app/usage/page_client-reference-manifest.js +1 -1
  35. package/app/apps/web/.next/server/chunks/[root-of-the-server]__0op9af~._.js +1 -1
  36. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__00z7zlm._.js +3 -0
  37. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__05lbtny._.js +12 -0
  38. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0ms7h0~._.js +1 -1
  39. package/app/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__08cr2u9._.js → [root-of-the-server]__0p~g4m6._.js} +2 -2
  40. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0w52fbc._.js +1 -1
  41. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0wvzyl7._.js +3 -0
  42. package/app/apps/web/.next/server/chunks/ssr/_09n75_5._.js +1 -1
  43. package/app/apps/web/.next/server/chunks/ssr/_0ph19-k._.js +12 -0
  44. package/app/apps/web/.next/server/chunks/ssr/_0u29mdd._.js +3 -0
  45. package/app/apps/web/.next/server/chunks/ssr/_0xies90._.js +1 -1
  46. package/app/apps/web/.next/server/chunks/ssr/apps_web_components_06j3c.0._.js +1 -1
  47. package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_0-jvt~a._.js +1 -1
  48. package/app/apps/web/.next/server/chunks/ssr/packages_parser_dist_analytics_0k4dgst.js +1 -1
  49. package/app/apps/web/.next/server/middleware-build-manifest.js +3 -3
  50. package/app/apps/web/.next/server/pages/500.html +1 -1
  51. package/app/apps/web/.next/server/server-reference-manifest.js +1 -1
  52. package/app/apps/web/.next/server/server-reference-manifest.json +1 -1
  53. package/app/apps/web/.next/static/chunks/03.mv4y4.w-vb.js +6 -0
  54. package/app/apps/web/.next/static/chunks/08983lz4~hffx.js +6 -0
  55. package/app/apps/web/.next/static/chunks/0fc6dk2qtokwh.js +1 -0
  56. package/app/apps/web/.next/static/chunks/0p1lpoh02zh8h.js +10 -0
  57. package/app/apps/web/.next/static/chunks/{03fw7f2obcvq~.js → 14q3xsfpkvuef.js} +2 -2
  58. package/app/apps/web/app/layout.tsx +2 -0
  59. package/app/apps/web/app/projects/[slug]/page.tsx +2 -0
  60. package/app/apps/web/app/sessions/[id]/page.tsx +27 -1
  61. package/app/apps/web/app/sessions/[id]/session-view.tsx +372 -793
  62. package/app/apps/web/app/sessions/[id]/team-tab/adapter.ts +633 -0
  63. package/app/apps/web/app/sessions/[id]/team-tab/format.ts +20 -0
  64. package/app/apps/web/app/sessions/[id]/team-tab/team-minimap.tsx +682 -0
  65. package/app/apps/web/app/sessions/[id]/team-tab/team-tab-client.tsx +78 -0
  66. package/app/apps/web/app/sessions/[id]/team-tab/team-table.tsx +796 -0
  67. package/app/apps/web/app/sessions/[id]/team-tab/turn-drawer.tsx +805 -0
  68. package/app/apps/web/app/sessions/[id]/tool-cards.tsx +461 -0
  69. package/app/apps/web/app/sessions/[id]/turn-steps.tsx +306 -0
  70. package/app/apps/web/app/sessions/sessions-grid.tsx +36 -5
  71. package/app/apps/web/components/live-sessions-widget.tsx +20 -6
  72. package/app/apps/web/components/team-badge.tsx +90 -0
  73. package/app/apps/web/package.json +1 -1
  74. package/app/apps/web/tsconfig.tsbuildinfo +1 -1
  75. package/dist/index.js +71 -13
  76. package/package.json +1 -1
  77. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0b..h_8._.js +0 -3
  78. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0cdd~8n._.js +0 -3
  79. package/app/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0~a~v00._.js +0 -3
  80. package/app/apps/web/.next/server/chunks/ssr/_0zv~jv-._.js +0 -12
  81. package/app/apps/web/.next/server/chunks/ssr/_12dtryh._.js +0 -12
  82. package/app/apps/web/.next/static/chunks/07oyxajlp3dvb.js +0 -6
  83. package/app/apps/web/.next/static/chunks/0a24elrqoqqep.js +0 -10
  84. package/app/apps/web/.next/static/chunks/0i4zodv86~~~i.js +0 -1
  85. package/app/apps/web/.next/static/chunks/0rbm60-qyshdm.js +0 -6
  86. /package/app/apps/web/.next/static/{2rEsiJssG30QsuNT0Lp9S → 0fPDRTdMQ-Y62h6fHNJXL}/_buildManifest.js +0 -0
  87. /package/app/apps/web/.next/static/{2rEsiJssG30QsuNT0Lp9S → 0fPDRTdMQ-Y62h6fHNJXL}/_clientMiddlewareManifest.js +0 -0
  88. /package/app/apps/web/.next/static/{2rEsiJssG30QsuNT0Lp9S → 0fPDRTdMQ-Y62h6fHNJXL}/_ssgManifest.js +0 -0
@@ -0,0 +1,461 @@
1
+ import React from "react";
2
+ import { shortenToolName } from "./turn-steps";
3
+
4
+ export type ToolUseInput = Record<string, unknown> | unknown;
5
+
6
+ function splitPath(p: string): { dir: string; file: string } {
7
+ const parts = p.split("/");
8
+ const file = parts[parts.length - 1] ?? p;
9
+ const dirParts = parts.slice(0, -1).filter(Boolean);
10
+ const dir =
11
+ dirParts.length > 3
12
+ ? "…/" + dirParts.slice(-3).join("/")
13
+ : dirParts.join("/");
14
+ return { dir: dir || "", file };
15
+ }
16
+
17
+ export function PathLabel({ path }: { path: string }) {
18
+ const { dir, file } = splitPath(path);
19
+ return (
20
+ <code
21
+ style={{
22
+ fontSize: 11,
23
+ fontFamily: "var(--font-mono)",
24
+ color: "var(--af-text)",
25
+ }}
26
+ >
27
+ {dir && <span style={{ color: "var(--af-text-tertiary)" }}>{dir}/</span>}
28
+ <b style={{ fontWeight: 600 }}>{file}</b>
29
+ </code>
30
+ );
31
+ }
32
+
33
+ export function ToolCardShell({
34
+ icon,
35
+ label,
36
+ children,
37
+ }: {
38
+ icon: React.ReactNode;
39
+ label: React.ReactNode;
40
+ children?: React.ReactNode;
41
+ }) {
42
+ return (
43
+ <div
44
+ style={{
45
+ border: "1px solid var(--af-border-subtle)",
46
+ borderRadius: 8,
47
+ background: "var(--background)",
48
+ overflow: "hidden",
49
+ }}
50
+ >
51
+ <div
52
+ style={{
53
+ padding: "8px 12px",
54
+ display: "flex",
55
+ alignItems: "center",
56
+ gap: 8,
57
+ borderBottom: children ? "1px solid var(--af-border-subtle)" : "none",
58
+ fontSize: 12,
59
+ color: "var(--af-text-secondary)",
60
+ }}
61
+ >
62
+ <span style={{ fontSize: 13 }}>{icon}</span>
63
+ <span>{label}</span>
64
+ </div>
65
+ {children}
66
+ </div>
67
+ );
68
+ }
69
+
70
+ export function CodeBlock({
71
+ text,
72
+ maxHeight = 280,
73
+ }: {
74
+ text: string;
75
+ maxHeight?: number;
76
+ }) {
77
+ return (
78
+ <pre
79
+ style={{
80
+ margin: 0,
81
+ padding: "10px 12px",
82
+ fontFamily: "var(--font-mono)",
83
+ fontSize: 11.5,
84
+ lineHeight: 1.55,
85
+ color: "var(--af-text)",
86
+ whiteSpace: "pre",
87
+ overflow: "auto",
88
+ maxHeight,
89
+ }}
90
+ >
91
+ {text}
92
+ </pre>
93
+ );
94
+ }
95
+
96
+ export function DiffView({
97
+ oldText,
98
+ newText,
99
+ }: {
100
+ oldText: string;
101
+ newText: string;
102
+ }) {
103
+ const oldLines = oldText.split("\n");
104
+ const newLines = newText.split("\n");
105
+ return (
106
+ <pre
107
+ style={{
108
+ margin: 0,
109
+ padding: "10px 12px",
110
+ fontFamily: "var(--font-mono)",
111
+ fontSize: 11.5,
112
+ lineHeight: 1.55,
113
+ whiteSpace: "pre",
114
+ overflow: "auto",
115
+ maxHeight: 320,
116
+ }}
117
+ >
118
+ {oldLines.map((line, i) => (
119
+ <div
120
+ key={`o${i}`}
121
+ style={{
122
+ background: "rgba(220, 38, 38, 0.08)",
123
+ color: "#991B1B",
124
+ padding: "0 4px",
125
+ borderLeft: "3px solid #DC2626",
126
+ }}
127
+ >
128
+ <span style={{ opacity: 0.6, userSelect: "none" }}>− </span>
129
+ {line || "\u00A0"}
130
+ </div>
131
+ ))}
132
+ {newLines.map((line, i) => (
133
+ <div
134
+ key={`n${i}`}
135
+ style={{
136
+ background: "rgba(5, 150, 105, 0.08)",
137
+ color: "#065F46",
138
+ padding: "0 4px",
139
+ borderLeft: "3px solid #059669",
140
+ }}
141
+ >
142
+ <span style={{ opacity: 0.6, userSelect: "none" }}>+ </span>
143
+ {line || "\u00A0"}
144
+ </div>
145
+ ))}
146
+ </pre>
147
+ );
148
+ }
149
+
150
+ export function ToolUseCard({
151
+ name,
152
+ input,
153
+ }: {
154
+ name: string;
155
+ input: ToolUseInput;
156
+ }) {
157
+ const i = (input ?? {}) as Record<string, unknown>;
158
+ const str = (k: string): string | undefined =>
159
+ typeof i[k] === "string" ? (i[k] as string) : undefined;
160
+ const num = (k: string): number | undefined =>
161
+ typeof i[k] === "number" ? (i[k] as number) : undefined;
162
+
163
+ if (name === "Write") {
164
+ const filePath = str("file_path") ?? "";
165
+ const content = str("content") ?? "";
166
+ return (
167
+ <ToolCardShell
168
+ icon="📝"
169
+ label={
170
+ <>
171
+ <b>Write</b> <PathLabel path={filePath} />
172
+ </>
173
+ }
174
+ >
175
+ <CodeBlock text={content} />
176
+ </ToolCardShell>
177
+ );
178
+ }
179
+
180
+ if (name === "Edit") {
181
+ const filePath = str("file_path") ?? "";
182
+ const oldStr = str("old_string") ?? "";
183
+ const newStr = str("new_string") ?? "";
184
+ const replaceAll = i.replace_all === true;
185
+ return (
186
+ <ToolCardShell
187
+ icon="✏️"
188
+ label={
189
+ <>
190
+ <b>Edit</b> <PathLabel path={filePath} />
191
+ {replaceAll && (
192
+ <span
193
+ style={{
194
+ fontSize: 10,
195
+ color: "var(--af-warning)",
196
+ background: "var(--af-warning-subtle)",
197
+ padding: "1px 6px",
198
+ borderRadius: 10,
199
+ }}
200
+ >
201
+ replace all
202
+ </span>
203
+ )}
204
+ </>
205
+ }
206
+ >
207
+ <DiffView oldText={oldStr} newText={newStr} />
208
+ </ToolCardShell>
209
+ );
210
+ }
211
+
212
+ if (name === "Read") {
213
+ const filePath = str("file_path") ?? "";
214
+ const offset = num("offset");
215
+ const limit = num("limit");
216
+ const range =
217
+ offset !== undefined || limit !== undefined
218
+ ? ` · lines ${offset ?? 1}${limit !== undefined ? `–${(offset ?? 0) + limit}` : "…"}`
219
+ : "";
220
+ return (
221
+ <ToolCardShell
222
+ icon="📖"
223
+ label={
224
+ <>
225
+ <b>Read</b> <PathLabel path={filePath} />
226
+ <span style={{ color: "var(--af-text-tertiary)" }}>{range}</span>
227
+ </>
228
+ }
229
+ />
230
+ );
231
+ }
232
+
233
+ if (name === "Bash") {
234
+ const command = str("command") ?? "";
235
+ const description = str("description");
236
+ const runInBg = i.run_in_background === true;
237
+ return (
238
+ <ToolCardShell
239
+ icon="⚡"
240
+ label={
241
+ <>
242
+ <b>Bash</b>
243
+ {description && (
244
+ <span style={{ color: "var(--af-text)", fontStyle: "italic" }}>
245
+ {description}
246
+ </span>
247
+ )}
248
+ {runInBg && (
249
+ <span
250
+ style={{
251
+ fontSize: 10,
252
+ color: "var(--af-info)",
253
+ background: "var(--af-info-subtle)",
254
+ padding: "1px 6px",
255
+ borderRadius: 10,
256
+ }}
257
+ >
258
+ background
259
+ </span>
260
+ )}
261
+ </>
262
+ }
263
+ >
264
+ <CodeBlock text={command} maxHeight={220} />
265
+ </ToolCardShell>
266
+ );
267
+ }
268
+
269
+ if (name === "Grep") {
270
+ const pattern = str("pattern") ?? "";
271
+ const path = str("path");
272
+ const glob = str("glob");
273
+ const type = str("type");
274
+ const outputMode = str("output_mode");
275
+ return (
276
+ <ToolCardShell
277
+ icon="🔍"
278
+ label={
279
+ <>
280
+ <b>Grep</b>{" "}
281
+ <code
282
+ style={{
283
+ background: "var(--af-border-subtle)",
284
+ padding: "1px 6px",
285
+ borderRadius: 4,
286
+ fontFamily: "var(--font-mono)",
287
+ fontSize: 11,
288
+ }}
289
+ >
290
+ {pattern}
291
+ </code>
292
+ {path && (
293
+ <>
294
+ {" in "}
295
+ <PathLabel path={path} />
296
+ </>
297
+ )}
298
+ {(glob || type || outputMode) && (
299
+ <span
300
+ style={{
301
+ color: "var(--af-text-tertiary)",
302
+ fontSize: 11,
303
+ marginLeft: 6,
304
+ }}
305
+ >
306
+ {[
307
+ glob && `glob=${glob}`,
308
+ type && `type=${type}`,
309
+ outputMode && `mode=${outputMode}`,
310
+ ]
311
+ .filter(Boolean)
312
+ .join(" · ")}
313
+ </span>
314
+ )}
315
+ </>
316
+ }
317
+ />
318
+ );
319
+ }
320
+
321
+ if (name === "Glob") {
322
+ const pattern = str("pattern") ?? "";
323
+ const path = str("path");
324
+ return (
325
+ <ToolCardShell
326
+ icon="📁"
327
+ label={
328
+ <>
329
+ <b>Glob</b>{" "}
330
+ <code
331
+ style={{
332
+ background: "var(--af-border-subtle)",
333
+ padding: "1px 6px",
334
+ borderRadius: 4,
335
+ fontFamily: "var(--font-mono)",
336
+ fontSize: 11,
337
+ }}
338
+ >
339
+ {pattern}
340
+ </code>
341
+ {path && (
342
+ <>
343
+ {" in "}
344
+ <PathLabel path={path} />
345
+ </>
346
+ )}
347
+ </>
348
+ }
349
+ />
350
+ );
351
+ }
352
+
353
+ if (name === "Skill") {
354
+ const skill = str("skill") ?? "";
355
+ const args = str("args");
356
+ return (
357
+ <ToolCardShell
358
+ icon="🧩"
359
+ label={
360
+ <>
361
+ <b>/{skill}</b>
362
+ {args && (
363
+ <span style={{ color: "var(--af-text-secondary)" }}>{args}</span>
364
+ )}
365
+ </>
366
+ }
367
+ />
368
+ );
369
+ }
370
+
371
+ if (name === "ToolSearch") {
372
+ const query = str("query") ?? "";
373
+ const max = num("max_results");
374
+ return (
375
+ <ToolCardShell
376
+ icon="🔎"
377
+ label={
378
+ <>
379
+ <b>ToolSearch</b>{" "}
380
+ <code
381
+ style={{
382
+ background: "var(--af-border-subtle)",
383
+ padding: "1px 6px",
384
+ borderRadius: 4,
385
+ fontFamily: "var(--font-mono)",
386
+ fontSize: 11,
387
+ }}
388
+ >
389
+ {query}
390
+ </code>
391
+ {max !== undefined && (
392
+ <span
393
+ style={{ color: "var(--af-text-tertiary)", fontSize: 11 }}
394
+ >
395
+ max={max}
396
+ </span>
397
+ )}
398
+ </>
399
+ }
400
+ />
401
+ );
402
+ }
403
+
404
+ if (name === "TodoWrite") {
405
+ const todos = Array.isArray(i.todos)
406
+ ? (i.todos as Array<Record<string, unknown>>)
407
+ : [];
408
+ return (
409
+ <ToolCardShell icon="✅" label={<b>TodoWrite · {todos.length} items</b>}>
410
+ <div style={{ padding: "10px 12px", fontSize: 12 }}>
411
+ {todos.map((t, ti) => {
412
+ const status = String(t.status ?? "pending");
413
+ const content =
414
+ typeof t.content === "string"
415
+ ? t.content
416
+ : typeof t.activeForm === "string"
417
+ ? t.activeForm
418
+ : "";
419
+ const icon =
420
+ status === "completed"
421
+ ? "✔"
422
+ : status === "in_progress"
423
+ ? "◐"
424
+ : "○";
425
+ return (
426
+ <div
427
+ key={ti}
428
+ style={{
429
+ display: "flex",
430
+ gap: 8,
431
+ padding: "2px 0",
432
+ opacity: status === "completed" ? 0.6 : 1,
433
+ textDecoration:
434
+ status === "completed" ? "line-through" : "none",
435
+ }}
436
+ >
437
+ <span style={{ color: "var(--af-text-tertiary)" }}>{icon}</span>
438
+ <span>{content}</span>
439
+ </div>
440
+ );
441
+ })}
442
+ </div>
443
+ </ToolCardShell>
444
+ );
445
+ }
446
+
447
+ if (name.startsWith("mcp__")) {
448
+ const short = shortenToolName(name);
449
+ return (
450
+ <ToolCardShell icon="🔌" label={<b>{short}</b>}>
451
+ <CodeBlock text={JSON.stringify(input, null, 2)} maxHeight={200} />
452
+ </ToolCardShell>
453
+ );
454
+ }
455
+
456
+ return (
457
+ <ToolCardShell icon="🔧" label={<b>{name}</b>}>
458
+ <CodeBlock text={JSON.stringify(input, null, 2)} maxHeight={220} />
459
+ </ToolCardShell>
460
+ );
461
+ }