@machina.ai/cell-cli 1.11.0-rc1 → 1.13.0-rc2

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 (538) hide show
  1. package/dist/package.json +16 -10
  2. package/dist/src/commands/extensions/disable.d.ts +1 -1
  3. package/dist/src/commands/extensions/disable.js +15 -7
  4. package/dist/src/commands/extensions/disable.js.map +1 -1
  5. package/dist/src/commands/extensions/enable.d.ts +1 -1
  6. package/dist/src/commands/extensions/enable.js +15 -7
  7. package/dist/src/commands/extensions/enable.js.map +1 -1
  8. package/dist/src/commands/extensions/install.js +14 -3
  9. package/dist/src/commands/extensions/install.js.map +1 -1
  10. package/dist/src/commands/extensions/install.test.js +39 -19
  11. package/dist/src/commands/extensions/install.test.js.map +1 -1
  12. package/dist/src/commands/extensions/link.js +14 -3
  13. package/dist/src/commands/extensions/link.js.map +1 -1
  14. package/dist/src/commands/extensions/list.js +13 -4
  15. package/dist/src/commands/extensions/list.js.map +1 -1
  16. package/dist/src/commands/extensions/uninstall.js +13 -2
  17. package/dist/src/commands/extensions/uninstall.js.map +1 -1
  18. package/dist/src/commands/extensions/update.js +18 -13
  19. package/dist/src/commands/extensions/update.js.map +1 -1
  20. package/dist/src/commands/extensions/validate.d.ts +12 -0
  21. package/dist/src/commands/extensions/validate.js +83 -0
  22. package/dist/src/commands/extensions/validate.js.map +1 -0
  23. package/dist/src/commands/extensions/validate.test.js +93 -0
  24. package/dist/src/commands/extensions/validate.test.js.map +1 -0
  25. package/dist/src/commands/extensions.js +3 -0
  26. package/dist/src/commands/extensions.js.map +1 -1
  27. package/dist/src/commands/mcp/add.test.js +3 -0
  28. package/dist/src/commands/mcp/add.test.js.map +1 -1
  29. package/dist/src/commands/mcp/list.js +10 -3
  30. package/dist/src/commands/mcp/list.js.map +1 -1
  31. package/dist/src/commands/mcp/list.test.js +37 -27
  32. package/dist/src/commands/mcp/list.test.js.map +1 -1
  33. package/dist/src/config/auth.js +0 -5
  34. package/dist/src/config/auth.js.map +1 -1
  35. package/dist/src/config/config.d.ts +6 -3
  36. package/dist/src/config/config.js +65 -80
  37. package/dist/src/config/config.js.map +1 -1
  38. package/dist/src/config/config.test.js +235 -212
  39. package/dist/src/config/config.test.js.map +1 -1
  40. package/dist/src/config/extension-manager.d.ts +63 -0
  41. package/dist/src/config/extension-manager.js +450 -0
  42. package/dist/src/config/extension-manager.js.map +1 -0
  43. package/dist/src/config/extension.d.ts +4 -51
  44. package/dist/src/config/extension.js +1 -535
  45. package/dist/src/config/extension.js.map +1 -1
  46. package/dist/src/config/extension.test.js +525 -201
  47. package/dist/src/config/extension.test.js.map +1 -1
  48. package/dist/src/config/extensions/consent.d.ts +38 -0
  49. package/dist/src/config/extensions/consent.js +123 -0
  50. package/dist/src/config/extensions/consent.js.map +1 -0
  51. package/dist/src/config/extensions/extensionEnablement.d.ts +1 -1
  52. package/dist/src/config/extensions/extensionEnablement.js +4 -3
  53. package/dist/src/config/extensions/extensionEnablement.js.map +1 -1
  54. package/dist/src/config/extensions/extensionEnablement.test.js +10 -10
  55. package/dist/src/config/extensions/extensionEnablement.test.js.map +1 -1
  56. package/dist/src/config/extensions/extensionSettings.d.ts +15 -0
  57. package/dist/src/config/extensions/extensionSettings.js +113 -0
  58. package/dist/src/config/extensions/extensionSettings.js.map +1 -0
  59. package/dist/src/config/extensions/extensionSettings.test.d.ts +6 -0
  60. package/dist/src/config/extensions/extensionSettings.test.js +254 -0
  61. package/dist/src/config/extensions/extensionSettings.test.js.map +1 -0
  62. package/dist/src/config/extensions/github.d.ts +2 -2
  63. package/dist/src/config/extensions/github.js +5 -10
  64. package/dist/src/config/extensions/github.js.map +1 -1
  65. package/dist/src/config/extensions/github.test.js +153 -167
  66. package/dist/src/config/extensions/github.test.js.map +1 -1
  67. package/dist/src/config/extensions/github_fetch.d.ts +1 -1
  68. package/dist/src/config/extensions/github_fetch.js +13 -1
  69. package/dist/src/config/extensions/github_fetch.js.map +1 -1
  70. package/dist/src/config/extensions/github_fetch.test.d.ts +6 -0
  71. package/dist/src/config/extensions/github_fetch.test.js +169 -0
  72. package/dist/src/config/extensions/github_fetch.test.js.map +1 -0
  73. package/dist/src/config/extensions/storage.d.ts +14 -0
  74. package/dist/src/config/extensions/storage.js +32 -0
  75. package/dist/src/config/extensions/storage.js.map +1 -0
  76. package/dist/src/config/extensions/update.d.ts +4 -4
  77. package/dist/src/config/extensions/update.js +39 -39
  78. package/dist/src/config/extensions/update.js.map +1 -1
  79. package/dist/src/config/extensions/update.test.js +72 -74
  80. package/dist/src/config/extensions/update.test.js.map +1 -1
  81. package/dist/src/config/extensions/variableSchema.d.ts +0 -6
  82. package/dist/src/config/extensions/variableSchema.js.map +1 -1
  83. package/dist/src/config/extensions/variables.d.ts +4 -0
  84. package/dist/src/config/extensions/variables.js +6 -0
  85. package/dist/src/config/extensions/variables.js.map +1 -1
  86. package/dist/src/config/keyBindings.d.ts +3 -0
  87. package/dist/src/config/keyBindings.js +30 -8
  88. package/dist/src/config/keyBindings.js.map +1 -1
  89. package/dist/src/config/keyBindings.test.js +17 -0
  90. package/dist/src/config/keyBindings.test.js.map +1 -1
  91. package/dist/src/config/policies/read-only.toml +56 -0
  92. package/dist/src/config/policies/write.toml +63 -0
  93. package/dist/src/config/policies/yolo.toml +31 -0
  94. package/dist/src/config/policy-engine.integration.test.js +41 -38
  95. package/dist/src/config/policy-engine.integration.test.js.map +1 -1
  96. package/dist/src/config/policy.d.ts +2 -2
  97. package/dist/src/config/policy.js +10 -148
  98. package/dist/src/config/policy.js.map +1 -1
  99. package/dist/src/config/sandboxConfig.d.ts +1 -1
  100. package/dist/src/config/sandboxConfig.js +6 -3
  101. package/dist/src/config/sandboxConfig.js.map +1 -1
  102. package/dist/src/config/settings.d.ts +2 -1
  103. package/dist/src/config/settings.js +58 -18
  104. package/dist/src/config/settings.js.map +1 -1
  105. package/dist/src/config/settings.test.js +128 -69
  106. package/dist/src/config/settings.test.js.map +1 -1
  107. package/dist/src/config/settingsSchema.d.ts +170 -28
  108. package/dist/src/config/settingsSchema.js +418 -27
  109. package/dist/src/config/settingsSchema.js.map +1 -1
  110. package/dist/src/config/settingsSchema.test.js +42 -1
  111. package/dist/src/config/settingsSchema.test.js.map +1 -1
  112. package/dist/src/config/trustedFolders.d.ts +1 -1
  113. package/dist/src/config/trustedFolders.js +4 -2
  114. package/dist/src/config/trustedFolders.js.map +1 -1
  115. package/dist/src/core/initializer.js +2 -1
  116. package/dist/src/core/initializer.js.map +1 -1
  117. package/dist/src/gemini.d.ts +1 -1
  118. package/dist/src/gemini.js +46 -16
  119. package/dist/src/gemini.js.map +1 -1
  120. package/dist/src/gemini.test.js +88 -30
  121. package/dist/src/gemini.test.js.map +1 -1
  122. package/dist/src/generated/git-commit.d.ts +2 -2
  123. package/dist/src/generated/git-commit.js +2 -2
  124. package/dist/src/nonInteractiveCli.d.ts +9 -1
  125. package/dist/src/nonInteractiveCli.js +114 -7
  126. package/dist/src/nonInteractiveCli.js.map +1 -1
  127. package/dist/src/nonInteractiveCli.test.js +355 -112
  128. package/dist/src/nonInteractiveCli.test.js.map +1 -1
  129. package/dist/src/services/BuiltinCommandLoader.js +4 -0
  130. package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
  131. package/dist/src/services/BuiltinCommandLoader.test.js +22 -0
  132. package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -1
  133. package/dist/src/services/FeedbackService.js +2 -2
  134. package/dist/src/services/FeedbackService.js.map +1 -1
  135. package/dist/src/services/McpPromptLoader.js +2 -2
  136. package/dist/src/services/McpPromptLoader.js.map +1 -1
  137. package/dist/src/services/McpPromptLoader.test.js +4 -2
  138. package/dist/src/services/McpPromptLoader.test.js.map +1 -1
  139. package/dist/src/test-utils/async.d.ts +9 -0
  140. package/dist/src/test-utils/async.js +29 -0
  141. package/dist/src/test-utils/async.js.map +1 -0
  142. package/dist/src/test-utils/createExtension.d.ts +3 -1
  143. package/dist/src/test-utils/createExtension.js +3 -3
  144. package/dist/src/test-utils/createExtension.js.map +1 -1
  145. package/dist/src/test-utils/render.d.ts +16 -2
  146. package/dist/src/test-utils/render.js +66 -4
  147. package/dist/src/test-utils/render.js.map +1 -1
  148. package/dist/src/test-utils/render.test.d.ts +6 -0
  149. package/dist/src/test-utils/render.test.js +79 -0
  150. package/dist/src/test-utils/render.test.js.map +1 -0
  151. package/dist/src/ui/App.test.js +1 -1
  152. package/dist/src/ui/App.test.js.map +1 -1
  153. package/dist/src/ui/AppContainer.js +181 -65
  154. package/dist/src/ui/AppContainer.js.map +1 -1
  155. package/dist/src/ui/AppContainer.test.js +505 -147
  156. package/dist/src/ui/AppContainer.test.js.map +1 -1
  157. package/dist/src/ui/IdeIntegrationNudge.js +1 -1
  158. package/dist/src/ui/IdeIntegrationNudge.js.map +1 -1
  159. package/dist/src/ui/auth/ApiAuthDialog.d.ts +14 -0
  160. package/dist/src/ui/auth/ApiAuthDialog.js +26 -0
  161. package/dist/src/ui/auth/ApiAuthDialog.js.map +1 -0
  162. package/dist/src/ui/auth/ApiAuthDialog.test.d.ts +6 -0
  163. package/dist/src/ui/auth/ApiAuthDialog.test.js +91 -0
  164. package/dist/src/ui/auth/ApiAuthDialog.test.js.map +1 -0
  165. package/dist/src/ui/auth/AuthDialog.js +7 -3
  166. package/dist/src/ui/auth/AuthDialog.js.map +1 -1
  167. package/dist/src/ui/auth/useAuth.d.ts +2 -0
  168. package/dist/src/ui/auth/useAuth.js +31 -2
  169. package/dist/src/ui/auth/useAuth.js.map +1 -1
  170. package/dist/src/ui/colors.js +3 -0
  171. package/dist/src/ui/colors.js.map +1 -1
  172. package/dist/src/ui/commands/directoryCommand.js +1 -1
  173. package/dist/src/ui/commands/directoryCommand.js.map +1 -1
  174. package/dist/src/ui/commands/extensionsCommand.js +64 -11
  175. package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
  176. package/dist/src/ui/commands/extensionsCommand.test.js +72 -1
  177. package/dist/src/ui/commands/extensionsCommand.test.js.map +1 -1
  178. package/dist/src/ui/commands/mcpCommand.js +14 -14
  179. package/dist/src/ui/commands/mcpCommand.js.map +1 -1
  180. package/dist/src/ui/commands/mcpCommand.test.js +4 -0
  181. package/dist/src/ui/commands/mcpCommand.test.js.map +1 -1
  182. package/dist/src/ui/commands/memoryCommand.js +1 -1
  183. package/dist/src/ui/commands/memoryCommand.js.map +1 -1
  184. package/dist/src/ui/commands/memoryCommand.test.js +3 -1
  185. package/dist/src/ui/commands/memoryCommand.test.js.map +1 -1
  186. package/dist/src/ui/commands/policiesCommand.d.ts +7 -0
  187. package/dist/src/ui/commands/policiesCommand.js +59 -0
  188. package/dist/src/ui/commands/policiesCommand.js.map +1 -0
  189. package/dist/src/ui/commands/policiesCommand.test.d.ts +6 -0
  190. package/dist/src/ui/commands/policiesCommand.test.js +83 -0
  191. package/dist/src/ui/commands/policiesCommand.test.js.map +1 -0
  192. package/dist/src/ui/components/AnsiOutput.test.js +1 -1
  193. package/dist/src/ui/components/AnsiOutput.test.js.map +1 -1
  194. package/dist/src/ui/components/AsciiArt.d.ts +3 -3
  195. package/dist/src/ui/components/AsciiArt.js +3 -3
  196. package/dist/src/ui/components/Composer.js +1 -1
  197. package/dist/src/ui/components/Composer.js.map +1 -1
  198. package/dist/src/ui/components/Composer.test.js +5 -2
  199. package/dist/src/ui/components/Composer.test.js.map +1 -1
  200. package/dist/src/ui/components/ConfigInitDisplay.js +4 -6
  201. package/dist/src/ui/components/ConfigInitDisplay.js.map +1 -1
  202. package/dist/src/ui/components/ConsentPrompt.test.js +18 -8
  203. package/dist/src/ui/components/ConsentPrompt.test.js.map +1 -1
  204. package/dist/src/ui/components/ConsoleSummaryDisplay.js +1 -1
  205. package/dist/src/ui/components/ConsoleSummaryDisplay.js.map +1 -1
  206. package/dist/src/ui/components/ContextSummaryDisplay.test.js +11 -6
  207. package/dist/src/ui/components/ContextSummaryDisplay.test.js.map +1 -1
  208. package/dist/src/ui/components/DetailedMessagesDisplay.js +1 -1
  209. package/dist/src/ui/components/DetailedMessagesDisplay.js.map +1 -1
  210. package/dist/src/ui/components/DialogManager.js +4 -0
  211. package/dist/src/ui/components/DialogManager.js.map +1 -1
  212. package/dist/src/ui/components/FolderTrustDialog.test.js +2 -1
  213. package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
  214. package/dist/src/ui/components/Footer.js +4 -3
  215. package/dist/src/ui/components/Footer.js.map +1 -1
  216. package/dist/src/ui/components/Footer.test.js +83 -0
  217. package/dist/src/ui/components/Footer.test.js.map +1 -1
  218. package/dist/src/ui/components/Header.test.js +13 -5
  219. package/dist/src/ui/components/Header.test.js.map +1 -1
  220. package/dist/src/ui/components/Help.test.js +5 -4
  221. package/dist/src/ui/components/Help.test.js.map +1 -1
  222. package/dist/src/ui/components/HistoryItemDisplay.js +1 -1
  223. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  224. package/dist/src/ui/components/InputPrompt.js +27 -8
  225. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  226. package/dist/src/ui/components/InputPrompt.test.js +776 -727
  227. package/dist/src/ui/components/InputPrompt.test.js.map +1 -1
  228. package/dist/src/ui/components/LoadingIndicator.js +2 -2
  229. package/dist/src/ui/components/LoadingIndicator.js.map +1 -1
  230. package/dist/src/ui/components/LoadingIndicator.test.js +28 -15
  231. package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -1
  232. package/dist/src/ui/components/LoopDetectionConfirmation.js +1 -1
  233. package/dist/src/ui/components/LoopDetectionConfirmation.js.map +1 -1
  234. package/dist/src/ui/components/LoopDetectionConfirmation.test.js +2 -2
  235. package/dist/src/ui/components/LoopDetectionConfirmation.test.js.map +1 -1
  236. package/dist/src/ui/components/MainContent.js +15 -4
  237. package/dist/src/ui/components/MainContent.js.map +1 -1
  238. package/dist/src/ui/components/ModelDialog.js +1 -1
  239. package/dist/src/ui/components/ModelDialog.js.map +1 -1
  240. package/dist/src/ui/components/ModelDialog.test.js +23 -13
  241. package/dist/src/ui/components/ModelDialog.test.js.map +1 -1
  242. package/dist/src/ui/components/ModelStatsDisplay.test.js +1 -1
  243. package/dist/src/ui/components/ModelStatsDisplay.test.js.map +1 -1
  244. package/dist/src/ui/components/Notifications.js +38 -5
  245. package/dist/src/ui/components/Notifications.js.map +1 -1
  246. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +2 -2
  247. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +1 -1
  248. package/dist/src/ui/components/PrepareLabel.test.js +14 -8
  249. package/dist/src/ui/components/PrepareLabel.test.js.map +1 -1
  250. package/dist/src/ui/components/ProQuotaDialog.test.js +14 -6
  251. package/dist/src/ui/components/ProQuotaDialog.test.js.map +1 -1
  252. package/dist/src/ui/components/QueuedMessageDisplay.test.js +11 -6
  253. package/dist/src/ui/components/QueuedMessageDisplay.test.js.map +1 -1
  254. package/dist/src/ui/components/SessionSummaryDisplay.test.js +1 -1
  255. package/dist/src/ui/components/SessionSummaryDisplay.test.js.map +1 -1
  256. package/dist/src/ui/components/SettingsDialog.js +32 -25
  257. package/dist/src/ui/components/SettingsDialog.js.map +1 -1
  258. package/dist/src/ui/components/SettingsDialog.test.js +428 -532
  259. package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
  260. package/dist/src/ui/components/ShellConfirmationDialog.js +1 -1
  261. package/dist/src/ui/components/ShellConfirmationDialog.js.map +1 -1
  262. package/dist/src/ui/components/ShellConfirmationDialog.test.js +2 -2
  263. package/dist/src/ui/components/ShellConfirmationDialog.test.js.map +1 -1
  264. package/dist/src/ui/components/StatsDisplay.test.js +1 -1
  265. package/dist/src/ui/components/StatsDisplay.test.js.map +1 -1
  266. package/dist/src/ui/components/SuggestionsDisplay.js +1 -1
  267. package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
  268. package/dist/src/ui/components/ThemeDialog.test.js +2 -2
  269. package/dist/src/ui/components/ThemeDialog.test.js.map +1 -1
  270. package/dist/src/ui/components/ToolStatsDisplay.test.js +1 -1
  271. package/dist/src/ui/components/ToolStatsDisplay.test.js.map +1 -1
  272. package/dist/src/ui/components/messages/CompressionMessage.test.js +25 -17
  273. package/dist/src/ui/components/messages/CompressionMessage.test.js.map +1 -1
  274. package/dist/src/ui/components/messages/DiffRenderer.test.js +1 -1
  275. package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -1
  276. package/dist/src/ui/components/messages/InfoMessage.js +1 -1
  277. package/dist/src/ui/components/messages/InfoMessage.js.map +1 -1
  278. package/dist/src/ui/components/messages/Todo.js +27 -5
  279. package/dist/src/ui/components/messages/Todo.js.map +1 -1
  280. package/dist/src/ui/components/messages/Todo.test.js +20 -8
  281. package/dist/src/ui/components/messages/Todo.test.js.map +1 -1
  282. package/dist/src/ui/components/messages/ToolConfirmationMessage.js +1 -1
  283. package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
  284. package/dist/src/ui/components/messages/ToolGroupMessage.test.js +29 -15
  285. package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -1
  286. package/dist/src/ui/components/messages/WarningMessage.js +2 -2
  287. package/dist/src/ui/components/messages/WarningMessage.js.map +1 -1
  288. package/dist/src/ui/components/shared/BaseSelectionList.test.js +1 -1
  289. package/dist/src/ui/components/shared/BaseSelectionList.test.js.map +1 -1
  290. package/dist/src/ui/components/shared/MaxSizedBox.test.js +43 -22
  291. package/dist/src/ui/components/shared/MaxSizedBox.test.js.map +1 -1
  292. package/dist/src/ui/components/shared/TextInput.d.ts +15 -0
  293. package/dist/src/ui/components/shared/TextInput.js +38 -0
  294. package/dist/src/ui/components/shared/TextInput.js.map +1 -0
  295. package/dist/src/ui/components/shared/TextInput.test.d.ts +6 -0
  296. package/dist/src/ui/components/shared/TextInput.test.js +242 -0
  297. package/dist/src/ui/components/shared/TextInput.test.js.map +1 -0
  298. package/dist/src/ui/components/shared/text-buffer.d.ts +9 -2
  299. package/dist/src/ui/components/shared/text-buffer.js +51 -13
  300. package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
  301. package/dist/src/ui/components/shared/text-buffer.test.js +385 -202
  302. package/dist/src/ui/components/shared/text-buffer.test.js.map +1 -1
  303. package/dist/src/ui/components/views/ChatList.test.js +7 -4
  304. package/dist/src/ui/components/views/ChatList.test.js.map +1 -1
  305. package/dist/src/ui/components/views/ExtensionsList.d.ts +7 -1
  306. package/dist/src/ui/components/views/ExtensionsList.js +9 -11
  307. package/dist/src/ui/components/views/ExtensionsList.js.map +1 -1
  308. package/dist/src/ui/components/views/ExtensionsList.test.js +43 -22
  309. package/dist/src/ui/components/views/ExtensionsList.test.js.map +1 -1
  310. package/dist/src/ui/components/views/McpStatus.test.js +23 -12
  311. package/dist/src/ui/components/views/McpStatus.test.js.map +1 -1
  312. package/dist/src/ui/contexts/KeypressContext.d.ts +3 -2
  313. package/dist/src/ui/contexts/KeypressContext.js +610 -540
  314. package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
  315. package/dist/src/ui/contexts/KeypressContext.test.js +438 -718
  316. package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
  317. package/dist/src/ui/contexts/MouseContext.d.ts +21 -0
  318. package/dist/src/ui/contexts/MouseContext.js +89 -0
  319. package/dist/src/ui/contexts/MouseContext.js.map +1 -0
  320. package/dist/src/ui/contexts/MouseContext.test.d.ts +6 -0
  321. package/dist/src/ui/contexts/MouseContext.test.js +164 -0
  322. package/dist/src/ui/contexts/MouseContext.test.js.map +1 -0
  323. package/dist/src/ui/contexts/SessionContext.test.js +35 -17
  324. package/dist/src/ui/contexts/SessionContext.test.js.map +1 -1
  325. package/dist/src/ui/contexts/UIActionsContext.d.ts +2 -0
  326. package/dist/src/ui/contexts/UIActionsContext.js.map +1 -1
  327. package/dist/src/ui/contexts/UIStateContext.d.ts +2 -0
  328. package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
  329. package/dist/src/ui/hooks/atCommandProcessor.js +31 -9
  330. package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
  331. package/dist/src/ui/hooks/atCommandProcessor.test.js +163 -64
  332. package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -1
  333. package/dist/src/ui/hooks/shellCommandProcessor.test.js +64 -35
  334. package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -1
  335. package/dist/src/ui/hooks/slashCommandProcessor.test.js +193 -165
  336. package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +1 -1
  337. package/dist/src/ui/hooks/useAtCompletion.test.js +16 -5
  338. package/dist/src/ui/hooks/useAtCompletion.test.js.map +1 -1
  339. package/dist/src/ui/hooks/useAutoAcceptIndicator.js +10 -0
  340. package/dist/src/ui/hooks/useAutoAcceptIndicator.js.map +1 -1
  341. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js +32 -1
  342. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +1 -1
  343. package/dist/src/ui/hooks/useCommandCompletion.test.js +66 -64
  344. package/dist/src/ui/hooks/useCommandCompletion.test.js.map +1 -1
  345. package/dist/src/ui/hooks/useConsoleMessages.test.js +26 -9
  346. package/dist/src/ui/hooks/useConsoleMessages.test.js.map +1 -1
  347. package/dist/src/ui/hooks/useEditorSettings.test.js +40 -34
  348. package/dist/src/ui/hooks/useEditorSettings.test.js.map +1 -1
  349. package/dist/src/ui/hooks/useExtensionUpdates.d.ts +14 -5
  350. package/dist/src/ui/hooks/useExtensionUpdates.js +18 -13
  351. package/dist/src/ui/hooks/useExtensionUpdates.js.map +1 -1
  352. package/dist/src/ui/hooks/useExtensionUpdates.test.js +49 -44
  353. package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +1 -1
  354. package/dist/src/ui/hooks/useFlickerDetector.test.js +9 -5
  355. package/dist/src/ui/hooks/useFlickerDetector.test.js.map +1 -1
  356. package/dist/src/ui/hooks/useFocus.test.js +25 -9
  357. package/dist/src/ui/hooks/useFocus.test.js.map +1 -1
  358. package/dist/src/ui/hooks/useFolderTrust.test.js +46 -22
  359. package/dist/src/ui/hooks/useFolderTrust.test.js.map +1 -1
  360. package/dist/src/ui/hooks/useGeminiStream.js +56 -19
  361. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  362. package/dist/src/ui/hooks/useGeminiStream.test.js +260 -411
  363. package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -1
  364. package/dist/src/ui/hooks/useGitBranchName.js +4 -0
  365. package/dist/src/ui/hooks/useGitBranchName.js.map +1 -1
  366. package/dist/src/ui/hooks/useGitBranchName.test.js +46 -34
  367. package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -1
  368. package/dist/src/ui/hooks/useHistoryManager.test.js +2 -1
  369. package/dist/src/ui/hooks/useHistoryManager.test.js.map +1 -1
  370. package/dist/src/ui/hooks/useIdeTrustListener.test.js +40 -9
  371. package/dist/src/ui/hooks/useIdeTrustListener.test.js.map +1 -1
  372. package/dist/src/ui/hooks/useInputHistory.test.js +2 -1
  373. package/dist/src/ui/hooks/useInputHistory.test.js.map +1 -1
  374. package/dist/src/ui/hooks/useInputHistoryStore.test.js +2 -1
  375. package/dist/src/ui/hooks/useInputHistoryStore.test.js.map +1 -1
  376. package/dist/src/ui/hooks/useKeypress.test.js +103 -114
  377. package/dist/src/ui/hooks/useKeypress.test.js.map +1 -1
  378. package/dist/src/ui/hooks/useLoadingIndicator.test.js +24 -6
  379. package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
  380. package/dist/src/ui/hooks/useMemoryMonitor.test.js +10 -5
  381. package/dist/src/ui/hooks/useMemoryMonitor.test.js.map +1 -1
  382. package/dist/src/ui/hooks/useMessageQueue.test.js +62 -45
  383. package/dist/src/ui/hooks/useMessageQueue.test.js.map +1 -1
  384. package/dist/src/ui/hooks/useModelCommand.test.js +21 -11
  385. package/dist/src/ui/hooks/useModelCommand.test.js.map +1 -1
  386. package/dist/src/ui/hooks/useMouse.d.ts +17 -0
  387. package/dist/src/ui/hooks/useMouse.js +27 -0
  388. package/dist/src/ui/hooks/useMouse.js.map +1 -0
  389. package/dist/src/ui/hooks/useMouse.test.d.ts +6 -0
  390. package/dist/src/ui/hooks/useMouse.test.js +57 -0
  391. package/dist/src/ui/hooks/useMouse.test.js.map +1 -0
  392. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js +2 -2
  393. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js.map +1 -1
  394. package/dist/src/ui/hooks/usePhraseCycler.js +1 -1
  395. package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
  396. package/dist/src/ui/hooks/usePhraseCycler.test.js +109 -106
  397. package/dist/src/ui/hooks/usePhraseCycler.test.js.map +1 -1
  398. package/dist/src/ui/hooks/usePrivacySettings.test.js +26 -6
  399. package/dist/src/ui/hooks/usePrivacySettings.test.js.map +1 -1
  400. package/dist/src/ui/hooks/usePromptCompletion.js +2 -2
  401. package/dist/src/ui/hooks/usePromptCompletion.js.map +1 -1
  402. package/dist/src/ui/hooks/useQuotaAndFallback.js +13 -14
  403. package/dist/src/ui/hooks/useQuotaAndFallback.js.map +1 -1
  404. package/dist/src/ui/hooks/useQuotaAndFallback.test.js +55 -48
  405. package/dist/src/ui/hooks/useQuotaAndFallback.test.js.map +1 -1
  406. package/dist/src/ui/hooks/useReactToolScheduler.d.ts +8 -1
  407. package/dist/src/ui/hooks/useReactToolScheduler.js +59 -34
  408. package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
  409. package/dist/src/ui/hooks/useReactToolScheduler.test.d.ts +6 -0
  410. package/dist/src/ui/hooks/useReactToolScheduler.test.js +65 -0
  411. package/dist/src/ui/hooks/useReactToolScheduler.test.js.map +1 -0
  412. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js +2 -2
  413. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js.map +1 -1
  414. package/dist/src/ui/hooks/useSelectionList.js +5 -4
  415. package/dist/src/ui/hooks/useSelectionList.js.map +1 -1
  416. package/dist/src/ui/hooks/useSelectionList.test.js +272 -183
  417. package/dist/src/ui/hooks/useSelectionList.test.js.map +1 -1
  418. package/dist/src/ui/hooks/useShellHistory.test.js +52 -20
  419. package/dist/src/ui/hooks/useShellHistory.test.js.map +1 -1
  420. package/dist/src/ui/hooks/useSlashCompletion.js +18 -7
  421. package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
  422. package/dist/src/ui/hooks/useSlashCompletion.test.js +275 -137
  423. package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
  424. package/dist/src/ui/hooks/useTimer.test.js +43 -14
  425. package/dist/src/ui/hooks/useTimer.test.js.map +1 -1
  426. package/dist/src/ui/hooks/useToolScheduler.test.js +226 -242
  427. package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
  428. package/dist/src/ui/hooks/vim.test.js +235 -355
  429. package/dist/src/ui/hooks/vim.test.js.map +1 -1
  430. package/dist/src/ui/keyMatchers.test.js +30 -3
  431. package/dist/src/ui/keyMatchers.test.js.map +1 -1
  432. package/dist/src/ui/state/extensions.d.ts +1 -0
  433. package/dist/src/ui/state/extensions.js +1 -0
  434. package/dist/src/ui/state/extensions.js.map +1 -1
  435. package/dist/src/ui/themes/ansi-light.js +1 -0
  436. package/dist/src/ui/themes/ansi-light.js.map +1 -1
  437. package/dist/src/ui/themes/ansi.js +1 -0
  438. package/dist/src/ui/themes/ansi.js.map +1 -1
  439. package/dist/src/ui/themes/atom-one-dark.js +2 -0
  440. package/dist/src/ui/themes/atom-one-dark.js.map +1 -1
  441. package/dist/src/ui/themes/ayu-light.js +2 -0
  442. package/dist/src/ui/themes/ayu-light.js.map +1 -1
  443. package/dist/src/ui/themes/ayu.js +2 -0
  444. package/dist/src/ui/themes/ayu.js.map +1 -1
  445. package/dist/src/ui/themes/color-utils.d.ts +1 -0
  446. package/dist/src/ui/themes/color-utils.js +6 -0
  447. package/dist/src/ui/themes/color-utils.js.map +1 -1
  448. package/dist/src/ui/themes/color-utils.test.js +13 -1
  449. package/dist/src/ui/themes/color-utils.test.js.map +1 -1
  450. package/dist/src/ui/themes/dracula.js +2 -0
  451. package/dist/src/ui/themes/dracula.js.map +1 -1
  452. package/dist/src/ui/themes/github-dark.js +2 -0
  453. package/dist/src/ui/themes/github-dark.js.map +1 -1
  454. package/dist/src/ui/themes/github-light.js +2 -0
  455. package/dist/src/ui/themes/github-light.js.map +1 -1
  456. package/dist/src/ui/themes/googlecode.js +2 -0
  457. package/dist/src/ui/themes/googlecode.js.map +1 -1
  458. package/dist/src/ui/themes/no-color.js +3 -0
  459. package/dist/src/ui/themes/no-color.js.map +1 -1
  460. package/dist/src/ui/themes/semantic-tokens.d.ts +2 -0
  461. package/dist/src/ui/themes/semantic-tokens.js +6 -0
  462. package/dist/src/ui/themes/semantic-tokens.js.map +1 -1
  463. package/dist/src/ui/themes/shades-of-purple.js +2 -0
  464. package/dist/src/ui/themes/shades-of-purple.js.map +1 -1
  465. package/dist/src/ui/themes/theme.d.ts +3 -0
  466. package/dist/src/ui/themes/theme.js +14 -3
  467. package/dist/src/ui/themes/theme.js.map +1 -1
  468. package/dist/src/ui/themes/theme.test.js +67 -1
  469. package/dist/src/ui/themes/theme.test.js.map +1 -1
  470. package/dist/src/ui/themes/xcode.js +2 -0
  471. package/dist/src/ui/themes/xcode.js.map +1 -1
  472. package/dist/src/ui/types.d.ts +3 -1
  473. package/dist/src/ui/types.js +2 -0
  474. package/dist/src/ui/types.js.map +1 -1
  475. package/dist/src/ui/utils/CodeColorizer.js +2 -1
  476. package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
  477. package/dist/src/ui/utils/InlineMarkdownRenderer.d.ts +1 -0
  478. package/dist/src/ui/utils/InlineMarkdownRenderer.js +11 -10
  479. package/dist/src/ui/utils/InlineMarkdownRenderer.js.map +1 -1
  480. package/dist/src/ui/utils/MarkdownDisplay.js +11 -9
  481. package/dist/src/ui/utils/MarkdownDisplay.js.map +1 -1
  482. package/dist/src/ui/utils/clipboardUtils.js +2 -2
  483. package/dist/src/ui/utils/clipboardUtils.js.map +1 -1
  484. package/dist/src/ui/utils/input.d.ts +17 -0
  485. package/dist/src/ui/utils/input.js +51 -0
  486. package/dist/src/ui/utils/input.js.map +1 -0
  487. package/dist/src/ui/utils/input.test.d.ts +6 -0
  488. package/dist/src/ui/utils/input.test.js +44 -0
  489. package/dist/src/ui/utils/input.test.js.map +1 -0
  490. package/dist/src/ui/utils/kittyProtocolDetector.js +13 -4
  491. package/dist/src/ui/utils/kittyProtocolDetector.js.map +1 -1
  492. package/dist/src/ui/utils/mouse.d.ts +31 -0
  493. package/dist/src/ui/utils/mouse.js +164 -0
  494. package/dist/src/ui/utils/mouse.js.map +1 -0
  495. package/dist/src/ui/utils/mouse.test.d.ts +6 -0
  496. package/dist/src/ui/utils/mouse.test.js +131 -0
  497. package/dist/src/ui/utils/mouse.test.js.map +1 -0
  498. package/dist/src/ui/utils/textOutput.d.ts +25 -0
  499. package/dist/src/ui/utils/textOutput.js +49 -0
  500. package/dist/src/ui/utils/textOutput.js.map +1 -0
  501. package/dist/src/ui/utils/textOutput.test.d.ts +6 -0
  502. package/dist/src/ui/utils/textOutput.test.js +79 -0
  503. package/dist/src/ui/utils/textOutput.test.js.map +1 -0
  504. package/dist/src/ui/utils/updateCheck.d.ts +7 -1
  505. package/dist/src/ui/utils/updateCheck.js +33 -29
  506. package/dist/src/ui/utils/updateCheck.js.map +1 -1
  507. package/dist/src/ui/utils/updateCheck.test.js +24 -50
  508. package/dist/src/ui/utils/updateCheck.test.js.map +1 -1
  509. package/dist/src/utils/commentJson.js +2 -2
  510. package/dist/src/utils/commentJson.js.map +1 -1
  511. package/dist/src/utils/commentJson.test.js +7 -6
  512. package/dist/src/utils/commentJson.test.js.map +1 -1
  513. package/dist/src/utils/envVarResolver.d.ts +2 -2
  514. package/dist/src/utils/envVarResolver.js +10 -7
  515. package/dist/src/utils/envVarResolver.js.map +1 -1
  516. package/dist/src/utils/events.d.ts +11 -2
  517. package/dist/src/utils/events.js +1 -0
  518. package/dist/src/utils/events.js.map +1 -1
  519. package/dist/src/utils/handleAutoUpdate.js +9 -3
  520. package/dist/src/utils/handleAutoUpdate.js.map +1 -1
  521. package/dist/src/utils/sandbox.js +16 -18
  522. package/dist/src/utils/sandbox.js.map +1 -1
  523. package/dist/src/utils/version.js +6 -2
  524. package/dist/src/utils/version.js.map +1 -1
  525. package/dist/src/zed-integration/acp.js +2 -1
  526. package/dist/src/zed-integration/acp.js.map +1 -1
  527. package/dist/src/zed-integration/schema.d.ts +4 -4
  528. package/dist/src/zed-integration/zedIntegration.d.ts +2 -2
  529. package/dist/src/zed-integration/zedIntegration.js +12 -19
  530. package/dist/src/zed-integration/zedIntegration.js.map +1 -1
  531. package/dist/tsconfig.tsbuildinfo +1 -1
  532. package/package.json +18 -14
  533. package/dist/src/config/policy.test.js +0 -360
  534. package/dist/src/config/policy.test.js.map +0 -1
  535. package/dist/src/utils/package.d.ts +0 -12
  536. package/dist/src/utils/package.js +0 -24
  537. package/dist/src/utils/package.js.map +0 -1
  538. /package/dist/src/{config/policy.test.d.ts → commands/extensions/validate.test.d.ts} +0 -0
