@machina.ai/cell-cli 1.10.0-rc1 → 1.13.0-rc1

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 (813) hide show
  1. package/dist/index.js +5 -5
  2. package/dist/index.js.map +1 -1
  3. package/dist/package.json +14 -12
  4. package/dist/src/commands/extensions/disable.d.ts +1 -1
  5. package/dist/src/commands/extensions/disable.js +19 -8
  6. package/dist/src/commands/extensions/disable.js.map +1 -1
  7. package/dist/src/commands/extensions/enable.d.ts +1 -1
  8. package/dist/src/commands/extensions/enable.js +19 -9
  9. package/dist/src/commands/extensions/enable.js.map +1 -1
  10. package/dist/src/commands/extensions/examples/mcp-server/example.js +46 -0
  11. package/dist/src/commands/extensions/examples/mcp-server/example.js.map +1 -0
  12. package/dist/src/commands/extensions/install.d.ts +1 -0
  13. package/dist/src/commands/extensions/install.js +29 -4
  14. package/dist/src/commands/extensions/install.js.map +1 -1
  15. package/dist/src/commands/extensions/install.test.js +39 -19
  16. package/dist/src/commands/extensions/install.test.js.map +1 -1
  17. package/dist/src/commands/extensions/link.js +16 -4
  18. package/dist/src/commands/extensions/link.js.map +1 -1
  19. package/dist/src/commands/extensions/list.js +17 -6
  20. package/dist/src/commands/extensions/list.js.map +1 -1
  21. package/dist/src/commands/extensions/new.js +14 -20
  22. package/dist/src/commands/extensions/new.js.map +1 -1
  23. package/dist/src/commands/extensions/uninstall.js +16 -4
  24. package/dist/src/commands/extensions/uninstall.js.map +1 -1
  25. package/dist/src/commands/extensions/update.js +28 -23
  26. package/dist/src/commands/extensions/update.js.map +1 -1
  27. package/dist/src/commands/extensions/validate.d.ts +12 -0
  28. package/dist/src/commands/extensions/validate.js +83 -0
  29. package/dist/src/commands/extensions/validate.js.map +1 -0
  30. package/dist/src/commands/extensions/validate.test.d.ts +6 -0
  31. package/dist/src/commands/extensions/validate.test.js +93 -0
  32. package/dist/src/commands/extensions/validate.test.js.map +1 -0
  33. package/dist/src/commands/extensions.js +3 -0
  34. package/dist/src/commands/extensions.js.map +1 -1
  35. package/dist/src/commands/mcp/add.js +7 -4
  36. package/dist/src/commands/mcp/add.js.map +1 -1
  37. package/dist/src/commands/mcp/add.test.d.ts +6 -0
  38. package/dist/src/commands/mcp/add.test.js +247 -0
  39. package/dist/src/commands/mcp/add.test.js.map +1 -0
  40. package/dist/src/commands/mcp/list.js +18 -9
  41. package/dist/src/commands/mcp/list.js.map +1 -1
  42. package/dist/src/commands/mcp/list.test.d.ts +6 -0
  43. package/dist/src/commands/mcp/list.test.js +128 -0
  44. package/dist/src/commands/mcp/list.test.js.map +1 -0
  45. package/dist/src/commands/mcp/remove.js +3 -2
  46. package/dist/src/commands/mcp/remove.js.map +1 -1
  47. package/dist/src/commands/mcp/remove.test.d.ts +6 -0
  48. package/dist/src/commands/mcp/remove.test.js +175 -0
  49. package/dist/src/commands/mcp/remove.test.js.map +1 -0
  50. package/dist/src/commands/mcp.test.d.ts +6 -0
  51. package/dist/src/commands/mcp.test.js +62 -0
  52. package/dist/src/commands/mcp.test.js.map +1 -0
  53. package/dist/src/config/auth.js +0 -3
  54. package/dist/src/config/auth.js.map +1 -1
  55. package/dist/src/config/config.d.ts +6 -15
  56. package/dist/src/config/config.integration.test.d.ts +6 -0
  57. package/dist/src/config/config.integration.test.js +321 -0
  58. package/dist/src/config/config.integration.test.js.map +1 -0
  59. package/dist/src/config/config.js +85 -164
  60. package/dist/src/config/config.js.map +1 -1
  61. package/dist/src/config/config.test.d.ts +6 -0
  62. package/dist/src/config/config.test.js +1972 -0
  63. package/dist/src/config/config.test.js.map +1 -0
  64. package/dist/src/config/extension-manager.d.ts +63 -0
  65. package/dist/src/config/extension-manager.js +450 -0
  66. package/dist/src/config/extension-manager.js.map +1 -0
  67. package/dist/src/config/extension.d.ts +4 -61
  68. package/dist/src/config/extension.js +1 -538
  69. package/dist/src/config/extension.js.map +1 -1
  70. package/dist/src/config/extension.test.d.ts +6 -0
  71. package/dist/src/config/extension.test.js +1412 -0
  72. package/dist/src/config/extension.test.js.map +1 -0
  73. package/dist/src/config/extensions/consent.d.ts +38 -0
  74. package/dist/src/config/extensions/consent.js +123 -0
  75. package/dist/src/config/extensions/consent.js.map +1 -0
  76. package/dist/src/config/extensions/extensionEnablement.d.ts +2 -2
  77. package/dist/src/config/extensions/extensionEnablement.js +7 -5
  78. package/dist/src/config/extensions/extensionEnablement.js.map +1 -1
  79. package/dist/src/config/extensions/extensionEnablement.test.js +31 -28
  80. package/dist/src/config/extensions/extensionEnablement.test.js.map +1 -1
  81. package/dist/src/config/extensions/extensionSettings.d.ts +15 -0
  82. package/dist/src/config/extensions/extensionSettings.js +113 -0
  83. package/dist/src/config/extensions/extensionSettings.js.map +1 -0
  84. package/dist/src/config/extensions/extensionSettings.test.d.ts +6 -0
  85. package/dist/src/config/extensions/extensionSettings.test.js +254 -0
  86. package/dist/src/config/extensions/extensionSettings.test.js.map +1 -0
  87. package/dist/src/config/extensions/github.d.ts +18 -9
  88. package/dist/src/config/extensions/github.js +108 -36
  89. package/dist/src/config/extensions/github.js.map +1 -1
  90. package/dist/src/config/extensions/github.test.js +158 -164
  91. package/dist/src/config/extensions/github.test.js.map +1 -1
  92. package/dist/src/config/extensions/github_fetch.d.ts +1 -1
  93. package/dist/src/config/extensions/github_fetch.js +13 -1
  94. package/dist/src/config/extensions/github_fetch.js.map +1 -1
  95. package/dist/src/config/extensions/github_fetch.test.d.ts +6 -0
  96. package/dist/src/config/extensions/github_fetch.test.js +169 -0
  97. package/dist/src/config/extensions/github_fetch.test.js.map +1 -0
  98. package/dist/src/config/extensions/storage.d.ts +14 -0
  99. package/dist/src/config/extensions/storage.js +32 -0
  100. package/dist/src/config/extensions/storage.js.map +1 -0
  101. package/dist/src/config/extensions/update.d.ts +5 -4
  102. package/dist/src/config/extensions/update.js +41 -37
  103. package/dist/src/config/extensions/update.js.map +1 -1
  104. package/dist/src/config/extensions/update.test.js +72 -74
  105. package/dist/src/config/extensions/update.test.js.map +1 -1
  106. package/dist/src/config/extensions/variableSchema.d.ts +0 -4
  107. package/dist/src/config/extensions/variableSchema.js.map +1 -1
  108. package/dist/src/config/extensions/variables.d.ts +4 -0
  109. package/dist/src/config/extensions/variables.js +6 -0
  110. package/dist/src/config/extensions/variables.js.map +1 -1
  111. package/dist/src/config/keyBindings.d.ts +5 -1
  112. package/dist/src/config/keyBindings.js +34 -10
  113. package/dist/src/config/keyBindings.js.map +1 -1
  114. package/dist/src/config/keyBindings.test.js +17 -0
  115. package/dist/src/config/keyBindings.test.js.map +1 -1
  116. package/dist/src/config/policies/read-only.toml +56 -0
  117. package/dist/src/config/policies/write.toml +63 -0
  118. package/dist/src/config/policies/yolo.toml +31 -0
  119. package/dist/src/config/policy-engine.integration.test.js +41 -38
  120. package/dist/src/config/policy-engine.integration.test.js.map +1 -1
  121. package/dist/src/config/policy.d.ts +4 -3
  122. package/dist/src/config/policy.js +13 -142
  123. package/dist/src/config/policy.js.map +1 -1
  124. package/dist/src/config/sandboxConfig.d.ts +1 -2
  125. package/dist/src/config/sandboxConfig.js +7 -6
  126. package/dist/src/config/sandboxConfig.js.map +1 -1
  127. package/dist/src/config/settings.d.ts +2 -1
  128. package/dist/src/config/settings.js +59 -15
  129. package/dist/src/config/settings.js.map +1 -1
  130. package/dist/src/config/settings.test.d.ts +6 -0
  131. package/dist/src/config/settings.test.js +2000 -0
  132. package/dist/src/config/settings.test.js.map +1 -0
  133. package/dist/src/config/settingsSchema.d.ts +170 -28
  134. package/dist/src/config/settingsSchema.js +418 -27
  135. package/dist/src/config/settingsSchema.js.map +1 -1
  136. package/dist/src/config/settingsSchema.test.js +42 -1
  137. package/dist/src/config/settingsSchema.test.js.map +1 -1
  138. package/dist/src/config/trustedFolders.d.ts +1 -1
  139. package/dist/src/config/trustedFolders.js +4 -2
  140. package/dist/src/config/trustedFolders.js.map +1 -1
  141. package/dist/src/core/initializer.js +2 -1
  142. package/dist/src/core/initializer.js.map +1 -1
  143. package/dist/src/gemini.d.ts +1 -1
  144. package/dist/src/gemini.js +63 -27
  145. package/dist/src/gemini.js.map +1 -1
  146. package/dist/src/gemini.test.js +123 -34
  147. package/dist/src/gemini.test.js.map +1 -1
  148. package/dist/src/generated/git-commit.d.ts +2 -2
  149. package/dist/src/generated/git-commit.js +2 -2
  150. package/dist/src/nonInteractiveCli.d.ts +9 -1
  151. package/dist/src/nonInteractiveCli.js +205 -10
  152. package/dist/src/nonInteractiveCli.js.map +1 -1
  153. package/dist/src/nonInteractiveCli.test.d.ts +6 -0
  154. package/dist/src/nonInteractiveCli.test.js +984 -0
  155. package/dist/src/nonInteractiveCli.test.js.map +1 -0
  156. package/dist/src/nonInteractiveCliCommands.js +2 -2
  157. package/dist/src/nonInteractiveCliCommands.js.map +1 -1
  158. package/dist/src/services/BuiltinCommandLoader.js +4 -0
  159. package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
  160. package/dist/src/services/BuiltinCommandLoader.test.js +22 -0
  161. package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -1
  162. package/dist/src/services/CommandService.js +2 -1
  163. package/dist/src/services/CommandService.js.map +1 -1
  164. package/dist/src/services/FeedbackService.js +2 -2
  165. package/dist/src/services/FeedbackService.js.map +1 -1
  166. package/dist/src/services/FileCommandLoader.test.d.ts +6 -0
  167. package/dist/src/services/FileCommandLoader.test.js +971 -0
  168. package/dist/src/services/FileCommandLoader.test.js.map +1 -0
  169. package/dist/src/services/McpPromptLoader.js +2 -2
  170. package/dist/src/services/McpPromptLoader.js.map +1 -1
  171. package/dist/src/services/McpPromptLoader.test.js +4 -2
  172. package/dist/src/services/McpPromptLoader.test.js.map +1 -1
  173. package/dist/src/services/prompt-processors/argumentProcessor.test.d.ts +6 -0
  174. package/dist/src/services/prompt-processors/argumentProcessor.test.js +40 -0
  175. package/dist/src/services/prompt-processors/argumentProcessor.test.js.map +1 -0
  176. package/dist/src/services/prompt-processors/atFileProcessor.js +3 -2
  177. package/dist/src/services/prompt-processors/atFileProcessor.js.map +1 -1
  178. package/dist/src/services/prompt-processors/shellProcessor.test.d.ts +6 -0
  179. package/dist/src/services/prompt-processors/shellProcessor.test.js +482 -0
  180. package/dist/src/services/prompt-processors/shellProcessor.test.js.map +1 -0
  181. package/dist/src/test-utils/async.d.ts +9 -0
  182. package/dist/src/test-utils/async.js +29 -0
  183. package/dist/src/test-utils/async.js.map +1 -0
  184. package/dist/src/test-utils/createExtension.d.ts +3 -1
  185. package/dist/src/test-utils/createExtension.js +3 -3
  186. package/dist/src/test-utils/createExtension.js.map +1 -1
  187. package/dist/src/test-utils/render.d.ts +17 -2
  188. package/dist/src/test-utils/render.js +69 -4
  189. package/dist/src/test-utils/render.js.map +1 -1
  190. package/dist/src/test-utils/render.test.d.ts +6 -0
  191. package/dist/src/test-utils/render.test.js +79 -0
  192. package/dist/src/test-utils/render.test.js.map +1 -0
  193. package/dist/src/ui/App.test.d.ts +6 -0
  194. package/dist/src/ui/App.test.js +110 -0
  195. package/dist/src/ui/App.test.js.map +1 -0
  196. package/dist/src/ui/AppContainer.js +223 -92
  197. package/dist/src/ui/AppContainer.js.map +1 -1
  198. package/dist/src/ui/AppContainer.test.js +531 -147
  199. package/dist/src/ui/AppContainer.test.js.map +1 -1
  200. package/dist/src/ui/IdeIntegrationNudge.js +1 -1
  201. package/dist/src/ui/IdeIntegrationNudge.js.map +1 -1
  202. package/dist/src/ui/auth/ApiAuthDialog.d.ts +14 -0
  203. package/dist/src/ui/auth/ApiAuthDialog.js +26 -0
  204. package/dist/src/ui/auth/ApiAuthDialog.js.map +1 -0
  205. package/dist/src/ui/auth/ApiAuthDialog.test.d.ts +6 -0
  206. package/dist/src/ui/auth/ApiAuthDialog.test.js +91 -0
  207. package/dist/src/ui/auth/ApiAuthDialog.test.js.map +1 -0
  208. package/dist/src/ui/auth/AuthDialog.d.ts +1 -1
  209. package/dist/src/ui/auth/AuthDialog.js +9 -3
  210. package/dist/src/ui/auth/AuthDialog.js.map +1 -1
  211. package/dist/src/ui/auth/useAuth.d.ts +3 -1
  212. package/dist/src/ui/auth/useAuth.js +35 -4
  213. package/dist/src/ui/auth/useAuth.js.map +1 -1
  214. package/dist/src/ui/colors.js +3 -0
  215. package/dist/src/ui/colors.js.map +1 -1
  216. package/dist/src/ui/commands/aboutCommand.js +1 -1
  217. package/dist/src/ui/commands/aboutCommand.test.d.ts +6 -0
  218. package/dist/src/ui/commands/aboutCommand.test.js +130 -0
  219. package/dist/src/ui/commands/aboutCommand.test.js.map +1 -0
  220. package/dist/src/ui/commands/authCommand.js +1 -1
  221. package/dist/src/ui/commands/authCommand.test.d.ts +6 -0
  222. package/dist/src/ui/commands/authCommand.test.js +30 -0
  223. package/dist/src/ui/commands/authCommand.test.js.map +1 -0
  224. package/dist/src/ui/commands/bugCommand.js +1 -1
  225. package/dist/src/ui/commands/bugCommand.test.d.ts +6 -0
  226. package/dist/src/ui/commands/bugCommand.test.js +105 -0
  227. package/dist/src/ui/commands/bugCommand.test.js.map +1 -0
  228. package/dist/src/ui/commands/chatCommand.js +1 -1
  229. package/dist/src/ui/commands/chatCommand.js.map +1 -1
  230. package/dist/src/ui/commands/chatCommand.test.d.ts +6 -0
  231. package/dist/src/ui/commands/chatCommand.test.js +555 -0
  232. package/dist/src/ui/commands/chatCommand.test.js.map +1 -0
  233. package/dist/src/ui/commands/clearCommand.js +1 -1
  234. package/dist/src/ui/commands/clearCommand.test.d.ts +6 -0
  235. package/dist/src/ui/commands/clearCommand.test.js +76 -0
  236. package/dist/src/ui/commands/clearCommand.test.js.map +1 -0
  237. package/dist/src/ui/commands/compressCommand.js +1 -1
  238. package/dist/src/ui/commands/compressCommand.js.map +1 -1
  239. package/dist/src/ui/commands/compressCommand.test.d.ts +6 -0
  240. package/dist/src/ui/commands/compressCommand.test.js +98 -0
  241. package/dist/src/ui/commands/compressCommand.test.js.map +1 -0
  242. package/dist/src/ui/commands/copyCommand.js +2 -1
  243. package/dist/src/ui/commands/copyCommand.js.map +1 -1
  244. package/dist/src/ui/commands/copyCommand.test.d.ts +6 -0
  245. package/dist/src/ui/commands/copyCommand.test.js +242 -0
  246. package/dist/src/ui/commands/copyCommand.test.js.map +1 -0
  247. package/dist/src/ui/commands/corgiCommand.js +1 -1
  248. package/dist/src/ui/commands/corgiCommand.js.map +1 -1
  249. package/dist/src/ui/commands/corgiCommand.test.d.ts +6 -0
  250. package/dist/src/ui/commands/corgiCommand.test.js +28 -0
  251. package/dist/src/ui/commands/corgiCommand.test.js.map +1 -0
  252. package/dist/src/ui/commands/directoryCommand.js +1 -1
  253. package/dist/src/ui/commands/directoryCommand.js.map +1 -1
  254. package/dist/src/ui/commands/directoryCommand.test.d.ts +6 -0
  255. package/dist/src/ui/commands/directoryCommand.test.js +144 -0
  256. package/dist/src/ui/commands/directoryCommand.test.js.map +1 -0
  257. package/dist/src/ui/commands/docsCommand.js +1 -1
  258. package/dist/src/ui/commands/docsCommand.test.d.ts +6 -0
  259. package/dist/src/ui/commands/docsCommand.test.js +72 -0
  260. package/dist/src/ui/commands/docsCommand.test.js.map +1 -0
  261. package/dist/src/ui/commands/editorCommand.js +1 -1
  262. package/dist/src/ui/commands/editorCommand.test.d.ts +6 -0
  263. package/dist/src/ui/commands/editorCommand.test.js +27 -0
  264. package/dist/src/ui/commands/editorCommand.test.js.map +1 -0
  265. package/dist/src/ui/commands/extensionsCommand.js +64 -11
  266. package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
  267. package/dist/src/ui/commands/extensionsCommand.test.d.ts +6 -0
  268. package/dist/src/ui/commands/extensionsCommand.test.js +315 -0
  269. package/dist/src/ui/commands/extensionsCommand.test.js.map +1 -0
  270. package/dist/src/ui/commands/helpCommand.js +1 -1
  271. package/dist/src/ui/commands/helpCommand.test.d.ts +6 -0
  272. package/dist/src/ui/commands/helpCommand.test.js +42 -0
  273. package/dist/src/ui/commands/helpCommand.test.js.map +1 -0
  274. package/dist/src/ui/commands/ideCommand.js +6 -6
  275. package/dist/src/ui/commands/ideCommand.test.d.ts +6 -0
  276. package/dist/src/ui/commands/ideCommand.test.js +205 -0
  277. package/dist/src/ui/commands/ideCommand.test.js.map +1 -0
  278. package/dist/src/ui/commands/initCommand.js +1 -1
  279. package/dist/src/ui/commands/initCommand.js.map +1 -1
  280. package/dist/src/ui/commands/initCommand.test.d.ts +6 -0
  281. package/dist/src/ui/commands/initCommand.test.js +80 -0
  282. package/dist/src/ui/commands/initCommand.test.js.map +1 -0
  283. package/dist/src/ui/commands/mcpCommand.js +110 -100
  284. package/dist/src/ui/commands/mcpCommand.js.map +1 -1
  285. package/dist/src/ui/commands/mcpCommand.test.d.ts +6 -0
  286. package/dist/src/ui/commands/mcpCommand.test.js +152 -0
  287. package/dist/src/ui/commands/mcpCommand.test.js.map +1 -0
  288. package/dist/src/ui/commands/memoryCommand.js +6 -6
  289. package/dist/src/ui/commands/memoryCommand.js.map +1 -1
  290. package/dist/src/ui/commands/memoryCommand.test.d.ts +6 -0
  291. package/dist/src/ui/commands/memoryCommand.test.js +268 -0
  292. package/dist/src/ui/commands/memoryCommand.test.js.map +1 -0
  293. package/dist/src/ui/commands/policiesCommand.d.ts +7 -0
  294. package/dist/src/ui/commands/policiesCommand.js +59 -0
  295. package/dist/src/ui/commands/policiesCommand.js.map +1 -0
  296. package/dist/src/ui/commands/policiesCommand.test.d.ts +6 -0
  297. package/dist/src/ui/commands/policiesCommand.test.js +83 -0
  298. package/dist/src/ui/commands/policiesCommand.test.js.map +1 -0
  299. package/dist/src/ui/commands/privacyCommand.js +1 -1
  300. package/dist/src/ui/commands/privacyCommand.test.d.ts +6 -0
  301. package/dist/src/ui/commands/privacyCommand.test.js +32 -0
  302. package/dist/src/ui/commands/privacyCommand.test.js.map +1 -0
  303. package/dist/src/ui/commands/quitCommand.js +1 -1
  304. package/dist/src/ui/commands/quitCommand.test.d.ts +6 -0
  305. package/dist/src/ui/commands/quitCommand.test.js +50 -0
  306. package/dist/src/ui/commands/quitCommand.test.js.map +1 -0
  307. package/dist/src/ui/commands/restoreCommand.test.d.ts +6 -0
  308. package/dist/src/ui/commands/restoreCommand.test.js +190 -0
  309. package/dist/src/ui/commands/restoreCommand.test.js.map +1 -0
  310. package/dist/src/ui/commands/settingsCommand.test.d.ts +6 -0
  311. package/dist/src/ui/commands/settingsCommand.test.js +30 -0
  312. package/dist/src/ui/commands/settingsCommand.test.js.map +1 -0
  313. package/dist/src/ui/commands/setupGithubCommand.js +4 -3
  314. package/dist/src/ui/commands/setupGithubCommand.js.map +1 -1
  315. package/dist/src/ui/commands/setupGithubCommand.test.js +1 -2
  316. package/dist/src/ui/commands/setupGithubCommand.test.js.map +1 -1
  317. package/dist/src/ui/commands/statsCommand.js +3 -3
  318. package/dist/src/ui/commands/statsCommand.js.map +1 -1
  319. package/dist/src/ui/commands/statsCommand.test.d.ts +6 -0
  320. package/dist/src/ui/commands/statsCommand.test.js +53 -0
  321. package/dist/src/ui/commands/statsCommand.test.js.map +1 -0
  322. package/dist/src/ui/commands/terminalSetupCommand.test.d.ts +6 -0
  323. package/dist/src/ui/commands/terminalSetupCommand.test.js +66 -0
  324. package/dist/src/ui/commands/terminalSetupCommand.test.js.map +1 -0
  325. package/dist/src/ui/commands/themeCommand.js +1 -1
  326. package/dist/src/ui/commands/themeCommand.test.d.ts +6 -0
  327. package/dist/src/ui/commands/themeCommand.test.js +32 -0
  328. package/dist/src/ui/commands/themeCommand.test.js.map +1 -0
  329. package/dist/src/ui/commands/toolsCommand.js +1 -1
  330. package/dist/src/ui/commands/toolsCommand.test.d.ts +6 -0
  331. package/dist/src/ui/commands/toolsCommand.test.js +100 -0
  332. package/dist/src/ui/commands/toolsCommand.test.js.map +1 -0
  333. package/dist/src/ui/commands/types.d.ts +1 -0
  334. package/dist/src/ui/commands/vimCommand.js +1 -1
  335. package/dist/src/ui/components/AnsiOutput.test.js +1 -1
  336. package/dist/src/ui/components/AnsiOutput.test.js.map +1 -1
  337. package/dist/src/ui/components/AsciiArt.d.ts +3 -3
  338. package/dist/src/ui/components/AsciiArt.js +3 -3
  339. package/dist/src/ui/components/Composer.js +6 -4
  340. package/dist/src/ui/components/Composer.js.map +1 -1
  341. package/dist/src/ui/components/Composer.test.js +21 -3
  342. package/dist/src/ui/components/Composer.test.js.map +1 -1
  343. package/dist/src/ui/components/ConfigInitDisplay.js +4 -6
  344. package/dist/src/ui/components/ConfigInitDisplay.js.map +1 -1
  345. package/dist/src/ui/components/ConsentPrompt.test.js +18 -8
  346. package/dist/src/ui/components/ConsentPrompt.test.js.map +1 -1
  347. package/dist/src/ui/components/ConsoleSummaryDisplay.js +1 -1
  348. package/dist/src/ui/components/ConsoleSummaryDisplay.js.map +1 -1
  349. package/dist/src/ui/components/ContextSummaryDisplay.d.ts +0 -1
  350. package/dist/src/ui/components/ContextSummaryDisplay.js +2 -12
  351. package/dist/src/ui/components/ContextSummaryDisplay.js.map +1 -1
  352. package/dist/src/ui/components/ContextSummaryDisplay.test.d.ts +6 -0
  353. package/dist/src/ui/components/ContextSummaryDisplay.test.js +71 -0
  354. package/dist/src/ui/components/ContextSummaryDisplay.test.js.map +1 -0
  355. package/dist/src/ui/components/DetailedMessagesDisplay.js +1 -1
  356. package/dist/src/ui/components/DetailedMessagesDisplay.js.map +1 -1
  357. package/dist/src/ui/components/DialogManager.js +5 -5
  358. package/dist/src/ui/components/DialogManager.js.map +1 -1
  359. package/dist/src/ui/components/EditorSettingsDialog.js +1 -1
  360. package/dist/src/ui/components/EditorSettingsDialog.js.map +1 -1
  361. package/dist/src/ui/components/FolderTrustDialog.test.js +8 -3
  362. package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
  363. package/dist/src/ui/components/Footer.js +4 -3
  364. package/dist/src/ui/components/Footer.js.map +1 -1
  365. package/dist/src/ui/components/Footer.test.d.ts +6 -0
  366. package/dist/src/ui/components/Footer.test.js +314 -0
  367. package/dist/src/ui/components/Footer.test.js.map +1 -0
  368. package/dist/src/ui/components/Header.test.js +13 -5
  369. package/dist/src/ui/components/Header.test.js.map +1 -1
  370. package/dist/src/ui/components/Help.test.js +5 -4
  371. package/dist/src/ui/components/Help.test.js.map +1 -1
  372. package/dist/src/ui/components/HistoryItemDisplay.js +1 -1
  373. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  374. package/dist/src/ui/components/InputPrompt.d.ts +4 -0
  375. package/dist/src/ui/components/InputPrompt.js +80 -12
  376. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  377. package/dist/src/ui/components/InputPrompt.test.d.ts +6 -0
  378. package/dist/src/ui/components/InputPrompt.test.js +1786 -0
  379. package/dist/src/ui/components/InputPrompt.test.js.map +1 -0
  380. package/dist/src/ui/components/LoadingIndicator.js +2 -2
  381. package/dist/src/ui/components/LoadingIndicator.js.map +1 -1
  382. package/dist/src/ui/components/LoadingIndicator.test.js +28 -15
  383. package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -1
  384. package/dist/src/ui/components/LoopDetectionConfirmation.js +1 -1
  385. package/dist/src/ui/components/LoopDetectionConfirmation.js.map +1 -1
  386. package/dist/src/ui/components/LoopDetectionConfirmation.test.js +2 -2
  387. package/dist/src/ui/components/LoopDetectionConfirmation.test.js.map +1 -1
  388. package/dist/src/ui/components/MainContent.js +15 -4
  389. package/dist/src/ui/components/MainContent.js.map +1 -1
  390. package/dist/src/ui/components/ModelDialog.js +1 -1
  391. package/dist/src/ui/components/ModelDialog.js.map +1 -1
  392. package/dist/src/ui/components/ModelDialog.test.js +23 -13
  393. package/dist/src/ui/components/ModelDialog.test.js.map +1 -1
  394. package/dist/src/ui/components/ModelStatsDisplay.test.d.ts +6 -0
  395. package/dist/src/ui/components/ModelStatsDisplay.test.js +285 -0
  396. package/dist/src/ui/components/ModelStatsDisplay.test.js.map +1 -0
  397. package/dist/src/ui/components/Notifications.js +38 -5
  398. package/dist/src/ui/components/Notifications.js.map +1 -1
  399. package/dist/src/ui/components/PermissionsModifyTrustDialog.js +22 -18
  400. package/dist/src/ui/components/PermissionsModifyTrustDialog.js.map +1 -1
  401. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +12 -4
  402. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +1 -1
  403. package/dist/src/ui/components/PrepareLabel.test.js +14 -8
  404. package/dist/src/ui/components/PrepareLabel.test.js.map +1 -1
  405. package/dist/src/ui/components/ProQuotaDialog.test.js +14 -6
  406. package/dist/src/ui/components/ProQuotaDialog.test.js.map +1 -1
  407. package/dist/src/ui/components/QueuedMessageDisplay.js +3 -3
  408. package/dist/src/ui/components/QueuedMessageDisplay.js.map +1 -1
  409. package/dist/src/ui/components/QueuedMessageDisplay.test.js +15 -6
  410. package/dist/src/ui/components/QueuedMessageDisplay.test.js.map +1 -1
  411. package/dist/src/ui/components/RawMarkdownIndicator.d.ts +7 -0
  412. package/dist/src/ui/components/RawMarkdownIndicator.js +8 -0
  413. package/dist/src/ui/components/RawMarkdownIndicator.js.map +1 -0
  414. package/dist/src/ui/components/SessionSummaryDisplay.test.d.ts +6 -0
  415. package/dist/src/ui/components/SessionSummaryDisplay.test.js +74 -0
  416. package/dist/src/ui/components/SessionSummaryDisplay.test.js.map +1 -0
  417. package/dist/src/ui/components/SettingsDialog.js +43 -35
  418. package/dist/src/ui/components/SettingsDialog.js.map +1 -1
  419. package/dist/src/ui/components/SettingsDialog.test.js +554 -545
  420. package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
  421. package/dist/src/ui/components/ShellConfirmationDialog.js +1 -1
  422. package/dist/src/ui/components/ShellConfirmationDialog.js.map +1 -1
  423. package/dist/src/ui/components/ShellConfirmationDialog.test.js +2 -2
  424. package/dist/src/ui/components/ShellConfirmationDialog.test.js.map +1 -1
  425. package/dist/src/ui/components/StatsDisplay.test.d.ts +6 -0
  426. package/dist/src/ui/components/StatsDisplay.test.js +351 -0
  427. package/dist/src/ui/components/StatsDisplay.test.js.map +1 -0
  428. package/dist/src/ui/components/SuggestionsDisplay.js +1 -1
  429. package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
  430. package/dist/src/ui/components/ThemeDialog.d.ts +4 -2
  431. package/dist/src/ui/components/ThemeDialog.js +3 -3
  432. package/dist/src/ui/components/ThemeDialog.js.map +1 -1
  433. package/dist/src/ui/components/ThemeDialog.test.js +14 -1
  434. package/dist/src/ui/components/ThemeDialog.test.js.map +1 -1
  435. package/dist/src/ui/components/ToolStatsDisplay.test.d.ts +6 -0
  436. package/dist/src/ui/components/ToolStatsDisplay.test.js +227 -0
  437. package/dist/src/ui/components/ToolStatsDisplay.test.js.map +1 -0
  438. package/dist/src/ui/components/messages/CompressionMessage.test.js +25 -17
  439. package/dist/src/ui/components/messages/CompressionMessage.test.js.map +1 -1
  440. package/dist/src/ui/components/messages/DiffRenderer.test.js +1 -1
  441. package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -1
  442. package/dist/src/ui/components/messages/GeminiMessage.js +3 -1
  443. package/dist/src/ui/components/messages/GeminiMessage.js.map +1 -1
  444. package/dist/src/ui/components/messages/GeminiMessage.test.d.ts +6 -0
  445. package/dist/src/ui/components/messages/GeminiMessage.test.js +35 -0
  446. package/dist/src/ui/components/messages/GeminiMessage.test.js.map +1 -0
  447. package/dist/src/ui/components/messages/GeminiMessageContent.js +3 -1
  448. package/dist/src/ui/components/messages/GeminiMessageContent.js.map +1 -1
  449. package/dist/src/ui/components/messages/InfoMessage.js +1 -1
  450. package/dist/src/ui/components/messages/InfoMessage.js.map +1 -1
  451. package/dist/src/ui/components/messages/Todo.d.ts +7 -0
  452. package/dist/src/ui/components/messages/Todo.js +91 -0
  453. package/dist/src/ui/components/messages/Todo.js.map +1 -0
  454. package/dist/src/ui/components/messages/Todo.test.d.ts +6 -0
  455. package/dist/src/ui/components/messages/Todo.test.js +114 -0
  456. package/dist/src/ui/components/messages/Todo.test.js.map +1 -0
  457. package/dist/src/ui/components/messages/ToolConfirmationMessage.js +1 -1
  458. package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
  459. package/dist/src/ui/components/messages/ToolGroupMessage.js +1 -1
  460. package/dist/src/ui/components/messages/ToolGroupMessage.js.map +1 -1
  461. package/dist/src/ui/components/messages/ToolGroupMessage.test.js +29 -15
  462. package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -1
  463. package/dist/src/ui/components/messages/ToolMessage.js +8 -3
  464. package/dist/src/ui/components/messages/ToolMessage.js.map +1 -1
  465. package/dist/src/ui/components/messages/ToolMessage.test.js +2 -2
  466. package/dist/src/ui/components/messages/ToolMessage.test.js.map +1 -1
  467. package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.d.ts +6 -0
  468. package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.js +30 -0
  469. package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.js.map +1 -0
  470. package/dist/src/ui/components/messages/UserShellMessage.js +1 -1
  471. package/dist/src/ui/components/messages/UserShellMessage.js.map +1 -1
  472. package/dist/src/ui/components/messages/WarningMessage.js +2 -2
  473. package/dist/src/ui/components/messages/WarningMessage.js.map +1 -1
  474. package/dist/src/ui/components/shared/BaseSelectionList.test.js +34 -25
  475. package/dist/src/ui/components/shared/BaseSelectionList.test.js.map +1 -1
  476. package/dist/src/ui/components/shared/MaxSizedBox.test.js +43 -22
  477. package/dist/src/ui/components/shared/MaxSizedBox.test.js.map +1 -1
  478. package/dist/src/ui/components/shared/TextInput.d.ts +15 -0
  479. package/dist/src/ui/components/shared/TextInput.js +38 -0
  480. package/dist/src/ui/components/shared/TextInput.js.map +1 -0
  481. package/dist/src/ui/components/shared/TextInput.test.d.ts +6 -0
  482. package/dist/src/ui/components/shared/TextInput.test.js +242 -0
  483. package/dist/src/ui/components/shared/TextInput.test.js.map +1 -0
  484. package/dist/src/ui/components/shared/text-buffer.d.ts +9 -2
  485. package/dist/src/ui/components/shared/text-buffer.js +52 -14
  486. package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
  487. package/dist/src/ui/components/shared/text-buffer.test.d.ts +6 -0
  488. package/dist/src/ui/components/shared/text-buffer.test.js +1761 -0
  489. package/dist/src/ui/components/shared/text-buffer.test.js.map +1 -0
  490. package/dist/src/ui/components/shared/vim-buffer-actions.test.d.ts +6 -0
  491. package/dist/src/ui/components/shared/vim-buffer-actions.test.js +951 -0
  492. package/dist/src/ui/components/shared/vim-buffer-actions.test.js.map +1 -0
  493. package/dist/src/ui/components/views/ChatList.test.js +7 -4
  494. package/dist/src/ui/components/views/ChatList.test.js.map +1 -1
  495. package/dist/src/ui/components/views/ExtensionsList.d.ts +7 -1
  496. package/dist/src/ui/components/views/ExtensionsList.js +12 -15
  497. package/dist/src/ui/components/views/ExtensionsList.js.map +1 -1
  498. package/dist/src/ui/components/views/ExtensionsList.test.js +43 -29
  499. package/dist/src/ui/components/views/ExtensionsList.test.js.map +1 -1
  500. package/dist/src/ui/components/views/McpStatus.d.ts +0 -1
  501. package/dist/src/ui/components/views/McpStatus.js +4 -4
  502. package/dist/src/ui/components/views/McpStatus.js.map +1 -1
  503. package/dist/src/ui/components/views/McpStatus.test.js +23 -17
  504. package/dist/src/ui/components/views/McpStatus.test.js.map +1 -1
  505. package/dist/src/ui/components/views/ToolsList.test.js +4 -4
  506. package/dist/src/ui/components/views/ToolsList.test.js.map +1 -1
  507. package/dist/src/ui/contexts/KeypressContext.d.ts +4 -2
  508. package/dist/src/ui/contexts/KeypressContext.js +635 -439
  509. package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
  510. package/dist/src/ui/contexts/KeypressContext.test.js +634 -515
  511. package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
  512. package/dist/src/ui/contexts/MouseContext.d.ts +21 -0
  513. package/dist/src/ui/contexts/MouseContext.js +89 -0
  514. package/dist/src/ui/contexts/MouseContext.js.map +1 -0
  515. package/dist/src/ui/contexts/MouseContext.test.d.ts +6 -0
  516. package/dist/src/ui/contexts/MouseContext.test.js +164 -0
  517. package/dist/src/ui/contexts/MouseContext.test.js.map +1 -0
  518. package/dist/src/ui/contexts/SessionContext.test.d.ts +6 -0
  519. package/dist/src/ui/contexts/SessionContext.test.js +195 -0
  520. package/dist/src/ui/contexts/SessionContext.test.js.map +1 -0
  521. package/dist/src/ui/contexts/UIActionsContext.d.ts +7 -4
  522. package/dist/src/ui/contexts/UIStateContext.d.ts +5 -3
  523. package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
  524. package/dist/src/ui/hooks/atCommandProcessor.js +33 -11
  525. package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
  526. package/dist/src/ui/hooks/atCommandProcessor.test.js +163 -64
  527. package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -1
  528. package/dist/src/ui/hooks/shellCommandProcessor.js +0 -1
  529. package/dist/src/ui/hooks/shellCommandProcessor.js.map +1 -1
  530. package/dist/src/ui/hooks/shellCommandProcessor.test.js +64 -35
  531. package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -1
  532. package/dist/src/ui/hooks/slashCommandProcessor.js +2 -0
  533. package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
  534. package/dist/src/ui/hooks/slashCommandProcessor.test.d.ts +6 -0
  535. package/dist/src/ui/hooks/slashCommandProcessor.test.js +807 -0
  536. package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +1 -0
  537. package/dist/src/ui/hooks/useAtCompletion.js +2 -2
  538. package/dist/src/ui/hooks/useAtCompletion.js.map +1 -1
  539. package/dist/src/ui/hooks/useAtCompletion.test.d.ts +6 -0
  540. package/dist/src/ui/hooks/useAtCompletion.test.js +396 -0
  541. package/dist/src/ui/hooks/useAtCompletion.test.js.map +1 -0
  542. package/dist/src/ui/hooks/useAutoAcceptIndicator.js +10 -0
  543. package/dist/src/ui/hooks/useAutoAcceptIndicator.js.map +1 -1
  544. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js +32 -2
  545. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +1 -1
  546. package/dist/src/ui/hooks/useCommandCompletion.d.ts +1 -1
  547. package/dist/src/ui/hooks/useCommandCompletion.js +5 -3
  548. package/dist/src/ui/hooks/useCommandCompletion.js.map +1 -1
  549. package/dist/src/ui/hooks/useCommandCompletion.test.d.ts +6 -0
  550. package/dist/src/ui/hooks/useCommandCompletion.test.js +377 -0
  551. package/dist/src/ui/hooks/useCommandCompletion.test.js.map +1 -0
  552. package/dist/src/ui/hooks/useConsoleMessages.test.d.ts +6 -0
  553. package/dist/src/ui/hooks/useConsoleMessages.test.js +127 -0
  554. package/dist/src/ui/hooks/useConsoleMessages.test.js.map +1 -0
  555. package/dist/src/ui/hooks/useEditorSettings.test.js +40 -34
  556. package/dist/src/ui/hooks/useEditorSettings.test.js.map +1 -1
  557. package/dist/src/ui/hooks/useExtensionUpdates.d.ts +14 -4
  558. package/dist/src/ui/hooks/useExtensionUpdates.js +18 -11
  559. package/dist/src/ui/hooks/useExtensionUpdates.js.map +1 -1
  560. package/dist/src/ui/hooks/useExtensionUpdates.test.js +52 -35
  561. package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +1 -1
  562. package/dist/src/ui/hooks/useFlickerDetector.test.js +9 -5
  563. package/dist/src/ui/hooks/useFlickerDetector.test.js.map +1 -1
  564. package/dist/src/ui/hooks/useFocus.test.d.ts +6 -0
  565. package/dist/src/ui/hooks/useFocus.test.js +131 -0
  566. package/dist/src/ui/hooks/useFocus.test.js.map +1 -0
  567. package/dist/src/ui/hooks/useFolderTrust.test.d.ts +6 -0
  568. package/dist/src/ui/hooks/useFolderTrust.test.js +188 -0
  569. package/dist/src/ui/hooks/useFolderTrust.test.js.map +1 -0
  570. package/dist/src/ui/hooks/useGeminiStream.js +119 -74
  571. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  572. package/dist/src/ui/hooks/useGeminiStream.test.d.ts +6 -0
  573. package/dist/src/ui/hooks/useGeminiStream.test.js +1820 -0
  574. package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -0
  575. package/dist/src/ui/hooks/useGitBranchName.js +4 -0
  576. package/dist/src/ui/hooks/useGitBranchName.js.map +1 -1
  577. package/dist/src/ui/hooks/useGitBranchName.test.js +46 -34
  578. package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -1
  579. package/dist/src/ui/hooks/useHistoryManager.test.js +2 -1
  580. package/dist/src/ui/hooks/useHistoryManager.test.js.map +1 -1
  581. package/dist/src/ui/hooks/useIdeTrustListener.test.js +40 -9
  582. package/dist/src/ui/hooks/useIdeTrustListener.test.js.map +1 -1
  583. package/dist/src/ui/hooks/useInputHistory.test.js +2 -1
  584. package/dist/src/ui/hooks/useInputHistory.test.js.map +1 -1
  585. package/dist/src/ui/hooks/useInputHistoryStore.js +2 -1
  586. package/dist/src/ui/hooks/useInputHistoryStore.js.map +1 -1
  587. package/dist/src/ui/hooks/useInputHistoryStore.test.js +2 -1
  588. package/dist/src/ui/hooks/useInputHistoryStore.test.js.map +1 -1
  589. package/dist/src/ui/hooks/useKeypress.test.d.ts +6 -0
  590. package/dist/src/ui/hooks/useKeypress.test.js +223 -0
  591. package/dist/src/ui/hooks/useKeypress.test.js.map +1 -0
  592. package/dist/src/ui/hooks/useLoadingIndicator.test.js +29 -6
  593. package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
  594. package/dist/src/ui/hooks/useMemoryMonitor.test.js +10 -5
  595. package/dist/src/ui/hooks/useMemoryMonitor.test.js.map +1 -1
  596. package/dist/src/ui/hooks/useMessageQueue.d.ts +1 -0
  597. package/dist/src/ui/hooks/useMessageQueue.js +14 -0
  598. package/dist/src/ui/hooks/useMessageQueue.js.map +1 -1
  599. package/dist/src/ui/hooks/useMessageQueue.test.js +173 -35
  600. package/dist/src/ui/hooks/useMessageQueue.test.js.map +1 -1
  601. package/dist/src/ui/hooks/useModelCommand.test.js +21 -11
  602. package/dist/src/ui/hooks/useModelCommand.test.js.map +1 -1
  603. package/dist/src/ui/hooks/useMouse.d.ts +17 -0
  604. package/dist/src/ui/hooks/useMouse.js +27 -0
  605. package/dist/src/ui/hooks/useMouse.js.map +1 -0
  606. package/dist/src/ui/hooks/useMouse.test.d.ts +6 -0
  607. package/dist/src/ui/hooks/useMouse.test.js +57 -0
  608. package/dist/src/ui/hooks/useMouse.test.js.map +1 -0
  609. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js +2 -2
  610. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js.map +1 -1
  611. package/dist/src/ui/hooks/usePhraseCycler.d.ts +1 -0
  612. package/dist/src/ui/hooks/usePhraseCycler.js +156 -5
  613. package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
  614. package/dist/src/ui/hooks/usePhraseCycler.test.d.ts +6 -0
  615. package/dist/src/ui/hooks/usePhraseCycler.test.js +158 -0
  616. package/dist/src/ui/hooks/usePhraseCycler.test.js.map +1 -0
  617. package/dist/src/ui/hooks/usePrivacySettings.test.js +26 -6
  618. package/dist/src/ui/hooks/usePrivacySettings.test.js.map +1 -1
  619. package/dist/src/ui/hooks/usePromptCompletion.js +2 -2
  620. package/dist/src/ui/hooks/usePromptCompletion.js.map +1 -1
  621. package/dist/src/ui/hooks/useQuotaAndFallback.js +13 -14
  622. package/dist/src/ui/hooks/useQuotaAndFallback.js.map +1 -1
  623. package/dist/src/ui/hooks/useQuotaAndFallback.test.js +55 -48
  624. package/dist/src/ui/hooks/useQuotaAndFallback.test.js.map +1 -1
  625. package/dist/src/ui/hooks/useReactToolScheduler.d.ts +8 -1
  626. package/dist/src/ui/hooks/useReactToolScheduler.js +61 -36
  627. package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
  628. package/dist/src/ui/hooks/useReactToolScheduler.test.d.ts +6 -0
  629. package/dist/src/ui/hooks/useReactToolScheduler.test.js +65 -0
  630. package/dist/src/ui/hooks/useReactToolScheduler.test.js.map +1 -0
  631. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js +2 -2
  632. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js.map +1 -1
  633. package/dist/src/ui/hooks/useSelectionList.js +5 -4
  634. package/dist/src/ui/hooks/useSelectionList.js.map +1 -1
  635. package/dist/src/ui/hooks/useSelectionList.test.js +272 -183
  636. package/dist/src/ui/hooks/useSelectionList.test.js.map +1 -1
  637. package/dist/src/ui/hooks/useShellHistory.test.js +52 -20
  638. package/dist/src/ui/hooks/useShellHistory.test.js.map +1 -1
  639. package/dist/src/ui/hooks/useShowMemoryCommand.d.ts +1 -1
  640. package/dist/src/ui/hooks/useShowMemoryCommand.js +4 -3
  641. package/dist/src/ui/hooks/useShowMemoryCommand.js.map +1 -1
  642. package/dist/src/ui/hooks/useSlashCompletion.js +20 -8
  643. package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
  644. package/dist/src/ui/hooks/useSlashCompletion.test.js +275 -137
  645. package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
  646. package/dist/src/ui/hooks/useThemeCommand.d.ts +2 -1
  647. package/dist/src/ui/hooks/useThemeCommand.js +6 -0
  648. package/dist/src/ui/hooks/useThemeCommand.js.map +1 -1
  649. package/dist/src/ui/hooks/useTimer.test.js +43 -14
  650. package/dist/src/ui/hooks/useTimer.test.js.map +1 -1
  651. package/dist/src/ui/hooks/useToolScheduler.test.js +229 -242
  652. package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
  653. package/dist/src/ui/hooks/vim.js +2 -1
  654. package/dist/src/ui/hooks/vim.js.map +1 -1
  655. package/dist/src/ui/hooks/vim.test.d.ts +6 -0
  656. package/dist/src/ui/hooks/vim.test.js +1269 -0
  657. package/dist/src/ui/hooks/vim.test.js.map +1 -0
  658. package/dist/src/ui/keyMatchers.test.js +39 -6
  659. package/dist/src/ui/keyMatchers.test.js.map +1 -1
  660. package/dist/src/ui/state/extensions.d.ts +1 -0
  661. package/dist/src/ui/state/extensions.js +1 -0
  662. package/dist/src/ui/state/extensions.js.map +1 -1
  663. package/dist/src/ui/themes/ansi-light.js +1 -0
  664. package/dist/src/ui/themes/ansi-light.js.map +1 -1
  665. package/dist/src/ui/themes/ansi.js +1 -0
  666. package/dist/src/ui/themes/ansi.js.map +1 -1
  667. package/dist/src/ui/themes/atom-one-dark.js +2 -0
  668. package/dist/src/ui/themes/atom-one-dark.js.map +1 -1
  669. package/dist/src/ui/themes/ayu-light.js +2 -0
  670. package/dist/src/ui/themes/ayu-light.js.map +1 -1
  671. package/dist/src/ui/themes/ayu.js +2 -0
  672. package/dist/src/ui/themes/ayu.js.map +1 -1
  673. package/dist/src/ui/themes/color-utils.d.ts +1 -0
  674. package/dist/src/ui/themes/color-utils.js +8 -1
  675. package/dist/src/ui/themes/color-utils.js.map +1 -1
  676. package/dist/src/ui/themes/color-utils.test.js +13 -1
  677. package/dist/src/ui/themes/color-utils.test.js.map +1 -1
  678. package/dist/src/ui/themes/dracula.js +2 -0
  679. package/dist/src/ui/themes/dracula.js.map +1 -1
  680. package/dist/src/ui/themes/github-dark.js +2 -0
  681. package/dist/src/ui/themes/github-dark.js.map +1 -1
  682. package/dist/src/ui/themes/github-light.js +2 -0
  683. package/dist/src/ui/themes/github-light.js.map +1 -1
  684. package/dist/src/ui/themes/googlecode.js +2 -0
  685. package/dist/src/ui/themes/googlecode.js.map +1 -1
  686. package/dist/src/ui/themes/no-color.js +3 -0
  687. package/dist/src/ui/themes/no-color.js.map +1 -1
  688. package/dist/src/ui/themes/semantic-tokens.d.ts +2 -0
  689. package/dist/src/ui/themes/semantic-tokens.js +6 -0
  690. package/dist/src/ui/themes/semantic-tokens.js.map +1 -1
  691. package/dist/src/ui/themes/shades-of-purple.js +2 -0
  692. package/dist/src/ui/themes/shades-of-purple.js.map +1 -1
  693. package/dist/src/ui/themes/theme-manager.js +8 -7
  694. package/dist/src/ui/themes/theme-manager.js.map +1 -1
  695. package/dist/src/ui/themes/theme.d.ts +3 -0
  696. package/dist/src/ui/themes/theme.js +14 -3
  697. package/dist/src/ui/themes/theme.js.map +1 -1
  698. package/dist/src/ui/themes/theme.test.d.ts +6 -0
  699. package/dist/src/ui/themes/theme.test.js +151 -0
  700. package/dist/src/ui/themes/theme.test.js.map +1 -0
  701. package/dist/src/ui/themes/xcode.js +2 -0
  702. package/dist/src/ui/themes/xcode.js.map +1 -1
  703. package/dist/src/ui/types.d.ts +3 -2
  704. package/dist/src/ui/types.js +2 -0
  705. package/dist/src/ui/types.js.map +1 -1
  706. package/dist/src/ui/utils/CodeColorizer.d.ts +1 -1
  707. package/dist/src/ui/utils/CodeColorizer.js +6 -3
  708. package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
  709. package/dist/src/ui/utils/InlineMarkdownRenderer.d.ts +1 -0
  710. package/dist/src/ui/utils/InlineMarkdownRenderer.js +11 -10
  711. package/dist/src/ui/utils/InlineMarkdownRenderer.js.map +1 -1
  712. package/dist/src/ui/utils/MarkdownDisplay.d.ts +1 -0
  713. package/dist/src/ui/utils/MarkdownDisplay.js +19 -10
  714. package/dist/src/ui/utils/MarkdownDisplay.js.map +1 -1
  715. package/dist/src/ui/utils/clipboardUtils.js +2 -2
  716. package/dist/src/ui/utils/clipboardUtils.js.map +1 -1
  717. package/dist/src/ui/utils/commandUtils.js +20 -3
  718. package/dist/src/ui/utils/commandUtils.js.map +1 -1
  719. package/dist/src/ui/utils/commandUtils.test.js +61 -6
  720. package/dist/src/ui/utils/commandUtils.test.js.map +1 -1
  721. package/dist/src/ui/utils/computeStats.js +5 -2
  722. package/dist/src/ui/utils/computeStats.js.map +1 -1
  723. package/dist/src/ui/utils/computeStats.test.d.ts +6 -0
  724. package/dist/src/ui/utils/computeStats.test.js +262 -0
  725. package/dist/src/ui/utils/computeStats.test.js.map +1 -0
  726. package/dist/src/ui/utils/input.d.ts +17 -0
  727. package/dist/src/ui/utils/input.js +51 -0
  728. package/dist/src/ui/utils/input.js.map +1 -0
  729. package/dist/src/ui/utils/input.test.d.ts +6 -0
  730. package/dist/src/ui/utils/input.test.js +44 -0
  731. package/dist/src/ui/utils/input.test.js.map +1 -0
  732. package/dist/src/ui/utils/kittyProtocolDetector.js +13 -4
  733. package/dist/src/ui/utils/kittyProtocolDetector.js.map +1 -1
  734. package/dist/src/ui/utils/mouse.d.ts +31 -0
  735. package/dist/src/ui/utils/mouse.js +164 -0
  736. package/dist/src/ui/utils/mouse.js.map +1 -0
  737. package/dist/src/ui/utils/mouse.test.d.ts +6 -0
  738. package/dist/src/ui/utils/mouse.test.js +131 -0
  739. package/dist/src/ui/utils/mouse.test.js.map +1 -0
  740. package/dist/src/ui/utils/terminalSetup.js +3 -2
  741. package/dist/src/ui/utils/terminalSetup.js.map +1 -1
  742. package/dist/src/ui/utils/textOutput.d.ts +25 -0
  743. package/dist/src/ui/utils/textOutput.js +49 -0
  744. package/dist/src/ui/utils/textOutput.js.map +1 -0
  745. package/dist/src/ui/utils/textOutput.test.d.ts +6 -0
  746. package/dist/src/ui/utils/textOutput.test.js +79 -0
  747. package/dist/src/ui/utils/textOutput.test.js.map +1 -0
  748. package/dist/src/ui/utils/updateCheck.d.ts +9 -2
  749. package/dist/src/ui/utils/updateCheck.js +38 -30
  750. package/dist/src/ui/utils/updateCheck.js.map +1 -1
  751. package/dist/src/ui/utils/updateCheck.test.js +48 -59
  752. package/dist/src/ui/utils/updateCheck.test.js.map +1 -1
  753. package/dist/src/utils/cleanup.test.d.ts +6 -0
  754. package/dist/src/utils/cleanup.test.js +49 -0
  755. package/dist/src/utils/cleanup.test.js.map +1 -0
  756. package/dist/src/utils/commentJson.js +2 -2
  757. package/dist/src/utils/commentJson.js.map +1 -1
  758. package/dist/src/utils/commentJson.test.js +7 -6
  759. package/dist/src/utils/commentJson.test.js.map +1 -1
  760. package/dist/src/utils/envVarResolver.d.ts +2 -2
  761. package/dist/src/utils/envVarResolver.js +10 -7
  762. package/dist/src/utils/envVarResolver.js.map +1 -1
  763. package/dist/src/utils/errors.d.ts +1 -0
  764. package/dist/src/utils/errors.js +66 -5
  765. package/dist/src/utils/errors.js.map +1 -1
  766. package/dist/src/utils/events.d.ts +11 -2
  767. package/dist/src/utils/events.js +1 -0
  768. package/dist/src/utils/events.js.map +1 -1
  769. package/dist/src/utils/gitUtils.js +3 -2
  770. package/dist/src/utils/gitUtils.js.map +1 -1
  771. package/dist/src/utils/handleAutoUpdate.js +9 -3
  772. package/dist/src/utils/handleAutoUpdate.js.map +1 -1
  773. package/dist/src/utils/handleAutoUpdate.test.d.ts +6 -0
  774. package/dist/src/utils/handleAutoUpdate.test.js +225 -0
  775. package/dist/src/utils/handleAutoUpdate.test.js.map +1 -0
  776. package/dist/src/utils/installationInfo.js +2 -2
  777. package/dist/src/utils/installationInfo.js.map +1 -1
  778. package/dist/src/utils/installationInfo.test.js +8 -4
  779. package/dist/src/utils/installationInfo.test.js.map +1 -1
  780. package/dist/src/utils/readStdin.js +2 -1
  781. package/dist/src/utils/readStdin.js.map +1 -1
  782. package/dist/src/utils/sandbox-macos-permissive-open.sb +2 -0
  783. package/dist/src/utils/sandbox.js +28 -30
  784. package/dist/src/utils/sandbox.js.map +1 -1
  785. package/dist/src/utils/sessionCleanup.js +4 -4
  786. package/dist/src/utils/sessionCleanup.js.map +1 -1
  787. package/dist/src/utils/startupWarnings.test.d.ts +6 -0
  788. package/dist/src/utils/startupWarnings.test.js +61 -0
  789. package/dist/src/utils/startupWarnings.test.js.map +1 -0
  790. package/dist/src/utils/version.js +6 -2
  791. package/dist/src/utils/version.js.map +1 -1
  792. package/dist/src/validateNonInterActiveAuth.js +2 -2
  793. package/dist/src/validateNonInterActiveAuth.js.map +1 -1
  794. package/dist/src/zed-integration/acp.js +2 -1
  795. package/dist/src/zed-integration/acp.js.map +1 -1
  796. package/dist/src/zed-integration/schema.d.ts +4 -4
  797. package/dist/src/zed-integration/zedIntegration.d.ts +2 -2
  798. package/dist/src/zed-integration/zedIntegration.js +16 -25
  799. package/dist/src/zed-integration/zedIntegration.js.map +1 -1
  800. package/dist/tsconfig.tsbuildinfo +1 -1
  801. package/package.json +17 -17
  802. package/dist/src/config/policy.test.js +0 -336
  803. package/dist/src/config/policy.test.js.map +0 -1
  804. package/dist/src/ui/components/WorkspaceMigrationDialog.d.ts +0 -11
  805. package/dist/src/ui/components/WorkspaceMigrationDialog.js +0 -44
  806. package/dist/src/ui/components/WorkspaceMigrationDialog.js.map +0 -1
  807. package/dist/src/ui/hooks/useWorkspaceMigration.d.ts +0 -13
  808. package/dist/src/ui/hooks/useWorkspaceMigration.js +0 -59
  809. package/dist/src/ui/hooks/useWorkspaceMigration.js.map +0 -1
  810. package/dist/src/utils/package.d.ts +0 -12
  811. package/dist/src/utils/package.js +0 -24
  812. package/dist/src/utils/package.js.map +0 -1
  813. /package/dist/src/{config/policy.test.d.ts → commands/extensions/examples/mcp-server/example.d.ts} +0 -0
