@google/gemini-cli-core 0.35.0-preview.2 → 0.36.0-nightly.20260321.fc03891a1

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 (366) hide show
  1. package/README.md +0 -1
  2. package/dist/docs/CONTRIBUTING.md +0 -15
  3. package/dist/docs/admin/enterprise-controls.md +61 -0
  4. package/dist/docs/changelogs/index.md +11 -0
  5. package/dist/docs/changelogs/latest.md +459 -209
  6. package/dist/docs/changelogs/preview.md +355 -454
  7. package/dist/docs/cli/checkpointing.md +3 -1
  8. package/dist/docs/cli/cli-reference.md +1 -0
  9. package/dist/docs/cli/custom-commands.md +7 -5
  10. package/dist/docs/cli/enterprise.md +15 -9
  11. package/dist/docs/cli/git-worktrees.md +107 -0
  12. package/dist/docs/cli/model-steering.md +4 -3
  13. package/dist/docs/cli/model.md +3 -1
  14. package/dist/docs/cli/notifications.md +4 -3
  15. package/dist/docs/cli/plan-mode.md +28 -8
  16. package/dist/docs/cli/sandbox.md +24 -4
  17. package/dist/docs/cli/session-management.md +6 -0
  18. package/dist/docs/cli/settings.md +14 -1
  19. package/dist/docs/cli/skills.md +4 -2
  20. package/dist/docs/cli/system-prompt.md +3 -1
  21. package/dist/docs/cli/telemetry.md +6 -3
  22. package/dist/docs/cli/themes.md +12 -8
  23. package/dist/docs/cli/tutorials/file-management.md +8 -6
  24. package/dist/docs/cli/tutorials/mcp-setup.md +5 -3
  25. package/dist/docs/cli/tutorials/memory-management.md +6 -6
  26. package/dist/docs/cli/tutorials/plan-mode-steering.md +4 -3
  27. package/dist/docs/cli/tutorials/shell-commands.md +3 -3
  28. package/dist/docs/core/remote-agents.md +8 -3
  29. package/dist/docs/core/subagents.md +21 -13
  30. package/dist/docs/extensions/reference.md +8 -3
  31. package/dist/docs/get-started/authentication.md +60 -50
  32. package/dist/docs/get-started/examples.md +3 -1
  33. package/dist/docs/get-started/gemini-3.md +11 -5
  34. package/dist/docs/hooks/index.md +3 -1
  35. package/dist/docs/hooks/writing-hooks.md +2 -2
  36. package/dist/docs/ide-integration/ide-companion-spec.md +5 -3
  37. package/dist/docs/ide-integration/index.md +8 -4
  38. package/dist/docs/issue-and-pr-automation.md +3 -1
  39. package/dist/docs/local-development.md +3 -1
  40. package/dist/docs/reference/commands.md +2 -2
  41. package/dist/docs/reference/configuration.md +410 -16
  42. package/dist/docs/reference/policy-engine.md +47 -19
  43. package/dist/docs/reference/tools.md +3 -1
  44. package/dist/docs/release-confidence.md +7 -3
  45. package/dist/docs/releases.md +11 -7
  46. package/dist/docs/resources/faq.md +13 -0
  47. package/dist/docs/resources/tos-privacy.md +4 -2
  48. package/dist/docs/resources/troubleshooting.md +3 -1
  49. package/dist/docs/sidebar.json +5 -0
  50. package/dist/docs/tools/mcp-server.md +17 -9
  51. package/dist/docs/tools/planning.md +3 -1
  52. package/dist/docs/tools/shell.md +4 -4
  53. package/dist/docs/tools/todos.md +2 -1
  54. package/dist/{google-gemini-cli-core-0.35.0-preview.1.tgz → google-gemini-cli-core-0.36.0-nightly.20260317.2f90b4653.tgz} +0 -0
  55. package/dist/src/agent/agent-session.d.ts +37 -0
  56. package/dist/src/agent/agent-session.js +168 -0
  57. package/dist/src/agent/agent-session.js.map +1 -0
  58. package/dist/src/agent/agent-session.test.d.ts +6 -0
  59. package/dist/src/agent/agent-session.test.js +217 -0
  60. package/dist/src/agent/agent-session.test.js.map +1 -0
  61. package/dist/src/agent/content-utils.d.ts +33 -0
  62. package/dist/src/agent/content-utils.js +135 -0
  63. package/dist/src/agent/content-utils.js.map +1 -0
  64. package/dist/src/agent/content-utils.test.d.ts +6 -0
  65. package/dist/src/agent/content-utils.test.js +223 -0
  66. package/dist/src/agent/content-utils.test.js.map +1 -0
  67. package/dist/src/agent/mock.d.ts +9 -12
  68. package/dist/src/agent/mock.js +88 -129
  69. package/dist/src/agent/mock.js.map +1 -1
  70. package/dist/src/agent/mock.test.js +114 -144
  71. package/dist/src/agent/mock.test.js.map +1 -1
  72. package/dist/src/agent/types.d.ts +21 -21
  73. package/dist/src/agents/a2a-client-manager.d.ts +2 -11
  74. package/dist/src/agents/a2a-client-manager.js +3 -19
  75. package/dist/src/agents/a2a-client-manager.js.map +1 -1
  76. package/dist/src/agents/a2a-client-manager.test.js +6 -10
  77. package/dist/src/agents/a2a-client-manager.test.js.map +1 -1
  78. package/dist/src/agents/agent-scheduler.d.ts +6 -0
  79. package/dist/src/agents/agent-scheduler.js +3 -2
  80. package/dist/src/agents/agent-scheduler.js.map +1 -1
  81. package/dist/src/agents/agent-scheduler.test.js +6 -0
  82. package/dist/src/agents/agent-scheduler.test.js.map +1 -1
  83. package/dist/src/agents/browser/browserAgentDefinition.js +10 -1
  84. package/dist/src/agents/browser/browserAgentDefinition.js.map +1 -1
  85. package/dist/src/agents/browser/browserAgentFactory.js +62 -1
  86. package/dist/src/agents/browser/browserAgentFactory.js.map +1 -1
  87. package/dist/src/agents/browser/browserAgentFactory.test.js +73 -0
  88. package/dist/src/agents/browser/browserAgentFactory.test.js.map +1 -1
  89. package/dist/src/agents/browser/browserAgentInvocation.js +2 -97
  90. package/dist/src/agents/browser/browserAgentInvocation.js.map +1 -1
  91. package/dist/src/agents/browser/browserAgentInvocation.test.js +30 -0
  92. package/dist/src/agents/browser/browserAgentInvocation.test.js.map +1 -1
  93. package/dist/src/agents/browser/browserManager.js +11 -0
  94. package/dist/src/agents/browser/browserManager.js.map +1 -1
  95. package/dist/src/agents/browser/browserManager.test.js +37 -0
  96. package/dist/src/agents/browser/browserManager.test.js.map +1 -1
  97. package/dist/src/agents/browser/mcpToolWrapper.d.ts +4 -2
  98. package/dist/src/agents/browser/mcpToolWrapper.js +30 -8
  99. package/dist/src/agents/browser/mcpToolWrapper.js.map +1 -1
  100. package/dist/src/agents/browser/mcpToolWrapper.test.js +30 -0
  101. package/dist/src/agents/browser/mcpToolWrapper.test.js.map +1 -1
  102. package/dist/src/agents/browser/mcpToolWrapperConfirmation.test.js +3 -3
  103. package/dist/src/agents/codebase-investigator.js +3 -3
  104. package/dist/src/agents/codebase-investigator.js.map +1 -1
  105. package/dist/src/agents/local-executor.d.ts +3 -1
  106. package/dist/src/agents/local-executor.js +138 -39
  107. package/dist/src/agents/local-executor.js.map +1 -1
  108. package/dist/src/agents/local-executor.test.js +305 -12
  109. package/dist/src/agents/local-executor.test.js.map +1 -1
  110. package/dist/src/agents/local-invocation.js +43 -24
  111. package/dist/src/agents/local-invocation.js.map +1 -1
  112. package/dist/src/agents/local-invocation.test.js +89 -14
  113. package/dist/src/agents/local-invocation.test.js.map +1 -1
  114. package/dist/src/agents/memory-manager-agent.d.ts +25 -0
  115. package/dist/src/agents/memory-manager-agent.js +137 -0
  116. package/dist/src/agents/memory-manager-agent.js.map +1 -0
  117. package/dist/src/agents/memory-manager-agent.test.d.ts +6 -0
  118. package/dist/src/agents/memory-manager-agent.test.js +117 -0
  119. package/dist/src/agents/memory-manager-agent.test.js.map +1 -0
  120. package/dist/src/agents/registry.js +21 -3
  121. package/dist/src/agents/registry.js.map +1 -1
  122. package/dist/src/agents/registry.test.js +23 -24
  123. package/dist/src/agents/registry.test.js.map +1 -1
  124. package/dist/src/agents/remote-invocation.d.ts +3 -1
  125. package/dist/src/agents/remote-invocation.js +10 -5
  126. package/dist/src/agents/remote-invocation.js.map +1 -1
  127. package/dist/src/agents/remote-invocation.test.js +64 -41
  128. package/dist/src/agents/remote-invocation.test.js.map +1 -1
  129. package/dist/src/agents/subagent-tool-wrapper.js +1 -1
  130. package/dist/src/agents/subagent-tool-wrapper.js.map +1 -1
  131. package/dist/src/agents/types.d.ts +12 -0
  132. package/dist/src/agents/types.js +14 -0
  133. package/dist/src/agents/types.js.map +1 -1
  134. package/dist/src/availability/policyHelpers.js +41 -1
  135. package/dist/src/availability/policyHelpers.js.map +1 -1
  136. package/dist/src/availability/policyHelpers.test.js +47 -0
  137. package/dist/src/availability/policyHelpers.test.js.map +1 -1
  138. package/dist/src/code_assist/admin/admin_controls.js +11 -0
  139. package/dist/src/code_assist/admin/admin_controls.js.map +1 -1
  140. package/dist/src/code_assist/admin/admin_controls.test.js +68 -0
  141. package/dist/src/code_assist/admin/admin_controls.test.js.map +1 -1
  142. package/dist/src/code_assist/admin/mcpUtils.d.ts +16 -1
  143. package/dist/src/code_assist/admin/mcpUtils.js +43 -0
  144. package/dist/src/code_assist/admin/mcpUtils.js.map +1 -1
  145. package/dist/src/code_assist/admin/mcpUtils.test.js +130 -1
  146. package/dist/src/code_assist/admin/mcpUtils.test.js.map +1 -1
  147. package/dist/src/code_assist/types.d.ts +458 -0
  148. package/dist/src/code_assist/types.js +26 -0
  149. package/dist/src/code_assist/types.js.map +1 -1
  150. package/dist/src/config/agent-loop-context.d.ts +6 -0
  151. package/dist/src/config/config.d.ts +41 -10
  152. package/dist/src/config/config.js +96 -19
  153. package/dist/src/config/config.js.map +1 -1
  154. package/dist/src/config/config.test.js +29 -1
  155. package/dist/src/config/config.test.js.map +1 -1
  156. package/dist/src/config/defaultModelConfigs.js +265 -9
  157. package/dist/src/config/defaultModelConfigs.js.map +1 -1
  158. package/dist/src/config/models.d.ts +13 -2
  159. package/dist/src/config/models.js +31 -3
  160. package/dist/src/config/models.js.map +1 -1
  161. package/dist/src/config/models.test.js +52 -7
  162. package/dist/src/config/models.test.js.map +1 -1
  163. package/dist/src/config/path-validation.test.d.ts +6 -0
  164. package/dist/src/config/path-validation.test.js +59 -0
  165. package/dist/src/config/path-validation.test.js.map +1 -0
  166. package/dist/src/core/client.d.ts +1 -0
  167. package/dist/src/core/client.js +6 -1
  168. package/dist/src/core/client.js.map +1 -1
  169. package/dist/src/core/client.test.js +9 -1
  170. package/dist/src/core/client.test.js.map +1 -1
  171. package/dist/src/core/contentGenerator.js +36 -6
  172. package/dist/src/core/contentGenerator.js.map +1 -1
  173. package/dist/src/core/contentGenerator.test.js +97 -3
  174. package/dist/src/core/contentGenerator.test.js.map +1 -1
  175. package/dist/src/core/geminiChat.js +2 -2
  176. package/dist/src/core/geminiChat.js.map +1 -1
  177. package/dist/src/core/prompts.test.js +10 -0
  178. package/dist/src/core/prompts.test.js.map +1 -1
  179. package/dist/src/generated/git-commit.d.ts +2 -2
  180. package/dist/src/generated/git-commit.js +2 -2
  181. package/dist/src/generated/git-commit.js.map +1 -1
  182. package/dist/src/ide/ide-connection-utils.js +2 -7
  183. package/dist/src/ide/ide-connection-utils.js.map +1 -1
  184. package/dist/src/ide/ide-connection-utils.test.js +7 -0
  185. package/dist/src/ide/ide-connection-utils.test.js.map +1 -1
  186. package/dist/src/index.d.ts +4 -0
  187. package/dist/src/index.js +4 -0
  188. package/dist/src/index.js.map +1 -1
  189. package/dist/src/policy/config.js +2 -0
  190. package/dist/src/policy/config.js.map +1 -1
  191. package/dist/src/policy/config.test.js +15 -0
  192. package/dist/src/policy/config.test.js.map +1 -1
  193. package/dist/src/policy/memory-manager-policy.test.d.ts +6 -0
  194. package/dist/src/policy/memory-manager-policy.test.js +80 -0
  195. package/dist/src/policy/memory-manager-policy.test.js.map +1 -0
  196. package/dist/src/policy/policies/memory-manager.toml +10 -0
  197. package/dist/src/policy/policies/plan.toml +14 -0
  198. package/dist/src/policy/policies/yolo.toml +1 -0
  199. package/dist/src/policy/policy-engine.js +33 -6
  200. package/dist/src/policy/policy-engine.js.map +1 -1
  201. package/dist/src/policy/policy-engine.test.js +85 -3
  202. package/dist/src/policy/policy-engine.test.js.map +1 -1
  203. package/dist/src/policy/policy-updater.test.js +44 -0
  204. package/dist/src/policy/policy-updater.test.js.map +1 -1
  205. package/dist/src/policy/toml-loader.js +2 -0
  206. package/dist/src/policy/toml-loader.js.map +1 -1
  207. package/dist/src/policy/types.d.ts +11 -0
  208. package/dist/src/policy/types.js +5 -0
  209. package/dist/src/policy/types.js.map +1 -1
  210. package/dist/src/prompts/promptProvider.js +5 -3
  211. package/dist/src/prompts/promptProvider.js.map +1 -1
  212. package/dist/src/prompts/promptProvider.test.js +1 -0
  213. package/dist/src/prompts/promptProvider.test.js.map +1 -1
  214. package/dist/src/prompts/snippets-memory-manager.test.d.ts +6 -0
  215. package/dist/src/prompts/snippets-memory-manager.test.js +31 -0
  216. package/dist/src/prompts/snippets-memory-manager.test.js.map +1 -0
  217. package/dist/src/prompts/snippets.d.ts +2 -0
  218. package/dist/src/prompts/snippets.js +7 -3
  219. package/dist/src/prompts/snippets.js.map +1 -1
  220. package/dist/src/prompts/snippets.legacy.d.ts +5 -0
  221. package/dist/src/prompts/snippets.legacy.js +30 -2
  222. package/dist/src/prompts/snippets.legacy.js.map +1 -1
  223. package/dist/src/routing/strategies/classifierStrategy.js +1 -1
  224. package/dist/src/routing/strategies/classifierStrategy.js.map +1 -1
  225. package/dist/src/routing/strategies/defaultStrategy.js +1 -1
  226. package/dist/src/routing/strategies/defaultStrategy.js.map +1 -1
  227. package/dist/src/routing/strategies/fallbackStrategy.js +1 -1
  228. package/dist/src/routing/strategies/fallbackStrategy.js.map +1 -1
  229. package/dist/src/routing/strategies/numericalClassifierStrategy.js +1 -1
  230. package/dist/src/routing/strategies/numericalClassifierStrategy.js.map +1 -1
  231. package/dist/src/routing/strategies/overrideStrategy.js +1 -1
  232. package/dist/src/routing/strategies/overrideStrategy.js.map +1 -1
  233. package/dist/src/sandbox/macos/MacOsSandboxManager.d.ts +28 -0
  234. package/dist/src/sandbox/macos/MacOsSandboxManager.integration.test.d.ts +1 -0
  235. package/dist/src/sandbox/macos/MacOsSandboxManager.integration.test.js +160 -0
  236. package/dist/src/sandbox/macos/MacOsSandboxManager.integration.test.js.map +1 -0
  237. package/dist/src/sandbox/macos/MacOsSandboxManager.js +33 -0
  238. package/dist/src/sandbox/macos/MacOsSandboxManager.js.map +1 -0
  239. package/dist/src/sandbox/macos/MacOsSandboxManager.test.d.ts +1 -0
  240. package/dist/src/sandbox/macos/MacOsSandboxManager.test.js +87 -0
  241. package/dist/src/sandbox/macos/MacOsSandboxManager.test.js.map +1 -0
  242. package/dist/src/sandbox/macos/baseProfile.d.ts +20 -0
  243. package/dist/src/sandbox/macos/baseProfile.js +93 -0
  244. package/dist/src/sandbox/macos/baseProfile.js.map +1 -0
  245. package/dist/src/sandbox/macos/seatbeltArgsBuilder.d.ts +25 -0
  246. package/dist/src/sandbox/macos/seatbeltArgsBuilder.js +58 -0
  247. package/dist/src/sandbox/macos/seatbeltArgsBuilder.js.map +1 -0
  248. package/dist/src/sandbox/macos/seatbeltArgsBuilder.test.d.ts +1 -0
  249. package/dist/src/sandbox/macos/seatbeltArgsBuilder.test.js +80 -0
  250. package/dist/src/sandbox/macos/seatbeltArgsBuilder.test.js.map +1 -0
  251. package/dist/src/scheduler/scheduler.js +2 -0
  252. package/dist/src/scheduler/scheduler.js.map +1 -1
  253. package/dist/src/services/contextManager.js +2 -3
  254. package/dist/src/services/contextManager.js.map +1 -1
  255. package/dist/src/services/contextManager.test.js +1 -1
  256. package/dist/src/services/contextManager.test.js.map +1 -1
  257. package/dist/src/services/modelConfigService.d.ts +36 -1
  258. package/dist/src/services/modelConfigService.js +66 -0
  259. package/dist/src/services/modelConfigService.js.map +1 -1
  260. package/dist/src/services/sandboxManager.d.ts +3 -4
  261. package/dist/src/services/sandboxManager.js +1 -14
  262. package/dist/src/services/sandboxManager.js.map +1 -1
  263. package/dist/src/services/sandboxManager.test.js +13 -16
  264. package/dist/src/services/sandboxManager.test.js.map +1 -1
  265. package/dist/src/services/sandboxManagerFactory.d.ts +11 -0
  266. package/dist/src/services/sandboxManagerFactory.js +31 -0
  267. package/dist/src/services/sandboxManagerFactory.js.map +1 -0
  268. package/dist/src/services/sandboxedFileSystemService.d.ts +17 -0
  269. package/dist/src/services/sandboxedFileSystemService.js +95 -0
  270. package/dist/src/services/sandboxedFileSystemService.js.map +1 -0
  271. package/dist/src/services/sandboxedFileSystemService.test.d.ts +6 -0
  272. package/dist/src/services/sandboxedFileSystemService.test.js +87 -0
  273. package/dist/src/services/sandboxedFileSystemService.test.js.map +1 -0
  274. package/dist/src/services/scripts/GeminiSandbox.cs +370 -0
  275. package/dist/src/services/shellExecutionService.d.ts +2 -0
  276. package/dist/src/services/shellExecutionService.js +79 -75
  277. package/dist/src/services/shellExecutionService.js.map +1 -1
  278. package/dist/src/services/trackerTypes.d.ts +1 -0
  279. package/dist/src/services/trackerTypes.js +1 -0
  280. package/dist/src/services/trackerTypes.js.map +1 -1
  281. package/dist/src/services/windowsSandboxManager.d.ts +27 -0
  282. package/dist/src/services/windowsSandboxManager.js +148 -0
  283. package/dist/src/services/windowsSandboxManager.js.map +1 -0
  284. package/dist/src/services/windowsSandboxManager.test.d.ts +6 -0
  285. package/dist/src/services/windowsSandboxManager.test.js +59 -0
  286. package/dist/src/services/windowsSandboxManager.test.js.map +1 -0
  287. package/dist/src/services/worktreeService.d.ts +33 -0
  288. package/dist/src/services/worktreeService.js +174 -0
  289. package/dist/src/services/worktreeService.js.map +1 -0
  290. package/dist/src/services/worktreeService.test.d.ts +6 -0
  291. package/dist/src/services/worktreeService.test.js +200 -0
  292. package/dist/src/services/worktreeService.test.js.map +1 -0
  293. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +4 -0
  294. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  295. package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +1 -0
  296. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +2 -0
  297. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
  298. package/dist/src/telemetry/loggers.test.js +62 -40
  299. package/dist/src/telemetry/loggers.test.js.map +1 -1
  300. package/dist/src/telemetry/types.d.ts +1 -0
  301. package/dist/src/telemetry/types.js +3 -0
  302. package/dist/src/telemetry/types.js.map +1 -1
  303. package/dist/src/tools/definitions/model-family-sets/default-legacy.js +8 -1
  304. package/dist/src/tools/definitions/model-family-sets/default-legacy.js.map +1 -1
  305. package/dist/src/tools/definitions/model-family-sets/gemini-3.js +8 -1
  306. package/dist/src/tools/definitions/model-family-sets/gemini-3.js.map +1 -1
  307. package/dist/src/tools/exit-plan-mode.d.ts +6 -1
  308. package/dist/src/tools/exit-plan-mode.js +17 -6
  309. package/dist/src/tools/exit-plan-mode.js.map +1 -1
  310. package/dist/src/tools/exit-plan-mode.test.js +22 -1
  311. package/dist/src/tools/exit-plan-mode.test.js.map +1 -1
  312. package/dist/src/tools/mcp-client-manager.d.ts +22 -3
  313. package/dist/src/tools/mcp-client-manager.js +84 -32
  314. package/dist/src/tools/mcp-client-manager.js.map +1 -1
  315. package/dist/src/tools/mcp-client-manager.test.js +76 -56
  316. package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
  317. package/dist/src/tools/mcp-client.d.ts +15 -6
  318. package/dist/src/tools/mcp-client.js +85 -71
  319. package/dist/src/tools/mcp-client.js.map +1 -1
  320. package/dist/src/tools/mcp-client.test.js +195 -88
  321. package/dist/src/tools/mcp-client.test.js.map +1 -1
  322. package/dist/src/tools/tool-registry.d.ts +2 -1
  323. package/dist/src/tools/tool-registry.js +12 -1
  324. package/dist/src/tools/tool-registry.js.map +1 -1
  325. package/dist/src/tools/tool-registry.test.js +15 -0
  326. package/dist/src/tools/tool-registry.test.js.map +1 -1
  327. package/dist/src/tools/tools.d.ts +1 -1
  328. package/dist/src/tools/tools.js.map +1 -1
  329. package/dist/src/tools/trackerTools.js +6 -1
  330. package/dist/src/tools/trackerTools.js.map +1 -1
  331. package/dist/src/tools/trackerTools.test.js +9 -1
  332. package/dist/src/tools/trackerTools.test.js.map +1 -1
  333. package/dist/src/tools/write-todos.js +1 -0
  334. package/dist/src/tools/write-todos.js.map +1 -1
  335. package/dist/src/tools/write-todos.test.js +4 -1
  336. package/dist/src/tools/write-todos.test.js.map +1 -1
  337. package/dist/src/utils/agent-sanitization-utils.d.ts +23 -0
  338. package/dist/src/utils/agent-sanitization-utils.js +123 -0
  339. package/dist/src/utils/agent-sanitization-utils.js.map +1 -0
  340. package/dist/src/utils/agent-sanitization-utils.test.d.ts +6 -0
  341. package/dist/src/utils/agent-sanitization-utils.test.js +83 -0
  342. package/dist/src/utils/agent-sanitization-utils.test.js.map +1 -0
  343. package/dist/src/utils/browserConsent.d.ts +17 -0
  344. package/dist/src/utils/browserConsent.js +78 -0
  345. package/dist/src/utils/browserConsent.js.map +1 -0
  346. package/dist/src/utils/browserConsent.test.d.ts +6 -0
  347. package/dist/src/utils/browserConsent.test.js +93 -0
  348. package/dist/src/utils/browserConsent.test.js.map +1 -0
  349. package/dist/src/utils/compatibility.d.ts +16 -0
  350. package/dist/src/utils/compatibility.js +58 -9
  351. package/dist/src/utils/compatibility.js.map +1 -1
  352. package/dist/src/utils/compatibility.test.js +127 -29
  353. package/dist/src/utils/compatibility.test.js.map +1 -1
  354. package/dist/src/utils/memoryDiscovery.d.ts +2 -2
  355. package/dist/src/utils/memoryDiscovery.js +5 -10
  356. package/dist/src/utils/memoryDiscovery.js.map +1 -1
  357. package/dist/src/utils/memoryDiscovery.test.js +37 -37
  358. package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
  359. package/dist/src/utils/memoryImportProcessor.js +5 -5
  360. package/dist/src/utils/memoryImportProcessor.js.map +1 -1
  361. package/dist/src/utils/surface.js +4 -3
  362. package/dist/src/utils/surface.js.map +1 -1
  363. package/dist/src/utils/toolCallContext.d.ts +2 -0
  364. package/dist/src/utils/toolCallContext.js.map +1 -1
  365. package/dist/tsconfig.tsbuildinfo +1 -1
  366. package/package.json +2 -1
