@alumbwe/anvil 1.0.0 → 1.0.2

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 (530) hide show
  1. package/bin/anvil.js +2 -0
  2. package/dist/bundled.js +79559 -0
  3. package/dist/bundled.js.map +581 -0
  4. package/package.json +7 -4
  5. package/bin/anvil +0 -2
  6. package/src/__tests__/README.md +0 -256
  7. package/src/__tests__/bash-mode.test.ts +0 -442
  8. package/src/__tests__/cli-args.test.ts +0 -181
  9. package/src/__tests__/cli-harness.test.ts +0 -52
  10. package/src/__tests__/e2e/first-time-login.test.ts +0 -173
  11. package/src/__tests__/e2e/logout-relogin-flow.test.ts +0 -110
  12. package/src/__tests__/e2e/returning-user-auth.test.ts +0 -113
  13. package/src/__tests__/e2e-cli.test.ts +0 -183
  14. package/src/__tests__/helpers/launcher-disconnect-fixture.cjs +0 -176
  15. package/src/__tests__/helpers/mock-api-client.ts +0 -64
  16. package/src/__tests__/helpers/renderer-cleanup-fixture.tsx +0 -89
  17. package/src/__tests__/helpers/terminal-watchdog-fixture.ts +0 -75
  18. package/src/__tests__/home-directory-detection.test.ts +0 -213
  19. package/src/__tests__/integration/api-integration.test.ts +0 -288
  20. package/src/__tests__/integration/credentials-storage.test.ts +0 -486
  21. package/src/__tests__/integration/local-agents.test.ts +0 -1187
  22. package/src/__tests__/integration/login-flow-instrumentation.test.ts +0 -134
  23. package/src/__tests__/integration/login-polling-working.test.ts +0 -285
  24. package/src/__tests__/integration/queue-editing.test.tsx +0 -261
  25. package/src/__tests__/integration/usage-refresh-on-completion.test.ts +0 -168
  26. package/src/__tests__/integration-tmux.test.ts +0 -188
  27. package/src/__tests__/launcher-avx2-fallback.test.ts +0 -630
  28. package/src/__tests__/launcher-disconnect.test.ts +0 -104
  29. package/src/__tests__/mocks/hover-toggle-controller.ts +0 -71
  30. package/src/__tests__/open-tui-native-bundle.test.ts +0 -378
  31. package/src/__tests__/path-completion.test.ts +0 -243
  32. package/src/__tests__/project-files-chat-id.test.ts +0 -34
  33. package/src/__tests__/release/proxy-http-get.test.ts +0 -667
  34. package/src/__tests__/release/wrapper-safety.test.ts +0 -412
  35. package/src/__tests__/renderer-cleanup.test.ts +0 -174
  36. package/src/__tests__/rerender-perf.integration.test.ts +0 -283
  37. package/src/__tests__/terminal-reset-sequences.test.ts +0 -36
  38. package/src/__tests__/terminal-watchdog.test.ts +0 -388
  39. package/src/__tests__/test-utils.ts +0 -271
  40. package/src/__tests__/tmux-poc.ts +0 -150
  41. package/src/__tests__/unit/agent-mode-toggle.test.ts +0 -137
  42. package/src/__tests__/unit/copy-button.test.ts +0 -157
  43. package/src/__tests__/unit/create-run-config.test.ts +0 -66
  44. package/src/__tests__/unit/publish-confirmation.test.ts +0 -70
  45. package/src/__tests__/unit/segmented-control.test.ts +0 -152
  46. package/src/__tests__/utils/env.test.ts +0 -169
  47. package/src/__tests__/utils/project-picker.test.ts +0 -39
  48. package/src/agents/bundled-agents.generated.d.ts +0 -14
  49. package/src/agents/bundled-agents.generated.ts +0 -3692
  50. package/src/app.tsx +0 -399
  51. package/src/chat.tsx +0 -1698
  52. package/src/cli-args.ts +0 -134
  53. package/src/commands/__tests__/bash-command.test.ts +0 -445
  54. package/src/commands/__tests__/command-args.test.ts +0 -349
  55. package/src/commands/__tests__/copy-conversation-clipboard.test.ts +0 -108
  56. package/src/commands/__tests__/copy-conversation.test.ts +0 -226
  57. package/src/commands/__tests__/diagnostics-command.test.ts +0 -35
  58. package/src/commands/__tests__/freebuff-command-aliases.test.ts +0 -56
  59. package/src/commands/__tests__/image.test.ts +0 -99
  60. package/src/commands/__tests__/init.test.ts +0 -456
  61. package/src/commands/__tests__/new-command-rotates-chat.test.ts +0 -91
  62. package/src/commands/__tests__/process-diagnostics.test.ts +0 -54
  63. package/src/commands/__tests__/prompt-builders.test.ts +0 -28
  64. package/src/commands/__tests__/router-input.test.ts +0 -298
  65. package/src/commands/ads.ts +0 -44
  66. package/src/commands/command-registry.ts +0 -726
  67. package/src/commands/copy-conversation.ts +0 -392
  68. package/src/commands/help.ts +0 -13
  69. package/src/commands/image.ts +0 -20
  70. package/src/commands/init.ts +0 -121
  71. package/src/commands/process-diagnostics.ts +0 -120
  72. package/src/commands/prompt-builders.ts +0 -100
  73. package/src/commands/publish.ts +0 -203
  74. package/src/commands/router-utils.ts +0 -80
  75. package/src/commands/router.ts +0 -487
  76. package/src/commands/usage.ts +0 -26
  77. package/src/components/__tests__/ad-banner.test.tsx +0 -83
  78. package/src/components/__tests__/chat-input-bar.test.tsx +0 -130
  79. package/src/components/__tests__/freebuff-landing-heading-row.test.tsx +0 -91
  80. package/src/components/__tests__/freebuff-model-selector.test.tsx +0 -519
  81. package/src/components/__tests__/freebuff-offer-invariants.test.ts +0 -54
  82. package/src/components/__tests__/freebuff-takeover-prompt.test.tsx +0 -212
  83. package/src/components/__tests__/grid-layout.integration.test.tsx +0 -304
  84. package/src/components/__tests__/grid-layout.test.tsx +0 -1051
  85. package/src/components/__tests__/message-block.completion.test.tsx +0 -104
  86. package/src/components/__tests__/message-block.streaming.test.tsx +0 -78
  87. package/src/components/__tests__/message-with-agents.test.tsx +0 -579
  88. package/src/components/__tests__/multiline-input.test.tsx +0 -1132
  89. package/src/components/__tests__/queue-panel.test.tsx +0 -398
  90. package/src/components/__tests__/selectable-list.test.ts +0 -232
  91. package/src/components/__tests__/status-bar.test.tsx +0 -44
  92. package/src/components/__tests__/status-indicator.test.tsx +0 -204
  93. package/src/components/__tests__/terminal-thinking-orb.test.tsx +0 -111
  94. package/src/components/__tests__/user-error-banner.test.tsx +0 -102
  95. package/src/components/ad-banner.tsx +0 -323
  96. package/src/components/agent-checklist.tsx +0 -350
  97. package/src/components/agent-mode-toggle.tsx +0 -241
  98. package/src/components/anvil-mark.tsx +0 -52
  99. package/src/components/ask-user/__tests__/multiple-choice-form.test.ts +0 -432
  100. package/src/components/ask-user/__tests__/validation.test.ts +0 -213
  101. package/src/components/ask-user/components/accordion-question.tsx +0 -153
  102. package/src/components/ask-user/components/custom-answer-input.tsx +0 -66
  103. package/src/components/ask-user/components/options-list.tsx +0 -133
  104. package/src/components/ask-user/components/question-header.tsx +0 -80
  105. package/src/components/ask-user/components/question-option.tsx +0 -89
  106. package/src/components/ask-user/constants.ts +0 -38
  107. package/src/components/ask-user/index.tsx +0 -631
  108. package/src/components/ask-user/utils/validation.ts +0 -85
  109. package/src/components/attachment-card.tsx +0 -65
  110. package/src/components/blocks/agent-block-grid.tsx +0 -58
  111. package/src/components/blocks/agent-branch-item.tsx +0 -311
  112. package/src/components/blocks/agent-branch-wrapper.tsx +0 -493
  113. package/src/components/blocks/agent-list-branch.tsx +0 -77
  114. package/src/components/blocks/ask-user-branch.tsx +0 -81
  115. package/src/components/blocks/block-helpers.ts +0 -11
  116. package/src/components/blocks/blocks-renderer.tsx +0 -289
  117. package/src/components/blocks/content-with-markdown.tsx +0 -33
  118. package/src/components/blocks/image-block.tsx +0 -128
  119. package/src/components/blocks/implementor-row.tsx +0 -429
  120. package/src/components/blocks/single-block.tsx +0 -201
  121. package/src/components/blocks/thinking-block.tsx +0 -67
  122. package/src/components/blocks/tool-block-group.tsx +0 -57
  123. package/src/components/blocks/tool-branch.tsx +0 -206
  124. package/src/components/blocks/user-content-copy.tsx +0 -157
  125. package/src/components/bottom-banner.tsx +0 -136
  126. package/src/components/build-mode-buttons.tsx +0 -110
  127. package/src/components/button.tsx +0 -66
  128. package/src/components/chat-header.tsx +0 -77
  129. package/src/components/chat-history-screen.tsx +0 -413
  130. package/src/components/chat-input-bar.tsx +0 -523
  131. package/src/components/clickable-title-box.tsx +0 -66
  132. package/src/components/clickable.tsx +0 -119
  133. package/src/components/collapse-button.tsx +0 -34
  134. package/src/components/copy-button.tsx +0 -203
  135. package/src/components/elapsed-timer.tsx +0 -55
  136. package/src/components/error-boundary.tsx +0 -55
  137. package/src/components/feedback-container.tsx +0 -181
  138. package/src/components/feedback-icon-button.tsx +0 -89
  139. package/src/components/feedback-input-mode.tsx +0 -344
  140. package/src/components/file-attachment-card.tsx +0 -98
  141. package/src/components/freebuff-active-session-summary.tsx +0 -63
  142. package/src/components/freebuff-landing-screen.tsx +0 -865
  143. package/src/components/freebuff-model-selector.tsx +0 -1087
  144. package/src/components/freebuff-referral-banner.tsx +0 -604
  145. package/src/components/freebuff-superseded-screen.tsx +0 -62
  146. package/src/components/grid-layout.tsx +0 -80
  147. package/src/components/help-banner.tsx +0 -127
  148. package/src/components/highlighted-text.tsx +0 -52
  149. package/src/components/image-card.tsx +0 -167
  150. package/src/components/image-thumbnail.tsx +0 -114
  151. package/src/components/input-cursor.tsx +0 -77
  152. package/src/components/input-mode-banner.tsx +0 -57
  153. package/src/components/load-previous-button.tsx +0 -48
  154. package/src/components/login-modal.tsx +0 -475
  155. package/src/components/message-block.tsx +0 -346
  156. package/src/components/message-footer.tsx +0 -258
  157. package/src/components/message-with-agents.tsx +0 -506
  158. package/src/components/mode-divider.tsx +0 -43
  159. package/src/components/multiline-input.tsx +0 -1241
  160. package/src/components/out-of-credits-banner.tsx +0 -160
  161. package/src/components/pending-attachments-banner.tsx +0 -116
  162. package/src/components/pending-bash-message.tsx +0 -59
  163. package/src/components/progress-bar.tsx +0 -81
  164. package/src/components/project-picker-screen.tsx +0 -485
  165. package/src/components/publish-confirmation.tsx +0 -493
  166. package/src/components/publish-container.tsx +0 -687
  167. package/src/components/queue-panel.tsx +0 -310
  168. package/src/components/raised-pill.tsx +0 -95
  169. package/src/components/renderers/plan-box.tsx +0 -59
  170. package/src/components/review-screen.tsx +0 -112
  171. package/src/components/scroll-to-bottom-button.tsx +0 -34
  172. package/src/components/segmented-control.tsx +0 -187
  173. package/src/components/selectable-list.tsx +0 -248
  174. package/src/components/selected-chips.tsx +0 -80
  175. package/src/components/separator.tsx +0 -40
  176. package/src/components/session-ended-banner.tsx +0 -226
  177. package/src/components/shimmer-text.tsx +0 -248
  178. package/src/components/status-bar.tsx +0 -313
  179. package/src/components/subscription-limit-banner.tsx +0 -206
  180. package/src/components/suggested-prompts.tsx +0 -184
  181. package/src/components/suggestion-menu.tsx +0 -215
  182. package/src/components/terminal-command-display.tsx +0 -151
  183. package/src/components/terminal-link.tsx +0 -97
  184. package/src/components/terminal-thinking-orb.tsx +0 -95
  185. package/src/components/text-attachment-card.tsx +0 -77
  186. package/src/components/thinking.tsx +0 -109
  187. package/src/components/tools/__tests__/apply-patch.test.tsx +0 -84
  188. package/src/components/tools/__tests__/code-search.test.tsx +0 -45
  189. package/src/components/tools/__tests__/gravity-index.test.ts +0 -76
  190. package/src/components/tools/__tests__/render-ui.test.tsx +0 -92
  191. package/src/components/tools/__tests__/run-terminal-command.test.ts +0 -233
  192. package/src/components/tools/apply-patch.tsx +0 -95
  193. package/src/components/tools/code-search.tsx +0 -45
  194. package/src/components/tools/composio.tsx +0 -152
  195. package/src/components/tools/diff-viewer.tsx +0 -76
  196. package/src/components/tools/glob.tsx +0 -61
  197. package/src/components/tools/gravity-index.tsx +0 -77
  198. package/src/components/tools/list-directory.tsx +0 -61
  199. package/src/components/tools/read-docs.tsx +0 -37
  200. package/src/components/tools/read-files.tsx +0 -91
  201. package/src/components/tools/read-subtree.tsx +0 -44
  202. package/src/components/tools/read-url.tsx +0 -33
  203. package/src/components/tools/registry.ts +0 -126
  204. package/src/components/tools/render-ui.tsx +0 -122
  205. package/src/components/tools/run-terminal-command.tsx +0 -79
  206. package/src/components/tools/skill.tsx +0 -29
  207. package/src/components/tools/str-replace.tsx +0 -77
  208. package/src/components/tools/suggest-followups.tsx +0 -369
  209. package/src/components/tools/task-completed.tsx +0 -16
  210. package/src/components/tools/tool-call-item.tsx +0 -273
  211. package/src/components/tools/types.ts +0 -55
  212. package/src/components/tools/web-search.tsx +0 -33
  213. package/src/components/tools/write-file.tsx +0 -16
  214. package/src/components/tools/write-todos.tsx +0 -95
  215. package/src/components/top-banner.tsx +0 -178
  216. package/src/components/usage-banner.tsx +0 -244
  217. package/src/components/user-error-banner.tsx +0 -56
  218. package/src/components/validation-error-popover.tsx +0 -192
  219. package/src/contexts/__tests__/chat-runtime-context.test.tsx +0 -149
  220. package/src/contexts/chat-runtime-context.tsx +0 -240
  221. package/src/data/slash-commands.test.ts +0 -24
  222. package/src/data/slash-commands.ts +0 -249
  223. package/src/entry.ts +0 -12
  224. package/src/hooks/__tests__/holds-live-freebuff-slot.test.ts +0 -49
  225. package/src/hooks/__tests__/session-fetch-signal.test.ts +0 -63
  226. package/src/hooks/__tests__/use-activity-query.test.ts +0 -1000
  227. package/src/hooks/__tests__/use-ask-user-bridge.test.ts +0 -176
  228. package/src/hooks/__tests__/use-auth-query.test.ts +0 -21
  229. package/src/hooks/__tests__/use-chat-input-remount.test.tsx +0 -66
  230. package/src/hooks/__tests__/use-clipboard.test.tsx +0 -73
  231. package/src/hooks/__tests__/use-connection-status.test.ts +0 -112
  232. package/src/hooks/__tests__/use-directory-browser.test.ts +0 -203
  233. package/src/hooks/__tests__/use-gravity-ad.test.ts +0 -73
  234. package/src/hooks/__tests__/use-grid-layout.test.ts +0 -349
  235. package/src/hooks/__tests__/use-input-history.test.ts +0 -699
  236. package/src/hooks/__tests__/use-message-queue-editing.test.tsx +0 -209
  237. package/src/hooks/__tests__/use-message-queue.test.tsx +0 -71
  238. package/src/hooks/__tests__/use-path-tab-completion.test.ts +0 -315
  239. package/src/hooks/__tests__/use-queue-controls.test.ts +0 -68
  240. package/src/hooks/__tests__/use-queue-ui.test.tsx +0 -83
  241. package/src/hooks/__tests__/use-searchable-list.test.ts +0 -359
  242. package/src/hooks/__tests__/use-send-message-timer.test.ts +0 -146
  243. package/src/hooks/__tests__/use-suggestion-engine-mention.test.ts +0 -361
  244. package/src/hooks/__tests__/use-suggestion-engine.test.ts +0 -485
  245. package/src/hooks/__tests__/use-terminal-focus.test.ts +0 -66
  246. package/src/hooks/__tests__/use-terminal-layout.test.ts +0 -675
  247. package/src/hooks/__tests__/use-timeout.test.ts +0 -330
  248. package/src/hooks/__tests__/use-usage-query.test.ts +0 -502
  249. package/src/hooks/__tests__/use-user-details-query.test.ts +0 -195
  250. package/src/hooks/helpers/__tests__/send-message.test.ts +0 -1918
  251. package/src/hooks/helpers/send-message.ts +0 -654
  252. package/src/hooks/stream-state.ts +0 -83
  253. package/src/hooks/use-activity-query.ts +0 -668
  254. package/src/hooks/use-agent-validation.ts +0 -74
  255. package/src/hooks/use-ask-user-bridge.ts +0 -92
  256. package/src/hooks/use-auth-query.ts +0 -253
  257. package/src/hooks/use-auth-state.ts +0 -152
  258. package/src/hooks/use-chat-input.ts +0 -105
  259. package/src/hooks/use-chat-keyboard.ts +0 -321
  260. package/src/hooks/use-chat-messages.ts +0 -254
  261. package/src/hooks/use-chat-state.ts +0 -165
  262. package/src/hooks/use-chat-streaming.ts +0 -180
  263. package/src/hooks/use-chat-ui.ts +0 -131
  264. package/src/hooks/use-clipboard.ts +0 -151
  265. package/src/hooks/use-connection-status.ts +0 -142
  266. package/src/hooks/use-directory-browser.ts +0 -88
  267. package/src/hooks/use-elapsed-time.ts +0 -116
  268. package/src/hooks/use-event.ts +0 -34
  269. package/src/hooks/use-exit-handler.ts +0 -66
  270. package/src/hooks/use-fetch-login-url.ts +0 -65
  271. package/src/hooks/use-fingerprint.ts +0 -61
  272. package/src/hooks/use-freebuff-ctrl-c-exit.ts +0 -23
  273. package/src/hooks/use-freebuff-session-progress.ts +0 -34
  274. package/src/hooks/use-freebuff-session.ts +0 -806
  275. package/src/hooks/use-freebuff-streak-query.ts +0 -61
  276. package/src/hooks/use-gravity-ad.ts +0 -656
  277. package/src/hooks/use-grid-layout.ts +0 -73
  278. package/src/hooks/use-input-history.ts +0 -173
  279. package/src/hooks/use-login-keyboard-handlers.ts +0 -75
  280. package/src/hooks/use-login-polling.ts +0 -114
  281. package/src/hooks/use-logo.tsx +0 -161
  282. package/src/hooks/use-message-queue.ts +0 -387
  283. package/src/hooks/use-now.ts +0 -20
  284. package/src/hooks/use-path-tab-completion.ts +0 -88
  285. package/src/hooks/use-publish-mutation.ts +0 -60
  286. package/src/hooks/use-queue-controls.ts +0 -68
  287. package/src/hooks/use-queue-ui.ts +0 -74
  288. package/src/hooks/use-scroll-management.ts +0 -184
  289. package/src/hooks/use-searchable-list.ts +0 -98
  290. package/src/hooks/use-send-message.ts +0 -773
  291. package/src/hooks/use-sheen-animation.tsx +0 -88
  292. package/src/hooks/use-subscription-query.ts +0 -71
  293. package/src/hooks/use-suggestion-engine.ts +0 -783
  294. package/src/hooks/use-terminal-breakpoints.ts +0 -77
  295. package/src/hooks/use-terminal-dimensions.ts +0 -46
  296. package/src/hooks/use-terminal-focus.ts +0 -29
  297. package/src/hooks/use-terminal-layout.ts +0 -189
  298. package/src/hooks/use-theme.tsx +0 -140
  299. package/src/hooks/use-timeout.ts +0 -85
  300. package/src/hooks/use-update-preference.ts +0 -66
  301. package/src/hooks/use-usage-monitor.ts +0 -55
  302. package/src/hooks/use-usage-query.ts +0 -124
  303. package/src/hooks/use-user-details-query.ts +0 -93
  304. package/src/hooks/use-why-did-you-update.ts +0 -177
  305. package/src/index.tsx +0 -441
  306. package/src/init/__tests__/init-direnv.test.ts +0 -526
  307. package/src/init/init-app.ts +0 -34
  308. package/src/init/init-direnv.ts +0 -133
  309. package/src/login/constants.ts +0 -60
  310. package/src/login/login-flow.ts +0 -204
  311. package/src/login/plain-login.ts +0 -108
  312. package/src/login/utils.ts +0 -183
  313. package/src/native/ripgrep.ts +0 -80
  314. package/src/polyfills/bun-strip-ansi.ts +0 -12
  315. package/src/pre-init/tree-sitter-wasm.ts +0 -96
  316. package/src/project-files.ts +0 -102
  317. package/src/smoke/terminal-command-broker.ts +0 -439
  318. package/src/state/__tests__/chat-store-focus.test.ts +0 -22
  319. package/src/state/__tests__/feedback-store.test.ts +0 -257
  320. package/src/state/chat-history-store.ts +0 -30
  321. package/src/state/chat-store.ts +0 -544
  322. package/src/state/feedback-store.ts +0 -160
  323. package/src/state/freebuff-model-store.ts +0 -42
  324. package/src/state/freebuff-session-store.ts +0 -53
  325. package/src/state/login-store.ts +0 -150
  326. package/src/state/message-block-store.ts +0 -149
  327. package/src/state/publish-store.ts +0 -146
  328. package/src/state/queue-panel-store.ts +0 -26
  329. package/src/state/review-store.ts +0 -24
  330. package/src/testing/env.ts +0 -46
  331. package/src/types/chat-state.ts +0 -15
  332. package/src/types/chat.ts +0 -241
  333. package/src/types/contracts/send-message.ts +0 -12
  334. package/src/types/env.ts +0 -98
  335. package/src/types/freebuff-session.ts +0 -17
  336. package/src/types/function-params.ts +0 -28
  337. package/src/types/react19-compat.d.ts +0 -19
  338. package/src/types/store.ts +0 -111
  339. package/src/types/theme-system.ts +0 -144
  340. package/src/types/utils.ts +0 -3
  341. package/src/utils/__tests__/active-run.test.ts +0 -140
  342. package/src/utils/__tests__/activity-tracker.test.ts +0 -440
  343. package/src/utils/__tests__/agent-display.test.ts +0 -139
  344. package/src/utils/__tests__/analytics-client.test.ts +0 -262
  345. package/src/utils/__tests__/anonymous-id.test.ts +0 -74
  346. package/src/utils/__tests__/anvil-api.test.ts +0 -578
  347. package/src/utils/__tests__/arrays.test.ts +0 -264
  348. package/src/utils/__tests__/bash-context-processor.test.ts +0 -38
  349. package/src/utils/__tests__/block-processor.test.ts +0 -810
  350. package/src/utils/__tests__/chat-history.test.ts +0 -203
  351. package/src/utils/__tests__/chat-input-key-intercept.test.ts +0 -40
  352. package/src/utils/__tests__/chat-meta.test.ts +0 -130
  353. package/src/utils/__tests__/clipboard-linux.test.ts +0 -359
  354. package/src/utils/__tests__/clipboard.test.ts +0 -910
  355. package/src/utils/__tests__/code-search-summary.test.ts +0 -84
  356. package/src/utils/__tests__/collapse-helpers.test.ts +0 -1109
  357. package/src/utils/__tests__/error-handling.test.ts +0 -658
  358. package/src/utils/__tests__/exit-cleanly.test.ts +0 -110
  359. package/src/utils/__tests__/feedback-helpers.test.ts +0 -444
  360. package/src/utils/__tests__/feedback-submission.test.ts +0 -26
  361. package/src/utils/__tests__/fetch-usage.test.ts +0 -355
  362. package/src/utils/__tests__/fingerprint.test.ts +0 -144
  363. package/src/utils/__tests__/fixtures/terminal-command-broker-child.ts +0 -7
  364. package/src/utils/__tests__/fixtures/terminal-command-broker-entry.ts +0 -3
  365. package/src/utils/__tests__/fixtures/terminal-command-broker-owner.ts +0 -33
  366. package/src/utils/__tests__/format-elapsed-time.test.ts +0 -103
  367. package/src/utils/__tests__/format-timeout.test.ts +0 -87
  368. package/src/utils/__tests__/freebuff-instance-owner.test.ts +0 -69
  369. package/src/utils/__tests__/freebuff-model-navigation.test.ts +0 -102
  370. package/src/utils/__tests__/freebuff-premium-reset.test.ts +0 -79
  371. package/src/utils/__tests__/freebuff-referral-cache.test.ts +0 -116
  372. package/src/utils/__tests__/freebuff-session-api.test.ts +0 -215
  373. package/src/utils/__tests__/freebuff-session-display.test.ts +0 -23
  374. package/src/utils/__tests__/freebuff-streak-line.test.ts +0 -217
  375. package/src/utils/__tests__/image-dimensions.test.ts +0 -249
  376. package/src/utils/__tests__/image-processor.test.ts +0 -209
  377. package/src/utils/__tests__/implementor-helpers.test.ts +0 -1458
  378. package/src/utils/__tests__/keyboard-actions.test.ts +0 -660
  379. package/src/utils/__tests__/layout-helpers.test.ts +0 -36
  380. package/src/utils/__tests__/lazy-response-ads.test.ts +0 -167
  381. package/src/utils/__tests__/log-shipper.test.ts +0 -53
  382. package/src/utils/__tests__/markdown-renderer.test.tsx +0 -421
  383. package/src/utils/__tests__/message-block-helpers.test.ts +0 -1263
  384. package/src/utils/__tests__/message-updater.test.ts +0 -645
  385. package/src/utils/__tests__/osc-timeout-scenarios.test.ts +0 -172
  386. package/src/utils/__tests__/pending-attachments.test.ts +0 -277
  387. package/src/utils/__tests__/polling-backoff.test.ts +0 -51
  388. package/src/utils/__tests__/queue-panel-actions.test.ts +0 -148
  389. package/src/utils/__tests__/run-state-storage.test.ts +0 -919
  390. package/src/utils/__tests__/safe-json.test.ts +0 -77
  391. package/src/utils/__tests__/sdk-event-handlers.test.ts +0 -685
  392. package/src/utils/__tests__/send-message-helpers.test.ts +0 -1898
  393. package/src/utils/__tests__/send-message-timer.test.ts +0 -64
  394. package/src/utils/__tests__/settings.test.ts +0 -99
  395. package/src/utils/__tests__/strings.test.ts +0 -192
  396. package/src/utils/__tests__/terminal-color-detection.test.ts +0 -425
  397. package/src/utils/__tests__/terminal-command-broker.test.ts +0 -528
  398. package/src/utils/__tests__/terminal-enter-detection.test.ts +0 -77
  399. package/src/utils/__tests__/terminal-io.test.ts +0 -137
  400. package/src/utils/__tests__/terminal-protocol-controller.test.ts +0 -119
  401. package/src/utils/__tests__/text-layout.test.ts +0 -82
  402. package/src/utils/__tests__/theme-platform-detection.test.ts +0 -125
  403. package/src/utils/__tests__/think-tag-parser.test.ts +0 -159
  404. package/src/utils/__tests__/trace-writer.test.ts +0 -223
  405. package/src/utils/__tests__/trim-chat-logs.test.ts +0 -78
  406. package/src/utils/__tests__/usage-banner-state.test.ts +0 -298
  407. package/src/utils/__tests__/validation-error-formatting.test.ts +0 -126
  408. package/src/utils/__tests__/windows-terminal-health.test.ts +0 -101
  409. package/src/utils/__tests__/write-file-atomic.test.ts +0 -127
  410. package/src/utils/active-run.ts +0 -131
  411. package/src/utils/activity-tracker.ts +0 -66
  412. package/src/utils/agent-display.ts +0 -87
  413. package/src/utils/agent-helpers.ts +0 -27
  414. package/src/utils/agent-id-utils.ts +0 -14
  415. package/src/utils/ai-message-id.ts +0 -12
  416. package/src/utils/analytics.ts +0 -361
  417. package/src/utils/anonymous-id.ts +0 -87
  418. package/src/utils/anvil-api.ts +0 -612
  419. package/src/utils/anvil-client.ts +0 -217
  420. package/src/utils/arrays.ts +0 -117
  421. package/src/utils/auth.ts +0 -258
  422. package/src/utils/bash-context-processor.ts +0 -47
  423. package/src/utils/bash-messages.ts +0 -108
  424. package/src/utils/block-margins.ts +0 -35
  425. package/src/utils/block-operations.ts +0 -523
  426. package/src/utils/block-processor.ts +0 -213
  427. package/src/utils/chat-history.ts +0 -253
  428. package/src/utils/chat-input-key-intercept.ts +0 -52
  429. package/src/utils/chat-meta.ts +0 -90
  430. package/src/utils/chat-scroll-accel.ts +0 -151
  431. package/src/utils/clipboard-image.ts +0 -588
  432. package/src/utils/clipboard.ts +0 -397
  433. package/src/utils/code-search-summary.ts +0 -70
  434. package/src/utils/collapse-helpers.ts +0 -256
  435. package/src/utils/config-dir.ts +0 -24
  436. package/src/utils/constants.ts +0 -190
  437. package/src/utils/create-event-handler-state.ts +0 -73
  438. package/src/utils/create-run-config.ts +0 -121
  439. package/src/utils/detect-shell.ts +0 -116
  440. package/src/utils/directory-browser.ts +0 -72
  441. package/src/utils/engagement.ts +0 -55
  442. package/src/utils/env.ts +0 -92
  443. package/src/utils/error-handling.ts +0 -255
  444. package/src/utils/error-messages.ts +0 -62
  445. package/src/utils/exit-cleanly.ts +0 -86
  446. package/src/utils/feedback-helpers.ts +0 -103
  447. package/src/utils/feedback-submission.ts +0 -22
  448. package/src/utils/fetch-usage.ts +0 -76
  449. package/src/utils/fingerprint.ts +0 -245
  450. package/src/utils/format-elapsed-time.ts +0 -33
  451. package/src/utils/format-session-units.ts +0 -6
  452. package/src/utils/format-timeout.ts +0 -28
  453. package/src/utils/format-validation-errors-for-message.ts +0 -84
  454. package/src/utils/freebuff-agent-selection.ts +0 -33
  455. package/src/utils/freebuff-instance-owner.ts +0 -66
  456. package/src/utils/freebuff-model-navigation.ts +0 -50
  457. package/src/utils/freebuff-premium-reset.ts +0 -55
  458. package/src/utils/freebuff-referral-cache.ts +0 -51
  459. package/src/utils/freebuff-session-api.ts +0 -243
  460. package/src/utils/freebuff-session-display.ts +0 -21
  461. package/src/utils/freebuff-streak-line.ts +0 -93
  462. package/src/utils/git.ts +0 -17
  463. package/src/utils/helpers.ts +0 -47
  464. package/src/utils/image-display.ts +0 -67
  465. package/src/utils/image-handler.ts +0 -325
  466. package/src/utils/image-processor.ts +0 -133
  467. package/src/utils/image-thumbnail.ts +0 -78
  468. package/src/utils/implementor-helpers.ts +0 -787
  469. package/src/utils/input-modes.ts +0 -174
  470. package/src/utils/keyboard-actions.ts +0 -392
  471. package/src/utils/keypad-keys.ts +0 -47
  472. package/src/utils/layout-helpers.ts +0 -33
  473. package/src/utils/lazy-response-ads.ts +0 -1
  474. package/src/utils/local-agent-registry.ts +0 -474
  475. package/src/utils/log-shipper.ts +0 -126
  476. package/src/utils/logger.ts +0 -327
  477. package/src/utils/markdown-renderer.tsx +0 -1090
  478. package/src/utils/math.ts +0 -3
  479. package/src/utils/message-block-helpers.ts +0 -684
  480. package/src/utils/message-history.ts +0 -143
  481. package/src/utils/message-tree-utils.ts +0 -67
  482. package/src/utils/message-updater.ts +0 -279
  483. package/src/utils/open-file.ts +0 -146
  484. package/src/utils/open-url.ts +0 -63
  485. package/src/utils/path-completion.ts +0 -111
  486. package/src/utils/path-helpers.ts +0 -38
  487. package/src/utils/pending-attachments.ts +0 -360
  488. package/src/utils/polling-backoff.ts +0 -59
  489. package/src/utils/project-picker.ts +0 -12
  490. package/src/utils/queue-panel-actions.ts +0 -70
  491. package/src/utils/recent-projects.ts +0 -156
  492. package/src/utils/renderer-cleanup.ts +0 -233
  493. package/src/utils/response-ad-positions.ts +0 -1
  494. package/src/utils/run-state-storage.ts +0 -603
  495. package/src/utils/safe-json.ts +0 -153
  496. package/src/utils/sdk-event-handlers.ts +0 -571
  497. package/src/utils/send-message-helpers.ts +0 -210
  498. package/src/utils/send-message-timer.ts +0 -110
  499. package/src/utils/settings.ts +0 -226
  500. package/src/utils/skill-registry.ts +0 -94
  501. package/src/utils/spawn-agent-matcher.ts +0 -55
  502. package/src/utils/status-indicator-state.ts +0 -107
  503. package/src/utils/stream-chunk-processor.ts +0 -57
  504. package/src/utils/strings.ts +0 -271
  505. package/src/utils/subscription.ts +0 -31
  506. package/src/utils/syntax-highlighter.tsx +0 -19
  507. package/src/utils/terminal-color-detection.ts +0 -474
  508. package/src/utils/terminal-command-broker.ts +0 -467
  509. package/src/utils/terminal-enter-detection.ts +0 -63
  510. package/src/utils/terminal-images.ts +0 -229
  511. package/src/utils/terminal-io.ts +0 -85
  512. package/src/utils/terminal-protocol-controller.ts +0 -173
  513. package/src/utils/terminal-reset-sequences.ts +0 -33
  514. package/src/utils/terminal-title.ts +0 -84
  515. package/src/utils/terminal-watchdog.ts +0 -366
  516. package/src/utils/text-layout.ts +0 -149
  517. package/src/utils/theme-config.ts +0 -141
  518. package/src/utils/theme-system.ts +0 -1206
  519. package/src/utils/think-tag-parser.ts +0 -95
  520. package/src/utils/time-format.ts +0 -21
  521. package/src/utils/trace-writer.ts +0 -162
  522. package/src/utils/ui-constants.ts +0 -69
  523. package/src/utils/update-checker.ts +0 -110
  524. package/src/utils/usage-banner-state.ts +0 -146
  525. package/src/utils/validation-error-formatting.ts +0 -86
  526. package/src/utils/validation-error-helpers.ts +0 -19
  527. package/src/utils/windows-terminal-health.ts +0 -124
  528. package/src/utils/word-wrap-utils.ts +0 -53
  529. package/src/utils/write-file-atomic.ts +0 -54
  530. package/src/utils/yield-to-event-loop.ts +0 -9