@@ -1,7 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { renderHook, act, waitFor } from '@testing-library/react';
2
+ import { act } from 'react';
3
+ import { renderHook } from '../../test-utils/render.js';
4
+ import { waitFor } from '../../test-utils/async.js';
3
5
  import { vi } from 'vitest';
4
- import { KeypressProvider, useKeypressContext, DRAG_COMPLETION_TIMEOUT_MS,
6
+ import { KeypressProvider, useKeypressContext, DRAG_COMPLETION_TIMEOUT_MS, KITTY_SEQUENCE_TIMEOUT_MS,
5
7
  // CSI_END_O,
6
8
  // SS3_END,
7
9
  SINGLE_QUOTE, DOUBLE_QUOTE, } from './KeypressContext.js';
@@ -15,35 +17,34 @@ vi.mock('ink', async (importOriginal) => {
15
17
  useStdin: vi.fn(),
16
18
  };
17
19
  });
20
+ const PASTE_START = '\x1B[200~';
21
+ const PASTE_END = '\x1B[201~';
22
+ // readline will not emit most incomplete kitty sequences but it will give
23
+ // up on sequences like this where the modifier (135) has more than two digits.
24
+ const INCOMPLETE_KITTY_SEQUENCE = '\x1b[97;135';
18
25
  class MockStdin extends EventEmitter {
19
26
  isTTY = true;
20
27
  setRawMode = vi.fn();
21
28
  on = this.addListener;
22
29
  removeListener = super.removeListener;
23
- write = vi.fn();
24
30
  resume = vi.fn();
25
31
  pause = vi.fn();
26
- // Helper to simulate a keypress event
27
- pressKey(key) {
28
- this.emit('keypress', null, key);
29
- }
30
- // Helper to simulate a kitty protocol sequence
31
- sendKittySequence(sequence) {
32
- this.emit('data', Buffer.from(sequence));
33
- }
34
- // Helper to simulate a paste event
35
- sendPaste(text) {
36
- const PASTE_MODE_PREFIX = `\x1b[200~`;
37
- const PASTE_MODE_SUFFIX = `\x1b[201~`;
38
- this.emit('data', Buffer.from(PASTE_MODE_PREFIX));
39
- this.emit('data', Buffer.from(text));
40
- this.emit('data', Buffer.from(PASTE_MODE_SUFFIX));
32
+ write(text) {
33
+ this.emit('data', text);
41
34
  }
42
35
  }
36
+ // Helper function to setup keypress test with standard configuration
37
+ const setupKeypressTest = (kittyProtocolEnabled = true) => {
38
+ const keyHandler = vi.fn();
39
+ const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: kittyProtocolEnabled, children: children }));
40
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
41
+ act(() => result.current.subscribe(keyHandler));
42
+ return { result, keyHandler };
43
+ };
43
44
  describe('KeypressContext - Kitty Protocol', () => {
44
45
  let stdin;
45
46
  const mockSetRawMode = vi.fn();
46
- const wrapper = ({ children, kittyProtocolEnabled = true, }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: kittyProtocolEnabled, children: children }));
47
+ const wrapper = ({ children, kittyProtocolEnabled = true, }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: kittyProtocolEnabled ?? false, children: children }));
47
48
  beforeEach(() => {
48
49
  vi.clearAllMocks();
49
50
  stdin = new MockStdin();
@@ -53,117 +54,58 @@ describe('KeypressContext - Kitty Protocol', () => {
53
54
  });
54
55
  });