@@ -0,0 +1,83 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect } from 'vitest';
7
+ import { sanitizeErrorMessage, sanitizeToolArgs, sanitizeThoughtContent, } from './agent-sanitization-utils.js';
8
+ describe('agent-sanitization-utils', () => {
9
+ describe('sanitizeErrorMessage', () => {
10
+ it('should redact standard inline PEM content', () => {
11
+ const input = 'Here is my key: -----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEA12345\n-----END RSA PRIVATE KEY----- do not share.';
12
+ const expected = 'Here is my key: [REDACTED_PEM] do not share.';
13
+ expect(sanitizeErrorMessage(input)).toBe(expected);
14
+ });
15
+ it('should redact non-standard inline PEM content (with punctuation)', () => {
16
+ const input = '-----BEGIN X.509 CERTIFICATE-----\nMIIEowIBAAKCAQEA12345\n-----END X.509 CERTIFICATE-----';
17
+ const expected = '[REDACTED_PEM]';
18
+ expect(sanitizeErrorMessage(input)).toBe(expected);
19
+ });
20
+ it('should not hang on ReDoS attack string for PEM redaction', () => {
21
+ const start = Date.now();
22
+ // A string that starts with -----BEGIN but has no ending, with many spaces
23
+ // In the vulnerable regex, this would cause catastrophic backtracking.
24
+ const maliciousInput = '-----BEGIN ' + ' '.repeat(50000) + 'A';
25
+ const result = sanitizeErrorMessage(maliciousInput);
26
+ const duration = Date.now() - start;
27
+ // Should process very quickly (e.g. < 50ms)
28
+ expect(duration).toBeLessThan(50);
29
+ // Since it doesn't match the full PEM block pattern, it should return the input unaltered
30
+ expect(result).toBe(maliciousInput);
31
+ });
32
+ it('should redact key-value pairs with sensitive keys', () => {
33
+ const input = 'Error: connection failed. --api-key="secret123"';
34
+ const result = sanitizeErrorMessage(input);
35
+ expect(result).toContain('[REDACTED]');
36
+ expect(result).not.toContain('secret123');
37
+ });
38
+ it('should redact space-separated sensitive keywords', () => {
39
+ // The keyword regex requires tokens to be 8+ chars
40
+ const input = 'Using password mySuperSecretPassword123';
41
+ const result = sanitizeErrorMessage(input);
42
+ expect(result).toContain('[REDACTED]');
43
+ expect(result).not.toContain('mySuperSecretPassword123');
44
+ });
45
+ });
46
+ describe('sanitizeToolArgs', () => {
47
+ it('should redact sensitive fields in an object', () => {
48
+ const input = {
49
+ username: 'admin',
50
+ password: 'superSecretPassword',
51
+ nested: {
52
+ api_key: 'abc123xyz',
53
+ normal_field: 'hello',
54
+ },
55
+ };
56
+ const result = sanitizeToolArgs(input);
57
+ expect(result).toEqual({
58
+ username: 'admin',
59
+ password: '[REDACTED]',
60
+ nested: {
61
+ api_key: '[REDACTED]',
62
+ normal_field: 'hello',
63
+ },
64
+ });
65
+ });
66
+ it('should handle arrays and strings correctly', () => {
67
+ const input = ['normal string', '--api-key="secret123"'];
68
+ const result = sanitizeToolArgs(input);
69
+ expect(result[0]).toBe('normal string');
70
+ expect(result[1]).toContain('[REDACTED]');
71
+ expect(result[1]).not.toContain('secret123');
72
+ });
73
+ });
74
+ describe('sanitizeThoughtContent', () => {
75
+ it('should redact sensitive patterns from thought content', () => {
76
+ const input = 'I will now authenticate using token 1234567890abcdef.';
77
+ const result = sanitizeThoughtContent(input);
78
+ expect(result).toContain('[REDACTED]');
79
+ expect(result).not.toContain('1234567890abcdef');
80
+ });
81
+ });
82
+ });
83
+ //# sourceMappingURL=agent-sanitization-utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-sanitization-utils.test.js","sourceRoot":"","sources":["../../../src/utils/agent-sanitization-utils.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /**
7
+ * Ensures the user has acknowledged the browser agent privacy notice.
8
+ *
9
+ * On first invocation (per profile), an interactive consent dialog is shown
10
+ * describing chrome-devtools-mcp's data collection and the fact that browser
11
+ * content is exposed to the AI model. A sentinel file is written to the
12
+ * browser profile directory once the user accepts.
13
+ *
14
+ * @returns `true` if consent was already given or the user accepted,
15
+ * `false` if the user declined.
16
+ */
17
+ export declare function getBrowserConsentIfNeeded(): Promise<boolean>;
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { CoreEvent, coreEvents } from './events.js';
7
+ import { Storage } from '../config/storage.js';
8
+ import * as fs from 'node:fs/promises';
9
+ import * as path from 'node:path';
10
+ /** Sentinel file written after the user acknowledges the browser privacy notice. */
11
+ const BROWSER_CONSENT_FLAG_FILE = 'browser-consent-acknowledged.txt';
12
+ /** Default browser profile directory name within ~/.gemini/ */
13
+ const BROWSER_PROFILE_DIR = 'cli-browser-profile';
14
+ /**
15
+ * Ensures the user has acknowledged the browser agent privacy notice.
16
+ *
17
+ * On first invocation (per profile), an interactive consent dialog is shown
18
+ * describing chrome-devtools-mcp's data collection and the fact that browser
19
+ * content is exposed to the AI model. A sentinel file is written to the
20
+ * browser profile directory once the user accepts.
21
+ *
22
+ * @returns `true` if consent was already given or the user accepted,
23
+ * `false` if the user declined.
24
+ */
25
+ export async function getBrowserConsentIfNeeded() {
26
+ const consentFilePath = path.join(Storage.getGlobalGeminiDir(), BROWSER_PROFILE_DIR, BROWSER_CONSENT_FLAG_FILE);
27
+ // Fast path: consent already persisted.
28
+ try {
29
+ await fs.access(consentFilePath);
30
+ return true;
31
+ }
32
+ catch {
33
+ // File doesn't exist — need to request consent.
34
+ void 0;
35
+ }
36
+ // Non-interactive mode (no UI listeners): skip the dialog for this session
37
+ // only. Do NOT persist the sentinel file — an interactive user on the same
38
+ // machine should still see the consent dialog the first time they use the
39
+ // browser agent.
40
+ if (coreEvents.listenerCount(CoreEvent.ConsentRequest) === 0) {
41
+ return true;
42
+ }
43
+ const prompt = '🔒 Browser Agent Privacy Notice\n\n' +
44
+ 'The Browser Agent uses chrome-devtools-mcp to control your browser. ' +
45
+ 'Please note:\n\n' +
46
+ '• Chrome DevTools MCP collects usage statistics by default ' +
47
+ '(can be disabled via privacy settings)\n' +
48
+ '• Performance tools may send trace URLs to Google CrUX API\n' +
49
+ '• Browser content will be exposed to the AI model for analysis\n' +
50
+ '• All data is handled per the Google Privacy Policy ' +
51
+ '(https://policies.google.com/privacy)\n\n' +
52
+ 'Do you understand and consent to proceed?';
53
+ return new Promise((resolve) => {
54
+ coreEvents.emitConsentRequest({
55
+ prompt,
56
+ onConfirm: async (confirmed) => {
57
+ if (confirmed) {
58
+ await markConsentAsAcknowledged(consentFilePath);
59
+ }
60
+ resolve(confirmed);
61
+ },
62
+ });
63
+ });
64
+ }
65
+ /**
66
+ * Persists a sentinel file so consent is not requested again.
67
+ */
68
+ async function markConsentAsAcknowledged(consentFilePath) {
69
+ try {
70
+ await fs.mkdir(path.dirname(consentFilePath), { recursive: true });
71
+ await fs.writeFile(consentFilePath, `Browser privacy consent acknowledged at ${new Date().toISOString()}\n`);
72
+ }
73
+ catch {
74
+ // Best-effort: if we can't persist, the dialog will appear again next time.
75
+ void 0;
76
+ }
77
+ }
78
+ //# sourceMappingURL=browserConsent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browserConsent.js","sourceRoot":"","sources":["../../../src/utils/browserConsent.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAC/C,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,oFAAoF;AACpF,MAAM,yBAAyB,GAAG,kCAAkC,CAAC;AAErE,+DAA+D;AAC/D,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;AAElD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB;IAC7C,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAC/B,OAAO,CAAC,kBAAkB,EAAE,EAC5B,mBAAmB,EACnB,yBAAyB,CAC1B,CAAC;IAEF,wCAAwC;IACxC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;QAChD,KAAK,CAAC,CAAC;IACT,CAAC;IAED,2EAA2E;IAC3E,2EAA2E;IAC3E,0EAA0E;IAC1E,iBAAiB;IACjB,IAAI,UAAU,CAAC,aAAa,CAAC,SAAS,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GACV,qCAAqC;QACrC,sEAAsE;QACtE,kBAAkB;QAClB,6DAA6D;QAC7D,0CAA0C;QAC1C,8DAA8D;QAC9D,kEAAkE;QAClE,sDAAsD;QACtD,2CAA2C;QAC3C,2CAA2C,CAAC;IAE9C,OAAO,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;QACtC,UAAU,CAAC,kBAAkB,CAAC;YAC5B,MAAM;YACN,SAAS,EAAE,KAAK,EAAE,SAAkB,EAAE,EAAE;gBACtC,IAAI,SAAS,EAAE,CAAC;oBACd,MAAM,yBAAyB,CAAC,eAAe,CAAC,CAAC;gBACnD,CAAC;gBACD,OAAO,CAAC,SAAS,CAAC,CAAC;YACrB,CAAC;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,yBAAyB,CACtC,eAAuB;IAEvB,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnE,MAAM,EAAE,CAAC,SAAS,CAChB,eAAe,EACf,2CAA2C,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,CACxE,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,4EAA4E;QAC5E,KAAK,CAAC,CAAC;IACT,CAAC;AACH,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
@@ -0,0 +1,93 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
7
+ import * as fs from 'node:fs/promises';
8
+ import { coreEvents } from './events.js';
9
+ import { Storage } from '../config/storage.js';
10
+ // Mock fs/promises before importing the module under test
11
+ vi.mock('node:fs/promises', () => ({
12
+ access: vi.fn(),
13
+ mkdir: vi.fn().mockResolvedValue(undefined),
14
+ writeFile: vi.fn().mockResolvedValue(undefined),
15
+ }));
16
+ // Mock Storage to return a predictable directory
17
+ vi.mock('../config/storage.js', () => ({
18
+ Storage: {
19
+ getGlobalGeminiDir: vi.fn(),
20
+ },
21
+ }));
22
+ import { getBrowserConsentIfNeeded } from './browserConsent.js';
23
+ describe('browserConsent', () => {
24
+ beforeEach(() => {
25
+ vi.resetAllMocks();
26
+ vi.mocked(Storage.getGlobalGeminiDir).mockReturnValue('/mock/.gemini');
27
+ });
28
+ afterEach(() => {
29
+ vi.restoreAllMocks();
30
+ });
31
+ it('should return true if consent file already exists', async () => {
32
+ // Consent file exists — fs.access resolves
33
+ vi.mocked(fs.access).mockResolvedValue(undefined);
34
+ const result = await getBrowserConsentIfNeeded();
35
+ expect(result).toBe(true);
36
+ // Should not emit a consent request
37
+ const emitSpy = vi.spyOn(coreEvents, 'emitConsentRequest');
38
+ expect(emitSpy).not.toHaveBeenCalled();
39
+ });
40
+ it('should auto-accept in non-interactive mode (no listeners) without persisting consent', async () => {
41
+ // Consent file does not exist
42
+ vi.mocked(fs.access).mockRejectedValue(new Error('ENOENT'));
43
+ // No listeners registered
44
+ vi.spyOn(coreEvents, 'listenerCount').mockReturnValue(0);
45
+ const result = await getBrowserConsentIfNeeded();
46
+ expect(result).toBe(true);
47
+ // Should NOT persist the consent — an interactive user on the same machine
48
+ // must still see the dialog the first time they use the browser agent.
49
+ expect(fs.writeFile).not.toHaveBeenCalled();
50
+ });
51
+ it('should request consent interactively and return true when accepted', async () => {
52
+ // Consent file does not exist
53
+ vi.mocked(fs.access).mockRejectedValue(new Error('ENOENT'));
54
+ // Simulate interactive mode: there is at least one listener
55
+ vi.spyOn(coreEvents, 'listenerCount').mockReturnValue(1);
56
+ // Mock emitConsentRequest to auto-confirm
57
+ vi.spyOn(coreEvents, 'emitConsentRequest').mockImplementation((payload) => {
58
+ payload.onConfirm(true);
59
+ });
60
+ const result = await getBrowserConsentIfNeeded();
61
+ expect(result).toBe(true);
62
+ expect(coreEvents.emitConsentRequest).toHaveBeenCalledWith(expect.objectContaining({
63
+ prompt: expect.stringContaining('Privacy Notice'),
64
+ }));
65
+ expect(fs.writeFile).toHaveBeenCalled();
66
+ });
67
+ it('should return false when user declines consent', async () => {
68
+ // Consent file does not exist
69
+ vi.mocked(fs.access).mockRejectedValue(new Error('ENOENT'));
70
+ // Simulate interactive mode
71
+ vi.spyOn(coreEvents, 'listenerCount').mockReturnValue(1);
72
+ // Mock emitConsentRequest to decline
73
+ vi.spyOn(coreEvents, 'emitConsentRequest').mockImplementation((payload) => {
74
+ payload.onConfirm(false);
75
+ });
76
+ const result = await getBrowserConsentIfNeeded();
77
+ expect(result).toBe(false);
78
+ // Should NOT persist consent
79
+ expect(fs.writeFile).not.toHaveBeenCalled();
80
+ });
81
+ it('should include privacy policy link in the prompt', async () => {
82
+ vi.mocked(fs.access).mockRejectedValue(new Error('ENOENT'));
83
+ vi.spyOn(coreEvents, 'listenerCount').mockReturnValue(1);
84
+ vi.spyOn(coreEvents, 'emitConsentRequest').mockImplementation((payload) => {
85
+ payload.onConfirm(true);
86
+ });
87
+ await getBrowserConsentIfNeeded();
88
+ expect(coreEvents.emitConsentRequest).toHaveBeenCalledWith(expect.objectContaining({
89
+ prompt: expect.stringContaining('policies.google.com/privacy'),
90
+ }));
91
+ });
92
+ });
93
+ //# sourceMappingURL=browserConsent.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browserConsent.test.js","sourceRoot":"","sources":["../../../src/utils/browserConsent.test.ts"],"names":[],"mappings":"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"}
@@ -12,6 +12,22 @@ export declare function isWindows10(): boolean;
12
12
  * Detects if the current terminal is a JetBrains-based IDE terminal.
