@umsai/ums-code 0.0.14-v1 → 0.0.14-v2

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 (892) hide show
  1. package/dist/index.js +9 -0
  2. package/dist/index.js.map +1 -1
  3. package/dist/package.json +10 -7
  4. package/dist/src/commands/extensions/disable.d.ts +14 -0
  5. package/dist/src/commands/extensions/disable.js +42 -0
  6. package/dist/src/commands/extensions/disable.js.map +1 -0
  7. package/dist/src/commands/extensions/enable.d.ts +14 -0
  8. package/dist/src/commands/extensions/enable.js +48 -0
  9. package/dist/src/commands/extensions/enable.js.map +1 -0
  10. package/dist/src/commands/extensions/install.d.ts +13 -0
  11. package/dist/src/commands/extensions/install.js +48 -0
  12. package/dist/src/commands/extensions/install.js.map +1 -0
  13. package/dist/src/commands/extensions/install.test.d.ts +6 -0
  14. package/dist/src/commands/extensions/install.test.js +25 -0
  15. package/dist/src/commands/extensions/install.test.js.map +1 -0
  16. package/dist/src/commands/extensions/list.d.ts +8 -0
  17. package/dist/src/commands/extensions/list.js +32 -0
  18. package/dist/src/commands/extensions/list.js.map +1 -0
  19. package/dist/src/commands/extensions/uninstall.d.ts +12 -0
  20. package/dist/src/commands/extensions/uninstall.js +38 -0
  21. package/dist/src/commands/extensions/uninstall.js.map +1 -0
  22. package/dist/src/commands/extensions/uninstall.test.d.ts +6 -0
  23. package/dist/src/commands/extensions/uninstall.test.js +18 -0
  24. package/dist/src/commands/extensions/uninstall.test.js.map +1 -0
  25. package/dist/src/commands/extensions/update.d.ts +12 -0
  26. package/dist/src/commands/extensions/update.js +38 -0
  27. package/dist/src/commands/extensions/update.js.map +1 -0
  28. package/dist/src/commands/extensions.d.ts +7 -0
  29. package/dist/src/commands/extensions.js +29 -0
  30. package/dist/src/commands/extensions.js.map +1 -0
  31. package/dist/src/commands/mcp/add.d.ts +7 -0
  32. package/dist/src/commands/mcp/add.js +167 -0
  33. package/dist/src/commands/mcp/add.js.map +1 -0
  34. package/dist/src/commands/mcp/list.d.ts +8 -0
  35. package/dist/src/commands/mcp/list.js +110 -0
  36. package/dist/src/commands/mcp/list.js.map +1 -0
  37. package/dist/src/commands/mcp/remove.d.ts +7 -0
  38. package/dist/src/commands/mcp/remove.js +44 -0
  39. package/dist/src/commands/mcp/remove.js.map +1 -0
  40. package/dist/src/commands/mcp.d.ts +7 -0
  41. package/dist/src/commands/mcp.js +23 -0
  42. package/dist/src/commands/mcp.js.map +1 -0
  43. package/dist/src/config/auth.js +13 -12
  44. package/dist/src/config/auth.js.map +1 -1
  45. package/dist/src/config/auth.test.d.ts +6 -0
  46. package/dist/src/config/auth.test.js +57 -0
  47. package/dist/src/config/auth.test.js.map +1 -0
  48. package/dist/src/config/config.d.ts +11 -9
  49. package/dist/src/config/config.js +257 -133
  50. package/dist/src/config/config.js.map +1 -1
  51. package/dist/src/config/extension.d.ts +41 -3
  52. package/dist/src/config/extension.js +277 -18
  53. package/dist/src/config/extension.js.map +1 -1
  54. package/dist/src/config/extensions/variableSchema.d.ts +28 -0
  55. package/dist/src/config/extensions/variableSchema.js +18 -0
  56. package/dist/src/config/extensions/variableSchema.js.map +1 -0
  57. package/dist/src/config/extensions/variables.d.ts +17 -0
  58. package/dist/src/config/extensions/variables.js +40 -0
  59. package/dist/src/config/extensions/variables.js.map +1 -0
  60. package/dist/src/config/extensions/variables.test.d.ts +6 -0
  61. package/dist/src/config/extensions/variables.test.js +17 -0
  62. package/dist/src/config/extensions/variables.test.js.map +1 -0
  63. package/dist/src/config/keyBindings.d.ts +66 -0
  64. package/dist/src/config/keyBindings.js +141 -0
  65. package/dist/src/config/keyBindings.js.map +1 -0
  66. package/dist/src/config/keyBindings.test.d.ts +6 -0
  67. package/dist/src/config/keyBindings.test.js +51 -0
  68. package/dist/src/config/keyBindings.test.js.map +1 -0
  69. package/dist/src/config/sandboxConfig.d.ts +2 -2
  70. package/dist/src/config/sandboxConfig.js +8 -10
  71. package/dist/src/config/sandboxConfig.js.map +1 -1
  72. package/dist/src/config/settings.d.ts +14 -69
  73. package/dist/src/config/settings.js +425 -94
  74. package/dist/src/config/settings.js.map +1 -1
  75. package/dist/src/config/settingsSchema.d.ts +884 -0
  76. package/dist/src/config/settingsSchema.js +857 -0
  77. package/dist/src/config/settingsSchema.js.map +1 -0
  78. package/dist/src/config/settingsSchema.test.d.ts +6 -0
  79. package/dist/src/config/settingsSchema.test.js +194 -0
  80. package/dist/src/config/settingsSchema.test.js.map +1 -0
  81. package/dist/src/config/trustedFolders.d.ts +37 -0
  82. package/dist/src/config/trustedFolders.js +118 -0
  83. package/dist/src/config/trustedFolders.js.map +1 -0
  84. package/dist/src/config/trustedFolders.test.d.ts +6 -0
  85. package/dist/src/config/trustedFolders.test.js +164 -0
  86. package/dist/src/config/trustedFolders.test.js.map +1 -0
  87. package/dist/src/gemini.d.ts +3 -1
  88. package/dist/src/gemini.js +118 -99
  89. package/dist/src/gemini.js.map +1 -1
  90. package/dist/src/gemini.test.d.ts +6 -0
  91. package/dist/src/gemini.test.js +247 -0
  92. package/dist/src/gemini.test.js.map +1 -0
  93. package/dist/src/generated/git-commit.d.ts +2 -1
  94. package/dist/src/generated/git-commit.js +2 -1
  95. package/dist/src/generated/git-commit.js.map +1 -1
  96. package/dist/src/nonInteractiveCli.d.ts +1 -1
  97. package/dist/src/nonInteractiveCli.js +26 -42
  98. package/dist/src/nonInteractiveCli.js.map +1 -1
  99. package/dist/src/services/BuiltinCommandLoader.d.ts +3 -4
  100. package/dist/src/services/BuiltinCommandLoader.js +15 -4
  101. package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
  102. package/dist/src/services/BuiltinCommandLoader.test.d.ts +6 -0
  103. package/dist/src/services/BuiltinCommandLoader.test.js +130 -0
  104. package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -0
  105. package/dist/src/services/CommandService.d.ts +2 -2
  106. package/dist/src/services/CommandService.test.d.ts +6 -0
  107. package/dist/src/services/CommandService.test.js +233 -0
  108. package/dist/src/services/CommandService.test.js.map +1 -0
  109. package/dist/src/services/FileCommandLoader.d.ts +3 -3
  110. package/dist/src/services/FileCommandLoader.js +31 -19
  111. package/dist/src/services/FileCommandLoader.js.map +1 -1
  112. package/dist/src/services/McpPromptLoader.d.ts +14 -4
  113. package/dist/src/services/McpPromptLoader.js +46 -20
  114. package/dist/src/services/McpPromptLoader.js.map +1 -1
  115. package/dist/src/services/McpPromptLoader.test.d.ts +6 -0
  116. package/dist/src/services/McpPromptLoader.test.js +114 -0
  117. package/dist/src/services/McpPromptLoader.test.js.map +1 -0
  118. package/dist/src/services/prompt-processors/argumentProcessor.d.ts +5 -10
  119. package/dist/src/services/prompt-processors/argumentProcessor.js +5 -12
  120. package/dist/src/services/prompt-processors/argumentProcessor.js.map +1 -1
  121. package/dist/src/services/prompt-processors/atFileProcessor.d.ts +12 -0
  122. package/dist/src/services/prompt-processors/atFileProcessor.js +62 -0
  123. package/dist/src/services/prompt-processors/atFileProcessor.js.map +1 -0
  124. package/dist/src/services/prompt-processors/atFileProcessor.test.d.ts +6 -0
  125. package/dist/src/services/prompt-processors/atFileProcessor.test.js +174 -0
  126. package/dist/src/services/prompt-processors/atFileProcessor.test.js.map +1 -0
  127. package/dist/src/services/prompt-processors/injectionParser.d.ts +29 -0
  128. package/dist/src/services/prompt-processors/injectionParser.js +60 -0
  129. package/dist/src/services/prompt-processors/injectionParser.js.map +1 -0
  130. package/dist/src/services/prompt-processors/injectionParser.test.d.ts +6 -0
  131. package/dist/src/services/prompt-processors/injectionParser.test.js +189 -0
  132. package/dist/src/services/prompt-processors/injectionParser.test.js.map +1 -0
  133. package/dist/src/services/prompt-processors/shellProcessor.d.ts +11 -16
  134. package/dist/src/services/prompt-processors/shellProcessor.js +85 -41
  135. package/dist/src/services/prompt-processors/shellProcessor.js.map +1 -1
  136. package/dist/src/services/prompt-processors/types.d.ts +15 -8
  137. package/dist/src/services/prompt-processors/types.js +6 -0
  138. package/dist/src/services/prompt-processors/types.js.map +1 -1
  139. package/dist/src/services/types.d.ts +1 -1
  140. package/dist/src/test-utils/customMatchers.d.ts +14 -0
  141. package/dist/src/test-utils/customMatchers.js +40 -0
  142. package/dist/src/test-utils/customMatchers.js.map +1 -0
  143. package/dist/src/test-utils/mockCommandContext.d.ts +18 -0
  144. package/dist/src/test-utils/mockCommandContext.js +90 -0
  145. package/dist/src/test-utils/mockCommandContext.js.map +1 -0
  146. package/dist/src/test-utils/mockCommandContext.test.d.ts +6 -0
  147. package/dist/src/test-utils/mockCommandContext.test.js +51 -0
  148. package/dist/src/test-utils/mockCommandContext.test.js.map +1 -0
  149. package/dist/src/test-utils/render.d.ts +8 -0
  150. package/dist/src/test-utils/render.js +10 -0
  151. package/dist/src/test-utils/render.js.map +1 -0
  152. package/dist/src/ui/App.d.ts +2 -2
  153. package/dist/src/ui/App.js +342 -70
  154. package/dist/src/ui/App.js.map +1 -1
  155. package/dist/src/ui/IdeIntegrationNudge.d.ts +16 -0
  156. package/dist/src/ui/IdeIntegrationNudge.js +52 -0
  157. package/dist/src/ui/IdeIntegrationNudge.js.map +1 -0
  158. package/dist/src/ui/colors.d.ts +1 -1
  159. package/dist/src/ui/commands/aboutCommand.d.ts +1 -1
  160. package/dist/src/ui/commands/aboutCommand.js +10 -6
  161. package/dist/src/ui/commands/aboutCommand.js.map +1 -1
  162. package/dist/src/ui/commands/agentsCommand.d.ts +7 -0
  163. package/dist/src/ui/commands/agentsCommand.js +32 -0
  164. package/dist/src/ui/commands/agentsCommand.js.map +1 -0
  165. package/dist/src/ui/commands/approvalModeCommand.d.ts +7 -0
  166. package/dist/src/ui/commands/approvalModeCommand.js +340 -0
  167. package/dist/src/ui/commands/approvalModeCommand.js.map +1 -0
  168. package/dist/src/ui/commands/approvalModeCommand.test.d.ts +6 -0
  169. package/dist/src/ui/commands/approvalModeCommand.test.js +293 -0
  170. package/dist/src/ui/commands/approvalModeCommand.test.js.map +1 -0
  171. package/dist/src/ui/commands/authCommand.d.ts +1 -1
  172. package/dist/src/ui/commands/authCommand.js.map +1 -1
  173. package/dist/src/ui/commands/bugCommand.js +13 -5
  174. package/dist/src/ui/commands/bugCommand.js.map +1 -1
  175. package/dist/src/ui/commands/chatCommand.d.ts +1 -1
  176. package/dist/src/ui/commands/chatCommand.js +27 -9
  177. package/dist/src/ui/commands/chatCommand.js.map +1 -1
  178. package/dist/src/ui/commands/clearCommand.d.ts +1 -1
  179. package/dist/src/ui/commands/clearCommand.js +0 -1
  180. package/dist/src/ui/commands/clearCommand.js.map +1 -1
  181. package/dist/src/ui/commands/compressCommand.d.ts +1 -1
  182. package/dist/src/ui/commands/compressCommand.js +2 -0
  183. package/dist/src/ui/commands/compressCommand.js.map +1 -1
  184. package/dist/src/ui/commands/copyCommand.d.ts +1 -1
  185. package/dist/src/ui/commands/copyCommand.js +2 -2
  186. package/dist/src/ui/commands/copyCommand.js.map +1 -1
  187. package/dist/src/ui/commands/directoryCommand.d.ts +1 -1
  188. package/dist/src/ui/commands/directoryCommand.js +7 -8
  189. package/dist/src/ui/commands/directoryCommand.js.map +1 -1
  190. package/dist/src/ui/commands/docsCommand.js +1 -1
  191. package/dist/src/ui/commands/docsCommand.js.map +1 -1
  192. package/dist/src/ui/commands/helpCommand.d.ts +1 -1
  193. package/dist/src/ui/commands/helpCommand.js.map +1 -1
  194. package/dist/src/ui/commands/ideCommand.d.ts +2 -2
  195. package/dist/src/ui/commands/ideCommand.js +92 -22
  196. package/dist/src/ui/commands/ideCommand.js.map +1 -1
  197. package/dist/src/ui/commands/initCommand.d.ts +2 -2
  198. package/dist/src/ui/commands/initCommand.js +20 -10
  199. package/dist/src/ui/commands/initCommand.js.map +1 -1
  200. package/dist/src/ui/commands/mcpCommand.d.ts +1 -1
  201. package/dist/src/ui/commands/mcpCommand.js +12 -8
  202. package/dist/src/ui/commands/mcpCommand.js.map +1 -1
  203. package/dist/src/ui/commands/memoryCommand.d.ts +1 -1
  204. package/dist/src/ui/commands/memoryCommand.js +143 -9
  205. package/dist/src/ui/commands/memoryCommand.js.map +1 -1
  206. package/dist/src/ui/commands/modelCommand.d.ts +7 -0
  207. package/dist/src/ui/commands/modelCommand.js +68 -0
  208. package/dist/src/ui/commands/modelCommand.js.map +1 -0
  209. package/dist/src/ui/commands/modelCommand.test.d.ts +6 -0
  210. package/dist/src/ui/commands/modelCommand.test.js +138 -0
  211. package/dist/src/ui/commands/modelCommand.test.js.map +1 -0
  212. package/dist/src/ui/commands/privacyCommand.d.ts +1 -1
  213. package/dist/src/ui/commands/privacyCommand.js.map +1 -1
  214. package/dist/src/ui/commands/quitCommand.d.ts +1 -0
  215. package/dist/src/ui/commands/quitCommand.js +25 -0
  216. package/dist/src/ui/commands/quitCommand.js.map +1 -1
  217. package/dist/src/ui/commands/restoreCommand.d.ts +1 -1
  218. package/dist/src/ui/commands/restoreCommand.js +4 -8
  219. package/dist/src/ui/commands/restoreCommand.js.map +1 -1
  220. package/dist/src/ui/commands/settingsCommand.d.ts +7 -0
  221. package/dist/src/ui/commands/settingsCommand.js +16 -0
  222. package/dist/src/ui/commands/settingsCommand.js.map +1 -0
  223. package/dist/src/ui/commands/setupGithubCommand.d.ts +3 -1
  224. package/dist/src/ui/commands/setupGithubCommand.js +133 -27
  225. package/dist/src/ui/commands/setupGithubCommand.js.map +1 -1
  226. package/dist/src/ui/commands/setupGithubCommand.test.d.ts +6 -0
  227. package/dist/src/ui/commands/setupGithubCommand.test.js +167 -0
  228. package/dist/src/ui/commands/setupGithubCommand.test.js.map +1 -0
  229. package/dist/src/ui/commands/statsCommand.js.map +1 -1
  230. package/dist/src/ui/commands/summaryCommand.d.ts +7 -0
  231. package/dist/src/ui/commands/summaryCommand.js +149 -0
  232. package/dist/src/ui/commands/summaryCommand.js.map +1 -0
  233. package/dist/src/ui/commands/terminalSetupCommand.d.ts +13 -0
  234. package/dist/src/ui/commands/terminalSetupCommand.js +41 -0
  235. package/dist/src/ui/commands/terminalSetupCommand.js.map +1 -0
  236. package/dist/src/ui/commands/themeCommand.d.ts +1 -1
  237. package/dist/src/ui/commands/themeCommand.js.map +1 -1
  238. package/dist/src/ui/commands/toolsCommand.js +1 -1
  239. package/dist/src/ui/commands/toolsCommand.js.map +1 -1
  240. package/dist/src/ui/commands/types.d.ts +26 -11
  241. package/dist/src/ui/commands/types.js +1 -0
  242. package/dist/src/ui/commands/types.js.map +1 -1
  243. package/dist/src/ui/commands/ums/umsInitCommand.d.ts +1 -1
  244. package/dist/src/ui/commands/ums/umsInitCommand.js +54 -20
  245. package/dist/src/ui/commands/ums/umsInitCommand.js.map +1 -1
  246. package/dist/src/ui/commands/vimCommand.d.ts +1 -1
  247. package/dist/src/ui/commands/vimCommand.js.map +1 -1
  248. package/dist/src/ui/components/AboutBox.d.ts +2 -1
  249. package/dist/src/ui/components/AboutBox.js +1 -1
  250. package/dist/src/ui/components/AboutBox.js.map +1 -1
  251. package/dist/src/ui/components/AsciiArt.d.ts +1 -0
  252. package/dist/src/ui/components/AsciiArt.js +8 -0
  253. package/dist/src/ui/components/AsciiArt.js.map +1 -1
  254. package/dist/src/ui/components/AuthDialog.d.ts +2 -2
  255. package/dist/src/ui/components/AuthDialog.js +23 -22
  256. package/dist/src/ui/components/AuthDialog.js.map +1 -1
  257. package/dist/src/ui/components/AuthDialog.test.d.ts +6 -0
  258. package/dist/src/ui/components/AuthDialog.test.js +280 -0
  259. package/dist/src/ui/components/AuthDialog.test.js.map +1 -0
  260. package/dist/src/ui/components/AuthInProgress.d.ts +1 -1
  261. package/dist/src/ui/components/AuthInProgress.js +6 -10
  262. package/dist/src/ui/components/AuthInProgress.js.map +1 -1
  263. package/dist/src/ui/components/AutoAcceptIndicator.d.ts +1 -1
  264. package/dist/src/ui/components/AutoAcceptIndicator.js +8 -3
  265. package/dist/src/ui/components/AutoAcceptIndicator.js.map +1 -1
  266. package/dist/src/ui/components/ConsoleSummaryDisplay.d.ts +1 -1
  267. package/dist/src/ui/components/ContextSummaryDisplay.d.ts +1 -1
  268. package/dist/src/ui/components/ContextSummaryDisplay.js +23 -25
  269. package/dist/src/ui/components/ContextSummaryDisplay.js.map +1 -1
  270. package/dist/src/ui/components/ContextUsageDisplay.d.ts +9 -0
  271. package/dist/src/ui/components/ContextUsageDisplay.js +14 -0
  272. package/dist/src/ui/components/ContextUsageDisplay.js.map +1 -0
  273. package/dist/src/ui/components/DebugProfiler.js +5 -4
  274. package/dist/src/ui/components/DebugProfiler.js.map +1 -1
  275. package/dist/src/ui/components/DetailedMessagesDisplay.d.ts +2 -2
  276. package/dist/src/ui/components/DetailedMessagesDisplay.js +1 -1
  277. package/dist/src/ui/components/DetailedMessagesDisplay.js.map +1 -1
  278. package/dist/src/ui/components/EditorSettingsDialog.d.ts +4 -3
  279. package/dist/src/ui/components/EditorSettingsDialog.js +14 -16
  280. package/dist/src/ui/components/EditorSettingsDialog.js.map +1 -1
  281. package/dist/src/ui/components/FolderTrustDialog.d.ts +17 -0
  282. package/dist/src/ui/components/FolderTrustDialog.js +45 -0
  283. package/dist/src/ui/components/FolderTrustDialog.js.map +1 -0
  284. package/dist/src/ui/components/FolderTrustDialog.test.d.ts +6 -0
  285. package/dist/src/ui/components/FolderTrustDialog.test.js +63 -0
  286. package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -0
  287. package/dist/src/ui/components/Footer.d.ts +2 -1
  288. package/dist/src/ui/components/Footer.js +16 -6
  289. package/dist/src/ui/components/Footer.js.map +1 -1
  290. package/dist/src/ui/components/GeminiRespondingSpinner.d.ts +1 -1
  291. package/dist/src/ui/components/GeminiRespondingSpinner.js +5 -3
  292. package/dist/src/ui/components/GeminiRespondingSpinner.js.map +1 -1
  293. package/dist/src/ui/components/Header.d.ts +1 -2
  294. package/dist/src/ui/components/Header.js +13 -5
  295. package/dist/src/ui/components/Header.js.map +1 -1
  296. package/dist/src/ui/components/Header.test.d.ts +6 -0
  297. package/dist/src/ui/components/Header.test.js +37 -0
  298. package/dist/src/ui/components/Header.test.js.map +1 -0
  299. package/dist/src/ui/components/Help.d.ts +2 -2
  300. package/dist/src/ui/components/Help.js +2 -2
  301. package/dist/src/ui/components/Help.js.map +1 -1
  302. package/dist/src/ui/components/HistoryItemDisplay.d.ts +5 -5
  303. package/dist/src/ui/components/HistoryItemDisplay.js +5 -1
  304. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  305. package/dist/src/ui/components/HistoryItemDisplay.test.d.ts +6 -0
  306. package/dist/src/ui/components/HistoryItemDisplay.test.js +93 -0
  307. package/dist/src/ui/components/HistoryItemDisplay.test.js.map +1 -0
  308. package/dist/src/ui/components/InputPrompt.d.ts +6 -5
  309. package/dist/src/ui/components/InputPrompt.js +238 -53
  310. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  311. package/dist/src/ui/components/LoadingIndicator.d.ts +2 -2
  312. package/dist/src/ui/components/LoadingIndicator.js +10 -5
  313. package/dist/src/ui/components/LoadingIndicator.js.map +1 -1
  314. package/dist/src/ui/components/LoadingIndicator.test.d.ts +6 -0
  315. package/dist/src/ui/components/LoadingIndicator.test.js +190 -0
  316. package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -0
  317. package/dist/src/ui/components/MemoryUsageDisplay.d.ts +1 -1
  318. package/dist/src/ui/components/MemoryUsageDisplay.js +0 -5
  319. package/dist/src/ui/components/MemoryUsageDisplay.js.map +1 -1
  320. package/dist/src/ui/components/ModelSelectionDialog.d.ts +14 -0
  321. package/dist/src/ui/components/ModelSelectionDialog.js +26 -0
  322. package/dist/src/ui/components/ModelSelectionDialog.js.map +1 -0
  323. package/dist/src/ui/components/ModelSelectionDialog.test.d.ts +6 -0
  324. package/dist/src/ui/components/ModelSelectionDialog.test.js +124 -0
  325. package/dist/src/ui/components/ModelSelectionDialog.test.js.map +1 -0
  326. package/dist/src/ui/components/ModelStatsDisplay.d.ts +1 -1
  327. package/dist/src/ui/components/ModelStatsDisplay.js.map +1 -1
  328. package/dist/src/ui/components/ModelSwitchDialog.d.ts +15 -0
  329. package/dist/src/ui/components/ModelSwitchDialog.js +37 -0
  330. package/dist/src/ui/components/ModelSwitchDialog.js.map +1 -0
  331. package/dist/src/ui/components/ModelSwitchDialog.test.d.ts +6 -0
  332. package/dist/src/ui/components/ModelSwitchDialog.test.js +125 -0
  333. package/dist/src/ui/components/ModelSwitchDialog.test.js.map +1 -0
  334. package/dist/src/ui/components/OpenAIKeyPrompt.d.ts +1 -1
  335. package/dist/src/ui/components/OpenAIKeyPrompt.js +0 -5
  336. package/dist/src/ui/components/OpenAIKeyPrompt.js.map +1 -1
  337. package/dist/src/ui/components/OpenAIKeyPrompt.test.d.ts +6 -0
  338. package/dist/src/ui/components/OpenAIKeyPrompt.test.js +44 -0
  339. package/dist/src/ui/components/OpenAIKeyPrompt.test.js.map +1 -0
  340. package/dist/src/ui/components/PlanSummaryDisplay.d.ts +14 -0
  341. package/dist/src/ui/components/PlanSummaryDisplay.js +9 -0
  342. package/dist/src/ui/components/PlanSummaryDisplay.js.map +1 -0
  343. package/dist/src/ui/components/PrepareLabel.d.ts +1 -1
  344. package/dist/src/ui/components/QuitConfirmationDialog.d.ts +17 -0
  345. package/dist/src/ui/components/QuitConfirmationDialog.js +44 -0
  346. package/dist/src/ui/components/QuitConfirmationDialog.js.map +1 -0
  347. package/dist/src/ui/components/QwenOAuthProgress.d.ts +2 -2
  348. package/dist/src/ui/components/QwenOAuthProgress.js +0 -5
  349. package/dist/src/ui/components/QwenOAuthProgress.js.map +1 -1
  350. package/dist/src/ui/components/QwenOAuthProgress.test.d.ts +6 -0
  351. package/dist/src/ui/components/QwenOAuthProgress.test.js +292 -0
  352. package/dist/src/ui/components/QwenOAuthProgress.test.js.map +1 -0
  353. package/dist/src/ui/components/SessionSummaryDisplay.d.ts +1 -1
  354. package/dist/src/ui/components/SettingsDialog.d.ts +15 -0
  355. package/dist/src/ui/components/SettingsDialog.js +550 -0
  356. package/dist/src/ui/components/SettingsDialog.js.map +1 -0
  357. package/dist/src/ui/components/SettingsDialog.test.d.ts +6 -0
  358. package/dist/src/ui/components/SettingsDialog.test.js +646 -0
  359. package/dist/src/ui/components/SettingsDialog.test.js.map +1 -0
  360. package/dist/src/ui/components/ShellConfirmationDialog.d.ts +1 -1
  361. package/dist/src/ui/components/ShellConfirmationDialog.js +8 -6
  362. package/dist/src/ui/components/ShellConfirmationDialog.js.map +1 -1
  363. package/dist/src/ui/components/ShellConfirmationDialog.test.d.ts +6 -0
  364. package/dist/src/ui/components/ShellConfirmationDialog.test.js +40 -0
  365. package/dist/src/ui/components/ShellConfirmationDialog.test.js.map +1 -0
  366. package/dist/src/ui/components/ShellModeIndicator.d.ts +1 -1
  367. package/dist/src/ui/components/StatsDisplay.d.ts +1 -1
  368. package/dist/src/ui/components/StatsDisplay.js +9 -8
  369. package/dist/src/ui/components/StatsDisplay.js.map +1 -1
  370. package/dist/src/ui/components/SuggestionsDisplay.js +12 -4
  371. package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
  372. package/dist/src/ui/components/ThemeDialog.d.ts +3 -2
  373. package/dist/src/ui/components/ThemeDialog.js +14 -29
  374. package/dist/src/ui/components/ThemeDialog.js.map +1 -1
  375. package/dist/src/ui/components/Tips.d.ts +1 -1
  376. package/dist/src/ui/components/Tips.js +1 -0
  377. package/dist/src/ui/components/Tips.js.map +1 -1
  378. package/dist/src/ui/components/TodoDisplay.d.ts +16 -0
  379. package/dist/src/ui/components/TodoDisplay.js +27 -0
  380. package/dist/src/ui/components/TodoDisplay.js.map +1 -0
  381. package/dist/src/ui/components/TodoDisplay.test.d.ts +6 -0
  382. package/dist/src/ui/components/TodoDisplay.test.js +77 -0
  383. package/dist/src/ui/components/TodoDisplay.test.js.map +1 -0
  384. package/dist/src/ui/components/ToolStatsDisplay.d.ts +1 -1
  385. package/dist/src/ui/components/WelcomeBackDialog.d.ts +13 -0
  386. package/dist/src/ui/components/WelcomeBackDialog.js +32 -0
  387. package/dist/src/ui/components/WelcomeBackDialog.js.map +1 -0
  388. package/dist/src/ui/components/WorkspaceMigrationDialog.d.ts +11 -0
  389. package/dist/src/ui/components/WorkspaceMigrationDialog.js +42 -0
  390. package/dist/src/ui/components/WorkspaceMigrationDialog.js.map +1 -0
  391. package/dist/src/ui/components/messages/CompressionMessage.d.ts +2 -2
  392. package/dist/src/ui/components/messages/CompressionMessage.js +2 -1
  393. package/dist/src/ui/components/messages/CompressionMessage.js.map +1 -1
  394. package/dist/src/ui/components/messages/DiffRenderer.d.ts +1 -1
  395. package/dist/src/ui/components/messages/DiffRenderer.js +16 -3
  396. package/dist/src/ui/components/messages/DiffRenderer.js.map +1 -1
  397. package/dist/src/ui/components/messages/DiffRenderer.test.d.ts +6 -0
  398. package/dist/src/ui/components/messages/DiffRenderer.test.js +239 -0
  399. package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -0
  400. package/dist/src/ui/components/messages/ErrorMessage.d.ts +1 -1
  401. package/dist/src/ui/components/messages/GeminiMessage.d.ts +1 -1
  402. package/dist/src/ui/components/messages/GeminiMessage.js +2 -1
  403. package/dist/src/ui/components/messages/GeminiMessage.js.map +1 -1
  404. package/dist/src/ui/components/messages/GeminiMessageContent.d.ts +1 -1
  405. package/dist/src/ui/components/messages/InfoMessage.d.ts +1 -1
  406. package/dist/src/ui/components/messages/InfoMessage.js +6 -1
  407. package/dist/src/ui/components/messages/InfoMessage.js.map +1 -1
  408. package/dist/src/ui/components/messages/SummaryMessage.d.ts +11 -0
  409. package/dist/src/ui/components/messages/SummaryMessage.js +35 -0
  410. package/dist/src/ui/components/messages/SummaryMessage.js.map +1 -0
  411. package/dist/src/ui/components/messages/ToolConfirmationMessage.d.ts +4 -3
  412. package/dist/src/ui/components/messages/ToolConfirmationMessage.js +111 -35
  413. package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
  414. package/dist/src/ui/components/messages/ToolConfirmationMessage.test.d.ts +6 -0
  415. package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js +137 -0
  416. package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js.map +1 -0
  417. package/dist/src/ui/components/messages/ToolGroupMessage.d.ts +4 -4
  418. package/dist/src/ui/components/messages/ToolGroupMessage.js +2 -7
  419. package/dist/src/ui/components/messages/ToolGroupMessage.js.map +1 -1
  420. package/dist/src/ui/components/messages/ToolGroupMessage.test.d.ts +6 -0
  421. package/dist/src/ui/components/messages/ToolGroupMessage.test.js +259 -0
  422. package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -0
  423. package/dist/src/ui/components/messages/ToolMessage.d.ts +3 -1
  424. package/dist/src/ui/components/messages/ToolMessage.js +88 -11
  425. package/dist/src/ui/components/messages/ToolMessage.js.map +1 -1
  426. package/dist/src/ui/components/messages/ToolMessage.test.d.ts +6 -0
  427. package/dist/src/ui/components/messages/ToolMessage.test.js +149 -0
  428. package/dist/src/ui/components/messages/ToolMessage.test.js.map +1 -0
  429. package/dist/src/ui/components/messages/UserMessage.d.ts +1 -1
  430. package/dist/src/ui/components/messages/UserMessage.js +4 -2
  431. package/dist/src/ui/components/messages/UserMessage.js.map +1 -1
  432. package/dist/src/ui/components/messages/UserShellMessage.d.ts +1 -1
  433. package/dist/src/ui/components/shared/MaxSizedBox.js +1 -1
  434. package/dist/src/ui/components/shared/MaxSizedBox.js.map +1 -1
  435. package/dist/src/ui/components/shared/MaxSizedBox.test.d.ts +6 -0
  436. package/dist/src/ui/components/shared/MaxSizedBox.test.js +154 -0
  437. package/dist/src/ui/components/shared/MaxSizedBox.test.js.map +1 -0
  438. package/dist/src/ui/components/shared/RadioButtonSelect.d.ts +1 -1
  439. package/dist/src/ui/components/shared/RadioButtonSelect.js +12 -15
  440. package/dist/src/ui/components/shared/RadioButtonSelect.js.map +1 -1
  441. package/dist/src/ui/components/shared/RadioButtonSelect.test.d.ts +6 -0
  442. package/dist/src/ui/components/shared/RadioButtonSelect.test.js +111 -0
  443. package/dist/src/ui/components/shared/RadioButtonSelect.test.js.map +1 -0
  444. package/dist/src/ui/components/shared/TextInput.d.ts +16 -0
  445. package/dist/src/ui/components/shared/TextInput.js +127 -0
  446. package/dist/src/ui/components/shared/TextInput.js.map +1 -0
  447. package/dist/src/ui/components/shared/text-buffer.d.ts +17 -4
  448. package/dist/src/ui/components/shared/text-buffer.js +235 -97
  449. package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
  450. package/dist/src/ui/components/shared/vim-buffer-actions.d.ts +1 -1
  451. package/dist/src/ui/components/shared/vim-buffer-actions.js +139 -152
  452. package/dist/src/ui/components/shared/vim-buffer-actions.js.map +1 -1
  453. package/dist/src/ui/components/subagents/constants.d.ts +23 -0
  454. package/dist/src/ui/components/subagents/constants.js +67 -0
  455. package/dist/src/ui/components/subagents/constants.js.map +1 -0
  456. package/dist/src/ui/components/subagents/create/AgentCreationWizard.d.ts +15 -0
  457. package/dist/src/ui/components/subagents/create/AgentCreationWizard.js +174 -0
  458. package/dist/src/ui/components/subagents/create/AgentCreationWizard.js.map +1 -0
  459. package/dist/src/ui/components/subagents/create/ColorSelector.d.ts +15 -0
  460. package/dist/src/ui/components/subagents/create/ColorSelector.js +42 -0
  461. package/dist/src/ui/components/subagents/create/ColorSelector.js.map +1 -0
  462. package/dist/src/ui/components/subagents/create/CreationSummary.d.ts +10 -0
  463. package/dist/src/ui/components/subagents/create/CreationSummary.js +163 -0
  464. package/dist/src/ui/components/subagents/create/CreationSummary.js.map +1 -0
  465. package/dist/src/ui/components/subagents/create/DescriptionInput.d.ts +10 -0
  466. package/dist/src/ui/components/subagents/create/DescriptionInput.js +105 -0
  467. package/dist/src/ui/components/subagents/create/DescriptionInput.js.map +1 -0
  468. package/dist/src/ui/components/subagents/create/GenerationMethodSelector.d.ts +10 -0
  469. package/dist/src/ui/components/subagents/create/GenerationMethodSelector.js +33 -0
  470. package/dist/src/ui/components/subagents/create/GenerationMethodSelector.js.map +1 -0
  471. package/dist/src/ui/components/subagents/create/LocationSelector.d.ts +10 -0
  472. package/dist/src/ui/components/subagents/create/LocationSelector.js +33 -0
  473. package/dist/src/ui/components/subagents/create/LocationSelector.js.map +1 -0
  474. package/dist/src/ui/components/subagents/create/TextEntryStep.d.ts +26 -0
  475. package/dist/src/ui/components/subagents/create/TextEntryStep.js +28 -0
  476. package/dist/src/ui/components/subagents/create/TextEntryStep.js.map +1 -0
  477. package/dist/src/ui/components/subagents/create/ToolSelector.d.ts +16 -0
  478. package/dist/src/ui/components/subagents/create/ToolSelector.js +143 -0
  479. package/dist/src/ui/components/subagents/create/ToolSelector.js.map +1 -0
  480. package/dist/src/ui/components/subagents/index.d.ts +8 -0
  481. package/dist/src/ui/components/subagents/index.js +12 -0
  482. package/dist/src/ui/components/subagents/index.js.map +1 -0
  483. package/dist/src/ui/components/subagents/manage/ActionSelectionStep.d.ts +13 -0
  484. package/dist/src/ui/components/subagents/manage/ActionSelectionStep.js +46 -0
  485. package/dist/src/ui/components/subagents/manage/ActionSelectionStep.js.map +1 -0
  486. package/dist/src/ui/components/subagents/manage/AgentDeleteStep.d.ts +13 -0
  487. package/dist/src/ui/components/subagents/manage/AgentDeleteStep.js +33 -0
  488. package/dist/src/ui/components/subagents/manage/AgentDeleteStep.js.map +1 -0
  489. package/dist/src/ui/components/subagents/manage/AgentEditStep.d.ts +15 -0
  490. package/dist/src/ui/components/subagents/manage/AgentEditStep.js +63 -0
  491. package/dist/src/ui/components/subagents/manage/AgentEditStep.js.map +1 -0
  492. package/dist/src/ui/components/subagents/manage/AgentSelectionStep.d.ts +12 -0
  493. package/dist/src/ui/components/subagents/manage/AgentSelectionStep.js +225 -0
  494. package/dist/src/ui/components/subagents/manage/AgentSelectionStep.js.map +1 -0
  495. package/dist/src/ui/components/subagents/manage/AgentViewerStep.d.ts +11 -0
  496. package/dist/src/ui/components/subagents/manage/AgentViewerStep.js +19 -0
  497. package/dist/src/ui/components/subagents/manage/AgentViewerStep.js.map +1 -0
  498. package/dist/src/ui/components/subagents/manage/AgentsManagerDialog.d.ts +15 -0
  499. package/dist/src/ui/components/subagents/manage/AgentsManagerDialog.js +212 -0
  500. package/dist/src/ui/components/subagents/manage/AgentsManagerDialog.js.map +1 -0
  501. package/dist/src/ui/components/subagents/reducers.d.ts +14 -0
  502. package/dist/src/ui/components/subagents/reducers.js +162 -0
  503. package/dist/src/ui/components/subagents/reducers.js.map +1 -0
  504. package/dist/src/ui/components/subagents/runtime/AgentExecutionDisplay.d.ts +20 -0
  505. package/dist/src/ui/components/subagents/runtime/AgentExecutionDisplay.js +194 -0
  506. package/dist/src/ui/components/subagents/runtime/AgentExecutionDisplay.js.map +1 -0
  507. package/dist/src/ui/components/subagents/types.d.ts +137 -0
  508. package/dist/src/ui/components/subagents/types.js +15 -0
  509. package/dist/src/ui/components/subagents/types.js.map +1 -0
  510. package/dist/src/ui/components/subagents/utils.d.ts +15 -0
  511. package/dist/src/ui/components/subagents/utils.js +79 -0
  512. package/dist/src/ui/components/subagents/utils.js.map +1 -0
  513. package/dist/src/ui/components/ums/UMSKeyPrompt.js +4 -4
  514. package/dist/src/ui/components/ums/UMSKeyPrompt.js.map +1 -1
  515. package/dist/src/ui/components/ums/useUMSAuth.d.ts +1 -1
  516. package/dist/src/ui/components/ums/useUMSAuth.js +1 -1
  517. package/dist/src/ui/components/ums/useUMSAuth.js.map +1 -1
  518. package/dist/src/ui/constants.d.ts +8 -0
  519. package/dist/src/ui/constants.js +9 -0
  520. package/dist/src/ui/constants.js.map +1 -1
  521. package/dist/src/ui/contexts/KeypressContext.d.ts +32 -0
  522. package/dist/src/ui/contexts/KeypressContext.js +371 -0
  523. package/dist/src/ui/contexts/KeypressContext.js.map +1 -0
  524. package/dist/src/ui/contexts/KeypressContext.test.d.ts +6 -0
  525. package/dist/src/ui/contexts/KeypressContext.test.js +894 -0
  526. package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -0
  527. package/dist/src/ui/contexts/OverflowContext.d.ts +1 -1
  528. package/dist/src/ui/contexts/OverflowContext.js +0 -5
  529. package/dist/src/ui/contexts/OverflowContext.js.map +1 -1
  530. package/dist/src/ui/contexts/SessionContext.d.ts +5 -3
  531. package/dist/src/ui/contexts/SessionContext.js +3 -16
  532. package/dist/src/ui/contexts/SessionContext.js.map +1 -1
  533. package/dist/src/ui/contexts/SettingsContext.d.ts +9 -0
  534. package/dist/src/ui/contexts/SettingsContext.js +15 -0
  535. package/dist/src/ui/contexts/SettingsContext.js.map +1 -0
  536. package/dist/src/ui/contexts/StreamingContext.d.ts +1 -1
  537. package/dist/src/ui/contexts/VimModeContext.d.ts +1 -1
  538. package/dist/src/ui/contexts/VimModeContext.js +4 -4
  539. package/dist/src/ui/contexts/VimModeContext.js.map +1 -1
  540. package/dist/src/ui/hooks/atCommandProcessor.d.ts +3 -3
  541. package/dist/src/ui/hooks/atCommandProcessor.js +20 -20
  542. package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
  543. package/dist/src/ui/hooks/atCommandProcessor.test.d.ts +6 -0
  544. package/dist/src/ui/hooks/atCommandProcessor.test.js +832 -0
  545. package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -0
  546. package/dist/src/ui/hooks/shellCommandProcessor.d.ts +3 -3
  547. package/dist/src/ui/hooks/shellCommandProcessor.js +15 -19
  548. package/dist/src/ui/hooks/shellCommandProcessor.js.map +1 -1
  549. package/dist/src/ui/hooks/shellCommandProcessor.test.d.ts +6 -0
  550. package/dist/src/ui/hooks/shellCommandProcessor.test.js +329 -0
  551. package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -0
  552. package/dist/src/ui/hooks/slashCommandProcessor.d.ts +14 -6
  553. package/dist/src/ui/hooks/slashCommandProcessor.js +243 -65
  554. package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
  555. package/dist/src/ui/hooks/useAgentsManagerDialog.d.ts +11 -0
  556. package/dist/src/ui/hooks/useAgentsManagerDialog.js +21 -0
  557. package/dist/src/ui/hooks/useAgentsManagerDialog.js.map +1 -0
  558. package/dist/src/ui/hooks/useAtCompletion.d.ts +2 -2
  559. package/dist/src/ui/hooks/useAtCompletion.js +6 -4
  560. package/dist/src/ui/hooks/useAtCompletion.js.map +1 -1
  561. package/dist/src/ui/hooks/useAuthCommand.d.ts +2 -2
  562. package/dist/src/ui/hooks/useAuthCommand.js +5 -4
  563. package/dist/src/ui/hooks/useAuthCommand.js.map +1 -1
  564. package/dist/src/ui/hooks/useAutoAcceptIndicator.d.ts +4 -2
  565. package/dist/src/ui/hooks/useAutoAcceptIndicator.js +20 -19
  566. package/dist/src/ui/hooks/useAutoAcceptIndicator.js.map +1 -1
  567. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.d.ts +6 -0
  568. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js +263 -0
  569. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +1 -0
  570. package/dist/src/ui/hooks/useCommandCompletion.d.ts +8 -5
  571. package/dist/src/ui/hooks/useCommandCompletion.js +30 -9
  572. package/dist/src/ui/hooks/useCommandCompletion.js.map +1 -1
  573. package/dist/src/ui/hooks/useCompletion.d.ts +1 -1
  574. package/dist/src/ui/hooks/useCompletion.js +1 -1
  575. package/dist/src/ui/hooks/useCompletion.js.map +1 -1
  576. package/dist/src/ui/hooks/useConsoleMessages.d.ts +1 -1
  577. package/dist/src/ui/hooks/useDialogClose.d.ts +34 -0
  578. package/dist/src/ui/hooks/useDialogClose.js +62 -0
  579. package/dist/src/ui/hooks/useDialogClose.js.map +1 -0
  580. package/dist/src/ui/hooks/useEditorSettings.d.ts +2 -2
  581. package/dist/src/ui/hooks/useEditorSettings.js.map +1 -1
  582. package/dist/src/ui/hooks/useEditorSettings.test.d.ts +6 -0
  583. package/dist/src/ui/hooks/useEditorSettings.test.js +164 -0
  584. package/dist/src/ui/hooks/useEditorSettings.test.js.map +1 -0
  585. package/dist/src/ui/hooks/useFocus.d.ts +4 -0
  586. package/dist/src/ui/hooks/useFocus.js +4 -4
  587. package/dist/src/ui/hooks/useFocus.js.map +1 -1
  588. package/dist/src/ui/hooks/useFolderTrust.d.ts +13 -0
  589. package/dist/src/ui/hooks/useFolderTrust.js +64 -0
  590. package/dist/src/ui/hooks/useFolderTrust.js.map +1 -0
  591. package/dist/src/ui/hooks/useGeminiStream.d.ts +10 -5
  592. package/dist/src/ui/hooks/useGeminiStream.js +118 -71
  593. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  594. package/dist/src/ui/hooks/useGitBranchName.js +1 -1
  595. package/dist/src/ui/hooks/useGitBranchName.js.map +1 -1
  596. package/dist/src/ui/hooks/useGitBranchName.test.d.ts +6 -0
  597. package/dist/src/ui/hooks/useGitBranchName.test.js +175 -0
  598. package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -0
  599. package/dist/src/ui/hooks/useHistoryManager.d.ts +1 -1
  600. package/dist/src/ui/hooks/useHistoryManager.test.d.ts +6 -0
  601. package/dist/src/ui/hooks/useHistoryManager.test.js +171 -0
  602. package/dist/src/ui/hooks/useHistoryManager.test.js.map +1 -0
  603. package/dist/src/ui/hooks/useInputHistory.test.d.ts +6 -0
  604. package/dist/src/ui/hooks/useInputHistory.test.js +207 -0
  605. package/dist/src/ui/hooks/useInputHistory.test.js.map +1 -0
  606. package/dist/src/ui/hooks/useKeypress.d.ts +4 -16
  607. package/dist/src/ui/hooks/useKeypress.js +8 -140
  608. package/dist/src/ui/hooks/useKeypress.js.map +1 -1
  609. package/dist/src/ui/hooks/useKittyKeyboardProtocol.d.ts +15 -0
  610. package/dist/src/ui/hooks/useKittyKeyboardProtocol.js +20 -0
  611. package/dist/src/ui/hooks/useKittyKeyboardProtocol.js.map +1 -0
  612. package/dist/src/ui/hooks/useLaunchEditor.d.ts +10 -0
  613. package/dist/src/ui/hooks/useLaunchEditor.js +70 -0
  614. package/dist/src/ui/hooks/useLaunchEditor.js.map +1 -0
  615. package/dist/src/ui/hooks/useLoadingIndicator.test.d.ts +6 -0
  616. package/dist/src/ui/hooks/useLoadingIndicator.test.js +91 -0
  617. package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -0
  618. package/dist/src/ui/hooks/useLogger.d.ts +2 -1
  619. package/dist/src/ui/hooks/useLogger.js +3 -3
  620. package/dist/src/ui/hooks/useLogger.js.map +1 -1
  621. package/dist/src/ui/hooks/useMessageQueue.d.ts +22 -0
  622. package/dist/src/ui/hooks/useMessageQueue.js +49 -0
  623. package/dist/src/ui/hooks/useMessageQueue.js.map +1 -0
  624. package/dist/src/ui/hooks/useMessageQueue.test.d.ts +6 -0
  625. package/dist/src/ui/hooks/useMessageQueue.test.js +158 -0
  626. package/dist/src/ui/hooks/useMessageQueue.test.js.map +1 -0
  627. package/dist/src/ui/hooks/usePhraseCycler.js +2 -2
  628. package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
  629. package/dist/src/ui/hooks/usePrivacySettings.d.ts +1 -1
  630. package/dist/src/ui/hooks/usePrivacySettings.js +6 -2
  631. package/dist/src/ui/hooks/usePrivacySettings.js.map +1 -1
  632. package/dist/src/ui/hooks/usePrivacySettings.test.d.ts +6 -0
  633. package/dist/src/ui/hooks/usePrivacySettings.test.js +154 -0
  634. package/dist/src/ui/hooks/usePrivacySettings.test.js.map +1 -0
  635. package/dist/src/ui/hooks/usePromptCompletion.d.ts +23 -0
  636. package/dist/src/ui/hooks/usePromptCompletion.js +177 -0
  637. package/dist/src/ui/hooks/usePromptCompletion.js.map +1 -0
  638. package/dist/src/ui/hooks/useQuitConfirmation.d.ts +14 -0
  639. package/dist/src/ui/hooks/useQuitConfirmation.js +36 -0
  640. package/dist/src/ui/hooks/useQuitConfirmation.js.map +1 -0
  641. package/dist/src/ui/hooks/useQwenAuth.d.ts +1 -1
  642. package/dist/src/ui/hooks/useQwenAuth.js +1 -1
  643. package/dist/src/ui/hooks/useQwenAuth.js.map +1 -1
  644. package/dist/src/ui/hooks/useQwenAuth.test.d.ts +6 -0
  645. package/dist/src/ui/hooks/useQwenAuth.test.js +292 -0
  646. package/dist/src/ui/hooks/useQwenAuth.test.js.map +1 -0
  647. package/dist/src/ui/hooks/useReactToolScheduler.d.ts +3 -3
  648. package/dist/src/ui/hooks/useReactToolScheduler.js +17 -18
  649. package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
  650. package/dist/src/ui/hooks/useReverseSearchCompletion.d.ts +2 -2
  651. package/dist/src/ui/hooks/useReverseSearchCompletion.test.d.ts +6 -0
  652. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js +163 -0
  653. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js.map +1 -0
  654. package/dist/src/ui/hooks/useSettingsCommand.d.ts +10 -0
  655. package/dist/src/ui/hooks/useSettingsCommand.js +21 -0
  656. package/dist/src/ui/hooks/useSettingsCommand.js.map +1 -0
  657. package/dist/src/ui/hooks/useShellHistory.d.ts +2 -1
  658. package/dist/src/ui/hooks/useShellHistory.js +9 -10
  659. package/dist/src/ui/hooks/useShellHistory.js.map +1 -1
  660. package/dist/src/ui/hooks/useShellHistory.test.d.ts +6 -0
  661. package/dist/src/ui/hooks/useShellHistory.test.js +187 -0
  662. package/dist/src/ui/hooks/useShellHistory.test.js.map +1 -0
  663. package/dist/src/ui/hooks/useShowMemoryCommand.d.ts +3 -3
  664. package/dist/src/ui/hooks/useShowMemoryCommand.js +1 -1
  665. package/dist/src/ui/hooks/useShowMemoryCommand.js.map +1 -1
  666. package/dist/src/ui/hooks/useSlashCompletion.d.ts +2 -2
  667. package/dist/src/ui/hooks/useSlashCompletion.test.d.ts +6 -0
  668. package/dist/src/ui/hooks/useSlashCompletion.test.js +272 -0
  669. package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -0
  670. package/dist/src/ui/hooks/useSubagentCreateDialog.d.ts +10 -0
  671. package/dist/src/ui/hooks/useSubagentCreateDialog.js +21 -0
  672. package/dist/src/ui/hooks/useSubagentCreateDialog.js.map +1 -0
  673. package/dist/src/ui/hooks/useThemeCommand.d.ts +1 -1
  674. package/dist/src/ui/hooks/useThemeCommand.js +9 -9
  675. package/dist/src/ui/hooks/useThemeCommand.js.map +1 -1
  676. package/dist/src/ui/hooks/useTimer.test.d.ts +6 -0
  677. package/dist/src/ui/hooks/useTimer.test.js +90 -0
  678. package/dist/src/ui/hooks/useTimer.test.js.map +1 -0
  679. package/dist/src/ui/hooks/useToolScheduler.test.d.ts +6 -0
  680. package/dist/src/ui/hooks/useToolScheduler.test.js +850 -0
  681. package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -0
  682. package/dist/src/ui/hooks/useVisionAutoSwitch.d.ts +47 -0
  683. package/dist/src/ui/hooks/useVisionAutoSwitch.js +262 -0
  684. package/dist/src/ui/hooks/useVisionAutoSwitch.js.map +1 -0
  685. package/dist/src/ui/hooks/useVisionAutoSwitch.test.d.ts +6 -0
  686. package/dist/src/ui/hooks/useVisionAutoSwitch.test.js +515 -0
  687. package/dist/src/ui/hooks/useVisionAutoSwitch.test.js.map +1 -0
  688. package/dist/src/ui/hooks/useWelcomeBack.d.ts +23 -0
  689. package/dist/src/ui/hooks/useWelcomeBack.js +79 -0
  690. package/dist/src/ui/hooks/useWelcomeBack.js.map +1 -0
  691. package/dist/src/ui/hooks/useWorkspaceMigration.d.ts +13 -0
  692. package/dist/src/ui/hooks/useWorkspaceMigration.js +53 -0
  693. package/dist/src/ui/hooks/useWorkspaceMigration.js.map +1 -0
  694. package/dist/src/ui/keyMatchers.d.ts +27 -0
  695. package/dist/src/ui/keyMatchers.js +68 -0
  696. package/dist/src/ui/keyMatchers.js.map +1 -0
  697. package/dist/src/ui/keyMatchers.test.d.ts +6 -0
  698. package/dist/src/ui/keyMatchers.test.js +276 -0
  699. package/dist/src/ui/keyMatchers.test.js.map +1 -0
  700. package/dist/src/ui/models/availableModels.d.ts +29 -0
  701. package/dist/src/ui/models/availableModels.js +40 -0
  702. package/dist/src/ui/models/availableModels.js.map +1 -0
  703. package/dist/src/ui/privacy/CloudFreePrivacyNotice.d.ts +1 -1
  704. package/dist/src/ui/privacy/CloudFreePrivacyNotice.js +5 -4
  705. package/dist/src/ui/privacy/CloudFreePrivacyNotice.js.map +1 -1
  706. package/dist/src/ui/privacy/CloudPaidPrivacyNotice.js +5 -4
  707. package/dist/src/ui/privacy/CloudPaidPrivacyNotice.js.map +1 -1
  708. package/dist/src/ui/privacy/GeminiPrivacyNotice.js +5 -4
  709. package/dist/src/ui/privacy/GeminiPrivacyNotice.js.map +1 -1
  710. package/dist/src/ui/semantic-colors.d.ts +7 -0
  711. package/dist/src/ui/semantic-colors.js +24 -0
  712. package/dist/src/ui/semantic-colors.js.map +1 -0
  713. package/dist/src/ui/textConstants.d.ts +9 -0
  714. package/dist/src/ui/textConstants.js +10 -0
  715. package/dist/src/ui/textConstants.js.map +1 -0
  716. package/dist/src/ui/themes/ansi-light.js +2 -1
  717. package/dist/src/ui/themes/ansi-light.js.map +1 -1
  718. package/dist/src/ui/themes/ansi.js +2 -1
  719. package/dist/src/ui/themes/ansi.js.map +1 -1
  720. package/dist/src/ui/themes/color-utils.test.d.ts +6 -0
  721. package/dist/src/ui/themes/color-utils.test.js +197 -0
  722. package/dist/src/ui/themes/color-utils.test.js.map +1 -0
  723. package/dist/src/ui/themes/googlecode.js +1 -1
  724. package/dist/src/ui/themes/googlecode.js.map +1 -1
  725. package/dist/src/ui/themes/no-color.js +30 -1
  726. package/dist/src/ui/themes/no-color.js.map +1 -1
  727. package/dist/src/ui/themes/qwen-dark.js +2 -1
  728. package/dist/src/ui/themes/qwen-dark.js.map +1 -1
  729. package/dist/src/ui/themes/qwen-light.js +2 -1
  730. package/dist/src/ui/themes/qwen-light.js.map +1 -1
  731. package/dist/src/ui/themes/semantic-tokens.d.ts +37 -0
  732. package/dist/src/ui/themes/semantic-tokens.js +94 -0
  733. package/dist/src/ui/themes/semantic-tokens.js.map +1 -0
  734. package/dist/src/ui/themes/theme-manager.d.ts +9 -1
  735. package/dist/src/ui/themes/theme-manager.js +81 -7
  736. package/dist/src/ui/themes/theme-manager.js.map +1 -1
  737. package/dist/src/ui/themes/theme-manager.test.d.ts +6 -0
  738. package/dist/src/ui/themes/theme-manager.test.js +142 -0
  739. package/dist/src/ui/themes/theme-manager.test.js.map +1 -0
  740. package/dist/src/ui/themes/theme.d.ts +45 -2
  741. package/dist/src/ui/themes/theme.js +120 -107
  742. package/dist/src/ui/themes/theme.js.map +1 -1
  743. package/dist/src/ui/types.d.ts +34 -6
  744. package/dist/src/ui/types.js +2 -0
  745. package/dist/src/ui/types.js.map +1 -1
  746. package/dist/src/ui/utils/CodeColorizer.d.ts +3 -2
  747. package/dist/src/ui/utils/CodeColorizer.js +5 -4
  748. package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
  749. package/dist/src/ui/utils/ConsolePatcher.d.ts +2 -1
  750. package/dist/src/ui/utils/ConsolePatcher.js +4 -1
  751. package/dist/src/ui/utils/ConsolePatcher.js.map +1 -1
  752. package/dist/src/ui/utils/InlineMarkdownRenderer.js +8 -1
  753. package/dist/src/ui/utils/InlineMarkdownRenderer.js.map +1 -1
  754. package/dist/src/ui/utils/MarkdownDisplay.js +5 -3
  755. package/dist/src/ui/utils/MarkdownDisplay.js.map +1 -1
  756. package/dist/src/ui/utils/MarkdownDisplay.test.d.ts +6 -0
  757. package/dist/src/ui/utils/MarkdownDisplay.test.js +161 -0
  758. package/dist/src/ui/utils/MarkdownDisplay.test.js.map +1 -0
  759. package/dist/src/ui/utils/clipboardUtils.js +4 -4
  760. package/dist/src/ui/utils/clipboardUtils.js.map +1 -1
  761. package/dist/src/ui/utils/clipboardUtils.test.d.ts +6 -0
  762. package/dist/src/ui/utils/clipboardUtils.test.js +65 -0
  763. package/dist/src/ui/utils/clipboardUtils.test.js.map +1 -0
  764. package/dist/src/ui/utils/commandUtils.d.ts +2 -1
  765. package/dist/src/ui/utils/commandUtils.js +74 -15
  766. package/dist/src/ui/utils/commandUtils.js.map +1 -1
  767. package/dist/src/ui/utils/commandUtils.test.d.ts +6 -0
  768. package/dist/src/ui/utils/commandUtils.test.js +349 -0
  769. package/dist/src/ui/utils/commandUtils.test.js.map +1 -0
  770. package/dist/src/ui/utils/computeStats.d.ts +1 -1
  771. package/dist/src/ui/utils/computeStats.js +3 -1
  772. package/dist/src/ui/utils/computeStats.js.map +1 -1
  773. package/dist/src/ui/utils/displayUtils.test.d.ts +6 -0
  774. package/dist/src/ui/utils/displayUtils.test.js +42 -0
  775. package/dist/src/ui/utils/displayUtils.test.js.map +1 -0
  776. package/dist/src/ui/utils/formatters.test.d.ts +6 -0
  777. package/dist/src/ui/utils/formatters.test.js +56 -0
  778. package/dist/src/ui/utils/formatters.test.js.map +1 -0
  779. package/dist/src/ui/utils/isNarrowWidth.d.ts +6 -0
  780. package/dist/src/ui/utils/isNarrowWidth.js +9 -0
  781. package/dist/src/ui/utils/isNarrowWidth.js.map +1 -0
  782. package/dist/src/ui/utils/kittyProtocolDetector.d.ts +13 -0
  783. package/dist/src/ui/utils/kittyProtocolDetector.js +88 -0
  784. package/dist/src/ui/utils/kittyProtocolDetector.js.map +1 -0
  785. package/dist/src/ui/utils/markdownUtilities.test.d.ts +6 -0
  786. package/dist/src/ui/utils/markdownUtilities.test.js +42 -0
  787. package/dist/src/ui/utils/markdownUtilities.test.js.map +1 -0
  788. package/dist/src/ui/utils/platformConstants.d.ts +52 -0
  789. package/dist/src/ui/utils/platformConstants.js +53 -0
  790. package/dist/src/ui/utils/platformConstants.js.map +1 -0
  791. package/dist/src/ui/utils/terminalSetup.d.ts +30 -0
  792. package/dist/src/ui/utils/terminalSetup.js +281 -0
  793. package/dist/src/ui/utils/terminalSetup.js.map +1 -0
  794. package/dist/src/ui/utils/textUtils.d.ts +18 -0
  795. package/dist/src/ui/utils/textUtils.js +44 -0
  796. package/dist/src/ui/utils/textUtils.js.map +1 -1
  797. package/dist/src/ui/utils/updateCheck.d.ts +2 -2
  798. package/dist/src/ui/utils/updateCheck.js +2 -2
  799. package/dist/src/ui/utils/updateCheck.js.map +1 -1
  800. package/dist/src/ui/utils/updateCheck.test.d.ts +6 -0
  801. package/dist/src/ui/utils/updateCheck.test.js +145 -0
  802. package/dist/src/ui/utils/updateCheck.test.js.map +1 -0
  803. package/dist/src/utils/checks.d.ts +19 -0
  804. package/dist/src/utils/checks.js +24 -0
  805. package/dist/src/utils/checks.js.map +1 -0
  806. package/dist/src/utils/cleanup.d.ts +2 -2
  807. package/dist/src/utils/cleanup.js +7 -6
  808. package/dist/src/utils/cleanup.js.map +1 -1
  809. package/dist/src/utils/dialogScopeUtils.d.ts +32 -0
  810. package/dist/src/utils/dialogScopeUtils.js +48 -0
  811. package/dist/src/utils/dialogScopeUtils.js.map +1 -0
  812. package/dist/src/utils/errors.d.ts +6 -0
  813. package/dist/src/utils/errors.js +12 -0
  814. package/dist/src/utils/errors.js.map +1 -0
  815. package/dist/src/utils/events.d.ts +1 -1
  816. package/dist/src/utils/events.js +1 -1
  817. package/dist/src/utils/events.js.map +1 -1
  818. package/dist/src/utils/gitUtils.d.ts +21 -1
  819. package/dist/src/utils/gitUtils.js +69 -4
  820. package/dist/src/utils/gitUtils.js.map +1 -1
  821. package/dist/src/utils/gitUtils.test.d.ts +6 -0
  822. package/dist/src/utils/gitUtils.test.js +113 -0
  823. package/dist/src/utils/gitUtils.test.js.map +1 -0
  824. package/dist/src/utils/handleAutoUpdate.d.ts +4 -4
  825. package/dist/src/utils/handleAutoUpdate.js +4 -3
  826. package/dist/src/utils/handleAutoUpdate.js.map +1 -1
  827. package/dist/src/utils/installationInfo.js +3 -3
  828. package/dist/src/utils/installationInfo.js.map +1 -1
  829. package/dist/src/utils/installationInfo.test.d.ts +6 -0
  830. package/dist/src/utils/installationInfo.test.js +242 -0
  831. package/dist/src/utils/installationInfo.test.js.map +1 -0
  832. package/dist/src/utils/package.js +2 -2
  833. package/dist/src/utils/package.js.map +1 -1
  834. package/dist/src/utils/readStdin.js +25 -0
  835. package/dist/src/utils/readStdin.js.map +1 -1
  836. package/dist/src/utils/readStdin.test.d.ts +6 -0
  837. package/dist/src/utils/readStdin.test.js +88 -0
  838. package/dist/src/utils/readStdin.test.js.map +1 -0
  839. package/dist/src/utils/resolvePath.js +2 -2
  840. package/dist/src/utils/resolvePath.js.map +1 -1
  841. package/dist/src/utils/sandbox.d.ts +2 -2
  842. package/dist/src/utils/sandbox.js +460 -444
  843. package/dist/src/utils/sandbox.js.map +1 -1
  844. package/dist/src/utils/settingsUtils.d.ts +134 -0
  845. package/dist/src/utils/settingsUtils.js +330 -0
  846. package/dist/src/utils/settingsUtils.js.map +1 -0
  847. package/dist/src/utils/settingsUtils.test.d.ts +6 -0
  848. package/dist/src/utils/settingsUtils.test.js +511 -0
  849. package/dist/src/utils/settingsUtils.test.js.map +1 -0
  850. package/dist/src/utils/spawnWrapper.d.ts +1 -1
  851. package/dist/src/utils/spawnWrapper.js +1 -1
  852. package/dist/src/utils/spawnWrapper.js.map +1 -1
  853. package/dist/src/utils/startupWarnings.js +2 -2
  854. package/dist/src/utils/startupWarnings.js.map +1 -1
  855. package/dist/src/utils/updateEventEmitter.d.ts +1 -1
  856. package/dist/src/utils/updateEventEmitter.js +1 -1
  857. package/dist/src/utils/updateEventEmitter.js.map +1 -1
  858. package/dist/src/utils/userStartupWarnings.js +3 -3
  859. package/dist/src/utils/userStartupWarnings.js.map +1 -1
  860. package/dist/src/utils/userStartupWarnings.test.d.ts +6 -0
  861. package/dist/src/utils/userStartupWarnings.test.js +67 -0
  862. package/dist/src/utils/userStartupWarnings.test.js.map +1 -0
  863. package/dist/src/utils/version.js +1 -1
  864. package/dist/src/utils/version.js.map +1 -1
  865. package/dist/src/validateNonInterActiveAuth.d.ts +1 -1
  866. package/dist/src/validateNonInterActiveAuth.js +4 -7
  867. package/dist/src/validateNonInterActiveAuth.js.map +1 -1
  868. package/dist/src/zed-integration/acp.d.ts +63 -0
  869. package/dist/src/{acp → zed-integration}/acp.js +78 -45
  870. package/dist/src/zed-integration/acp.js.map +1 -0
  871. package/dist/src/zed-integration/fileSystemService.d.ts +19 -0
  872. package/dist/src/zed-integration/fileSystemService.js +43 -0
  873. package/dist/src/zed-integration/fileSystemService.js.map +1 -0
  874. package/dist/src/zed-integration/schema.d.ts +11782 -0
  875. package/dist/src/zed-integration/schema.js +311 -0
  876. package/dist/src/zed-integration/schema.js.map +1 -0
  877. package/dist/src/zed-integration/zedIntegration.d.ts +10 -0
  878. package/dist/src/zed-integration/zedIntegration.js +787 -0
  879. package/dist/src/zed-integration/zedIntegration.js.map +1 -0
  880. package/dist/tsconfig.tsbuildinfo +1 -1
  881. package/package.json +10 -7
  882. package/dist/src/acp/acp.d.ts +0 -208
  883. package/dist/src/acp/acp.js.map +0 -1
  884. package/dist/src/acp/acpPeer.d.ts +0 -8
  885. package/dist/src/acp/acpPeer.js +0 -537
  886. package/dist/src/acp/acpPeer.js.map +0 -1
  887. package/dist/src/ui/components/IDEContextDetailDisplay.d.ts +0 -12
  888. package/dist/src/ui/components/IDEContextDetailDisplay.js +0 -12
  889. package/dist/src/ui/components/IDEContextDetailDisplay.js.map +0 -1
  890. package/dist/src/ui/utils/errorParsing.d.ts +0 -7
  891. package/dist/src/ui/utils/errorParsing.js +0 -90
  892. package/dist/src/ui/utils/errorParsing.js.map +0 -1