55
56
  describe('Enter key handling', () => {
56
- it('should recognize regular enter key (keycode 13) in kitty protocol', async () => {
57
- const keyHandler = vi.fn();
58
- const { result } = renderHook(() => useKeypressContext(), {
59
- wrapper: ({ children }) => wrapper({ children, kittyProtocolEnabled: true }),
60
- });
61
- act(() => {
62
- result.current.subscribe(keyHandler);
63
- });
64
- // Send kitty protocol sequence for regular enter: ESC[13u
65
- act(() => {
66
- stdin.sendKittySequence(`\x1b[13u`);
67
- });
68
- expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
69
- name: 'return',
70
- kittyProtocol: true,
71
- ctrl: false,
72
- meta: false,
73
- shift: false,
74
- }));
75
- });
76
- it('should recognize numpad enter key (keycode 57414) in kitty protocol', async () => {
77
- const keyHandler = vi.fn();
78
- const { result } = renderHook(() => useKeypressContext(), {
79
- wrapper: ({ children }) => wrapper({ children, kittyProtocolEnabled: true }),
80
- });
81
- act(() => {
82
- result.current.subscribe(keyHandler);
83
- });
84
- // Send kitty protocol sequence for numpad enter: ESC[57414u
85
- act(() => {
86
- stdin.sendKittySequence(`\x1b[57414u`);
87
- });
88
- expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
89
- name: 'return',
90
- kittyProtocol: true,
91
- ctrl: false,
92
- meta: false,
93
- shift: false,
94
- }));
95
- });
96
- it('should handle numpad enter with modifiers', async () => {
97
- const keyHandler = vi.fn();
98
- const { result } = renderHook(() => useKeypressContext(), {
99
- wrapper: ({ children }) => wrapper({ children, kittyProtocolEnabled: true }),
100
- });
101
- act(() => {
102
- result.current.subscribe(keyHandler);
103
- });
104
- // Send kitty protocol sequence for numpad enter with Shift (modifier 2): ESC[57414;2u
57
+ it.each([
58
+ {
59
+ name: 'regular enter key (keycode 13)',
60
+ sequence: '\x1b[13u',
61
+ },
62
+ {
63
+ name: 'numpad enter key (keycode 57414)',
64
+ sequence: '\x1b[57414u',
65
+ },
66
+ ])('should recognize $name in kitty protocol', async ({ sequence }) => {
67
+ const { keyHandler } = setupKeypressTest(true);
105
68
  act(() => {
106
- stdin.sendKittySequence(`\x1b[57414;2u`);
69
+ stdin.write(sequence);
107
70
  });
108
71
  expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
109
72
  name: 'return',
110
73
  kittyProtocol: true,
111
74
  ctrl: false,
112
75
  meta: false,
113
- shift: true,
114
- }));
115
- });
116
- it('should handle numpad enter with Ctrl modifier', async () => {
117
- const keyHandler = vi.fn();
118
- const { result } = renderHook(() => useKeypressContext(), {
119
- wrapper: ({ children }) => wrapper({ children, kittyProtocolEnabled: true }),
120
- });
121
- act(() => {
122
- result.current.subscribe(keyHandler);
123
- });
124
- // Send kitty protocol sequence for numpad enter with Ctrl (modifier 5): ESC[57414;5u
125
- act(() => {
126
- stdin.sendKittySequence(`\x1b[57414;5u`);
127
- });
128
- expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
129
- name: 'return',
130
- kittyProtocol: true,
131
- ctrl: true,
132
- meta: false,
133
76
  shift: false,
134
77
  }));
