@tonyclaw/agent-inspector 2.0.5 → 2.0.6

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 (39) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/{CompareDrawer-3nRwtk8J.js → CompareDrawer-DDmqSAfl.js} +1 -1
  3. package/.output/public/assets/{ProxyViewerContainer-CbW5VRER.js → ProxyViewerContainer-Cxpdziwd.js} +5 -5
  4. package/.output/public/assets/{ReplayDialog-Cl62N9PI.js → ReplayDialog-Bt5DGzlh.js} +1 -1
  5. package/.output/public/assets/RequestAnatomy-BxX3_N9S.js +1 -0
  6. package/.output/public/assets/{ResponseView-Cvc-ct4E.js → ResponseView-Bl_5S9gZ.js} +1 -1
  7. package/.output/public/assets/{StreamingChunkSequence-BCQaCAIe.js → StreamingChunkSequence-RJMwNf6F.js} +1 -1
  8. package/.output/public/assets/_sessionId-b4isaoDp.js +1 -0
  9. package/.output/public/assets/index-BZ4x5UI6.js +1 -0
  10. package/.output/public/assets/index-C624DUk9.css +1 -0
  11. package/.output/public/assets/{json-viewer-IXejqXB0.js → json-viewer-CRL_gWEZ.js} +1 -1
  12. package/.output/public/assets/{main-2NlGzgOe.js → main-CKnTJ4-O.js} +6 -6
  13. package/.output/server/{_sessionId-DWCTasJU.mjs → _sessionId-B-x9fRY3.mjs} +2 -2
  14. package/.output/server/_ssr/{CompareDrawer-DhrN1uC2.mjs → CompareDrawer-BQVNsAY2.mjs} +3 -3
  15. package/.output/server/_ssr/{ProxyViewerContainer-DRl51s_n.mjs → ProxyViewerContainer-CYm2Dw19.mjs} +12 -12
  16. package/.output/server/_ssr/{ReplayDialog-BQT_ygxC.mjs → ReplayDialog-CaMQBc79.mjs} +4 -4
  17. package/.output/server/_ssr/{RequestAnatomy-DS2tZOgq.mjs → RequestAnatomy--P5arRH2.mjs} +235 -65
  18. package/.output/server/_ssr/{ResponseView-e0kL2C3x.mjs → ResponseView-RtFwNvgD.mjs} +3 -3
  19. package/.output/server/_ssr/{StreamingChunkSequence-BJG-m7xs.mjs → StreamingChunkSequence-B5HPkzab.mjs} +3 -3
  20. package/.output/server/_ssr/{index-Dea3OeRw.mjs → index-CZIKZU43.mjs} +2 -2
  21. package/.output/server/_ssr/index.mjs +2 -2
  22. package/.output/server/_ssr/{json-viewer-DDU55MLK.mjs → json-viewer-d4obyRaA.mjs} +2 -2
  23. package/.output/server/_ssr/{router-Dl7oh0zx.mjs → router-DGPt3MUc.mjs} +3 -3
  24. package/.output/server/{_tanstack-start-manifest_v-m-FJNBVf.mjs → _tanstack-start-manifest_v-BzH4pNaI.mjs} +1 -1
  25. package/.output/server/index.mjs +68 -68
  26. package/package.json +1 -1
  27. package/src/components/proxy-viewer/LogEntry.tsx +4 -4
  28. package/src/components/proxy-viewer/LogEntryHeader.tsx +3 -3
  29. package/src/components/proxy-viewer/anatomy/RequestAnatomy.tsx +196 -45
  30. package/src/components/proxy-viewer/anatomy/SegmentBar.tsx +92 -67
  31. package/src/components/proxy-viewer/anatomy/types.ts +15 -13
  32. package/src/components/proxy-viewer/log-formats/anthropic.ts +1 -1
  33. package/src/components/proxy-viewer/log-formats/openai.ts +1 -1
  34. package/src/components/proxy-viewer/log-formats/types.ts +1 -1
  35. package/src/components/ui/json-viewer.tsx +1 -1
  36. package/.output/public/assets/RequestAnatomy-DgQWGvjs.js +0 -1
  37. package/.output/public/assets/_sessionId-CcD_aLGq.js +0 -1
  38. package/.output/public/assets/index-B_dffD3u.js +0 -1
  39. package/.output/public/assets/index-CX796gvi.css +0 -1
@@ -49,7 +49,7 @@ import "../_libs/mimic-function.mjs";
49
49
  import "../_libs/semver.mjs";
50
50
  import "../_libs/uint8array-extras.mjs";