@@ -20,14 +20,14 @@ import { jsx as _jsx } from "react/jsx-runtime";
20
20
  * - Display values for inherited and overridden settings
21
21
  *
22
22
  */
23
- import { render } from 'ink-testing-library';
23
+ import { render } from '../../test-utils/render.js';
24
+ import { waitFor } from '../../test-utils/async.js';
24
25
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
25
26
  import { SettingsDialog } from './SettingsDialog.js';
26
27
  import { LoadedSettings, SettingScope } from '../../config/settings.js';
27
28
  import { VimModeProvider } from '../contexts/VimModeContext.js';
28
29
  import { KeypressProvider } from '../contexts/KeypressContext.js';
29
30
  import { act } from 'react';
30
- import { waitFor } from '@testing-library/react';
31
31
  import { saveModifiedSettings, TEST_ONLY } from '../../utils/settingsUtils.js';
32
32
  import { getSettingsSchema, } from '../../config/settingsSchema.js';
33
33
  // Mock the VimModeContext
@@ -197,127 +197,95 @@ const TOOLS_SHELL_FAKE_SCHEMA = {
197
197
  },
198
198
  },
199
199
  };
200
- // Helper function to simulate key presses (commented out for now)
201
- // const simulateKeyPress = async (keyData: Partial<Key> & { name: string }) => {
202
- // if (currentKeypressHandler) {
203
- // const key: Key = {
204
- // ctrl: false,
205
- // meta: false,
206
- // shift: false,
207
- // paste: false,
208
- // sequence: keyData.sequence || keyData.name,
209
- // ...keyData,
210
- // };
211
- // currentKeypressHandler(key);
212
- // // Allow React to process the state update
213
- // await new Promise(resolve => setTimeout(resolve, 10));
214
- // }
215
- // };
216
- // Mock console.log to avoid noise in tests
217
- // const originalConsoleLog = console.log;
218
- // const originalConsoleError = console.error;
200
+ // Helper function to render SettingsDialog with standard wrapper
201
+ const renderDialog = (settings, onSelect, options) => render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect, onRestartRequest: options?.onRestartRequest, availableTerminalHeight: options?.availableTerminalHeight }) }));
219
202
  describe('SettingsDialog', () => {
220
- // Simple delay function for remaining tests that need gradual migration
221
- const wait = (ms = 50) => new Promise((resolve) => setTimeout(resolve, ms));
222
203
  beforeEach(() => {
223
- // Reset keypress mock state (variables are commented out)
224
- // currentKeypressHandler = null;
225
- // isKeypressActive = false;
226
- // console.log = vi.fn();
227
- // console.error = vi.fn();
228
204
  mockToggleVimEnabled.mockResolvedValue(true);
229
205
  });
230
206
  afterEach(() => {
231
207
  TEST_ONLY.clearFlattenedSchema();
232
208
  vi.clearAllMocks();
233
209
  vi.resetAllMocks();
234
- // Reset keypress mock state (variables are commented out)
235
- // currentKeypressHandler = null;
236
- // isKeypressActive = false;
237
- // console.log = originalConsoleLog;
238
- // console.error = originalConsoleError;
239
210
  });
240
211
  describe('Initial Rendering', () => {
241
212
  it('should render the settings dialog with default state', () => {
242
213
  const settings = createMockSettings();
243
214
  const onSelect = vi.fn();
244
- const { lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
215
+ const { lastFrame } = renderDialog(settings, onSelect);
245
216
  const output = lastFrame();
246
217
  expect(output).toContain('Settings');
247
218
  expect(output).toContain('Apply To');
248
- expect(output).toContain('Use Enter to select, Tab to change focus, Esc to close');
219
+ // Use regex for more flexible help text matching
220
+ expect(output).toMatch(/Enter.*select.*Esc.*close/);
249
221
  });
250
222
  it('should accept availableTerminalHeight prop without errors', () => {
251
223
  const settings = createMockSettings();
252
224
  const onSelect = vi.fn();
253
- const { lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect, availableTerminalHeight: 20 }) }));
225
+ const { lastFrame } = renderDialog(settings, onSelect, {
226
+ availableTerminalHeight: 20,
227
+ });
254
228
  const output = lastFrame();
255
229
  // Should still render properly with the height prop
256
230
  expect(output).toContain('Settings');
257
- expect(output).toContain('Use Enter to select, Esc to close');
258
- });
259
- it('should show settings list with default values', () => {
260
- const settings = createMockSettings();
261
- const onSelect = vi.fn();
262
- const { lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
263
- const output = lastFrame();
264
- // Should show some default settings
265
- expect(output).toContain('●'); // Active indicator
231
+ // Use regex for more flexible help text matching
232
+ expect(output).toMatch(/Enter.*select.*Esc.*close/);
266
233
  });
267
- it('should highlight first setting by default', () => {
234
+ it('should render settings list with visual indicators', () => {
268
235
  const settings = createMockSettings();
269
236
  const onSelect = vi.fn();
270
- const { lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
237
+ const { lastFrame } = renderDialog(settings, onSelect);
271
238
  const output = lastFrame();
272
- // First item should be highlighted with green color and active indicator
273
- expect(output).toContain('●');
239
+ // Use snapshot to capture visual layout including indicators
240
+ expect(output).toMatchSnapshot();
274
241
  });
275
242
  });
276
243
  describe('Settings Navigation', () => {
277
- it('should navigate down with arrow key', async () => {
244
+ it.each([
245
+ {
246
+ name: 'arrow keys',
247
+ down: TerminalKeys.DOWN_ARROW,
248
+ up: TerminalKeys.UP_ARROW,
249
+ },
250
+ {
251
+ name: 'vim keys (j/k)',
252
+ down: 'j',
253
+ up: 'k',
254
+ },
255
+ ])('should navigate with $name', async ({ down, up }) => {
278
256
  const settings = createMockSettings();
279
257
  const onSelect = vi.fn();
280
- const { stdin, unmount, lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
281
- // Press down arrow
258
+ const { stdin, unmount, lastFrame } = renderDialog(settings, onSelect);
259
+ const initialFrame = lastFrame();
260
+ expect(initialFrame).toContain('Vim Mode');
261
+ // Navigate down
282
262
  act(() => {
283
- stdin.write(TerminalKeys.DOWN_ARROW); // Down arrow
263
+ stdin.write(down);
264
+ });
265
+ await waitFor(() => {
266
+ expect(lastFrame()).toContain('Disable Auto Update');
267
+ });
268
+ // Navigate up
269
+ act(() => {
270
+ stdin.write(up);
271
+ });
272
+ await waitFor(() => {
273
+ expect(lastFrame()).toContain('Vim Mode');
284
274
  });
285
- expect(lastFrame()).toContain('● Disable Auto Update');
286
- // The active index should have changed (tested indirectly through behavior)
287
- unmount();
288
- });
289
- it('should navigate up with arrow key', async () => {
290
- const settings = createMockSettings();
291
- const onSelect = vi.fn();
292
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
293
- // First go down, then up
294
- stdin.write(TerminalKeys.DOWN_ARROW); // Down arrow
295
- await wait();
296
- stdin.write(TerminalKeys.UP_ARROW);
297
- await wait();
298
- unmount();
299
- });
300
- it('should navigate with vim keys (j/k)', async () => {
301
- const settings = createMockSettings();
302
- const onSelect = vi.fn();
303
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
304
- // Navigate with vim keys
305
- stdin.write('j'); // Down
306
- await wait();
307
- stdin.write('k'); // Up
308
- await wait();
309
275
  unmount();
310
276
  });
311
277
  it('wraps around when at the top of the list', async () => {
312
278
  const settings = createMockSettings();
313
279
  const onSelect = vi.fn();
314
- const { stdin, unmount, lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
280
+ const { stdin, unmount, lastFrame } = renderDialog(settings, onSelect);
315
281
  // Try to go up from first item
316
282
  act(() => {
317
283
  stdin.write(TerminalKeys.UP_ARROW);
318
284
  });
319
- await wait();
320
- expect(lastFrame()).toContain('● Codebase Investigator Max Num Turns');
285
+ await waitFor(() => {
286
+ // Should wrap to last setting (without relying on exact bullet character)
287
+ expect(lastFrame()).toContain('Codebase Investigator Max Num Turns');
288
+ });
321
289
  unmount();
322
290
  });
323
291
  });
@@ -326,18 +294,17 @@ describe('SettingsDialog', () => {
326
294
  vi.mocked(saveModifiedSettings).mockClear();
327
295
  const settings = createMockSettings();
328
296
  const onSelect = vi.fn();
329
- const component = (_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
330
- const { stdin, unmount, lastFrame } = render(component);
297
+ const { stdin, unmount, lastFrame } = renderDialog(settings, onSelect);
331
298
  // Wait for initial render and verify we're on Vim Mode (first setting)
332
299
  await waitFor(() => {
333
- expect(lastFrame()).toContain('Vim Mode');
300
+ expect(lastFrame()).toContain('Vim Mode');
334
301
  });
335
302
  // Navigate to Disable Auto Update setting and verify we're there
336
303
  act(() => {
337
304
  stdin.write(TerminalKeys.DOWN_ARROW);
338
305
  });
339
306
  await waitFor(() => {
340
- expect(lastFrame()).toContain('Disable Auto Update');
307
+ expect(lastFrame()).toContain('Disable Auto Update');
341
308
  });
342
309
  // Toggle the setting
343
310
  act(() => {
@@ -359,47 +326,36 @@ describe('SettingsDialog', () => {
359
326
  unmount();
360
327
  });
361
328
  describe('enum values', () => {
362
- it('toggles enum values with the enter key', async () => {
329
+ it.each([
330
+ {
331
+ name: 'toggles to next value',
332
+ initialValue: undefined,
333
+ expectedValue: StringEnum.BAZ,
334
+ },
335
+ {
336
+ name: 'loops back to first value when at end',
337
+ initialValue: StringEnum.BAZ,
338
+ expectedValue: StringEnum.FOO,
339
+ },
340
+ ])('$name', async ({ initialValue, expectedValue }) => {
363
341
  vi.mocked(saveModifiedSettings).mockClear();
364
342
  vi.mocked(getSettingsSchema).mockReturnValue(ENUM_FAKE_SCHEMA);
365
343
  const settings = createMockSettings();
344
+ if (initialValue !== undefined) {
345
+ settings.setValue(SettingScope.User, 'ui.theme', initialValue);
346
+ }
366
347
  const onSelect = vi.fn();
367
- const component = (_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
368
- const { stdin, unmount } = render(component);
369
- // Press Enter to toggle current setting
370
- stdin.write(TerminalKeys.DOWN_ARROW);
371
- await wait();
372
- stdin.write(TerminalKeys.ENTER);
373
- await wait();
374
- await waitFor(() => {
375
- expect(vi.mocked(saveModifiedSettings)).toHaveBeenCalled();
348
+ const { stdin, unmount } = renderDialog(settings, onSelect);
349
+ act(() => {
350
+ stdin.write(TerminalKeys.DOWN_ARROW);
351
+ stdin.write(TerminalKeys.ENTER);
376
352
  });
377
- expect(vi.mocked(saveModifiedSettings)).toHaveBeenCalledWith(new Set(['ui.theme']), expect.objectContaining({
378
- ui: expect.objectContaining({
379
- theme: StringEnum.BAZ,
380
- }),
381
- }), expect.any(LoadedSettings), SettingScope.User);
382
- unmount();
383
- });
384
- it('loops back when reaching the end of an enum', async () => {
385
- vi.mocked(saveModifiedSettings).mockClear();
386
- vi.mocked(getSettingsSchema).mockReturnValue(ENUM_FAKE_SCHEMA);
387
- const settings = createMockSettings();
388
- settings.setValue(SettingScope.User, 'ui.theme', StringEnum.BAZ);
389
- const onSelect = vi.fn();
390
- const component = (_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
391
- const { stdin, unmount } = render(component);
392
- // Press Enter to toggle current setting
393
- stdin.write(TerminalKeys.DOWN_ARROW);
394
- await wait();
395
- stdin.write(TerminalKeys.ENTER);
396
- await wait();
397
353
  await waitFor(() => {
398
354
  expect(vi.mocked(saveModifiedSettings)).toHaveBeenCalled();
399
355
  });
400
356
  expect(vi.mocked(saveModifiedSettings)).toHaveBeenCalledWith(new Set(['ui.theme']), expect.objectContaining({
401
357
  ui: expect.objectContaining({
402
- theme: StringEnum.FOO,
358
+ theme: expectedValue,
403
359
  }),
404
360
  }), expect.any(LoadedSettings), SettingScope.User);
405
361
  unmount();
@@ -408,20 +364,22 @@ describe('SettingsDialog', () => {
408
364
  it('should toggle setting with Space key', async () => {
409
365
  const settings = createMockSettings();
410
366
  const onSelect = vi.fn();
411
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
367
+ const { stdin, unmount } = renderDialog(settings, onSelect);
412
368
  // Press Space to toggle current setting
413
- stdin.write(' '); // Space key
414
- await wait();
369
+ act(() => {
370
+ stdin.write(' '); // Space key
371
+ });
415
372
  unmount();
416
373
  });
417
374
  it('should handle vim mode setting specially', async () => {
418
375
  const settings = createMockSettings();
419
376
  const onSelect = vi.fn();
420
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
377
+ const { stdin, unmount } = renderDialog(settings, onSelect);
421
378
  // Navigate to vim mode setting and toggle it
422
379
  // This would require knowing the exact position, so we'll just test that the mock is called
423
- stdin.write(TerminalKeys.ENTER); // Enter key
424
- await wait();
380
+ act(() => {
381
+ stdin.write(TerminalKeys.ENTER); // Enter key
382
+ });
425
383
  // The mock should potentially be called if vim mode was toggled
426
384
  unmount();
427
385
  });
@@ -430,26 +388,26 @@ describe('SettingsDialog', () => {
430
388
  it('should switch between scopes', async () => {
431
389
  const settings = createMockSettings();
432
390
  const onSelect = vi.fn();
433
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
391
+ const { stdin, unmount } = renderDialog(settings, onSelect);
434
392
  // Switch to scope focus
435
- stdin.write(TerminalKeys.TAB); // Tab key
436
- await wait();
437
- // Select different scope (numbers 1-3 typically available)
438
- stdin.write('2'); // Select second scope option
439
- await wait();
393
+ act(() => {
394
+ stdin.write(TerminalKeys.TAB); // Tab key
395
+ // Select different scope (numbers 1-3 typically available)
396
+ stdin.write('2'); // Select second scope option
397
+ });
440
398
  unmount();
441
399
  });
442
400
  it('should reset to settings focus when scope is selected', async () => {
443
401
  const settings = createMockSettings();
444
402
  const onSelect = vi.fn();
445
- const { lastFrame, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
403
+ const { lastFrame, unmount } = renderDialog(settings, onSelect);
446
404
  // Wait for initial render
447
405
  await waitFor(() => {
448
406
  expect(lastFrame()).toContain('Vim Mode');
449
407
  });
450
408
  // The UI should show the settings section is active and scope section is inactive
451
- expect(lastFrame()).toContain('Vim Mode'); // Settings section active
452
- expect(lastFrame()).toContain(' Apply To'); // Scope section inactive
409
+ expect(lastFrame()).toContain('Vim Mode'); // Settings section active
410
+ expect(lastFrame()).toContain('Apply To'); // Scope section (don't rely on exact spacing)
453
411
  // This test validates the initial state - scope selection behavior
454
412
  // is complex due to keypress handling, so we focus on state validation
455
413
  unmount();
@@ -459,19 +417,23 @@ describe('SettingsDialog', () => {
459
417
  it('should show restart prompt for restart-required settings', async () => {
460
418
  const settings = createMockSettings();
461
419
  const onRestartRequest = vi.fn();
462
- const { unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: () => { }, onRestartRequest: onRestartRequest }) }));
420
+ const { unmount } = renderDialog(settings, vi.fn(), {
421
+ onRestartRequest,
422
+ });
463
423
  // This test would need to trigger a restart-required setting change
464
424
  // The exact steps depend on which settings require restart
465
- await wait();
466
425
  unmount();
467
426
  });
468
427
  it('should handle restart request when r is pressed', async () => {
469
428
  const settings = createMockSettings();
470
429
  const onRestartRequest = vi.fn();
471
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: () => { }, onRestartRequest: onRestartRequest }) }));
430
+ const { stdin, unmount } = renderDialog(settings, vi.fn(), {
431
+ onRestartRequest,
432
+ });
472
433
  // Press 'r' key (this would only work if restart prompt is showing)
473
- stdin.write('r');
474
- await wait();
434
+ act(() => {
435
+ stdin.write('r');
436
+ });
475
437
  // If restart prompt was showing, onRestartRequest should be called
476
438
  unmount();
477
439
  });
@@ -480,7 +442,7 @@ describe('SettingsDialog', () => {
480
442
  it('should call onSelect with undefined when Escape is pressed', async () => {
481
443
  const settings = createMockSettings();
482
444
  const onSelect = vi.fn();
483
- const { lastFrame, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
445
+ const { lastFrame, unmount } = renderDialog(settings, onSelect);
484
446
  // Wait for initial render
485
447
  await waitFor(() => {
486
448
  expect(lastFrame()).toContain('Hide Window Title');
@@ -497,13 +459,12 @@ describe('SettingsDialog', () => {
497
459
  it('should persist settings across scope changes', async () => {
498
460
  const settings = createMockSettings({ vimMode: true });
499
461
  const onSelect = vi.fn();
500
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
501
- // Switch to scope selector
502
- stdin.write(TerminalKeys.TAB); // Tab
503
- await wait();
504
- // Change scope
505
- stdin.write('2'); // Select workspace scope
506
- await wait();
462
+ const { stdin, unmount } = renderDialog(settings, onSelect);
463
+ // Switch to scope selector and change scope
464
+ act(() => {
465
+ stdin.write(TerminalKeys.TAB); // Tab
466
+ stdin.write('2'); // Select workspace scope
467
+ });
507
468
  // Settings should be reloaded for new scope
508
469
  unmount();
509
470
  });
@@ -512,7 +473,7 @@ describe('SettingsDialog', () => {
512
473
  { vimMode: false }, // System settings
513
474
  { autoUpdate: false });
514
475
  const onSelect = vi.fn();
515
- const { lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
476
+ const { lastFrame } = renderDialog(settings, onSelect);
516
477
  // Should show user scope values initially
517
478
  const output = lastFrame();
518
479
  expect(output).toContain('Settings');
@@ -523,10 +484,11 @@ describe('SettingsDialog', () => {
523
484
  mockToggleVimEnabled.mockRejectedValue(new Error('Toggle failed'));
524
485
  const settings = createMockSettings();
525
486
  const onSelect = vi.fn();
526
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
487
+ const { stdin, unmount } = renderDialog(settings, onSelect);
527
488
  // Try to toggle a setting (this might trigger vim mode toggle)
528
- stdin.write(TerminalKeys.ENTER); // Enter
529
- await wait();
489
+ act(() => {
490
+ stdin.write(TerminalKeys.ENTER); // Enter
491
+ });
530
492
  // Should not crash
531
493
  unmount();
532
494
  });
@@ -535,27 +497,26 @@ describe('SettingsDialog', () => {
535
497
  it('should track modified settings correctly', async () => {
536
498
  const settings = createMockSettings();
537
499
  const onSelect = vi.fn();
538
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
539
- // Toggle a setting
540
- stdin.write(TerminalKeys.ENTER); // Enter
541
- await wait();
542
- // Toggle another setting
543
- stdin.write(TerminalKeys.DOWN_ARROW); // Down
544
- await wait();
545
- stdin.write(TerminalKeys.ENTER); // Enter
546
- await wait();
500
+ const { stdin, unmount } = renderDialog(settings, onSelect);
501
+ // Toggle a setting, then toggle another setting
502
+ act(() => {
503
+ stdin.write(TerminalKeys.ENTER); // Enter
504
+ stdin.write(TerminalKeys.DOWN_ARROW); // Down
505
+ stdin.write(TerminalKeys.ENTER); // Enter
506
+ });
547
507
  // Should track multiple modified settings
548
508
  unmount();
549
509
  });
550
510
  it('should handle scrolling when there are many settings', async () => {
551
511
  const settings = createMockSettings();
552
512
  const onSelect = vi.fn();
553
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
513
+ const { stdin, unmount } = renderDialog(settings, onSelect);
554
514
  // Navigate down many times to test scrolling
555
- for (let i = 0; i < 10; i++) {
556
- stdin.write(TerminalKeys.DOWN_ARROW); // Down arrow
557
- await wait(10);
558
- }
515
+ act(() => {
516
+ for (let i = 0; i < 10; i++) {
517
+ stdin.write(TerminalKeys.DOWN_ARROW); // Down arrow
518
+ }
519
+ });
559
520
  unmount();
560
521
  });
561
522
  });
@@ -566,8 +527,9 @@ describe('SettingsDialog', () => {
566
527
  const { stdin, unmount } = render(_jsx(VimModeProvider, { settings: settings, children: _jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }) }));
567
528
  // Navigate to and toggle vim mode setting
568
529
  // This would require knowing the exact position of vim mode setting
569
- stdin.write(TerminalKeys.ENTER); // Enter
570
- await wait();
530
+ act(() => {
531
+ stdin.write(TerminalKeys.ENTER); // Enter
532
+ });
571
533
  unmount();
572
534
  });
573
535
  });
@@ -577,7 +539,7 @@ describe('SettingsDialog', () => {
577
539
  { hideWindowTitle: true }, // System settings
578
540
  { ideMode: false });
579
541
  const onSelect = vi.fn();
580
- const { lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
542
+ const { lastFrame } = renderDialog(settings, onSelect);
581
543
  const output = lastFrame();
582
544
  // Should contain settings labels
583
545
  expect(output).toContain('Settings');
@@ -585,28 +547,30 @@ describe('SettingsDialog', () => {
585
547
  it('should handle immediate settings save for non-restart-required settings', async () => {
586
548
  const settings = createMockSettings();
587
549
  const onSelect = vi.fn();
588
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
550
+ const { stdin, unmount } = renderDialog(settings, onSelect);
589
551
  // Toggle a non-restart-required setting (like hideTips)
590
- stdin.write(TerminalKeys.ENTER); // Enter - toggle current setting
591
- await wait();
552
+ act(() => {
553
+ stdin.write(TerminalKeys.ENTER); // Enter - toggle current setting
554
+ });
592
555
  // Should save immediately without showing restart prompt
593
556
  unmount();
594
557
  });
595
558
  it('should show restart prompt for restart-required settings', async () => {
596
559
  const settings = createMockSettings();
597
560
  const onSelect = vi.fn();
598
- const { lastFrame, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
561
+ const { lastFrame, unmount } = renderDialog(settings, onSelect);
599
562
  // This test would need to navigate to a specific restart-required setting
600
563
  // Since we can't easily target specific settings, we test the general behavior
601
- await wait();
602
564
  // Should not show restart prompt initially
603
- expect(lastFrame()).not.toContain('To see changes, Gemini CLI must be restarted');
565
+ await waitFor(() => {
566
+ expect(lastFrame()).not.toContain('To see changes, Gemini CLI must be restarted');
567
+ });
604
568
  unmount();
605
569
  });
606
570
  it('should clear restart prompt when switching scopes', async () => {
607
571
  const settings = createMockSettings();
608
572
  const onSelect = vi.fn();
609
- const { unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
573
+ const { unmount } = renderDialog(settings, onSelect);
610
574
  // Restart prompt should be cleared when switching scopes
611
575
  unmount();
612
576
  });
@@ -616,7 +580,7 @@ describe('SettingsDialog', () => {
616
580
  const settings = createMockSettings({}, { vimMode: true, hideWindowTitle: false }, // System settings
617
581
  {});
618
582
  const onSelect = vi.fn();
619
- const { lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
583
+ const { lastFrame } = renderDialog(settings, onSelect);
620
584
  const output = lastFrame();
621
585
  // Settings should show inherited values
622
586
  expect(output).toContain('Settings');
@@ -626,89 +590,69 @@ describe('SettingsDialog', () => {
626
590
  { vimMode: true }, // System default
627
591
  {});
628
592
  const onSelect = vi.fn();
629
- const { lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
593
+ const { lastFrame } = renderDialog(settings, onSelect);
630
594
  const output = lastFrame();
631
595
  // Should show settings with override indicators
632
596
  expect(output).toContain('Settings');
633
597
  });
634
598
  });
635
599
  describe('Race Condition Regression Tests', () => {
636
- it('should not reset sibling settings when toggling a nested setting multiple times', async () => {
637
- vi.mocked(saveModifiedSettings).mockClear();
638
- vi.mocked(getSettingsSchema).mockReturnValue(TOOLS_SHELL_FAKE_SCHEMA);
639
- const settings = createMockSettings({
640
- tools: {
641
- shell: {
642
- showColor: false,
643
- enableInteractiveShell: true,
644
- },
600
+ it.each([
601
+ {
602
+ name: 'not reset sibling settings when toggling a nested setting multiple times',
603
+ toggleCount: 5,
604
+ shellSettings: {
605
+ showColor: false,
606
+ enableInteractiveShell: true,
645
607
  },
646
- });
647
- const onSelect = vi.fn();
648
- const component = (_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
649
- const { stdin, unmount } = render(component);
650
- await wait();
651
- // Toggle showColor 5 times to trigger race condition
652
- for (let i = 0; i < 5; i++) {
653
- act(() => {
654
- stdin.write(TerminalKeys.ENTER);
655
- });
656
- await wait(50);
657
- }
658
- await waitFor(() => {
659
- expect(vi.mocked(saveModifiedSettings).mock.calls.length).toBeGreaterThan(0);
660
- });
661
- // Verify sibling settings are preserved
662
- const calls = vi.mocked(saveModifiedSettings).mock.calls;
663
- calls.forEach((call) => {
664
- const [modifiedKeys, pendingSettings] = call;
665
- if (modifiedKeys.has('tools.shell.showColor')) {
666
- expect(pendingSettings.tools?.shell?.enableInteractiveShell).toBe(true);
667
- expect(modifiedKeys.has('tools.shell.enableInteractiveShell')).toBe(false);
668
- }
669
- });
670
- expect(calls.length).toBeGreaterThan(0);
671
- unmount();
672
- });
673
- it('should preserve multiple sibling settings in nested objects during rapid toggles', async () => {
608
+ expectedSiblings: {
609
+ enableInteractiveShell: true,
610
+ },
611
+ },
612
+ {
613
+ name: 'preserve multiple sibling settings in nested objects during rapid toggles',
614
+ toggleCount: 3,
615
+ shellSettings: {
616
+ showColor: false,
617
+ enableInteractiveShell: true,
618
+ pager: 'less',
619
+ },
620
+ expectedSiblings: {
621
+ enableInteractiveShell: true,
622
+ pager: 'less',
623
+ },
624
+ },
625
+ ])('should $name', async ({ toggleCount, shellSettings, expectedSiblings }) => {
674
626
  vi.mocked(saveModifiedSettings).mockClear();
675
627
  vi.mocked(getSettingsSchema).mockReturnValue(TOOLS_SHELL_FAKE_SCHEMA);
676
628
  const settings = createMockSettings({
677
629
  tools: {
678
- shell: {
679
- showColor: false,
680
- enableInteractiveShell: true,
681
- pager: 'less',
682
- },
630
+ shell: shellSettings,
683
631
  },
684
632
  });
685
633
  const onSelect = vi.fn();
686
- const component = (_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
687
- const { stdin, unmount } = render(component);
688
- await wait();
689
- // Rapid toggles
690
- for (let i = 0; i < 3; i++) {
634
+ const { stdin, unmount } = renderDialog(settings, onSelect);
635
+ for (let i = 0; i < toggleCount; i++) {
691
636
  act(() => {
692
637
  stdin.write(TerminalKeys.ENTER);
693
638
  });
694
- await wait(30);
695
639
  }
696
640
  await waitFor(() => {
697
641
  expect(vi.mocked(saveModifiedSettings).mock.calls.length).toBeGreaterThan(0);
698
642
  });
699
- // Verify all siblings preserved
700
643
  const calls = vi.mocked(saveModifiedSettings).mock.calls;
701
644
  calls.forEach((call) => {
702
645
  const [modifiedKeys, pendingSettings] = call;
703
646
  if (modifiedKeys.has('tools.shell.showColor')) {
704
647
  const shellSettings = pendingSettings.tools?.shell;
705
- expect(shellSettings?.['enableInteractiveShell']).toBe(true);
706
- expect(shellSettings?.['pager']).toBe('less');
648
+ Object.entries(expectedSiblings).forEach(([key, value]) => {
649
+ expect(shellSettings?.[key]).toBe(value);
650
+ expect(modifiedKeys.has(`tools.shell.${key}`)).toBe(false);
651
+ });
707
652
  expect(modifiedKeys.size).toBe(1);
708
- expect(modifiedKeys.has('tools.shell.enableInteractiveShell')).toBe(false);
709
- expect(modifiedKeys.has('tools.shell.pager')).toBe(false);
710
653
  }
711
654
  });
655
+ expect(calls.length).toBeGreaterThan(0);
712
656
  unmount();
713
657
  });
714
658
  });
@@ -716,58 +660,52 @@ describe('SettingsDialog', () => {
716
660
  it('should handle rapid key presses gracefully', async () => {
717
661
  const settings = createMockSettings();
718
662
  const onSelect = vi.fn();
719
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
663
+ const { stdin, unmount } = renderDialog(settings, onSelect);
720
664
  // Rapid navigation
721
- for (let i = 0; i < 5; i++) {
722
- stdin.write(TerminalKeys.DOWN_ARROW);
723
- stdin.write(TerminalKeys.UP_ARROW);
724
- }
725
- await wait(100);
665
+ act(() => {
666
+ for (let i = 0; i < 5; i++) {
667
+ stdin.write(TerminalKeys.DOWN_ARROW);
668
+ stdin.write(TerminalKeys.UP_ARROW);
669
+ }
670
+ });
726
671
  // Should not crash
727
672
  unmount();
728
673
  });
729
- it('should handle Ctrl+C to reset current setting to default', async () => {
730
- const settings = createMockSettings({ vimMode: true }); // Start with vimMode enabled
731
- const onSelect = vi.fn();
732
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
733
- // Press Ctrl+C to reset current setting to default
734
- stdin.write('\u0003'); // Ctrl+C
735
- await wait();
736
- // Should reset the current setting to its default value
737
- unmount();
738
- });
739
- it('should handle Ctrl+L to reset current setting to default', async () => {
740
- const settings = createMockSettings({ vimMode: true }); // Start with vimMode enabled
674
+ it.each([
675
+ { key: 'Ctrl+C', code: '\u0003' },
676
+ { key: 'Ctrl+L', code: '\u000C' },
677
+ ])('should handle $key to reset current setting to default', async ({ code }) => {
678
+ const settings = createMockSettings({ vimMode: true });
741
679
  const onSelect = vi.fn();
742
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
743
- // Press Ctrl+L to reset current setting to default
744
- stdin.write('\u000C'); // Ctrl+L
745
- await wait();
680
+ const { stdin, unmount } = renderDialog(settings, onSelect);
681
+ act(() => {
682
+ stdin.write(code);
683
+ });
746
684
  // Should reset the current setting to its default value
747
685
  unmount();
748
686
  });
749
687
  it('should handle navigation when only one setting exists', async () => {
750
688
  const settings = createMockSettings();
751
689
  const onSelect = vi.fn();
752
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
690
+ const { stdin, unmount } = renderDialog(settings, onSelect);
753
691
  // Try to navigate when potentially at bounds
754
- stdin.write(TerminalKeys.DOWN_ARROW);
755
- await wait();
756
- stdin.write(TerminalKeys.UP_ARROW);
757
- await wait();
692
+ act(() => {
693
+ stdin.write(TerminalKeys.DOWN_ARROW);
694
+ stdin.write(TerminalKeys.UP_ARROW);
695
+ });
758
696
  unmount();
759
697
  });
760
698
  it('should properly handle Tab navigation between sections', async () => {
761
699
  const settings = createMockSettings();
762
700
  const onSelect = vi.fn();
763
- const { lastFrame, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
701
+ const { lastFrame, unmount } = renderDialog(settings, onSelect);
764
702
  // Wait for initial render
765
703
  await waitFor(() => {
766
704
  expect(lastFrame()).toContain('Vim Mode');
767
705
  });
768
706
  // Verify initial state: settings section active, scope section inactive
769
- expect(lastFrame()).toContain('Vim Mode'); // Settings section active
770
- expect(lastFrame()).toContain(' Apply To'); // Scope section inactive
707
+ expect(lastFrame()).toContain('Vim Mode'); // Settings section active
708
+ expect(lastFrame()).toContain('Apply To'); // Scope section (don't rely on exact spacing)
771
709
  // This test validates the rendered UI structure for tab navigation
772
710
  // Actual tab behavior testing is complex due to keypress handling
773
711
  unmount();
@@ -779,7 +717,7 @@ describe('SettingsDialog', () => {
779
717
  const settings = createMockSettings({ vimMode: null }, // Invalid value
780
718
  {}, {});
781
719
  const onSelect = vi.fn();
782
- const { lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
720
+ const { lastFrame } = renderDialog(settings, onSelect);
783
721
  // Should still render without crashing
784
722
  expect(lastFrame()).toContain('Settings');
785
723
  });
@@ -787,7 +725,7 @@ describe('SettingsDialog', () => {
787
725
  const settings = createMockSettings();
788
726
  const onSelect = vi.fn();
789
727
  // Should not crash even if some settings are missing definitions
790
- const { lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
728
+ const { lastFrame } = renderDialog(settings, onSelect);
791
729
  expect(lastFrame()).toContain('Settings');
792
730
  });
793
731
  });
@@ -795,17 +733,18 @@ describe('SettingsDialog', () => {
795
733
  it('should handle complete user workflow: navigate, toggle, change scope, exit', async () => {
796
734
  const settings = createMockSettings();
797
735
  const onSelect = vi.fn();
798
- const { lastFrame, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
736
+ const { lastFrame, unmount } = renderDialog(settings, onSelect);
799
737
  // Wait for initial render
800
738
  await waitFor(() => {
801
739
  expect(lastFrame()).toContain('Vim Mode');
802
740
  });
803
741
  // Verify the complete UI is rendered with all necessary sections
804
742
  expect(lastFrame()).toContain('Settings'); // Title
805
- expect(lastFrame()).toContain('Vim Mode'); // Active setting
743
+ expect(lastFrame()).toContain('Vim Mode'); // Active setting
806
744
  expect(lastFrame()).toContain('Apply To'); // Scope section
807
745
  expect(lastFrame()).toContain('User Settings'); // Scope options (no numbers when settings focused)
808
- expect(lastFrame()).toContain('(Use Enter to select, Tab to change focus, Esc to close)'); // Help text
746
+ // Use regex for more flexible help text matching
747
+ expect(lastFrame()).toMatch(/Enter.*select.*Tab.*focus.*Esc.*close/);
809
748
  // This test validates the complete UI structure is available for user workflow
810
749
  // Individual interactions are tested in focused unit tests
811
750
  unmount();
@@ -813,20 +752,15 @@ describe('SettingsDialog', () => {
813
752
  it('should allow changing multiple settings without losing pending changes', async () => {
814
753
  const settings = createMockSettings();
815
754
  const onSelect = vi.fn();
816
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
817
- // Toggle first setting (should require restart)
818
- stdin.write(TerminalKeys.ENTER); // Enter
819
- await wait();
820
- // Navigate to next setting and toggle it (should not require restart - e.g., vimMode)
821
- stdin.write(TerminalKeys.DOWN_ARROW); // Down
822
- await wait();
823
- stdin.write(TerminalKeys.ENTER); // Enter
824
- await wait();
825
- // Navigate to another setting and toggle it (should also require restart)
826
- stdin.write(TerminalKeys.DOWN_ARROW); // Down
827
- await wait();
828
- stdin.write(TerminalKeys.ENTER); // Enter
829
- await wait();
755
+ const { stdin, unmount } = renderDialog(settings, onSelect);
756
+ // Toggle multiple settings
757
+ act(() => {
758
+ stdin.write(TerminalKeys.ENTER); // Enter
759
+ stdin.write(TerminalKeys.DOWN_ARROW); // Down
760
+ stdin.write(TerminalKeys.ENTER); // Enter
761
+ stdin.write(TerminalKeys.DOWN_ARROW); // Down
762
+ stdin.write(TerminalKeys.ENTER); // Enter
763
+ });
830
764
  // The test verifies that all changes are preserved and the dialog still works
831
765
  // This tests the fix for the bug where changing one setting would reset all pending changes
832
766
  unmount();
@@ -834,28 +768,28 @@ describe('SettingsDialog', () => {
834
768
  it('should maintain state consistency during complex interactions', async () => {
835
769
  const settings = createMockSettings({ vimMode: true });
836
770
  const onSelect = vi.fn();
837
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
771
+ const { stdin, unmount } = renderDialog(settings, onSelect);
838
772
  // Multiple scope changes
839
- stdin.write(TerminalKeys.TAB); // Tab to scope
840
- await wait();
841
- stdin.write('2'); // Workspace
842
- await wait();
843
- stdin.write(TerminalKeys.TAB); // Tab to settings
844
- await wait();
845
- stdin.write(TerminalKeys.TAB); // Tab to scope
846
- await wait();
847
- stdin.write('1'); // User
848
- await wait();
773
+ act(() => {
774
+ stdin.write(TerminalKeys.TAB); // Tab to scope
775
+ stdin.write('2'); // Workspace
776
+ stdin.write(TerminalKeys.TAB); // Tab to settings
777
+ stdin.write(TerminalKeys.TAB); // Tab to scope
778
+ stdin.write('1'); // User
779
+ });
849
780
  // Should maintain consistent state
850
781
  unmount();
851
782
  });
852
783
  it('should handle restart workflow correctly', async () => {
853
784
  const settings = createMockSettings();
854
785
  const onRestartRequest = vi.fn();
855
- const { stdin, unmount } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: () => { }, onRestartRequest: onRestartRequest }) }));
786
+ const { stdin, unmount } = renderDialog(settings, vi.fn(), {
787
+ onRestartRequest,
788
+ });
856
789
  // This would test the restart workflow if we could trigger it
857
- stdin.write('r'); // Try restart key
858
- await wait();
790
+ act(() => {
791
+ stdin.write('r'); // Try restart key
792
+ });
859
793
  // Without restart prompt showing, this should have no effect
860
794
  expect(onRestartRequest).not.toHaveBeenCalled();
861
795
  unmount();
@@ -866,282 +800,244 @@ describe('SettingsDialog', () => {
866
800
  let settings = createMockSettings({ 'a.string.setting': 'initial' });
867
801
  const onSelect = vi.fn();
868
802
  const { stdin, unmount, rerender } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
869
- // Wait for the dialog to render
870
- await wait();
871
803
  // Navigate to the last setting
872
- for (let i = 0; i < 20; i++) {
873
- stdin.write('j'); // Down
874
- await wait(10);
875
- }
876
- // Press Enter to start editing
877
- stdin.write('\r');
878
- await wait();
879
- // Type a new value
880
- stdin.write('new value');
881
- await wait();
882
- // Press Enter to commit
883
- stdin.write('\r');
884
- await wait();
804
+ act(() => {
805
+ for (let i = 0; i < 20; i++) {
806
+ stdin.write('j'); // Down
807
+ }
808
+ });
809
+ // Press Enter to start editing, type new value, and commit
810
+ act(() => {
811
+ stdin.write('\r'); // Start editing
812
+ stdin.write('new value');
813
+ stdin.write('\r'); // Commit
814
+ });
885
815
  settings = createMockSettings({ 'a.string.setting': 'new value' }, {}, {});
886
816
  rerender(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
887
- await wait();
888
817
  // Press Escape to exit
889
- stdin.write('\u001B');
890
- await wait();
891
- expect(onSelect).toHaveBeenCalledWith(undefined, 'User');
818
+ act(() => {
819
+ stdin.write('\u001B');
820
+ });
821
+ await waitFor(() => {
822
+ expect(onSelect).toHaveBeenCalledWith(undefined, 'User');
823
+ });
892
824
  unmount();
893
825
  });
894
826
  });
895
827
  describe('Snapshot Tests', () => {
896
828
  /**
897
829
  * Snapshot tests for SettingsDialog component using ink-testing-library.
898
- * These tests capture the visual output of the component in various states:
899
- *
900
- * - Default rendering with no custom settings
901
- * - Various combinations of boolean settings (enabled/disabled)
902
- * - Mixed boolean and number settings configurations
903
- * - Different focus states (settings vs scope selector)
904
- * - Different scope selections (User, System, Workspace)
905
- * - Accessibility settings enabled
906
- * - File filtering configurations
907
- * - Tools and security settings
908
- * - All settings disabled state
909
- *
830
+ * These tests capture the visual output of the component in various states.
910
831
  * The snapshots help ensure UI consistency and catch unintended visual changes.
911
832
  */
912
- it('should render default state correctly', () => {
913
- const settings = createMockSettings();
914
- const onSelect = vi.fn();
915
- const { lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
916
- expect(lastFrame()).toMatchSnapshot();
917
- });
918
- it('should render with various boolean settings enabled', () => {
919
- const settings = createMockSettings({
920
- general: {
921
- vimMode: true,
922
- disableAutoUpdate: true,
923
- debugKeystrokeLogging: true,
924
- enablePromptCompletion: true,
925
- },
926
- ui: {
927
- hideWindowTitle: true,
928
- hideTips: true,
929
- showMemoryUsage: true,
930
- showLineNumbers: true,
931
- showCitations: true,
932
- accessibility: {
933
- disableLoadingPhrases: true,
934
- screenReader: true,
833
+ it.each([
834
+ {
835
+ name: 'default state',
836
+ userSettings: {},
837
+ systemSettings: {},
838
+ workspaceSettings: {},
839
+ stdinActions: undefined,
840
+ },
841
+ {
842
+ name: 'various boolean settings enabled',
843
+ userSettings: {
844
+ general: {
845
+ vimMode: true,
846
+ disableAutoUpdate: true,
847
+ debugKeystrokeLogging: true,
848
+ enablePromptCompletion: true,
935
849
  },
936
- },
937
- ide: {
938
- enabled: true,
939
- },
940
- context: {
941
- loadMemoryFromIncludeDirectories: true,
942
- fileFiltering: {
943
- respectGitIgnore: true,
944
- respectGeminiIgnore: true,
945
- enableRecursiveFileSearch: true,
946
- disableFuzzySearch: false,
850
+ ui: {
851
+ hideWindowTitle: true,
852
+ hideTips: true,
853
+ showMemoryUsage: true,
854
+ showLineNumbers: true,
855
+ showCitations: true,
856
+ accessibility: {
857
+ disableLoadingPhrases: true,
858
+ screenReader: true,
859
+ },
947
860
  },
948
- },
949
- tools: {
950
- enableInteractiveShell: true,
951
- autoAccept: true,
952
- useRipgrep: true,
953
- },
954
- security: {
955
- folderTrust: {
861
+ ide: {
956
862
  enabled: true,
957
863
  },
864
+ context: {
865
+ loadMemoryFromIncludeDirectories: true,
866
+ fileFiltering: {
867
+ respectGitIgnore: true,
868
+ respectGeminiIgnore: true,
869
+ enableRecursiveFileSearch: true,
870
+ disableFuzzySearch: false,
871
+ },
872
+ },
873
+ tools: {
874
+ enableInteractiveShell: true,
875
+ autoAccept: true,
876
+ useRipgrep: true,
877
+ },
878
+ security: {
879
+ folderTrust: {
880
+ enabled: true,
881
+ },
882
+ },
958
883
  },
959
- });
960
- const onSelect = vi.fn();
961
- const { lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
962
- expect(lastFrame()).toMatchSnapshot();
963
- });
964
- it('should render with mixed boolean and number settings', () => {
965
- const settings = createMockSettings({
966
- general: {
967
- vimMode: false,
968
- disableAutoUpdate: true,
969
- },
970
- ui: {
971
- showMemoryUsage: true,
972
- hideWindowTitle: false,
973
- },
974
- tools: {
975
- truncateToolOutputThreshold: 50000,
976
- truncateToolOutputLines: 1000,
977
- },
978
- context: {
979
- discoveryMaxDirs: 500,
980
- },
981
- model: {
982
- maxSessionTurns: 100,
983
- skipNextSpeakerCheck: false,
984
- },
985
- });
986
- const onSelect = vi.fn();
987
- const { lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
988
- expect(lastFrame()).toMatchSnapshot();
989
- });
990
- it('should render focused on scope selector', () => {
991
- const settings = createMockSettings();
992
- const onSelect = vi.fn();
993
- const { lastFrame, stdin } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
994
- // Switch focus to scope selector with Tab
995
- stdin.write('\t');
996
- expect(lastFrame()).toMatchSnapshot();
997
- });
998
- it('should render with different scope selected (System)', () => {
999
- const settings = createMockSettings({}, // userSettings
884
+ systemSettings: {},
885
+ workspaceSettings: {},
886
+ stdinActions: undefined,
887
+ },
1000
888
  {
1001
- // systemSettings
1002
- general: {
1003
- vimMode: true,
1004
- disableAutoUpdate: false,
1005
- },
1006
- ui: {
1007
- showMemoryUsage: true,
889
+ name: 'mixed boolean and number settings',
890
+ userSettings: {
891
+ general: {
892
+ vimMode: false,
893
+ disableAutoUpdate: true,
894
+ },
895
+ ui: {
896
+ showMemoryUsage: true,
897
+ hideWindowTitle: false,
898
+ },
899
+ tools: {
900
+ truncateToolOutputThreshold: 50000,
901
+ truncateToolOutputLines: 1000,
902
+ },
903
+ context: {
904
+ discoveryMaxDirs: 500,
905
+ },
906
+ model: {
907
+ maxSessionTurns: 100,
908
+ skipNextSpeakerCheck: false,
909
+ },
1008
910
  },
1009
- });
1010
- const onSelect = vi.fn();
1011
- const { lastFrame, stdin } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
1012
- // Switch to scope selector
1013
- stdin.write('\t');
1014
- // Navigate to System scope
1015
- stdin.write('ArrowDown');
1016
- stdin.write('\r'); // Enter to select
1017
- expect(lastFrame()).toMatchSnapshot();
1018
- });
1019
- it('should render with different scope selected (Workspace)', () => {
1020
- const settings = createMockSettings({}, // userSettings
1021
- {}, // systemSettings
911
+ systemSettings: {},
912
+ workspaceSettings: {},
913
+ stdinActions: undefined,
914
+ },
1022
915
  {
1023
- // workspaceSettings
1024
- general: {
1025
- vimMode: false,
1026
- debugKeystrokeLogging: true,
1027
- },
1028
- tools: {
1029
- useRipgrep: true,
1030
- enableInteractiveShell: false,
916
+ name: 'focused on scope selector',
917
+ userSettings: {},
918
+ systemSettings: {},
919
+ workspaceSettings: {},
920
+ stdinActions: (stdin) => {
921
+ act(() => {
922
+ stdin.write('\t');
923
+ });
1031
924
  },
1032
- });
1033
- const onSelect = vi.fn();
1034
- const { lastFrame, stdin } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
1035
- // Switch to scope selector
1036
- stdin.write('\t');
1037
- // Navigate to Workspace scope (down twice)
1038
- stdin.write('ArrowDown');
1039
- stdin.write('ArrowDown');
1040
- stdin.write('\r'); // Enter to select
1041
- expect(lastFrame()).toMatchSnapshot();
1042
- });
1043
- it('should render with accessibility settings enabled', () => {
1044
- const settings = createMockSettings({
1045
- ui: {
1046
- accessibility: {
1047
- disableLoadingPhrases: true,
1048
- screenReader: true,
925
+ },
926
+ {
927
+ name: 'accessibility settings enabled',
928
+ userSettings: {
929
+ ui: {
930
+ accessibility: {
931
+ disableLoadingPhrases: true,
932
+ screenReader: true,
933
+ },
934
+ showMemoryUsage: true,
935
+ showLineNumbers: true,
1049
936
  },
1050
- showMemoryUsage: true,
1051
- showLineNumbers: true,
1052
- },
1053
- general: {
1054
- vimMode: true,
1055
- },
1056
- });
1057
- const onSelect = vi.fn();
1058
- const { lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
1059
- expect(lastFrame()).toMatchSnapshot();
1060
- });
1061
- it('should render with file filtering settings configured', () => {
1062
- const settings = createMockSettings({
1063
- context: {
1064
- fileFiltering: {
1065
- respectGitIgnore: false,
1066
- respectGeminiIgnore: true,
1067
- enableRecursiveFileSearch: false,
1068
- disableFuzzySearch: true,
937
+ general: {
938
+ vimMode: true,
1069
939
  },
1070
- loadMemoryFromIncludeDirectories: true,
1071
- discoveryMaxDirs: 100,
1072
- },
1073
- });
1074
- const onSelect = vi.fn();
1075
- const { lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
1076
- expect(lastFrame()).toMatchSnapshot();
1077
- });
1078
- it('should render with tools and security settings', () => {
1079
- const settings = createMockSettings({
1080
- tools: {
1081
- enableInteractiveShell: true,
1082
- autoAccept: false,
1083
- useRipgrep: true,
1084
- truncateToolOutputThreshold: 25000,
1085
- truncateToolOutputLines: 500,
1086
940
  },
1087
- security: {
1088
- folderTrust: {
1089
- enabled: true,
941
+ systemSettings: {},
942
+ workspaceSettings: {},
943
+ stdinActions: undefined,
944
+ },
945
+ {
946
+ name: 'file filtering settings configured',
947
+ userSettings: {
948
+ context: {
949
+ fileFiltering: {
950
+ respectGitIgnore: false,
951
+ respectGeminiIgnore: true,
952
+ enableRecursiveFileSearch: false,
953
+ disableFuzzySearch: true,
954
+ },
955
+ loadMemoryFromIncludeDirectories: true,
956
+ discoveryMaxDirs: 100,
1090
957
  },
1091
958
  },
1092
- model: {
1093
- maxSessionTurns: 50,
1094
- skipNextSpeakerCheck: true,
1095
- },
1096
- });
1097
- const onSelect = vi.fn();
1098
- const { lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
1099
- expect(lastFrame()).toMatchSnapshot();
1100
- });
1101
- it('should render with all boolean settings disabled', () => {
1102
- const settings = createMockSettings({
1103
- general: {
1104
- vimMode: false,
1105
- disableAutoUpdate: false,
1106
- debugKeystrokeLogging: false,
1107
- enablePromptCompletion: false,
1108
- },
1109
- ui: {
1110
- hideWindowTitle: false,
1111
- hideTips: false,
1112
- showMemoryUsage: false,
1113
- showLineNumbers: false,
1114
- showCitations: false,
1115
- accessibility: {
1116
- disableLoadingPhrases: false,
1117
- screenReader: false,
959
+ systemSettings: {},
960
+ workspaceSettings: {},
961
+ stdinActions: undefined,
962
+ },
963
+ {
964
+ name: 'tools and security settings',
965
+ userSettings: {
966
+ tools: {
967
+ enableInteractiveShell: true,
968
+ autoAccept: false,
969
+ useRipgrep: true,
970
+ truncateToolOutputThreshold: 25000,
971
+ truncateToolOutputLines: 500,
1118
972
  },
1119
- },
1120
- ide: {
1121
- enabled: false,
1122
- },
1123
- context: {
1124
- loadMemoryFromIncludeDirectories: false,
1125
- fileFiltering: {
1126
- respectGitIgnore: false,
1127
- respectGeminiIgnore: false,
1128
- enableRecursiveFileSearch: false,
1129
- disableFuzzySearch: false,
973
+ security: {
974
+ folderTrust: {
975
+ enabled: true,
976
+ },
977
+ },
978
+ model: {
979
+ maxSessionTurns: 50,
980
+ skipNextSpeakerCheck: true,
1130
981
  },
1131
982
  },
1132
- tools: {
1133
- enableInteractiveShell: false,
1134
- autoAccept: false,
1135
- useRipgrep: false,
1136
- },
1137
- security: {
1138
- folderTrust: {
983
+ systemSettings: {},
984
+ workspaceSettings: {},
985
+ stdinActions: undefined,
986
+ },
987
+ {
988
+ name: 'all boolean settings disabled',
989
+ userSettings: {
990
+ general: {
991
+ vimMode: false,
992
+ disableAutoUpdate: false,
993
+ debugKeystrokeLogging: false,
994
+ enablePromptCompletion: false,
995
+ },
996
+ ui: {
997
+ hideWindowTitle: false,
998
+ hideTips: false,
999
+ showMemoryUsage: false,
1000
+ showLineNumbers: false,
1001
+ showCitations: false,
1002
+ accessibility: {
1003
+ disableLoadingPhrases: false,
1004
+ screenReader: false,
1005
+ },
1006
+ },
1007
+ ide: {
1139
1008
  enabled: false,
1140
1009
  },
1010
+ context: {
1011
+ loadMemoryFromIncludeDirectories: false,
1012
+ fileFiltering: {
1013
+ respectGitIgnore: false,
1014
+ respectGeminiIgnore: false,
1015
+ enableRecursiveFileSearch: false,
1016
+ disableFuzzySearch: false,
1017
+ },
1018
+ },
1019
+ tools: {
1020
+ enableInteractiveShell: false,
1021
+ autoAccept: false,
1022
+ useRipgrep: false,
1023
+ },
1024
+ security: {
1025
+ folderTrust: {
1026
+ enabled: false,
1027
+ },
1028
+ },
1141
1029
  },
1142
- });
1030
+ systemSettings: {},
1031
+ workspaceSettings: {},
1032
+ stdinActions: undefined,
1033
+ },
1034
+ ])('should render $name correctly', ({ userSettings, systemSettings, workspaceSettings, stdinActions }) => {
1035
+ const settings = createMockSettings(userSettings, systemSettings, workspaceSettings);
1143
1036
  const onSelect = vi.fn();
1144
- const { lastFrame } = render(_jsx(KeypressProvider, { kittyProtocolEnabled: false, children: _jsx(SettingsDialog, { settings: settings, onSelect: onSelect }) }));
1037
+ const { lastFrame, stdin } = renderDialog(settings, onSelect);
1038
+ if (stdinActions) {
1039
+ stdinActions(stdin);
1040
+ }
1145
1041
  expect(lastFrame()).toMatchSnapshot();
1146
1042
  });
1147
1043
  });