@tonyclaw/agent-inspector 2.1.13 → 2.1.15

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 (92) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/CompareDrawer-BcEd6V-V.js +1 -0
  3. package/.output/public/assets/ProxyViewerContainer-h851qWNp.js +106 -0
  4. package/.output/public/assets/ReplayDialog-BNpC0548.js +1 -0
  5. package/.output/public/assets/{RequestAnatomy-BjlBT-Cy.js → RequestAnatomy-Ds1uRLVB.js} +1 -1
  6. package/.output/public/assets/ResponseView-7KPVqKl5.js +3 -0
  7. package/.output/public/assets/{StreamingChunkSequence-D2_SMhlE.js → StreamingChunkSequence-BHQT261s.js} +1 -1
  8. package/.output/public/assets/_sessionId-DWePGjnS.js +1 -0
  9. package/.output/public/assets/index-CI1-G8ua.js +1 -0
  10. package/.output/public/assets/index-DdhFqPsI.css +1 -0
  11. package/.output/public/assets/index-DjKt8XKe.js +14 -0
  12. package/.output/public/assets/json-viewer-CkCu-rka.js +1 -0
  13. package/.output/public/assets/{main-Dtspb4Ui.js → main-DpD1N0S8.js} +2 -2
  14. package/.output/server/_libs/lucide-react.mjs +194 -200
  15. package/.output/server/_libs/react-markdown.mjs +90 -2
  16. package/.output/server/{_sessionId-CXDcLuvi.mjs → _sessionId-DF9Sy8cP.mjs} +6 -57
  17. package/.output/server/_ssr/{CompareDrawer-CMoCAoeq.mjs → CompareDrawer-BoxztaO7.mjs} +50 -74
  18. package/.output/server/_ssr/{ProxyViewerContainer-BW2vVCBN.mjs → ProxyViewerContainer-CRBkqFlJ.mjs} +1221 -799
  19. package/.output/server/_ssr/{ReplayDialog-ChXL1t8H.mjs → ReplayDialog-Cc1dyDuK.mjs} +18 -62
  20. package/.output/server/_ssr/{RequestAnatomy-DtKzIlfU.mjs → RequestAnatomy-CMGSsz5Z.mjs} +6 -57
  21. package/.output/server/_ssr/{ResponseView-B5I8drzc.mjs → ResponseView-Cp10DM1D.mjs} +139 -61
  22. package/.output/server/_ssr/{StreamingChunkSequence-DvwjQNcO.mjs → StreamingChunkSequence-B1VGxy3A.mjs} +13 -58
  23. package/.output/server/_ssr/{index-D_ZHtRfl.mjs → index-47XVPghS.mjs} +6 -57
  24. package/.output/server/_ssr/index.mjs +2 -2
  25. package/.output/server/_ssr/json-viewer-zDE2rrmJ.mjs +478 -0
  26. package/.output/server/_ssr/{router-DhL9Wp3N.mjs → router-DVeuZFqI.mjs} +680 -174
  27. package/.output/server/{_tanstack-start-manifest_v-BHgoAmxZ.mjs → _tanstack-start-manifest_v-Bp8JxtPW.mjs} +1 -1
  28. package/.output/server/index.mjs +72 -58
  29. package/package.json +1 -1
  30. package/src/components/ProxyViewer.tsx +28 -2
  31. package/src/components/ProxyViewerContainer.tsx +25 -17
  32. package/src/components/clients/ClientLogo.tsx +132 -0
  33. package/src/components/groups/GroupsDialog.tsx +18 -13
  34. package/src/components/providers/ImportWizardDialog.tsx +7 -1
  35. package/src/components/providers/ProviderCard.tsx +10 -1
  36. package/src/components/providers/ProviderForm.tsx +157 -41
  37. package/src/components/providers/ProvidersPanel.tsx +5 -1
  38. package/src/components/proxy-viewer/AgentTraceSummary.tsx +56 -23
  39. package/src/components/proxy-viewer/AnswerMarkdown.tsx +8 -3
  40. package/src/components/proxy-viewer/CompareDrawer.tsx +58 -14
  41. package/src/components/proxy-viewer/ConversationGroup.tsx +11 -15
  42. package/src/components/proxy-viewer/ConversationHeader.tsx +33 -41
  43. package/src/components/proxy-viewer/LogEntry.tsx +41 -12
  44. package/src/components/proxy-viewer/LogEntryHeader.tsx +122 -51
  45. package/src/components/proxy-viewer/ProviderLogoStack.tsx +60 -0
  46. package/src/components/proxy-viewer/ReplayDialog.tsx +8 -2
  47. package/src/components/proxy-viewer/RequestToolsPanel.tsx +19 -13
  48. package/src/components/proxy-viewer/StreamingChunkSequence.tsx +9 -3
  49. package/src/components/proxy-viewer/ThreadConnector.tsx +18 -7
  50. package/src/components/proxy-viewer/TurnGroup.tsx +67 -32
  51. package/src/components/proxy-viewer/TurnGroupList.tsx +153 -0
  52. package/src/components/proxy-viewer/anatomy/sessionContextSummary.ts +74 -2
  53. package/src/components/proxy-viewer/formats/anthropic/ContentBlocks.tsx +13 -7
  54. package/src/components/proxy-viewer/formats/index.tsx +10 -3
  55. package/src/components/proxy-viewer/formats/openai/ResponseView.tsx +185 -17
  56. package/src/components/proxy-viewer/log-formats/openai.ts +107 -15
  57. package/src/components/proxy-viewer/logFocus.ts +15 -2
  58. package/src/components/proxy-viewer/requestTools.ts +7 -3
  59. package/src/components/proxy-viewer/viewerState.ts +77 -5
  60. package/src/components/ui/json-viewer-bulk.ts +41 -6
  61. package/src/components/ui/json-viewer.tsx +9 -8
  62. package/src/contracts/index.ts +15 -1
  63. package/src/contracts/openai.ts +94 -0
  64. package/src/lib/providerContract.ts +1 -0
  65. package/src/lib/providerModelMetadata.ts +7 -1
  66. package/src/lib/sessionInfoContract.ts +1 -0
  67. package/src/lib/stopReason.ts +59 -15
  68. package/src/lib/upstreamUrl.ts +46 -0
  69. package/src/mcp/previewExtractor.ts +73 -3
  70. package/src/mcp/server.ts +2 -0
  71. package/src/mcp/toolHandlers.ts +2 -0
  72. package/src/proxy/constants.ts +2 -0
  73. package/src/proxy/formats/openai/handler.ts +40 -9
  74. package/src/proxy/formats/openai/index.ts +7 -0
  75. package/src/proxy/formats/openai/schemas.ts +15 -1
  76. package/src/proxy/formats/openai/stream.ts +529 -135
  77. package/src/proxy/formats/registry.ts +9 -1
  78. package/src/proxy/providerImporters.ts +45 -5
  79. package/src/proxy/providers.ts +31 -11
  80. package/src/proxy/schemas.ts +6 -0
  81. package/src/proxy/sessionInfo.ts +5 -1
  82. package/src/proxy/toolSchemaWarnings.ts +25 -3
  83. package/src/proxy/upstream.ts +18 -37
  84. package/src/routes/api/providers.$providerId.ts +1 -0
  85. package/src/routes/api/providers.ts +2 -0
  86. package/.output/public/assets/CompareDrawer-Cz_1vIpR.js +0 -1
  87. package/.output/public/assets/ProxyViewerContainer-7QSiluMf.js +0 -117
  88. package/.output/public/assets/ReplayDialog-sBA1KAYD.js +0 -1
  89. package/.output/public/assets/ResponseView-PtEKzml9.js +0 -1
  90. package/.output/public/assets/_sessionId-DZfB4ruK.js +0 -1
  91. package/.output/public/assets/index-B-QQLbpz.js +0 -1
  92. package/.output/public/assets/index-CmtfjQPv.css +0 -1
