@assistant-ui/react-devtools 1.2.6 → 1.2.7

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 (533) hide show
  1. package/README.md +26 -8
  2. package/dist/DevToolsModal.d.ts +18 -2
  3. package/dist/DevToolsModal.d.ts.map +1 -1
  4. package/dist/DevToolsModal.js +25 -232
  5. package/dist/DevToolsModal.js.map +1 -1
  6. package/dist/DevToolsModalImpl.d.ts +11 -0
  7. package/dist/DevToolsModalImpl.d.ts.map +1 -0
  8. package/dist/DevToolsModalImpl.js +62 -0
  9. package/dist/DevToolsModalImpl.js.map +1 -0
  10. package/dist/data/createInProcessClient.d.ts +17 -0
  11. package/dist/data/createInProcessClient.d.ts.map +1 -0
  12. package/dist/data/createInProcessClient.js +54 -0
  13. package/dist/data/createInProcessClient.js.map +1 -0
  14. package/dist/data/projectApi.d.ts +22 -0
  15. package/dist/data/projectApi.d.ts.map +1 -0
  16. package/dist/data/projectApi.js +103 -0
  17. package/dist/data/projectApi.js.map +1 -0
  18. package/dist/data/types.d.ts +52 -0
  19. package/dist/data/types.d.ts.map +1 -0
  20. package/dist/data/types.js +10 -0
  21. package/dist/data/types.js.map +1 -0
  22. package/dist/data/useDevToolsClient.d.ts +19 -0
  23. package/dist/data/useDevToolsClient.d.ts.map +1 -0
  24. package/dist/data/useDevToolsClient.js +70 -0
  25. package/dist/data/useDevToolsClient.js.map +1 -0
  26. package/dist/index.d.ts +9 -10
  27. package/dist/index.js +7 -9
  28. package/dist/shell/DevToolsOverlay.d.ts +23 -0
  29. package/dist/shell/DevToolsOverlay.d.ts.map +1 -0
  30. package/dist/shell/DevToolsOverlay.js +106 -0
  31. package/dist/shell/DevToolsOverlay.js.map +1 -0
  32. package/dist/shell/DevToolsPanel.d.ts +23 -0
  33. package/dist/shell/DevToolsPanel.d.ts.map +1 -0
  34. package/dist/shell/DevToolsPanel.js +256 -0
  35. package/dist/shell/DevToolsPanel.js.map +1 -0
  36. package/dist/shell/ShadowRoot.d.ts +24 -0
  37. package/dist/shell/ShadowRoot.d.ts.map +1 -0
  38. package/dist/shell/ShadowRoot.js +107 -0
  39. package/dist/shell/ShadowRoot.js.map +1 -0
  40. package/dist/shell/SplitLayout.d.ts +28 -0
  41. package/dist/shell/SplitLayout.d.ts.map +1 -0
  42. package/dist/shell/SplitLayout.js +67 -0
  43. package/dist/shell/SplitLayout.js.map +1 -0
  44. package/dist/shell/registry.d.ts +41 -0
  45. package/dist/shell/registry.d.ts.map +1 -0
  46. package/dist/shell/registry.js +36 -0
  47. package/dist/shell/registry.js.map +1 -0
  48. package/dist/shell/tabs/ActivityTab.d.ts +13 -0
  49. package/dist/shell/tabs/ActivityTab.d.ts.map +1 -0
  50. package/dist/shell/tabs/ActivityTab.js +259 -0
  51. package/dist/shell/tabs/ActivityTab.js.map +1 -0
  52. package/dist/shell/tabs/ContextTab.d.ts +11 -0
  53. package/dist/shell/tabs/ContextTab.d.ts.map +1 -0
  54. package/dist/shell/tabs/ContextTab.js +210 -0
  55. package/dist/shell/tabs/ContextTab.js.map +1 -0
  56. package/dist/shell/tabs/RawTab.d.ts +11 -0
  57. package/dist/shell/tabs/RawTab.d.ts.map +1 -0
  58. package/dist/shell/tabs/RawTab.js +238 -0
  59. package/dist/shell/tabs/RawTab.js.map +1 -0
  60. package/dist/shell/tabs/ThreadTab.d.ts +12 -0
  61. package/dist/shell/tabs/ThreadTab.d.ts.map +1 -0
  62. package/dist/shell/tabs/ThreadTab.js +426 -0
  63. package/dist/shell/tabs/ThreadTab.js.map +1 -0
  64. package/dist/shell/tabs/navSelection.d.ts +10 -0
  65. package/dist/shell/tabs/navSelection.d.ts.map +1 -0
  66. package/dist/shell/tabs/navSelection.js +37 -0
  67. package/dist/shell/tabs/navSelection.js.map +1 -0
  68. package/dist/styles/panel.generated.d.ts +5 -0
  69. package/dist/styles/panel.generated.d.ts.map +1 -0
  70. package/dist/styles/panel.generated.js +6 -0
  71. package/dist/styles/panel.generated.js.map +1 -0
  72. package/dist/types.d.ts +1 -3
  73. package/dist/types.d.ts.map +1 -1
  74. package/dist/utils/common.d.ts +24 -0
  75. package/dist/utils/common.d.ts.map +1 -0
  76. package/dist/utils/common.js +64 -0
  77. package/dist/utils/common.js.map +1 -0
  78. package/dist/utils/diff.d.ts +16 -0
  79. package/dist/utils/diff.d.ts.map +1 -0
  80. package/dist/utils/diff.js +41 -0
  81. package/dist/utils/diff.js.map +1 -0
  82. package/dist/utils/serialization.d.ts.map +1 -1
  83. package/dist/utils/serialization.js +4 -1
  84. package/dist/utils/serialization.js.map +1 -1
  85. package/dist/views/activity/EventLogRow.d.ts +28 -0
  86. package/dist/views/activity/EventLogRow.d.ts.map +1 -0
  87. package/dist/views/activity/EventLogRow.js +185 -0
  88. package/dist/views/activity/EventLogRow.js.map +1 -0
  89. package/dist/views/activity/EventStreamPane.d.ts +11 -0
  90. package/dist/views/activity/EventStreamPane.d.ts.map +1 -0
  91. package/dist/views/activity/EventStreamPane.js +98 -0
  92. package/dist/views/activity/EventStreamPane.js.map +1 -0
  93. package/dist/views/activity/OrphansPane.d.ts +11 -0
  94. package/dist/views/activity/OrphansPane.d.ts.map +1 -0
  95. package/dist/views/activity/OrphansPane.js +39 -0
  96. package/dist/views/activity/OrphansPane.js.map +1 -0
  97. package/dist/views/activity/RunDetailPane.d.ts +11 -0
  98. package/dist/views/activity/RunDetailPane.d.ts.map +1 -0
  99. package/dist/views/activity/RunDetailPane.js +344 -0
  100. package/dist/views/activity/RunDetailPane.js.map +1 -0
  101. package/dist/views/activity/activityNodes.d.ts +39 -0
  102. package/dist/views/activity/activityNodes.d.ts.map +1 -0
  103. package/dist/views/activity/activityNodes.js +199 -0
  104. package/dist/views/activity/activityNodes.js.map +1 -0
  105. package/dist/views/activity/index.d.ts +6 -0
  106. package/dist/views/activity/index.js +6 -0
  107. package/dist/views/attachments/AttachmentList.d.ts +15 -0
  108. package/dist/views/attachments/AttachmentList.d.ts.map +1 -0
  109. package/dist/views/attachments/AttachmentList.js +279 -0
  110. package/dist/views/attachments/AttachmentList.js.map +1 -0
  111. package/dist/views/attachments/MediaPartView.d.ts +27 -0
  112. package/dist/views/attachments/MediaPartView.d.ts.map +1 -0
  113. package/dist/views/attachments/MediaPartView.js +180 -0
  114. package/dist/views/attachments/MediaPartView.js.map +1 -0
  115. package/dist/views/attachments/formatBytes.d.ts +8 -0
  116. package/dist/views/attachments/formatBytes.d.ts.map +1 -0
  117. package/dist/views/attachments/formatBytes.js +14 -0
  118. package/dist/views/attachments/formatBytes.js.map +1 -0
  119. package/dist/views/attachments/index.d.ts +5 -0
  120. package/dist/views/attachments/index.js +4 -0
  121. package/dist/views/attachments/parseAttachment.d.ts +8 -0
  122. package/dist/views/attachments/parseAttachment.d.ts.map +1 -0
  123. package/dist/views/attachments/parseAttachment.js +58 -0
  124. package/dist/views/attachments/parseAttachment.js.map +1 -0
  125. package/dist/views/attachments/types.d.ts +18 -0
  126. package/dist/views/attachments/types.d.ts.map +1 -0
  127. package/dist/views/attachments/types.js +0 -0
  128. package/dist/views/context/ContextDetail.d.ts +14 -0
  129. package/dist/views/context/ContextDetail.d.ts.map +1 -0
  130. package/dist/views/context/ContextDetail.js +87 -0
  131. package/dist/views/context/ContextDetail.js.map +1 -0
  132. package/dist/views/context/ToolUIsView.d.ts +9 -0
  133. package/dist/views/context/ToolUIsView.d.ts.map +1 -0
  134. package/dist/views/context/ToolUIsView.js +80 -0
  135. package/dist/views/context/ToolUIsView.js.map +1 -0
  136. package/dist/views/context/contextNodes.d.ts +32 -0
  137. package/dist/views/context/contextNodes.d.ts.map +1 -0
  138. package/dist/views/context/contextNodes.js +49 -0
  139. package/dist/views/context/contextNodes.js.map +1 -0
  140. package/dist/views/context/index.d.ts +4 -0
  141. package/dist/views/context/index.js +4 -0
  142. package/dist/views/mcp/McpView.d.ts +11 -0
  143. package/dist/views/mcp/McpView.d.ts.map +1 -0
  144. package/dist/views/mcp/McpView.js +239 -0
  145. package/dist/views/mcp/McpView.js.map +1 -0
  146. package/dist/views/mcp/index.d.ts +2 -0
  147. package/dist/views/mcp/index.js +2 -0
  148. package/dist/views/mcp/parse.d.ts +7 -0
  149. package/dist/views/mcp/parse.d.ts.map +1 -0
  150. package/dist/views/mcp/parse.js +43 -0
  151. package/dist/views/mcp/parse.js.map +1 -0
  152. package/dist/views/mcp/types.d.ts +22 -0
  153. package/dist/views/mcp/types.d.ts.map +1 -0
  154. package/dist/views/mcp/types.js +0 -0
  155. package/dist/views/message/ChainOfThought.d.ts +11 -0
  156. package/dist/views/message/ChainOfThought.d.ts.map +1 -0
  157. package/dist/views/message/ChainOfThought.js +132 -0
  158. package/dist/views/message/ChainOfThought.js.map +1 -0
  159. package/dist/views/message/MessageDetailPane.d.ts +12 -0
  160. package/dist/views/message/MessageDetailPane.d.ts.map +1 -0
  161. package/dist/views/message/MessageDetailPane.js +38 -0
  162. package/dist/views/message/MessageDetailPane.js.map +1 -0
  163. package/dist/views/message/MessageItem.d.ts +13 -0
  164. package/dist/views/message/MessageItem.d.ts.map +1 -0
  165. package/dist/views/message/MessageItem.js +136 -0
  166. package/dist/views/message/MessageItem.js.map +1 -0
  167. package/dist/views/message/MessageList.d.ts +13 -0
  168. package/dist/views/message/MessageList.d.ts.map +1 -0
  169. package/dist/views/message/MessageList.js +95 -0
  170. package/dist/views/message/MessageList.js.map +1 -0
  171. package/dist/views/message/MessageMetrics.d.ts +11 -0
  172. package/dist/views/message/MessageMetrics.d.ts.map +1 -0
  173. package/dist/views/message/MessageMetrics.js +93 -0
  174. package/dist/views/message/MessageMetrics.js.map +1 -0
  175. package/dist/views/message/MessageTimeline.d.ts +16 -0
  176. package/dist/views/message/MessageTimeline.d.ts.map +1 -0
  177. package/dist/views/message/MessageTimeline.js +100 -0
  178. package/dist/views/message/MessageTimeline.js.map +1 -0
  179. package/dist/views/message/PartDisclosure.d.ts +18 -0
  180. package/dist/views/message/PartDisclosure.d.ts.map +1 -0
  181. package/dist/views/message/PartDisclosure.js +79 -0
  182. package/dist/views/message/PartDisclosure.js.map +1 -0
  183. package/dist/views/message/PartView.d.ts +13 -0
  184. package/dist/views/message/PartView.d.ts.map +1 -0
  185. package/dist/views/message/PartView.js +416 -0
  186. package/dist/views/message/PartView.js.map +1 -0
  187. package/dist/views/message/RoleLabel.d.ts +11 -0
  188. package/dist/views/message/RoleLabel.d.ts.map +1 -0
  189. package/dist/views/message/RoleLabel.js +30 -0
  190. package/dist/views/message/RoleLabel.js.map +1 -0
  191. package/dist/views/message/StatusBadge.d.ts +17 -0
  192. package/dist/views/message/StatusBadge.d.ts.map +1 -0
  193. package/dist/views/message/StatusBadge.js +58 -0
  194. package/dist/views/message/StatusBadge.js.map +1 -0
  195. package/dist/views/message/ToolCallView.d.ts +13 -0
  196. package/dist/views/message/ToolCallView.d.ts.map +1 -0
  197. package/dist/views/message/ToolCallView.js +289 -0
  198. package/dist/views/message/ToolCallView.js.map +1 -0
  199. package/dist/views/message/TtftBar.d.ts +16 -0
  200. package/dist/views/message/TtftBar.d.ts.map +1 -0
  201. package/dist/views/message/TtftBar.js +128 -0
  202. package/dist/views/message/TtftBar.js.map +1 -0
  203. package/dist/views/message/index.d.ts +6 -0
  204. package/dist/views/message/index.js +5 -0
  205. package/dist/views/message/messagePlainText.d.ts +8 -0
  206. package/dist/views/message/messagePlainText.d.ts.map +1 -0
  207. package/dist/views/message/messagePlainText.js +39 -0
  208. package/dist/views/message/messagePlainText.js.map +1 -0
  209. package/dist/views/message/parse.d.ts +10 -0
  210. package/dist/views/message/parse.d.ts.map +1 -0
  211. package/dist/views/message/parse.js +235 -0
  212. package/dist/views/message/parse.js.map +1 -0
  213. package/dist/views/message/types.d.ts +114 -0
  214. package/dist/views/message/types.d.ts.map +1 -0
  215. package/dist/views/message/types.js +0 -0
  216. package/dist/views/model-context/ModelContextView.d.ts +26 -0
  217. package/dist/views/model-context/ModelContextView.d.ts.map +1 -0
  218. package/dist/views/model-context/ModelContextView.js +214 -0
  219. package/dist/views/model-context/ModelContextView.js.map +1 -0
  220. package/dist/views/nav.d.ts +19 -0
  221. package/dist/views/nav.d.ts.map +1 -0
  222. package/dist/views/nav.js +8 -0
  223. package/dist/views/nav.js.map +1 -0
  224. package/dist/views/raw/RawDetail.d.ts +15 -0
  225. package/dist/views/raw/RawDetail.d.ts.map +1 -0
  226. package/dist/views/raw/RawDetail.js +79 -0
  227. package/dist/views/raw/RawDetail.js.map +1 -0
  228. package/dist/views/raw/index.d.ts +3 -0
  229. package/dist/views/raw/index.js +3 -0
  230. package/dist/views/raw/rawNodes.d.ts +20 -0
  231. package/dist/views/raw/rawNodes.d.ts.map +1 -0
  232. package/dist/views/raw/rawNodes.js +78 -0
  233. package/dist/views/raw/rawNodes.js.map +1 -0
  234. package/dist/views/raw/statePreview.d.ts +5 -0
  235. package/dist/views/raw/statePreview.d.ts.map +1 -0
  236. package/dist/views/raw/statePreview.js +213 -0
  237. package/dist/views/raw/statePreview.js.map +1 -0
  238. package/dist/views/runs/PayloadDiff.d.ts +11 -0
  239. package/dist/views/runs/PayloadDiff.d.ts.map +1 -0
  240. package/dist/views/runs/PayloadDiff.js +92 -0
  241. package/dist/views/runs/PayloadDiff.js.map +1 -0
  242. package/dist/views/runs/parse.d.ts +8 -0
  243. package/dist/views/runs/parse.d.ts.map +1 -0
  244. package/dist/views/runs/parse.js +78 -0
  245. package/dist/views/runs/parse.js.map +1 -0
  246. package/dist/views/runs/types.d.ts +25 -0
  247. package/dist/views/runs/types.d.ts.map +1 -0
  248. package/dist/views/runs/types.js +0 -0
  249. package/dist/views/scopes/ScopesView.d.ts +9 -0
  250. package/dist/views/scopes/ScopesView.d.ts.map +1 -0
  251. package/dist/views/scopes/ScopesView.js +235 -0
  252. package/dist/views/scopes/ScopesView.js.map +1 -0
  253. package/dist/views/scopes/index.d.ts +2 -0
  254. package/dist/views/scopes/index.js +2 -0
  255. package/dist/views/scopes/parse.d.ts +7 -0
  256. package/dist/views/scopes/parse.d.ts.map +1 -0
  257. package/dist/views/scopes/parse.js +23 -0
  258. package/dist/views/scopes/parse.js.map +1 -0
  259. package/dist/views/scopes/types.d.ts +10 -0
  260. package/dist/views/scopes/types.d.ts.map +1 -0
  261. package/dist/views/scopes/types.js +0 -0
  262. package/dist/views/thread/ComposerAttachments.d.ts +11 -0
  263. package/dist/views/thread/ComposerAttachments.d.ts.map +1 -0
  264. package/dist/views/thread/ComposerAttachments.js +22 -0
  265. package/dist/views/thread/ComposerAttachments.js.map +1 -0
  266. package/dist/views/thread/ComposerFlags.d.ts +11 -0
  267. package/dist/views/thread/ComposerFlags.d.ts.map +1 -0
  268. package/dist/views/thread/ComposerFlags.js +54 -0
  269. package/dist/views/thread/ComposerFlags.js.map +1 -0
  270. package/dist/views/thread/ComposerQueue.d.ts +11 -0
  271. package/dist/views/thread/ComposerQueue.d.ts.map +1 -0
  272. package/dist/views/thread/ComposerQueue.js +55 -0
  273. package/dist/views/thread/ComposerQueue.js.map +1 -0
  274. package/dist/views/thread/ConversationList.d.ts +18 -0
  275. package/dist/views/thread/ConversationList.d.ts.map +1 -0
  276. package/dist/views/thread/ConversationList.js +228 -0
  277. package/dist/views/thread/ConversationList.js.map +1 -0
  278. package/dist/views/thread/ConversationStatusDot.d.ts +29 -0
  279. package/dist/views/thread/ConversationStatusDot.d.ts.map +1 -0
  280. package/dist/views/thread/ConversationStatusDot.js +91 -0
  281. package/dist/views/thread/ConversationStatusDot.js.map +1 -0
  282. package/dist/views/thread/ThreadDetails.d.ts +13 -0
  283. package/dist/views/thread/ThreadDetails.d.ts.map +1 -0
  284. package/dist/views/thread/ThreadDetails.js +170 -0
  285. package/dist/views/thread/ThreadDetails.js.map +1 -0
  286. package/dist/views/thread/Transcript.d.ts +21 -0
  287. package/dist/views/thread/Transcript.d.ts.map +1 -0
  288. package/dist/views/thread/Transcript.js +520 -0
  289. package/dist/views/thread/Transcript.js.map +1 -0
  290. package/dist/views/thread/index.d.ts +10 -0
  291. package/dist/views/thread/index.js +9 -0
  292. package/dist/views/thread/resolve.d.ts +13 -0
  293. package/dist/views/thread/resolve.d.ts.map +1 -0
  294. package/dist/views/thread/resolve.js +29 -0
  295. package/dist/views/thread/resolve.js.map +1 -0
  296. package/dist/views/thread/types.d.ts +50 -0
  297. package/dist/views/thread/types.d.ts.map +1 -0
  298. package/dist/views/thread/types.js +0 -0
  299. package/dist/views/thread/utils.d.ts +10 -0
  300. package/dist/views/thread/utils.d.ts.map +1 -0
  301. package/dist/views/thread/utils.js +77 -0
  302. package/dist/views/thread/utils.js.map +1 -0
  303. package/dist/views/ui/CenteredMessage.d.ts +11 -0
  304. package/dist/views/ui/CenteredMessage.d.ts.map +1 -0
  305. package/dist/views/ui/CenteredMessage.js +21 -0
  306. package/dist/views/ui/CenteredMessage.js.map +1 -0
  307. package/dist/views/ui/Chip.d.ts +13 -0
  308. package/dist/views/ui/Chip.d.ts.map +1 -0
  309. package/dist/views/ui/Chip.js +30 -0
  310. package/dist/views/ui/Chip.js.map +1 -0
  311. package/dist/views/ui/ControlButton.d.ts +10 -0
  312. package/dist/views/ui/ControlButton.d.ts.map +1 -0
  313. package/dist/views/ui/ControlButton.js +39 -0
  314. package/dist/views/ui/ControlButton.js.map +1 -0
  315. package/dist/views/ui/CopyButton.d.ts +19 -0
  316. package/dist/views/ui/CopyButton.d.ts.map +1 -0
  317. package/dist/views/ui/CopyButton.js +125 -0
  318. package/dist/views/ui/CopyButton.js.map +1 -0
  319. package/dist/views/ui/EmptyState.d.ts +11 -0
  320. package/dist/views/ui/EmptyState.d.ts.map +1 -0
  321. package/dist/views/ui/EmptyState.js +21 -0
  322. package/dist/views/ui/EmptyState.js.map +1 -0
  323. package/dist/views/ui/InfoCard.d.ts +22 -0
  324. package/dist/views/ui/InfoCard.d.ts.map +1 -0
  325. package/dist/views/ui/InfoCard.js +44 -0
  326. package/dist/views/ui/InfoCard.js.map +1 -0
  327. package/dist/views/ui/JSONTree.d.ts +16 -0
  328. package/dist/views/ui/JSONTree.d.ts.map +1 -0
  329. package/dist/views/ui/JSONTree.js +394 -0
  330. package/dist/views/ui/JSONTree.js.map +1 -0
  331. package/dist/views/ui/PaneHeader.d.ts +27 -0
  332. package/dist/views/ui/PaneHeader.d.ts.map +1 -0
  333. package/dist/views/ui/PaneHeader.js +71 -0
  334. package/dist/views/ui/PaneHeader.js.map +1 -0
  335. package/dist/views/ui/RailTime.d.ts +12 -0
  336. package/dist/views/ui/RailTime.d.ts.map +1 -0
  337. package/dist/views/ui/RailTime.js +49 -0
  338. package/dist/views/ui/RailTime.js.map +1 -0
  339. package/dist/views/ui/SectionLabel.d.ts +11 -0
  340. package/dist/views/ui/SectionLabel.d.ts.map +1 -0
  341. package/dist/views/ui/SectionLabel.js +21 -0
  342. package/dist/views/ui/SectionLabel.js.map +1 -0
  343. package/dist/views/ui/SelectableRow.d.ts +18 -0
  344. package/dist/views/ui/SelectableRow.d.ts.map +1 -0
  345. package/dist/views/ui/SelectableRow.js +49 -0
  346. package/dist/views/ui/SelectableRow.js.map +1 -0
  347. package/dist/views/ui/Sparkline.d.ts +17 -0
  348. package/dist/views/ui/Sparkline.d.ts.map +1 -0
  349. package/dist/views/ui/Sparkline.js +96 -0
  350. package/dist/views/ui/Sparkline.js.map +1 -0
  351. package/dist/views/ui/SummaryItem.d.ts +23 -0
  352. package/dist/views/ui/SummaryItem.d.ts.map +1 -0
  353. package/dist/views/ui/SummaryItem.js +59 -0
  354. package/dist/views/ui/SummaryItem.js.map +1 -0
  355. package/dist/views/ui/ToneBadge.d.ts +18 -0
  356. package/dist/views/ui/ToneBadge.d.ts.map +1 -0
  357. package/dist/views/ui/ToneBadge.js +34 -0
  358. package/dist/views/ui/ToneBadge.js.map +1 -0
  359. package/dist/views/ui/badgeTone.d.ts +21 -0
  360. package/dist/views/ui/badgeTone.d.ts.map +1 -0
  361. package/dist/views/ui/badgeTone.js +33 -0
  362. package/dist/views/ui/badgeTone.js.map +1 -0
  363. package/dist/views/ui/index.d.ts +16 -0
  364. package/dist/views/ui/index.js +16 -0
  365. package/dist/views/ui/useCopyToClipboard.d.ts +12 -0
  366. package/dist/views/ui/useCopyToClipboard.d.ts.map +1 -0
  367. package/dist/views/ui/useCopyToClipboard.js +44 -0
  368. package/dist/views/ui/useCopyToClipboard.js.map +1 -0
  369. package/package.json +9 -5
  370. package/src/DevToolsModal.tsx +26 -179
  371. package/src/DevToolsModalImpl.tsx +60 -0
  372. package/src/data/createInProcessClient.ts +66 -0
  373. package/src/data/projectApi.test.ts +100 -0
  374. package/src/data/projectApi.ts +169 -0
  375. package/src/data/types.ts +54 -0
  376. package/src/data/useDevToolsClient.ts +59 -0
  377. package/src/index.ts +16 -13
  378. package/src/shell/DevToolsOverlay.tsx +84 -0
  379. package/src/shell/DevToolsPanel.tsx +192 -0
  380. package/src/shell/ShadowRoot.tsx +85 -0
  381. package/src/shell/SplitLayout.tsx +46 -0
  382. package/src/shell/registry.ts +51 -0
  383. package/src/shell/tabs/ActivityTab.test.tsx +34 -0
  384. package/src/shell/tabs/ActivityTab.tsx +161 -0
  385. package/src/shell/tabs/ContextTab.test.tsx +37 -0
  386. package/src/shell/tabs/ContextTab.tsx +157 -0
  387. package/src/shell/tabs/RawTab.test.tsx +43 -0
  388. package/src/shell/tabs/RawTab.tsx +123 -0
  389. package/src/shell/tabs/ThreadTab.tsx +220 -0
  390. package/src/shell/tabs/navSelection.ts +17 -0
  391. package/src/styles/panel.css +153 -0
  392. package/src/styles/panel.generated.ts +2 -0
  393. package/src/types.ts +0 -5
  394. package/src/utils/common.test.ts +30 -0
  395. package/src/utils/common.ts +101 -0
  396. package/src/utils/diff.test.ts +37 -0
  397. package/src/utils/diff.ts +41 -0
  398. package/src/utils/serialization.test.ts +31 -0
  399. package/src/utils/serialization.ts +4 -1
  400. package/src/views/activity/EventLogRow.tsx +108 -0
  401. package/src/views/activity/EventStreamPane.tsx +86 -0
  402. package/src/views/activity/OrphansPane.tsx +23 -0
  403. package/src/views/activity/RunDetailPane.tsx +128 -0
  404. package/src/views/activity/activityNodes.test.ts +24 -0
  405. package/src/views/activity/activityNodes.ts +179 -0
  406. package/src/views/activity/index.ts +10 -0
  407. package/src/views/attachments/AttachmentList.tsx +122 -0
  408. package/src/views/attachments/MediaPartView.tsx +77 -0
  409. package/src/views/attachments/formatBytes.ts +15 -0
  410. package/src/views/attachments/index.ts +4 -0
  411. package/src/views/attachments/parseAttachment.test.ts +37 -0
  412. package/src/views/attachments/parseAttachment.ts +85 -0
  413. package/src/views/attachments/types.ts +15 -0
  414. package/src/views/context/ContextDetail.tsx +37 -0
  415. package/src/views/context/ToolUIsView.tsx +44 -0
  416. package/src/views/context/contextNodes.test.ts +31 -0
  417. package/src/views/context/contextNodes.ts +66 -0
  418. package/src/views/context/index.ts +4 -0
  419. package/src/views/mcp/McpView.tsx +125 -0
  420. package/src/views/mcp/index.ts +1 -0
  421. package/src/views/mcp/parse.test.ts +63 -0
  422. package/src/views/mcp/parse.ts +65 -0
  423. package/src/views/mcp/render.test.tsx +34 -0
  424. package/src/views/mcp/types.ts +20 -0
  425. package/src/views/message/ChainOfThought.tsx +74 -0
  426. package/src/views/message/MessageDetailPane.tsx +26 -0
  427. package/src/views/message/MessageItem.tsx +94 -0
  428. package/src/views/message/MessageList.tsx +48 -0
  429. package/src/views/message/MessageMetrics.tsx +68 -0
  430. package/src/views/message/MessageTimeline.test.tsx +78 -0
  431. package/src/views/message/MessageTimeline.tsx +51 -0
  432. package/src/views/message/PartDisclosure.tsx +32 -0
  433. package/src/views/message/PartView.tsx +197 -0
  434. package/src/views/message/RoleLabel.tsx +22 -0
  435. package/src/views/message/StatusBadge.tsx +28 -0
  436. package/src/views/message/ToolCallView.tsx +151 -0
  437. package/src/views/message/TtftBar.tsx +44 -0
  438. package/src/views/message/index.ts +5 -0
  439. package/src/views/message/messagePlainText.test.ts +48 -0
  440. package/src/views/message/messagePlainText.ts +65 -0
  441. package/src/views/message/parse.test.ts +269 -0
  442. package/src/views/message/parse.ts +282 -0
  443. package/src/views/message/render.test.tsx +128 -0
  444. package/src/views/message/types.ts +137 -0
  445. package/src/views/model-context/ModelContextView.tsx +71 -0
  446. package/src/views/model-context/render.test.tsx +24 -0
  447. package/src/views/nav.ts +18 -0
  448. package/src/views/raw/RawDetail.tsx +39 -0
  449. package/src/views/raw/index.ts +3 -0
  450. package/src/views/raw/rawNodes.test.ts +38 -0
  451. package/src/views/raw/rawNodes.ts +107 -0
  452. package/src/views/raw/statePreview.tsx +188 -0
  453. package/src/views/runs/PayloadDiff.tsx +49 -0
  454. package/src/views/runs/parse.test.ts +152 -0
  455. package/src/views/runs/parse.ts +110 -0
  456. package/src/views/runs/types.ts +23 -0
  457. package/src/views/scopes/ScopesView.tsx +105 -0
  458. package/src/views/scopes/index.ts +1 -0
  459. package/src/views/scopes/parse.test.ts +35 -0
  460. package/src/views/scopes/parse.ts +30 -0
  461. package/src/views/scopes/render.test.tsx +35 -0
  462. package/src/views/scopes/types.ts +6 -0
  463. package/src/views/thread/ComposerAttachments.test.tsx +36 -0
  464. package/src/views/thread/ComposerAttachments.tsx +8 -0
  465. package/src/views/thread/ComposerFlags.test.tsx +23 -0
  466. package/src/views/thread/ComposerFlags.tsx +19 -0
  467. package/src/views/thread/ComposerQueue.test.tsx +20 -0
  468. package/src/views/thread/ComposerQueue.tsx +26 -0
  469. package/src/views/thread/ConversationList.tsx +127 -0
  470. package/src/views/thread/ConversationStatusDot.test.ts +86 -0
  471. package/src/views/thread/ConversationStatusDot.tsx +126 -0
  472. package/src/views/thread/ThreadDetails.tsx +85 -0
  473. package/src/views/thread/Transcript.test.tsx +56 -0
  474. package/src/views/thread/Transcript.tsx +332 -0
  475. package/src/views/thread/index.ts +19 -0
  476. package/src/views/thread/render.test.tsx +41 -0
  477. package/src/views/thread/resolve.ts +36 -0
  478. package/src/views/thread/types.ts +53 -0
  479. package/src/views/thread/utils.test.ts +72 -0
  480. package/src/views/thread/utils.ts +149 -0
  481. package/src/views/ui/CenteredMessage.tsx +7 -0
  482. package/src/views/ui/Chip.tsx +17 -0
  483. package/src/views/ui/ControlButton.tsx +15 -0
  484. package/src/views/ui/CopyButton.tsx +73 -0
  485. package/src/views/ui/EmptyState.tsx +7 -0
  486. package/src/views/ui/InfoCard.tsx +35 -0
  487. package/src/views/ui/JSONTree.test.tsx +29 -0
  488. package/src/views/ui/JSONTree.tsx +240 -0
  489. package/src/views/ui/PaneHeader.tsx +46 -0
  490. package/src/views/ui/RailTime.tsx +27 -0
  491. package/src/views/ui/SectionLabel.tsx +7 -0
  492. package/src/views/ui/SelectableRow.tsx +41 -0
  493. package/src/views/ui/Sparkline.tsx +49 -0
  494. package/src/views/ui/SummaryItem.tsx +25 -0
  495. package/src/views/ui/ToneBadge.tsx +26 -0
  496. package/src/views/ui/badgeTone.ts +40 -0
  497. package/src/views/ui/index.ts +20 -0
  498. package/src/views/ui/useCopyToClipboard.ts +27 -0
  499. package/dist/DevToolsFrame.d.ts +0 -11
  500. package/dist/DevToolsFrame.d.ts.map +0 -1
  501. package/dist/DevToolsFrame.js +0 -66
  502. package/dist/DevToolsFrame.js.map +0 -1
  503. package/dist/DevToolsHost.d.ts +0 -38
  504. package/dist/DevToolsHost.d.ts.map +0 -1
  505. package/dist/DevToolsHost.js +0 -93
  506. package/dist/DevToolsHost.js.map +0 -1
  507. package/dist/ExtensionHost.d.ts +0 -10
  508. package/dist/ExtensionHost.d.ts.map +0 -1
  509. package/dist/ExtensionHost.js +0 -42
  510. package/dist/ExtensionHost.js.map +0 -1
  511. package/dist/FrameClient.d.ts +0 -38
  512. package/dist/FrameClient.d.ts.map +0 -1
  513. package/dist/FrameClient.js +0 -53
  514. package/dist/FrameClient.js.map +0 -1
  515. package/dist/FrameHost.d.ts +0 -11
  516. package/dist/FrameHost.d.ts.map +0 -1
  517. package/dist/FrameHost.js +0 -26
  518. package/dist/FrameHost.js.map +0 -1
  519. package/dist/constants.d.ts +0 -6
  520. package/dist/constants.d.ts.map +0 -1
  521. package/dist/constants.js +0 -7
  522. package/dist/constants.js.map +0 -1
  523. package/dist/styles/DevToolsModal.styles.d.ts +0 -18
  524. package/dist/styles/DevToolsModal.styles.d.ts.map +0 -1
  525. package/dist/styles/DevToolsModal.styles.js +0 -120
  526. package/dist/styles/DevToolsModal.styles.js.map +0 -1
  527. package/src/DevToolsFrame.tsx +0 -55
  528. package/src/DevToolsHost.ts +0 -178
  529. package/src/ExtensionHost.ts +0 -57
  530. package/src/FrameClient.ts +0 -99
  531. package/src/FrameHost.ts +0 -31
  532. package/src/constants.ts +0 -2
  533. package/src/styles/DevToolsModal.styles.ts +0 -137
