@tonyclaw/agent-inspector 2.1.22 → 2.1.24

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 (43) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-B-I_z_oJ.js → CompareDrawer-DsHSCHSx.js} +1 -1
  3. package/.output/public/assets/ProxyViewerContainer-GI3xErl5.js +106 -0
  4. package/.output/public/assets/{ReplayDialog-ofqVRdc-.js → ReplayDialog-D0ixqStX.js} +1 -1
  5. package/.output/public/assets/{RequestAnatomy-lyPjHWzS.js → RequestAnatomy-BG5mb14k.js} +1 -1
  6. package/.output/public/assets/ResponseView-Bgns6xum.js +3 -0
  7. package/.output/public/assets/{StreamingChunkSequence-CIn2xdVv.js → StreamingChunkSequence-BeqKXAS6.js} +1 -1
  8. package/.output/public/assets/{_sessionId-KmeAKZJw.js → _sessionId-Nme0kuTf.js} +1 -1
  9. package/.output/public/assets/index-CUKpd9jb.js +1 -0
  10. package/.output/public/assets/index-Tq5s9NV0.css +1 -0
  11. package/.output/public/assets/{index-M6p8Q0LA.js → index-hbDdeKtc.js} +1 -1
  12. package/.output/public/assets/{json-viewer-VR9OOnl8.js → json-viewer-CWxF2eLV.js} +1 -1
  13. package/.output/public/assets/{main-C9gW57P6.js → main-BDfcCp_1.js} +2 -2
  14. package/.output/server/{_sessionId-CBwwWBFg.mjs → _sessionId-DOHtZHvJ.mjs} +2 -2
  15. package/.output/server/_ssr/{CompareDrawer-Dw6CL_qf.mjs → CompareDrawer-HMfALocK.mjs} +2 -2
  16. package/.output/server/_ssr/{ProxyViewerContainer-BX4RgrZU.mjs → ProxyViewerContainer-DgnyaJPd.mjs} +2680 -2642
  17. package/.output/server/_ssr/{ReplayDialog-DS9K_cof.mjs → ReplayDialog-DyIQdJHE.mjs} +3 -3
  18. package/.output/server/_ssr/{RequestAnatomy-B2JsAL49.mjs → RequestAnatomy-8v4e8mYT.mjs} +2 -2
  19. package/.output/server/_ssr/{ResponseView-C3LQSg2c.mjs → ResponseView-D17WnkXv.mjs} +201 -54
  20. package/.output/server/_ssr/{StreamingChunkSequence-O1Ti-7Pk.mjs → StreamingChunkSequence-CALVBf-R.mjs} +2 -2
  21. package/.output/server/_ssr/{index-BZ2ijzyu.mjs → index-D8EDemF-.mjs} +2 -2
  22. package/.output/server/_ssr/index.mjs +2 -2
  23. package/.output/server/_ssr/{json-viewer-BRMmlvXb.mjs → json-viewer-BgrtJGqX.mjs} +2 -2
  24. package/.output/server/_ssr/{router-DlGZ0qLz.mjs → router-D3qLyERI.mjs} +4 -4
  25. package/.output/server/{_tanstack-start-manifest_v-CYvWDgeN.mjs → _tanstack-start-manifest_v-6qZpokPP.mjs} +1 -1
  26. package/.output/server/index.mjs +70 -70
  27. package/package.json +1 -1
  28. package/src/components/ProxyViewer.tsx +28 -23
  29. package/src/components/proxy-viewer/LogEntry.tsx +10 -0
  30. package/src/components/proxy-viewer/ResponseView.tsx +5 -1
  31. package/src/components/proxy-viewer/ToolTraceEvents.tsx +19 -31
  32. package/src/components/proxy-viewer/TurnGroup.tsx +21 -7
  33. package/src/components/proxy-viewer/formats/anthropic/ContentBlocks.tsx +37 -4
  34. package/src/components/proxy-viewer/formats/anthropic/ResponseView.tsx +17 -3
  35. package/src/components/proxy-viewer/formats/index.tsx +8 -3
  36. package/src/components/proxy-viewer/formats/openai/ResponseView.tsx +122 -16
  37. package/src/components/proxy-viewer/logFocus.ts +11 -3
  38. package/src/components/proxy-viewer/viewerState.ts +22 -7
  39. package/src/components/ui/icon-trigger.ts +1 -1
  40. package/.output/public/assets/ProxyViewerContainer-ygSGJ4EB.js +0 -106
  41. package/.output/public/assets/ResponseView-BL263es5.js +0 -3
  42. package/.output/public/assets/index-DFEiGFKE.js +0 -1
  43. package/.output/public/assets/index-bXU6y_wh.css +0 -1
