@dexto/tui 1.14.6 → 1.15.0-beta.1

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 (570) hide show
  1. package/dist/InkCLIRefactored.cjs +30 -24
  2. package/dist/InkCLIRefactored.d.ts.map +1 -1
  3. package/dist/InkCLIRefactored.js +30 -24
  4. package/dist/components/ApprovalPrompt.cjs +128 -40
  5. package/dist/components/ApprovalPrompt.d.ts +2 -0
  6. package/dist/components/ApprovalPrompt.d.ts.map +1 -1
  7. package/dist/components/ApprovalPrompt.js +128 -41
  8. package/dist/components/CustomInput.cjs +4 -3
  9. package/dist/components/CustomInput.d.ts.map +1 -1
  10. package/dist/components/CustomInput.js +4 -3
  11. package/dist/components/DeckArea.cjs +43 -0
  12. package/dist/components/DeckArea.d.ts +14 -0
  13. package/dist/components/DeckArea.d.ts.map +1 -0
  14. package/dist/components/DeckArea.js +19 -0
  15. package/dist/components/EditableMultiLineInput.cjs +9 -8
  16. package/dist/components/EditableMultiLineInput.d.ts.map +1 -1
  17. package/dist/components/EditableMultiLineInput.js +9 -8
  18. package/dist/components/ElicitationForm.cjs +78 -18
  19. package/dist/components/ElicitationForm.d.ts.map +1 -1
  20. package/dist/components/ElicitationForm.js +78 -18
  21. package/dist/components/ErrorBoundary.cjs +15 -5
  22. package/dist/components/ErrorBoundary.d.ts.map +1 -1
  23. package/dist/components/ErrorBoundary.js +15 -5
  24. package/dist/components/Footer.cjs +41 -86
  25. package/dist/components/Footer.d.ts +2 -2
  26. package/dist/components/Footer.d.ts.map +1 -1
  27. package/dist/components/Footer.js +44 -92
  28. package/dist/components/Footer.test.cjs +44 -0
  29. package/dist/components/Footer.test.js +44 -0
  30. package/dist/components/HistorySearchBar.cjs +6 -5
  31. package/dist/components/HistorySearchBar.d.ts.map +1 -1
  32. package/dist/components/HistorySearchBar.js +6 -5
  33. package/dist/components/MultiLineInput.cjs +6 -5
  34. package/dist/components/MultiLineInput.d.ts.map +1 -1
  35. package/dist/components/MultiLineInput.js +6 -5
  36. package/dist/components/ResourceAutocomplete.cjs +5 -4
  37. package/dist/components/ResourceAutocomplete.d.ts.map +1 -1
  38. package/dist/components/ResourceAutocomplete.js +5 -4
  39. package/dist/components/SignalGates.test.cjs +215 -0
  40. package/dist/components/SignalGates.test.d.ts +2 -0
  41. package/dist/components/SignalGates.test.d.ts.map +1 -0
  42. package/dist/components/SignalGates.test.js +217 -0
  43. package/dist/components/SlashCommandAutocomplete.cjs +4 -3
  44. package/dist/components/SlashCommandAutocomplete.d.ts.map +1 -1
  45. package/dist/components/SlashCommandAutocomplete.js +4 -3
  46. package/dist/components/StatusBar.cjs +13 -30
  47. package/dist/components/StatusBar.d.ts +1 -3
  48. package/dist/components/StatusBar.d.ts.map +1 -1
  49. package/dist/components/StatusBar.js +13 -30
  50. package/dist/components/TextBufferInput.cjs +13 -12
  51. package/dist/components/TextBufferInput.d.ts.map +1 -1
  52. package/dist/components/TextBufferInput.js +13 -12
  53. package/dist/components/TodoPanel.cjs +23 -16
  54. package/dist/components/TodoPanel.d.ts.map +1 -1
  55. package/dist/components/TodoPanel.js +23 -16
  56. package/dist/components/base/BaseAutocomplete.cjs +7 -6
  57. package/dist/components/base/BaseAutocomplete.d.ts.map +1 -1
  58. package/dist/components/base/BaseAutocomplete.js +7 -6
  59. package/dist/components/base/BaseSelector.cjs +5 -4
  60. package/dist/components/base/BaseSelector.d.ts.map +1 -1
  61. package/dist/components/base/BaseSelector.js +5 -4
  62. package/dist/components/chat/Footer.cjs +2 -1
  63. package/dist/components/chat/Footer.d.ts.map +1 -1
  64. package/dist/components/chat/Footer.js +2 -1
  65. package/dist/components/chat/Header.cjs +20 -16
  66. package/dist/components/chat/Header.d.ts.map +1 -1
  67. package/dist/components/chat/Header.js +20 -16
  68. package/dist/components/chat/MessageItem.cjs +47 -30
  69. package/dist/components/chat/MessageItem.d.ts.map +1 -1
  70. package/dist/components/chat/MessageItem.js +52 -29
  71. package/dist/components/chat/MessageList.cjs +3 -2
  72. package/dist/components/chat/MessageList.d.ts.map +1 -1
  73. package/dist/components/chat/MessageList.js +3 -2
  74. package/dist/components/chat/QueuedMessagesDisplay.cjs +17 -5
  75. package/dist/components/chat/QueuedMessagesDisplay.d.ts.map +1 -1
  76. package/dist/components/chat/QueuedMessagesDisplay.js +18 -6
  77. package/dist/components/chat/SignalMessage.cjs +116 -0
  78. package/dist/components/chat/SignalMessage.d.ts +18 -0
  79. package/dist/components/chat/SignalMessage.d.ts.map +1 -0
  80. package/dist/components/chat/SignalMessage.js +96 -0
  81. package/dist/components/chat/SignalMessage.test.cjs +112 -0
  82. package/dist/components/chat/SignalMessage.test.d.ts +2 -0
  83. package/dist/components/chat/SignalMessage.test.d.ts.map +1 -0
  84. package/dist/components/chat/SignalMessage.test.js +116 -0
  85. package/dist/components/chat/ToolIcon.cjs +6 -5
  86. package/dist/components/chat/ToolIcon.d.ts.map +1 -1
  87. package/dist/components/chat/ToolIcon.js +6 -5
  88. package/dist/components/chat/styled-boxes/ConfigBox.cjs +8 -7
  89. package/dist/components/chat/styled-boxes/ConfigBox.d.ts.map +1 -1
  90. package/dist/components/chat/styled-boxes/ConfigBox.js +8 -7
  91. package/dist/components/chat/styled-boxes/HelpBox.cjs +4 -3
  92. package/dist/components/chat/styled-boxes/HelpBox.d.ts.map +1 -1
  93. package/dist/components/chat/styled-boxes/HelpBox.js +4 -3
  94. package/dist/components/chat/styled-boxes/LogConfigBox.cjs +11 -3
  95. package/dist/components/chat/styled-boxes/LogConfigBox.d.ts.map +1 -1
  96. package/dist/components/chat/styled-boxes/LogConfigBox.js +11 -3
  97. package/dist/components/chat/styled-boxes/SessionHistoryBox.cjs +8 -7
  98. package/dist/components/chat/styled-boxes/SessionHistoryBox.d.ts.map +1 -1
  99. package/dist/components/chat/styled-boxes/SessionHistoryBox.js +8 -7
  100. package/dist/components/chat/styled-boxes/SessionListBox.cjs +19 -11
  101. package/dist/components/chat/styled-boxes/SessionListBox.d.ts.map +1 -1
  102. package/dist/components/chat/styled-boxes/SessionListBox.js +19 -11
  103. package/dist/components/chat/styled-boxes/ShortcutsBox.cjs +4 -3
  104. package/dist/components/chat/styled-boxes/ShortcutsBox.d.ts.map +1 -1
  105. package/dist/components/chat/styled-boxes/ShortcutsBox.js +4 -3
  106. package/dist/components/chat/styled-boxes/StatsBox.cjs +13 -5
  107. package/dist/components/chat/styled-boxes/StatsBox.d.ts.map +1 -1
  108. package/dist/components/chat/styled-boxes/StatsBox.js +13 -5
  109. package/dist/components/chat/styled-boxes/StyledBox.cjs +7 -6
  110. package/dist/components/chat/styled-boxes/StyledBox.d.ts.map +1 -1
  111. package/dist/components/chat/styled-boxes/StyledBox.js +7 -6
  112. package/dist/components/chat/styled-boxes/SyspromptBox.cjs +2 -1
  113. package/dist/components/chat/styled-boxes/SyspromptBox.d.ts.map +1 -1
  114. package/dist/components/chat/styled-boxes/SyspromptBox.js +2 -1
  115. package/dist/components/modes/AlternateBufferCLI.cjs +53 -43
  116. package/dist/components/modes/AlternateBufferCLI.d.ts.map +1 -1
  117. package/dist/components/modes/AlternateBufferCLI.js +53 -43
  118. package/dist/components/modes/StaticCLI.cjs +53 -42
  119. package/dist/components/modes/StaticCLI.d.ts.map +1 -1
  120. package/dist/components/modes/StaticCLI.js +53 -42
  121. package/dist/components/overlays/ApiKeyInput.cjs +12 -11
  122. package/dist/components/overlays/ApiKeyInput.d.ts.map +1 -1
  123. package/dist/components/overlays/ApiKeyInput.js +12 -11
  124. package/dist/components/overlays/ChatGPTUsageCapOverlay.cjs +7 -6
  125. package/dist/components/overlays/ChatGPTUsageCapOverlay.d.ts.map +1 -1
  126. package/dist/components/overlays/ChatGPTUsageCapOverlay.js +7 -6
  127. package/dist/components/overlays/CommandOutputOverlay.cjs +2 -1
  128. package/dist/components/overlays/CommandOutputOverlay.d.ts.map +1 -1
  129. package/dist/components/overlays/CommandOutputOverlay.js +2 -1
  130. package/dist/components/overlays/ConnectOverlay.cjs +10 -9
  131. package/dist/components/overlays/ConnectOverlay.d.ts.map +1 -1
  132. package/dist/components/overlays/ConnectOverlay.js +10 -9
  133. package/dist/components/overlays/ContextStatsOverlay.cjs +48 -37
  134. package/dist/components/overlays/ContextStatsOverlay.d.ts.map +1 -1
  135. package/dist/components/overlays/ContextStatsOverlay.js +48 -37
  136. package/dist/components/overlays/CustomModelWizard.cjs +5 -4
  137. package/dist/components/overlays/CustomModelWizard.d.ts.map +1 -1
  138. package/dist/components/overlays/CustomModelWizard.js +5 -4
  139. package/dist/components/overlays/ExportWizard.cjs +28 -27
  140. package/dist/components/overlays/ExportWizard.d.ts.map +1 -1
  141. package/dist/components/overlays/ExportWizard.js +28 -27
  142. package/dist/components/overlays/InsufficientCreditsOverlay.cjs +25 -9
  143. package/dist/components/overlays/InsufficientCreditsOverlay.d.ts +2 -0
  144. package/dist/components/overlays/InsufficientCreditsOverlay.d.ts.map +1 -1
  145. package/dist/components/overlays/InsufficientCreditsOverlay.js +25 -9
  146. package/dist/components/overlays/LogLevelSelector.cjs +6 -5
  147. package/dist/components/overlays/LogLevelSelector.d.ts.map +1 -1
  148. package/dist/components/overlays/LogLevelSelector.js +6 -5
  149. package/dist/components/overlays/LoginOverlay.cjs +31 -66
  150. package/dist/components/overlays/LoginOverlay.d.ts +1 -3
  151. package/dist/components/overlays/LoginOverlay.d.ts.map +1 -1
  152. package/dist/components/overlays/LoginOverlay.js +32 -71
  153. package/dist/components/overlays/LogoutOverlay.cjs +16 -24
  154. package/dist/components/overlays/LogoutOverlay.d.ts +1 -0
  155. package/dist/components/overlays/LogoutOverlay.d.ts.map +1 -1
  156. package/dist/components/overlays/LogoutOverlay.js +18 -38
  157. package/dist/components/overlays/MarketplaceAddPrompt.cjs +12 -11
  158. package/dist/components/overlays/MarketplaceAddPrompt.d.ts.map +1 -1
  159. package/dist/components/overlays/MarketplaceAddPrompt.js +12 -11
  160. package/dist/components/overlays/MarketplaceBrowser.cjs +27 -26
  161. package/dist/components/overlays/MarketplaceBrowser.d.ts.map +1 -1
  162. package/dist/components/overlays/MarketplaceBrowser.js +27 -26
  163. package/dist/components/overlays/McpAddChoice.cjs +4 -3
  164. package/dist/components/overlays/McpAddChoice.d.ts.map +1 -1
  165. package/dist/components/overlays/McpAddChoice.js +4 -3
  166. package/dist/components/overlays/McpAddSelector.cjs +4 -3
  167. package/dist/components/overlays/McpAddSelector.d.ts.map +1 -1
  168. package/dist/components/overlays/McpAddSelector.js +4 -3
  169. package/dist/components/overlays/McpCustomTypeSelector.cjs +4 -3
  170. package/dist/components/overlays/McpCustomTypeSelector.d.ts.map +1 -1
  171. package/dist/components/overlays/McpCustomTypeSelector.js +4 -3
  172. package/dist/components/overlays/McpCustomWizard.cjs +9 -8
  173. package/dist/components/overlays/McpCustomWizard.d.ts.map +1 -1
  174. package/dist/components/overlays/McpCustomWizard.js +9 -8
  175. package/dist/components/overlays/McpRemoveSelector.cjs +5 -4
  176. package/dist/components/overlays/McpRemoveSelector.d.ts.map +1 -1
  177. package/dist/components/overlays/McpRemoveSelector.js +5 -4
  178. package/dist/components/overlays/McpSelector.cjs +4 -3
  179. package/dist/components/overlays/McpSelector.d.ts.map +1 -1
  180. package/dist/components/overlays/McpSelector.js +4 -3
  181. package/dist/components/overlays/McpServerActions.cjs +7 -6
  182. package/dist/components/overlays/McpServerActions.d.ts.map +1 -1
  183. package/dist/components/overlays/McpServerActions.js +7 -6
  184. package/dist/components/overlays/McpServerList.cjs +6 -5
  185. package/dist/components/overlays/McpServerList.d.ts.map +1 -1
  186. package/dist/components/overlays/McpServerList.js +6 -5
  187. package/dist/components/overlays/ModelSelectorRefactored.cjs +32 -17
  188. package/dist/components/overlays/ModelSelectorRefactored.d.ts.map +1 -1
  189. package/dist/components/overlays/ModelSelectorRefactored.js +32 -17
  190. package/dist/components/overlays/PermissionsSelector.cjs +6 -5
  191. package/dist/components/overlays/PermissionsSelector.d.ts.map +1 -1
  192. package/dist/components/overlays/PermissionsSelector.js +6 -5
  193. package/dist/components/overlays/PluginActions.cjs +7 -6
  194. package/dist/components/overlays/PluginActions.d.ts.map +1 -1
  195. package/dist/components/overlays/PluginActions.js +7 -6
  196. package/dist/components/overlays/PluginList.cjs +12 -11
  197. package/dist/components/overlays/PluginList.d.ts.map +1 -1
  198. package/dist/components/overlays/PluginList.js +12 -11
  199. package/dist/components/overlays/PluginManager.cjs +13 -5
  200. package/dist/components/overlays/PluginManager.d.ts.map +1 -1
  201. package/dist/components/overlays/PluginManager.js +13 -5
  202. package/dist/components/overlays/PromptAddChoice.cjs +5 -4
  203. package/dist/components/overlays/PromptAddChoice.d.ts.map +1 -1
  204. package/dist/components/overlays/PromptAddChoice.js +5 -4
  205. package/dist/components/overlays/PromptAddWizard.cjs +10 -9
  206. package/dist/components/overlays/PromptAddWizard.d.ts.map +1 -1
  207. package/dist/components/overlays/PromptAddWizard.js +10 -9
  208. package/dist/components/overlays/PromptDeleteSelector.cjs +6 -5
  209. package/dist/components/overlays/PromptDeleteSelector.d.ts.map +1 -1
  210. package/dist/components/overlays/PromptDeleteSelector.js +6 -5
  211. package/dist/components/overlays/PromptList.cjs +10 -9
  212. package/dist/components/overlays/PromptList.d.ts.map +1 -1
  213. package/dist/components/overlays/PromptList.js +10 -9
  214. package/dist/components/overlays/ReasoningOverlay.cjs +30 -23
  215. package/dist/components/overlays/ReasoningOverlay.d.ts.map +1 -1
  216. package/dist/components/overlays/ReasoningOverlay.js +30 -23
  217. package/dist/components/overlays/SearchOverlay.cjs +15 -14
  218. package/dist/components/overlays/SearchOverlay.d.ts.map +1 -1
  219. package/dist/components/overlays/SearchOverlay.js +15 -14
  220. package/dist/components/overlays/SessionRenameOverlay.cjs +9 -8
  221. package/dist/components/overlays/SessionRenameOverlay.d.ts.map +1 -1
  222. package/dist/components/overlays/SessionRenameOverlay.js +9 -8
  223. package/dist/components/overlays/SessionSelectorRefactored.cjs +4 -3
  224. package/dist/components/overlays/SessionSelectorRefactored.d.ts.map +1 -1
  225. package/dist/components/overlays/SessionSelectorRefactored.js +4 -3
  226. package/dist/components/overlays/SessionSubcommandSelector.cjs +4 -3
  227. package/dist/components/overlays/SessionSubcommandSelector.d.ts.map +1 -1
  228. package/dist/components/overlays/SessionSubcommandSelector.js +4 -3
  229. package/dist/components/overlays/SoundsSelector.cjs +15 -7
  230. package/dist/components/overlays/SoundsSelector.d.ts.map +1 -1
  231. package/dist/components/overlays/SoundsSelector.js +15 -7
  232. package/dist/components/overlays/StreamSelector.cjs +5 -4
  233. package/dist/components/overlays/StreamSelector.d.ts.map +1 -1
  234. package/dist/components/overlays/StreamSelector.js +5 -4
  235. package/dist/components/overlays/ToolBrowser.cjs +73 -56
  236. package/dist/components/overlays/ToolBrowser.d.ts.map +1 -1
  237. package/dist/components/overlays/ToolBrowser.js +73 -56
  238. package/dist/components/overlays/custom-model-wizard/LocalModelWizard.cjs +103 -69
  239. package/dist/components/overlays/custom-model-wizard/LocalModelWizard.d.ts.map +1 -1
  240. package/dist/components/overlays/custom-model-wizard/LocalModelWizard.js +103 -69
  241. package/dist/components/overlays/custom-model-wizard/provider-config.cjs +4 -4
  242. package/dist/components/overlays/custom-model-wizard/provider-config.js +4 -4
  243. package/dist/components/overlays/custom-model-wizard/shared/ApiKeyStep.cjs +3 -2
  244. package/dist/components/overlays/custom-model-wizard/shared/ApiKeyStep.d.ts.map +1 -1
  245. package/dist/components/overlays/custom-model-wizard/shared/ApiKeyStep.js +3 -2
  246. package/dist/components/overlays/custom-model-wizard/shared/ProviderSelector.cjs +5 -4
  247. package/dist/components/overlays/custom-model-wizard/shared/ProviderSelector.d.ts.map +1 -1
  248. package/dist/components/overlays/custom-model-wizard/shared/ProviderSelector.js +5 -4
  249. package/dist/components/overlays/custom-model-wizard/shared/SetupInfoBanner.cjs +4 -3
  250. package/dist/components/overlays/custom-model-wizard/shared/SetupInfoBanner.d.ts.map +1 -1
  251. package/dist/components/overlays/custom-model-wizard/shared/SetupInfoBanner.js +4 -3
  252. package/dist/components/overlays/custom-model-wizard/shared/WizardStepInput.cjs +7 -6
  253. package/dist/components/overlays/custom-model-wizard/shared/WizardStepInput.d.ts.map +1 -1
  254. package/dist/components/overlays/custom-model-wizard/shared/WizardStepInput.js +7 -6
  255. package/dist/components/renderers/DiffRenderer.cjs +5 -4
  256. package/dist/components/renderers/DiffRenderer.d.ts.map +1 -1
  257. package/dist/components/renderers/DiffRenderer.js +5 -4
  258. package/dist/components/renderers/FilePreviewRenderer.cjs +23 -13
  259. package/dist/components/renderers/FilePreviewRenderer.d.ts.map +1 -1
  260. package/dist/components/renderers/FilePreviewRenderer.js +23 -13
  261. package/dist/components/renderers/FileRenderer.cjs +9 -8
  262. package/dist/components/renderers/FileRenderer.d.ts.map +1 -1
  263. package/dist/components/renderers/FileRenderer.js +9 -8
  264. package/dist/components/renderers/GenericRenderer.cjs +5 -4
  265. package/dist/components/renderers/GenericRenderer.d.ts.map +1 -1
  266. package/dist/components/renderers/GenericRenderer.js +5 -4
  267. package/dist/components/renderers/SearchRenderer.cjs +4 -3
  268. package/dist/components/renderers/SearchRenderer.d.ts.map +1 -1
  269. package/dist/components/renderers/SearchRenderer.js +4 -3
  270. package/dist/components/renderers/ShellRenderer.cjs +6 -5
  271. package/dist/components/renderers/ShellRenderer.d.ts.map +1 -1
  272. package/dist/components/renderers/ShellRenderer.js +6 -5
  273. package/dist/components/renderers/SignalDiff.cjs +139 -0
  274. package/dist/components/renderers/SignalDiff.d.ts +21 -0
  275. package/dist/components/renderers/SignalDiff.d.ts.map +1 -0
  276. package/dist/components/renderers/SignalDiff.js +106 -0
  277. package/dist/components/renderers/SignalDiff.test.cjs +78 -0
  278. package/dist/components/renderers/SignalDiff.test.d.ts +2 -0
  279. package/dist/components/renderers/SignalDiff.test.d.ts.map +1 -0
  280. package/dist/components/renderers/SignalDiff.test.js +77 -0
  281. package/dist/components/renderers/diff-shared.cjs +13 -7
  282. package/dist/components/renderers/diff-shared.d.ts +5 -0
  283. package/dist/components/renderers/diff-shared.d.ts.map +1 -1
  284. package/dist/components/renderers/diff-shared.js +12 -7
  285. package/dist/components/shared/FocusOverlayFrame.cjs +3 -2
  286. package/dist/components/shared/FocusOverlayFrame.d.ts.map +1 -1
  287. package/dist/components/shared/FocusOverlayFrame.js +3 -2
  288. package/dist/components/shared/HintBar.cjs +2 -1
  289. package/dist/components/shared/HintBar.d.ts.map +1 -1
  290. package/dist/components/shared/HintBar.js +2 -1
  291. package/dist/components/shared/MarkdownText.cjs +36 -53
  292. package/dist/components/shared/MarkdownText.d.ts +2 -0
  293. package/dist/components/shared/MarkdownText.d.ts.map +1 -1
  294. package/dist/components/shared/MarkdownText.js +36 -54
  295. package/dist/components/shared/VirtualizedList.cjs +2 -1
  296. package/dist/components/shared/VirtualizedList.d.ts.map +1 -1
  297. package/dist/components/shared/VirtualizedList.js +2 -1
  298. package/dist/containers/OverlayContainer.cjs +32 -44
  299. package/dist/containers/OverlayContainer.d.ts.map +1 -1
  300. package/dist/containers/OverlayContainer.js +32 -44
  301. package/dist/contexts/KeypressContext.cjs +7 -1
  302. package/dist/contexts/KeypressContext.d.ts.map +1 -1
  303. package/dist/contexts/KeypressContext.js +7 -1
  304. package/dist/contexts/KeypressContext.test.cjs +82 -0
  305. package/dist/contexts/KeypressContext.test.d.ts +2 -0
  306. package/dist/contexts/KeypressContext.test.d.ts.map +1 -0
  307. package/dist/contexts/KeypressContext.test.js +81 -0
  308. package/dist/hooks/useAgentEvents.cjs +1 -74
  309. package/dist/hooks/useAgentEvents.d.ts.map +1 -1
  310. package/dist/hooks/useAgentEvents.js +1 -74
  311. package/dist/hooks/useCLIState.cjs +0 -3
  312. package/dist/hooks/useCLIState.d.ts.map +1 -1
  313. package/dist/hooks/useCLIState.js +0 -3
  314. package/dist/hooks/useContextStats.cjs +91 -0
  315. package/dist/hooks/useContextStats.d.ts +13 -0
  316. package/dist/hooks/useContextStats.d.ts.map +1 -0
  317. package/dist/hooks/useContextStats.js +67 -0
  318. package/dist/hooks/useDeckState.cjs +140 -0
  319. package/dist/hooks/useDeckState.d.ts +20 -0
  320. package/dist/hooks/useDeckState.d.ts.map +1 -0
  321. package/dist/hooks/useDeckState.js +123 -0
  322. package/dist/hooks/useDextoCredits.cjs +81 -0
  323. package/dist/hooks/useDextoCredits.d.ts +14 -0
  324. package/dist/hooks/useDextoCredits.d.ts.map +1 -0
  325. package/dist/hooks/useDextoCredits.js +56 -0
  326. package/dist/hooks/useDextoCredits.test.cjs +73 -0
  327. package/dist/hooks/useDextoCredits.test.d.ts +2 -0
  328. package/dist/hooks/useDextoCredits.test.d.ts.map +1 -0
  329. package/dist/hooks/useDextoCredits.test.js +72 -0
  330. package/dist/hooks/useElapsedTime.cjs +13 -24
  331. package/dist/hooks/useElapsedTime.d.ts +3 -1
  332. package/dist/hooks/useElapsedTime.d.ts.map +1 -1
  333. package/dist/hooks/useElapsedTime.js +13 -24
  334. package/dist/hooks/useElapsedTime.test.cjs +35 -0
  335. package/dist/hooks/useElapsedTime.test.d.ts +2 -0
  336. package/dist/hooks/useElapsedTime.test.d.ts.map +1 -0
  337. package/dist/hooks/useElapsedTime.test.js +34 -0
  338. package/dist/hooks/useGitDirtyFiles.cjs +59 -0
  339. package/dist/hooks/useGitDirtyFiles.d.ts +5 -0
  340. package/dist/hooks/useGitDirtyFiles.d.ts.map +1 -0
  341. package/dist/hooks/useGitDirtyFiles.js +34 -0
  342. package/dist/hooks/useGitDirtyFiles.test.cjs +9 -0
  343. package/dist/hooks/useGitDirtyFiles.test.d.ts +2 -0
  344. package/dist/hooks/useGitDirtyFiles.test.d.ts.map +1 -0
  345. package/dist/hooks/useGitDirtyFiles.test.js +8 -0
  346. package/dist/hooks/useHeldValue.cjs +33 -0
  347. package/dist/hooks/useHeldValue.d.ts +3 -0
  348. package/dist/hooks/useHeldValue.d.ts.map +1 -0
  349. package/dist/hooks/useHeldValue.js +9 -0
  350. package/dist/hooks/useHeldValue.test.cjs +31 -0
  351. package/dist/hooks/useHeldValue.test.d.ts +2 -0
  352. package/dist/hooks/useHeldValue.test.d.ts.map +1 -0
  353. package/dist/hooks/useHeldValue.test.js +30 -0
  354. package/dist/hooks/useInputOrchestrator.cjs +22 -30
  355. package/dist/hooks/useInputOrchestrator.d.ts +2 -0
  356. package/dist/hooks/useInputOrchestrator.d.ts.map +1 -1
  357. package/dist/hooks/useInputOrchestrator.js +21 -30
  358. package/dist/hooks/useInputOrchestrator.test.cjs +24 -0
  359. package/dist/hooks/useInputOrchestrator.test.d.ts +2 -0
  360. package/dist/hooks/useInputOrchestrator.test.d.ts.map +1 -0
  361. package/dist/hooks/useInputOrchestrator.test.js +23 -0
  362. package/dist/host/index.cjs +22 -49
  363. package/dist/host/index.d.ts +18 -72
  364. package/dist/host/index.d.ts.map +1 -1
  365. package/dist/host/index.js +18 -42
  366. package/dist/host/index.test.cjs +21 -35
  367. package/dist/host/index.test.js +22 -40
  368. package/dist/index.d.cts +13 -52
  369. package/dist/interactive-commands/command-parser.cjs +13 -21
  370. package/dist/interactive-commands/command-parser.d.ts.map +1 -1
  371. package/dist/interactive-commands/command-parser.js +13 -11
  372. package/dist/interactive-commands/general-commands.cjs +8 -7
  373. package/dist/interactive-commands/general-commands.d.ts.map +1 -1
  374. package/dist/interactive-commands/general-commands.js +8 -7
  375. package/dist/services/processStream.cjs +33 -21
  376. package/dist/services/processStream.d.ts.map +1 -1
  377. package/dist/services/processStream.js +34 -22
  378. package/dist/services/processStream.test.cjs +52 -4
  379. package/dist/services/processStream.test.js +52 -4
  380. package/dist/signal/background.cjs +154 -0
  381. package/dist/signal/background.d.ts +43 -0
  382. package/dist/signal/background.d.ts.map +1 -0
  383. package/dist/signal/background.js +124 -0
  384. package/dist/signal/background.test.cjs +186 -0
  385. package/dist/signal/background.test.d.ts +2 -0
  386. package/dist/signal/background.test.d.ts.map +1 -0
  387. package/dist/signal/background.test.js +192 -0
  388. package/dist/signal/caps.cjs +100 -0
  389. package/dist/signal/caps.d.ts +23 -0
  390. package/dist/signal/caps.d.ts.map +1 -0
  391. package/dist/signal/caps.js +73 -0
  392. package/dist/signal/caps.test.cjs +56 -0
  393. package/dist/signal/caps.test.d.ts +2 -0
  394. package/dist/signal/caps.test.d.ts.map +1 -0
  395. package/dist/signal/caps.test.js +55 -0
  396. package/dist/signal/components.cjs +257 -0
  397. package/dist/signal/components.d.ts +120 -0
  398. package/dist/signal/components.d.ts.map +1 -0
  399. package/dist/signal/components.js +226 -0
  400. package/dist/signal/components.test.cjs +156 -0
  401. package/dist/signal/components.test.d.ts +2 -0
  402. package/dist/signal/components.test.d.ts.map +1 -0
  403. package/dist/signal/components.test.js +133 -0
  404. package/dist/signal/cut.cjs +103 -0
  405. package/dist/signal/cut.d.ts +11 -0
  406. package/dist/signal/cut.d.ts.map +1 -0
  407. package/dist/signal/cut.js +77 -0
  408. package/dist/signal/cut.test.cjs +20 -0
  409. package/dist/signal/cut.test.d.ts +2 -0
  410. package/dist/signal/cut.test.d.ts.map +1 -0
  411. package/dist/signal/cut.test.js +19 -0
  412. package/dist/signal/deck-layout.cjs +57 -0
  413. package/dist/signal/deck-layout.d.ts +29 -0
  414. package/dist/signal/deck-layout.d.ts.map +1 -0
  415. package/dist/signal/deck-layout.js +30 -0
  416. package/dist/signal/deck-parts.cjs +243 -0
  417. package/dist/signal/deck-parts.d.ts +55 -0
  418. package/dist/signal/deck-parts.d.ts.map +1 -0
  419. package/dist/signal/deck-parts.js +205 -0
  420. package/dist/signal/deck.test.cjs +311 -0
  421. package/dist/signal/deck.test.d.ts +2 -0
  422. package/dist/signal/deck.test.d.ts.map +1 -0
  423. package/dist/signal/deck.test.js +288 -0
  424. package/dist/signal/glyphs.cjs +195 -0
  425. package/dist/signal/glyphs.d.ts +8 -0
  426. package/dist/signal/glyphs.d.ts.map +1 -0
  427. package/dist/signal/glyphs.js +171 -0
  428. package/dist/signal/glyphs.test.cjs +17 -0
  429. package/dist/signal/glyphs.test.d.ts +2 -0
  430. package/dist/signal/glyphs.test.d.ts.map +1 -0
  431. package/dist/signal/glyphs.test.js +16 -0
  432. package/dist/signal/harness.cjs +103 -0
  433. package/dist/signal/harness.d.ts +70 -0
  434. package/dist/signal/harness.d.ts.map +1 -0
  435. package/dist/signal/harness.js +67 -0
  436. package/dist/signal/harness.test.cjs +84 -0
  437. package/dist/signal/harness.test.d.ts +2 -0
  438. package/dist/signal/harness.test.d.ts.map +1 -0
  439. package/dist/signal/harness.test.js +61 -0
  440. package/dist/signal/index.cjs +76 -0
  441. package/dist/signal/index.d.ts +8 -0
  442. package/dist/signal/index.d.ts.map +1 -0
  443. package/dist/signal/index.js +45 -0
  444. package/dist/signal/kit.snapshot.test.cjs +56 -0
  445. package/dist/signal/kit.snapshot.test.d.ts +2 -0
  446. package/dist/signal/kit.snapshot.test.d.ts.map +1 -0
  447. package/dist/signal/kit.snapshot.test.js +55 -0
  448. package/dist/signal/no-raw-colours.test.cjs +32 -0
  449. package/dist/signal/no-raw-colours.test.d.ts +2 -0
  450. package/dist/signal/no-raw-colours.test.d.ts.map +1 -0
  451. package/dist/signal/no-raw-colours.test.js +30 -0
  452. package/dist/signal/paint.cjs +76 -0
  453. package/dist/signal/paint.d.ts +15 -0
  454. package/dist/signal/paint.d.ts.map +1 -0
  455. package/dist/signal/paint.js +41 -0
  456. package/dist/signal/paint.test.cjs +98 -0
  457. package/dist/signal/paint.test.d.ts +2 -0
  458. package/dist/signal/paint.test.d.ts.map +1 -0
  459. package/dist/signal/paint.test.js +75 -0
  460. package/dist/signal/tone.cjs +109 -0
  461. package/dist/signal/tone.d.ts +17 -0
  462. package/dist/signal/tone.d.ts.map +1 -0
  463. package/dist/signal/tone.js +83 -0
  464. package/dist/signal/tone.test.cjs +70 -0
  465. package/dist/signal/tone.test.d.ts +2 -0
  466. package/dist/signal/tone.test.d.ts.map +1 -0
  467. package/dist/signal/tone.test.js +69 -0
  468. package/dist/signal/trace.cjs +142 -0
  469. package/dist/signal/trace.d.ts +41 -0
  470. package/dist/signal/trace.d.ts.map +1 -0
  471. package/dist/signal/trace.js +113 -0
  472. package/dist/signal/trace.test.cjs +50 -0
  473. package/dist/signal/trace.test.d.ts +2 -0
  474. package/dist/signal/trace.test.d.ts.map +1 -0
  475. package/dist/signal/trace.test.js +49 -0
  476. package/dist/signal/use-trace.cjs +73 -0
  477. package/dist/signal/use-trace.d.ts +5 -0
  478. package/dist/signal/use-trace.d.ts.map +1 -0
  479. package/dist/signal/use-trace.js +48 -0
  480. package/dist/signal/wordmark-art.generated.cjs +375 -0
  481. package/dist/signal/wordmark-art.generated.d.ts +3 -0
  482. package/dist/signal/wordmark-art.generated.d.ts.map +1 -0
  483. package/dist/signal/wordmark-art.generated.js +351 -0
  484. package/dist/signal/wordmark.cjs +60 -0
  485. package/dist/signal/wordmark.d.ts +23 -0
  486. package/dist/signal/wordmark.d.ts.map +1 -0
  487. package/dist/signal/wordmark.js +34 -0
  488. package/dist/signal/wordmark.test.cjs +71 -0
  489. package/dist/signal/wordmark.test.d.ts +2 -0
  490. package/dist/signal/wordmark.test.d.ts.map +1 -0
  491. package/dist/signal/wordmark.test.js +70 -0
  492. package/dist/state/initialState.cjs +0 -3
  493. package/dist/state/initialState.d.ts.map +1 -1
  494. package/dist/state/initialState.js +0 -3
  495. package/dist/state/types.d.ts +13 -7
  496. package/dist/state/types.d.ts.map +1 -1
  497. package/dist/utils/approval-response.cjs +45 -0
  498. package/dist/utils/approval-response.d.ts +14 -0
  499. package/dist/utils/approval-response.d.ts.map +1 -0
  500. package/dist/utils/approval-response.js +21 -0
  501. package/dist/utils/approval-response.test.cjs +49 -0
  502. package/dist/utils/approval-response.test.d.ts +2 -0
  503. package/dist/utils/approval-response.test.d.ts.map +1 -0
  504. package/dist/utils/approval-response.test.js +55 -0
  505. package/dist/utils/approvalScope.cjs +12 -0
  506. package/dist/utils/approvalScope.d.ts.map +1 -1
  507. package/dist/utils/approvalScope.js +12 -0
  508. package/dist/utils/approvalScope.test.cjs +23 -0
  509. package/dist/utils/approvalScope.test.d.ts +2 -0
  510. package/dist/utils/approvalScope.test.d.ts.map +1 -0
  511. package/dist/utils/approvalScope.test.js +22 -0
  512. package/dist/utils/background-failure.cjs +51 -0
  513. package/dist/utils/background-failure.d.ts +12 -0
  514. package/dist/utils/background-failure.d.ts.map +1 -0
  515. package/dist/utils/background-failure.js +26 -0
  516. package/dist/utils/chatgpt-rate-limit.cjs +10 -0
  517. package/dist/utils/chatgpt-rate-limit.d.ts +9 -0
  518. package/dist/utils/chatgpt-rate-limit.d.ts.map +1 -1
  519. package/dist/utils/chatgpt-rate-limit.js +9 -0
  520. package/dist/utils/chatgpt-rate-limit.test.cjs +10 -0
  521. package/dist/utils/chatgpt-rate-limit.test.js +11 -0
  522. package/dist/utils/deck-state.cjs +107 -0
  523. package/dist/utils/deck-state.d.ts +79 -0
  524. package/dist/utils/deck-state.d.ts.map +1 -0
  525. package/dist/utils/deck-state.js +76 -0
  526. package/dist/utils/deck-state.test.cjs +208 -0
  527. package/dist/utils/deck-state.test.d.ts +2 -0
  528. package/dist/utils/deck-state.test.d.ts.map +1 -0
  529. package/dist/utils/deck-state.test.js +216 -0
  530. package/dist/utils/fault-block.cjs +37 -0
  531. package/dist/utils/fault-block.d.ts +13 -0
  532. package/dist/utils/fault-block.d.ts.map +1 -0
  533. package/dist/utils/fault-block.js +13 -0
  534. package/dist/utils/fault-block.test.cjs +23 -0
  535. package/dist/utils/fault-block.test.d.ts +2 -0
  536. package/dist/utils/fault-block.test.d.ts.map +1 -0
  537. package/dist/utils/fault-block.test.js +22 -0
  538. package/dist/utils/llm-provider-display.cjs +1 -1
  539. package/dist/utils/llm-provider-display.js +1 -1
  540. package/dist/utils/messageFormatting.cjs +26 -23
  541. package/dist/utils/messageFormatting.d.ts +5 -2
  542. package/dist/utils/messageFormatting.d.ts.map +1 -1
  543. package/dist/utils/messageFormatting.js +25 -21
  544. package/dist/utils/messageFormatting.test.cjs +34 -0
  545. package/dist/utils/messageFormatting.test.js +35 -1
  546. package/dist/utils/reasoning-variant.cjs +35 -0
  547. package/dist/utils/reasoning-variant.d.ts +13 -0
  548. package/dist/utils/reasoning-variant.d.ts.map +1 -0
  549. package/dist/utils/reasoning-variant.js +11 -0
  550. package/dist/utils/resize-reflow.cjs +119 -0
  551. package/dist/utils/resize-reflow.d.ts +18 -0
  552. package/dist/utils/resize-reflow.d.ts.map +1 -0
  553. package/dist/utils/resize-reflow.js +83 -0
  554. package/dist/utils/resize-reflow.test.cjs +100 -0
  555. package/dist/utils/resize-reflow.test.d.ts +2 -0
  556. package/dist/utils/resize-reflow.test.d.ts.map +1 -0
  557. package/dist/utils/resize-reflow.test.js +99 -0
  558. package/dist/utils/tool-step.cjs +183 -0
  559. package/dist/utils/tool-step.d.ts +28 -0
  560. package/dist/utils/tool-step.d.ts.map +1 -0
  561. package/dist/utils/tool-step.js +156 -0
  562. package/dist/utils/tool-step.test.cjs +263 -0
  563. package/dist/utils/tool-step.test.d.ts +2 -0
  564. package/dist/utils/tool-step.test.d.ts.map +1 -0
  565. package/dist/utils/tool-step.test.js +262 -0
  566. package/package.json +9 -5
  567. package/dist/components/BackgroundTasksPanel.cjs +0 -117
  568. package/dist/components/BackgroundTasksPanel.d.ts +0 -18
  569. package/dist/components/BackgroundTasksPanel.d.ts.map +0 -1
  570. package/dist/components/BackgroundTasksPanel.js +0 -93
