@blackbox_ai/blackbox-cli 0.0.7 → 0.8.1

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 (422) hide show
  1. package/README.md +11 -183
  2. package/dist/index.js +8 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/package.json +13 -3
  5. package/dist/src/built-in-extensions/conductor/README.md +242 -0
  6. package/dist/src/built-in-extensions/conductor/blackbox-extension.json +5 -0
  7. package/dist/src/built-in-extensions/conductor/commands/conductor/implement.toml +170 -0
  8. package/dist/src/built-in-extensions/conductor/commands/conductor/newTrack.toml +142 -0
  9. package/dist/src/built-in-extensions/conductor/commands/conductor/revert.toml +122 -0
  10. package/dist/src/built-in-extensions/conductor/commands/conductor/setup.toml +424 -0
  11. package/dist/src/built-in-extensions/conductor/commands/conductor/status.toml +57 -0
  12. package/dist/src/built-in-extensions/conductor/templates/code_styleguides/general.md +23 -0
  13. package/dist/src/built-in-extensions/conductor/templates/code_styleguides/go.md +48 -0
  14. package/dist/src/built-in-extensions/conductor/templates/code_styleguides/html-css.md +49 -0
  15. package/dist/src/built-in-extensions/conductor/templates/code_styleguides/javascript.md +51 -0
  16. package/dist/src/built-in-extensions/conductor/templates/code_styleguides/python.md +37 -0
  17. package/dist/src/built-in-extensions/conductor/templates/code_styleguides/typescript.md +43 -0
  18. package/dist/src/built-in-extensions/conductor/templates/workflow.md +333 -0
  19. package/dist/src/built-in-extensions-data.d.ts +15 -0
  20. package/dist/src/built-in-extensions-data.js +61 -0
  21. package/dist/src/built-in-extensions-data.js.map +1 -0
  22. package/dist/src/commands/configure/ConfigureUI.d.ts +14 -0
  23. package/dist/src/commands/configure/ConfigureUI.js +556 -0
  24. package/dist/src/commands/configure/ConfigureUI.js.map +1 -0
  25. package/dist/src/commands/configure/index.d.ts +7 -0
  26. package/dist/src/commands/configure/index.js +62 -0
  27. package/dist/src/commands/configure/index.js.map +1 -0
  28. package/dist/src/commands/configure.d.ts +7 -0
  29. package/dist/src/commands/configure.js +276 -0
  30. package/dist/src/commands/configure.js.map +1 -0
  31. package/dist/src/commands/configure.test.d.ts +6 -0
  32. package/dist/src/commands/configure.test.js +32 -0
  33. package/dist/src/commands/configure.test.js.map +1 -0
  34. package/dist/src/commands/extensions/enable.js +1 -1
  35. package/dist/src/commands/extensions/enable.js.map +1 -1
  36. package/dist/src/commands/extensions/examples/context/CONTEXT.md +16 -0
  37. package/dist/src/commands/extensions/examples/context/blackbox-extension.json +5 -0
  38. package/dist/src/commands/extensions/examples/custom-commands/blackbox-extension.json +4 -0
  39. package/dist/src/commands/extensions/examples/custom-commands/commands/deploy.toml +12 -0
  40. package/dist/src/commands/extensions/examples/exclude-tools/README.md +28 -0
  41. package/dist/src/commands/extensions/examples/exclude-tools/blackbox-extension.json +5 -0
  42. package/dist/src/commands/extensions/install.d.ts +6 -2
  43. package/dist/src/commands/extensions/install.js +109 -15
  44. package/dist/src/commands/extensions/install.js.map +1 -1
  45. package/dist/src/commands/extensions/link.d.ts +12 -0
  46. package/dist/src/commands/extensions/link.js +53 -0
  47. package/dist/src/commands/extensions/link.js.map +1 -0
  48. package/dist/src/commands/extensions/list.js +2 -2
  49. package/dist/src/commands/extensions/list.js.map +1 -1
  50. package/dist/src/commands/extensions/new.d.ts +13 -0
  51. package/dist/src/commands/extensions/new.js +145 -0
  52. package/dist/src/commands/extensions/new.js.map +1 -0
  53. package/dist/src/commands/extensions/settings.d.ts +18 -0
  54. package/dist/src/commands/extensions/settings.js +98 -0
  55. package/dist/src/commands/extensions/settings.js.map +1 -0
  56. package/dist/src/commands/extensions/update.d.ts +2 -1
  57. package/dist/src/commands/extensions/update.js +59 -10
  58. package/dist/src/commands/extensions/update.js.map +1 -1
  59. package/dist/src/commands/extensions/validate.d.ts +12 -0
  60. package/dist/src/commands/extensions/validate.js +72 -0
  61. package/dist/src/commands/extensions/validate.js.map +1 -0
  62. package/dist/src/commands/extensions.js +10 -1
  63. package/dist/src/commands/extensions.js.map +1 -1
  64. package/dist/src/commands/mcp/add.d.ts +11 -0
  65. package/dist/src/commands/mcp/add.js +61 -7
  66. package/dist/src/commands/mcp/add.js.map +1 -1
  67. package/dist/src/commands/update.d.ts +7 -0
  68. package/dist/src/commands/update.js +103 -0
  69. package/dist/src/commands/update.js.map +1 -0
  70. package/dist/src/commands/voice.d.ts +7 -0
  71. package/dist/src/commands/voice.js +510 -0
  72. package/dist/src/commands/voice.js.map +1 -0
  73. package/dist/src/config/auth.d.ts +32 -1
  74. package/dist/src/config/auth.js +317 -2
  75. package/dist/src/config/auth.js.map +1 -1
  76. package/dist/src/config/config.d.ts +7 -1
  77. package/dist/src/config/config.js +71 -10
  78. package/dist/src/config/config.js.map +1 -1
  79. package/dist/src/config/extension.d.ts +6 -1
  80. package/dist/src/config/extension.js +137 -11
  81. package/dist/src/config/extension.js.map +1 -1
  82. package/dist/src/config/extensions/github.d.ts +48 -0
  83. package/dist/src/config/extensions/github.js +308 -0
  84. package/dist/src/config/extensions/github.js.map +1 -0
  85. package/dist/src/config/keyBindings.d.ts +1 -0
  86. package/dist/src/config/keyBindings.js +3 -0
  87. package/dist/src/config/keyBindings.js.map +1 -1
  88. package/dist/src/config/modelFetcher.d.ts +21 -0
  89. package/dist/src/config/modelFetcher.js +226 -0
  90. package/dist/src/config/modelFetcher.js.map +1 -0
  91. package/dist/src/config/settings.js +101 -0
  92. package/dist/src/config/settings.js.map +1 -1
  93. package/dist/src/config/settingsSchema.d.ts +626 -0
  94. package/dist/src/config/settingsSchema.js +626 -0
  95. package/dist/src/config/settingsSchema.js.map +1 -1
  96. package/dist/src/config/voice.d.ts +31 -0
  97. package/dist/src/config/voice.js +82 -0
  98. package/dist/src/config/voice.js.map +1 -0
  99. package/dist/src/encrypt/attestation.d.ts +5 -0
  100. package/dist/src/encrypt/attestation.js +100 -0
  101. package/dist/src/encrypt/attestation.js.map +1 -0
  102. package/dist/src/encrypt/bridge.d.ts +30 -0
  103. package/dist/src/encrypt/bridge.js +32 -0
  104. package/dist/src/encrypt/bridge.js.map +1 -0
  105. package/dist/src/encrypt/client.d.ts +14 -0
  106. package/dist/src/encrypt/client.js +133 -0
  107. package/dist/src/encrypt/client.js.map +1 -0
  108. package/dist/src/encrypt/config.d.ts +26 -0
  109. package/dist/src/encrypt/config.js +51 -0
  110. package/dist/src/encrypt/config.js.map +1 -0
  111. package/dist/src/encrypt/crypto-utils.d.ts +57 -0
  112. package/dist/src/encrypt/crypto-utils.js +257 -0
  113. package/dist/src/encrypt/crypto-utils.js.map +1 -0
  114. package/dist/src/encrypt/index.d.ts +12 -0
  115. package/dist/src/encrypt/index.js +13 -0
  116. package/dist/src/encrypt/index.js.map +1 -0
  117. package/dist/src/encrypt/retry-utils.d.ts +20 -0
  118. package/dist/src/encrypt/retry-utils.js +60 -0
  119. package/dist/src/encrypt/retry-utils.js.map +1 -0
  120. package/dist/src/encrypt/sessions.d.ts +17 -0
  121. package/dist/src/encrypt/sessions.js +221 -0
  122. package/dist/src/encrypt/sessions.js.map +1 -0
  123. package/dist/src/encrypt/streaming-client.d.ts +29 -0
  124. package/dist/src/encrypt/streaming-client.js +226 -0
  125. package/dist/src/encrypt/streaming-client.js.map +1 -0
  126. package/dist/src/encrypt/types.d.ts +81 -0
  127. package/dist/src/encrypt/types.js +2 -0
  128. package/dist/src/encrypt/types.js.map +1 -0
  129. package/dist/src/gemini.d.ts +1 -1
  130. package/dist/src/gemini.js +61 -28
  131. package/dist/src/gemini.js.map +1 -1
  132. package/dist/src/generated/git-commit.d.ts +3 -3
  133. package/dist/src/generated/git-commit.js +3 -3
  134. package/dist/src/nonInteractiveCli.d.ts +4 -0
  135. package/dist/src/nonInteractiveCli.js +563 -6
  136. package/dist/src/nonInteractiveCli.js.map +1 -1
  137. package/dist/src/on-demand-extensions/README.md +266 -0
  138. package/dist/src/on-demand-extensions/git-helper/README.md +16 -0
  139. package/dist/src/on-demand-extensions/git-helper/blackbox-extension.json +5 -0
  140. package/dist/src/on-demand-extensions/git-helper/commands/git/branch-cleanup.toml +18 -0
  141. package/dist/src/on-demand-extensions/git-helper/commands/git/smart-commit.toml +22 -0
  142. package/dist/src/on-demand-extensions/greet/README.md +76 -0
  143. package/dist/src/on-demand-extensions/greet/blackbox-extension.json +5 -0
  144. package/dist/src/on-demand-extensions/greet/commands/greet/hello.toml +9 -0
  145. package/dist/src/on-demand-extensions/registry.json +251 -0
  146. package/dist/src/services/BuiltinCommandLoader.js +20 -2
  147. package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
  148. package/dist/src/services/EncryptedContentGenerator.d.ts +63 -0
  149. package/dist/src/services/EncryptedContentGenerator.js +426 -0
  150. package/dist/src/services/EncryptedContentGenerator.js.map +1 -0
  151. package/dist/src/services/McpCommandLoader.d.ts +24 -0
  152. package/dist/src/services/McpCommandLoader.js +50 -0
  153. package/dist/src/services/McpCommandLoader.js.map +1 -0
  154. package/dist/src/services/McpPromptLoader.js +17 -2
  155. package/dist/src/services/McpPromptLoader.js.map +1 -1
  156. package/dist/src/services/ReleaseNotesCache.d.ts +57 -0
  157. package/dist/src/services/ReleaseNotesCache.js +186 -0
  158. package/dist/src/services/ReleaseNotesCache.js.map +1 -0
  159. package/dist/src/services/elevenLabsErrors.d.ts +65 -0
  160. package/dist/src/services/elevenLabsErrors.js +233 -0
  161. package/dist/src/services/elevenLabsErrors.js.map +1 -0
  162. package/dist/src/services/elevenLabsService.d.ts +62 -0
  163. package/dist/src/services/elevenLabsService.js +186 -0
  164. package/dist/src/services/elevenLabsService.js.map +1 -0
  165. package/dist/src/services/elevenLabsStreamingService.d.ts +59 -0
  166. package/dist/src/services/elevenLabsStreamingService.js +202 -0
  167. package/dist/src/services/elevenLabsStreamingService.js.map +1 -0
  168. package/dist/src/services/elevenLabsTokenService.d.ts +21 -0
  169. package/dist/src/services/elevenLabsTokenService.js +42 -0
  170. package/dist/src/services/elevenLabsTokenService.js.map +1 -0
  171. package/dist/src/services/voiceInputHandler.d.ts +26 -0
  172. package/dist/src/services/voiceInputHandler.js +209 -0
  173. package/dist/src/services/voiceInputHandler.js.map +1 -0
  174. package/dist/src/services/voiceRecordingService.d.ts +69 -0
  175. package/dist/src/services/voiceRecordingService.js +397 -0
  176. package/dist/src/services/voiceRecordingService.js.map +1 -0
  177. package/dist/src/ui/App.d.ts +1 -0
  178. package/dist/src/ui/App.js +412 -63
  179. package/dist/src/ui/App.js.map +1 -1
  180. package/dist/src/ui/commands/browseExtensionsCommand.d.ts +7 -0
  181. package/dist/src/ui/commands/browseExtensionsCommand.js +16 -0
  182. package/dist/src/ui/commands/browseExtensionsCommand.js.map +1 -0
  183. package/dist/src/ui/commands/chatCommand.js +356 -16
  184. package/dist/src/ui/commands/chatCommand.js.map +1 -1
  185. package/dist/src/ui/commands/dbCommand.d.ts +7 -0
  186. package/dist/src/ui/commands/dbCommand.js +37 -0
  187. package/dist/src/ui/commands/dbCommand.js.map +1 -0
  188. package/dist/src/ui/commands/docsCommand.js +1 -1
  189. package/dist/src/ui/commands/docsCommand.js.map +1 -1
  190. package/dist/src/ui/commands/mcpCommand.js +3 -2
  191. package/dist/src/ui/commands/mcpCommand.js.map +1 -1
  192. package/dist/src/ui/commands/mcpInvokeCommand.d.ts +16 -0
  193. package/dist/src/ui/commands/mcpInvokeCommand.js +263 -0
  194. package/dist/src/ui/commands/mcpInvokeCommand.js.map +1 -0
  195. package/dist/src/ui/commands/modelCommand.js +79 -5
  196. package/dist/src/ui/commands/modelCommand.js.map +1 -1
  197. package/dist/src/ui/commands/multiAgentCommand.d.ts +7 -0
  198. package/dist/src/ui/commands/multiAgentCommand.js +833 -0
  199. package/dist/src/ui/commands/multiAgentCommand.js.map +1 -0
  200. package/dist/src/ui/commands/multiAgentConfigureCommand.d.ts +7 -0
  201. package/dist/src/ui/commands/multiAgentConfigureCommand.js +17 -0
  202. package/dist/src/ui/commands/multiAgentConfigureCommand.js.map +1 -0
  203. package/dist/src/ui/commands/quitCommand.js +71 -2
  204. package/dist/src/ui/commands/quitCommand.js.map +1 -1
  205. package/dist/src/ui/commands/releasesCommand.d.ts +7 -0
  206. package/dist/src/ui/commands/releasesCommand.js +16 -0
  207. package/dist/src/ui/commands/releasesCommand.js.map +1 -0
  208. package/dist/src/ui/commands/setupGithubCommand.js.map +1 -1
  209. package/dist/src/ui/commands/shellPermissionsCommand.d.ts +7 -0
  210. package/dist/src/ui/commands/shellPermissionsCommand.js +109 -0
  211. package/dist/src/ui/commands/shellPermissionsCommand.js.map +1 -0
  212. package/dist/src/ui/commands/skillCommand.d.ts +7 -0
  213. package/dist/src/ui/commands/skillCommand.js +240 -0
  214. package/dist/src/ui/commands/skillCommand.js.map +1 -0
  215. package/dist/src/ui/commands/statsCommand.js +243 -1
  216. package/dist/src/ui/commands/statsCommand.js.map +1 -1
  217. package/dist/src/ui/commands/tasksCommand.d.ts +7 -0
  218. package/dist/src/ui/commands/tasksCommand.js +535 -0
  219. package/dist/src/ui/commands/tasksCommand.js.map +1 -0
  220. package/dist/src/ui/commands/toolPermissionsCommand.d.ts +7 -0
  221. package/dist/src/ui/commands/toolPermissionsCommand.js +408 -0
  222. package/dist/src/ui/commands/toolPermissionsCommand.js.map +1 -0
  223. package/dist/src/ui/commands/types.d.ts +10 -2
  224. package/dist/src/ui/commands/types.js.map +1 -1
  225. package/dist/src/ui/commands/voiceCommand.d.ts +7 -0
  226. package/dist/src/ui/commands/voiceCommand.js +525 -0
  227. package/dist/src/ui/commands/voiceCommand.js.map +1 -0
  228. package/dist/src/ui/components/AuthDialog.d.ts +4 -2
  229. package/dist/src/ui/components/AuthDialog.js +349 -64
  230. package/dist/src/ui/components/AuthDialog.js.map +1 -1
  231. package/dist/src/ui/components/AuthInProgress.js +3 -1
  232. package/dist/src/ui/components/AuthInProgress.js.map +1 -1
  233. package/dist/src/ui/components/ExtensionsDialog.d.ts +11 -0
  234. package/dist/src/ui/components/ExtensionsDialog.js +303 -0
  235. package/dist/src/ui/components/ExtensionsDialog.js.map +1 -0
  236. package/dist/src/ui/components/GenericProviderKeyPrompt.d.ts +24 -0
  237. package/dist/src/ui/components/GenericProviderKeyPrompt.js +99 -0
  238. package/dist/src/ui/components/GenericProviderKeyPrompt.js.map +1 -0
  239. package/dist/src/ui/components/Header.js +10 -1
  240. package/dist/src/ui/components/Header.js.map +1 -1
  241. package/dist/src/ui/components/HistoryBrowserDialog.d.ts +15 -0
  242. package/dist/src/ui/components/HistoryBrowserDialog.js +166 -0
  243. package/dist/src/ui/components/HistoryBrowserDialog.js.map +1 -0
  244. package/dist/src/ui/components/HistoryItemDisplay.js +13 -1
  245. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  246. package/dist/src/ui/components/InputPrompt.js +22 -8
  247. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  248. package/dist/src/ui/components/LoadingIndicator.d.ts +4 -0
  249. package/dist/src/ui/components/LoadingIndicator.js +16 -4
  250. package/dist/src/ui/components/LoadingIndicator.js.map +1 -1
  251. package/dist/src/ui/components/LoadingIndicator.test.js +108 -16
  252. package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -1
  253. package/dist/src/ui/components/ModelSelectionDialog.d.ts +2 -0
  254. package/dist/src/ui/components/ModelSelectionDialog.js +33 -4
  255. package/dist/src/ui/components/ModelSelectionDialog.js.map +1 -1
  256. package/dist/src/ui/components/ModelSelectionDialog.test.js +41 -4
  257. package/dist/src/ui/components/ModelSelectionDialog.test.js.map +1 -1
  258. package/dist/src/ui/components/ReleaseNotesDialog.d.ts +23 -0
  259. package/dist/src/ui/components/ReleaseNotesDialog.js +150 -0
  260. package/dist/src/ui/components/ReleaseNotesDialog.js.map +1 -0
  261. package/dist/src/ui/components/ReleaseNotesDisplay.d.ts +18 -0
  262. package/dist/src/ui/components/ReleaseNotesDisplay.js +14 -0
  263. package/dist/src/ui/components/ReleaseNotesDisplay.js.map +1 -0
  264. package/dist/src/ui/components/SessionSummaryDisplay.d.ts +2 -0
  265. package/dist/src/ui/components/SessionSummaryDisplay.js +1 -1
  266. package/dist/src/ui/components/SessionSummaryDisplay.js.map +1 -1
  267. package/dist/src/ui/components/SettingsDialog.d.ts +3 -1
  268. package/dist/src/ui/components/SettingsDialog.js +17 -7
  269. package/dist/src/ui/components/SettingsDialog.js.map +1 -1
  270. package/dist/src/ui/components/ShellConfirmationDialog.d.ts +2 -0
  271. package/dist/src/ui/components/ShellConfirmationDialog.js +7 -3
  272. package/dist/src/ui/components/ShellConfirmationDialog.js.map +1 -1
  273. package/dist/src/ui/components/StatsDisplay.d.ts +2 -0
  274. package/dist/src/ui/components/StatsDisplay.js +92 -7
  275. package/dist/src/ui/components/StatsDisplay.js.map +1 -1
  276. package/dist/src/ui/components/SuggestionsDisplay.js +6 -1
  277. package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
  278. package/dist/src/ui/components/ThemeDialog.d.ts +3 -1
  279. package/dist/src/ui/components/ThemeDialog.js +5 -2
  280. package/dist/src/ui/components/ThemeDialog.js.map +1 -1
  281. package/dist/src/ui/components/Tips.js +1 -4
  282. package/dist/src/ui/components/Tips.js.map +1 -1
  283. package/dist/src/ui/components/TodoListDialog.d.ts +13 -0
  284. package/dist/src/ui/components/TodoListDialog.js +29 -0
  285. package/dist/src/ui/components/TodoListDialog.js.map +1 -0
  286. package/dist/src/ui/components/TodoListDialog.test.d.ts +6 -0
  287. package/dist/src/ui/components/TodoListDialog.test.js +60 -0
  288. package/dist/src/ui/components/TodoListDialog.test.js.map +1 -0
  289. package/dist/src/ui/components/VoiceConfigDialog.d.ts +17 -0
  290. package/dist/src/ui/components/VoiceConfigDialog.js +47 -0
  291. package/dist/src/ui/components/VoiceConfigDialog.js.map +1 -0
  292. package/dist/src/ui/components/messages/GeminiMessage.js +4 -0
  293. package/dist/src/ui/components/messages/GeminiMessage.js.map +1 -1
  294. package/dist/src/ui/components/messages/GeminiMessageContent.js +4 -0
  295. package/dist/src/ui/components/messages/GeminiMessageContent.js.map +1 -1
  296. package/dist/src/ui/components/messages/ToolConfirmationMessage.d.ts +2 -0
  297. package/dist/src/ui/components/messages/ToolConfirmationMessage.js +96 -9
  298. package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
  299. package/dist/src/ui/components/messages/ToolGroupMessage.test.js +3 -3
  300. package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -1
  301. package/dist/src/ui/components/messages/ToolMessage.js +1 -1
  302. package/dist/src/ui/components/messages/ToolMessage.js.map +1 -1
  303. package/dist/src/ui/components/messages/ToolMessage.test.js +9 -12
  304. package/dist/src/ui/components/messages/ToolMessage.test.js.map +1 -1
  305. package/dist/src/ui/components/multiagent/MultiAgentConfigDialog.d.ts +25 -0
  306. package/dist/src/ui/components/multiagent/MultiAgentConfigDialog.js +179 -0
  307. package/dist/src/ui/components/multiagent/MultiAgentConfigDialog.js.map +1 -0
  308. package/dist/src/ui/components/shared/RadioButtonSelect.d.ts +3 -1
  309. package/dist/src/ui/components/shared/RadioButtonSelect.js +57 -18
  310. package/dist/src/ui/components/shared/RadioButtonSelect.js.map +1 -1
  311. package/dist/src/ui/components/shared/TextInput.d.ts +2 -1
  312. package/dist/src/ui/components/shared/TextInput.js +5 -2
  313. package/dist/src/ui/components/shared/TextInput.js.map +1 -1
  314. package/dist/src/ui/components/subagents/runtime/AgentExecutionDisplay.js +3 -3
  315. package/dist/src/ui/components/subagents/runtime/AgentExecutionDisplay.js.map +1 -1
  316. package/dist/src/ui/constants.d.ts +3 -3
  317. package/dist/src/ui/constants.js +3 -3
  318. package/dist/src/ui/constants.js.map +1 -1
  319. package/dist/src/ui/contexts/SessionContext.d.ts +6 -0
  320. package/dist/src/ui/contexts/SessionContext.js +24 -2
  321. package/dist/src/ui/contexts/SessionContext.js.map +1 -1
  322. package/dist/src/ui/hooks/atCommandProcessor.js +139 -57
  323. package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
  324. package/dist/src/ui/hooks/slashCommandProcessor.d.ts +2 -1
  325. package/dist/src/ui/hooks/slashCommandProcessor.js +189 -17
  326. package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
  327. package/dist/src/ui/hooks/useAdaptiveStream.d.ts +42 -0
  328. package/dist/src/ui/hooks/useAdaptiveStream.js +31 -0
  329. package/dist/src/ui/hooks/useAdaptiveStream.js.map +1 -0
  330. package/dist/src/ui/hooks/useAtCompletion.js +20 -4
  331. package/dist/src/ui/hooks/useAtCompletion.js.map +1 -1
  332. package/dist/src/ui/hooks/useAuthCommand.d.ts +2 -2
  333. package/dist/src/ui/hooks/useAuthCommand.js +99 -5
  334. package/dist/src/ui/hooks/useAuthCommand.js.map +1 -1
  335. package/dist/src/ui/hooks/useCommandCompletion.js +14 -10
  336. package/dist/src/ui/hooks/useCommandCompletion.js.map +1 -1
  337. package/dist/src/ui/hooks/useDialogClose.d.ts +10 -0
  338. package/dist/src/ui/hooks/useDialogClose.js +25 -0
  339. package/dist/src/ui/hooks/useDialogClose.js.map +1 -1
  340. package/dist/src/ui/hooks/useDialogCloseAnimation.d.ts +22 -0
  341. package/dist/src/ui/hooks/useDialogCloseAnimation.js +68 -0
  342. package/dist/src/ui/hooks/useDialogCloseAnimation.js.map +1 -0
  343. package/dist/src/ui/hooks/useEncryptedStream.d.ts +22 -0
  344. package/dist/src/ui/hooks/useEncryptedStream.js +378 -0
  345. package/dist/src/ui/hooks/useEncryptedStream.js.map +1 -0
  346. package/dist/src/ui/hooks/useExtensionsDialog.d.ts +10 -0
  347. package/dist/src/ui/hooks/useExtensionsDialog.js +21 -0
  348. package/dist/src/ui/hooks/useExtensionsDialog.js.map +1 -0
  349. package/dist/src/ui/hooks/useGeminiStream.js +6 -2
  350. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  351. package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -1
  352. package/dist/src/ui/hooks/useLoadingIndicator.d.ts +1 -1
  353. package/dist/src/ui/hooks/useLoadingIndicator.js +3 -2
  354. package/dist/src/ui/hooks/useLoadingIndicator.js.map +1 -1
  355. package/dist/src/ui/hooks/useLoadingIndicator.test.js +27 -5
  356. package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
  357. package/dist/src/ui/hooks/useMultiAgentConfigCommand.d.ts +10 -0
  358. package/dist/src/ui/hooks/useMultiAgentConfigCommand.js +21 -0
  359. package/dist/src/ui/hooks/useMultiAgentConfigCommand.js.map +1 -0
  360. package/dist/src/ui/hooks/useReleasesDialog.d.ts +20 -0
  361. package/dist/src/ui/hooks/useReleasesDialog.js +214 -0
  362. package/dist/src/ui/hooks/useReleasesDialog.js.map +1 -0
  363. package/dist/src/ui/hooks/useSlashCompletion.js +10 -8
  364. package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
  365. package/dist/src/ui/hooks/useTodoList.d.ts +17 -0
  366. package/dist/src/ui/hooks/useTodoList.js +51 -0
  367. package/dist/src/ui/hooks/useTodoList.js.map +1 -0
  368. package/dist/src/ui/keyMatchers.test.js +6 -0
  369. package/dist/src/ui/keyMatchers.test.js.map +1 -1
  370. package/dist/src/ui/themes/blackbox-dark.js +1 -1
  371. package/dist/src/ui/themes/blackbox-dark.js.map +1 -1
  372. package/dist/src/ui/themes/blackbox-light.js +1 -1
  373. package/dist/src/ui/themes/blackbox-light.js.map +1 -1
  374. package/dist/src/ui/types.d.ts +15 -2
  375. package/dist/src/ui/types.js +1 -0
  376. package/dist/src/ui/types.js.map +1 -1
  377. package/dist/src/ui/utils/computeStats.d.ts +25 -1
  378. package/dist/src/ui/utils/computeStats.js +58 -1
  379. package/dist/src/ui/utils/computeStats.js.map +1 -1
  380. package/dist/src/ui/utils/updateCheck.js +37 -54
  381. package/dist/src/ui/utils/updateCheck.js.map +1 -1
  382. package/dist/src/utils/backgroundUpdateCheck.d.ts +15 -0
  383. package/dist/src/utils/backgroundUpdateCheck.js +48 -0
  384. package/dist/src/utils/backgroundUpdateCheck.js.map +1 -0
  385. package/dist/src/utils/gitAutoDetect.d.ts +16 -0
  386. package/dist/src/utils/gitAutoDetect.js +45 -0
  387. package/dist/src/utils/gitAutoDetect.js.map +1 -0
  388. package/dist/src/utils/installationInfo.d.ts +1 -0
  389. package/dist/src/utils/installationInfo.js +24 -4
  390. package/dist/src/utils/installationInfo.js.map +1 -1
  391. package/dist/src/utils/preLaunchUpdateCheck.d.ts +17 -0
  392. package/dist/src/utils/preLaunchUpdateCheck.js +75 -0
  393. package/dist/src/utils/preLaunchUpdateCheck.js.map +1 -0
  394. package/dist/src/utils/version.js +12 -1
  395. package/dist/src/utils/version.js.map +1 -1
  396. package/dist/src/utils/versionStorage.d.ts +50 -0
  397. package/dist/src/utils/versionStorage.js +224 -0
  398. package/dist/src/utils/versionStorage.js.map +1 -0
  399. package/dist/src/validateNonInterActiveAuth.js +10 -3
  400. package/dist/src/validateNonInterActiveAuth.js.map +1 -1
  401. package/dist/src/virtual-extensions.d.ts +14 -0
  402. package/dist/src/virtual-extensions.js +56 -0
  403. package/dist/src/virtual-extensions.js.map +1 -0
  404. package/dist/src/zed-integration/fileSystemService.d.ts +3 -3
  405. package/dist/src/zed-integration/fileSystemService.js +5 -7
  406. package/dist/src/zed-integration/fileSystemService.js.map +1 -1
  407. package/dist/src/zed-integration/zedIntegration.js +62 -17
  408. package/dist/src/zed-integration/zedIntegration.js.map +1 -1
  409. package/dist/tsconfig.tsbuildinfo +1 -1
  410. package/package.json +13 -3
  411. package/dist/src/utils/handleAutoUpdate.d.ts +0 -11
  412. package/dist/src/utils/handleAutoUpdate.js +0 -102
  413. package/dist/src/utils/handleAutoUpdate.js.map +0 -1
  414. package/dist/src/utils/updateEventEmitter.d.ts +0 -11
  415. package/dist/src/utils/updateEventEmitter.js +0 -12
  416. package/dist/src/utils/updateEventEmitter.js.map +0 -1
  417. package/dist/src/zed-integration/acp.d.ts +0 -63
  418. package/dist/src/zed-integration/acp.js +0 -226
  419. package/dist/src/zed-integration/acp.js.map +0 -1
  420. package/dist/src/zed-integration/schema.d.ts +0 -11782
  421. package/dist/src/zed-integration/schema.js +0 -311
  422. package/dist/src/zed-integration/schema.js.map +0 -1
