@google/gemini-cli-core 0.39.0-preview.2 → 0.40.0-preview.0

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 (259) hide show
  1. package/dist/docs/changelogs/index.md +21 -0
  2. package/dist/docs/changelogs/latest.md +253 -407
  3. package/dist/docs/changelogs/preview.md +236 -247
  4. package/dist/docs/cli/auto-memory.md +143 -0
  5. package/dist/docs/cli/enterprise.md +1 -1
  6. package/dist/docs/cli/plan-mode.md +3 -1
  7. package/dist/docs/cli/settings.md +29 -25
  8. package/dist/docs/cli/system-prompt.md +6 -6
  9. package/dist/docs/cli/telemetry.md +18 -11
  10. package/dist/docs/cli/tutorials/memory-management.md +2 -0
  11. package/dist/docs/get-started/{authentication.md → authentication.mdx} +139 -93
  12. package/dist/docs/get-started/index.md +3 -2
  13. package/dist/docs/get-started/installation.mdx +201 -0
  14. package/dist/docs/index.md +2 -2
  15. package/dist/docs/reference/configuration.md +88 -12
  16. package/dist/docs/reference/policy-engine.md +18 -12
  17. package/dist/docs/reference/tools.md +22 -0
  18. package/dist/docs/sidebar.json +13 -1
  19. package/dist/docs/tools/mcp-resources.md +44 -0
  20. package/dist/docs/tools/mcp-server.md +2 -1
  21. package/dist/docs/tools/tracker.md +61 -0
  22. package/dist/src/agents/agent-tool.js +1 -0
  23. package/dist/src/agents/agent-tool.js.map +1 -1
  24. package/dist/src/agents/agentLoader.d.ts +4 -4
  25. package/dist/src/agents/generalist-agent.js +3 -2
  26. package/dist/src/agents/generalist-agent.js.map +1 -1
  27. package/dist/src/agents/local-executor.js +4 -1
  28. package/dist/src/agents/local-executor.js.map +1 -1
  29. package/dist/src/agents/registry.js +0 -8
  30. package/dist/src/agents/registry.js.map +1 -1
  31. package/dist/src/agents/skill-extraction-agent.d.ts +3 -2
  32. package/dist/src/agents/skill-extraction-agent.js +72 -67
  33. package/dist/src/agents/skill-extraction-agent.js.map +1 -1
  34. package/dist/src/agents/skill-extraction-agent.test.js +54 -0
  35. package/dist/src/agents/skill-extraction-agent.test.js.map +1 -0
  36. package/dist/src/config/config.d.ts +21 -6
  37. package/dist/src/config/config.js +103 -19
  38. package/dist/src/config/config.js.map +1 -1
  39. package/dist/src/config/config.test.js +262 -6
  40. package/dist/src/config/config.test.js.map +1 -1
  41. package/dist/src/config/constants.d.ts +1 -0
  42. package/dist/src/config/constants.js +2 -0
  43. package/dist/src/config/constants.js.map +1 -1
  44. package/dist/src/config/memory.js +1 -1
  45. package/dist/src/config/memory.js.map +1 -1
  46. package/dist/src/config/path-validation.test.js +15 -6
  47. package/dist/src/config/path-validation.test.js.map +1 -1
  48. package/dist/src/config/projectRegistry.js +113 -32
  49. package/dist/src/config/projectRegistry.js.map +1 -1
  50. package/dist/src/config/projectRegistry.test.js +51 -0
  51. package/dist/src/config/projectRegistry.test.js.map +1 -1
  52. package/dist/src/config/storage.d.ts +3 -1
  53. package/dist/src/config/storage.js +6 -0
  54. package/dist/src/config/storage.js.map +1 -1
  55. package/dist/src/config/storage.test.js +12 -0
  56. package/dist/src/config/storage.test.js.map +1 -1
  57. package/dist/src/core/contentGenerator.d.ts +8 -1
  58. package/dist/src/core/contentGenerator.js +46 -4
  59. package/dist/src/core/contentGenerator.js.map +1 -1
  60. package/dist/src/core/contentGenerator.test.js +174 -8
  61. package/dist/src/core/contentGenerator.test.js.map +1 -1
  62. package/dist/src/core/geminiChat.test.js +1 -0
  63. package/dist/src/core/geminiChat.test.js.map +1 -1
  64. package/dist/src/core/geminiChat_network_retry.test.js +42 -0
  65. package/dist/src/core/geminiChat_network_retry.test.js.map +1 -1
  66. package/dist/src/core/localLiteRtLmClient.js +2 -0
  67. package/dist/src/core/localLiteRtLmClient.js.map +1 -1
  68. package/dist/src/core/localLiteRtLmClient.test.js +7 -0
  69. package/dist/src/core/localLiteRtLmClient.test.js.map +1 -1
  70. package/dist/src/core/loggingContentGenerator.js +3 -0
  71. package/dist/src/core/loggingContentGenerator.js.map +1 -1
  72. package/dist/src/core/loggingContentGenerator.test.js +1 -0
  73. package/dist/src/core/loggingContentGenerator.test.js.map +1 -1
  74. package/dist/src/core/prompts.d.ts +1 -1
  75. package/dist/src/core/prompts.js +2 -2
  76. package/dist/src/core/prompts.js.map +1 -1
  77. package/dist/src/core/prompts.test.js +2 -2
  78. package/dist/src/core/prompts.test.js.map +1 -1
  79. package/dist/src/generated/git-commit.d.ts +2 -2
  80. package/dist/src/generated/git-commit.js +2 -2
  81. package/dist/src/ide/ide-client.js +3 -4
  82. package/dist/src/ide/ide-client.js.map +1 -1
  83. package/dist/src/policy/policies/read-only.toml +4 -1
  84. package/dist/src/policy/policy-engine.js +4 -0
  85. package/dist/src/policy/policy-engine.js.map +1 -1
  86. package/dist/src/policy/policy-engine.test.js +25 -0
  87. package/dist/src/policy/policy-engine.test.js.map +1 -1
  88. package/dist/src/policy/toml-loader.test.js +5 -0
  89. package/dist/src/policy/toml-loader.test.js.map +1 -1
  90. package/dist/src/prompts/promptProvider.d.ts +1 -1
  91. package/dist/src/prompts/promptProvider.js +15 -7
  92. package/dist/src/prompts/promptProvider.js.map +1 -1
  93. package/dist/src/prompts/promptProvider.test.js +31 -1
  94. package/dist/src/prompts/promptProvider.test.js.map +1 -1
  95. package/dist/src/prompts/snippets-memory-v2.test.js +94 -0
  96. package/dist/src/prompts/snippets-memory-v2.test.js.map +1 -0
  97. package/dist/src/prompts/snippets.d.ts +19 -1
  98. package/dist/src/prompts/snippets.js +24 -3
  99. package/dist/src/prompts/snippets.js.map +1 -1
  100. package/dist/src/prompts/snippets.legacy.d.ts +6 -1
  101. package/dist/src/prompts/snippets.legacy.js +10 -3
  102. package/dist/src/prompts/snippets.legacy.js.map +1 -1
  103. package/dist/src/sandbox/linux/LinuxSandboxManager.js +16 -2
  104. package/dist/src/sandbox/linux/LinuxSandboxManager.js.map +1 -1
  105. package/dist/src/sandbox/linux/bwrapArgsBuilder.js +64 -36
  106. package/dist/src/sandbox/linux/bwrapArgsBuilder.js.map +1 -1
  107. package/dist/src/sandbox/linux/bwrapArgsBuilder.test.js +3 -3
  108. package/dist/src/sandbox/linux/bwrapArgsBuilder.test.js.map +1 -1
  109. package/dist/src/sandbox/macos/MacOsSandboxManager.js +13 -1
  110. package/dist/src/sandbox/macos/MacOsSandboxManager.js.map +1 -1
  111. package/dist/src/sandbox/macos/seatbeltArgsBuilder.js +61 -42
  112. package/dist/src/sandbox/macos/seatbeltArgsBuilder.js.map +1 -1
  113. package/dist/src/sandbox/windows/WindowsSandboxManager.js +12 -1
  114. package/dist/src/sandbox/windows/WindowsSandboxManager.js.map +1 -1
  115. package/dist/src/scheduler/policy.js +1 -2
  116. package/dist/src/scheduler/policy.js.map +1 -1
  117. package/dist/src/scheduler/policy.test.js +35 -2
  118. package/dist/src/scheduler/policy.test.js.map +1 -1
  119. package/dist/src/scheduler/scheduler.js +1 -0
  120. package/dist/src/scheduler/scheduler.js.map +1 -1
  121. package/dist/src/scheduler/scheduler.test.js +2 -0
  122. package/dist/src/scheduler/scheduler.test.js.map +1 -1
  123. package/dist/src/scheduler/scheduler_hooks.test.js +1 -0
  124. package/dist/src/scheduler/scheduler_hooks.test.js.map +1 -1
  125. package/dist/src/scheduler/scheduler_parallel.test.js +1 -0
  126. package/dist/src/scheduler/scheduler_parallel.test.js.map +1 -1
  127. package/dist/src/scheduler/tool-executor.js +1 -0
  128. package/dist/src/scheduler/tool-executor.js.map +1 -1
  129. package/dist/src/services/chatRecordingService.d.ts +1 -0
  130. package/dist/src/services/chatRecordingService.js +48 -19
  131. package/dist/src/services/chatRecordingService.js.map +1 -1
  132. package/dist/src/services/memoryService.d.ts +15 -1
  133. package/dist/src/services/memoryService.js +276 -57
  134. package/dist/src/services/memoryService.js.map +1 -1
  135. package/dist/src/services/memoryService.test.js +296 -2
  136. package/dist/src/services/memoryService.test.js.map +1 -1
  137. package/dist/src/services/sandboxManager.integration.test.js +204 -0
  138. package/dist/src/services/sandboxManager.integration.test.js.map +1 -1
  139. package/dist/src/services/sandboxManager.js +16 -0
  140. package/dist/src/services/sandboxManager.js.map +1 -1
  141. package/dist/src/services/sessionSummaryUtils.d.ts +1 -1
  142. package/dist/src/services/sessionSummaryUtils.js +111 -38
  143. package/dist/src/services/sessionSummaryUtils.js.map +1 -1
  144. package/dist/src/services/sessionSummaryUtils.test.js +204 -51
  145. package/dist/src/services/sessionSummaryUtils.test.js.map +1 -1
  146. package/dist/src/services/shellExecutionService.js +7 -1
  147. package/dist/src/services/shellExecutionService.js.map +1 -1
  148. package/dist/src/telemetry/config.js +3 -0
  149. package/dist/src/telemetry/config.js.map +1 -1
  150. package/dist/src/telemetry/conseca-logger.test.js +1 -0
  151. package/dist/src/telemetry/conseca-logger.test.js.map +1 -1
  152. package/dist/src/telemetry/loggers.test.js +72 -4
  153. package/dist/src/telemetry/loggers.test.js.map +1 -1
  154. package/dist/src/telemetry/memory-monitor.d.ts +1 -0
  155. package/dist/src/telemetry/memory-monitor.js +8 -1
  156. package/dist/src/telemetry/memory-monitor.js.map +1 -1
  157. package/dist/src/telemetry/memory-monitor.test.js +6 -1
  158. package/dist/src/telemetry/memory-monitor.test.js.map +1 -1
  159. package/dist/src/telemetry/trace.d.ts +1 -0
  160. package/dist/src/telemetry/trace.js +33 -13
  161. package/dist/src/telemetry/trace.js.map +1 -1
  162. package/dist/src/telemetry/trace.test.js +50 -10
  163. package/dist/src/telemetry/trace.test.js.map +1 -1
  164. package/dist/src/telemetry/types.js +11 -4
  165. package/dist/src/telemetry/types.js.map +1 -1
  166. package/dist/src/tools/definitions/base-declarations.d.ts +2 -0
  167. package/dist/src/tools/definitions/base-declarations.js +3 -0
  168. package/dist/src/tools/definitions/base-declarations.js.map +1 -1
  169. package/dist/src/tools/definitions/coreTools.d.ts +3 -1
  170. package/dist/src/tools/definitions/coreTools.js +13 -1
  171. package/dist/src/tools/definitions/coreTools.js.map +1 -1
  172. package/dist/src/tools/definitions/model-family-sets/default-legacy.js +29 -1
  173. package/dist/src/tools/definitions/model-family-sets/default-legacy.js.map +1 -1
  174. package/dist/src/tools/definitions/model-family-sets/gemini-3.js +29 -1
  175. package/dist/src/tools/definitions/model-family-sets/gemini-3.js.map +1 -1
  176. package/dist/src/tools/definitions/types.d.ts +2 -0
  177. package/dist/src/tools/get-internal-docs.js +5 -2
  178. package/dist/src/tools/get-internal-docs.js.map +1 -1
  179. package/dist/src/tools/list-mcp-resources.d.ts +24 -0
  180. package/dist/src/tools/list-mcp-resources.js +74 -0
  181. package/dist/src/tools/list-mcp-resources.js.map +1 -0
  182. package/dist/src/tools/list-mcp-resources.test.d.ts +6 -0
  183. package/dist/src/tools/list-mcp-resources.test.js +79 -0
  184. package/dist/src/tools/list-mcp-resources.test.js.map +1 -0
  185. package/dist/src/tools/mcp-client-manager.d.ts +3 -1
  186. package/dist/src/tools/mcp-client-manager.js +24 -1
  187. package/dist/src/tools/mcp-client-manager.js.map +1 -1
  188. package/dist/src/tools/mcp-client-manager.test.js +43 -0
  189. package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
  190. package/dist/src/tools/memoryTool.d.ts +2 -1
  191. package/dist/src/tools/memoryTool.js +42 -13
  192. package/dist/src/tools/memoryTool.js.map +1 -1
  193. package/dist/src/tools/memoryTool.test.js +23 -3
  194. package/dist/src/tools/memoryTool.test.js.map +1 -1
  195. package/dist/src/tools/read-mcp-resource.d.ts +25 -0
  196. package/dist/src/tools/read-mcp-resource.js +120 -0
  197. package/dist/src/tools/read-mcp-resource.js.map +1 -0
  198. package/dist/src/tools/read-mcp-resource.test.d.ts +6 -0
  199. package/dist/src/tools/read-mcp-resource.test.js +110 -0
  200. package/dist/src/tools/read-mcp-resource.test.js.map +1 -0
  201. package/dist/src/tools/ripGrep.d.ts +3 -2
  202. package/dist/src/tools/ripGrep.js +25 -54
  203. package/dist/src/tools/ripGrep.js.map +1 -1
  204. package/dist/src/tools/ripGrep.test.js +73 -131
  205. package/dist/src/tools/ripGrep.test.js.map +1 -1
  206. package/dist/src/tools/shell.js +38 -12
  207. package/dist/src/tools/shell.js.map +1 -1
  208. package/dist/src/tools/shell.test.js +410 -25
  209. package/dist/src/tools/shell.test.js.map +1 -1
  210. package/dist/src/tools/tool-error.d.ts +1 -0
  211. package/dist/src/tools/tool-error.js +1 -0
  212. package/dist/src/tools/tool-error.js.map +1 -1
  213. package/dist/src/tools/tool-names.d.ts +4 -4
  214. package/dist/src/tools/tool-names.js +6 -2
  215. package/dist/src/tools/tool-names.js.map +1 -1
  216. package/dist/src/tools/tool-registry.js +8 -1
  217. package/dist/src/tools/tool-registry.js.map +1 -1
  218. package/dist/src/utils/filesearch/fileSearch.d.ts +2 -0
  219. package/dist/src/utils/filesearch/fileSearch.js +97 -6
  220. package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
  221. package/dist/src/utils/filesearch/fileSearch.test.js +54 -0
  222. package/dist/src/utils/filesearch/fileSearch.test.js.map +1 -1
  223. package/dist/src/utils/filesearch/fileWatcher.d.ts +25 -0
  224. package/dist/src/utils/filesearch/fileWatcher.js +86 -0
  225. package/dist/src/utils/filesearch/fileWatcher.js.map +1 -0
  226. package/dist/src/utils/filesearch/fileWatcher.test.d.ts +6 -0
  227. package/dist/src/utils/filesearch/fileWatcher.test.js +142 -0
  228. package/dist/src/utils/filesearch/fileWatcher.test.js.map +1 -0
  229. package/dist/src/utils/gitIgnoreParser.js +1 -1
  230. package/dist/src/utils/gitIgnoreParser.js.map +1 -1
  231. package/dist/src/utils/ignoreFileParser.js +1 -1
  232. package/dist/src/utils/ignoreFileParser.js.map +1 -1
  233. package/dist/src/utils/memoryDiscovery.js +15 -5
  234. package/dist/src/utils/memoryDiscovery.js.map +1 -1
  235. package/dist/src/utils/retry.js +18 -6
  236. package/dist/src/utils/retry.js.map +1 -1
  237. package/dist/src/utils/retry.test.js +30 -0
  238. package/dist/src/utils/retry.test.js.map +1 -1
  239. package/dist/src/utils/shell-utils.d.ts +1 -0
  240. package/dist/src/utils/shell-utils.js +106 -0
  241. package/dist/src/utils/shell-utils.js.map +1 -1
  242. package/dist/tsconfig.tsbuildinfo +1 -1
  243. package/package.json +5 -3
  244. package/vendor/ripgrep/rg-darwin-arm64 +0 -0
  245. package/vendor/ripgrep/rg-darwin-x64 +0 -0
  246. package/vendor/ripgrep/rg-linux-arm64 +0 -0
  247. package/vendor/ripgrep/rg-linux-x64 +0 -0
  248. package/vendor/ripgrep/rg-win32-x64.exe +0 -0
  249. package/dist/docs/get-started/installation.md +0 -181
  250. package/dist/google-gemini-cli-core-0.39.0-preview.1.tgz +0 -0
  251. package/dist/src/agents/memory-manager-agent.d.ts +0 -25
  252. package/dist/src/agents/memory-manager-agent.js +0 -138
  253. package/dist/src/agents/memory-manager-agent.js.map +0 -1
  254. package/dist/src/agents/memory-manager-agent.test.js +0 -123
  255. package/dist/src/agents/memory-manager-agent.test.js.map +0 -1
  256. package/dist/src/prompts/snippets-memory-manager.test.js +0 -31
  257. package/dist/src/prompts/snippets-memory-manager.test.js.map +0 -1
  258. /package/dist/src/agents/{memory-manager-agent.test.d.ts → skill-extraction-agent.test.d.ts} +0 -0
  259. /package/dist/src/prompts/{snippets-memory-manager.test.d.ts → snippets-memory-v2.test.d.ts} +0 -0