135
78
  });
136
- it('should handle numpad enter with Alt modifier', async () => {
137
- const keyHandler = vi.fn();
138
- const { result } = renderHook(() => useKeypressContext(), {
139
- wrapper: ({ children }) => wrapper({ children, kittyProtocolEnabled: true }),
140
- });
141
- act(() => {
142
- result.current.subscribe(keyHandler);
143
- });
144
- // Send kitty protocol sequence for numpad enter with Alt (modifier 3): ESC[57414;3u
145
- act(() => {
146
- stdin.sendKittySequence(`\x1b[57414;3u`);
147
- });
79
+ it.each([
80
+ {
81
+ modifier: 'Shift',
82
+ sequence: '\x1b[57414;2u',
83
+ expected: { ctrl: false, meta: false, shift: true },
84
+ },
85
+ {
86
+ modifier: 'Ctrl',
87
+ sequence: '\x1b[57414;5u',
88
+ expected: { ctrl: true, meta: false, shift: false },
89
+ },
90
+ {
91
+ modifier: 'Alt',
92
+ sequence: '\x1b[57414;3u',
93
+ expected: { ctrl: false, meta: true, shift: false },
94
+ },
95
+ ])('should handle numpad enter with $modifier modifier', async ({ sequence, expected }) => {
96
+ const { keyHandler } = setupKeypressTest(true);
97
+ act(() => stdin.write(sequence));
148
98
  expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
149
99
  name: 'return',
150
100
  kittyProtocol: true,
151
- ctrl: false,
152
- meta: true,
153
- shift: false,
101
+ ...expected,
154
102
  }));
155
103
  });