@@ -1,4 +1,4 @@
1
- const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/__root.tsx", "children": ["/", "/api/alerts", "/api/config", "/api/groups", "/api/health", "/api/logs", "/api/mcp", "/api/models", "/api/providers", "/api/runs", "/api/sessions", "/proxy/$", "/session/$sessionId", "/api/knowledge/candidates", "/api/knowledge/project-context", "/api/knowledge/search", "/api/knowledge/sessions/$sessionId/candidates"], "preloads": ["/assets/main-Dtspb4Ui.js"], "assets": [] }, "/": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/index.tsx", "assets": [], "preloads": ["/assets/index-B-QQLbpz.js", "/assets/ProxyViewerContainer-7QSiluMf.js"] }, "/api/alerts": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/alerts.ts", "children": ["/api/alerts/summary"] }, "/api/config": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/config.ts", "children": ["/api/config/paths"] }, "/api/groups": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/groups.ts", "children": ["/api/groups/$groupId"] }, "/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/import", "/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/runs": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/runs.ts", "children": ["/api/runs/$runId"] }, "/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-DZfB4ruK.js", "/assets/ProxyViewerContainer-7QSiluMf.js"] }, "/api/alerts/summary": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/alerts.summary.ts" }, "/api/config/paths": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/config.paths.ts" }, "/api/groups/$groupId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/groups.$groupId.ts", "children": ["/api/groups/$groupId/evidence", "/api/groups/$groupId/sessions"] }, "/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/body", "/api/logs/$id/chunks", "/api/logs/$id/replay"] }, "/api/logs/import": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.import.ts" }, "/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/model-metadata", "/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/runs/$runId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/runs.$runId.ts", "children": ["/api/runs/$runId/evidence"] }, "/api/groups/$groupId/evidence": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/groups.$groupId.evidence.ts" }, "/api/groups/$groupId/sessions": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/groups.$groupId.sessions.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/body": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.body.ts" }, "/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/model-metadata": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.model-metadata.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/runs/$runId/evidence": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/runs.$runId.evidence.ts" }, "/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-Dtspb4Ui.js" });
1
+ const tsrStartManifest = () => ({ "routes": { "__root__": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/__root.tsx", "children": ["/", "/api/alerts", "/api/config", "/api/groups", "/api/health", "/api/logs", "/api/mcp", "/api/models", "/api/providers", "/api/runs", "/api/sessions", "/proxy/$", "/session/$sessionId", "/api/knowledge/candidates", "/api/knowledge/project-context", "/api/knowledge/search", "/api/knowledge/sessions/$sessionId/candidates"], "preloads": ["/assets/main-DpD1N0S8.js"], "assets": [] }, "/": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/index.tsx", "assets": [], "preloads": ["/assets/index-CI1-G8ua.js", "/assets/ProxyViewerContainer-h851qWNp.js"] }, "/api/alerts": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/alerts.ts", "children": ["/api/alerts/summary"] }, "/api/config": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/config.ts", "children": ["/api/config/paths"] }, "/api/groups": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/groups.ts", "children": ["/api/groups/$groupId"] }, "/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/import", "/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/runs": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/runs.ts", "children": ["/api/runs/$runId"] }, "/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-DWePGjnS.js", "/assets/ProxyViewerContainer-h851qWNp.js"] }, "/api/alerts/summary": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/alerts.summary.ts" }, "/api/config/paths": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/config.paths.ts" }, "/api/groups/$groupId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/groups.$groupId.ts", "children": ["/api/groups/$groupId/evidence", "/api/groups/$groupId/sessions"] }, "/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/body", "/api/logs/$id/chunks", "/api/logs/$id/replay"] }, "/api/logs/import": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.import.ts" }, "/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/model-metadata", "/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/runs/$runId": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/runs.$runId.ts", "children": ["/api/runs/$runId/evidence"] }, "/api/groups/$groupId/evidence": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/groups.$groupId.evidence.ts" }, "/api/groups/$groupId/sessions": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/groups.$groupId.sessions.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/body": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/logs.$id.body.ts" }, "/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/model-metadata": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/providers.$providerId.model-metadata.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/runs/$runId/evidence": { "filePath": "C:/Users/claw/workspace/agent-inspector/src/routes/api/runs.$runId.evidence.ts" }, "/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-DpD1N0S8.js" });
2
2
  export {
3
3
  tsrStartManifest
4
4
  };
