fss-link 1.0.40 → 1.0.45

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 (428) hide show
  1. package/dist/commands/mcp/add.test.ts +122 -0
  2. package/dist/commands/mcp/add.ts +222 -0
  3. package/dist/commands/mcp/list.test.ts +154 -0
  4. package/dist/commands/mcp/list.ts +139 -0
  5. package/dist/commands/mcp/remove.test.ts +69 -0
  6. package/dist/commands/mcp/remove.ts +60 -0
  7. package/dist/commands/mcp.test.ts +55 -0
  8. package/dist/commands/mcp.ts +27 -0
  9. package/dist/config/apiValidation.test.ts +118 -0
  10. package/dist/config/auth.test.ts +79 -0
  11. package/dist/config/auth.ts +100 -0
  12. package/dist/config/config.integration.test.ts +407 -0
  13. package/dist/config/config.test.ts +1952 -0
  14. package/dist/config/config.ts +690 -0
  15. package/dist/config/database.test.ts +96 -0
  16. package/dist/config/database.ts +752 -0
  17. package/dist/config/extension.test.ts +236 -0
  18. package/dist/config/extension.ts +180 -0
  19. package/dist/config/keyBindings.test.ts +62 -0
  20. package/dist/config/keyBindings.ts +184 -0
  21. package/dist/config/modelManager.ts +275 -0
  22. package/dist/config/providerManager.ts +244 -0
  23. package/dist/config/providerPersistence.test.ts +377 -0
  24. package/dist/config/providerPersistence.ts +105 -0
  25. package/dist/config/sandboxConfig.ts +107 -0
  26. package/dist/config/settings.test.ts +1424 -0
  27. package/dist/config/settings.ts +517 -0
  28. package/dist/config/settingsSchema.test.ts +252 -0
  29. package/dist/config/settingsSchema.ts +728 -0
  30. package/dist/config/trustedFolders.test.ts +208 -0
  31. package/dist/config/trustedFolders.ts +167 -0
  32. package/dist/gemini.test.tsx +252 -0
  33. package/dist/gemini.tsx +357 -0
  34. package/dist/generated/git-commit.ts +10 -0
  35. package/dist/index.ts +21 -0
  36. package/dist/nonInteractiveCli.test.ts +276 -0
  37. package/dist/nonInteractiveCli.ts +143 -0
  38. package/dist/package.json +87 -87
  39. package/dist/patches/is-in-ci.ts +17 -0
  40. package/dist/services/BuiltinCommandLoader.test.ts +127 -0
  41. package/dist/services/BuiltinCommandLoader.ts +95 -0
  42. package/dist/services/CommandService.test.ts +352 -0
  43. package/dist/services/CommandService.ts +103 -0
  44. package/dist/services/FileCommandLoader.test.ts +1002 -0
  45. package/dist/services/FileCommandLoader.ts +289 -0
  46. package/dist/services/McpPromptLoader.ts +231 -0
  47. package/dist/services/SearchEngineConfigProvider.ts +100 -0
  48. package/dist/services/prompt-processors/argumentProcessor.test.ts +41 -0
  49. package/dist/services/prompt-processors/argumentProcessor.ts +23 -0
  50. package/dist/services/prompt-processors/shellProcessor.test.ts +709 -0
  51. package/dist/services/prompt-processors/shellProcessor.ts +248 -0
  52. package/dist/services/prompt-processors/types.ts +44 -0
  53. package/dist/services/types.ts +24 -0
  54. package/dist/src/config/apiValidation.test.d.ts +6 -0
  55. package/dist/src/config/apiValidation.test.js +99 -0
  56. package/dist/src/config/apiValidation.test.js.map +1 -0
  57. package/dist/src/config/database.d.ts +32 -0
  58. package/dist/src/config/database.js +281 -2
  59. package/dist/src/config/database.js.map +1 -1
  60. package/dist/src/config/database.test.d.ts +6 -0
  61. package/dist/src/config/database.test.js +80 -0
  62. package/dist/src/config/database.test.js.map +1 -0
  63. package/dist/src/config/providerManager.d.ts +74 -0
  64. package/dist/src/config/providerManager.js +203 -0
  65. package/dist/src/config/providerManager.js.map +1 -0
  66. package/dist/src/config/providerPersistence.d.ts +75 -0
  67. package/dist/src/config/providerPersistence.js +55 -0
  68. package/dist/src/config/providerPersistence.js.map +1 -0
  69. package/dist/src/config/providerPersistence.test.d.ts +6 -0
  70. package/dist/src/config/providerPersistence.test.js +283 -0
  71. package/dist/src/config/providerPersistence.test.js.map +1 -0
  72. package/dist/src/config/settingsSchema.d.ts +9 -0
  73. package/dist/src/config/settingsSchema.js +9 -0
  74. package/dist/src/config/settingsSchema.js.map +1 -1
  75. package/dist/src/generated/git-commit.d.ts +1 -1
  76. package/dist/src/generated/git-commit.js +1 -1
  77. package/dist/src/services/BuiltinCommandLoader.js +2 -0
  78. package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
  79. package/dist/src/ui/App.js +14 -2
  80. package/dist/src/ui/App.js.map +1 -1
  81. package/dist/src/ui/commands/contextCommand.d.ts +7 -0
  82. package/dist/src/ui/commands/contextCommand.js +115 -0
  83. package/dist/src/ui/commands/contextCommand.js.map +1 -0
  84. package/dist/src/ui/components/ContextUsageDisplay.d.ts +3 -1
  85. package/dist/src/ui/components/ContextUsageDisplay.js +43 -3
  86. package/dist/src/ui/components/ContextUsageDisplay.js.map +1 -1
  87. package/dist/src/ui/components/Footer.d.ts +1 -0
  88. package/dist/src/ui/components/Footer.js +2 -2
  89. package/dist/src/ui/components/Footer.js.map +1 -1
  90. package/dist/src/ui/components/GeminiKeyDialog.d.ts +11 -0
  91. package/dist/src/ui/components/GeminiKeyDialog.js +156 -0
  92. package/dist/src/ui/components/GeminiKeyDialog.js.map +1 -0
  93. package/dist/src/ui/components/OpenAIEndpointDialog.d.ts +19 -0
  94. package/dist/src/ui/components/OpenAIEndpointDialog.js +163 -0
  95. package/dist/src/ui/components/OpenAIEndpointDialog.js.map +1 -0
  96. package/dist/src/ui/components/WelcomeBackDialog.d.ts +36 -0
  97. package/dist/src/ui/components/WelcomeBackDialog.js +109 -0
  98. package/dist/src/ui/components/WelcomeBackDialog.js.map +1 -0
  99. package/dist/src/ui/hooks/useWelcomeBack.d.ts +52 -0
  100. package/dist/src/ui/hooks/useWelcomeBack.js +214 -0
  101. package/dist/src/ui/hooks/useWelcomeBack.js.map +1 -0
  102. package/dist/src/zed-integration/schema.d.ts +1516 -1516
  103. package/dist/test-setup.ts +12 -0
  104. package/dist/test-utils/customMatchers.ts +65 -0
  105. package/dist/test-utils/mockCommandContext.test.ts +62 -0
  106. package/dist/test-utils/mockCommandContext.ts +105 -0
  107. package/dist/test-utils/render.tsx +18 -0
  108. package/dist/tsconfig.tsbuildinfo +1 -1
  109. package/dist/ui/App.test.tsx +2181 -0
  110. package/dist/ui/App.tsx +1344 -0
  111. package/dist/ui/IdeIntegrationNudge.tsx +98 -0
  112. package/dist/ui/__snapshots__/App.test.tsx.snap +124 -0
  113. package/dist/ui/colors.ts +56 -0
  114. package/dist/ui/commands/aboutCommand.test.ts +153 -0
  115. package/dist/ui/commands/aboutCommand.ts +49 -0
  116. package/dist/ui/commands/authCommand.test.ts +36 -0
  117. package/dist/ui/commands/authCommand.ts +17 -0
  118. package/dist/ui/commands/bugCommand.test.ts +114 -0
  119. package/dist/ui/commands/bugCommand.ts +92 -0
  120. package/dist/ui/commands/chatCommand.test.ts +414 -0
  121. package/dist/ui/commands/chatCommand.ts +280 -0
  122. package/dist/ui/commands/clearCommand.test.ts +100 -0
  123. package/dist/ui/commands/clearCommand.ts +29 -0
  124. package/dist/ui/commands/compressCommand.test.ts +129 -0
  125. package/dist/ui/commands/compressCommand.ts +78 -0
  126. package/dist/ui/commands/contextCommand.ts +132 -0
  127. package/dist/ui/commands/copyCommand.test.ts +296 -0
  128. package/dist/ui/commands/copyCommand.ts +67 -0
  129. package/dist/ui/commands/corgiCommand.test.ts +34 -0
  130. package/dist/ui/commands/corgiCommand.ts +16 -0
  131. package/dist/ui/commands/directoryCommand.test.tsx +185 -0
  132. package/dist/ui/commands/directoryCommand.tsx +179 -0
  133. package/dist/ui/commands/docsCommand.test.ts +99 -0
  134. package/dist/ui/commands/docsCommand.ts +42 -0
  135. package/dist/ui/commands/editorCommand.test.ts +30 -0
  136. package/dist/ui/commands/editorCommand.ts +21 -0
  137. package/dist/ui/commands/extensionsCommand.test.ts +67 -0
  138. package/dist/ui/commands/extensionsCommand.ts +46 -0
  139. package/dist/ui/commands/helpCommand.test.ts +52 -0
  140. package/dist/ui/commands/helpCommand.ts +23 -0
  141. package/dist/ui/commands/ideCommand.test.ts +255 -0
  142. package/dist/ui/commands/ideCommand.ts +283 -0
  143. package/dist/ui/commands/initCommand.test.ts +127 -0
  144. package/dist/ui/commands/initCommand.ts +117 -0
  145. package/dist/ui/commands/mcpCommand.test.ts +1057 -0
  146. package/dist/ui/commands/mcpCommand.ts +531 -0
  147. package/dist/ui/commands/memoryCommand.test.ts +344 -0
  148. package/dist/ui/commands/memoryCommand.ts +305 -0
  149. package/dist/ui/commands/privacyCommand.test.ts +38 -0
  150. package/dist/ui/commands/privacyCommand.ts +17 -0
  151. package/dist/ui/commands/quitCommand.test.ts +55 -0
  152. package/dist/ui/commands/quitCommand.ts +36 -0
  153. package/dist/ui/commands/restoreCommand.test.ts +250 -0
  154. package/dist/ui/commands/restoreCommand.ts +157 -0
  155. package/dist/ui/commands/searchEngineSetupCommand.ts +18 -0
  156. package/dist/ui/commands/settingsCommand.test.ts +36 -0
  157. package/dist/ui/commands/settingsCommand.ts +17 -0
  158. package/dist/ui/commands/setupGithubCommand.test.ts +238 -0
  159. package/dist/ui/commands/setupGithubCommand.ts +212 -0
  160. package/dist/ui/commands/speakCommand.ts +175 -0
  161. package/dist/ui/commands/statsCommand.test.ts +78 -0
  162. package/dist/ui/commands/statsCommand.ts +70 -0
  163. package/dist/ui/commands/terminalSetupCommand.test.ts +85 -0
  164. package/dist/ui/commands/terminalSetupCommand.ts +45 -0
  165. package/dist/ui/commands/themeCommand.test.ts +38 -0
  166. package/dist/ui/commands/themeCommand.ts +17 -0
  167. package/dist/ui/commands/toolsCommand.test.ts +105 -0
  168. package/dist/ui/commands/toolsCommand.ts +71 -0
  169. package/dist/ui/commands/ttsCommand.ts +143 -0
  170. package/dist/ui/commands/types.ts +204 -0
  171. package/dist/ui/commands/vimCommand.ts +25 -0
  172. package/dist/ui/commands/voiceCommand.ts +125 -0
  173. package/dist/ui/components/AboutBox.tsx +133 -0
  174. package/dist/ui/components/AsciiArt.ts +54 -0
  175. package/dist/ui/components/AuthDialog.test.tsx +334 -0
  176. package/dist/ui/components/AuthDialog.tsx +289 -0
  177. package/dist/ui/components/AuthInProgress.tsx +62 -0
  178. package/dist/ui/components/AutoAcceptIndicator.tsx +47 -0
  179. package/dist/ui/components/ConsoleSummaryDisplay.tsx +35 -0
  180. package/dist/ui/components/ContextSummaryDisplay.test.tsx +85 -0
  181. package/dist/ui/components/ContextSummaryDisplay.tsx +120 -0
  182. package/dist/ui/components/ContextUsageDisplay.tsx +77 -0
  183. package/dist/ui/components/DebugProfiler.tsx +36 -0
  184. package/dist/ui/components/DetailedMessagesDisplay.tsx +82 -0
  185. package/dist/ui/components/EditorSettingsDialog.tsx +172 -0
  186. package/dist/ui/components/FolderTrustDialog.test.tsx +36 -0
  187. package/dist/ui/components/FolderTrustDialog.tsx +74 -0
  188. package/dist/ui/components/Footer.test.tsx +159 -0
  189. package/dist/ui/components/Footer.tsx +158 -0
  190. package/dist/ui/components/GeminiKeyDialog.tsx +252 -0
  191. package/dist/ui/components/GeminiRespondingSpinner.tsx +34 -0
  192. package/dist/ui/components/Header.test.tsx +44 -0
  193. package/dist/ui/components/Header.tsx +70 -0
  194. package/dist/ui/components/Help.tsx +174 -0
  195. package/dist/ui/components/HistoryItemDisplay.test.tsx +125 -0
  196. package/dist/ui/components/HistoryItemDisplay.tsx +98 -0
  197. package/dist/ui/components/InputPrompt.test.tsx +1467 -0
  198. package/dist/ui/components/InputPrompt.tsx +641 -0
  199. package/dist/ui/components/LMStudioModelPrompt.tsx +215 -0
  200. package/dist/ui/components/LoadingIndicator.test.tsx +296 -0
  201. package/dist/ui/components/LoadingIndicator.tsx +82 -0
  202. package/dist/ui/components/MemoryUsageDisplay.tsx +36 -0
  203. package/dist/ui/components/ModelStatsDisplay.test.tsx +252 -0
  204. package/dist/ui/components/ModelStatsDisplay.tsx +197 -0
  205. package/dist/ui/components/OllamaModelPrompt.tsx +206 -0
  206. package/dist/ui/components/OpenAIEndpointDialog.tsx +261 -0
  207. package/dist/ui/components/OpenAIKeyPrompt.test.tsx +64 -0
  208. package/dist/ui/components/OpenAIKeyPrompt.tsx +197 -0
  209. package/dist/ui/components/PrepareLabel.tsx +48 -0
  210. package/dist/ui/components/SearchEngineConfigDialog.tsx +280 -0
  211. package/dist/ui/components/SessionSummaryDisplay.test.tsx +75 -0
  212. package/dist/ui/components/SessionSummaryDisplay.tsx +18 -0
  213. package/dist/ui/components/SettingsDialog.test.tsx +865 -0
  214. package/dist/ui/components/SettingsDialog.tsx +753 -0
  215. package/dist/ui/components/ShellConfirmationDialog.test.tsx +53 -0
  216. package/dist/ui/components/ShellConfirmationDialog.tsx +103 -0
  217. package/dist/ui/components/ShellModeIndicator.tsx +18 -0
  218. package/dist/ui/components/ShowMoreLines.tsx +40 -0
  219. package/dist/ui/components/StatsDisplay.test.tsx +401 -0
  220. package/dist/ui/components/StatsDisplay.tsx +273 -0
  221. package/dist/ui/components/SuggestionsDisplay.tsx +102 -0
  222. package/dist/ui/components/ThemeDialog.tsx +310 -0
  223. package/dist/ui/components/Tips.tsx +45 -0
  224. package/dist/ui/components/TodoDisplay.test.tsx +97 -0
  225. package/dist/ui/components/TodoDisplay.tsx +72 -0
  226. package/dist/ui/components/ToolStatsDisplay.test.tsx +180 -0
  227. package/dist/ui/components/ToolStatsDisplay.tsx +208 -0
  228. package/dist/ui/components/UpdateNotification.tsx +23 -0
  229. package/dist/ui/components/WelcomeBackDialog.tsx +290 -0
  230. package/dist/ui/components/__snapshots__/IDEContextDetailDisplay.test.tsx.snap +24 -0
  231. package/dist/ui/components/__snapshots__/ModelStatsDisplay.test.tsx.snap +121 -0
  232. package/dist/ui/components/__snapshots__/SessionSummaryDisplay.test.tsx.snap +30 -0
  233. package/dist/ui/components/__snapshots__/ShellConfirmationDialog.test.tsx.snap +21 -0
  234. package/dist/ui/components/__snapshots__/StatsDisplay.test.tsx.snap +264 -0
  235. package/dist/ui/components/__snapshots__/ToolStatsDisplay.test.tsx.snap +91 -0
  236. package/dist/ui/components/messages/CompressionMessage.tsx +49 -0
  237. package/dist/ui/components/messages/DiffRenderer.test.tsx +365 -0
  238. package/dist/ui/components/messages/DiffRenderer.tsx +358 -0
  239. package/dist/ui/components/messages/ErrorMessage.tsx +31 -0
  240. package/dist/ui/components/messages/GeminiMessage.tsx +43 -0
  241. package/dist/ui/components/messages/GeminiMessageContent.tsx +43 -0
  242. package/dist/ui/components/messages/InfoMessage.tsx +32 -0
  243. package/dist/ui/components/messages/ToolConfirmationMessage.test.tsx +58 -0
  244. package/dist/ui/components/messages/ToolConfirmationMessage.tsx +297 -0
  245. package/dist/ui/components/messages/ToolGroupMessage.tsx +126 -0
  246. package/dist/ui/components/messages/ToolMessage.test.tsx +183 -0
  247. package/dist/ui/components/messages/ToolMessage.tsx +296 -0
  248. package/dist/ui/components/messages/UserMessage.tsx +43 -0
  249. package/dist/ui/components/messages/UserShellMessage.tsx +25 -0
  250. package/dist/ui/components/shared/MaxSizedBox.test.tsx +425 -0
  251. package/dist/ui/components/shared/MaxSizedBox.tsx +624 -0
  252. package/dist/ui/components/shared/RadioButtonSelect.test.tsx +181 -0
  253. package/dist/ui/components/shared/RadioButtonSelect.tsx +234 -0
  254. package/dist/ui/components/shared/__snapshots__/RadioButtonSelect.test.tsx.snap +47 -0
  255. package/dist/ui/components/shared/text-buffer.test.ts +1728 -0
  256. package/dist/ui/components/shared/text-buffer.ts +2227 -0
  257. package/dist/ui/components/shared/vim-buffer-actions.test.ts +1119 -0
  258. package/dist/ui/components/shared/vim-buffer-actions.ts +814 -0
  259. package/dist/ui/constants.ts +17 -0
  260. package/dist/ui/contexts/KeypressContext.test.tsx +391 -0
  261. package/dist/ui/contexts/KeypressContext.tsx +440 -0
  262. package/dist/ui/contexts/OverflowContext.tsx +87 -0
  263. package/dist/ui/contexts/SessionContext.test.tsx +132 -0
  264. package/dist/ui/contexts/SessionContext.tsx +143 -0
  265. package/dist/ui/contexts/SettingsContext.tsx +20 -0
  266. package/dist/ui/contexts/StreamingContext.tsx +22 -0
  267. package/dist/ui/contexts/VimModeContext.tsx +79 -0
  268. package/dist/ui/editors/editorSettingsManager.ts +66 -0
  269. package/dist/ui/hooks/atCommandProcessor.test.ts +1102 -0
  270. package/dist/ui/hooks/atCommandProcessor.ts +485 -0
  271. package/dist/ui/hooks/shellCommandProcessor.test.ts +481 -0
  272. package/dist/ui/hooks/shellCommandProcessor.ts +314 -0
  273. package/dist/ui/hooks/slashCommandProcessor.test.ts +1044 -0
  274. package/dist/ui/hooks/slashCommandProcessor.ts +595 -0
  275. package/dist/ui/hooks/useAtCompletion.test.ts +497 -0
  276. package/dist/ui/hooks/useAtCompletion.ts +244 -0
  277. package/dist/ui/hooks/useAuthCommand.ts +129 -0
  278. package/dist/ui/hooks/useAutoAcceptIndicator.test.ts +300 -0
  279. package/dist/ui/hooks/useAutoAcceptIndicator.ts +52 -0
  280. package/dist/ui/hooks/useBracketedPaste.ts +37 -0
  281. package/dist/ui/hooks/useCommandCompletion.test.ts +518 -0
  282. package/dist/ui/hooks/useCommandCompletion.tsx +238 -0
  283. package/dist/ui/hooks/useCompletion.ts +128 -0
  284. package/dist/ui/hooks/useConsoleMessages.test.ts +147 -0
  285. package/dist/ui/hooks/useConsoleMessages.ts +110 -0
  286. package/dist/ui/hooks/useEditorSettings.test.ts +283 -0
  287. package/dist/ui/hooks/useEditorSettings.ts +75 -0
  288. package/dist/ui/hooks/useFocus.test.ts +119 -0
  289. package/dist/ui/hooks/useFocus.ts +48 -0
  290. package/dist/ui/hooks/useFolderTrust.test.ts +159 -0
  291. package/dist/ui/hooks/useFolderTrust.ts +72 -0
  292. package/dist/ui/hooks/useGeminiStream.test.tsx +1998 -0
  293. package/dist/ui/hooks/useGeminiStream.ts +1017 -0
  294. package/dist/ui/hooks/useGitBranchName.test.ts +280 -0
  295. package/dist/ui/hooks/useGitBranchName.ts +79 -0
  296. package/dist/ui/hooks/useHistoryManager.test.ts +202 -0
  297. package/dist/ui/hooks/useHistoryManager.ts +111 -0
  298. package/dist/ui/hooks/useInputHistory.test.ts +261 -0
  299. package/dist/ui/hooks/useInputHistory.ts +111 -0
  300. package/dist/ui/hooks/useKeypress.test.ts +280 -0
  301. package/dist/ui/hooks/useKeypress.ts +39 -0
  302. package/dist/ui/hooks/useKittyKeyboardProtocol.ts +31 -0
  303. package/dist/ui/hooks/useLoadingIndicator.test.ts +139 -0
  304. package/dist/ui/hooks/useLoadingIndicator.ts +57 -0
  305. package/dist/ui/hooks/useLogger.ts +32 -0
  306. package/dist/ui/hooks/useMessageQueue.test.ts +226 -0
  307. package/dist/ui/hooks/useMessageQueue.ts +69 -0
  308. package/dist/ui/hooks/usePhraseCycler.test.ts +145 -0
  309. package/dist/ui/hooks/usePhraseCycler.ts +198 -0
  310. package/dist/ui/hooks/usePrivacySettings.test.ts +242 -0
  311. package/dist/ui/hooks/usePrivacySettings.ts +150 -0
  312. package/dist/ui/hooks/useReactToolScheduler.ts +309 -0
  313. package/dist/ui/hooks/useRefreshMemoryCommand.ts +7 -0
  314. package/dist/ui/hooks/useReverseSearchCompletion.test.tsx +260 -0
  315. package/dist/ui/hooks/useReverseSearchCompletion.tsx +95 -0
  316. package/dist/ui/hooks/useSettingsCommand.ts +25 -0
  317. package/dist/ui/hooks/useShellHistory.test.ts +219 -0
  318. package/dist/ui/hooks/useShellHistory.ts +133 -0
  319. package/dist/ui/hooks/useShowMemoryCommand.ts +75 -0
  320. package/dist/ui/hooks/useSlashCompletion.test.ts +434 -0
  321. package/dist/ui/hooks/useSlashCompletion.ts +187 -0
  322. package/dist/ui/hooks/useStateAndRef.ts +36 -0
  323. package/dist/ui/hooks/useTerminalSize.ts +32 -0
  324. package/dist/ui/hooks/useThemeCommand.ts +110 -0
  325. package/dist/ui/hooks/useTimer.test.ts +120 -0
  326. package/dist/ui/hooks/useTimer.ts +65 -0
  327. package/dist/ui/hooks/useToolScheduler.test.ts +1123 -0
  328. package/dist/ui/hooks/useWelcomeBack.ts +253 -0
  329. package/dist/ui/hooks/vim.test.ts +1691 -0
  330. package/dist/ui/hooks/vim.ts +784 -0
  331. package/dist/ui/keyMatchers.test.ts +337 -0
  332. package/dist/ui/keyMatchers.ts +105 -0
  333. package/dist/ui/privacy/CloudFreePrivacyNotice.tsx +117 -0
  334. package/dist/ui/privacy/CloudPaidPrivacyNotice.tsx +59 -0
  335. package/dist/ui/privacy/GeminiPrivacyNotice.tsx +62 -0
  336. package/dist/ui/privacy/PrivacyNotice.tsx +42 -0
  337. package/dist/ui/semantic-colors.ts +26 -0
  338. package/dist/ui/themes/ansi-light.ts +150 -0
  339. package/dist/ui/themes/ansi.ts +159 -0
  340. package/dist/ui/themes/atom-one-dark.ts +147 -0
  341. package/dist/ui/themes/ayu-light.ts +139 -0
  342. package/dist/ui/themes/ayu.ts +113 -0
  343. package/dist/ui/themes/color-utils.test.ts +221 -0
  344. package/dist/ui/themes/color-utils.ts +231 -0
  345. package/dist/ui/themes/default-light.ts +108 -0
  346. package/dist/ui/themes/default.ts +151 -0
  347. package/dist/ui/themes/dracula.ts +124 -0
  348. package/dist/ui/themes/fss-code-dark.ts +156 -0
  349. package/dist/ui/themes/fss-dark.ts +113 -0
  350. package/dist/ui/themes/fss-light.ts +139 -0
  351. package/dist/ui/themes/github-dark.ts +147 -0
  352. package/dist/ui/themes/github-light.ts +149 -0
  353. package/dist/ui/themes/googlecode.ts +146 -0
  354. package/dist/ui/themes/no-color.ts +125 -0
  355. package/dist/ui/themes/qwen-dark.ts +118 -0
  356. package/dist/ui/themes/qwen-light.ts +144 -0
  357. package/dist/ui/themes/semantic-tokens.ts +127 -0
  358. package/dist/ui/themes/shades-of-purple.ts +352 -0
  359. package/dist/ui/themes/theme-manager.test.ts +99 -0
  360. package/dist/ui/themes/theme-manager.ts +257 -0
  361. package/dist/ui/themes/theme.test.ts +97 -0
  362. package/dist/ui/themes/theme.ts +451 -0
  363. package/dist/ui/themes/xcode.ts +154 -0
  364. package/dist/ui/types.ts +255 -0
  365. package/dist/ui/utils/CodeColorizer.tsx +217 -0
  366. package/dist/ui/utils/ConsolePatcher.ts +71 -0
  367. package/dist/ui/utils/InlineMarkdownRenderer.tsx +173 -0
  368. package/dist/ui/utils/MarkdownDisplay.test.tsx +244 -0
  369. package/dist/ui/utils/MarkdownDisplay.tsx +415 -0
  370. package/dist/ui/utils/TableRenderer.tsx +159 -0
  371. package/dist/ui/utils/__snapshots__/MarkdownDisplay.test.tsx.snap +93 -0
  372. package/dist/ui/utils/clipboardUtils.test.ts +76 -0
  373. package/dist/ui/utils/clipboardUtils.ts +149 -0
  374. package/dist/ui/utils/commandUtils.test.ts +384 -0
  375. package/dist/ui/utils/commandUtils.ts +106 -0
  376. package/dist/ui/utils/computeStats.test.ts +292 -0
  377. package/dist/ui/utils/computeStats.ts +86 -0
  378. package/dist/ui/utils/displayUtils.test.ts +58 -0
  379. package/dist/ui/utils/displayUtils.ts +32 -0
  380. package/dist/ui/utils/formatters.test.ts +72 -0
  381. package/dist/ui/utils/formatters.ts +63 -0
  382. package/dist/ui/utils/isNarrowWidth.ts +9 -0
  383. package/dist/ui/utils/kittyProtocolDetector.ts +105 -0
  384. package/dist/ui/utils/markdownUtilities.test.ts +50 -0
  385. package/dist/ui/utils/markdownUtilities.ts +125 -0
  386. package/dist/ui/utils/platformConstants.ts +52 -0
  387. package/dist/ui/utils/terminalSetup.ts +342 -0
  388. package/dist/ui/utils/textUtils.ts +40 -0
  389. package/dist/ui/utils/updateCheck.test.ts +163 -0
  390. package/dist/ui/utils/updateCheck.ts +100 -0
  391. package/dist/utils/checks.ts +28 -0
  392. package/dist/utils/cleanup.test.ts +68 -0
  393. package/dist/utils/cleanup.ts +36 -0
  394. package/dist/utils/dialogScopeUtils.ts +64 -0
  395. package/dist/utils/events.ts +14 -0
  396. package/dist/utils/gitUtils.test.ts +149 -0
  397. package/dist/utils/gitUtils.ts +116 -0
  398. package/dist/utils/handleAutoUpdate.test.ts +272 -0
  399. package/dist/utils/handleAutoUpdate.ts +145 -0
  400. package/dist/utils/installationInfo.test.ts +315 -0
  401. package/dist/utils/installationInfo.ts +176 -0
  402. package/dist/utils/package.ts +38 -0
  403. package/dist/utils/readStdin.ts +51 -0
  404. package/dist/utils/resolvePath.ts +21 -0
  405. package/dist/utils/sandbox-macos-permissive-closed.sb +32 -0
  406. package/dist/utils/sandbox-macos-permissive-open.sb +25 -0
  407. package/dist/utils/sandbox-macos-permissive-proxied.sb +37 -0
  408. package/dist/utils/sandbox-macos-restrictive-closed.sb +93 -0
  409. package/dist/utils/sandbox-macos-restrictive-open.sb +96 -0
  410. package/dist/utils/sandbox-macos-restrictive-proxied.sb +98 -0
  411. package/dist/utils/sandbox.ts +962 -0
  412. package/dist/utils/settingsUtils.test.ts +797 -0
  413. package/dist/utils/settingsUtils.ts +489 -0
  414. package/dist/utils/spawnWrapper.ts +9 -0
  415. package/dist/utils/startupWarnings.test.ts +83 -0
  416. package/dist/utils/startupWarnings.ts +40 -0
  417. package/dist/utils/updateEventEmitter.ts +13 -0
  418. package/dist/utils/userStartupWarnings.test.ts +87 -0
  419. package/dist/utils/userStartupWarnings.ts +69 -0
  420. package/dist/utils/version.ts +12 -0
  421. package/dist/validateNonInterActiveAuth.test.ts +260 -0
  422. package/dist/validateNonInterActiveAuth.ts +51 -0
  423. package/dist/vitest.config.ts +37 -0
  424. package/dist/zed-integration/acp.ts +366 -0
  425. package/dist/zed-integration/fileSystemService.ts +47 -0
  426. package/dist/zed-integration/schema.ts +466 -0
  427. package/dist/zed-integration/zedIntegration.ts +944 -0
  428. package/package.json +2 -2