@@ -270,6 +270,22 @@ describe('Server Config (config.ts)', () => {
270
270
  backgroundCompletionBehavior: 'notify',
271
271
  }));
272
272
  });
273
+ it('should ignore properties that are explicitly undefined and preserve existing values', () => {
274
+ const config = new Config(baseParams);
275
+ config.setShellExecutionConfig({
276
+ terminalWidth: 80,
277
+ showColor: true,
278
+ });
279
+ expect(config.getShellExecutionConfig().terminalWidth).toBe(80);
280
+ expect(config.getShellExecutionConfig().showColor).toBe(true);
281
+ // Provide undefined for terminalWidth, which should be ignored
282
+ config.setShellExecutionConfig({
283
+ terminalWidth: undefined,
284
+ showColor: false,
285
+ });
286
+ expect(config.getShellExecutionConfig().terminalWidth).toBe(80); // Should still be 80, not undefined
287
+ expect(config.getShellExecutionConfig().showColor).toBe(false); // Should be updated
288
+ });
273
289
  });
274
290
  beforeEach(() => {
275
291
  // Reset mocks if necessary
@@ -551,6 +567,56 @@ describe('Server Config (config.ts)', () => {
551
567
  expect(config.getGemini31FlashLiteLaunchedSync()).toBe(true);
552
568
  });
553
569
  });
