@vybestack/llxprt-code 0.5.0 → 0.6.0

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 (515) hide show
  1. package/README.md +0 -244
  2. package/dist/package.json +15 -6
  3. package/dist/src/auth/gemini-oauth-provider.d.ts +18 -0
  4. package/dist/src/auth/gemini-oauth-provider.js +140 -78
  5. package/dist/src/auth/gemini-oauth-provider.js.map +1 -1
  6. package/dist/src/auth/local-oauth-callback.spec.js +29 -2
  7. package/dist/src/auth/local-oauth-callback.spec.js.map +1 -1
  8. package/dist/src/commands/extensions/disable.d.ts +1 -2
  9. package/dist/src/commands/extensions/disable.js +15 -3
  10. package/dist/src/commands/extensions/disable.js.map +1 -1
  11. package/dist/src/commands/extensions/enable.d.ts +1 -2
  12. package/dist/src/commands/extensions/enable.js +17 -6
  13. package/dist/src/commands/extensions/enable.js.map +1 -1
  14. package/dist/src/commands/extensions/install.d.ts +3 -1
  15. package/dist/src/commands/extensions/install.js +63 -12
  16. package/dist/src/commands/extensions/install.js.map +1 -1
  17. package/dist/src/commands/extensions/install.test.js +166 -13
  18. package/dist/src/commands/extensions/install.test.js.map +1 -1
  19. package/dist/src/commands/extensions/link.js +2 -2
  20. package/dist/src/commands/extensions/link.js.map +1 -1
  21. package/dist/src/commands/extensions/list.d.ts +1 -1
  22. package/dist/src/commands/extensions/list.js +3 -2
  23. package/dist/src/commands/extensions/list.js.map +1 -1
  24. package/dist/src/commands/extensions/new.test.js +2 -2
  25. package/dist/src/commands/extensions/new.test.js.map +1 -1
  26. package/dist/src/commands/extensions/uninstall.js +1 -1
  27. package/dist/src/commands/extensions/uninstall.js.map +1 -1
  28. package/dist/src/commands/extensions/uninstall.test.js +4 -1
  29. package/dist/src/commands/extensions/uninstall.test.js.map +1 -1
  30. package/dist/src/commands/extensions/update.d.ts +2 -2
  31. package/dist/src/commands/extensions/update.js +68 -19
  32. package/dist/src/commands/extensions/update.js.map +1 -1
  33. package/dist/src/commands/mcp/add.js +6 -1
  34. package/dist/src/commands/mcp/add.js.map +1 -1
  35. package/dist/src/commands/mcp/list.js +3 -2
  36. package/dist/src/commands/mcp/list.js.map +1 -1
  37. package/dist/src/config/__tests__/profileBootstrap.test.js +1351 -1
  38. package/dist/src/config/__tests__/profileBootstrap.test.js.map +1 -1
  39. package/dist/src/config/config.d.ts +4 -1
  40. package/dist/src/config/config.js +172 -69
  41. package/dist/src/config/config.js.map +1 -1
  42. package/dist/src/config/config.loadMemory.test.js +6 -3
  43. package/dist/src/config/config.loadMemory.test.js.map +1 -1
  44. package/dist/src/config/extension.d.ts +48 -14
  45. package/dist/src/config/extension.js +263 -142
  46. package/dist/src/config/extension.js.map +1 -1
  47. package/dist/src/config/extensions/extensionEnablement.d.ts +47 -0
  48. package/dist/src/config/extensions/extensionEnablement.js +188 -0
  49. package/dist/src/config/extensions/extensionEnablement.js.map +1 -0
  50. package/dist/src/config/extensions/extensionEnablement.test.d.ts +6 -0
  51. package/dist/src/config/extensions/extensionEnablement.test.js +333 -0
  52. package/dist/src/config/extensions/extensionEnablement.test.js.map +1 -0
  53. package/dist/src/config/extensions/github.d.ts +37 -0
  54. package/dist/src/config/extensions/github.js +348 -0
  55. package/dist/src/config/extensions/github.js.map +1 -0
  56. package/dist/src/config/extensions/github.test.d.ts +6 -0
  57. package/dist/src/config/extensions/github.test.js +340 -0
  58. package/dist/src/config/extensions/github.test.js.map +1 -0
  59. package/dist/src/config/extensions/update.d.ts +19 -0
  60. package/dist/src/config/extensions/update.js +118 -0
  61. package/dist/src/config/extensions/update.js.map +1 -0
  62. package/dist/src/config/extensions/update.test.d.ts +6 -0
  63. package/dist/src/config/extensions/update.test.js +340 -0
  64. package/dist/src/config/extensions/update.test.js.map +1 -0
  65. package/dist/src/config/extensions/variableSchema.d.ts +8 -0
  66. package/dist/src/config/extensions/variableSchema.js +4 -0
  67. package/dist/src/config/extensions/variableSchema.js.map +1 -1
  68. package/dist/src/config/keyBindings.d.ts +1 -0
  69. package/dist/src/config/keyBindings.js +3 -1
  70. package/dist/src/config/keyBindings.js.map +1 -1
  71. package/dist/src/config/paths.d.ts +8 -0
  72. package/dist/src/config/paths.js +11 -0
  73. package/dist/src/config/paths.js.map +1 -0
  74. package/dist/src/config/profileBootstrap.d.ts +13 -0
  75. package/dist/src/config/profileBootstrap.js +369 -15
  76. package/dist/src/config/profileBootstrap.js.map +1 -1
  77. package/dist/src/config/settings.d.ts +14 -4
  78. package/dist/src/config/settings.js +161 -99
  79. package/dist/src/config/settings.js.map +1 -1
  80. package/dist/src/config/settingsSchema.d.ts +510 -216
  81. package/dist/src/config/settingsSchema.js +468 -214
  82. package/dist/src/config/settingsSchema.js.map +1 -1
  83. package/dist/src/config/settingsSchema.test.js +18 -31
  84. package/dist/src/config/settingsSchema.test.js.map +1 -1
  85. package/dist/src/config/trustedFolders.d.ts +6 -3
  86. package/dist/src/config/trustedFolders.js +35 -13
  87. package/dist/src/config/trustedFolders.js.map +1 -1
  88. package/dist/src/config/trustedFolders.test.js +83 -9
  89. package/dist/src/config/trustedFolders.test.js.map +1 -1
  90. package/dist/src/coreToolToggle.test.d.ts +6 -0
  91. package/dist/src/coreToolToggle.test.js +427 -0
  92. package/dist/src/coreToolToggle.test.js.map +1 -0
  93. package/dist/src/extensions/extensionAutoUpdater.d.ts +76 -0
  94. package/dist/src/extensions/extensionAutoUpdater.js +279 -0
  95. package/dist/src/extensions/extensionAutoUpdater.js.map +1 -0
  96. package/dist/src/extensions/extensionAutoUpdater.test.d.ts +6 -0
  97. package/dist/src/extensions/extensionAutoUpdater.test.js +146 -0
  98. package/dist/src/extensions/extensionAutoUpdater.test.js.map +1 -0
  99. package/dist/src/gemini.js +93 -63
  100. package/dist/src/gemini.js.map +1 -1
  101. package/dist/src/gemini.test.js +121 -1
  102. package/dist/src/gemini.test.js.map +1 -1
  103. package/dist/src/generated/git-commit.d.ts +1 -1
  104. package/dist/src/generated/git-commit.js +1 -1
  105. package/dist/src/generated/git-commit.js.map +1 -1
  106. package/dist/src/integration-tests/cli-args.integration.test.js +299 -0
  107. package/dist/src/integration-tests/cli-args.integration.test.js.map +1 -1
  108. package/dist/src/nonInteractiveCli.d.ts +2 -1
  109. package/dist/src/nonInteractiveCli.js +29 -16
  110. package/dist/src/nonInteractiveCli.js.map +1 -1
  111. package/dist/src/nonInteractiveCliCommands.d.ts +17 -0
  112. package/dist/src/nonInteractiveCliCommands.js +81 -0
  113. package/dist/src/nonInteractiveCliCommands.js.map +1 -0
  114. package/dist/src/runtime/runtimeSettings.test.js +2 -0
  115. package/dist/src/runtime/runtimeSettings.test.js.map +1 -1
  116. package/dist/src/services/BuiltinCommandLoader.d.ts +3 -3
  117. package/dist/src/services/BuiltinCommandLoader.js +7 -0
  118. package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
  119. package/dist/src/services/BuiltinCommandLoader.test.js +37 -0
  120. package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -1
  121. package/dist/src/services/McpPromptLoader.js +39 -34
  122. package/dist/src/services/McpPromptLoader.js.map +1 -1
  123. package/dist/src/settings/ephemeralSettings.js +56 -0
  124. package/dist/src/settings/ephemeralSettings.js.map +1 -1
  125. package/dist/src/test-utils/createExtension.d.ts +15 -0
  126. package/dist/src/test-utils/createExtension.js +24 -0
  127. package/dist/src/test-utils/createExtension.js.map +1 -0
  128. package/dist/src/test-utils/mockCommandContext.js +4 -2
  129. package/dist/src/test-utils/mockCommandContext.js.map +1 -1
  130. package/dist/src/test-utils/render.d.ts +3 -1
  131. package/dist/src/test-utils/render.js +4 -1
  132. package/dist/src/test-utils/render.js.map +1 -1
  133. package/dist/src/ui/App.d.ts +18 -3
  134. package/dist/src/ui/App.js +32 -873
  135. package/dist/src/ui/App.js.map +1 -1
  136. package/dist/src/ui/AppContainer.d.ts +19 -0
  137. package/dist/src/ui/AppContainer.js +1187 -0
  138. package/dist/src/ui/AppContainer.js.map +1 -0
  139. package/dist/src/ui/IdeIntegrationNudge.d.ts +2 -2
  140. package/dist/src/ui/IdeIntegrationNudge.js +4 -7
  141. package/dist/src/ui/IdeIntegrationNudge.js.map +1 -1
  142. package/dist/src/ui/commands/chatCommand.js +214 -58
  143. package/dist/src/ui/commands/chatCommand.js.map +1 -1
  144. package/dist/src/ui/commands/clearCommand.js +1 -2
  145. package/dist/src/ui/commands/clearCommand.js.map +1 -1
  146. package/dist/src/ui/commands/diagnosticsCommand.js +2 -2
  147. package/dist/src/ui/commands/diagnosticsCommand.js.map +1 -1
  148. package/dist/src/ui/commands/directoryCommand.js +3 -2
  149. package/dist/src/ui/commands/directoryCommand.js.map +1 -1
  150. package/dist/src/ui/commands/docsCommand.js +1 -1
  151. package/dist/src/ui/commands/docsCommand.js.map +1 -1
  152. package/dist/src/ui/commands/extensionsCommand.d.ts +1 -1
  153. package/dist/src/ui/commands/extensionsCommand.js +92 -17
  154. package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
  155. package/dist/src/ui/commands/helpCommand.js +6 -5
  156. package/dist/src/ui/commands/helpCommand.js.map +1 -1
  157. package/dist/src/ui/commands/ideCommand.js +7 -7
  158. package/dist/src/ui/commands/ideCommand.js.map +1 -1
  159. package/dist/src/ui/commands/loggingCommand.js +1 -1
  160. package/dist/src/ui/commands/loggingCommand.js.map +1 -1
  161. package/dist/src/ui/commands/mcpCommand.js +11 -3
  162. package/dist/src/ui/commands/mcpCommand.js.map +1 -1
  163. package/dist/src/ui/commands/memoryCommand.js +21 -3
  164. package/dist/src/ui/commands/memoryCommand.js.map +1 -1
  165. package/dist/src/ui/commands/permissionsCommand.d.ts +7 -0
  166. package/dist/src/ui/commands/permissionsCommand.js +16 -0
  167. package/dist/src/ui/commands/permissionsCommand.js.map +1 -0
  168. package/dist/src/ui/commands/permissionsCommand.test.d.ts +6 -0
  169. package/dist/src/ui/commands/permissionsCommand.test.js +55 -0
  170. package/dist/src/ui/commands/permissionsCommand.test.js.map +1 -0
  171. package/dist/src/ui/commands/policiesCommand.d.ts +10 -0
  172. package/dist/src/ui/commands/policiesCommand.js +112 -0
  173. package/dist/src/ui/commands/policiesCommand.js.map +1 -0
  174. package/dist/src/ui/commands/policiesCommand.test.d.ts +6 -0
  175. package/dist/src/ui/commands/policiesCommand.test.js +224 -0
  176. package/dist/src/ui/commands/policiesCommand.test.js.map +1 -0
  177. package/dist/src/ui/commands/setCommand.js +105 -30
  178. package/dist/src/ui/commands/setCommand.js.map +1 -1
  179. package/dist/src/ui/commands/setCommand.test.js +1 -1
  180. package/dist/src/ui/commands/setCommand.test.js.map +1 -1
  181. package/dist/src/ui/commands/statsCommand.js +11 -1
  182. package/dist/src/ui/commands/statsCommand.js.map +1 -1
  183. package/dist/src/ui/commands/test/subagentCommand.test.js +6 -1
  184. package/dist/src/ui/commands/test/subagentCommand.test.js.map +1 -1
  185. package/dist/src/ui/commands/types.d.ts +19 -23
  186. package/dist/src/ui/commands/types.js +1 -1
  187. package/dist/src/ui/commands/types.js.map +1 -1
  188. package/dist/src/ui/commands/uiprofileCommand.d.ts +7 -0
  189. package/dist/src/ui/commands/uiprofileCommand.js +23 -0
  190. package/dist/src/ui/commands/uiprofileCommand.js.map +1 -0
  191. package/dist/src/ui/components/AuthDialog.js +4 -0
  192. package/dist/src/ui/components/AuthDialog.js.map +1 -1
  193. package/dist/src/ui/components/AuthDialog.test.js +32 -32
  194. package/dist/src/ui/components/AuthDialog.test.js.map +1 -1
  195. package/dist/src/ui/components/CacheStatsDisplay.d.ts +7 -0
  196. package/dist/src/ui/components/CacheStatsDisplay.js +35 -0
  197. package/dist/src/ui/components/CacheStatsDisplay.js.map +1 -0
  198. package/dist/src/ui/components/CacheStatsDisplay.test.d.ts +6 -0
  199. package/dist/src/ui/components/CacheStatsDisplay.test.js +118 -0
  200. package/dist/src/ui/components/CacheStatsDisplay.test.js.map +1 -0
  201. package/dist/src/ui/components/CliSpinner.d.ts +10 -0
  202. package/dist/src/ui/components/CliSpinner.js +20 -0
  203. package/dist/src/ui/components/CliSpinner.js.map +1 -0
  204. package/dist/src/ui/components/Composer.d.ts +17 -0
  205. package/dist/src/ui/components/Composer.js +16 -0
  206. package/dist/src/ui/components/Composer.js.map +1 -0
  207. package/dist/src/ui/components/ConsentPrompt.d.ts +13 -0
  208. package/dist/src/ui/components/ConsentPrompt.js +18 -0
  209. package/dist/src/ui/components/ConsentPrompt.js.map +1 -0
  210. package/dist/src/ui/components/ConsentPrompt.test.d.ts +6 -0
  211. package/dist/src/ui/components/ConsentPrompt.test.js +67 -0
  212. package/dist/src/ui/components/ConsentPrompt.test.js.map +1 -0
  213. package/dist/src/ui/components/DebugProfiler.d.ts +15 -0
  214. package/dist/src/ui/components/DebugProfiler.js +137 -13
  215. package/dist/src/ui/components/DebugProfiler.js.map +1 -1
  216. package/dist/src/ui/components/DebugProfiler.test.d.ts +6 -0
  217. package/dist/src/ui/components/DebugProfiler.test.js +131 -0
  218. package/dist/src/ui/components/DebugProfiler.test.js.map +1 -0
  219. package/dist/src/ui/components/DialogManager.d.ts +16 -0
  220. package/dist/src/ui/components/DialogManager.js +131 -0
  221. package/dist/src/ui/components/DialogManager.js.map +1 -0
  222. package/dist/src/ui/components/EditorSettingsDialog.js +18 -8
  223. package/dist/src/ui/components/EditorSettingsDialog.js.map +1 -1
  224. package/dist/src/ui/components/FolderTrustDialog.js +4 -0
  225. package/dist/src/ui/components/FolderTrustDialog.js.map +1 -1
  226. package/dist/src/ui/components/FolderTrustDialog.test.js +2 -2
  227. package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
  228. package/dist/src/ui/components/HistoryItemDisplay.d.ts +6 -2
  229. package/dist/src/ui/components/HistoryItemDisplay.js +10 -2
  230. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  231. package/dist/src/ui/components/HistoryItemDisplay.test.js +90 -10
  232. package/dist/src/ui/components/HistoryItemDisplay.test.js.map +1 -1
  233. package/dist/src/ui/components/InputPrompt.d.ts +6 -0
  234. package/dist/src/ui/components/InputPrompt.js +52 -18
  235. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  236. package/dist/src/ui/components/LoadProfileDialog.js +13 -9
  237. package/dist/src/ui/components/LoadProfileDialog.js.map +1 -1
  238. package/dist/src/ui/components/LoadingIndicator.js +1 -1
  239. package/dist/src/ui/components/LoadingIndicator.js.map +1 -1
  240. package/dist/src/ui/components/LoadingIndicator.test.js +6 -0
  241. package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -1
  242. package/dist/src/ui/components/LoggingDialog.js +14 -10
  243. package/dist/src/ui/components/LoggingDialog.js.map +1 -1
  244. package/dist/src/ui/components/Notifications.d.ts +14 -0
  245. package/dist/src/ui/components/Notifications.js +34 -0
  246. package/dist/src/ui/components/Notifications.js.map +1 -0
  247. package/dist/src/ui/components/OAuthCodeDialog.js +2 -1
  248. package/dist/src/ui/components/OAuthCodeDialog.js.map +1 -1
  249. package/dist/src/ui/components/PermissionsModifyTrustDialog.d.ts +14 -0
  250. package/dist/src/ui/components/PermissionsModifyTrustDialog.js +115 -0
  251. package/dist/src/ui/components/PermissionsModifyTrustDialog.js.map +1 -0
  252. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.d.ts +6 -0
  253. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +98 -0
  254. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +1 -0
  255. package/dist/src/ui/components/ProviderDialog.js +23 -18
  256. package/dist/src/ui/components/ProviderDialog.js.map +1 -1
  257. package/dist/src/ui/components/ProviderModelDialog.js +24 -18
  258. package/dist/src/ui/components/ProviderModelDialog.js.map +1 -1
  259. package/dist/src/ui/components/SettingsDialog.d.ts +12 -2
  260. package/dist/src/ui/components/SettingsDialog.js +253 -23
  261. package/dist/src/ui/components/SettingsDialog.js.map +1 -1
  262. package/dist/src/ui/components/SettingsDialog.test.js +90 -8
  263. package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
  264. package/dist/src/ui/components/ShellConfirmationDialog.js +3 -0
  265. package/dist/src/ui/components/ShellConfirmationDialog.js.map +1 -1
  266. package/dist/src/ui/components/ThemeDialog.js +6 -4
  267. package/dist/src/ui/components/ThemeDialog.js.map +1 -1
  268. package/dist/src/ui/components/ToolsDialog.js +6 -4
  269. package/dist/src/ui/components/ToolsDialog.js.map +1 -1
  270. package/dist/src/ui/components/WorkspaceMigrationDialog.js +5 -3
  271. package/dist/src/ui/components/WorkspaceMigrationDialog.js.map +1 -1
  272. package/dist/src/ui/components/messages/ToolConfirmationMessage.js +37 -6
  273. package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
  274. package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js +9 -0
  275. package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js.map +1 -1
  276. package/dist/src/ui/components/messages/ToolGroupMessage.js +7 -3
  277. package/dist/src/ui/components/messages/ToolGroupMessage.js.map +1 -1
  278. package/dist/src/ui/components/messages/ToolMessage.js +7 -3
  279. package/dist/src/ui/components/messages/ToolMessage.js.map +1 -1
  280. package/dist/src/ui/components/messages/WarningMessage.d.ts +11 -0
  281. package/dist/src/ui/components/messages/WarningMessage.js +10 -0
  282. package/dist/src/ui/components/messages/WarningMessage.js.map +1 -0
  283. package/dist/src/ui/components/messages/WarningMessage.test.d.ts +6 -0
  284. package/dist/src/ui/components/messages/WarningMessage.test.js +15 -0
  285. package/dist/src/ui/components/messages/WarningMessage.test.js.map +1 -0
  286. package/dist/src/ui/components/shared/BaseSelectionList.d.ts +38 -0
  287. package/dist/src/ui/components/shared/BaseSelectionList.js +76 -0
  288. package/dist/src/ui/components/shared/BaseSelectionList.js.map +1 -0
  289. package/dist/src/ui/components/shared/BaseSelectionList.test.d.ts +6 -0
  290. package/dist/src/ui/components/shared/BaseSelectionList.test.js +376 -0
  291. package/dist/src/ui/components/shared/BaseSelectionList.test.js.map +1 -0
  292. package/dist/src/ui/components/shared/RadioButtonSelect.d.ts +4 -5
  293. package/dist/src/ui/components/shared/RadioButtonSelect.js +11 -117
  294. package/dist/src/ui/components/shared/RadioButtonSelect.js.map +1 -1
  295. package/dist/src/ui/components/shared/RadioButtonSelect.test.d.ts +1 -1
  296. package/dist/src/ui/components/shared/RadioButtonSelect.test.js +116 -95
  297. package/dist/src/ui/components/shared/RadioButtonSelect.test.js.map +1 -1
  298. package/dist/src/ui/components/shared/text-buffer.d.ts +6 -0
  299. package/dist/src/ui/components/shared/text-buffer.js +71 -4
  300. package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
  301. package/dist/src/ui/components/views/ChatList.d.ts +12 -0
  302. package/dist/src/ui/components/views/ChatList.js +17 -0
  303. package/dist/src/ui/components/views/ChatList.js.map +1 -0
  304. package/dist/src/ui/components/views/ChatList.test.d.ts +6 -0
  305. package/dist/src/ui/components/views/ChatList.test.js +42 -0
  306. package/dist/src/ui/components/views/ChatList.test.js.map +1 -0
  307. package/dist/src/ui/constants.d.ts +1 -0
  308. package/dist/src/ui/constants.js +1 -0
  309. package/dist/src/ui/constants.js.map +1 -1
  310. package/dist/src/ui/contexts/FocusContext.d.ts +7 -0
  311. package/dist/src/ui/contexts/FocusContext.js +9 -0
  312. package/dist/src/ui/contexts/FocusContext.js.map +1 -0
  313. package/dist/src/ui/contexts/KeypressContext.d.ts +1 -1
  314. package/dist/src/ui/contexts/KeypressContext.js +63 -4
  315. package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
  316. package/dist/src/ui/contexts/KeypressContext.test.js +156 -0
  317. package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
  318. package/dist/src/ui/contexts/SessionContext.d.ts +6 -0
  319. package/dist/src/ui/contexts/SessionContext.js +107 -5
  320. package/dist/src/ui/contexts/SessionContext.js.map +1 -1
  321. package/dist/src/ui/contexts/UIActionsContext.d.ts +82 -0
  322. package/dist/src/ui/contexts/UIActionsContext.js +20 -0
  323. package/dist/src/ui/contexts/UIActionsContext.js.map +1 -0
  324. package/dist/src/ui/contexts/UIStateContext.d.ts +121 -0
  325. package/dist/src/ui/contexts/UIStateContext.js +20 -0
  326. package/dist/src/ui/contexts/UIStateContext.js.map +1 -0
  327. package/dist/src/ui/contexts/VimModeContext.js +4 -4
  328. package/dist/src/ui/contexts/VimModeContext.js.map +1 -1
  329. package/dist/src/ui/hooks/slashCommandProcessor.d.ts +29 -6
  330. package/dist/src/ui/hooks/slashCommandProcessor.js +150 -155
  331. package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
  332. package/dist/src/ui/hooks/useBracketedPaste.js +3 -4
  333. package/dist/src/ui/hooks/useBracketedPaste.js.map +1 -1
  334. package/dist/src/ui/hooks/useEditorSettings.js +1 -1
  335. package/dist/src/ui/hooks/useEditorSettings.js.map +1 -1
  336. package/dist/src/ui/hooks/useExtensionAutoUpdate.d.ts +13 -0
  337. package/dist/src/ui/hooks/useExtensionAutoUpdate.js +40 -0
  338. package/dist/src/ui/hooks/useExtensionAutoUpdate.js.map +1 -0
  339. package/dist/src/ui/hooks/useExtensionUpdates.d.ts +21 -0
  340. package/dist/src/ui/hooks/useExtensionUpdates.js +168 -0
  341. package/dist/src/ui/hooks/useExtensionUpdates.js.map +1 -0
  342. package/dist/src/ui/hooks/useExtensionUpdates.test.d.ts +6 -0
  343. package/dist/src/ui/hooks/useExtensionUpdates.test.js +243 -0
  344. package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +1 -0
  345. package/dist/src/ui/hooks/useFlickerDetector.d.ts +22 -0
  346. package/dist/src/ui/hooks/useFlickerDetector.js +38 -0
  347. package/dist/src/ui/hooks/useFlickerDetector.js.map +1 -0
  348. package/dist/src/ui/hooks/useFlickerDetector.test.d.ts +6 -0
  349. package/dist/src/ui/hooks/useFlickerDetector.test.js +142 -0
  350. package/dist/src/ui/hooks/useFlickerDetector.test.js.map +1 -0
  351. package/dist/src/ui/hooks/useGeminiStream.d.ts +1 -1
  352. package/dist/src/ui/hooks/useGeminiStream.integration.test.js +1 -1
  353. package/dist/src/ui/hooks/useGeminiStream.integration.test.js.map +1 -1
  354. package/dist/src/ui/hooks/useGeminiStream.js +41 -18
  355. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  356. package/dist/src/ui/hooks/useMemoryMonitor.d.ts +13 -0
  357. package/dist/src/ui/hooks/useMemoryMonitor.js +28 -0
  358. package/dist/src/ui/hooks/useMemoryMonitor.js.map +1 -0
  359. package/dist/src/ui/hooks/usePermissionsModifyTrust.d.ts +34 -0
  360. package/dist/src/ui/hooks/usePermissionsModifyTrust.js +90 -0
  361. package/dist/src/ui/hooks/usePermissionsModifyTrust.js.map +1 -0
  362. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.d.ts +6 -0
  363. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js +60 -0
  364. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js.map +1 -0
  365. package/dist/src/ui/hooks/useReactToolScheduler.d.ts +1 -1
  366. package/dist/src/ui/hooks/useReactToolScheduler.js +5 -1
  367. package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
  368. package/dist/src/ui/hooks/useSelectionList.d.ts +34 -0
  369. package/dist/src/ui/hooks/useSelectionList.js +292 -0
  370. package/dist/src/ui/hooks/useSelectionList.js.map +1 -0
  371. package/dist/src/ui/hooks/useSelectionList.test.d.ts +6 -0
  372. package/dist/src/ui/hooks/useSelectionList.test.js +726 -0
  373. package/dist/src/ui/hooks/useSelectionList.test.js.map +1 -0
  374. package/dist/src/ui/hooks/useShowMemoryCommand.js +1 -1
  375. package/dist/src/ui/hooks/useShowMemoryCommand.js.map +1 -1
  376. package/dist/src/ui/hooks/useStateAndRef.d.ts +1 -1
  377. package/dist/src/ui/hooks/useStateAndRef.js +2 -2
  378. package/dist/src/ui/hooks/useStateAndRef.js.map +1 -1
  379. package/dist/src/ui/hooks/useStaticHistoryRefresh.d.ts +13 -0
  380. package/dist/src/ui/hooks/useStaticHistoryRefresh.js +35 -0
  381. package/dist/src/ui/hooks/useStaticHistoryRefresh.js.map +1 -0
  382. package/dist/src/ui/hooks/useStaticHistoryRefresh.test.d.ts +6 -0
  383. package/dist/src/ui/hooks/useStaticHistoryRefresh.test.js +42 -0
  384. package/dist/src/ui/hooks/useStaticHistoryRefresh.test.js.map +1 -0
  385. package/dist/src/ui/hooks/useThemeCommand.js +7 -7
  386. package/dist/src/ui/hooks/useThemeCommand.js.map +1 -1
  387. package/dist/src/ui/hooks/useToolScheduler.test.js +17 -20
  388. package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
  389. package/dist/src/ui/keyMatchers.test.js +6 -0
  390. package/dist/src/ui/keyMatchers.test.js.map +1 -1
  391. package/dist/src/ui/layouts/DefaultAppLayout.d.ts +23 -0
  392. package/dist/src/ui/layouts/DefaultAppLayout.js +76 -0
  393. package/dist/src/ui/layouts/DefaultAppLayout.js.map +1 -0
  394. package/dist/src/ui/noninteractive/nonInteractiveUi.d.ts +12 -0
  395. package/dist/src/ui/noninteractive/nonInteractiveUi.js +31 -0
  396. package/dist/src/ui/noninteractive/nonInteractiveUi.js.map +1 -0
  397. package/dist/src/ui/privacy/CloudFreePrivacyNotice.js +2 -2
  398. package/dist/src/ui/privacy/CloudFreePrivacyNotice.js.map +1 -1
  399. package/dist/src/ui/privacy/MultiProviderPrivacyNotice.d.ts +11 -0
  400. package/dist/src/ui/privacy/MultiProviderPrivacyNotice.js +92 -0
  401. package/dist/src/ui/privacy/MultiProviderPrivacyNotice.js.map +1 -0
  402. package/dist/src/ui/privacy/MultiProviderPrivacyNotice.test.d.ts +6 -0
  403. package/dist/src/ui/privacy/MultiProviderPrivacyNotice.test.js +106 -0
  404. package/dist/src/ui/privacy/MultiProviderPrivacyNotice.test.js.map +1 -0
  405. package/dist/src/ui/privacy/PrivacyNotice.js +4 -9
  406. package/dist/src/ui/privacy/PrivacyNotice.js.map +1 -1
  407. package/dist/src/ui/state/extensions.d.ts +61 -0
  408. package/dist/src/ui/state/extensions.js +84 -0
  409. package/dist/src/ui/state/extensions.js.map +1 -0
  410. package/dist/src/ui/themes/theme.js +2 -2
  411. package/dist/src/ui/themes/theme.js.map +1 -1
  412. package/dist/src/ui/types.d.ts +58 -2
  413. package/dist/src/ui/types.js +6 -0
  414. package/dist/src/ui/types.js.map +1 -1
  415. package/dist/src/ui/utils/MarkdownDisplay.js +1 -2
  416. package/dist/src/ui/utils/MarkdownDisplay.js.map +1 -1
  417. package/dist/src/ui/utils/MarkdownDisplay.test.d.ts +1 -1
  418. package/dist/src/ui/utils/MarkdownDisplay.test.js +94 -104
  419. package/dist/src/ui/utils/MarkdownDisplay.test.js.map +1 -1
  420. package/dist/src/ui/utils/bracketedPaste.d.ts +9 -0
  421. package/dist/src/ui/utils/bracketedPaste.js +14 -0
  422. package/dist/src/ui/utils/bracketedPaste.js.map +1 -0
  423. package/dist/src/ui/utils/displayUtils.d.ts +1 -0
  424. package/dist/src/ui/utils/displayUtils.js +4 -1
  425. package/dist/src/ui/utils/displayUtils.js.map +1 -1
  426. package/dist/src/ui/utils/displayUtils.test.js +36 -17
  427. package/dist/src/ui/utils/displayUtils.test.js.map +1 -1
  428. package/dist/src/ui/utils/highlight.d.ts +2 -1
  429. package/dist/src/ui/utils/highlight.js +52 -8
  430. package/dist/src/ui/utils/highlight.js.map +1 -1
  431. package/dist/src/ui/utils/highlight.test.js +15 -14
  432. package/dist/src/ui/utils/highlight.test.js.map +1 -1
  433. package/dist/src/ui/utils/kittyProtocolDetector.d.ts +1 -0
  434. package/dist/src/ui/utils/kittyProtocolDetector.js +11 -3
  435. package/dist/src/ui/utils/kittyProtocolDetector.js.map +1 -1
  436. package/dist/src/ui/utils/terminalSequences.d.ts +22 -0
  437. package/dist/src/ui/utils/terminalSequences.js +23 -0
  438. package/dist/src/ui/utils/terminalSequences.js.map +1 -0
  439. package/dist/src/ui/utils/textUtils.d.ts +10 -0
  440. package/dist/src/ui/utils/textUtils.js +82 -1
  441. package/dist/src/ui/utils/textUtils.js.map +1 -1
  442. package/dist/src/ui/utils/textUtils.test.d.ts +6 -0
  443. package/dist/src/ui/utils/textUtils.test.js +132 -0
  444. package/dist/src/ui/utils/textUtils.test.js.map +1 -0
  445. package/dist/src/utils/bootstrap.d.ts +24 -0
  446. package/dist/src/utils/bootstrap.js +55 -0
  447. package/dist/src/utils/bootstrap.js.map +1 -0
  448. package/dist/src/utils/bootstrap.test.d.ts +6 -0
  449. package/dist/src/utils/bootstrap.test.js +103 -0
  450. package/dist/src/utils/bootstrap.test.js.map +1 -0
  451. package/dist/src/utils/cleanup.d.ts +6 -0
  452. package/dist/src/utils/cleanup.js +14 -0
  453. package/dist/src/utils/cleanup.js.map +1 -1
  454. package/dist/src/utils/commands.d.ts +17 -0
  455. package/dist/src/utils/commands.js +60 -0
  456. package/dist/src/utils/commands.js.map +1 -0
  457. package/dist/src/utils/dialogScopeUtils.d.ts +3 -0
  458. package/dist/src/utils/dialogScopeUtils.js +11 -2
  459. package/dist/src/utils/dialogScopeUtils.js.map +1 -1
  460. package/dist/src/utils/dynamicSettings.d.ts +20 -0
  461. package/dist/src/utils/dynamicSettings.js +110 -0
  462. package/dist/src/utils/dynamicSettings.js.map +1 -0
  463. package/dist/src/utils/dynamicSettings.test.d.ts +6 -0
  464. package/dist/src/utils/dynamicSettings.test.js +329 -0
  465. package/dist/src/utils/dynamicSettings.test.js.map +1 -0
  466. package/dist/src/utils/events.d.ts +3 -1
  467. package/dist/src/utils/events.js +2 -0
  468. package/dist/src/utils/events.js.map +1 -1
  469. package/dist/src/utils/handleAutoUpdate.js +4 -1
  470. package/dist/src/utils/handleAutoUpdate.js.map +1 -1
  471. package/dist/src/utils/installationInfo.d.ts +1 -0
  472. package/dist/src/utils/installationInfo.js +5 -3
  473. package/dist/src/utils/installationInfo.js.map +1 -1
  474. package/dist/src/utils/relaunch.d.ts +16 -0
  475. package/dist/src/utils/relaunch.js +34 -0
  476. package/dist/src/utils/relaunch.js.map +1 -0
  477. package/dist/src/utils/relaunch.test.d.ts +6 -0
  478. package/dist/src/utils/relaunch.test.js +96 -0
  479. package/dist/src/utils/relaunch.test.js.map +1 -0
  480. package/dist/src/utils/sessionCleanup.d.ts +22 -0
  481. package/dist/src/utils/sessionCleanup.integration.test.d.ts +6 -0
  482. package/dist/src/utils/sessionCleanup.integration.test.js +174 -0
  483. package/dist/src/utils/sessionCleanup.integration.test.js.map +1 -0
  484. package/dist/src/utils/sessionCleanup.js +213 -0
  485. package/dist/src/utils/sessionCleanup.js.map +1 -0
  486. package/dist/src/utils/sessionCleanup.test.d.ts +6 -0
  487. package/dist/src/utils/sessionCleanup.test.js +1144 -0
  488. package/dist/src/utils/sessionCleanup.test.js.map +1 -0
  489. package/dist/src/utils/sessionUtils.d.ts +37 -0
  490. package/dist/src/utils/sessionUtils.js +71 -0
  491. package/dist/src/utils/sessionUtils.js.map +1 -0
  492. package/dist/src/utils/settingsUtils.d.ts +6 -3
  493. package/dist/src/utils/settingsUtils.js +39 -11
  494. package/dist/src/utils/settingsUtils.js.map +1 -1
  495. package/dist/src/utils/settingsUtils.test.js +96 -96
  496. package/dist/src/utils/settingsUtils.test.js.map +1 -1
  497. package/dist/src/utils/singleSettingSaver.js +5 -0
  498. package/dist/src/utils/singleSettingSaver.js.map +1 -1
  499. package/dist/src/utils/windowTitle.d.ts +12 -0
  500. package/dist/src/utils/windowTitle.js +19 -0
  501. package/dist/src/utils/windowTitle.js.map +1 -0
  502. package/dist/src/utils/windowTitle.test.d.ts +6 -0
  503. package/dist/src/utils/windowTitle.test.js +49 -0
  504. package/dist/src/utils/windowTitle.test.js.map +1 -0
  505. package/dist/src/zed-integration/acp.js +1 -2
  506. package/dist/src/zed-integration/acp.js.map +1 -1
  507. package/dist/src/zed-integration/fileSystemService.d.ts +1 -0
  508. package/dist/src/zed-integration/fileSystemService.js +3 -0
  509. package/dist/src/zed-integration/fileSystemService.js.map +1 -1
  510. package/dist/src/zed-integration/schema.d.ts +212 -212
  511. package/dist/tsconfig.build.tsbuildinfo +1 -1
  512. package/package.json +15 -6
  513. package/dist/src/ui/App.quittingMessages.test.d.ts +0 -1
  514. package/dist/src/ui/App.quittingMessages.test.js +0 -14
  515. package/dist/src/ui/App.quittingMessages.test.js.map +0 -1