@@ -38,100 +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-04T05:36:48.779Z",
41
+ "mtime": "2026-07-04T08:29:06.393Z",
42
42
  "size": 5915,
43
43
  "path": "../public/assets/alibaba-TTwafVwX.svg"
44
44
  },
45
- "/assets/CompareDrawer-Cz_1vIpR.js": {
45
+ "/assets/CompareDrawer-BcEd6V-V.js": {
46
46
  "type": "text/javascript; charset=utf-8",
47
- "etag": '"49e8-IQAhbCzceTeYxZxKJ3H1D4vN5lI"',
48
- "mtime": "2026-07-04T05:36:48.779Z",
49
- "size": 18920,
50
- "path": "../public/assets/CompareDrawer-Cz_1vIpR.js"
47
+ "etag": '"4bbf-xnctyyrpUlw9iwRDiN8n7dDP2ak"',
48
+ "mtime": "2026-07-04T08:29:06.393Z",
49
+ "size": 19391,
50
+ "path": "../public/assets/CompareDrawer-BcEd6V-V.js"
51
51
  },
52
- "/assets/index-B-QQLbpz.js": {
53
- "type": "text/javascript; charset=utf-8",
54
- "etag": '"74-5Zl3E5e37SnRK730IWxTDix9Cew"',
55
- "mtime": "2026-07-04T05:36:48.779Z",
56
- "size": 116,
57
- "path": "../public/assets/index-B-QQLbpz.js"
58
- },
59
- "/assets/index-CmtfjQPv.css": {
52
+ "/assets/index-DdhFqPsI.css": {
60
53
  "type": "text/css; charset=utf-8",
61
- "etag": '"1e968-15dLAIs72Zhi4Qe/CRWBTVZ7MtI"',
62
- "mtime": "2026-07-04T05:36:48.779Z",
63
- "size": 125288,
64
- "path": "../public/assets/index-CmtfjQPv.css"
54
+ "etag": '"215a1-oGtBN21bbG9XXw6KUOxGJs8nN5k"',
55
+ "mtime": "2026-07-04T08:29:06.393Z",
56
+ "size": 136609,
57
+ "path": "../public/assets/index-DdhFqPsI.css"
65
58
  },
66
- "/assets/ReplayDialog-sBA1KAYD.js": {
59
+ "/assets/index-DjKt8XKe.js": {
67
60
  "type": "text/javascript; charset=utf-8",
68
- "etag": '"318c-/uOpj+S8IOxd8JplqqWJ9qOWH3I"',
69
- "mtime": "2026-07-04T05:36:48.779Z",
70
- "size": 12684,
71
- "path": "../public/assets/ReplayDialog-sBA1KAYD.js"
61
+ "etag": '"1cd2c-tx2svUPlWKqZmckbUC3QdLcZvAI"',
62
+ "mtime": "2026-07-04T08:29:06.395Z",
63
+ "size": 118060,
64
+ "path": "../public/assets/index-DjKt8XKe.js"
72
65
  },
73
- "/assets/StreamingChunkSequence-D2_SMhlE.js": {
66
+ "/assets/json-viewer-CkCu-rka.js": {
74
67
  "type": "text/javascript; charset=utf-8",
75
- "etag": '"d5c-k/lB4x1Vah+nlw2D1J4Zn+Hqm/o"',
76
- "mtime": "2026-07-04T05:36:48.781Z",
77
- "size": 3420,
78
- "path": "../public/assets/StreamingChunkSequence-D2_SMhlE.js"
68
+ "etag": '"1ae6-2bgY4h+p+tUN/whEBQOWKsJ3qYQ"',
69
+ "mtime": "2026-07-04T08:29:06.395Z",
70
+ "size": 6886,
71
+ "path": "../public/assets/json-viewer-CkCu-rka.js"
79
72
  },
80
- "/assets/RequestAnatomy-BjlBT-Cy.js": {
73
+ "/assets/index-CI1-G8ua.js": {
81
74
  "type": "text/javascript; charset=utf-8",
82
- "etag": '"43f2-aSr44l/LuOOCwx52V5TxpIleLAM"',
83
- "mtime": "2026-07-04T05:36:48.779Z",
84
- "size": 17394,
85
- "path": "../public/assets/RequestAnatomy-BjlBT-Cy.js"
75
+ "etag": '"74-EIeYwTAITYEdQc7ccvRe2pZrl1c"',
76
+ "mtime": "2026-07-04T08:29:06.393Z",
77
+ "size": 116,
78
+ "path": "../public/assets/index-CI1-G8ua.js"
86
79
  },
87
80
  "/assets/minimax-BPMzvuL-.jpeg": {
88
81
  "type": "image/jpeg",
89
82
  "etag": '"1b06-IwivU89ko5UTMUM1/t7hn4sQK9A"',
90
- "mtime": "2026-07-04T05:36:48.779Z",
83
+ "mtime": "2026-07-04T08:29:06.393Z",
91
84
  "size": 6918,
92
85
  "path": "../public/assets/minimax-BPMzvuL-.jpeg"
93
86
  },
94
- "/assets/main-Dtspb4Ui.js": {
87
+ "/assets/ReplayDialog-BNpC0548.js": {
95
88
  "type": "text/javascript; charset=utf-8",
96
- "etag": '"512fd-xu5QhSDM+B1+HCE/S55XRSP7mzM"',
97
- "mtime": "2026-07-04T05:36:48.779Z",
98
- "size": 332541,
99
- "path": "../public/assets/main-Dtspb4Ui.js"
89
+ "etag": '"31d6-OqVZaeoLKFYexfhY+mk0sL5psk4"',
90
+ "mtime": "2026-07-04T08:29:06.393Z",
91
+ "size": 12758,
92
+ "path": "../public/assets/ReplayDialog-BNpC0548.js"
93
+ },
94
+ "/assets/RequestAnatomy-Ds1uRLVB.js": {
95
+ "type": "text/javascript; charset=utf-8",
96
+ "etag": '"43f2-4Ax9Y1ZjuvUwkXemqmrSK7aPKqk"',
97
+ "mtime": "2026-07-04T08:29:06.393Z",
98
+ "size": 17394,
99
+ "path": "../public/assets/RequestAnatomy-Ds1uRLVB.js"
100
+ },
101
+ "/assets/ResponseView-7KPVqKl5.js": {
102
+ "type": "text/javascript; charset=utf-8",
103
+ "etag": '"3fbb-bslwKE65FOBUHRcwxQQU0c94KJE"',
104
+ "mtime": "2026-07-04T08:29:06.395Z",
105
+ "size": 16315,
106
+ "path": "../public/assets/ResponseView-7KPVqKl5.js"
107
+ },
108
+ "/assets/StreamingChunkSequence-BHQT261s.js": {
109
+ "type": "text/javascript; charset=utf-8",
110
+ "etag": '"dd6-yiWtPjTykwFM62Q1LOw43GSPAx0"',
111
+ "mtime": "2026-07-04T08:29:06.395Z",
112
+ "size": 3542,
113
+ "path": "../public/assets/StreamingChunkSequence-BHQT261s.js"
100
114
  },
101
115
  "/assets/zhipuai-BPNAnxo-.svg": {
102
116
  "type": "image/svg+xml",
103
117
  "etag": '"2bf8-hNaLCTi89nOFCsIIfWpP/jrfo0s"',
104
- "mtime": "2026-07-04T05:36:48.779Z",
118
+ "mtime": "2026-07-04T08:29:06.393Z",
105
119
  "size": 11256,
106
120
  "path": "../public/assets/zhipuai-BPNAnxo-.svg"
107
121
  },
108
- "/assets/ResponseView-PtEKzml9.js": {
122
+ "/assets/_sessionId-DWePGjnS.js": {
123
+ "type": "text/javascript; charset=utf-8",
124
+ "etag": '"d2-ONKmnhfoA+60/NY+/v084oYX2M4"',
125
+ "mtime": "2026-07-04T08:29:06.393Z",
126
+ "size": 210,
127
+ "path": "../public/assets/_sessionId-DWePGjnS.js"
128
+ },
129
+ "/assets/main-DpD1N0S8.js": {
109
130
  "type": "text/javascript; charset=utf-8",
110
- "etag": '"30d2-PgPHao5hEC1x+egdBk+5Bh5Ykuc"',
111
- "mtime": "2026-07-04T05:36:48.781Z",
112
- "size": 12498,
113
- "path": "../public/assets/ResponseView-PtEKzml9.js"
131
+ "etag": '"512fd-MPKJm1sPG3F35PU/2xjL93KYUyo"',
132
+ "mtime": "2026-07-04T08:29:06.393Z",
133
+ "size": 332541,
134
+ "path": "../public/assets/main-DpD1N0S8.js"
114
135
  },
115
136
  "/assets/qwen-CONDcHqt.png": {
116
137
  "type": "image/png",
117
138
  "etag": '"572c3-cdJAPaHdOvFCGzuaQjagdgOu6XE"',
118
- "mtime": "2026-07-04T05:36:48.779Z",
139
+ "mtime": "2026-07-04T08:29:06.393Z",
119
140
  "size": 357059,
120
141
  "path": "../public/assets/qwen-CONDcHqt.png"
121
142
  },
122
- "/assets/_sessionId-DZfB4ruK.js": {
123
- "type": "text/javascript; charset=utf-8",
124
- "etag": '"d2-MK+vvObaH7Ulj3vGGu5D9UigZf8"',
125
- "mtime": "2026-07-04T05:36:48.779Z",
126
- "size": 210,
127
- "path": "../public/assets/_sessionId-DZfB4ruK.js"
128
- },
129
- "/assets/ProxyViewerContainer-7QSiluMf.js": {
143
+ "/assets/ProxyViewerContainer-h851qWNp.js": {
130
144
  "type": "text/javascript; charset=utf-8",
131
- "etag": '"c1d99-OTDVU1kkKfVtUjde6m6DdNv1knE"',
132
- "mtime": "2026-07-04T05:36:48.779Z",
133
- "size": 794009,
134
- "path": "../public/assets/ProxyViewerContainer-7QSiluMf.js"
145
+ "etag": '"a8fdb-3dhZI4F1WvCGzLHRBgWIFmmvah0"',
146
+ "mtime": "2026-07-04T08:29:06.395Z",
147
+ "size": 692187,
148
+ "path": "../public/assets/ProxyViewerContainer-h851qWNp.js"
135
149
  }
136
150
  };
137
151
  function readAsset(id) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonyclaw/agent-inspector",
3
- "version": "2.1.13",
3
+ "version": "2.1.15",
4
4
  "type": "module",
5
5
  "description": "Agent observability and knowledge capture layer for AI coding tools.",
6
6
  "license": "MIT",
@@ -40,7 +40,7 @@ import { formatTimestampRange } from "../lib/timeDisplay";
40
40
  import { cn, formatContextWindowTokens, formatTokens } from "../lib/utils";
41
41
  import { useProviders } from "../lib/useProviders";
42
42
  import packageJson from "../../package.json";
43
- import { groupLogsByConversation } from "./proxy-viewer";
43
+ import { groupLogsByConversation, type ConversationGroupData } from "./proxy-viewer";
44
44
 
45
45
  import { CrabLogo } from "./ui/crab-logo";
46
46
  import { crabVariants } from "./ui/crab-variants";
@@ -72,6 +72,25 @@ function truncateSessionId(id: string): string {
72
72
  return `${id.slice(0, 12)}...${id.slice(-12)}`;
73
73
  }
74
74
 
75
+ function buildDisplayNumberByLogId(groups: readonly ConversationGroupData[]): Map<number, number> {
76
+ const result = new Map<number, number>();
77
+ for (const group of groups) {
78
+ for (let index = 0; index < group.logs.length; index += 1) {
79
+ const log = group.logs[index];
80
+ if (log === undefined) continue;
81
+ result.set(log.id, index + 1);
82
+ }
83
+ }
84
+ return result;
85
+ }
86
+
87
+ function displayNumberForLog(
88
+ log: CapturedLog,
89
+ displayNumberByLogId: ReadonlyMap<number, number>,
90
+ ): number {
91
+ return displayNumberByLogId.get(log.id) ?? log.id;
92
+ }
93
+
75
94
  export function shouldShowRawExport(captureMode: CaptureMode): boolean {
76
95
  return captureMode === "full";
77
96
  }
@@ -1404,6 +1423,7 @@ export function ProxyViewer({
1404
1423
  }, []);
1405
1424
 
1406
1425
  const groups = useMemo(() => groupLogsByConversation(logs), [logs]);
1426
+ const displayNumberByLogId = useMemo(() => buildDisplayNumberByLogId(groups), [groups]);
1407
1427
  const sessionContextScope = useMemo(
1408
1428
  () => resolveSessionContextScope({ pinnedSessionId, selectedSession, sessions, logs }),
1409
1429
  [logs, pinnedSessionId, selectedSession, sessions],
@@ -1733,7 +1753,13 @@ export function ProxyViewer({
1733
1753
  {/* Compare drawer: sibling of the log list, not a route change. */}
1734
1754
  {comparePair !== null && (
1735
1755
  <Suspense fallback={null}>
1736
- <LazyCompareDrawer left={comparePair[0]} right={comparePair[1]} onClose={closeCompare} />
1756
+ <LazyCompareDrawer
1757
+ left={comparePair[0]}
1758
+ right={comparePair[1]}
1759
+ leftDisplayNumber={displayNumberForLog(comparePair[0], displayNumberByLogId)}
1760
+ rightDisplayNumber={displayNumberForLog(comparePair[1], displayNumberByLogId)}
1761
+ onClose={closeCompare}
1762
+ />
1737
1763
  </Suspense>
1738
1764
  )}
1739
1765
  </div>
@@ -1,4 +1,4 @@
1
- import { useState, useEffect, useCallback, useRef, useMemo, type JSX } from "react";
1
+ import { useState, useEffect, useCallback, useRef, useMemo, useTransition, type JSX } from "react";
2
2
  import { z } from "zod";
3
3
  import { CapturedLogSchema, type CapturedLog } from "../contracts";
4
4
  import { fetchJson } from "../lib/apiClient";
@@ -109,7 +109,7 @@ function filterLogs(
109
109
  });
110
110
  }
111
111
 
112
- const DEBOUNCE_MS = 50;
112
+ const DEBOUNCE_MS = 100;
113
113
  const HASH_SCROLL_ATTEMPTS = 12;
114
114
  const HASH_HIGHLIGHT_MS = 1800;
115
115
  const MAX_CLIENT_LOGS = 500;
@@ -190,6 +190,7 @@ export function ProxyViewerContainer({
190
190
  const [logPage, setLogPage] = useState<LogCursorPage | null>(null);
191
191
  const [sessionPageLoading, setSessionPageLoading] = useState(initialSessionId !== undefined);
192
192
  const [sessionMemberships, setSessionMemberships] = useState<SessionMembershipEvidence[]>([]);
193
+ const [, startLogTransition] = useTransition();
193
194
  const eventSourceRef = useRef<EventSource | null>(null);
194
195
  const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
195
196
  const handledHashRef = useRef<string | null>(null);
@@ -217,23 +218,30 @@ export function ProxyViewerContainer({
217
218
  pendingUpdatesRef.current = [];
218
219
  if (updates.length === 0) return;
219
220
 
220
- setAllLogs((prev) => {
221
- let next = prev;
222
- for (const log of updates) {
223
- const idx = logIndexRef.current.get(log.id);
224
- if (idx !== undefined) {
225
- // Replace existing entry
226
- next = [...next.slice(0, idx), log, ...next.slice(idx + 1)];
227
- } else {
228
- logIndexRef.current.set(log.id, next.length);
229
- next = [...next, log];
221
+ startLogTransition(() => {
222
+ setAllLogs((prev) => {
223
+ const next = [...prev];
224
+ for (const log of updates) {
225
+ const indexedPosition = logIndexRef.current.get(log.id);
226
+ if (indexedPosition !== undefined && next[indexedPosition]?.id === log.id) {
227
+ next[indexedPosition] = log;
228
+ continue;
229
+ }
230
+
231
+ const existingPosition = next.findIndex((entry) => entry.id === log.id);
232
+ if (existingPosition >= 0) {
233
+ next[existingPosition] = log;
234
+ continue;
235
+ }
236
+
237
+ next.push(log);
230
238
  }
231
- }
232
- next = trimClientLogs(next);
233
- logIndexRef.current = buildLogIndex(next);
234
- return next;
239
+ const trimmed = trimClientLogs(next);
240
+ logIndexRef.current = buildLogIndex(trimmed);
241
+ return trimmed;
242
+ });
235
243
  });
236
- }, []);
244
+ }, [startLogTransition]);
237
245
 
238
246
  const scheduleUpdate = useCallback(
239
247
  (log: CapturedLog) => {
@@ -0,0 +1,132 @@
1
+ import type { JSX } from "react";
2
+ import { cn } from "../../lib/utils";
3
+
4
+ export type ClientApp = "codex" | "opencode" | "mimo-code" | "claude-code" | "unknown";
5
+
6
+ export type ClientAppDetectionInput = {
7
+ userAgent?: string | null;
8
+ conversationId?: string | null;
9
+ clientProjectFolder?: string | null;
10
+ };
11
+
12
+ const CLIENT_LABELS: Record<Exclude<ClientApp, "unknown">, string> = {
13
+ codex: "Codex",
14
+ opencode: "OpenCode",
15
+ "mimo-code": "MiMo Code",
16
+ "claude-code": "Claude Code",
17
+ };
18
+
19
+ function normalize(value: string | null | undefined): string {
20
+ return value?.toLowerCase() ?? "";
21
+ }
22
+
23
+ function matchesAny(value: string, candidates: readonly string[]): boolean {
24
+ for (const candidate of candidates) {
25
+ if (value.includes(candidate)) return true;
26
+ }
27
+ return false;
28
+ }
29
+
30
+ export function detectClientApp(input: ClientAppDetectionInput): ClientApp {
31
+ const haystack = [
32
+ normalize(input.userAgent),
33
+ normalize(input.conversationId),
34
+ normalize(input.clientProjectFolder),
35
+ ].join(" ");
36
+
37
+ if (matchesAny(haystack, ["mimocode", "mimo-code", "mimo code"])) return "mimo-code";
38
+ if (matchesAny(haystack, ["opencode", "open-code", "open code"])) return "opencode";
39
+ if (matchesAny(haystack, ["claude-code", "claude code", "claudecode"])) return "claude-code";
40
+ if (matchesAny(haystack, ["codex desktop", "codex-cli", "openai-codex", "codex"])) {
41
+ return "codex";
42
+ }
43
+
44
+ return "unknown";
45
+ }
46
+
47
+ export function clientAppLabel(client: ClientApp): string | null {
48
+ switch (client) {
49
+ case "codex":
50
+ case "opencode":
51
+ case "mimo-code":
52
+ case "claude-code":
53
+ return CLIENT_LABELS[client];
54
+ case "unknown":
55
+ return null;
56
+ }
57
+ }
58
+
59
+ function CodexMark(): JSX.Element {
60
+ return (
61
+ <svg viewBox="0 0 24 24" className="size-full" aria-hidden="true">
62
+ <circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" strokeWidth="2.2" />
63
+ <path
64
+ d="M14.8 8.6a4.8 4.8 0 1 0 0 6.8"
65
+ fill="none"
66
+ stroke="currentColor"
67
+ strokeLinecap="round"
68
+ strokeWidth="2.2"
69
+ />
70
+ </svg>
71
+ );
72
+ }
73
+
74
+ function OpenCodeMark(): JSX.Element {
75
+ return (
76
+ <svg viewBox="0 0 24 24" className="size-full" aria-hidden="true">
77
+ <path d="M7 4h10v16H7z" fill="none" stroke="currentColor" strokeWidth="2.2" />
78
+ <path d="M10 8h4M10 12h4M10 16h2" stroke="currentColor" strokeLinecap="round" />
79
+ </svg>
80
+ );
81
+ }
82
+
83
+ function MiMoCodeMark(): JSX.Element {
84
+ return (
85
+ <svg viewBox="0 0 24 24" className="size-full" aria-hidden="true">
86
+ <path
87
+ d="M5 18V6h3.2l3.8 6.1L15.8 6H19v12h-3V11.3l-3.1 5h-1.8L8 11.3V18z"
88
+ fill="currentColor"
89
+ />
90
+ </svg>
91
+ );
92
+ }
93
+
94
+ function ClaudeCodeMark(): JSX.Element {
95
+ return (
96
+ <svg viewBox="0 0 24 24" className="size-full" aria-hidden="true">
97
+ <path
98
+ fill="currentColor"
99
+ fillRule="evenodd"
100
+ clipRule="evenodd"
101
+ d="M21 10.95h3v3.1h-3v3.03h-1.49V20H18v-2.92h-1.49V20H15v-2.92H9V20H7.49v-2.92H6V20H4.49v-2.92H3v-3.03H0v-3.1h3V5h18v5.95zM6 10.95h1.49V8.1H6v2.85zm10.51 0H18V8.1h-1.49v2.85z"
102
+ />
103
+ </svg>
104
+ );
105
+ }
106
+
107
+ export function ClientLogo({
108
+ client,
109
+ className,
110
+ }: {
111
+ client: ClientApp;
112
+ className?: string;
113
+ }): JSX.Element | null {
114
+ const label = clientAppLabel(client);
115
+ if (label === null) return null;
116
+
117
+ return (
118
+ <span
119
+ className={cn(
120
+ "inline-flex size-6 shrink-0 items-center justify-center rounded-md border border-white/10 bg-black/20 p-1 text-cyan-100 shadow-[inset_0_1px_0_rgba(255,255,255,0.05)]",
121
+ className,
122
+ )}
123
+ aria-label={label}
124
+ title={label}
125
+ >
126
+ {client === "codex" && <CodexMark />}
127
+ {client === "opencode" && <OpenCodeMark />}
128
+ {client === "mimo-code" && <MiMoCodeMark />}
129
+ {client === "claude-code" && <ClaudeCodeMark />}
130
+ </span>
131
+ );
132
+ }
@@ -1173,19 +1173,24 @@ function LatestLogsPreview({ logs }: { logs: SessionLogSummary[] }): JSX.Element
1173
1173
  Latest logs
1174
1174
  </div>
1175
1175
  <div className="divide-y divide-border">
1176
- {visibleLogs.map((log) => (
1177
- <div
1178
- key={log.id}
1179
- className="grid gap-2 px-3 py-2 text-xs sm:grid-cols-[72px_1fr_88px_88px]"
1180
- >
1181
- <span className="font-mono text-muted-foreground">#{log.id}</span>
1182
- <span className="min-w-0 truncate">
1183
- {displayText(log.model)} · {log.apiFormat} · {log.path}
1184
- </span>
1185
- <span className="font-mono text-muted-foreground">{formatMs(log.firstChunkMs)}</span>
1186
- <span className="font-mono text-muted-foreground">{formatMs(log.latencyMs)}</span>
1187
- </div>
1188
- ))}
1176
+ {visibleLogs.map((log) => {
1177
+ const displayNumber = log.sessionLogNumber ?? log.id;
1178
+ return (
1179
+ <div
1180
+ key={log.id}
1181
+ className="grid gap-2 px-3 py-2 text-xs sm:grid-cols-[72px_1fr_88px_88px]"
1182
+ >
1183
+ <span className="font-mono text-muted-foreground" title={`Log ID ${String(log.id)}`}>
1184
+ #{displayNumber}
1185
+ </span>
1186
+ <span className="min-w-0 truncate">
1187
+ {displayText(log.model)} · {log.apiFormat} · {log.path}
1188
+ </span>
1189
+ <span className="font-mono text-muted-foreground">{formatMs(log.firstChunkMs)}</span>
1190
+ <span className="font-mono text-muted-foreground">{formatMs(log.latencyMs)}</span>
1191
+ </div>
1192
+ );
1193
+ })}
1189
1194
  </div>
1190
1195
  </div>
1191
1196
  );
@@ -67,6 +67,7 @@ const ExternalProviderSchema = z.object({
67
67
  format: z.enum(["anthropic", "openai"]),
68
68
  anthropicBaseUrl: z.string(),
69
69
  openaiBaseUrl: z.string(),
70
+ openaiResponsesBaseUrl: z.string().optional().default(""),
70
71
  models: z.array(z.string()),
71
72
  sourceTool: z.enum(["claude-code", "opencode", "mimo-code"]),
72
73
  alreadyExists: z.boolean(),
@@ -186,6 +187,7 @@ export function ImportWizardDialog({
186
187
  format: p.format,
187
188
  anthropicBaseUrl: p.anthropicBaseUrl,
188
189
  openaiBaseUrl: p.openaiBaseUrl,
190
+ openaiResponsesBaseUrl: p.openaiResponsesBaseUrl,
189
191
  models: p.models,
190
192
  createdAt: now,
191
193
  updatedAt: now,
@@ -298,7 +300,11 @@ export function ImportWizardDialog({
298
300
  {p.models.length > 4 ? ` +${p.models.length - 4} more` : ""}
299
301
  </div>
300
302
  <div className="text-xs text-muted-foreground mt-0.5 truncate">
301
- {p.format === "anthropic" ? p.anthropicBaseUrl : p.openaiBaseUrl}
303
+ {p.format === "anthropic"
304
+ ? p.anthropicBaseUrl
305
+ : p.openaiResponsesBaseUrl !== ""
306
+ ? p.openaiResponsesBaseUrl
307
+ : p.openaiBaseUrl}
302
308
  </div>
303
309
  <div className="text-xs text-muted-foreground mt-0.5 font-mono">
304
310
  {p.apiKey.length > 8
@@ -594,13 +594,22 @@ export function ProviderCard({
594
594
  {provider.openaiBaseUrl !== undefined && provider.openaiBaseUrl !== "" && (
595
595
  <div className="flex min-w-0 flex-col gap-2">
596
596
  <div className="min-w-0 text-xs text-muted-foreground">
597
- <span className="font-medium">OpenAI:</span>{" "}
597
+ <span className="font-medium">OpenAI Chat:</span>{" "}
598
598
  <span className="truncate">{provider.openaiBaseUrl}</span>
599
599
  </div>
600
600
  {testResults !== undefined && <ProviderFormatTestStatus results={testResults.openai} />}
601
601
  </div>
602
602
  )}
603
603
 
604
+ {provider.openaiResponsesBaseUrl !== undefined && provider.openaiResponsesBaseUrl !== "" && (
605
+ <div className="flex min-w-0 flex-col gap-2">
606
+ <div className="min-w-0 text-xs text-muted-foreground">
607
+ <span className="font-medium">OpenAI Responses:</span>{" "}
608
+ <span className="truncate">{provider.openaiResponsesBaseUrl}</span>
609
+ </div>
610
+ </div>
611
+ )}
612
+
604
613
  {testResults?.testedAt !== undefined && (
605
614
  <div className="text-xs text-muted-foreground flex items-center gap-1">
606
615
  <Clock className="size-3" />