156
104
  it('should not process kitty sequences when kitty protocol is disabled', async () => {
157
- const keyHandler = vi.fn();
158
- const { result } = renderHook(() => useKeypressContext(), {
159
- wrapper: ({ children }) => wrapper({ children, kittyProtocolEnabled: false }),
160
- });
161
- act(() => {
162
- result.current.subscribe(keyHandler);
163
- });
105
+ const { keyHandler } = setupKeypressTest(false);
164
106
  // Send kitty protocol sequence for numpad enter
165
107
  act(() => {
166
- stdin.sendKittySequence(`\x1b[57414u`);
108
+ stdin.write(`\x1b[57414u`);
167
109
  });
168
110
  // When kitty protocol is disabled, the sequence should be passed through
169
111
  // as individual keypresses, not recognized as a single enter key
@@ -175,112 +117,115 @@ describe('KeypressContext - Kitty Protocol', () => {
175
117
  });
176
118
  describe('Escape key handling', () => {
177
119
  it('should recognize escape key (keycode 27) in kitty protocol', async () => {
178
- const keyHandler = vi.fn();
179
- const { result } = renderHook(() => useKeypressContext(), {
180
- wrapper: ({ children }) => wrapper({ children, kittyProtocolEnabled: true }),
181
- });
182
- act(() => {
183
- result.current.subscribe(keyHandler);
184
- });
120
+ const { keyHandler } = setupKeypressTest(true);
185
121
  // Send kitty protocol sequence for escape: ESC[27u
186
122
  act(() => {
187
- stdin.sendKittySequence('\x1b[27u');
123
+ stdin.write('\x1b[27u');
188
124
  });
189
125
  expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
190
126
  name: 'escape',
191
127
  kittyProtocol: true,
192
128
  }));
193
129
  });
194
- });
195
- describe('Tab and Backspace handling', () => {
196
- it('should recognize Tab key in kitty protocol', async () => {
197
- const keyHandler = vi.fn();
198
- const { result } = renderHook(() => useKeypressContext(), { wrapper });
199
- act(() => result.current.subscribe(keyHandler));
200
- act(() => {
201
- stdin.sendKittySequence(`\x1b[9u`);
202
- });
203
- expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
204
- name: 'tab',
205
- kittyProtocol: true,
206
- shift: false,
207
- }));
208
- });
209
- it('should recognize Shift+Tab in kitty protocol', async () => {
210
- const keyHandler = vi.fn();
211
- const { result } = renderHook(() => useKeypressContext(), { wrapper });
212
- act(() => result.current.subscribe(keyHandler));
213
- // Modifier 2 is Shift
214
- act(() => {
215
- stdin.sendKittySequence(`\x1b[9;2u`);
216
- });
217
- expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
218
- name: 'tab',
219
- kittyProtocol: true,
220
- shift: true,
221
- }));
222
- });
223
- it('should recognize Backspace key in kitty protocol', async () => {
224
- const keyHandler = vi.fn();
225
- const { result } = renderHook(() => useKeypressContext(), { wrapper });
226
- act(() => result.current.subscribe(keyHandler));
227
- act(() => {
228
- stdin.sendKittySequence(`\x1b[127u`);
229
- });
230
- expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
231
- name: 'backspace',
232
- kittyProtocol: true,
233
- meta: false,
234
- }));
235
- });
236
- it('should recognize Option+Backspace in kitty protocol', async () => {
130
+ it('should handle lone Escape key (keycode 27) with timeout when kitty protocol is enabled', async () => {
131
+ // Use real timers for this test to avoid issues with stream/buffer timing
132
+ vi.useRealTimers();
237
133
  const keyHandler = vi.fn();
134
+ const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: true, children: children }));
238
135
  const { result } = renderHook(() => useKeypressContext(), { wrapper });
239
136
  act(() => result.current.subscribe(keyHandler));
240
- // Modifier 3 is Alt/Option
137
+ // Send just ESC
241
138
  act(() => {
242
- stdin.sendKittySequence(`\x1b[127;3u`);
139
+ stdin.write('\x1b');
243
140
  });
244
- expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
245
- name: 'backspace',
246
- kittyProtocol: true,
247
- meta: true,
248
- }));
141
+ // Should be buffered initially
142
+ expect(keyHandler).not.toHaveBeenCalled();
143
+ // Wait for timeout
144
+ await waitFor(() => {
145
+ expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
146
+ name: 'escape',
147
+ meta: true,
148
+ }));
149
+ }, { timeout: 500 });
249
150
  });