@@ -8,9 +8,12 @@ import os from 'node:os';
8
8
  import path from 'node:path';
9
9
  import fs from 'node:fs';
10
10
  import { readFile } from 'node:fs/promises';
11
+ import { fileURLToPath } from 'node:url';
11
12
  import { quote, parse } from 'shell-quote';
12
13
  import { USER_SETTINGS_DIR, SETTINGS_DIRECTORY_NAME, } from '../config/settings.js';
13
- import { promisify } from 'util';
14
+ import { promisify } from 'node:util';
15
+ import { FatalSandboxError } from '@umsai/ums-code-core';
16
+ import { ConsolePatcher } from '../ui/utils/ConsolePatcher.js';
14
17
  const execAsync = promisify(exec);
15
18
  function getContainerPath(hostPath) {
16
19
  if (os.platform() !== 'win32') {
@@ -53,7 +56,7 @@ const BUILTIN_SEATBELT_PROFILES = [
53
56
  * @returns {Promise<boolean>} A promise that resolves to true if the current user's UID/GID should be used, false otherwise.
54
57
  */
55
58
  async function shouldUseCurrentUserInSandbox() {
56
- const envVar = process.env.SANDBOX_SET_UID_GID?.toLowerCase().trim();
59
+ const envVar = process.env['SANDBOX_SET_UID_GID']?.toLowerCase().trim();
57
60
  if (envVar === '1' || envVar === 'true') {
58
61
  return true;
59
62
  }
@@ -90,19 +93,19 @@ function parseImageName(image) {
90
93
  return tag ? `${name}-${tag}` : name;
91
94
  }
92
95
  function ports() {
93
- return (process.env.SANDBOX_PORTS ?? '')
96
+ return (process.env['SANDBOX_PORTS'] ?? '')
94
97
  .split(',')
95
98
  .filter((p) => p.trim())
96
99
  .map((p) => p.trim());
97
100
  }
98
- function entrypoint(workdir) {
101
+ function entrypoint(workdir, cliArgs) {
99
102
  const isWindows = os.platform() === 'win32';
100
103
  const containerWorkdir = getContainerPath(workdir);
101
104
  const shellCmds = [];
102
105
  const pathSeparator = isWindows ? ';' : ':';
103
106
  let pathSuffix = '';
104
- if (process.env.PATH) {
105
- const paths = process.env.PATH.split(pathSeparator);
107
+ if (process.env['PATH']) {
108
+ const paths = process.env['PATH'].split(pathSeparator);
106
109
  for (const p of paths) {
107
110
  const containerPath = getContainerPath(p);
108
111
  if (containerPath.toLowerCase().startsWith(containerWorkdir.toLowerCase())) {
@@ -114,8 +117,8 @@ function entrypoint(workdir) {
114
117
  shellCmds.push(`export PATH="$PATH${pathSuffix}";`);
115
118
  }
116
119
  let pythonPathSuffix = '';
117
- if (process.env.PYTHONPATH) {
118
- const paths = process.env.PYTHONPATH.split(pathSeparator);
120
+ if (process.env['PYTHONPATH']) {
121
+ const paths = process.env['PYTHONPATH'].split(pathSeparator);
119
122
  for (const p of paths) {
120
123
  const containerPath = getContainerPath(p);
121
124
  if (containerPath.toLowerCase().startsWith(containerWorkdir.toLowerCase())) {
@@ -131,111 +134,458 @@ function entrypoint(workdir) {
131
134
  shellCmds.push(`source ${getContainerPath(projectSandboxBashrc)};`);
132
135
  }
133
136
  ports().forEach((p) => shellCmds.push(`socat TCP4-LISTEN:${p},bind=$(hostname -i),fork,reuseaddr TCP4:127.0.0.1:${p} 2> /dev/null &`));
134
- const cliArgs = process.argv.slice(2).map((arg) => quote([arg]));
135
- const cliCmd = process.env.NODE_ENV === 'development'
136
- ? process.env.DEBUG
137
+ const quotedCliArgs = cliArgs.slice(2).map((arg) => quote([arg]));
138
+ const cliCmd = process.env['NODE_ENV'] === 'development'
139
+ ? process.env['DEBUG']
137
140
  ? 'npm run debug --'
138
141
  : 'npm rebuild && npm run start --'
139
- : process.env.DEBUG
140
- ? `node --inspect-brk=0.0.0.0:${process.env.DEBUG_PORT || '9229'} $(which qwen)`
142
+ : process.env['DEBUG']
143
+ ? `node --inspect-brk=0.0.0.0:${process.env['DEBUG_PORT'] || '9229'} $(which qwen)`
141
144
  : 'qwen';
142
- const args = [...shellCmds, cliCmd, ...cliArgs];
145
+ const args = [...shellCmds, cliCmd, ...quotedCliArgs];
143
146
  return ['bash', '-c', args.join(' ')];
144
147
  }
145
- export async function start_sandbox(config, nodeArgs = [], cliConfig) {
146
- if (config.command === 'sandbox-exec') {
147
- // disallow BUILD_SANDBOX
148
- if (process.env.BUILD_SANDBOX) {
149
- console.error('ERROR: cannot BUILD_SANDBOX when using macOS Seatbelt');
150
- process.exit(1);
151
- }
152
- const profile = (process.env.SEATBELT_PROFILE ??= 'permissive-open');
153
- let profileFile = new URL(`sandbox-macos-${profile}.sb`, import.meta.url)
154
- .pathname;
155
- // if profile name is not recognized, then look for file under project settings directory
156
- if (!BUILTIN_SEATBELT_PROFILES.includes(profile)) {
157
- profileFile = path.join(SETTINGS_DIRECTORY_NAME, `sandbox-macos-${profile}.sb`);
158
- }
159
- if (!fs.existsSync(profileFile)) {
160
- console.error(`ERROR: missing macos seatbelt profile file '${profileFile}'`);
161
- process.exit(1);
162
- }
163
- // Log on STDERR so it doesn't clutter the output on STDOUT
164
- console.error(`using macos seatbelt (profile: ${profile}) ...`);
165
- // if DEBUG is set, convert to --inspect-brk in NODE_OPTIONS
166
- const nodeOptions = [
167
- ...(process.env.DEBUG ? ['--inspect-brk'] : []),
168
- ...nodeArgs,
169
- ].join(' ');
170
- const args = [
171
- '-D',
172
- `TARGET_DIR=${fs.realpathSync(process.cwd())}`,
173
- '-D',
174
- `TMP_DIR=${fs.realpathSync(os.tmpdir())}`,
175
- '-D',
176
- `HOME_DIR=${fs.realpathSync(os.homedir())}`,
177
- '-D',
178
- `CACHE_DIR=${fs.realpathSync(execSync(`getconf DARWIN_USER_CACHE_DIR`).toString().trim())}`,
179
- ];
180
- // Add included directories from the workspace context
181
- // Always add 5 INCLUDE_DIR parameters to ensure .sb files can reference them
182
- const MAX_INCLUDE_DIRS = 5;
183
- const targetDir = fs.realpathSync(cliConfig?.getTargetDir() || '');
184
- const includedDirs = [];
185
- if (cliConfig) {
186
- const workspaceContext = cliConfig.getWorkspaceContext();
187
- const directories = workspaceContext.getDirectories();
188
- // Filter out TARGET_DIR
189
- for (const dir of directories) {
190
- const realDir = fs.realpathSync(dir);
191
- if (realDir !== targetDir) {
192
- includedDirs.push(realDir);
148
+ export async function start_sandbox(config, nodeArgs = [], cliConfig, cliArgs = []) {
149
+ const patcher = new ConsolePatcher({
150
+ debugMode: cliConfig?.getDebugMode() || !!process.env['DEBUG'],
151
+ stderr: true,
152
+ });
153
+ patcher.patch();
154
+ try {
155
+ if (config.command === 'sandbox-exec') {
156
+ // disallow BUILD_SANDBOX
157
+ if (process.env['BUILD_SANDBOX']) {
158
+ throw new FatalSandboxError('Cannot BUILD_SANDBOX when using macOS Seatbelt');
159
+ }
160
+ const profile = (process.env['SEATBELT_PROFILE'] ??= 'permissive-open');
161
+ let profileFile = fileURLToPath(new URL(`sandbox-macos-${profile}.sb`, import.meta.url));
162
+ // if profile name is not recognized, then look for file under project settings directory
163
+ if (!BUILTIN_SEATBELT_PROFILES.includes(profile)) {
164
+ profileFile = path.join(SETTINGS_DIRECTORY_NAME, `sandbox-macos-${profile}.sb`);
165
+ }
166
+ if (!fs.existsSync(profileFile)) {
167
+ throw new FatalSandboxError(`Missing macos seatbelt profile file '${profileFile}'`);
168
+ }
169
+ // Log on STDERR so it doesn't clutter the output on STDOUT
170
+ console.error(`using macos seatbelt (profile: ${profile}) ...`);
171
+ // if DEBUG is set, convert to --inspect-brk in NODE_OPTIONS
172
+ const nodeOptions = [
173
+ ...(process.env['DEBUG'] ? ['--inspect-brk'] : []),
174
+ ...nodeArgs,
175
+ ].join(' ');
176
+ const args = [
177
+ '-D',
178
+ `TARGET_DIR=${fs.realpathSync(process.cwd())}`,
179
+ '-D',
180
+ `TMP_DIR=${fs.realpathSync(os.tmpdir())}`,
181
+ '-D',
182
+ `HOME_DIR=${fs.realpathSync(os.homedir())}`,
183
+ '-D',
184
+ `CACHE_DIR=${fs.realpathSync(execSync(`getconf DARWIN_USER_CACHE_DIR`).toString().trim())}`,
185
+ ];
186
+ // Add included directories from the workspace context
187
+ // Always add 5 INCLUDE_DIR parameters to ensure .sb files can reference them
188
+ const MAX_INCLUDE_DIRS = 5;
189
+ const targetDir = fs.realpathSync(cliConfig?.getTargetDir() || '');
190
+ const includedDirs = [];
191
+ if (cliConfig) {
192
+ const workspaceContext = cliConfig.getWorkspaceContext();
193
+ const directories = workspaceContext.getDirectories();
194
+ // Filter out TARGET_DIR
195
+ for (const dir of directories) {
196
+ const realDir = fs.realpathSync(dir);
197
+ if (realDir !== targetDir) {
198
+ includedDirs.push(realDir);
199
+ }
200
+ }
201
+ }
202
+ for (let i = 0; i < MAX_INCLUDE_DIRS; i++) {
203
+ let dirPath = '/dev/null'; // Default to a safe path that won't cause issues
204
+ if (i < includedDirs.length) {
205
+ dirPath = includedDirs[i];
193
206
  }
207
+ args.push('-D', `INCLUDE_DIR_${i}=${dirPath}`);
194
208
  }
209
+ const finalArgv = cliArgs;
210
+ args.push('-f', profileFile, 'sh', '-c', [
211
+ `SANDBOX=sandbox-exec`,
212
+ `NODE_OPTIONS="${nodeOptions}"`,
213
+ ...finalArgv.map((arg) => quote([arg])),
214
+ ].join(' '));
215
+ // start and set up proxy if GEMINI_SANDBOX_PROXY_COMMAND is set
216
+ const proxyCommand = process.env['GEMINI_SANDBOX_PROXY_COMMAND'];
217
+ let proxyProcess = undefined;
218
+ let sandboxProcess = undefined;
219
+ const sandboxEnv = { ...process.env };
220
+ if (proxyCommand) {
221
+ const proxy = process.env['HTTPS_PROXY'] ||
222
+ process.env['https_proxy'] ||
223
+ process.env['HTTP_PROXY'] ||
224
+ process.env['http_proxy'] ||
225
+ 'http://localhost:8877';
226
+ sandboxEnv['HTTPS_PROXY'] = proxy;
227
+ sandboxEnv['https_proxy'] = proxy; // lower-case can be required, e.g. for curl
228
+ sandboxEnv['HTTP_PROXY'] = proxy;
229
+ sandboxEnv['http_proxy'] = proxy;
230
+ const noProxy = process.env['NO_PROXY'] || process.env['no_proxy'];
231
+ if (noProxy) {
232
+ sandboxEnv['NO_PROXY'] = noProxy;
233
+ sandboxEnv['no_proxy'] = noProxy;
234
+ }
235
+ proxyProcess = spawn(proxyCommand, {
236
+ stdio: ['ignore', 'pipe', 'pipe'],
237
+ shell: true,
238
+ detached: true,
239
+ });
240
+ // install handlers to stop proxy on exit/signal
241
+ const stopProxy = () => {
242
+ console.log('stopping proxy ...');
243
+ if (proxyProcess?.pid) {
244
+ process.kill(-proxyProcess.pid, 'SIGTERM');
245
+ }
246
+ };
247
+ process.on('exit', stopProxy);
248
+ process.on('SIGINT', stopProxy);
249
+ process.on('SIGTERM', stopProxy);
250
+ // commented out as it disrupts ink rendering
251
+ // proxyProcess.stdout?.on('data', (data) => {
252
+ // console.info(data.toString());
253
+ // });
254
+ proxyProcess.stderr?.on('data', (data) => {
255
+ console.error(data.toString());
256
+ });
257
+ proxyProcess.on('close', (code, signal) => {
258
+ if (sandboxProcess?.pid) {
259
+ process.kill(-sandboxProcess.pid, 'SIGTERM');
260
+ }
261
+ throw new FatalSandboxError(`Proxy command '${proxyCommand}' exited with code ${code}, signal ${signal}`);
262
+ });
263
+ console.log('waiting for proxy to start ...');
264
+ await execAsync(`until timeout 0.25 curl -s http://localhost:8877; do sleep 0.25; done`);
265
+ }
266
+ // spawn child and let it inherit stdio
267
+ sandboxProcess = spawn(config.command, args, {
268
+ stdio: 'inherit',
269
+ });
270
+ await new Promise((resolve) => sandboxProcess?.on('close', resolve));
271
+ return;
195
272
  }
196
- for (let i = 0; i < MAX_INCLUDE_DIRS; i++) {
197
- let dirPath = '/dev/null'; // Default to a safe path that won't cause issues
198
- if (i < includedDirs.length) {
199
- dirPath = includedDirs[i];
273
+ console.error(`hopping into sandbox (command: ${config.command}) ...`);
274
+ // determine full path for gemini-cli to distinguish linked vs installed setting
275
+ const gcPath = fs.realpathSync(process.argv[1]);
276
+ const projectSandboxDockerfile = path.join(SETTINGS_DIRECTORY_NAME, 'sandbox.Dockerfile');
277
+ const isCustomProjectSandbox = fs.existsSync(projectSandboxDockerfile);
278
+ const image = config.image;
279
+ const workdir = path.resolve(process.cwd());
280
+ const containerWorkdir = getContainerPath(workdir);
281
+ // if BUILD_SANDBOX is set, then call scripts/build_sandbox.js under gemini-cli repo
282
+ //
283
+ // note this can only be done with binary linked from gemini-cli repo
284
+ if (process.env['BUILD_SANDBOX']) {
285
+ if (!gcPath.includes('gemini-cli/packages/')) {
286
+ throw new FatalSandboxError('Cannot build sandbox using installed gemini binary; ' +
287
+ 'run `npm link ./packages/cli` under gemini-cli repo to switch to linked binary.');
288
+ }
289
+ else {
290
+ console.error('building sandbox ...');
291
+ const gcRoot = gcPath.split('/packages/')[0];
292
+ // if project folder has sandbox.Dockerfile under project settings folder, use that
293
+ let buildArgs = '';
294
+ const projectSandboxDockerfile = path.join(SETTINGS_DIRECTORY_NAME, 'sandbox.Dockerfile');
295
+ if (isCustomProjectSandbox) {
296
+ console.error(`using ${projectSandboxDockerfile} for sandbox`);
297
+ buildArgs += `-f ${path.resolve(projectSandboxDockerfile)} -i ${image}`;
298
+ }
299
+ execSync(`cd ${gcRoot} && node scripts/build_sandbox.js -s ${buildArgs}`, {
300
+ stdio: 'inherit',
301
+ env: {
302
+ ...process.env,
303
+ GEMINI_SANDBOX: config.command, // in case sandbox is enabled via flags (see config.ts under cli package)
304
+ },
305
+ });
200
306
  }
201
- args.push('-D', `INCLUDE_DIR_${i}=${dirPath}`);
202
307
  }
203
- args.push('-f', profileFile, 'sh', '-c', [
204
- `SANDBOX=sandbox-exec`,
205
- `NODE_OPTIONS="${nodeOptions}"`,
206
- ...process.argv.map((arg) => quote([arg])),
207
- ].join(' '));
208
- // start and set up proxy if GEMINI_SANDBOX_PROXY_COMMAND is set
209
- const proxyCommand = process.env.GEMINI_SANDBOX_PROXY_COMMAND;
210
- let proxyProcess = undefined;
211
- let sandboxProcess = undefined;
212
- const sandboxEnv = { ...process.env };
308
+ // stop if image is missing
309
+ if (!(await ensureSandboxImageIsPresent(config.command, image))) {
310
+ const remedy = image === LOCAL_DEV_SANDBOX_IMAGE_NAME
311
+ ? 'Try running `npm run build:all` or `npm run build:sandbox` under the gemini-cli repo to build it locally, or check the image name and your network connection.'
312
+ : 'Please check the image name, your network connection, or notify gemini-cli-dev@google.com if the issue persists.';
313
+ throw new FatalSandboxError(`Sandbox image '${image}' is missing or could not be pulled. ${remedy}`);
314
+ }
315
+ // use interactive mode and auto-remove container on exit
316
+ // run init binary inside container to forward signals & reap zombies
317
+ const args = ['run', '-i', '--rm', '--init', '--workdir', containerWorkdir];
318
+ // add custom flags from SANDBOX_FLAGS
319
+ if (process.env['SANDBOX_FLAGS']) {
320
+ const flags = parse(process.env['SANDBOX_FLAGS'], process.env).filter((f) => typeof f === 'string');
321
+ args.push(...flags);
322
+ }
323
+ // add TTY only if stdin is TTY as well, i.e. for piped input don't init TTY in container
324
+ if (process.stdin.isTTY) {
325
+ args.push('-t');
326
+ }
327
+ // mount current directory as working directory in sandbox (set via --workdir)
328
+ args.push('--volume', `${workdir}:${containerWorkdir}`);
329
+ // mount user settings directory inside container, after creating if missing
330
+ // note user/home changes inside sandbox and we mount at BOTH paths for consistency
331
+ const userSettingsDirOnHost = USER_SETTINGS_DIR;
332
+ const userSettingsDirInSandbox = getContainerPath(`/home/node/${SETTINGS_DIRECTORY_NAME}`);
333
+ if (!fs.existsSync(userSettingsDirOnHost)) {
334
+ fs.mkdirSync(userSettingsDirOnHost);
335
+ }
336
+ args.push('--volume', `${userSettingsDirOnHost}:${userSettingsDirInSandbox}`);
337
+ if (userSettingsDirInSandbox !== userSettingsDirOnHost) {
338
+ args.push('--volume', `${userSettingsDirOnHost}:${getContainerPath(userSettingsDirOnHost)}`);
339
+ }
340
+ // mount os.tmpdir() as os.tmpdir() inside container
341
+ args.push('--volume', `${os.tmpdir()}:${getContainerPath(os.tmpdir())}`);
342
+ // mount gcloud config directory if it exists
343
+ const gcloudConfigDir = path.join(os.homedir(), '.config', 'gcloud');
344
+ if (fs.existsSync(gcloudConfigDir)) {
345
+ args.push('--volume', `${gcloudConfigDir}:${getContainerPath(gcloudConfigDir)}:ro`);
346
+ }
347
+ // mount ADC file if GOOGLE_APPLICATION_CREDENTIALS is set
348
+ if (process.env['GOOGLE_APPLICATION_CREDENTIALS']) {
349
+ const adcFile = process.env['GOOGLE_APPLICATION_CREDENTIALS'];
350
+ if (fs.existsSync(adcFile)) {
351
+ args.push('--volume', `${adcFile}:${getContainerPath(adcFile)}:ro`);
352
+ args.push('--env', `GOOGLE_APPLICATION_CREDENTIALS=${getContainerPath(adcFile)}`);
353
+ }
354
+ }
355
+ // mount paths listed in SANDBOX_MOUNTS
356
+ if (process.env['SANDBOX_MOUNTS']) {
357
+ for (let mount of process.env['SANDBOX_MOUNTS'].split(',')) {
358
+ if (mount.trim()) {
359
+ // parse mount as from:to:opts
360
+ let [from, to, opts] = mount.trim().split(':');
361
+ to = to || from; // default to mount at same path inside container
362
+ opts = opts || 'ro'; // default to read-only
363
+ mount = `${from}:${to}:${opts}`;
364
+ // check that from path is absolute
365
+ if (!path.isAbsolute(from)) {
366
+ throw new FatalSandboxError(`Path '${from}' listed in SANDBOX_MOUNTS must be absolute`);
367
+ }
368
+ // check that from path exists on host
369
+ if (!fs.existsSync(from)) {
370
+ throw new FatalSandboxError(`Missing mount path '${from}' listed in SANDBOX_MOUNTS`);
371
+ }
372
+ console.error(`SANDBOX_MOUNTS: ${from} -> ${to} (${opts})`);
373
+ args.push('--volume', mount);
374
+ }
375
+ }
376
+ }
377
+ // expose env-specified ports on the sandbox
378
+ ports().forEach((p) => args.push('--publish', `${p}:${p}`));
379
+ // if DEBUG is set, expose debugging port
380
+ if (process.env['DEBUG']) {
381
+ const debugPort = process.env['DEBUG_PORT'] || '9229';
382
+ args.push(`--publish`, `${debugPort}:${debugPort}`);
383
+ }
384
+ // copy proxy environment variables, replacing localhost with SANDBOX_PROXY_NAME
385
+ // copy as both upper-case and lower-case as is required by some utilities
386
+ // GEMINI_SANDBOX_PROXY_COMMAND implies HTTPS_PROXY unless HTTP_PROXY is set
387
+ const proxyCommand = process.env['GEMINI_SANDBOX_PROXY_COMMAND'];
213
388
  if (proxyCommand) {
214
- const proxy = process.env.HTTPS_PROXY ||
215
- process.env.https_proxy ||
216
- process.env.HTTP_PROXY ||
217
- process.env.http_proxy ||
389
+ let proxy = process.env['HTTPS_PROXY'] ||
390
+ process.env['https_proxy'] ||
391
+ process.env['HTTP_PROXY'] ||
392
+ process.env['http_proxy'] ||
218
393
  'http://localhost:8877';
219
- sandboxEnv['HTTPS_PROXY'] = proxy;
220
- sandboxEnv['https_proxy'] = proxy; // lower-case can be required, e.g. for curl
221
- sandboxEnv['HTTP_PROXY'] = proxy;
222
- sandboxEnv['http_proxy'] = proxy;
223
- const noProxy = process.env.NO_PROXY || process.env.no_proxy;
394
+ proxy = proxy.replace('localhost', SANDBOX_PROXY_NAME);
395
+ if (proxy) {
396
+ args.push('--env', `HTTPS_PROXY=${proxy}`);
397
+ args.push('--env', `https_proxy=${proxy}`); // lower-case can be required, e.g. for curl
398
+ args.push('--env', `HTTP_PROXY=${proxy}`);
399
+ args.push('--env', `http_proxy=${proxy}`);
400
+ }
401
+ const noProxy = process.env['NO_PROXY'] || process.env['no_proxy'];
224
402
  if (noProxy) {
225
- sandboxEnv['NO_PROXY'] = noProxy;
226
- sandboxEnv['no_proxy'] = noProxy;
403
+ args.push('--env', `NO_PROXY=${noProxy}`);
404
+ args.push('--env', `no_proxy=${noProxy}`);
227
405
  }
228
- proxyProcess = spawn(proxyCommand, {
406
+ // if using proxy, switch to internal networking through proxy
407
+ if (proxy) {
408
+ execSync(`${config.command} network inspect ${SANDBOX_NETWORK_NAME} || ${config.command} network create --internal ${SANDBOX_NETWORK_NAME}`);
409
+ args.push('--network', SANDBOX_NETWORK_NAME);
410
+ // if proxy command is set, create a separate network w/ host access (i.e. non-internal)
411
+ // we will run proxy in its own container connected to both host network and internal network
412
+ // this allows proxy to work even on rootless podman on macos with host<->vm<->container isolation
413
+ if (proxyCommand) {
414
+ execSync(`${config.command} network inspect ${SANDBOX_PROXY_NAME} || ${config.command} network create ${SANDBOX_PROXY_NAME}`);
415
+ }
416
+ }
417
+ }
418
+ // name container after image, plus numeric suffix to avoid conflicts
419
+ const imageName = parseImageName(image);
420
+ let index = 0;
421
+ const containerNameCheck = execSync(`${config.command} ps -a --format "{{.Names}}"`)
422
+ .toString()
423
+ .trim();
424
+ while (containerNameCheck.includes(`${imageName}-${index}`)) {
425
+ index++;
426
+ }
427
+ const containerName = `${imageName}-${index}`;
428
+ args.push('--name', containerName, '--hostname', containerName);
429
+ // copy GEMINI_API_KEY(s)
430
+ if (process.env['GEMINI_API_KEY']) {
431
+ args.push('--env', `GEMINI_API_KEY=${process.env['GEMINI_API_KEY']}`);
432
+ }
433
+ if (process.env['GOOGLE_API_KEY']) {
434
+ args.push('--env', `GOOGLE_API_KEY=${process.env['GOOGLE_API_KEY']}`);
435
+ }
436
+ // copy OPENAI_API_KEY and related env vars for Qwen
437
+ if (process.env['OPENAI_API_KEY']) {
438
+ args.push('--env', `OPENAI_API_KEY=${process.env['OPENAI_API_KEY']}`);
439
+ }
440
+ // copy TAVILY_API_KEY for web search tool
441
+ if (process.env['TAVILY_API_KEY']) {
442
+ args.push('--env', `TAVILY_API_KEY=${process.env['TAVILY_API_KEY']}`);
443
+ }
444
+ if (process.env['OPENAI_BASE_URL']) {
445
+ args.push('--env', `OPENAI_BASE_URL=${process.env['OPENAI_BASE_URL']}`);
446
+ }
447
+ if (process.env['OPENAI_MODEL']) {
448
+ args.push('--env', `OPENAI_MODEL=${process.env['OPENAI_MODEL']}`);
449
+ }
450
+ // copy GOOGLE_GENAI_USE_VERTEXAI
451
+ if (process.env['GOOGLE_GENAI_USE_VERTEXAI']) {
452
+ args.push('--env', `GOOGLE_GENAI_USE_VERTEXAI=${process.env['GOOGLE_GENAI_USE_VERTEXAI']}`);
453
+ }
454
+ // copy GOOGLE_GENAI_USE_GCA
455
+ if (process.env['GOOGLE_GENAI_USE_GCA']) {
456
+ args.push('--env', `GOOGLE_GENAI_USE_GCA=${process.env['GOOGLE_GENAI_USE_GCA']}`);
457
+ }
458
+ // copy GOOGLE_CLOUD_PROJECT
459
+ if (process.env['GOOGLE_CLOUD_PROJECT']) {
460
+ args.push('--env', `GOOGLE_CLOUD_PROJECT=${process.env['GOOGLE_CLOUD_PROJECT']}`);
461
+ }
462
+ // copy GOOGLE_CLOUD_LOCATION
463
+ if (process.env['GOOGLE_CLOUD_LOCATION']) {
464
+ args.push('--env', `GOOGLE_CLOUD_LOCATION=${process.env['GOOGLE_CLOUD_LOCATION']}`);
465
+ }
466
+ // copy GEMINI_MODEL
467
+ if (process.env['GEMINI_MODEL']) {
468
+ args.push('--env', `GEMINI_MODEL=${process.env['GEMINI_MODEL']}`);
469
+ }
470
+ // copy TERM and COLORTERM to try to maintain terminal setup
471
+ if (process.env['TERM']) {
472
+ args.push('--env', `TERM=${process.env['TERM']}`);
473
+ }
474
+ if (process.env['COLORTERM']) {
475
+ args.push('--env', `COLORTERM=${process.env['COLORTERM']}`);
476
+ }
477
+ // Pass through IDE mode environment variables
478
+ for (const envVar of [
479
+ 'QWEN_CODE_IDE_SERVER_PORT',
480
+ 'QWEN_CODE_IDE_WORKSPACE_PATH',
481
+ 'TERM_PROGRAM',
482
+ ]) {
483
+ if (process.env[envVar]) {
484
+ args.push('--env', `${envVar}=${process.env[envVar]}`);
485
+ }
486
+ }
487
+ // copy VIRTUAL_ENV if under working directory
488
+ // also mount-replace VIRTUAL_ENV directory with <project_settings>/sandbox.venv
489
+ // sandbox can then set up this new VIRTUAL_ENV directory using sandbox.bashrc (see below)
490
+ // directory will be empty if not set up, which is still preferable to having host binaries
491
+ if (process.env['VIRTUAL_ENV']
492
+ ?.toLowerCase()
493
+ .startsWith(workdir.toLowerCase())) {
494
+ const sandboxVenvPath = path.resolve(SETTINGS_DIRECTORY_NAME, 'sandbox.venv');
495
+ if (!fs.existsSync(sandboxVenvPath)) {
496
+ fs.mkdirSync(sandboxVenvPath, { recursive: true });
497
+ }
498
+ args.push('--volume', `${sandboxVenvPath}:${getContainerPath(process.env['VIRTUAL_ENV'])}`);
499
+ args.push('--env', `VIRTUAL_ENV=${getContainerPath(process.env['VIRTUAL_ENV'])}`);
500
+ }
501
+ // copy additional environment variables from SANDBOX_ENV
502
+ if (process.env['SANDBOX_ENV']) {
503
+ for (let env of process.env['SANDBOX_ENV'].split(',')) {
504
+ if ((env = env.trim())) {
505
+ if (env.includes('=')) {
506
+ console.error(`SANDBOX_ENV: ${env}`);
507
+ args.push('--env', env);
508
+ }
509
+ else {
510
+ throw new FatalSandboxError('SANDBOX_ENV must be a comma-separated list of key=value pairs');
511
+ }
512
+ }
513
+ }
514
+ }
515
+ // copy NODE_OPTIONS
516
+ const existingNodeOptions = process.env['NODE_OPTIONS'] || '';
517
+ const allNodeOptions = [
518
+ ...(existingNodeOptions ? [existingNodeOptions] : []),
519
+ ...nodeArgs,
520
+ ].join(' ');
521
+ if (allNodeOptions.length > 0) {
522
+ args.push('--env', `NODE_OPTIONS="${allNodeOptions}"`);
523
+ }
524
+ // set SANDBOX as container name
525
+ args.push('--env', `SANDBOX=${containerName}`);
526
+ // for podman only, use empty --authfile to skip unnecessary auth refresh overhead
527
+ if (config.command === 'podman') {
528
+ const emptyAuthFilePath = path.join(os.tmpdir(), 'empty_auth.json');
529
+ fs.writeFileSync(emptyAuthFilePath, '{}', 'utf-8');
530
+ args.push('--authfile', emptyAuthFilePath);
531
+ }
532
+ // Determine if the current user's UID/GID should be passed to the sandbox.
533
+ // See shouldUseCurrentUserInSandbox for more details.
534
+ let userFlag = '';
535
+ const finalEntrypoint = entrypoint(workdir, cliArgs);
536
+ if (process.env['GEMINI_CLI_INTEGRATION_TEST'] === 'true') {
537
+ args.push('--user', 'root');
538
+ userFlag = '--user root';
539
+ }
540
+ else if (await shouldUseCurrentUserInSandbox()) {
541
+ // For the user-creation logic to work, the container must start as root.
542
+ // The entrypoint script then handles dropping privileges to the correct user.
543
+ args.push('--user', 'root');
544
+ const uid = execSync('id -u').toString().trim();
545
+ const gid = execSync('id -g').toString().trim();
546
+ // Instead of passing --user to the main sandbox container, we let it
547
+ // start as root, then create a user with the host's UID/GID, and
548
+ // finally switch to that user to run the gemini process. This is
549
+ // necessary on Linux to ensure the user exists within the
550
+ // container's /etc/passwd file, which is required by os.userInfo().
551
+ const username = 'gemini';
552
+ const homeDir = getContainerPath(os.homedir());
553
+ const setupUserCommands = [
554
+ // Use -f with groupadd to avoid errors if the group already exists.
555
+ `groupadd -f -g ${gid} ${username}`,
556
+ // Create user only if it doesn't exist. Use -o for non-unique UID.
557
+ `id -u ${username} &>/dev/null || useradd -o -u ${uid} -g ${gid} -d ${homeDir} -s /bin/bash ${username}`,
558
+ ].join(' && ');
559
+ const originalCommand = finalEntrypoint[2];
560
+ const escapedOriginalCommand = originalCommand.replace(/'/g, "'\\''");
561
+ // Use `su -p` to preserve the environment.
562
+ const suCommand = `su -p ${username} -c '${escapedOriginalCommand}'`;
563
+ // The entrypoint is always `['bash', '-c', '<command>']`, so we modify the command part.
564
+ finalEntrypoint[2] = `${setupUserCommands} && ${suCommand}`;
565
+ // We still need userFlag for the simpler proxy container, which does not have this issue.
566
+ userFlag = `--user ${uid}:${gid}`;
567
+ // When forcing a UID in the sandbox, $HOME can be reset to '/', so we copy $HOME as well.
568
+ args.push('--env', `HOME=${os.homedir()}`);
569
+ }
570
+ // push container image name
571
+ args.push(image);
572
+ // push container entrypoint (including args)
573
+ args.push(...finalEntrypoint);
574
+ // start and set up proxy if GEMINI_SANDBOX_PROXY_COMMAND is set
575
+ let proxyProcess = undefined;
576
+ let sandboxProcess = undefined;
577
+ if (proxyCommand) {
578
+ // run proxyCommand in its own container
579
+ const proxyContainerCommand = `${config.command} run --rm --init ${userFlag} --name ${SANDBOX_PROXY_NAME} --network ${SANDBOX_PROXY_NAME} -p 8877:8877 -v ${process.cwd()}:${workdir} --workdir ${workdir} ${image} ${proxyCommand}`;
580
+ proxyProcess = spawn(proxyContainerCommand, {
229
581
  stdio: ['ignore', 'pipe', 'pipe'],
230
582
  shell: true,
231
583
  detached: true,
232
584
  });
233
585
  // install handlers to stop proxy on exit/signal
234
586
  const stopProxy = () => {
235
- console.log('stopping proxy ...');
236
- if (proxyProcess?.pid) {
237
- process.kill(-proxyProcess.pid, 'SIGTERM');
238
- }
587
+ console.log('stopping proxy container ...');
588
+ execSync(`${config.command} rm -f ${SANDBOX_PROXY_NAME}`);
239
589
  };
240
590
  process.on('exit', stopProxy);
241
591
  process.on('SIGINT', stopProxy);
@@ -245,373 +595,39 @@ export async function start_sandbox(config, nodeArgs = [], cliConfig) {
245
595
  // console.info(data.toString());
246
596
  // });
247
597
  proxyProcess.stderr?.on('data', (data) => {
248
- console.error(data.toString());
598
+ console.error(data.toString().trim());
249
599
  });
250
600
  proxyProcess.on('close', (code, signal) => {
251
- console.error(`ERROR: proxy command '${proxyCommand}' exited with code ${code}, signal ${signal}`);
252
601
  if (sandboxProcess?.pid) {
253
602
  process.kill(-sandboxProcess.pid, 'SIGTERM');
254
603
  }
255
- process.exit(1);
604
+ throw new FatalSandboxError(`Proxy container command '${proxyContainerCommand}' exited with code ${code}, signal ${signal}`);
256
605
  });
257
606
  console.log('waiting for proxy to start ...');
258
607
  await execAsync(`until timeout 0.25 curl -s http://localhost:8877; do sleep 0.25; done`);
608
+ // connect proxy container to sandbox network
609
+ // (workaround for older versions of docker that don't support multiple --network args)
610
+ await execAsync(`${config.command} network connect ${SANDBOX_NETWORK_NAME} ${SANDBOX_PROXY_NAME}`);
259
611
  }
260
612
  // spawn child and let it inherit stdio
261
613
  sandboxProcess = spawn(config.command, args, {
262
614
  stdio: 'inherit',
263
615
  });
264
- await new Promise((resolve) => sandboxProcess?.on('close', resolve));
265
- return;
266
- }
267
- console.error(`hopping into sandbox (command: ${config.command}) ...`);
268
- // determine full path for gemini-cli to distinguish linked vs installed setting
269
- const gcPath = fs.realpathSync(process.argv[1]);
270
- const projectSandboxDockerfile = path.join(SETTINGS_DIRECTORY_NAME, 'sandbox.Dockerfile');
271
- const isCustomProjectSandbox = fs.existsSync(projectSandboxDockerfile);
272
- const image = config.image;
273
- const workdir = path.resolve(process.cwd());
274
- const containerWorkdir = getContainerPath(workdir);
275
- // if BUILD_SANDBOX is set, then call scripts/build_sandbox.js under gemini-cli repo
276
- //
277
- // note this can only be done with binary linked from gemini-cli repo
278
- if (process.env.BUILD_SANDBOX) {
279
- if (!gcPath.includes('gemini-cli/packages/')) {
280
- console.error('ERROR: cannot build sandbox using installed gemini binary; ' +
281
- 'run `npm link ./packages/cli` under gemini-cli repo to switch to linked binary.');
282
- process.exit(1);
283
- }
284
- else {
285
- console.error('building sandbox ...');
286
- const gcRoot = gcPath.split('/packages/')[0];
287
- // if project folder has sandbox.Dockerfile under project settings folder, use that
288
- let buildArgs = '';
289
- const projectSandboxDockerfile = path.join(SETTINGS_DIRECTORY_NAME, 'sandbox.Dockerfile');
290
- if (isCustomProjectSandbox) {
291
- console.error(`using ${projectSandboxDockerfile} for sandbox`);
292
- buildArgs += `-f ${path.resolve(projectSandboxDockerfile)} -i ${image}`;
293
- }
294
- execSync(`cd ${gcRoot} && node scripts/build_sandbox.js -s ${buildArgs}`, {
295
- stdio: 'inherit',
296
- env: {
297
- ...process.env,
298
- GEMINI_SANDBOX: config.command, // in case sandbox is enabled via flags (see config.ts under cli package)
299
- },
300
- });
301
- }
302
- }
303
- // stop if image is missing
304
- if (!(await ensureSandboxImageIsPresent(config.command, image))) {
305
- const remedy = image === LOCAL_DEV_SANDBOX_IMAGE_NAME
306
- ? 'Try running `npm run build:all` or `npm run build:sandbox` under the gemini-cli repo to build it locally, or check the image name and your network connection.'
307
- : 'Please check the image name, your network connection, or notify gemini-cli-dev@google.com if the issue persists.';
308
- console.error(`ERROR: Sandbox image '${image}' is missing or could not be pulled. ${remedy}`);
309
- process.exit(1);
310
- }
311
- // use interactive mode and auto-remove container on exit
312
- // run init binary inside container to forward signals & reap zombies
313
- const args = ['run', '-i', '--rm', '--init', '--workdir', containerWorkdir];
314
- // add custom flags from SANDBOX_FLAGS
315
- if (process.env.SANDBOX_FLAGS) {
316
- const flags = parse(process.env.SANDBOX_FLAGS, process.env).filter((f) => typeof f === 'string');
317
- args.push(...flags);
318
- }
319
- // add TTY only if stdin is TTY as well, i.e. for piped input don't init TTY in container
320
- if (process.stdin.isTTY) {
321
- args.push('-t');
322
- }
323
- // mount current directory as working directory in sandbox (set via --workdir)
324
- args.push('--volume', `${workdir}:${containerWorkdir}`);
325
- // mount user settings directory inside container, after creating if missing
326
- // note user/home changes inside sandbox and we mount at BOTH paths for consistency
327
- const userSettingsDirOnHost = USER_SETTINGS_DIR;
328
- const userSettingsDirInSandbox = getContainerPath(`/home/node/${SETTINGS_DIRECTORY_NAME}`);
329
- if (!fs.existsSync(userSettingsDirOnHost)) {
330
- fs.mkdirSync(userSettingsDirOnHost);
331
- }
332
- args.push('--volume', `${userSettingsDirOnHost}:${userSettingsDirInSandbox}`);
333
- if (userSettingsDirInSandbox !== userSettingsDirOnHost) {
334
- args.push('--volume', `${userSettingsDirOnHost}:${getContainerPath(userSettingsDirOnHost)}`);
335
- }
336
- // mount os.tmpdir() as os.tmpdir() inside container
337
- args.push('--volume', `${os.tmpdir()}:${getContainerPath(os.tmpdir())}`);
338
- // mount gcloud config directory if it exists
339
- const gcloudConfigDir = path.join(os.homedir(), '.config', 'gcloud');
340
- if (fs.existsSync(gcloudConfigDir)) {
341
- args.push('--volume', `${gcloudConfigDir}:${getContainerPath(gcloudConfigDir)}:ro`);
342
- }
343
- // mount ADC file if GOOGLE_APPLICATION_CREDENTIALS is set
344
- if (process.env.GOOGLE_APPLICATION_CREDENTIALS) {
345
- const adcFile = process.env.GOOGLE_APPLICATION_CREDENTIALS;
346
- if (fs.existsSync(adcFile)) {
347
- args.push('--volume', `${adcFile}:${getContainerPath(adcFile)}:ro`);
348
- args.push('--env', `GOOGLE_APPLICATION_CREDENTIALS=${getContainerPath(adcFile)}`);
349
- }
350
- }
351
- // mount paths listed in SANDBOX_MOUNTS
352
- if (process.env.SANDBOX_MOUNTS) {
353
- for (let mount of process.env.SANDBOX_MOUNTS.split(',')) {
354
- if (mount.trim()) {
355
- // parse mount as from:to:opts
356
- let [from, to, opts] = mount.trim().split(':');
357
- to = to || from; // default to mount at same path inside container
358
- opts = opts || 'ro'; // default to read-only
359
- mount = `${from}:${to}:${opts}`;
360
- // check that from path is absolute
361
- if (!path.isAbsolute(from)) {
362
- console.error(`ERROR: path '${from}' listed in SANDBOX_MOUNTS must be absolute`);
363
- process.exit(1);
364
- }
365
- // check that from path exists on host
366
- if (!fs.existsSync(from)) {
367
- console.error(`ERROR: missing mount path '${from}' listed in SANDBOX_MOUNTS`);
368
- process.exit(1);
369
- }
370
- console.error(`SANDBOX_MOUNTS: ${from} -> ${to} (${opts})`);
371
- args.push('--volume', mount);
372
- }
373
- }
374
- }
375
- // expose env-specified ports on the sandbox
376
- ports().forEach((p) => args.push('--publish', `${p}:${p}`));
377
- // if DEBUG is set, expose debugging port
378
- if (process.env.DEBUG) {
379
- const debugPort = process.env.DEBUG_PORT || '9229';
380
- args.push(`--publish`, `${debugPort}:${debugPort}`);
381
- }
382
- // copy proxy environment variables, replacing localhost with SANDBOX_PROXY_NAME
383
- // copy as both upper-case and lower-case as is required by some utilities
384
- // GEMINI_SANDBOX_PROXY_COMMAND implies HTTPS_PROXY unless HTTP_PROXY is set
385
- const proxyCommand = process.env.GEMINI_SANDBOX_PROXY_COMMAND;
386
- if (proxyCommand) {
387
- let proxy = process.env.HTTPS_PROXY ||
388
- process.env.https_proxy ||
389
- process.env.HTTP_PROXY ||
390
- process.env.http_proxy ||
391
- 'http://localhost:8877';
392
- proxy = proxy.replace('localhost', SANDBOX_PROXY_NAME);
393
- if (proxy) {
394
- args.push('--env', `HTTPS_PROXY=${proxy}`);
395
- args.push('--env', `https_proxy=${proxy}`); // lower-case can be required, e.g. for curl
396
- args.push('--env', `HTTP_PROXY=${proxy}`);
397
- args.push('--env', `http_proxy=${proxy}`);
398
- }
399
- const noProxy = process.env.NO_PROXY || process.env.no_proxy;
400
- if (noProxy) {
401
- args.push('--env', `NO_PROXY=${noProxy}`);
402
- args.push('--env', `no_proxy=${noProxy}`);
403
- }
404
- // if using proxy, switch to internal networking through proxy
405
- if (proxy) {
406
- execSync(`${config.command} network inspect ${SANDBOX_NETWORK_NAME} || ${config.command} network create --internal ${SANDBOX_NETWORK_NAME}`);
407
- args.push('--network', SANDBOX_NETWORK_NAME);
408
- // if proxy command is set, create a separate network w/ host access (i.e. non-internal)
409
- // we will run proxy in its own container connected to both host network and internal network
410
- // this allows proxy to work even on rootless podman on macos with host<->vm<->container isolation
411
- if (proxyCommand) {
412
- execSync(`${config.command} network inspect ${SANDBOX_PROXY_NAME} || ${config.command} network create ${SANDBOX_PROXY_NAME}`);
413
- }
414
- }
415
- }
416
- // name container after image, plus numeric suffix to avoid conflicts
417
- const imageName = parseImageName(image);
418
- let index = 0;
419
- const containerNameCheck = execSync(`${config.command} ps -a --format "{{.Names}}"`)
420
- .toString()
421
- .trim();
422
- while (containerNameCheck.includes(`${imageName}-${index}`)) {
423
- index++;
424
- }
425
- const containerName = `${imageName}-${index}`;
426
- args.push('--name', containerName, '--hostname', containerName);
427
- // copy GEMINI_API_KEY(s)
428
- if (process.env.GEMINI_API_KEY) {
429
- args.push('--env', `GEMINI_API_KEY=${process.env.GEMINI_API_KEY}`);
430
- }
431
- if (process.env.GOOGLE_API_KEY) {
432
- args.push('--env', `GOOGLE_API_KEY=${process.env.GOOGLE_API_KEY}`);
433
- }
434
- // copy OPENAI_API_KEY and related env vars for Qwen
435
- if (process.env.OPENAI_API_KEY) {
436
- args.push('--env', `OPENAI_API_KEY=${process.env.OPENAI_API_KEY}`);
437
- }
438
- // copy TAVILY_API_KEY for web search tool
439
- if (process.env.TAVILY_API_KEY) {
440
- args.push('--env', `TAVILY_API_KEY=${process.env.TAVILY_API_KEY}`);
441
- }
442
- if (process.env.OPENAI_BASE_URL) {
443
- args.push('--env', `OPENAI_BASE_URL=${process.env.OPENAI_BASE_URL}`);
444
- }
445
- if (process.env.OPENAI_MODEL) {
446
- args.push('--env', `OPENAI_MODEL=${process.env.OPENAI_MODEL}`);
447
- }
448
- // copy GOOGLE_GENAI_USE_VERTEXAI
449
- if (process.env.GOOGLE_GENAI_USE_VERTEXAI) {
450
- args.push('--env', `GOOGLE_GENAI_USE_VERTEXAI=${process.env.GOOGLE_GENAI_USE_VERTEXAI}`);
451
- }
452
- // copy GOOGLE_GENAI_USE_GCA
453
- if (process.env.GOOGLE_GENAI_USE_GCA) {
454
- args.push('--env', `GOOGLE_GENAI_USE_GCA=${process.env.GOOGLE_GENAI_USE_GCA}`);
455
- }
456
- // copy GOOGLE_CLOUD_PROJECT
457
- if (process.env.GOOGLE_CLOUD_PROJECT) {
458
- args.push('--env', `GOOGLE_CLOUD_PROJECT=${process.env.GOOGLE_CLOUD_PROJECT}`);
459
- }
460
- // copy GOOGLE_CLOUD_LOCATION
461
- if (process.env.GOOGLE_CLOUD_LOCATION) {
462
- args.push('--env', `GOOGLE_CLOUD_LOCATION=${process.env.GOOGLE_CLOUD_LOCATION}`);
463
- }
464
- // copy GEMINI_MODEL
465
- if (process.env.GEMINI_MODEL) {
466
- args.push('--env', `GEMINI_MODEL=${process.env.GEMINI_MODEL}`);
467
- }
468
- // copy TERM and COLORTERM to try to maintain terminal setup
469
- if (process.env.TERM) {
470
- args.push('--env', `TERM=${process.env.TERM}`);
471
- }
472
- if (process.env.COLORTERM) {
473
- args.push('--env', `COLORTERM=${process.env.COLORTERM}`);
474
- }
475
- // copy VIRTUAL_ENV if under working directory
476
- // also mount-replace VIRTUAL_ENV directory with <project_settings>/sandbox.venv
477
- // sandbox can then set up this new VIRTUAL_ENV directory using sandbox.bashrc (see below)
478
- // directory will be empty if not set up, which is still preferable to having host binaries
479
- if (process.env.VIRTUAL_ENV?.toLowerCase().startsWith(workdir.toLowerCase())) {
480
- const sandboxVenvPath = path.resolve(SETTINGS_DIRECTORY_NAME, 'sandbox.venv');
481
- if (!fs.existsSync(sandboxVenvPath)) {
482
- fs.mkdirSync(sandboxVenvPath, { recursive: true });
483
- }
484
- args.push('--volume', `${sandboxVenvPath}:${getContainerPath(process.env.VIRTUAL_ENV)}`);
485
- args.push('--env', `VIRTUAL_ENV=${getContainerPath(process.env.VIRTUAL_ENV)}`);
486
- }
487
- // copy additional environment variables from SANDBOX_ENV
488
- if (process.env.SANDBOX_ENV) {
489
- for (let env of process.env.SANDBOX_ENV.split(',')) {
490
- if ((env = env.trim())) {
491
- if (env.includes('=')) {
492
- console.error(`SANDBOX_ENV: ${env}`);
493
- args.push('--env', env);
494
- }
495
- else {
496
- console.error('ERROR: SANDBOX_ENV must be a comma-separated list of key=value pairs');
497
- process.exit(1);
498
- }
499
- }
500
- }
501
- }
502
- // copy NODE_OPTIONS
503
- const existingNodeOptions = process.env.NODE_OPTIONS || '';
504
- const allNodeOptions = [
505
- ...(existingNodeOptions ? [existingNodeOptions] : []),
506
- ...nodeArgs,
507
- ].join(' ');
508
- if (allNodeOptions.length > 0) {
509
- args.push('--env', `NODE_OPTIONS="${allNodeOptions}"`);
510
- }
511
- // set SANDBOX as container name
512
- args.push('--env', `SANDBOX=${containerName}`);
513
- // for podman only, use empty --authfile to skip unnecessary auth refresh overhead
514
- if (config.command === 'podman') {
515
- const emptyAuthFilePath = path.join(os.tmpdir(), 'empty_auth.json');
516
- fs.writeFileSync(emptyAuthFilePath, '{}', 'utf-8');
517
- args.push('--authfile', emptyAuthFilePath);
518
- }
519
- // Determine if the current user's UID/GID should be passed to the sandbox.
520
- // See shouldUseCurrentUserInSandbox for more details.
521
- let userFlag = '';
522
- const finalEntrypoint = entrypoint(workdir);
523
- if (process.env.GEMINI_CLI_INTEGRATION_TEST === 'true') {
524
- args.push('--user', 'root');
525
- userFlag = '--user root';
526
- }
527
- else if (await shouldUseCurrentUserInSandbox()) {
528
- // For the user-creation logic to work, the container must start as root.
529
- // The entrypoint script then handles dropping privileges to the correct user.
530
- args.push('--user', 'root');
531
- const uid = execSync('id -u').toString().trim();
532
- const gid = execSync('id -g').toString().trim();
533
- // Instead of passing --user to the main sandbox container, we let it
534
- // start as root, then create a user with the host's UID/GID, and
535
- // finally switch to that user to run the gemini process. This is
536
- // necessary on Linux to ensure the user exists within the
537
- // container's /etc/passwd file, which is required by os.userInfo().
538
- const username = 'gemini';
539
- const homeDir = getContainerPath(os.homedir());
540
- const setupUserCommands = [
541
- // Use -f with groupadd to avoid errors if the group already exists.
542
- `groupadd -f -g ${gid} ${username}`,
543
- // Create user only if it doesn't exist. Use -o for non-unique UID.
544
- `id -u ${username} &>/dev/null || useradd -o -u ${uid} -g ${gid} -d ${homeDir} -s /bin/bash ${username}`,
545
- ].join(' && ');
546
- const originalCommand = finalEntrypoint[2];
547
- const escapedOriginalCommand = originalCommand.replace(/'/g, "'\\''");
548
- // Use `su -p` to preserve the environment.
549
- const suCommand = `su -p ${username} -c '${escapedOriginalCommand}'`;
550
- // The entrypoint is always `['bash', '-c', '<command>']`, so we modify the command part.
551
- finalEntrypoint[2] = `${setupUserCommands} && ${suCommand}`;
552
- // We still need userFlag for the simpler proxy container, which does not have this issue.
553
- userFlag = `--user ${uid}:${gid}`;
554
- // When forcing a UID in the sandbox, $HOME can be reset to '/', so we copy $HOME as well.
555
- args.push('--env', `HOME=${os.homedir()}`);
556
- }
557
- // push container image name
558
- args.push(image);
559
- // push container entrypoint (including args)
560
- args.push(...finalEntrypoint);
561
- // start and set up proxy if GEMINI_SANDBOX_PROXY_COMMAND is set
562
- let proxyProcess = undefined;
563
- let sandboxProcess = undefined;
564
- if (proxyCommand) {
565
- // run proxyCommand in its own container
566
- const proxyContainerCommand = `${config.command} run --rm --init ${userFlag} --name ${SANDBOX_PROXY_NAME} --network ${SANDBOX_PROXY_NAME} -p 8877:8877 -v ${process.cwd()}:${workdir} --workdir ${workdir} ${image} ${proxyCommand}`;
567
- proxyProcess = spawn(proxyContainerCommand, {
568
- stdio: ['ignore', 'pipe', 'pipe'],
569
- shell: true,
570
- detached: true,
616
+ sandboxProcess.on('error', (err) => {
617
+ console.error('Sandbox process error:', err);
571
618
  });
572
- // install handlers to stop proxy on exit/signal
573
- const stopProxy = () => {
574
- console.log('stopping proxy container ...');
575
- execSync(`${config.command} rm -f ${SANDBOX_PROXY_NAME}`);
576
- };
577
- process.on('exit', stopProxy);
578
- process.on('SIGINT', stopProxy);
579
- process.on('SIGTERM', stopProxy);
580
- // commented out as it disrupts ink rendering
581
- // proxyProcess.stdout?.on('data', (data) => {
582
- // console.info(data.toString());
583
- // });
584
- proxyProcess.stderr?.on('data', (data) => {
585
- console.error(data.toString().trim());
586
- });
587
- proxyProcess.on('close', (code, signal) => {
588
- console.error(`ERROR: proxy container command '${proxyContainerCommand}' exited with code ${code}, signal ${signal}`);
589
- if (sandboxProcess?.pid) {
590
- process.kill(-sandboxProcess.pid, 'SIGTERM');
591
- }
592
- process.exit(1);
619
+ await new Promise((resolve) => {
620
+ sandboxProcess?.on('close', (code, signal) => {
621
+ if (code !== 0) {
622
+ console.log(`Sandbox process exited with code: ${code}, signal: ${signal}`);
623
+ }
624
+ resolve();
625
+ });
593
626
  });
594
- console.log('waiting for proxy to start ...');
595
- await execAsync(`until timeout 0.25 curl -s http://localhost:8877; do sleep 0.25; done`);
596
- // connect proxy container to sandbox network
597
- // (workaround for older versions of docker that don't support multiple --network args)
598
- await execAsync(`${config.command} network connect ${SANDBOX_NETWORK_NAME} ${SANDBOX_PROXY_NAME}`);
599
627
  }
600
- // spawn child and let it inherit stdio
601
- sandboxProcess = spawn(config.command, args, {
602
- stdio: 'inherit',
603
- });
604
- sandboxProcess.on('error', (err) => {
605
- console.error('Sandbox process error:', err);
606
- });
607
- await new Promise((resolve) => {
608
- sandboxProcess?.on('close', (code, signal) => {
609
- if (code !== 0) {
610
- console.log(`Sandbox process exited with code: ${code}, signal: ${signal}`);
611
- }
612
- resolve();
613
- });
614
- });
628
+ finally {
629
+ patcher.cleanup();
630
+ }
615
631
  }
616
632
  // Helper functions to ensure sandbox image is present
617
633
  async function imageExists(sandbox, image) {