@@ -0,0 +1,311 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (let key of __getOwnPropNames(from))
11
+ if (!__hasOwnProp.call(to, key) && key !== except)
12
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
13
+ }
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
22
+ mod
23
+ ));
24
+ var import_react = require("react");
25
+ var import_node_stream = require("node:stream");
26
+ var import_ink = require("ink");
27
+ var import_strip_ansi = __toESM(require("strip-ansi"), 1);
28
+ var import_vitest = require("vitest");
29
+ var import_caps = require("./caps.js");
30
+ var import_components = require("./components.js");
31
+ var import_deck_layout = require("./deck-layout.js");
32
+ var import_deck_parts = require("./deck-parts.js");
33
+ function recordingStdout(columns) {
34
+ const writes = [];
35
+ const stdout = Object.assign(new import_node_stream.PassThrough(), { columns, rows: 40, isTTY: false });
36
+ stdout.write = ((chunk) => {
37
+ writes.push(String(chunk));
38
+ return true;
39
+ });
40
+ return { stdout, writes };
41
+ }
42
+ async function frame(element, columns) {
43
+ const { stdout, writes } = recordingStdout(columns);
44
+ const view = (0, import_ink.render)(element, { stdout, debug: true, patchConsole: false, exitOnCtrlC: false });
45
+ await new Promise((resolve) => setTimeout(resolve, 20));
46
+ view.unmount();
47
+ const last = writes.filter((w) => w.trim() !== "").at(-1) ?? "";
48
+ return (0, import_strip_ansi.default)(last).replace(/\n+$/, "");
49
+ }
50
+ const WORDMARK = 42;
51
+ const state = {
52
+ mode: "stream",
53
+ readout: "84 tok/s \xB7 12.4s",
54
+ status: {
55
+ model: "dexto/sonnet-5.5",
56
+ contextUsedTokens: 46e3,
57
+ contextMaxTokens: 2e5,
58
+ where: { kind: "local" },
59
+ branch: "main",
60
+ dirtyFiles: 3,
61
+ credits: { kind: "balance", balance: 12.84, spend: null }
62
+ }
63
+ };
64
+ function deck(s = state, gate = null, paused = false) {
65
+ const children = (0, import_react.createElement)(import_ink.Text, null, "\u203A ask");
66
+ return (0, import_react.createElement)(
67
+ import_components.Deck,
68
+ gate === null ? { state: s, collapsed: false, paused, children } : { state: s, gate, collapsed: false, paused, children }
69
+ );
70
+ }
71
+ (0, import_vitest.describe)("deckLayout", () => {
72
+ (0, import_vitest.it)("steps down from a status block to a status row to a bare trace", () => {
73
+ (0, import_vitest.expect)((0, import_deck_layout.deckLayout)(120, WORDMARK)).toMatchObject({
74
+ band: "wide",
75
+ bandRows: 3,
76
+ statusRow: false
77
+ });
78
+ (0, import_vitest.expect)((0, import_deck_layout.deckLayout)(78, WORDMARK)).toMatchObject({
79
+ band: "mid",
80
+ bandRows: 3,
81
+ statusRow: true
82
+ });
83
+ (0, import_vitest.expect)((0, import_deck_layout.deckLayout)(42, WORDMARK)).toMatchObject({
84
+ band: "bare",
85
+ bandRows: 2,
86
+ statusRow: true
87
+ });
88
+ });
89
+ (0, import_vitest.it)("keeps the deck to four or five rows with a one-line input", () => {
90
+ const rows = (cols) => {
91
+ const l = (0, import_deck_layout.deckLayout)(cols, WORDMARK);
92
+ return l.bandRows + 1 + (l.statusRow ? 1 : 0);
93
+ };
94
+ (0, import_vitest.expect)(rows(120)).toBe(4);
95
+ (0, import_vitest.expect)(rows(78)).toBe(5);
96
+ (0, import_vitest.expect)(rows(42)).toBe(4);
97
+ });
98
+ (0, import_vitest.it)("goes bare when the wordmark would leave no room for the mode and readout", () => {
99
+ (0, import_vitest.expect)((0, import_deck_layout.deckLayout)(66, WORDMARK).band).toBe("mid");
100
+ (0, import_vitest.expect)((0, import_deck_layout.deckLayout)(65, WORDMARK).band).toBe("bare");
101
+ (0, import_vitest.expect)((0, import_deck_layout.deckLayout)(50, WORDMARK).band).toBe("bare");
102
+ });
103
+ (0, import_vitest.it)("sizes the status block between 30 and 36 columns", () => {
104
+ (0, import_vitest.expect)((0, import_deck_layout.deckLayout)(100, WORDMARK).blockWidth).toBe(30);
105
+ (0, import_vitest.expect)((0, import_deck_layout.deckLayout)(200, WORDMARK).blockWidth).toBe(36);
106
+ (0, import_vitest.expect)((0, import_deck_layout.deckLayout)(80, WORDMARK).blockWidth).toBe(0);
107
+ });
108
+ });
109
+ (0, import_vitest.describe)("laneParts", () => {
110
+ (0, import_vitest.it)("drops the dirty count first, then the branch", () => {
111
+ const status = state.status;
112
+ (0, import_vitest.expect)((0, import_deck_parts.laneParts)(status, 28)).toEqual({ branch: true, dirty: true, spend: false });
113
+ (0, import_vitest.expect)((0, import_deck_parts.laneParts)(status, 27)).toEqual({ branch: true, dirty: false, spend: false });
114
+ (0, import_vitest.expect)((0, import_deck_parts.laneParts)(status, 24)).toEqual({ branch: false, dirty: false, spend: false });
115
+ });
116
+ (0, import_vitest.it)("drops this turn's spend last", () => {
117
+ const status = {
118
+ ...state.status,
119
+ credits: { kind: "balance", balance: 12.84, spend: 0.31 }
120
+ };
121
+ (0, import_vitest.expect)((0, import_deck_parts.laneParts)(status, 25)).toEqual({ branch: false, dirty: false, spend: true });
122
+ (0, import_vitest.expect)((0, import_deck_parts.laneParts)(status, 24)).toEqual({ branch: false, dirty: false, spend: false });
123
+ });
124
+ });
125
+ (0, import_vitest.describe)("statusRowFit", () => {
126
+ const status = { ...state.status, model: "dexto/anthropic/claude-sonnet-4.5" };
127
+ (0, import_vitest.it)("reserves the lane and lets the model truncate", () => {
128
+ (0, import_vitest.expect)((0, import_deck_parts.statusRowFit)(status, 42, 0)).toEqual({ notice: 0, model: 22, lane: 18 });
129
+ });
130
+ (0, import_vitest.it)("hides the model rather than show a stub", () => {
131
+ (0, import_vitest.expect)((0, import_deck_parts.statusRowFit)(status, 42, 17)).toEqual({ notice: 17, model: 0, lane: 23 });
132
+ });
133
+ (0, import_vitest.it)("truncates a long notice rather than the lane", () => {
134
+ (0, import_vitest.expect)((0, import_deck_parts.statusRowFit)(status, 42, 23)).toEqual({ notice: 22, model: 0, lane: 18 });
135
+ });
136
+ (0, import_vitest.it)("hides the notice when a stub is all that fits", () => {
137
+ (0, import_vitest.expect)((0, import_deck_parts.statusRowFit)(status, 22, 12)).toEqual({ notice: 0, model: 0, lane: 22 });
138
+ });
139
+ (0, import_vitest.it)("gives the lane whatever the model leaves", () => {
140
+ (0, import_vitest.expect)((0, import_deck_parts.statusRowFit)(state.status, 120, 0)).toEqual({ notice: 0, model: 21, lane: 97 });
141
+ });
142
+ });
143
+ (0, import_vitest.describe)("formatTokens", () => {
144
+ (0, import_vitest.it)("reads like 46k, 1.2M and 850", () => {
145
+ (0, import_vitest.expect)((0, import_deck_layout.formatTokens)(46e3)).toBe("46k");
146
+ (0, import_vitest.expect)((0, import_deck_layout.formatTokens)(12e5)).toBe("1.2M");
147
+ (0, import_vitest.expect)((0, import_deck_layout.formatTokens)(850)).toBe("850");
148
+ });
149
+ });
150
+ (0, import_vitest.describe)("Deck", () => {
151
+ let saved;
152
+ (0, import_vitest.beforeEach)(() => {
153
+ saved = (0, import_caps.getCaps)();
154
+ (0, import_caps.setCaps)({ ...saved, color: "none", glyphs: "unicode", motion: "reduced" });
155
+ });
156
+ (0, import_vitest.afterEach)(() => (0, import_caps.setCaps)(saved));
157
+ (0, import_vitest.it)("is four rows at 120 columns, with the status block beside the trace", async () => {
158
+ const out = await frame(deck(), 120);
159
+ const lines = out.split("\n");
160
+ (0, import_vitest.expect)(lines).toHaveLength(4);
161
+ (0, import_vitest.expect)(lines[0]).toMatch(/STREAMING · 84 tok\/s · 12\.4s\s*$/);
162
+ (0, import_vitest.expect)(lines[1]).toMatch(/dexto\/sonnet-5\.5\s+46k\/200k\s*$/);
163
+ (0, import_vitest.expect)(lines[2]).toMatch(/◇ local ⎇ main ±3 · ◆ \$12\.84\s*$/);
164
+ (0, import_vitest.expect)(lines[3]).toBe("\u203A ask");
165
+ });
166
+ (0, import_vitest.it)("moves the status to a compact row under the input below 100 columns", async () => {
167
+ const out = await frame(deck(), 78);
168
+ const lines = out.split("\n");
169
+ (0, import_vitest.expect)(lines).toHaveLength(5);
170
+ (0, import_vitest.expect)(lines[0]).toMatch(/STREAMING · 84 tok\/s · 12\.4s\s*$/);
171
+ (0, import_vitest.expect)(lines[3]).toBe("\u203A ask");
172
+ (0, import_vitest.expect)(lines[4]).toMatch(/^dexto\/sonnet-5\.5\s+46k\s+◇ local ⎇ main ±3 · ◆ \$12\.84/);
173
+ });
174
+ (0, import_vitest.it)("drops the wordmark below 44 columns and keeps the trace", async () => {
175
+ const out = await frame(deck(), 42);
176
+ const lines = out.split("\n");
177
+ (0, import_vitest.expect)(lines).toHaveLength(4);
178
+ (0, import_vitest.expect)(out).not.toContain("dexto ");
179
+ (0, import_vitest.expect)(lines[0]).toMatch(/[▁-█]/);
180
+ (0, import_vitest.expect)(lines[2]).toBe("\u203A ask");
181
+ (0, import_vitest.expect)(lines[3]).toMatch(/^84 tok\/s · 12\.4s\s+46k\s+◇ local · ◆ \$12\.84$/);
182
+ });
183
+ (0, import_vitest.it)("keeps the readout, and so the permission mode, in the middle step", async () => {
184
+ const out = await frame(deck({ ...state, mode: "idle", readout: "plan mode" }), 78);
185
+ (0, import_vitest.expect)(out.split("\n")[0]).toMatch(/READY · plan mode\s*$/);
186
+ });
187
+ (0, import_vitest.it)("leads the bare status row with the readout and never cuts the lane", async () => {
188
+ const long = {
189
+ ...state,
190
+ mode: "idle",
191
+ readout: "auto-approve",
192
+ status: { ...state.status, model: "dexto/anthropic/claude-sonnet-4.5" }
193
+ };
194
+ const row = (await frame(deck(long), 42)).split("\n")[3] ?? "";
195
+ (0, import_vitest.expect)(row).toMatch(/^auto-approve\s+46k\s+◇ local · ◆ \$12\.84$/);
196
+ const plain = (await frame(deck({ ...long, readout: null }), 42)).split("\n")[3] ?? "";
197
+ (0, import_vitest.expect)(plain).toMatch(/^dexto\/anthropic.*…\s+46k\s+◇ local · ◆ \$12\.84$/);
198
+ });
199
+ (0, import_vitest.it)("keeps the lane whole beside a notice too long to fit", async () => {
200
+ const long = { ...state, mode: "idle", readout: "auto-approve \xB7 r:medium" };
201
+ const row = (await frame(deck(long), 42)).split("\n")[3] ?? "";
202
+ (0, import_vitest.expect)(row).toMatch(/^auto-approve · r:medi…\s+◇ local · ◆ \$12\.84$/);
203
+ });
204
+ (0, import_vitest.it)("draws only the input when collapsed, leaving it mounted", async () => {
205
+ const collapsed = (0, import_react.createElement)(import_components.Deck, {
206
+ state,
207
+ collapsed: true,
208
+ paused: false,
209
+ children: (0, import_react.createElement)(import_ink.Text, null, "INPUT")
210
+ });
211
+ (0, import_vitest.expect)(await frame(collapsed, 120)).toBe("INPUT");
212
+ });
213
+ (0, import_vitest.it)("keeps context use visible beside a long model id", async () => {
214
+ const long = {
215
+ ...state,
216
+ status: { ...state.status, model: "anthropic/claude-sonnet-4-5-20250929" }
217
+ };
218
+ const lines = (await frame(deck(long), 120)).split("\n");
219
+ (0, import_vitest.expect)(lines[1]).toMatch(/anthropic\/claude-\S*…\s+46k\/200k\s*$/);
220
+ });
221
+ (0, import_vitest.it)("slots a gate between the band and the input", async () => {
222
+ const out = await frame(deck(state, (0, import_react.createElement)(import_ink.Text, null, "GATE")), 120);
223
+ const lines = out.split("\n");
224
+ (0, import_vitest.expect)(lines[3]).toBe("GATE");
225
+ (0, import_vitest.expect)(lines[4]).toBe("\u203A ask");
226
+ });
227
+ (0, import_vitest.it)("says when you are signed out, out of credits, or on a cloud computer", async () => {
228
+ const signedOut = await frame(
229
+ deck({ ...state, status: { ...state.status, credits: { kind: "signed-out" } } }),
230
+ 120
231
+ );
232
+ (0, import_vitest.expect)(signedOut).toContain("\xB7 cloud off");
233
+ const loading = await frame(
234
+ deck({ ...state, status: { ...state.status, credits: { kind: "signed-in" } } }),
235
+ 120
236
+ );
237
+ (0, import_vitest.expect)(loading).toMatch(/◇ local ⎇ main ±3 · ◆\s*$/m);
238
+ const out = await frame(
239
+ deck({ ...state, status: { ...state.status, credits: { kind: "out" } } }),
240
+ 120
241
+ );
242
+ (0, import_vitest.expect)(out).toContain("out of credits");
243
+ const cloud = await frame(
244
+ deck({
245
+ ...state,
246
+ status: { ...state.status, where: { kind: "computer", name: "dx-7f3a" } }
247
+ }),
248
+ 120
249
+ );
250
+ (0, import_vitest.expect)(cloud).toContain("\u25C6 dx-7f3a");
251
+ });
252
+ (0, import_vitest.it)("leaves out what it does not know", async () => {
253
+ const out = await frame(
254
+ deck({
255
+ mode: "idle",
256
+ readout: null,
257
+ status: {
258
+ ...state.status,
259
+ model: "gpt-5",
260
+ contextUsedTokens: null,
261
+ contextMaxTokens: null,
262
+ branch: null,
263
+ dirtyFiles: 0
264
+ }
265
+ }),
266
+ 120
267
+ );
268
+ const lines = out.split("\n");
269
+ (0, import_vitest.expect)(lines[0]).toMatch(/READY\s*$/);
270
+ (0, import_vitest.expect)(lines[1]).toMatch(/gpt-5\s*$/);
271
+ (0, import_vitest.expect)(lines[2]).toMatch(/◇ local · ◆ \$12\.84\s*$/);
272
+ });
273
+ (0, import_vitest.it)("falls back to ASCII glyphs", async () => {
274
+ (0, import_caps.setCaps)({ ...(0, import_caps.getCaps)(), glyphs: "ascii" });
275
+ const out = await frame(deck(), 120);
276
+ (0, import_vitest.expect)(out).toContain("o local @ main +3 . * $12.84");
277
+ (0, import_vitest.expect)(out).not.toMatch(/[▁-█◇◆⎇]/);
278
+ });
279
+ });
280
+ (0, import_vitest.describe)("Deck trace clock", () => {
281
+ let saved;
282
+ (0, import_vitest.beforeEach)(() => {
283
+ saved = (0, import_caps.getCaps)();
284
+ (0, import_caps.setCaps)({ ...saved, color: "none", glyphs: "unicode", motion: "full" });
285
+ });
286
+ (0, import_vitest.afterEach)(() => (0, import_caps.setCaps)(saved));
287
+ async function framesOver(s, ms, paused = false) {
288
+ const { stdout, writes } = recordingStdout(120);
289
+ const view = (0, import_ink.render)(deck(s, null, paused), {
290
+ stdout,
291
+ debug: true,
292
+ patchConsole: false,
293
+ exitOnCtrlC: false
294
+ });
295
+ await new Promise((resolve) => setTimeout(resolve, 50));
296
+ const settled = writes.length;
297
+ await new Promise((resolve) => setTimeout(resolve, ms));
298
+ const written = writes.length - settled;
299
+ view.unmount();
300
+ return written;
301
+ }
302
+ (0, import_vitest.it)("scrolls while the agent works", async () => {
303
+ (0, import_vitest.expect)(await framesOver(state, 350)).toBeGreaterThanOrEqual(2);
304
+ });
305
+ (0, import_vitest.it)("holds trace and wordmark still while paused for copy mode", async () => {
306
+ (0, import_vitest.expect)(await framesOver({ ...state, mode: "think" }, 350, true)).toBe(0);
307
+ });
308
+ (0, import_vitest.it)("writes nothing while the session sits idle", async () => {
309
+ (0, import_vitest.expect)(await framesOver({ ...state, mode: "idle", readout: null }, 350)).toBe(0);
310
+ });
311
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=deck.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deck.test.d.ts","sourceRoot":"","sources":["../../src/signal/deck.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,288 @@
1
+ import { createElement } from "react";
2
+ import { PassThrough } from "node:stream";
3
+ import { render, Text } from "ink";
4
+ import stripAnsi from "strip-ansi";
5
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
6
+ import { getCaps, setCaps } from "./caps.js";
7
+ import { Deck } from "./components.js";
8
+ import { deckLayout, formatTokens } from "./deck-layout.js";
9
+ import { laneParts, statusRowFit } from "./deck-parts.js";
10
+ function recordingStdout(columns) {
11
+ const writes = [];
12
+ const stdout = Object.assign(new PassThrough(), { columns, rows: 40, isTTY: false });
13
+ stdout.write = ((chunk) => {
14
+ writes.push(String(chunk));
15
+ return true;
16
+ });
17
+ return { stdout, writes };
18
+ }
19
+ async function frame(element, columns) {
20
+ const { stdout, writes } = recordingStdout(columns);
21
+ const view = render(element, { stdout, debug: true, patchConsole: false, exitOnCtrlC: false });
22
+ await new Promise((resolve) => setTimeout(resolve, 20));
23
+ view.unmount();
24
+ const last = writes.filter((w) => w.trim() !== "").at(-1) ?? "";
25
+ return stripAnsi(last).replace(/\n+$/, "");
26
+ }
27
+ const WORDMARK = 42;
28
+ const state = {
29
+ mode: "stream",
30
+ readout: "84 tok/s \xB7 12.4s",
31
+ status: {
32
+ model: "dexto/sonnet-5.5",
33
+ contextUsedTokens: 46e3,
34
+ contextMaxTokens: 2e5,
35
+ where: { kind: "local" },
36
+ branch: "main",
37
+ dirtyFiles: 3,
38
+ credits: { kind: "balance", balance: 12.84, spend: null }
39
+ }
40
+ };
41
+ function deck(s = state, gate = null, paused = false) {
42
+ const children = createElement(Text, null, "\u203A ask");
43
+ return createElement(
44
+ Deck,
45
+ gate === null ? { state: s, collapsed: false, paused, children } : { state: s, gate, collapsed: false, paused, children }
46
+ );
47
+ }
48
+ describe("deckLayout", () => {
49
+ it("steps down from a status block to a status row to a bare trace", () => {
50
+ expect(deckLayout(120, WORDMARK)).toMatchObject({
51
+ band: "wide",
52
+ bandRows: 3,
53
+ statusRow: false
54
+ });
55
+ expect(deckLayout(78, WORDMARK)).toMatchObject({
56
+ band: "mid",
57
+ bandRows: 3,
58
+ statusRow: true
59
+ });
60
+ expect(deckLayout(42, WORDMARK)).toMatchObject({
61
+ band: "bare",
62
+ bandRows: 2,
63
+ statusRow: true
64
+ });
65
+ });
66
+ it("keeps the deck to four or five rows with a one-line input", () => {
67
+ const rows = (cols) => {
68
+ const l = deckLayout(cols, WORDMARK);
69
+ return l.bandRows + 1 + (l.statusRow ? 1 : 0);
70
+ };
71
+ expect(rows(120)).toBe(4);
72
+ expect(rows(78)).toBe(5);
73
+ expect(rows(42)).toBe(4);
74
+ });
75
+ it("goes bare when the wordmark would leave no room for the mode and readout", () => {
76
+ expect(deckLayout(66, WORDMARK).band).toBe("mid");
77
+ expect(deckLayout(65, WORDMARK).band).toBe("bare");
78
+ expect(deckLayout(50, WORDMARK).band).toBe("bare");
79
+ });
80
+ it("sizes the status block between 30 and 36 columns", () => {
81
+ expect(deckLayout(100, WORDMARK).blockWidth).toBe(30);
82
+ expect(deckLayout(200, WORDMARK).blockWidth).toBe(36);
83
+ expect(deckLayout(80, WORDMARK).blockWidth).toBe(0);
84
+ });
85
+ });
86
+ describe("laneParts", () => {
87
+ it("drops the dirty count first, then the branch", () => {
88
+ const status = state.status;
89
+ expect(laneParts(status, 28)).toEqual({ branch: true, dirty: true, spend: false });
90
+ expect(laneParts(status, 27)).toEqual({ branch: true, dirty: false, spend: false });
91
+ expect(laneParts(status, 24)).toEqual({ branch: false, dirty: false, spend: false });
92
+ });
93
+ it("drops this turn's spend last", () => {
94
+ const status = {
95
+ ...state.status,
96
+ credits: { kind: "balance", balance: 12.84, spend: 0.31 }
97
+ };
98
+ expect(laneParts(status, 25)).toEqual({ branch: false, dirty: false, spend: true });
99
+ expect(laneParts(status, 24)).toEqual({ branch: false, dirty: false, spend: false });
100
+ });
101
+ });
102
+ describe("statusRowFit", () => {
103
+ const status = { ...state.status, model: "dexto/anthropic/claude-sonnet-4.5" };
104
+ it("reserves the lane and lets the model truncate", () => {
105
+ expect(statusRowFit(status, 42, 0)).toEqual({ notice: 0, model: 22, lane: 18 });
106
+ });
107
+ it("hides the model rather than show a stub", () => {
108
+ expect(statusRowFit(status, 42, 17)).toEqual({ notice: 17, model: 0, lane: 23 });
109
+ });
110
+ it("truncates a long notice rather than the lane", () => {
111
+ expect(statusRowFit(status, 42, 23)).toEqual({ notice: 22, model: 0, lane: 18 });
112
+ });
113
+ it("hides the notice when a stub is all that fits", () => {
114
+ expect(statusRowFit(status, 22, 12)).toEqual({ notice: 0, model: 0, lane: 22 });
115
+ });
116
+ it("gives the lane whatever the model leaves", () => {
117
+ expect(statusRowFit(state.status, 120, 0)).toEqual({ notice: 0, model: 21, lane: 97 });
118
+ });
119
+ });
120
+ describe("formatTokens", () => {
121
+ it("reads like 46k, 1.2M and 850", () => {
122
+ expect(formatTokens(46e3)).toBe("46k");
123
+ expect(formatTokens(12e5)).toBe("1.2M");
124
+ expect(formatTokens(850)).toBe("850");
125
+ });
126
+ });
127
+ describe("Deck", () => {
128
+ let saved;
129
+ beforeEach(() => {
130
+ saved = getCaps();
131
+ setCaps({ ...saved, color: "none", glyphs: "unicode", motion: "reduced" });
132
+ });
133
+ afterEach(() => setCaps(saved));
134
+ it("is four rows at 120 columns, with the status block beside the trace", async () => {
135
+ const out = await frame(deck(), 120);
136
+ const lines = out.split("\n");
137
+ expect(lines).toHaveLength(4);
138
+ expect(lines[0]).toMatch(/STREAMING · 84 tok\/s · 12\.4s\s*$/);
139
+ expect(lines[1]).toMatch(/dexto\/sonnet-5\.5\s+46k\/200k\s*$/);
140
+ expect(lines[2]).toMatch(/◇ local ⎇ main ±3 · ◆ \$12\.84\s*$/);
141
+ expect(lines[3]).toBe("\u203A ask");
142
+ });
143
+ it("moves the status to a compact row under the input below 100 columns", async () => {
144
+ const out = await frame(deck(), 78);
145
+ const lines = out.split("\n");
146
+ expect(lines).toHaveLength(5);
147
+ expect(lines[0]).toMatch(/STREAMING · 84 tok\/s · 12\.4s\s*$/);
148
+ expect(lines[3]).toBe("\u203A ask");
149
+ expect(lines[4]).toMatch(/^dexto\/sonnet-5\.5\s+46k\s+◇ local ⎇ main ±3 · ◆ \$12\.84/);
150
+ });
151
+ it("drops the wordmark below 44 columns and keeps the trace", async () => {
152
+ const out = await frame(deck(), 42);
153
+ const lines = out.split("\n");
154
+ expect(lines).toHaveLength(4);
155
+ expect(out).not.toContain("dexto ");
156
+ expect(lines[0]).toMatch(/[▁-█]/);
157
+ expect(lines[2]).toBe("\u203A ask");
158
+ expect(lines[3]).toMatch(/^84 tok\/s · 12\.4s\s+46k\s+◇ local · ◆ \$12\.84$/);
159
+ });
160
+ it("keeps the readout, and so the permission mode, in the middle step", async () => {
161
+ const out = await frame(deck({ ...state, mode: "idle", readout: "plan mode" }), 78);
162
+ expect(out.split("\n")[0]).toMatch(/READY · plan mode\s*$/);
163
+ });
164
+ it("leads the bare status row with the readout and never cuts the lane", async () => {
165
+ const long = {
166
+ ...state,
167
+ mode: "idle",
168
+ readout: "auto-approve",
169
+ status: { ...state.status, model: "dexto/anthropic/claude-sonnet-4.5" }
170
+ };
171
+ const row = (await frame(deck(long), 42)).split("\n")[3] ?? "";
172
+ expect(row).toMatch(/^auto-approve\s+46k\s+◇ local · ◆ \$12\.84$/);
173
+ const plain = (await frame(deck({ ...long, readout: null }), 42)).split("\n")[3] ?? "";
174
+ expect(plain).toMatch(/^dexto\/anthropic.*…\s+46k\s+◇ local · ◆ \$12\.84$/);
175
+ });
176
+ it("keeps the lane whole beside a notice too long to fit", async () => {
177
+ const long = { ...state, mode: "idle", readout: "auto-approve \xB7 r:medium" };
178
+ const row = (await frame(deck(long), 42)).split("\n")[3] ?? "";
179
+ expect(row).toMatch(/^auto-approve · r:medi…\s+◇ local · ◆ \$12\.84$/);
180
+ });
181
+ it("draws only the input when collapsed, leaving it mounted", async () => {
182
+ const collapsed = createElement(Deck, {
183
+ state,
184
+ collapsed: true,
185
+ paused: false,
186
+ children: createElement(Text, null, "INPUT")
187
+ });
188
+ expect(await frame(collapsed, 120)).toBe("INPUT");
189
+ });
190
+ it("keeps context use visible beside a long model id", async () => {
191
+ const long = {
192
+ ...state,
193
+ status: { ...state.status, model: "anthropic/claude-sonnet-4-5-20250929" }
194
+ };
195
+ const lines = (await frame(deck(long), 120)).split("\n");
196
+ expect(lines[1]).toMatch(/anthropic\/claude-\S*…\s+46k\/200k\s*$/);
197
+ });
198
+ it("slots a gate between the band and the input", async () => {
199
+ const out = await frame(deck(state, createElement(Text, null, "GATE")), 120);
200
+ const lines = out.split("\n");
201
+ expect(lines[3]).toBe("GATE");
202
+ expect(lines[4]).toBe("\u203A ask");
203
+ });
204
+ it("says when you are signed out, out of credits, or on a cloud computer", async () => {
205
+ const signedOut = await frame(
206
+ deck({ ...state, status: { ...state.status, credits: { kind: "signed-out" } } }),
207
+ 120
208
+ );
209
+ expect(signedOut).toContain("\xB7 cloud off");
210
+ const loading = await frame(
211
+ deck({ ...state, status: { ...state.status, credits: { kind: "signed-in" } } }),
212
+ 120
213
+ );
214
+ expect(loading).toMatch(/◇ local ⎇ main ±3 · ◆\s*$/m);
215
+ const out = await frame(
216
+ deck({ ...state, status: { ...state.status, credits: { kind: "out" } } }),
217
+ 120
218
+ );
219
+ expect(out).toContain("out of credits");
220
+ const cloud = await frame(
221
+ deck({
222
+ ...state,
223
+ status: { ...state.status, where: { kind: "computer", name: "dx-7f3a" } }
224
+ }),
225
+ 120
226
+ );
227
+ expect(cloud).toContain("\u25C6 dx-7f3a");
228
+ });
229
+ it("leaves out what it does not know", async () => {
230
+ const out = await frame(
231
+ deck({
232
+ mode: "idle",
233
+ readout: null,
234
+ status: {
235
+ ...state.status,
236
+ model: "gpt-5",
237
+ contextUsedTokens: null,
238
+ contextMaxTokens: null,
239
+ branch: null,
240
+ dirtyFiles: 0
241
+ }
242
+ }),
243
+ 120
244
+ );
245
+ const lines = out.split("\n");
246
+ expect(lines[0]).toMatch(/READY\s*$/);
247
+ expect(lines[1]).toMatch(/gpt-5\s*$/);
248
+ expect(lines[2]).toMatch(/◇ local · ◆ \$12\.84\s*$/);
249
+ });
250
+ it("falls back to ASCII glyphs", async () => {
251
+ setCaps({ ...getCaps(), glyphs: "ascii" });
252
+ const out = await frame(deck(), 120);
253
+ expect(out).toContain("o local @ main +3 . * $12.84");
254
+ expect(out).not.toMatch(/[▁-█◇◆⎇]/);
255
+ });
256
+ });
257
+ describe("Deck trace clock", () => {
258
+ let saved;
259
+ beforeEach(() => {
260
+ saved = getCaps();
261
+ setCaps({ ...saved, color: "none", glyphs: "unicode", motion: "full" });
262
+ });
263
+ afterEach(() => setCaps(saved));
264
+ async function framesOver(s, ms, paused = false) {
265
+ const { stdout, writes } = recordingStdout(120);
266
+ const view = render(deck(s, null, paused), {
267
+ stdout,
268
+ debug: true,
269
+ patchConsole: false,
270
+ exitOnCtrlC: false
271
+ });
272
+ await new Promise((resolve) => setTimeout(resolve, 50));
273
+ const settled = writes.length;
274
+ await new Promise((resolve) => setTimeout(resolve, ms));
275
+ const written = writes.length - settled;
276
+ view.unmount();
277
+ return written;
278
+ }
279
+ it("scrolls while the agent works", async () => {
280
+ expect(await framesOver(state, 350)).toBeGreaterThanOrEqual(2);
281
+ });
282
+ it("holds trace and wordmark still while paused for copy mode", async () => {
283
+ expect(await framesOver({ ...state, mode: "think" }, 350, true)).toBe(0);
284
+ });
285
+ it("writes nothing while the session sits idle", async () => {
286
+ expect(await framesOver({ ...state, mode: "idle", readout: null }, 350)).toBe(0);
287
+ });
288
+ });