250
- it('should recognize Ctrl+Backspace in kitty protocol', async () => {
251
- const keyHandler = vi.fn();
252
- const { result } = renderHook(() => useKeypressContext(), { wrapper });
253
- act(() => result.current.subscribe(keyHandler));
254
- // Modifier 5 is Ctrl
151
+ });
152
+ describe('Tab and Backspace handling', () => {
153
+ it.each([
154
+ {
155
+ name: 'Tab key',
156
+ sequence: '\x1b[9u',
157
+ expected: { name: 'tab', shift: false },
158
+ },
159
+ {
160
+ name: 'Shift+Tab',
161
+ sequence: '\x1b[9;2u',
162
+ expected: { name: 'tab', shift: true },
163
+ },
164
+ {
165
+ name: 'Backspace',
166
+ sequence: '\x1b[127u',
167
+ expected: { name: 'backspace', meta: false },
168
+ },
169
+ {
170
+ name: 'Option+Backspace',
171
+ sequence: '\x1b[127;3u',
172
+ expected: { name: 'backspace', meta: true },
173
+ },
174
+ {
175
+ name: 'Ctrl+Backspace',
176
+ sequence: '\x1b[127;5u',
177
+ expected: { name: 'backspace', ctrl: true },
178
+ },
179
+ ])('should recognize $name in kitty protocol', async ({ sequence, expected }) => {
180
+ const { keyHandler } = setupKeypressTest(true);
255
181
  act(() => {
256
- stdin.sendKittySequence(`\x1b[127;5u`);
182
+ stdin.write(sequence);
257
183
  });
258
184
  expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
259
- name: 'backspace',
185
+ ...expected,
260
186
  kittyProtocol: true,
261
- ctrl: true,
262
187
  }));
263
188
  });
264
189
  });
265
190
  describe('paste mode', () => {
266
- it('should handle multiline paste as a single event', async () => {
191
+ it.each([
192
+ {
193
+ name: 'handle multiline paste as a single event',
194
+ pastedText: 'This \n is \n a \n multiline \n paste.',
195
+ writeSequence: (text) => {
196
+ stdin.write(PASTE_START);
197
+ stdin.write(text);
198
+ stdin.write(PASTE_END);
199
+ },
200
+ },
201
+ {
202
+ name: 'handle paste start code split over multiple writes',
203
+ pastedText: 'pasted content',
204
+ writeSequence: (text) => {
205
+ stdin.write(PASTE_START.slice(0, 3));
206
+ stdin.write(PASTE_START.slice(3));
207
+ stdin.write(text);
208
+ stdin.write(PASTE_END);
209
+ },
210
+ },
211
+ {
212
+ name: 'handle paste end code split over multiple writes',
213
+ pastedText: 'pasted content',
214
+ writeSequence: (text) => {
215
+ stdin.write(PASTE_START);
216
+ stdin.write(text);
217
+ stdin.write(PASTE_END.slice(0, 3));
218
+ stdin.write(PASTE_END.slice(3));
219
+ },
220
+ },
221
+ ])('should $name', async ({ pastedText, writeSequence }) => {
267
222
  const keyHandler = vi.fn();
268
- const pastedText = 'This \n is \n a \n multiline \n paste.';
269
- const { result } = renderHook(() => useKeypressContext(), {
270
- wrapper,
271
- });
272
- act(() => {
273
- result.current.subscribe(keyHandler);
274
- });
275
- // Simulate a bracketed paste event
276
- act(() => {
277
- stdin.sendPaste(pastedText);
278
- });
223
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
224
+ act(() => result.current.subscribe(keyHandler));
225
+ act(() => writeSequence(pastedText));
279
226
  await waitFor(() => {
280
- // Expect the handler to be called exactly once for the entire paste
281
227
  expect(keyHandler).toHaveBeenCalledTimes(1);
282
228
  });
283
- // Verify the single event contains the full pasted text
284
229
  expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
285
230
  paste: true,
286
231
  sequence: pastedText,
@@ -302,12 +247,10 @@ describe('KeypressContext - Kitty Protocol', () => {
302
247
  const keyHandler = vi.fn();
303
248
  const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: true, debugKeystrokeLogging: false, children: children }));
304
249
  const { result } = renderHook(() => useKeypressContext(), { wrapper });
305
- act(() => {
306
- result.current.subscribe(keyHandler);
307
- });
250
+ act(() => result.current.subscribe(keyHandler));
308
251
  // Send a kitty sequence
309
252
  act(() => {
310
- stdin.sendKittySequence('\x1b[27u');
253
+ stdin.write('\x1b[27u');
311
254
  });
312
255
  expect(keyHandler).toHaveBeenCalled();
313
256
  expect(consoleLogSpy).not.toHaveBeenCalledWith(expect.stringContaining('[DEBUG] Kitty'));
@@ -316,61 +259,34 @@ describe('KeypressContext - Kitty Protocol', () => {
316
259
  const keyHandler = vi.fn();
317
260
  const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: true, debugKeystrokeLogging: true, children: children }));
318
261
  const { result } = renderHook(() => useKeypressContext(), { wrapper });
319
- act(() => {
320
- result.current.subscribe(keyHandler);
321
- });
262
+ act(() => result.current.subscribe(keyHandler));
322
263
  // Send a complete kitty sequence for escape
323
- act(() => {
324
- stdin.sendKittySequence('\x1b[27u');
325
- });
326
- expect(consoleLogSpy).toHaveBeenCalledWith('[DEBUG] Kitty buffer accumulating:', expect.stringContaining('\x1b[27u'));
264
+ act(() => stdin.write('\x1b[27u'));
265
+ expect(consoleLogSpy).toHaveBeenCalledWith('[DEBUG] Input buffer accumulating:', expect.stringContaining('"\\u001b[27u"'));
327
266
  const parsedCall = consoleLogSpy.mock.calls.find((args) => typeof args[0] === 'string' &&
328
- args[0].includes('[DEBUG] Kitty sequence parsed successfully'));
267
+ args[0].includes('[DEBUG] Sequence parsed successfully'));
329
268
  expect(parsedCall).toBeTruthy();
330
- expect(parsedCall?.[1]).toEqual(expect.stringContaining('\x1b[27u'));
269
+ expect(parsedCall?.[1]).toEqual(expect.stringContaining('\\u001b[27u'));
331
270
  });
332
271
  it('should log kitty buffer overflow when debugKeystrokeLogging is true', async () => {
333
272
  const keyHandler = vi.fn();
334
273
  const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: true, debugKeystrokeLogging: true, children: children }));
335
274
  const { result } = renderHook(() => useKeypressContext(), { wrapper });
336
- act(() => {
337
- result.current.subscribe(keyHandler);
338
- });
339
- // Send an invalid long sequence to trigger overflow
340
- const longInvalidSequence = '\x1b[' + 'x'.repeat(100);
341
- act(() => {
342
- stdin.sendKittySequence(longInvalidSequence);
343
- });
344
- expect(consoleLogSpy).toHaveBeenCalledWith('[DEBUG] Kitty buffer overflow, clearing:', expect.any(String));
275
+ act(() => result.current.subscribe(keyHandler));
276
+ // Send a long sequence starting with a valid kitty prefix to trigger overflow
277
+ const longSequence = '\x1b[1;' + '1'.repeat(100);
278
+ act(() => stdin.write(longSequence));
279
+ expect(consoleLogSpy).toHaveBeenCalledWith('[DEBUG] Input buffer overflow, clearing:', expect.any(String));
345
280
  });
346
281
  it('should log kitty buffer clear on Ctrl+C when debugKeystrokeLogging is true', async () => {
347
282
  const keyHandler = vi.fn();
348
283
  const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: true, debugKeystrokeLogging: true, children: children }));
349
284
  const { result } = renderHook(() => useKeypressContext(), { wrapper });
350
- act(() => {
351
- result.current.subscribe(keyHandler);
352
- });
353
- // Send incomplete kitty sequence
354
- act(() => {
355
- stdin.pressKey({
356
- name: undefined,
357
- ctrl: false,
358
- meta: false,
359
- shift: false,
360
- sequence: '\x1b[1',
361
- });
362
- });
285
+ act(() => result.current.subscribe(keyHandler));
286
+ act(() => stdin.write(INCOMPLETE_KITTY_SEQUENCE));
363
287
  // Send Ctrl+C
364
- act(() => {
365
- stdin.pressKey({
366
- name: 'c',
367
- ctrl: true,
368
- meta: false,
369
- shift: false,
370
- sequence: '\x03',
371
- });
372
- });
373
- expect(consoleLogSpy).toHaveBeenCalledWith('[DEBUG] Kitty buffer cleared on Ctrl+C:', '\x1b[1');
288
+ act(() => stdin.write('\x03'));
289
+ expect(consoleLogSpy).toHaveBeenCalledWith('[DEBUG] Input buffer cleared on Ctrl+C:', INCOMPLETE_KITTY_SEQUENCE);
374
290
  // Verify Ctrl+C was handled
375
291
  expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
376
292
  name: 'c',
@@ -381,24 +297,13 @@ describe('KeypressContext - Kitty Protocol', () => {
381
297
  const keyHandler = vi.fn();
382
298
  const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: true, debugKeystrokeLogging: true, children: children }));
383
299
  const { result } = renderHook(() => useKeypressContext(), { wrapper });
384
- act(() => {
385
- result.current.subscribe(keyHandler);
386
- });
300
+ act(() => result.current.subscribe(keyHandler));
387
301
  // Send incomplete kitty sequence
388
- const sequence = '\x1b[12';
389
- act(() => {
390
- stdin.pressKey({
391
- name: undefined,
392
- ctrl: false,
393
- meta: false,
394
- shift: false,
395
- sequence,
396
- });
397
- });
302
+ act(() => stdin.write(INCOMPLETE_KITTY_SEQUENCE));
398
303
  // Verify debug logging for accumulation
399
- expect(consoleLogSpy).toHaveBeenCalledWith('[DEBUG] Kitty buffer accumulating:', sequence);
304
+ expect(consoleLogSpy).toHaveBeenCalledWith('[DEBUG] Input buffer accumulating:', JSON.stringify(INCOMPLETE_KITTY_SEQUENCE));
400
305
  // Verify warning for char codes
401
- expect(consoleWarnSpy).toHaveBeenCalledWith('Kitty sequence buffer has char codes:', [27, 91, 49, 50]);
306
+ expect(consoleWarnSpy).toHaveBeenCalledWith('Input sequence buffer has content:', JSON.stringify(INCOMPLETE_KITTY_SEQUENCE));
402
307
  });
403
308
  });
404
309
  describe('Parameterized functional keys', () => {
@@ -414,6 +319,13 @@ describe('KeypressContext - Kitty Protocol', () => {
414
319
  { sequence: `\x1b[1~`, expected: { name: 'home' } },
415
320
  { sequence: `\x1b[4~`, expected: { name: 'end' } },
416
321
  { sequence: `\x1b[2~`, expected: { name: 'insert' } },
322
+ { sequence: `\x1b[11~`, expected: { name: 'f1' } },
323
+ { sequence: `\x1b[17~`, expected: { name: 'f6' } },
324
+ { sequence: `\x1b[23~`, expected: { name: 'f11' } },
325
+ { sequence: `\x1b[24~`, expected: { name: 'f12' } },
326
+ // Reverse tabs
327
+ { sequence: `\x1b[Z`, expected: { name: 'tab', shift: true } },
328
+ { sequence: `\x1b[1;2Z`, expected: { name: 'tab', shift: true } },
417
329
  // Legacy Arrows
418
330
  {
419
331
  sequence: `\x1b[A`,
@@ -444,56 +356,32 @@ describe('KeypressContext - Kitty Protocol', () => {
444
356
  const keyHandler = vi.fn();
445
357
  const { result } = renderHook(() => useKeypressContext(), { wrapper });
446
358
  act(() => result.current.subscribe(keyHandler));
447
- act(() => stdin.sendKittySequence(sequence));
359
+ act(() => stdin.write(sequence));
448
360
  expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining(expected));
449
361
  });
450
362
  });
451
- describe('Shift+Tab forms', () => {
452
- it.each([
453
- { sequence: `\x1b[Z`, description: 'legacy reverse Tab' },
454
- { sequence: `\x1b[1;2Z`, description: 'parameterized reverse Tab' },
455
- ])('should recognize $description "$sequence" as Shift+Tab', ({ sequence }) => {
456
- const keyHandler = vi.fn();
457
- const { result } = renderHook(() => useKeypressContext(), { wrapper });
458
- act(() => result.current.subscribe(keyHandler));
459
- act(() => stdin.sendKittySequence(sequence));
460
- expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({ name: 'tab', shift: true }));
461
- });
462
- });
463
363
  describe('Double-tap and batching', () => {
464
364
  it('should emit two delete events for double-tap CSI[3~', async () => {
465
- const keyHandler = vi.fn();
466
- const { result } = renderHook(() => useKeypressContext(), { wrapper });
467
- act(() => result.current.subscribe(keyHandler));
468
- act(() => stdin.sendKittySequence(`\x1b[3~`));
469
- act(() => stdin.sendKittySequence(`\x1b[3~`));
365
+ const { keyHandler } = setupKeypressTest(true);
366
+ act(() => stdin.write(`\x1b[3~`));
367
+ act(() => stdin.write(`\x1b[3~`));
470
368
  expect(keyHandler).toHaveBeenNthCalledWith(1, expect.objectContaining({ name: 'delete' }));
471
369
  expect(keyHandler).toHaveBeenNthCalledWith(2, expect.objectContaining({ name: 'delete' }));
472
370
  });
473
371
  it('should parse two concatenated tilde-coded sequences in one chunk', async () => {
474
- const keyHandler = vi.fn();
475
- const { result } = renderHook(() => useKeypressContext(), { wrapper });
476
- act(() => result.current.subscribe(keyHandler));
477
- act(() => stdin.sendKittySequence(`\x1b[3~\x1b[5~`));
372
+ const { keyHandler } = setupKeypressTest(true);
373
+ act(() => stdin.write(`\x1b[3~\x1b[5~`));
478
374
  expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({ name: 'delete' }));
479
375
  expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({ name: 'pageup' }));
480
376
  });
481
377
  it('should ignore incomplete CSI then parse the next complete sequence', async () => {
482
- const keyHandler = vi.fn();
483
- const { result } = renderHook(() => useKeypressContext(), { wrapper });
484
- act(() => result.current.subscribe(keyHandler));
378
+ const { keyHandler } = setupKeypressTest(true);
485
379
  // Incomplete ESC sequence then a complete Delete
486
380
  act(() => {
487
381
  // Provide an incomplete ESC sequence chunk with a real ESC character
488
- stdin.pressKey({
489
- name: undefined,
490
- ctrl: false,
491
- meta: false,
492
- shift: false,
493
- sequence: '\x1b[1;',
494
- });
382
+ stdin.write('\x1b[1;');
495
383
  });
496
- act(() => stdin.sendKittySequence(`\x1b[3~`));
384
+ act(() => stdin.write(`\x1b[3~`));
497
385
  expect(keyHandler).toHaveBeenCalledTimes(1);
498
386
  expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({ name: 'delete' }));
499
387
  });