570
+ describe('getProModelNoAccessSync', () => {
571
+ it('should return experiment value for AuthType.LOGIN_WITH_GOOGLE', async () => {
572
+ vi.mocked(getExperiments).mockResolvedValue({
573
+ experimentIds: [],
574
+ flags: {
575
+ [ExperimentFlags.PRO_MODEL_NO_ACCESS]: {
576
+ boolValue: true,
577
+ },
578
+ },
579
+ });
580
+ const config = new Config(baseParams);
581
+ vi.mocked(createContentGeneratorConfig).mockResolvedValue({
582
+ authType: AuthType.LOGIN_WITH_GOOGLE,
583
+ });
584
+ await config.refreshAuth(AuthType.LOGIN_WITH_GOOGLE);
585
+ expect(config.getProModelNoAccessSync()).toBe(true);
586
+ });
587
+ it('should return experiment value for AuthType.COMPUTE_ADC', async () => {
588
+ vi.mocked(getExperiments).mockResolvedValue({
589
+ experimentIds: [],
590
+ flags: {
591
+ [ExperimentFlags.PRO_MODEL_NO_ACCESS]: {
592
+ boolValue: true,
593
+ },
594
+ },
595
+ });
596
+ const config = new Config(baseParams);
597
+ vi.mocked(createContentGeneratorConfig).mockResolvedValue({
598
+ authType: AuthType.COMPUTE_ADC,
599
+ });
600
+ await config.refreshAuth(AuthType.COMPUTE_ADC);
601
+ expect(config.getProModelNoAccessSync()).toBe(true);
602
+ });
603
+ it('should return false for other auth types even if experiment is true', async () => {
604
+ vi.mocked(getExperiments).mockResolvedValue({
605
+ experimentIds: [],
606
+ flags: {
607
+ [ExperimentFlags.PRO_MODEL_NO_ACCESS]: {
608
+ boolValue: true,
609
+ },
610
+ },
611
+ });
612
+ const config = new Config(baseParams);
613
+ vi.mocked(createContentGeneratorConfig).mockResolvedValue({
614
+ authType: AuthType.USE_GEMINI,
615
+ });
616
+ await config.refreshAuth(AuthType.USE_GEMINI);
617
+ expect(config.getProModelNoAccessSync()).toBe(false);
618
+ });
619
+ });
554
620
  describe('getRequestTimeoutMs', () => {
555
621
  it('should return undefined if the flag is not set', () => {
556
622
  const config = new Config(baseParams);
@@ -609,11 +675,24 @@ describe('Server Config (config.ts)', () => {
609
675
  };
610
676
  vi.mocked(createContentGeneratorConfig).mockResolvedValue(mockContentConfig);
611
677
  await config.refreshAuth(authType);
612
- expect(createContentGeneratorConfig).toHaveBeenCalledWith(config, authType, undefined, undefined, undefined);
678
+ expect(createContentGeneratorConfig).toHaveBeenCalledWith(config, authType, undefined, undefined, undefined, undefined);
613
679
  // Verify that contentGeneratorConfig is updated
614
680
  expect(config.getContentGeneratorConfig()).toEqual(mockContentConfig);
615
681
  expect(GeminiClient).toHaveBeenCalledWith(config);
616
682
  });
683
+ it('should pass Vertex AI routing settings when refreshing auth', async () => {
684
+ const vertexAiRouting = {
685
+ requestType: 'shared',
686
+ sharedRequestType: 'priority',
687
+ };
688
+ const config = new Config({
689
+ ...baseParams,
690
+ vertexAiRouting,
691
+ });
692
+ vi.mocked(createContentGeneratorConfig).mockResolvedValue({});
693
+ await config.refreshAuth(AuthType.USE_VERTEX_AI);
694
+ expect(createContentGeneratorConfig).toHaveBeenCalledWith(config, AuthType.USE_VERTEX_AI, undefined, undefined, undefined, vertexAiRouting);
695
+ });
617
696
  it('should reset model availability status', async () => {
618
697
  const config = new Config(baseParams);
619
698
  const service = config.getModelAvailabilityService();
@@ -1391,6 +1470,72 @@ describe('Server Config (config.ts)', () => {
1391
1470
  expect(config1.topicState.getTopic()).toBe('Topic 1');
1392
1471
  expect(config2.topicState.getTopic()).toBe('Topic 2');
1393
1472
  });
1473
+ it('updates storage session-scoped directories when the sessionId changes', async () => {
1474
+ const config = new Config({
1475
+ ...baseParams,
1476
+ sessionId: 'session-one',
1477
+ plan: true,
1478
+ });
1479
+ await config.initialize();
1480
+ const tempDir = config.storage.getProjectTempDir();
1481
+ const oldPlansDir = path.join(tempDir, 'session-one', 'plans');
1482
+ const oldTrackerService = config.getTrackerService();
1483
+ config.setSessionId('session-two');
1484
+ expect(config.getSessionId()).toBe('session-two');
1485
+ expect(config.storage.getProjectTempPlansDir()).toBe(path.join(tempDir, 'session-two', 'plans'));
1486
+ expect(config.storage.getProjectTempTrackerDir()).toBe(path.join(tempDir, 'session-two', 'tracker'));
1487
+ expect(config.getTrackerService()).not.toBe(oldTrackerService);
1488
+ expect(config.getTrackerService().trackerDir).toBe(path.join(tempDir, 'session-two', 'tracker'));
1489
+ expect(config.getWorkspaceContext().getDirectories()).not.toContain(oldPlansDir);
1490
+ });
1491
+ it('does not throw when changing sessions before the previous plans dir exists', async () => {
1492
+ const config = new Config({
1493
+ ...baseParams,
1494
+ sessionId: 'session-one',
1495
+ plan: true,
1496
+ });
1497
+ await config.initialize();
1498
+ const missingPlansDir = config.storage.getProjectTempPlansDir();
1499
+ const realpathMock = vi.mocked(fs.realpathSync);
1500
+ const originalImplementation = realpathMock.getMockImplementation();
1501
+ try {
1502
+ realpathMock.mockImplementation((input) => {
1503
+ const normalizedInput = typeof input === 'string' || Buffer.isBuffer(input)
1504
+ ? input
1505
+ : input.toString();
1506
+ if (normalizedInput === missingPlansDir) {
1507
+ const error = new Error(`ENOENT: no such file or directory, ${normalizedInput}`);
1508
+ Object.assign(error, { code: 'ENOENT' });
1509
+ throw error;
1510
+ }
1511
+ if (originalImplementation) {
1512
+ return originalImplementation(input);
1513
+ }
1514
+ return normalizedInput;
1515
+ });
1516
+ expect(() => config.setSessionId('session-two')).not.toThrow();
1517
+ }
1518
+ finally {
1519
+ realpathMock.mockImplementation((input) => {
1520
+ if (originalImplementation) {
1521
+ return originalImplementation(input);
1522
+ }
1523
+ return typeof input === 'string' || Buffer.isBuffer(input)
1524
+ ? input
1525
+ : input.toString();
1526
+ });
1527
+ }
1528
+ });
1529
+ it('clears the approved plan when starting a new session', () => {
1530
+ const config = new Config({
1531
+ ...baseParams,
1532
+ sessionId: 'session-one',
1533
+ });
1534
+ config.setApprovedPlanPath('/tmp/session-one/plans/approved.md');
1535
+ expect(() => config.resetNewSessionState('session-two')).not.toThrow();
1536
+ expect(config.getSessionId()).toBe('session-two');
1537
+ expect(config.getApprovedPlanPath()).toBeUndefined();
1538
+ });
1394
1539
  });
1395
1540
  describe('GemmaModelRouterSettings', () => {
1396
1541
  const MODEL = DEFAULT_GEMINI_MODEL;
@@ -1426,6 +1571,8 @@ describe('GemmaModelRouterSettings', () => {
1426
1571
  const config = new Config(baseParams);
1427
1572
  const settings = config.getGemmaModelRouterSettings();
1428
1573
  expect(settings.enabled).toBe(false);
1574
+ expect(settings.autoStartServer).toBe(true);
1575
+ expect(settings.binaryPath).toBe('');
1429
1576
  expect(settings.classifier?.host).toBe('http://localhost:9379');
1430
1577
  expect(settings.classifier?.model).toBe('gemma3-1b-gpu-custom');
1431
1578
  });
@@ -1434,6 +1581,8 @@ describe('GemmaModelRouterSettings', () => {
1434
1581
  ...baseParams,
1435
1582
  gemmaModelRouter: {
1436
1583
  enabled: true,
1584
+ autoStartServer: false,
1585
+ binaryPath: '/custom/lit',
1437
1586
  classifier: {
1438
1587
  host: 'http://custom:1234',
1439
1588
  model: 'custom-gemma',
@@ -1443,6 +1592,8 @@ describe('GemmaModelRouterSettings', () => {
1443
1592
  const config = new Config(params);
1444
1593
  const settings = config.getGemmaModelRouterSettings();
1445
1594
  expect(settings.enabled).toBe(true);
1595
+ expect(settings.autoStartServer).toBe(false);
1596
+ expect(settings.binaryPath).toBe('/custom/lit');
1446
1597
  expect(settings.classifier?.host).toBe('http://custom:1234');
1447
1598
  expect(settings.classifier?.model).toBe('custom-gemma');
1448
1599
  });
@@ -1456,6 +1607,8 @@ describe('GemmaModelRouterSettings', () => {
1456
1607
  const config = new Config(params);
1457
1608
  const settings = config.getGemmaModelRouterSettings();
1458
1609
  expect(settings.enabled).toBe(true);
1610
+ expect(settings.autoStartServer).toBe(true);
1611
+ expect(settings.binaryPath).toBe('');
1459
1612
  expect(settings.classifier?.host).toBe('http://localhost:9379');
1460
1613
  expect(settings.classifier?.model).toBe('gemma3-1b-gpu-custom');
1461
1614
  });
@@ -2604,7 +2757,97 @@ describe('Config JIT Initialization', () => {
2604
2757
  expect(MemoryContextManager).not.toHaveBeenCalled();
2605
2758
  expect(config.getUserMemory()).toBe('Initial Memory');
2606
2759
  });
2607
- describe('isMemoryManagerEnabled', () => {
2760
+ describe('isMemoryV2Enabled', () => {
2761
+ it('should default to true', () => {
2762
+ const params = {
2763
+ sessionId: 'test-session',
2764
+ targetDir: '/tmp/test',
2765
+ debugMode: false,
2766
+ model: 'test-model',
2767
+ cwd: '/tmp/test',
2768
+ };
2769
+ config = new Config(params);
2770
+ expect(config.isMemoryV2Enabled()).toBe(true);
2771
+ });
2772
+ it('should return false when experimentalMemoryV2 is explicitly false', () => {
2773
+ const params = {
2774
+ sessionId: 'test-session',
2775
+ targetDir: '/tmp/test',
2776
+ debugMode: false,
2777
+ model: 'test-model',
2778
+ cwd: '/tmp/test',
2779
+ experimentalMemoryV2: false,
2780
+ };
2781
+ config = new Config(params);
2782
+ expect(config.isMemoryV2Enabled()).toBe(false);
2783
+ });
2784
+ it('should return true when experimentalMemoryV2 is true', () => {
2785
+ const params = {
2786
+ sessionId: 'test-session',
2787
+ targetDir: '/tmp/test',
2788
+ debugMode: false,
2789
+ model: 'test-model',
2790
+ cwd: '/tmp/test',
2791
+ experimentalMemoryV2: true,
2792
+ };
2793
+ config = new Config(params);
2794
+ expect(config.isMemoryV2Enabled()).toBe(true);
2795
+ });
2796
+ it('should NOT add the global ~/.gemini directory to the workspace when enabled', async () => {
2797
+ // The prompt-driven memoryV2 mode does not broaden the workspace
2798
+ // to include the global ~/.gemini/ directory. Cross-project personal
2799
+ // preferences are routed to ~/.gemini/GEMINI.md via the surgical
2800
+ // isPathAllowed allowlist instead — see the next two tests.
2801
+ const params = {
2802
+ sessionId: 'test-session',
2803
+ targetDir: '/tmp/test',
2804
+ debugMode: false,
2805
+ model: 'test-model',
2806
+ cwd: '/tmp/test',
2807
+ experimentalMemoryV2: true,
2808
+ };
2809
+ config = new Config(params);
2810
+ await config.initialize();
2811
+ const directories = config.getWorkspaceContext().getDirectories();
2812
+ expect(directories).not.toContain(Storage.getGlobalGeminiDir());
2813
+ });
2814
+ it('should allow isPathAllowed to write the global ~/.gemini/GEMINI.md file', async () => {
2815
+ // Surgical allowlist: when memoryV2 is on, the prompt routes
2816
+ // cross-project personal preferences to ~/.gemini/GEMINI.md, so the
2817
+ // agent must be able to edit that exact file via edit/write_file.
2818
+ const params = {
2819
+ sessionId: 'test-session',
2820
+ targetDir: '/tmp/test',
2821
+ debugMode: false,
2822
+ model: 'test-model',
2823
+ cwd: '/tmp/test',
2824
+ experimentalMemoryV2: true,
2825
+ };
2826
+ config = new Config(params);
2827
+ await config.initialize();
2828
+ const globalGeminiMdPath = path.join(Storage.getGlobalGeminiDir(), 'GEMINI.md');
2829
+ expect(config.isPathAllowed(globalGeminiMdPath)).toBe(true);
2830
+ });
2831
+ it('should NOT allow isPathAllowed to write other files under ~/.gemini/ (least privilege)', async () => {
2832
+ // The allowlist is surgical: only ~/.gemini/GEMINI.md is reachable.
2833
+ // settings.json, keybindings.json, credentials, etc. remain disallowed.
2834
+ const params = {
2835
+ sessionId: 'test-session',
2836
+ targetDir: '/tmp/test',
2837
+ debugMode: false,
2838
+ model: 'test-model',
2839
+ cwd: '/tmp/test',
2840
+ experimentalMemoryV2: true,
2841
+ };
2842
+ config = new Config(params);
2843
+ await config.initialize();
2844
+ const globalDir = Storage.getGlobalGeminiDir();
2845
+ expect(config.isPathAllowed(path.join(globalDir, 'settings.json'))).toBe(false);
2846
+ expect(config.isPathAllowed(path.join(globalDir, 'keybindings.json'))).toBe(false);
2847
+ expect(config.isPathAllowed(path.join(globalDir, 'oauth_creds.json'))).toBe(false);
2848
+ });
2849
+ });
2850
+ describe('isAutoMemoryEnabled', () => {
2608
2851
  it('should default to false', () => {
2609
2852
  const params = {
2610
2853
  sessionId: 'test-session',
@@ -2614,19 +2857,32 @@ describe('Config JIT Initialization', () => {
2614
2857
  cwd: '/tmp/test',
2615
2858
  };
2616
2859
  config = new Config(params);
2617
- expect(config.isMemoryManagerEnabled()).toBe(false);
2860
+ expect(config.isAutoMemoryEnabled()).toBe(false);
2861
+ });
2862
+ it('should return true when experimentalAutoMemory is true', () => {
2863
+ const params = {
2864
+ sessionId: 'test-session',
2865
+ targetDir: '/tmp/test',
2866
+ debugMode: false,
2867
+ model: 'test-model',
2868
+ cwd: '/tmp/test',
2869
+ experimentalAutoMemory: true,
2870
+ };
2871
+ config = new Config(params);
2872
+ expect(config.isAutoMemoryEnabled()).toBe(true);
2618
2873
  });
2619
- it('should return true when experimentalMemoryManager is true', () => {
2874
+ it('should be independent of experimentalMemoryV2', () => {
2620
2875
  const params = {
2621
2876
  sessionId: 'test-session',
2622
2877
  targetDir: '/tmp/test',
2623
2878
  debugMode: false,
2624
2879
  model: 'test-model',
2625
2880
  cwd: '/tmp/test',
2626
- experimentalMemoryManager: true,
2881
+ experimentalMemoryV2: true,
2627
2882
  };
2628
2883
  config = new Config(params);
2629
- expect(config.isMemoryManagerEnabled()).toBe(true);
2884
+ expect(config.isMemoryV2Enabled()).toBe(true);
2885
+ expect(config.isAutoMemoryEnabled()).toBe(false);
2630
2886
  });
2631
2887
  });
2632
2888
  describe('reloadSkills', () => {