@@ -1,96 +0,0 @@
1
- // Find tree-sitter.wasm so the SDK's tree-sitter parser singleton can load
2
- // it at runtime. Must be the very first import in `index.tsx`: subsequent
3
- // imports (the SDK / code-map) eagerly construct the parser, and its init
4
- // reads what we publish here on `globalThis` and via the env var.
5
- //
6
- // Final approach after several attempts to embed the wasm into the bun
7
- // --compile binary all failed on Windows (the bytes ended up in the
8
- // binary, but every JS-level retrieval mechanism — `with { type: 'file' }`
9
- // import binding, base64 string literals, chunked base64 in a generated
10
- // module, function-export wrappers — was either tree-shaken, transformed
11
- // by the minifier, or otherwise stripped):
12
- //
13
- // ship tree-sitter.wasm as a sibling file next to the binary.
14
- //
15
- // It's 200KB, the npm tarball already contains the binary; adding one
16
- // more file is trivial. The build script copies the wasm into `cli/bin/`
17
- // after compile, the release workflow tarballs both, and the freebuff /
18
- // anvil downloader extracts both into the same directory. At runtime,
19
- // `process.execPath` plus a relative file lookup gets us the wasm with
20
- // zero bundler involvement.
21
-
22
- import { existsSync, readFileSync } from 'fs'
23
- import { dirname, isAbsolute, join, resolve } from 'path'
24
-
25
- // Where to look for the sibling tree-sitter.wasm. We can't just use
26
- // `dirname(process.execPath)`: at pre-init time inside a bun --compile
27
- // binary on Windows, `process.execPath` returns the *bunfs* internal
28
- // path (`B:\~BUN\root\<binary>.exe`) rather than the on-disk path of
29
- // the .exe the user invoked. By the time main() runs it switches to
30
- // the disk path, but pre-init has long since bailed out.
31
- //
32
- // Try several sources in order; the first whose sibling .wasm exists
33
- // wins. argv[0] is normally the path the binary was invoked with —
34
- // always a real disk path, never bunfs. execPath is kept as a fallback
35
- // for environments where argv[0] is something exotic.
36
- const candidates = (
37
- [process.argv[0], process.execPath] as Array<string | undefined>
38
- )
39
- .filter((p): p is string => typeof p === 'string' && p.length > 0)
40
- .map((p) => (isAbsolute(p) ? p : resolve(p)))
41
- .map((p) => join(dirname(p), 'tree-sitter.wasm'))
42
-
43
- const siblingPath = candidates.find((p) => existsSync(p))
44
-
45
- // Pre-init diagnostic — only fires when --smoke-tree-sitter is set so we
46
- // don't spam every run. We need to see what argv[0] / execPath looked
47
- // like at this exact phase on Windows: the round-7 main() diag showed
48
- // disk paths, but pre-init silently bailed, meaning module-init time
49
- // gives different values. argv[0] alone wasn't enough to fix it.
50
- if (process.argv.includes('--smoke-tree-sitter')) {
51
- console.error(
52
- `[pre-init diag] argv[0]=${process.argv[0]}\n` +
53
- `[pre-init diag] execPath=${process.execPath}\n` +
54
- `[pre-init diag] candidates=${JSON.stringify(candidates)}\n` +
55
- `[pre-init diag] resolved siblingPath=${siblingPath ?? '<none>'}\n`,
56
- )
57
- }
58
-
59
- if (siblingPath) {
60
- // Tell init-node.ts (in code-map / the SDK bundle) where the wasm
61
- // is. The locateFile callback there will hand this path to
62
- // emscripten, which fs.readFile's it.
63
- process.env.ANVIL_TREE_SITTER_WASM_PATH = siblingPath
64
-
65
- // Also publish on globalThis so the smoke handler in index.tsx can
66
- // read it without touching process.env (which is gated by the env
67
- // architecture check outside the allowlisted pre-init files).
68
- ;(
69
- globalThis as { __ANVIL_TREE_SITTER_WASM_PATH__?: string }
70
- ).__ANVIL_TREE_SITTER_WASM_PATH__ = siblingPath
71
-
72
- // Also try the synchronous-bytes path: hand the bytes straight to
73
- // Parser.init({ wasmBinary }) so the SDK doesn't need to round-trip
74
- // through emscripten's path resolution. Both channels feed the same
75
- // tree-sitter init; whichever one trips first wins.
76
- try {
77
- const buf = readFileSync(siblingPath)
78
- ;(
79
- globalThis as { __ANVIL_TREE_SITTER_WASM_BINARY__?: Uint8Array }
80
- ).__ANVIL_TREE_SITTER_WASM_BINARY__ = new Uint8Array(
81
- buf.buffer,
82
- buf.byteOffset,
83
- buf.byteLength,
84
- )
85
- } catch (err) {
86
- console.error(
87
- '[tree-sitter pre-init] readFileSync failed for sibling wasm at',
88
- siblingPath,
89
- '—',
90
- err instanceof Error ? err.message : String(err),
91
- )
92
- }
93
- }
94
-
95
- // `--smoke-tree-sitter` is the deterministic CI gate. The handler lives at
96
- // the top of main() in cli/src/index.tsx (before parseArgs).
@@ -1,102 +0,0 @@
1
- import { mkdirSync, readdirSync, statSync } from 'fs'
2
- import path from 'path'
3
-
4
- import { getConfigDir } from './utils/auth'
5
-
6
- let projectRoot: string | undefined
7
- let currentChatId: string | undefined
8
-
9
- function ensureChatDirectory(dir: string) {
10
- mkdirSync(dir, { recursive: true })
11
- }
12
-
13
- export function setProjectRoot(dir: string) {
14
- projectRoot = dir
15
- return projectRoot
16
- }
17
-
18
- export function getProjectRoot() {
19
- if (!projectRoot) {
20
- throw new Error('Project root not set')
21
- }
22
- return projectRoot
23
- }
24
-
25
- export function tryGetProjectRoot() {
26
- return projectRoot
27
- }
28
-
29
- export function getCurrentChatId() {
30
- if (!currentChatId) {
31
- currentChatId = new Date().toISOString().replace(/:/g, '-')
32
- }
33
- return currentChatId
34
- }
35
-
36
- export function setCurrentChatId(chatId: string) {
37
- currentChatId = chatId
38
- return currentChatId
39
- }
40
-
41
- export function startNewChat() {
42
- currentChatId = new Date().toISOString().replace(/:/g, '-')
43
- return currentChatId
44
- }
45
-
46
- // Get the project-specific data directory
47
- export function getProjectDataDir(): string {
48
- const root = getProjectRoot()
49
- if (!root) {
50
- throw new Error('Project root not set')
51
- }
52
-
53
- const baseName = path.basename(root)
54
- const baseDir = path.join(getConfigDir(), 'projects', baseName)
55
-
56
- return baseDir
57
- }
58
-
59
- /**
60
- * Find the most recent chat directory based on modification time
61
- * Returns null if no chat directories exist
62
- */
63
- export function getMostRecentChatDir(): string | null {
64
- try {
65
- const chatsDir = path.join(getProjectDataDir(), 'chats')
66
- if (!statSync(chatsDir, { throwIfNoEntry: false })) {
67
- return null
68
- }
69
-
70
- const chatDirs = readdirSync(chatsDir)
71
- .map((name) => {
72
- const fullPath = path.join(chatsDir, name)
73
- try {
74
- const stat = statSync(fullPath)
75
- return { name, fullPath, mtime: stat.mtime }
76
- } catch {
77
- return null
78
- }
79
- })
80
- .filter(
81
- (item): item is { name: string; fullPath: string; mtime: Date } =>
82
- item !== null && statSync(item.fullPath).isDirectory(),
83
- )
84
-
85
- if (chatDirs.length === 0) {
86
- return null
87
- }
88
-
89
- // Sort by modification time, most recent first
90
- chatDirs.sort((a, b) => b.mtime.getTime() - a.mtime.getTime())
91
- return chatDirs[0].fullPath
92
- } catch {
93
- return null
94
- }
95
- }
96
-
97
- export function getCurrentChatDir(): string {
98
- const chatId = getCurrentChatId()
99
- const dir = path.join(getProjectDataDir(), 'chats', chatId)
100
- ensureChatDirectory(dir)
101
- return dir
102
- }
@@ -1,439 +0,0 @@
1
- import { runTerminalCommand } from '@anvil/sdk'
2
- import { createCliRenderer } from '@opentui/core'
3
- import { existsSync, mkdirSync, writeFileSync } from 'fs'
4
- import path from 'path'
5
-
6
- import { installProcessCleanupHandlers } from '../utils/renderer-cleanup'
7
- import { startTerminalWatchdog } from '../utils/terminal-watchdog'
8
- import {
9
- createTerminalCommandBroker,
10
- terminalCommandBroker,
11
- } from '../utils/terminal-command-broker'
12
- import { installTerminalProtocolController } from '../utils/terminal-protocol-controller'
13
- import { writeTerminalControlSync } from '../utils/terminal-io'
14
-
15
- import type { CliRenderer } from '@opentui/core'
16
- import type { AnvilToolOutput } from '@anvil/sdk'
17
-
18
- const WAIT_INTERVAL_MS = 25
19
-
20
- type TerminalResult =
21
- AnvilToolOutput<'run_terminal_command'>[number]['value']
22
-
23
- type SmokeResult = {
24
- ok: boolean
25
- platform: NodeJS.Platform
26
- stdinIsTTY: boolean
27
- stdoutIsTTY: boolean
28
- simpleCommand?: { stdout: string; stderr: string; exitCode: number | null }
29
- repeatedCommands?: { completed: number }
30
- overlap?: {
31
- focusStates: boolean[]
32
- controlWrites: string[]
33
- mouseStayedEnabledDuringOverlap: boolean
34
- mouseStayedEnabledAfterCancellation: boolean
35
- mouseStayedEnabledAfterCompletion: boolean
36
- firstCancellationMessage: string
37
- secondStdout: string
38
- consoleReaderStdout: string
39
- }
40
- brokerFailure?: { message: string; commandStarted: boolean }
41
- error?: string
42
- stack?: string
43
- }
44
-
45
- function assertSmoke(condition: unknown, message: string): asserts condition {
46
- if (!condition) throw new Error(message)
47
- }
48
-
49
- function shellQuote(value: string): string {
50
- return `'${value.replace(/'/g, `'\\''`)}'`
51
- }
52
-
53
- function toBashPath(value: string): string {
54
- return value.replace(/\\/g, '/')
55
- }
56
-
57
- function asTerminalResult(
58
- output: AnvilToolOutput<'run_terminal_command'>,
59
- ): TerminalResult {
60
- assertSmoke(output.length === 1, 'terminal command returned no result')
61
- return output[0].value
62
- }
63
-
64
- function readString(value: TerminalResult, key: 'stdout' | 'stderr'): string {
65
- if (key === 'stdout') {
66
- return 'stdout' in value && typeof value.stdout === 'string'
67
- ? value.stdout
68
- : ''
69
- }
70
- return 'stderr' in value && typeof value.stderr === 'string'
71
- ? value.stderr
72
- : ''
73
- }
74
-
75
- function readExitCode(value: TerminalResult): number | null {
76
- return 'exitCode' in value && typeof value.exitCode === 'number'
77
- ? value.exitCode
78
- : null
79
- }
80
-
81
- function readMessage(value: TerminalResult): string {
82
- return 'message' in value && typeof value.message === 'string'
83
- ? value.message
84
- : ''
85
- }
86
-
87
- async function waitFor(
88
- condition: () => boolean,
89
- timeoutMs: number,
90
- failureMessage: string,
91
- ): Promise<void> {
92
- const deadline = Date.now() + timeoutMs
93
- while (!condition()) {
94
- if (Date.now() >= deadline) throw new Error(failureMessage)
95
- await Bun.sleep(WAIT_INTERVAL_MS)
96
- }
97
- }
98
-
99
- function writeResult(resultPath: string, result: SmokeResult): void {
100
- mkdirSync(path.dirname(resultPath), { recursive: true })
101
- writeFileSync(resultPath, JSON.stringify(result, null, 2))
102
- }
103
-
104
- async function destroyRenderer(renderer: CliRenderer): Promise<void> {
105
- if (renderer.isDestroyed) return
106
- await new Promise<void>((resolve, reject) => {
107
- const onDestroy = () => {
108
- clearTimeout(timeout)
109
- resolve()
110
- }
111
- const timeout = setTimeout(() => {
112
- renderer.removeListener('destroy', onDestroy)
113
- renderer.isDestroyed
114
- ? resolve()
115
- : reject(new Error('OpenTUI renderer did not finish destroying'))
116
- }, 2_000)
117
- renderer.once('destroy', onDestroy)
118
- renderer.destroy()
119
- })
120
- }
121
-
122
- /**
123
- * `markerPath` is written before the CONIN$ probe so the harness knows the descendant is alive and
124
- * can start injecting terminal reports for a leaked console to pick up. It cannot also stand for
125
- * "the probe finished" — it is written while the outcome is still unknown.
126
- *
127
- * `verdictPath` is written once the probe has resolved, down both branches, and is what makes the
128
- * abort deterministic. Waiting a fixed interval after the ready marker instead raced PowerShell's
129
- * startup on a loaded runner and aborted before the verdict reached stdout.
130
- *
131
- * The flush is load-bearing: the broker force-kills on Windows (`taskkill /f`), so a line still
132
- * sitting in PowerShell's own buffer is lost outright rather than drained from the pipe.
133
- */
134
- function createConsoleReaderScript(
135
- markerPath: string,
136
- verdictPath: string,
137
- ): string {
138
- const quotedMarker = markerPath.replace(/'/g, "''")
139
- const quotedVerdict = verdictPath.replace(/'/g, "''")
140
- return [
141
- `$ErrorActionPreference = 'Stop'`,
142
- `[System.IO.File]::WriteAllText('${quotedMarker}', 'ready')`,
143
- `try {`,
144
- ` $stream = [System.IO.File]::Open('CONIN$', [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)`,
145
- ` $buffer = New-Object byte[] 4096`,
146
- ` $count = $stream.Read($buffer, 0, $buffer.Length)`,
147
- ` if ($count -gt 0) {`,
148
- ` $hex = [System.BitConverter]::ToString($buffer, 0, $count).Replace('-', '')`,
149
- ` [Console]::Out.WriteLine('CONSOLE_LEAK_HEX:' + $hex)`,
150
- ` }`,
151
- `} catch {`,
152
- ` [Console]::Out.WriteLine('CONSOLE_UNAVAILABLE')`,
153
- `}`,
154
- `[Console]::Out.Flush()`,
155
- `[System.IO.File]::WriteAllText('${quotedVerdict}', 'done')`,
156
- `Start-Sleep -Seconds 20`,
157
- ].join('\r\n')
158
- }
159
-
160
- export async function runPackagedTerminalBrokerSmoke({
161
- resultPath,
162
- exchangeDir,
163
- }: {
164
- resultPath: string
165
- exchangeDir: string
166
- }): Promise<number> {
167
- const result: SmokeResult = {
168
- ok: false,
169
- platform: process.platform,
170
- stdinIsTTY: Boolean(process.stdin.isTTY),
171
- stdoutIsTTY: Boolean(process.stdout.isTTY),
172
- }
173
- let renderer: CliRenderer | null = null
174
-
175
- try {
176
- assertSmoke(process.platform === 'win32', 'broker smoke requires Windows')
177
- assertSmoke(
178
- process.stdin.isTTY && process.stdout.isTTY,
179
- 'broker smoke requires a native Windows console',
180
- )
181
-
182
- mkdirSync(exchangeDir, { recursive: true })
183
- const harnessReadyPath = path.join(exchangeDir, 'broker-ready')
184
- const reportsSentPath = path.join(exchangeDir, 'reports-sent')
185
- const consoleReaderReadyPath = path.join(
186
- exchangeDir,
187
- 'console-reader-ready',
188
- )
189
- const consoleReaderVerdictPath = path.join(
190
- exchangeDir,
191
- 'console-reader-verdict',
192
- )
193
- const consoleReaderScriptPath = path.join(exchangeDir, 'console-reader.ps1')
194
- const forbiddenSpawnPath = path.join(exchangeDir, 'broker-failure-spawned')
195
- writeFileSync(
196
- consoleReaderScriptPath,
197
- createConsoleReaderScript(
198
- consoleReaderReadyPath,
199
- consoleReaderVerdictPath,
200
- ),
201
- )
202
-
203
- startTerminalWatchdog()
204
- renderer = await createCliRenderer({
205
- backgroundColor: 'transparent',
206
- exitOnCtrlC: false,
207
- screenMode: 'alternate-screen',
208
- })
209
- installProcessCleanupHandlers(renderer)
210
-
211
- const controlWrites: string[] = []
212
- const controller = installTerminalProtocolController(renderer, {
213
- writeControl: (sequence) => {
214
- controlWrites.push(sequence)
215
- return writeTerminalControlSync(sequence)
216
- },
217
- })
218
- renderer.once('destroy', () => controller.dispose())
219
- const focusStates: boolean[] = []
220
- const unsubscribeFocus = controller.subscribeToFocus({
221
- onFocusChange: (focused) => focusStates.push(focused),
222
- })
223
-
224
- const simple = asTerminalResult(
225
- await runTerminalCommand({
226
- command: `printf 'COMMAND_OK'; printf 'COMMAND_ERR' >&2`,
227
- process_type: 'SYNC',
228
- cwd: process.cwd(),
229
- timeout_seconds: 10,
230
- terminalCommandBroker,
231
- }),
232
- )
233
- const simpleStdout = readString(simple, 'stdout')
234
- const simpleStderr = readString(simple, 'stderr')
235
- const simpleExitCode = readExitCode(simple)
236
- assertSmoke(simpleStdout === 'COMMAND_OK', 'simple command stdout was lost')
237
- assertSmoke(
238
- simpleStderr === 'COMMAND_ERR',
239
- 'simple command stderr was lost',
240
- )
241
- assertSmoke(
242
- simpleExitCode === 0,
243
- 'simple command did not exit successfully',
244
- )
245
- result.simpleCommand = {
246
- stdout: simpleStdout,
247
- stderr: simpleStderr,
248
- exitCode: simpleExitCode,
249
- }
250
-
251
- const overlapWriteStart = controlWrites.length
252
- const firstAbort = new AbortController()
253
- const readerCommand =
254
- `powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File ` +
255
- shellQuote(toBashPath(consoleReaderScriptPath))
256
- const firstRun = runTerminalCommand({
257
- command: readerCommand,
258
- process_type: 'SYNC',
259
- cwd: process.cwd(),
260
- timeout_seconds: 30,
261
- signal: firstAbort.signal,
262
- terminalCommandBroker,
263
- })
264
- const secondRun = runTerminalCommand({
265
- command: `sleep 5; printf 'SECOND_DONE'`,
266
- process_type: 'SYNC',
267
- cwd: process.cwd(),
268
- timeout_seconds: 15,
269
- terminalCommandBroker,
270
- })
271
-
272
- const mouseStayedEnabledDuringOverlap = renderer.useMouse === true
273
- assertSmoke(
274
- mouseStayedEnabledDuringOverlap,
275
- 'brokers changed mouse reporting',
276
- )
277
- assertSmoke(
278
- controlWrites.length === overlapWriteStart,
279
- 'brokers changed focus reporting',
280
- )
281
- await waitFor(
282
- () => existsSync(consoleReaderReadyPath),
283
- 10_000,
284
- 'console reader descendant did not start',
285
- )
286
- writeFileSync(harnessReadyPath, 'ready')
287
- await waitFor(
288
- () => existsSync(reportsSentPath),
289
- 10_000,
290
- 'native Windows harness did not inject terminal reports',
291
- )
292
- await waitFor(
293
- () => focusStates.includes(false) && focusStates.includes(true),
294
- 5_000,
295
- 'OpenTUI did not receive focus activity while commands ran',
296
- )
297
- // Only abort once the descendant has actually resolved its CONIN$ probe and flushed the
298
- // verdict. This sits after the reports-sent wait deliberately: a descendant that DID inherit a
299
- // console is blocked in $stream.Read until those reports arrive, and only then writes its leak
300
- // line and the verdict. A descendant with no console fails File.Open immediately, so if the
301
- // verdict never lands the open must have succeeded — which is itself the leak this asserts
302
- // against, hence the wording below rather than a bare timeout.
303
- // 10s to match the waits above, and because the abort has a real budget: the script exits on
304
- // its own after Start-Sleep -Seconds 20 and firstRun times out at 30, either of which would
305
- // turn the cancellation assertion below into a confusing failure. In practice the verdict is
306
- // already on disk by the time this runs — a console-free open throws at once.
307
- await waitFor(
308
- () => existsSync(consoleReaderVerdictPath),
309
- 10_000,
310
- 'console reader never resolved its CONIN$ probe — an open that blocks instead of failing means the descendant did have a Windows console',
311
- )
312
-
313
- firstAbort.abort()
314
- const first = asTerminalResult(await firstRun)
315
- const firstCancellationMessage = readMessage(first)
316
- assertSmoke(
317
- firstCancellationMessage.includes('aborted by the user'),
318
- 'first overlapping command did not report cancellation',
319
- )
320
- const mouseStayedEnabledAfterCancellation = renderer.useMouse === true
321
- assertSmoke(
322
- mouseStayedEnabledAfterCancellation,
323
- 'broker cancellation changed mouse reporting',
324
- )
325
-
326
- const second = asTerminalResult(await secondRun)
327
- const secondStdout = readString(second, 'stdout')
328
- assertSmoke(secondStdout === 'SECOND_DONE', 'overlapping command was lost')
329
- const mouseStayedEnabledAfterCompletion = renderer.useMouse === true
330
- const overlapWrites = controlWrites.slice(overlapWriteStart)
331
- assertSmoke(
332
- overlapWrites.length === 0,
333
- 'completion changed focus reporting',
334
- )
335
-
336
- const consoleReaderStdout = readString(first, 'stdout')
337
- assertSmoke(
338
- !consoleReaderStdout.includes('CONSOLE_LEAK_HEX:'),
339
- 'a command descendant read terminal reports from CONIN$',
340
- )
341
- assertSmoke(
342
- consoleReaderStdout.includes('CONSOLE_UNAVAILABLE'),
343
- 'the command descendant still had a Windows console',
344
- )
345
- result.overlap = {
346
- focusStates,
347
- controlWrites: overlapWrites,
348
- mouseStayedEnabledDuringOverlap,
349
- mouseStayedEnabledAfterCancellation,
350
- mouseStayedEnabledAfterCompletion,
351
- firstCancellationMessage,
352
- secondStdout,
353
- consoleReaderStdout,
354
- }
355
-
356
- // The Windows failure that motivated this gate appeared only after users
357
- // had run several agent commands. Exercise repeated packaged-broker stdio
358
- // setup after the driver has completed its time-sensitive report injection.
359
- const repeatedCommandCount = 64
360
- for (let index = 0; index < repeatedCommandCount; index++) {
361
- const marker = `REPEATED_${index}`
362
- const repeated = asTerminalResult(
363
- await runTerminalCommand({
364
- command: `printf '${marker}'`,
365
- process_type: 'SYNC',
366
- cwd: process.cwd(),
367
- timeout_seconds: 10,
368
- terminalCommandBroker,
369
- }),
370
- )
371
- assertSmoke(
372
- readString(repeated, 'stdout') === marker,
373
- `repeated broker command ${index} lost its output`,
374
- )
375
- assertSmoke(
376
- readExitCode(repeated) === 0,
377
- `repeated broker command ${index} failed`,
378
- )
379
- }
380
- result.repeatedCommands = { completed: repeatedCommandCount }
381
-
382
- let failureMessage = ''
383
- try {
384
- await runTerminalCommand({
385
- command: `printf 'spawned' > ${shellQuote(toBashPath(forbiddenSpawnPath))}`,
386
- process_type: 'SYNC',
387
- cwd: process.cwd(),
388
- timeout_seconds: 10,
389
- terminalCommandBroker: createTerminalCommandBroker({
390
- invocation: () => ({
391
- executable: path.join(
392
- exchangeDir,
393
- `missing-terminal-broker-${crypto.randomUUID()}.exe`,
394
- ),
395
- args: [],
396
- }),
397
- }),
398
- })
399
- throw new Error('command unexpectedly started without its broker')
400
- } catch (error) {
401
- failureMessage = error instanceof Error ? error.message : String(error)
402
- }
403
- result.brokerFailure = {
404
- message: failureMessage,
405
- commandStarted: existsSync(forbiddenSpawnPath),
406
- }
407
- assertSmoke(
408
- failureMessage.includes('Restart Freebuff'),
409
- 'broker failure did not include actionable recovery guidance',
410
- )
411
- assertSmoke(
412
- !existsSync(forbiddenSpawnPath),
413
- 'command spawned after broker startup failed',
414
- )
415
-
416
- unsubscribeFocus()
417
- controller.dispose()
418
- await destroyRenderer(renderer)
419
- result.ok = true
420
- writeResult(resultPath, result)
421
- return 0
422
- } catch (error) {
423
- result.error = error instanceof Error ? error.message : String(error)
424
- if (error instanceof Error && error.stack) result.stack = error.stack
425
- if (renderer && !renderer.isDestroyed) {
426
- try {
427
- await destroyRenderer(renderer)
428
- } catch (cleanupError) {
429
- result.error += `; cleanup failed: ${errorMessage(cleanupError)}`
430
- }
431
- }
432
- writeResult(resultPath, result)
433
- return 1
434
- }
435
- }
436
-
437
- function errorMessage(error: unknown): string {
438
- return error instanceof Error ? error.message : String(error)
439
- }
@@ -1,22 +0,0 @@
1
- import { afterEach, describe, expect, test } from 'bun:test'
2
-
3
- import { useChatStore } from '../chat-store'
4
-
5
- afterEach(() => {
6
- const store = useChatStore.getState()
7
- store.setInputFocused(true)
8
- store.setIsFocusSupported(false)
9
- })
10
-
11
- describe('chat store focus state', () => {
12
- test('chat reset preserves terminal focus and detected capabilities', () => {
13
- const store = useChatStore.getState()
14
- store.setInputFocused(false)
15
- store.setIsFocusSupported(true)
16
-
17
- store.reset()
18
-
19
- expect(useChatStore.getState().inputFocused).toBe(false)
20
- expect(useChatStore.getState().isFocusSupported).toBe(true)
21
- })
22
- })