@@ -502,7 +390,7 @@ describe('KeypressContext - Kitty Protocol', () => {
502
390
  describe('Drag and Drop Handling', () => {
503
391
  let stdin;
504
392
  const mockSetRawMode = vi.fn();
505
- const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: true, children: children }));
393
+ const wrapper = ({ children, kittyProtocolEnabled = true, }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: kittyProtocolEnabled, children: children }));
506
394
  beforeEach(() => {
507
395
  vi.clearAllMocks();
508
396
  vi.useFakeTimers();
@@ -516,254 +404,150 @@ describe('Drag and Drop Handling', () => {
516
404
  vi.useRealTimers();
517
405
  });
518
406
  describe('drag start by quotes', () => {
519
- it('should start collecting when single quote arrives and not broadcast immediately', async () => {
520
- const keyHandler = vi.fn();
521
- const { result } = renderHook(() => useKeypressContext(), { wrapper });
522
- act(() => {
523
- result.current.subscribe(keyHandler);
524
- });
525
- act(() => {
526
- stdin.pressKey({
527
- name: undefined,
528
- ctrl: false,
529
- meta: false,
530
- shift: false,
531
- paste: false,
532
- sequence: SINGLE_QUOTE,
533
- });
534
- });
535
- expect(keyHandler).not.toHaveBeenCalled();
536
- });
537
- it('should start collecting when double quote arrives and not broadcast immediately', async () => {
407
+ it.each([
408
+ { name: 'single quote', quote: SINGLE_QUOTE },
409
+ { name: 'double quote', quote: DOUBLE_QUOTE },
410
+ ])('should start collecting when $name arrives and not broadcast immediately', async ({ quote }) => {
538
411
  const keyHandler = vi.fn();
539
412
  const { result } = renderHook(() => useKeypressContext(), { wrapper });
540
- act(() => {
541
- result.current.subscribe(keyHandler);
542
- });
543
- act(() => {
544
- stdin.pressKey({
545
- name: undefined,
546
- ctrl: false,
547
- meta: false,
548
- shift: false,
549
- paste: false,
550
- sequence: DOUBLE_QUOTE,
551
- });
552
- });
413
+ act(() => result.current.subscribe(keyHandler));
414
+ act(() => stdin.write(quote));
553
415
  expect(keyHandler).not.toHaveBeenCalled();
554
416
  });
555
417
  });
556
418
  describe('drag collection and completion', () => {
557
- it('should collect single character inputs during drag mode', async () => {
558
- const keyHandler = vi.fn();
559
- const { result } = renderHook(() => useKeypressContext(), { wrapper });
560
- act(() => {
561
- result.current.subscribe(keyHandler);
562
- });
563
- // Start by single quote
564
- act(() => {
565
- stdin.pressKey({
566
- name: undefined,
567
- ctrl: false,
568
- meta: false,
569
- shift: false,
570
- paste: false,
571
- sequence: SINGLE_QUOTE,
572
- });
573
- });
574
- // Send single character
575
- act(() => {
576
- stdin.pressKey({
577
- name: undefined,
578
- ctrl: false,
579
- meta: false,
580
- shift: false,
581
- paste: false,
582
- sequence: 'a',
583
- });
584
- });
585
- // Character should not be immediately broadcast
586
- expect(keyHandler).not.toHaveBeenCalled();
587
- // Fast-forward to completion timeout
588
- act(() => {
589
- vi.advanceTimersByTime(DRAG_COMPLETION_TIMEOUT_MS + 10);
590
- });
591
- // Should broadcast the collected path as paste (includes starting quote)
592
- expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
593
- name: '',
594
- paste: true,
595
- sequence: `${SINGLE_QUOTE}a`,
596
- }));
597
- });
598
- it('should collect multiple characters and complete on timeout', async () => {
419
+ it.each([
420
+ {
421
+ name: 'collect single character inputs during drag mode',
422
+ characters: ['a'],
423
+ expectedText: 'a',
424
+ },
425
+ {
426
+ name: 'collect multiple characters and complete on timeout',
427
+ characters: ['p', 'a', 't', 'h'],
428
+ expectedText: 'path',
429
+ },
430
+ ])('should $name', async ({ characters, expectedText }) => {
599
431
  const keyHandler = vi.fn();
600
432
  const { result } = renderHook(() => useKeypressContext(), { wrapper });
601
- act(() => {
602
- result.current.subscribe(keyHandler);
603
- });
604
- // Start by single quote
605
- act(() => {
606
- stdin.pressKey({
607
- name: undefined,
608
- ctrl: false,
609
- meta: false,
610
- shift: false,
611
- paste: false,
612
- sequence: SINGLE_QUOTE,
613
- });
614
- });
615
- // Send multiple characters
616
- act(() => {
617
- stdin.pressKey({
618
- name: undefined,
619
- ctrl: false,
620
- meta: false,
621
- shift: false,
622
- paste: false,
623
- sequence: 'p',
624
- });
625
- });
626
- act(() => {
627
- stdin.pressKey({
628
- name: undefined,
629
- ctrl: false,
630
- meta: false,
631
- shift: false,
632
- paste: false,
633
- sequence: 'a',
634
- });
635
- });
636
- act(() => {
637
- stdin.pressKey({
638
- name: undefined,
639
- ctrl: false,
640
- meta: false,
641
- shift: false,
642
- paste: false,
643
- sequence: 't',
644
- });
645
- });
646
- act(() => {
647
- stdin.pressKey({
648
- name: undefined,
649
- ctrl: false,
650
- meta: false,
651
- shift: false,
652
- paste: false,
653
- sequence: 'h',
654
- });
433
+ act(() => result.current.subscribe(keyHandler));
434
+ act(() => stdin.write(SINGLE_QUOTE));
435
+ characters.forEach((char) => {
436
+ act(() => stdin.write(char));
655
437
  });
656
- // Characters should not be immediately broadcast
657
438
  expect(keyHandler).not.toHaveBeenCalled();
658
- // Fast-forward to completion timeout
659
439
  act(() => {
660
440
  vi.advanceTimersByTime(DRAG_COMPLETION_TIMEOUT_MS + 10);
661
441
  });
662
- // Should broadcast the collected path as paste (includes starting quote)
663
442
  expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
664
443
  name: '',
665
444
  paste: true,
666
- sequence: `${SINGLE_QUOTE}path`,
445
+ sequence: `${SINGLE_QUOTE}${expectedText}`,
667
446
  }));
668
447
  });
669
448
  });
670
449
  });
671
- describe('Terminal-specific Alt+key combinations', () => {
450
+ describe('Kitty Sequence Parsing', () => {
672
451
  let stdin;
673
452
  const mockSetRawMode = vi.fn();
674
- const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: true, children: children }));
453
+ const wrapper = ({ children, kittyProtocolEnabled = true, }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: kittyProtocolEnabled, children: children }));
675
454
  beforeEach(() => {
676
455
  vi.clearAllMocks();
456
+ vi.useFakeTimers();
677
457
  stdin = new MockStdin();
678
458
  useStdin.mockReturnValue({
679
459
  stdin,
680
460
  setRawMode: mockSetRawMode,
681
461
  });
682
462
  });
683
- // Terminals to test
684
- const terminals = ['iTerm2', 'Ghostty', 'MacTerminal', 'VSCodeTerminal'];
685
- // Key mappings: letter -> [keycode, accented character, shouldHaveMeta]
686
- // Note: µ (mu) is sent with meta:false on iTerm2/VSCode
687
- const keys = {
688
- a: [97, 'å', true],
689
- o: [111, 'ø', true],
690
- m: [109, 'µ', false],
691
- };
692
- it.each(terminals.flatMap((terminal) => Object.entries(keys).map(([key, [keycode, accentedChar, shouldHaveMeta]]) => {
693
- if (terminal === 'Ghostty') {
694
- // Ghostty uses kitty protocol sequences
695
- return {
696
- terminal,
697
- key,
698
- kittySequence: `\x1b[${keycode};3u`,
699
- expected: {
700
- name: key,
701
- ctrl: false,
702
- meta: true,
703
- shift: false,
704
- paste: false,
705
- kittyProtocol: true,
706
- },
707
- };
708
- }
709
- else if (terminal === 'MacTerminal') {
710
- // Mac Terminal sends ESC + letter
711
- return {
712
- terminal,
713
- key,
714
- input: {
715
- sequence: `\x1b${key}`,
716
- name: key,
717
- ctrl: false,
718
- meta: true,
719
- shift: false,
720
- paste: false,
721
- },
722
- expected: {
723
- sequence: `\x1b${key}`,
724
- name: key,
725
- ctrl: false,
726
- meta: true,
727
- shift: false,
728
- paste: false,
729
- },
730
- };
731
- }
732
- else {
733
- // iTerm2 and VSCode send accented characters (å, ø, µ)
734
- // Note: µ comes with meta:false but gets converted to m with meta:true
735
- return {
736
- terminal,
737
- key,
738
- input: {
739
- name: key,
740
- ctrl: false,
741
- meta: shouldHaveMeta,
742
- shift: false,
743
- paste: false,
744
- sequence: accentedChar,
745
- },
746
- expected: {
747
- name: key,
748
- ctrl: false,
749
- meta: true, // Always expect meta:true after conversion
750
- shift: false,
751
- paste: false,
752
- sequence: accentedChar,
753
- },
754
- };
755
- }
756
- })))('should handle Alt+$key in $terminal', ({ kittySequence, input, expected, }) => {
757
- const keyHandler = vi.fn();
758
- const { result } = renderHook(() => useKeypressContext(), { wrapper });
759
- act(() => result.current.subscribe(keyHandler));
760
- if (kittySequence) {
761
- act(() => stdin.sendKittySequence(kittySequence));
762
- }
763
- else if (input) {
764
- act(() => stdin.pressKey(input));
765
- }
766
- expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining(expected));
463
+ afterEach(() => {
464
+ vi.useRealTimers();
465
+ });
466
+ describe('Cross-terminal Alt key handling (simulating macOS)', () => {
467
+ let originalPlatform;
468
+ beforeEach(() => {
469
+ originalPlatform = process.platform;
470
+ Object.defineProperty(process, 'platform', {
471
+ value: 'darwin',
472
+ configurable: true,
473
+ });
474
+ });
475
+ afterEach(() => {
476
+ Object.defineProperty(process, 'platform', {
477
+ value: originalPlatform,
478
+ configurable: true,
479
+ });
480
+ });
481
+ // Terminals to test
482
+ const terminals = ['iTerm2', 'Ghostty', 'MacTerminal', 'VSCodeTerminal'];
483
+ // Key mappings: letter -> [keycode, accented character]
484
+ const keys = {
485
+ b: [98, '\u222B'],
486
+ f: [102, '\u0192'],
487
+ m: [109, '\u00B5'],
488
+ };
489
+ it.each(terminals.flatMap((terminal) => Object.entries(keys).map(([key, [keycode, accentedChar]]) => {
490
+ if (terminal === 'Ghostty') {
491
+ // Ghostty uses kitty protocol sequences
492
+ return {
493
+ terminal,
494
+ key,
495
+ chunk: `\x1b[${keycode};3u`,
496
+ expected: {
497
+ name: key,
498
+ ctrl: false,
499
+ meta: true,
500
+ shift: false,
501
+ paste: false,
502
+ kittyProtocol: true,
503
+ },
504
+ };
505
+ }
506
+ else if (terminal === 'MacTerminal') {
507
+ // Mac Terminal sends ESC + letter
508
+ return {
509
+ terminal,
510
+ key,
511
+ kitty: false,
512
+ chunk: `\x1b${key}`,
513
+ expected: {
514
+ sequence: `\x1b${key}`,
515
+ name: key,
516
+ ctrl: false,
517
+ meta: true,
518
+ shift: false,
519
+ paste: false,
520
+ },
521
+ };
522
+ }
523
+ else {
524
+ // iTerm2 and VSCode send accented characters (å, ø, µ)
525
+ // Note: µ (mu) is sent with meta:false on iTerm2/VSCode but
526
+ // gets converted to m with meta:true
527
+ return {
528
+ terminal,
529
+ key,
530
+ chunk: accentedChar,
531
+ expected: {
532
+ name: key,
533
+ ctrl: false,
534
+ meta: true, // Always expect meta:true after conversion
535
+ shift: false,
536
+ paste: false,
537
+ sequence: accentedChar,
538
+ },
539
+ };
540
+ }
541
+ })))('should handle Alt+$key in $terminal', ({ chunk, expected, kitty = true, }) => {
542
+ const keyHandler = vi.fn();
543
+ const testWrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: kitty, children: children }));
544
+ const { result } = renderHook(() => useKeypressContext(), {
545
+ wrapper: testWrapper,
546
+ });
547
+ act(() => result.current.subscribe(keyHandler));
548
+ act(() => stdin.write(chunk));
549
+ expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining(expected));
550
+ });
767
551
  });