@@ -0,0 +1,595 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { useCallback, useMemo, useEffect, useState } from 'react';
8
+ import { type PartListUnion } from '@google/genai';
9
+ import process from 'node:process';
10
+ import { UseHistoryManagerReturn } from './useHistoryManager.js';
11
+ import {
12
+ Config,
13
+ GitService,
14
+ Logger,
15
+ logSlashCommand,
16
+ makeSlashCommandEvent,
17
+ SlashCommandStatus,
18
+ ToolConfirmationOutcome,
19
+ } from 'fss-link-core';
20
+ import { useSessionStats } from '../contexts/SessionContext.js';
21
+ import { runExitCleanup } from '../../utils/cleanup.js';
22
+ import {
23
+ Message,
24
+ MessageType,
25
+ HistoryItemWithoutId,
26
+ HistoryItem,
27
+ SlashCommandProcessorResult,
28
+ } from '../types.js';
29
+ import { LoadedSettings } from '../../config/settings.js';
30
+ import { type CommandContext, type SlashCommand } from '../commands/types.js';
31
+ import { CommandService } from '../../services/CommandService.js';
32
+ import { BuiltinCommandLoader } from '../../services/BuiltinCommandLoader.js';
33
+ import { FileCommandLoader } from '../../services/FileCommandLoader.js';
34
+ import { McpPromptLoader } from '../../services/McpPromptLoader.js';
35
+
36
+ /**
37
+ * Hook to define and process slash commands (e.g., /help, /clear).
38
+ */
39
+ export const useSlashCommandProcessor = (
40
+ config: Config | null,
41
+ settings: LoadedSettings,
42
+ addItem: UseHistoryManagerReturn['addItem'],
43
+ clearItems: UseHistoryManagerReturn['clearItems'],
44
+ loadHistory: UseHistoryManagerReturn['loadHistory'],
45
+ refreshStatic: () => void,
46
+ onDebugMessage: (message: string) => void,
47
+ openThemeDialog: () => void,
48
+ openAuthDialog: () => void,
49
+ openEditorDialog: () => void,
50
+ openSearchDialog: () => void,
51
+ toggleCorgiMode: () => void,
52
+ setQuittingMessages: (message: HistoryItem[]) => void,
53
+ openPrivacyNotice: () => void,
54
+ openSettingsDialog: () => void,
55
+ toggleVimEnabled: () => Promise<boolean>,
56
+ setIsProcessing: (isProcessing: boolean) => void,
57
+ setGeminiMdFileCount: (count: number) => void,
58
+ ) => {
59
+ const session = useSessionStats();
60
+ const [commands, setCommands] = useState<readonly SlashCommand[]>([]);
61
+ const [reloadTrigger, setReloadTrigger] = useState(0);
62
+
63
+ const reloadCommands = useCallback(() => {
64
+ setReloadTrigger((v) => v + 1);
65
+ }, []);
66
+ const [shellConfirmationRequest, setShellConfirmationRequest] =
67
+ useState<null | {
68
+ commands: string[];
69
+ onConfirm: (
70
+ outcome: ToolConfirmationOutcome,
71
+ approvedCommands?: string[],
72
+ ) => void;
73
+ }>(null);
74
+ const [confirmationRequest, setConfirmationRequest] = useState<null | {
75
+ prompt: React.ReactNode;
76
+ onConfirm: (confirmed: boolean) => void;
77
+ }>(null);
78
+
79
+ const [sessionShellAllowlist, setSessionShellAllowlist] = useState(
80
+ new Set<string>(),
81
+ );
82
+
83
+ // TTS session state
84
+ const [ttsVoice, setTtsVoice] = useState<string>('Bella');
85
+ const [ttsEnabled, setTtsEnabled] = useState<boolean>(false);
86
+
87
+ // Set up TTS voice getter for the core Config
88
+ useEffect(() => {
89
+ if (config) {
90
+ config.setCurrentVoiceGetter(() => ttsVoice);
91
+ }
92
+ }, [config, ttsVoice]);
93
+ const gitService = useMemo(() => {
94
+ if (!config?.getProjectRoot()) {
95
+ return;
96
+ }
97
+ return new GitService(config.getProjectRoot());
98
+ }, [config]);
99
+
100
+ const logger = useMemo(() => {
101
+ const l = new Logger(config?.getSessionId() || '');
102
+ // The logger's initialize is async, but we can create the instance
103
+ // synchronously. Commands that use it will await its initialization.
104
+ return l;
105
+ }, [config]);
106
+
107
+ const [pendingCompressionItem, setPendingCompressionItem] =
108
+ useState<HistoryItemWithoutId | null>(null);
109
+
110
+ const pendingHistoryItems = useMemo(() => {
111
+ const items: HistoryItemWithoutId[] = [];
112
+ if (pendingCompressionItem != null) {
113
+ items.push(pendingCompressionItem);
114
+ }
115
+ return items;
116
+ }, [pendingCompressionItem]);
117
+
118
+ const addMessage = useCallback(
119
+ (message: Message) => {
120
+ // Convert Message to HistoryItemWithoutId
121
+ let historyItemContent: HistoryItemWithoutId;
122
+ if (message.type === MessageType.ABOUT) {
123
+ historyItemContent = {
124
+ type: 'about',
125
+ cliVersion: message.cliVersion,
126
+ osVersion: message.osVersion,
127
+ sandboxEnv: message.sandboxEnv,
128
+ modelVersion: message.modelVersion,
129
+ selectedAuthType: message.selectedAuthType,
130
+ gcpProject: message.gcpProject,
131
+ ideClient: message.ideClient,
132
+ };
133
+ } else if (message.type === MessageType.HELP) {
134
+ historyItemContent = {
135
+ type: 'help',
136
+ timestamp: message.timestamp,
137
+ };
138
+ } else if (message.type === MessageType.STATS) {
139
+ historyItemContent = {
140
+ type: 'stats',
141
+ duration: message.duration,
142
+ };
143
+ } else if (message.type === MessageType.MODEL_STATS) {
144
+ historyItemContent = {
145
+ type: 'model_stats',
146
+ };
147
+ } else if (message.type === MessageType.TOOL_STATS) {
148
+ historyItemContent = {
149
+ type: 'tool_stats',
150
+ };
151
+ } else if (message.type === MessageType.QUIT) {
152
+ historyItemContent = {
153
+ type: 'quit',
154
+ duration: message.duration,
155
+ };
156
+ } else if (message.type === MessageType.COMPRESSION) {
157
+ historyItemContent = {
158
+ type: 'compression',
159
+ compression: message.compression,
160
+ };
161
+ } else {
162
+ historyItemContent = {
163
+ type: message.type,
164
+ text: message.content,
165
+ };
166
+ }
167
+ addItem(historyItemContent, message.timestamp.getTime());
168
+ },
169
+ [addItem],
170
+ );
171
+ const commandContext = useMemo(
172
+ (): CommandContext => ({
173
+ services: {
174
+ config,
175
+ settings,
176
+ git: gitService,
177
+ logger,
178
+ },
179
+ ui: {
180
+ addItem,
181
+ clear: () => {
182
+ clearItems();
183
+ console.clear();
184
+ refreshStatic();
185
+ },
186
+ loadHistory,
187
+ setDebugMessage: onDebugMessage,
188
+ pendingItem: pendingCompressionItem,
189
+ setPendingItem: setPendingCompressionItem,
190
+ toggleCorgiMode,
191
+ toggleVimEnabled,
192
+ setGeminiMdFileCount,
193
+ reloadCommands,
194
+ setTtsVoice,
195
+ setTtsEnabled,
196
+ },
197
+ session: {
198
+ stats: session.stats,
199
+ sessionShellAllowlist,
200
+ ttsVoice,
201
+ ttsEnabled,
202
+ },
203
+ }),
204
+ [
205
+ config,
206
+ settings,
207
+ gitService,
208
+ logger,
209
+ loadHistory,
210
+ addItem,
211
+ clearItems,
212
+ refreshStatic,
213
+ session.stats,
214
+ onDebugMessage,
215
+ pendingCompressionItem,
216
+ setPendingCompressionItem,
217
+ toggleCorgiMode,
218
+ toggleVimEnabled,
219
+ sessionShellAllowlist,
220
+ setGeminiMdFileCount,
221
+ reloadCommands,
222
+ ttsVoice,
223
+ ttsEnabled,
224
+ setTtsVoice,
225
+ setTtsEnabled,
226
+ ],
227
+ );
228
+
229
+ useEffect(() => {
230
+ if (!config) {
231
+ return;
232
+ }
233
+
234
+ const ideClient = config.getIdeClient();
235
+ const listener = () => {
236
+ reloadCommands();
237
+ };
238
+
239
+ ideClient.addStatusChangeListener(listener);
240
+
241
+ return () => {
242
+ ideClient.removeStatusChangeListener(listener);
243
+ };
244
+ }, [config, reloadCommands]);
245
+
246
+ useEffect(() => {
247
+ const controller = new AbortController();
248
+ const load = async () => {
249
+ const loaders = [
250
+ new McpPromptLoader(config),
251
+ new BuiltinCommandLoader(config),
252
+ new FileCommandLoader(config),
253
+ ];
254
+ const commandService = await CommandService.create(
255
+ loaders,
256
+ controller.signal,
257
+ );
258
+ setCommands(commandService.getCommands());
259
+ };
260
+
261
+ load();
262
+
263
+ return () => {
264
+ controller.abort();
265
+ };
266
+ }, [config, reloadTrigger]);
267
+
268
+ const handleSlashCommand = useCallback(
269
+ async (
270
+ rawQuery: PartListUnion,
271
+ oneTimeShellAllowlist?: Set<string>,
272
+ overwriteConfirmed?: boolean,
273
+ ): Promise<SlashCommandProcessorResult | false> => {
274
+ if (typeof rawQuery !== 'string') {
275
+ return false;
276
+ }
277
+
278
+ const trimmed = rawQuery.trim();
279
+ if (!trimmed.startsWith('/') && !trimmed.startsWith('?')) {
280
+ return false;
281
+ }
282
+
283
+ setIsProcessing(true);
284
+
285
+ const userMessageTimestamp = Date.now();
286
+ addItem({ type: MessageType.USER, text: trimmed }, userMessageTimestamp);
287
+
288
+ const parts = trimmed.substring(1).trim().split(/\s+/);
289
+ const commandPath = parts.filter((p) => p); // The parts of the command, e.g., ['memory', 'add']
290
+
291
+
292
+ let currentCommands = commands;
293
+ let commandToExecute: SlashCommand | undefined;
294
+ let pathIndex = 0;
295
+ let hasError = false;
296
+ const canonicalPath: string[] = [];
297
+
298
+ for (const part of commandPath) {
299
+ // TODO: For better performance and architectural clarity, this two-pass
300
+ // search could be replaced. A more optimal approach would be to
301
+ // pre-compute a single lookup map in `CommandService.ts` that resolves
302
+ // all name and alias conflicts during the initial loading phase. The
303
+ // processor would then perform a single, fast lookup on that map.
304
+
305
+ // First pass: check for an exact match on the primary command name.
306
+ let foundCommand = currentCommands.find((cmd) => cmd.name === part);
307
+
308
+ // Second pass: if no primary name matches, check for an alias.
309
+ if (!foundCommand) {
310
+ foundCommand = currentCommands.find((cmd) =>
311
+ cmd.altNames?.includes(part),
312
+ );
313
+ }
314
+
315
+ if (foundCommand) {
316
+ commandToExecute = foundCommand;
317
+ canonicalPath.push(foundCommand.name);
318
+ pathIndex++;
319
+ if (foundCommand.subCommands) {
320
+ currentCommands = foundCommand.subCommands;
321
+ } else {
322
+ break;
323
+ }
324
+ } else {
325
+ break;
326
+ }
327
+ }
328
+
329
+ const resolvedCommandPath = canonicalPath;
330
+ const subcommand =
331
+ resolvedCommandPath.length > 1
332
+ ? resolvedCommandPath.slice(1).join(' ')
333
+ : undefined;
334
+
335
+
336
+ try {
337
+ if (commandToExecute) {
338
+ const args = parts.slice(pathIndex).join(' ');
339
+
340
+ if (commandToExecute.action) {
341
+ const fullCommandContext: CommandContext = {
342
+ ...commandContext,
343
+ invocation: {
344
+ raw: trimmed,
345
+ name: commandToExecute.name,
346
+ args,
347
+ },
348
+ overwriteConfirmed,
349
+ };
350
+
351
+ // If a one-time list is provided for a "Proceed" action, temporarily
352
+ // augment the session allowlist for this single execution.
353
+ if (oneTimeShellAllowlist && oneTimeShellAllowlist.size > 0) {
354
+ fullCommandContext.session = {
355
+ ...fullCommandContext.session,
356
+ sessionShellAllowlist: new Set([
357
+ ...fullCommandContext.session.sessionShellAllowlist,
358
+ ...oneTimeShellAllowlist,
359
+ ]),
360
+ };
361
+ }
362
+ const result = await commandToExecute.action(
363
+ fullCommandContext,
364
+ args,
365
+ );
366
+
367
+ console.debug('[SlashCommand] Command execution result:', result);
368
+
369
+ if (result) {
370
+ switch (result.type) {
371
+ case 'tool':
372
+ return {
373
+ type: 'schedule_tool',
374
+ toolName: result.toolName,
375
+ toolArgs: result.toolArgs,
376
+ };
377
+ case 'message':
378
+ addItem(
379
+ {
380
+ type:
381
+ result.messageType === 'error'
382
+ ? MessageType.ERROR
383
+ : MessageType.INFO,
384
+ text: result.content,
385
+ },
386
+ Date.now(),
387
+ );
388
+ return { type: 'handled' };
389
+ case 'dialog':
390
+ switch (result.dialog) {
391
+ case 'auth':
392
+ openAuthDialog();
393
+ return { type: 'handled' };
394
+ case 'theme':
395
+ openThemeDialog();
396
+ return { type: 'handled' };
397
+ case 'editor':
398
+ openEditorDialog();
399
+ return { type: 'handled' };
400
+ case 'privacy':
401
+ openPrivacyNotice();
402
+ return { type: 'handled' };
403
+ case 'settings':
404
+ openSettingsDialog();
405
+ return { type: 'handled' };
406
+ case 'search':
407
+ openSearchDialog();
408
+ return { type: 'handled' };
409
+ case 'help':
410
+ return { type: 'handled' };
411
+ default: {
412
+ const unhandled: never = result.dialog;
413
+ throw new Error(
414
+ `Unhandled slash command result: ${unhandled}`,
415
+ );
416
+ }
417
+ }
418
+ case 'load_history': {
419
+ await config
420
+ ?.getGeminiClient()
421
+ ?.setHistory(result.clientHistory);
422
+ fullCommandContext.ui.clear();
423
+ result.history.forEach((item, index) => {
424
+ fullCommandContext.ui.addItem(item, index);
425
+ });
426
+ return { type: 'handled' };
427
+ }
428
+ case 'quit':
429
+ setQuittingMessages(result.messages);
430
+ setTimeout(async () => {
431
+ await runExitCleanup();
432
+ process.exit(0);
433
+ }, 100);
434
+ return { type: 'handled' };
435
+
436
+ case 'submit_prompt':
437
+ return {
438
+ type: 'submit_prompt',
439
+ content: result.content,
440
+ };
441
+ case 'confirm_shell_commands': {
442
+ const { outcome, approvedCommands } = await new Promise<{
443
+ outcome: ToolConfirmationOutcome;
444
+ approvedCommands?: string[];
445
+ }>((resolve) => {
446
+ setShellConfirmationRequest({
447
+ commands: result.commandsToConfirm,
448
+ onConfirm: (
449
+ resolvedOutcome,
450
+ resolvedApprovedCommands,
451
+ ) => {
452
+ setShellConfirmationRequest(null); // Close the dialog
453
+ resolve({
454
+ outcome: resolvedOutcome,
455
+ approvedCommands: resolvedApprovedCommands,
456
+ });
457
+ },
458
+ });
459
+ });
460
+
461
+ if (
462
+ outcome === ToolConfirmationOutcome.Cancel ||
463
+ !approvedCommands ||
464
+ approvedCommands.length === 0
465
+ ) {
466
+ return { type: 'handled' };
467
+ }
468
+
469
+ if (outcome === ToolConfirmationOutcome.ProceedAlways) {
470
+ setSessionShellAllowlist(
471
+ (prev) => new Set([...prev, ...approvedCommands]),
472
+ );
473
+ }
474
+
475
+ return await handleSlashCommand(
476
+ result.originalInvocation.raw,
477
+ // Pass the approved commands as a one-time grant for this execution.
478
+ new Set(approvedCommands),
479
+ );
480
+ }
481
+ case 'confirm_action': {
482
+ const { confirmed } = await new Promise<{
483
+ confirmed: boolean;
484
+ }>((resolve) => {
485
+ setConfirmationRequest({
486
+ prompt: result.prompt,
487
+ onConfirm: (resolvedConfirmed) => {
488
+ setConfirmationRequest(null);
489
+ resolve({ confirmed: resolvedConfirmed });
490
+ },
491
+ });
492
+ });
493
+
494
+ if (!confirmed) {
495
+ addItem(
496
+ {
497
+ type: MessageType.INFO,
498
+ text: 'Operation cancelled.',
499
+ },
500
+ Date.now(),
501
+ );
502
+ return { type: 'handled' };
503
+ }
504
+
505
+ return await handleSlashCommand(
506
+ result.originalInvocation.raw,
507
+ undefined,
508
+ true,
509
+ );
510
+ }
511
+ default: {
512
+ const unhandled: never = result;
513
+ throw new Error(
514
+ `Unhandled slash command result: ${unhandled}`,
515
+ );
516
+ }
517
+ }
518
+ }
519
+
520
+ return { type: 'handled' };
521
+ } else if (commandToExecute.subCommands) {
522
+ const helpText = `Command '/${commandToExecute.name}' requires a subcommand. Available:\n${commandToExecute.subCommands
523
+ .map((sc) => ` - ${sc.name}: ${sc.description || ''}`)
524
+ .join('\n')}`;
525
+ addMessage({
526
+ type: MessageType.INFO,
527
+ content: helpText,
528
+ timestamp: new Date(),
529
+ });
530
+ return { type: 'handled' };
531
+ }
532
+ }
533
+
534
+
535
+ // Return false to let AI process the command instead of showing error
536
+ return false;
537
+ } catch (e: unknown) {
538
+ hasError = true;
539
+ if (config) {
540
+ const event = makeSlashCommandEvent({
541
+ command: resolvedCommandPath[0],
542
+ subcommand,
543
+ status: SlashCommandStatus.ERROR,
544
+ });
545
+ logSlashCommand(config, event);
546
+ }
547
+ addItem(
548
+ {
549
+ type: MessageType.ERROR,
550
+ text: e instanceof Error ? e.message : String(e),
551
+ },
552
+ Date.now(),
553
+ );
554
+ return { type: 'handled' };
555
+ } finally {
556
+ if (config && resolvedCommandPath[0] && !hasError) {
557
+ const event = makeSlashCommandEvent({
558
+ command: resolvedCommandPath[0],
559
+ subcommand,
560
+ status: SlashCommandStatus.SUCCESS,
561
+ });
562
+ logSlashCommand(config, event);
563
+ }
564
+ setIsProcessing(false);
565
+ }
566
+ },
567
+ [
568
+ config,
569
+ addItem,
570
+ openAuthDialog,
571
+ commands,
572
+ commandContext,
573
+ addMessage,
574
+ openThemeDialog,
575
+ openPrivacyNotice,
576
+ openEditorDialog,
577
+ openSearchDialog,
578
+ setQuittingMessages,
579
+ openSettingsDialog,
580
+ setShellConfirmationRequest,
581
+ setSessionShellAllowlist,
582
+ setIsProcessing,
583
+ setConfirmationRequest,
584
+ ],
585
+ );
586
+
587
+ return {
588
+ handleSlashCommand,
589
+ slashCommands: commands,
590
+ pendingHistoryItems,
591
+ commandContext,
592
+ shellConfirmationRequest,
593
+ confirmationRequest,
594
+ };
595
+ };