@google/gemini-cli 0.7.0-nightly.20250912.68035591 → 0.7.0-nightly.20250918.2722473a

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 (190) hide show
  1. package/dist/package.json +3 -2
  2. package/dist/src/commands/extensions/disable.d.ts +1 -1
  3. package/dist/src/commands/extensions/disable.js +3 -3
  4. package/dist/src/commands/extensions/disable.js.map +1 -1
  5. package/dist/src/commands/extensions/enable.d.ts +1 -1
  6. package/dist/src/commands/extensions/enable.js +5 -7
  7. package/dist/src/commands/extensions/enable.js.map +1 -1
  8. package/dist/src/commands/extensions/install.js +3 -2
  9. package/dist/src/commands/extensions/install.js.map +1 -1
  10. package/dist/src/commands/extensions/install.test.js +75 -2
  11. package/dist/src/commands/extensions/install.test.js.map +1 -1
  12. package/dist/src/commands/extensions/update.js +14 -4
  13. package/dist/src/commands/extensions/update.js.map +1 -1
  14. package/dist/src/config/config.d.ts +0 -1
  15. package/dist/src/config/config.js +13 -7
  16. package/dist/src/config/config.js.map +1 -1
  17. package/dist/src/config/extension.d.ts +13 -16
  18. package/dist/src/config/extension.js +170 -135
  19. package/dist/src/config/extension.js.map +1 -1
  20. package/dist/src/config/extensions/extensionEnablement.d.ts +30 -0
  21. package/dist/src/config/extensions/extensionEnablement.js +113 -0
  22. package/dist/src/config/extensions/extensionEnablement.js.map +1 -0
  23. package/dist/src/config/extensions/extensionEnablement.test.d.ts +6 -0
  24. package/dist/src/config/extensions/extensionEnablement.test.js +116 -0
  25. package/dist/src/config/extensions/extensionEnablement.test.js.map +1 -0
  26. package/dist/src/config/extensions/variableSchema.d.ts +8 -0
  27. package/dist/src/config/extensions/variableSchema.js +4 -0
  28. package/dist/src/config/extensions/variableSchema.js.map +1 -1
  29. package/dist/src/config/keyBindings.d.ts +3 -1
  30. package/dist/src/config/keyBindings.js +6 -0
  31. package/dist/src/config/keyBindings.js.map +1 -1
  32. package/dist/src/config/settings.d.ts +3 -0
  33. package/dist/src/config/settings.js +52 -15
  34. package/dist/src/config/settings.js.map +1 -1
  35. package/dist/src/config/settingsSchema.d.ts +9 -0
  36. package/dist/src/config/settingsSchema.js +9 -0
  37. package/dist/src/config/settingsSchema.js.map +1 -1
  38. package/dist/src/config/settingsSchema.test.js +6 -0
  39. package/dist/src/config/settingsSchema.test.js.map +1 -1
  40. package/dist/src/config/trustedFolders.d.ts +1 -1
  41. package/dist/src/config/trustedFolders.js +7 -2
  42. package/dist/src/config/trustedFolders.js.map +1 -1
  43. package/dist/src/config/trustedFolders.test.js +30 -8
  44. package/dist/src/config/trustedFolders.test.js.map +1 -1
  45. package/dist/src/gemini.js +52 -30
  46. package/dist/src/gemini.js.map +1 -1
  47. package/dist/src/gemini.test.js +23 -2
  48. package/dist/src/gemini.test.js.map +1 -1
  49. package/dist/src/generated/git-commit.d.ts +2 -2
  50. package/dist/src/generated/git-commit.js +2 -2
  51. package/dist/src/services/McpPromptLoader.js +43 -8
  52. package/dist/src/services/McpPromptLoader.js.map +1 -1
  53. package/dist/src/services/McpPromptLoader.test.js +228 -1
  54. package/dist/src/services/McpPromptLoader.test.js.map +1 -1
  55. package/dist/src/ui/AppContainer.js +38 -25
  56. package/dist/src/ui/AppContainer.js.map +1 -1
  57. package/dist/src/ui/AppContainer.test.js +36 -0
  58. package/dist/src/ui/AppContainer.test.js.map +1 -1
  59. package/dist/src/ui/commands/chatCommand.d.ts +2 -0
  60. package/dist/src/ui/commands/chatCommand.js +80 -1
  61. package/dist/src/ui/commands/chatCommand.js.map +1 -1
  62. package/dist/src/ui/commands/extensionsCommand.js +23 -33
  63. package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
  64. package/dist/src/ui/commands/types.d.ts +4 -1
  65. package/dist/src/ui/commands/types.js +0 -1
  66. package/dist/src/ui/commands/types.js.map +1 -1
  67. package/dist/src/ui/components/Composer.js +11 -3
  68. package/dist/src/ui/components/Composer.js.map +1 -1
  69. package/dist/src/ui/components/Composer.test.js +5 -0
  70. package/dist/src/ui/components/Composer.test.js.map +1 -1
  71. package/dist/src/ui/components/DialogManager.js +1 -1
  72. package/dist/src/ui/components/DialogManager.js.map +1 -1
  73. package/dist/src/ui/components/FolderTrustDialog.js +13 -6
  74. package/dist/src/ui/components/FolderTrustDialog.js.map +1 -1
  75. package/dist/src/ui/components/FolderTrustDialog.test.js +12 -7
  76. package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
  77. package/dist/src/ui/components/Footer.d.ts +3 -0
  78. package/dist/src/ui/components/Footer.js +8 -3
  79. package/dist/src/ui/components/Footer.js.map +1 -1
  80. package/dist/src/ui/components/HistoryItemDisplay.js +3 -1
  81. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  82. package/dist/src/ui/components/InputPrompt.d.ts +6 -0
  83. package/dist/src/ui/components/InputPrompt.js +119 -30
  84. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  85. package/dist/src/ui/components/PrepareLabel.d.ts +5 -5
  86. package/dist/src/ui/components/PrepareLabel.js +66 -10
  87. package/dist/src/ui/components/PrepareLabel.js.map +1 -1
  88. package/dist/src/ui/components/PrepareLabel.test.d.ts +6 -0
  89. package/dist/src/ui/components/PrepareLabel.test.js +71 -0
  90. package/dist/src/ui/components/PrepareLabel.test.js.map +1 -0
  91. package/dist/src/ui/components/SettingsDialog.d.ts +2 -1
  92. package/dist/src/ui/components/SettingsDialog.js +68 -12
  93. package/dist/src/ui/components/SettingsDialog.js.map +1 -1
  94. package/dist/src/ui/components/SettingsDialog.test.js +291 -0
  95. package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
  96. package/dist/src/ui/components/SuggestionsDisplay.d.ts +5 -2
  97. package/dist/src/ui/components/SuggestionsDisplay.js +11 -5
  98. package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
  99. package/dist/src/ui/components/ThemeDialog.test.js +10 -0
  100. package/dist/src/ui/components/ThemeDialog.test.js.map +1 -1
  101. package/dist/src/ui/components/messages/WarningMessage.d.ts +11 -0
  102. package/dist/src/ui/components/messages/WarningMessage.js +10 -0
  103. package/dist/src/ui/components/messages/WarningMessage.js.map +1 -0
  104. package/dist/src/ui/components/shared/text-buffer.d.ts +6 -0
  105. package/dist/src/ui/components/shared/text-buffer.js +23 -3
  106. package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
  107. package/dist/src/ui/components/views/ExtensionsList.d.ts +6 -0
  108. package/dist/src/ui/components/views/ExtensionsList.js +47 -0
  109. package/dist/src/ui/components/views/ExtensionsList.js.map +1 -0
  110. package/dist/src/ui/components/views/ExtensionsList.test.d.ts +6 -0
  111. package/dist/src/ui/components/views/ExtensionsList.test.js +97 -0
  112. package/dist/src/ui/components/views/ExtensionsList.test.js.map +1 -0
  113. package/dist/src/ui/contexts/UIStateContext.d.ts +2 -0
  114. package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
  115. package/dist/src/ui/hooks/slashCommandProcessor.d.ts +3 -1
  116. package/dist/src/ui/hooks/slashCommandProcessor.js +14 -44
  117. package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
  118. package/dist/src/ui/hooks/useAutoAcceptIndicator.d.ts +3 -2
  119. package/dist/src/ui/hooks/useAutoAcceptIndicator.js +9 -5
  120. package/dist/src/ui/hooks/useAutoAcceptIndicator.js.map +1 -1
  121. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js +69 -0
  122. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +1 -1
  123. package/dist/src/ui/hooks/useGeminiStream.d.ts +4 -0
  124. package/dist/src/ui/hooks/useGeminiStream.js +46 -17
  125. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  126. package/dist/src/ui/hooks/useGitBranchName.js +15 -18
  127. package/dist/src/ui/hooks/useGitBranchName.js.map +1 -1
  128. package/dist/src/ui/hooks/useGitBranchName.test.js +49 -53
  129. package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -1
  130. package/dist/src/ui/hooks/useMemoryMonitor.d.ts +13 -0
  131. package/dist/src/ui/hooks/useMemoryMonitor.js +28 -0
  132. package/dist/src/ui/hooks/useMemoryMonitor.js.map +1 -0
  133. package/dist/src/ui/hooks/useMemoryMonitor.test.d.ts +6 -0
  134. package/dist/src/ui/hooks/useMemoryMonitor.test.js +57 -0
  135. package/dist/src/ui/hooks/useMemoryMonitor.test.js.map +1 -0
  136. package/dist/src/ui/hooks/useReverseSearchCompletion.d.ts +1 -1
  137. package/dist/src/ui/hooks/useReverseSearchCompletion.js +67 -20
  138. package/dist/src/ui/hooks/useReverseSearchCompletion.js.map +1 -1
  139. package/dist/src/ui/hooks/useSlashCompletion.d.ts +1 -1
  140. package/dist/src/ui/hooks/useSlashCompletion.js +12 -1
  141. package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
  142. package/dist/src/ui/hooks/useSlashCompletion.test.js +14 -2
  143. package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
  144. package/dist/src/ui/hooks/useToolScheduler.test.js +1 -0
  145. package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
  146. package/dist/src/ui/keyMatchers.test.js +2 -0
  147. package/dist/src/ui/keyMatchers.test.js.map +1 -1
  148. package/dist/src/ui/state/extensions.d.ts +14 -0
  149. package/dist/src/ui/state/extensions.js +16 -0
  150. package/dist/src/ui/state/extensions.js.map +1 -0
  151. package/dist/src/ui/themes/ayu.js +1 -1
  152. package/dist/src/ui/themes/dracula.js +2 -2
  153. package/dist/src/ui/themes/github-dark.js +1 -1
  154. package/dist/src/ui/types.d.ts +11 -2
  155. package/dist/src/ui/types.js +2 -0
  156. package/dist/src/ui/types.js.map +1 -1
  157. package/dist/src/ui/utils/MarkdownDisplay.test.js +6 -2
  158. package/dist/src/ui/utils/MarkdownDisplay.test.js.map +1 -1
  159. package/dist/src/ui/utils/clipboardUtils.js +5 -6
  160. package/dist/src/ui/utils/clipboardUtils.js.map +1 -1
  161. package/dist/src/ui/utils/highlight.d.ts +1 -0
  162. package/dist/src/ui/utils/highlight.js +28 -0
  163. package/dist/src/ui/utils/highlight.js.map +1 -1
  164. package/dist/src/utils/commands.d.ts +20 -0
  165. package/dist/src/utils/commands.js +53 -0
  166. package/dist/src/utils/commands.js.map +1 -0
  167. package/dist/src/utils/commands.test.d.ts +6 -0
  168. package/dist/src/utils/commands.test.js +115 -0
  169. package/dist/src/utils/commands.test.js.map +1 -0
  170. package/dist/src/utils/commentJson.d.ts +9 -0
  171. package/dist/src/utils/commentJson.js +48 -0
  172. package/dist/src/utils/commentJson.js.map +1 -0
  173. package/dist/src/utils/commentJson.test.d.ts +6 -0
  174. package/dist/src/utils/commentJson.test.js +146 -0
  175. package/dist/src/utils/commentJson.test.js.map +1 -0
  176. package/dist/src/utils/processUtils.d.ts +13 -0
  177. package/dist/src/utils/processUtils.js +18 -0
  178. package/dist/src/utils/processUtils.js.map +1 -0
  179. package/dist/src/utils/processUtils.test.d.ts +6 -0
  180. package/dist/src/utils/processUtils.test.js +20 -0
  181. package/dist/src/utils/processUtils.test.js.map +1 -0
  182. package/dist/src/utils/sandbox.d.ts +1 -1
  183. package/dist/src/utils/sandbox.js +17 -8
  184. package/dist/src/utils/sandbox.js.map +1 -1
  185. package/dist/src/validateNonInterActiveAuth.js +30 -18
  186. package/dist/src/validateNonInterActiveAuth.js.map +1 -1
  187. package/dist/src/zed-integration/schema.d.ts +18 -18
  188. package/dist/tsconfig.tsbuildinfo +1 -1
  189. package/package.json +4 -3
  190. package/dist/google-gemini-cli-0.6.0-nightly.tgz +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"highlight.js","sourceRoot":"","sources":["../../../../src/ui/utils/highlight.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,MAAM,eAAe,GAAG,gDAAgD,CAAC;AAEzE,MAAM,UAAU,yBAAyB,CACvC,IAAY,EACZ,KAAa;IAEb,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,MAAM,GAAqB,EAAE,CAAC;IACpC,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,KAAK,CAAC;IAEV,OAAO,CAAC,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACrD,MAAM,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC;QAC1B,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC;QAE/B,mDAAmD;QACnD,IAAI,UAAU,GAAG,SAAS,EAAE,CAAC;YAC3B,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,UAAU,CAAC;gBACvC,IAAI,EAAE,SAAS;aAChB,CAAC,CAAC;QACL,CAAC;QAED,wBAAwB;QACxB,MAAM,IAAI,GAAG,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;QAC5D,mDAAmD;QACnD,IAAI,IAAI,KAAK,SAAS,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,SAAS;aAChB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,SAAS;gBACf,IAAI;aACL,CAAC,CAAC;QACL,CAAC;QAED,SAAS,GAAG,UAAU,GAAG,SAAS,CAAC,MAAM,CAAC;IAC5C,CAAC;IAED,8CAA8C;IAC9C,IAAI,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC;YAC3B,IAAI,EAAE,SAAS;SAChB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"highlight.js","sourceRoot":"","sources":["../../../../src/ui/utils/highlight.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { type SlashCommand } from '../ui/commands/types.js';
7
+ export type ParsedSlashCommand = {
8
+ commandToExecute: SlashCommand | undefined;
9
+ args: string;
10
+ canonicalPath: string[];
11
+ };
12
+ /**
13
+ * Parses a raw slash command string into its command, arguments, and canonical path.
14
+ * If no valid command is found, the `commandToExecute` property will be `undefined`.
15
+ *
16
+ * @param query The raw input string, e.g., "/memory add some data" or "/help".
17
+ * @param commands The list of available top-level slash commands.
18
+ * @returns An object containing the resolved command, its arguments, and its canonical path.
19
+ */
20
+ export declare const parseSlashCommand: (query: string, commands: readonly SlashCommand[]) => ParsedSlashCommand;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import {} from '../ui/commands/types.js';
7
+ /**
8
+ * Parses a raw slash command string into its command, arguments, and canonical path.
9
+ * If no valid command is found, the `commandToExecute` property will be `undefined`.
10
+ *
11
+ * @param query The raw input string, e.g., "/memory add some data" or "/help".
12
+ * @param commands The list of available top-level slash commands.
13
+ * @returns An object containing the resolved command, its arguments, and its canonical path.
14
+ */
15
+ export const parseSlashCommand = (query, commands) => {
16
+ const trimmed = query.trim();
17
+ const parts = trimmed.substring(1).trim().split(/\s+/);
18
+ const commandPath = parts.filter((p) => p); // The parts of the command, e.g., ['memory', 'add']
19
+ let currentCommands = commands;
20
+ let commandToExecute;
21
+ let pathIndex = 0;
22
+ const canonicalPath = [];
23
+ for (const part of commandPath) {
24
+ // TODO: For better performance and architectural clarity, this two-pass
25
+ // search could be replaced. A more optimal approach would be to
26
+ // pre-compute a single lookup map in `CommandService.ts` that resolves
27
+ // all name and alias conflicts during the initial loading phase. The
28
+ // processor would then perform a single, fast lookup on that map.
29
+ // First pass: check for an exact match on the primary command name.
30
+ let foundCommand = currentCommands.find((cmd) => cmd.name === part);
31
+ // Second pass: if no primary name matches, check for an alias.
32
+ if (!foundCommand) {
33
+ foundCommand = currentCommands.find((cmd) => cmd.altNames?.includes(part));
34
+ }
35
+ if (foundCommand) {
36
+ commandToExecute = foundCommand;
37
+ canonicalPath.push(foundCommand.name);
38
+ pathIndex++;
39
+ if (foundCommand.subCommands) {
40
+ currentCommands = foundCommand.subCommands;
41
+ }
42
+ else {
43
+ break;
44
+ }
45
+ }
46
+ else {
47
+ break;
48
+ }
49
+ }
50
+ const args = parts.slice(pathIndex).join(' ');
51
+ return { commandToExecute, args, canonicalPath };
52
+ };
53
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../../src/utils/commands.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAqB,MAAM,yBAAyB,CAAC;AAQ5D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,KAAa,EACb,QAAiC,EACb,EAAE;IACtB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAE7B,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvD,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,oDAAoD;IAEhG,IAAI,eAAe,GAAG,QAAQ,CAAC;IAC/B,IAAI,gBAA0C,CAAC;IAC/C,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,MAAM,aAAa,GAAa,EAAE,CAAC;IAEnC,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,wEAAwE;QACxE,gEAAgE;QAChE,uEAAuE;QACvE,qEAAqE;QACrE,kEAAkE;QAElE,oEAAoE;QACpE,IAAI,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QAEpE,+DAA+D;QAC/D,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAC1C,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,CAC7B,CAAC;QACJ,CAAC;QAED,IAAI,YAAY,EAAE,CAAC;YACjB,gBAAgB,GAAG,YAAY,CAAC;YAChC,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YACtC,SAAS,EAAE,CAAC;YACZ,IAAI,YAAY,CAAC,WAAW,EAAE,CAAC;gBAC7B,eAAe,GAAG,YAAY,CAAC,WAAW,CAAC;YAC7C,CAAC;iBAAM,CAAC;gBACN,MAAM;YACR,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM;QACR,CAAC;IACH,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE9C,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;AACnD,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
@@ -0,0 +1,115 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect } from 'vitest';
7
+ import { parseSlashCommand } from './commands.js';
8
+ import { CommandKind } from '../ui/commands/types.js';
9
+ // Mock command structure for testing
10
+ const mockCommands = [
11
+ {
12
+ name: 'help',
13
+ description: 'Show help',
14
+ action: async () => { },
15
+ kind: CommandKind.BUILT_IN,
16
+ },
17
+ {
18
+ name: 'commit',
19
+ description: 'Commit changes',
20
+ action: async () => { },
21
+ kind: CommandKind.FILE,
22
+ },
23
+ {
24
+ name: 'memory',
25
+ description: 'Manage memory',
26
+ altNames: ['mem'],
27
+ subCommands: [
28
+ {
29
+ name: 'add',
30
+ description: 'Add to memory',
31
+ action: async () => { },
32
+ kind: CommandKind.BUILT_IN,
33
+ },
34
+ {
35
+ name: 'clear',
36
+ description: 'Clear memory',
37
+ altNames: ['c'],
38
+ action: async () => { },
39
+ kind: CommandKind.BUILT_IN,
40
+ },
41
+ ],
42
+ kind: CommandKind.BUILT_IN,
43
+ },
44
+ ];
45
+ describe('parseSlashCommand', () => {
46
+ it('should parse a simple command without arguments', () => {
47
+ const result = parseSlashCommand('/help', mockCommands);
48
+ expect(result.commandToExecute?.name).toBe('help');
49
+ expect(result.args).toBe('');
50
+ expect(result.canonicalPath).toEqual(['help']);
51
+ });
52
+ it('should parse a simple command with arguments', () => {
53
+ const result = parseSlashCommand('/commit -m "Initial commit"', mockCommands);
54
+ expect(result.commandToExecute?.name).toBe('commit');
55
+ expect(result.args).toBe('-m "Initial commit"');
56
+ expect(result.canonicalPath).toEqual(['commit']);
57
+ });
58
+ it('should parse a subcommand', () => {
59
+ const result = parseSlashCommand('/memory add', mockCommands);
60
+ expect(result.commandToExecute?.name).toBe('add');
61
+ expect(result.args).toBe('');
62
+ expect(result.canonicalPath).toEqual(['memory', 'add']);
63
+ });
64
+ it('should parse a subcommand with arguments', () => {
65
+ const result = parseSlashCommand('/memory add some important data', mockCommands);
66
+ expect(result.commandToExecute?.name).toBe('add');
67
+ expect(result.args).toBe('some important data');
68
+ expect(result.canonicalPath).toEqual(['memory', 'add']);
69
+ });
70
+ it('should handle a command alias', () => {
71
+ const result = parseSlashCommand('/mem add some data', mockCommands);
72
+ expect(result.commandToExecute?.name).toBe('add');
73
+ expect(result.args).toBe('some data');
74
+ expect(result.canonicalPath).toEqual(['memory', 'add']);
75
+ });
76
+ it('should handle a subcommand alias', () => {
77
+ const result = parseSlashCommand('/memory c', mockCommands);
78
+ expect(result.commandToExecute?.name).toBe('clear');
79
+ expect(result.args).toBe('');
80
+ expect(result.canonicalPath).toEqual(['memory', 'clear']);
81
+ });
82
+ it('should return undefined for an unknown command', () => {
83
+ const result = parseSlashCommand('/unknown', mockCommands);
84
+ expect(result.commandToExecute).toBeUndefined();
85
+ expect(result.args).toBe('unknown');
86
+ expect(result.canonicalPath).toEqual([]);
87
+ });
88
+ it('should return the parent command if subcommand is unknown', () => {
89
+ const result = parseSlashCommand('/memory unknownsub some args', mockCommands);
90
+ expect(result.commandToExecute?.name).toBe('memory');
91
+ expect(result.args).toBe('unknownsub some args');
92
+ expect(result.canonicalPath).toEqual(['memory']);
93
+ });
94
+ it('should handle extra whitespace', () => {
95
+ const result = parseSlashCommand(' /memory add some data ', mockCommands);
96
+ expect(result.commandToExecute?.name).toBe('add');
97
+ expect(result.args).toBe('some data');
98
+ expect(result.canonicalPath).toEqual(['memory', 'add']);
99
+ });
100
+ it('should return undefined if query does not start with a slash', () => {
101
+ const result = parseSlashCommand('help', mockCommands);
102
+ expect(result.commandToExecute).toBeUndefined();
103
+ });
104
+ it('should handle an empty query', () => {
105
+ const result = parseSlashCommand('', mockCommands);
106
+ expect(result.commandToExecute).toBeUndefined();
107
+ });
108
+ it('should handle a query with only a slash', () => {
109
+ const result = parseSlashCommand('/', mockCommands);
110
+ expect(result.commandToExecute).toBeUndefined();
111
+ expect(result.args).toBe('');
112
+ expect(result.canonicalPath).toEqual([]);
113
+ });
114
+ });
115
+ //# sourceMappingURL=commands.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.test.js","sourceRoot":"","sources":["../../../src/utils/commands.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * Updates a JSON file while preserving comments and formatting.
8
+ */
9
+ export declare function updateSettingsFilePreservingFormat(filePath: string, updates: Record<string, unknown>): void;
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import * as fs from 'node:fs';
7
+ import { parse, stringify } from 'comment-json';
8
+ /**
9
+ * Updates a JSON file while preserving comments and formatting.
10
+ */
11
+ export function updateSettingsFilePreservingFormat(filePath, updates) {
12
+ if (!fs.existsSync(filePath)) {
13
+ fs.writeFileSync(filePath, JSON.stringify(updates, null, 2), 'utf-8');
14
+ return;
15
+ }
16
+ const originalContent = fs.readFileSync(filePath, 'utf-8');
17
+ let parsed;
18
+ try {
19
+ parsed = parse(originalContent);
20
+ }
21
+ catch (error) {
22
+ console.error('Error parsing settings file:', error);
23
+ console.error('Settings file may be corrupted. Please check the JSON syntax.');
24
+ return;
25
+ }
26
+ const updatedStructure = applyUpdates(parsed, updates);
27
+ const updatedContent = stringify(updatedStructure, null, 2);
28
+ fs.writeFileSync(filePath, updatedContent, 'utf-8');
29
+ }
30
+ function applyUpdates(current, updates) {
31
+ const result = current;
32
+ for (const key of Object.getOwnPropertyNames(updates)) {
33
+ const value = updates[key];
34
+ if (typeof value === 'object' &&
35
+ value !== null &&
36
+ !Array.isArray(value) &&
37
+ typeof result[key] === 'object' &&
38
+ result[key] !== null &&
39
+ !Array.isArray(result[key])) {
40
+ result[key] = applyUpdates(result[key], value);
41
+ }
42
+ else {
43
+ result[key] = value;
44
+ }
45
+ }
46
+ return result;
47
+ }
48
+ //# sourceMappingURL=commentJson.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commentJson.js","sourceRoot":"","sources":["../../../src/utils/commentJson.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEhD;;GAEG;AACH,MAAM,UAAU,kCAAkC,CAChD,QAAgB,EAChB,OAAgC;IAEhC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;QACtE,OAAO;IACT,CAAC;IAED,MAAM,eAAe,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAE3D,IAAI,MAA+B,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,GAAG,KAAK,CAAC,eAAe,CAA4B,CAAC;IAC7D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;QACrD,OAAO,CAAC,KAAK,CACX,+DAA+D,CAChE,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,gBAAgB,GAAG,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvD,MAAM,cAAc,GAAG,SAAS,CAAC,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAE5D,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;AACtD,CAAC;AAED,SAAS,YAAY,CACnB,OAAgC,EAChC,OAAgC;IAEhC,MAAM,MAAM,GAAG,OAAO,CAAC;IAEvB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,mBAAmB,CAAC,OAAO,CAAC,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC3B,IACE,OAAO,KAAK,KAAK,QAAQ;YACzB,KAAK,KAAK,IAAI;YACd,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YACrB,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,QAAQ;YAC/B,MAAM,CAAC,GAAG,CAAC,KAAK,IAAI;YACpB,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAC3B,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,GAAG,YAAY,CACxB,MAAM,CAAC,GAAG,CAA4B,EACtC,KAAgC,CACjC,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
@@ -0,0 +1,146 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
7
+ import * as fs from 'node:fs';
8
+ import * as path from 'node:path';
9
+ import * as os from 'node:os';
10
+ import { updateSettingsFilePreservingFormat } from './commentJson.js';
11
+ describe('commentJson', () => {
12
+ let tempDir;
13
+ let testFilePath;
14
+ beforeEach(() => {
15
+ // Create a temporary directory for test files
16
+ tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'preserve-format-test-'));
17
+ testFilePath = path.join(tempDir, 'settings.json');
18
+ });
19
+ afterEach(() => {
20
+ // Clean up temporary directory
21
+ if (fs.existsSync(tempDir)) {
22
+ fs.rmSync(tempDir, { recursive: true, force: true });
23
+ }
24
+ });
25
+ describe('updateSettingsFilePreservingFormat', () => {
26
+ it('should preserve comments when updating settings', () => {
27
+ const originalContent = `{
28
+ // Model configuration
29
+ "model": "gemini-2.5-pro",
30
+ "ui": {
31
+ // Theme setting
32
+ "theme": "dark"
33
+ }
34
+ }`;
35
+ fs.writeFileSync(testFilePath, originalContent, 'utf-8');
36
+ updateSettingsFilePreservingFormat(testFilePath, {
37
+ model: 'gemini-2.5-flash',
38
+ });
39
+ const updatedContent = fs.readFileSync(testFilePath, 'utf-8');
40
+ expect(updatedContent).toContain('// Model configuration');
41
+ expect(updatedContent).toContain('// Theme setting');
42
+ expect(updatedContent).toContain('"model": "gemini-2.5-flash"');
43
+ expect(updatedContent).toContain('"theme": "dark"');
44
+ });
45
+ it('should handle nested object updates', () => {
46
+ const originalContent = `{
47
+ "ui": {
48
+ "theme": "dark",
49
+ "showLineNumbers": true
50
+ }
51
+ }`;
52
+ fs.writeFileSync(testFilePath, originalContent, 'utf-8');
53
+ updateSettingsFilePreservingFormat(testFilePath, {
54
+ ui: {
55
+ theme: 'light',
56
+ showLineNumbers: true,
57
+ },
58
+ });
59
+ const updatedContent = fs.readFileSync(testFilePath, 'utf-8');
60
+ expect(updatedContent).toContain('"theme": "light"');
61
+ expect(updatedContent).toContain('"showLineNumbers": true');
62
+ });
63
+ it('should add new fields while preserving existing structure', () => {
64
+ const originalContent = `{
65
+ // Existing config
66
+ "model": "gemini-2.5-pro"
67
+ }`;
68
+ fs.writeFileSync(testFilePath, originalContent, 'utf-8');
69
+ updateSettingsFilePreservingFormat(testFilePath, {
70
+ model: 'gemini-2.5-pro',
71
+ newField: 'newValue',
72
+ });
73
+ const updatedContent = fs.readFileSync(testFilePath, 'utf-8');
74
+ expect(updatedContent).toContain('// Existing config');
75
+ expect(updatedContent).toContain('"newField": "newValue"');
76
+ });
77
+ it('should create file if it does not exist', () => {
78
+ updateSettingsFilePreservingFormat(testFilePath, {
79
+ model: 'gemini-2.5-pro',
80
+ });
81
+ expect(fs.existsSync(testFilePath)).toBe(true);
82
+ const content = fs.readFileSync(testFilePath, 'utf-8');
83
+ expect(content).toContain('"model": "gemini-2.5-pro"');
84
+ });
85
+ it('should handle complex real-world scenario', () => {
86
+ const complexContent = `{
87
+ // Settings
88
+ "model": "gemini-2.5-pro",
89
+ "mcpServers": {
90
+ // Active server
91
+ "context7": {
92
+ "headers": {
93
+ "API_KEY": "test-key" // API key
94
+ }
95
+ }
96
+ }
97
+ }`;
98
+ fs.writeFileSync(testFilePath, complexContent, 'utf-8');
99
+ updateSettingsFilePreservingFormat(testFilePath, {
100
+ model: 'gemini-2.5-flash',
101
+ mcpServers: {
102
+ context7: {
103
+ headers: {
104
+ API_KEY: 'new-test-key',
105
+ },
106
+ },
107
+ },
108
+ newSection: {
109
+ setting: 'value',
110
+ },
111
+ });
112
+ const updatedContent = fs.readFileSync(testFilePath, 'utf-8');
113
+ // Verify comments preserved
114
+ expect(updatedContent).toContain('// Settings');
115
+ expect(updatedContent).toContain('// Active server');
116
+ expect(updatedContent).toContain('// API key');
117
+ // Verify updates applied
118
+ expect(updatedContent).toContain('"model": "gemini-2.5-flash"');
119
+ expect(updatedContent).toContain('"newSection"');
120
+ expect(updatedContent).toContain('"API_KEY": "new-test-key"');
121
+ });
122
+ it('should handle corrupted JSON files gracefully', () => {
123
+ const corruptedContent = `{
124
+ "model": "gemini-2.5-pro",
125
+ "ui": {
126
+ "theme": "dark"
127
+ // Missing closing brace
128
+ `;
129
+ fs.writeFileSync(testFilePath, corruptedContent, 'utf-8');
130
+ const consoleSpy = vi
131
+ .spyOn(console, 'error')
132
+ .mockImplementation(() => { });
133
+ expect(() => {
134
+ updateSettingsFilePreservingFormat(testFilePath, {
135
+ model: 'gemini-2.5-flash',
136
+ });
137
+ }).not.toThrow();
138
+ expect(consoleSpy).toHaveBeenCalledWith('Error parsing settings file:', expect.any(Error));
139
+ expect(consoleSpy).toHaveBeenCalledWith('Settings file may be corrupted. Please check the JSON syntax.');
140
+ const unchangedContent = fs.readFileSync(testFilePath, 'utf-8');
141
+ expect(unchangedContent).toBe(corruptedContent);
142
+ consoleSpy.mockRestore();
143
+ });
144
+ });
145
+ });
146
+ //# sourceMappingURL=commentJson.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commentJson.test.js","sourceRoot":"","sources":["../../../src/utils/commentJson.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * Exit code used to signal that the CLI should be relaunched.
8
+ */
9
+ export declare const RELAUNCH_EXIT_CODE = 42;
10
+ /**
11
+ * Exits the process with a special code to signal that the parent process should relaunch it.
12
+ */
13
+ export declare function relaunchApp(): Promise<void>;
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { runExitCleanup } from './cleanup.js';
7
+ /**
8
+ * Exit code used to signal that the CLI should be relaunched.
9
+ */
10
+ export const RELAUNCH_EXIT_CODE = 42;
11
+ /**
12
+ * Exits the process with a special code to signal that the parent process should relaunch it.
13
+ */
14
+ export async function relaunchApp() {
15
+ await runExitCleanup();
16
+ process.exit(RELAUNCH_EXIT_CODE);
17
+ }
18
+ //# sourceMappingURL=processUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processUtils.js","sourceRoot":"","sources":["../../../src/utils/processUtils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,cAAc,EAAE,CAAC;IACvB,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;AACnC,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { vi } from 'vitest';
7
+ import { RELAUNCH_EXIT_CODE, relaunchApp } from './processUtils.js';
8
+ import * as cleanup from './cleanup.js';
9
+ describe('processUtils', () => {
10
+ const processExit = vi
11
+ .spyOn(process, 'exit')
12
+ .mockReturnValue(undefined);
13
+ const runExitCleanup = vi.spyOn(cleanup, 'runExitCleanup');
14
+ it('should run cleanup and exit with the relaunch code', async () => {
15
+ await relaunchApp();
16
+ expect(runExitCleanup).toHaveBeenCalledTimes(1);
17
+ expect(processExit).toHaveBeenCalledWith(RELAUNCH_EXIT_CODE);
18
+ });
19
+ });
20
+ //# sourceMappingURL=processUtils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"processUtils.test.js","sourceRoot":"","sources":["../../../src/utils/processUtils.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAExC,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,MAAM,WAAW,GAAG,EAAE;SACnB,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC;SACtB,eAAe,CAAC,SAAkB,CAAC,CAAC;IACvC,MAAM,cAAc,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC;IAE3D,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,WAAW,EAAE,CAAC;QACpB,MAAM,CAAC,cAAc,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAChD,MAAM,CAAC,WAAW,CAAC,CAAC,oBAAoB,CAAC,kBAAkB,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -4,4 +4,4 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import type { Config, SandboxConfig } from '@google/gemini-cli-core';
7
- export declare function start_sandbox(config: SandboxConfig, nodeArgs?: string[], cliConfig?: Config, cliArgs?: string[]): Promise<void>;
7
+ export declare function start_sandbox(config: SandboxConfig, nodeArgs?: string[], cliConfig?: Config, cliArgs?: string[]): Promise<number>;
@@ -264,11 +264,17 @@ export async function start_sandbox(config, nodeArgs = [], cliConfig, cliArgs =
264
264
  await execAsync(`until timeout 0.25 curl -s http://localhost:8877; do sleep 0.25; done`);
265
265
  }