@@ -0,0 +1,41 @@
1
+ export interface DiffEntry {
2
+ path: string;
3
+ kind: "added" | "removed" | "changed";
4
+ before?: unknown;
5
+ after?: unknown;
6
+ }
7
+
8
+ const isPlainObject = (value: unknown): value is Record<string, unknown> =>
9
+ value !== null && typeof value === "object" && !Array.isArray(value);
10
+
11
+ /**
12
+ * Structural diff of two JSON-safe values by dotted path. Objects recurse
13
+ * key-by-key; arrays and primitives are compared as whole leaves. Used for the
14
+ * opt-in event payload diff, where most payloads are shallow.
15
+ */
16
+ export const diffValues = (
17
+ before: unknown,
18
+ after: unknown,
19
+ base = "",
20
+ ): DiffEntry[] => {
21
+ if (isPlainObject(before) && isPlainObject(after)) {
22
+ const entries: DiffEntry[] = [];
23
+ const keys = new Set([...Object.keys(before), ...Object.keys(after)]);
24
+ for (const key of keys) {
25
+ const path = base ? `${base}.${key}` : key;
26
+ const hasBefore = key in before;
27
+ const hasAfter = key in after;
28
+ if (hasBefore && !hasAfter) {
29
+ entries.push({ path, kind: "removed", before: before[key] });
30
+ } else if (!hasBefore && hasAfter) {
31
+ entries.push({ path, kind: "added", after: after[key] });
32
+ } else {
33
+ entries.push(...diffValues(before[key], after[key], path));
34
+ }
35
+ }
36
+ return entries;
37
+ }
38
+
39
+ if (JSON.stringify(before) === JSON.stringify(after)) return [];
40
+ return [{ path: base || "(value)", kind: "changed", before, after }];
41
+ };
@@ -2,9 +2,40 @@ import { describe, expect, it } from "vitest";
2
2
  import {
3
3
  REDACTED,
4
4
  redactSensitive,
5
+ sanitizeForMessage,
5
6
  serializeModelContext,
6
7
  } from "./serialization";