@@ -3,10 +3,420 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import { executeToolCall, shutdownTelemetry, isTelemetrySdkInitialized, GeminiEventType, parseAndFormatApiError, FatalInputError, FatalTurnLimitedError, } from '@blackbox_ai/blackbox-cli-core';
6
+ import { executeToolCall, shutdownTelemetry, isTelemetrySdkInitialized, GeminiEventType, parseAndFormatApiError, FatalInputError, FatalTurnLimitedError, Logger, decodeTagName, CheckpointApiService, } from '@blackbox_ai/blackbox-cli-core';
7
+ import { FinishReason } from '@google/genai';
8
+ import * as fsPromises from 'node:fs/promises';
9
+ import path from 'node:path';
7
10
  import { ConsolePatcher } from './ui/utils/ConsolePatcher.js';
8
11
  import { handleAtCommand } from './ui/hooks/atCommandProcessor.js';
12
+ // Minimal ANSI color helpers (avoid extra deps; disable when not a TTY or NO_COLOR=1)
13
+ const USE_COLOR = Boolean(process.stdout.isTTY) && process.env['NO_COLOR'] !== '1';
14
+ const ansi = (open, close) => (s) => USE_COLOR ? `\u001b[${open}m${s}\u001b[${close}m` : s;
15
+ const bold = ansi(1, 22);
16
+ const dim = ansi(2, 22);
17
+ const red = ansi(31, 39);
18
+ const green = ansi(32, 39);
19
+ const yellow = ansi(33, 39);
20
+ const blue = ansi(34, 39);
21
+ const magenta = ansi(35, 39);
22
+ const cyan = ansi(36, 39);
23
+ const gray = ansi(90, 39);
24
+ function printInfoToStderr(prefix, message) {
25
+ console.error(`${prefix} ${message}`);
26
+ }
27
+ function printToolSectionToStdout(toolName, content) {
28
+ const columns = Math.max(30, Math.min(100, process.stdout.columns || 80));
29
+ const horizontal = '─'.repeat(columns - 2);
30
+ const top = USE_COLOR
31
+ ? cyan(`┌${horizontal}┐`)
32
+ : `┌${horizontal}┐`;
33
+ const bottom = USE_COLOR
34
+ ? cyan(`└${horizontal}┘`)
35
+ : `└${horizontal}┘`;
36
+ const title = `${bold(cyan('Tool'))} ${bold(magenta(toolName))}`;
37
+ const titleLine = `│ ${title}${' '.repeat(Math.max(0, columns - 3 - title.length))}│`;
38
+ const lines = content.split(/\r?\n/);
39
+ const body = lines
40
+ .map((line) => {
41
+ const safe = line.replace(/\t/g, ' ');
42
+ const visibleLen = safe.length; // best-effort; we avoid nested ANSI here
43
+ const padding = Math.max(0, columns - 3 - visibleLen);
44
+ return `│ ${safe}${' '.repeat(padding)}│`;
45
+ })
46
+ .join('\n');
47
+ process.stdout.write(`\n${top}\n${titleLine}\n${gray(`│${' '.repeat(columns - 2)}│`)}\n${body}\n${bottom}\n`);
48
+ }
49
+ /**
50
+ * Formats tool result display for clean, user-friendly output.
51
+ * Handles different result types similar to the interactive mode.
52
+ */
53
+ function formatToolResultDisplay(resultDisplay) {
54
+ if (!resultDisplay) {
55
+ return null;
56
+ }
57
+ // Handle string results with truncation for very long outputs
58
+ if (typeof resultDisplay === 'string') {
59
+ const MAX_STRING_LENGTH = 2000;
60
+ if (resultDisplay.length > MAX_STRING_LENGTH) {
61
+ const truncated = resultDisplay.substring(0, MAX_STRING_LENGTH);
62
+ const remaining = resultDisplay.length - MAX_STRING_LENGTH;
63
+ return `${truncated}\n\n${dim(`... (${remaining} more characters truncated)`)}`;
64
+ }
65
+ return resultDisplay;
66
+ }
67
+ // Handle object results
68
+ if (typeof resultDisplay === 'object' && resultDisplay !== null) {
69
+ // Check for FileDiff (write_file, edit_file results)
70
+ if ('fileDiff' in resultDisplay && 'fileName' in resultDisplay) {
71
+ const result = resultDisplay;
72
+ let summary = `${bold('File:')} ${result.fileName}\n`;
73
+ // Parse the diff to show visual changes
74
+ const diffLines = result.fileDiff.split('\n');
75
+ const addedLines = [];
76
+ const removedLines = [];
77
+ for (const line of diffLines) {
78
+ if (line.startsWith('+') && !line.startsWith('+++')) {
79
+ const content = line.substring(1);
80
+ // Skip empty lines that are just formatting
81
+ if (content.trim().length > 0) {
82
+ addedLines.push(content);
83
+ }
84
+ }
85
+ else if (line.startsWith('-') && !line.startsWith('---')) {
86
+ const content = line.substring(1);
87
+ // Skip empty lines that are just formatting
88
+ if (content.trim().length > 0) {
89
+ removedLines.push(content);
90
+ }
91
+ }
92
+ }
93
+ // Show change statistics - use actual parsed lines, not diffStat which includes markers
94
+ const totalAdded = addedLines.length;
95
+ const totalRemoved = removedLines.length;
96
+ if (totalAdded > 0 || totalRemoved > 0) {
97
+ summary += `${bold('Changes:')} `;
98
+ if (totalRemoved > 0)
99
+ summary += `${red(`-${totalRemoved} lines`)} `;
100
+ if (totalAdded > 0)
101
+ summary += `${green(`+${totalAdded} lines`)}`;
102
+ summary += '\n\n';
103
+ }
104
+ // Show visual diff (deletions and additions)
105
+ const MAX_DIFF_LINES = 15;
106
+ let diffDisplay = '';
107
+ if (removedLines.length > 0) {
108
+ diffDisplay += `${bold(red('Removed:'))}\n`;
109
+ const linesToShow = removedLines.slice(0, MAX_DIFF_LINES);
110
+ for (const line of linesToShow) {
111
+ diffDisplay += `${red('- ' + line)}\n`;
112
+ }
113
+ if (removedLines.length > MAX_DIFF_LINES) {
114
+ diffDisplay += `${dim(`... (${removedLines.length - MAX_DIFF_LINES} more lines removed)`)}\n`;
115
+ }
116
+ diffDisplay += '\n';
117
+ }
118
+ if (addedLines.length > 0) {
119
+ diffDisplay += `${bold(green('Added:'))}\n`;
120
+ const linesToShow = addedLines.slice(0, MAX_DIFF_LINES);
121
+ for (const line of linesToShow) {
122
+ diffDisplay += `${green('+ ' + line)}\n`;
123
+ }
124
+ if (addedLines.length > MAX_DIFF_LINES) {
125
+ diffDisplay += `${dim(`... (${addedLines.length - MAX_DIFF_LINES} more lines added)`)}\n`;
126
+ }
127
+ }
128
+ if (diffDisplay) {
129
+ summary += diffDisplay;
130
+ }
131
+ else if (result.newContent) {
132
+ // Fallback: show content preview if no diff lines parsed
133
+ const MAX_CONTENT_PREVIEW = 300;
134
+ if (result.newContent.length < MAX_CONTENT_PREVIEW) {
135
+ summary += `${bold('Content:')}\n${dim(result.newContent)}`;
136
+ }
137
+ else {
138
+ const preview = result.newContent.substring(0, MAX_CONTENT_PREVIEW);
139
+ const remaining = result.newContent.length - MAX_CONTENT_PREVIEW;
140
+ summary += `${bold('Content preview:')}\n${dim(preview)}\n${dim(`... (${remaining} more characters)`)}`;
141
+ }
142
+ }
143
+ return summary.trim();
144
+ }
145
+ // Check for todo_list results
146
+ if ('type' in resultDisplay && resultDisplay.type === 'todo_list') {
147
+ const todoResult = resultDisplay;
148
+ let output = `${bold('TODO List:')}\n`;
149
+ if (Array.isArray(todoResult.todos)) {
150
+ const MAX_TODOS = 20;
151
+ const todosToShow = todoResult.todos.slice(0, MAX_TODOS);
152
+ todosToShow.forEach((todo) => {
153
+ // Use status icons matching the UI
154
+ const statusIcon = {
155
+ pending: '○',
156
+ in_progress: '◐',
157
+ completed: '●',
158
+ }[todo.status] || '○';
159
+ const checkbox = todo.status === 'completed' ? '[✓]' : '[ ]';
160
+ output += `${checkbox} ${statusIcon} ${todo.content}\n`;
161
+ });
162
+ if (todoResult.todos.length > MAX_TODOS) {
163
+ output += `${dim(`... (${todoResult.todos.length - MAX_TODOS} more todos)`)}`;
164
+ }
165
+ }
166
+ return output.trim();
167
+ }
168
+ // Check for task_execution (subagent) results
169
+ if ('type' in resultDisplay && resultDisplay.type === 'task_execution') {
170
+ const taskResult = resultDisplay;
171
+ let output = `${bold(cyan('Subagent:'))} ${magenta(taskResult.subagentName)}\n`;
172
+ output += `${bold('Task:')} ${taskResult.taskDescription}\n`;
173
+ output += `${bold('Status:')} ${taskResult.status}\n`;
174
+ if (taskResult.result) {
175
+ const MAX_RESULT_LENGTH = 1000;
176
+ if (taskResult.result.length > MAX_RESULT_LENGTH) {
177
+ const truncated = taskResult.result.substring(0, MAX_RESULT_LENGTH);
178
+ const remaining = taskResult.result.length - MAX_RESULT_LENGTH;
179
+ output += `${bold('Result:')}\n${truncated}\n${dim(`... (${remaining} more characters)`)}`;
180
+ }
181
+ else {
182
+ output += `${bold('Result:')}\n${taskResult.result}`;
183
+ }
184
+ }
185
+ return output;
186
+ }
187
+ // Check for plan_summary results
188
+ if ('type' in resultDisplay && resultDisplay.type === 'plan_summary') {
189
+ const planResult = resultDisplay;
190
+ return `${bold(planResult.message)}\n\n${planResult.plan}`;
191
+ }
192
+ // For other objects, show a clean summary instead of raw JSON
193
+ // Extract key information if available
194
+ const obj = resultDisplay;
195
+ if ('message' in obj && typeof obj['message'] === 'string') {
196
+ const msg = obj['message'];
197
+ if (msg.length > 1000) {
198
+ return msg.substring(0, 1000) + dim('\n... (truncated)');
199
+ }
200
+ return msg;
201
+ }
202
+ if ('result' in obj && typeof obj['result'] === 'string') {
203
+ const res = obj['result'];
204
+ if (res.length > 1000) {
205
+ return res.substring(0, 1000) + dim('\n... (truncated)');
206
+ }
207
+ return res;
208
+ }
209
+ if ('output' in obj && typeof obj['output'] === 'string') {
210
+ const out = obj['output'];
211
+ if (out.length > 1000) {
212
+ return out.substring(0, 1000) + dim('\n... (truncated)');
213
+ }
214
+ return out;
215
+ }
216
+ // Last resort: show formatted JSON but only for small objects
217
+ const jsonStr = JSON.stringify(resultDisplay, null, 2);
218
+ const MAX_JSON_LENGTH = 500;
219
+ if (jsonStr.length < MAX_JSON_LENGTH) {
220
+ return jsonStr;
221
+ }
222
+ // For large objects, show a summary
223
+ return `${bold('Result:')} ${dim('[Complex object with ' + Object.keys(obj).length + ' properties - output truncated]')}`;
224
+ }
225
+ return String(resultDisplay);
226
+ }
227
+ function printPlanSectionToStderr(toolName, planDescription, argsJsonPretty) {
228
+ const columns = Math.max(30, Math.min(100, process.stderr.columns || process.stdout.columns || 80));
229
+ const horizontal = '─'.repeat(columns - 2);
230
+ const top = USE_COLOR ? yellow(`┌${horizontal}┐`) : `┌${horizontal}┐`;
231
+ const bottom = USE_COLOR ? yellow(`└${horizontal}┘`) : `└${horizontal}┘`;
232
+ const title = `${bold(yellow('Tool'))} ${bold(magenta(toolName))}`;
233
+ const titleLine = `│ ${title}${' '.repeat(Math.max(0, columns - 3 - title.length))}│`;
234
+ const bodyLines = [`${bold('Description:')}`, planDescription || '(none)', '', `${bold('Invocation payload:')}`, argsJsonPretty];
235
+ const body = bodyLines
236
+ .flatMap((line) => (line.includes('\n') ? line.split(/\r?\n/) : [line]))
237
+ .map((line) => {
238
+ const safe = line.replace(/\t/g, ' ');
239
+ const visibleLen = safe.length;
240
+ const padding = Math.max(0, columns - 3 - visibleLen);
241
+ return `│ ${safe}${' '.repeat(padding)}│`;
242
+ })
243
+ .join('\n');
244
+ process.stderr.write(`\n${top}\n${titleLine}\n${gray(`│${' '.repeat(columns - 2)}│`)}\n${body}\n${bottom}\n`);
245
+ }
246
+ /**
247
+ * Lists all available checkpoints and exits
248
+ */
249
+ export async function listCheckpoints(config) {
250
+ try {
251
+ const geminiDir = config.storage?.getProjectTempDir();
252
+ if (!geminiDir) {
253
+ printInfoToStderr(red('✖ Error'), 'Could not determine the .blackboxcli directory path.');
254
+ process.exit(1);
255
+ }
256
+ const file_head = 'checkpoint-';
257
+ const file_tail = '.json';
258
+ const files = await fsPromises.readdir(geminiDir);
259
+ const checkpoints = [];
260
+ for (const file of files) {
261
+ if (file.startsWith(file_head) && file.endsWith(file_tail)) {
262
+ const filePath = path.join(geminiDir, file);
263
+ const stats = await fsPromises.stat(filePath);
264
+ const tagName = file.slice(file_head.length, -file_tail.length);
265
+ checkpoints.push({
266
+ name: decodeTagName(tagName),
267
+ mtime: stats.mtime,
268
+ });
269
+ }
270
+ }
271
+ if (checkpoints.length === 0) {
272
+ console.log('No saved conversation checkpoints found.');
273
+ process.exit(0);
274
+ }
275
+ // Sort by modification time (newest first)
276
+ checkpoints.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
277
+ const maxNameLength = Math.max(...checkpoints.map((cp) => cp.name.length));
278
+ console.log('Available conversation checkpoints:\n');
279
+ for (const checkpoint of checkpoints) {
280
+ const paddedName = checkpoint.name.padEnd(maxNameLength, ' ');
281
+ const isoString = checkpoint.mtime.toISOString();
282
+ const match = isoString.match(/(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2})/);
283
+ const formattedDate = match ? `${match[1]} ${match[2]}` : 'Invalid Date';
284
+ console.log(` ${cyan(paddedName)} ${gray(`(saved on ${formattedDate})`)}`);
285
+ }
286
+ console.log(`\n${gray('Resume with:')} ${cyan('blackbox --resume-checkpoint "<tag>" --prompt "<new-task>"')}`);
287
+ process.exit(0);
288
+ }
289
+ catch (error) {
290
+ printInfoToStderr(red('✖ Error'), `Failed to list checkpoints: ${error instanceof Error ? error.message : String(error)}`);
291
+ process.exit(1);
292
+ }
293
+ }
294
+ /**
295
+ * Resumes conversation from a checkpoint
296
+ * Supports both local and cloud checkpoints (from Supabase database)
297
+ */
298
+ async function resumeFromCheckpoint(config, tag) {
299
+ try {
300
+ const logger = new Logger(config.getSessionId(), config.storage);
301
+ await logger.initialize();
302
+ // Try loading from local storage first
303
+ let conversation = await logger.loadCheckpoint(tag);
304
+ // If not found locally and should check cloud (starts with "cloud-" or is a 21-char ID), try fetching from database
305
+ if (conversation.length === 0 && (tag.startsWith('cloud-') || (tag.length === 21 && /^[a-zA-Z0-9_-]+$/.test(tag)))) {
306
+ try {
307
+ const apiService = new CheckpointApiService();
308
+ // Check if API key is configured
309
+ if (!apiService.isConfigured()) {
310
+ printInfoToStderr(yellow('⚠ Warning'), 'Blackbox API key not configured. Set BLACKBOX_API_KEY environment variable to restore checkpoints.');
311
+ printInfoToStderr(red('✖ Error'), `No saved checkpoint found with tag: ${decodeTagName(tag)}`);
312
+ process.exit(1);
313
+ }
314
+ // Fetch checkpoint from API
315
+ printInfoToStderr(dim('→ Restoring'), 'checkpoint from database...');
316
+ const checkpoint = await apiService.fetchCheckpointByTag(tag);
317
+ if (!checkpoint || !checkpoint.content) {
318
+ printInfoToStderr(yellow('⚠ Warning'), `Checkpoint not found: ${decodeTagName(tag)}`);
319
+ printInfoToStderr(red('✖ Error'), `No saved checkpoint found with tag: ${decodeTagName(tag)}`);
320
+ process.exit(1);
321
+ }
322
+ // Save the fetched checkpoint to local filesystem
323
+ await logger.saveCheckpointFromDatabase(tag, checkpoint.content);
324
+ // Load the checkpoint from local filesystem
325
+ conversation = await logger.loadCheckpoint(tag);
326
+ if (conversation.length === 0) {
327
+ printInfoToStderr(red('✖ Error'), 'Failed to load checkpoint');
328
+ process.exit(1);
329
+ }
330
+ }
331
+ catch (apiError) {
332
+ // Log API error but don't expose sensitive details
333
+ if (config.getDebugMode()) {
334
+ console.error('API error details:', apiError);
335
+ }
336
+ printInfoToStderr(red('✖ Error'), `Failed to fetch checkpoint: ${apiError instanceof Error ? apiError.message : 'Unknown error'}`);
337
+ process.exit(1);
338
+ }
339
+ }
340
+ // Final check if checkpoint was found
341
+ if (conversation.length === 0) {
342
+ printInfoToStderr(red('✖ Error'), `No saved checkpoint found with tag: ${decodeTagName(tag)}`);
343
+ process.exit(1);
344
+ }
345
+ // Restore the conversation history to the Gemini client
346
+ const geminiClient = config.getGeminiClient();
347
+ if (geminiClient && geminiClient.isInitialized()) {
348
+ geminiClient.setHistory(conversation);
349
+ printInfoToStderr(green('✓ Checkpoint restored:'), `${bold(decodeTagName(tag))} ${dim('(continuing conversation)')}`);
350
+ }
351
+ else {
352
+ printInfoToStderr(red('✖ Error'), 'Gemini client not initialized');
353
+ process.exit(1);
354
+ }
355
+ }
356
+ catch (error) {
357
+ printInfoToStderr(red('✖ Error'), `Failed to resume checkpoint: ${error instanceof Error ? error.message : String(error)}`);
358
+ process.exit(1);
359
+ }
360
+ }
361
+ /**
362
+ * Generates a safe, unique checkpoint name using UUID and timestamp
363
+ */
364
+ function generateCheckpointName() {
365
+ // Generate a simple UUID-like string (8 characters)
366
+ const uuid = Math.random().toString(36).substring(2, 10);
367
+ // Generate timestamp
368
+ const now = new Date();
369
+ const timestamp = now.toISOString()
370
+ .replace(/[:.]/g, '-')
371
+ .replace('T', '-')
372
+ .substring(0, 19); // YYYY-MM-DD-HH-MM-SS
373
+ return `task-${uuid}-${timestamp}`;
374
+ }
375
+ /**
376
+ * Saves conversation checkpoint after successful task completion in non-interactive mode
377
+ */
378
+ async function saveConversationCheckpoint(config, originalInput, customTag) {
379
+ try {
380
+ const chat = config.getGeminiClient()?.getChat();
381
+ if (!chat)
382
+ return;
383
+ const history = chat.getHistory();
384
+ if (history.length <= 2)
385
+ return; // No meaningful conversation
386
+ const logger = new Logger(config.getSessionId(), config.storage);
387
+ await logger.initialize();
388
+ let tag;
389
+ if (customTag) {
390
+ tag = customTag;
391
+ }
392
+ else {
393
+ // Generate safe, unique tag
394
+ tag = generateCheckpointName();
395
+ }
396
+ await logger.saveCheckpoint(history, tag);
397
+ // Get the full path to the checkpoint file
398
+ const checkpointDir = config.storage?.getProjectTempDir();
399
+ const checkpointPath = checkpointDir ? path.join(checkpointDir, `checkpoint-${tag}.json`) : `checkpoint-${tag}.json`;
400
+ printInfoToStderr(green('✓ Checkpoint saved:'), `${bold(tag)}\n ${dim('- Path:')} ${checkpointPath}\n ${dim('- Resume with:')} ${cyan(`blackbox`)} ${dim('then')} ${cyan(`/chat resume "${tag}"`)}`);
401
+ }
402
+ catch (error) {
403
+ // Don't fail the main task if checkpoint saving fails
404
+ if (config.getDebugMode()) {
405
+ printInfoToStderr(yellow('⚠ Checkpoint save failed:'), error instanceof Error ? error.message : String(error));
406
+ }
407
+ }
408
+ }
9
409
  export async function runNonInteractive(config, input, prompt_id) {
410
+ // Handle list checkpoints command
411
+ if (config.getListCheckpoints()) {
412
+ await listCheckpoints(config);
413
+ return;
414
+ }
415
+ // Handle resume checkpoint
416
+ const resumeTag = config.getResumeCheckpoint();
417
+ if (resumeTag) {
418
+ await resumeFromCheckpoint(config, resumeTag);
419
+ }
10
420
  const consolePatcher = new ConsolePatcher({
11
421
  stderr: true,
12
422
  debugMode: config.getDebugMode(),
@@ -52,21 +462,164 @@ export async function runNonInteractive(config, input, prompt_id) {
52
462
  console.error('Operation cancelled.');
53
463
  return;
54
464
  }
55
- if (event.type === GeminiEventType.Content) {
56
- process.stdout.write(event.value);
57
- }
58
- else if (event.type === GeminiEventType.ToolCallRequest) {
59
- toolCallRequests.push(event.value);
465
+ switch (event.type) {
466
+ case GeminiEventType.Content: {
467
+ process.stdout.write(event.value);
468
+ break;
469
+ }
470
+ case GeminiEventType.ToolCallRequest: {
471
+ toolCallRequests.push(event.value);
472
+ break;
473
+ }
474
+ case GeminiEventType.Thought: {
475
+ // Keep agent "thoughts" off stdout so piping remains clean
476
+ printInfoToStderr(cyan('ℹ Thought:'), `${bold(event.value.subject)} ${dim('-')} ${event.value.description}`);
477
+ break;
478
+ }
479
+ case GeminiEventType.Retry: {
480
+ printInfoToStderr(yellow('↻ Retrying'), dim('request...'));
481
+ break;
482
+ }
483
+ case GeminiEventType.ChatCompressed: {
484
+ printInfoToStderr(blue('ℹ Compression'), `Using compressed context (${event.value?.originalTokenCount ?? 'unknown'} → ${event.value?.newTokenCount ?? 'unknown'} tokens).`);
485
+ break;
486
+ }
487
+ case GeminiEventType.MaxSessionTurns: {
488
+ printInfoToStderr(yellow('⚠ Max turns'), 'Reached max session turns.');
489
+ return;
490
+ }
491
+ case GeminiEventType.SessionTokenLimitExceeded: {
492
+ printInfoToStderr(red('🚫 Token limit'), `${event.value.message}\n` +
493
+ `${dim('Tips:')}\n` +
494
+ ` ${dim('•')} Start a new session.\n` +
495
+ ` ${dim('•')} Increase limit via settings.json (sessionTokenLimit).\n` +
496
+ ` ${dim('•')} Compress history using /compress in interactive mode.`);
497
+ return;
498
+ }
499
+ case GeminiEventType.Finished: {
500
+ const finishReason = event.value;
501
+ const finishReasonMessages = {
502
+ [FinishReason.MAX_TOKENS]: 'Response truncated due to token limits.',
503
+ [FinishReason.SAFETY]: 'Response stopped due to safety reasons.',
504
+ [FinishReason.RECITATION]: 'Response stopped due to recitation policy.',
505
+ [FinishReason.LANGUAGE]: 'Response stopped due to unsupported language.',
506
+ [FinishReason.BLOCKLIST]: 'Response stopped due to forbidden terms.',
507
+ [FinishReason.PROHIBITED_CONTENT]: 'Response stopped due to prohibited content.',
508
+ [FinishReason.SPII]: 'Response stopped due to sensitive personally identifiable information.',
509
+ [FinishReason.OTHER]: 'Response stopped for other reasons.',
510
+ [FinishReason.MALFORMED_FUNCTION_CALL]: 'Response stopped due to malformed function call.',
511
+ [FinishReason.IMAGE_SAFETY]: 'Response stopped due to image safety violations.',
512
+ [FinishReason.UNEXPECTED_TOOL_CALL]: 'Response stopped due to unexpected tool call.',
513
+ [FinishReason.IMAGE_PROHIBITED_CONTENT]: 'Response stopped due to prohibited image content.',
514
+ [FinishReason.NO_IMAGE]: 'Response stopped because no image was provided.',
515
+ };
516
+ const message = finishReasonMessages[finishReason];
517
+ if (message) {
518
+ printInfoToStderr(yellow('⚠ Finished'), message);
519
+ }
520
+ break;
521
+ }
522
+ case GeminiEventType.LoopDetected: {
523
+ printInfoToStderr(magenta('⚠ Loop detected'), 'A potential loop was detected. The request has been halted.');
524
+ return;
525
+ }
526
+ case GeminiEventType.Error: {
527
+ printInfoToStderr(red('✖ Error'), event.value.error.message);
528
+ return;
529
+ }
530
+ default: {
531
+ // Ignore other event types in non-interactive mode
532
+ break;
533
+ }
60
534
  }
61
535
  }
62
536
  if (toolCallRequests.length > 0) {
63
537
  const toolResponseParts = [];
64
538
  for (const requestInfo of toolCallRequests) {
539
+ // Build a plan preview using ToolRegistry if available
540
+ try {
541
+ const tool = config.getToolRegistry().getTool(requestInfo.name);
542
+ if (tool) {
543
+ const invocation = tool.build(requestInfo.args);
544
+ const description = invocation.getDescription() || '';
545
+ // For edit_file, edit, and write_file, hide long content in the payload
546
+ let argsToShow = requestInfo.args;
547
+ const MAX_CONTENT_DISPLAY = 200;
548
+ // Hide edit_file SEARCH/REPLACE content
549
+ if (requestInfo.name === 'edit_file' && requestInfo.args && typeof requestInfo.args === 'object') {
550
+ const args = requestInfo.args;
551
+ if ('content' in args && typeof args['content'] === 'string') {
552
+ const content = args['content'];
553
+ // Show a summary instead of the full SEARCH/REPLACE blocks
554
+ const searchBlocks = (content.match(/<<<<<<< SEARCH/g) || []).length;
555
+ argsToShow = {
556
+ ...args,
557
+ content: `[${searchBlocks} edit block${searchBlocks !== 1 ? 's' : ''} - content hidden for clarity]`
558
+ };
559
+ }
560
+ }
561
+ // Hide edit tool old_string and new_string if they're long
562
+ if (requestInfo.name === 'edit' && requestInfo.args && typeof requestInfo.args === 'object') {
563
+ const args = requestInfo.args;
564
+ const updatedArgs = { ...args };
565
+ if ('old_string' in args && typeof args['old_string'] === 'string') {
566
+ const oldString = args['old_string'];
567
+ if (oldString.length > MAX_CONTENT_DISPLAY) {
568
+ const lines = oldString.split('\n').length;
569
+ const chars = oldString.length;
570
+ updatedArgs['old_string'] = `[Content hidden - ${lines} lines, ${chars} characters]`;
571
+ }
572
+ }
573
+ if ('new_string' in args && typeof args['new_string'] === 'string') {
574
+ const newString = args['new_string'];
575
+ if (newString.length > MAX_CONTENT_DISPLAY) {
576
+ const lines = newString.split('\n').length;
577
+ const chars = newString.length;
578
+ updatedArgs['new_string'] = `[Content hidden - ${lines} lines, ${chars} characters]`;
579
+ }
580
+ }
581
+ argsToShow = updatedArgs;
582
+ }
583
+ // Hide write_file content if it's long
584
+ if (requestInfo.name === 'write_file' && requestInfo.args && typeof requestInfo.args === 'object') {
585
+ const args = requestInfo.args;
586
+ if ('content' in args && typeof args['content'] === 'string') {
587
+ const content = args['content'];
588
+ if (content.length > MAX_CONTENT_DISPLAY) {
589
+ const lines = content.split('\n').length;
590
+ const chars = content.length;
591
+ argsToShow = {
592
+ ...args,
593
+ content: `[Content hidden - ${lines} lines, ${chars} characters]`
594
+ };
595
+ }
596
+ }
597
+ }
598
+ const prettyArgs = JSON.stringify(argsToShow, null, 2);
599
+ printPlanSectionToStderr(requestInfo.name, description, prettyArgs);
600
+ }
601
+ else {
602
+ const prettyArgs = JSON.stringify(requestInfo.args, null, 2);
603
+ printPlanSectionToStderr(requestInfo.name, '(tool not found in registry)', prettyArgs);
604
+ }
605
+ }
606
+ catch (_e) {
607
+ // If plan building fails, still show the raw args so users see payload
608
+ const prettyArgs = JSON.stringify(requestInfo.args, null, 2);
609
+ printPlanSectionToStderr(requestInfo.name, '(failed to build plan; showing raw payload)', prettyArgs);
610
+ }
65
611
  const toolResponse = await executeToolCall(config, requestInfo, abortController.signal);
66
612
  if (toolResponse.error &&
67
613
  !config.getSupressToolIterationErrors()) {
68
614
  console.error(`Error executing tool ${requestInfo.name}: ${toolResponse.resultDisplay || toolResponse.error.message}`);
69
615
  }
616
+ // Print tool results to stdout with a styled section
617
+ if (toolResponse.resultDisplay) {
618
+ const displayContent = formatToolResultDisplay(toolResponse.resultDisplay);
619
+ if (displayContent) {
620
+ printToolSectionToStdout(requestInfo.name, displayContent);
621
+ }
622
+ }
70
623
  if (toolResponse.responseParts) {
71
624
  toolResponseParts.push(...toolResponse.responseParts);
72
625
  }
@@ -75,6 +628,10 @@ export async function runNonInteractive(config, input, prompt_id) {
75
628
  }
76
629
  else {
77
630
  process.stdout.write('\n'); // Ensure a final newline
631
+ // Save checkpoint if requested
632
+ if (config.getSaveCheckpoint() || config.getAutoSave()) {
633
+ await saveConversationCheckpoint(config, input, config.getSaveCheckpoint());
634
+ }
78
635
  return;
79
636
  }
80
637
  }