@tonyclaw/agent-inspector 3.0.28 → 3.0.29

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 (32) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-TghZr5t1.js → CompareDrawer-Cb5ccPeX.js} +1 -1
  3. package/.output/public/assets/{ProxyViewerContainer-fShBAZjj.js → ProxyViewerContainer-COBe5GTT.js} +32 -32
  4. package/.output/public/assets/{ReplayDialog-CZMApaF4.js → ReplayDialog-CctnITbt.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-DNWccR7O.js → RequestAnatomy-BrN0RBbL.js} +1 -1
  6. package/.output/public/assets/{ResponseView-d25MdFhY.js → ResponseView-Cqq87lX_.js} +2 -2
  7. package/.output/public/assets/{StreamingChunkSequence-DIFZEnWe.js → StreamingChunkSequence-CnTa9mCr.js} +1 -1
  8. package/.output/public/assets/{_sessionId-DRfvuE2k.js → _sessionId-DKM91udC.js} +1 -1
  9. package/.output/public/assets/{index-D4HkS7Ct.js → index-Bq-nqolG.js} +1 -1
  10. package/.output/public/assets/{index-B3aAuqWq.js → index-DPiESBo2.js} +1 -1
  11. package/.output/public/assets/{index-DzARL2Fi.js → index-DTLNVcgc.js} +7 -7
  12. package/.output/public/assets/index-DliqmwUw.css +1 -0
  13. package/.output/public/assets/{json-viewer-wuJSKaed.js → json-viewer-CfaDJwx8.js} +1 -1
  14. package/.output/server/{_sessionId-BJTNiP_O.mjs → _sessionId-CwGXPD4C.mjs} +2 -2
  15. package/.output/server/_ssr/{CompareDrawer-BMRH3N97.mjs → CompareDrawer-R_P1-VNr.mjs} +2 -2
  16. package/.output/server/_ssr/{ProxyViewerContainer-AFwcHAIR.mjs → ProxyViewerContainer-DUgxRNbj.mjs} +80 -67
  17. package/.output/server/_ssr/{ReplayDialog-CbWvRHiN.mjs → ReplayDialog-De9wKKzS.mjs} +3 -3
  18. package/.output/server/_ssr/{RequestAnatomy-C4kcPyqN.mjs → RequestAnatomy-Db4MxUYo.mjs} +2 -2
  19. package/.output/server/_ssr/{ResponseView-D8VYt-gZ.mjs → ResponseView-8rDXOiNB.mjs} +2 -2
  20. package/.output/server/_ssr/{StreamingChunkSequence-BUUo6vU0.mjs → StreamingChunkSequence-N9teZHkA.mjs} +2 -2
  21. package/.output/server/_ssr/{index-DTwMEEXO.mjs → index-D4DvByuW.mjs} +2 -2
  22. package/.output/server/_ssr/index.mjs +2 -2
  23. package/.output/server/_ssr/{json-viewer-BqF1pSQD.mjs → json-viewer-BjoHRbjS.mjs} +2 -2
  24. package/.output/server/_ssr/{router-C8BOns7y.mjs → router-BYlePDj8.mjs} +4 -4
  25. package/.output/server/{_tanstack-start-manifest_v-BBf2nRhb.mjs → _tanstack-start-manifest_v-DMCA8KK3.mjs} +1 -1
  26. package/.output/server/index.mjs +70 -70
  27. package/package.json +1 -1
  28. package/src/components/clients/ClientLogo.tsx +9 -6
  29. package/src/components/proxy-viewer/ConversationGroupList.tsx +49 -34
  30. package/src/components/proxy-viewer/ConversationHeader.tsx +22 -18
  31. package/src/lib/utils.ts +5 -1
  32. package/.output/public/assets/index-BsxAGqMA.css +0 -1