@@ -0,0 +1,1187 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * @license
4
+ * Copyright 2025 Vybestack LLC
5
+ * SPDX-License-Identifier: Apache-2.0
6
+ */
7
+ import { useCallback, useEffect, useLayoutEffect, useMemo, useState, useRef, } from 'react';
8
+ import { measureElement, useStdin, useStdout } from 'ink';
9
+ import { StreamingState, MessageType, ToolCallStatus, } from './types.js';
10
+ import { useTerminalSize } from './hooks/useTerminalSize.js';
11
+ import { useResponsive } from './hooks/useResponsive.js';
12
+ import { useGeminiStream } from './hooks/useGeminiStream.js';
13
+ import { useLoadingIndicator } from './hooks/useLoadingIndicator.js';
14
+ import { useThemeCommand } from './hooks/useThemeCommand.js';
15
+ import { useAuthCommand } from './hooks/useAuthCommand.js';
16
+ import { useFolderTrust } from './hooks/useFolderTrust.js';
17
+ import { useIdeTrustListener } from './hooks/useIdeTrustListener.js';
18
+ import { useEditorSettings } from './hooks/useEditorSettings.js';
19
+ import { useSlashCommandProcessor } from './hooks/slashCommandProcessor.js';
20
+ import { useAutoAcceptIndicator } from './hooks/useAutoAcceptIndicator.js';
21
+ import { useConsoleMessages } from './hooks/useConsoleMessages.js';
22
+ import { useExtensionAutoUpdate } from './hooks/useExtensionAutoUpdate.js';
23
+ import { useExtensionUpdates } from './hooks/useExtensionUpdates.js';
24
+ import { loadHierarchicalLlxprtMemory } from '../config/config.js';
25
+ import { DEFAULT_HISTORY_MAX_BYTES, DEFAULT_HISTORY_MAX_ITEMS, } from '../constants/historyLimits.js';
26
+ import { SettingScope } from '../config/settings.js';
27
+ import { ConsolePatcher } from './utils/ConsolePatcher.js';
28
+ import { registerCleanup } from '../utils/cleanup.js';
29
+ import { useHistory } from './hooks/useHistoryManager.js';
30
+ import { useInputHistoryStore } from './hooks/useInputHistoryStore.js';
31
+ import { useMemoryMonitor } from './hooks/useMemoryMonitor.js';
32
+ import { useTodoPausePreserver, TodoPausePreserver, } from './hooks/useTodoPausePreserver.js';
33
+ import process from 'node:process';
34
+ import { getErrorMessage, getAllLlxprtMdFilenames, isEditorAvailable, ideContext,
35
+ // type IdeInfo, // TODO: Fix IDE integration
36
+ getSettingsService, DebugLogger, uiTelemetryService, } from '@vybestack/llxprt-code-core';
37
+ import { validateAuthMethod } from '../config/auth.js';
38
+ import { useLogger } from './hooks/useLogger.js';
39
+ import { useSessionStats } from './contexts/SessionContext.js';
40
+ import { useGitBranchName } from './hooks/useGitBranchName.js';
41
+ import { useFocus } from './hooks/useFocus.js';
42
+ import { useBracketedPaste } from './hooks/useBracketedPaste.js';
43
+ import { useTextBuffer } from './components/shared/text-buffer.js';
44
+ import { useVimMode } from './contexts/VimModeContext.js';
45
+ import { useVim } from './hooks/vim.js';
46
+ import { useKeypress } from './hooks/useKeypress.js';
47
+ import { keyMatchers, Command } from './keyMatchers.js';
48
+ import * as fs from 'fs';
49
+ import ansiEscapes from 'ansi-escapes';
50
+ import { useSettingsCommand } from './hooks/useSettingsCommand.js';
51
+ import { setUpdateHandler } from '../utils/handleAutoUpdate.js';
52
+ import { appEvents, AppEvent } from '../utils/events.js';
53
+ import { useRuntimeApi } from './contexts/RuntimeContext.js';
54
+ import { useProviderModelDialog } from './hooks/useProviderModelDialog.js';
55
+ import { useProviderDialog } from './hooks/useProviderDialog.js';
56
+ import { useLoadProfileDialog } from './hooks/useLoadProfileDialog.js';
57
+ import { useToolsDialog } from './hooks/useToolsDialog.js';
58
+ import { shouldUpdateTokenMetrics, toTokenMetricsSnapshot, } from './utils/tokenMetricsTracker.js';
59
+ import { useStaticHistoryRefresh } from './hooks/useStaticHistoryRefresh.js';
60
+ import { useTodoContext } from './contexts/TodoContext.js';
61
+ import { useWorkspaceMigration } from './hooks/useWorkspaceMigration.js';
62
+ import { useFlickerDetector } from './hooks/useFlickerDetector.js';
63
+ import { isWorkspaceTrusted } from '../config/trustedFolders.js';
64
+ import { globalOAuthUI } from '../auth/global-oauth-ui.js';
65
+ import { UIStateProvider } from './contexts/UIStateContext.js';
66
+ import { UIActionsProvider, } from './contexts/UIActionsContext.js';
67
+ import { DefaultAppLayout } from './layouts/DefaultAppLayout.js';
68
+ import { disableBracketedPaste, enableBracketedPaste, } from './utils/bracketedPaste.js';
69
+ import { enableSupportedProtocol } from './utils/kittyProtocolDetector.js';
70
+ import { ENABLE_FOCUS_TRACKING, DISABLE_FOCUS_TRACKING, SHOW_CURSOR, } from './utils/terminalSequences.js';
71
+ const CTRL_EXIT_PROMPT_DURATION_MS = 1000;
72
+ const debug = new DebugLogger('llxprt:ui:appcontainer');
73
+ const selectionLogger = new DebugLogger('llxprt:ui:selection');
74
+ function isToolExecuting(pendingHistoryItems) {
75
+ return pendingHistoryItems.some((item) => {
76
+ if (item && item.type === 'tool_group') {
77
+ return item.tools.some((tool) => ToolCallStatus.Executing === tool.status);
78
+ }
79
+ return false;
80
+ });
81
+ }
82
+ export const AppContainer = (props) => {
83
+ debug.log('AppContainer architecture active (v2)');
84
+ const { config, settings, startupWarnings = [], appState, appDispatch, } = props;
85
+ const runtime = useRuntimeApi();
86
+ const isFocused = useFocus();
87
+ const { isNarrow } = useResponsive();
88
+ useBracketedPaste();
89
+ const [updateInfo, setUpdateInfo] = useState(null);
90
+ const { stdout } = useStdout();
91
+ const { stdin, setRawMode } = useStdin();
92
+ const nightly = props.version.includes('nightly'); // TODO: Use for nightly-specific features
93
+ const historyLimits = useMemo(() => ({
94
+ maxItems: typeof settings.merged.ui?.historyMaxItems === 'number'
95
+ ? settings.merged.ui.historyMaxItems
96
+ : DEFAULT_HISTORY_MAX_ITEMS,
97
+ maxBytes: typeof settings.merged.ui?.historyMaxBytes === 'number'
98
+ ? settings.merged.ui.historyMaxBytes
99
+ : DEFAULT_HISTORY_MAX_BYTES,
100
+ }), [settings.merged.ui?.historyMaxItems, settings.merged.ui?.historyMaxBytes]);
101
+ const { history, addItem, clearItems, loadHistory } = useHistory(historyLimits);
102
+ useMemoryMonitor({ addItem });
103
+ const { updateTodos } = useTodoContext();
104
+ const todoPauseController = useMemo(() => new TodoPausePreserver(), []);
105
+ const registerTodoPause = useCallback(() => {
106
+ todoPauseController.registerTodoPause();
107
+ }, [todoPauseController]);
108
+ const [idePromptAnswered, setIdePromptAnswered] = useState(false);
109
+ const currentIDE = config.getIdeClient()?.getCurrentIde();
110
+ useEffect(() => {
111
+ const ideClient = config.getIdeClient();
112
+ if (ideClient) {
113
+ registerCleanup(() => ideClient.disconnect());
114
+ }
115
+ }, [config]);
116
+ const shouldShowIdePrompt = currentIDE &&
117
+ !config.getIdeMode() &&
118
+ !settings.merged.hasSeenIdeIntegrationNudge &&
119
+ !idePromptAnswered;
120
+ useEffect(() => {
121
+ const cleanup = setUpdateHandler(addItem, setUpdateInfo);
122
+ // Attach addItem to OAuth providers for displaying auth URLs
123
+ if (addItem) {
124
+ const oauthManager = runtime.getCliOAuthManager();
125
+ if (oauthManager) {
126
+ const providersMap = oauthManager.providers;
127
+ if (providersMap instanceof Map) {
128
+ for (const provider of providersMap.values()) {
129
+ const candidate = provider;
130
+ candidate.setAddItem?.(addItem);
131
+ }
132
+ }
133
+ }
134
+ }
135
+ return cleanup;
136
+ }, [addItem, runtime]);
137
+ // Set global OAuth addItem callback for all OAuth flows
138
+ useEffect(() => {
139
+ global.__oauth_add_item = addItem;
140
+ globalOAuthUI.setAddItem(addItem);
141
+ return () => {
142
+ delete global.__oauth_add_item;
143
+ globalOAuthUI.clearAddItem();
144
+ };
145
+ }, [addItem]);
146
+ const { consoleMessages, handleNewMessage, clearConsoleMessages: clearConsoleMessagesState, } = useConsoleMessages();
147
+ useExtensionAutoUpdate({
148
+ settings,
149
+ onConsoleMessage: handleNewMessage,
150
+ });
151
+ useEffect(() => {
152
+ const consolePatcher = new ConsolePatcher({
153
+ onNewMessage: handleNewMessage,
154
+ debugMode: config.getDebugMode(),
155
+ });
156
+ consolePatcher.patch();
157
+ registerCleanup(consolePatcher.cleanup);
158
+ }, [handleNewMessage, config]);
159
+ const { stats: sessionStats, updateHistoryTokenCount } = useSessionStats();
160
+ const historyTokenCleanupRef = useRef(null);
161
+ const lastHistoryServiceRef = useRef(null);
162
+ const lastPublishedHistoryTokensRef = useRef(null);
163
+ const tokenLogger = useMemo(() => new DebugLogger('llxprt:ui:tokentracking'), []);
164
+ // Set up history token count listener
165
+ useEffect(() => {
166
+ let intervalCleared = false;
167
+ // Poll continuously to detect when the history service changes (e.g., after compression)
168
+ const checkInterval = setInterval(() => {
169
+ if (intervalCleared)
170
+ return;
171
+ const geminiClient = config.getGeminiClient();
172
+ // Check if chat is initialized first
173
+ if (geminiClient?.hasChatInitialized?.()) {
174
+ const historyService = geminiClient.getHistoryService?.();
175
+ if (!historyService && lastHistoryServiceRef.current === null) {
176
+ tokenLogger.debug(() => 'No history service available yet');
177
+ }
178
+ else if (historyService) {
179
+ // Always get the current token count even if not a new instance
180
+ const currentTokens = historyService.getTotalTokens();
181
+ if (currentTokens > 0 &&
182
+ currentTokens !== lastPublishedHistoryTokensRef.current) {
183
+ lastPublishedHistoryTokensRef.current = currentTokens;
184
+ updateHistoryTokenCount(currentTokens);
185
+ }
186
+ }
187
+ // Check if we have a new history service instance (happens after compression)
188
+ if (historyService &&
189
+ historyService !== lastHistoryServiceRef.current) {
190
+ tokenLogger.debug(() => 'Found new history service, setting up listener');
191
+ // Clean up old listener if it exists
192
+ if (historyTokenCleanupRef.current) {
193
+ historyTokenCleanupRef.current();
194
+ historyTokenCleanupRef.current = null;
195
+ }
196
+ // Store reference to current history service
197
+ lastHistoryServiceRef.current = historyService;
198
+ const handleTokensUpdated = (event) => {
199
+ tokenLogger.debug(() => `Received tokensUpdated event: totalTokens=${event.totalTokens}`);
200
+ if (event.totalTokens !== lastPublishedHistoryTokensRef.current) {
201
+ lastPublishedHistoryTokensRef.current = event.totalTokens;
202
+ updateHistoryTokenCount(event.totalTokens);
203
+ }
204
+ };
205
+ historyService.on('tokensUpdated', handleTokensUpdated);
206
+ // Initialize with current token count
207
+ const currentTokens = historyService.getTotalTokens();
208
+ tokenLogger.debug(() => `Initial token count: ${currentTokens}`);
209
+ lastPublishedHistoryTokensRef.current = currentTokens;
210
+ updateHistoryTokenCount(currentTokens);
211
+ // Store cleanup function for later
212
+ historyTokenCleanupRef.current = () => {
213
+ historyService.off('tokensUpdated', handleTokensUpdated);
214
+ };
215
+ }
216
+ }
217
+ }, 100); // Check every 100ms
218
+ return () => {
219
+ clearInterval(checkInterval);
220
+ intervalCleared = true;
221
+ // Clean up the event listener if it was set up
222
+ if (historyTokenCleanupRef.current) {
223
+ historyTokenCleanupRef.current();
224
+ historyTokenCleanupRef.current = null;
225
+ }
226
+ lastHistoryServiceRef.current = null;
227
+ lastPublishedHistoryTokensRef.current = null;
228
+ };
229
+ }, [config, updateHistoryTokenCount, tokenLogger]);
230
+ const [_staticNeedsRefresh, setStaticNeedsRefresh] = useState(false);
231
+ const [staticKey, setStaticKey] = useState(0);
232
+ const externalEditorStateRef = useRef(null);
233
+ const keypressRefreshRef = useRef(() => { });
234
+ const restoreTerminalStateAfterEditor = useCallback(() => {
235
+ const editorState = externalEditorStateRef.current;
236
+ if (!stdin) {
237
+ return;
238
+ }
239
+ const readStream = stdin;
240
+ if (editorState?.paused && typeof readStream.resume === 'function') {
241
+ readStream.resume();
242
+ }
243
+ if (editorState?.rawModeManaged && setRawMode) {
244
+ try {
245
+ setRawMode(true);
246
+ }
247
+ catch (error) {
248
+ console.error('Failed to re-enable raw mode:', error);
249
+ }
250
+ }
251
+ if (keypressRefreshRef.current) {
252
+ keypressRefreshRef.current();
253
+ debug.debug(() => 'Keypress refresh requested after external editor closed');
254
+ }
255
+ externalEditorStateRef.current = null;
256
+ }, [setRawMode, stdin]);
257
+ const refreshStatic = useCallback(() => {
258
+ stdout.write(ansiEscapes.clearTerminal);
259
+ setStaticKey((prev) => prev + 1);
260
+ restoreTerminalStateAfterEditor();
261
+ // Re-send terminal control sequences
262
+ enableBracketedPaste();
263
+ enableSupportedProtocol();
264
+ stdout.write(ENABLE_FOCUS_TRACKING);
265
+ stdout.write(SHOW_CURSOR);
266
+ }, [restoreTerminalStateAfterEditor, setStaticKey, stdout]);
267
+ const handleExternalEditorOpen = useCallback(() => {
268
+ if (!stdin) {
269
+ return;
270
+ }
271
+ const readStream = stdin;
272
+ externalEditorStateRef.current = {
273
+ paused: false,
274
+ rawModeManaged: false,
275
+ };
276
+ if (typeof readStream.pause === 'function') {
277
+ readStream.pause();
278
+ externalEditorStateRef.current.paused = true;
279
+ }
280
+ if (setRawMode) {
281
+ try {
282
+ setRawMode(false);
283
+ externalEditorStateRef.current.rawModeManaged = true;
284
+ }
285
+ catch (error) {
286
+ console.error('Failed to disable raw mode:', error);
287
+ }
288
+ }
289
+ disableBracketedPaste();
290
+ stdout.write(DISABLE_FOCUS_TRACKING);
291
+ stdout.write(SHOW_CURSOR);
292
+ }, [setRawMode, stdin, stdout]);
293
+ useStaticHistoryRefresh(history, refreshStatic);
294
+ const [llxprtMdFileCount, setLlxprtMdFileCount] = useState(0);
295
+ const [debugMessage, setDebugMessage] = useState('');
296
+ const [themeError, _setThemeError] = useState(null);
297
+ const [authError, setAuthError] = useState(null);
298
+ const [editorError, _setEditorError] = useState(null);
299
+ const [footerHeight, setFooterHeight] = useState(0);
300
+ // Token metrics state for live updates
301
+ const [tokenMetrics, setTokenMetrics] = useState({
302
+ tokensPerMinute: 0,
303
+ throttleWaitTimeMs: 0,
304
+ sessionTokenTotal: 0,
305
+ });
306
+ const tokenMetricsSnapshotRef = useRef(null);
307
+ const [_corgiMode, setCorgiMode] = useState(false);
308
+ const [_isTrustedFolderState, _setIsTrustedFolder] = useState(isWorkspaceTrusted(settings.merged));
309
+ const [currentModel, setCurrentModel] = useState(config.getModel());
310
+ const [shellModeActive, setShellModeActive] = useState(false);
311
+ const [showErrorDetails, setShowErrorDetails] = useState(false);
312
+ const [showToolDescriptions, setShowToolDescriptions] = useState(false);
313
+ const [showDebugProfiler, setShowDebugProfiler] = useState(false);
314
+ const [ctrlCPressedOnce, setCtrlCPressedOnce] = useState(false);
315
+ const [quittingMessages, setQuittingMessages] = useState(null);
316
+ const ctrlCTimerRef = useRef(null);
317
+ const [ctrlDPressedOnce, setCtrlDPressedOnce] = useState(false);
318
+ const ctrlDTimerRef = useRef(null);
319
+ const [constrainHeight, setConstrainHeight] = useState(true);
320
+ const [showPrivacyNotice, setShowPrivacyNotice] = useState(false);
321
+ const [ideContextState, setIdeContextState] = useState();
322
+ const [showEscapePrompt, setShowEscapePrompt] = useState(false);
323
+ const [showIdeRestartPrompt, setShowIdeRestartPrompt] = useState(false);
324
+ const [isProcessing, setIsProcessing] = useState(false);
325
+ const [providerModels, setProviderModels] = useState([]);
326
+ const [isPermissionsDialogOpen, setIsPermissionsDialogOpen] = useState(false);
327
+ const openPermissionsDialog = useCallback(() => {
328
+ setIsPermissionsDialogOpen(true);
329
+ }, []);
330
+ const closePermissionsDialog = useCallback(() => {
331
+ setIsPermissionsDialogOpen(false);
332
+ }, []);
333
+ const [isLoggingDialogOpen, setIsLoggingDialogOpen] = useState(false);
334
+ const [loggingDialogData, setLoggingDialogData] = useState({ entries: [] });
335
+ const openLoggingDialog = useCallback((data) => {
336
+ setLoggingDialogData(data || { entries: [] });
337
+ setIsLoggingDialogOpen(true);
338
+ }, []);
339
+ const closeLoggingDialog = useCallback(() => {
340
+ setIsLoggingDialogOpen(false);
341
+ }, []);
342
+ const { showWorkspaceMigrationDialog, workspaceExtensions, onWorkspaceMigrationDialogOpen, onWorkspaceMigrationDialogClose, } = useWorkspaceMigration(settings);
343
+ const extensions = config.getExtensions();
344
+ const { extensionsUpdateState, dispatchExtensionStateUpdate, confirmUpdateExtensionRequests, addConfirmUpdateExtensionRequest, } = useExtensionUpdates(extensions, addItem, config.getWorkingDir());
345
+ useEffect(() => {
346
+ const unsubscribe = ideContext.subscribeToIdeContext(setIdeContextState);
347
+ // Set the initial value
348
+ setIdeContextState(ideContext.getIdeContext());
349
+ return unsubscribe;
350
+ }, []);
351
+ // Update currentModel when settings change - get it from the SAME place as diagnostics
352
+ useEffect(() => {
353
+ const updateModel = async () => {
354
+ const settingsService = getSettingsService();
355
+ // Try to get from SettingsService first (same as diagnostics does)
356
+ if (settingsService && settingsService.getDiagnosticsData) {
357
+ try {
358
+ const diagnosticsData = await settingsService.getDiagnosticsData();
359
+ if (diagnosticsData && diagnosticsData.model) {
360
+ setCurrentModel(diagnosticsData.model);
361
+ return;
362
+ }
363
+ }
364
+ catch (_error) {
365
+ // Fall through to config
366
+ }
367
+ }
368
+ // Otherwise use config (which is what diagnostics falls back to)
369
+ setCurrentModel(config.getModel());
370
+ };
371
+ // Update immediately
372
+ updateModel();
373
+ // Also listen for any changes if SettingsService is available
374
+ const settingsService = getSettingsService();
375
+ if (settingsService) {
376
+ settingsService.on('settings-changed', updateModel);
377
+ return () => {
378
+ settingsService.off('settings-changed', updateModel);
379
+ };
380
+ }
381
+ return undefined;
382
+ }, [config]);
383
+ useEffect(() => {
384
+ const openDebugConsole = () => {
385
+ setShowErrorDetails(true);
386
+ setConstrainHeight(false); // Make sure the user sees the full message.
387
+ };
388
+ appEvents.on(AppEvent.OpenDebugConsole, openDebugConsole);
389
+ const logErrorHandler = (errorMessage) => {
390
+ handleNewMessage({
391
+ type: 'error',
392
+ content: String(errorMessage),
393
+ count: 1,
394
+ });
395
+ };
396
+ appEvents.on(AppEvent.LogError, logErrorHandler);
397
+ return () => {
398
+ appEvents.off(AppEvent.OpenDebugConsole, openDebugConsole);
399
+ appEvents.off(AppEvent.LogError, logErrorHandler);
400
+ };
401
+ }, [handleNewMessage]);
402
+ const openPrivacyNotice = useCallback(() => {
403
+ setShowPrivacyNotice(true);
404
+ }, []);
405
+ const handleEscapePromptChange = useCallback((showPrompt) => {
406
+ setShowEscapePrompt(showPrompt);
407
+ }, []);
408
+ const initialPromptSubmitted = useRef(false);
409
+ const errorCount = useMemo(() => consoleMessages
410
+ .filter((msg) => msg.type === 'error')
411
+ .reduce((total, msg) => total + msg.count, 0), [consoleMessages]);
412
+ const { isThemeDialogOpen, openThemeDialog, handleThemeSelect, handleThemeHighlight, } = useThemeCommand(settings, appState, addItem);
413
+ const { isSettingsDialogOpen, openSettingsDialog, closeSettingsDialog } = useSettingsCommand();
414
+ const { isFolderTrustDialogOpen, handleFolderTrustSelect, isRestarting } = useFolderTrust(settings, config);
415
+ const { needsRestart: ideNeedsRestart } = useIdeTrustListener(config);
416
+ useEffect(() => {
417
+ if (ideNeedsRestart) {
418
+ // IDE trust changed, force a restart.
419
+ setShowIdeRestartPrompt(true);
420
+ }
421
+ }, [ideNeedsRestart]);
422
+ useKeypress((key) => {
423
+ if (key.name === 'r' || key.name === 'R') {
424
+ process.exit(0);
425
+ }
426
+ }, { isActive: showIdeRestartPrompt });
427
+ const { isAuthDialogOpen, openAuthDialog, handleAuthSelect, isAuthenticating, cancelAuthentication, } = useAuthCommand(settings, appState, config);
428
+ useEffect(() => {
429
+ if (settings.merged.selectedAuthType && !settings.merged.useExternalAuth) {
430
+ const error = validateAuthMethod(settings.merged.selectedAuthType);
431
+ if (error) {
432
+ setAuthError(error);
433
+ // Don't automatically open auth dialog - user must use /auth command
434
+ }
435
+ }
436
+ }, [
437
+ settings.merged.selectedAuthType,
438
+ settings.merged.useExternalAuth,
439
+ setAuthError,
440
+ ]);
441
+ // Check for OAuth code needed flag
442
+ useEffect(() => {
443
+ const checkOAuthFlag = setInterval(() => {
444
+ if (global.__oauth_needs_code) {
445
+ // Clear the flag
446
+ global.__oauth_needs_code = false;
447
+ // Open the OAuth code dialog
448
+ appDispatch({ type: 'OPEN_DIALOG', payload: 'oauthCode' });
449
+ }
450
+ }, 100); // Check every 100ms
451
+ return () => clearInterval(checkOAuthFlag);
452
+ }, [appDispatch]);
453
+ const { isEditorDialogOpen, openEditorDialog, handleEditorSelect, exitEditorDialog, } = useEditorSettings(settings, appState, addItem);
454
+ const { showDialog: isProviderDialogOpen, openDialog: openProviderDialog, handleSelect: handleProviderSelect, closeDialog: exitProviderDialog, providers: providerOptions, currentProvider: selectedProvider, } = useProviderDialog({
455
+ addMessage: (msg) => addItem({ type: msg.type, text: msg.content }, msg.timestamp.getTime()),
456
+ appState,
457
+ config,
458
+ });
459
+ const { showDialog: isProviderModelDialogOpen, openDialog: openProviderModelDialogRaw, handleSelect: handleProviderModelChange, closeDialog: exitProviderModelDialog, } = useProviderModelDialog({
460
+ addMessage: (msg) => addItem({ type: msg.type, text: msg.content }, msg.timestamp.getTime()),
461
+ appState,
462
+ });
463
+ const openProviderModelDialog = useCallback(async () => {
464
+ try {
465
+ const models = await runtime.listAvailableModels();
466
+ setProviderModels(models);
467
+ }
468
+ catch (e) {
469
+ console.error('Failed to load models:', e);
470
+ setProviderModels([]);
471
+ }
472
+ await openProviderModelDialogRaw();
473
+ }, [openProviderModelDialogRaw, runtime]);
474
+ // Watch for model changes from config
475
+ useEffect(() => {
476
+ const checkModelChange = () => {
477
+ const configModel = config.getModel();
478
+ const providerModel = runtime.getActiveModelName();
479
+ const effectiveModel = providerModel && providerModel.trim() !== ''
480
+ ? providerModel
481
+ : configModel;
482
+ if (effectiveModel !== currentModel) {
483
+ console.debug(`[Model Update] Updating footer from ${currentModel} to ${effectiveModel}`);
484
+ setCurrentModel(effectiveModel);
485
+ }
486
+ };
487
+ // Check immediately
488
+ checkModelChange();
489
+ // Check periodically (every 500ms)
490
+ const interval = setInterval(checkModelChange, 500);
491
+ return () => clearInterval(interval);
492
+ }, [config, currentModel, runtime]); // Include currentModel in dependencies
493
+ const toggleCorgiMode = useCallback(() => {
494
+ setCorgiMode((prev) => !prev);
495
+ }, []);
496
+ const toggleDebugProfiler = useCallback(() => {
497
+ setShowDebugProfiler((prev) => !prev);
498
+ }, []);
499
+ const { showDialog: isLoadProfileDialogOpen, openDialog: openLoadProfileDialog, handleSelect: handleProfileSelect, closeDialog: exitLoadProfileDialog, profiles, } = useLoadProfileDialog({
500
+ addMessage: (msg) => addItem({ type: msg.type, text: msg.content }, msg.timestamp.getTime()),
501
+ appState,
502
+ config,
503
+ settings,
504
+ });
505
+ const { showDialog: isToolsDialogOpen, openDialog: openToolsDialogRaw, closeDialog: exitToolsDialog, action: toolsDialogAction, availableTools: toolsDialogTools, disabledTools: toolsDialogDisabledTools, handleSelect: handleToolsSelect, } = useToolsDialog({
506
+ addMessage: (msg) => addItem({ type: msg.type, text: msg.content }, msg.timestamp.getTime()),
507
+ appState,
508
+ config,
509
+ });
510
+ const openToolsDialog = useCallback((action) => {
511
+ openToolsDialogRaw(action);
512
+ }, [openToolsDialogRaw]);
513
+ const performMemoryRefresh = useCallback(async () => {
514
+ addItem({
515
+ type: MessageType.INFO,
516
+ text: 'Refreshing hierarchical memory (LLXPRT.md or other context files)...',
517
+ }, Date.now());
518
+ try {
519
+ const { memoryContent, fileCount } = await loadHierarchicalLlxprtMemory(process.cwd(), settings.merged.loadMemoryFromIncludeDirectories
520
+ ? config.getWorkspaceContext().getDirectories()
521
+ : [], config.getDebugMode(), config.getFileService(), settings.merged, config.getExtensionContextFilePaths(), config.getFolderTrust(), settings.merged.ui?.memoryImportFormat || 'tree', // Use setting or default to 'tree'
522
+ config.getFileFilteringOptions());
523
+ config.setUserMemory(memoryContent);
524
+ config.setLlxprtMdFileCount(fileCount);
525
+ setLlxprtMdFileCount(fileCount);
526
+ addItem({
527
+ type: MessageType.INFO,
528
+ text: `Memory refreshed successfully. ${memoryContent.length > 0 ? `Loaded ${memoryContent.length} characters from ${fileCount} file(s).` : 'No memory content found.'}`,
529
+ }, Date.now());
530
+ if (config.getDebugMode()) {
531
+ console.log(`[DEBUG] Refreshed memory content in config: ${memoryContent.substring(0, 200)}...`);
532
+ }
533
+ }
534
+ catch (error) {
535
+ const errorMessage = getErrorMessage(error);
536
+ addItem({
537
+ type: MessageType.ERROR,
538
+ text: `Error refreshing memory: ${errorMessage}`,
539
+ }, Date.now());
540
+ console.error('Error refreshing memory:', error);
541
+ }
542
+ }, [config, addItem, settings.merged]);
543
+ // Poll for token metrics updates
544
+ useEffect(() => {
545
+ const updateTokenMetrics = () => {
546
+ const metrics = runtime.getActiveProviderMetrics();
547
+ const usage = runtime.getSessionTokenUsage();
548
+ if (!shouldUpdateTokenMetrics(tokenMetricsSnapshotRef.current, metrics, usage)) {
549
+ return;
550
+ }
551
+ const snapshot = toTokenMetricsSnapshot(metrics, usage);
552
+ tokenMetricsSnapshotRef.current = snapshot;
553
+ setTokenMetrics({
554
+ tokensPerMinute: snapshot.tokensPerMinute,
555
+ throttleWaitTimeMs: snapshot.throttleWaitTimeMs,
556
+ sessionTokenTotal: snapshot.sessionTokenTotal,
557
+ });
558
+ uiTelemetryService.setTokenTrackingMetrics({
559
+ tokensPerMinute: snapshot.tokensPerMinute,
560
+ throttleWaitTimeMs: snapshot.throttleWaitTimeMs,
561
+ sessionTokenUsage: usage,
562
+ });
563
+ };
564
+ // Update immediately
565
+ updateTokenMetrics();
566
+ // Poll every second to show live updates
567
+ const interval = setInterval(updateTokenMetrics, 1000);
568
+ return () => clearInterval(interval);
569
+ }, [runtime]);
570
+ // Terminal and UI setup
571
+ const { rows: terminalHeight, columns: terminalWidth } = useTerminalSize();
572
+ const isInitialMount = useRef(true);
573
+ const widthFraction = 0.9;
574
+ // Calculate inputWidth accounting for:
575
+ // - Prompt: 2 chars ("! " or "> ")
576
+ // - Padding: 2 chars (paddingX={1} on each side in InputPrompt)
577
+ // - Additional margin: 2 chars (for proper wrapping)
578
+ const inputWidth = Math.max(20, Math.floor(terminalWidth * widthFraction) - 6);
579
+ const suggestionsWidth = Math.max(60, Math.floor(terminalWidth * 0.8));
580
+ // Utility callbacks
581
+ const isValidPath = useCallback((filePath) => {
582
+ try {
583
+ return fs.existsSync(filePath) && fs.statSync(filePath).isFile();
584
+ }
585
+ catch (_e) {
586
+ return false;
587
+ }
588
+ }, []);
589
+ const getPreferredEditor = useCallback(() => {
590
+ const editorType = settings.merged.ui?.preferredEditor;
591
+ const isValidEditor = isEditorAvailable(editorType);
592
+ if (!isValidEditor) {
593
+ openEditorDialog();
594
+ return;
595
+ }
596
+ return editorType;
597
+ }, [settings, openEditorDialog]);
598
+ const onAuthError = useCallback(() => {
599
+ setAuthError('reauth required');
600
+ // Open the auth dialog when authentication errors occur
601
+ appDispatch({ type: 'OPEN_DIALOG', payload: 'auth' });
602
+ }, [setAuthError, appDispatch]);
603
+ const handleAuthTimeout = useCallback(() => {
604
+ setAuthError('Authentication timed out. Please try again.');
605
+ cancelAuthentication();
606
+ // NEVER automatically open auth dialog - user must use /auth
607
+ }, [setAuthError, cancelAuthentication]);
608
+ const handlePrivacyNoticeExit = useCallback(() => {
609
+ setShowPrivacyNotice(false);
610
+ }, []);
611
+ // Core hooks and processors
612
+ const { vimEnabled: vimModeEnabled, vimMode, toggleVimEnabled, } = useVimMode();
613
+ const slashCommandProcessorActions = useMemo(() => ({
614
+ openAuthDialog,
615
+ openThemeDialog,
616
+ openEditorDialog,
617
+ openPrivacyNotice,
618
+ openSettingsDialog,
619
+ openLoggingDialog,
620
+ openProviderModelDialog,
621
+ openPermissionsDialog,
622
+ openProviderDialog,
623
+ openLoadProfileDialog,
624
+ quit: setQuittingMessages,
625
+ setDebugMessage,
626
+ toggleCorgiMode,
627
+ toggleDebugProfiler,
628
+ dispatchExtensionStateUpdate,
629
+ addConfirmUpdateExtensionRequest,
630
+ }), [
631
+ openAuthDialog,
632
+ openThemeDialog,
633
+ openEditorDialog,
634
+ openPrivacyNotice,
635
+ openSettingsDialog,
636
+ openLoggingDialog,
637
+ openProviderModelDialog,
638
+ openPermissionsDialog,
639
+ openProviderDialog,
640
+ openLoadProfileDialog,
641
+ setQuittingMessages,
642
+ setDebugMessage,
643
+ toggleCorgiMode,
644
+ toggleDebugProfiler,
645
+ dispatchExtensionStateUpdate,
646
+ addConfirmUpdateExtensionRequest,
647
+ ]);
648
+ const { handleSlashCommand, slashCommands, pendingHistoryItems: pendingSlashCommandHistoryItems, commandContext, shellConfirmationRequest, confirmationRequest, } = useSlashCommandProcessor(config, settings, addItem, clearItems, loadHistory, refreshStatic, toggleVimEnabled, setIsProcessing, setLlxprtMdFileCount, slashCommandProcessorActions, extensionsUpdateState, true);
649
+ // Memoize viewport to ensure it updates when inputWidth changes
650
+ const viewport = useMemo(() => ({ height: 10, width: inputWidth }), [inputWidth]);
651
+ const buffer = useTextBuffer({
652
+ initialText: '',
653
+ viewport,
654
+ stdin,
655
+ setRawMode,
656
+ isValidPath,
657
+ shellModeActive,
658
+ });
659
+ // Independent input history management (unaffected by /clear)
660
+ const inputHistoryStore = useInputHistoryStore();
661
+ const handleUserCancel = useCallback(() => {
662
+ const lastUserMessage = inputHistoryStore.inputHistory.at(-1);
663
+ if (lastUserMessage) {
664
+ buffer.setText(lastUserMessage);
665
+ }
666
+ }, [buffer, inputHistoryStore.inputHistory]);
667
+ const handleOAuthCodeDialogClose = useCallback(() => {
668
+ appDispatch({ type: 'CLOSE_DIALOG', payload: 'oauthCode' });
669
+ }, [appDispatch]);
670
+ const handleOAuthCodeSubmit = useCallback(async (code) => {
671
+ const provider = global
672
+ .__oauth_provider;
673
+ if (provider === 'anthropic') {
674
+ const oauthManager = runtime.getCliOAuthManager();
675
+ if (oauthManager) {
676
+ const anthropicProvider = oauthManager.getProvider('anthropic');
677
+ if (anthropicProvider && 'submitAuthCode' in anthropicProvider) {
678
+ anthropicProvider.submitAuthCode(code);
679
+ }
680
+ }
681
+ }
682
+ }, [runtime]);
683
+ const { streamingState, submitQuery, initError, pendingHistoryItems: pendingGeminiHistoryItems, thought, cancelOngoingRequest, } = useGeminiStream(config.getGeminiClient(), history, addItem, config, settings, setDebugMessage, handleSlashCommand, shellModeActive, getPreferredEditor, onAuthError, performMemoryRefresh, refreshStatic, handleUserCancel, registerTodoPause, handleExternalEditorOpen);
684
+ const pendingHistoryItems = useMemo(() => [...pendingSlashCommandHistoryItems, ...pendingGeminiHistoryItems], [pendingSlashCommandHistoryItems, pendingGeminiHistoryItems]);
685
+ // Update the cancel handler with message queue support
686
+ const cancelHandlerRef = useRef(null);
687
+ cancelHandlerRef.current = useCallback(() => {
688
+ if (isToolExecuting(pendingHistoryItems)) {
689
+ buffer.setText(''); // Just clear the prompt
690
+ return;
691
+ }
692
+ const lastUserMessage = inputHistoryStore.inputHistory.at(-1);
693
+ const textToSet = lastUserMessage || '';
694
+ if (textToSet) {
695
+ buffer.setText(textToSet);
696
+ }
697
+ }, [buffer, inputHistoryStore.inputHistory, pendingHistoryItems]);
698
+ // Input handling - queue messages for processing
699
+ const handleFinalSubmit = useCallback((submittedValue) => {
700
+ const trimmedValue = submittedValue.trim();
701
+ if (trimmedValue.length > 0) {
702
+ // Add to independent input history
703
+ inputHistoryStore.addInput(trimmedValue);
704
+ submitQuery(trimmedValue);
705
+ }
706
+ }, [submitQuery, inputHistoryStore]);
707
+ const { handleUserInputSubmit } = useTodoPausePreserver({
708
+ controller: todoPauseController,
709
+ updateTodos,
710
+ handleFinalSubmit,
711
+ });
712
+ const handleIdePromptComplete = useCallback((result) => {
713
+ if (result.userSelection === 'yes') {
714
+ if (result.isExtensionPreInstalled) {
715
+ handleSlashCommand('/ide enable');
716
+ }
717
+ else {
718
+ handleSlashCommand('/ide install');
719
+ }
720
+ settings.setValue(SettingScope.User, 'hasSeenIdeIntegrationNudge', true);
721
+ }
722
+ else if (result.userSelection === 'dismiss') {
723
+ settings.setValue(SettingScope.User, 'hasSeenIdeIntegrationNudge', true);
724
+ }
725
+ setIdePromptAnswered(true);
726
+ }, [handleSlashCommand, settings]);
727
+ const { handleInput: vimHandleInput } = useVim(buffer, handleFinalSubmit);
728
+ const { elapsedTime, currentLoadingPhrase } = useLoadingIndicator(streamingState, settings.merged.ui?.customWittyPhrases);
729
+ const showAutoAcceptIndicator = useAutoAcceptIndicator({ config, addItem });
730
+ const handleExit = useCallback((pressedOnce, setPressedOnce, timerRef) => {
731
+ if (pressedOnce) {
732
+ if (timerRef.current) {
733
+ clearTimeout(timerRef.current);
734
+ }
735
+ // Directly invoke the central command handler.
736
+ handleSlashCommand('/quit');
737
+ }
738
+ else {
739
+ setPressedOnce(true);
740
+ timerRef.current = setTimeout(() => {
741
+ setPressedOnce(false);
742
+ timerRef.current = null;
743
+ }, CTRL_EXIT_PROMPT_DURATION_MS);
744
+ }
745
+ }, [handleSlashCommand]);
746
+ const handleSettingsRestart = useCallback(() => {
747
+ handleSlashCommand('/quit');
748
+ }, [handleSlashCommand]);
749
+ const handleGlobalKeypress = useCallback((key) => {
750
+ // Debug log keystrokes if enabled
751
+ if (settings.merged.debugKeystrokeLogging) {
752
+ console.log('[DEBUG] Keystroke:', JSON.stringify(key));
753
+ }
754
+ // Handle exit keys BEFORE dialog visibility check so exit prompts work even when dialogs are open
755
+ if (keyMatchers[Command.QUIT](key)) {
756
+ // When authenticating, let AuthInProgress component handle Ctrl+C.
757
+ if (isAuthenticating) {
758
+ return;
759
+ }
760
+ if (!ctrlCPressedOnce) {
761
+ cancelOngoingRequest?.();
762
+ }
763
+ if (!ctrlCPressedOnce) {
764
+ setCtrlCPressedOnce(true);
765
+ ctrlCTimerRef.current = setTimeout(() => {
766
+ setCtrlCPressedOnce(false);
767
+ ctrlCTimerRef.current = null;
768
+ }, CTRL_EXIT_PROMPT_DURATION_MS);
769
+ return;
770
+ }
771
+ handleExit(ctrlCPressedOnce, setCtrlCPressedOnce, ctrlCTimerRef);
772
+ return;
773
+ }
774
+ else if (keyMatchers[Command.EXIT](key)) {
775
+ if (buffer.text.length > 0) {
776
+ return;
777
+ }
778
+ handleExit(ctrlDPressedOnce, setCtrlDPressedOnce, ctrlDTimerRef);
779
+ return;
780
+ }
781
+ let enteringConstrainHeightMode = false;
782
+ if (!constrainHeight) {
783
+ enteringConstrainHeightMode = true;
784
+ setConstrainHeight(true);
785
+ }
786
+ if (keyMatchers[Command.SHOW_ERROR_DETAILS](key)) {
787
+ setShowErrorDetails((prev) => !prev);
788
+ }
789
+ else if (keyMatchers[Command.TOGGLE_TOOL_DESCRIPTIONS](key)) {
790
+ const newValue = !showToolDescriptions;
791
+ setShowToolDescriptions(newValue);
792
+ const mcpServers = config.getMcpServers();
793
+ if (Object.keys(mcpServers || {}).length > 0) {
794
+ handleSlashCommand(newValue ? '/mcp desc' : '/mcp nodesc');
795
+ }
796
+ }
797
+ else if (keyMatchers[Command.TOGGLE_IDE_CONTEXT_DETAIL](key) &&
798
+ config.getIdeMode() &&
799
+ ideContextState) {
800
+ // Show IDE status when in IDE mode and context is available.
801
+ handleSlashCommand('/ide status');
802
+ }
803
+ else if (keyMatchers[Command.SHOW_MORE_LINES](key) &&
804
+ !enteringConstrainHeightMode) {
805
+ setConstrainHeight(false);
806
+ }
807
+ }, [
808
+ constrainHeight,
809
+ setConstrainHeight,
810
+ setShowErrorDetails,
811
+ showToolDescriptions,
812
+ setShowToolDescriptions,
813
+ config,
814
+ ideContextState,
815
+ handleExit,
816
+ ctrlCPressedOnce,
817
+ setCtrlCPressedOnce,
818
+ ctrlCTimerRef,
819
+ buffer.text.length,
820
+ ctrlDPressedOnce,
821
+ setCtrlDPressedOnce,
822
+ ctrlDTimerRef,
823
+ handleSlashCommand,
824
+ isAuthenticating,
825
+ cancelOngoingRequest,
826
+ settings.merged.debugKeystrokeLogging,
827
+ ]);
828
+ const { refresh: globalKeypressRefresh } = useKeypress(handleGlobalKeypress, {
829
+ isActive: true,
830
+ });
831
+ useEffect(() => {
832
+ keypressRefreshRef.current = globalKeypressRefresh;
833
+ }, [globalKeypressRefresh]);
834
+ useEffect(() => {
835
+ if (config) {
836
+ setLlxprtMdFileCount(config.getLlxprtMdFileCount());
837
+ }
838
+ }, [config, config.getLlxprtMdFileCount]);
839
+ const logger = useLogger(config.storage);
840
+ // Initialize independent input history from logger
841
+ useEffect(() => {
842
+ inputHistoryStore.initializeFromLogger(logger);
843
+ }, [logger, inputHistoryStore]);
844
+ // Handle process exit when quit command is issued
845
+ useEffect(() => {
846
+ if (quittingMessages) {
847
+ // Allow UI to render the quit message briefly before exiting
848
+ const timer = setTimeout(() => {
849
+ process.exit(0);
850
+ }, 100); // 100ms delay to show quit screen
851
+ return () => clearTimeout(timer);
852
+ }
853
+ return undefined;
854
+ }, [quittingMessages]);
855
+ const isInputActive = (streamingState === StreamingState.Idle ||
856
+ streamingState === StreamingState.Responding) &&
857
+ !initError &&
858
+ !isProcessing;
859
+ useEffect(() => {
860
+ if (selectionLogger.enabled) {
861
+ if (confirmationRequest) {
862
+ selectionLogger.debug(() => 'Confirmation dialog opened');
863
+ }
864
+ else {
865
+ selectionLogger.debug(() => 'Confirmation dialog closed');
866
+ }
867
+ }
868
+ }, [confirmationRequest]);
869
+ const handleClearScreen = useCallback(() => {
870
+ clearItems();
871
+ clearConsoleMessagesState();
872
+ console.clear();
873
+ refreshStatic();
874
+ }, [clearItems, clearConsoleMessagesState, refreshStatic]);
875
+ const handleConfirmationSelect = useCallback((value) => {
876
+ if (confirmationRequest) {
877
+ if (selectionLogger.enabled) {
878
+ selectionLogger.debug(() => `AppContainer.handleConfirmationSelect value=${value} hasRequest=${Boolean(confirmationRequest)}`);
879
+ }
880
+ confirmationRequest.onConfirm(value);
881
+ }
882
+ }, [confirmationRequest]);
883
+ const mainControlsRef = useRef(null);
884
+ const pendingHistoryItemRef = useRef(null);
885
+ const rootUiRef = useRef(null);
886
+ useLayoutEffect(() => {
887
+ if (mainControlsRef.current) {
888
+ const fullFooterMeasurement = measureElement(mainControlsRef.current);
889
+ setFooterHeight(fullFooterMeasurement.height);
890
+ }
891
+ }, [terminalHeight, consoleMessages, showErrorDetails]);
892
+ const staticExtraHeight = /* margins and padding */ 3;
893
+ const availableTerminalHeight = useMemo(() => terminalHeight - footerHeight - staticExtraHeight, [terminalHeight, footerHeight]);
894
+ // Flicker detection - measures root UI element vs terminal height
895
+ // to detect overflow that could cause flickering (issue #456)
896
+ // This is for TELEMETRY ONLY - actual prevention is via availableTerminalHeight
897
+ useFlickerDetector(rootUiRef, terminalHeight, constrainHeight);
898
+ // Listen for Flicker events for additional corrective actions
899
+ useEffect(() => {
900
+ const handleFlicker = (data) => {
901
+ debug.log(`Flicker event received: overflow=${data.overflow}, content=${data.contentHeight}, terminal=${data.terminalHeight}`);
902
+ // When flicker is detected, ensure constrainHeight is enabled
903
+ // This provides a feedback loop to keep the UI constrained
904
+ if (!constrainHeight) {
905
+ setConstrainHeight(true);
906
+ }
907
+ };
908
+ appEvents.on(AppEvent.Flicker, handleFlicker);
909
+ return () => {
910
+ appEvents.off(AppEvent.Flicker, handleFlicker);
911
+ };
912
+ }, [constrainHeight]);
913
+ useEffect(() => {
914
+ // skip refreshing Static during first mount
915
+ if (isInitialMount.current) {
916
+ isInitialMount.current = false;
917
+ return;
918
+ }
919
+ // debounce so it doesn't fire up too often during resize
920
+ const handler = setTimeout(() => {
921
+ if (streamingState === StreamingState.Idle) {
922
+ refreshStatic();
923
+ }
924
+ else {
925
+ setStaticNeedsRefresh(true);
926
+ }
927
+ }, 300);
928
+ return () => {
929
+ clearTimeout(handler);
930
+ };
931
+ }, [terminalWidth, terminalHeight, refreshStatic, streamingState]);
932
+ useEffect(() => {
933
+ if (streamingState === StreamingState.Idle && _staticNeedsRefresh) {
934
+ setStaticNeedsRefresh(false);
935
+ refreshStatic();
936
+ }
937
+ }, [streamingState, refreshStatic, _staticNeedsRefresh]);
938
+ const filteredConsoleMessages = useMemo(() => {
939
+ if (config.getDebugMode()) {
940
+ return consoleMessages;
941
+ }
942
+ return consoleMessages.filter((msg) => msg.type !== 'debug');
943
+ }, [consoleMessages, config]);
944
+ const branchName = useGitBranchName(config.getTargetDir());
945
+ const contextFileNames = useMemo(() => {
946
+ const fromSettings = settings.merged.ui?.contextFileName;
947
+ if (fromSettings) {
948
+ return Array.isArray(fromSettings) ? fromSettings : [fromSettings];
949
+ }
950
+ return getAllLlxprtMdFilenames();
951
+ }, [settings.merged.ui?.contextFileName]);
952
+ const initialPrompt = useMemo(() => config.getQuestion(), [config]);
953
+ const geminiClient = config.getGeminiClient();
954
+ useEffect(() => {
955
+ if (initialPrompt &&
956
+ !initialPromptSubmitted.current &&
957
+ !isAuthenticating &&
958
+ !isAuthDialogOpen &&
959
+ !isThemeDialogOpen &&
960
+ !isEditorDialogOpen &&
961
+ !isProviderDialogOpen &&
962
+ !isProviderModelDialogOpen &&
963
+ !isToolsDialogOpen &&
964
+ !showPrivacyNotice &&
965
+ geminiClient) {
966
+ submitQuery(initialPrompt);
967
+ initialPromptSubmitted.current = true;
968
+ }
969
+ }, [
970
+ initialPrompt,
971
+ submitQuery,
972
+ isAuthenticating,
973
+ isAuthDialogOpen,
974
+ isThemeDialogOpen,
975
+ isEditorDialogOpen,
976
+ isProviderDialogOpen,
977
+ isProviderModelDialogOpen,
978
+ isToolsDialogOpen,
979
+ showPrivacyNotice,
980
+ geminiClient,
981
+ ]);
982
+ const mainAreaWidth = Math.floor(terminalWidth * 0.9);
983
+ // Detect PowerShell for file reference syntax tip
984
+ const isPowerShell = process.env.PSModulePath !== undefined ||
985
+ process.env.PSVERSION !== undefined;
986
+ const placeholder = vimModeEnabled
987
+ ? " Press 'i' for INSERT mode and 'Esc' for NORMAL mode."
988
+ : isPowerShell
989
+ ? ' Type your message, @path/to/file or +path/to/file'
990
+ : ' Type your message or @path/to/file';
991
+ // Build UIState object
992
+ const uiState = {
993
+ // Core app context
994
+ config,
995
+ settings,
996
+ // Terminal dimensions
997
+ terminalWidth,
998
+ terminalHeight,
999
+ mainAreaWidth,
1000
+ inputWidth,
1001
+ suggestionsWidth,
1002
+ // History and streaming
1003
+ history,
1004
+ pendingHistoryItems,
1005
+ streamingState,
1006
+ thought,
1007
+ // Input buffer
1008
+ buffer,
1009
+ shellModeActive,
1010
+ // Dialog states
1011
+ isThemeDialogOpen,
1012
+ isSettingsDialogOpen,
1013
+ isAuthDialogOpen,
1014
+ isAuthenticating,
1015
+ isEditorDialogOpen,
1016
+ isProviderDialogOpen,
1017
+ isProviderModelDialogOpen,
1018
+ isLoadProfileDialogOpen,
1019
+ isToolsDialogOpen,
1020
+ isFolderTrustDialogOpen,
1021
+ showWorkspaceMigrationDialog,
1022
+ showPrivacyNotice,
1023
+ isOAuthCodeDialogOpen: appState.openDialogs.oauthCode,
1024
+ isPermissionsDialogOpen,
1025
+ isLoggingDialogOpen,
1026
+ // Dialog data
1027
+ providerOptions,
1028
+ selectedProvider,
1029
+ providerModels,
1030
+ currentModel,
1031
+ profiles,
1032
+ toolsDialogAction,
1033
+ toolsDialogTools,
1034
+ toolsDialogDisabledTools,
1035
+ workspaceExtensions,
1036
+ loggingDialogData,
1037
+ // Confirmation requests
1038
+ shellConfirmationRequest,
1039
+ confirmationRequest,
1040
+ confirmUpdateExtensionRequests,
1041
+ // Exit/warning states
1042
+ ctrlCPressedOnce,
1043
+ ctrlDPressedOnce,
1044
+ showEscapePrompt,
1045
+ showIdeRestartPrompt,
1046
+ quittingMessages,
1047
+ // Display options
1048
+ constrainHeight,
1049
+ showErrorDetails,
1050
+ showToolDescriptions,
1051
+ isNarrow,
1052
+ vimModeEnabled,
1053
+ vimMode,
1054
+ // Context and status
1055
+ ideContextState,
1056
+ llxprtMdFileCount,
1057
+ branchName,
1058
+ errorCount,
1059
+ // Console and messages
1060
+ consoleMessages: filteredConsoleMessages,
1061
+ // Loading and status
1062
+ elapsedTime,
1063
+ currentLoadingPhrase,
1064
+ showAutoAcceptIndicator,
1065
+ // Token metrics
1066
+ tokenMetrics,
1067
+ historyTokenCount: sessionStats.historyTokenCount,
1068
+ // Error states
1069
+ initError,
1070
+ authError,
1071
+ themeError,
1072
+ editorError,
1073
+ // Processing states
1074
+ isProcessing,
1075
+ isInputActive,
1076
+ isFocused,
1077
+ // Refs for flicker detection
1078
+ rootUiRef,
1079
+ pendingHistoryItemRef,
1080
+ // Slash commands
1081
+ slashCommands,
1082
+ commandContext,
1083
+ // IDE prompt
1084
+ shouldShowIdePrompt: !!shouldShowIdePrompt,
1085
+ currentIDE,
1086
+ // Trust
1087
+ isRestarting,
1088
+ isTrustedFolder: config.isTrustedFolder(),
1089
+ // Input history
1090
+ inputHistory: inputHistoryStore.inputHistory,
1091
+ // Static key for refreshing
1092
+ staticKey,
1093
+ // Debug
1094
+ debugMessage,
1095
+ showDebugProfiler,
1096
+ // Footer height
1097
+ footerHeight,
1098
+ // Placeholder text
1099
+ placeholder,
1100
+ // Available terminal height for content (after footer measurement)
1101
+ availableTerminalHeight,
1102
+ };
1103
+ // Build UIActions object
1104
+ const uiActions = {
1105
+ // History actions
1106
+ addItem,
1107
+ clearItems,
1108
+ loadHistory,
1109
+ refreshStatic,
1110
+ // Input actions
1111
+ handleUserInputSubmit,
1112
+ handleClearScreen,
1113
+ // Theme dialog
1114
+ openThemeDialog,
1115
+ handleThemeSelect,
1116
+ handleThemeHighlight,
1117
+ // Settings dialog
1118
+ openSettingsDialog,
1119
+ closeSettingsDialog,
1120
+ handleSettingsRestart,
1121
+ // Auth dialog
1122
+ openAuthDialog,
1123
+ handleAuthSelect,
1124
+ cancelAuthentication,
1125
+ handleAuthTimeout,
1126
+ // Editor dialog
1127
+ openEditorDialog,
1128
+ handleEditorSelect,
1129
+ exitEditorDialog,
1130
+ // Provider dialog
1131
+ openProviderDialog,
1132
+ handleProviderSelect,
1133
+ exitProviderDialog,
1134
+ // Provider model dialog
1135
+ openProviderModelDialog,
1136
+ handleProviderModelChange,
1137
+ exitProviderModelDialog,
1138
+ // Load profile dialog
1139
+ openLoadProfileDialog,
1140
+ handleProfileSelect,
1141
+ exitLoadProfileDialog,
1142
+ // Tools dialog
1143
+ openToolsDialog,
1144
+ handleToolsSelect,
1145
+ exitToolsDialog,
1146
+ // Folder trust dialog
1147
+ handleFolderTrustSelect,
1148
+ // Permissions dialog
1149
+ openPermissionsDialog,
1150
+ closePermissionsDialog,
1151
+ // Logging dialog
1152
+ openLoggingDialog,
1153
+ closeLoggingDialog,
1154
+ // Workspace migration dialog
1155
+ onWorkspaceMigrationDialogOpen,
1156
+ onWorkspaceMigrationDialogClose,
1157
+ // Privacy notice
1158
+ openPrivacyNotice,
1159
+ handlePrivacyNoticeExit,
1160
+ // OAuth code dialog
1161
+ handleOAuthCodeDialogClose,
1162
+ handleOAuthCodeSubmit,
1163
+ // Confirmation handlers
1164
+ handleConfirmationSelect,
1165
+ // IDE prompt
1166
+ handleIdePromptComplete,
1167
+ // Vim
1168
+ vimHandleInput,
1169
+ toggleVimEnabled,
1170
+ // Slash commands
1171
+ handleSlashCommand,
1172
+ // Memory
1173
+ performMemoryRefresh,
1174
+ // Display toggles
1175
+ setShowErrorDetails,
1176
+ setShowToolDescriptions,
1177
+ setConstrainHeight,
1178
+ // Shell mode
1179
+ setShellModeActive,
1180
+ // Escape prompt
1181
+ handleEscapePromptChange,
1182
+ // Cancel ongoing request
1183
+ cancelOngoingRequest,
1184
+ };
1185
+ return (_jsx(UIStateProvider, { value: uiState, children: _jsx(UIActionsProvider, { value: uiActions, children: _jsx(DefaultAppLayout, { config: config, settings: settings, startupWarnings: startupWarnings, version: props.version, nightly: nightly, mainControlsRef: mainControlsRef, availableTerminalHeight: availableTerminalHeight, contextFileNames: contextFileNames, updateInfo: updateInfo }) }) }));
1186
+ };
1187
+ //# sourceMappingURL=AppContainer.js.map