@agent-native/toolkit 0.228.0-nightly-20261111212500 → 0.228.0

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 (361) hide show
  1. package/agent-native.eject.json +2 -0
  2. package/dist/app/agentkit/react/approval-card.d.ts.map +1 -1
  3. package/dist/app/agentkit/react/approval-card.js +5 -3
  4. package/dist/app/agentkit/react/approval-card.js.map +1 -1
  5. package/dist/app/agentkit/react/code-block.d.ts +32 -0
  6. package/dist/app/agentkit/react/code-block.d.ts.map +1 -0
  7. package/dist/app/agentkit/react/code-block.js +125 -0
  8. package/dist/app/agentkit/react/code-block.js.map +1 -0
  9. package/dist/app/agentkit/react/components.d.ts +33 -14
  10. package/dist/app/agentkit/react/components.d.ts.map +1 -1
  11. package/dist/app/agentkit/react/components.js +843 -168
  12. package/dist/app/agentkit/react/components.js.map +1 -1
  13. package/dist/app/agentkit/react/context-usage.d.ts +45 -0
  14. package/dist/app/agentkit/react/context-usage.d.ts.map +1 -0
  15. package/dist/app/agentkit/react/context-usage.js +93 -0
  16. package/dist/app/agentkit/react/context-usage.js.map +1 -0
  17. package/dist/app/agentkit/react/context.d.ts +42 -3
  18. package/dist/app/agentkit/react/context.d.ts.map +1 -1
  19. package/dist/app/agentkit/react/context.js +46 -1
  20. package/dist/app/agentkit/react/context.js.map +1 -1
  21. package/dist/app/agentkit/react/disclosure-content.d.ts +12 -0
  22. package/dist/app/agentkit/react/disclosure-content.d.ts.map +1 -0
  23. package/dist/app/agentkit/react/disclosure-content.js +33 -0
  24. package/dist/app/agentkit/react/disclosure-content.js.map +1 -0
  25. package/dist/app/agentkit/react/duration.d.ts +6 -0
  26. package/dist/app/agentkit/react/duration.d.ts.map +1 -0
  27. package/dist/app/agentkit/react/duration.js +21 -0
  28. package/dist/app/agentkit/react/duration.js.map +1 -0
  29. package/dist/app/agentkit/react/file-change.d.ts +33 -0
  30. package/dist/app/agentkit/react/file-change.d.ts.map +1 -0
  31. package/dist/app/agentkit/react/file-change.js +83 -0
  32. package/dist/app/agentkit/react/file-change.js.map +1 -0
  33. package/dist/app/agentkit/react/file-diff.d.ts +17 -0
  34. package/dist/app/agentkit/react/file-diff.d.ts.map +1 -0
  35. package/dist/app/agentkit/react/file-diff.js +94 -0
  36. package/dist/app/agentkit/react/file-diff.js.map +1 -0
  37. package/dist/app/agentkit/react/index.d.ts +7 -0
  38. package/dist/app/agentkit/react/index.d.ts.map +1 -1
  39. package/dist/app/agentkit/react/index.js +7 -0
  40. package/dist/app/agentkit/react/index.js.map +1 -1
  41. package/dist/app/agentkit/react/question-card.d.ts +67 -0
  42. package/dist/app/agentkit/react/question-card.d.ts.map +1 -0
  43. package/dist/app/agentkit/react/question-card.js +198 -0
  44. package/dist/app/agentkit/react/question-card.js.map +1 -0
  45. package/dist/app/agentkit/react/root.d.ts +3 -2
  46. package/dist/app/agentkit/react/root.d.ts.map +1 -1
  47. package/dist/app/agentkit/react/root.js +2 -2
  48. package/dist/app/agentkit/react/root.js.map +1 -1
  49. package/dist/app/agentkit/react/roving-focus.d.ts +4 -0
  50. package/dist/app/agentkit/react/roving-focus.d.ts.map +1 -0
  51. package/dist/app/agentkit/react/roving-focus.js +75 -0
  52. package/dist/app/agentkit/react/roving-focus.js.map +1 -0
  53. package/dist/app/agentkit/react/stack-trace.d.ts +34 -0
  54. package/dist/app/agentkit/react/stack-trace.d.ts.map +1 -0
  55. package/dist/app/agentkit/react/stack-trace.js +121 -0
  56. package/dist/app/agentkit/react/stack-trace.js.map +1 -0
  57. package/dist/app/agentkit/react/stop-button.d.ts.map +1 -1
  58. package/dist/app/agentkit/react/stop-button.js +22 -6
  59. package/dist/app/agentkit/react/stop-button.js.map +1 -1
  60. package/dist/app/agentkit/react/styles.css +1306 -395
  61. package/dist/app/agentkit/react/terminal.d.ts +28 -0
  62. package/dist/app/agentkit/react/terminal.d.ts.map +1 -0
  63. package/dist/app/agentkit/react/terminal.js +84 -0
  64. package/dist/app/agentkit/react/terminal.js.map +1 -0
  65. package/dist/app/agentkit/react/trace.d.ts +31 -0
  66. package/dist/app/agentkit/react/trace.d.ts.map +1 -0
  67. package/dist/app/agentkit/react/trace.js +73 -0
  68. package/dist/app/agentkit/react/trace.js.map +1 -0
  69. package/dist/app/blocks/library/HighlightedCode.d.ts +2 -1
  70. package/dist/app/blocks/library/HighlightedCode.d.ts.map +1 -1
  71. package/dist/app/blocks/library/HighlightedCode.js +8 -111
  72. package/dist/app/blocks/library/HighlightedCode.js.map +1 -1
  73. package/dist/app/chat/AgentKitAssistantChat.d.ts.map +1 -1
  74. package/dist/app/chat/AgentKitAssistantChat.js +23 -245
  75. package/dist/app/chat/AgentKitAssistantChat.js.map +1 -1
  76. package/dist/app/chat/agentkit-chat/guided-questions.d.ts +15 -1
  77. package/dist/app/chat/agentkit-chat/guided-questions.d.ts.map +1 -1
  78. package/dist/app/chat/agentkit-chat/guided-questions.js +142 -2
  79. package/dist/app/chat/agentkit-chat/guided-questions.js.map +1 -1
  80. package/dist/app/chat/agentkit-chat/history.js +1 -1
  81. package/dist/app/chat/agentkit-chat/history.js.map +1 -1
  82. package/dist/app/chat/agentkit-chat/index.d.ts +1 -1
  83. package/dist/app/chat/agentkit-chat/index.d.ts.map +1 -1
  84. package/dist/app/chat/agentkit-chat/index.js +1 -1
  85. package/dist/app/chat/agentkit-chat/index.js.map +1 -1
  86. package/dist/app/chat/agentkit-chat/labels.d.ts +5 -0
  87. package/dist/app/chat/agentkit-chat/labels.d.ts.map +1 -0
  88. package/dist/app/chat/agentkit-chat/labels.js +245 -0
  89. package/dist/app/chat/agentkit-chat/labels.js.map +1 -0
  90. package/dist/app/chat/agentkit-chat/questions.d.ts +1 -1
  91. package/dist/app/chat/agentkit-chat/questions.d.ts.map +1 -1
  92. package/dist/app/chat/agentkit-chat/questions.js +1 -1
  93. package/dist/app/chat/agentkit-chat/questions.js.map +1 -1
  94. package/dist/app/chat/agentkit-chat/root.d.ts.map +1 -1
  95. package/dist/app/chat/agentkit-chat/root.js +5 -64
  96. package/dist/app/chat/agentkit-chat/root.js.map +1 -1
  97. package/dist/app/chat/agentkit-chat/work-step-labels.d.ts +2 -0
  98. package/dist/app/chat/agentkit-chat/work-step-labels.d.ts.map +1 -1
  99. package/dist/app/chat/agentkit-chat/work-step-labels.js +31 -0
  100. package/dist/app/chat/agentkit-chat/work-step-labels.js.map +1 -1
  101. package/dist/app/chat/chat/markdown-renderer.d.ts +2 -12
  102. package/dist/app/chat/chat/markdown-renderer.d.ts.map +1 -1
  103. package/dist/app/chat/chat/markdown-renderer.js +2 -41
  104. package/dist/app/chat/chat/markdown-renderer.js.map +1 -1
  105. package/dist/app/chat/chat/tool-call-display.d.ts.map +1 -1
  106. package/dist/app/chat/chat/tool-call-display.js +2 -2
  107. package/dist/app/chat/chat/tool-call-display.js.map +1 -1
  108. package/dist/app/chat/conversation/AgentConversation.d.ts.map +1 -1
  109. package/dist/app/chat/conversation/AgentConversation.js +2 -37
  110. package/dist/app/chat/conversation/AgentConversation.js.map +1 -1
  111. package/dist/app/chat/tool-cells/BashCell.d.ts +3 -1
  112. package/dist/app/chat/tool-cells/BashCell.d.ts.map +1 -1
  113. package/dist/app/chat/tool-cells/BashCell.js +4 -40
  114. package/dist/app/chat/tool-cells/BashCell.js.map +1 -1
  115. package/dist/app/chat/tool-cells/EditCell.d.ts.map +1 -1
  116. package/dist/app/chat/tool-cells/EditCell.js +5 -108
  117. package/dist/app/chat/tool-cells/EditCell.js.map +1 -1
  118. package/dist/app/chat/tool-cells/FilesChangedSummary.d.ts.map +1 -1
  119. package/dist/app/chat/tool-cells/FilesChangedSummary.js +23 -81
  120. package/dist/app/chat/tool-cells/FilesChangedSummary.js.map +1 -1
  121. package/dist/app/chat/tool-cells/WriteCell.d.ts.map +1 -1
  122. package/dist/app/chat/tool-cells/WriteCell.js +5 -24
  123. package/dist/app/chat/tool-cells/WriteCell.js.map +1 -1
  124. package/dist/app/code-highlighter.d.ts +11 -0
  125. package/dist/app/code-highlighter.d.ts.map +1 -0
  126. package/dist/app/code-highlighter.js +122 -0
  127. package/dist/app/code-highlighter.js.map +1 -0
  128. package/dist/app/context-xray/ThreadContextRing.js +3 -3
  129. package/dist/app/context-xray/ThreadContextRing.js.map +1 -1
  130. package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
  131. package/dist/app/i18n/catalogs/ar-SA.js +22 -0
  132. package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
  133. package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
  134. package/dist/app/i18n/catalogs/de-DE.js +22 -0
  135. package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
  136. package/dist/app/i18n/catalogs/en-US.d.ts +22 -0
  137. package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
  138. package/dist/app/i18n/catalogs/en-US.js +22 -0
  139. package/dist/app/i18n/catalogs/en-US.js.map +1 -1
  140. package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
  141. package/dist/app/i18n/catalogs/es-ES.js +22 -0
  142. package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
  143. package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
  144. package/dist/app/i18n/catalogs/fr-FR.js +22 -0
  145. package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
  146. package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
  147. package/dist/app/i18n/catalogs/hi-IN.js +22 -0
  148. package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
  149. package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
  150. package/dist/app/i18n/catalogs/ja-JP.js +22 -0
  151. package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
  152. package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
  153. package/dist/app/i18n/catalogs/ko-KR.js +22 -0
  154. package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
  155. package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
  156. package/dist/app/i18n/catalogs/pt-BR.js +22 -0
  157. package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
  158. package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
  159. package/dist/app/i18n/catalogs/zh-CN.js +22 -0
  160. package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
  161. package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
  162. package/dist/app/i18n/catalogs/zh-TW.js +22 -0
  163. package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
  164. package/dist/app/onboarding/first-run-first-paint.d.ts +10 -0
  165. package/dist/app/onboarding/first-run-first-paint.d.ts.map +1 -0
  166. package/dist/app/onboarding/first-run-first-paint.js +22 -0
  167. package/dist/app/onboarding/first-run-first-paint.js.map +1 -0
  168. package/dist/app/onboarding/first-run-startup-gate.d.ts +3 -1
  169. package/dist/app/onboarding/first-run-startup-gate.d.ts.map +1 -1
  170. package/dist/app/onboarding/first-run-startup-gate.js +30 -6
  171. package/dist/app/onboarding/first-run-startup-gate.js.map +1 -1
  172. package/dist/app/providers/AppProviders.d.ts.map +1 -1
  173. package/dist/app/providers/AppProviders.js +9 -2
  174. package/dist/app/providers/AppProviders.js.map +1 -1
  175. package/dist/app/providers/BuilderSignupActivation.d.ts +2 -1
  176. package/dist/app/providers/BuilderSignupActivation.d.ts.map +1 -1
  177. package/dist/app/providers/BuilderSignupActivation.js +6 -3
  178. package/dist/app/providers/BuilderSignupActivation.js.map +1 -1
  179. package/dist/app/shared/AppShellSkeleton.d.ts.map +1 -1
  180. package/dist/app/shared/AppShellSkeleton.js +11 -1
  181. package/dist/app/shared/AppShellSkeleton.js.map +1 -1
  182. package/dist/app/styles/agent-native.css +2 -2
  183. package/dist/app/styles/tokens/agent-kit.css +20 -3
  184. package/dist/composer/AgentSuggestionBar.d.ts.map +1 -1
  185. package/dist/composer/AgentSuggestionBar.js +2 -2
  186. package/dist/composer/AgentSuggestionBar.js.map +1 -1
  187. package/dist/composer/ComposerContextMenu.js +4 -4
  188. package/dist/composer/ComposerContextMenu.js.map +1 -1
  189. package/dist/composer/ComposerContextPicker.d.ts.map +1 -1
  190. package/dist/composer/ComposerContextPicker.js +2 -2
  191. package/dist/composer/ComposerContextPicker.js.map +1 -1
  192. package/dist/composer/ComposerContextPickerDialog.d.ts.map +1 -1
  193. package/dist/composer/ComposerContextPickerDialog.js +2 -2
  194. package/dist/composer/ComposerContextPickerDialog.js.map +1 -1
  195. package/dist/composer/ComposerModePicker.d.ts.map +1 -1
  196. package/dist/composer/ComposerModePicker.js +2 -1
  197. package/dist/composer/ComposerModePicker.js.map +1 -1
  198. package/dist/composer/ComposerPlusMenu.js +1 -1
  199. package/dist/composer/ComposerPlusMenu.js.map +1 -1
  200. package/dist/composer/MentionChip.js +1 -1
  201. package/dist/composer/MentionChip.js.map +1 -1
  202. package/dist/composer/MentionPopover.d.ts +3 -0
  203. package/dist/composer/MentionPopover.d.ts.map +1 -1
  204. package/dist/composer/MentionPopover.js +34 -15
  205. package/dist/composer/MentionPopover.js.map +1 -1
  206. package/dist/composer/MessageQueueDrawer.d.ts.map +1 -1
  207. package/dist/composer/MessageQueueDrawer.js +14 -9
  208. package/dist/composer/MessageQueueDrawer.js.map +1 -1
  209. package/dist/composer/PastedTextChip.d.ts.map +1 -1
  210. package/dist/composer/PastedTextChip.js +14 -18
  211. package/dist/composer/PastedTextChip.js.map +1 -1
  212. package/dist/composer/PromptBar.js +1 -1
  213. package/dist/composer/PromptBar.js.map +1 -1
  214. package/dist/composer/PromptComposer.d.ts.map +1 -1
  215. package/dist/composer/PromptComposer.js +11 -9
  216. package/dist/composer/PromptComposer.js.map +1 -1
  217. package/dist/composer/RealtimeVoiceMode.js +2 -2
  218. package/dist/composer/RealtimeVoiceMode.js.map +1 -1
  219. package/dist/composer/TiptapComposer.d.ts.map +1 -1
  220. package/dist/composer/TiptapComposer.js +52 -89
  221. package/dist/composer/TiptapComposer.js.map +1 -1
  222. package/dist/composer/VoiceButton.d.ts +3 -1
  223. package/dist/composer/VoiceButton.d.ts.map +1 -1
  224. package/dist/composer/VoiceButton.js +10 -8
  225. package/dist/composer/VoiceButton.js.map +1 -1
  226. package/dist/composer/composer-notice.js +3 -3
  227. package/dist/composer/composer-notice.js.map +1 -1
  228. package/dist/composer/extensions/FileReference.js +1 -1
  229. package/dist/composer/extensions/FileReference.js.map +1 -1
  230. package/dist/composer/extensions/SkillReference.js +1 -1
  231. package/dist/composer/extensions/SkillReference.js.map +1 -1
  232. package/dist/composer/popover-surface.d.ts +1 -1
  233. package/dist/composer/popover-surface.d.ts.map +1 -1
  234. package/dist/composer/popover-surface.js +1 -1
  235. package/dist/composer/popover-surface.js.map +1 -1
  236. package/dist/context-ui/ContextUsageRing.d.ts +1 -45
  237. package/dist/context-ui/ContextUsageRing.d.ts.map +1 -1
  238. package/dist/context-ui/ContextUsageRing.js +2 -87
  239. package/dist/context-ui/ContextUsageRing.js.map +1 -1
  240. package/dist/context-ui/index.d.ts +2 -2
  241. package/dist/context-ui/index.d.ts.map +1 -1
  242. package/dist/context-ui/index.js +2 -2
  243. package/dist/context-ui/index.js.map +1 -1
  244. package/package.json +4 -4
  245. package/src/app/agentkit/react/approval-card.tsx +14 -2
  246. package/src/app/agentkit/react/code-block.spec.tsx +154 -0
  247. package/src/app/agentkit/react/code-block.tsx +317 -0
  248. package/src/app/agentkit/react/components.interaction.spec.tsx +7 -0
  249. package/src/app/agentkit/react/components.papercuts.spec.tsx +143 -2
  250. package/src/app/agentkit/react/components.spec.tsx +40 -47
  251. package/src/app/agentkit/react/components.tsx +1533 -413
  252. package/src/app/agentkit/react/composer-context.spec.tsx +35 -0
  253. package/src/app/agentkit/react/context-usage.tsx +353 -0
  254. package/src/app/agentkit/react/context.tsx +93 -1
  255. package/src/app/agentkit/react/disclosure-content.ts +42 -0
  256. package/src/app/agentkit/react/disclosures.spec.tsx +62 -4
  257. package/src/app/agentkit/react/duration.ts +22 -0
  258. package/src/app/agentkit/react/file-change.spec.tsx +124 -0
  259. package/src/app/agentkit/react/file-change.tsx +228 -0
  260. package/src/app/agentkit/react/file-diff.ts +110 -0
  261. package/src/app/agentkit/react/index.ts +7 -0
  262. package/src/app/agentkit/react/lifecycle.spec.tsx +565 -20
  263. package/src/app/agentkit/react/markdown.spec.tsx +18 -8
  264. package/src/app/agentkit/react/message-actions.spec.tsx +55 -1
  265. package/src/app/agentkit/react/notices.spec.tsx +4 -4
  266. package/src/app/agentkit/react/optimistic-send.spec.tsx +43 -0
  267. package/src/app/agentkit/react/question-card.spec.tsx +276 -0
  268. package/src/app/agentkit/react/question-card.tsx +533 -0
  269. package/src/app/agentkit/react/root.tsx +4 -0
  270. package/src/app/agentkit/react/roving-focus.spec.tsx +114 -0
  271. package/src/app/agentkit/react/roving-focus.ts +82 -0
  272. package/src/app/agentkit/react/stack-trace.spec.tsx +177 -0
  273. package/src/app/agentkit/react/stack-trace.tsx +281 -0
  274. package/src/app/agentkit/react/stop-button.spec.tsx +40 -0
  275. package/src/app/agentkit/react/stop-button.tsx +22 -5
  276. package/src/app/agentkit/react/styles.css +1306 -395
  277. package/src/app/agentkit/react/subagent-step.spec.tsx +554 -0
  278. package/src/app/agentkit/react/terminal.spec.tsx +228 -0
  279. package/src/app/agentkit/react/terminal.tsx +228 -0
  280. package/src/app/agentkit/react/trace.spec.tsx +120 -0
  281. package/src/app/agentkit/react/trace.tsx +239 -0
  282. package/src/app/blocks/library/HighlightedCode.tsx +14 -126
  283. package/src/app/chat/AgentKitAssistantChat.spec.tsx +28 -12
  284. package/src/app/chat/AgentKitAssistantChat.tsx +27 -253
  285. package/src/app/chat/agentkit-chat/approval-card.spec.tsx +1 -0
  286. package/src/app/chat/agentkit-chat/guided-questions.flow.spec.tsx +381 -0
  287. package/src/app/chat/agentkit-chat/guided-questions.tsx +236 -3
  288. package/src/app/chat/agentkit-chat/history.tsx +1 -1
  289. package/src/app/chat/agentkit-chat/index.ts +2 -0
  290. package/src/app/chat/agentkit-chat/labels.ts +259 -0
  291. package/src/app/chat/agentkit-chat/questions.ts +2 -0
  292. package/src/app/chat/agentkit-chat/root.spec.tsx +18 -0
  293. package/src/app/chat/agentkit-chat/root.tsx +5 -64
  294. package/src/app/chat/agentkit-chat/work-step-labels.ts +42 -0
  295. package/src/app/chat/chat/markdown-renderer.tsx +2 -59
  296. package/src/app/chat/chat/tool-call-display.spec.tsx +26 -14
  297. package/src/app/chat/chat/tool-call-display.tsx +2 -1
  298. package/src/app/chat/conversation/AgentConversation.tsx +2 -50
  299. package/src/app/chat/tool-cells/BashCell.tsx +14 -136
  300. package/src/app/chat/tool-cells/EditCell.tsx +11 -248
  301. package/src/app/chat/tool-cells/FilesChangedSummary.spec.tsx +62 -5
  302. package/src/app/chat/tool-cells/FilesChangedSummary.tsx +31 -162
  303. package/src/app/chat/tool-cells/WriteCell.tsx +11 -121
  304. package/src/app/code-highlighter.ts +131 -0
  305. package/src/app/context-xray/ThreadContextRing.tsx +7 -7
  306. package/src/app/i18n/catalogs/ar-SA.ts +22 -0
  307. package/src/app/i18n/catalogs/de-DE.ts +22 -0
  308. package/src/app/i18n/catalogs/en-US.ts +22 -0
  309. package/src/app/i18n/catalogs/es-ES.ts +22 -0
  310. package/src/app/i18n/catalogs/fr-FR.ts +22 -0
  311. package/src/app/i18n/catalogs/hi-IN.ts +22 -0
  312. package/src/app/i18n/catalogs/ja-JP.ts +22 -0
  313. package/src/app/i18n/catalogs/ko-KR.ts +22 -0
  314. package/src/app/i18n/catalogs/pt-BR.ts +22 -0
  315. package/src/app/i18n/catalogs/zh-CN.ts +22 -0
  316. package/src/app/i18n/catalogs/zh-TW.ts +22 -0
  317. package/src/app/onboarding/first-run-first-paint.spec.ts +39 -0
  318. package/src/app/onboarding/first-run-first-paint.ts +24 -0
  319. package/src/app/onboarding/first-run-startup-gate.spec.tsx +125 -13
  320. package/src/app/onboarding/first-run-startup-gate.tsx +48 -5
  321. package/src/app/providers/AppProviders.tsx +18 -0
  322. package/src/app/providers/BuilderSignupActivation.tsx +8 -2
  323. package/src/app/shared/AppShellSkeleton.spec.tsx +60 -1
  324. package/src/app/shared/AppShellSkeleton.tsx +31 -1
  325. package/src/app/styles/agent-native.css +2 -2
  326. package/src/app/styles/agent-native.spec.ts +2 -2
  327. package/src/app/styles/tokens/agent-kit.css +20 -3
  328. package/src/composer/AgentSuggestionBar.spec.tsx +3 -1
  329. package/src/composer/AgentSuggestionBar.tsx +5 -2
  330. package/src/composer/ComposerContextMenu.tsx +4 -4
  331. package/src/composer/ComposerContextPicker.tsx +8 -2
  332. package/src/composer/ComposerContextPickerDialog.tsx +5 -2
  333. package/src/composer/ComposerModePicker.tsx +2 -1
  334. package/src/composer/ComposerPlusMenu.tsx +1 -1
  335. package/src/composer/MentionChip.tsx +1 -1
  336. package/src/composer/MentionPopover.spec.tsx +108 -2
  337. package/src/composer/MentionPopover.tsx +93 -17
  338. package/src/composer/MessageQueueDrawer.spec.tsx +5 -5
  339. package/src/composer/MessageQueueDrawer.tsx +19 -12
  340. package/src/composer/PastedTextChip.spec.tsx +36 -0
  341. package/src/composer/PastedTextChip.tsx +52 -58
  342. package/src/composer/PromptBar.tsx +1 -1
  343. package/src/composer/PromptComposer.context.spec.tsx +2 -2
  344. package/src/composer/PromptComposer.submission.spec.tsx +27 -0
  345. package/src/composer/PromptComposer.tsx +17 -9
  346. package/src/composer/RealtimeVoiceMode.tsx +2 -2
  347. package/src/composer/TiptapComposer.model-picker.spec.tsx +23 -82
  348. package/src/composer/TiptapComposer.tsx +68 -145
  349. package/src/composer/VoiceButton.tsx +12 -7
  350. package/src/composer/composer-notice.tsx +3 -3
  351. package/src/composer/extensions/FileReference.tsx +1 -1
  352. package/src/composer/extensions/SkillReference.tsx +1 -1
  353. package/src/composer/popover-surface.ts +1 -1
  354. package/src/context-ui/ContextUsageRing.spec.tsx +33 -8
  355. package/src/context-ui/ContextUsageRing.tsx +13 -348
  356. package/src/context-ui/index.ts +7 -1
  357. package/dist/composer/ModelPickerParts.d.ts +0 -20
  358. package/dist/composer/ModelPickerParts.d.ts.map +0 -1
  359. package/dist/composer/ModelPickerParts.js +0 -77
  360. package/dist/composer/ModelPickerParts.js.map +0 -1
  361. package/src/composer/ModelPickerParts.tsx +0 -188