@@ -20,121 +20,121 @@ const assets = {
20
20
  "/assets/agent-inspector-58K1_MsC.ico": {
21
21
  "type": "image/vnd.microsoft.icon",
22
22
  "etag": '"38fa-ZD8kPABHYjPIkcH82FMY6iZM7fI"',
23
- "mtime": "2026-07-11T07:25:10.079Z",
23
+ "mtime": "2026-07-11T08:33:29.981Z",
24
24
  "size": 14586,
25
25
  "path": "../public/assets/agent-inspector-58K1_MsC.ico"
26
26
  },
27
- "/assets/index-B3aAuqWq.js": {
28
- "type": "text/javascript; charset=utf-8",
29
- "etag": '"1cd2d-NtF7W+NRjTmAvD+1JKZI8rtHI7U"',
30
- "mtime": "2026-07-11T07:25:10.087Z",
31
- "size": 118061,
32
- "path": "../public/assets/index-B3aAuqWq.js"
33
- },
34
27
  "/assets/alibaba-TTwafVwX.svg": {
35
28
  "type": "image/svg+xml",
36
29
  "etag": '"171b-6dyV5K8QjiaY35sN9qNprh9zDIs"',
37
- "mtime": "2026-07-11T07:25:10.085Z",
30
+ "mtime": "2026-07-11T08:33:29.981Z",
38
31
  "size": 5915,
39
32
  "path": "../public/assets/alibaba-TTwafVwX.svg"
40
33
  },
41
- "/assets/json-viewer-wuJSKaed.js": {
34
+ "/assets/json-viewer-CfaDJwx8.js": {
42
35
  "type": "text/javascript; charset=utf-8",
43
- "etag": '"1ae7-BU19qUySeFzJhdQR46CWzhjoXCo"',
44
- "mtime": "2026-07-11T07:25:10.087Z",
36
+ "etag": '"1ae7-T+/M8FSSwkvGbzOkJ/2Lb5mJqSs"',
37
+ "mtime": "2026-07-11T08:33:29.982Z",
45
38
  "size": 6887,
46
- "path": "../public/assets/json-viewer-wuJSKaed.js"
39
+ "path": "../public/assets/json-viewer-CfaDJwx8.js"
40
+ },
41
+ "/assets/index-DPiESBo2.js": {
42
+ "type": "text/javascript; charset=utf-8",
43
+ "etag": '"1cd2d-ZvxO1FYMv7b0bavhQij+IxPqNxI"',
44
+ "mtime": "2026-07-11T08:33:29.982Z",
45
+ "size": 118061,
46
+ "path": "../public/assets/index-DPiESBo2.js"
47
47
  },
48
- "/assets/index-BsxAGqMA.css": {
48
+ "/assets/index-DliqmwUw.css": {
49
49
  "type": "text/css; charset=utf-8",
50
- "etag": '"28b55-jHTF06GuUcizq3n19QXDY4Rs9bY"',
51
- "mtime": "2026-07-11T07:25:10.085Z",
52
- "size": 166741,
53
- "path": "../public/assets/index-BsxAGqMA.css"
50
+ "etag": '"28ec4-pKYnk6JA2sEAWeib/WGc4RsJlZo"',
51
+ "mtime": "2026-07-11T08:33:29.981Z",
52
+ "size": 167620,
53
+ "path": "../public/assets/index-DliqmwUw.css"
54
+ },
55
+ "/assets/index-DTLNVcgc.js": {
56
+ "type": "text/javascript; charset=utf-8",
57
+ "etag": '"537cd-D7PyRt2jku7bDF92q6ovZ+at3vc"',
58
+ "mtime": "2026-07-11T08:33:29.981Z",
59
+ "size": 341965,
60
+ "path": "../public/assets/index-DTLNVcgc.js"
54
61
  },
55
62
  "/assets/minimax-BPMzvuL-.jpeg": {
56
63
  "type": "image/jpeg",
57
64
  "etag": '"1b06-IwivU89ko5UTMUM1/t7hn4sQK9A"',
58
- "mtime": "2026-07-11T07:25:10.085Z",
65
+ "mtime": "2026-07-11T08:33:29.981Z",
59
66
  "size": 6918,
60
67
  "path": "../public/assets/minimax-BPMzvuL-.jpeg"
61
68
  },
62
- "/assets/index-DzARL2Fi.js": {
63
- "type": "text/javascript; charset=utf-8",
64
- "etag": '"537cd-n0LgXNt1QLHB07TADWQSjwwA7ao"',
65
- "mtime": "2026-07-11T07:25:10.085Z",
66
- "size": 341965,
67
- "path": "../public/assets/index-DzARL2Fi.js"
68
- },
69
- "/assets/CompareDrawer-TghZr5t1.js": {
69
+ "/assets/CompareDrawer-Cb5ccPeX.js": {
70
70
  "type": "text/javascript; charset=utf-8",
71
- "etag": '"4bc4-EO0Pced4VNvNgQhISz9DCokb9HU"',
72
- "mtime": "2026-07-11T07:25:10.087Z",
71
+ "etag": '"4bc4-DHG9pbDatJk9bClyztEt1UqrAT4"',
72
+ "mtime": "2026-07-11T08:33:29.981Z",
73
73
  "size": 19396,
74
- "path": "../public/assets/CompareDrawer-TghZr5t1.js"
74
+ "path": "../public/assets/CompareDrawer-Cb5ccPeX.js"
75
75
  },
76
- "/assets/index-D4HkS7Ct.js": {
76
+ "/assets/ReplayDialog-CctnITbt.js": {
77
77
  "type": "text/javascript; charset=utf-8",
78
- "etag": '"265-GATgiXd9lc1ztQtCZI0flLv7tLY"',
79
- "mtime": "2026-07-11T07:25:10.085Z",
80
- "size": 613,
81
- "path": "../public/assets/index-D4HkS7Ct.js"
78
+ "etag": '"3348-0fckCAOkK1UC4nkjRLBGehN4X2A"',
79
+ "mtime": "2026-07-11T08:33:29.981Z",
80
+ "size": 13128,
81
+ "path": "../public/assets/ReplayDialog-CctnITbt.js"
82
82
  },
83
- "/assets/ResponseView-d25MdFhY.js": {
83
+ "/assets/index-Bq-nqolG.js": {
84
84
  "type": "text/javascript; charset=utf-8",
85
- "etag": '"47fe-Po8oiwgEzmPD5hRtGam0HQony8k"',
86
- "mtime": "2026-07-11T07:25:10.087Z",
87
- "size": 18430,
88
- "path": "../public/assets/ResponseView-d25MdFhY.js"
85
+ "etag": '"265-eCPwzF17tobzPmkS8kveSyjk/f8"',
86
+ "mtime": "2026-07-11T08:33:29.981Z",
87
+ "size": 613,
88
+ "path": "../public/assets/index-Bq-nqolG.js"
89
89
  },
90
- "/assets/RequestAnatomy-DNWccR7O.js": {
90
+ "/assets/RequestAnatomy-BrN0RBbL.js": {
91
91
  "type": "text/javascript; charset=utf-8",
92
- "etag": '"43f3-aiF5LhFVPVUreSkzjdqgZFSwONM"',
93
- "mtime": "2026-07-11T07:25:10.087Z",
92
+ "etag": '"43f3-tHiogWhSlLk1V4B2zt7nDCFLDWI"',
93
+ "mtime": "2026-07-11T08:33:29.981Z",
94
94
  "size": 17395,
95
- "path": "../public/assets/RequestAnatomy-DNWccR7O.js"
95
+ "path": "../public/assets/RequestAnatomy-BrN0RBbL.js"
96
96
  },
97
- "/assets/ReplayDialog-CZMApaF4.js": {
97
+ "/assets/ResponseView-Cqq87lX_.js": {
98
98
  "type": "text/javascript; charset=utf-8",
99
- "etag": '"3348-CNibW415vjAp7j+7orWWQiIbLDA"',
100
- "mtime": "2026-07-11T07:25:10.085Z",
101
- "size": 13128,
102
- "path": "../public/assets/ReplayDialog-CZMApaF4.js"
99
+ "etag": '"47fe-jzMkpDCjmJMzOygADqj3agP67TA"',
100
+ "mtime": "2026-07-11T08:33:29.981Z",
101
+ "size": 18430,
102
+ "path": "../public/assets/ResponseView-Cqq87lX_.js"
103
103
  },
104
- "/assets/StreamingChunkSequence-DIFZEnWe.js": {
104
+ "/assets/StreamingChunkSequence-CnTa9mCr.js": {
105
105
  "type": "text/javascript; charset=utf-8",
106
- "etag": '"e96-uRF1QBlYJ4LJvlyn05RZzDtEbkE"',
107
- "mtime": "2026-07-11T07:25:10.087Z",
106
+ "etag": '"e96-YzbbUNDZ2WAJTeAaxiEjdXJL4uA"',
107
+ "mtime": "2026-07-11T08:33:29.982Z",
108
108
  "size": 3734,
109
- "path": "../public/assets/StreamingChunkSequence-DIFZEnWe.js"
110
- },
111
- "/assets/qwen-CONDcHqt.png": {
112
- "type": "image/png",
113
- "etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
114
- "mtime": "2026-07-11T07:25:10.085Z",
115
- "size": 357059,
116
- "path": "../public/assets/qwen-CONDcHqt.png"
109
+ "path": "../public/assets/StreamingChunkSequence-CnTa9mCr.js"
117
110
  },
118
111
  "/assets/zhipuai-BPNAnxo-.svg": {
119
112
  "type": "image/svg+xml",
120
113
  "etag": '"2bf8-hNaLCTi89nOFCsIIfWpP/jrfo0s"',
121
- "mtime": "2026-07-11T07:25:10.085Z",
114
+ "mtime": "2026-07-11T08:33:29.981Z",
122
115
  "size": 11256,
123
116
  "path": "../public/assets/zhipuai-BPNAnxo-.svg"
124
117
  },
125
- "/assets/_sessionId-DRfvuE2k.js": {
118
+ "/assets/qwen-CONDcHqt.png": {
119
+ "type": "image/png",
120
+ "etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
121
+ "mtime": "2026-07-11T08:33:29.981Z",
122
+ "size": 357059,
123
+ "path": "../public/assets/qwen-CONDcHqt.png"
124
+ },
125
+ "/assets/_sessionId-DKM91udC.js": {
126
126
  "type": "text/javascript; charset=utf-8",
127
- "etag": '"36d-DdOUH1ep4qcEQKZ8gAcubBJENCU"',
128
- "mtime": "2026-07-11T07:25:10.085Z",
127
+ "etag": '"36d-H7Npt5FbAUZ4PkVzy9EXc0/6t3c"',
128
+ "mtime": "2026-07-11T08:33:29.981Z",
129
129
  "size": 877,
130
- "path": "../public/assets/_sessionId-DRfvuE2k.js"
130
+ "path": "../public/assets/_sessionId-DKM91udC.js"
131
131
  },
132
- "/assets/ProxyViewerContainer-fShBAZjj.js": {
132
+ "/assets/ProxyViewerContainer-COBe5GTT.js": {
133
133
  "type": "text/javascript; charset=utf-8",
134
- "etag": '"140e7c-9dZ35KxZynE0VFMwXVZlbDNocic"',
135
- "mtime": "2026-07-11T07:25:10.087Z",
136
- "size": 1314428,
137
- "path": "../public/assets/ProxyViewerContainer-fShBAZjj.js"
134
+ "etag": '"141300-JvEEzV1kBx2VyyR9a6sSD0j8rSQ"',
135
+ "mtime": "2026-07-11T08:33:29.982Z",
136
+ "size": 1315584,
137
+ "path": "../public/assets/ProxyViewerContainer-COBe5GTT.js"
138
138
  }
139
139
  };
140
140
  function readAsset(id) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonyclaw/agent-inspector",
3
- "version": "3.0.28",
3
+ "version": "3.0.29",
4
4
  "type": "module",
5
5
  "description": "Agent observability and knowledge capture layer for AI coding tools.",
6
6
  "license": "MIT",
@@ -106,11 +106,14 @@ const CLIENT_LOGOS: Record<ImageClientApp, string> = {
106
106
  };
107
107
 
108
108
  const CLIENT_LOGO_FRAMES: Record<ImageClientApp, string> = {
109
- "agent-inspector": "border-orange-200/25 bg-orange-300/[0.12]",
110
- codex: "border-cyan-200/20 bg-cyan-300/[0.08]",
111
- opencode: "border-sky-200/25 bg-sky-300/[0.12]",
112
- "mimo-code": "border-orange-200/25 bg-orange-400/[0.12]",
113
- "claude-code": "border-amber-100/20 bg-amber-300/[0.09]",
109
+ "agent-inspector":
110
+ "border-orange-700/15 bg-orange-500/[0.08] dark:border-orange-200/25 dark:bg-orange-300/[0.12]",
111
+ codex: "border-cyan-700/15 bg-cyan-500/[0.08] dark:border-cyan-200/20 dark:bg-cyan-300/[0.08]",
112
+ opencode: "border-sky-700/15 bg-sky-500/[0.09] dark:border-sky-200/25 dark:bg-sky-300/[0.12]",
113
+ "mimo-code":
114
+ "border-orange-700/15 bg-orange-500/[0.09] dark:border-orange-200/25 dark:bg-orange-400/[0.12]",
115
+ "claude-code":
116
+ "border-amber-700/15 bg-amber-500/[0.08] dark:border-amber-100/20 dark:bg-amber-300/[0.09]",
114
117
  };
115
118
 
116
119
  const CLIENT_LOGO_IMAGES: Record<ImageClientApp, string> = {
@@ -137,7 +140,7 @@ export function ClientLogo({
137
140
  return (
138
141
  <span
139
142
  className={cn(
140
- "inline-flex size-6 shrink-0 items-center justify-center rounded-md border border-cyan-200/20 bg-cyan-300/[0.08] text-cyan-100 shadow-sm",
143
+ "inline-flex size-6 shrink-0 items-center justify-center rounded-md border border-cyan-700/15 bg-cyan-500/[0.08] text-[var(--inspector-status-cool)] shadow-sm dark:border-cyan-200/20 dark:bg-cyan-300/[0.08]",
141
144
  className,
142
145
  )}
143
146
  aria-label={decorative ? undefined : label}
@@ -284,14 +284,16 @@ function countSessions(processes: readonly ProcessGroupData[]): number {
284
284
  return sessions;
285
285
  }
286
286
 
287
- function readStoredIdSet(storageKey: string): ReadonlySet<string> {
288
- if (typeof window === "undefined") return new Set();
287
+ function readStoredIdSet(storageKey: string): ReadonlySet<string> | null {
288
+ if (typeof window === "undefined") return null;
289
289
  try {
290
- const parsed: unknown = JSON.parse(window.localStorage.getItem(storageKey) ?? "[]");
291
- if (!Array.isArray(parsed)) return new Set();
290
+ const storedValue = window.localStorage.getItem(storageKey);
291
+ if (storedValue === null) return null;
292
+ const parsed: unknown = JSON.parse(storedValue);
293
+ if (!Array.isArray(parsed)) return null;
292
294
  return new Set(parsed.filter((value): value is string => typeof value === "string"));
293
295
  } catch {
294
- return new Set();
296
+ return null;
295
297
  }
296
298
  }
297
299
 
@@ -312,6 +314,21 @@ function removeIds(values: ReadonlySet<string>, ids: ReadonlySet<string>): Reado
312
314
  return changed ? next : values;
313
315
  }
314
316
 
317
+ export function buildDefaultCollapsedProcessIds(
318
+ hierarchy: readonly ClientGroupData[],
319
+ ): ReadonlySet<string> {
320
+ const collapsedIds = new Set<string>();
321
+ for (const clientGroup of hierarchy) {
322
+ for (let index = 1; index < clientGroup.processes.length; index++) {
323
+ const processGroup = clientGroup.processes[index];
324
+ if (processGroup !== undefined && !hasPendingLogs(processGroup.logs)) {
325
+ collapsedIds.add(processGroup.id);
326
+ }
327
+ }
328
+ }
329
+ return collapsedIds;
330
+ }
331
+
315
332
  function shortProjectPath(projectFolder: string | null): string | null {
316
333
  if (projectFolder === null || projectFolder === "") return null;
317
334
  const parts = projectFolder
@@ -337,12 +354,12 @@ function SummaryChip({
337
354
  return (
338
355
  <span
339
356
  className={cn(
340
- "bg-white/[0.04] inline-flex h-7 items-center gap-1 rounded-md px-2 text-xs text-muted-foreground",
357
+ "inline-flex h-7 items-center gap-1 rounded-md bg-[var(--inspector-surface-low)] px-2 text-xs text-muted-foreground",
341
358
  className,
342
359
  )}
343
360
  >
344
- <span className="font-mono text-[10px] uppercase text-white/35">{label}</span>
345
- <span className="font-mono tabular-nums text-slate-100">{value}</span>
361
+ <span className="font-mono text-[10px] uppercase text-muted-foreground/70">{label}</span>
362
+ <span className="font-mono tabular-nums text-foreground">{value}</span>
346
363
  </span>
347
364
  );
348
365
  }
@@ -351,13 +368,13 @@ function AncestorActivityIndicator({ count }: { count: number }): JSX.Element {
351
368
  const label = `${count} open turn${count === 1 ? "" : "s"}`;
352
369
  return (
353
370
  <span
354
- className="relative inline-flex size-6 shrink-0 items-center justify-center rounded-md bg-amber-300/[0.08] text-amber-100/90 ring-1 ring-amber-200/10"
371
+ className="relative inline-flex size-6 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-medium)] text-[var(--inspector-status-watch)] ring-1 ring-border/50"
355
372
  aria-label={label}
356
373
  title={label}
357
374
  >
358
375
  <Loader2 className="size-3 animate-spin" />
359
376
  {count > 1 && (
360
- <span className="absolute translate-x-2 -translate-y-2 rounded bg-background px-0.5 font-mono text-[8px] tabular-nums text-amber-100">
377
+ <span className="absolute translate-x-2 -translate-y-2 rounded bg-card px-0.5 font-mono text-[8px] tabular-nums text-[var(--inspector-status-watch)]">
361
378
  {count}
362
379
  </span>
363
380
  )}
@@ -373,14 +390,16 @@ export function ConversationGroupList({
373
390
  const [collapsedClientIds, setCollapsedClientIds] = useState<ReadonlySet<string>>(
374
391
  () => new Set(),
375
392
  );
376
- const [collapsedProcessIds, setCollapsedProcessIds] = useState<ReadonlySet<string>>(
377
- () => new Set(),
393
+ const [collapsedProcessIds, setCollapsedProcessIds] = useState<ReadonlySet<string>>(() =>
394
+ buildDefaultCollapsedProcessIds(hierarchy),
378
395
  );
379
396
  const [storedCollapseStateLoaded, setStoredCollapseStateLoaded] = useState(false);
380
397
 
381
398
  useEffect(() => {
382
- setCollapsedClientIds(readStoredIdSet(COLLAPSED_CLIENTS_STORAGE_KEY));
383
- setCollapsedProcessIds(readStoredIdSet(COLLAPSED_PROCESSES_STORAGE_KEY));
399
+ const storedClientIds = readStoredIdSet(COLLAPSED_CLIENTS_STORAGE_KEY);
400
+ const storedProcessIds = readStoredIdSet(COLLAPSED_PROCESSES_STORAGE_KEY);
401
+ if (storedClientIds !== null) setCollapsedClientIds(storedClientIds);
402
+ if (storedProcessIds !== null) setCollapsedProcessIds(storedProcessIds);
384
403
  setStoredCollapseStateLoaded(true);
385
404
  }, []);
386
405
 
@@ -470,38 +489,34 @@ function ClientGroupSection({
470
489
  return (
471
490
  <section
472
491
  className={cn(
473
- "bg-card/60 relative isolate overflow-hidden rounded-[8px] shadow-sm",
474
- isWorking && "bg-card/70",
492
+ "relative isolate overflow-hidden rounded-[8px] bg-card/65",
493
+ isWorking && "bg-card/80",
475
494
  )}
476
495
  data-ide-group={group.id}
477
496
  >
478
497
  <button
479
498
  type="button"
480
- className="grid w-full min-w-0 grid-cols-[2.25rem_minmax(0,1fr)_auto] items-center gap-2.5 px-3 py-2.5 text-left transition-colors hover:bg-white/[0.025] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-cyan-300/40"
499
+ className="grid w-full min-w-0 grid-cols-[2.25rem_minmax(0,1fr)_auto] items-center gap-2.5 px-3 py-2.5 text-left transition-colors hover:bg-[var(--inspector-surface-low)] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
481
500
  onClick={onToggleClient}
482
501
  aria-expanded={!collapsed}
483
502
  >
484
503
  {group.client === "unknown" ? (
485
- <span className="bg-white/[0.04] inline-flex size-9 shrink-0 items-center justify-center rounded-md text-slate-300">
504
+ <span className="inline-flex size-9 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground">
486
505
  <Monitor className="size-4" />
487
506
  </span>
488
507
  ) : (
489
- <ClientLogo
490
- client={group.client}
491
- className="size-9 rounded-md text-cyan-100"
492
- decorative={true}
493
- />
508
+ <ClientLogo client={group.client} className="size-9 rounded-md" decorative={true} />
494
509
  )}
495
510
 
496
511
  <span className="min-w-0">
497
512
  <span className="flex min-w-0 items-center gap-2">
498
513
  <span
499
- className="truncate text-sm font-semibold text-slate-50"
514
+ className="truncate text-sm font-semibold text-foreground"
500
515
  title={group.userAgent ?? group.label}
501
516
  >
502
517
  {group.label}
503
518
  </span>
504
- <span className="rounded bg-cyan-300/[0.05] px-1.5 py-0.5 font-mono text-[9px] uppercase text-cyan-100/70">
519
+ <span className="rounded bg-[var(--inspector-surface-medium)] px-1.5 py-0.5 font-mono text-[9px] uppercase text-muted-foreground">
505
520
  {clientAppTypeLabel(group.client)}
506
521
  </span>
507
522
  {isWorking && <AncestorActivityIndicator count={pendingTurnCount} />}
@@ -524,14 +539,14 @@ function ClientGroupSection({
524
539
  <SummaryChip label="OUT" value={formatTokenCount(totals.outputTokens)} />
525
540
  </span>
526
541
  )}
527
- <span className="bg-white/[0.04] hover:bg-white/[0.07] inline-flex size-8 shrink-0 items-center justify-center rounded-md text-slate-300">
542
+ <span className="inline-flex size-8 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground transition-colors group-hover:bg-[var(--inspector-surface-medium)]">
528
543
  {collapsed ? <ChevronRight className="size-4" /> : <ChevronDown className="size-4" />}
529
544
  </span>
530
545
  </span>
531
546
  </button>
532
547
 
533
548
  {!collapsed && (
534
- <div className="space-y-1 px-2 pb-2 pt-1">
549
+ <div className="space-y-0.5 px-2 pb-2 pt-0.5">
535
550
  {group.processes.map((processGroup) => (
536
551
  <ProcessGroupSection
537
552
  key={processGroup.id}
@@ -567,23 +582,23 @@ function ProcessGroupSection({
567
582
  const processLabel =
568
583
  group.clientPid !== null && group.clientPid !== undefined
569
584
  ? `PID ${group.clientPid}`
570
- : "PID unavailable";
585
+ : "Process unavailable";
571
586
 
572
587
  return (
573
- <section className="relative pl-4">
588
+ <section className="relative pl-3">
574
589
  <button
575
590
  type="button"
576
- className="bg-black/[0.07] grid w-full min-w-0 grid-cols-[2rem_minmax(0,1fr)_auto] items-center gap-2.5 rounded-md px-2.5 py-2 text-left transition-colors hover:bg-white/[0.03] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-cyan-300/35"
591
+ className="grid w-full min-w-0 grid-cols-[2rem_minmax(0,1fr)_auto] items-center gap-2.5 rounded-md bg-[var(--inspector-surface-low)] px-2.5 py-2 text-left transition-colors hover:bg-[var(--inspector-surface-medium)] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
577
592
  onClick={onToggle}
578
593
  aria-expanded={!collapsed}
579
594
  >
580
- <span className="bg-white/[0.04] inline-flex size-8 shrink-0 items-center justify-center rounded-md text-amber-100/85">
595
+ <span className="inline-flex size-8 shrink-0 items-center justify-center text-[var(--inspector-status-watch)]">
581
596
  <Cpu className="size-4" />
582
597
  </span>
583
598
 
584
599
  <span className="min-w-0">
585
600
  <span className="flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1">
586
- <span className="font-mono text-xs font-semibold tabular-nums text-slate-100">
601
+ <span className="font-mono text-xs font-semibold tabular-nums text-foreground">
587
602
  {processLabel}
588
603
  </span>
589
604
  {isWorking && <AncestorActivityIndicator count={pendingTurnCount} />}
@@ -612,14 +627,14 @@ function ProcessGroupSection({
612
627
  <SummaryChip label="OUT" value={formatTokenCount(totals.outputTokens)} />
613
628
  </span>
614
629
  )}
615
- <span className="bg-white/[0.04] hover:bg-white/[0.07] inline-flex size-7 shrink-0 items-center justify-center rounded-md text-slate-300">
630
+ <span className="inline-flex size-7 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground transition-colors hover:bg-[var(--inspector-surface-medium)]">
616
631
  {collapsed ? <ChevronRight className="size-4" /> : <ChevronDown className="size-4" />}
617
632
  </span>
618
633
  </span>
619
634
  </button>
620
635
 
621
636
  {!collapsed && (
622
- <div className="space-y-1.5 pb-1 pl-4 pr-1 pt-1.5">
637
+ <div className="space-y-1 pb-1 pl-3 pr-1 pt-1">
623
638
  {group.sessions.map((session) => (
624
639
  <ConversationGroup
625
640
  key={session.id}
@@ -22,7 +22,7 @@ import { ProviderLogoStack } from "./ProviderLogoStack";
22
22
  import { resolveLogFormat } from "./log-formats";
23
23
 
24
24
  const HEADER_ACTION_BUTTON_CLASS =
25
- "bg-white/[0.045] hover:bg-white/[0.075] inline-flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors hover:text-foreground";
25
+ "inline-flex size-8 shrink-0 cursor-pointer items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground transition-colors hover:bg-[var(--inspector-surface-medium)] hover:text-foreground";
26
26
 
27
27
  export function isSyntheticSessionId(conversationId: string): boolean {
28
28
  return (
@@ -34,7 +34,7 @@ export function isSyntheticSessionId(conversationId: string): boolean {
34
34
  }
35
35
 
36
36
  export function compactSessionLabel(conversationId: string): string {
37
- if (isSyntheticSessionId(conversationId)) return "Sessionless";
37
+ if (isSyntheticSessionId(conversationId)) return "No session ID";
38
38
  return conversationId.length > 24
39
39
  ? `${conversationId.slice(0, 12)}...${conversationId.slice(-12)}`
40
40
  : conversationId;
@@ -54,7 +54,7 @@ function HeaderMetric({
54
54
  return (
55
55
  <span
56
56
  className={cn(
57
- "bg-white/[0.045] inline-flex h-7 min-w-0 items-center gap-1.5 rounded-md px-2 text-xs text-muted-foreground",
57
+ "inline-flex h-7 min-w-0 items-center gap-1.5 rounded-md bg-[var(--inspector-surface-low)] px-2 text-xs text-muted-foreground",
58
58
  className,
59
59
  )}
60
60
  title={title}
@@ -68,7 +68,7 @@ function HeaderMetric({
68
68
  function PendingTurnBadge(): JSX.Element {
69
69
  return (
70
70
  <span
71
- className="inline-flex h-6 shrink-0 items-center gap-1.5 rounded-md bg-amber-300/[0.10] px-1.5 font-mono text-[10px] uppercase text-amber-100/90 ring-1 ring-amber-200/10"
71
+ className="inline-flex h-6 shrink-0 items-center gap-1.5 rounded-md bg-[var(--inspector-surface-medium)] px-1.5 font-mono text-[10px] uppercase text-[var(--inspector-status-watch)] ring-1 ring-border/50"
72
72
  title="This session has a turn that has not finished yet"
73
73
  >
74
74
  <Loader2 className="size-3 animate-spin" />
@@ -174,11 +174,11 @@ export function ConversationHeader({
174
174
  data-nav-id={`conv-${conversationId}`}
175
175
  data-nav-action={expanded ? "collapse" : "expand"}
176
176
  className={cn(
177
- "bg-black/[0.10] relative flex cursor-pointer items-start gap-2.5 overflow-hidden rounded-[8px] px-3 py-2.5 transition-colors",
178
- "hover:bg-black/[0.16]",
177
+ "relative flex cursor-pointer items-start gap-2.5 overflow-hidden rounded-md bg-[var(--inspector-surface-low)] px-3 py-2.5 transition-colors",
178
+ "hover:bg-[var(--inspector-surface-medium)]",
179
179
  "select-none",
180
180
  "sticky top-0 z-10 mb-2",
181
- "focus-visible:ring-1 focus-visible:ring-cyan-300/35 focus-visible:outline-none",
181
+ "focus-visible:ring-1 focus-visible:ring-ring focus-visible:outline-none",
182
182
  )}
183
183
  onClick={onToggle}
184
184
  onKeyDown={(e) => {
@@ -198,20 +198,20 @@ export function ConversationHeader({
198
198
 
199
199
  <span className="min-w-0 flex-1">
200
200
  <span className="flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1">
201
- <span className="shrink-0 rounded bg-white/[0.04] px-1.5 py-0.5 font-mono text-[9px] uppercase text-muted-foreground/70">
201
+ <span className="shrink-0 rounded bg-[var(--inspector-surface-medium)] px-1.5 py-0.5 font-mono text-[9px] uppercase text-muted-foreground">
202
202
  Session
203
203
  </span>
204
204
  {isFallbackConversation && showProcessMetadata ? (
205
205
  clientPid !== null && clientPid !== undefined ? (
206
206
  <span
207
- className="min-w-0 max-w-full truncate font-mono text-xs font-semibold text-slate-100"
207
+ className="min-w-0 max-w-full truncate font-mono text-xs font-semibold text-foreground"
208
208
  title={`PID ${clientPid}`}
209
209
  >
210
210
  PID {clientPid}
211
211
  </span>
212
212
  ) : (
213
213
  <span
214
- className="min-w-0 max-w-full truncate font-mono text-xs font-semibold text-slate-100"
214
+ className="min-w-0 max-w-full truncate font-mono text-xs font-semibold text-foreground"
215
215
  title={conversationId}
216
216
  >
217
217
  {conversationId}
@@ -219,7 +219,7 @@ export function ConversationHeader({
219
219
  )
220
220
  ) : (
221
221
  <span
222
- className="min-w-0 max-w-full truncate font-mono text-xs font-semibold text-slate-100"
222
+ className="min-w-0 max-w-full truncate font-mono text-xs font-semibold text-foreground"
223
223
  title={conversationId}
224
224
  >
225
225
  {sessionLabel}
@@ -231,7 +231,7 @@ export function ConversationHeader({
231
231
  clientPid !== null &&
232
232
  clientPid !== undefined && (
233
233
  <span
234
- className="bg-white/[0.045] shrink-0 rounded px-1.5 py-0.5 font-mono text-xs tabular-nums text-muted-foreground"
234
+ className="shrink-0 rounded bg-[var(--inspector-surface-medium)] px-1.5 py-0.5 font-mono text-xs tabular-nums text-muted-foreground"
235
235
  title={`Client process ID ${clientPid}`}
236
236
  >
237
237
  PID {clientPid}
@@ -253,7 +253,7 @@ export function ConversationHeader({
253
253
 
254
254
  {showClientIdentity && clientDisplayLabel !== null && clientDisplayLabel !== "" && (
255
255
  <span
256
- className="bg-white/[0.045] inline-flex min-h-6 shrink-0 flex-wrap items-center gap-1 rounded-md px-1.5 py-0.5 text-xs text-muted-foreground"
256
+ className="inline-flex min-h-6 shrink-0 flex-wrap items-center gap-1 rounded-md bg-[var(--inspector-surface-medium)] px-1.5 py-0.5 text-xs text-muted-foreground"
257
257
  title={clientTooltip ?? clientDisplayLabel}
258
258
  >
259
259
  <ClientLogo client={clientApp} className="size-4 shrink-0" decorative={true} />
@@ -272,9 +272,13 @@ export function ConversationHeader({
272
272
  {callsLabel}
273
273
  </HeaderMetric>
274
274
  <HeaderMetric icon={<Zap className="size-3 shrink-0" />} className="max-w-full">
275
- <span className="text-blue-400">{formatTokens(totalInputTokens)}</span>
275
+ <span className="text-[var(--inspector-status-info)]">
276
+ {formatTokens(totalInputTokens)}
277
+ </span>
276
278
  {" / "}
277
- <span className="text-amber-400">{formatTokens(totalOutputTokens)}</span>
279
+ <span className="text-[var(--inspector-status-watch)]">
280
+ {formatTokens(totalOutputTokens)}
281
+ </span>
278
282
  </HeaderMetric>
279
283
  </span>
280
284
  </span>
@@ -311,7 +315,7 @@ export function ConversationHeader({
311
315
 
312
316
  {/* Expand chevron - shows spinner when collapsed and group has pending logs */}
313
317
  <span
314
- className="bg-white/[0.045] hover:bg-white/[0.075] inline-flex size-8 shrink-0 items-center justify-center rounded-md text-slate-200"
318
+ className="inline-flex size-8 shrink-0 items-center justify-center rounded-md bg-[var(--inspector-surface-low)] text-muted-foreground transition-colors hover:bg-[var(--inspector-surface-medium)] hover:text-foreground"
315
319
  aria-hidden="true"
316
320
  >
317
321
  {expanded ? (
@@ -326,10 +330,10 @@ export function ConversationHeader({
326
330
 
327
331
  {isLoading && (
328
332
  <span
329
- className="pointer-events-none absolute inset-x-3 bottom-0 h-px overflow-hidden rounded-full bg-white/[0.06]"
333
+ className="pointer-events-none absolute inset-x-3 bottom-0 h-px overflow-hidden rounded-full bg-[var(--inspector-surface-medium)]"
330
334
  aria-hidden="true"
331
335
  >
332
- <span className="absolute inset-y-0 left-0 w-1/3 animate-pulse rounded-full bg-amber-200/65 shadow-[0_0_14px_rgba(252,211,77,0.32)]" />
336
+ <span className="absolute inset-y-0 left-0 w-1/3 animate-pulse rounded-full bg-[var(--inspector-status-watch)] opacity-70" />
333
337
  </span>
334
338
  )}
335
339
 
package/src/lib/utils.ts CHANGED
@@ -6,7 +6,11 @@ export function cn(...inputs: ClassValue[]): string {
6
6
  }
7
7
 
8
8
  export function formatTokens(count: number): string {
9
- if (count >= 1_000_000) return (count / 1_000_000).toFixed(1).replace(/\.0$/, "") + "M";
9
+ const absoluteCount = Math.abs(count);
10
+ if (absoluteCount < 1000) return String(count);
11
+ if (absoluteCount >= 1_000_000) {
12
+ return (count / 1_000_000).toFixed(1).replace(/\.0$/, "") + "M";
13
+ }
10
14
  return (count / 1000).toFixed(1).replace(/\.0$/, "") + "K";
11
15
  }
12
16