13
13
  */
14
14
  export declare function isJetBrainsTerminal(): boolean;
15
+ /**
16
+ * Detects if the current terminal is running inside tmux.
17
+ */
18
+ export declare function isTmux(): boolean;
19
+ /**
20
+ * Detects if the current terminal is running inside GNU screen.
21
+ */
22
+ export declare function isGnuScreen(): boolean;
23
+ /**
24
+ * Detects if the terminal is low-color mode (TERM=screen* with no COLORTERM).
25
+ */
26
+ export declare function isLowColorTmux(): boolean;
27
+ /**
28
+ * Detects if the terminal is a "dumb" terminal.
29
+ */
30
+ export declare function isDumbTerminal(): boolean;
15
31
  /**
16
32
  * Detects if the current terminal is the default Apple Terminal.app.
17
33
  */
@@ -24,7 +24,34 @@ export function isWindows10() {
24
24
  * Detects if the current terminal is a JetBrains-based IDE terminal.
25
25
  */
26
26
  export function isJetBrainsTerminal() {
27
- return process.env['TERMINAL_EMULATOR'] === 'JetBrains-JediTerm';
27
+ const env = process.env;
28
+ return !!(env['TERMINAL_EMULATOR']?.startsWith('JetBrains') || env['JETBRAINS_IDE']);
29
+ }
30
+ /**
31
+ * Detects if the current terminal is running inside tmux.
32
+ */
33
+ export function isTmux() {
34
+ return !!process.env['TMUX'];
35
+ }
36
+ /**
37
+ * Detects if the current terminal is running inside GNU screen.
38
+ */
39
+ export function isGnuScreen() {
40
+ return !!process.env['STY'];
41
+ }
42
+ /**
43
+ * Detects if the terminal is low-color mode (TERM=screen* with no COLORTERM).
44
+ */
45
+ export function isLowColorTmux() {
46
+ const term = process.env['TERM'] || '';
47
+ return isTmux() && term.startsWith('screen') && !process.env['COLORTERM'];
48
+ }
49
+ /**
50
+ * Detects if the terminal is a "dumb" terminal.
51
+ */
52
+ export function isDumbTerminal() {
53
+ const term = process.env['TERM'] || '';
54
+ return term === 'dumb' || term === 'vt100';
28
55
  }
29
56
  /**
30
57
  * Detects if the current terminal is the default Apple Terminal.app.
@@ -80,16 +107,38 @@ export function getCompatibilityWarnings(options) {
80
107
  });
81
108
  }
82
109
  if (isJetBrainsTerminal() && options?.isAlternateBuffer) {
83
- const platformTerminals = {
84
- win32: 'Windows Terminal',
85
- darwin: 'iTerm2 or Ghostty',
86
- linux: 'Ghostty',
87
- };
88
- const suggestion = platformTerminals[os.platform()];
89
- const suggestedTerminals = suggestion ? ` (e.g., ${suggestion})` : '';
90
110
  warnings.push({
91
111
  id: 'jetbrains-terminal',
92
- message: `Warning: JetBrains mouse scrolling is unreliable. Disabling alternate buffer mode in settings or using an external terminal${suggestedTerminals} is recommended.`,
112
+ message: 'Warning: JetBrains terminal detected alternate buffer mode may cause scroll wheel issues and rendering artifacts. If you experience problems, disable it in /settings "Use Alternate Screen Buffer".',
113
+ priority: WarningPriority.High,
114
+ });
115
+ }
116
+ if (isTmux() && options?.isAlternateBuffer) {
117
+ warnings.push({
118
+ id: 'tmux-alternate-buffer',
119
+ message: 'Warning: tmux detected — alternate buffer mode may cause unexpected scrollback loss and flickering. If you experience issues, disable it in /settings → "Use Alternate Screen Buffer".\n Tip: Use Ctrl-b [ to access tmux copy mode for scrolling history.',
120
+ priority: WarningPriority.High,
121
+ });
122
+ }
123
+ if (isLowColorTmux()) {
124
+ warnings.push({
125
+ id: 'low-color-tmux',
126
+ message: 'Warning: Limited color support detected (TERM=screen). Some visual elements may not render correctly. For better color support in tmux, add to ~/.tmux.conf:\n set -g default-terminal "tmux-256color"\n set -ga terminal-overrides ",*256col*:Tc"',
127
+ priority: WarningPriority.High,
128
+ });
129
+ }
130
+ if (isGnuScreen()) {
131
+ warnings.push({
132
+ id: 'gnu-screen',
133
+ message: 'Warning: GNU screen detected. Some keyboard shortcuts and visual features may behave unexpectedly. For the best experience, consider using tmux or running Gemini CLI directly in your terminal.',
134
+ priority: WarningPriority.Low,
135
+ });
136
+ }
137
+ if (isDumbTerminal()) {
138
+ const term = process.env['TERM'] || 'dumb';
139
+ warnings.push({
140
+ id: 'dumb-terminal',
141
+ message: `Warning: Basic terminal detected (TERM=${term}). Visual rendering will be limited. For the best experience, use a terminal emulator with truecolor support.`,
93
142
  priority: WarningPriority.High,
94
143
  });
95
144
  }
@@ -1 +1 @@
1
- {"version":3,"file":"compatibility.js","sourceRoot":"","sources":["../../../src/utils/compatibility.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"compatibility.js","sourceRoot":"","sources":["../../../src/utils/compatibility.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
7
7
  import os from 'node:os';
8
- import { isWindows10, isJetBrainsTerminal, supports256Colors, supportsTrueColor, getCompatibilityWarnings, WarningPriority, } from './compatibility.js';
8
+ import { isWindows10, isJetBrainsTerminal, isTmux, isGnuScreen, isLowColorTmux, isDumbTerminal, supports256Colors, supportsTrueColor, getCompatibilityWarnings, WarningPriority, } from './compatibility.js';
9
9
  vi.mock('node:os', () => ({
10
10
  default: {
11
11
  platform: vi.fn(),
@@ -46,19 +46,89 @@ describe('compatibility', () => {
46
46
  });
47
47
  });
48
48
  describe('isJetBrainsTerminal', () => {
49
+ beforeEach(() => {
50
+ vi.stubEnv('TERMINAL_EMULATOR', '');
51
+ vi.stubEnv('JETBRAINS_IDE', '');
52
+ });
49
53
  it.each([
50
54
  {
51
- env: 'JetBrains-JediTerm',
55
+ env: { TERMINAL_EMULATOR: 'JetBrains-JediTerm' },
52
56
  expected: true,
53
- desc: 'TERMINAL_EMULATOR is JetBrains-JediTerm',
57
+ desc: 'TERMINAL_EMULATOR starts with JetBrains',
58
+ },
59
+ {
60
+ env: { JETBRAINS_IDE: 'IntelliJ' },
61
+ expected: true,
62
+ desc: 'JETBRAINS_IDE is set',
63
+ },
64
+ {
65
+ env: { TERMINAL_EMULATOR: 'xterm' },
66
+ expected: false,
67
+ desc: 'other terminals',
54
68
  },
55
- { env: 'something-else', expected: false, desc: 'other terminals' },
56
- { env: '', expected: false, desc: 'TERMINAL_EMULATOR is not set' },
69
+ { env: {}, expected: false, desc: 'no env vars set' },
57
70
  ])('should return $expected when $desc', ({ env, expected }) => {
58
- vi.stubEnv('TERMINAL_EMULATOR', env);
71
+ vi.stubEnv('TERMINAL_EMULATOR', '');
72
+ vi.stubEnv('JETBRAINS_IDE', '');
73
+ for (const [key, value] of Object.entries(env)) {
74
+ vi.stubEnv(key, value);
75
+ }
59
76
  expect(isJetBrainsTerminal()).toBe(expected);
60
77
  });
61
78
  });
79
+ describe('isTmux', () => {
80
+ it('should return true when TMUX is set', () => {
81
+ vi.stubEnv('TMUX', '/tmp/tmux-1001/default,1425,0');
82
+ expect(isTmux()).toBe(true);
83
+ });
84
+ it('should return false when TMUX is not set', () => {
85
+ vi.stubEnv('TMUX', '');
86
+ expect(isTmux()).toBe(false);
87
+ });
88
+ });
89
+ describe('isGnuScreen', () => {
90
+ it('should return true when STY is set', () => {
91
+ vi.stubEnv('STY', '1234.pts-0.host');
92
+ expect(isGnuScreen()).toBe(true);
93
+ });
94
+ it('should return false when STY is not set', () => {
95
+ vi.stubEnv('STY', '');
96
+ expect(isGnuScreen()).toBe(false);
97
+ });
98
+ });
99
+ describe('isLowColorTmux', () => {
100
+ it('should return true when TERM=screen and COLORTERM is not set', () => {
101
+ vi.stubEnv('TERM', 'screen');
102
+ vi.stubEnv('TMUX', '1');
103
+ vi.stubEnv('COLORTERM', '');
104
+ expect(isLowColorTmux()).toBe(true);
105
+ });
106
+ it('should return false when TERM=screen and COLORTERM is set', () => {
107
+ vi.stubEnv('TERM', 'screen');
108
+ vi.stubEnv('TMUX', '1');
109
+ vi.stubEnv('COLORTERM', 'truecolor');
110
+ expect(isLowColorTmux()).toBe(false);
111
+ });
112
+ it('should return false when TERM=xterm-256color', () => {
113
+ vi.stubEnv('TERM', 'xterm-256color');
114
+ vi.stubEnv('COLORTERM', '');
115
+ expect(isLowColorTmux()).toBe(false);
116
+ });
117
+ });
118
+ describe('isDumbTerminal', () => {
119
+ it('should return true when TERM=dumb', () => {
120
+ vi.stubEnv('TERM', 'dumb');
121
+ expect(isDumbTerminal()).toBe(true);
122
+ });
123
+ it('should return true when TERM=vt100', () => {
124
+ vi.stubEnv('TERM', 'vt100');
125
+ expect(isDumbTerminal()).toBe(true);
126
+ });
127
+ it('should return false when TERM=xterm', () => {
128
+ vi.stubEnv('TERM', 'xterm');
129
+ expect(isDumbTerminal()).toBe(false);
130
+ });
131
+ });
62
132
  describe('supports256Colors', () => {
63
133
  it.each([
64
134
  {
@@ -84,6 +154,9 @@ describe('compatibility', () => {
84
154
  if (term !== undefined) {
85
155
  vi.stubEnv('TERM', term);
86
156
  }
157
+ else {
158
+ vi.stubEnv('TERM', '');
159
+ }
87
160
  expect(supports256Colors()).toBe(expected);
88
161
  });
89
162
  });
@@ -121,6 +194,13 @@ describe('compatibility', () => {
121
194
  });
122
195
  describe('getCompatibilityWarnings', () => {
123
196
  beforeEach(() => {
197
+ // Clear out potential local environment variables that might trigger warnings
198
+ vi.stubEnv('TERMINAL_EMULATOR', '');
199
+ vi.stubEnv('JETBRAINS_IDE', '');
200
+ vi.stubEnv('TMUX', '');
201
+ vi.stubEnv('STY', '');
202
+ vi.stubEnv('TERM', 'xterm-256color'); // Prevent dumb terminal warning
203
+ vi.stubEnv('TERM_PROGRAM', '');
124
204
  // Default to supporting true color to keep existing tests simple
125
205
  vi.stubEnv('COLORTERM', 'truecolor');
126
206
  process.stdout.getColorDepth = vi.fn().mockReturnValue(24);
@@ -135,33 +215,51 @@ describe('compatibility', () => {
135
215
  message: expect.stringContaining('Windows 10 detected'),
136
216
  }));
137
217
  });
138
- it.each([
139
- {
140
- platform: 'darwin',
141
- release: '20.6.0',
142
- externalTerminal: 'iTerm2 or Ghostty',
143
- desc: 'macOS',
144
- },
145
- {
146
- platform: 'win32',
147
- release: '10.0.22000',
148
- externalTerminal: 'Windows Terminal',
149
- desc: 'Windows',
150
- }, // Valid Windows 11 release to not trigger the Windows 10 warning
151
- {
152
- platform: 'linux',
153
- release: '5.10.0',
154
- externalTerminal: 'Ghostty',
155
- desc: 'Linux',
156
- },
157
- ])('should return JetBrains warning when detected and in alternate buffer ($desc)', ({ platform, release, externalTerminal }) => {
158
- vi.mocked(os.platform).mockReturnValue(platform);
159
- vi.mocked(os.release).mockReturnValue(release);
218
+ it('should return JetBrains warning when detected and in alternate buffer', () => {
219
+ vi.mocked(os.platform).mockReturnValue('darwin');
160
220
  vi.stubEnv('TERMINAL_EMULATOR', 'JetBrains-JediTerm');
161
221
  const warnings = getCompatibilityWarnings({ isAlternateBuffer: true });
162
222
  expect(warnings).toContainEqual(expect.objectContaining({
163
223
  id: 'jetbrains-terminal',
164
- message: expect.stringContaining(`Warning: JetBrains mouse scrolling is unreliable. Disabling alternate buffer mode in settings or using an external terminal (e.g., ${externalTerminal}) is recommended.`),
224
+ message: expect.stringContaining('JetBrains terminal detected'),
225
+ priority: WarningPriority.High,
226
+ }));
227
+ });
228
+ it('should return tmux warning when detected and in alternate buffer', () => {
229
+ vi.stubEnv('TMUX', '/tmp/tmux-1001/default,1,0');
230
+ const warnings = getCompatibilityWarnings({ isAlternateBuffer: true });
231
+ expect(warnings).toContainEqual(expect.objectContaining({
232
+ id: 'tmux-alternate-buffer',
233
+ message: expect.stringContaining('tmux detected'),
234
+ priority: WarningPriority.High,
235
+ }));
236
+ });
237
+ it('should return low-color tmux warning when detected', () => {
238
+ vi.stubEnv('TERM', 'screen');
239
+ vi.stubEnv('TMUX', '1');
240
+ vi.stubEnv('COLORTERM', '');
241
+ const warnings = getCompatibilityWarnings();
242
+ expect(warnings).toContainEqual(expect.objectContaining({
243
+ id: 'low-color-tmux',
244
+ message: expect.stringContaining('Limited color support detected'),
245
+ priority: WarningPriority.High,
246
+ }));
247
+ });
248
+ it('should return GNU screen warning when detected', () => {
249
+ vi.stubEnv('STY', '1234.pts-0.host');
250
+ const warnings = getCompatibilityWarnings();
251
+ expect(warnings).toContainEqual(expect.objectContaining({
252
+ id: 'gnu-screen',
253
+ message: expect.stringContaining('GNU screen detected'),
254
+ priority: WarningPriority.Low,
255
+ }));
256
+ });
257
+ it.each(['dumb', 'vt100'])('should return dumb terminal warning when TERM=%s', (term) => {
258
+ vi.stubEnv('TERM', term);
259
+ const warnings = getCompatibilityWarnings();
260
+ expect(warnings).toContainEqual(expect.objectContaining({
261
+ id: 'dumb-terminal',
262
+ message: `Warning: Basic terminal detected (TERM=${term}). Visual rendering will be limited. For the best experience, use a terminal emulator with truecolor support.`,
165
263
  priority: WarningPriority.High,
166
264
  }));
167
265
  });