51
51
  const faviconSvg = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2064%2064'%20role='img'%20aria-label='Agent%20Inspector'%3e%3crect%20width='64'%20height='64'%20rx='14'%20fill='%23111827'%20/%3e%3cg%20fill='none'%20stroke='%23f59e0b'%20stroke-width='4.2'%20stroke-linecap='round'%20stroke-linejoin='round'%3e%3cpath%20fill='%23f59e0b'%20d='M15%2036c0-11%207-18%2017-18s17%207%2017%2018c0%208-7%2013-17%2013s-17-5-17-13z'%20/%3e%3cpath%20d='M16%2031c-6-5-12-3-12%204%200%205%206%206%2011%202'%20/%3e%3cpath%20d='M48%2031c6-5%2012-3%2012%204%200%205-6%206-11%202'%20/%3e%3cpath%20d='M27%2019l-3-7'%20/%3e%3cpath%20d='M37%2019l3-7'%20/%3e%3cpath%20d='M19%2045l-6%209'%20/%3e%3cpath%20d='M27%2048l-3%209'%20/%3e%3cpath%20d='M37%2048l3%209'%20/%3e%3cpath%20d='M45%2045l6%209'%20/%3e%3c/g%3e%3cpath%20d='M14%2047l9-8%208%209c-5%203.5-12%203-17-1z'%20fill='%232f6b3f'%20opacity='.95'%20/%3e%3cpath%20d='M18%2046l5-5%205%206c-3%201.6-7%201.4-10-1z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M23%2041v10'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='1.6'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='31'%20cy='48'%20r='1.8'%20fill='%23c2412d'%20/%3e%3cpath%20d='M24%2044l13-11%2014%2013c-8%205.8-18%205.3-27-2z'%20fill='%232f6b3f'%20opacity='.97'%20/%3e%3cpath%20d='M30%2043l7-7%209%209c-5%202.7-11%202.5-16-2z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M37%2036v14'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='2'%20stroke-linecap='round'%20/%3e%3cpath%20d='M30%2043c5-2%2011-1.5%2016%202'%20fill='none'%20stroke='%239fca78'%20stroke-width='1.8'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='51'%20cy='46'%20r='2'%20fill='%23c2412d'%20/%3e%3cpath%20d='M40%2050l8-8%207%208c-4.2%203.2-10%203-15%200z'%20fill='%232f6b3f'%20opacity='.95'%20/%3e%3cpath%20d='M43%2049l5-5%204.5%205.5c-3%201.5-6%201.2-9.5-.5z'%20fill='%236fb36f'%20opacity='.95'%20/%3e%3cpath%20d='M48%2044v9'%20fill='none'%20stroke='%23d6b45f'%20stroke-width='1.5'%20stroke-linecap='round'%20/%3e%3ccircle%20cx='55'%20cy='50'%20r='1.7'%20fill='%23c2412d'%20/%3e%3ccircle%20cx='24'%20cy='11'%20r='3.2'%20fill='%23f59e0b'%20/%3e%3ccircle%20cx='40'%20cy='11'%20r='3.2'%20fill='%23f59e0b'%20/%3e%3ccircle%20cx='25'%20cy='34'%20r='2.1'%20fill='%23111827'%20/%3e%3ccircle%20cx='39'%20cy='34'%20r='2.1'%20fill='%23111827'%20/%3e%3c/svg%3e";
52
- const appCss = "/assets/index-CX796gvi.css";
52
+ const appCss = "/assets/index-C624DUk9.css";
53
53
  const Route$r = createRootRoute({
54
54
  head: () => ({
55
55
  meta: [
@@ -76,7 +76,7 @@ function RootDocument({ children }) {
76
76
  ] })
77
77
  ] });
78
78
  }
79
- const $$splitComponentImporter$1 = () => import("./index-Dea3OeRw.mjs");
79
+ const $$splitComponentImporter$1 = () => import("./index-CZIKZU43.mjs");
80
80
  const Route$q = createFileRoute("/")({
81
81
  component: lazyRouteComponent($$splitComponentImporter$1, "component")
82
82
  });