@@ -0,0 +1,228 @@
1
+ // @vitest-environment happy-dom
2
+
3
+ import { act, type ReactNode } from "react";
4
+ import { createRoot, type Root } from "react-dom/client";
5
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
6
+
7
+ import { Terminal, TerminalOutput } from "./terminal.js";
8
+
9
+ let root: Root;
10
+ let container: HTMLDivElement;
11
+
12
+ beforeEach(() => {
13
+ vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
14
+ container = document.createElement("div");
15
+ document.body.append(container);
16
+ root = createRoot(container);
17
+ });
18
+
19
+ afterEach(() => {
20
+ act(() => root.unmount());
21
+ container.remove();
22
+ vi.unstubAllGlobals();
23
+ });
24
+
25
+ async function render(node: ReactNode) {
26
+ await act(async () => root.render(node));
27
+ }
28
+
29
+ const trigger = () =>
30
+ container.querySelector<HTMLButtonElement>(
31
+ "button.agentkit-disclosure-summary",
32
+ );
33
+ const status = () =>
34
+ container
35
+ .querySelector('[data-slot="trace-line"]')
36
+ ?.getAttribute("data-trace-status");
37
+
38
+ describe("Terminal", () => {
39
+ it("shows a command with no output yet as a static running step", async () => {
40
+ await render(<Terminal command="pnpm build" running />);
41
+ expect(trigger()).toBeNull();
42
+ expect(container.querySelector(".agentkit-trace-title")?.textContent).toBe(
43
+ "pnpm build",
44
+ );
45
+ expect(status()).toBe("running");
46
+ });
47
+
48
+ it("masks closed output in fresh nodes, so replay never keeps it", async () => {
49
+ await render(
50
+ <Terminal command="pnpm build" output={"token=abc\n"} exitCode={0} />,
51
+ );
52
+ const output = () =>
53
+ document.querySelector(".agentkit-terminal-body [data-an-mask]");
54
+ expect(
55
+ document.querySelector(".agentkit-terminal-body")?.textContent,
56
+ ).toContain("token=abc");
57
+ expect(output()).not.toBeNull();
58
+
59
+ await act(async () =>
60
+ document
61
+ .querySelector<HTMLButtonElement>(".agentkit-disclosure-summary")
62
+ ?.click(),
63
+ );
64
+ const opened = document.querySelector(".agentkit-terminal-body");
65
+ expect(output()).toBeNull();
66
+
67
+ await act(async () =>
68
+ document
69
+ .querySelector<HTMLButtonElement>(".agentkit-disclosure-summary")
70
+ ?.click(),
71
+ );
72
+ // Closing replaces the node instead of masking the one replay recorded.
73
+ expect(opened?.isConnected).toBe(false);
74
+ expect(output()).not.toBeNull();
75
+ });
76
+
77
+ it("opens when output starts streaming and marks a nonzero exit failed", async () => {
78
+ await render(<Terminal command="pnpm test" running output="" />);
79
+ await render(
80
+ <Terminal command="pnpm test" running output={"1 passed\n"} />,
81
+ );
82
+ expect(trigger()?.getAttribute("aria-expanded")).toBe("true");
83
+ expect(container.querySelector("pre")?.textContent).toBe("1 passed");
84
+
85
+ await render(
86
+ <Terminal
87
+ command="pnpm test"
88
+ output={"1 passed\n1 failed\n"}
89
+ exitCode={1}
90
+ durationMs={4_200}
91
+ />,
92
+ );
93
+ expect(status()).toBe("error");
94
+ expect(
95
+ container.querySelector(".agentkit-trace-description")?.textContent,
96
+ ).toBe("4s · Exit code 1");
97
+ // Finishing never closes what streaming opened.
98
+ expect(trigger()?.getAttribute("aria-expanded")).toBe("true");
99
+ });
100
+
101
+ it("stays closed once the user closes it, while output keeps streaming", async () => {
102
+ await render(<Terminal command="pnpm dev" running output={"ready\n"} />);
103
+ await act(async () => trigger()?.click());
104
+ expect(trigger()?.getAttribute("aria-expanded")).toBe("false");
105
+ await render(
106
+ <Terminal command="pnpm dev" running output={"ready\nrebuilt\n"} />,
107
+ );
108
+ expect(trigger()?.getAttribute("aria-expanded")).toBe("false");
109
+ });
110
+
111
+ it("shows the newest lines first and reveals the earlier ones", async () => {
112
+ const output = Array.from(
113
+ { length: 8 },
114
+ (_, index) => `line ${index + 1}`,
115
+ ).join("\n");
116
+ await render(
117
+ <Terminal command="seq 8" output={output} maxLines={3} defaultOpen />,
118
+ );
119
+ expect(trigger()?.getAttribute("aria-expanded")).toBe("true");
120
+ const pre = () => container.querySelector("pre")?.textContent;
121
+ expect(pre()).toBe("line 6\nline 7\nline 8");
122
+ const earlier = container.querySelector<HTMLButtonElement>(
123
+ ".agentkit-terminal-earlier",
124
+ );
125
+ expect(earlier?.textContent).toBe("Show 5 earlier lines");
126
+ await act(async () => earlier?.click());
127
+ expect(pre()).toBe(output);
128
+
129
+ // The body remounts on each toggle; the revealed lines stay revealed.
130
+ await act(async () => trigger()?.click());
131
+ await act(async () => trigger()?.click());
132
+ expect(pre()).toBe(output);
133
+ });
134
+
135
+ it("reveals earlier lines when given showAll without onShowAll", async () => {
136
+ const output = ["one", "two", "three"].join("\n");
137
+ await render(
138
+ <TerminalOutput output={output} maxLines={1} showAll={false} />,
139
+ );
140
+ await act(async () =>
141
+ container
142
+ .querySelector<HTMLButtonElement>(".agentkit-terminal-earlier")
143
+ ?.click(),
144
+ );
145
+ expect(container.querySelector("pre")?.textContent).toBe(output);
146
+ });
147
+
148
+ it("shows every line for showAll and reports a reveal to onShowAll", async () => {
149
+ const output = ["one", "two", "three"].join("\n");
150
+ const pre = () => container.querySelector("pre")?.textContent;
151
+ await render(<TerminalOutput output={output} maxLines={1} showAll />);
152
+ expect(pre()).toBe(output);
153
+
154
+ const onShowAll = vi.fn();
155
+ await render(
156
+ <TerminalOutput
157
+ key="callback-only"
158
+ output={output}
159
+ maxLines={1}
160
+ onShowAll={onShowAll}
161
+ />,
162
+ );
163
+ expect(pre()).toBe("three");
164
+ await act(async () =>
165
+ container
166
+ .querySelector<HTMLButtonElement>(".agentkit-terminal-earlier")
167
+ ?.click(),
168
+ );
169
+ expect(pre()).toBe(output);
170
+ expect(onShowAll).toHaveBeenCalledTimes(1);
171
+ });
172
+
173
+ it("leaves showAll to the host when it also passes onShowAll", async () => {
174
+ const output = ["one", "two", "three"].join("\n");
175
+ const pre = () => container.querySelector("pre")?.textContent;
176
+ const onShowAll = vi.fn();
177
+ const renderWith = (showAll: boolean) =>
178
+ render(
179
+ <TerminalOutput
180
+ output={output}
181
+ maxLines={1}
182
+ showAll={showAll}
183
+ onShowAll={onShowAll}
184
+ />,
185
+ );
186
+ await renderWith(false);
187
+ await act(async () =>
188
+ container
189
+ .querySelector<HTMLButtonElement>(".agentkit-terminal-earlier")
190
+ ?.click(),
191
+ );
192
+ expect(onShowAll).toHaveBeenCalledTimes(1);
193
+ expect(pre()).toBe("three");
194
+ await renderWith(true);
195
+ expect(pre()).toBe(output);
196
+ await renderWith(false);
197
+ expect(pre()).toBe("three");
198
+ });
199
+
200
+ it("copies the whole output without color codes", async () => {
201
+ const writeText = vi.fn(async () => undefined);
202
+ vi.stubGlobal("navigator", { ...navigator, clipboard: { writeText } });
203
+ await render(
204
+ <Terminal
205
+ command="pnpm lint"
206
+ output={"\u001b[31merror\u001b[0m in a.ts"}
207
+ exitCode={1}
208
+ />,
209
+ );
210
+ const copy = container.querySelector<HTMLButtonElement>(
211
+ ".agentkit-terminal-actions button",
212
+ );
213
+ expect(copy?.getAttribute("aria-label")).toBe("Copy output");
214
+ await act(async () => {
215
+ copy?.click();
216
+ await Promise.resolve();
217
+ await Promise.resolve();
218
+ });
219
+ expect(writeText).toHaveBeenCalledWith("error in a.ts");
220
+ });
221
+
222
+ it("marks a call that failed apart from its exit code", async () => {
223
+ await render(
224
+ <Terminal command="rm -rf /" output="Error: command blocked" failed />,
225
+ );
226
+ expect(status()).toBe("error");
227
+ });
228
+ });
@@ -0,0 +1,228 @@
1
+ import { IconAlertTriangle, IconTerminal2 } from "@tabler/icons-react";
2
+ import { useEffect, useRef, useState } from "react";
3
+
4
+ import {
5
+ CodeBlock,
6
+ CodeBlockContent,
7
+ CodeBlockCopyButton,
8
+ CodeBlockHeader,
9
+ } from "./code-block.js";
10
+ import { useAgentKitDurationFormat, useAgentKitLabels } from "./context.js";
11
+ import {
12
+ Trace,
13
+ TraceCollapsible,
14
+ TraceCollapsibleContent,
15
+ TraceCollapsibleTrigger,
16
+ TraceDescription,
17
+ TraceIcon,
18
+ TraceLine,
19
+ TraceTitle,
20
+ type TraceCollapsibleOpenProps,
21
+ } from "./trace.js";
22
+
23
+ // A global regex's `test` keeps state between calls, so `HAS_ANSI` is separate.
24
+ const ANSI_SEQUENCE = /\u001b\[[0-9;]*m/g;
25
+ const HAS_ANSI = /\u001b\[[0-9;]*m/;
26
+
27
+ const DEFAULT_MAX_LINES = 500;
28
+ const SESSION_REPLAY_MASK_PROPS = { "data-an-mask": "" } as const;
29
+ const FOLLOW_SLACK_PX = 24;
30
+
31
+ /** Copy sits beside the trigger: a button cannot nest in the trigger. */
32
+ export function Terminal({
33
+ command,
34
+ output,
35
+ running = false,
36
+ exitCode,
37
+ durationMs,
38
+ timedOut = false,
39
+ failed: failedOverride,
40
+ defaultOpen = false,
41
+ maxLines = DEFAULT_MAX_LINES,
42
+ className,
43
+ ...openProps
44
+ }: TraceCollapsibleOpenProps & {
45
+ command: string;
46
+ /** May hold ANSI color codes. */
47
+ output?: string | undefined;
48
+ running?: boolean;
49
+ exitCode?: number | null | undefined;
50
+ durationMs?: number | undefined;
51
+ timedOut?: boolean | undefined;
52
+ /** A failure the exit code does not show, such as a rejected command. */
53
+ failed?: boolean | undefined;
54
+ defaultOpen?: boolean;
55
+ /** How many of the newest lines show before "Show earlier lines". */
56
+ maxLines?: number;
57
+ className?: string;
58
+ }) {
59
+ const labels = useAgentKitLabels();
60
+ const formatDuration = useAgentKitDurationFormat();
61
+ const failed =
62
+ !running &&
63
+ (failedOverride === true ||
64
+ timedOut ||
65
+ (exitCode !== undefined && exitCode !== null && exitCode !== 0));
66
+ const hasOutput = Boolean(output?.trim());
67
+ // Opens once when running output starts; never closes on its own.
68
+ const [autoOpen, setAutoOpen] = useState(false);
69
+ // Outlives the body, which remounts on each toggle.
70
+ const [showAllOutput, setShowAllOutput] = useState(false);
71
+ useEffect(() => {
72
+ if (running && hasOutput) setAutoOpen(true);
73
+ }, [running, hasOutput]);
74
+ const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
75
+ const open = openProps.open ?? (uncontrolledOpen || autoOpen);
76
+ const setOpen = (next: boolean) => {
77
+ if (openProps.open === undefined) {
78
+ setUncontrolledOpen(next);
79
+ setAutoOpen(false);
80
+ }
81
+ openProps.onOpenChange?.(next);
82
+ };
83
+ const meta = [
84
+ !running && durationMs !== undefined && durationMs >= 1_000
85
+ ? formatDuration(durationMs)
86
+ : undefined,
87
+ failed && exitCode !== undefined && exitCode !== null && exitCode !== 0
88
+ ? labels.workStepTerminalExitCode.replace("{{code}}", () => `${exitCode}`)
89
+ : undefined,
90
+ timedOut ? labels.workStepTerminalTimedOut : undefined,
91
+ ].filter((part): part is string => Boolean(part));
92
+ const line = (
93
+ <TraceLine status={running ? "running" : failed ? "error" : undefined}>
94
+ <TraceIcon>
95
+ {/* Without an exit code, the triangle marks a failure besides color. */}
96
+ {failed ? (
97
+ <IconAlertTriangle aria-hidden="true" className="agentkit-icon" />
98
+ ) : (
99
+ <IconTerminal2 aria-hidden="true" className="agentkit-icon" />
100
+ )}
101
+ </TraceIcon>
102
+ <TraceTitle className="agentkit-terminal-command">{command}</TraceTitle>
103
+ {running || failed ? (
104
+ // Status shows as motion and color; the accessible name says it.
105
+ <span className="agentkit-visually-hidden">
106
+ {running ? labels.taskStatusRunning : labels.taskStatusFailed}
107
+ </span>
108
+ ) : null}
109
+ {meta.length ? (
110
+ <TraceDescription>{meta.join(" · ")}</TraceDescription>
111
+ ) : null}
112
+ </TraceLine>
113
+ );
114
+ return (
115
+ <Trace
116
+ data-slot="terminal"
117
+ data-status={running ? "running" : failed ? "failed" : "completed"}
118
+ className={
119
+ className ? `agentkit-terminal ${className}` : "agentkit-terminal"
120
+ }
121
+ >
122
+ {hasOutput ? (
123
+ <TraceCollapsible open={open} onOpenChange={setOpen}>
124
+ <div className="agentkit-terminal-row">
125
+ <TraceCollapsibleTrigger>{line}</TraceCollapsibleTrigger>
126
+ <span className="agentkit-terminal-actions">
127
+ <CodeBlockCopyButton
128
+ value={(output ?? "").replace(ANSI_SEQUENCE, "")}
129
+ label={labels.workStepCopyOutput}
130
+ />
131
+ </span>
132
+ </div>
133
+ <TraceCollapsibleContent
134
+ // A fresh node on each toggle: masking a node replay already
135
+ // recorded would not hide its text.
136
+ key={open ? "open" : "closed"}
137
+ keepMounted
138
+ className="agentkit-terminal-body"
139
+ >
140
+ <TerminalOutput
141
+ output={output ?? ""}
142
+ maxLines={maxLines}
143
+ masked={failed || !open}
144
+ showAll={showAllOutput}
145
+ onShowAll={() => setShowAllOutput(true)}
146
+ />
147
+ </TraceCollapsibleContent>
148
+ </TraceCollapsible>
149
+ ) : (
150
+ <span className="agentkit-disclosure-summary" data-expandable="false">
151
+ {line}
152
+ </span>
153
+ )}
154
+ </Trace>
155
+ );
156
+ }
157
+
158
+ export function TerminalOutput({
159
+ output,
160
+ maxLines = DEFAULT_MAX_LINES,
161
+ masked = false,
162
+ showAll: controlledShowAll,
163
+ onShowAll,
164
+ }: {
165
+ output: string;
166
+ maxLines?: number;
167
+ /** Hides the output from session replays. */
168
+ masked?: boolean;
169
+ /** Shows every line. Pass with `onShowAll` to control it. */
170
+ showAll?: boolean;
171
+ /** Called when the user reveals the earlier lines. */
172
+ onShowAll?: () => void;
173
+ }) {
174
+ const labels = useAgentKitLabels();
175
+ const [revealed, setRevealed] = useState(false);
176
+ // With both props the host owns it; with one, a press still reveals.
177
+ const showAll =
178
+ onShowAll && controlledShowAll !== undefined
179
+ ? controlledShowAll
180
+ : controlledShowAll === true || revealed;
181
+ const setShowAll = () => {
182
+ setRevealed(true);
183
+ onShowAll?.();
184
+ };
185
+ const content = useRef<HTMLPreElement>(null);
186
+ const lines = output.replace(/\n$/, "").split("\n");
187
+ const hidden = showAll ? 0 : Math.max(0, lines.length - maxLines);
188
+ const visible = hidden ? lines.slice(hidden).join("\n") : output;
189
+ // Follow only if the reader was at the bottom before the output grew;
190
+ // measured here, not tracked from scroll events.
191
+ const lastHeight = useRef(0);
192
+ useEffect(() => {
193
+ const element = content.current;
194
+ if (!element) return;
195
+ const wasAtBottom =
196
+ lastHeight.current - element.scrollTop - element.clientHeight <=
197
+ FOLLOW_SLACK_PX;
198
+ if (wasAtBottom) element.scrollTop = element.scrollHeight;
199
+ lastHeight.current = element.scrollHeight;
200
+ }, [visible]);
201
+ return (
202
+ <CodeBlock size="sm">
203
+ {hidden ? (
204
+ <CodeBlockHeader>
205
+ <button
206
+ type="button"
207
+ className="agentkit-terminal-earlier"
208
+ onClick={setShowAll}
209
+ >
210
+ {labels.workStepTerminalEarlierLines.replace(
211
+ "{{count}}",
212
+ () => `${hidden}`,
213
+ )}
214
+ </button>
215
+ </CodeBlockHeader>
216
+ ) : null}
217
+ <CodeBlockContent
218
+ ref={content}
219
+ wrap
220
+ language={HAS_ANSI.test(visible) ? "ansi" : undefined}
221
+ className="agentkit-terminal-output"
222
+ {...(masked ? SESSION_REPLAY_MASK_PROPS : {})}
223
+ >
224
+ {visible}
225
+ </CodeBlockContent>
226
+ </CodeBlock>
227
+ );
228
+ }
@@ -0,0 +1,120 @@
1
+ // @vitest-environment happy-dom
2
+
3
+ import { act, useState, type ReactNode } from "react";
4
+ import { createRoot, type Root } from "react-dom/client";
5
+ import { afterEach, describe, expect, it } from "vitest";
6
+
7
+ import {
8
+ TraceCollapsible,
9
+ TraceCollapsibleContent,
10
+ TraceCollapsibleTrigger,
11
+ TraceLine,
12
+ TraceTitle,
13
+ } from "./trace.js";
14
+
15
+ (
16
+ globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT: boolean }
17
+ ).IS_REACT_ACT_ENVIRONMENT = true;
18
+
19
+ let root: Root | undefined;
20
+ let container: HTMLDivElement | undefined;
21
+
22
+ afterEach(() => {
23
+ act(() => root?.unmount());
24
+ container?.remove();
25
+ root = undefined;
26
+ container = undefined;
27
+ });
28
+
29
+ function render(node: ReactNode): HTMLDivElement {
30
+ container = document.createElement("div");
31
+ document.body.append(container);
32
+ root = createRoot(container);
33
+ act(() => root!.render(node));
34
+ return container;
35
+ }
36
+
37
+ function step(keepMounted?: boolean) {
38
+ return (
39
+ <TraceCollapsible>
40
+ <TraceCollapsibleTrigger>
41
+ <TraceLine status="running">
42
+ <TraceTitle>Reading file</TraceTitle>
43
+ </TraceLine>
44
+ </TraceCollapsibleTrigger>
45
+ <TraceCollapsibleContent keepMounted={keepMounted}>
46
+ File contents
47
+ </TraceCollapsibleContent>
48
+ </TraceCollapsible>
49
+ );
50
+ }
51
+
52
+ describe("Trace", () => {
53
+ it("mounts closed content only while open by default", () => {
54
+ const view = render(step());
55
+ const trigger = view.querySelector("button")!;
56
+ expect(trigger.getAttribute("aria-expanded")).toBe("false");
57
+ expect(trigger.hasAttribute("aria-controls")).toBe(false);
58
+ expect(view.textContent).not.toContain("File contents");
59
+
60
+ act(() => trigger.click());
61
+ const content = view.querySelector<HTMLElement>(
62
+ '[data-slot="trace-collapsible-content"]',
63
+ )!;
64
+ expect(trigger.getAttribute("aria-expanded")).toBe("true");
65
+ expect(trigger.getAttribute("aria-controls")).toBe(content.id);
66
+ expect(content.textContent).toBe("File contents");
67
+
68
+ act(() => trigger.click());
69
+ expect(view.textContent).not.toContain("File contents");
70
+ });
71
+
72
+ it("keeps closed content findable and opens on a find-in-page match", () => {
73
+ const view = render(step(true));
74
+ const trigger = view.querySelector("button")!;
75
+ const content = view.querySelector<HTMLElement>(
76
+ '[data-slot="trace-collapsible-content"]',
77
+ )!;
78
+ expect(content.getAttribute("hidden")).toBe("until-found");
79
+ expect(content.textContent).toBe("File contents");
80
+ expect(trigger.getAttribute("aria-controls")).toBe(content.id);
81
+
82
+ act(() => content.dispatchEvent(new Event("beforematch")));
83
+ expect(trigger.getAttribute("aria-expanded")).toBe("true");
84
+ expect(content.hidden).toBe(false);
85
+ });
86
+
87
+ it("follows a controlled open state", () => {
88
+ let setOpen: (open: boolean) => void = () => undefined;
89
+ const changes: boolean[] = [];
90
+ function Controlled() {
91
+ const [open, update] = useState(false);
92
+ setOpen = update;
93
+ return (
94
+ <TraceCollapsible
95
+ open={open}
96
+ onOpenChange={(next) => {
97
+ changes.push(next);
98
+ update(next);
99
+ }}
100
+ >
101
+ <TraceCollapsibleTrigger>Step</TraceCollapsibleTrigger>
102
+ <TraceCollapsibleContent>Detail</TraceCollapsibleContent>
103
+ </TraceCollapsible>
104
+ );
105
+ }
106
+ const view = render(<Controlled />);
107
+ act(() => setOpen(true));
108
+ expect(view.textContent).toContain("Detail");
109
+ act(() => view.querySelector("button")!.click());
110
+ expect(changes).toEqual([false]);
111
+ expect(view.textContent).not.toContain("Detail");
112
+ });
113
+
114
+ it("keeps the trace status apart from a row's protocol status", () => {
115
+ const view = render(step());
116
+ const line = view.querySelector('[data-slot="trace-line"]')!;
117
+ expect(line.getAttribute("data-trace-status")).toBe("running");
118
+ expect(line.hasAttribute("data-status")).toBe(false);
119
+ });
120
+ });