768
552
  describe('Backslash key handling', () => {
769
553
  beforeEach(() => {
@@ -773,17 +557,8 @@ describe('Terminal-specific Alt+key combinations', () => {
773
557
  vi.useRealTimers();
774
558
  });
775
559
  it('should treat backslash as a regular keystroke', () => {
776
- const keyHandler = vi.fn();
777
- const { result } = renderHook(() => useKeypressContext(), { wrapper });
778
- act(() => result.current.subscribe(keyHandler));
779
- act(() => stdin.pressKey({
780
- name: undefined,
781
- ctrl: false,
782
- meta: false,
783
- shift: false,
784
- paste: false,
785
- sequence: '\\',
786
- }));
560
+ const { keyHandler } = setupKeypressTest(true);
561
+ act(() => stdin.write('\\'));
787
562
  // Advance timers to trigger the backslash timeout
788
563
  act(() => {
789
564
  vi.runAllTimers();
@@ -794,5 +569,349 @@ describe('Terminal-specific Alt+key combinations', () => {
794
569
  }));
795
570
  });
796
571
  });
572
+ it('should timeout and flush incomplete kitty sequences after 50ms', async () => {
573
+ const keyHandler = vi.fn();
574
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
575
+ act(() => result.current.subscribe(keyHandler));
576
+ act(() => stdin.write(INCOMPLETE_KITTY_SEQUENCE));
577
+ // Should not broadcast immediately
578
+ expect(keyHandler).not.toHaveBeenCalled();
579
+ // Advance time just before timeout
580
+ act(() => vi.advanceTimersByTime(KITTY_SEQUENCE_TIMEOUT_MS - 5));
581
+ // Still shouldn't broadcast
582
+ expect(keyHandler).not.toHaveBeenCalled();
583
+ // Advance past timeout
584
+ act(() => vi.advanceTimersByTime(10));
585
+ // Should now broadcast the incomplete sequence as regular input
586
+ expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
587
+ name: '',
588
+ sequence: INCOMPLETE_KITTY_SEQUENCE,
589
+ paste: false,
590
+ }));
591
+ });
592
+ it('should immediately flush non-kitty CSI sequences', async () => {
593
+ const keyHandler = vi.fn();
594
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
595
+ act(() => result.current.subscribe(keyHandler));
596
+ // Send a CSI sequence that doesn't match kitty patterns
597
+ // ESC[m is SGR reset, not a kitty sequence
598
+ act(() => stdin.write('\x1b[m'));
599
+ // Should broadcast immediately as it's not a valid kitty pattern
600
+ expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
601
+ sequence: '\x1b[m',
602
+ paste: false,
603
+ }));
604
+ });
605
+ it('should parse valid kitty sequences immediately when complete', async () => {
606
+ const keyHandler = vi.fn();
607
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
608
+ act(() => result.current.subscribe(keyHandler));
609
+ // Send complete kitty sequence for Ctrl+A
610
+ act(() => stdin.write('\x1b[97;5u'));
611
+ // Should parse and broadcast immediately
612
+ expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
613
+ name: 'a',
614
+ ctrl: true,
615
+ kittyProtocol: true,
616
+ }));
617
+ });
618
+ it('should handle batched kitty sequences correctly', async () => {
619
+ const keyHandler = vi.fn();
620
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
621
+ act(() => result.current.subscribe(keyHandler));
622
+ // Send Ctrl+a followed by Ctrl+b
623
+ act(() => stdin.write('\x1b[97;5u\x1b[98;5u'));
624
+ // Should parse both sequences
625
+ expect(keyHandler).toHaveBeenCalledTimes(2);
626
+ expect(keyHandler).toHaveBeenNthCalledWith(1, expect.objectContaining({
627
+ name: 'a',
628
+ ctrl: true,
629
+ kittyProtocol: true,
630
+ }));
631
+ expect(keyHandler).toHaveBeenNthCalledWith(2, expect.objectContaining({
632
+ name: 'b',
633
+ ctrl: true,
634
+ kittyProtocol: true,
635
+ }));
636
+ });
637
+ it('should clear kitty buffer and timeout on Ctrl+C', async () => {
638
+ const keyHandler = vi.fn();
639
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
640
+ act(() => result.current.subscribe(keyHandler));
641
+ act(() => stdin.write(INCOMPLETE_KITTY_SEQUENCE));
642
+ // Press Ctrl+C
643
+ act(() => stdin.write('\x03'));
644
+ // Advance past timeout
645
+ act(() => vi.advanceTimersByTime(KITTY_SEQUENCE_TIMEOUT_MS + 10));
646
+ // Should only have received Ctrl+C, not the incomplete sequence
647
+ expect(keyHandler).toHaveBeenCalledTimes(1);
648
+ expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
649
+ name: 'c',
650
+ ctrl: true,
651
+ }));
652
+ });
653
+ it('should handle mixed valid and invalid sequences', async () => {
654
+ const keyHandler = vi.fn();
655
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
656
+ act(() => result.current.subscribe(keyHandler));
657
+ // Send valid kitty sequence followed by invalid CSI
658
+ // Valid enter, then invalid sequence
659
+ act(() => stdin.write('\x1b[13u\x1b[!'));
660
+ // Should parse valid sequence and flush invalid immediately
661
+ expect(keyHandler).toHaveBeenCalledTimes(2);
662
+ expect(keyHandler).toHaveBeenNthCalledWith(1, expect.objectContaining({
663
+ name: 'return',
664
+ kittyProtocol: true,
665
+ }));
666
+ expect(keyHandler).toHaveBeenNthCalledWith(2, expect.objectContaining({
667
+ sequence: '\x1b[!',
668
+ }));
669
+ });
670
+ it('should not buffer sequences when kitty protocol is disabled', async () => {
671
+ const keyHandler = vi.fn();
672
+ const { result } = renderHook(() => useKeypressContext(), {
673
+ wrapper: ({ children }) => wrapper({ children, kittyProtocolEnabled: false }),
674
+ });
675
+ act(() => result.current.subscribe(keyHandler));
676
+ // Send what would be a kitty sequence
677
+ act(() => stdin.write('\x1b[13u'));
678
+ // Should pass through without parsing
679
+ expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
680
+ sequence: '\x1b[13u',
681
+ }));
682
+ expect(keyHandler).not.toHaveBeenCalledWith(expect.objectContaining({
683
+ name: 'return',
684
+ kittyProtocol: true,
685
+ }));
686
+ });
687
+ it('should handle sequences arriving character by character', async () => {
688
+ vi.useRealTimers(); // Required for correct buffering timing.
689
+ const keyHandler = vi.fn();
690
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
691
+ act(() => {
692
+ result.current.subscribe(keyHandler);
693
+ });
694
+ // Send kitty sequence character by character
695
+ const sequence = '\x1b[27u'; // Escape key
696
+ for (const char of sequence) {
697
+ act(() => {
698
+ stdin.emit('data', Buffer.from(char));
699
+ });
700
+ await new Promise((resolve) => setImmediate(resolve));
701
+ }
702
+ // Should parse once complete
703
+ await waitFor(() => {
704
+ expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
705
+ name: 'escape',
706
+ kittyProtocol: true,
707
+ }));
708
+ });
709
+ });
710
+ it('should reset timeout when new input arrives', async () => {
711
+ const keyHandler = vi.fn();
712
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
713
+ act(() => result.current.subscribe(keyHandler));
714
+ // Start incomplete sequence
715
+ act(() => stdin.write('\x1b[97;13'));
716
+ // Advance time partway
717
+ act(() => vi.advanceTimersByTime(30));
718
+ // Add more to sequence
719
+ act(() => stdin.write('5'));
720
+ // Advance time from the first timeout point
721
+ act(() => vi.advanceTimersByTime(25));
722
+ // Should not have timed out yet (timeout restarted)
723
+ expect(keyHandler).not.toHaveBeenCalled();
724
+ // Complete the sequence
725
+ act(() => stdin.write('u'));
726
+ // Should now parse as complete enter key
727
+ expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
728
+ name: 'a',
729
+ kittyProtocol: true,
730
+ }));
731
+ });
732
+ it('should flush incomplete kitty sequence on FOCUS_IN event', async () => {
733
+ const keyHandler = vi.fn();
734
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
735
+ act(() => result.current.subscribe(keyHandler));
736
+ act(() => stdin.write(INCOMPLETE_KITTY_SEQUENCE));
737
+ // Incomplete sequence should be buffered, not broadcast
738
+ expect(keyHandler).not.toHaveBeenCalled();
739
+ // Send FOCUS_IN event
740
+ act(() => stdin.write('\x1b[I'));
741
+ // The buffered sequence should be flushed
742
+ expect(keyHandler).toHaveBeenCalledTimes(1);
743
+ expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
744
+ name: '',
745
+ sequence: INCOMPLETE_KITTY_SEQUENCE,
746
+ paste: false,
747
+ }));
748
+ });
749
+ it('should flush incomplete kitty sequence on FOCUS_OUT event', async () => {
750
+ const keyHandler = vi.fn();
751
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
752
+ act(() => result.current.subscribe(keyHandler));
753
+ act(() => stdin.write(INCOMPLETE_KITTY_SEQUENCE));
754
+ // Incomplete sequence should be buffered, not broadcast
755
+ expect(keyHandler).not.toHaveBeenCalled();
756
+ // Send FOCUS_OUT event
757
+ act(() => stdin.write('\x1b[O'));
758
+ // The buffered sequence should be flushed
759
+ expect(keyHandler).toHaveBeenCalledTimes(1);
760
+ expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
761
+ name: '',
762
+ sequence: INCOMPLETE_KITTY_SEQUENCE,
763
+ paste: false,
764
+ }));
765
+ });
766
+ it('should flush incomplete kitty sequence on paste event', async () => {
767
+ vi.useFakeTimers();
768
+ const keyHandler = vi.fn();
769
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
770
+ act(() => result.current.subscribe(keyHandler));
771
+ act(() => stdin.write(INCOMPLETE_KITTY_SEQUENCE));
772
+ // Incomplete sequence should be buffered, not broadcast
773
+ expect(keyHandler).not.toHaveBeenCalled();
774
+ // Send paste start sequence
775
+ act(() => stdin.write(`\x1b[200~`));
776
+ // The buffered sequence should be flushed
777
+ expect(keyHandler).toHaveBeenCalledTimes(1);
778
+ expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
779
+ name: '',
780
+ sequence: INCOMPLETE_KITTY_SEQUENCE,
781
+ paste: false,
782
+ }));
783
+ // Now send some paste content and end paste to make sure paste still works
784
+ const pastedText = 'hello';
785
+ const PASTE_MODE_SUFFIX = `\x1b[201~`;
786
+ act(() => {
787
+ stdin.write(pastedText);
788
+ stdin.write(PASTE_MODE_SUFFIX);
789
+ });
790
+ act(() => vi.runAllTimers());
791
+ // The paste event should be broadcast
792
+ expect(keyHandler).toHaveBeenCalledTimes(2);
793
+ expect(keyHandler).toHaveBeenNthCalledWith(2, expect.objectContaining({
794
+ paste: true,
795
+ sequence: pastedText,
796
+ }));
797
+ vi.useRealTimers();
798
+ });
799
+ describe('SGR Mouse Handling', () => {
800
+ it('should ignore SGR mouse sequences', async () => {
801
+ const keyHandler = vi.fn();
802
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
803
+ act(() => result.current.subscribe(keyHandler));
804
+ // Send various SGR mouse sequences
805
+ act(() => {
806
+ stdin.write('\x1b[<0;10;20M'); // Mouse press
807
+ stdin.write('\x1b[<0;10;20m'); // Mouse release
808
+ stdin.write('\x1b[<32;30;40M'); // Mouse drag
809
+ stdin.write('\x1b[<64;5;5M'); // Scroll up
810
+ });
811
+ // Should not broadcast any of these as keystrokes
812
+ expect(keyHandler).not.toHaveBeenCalled();
813
+ });
814
+ it('should handle mixed SGR mouse and key sequences', async () => {
815
+ const keyHandler = vi.fn();
816
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
817
+ act(() => result.current.subscribe(keyHandler));
818
+ // Send mouse event then a key press
819
+ act(() => {
820
+ stdin.write('\x1b[<0;10;20M');
821
+ stdin.write('a');
822
+ });
823
+ // Should only broadcast 'a'
824
+ expect(keyHandler).toHaveBeenCalledTimes(1);
825
+ expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({
826
+ name: 'a',
827
+ sequence: 'a',
828
+ }));
829
+ });
830
+ it('should ignore X11 mouse sequences', async () => {
831
+ const keyHandler = vi.fn();
832
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
833
+ act(() => result.current.subscribe(keyHandler));
834
+ // Send X11 mouse sequence: ESC [ M followed by 3 bytes
835
+ // Space is 32. 32+0=32 (button 0), 32+33=65 ('A', col 33), 32+34=66 ('B', row 34)
836
+ const x11Seq = '\x1b[M AB';
837
+ act(() => {
838
+ stdin.write(x11Seq);
839
+ });
840
+ // Should not broadcast as keystrokes
841
+ expect(keyHandler).not.toHaveBeenCalled();
842
+ });
843
+ it('should not flush slow SGR mouse sequences as garbage', async () => {
844
+ vi.useFakeTimers();
845
+ const keyHandler = vi.fn();
846
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
847
+ act(() => result.current.subscribe(keyHandler));
848
+ // Send start of SGR sequence
849
+ act(() => stdin.write('\x1b[<'));
850
+ // Advance time past the normal kitty timeout (50ms)
851
+ act(() => vi.advanceTimersByTime(KITTY_SEQUENCE_TIMEOUT_MS + 10));
852
+ // Send the rest
853
+ act(() => stdin.write('0;37;25M'));
854
+ // Should NOT have flushed the prefix as garbage, and should have consumed the whole thing
855
+ expect(keyHandler).not.toHaveBeenCalled();
856
+ vi.useRealTimers();
857
+ });
858
+ it('should ignore specific SGR mouse sequence sandwiched between keystrokes', async () => {
859
+ const keyHandler = vi.fn();
860
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
861
+ act(() => result.current.subscribe(keyHandler));
862
+ act(() => {
863
+ stdin.write('H');
864
+ stdin.write('\x1b[<64;96;8M');
865
+ stdin.write('I');
866
+ });
867
+ expect(keyHandler).toHaveBeenCalledTimes(2);
868
+ expect(keyHandler).toHaveBeenNthCalledWith(1, expect.objectContaining({ name: 'h', sequence: 'H', shift: true }));
869
+ expect(keyHandler).toHaveBeenNthCalledWith(2, expect.objectContaining({ name: 'i', sequence: 'I', shift: true }));
870
+ });
871
+ });
872
+ describe('Ignored Sequences', () => {
873
+ describe.each([true, false])('with kittyProtocolEnabled = %s', (kittyEnabled) => {
874
+ it.each([
875
+ { name: 'Focus In', sequence: '\x1b[I' },
876
+ { name: 'Focus Out', sequence: '\x1b[O' },
877
+ { name: 'SGR Mouse Release', sequence: '\u001b[<0;44;18m' },
878
+ { name: 'something mouse', sequence: '\u001b[<0;53;19M' },
879
+ { name: 'another mouse', sequence: '\u001b[<0;29;19m' },
880
+ ])('should ignore $name sequence', async ({ sequence }) => {
881
+ vi.useFakeTimers();
882
+ const keyHandler = vi.fn();
883
+ const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: kittyEnabled, children: children }));
884
+ const { result } = renderHook(() => useKeypressContext(), {
885
+ wrapper,
886
+ });
887
+ act(() => result.current.subscribe(keyHandler));
888
+ for (const char of sequence) {
889
+ act(() => {
890
+ stdin.write(char);
891
+ });
892
+ await act(async () => {
893
+ vi.advanceTimersByTime(0);
894
+ });
895
+ }
896
+ act(() => {
897
+ stdin.write('HI');
898
+ });
899
+ expect(keyHandler).toHaveBeenCalledTimes(2);
900
+ expect(keyHandler).toHaveBeenNthCalledWith(1, expect.objectContaining({ name: 'h', sequence: 'H', shift: true }));
901
+ expect(keyHandler).toHaveBeenNthCalledWith(2, expect.objectContaining({ name: 'i', sequence: 'I', shift: true }));
902
+ vi.useRealTimers();
903
+ });
904
+ });
905
+ it('should handle F12 when kittyProtocolEnabled is false', async () => {
906
+ const keyHandler = vi.fn();
907
+ const wrapper = ({ children }) => (_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: children }));
908
+ const { result } = renderHook(() => useKeypressContext(), { wrapper });
909
+ act(() => result.current.subscribe(keyHandler));
910
+ act(() => {
911
+ stdin.write('\u001b[24~');
912
+ });
913
+ expect(keyHandler).toHaveBeenCalledWith(expect.objectContaining({ name: 'f12', sequence: '\u001b[24~' }));
914
+ });
915
+ });
797
916
  });
798
917
  //# sourceMappingURL=KeypressContext.test.js.map