@@ -119,7 +119,7 @@ function decodeSessionIdFromPath(encoded) {
119
119
  function getSessionPath(sessionId) {
120
120
  return `/session/${encodeSessionIdForPath(sessionId)}`;
121
121
  }
122
- const $$splitComponentImporter = () => import("../_sessionId-DWCTasJU.mjs");
122
+ const $$splitComponentImporter = () => import("../_sessionId-B-x9fRY3.mjs");
123
123
  const Route$p = createFileRoute("/session/$sessionId")({
124
124
  component: lazyRouteComponent($$splitComponentImporter, "component"),
125
125
  parseParams: (params) => ({
@@ -1,4 +1,4 @@
1
- const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/__root.tsx", "children": ["/", "/api/config", "/api/health", "/api/logs", "/api/mcp", "/api/models", "/api/providers", "/api/sessions", "/proxy/$", "/session/$sessionId", "/api/knowledge/candidates", "/api/knowledge/project-context", "/api/knowledge/search", "/api/knowledge/sessions/$sessionId/candidates"], "preloads": ["/assets/main-2NlGzgOe.js"], "assets": [] }, "/": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/index.tsx", "assets": [], "preloads": ["/assets/index-B_dffD3u.js", "/assets/ProxyViewerContainer-CbW5VRER.js"] }, "/api/config": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/config.ts", "children": ["/api/config/paths"] }, "/api/health": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/health.ts" }, "/api/logs": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.ts", "children": ["/api/logs/$id", "/api/logs/stream"] }, "/api/mcp": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/mcp.ts" }, "/api/models": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/models.ts" }, "/api/providers": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.ts", "children": ["/api/providers/$providerId", "/api/providers/export", "/api/providers/import", "/api/providers/scan"] }, "/api/sessions": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/sessions.ts" }, "/proxy/$": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/proxy/$.ts" }, "/session/$sessionId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/session/$sessionId.tsx", "assets": [], "preloads": ["/assets/_sessionId-CcD_aLGq.js", "/assets/ProxyViewerContainer-CbW5VRER.js"] }, "/api/config/paths": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/config.paths.ts" }, "/api/knowledge/candidates": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.candidates.ts", "children": ["/api/knowledge/candidates/$candidateId"] }, "/api/knowledge/project-context": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.project-context.ts" }, "/api/knowledge/search": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.search.ts" }, "/api/logs/$id": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.ts", "children": ["/api/logs/$id/chunks", "/api/logs/$id/replay"] }, "/api/logs/stream": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.stream.ts" }, "/api/providers/$providerId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.ts", "children": ["/api/providers/$providerId/test"] }, "/api/providers/export": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.export.ts" }, "/api/providers/import": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.import.ts" }, "/api/providers/scan": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.scan.ts" }, "/api/knowledge/candidates/$candidateId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.candidates.$candidateId.ts", "children": ["/api/knowledge/candidates/$candidateId/promote"] }, "/api/logs/$id/chunks": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.chunks.ts" }, "/api/logs/$id/replay": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.replay.ts" }, "/api/providers/$providerId/test": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.test.ts", "children": ["/api/providers/$providerId/test/log"] }, "/api/knowledge/candidates/$candidateId/promote": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.candidates.$candidateId.promote.ts" }, "/api/knowledge/sessions/$sessionId/candidates": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.sessions.$sessionId.candidates.ts" }, "/api/providers/$providerId/test/log": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.test.log.ts" } }, "clientEntry": "/assets/main-2NlGzgOe.js" });
1
+ const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/__root.tsx", "children": ["/", "/api/config", "/api/health", "/api/logs", "/api/mcp", "/api/models", "/api/providers", "/api/sessions", "/proxy/$", "/session/$sessionId", "/api/knowledge/candidates", "/api/knowledge/project-context", "/api/knowledge/search", "/api/knowledge/sessions/$sessionId/candidates"], "preloads": ["/assets/main-CKnTJ4-O.js"], "assets": [] }, "/": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/index.tsx", "assets": [], "preloads": ["/assets/index-BZ4x5UI6.js", "/assets/ProxyViewerContainer-Cxpdziwd.js"] }, "/api/config": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/config.ts", "children": ["/api/config/paths"] }, "/api/health": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/health.ts" }, "/api/logs": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.ts", "children": ["/api/logs/$id", "/api/logs/stream"] }, "/api/mcp": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/mcp.ts" }, "/api/models": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/models.ts" }, "/api/providers": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.ts", "children": ["/api/providers/$providerId", "/api/providers/export", "/api/providers/import", "/api/providers/scan"] }, "/api/sessions": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/sessions.ts" }, "/proxy/$": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/proxy/$.ts" }, "/session/$sessionId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/session/$sessionId.tsx", "assets": [], "preloads": ["/assets/_sessionId-b4isaoDp.js", "/assets/ProxyViewerContainer-Cxpdziwd.js"] }, "/api/config/paths": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/config.paths.ts" }, "/api/knowledge/candidates": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.candidates.ts", "children": ["/api/knowledge/candidates/$candidateId"] }, "/api/knowledge/project-context": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.project-context.ts" }, "/api/knowledge/search": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.search.ts" }, "/api/logs/$id": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.ts", "children": ["/api/logs/$id/chunks", "/api/logs/$id/replay"] }, "/api/logs/stream": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.stream.ts" }, "/api/providers/$providerId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.ts", "children": ["/api/providers/$providerId/test"] }, "/api/providers/export": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.export.ts" }, "/api/providers/import": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.import.ts" }, "/api/providers/scan": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.scan.ts" }, "/api/knowledge/candidates/$candidateId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.candidates.$candidateId.ts", "children": ["/api/knowledge/candidates/$candidateId/promote"] }, "/api/logs/$id/chunks": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.chunks.ts" }, "/api/logs/$id/replay": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.replay.ts" }, "/api/providers/$providerId/test": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.test.ts", "children": ["/api/providers/$providerId/test/log"] }, "/api/knowledge/candidates/$candidateId/promote": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.candidates.$candidateId.promote.ts" }, "/api/knowledge/sessions/$sessionId/candidates": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/knowledge.sessions.$sessionId.candidates.ts" }, "/api/providers/$providerId/test/log": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.test.log.ts" } }, "clientEntry": "/assets/main-CKnTJ4-O.js" });
2
2
  export {
3
3
  tsrStartManifest
4
4
  };