@@ -38,114 +38,114 @@ const assets = {
38
38
  "/assets/alibaba-TTwafVwX.svg": {
39
39
  "type": "image/svg+xml",
40
40
  "etag": '"171b-6dyV5K8QjiaY35sN9qNprh9zDIs"',
41
- "mtime": "2026-07-06T08:42:14.499Z",
41
+ "mtime": "2026-07-06T23:47:30.045Z",
42
42
  "size": 5915,
43
43
  "path": "../public/assets/alibaba-TTwafVwX.svg"
44
44
  },
45
- "/assets/CompareDrawer-B-I_z_oJ.js": {
45
+ "/assets/index-CUKpd9jb.js": {
46
46
  "type": "text/javascript; charset=utf-8",
47
- "etag": '"4bbf-boMYNxH3OYElTxrB6f+S8JpJhEU"',
48
- "mtime": "2026-07-06T08:42:14.500Z",
49
- "size": 19391,
50
- "path": "../public/assets/CompareDrawer-B-I_z_oJ.js"
47
+ "etag": '"74-S5coP0OJAkI32YF22K1A7pIhhaQ"',
48
+ "mtime": "2026-07-06T23:47:30.045Z",
49
+ "size": 116,
50
+ "path": "../public/assets/index-CUKpd9jb.js"
51
51
  },
52
- "/assets/json-viewer-VR9OOnl8.js": {
52
+ "/assets/json-viewer-CWxF2eLV.js": {
53
53
  "type": "text/javascript; charset=utf-8",
54
- "etag": '"1ae6-q2HRnhbr4RmbtnJRlXqA3AA5pn0"',
55
- "mtime": "2026-07-06T08:42:14.500Z",
54
+ "etag": '"1ae6-W5gyZM3eWBF1xbeKMyl4smbFfEM"',
55
+ "mtime": "2026-07-06T23:47:30.047Z",
56
56
  "size": 6886,
57
- "path": "../public/assets/json-viewer-VR9OOnl8.js"
57
+ "path": "../public/assets/json-viewer-CWxF2eLV.js"
58
58
  },
59
- "/assets/index-DFEiGFKE.js": {
59
+ "/assets/CompareDrawer-DsHSCHSx.js": {
60
60
  "type": "text/javascript; charset=utf-8",
61
- "etag": '"74-qVbgeAxjdS6pAIAlbzvrFevVSso"',
62
- "mtime": "2026-07-06T08:42:14.500Z",
63
- "size": 116,
64
- "path": "../public/assets/index-DFEiGFKE.js"
61
+ "etag": '"4bbf-nlyV9TgErKS/2wxRBsjCrr8IQBo"',
62
+ "mtime": "2026-07-06T23:47:30.047Z",
63
+ "size": 19391,
64
+ "path": "../public/assets/CompareDrawer-DsHSCHSx.js"
65
65
  },
66
- "/assets/index-M6p8Q0LA.js": {
67
- "type": "text/javascript; charset=utf-8",
68
- "etag": '"1cd2c-dKmvWl4iX4kQEQiFVvEkD2o9yeo"',
69
- "mtime": "2026-07-06T08:42:14.500Z",
70
- "size": 118060,
71
- "path": "../public/assets/index-M6p8Q0LA.js"
66
+ "/assets/index-Tq5s9NV0.css": {
67
+ "type": "text/css; charset=utf-8",
68
+ "etag": '"22408-MQKT02eqQudVEj/DozyiEJoTl6E"',
69
+ "mtime": "2026-07-06T23:47:30.045Z",
70
+ "size": 140296,
71
+ "path": "../public/assets/index-Tq5s9NV0.css"
72
72
  },
73
73
  "/assets/minimax-BPMzvuL-.jpeg": {
74
74
  "type": "image/jpeg",
75
75
  "etag": '"1b06-IwivU89ko5UTMUM1/t7hn4sQK9A"',
76
- "mtime": "2026-07-06T08:42:14.499Z",
76
+ "mtime": "2026-07-06T23:47:30.042Z",
77
77
  "size": 6918,
78
78
  "path": "../public/assets/minimax-BPMzvuL-.jpeg"
79
79
  },
80
- "/assets/main-C9gW57P6.js": {
80
+ "/assets/RequestAnatomy-BG5mb14k.js": {
81
81
  "type": "text/javascript; charset=utf-8",
82
- "etag": '"512fd-Qkx6OXZVaW68qCJzUwcgoV0n85s"',
83
- "mtime": "2026-07-06T08:42:14.499Z",
84
- "size": 332541,
85
- "path": "../public/assets/main-C9gW57P6.js"
82
+ "etag": '"43f2-5+JmeO4mEgbfXx4qZ0z/5j/kGC0"',
83
+ "mtime": "2026-07-06T23:47:30.047Z",
84
+ "size": 17394,
85
+ "path": "../public/assets/RequestAnatomy-BG5mb14k.js"
86
86
  },
87
- "/assets/ReplayDialog-ofqVRdc-.js": {
87
+ "/assets/StreamingChunkSequence-BeqKXAS6.js": {
88
88
  "type": "text/javascript; charset=utf-8",
89
- "etag": '"31d6-1x+H2vdKEwKrpalZioFQypNeHQk"',
90
- "mtime": "2026-07-06T08:42:14.500Z",
91
- "size": 12758,
92
- "path": "../public/assets/ReplayDialog-ofqVRdc-.js"
89
+ "etag": '"dd6-+UuLiAyXfMce8K34YDVdE2+W+dQ"',
90
+ "mtime": "2026-07-06T23:47:30.047Z",
91
+ "size": 3542,
92
+ "path": "../public/assets/StreamingChunkSequence-BeqKXAS6.js"
93
93
  },
94
- "/assets/index-bXU6y_wh.css": {
95
- "type": "text/css; charset=utf-8",
96
- "etag": '"21894-+/BIDNcJdO1E5wKWMCSoJKkp5xY"',
97
- "mtime": "2026-07-06T08:42:14.499Z",
98
- "size": 137364,
99
- "path": "../public/assets/index-bXU6y_wh.css"
94
+ "/assets/zhipuai-BPNAnxo-.svg": {
95
+ "type": "image/svg+xml",
96
+ "etag": '"2bf8-hNaLCTi89nOFCsIIfWpP/jrfo0s"',
97
+ "mtime": "2026-07-06T23:47:30.045Z",
98
+ "size": 11256,
99
+ "path": "../public/assets/zhipuai-BPNAnxo-.svg"
100
100
  },
101
- "/assets/RequestAnatomy-lyPjHWzS.js": {
101
+ "/assets/main-BDfcCp_1.js": {
102
102
  "type": "text/javascript; charset=utf-8",
103
- "etag": '"43f2-dm2JSsxHwTjClZaY75s6pB3OCRE"',
104
- "mtime": "2026-07-06T08:42:14.500Z",
105
- "size": 17394,
106
- "path": "../public/assets/RequestAnatomy-lyPjHWzS.js"
103
+ "etag": '"512fd-wNI+QxyzwhA/0QqJbbcpb3MMxmg"',
104
+ "mtime": "2026-07-06T23:47:30.047Z",
105
+ "size": 332541,
106
+ "path": "../public/assets/main-BDfcCp_1.js"
107
107
  },
108
- "/assets/StreamingChunkSequence-CIn2xdVv.js": {
108
+ "/assets/ReplayDialog-D0ixqStX.js": {
109
109
  "type": "text/javascript; charset=utf-8",
110
- "etag": '"dd6-1z9xyDwQxM73GFtieH0lBUQMPeo"',
111
- "mtime": "2026-07-06T08:42:14.500Z",
112
- "size": 3542,
113
- "path": "../public/assets/StreamingChunkSequence-CIn2xdVv.js"
110
+ "etag": '"31d6-kYb7AI9zYbXu6Y118c89CIIKsQk"',
111
+ "mtime": "2026-07-06T23:47:30.047Z",
112
+ "size": 12758,
113
+ "path": "../public/assets/ReplayDialog-D0ixqStX.js"
114
114
  },
115
- "/assets/ResponseView-BL263es5.js": {
115
+ "/assets/ResponseView-Bgns6xum.js": {
116
116
  "type": "text/javascript; charset=utf-8",
117
- "etag": '"3fbb-YhzY74QAmiktBkyeD8ZWACFw+Rc"',
118
- "mtime": "2026-07-06T08:42:14.500Z",
119
- "size": 16315,
120
- "path": "../public/assets/ResponseView-BL263es5.js"
117
+ "etag": '"47fa-9tCNwF7F78L1zRC3UidiQKud7L8"',
118
+ "mtime": "2026-07-06T23:47:30.047Z",
119
+ "size": 18426,
120
+ "path": "../public/assets/ResponseView-Bgns6xum.js"
121
121
  },
122
- "/assets/_sessionId-KmeAKZJw.js": {
122
+ "/assets/_sessionId-Nme0kuTf.js": {
123
123
  "type": "text/javascript; charset=utf-8",
124
- "etag": '"36c-l3ljkLbVkD0313o3NVfJSSh4zLI"',
125
- "mtime": "2026-07-06T08:42:14.499Z",
124
+ "etag": '"36c-gpP2xqLaqXgb4GOWSbhVDrqjv3g"',
125
+ "mtime": "2026-07-06T23:47:30.045Z",
126
126
  "size": 876,
127
- "path": "../public/assets/_sessionId-KmeAKZJw.js"
128
- },
129
- "/assets/zhipuai-BPNAnxo-.svg": {
130
- "type": "image/svg+xml",
131
- "etag": '"2bf8-hNaLCTi89nOFCsIIfWpP/jrfo0s"',
132
- "mtime": "2026-07-06T08:42:14.499Z",
133
- "size": 11256,
134
- "path": "../public/assets/zhipuai-BPNAnxo-.svg"
127
+ "path": "../public/assets/_sessionId-Nme0kuTf.js"
135
128
  },
136
129
  "/assets/qwen-CONDcHqt.png": {
137
130
  "type": "image/png",
138
131
  "etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
139
- "mtime": "2026-07-06T08:42:14.500Z",
132
+ "mtime": "2026-07-06T23:47:30.045Z",
140
133
  "size": 357059,
141
134
  "path": "../public/assets/qwen-CONDcHqt.png"
142
135
  },
143
- "/assets/ProxyViewerContainer-ygSGJ4EB.js": {
136
+ "/assets/index-hbDdeKtc.js": {
137
+ "type": "text/javascript; charset=utf-8",
138
+ "etag": '"1cd2c-o4cSL+ZBVABZPPb9xrCnibEnQQQ"',
139
+ "mtime": "2026-07-06T23:47:30.047Z",
140
+ "size": 118060,
141
+ "path": "../public/assets/index-hbDdeKtc.js"
142
+ },
143
+ "/assets/ProxyViewerContainer-GI3xErl5.js": {
144
144
  "type": "text/javascript; charset=utf-8",
145
- "etag": '"aec2b-qUHkR4rnnxAag/CXPZQmFBfa3hA"',
146
- "mtime": "2026-07-06T08:42:14.500Z",
147
- "size": 715819,
148
- "path": "../public/assets/ProxyViewerContainer-ygSGJ4EB.js"
145
+ "etag": '"aef16-1fUWo2IWu+2OgSdsAPCGVYmzUNU"',
146
+ "mtime": "2026-07-06T23:47:30.047Z",
147
+ "size": 716566,
148
+ "path": "../public/assets/ProxyViewerContainer-GI3xErl5.js"
149
149
  }
150
150
  };
151
151
  function readAsset(id) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonyclaw/agent-inspector",
3
- "version": "2.1.22",
3
+ "version": "2.1.24",
4
4
  "type": "module",
5
5
  "description": "Agent observability and knowledge capture layer for AI coding tools.",
6
6
  "license": "MIT",
@@ -1151,7 +1151,7 @@ function CopyableCommand({ command }: { command: string }): JSX.Element {
1151
1151
  }, [command]);
1152
1152
 
1153
1153
  return (
1154
- <div className="border border-border bg-muted/40 inline-flex max-w-full items-center gap-2 rounded-md px-3 py-2">
1154
+ <div className="bg-black/20 inline-flex max-w-full items-center gap-2 rounded-md px-3 py-2 shadow-[inset_0_0_0_1px_rgba(255,255,255,0.055)]">
1155
1155
  <pre className="m-0 overflow-x-auto font-mono text-sm text-cyan-200">{command}</pre>
1156
1156
  <button
1157
1157
  type="button"
@@ -1170,7 +1170,7 @@ function McpReadyBadge(): JSX.Element {
1170
1170
  <TooltipProvider>
1171
1171
  <Tooltip>
1172
1172
  <TooltipTrigger asChild>
1173
- <span className="border border-border bg-muted/40 inline-flex h-7 items-center gap-2 rounded-md px-2.5 font-mono text-[11px] font-medium text-cyan-200">
1173
+ <span className="bg-cyan-300/[0.055] shadow-[inset_0_1px_0_rgba(255,255,255,0.05)] inline-flex h-7 items-center gap-2 rounded-md px-2.5 font-mono text-[11px] font-medium text-cyan-200">
1174
1174
  <span className="size-1.5 rounded-full bg-cyan-200 shadow-[0_0_8px_rgba(125,211,252,0.75)]" />
1175
1175
  MCP Ready
1176
1176
  <span className="hidden text-cyan-200/70 sm:inline">/api/mcp</span>
@@ -1195,20 +1195,25 @@ function SidebarPanel({
1195
1195
  className?: string;
1196
1196
  }): JSX.Element {
1197
1197
  return (
1198
- <section className={cn("border border-border bg-card shadow-sm rounded-[8px]", className)}>
1199
- <div className="border-b border-white/10 px-3 py-2">
1200
- <div className="font-mono text-[10px] font-semibold uppercase tracking-[0.14em] text-white/40">
1198
+ <section
1199
+ className={cn(
1200
+ "bg-white/[0.028] shadow-[inset_0_1px_0_rgba(255,255,255,0.035)] rounded-[8px]",
1201
+ className,
1202
+ )}
1203
+ >
1204
+ <div className="px-3 pt-3">
1205
+ <div className="font-mono text-[10px] font-semibold uppercase tracking-[0.14em] text-white/35">
1201
1206
  {label}
1202
1207
  </div>
1203
1208
  </div>
1204
- <div className="p-3">{children}</div>
1209
+ <div className="p-3 pt-2">{children}</div>
1205
1210
  </section>
1206
1211
  );
1207
1212
  }
1208
1213
 
1209
1214
  function SidebarMetric({ label, value }: { label: string; value: string | number }): JSX.Element {
1210
1215
  return (
1211
- <div className="border border-border bg-muted/40 min-w-0 rounded-md px-2 py-2">
1216
+ <div className="bg-black/20 min-w-0 rounded-md px-2 py-2 shadow-[inset_0_1px_0_rgba(255,255,255,0.035)]">
1212
1217
  <div className="truncate font-mono text-lg font-semibold leading-6 text-slate-100">
1213
1218
  {value}
1214
1219
  </div>
@@ -1282,7 +1287,7 @@ function BrandHeader({
1282
1287
  }): JSX.Element {
1283
1288
  if (compact) {
1284
1289
  return (
1285
- <div className="border border-border bg-card shadow-sm rounded-[8px] p-3">
1290
+ <div className="bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.045),0_16px_44px_rgba(0,0,0,0.18)] rounded-[8px] p-3">
1286
1291
  <div className="flex items-start justify-between gap-3">
1287
1292
  <div className="flex min-w-0 items-start gap-2">
1288
1293
  <CrabFamily compact={true} entrancePhase={crabEntrancePhase} />
@@ -1583,7 +1588,7 @@ function SessionContextBar({
1583
1588
  {showBackLink && (
1584
1589
  <a
1585
1590
  href="/"
1586
- className="border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex size-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:text-foreground"
1591
+ className="bg-white/[0.035] hover:bg-white/[0.065] inline-flex size-8 shrink-0 items-center justify-center rounded-md text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground"
1587
1592
  aria-label="Back to all sessions"
1588
1593
  title="Back to all sessions"
1589
1594
  >
@@ -1620,7 +1625,7 @@ function SessionContextBar({
1620
1625
  <button
1621
1626
  type="button"
1622
1627
  onClick={() => setDetailsOpen((value) => !value)}
1623
- className="border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex h-8 shrink-0 items-center gap-1.5 rounded-md px-2.5 font-mono text-[11px] text-muted-foreground transition-colors hover:text-foreground"
1628
+ className="bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 shrink-0 items-center gap-1.5 rounded-md px-2.5 font-mono text-[11px] text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground"
1624
1629
  aria-expanded={detailsOpen}
1625
1630
  title={detailsOpen ? "Hide context details" : "Show context details"}
1626
1631
  >
@@ -1635,7 +1640,7 @@ function SessionContextBar({
1635
1640
  <button
1636
1641
  type="button"
1637
1642
  onClick={handleCopyLink}
1638
- className="border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex size-8 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:text-foreground"
1643
+ className="bg-white/[0.035] hover:bg-white/[0.065] inline-flex size-8 shrink-0 items-center justify-center rounded-md text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground"
1639
1644
  aria-label={copied ? "Copied session link" : "Copy session link"}
1640
1645
  title={copied ? "Copied session link" : "Copy session link"}
1641
1646
  >
@@ -1877,7 +1882,7 @@ export function ProxyViewer({
1877
1882
  return (
1878
1883
  <div className="bg-background min-h-screen w-full text-foreground">
1879
1884
  <div className="grid min-h-screen w-full grid-cols-1 lg:grid-cols-[340px_minmax(0,1fr)] xl:grid-cols-[360px_minmax(0,1fr)]">
1880
- <aside className="bg-background border-b lg:sticky lg:top-0 lg:h-screen lg:overflow-y-auto lg:border-b-0 lg:border-r">
1885
+ <aside className="bg-background/95 border-b border-white/[0.045] lg:sticky lg:top-0 lg:h-screen lg:overflow-y-auto lg:border-b-0 lg:border-r lg:border-white/[0.055]">
1881
1886
  <div className="space-y-4 p-4">
1882
1887
  <BrandHeader compact={true} crabEntrancePhase={crabEntrancePhase} />
1883
1888
 
@@ -1896,7 +1901,7 @@ export function ProxyViewer({
1896
1901
  </SidebarPanel>
1897
1902
 
1898
1903
  <SidebarPanel label="Workspace">
1899
- <div className="border border-border bg-muted/40 rounded-md px-3 py-2">
1904
+ <div className="bg-black/20 rounded-md px-3 py-2 shadow-[inset_0_1px_0_rgba(255,255,255,0.035)]">
1900
1905
  <div
1901
1906
  className="truncate font-mono text-xs font-semibold text-cyan-100"
1902
1907
  title={activeScopeLabel}
@@ -1938,7 +1943,7 @@ export function ProxyViewer({
1938
1943
  value={sessionInputValue}
1939
1944
  onChange={handleSessionInputChange}
1940
1945
  placeholder="Paste session ID"
1941
- className="border border-input bg-background hover:bg-accent focus-visible:ring-ring h-9 w-full rounded-md px-8 font-mono text-xs text-foreground outline-none transition-colors placeholder:font-sans placeholder:text-muted-foreground focus-visible:ring-1"
1946
+ className="bg-black/25 hover:bg-white/[0.045] focus-visible:ring-ring h-9 w-full rounded-md px-8 font-mono text-xs text-foreground outline-none shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors placeholder:font-sans placeholder:text-muted-foreground focus-visible:ring-1"
1942
1947
  aria-label="Filter by session ID"
1943
1948
  title="Filter by exact session ID"
1944
1949
  />
@@ -1955,7 +1960,7 @@ export function ProxyViewer({
1955
1960
  )}
1956
1961
  </div>
1957
1962
  <Select value={sessionSelectValue} onValueChange={handleSessionSelectChange}>
1958
- <SelectTrigger className="border border-input bg-background hover:bg-accent hover:text-accent-foreground h-9 w-full text-xs">
1963
+ <SelectTrigger className="bg-black/25 hover:bg-white/[0.045] h-9 w-full border-0 text-xs text-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)]">
1959
1964
  <SelectValue placeholder="All sessions" />
1960
1965
  </SelectTrigger>
1961
1966
  <SelectContent>
@@ -1975,7 +1980,7 @@ export function ProxyViewer({
1975
1980
  </>
1976
1981
  )}
1977
1982
  <Select value={selectedModel} onValueChange={onModelChange}>
1978
- <SelectTrigger className="border border-input bg-background hover:bg-accent hover:text-accent-foreground h-9 w-full text-xs">
1983
+ <SelectTrigger className="bg-black/25 hover:bg-white/[0.045] h-9 w-full border-0 text-xs text-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)]">
1979
1984
  <SelectValue placeholder="All models" />
1980
1985
  </SelectTrigger>
1981
1986
  <SelectContent>
@@ -1993,7 +1998,7 @@ export function ProxyViewer({
1993
1998
  </aside>
1994
1999
 
1995
2000
  <main className="min-w-0">
1996
- <div className="border border-border bg-background/95 shadow-sm sticky top-0 z-30 border-b px-4 py-3 lg:px-5">
2001
+ <div className="bg-background/95 shadow-[0_12px_36px_rgba(0,0,0,0.18),inset_0_-1px_0_rgba(255,255,255,0.045)] sticky top-0 z-30 px-4 py-3 lg:px-5">
1997
2002
  <div className="flex flex-wrap items-center gap-2">
1998
2003
  <div className="min-w-[180px] flex-1">
1999
2004
  <div className="text-sm font-semibold text-foreground">Logs</div>
@@ -2014,7 +2019,7 @@ export function ProxyViewer({
2014
2019
  type="button"
2015
2020
  onClick={handleImportClick}
2016
2021
  disabled={importing}
2017
- className="border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50"
2022
+ className="bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50"
2018
2023
  title="Import Agent Inspector export"
2019
2024
  >
2020
2025
  {importing ? (
@@ -2035,7 +2040,7 @@ export function ProxyViewer({
2035
2040
  void handleExport("redacted");
2036
2041
  }}
2037
2042
  disabled={exporting !== null}
2038
- className="border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50"
2043
+ className="bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50"
2039
2044
  title="Export redacted logs as JSON ZIP"
2040
2045
  >
2041
2046
  {exporting === "redacted" ? (
@@ -2055,7 +2060,7 @@ export function ProxyViewer({
2055
2060
  void handleExport("raw");
2056
2061
  }}
2057
2062
  disabled={exporting !== null}
2058
- className="border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs text-muted-foreground transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50"
2063
+ className="bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-2.5 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50"
2059
2064
  title="Export raw logs without redaction"
2060
2065
  >
2061
2066
  {exporting === "raw" ? (
@@ -2071,7 +2076,7 @@ export function ProxyViewer({
2071
2076
  <button
2072
2077
  type="button"
2073
2078
  onClick={onClearAll}
2074
- className="border border-input bg-background hover:bg-accent hover:text-accent-foreground inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground transition-colors hover:text-foreground"
2079
+ className="bg-white/[0.035] hover:bg-white/[0.065] inline-flex h-8 items-center gap-1.5 rounded-md px-3 text-xs text-muted-foreground shadow-[inset_0_0_0_1px_rgba(255,255,255,0.06)] transition-colors hover:text-foreground"
2075
2080
  title="Clear all logs"
2076
2081
  >
2077
2082
  <Trash2 className="size-3.5" />
@@ -2101,7 +2106,7 @@ export function ProxyViewer({
2101
2106
  {logs.length === 0 ? (
2102
2107
  selectedSession !== "__all__" ? (
2103
2108
  <div className="py-16 text-center text-muted-foreground">
2104
- <div className="border border-border bg-card shadow-sm mx-auto max-w-xl space-y-4 rounded-[8px] px-4 py-8">
2109
+ <div className="bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.045),0_18px_52px_rgba(0,0,0,0.18)] mx-auto max-w-xl space-y-4 rounded-[8px] px-4 py-8">
2105
2110
  <p className="text-sm font-medium">
2106
2111
  {isLoading ? "Loading session data..." : "Session not found"}
2107
2112
  </p>
@@ -2135,7 +2140,7 @@ export function ProxyViewer({
2135
2140
  </div>
2136
2141
  ) : (
2137
2142
  <div className="py-16 text-center text-muted-foreground">
2138
- <div className="border border-border bg-card shadow-sm mx-auto max-w-2xl space-y-4 rounded-[8px] px-4 py-8">
2143
+ <div className="bg-white/[0.035] shadow-[inset_0_1px_0_rgba(255,255,255,0.045),0_18px_52px_rgba(0,0,0,0.18)] mx-auto max-w-2xl space-y-4 rounded-[8px] px-4 py-8">
2139
2144
  <p className="text-sm">No requests captured yet.</p>
2140
2145
  <div className="flex flex-col items-center gap-2">
2141
2146
  <CopyableCommand command="ANTHROPIC_BASE_URL=http://localhost:25947/proxy <your-tool>" />
@@ -60,6 +60,8 @@ function resolveFocusedTab(tab: LogFocusTab, anatomySegments: AnatomySegment[] |
60
60
  return anatomySegments === null ? "request" : "anatomy";
61
61
  case "request":
62
62
  return "request";
63
+ case "response":
64
+ return "parsed";
63
65
  }
64
66
  }
65
67
 
@@ -429,6 +431,8 @@ export const LogEntry = memo(function ({
429
431
  const [headersDiff, setHeadersDiff] = useState<boolean>(false);
430
432
  const [requestDiff, setRequestDiff] = useState<boolean>(false);
431
433
  const [activeTab, setActiveTab] = useState("request");
434
+ const [focusedToolIndex, setFocusedToolIndex] = useState<number | null>(null);
435
+ const [toolFocusNonce, setToolFocusNonce] = useState(0);
432
436
  const [expandToPath, setExpandToPath] = useState<string | null>(null);
433
437
  const [hydratedLog, setHydratedLog] = useState<CapturedLog | null>(null);
434
438
  const [bodyHydrationStatus, setBodyHydrationStatus] = useState<BodyHydrationStatus>("idle");
@@ -779,6 +783,10 @@ export const LogEntry = memo(function ({
779
783
  if (request.logId !== log.id) return;
780
784
  setExpanded(true);
781
785
  setActiveTab(resolveFocusedTab(request.tab, anatomySegments));
786
+ if (request.tab === "response" && request.toolCallIndex !== undefined) {
787
+ setFocusedToolIndex(request.toolCallIndex);
788
+ setToolFocusNonce((current) => current + 1);
789
+ }
782
790
  };
783
791
 
784
792
  window.addEventListener(LOG_FOCUS_REQUEST_EVENT, handleLogFocusRequest);
@@ -1120,6 +1128,8 @@ export const LogEntry = memo(function ({
1120
1128
  cacheReadInputTokens={displayLog.cacheReadInputTokens}
1121
1129
  apiFormat={resolvedFormat}
1122
1130
  error={displayLog.error}
1131
+ focusedToolIndex={focusedToolIndex}
1132
+ toolFocusNonce={toolFocusNonce}
1123
1133
  />
1124
1134
  </Suspense>
1125
1135
  )}
@@ -19,6 +19,8 @@ export type ResponseViewProps = {
19
19
  apiFormat?: ApiFormat;
20
20
  /** SSE error message from streaming response */
21
21
  error?: string | null;
22
+ focusedToolIndex?: number | null;
23
+ toolFocusNonce?: number;
22
24
  };
23
25
 
24
26
  function getStatusClasses(category: StatusCategory): string {
@@ -74,6 +76,8 @@ export const ResponseView = memo(function ResponseView({
74
76
  cacheReadInputTokens,
75
77
  apiFormat,
76
78
  error,
79
+ focusedToolIndex = null,
80
+ toolFocusNonce = 0,
77
81
  }: ResponseViewProps): JSX.Element {
78
82
  const resolvedFormat = apiFormat ?? "unknown";
79
83
  const parsed = useMemo(
@@ -128,7 +132,7 @@ export const ResponseView = memo(function ResponseView({
128
132
  return (
129
133
  <div className="space-y-2">
130
134
  <StatusIndicator status={responseStatus} />
131
- {formatViewFor(resolvedFormat, parsed)}
135
+ {formatViewFor(resolvedFormat, parsed, { focusedToolIndex, toolFocusNonce })}
132
136
  </div>
133
137
  );
134
138
  }
@@ -1,52 +1,40 @@
1
1
  import { type JSX } from "react";
2
- import { Check, ChevronRight, Copy, Wrench } from "lucide-react";
2
+ import { Wrench } from "lucide-react";
3
3
  import type { ToolTraceEvent } from "./viewerState";
4
- import { useCopyFeedback } from "./useCopyFeedback";
4
+ import { dispatchLogFocusRequest } from "./logFocus";
5
5
 
6
6
  type ToolTraceEventsProps = {
7
7
  events: ToolTraceEvent[];
8
8
  };
9
9
 
10
- function ToolTraceEventRow({ event }: { event: ToolTraceEvent }): JSX.Element {
11
- const argumentCopy = useCopyFeedback(event.argumentsText);
12
- const canCopyArguments = event.argumentsText !== null;
13
-
10
+ function ToolTraceEventChip({ event }: { event: ToolTraceEvent }): JSX.Element {
14
11
  return (
15
- <div
12
+ <button
13
+ type="button"
16
14
  key={event.id}
17
- className="group/tool-trace flex min-w-0 items-center gap-2 rounded-md bg-white/[0.035] px-2.5 py-1.5 text-xs"
15
+ className="inline-flex min-w-0 items-center gap-1.5 rounded-md bg-white/[0.035] px-2 py-1 text-xs text-muted-foreground transition-colors hover:bg-sky-400/[0.08] hover:text-sky-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
16
+ onClick={() =>
17
+ dispatchLogFocusRequest({
18
+ logId: event.logId,
19
+ tab: "response",
20
+ toolCallIndex: event.index,
21
+ })
22
+ }
23
+ aria-label={`Open response tool call ${event.name}`}
24
+ title={`Open ${event.name} in Response`}
18
25
  >
19
26
  <Wrench className="size-3.5 shrink-0 text-sky-400/70" />
20
- <span className="font-mono font-semibold text-foreground/80">{event.name}</span>
21
- {event.argumentsPreview !== null && (
22
- <>
23
- <ChevronRight className="size-3 shrink-0 text-muted-foreground/60" />
24
- <span className="min-w-0 truncate font-mono text-muted-foreground">
25
- {event.argumentsPreview}
26
- </span>
27
- </>
28
- )}
29
- {canCopyArguments && (
30
- <button
31
- type="button"
32
- className="ml-auto inline-flex size-6 shrink-0 items-center justify-center rounded text-muted-foreground opacity-0 transition-opacity hover:bg-background/80 hover:text-foreground focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring group-hover/tool-trace:opacity-100 group-focus-within/tool-trace:opacity-100"
33
- onClick={argumentCopy.copy}
34
- aria-label={argumentCopy.copied ? "Copied tool arguments" : "Copy tool arguments"}
35
- title={argumentCopy.copied ? "Copied tool arguments" : "Copy tool arguments"}
36
- >
37
- {argumentCopy.copied ? <Check className="size-3.5" /> : <Copy className="size-3.5" />}
38
- </button>
39
- )}
40
- </div>
27
+ <span className="min-w-0 truncate font-mono font-semibold">{event.name}</span>
28
+ </button>
41
29
  );
42
30
  }
43
31
 
44
32
  export function ToolTraceEvents({ events }: ToolTraceEventsProps): JSX.Element | null {
45
33
  if (events.length === 0) return null;
46
34
  return (
47
- <div className="mx-3 mb-2 grid gap-1.5">
35
+ <div className="mx-3 mb-2 flex flex-wrap gap-1.5">
48
36
  {events.map((event) => (
49
- <ToolTraceEventRow key={event.id} event={event} />
37
+ <ToolTraceEventChip key={event.id} event={event} />
50
38
  ))}
51
39
  </div>
52
40
  );
@@ -14,6 +14,7 @@ import type { TimeDisplayFormat } from "../../lib/runtimeConfig";
14
14
  import { cn, formatTokens } from "../../lib/utils";
15
15
  import type { CapturedLog } from "../../contracts";
16
16
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../ui/tooltip";
17
+ import { getCrabVariant } from "../ui/crab-variants";
17
18
  import type { CacheTrendEntry } from "./cacheTrend";
18
19
  import { LogEntry } from "./LogEntry";
19
20
  import {
@@ -177,6 +178,7 @@ export const TurnGroup = memo(function TurnGroup({
177
178
 
178
179
  const firstLogId = entries[0]?.log.id ?? turnIndex;
179
180
  const turnLabel = `Turn ${String(turnIndex + 1)}`;
181
+ const CollapsedCrab = useMemo(() => getCrabVariant(firstLogId % 12), [firstLogId]);
180
182
  const containmentStyle = useMemo<CSSProperties>(
181
183
  () => ({
182
184
  contentVisibility: "auto",
@@ -224,16 +226,28 @@ export const TurnGroup = memo(function TurnGroup({
224
226
 
225
227
  <div className="w-6 shrink-0 flex flex-col items-center pt-1.5 pb-1.5">
226
228
  <div className="flex justify-center h-[calc(0.75rem-8px)]" />
227
- <span className="size-2 rounded-full bg-cyan-300/45" />
228
- <div className="flex-1 flex justify-center min-h-0">
229
- <div className="w-px bg-muted-foreground/14 h-full" />
230
- </div>
231
- <span
229
+ <CollapsedCrab
232
230
  className={cn(
233
- "size-2 rounded-full",
234
- isComplete ? "bg-amber-300/45" : "bg-muted-foreground/25",
231
+ "size-3.5",
232
+ isPending
233
+ ? "animate-crab-crawl text-amber-300/80"
234
+ : "animate-crab-appear text-emerald-400",
235
+ isPending
236
+ ? "drop-shadow-[0_0_4px_rgba(252,211,77,0.42)]"
237
+ : "drop-shadow-[0_0_4px_rgba(52,211,153,0.45)]",
235
238
  )}
236
239
  />
240
+ <div className="flex-1 flex justify-center min-h-0">
241
+ <div className="w-px bg-muted-foreground/14 h-full" />
242
+ </div>
243
+ {isComplete && (
244
+ <CollapsedCrab
245
+ className={cn(
246
+ "size-3.5 animate-crab-settle text-amber-400",
247
+ "drop-shadow-[0_0_4px_rgba(251,191,36,0.45)]",
248
+ )}
249
+ />
250
+ )}
237
251
  </div>
238
252
 
239
253
  {/* Summary content - hidden for single-log turns. */}