@quantum-ai/gemini-cli 0.45.4 → 0.45.5

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 (1440) hide show
  1. package/README.md +394 -0
  2. package/dist/index.js +1 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/package.json +12 -11
  5. package/dist/src/config/settingsSchema.d.ts +1 -1
  6. package/dist/src/index.d.ts +1 -0
  7. package/dist/src/index.js +1 -0
  8. package/dist/src/index.js.map +1 -1
  9. package/dist/src/ui/App.d.ts +1 -1
  10. package/dist/src/ui/AppContainer.d.ts +1 -1
  11. package/dist/src/ui/IdeIntegrationNudge.d.ts +1 -1
  12. package/dist/src/ui/auth/LoginRestartDialog.d.ts +1 -1
  13. package/dist/src/ui/components/AdminSettingsChangedDialog.d.ts +1 -1
  14. package/dist/src/ui/components/AlternateBufferQuittingDisplay.d.ts +1 -1
  15. package/dist/src/ui/components/AppHeader.d.ts +1 -1
  16. package/dist/src/ui/components/BackgroundTaskDisplay.d.ts +1 -1
  17. package/dist/src/ui/components/Banner.d.ts +1 -1
  18. package/dist/src/ui/components/CliSpinner.d.ts +1 -1
  19. package/dist/src/ui/components/Composer.d.ts +1 -1
  20. package/dist/src/ui/components/ConfigInitDisplay.d.ts +1 -1
  21. package/dist/src/ui/components/ConsentPrompt.d.ts +1 -1
  22. package/dist/src/ui/components/ContextUsageDisplay.d.ts +1 -1
  23. package/dist/src/ui/components/DebugProfiler.d.ts +1 -1
  24. package/dist/src/ui/components/DialogManager.d.ts +1 -1
  25. package/dist/src/ui/components/IdeTrustChangeDialog.d.ts +1 -1
  26. package/dist/src/ui/components/LoopDetectionConfirmation.d.ts +1 -1
  27. package/dist/src/ui/components/MainContent.d.ts +1 -1
  28. package/dist/src/ui/components/ModelQuotaDisplay.d.ts +1 -1
  29. package/dist/src/ui/components/NewAgentsNotification.d.ts +1 -1
  30. package/dist/src/ui/components/Notifications.d.ts +1 -1
  31. package/dist/src/ui/components/QueuedMessageDisplay.d.ts +1 -1
  32. package/dist/src/ui/components/QuittingDisplay.d.ts +1 -1
  33. package/dist/src/ui/components/ShowMoreLines.d.ts +1 -1
  34. package/dist/src/ui/components/SuggestionsDisplay.d.ts +1 -1
  35. package/dist/src/ui/components/Table.d.ts +1 -1
  36. package/dist/src/ui/components/UpdateNotification.d.ts +1 -1
  37. package/dist/src/ui/components/shared/SlicingMaxSizedBox.d.ts +1 -1
  38. package/dist/src/ui/components/triage/TriageDuplicates.d.ts +1 -1
  39. package/dist/src/ui/components/triage/TriageIssues.d.ts +1 -1
  40. package/dist/src/ui/contexts/KeypressContext.d.ts +1 -1
  41. package/dist/src/ui/contexts/MouseContext.d.ts +1 -1
  42. package/dist/src/ui/contexts/TerminalContext.d.ts +1 -1
  43. package/dist/src/ui/contexts/VimModeContext.d.ts +1 -1
  44. package/dist/src/ui/hooks/useExtensionUpdates.d.ts +2 -2
  45. package/dist/src/ui/hooks/useInlineEditBuffer.d.ts +1 -1
  46. package/dist/src/ui/hooks/useStateAndRef.d.ts +1 -1
  47. package/dist/src/ui/privacy/CloudFreePrivacyNotice.d.ts +1 -1
  48. package/dist/src/ui/privacy/CloudPaidPrivacyNotice.d.ts +1 -1
  49. package/dist/src/ui/privacy/GeminiPrivacyNotice.d.ts +1 -1
  50. package/dist/src/ui/privacy/PrivacyNotice.d.ts +1 -1
  51. package/dist/src/utils/devtoolsService.js +1 -1
  52. package/dist/src/utils/devtoolsService.js.map +1 -1
  53. package/dist/tsconfig.tsbuildinfo +1 -1
  54. package/package.json +12 -11
  55. package/dist/src/acp/acpCommandHandler.test.d.ts +0 -6
  56. package/dist/src/acp/acpCommandHandler.test.js +0 -28
  57. package/dist/src/acp/acpCommandHandler.test.js.map +0 -1
  58. package/dist/src/acp/acpErrors.test.d.ts +0 -6
  59. package/dist/src/acp/acpErrors.test.js +0 -38
  60. package/dist/src/acp/acpErrors.test.js.map +0 -1
  61. package/dist/src/acp/acpFileSystemService.test.d.ts +0 -6
  62. package/dist/src/acp/acpFileSystemService.test.js +0 -162
  63. package/dist/src/acp/acpFileSystemService.test.js.map +0 -1
  64. package/dist/src/acp/acpResume.test.d.ts +0 -6
  65. package/dist/src/acp/acpResume.test.js +0 -260
  66. package/dist/src/acp/acpResume.test.js.map +0 -1
  67. package/dist/src/acp/acpRpcDispatcher.test.d.ts +0 -6
  68. package/dist/src/acp/acpRpcDispatcher.test.js +0 -238
  69. package/dist/src/acp/acpRpcDispatcher.test.js.map +0 -1
  70. package/dist/src/acp/acpSession.test.d.ts +0 -6
  71. package/dist/src/acp/acpSession.test.js +0 -742
  72. package/dist/src/acp/acpSession.test.js.map +0 -1
  73. package/dist/src/acp/acpSessionManager.test.d.ts +0 -6
  74. package/dist/src/acp/acpSessionManager.test.js +0 -283
  75. package/dist/src/acp/acpSessionManager.test.js.map +0 -1
  76. package/dist/src/acp/commands/extensions.test.d.ts +0 -6
  77. package/dist/src/acp/commands/extensions.test.js +0 -70
  78. package/dist/src/acp/commands/extensions.test.js.map +0 -1
  79. package/dist/src/acp/commands/help.test.d.ts +0 -6
  80. package/dist/src/acp/commands/help.test.js +0 -40
  81. package/dist/src/acp/commands/help.test.js.map +0 -1
  82. package/dist/src/acp/commands/restore.test.d.ts +0 -6
  83. package/dist/src/acp/commands/restore.test.js +0 -173
  84. package/dist/src/acp/commands/restore.test.js.map +0 -1
  85. package/dist/src/commands/extensions/configure.test.d.ts +0 -1
  86. package/dist/src/commands/extensions/configure.test.js +0 -195
  87. package/dist/src/commands/extensions/configure.test.js.map +0 -1
  88. package/dist/src/commands/extensions/disable.test.d.ts +0 -6
  89. package/dist/src/commands/extensions/disable.test.js +0 -169
  90. package/dist/src/commands/extensions/disable.test.js.map +0 -1
  91. package/dist/src/commands/extensions/enable.test.d.ts +0 -6
  92. package/dist/src/commands/extensions/enable.test.js +0 -199
  93. package/dist/src/commands/extensions/enable.test.js.map +0 -1
  94. package/dist/src/commands/extensions/install.test.d.ts +0 -6
  95. package/dist/src/commands/extensions/install.test.js +0 -311
  96. package/dist/src/commands/extensions/install.test.js.map +0 -1
  97. package/dist/src/commands/extensions/link.test.d.ts +0 -6
  98. package/dist/src/commands/extensions/link.test.js +0 -121
  99. package/dist/src/commands/extensions/link.test.js.map +0 -1
  100. package/dist/src/commands/extensions/list.test.d.ts +0 -6
  101. package/dist/src/commands/extensions/list.test.js +0 -132
  102. package/dist/src/commands/extensions/list.test.js.map +0 -1
  103. package/dist/src/commands/extensions/new.test.d.ts +0 -6
  104. package/dist/src/commands/extensions/new.test.js +0 -62
  105. package/dist/src/commands/extensions/new.test.js.map +0 -1
  106. package/dist/src/commands/extensions/uninstall.test.d.ts +0 -6
  107. package/dist/src/commands/extensions/uninstall.test.js +0 -240
  108. package/dist/src/commands/extensions/uninstall.test.js.map +0 -1
  109. package/dist/src/commands/extensions/update.test.d.ts +0 -6
  110. package/dist/src/commands/extensions/update.test.js +0 -196
  111. package/dist/src/commands/extensions/update.test.js.map +0 -1
  112. package/dist/src/commands/extensions/validate.test.d.ts +0 -6
  113. package/dist/src/commands/extensions/validate.test.js +0 -96
  114. package/dist/src/commands/extensions/validate.test.js.map +0 -1
  115. package/dist/src/commands/extensions.test.d.ts +0 -6
  116. package/dist/src/commands/extensions.test.js +0 -67
  117. package/dist/src/commands/extensions.test.js.map +0 -1
  118. package/dist/src/commands/gemma/logs.test.d.ts +0 -6
  119. package/dist/src/commands/gemma/logs.test.js +0 -122
  120. package/dist/src/commands/gemma/logs.test.js.map +0 -1
  121. package/dist/src/commands/gemma/platform.test.d.ts +0 -6
  122. package/dist/src/commands/gemma/platform.test.js +0 -108
  123. package/dist/src/commands/gemma/platform.test.js.map +0 -1
  124. package/dist/src/commands/gemma/setup.test.d.ts +0 -6
  125. package/dist/src/commands/gemma/setup.test.js +0 -36
  126. package/dist/src/commands/gemma/setup.test.js.map +0 -1
  127. package/dist/src/commands/gemma/stop.test.d.ts +0 -6
  128. package/dist/src/commands/gemma/stop.test.js +0 -89
  129. package/dist/src/commands/gemma/stop.test.js.map +0 -1
  130. package/dist/src/commands/hooks/migrate.test.d.ts +0 -6
  131. package/dist/src/commands/hooks/migrate.test.js +0 -388
  132. package/dist/src/commands/hooks/migrate.test.js.map +0 -1
  133. package/dist/src/commands/mcp/add.test.d.ts +0 -6
  134. package/dist/src/commands/mcp/add.test.js +0 -274
  135. package/dist/src/commands/mcp/add.test.js.map +0 -1
  136. package/dist/src/commands/mcp/list.test.d.ts +0 -6
  137. package/dist/src/commands/mcp/list.test.js +0 -477
  138. package/dist/src/commands/mcp/list.test.js.map +0 -1
  139. package/dist/src/commands/mcp/remove.test.d.ts +0 -6
  140. package/dist/src/commands/mcp/remove.test.js +0 -206
  141. package/dist/src/commands/mcp/remove.test.js.map +0 -1
  142. package/dist/src/commands/mcp.test.d.ts +0 -6
  143. package/dist/src/commands/mcp.test.js +0 -64
  144. package/dist/src/commands/mcp.test.js.map +0 -1
  145. package/dist/src/commands/skills/disable.test.d.ts +0 -6
  146. package/dist/src/commands/skills/disable.test.js +0 -93
  147. package/dist/src/commands/skills/disable.test.js.map +0 -1
  148. package/dist/src/commands/skills/enable.test.d.ts +0 -6
  149. package/dist/src/commands/skills/enable.test.js +0 -104
  150. package/dist/src/commands/skills/enable.test.js.map +0 -1
  151. package/dist/src/commands/skills/install.test.d.ts +0 -6
  152. package/dist/src/commands/skills/install.test.js +0 -99
  153. package/dist/src/commands/skills/install.test.js.map +0 -1
  154. package/dist/src/commands/skills/link.test.d.ts +0 -6
  155. package/dist/src/commands/skills/link.test.js +0 -53
  156. package/dist/src/commands/skills/link.test.js.map +0 -1
  157. package/dist/src/commands/skills/list.test.d.ts +0 -6
  158. package/dist/src/commands/skills/list.test.js +0 -127
  159. package/dist/src/commands/skills/list.test.js.map +0 -1
  160. package/dist/src/commands/skills/uninstall.test.d.ts +0 -6
  161. package/dist/src/commands/skills/uninstall.test.js +0 -65
  162. package/dist/src/commands/skills/uninstall.test.js.map +0 -1
  163. package/dist/src/commands/skills.test.d.ts +0 -6
  164. package/dist/src/commands/skills.test.js +0 -49
  165. package/dist/src/commands/skills.test.js.map +0 -1
  166. package/dist/src/commands/utils.test.d.ts +0 -6
  167. package/dist/src/commands/utils.test.js +0 -35
  168. package/dist/src/commands/utils.test.js.map +0 -1
  169. package/dist/src/config/auth.test.d.ts +0 -6
  170. package/dist/src/config/auth.test.js +0 -96
  171. package/dist/src/config/auth.test.js.map +0 -1
  172. package/dist/src/config/config.integration.test.d.ts +0 -6
  173. package/dist/src/config/config.integration.test.js +0 -205
  174. package/dist/src/config/config.integration.test.js.map +0 -1
  175. package/dist/src/config/config.test.d.ts +0 -6
  176. package/dist/src/config/config.test.js +0 -3124
  177. package/dist/src/config/config.test.js.map +0 -1
  178. package/dist/src/config/extension-manager-agents.test.d.ts +0 -6
  179. package/dist/src/config/extension-manager-agents.test.js +0 -116
  180. package/dist/src/config/extension-manager-agents.test.js.map +0 -1
  181. package/dist/src/config/extension-manager-hydration.test.d.ts +0 -6
  182. package/dist/src/config/extension-manager-hydration.test.js +0 -262
  183. package/dist/src/config/extension-manager-hydration.test.js.map +0 -1
  184. package/dist/src/config/extension-manager-permissions.test.d.ts +0 -6
  185. package/dist/src/config/extension-manager-permissions.test.js +0 -107
  186. package/dist/src/config/extension-manager-permissions.test.js.map +0 -1
  187. package/dist/src/config/extension-manager-scope.test.d.ts +0 -6
  188. package/dist/src/config/extension-manager-scope.test.js +0 -158
  189. package/dist/src/config/extension-manager-scope.test.js.map +0 -1
  190. package/dist/src/config/extension-manager-skills.test.d.ts +0 -6
  191. package/dist/src/config/extension-manager-skills.test.js +0 -157
  192. package/dist/src/config/extension-manager-skills.test.js.map +0 -1
  193. package/dist/src/config/extension-manager.test.d.ts +0 -6
  194. package/dist/src/config/extension-manager.test.js +0 -430
  195. package/dist/src/config/extension-manager.test.js.map +0 -1
  196. package/dist/src/config/extension.test.d.ts +0 -6
  197. package/dist/src/config/extension.test.js +0 -1800
  198. package/dist/src/config/extension.test.js.map +0 -1
  199. package/dist/src/config/extensionRegistryClient.test.d.ts +0 -6
  200. package/dist/src/config/extensionRegistryClient.test.js +0 -261
  201. package/dist/src/config/extensionRegistryClient.test.js.map +0 -1
  202. package/dist/src/config/extensions/consent.test.d.ts +0 -6
  203. package/dist/src/config/extensions/consent.test.js +0 -302
  204. package/dist/src/config/extensions/consent.test.js.map +0 -1
  205. package/dist/src/config/extensions/extensionEnablement.test.d.ts +0 -6
  206. package/dist/src/config/extensions/extensionEnablement.test.js +0 -404
  207. package/dist/src/config/extensions/extensionEnablement.test.js.map +0 -1
  208. package/dist/src/config/extensions/extensionSettings.test.d.ts +0 -6
  209. package/dist/src/config/extensions/extensionSettings.test.js +0 -575
  210. package/dist/src/config/extensions/extensionSettings.test.js.map +0 -1
  211. package/dist/src/config/extensions/extensionUpdates.test.d.ts +0 -6
  212. package/dist/src/config/extensions/extensionUpdates.test.js +0 -265
  213. package/dist/src/config/extensions/extensionUpdates.test.js.map +0 -1
  214. package/dist/src/config/extensions/github.test.d.ts +0 -6
  215. package/dist/src/config/extensions/github.test.js +0 -454
  216. package/dist/src/config/extensions/github.test.js.map +0 -1
  217. package/dist/src/config/extensions/github_fetch.test.d.ts +0 -6
  218. package/dist/src/config/extensions/github_fetch.test.js +0 -171
  219. package/dist/src/config/extensions/github_fetch.test.js.map +0 -1
  220. package/dist/src/config/extensions/storage.test.d.ts +0 -6
  221. package/dist/src/config/extensions/storage.test.js +0 -64
  222. package/dist/src/config/extensions/storage.test.js.map +0 -1
  223. package/dist/src/config/extensions/update.test.d.ts +0 -6
  224. package/dist/src/config/extensions/update.test.js +0 -296
  225. package/dist/src/config/extensions/update.test.js.map +0 -1
  226. package/dist/src/config/extensions/variables.test.d.ts +0 -6
  227. package/dist/src/config/extensions/variables.test.js +0 -119
  228. package/dist/src/config/extensions/variables.test.js.map +0 -1
  229. package/dist/src/config/footerItems.test.d.ts +0 -6
  230. package/dist/src/config/footerItems.test.js +0 -180
  231. package/dist/src/config/footerItems.test.js.map +0 -1
  232. package/dist/src/config/mcp/mcpServerEnablement.test.d.ts +0 -6
  233. package/dist/src/config/mcp/mcpServerEnablement.test.js +0 -148
  234. package/dist/src/config/mcp/mcpServerEnablement.test.js.map +0 -1
  235. package/dist/src/config/mutual-exclusivity.test.d.ts +0 -6
  236. package/dist/src/config/mutual-exclusivity.test.js +0 -33
  237. package/dist/src/config/mutual-exclusivity.test.js.map +0 -1
  238. package/dist/src/config/policy-engine.integration.test.d.ts +0 -6
  239. package/dist/src/config/policy-engine.integration.test.js +0 -394
  240. package/dist/src/config/policy-engine.integration.test.js.map +0 -1
  241. package/dist/src/config/policy.test.d.ts +0 -6
  242. package/dist/src/config/policy.test.js +0 -199
  243. package/dist/src/config/policy.test.js.map +0 -1
  244. package/dist/src/config/sandboxConfig.test.d.ts +0 -6
  245. package/dist/src/config/sandboxConfig.test.js +0 -401
  246. package/dist/src/config/sandboxConfig.test.js.map +0 -1
  247. package/dist/src/config/settingPaths.test.d.ts +0 -6
  248. package/dist/src/config/settingPaths.test.js +0 -22
  249. package/dist/src/config/settingPaths.test.js.map +0 -1
  250. package/dist/src/config/settings-env-isolation.test.d.ts +0 -6
  251. package/dist/src/config/settings-env-isolation.test.js +0 -188
  252. package/dist/src/config/settings-env-isolation.test.js.map +0 -1
  253. package/dist/src/config/settings-validation.test.d.ts +0 -6
  254. package/dist/src/config/settings-validation.test.js +0 -464
  255. package/dist/src/config/settings-validation.test.js.map +0 -1
  256. package/dist/src/config/settings.test.d.ts +0 -6
  257. package/dist/src/config/settings.test.js +0 -2660
  258. package/dist/src/config/settings.test.js.map +0 -1
  259. package/dist/src/config/settingsSchema.test.d.ts +0 -6
  260. package/dist/src/config/settingsSchema.test.js +0 -450
  261. package/dist/src/config/settingsSchema.test.js.map +0 -1
  262. package/dist/src/config/settings_repro.test.d.ts +0 -6
  263. package/dist/src/config/settings_repro.test.js +0 -163
  264. package/dist/src/config/settings_repro.test.js.map +0 -1
  265. package/dist/src/config/settings_validation_warning.test.d.ts +0 -6
  266. package/dist/src/config/settings_validation_warning.test.js +0 -124
  267. package/dist/src/config/settings_validation_warning.test.js.map +0 -1
  268. package/dist/src/config/skipExtensions.test.d.ts +0 -6
  269. package/dist/src/config/skipExtensions.test.js +0 -49
  270. package/dist/src/config/skipExtensions.test.js.map +0 -1
  271. package/dist/src/config/trustedFolders.test.d.ts +0 -6
  272. package/dist/src/config/trustedFolders.test.js +0 -411
  273. package/dist/src/config/trustedFolders.test.js.map +0 -1
  274. package/dist/src/config/workspace-policy-cli.test.d.ts +0 -6
  275. package/dist/src/config/workspace-policy-cli.test.js +0 -204
  276. package/dist/src/config/workspace-policy-cli.test.js.map +0 -1
  277. package/dist/src/core/auth.test.d.ts +0 -6
  278. package/dist/src/core/auth.test.js +0 -93
  279. package/dist/src/core/auth.test.js.map +0 -1
  280. package/dist/src/core/initializer.test.d.ts +0 -6
  281. package/dist/src/core/initializer.test.js +0 -111
  282. package/dist/src/core/initializer.test.js.map +0 -1
  283. package/dist/src/core/theme.test.d.ts +0 -6
  284. package/dist/src/core/theme.test.js +0 -46
  285. package/dist/src/core/theme.test.js.map +0 -1
  286. package/dist/src/deferred.test.d.ts +0 -6
  287. package/dist/src/deferred.test.js +0 -180
  288. package/dist/src/deferred.test.js.map +0 -1
  289. package/dist/src/gemini.test.d.ts +0 -6
  290. package/dist/src/gemini.test.js +0 -1432
  291. package/dist/src/gemini.test.js.map +0 -1
  292. package/dist/src/gemini_cleanup.test.d.ts +0 -6
  293. package/dist/src/gemini_cleanup.test.js +0 -391
  294. package/dist/src/gemini_cleanup.test.js.map +0 -1
  295. package/dist/src/integration-tests/modelSteering.test.d.ts +0 -6
  296. package/dist/src/integration-tests/modelSteering.test.js +0 -62
  297. package/dist/src/integration-tests/modelSteering.test.js.map +0 -1
  298. package/dist/src/nonInteractiveCli.test.d.ts +0 -6
  299. package/dist/src/nonInteractiveCli.test.js +0 -1921
  300. package/dist/src/nonInteractiveCli.test.js.map +0 -1
  301. package/dist/src/nonInteractiveCliAgentSession.test.d.ts +0 -6
  302. package/dist/src/nonInteractiveCliAgentSession.test.js +0 -2015
  303. package/dist/src/nonInteractiveCliAgentSession.test.js.map +0 -1
  304. package/dist/src/output-redirection.test.d.ts +0 -6
  305. package/dist/src/output-redirection.test.js +0 -77
  306. package/dist/src/output-redirection.test.js.map +0 -1
  307. package/dist/src/services/BuiltinCommandLoader.test.d.ts +0 -6
  308. package/dist/src/services/BuiltinCommandLoader.test.js +0 -369
  309. package/dist/src/services/BuiltinCommandLoader.test.js.map +0 -1
  310. package/dist/src/services/CommandService.test.d.ts +0 -6
  311. package/dist/src/services/CommandService.test.js +0 -74
  312. package/dist/src/services/CommandService.test.js.map +0 -1
  313. package/dist/src/services/FileCommandLoader.test.d.ts +0 -6
  314. package/dist/src/services/FileCommandLoader.test.js +0 -1128
  315. package/dist/src/services/FileCommandLoader.test.js.map +0 -1
  316. package/dist/src/services/McpPromptLoader.test.d.ts +0 -6
  317. package/dist/src/services/McpPromptLoader.test.js +0 -411
  318. package/dist/src/services/McpPromptLoader.test.js.map +0 -1
  319. package/dist/src/services/SkillCommandLoader.test.d.ts +0 -6
  320. package/dist/src/services/SkillCommandLoader.test.js +0 -113
  321. package/dist/src/services/SkillCommandLoader.test.js.map +0 -1
  322. package/dist/src/services/SlashCommandConflictHandler.test.d.ts +0 -6
  323. package/dist/src/services/SlashCommandConflictHandler.test.js +0 -144
  324. package/dist/src/services/SlashCommandConflictHandler.test.js.map +0 -1
  325. package/dist/src/services/SlashCommandResolver.test.d.ts +0 -6
  326. package/dist/src/services/SlashCommandResolver.test.js +0 -186
  327. package/dist/src/services/SlashCommandResolver.test.js.map +0 -1
  328. package/dist/src/services/liteRtServerManager.test.d.ts +0 -6
  329. package/dist/src/services/liteRtServerManager.test.js +0 -54
  330. package/dist/src/services/liteRtServerManager.test.js.map +0 -1
  331. package/dist/src/services/prompt-processors/argumentProcessor.test.d.ts +0 -6
  332. package/dist/src/services/prompt-processors/argumentProcessor.test.js +0 -40
  333. package/dist/src/services/prompt-processors/argumentProcessor.test.js.map +0 -1
  334. package/dist/src/services/prompt-processors/atFileProcessor.test.d.ts +0 -6
  335. package/dist/src/services/prompt-processors/atFileProcessor.test.js +0 -177
  336. package/dist/src/services/prompt-processors/atFileProcessor.test.js.map +0 -1
  337. package/dist/src/services/prompt-processors/injectionParser.test.d.ts +0 -6
  338. package/dist/src/services/prompt-processors/injectionParser.test.js +0 -189
  339. package/dist/src/services/prompt-processors/injectionParser.test.js.map +0 -1
  340. package/dist/src/services/prompt-processors/shellProcessor.test.d.ts +0 -6
  341. package/dist/src/services/prompt-processors/shellProcessor.test.js +0 -525
  342. package/dist/src/services/prompt-processors/shellProcessor.test.js.map +0 -1
  343. package/dist/src/test-utils/AppRig.test.d.ts +0 -6
  344. package/dist/src/test-utils/AppRig.test.js +0 -60
  345. package/dist/src/test-utils/AppRig.test.js.map +0 -1
  346. package/dist/src/test-utils/mockCommandContext.test.d.ts +0 -6
  347. package/dist/src/test-utils/mockCommandContext.test.js +0 -51
  348. package/dist/src/test-utils/mockCommandContext.test.js.map +0 -1
  349. package/dist/src/test-utils/render.test.d.ts +0 -6
  350. package/dist/src/test-utils/render.test.js +0 -84
  351. package/dist/src/test-utils/render.test.js.map +0 -1
  352. package/dist/src/ui/App.test.d.ts +0 -6
  353. package/dist/src/ui/App.test.js +0 -244
  354. package/dist/src/ui/App.test.js.map +0 -1
  355. package/dist/src/ui/AppContainer.test.d.ts +0 -6
  356. package/dist/src/ui/AppContainer.test.js +0 -2824
  357. package/dist/src/ui/AppContainer.test.js.map +0 -1
  358. package/dist/src/ui/IdeIntegrationNudge.test.d.ts +0 -6
  359. package/dist/src/ui/IdeIntegrationNudge.test.js +0 -149
  360. package/dist/src/ui/IdeIntegrationNudge.test.js.map +0 -1
  361. package/dist/src/ui/ToolConfirmationFullFrame.test.d.ts +0 -1
  362. package/dist/src/ui/ToolConfirmationFullFrame.test.js +0 -153
  363. package/dist/src/ui/ToolConfirmationFullFrame.test.js.map +0 -1
  364. package/dist/src/ui/auth/ApiAuthDialog.test.d.ts +0 -6
  365. package/dist/src/ui/auth/ApiAuthDialog.test.js +0 -127
  366. package/dist/src/ui/auth/ApiAuthDialog.test.js.map +0 -1
  367. package/dist/src/ui/auth/AuthDialog.test.d.ts +0 -6
  368. package/dist/src/ui/auth/AuthDialog.test.js +0 -350
  369. package/dist/src/ui/auth/AuthDialog.test.js.map +0 -1
  370. package/dist/src/ui/auth/AuthInProgress.test.d.ts +0 -6
  371. package/dist/src/ui/auth/AuthInProgress.test.js +0 -99
  372. package/dist/src/ui/auth/AuthInProgress.test.js.map +0 -1
  373. package/dist/src/ui/auth/BannedAccountDialog.test.d.ts +0 -6
  374. package/dist/src/ui/auth/BannedAccountDialog.test.js +0 -141
  375. package/dist/src/ui/auth/BannedAccountDialog.test.js.map +0 -1
  376. package/dist/src/ui/auth/LoginRestartDialog.test.d.ts +0 -6
  377. package/dist/src/ui/auth/LoginRestartDialog.test.js +0 -79
  378. package/dist/src/ui/auth/LoginRestartDialog.test.js.map +0 -1
  379. package/dist/src/ui/auth/useAuth.test.d.ts +0 -6
  380. package/dist/src/ui/auth/useAuth.test.js +0 -214
  381. package/dist/src/ui/auth/useAuth.test.js.map +0 -1
  382. package/dist/src/ui/commands/aboutCommand.test.d.ts +0 -6
  383. package/dist/src/ui/commands/aboutCommand.test.js +0 -145
  384. package/dist/src/ui/commands/aboutCommand.test.js.map +0 -1
  385. package/dist/src/ui/commands/agentsCommand.test.d.ts +0 -6
  386. package/dist/src/ui/commands/agentsCommand.test.js +0 -382
  387. package/dist/src/ui/commands/agentsCommand.test.js.map +0 -1
  388. package/dist/src/ui/commands/authCommand.test.d.ts +0 -6
  389. package/dist/src/ui/commands/authCommand.test.js +0 -103
  390. package/dist/src/ui/commands/authCommand.test.js.map +0 -1
  391. package/dist/src/ui/commands/bugCommand.test.d.ts +0 -6
  392. package/dist/src/ui/commands/bugCommand.test.js +0 -305
  393. package/dist/src/ui/commands/bugCommand.test.js.map +0 -1
  394. package/dist/src/ui/commands/bugMemoryCommand.test.d.ts +0 -6
  395. package/dist/src/ui/commands/bugMemoryCommand.test.js +0 -100
  396. package/dist/src/ui/commands/bugMemoryCommand.test.js.map +0 -1
  397. package/dist/src/ui/commands/chatCommand.test.d.ts +0 -6
  398. package/dist/src/ui/commands/chatCommand.test.js +0 -627
  399. package/dist/src/ui/commands/chatCommand.test.js.map +0 -1
  400. package/dist/src/ui/commands/clearCommand.test.d.ts +0 -6
  401. package/dist/src/ui/commands/clearCommand.test.js +0 -98
  402. package/dist/src/ui/commands/clearCommand.test.js.map +0 -1
  403. package/dist/src/ui/commands/commandsCommand.test.d.ts +0 -6
  404. package/dist/src/ui/commands/commandsCommand.test.js +0 -115
  405. package/dist/src/ui/commands/commandsCommand.test.js.map +0 -1
  406. package/dist/src/ui/commands/compressCommand.test.d.ts +0 -6
  407. package/dist/src/ui/commands/compressCommand.test.js +0 -110
  408. package/dist/src/ui/commands/compressCommand.test.js.map +0 -1
  409. package/dist/src/ui/commands/copyCommand.test.d.ts +0 -6
  410. package/dist/src/ui/commands/copyCommand.test.js +0 -244
  411. package/dist/src/ui/commands/copyCommand.test.js.map +0 -1
  412. package/dist/src/ui/commands/corgiCommand.test.d.ts +0 -6
  413. package/dist/src/ui/commands/corgiCommand.test.js +0 -28
  414. package/dist/src/ui/commands/corgiCommand.test.js.map +0 -1
  415. package/dist/src/ui/commands/directoryCommand.test.d.ts +0 -6
  416. package/dist/src/ui/commands/directoryCommand.test.js +0 -365
  417. package/dist/src/ui/commands/directoryCommand.test.js.map +0 -1
  418. package/dist/src/ui/commands/docsCommand.test.d.ts +0 -6
  419. package/dist/src/ui/commands/docsCommand.test.js +0 -72
  420. package/dist/src/ui/commands/docsCommand.test.js.map +0 -1
  421. package/dist/src/ui/commands/editorCommand.test.d.ts +0 -6
  422. package/dist/src/ui/commands/editorCommand.test.js +0 -27
  423. package/dist/src/ui/commands/editorCommand.test.js.map +0 -1
  424. package/dist/src/ui/commands/exportSessionCommand.test.d.ts +0 -6
  425. package/dist/src/ui/commands/exportSessionCommand.test.js +0 -100
  426. package/dist/src/ui/commands/exportSessionCommand.test.js.map +0 -1
  427. package/dist/src/ui/commands/extensionsCommand.test.d.ts +0 -6
  428. package/dist/src/ui/commands/extensionsCommand.test.js +0 -947
  429. package/dist/src/ui/commands/extensionsCommand.test.js.map +0 -1
  430. package/dist/src/ui/commands/helpCommand.test.d.ts +0 -6
  431. package/dist/src/ui/commands/helpCommand.test.js +0 -94
  432. package/dist/src/ui/commands/helpCommand.test.js.map +0 -1
  433. package/dist/src/ui/commands/hooksCommand.test.d.ts +0 -6
  434. package/dist/src/ui/commands/hooksCommand.test.js +0 -562
  435. package/dist/src/ui/commands/hooksCommand.test.js.map +0 -1
  436. package/dist/src/ui/commands/ideCommand.test.d.ts +0 -6
  437. package/dist/src/ui/commands/ideCommand.test.js +0 -205
  438. package/dist/src/ui/commands/ideCommand.test.js.map +0 -1
  439. package/dist/src/ui/commands/initCommand.test.d.ts +0 -6
  440. package/dist/src/ui/commands/initCommand.test.js +0 -86
  441. package/dist/src/ui/commands/initCommand.test.js.map +0 -1
  442. package/dist/src/ui/commands/mcpCommand.test.d.ts +0 -6
  443. package/dist/src/ui/commands/mcpCommand.test.js +0 -231
  444. package/dist/src/ui/commands/mcpCommand.test.js.map +0 -1
  445. package/dist/src/ui/commands/memoryCommand.test.d.ts +0 -6
  446. package/dist/src/ui/commands/memoryCommand.test.js +0 -361
  447. package/dist/src/ui/commands/memoryCommand.test.js.map +0 -1
  448. package/dist/src/ui/commands/modelCommand.test.d.ts +0 -6
  449. package/dist/src/ui/commands/modelCommand.test.js +0 -135
  450. package/dist/src/ui/commands/modelCommand.test.js.map +0 -1
  451. package/dist/src/ui/commands/permissionsCommand.test.d.ts +0 -6
  452. package/dist/src/ui/commands/permissionsCommand.test.js +0 -86
  453. package/dist/src/ui/commands/permissionsCommand.test.js.map +0 -1
  454. package/dist/src/ui/commands/planCommand.test.d.ts +0 -6
  455. package/dist/src/ui/commands/planCommand.test.js +0 -146
  456. package/dist/src/ui/commands/planCommand.test.js.map +0 -1
  457. package/dist/src/ui/commands/policiesCommand.test.d.ts +0 -6
  458. package/dist/src/ui/commands/policiesCommand.test.js +0 -133
  459. package/dist/src/ui/commands/policiesCommand.test.js.map +0 -1
  460. package/dist/src/ui/commands/privacyCommand.test.d.ts +0 -6
  461. package/dist/src/ui/commands/privacyCommand.test.js +0 -32
  462. package/dist/src/ui/commands/privacyCommand.test.js.map +0 -1
  463. package/dist/src/ui/commands/quitCommand.test.d.ts +0 -6
  464. package/dist/src/ui/commands/quitCommand.test.js +0 -95
  465. package/dist/src/ui/commands/quitCommand.test.js.map +0 -1
  466. package/dist/src/ui/commands/restoreCommand.test.d.ts +0 -6
  467. package/dist/src/ui/commands/restoreCommand.test.js +0 -193
  468. package/dist/src/ui/commands/restoreCommand.test.js.map +0 -1
  469. package/dist/src/ui/commands/resumeCommand.test.d.ts +0 -6
  470. package/dist/src/ui/commands/resumeCommand.test.js +0 -28
  471. package/dist/src/ui/commands/resumeCommand.test.js.map +0 -1
  472. package/dist/src/ui/commands/rewindCommand.test.d.ts +0 -6
  473. package/dist/src/ui/commands/rewindCommand.test.js +0 -256
  474. package/dist/src/ui/commands/rewindCommand.test.js.map +0 -1
  475. package/dist/src/ui/commands/settingsCommand.test.d.ts +0 -6
  476. package/dist/src/ui/commands/settingsCommand.test.js +0 -30
  477. package/dist/src/ui/commands/settingsCommand.test.js.map +0 -1
  478. package/dist/src/ui/commands/setupGithubCommand.test.d.ts +0 -6
  479. package/dist/src/ui/commands/setupGithubCommand.test.js +0 -238
  480. package/dist/src/ui/commands/setupGithubCommand.test.js.map +0 -1
  481. package/dist/src/ui/commands/skillsCommand.test.d.ts +0 -6
  482. package/dist/src/ui/commands/skillsCommand.test.js +0 -500
  483. package/dist/src/ui/commands/skillsCommand.test.js.map +0 -1
  484. package/dist/src/ui/commands/statsCommand.test.d.ts +0 -6
  485. package/dist/src/ui/commands/statsCommand.test.js +0 -122
  486. package/dist/src/ui/commands/statsCommand.test.js.map +0 -1
  487. package/dist/src/ui/commands/tasksCommand.test.d.ts +0 -6
  488. package/dist/src/ui/commands/tasksCommand.test.js +0 -30
  489. package/dist/src/ui/commands/tasksCommand.test.js.map +0 -1
  490. package/dist/src/ui/commands/terminalSetupCommand.test.d.ts +0 -6
  491. package/dist/src/ui/commands/terminalSetupCommand.test.js +0 -66
  492. package/dist/src/ui/commands/terminalSetupCommand.test.js.map +0 -1
  493. package/dist/src/ui/commands/themeCommand.test.d.ts +0 -6
  494. package/dist/src/ui/commands/themeCommand.test.js +0 -32
  495. package/dist/src/ui/commands/themeCommand.test.js.map +0 -1
  496. package/dist/src/ui/commands/toolsCommand.test.d.ts +0 -6
  497. package/dist/src/ui/commands/toolsCommand.test.js +0 -187
  498. package/dist/src/ui/commands/toolsCommand.test.js.map +0 -1
  499. package/dist/src/ui/commands/upgradeCommand.test.d.ts +0 -6
  500. package/dist/src/ui/commands/upgradeCommand.test.js +0 -102
  501. package/dist/src/ui/commands/upgradeCommand.test.js.map +0 -1
  502. package/dist/src/ui/components/AboutBox.test.d.ts +0 -6
  503. package/dist/src/ui/components/AboutBox.test.js +0 -63
  504. package/dist/src/ui/components/AboutBox.test.js.map +0 -1
  505. package/dist/src/ui/components/AdminSettingsChangedDialog.test.d.ts +0 -6
  506. package/dist/src/ui/components/AdminSettingsChangedDialog.test.js +0 -43
  507. package/dist/src/ui/components/AdminSettingsChangedDialog.test.js.map +0 -1
  508. package/dist/src/ui/components/AgentConfigDialog.test.d.ts +0 -6
  509. package/dist/src/ui/components/AgentConfigDialog.test.js +0 -267
  510. package/dist/src/ui/components/AgentConfigDialog.test.js.map +0 -1
  511. package/dist/src/ui/components/AlternateBufferQuittingDisplay.test.d.ts +0 -6
  512. package/dist/src/ui/components/AlternateBufferQuittingDisplay.test.js +0 -196
  513. package/dist/src/ui/components/AlternateBufferQuittingDisplay.test.js.map +0 -1
  514. package/dist/src/ui/components/AnsiOutput.test.d.ts +0 -6
  515. package/dist/src/ui/components/AnsiOutput.test.js +0 -142
  516. package/dist/src/ui/components/AnsiOutput.test.js.map +0 -1
  517. package/dist/src/ui/components/AppHeader.test.d.ts +0 -6
  518. package/dist/src/ui/components/AppHeader.test.js +0 -212
  519. package/dist/src/ui/components/AppHeader.test.js.map +0 -1
  520. package/dist/src/ui/components/AppHeaderIcon.test.d.ts +0 -6
  521. package/dist/src/ui/components/AppHeaderIcon.test.js +0 -39
  522. package/dist/src/ui/components/AppHeaderIcon.test.js.map +0 -1
  523. package/dist/src/ui/components/ApprovalModeIndicator.test.d.ts +0 -6
  524. package/dist/src/ui/components/ApprovalModeIndicator.test.js +0 -37
  525. package/dist/src/ui/components/ApprovalModeIndicator.test.js.map +0 -1
  526. package/dist/src/ui/components/AskUserDialog.test.d.ts +0 -6
  527. package/dist/src/ui/components/AskUserDialog.test.js +0 -1121
  528. package/dist/src/ui/components/AskUserDialog.test.js.map +0 -1
  529. package/dist/src/ui/components/BackgroundTaskDisplay.test.d.ts +0 -6
  530. package/dist/src/ui/components/BackgroundTaskDisplay.test.js +0 -209
  531. package/dist/src/ui/components/BackgroundTaskDisplay.test.js.map +0 -1
  532. package/dist/src/ui/components/Banner.test.d.ts +0 -6
  533. package/dist/src/ui/components/Banner.test.js +0 -29
  534. package/dist/src/ui/components/Banner.test.js.map +0 -1
  535. package/dist/src/ui/components/BubblingRegression.test.d.ts +0 -6
  536. package/dist/src/ui/components/BubblingRegression.test.js +0 -60
  537. package/dist/src/ui/components/BubblingRegression.test.js.map +0 -1
  538. package/dist/src/ui/components/Checklist.test.d.ts +0 -6
  539. package/dist/src/ui/components/Checklist.test.js +0 -46
  540. package/dist/src/ui/components/Checklist.test.js.map +0 -1
  541. package/dist/src/ui/components/ChecklistItem.test.d.ts +0 -6
  542. package/dist/src/ui/components/ChecklistItem.test.js +0 -40
  543. package/dist/src/ui/components/ChecklistItem.test.js.map +0 -1
  544. package/dist/src/ui/components/CliSpinner.test.d.ts +0 -6
  545. package/dist/src/ui/components/CliSpinner.test.js +0 -32
  546. package/dist/src/ui/components/CliSpinner.test.js.map +0 -1
  547. package/dist/src/ui/components/ColorsDisplay.test.d.ts +0 -6
  548. package/dist/src/ui/components/ColorsDisplay.test.js +0 -107
  549. package/dist/src/ui/components/ColorsDisplay.test.js.map +0 -1
  550. package/dist/src/ui/components/Composer.test.d.ts +0 -6
  551. package/dist/src/ui/components/Composer.test.js +0 -853
  552. package/dist/src/ui/components/Composer.test.js.map +0 -1
  553. package/dist/src/ui/components/ConfigInitDisplay.test.d.ts +0 -6
  554. package/dist/src/ui/components/ConfigInitDisplay.test.js +0 -118
  555. package/dist/src/ui/components/ConfigInitDisplay.test.js.map +0 -1
  556. package/dist/src/ui/components/ConsentPrompt.test.d.ts +0 -6
  557. package/dist/src/ui/components/ConsentPrompt.test.js +0 -80
  558. package/dist/src/ui/components/ConsentPrompt.test.js.map +0 -1
  559. package/dist/src/ui/components/ConsoleSummaryDisplay.test.d.ts +0 -6
  560. package/dist/src/ui/components/ConsoleSummaryDisplay.test.js +0 -28
  561. package/dist/src/ui/components/ConsoleSummaryDisplay.test.js.map +0 -1
  562. package/dist/src/ui/components/ContextSummaryDisplay.test.d.ts +0 -6
  563. package/dist/src/ui/components/ContextSummaryDisplay.test.js +0 -81
  564. package/dist/src/ui/components/ContextSummaryDisplay.test.js.map +0 -1
  565. package/dist/src/ui/components/ContextUsageDisplay.test.d.ts +0 -6
  566. package/dist/src/ui/components/ContextUsageDisplay.test.js +0 -50
  567. package/dist/src/ui/components/ContextUsageDisplay.test.js.map +0 -1
  568. package/dist/src/ui/components/CopyModeWarning.test.d.ts +0 -6
  569. package/dist/src/ui/components/CopyModeWarning.test.js +0 -35
  570. package/dist/src/ui/components/CopyModeWarning.test.js.map +0 -1
  571. package/dist/src/ui/components/DebugProfiler.test.d.ts +0 -6
  572. package/dist/src/ui/components/DebugProfiler.test.js +0 -228
  573. package/dist/src/ui/components/DebugProfiler.test.js.map +0 -1
  574. package/dist/src/ui/components/DetailedMessagesDisplay.test.d.ts +0 -6
  575. package/dist/src/ui/components/DetailedMessagesDisplay.test.js +0 -81
  576. package/dist/src/ui/components/DetailedMessagesDisplay.test.js.map +0 -1
  577. package/dist/src/ui/components/DialogManager.test.d.ts +0 -6
  578. package/dist/src/ui/components/DialogManager.test.js +0 -187
  579. package/dist/src/ui/components/DialogManager.test.js.map +0 -1
  580. package/dist/src/ui/components/EditorSettingsDialog.test.d.ts +0 -6
  581. package/dist/src/ui/components/EditorSettingsDialog.test.js +0 -145
  582. package/dist/src/ui/components/EditorSettingsDialog.test.js.map +0 -1
  583. package/dist/src/ui/components/EmptyWalletDialog.test.d.ts +0 -6
  584. package/dist/src/ui/components/EmptyWalletDialog.test.js +0 -116
  585. package/dist/src/ui/components/EmptyWalletDialog.test.js.map +0 -1
  586. package/dist/src/ui/components/ExitPlanModeDialog.test.d.ts +0 -6
  587. package/dist/src/ui/components/ExitPlanModeDialog.test.js +0 -443
  588. package/dist/src/ui/components/ExitPlanModeDialog.test.js.map +0 -1
  589. package/dist/src/ui/components/ExitWarning.test.d.ts +0 -6
  590. package/dist/src/ui/components/ExitWarning.test.js +0 -58
  591. package/dist/src/ui/components/ExitWarning.test.js.map +0 -1
  592. package/dist/src/ui/components/FolderTrustDialog.test.d.ts +0 -6
  593. package/dist/src/ui/components/FolderTrustDialog.test.js +0 -342
  594. package/dist/src/ui/components/FolderTrustDialog.test.js.map +0 -1
  595. package/dist/src/ui/components/Footer.test.d.ts +0 -6
  596. package/dist/src/ui/components/Footer.test.js +0 -806
  597. package/dist/src/ui/components/Footer.test.js.map +0 -1
  598. package/dist/src/ui/components/FooterConfigDialog.test.d.ts +0 -6
  599. package/dist/src/ui/components/FooterConfigDialog.test.js +0 -191
  600. package/dist/src/ui/components/FooterConfigDialog.test.js.map +0 -1
  601. package/dist/src/ui/components/GeminiRespondingSpinner.test.d.ts +0 -6
  602. package/dist/src/ui/components/GeminiRespondingSpinner.test.js +0 -63
  603. package/dist/src/ui/components/GeminiRespondingSpinner.test.js.map +0 -1
  604. package/dist/src/ui/components/GradientRegression.test.d.ts +0 -6
  605. package/dist/src/ui/components/GradientRegression.test.js +0 -116
  606. package/dist/src/ui/components/GradientRegression.test.js.map +0 -1
  607. package/dist/src/ui/components/Header.test.d.ts +0 -6
  608. package/dist/src/ui/components/Header.test.js +0 -131
  609. package/dist/src/ui/components/Header.test.js.map +0 -1
  610. package/dist/src/ui/components/Help.test.d.ts +0 -6
  611. package/dist/src/ui/components/Help.test.js +0 -67
  612. package/dist/src/ui/components/Help.test.js.map +0 -1
  613. package/dist/src/ui/components/HistoryItemDisplay.test.d.ts +0 -6
  614. package/dist/src/ui/components/HistoryItemDisplay.test.js +0 -302
  615. package/dist/src/ui/components/HistoryItemDisplay.test.js.map +0 -1
  616. package/dist/src/ui/components/HookStatusDisplay.test.d.ts +0 -6
  617. package/dist/src/ui/components/HookStatusDisplay.test.js +0 -77
  618. package/dist/src/ui/components/HookStatusDisplay.test.js.map +0 -1
  619. package/dist/src/ui/components/HooksDialog.test.d.ts +0 -6
  620. package/dist/src/ui/components/HooksDialog.test.js +0 -175
  621. package/dist/src/ui/components/HooksDialog.test.js.map +0 -1
  622. package/dist/src/ui/components/IdeTrustChangeDialog.test.d.ts +0 -6
  623. package/dist/src/ui/components/IdeTrustChangeDialog.test.js +0 -78
  624. package/dist/src/ui/components/IdeTrustChangeDialog.test.js.map +0 -1
  625. package/dist/src/ui/components/InboxDialog.test.d.ts +0 -6
  626. package/dist/src/ui/components/InboxDialog.test.js +0 -804
  627. package/dist/src/ui/components/InboxDialog.test.js.map +0 -1
  628. package/dist/src/ui/components/InputPrompt.test.d.ts +0 -17
  629. package/dist/src/ui/components/InputPrompt.test.js +0 -4078
  630. package/dist/src/ui/components/InputPrompt.test.js.map +0 -1
  631. package/dist/src/ui/components/LoadingIndicator.test.d.ts +0 -6
  632. package/dist/src/ui/components/LoadingIndicator.test.js +0 -325
  633. package/dist/src/ui/components/LoadingIndicator.test.js.map +0 -1
  634. package/dist/src/ui/components/LogoutConfirmationDialog.test.d.ts +0 -6
  635. package/dist/src/ui/components/LogoutConfirmationDialog.test.js +0 -74
  636. package/dist/src/ui/components/LogoutConfirmationDialog.test.js.map +0 -1
  637. package/dist/src/ui/components/LoopDetectionConfirmation.test.d.ts +0 -6
  638. package/dist/src/ui/components/LoopDetectionConfirmation.test.js +0 -27
  639. package/dist/src/ui/components/LoopDetectionConfirmation.test.js.map +0 -1
  640. package/dist/src/ui/components/MainContent.test.d.ts +0 -6
  641. package/dist/src/ui/components/MainContent.test.js +0 -750
  642. package/dist/src/ui/components/MainContent.test.js.map +0 -1
  643. package/dist/src/ui/components/MemoryUsageDisplay.test.d.ts +0 -6
  644. package/dist/src/ui/components/MemoryUsageDisplay.test.js +0 -52
  645. package/dist/src/ui/components/MemoryUsageDisplay.test.js.map +0 -1
  646. package/dist/src/ui/components/ModelDialog.test.d.ts +0 -6
  647. package/dist/src/ui/components/ModelDialog.test.js +0 -356
  648. package/dist/src/ui/components/ModelDialog.test.js.map +0 -1
  649. package/dist/src/ui/components/ModelQuotaDisplay.test.d.ts +0 -6
  650. package/dist/src/ui/components/ModelQuotaDisplay.test.js +0 -62
  651. package/dist/src/ui/components/ModelQuotaDisplay.test.js.map +0 -1
  652. package/dist/src/ui/components/ModelStatsDisplay.test.d.ts +0 -6
  653. package/dist/src/ui/components/ModelStatsDisplay.test.js +0 -651
  654. package/dist/src/ui/components/ModelStatsDisplay.test.js.map +0 -1
  655. package/dist/src/ui/components/MultiFolderTrustDialog.test.d.ts +0 -6
  656. package/dist/src/ui/components/MultiFolderTrustDialog.test.js +0 -177
  657. package/dist/src/ui/components/MultiFolderTrustDialog.test.js.map +0 -1
  658. package/dist/src/ui/components/NewAgentsNotification.test.d.ts +0 -6
  659. package/dist/src/ui/components/NewAgentsNotification.test.js +0 -83
  660. package/dist/src/ui/components/NewAgentsNotification.test.js.map +0 -1
  661. package/dist/src/ui/components/Notifications.test.d.ts +0 -6
  662. package/dist/src/ui/components/Notifications.test.js +0 -285
  663. package/dist/src/ui/components/Notifications.test.js.map +0 -1
  664. package/dist/src/ui/components/OverageMenuDialog.test.d.ts +0 -6
  665. package/dist/src/ui/components/OverageMenuDialog.test.js +0 -118
  666. package/dist/src/ui/components/OverageMenuDialog.test.js.map +0 -1
  667. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.d.ts +0 -6
  668. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +0 -181
  669. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +0 -1
  670. package/dist/src/ui/components/PolicyUpdateDialog.test.d.ts +0 -6
  671. package/dist/src/ui/components/PolicyUpdateDialog.test.js +0 -92
  672. package/dist/src/ui/components/PolicyUpdateDialog.test.js.map +0 -1
  673. package/dist/src/ui/components/ProQuotaDialog.test.d.ts +0 -6
  674. package/dist/src/ui/components/ProQuotaDialog.test.js +0 -222
  675. package/dist/src/ui/components/ProQuotaDialog.test.js.map +0 -1
  676. package/dist/src/ui/components/ProgressBar.test.d.ts +0 -6
  677. package/dist/src/ui/components/ProgressBar.test.js +0 -28
  678. package/dist/src/ui/components/ProgressBar.test.js.map +0 -1
  679. package/dist/src/ui/components/QueuedMessageDisplay.test.d.ts +0 -6
  680. package/dist/src/ui/components/QueuedMessageDisplay.test.js +0 -65
  681. package/dist/src/ui/components/QueuedMessageDisplay.test.js.map +0 -1
  682. package/dist/src/ui/components/QuittingDisplay.test.d.ts +0 -6
  683. package/dist/src/ui/components/QuittingDisplay.test.js +0 -60
  684. package/dist/src/ui/components/QuittingDisplay.test.js.map +0 -1
  685. package/dist/src/ui/components/QuotaDisplay.test.d.ts +0 -6
  686. package/dist/src/ui/components/QuotaDisplay.test.js +0 -68
  687. package/dist/src/ui/components/QuotaDisplay.test.js.map +0 -1
  688. package/dist/src/ui/components/RawMarkdownIndicator.test.d.ts +0 -6
  689. package/dist/src/ui/components/RawMarkdownIndicator.test.js +0 -38
  690. package/dist/src/ui/components/RawMarkdownIndicator.test.js.map +0 -1
  691. package/dist/src/ui/components/RewindConfirmation.test.d.ts +0 -6
  692. package/dist/src/ui/components/RewindConfirmation.test.js +0 -57
  693. package/dist/src/ui/components/RewindConfirmation.test.js.map +0 -1
  694. package/dist/src/ui/components/RewindViewer.test.d.ts +0 -6
  695. package/dist/src/ui/components/RewindViewer.test.js +0 -334
  696. package/dist/src/ui/components/RewindViewer.test.js.map +0 -1
  697. package/dist/src/ui/components/SessionBrowser/SessionBrowserSearchNav.test.d.ts +0 -6
  698. package/dist/src/ui/components/SessionBrowser/SessionBrowserSearchNav.test.js +0 -47
  699. package/dist/src/ui/components/SessionBrowser/SessionBrowserSearchNav.test.js.map +0 -1
  700. package/dist/src/ui/components/SessionBrowser/SessionBrowserStates.test.d.ts +0 -6
  701. package/dist/src/ui/components/SessionBrowser/SessionBrowserStates.test.js +0 -27
  702. package/dist/src/ui/components/SessionBrowser/SessionBrowserStates.test.js.map +0 -1
  703. package/dist/src/ui/components/SessionBrowser/utils.test.d.ts +0 -6
  704. package/dist/src/ui/components/SessionBrowser/utils.test.js +0 -108
  705. package/dist/src/ui/components/SessionBrowser/utils.test.js.map +0 -1
  706. package/dist/src/ui/components/SessionBrowser.test.d.ts +0 -6
  707. package/dist/src/ui/components/SessionBrowser.test.js +0 -266
  708. package/dist/src/ui/components/SessionBrowser.test.js.map +0 -1
  709. package/dist/src/ui/components/SessionSummaryDisplay.test.d.ts +0 -6
  710. package/dist/src/ui/components/SessionSummaryDisplay.test.js +0 -164
  711. package/dist/src/ui/components/SessionSummaryDisplay.test.js.map +0 -1
  712. package/dist/src/ui/components/SettingsDialog.test.d.ts +0 -6
  713. package/dist/src/ui/components/SettingsDialog.test.js +0 -1499
  714. package/dist/src/ui/components/SettingsDialog.test.js.map +0 -1
  715. package/dist/src/ui/components/ShellInputPrompt.test.d.ts +0 -6
  716. package/dist/src/ui/components/ShellInputPrompt.test.js +0 -201
  717. package/dist/src/ui/components/ShellInputPrompt.test.js.map +0 -1
  718. package/dist/src/ui/components/ShellModeIndicator.test.d.ts +0 -6
  719. package/dist/src/ui/components/ShellModeIndicator.test.js +0 -18
  720. package/dist/src/ui/components/ShellModeIndicator.test.js.map +0 -1
  721. package/dist/src/ui/components/ShortcutsHelp.test.d.ts +0 -6
  722. package/dist/src/ui/components/ShortcutsHelp.test.js +0 -45
  723. package/dist/src/ui/components/ShortcutsHelp.test.js.map +0 -1
  724. package/dist/src/ui/components/ShowMoreLines.test.d.ts +0 -6
  725. package/dist/src/ui/components/ShowMoreLines.test.js +0 -79
  726. package/dist/src/ui/components/ShowMoreLines.test.js.map +0 -1
  727. package/dist/src/ui/components/ShowMoreLinesLayout.test.d.ts +0 -1
  728. package/dist/src/ui/components/ShowMoreLinesLayout.test.js +0 -68
  729. package/dist/src/ui/components/ShowMoreLinesLayout.test.js.map +0 -1
  730. package/dist/src/ui/components/StatsDisplay.test.d.ts +0 -6
  731. package/dist/src/ui/components/StatsDisplay.test.js +0 -489
  732. package/dist/src/ui/components/StatsDisplay.test.js.map +0 -1
  733. package/dist/src/ui/components/StatusDisplay.test.d.ts +0 -6
  734. package/dist/src/ui/components/StatusDisplay.test.js +0 -117
  735. package/dist/src/ui/components/StatusDisplay.test.js.map +0 -1
  736. package/dist/src/ui/components/StatusRow.test.d.ts +0 -6
  737. package/dist/src/ui/components/StatusRow.test.js +0 -99
  738. package/dist/src/ui/components/StatusRow.test.js.map +0 -1
  739. package/dist/src/ui/components/StickyHeader.test.d.ts +0 -6
  740. package/dist/src/ui/components/StickyHeader.test.js +0 -19
  741. package/dist/src/ui/components/StickyHeader.test.js.map +0 -1
  742. package/dist/src/ui/components/SuggestionsDisplay.test.d.ts +0 -6
  743. package/dist/src/ui/components/SuggestionsDisplay.test.js +0 -82
  744. package/dist/src/ui/components/SuggestionsDisplay.test.js.map +0 -1
  745. package/dist/src/ui/components/Table.test.d.ts +0 -6
  746. package/dist/src/ui/components/Table.test.js +0 -72
  747. package/dist/src/ui/components/Table.test.js.map +0 -1
  748. package/dist/src/ui/components/ThemeDialog.test.d.ts +0 -6
  749. package/dist/src/ui/components/ThemeDialog.test.js +0 -162
  750. package/dist/src/ui/components/ThemeDialog.test.js.map +0 -1
  751. package/dist/src/ui/components/ThemedGradient.test.d.ts +0 -6
  752. package/dist/src/ui/components/ThemedGradient.test.js +0 -35
  753. package/dist/src/ui/components/ThemedGradient.test.js.map +0 -1
  754. package/dist/src/ui/components/Tips.test.d.ts +0 -6
  755. package/dist/src/ui/components/Tips.test.js +0 -23
  756. package/dist/src/ui/components/Tips.test.js.map +0 -1
  757. package/dist/src/ui/components/ToastDisplay.test.d.ts +0 -6
  758. package/dist/src/ui/components/ToastDisplay.test.js +0 -167
  759. package/dist/src/ui/components/ToastDisplay.test.js.map +0 -1
  760. package/dist/src/ui/components/ToolConfirmationQueue.test.d.ts +0 -6
  761. package/dist/src/ui/components/ToolConfirmationQueue.test.js +0 -444
  762. package/dist/src/ui/components/ToolConfirmationQueue.test.js.map +0 -1
  763. package/dist/src/ui/components/ToolStatsDisplay.test.d.ts +0 -6
  764. package/dist/src/ui/components/ToolStatsDisplay.test.js +0 -234
  765. package/dist/src/ui/components/ToolStatsDisplay.test.js.map +0 -1
  766. package/dist/src/ui/components/UpdateNotification.test.d.ts +0 -6
  767. package/dist/src/ui/components/UpdateNotification.test.js +0 -17
  768. package/dist/src/ui/components/UpdateNotification.test.js.map +0 -1
  769. package/dist/src/ui/components/UserIdentity.test.d.ts +0 -6
  770. package/dist/src/ui/components/UserIdentity.test.js +0 -138
  771. package/dist/src/ui/components/UserIdentity.test.js.map +0 -1
  772. package/dist/src/ui/components/ValidationDialog.test.d.ts +0 -6
  773. package/dist/src/ui/components/ValidationDialog.test.js +0 -162
  774. package/dist/src/ui/components/ValidationDialog.test.js.map +0 -1
  775. package/dist/src/ui/components/VoiceModelDialog.test.d.ts +0 -6
  776. package/dist/src/ui/components/VoiceModelDialog.test.js +0 -68
  777. package/dist/src/ui/components/VoiceModelDialog.test.js.map +0 -1
  778. package/dist/src/ui/components/messages/CompressionMessage.test.d.ts +0 -6
  779. package/dist/src/ui/components/messages/CompressionMessage.test.js +0 -180
  780. package/dist/src/ui/components/messages/CompressionMessage.test.js.map +0 -1
  781. package/dist/src/ui/components/messages/DenseToolMessage.test.d.ts +0 -6
  782. package/dist/src/ui/components/messages/DenseToolMessage.test.js +0 -406
  783. package/dist/src/ui/components/messages/DenseToolMessage.test.js.map +0 -1
  784. package/dist/src/ui/components/messages/DiffRenderer.test.d.ts +0 -6
  785. package/dist/src/ui/components/messages/DiffRenderer.test.js +0 -269
  786. package/dist/src/ui/components/messages/DiffRenderer.test.js.map +0 -1
  787. package/dist/src/ui/components/messages/ErrorMessage.test.d.ts +0 -6
  788. package/dist/src/ui/components/messages/ErrorMessage.test.js +0 -25
  789. package/dist/src/ui/components/messages/ErrorMessage.test.js.map +0 -1
  790. package/dist/src/ui/components/messages/ExportSessionMessage.test.d.ts +0 -6
  791. package/dist/src/ui/components/messages/ExportSessionMessage.test.js +0 -32
  792. package/dist/src/ui/components/messages/ExportSessionMessage.test.js.map +0 -1
  793. package/dist/src/ui/components/messages/GeminiMessage.test.d.ts +0 -6
  794. package/dist/src/ui/components/messages/GeminiMessage.test.js +0 -46
  795. package/dist/src/ui/components/messages/GeminiMessage.test.js.map +0 -1
  796. package/dist/src/ui/components/messages/HintMessage.test.d.ts +0 -6
  797. package/dist/src/ui/components/messages/HintMessage.test.js +0 -42
  798. package/dist/src/ui/components/messages/HintMessage.test.js.map +0 -1
  799. package/dist/src/ui/components/messages/InfoMessage.test.d.ts +0 -6
  800. package/dist/src/ui/components/messages/InfoMessage.test.js +0 -31
  801. package/dist/src/ui/components/messages/InfoMessage.test.js.map +0 -1
  802. package/dist/src/ui/components/messages/RedirectionConfirmation.test.d.ts +0 -6
  803. package/dist/src/ui/components/messages/RedirectionConfirmation.test.js +0 -35
  804. package/dist/src/ui/components/messages/RedirectionConfirmation.test.js.map +0 -1
  805. package/dist/src/ui/components/messages/ShellToolMessage.test.d.ts +0 -6
  806. package/dist/src/ui/components/messages/ShellToolMessage.test.js +0 -290
  807. package/dist/src/ui/components/messages/ShellToolMessage.test.js.map +0 -1
  808. package/dist/src/ui/components/messages/SubagentGroupDisplay.test.d.ts +0 -1
  809. package/dist/src/ui/components/messages/SubagentGroupDisplay.test.js +0 -92
  810. package/dist/src/ui/components/messages/SubagentGroupDisplay.test.js.map +0 -1
  811. package/dist/src/ui/components/messages/SubagentHistoryMessage.test.d.ts +0 -6
  812. package/dist/src/ui/components/messages/SubagentHistoryMessage.test.js +0 -69
  813. package/dist/src/ui/components/messages/SubagentHistoryMessage.test.js.map +0 -1
  814. package/dist/src/ui/components/messages/SubagentProgressDisplay.test.d.ts +0 -6
  815. package/dist/src/ui/components/messages/SubagentProgressDisplay.test.js +0 -164
  816. package/dist/src/ui/components/messages/SubagentProgressDisplay.test.js.map +0 -1
  817. package/dist/src/ui/components/messages/ThinkingMessage.test.d.ts +0 -6
  818. package/dist/src/ui/components/messages/ThinkingMessage.test.js +0 -104
  819. package/dist/src/ui/components/messages/ThinkingMessage.test.js.map +0 -1
  820. package/dist/src/ui/components/messages/Todo.test.d.ts +0 -6
  821. package/dist/src/ui/components/messages/Todo.test.js +0 -129
  822. package/dist/src/ui/components/messages/Todo.test.js.map +0 -1
  823. package/dist/src/ui/components/messages/ToolConfirmationMessage.test.d.ts +0 -6
  824. package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js +0 -558
  825. package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js.map +0 -1
  826. package/dist/src/ui/components/messages/ToolGroupDisplay.test.d.ts +0 -6
  827. package/dist/src/ui/components/messages/ToolGroupDisplay.test.js +0 -210
  828. package/dist/src/ui/components/messages/ToolGroupDisplay.test.js.map +0 -1
  829. package/dist/src/ui/components/messages/ToolGroupMessage.compact.test.d.ts +0 -6
  830. package/dist/src/ui/components/messages/ToolGroupMessage.compact.test.js +0 -147
  831. package/dist/src/ui/components/messages/ToolGroupMessage.compact.test.js.map +0 -1
  832. package/dist/src/ui/components/messages/ToolGroupMessage.test.d.ts +0 -6
  833. package/dist/src/ui/components/messages/ToolGroupMessage.test.js +0 -828
  834. package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +0 -1
  835. package/dist/src/ui/components/messages/ToolGroupMessageRegression.test.d.ts +0 -6
  836. package/dist/src/ui/components/messages/ToolGroupMessageRegression.test.js +0 -101
  837. package/dist/src/ui/components/messages/ToolGroupMessageRegression.test.js.map +0 -1
  838. package/dist/src/ui/components/messages/ToolMessage.test.d.ts +0 -6
  839. package/dist/src/ui/components/messages/ToolMessage.test.js +0 -292
  840. package/dist/src/ui/components/messages/ToolMessage.test.js.map +0 -1
  841. package/dist/src/ui/components/messages/ToolMessageFocusHint.test.d.ts +0 -6
  842. package/dist/src/ui/components/messages/ToolMessageFocusHint.test.js +0 -96
  843. package/dist/src/ui/components/messages/ToolMessageFocusHint.test.js.map +0 -1
  844. package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.d.ts +0 -6
  845. package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.js +0 -72
  846. package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.js.map +0 -1
  847. package/dist/src/ui/components/messages/ToolOverflowConsistencyChecks.test.d.ts +0 -6
  848. package/dist/src/ui/components/messages/ToolOverflowConsistencyChecks.test.js +0 -88
  849. package/dist/src/ui/components/messages/ToolOverflowConsistencyChecks.test.js.map +0 -1
  850. package/dist/src/ui/components/messages/ToolResultDisplay.test.d.ts +0 -6
  851. package/dist/src/ui/components/messages/ToolResultDisplay.test.js +0 -333
  852. package/dist/src/ui/components/messages/ToolResultDisplay.test.js.map +0 -1
  853. package/dist/src/ui/components/messages/ToolResultDisplayOverflow.test.d.ts +0 -6
  854. package/dist/src/ui/components/messages/ToolResultDisplayOverflow.test.js +0 -77
  855. package/dist/src/ui/components/messages/ToolResultDisplayOverflow.test.js.map +0 -1
  856. package/dist/src/ui/components/messages/ToolShared.test.d.ts +0 -6
  857. package/dist/src/ui/components/messages/ToolShared.test.js +0 -65
  858. package/dist/src/ui/components/messages/ToolShared.test.js.map +0 -1
  859. package/dist/src/ui/components/messages/ToolStickyHeaderRegression.test.d.ts +0 -6
  860. package/dist/src/ui/components/messages/ToolStickyHeaderRegression.test.js +0 -142
  861. package/dist/src/ui/components/messages/ToolStickyHeaderRegression.test.js.map +0 -1
  862. package/dist/src/ui/components/messages/TopicMessage.test.d.ts +0 -6
  863. package/dist/src/ui/components/messages/TopicMessage.test.js +0 -77
  864. package/dist/src/ui/components/messages/TopicMessage.test.js.map +0 -1
  865. package/dist/src/ui/components/messages/UserMessage.test.d.ts +0 -6
  866. package/dist/src/ui/components/messages/UserMessage.test.js +0 -67
  867. package/dist/src/ui/components/messages/UserMessage.test.js.map +0 -1
  868. package/dist/src/ui/components/messages/UserShellMessage.test.d.ts +0 -6
  869. package/dist/src/ui/components/messages/UserShellMessage.test.js +0 -40
  870. package/dist/src/ui/components/messages/UserShellMessage.test.js.map +0 -1
  871. package/dist/src/ui/components/messages/WarningMessage.test.d.ts +0 -6
  872. package/dist/src/ui/components/messages/WarningMessage.test.js +0 -25
  873. package/dist/src/ui/components/messages/WarningMessage.test.js.map +0 -1
  874. package/dist/src/ui/components/shared/BaseSelectionList.test.d.ts +0 -6
  875. package/dist/src/ui/components/shared/BaseSelectionList.test.js +0 -441
  876. package/dist/src/ui/components/shared/BaseSelectionList.test.js.map +0 -1
  877. package/dist/src/ui/components/shared/BaseSettingsDialog.test.d.ts +0 -6
  878. package/dist/src/ui/components/shared/BaseSettingsDialog.test.js +0 -710
  879. package/dist/src/ui/components/shared/BaseSettingsDialog.test.js.map +0 -1
  880. package/dist/src/ui/components/shared/DescriptiveRadioButtonSelect.test.d.ts +0 -6
  881. package/dist/src/ui/components/shared/DescriptiveRadioButtonSelect.test.js +0 -89
  882. package/dist/src/ui/components/shared/DescriptiveRadioButtonSelect.test.js.map +0 -1
  883. package/dist/src/ui/components/shared/EnumSelector.test.d.ts +0 -6
  884. package/dist/src/ui/components/shared/EnumSelector.test.js +0 -83
  885. package/dist/src/ui/components/shared/EnumSelector.test.js.map +0 -1
  886. package/dist/src/ui/components/shared/ExpandableText.test.d.ts +0 -6
  887. package/dist/src/ui/components/shared/ExpandableText.test.js +0 -95
  888. package/dist/src/ui/components/shared/ExpandableText.test.js.map +0 -1
  889. package/dist/src/ui/components/shared/HalfLinePaddedBox.test.d.ts +0 -1
  890. package/dist/src/ui/components/shared/HalfLinePaddedBox.test.js +0 -47
  891. package/dist/src/ui/components/shared/HalfLinePaddedBox.test.js.map +0 -1
  892. package/dist/src/ui/components/shared/MaxSizedBox.test.d.ts +0 -6
  893. package/dist/src/ui/components/shared/MaxSizedBox.test.js +0 -161
  894. package/dist/src/ui/components/shared/MaxSizedBox.test.js.map +0 -1
  895. package/dist/src/ui/components/shared/RadioButtonSelect.test.d.ts +0 -6
  896. package/dist/src/ui/components/shared/RadioButtonSelect.test.js +0 -146
  897. package/dist/src/ui/components/shared/RadioButtonSelect.test.js.map +0 -1
  898. package/dist/src/ui/components/shared/Scrollable.test.d.ts +0 -6
  899. package/dist/src/ui/components/shared/Scrollable.test.js +0 -143
  900. package/dist/src/ui/components/shared/Scrollable.test.js.map +0 -1
  901. package/dist/src/ui/components/shared/ScrollableList.test.d.ts +0 -6
  902. package/dist/src/ui/components/shared/ScrollableList.test.js +0 -438
  903. package/dist/src/ui/components/shared/ScrollableList.test.js.map +0 -1
  904. package/dist/src/ui/components/shared/SearchableList.test.d.ts +0 -6
  905. package/dist/src/ui/components/shared/SearchableList.test.js +0 -169
  906. package/dist/src/ui/components/shared/SearchableList.test.js.map +0 -1
  907. package/dist/src/ui/components/shared/SectionHeader.test.d.ts +0 -6
  908. package/dist/src/ui/components/shared/SectionHeader.test.js +0 -42
  909. package/dist/src/ui/components/shared/SectionHeader.test.js.map +0 -1
  910. package/dist/src/ui/components/shared/SlicingMaxSizedBox.test.d.ts +0 -6
  911. package/dist/src/ui/components/shared/SlicingMaxSizedBox.test.js +0 -54
  912. package/dist/src/ui/components/shared/SlicingMaxSizedBox.test.js.map +0 -1
  913. package/dist/src/ui/components/shared/TabHeader.test.d.ts +0 -6
  914. package/dist/src/ui/components/shared/TabHeader.test.js +0 -144
  915. package/dist/src/ui/components/shared/TabHeader.test.js.map +0 -1
  916. package/dist/src/ui/components/shared/TextInput.test.d.ts +0 -6
  917. package/dist/src/ui/components/shared/TextInput.test.js +0 -353
  918. package/dist/src/ui/components/shared/TextInput.test.js.map +0 -1
  919. package/dist/src/ui/components/shared/VirtualizedList.test.d.ts +0 -6
  920. package/dist/src/ui/components/shared/VirtualizedList.test.js +0 -174
  921. package/dist/src/ui/components/shared/VirtualizedList.test.js.map +0 -1
  922. package/dist/src/ui/components/shared/performance.test.d.ts +0 -1
  923. package/dist/src/ui/components/shared/performance.test.js +0 -74
  924. package/dist/src/ui/components/shared/performance.test.js.map +0 -1
  925. package/dist/src/ui/components/shared/text-buffer.test.d.ts +0 -6
  926. package/dist/src/ui/components/shared/text-buffer.test.js +0 -2965
  927. package/dist/src/ui/components/shared/text-buffer.test.js.map +0 -1
  928. package/dist/src/ui/components/shared/vim-buffer-actions.test.d.ts +0 -6
  929. package/dist/src/ui/components/shared/vim-buffer-actions.test.js +0 -2272
  930. package/dist/src/ui/components/shared/vim-buffer-actions.test.js.map +0 -1
  931. package/dist/src/ui/components/views/ChatList.test.d.ts +0 -6
  932. package/dist/src/ui/components/views/ChatList.test.js +0 -45
  933. package/dist/src/ui/components/views/ChatList.test.js.map +0 -1
  934. package/dist/src/ui/components/views/ExtensionDetails.test.d.ts +0 -6
  935. package/dist/src/ui/components/views/ExtensionDetails.test.js +0 -154
  936. package/dist/src/ui/components/views/ExtensionDetails.test.js.map +0 -1
  937. package/dist/src/ui/components/views/ExtensionRegistryView.test.d.ts +0 -6
  938. package/dist/src/ui/components/views/ExtensionRegistryView.test.js +0 -222
  939. package/dist/src/ui/components/views/ExtensionRegistryView.test.js.map +0 -1
  940. package/dist/src/ui/components/views/ExtensionsList.test.d.ts +0 -6
  941. package/dist/src/ui/components/views/ExtensionsList.test.js +0 -145
  942. package/dist/src/ui/components/views/ExtensionsList.test.js.map +0 -1
  943. package/dist/src/ui/components/views/McpStatus.test.d.ts +0 -6
  944. package/dist/src/ui/components/views/McpStatus.test.js +0 -174
  945. package/dist/src/ui/components/views/McpStatus.test.js.map +0 -1
  946. package/dist/src/ui/components/views/SkillsList.test.d.ts +0 -6
  947. package/dist/src/ui/components/views/SkillsList.test.js +0 -99
  948. package/dist/src/ui/components/views/SkillsList.test.js.map +0 -1
  949. package/dist/src/ui/components/views/ToolsList.test.d.ts +0 -6
  950. package/dist/src/ui/components/views/ToolsList.test.js +0 -45
  951. package/dist/src/ui/components/views/ToolsList.test.js.map +0 -1
  952. package/dist/src/ui/contexts/KeypressContext.test.d.ts +0 -6
  953. package/dist/src/ui/contexts/KeypressContext.test.js +0 -1133
  954. package/dist/src/ui/contexts/KeypressContext.test.js.map +0 -1
  955. package/dist/src/ui/contexts/MouseContext.test.d.ts +0 -6
  956. package/dist/src/ui/contexts/MouseContext.test.js +0 -269
  957. package/dist/src/ui/contexts/MouseContext.test.js.map +0 -1
  958. package/dist/src/ui/contexts/ScrollProvider.drag.test.d.ts +0 -6
  959. package/dist/src/ui/contexts/ScrollProvider.drag.test.js +0 -320
  960. package/dist/src/ui/contexts/ScrollProvider.drag.test.js.map +0 -1
  961. package/dist/src/ui/contexts/ScrollProvider.test.d.ts +0 -6
  962. package/dist/src/ui/contexts/ScrollProvider.test.js +0 -478
  963. package/dist/src/ui/contexts/ScrollProvider.test.js.map +0 -1
  964. package/dist/src/ui/contexts/SessionContext.test.d.ts +0 -6
  965. package/dist/src/ui/contexts/SessionContext.test.js +0 -213
  966. package/dist/src/ui/contexts/SessionContext.test.js.map +0 -1
  967. package/dist/src/ui/contexts/SettingsContext.test.d.ts +0 -6
  968. package/dist/src/ui/contexts/SettingsContext.test.js +0 -106
  969. package/dist/src/ui/contexts/SettingsContext.test.js.map +0 -1
  970. package/dist/src/ui/contexts/TerminalContext.test.d.ts +0 -6
  971. package/dist/src/ui/contexts/TerminalContext.test.js +0 -75
  972. package/dist/src/ui/contexts/TerminalContext.test.js.map +0 -1
  973. package/dist/src/ui/contexts/ToolActionsContext.test.d.ts +0 -6
  974. package/dist/src/ui/contexts/ToolActionsContext.test.js +0 -247
  975. package/dist/src/ui/contexts/ToolActionsContext.test.js.map +0 -1
  976. package/dist/src/ui/hooks/atCommandProcessor.test.d.ts +0 -6
  977. package/dist/src/ui/hooks/atCommandProcessor.test.js +0 -1265
  978. package/dist/src/ui/hooks/atCommandProcessor.test.js.map +0 -1
  979. package/dist/src/ui/hooks/atCommandProcessor_agents.test.d.ts +0 -6
  980. package/dist/src/ui/hooks/atCommandProcessor_agents.test.js +0 -210
  981. package/dist/src/ui/hooks/atCommandProcessor_agents.test.js.map +0 -1
  982. package/dist/src/ui/hooks/creditsFlowHandler.test.d.ts +0 -6
  983. package/dist/src/ui/hooks/creditsFlowHandler.test.js +0 -211
  984. package/dist/src/ui/hooks/creditsFlowHandler.test.js.map +0 -1
  985. package/dist/src/ui/hooks/shell-completions/gitProvider.test.d.ts +0 -6
  986. package/dist/src/ui/hooks/shell-completions/gitProvider.test.js +0 -73
  987. package/dist/src/ui/hooks/shell-completions/gitProvider.test.js.map +0 -1
  988. package/dist/src/ui/hooks/shell-completions/npmProvider.test.d.ts +0 -6
  989. package/dist/src/ui/hooks/shell-completions/npmProvider.test.js +0 -69
  990. package/dist/src/ui/hooks/shell-completions/npmProvider.test.js.map +0 -1
  991. package/dist/src/ui/hooks/shellReducer.test.d.ts +0 -6
  992. package/dist/src/ui/hooks/shellReducer.test.js +0 -341
  993. package/dist/src/ui/hooks/shellReducer.test.js.map +0 -1
  994. package/dist/src/ui/hooks/slashCommandProcessor.test.d.ts +0 -6
  995. package/dist/src/ui/hooks/slashCommandProcessor.test.js +0 -881
  996. package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +0 -1
  997. package/dist/src/ui/hooks/toolMapping.test.d.ts +0 -6
  998. package/dist/src/ui/hooks/toolMapping.test.js +0 -292
  999. package/dist/src/ui/hooks/toolMapping.test.js.map +0 -1
  1000. package/dist/src/ui/hooks/useAgentStream.test.d.ts +0 -6
  1001. package/dist/src/ui/hooks/useAgentStream.test.js +0 -161
  1002. package/dist/src/ui/hooks/useAgentStream.test.js.map +0 -1
  1003. package/dist/src/ui/hooks/useAlternateBuffer.test.d.ts +0 -6
  1004. package/dist/src/ui/hooks/useAlternateBuffer.test.js +0 -62
  1005. package/dist/src/ui/hooks/useAlternateBuffer.test.js.map +0 -1
  1006. package/dist/src/ui/hooks/useAnimatedScrollbar.test.d.ts +0 -6
  1007. package/dist/src/ui/hooks/useAnimatedScrollbar.test.js +0 -85
  1008. package/dist/src/ui/hooks/useAnimatedScrollbar.test.js.map +0 -1
  1009. package/dist/src/ui/hooks/useApprovalModeIndicator.test.d.ts +0 -6
  1010. package/dist/src/ui/hooks/useApprovalModeIndicator.test.js +0 -477
  1011. package/dist/src/ui/hooks/useApprovalModeIndicator.test.js.map +0 -1
  1012. package/dist/src/ui/hooks/useAtCompletion.test.d.ts +0 -6
  1013. package/dist/src/ui/hooks/useAtCompletion.test.js +0 -567
  1014. package/dist/src/ui/hooks/useAtCompletion.test.js.map +0 -1
  1015. package/dist/src/ui/hooks/useAtCompletion_agents.test.d.ts +0 -6
  1016. package/dist/src/ui/hooks/useAtCompletion_agents.test.js +0 -87
  1017. package/dist/src/ui/hooks/useAtCompletion_agents.test.js.map +0 -1
  1018. package/dist/src/ui/hooks/useBackgroundTaskManager.test.d.ts +0 -6
  1019. package/dist/src/ui/hooks/useBackgroundTaskManager.test.js +0 -168
  1020. package/dist/src/ui/hooks/useBackgroundTaskManager.test.js.map +0 -1
  1021. package/dist/src/ui/hooks/useBanner.test.d.ts +0 -6
  1022. package/dist/src/ui/hooks/useBanner.test.js +0 -144
  1023. package/dist/src/ui/hooks/useBanner.test.js.map +0 -1
  1024. package/dist/src/ui/hooks/useBatchedScroll.test.d.ts +0 -6
  1025. package/dist/src/ui/hooks/useBatchedScroll.test.js +0 -62
  1026. package/dist/src/ui/hooks/useBatchedScroll.test.js.map +0 -1
  1027. package/dist/src/ui/hooks/useCommandCompletion.test.d.ts +0 -6
  1028. package/dist/src/ui/hooks/useCommandCompletion.test.js +0 -722
  1029. package/dist/src/ui/hooks/useCommandCompletion.test.js.map +0 -1
  1030. package/dist/src/ui/hooks/useConsoleMessages.test.d.ts +0 -6
  1031. package/dist/src/ui/hooks/useConsoleMessages.test.js +0 -201
  1032. package/dist/src/ui/hooks/useConsoleMessages.test.js.map +0 -1
  1033. package/dist/src/ui/hooks/useEditorSettings.test.d.ts +0 -6
  1034. package/dist/src/ui/hooks/useEditorSettings.test.js +0 -179
  1035. package/dist/src/ui/hooks/useEditorSettings.test.js.map +0 -1
  1036. package/dist/src/ui/hooks/useExecutionLifecycle.test.d.ts +0 -6
  1037. package/dist/src/ui/hooks/useExecutionLifecycle.test.js +0 -903
  1038. package/dist/src/ui/hooks/useExecutionLifecycle.test.js.map +0 -1
  1039. package/dist/src/ui/hooks/useExtensionUpdates.test.d.ts +0 -6
  1040. package/dist/src/ui/hooks/useExtensionUpdates.test.js +0 -280
  1041. package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +0 -1
  1042. package/dist/src/ui/hooks/useFlickerDetector.test.d.ts +0 -6
  1043. package/dist/src/ui/hooks/useFlickerDetector.test.js +0 -106
  1044. package/dist/src/ui/hooks/useFlickerDetector.test.js.map +0 -1
  1045. package/dist/src/ui/hooks/useFocus.test.d.ts +0 -6
  1046. package/dist/src/ui/hooks/useFocus.test.js +0 -140
  1047. package/dist/src/ui/hooks/useFocus.test.js.map +0 -1
  1048. package/dist/src/ui/hooks/useFolderTrust.test.d.ts +0 -6
  1049. package/dist/src/ui/hooks/useFolderTrust.test.js +0 -268
  1050. package/dist/src/ui/hooks/useFolderTrust.test.js.map +0 -1
  1051. package/dist/src/ui/hooks/useGeminiStream.test.d.ts +0 -6
  1052. package/dist/src/ui/hooks/useGeminiStream.test.js +0 -2855
  1053. package/dist/src/ui/hooks/useGeminiStream.test.js.map +0 -1
  1054. package/dist/src/ui/hooks/useGitBranchName.test.d.ts +0 -6
  1055. package/dist/src/ui/hooks/useGitBranchName.test.js +0 -237
  1056. package/dist/src/ui/hooks/useGitBranchName.test.js.map +0 -1
  1057. package/dist/src/ui/hooks/useHistoryManager.test.d.ts +0 -6
  1058. package/dist/src/ui/hooks/useHistoryManager.test.js +0 -259
  1059. package/dist/src/ui/hooks/useHistoryManager.test.js.map +0 -1
  1060. package/dist/src/ui/hooks/useHookDisplayState.test.d.ts +0 -6
  1061. package/dist/src/ui/hooks/useHookDisplayState.test.js +0 -200
  1062. package/dist/src/ui/hooks/useHookDisplayState.test.js.map +0 -1
  1063. package/dist/src/ui/hooks/useIdeTrustListener.test.d.ts +0 -6
  1064. package/dist/src/ui/hooks/useIdeTrustListener.test.js +0 -225
  1065. package/dist/src/ui/hooks/useIdeTrustListener.test.js.map +0 -1
  1066. package/dist/src/ui/hooks/useIncludeDirsTrust.test.d.ts +0 -6
  1067. package/dist/src/ui/hooks/useIncludeDirsTrust.test.js +0 -174
  1068. package/dist/src/ui/hooks/useIncludeDirsTrust.test.js.map +0 -1
  1069. package/dist/src/ui/hooks/useInlineEditBuffer.test.d.ts +0 -6
  1070. package/dist/src/ui/hooks/useInlineEditBuffer.test.js +0 -112
  1071. package/dist/src/ui/hooks/useInlineEditBuffer.test.js.map +0 -1
  1072. package/dist/src/ui/hooks/useInputHistory.test.d.ts +0 -6
  1073. package/dist/src/ui/hooks/useInputHistory.test.js +0 -389
  1074. package/dist/src/ui/hooks/useInputHistory.test.js.map +0 -1
  1075. package/dist/src/ui/hooks/useInputHistoryStore.test.d.ts +0 -6
  1076. package/dist/src/ui/hooks/useInputHistoryStore.test.js +0 -238
  1077. package/dist/src/ui/hooks/useInputHistoryStore.test.js.map +0 -1
  1078. package/dist/src/ui/hooks/useKeypress.test.d.ts +0 -6
  1079. package/dist/src/ui/hooks/useKeypress.test.js +0 -198
  1080. package/dist/src/ui/hooks/useKeypress.test.js.map +0 -1
  1081. package/dist/src/ui/hooks/useLoadingIndicator.test.d.ts +0 -6
  1082. package/dist/src/ui/hooks/useLoadingIndicator.test.js +0 -177
  1083. package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +0 -1
  1084. package/dist/src/ui/hooks/useLogger.test.d.ts +0 -6
  1085. package/dist/src/ui/hooks/useLogger.test.js +0 -44
  1086. package/dist/src/ui/hooks/useLogger.test.js.map +0 -1
  1087. package/dist/src/ui/hooks/useMcpStatus.test.d.ts +0 -6
  1088. package/dist/src/ui/hooks/useMcpStatus.test.js +0 -69
  1089. package/dist/src/ui/hooks/useMcpStatus.test.js.map +0 -1
  1090. package/dist/src/ui/hooks/useMemoryMonitor.test.d.ts +0 -6
  1091. package/dist/src/ui/hooks/useMemoryMonitor.test.js +0 -62
  1092. package/dist/src/ui/hooks/useMemoryMonitor.test.js.map +0 -1
  1093. package/dist/src/ui/hooks/useMessageQueue.test.d.ts +0 -6
  1094. package/dist/src/ui/hooks/useMessageQueue.test.js +0 -365
  1095. package/dist/src/ui/hooks/useMessageQueue.test.js.map +0 -1
  1096. package/dist/src/ui/hooks/useModelCommand.test.d.ts +0 -6
  1097. package/dist/src/ui/hooks/useModelCommand.test.js +0 -45
  1098. package/dist/src/ui/hooks/useModelCommand.test.js.map +0 -1
  1099. package/dist/src/ui/hooks/useMouse.test.d.ts +0 -6
  1100. package/dist/src/ui/hooks/useMouse.test.js +0 -52
  1101. package/dist/src/ui/hooks/useMouse.test.js.map +0 -1
  1102. package/dist/src/ui/hooks/useMouseClick.test.d.ts +0 -6
  1103. package/dist/src/ui/hooks/useMouseClick.test.js +0 -68
  1104. package/dist/src/ui/hooks/useMouseClick.test.js.map +0 -1
  1105. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.d.ts +0 -6
  1106. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js +0 -291
  1107. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js.map +0 -1
  1108. package/dist/src/ui/hooks/usePhraseCycler.test.d.ts +0 -6
  1109. package/dist/src/ui/hooks/usePhraseCycler.test.js +0 -187
  1110. package/dist/src/ui/hooks/usePhraseCycler.test.js.map +0 -1
  1111. package/dist/src/ui/hooks/usePrivacySettings.test.d.ts +0 -6
  1112. package/dist/src/ui/hooks/usePrivacySettings.test.js +0 -113
  1113. package/dist/src/ui/hooks/usePrivacySettings.test.js.map +0 -1
  1114. package/dist/src/ui/hooks/useQuotaAndFallback.test.d.ts +0 -6
  1115. package/dist/src/ui/hooks/useQuotaAndFallback.test.js +0 -817
  1116. package/dist/src/ui/hooks/useQuotaAndFallback.test.js.map +0 -1
  1117. package/dist/src/ui/hooks/useReverseSearchCompletion.test.d.ts +0 -6
  1118. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js +0 -168
  1119. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js.map +0 -1
  1120. package/dist/src/ui/hooks/useRewind.test.d.ts +0 -6
  1121. package/dist/src/ui/hooks/useRewind.test.js +0 -100
  1122. package/dist/src/ui/hooks/useRewind.test.js.map +0 -1
  1123. package/dist/src/ui/hooks/useSelectionList.test.d.ts +0 -6
  1124. package/dist/src/ui/hooks/useSelectionList.test.js +0 -960
  1125. package/dist/src/ui/hooks/useSelectionList.test.js.map +0 -1
  1126. package/dist/src/ui/hooks/useSessionBrowser.test.d.ts +0 -6
  1127. package/dist/src/ui/hooks/useSessionBrowser.test.js +0 -277
  1128. package/dist/src/ui/hooks/useSessionBrowser.test.js.map +0 -1
  1129. package/dist/src/ui/hooks/useSessionResume.test.d.ts +0 -6
  1130. package/dist/src/ui/hooks/useSessionResume.test.js +0 -402
  1131. package/dist/src/ui/hooks/useSessionResume.test.js.map +0 -1
  1132. package/dist/src/ui/hooks/useSettingsNavigation.test.d.ts +0 -6
  1133. package/dist/src/ui/hooks/useSettingsNavigation.test.js +0 -87
  1134. package/dist/src/ui/hooks/useSettingsNavigation.test.js.map +0 -1
  1135. package/dist/src/ui/hooks/useShellCompletion.test.d.ts +0 -6
  1136. package/dist/src/ui/hooks/useShellCompletion.test.js +0 -354
  1137. package/dist/src/ui/hooks/useShellCompletion.test.js.map +0 -1
  1138. package/dist/src/ui/hooks/useShellHistory.test.d.ts +0 -6
  1139. package/dist/src/ui/hooks/useShellHistory.test.js +0 -226
  1140. package/dist/src/ui/hooks/useShellHistory.test.js.map +0 -1
  1141. package/dist/src/ui/hooks/useShellInactivityStatus.test.d.ts +0 -6
  1142. package/dist/src/ui/hooks/useShellInactivityStatus.test.js +0 -84
  1143. package/dist/src/ui/hooks/useShellInactivityStatus.test.js.map +0 -1
  1144. package/dist/src/ui/hooks/useSlashCompletion.test.d.ts +0 -10
  1145. package/dist/src/ui/hooks/useSlashCompletion.test.js +0 -977
  1146. package/dist/src/ui/hooks/useSlashCompletion.test.js.map +0 -1
  1147. package/dist/src/ui/hooks/useSnowfall.test.d.ts +0 -6
  1148. package/dist/src/ui/hooks/useSnowfall.test.js +0 -92
  1149. package/dist/src/ui/hooks/useSnowfall.test.js.map +0 -1
  1150. package/dist/src/ui/hooks/useSuspend.test.d.ts +0 -6
  1151. package/dist/src/ui/hooks/useSuspend.test.js +0 -136
  1152. package/dist/src/ui/hooks/useSuspend.test.js.map +0 -1
  1153. package/dist/src/ui/hooks/useTabbedNavigation.test.d.ts +0 -6
  1154. package/dist/src/ui/hooks/useTabbedNavigation.test.js +0 -243
  1155. package/dist/src/ui/hooks/useTabbedNavigation.test.js.map +0 -1
  1156. package/dist/src/ui/hooks/useTerminalTheme.test.d.ts +0 -6
  1157. package/dist/src/ui/hooks/useTerminalTheme.test.js +0 -169
  1158. package/dist/src/ui/hooks/useTerminalTheme.test.js.map +0 -1
  1159. package/dist/src/ui/hooks/useTimer.test.d.ts +0 -6
  1160. package/dist/src/ui/hooks/useTimer.test.js +0 -119
  1161. package/dist/src/ui/hooks/useTimer.test.js.map +0 -1
  1162. package/dist/src/ui/hooks/useTips.test.d.ts +0 -6
  1163. package/dist/src/ui/hooks/useTips.test.js +0 -33
  1164. package/dist/src/ui/hooks/useTips.test.js.map +0 -1
  1165. package/dist/src/ui/hooks/useToolScheduler.test.d.ts +0 -6
  1166. package/dist/src/ui/hooks/useToolScheduler.test.js +0 -534
  1167. package/dist/src/ui/hooks/useToolScheduler.test.js.map +0 -1
  1168. package/dist/src/ui/hooks/useTurnActivityMonitor.test.d.ts +0 -6
  1169. package/dist/src/ui/hooks/useTurnActivityMonitor.test.js +0 -99
  1170. package/dist/src/ui/hooks/useTurnActivityMonitor.test.js.map +0 -1
  1171. package/dist/src/ui/hooks/vim-passthrough.test.d.ts +0 -6
  1172. package/dist/src/ui/hooks/vim-passthrough.test.js +0 -84
  1173. package/dist/src/ui/hooks/vim-passthrough.test.js.map +0 -1
  1174. package/dist/src/ui/hooks/vim.test.d.ts +0 -6
  1175. package/dist/src/ui/hooks/vim.test.js +0 -2156
  1176. package/dist/src/ui/hooks/vim.test.js.map +0 -1
  1177. package/dist/src/ui/key/keyBindings.test.d.ts +0 -6
  1178. package/dist/src/ui/key/keyBindings.test.js +0 -225
  1179. package/dist/src/ui/key/keyBindings.test.js.map +0 -1
  1180. package/dist/src/ui/key/keyMatchers.test.d.ts +0 -6
  1181. package/dist/src/ui/key/keyMatchers.test.js +0 -524
  1182. package/dist/src/ui/key/keyMatchers.test.js.map +0 -1
  1183. package/dist/src/ui/key/keybindingUtils.test.d.ts +0 -6
  1184. package/dist/src/ui/key/keybindingUtils.test.js +0 -121
  1185. package/dist/src/ui/key/keybindingUtils.test.js.map +0 -1
  1186. package/dist/src/ui/layouts/DefaultAppLayout.test.d.ts +0 -6
  1187. package/dist/src/ui/layouts/DefaultAppLayout.test.js +0 -126
  1188. package/dist/src/ui/layouts/DefaultAppLayout.test.js.map +0 -1
  1189. package/dist/src/ui/privacy/CloudFreePrivacyNotice.test.d.ts +0 -6
  1190. package/dist/src/ui/privacy/CloudFreePrivacyNotice.test.js +0 -134
  1191. package/dist/src/ui/privacy/CloudFreePrivacyNotice.test.js.map +0 -1
  1192. package/dist/src/ui/privacy/CloudPaidPrivacyNotice.test.d.ts +0 -6
  1193. package/dist/src/ui/privacy/CloudPaidPrivacyNotice.test.js +0 -43
  1194. package/dist/src/ui/privacy/CloudPaidPrivacyNotice.test.js.map +0 -1
  1195. package/dist/src/ui/privacy/GeminiPrivacyNotice.test.d.ts +0 -6
  1196. package/dist/src/ui/privacy/GeminiPrivacyNotice.test.js +0 -43
  1197. package/dist/src/ui/privacy/GeminiPrivacyNotice.test.js.map +0 -1
  1198. package/dist/src/ui/privacy/PrivacyNotice.test.d.ts +0 -6
  1199. package/dist/src/ui/privacy/PrivacyNotice.test.js +0 -63
  1200. package/dist/src/ui/privacy/PrivacyNotice.test.js.map +0 -1
  1201. package/dist/src/ui/state/extensions.test.d.ts +0 -6
  1202. package/dist/src/ui/state/extensions.test.js +0 -219
  1203. package/dist/src/ui/state/extensions.test.js.map +0 -1
  1204. package/dist/src/ui/themes/color-utils.test.d.ts +0 -6
  1205. package/dist/src/ui/themes/color-utils.test.js +0 -326
  1206. package/dist/src/ui/themes/color-utils.test.js.map +0 -1
  1207. package/dist/src/ui/themes/theme-manager.test.d.ts +0 -6
  1208. package/dist/src/ui/themes/theme-manager.test.js +0 -274
  1209. package/dist/src/ui/themes/theme-manager.test.js.map +0 -1
  1210. package/dist/src/ui/themes/theme.test.d.ts +0 -6
  1211. package/dist/src/ui/themes/theme.test.js +0 -171
  1212. package/dist/src/ui/themes/theme.test.js.map +0 -1
  1213. package/dist/src/ui/utils/CodeColorizer.test.d.ts +0 -6
  1214. package/dist/src/ui/utils/CodeColorizer.test.js +0 -74
  1215. package/dist/src/ui/utils/CodeColorizer.test.js.map +0 -1
  1216. package/dist/src/ui/utils/ConsolePatcher.test.d.ts +0 -6
  1217. package/dist/src/ui/utils/ConsolePatcher.test.js +0 -199
  1218. package/dist/src/ui/utils/ConsolePatcher.test.js.map +0 -1
  1219. package/dist/src/ui/utils/MarkdownDisplay.test.d.ts +0 -6
  1220. package/dist/src/ui/utils/MarkdownDisplay.test.js +0 -175
  1221. package/dist/src/ui/utils/MarkdownDisplay.test.js.map +0 -1
  1222. package/dist/src/ui/utils/TableRenderer.test.d.ts +0 -1
  1223. package/dist/src/ui/utils/TableRenderer.test.js +0 -396
  1224. package/dist/src/ui/utils/TableRenderer.test.js.map +0 -1
  1225. package/dist/src/ui/utils/antigravityUtils.test.d.ts +0 -6
  1226. package/dist/src/ui/utils/antigravityUtils.test.js +0 -54
  1227. package/dist/src/ui/utils/antigravityUtils.test.js.map +0 -1
  1228. package/dist/src/ui/utils/borderStyles.test.d.ts +0 -6
  1229. package/dist/src/ui/utils/borderStyles.test.js +0 -172
  1230. package/dist/src/ui/utils/borderStyles.test.js.map +0 -1
  1231. package/dist/src/ui/utils/clipboardUtils.test.d.ts +0 -6
  1232. package/dist/src/ui/utils/clipboardUtils.test.js +0 -442
  1233. package/dist/src/ui/utils/clipboardUtils.test.js.map +0 -1
  1234. package/dist/src/ui/utils/clipboardUtils.windows.test.d.ts +0 -6
  1235. package/dist/src/ui/utils/clipboardUtils.windows.test.js +0 -56
  1236. package/dist/src/ui/utils/clipboardUtils.windows.test.js.map +0 -1
  1237. package/dist/src/ui/utils/commandUtils.test.d.ts +0 -6
  1238. package/dist/src/ui/utils/commandUtils.test.js +0 -511
  1239. package/dist/src/ui/utils/commandUtils.test.js.map +0 -1
  1240. package/dist/src/ui/utils/computeStats.test.d.ts +0 -6
  1241. package/dist/src/ui/utils/computeStats.test.js +0 -279
  1242. package/dist/src/ui/utils/computeStats.test.js.map +0 -1
  1243. package/dist/src/ui/utils/directoryUtils.test.d.ts +0 -6
  1244. package/dist/src/ui/utils/directoryUtils.test.js +0 -239
  1245. package/dist/src/ui/utils/directoryUtils.test.js.map +0 -1
  1246. package/dist/src/ui/utils/displayUtils.test.d.ts +0 -6
  1247. package/dist/src/ui/utils/displayUtils.test.js +0 -61
  1248. package/dist/src/ui/utils/displayUtils.test.js.map +0 -1
  1249. package/dist/src/ui/utils/formatters.test.d.ts +0 -6
  1250. package/dist/src/ui/utils/formatters.test.js +0 -152
  1251. package/dist/src/ui/utils/formatters.test.js.map +0 -1
  1252. package/dist/src/ui/utils/highlight.test.d.ts +0 -6
  1253. package/dist/src/ui/utils/highlight.test.js +0 -205
  1254. package/dist/src/ui/utils/highlight.test.js.map +0 -1
  1255. package/dist/src/ui/utils/input.test.d.ts +0 -6
  1256. package/dist/src/ui/utils/input.test.js +0 -44
  1257. package/dist/src/ui/utils/input.test.js.map +0 -1
  1258. package/dist/src/ui/utils/latexToUnicode.test.d.ts +0 -6
  1259. package/dist/src/ui/utils/latexToUnicode.test.js +0 -222
  1260. package/dist/src/ui/utils/latexToUnicode.test.js.map +0 -1
  1261. package/dist/src/ui/utils/markdownParsingUtils.test.d.ts +0 -6
  1262. package/dist/src/ui/utils/markdownParsingUtils.test.js +0 -201
  1263. package/dist/src/ui/utils/markdownParsingUtils.test.js.map +0 -1
  1264. package/dist/src/ui/utils/markdownUtilities.test.d.ts +0 -6
  1265. package/dist/src/ui/utils/markdownUtilities.test.js +0 -42
  1266. package/dist/src/ui/utils/markdownUtilities.test.js.map +0 -1
  1267. package/dist/src/ui/utils/memorySnapshot.test.d.ts +0 -6
  1268. package/dist/src/ui/utils/memorySnapshot.test.js +0 -62
  1269. package/dist/src/ui/utils/memorySnapshot.test.js.map +0 -1
  1270. package/dist/src/ui/utils/mouse.test.d.ts +0 -6
  1271. package/dist/src/ui/utils/mouse.test.js +0 -136
  1272. package/dist/src/ui/utils/mouse.test.js.map +0 -1
  1273. package/dist/src/ui/utils/pendingAttentionNotification.test.d.ts +0 -6
  1274. package/dist/src/ui/utils/pendingAttentionNotification.test.js +0 -79
  1275. package/dist/src/ui/utils/pendingAttentionNotification.test.js.map +0 -1
  1276. package/dist/src/ui/utils/rewindFileOps.test.d.ts +0 -6
  1277. package/dist/src/ui/utils/rewindFileOps.test.js +0 -375
  1278. package/dist/src/ui/utils/rewindFileOps.test.js.map +0 -1
  1279. package/dist/src/ui/utils/terminalCapabilityManager.test.d.ts +0 -6
  1280. package/dist/src/ui/utils/terminalCapabilityManager.test.js +0 -400
  1281. package/dist/src/ui/utils/terminalCapabilityManager.test.js.map +0 -1
  1282. package/dist/src/ui/utils/terminalSetup.test.d.ts +0 -6
  1283. package/dist/src/ui/utils/terminalSetup.test.js +0 -201
  1284. package/dist/src/ui/utils/terminalSetup.test.js.map +0 -1
  1285. package/dist/src/ui/utils/textOutput.test.d.ts +0 -6
  1286. package/dist/src/ui/utils/textOutput.test.js +0 -80
  1287. package/dist/src/ui/utils/textOutput.test.js.map +0 -1
  1288. package/dist/src/ui/utils/textUtils.test.d.ts +0 -6
  1289. package/dist/src/ui/utils/textUtils.test.js +0 -430
  1290. package/dist/src/ui/utils/textUtils.test.js.map +0 -1
  1291. package/dist/src/ui/utils/toolLayoutUtils.test.d.ts +0 -6
  1292. package/dist/src/ui/utils/toolLayoutUtils.test.js +0 -187
  1293. package/dist/src/ui/utils/toolLayoutUtils.test.js.map +0 -1
  1294. package/dist/src/ui/utils/ui-sizing.test.d.ts +0 -6
  1295. package/dist/src/ui/utils/ui-sizing.test.js +0 -25
  1296. package/dist/src/ui/utils/ui-sizing.test.js.map +0 -1
  1297. package/dist/src/ui/utils/updateCheck.test.d.ts +0 -6
  1298. package/dist/src/ui/utils/updateCheck.test.js +0 -207
  1299. package/dist/src/ui/utils/updateCheck.test.js.map +0 -1
  1300. package/dist/src/ui/utils/urlSecurityUtils.test.d.ts +0 -6
  1301. package/dist/src/ui/utils/urlSecurityUtils.test.js +0 -49
  1302. package/dist/src/ui/utils/urlSecurityUtils.test.js.map +0 -1
  1303. package/dist/src/utils/activityLogger.test.d.ts +0 -6
  1304. package/dist/src/utils/activityLogger.test.js +0 -196
  1305. package/dist/src/utils/activityLogger.test.js.map +0 -1
  1306. package/dist/src/utils/agentSettings.test.d.ts +0 -6
  1307. package/dist/src/utils/agentSettings.test.js +0 -111
  1308. package/dist/src/utils/agentSettings.test.js.map +0 -1
  1309. package/dist/src/utils/agentUtils.test.d.ts +0 -6
  1310. package/dist/src/utils/agentUtils.test.js +0 -121
  1311. package/dist/src/utils/agentUtils.test.js.map +0 -1
  1312. package/dist/src/utils/cleanup.test.d.ts +0 -6
  1313. package/dist/src/utils/cleanup.test.js +0 -256
  1314. package/dist/src/utils/cleanup.test.js.map +0 -1
  1315. package/dist/src/utils/commands.test.d.ts +0 -6
  1316. package/dist/src/utils/commands.test.js +0 -194
  1317. package/dist/src/utils/commands.test.js.map +0 -1
  1318. package/dist/src/utils/commentJson.test.d.ts +0 -6
  1319. package/dist/src/utils/commentJson.test.js +0 -308
  1320. package/dist/src/utils/commentJson.test.js.map +0 -1
  1321. package/dist/src/utils/deepMerge.test.d.ts +0 -6
  1322. package/dist/src/utils/deepMerge.test.js +0 -211
  1323. package/dist/src/utils/deepMerge.test.js.map +0 -1
  1324. package/dist/src/utils/devtoolsService.test.d.ts +0 -6
  1325. package/dist/src/utils/devtoolsService.test.js +0 -346
  1326. package/dist/src/utils/devtoolsService.test.js.map +0 -1
  1327. package/dist/src/utils/dialogScopeUtils.test.d.ts +0 -6
  1328. package/dist/src/utils/dialogScopeUtils.test.js +0 -81
  1329. package/dist/src/utils/dialogScopeUtils.test.js.map +0 -1
  1330. package/dist/src/utils/envVarResolver.test.d.ts +0 -6
  1331. package/dist/src/utils/envVarResolver.test.js +0 -238
  1332. package/dist/src/utils/envVarResolver.test.js.map +0 -1
  1333. package/dist/src/utils/errors.test.d.ts +0 -6
  1334. package/dist/src/utils/errors.test.js +0 -420
  1335. package/dist/src/utils/errors.test.js.map +0 -1
  1336. package/dist/src/utils/events.test.d.ts +0 -6
  1337. package/dist/src/utils/events.test.js +0 -24
  1338. package/dist/src/utils/events.test.js.map +0 -1
  1339. package/dist/src/utils/featureToggleUtils.test.d.ts +0 -6
  1340. package/dist/src/utils/featureToggleUtils.test.js +0 -126
  1341. package/dist/src/utils/featureToggleUtils.test.js.map +0 -1
  1342. package/dist/src/utils/gitUtils.test.d.ts +0 -6
  1343. package/dist/src/utils/gitUtils.test.js +0 -172
  1344. package/dist/src/utils/gitUtils.test.js.map +0 -1
  1345. package/dist/src/utils/handleAutoUpdate.test.d.ts +0 -6
  1346. package/dist/src/utils/handleAutoUpdate.test.js +0 -399
  1347. package/dist/src/utils/handleAutoUpdate.test.js.map +0 -1
  1348. package/dist/src/utils/hookSettings.test.d.ts +0 -6
  1349. package/dist/src/utils/hookSettings.test.js +0 -117
  1350. package/dist/src/utils/hookSettings.test.js.map +0 -1
  1351. package/dist/src/utils/hookUtils.test.d.ts +0 -6
  1352. package/dist/src/utils/hookUtils.test.js +0 -113
  1353. package/dist/src/utils/hookUtils.test.js.map +0 -1
  1354. package/dist/src/utils/installationInfo.test.d.ts +0 -6
  1355. package/dist/src/utils/installationInfo.test.js +0 -322
  1356. package/dist/src/utils/installationInfo.test.js.map +0 -1
  1357. package/dist/src/utils/jsonoutput.test.d.ts +0 -6
  1358. package/dist/src/utils/jsonoutput.test.js +0 -74
  1359. package/dist/src/utils/jsonoutput.test.js.map +0 -1
  1360. package/dist/src/utils/logCleanup.test.d.ts +0 -6
  1361. package/dist/src/utils/logCleanup.test.js +0 -87
  1362. package/dist/src/utils/logCleanup.test.js.map +0 -1
  1363. package/dist/src/utils/math.test.d.ts +0 -6
  1364. package/dist/src/utils/math.test.js +0 -23
  1365. package/dist/src/utils/math.test.js.map +0 -1
  1366. package/dist/src/utils/persistentState.test.d.ts +0 -6
  1367. package/dist/src/utils/persistentState.test.js +0 -68
  1368. package/dist/src/utils/persistentState.test.js.map +0 -1
  1369. package/dist/src/utils/processUtils.test.d.ts +0 -6
  1370. package/dist/src/utils/processUtils.test.js +0 -150
  1371. package/dist/src/utils/processUtils.test.js.map +0 -1
  1372. package/dist/src/utils/readStdin.test.d.ts +0 -6
  1373. package/dist/src/utils/readStdin.test.js +0 -149
  1374. package/dist/src/utils/readStdin.test.js.map +0 -1
  1375. package/dist/src/utils/readStdin_safety.test.d.ts +0 -6
  1376. package/dist/src/utils/readStdin_safety.test.js +0 -68
  1377. package/dist/src/utils/readStdin_safety.test.js.map +0 -1
  1378. package/dist/src/utils/relaunch.test.d.ts +0 -6
  1379. package/dist/src/utils/relaunch.test.js +0 -275
  1380. package/dist/src/utils/relaunch.test.js.map +0 -1
  1381. package/dist/src/utils/resolvePath.test.d.ts +0 -6
  1382. package/dist/src/utils/resolvePath.test.js +0 -34
  1383. package/dist/src/utils/resolvePath.test.js.map +0 -1
  1384. package/dist/src/utils/sandbox.test.d.ts +0 -6
  1385. package/dist/src/utils/sandbox.test.js +0 -725
  1386. package/dist/src/utils/sandbox.test.js.map +0 -1
  1387. package/dist/src/utils/sandboxUtils.test.d.ts +0 -6
  1388. package/dist/src/utils/sandboxUtils.test.js +0 -190
  1389. package/dist/src/utils/sandboxUtils.test.js.map +0 -1
  1390. package/dist/src/utils/sessionCleanup.integration.test.d.ts +0 -6
  1391. package/dist/src/utils/sessionCleanup.integration.test.js +0 -276
  1392. package/dist/src/utils/sessionCleanup.integration.test.js.map +0 -1
  1393. package/dist/src/utils/sessionCleanup.test.d.ts +0 -6
  1394. package/dist/src/utils/sessionCleanup.test.js +0 -829
  1395. package/dist/src/utils/sessionCleanup.test.js.map +0 -1
  1396. package/dist/src/utils/sessionUtils.test.d.ts +0 -6
  1397. package/dist/src/utils/sessionUtils.test.js +0 -815
  1398. package/dist/src/utils/sessionUtils.test.js.map +0 -1
  1399. package/dist/src/utils/sessions.test.d.ts +0 -6
  1400. package/dist/src/utils/sessions.test.js +0 -580
  1401. package/dist/src/utils/sessions.test.js.map +0 -1
  1402. package/dist/src/utils/settingsUtils.test.d.ts +0 -6
  1403. package/dist/src/utils/settingsUtils.test.js +0 -673
  1404. package/dist/src/utils/settingsUtils.test.js.map +0 -1
  1405. package/dist/src/utils/skillSettings.test.d.ts +0 -6
  1406. package/dist/src/utils/skillSettings.test.js +0 -142
  1407. package/dist/src/utils/skillSettings.test.js.map +0 -1
  1408. package/dist/src/utils/skillUtils.test.d.ts +0 -6
  1409. package/dist/src/utils/skillUtils.test.js +0 -248
  1410. package/dist/src/utils/skillUtils.test.js.map +0 -1
  1411. package/dist/src/utils/startupWarnings.test.d.ts +0 -6
  1412. package/dist/src/utils/startupWarnings.test.js +0 -61
  1413. package/dist/src/utils/startupWarnings.test.js.map +0 -1
  1414. package/dist/src/utils/terminalNotifications.test.d.ts +0 -6
  1415. package/dist/src/utils/terminalNotifications.test.js +0 -219
  1416. package/dist/src/utils/terminalNotifications.test.js.map +0 -1
  1417. package/dist/src/utils/terminalTheme.test.d.ts +0 -6
  1418. package/dist/src/utils/terminalTheme.test.js +0 -91
  1419. package/dist/src/utils/terminalTheme.test.js.map +0 -1
  1420. package/dist/src/utils/tierUtils.test.d.ts +0 -6
  1421. package/dist/src/utils/tierUtils.test.js +0 -25
  1422. package/dist/src/utils/tierUtils.test.js.map +0 -1
  1423. package/dist/src/utils/toolOutputCleanup.test.d.ts +0 -6
  1424. package/dist/src/utils/toolOutputCleanup.test.js +0 -280
  1425. package/dist/src/utils/toolOutputCleanup.test.js.map +0 -1
  1426. package/dist/src/utils/updateEventEmitter.test.d.ts +0 -6
  1427. package/dist/src/utils/updateEventEmitter.test.js +0 -18
  1428. package/dist/src/utils/updateEventEmitter.test.js.map +0 -1
  1429. package/dist/src/utils/userStartupWarnings.test.d.ts +0 -6
  1430. package/dist/src/utils/userStartupWarnings.test.js +0 -225
  1431. package/dist/src/utils/userStartupWarnings.test.js.map +0 -1
  1432. package/dist/src/utils/windowTitle.test.d.ts +0 -6
  1433. package/dist/src/utils/windowTitle.test.js +0 -216
  1434. package/dist/src/utils/windowTitle.test.js.map +0 -1
  1435. package/dist/src/utils/worktreeSetup.test.d.ts +0 -6
  1436. package/dist/src/utils/worktreeSetup.test.js +0 -89
  1437. package/dist/src/utils/worktreeSetup.test.js.map +0 -1
  1438. package/dist/src/validateNonInterActiveAuth.test.d.ts +0 -6
  1439. package/dist/src/validateNonInterActiveAuth.test.js +0 -319
  1440. package/dist/src/validateNonInterActiveAuth.test.js.map +0 -1
