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,98 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { DetectedIde, getIdeInfo } from 'fss-link-core';
8
+ import { Box, Text } from 'ink';
9
+ import {
10
+ RadioButtonSelect,
11
+ RadioSelectItem,
12
+ } from './components/shared/RadioButtonSelect.js';
13
+ import { useKeypress } from './hooks/useKeypress.js';
14
+
15
+ export type IdeIntegrationNudgeResult = {
16
+ userSelection: 'yes' | 'no' | 'dismiss';
17
+ isExtensionPreInstalled: boolean;
18
+ };
19
+
20
+ interface IdeIntegrationNudgeProps {
21
+ ide: DetectedIde;
22
+ onComplete: (result: IdeIntegrationNudgeResult) => void;
23
+ }
24
+
25
+ export function IdeIntegrationNudge({
26
+ ide,
27
+ onComplete,
28
+ }: IdeIntegrationNudgeProps) {
29
+ useKeypress(
30
+ (key) => {
31
+ if (key.name === 'escape') {
32
+ onComplete({
33
+ userSelection: 'no',
34
+ isExtensionPreInstalled: false,
35
+ });
36
+ }
37
+ },
38
+ { isActive: true },
39
+ );
40
+
41
+ const { displayName: ideName } = getIdeInfo(ide);
42
+ // Assume extension is already installed if the env variables are set.
43
+ const isExtensionPreInstalled =
44
+ !!process.env['GEMINI_CLI_IDE_SERVER_PORT'] &&
45
+ !!process.env['GEMINI_CLI_IDE_WORKSPACE_PATH'];
46
+
47
+ const OPTIONS: Array<RadioSelectItem<IdeIntegrationNudgeResult>> = [
48
+ {
49
+ label: 'Yes',
50
+ value: {
51
+ userSelection: 'yes',
52
+ isExtensionPreInstalled,
53
+ },
54
+ },
55
+ {
56
+ label: 'No (esc)',
57
+ value: {
58
+ userSelection: 'no',
59
+ isExtensionPreInstalled,
60
+ },
61
+ },
62
+ {
63
+ label: "No, don't ask again",
64
+ value: {
65
+ userSelection: 'dismiss',
66
+ isExtensionPreInstalled,
67
+ },
68
+ },
69
+ ];
70
+
71
+ const installText = isExtensionPreInstalled
72
+ ? `If you select Yes, the CLI will have access to your open files and display diffs directly in ${
73
+ ideName ?? 'your editor'
74
+ }.`
75
+ : `If you select Yes, we'll install an extension that allows the CLI to access your open files and display diffs directly in ${
76
+ ideName ?? 'your editor'
77
+ }.`;
78
+
79
+ return (
80
+ <Box
81
+ flexDirection="column"
82
+ borderStyle="round"
83
+ borderColor="yellow"
84
+ padding={1}
85
+ width="100%"
86
+ marginLeft={1}
87
+ >
88
+ <Box marginBottom={1} flexDirection="column">
89
+ <Text>
90
+ <Text color="yellow">{'> '}</Text>
91
+ {`Do you want to connect ${ideName ?? 'your'} editor to FSS Link?`}
92
+ </Text>
93
+ <Text dimColor>{installText}</Text>
94
+ </Box>
95
+ <RadioButtonSelect items={OPTIONS} onSelect={onComplete} />
96
+ </Box>
97
+ );
98
+ }
@@ -0,0 +1,124 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`App UI > should render correctly with the prompt input box 1`] = `
4
+ "
5
+ ERROR Element type is invalid: expected a string (for built-in components) or a class/function
6
+ (for composite components) but got: undefined. You likely forgot to export your component
7
+ from the file it's defined in, or you might have mixed up default and named imports.
8
+
9
+ /MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconciler.development.js:
10
+ 14015:28
11
+
12
+ 14012: (resolvedType +=
13
+ 14013: "\\n\\nCheck the render method of \`" + fiberTag + "\`.");
14
+ 14014: fiberTag = 29;
15
+ 14015: pendingProps = Error(
16
+ 14016: "Element type is invalid: expected a string (for built-in components) or a
17
+ class/function (for composite components) but got: " +
18
+ 14017: (pendingProps + "." + resolvedType)
19
+ 14018: );
20
+
21
+ -createFiberFromTypeAn (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-re
22
+ Props conciler.development.js:14015:28)
23
+ -createFiberFromEle (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-recon
24
+ ent ciler.development.js:14029:14)
25
+ -reconcileChildFiber (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reco
26
+ Impl nciler.development.js:5515:31)
27
+ - (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconciler.development.
28
+ js:5693:33)
29
+ -reconcileChild (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconcile
30
+ en r.development.js:6197:13)
31
+ -updateFunctionComp (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-recon
32
+ nent ciler.development.js:6492:7)
33
+ -beginWor (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconciler.deve
34
+ lopment.js:8009:18)
35
+ -runWithFiberIn (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconcile
36
+ EV r.development.js:1738:13)
37
+ -performUnitOfW (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconcile
38
+ rk r.development.js:12834:22)
39
+ -workLoopSyn (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconciler.d
40
+ evelopment.js:12644:41)
41
+ "
42
+ `;
43
+
44
+ exports[`App UI > should render the initial UI correctly 1`] = `
45
+ "
46
+ ERROR Element type is invalid: expected a string (for built-in components) or a class/function
47
+ (for composite components) but got: undefined. You likely forgot to export your component
48
+ from the file it's defined in, or you might have mixed up default and named imports.
49
+
50
+ /MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconciler.development.js:
51
+ 14015:28
52
+
53
+ 14012: (resolvedType +=
54
+ 14013: "\\n\\nCheck the render method of \`" + fiberTag + "\`.");
55
+ 14014: fiberTag = 29;
56
+ 14015: pendingProps = Error(
57
+ 14016: "Element type is invalid: expected a string (for built-in components) or a
58
+ class/function (for composite components) but got: " +
59
+ 14017: (pendingProps + "." + resolvedType)
60
+ 14018: );
61
+
62
+ -createFiberFromTypeAn (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-re
63
+ Props conciler.development.js:14015:28)
64
+ -createFiberFromEle (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-recon
65
+ ent ciler.development.js:14029:14)
66
+ -reconcileChildFiber (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reco
67
+ Impl nciler.development.js:5515:31)
68
+ - (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconciler.development.
69
+ js:5693:33)
70
+ -reconcileChild (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconcile
71
+ en r.development.js:6197:13)
72
+ -updateFunctionComp (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-recon
73
+ nent ciler.development.js:6492:7)
74
+ -beginWor (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconciler.deve
75
+ lopment.js:8009:18)
76
+ -runWithFiberIn (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconcile
77
+ EV r.development.js:1738:13)
78
+ -performUnitOfW (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconcile
79
+ rk r.development.js:12834:22)
80
+ -workLoopSyn (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconciler.d
81
+ evelopment.js:12644:41)
82
+ "
83
+ `;
84
+
85
+ exports[`App UI > when in a narrow terminal > should render with a column layout 1`] = `
86
+ "
87
+ ERROR Element type is invalid: expected a string (for built-in components) or a class/function
88
+ (for composite components) but got: undefined. You likely forgot to export your component
89
+ from the file it's defined in, or you might have mixed up default and named imports.
90
+
91
+ /MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconciler.development.js:
92
+ 14015:28
93
+
94
+ 14012: (resolvedType +=
95
+ 14013: "\\n\\nCheck the render method of \`" + fiberTag + "\`.");
96
+ 14014: fiberTag = 29;
97
+ 14015: pendingProps = Error(
98
+ 14016: "Element type is invalid: expected a string (for built-in components) or a
99
+ class/function (for composite components) but got: " +
100
+ 14017: (pendingProps + "." + resolvedType)
101
+ 14018: );
102
+
103
+ -createFiberFromTypeAn (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-re
104
+ Props conciler.development.js:14015:28)
105
+ -createFiberFromEle (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-recon
106
+ ent ciler.development.js:14029:14)
107
+ -reconcileChildFiber (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reco
108
+ Impl nciler.development.js:5515:31)
109
+ - (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconciler.development.
110
+ js:5693:33)
111
+ -reconcileChild (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconcile
112
+ en r.development.js:6197:13)
113
+ -updateFunctionComp (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-recon
114
+ nent ciler.development.js:6492:7)
115
+ -beginWor (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconciler.deve
116
+ lopment.js:8009:18)
117
+ -runWithFiberIn (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconcile
118
+ EV r.development.js:1738:13)
119
+ -performUnitOfW (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconcile
120
+ rk r.development.js:12834:22)
121
+ -workLoopSyn (/MASTERFOLDER/Projects/fss-link/node_modules/react-reconciler/cjs/react-reconciler.d
122
+ evelopment.js:12644:41)
123
+ "
124
+ `;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { themeManager } from './themes/theme-manager.js';
8
+ import { ColorsTheme } from './themes/theme.js';
9
+
10
+ export const Colors: ColorsTheme = {
11
+ get type() {
12
+ return themeManager.getActiveTheme().colors.type;
13
+ },
14
+ get Foreground() {
15
+ return themeManager.getActiveTheme().colors.Foreground;
16
+ },
17
+ get Background() {
18
+ return themeManager.getActiveTheme().colors.Background;
19
+ },
20
+ get LightBlue() {
21
+ return themeManager.getActiveTheme().colors.LightBlue;
22
+ },
23
+ get AccentBlue() {
24
+ return themeManager.getActiveTheme().colors.AccentBlue;
25
+ },
26
+ get AccentPurple() {
27
+ return themeManager.getActiveTheme().colors.AccentPurple;
28
+ },
29
+ get AccentCyan() {
30
+ return themeManager.getActiveTheme().colors.AccentCyan;
31
+ },
32
+ get AccentGreen() {
33
+ return themeManager.getActiveTheme().colors.AccentGreen;
34
+ },
35
+ get AccentYellow() {
36
+ return themeManager.getActiveTheme().colors.AccentYellow;
37
+ },
38
+ get AccentRed() {
39
+ return themeManager.getActiveTheme().colors.AccentRed;
40
+ },
41
+ get DiffAdded() {
42
+ return themeManager.getActiveTheme().colors.DiffAdded;
43
+ },
44
+ get DiffRemoved() {
45
+ return themeManager.getActiveTheme().colors.DiffRemoved;
46
+ },
47
+ get Comment() {
48
+ return themeManager.getActiveTheme().colors.Comment;
49
+ },
50
+ get Gray() {
51
+ return themeManager.getActiveTheme().colors.Gray;
52
+ },
53
+ get GradientColors() {
54
+ return themeManager.getActiveTheme().colors.GradientColors;
55
+ },
56
+ };
@@ -0,0 +1,153 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
8
+ import { aboutCommand } from './aboutCommand.js';
9
+ import { type CommandContext } from './types.js';
10
+ import { createMockCommandContext } from '../../test-utils/mockCommandContext.js';
11
+ import * as versionUtils from '../../utils/version.js';
12
+ import { MessageType } from '../types.js';
13
+
14
+ import { IdeClient } from '../../../../core/src/ide/ide-client.js';
15
+
16
+ vi.mock('../../utils/version.js', () => ({
17
+ getCliVersion: vi.fn(),
18
+ }));
19
+
20
+ describe('aboutCommand', () => {
21
+ let mockContext: CommandContext;
22
+ const originalPlatform = process.platform;
23
+ const originalEnv = { ...process.env };
24
+
25
+ beforeEach(() => {
26
+ mockContext = createMockCommandContext({
27
+ services: {
28
+ config: {
29
+ getModel: vi.fn(),
30
+ getIdeClient: vi.fn(),
31
+ getIdeMode: vi.fn().mockReturnValue(true),
32
+ },
33
+ settings: {
34
+ merged: {
35
+ selectedAuthType: 'test-auth',
36
+ },
37
+ },
38
+ },
39
+ ui: {
40
+ addItem: vi.fn(),
41
+ },
42
+ } as unknown as CommandContext);
43
+
44
+ vi.mocked(versionUtils.getCliVersion).mockResolvedValue('test-version');
45
+ vi.spyOn(mockContext.services.config!, 'getModel').mockReturnValue(
46
+ 'test-model',
47
+ );
48
+ process.env['GOOGLE_CLOUD_PROJECT'] = 'test-gcp-project';
49
+ Object.defineProperty(process, 'platform', {
50
+ value: 'test-os',
51
+ });
52
+ vi.spyOn(mockContext.services.config!, 'getIdeClient').mockReturnValue({
53
+ getDetectedIdeDisplayName: vi.fn().mockReturnValue('test-ide'),
54
+ } as Partial<IdeClient> as IdeClient);
55
+ });
56
+
57
+ afterEach(() => {
58
+ vi.unstubAllEnvs();
59
+ Object.defineProperty(process, 'platform', {
60
+ value: originalPlatform,
61
+ });
62
+ process.env = originalEnv;
63
+ vi.clearAllMocks();
64
+ });
65
+
66
+ it('should have the correct name and description', () => {
67
+ expect(aboutCommand.name).toBe('about');
68
+ expect(aboutCommand.description).toBe('show version info');
69
+ });
70
+
71
+ it('should call addItem with all version info', async () => {
72
+ process.env['SANDBOX'] = '';
73
+ if (!aboutCommand.action) {
74
+ throw new Error('The about command must have an action.');
75
+ }
76
+
77
+ await aboutCommand.action(mockContext, '');
78
+
79
+ expect(mockContext.ui.addItem).toHaveBeenCalledWith(
80
+ {
81
+ type: MessageType.ABOUT,
82
+ cliVersion: 'test-version',
83
+ osVersion: 'test-os',
84
+ sandboxEnv: 'no sandbox',
85
+ modelVersion: 'test-model',
86
+ selectedAuthType: 'test-auth',
87
+ gcpProject: 'test-gcp-project',
88
+ ideClient: 'test-ide',
89
+ },
90
+ expect.any(Number),
91
+ );
92
+ });
93
+
94
+ it('should show the correct sandbox environment variable', async () => {
95
+ process.env['SANDBOX'] = 'gemini-sandbox';
96
+ if (!aboutCommand.action) {
97
+ throw new Error('The about command must have an action.');
98
+ }
99
+
100
+ await aboutCommand.action(mockContext, '');
101
+
102
+ expect(mockContext.ui.addItem).toHaveBeenCalledWith(
103
+ expect.objectContaining({
104
+ sandboxEnv: 'gemini-sandbox',
105
+ }),
106
+ expect.any(Number),
107
+ );
108
+ });
109
+
110
+ it('should show sandbox-exec profile when applicable', async () => {
111
+ process.env['SANDBOX'] = 'sandbox-exec';
112
+ process.env['SEATBELT_PROFILE'] = 'test-profile';
113
+ if (!aboutCommand.action) {
114
+ throw new Error('The about command must have an action.');
115
+ }
116
+
117
+ await aboutCommand.action(mockContext, '');
118
+
119
+ expect(mockContext.ui.addItem).toHaveBeenCalledWith(
120
+ expect.objectContaining({
121
+ sandboxEnv: 'sandbox-exec (test-profile)',
122
+ }),
123
+ expect.any(Number),
124
+ );
125
+ });
126
+
127
+ it('should not show ide client when it is not detected', async () => {
128
+ vi.spyOn(mockContext.services.config!, 'getIdeClient').mockReturnValue({
129
+ getDetectedIdeDisplayName: vi.fn().mockReturnValue(undefined),
130
+ } as Partial<IdeClient> as IdeClient);
131
+
132
+ process.env['SANDBOX'] = '';
133
+ if (!aboutCommand.action) {
134
+ throw new Error('The about command must have an action.');
135
+ }
136
+
137
+ await aboutCommand.action(mockContext, '');
138
+
139
+ expect(mockContext.ui.addItem).toHaveBeenCalledWith(
140
+ expect.objectContaining({
141
+ type: MessageType.ABOUT,
142
+ cliVersion: 'test-version',
143
+ osVersion: 'test-os',
144
+ sandboxEnv: 'no sandbox',
145
+ modelVersion: 'test-model',
146
+ selectedAuthType: 'test-auth',
147
+ gcpProject: 'test-gcp-project',
148
+ ideClient: '',
149
+ }),
150
+ expect.any(Number),
151
+ );
152
+ });
153
+ });
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { getCliVersion } from '../../utils/version.js';
8
+ import { CommandKind, SlashCommand } from './types.js';
9
+ import process from 'node:process';
10
+ import { MessageType, type HistoryItemAbout } from '../types.js';
11
+
12
+ export const aboutCommand: SlashCommand = {
13
+ name: 'about',
14
+ description: 'show version info',
15
+ kind: CommandKind.BUILT_IN,
16
+ action: async (context) => {
17
+ const osVersion = process.platform;
18
+ let sandboxEnv = 'no sandbox';
19
+ if (process.env['SANDBOX'] && process.env['SANDBOX'] !== 'sandbox-exec') {
20
+ sandboxEnv = process.env['SANDBOX'];
21
+ } else if (process.env['SANDBOX'] === 'sandbox-exec') {
22
+ sandboxEnv = `sandbox-exec (${
23
+ process.env['SEATBELT_PROFILE'] || 'unknown'
24
+ })`;
25
+ }
26
+ const modelVersion = context.services.config?.getModel() || 'Unknown';
27
+ const cliVersion = await getCliVersion();
28
+ const selectedAuthType =
29
+ context.services.settings.merged.selectedAuthType || '';
30
+ const gcpProject = process.env['GOOGLE_CLOUD_PROJECT'] || '';
31
+ const ideClient =
32
+ (context.services.config?.getIdeMode() &&
33
+ context.services.config?.getIdeClient()?.getDetectedIdeDisplayName()) ||
34
+ '';
35
+
36
+ const aboutItem: Omit<HistoryItemAbout, 'id'> = {
37
+ type: MessageType.ABOUT,
38
+ cliVersion,
39
+ osVersion,
40
+ sandboxEnv,
41
+ modelVersion,
42
+ selectedAuthType,
43
+ gcpProject,
44
+ ideClient,
45
+ };
46
+
47
+ context.ui.addItem(aboutItem, Date.now());
48
+ },
49
+ };
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { describe, it, expect, beforeEach } from 'vitest';
8
+ import { authCommand } from './authCommand.js';
9
+ import { type CommandContext } from './types.js';
10
+ import { createMockCommandContext } from '../../test-utils/mockCommandContext.js';
11
+
12
+ describe('authCommand', () => {
13
+ let mockContext: CommandContext;
14
+
15
+ beforeEach(() => {
16
+ mockContext = createMockCommandContext();
17
+ });
18
+
19
+ it('should return a dialog action to open the auth dialog', () => {
20
+ if (!authCommand.action) {
21
+ throw new Error('The auth command must have an action.');
22
+ }
23
+
24
+ const result = authCommand.action(mockContext, '');
25
+
26
+ expect(result).toEqual({
27
+ type: 'dialog',
28
+ dialog: 'auth',
29
+ });
30
+ });
31
+
32
+ it('should have the correct name and description', () => {
33
+ expect(authCommand.name).toBe('auth');
34
+ expect(authCommand.description).toBe('change the auth method');
35
+ });
36
+ });
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { CommandKind, OpenDialogActionReturn, SlashCommand } from './types.js';
8
+
9
+ export const authCommand: SlashCommand = {
10
+ name: 'auth',
11
+ description: 'change the auth method',
12
+ kind: CommandKind.BUILT_IN,
13
+ action: (_context, _args): OpenDialogActionReturn => ({
14
+ type: 'dialog',
15
+ dialog: 'auth',
16
+ }),
17
+ };
@@ -0,0 +1,114 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
8
+ import open from 'open';
9
+ import { bugCommand } from './bugCommand.js';
10
+ import { createMockCommandContext } from '../../test-utils/mockCommandContext.js';
11
+ import { getCliVersion } from '../../utils/version.js';
12
+ import { GIT_COMMIT_INFO } from '../../generated/git-commit.js';
13
+ import { formatMemoryUsage } from '../utils/formatters.js';
14
+
15
+ // Mock dependencies
16
+ vi.mock('open');
17
+ vi.mock('../../utils/version.js');
18
+ vi.mock('../utils/formatters.js');
19
+ vi.mock('fss-link-core');
20
+ vi.mock('node:process', () => ({
21
+ default: {
22
+ platform: 'test-platform',
23
+ version: 'v20.0.0',
24
+ // Keep other necessary process properties if needed by other parts of the code
25
+ env: process.env,
26
+ memoryUsage: () => ({ rss: 0 }),
27
+ },
28
+ }));
29
+
30
+ describe('bugCommand', () => {
31
+ beforeEach(() => {
32
+ vi.mocked(getCliVersion).mockResolvedValue('0.1.0');
33
+ vi.mocked(formatMemoryUsage).mockReturnValue('100 MB');
34
+ vi.mock('fss-link-core', () => ({
35
+ sessionId: 'test-session-id',
36
+ }));
37
+ vi.stubEnv('SANDBOX', 'qwen-test');
38
+ });
39
+
40
+ afterEach(() => {
41
+ vi.unstubAllEnvs();
42
+ vi.clearAllMocks();
43
+ });
44
+
45
+ it('should generate the default GitHub issue URL', async () => {
46
+ const mockContext = createMockCommandContext({
47
+ services: {
48
+ config: {
49
+ getModel: () => 'qwen3-coder-plus',
50
+ getBugCommand: () => undefined,
51
+ getIdeClient: () => ({
52
+ getDetectedIdeDisplayName: () => 'VSCode',
53
+ }),
54
+ getIdeMode: () => true,
55
+ },
56
+ },
57
+ });
58
+
59
+ if (!bugCommand.action) throw new Error('Action is not defined');
60
+ await bugCommand.action(mockContext, 'A test bug');
61
+
62
+ const expectedInfo = `
63
+ * **CLI Version:** 0.1.0
64
+ * **Git Commit:** ${GIT_COMMIT_INFO}
65
+ * **Session ID:** test-session-id
66
+ * **Operating System:** test-platform v20.0.0
67
+ * **Sandbox Environment:** test
68
+ * **Model Version:** qwen3-coder-plus
69
+ * **Memory Usage:** 100 MB
70
+ * **IDE Client:** VSCode
71
+ `;
72
+ const expectedUrl =
73
+ 'https://github.com/FSSCoding/fss-link/issues/new?template=bug_report.yml&title=A%20test%20bug&info=' +
74
+ encodeURIComponent(expectedInfo);
75
+
76
+ expect(open).toHaveBeenCalledWith(expectedUrl);
77
+ });
78
+
79
+ it('should use a custom URL template from config if provided', async () => {
80
+ const customTemplate =
81
+ 'https://internal.bug-tracker.com/new?desc={title}&details={info}';
82
+ const mockContext = createMockCommandContext({
83
+ services: {
84
+ config: {
85
+ getModel: () => 'qwen3-coder-plus',
86
+ getBugCommand: () => ({ urlTemplate: customTemplate }),
87
+ getIdeClient: () => ({
88
+ getDetectedIdeDisplayName: () => 'VSCode',
89
+ }),
90
+ getIdeMode: () => true,
91
+ },
92
+ },
93
+ });
94
+
95
+ if (!bugCommand.action) throw new Error('Action is not defined');
96
+ await bugCommand.action(mockContext, 'A custom bug');
97
+
98
+ const expectedInfo = `
99
+ * **CLI Version:** 0.1.0
100
+ * **Git Commit:** ${GIT_COMMIT_INFO}
101
+ * **Session ID:** test-session-id
102
+ * **Operating System:** test-platform v20.0.0
103
+ * **Sandbox Environment:** test
104
+ * **Model Version:** qwen3-coder-plus
105
+ * **Memory Usage:** 100 MB
106
+ * **IDE Client:** VSCode
107
+ `;
108
+ const expectedUrl = customTemplate
109
+ .replace('{title}', encodeURIComponent('A custom bug'))
110
+ .replace('{info}', encodeURIComponent(expectedInfo));
111
+
112
+ expect(open).toHaveBeenCalledWith(expectedUrl);
113
+ });
114
+ });