@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
@@ -1,183 +1,26 @@
1
1
  "use client";
2
2
 
3
- import { useEffect, useMemo, useState, useSyncExternalStore } from "react";
4
- import { DevToolsFrame } from "./DevToolsFrame";
5
- import { getStyles, ANIMATION_STYLES } from "./styles/DevToolsModal.styles";
6
-
7
- const isDarkMode = (): boolean => {
8
- if (typeof document === "undefined") return false;
9
- return (
10
- document.documentElement.classList.contains("dark") ||
11
- document.body.classList.contains("dark")
12
- );
13
- };
14
-
15
- const subscribeToThemeChanges = (callback: () => void) => {
16
- if (typeof MutationObserver === "undefined") {
17
- return () => {};
18
- }
19
-
20
- const observer = new MutationObserver(callback);
21
-
22
- observer.observe(document.documentElement, {
23
- attributes: true,
24
- attributeFilter: ["class"],
25
- });
26
-
27
- if (document.body !== document.documentElement) {
28
- observer.observe(document.body, {
29
- attributes: true,
30
- attributeFilter: ["class"],
31
- });
32
- }
33
-
34
- return () => observer.disconnect();
35
- };
36
-
37
- const DevToolsModalImpl = () => {
38
- const [isOpen, setIsOpen] = useState(false);
39
- const [buttonHover, setButtonHover] = useState(false);
40
- const [closeHover, setCloseHover] = useState(false);
41
-
42
- const darkMode = useSyncExternalStore(
43
- subscribeToThemeChanges,
44
- isDarkMode,
45
- () => false, // Server-side always returns false
46
- );
47
-
48
- const styles = useMemo(() => getStyles(darkMode), [darkMode]);
49
-
50
- useEffect(() => {
51
- if (typeof document === "undefined") return;
52
-
53
- const styleId = "devtools-modal-animations";
54
- if (!document.getElementById(styleId)) {
55
- const style = document.createElement("style");
56
- style.id = styleId;
57
- style.textContent = ANIMATION_STYLES;
58
- document.head.appendChild(style);
59
- }
60
-
61
- return () => {
62
- const style = document.getElementById(styleId);
63
- if (style && !document.querySelector("[data-devtools-modal]")) {
64
- style.remove();
65
- }
66
- };
67
- }, []);
68
-
69
- useEffect(() => {
70
- if (!isOpen) return;
71
-
72
- const handleEscape = (event: KeyboardEvent) => {
73
- if (event.key === "Escape") {
74
- setIsOpen(false);
75
- }
76
- };
77
-
78
- document.addEventListener("keydown", handleEscape);
79
- return () => document.removeEventListener("keydown", handleEscape);
80
- }, [isOpen]);
81
-
82
- return (
83
- <>
84
- <div style={styles.floatingContainer}>
85
- <button
86
- type="button"
87
- onClick={() => setIsOpen(true)}
88
- onMouseEnter={() => setButtonHover(true)}
89
- onMouseLeave={() => setButtonHover(false)}
90
- style={{
91
- ...styles.floatingButton,
92
- ...(buttonHover ? styles.floatingButtonHover : {}),
93
- }}
94
- aria-label="Open assistant-ui DevTools"
95
- title="Open assistant-ui DevTools"
96
- >
97
- <svg
98
- aria-hidden="true"
99
- width="20"
100
- height="20"
101
- viewBox="0 0 24 24"
102
- fill="none"
103
- xmlns="http://www.w3.org/2000/svg"
104
- style={{ width: "20px", height: "20px" }}
105
- >
106
- <path
107
- d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"
108
- stroke="currentColor"
109
- strokeWidth="1.8"
110
- strokeLinecap="round"
111
- strokeLinejoin="round"
112
- fill="none"
113
- />
114
- </svg>
115
- </button>
116
- </div>
117
-
118
- {isOpen && (
119
- <>
120
- <div style={styles.backdrop} onClick={() => setIsOpen(false)} />
121
-
122
- <div style={styles.modal} data-devtools-modal>
123
- <button
124
- type="button"
125
- onClick={() => setIsOpen(false)}
126
- onMouseEnter={() => setCloseHover(true)}
127
- onMouseLeave={() => setCloseHover(false)}
128
- style={{
129
- ...styles.dismissButton,
130
- ...(closeHover ? styles.dismissButtonHover : {}),
131
- }}
132
- aria-label="Close DevTools"
133
- >
134
- <svg
135
- aria-hidden="true"
136
- width="14"
137
- height="14"
138
- viewBox="0 0 24 24"
139
- fill="none"
140
- xmlns="http://www.w3.org/2000/svg"
141
- >
142
- <path
143
- d="M18 6L6 18"
144
- stroke="currentColor"
145
- strokeWidth="1.6"
146
- strokeLinecap="round"
147
- strokeLinejoin="round"
148
- />
149
- <path
150
- d="M6 6L18 18"
151
- stroke="currentColor"
152
- strokeWidth="1.6"
153
- strokeLinecap="round"
154
- strokeLinejoin="round"
155
- />
156
- </svg>
157
- </button>
158
-
159
- <div style={styles.modalContent}>
160
- <DevToolsFrame
161
- style={{
162
- width: "100%",
163
- height: "100%",
164
- border: "none",
165
- borderRadius: "12px",
166
- backgroundColor: "transparent",
167
- }}
168
- />
169
- </div>
170
- </div>
171
- </>
172
- )}
173
- </>
174
- );
175
- };
176
-
177
- // Export a component that only renders in development
178
- export const DevToolsModal = () => {
179
- // Check if we're in production - most bundlers will replace process.env.NODE_ENV
180
- // This allows the entire component to be eliminated via dead code elimination
3
+ import { lazy, Suspense } from "react";
4
+ import type { DevToolsPanelPlugin } from "./shell/registry";
5
+ import type { DevToolsClient } from "./data/types";
6
+
7
+ export interface DevToolsModalProps {
8
+ /** Extra inspector tabs appended after the builtins. */
9
+ plugins?: DevToolsPanelPlugin[];
10
+ /** Force a theme. Defaults to "system", which follows the host `.dark` class. */
11
+ theme?: "light" | "dark" | "system";
12
+ /** Data source. Defaults to the in-process DevToolsHooks client. */
13
+ client?: DevToolsClient;
14
+ }
15
+
16
+ const DevToolsModalImpl = lazy(() => import("./DevToolsModalImpl"));
17
+
18
+ /**
19
+ * Dev-only. In production the body returns null before the lazy panel chunk is
20
+ * ever requested, so the panel and its compiled styles stay out of the
21
+ * production bundle (the dynamic import is also code-split).
22
+ */
23
+ export const DevToolsModal = (props: DevToolsModalProps = {}) => {
181
24
  if (
182
25
  typeof process !== "undefined" &&
183
26
  process.env?.NODE_ENV === "production"
@@ -185,5 +28,9 @@ export const DevToolsModal = () => {
185
28
  return null;
186
29
  }
187
30
 
188
- return <DevToolsModalImpl />;
31
+ return (
32
+ <Suspense fallback={null}>
33
+ <DevToolsModalImpl {...props} />
34
+ </Suspense>
35
+ );
189
36
  };
@@ -0,0 +1,60 @@
1
+ "use client";
2
+
3
+ import { useMemo, useSyncExternalStore } from "react";
4
+ import { DevToolsOverlay } from "./shell/DevToolsOverlay";
5
+ import { ShadowRoot } from "./shell/ShadowRoot";
6
+ import type { DevToolsModalProps } from "./DevToolsModal";
7
+
8
+ const isDarkMode = (): boolean => {
9
+ if (typeof document === "undefined") return false;
10
+ return (
11
+ document.documentElement.classList.contains("dark") ||
12
+ document.body.classList.contains("dark")
13
+ );
14
+ };
15
+
16
+ const subscribeToThemeChanges = (callback: () => void) => {
17
+ if (typeof MutationObserver === "undefined") {
18
+ return () => {};
19
+ }
20
+
21
+ const observer = new MutationObserver(callback);
22
+ observer.observe(document.documentElement, {
23
+ attributes: true,
24
+ attributeFilter: ["class"],
25
+ });
26
+ if (document.body !== document.documentElement) {
27
+ observer.observe(document.body, {
28
+ attributes: true,
29
+ attributeFilter: ["class"],
30
+ });
31
+ }
32
+
33
+ return () => observer.disconnect();
34
+ };
35
+
36
+ const DevToolsModalImpl = ({
37
+ plugins,
38
+ theme = "system",
39
+ client,
40
+ }: DevToolsModalProps) => {
41
+ const darkMode = useSyncExternalStore(
42
+ subscribeToThemeChanges,
43
+ isDarkMode,
44
+ () => false,
45
+ );
46
+ const resolved = theme === "system" ? (darkMode ? "dark" : "light") : theme;
47
+
48
+ // Stable element identity so the shadow root only re-renders on real changes,
49
+ // not on every render of the host tree.
50
+ const overlay = useMemo(
51
+ () => (
52
+ <DevToolsOverlay theme={resolved} plugins={plugins} client={client} />
53
+ ),
54
+ [resolved, plugins, client],
55
+ );
56
+
57
+ return <ShadowRoot theme={resolved}>{overlay}</ShadowRoot>;
58
+ };
59
+
60
+ export default DevToolsModalImpl;
@@ -0,0 +1,66 @@
1
+ import { DevToolsHooks } from "@assistant-ui/react";
2
+ import { projectApi } from "./projectApi";
3
+ import {
4
+ EMPTY_SNAPSHOT,
5
+ type ApiInfo,
6
+ type DevToolsClient,
7
+ type DevToolsSnapshot,
8
+ } from "./types";
9
+
10
+ /**
11
+ * The default transport: reads the in-process DevToolsHooks registry and
12
+ * re-projects it on every change.
13
+ *
14
+ * Projection runs inside the subscribe/change callbacks (outside React render)
15
+ * because the scope accessors throw when invoked during a render, and
16
+ * getSnapshot returns the cached result.
17
+ */
18
+ export const createInProcessClient = (): DevToolsClient => {
19
+ let snapshot: DevToolsSnapshot = EMPTY_SNAPSHOT;
20
+
21
+ const rebuild = () => {
22
+ const apis = DevToolsHooks.getApis();
23
+ const byId = new Map<number, ApiInfo>();
24
+ for (const [id, entry] of apis) {
25
+ try {
26
+ byId.set(id, projectApi(id, entry));
27
+ } catch {
28
+ // Skip an api that fails to project rather than breaking the panel.
29
+ }
30
+ }
31
+ // apiIds tracks byId so the selector never lists an id without data.
32
+ snapshot = { apiIds: [...byId.keys()], byId };
33
+ };
34
+
35
+ return {
36
+ subscribe(listener) {
37
+ rebuild();
38
+ return DevToolsHooks.subscribe(() => {
39
+ rebuild();
40
+ listener();
41
+ });
42
+ },
43
+ getSnapshot: () => snapshot,
44
+ getServerSnapshot: () => EMPTY_SNAPSHOT,
45
+ clearEvents: (apiId) => DevToolsHooks.clearEventLogs(apiId),
46
+ switchToThread: (apiId, threadId) => {
47
+ const entry = DevToolsHooks.getApis().get(apiId);
48
+ const threads = entry?.api.threads;
49
+ if (!threads || typeof threads !== "function") return;
50
+ try {
51
+ const methods = threads() as {
52
+ switchToThread?: (id: string) => void | Promise<void>;
53
+ };
54
+ return Promise.resolve(methods.switchToThread?.(threadId)).catch(
55
+ () => {},
56
+ );
57
+ } catch {
58
+ // The thread scope can throw when the runtime is not ready; ignore.
59
+ return;
60
+ }
61
+ },
62
+ };
63
+ };
64
+
65
+ /** Shared default client used by DevToolsModal and DevToolsPanel. */
66
+ export const inProcessClient = createInProcessClient();
@@ -0,0 +1,100 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { projectApi } from "./projectApi";
3
+
4
+ type Scope = (() => unknown) & {
5
+ source: string | null;
6
+ query: Record<string, unknown> | null;
7
+ };
8
+
9
+ const scope = (
10
+ source: string | null,
11
+ query: Record<string, unknown> | null,
12
+ value: unknown,
13
+ ): Scope => {
14
+ const fn = (() => value) as Scope;
15
+ fn.source = source;
16
+ fn.query = query;
17
+ return fn;
18
+ };
19
+
20
+ describe("projectApi", () => {
21
+ const entry = {
22
+ api: {
23
+ thread: scope(
24
+ "root",
25
+ {},
26
+ {
27
+ getState: () => ({ messages: [], isRunning: false }),
28
+ append: () => {},
29
+ getModelContext: () => ({ system: "be nice", tools: [] }),
30
+ },
31
+ ),
32
+ composer: scope(
33
+ "root",
34
+ {},
35
+ {
36
+ getState: () => ({ text: "hello" }),
37
+ },
38
+ ),
39
+ message: scope(
40
+ "messages",
41
+ { index: 0 },
42
+ {
43
+ getState: () => ({}),
44
+ },
45
+ ),
46
+ },
47
+ logs: [{ time: new Date(0), event: "thread.run-start", data: { foo: 1 } }],
48
+ } as unknown as Parameters<typeof projectApi>[1];
49
+
50
+ const result = projectApi(7, entry);
51
+
52
+ it("carries the api id", () => {
53
+ expect(result.id).toBe(7);
54
+ });
55
+
56
+ it("collects root-scope state by scope name", () => {
57
+ expect(result.state.thread).toEqual({ messages: [], isRunning: false });
58
+ expect(result.state.composer).toEqual({ text: "hello" });
59
+ });
60
+
61
+ it("omits non-root scopes from state but keeps them in the scope graph", () => {
62
+ expect(result.state.message).toBeUndefined();
63
+ const scopes = result.scopes as Array<{
64
+ name: string;
65
+ source: string | null;
66
+ methods: string[];
67
+ }>;
68
+ const thread = scopes.find((s) => s.name === "thread");
69
+ expect(thread?.source).toBe("root");
70
+ expect(thread?.methods).toEqual(
71
+ expect.arrayContaining(["getState", "append", "getModelContext"]),
72
+ );
73
+ expect(scopes.find((s) => s.name === "message")?.source).toBe("messages");
74
+ });
75
+
76
+ it("normalizes the model context from the thread scope", () => {
77
+ expect(result.modelContext).toEqual({ system: "be nice" });
78
+ });
79
+
80
+ it("keeps event-log timestamps as Date instances", () => {
81
+ expect(result.logs[0]?.time).toBeInstanceOf(Date);
82
+ expect(result.logs[0]?.event).toBe("thread.run-start");
83
+ expect(result.logs[0]?.data).toEqual({ foo: 1 });
84
+ });
85
+
86
+ it("does not throw on scopes whose accessor throws", () => {
87
+ const broken = scope("root", {}, undefined);
88
+ const throwing = (() => {
89
+ throw new Error("not mounted");
90
+ }) as unknown as Scope;
91
+ throwing.source = "derived";
92
+ throwing.query = null;
93
+ const result = projectApi(1, {
94
+ api: { broken, throwing },
95
+ logs: [],
96
+ } as unknown as Parameters<typeof projectApi>[1]);
97
+ const scopes = result.scopes as Array<{ name: string }>;
98
+ expect(scopes.map((s) => s.name)).toEqual(["broken", "throwing"]);
99
+ });
100
+ });
@@ -0,0 +1,169 @@
1
+ import type { AssistantClient } from "@assistant-ui/react";
2
+ import { isRecord, isStringArray } from "../utils/common";
3
+ import {
4
+ sanitizeAndRedact,
5
+ sanitizeForMessage,
6
+ serializeModelContext,
7
+ } from "../utils/serialization";
8
+ import type { ApiInfo, EventLogEntry } from "./types";
9
+
10
+ interface DevToolsApiEntry {
11
+ api: Partial<AssistantClient>;
12
+ logs: ReadonlyArray<EventLogEntry>;
13
+ }
14
+
15
+ /**
16
+ * Lists the method names of a client proxy. The client proxy throws from its
17
+ * `getOwnPropertyDescriptor` trap, so `Object.keys` is best-effort and isolated
18
+ * from state extraction.
19
+ */
20
+ const readMethods = (scopeValue: unknown): string[] => {
21
+ if (!scopeValue || typeof scopeValue !== "object") return [];
22
+ try {
23
+ return Object.keys(scopeValue).filter(
24
+ (key) =>
25
+ typeof (scopeValue as Record<string, unknown>)[key] === "function",
26
+ );
27
+ } catch {
28
+ return [];
29
+ }
30
+ };
31
+
32
+ type ThreadsClientMethods = {
33
+ __internal_getAssistantRuntime?: () => {
34
+ threads: {
35
+ getById: (threadId: string) => {
36
+ getState: () => {
37
+ messages: unknown;
38
+ isRunning?: boolean;
39
+ isLoading?: boolean;
40
+ isDisabled?: boolean;
41
+ suggestions: unknown;
42
+ capabilities: unknown;
43
+ };
44
+ composer: { getState: () => unknown };
45
+ };
46
+ };
47
+ };
48
+ };
49
+
50
+ /**
51
+ * Reads cached thread states for every id in the thread list. Only threads whose
52
+ * runtime has been mounted (visited in the app) return data; unvisited threads
53
+ * are omitted so DevTools can still list them from `state.threads.threadItems`.
54
+ */
55
+ const collectThreadSnapshots = (
56
+ entry: DevToolsApiEntry,
57
+ state: Record<string, unknown>,
58
+ ): Record<string, unknown> | undefined => {
59
+ const threadsState = state.threads;
60
+ if (!isRecord(threadsState)) return undefined;
61
+
62
+ const threadsScope = entry.api.threads;
63
+ if (typeof threadsScope !== "function") return undefined;
64
+
65
+ let threadsClient: ThreadsClientMethods;
66
+ try {
67
+ threadsClient = threadsScope() as ThreadsClientMethods;
68
+ } catch {
69
+ return undefined;
70
+ }
71
+
72
+ const assistantRuntime = threadsClient.__internal_getAssistantRuntime?.();
73
+ if (!assistantRuntime) return undefined;
74
+
75
+ const threadIds = [
76
+ ...isStringArray(threadsState.threadIds),
77
+ ...isStringArray(threadsState.archivedThreadIds),
78
+ ];
79
+ if (threadIds.length === 0) return undefined;
80
+
81
+ const snapshots: Record<string, unknown> = {};
82
+ for (const threadId of threadIds) {
83
+ try {
84
+ const threadRuntime = assistantRuntime.threads.getById(threadId);
85
+ const threadState = threadRuntime.getState();
86
+ snapshots[threadId] = sanitizeForMessage({
87
+ messages: threadState.messages,
88
+ isRunning: threadState.isRunning,
89
+ isLoading: threadState.isLoading,
90
+ isDisabled: threadState.isDisabled,
91
+ suggestions: threadState.suggestions,
92
+ capabilities: threadState.capabilities,
93
+ composer: threadRuntime.composer.getState(),
94
+ });
95
+ } catch {
96
+ // Thread runtime not mounted yet (never opened in the app).
97
+ }
98
+ }
99
+
100
+ return Object.keys(snapshots).length > 0 ? snapshots : undefined;
101
+ };
102
+
103
+ /**
104
+ * Projects a live DevToolsHooks api entry into the plain, render-ready shape the
105
+ * views consume. This is the in-process equivalent of the old
106
+ * DevToolsHost.sendUpdate(): it walks the scope accessors for root-scope state
107
+ * and the scope graph, normalizes the model context, and redacts credentials.
108
+ *
109
+ * `state` and each `log.data` are passed through sanitizeForMessage so the JSON
110
+ * renderers cannot crash on circular references or non-serializable values;
111
+ * `log.time` is kept as a Date for the clock formatter.
112
+ */
113
+ export const projectApi = (apiId: number, entry: DevToolsApiEntry): ApiInfo => {
114
+ const state: Record<string, unknown> = {};
115
+ const scopes: Array<{
116
+ name: string;
117
+ source: string | null;
118
+ query: Record<string, unknown> | null;
119
+ methods: string[];
120
+ }> = [];
121
+
122
+ for (const [name, scope] of Object.entries(entry.api)) {
123
+ if (typeof scope !== "function" || !("source" in scope)) continue;
124
+
125
+ let methods: string[] = [];
126
+ try {
127
+ const scopeValue = scope();
128
+ if (scope.source === "root") {
129
+ state[name] = scopeValue?.getState?.() ?? scopeValue;
130
+ }
131
+ methods = readMethods(scopeValue);
132
+ } catch {
133
+ // scope() may throw for derived scopes before the client is mounted.
134
+ }
135
+
136
+ scopes.push({
137
+ name,
138
+ source: scope.source,
139
+ query: scope.query,
140
+ methods,
141
+ });
142
+ }
143
+
144
+ let modelContext: ApiInfo["modelContext"];
145
+ try {
146
+ modelContext = serializeModelContext(
147
+ entry.api.thread?.().getModelContext(),
148
+ );
149
+ } catch {
150
+ // A throwing thread()/getModelContext() should not drop the whole api;
151
+ // show partial data (state, scopes, logs) without the model context.
152
+ }
153
+
154
+ const sanitizedState = sanitizeForMessage(state) as Record<string, unknown>;
155
+ const threadSnapshots = collectThreadSnapshots(entry, sanitizedState);
156
+
157
+ return {
158
+ id: apiId,
159
+ state: sanitizedState,
160
+ logs: entry.logs.map((log) => ({
161
+ time: log.time,
162
+ event: log.event,
163
+ data: sanitizeForMessage(log.data),
164
+ })),
165
+ modelContext,
166
+ scopes: sanitizeAndRedact(scopes),
167
+ ...(threadSnapshots ? { threadSnapshots } : {}),
168
+ };
169
+ };
@@ -0,0 +1,54 @@
1
+ import type { SerializedModelContext } from "../types";
2
+
3
+ export type { SerializedModelContext } from "../types";
4
+
5
+ export interface EventLogEntry {
6
+ readonly time: Date;
7
+ readonly event: string;
8
+ readonly data: unknown;
9
+ }
10
+
11
+ export interface ApiInfo {
12
+ id: number;
13
+ state: Record<string, unknown>;
14
+ logs: EventLogEntry[];
15
+ modelContext?: SerializedModelContext | undefined;
16
+ scopes?: unknown;
17
+ /**
18
+ * Cached thread states keyed by thread id. Populated for threads whose runtime
19
+ * has been mounted (visited in the app). Unvisited threads only appear in
20
+ * `state.threads.threadItems`.
21
+ */
22
+ threadSnapshots?: Readonly<Record<string, unknown>>;
23
+ }
24
+
25
+ /**
26
+ * A JSON-safe view of every inspected instance. The map values are stable until
27
+ * the next change so it can be returned directly from useSyncExternalStore.
28
+ */
29
+ export interface DevToolsSnapshot {
30
+ apiIds: number[];
31
+ byId: ReadonlyMap<number, ApiInfo>;
32
+ }
33
+
34
+ /**
35
+ * The transport between the data source and the panel UI. The default
36
+ * implementation reads the in-process DevToolsHooks registry, but the panel only
37
+ * depends on this interface, so the same UI can be driven by a postMessage
38
+ * bridge, a browser-extension relay, a remote socket, or a fixture for tests.
39
+ */
40
+ export interface DevToolsClient {
41
+ /** Subscribe to snapshot changes; returns an unsubscribe. */
42
+ subscribe(listener: () => void): () => void;
43
+ /** The current snapshot. Must return a stable reference until it changes. */
44
+ getSnapshot(): DevToolsSnapshot;
45
+ /** Snapshot used during SSR/hydration. Defaults to an empty snapshot. */
46
+ getServerSnapshot?(): DevToolsSnapshot;
47
+ /** Clears the buffered event log for an instance. */
48
+ clearEvents(apiId: number): void;
49
+ /** Switches the inspected instance to a thread by id, when supported. */
50
+ switchToThread?(apiId: number, threadId: string): void | Promise<void>;
51
+ }
52
+
53
+ /** Shared stable empty snapshot identity for the empty/server state. */
54
+ export const EMPTY_SNAPSHOT: DevToolsSnapshot = { apiIds: [], byId: new Map() };