@@ -1,4078 +0,0 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- /**
3
- * @license
4
- * Copyright 2025 Google LLC
5
- * SPDX-License-Identifier: Apache-2.0
6
- */
7
- import { renderWithProviders, cleanup } from '../../test-utils/render.js';
8
- import { createMockSettings } from '../../test-utils/settings.js';
9
- import { makeFakeConfig } from '@google/gemini-cli-core';
10
- import { waitFor } from '../../test-utils/async.js';
11
- import { act, useState, useMemo } from 'react';
12
- const { fakeTranscriptionProvider } = vi.hoisted(() => {
13
- // Use require within hoisted block for immediate synchronous access
14
- // eslint-disable-next-line @typescript-eslint/no-require-imports, no-restricted-syntax
15
- const { EventEmitter } = require('node:events');
16
- class FakeTranscriptionProvider extends EventEmitter {
17
- connect = vi.fn().mockResolvedValue(undefined);
18
- disconnect = vi.fn();
19
- sendAudioChunk = vi.fn();
20
- getTranscription = vi.fn().mockReturnValue('');
21
- }
22
- return {
23
- fakeTranscriptionProvider: new FakeTranscriptionProvider(),
24
- };
25
- });
26
- vi.mock('@google/gemini-cli-core', async (importOriginal) => {
27
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
- const actual = (await importOriginal());
29
- return {
30
- ...actual,
31
- TranscriptionFactory: {
32
- createProvider: vi.fn(() => fakeTranscriptionProvider),
33
- },
34
- };
35
- });
36
- import { InputPrompt, tryTogglePasteExpansion, } from './InputPrompt.js';
37
- import { InputContext } from '../contexts/InputContext.js';
38
- import {} from '../contexts/UIStateContext.js';
39
- import { calculateTransformationsForLine, calculateTransformedLine, } from './shared/text-buffer.js';
40
- import { ApprovalMode, debugLogger, coreEvents, } from '@google/gemini-cli-core';
41
- import * as path from 'node:path';
42
- import { CommandKind, } from '../commands/types.js';
43
- import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
44
- import { Text } from 'ink';
45
- ;
46
- import { useShellHistory, } from '../hooks/useShellHistory.js';
47
- import { useCommandCompletion, CompletionMode, } from '../hooks/useCommandCompletion.js';
48
- import { useInputHistory, } from '../hooks/useInputHistory.js';
49
- import { useReverseSearchCompletion, } from '../hooks/useReverseSearchCompletion.js';
50
- import clipboardy from 'clipboardy';
51
- import * as clipboardUtils from '../utils/clipboardUtils.js';
52
- import { useKittyKeyboardProtocol } from '../hooks/useKittyKeyboardProtocol.js';
53
- import { createMockCommandContext } from '../../test-utils/mockCommandContext.js';
54
- import stripAnsi from 'strip-ansi';
55
- import { StreamingState } from '../types.js';
56
- import { terminalCapabilityManager } from '../utils/terminalCapabilityManager.js';
57
- import { cpLen } from '../utils/textUtils.js';
58
- import { defaultKeyMatchers, Command } from '../key/keyMatchers.js';
59
- import { useKeypress } from '../hooks/useKeypress.js';
60
- import { appEvents, AppEvent, TransientMessageType, } from '../../utils/events.js';
61
- import '../../test-utils/customMatchers.js';
62
- vi.mock('../hooks/useShellHistory.js');
63
- vi.mock('../hooks/useCommandCompletion.js');
64
- vi.mock('../hooks/useInputHistory.js');
65
- vi.mock('../hooks/useReverseSearchCompletion.js');
66
- vi.mock('clipboardy');
67
- vi.mock('../utils/clipboardUtils.js');
68
- vi.mock('../hooks/useKittyKeyboardProtocol.js');
69
- vi.mock('./ListeningIndicator.js', () => ({
70
- ListeningIndicator: vi.fn(({ color }) => _jsx(Text, { color: color, children: "~~~ " })),
71
- }));
72
- // Mock ink BEFORE importing components that use it to intercept terminalCursorPosition
73
- vi.mock('ink', async (importOriginal) => {
74
- const actual = await importOriginal();
75
- return {
76
- ...actual,
77
- Text: vi.fn(({ children, ...props }) => (_jsx(actual.Text, { ...props, children: children }))),
78
- };
79
- });
80
- afterEach(() => {
81
- vi.restoreAllMocks();
82
- vi.useRealTimers();
83
- cleanup();
84
- });
85
- const mockSlashCommands = [
86
- {
87
- name: 'stats',
88
- description: 'Check stats',
89
- kind: CommandKind.BUILT_IN,
90
- isSafeConcurrent: true,
91
- },
92
- {
93
- name: 'clear',
94
- kind: CommandKind.BUILT_IN,
95
- description: 'Clear screen',
96
- action: vi.fn(),
97
- },
98
- {
99
- name: 'memory',
100
- kind: CommandKind.BUILT_IN,
101
- description: 'Manage memory',
102
- subCommands: [
103
- {
104
- name: 'show',
105
- kind: CommandKind.BUILT_IN,
106
- description: 'Show memory',
107
- action: vi.fn(),
108
- },
109
- {
110
- name: 'add',
111
- kind: CommandKind.BUILT_IN,
112
- description: 'Add to memory',
113
- action: vi.fn(),
114
- },
115
- {
116
- name: 'refresh',
117
- kind: CommandKind.BUILT_IN,
118
- description: 'Refresh memory',
119
- action: vi.fn(),
120
- },
121
- ],
122
- },
123
- {
124
- name: 'chat',
125
- description: 'Manage chats',
126
- kind: CommandKind.BUILT_IN,
127
- subCommands: [
128
- {
129
- name: 'resume',
130
- description: 'Resume a chat',
131
- kind: CommandKind.BUILT_IN,
132
- action: vi.fn(),
133
- completion: async () => ['fix-foo', 'fix-bar'],
134
- },
135
- ],
136
- },
137
- {
138
- name: 'resume',
139
- description: 'Browse and resume sessions',
140
- kind: CommandKind.BUILT_IN,
141
- action: vi.fn(),
142
- },
143
- ];
144
- const TestInputPrompt = (props) => {
145
- const contextValue = useMemo(() => ({
146
- buffer: props.buffer,
147
- userMessages: props.userMessages,
148
- shellModeActive: props.shellModeActive,
149
- copyModeEnabled: props.copyModeEnabled,
150
- showEscapePrompt: props.showEscapePrompt || false,
151
- inputWidth: props.inputWidth,
152
- suggestionsWidth: props.suggestionsWidth,
153
- }), [
154
- props.buffer,
155
- props.userMessages,
156
- props.shellModeActive,
157
- props.copyModeEnabled,
158
- props.showEscapePrompt,
159
- props.inputWidth,
160
- props.suggestionsWidth,
161
- ]);
162
- return (_jsx(InputContext.Provider, { value: contextValue, children: _jsx(InputPrompt, { ...props }) }));
163
- };
164
- describe('InputPrompt', () => {
165
- let props;
166
- let mockShellHistory;
167
- let mockCommandCompletion;
168
- let mockInputHistory;
169
- let mockReverseSearchCompletion;
170
- let mockBuffer;
171
- let mockCommandContext;
172
- const GlobalEscapeHandler = ({ onEscape }) => {
173
- useKeypress((key) => {
174
- if (key.name !== 'escape')
175
- return false;
176
- onEscape();
177
- return true;
178
- }, { isActive: true, priority: false });
179
- return null;
180
- };
181
- const mockedUseShellHistory = vi.mocked(useShellHistory);
182
- const mockedUseCommandCompletion = vi.mocked(useCommandCompletion);
183
- const mockedUseInputHistory = vi.mocked(useInputHistory);
184
- const mockedUseReverseSearchCompletion = vi.mocked(useReverseSearchCompletion);
185
- const mockedUseKittyKeyboardProtocol = vi.mocked(useKittyKeyboardProtocol);
186
- const mockSetEmbeddedShellFocused = vi.fn();
187
- const mockSetCleanUiDetailsVisible = vi.fn();
188
- const mockToggleCleanUiDetailsVisible = vi.fn();
189
- const mockRevealCleanUiDetailsTemporarily = vi.fn();
190
- const uiActions = {
191
- setEmbeddedShellFocused: mockSetEmbeddedShellFocused,
192
- setCleanUiDetailsVisible: mockSetCleanUiDetailsVisible,
193
- toggleCleanUiDetailsVisible: mockToggleCleanUiDetailsVisible,
194
- revealCleanUiDetailsTemporarily: mockRevealCleanUiDetailsTemporarily,
195
- addMessage: vi.fn(),
196
- };
197
- beforeEach(() => {
198
- vi.resetAllMocks();
199
- coreEvents.removeAllListeners();
200
- vi.spyOn(terminalCapabilityManager, 'isKittyProtocolEnabled').mockReturnValue(true);
201
- mockCommandContext = createMockCommandContext();
202
- mockBuffer = {
203
- text: '',
204
- cursor: [0, 0],
205
- lines: [''],
206
- setText: vi.fn((newText, cursorPosition) => {
207
- mockBuffer.text = newText;
208
- mockBuffer.lines = newText.split('\n');
209
- let col = 0;
210
- if (typeof cursorPosition === 'number') {
211
- col = cursorPosition;
212
- }
213
- else if (cursorPosition === 'start') {
214
- col = 0;
215
- }
216
- else {
217
- col = newText.length;
218
- }
219
- mockBuffer.cursor = [0, col];
220
- mockBuffer.allVisualLines = newText.split('\n');
221
- mockBuffer.viewportVisualLines = newText.split('\n');
222
- mockBuffer.visualToLogicalMap = newText
223
- .split('\n')
224
- .map((_, i) => [i, 0]);
225
- mockBuffer.visualCursor = [0, col];
226
- mockBuffer.visualScrollRow = 0;
227
- mockBuffer.viewportHeight = 10;
228
- mockBuffer.visualToTransformedMap = newText
229
- .split('\n')
230
- .map((_, i) => i);
231
- mockBuffer.transformationsByLine = newText.split('\n').map(() => []);
232
- }),
233
- replaceRangeByOffset: vi.fn(),
234
- viewportVisualLines: [''],
235
- allVisualLines: [''],
236
- visualCursor: [0, 0],
237
- visualScrollRow: 0,
238
- viewportHeight: 10,
239
- handleInput: vi.fn((key) => {
240
- if (defaultKeyMatchers[Command.CLEAR_INPUT](key)) {
241
- if (mockBuffer.text.length > 0) {
242
- mockBuffer.setText('');
243
- return true;
244
- }
245
- return false;
246
- }
247
- return false;
248
- }),
249
- move: vi.fn((dir) => {
250
- if (dir === 'home') {
251
- mockBuffer.visualCursor = [mockBuffer.visualCursor[0], 0];
252
- }
253
- else if (dir === 'end') {
254
- const line = mockBuffer.allVisualLines[mockBuffer.visualCursor[0]] || '';
255
- mockBuffer.visualCursor = [mockBuffer.visualCursor[0], cpLen(line)];
256
- }
257
- }),
258
- moveToOffset: vi.fn((offset) => {
259
- mockBuffer.cursor = [0, offset];
260
- }),
261
- moveToVisualPosition: vi.fn(),
262
- killLineRight: vi.fn(),
263
- killLineLeft: vi.fn(),
264
- openInExternalEditor: vi.fn(),
265
- newline: vi.fn(),
266
- undo: vi.fn(),
267
- redo: vi.fn(),
268
- backspace: vi.fn(),
269
- preferredCol: null,
270
- selectionAnchor: null,
271
- insert: vi.fn(),
272
- del: vi.fn(),
273
- replaceRange: vi.fn(),
274
- deleteWordLeft: vi.fn(),
275
- deleteWordRight: vi.fn(),
276
- visualToLogicalMap: [[0, 0]],
277
- visualToTransformedMap: [0],
278
- transformationsByLine: [],
279
- getOffset: vi.fn().mockImplementation(() => mockBuffer.cursor[1]),
280
- pastedContent: {},
281
- };
282
- mockShellHistory = {
283
- history: [],
284
- addCommandToHistory: vi.fn(),
285
- getPreviousCommand: vi.fn().mockReturnValue(null),
286
- getNextCommand: vi.fn().mockReturnValue(null),
287
- resetHistoryPosition: vi.fn(),
288
- };
289
- mockedUseShellHistory.mockReturnValue(mockShellHistory);
290
- mockCommandCompletion = {
291
- suggestions: [],
292
- activeSuggestionIndex: -1,
293
- isLoadingSuggestions: false,
294
- showSuggestions: false,
295
- visibleStartIndex: 0,
296
- isPerfectMatch: false,
297
- navigateUp: vi.fn(),
298
- navigateDown: vi.fn(),
299
- resetCompletionState: vi.fn(),
300
- setActiveSuggestionIndex: vi.fn(),
301
- handleAutocomplete: vi.fn(),
302
- promptCompletion: {
303
- text: '',
304
- accept: vi.fn(),
305
- clear: vi.fn(),
306
- isLoading: false,
307
- isActive: false,
308
- markSelected: vi.fn(),
309
- },
310
- getCommandFromSuggestion: vi.fn().mockReturnValue(undefined),
311
- slashCompletionRange: {
312
- completionStart: -1,
313
- completionEnd: -1,
314
- getCommandFromSuggestion: vi.fn().mockReturnValue(undefined),
315
- isArgumentCompletion: false,
316
- leafCommand: null,
317
- },
318
- getCompletedText: vi.fn().mockReturnValue(null),
319
- completionMode: CompletionMode.IDLE,
320
- forceShowShellSuggestions: false,
321
- setForceShowShellSuggestions: vi.fn(),
322
- isShellSuggestionsVisible: true,
323
- };
324
- mockedUseCommandCompletion.mockReturnValue(mockCommandCompletion);
325
- mockInputHistory = {
326
- navigateUp: vi.fn(),
327
- navigateDown: vi.fn(),
328
- handleSubmit: vi.fn(),
329
- };
330
- mockedUseInputHistory.mockImplementation(({ onSubmit }) => {
331
- mockInputHistory.handleSubmit = vi.fn((val) => onSubmit(val));
332
- return mockInputHistory;
333
- });
334
- mockReverseSearchCompletion = {
335
- suggestions: [],
336
- activeSuggestionIndex: -1,
337
- visibleStartIndex: 0,
338
- showSuggestions: false,
339
- isLoadingSuggestions: false,
340
- navigateUp: vi.fn(),
341
- navigateDown: vi.fn(),
342
- handleAutocomplete: vi.fn(),
343
- resetCompletionState: vi.fn(),
344
- };
345
- mockedUseReverseSearchCompletion.mockReturnValue(mockReverseSearchCompletion);
346
- mockedUseKittyKeyboardProtocol.mockReturnValue({
347
- enabled: false,
348
- checking: false,
349
- });
350
- vi.mocked(clipboardy.read).mockResolvedValue('');
351
- props = {
352
- onQueueMessage: vi.fn(),
353
- buffer: mockBuffer,
354
- onSubmit: vi.fn(),
355
- userMessages: [],
356
- onClearScreen: vi.fn(),
357
- config: {
358
- getProjectRoot: () => path.join('test', 'project'),
359
- getTargetDir: () => path.join('test', 'project', 'src'),
360
- getVimMode: () => false,
361
- getUseBackgroundColor: () => true,
362
- getUseTerminalBuffer: () => false,
363
- getTerminalBackground: () => undefined,
364
- getWorkspaceContext: () => ({
365
- getDirectories: () => ['/test/project/src'],
366
- }),
367
- getContentGeneratorConfig: () => ({ apiKey: 'test-api-key' }),
368
- },
369
- slashCommands: mockSlashCommands,
370
- commandContext: mockCommandContext,
371
- shellModeActive: false,
372
- setShellModeActive: vi.fn(),
373
- approvalMode: ApprovalMode.DEFAULT,
374
- inputWidth: 80,
375
- suggestionsWidth: 80,
376
- focus: true,
377
- setQueueErrorMessage: vi.fn(),
378
- streamingState: StreamingState.Idle,
379
- setBannerVisible: vi.fn(),
380
- };
381
- });
382
- it('should call shellHistory.getPreviousCommand on up arrow in shell mode', async () => {
383
- props.shellModeActive = true;
384
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
385
- uiActions,
386
- });
387
- await act(async () => {
388
- stdin.write('\u001B[A');
389
- });
390
- await waitFor(() => expect(mockShellHistory.getPreviousCommand).toHaveBeenCalled());
391
- unmount();
392
- });
393
- it('should call shellHistory.getNextCommand on down arrow in shell mode', async () => {
394
- props.shellModeActive = true;
395
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
396
- uiActions,
397
- });
398
- await act(async () => {
399
- stdin.write('\u001B[B');
400
- await waitFor(() => expect(mockShellHistory.getNextCommand).toHaveBeenCalled());
401
- });
402
- unmount();
403
- });
404
- it('should set the buffer text when a shell history command is retrieved', async () => {
405
- props.shellModeActive = true;
406
- vi.mocked(mockShellHistory.getPreviousCommand).mockReturnValue('previous command');
407
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
408
- uiActions,
409
- });
410
- await act(async () => {
411
- stdin.write('\u001B[A');
412
- });
413
- await waitFor(() => {
414
- expect(mockShellHistory.getPreviousCommand).toHaveBeenCalled();
415
- expect(props.buffer.setText).toHaveBeenCalledWith('previous command');
416
- });
417
- unmount();
418
- });
419
- it('should call shellHistory.addCommandToHistory on submit in shell mode', async () => {
420
- props.shellModeActive = true;
421
- props.buffer.setText('ls -l');
422
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
423
- uiActions,
424
- });
425
- await act(async () => {
426
- stdin.write('\r');
427
- });
428
- await waitFor(() => {
429
- expect(mockShellHistory.addCommandToHistory).toHaveBeenCalledWith('ls -l');
430
- expect(props.onSubmit).toHaveBeenCalledWith('ls -l');
431
- });
432
- unmount();
433
- });
434
- it('should submit command in shell mode when Enter pressed with suggestions visible but no arrow navigation', async () => {
435
- props.shellModeActive = true;
436
- props.buffer.setText('ls ');
437
- mockedUseCommandCompletion.mockReturnValue({
438
- ...mockCommandCompletion,
439
- showSuggestions: true,
440
- suggestions: [
441
- { label: 'dir1', value: 'dir1' },
442
- { label: 'dir2', value: 'dir2' },
443
- ],
444
- activeSuggestionIndex: 0,
445
- });
446
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
447
- uiActions,
448
- });
449
- // Press Enter without navigating — should dismiss suggestions and fall
450
- // through to the main submit handler.
451
- await act(async () => {
452
- stdin.write('\r');
453
- });
454
- await waitFor(() => {
455
- expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
456
- expect(props.onSubmit).toHaveBeenCalledWith('ls'); // Assert fall-through (text is trimmed)
457
- });
458
- expect(mockCommandCompletion.handleAutocomplete).not.toHaveBeenCalled();
459
- unmount();
460
- });
461
- it('should accept suggestion in shell mode when Enter pressed after arrow navigation', async () => {
462
- props.shellModeActive = true;
463
- props.buffer.setText('ls ');
464
- mockedUseCommandCompletion.mockReturnValue({
465
- ...mockCommandCompletion,
466
- showSuggestions: true,
467
- suggestions: [
468
- { label: 'dir1', value: 'dir1' },
469
- { label: 'dir2', value: 'dir2' },
470
- ],
471
- activeSuggestionIndex: 1,
472
- });
473
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
474
- uiActions,
475
- });
476
- // Press ArrowDown to navigate, then Enter to accept
477
- await act(async () => {
478
- stdin.write('\u001B[B'); // ArrowDown — sets hasUserNavigatedSuggestions
479
- });
480
- await waitFor(() => expect(mockCommandCompletion.navigateDown).toHaveBeenCalled());
481
- await act(async () => {
482
- stdin.write('\r'); // Enter — should accept navigated suggestion
483
- });
484
- await waitFor(() => {
485
- expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(1);
486
- });
487
- expect(props.onSubmit).not.toHaveBeenCalled();
488
- unmount();
489
- });
490
- it('should NOT call shell history methods when not in shell mode', async () => {
491
- props.buffer.setText('some text');
492
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
493
- uiActions,
494
- });
495
- await act(async () => {
496
- stdin.write('\u0010'); // Ctrl+P
497
- });
498
- await waitFor(() => expect(mockInputHistory.navigateUp).toHaveBeenCalled());
499
- await act(async () => {
500
- stdin.write('\u000E'); // Ctrl+N
501
- });
502
- await waitFor(() => expect(mockInputHistory.navigateDown).toHaveBeenCalled());
503
- await act(async () => {
504
- stdin.write('\r'); // Enter
505
- });
506
- await waitFor(() => expect(props.onSubmit).toHaveBeenCalledWith('some text'));
507
- expect(mockShellHistory.getPreviousCommand).not.toHaveBeenCalled();
508
- expect(mockShellHistory.getNextCommand).not.toHaveBeenCalled();
509
- expect(mockShellHistory.addCommandToHistory).not.toHaveBeenCalled();
510
- unmount();
511
- });
512
- describe('arrow key navigation', () => {
513
- it('should move to start of line on Up arrow if on first line but not at start', async () => {
514
- mockBuffer.allVisualLines = ['line 1', 'line 2'];
515
- mockBuffer.visualCursor = [0, 5]; // First line, not at start
516
- mockBuffer.visualScrollRow = 0;
517
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
518
- uiActions,
519
- });
520
- await act(async () => {
521
- stdin.write('\u001B[A'); // Up arrow
522
- });
523
- await waitFor(() => {
524
- expect(mockBuffer.move).toHaveBeenCalledWith('home');
525
- expect(mockInputHistory.navigateUp).not.toHaveBeenCalled();
526
- });
527
- unmount();
528
- });
529
- it('should navigate history on Up arrow if on first line and at start', async () => {
530
- mockBuffer.allVisualLines = ['line 1', 'line 2'];
531
- mockBuffer.visualCursor = [0, 0]; // First line, at start
532
- mockBuffer.visualScrollRow = 0;
533
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
534
- uiActions,
535
- });
536
- await act(async () => {
537
- stdin.write('\u001B[A'); // Up arrow
538
- });
539
- await waitFor(() => {
540
- expect(mockBuffer.move).not.toHaveBeenCalledWith('home');
541
- expect(mockInputHistory.navigateUp).toHaveBeenCalled();
542
- });
543
- unmount();
544
- });
545
- it('should move to end of line on Down arrow if on last line but not at end', async () => {
546
- mockBuffer.allVisualLines = ['line 1', 'line 2'];
547
- mockBuffer.visualCursor = [1, 0]; // Last line, not at end
548
- mockBuffer.visualScrollRow = 0;
549
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
550
- uiActions,
551
- });
552
- await act(async () => {
553
- stdin.write('\u001B[B'); // Down arrow
554
- });
555
- await waitFor(() => {
556
- expect(mockBuffer.move).toHaveBeenCalledWith('end');
557
- expect(mockInputHistory.navigateDown).not.toHaveBeenCalled();
558
- });
559
- unmount();
560
- });
561
- it('should navigate history on Down arrow if on last line and at end', async () => {
562
- mockBuffer.allVisualLines = ['line 1', 'line 2'];
563
- mockBuffer.visualCursor = [1, 6]; // Last line, at end ("line 2" is length 6)
564
- mockBuffer.visualScrollRow = 0;
565
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
566
- uiActions,
567
- });
568
- await act(async () => {
569
- stdin.write('\u001B[B'); // Down arrow
570
- });
571
- await waitFor(() => {
572
- expect(mockBuffer.move).not.toHaveBeenCalledWith('end');
573
- expect(mockInputHistory.navigateDown).toHaveBeenCalled();
574
- });
575
- unmount();
576
- });
577
- });
578
- it('should call completion.navigateUp for both up arrow and Ctrl+P when suggestions are showing', async () => {
579
- mockedUseCommandCompletion.mockReturnValue({
580
- ...mockCommandCompletion,
581
- showSuggestions: true,
582
- suggestions: [
583
- { label: 'memory', value: 'memory' },
584
- { label: 'memcache', value: 'memcache' },
585
- ],
586
- });
587
- props.buffer.setText('/mem');
588
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
589
- uiActions,
590
- });
591
- // Test up arrow
592
- await act(async () => {
593
- stdin.write('\u001B[A'); // Up arrow
594
- });
595
- await waitFor(() => expect(mockCommandCompletion.navigateUp).toHaveBeenCalledTimes(1));
596
- await act(async () => {
597
- stdin.write('\u0010'); // Ctrl+P
598
- });
599
- await waitFor(() => expect(mockCommandCompletion.navigateUp).toHaveBeenCalledTimes(2));
600
- expect(mockCommandCompletion.navigateDown).not.toHaveBeenCalled();
601
- unmount();
602
- });
603
- it('should call completion.navigateDown for both down arrow and Ctrl+N when suggestions are showing', async () => {
604
- mockedUseCommandCompletion.mockReturnValue({
605
- ...mockCommandCompletion,
606
- showSuggestions: true,
607
- suggestions: [
608
- { label: 'memory', value: 'memory' },
609
- { label: 'memcache', value: 'memcache' },
610
- ],
611
- });
612
- props.buffer.setText('/mem');
613
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
614
- uiActions,
615
- });
616
- // Test down arrow
617
- await act(async () => {
618
- stdin.write('\u001B[B'); // Down arrow
619
- });
620
- await waitFor(() => expect(mockCommandCompletion.navigateDown).toHaveBeenCalledTimes(1));
621
- await act(async () => {
622
- stdin.write('\u000E'); // Ctrl+N
623
- });
624
- await waitFor(() => expect(mockCommandCompletion.navigateDown).toHaveBeenCalledTimes(2));
625
- expect(mockCommandCompletion.navigateUp).not.toHaveBeenCalled();
626
- unmount();
627
- });
628
- it('should NOT call completion navigation when suggestions are not showing', async () => {
629
- mockedUseCommandCompletion.mockReturnValue({
630
- ...mockCommandCompletion,
631
- showSuggestions: false,
632
- });
633
- props.buffer.setText('some text');
634
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
635
- uiActions,
636
- });
637
- await act(async () => {
638
- stdin.write('\u0010'); // Ctrl+P
639
- });
640
- await waitFor(() => expect(mockInputHistory.navigateUp).toHaveBeenCalled());
641
- await act(async () => {
642
- stdin.write('\u000E'); // Ctrl+N
643
- });
644
- await waitFor(() => expect(mockInputHistory.navigateDown).toHaveBeenCalled());
645
- await act(async () => {
646
- stdin.write('\u0010'); // Ctrl+P
647
- });
648
- await act(async () => {
649
- stdin.write('\u000E'); // Ctrl+N
650
- });
651
- await waitFor(() => {
652
- expect(mockCommandCompletion.navigateUp).not.toHaveBeenCalled();
653
- expect(mockCommandCompletion.navigateDown).not.toHaveBeenCalled();
654
- });
655
- unmount();
656
- });
657
- it('should clear the buffer and reset completion on Ctrl+C', async () => {
658
- mockBuffer.text = 'some text';
659
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
660
- uiActions,
661
- });
662
- await act(async () => {
663
- stdin.write('\u0003'); // Ctrl+C
664
- });
665
- await waitFor(() => {
666
- expect(mockBuffer.setText).toHaveBeenCalledWith('');
667
- expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
668
- });
669
- unmount();
670
- });
671
- describe('clipboard image paste', () => {
672
- beforeEach(() => {
673
- vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);
674
- vi.mocked(clipboardUtils.saveClipboardImage).mockResolvedValue(null);
675
- vi.mocked(clipboardUtils.cleanupOldClipboardImages).mockResolvedValue(undefined);
676
- });
677
- it('should handle Ctrl+V when clipboard has an image', async () => {
678
- vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(true);
679
- vi.mocked(clipboardUtils.saveClipboardImage).mockResolvedValue('/test/.gemini-clipboard/clipboard-123.png');
680
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
681
- // Send Ctrl+V
682
- await act(async () => {
683
- stdin.write('\x16'); // Ctrl+V
684
- });
685
- await waitFor(() => {
686
- expect(clipboardUtils.clipboardHasImage).toHaveBeenCalled();
687
- expect(clipboardUtils.saveClipboardImage).toHaveBeenCalledWith(props.config.getTargetDir());
688
- expect(clipboardUtils.cleanupOldClipboardImages).toHaveBeenCalledWith(props.config.getTargetDir());
689
- expect(mockBuffer.replaceRangeByOffset).toHaveBeenCalled();
690
- });
691
- unmount();
692
- });
693
- it('should not insert anything when clipboard has no image', async () => {
694
- vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);
695
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
696
- await act(async () => {
697
- stdin.write('\x16'); // Ctrl+V
698
- });
699
- await waitFor(() => {
700
- expect(clipboardUtils.clipboardHasImage).toHaveBeenCalled();
701
- });
702
- expect(clipboardUtils.saveClipboardImage).not.toHaveBeenCalled();
703
- expect(mockBuffer.setText).not.toHaveBeenCalled();
704
- unmount();
705
- });
706
- it('should handle image save failure gracefully', async () => {
707
- vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(true);
708
- vi.mocked(clipboardUtils.saveClipboardImage).mockResolvedValue(null);
709
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
710
- await act(async () => {
711
- stdin.write('\x16'); // Ctrl+V
712
- });
713
- await waitFor(() => {
714
- expect(clipboardUtils.saveClipboardImage).toHaveBeenCalled();
715
- });
716
- expect(mockBuffer.setText).not.toHaveBeenCalled();
717
- unmount();
718
- });
719
- it('should insert image path at cursor position with proper spacing', async () => {
720
- const imagePath = path.join('test', '.gemini-clipboard', 'clipboard-456.png');
721
- vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(true);
722
- vi.mocked(clipboardUtils.saveClipboardImage).mockResolvedValue(imagePath);
723
- // Set initial text and cursor position
724
- mockBuffer.text = 'Hello world';
725
- mockBuffer.cursor = [0, 5]; // Cursor after "Hello"
726
- vi.mocked(mockBuffer.getOffset).mockReturnValue(5);
727
- mockBuffer.lines = ['Hello world'];
728
- mockBuffer.replaceRangeByOffset = vi.fn();
729
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
730
- await act(async () => {
731
- stdin.write('\x16'); // Ctrl+V
732
- });
733
- await waitFor(() => {
734
- // Should insert at cursor position with spaces
735
- expect(mockBuffer.replaceRangeByOffset).toHaveBeenCalled();
736
- });
737
- // Get the actual call to see what path was used
738
- const actualCall = vi.mocked(mockBuffer.replaceRangeByOffset).mock
739
- .calls[0];
740
- expect(actualCall[0]).toBe(5); // start offset
741
- expect(actualCall[1]).toBe(5); // end offset
742
- expect(actualCall[2]).toBe(' @' + path.relative(path.join('test', 'project', 'src'), imagePath));
743
- unmount();
744
- });
745
- it('should handle errors during clipboard operations', async () => {
746
- const debugLoggerErrorSpy = vi
747
- .spyOn(debugLogger, 'error')
748
- .mockImplementation(() => { });
749
- vi.mocked(clipboardUtils.clipboardHasImage).mockRejectedValue(new Error('Clipboard error'));
750
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
751
- await act(async () => {
752
- stdin.write('\x16'); // Ctrl+V
753
- });
754
- await waitFor(() => {
755
- expect(debugLoggerErrorSpy).toHaveBeenCalledWith('Error handling paste:', expect.any(Error));
756
- });
757
- expect(mockBuffer.setText).not.toHaveBeenCalled();
758
- debugLoggerErrorSpy.mockRestore();
759
- unmount();
760
- });
761
- });
762
- describe('clipboard text paste', () => {
763
- it('should insert text from clipboard on Ctrl+V', async () => {
764
- vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);
765
- vi.mocked(clipboardy.read).mockResolvedValue('pasted text');
766
- vi.mocked(mockBuffer.replaceRangeByOffset).mockClear();
767
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
768
- await act(async () => {
769
- stdin.write('\x16'); // Ctrl+V
770
- });
771
- await waitFor(() => {
772
- expect(clipboardy.read).toHaveBeenCalled();
773
- expect(mockBuffer.insert).toHaveBeenCalledWith('pasted text', expect.objectContaining({ paste: true }));
774
- });
775
- unmount();
776
- });
777
- it('should use OSC 52 when useOSC52Paste setting is enabled', async () => {
778
- vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);
779
- const settings = createMockSettings({
780
- experimental: { useOSC52Paste: true },
781
- });
782
- const { stdout, stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { settings });
783
- const writeSpy = vi.spyOn(stdout, 'write');
784
- await act(async () => {
785
- stdin.write('\x16'); // Ctrl+V
786
- });
787
- await waitFor(() => {
788
- expect(writeSpy).toHaveBeenCalledWith('\x1b]52;c;?\x07');
789
- });
790
- // Should NOT call clipboardy.read()
791
- expect(clipboardy.read).not.toHaveBeenCalled();
792
- unmount();
793
- });
794
- });
795
- it.each([
796
- {
797
- name: 'should complete a partial parent command',
798
- bufferText: '/mem',
799
- suggestions: [{ label: 'memory', value: 'memory', description: '...' }],
800
- activeIndex: 0,
801
- },
802
- {
803
- name: 'should append a sub-command when parent command is complete',
804
- bufferText: '/memory ',
805
- suggestions: [
806
- { label: 'show', value: 'show' },
807
- { label: 'add', value: 'add' },
808
- ],
809
- activeIndex: 1,
810
- },
811
- {
812
- name: 'should handle the backspace edge case correctly',
813
- bufferText: '/memory',
814
- suggestions: [
815
- { label: 'show', value: 'show' },
816
- { label: 'add', value: 'add' },
817
- ],
818
- activeIndex: 0,
819
- },
820
- {
821
- name: 'should complete a partial argument for a command',
822
- bufferText: '/chat resume fi-',
823
- suggestions: [{ label: 'fix-foo', value: 'fix-foo' }],
824
- activeIndex: 0,
825
- },
826
- ])('$name', async ({ bufferText, suggestions, activeIndex }) => {
827
- mockedUseCommandCompletion.mockReturnValue({
828
- ...mockCommandCompletion,
829
- showSuggestions: true,
830
- suggestions,
831
- activeSuggestionIndex: activeIndex,
832
- });
833
- props.buffer.setText(bufferText);
834
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
835
- uiActions,
836
- });
837
- await act(async () => stdin.write('\t'));
838
- await waitFor(() => expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(activeIndex));
839
- unmount();
840
- });
841
- it('should autocomplete on Enter when suggestions are active, without submitting', async () => {
842
- mockedUseCommandCompletion.mockReturnValue({
843
- ...mockCommandCompletion,
844
- showSuggestions: true,
845
- suggestions: [{ label: 'memory', value: 'memory' }],
846
- activeSuggestionIndex: 0,
847
- });
848
- props.buffer.setText('/mem');
849
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
850
- uiActions,
851
- });
852
- await act(async () => {
853
- stdin.write('\r');
854
- });
855
- await waitFor(() => {
856
- // The app should autocomplete the text, NOT submit.
857
- expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0);
858
- });
859
- expect(props.onSubmit).not.toHaveBeenCalled();
860
- unmount();
861
- });
862
- it('should complete a command based on its altNames', async () => {
863
- props.slashCommands = [
864
- {
865
- name: 'help',
866
- altNames: ['?'],
867
- kind: CommandKind.BUILT_IN,
868
- description: '...',
869
- },
870
- ];
871
- mockedUseCommandCompletion.mockReturnValue({
872
- ...mockCommandCompletion,
873
- showSuggestions: true,
874
- suggestions: [{ label: 'help', value: 'help' }],
875
- activeSuggestionIndex: 0,
876
- });
877
- props.buffer.setText('/?');
878
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
879
- uiActions,
880
- });
881
- await act(async () => {
882
- stdin.write('\t'); // Press Tab for autocomplete
883
- });
884
- await waitFor(() => expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0));
885
- unmount();
886
- });
887
- it('queues a message when Tab is pressed during generation', async () => {
888
- props.buffer.setText('A new prompt');
889
- props.streamingState = StreamingState.Responding;
890
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
891
- uiActions,
892
- });
893
- await act(async () => {
894
- stdin.write('\t');
895
- });
896
- await waitFor(() => {
897
- expect(props.onQueueMessage).toHaveBeenCalledWith('A new prompt');
898
- expect(props.buffer.text).toBe('');
899
- });
900
- unmount();
901
- });
902
- it('shows an error when attempting to queue a slash command', async () => {
903
- props.buffer.setText('/clear');
904
- props.streamingState = StreamingState.Responding;
905
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
906
- uiActions,
907
- });
908
- await act(async () => {
909
- stdin.write('\t');
910
- });
911
- await waitFor(() => {
912
- expect(props.setQueueErrorMessage).toHaveBeenCalledWith('Slash commands cannot be queued');
913
- expect(props.onQueueMessage).not.toHaveBeenCalled();
914
- });
915
- unmount();
916
- });
917
- it('shows an error when attempting to queue a shell command', async () => {
918
- props.shellModeActive = true;
919
- props.buffer.setText('ls');
920
- props.streamingState = StreamingState.Responding;
921
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
922
- uiActions,
923
- });
924
- await act(async () => {
925
- stdin.write('\t');
926
- });
927
- await waitFor(() => {
928
- expect(props.setQueueErrorMessage).toHaveBeenCalledWith('Shell commands cannot be queued');
929
- expect(props.onQueueMessage).not.toHaveBeenCalled();
930
- });
931
- unmount();
932
- });
933
- it('should not submit on Enter when the buffer is empty or only contains whitespace', async () => {
934
- props.buffer.setText(' '); // Set buffer to whitespace
935
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
936
- uiActions,
937
- });
938
- await act(async () => {
939
- stdin.write('\r'); // Press Enter
940
- });
941
- await waitFor(() => {
942
- expect(props.onSubmit).not.toHaveBeenCalled();
943
- });
944
- unmount();
945
- });
946
- it('should submit directly on Enter when isPerfectMatch is true', async () => {
947
- mockedUseCommandCompletion.mockReturnValue({
948
- ...mockCommandCompletion,
949
- showSuggestions: false,
950
- isPerfectMatch: true,
951
- });
952
- props.buffer.setText('/clear');
953
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
954
- uiActions,
955
- });
956
- await act(async () => {
957
- stdin.write('\r');
958
- });
959
- await waitFor(() => expect(props.onSubmit).toHaveBeenCalledWith('/clear'));
960
- unmount();
961
- });
962
- it('should execute perfect match on Enter even if suggestions are showing, if at first suggestion', async () => {
963
- mockedUseCommandCompletion.mockReturnValue({
964
- ...mockCommandCompletion,
965
- showSuggestions: true,
966
- suggestions: [
967
- { label: 'review', value: 'review' }, // Match is now at index 0
968
- { label: 'review-frontend', value: 'review-frontend' },
969
- ],
970
- activeSuggestionIndex: 0,
971
- isPerfectMatch: true,
972
- });
973
- props.buffer.text = '/review';
974
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
975
- uiActions,
976
- });
977
- await act(async () => {
978
- stdin.write('\r');
979
- });
980
- await waitFor(() => {
981
- expect(props.onSubmit).toHaveBeenCalledWith('/review');
982
- });
983
- unmount();
984
- });
985
- it('should autocomplete and NOT execute on Enter if a DIFFERENT suggestion is selected even if perfect match', async () => {
986
- mockedUseCommandCompletion.mockReturnValue({
987
- ...mockCommandCompletion,
988
- showSuggestions: true,
989
- suggestions: [
990
- { label: 'review', value: 'review' },
991
- { label: 'review-frontend', value: 'review-frontend' },
992
- ],
993
- activeSuggestionIndex: 1, // review-frontend selected (not the perfect match at 0)
994
- isPerfectMatch: true, // /review is a perfect match
995
- });
996
- props.buffer.text = '/review';
997
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
998
- uiActions,
999
- });
1000
- await act(async () => {
1001
- stdin.write('\r');
1002
- });
1003
- await waitFor(() => {
1004
- // Should handle autocomplete for index 1
1005
- expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(1);
1006
- // Should NOT submit
1007
- expect(props.onSubmit).not.toHaveBeenCalled();
1008
- });
1009
- unmount();
1010
- });
1011
- it('should submit directly on Enter when a complete leaf command is typed', async () => {
1012
- mockedUseCommandCompletion.mockReturnValue({
1013
- ...mockCommandCompletion,
1014
- showSuggestions: false,
1015
- isPerfectMatch: false, // Added explicit isPerfectMatch false
1016
- });
1017
- props.buffer.setText('/clear');
1018
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
1019
- uiActions,
1020
- });
1021
- await act(async () => {
1022
- stdin.write('\r');
1023
- });
1024
- await waitFor(() => expect(props.onSubmit).toHaveBeenCalledWith('/clear'));
1025
- unmount();
1026
- });
1027
- it('should submit on Enter when an @-path is a perfect match', async () => {
1028
- mockedUseCommandCompletion.mockReturnValue({
1029
- ...mockCommandCompletion,
1030
- showSuggestions: true,
1031
- suggestions: [{ label: 'file.txt', value: 'file.txt' }],
1032
- activeSuggestionIndex: 0,
1033
- isPerfectMatch: true,
1034
- completionMode: CompletionMode.AT,
1035
- });
1036
- props.buffer.text = '@file.txt';
1037
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
1038
- uiActions,
1039
- });
1040
- await act(async () => {
1041
- stdin.write('\r');
1042
- });
1043
- await waitFor(() => {
1044
- // Should submit directly
1045
- expect(props.onSubmit).toHaveBeenCalledWith('@file.txt');
1046
- });
1047
- unmount();
1048
- });
1049
- it('should NOT submit on Shift+Enter even if an @-path is a perfect match', async () => {
1050
- mockedUseCommandCompletion.mockReturnValue({
1051
- ...mockCommandCompletion,
1052
- showSuggestions: true,
1053
- suggestions: [{ label: 'file.txt', value: 'file.txt' }],
1054
- activeSuggestionIndex: 0,
1055
- isPerfectMatch: true,
1056
- completionMode: CompletionMode.AT,
1057
- });
1058
- props.buffer.text = '@file.txt';
1059
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
1060
- uiActions,
1061
- });
1062
- await act(async () => {
1063
- // Simulate Shift+Enter using CSI u sequence
1064
- stdin.write('\x1b[13;2u');
1065
- });
1066
- // Should NOT submit, should call newline instead
1067
- expect(props.onSubmit).not.toHaveBeenCalled();
1068
- expect(props.buffer.newline).toHaveBeenCalled();
1069
- unmount();
1070
- });
1071
- it('should auto-execute commands with autoExecute: true on Enter', async () => {
1072
- const aboutCommand = {
1073
- name: 'about',
1074
- kind: CommandKind.BUILT_IN,
1075
- description: 'About command',
1076
- action: vi.fn(),
1077
- autoExecute: true,
1078
- };
1079
- const suggestion = { label: 'about', value: 'about' };
1080
- mockedUseCommandCompletion.mockReturnValue({
1081
- ...mockCommandCompletion,
1082
- showSuggestions: true,
1083
- suggestions: [suggestion],
1084
- activeSuggestionIndex: 0,
1085
- getCommandFromSuggestion: vi.fn().mockReturnValue(aboutCommand),
1086
- getCompletedText: vi.fn().mockReturnValue('/about'),
1087
- slashCompletionRange: {
1088
- completionStart: 1,
1089
- completionEnd: 3, // "/ab" -> start at 1, end at 3
1090
- getCommandFromSuggestion: vi.fn(),
1091
- isArgumentCompletion: false,
1092
- leafCommand: null,
1093
- },
1094
- });
1095
- // User typed partial command
1096
- props.buffer.setText('/ab');
1097
- props.buffer.lines = ['/ab'];
1098
- props.buffer.cursor = [0, 3];
1099
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
1100
- uiActions,
1101
- });
1102
- await act(async () => {
1103
- stdin.write('\r'); // Enter
1104
- });
1105
- await waitFor(() => {
1106
- // Should submit the full command constructed from buffer + suggestion
1107
- expect(props.onSubmit).toHaveBeenCalledWith('/about');
1108
- // Should NOT handle autocomplete (which just fills text)
1109
- expect(mockCommandCompletion.handleAutocomplete).not.toHaveBeenCalled();
1110
- });
1111
- unmount();
1112
- });
1113
- it('should autocomplete commands with autoExecute: false on Enter', async () => {
1114
- const shareCommand = {
1115
- name: 'share',
1116
- kind: CommandKind.BUILT_IN,
1117
- description: 'Share conversation to file',
1118
- action: vi.fn(),
1119
- autoExecute: false, // Explicitly set to false
1120
- };
1121
- const suggestion = { label: 'share', value: 'share' };
1122
- mockedUseCommandCompletion.mockReturnValue({
1123
- ...mockCommandCompletion,
1124
- showSuggestions: true,
1125
- suggestions: [suggestion],
1126
- activeSuggestionIndex: 0,
1127
- getCommandFromSuggestion: vi.fn().mockReturnValue(shareCommand),
1128
- getCompletedText: vi.fn().mockReturnValue('/share'),
1129
- });
1130
- props.buffer.setText('/sh');
1131
- props.buffer.lines = ['/sh'];
1132
- props.buffer.cursor = [0, 3];
1133
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
1134
- uiActions,
1135
- });
1136
- await act(async () => {
1137
- stdin.write('\r'); // Enter
1138
- });
1139
- await waitFor(() => {
1140
- // Should autocomplete to allow adding file argument
1141
- expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0);
1142
- expect(props.onSubmit).not.toHaveBeenCalled();
1143
- });
1144
- unmount();
1145
- });
1146
- it('should autocomplete on Tab, even for executable commands', async () => {
1147
- const executableCommand = {
1148
- name: 'about',
1149
- kind: CommandKind.BUILT_IN,
1150
- description: 'About info',
1151
- action: vi.fn(),
1152
- autoExecute: true,
1153
- };
1154
- const suggestion = { label: 'about', value: 'about' };
1155
- mockedUseCommandCompletion.mockReturnValue({
1156
- ...mockCommandCompletion,
1157
- showSuggestions: true,
1158
- suggestions: [suggestion],
1159
- activeSuggestionIndex: 0,
1160
- getCommandFromSuggestion: vi.fn().mockReturnValue(executableCommand),
1161
- getCompletedText: vi.fn().mockReturnValue('/about'),
1162
- });
1163
- props.buffer.setText('/ab');
1164
- props.buffer.lines = ['/ab'];
1165
- props.buffer.cursor = [0, 3];
1166
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
1167
- uiActions,
1168
- });
1169
- await act(async () => {
1170
- stdin.write('\t'); // Tab
1171
- });
1172
- await waitFor(() => {
1173
- // Tab always autocompletes, never executes
1174
- expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0);
1175
- expect(props.onSubmit).not.toHaveBeenCalled();
1176
- });
1177
- unmount();
1178
- });
1179
- it('should NOT autocomplete on Shift+Tab', async () => {
1180
- const suggestion = { label: 'about', value: 'about' };
1181
- mockedUseCommandCompletion.mockReturnValue({
1182
- ...mockCommandCompletion,
1183
- showSuggestions: true,
1184
- suggestions: [suggestion],
1185
- activeSuggestionIndex: 0,
1186
- getCompletedText: vi.fn().mockReturnValue('/about'),
1187
- });
1188
- props.buffer.setText('/ab');
1189
- props.buffer.lines = ['/ab'];
1190
- props.buffer.cursor = [0, 3];
1191
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
1192
- uiActions,
1193
- });
1194
- await act(async () => {
1195
- stdin.write('\x1b[Z'); // Shift+Tab
1196
- });
1197
- // We need to wait a bit to ensure handleAutocomplete was NOT called
1198
- await new Promise((resolve) => setTimeout(resolve, 100));
1199
- expect(mockCommandCompletion.handleAutocomplete).not.toHaveBeenCalled();
1200
- unmount();
1201
- });
1202
- it('should autocomplete custom commands from .toml files on Enter', async () => {
1203
- const customCommand = {
1204
- name: 'find-capital',
1205
- kind: CommandKind.USER_FILE,
1206
- description: 'Find capital of a country',
1207
- action: vi.fn(),
1208
- // No autoExecute flag - custom commands default to undefined
1209
- };
1210
- const suggestion = { label: 'find-capital', value: 'find-capital' };
1211
- mockedUseCommandCompletion.mockReturnValue({
1212
- ...mockCommandCompletion,
1213
- showSuggestions: true,
1214
- suggestions: [suggestion],
1215
- activeSuggestionIndex: 0,
1216
- getCommandFromSuggestion: vi.fn().mockReturnValue(customCommand),
1217
- getCompletedText: vi.fn().mockReturnValue('/find-capital'),
1218
- });
1219
- props.buffer.setText('/find');
1220
- props.buffer.lines = ['/find'];
1221
- props.buffer.cursor = [0, 5];
1222
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
1223
- uiActions,
1224
- });
1225
- await act(async () => {
1226
- stdin.write('\r'); // Enter
1227
- });
1228
- await waitFor(() => {
1229
- // Should autocomplete (not execute) since autoExecute is undefined
1230
- expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0);
1231
- expect(props.onSubmit).not.toHaveBeenCalled();
1232
- });
1233
- unmount();
1234
- });
1235
- it('should auto-execute argument completion when command has autoExecute: true', async () => {
1236
- // Simulates: /mcp auth <server> where user selects a server from completions
1237
- const authCommand = {
1238
- name: 'auth',
1239
- kind: CommandKind.BUILT_IN,
1240
- description: 'Authenticate with MCP server',
1241
- action: vi.fn(),
1242
- autoExecute: true,
1243
- completion: vi.fn().mockResolvedValue(['server1', 'server2']),
1244
- };
1245
- const suggestion = { label: 'server1', value: 'server1' };
1246
- mockedUseCommandCompletion.mockReturnValue({
1247
- ...mockCommandCompletion,
1248
- showSuggestions: true,
1249
- suggestions: [suggestion],
1250
- activeSuggestionIndex: 0,
1251
- getCommandFromSuggestion: vi.fn().mockReturnValue(authCommand),
1252
- getCompletedText: vi.fn().mockReturnValue('/mcp auth server1'),
1253
- slashCompletionRange: {
1254
- completionStart: 10,
1255
- completionEnd: 10,
1256
- getCommandFromSuggestion: vi.fn(),
1257
- isArgumentCompletion: true,
1258
- leafCommand: authCommand,
1259
- },
1260
- });
1261
- props.buffer.setText('/mcp auth ');
1262
- props.buffer.lines = ['/mcp auth '];
1263
- props.buffer.cursor = [0, 10];
1264
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
1265
- uiActions,
1266
- });
1267
- await act(async () => {
1268
- stdin.write('\r'); // Enter
1269
- });
1270
- await waitFor(() => {
1271
- // Should auto-execute with the completed command
1272
- expect(props.onSubmit).toHaveBeenCalledWith('/mcp auth server1');
1273
- expect(mockCommandCompletion.handleAutocomplete).not.toHaveBeenCalled();
1274
- });
1275
- unmount();
1276
- });
1277
- it('should autocomplete argument completion when command has autoExecute: false', async () => {
1278
- // Simulates: /extensions enable <ext> where multi-arg completions should NOT auto-execute
1279
- const enableCommand = {
1280
- name: 'enable',
1281
- kind: CommandKind.BUILT_IN,
1282
- description: 'Enable an extension',
1283
- action: vi.fn(),
1284
- autoExecute: false,
1285
- completion: vi.fn().mockResolvedValue(['ext1 --scope user']),
1286
- };
1287
- const suggestion = {
1288
- label: 'ext1 --scope user',
1289
- value: 'ext1 --scope user',
1290
- };
1291
- mockedUseCommandCompletion.mockReturnValue({
1292
- ...mockCommandCompletion,
1293
- showSuggestions: true,
1294
- suggestions: [suggestion],
1295
- activeSuggestionIndex: 0,
1296
- getCommandFromSuggestion: vi.fn().mockReturnValue(enableCommand),
1297
- getCompletedText: vi
1298
- .fn()
1299
- .mockReturnValue('/extensions enable ext1 --scope user'),
1300
- slashCompletionRange: {
1301
- completionStart: 19,
1302
- completionEnd: 19,
1303
- getCommandFromSuggestion: vi.fn(),
1304
- isArgumentCompletion: true,
1305
- leafCommand: enableCommand,
1306
- },
1307
- });
1308
- props.buffer.setText('/extensions enable ');
1309
- props.buffer.lines = ['/extensions enable '];
1310
- props.buffer.cursor = [0, 19];
1311
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
1312
- uiActions,
1313
- });
1314
- await act(async () => {
1315
- stdin.write('\r'); // Enter
1316
- });
1317
- await waitFor(() => {
1318
- // Should autocomplete (not execute) to allow user to modify
1319
- expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0);
1320
- expect(props.onSubmit).not.toHaveBeenCalled();
1321
- });
1322
- unmount();
1323
- });
1324
- it('should autocomplete command name even with autoExecute: true if command has completion function', async () => {
1325
- // Simulates: /chat resu -> should NOT auto-execute, should autocomplete to show arg completions
1326
- const resumeCommand = {
1327
- name: 'resume',
1328
- kind: CommandKind.BUILT_IN,
1329
- description: 'Resume a conversation',
1330
- action: vi.fn(),
1331
- autoExecute: true,
1332
- completion: vi.fn().mockResolvedValue(['chat1', 'chat2']),
1333
- };
1334
- const suggestion = { label: 'resume', value: 'resume' };
1335
- mockedUseCommandCompletion.mockReturnValue({
1336
- ...mockCommandCompletion,
1337
- showSuggestions: true,
1338
- suggestions: [suggestion],
1339
- activeSuggestionIndex: 0,
1340
- getCommandFromSuggestion: vi.fn().mockReturnValue(resumeCommand),
1341
- getCompletedText: vi.fn().mockReturnValue('/chat resume'),
1342
- slashCompletionRange: {
1343
- completionStart: 6,
1344
- completionEnd: 10,
1345
- getCommandFromSuggestion: vi.fn(),
1346
- isArgumentCompletion: false,
1347
- leafCommand: null,
1348
- },
1349
- });
1350
- props.buffer.setText('/chat resu');
1351
- props.buffer.lines = ['/chat resu'];
1352
- props.buffer.cursor = [0, 10];
1353
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
1354
- uiActions,
1355
- });
1356
- await act(async () => {
1357
- stdin.write('\r'); // Enter
1358
- });
1359
- await waitFor(() => {
1360
- // Should autocomplete to allow selecting an argument, NOT auto-execute
1361
- expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0);
1362
- expect(props.onSubmit).not.toHaveBeenCalled();
1363
- });
1364
- unmount();
1365
- });
1366
- it('should autocomplete an @-path on Enter without submitting', async () => {
1367
- mockedUseCommandCompletion.mockReturnValue({
1368
- ...mockCommandCompletion,
1369
- showSuggestions: true,
1370
- suggestions: [{ label: 'index.ts', value: 'index.ts' }],
1371
- activeSuggestionIndex: 0,
1372
- });
1373
- props.buffer.setText('@src/components/');
1374
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
1375
- uiActions,
1376
- });
1377
- await act(async () => {
1378
- stdin.write('\r');
1379
- });
1380
- await waitFor(() => expect(mockCommandCompletion.handleAutocomplete).toHaveBeenCalledWith(0));
1381
- expect(props.onSubmit).not.toHaveBeenCalled();
1382
- unmount();
1383
- });
1384
- it('should add a newline on enter when the line ends with a backslash', async () => {
1385
- // This test simulates multi-line input, not submission
1386
- mockBuffer.text = 'first line\\';
1387
- mockBuffer.cursor = [0, 11];
1388
- mockBuffer.lines = ['first line\\'];
1389
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
1390
- uiActions,
1391
- });
1392
- await act(async () => {
1393
- stdin.write('\r');
1394
- });
1395
- await waitFor(() => {
1396
- expect(props.buffer.backspace).toHaveBeenCalled();
1397
- expect(props.buffer.newline).toHaveBeenCalled();
1398
- });
1399
- expect(props.onSubmit).not.toHaveBeenCalled();
1400
- unmount();
1401
- });
1402
- it('should clear the buffer on Ctrl+C if it has text', async () => {
1403
- await act(async () => {
1404
- props.buffer.setText('some text to clear');
1405
- });
1406
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
1407
- uiActions,
1408
- });
1409
- await act(async () => {
1410
- stdin.write('\x03'); // Ctrl+C character
1411
- });
1412
- await waitFor(() => {
1413
- expect(props.buffer.setText).toHaveBeenCalledWith('');
1414
- expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
1415
- });
1416
- expect(props.onSubmit).not.toHaveBeenCalled();
1417
- unmount();
1418
- });
1419
- it('should render correctly in plan mode', async () => {
1420
- props.approvalMode = ApprovalMode.PLAN;
1421
- const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
1422
- await waitFor(() => {
1423
- const frame = stdout.lastFrameRaw();
1424
- // In plan mode it uses '>' but with success color.
1425
- // We check that it contains '>' and not '*' or '!'.
1426
- expect(frame).toContain('>');
1427
- expect(frame).not.toContain('*');
1428
- expect(frame).not.toContain('!');
1429
- });
1430
- unmount();
1431
- });
1432
- it('should NOT clear the buffer on Ctrl+C if it is empty', async () => {
1433
- props.buffer.text = '';
1434
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
1435
- uiActions,
1436
- });
1437
- await act(async () => {
1438
- stdin.write('\x03'); // Ctrl+C character
1439
- });
1440
- await waitFor(() => {
1441
- expect(props.buffer.setText).not.toHaveBeenCalled();
1442
- });
1443
- unmount();
1444
- });
1445
- it('should call setBannerVisible(false) when clear screen key is pressed', async () => {
1446
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
1447
- uiActions,
1448
- });
1449
- await act(async () => {
1450
- stdin.write('\x0C'); // Ctrl+L
1451
- });
1452
- await waitFor(() => {
1453
- expect(props.setBannerVisible).toHaveBeenCalledWith(false);
1454
- });
1455
- unmount();
1456
- });
1457
- describe('cursor-based completion trigger', () => {
1458
- it.each([
1459
- {
1460
- name: 'should trigger completion when cursor is after @ without spaces',
1461
- text: '@src/components',
1462
- cursor: [0, 15],
1463
- showSuggestions: true,
1464
- },
1465
- {
1466
- name: 'should trigger completion when cursor is after / without spaces',
1467
- text: '/memory',
1468
- cursor: [0, 7],
1469
- showSuggestions: true,
1470
- },
1471
- {
1472
- name: 'should NOT trigger completion when cursor is after space following @',
1473
- text: '@src/file.ts hello',
1474
- cursor: [0, 18],
1475
- showSuggestions: false,
1476
- },
1477
- {
1478
- name: 'should NOT trigger completion when cursor is after space following /',
1479
- text: '/memory list',
1480
- cursor: [0, 12],
1481
- showSuggestions: false,
1482
- },
1483
- {
1484
- name: 'should NOT trigger completion when cursor is not after @ or /',
1485
- text: 'hello world',
1486
- cursor: [0, 5],
1487
- showSuggestions: false,
1488
- },
1489
- {
1490
- name: 'should handle multiline text correctly',
1491
- text: 'first line\n/memory',
1492
- cursor: [1, 7],
1493
- showSuggestions: false,
1494
- },
1495
- {
1496
- name: 'should handle Unicode characters (emojis) correctly in paths',
1497
- text: '@src/file👍.txt',
1498
- cursor: [0, 14],
1499
- showSuggestions: true,
1500
- },
1501
- {
1502
- name: 'should handle Unicode characters with spaces after them',
1503
- text: '@src/file👍.txt hello',
1504
- cursor: [0, 20],
1505
- showSuggestions: false,
1506
- },
1507
- {
1508
- name: 'should handle escaped spaces in paths correctly',
1509
- text: '@src/my\\ file.txt',
1510
- cursor: [0, 16],
1511
- showSuggestions: true,
1512
- },
1513
- {
1514
- name: 'should NOT trigger completion after unescaped space following escaped space',
1515
- text: '@path/my\\ file.txt hello',
1516
- cursor: [0, 24],
1517
- showSuggestions: false,
1518
- },
1519
- {
1520
- name: 'should handle multiple escaped spaces in paths',
1521
- text: '@docs/my\\ long\\ file\\ name.md',
1522
- cursor: [0, 29],
1523
- showSuggestions: true,
1524
- },
1525
- {
1526
- name: 'should handle escaped spaces in slash commands',
1527
- text: '/memory\\ test',
1528
- cursor: [0, 13],
1529
- showSuggestions: true,
1530
- },
1531
- {
1532
- name: 'should handle Unicode characters with escaped spaces',
1533
- text: `@${path.join('files', 'emoji\\ 👍\\ test.txt')}`,
1534
- cursor: [0, 25],
1535
- showSuggestions: true,
1536
- },
1537
- ])('$name', async ({ text, cursor, showSuggestions }) => {
1538
- mockBuffer.text = text;
1539
- mockBuffer.lines = text.split('\n');
1540
- mockBuffer.cursor = cursor;
1541
- mockedUseCommandCompletion.mockReturnValue({
1542
- ...mockCommandCompletion,
1543
- showSuggestions,
1544
- suggestions: showSuggestions
1545
- ? [{ label: 'suggestion', value: 'suggestion' }]
1546
- : [],
1547
- });
1548
- const { unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
1549
- uiActions,
1550
- });
1551
- await waitFor(() => {
1552
- expect(mockedUseCommandCompletion).toHaveBeenCalledWith({
1553
- buffer: mockBuffer,
1554
- cwd: path.join('test', 'project', 'src'),
1555
- slashCommands: mockSlashCommands,
1556
- commandContext: mockCommandContext,
1557
- reverseSearchActive: false,
1558
- shellModeActive: false,
1559
- config: expect.any(Object),
1560
- active: expect.anything(),
1561
- });
1562
- });
1563
- unmount();
1564
- });
1565
- });
1566
- describe('vim mode', () => {
1567
- it.each([
1568
- {
1569
- name: 'should not call buffer.handleInput when vim handles input',
1570
- vimHandled: true,
1571
- expectBufferHandleInput: false,
1572
- },
1573
- {
1574
- name: 'should call buffer.handleInput when vim does not handle input',
1575
- vimHandled: false,
1576
- expectBufferHandleInput: true,
1577
- },
1578
- {
1579
- name: 'should call handleInput when vim mode is disabled',
1580
- vimHandled: false,
1581
- expectBufferHandleInput: true,
1582
- },
1583
- ])('$name', async ({ vimHandled, expectBufferHandleInput }) => {
1584
- props.vimHandleInput = vi.fn().mockReturnValue(vimHandled);
1585
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
1586
- await act(async () => stdin.write('i'));
1587
- await waitFor(() => {
1588
- expect(props.vimHandleInput).toHaveBeenCalled();
1589
- if (expectBufferHandleInput) {
1590
- expect(mockBuffer.handleInput).toHaveBeenCalled();
1591
- }
1592
- else {
1593
- expect(mockBuffer.handleInput).not.toHaveBeenCalled();
1594
- }
1595
- });
1596
- unmount();
1597
- });
1598
- });
1599
- describe('unfocused paste', () => {
1600
- it('should handle bracketed paste when not focused', async () => {
1601
- props.focus = false;
1602
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
1603
- await act(async () => {
1604
- stdin.write('\x1B[200~pasted text\x1B[201~');
1605
- });
1606
- await waitFor(() => {
1607
- expect(mockBuffer.handleInput).toHaveBeenCalledWith(expect.objectContaining({
1608
- name: 'paste',
1609
- sequence: 'pasted text',
1610
- }));
1611
- });
1612
- unmount();
1613
- });
1614
- it('should ignore regular keypresses when not focused', async () => {
1615
- props.focus = false;
1616
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
1617
- await act(async () => {
1618
- stdin.write('a');
1619
- });
1620
- await waitFor(() => { });
1621
- expect(mockBuffer.handleInput).not.toHaveBeenCalled();
1622
- unmount();
1623
- });
1624
- });
1625
- describe('Highlighting and Cursor Display', () => {
1626
- describe('single-line scenarios', () => {
1627
- it.each([
1628
- {
1629
- name: 'mid-word',
1630
- text: 'hello world',
1631
- visualCursor: [0, 3],
1632
- },
1633
- {
1634
- name: 'at the beginning of the line',
1635
- text: 'hello',
1636
- visualCursor: [0, 0],
1637
- },
1638
- {
1639
- name: 'at the end of the line',
1640
- text: 'hello',
1641
- visualCursor: [0, 5],
1642
- },
1643
- {
1644
- name: 'on a highlighted token',
1645
- text: 'run @path/to/file',
1646
- visualCursor: [0, 9],
1647
- },
1648
- {
1649
- name: 'for multi-byte unicode characters',
1650
- text: 'hello 👍 world',
1651
- visualCursor: [0, 6],
1652
- },
1653
- {
1654
- name: 'after multi-byte unicode characters',
1655
- text: '👍A',
1656
- visualCursor: [0, 1],
1657
- },
1658
- {
1659
- name: 'at the end of a line with unicode characters',
1660
- text: 'hello 👍',
1661
- visualCursor: [0, 8],
1662
- },
1663
- {
1664
- name: 'at the end of a short line with unicode characters',
1665
- text: '👍',
1666
- visualCursor: [0, 1],
1667
- },
1668
- {
1669
- name: 'on an empty line',
1670
- text: '',
1671
- visualCursor: [0, 0],
1672
- },
1673
- {
1674
- name: 'on a space between words',
1675
- text: 'hello world',
1676
- visualCursor: [0, 5],
1677
- },
1678
- ])('should display cursor correctly $name', async ({ text, visualCursor }) => {
1679
- mockBuffer.text = text;
1680
- mockBuffer.lines = [text];
1681
- mockBuffer.allVisualLines = [text];
1682
- mockBuffer.viewportVisualLines = [text];
1683
- mockBuffer.visualCursor = visualCursor;
1684
- props.config.getUseBackgroundColor = () => false;
1685
- const renderResult = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
1686
- await renderResult.waitUntilReady();
1687
- await expect(renderResult).toMatchSvgSnapshot();
1688
- renderResult.unmount();
1689
- });
1690
- });
1691
- describe('multi-line scenarios', () => {
1692
- it.each([
1693
- {
1694
- name: 'in the middle of a line',
1695
- text: 'first line\nsecond line\nthird line',
1696
- visualCursor: [1, 3],
1697
- visualToLogicalMap: [
1698
- [0, 0],
1699
- [1, 0],
1700
- [2, 0],
1701
- ],
1702
- },
1703
- {
1704
- name: 'at the beginning of a line',
1705
- text: 'first line\nsecond line',
1706
- visualCursor: [1, 0],
1707
- visualToLogicalMap: [
1708
- [0, 0],
1709
- [1, 0],
1710
- ],
1711
- },
1712
- {
1713
- name: 'at the end of a line',
1714
- text: 'first line\nsecond line',
1715
- visualCursor: [0, 10],
1716
- visualToLogicalMap: [
1717
- [0, 0],
1718
- [1, 0],
1719
- ],
1720
- },
1721
- ])('should display cursor correctly $name in a multiline block', async ({ text, visualCursor, visualToLogicalMap }) => {
1722
- mockBuffer.text = text;
1723
- mockBuffer.lines = text.split('\n');
1724
- mockBuffer.allVisualLines = text.split('\n');
1725
- mockBuffer.viewportVisualLines = text.split('\n');
1726
- mockBuffer.visualCursor = visualCursor;
1727
- mockBuffer.visualToLogicalMap = visualToLogicalMap;
1728
- props.config.getUseBackgroundColor = () => false;
1729
- const renderResult = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
1730
- await renderResult.waitUntilReady();
1731
- await expect(renderResult).toMatchSvgSnapshot();
1732
- renderResult.unmount();
1733
- });
1734
- it('should display cursor on a blank line in a multiline block', async () => {
1735
- const text = 'first line\n\nthird line';
1736
- mockBuffer.text = text;
1737
- mockBuffer.lines = text.split('\n');
1738
- mockBuffer.allVisualLines = text.split('\n');
1739
- mockBuffer.viewportVisualLines = text.split('\n');
1740
- mockBuffer.visualCursor = [1, 0]; // cursor on the blank line
1741
- mockBuffer.visualToLogicalMap = [
1742
- [0, 0],
1743
- [1, 0],
1744
- [2, 0],
1745
- ];
1746
- props.config.getUseBackgroundColor = () => false;
1747
- const renderResult = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
1748
- await renderResult.waitUntilReady();
1749
- await expect(renderResult).toMatchSvgSnapshot();
1750
- renderResult.unmount();
1751
- });
1752
- });
1753
- });
1754
- describe('scrolling large inputs', () => {
1755
- it('should correctly render scrolling down and up for large inputs', async () => {
1756
- const lines = Array.from({ length: 50 }).map((_, i) => `testline ${i}`);
1757
- // Since we need to test how the React component tree responds to TextBuffer state changes,
1758
- // we must provide a fake TextBuffer implementation that triggers re-renders like the real one.
1759
- const TestWrapper = () => {
1760
- const [bufferState, setBufferState] = useState({
1761
- text: lines.join('\n'),
1762
- lines,
1763
- allVisualLines: lines,
1764
- viewportVisualLines: lines.slice(0, 10),
1765
- visualToLogicalMap: lines.map((_, i) => [i, 0]),
1766
- visualCursor: [0, 0],
1767
- visualScrollRow: 0,
1768
- viewportHeight: 10,
1769
- });
1770
- const fakeBuffer = {
1771
- ...mockBuffer,
1772
- ...bufferState,
1773
- handleInput: vi.fn().mockImplementation((key) => {
1774
- let newRow = bufferState.visualCursor[0];
1775
- let newScroll = bufferState.visualScrollRow;
1776
- if (key.name === 'down') {
1777
- newRow = Math.min(49, newRow + 1);
1778
- if (newRow >= newScroll + 10)
1779
- newScroll++;
1780
- }
1781
- else if (key.name === 'up') {
1782
- newRow = Math.max(0, newRow - 1);
1783
- if (newRow < newScroll)
1784
- newScroll--;
1785
- }
1786
- setBufferState({
1787
- ...bufferState,
1788
- visualCursor: [newRow, 0],
1789
- visualScrollRow: newScroll,
1790
- viewportVisualLines: lines.slice(newScroll, newScroll + 10),
1791
- });
1792
- return true;
1793
- }),
1794
- };
1795
- const inputState = {
1796
- buffer: fakeBuffer,
1797
- userMessages: [],
1798
- shellModeActive: false,
1799
- showEscapePrompt: false,
1800
- copyModeEnabled: false,
1801
- inputWidth: 80,
1802
- suggestionsWidth: 80,
1803
- };
1804
- return (_jsx(InputContext.Provider, { value: inputState, children: _jsx(InputPrompt, { ...props }) }));
1805
- };
1806
- const { stdout, unmount, stdin } = await renderWithProviders(_jsx(TestWrapper, {}), {
1807
- uiActions,
1808
- });
1809
- // Verify initial render
1810
- await waitFor(() => {
1811
- expect(stdout.lastFrame()).toContain('testline 0');
1812
- expect(stdout.lastFrame()).not.toContain('testline 49');
1813
- });
1814
- // Move cursor to bottom
1815
- for (let i = 0; i < 49; i++) {
1816
- act(() => {
1817
- stdin.write('\x1b[B'); // Arrow Down
1818
- });
1819
- }
1820
- await waitFor(() => {
1821
- expect(stdout.lastFrame()).toContain('testline 49');
1822
- expect(stdout.lastFrame()).not.toContain('testline 0');
1823
- });
1824
- // Move cursor back to top
1825
- for (let i = 0; i < 49; i++) {
1826
- act(() => {
1827
- stdin.write('\x1b[A'); // Arrow Up
1828
- });
1829
- }
1830
- await waitFor(() => {
1831
- expect(stdout.lastFrame()).toContain('testline 0');
1832
- expect(stdout.lastFrame()).not.toContain('testline 49');
1833
- });
1834
- unmount();
1835
- });
1836
- });
1837
- describe('multiline rendering', () => {
1838
- it('should correctly render multiline input including blank lines', async () => {
1839
- const text = 'hello\n\nworld';
1840
- mockBuffer.text = text;
1841
- mockBuffer.lines = text.split('\n');
1842
- mockBuffer.allVisualLines = text.split('\n');
1843
- mockBuffer.viewportVisualLines = text.split('\n');
1844
- mockBuffer.allVisualLines = text.split('\n');
1845
- mockBuffer.visualCursor = [2, 5]; // cursor at the end of "world"
1846
- // Provide a visual-to-logical mapping for each visual line
1847
- mockBuffer.visualToLogicalMap = [
1848
- [0, 0],
1849
- [1, 0],
1850
- [2, 0],
1851
- ];
1852
- props.config.getUseBackgroundColor = () => false;
1853
- const renderResult = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
1854
- await renderResult.waitUntilReady();
1855
- await expect(renderResult).toMatchSvgSnapshot();
1856
- renderResult.unmount();
1857
- });
1858
- });
1859
- describe('multiline paste', () => {
1860
- it.each([
1861
- {
1862
- description: 'with \n newlines',
1863
- pastedText: 'This \n is \n a \n multiline \n paste.',
1864
- },
1865
- {
1866
- description: 'with extra slashes before \n newlines',
1867
- pastedText: 'This \\\n is \\\n a \\\n multiline \\\n paste.',
1868
- },
1869
- {
1870
- description: 'with \r\n newlines',
1871
- pastedText: 'This\r\nis\r\na\r\nmultiline\r\npaste.',
1872
- },
1873
- ])('should handle multiline paste $description', async ({ pastedText }) => {
1874
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
1875
- // Simulate a bracketed paste event from the terminal
1876
- await act(async () => {
1877
- stdin.write(`\x1b[200~${pastedText}\x1b[201~`);
1878
- });
1879
- await waitFor(() => {
1880
- // Verify that the buffer's handleInput was called once with the full text
1881
- expect(props.buffer.handleInput).toHaveBeenCalledTimes(1);
1882
- expect(props.buffer.handleInput).toHaveBeenCalledWith(expect.objectContaining({
1883
- name: 'paste',
1884
- sequence: pastedText,
1885
- }));
1886
- });
1887
- unmount();
1888
- });
1889
- });
1890
- describe('large paste placeholder', () => {
1891
- it('should handle large clipboard paste (lines > 5) by calling buffer.insert', async () => {
1892
- vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);
1893
- const largeText = '1\n2\n3\n4\n5\n6';
1894
- vi.mocked(clipboardy.read).mockResolvedValue(largeText);
1895
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
1896
- await act(async () => {
1897
- stdin.write('\x16'); // Ctrl+V
1898
- });
1899
- await waitFor(() => {
1900
- expect(mockBuffer.insert).toHaveBeenCalledWith(largeText, expect.objectContaining({ paste: true }));
1901
- });
1902
- unmount();
1903
- });
1904
- it('should handle large clipboard paste (chars > 500) by calling buffer.insert', async () => {
1905
- vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);
1906
- const largeText = 'a'.repeat(501);
1907
- vi.mocked(clipboardy.read).mockResolvedValue(largeText);
1908
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
1909
- await act(async () => {
1910
- stdin.write('\x16'); // Ctrl+V
1911
- });
1912
- await waitFor(() => {
1913
- expect(mockBuffer.insert).toHaveBeenCalledWith(largeText, expect.objectContaining({ paste: true }));
1914
- });
1915
- unmount();
1916
- });
1917
- it('should handle normal clipboard paste by calling buffer.insert', async () => {
1918
- vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);
1919
- const smallText = 'hello world';
1920
- vi.mocked(clipboardy.read).mockResolvedValue(smallText);
1921
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
1922
- await act(async () => {
1923
- stdin.write('\x16'); // Ctrl+V
1924
- });
1925
- await waitFor(() => {
1926
- expect(mockBuffer.insert).toHaveBeenCalledWith(smallText, expect.objectContaining({ paste: true }));
1927
- });
1928
- unmount();
1929
- });
1930
- it('should replace placeholder with actual content on submit', async () => {
1931
- // Setup buffer to have the placeholder
1932
- const largeText = '1\n2\n3\n4\n5\n6';
1933
- const id = '[Pasted Text: 6 lines]';
1934
- mockBuffer.text = `Check this: ${id}`;
1935
- mockBuffer.pastedContent = { [id]: largeText };
1936
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
1937
- await act(async () => {
1938
- stdin.write('\r'); // Enter
1939
- });
1940
- await waitFor(() => {
1941
- expect(props.onSubmit).toHaveBeenCalledWith(`Check this: ${largeText}`);
1942
- });
1943
- unmount();
1944
- });
1945
- });
1946
- describe('paste auto-submission protection', () => {
1947
- beforeEach(() => {
1948
- vi.useFakeTimers();
1949
- mockedUseKittyKeyboardProtocol.mockReturnValue({
1950
- enabled: false,
1951
- checking: false,
1952
- });
1953
- });
1954
- afterEach(() => {
1955
- vi.useRealTimers();
1956
- vi.restoreAllMocks();
1957
- });
1958
- it('should prevent auto-submission immediately after an unsafe paste', async () => {
1959
- // isTerminalPasteTrusted will be false due to beforeEach setup.
1960
- props.buffer.text = 'some command';
1961
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
1962
- await act(async () => {
1963
- await vi.runAllTimersAsync();
1964
- });
1965
- // Simulate a paste operation (this should set the paste protection)
1966
- await act(async () => {
1967
- stdin.write(`\x1b[200~pasted content\x1b[201~`);
1968
- });
1969
- // Simulate an Enter key press immediately after paste
1970
- await act(async () => {
1971
- stdin.write('\r');
1972
- });
1973
- await act(async () => {
1974
- await vi.runAllTimersAsync();
1975
- });
1976
- // Verify that onSubmit was NOT called due to recent paste protection
1977
- expect(props.onSubmit).not.toHaveBeenCalled();
1978
- // It should call newline() instead
1979
- expect(props.buffer.newline).toHaveBeenCalled();
1980
- unmount();
1981
- });
1982
- it('should prevent perfect match auto-submission immediately after an unsafe paste', async () => {
1983
- // isTerminalPasteTrusted will be false due to beforeEach setup.
1984
- mockedUseCommandCompletion.mockReturnValue({
1985
- ...mockCommandCompletion,
1986
- isPerfectMatch: true,
1987
- completionMode: CompletionMode.AT,
1988
- });
1989
- props.buffer.text = '@file.txt';
1990
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
1991
- // Simulate an unsafe paste of a perfect match
1992
- await act(async () => {
1993
- stdin.write(`\x1b[200~@file.txt\x1b[201~`);
1994
- });
1995
- // Simulate an Enter key press immediately after paste
1996
- await act(async () => {
1997
- stdin.write('\r');
1998
- });
1999
- // Verify that onSubmit was NOT called due to recent paste protection
2000
- expect(props.onSubmit).not.toHaveBeenCalled();
2001
- // It should call newline() instead
2002
- expect(props.buffer.newline).toHaveBeenCalled();
2003
- unmount();
2004
- });
2005
- it('should allow submission after unsafe paste protection timeout', async () => {
2006
- // isTerminalPasteTrusted will be false due to beforeEach setup.
2007
- props.buffer.text = 'pasted text';
2008
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2009
- await act(async () => {
2010
- await vi.runAllTimersAsync();
2011
- });
2012
- // Simulate a paste operation (this sets the protection)
2013
- await act(async () => {
2014
- stdin.write('\x1b[200~pasted text\x1b[201~');
2015
- });
2016
- await act(async () => {
2017
- await vi.runAllTimersAsync();
2018
- });
2019
- // Advance timers past the protection timeout
2020
- await act(async () => {
2021
- await vi.advanceTimersByTimeAsync(50);
2022
- });
2023
- // Now Enter should work normally
2024
- await act(async () => {
2025
- stdin.write('\r');
2026
- });
2027
- await act(async () => {
2028
- await vi.runAllTimersAsync();
2029
- });
2030
- expect(props.onSubmit).toHaveBeenCalledWith('pasted text');
2031
- expect(props.buffer.newline).not.toHaveBeenCalled();
2032
- unmount();
2033
- });
2034
- it.each([
2035
- {
2036
- name: 'kitty',
2037
- setup: () => mockedUseKittyKeyboardProtocol.mockReturnValue({
2038
- enabled: true,
2039
- checking: false,
2040
- }),
2041
- },
2042
- ])('should allow immediate submission for a trusted paste ($name)', async ({ setup }) => {
2043
- setup();
2044
- props.buffer.text = 'pasted command';
2045
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2046
- await act(async () => {
2047
- await vi.runAllTimersAsync();
2048
- });
2049
- // Simulate a paste operation
2050
- await act(async () => {
2051
- stdin.write('\x1b[200~some pasted stuff\x1b[201~');
2052
- });
2053
- await act(async () => {
2054
- await vi.runAllTimersAsync();
2055
- });
2056
- // Simulate an Enter key press immediately after paste
2057
- await act(async () => {
2058
- stdin.write('\r');
2059
- });
2060
- await act(async () => {
2061
- await vi.runAllTimersAsync();
2062
- });
2063
- // Verify that onSubmit was called
2064
- expect(props.onSubmit).toHaveBeenCalledWith('pasted command');
2065
- unmount();
2066
- });
2067
- it('should not interfere with normal Enter key submission when no recent paste', async () => {
2068
- // Set up buffer with text before rendering to ensure submission works
2069
- props.buffer.text = 'normal command';
2070
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2071
- await act(async () => {
2072
- await vi.runAllTimersAsync();
2073
- });
2074
- // Press Enter without any recent paste
2075
- await act(async () => {
2076
- stdin.write('\r');
2077
- });
2078
- await act(async () => {
2079
- await vi.runAllTimersAsync();
2080
- });
2081
- // Verify that onSubmit was called normally
2082
- expect(props.onSubmit).toHaveBeenCalledWith('normal command');
2083
- unmount();
2084
- });
2085
- });
2086
- describe('enhanced input UX - keyboard shortcuts', () => {
2087
- beforeEach(() => vi.useFakeTimers());
2088
- afterEach(() => vi.useRealTimers());
2089
- it('should clear buffer on Ctrl-C', async () => {
2090
- const onEscapePromptChange = vi.fn();
2091
- props.onEscapePromptChange = onEscapePromptChange;
2092
- props.buffer.setText('text to clear');
2093
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2094
- await act(async () => {
2095
- stdin.write('\x03');
2096
- vi.advanceTimersByTime(100);
2097
- expect(props.buffer.setText).toHaveBeenCalledWith('');
2098
- expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
2099
- });
2100
- unmount();
2101
- });
2102
- it('should submit /rewind on double ESC when buffer is empty', async () => {
2103
- const onEscapePromptChange = vi.fn();
2104
- props.onEscapePromptChange = onEscapePromptChange;
2105
- props.buffer.setText('');
2106
- vi.mocked(props.buffer.setText).mockClear();
2107
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
2108
- uiState: {
2109
- history: [{ id: 1, type: 'user', text: 'test' }],
2110
- },
2111
- });
2112
- await act(async () => {
2113
- stdin.write('\x1B\x1B');
2114
- vi.advanceTimersByTime(100);
2115
- });
2116
- await waitFor(() => {
2117
- expect(props.onSubmit).toHaveBeenCalledWith('/rewind');
2118
- });
2119
- unmount();
2120
- });
2121
- it('should clear the buffer on esc esc if it has text', async () => {
2122
- const onEscapePromptChange = vi.fn();
2123
- props.onEscapePromptChange = onEscapePromptChange;
2124
- props.buffer.setText('some text');
2125
- vi.mocked(props.buffer.setText).mockClear();
2126
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2127
- await act(async () => {
2128
- stdin.write('\x1B\x1B');
2129
- vi.advanceTimersByTime(100);
2130
- expect(props.buffer.setText).toHaveBeenCalledWith('');
2131
- expect(props.onSubmit).not.toHaveBeenCalledWith('/rewind');
2132
- });
2133
- unmount();
2134
- });
2135
- it('should reset escape state on any non-ESC key', async () => {
2136
- const onEscapePromptChange = vi.fn();
2137
- props.onEscapePromptChange = onEscapePromptChange;
2138
- props.buffer.setText('some text');
2139
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2140
- await act(async () => {
2141
- stdin.write('\x1B');
2142
- await waitFor(() => {
2143
- expect(onEscapePromptChange).toHaveBeenCalledWith(false);
2144
- });
2145
- });
2146
- await act(async () => {
2147
- stdin.write('a');
2148
- await waitFor(() => {
2149
- expect(onEscapePromptChange).toHaveBeenCalledWith(false);
2150
- });
2151
- });
2152
- unmount();
2153
- });
2154
- it('should handle ESC in shell mode by disabling shell mode', async () => {
2155
- props.shellModeActive = true;
2156
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2157
- await act(async () => {
2158
- stdin.write('\x1B');
2159
- vi.advanceTimersByTime(100);
2160
- expect(props.setShellModeActive).toHaveBeenCalledWith(false);
2161
- });
2162
- unmount();
2163
- });
2164
- it('should not propagate ESC to global cancellation handler when shell mode is active (responding)', async () => {
2165
- props.shellModeActive = true;
2166
- props.streamingState = StreamingState.Responding;
2167
- const onGlobalEscape = vi.fn();
2168
- const { stdin, unmount } = await renderWithProviders(_jsxs(_Fragment, { children: [_jsx(GlobalEscapeHandler, { onEscape: onGlobalEscape }), _jsx(TestInputPrompt, { ...props })] }));
2169
- await act(async () => {
2170
- stdin.write('\x1B');
2171
- vi.advanceTimersByTime(100);
2172
- });
2173
- await waitFor(() => {
2174
- expect(props.setShellModeActive).toHaveBeenCalledWith(false);
2175
- });
2176
- expect(onGlobalEscape).not.toHaveBeenCalled();
2177
- unmount();
2178
- });
2179
- it('should allow ESC to reach global cancellation handler when responding and no overlay is active', async () => {
2180
- props.shellModeActive = false;
2181
- props.streamingState = StreamingState.Responding;
2182
- const onGlobalEscape = vi.fn();
2183
- const { stdin, unmount } = await renderWithProviders(_jsxs(_Fragment, { children: [_jsx(GlobalEscapeHandler, { onEscape: onGlobalEscape }), _jsx(TestInputPrompt, { ...props })] }));
2184
- await act(async () => {
2185
- stdin.write('\x1B');
2186
- vi.advanceTimersByTime(100);
2187
- });
2188
- await waitFor(() => {
2189
- expect(onGlobalEscape).toHaveBeenCalledTimes(1);
2190
- });
2191
- expect(props.setShellModeActive).not.toHaveBeenCalled();
2192
- unmount();
2193
- });
2194
- it('should handle ESC when completion suggestions are showing', async () => {
2195
- mockedUseCommandCompletion.mockReturnValue({
2196
- ...mockCommandCompletion,
2197
- showSuggestions: true,
2198
- suggestions: [{ label: 'suggestion', value: 'suggestion' }],
2199
- });
2200
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2201
- await act(async () => {
2202
- stdin.write('\x1B');
2203
- vi.advanceTimersByTime(100);
2204
- expect(mockCommandCompletion.resetCompletionState).toHaveBeenCalled();
2205
- });
2206
- unmount();
2207
- });
2208
- it('should not call onEscapePromptChange when not provided', async () => {
2209
- props.onEscapePromptChange = undefined;
2210
- props.buffer.setText('some text');
2211
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2212
- await act(async () => {
2213
- await vi.runAllTimersAsync();
2214
- });
2215
- await act(async () => {
2216
- stdin.write('\x1B');
2217
- });
2218
- await act(async () => {
2219
- await vi.runAllTimersAsync();
2220
- });
2221
- unmount();
2222
- });
2223
- it('should not interfere with existing keyboard shortcuts', async () => {
2224
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2225
- await act(async () => {
2226
- stdin.write('\x0C');
2227
- });
2228
- await waitFor(() => expect(props.onClearScreen).toHaveBeenCalled());
2229
- await act(async () => {
2230
- stdin.write('\x01');
2231
- });
2232
- await waitFor(() => expect(props.buffer.move).toHaveBeenCalledWith('home'));
2233
- unmount();
2234
- });
2235
- });
2236
- describe('reverse search', () => {
2237
- beforeEach(async () => {
2238
- props.shellModeActive = true;
2239
- vi.mocked(useShellHistory).mockReturnValue({
2240
- history: ['echo hello', 'echo world', 'ls'],
2241
- getPreviousCommand: vi.fn(),
2242
- getNextCommand: vi.fn(),
2243
- addCommandToHistory: vi.fn(),
2244
- resetHistoryPosition: vi.fn(),
2245
- });
2246
- });
2247
- it('invokes reverse search on Ctrl+R', async () => {
2248
- // Mock the reverse search completion to return suggestions
2249
- mockedUseReverseSearchCompletion.mockReturnValue({
2250
- ...mockReverseSearchCompletion,
2251
- suggestions: [
2252
- { label: 'echo hello', value: 'echo hello' },
2253
- { label: 'echo world', value: 'echo world' },
2254
- { label: 'ls', value: 'ls' },
2255
- ],
2256
- showSuggestions: true,
2257
- activeSuggestionIndex: 0,
2258
- });
2259
- const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2260
- // Trigger reverse search with Ctrl+R
2261
- await act(async () => {
2262
- stdin.write('\x12');
2263
- });
2264
- await waitFor(() => {
2265
- const frame = stdout.lastFrameRaw();
2266
- expect(frame).toContain('(r:)');
2267
- expect(frame).toContain('echo hello');
2268
- expect(frame).toContain('echo world');
2269
- expect(frame).toContain('ls');
2270
- });
2271
- unmount();
2272
- });
2273
- it.each([
2274
- { name: 'standard', escapeSequence: '\x1B' },
2275
- { name: 'kitty', escapeSequence: '\u001b[27u' },
2276
- ])('resets reverse search state on Escape ($name)', async ({ escapeSequence }) => {
2277
- const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2278
- await act(async () => {
2279
- stdin.write('\x12');
2280
- });
2281
- // Wait for reverse search to be active
2282
- await waitFor(() => {
2283
- expect(stdout.lastFrame()).toContain('(r:)');
2284
- });
2285
- await act(async () => {
2286
- stdin.write(escapeSequence);
2287
- });
2288
- await waitFor(() => {
2289
- expect(stdout.lastFrame()).not.toContain('(r:)');
2290
- expect(stdout.lastFrame()).not.toContain('echo hello');
2291
- });
2292
- unmount();
2293
- });
2294
- it('completes the highlighted entry on Tab and exits reverse-search', async () => {
2295
- // Mock the reverse search completion
2296
- const mockHandleAutocomplete = vi.fn(() => {
2297
- props.buffer.setText('echo hello');
2298
- });
2299
- mockedUseReverseSearchCompletion.mockImplementation((buffer, shellHistory, reverseSearchActive) => ({
2300
- ...mockReverseSearchCompletion,
2301
- suggestions: reverseSearchActive
2302
- ? [
2303
- { label: 'echo hello', value: 'echo hello' },
2304
- { label: 'echo world', value: 'echo world' },
2305
- { label: 'ls', value: 'ls' },
2306
- ]
2307
- : [],
2308
- showSuggestions: reverseSearchActive,
2309
- activeSuggestionIndex: reverseSearchActive ? 0 : -1,
2310
- handleAutocomplete: mockHandleAutocomplete,
2311
- }));
2312
- const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2313
- // Enter reverse search mode with Ctrl+R
2314
- await act(async () => {
2315
- stdin.write('\x12');
2316
- });
2317
- // Verify reverse search is active
2318
- await waitFor(() => {
2319
- expect(stdout.lastFrame()).toContain('(r:)');
2320
- });
2321
- // Press Tab to complete the highlighted entry
2322
- await act(async () => {
2323
- stdin.write('\t');
2324
- });
2325
- await waitFor(() => {
2326
- expect(mockHandleAutocomplete).toHaveBeenCalledWith(0);
2327
- expect(props.buffer.setText).toHaveBeenCalledWith('echo hello');
2328
- });
2329
- unmount();
2330
- }, 15000);
2331
- it('should NOT autocomplete on Shift+Tab in reverse search', async () => {
2332
- const mockHandleAutocomplete = vi.fn();
2333
- mockedUseReverseSearchCompletion.mockReturnValue({
2334
- ...mockReverseSearchCompletion,
2335
- suggestions: [{ label: 'echo hello', value: 'echo hello' }],
2336
- showSuggestions: true,
2337
- activeSuggestionIndex: 0,
2338
- handleAutocomplete: mockHandleAutocomplete,
2339
- });
2340
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
2341
- uiActions,
2342
- });
2343
- await act(async () => {
2344
- stdin.write('\x12'); // Ctrl+R
2345
- });
2346
- await act(async () => {
2347
- stdin.write('\x1b[Z'); // Shift+Tab
2348
- });
2349
- await new Promise((resolve) => setTimeout(resolve, 100));
2350
- expect(mockHandleAutocomplete).not.toHaveBeenCalled();
2351
- unmount();
2352
- });
2353
- it('submits the highlighted entry on Enter and exits reverse-search', async () => {
2354
- // Mock the reverse search completion to return suggestions
2355
- mockedUseReverseSearchCompletion.mockReturnValue({
2356
- ...mockReverseSearchCompletion,
2357
- suggestions: [
2358
- { label: 'echo hello', value: 'echo hello' },
2359
- { label: 'echo world', value: 'echo world' },
2360
- { label: 'ls', value: 'ls' },
2361
- ],
2362
- showSuggestions: true,
2363
- activeSuggestionIndex: 0,
2364
- });
2365
- const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2366
- await act(async () => {
2367
- stdin.write('\x12');
2368
- });
2369
- await waitFor(() => {
2370
- expect(stdout.lastFrame()).toContain('(r:)');
2371
- });
2372
- await act(async () => {
2373
- stdin.write('\r');
2374
- });
2375
- await waitFor(() => {
2376
- expect(stdout.lastFrame()).not.toContain('(r:)');
2377
- });
2378
- expect(props.onSubmit).toHaveBeenCalledWith('echo hello');
2379
- unmount();
2380
- });
2381
- it('should restore text and cursor position after reverse search"', async () => {
2382
- const initialText = 'initial text';
2383
- const initialCursor = [0, 3];
2384
- props.buffer.setText(initialText);
2385
- props.buffer.cursor = initialCursor;
2386
- // Mock the reverse search completion to be active and then reset
2387
- mockedUseReverseSearchCompletion.mockImplementation((buffer, shellHistory, reverseSearchActiveFromInputPrompt) => ({
2388
- ...mockReverseSearchCompletion,
2389
- suggestions: reverseSearchActiveFromInputPrompt
2390
- ? [{ label: 'history item', value: 'history item' }]
2391
- : [],
2392
- showSuggestions: reverseSearchActiveFromInputPrompt,
2393
- }));
2394
- const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2395
- // reverse search with Ctrl+R
2396
- await act(async () => {
2397
- stdin.write('\x12');
2398
- });
2399
- await waitFor(() => {
2400
- expect(stdout.lastFrame()).toContain('(r:)');
2401
- });
2402
- // Press kitty escape key
2403
- await act(async () => {
2404
- stdin.write('\u001b[27u');
2405
- });
2406
- await waitFor(() => {
2407
- expect(stdout.lastFrame()).not.toContain('(r:)');
2408
- expect(props.buffer.text).toBe(initialText);
2409
- expect(props.buffer.cursor).toEqual(initialCursor);
2410
- });
2411
- unmount();
2412
- });
2413
- });
2414
- describe('Ctrl+E keyboard shortcut', () => {
2415
- it('should move cursor to end of current line in multiline input', async () => {
2416
- props.buffer.text = 'line 1\nline 2\nline 3';
2417
- props.buffer.cursor = [1, 2];
2418
- props.buffer.lines = ['line 1', 'line 2', 'line 3'];
2419
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2420
- await act(async () => {
2421
- stdin.write('\x05'); // Ctrl+E
2422
- });
2423
- await waitFor(() => {
2424
- expect(props.buffer.move).toHaveBeenCalledWith('end');
2425
- });
2426
- expect(props.buffer.moveToOffset).not.toHaveBeenCalled();
2427
- unmount();
2428
- });
2429
- it('should move cursor to end of current line for single line input', async () => {
2430
- props.buffer.text = 'single line text';
2431
- props.buffer.cursor = [0, 5];
2432
- props.buffer.lines = ['single line text'];
2433
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2434
- await act(async () => {
2435
- stdin.write('\x05'); // Ctrl+E
2436
- });
2437
- await waitFor(() => {
2438
- expect(props.buffer.move).toHaveBeenCalledWith('end');
2439
- });
2440
- expect(props.buffer.moveToOffset).not.toHaveBeenCalled();
2441
- unmount();
2442
- });
2443
- });
2444
- describe('command search (Ctrl+R when not in shell)', () => {
2445
- it('enters command search on Ctrl+R and shows suggestions', async () => {
2446
- props.shellModeActive = false;
2447
- vi.mocked(useReverseSearchCompletion).mockImplementation((buffer, data, isActive) => ({
2448
- ...mockReverseSearchCompletion,
2449
- suggestions: isActive
2450
- ? [
2451
- { label: 'git commit -m "msg"', value: 'git commit -m "msg"' },
2452
- { label: 'git push', value: 'git push' },
2453
- ]
2454
- : [],
2455
- showSuggestions: !!isActive,
2456
- activeSuggestionIndex: isActive ? 0 : -1,
2457
- }));
2458
- const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2459
- await act(async () => {
2460
- stdin.write('\x12'); // Ctrl+R
2461
- });
2462
- await waitFor(() => {
2463
- const frame = stdout.lastFrameRaw() ?? '';
2464
- expect(frame).toContain('(r:)');
2465
- expect(frame).toContain('git commit');
2466
- expect(frame).toContain('git push');
2467
- });
2468
- unmount();
2469
- });
2470
- it('expands and collapses long suggestion via Right/Left arrows', async () => {
2471
- props.shellModeActive = false;
2472
- const longValue = 'l'.repeat(200);
2473
- vi.mocked(useReverseSearchCompletion).mockReturnValue({
2474
- ...mockReverseSearchCompletion,
2475
- suggestions: [{ label: longValue, value: longValue, matchedIndex: 0 }],
2476
- showSuggestions: true,
2477
- activeSuggestionIndex: 0,
2478
- visibleStartIndex: 0,
2479
- isLoadingSuggestions: false,
2480
- });
2481
- const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2482
- await act(async () => {
2483
- stdin.write('\x12');
2484
- });
2485
- await waitFor(() => {
2486
- expect(clean(stdout.lastFrame())).toContain('→');
2487
- });
2488
- await act(async () => {
2489
- stdin.write('\u001B[C');
2490
- });
2491
- await waitFor(() => {
2492
- expect(clean(stdout.lastFrame())).toContain('←');
2493
- });
2494
- expect(stdout.lastFrame()).toMatchSnapshot('command-search-render-expanded-match');
2495
- await act(async () => {
2496
- stdin.write('\u001B[D');
2497
- });
2498
- await waitFor(() => {
2499
- expect(clean(stdout.lastFrame())).toContain('→');
2500
- });
2501
- expect(stdout.lastFrame()).toMatchSnapshot('command-search-render-collapsed-match');
2502
- unmount();
2503
- });
2504
- it('renders match window and expanded view (snapshots)', async () => {
2505
- props.shellModeActive = false;
2506
- props.buffer.setText('commit');
2507
- const label = 'git commit -m "feat: add search" in src/app';
2508
- const matchedIndex = label.indexOf('commit');
2509
- vi.mocked(useReverseSearchCompletion).mockReturnValue({
2510
- ...mockReverseSearchCompletion,
2511
- suggestions: [{ label, value: label, matchedIndex }],
2512
- showSuggestions: true,
2513
- activeSuggestionIndex: 0,
2514
- visibleStartIndex: 0,
2515
- isLoadingSuggestions: false,
2516
- });
2517
- const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2518
- await act(async () => {
2519
- stdin.write('\x12');
2520
- });
2521
- await waitFor(() => {
2522
- expect(stdout.lastFrame()).toContain('(r:)');
2523
- });
2524
- expect(stdout.lastFrame()).toMatchSnapshot('command-search-render-collapsed-match');
2525
- await act(async () => {
2526
- stdin.write('\u001B[C');
2527
- });
2528
- await waitFor(() => {
2529
- // Just wait for any update to ensure it is stable.
2530
- // We could also wait for specific text if we knew it.
2531
- expect(stdout.lastFrame()).toContain('(r:)');
2532
- });
2533
- expect(stdout.lastFrame()).toMatchSnapshot('command-search-render-expanded-match');
2534
- unmount();
2535
- });
2536
- it('does not show expand/collapse indicator for short suggestions', async () => {
2537
- props.shellModeActive = false;
2538
- const shortValue = 'echo hello';
2539
- vi.mocked(useReverseSearchCompletion).mockReturnValue({
2540
- ...mockReverseSearchCompletion,
2541
- suggestions: [{ label: shortValue, value: shortValue }],
2542
- showSuggestions: true,
2543
- activeSuggestionIndex: 0,
2544
- visibleStartIndex: 0,
2545
- isLoadingSuggestions: false,
2546
- });
2547
- const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2548
- await act(async () => {
2549
- stdin.write('\x12');
2550
- });
2551
- await waitFor(() => {
2552
- const frame = clean(stdout.lastFrame());
2553
- // Ensure it rendered the search mode
2554
- expect(frame).toContain('(r:)');
2555
- expect(frame).not.toContain('→');
2556
- expect(frame).not.toContain('←');
2557
- });
2558
- unmount();
2559
- });
2560
- it('ensures Ctrl+R search results are prioritized newest-to-oldest by reversing userMessages', async () => {
2561
- props.shellModeActive = false;
2562
- props.userMessages = ['oldest', 'middle', 'newest'];
2563
- await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2564
- const calls = vi.mocked(useReverseSearchCompletion).mock.calls;
2565
- const commandSearchCall = calls.find((call) => call[1] === props.userMessages ||
2566
- (Array.isArray(call[1]) && call[1][0] === 'newest'));
2567
- expect(commandSearchCall).toBeDefined();
2568
- expect(commandSearchCall[1]).toEqual(['newest', 'middle', 'oldest']);
2569
- });
2570
- });
2571
- describe('Tab clean UI toggle', () => {
2572
- it.each([
2573
- {
2574
- name: 'should toggle clean UI details on double-Tab when no suggestions or ghost text',
2575
- showSuggestions: false,
2576
- ghostText: '',
2577
- suggestions: [],
2578
- expectedUiToggle: true,
2579
- },
2580
- {
2581
- name: 'should accept ghost text and NOT toggle clean UI details on Tab',
2582
- showSuggestions: false,
2583
- ghostText: 'ghost text',
2584
- suggestions: [],
2585
- expectedUiToggle: false,
2586
- expectedAcceptCall: true,
2587
- },
2588
- {
2589
- name: 'should NOT toggle clean UI details on Tab when suggestions are present',
2590
- showSuggestions: true,
2591
- ghostText: '',
2592
- suggestions: [{ label: 'test', value: 'test' }],
2593
- expectedUiToggle: false,
2594
- },
2595
- ])('$name', async ({ showSuggestions, ghostText, suggestions, expectedUiToggle, expectedAcceptCall, }) => {
2596
- const mockAccept = vi.fn();
2597
- mockedUseCommandCompletion.mockReturnValue({
2598
- ...mockCommandCompletion,
2599
- showSuggestions,
2600
- suggestions,
2601
- promptCompletion: {
2602
- text: ghostText,
2603
- accept: mockAccept,
2604
- clear: vi.fn(),
2605
- isLoading: false,
2606
- isActive: ghostText !== '',
2607
- markSelected: vi.fn(),
2608
- },
2609
- });
2610
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
2611
- uiActions,
2612
- uiState: {},
2613
- });
2614
- await act(async () => {
2615
- stdin.write('\t');
2616
- if (expectedUiToggle) {
2617
- stdin.write('\t');
2618
- }
2619
- });
2620
- await waitFor(() => {
2621
- if (expectedUiToggle) {
2622
- expect(uiActions.toggleCleanUiDetailsVisible).toHaveBeenCalled();
2623
- }
2624
- else {
2625
- expect(uiActions.toggleCleanUiDetailsVisible).not.toHaveBeenCalled();
2626
- }
2627
- if (expectedAcceptCall) {
2628
- expect(mockAccept).toHaveBeenCalled();
2629
- }
2630
- });
2631
- unmount();
2632
- });
2633
- it('should NOT accept ghost text on Shift+Tab', async () => {
2634
- const mockAccept = vi.fn();
2635
- mockedUseCommandCompletion.mockReturnValue({
2636
- ...mockCommandCompletion,
2637
- showSuggestions: false,
2638
- suggestions: [],
2639
- promptCompletion: {
2640
- text: 'ghost text',
2641
- accept: mockAccept,
2642
- clear: vi.fn(),
2643
- isLoading: false,
2644
- isActive: true,
2645
- markSelected: vi.fn(),
2646
- },
2647
- });
2648
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
2649
- uiActions,
2650
- });
2651
- await act(async () => {
2652
- stdin.write('\x1b[Z'); // Shift+Tab
2653
- });
2654
- await new Promise((resolve) => setTimeout(resolve, 100));
2655
- expect(mockAccept).not.toHaveBeenCalled();
2656
- unmount();
2657
- });
2658
- it('should not reveal clean UI details on Shift+Tab when hidden', async () => {
2659
- mockedUseCommandCompletion.mockReturnValue({
2660
- ...mockCommandCompletion,
2661
- showSuggestions: false,
2662
- suggestions: [],
2663
- promptCompletion: {
2664
- text: '',
2665
- accept: vi.fn(),
2666
- clear: vi.fn(),
2667
- isLoading: false,
2668
- isActive: false,
2669
- markSelected: vi.fn(),
2670
- },
2671
- });
2672
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
2673
- uiActions,
2674
- uiState: { activePtyId: 1, cleanUiDetailsVisible: false },
2675
- });
2676
- await act(async () => {
2677
- stdin.write('\x1b[Z');
2678
- });
2679
- await waitFor(() => {
2680
- expect(uiActions.revealCleanUiDetailsTemporarily).not.toHaveBeenCalled();
2681
- });
2682
- unmount();
2683
- });
2684
- it('should toggle clean UI details on double-Tab by default', async () => {
2685
- mockedUseCommandCompletion.mockReturnValue({
2686
- ...mockCommandCompletion,
2687
- showSuggestions: false,
2688
- suggestions: [],
2689
- promptCompletion: {
2690
- text: '',
2691
- accept: vi.fn(),
2692
- clear: vi.fn(),
2693
- isLoading: false,
2694
- isActive: false,
2695
- markSelected: vi.fn(),
2696
- },
2697
- });
2698
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
2699
- uiActions,
2700
- uiState: {},
2701
- });
2702
- await act(async () => {
2703
- stdin.write('\t');
2704
- stdin.write('\t');
2705
- });
2706
- await waitFor(() => {
2707
- expect(uiActions.toggleCleanUiDetailsVisible).toHaveBeenCalled();
2708
- });
2709
- unmount();
2710
- });
2711
- });
2712
- describe('mouse interaction', () => {
2713
- it.each([
2714
- {
2715
- name: 'first line, first char',
2716
- relX: 0,
2717
- relY: 0,
2718
- mouseCol: 4,
2719
- mouseRow: 2,
2720
- },
2721
- {
2722
- name: 'first line, middle char',
2723
- relX: 6,
2724
- relY: 0,
2725
- mouseCol: 10,
2726
- mouseRow: 2,
2727
- },
2728
- {
2729
- name: 'second line, first char',
2730
- relX: 0,
2731
- relY: 1,
2732
- mouseCol: 4,
2733
- mouseRow: 3,
2734
- },
2735
- {
2736
- name: 'second line, end char',
2737
- relX: 5,
2738
- relY: 1,
2739
- mouseCol: 9,
2740
- mouseRow: 3,
2741
- },
2742
- ])('should move cursor on mouse click - $name', async ({ relX, relY, mouseCol, mouseRow }) => {
2743
- props.buffer.text = 'hello world\nsecond line';
2744
- props.buffer.lines = ['hello world', 'second line'];
2745
- props.buffer.allVisualLines = ['hello world', 'second line'];
2746
- props.buffer.viewportVisualLines = ['hello world', 'second line'];
2747
- props.buffer.viewportHeight = 10;
2748
- props.buffer.visualToLogicalMap = [
2749
- [0, 0],
2750
- [1, 0],
2751
- ];
2752
- props.buffer.visualCursor = [0, 11];
2753
- props.buffer.visualScrollRow = 0;
2754
- const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { mouseEventsEnabled: true, uiActions });
2755
- // Wait for initial render
2756
- await waitFor(() => {
2757
- expect(stdout.lastFrame()).toContain('hello world');
2758
- });
2759
- // Simulate left mouse press at calculated coordinates.
2760
- // Without left border: inner box is at x=3, y=1 based on padding(1)+prompt(2) and border-top(1).
2761
- await act(async () => {
2762
- stdin.write(`\x1b[<0;${mouseCol};${mouseRow}M`);
2763
- });
2764
- await waitFor(() => {
2765
- expect(props.buffer.moveToVisualPosition).toHaveBeenCalledWith(relY, relX);
2766
- });
2767
- unmount();
2768
- });
2769
- it('should unfocus embedded shell on click', async () => {
2770
- props.buffer.setText('hello');
2771
- props.isEmbeddedShellFocused = true;
2772
- const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { mouseEventsEnabled: true, uiActions });
2773
- await waitFor(() => {
2774
- expect(stdout.lastFrame()).toContain('hello');
2775
- });
2776
- await act(async () => {
2777
- // Click somewhere in the prompt
2778
- stdin.write(`\x1b[<0;5;2M`);
2779
- });
2780
- await waitFor(() => {
2781
- expect(mockSetEmbeddedShellFocused).toHaveBeenCalledWith(false);
2782
- });
2783
- unmount();
2784
- });
2785
- it('should toggle paste expansion on double-click', async () => {
2786
- vi.spyOn(Date, 'now').mockReturnValue(1000);
2787
- const id = '[Pasted Text: 10 lines]';
2788
- const largeText = 'line1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nline9\nline10';
2789
- const togglePasteExpansion = vi.fn();
2790
- const baseProps = props;
2791
- const TestWrapper = () => {
2792
- const [isExpanded, setIsExpanded] = useState(false);
2793
- const currentLines = isExpanded ? largeText.split('\n') : [id];
2794
- const currentText = isExpanded ? largeText : id;
2795
- const buffer = {
2796
- ...baseProps.buffer,
2797
- text: currentText,
2798
- lines: currentLines,
2799
- viewportVisualLines: currentLines,
2800
- allVisualLines: currentLines,
2801
- viewportHeight: 10,
2802
- pastedContent: { [id]: largeText },
2803
- transformationsByLine: isExpanded
2804
- ? currentLines.map(() => [])
2805
- : [
2806
- [
2807
- {
2808
- logStart: 0,
2809
- logEnd: id.length,
2810
- logicalText: id,
2811
- collapsedText: id,
2812
- type: 'paste',
2813
- id,
2814
- },
2815
- ],
2816
- ],
2817
- visualScrollRow: 0,
2818
- visualToLogicalMap: currentLines.map((_, i) => [i, 0]),
2819
- visualToTransformedMap: currentLines.map(() => 0),
2820
- getLogicalPositionFromVisual: vi.fn().mockReturnValue({
2821
- row: 0,
2822
- col: 2,
2823
- }),
2824
- togglePasteExpansion: vi.fn().mockImplementation((...args) => {
2825
- togglePasteExpansion(...args);
2826
- setIsExpanded((expanded) => !expanded);
2827
- }),
2828
- getExpandedPasteAtLine: vi
2829
- .fn()
2830
- .mockReturnValue(isExpanded ? id : null),
2831
- };
2832
- return _jsx(TestInputPrompt, { ...baseProps, buffer: buffer });
2833
- };
2834
- const { stdout, unmount, simulateClick } = await renderWithProviders(_jsx(TestWrapper, {}), {
2835
- mouseEventsEnabled: true,
2836
- config: makeFakeConfig({ useAlternateBuffer: true }),
2837
- settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
2838
- uiActions,
2839
- });
2840
- // 1. Verify initial placeholder
2841
- await waitFor(() => {
2842
- expect(stdout.lastFrame()).toMatchSnapshot();
2843
- });
2844
- // Simulate double-click to expand
2845
- await simulateClick(5, 2);
2846
- await simulateClick(5, 2);
2847
- // 2. Verify expanded content is visible
2848
- await waitFor(() => {
2849
- expect(togglePasteExpansion).toHaveBeenCalledWith(id, 0, 2);
2850
- expect(stdout.lastFrame()).toContain('line10');
2851
- });
2852
- // Simulate double-click to collapse
2853
- await simulateClick(5, 2);
2854
- await simulateClick(5, 2);
2855
- // 3. Verify placeholder is restored
2856
- await waitFor(() => {
2857
- expect(togglePasteExpansion).toHaveBeenCalledTimes(2);
2858
- expect(stdout.lastFrame()).toContain(id);
2859
- expect(stdout.lastFrame()).toMatchSnapshot();
2860
- });
2861
- unmount();
2862
- });
2863
- it('should collapse expanded paste on double-click after the end of the line', async () => {
2864
- const id = '[Pasted Text: 10 lines]';
2865
- const largeText = 'line1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nline9\nline10';
2866
- const baseProps = props;
2867
- const TestWrapper = () => {
2868
- const [isExpanded, setIsExpanded] = useState(true); // Start expanded
2869
- const currentLines = isExpanded ? largeText.split('\n') : [id];
2870
- const currentText = isExpanded ? largeText : id;
2871
- const buffer = {
2872
- ...baseProps.buffer,
2873
- text: currentText,
2874
- lines: currentLines,
2875
- viewportVisualLines: currentLines,
2876
- allVisualLines: currentLines,
2877
- viewportHeight: 10,
2878
- pastedContent: { [id]: largeText },
2879
- transformationsByLine: isExpanded
2880
- ? currentLines.map(() => [])
2881
- : [
2882
- [
2883
- {
2884
- logStart: 0,
2885
- logEnd: id.length,
2886
- logicalText: id,
2887
- collapsedText: id,
2888
- type: 'paste',
2889
- id,
2890
- },
2891
- ],
2892
- ],
2893
- visualScrollRow: 0,
2894
- visualToLogicalMap: currentLines.map((_, i) => [i, 0]),
2895
- visualToTransformedMap: currentLines.map(() => 0),
2896
- getLogicalPositionFromVisual: vi.fn().mockImplementation((_vRow, _vCol) =>
2897
- // Simulate that we are past the end of the line by returning something
2898
- // that getTransformUnderCursor won't match, or having the caller handle it.
2899
- null),
2900
- togglePasteExpansion: vi.fn().mockImplementation(() => {
2901
- setIsExpanded(!isExpanded);
2902
- }),
2903
- getExpandedPasteAtLine: vi
2904
- .fn()
2905
- .mockImplementation((row) => isExpanded && row >= 0 && row < 10 ? id : null),
2906
- };
2907
- return _jsx(TestInputPrompt, { ...baseProps, buffer: buffer });
2908
- };
2909
- const { stdout, unmount, simulateClick } = await renderWithProviders(_jsx(TestWrapper, {}), {
2910
- mouseEventsEnabled: true,
2911
- config: makeFakeConfig({ useAlternateBuffer: true }),
2912
- settings: createMockSettings({ ui: { useAlternateBuffer: true } }),
2913
- uiActions,
2914
- });
2915
- // Verify initially expanded
2916
- await waitFor(() => {
2917
- expect(stdout.lastFrame()).toContain('line1');
2918
- });
2919
- // Simulate double-click WAY to the right on the first line
2920
- await simulateClick(90, 2);
2921
- await simulateClick(90, 2);
2922
- // Verify it is NOW collapsed
2923
- await waitFor(() => {
2924
- expect(stdout.lastFrame()).toContain(id);
2925
- expect(stdout.lastFrame()).not.toContain('line1');
2926
- });
2927
- unmount();
2928
- });
2929
- it('should move cursor on mouse click with plain borders', async () => {
2930
- props.config.getUseBackgroundColor = () => false;
2931
- props.buffer.text = 'hello world';
2932
- props.buffer.lines = ['hello world'];
2933
- props.buffer.allVisualLines = ['hello world'];
2934
- props.buffer.viewportVisualLines = ['hello world'];
2935
- props.buffer.viewportHeight = 10;
2936
- props.buffer.visualToLogicalMap = [[0, 0]];
2937
- props.buffer.visualCursor = [0, 11];
2938
- props.buffer.visualScrollRow = 0;
2939
- const { stdin, stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { mouseEventsEnabled: true, uiActions });
2940
- // Wait for initial render
2941
- await waitFor(() => {
2942
- expect(stdout.lastFrame()).toContain('hello world');
2943
- });
2944
- // With plain borders offset
2945
- await act(async () => {
2946
- stdin.write(`\x1b[<0;4;2M`); // Click at col 4, row 2
2947
- });
2948
- await waitFor(() => {
2949
- expect(props.buffer.moveToVisualPosition).toHaveBeenCalledWith(0, 0);
2950
- });
2951
- unmount();
2952
- });
2953
- });
2954
- describe('queued message editing', () => {
2955
- it('should load all queued messages when up arrow is pressed with empty input', async () => {
2956
- const mockPopAllMessages = vi.fn();
2957
- mockPopAllMessages.mockReturnValue('Message 1\n\nMessage 2\n\nMessage 3');
2958
- props.popAllMessages = mockPopAllMessages;
2959
- props.buffer.text = '';
2960
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2961
- await act(async () => {
2962
- stdin.write('\u001B[A');
2963
- });
2964
- await waitFor(() => expect(mockPopAllMessages).toHaveBeenCalled());
2965
- expect(props.buffer.setText).toHaveBeenCalledWith('Message 1\n\nMessage 2\n\nMessage 3');
2966
- unmount();
2967
- });
2968
- it('should not load queued messages when input is not empty', async () => {
2969
- const mockPopAllMessages = vi.fn();
2970
- props.popAllMessages = mockPopAllMessages;
2971
- props.buffer.text = 'some text';
2972
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2973
- await act(async () => {
2974
- stdin.write('\u001B[A');
2975
- });
2976
- await waitFor(() => expect(mockInputHistory.navigateUp).toHaveBeenCalled());
2977
- expect(mockPopAllMessages).not.toHaveBeenCalled();
2978
- unmount();
2979
- });
2980
- it('should handle undefined messages from popAllMessages', async () => {
2981
- const mockPopAllMessages = vi.fn();
2982
- mockPopAllMessages.mockReturnValue(undefined);
2983
- props.popAllMessages = mockPopAllMessages;
2984
- props.buffer.text = '';
2985
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
2986
- await act(async () => {
2987
- stdin.write('\u001B[A');
2988
- });
2989
- await waitFor(() => expect(mockPopAllMessages).toHaveBeenCalled());
2990
- expect(props.buffer.setText).not.toHaveBeenCalled();
2991
- expect(mockInputHistory.navigateUp).toHaveBeenCalled();
2992
- unmount();
2993
- });
2994
- it('should work with NAVIGATION_UP key as well', async () => {
2995
- const mockPopAllMessages = vi.fn();
2996
- props.popAllMessages = mockPopAllMessages;
2997
- props.buffer.text = '';
2998
- props.buffer.allVisualLines = [''];
2999
- props.buffer.visualCursor = [0, 0];
3000
- props.buffer.visualScrollRow = 0;
3001
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
3002
- await act(async () => {
3003
- stdin.write('\u001B[A');
3004
- });
3005
- await waitFor(() => expect(mockPopAllMessages).toHaveBeenCalled());
3006
- unmount();
3007
- });
3008
- it('should handle single queued message', async () => {
3009
- const mockPopAllMessages = vi.fn();
3010
- mockPopAllMessages.mockReturnValue('Single message');
3011
- props.popAllMessages = mockPopAllMessages;
3012
- props.buffer.text = '';
3013
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
3014
- await act(async () => {
3015
- stdin.write('\u001B[A');
3016
- });
3017
- await waitFor(() => expect(mockPopAllMessages).toHaveBeenCalled());
3018
- expect(props.buffer.setText).toHaveBeenCalledWith('Single message');
3019
- unmount();
3020
- });
3021
- it('should only check for queued messages when buffer text is trimmed empty', async () => {
3022
- const mockPopAllMessages = vi.fn();
3023
- props.popAllMessages = mockPopAllMessages;
3024
- props.buffer.text = ' '; // Whitespace only
3025
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
3026
- await act(async () => {
3027
- stdin.write('\u001B[A');
3028
- });
3029
- await waitFor(() => expect(mockPopAllMessages).toHaveBeenCalled());
3030
- unmount();
3031
- });
3032
- it('should not call popAllMessages if it is not provided', async () => {
3033
- props.popAllMessages = undefined;
3034
- props.buffer.text = '';
3035
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
3036
- await act(async () => {
3037
- stdin.write('\u001B[A');
3038
- });
3039
- await waitFor(() => expect(mockInputHistory.navigateUp).toHaveBeenCalled());
3040
- unmount();
3041
- });
3042
- it('should navigate input history on fresh start when no queued messages exist', async () => {
3043
- const mockPopAllMessages = vi.fn();
3044
- mockPopAllMessages.mockReturnValue(undefined);
3045
- props.popAllMessages = mockPopAllMessages;
3046
- props.buffer.text = '';
3047
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
3048
- await act(async () => {
3049
- stdin.write('\u001B[A');
3050
- });
3051
- await waitFor(() => expect(mockPopAllMessages).toHaveBeenCalled());
3052
- expect(mockInputHistory.navigateUp).toHaveBeenCalled();
3053
- expect(props.buffer.setText).not.toHaveBeenCalled();
3054
- unmount();
3055
- });
3056
- });
3057
- describe('snapshots', () => {
3058
- it('should render correctly in shell mode', async () => {
3059
- props.shellModeActive = true;
3060
- const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
3061
- await waitFor(() => expect(stdout.lastFrame()).toContain('!'));
3062
- expect(stdout.lastFrame()).toMatchSnapshot();
3063
- unmount();
3064
- });
3065
- it('should render correctly when accepting edits', async () => {
3066
- props.approvalMode = ApprovalMode.AUTO_EDIT;
3067
- const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
3068
- await waitFor(() => expect(stdout.lastFrame()).toContain('>'));
3069
- expect(stdout.lastFrame()).toMatchSnapshot();
3070
- unmount();
3071
- });
3072
- it('should render correctly in yolo mode', async () => {
3073
- props.approvalMode = ApprovalMode.YOLO;
3074
- const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
3075
- await waitFor(() => expect(stdout.lastFrame()).toContain('*'));
3076
- expect(stdout.lastFrame()).toMatchSnapshot();
3077
- unmount();
3078
- });
3079
- it('should not show inverted cursor when shell is focused', async () => {
3080
- props.isEmbeddedShellFocused = true;
3081
- props.focus = false;
3082
- const renderResult = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
3083
- await renderResult.waitUntilReady();
3084
- await expect(renderResult).toMatchSvgSnapshot();
3085
- renderResult.unmount();
3086
- });
3087
- });
3088
- it('should still allow input when shell is not focused', async () => {
3089
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
3090
- shellFocus: false,
3091
- });
3092
- await act(async () => {
3093
- stdin.write('a');
3094
- });
3095
- await waitFor(() => expect(mockBuffer.handleInput).toHaveBeenCalled());
3096
- unmount();
3097
- });
3098
- describe('command queuing while streaming', () => {
3099
- beforeEach(() => {
3100
- props.streamingState = StreamingState.Responding;
3101
- props.setQueueErrorMessage = vi.fn();
3102
- props.onSubmit = vi.fn();
3103
- });
3104
- it.each([
3105
- {
3106
- name: 'should prevent slash commands',
3107
- bufferText: '/help',
3108
- shellMode: false,
3109
- shouldSubmit: false,
3110
- errorMessage: 'Slash commands cannot be queued',
3111
- },
3112
- {
3113
- name: 'should allow concurrent-safe slash commands',
3114
- bufferText: '/stats',
3115
- shellMode: false,
3116
- shouldSubmit: true,
3117
- errorMessage: null,
3118
- },
3119
- {
3120
- name: 'should prevent shell commands',
3121
- bufferText: 'ls',
3122
- shellMode: true,
3123
- shouldSubmit: false,
3124
- errorMessage: 'Shell commands cannot be queued',
3125
- },
3126
- {
3127
- name: 'should allow regular messages',
3128
- bufferText: 'regular message',
3129
- shellMode: false,
3130
- shouldSubmit: true,
3131
- errorMessage: null,
3132
- },
3133
- ])('$name', async ({ bufferText, shellMode, shouldSubmit, errorMessage }) => {
3134
- props.buffer.text = bufferText;
3135
- props.shellModeActive = shellMode;
3136
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
3137
- await act(async () => {
3138
- stdin.write('\r');
3139
- });
3140
- await waitFor(() => {
3141
- if (shouldSubmit) {
3142
- expect(props.onSubmit).toHaveBeenCalledWith(bufferText);
3143
- expect(props.setQueueErrorMessage).not.toHaveBeenCalled();
3144
- }
3145
- else {
3146
- expect(props.onSubmit).not.toHaveBeenCalled();
3147
- expect(props.setQueueErrorMessage).toHaveBeenCalledWith(errorMessage);
3148
- }
3149
- });
3150
- unmount();
3151
- });
3152
- });
3153
- describe('IME Cursor Support', () => {
3154
- it('should report correct cursor position for simple ASCII text', async () => {
3155
- const text = 'hello';
3156
- mockBuffer.setText(text);
3157
- mockBuffer.visualCursor = [0, 3]; // Cursor after 'hel'
3158
- mockBuffer.visualScrollRow = 0;
3159
- const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { uiActions });
3160
- await waitFor(() => {
3161
- expect(stdout.lastFrame()).toContain('hello');
3162
- });
3163
- // Check Text calls from the LAST render
3164
- const textCalls = vi.mocked(Text).mock.calls;
3165
- const cursorLineCall = [...textCalls]
3166
- .reverse()
3167
- .find((call) => call[0].terminalCursorFocus === true);
3168
- expect(cursorLineCall).toBeDefined();
3169
- // 'hel' is 3 characters wide
3170
- expect(cursorLineCall[0].terminalCursorPosition).toBe(3);
3171
- unmount();
3172
- });
3173
- it('should report correct cursor position for text with double-width characters', async () => {
3174
- const text = '👍hello';
3175
- mockBuffer.setText(text);
3176
- mockBuffer.visualCursor = [0, 2]; // Cursor after '👍h' (Note: '👍' is one code point but width 2)
3177
- mockBuffer.visualScrollRow = 0;
3178
- const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { uiActions });
3179
- await waitFor(() => {
3180
- expect(stdout.lastFrame()).toContain('👍hello');
3181
- });
3182
- const textCalls = vi.mocked(Text).mock.calls;
3183
- const cursorLineCall = [...textCalls]
3184
- .reverse()
3185
- .find((call) => call[0].terminalCursorFocus === true);
3186
- expect(cursorLineCall).toBeDefined();
3187
- // '👍' is width 2, 'h' is width 1. Total width = 3.
3188
- expect(cursorLineCall[0].terminalCursorPosition).toBe(3);
3189
- unmount();
3190
- });
3191
- it('should report correct cursor position for a line full of "😀" emojis', async () => {
3192
- const text = '😀😀😀';
3193
- mockBuffer.setText(text);
3194
- mockBuffer.visualCursor = [0, 2]; // Cursor after 2 emojis (each 1 code point, width 2)
3195
- mockBuffer.visualScrollRow = 0;
3196
- const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { uiActions });
3197
- await waitFor(() => {
3198
- expect(stdout.lastFrame()).toContain('😀😀😀');
3199
- });
3200
- const textCalls = vi.mocked(Text).mock.calls;
3201
- const cursorLineCall = [...textCalls]
3202
- .reverse()
3203
- .find((call) => call[0].terminalCursorFocus === true);
3204
- expect(cursorLineCall).toBeDefined();
3205
- // 2 emojis * width 2 = 4
3206
- expect(cursorLineCall[0].terminalCursorPosition).toBe(4);
3207
- unmount();
3208
- });
3209
- it('should report correct cursor position for mixed emojis and multi-line input', async () => {
3210
- const lines = ['😀😀', 'hello 😀', 'world'];
3211
- mockBuffer.text = lines.join('\n');
3212
- mockBuffer.lines = lines;
3213
- mockBuffer.allVisualLines = lines;
3214
- mockBuffer.viewportVisualLines = lines;
3215
- mockBuffer.viewportHeight = 10;
3216
- mockBuffer.visualToLogicalMap = [
3217
- [0, 0],
3218
- [1, 0],
3219
- [2, 0],
3220
- ];
3221
- mockBuffer.visualCursor = [1, 7]; // Second line, after 'hello 😀' (6 chars + 1 emoji = 7 code points)
3222
- mockBuffer.visualScrollRow = 0;
3223
- const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { uiActions });
3224
- await waitFor(() => {
3225
- expect(stdout.lastFrame()).toContain('hello 😀');
3226
- });
3227
- const textCalls = vi.mocked(Text).mock.calls;
3228
- const lineCalls = textCalls.filter((call) => call[0].terminalCursorPosition !== undefined);
3229
- const lastRenderLineCalls = lineCalls.slice(-3);
3230
- const focusCall = lastRenderLineCalls.find((call) => call[0].terminalCursorFocus === true);
3231
- expect(focusCall).toBeDefined();
3232
- // 'hello ' is 6 units, '😀' is 2 units. Total = 8.
3233
- expect(focusCall[0].terminalCursorPosition).toBe(8);
3234
- unmount();
3235
- });
3236
- it('should report correct cursor position and focus for multi-line input', async () => {
3237
- const lines = ['first line', 'second line', 'third line'];
3238
- mockBuffer.text = lines.join('\n');
3239
- mockBuffer.lines = lines;
3240
- mockBuffer.allVisualLines = lines;
3241
- mockBuffer.viewportVisualLines = lines;
3242
- mockBuffer.viewportHeight = 10;
3243
- mockBuffer.visualToLogicalMap = [
3244
- [0, 0],
3245
- [1, 0],
3246
- [2, 0],
3247
- ];
3248
- mockBuffer.visualCursor = [1, 7]; // Cursor on second line, after 'second '
3249
- mockBuffer.visualScrollRow = 0;
3250
- const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { uiActions });
3251
- await waitFor(() => {
3252
- expect(stdout.lastFrame()).toContain('second line');
3253
- });
3254
- const textCalls = vi.mocked(Text).mock.calls;
3255
- // We look for the last set of line calls.
3256
- // Line calls have terminalCursorPosition set.
3257
- const lineCalls = textCalls.filter((call) => call[0].terminalCursorPosition !== undefined);
3258
- const lastRenderLineCalls = lineCalls.slice(-3);
3259
- expect(lastRenderLineCalls.length).toBe(3);
3260
- // Only one line should have terminalCursorFocus=true
3261
- const focusCalls = lastRenderLineCalls.filter((call) => call[0].terminalCursorFocus === true);
3262
- expect(focusCalls.length).toBe(1);
3263
- expect(focusCalls[0][0].terminalCursorPosition).toBe(7);
3264
- unmount();
3265
- });
3266
- it('should report cursor position 0 when input is empty and placeholder is shown', async () => {
3267
- mockBuffer.text = '';
3268
- mockBuffer.lines = [''];
3269
- mockBuffer.allVisualLines = [''];
3270
- mockBuffer.viewportVisualLines = [''];
3271
- mockBuffer.visualToLogicalMap = [[0, 0]];
3272
- mockBuffer.visualCursor = [0, 0];
3273
- mockBuffer.visualScrollRow = 0;
3274
- const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, placeholder: "Type here" }), { uiActions });
3275
- await waitFor(() => {
3276
- expect(stdout.lastFrame()).toContain('Type here');
3277
- });
3278
- const textCalls = vi.mocked(Text).mock.calls;
3279
- const cursorLineCall = [...textCalls]
3280
- .reverse()
3281
- .find((call) => call[0].terminalCursorFocus === true);
3282
- expect(cursorLineCall).toBeDefined();
3283
- expect(cursorLineCall[0].terminalCursorPosition).toBe(0);
3284
- unmount();
3285
- });
3286
- });
3287
- describe('image path transformation snapshots', () => {
3288
- const logicalLine = '@/path/to/screenshots/screenshot2x.png';
3289
- const transformations = calculateTransformationsForLine(logicalLine);
3290
- const applyVisualState = (visualLine, cursorCol) => {
3291
- mockBuffer.text = logicalLine;
3292
- mockBuffer.lines = [logicalLine];
3293
- mockBuffer.allVisualLines = [visualLine];
3294
- mockBuffer.viewportVisualLines = [visualLine];
3295
- mockBuffer.visualToLogicalMap = [[0, 0]];
3296
- mockBuffer.visualToTransformedMap = [0];
3297
- mockBuffer.transformationsByLine = [transformations];
3298
- mockBuffer.cursor = [0, cursorCol];
3299
- mockBuffer.visualCursor = [0, cursorCol];
3300
- mockBuffer.visualScrollRow = 0;
3301
- };
3302
- it('should snapshot collapsed image path', async () => {
3303
- const { transformedLine } = calculateTransformedLine(logicalLine, 0, [0, transformations[0].logEnd + 5], transformations);
3304
- applyVisualState(transformedLine, transformations[0].logEnd + 5);
3305
- const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
3306
- await waitFor(() => {
3307
- expect(stdout.lastFrame()).toContain('[Image');
3308
- });
3309
- expect(stdout.lastFrame()).toMatchSnapshot();
3310
- unmount();
3311
- });
3312
- it('should snapshot expanded image path when cursor is on it', async () => {
3313
- const { transformedLine } = calculateTransformedLine(logicalLine, 0, [0, transformations[0].logStart + 1], transformations);
3314
- applyVisualState(transformedLine, transformations[0].logStart + 1);
3315
- const { stdout, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }));
3316
- await waitFor(() => {
3317
- expect(stdout.lastFrame()).toContain('@/path/to/screenshots');
3318
- });
3319
- expect(stdout.lastFrame()).toMatchSnapshot();
3320
- unmount();
3321
- });
3322
- });
3323
- describe('Ctrl+O paste expansion', () => {
3324
- const CTRL_O = '\x0f'; // Ctrl+O key sequence
3325
- it('Ctrl+O triggers paste expansion via keybinding', async () => {
3326
- const id = '[Pasted Text: 10 lines]';
3327
- const toggleFn = vi.fn();
3328
- const buffer = {
3329
- ...props.buffer,
3330
- text: id,
3331
- cursor: [0, 0],
3332
- pastedContent: {
3333
- [id]: 'line1\nline2\nline3\nline4\nline5\nline6\nline7\nline8\nline9\nline10',
3334
- },
3335
- transformationsByLine: [
3336
- [
3337
- {
3338
- logStart: 0,
3339
- logEnd: id.length,
3340
- logicalText: id,
3341
- collapsedText: id,
3342
- type: 'paste',
3343
- id,
3344
- },
3345
- ],
3346
- ],
3347
- expandedPaste: null,
3348
- getExpandedPasteAtLine: vi.fn().mockReturnValue(null),
3349
- togglePasteExpansion: toggleFn,
3350
- };
3351
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, buffer: buffer }), { uiActions });
3352
- await act(async () => {
3353
- stdin.write(CTRL_O);
3354
- });
3355
- await waitFor(() => {
3356
- expect(toggleFn).toHaveBeenCalledWith(id, 0, 0);
3357
- });
3358
- unmount();
3359
- });
3360
- it.each([
3361
- {
3362
- name: 'hint appears on large paste via Ctrl+V',
3363
- text: 'line1\nline2\nline3\nline4\nline5\nline6',
3364
- method: 'ctrl-v',
3365
- expectHint: true,
3366
- },
3367
- {
3368
- name: 'hint does not appear for small pastes via Ctrl+V',
3369
- text: 'hello',
3370
- method: 'ctrl-v',
3371
- expectHint: false,
3372
- },
3373
- {
3374
- name: 'hint appears on large terminal paste event',
3375
- text: 'line1\nline2\nline3\nline4\nline5\nline6',
3376
- method: 'terminal-paste',
3377
- expectHint: true,
3378
- },
3379
- ])('$name', async ({ text, method, expectHint }) => {
3380
- vi.mocked(clipboardy.read).mockResolvedValue(text);
3381
- vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);
3382
- const emitSpy = vi.spyOn(appEvents, 'emit');
3383
- const buffer = {
3384
- ...props.buffer,
3385
- handleInput: vi.fn().mockReturnValue(true),
3386
- };
3387
- // Need kitty protocol enabled for terminal paste events
3388
- if (method === 'terminal-paste') {
3389
- mockedUseKittyKeyboardProtocol.mockReturnValue({
3390
- enabled: true,
3391
- checking: false,
3392
- });
3393
- }
3394
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, buffer: method === 'terminal-paste' ? buffer : props.buffer }));
3395
- await act(async () => {
3396
- if (method === 'ctrl-v') {
3397
- stdin.write('\x16'); // Ctrl+V
3398
- }
3399
- else {
3400
- stdin.write(`\x1b[200~${text}\x1b[201~`);
3401
- }
3402
- });
3403
- await waitFor(() => {
3404
- if (expectHint) {
3405
- expect(emitSpy).toHaveBeenCalledWith(AppEvent.TransientMessage, {
3406
- message: 'Press Ctrl+O to expand pasted text',
3407
- type: TransientMessageType.Hint,
3408
- });
3409
- }
3410
- else {
3411
- // If no hint expected, verify buffer was still updated
3412
- if (method === 'ctrl-v') {
3413
- expect(mockBuffer.insert).toHaveBeenCalledWith(text, {
3414
- paste: true,
3415
- });
3416
- }
3417
- else {
3418
- expect(buffer.handleInput).toHaveBeenCalled();
3419
- }
3420
- }
3421
- });
3422
- if (!expectHint) {
3423
- expect(emitSpy).not.toHaveBeenCalledWith(AppEvent.TransientMessage, expect.any(Object));
3424
- }
3425
- emitSpy.mockRestore();
3426
- unmount();
3427
- });
3428
- });
3429
- describe('tryTogglePasteExpansion', () => {
3430
- it.each([
3431
- {
3432
- name: 'returns false when no pasted content exists',
3433
- cursor: [0, 0],
3434
- pastedContent: {},
3435
- getExpandedPasteAtLine: null,
3436
- expected: false,
3437
- },
3438
- {
3439
- name: 'expands placeholder under cursor',
3440
- cursor: [0, 2],
3441
- pastedContent: { '[Pasted Text: 6 lines]': 'content' },
3442
- transformations: [
3443
- {
3444
- logStart: 0,
3445
- logEnd: '[Pasted Text: 6 lines]'.length,
3446
- id: '[Pasted Text: 6 lines]',
3447
- },
3448
- ],
3449
- expected: true,
3450
- expectedToggle: ['[Pasted Text: 6 lines]', 0, 2],
3451
- },
3452
- {
3453
- name: 'collapses expanded paste when cursor is inside',
3454
- cursor: [1, 0],
3455
- pastedContent: { '[Pasted Text: 6 lines]': 'a\nb\nc' },
3456
- getExpandedPasteAtLine: '[Pasted Text: 6 lines]',
3457
- expected: true,
3458
- expectedToggle: ['[Pasted Text: 6 lines]', 1, 0],
3459
- },
3460
- {
3461
- name: 'expands placeholder when cursor is immediately after it',
3462
- cursor: [0, '[Pasted Text: 6 lines]'.length],
3463
- pastedContent: { '[Pasted Text: 6 lines]': 'content' },
3464
- transformations: [
3465
- {
3466
- logStart: 0,
3467
- logEnd: '[Pasted Text: 6 lines]'.length,
3468
- id: '[Pasted Text: 6 lines]',
3469
- },
3470
- ],
3471
- expected: true,
3472
- expectedToggle: [
3473
- '[Pasted Text: 6 lines]',
3474
- 0,
3475
- '[Pasted Text: 6 lines]'.length,
3476
- ],
3477
- },
3478
- {
3479
- name: 'shows hint when cursor is not on placeholder but placeholders exist',
3480
- cursor: [0, 0],
3481
- pastedContent: { '[Pasted Text: 6 lines]': 'content' },
3482
- transformationsByLine: [
3483
- [],
3484
- [
3485
- {
3486
- logStart: 0,
3487
- logEnd: '[Pasted Text: 6 lines]'.length,
3488
- type: 'paste',
3489
- id: '[Pasted Text: 6 lines]',
3490
- },
3491
- ],
3492
- ],
3493
- expected: true,
3494
- expectedHint: 'Move cursor within placeholder to expand',
3495
- },
3496
- ])('$name', ({ cursor, pastedContent, transformations, transformationsByLine, getExpandedPasteAtLine, expected, expectedToggle, expectedHint, }) => {
3497
- const id = '[Pasted Text: 6 lines]';
3498
- const buffer = {
3499
- cursor,
3500
- pastedContent,
3501
- transformationsByLine: transformationsByLine || [
3502
- transformations
3503
- ? transformations.map((t) => ({
3504
- ...t,
3505
- logicalText: id,
3506
- collapsedText: id,
3507
- type: 'paste',
3508
- }))
3509
- : [],
3510
- ],
3511
- getExpandedPasteAtLine: vi
3512
- .fn()
3513
- .mockReturnValue(getExpandedPasteAtLine),
3514
- togglePasteExpansion: vi.fn(),
3515
- };
3516
- const emitSpy = vi.spyOn(appEvents, 'emit');
3517
- expect(tryTogglePasteExpansion(buffer)).toBe(expected);
3518
- if (expectedToggle) {
3519
- expect(buffer.togglePasteExpansion).toHaveBeenCalledWith(...expectedToggle);
3520
- }
3521
- else {
3522
- expect(buffer.togglePasteExpansion).not.toHaveBeenCalled();
3523
- }
3524
- if (expectedHint) {
3525
- expect(emitSpy).toHaveBeenCalledWith(AppEvent.TransientMessage, {
3526
- message: expectedHint,
3527
- type: TransientMessageType.Hint,
3528
- });
3529
- }
3530
- else {
3531
- expect(emitSpy).not.toHaveBeenCalledWith(AppEvent.TransientMessage, expect.any(Object));
3532
- }
3533
- emitSpy.mockRestore();
3534
- });
3535
- });
3536
- describe('History Navigation and Completion Suppression', () => {
3537
- beforeEach(() => {
3538
- props.userMessages = ['first message', 'second message'];
3539
- // Mock useInputHistory to actually call onChange
3540
- mockedUseInputHistory.mockImplementation(({ onChange, onSubmit }) => ({
3541
- navigateUp: () => {
3542
- onChange('second message', 'start');
3543
- return true;
3544
- },
3545
- navigateDown: () => {
3546
- onChange('first message', 'end');
3547
- return true;
3548
- },
3549
- handleSubmit: vi.fn((val) => onSubmit(val)),
3550
- }));
3551
- });
3552
- it.each([
3553
- { name: 'Up arrow', key: '\u001B[A', position: 'start' },
3554
- { name: 'Ctrl+P', key: '\u0010', position: 'start' },
3555
- ])('should move cursor to $position on $name (older history)', async ({ key, position }) => {
3556
- const { stdin } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
3557
- uiActions,
3558
- });
3559
- await act(async () => {
3560
- stdin.write(key);
3561
- });
3562
- await waitFor(() => {
3563
- expect(mockBuffer.setText).toHaveBeenCalledWith('second message', position);
3564
- });
3565
- });
3566
- it.each([
3567
- { name: 'Down arrow', key: '\u001B[B', position: 'end' },
3568
- { name: 'Ctrl+N', key: '\u000E', position: 'end' },
3569
- ])('should move cursor to $position on $name (newer history)', async ({ key, position }) => {
3570
- const { stdin } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
3571
- uiActions,
3572
- });
3573
- // First go up
3574
- await act(async () => {
3575
- stdin.write('\u001B[A');
3576
- });
3577
- // Then go down
3578
- await act(async () => {
3579
- stdin.write(key);
3580
- if (key === '\u001B[B') {
3581
- // Second press to actually navigate history
3582
- stdin.write(key);
3583
- }
3584
- });
3585
- await waitFor(() => {
3586
- expect(mockBuffer.setText).toHaveBeenCalledWith('first message', position);
3587
- });
3588
- });
3589
- it('should suppress completion after history navigation', async () => {
3590
- const { stdin } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
3591
- uiActions,
3592
- });
3593
- await act(async () => {
3594
- stdin.write('\u001B[A'); // Up arrow
3595
- });
3596
- await waitFor(() => {
3597
- expect(mockedUseCommandCompletion).toHaveBeenLastCalledWith({
3598
- buffer: mockBuffer,
3599
- cwd: expect.anything(),
3600
- slashCommands: expect.anything(),
3601
- commandContext: expect.anything(),
3602
- reverseSearchActive: expect.anything(),
3603
- shellModeActive: expect.anything(),
3604
- config: expect.anything(),
3605
- active: false,
3606
- });
3607
- });
3608
- });
3609
- it('should not render suggestions during history navigation', async () => {
3610
- // 1. Set up a dynamic mock implementation BEFORE rendering
3611
- mockedUseCommandCompletion.mockImplementation(({ active }) => ({
3612
- ...mockCommandCompletion,
3613
- showSuggestions: active,
3614
- suggestions: active
3615
- ? [{ value: 'suggestion', label: 'suggestion' }]
3616
- : [],
3617
- }));
3618
- const { stdout, stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { uiActions });
3619
- // 2. Verify suggestions ARE showing initially because active is true by default
3620
- await waitFor(() => {
3621
- expect(stdout.lastFrame()).toContain('suggestion');
3622
- });
3623
- // 3. Trigger history navigation which should set suppressCompletion to true
3624
- await act(async () => {
3625
- stdin.write('\u001B[A');
3626
- });
3627
- // 4. Verify that suggestions are NOT in the output frame after navigation
3628
- await waitFor(() => {
3629
- expect(stdout.lastFrame()).not.toContain('suggestion');
3630
- });
3631
- expect(stdout.lastFrame()).toMatchSnapshot();
3632
- unmount();
3633
- });
3634
- it('should continue to suppress completion after manual cursor movement', async () => {
3635
- const { stdin } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
3636
- uiActions,
3637
- });
3638
- // Navigate history (suppresses)
3639
- await act(async () => {
3640
- stdin.write('\u001B[A');
3641
- });
3642
- // Wait for it to be suppressed
3643
- await waitFor(() => {
3644
- expect(mockedUseCommandCompletion).toHaveBeenLastCalledWith({
3645
- buffer: mockBuffer,
3646
- cwd: expect.anything(),
3647
- slashCommands: expect.anything(),
3648
- commandContext: expect.anything(),
3649
- reverseSearchActive: expect.anything(),
3650
- shellModeActive: expect.anything(),
3651
- config: expect.anything(),
3652
- active: false,
3653
- });
3654
- });
3655
- // Move cursor manually
3656
- await act(async () => {
3657
- stdin.write('\u001B[D'); // Left arrow
3658
- });
3659
- await waitFor(() => {
3660
- expect(mockedUseCommandCompletion).toHaveBeenLastCalledWith({
3661
- buffer: mockBuffer,
3662
- cwd: expect.anything(),
3663
- slashCommands: expect.anything(),
3664
- commandContext: expect.anything(),
3665
- reverseSearchActive: expect.anything(),
3666
- shellModeActive: expect.anything(),
3667
- config: expect.anything(),
3668
- active: false,
3669
- });
3670
- });
3671
- });
3672
- it('should re-enable completion after typing', async () => {
3673
- const { stdin } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
3674
- uiActions,
3675
- });
3676
- // Navigate history (suppresses)
3677
- await act(async () => {
3678
- stdin.write('\u001B[A');
3679
- });
3680
- // Wait for it to be suppressed
3681
- await waitFor(() => {
3682
- expect(mockedUseCommandCompletion).toHaveBeenLastCalledWith(expect.objectContaining({ active: false }));
3683
- });
3684
- // Type a character
3685
- await act(async () => {
3686
- stdin.write('a');
3687
- });
3688
- await waitFor(() => {
3689
- expect(mockedUseCommandCompletion).toHaveBeenLastCalledWith(expect.objectContaining({ active: true }));
3690
- });
3691
- });
3692
- });
3693
- describe('shortcuts help visibility', () => {
3694
- it('opens shortcuts help with ? on empty prompt even when showShortcutsHint is false', async () => {
3695
- const setShortcutsHelpVisible = vi.fn();
3696
- const settings = createMockSettings({
3697
- ui: { showShortcutsHint: false },
3698
- });
3699
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
3700
- settings,
3701
- uiActions: { setShortcutsHelpVisible },
3702
- });
3703
- await act(async () => {
3704
- stdin.write('?');
3705
- });
3706
- await waitFor(() => {
3707
- expect(setShortcutsHelpVisible).toHaveBeenCalledWith(true);
3708
- });
3709
- unmount();
3710
- });
3711
- it('should NOT open shortcuts help with ? in vim NORMAL mode', async () => {
3712
- const setShortcutsHelpVisible = vi.fn();
3713
- const vimHandleInput = vi.fn().mockReturnValue(true);
3714
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, vimEnabled: true, vimMode: "NORMAL", vimHandleInput: vimHandleInput }), {
3715
- uiActions: { setShortcutsHelpVisible },
3716
- });
3717
- await act(async () => {
3718
- stdin.write('?');
3719
- });
3720
- expect(setShortcutsHelpVisible).not.toHaveBeenCalled();
3721
- expect(vimHandleInput).toHaveBeenCalled();
3722
- expect(mockBuffer.handleInput).not.toHaveBeenCalled();
3723
- unmount();
3724
- });
3725
- it('should open shortcuts help with ? in vim INSERT mode', async () => {
3726
- const setShortcutsHelpVisible = vi.fn();
3727
- const vimHandleInput = vi.fn().mockReturnValue(false);
3728
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, vimEnabled: true, vimMode: "INSERT", vimHandleInput: vimHandleInput }), {
3729
- uiActions: { setShortcutsHelpVisible },
3730
- });
3731
- await act(async () => {
3732
- stdin.write('?');
3733
- });
3734
- await waitFor(() => {
3735
- expect(setShortcutsHelpVisible).toHaveBeenCalledWith(true);
3736
- });
3737
- unmount();
3738
- });
3739
- it.each([
3740
- {
3741
- name: 'terminal paste event occurs',
3742
- input: '\x1b[200~pasted text\x1b[201~',
3743
- },
3744
- {
3745
- name: 'Ctrl+V (PASTE_CLIPBOARD) is pressed',
3746
- input: '\x16',
3747
- setupMocks: () => {
3748
- vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);
3749
- vi.mocked(clipboardy.read).mockResolvedValue('clipboard text');
3750
- },
3751
- },
3752
- {
3753
- name: 'mouse right-click paste occurs',
3754
- input: '\x1b[<2;1;1m',
3755
- mouseEventsEnabled: true,
3756
- setupMocks: () => {
3757
- vi.mocked(clipboardUtils.clipboardHasImage).mockResolvedValue(false);
3758
- vi.mocked(clipboardy.read).mockResolvedValue('clipboard text');
3759
- },
3760
- },
3761
- {
3762
- name: 'Ctrl+R hotkey is pressed',
3763
- input: '\x12',
3764
- },
3765
- {
3766
- name: 'Ctrl+G hotkey is pressed',
3767
- input: '\x07',
3768
- },
3769
- {
3770
- name: 'F12 hotkey is pressed',
3771
- input: '\x1b[24~',
3772
- },
3773
- ])('should close shortcuts help when a $name', async ({ input, setupMocks, mouseEventsEnabled }) => {
3774
- setupMocks?.();
3775
- const setShortcutsHelpVisible = vi.fn();
3776
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), {
3777
- uiState: { shortcutsHelpVisible: true },
3778
- uiActions: { setShortcutsHelpVisible },
3779
- mouseEventsEnabled,
3780
- });
3781
- await act(async () => {
3782
- stdin.write(input);
3783
- });
3784
- await waitFor(() => {
3785
- expect(setShortcutsHelpVisible).toHaveBeenCalledWith(false);
3786
- });
3787
- unmount();
3788
- });
3789
- });
3790
- describe('Voice Mode', () => {
3791
- beforeEach(() => {
3792
- fakeTranscriptionProvider.removeAllListeners();
3793
- vi.clearAllMocks();
3794
- });
3795
- it('should start recording when space is pressed and voice mode is enabled (toggle)', async () => {
3796
- await act(async () => {
3797
- mockBuffer.setText('');
3798
- });
3799
- const { stdin, unmount, lastFrame } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, focus: true, buffer: mockBuffer }), {
3800
- uiState: { isVoiceModeEnabled: true },
3801
- settings: createMockSettings({
3802
- experimental: { voice: { activationMode: 'toggle' } },
3803
- }),
3804
- });
3805
- // Initially not recording
3806
- expect(lastFrame()).toContain('🎤 >');
3807
- expect(lastFrame()).toContain('Type your message or space to talk (Esc to exit)');
3808
- // Press space to start
3809
- await act(async () => {
3810
- stdin.write(' ');
3811
- });
3812
- unmount();
3813
- });
3814
- it('should toggle recording off when space is pressed again (toggle)', async () => {
3815
- await act(async () => {
3816
- mockBuffer.setText('');
3817
- });
3818
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, focus: true, buffer: mockBuffer }), {
3819
- uiState: { isVoiceModeEnabled: true },
3820
- settings: createMockSettings({
3821
- experimental: { voice: { activationMode: 'toggle' } },
3822
- }),
3823
- });
3824
- // Start recording
3825
- await act(async () => {
3826
- stdin.write(' ');
3827
- });
3828
- // Stop recording
3829
- await act(async () => {
3830
- stdin.write(' ');
3831
- });
3832
- unmount();
3833
- });
3834
- it('should resume recording when space is pressed even if buffer is not empty (toggle)', async () => {
3835
- await act(async () => {
3836
- mockBuffer.setText('First turn.');
3837
- });
3838
- const { stdin, unmount, lastFrame } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, focus: true, buffer: mockBuffer }), {
3839
- uiState: { isVoiceModeEnabled: true },
3840
- settings: createMockSettings({
3841
- experimental: { voice: { activationMode: 'toggle' } },
3842
- }),
3843
- });
3844
- // Should show voice mode prefix even if buffer is not empty
3845
- expect(lastFrame()).toContain('🎤 >');
3846
- expect(lastFrame()).toContain('First turn.');
3847
- // Press space to start recording again
3848
- await act(async () => {
3849
- stdin.write(' ');
3850
- });
3851
- unmount();
3852
- });
3853
- it('should not start recording if voice mode is disabled (toggle)', async () => {
3854
- await act(async () => {
3855
- mockBuffer.setText('');
3856
- });
3857
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, focus: true, buffer: mockBuffer }), {
3858
- uiState: { isVoiceModeEnabled: false },
3859
- settings: createMockSettings({
3860
- experimental: { voice: { activationMode: 'toggle' } },
3861
- }),
3862
- });
3863
- // Press space
3864
- await act(async () => {
3865
- stdin.write(' ');
3866
- });
3867
- // Should NOT show listening, instead should call handleInput which handles space
3868
- expect(mockBuffer.handleInput).toHaveBeenCalled();
3869
- unmount();
3870
- });
3871
- it('should append transcription correctly across multiple turn updates (toggle)', async () => {
3872
- await act(async () => {
3873
- mockBuffer.setText('initial');
3874
- });
3875
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, focus: true, buffer: mockBuffer }), {
3876
- uiState: { isVoiceModeEnabled: true },
3877
- settings: createMockSettings({
3878
- experimental: { voice: { activationMode: 'toggle' } },
3879
- }),
3880
- });
3881
- // Start recording
3882
- await act(async () => {
3883
- stdin.write(' ');
3884
- });
3885
- // Emit first transcription
3886
- await act(async () => {
3887
- fakeTranscriptionProvider.emit('transcription', 'hello');
3888
- });
3889
- await waitFor(() => {
3890
- expect(mockBuffer.setText).toHaveBeenCalledWith('initial hello', 13);
3891
- });
3892
- // turnComplete advances the baseline; next turn appends after it
3893
- await act(async () => {
3894
- fakeTranscriptionProvider.emit('turnComplete');
3895
- });
3896
- await act(async () => {
3897
- fakeTranscriptionProvider.emit('transcription', 'world');
3898
- });
3899
- await waitFor(() => {
3900
- expect(mockBuffer.setText).toHaveBeenCalledWith('initial hello world', 19);
3901
- });
3902
- unmount();
3903
- });
3904
- it('should append transcription correctly when resuming voice mode (toggle)', async () => {
3905
- await act(async () => {
3906
- mockBuffer.setText('First turn.');
3907
- });
3908
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, focus: true, buffer: mockBuffer }), {
3909
- uiState: { isVoiceModeEnabled: true },
3910
- settings: createMockSettings({
3911
- experimental: { voice: { activationMode: 'toggle' } },
3912
- }),
3913
- });
3914
- // Start recording (resumed)
3915
- await act(async () => {
3916
- stdin.write(' ');
3917
- });
3918
- // Emit transcription
3919
- await act(async () => {
3920
- fakeTranscriptionProvider.emit('transcription', 'Second turn.');
3921
- });
3922
- await waitFor(() => {
3923
- expect(mockBuffer.setText).toHaveBeenCalledWith('First turn. Second turn.', 24);
3924
- });
3925
- unmount();
3926
- });
3927
- it('should insert transcription at cursor position when buffer has text before and after (toggle)', async () => {
3928
- await act(async () => {
3929
- mockBuffer.setText('hello world');
3930
- mockBuffer.cursor = [0, 5]; // cursor after 'hello'
3931
- });
3932
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, focus: true, buffer: mockBuffer }), {
3933
- uiState: { isVoiceModeEnabled: true },
3934
- settings: createMockSettings({
3935
- experimental: { voice: { activationMode: 'toggle' } },
3936
- }),
3937
- });
3938
- await act(async () => {
3939
- stdin.write(' ');
3940
- });
3941
- await act(async () => {
3942
- fakeTranscriptionProvider.emit('transcription', 'there');
3943
- });
3944
- // 'hello'(5) + ' '(1) + 'there'(5) = cursor at 11; ' world' preserved after
3945
- await waitFor(() => {
3946
- expect(mockBuffer.setText).toHaveBeenCalledWith('hello there world', 11);
3947
- });
3948
- unmount();
3949
- });
3950
- describe('push-to-talk', () => {
3951
- beforeEach(() => {
3952
- vi.useFakeTimers();
3953
- });
3954
- afterEach(() => {
3955
- vi.useRealTimers();
3956
- });
3957
- it('should insert a space on a single tap', async () => {
3958
- const { stdin, unmount, lastFrame } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, focus: true, buffer: mockBuffer }), {
3959
- uiState: { isVoiceModeEnabled: true },
3960
- settings: createMockSettings({
3961
- experimental: { voice: { activationMode: 'push-to-talk' } },
3962
- }),
3963
- });
3964
- expect(lastFrame()).toContain('🎤 >');
3965
- expect(lastFrame()).toContain('Type your message or hold space to talk (Esc to exit)');
3966
- // Press space once
3967
- await act(async () => {
3968
- stdin.write(' ');
3969
- });
3970
- // Should insert space optimistically
3971
- expect(mockBuffer.insert).toHaveBeenCalledWith(' ');
3972
- // Advance timer past HOLD_DELAY_MS
3973
- await act(async () => {
3974
- vi.advanceTimersByTime(700);
3975
- });
3976
- unmount();
3977
- });
3978
- it('should start recording on hold (simulated by repeat spaces)', async () => {
3979
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, focus: true, buffer: mockBuffer }), {
3980
- uiState: { isVoiceModeEnabled: true },
3981
- settings: createMockSettings({
3982
- experimental: { voice: { activationMode: 'push-to-talk' } },
3983
- }),
3984
- });
3985
- // First space
3986
- await act(async () => {
3987
- stdin.write(' ');
3988
- });
3989
- expect(mockBuffer.insert).toHaveBeenCalledWith(' ');
3990
- // Second space (repeat)
3991
- await act(async () => {
3992
- stdin.write(' ');
3993
- });
3994
- await waitFor(() => {
3995
- // Should have backspaced the optimistic space
3996
- expect(mockBuffer.backspace).toHaveBeenCalled();
3997
- });
3998
- unmount();
3999
- });
4000
- it('should stop recording when space heartbeat stops (release)', async () => {
4001
- const { stdin, unmount, lastFrame } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, focus: true, buffer: mockBuffer }), {
4002
- uiState: { isVoiceModeEnabled: true },
4003
- settings: createMockSettings({
4004
- experimental: { voice: { activationMode: 'push-to-talk' } },
4005
- }),
4006
- });
4007
- // Start hold
4008
- await act(async () => {
4009
- stdin.write(' ');
4010
- stdin.write(' ');
4011
- });
4012
- // Simulate heartbeat (held key) - send space first to reset timer, then advance
4013
- await act(async () => {
4014
- stdin.write(' ');
4015
- vi.advanceTimersByTime(100);
4016
- });
4017
- expect(lastFrame()).toContain('~~~ >');
4018
- // Stop heartbeat (release)
4019
- await act(async () => {
4020
- vi.advanceTimersByTime(400); // Past RELEASE_DELAY_MS
4021
- });
4022
- unmount();
4023
- });
4024
- it('should cancel hold state if non-space key is pressed after first space', async () => {
4025
- const { stdin, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props, focus: true, buffer: mockBuffer }), {
4026
- uiState: { isVoiceModeEnabled: true },
4027
- settings: createMockSettings({
4028
- experimental: { voice: { activationMode: 'push-to-talk' } },
4029
- }),
4030
- });
4031
- // First space
4032
- await act(async () => {
4033
- stdin.write(' ');
4034
- });
4035
- // Type 'a'
4036
- await act(async () => {
4037
- stdin.write('a');
4038
- });
4039
- // Should NOT start recording on next space even if fast
4040
- await act(async () => {
4041
- stdin.write(' ');
4042
- });
4043
- expect(mockBuffer.insert).toHaveBeenCalledTimes(2); // Two spaces inserted
4044
- expect(mockBuffer.handleInput).toHaveBeenCalledWith(expect.objectContaining({ name: 'a' }));
4045
- unmount();
4046
- });
4047
- });
4048
- });
4049
- describe('terminal buffer rendering', () => {
4050
- it('does not clip the last char of a visual line whose width equals inputWidth', async () => {
4051
- const fullLine = '1234567890'; // 10 chars, exactly props.inputWidth
4052
- props.inputWidth = 10;
4053
- props.suggestionsWidth = 10;
4054
- vi.spyOn(props.config, 'getUseTerminalBuffer').mockReturnValue(true);
4055
- mockBuffer.text = fullLine;
4056
- mockBuffer.lines = [fullLine];
4057
- mockBuffer.allVisualLines = [fullLine];
4058
- mockBuffer.viewportVisualLines = [fullLine];
4059
- mockBuffer.visualToLogicalMap = [[0, 0]];
4060
- mockBuffer.visualToTransformedMap = [0];
4061
- mockBuffer.transformationsByLine = [[]];
4062
- mockBuffer.cursor = [0, fullLine.length];
4063
- mockBuffer.visualCursor = [0, fullLine.length];
4064
- const { lastFrame, unmount } = await renderWithProviders(_jsx(TestInputPrompt, { ...props }), { uiActions });
4065
- await waitFor(() => {
4066
- expect(clean(lastFrame())).toContain(fullLine);
4067
- });
4068
- unmount();
4069
- });
4070
- });
4071
- });
4072
- function clean(str) {
4073
- if (!str)
4074
- return '';
4075
- // Remove ANSI escape codes and trim whitespace
4076
- return stripAnsi(str).trim();
4077
- }
4078
- //# sourceMappingURL=InputPrompt.test.js.map