@@ -38,107 +38,107 @@ const assets = {
38
38
  "/assets/alibaba-TTwafVwX.svg": {
39
39
  "type": "image/svg+xml",
40
40
  "etag": '"171b-6dyV5K8QjiaY35sN9qNprh9zDIs"',
41
- "mtime": "2026-06-21T02:55:38.892Z",
41
+ "mtime": "2026-06-21T03:27:09.298Z",
42
42
  "size": 5915,
43
43
  "path": "../public/assets/alibaba-TTwafVwX.svg"
44
44
  },
45
- "/assets/minimax-BPMzvuL-.jpeg": {
46
- "type": "image/jpeg",
47
- "etag": '"1b06-IwivU89ko5UTMUM1/t7hn4sQK9A"',
48
- "mtime": "2026-06-21T02:55:38.892Z",
49
- "size": 6918,
50
- "path": "../public/assets/minimax-BPMzvuL-.jpeg"
51
- },
52
- "/assets/CompareDrawer-3nRwtk8J.js": {
45
+ "/assets/CompareDrawer-DDmqSAfl.js": {
53
46
  "type": "text/javascript; charset=utf-8",
54
- "etag": '"4a25-urgvq4zVkJNkh48bDzRCZpmV0XU"',
55
- "mtime": "2026-06-21T02:55:38.893Z",
47
+ "etag": '"4a25-ax+lNTJqeO5Uw5iRn0IINDghlL8"',
48
+ "mtime": "2026-06-21T03:27:09.300Z",
56
49
  "size": 18981,
57
- "path": "../public/assets/CompareDrawer-3nRwtk8J.js"
50
+ "path": "../public/assets/CompareDrawer-DDmqSAfl.js"
58
51
  },
59
- "/assets/index-B_dffD3u.js": {
52
+ "/assets/index-BZ4x5UI6.js": {
60
53
  "type": "text/javascript; charset=utf-8",
61
- "etag": '"74-G34R32wRb35yFy01Xx5+tisQpbk"',
62
- "mtime": "2026-06-21T02:55:38.892Z",
54
+ "etag": '"74-I7Q+PS5hgyBfKRdQxaKtu+fOxCI"',
55
+ "mtime": "2026-06-21T03:27:09.300Z",
63
56
  "size": 116,
64
- "path": "../public/assets/index-B_dffD3u.js"
57
+ "path": "../public/assets/index-BZ4x5UI6.js"
65
58
  },
66
- "/assets/index-CX796gvi.css": {
59
+ "/assets/index-C624DUk9.css": {
67
60
  "type": "text/css; charset=utf-8",
68
- "etag": '"17a41-dqXsKD+MttGurME/qf9nmjJckRY"',
69
- "mtime": "2026-06-21T02:55:38.892Z",
70
- "size": 96833,
71
- "path": "../public/assets/index-CX796gvi.css"
61
+ "etag": '"17b64-fA2ShN0vgWgtCNH7S8ke3+06+1g"',
62
+ "mtime": "2026-06-21T03:27:09.300Z",
63
+ "size": 97124,
64
+ "path": "../public/assets/index-C624DUk9.css"
72
65
  },
73
- "/assets/json-viewer-IXejqXB0.js": {
66
+ "/assets/ReplayDialog-Bt5DGzlh.js": {
74
67
  "type": "text/javascript; charset=utf-8",
75
- "etag": '"1e653-JGlILG827/WNy4+hkJi+2gTndaU"',
76
- "mtime": "2026-06-21T02:55:38.893Z",
77
- "size": 124499,
78
- "path": "../public/assets/json-viewer-IXejqXB0.js"
68
+ "etag": '"2383-209uDqfCNP9kp/Eo1OJGkQf5K7o"',
69
+ "mtime": "2026-06-21T03:27:09.300Z",
70
+ "size": 9091,
71
+ "path": "../public/assets/ReplayDialog-Bt5DGzlh.js"
79
72
  },
80
- "/assets/ResponseView-Cvc-ct4E.js": {
73
+ "/assets/RequestAnatomy-BxX3_N9S.js": {
81
74
  "type": "text/javascript; charset=utf-8",
82
- "etag": '"6aab-UwVVOTtKRLo51GriiJxR9m6Feak"',
83
- "mtime": "2026-06-21T02:55:38.893Z",
84
- "size": 27307,
85
- "path": "../public/assets/ResponseView-Cvc-ct4E.js"
75
+ "etag": '"21df-RsC1hle1XaaRP0DDNQAtrI26Ohw"',
76
+ "mtime": "2026-06-21T03:27:09.300Z",
77
+ "size": 8671,
78
+ "path": "../public/assets/RequestAnatomy-BxX3_N9S.js"
86
79
  },
87
- "/assets/ReplayDialog-Cl62N9PI.js": {
88
- "type": "text/javascript; charset=utf-8",
89
- "etag": '"2383-flKSjr0F8tecuRkIDNpAYjivJcI"',
90
- "mtime": "2026-06-21T02:55:38.893Z",
91
- "size": 9091,
92
- "path": "../public/assets/ReplayDialog-Cl62N9PI.js"
80
+ "/assets/minimax-BPMzvuL-.jpeg": {
81
+ "type": "image/jpeg",
82
+ "etag": '"1b06-IwivU89ko5UTMUM1/t7hn4sQK9A"',
83
+ "mtime": "2026-06-21T03:27:09.300Z",
84
+ "size": 6918,
85
+ "path": "../public/assets/minimax-BPMzvuL-.jpeg"
93
86
  },
94
- "/assets/RequestAnatomy-DgQWGvjs.js": {
87
+ "/assets/json-viewer-CRL_gWEZ.js": {
95
88
  "type": "text/javascript; charset=utf-8",
96
- "etag": '"1426-61x287FrHKfb80GSEu4faAyIsQQ"',
97
- "mtime": "2026-06-21T02:55:38.893Z",
98
- "size": 5158,
99
- "path": "../public/assets/RequestAnatomy-DgQWGvjs.js"
89
+ "etag": '"1e653-xRVAXa9/k/0cz9lZfPZsShTfToA"',
90
+ "mtime": "2026-06-21T03:27:09.301Z",
91
+ "size": 124499,
92
+ "path": "../public/assets/json-viewer-CRL_gWEZ.js"
100
93
  },
101
- "/assets/StreamingChunkSequence-BCQaCAIe.js": {
94
+ "/assets/StreamingChunkSequence-RJMwNf6F.js": {
102
95
  "type": "text/javascript; charset=utf-8",
103
- "etag": '"d82-mxAzpHhDD3SrHO5SmP2+22ql54A"',
104
- "mtime": "2026-06-21T02:55:38.893Z",
96
+ "etag": '"d82-23sq9u+7FJWOVlw2ZwY9VyBv1us"',
97
+ "mtime": "2026-06-21T03:27:09.300Z",
105
98
  "size": 3458,
106
- "path": "../public/assets/StreamingChunkSequence-BCQaCAIe.js"
99
+ "path": "../public/assets/StreamingChunkSequence-RJMwNf6F.js"
107
100
  },
108
- "/assets/ProxyViewerContainer-CbW5VRER.js": {
101
+ "/assets/ResponseView-Bl_5S9gZ.js": {
109
102
  "type": "text/javascript; charset=utf-8",
110
- "etag": '"7d8fb-FLtU4XIXbbkqJROwzR9ncAvk86E"',
111
- "mtime": "2026-06-21T02:55:38.893Z",
112
- "size": 514299,
113
- "path": "../public/assets/ProxyViewerContainer-CbW5VRER.js"
114
- },
115
- "/assets/qwen-CONDcHqt.png": {
116
- "type": "image/png",
117
- "etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
118
- "mtime": "2026-06-21T02:55:38.892Z",
119
- "size": 357059,
120
- "path": "../public/assets/qwen-CONDcHqt.png"
103
+ "etag": '"6aab-UCFRuWGhCGLKb2s5NCp1phbPUzQ"',
104
+ "mtime": "2026-06-21T03:27:09.300Z",
105
+ "size": 27307,
106
+ "path": "../public/assets/ResponseView-Bl_5S9gZ.js"
121
107
  },
122
108
  "/assets/zhipuai-BPNAnxo-.svg": {
123
109
  "type": "image/svg+xml",
124
110
  "etag": '"2bf8-hNaLCTi89nOFCsIIfWpP/jrfo0s"',
125
- "mtime": "2026-06-21T02:55:38.892Z",
111
+ "mtime": "2026-06-21T03:27:09.298Z",
126
112
  "size": 11256,
127
113
  "path": "../public/assets/zhipuai-BPNAnxo-.svg"
128
114
  },
129
- "/assets/main-2NlGzgOe.js": {
115
+ "/assets/_sessionId-b4isaoDp.js": {
130
116
  "type": "text/javascript; charset=utf-8",
131
- "etag": '"5138c-nIshtdU9NYoVXvBBEN1D74xi9gk"',
132
- "mtime": "2026-06-21T02:55:38.892Z",
117
+ "etag": '"d2-p8zHXMHP91ArIYS6WLwFbKor58Y"',
118
+ "mtime": "2026-06-21T03:27:09.300Z",
119
+ "size": 210,
120
+ "path": "../public/assets/_sessionId-b4isaoDp.js"
121
+ },
122
+ "/assets/main-CKnTJ4-O.js": {
123
+ "type": "text/javascript; charset=utf-8",
124
+ "etag": '"5138c-MlPN81hCf/6HY5xIpWbk5sw0drc"',
125
+ "mtime": "2026-06-21T03:27:09.300Z",
133
126
  "size": 332684,
134
- "path": "../public/assets/main-2NlGzgOe.js"
127
+ "path": "../public/assets/main-CKnTJ4-O.js"
128
+ },
129
+ "/assets/qwen-CONDcHqt.png": {
130
+ "type": "image/png",
131
+ "etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
132
+ "mtime": "2026-06-21T03:27:09.300Z",
133
+ "size": 357059,
134
+ "path": "../public/assets/qwen-CONDcHqt.png"
135
135
  },
136
- "/assets/_sessionId-CcD_aLGq.js": {
136
+ "/assets/ProxyViewerContainer-Cxpdziwd.js": {
137
137
  "type": "text/javascript; charset=utf-8",
138
- "etag": '"d2-ELNVvbTmYkGjU2wEF0iGQm6YfmM"',
139
- "mtime": "2026-06-21T02:55:38.892Z",
140
- "size": 210,
141
- "path": "../public/assets/_sessionId-CcD_aLGq.js"
138
+ "etag": '"7d8f5-2o+HRUWRh8QXo5PbcEDo+/1GGt0"',
139
+ "mtime": "2026-06-21T03:27:09.300Z",
140
+ "size": 514293,
141
+ "path": "../public/assets/ProxyViewerContainer-Cxpdziwd.js"
142
142
  }
143
143
  };
144
144
  function readAsset(id) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonyclaw/agent-inspector",
3
- "version": "2.0.5",
3
+ "version": "2.0.6",
4
4
  "type": "module",
5
5
  "description": "Agent observability and knowledge capture layer for AI coding tools.",
6
6
  "license": "MIT",
@@ -177,7 +177,7 @@ export const LogEntry = memo(function ({
177
177
  const responseCopy = useCopyFeedback(log.responseText);
178
178
 
179
179
  // Per-tab action bundles consumed by the header. The header renders the
180
- // entry whose key matches `activeTab`. Tabs without an entry (Anatomy,
180
+ // entry whose key matches `activeTab`. Tabs without an entry (Context,
181
181
  // Parsed Response) render no header buttons.
182
182
  const tabActions: HeaderTabActions = useMemo(
183
183
  () => ({
@@ -320,7 +320,7 @@ export const LogEntry = memo(function ({
320
320
  <TabsTrigger value="raw-request">Raw Request</TabsTrigger>
321
321
  )}
322
322
  <TabsTrigger value="request">Request</TabsTrigger>
323
- {anatomySegments !== null && <TabsTrigger value="anatomy">Anatomy</TabsTrigger>}
323
+ {anatomySegments !== null && <TabsTrigger value="anatomy">Context</TabsTrigger>}
324
324
  {viewMode === "full" && <TabsTrigger value="raw">Raw Response</TabsTrigger>}
325
325
  <TabsTrigger value="parsed">Response</TabsTrigger>
326
326
  </TabsList>
@@ -359,7 +359,7 @@ export const LogEntry = memo(function ({
359
359
  <RequestDiffContent
360
360
  rawBody={log.rawRequestBody}
361
361
  displayedBody={displayedRequestBody}
362
- emptyLabel="No transformation applied raw and sent request bodies are identical."
362
+ emptyLabel="No transformation applied; raw and sent request bodies are identical."
363
363
  />
364
364
  ) : (
365
365
  <div ref={requestJsonRef}>
@@ -424,7 +424,7 @@ export const LogEntry = memo(function ({
424
424
  <HeadersDiffContent
425
425
  rawHeaders={log.rawHeaders}
426
426
  headers={log.headers}
427
- emptyLabel="No transformation applied raw and processed headers are identical."
427
+ emptyLabel="No transformation applied; raw and processed headers are identical."
428
428
  />
429
429
  ) : log.headers && Object.keys(log.headers).length > 0 ? (
430
430
  <div className="space-y-1 font-mono text-xs">
@@ -92,7 +92,7 @@ export type HeaderTabAction = {
92
92
  };
93
93
 
94
94
  /**
95
- * Tab actions keyed by Tabs value. Tabs without an entry (Anatomy, Parsed
95
+ * Tab actions keyed by Tabs value. Tabs without an entry (Context, Parsed
96
96
  * Response) leave the corresponding key unset, so the header renders no
97
97
  * action buttons for them. Typed as a record (rather than a `Partial<...>`
98
98
  * union) so the per-tab lookup in the header is type-safe.
@@ -109,14 +109,14 @@ export type LogEntryHeaderProps = {
109
109
  onToggle: () => void;
110
110
  /** Per-log cache token trend (creation + read) relative to the previous log
111
111
  * in the same conversation group. When `undefined` or a field is `null`,
112
- * the corresponding cache span renders as it did before no arrow.
112
+ * the corresponding cache span renders as it did before: no arrow.
113
113
  */
114
114
  cacheTrend?: { creation: CacheTrend | null; read: CacheTrend | null } | null;
115
115
  /** Currently-active tab value (matches the `Tabs` value prop). The header
116
116
  * uses this to pick the right entry from `tabActions`. */
117
117
  activeTab?: string;
118
118
  /** Per-tab Copy + Expand-all actions. Only tabs with an entry will show
119
- * buttons when active. Tabs without an entry (Anatomy, Parsed Response)
119
+ * buttons when active. Tabs without an entry (Context, Parsed Response)
120
120
  * render no header buttons. */
121
121
  tabActions?: HeaderTabActions;
122
122
  /** Re-send this request to the provider. Rendered in the header row when
@@ -1,27 +1,77 @@
1
1
  import { Info } from "lucide-react";
2
- import { type JSX, useMemo } from "react";
2
+ import { type JSX, useMemo, useState } from "react";
3
3
  import { cn, formatTokens } from "../../../lib/utils";
4
4
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../../ui/tooltip";
5
- import { SegmentBar } from "./SegmentBar";
6
- import type { AnatomySegment } from "./types";
5
+ import { ROLE_COLOR_CLASSES, SegmentBar } from "./SegmentBar";
6
+ import { ANATOMY_ROLE_LABELS, type AnatomyRole, type AnatomySegment } from "./types";
7
7
 
8
8
  export type RequestAnatomyProps = {
9
9
  /** Parsed request body, or `null` if it cannot be parsed. */
10
10
  parsed: unknown | null;
11
11
  /** Server-reported input token count, or `null` if unknown. */
12
12
  inputTokens: number | null;
13
- /** Optional callback fired when the user activates a segment. */
13
+ /** Optional callback fired when the user activates a concrete request segment. */
14
14
  onSegmentActivate?: (segment: AnatomySegment) => void;
15
15
  /** Pre-computed segments; if provided, `parsed` is ignored. */
16
16
  segments?: AnatomySegment[] | null;
17
17
  };
18
18
 
19
+ type ContextViewMode = "role" | "segment";
20
+
19
21
  const DIVERGENCE_AMBER_THRESHOLD = 0.25;
22
+ const TOP_CONTRIBUTOR_COUNT = 5;
23
+ const ROLE_ORDER: AnatomyRole[] = ["system", "user", "assistant", "tool", "tools"];
24
+
25
+ const ROLE_DESCRIPTIONS: Record<AnatomyRole, string> = {
26
+ system: "instructions",
27
+ user: "user turns",
28
+ assistant: "assistant turns",
29
+ tool: "tool results",
30
+ tools: "tool schemas",
31
+ };
32
+
33
+ const VIEW_MODE_OPTIONS: Array<{ value: ContextViewMode; label: string }> = [
34
+ { value: "role", label: "By Role" },
35
+ { value: "segment", label: "By Segment" },
36
+ ];
37
+
38
+ function formatPercent(value: number): string {
39
+ if (value >= 10) return `${value.toFixed(0)}%`;
40
+ if (value >= 1) return `${value.toFixed(1)}%`;
41
+ if (value > 0) return "<1%";
42
+ return "0%";
43
+ }
44
+
45
+ function aggregateByRole(segments: AnatomySegment[]): AnatomySegment[] {
46
+ const result: AnatomySegment[] = [];
47
+ for (const role of ROLE_ORDER) {
48
+ const matching = segments.filter((segment) => segment.role === role);
49
+ if (matching.length === 0) continue;
50
+ const size = matching.reduce((sum, segment) => sum + segment.size, 0);
51
+ const characters = matching.reduce((sum, segment) => sum + segment.characters, 0);
52
+ const label = ANATOMY_ROLE_LABELS[role];
53
+ const text = `${matching.length} segment${matching.length === 1 ? "" : "s"} grouped as ${
54
+ ROLE_DESCRIPTIONS[role]
55
+ }`;
56
+ result.push({
57
+ role,
58
+ label,
59
+ size,
60
+ characters,
61
+ text,
62
+ path: `role:${role}`,
63
+ });
64
+ }
65
+ return result;
66
+ }
67
+
68
+ function topContributors(segments: AnatomySegment[]): AnatomySegment[] {
69
+ return [...segments].sort((a, b) => b.size - a.size).slice(0, TOP_CONTRIBUTOR_COUNT);
70
+ }
20
71
 
21
72
  /**
22
- * Render the request anatomy view: a one-line summary plus the
23
- * stacked segment bar. Returns `null` when the request cannot be
24
- * parsed or the segment list is empty.
73
+ * Render a request context breakdown: headline metrics, a stacked token bar,
74
+ * role legend, and the largest individual context blocks.
25
75
  */
26
76
  export function RequestAnatomy({
27
77
  parsed,
@@ -29,69 +79,170 @@ export function RequestAnatomy({
29
79
  onSegmentActivate,
30
80
  segments: providedSegments,
31
81
  }: RequestAnatomyProps): JSX.Element | null {
32
- // Caller is expected to pre-compute segments in production (see
33
- // LogEntry). When called standalone, fall back to deriving from
34
- // `parsed` directly using the unknown adapter is not appropriate —
35
- // the caller is responsible for choosing the right adapter.
82
+ const [viewMode, setViewMode] = useState<ContextViewMode>("role");
36
83
  const segments = useMemo(() => providedSegments ?? null, [providedSegments]);
37
- const total = useMemo(() => (segments ?? []).reduce((sum, s) => sum + s.size, 0), [segments]);
84
+ const total = useMemo(
85
+ () => (segments ?? []).reduce((sum, segment) => sum + segment.size, 0),
86
+ [segments],
87
+ );
88
+ const roleSegments = useMemo(
89
+ () => (segments === null ? [] : aggregateByRole(segments)),
90
+ [segments],
91
+ );
92
+ const topSegments = useMemo(
93
+ () => (segments === null ? [] : topContributors(segments)),
94
+ [segments],
95
+ );
38
96
 
39
- // Show divergence warning when both estimate and server numbers exist.
40
97
  const showDivergenceWarning = useMemo(() => {
41
- if (segments === null || segments === undefined) return false;
98
+ if (segments === null) return false;
42
99
  if (inputTokens === null) return false;
43
100
  if (total === 0) return false;
44
101
  const ratio = Math.abs(inputTokens - total) / Math.max(inputTokens, total);
45
102
  return ratio >= DIVERGENCE_AMBER_THRESHOLD;
46
103
  }, [inputTokens, segments, total]);
47
104
 
48
- const summaryColorClass = useMemo(() => {
49
- if (inputTokens === null) return "text-muted-foreground";
50
- if (showDivergenceWarning) return "text-amber-400";
51
- return "text-muted-foreground";
52
- }, [inputTokens, showDivergenceWarning]);
105
+ if (segments === null) return null;
106
+ if (segments.length === 0) return null;
107
+ if (parsed === null && providedSegments === undefined) return null;
53
108
 
54
- if (segments === null || segments === undefined) {
55
- return null;
56
- }
57
- if (segments.length === 0) {
58
- return null;
59
- }
60
- if (parsed === null && providedSegments === undefined) {
61
- return null;
62
- }
109
+ const summaryColorClass =
110
+ inputTokens !== null && showDivergenceWarning ? "text-amber-400" : "text-muted-foreground";
111
+ const displayedSegments = viewMode === "role" ? roleSegments : segments;
112
+ const displayedTotal =
113
+ total > 0 ? total : displayedSegments.reduce((sum, item) => sum + item.size, 0);
114
+ const activateSegment = viewMode === "segment" ? onSegmentActivate : undefined;
115
+ const segmentCountLabel = `${String(segments.length)} segment${segments.length === 1 ? "" : "s"}`;
116
+ const providerInputLabel =
117
+ inputTokens === null ? "Provider input unknown" : `Provider input ${formatTokens(inputTokens)}`;
63
118
 
64
119
  return (
65
120
  <TooltipProvider delayDuration={150}>
66
- <div className="px-4 py-3 space-y-2" data-testid="anatomy-root">
67
- <div className="flex items-center gap-2 text-xs">
68
- <span className="font-mono tabular-nums text-foreground">
69
- ~{formatTokens(total)} tokens
70
- </span>
71
- {inputTokens !== null && (
72
- <span className={cn("font-mono tabular-nums", summaryColorClass)}>
73
- (server: {formatTokens(inputTokens)})
74
- </span>
75
- )}
76
- {showDivergenceWarning && (
121
+ <div className="px-4 py-3 space-y-3" data-testid="anatomy-root">
122
+ <div className="flex flex-wrap items-start justify-between gap-3">
123
+ <div className="min-w-0">
124
+ <div className="text-sm font-semibold text-foreground">Request Context</div>
125
+ <div className={cn("mt-0.5 text-xs font-mono tabular-nums", summaryColorClass)}>
126
+ Estimated ~{formatTokens(total)} tokens | {providerInputLabel} | {segmentCountLabel}
127
+ </div>
128
+ </div>
129
+
130
+ <div
131
+ className="inline-flex shrink-0 rounded border border-border bg-muted/20 p-0.5"
132
+ role="group"
133
+ aria-label="Context breakdown mode"
134
+ >
135
+ {VIEW_MODE_OPTIONS.map((option) => (
136
+ <button
137
+ key={option.value}
138
+ type="button"
139
+ aria-pressed={viewMode === option.value}
140
+ onClick={() => setViewMode(option.value)}
141
+ className={cn(
142
+ "h-6 rounded-sm px-2 text-[11px] font-medium transition-colors",
143
+ viewMode === option.value
144
+ ? "bg-background text-foreground shadow-sm"
145
+ : "text-muted-foreground hover:text-foreground",
146
+ )}
147
+ >
148
+ {option.label}
149
+ </button>
150
+ ))}
151
+ </div>
152
+ </div>
153
+
154
+ {showDivergenceWarning && (
155
+ <div className="inline-flex items-center gap-1.5 text-xs text-amber-400">
77
156
  <Tooltip>
78
157
  <TooltipTrigger asChild>
79
158
  <button
80
159
  type="button"
81
- className="inline-flex items-center text-amber-400 hover:text-amber-300"
82
- aria-label="Token estimate diverges from server"
160
+ className="inline-flex items-center hover:text-amber-300"
161
+ aria-label="Token estimate differs from provider input"
83
162
  >
84
163
  <Info className="size-3.5" />
85
164
  </button>
86
165
  </TooltipTrigger>
87
166
  <TooltipContent className="max-w-xs text-xs">
88
- Bar uses a token estimate heuristic (~4 ASCII chars / token, ~1 CJK / emoji char per
89
- token). The server&apos;s reported value is the source of truth for cost.
167
+ The bar uses a local token estimate. Provider input tokens remain the source of
168
+ truth for billing and context-window usage.
90
169
  </TooltipContent>
91
170
  </Tooltip>
92
- )}
171
+ Estimate differs from provider-reported input.
172
+ </div>
173
+ )}
174
+
175
+ <SegmentBar
176
+ segments={displayedSegments}
177
+ totalTokens={displayedTotal}
178
+ showLabels={viewMode === "segment"}
179
+ onActivate={activateSegment}
180
+ />
181
+
182
+ <div className="flex flex-wrap items-center gap-x-3 gap-y-1.5 text-[11px] text-muted-foreground">
183
+ {roleSegments.map((segment) => {
184
+ const percent = total > 0 ? (segment.size / total) * 100 : 0;
185
+ return (
186
+ <div key={segment.role} className="inline-flex items-center gap-1.5">
187
+ <span
188
+ aria-hidden="true"
189
+ className={cn("size-2.5 rounded-[2px]", ROLE_COLOR_CLASSES[segment.role])}
190
+ />
191
+ <span>{segment.label}</span>
192
+ <span className="font-mono text-muted-foreground/70">{formatPercent(percent)}</span>
193
+ </div>
194
+ );
195
+ })}
196
+ </div>
197
+
198
+ <div className="space-y-1.5">
199
+ <div className="text-xs font-medium text-foreground">Top Contributors</div>
200
+ <div className="grid gap-1">
201
+ {topSegments.map((segment, index) => {
202
+ const percent = total > 0 ? (segment.size / total) * 100 : 0;
203
+ const activate = onSegmentActivate;
204
+ const content = (
205
+ <>
206
+ <span className="w-5 shrink-0 text-right font-mono text-muted-foreground/70">
207
+ {String(index + 1)}
208
+ </span>
209
+ <span
210
+ aria-hidden="true"
211
+ className={cn(
212
+ "size-2.5 shrink-0 rounded-[2px]",
213
+ ROLE_COLOR_CLASSES[segment.role],
214
+ )}
215
+ />
216
+ <span className="min-w-0 flex-1 truncate text-left">{segment.label}</span>
217
+ <span className="shrink-0 font-mono text-muted-foreground">
218
+ {formatPercent(percent)} | ~{formatTokens(segment.size)}
219
+ </span>
220
+ </>
221
+ );
222
+ if (activate !== undefined) {
223
+ return (
224
+ <button
225
+ key={`${segment.path}-${index}`}
226
+ type="button"
227
+ onClick={() => activate(segment)}
228
+ className="flex h-7 items-center gap-2 rounded px-1.5 text-xs text-muted-foreground hover:bg-muted/40 hover:text-foreground"
229
+ title="Jump to this request block"
230
+ >
231
+ {content}
232
+ </button>
233
+ );
234
+ }
235
+ return (
236
+ <div
237
+ key={`${segment.path}-${index}`}
238
+ className="flex h-7 items-center gap-2 rounded px-1.5 text-xs text-muted-foreground"
239
+ >
240
+ {content}
241
+ </div>
242
+ );
243
+ })}
244
+ </div>
93
245
  </div>
94
- <SegmentBar segments={segments} totalTokens={total} onActivate={onSegmentActivate} />
95
246
  </div>
96
247
  </TooltipProvider>
97
248
  );