7
8
 
9
+ describe("sanitizeForMessage", () => {
10
+ it("preserves shared (non-cyclic) sibling references instead of marking them circular", () => {
11
+ const shared = { value: 1 };
12
+
13
+ expect(sanitizeForMessage({ a: shared, b: shared })).toEqual({
14
+ a: { value: 1 },
15
+ b: { value: 1 },
16
+ });
17
+
18
+ const sharedArray = [1, 2];
19
+ expect(sanitizeForMessage({ a: sharedArray, b: sharedArray })).toEqual({
20
+ a: [1, 2],
21
+ b: [1, 2],
22
+ });
23
+ });
24
+
25
+ it("still detects genuine circular references", () => {
26
+ const cyclic: Record<string, unknown> = { name: "root" };
27
+ cyclic.self = cyclic;
28
+ expect(sanitizeForMessage(cyclic)).toEqual({
29
+ name: "root",
30
+ self: "[Circular]",
31
+ });
32
+
33
+ const cyclicArray: unknown[] = [];
34
+ cyclicArray.push(cyclicArray);
35
+ expect(sanitizeForMessage(cyclicArray)).toEqual(["[Circular]"]);
36
+ });
37
+ });
38
+
8
39
  describe("redactSensitive", () => {
9
40
  it("masks credential-named keys but leaves lookalikes alone", () => {
10
41
  const out = redactSensitive({
@@ -34,9 +34,11 @@ export const sanitizeForMessage = (
34
34
  if (Array.isArray(value)) {
35
35
  if (seen.has(value as unknown as object)) return "[Circular]";
36
36
  seen.add(value as unknown as object);
37
- return value
37
+ const result = value
38
38
  .map((entry) => sanitizeForMessage(entry, seen))
39
39
  .filter((item) => item !== undefined);
40
+ seen.delete(value as unknown as object);
41
+ return result;
40
42
  }
41
43
  if (typeof value === "object") {
42
44
  if (seen.has(value as object)) return "[Circular]";
@@ -47,6 +49,7 @@ export const sanitizeForMessage = (
47
49
  )) {
48
50
  result[key] = sanitizeForMessage(entry, seen);
49
51
  }
52
+ seen.delete(value as object);
50
53
  return result;
51
54
  }
52
55
  return value;
@@ -0,0 +1,108 @@
1
+ import clsx from "clsx";
2
+ import { eventScope, formatClockTime } from "../../utils/common";
3
+ import type { EventLogEntry } from "../../data/types";
4
+ import { PartDisclosure } from "../message/PartDisclosure";
5
+ import { PayloadDiff } from "../runs/PayloadDiff";
6
+ import { Chip, JSONTree } from "../ui";
7
+
8
+ export const EventLogRow = ({
9
+ log,
10
+ previous,
11
+ showDiff = false,
12
+ timeLabel,
13
+ }: {
14
+ log: EventLogEntry;
15
+ previous?: EventLogEntry | undefined;
16
+ showDiff?: boolean;
17
+ /** Overrides the default clock time label. */
18
+ timeLabel?: string | undefined;
19
+ }) => {
20
+ const scope = eventScope(log.event);
21
+ const suffix = log.event.slice(scope.length + 1) || log.event;
22
+
23
+ return (
24
+ <div className="flex flex-col gap-1 py-1.5">
25
+ <div className="flex min-w-0 items-center gap-2">
26
+ <span className="text-muted-foreground w-16 shrink-0 font-mono text-[10px] tabular-nums">
27
+ {timeLabel ?? formatClockTime(log.time)}
28
+ </span>
29
+ <Chip className="shrink-0">{scope}</Chip>
30
+ <span className="text-foreground min-w-0 truncate text-[11px] font-medium">
31
+ {suffix}
32
+ </span>
33
+ </div>
34
+ <div className="ps-[4.5rem]">
35
+ <PartDisclosure label="Payload">
36
+ <JSONTree value={log.data} openDepth={0} compact />
37
+ </PartDisclosure>
38
+ {showDiff && previous ? (
39
+ <div className="mt-1">
40
+ <PartDisclosure label="Diff">
41
+ <PayloadDiff before={previous.data} after={log.data} />
42
+ </PartDisclosure>
43
+ </div>
44
+ ) : null}
45
+ </div>
46
+ </div>
47
+ );
48
+ };
49
+
50
+ export const ScopeFilterBar = ({
51
+ eventTypesByScope,
52
+ unselectedEventTypes,
53
+ toggleScope,
54
+ toggleEventType,
55
+ }: {
56
+ eventTypesByScope: readonly (readonly [string, string[]])[];
57
+ unselectedEventTypes: ReadonlySet<string>;
58
+ toggleScope: (types: string[]) => void;
59
+ toggleEventType: (eventType: string) => void;
60
+ }) => {
61
+ if (!eventTypesByScope.length) return null;
62
+
63
+ return (
64
+ <div className="flex flex-col gap-2 px-3 py-2">
65
+ {eventTypesByScope.map(([scope, types]) => {
66
+ const allSelected = types.every(
67
+ (type) => !unselectedEventTypes.has(type),
68
+ );
69
+ return (
70
+ <div key={scope} className="flex flex-wrap items-center gap-1.5">
71
+ <button
72
+ type="button"
73
+ onClick={() => toggleScope(types)}
74
+ className={clsx(
75
+ "rounded-md border px-1.5 py-0.5 text-[10px] font-medium transition-colors",
76
+ allSelected
77
+ ? "bg-accent text-foreground"
78
+ : "text-muted-foreground",
79
+ )}
80
+ >
81
+ {scope}
82
+ </button>
83
+ {types.map((eventType) => (
84
+ <label
85
+ key={eventType}
86
+ title={eventType}
87
+ className={clsx(
88
+ "flex items-center gap-1 rounded-md border px-1.5 py-0.5 text-[10px] font-medium transition-colors",
89
+ !unselectedEventTypes.has(eventType)
90
+ ? "bg-accent text-foreground"
91
+ : "text-muted-foreground",
92
+ )}
93
+ >
94
+ <input
95
+ type="checkbox"
96
+ checked={!unselectedEventTypes.has(eventType)}
97
+ onChange={() => toggleEventType(eventType)}
98
+ className="accent-foreground size-3 rounded"
99
+ />
100
+ <span>{eventType.slice(scope.length + 1) || eventType}</span>
101
+ </label>
102
+ ))}
103
+ </div>
104
+ );
105
+ })}
106
+ </div>
107
+ );
108
+ };
@@ -0,0 +1,86 @@
1
+ import { Fragment } from "react";
2
+ import type { EventLogEntry } from "../../data/types";
3
+ import { previousSameScope, useEventLogFilters } from "./activityNodes";
4
+ import { EventLogRow, ScopeFilterBar } from "./EventLogRow";
5
+
6
+ export const EventStreamPane = ({
7
+ logs,
8
+ }: {
9
+ logs: readonly EventLogEntry[];
10
+ }) => {
11
+ const {
12
+ eventTypes,
13
+ eventTypesByScope,
14
+ filteredLogs,
15
+ query,
16
+ setQuery,
17
+ showDiffs,
18
+ setShowDiffs,
19
+ toggleEventType,
20
+ toggleScope,
21
+ unselectedEventTypes,
22
+ } = useEventLogFilters(logs);
23
+
24
+ return (
25
+ <div className="flex flex-col">
26
+ {eventTypes.length ? (
27
+ <div className="border-border shrink-0 border-b">
28
+ <ScopeFilterBar
29
+ eventTypesByScope={eventTypesByScope}
30
+ unselectedEventTypes={unselectedEventTypes}
31
+ toggleScope={toggleScope}
32
+ toggleEventType={toggleEventType}
33
+ />
34
+ <div className="border-border flex items-center gap-2 border-t px-3 py-2">
35
+ <input
36
+ type="text"
37
+ value={query}
38
+ onChange={(event) => setQuery(event.target.value)}
39
+ placeholder="Filter events…"
40
+ className="border-border bg-background text-foreground placeholder:text-muted-foreground h-7 flex-1 rounded-md border px-2 text-[12px]"
41
+ />
42
+ <label className="text-muted-foreground flex shrink-0 items-center gap-1.5 text-[11px]">
43
+ <input
44
+ type="checkbox"
45
+ checked={showDiffs}
46
+ onChange={() => setShowDiffs((prev) => !prev)}
47
+ className="accent-foreground size-3 rounded"
48
+ />
49
+ Diffs
50
+ </label>
51
+ </div>
52
+ </div>
53
+ ) : null}
54
+
55
+ <div className="flex flex-col px-3 pb-3">
56
+ {filteredLogs.length === 0 ? (
57
+ <div className="text-muted-foreground py-6 text-center text-[12px]">
58
+ {eventTypes.length === 0
59
+ ? "No events logged for this assistant instance."
60
+ : "No events match the current filters."}
61
+ </div>
62
+ ) : (
63
+ filteredLogs.map((log, index) => {
64
+ const previous = showDiffs
65
+ ? previousSameScope(filteredLogs, index)
66
+ : undefined;
67
+ return (
68
+ <Fragment key={`${log.event}-${log.time.getTime()}-${index}`}>
69
+ {log.event === "thread.runStart" && index > 0 ? (
70
+ <div className="text-muted-foreground border-border/70 flex items-center gap-2 border-t py-2 text-[10px]">
71
+ new run
72
+ </div>
73
+ ) : null}
74
+ <EventLogRow
75
+ log={log}
76
+ previous={previous}
77
+ showDiff={showDiffs}
78
+ />
79
+ </Fragment>
80
+ );
81
+ })
82
+ )}
83
+ </div>
84
+ </div>
85
+ );
86
+ };
@@ -0,0 +1,23 @@
1
+ import { formatClockTime } from "../../utils/common";
2
+ import type { RunEventEntry } from "../runs/types";
3
+ import { EventLogRow } from "./EventLogRow";
4
+
5
+ export const OrphansPane = ({
6
+ events,
7
+ }: {
8
+ events: readonly RunEventEntry[];
9
+ }) => (
10
+ <div className="flex flex-col px-3 pb-3">
11
+ {events.map((entry, index) => (
12
+ <EventLogRow
13
+ key={`${entry.event}-${entry.time.getTime()}-${index}`}
14
+ log={{
15
+ time: entry.time,
16
+ event: entry.event,
17
+ data: entry.data,
18
+ }}
19
+ timeLabel={formatClockTime(entry.time)}
20
+ />
21
+ ))}
22
+ </div>
23
+ );
@@ -0,0 +1,128 @@
1
+ import clsx from "clsx";
2
+ import { formatClockTime, formatMs } from "../../utils/common";
3
+ import { PartDisclosure } from "../message/PartDisclosure";
4
+ import { Chip, JSONTree, SummaryItem, SummaryList, ToneBadge } from "../ui";
5
+ import type { RunEventEntry, RunPreview } from "../runs/types";
6
+
7
+ const SCOPE_TONE: Record<string, string> = {
8
+ thread: "bg-blue-500",
9
+ composer: "bg-emerald-500",
10
+ threadListItem: "bg-amber-500",
11
+ };
12
+
13
+ const clampPercent = (offset: number, span: number) =>
14
+ span > 0 ? Math.min(100, Math.max(0, (offset / span) * 100)) : 0;
15
+
16
+ const eventLabel = (entry: RunEventEntry) =>
17
+ entry.event.slice(entry.scope.length + 1) || entry.event;
18
+
19
+ const dotClass = (scope: string) => SCOPE_TONE[scope] ?? "bg-muted-foreground";
20
+
21
+ const RULER_TICKS = 4;
22
+
23
+ const Ruler = ({ spanMs }: { spanMs: number }) => (
24
+ <div className="flex items-center">
25
+ <span className="w-28 shrink-0" />
26
+ <div className="text-muted-foreground flex flex-1 justify-between font-mono text-[10px] tabular-nums">
27
+ {Array.from({ length: RULER_TICKS + 1 }, (_, index) => (
28
+ <span key={index}>{formatMs((spanMs * index) / RULER_TICKS)}</span>
29
+ ))}
30
+ </div>
31
+ <span className="w-10 shrink-0" />
32
+ </div>
33
+ );
34
+
35
+ const TimelineRow = ({
36
+ entry,
37
+ spanMs,
38
+ }: {
39
+ entry: RunEventEntry;
40
+ spanMs: number;
41
+ }) => (
42
+ <div className="flex items-center gap-2 py-0.5">
43
+ <span className="flex w-28 shrink-0 items-center gap-1.5">
44
+ <span
45
+ className={clsx(
46
+ "size-1.5 shrink-0 rounded-full",
47
+ dotClass(entry.scope),
48
+ )}
49
+ />
50
+ <span className="text-foreground truncate text-[11px]">
51
+ {eventLabel(entry)}
52
+ </span>
53
+ </span>
54
+ <div className="bg-muted/40 relative h-3 flex-1 rounded">
55
+ <span
56
+ title={`${entry.event} +${formatMs(entry.offsetMs)}`}
57
+ className={clsx(
58
+ "absolute top-0 h-full w-0.5 rounded",
59
+ dotClass(entry.scope),
60
+ )}
61
+ style={{ left: `${clampPercent(entry.offsetMs, spanMs)}%` }}
62
+ />
63
+ </div>
64
+ <span className="text-muted-foreground w-10 shrink-0 text-right font-mono text-[10px] tabular-nums">
65
+ +{formatMs(entry.offsetMs)}
66
+ </span>
67
+ </div>
68
+ );
69
+
70
+ export const RunDetailPane = ({ run }: { run: RunPreview }) => (
71
+ <div className="flex flex-col gap-3">
72
+ <SummaryList>
73
+ <SummaryItem label="Started" value={formatClockTime(run.startTime)} />
74
+ <SummaryItem
75
+ label="Duration"
76
+ value={
77
+ run.endTime === undefined ? (
78
+ <ToneBadge tone="blue" size="sm">
79
+ running
80
+ </ToneBadge>
81
+ ) : (
82
+ formatMs(run.durationMs ?? 0)
83
+ )
84
+ }
85
+ />
86
+ <SummaryItem label="Events" value={String(run.events.length)} />
87
+ {run.threadId ? (
88
+ <SummaryItem label="Thread" value={run.threadId} />
89
+ ) : null}
90
+ </SummaryList>
91
+
92
+ <div className="flex flex-col gap-0.5">
93
+ <Ruler spanMs={run.spanMs} />
94
+ {run.events.map((entry, index) => (
95
+ <TimelineRow
96
+ key={`${entry.event}-${index}`}
97
+ entry={entry}
98
+ spanMs={run.spanMs}
99
+ />
100
+ ))}
101
+ </div>
102
+
103
+ <div className="flex flex-col">
104
+ {run.events.map((entry, index) => {
105
+ const scope = entry.scope;
106
+ const suffix = eventLabel(entry);
107
+ return (
108
+ <div key={`detail-${entry.event}-${index}`} className="py-1.5">
109
+ <div className="flex min-w-0 items-center gap-2">
110
+ <span className="text-muted-foreground w-12 shrink-0 font-mono text-[10px] tabular-nums">
111
+ +{formatMs(entry.offsetMs)}
112
+ </span>
113
+ <Chip className="shrink-0">{scope}</Chip>
114
+ <span className="text-foreground min-w-0 truncate text-[11px] font-medium">
115
+ {suffix}
116
+ </span>
117
+ </div>
118
+ <div className="ps-[3.75rem]">
119
+ <PartDisclosure label="Payload">
120
+ <JSONTree value={entry.data} openDepth={0} compact />
121
+ </PartDisclosure>
122
+ </div>
123
+ </div>
124
+ );
125
+ })}
126
+ </div>
127
+ </div>
128
+ );
@@ -0,0 +1,24 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import type { EventLogEntry } from "../../data/types";
3
+ import { buildActivityNav, defaultActivitySelection } from "./activityNodes";
4
+
5
+ const base = 2_000_000_000_000;
6
+ const t = (ms: number) => new Date(base + ms);
7
+
8
+ describe("buildActivityNav", () => {
9
+ it("lists stream, runs newest-first, and orphans", () => {
10
+ const logs: EventLogEntry[] = [
11
+ { time: t(0), event: "thread.runStart", data: { threadId: "T1" } },
12
+ { time: t(100), event: "composer.send", data: { threadId: "T1" } },
13
+ { time: t(200), event: "thread.runEnd", data: { threadId: "T1" } },
14
+ { time: t(300), event: "composer.edit", data: {} },
15
+ ];
16
+
17
+ const { nodes, runs, orphans } = buildActivityNav(logs);
18
+ expect(nodes[0]?.id).toBe("activity:stream");
19
+ expect(runs).toHaveLength(1);
20
+ expect(orphans).toHaveLength(1);
21
+ expect(nodes.some((node) => node.id === "activity:orphans")).toBe(true);
22
+ expect(defaultActivitySelection(nodes)).toBe("activity:run:run-0");
23
+ });
24
+ });
@@ -0,0 +1,179 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
2
+ import type { EventLogEntry } from "../../data/types";
3
+ import { eventScope } from "../../utils/common";
4
+ import { groupRuns } from "../runs/parse";
5
+ import type { RunEventEntry, RunPreview } from "../runs/types";
6
+
7
+ export type ActivityNode =
8
+ | { id: "activity:stream"; kind: "stream" }
9
+ | {
10
+ id: "activity:orphans";
11
+ kind: "orphans";
12
+ events: readonly RunEventEntry[];
13
+ }
14
+ | { id: `activity:run:${string}`; kind: "run"; run: RunPreview };
15
+
16
+ const activityRunId = (runId: string) => `activity:run:${runId}` as const;
17
+
18
+ export const buildActivityNav = (logs: readonly EventLogEntry[]) => {
19
+ const { runs, orphans } = groupRuns(logs);
20
+ const nodes: ActivityNode[] = [{ id: "activity:stream", kind: "stream" }];
21
+
22
+ for (const run of [...runs].reverse()) {
23
+ nodes.push({
24
+ id: activityRunId(run.id),
25
+ kind: "run",
26
+ run,
27
+ });
28
+ }
29
+
30
+ if (orphans.length) {
31
+ nodes.push({
32
+ id: "activity:orphans",
33
+ kind: "orphans",
34
+ events: orphans,
35
+ });
36
+ }
37
+
38
+ return { nodes, runs, orphans };
39
+ };
40
+
41
+ export const findActivityNode = (
42
+ nodes: readonly ActivityNode[],
43
+ nodeId: string | null,
44
+ ): ActivityNode | undefined =>
45
+ nodeId ? nodes.find((node) => node.id === nodeId) : undefined;
46
+
47
+ export const defaultActivitySelection = (nodes: readonly ActivityNode[]) => {
48
+ const latestRun = nodes.find((node) => node.kind === "run");
49
+ if (latestRun) return latestRun.id;
50
+ if (nodes.some((node) => node.kind === "orphans")) return "activity:orphans";
51
+ return "activity:stream";
52
+ };
53
+
54
+ export const useEventLogFilters = (logs: readonly EventLogEntry[]) => {
55
+ const [unselectedEventTypes, setUnselectedEventTypes] = useState<Set<string>>(
56
+ new Set(),
57
+ );
58
+ const knownEventTypesRef = useRef(new Set<string>());
59
+ const [query, setQuery] = useState("");
60
+ const [debouncedQuery, setDebouncedQuery] = useState("");
61
+ const [showDiffs, setShowDiffs] = useState(false);
62
+
63
+ useEffect(() => {
64
+ const id = setTimeout(
65
+ () => setDebouncedQuery(query.trim().toLowerCase()),
66
+ 150,
67
+ );
68
+ return () => clearTimeout(id);
69
+ }, [query]);
70
+
71
+ const eventTypes = useMemo(() => {
72
+ const types = new Set<string>();
73
+ logs.forEach((log) => types.add(log.event));
74
+ return Array.from(types).sort();
75
+ }, [logs]);
76
+
77
+ const eventTypesByScope = useMemo(() => {
78
+ const grouped = new Map<string, string[]>();
79
+ for (const type of eventTypes) {
80
+ const scope = eventScope(type);
81
+ const existing = grouped.get(scope);
82
+ if (existing) {
83
+ existing.push(type);
84
+ } else {
85
+ grouped.set(scope, [type]);
86
+ }
87
+ }
88
+ return Array.from(grouped.entries());
89
+ }, [eventTypes]);
90
+
91
+ useEffect(() => {
92
+ setUnselectedEventTypes((prev) => {
93
+ const eventTypeSet = new Set(eventTypes);
94
+ const next = new Set(prev);
95
+ let changed = false;
96
+
97
+ Array.from(next).forEach((value) => {
98
+ if (!eventTypeSet.has(value)) {
99
+ next.delete(value);
100
+ knownEventTypesRef.current.delete(value);
101
+ changed = true;
102
+ }
103
+ });
104
+
105
+ eventTypes.forEach((type) => {
106
+ if (!knownEventTypesRef.current.has(type)) {
107
+ knownEventTypesRef.current.add(type);
108
+ changed = true;
109
+ }
110
+ });
111
+
112
+ return changed ? next : prev;
113
+ });
114
+ }, [eventTypes]);
115
+
116
+ const filteredLogs = useMemo(
117
+ () =>
118
+ logs.filter(
119
+ (log) =>
120
+ !unselectedEventTypes.has(log.event) &&
121
+ (debouncedQuery === "" ||
122
+ `${log.event} ${JSON.stringify(log.data)}`
123
+ .toLowerCase()
124
+ .includes(debouncedQuery)),
125
+ ),
126
+ [logs, unselectedEventTypes, debouncedQuery],
127
+ );
128
+
129
+ const toggleEventType = useCallback((eventType: string) => {
130
+ setUnselectedEventTypes((prev) => {
131
+ const next = new Set(prev);
132
+ if (next.has(eventType)) {
133
+ next.delete(eventType);
134
+ } else {
135
+ next.add(eventType);
136
+ }
137
+ return next;
138
+ });
139
+ }, []);
140
+
141
+ const toggleScope = useCallback((types: string[]) => {
142
+ setUnselectedEventTypes((prev) => {
143
+ const allSelected = types.every((type) => !prev.has(type));
144
+ const next = new Set(prev);
145
+ for (const type of types) {
146
+ if (allSelected) {
147
+ next.add(type);
148
+ } else {
149
+ next.delete(type);
150
+ }
151
+ }
152
+ return next;
153
+ });
154
+ }, []);
155
+
156
+ return {
157
+ eventTypes,
158
+ eventTypesByScope,
159
+ filteredLogs,
160
+ query,
161
+ setQuery,
162
+ showDiffs,
163
+ setShowDiffs,
164
+ toggleEventType,
165
+ toggleScope,
166
+ unselectedEventTypes,
167
+ };
168
+ };
169
+
170
+ export const previousSameScope = (
171
+ logs: readonly EventLogEntry[],
172
+ index: number,
173
+ ): EventLogEntry | undefined => {
174
+ const scope = eventScope(logs[index]!.event);
175
+ for (let cursor = index - 1; cursor >= 0; cursor -= 1) {
176
+ if (eventScope(logs[cursor]!.event) === scope) return logs[cursor];
177
+ }
178
+ return undefined;
179
+ };
@@ -0,0 +1,10 @@
1
+ export {
2
+ buildActivityNav,
3
+ defaultActivitySelection,
4
+ findActivityNode,
5
+ } from "./activityNodes";
6
+ export type { ActivityNode } from "./activityNodes";
7
+ export { EventLogRow, ScopeFilterBar } from "./EventLogRow";
8
+ export { EventStreamPane } from "./EventStreamPane";
9
+ export { OrphansPane } from "./OrphansPane";
10
+ export { RunDetailPane } from "./RunDetailPane";