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,261 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { useState, useEffect } from 'react';
8
+ import { Box, Text } from 'ink';
9
+ import { Colors } from '../colors.js';
10
+ import { useKeypress } from '../hooks/useKeypress.js';
11
+ import { RadioButtonSelect } from './shared/RadioButtonSelect.js';
12
+ import { TextInput } from './shared/TextInput.js';
13
+ import { getFSSLinkDatabase } from '../../config/database.js';
14
+
15
+ interface CustomEndpoint {
16
+ id?: number;
17
+ name: string;
18
+ url: string;
19
+ description?: string;
20
+ isDefault: boolean;
21
+ }
22
+
23
+ interface OpenAIEndpointDialogProps {
24
+ providerId: number;
25
+ onSelect: (endpoint: CustomEndpoint | null) => void;
26
+ onCancel: () => void;
27
+ }
28
+
29
+ const COMMON_ENDPOINTS: CustomEndpoint[] = [
30
+ {
31
+ name: 'OpenAI Official',
32
+ url: 'https://api.openai.com/v1',
33
+ description: 'Official OpenAI API endpoint',
34
+ isDefault: true
35
+ },
36
+ {
37
+ name: 'Azure OpenAI',
38
+ url: 'https://your-resource.openai.azure.com',
39
+ description: 'Azure OpenAI Service endpoint (update URL)',
40
+ isDefault: false
41
+ },
42
+ {
43
+ name: 'Custom Local',
44
+ url: 'http://localhost:8000/v1',
45
+ description: 'Local OpenAI-compatible server',
46
+ isDefault: false
47
+ }
48
+ ];
49
+
50
+ export function OpenAIEndpointDialog({
51
+ providerId,
52
+ onSelect,
53
+ onCancel
54
+ }: OpenAIEndpointDialogProps) {
55
+ const [savedEndpoints, setSavedEndpoints] = useState<CustomEndpoint[]>([]);
56
+ const [isLoading, setIsLoading] = useState(true);
57
+ const [mode, setMode] = useState<'select' | 'add'>('select');
58
+ const [newEndpoint, setNewEndpoint] = useState({
59
+ name: '',
60
+ url: '',
61
+ description: ''
62
+ });
63
+ const [selectedIndex, setSelectedIndex] = useState(0);
64
+ const [inputField, setInputField] = useState<'name' | 'url' | 'description'>('name');
65
+
66
+ // Load saved endpoints
67
+ useEffect(() => {
68
+ const loadEndpoints = async () => {
69
+ try {
70
+ const db = await getFSSLinkDatabase();
71
+ const saved = await db.getCustomEndpoints(providerId);
72
+ setSavedEndpoints(saved.map(e => ({
73
+ id: e.id,
74
+ name: e.name,
75
+ url: e.url,
76
+ description: e.description,
77
+ isDefault: Boolean(e.is_default)
78
+ })));
79
+ } catch (error) {
80
+ console.error('Failed to load endpoints:', error);
81
+ } finally {
82
+ setIsLoading(false);
83
+ }
84
+ };
85
+
86
+ loadEndpoints();
87
+ }, [providerId]);
88
+
89
+ // Combine saved and common endpoints
90
+ const allEndpoints = [...savedEndpoints, ...COMMON_ENDPOINTS];
91
+
92
+ useKeypress((input, key) => {
93
+ if (mode === 'select') {
94
+ if (key?.upArrow) {
95
+ setSelectedIndex(Math.max(0, selectedIndex - 1));
96
+ } else if (key?.downArrow) {
97
+ setSelectedIndex(Math.min(allEndpoints.length, selectedIndex + 1));
98
+ } else if (key?.return) {
99
+ if (selectedIndex === allEndpoints.length) {
100
+ // Add new endpoint option selected
101
+ setMode('add');
102
+ } else {
103
+ // Endpoint selected
104
+ onSelect(allEndpoints[selectedIndex]);
105
+ }
106
+ } else if (key?.escape || input === 'q') {
107
+ onCancel();
108
+ }
109
+ } else if (mode === 'add') {
110
+ if (key?.escape) {
111
+ setMode('select');
112
+ } else if (key?.tab) {
113
+ // Move to next field
114
+ const fields: Array<'name' | 'url' | 'description'> = ['name', 'url', 'description'];
115
+ const currentIndex = fields.indexOf(inputField);
116
+ const nextIndex = (currentIndex + 1) % fields.length;
117
+ setInputField(fields[nextIndex]);
118
+ } else if (key?.return && inputField === 'description') {
119
+ // Save new endpoint
120
+ if (newEndpoint.name && newEndpoint.url) {
121
+ saveNewEndpoint();
122
+ }
123
+ }
124
+ }
125
+ });
126
+
127
+ const saveNewEndpoint = async () => {
128
+ try {
129
+ const db = await getFSSLinkDatabase();
130
+ const endpointId = await db.saveCustomEndpoint(
131
+ providerId,
132
+ newEndpoint.name,
133
+ newEndpoint.url,
134
+ newEndpoint.description || undefined,
135
+ false // Not default by default
136
+ );
137
+
138
+ const savedEndpoint: CustomEndpoint = {
139
+ id: endpointId,
140
+ name: newEndpoint.name,
141
+ url: newEndpoint.url,
142
+ description: newEndpoint.description,
143
+ isDefault: false
144
+ };
145
+
146
+ setSavedEndpoints([...savedEndpoints, savedEndpoint]);
147
+ onSelect(savedEndpoint);
148
+ } catch (error) {
149
+ console.error('Failed to save endpoint:', error);
150
+ }
151
+ };
152
+
153
+ if (isLoading) {
154
+ return (
155
+ <Box flexDirection="column" padding={1}>
156
+ <Text color={Colors.AccentBlue}>Loading saved endpoints...</Text>
157
+ </Box>
158
+ );
159
+ }
160
+
161
+ if (mode === 'add') {
162
+ return (
163
+ <Box flexDirection="column" padding={1}>
164
+ <Text color={Colors.AccentBlue} bold>
165
+ Add Custom Endpoint
166
+ </Text>
167
+ <Text color={Colors.Gray} marginBottom={1}>
168
+ Tab to move between fields, Enter to save, Escape to cancel
169
+ </Text>
170
+
171
+ <Box marginBottom={1}>
172
+ <Text color={inputField === 'name' ? Colors.AccentGreen : Colors.Gray}>
173
+ Name:
174
+ </Text>
175
+ <TextInput
176
+ value={newEndpoint.name}
177
+ onChange={(value) => setNewEndpoint(prev => ({ ...prev, name: value }))}
178
+ isActive={inputField === 'name'}
179
+ placeholder="e.g., My Custom API"
180
+ />
181
+ </Box>
182
+
183
+ <Box marginBottom={1}>
184
+ <Text color={inputField === 'url' ? Colors.AccentGreen : Colors.Gray}>
185
+ URL:
186
+ </Text>
187
+ <TextInput
188
+ value={newEndpoint.url}
189
+ onChange={(value) => setNewEndpoint(prev => ({ ...prev, url: value }))}
190
+ isActive={inputField === 'url'}
191
+ placeholder="https://api.example.com/v1"
192
+ />
193
+ </Box>
194
+
195
+ <Box marginBottom={1}>
196
+ <Text color={inputField === 'description' ? Colors.AccentGreen : Colors.Gray}>
197
+ Description:
198
+ </Text>
199
+ <TextInput
200
+ value={newEndpoint.description}
201
+ onChange={(value) => setNewEndpoint(prev => ({ ...prev, description: value }))}
202
+ isActive={inputField === 'description'}
203
+ placeholder="Optional description"
204
+ />
205
+ </Box>
206
+
207
+ <Text color={Colors.Gray} fontSize={0.8}>
208
+ {newEndpoint.name && newEndpoint.url
209
+ ? "Press Enter to save endpoint"
210
+ : "Name and URL are required"}
211
+ </Text>
212
+ </Box>
213
+ );
214
+ }
215
+
216
+ const options = [
217
+ ...allEndpoints.map(endpoint => ({
218
+ label: endpoint.name,
219
+ description: `${endpoint.url}${endpoint.description ? ` - ${endpoint.description}` : ''}`,
220
+ value: endpoint
221
+ })),
222
+ {
223
+ label: '+ Add New Endpoint',
224
+ description: 'Create a custom endpoint configuration',
225
+ value: 'add'
226
+ }
227
+ ];
228
+
229
+ return (
230
+ <Box flexDirection="column" padding={1}>
231
+ <Text color={Colors.AccentBlue} bold marginBottom={1}>
232
+ Select OpenAI Endpoint
233
+ </Text>
234
+
235
+ <Text color={Colors.Gray} marginBottom={1}>
236
+ Choose from saved endpoints or add a new one
237
+ </Text>
238
+
239
+ <RadioButtonSelect
240
+ options={options}
241
+ selectedIndex={selectedIndex}
242
+ onSelect={(option) => {
243
+ if (option.value === 'add') {
244
+ setMode('add');
245
+ } else {
246
+ onSelect(option.value as CustomEndpoint);
247
+ }
248
+ }}
249
+ colors={{
250
+ selected: Colors.AccentGreen,
251
+ unselected: Colors.Gray,
252
+ description: Colors.Comment
253
+ }}
254
+ />
255
+
256
+ <Text color={Colors.Gray} marginTop={1} fontSize={0.8}>
257
+ ↑/↓ navigate, Enter select, q/Escape cancel
258
+ </Text>
259
+ </Box>
260
+ );
261
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import { render } from 'ink-testing-library';
8
+ import { describe, it, expect, vi } from 'vitest';
9
+ import { OpenAIKeyPrompt } from './OpenAIKeyPrompt.js';
10
+
11
+ describe('OpenAIKeyPrompt', () => {
12
+ it('should render the prompt correctly', () => {
13
+ const onSubmit = vi.fn();
14
+ const onCancel = vi.fn();
15
+
16
+ const { lastFrame } = render(
17
+ <OpenAIKeyPrompt onSubmit={onSubmit} onCancel={onCancel} />,
18
+ );
19
+
20
+ expect(lastFrame()).toContain('OpenAI Configuration Required');
21
+ expect(lastFrame()).toContain('https://platform.openai.com/api-keys');
22
+ expect(lastFrame()).toContain(
23
+ 'Press Enter to continue, Tab/↑↓ to navigate, Esc to cancel',
24
+ );
25
+ });
26
+
27
+ it('should show the component with proper styling', () => {
28
+ const onSubmit = vi.fn();
29
+ const onCancel = vi.fn();
30
+
31
+ const { lastFrame } = render(
32
+ <OpenAIKeyPrompt onSubmit={onSubmit} onCancel={onCancel} />,
33
+ );
34
+
35
+ const output = lastFrame();
36
+ expect(output).toContain('OpenAI Configuration Required');
37
+ expect(output).toContain('API Key:');
38
+ expect(output).toContain('Base URL:');
39
+ expect(output).toContain('Model:');
40
+ expect(output).toContain(
41
+ 'Press Enter to continue, Tab/↑↓ to navigate, Esc to cancel',
42
+ );
43
+ });
44
+
45
+ it('should handle paste with control characters', async () => {
46
+ const onSubmit = vi.fn();
47
+ const onCancel = vi.fn();
48
+
49
+ const { stdin } = render(
50
+ <OpenAIKeyPrompt onSubmit={onSubmit} onCancel={onCancel} />,
51
+ );
52
+
53
+ // Simulate paste with control characters
54
+ const pasteWithControlChars = '\x1b[200~sk-test123\x1b[201~';
55
+ stdin.write(pasteWithControlChars);
56
+
57
+ // Wait a bit for processing
58
+ await new Promise((resolve) => setTimeout(resolve, 50));
59
+
60
+ // The component should have filtered out the control characters
61
+ // and only kept 'sk-test123'
62
+ expect(onSubmit).not.toHaveBeenCalled(); // Should not submit yet
63
+ });
64
+ });
@@ -0,0 +1,197 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import React, { useState } from 'react';
8
+ import { Box, Text, useInput } from 'ink';
9
+ import { Colors } from '../colors.js';
10
+
11
+ interface OpenAIKeyPromptProps {
12
+ onSubmit: (apiKey: string, baseUrl: string, model: string) => void;
13
+ onCancel: () => void;
14
+ }
15
+
16
+ export function OpenAIKeyPrompt({
17
+ onSubmit,
18
+ onCancel,
19
+ }: OpenAIKeyPromptProps): React.JSX.Element {
20
+ const [apiKey, setApiKey] = useState('');
21
+ const [baseUrl, setBaseUrl] = useState('');
22
+ const [model, setModel] = useState('');
23
+ const [currentField, setCurrentField] = useState<
24
+ 'apiKey' | 'baseUrl' | 'model'
25
+ >('apiKey');
26
+
27
+ useInput((input, key) => {
28
+ // 过滤粘贴相关的控制序列
29
+ let cleanInput = (input || '')
30
+ // 过滤 ESC 开头的控制序列(如 \u001b[200~、\u001b[201~ 等)
31
+ .replace(/\u001b\[[0-9;]*[a-zA-Z]/g, '') // eslint-disable-line no-control-regex
32
+ // 过滤粘贴开始标记 [200~
33
+ .replace(/\[200~/g, '')
34
+ // 过滤粘贴结束标记 [201~
35
+ .replace(/\[201~/g, '')
36
+ // 过滤单独的 [ 和 ~ 字符(可能是粘贴标记的残留)
37
+ .replace(/^\[|~$/g, '');
38
+
39
+ // 再过滤所有不可见字符(ASCII < 32,除了回车换行)
40
+ cleanInput = cleanInput
41
+ .split('')
42
+ .filter((ch) => ch.charCodeAt(0) >= 32)
43
+ .join('');
44
+
45
+ if (cleanInput.length > 0) {
46
+ if (currentField === 'apiKey') {
47
+ setApiKey((prev) => prev + cleanInput);
48
+ } else if (currentField === 'baseUrl') {
49
+ setBaseUrl((prev) => prev + cleanInput);
50
+ } else if (currentField === 'model') {
51
+ setModel((prev) => prev + cleanInput);
52
+ }
53
+ return;
54
+ }
55
+
56
+ // 检查是否是 Enter 键(通过检查输入是否包含换行符)
57
+ if (input.includes('\n') || input.includes('\r')) {
58
+ if (currentField === 'apiKey') {
59
+ // 允许空 API key 跳转到下一个字段,让用户稍后可以返回修改
60
+ setCurrentField('baseUrl');
61
+ return;
62
+ } else if (currentField === 'baseUrl') {
63
+ setCurrentField('model');
64
+ return;
65
+ } else if (currentField === 'model') {
66
+ // 只有在提交时才检查 API key 是否为空
67
+ if (apiKey.trim()) {
68
+ onSubmit(apiKey.trim(), baseUrl.trim(), model.trim());
69
+ } else {
70
+ // 如果 API key 为空,回到 API key 字段
71
+ setCurrentField('apiKey');
72
+ }
73
+ }
74
+ return;
75
+ }
76
+
77
+ if (key.escape) {
78
+ onCancel();
79
+ return;
80
+ }
81
+
82
+ // Handle Tab key for field navigation
83
+ if (key.tab) {
84
+ if (currentField === 'apiKey') {
85
+ setCurrentField('baseUrl');
86
+ } else if (currentField === 'baseUrl') {
87
+ setCurrentField('model');
88
+ } else if (currentField === 'model') {
89
+ setCurrentField('apiKey');
90
+ }
91
+ return;
92
+ }
93
+
94
+ // Handle arrow keys for field navigation
95
+ if (key.upArrow) {
96
+ if (currentField === 'baseUrl') {
97
+ setCurrentField('apiKey');
98
+ } else if (currentField === 'model') {
99
+ setCurrentField('baseUrl');
100
+ }
101
+ return;
102
+ }
103
+
104
+ if (key.downArrow) {
105
+ if (currentField === 'apiKey') {
106
+ setCurrentField('baseUrl');
107
+ } else if (currentField === 'baseUrl') {
108
+ setCurrentField('model');
109
+ }
110
+ return;
111
+ }
112
+
113
+ // Handle backspace - check both key.backspace and delete key
114
+ if (key.backspace || key.delete) {
115
+ if (currentField === 'apiKey') {
116
+ setApiKey((prev) => prev.slice(0, -1));
117
+ } else if (currentField === 'baseUrl') {
118
+ setBaseUrl((prev) => prev.slice(0, -1));
119
+ } else if (currentField === 'model') {
120
+ setModel((prev) => prev.slice(0, -1));
121
+ }
122
+ return;
123
+ }
124
+ });
125
+
126
+ return (
127
+ <Box
128
+ borderStyle="round"
129
+ borderColor={Colors.AccentBlue}
130
+ flexDirection="column"
131
+ padding={1}
132
+ width="100%"
133
+ >
134
+ <Text bold color={Colors.AccentBlue}>
135
+ OpenAI Configuration Required
136
+ </Text>
137
+ <Box marginTop={1}>
138
+ <Text>
139
+ Please enter your OpenAI configuration. You can get an API key from{' '}
140
+ <Text color={Colors.AccentBlue}>
141
+ https://platform.openai.com/api-keys
142
+ </Text>
143
+ </Text>
144
+ </Box>
145
+ <Box marginTop={1} flexDirection="row">
146
+ <Box width={12}>
147
+ <Text
148
+ color={currentField === 'apiKey' ? Colors.AccentBlue : Colors.Gray}
149
+ >
150
+ API Key:
151
+ </Text>
152
+ </Box>
153
+ <Box flexGrow={1}>
154
+ <Text>
155
+ {currentField === 'apiKey' ? '> ' : ' '}
156
+ {apiKey || ' '}
157
+ </Text>
158
+ </Box>
159
+ </Box>
160
+ <Box marginTop={1} flexDirection="row">
161
+ <Box width={12}>
162
+ <Text
163
+ color={currentField === 'baseUrl' ? Colors.AccentBlue : Colors.Gray}
164
+ >
165
+ Base URL:
166
+ </Text>
167
+ </Box>
168
+ <Box flexGrow={1}>
169
+ <Text>
170
+ {currentField === 'baseUrl' ? '> ' : ' '}
171
+ {baseUrl}
172
+ </Text>
173
+ </Box>
174
+ </Box>
175
+ <Box marginTop={1} flexDirection="row">
176
+ <Box width={12}>
177
+ <Text
178
+ color={currentField === 'model' ? Colors.AccentBlue : Colors.Gray}
179
+ >
180
+ Model:
181
+ </Text>
182
+ </Box>
183
+ <Box flexGrow={1}>
184
+ <Text>
185
+ {currentField === 'model' ? '> ' : ' '}
186
+ {model}
187
+ </Text>
188
+ </Box>
189
+ </Box>
190
+ <Box marginTop={1}>
191
+ <Text color={Colors.Gray}>
192
+ Press Enter to continue, Tab/↑↓ to navigate, Esc to cancel
193
+ </Text>
194
+ </Box>
195
+ </Box>
196
+ );
197
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ import React from 'react';
8
+ import { Text } from 'ink';
9
+ import { Colors } from '../colors.js';
10
+
11
+ interface PrepareLabelProps {
12
+ label: string;
13
+ matchedIndex?: number;
14
+ userInput: string;
15
+ textColor: string;
16
+ highlightColor?: string;
17
+ }
18
+
19
+ export const PrepareLabel: React.FC<PrepareLabelProps> = ({
20
+ label,
21
+ matchedIndex,
22
+ userInput,
23
+ textColor,
24
+ highlightColor = Colors.AccentYellow,
25
+ }) => {
26
+ if (
27
+ matchedIndex === undefined ||
28
+ matchedIndex < 0 ||
29
+ matchedIndex >= label.length ||
30
+ userInput.length === 0
31
+ ) {
32
+ return <Text color={textColor}>{label}</Text>;
33
+ }
34
+
35
+ const start = label.slice(0, matchedIndex);
36
+ const match = label.slice(matchedIndex, matchedIndex + userInput.length);
37
+ const end = label.slice(matchedIndex + userInput.length);
38
+
39
+ return (
40
+ <Text>
41
+ <Text color={textColor}>{start}</Text>
42
+ <Text color="black" bold backgroundColor={highlightColor}>
43
+ {match}
44
+ </Text>
45
+ <Text color={textColor}>{end}</Text>
46
+ </Text>
47
+ );
48
+ };