266
266
  // spawn child and let it inherit stdio
267
+ process.stdin.pause();
267
268
  sandboxProcess = spawn(config.command, args, {
268
269
  stdio: 'inherit',
269
270
  });
270
- await new Promise((resolve) => sandboxProcess?.on('close', resolve));
271
- return;
271
+ return new Promise((resolve, reject) => {
272
+ sandboxProcess?.on('error', reject);
273
+ sandboxProcess?.on('close', (code) => {
274
+ process.stdin.resume();
275
+ resolve(code ?? 1);
276
+ });
277
+ });
272
278
  }
273
279
  console.error(`hopping into sandbox (command: ${config.command}) ...`);
274
280
  // determine full path for gemini-cli to distinguish linked vs installed setting
@@ -598,18 +604,21 @@ export async function start_sandbox(config, nodeArgs = [], cliConfig, cliArgs =
598
604
  await execAsync(`${config.command} network connect ${SANDBOX_NETWORK_NAME} ${SANDBOX_PROXY_NAME}`);
599
605
  }
600
606
  // spawn child and let it inherit stdio
607
+ process.stdin.pause();
601
608
  sandboxProcess = spawn(config.command, args, {
602
609
  stdio: 'inherit',
603
610
  });
604
- sandboxProcess.on('error', (err) => {
605
- console.error('Sandbox process error:', err);
606
- });
607
- await new Promise((resolve) => {
611
+ return new Promise((resolve, reject) => {
612
+ sandboxProcess.on('error', (err) => {
613
+ console.error('Sandbox process error:', err);
614
+ reject(err);
615
+ });
608
616
  sandboxProcess?.on('close', (code, signal) => {
609
- if (code !== 0) {
617
+ process.stdin.resume();
618
+ if (code !== 0 && code !== null) {
610
619
  console.log(`Sandbox process exited with code: ${code}, signal: ${signal}`);
611
620
  }
612
- resolve();
621
+ resolve(code ?? 1);
613
622
  });
614
623
  });
615
624
  }