Compare commits

..

2 Commits

Author SHA1 Message Date
galz10 df20164268 docs(changelog): update for v0.31.0 and v0.32.0-preview.0 releases 2026-02-27 16:05:35 -08:00
Aditya Sharma 08ee136132 docs: fix typo in installation documentation (#20153) 2026-02-27 23:04:52 +00:00
28 changed files with 527 additions and 3272 deletions
+45
View File
@@ -18,6 +18,51 @@ on GitHub.
| [Preview](preview.md) | Experimental features ready for early feedback. |
| [Stable](latest.md) | Stable, recommended for general use. |
## Announcements: v0.32.0-preview.0 - 2026-02-27
- **Plan Mode Enhancements:** Added support for modifying plans in external
editors and adaptive workflows that adjust based on task complexity
([#20348](https://github.com/google-gemini/gemini-cli/pull/20348) by @jerop,
[#20465](https://github.com/google-gemini/gemini-cli/pull/20465) by @Adib234).
- **Agent and Core Engine:** Enabled the generalist agent for broader task
handling and introduced `Kind.Agent` for sub-agent classification
([#19665](https://github.com/google-gemini/gemini-cli/pull/19665) by
@gsquared94, [#20369](https://github.com/google-gemini/gemini-cli/pull/20369)
by @jerop).
- **CLI & User Experience:** Introduced interactive shell autocompletion,
parallel loading of extensions, and new low/full error verbosity modes for
cleaner UI reporting
([#20082](https://github.com/google-gemini/gemini-cli/pull/20082) by
@scidomino, [#20229](https://github.com/google-gemini/gemini-cli/pull/20229)
by @galz10).
- **Stability and Bug Fixes:** Resolved an issue where orphaned processes could
consume 100% CPU and improved retry logic for Code Assist API calls
([#16965](https://github.com/google-gemini/gemini-cli/pull/16965) by @braddux,
[#19949](https://github.com/google-gemini/gemini-cli/pull/19949) by
@sehoon38).
## Announcements: v0.31.0 - 2026-02-27
- **Models & Agents:** Support for Gemini 3.1 Pro Preview and the introduction
of an experimental browser agent for web-based tasks
([#19676](https://github.com/google-gemini/gemini-cli/pull/19676) by
@sehoon38, [#19284](https://github.com/google-gemini/gemini-cli/pull/19284) by
@gsquared94).
- **Policy Engine Updates:** Project-level policy support, MCP server wildcard
support, and tool annotation matching in the policy engine
([#18682](https://github.com/google-gemini/gemini-cli/pull/18682) by
@Abhijit-2592,
[#20024](https://github.com/google-gemini/gemini-cli/pull/20024) by @jerop).
- **Web Capabilities:** Implemented a new direct web fetch tool with built-in
rate limiting to mitigate DDoS risks via prompt injection
([#19557](https://github.com/google-gemini/gemini-cli/pull/19557) by @mbleigh,
[#19567](https://github.com/google-gemini/gemini-cli/pull/19567) by
@mattKorwel).
- **Plan Mode Enhancements:** Added support for automatic model switching,
configuring custom plan storage, and post-execution work summaries
([#20240](https://github.com/google-gemini/gemini-cli/pull/20240) by @jerop,
[#19577](https://github.com/google-gemini/gemini-cli/pull/19577) by @jerop).
## Announcements: v0.30.0 - 2026-02-25
- **SDK & Custom Skills:** Introduced the initial SDK package, enabling dynamic
+47 -317
View File
@@ -1,4 +1,4 @@
# Latest stable release: v0.30.1
# Latest stable release: v0.31.0
Released: February 27, 2026
@@ -11,326 +11,56 @@ npm install -g @google/gemini-cli
## Highlights
- **SDK & Custom Skills**: Introduced the initial SDK package, dynamic system
instructions, `SessionContext` for SDK tool calls, and support for custom
skills.
- **Policy Engine Enhancements**: Added a `--policy` flag for user-defined
policies, strict seatbelt profiles, and transitioned away from
`--allowed-tools`.
- **UI & Themes**: Introduced a generic searchable list for settings and
extensions, added Solarized Dark and Light themes, text wrapping capabilities
to markdown tables, and a clean UI toggle prototype.
- **Vim Support & Ctrl-Z**: Improved Vim support to provide a more complete
experience and added support for Ctrl-Z suspension.
- **Plan Mode & Tools**: Plan Mode now supports project exploration without
planning and skills can be enabled in plan mode. Tool output masking is
enabled by default, and core tool definitions have been centralized.
- **Gemini 3.1 Pro Preview**: Support for the new Gemini 3.1 Pro Preview models
with improved reasoning and context handling.
- **Experimental Browser Agent**: Introduced a new experimental agent that can
interact directly with web pages to perform complex tasks.
- **Project-Level Policy**: Support for project-level policy enforcement,
allowing for more granular control over tools and security.
- **Direct Web Fetch**: Implementation of a direct web fetch tool with built-in
rate limiting to prevent abuse and ensure stability.
- **Plan Mode Enhancements**: Support for automatic model switching, custom
storage directory configuration, and post-execution work summaries.
## What's Changed
- fix(patch): cherry-pick 58df1c6 to release/v0.30.0-pr-20374 [CONFLICTS] by
@gemini-cli-robot in
[#20567](https://github.com/google-gemini/gemini-cli/pull/20567)
- feat(ux): added text wrapping capabilities to markdown tables by @devr0306 in
[#18240](https://github.com/google-gemini/gemini-cli/pull/18240)
- Revert "fix(mcp): ensure MCP transport is closed to prevent memory leaks" by
@skeshive in [#18771](https://github.com/google-gemini/gemini-cli/pull/18771)
- chore(release): bump version to 0.30.0-nightly.20260210.a2174751d by
@gemini-cli-robot in
[#18772](https://github.com/google-gemini/gemini-cli/pull/18772)
- chore: cleanup unused and add unlisted dependencies in packages/core by
@adamfweidman in
[#18762](https://github.com/google-gemini/gemini-cli/pull/18762)
- chore(core): update activate_skill prompt verbiage to be more direct by
@NTaylorMullen in
[#18605](https://github.com/google-gemini/gemini-cli/pull/18605)
- Add autoconfigure memory usage setting to the dialog by @jacob314 in
[#18510](https://github.com/google-gemini/gemini-cli/pull/18510)
- fix(core): prevent race condition in policy persistence by @braddux in
[#18506](https://github.com/google-gemini/gemini-cli/pull/18506)
- fix(evals): prevent false positive in hierarchical memory test by
@Abhijit-2592 in
[#18777](https://github.com/google-gemini/gemini-cli/pull/18777)
- test(evals): mark all `save_memory` evals as `USUALLY_PASSES` due to
unreliability by @jerop in
[#18786](https://github.com/google-gemini/gemini-cli/pull/18786)
- feat(cli): add setting to hide shortcuts hint UI by @LyalinDotCom in
[#18562](https://github.com/google-gemini/gemini-cli/pull/18562)
- feat(core): formalize 5-phase sequential planning workflow by @jerop in
[#18759](https://github.com/google-gemini/gemini-cli/pull/18759)
- Introduce limits for search results. by @gundermanc in
[#18767](https://github.com/google-gemini/gemini-cli/pull/18767)
- fix(cli): allow closing debug console after auto-open via flicker by
@SandyTao520 in
[#18795](https://github.com/google-gemini/gemini-cli/pull/18795)
- feat(masking): enable tool output masking by default by @abhipatel12 in
[#18564](https://github.com/google-gemini/gemini-cli/pull/18564)
- perf(ui): optimize table rendering by memoizing styled characters by @devr0306
in [#18770](https://github.com/google-gemini/gemini-cli/pull/18770)
- feat: multi-line text answers in ask-user tool by @jackwotherspoon in
[#18741](https://github.com/google-gemini/gemini-cli/pull/18741)
- perf(cli): truncate large debug logs and limit message history by @mattKorwel
in [#18663](https://github.com/google-gemini/gemini-cli/pull/18663)
- fix(core): complete MCP discovery when configured servers are skipped by
- feat(models): support Gemini 3.1 Pro Preview and fixes by @sehoon38 in
[#19676](https://github.com/google-gemini/gemini-cli/pull/19676)
- feat(browser): implement experimental browser agent by @gsquared94 in
[#19284](https://github.com/google-gemini/gemini-cli/pull/19284)
- feat(policy): implement project-level policy support by @Abhijit-2592 in
[#18682](https://github.com/google-gemini/gemini-cli/pull/18682)
- feat(core): implement experimental direct web fetch by @mbleigh in
[#19557](https://github.com/google-gemini/gemini-cli/pull/19557)
- fix(security): rate limit web_fetch tool to mitigate DDoS via prompt injection
by @mattKorwel in
[#19567](https://github.com/google-gemini/gemini-cli/pull/19567)
- feat(plan): support automatic model switching for Plan Mode by @jerop in
[#20240](https://github.com/google-gemini/gemini-cli/pull/20240)
- feat(plan): summarize work after executing a plan by @jerop in
[#19432](https://github.com/google-gemini/gemini-cli/pull/19432)
- feat(plan): support configuring custom plans storage directory by @jerop in
[#19577](https://github.com/google-gemini/gemini-cli/pull/19577)
- feat(policy): Support MCP Server Wildcards in Policy Engine by @jerop in
[#20024](https://github.com/google-gemini/gemini-cli/pull/20024)
- feat(policy): Implement Tool Annotation Matching in Policy Engine by @jerop in
[#20029](https://github.com/google-gemini/gemini-cli/pull/20029)
- feat(cli): add gemini --resume hint on exit by @Mag1ck in
[#16285](https://github.com/google-gemini/gemini-cli/pull/16285)
- feat(cli): add macOS run-event notifications (interactive only) by
@LyalinDotCom in
[#18586](https://github.com/google-gemini/gemini-cli/pull/18586)
- fix(core): cache CLI version to ensure consistency during sessions by
@sehoon38 in [#18793](https://github.com/google-gemini/gemini-cli/pull/18793)
- fix(cli): resolve double rendering in shpool and address vscode lint warnings
by @braddux in
[#18704](https://github.com/google-gemini/gemini-cli/pull/18704)
- feat(plan): document and validate Plan Mode policy overrides by @jerop in
[#18825](https://github.com/google-gemini/gemini-cli/pull/18825)
- Fix pressing any key to exit select mode. by @jacob314 in
[#18421](https://github.com/google-gemini/gemini-cli/pull/18421)
- fix(cli): update F12 behavior to only open drawer if browser fails by
@SandyTao520 in
[#18829](https://github.com/google-gemini/gemini-cli/pull/18829)
- feat(plan): allow skills to be enabled in plan mode by @Adib234 in
[#18817](https://github.com/google-gemini/gemini-cli/pull/18817)
- docs(plan): add documentation for plan mode tools by @jerop in
[#18827](https://github.com/google-gemini/gemini-cli/pull/18827)
- Remove experimental note in extension settings docs by @chrstnb in
[#18822](https://github.com/google-gemini/gemini-cli/pull/18822)
- Update prompt and grep tool definition to limit context size by @gundermanc in
[#18780](https://github.com/google-gemini/gemini-cli/pull/18780)
- docs(plan): add `ask_user` tool documentation by @jerop in
[#18830](https://github.com/google-gemini/gemini-cli/pull/18830)
- Revert unintended credentials exposure by @Adib234 in
[#18840](https://github.com/google-gemini/gemini-cli/pull/18840)
- feat(core): update internal utility models to Gemini 3 by @SandyTao520 in
[#18773](https://github.com/google-gemini/gemini-cli/pull/18773)
- feat(a2a): add value-resolver for auth credential resolution by @adamfweidman
in [#18653](https://github.com/google-gemini/gemini-cli/pull/18653)
- Removed getPlainTextLength by @devr0306 in
[#18848](https://github.com/google-gemini/gemini-cli/pull/18848)
- More grep prompt tweaks by @gundermanc in
[#18846](https://github.com/google-gemini/gemini-cli/pull/18846)
- refactor(cli): Reactive useSettingsStore hook by @psinha40898 in
[#14915](https://github.com/google-gemini/gemini-cli/pull/14915)
- fix(mcp): Ensure that stdio MCP server execution has the `GEMINI_CLI=1` env
variable populated. by @richieforeman in
[#18832](https://github.com/google-gemini/gemini-cli/pull/18832)
- fix(core): improve headless mode detection for flags and query args by @galz10
in [#18855](https://github.com/google-gemini/gemini-cli/pull/18855)
- refactor(cli): simplify UI and remove legacy inline tool confirmation logic by
@abhipatel12 in
[#18566](https://github.com/google-gemini/gemini-cli/pull/18566)
- feat(cli): deprecate --allowed-tools and excludeTools in favor of policy
engine by @Abhijit-2592 in
[#18508](https://github.com/google-gemini/gemini-cli/pull/18508)
- fix(workflows): improve maintainer detection for automated PR actions by
@bdmorgan in [#18869](https://github.com/google-gemini/gemini-cli/pull/18869)
- refactor(cli): consolidate useToolScheduler and delete legacy implementation
by @abhipatel12 in
[#18567](https://github.com/google-gemini/gemini-cli/pull/18567)
- Update changelog for v0.28.0 and v0.29.0-preview0 by @g-samroberts in
[#18819](https://github.com/google-gemini/gemini-cli/pull/18819)
- fix(core): ensure sub-agents are registered regardless of tools.allowed by
@mattKorwel in
[#18870](https://github.com/google-gemini/gemini-cli/pull/18870)
- Show notification when there's a conflict with an extensions command by
@chrstnb in [#17890](https://github.com/google-gemini/gemini-cli/pull/17890)
- fix(cli): dismiss '?' shortcuts help on hotkeys and active states by
@LyalinDotCom in
[#18583](https://github.com/google-gemini/gemini-cli/pull/18583)
- fix(core): prioritize conditional policy rules and harden Plan Mode by
@Abhijit-2592 in
[#18882](https://github.com/google-gemini/gemini-cli/pull/18882)
- feat(core): refine Plan Mode system prompt for agentic execution by
@NTaylorMullen in
[#18799](https://github.com/google-gemini/gemini-cli/pull/18799)
- feat(plan): create metrics for usage of `AskUser` tool by @Adib234 in
[#18820](https://github.com/google-gemini/gemini-cli/pull/18820)
- feat(cli): support Ctrl-Z suspension by @scidomino in
[#18931](https://github.com/google-gemini/gemini-cli/pull/18931)
- fix(github-actions): use robot PAT for release creation to trigger release
notes by @SandyTao520 in
[#18794](https://github.com/google-gemini/gemini-cli/pull/18794)
- feat: add strict seatbelt profiles and remove unusable closed profiles by
@SandyTao520 in
[#18876](https://github.com/google-gemini/gemini-cli/pull/18876)
- chore: cleanup unused and add unlisted dependencies in packages/a2a-server by
@adamfweidman in
[#18916](https://github.com/google-gemini/gemini-cli/pull/18916)
- fix(plan): isolate plan files per session by @Adib234 in
[#18757](https://github.com/google-gemini/gemini-cli/pull/18757)
- fix: character truncation in raw markdown mode by @jackwotherspoon in
[#18938](https://github.com/google-gemini/gemini-cli/pull/18938)
- feat(cli): prototype clean UI toggle and minimal-mode bleed-through by
@LyalinDotCom in
[#18683](https://github.com/google-gemini/gemini-cli/pull/18683)
- ui(polish) blend background color with theme by @jacob314 in
[#18802](https://github.com/google-gemini/gemini-cli/pull/18802)
- Add generic searchable list to back settings and extensions by @chrstnb in
[#18838](https://github.com/google-gemini/gemini-cli/pull/18838)
- feat(ui): align `AskUser` color scheme with UX spec by @jerop in
[#18943](https://github.com/google-gemini/gemini-cli/pull/18943)
- Hide AskUser tool validation errors from UI (agent self-corrects) by @jerop in
[#18954](https://github.com/google-gemini/gemini-cli/pull/18954)
- bug(cli) fix flicker due to AppContainer continuous initialization by
@jacob314 in [#18958](https://github.com/google-gemini/gemini-cli/pull/18958)
- feat(admin): Add admin controls documentation by @skeshive in
[#18644](https://github.com/google-gemini/gemini-cli/pull/18644)
- feat(cli): disable ctrl-s shortcut outside of alternate buffer mode by
@jacob314 in [#18887](https://github.com/google-gemini/gemini-cli/pull/18887)
- fix(vim): vim support that feels (more) complete by @ppgranger in
[#18755](https://github.com/google-gemini/gemini-cli/pull/18755)
- feat(policy): add --policy flag for user defined policies by @allenhutchison
in [#18500](https://github.com/google-gemini/gemini-cli/pull/18500)
- Update installation guide by @g-samroberts in
[#18823](https://github.com/google-gemini/gemini-cli/pull/18823)
- refactor(core): centralize tool definitions (Group 1: replace, search, grep)
by @aishaneeshah in
[#18944](https://github.com/google-gemini/gemini-cli/pull/18944)
- refactor(cli): finalize event-driven transition and remove interaction bridge
by @abhipatel12 in
[#18569](https://github.com/google-gemini/gemini-cli/pull/18569)
- Fix drag and drop escaping by @scidomino in
[#18965](https://github.com/google-gemini/gemini-cli/pull/18965)
- feat(sdk): initial package bootstrap for SDK by @mbleigh in
[#18861](https://github.com/google-gemini/gemini-cli/pull/18861)
- feat(sdk): implements SessionContext for SDK tool calls by @mbleigh in
[#18862](https://github.com/google-gemini/gemini-cli/pull/18862)
- fix(plan): make question type required in AskUser tool by @Adib234 in
[#18959](https://github.com/google-gemini/gemini-cli/pull/18959)
- fix(core): ensure --yolo does not force headless mode by @NTaylorMullen in
[#18976](https://github.com/google-gemini/gemini-cli/pull/18976)
- refactor(core): adopt `CoreToolCallStatus` enum for type safety by @jerop in
[#18998](https://github.com/google-gemini/gemini-cli/pull/18998)
- Enable in-CLI extension management commands for team by @chrstnb in
[#18957](https://github.com/google-gemini/gemini-cli/pull/18957)
- Adjust lint rules to avoid unnecessary warning. by @scidomino in
[#18970](https://github.com/google-gemini/gemini-cli/pull/18970)
- fix(vscode): resolve unsafe type assertion lint errors by @ehedlund in
[#19006](https://github.com/google-gemini/gemini-cli/pull/19006)
- Remove unnecessary eslint config file by @scidomino in
[#19015](https://github.com/google-gemini/gemini-cli/pull/19015)
- fix(core): Prevent loop detection false positives on lists with long shared
prefixes by @SandyTao520 in
[#18975](https://github.com/google-gemini/gemini-cli/pull/18975)
- feat(core): fallback to chat-base when using unrecognized models for chat by
@SandyTao520 in
[#19016](https://github.com/google-gemini/gemini-cli/pull/19016)
- docs: fix inconsistent commandRegex example in policy engine by @NTaylorMullen
in [#19027](https://github.com/google-gemini/gemini-cli/pull/19027)
- fix(plan): persist the approval mode in UI even when agent is thinking by
@Adib234 in [#18955](https://github.com/google-gemini/gemini-cli/pull/18955)
- feat(sdk): Implement dynamic system instructions by @mbleigh in
[#18863](https://github.com/google-gemini/gemini-cli/pull/18863)
- Docs: Refresh docs to organize and standardize reference materials. by
@jkcinouye in [#18403](https://github.com/google-gemini/gemini-cli/pull/18403)
- fix windows escaping (and broken tests) by @scidomino in
[#19011](https://github.com/google-gemini/gemini-cli/pull/19011)
- refactor: use `CoreToolCallStatus` in the the history data model by @jerop in
[#19033](https://github.com/google-gemini/gemini-cli/pull/19033)
- feat(cleanup): enable 30-day session retention by default by @skeshive in
[#18854](https://github.com/google-gemini/gemini-cli/pull/18854)
- feat(plan): hide plan write and edit operations on plans in Plan Mode by
@jerop in [#19012](https://github.com/google-gemini/gemini-cli/pull/19012)
- bug(ui) fix flicker refreshing background color by @jacob314 in
[#19041](https://github.com/google-gemini/gemini-cli/pull/19041)
- chore: fix dep vulnerabilities by @scidomino in
[#19036](https://github.com/google-gemini/gemini-cli/pull/19036)
- Revamp automated changelog skill by @g-samroberts in
[#18974](https://github.com/google-gemini/gemini-cli/pull/18974)
- feat(sdk): implement support for custom skills by @mbleigh in
[#19031](https://github.com/google-gemini/gemini-cli/pull/19031)
- refactor(core): complete centralization of core tool definitions by
@aishaneeshah in
[#18991](https://github.com/google-gemini/gemini-cli/pull/18991)
- feat: add /commands reload to refresh custom TOML commands by @korade-krushna
in [#19078](https://github.com/google-gemini/gemini-cli/pull/19078)
- fix(cli): wrap terminal capability queries in hidden sequence by @srithreepo
in [#19080](https://github.com/google-gemini/gemini-cli/pull/19080)
- fix(workflows): fix GitHub App token permissions for maintainer detection by
@bdmorgan in [#19139](https://github.com/google-gemini/gemini-cli/pull/19139)
- test: fix hook integration test flakiness on Windows CI by @NTaylorMullen in
[#18665](https://github.com/google-gemini/gemini-cli/pull/18665)
- fix(core): Encourage non-interactive flags for scaffolding commands by
@NTaylorMullen in
[#18804](https://github.com/google-gemini/gemini-cli/pull/18804)
- fix(core): propagate User-Agent header to setup-phase CodeAssist API calls by
@gsquared94 in
[#19182](https://github.com/google-gemini/gemini-cli/pull/19182)
- docs: document .agents/skills alias and discovery precedence by @kevmoo in
[#19166](https://github.com/google-gemini/gemini-cli/pull/19166)
- feat(cli): add loading state to new agents notification by @sehoon38 in
[#19190](https://github.com/google-gemini/gemini-cli/pull/19190)
- Add base branch to workflow. by @g-samroberts in
[#19189](https://github.com/google-gemini/gemini-cli/pull/19189)
- feat(cli): handle invalid model names in useQuotaAndFallback by @sehoon38 in
[#19222](https://github.com/google-gemini/gemini-cli/pull/19222)
- docs: custom themes in extensions by @jackwotherspoon in
[#19219](https://github.com/google-gemini/gemini-cli/pull/19219)
- Disable workspace settings when starting GCLI in the home directory. by
@kevinjwang1 in
[#19034](https://github.com/google-gemini/gemini-cli/pull/19034)
- feat(cli): refactor model command to support set and manage subcommands by
@sehoon38 in [#19221](https://github.com/google-gemini/gemini-cli/pull/19221)
- Add refresh/reload aliases to slash command subcommands by @korade-krushna in
[#19218](https://github.com/google-gemini/gemini-cli/pull/19218)
- refactor: consolidate development rules and add cli guidelines by @jacob314 in
[#19214](https://github.com/google-gemini/gemini-cli/pull/19214)
- chore(ui): remove outdated tip about model routing by @sehoon38 in
[#19226](https://github.com/google-gemini/gemini-cli/pull/19226)
- feat(core): support custom reasoning models by default by @NTaylorMullen in
[#19227](https://github.com/google-gemini/gemini-cli/pull/19227)
- Add Solarized Dark and Solarized Light themes by @rmedranollamas in
[#19064](https://github.com/google-gemini/gemini-cli/pull/19064)
- fix(telemetry): replace JSON.stringify with safeJsonStringify in file
exporters by @gsquared94 in
[#19244](https://github.com/google-gemini/gemini-cli/pull/19244)
- feat(telemetry): add keychain availability and token storage metrics by
@abhipatel12 in
[#18971](https://github.com/google-gemini/gemini-cli/pull/18971)
- feat(cli): update approval mode cycle order by @jerop in
[#19254](https://github.com/google-gemini/gemini-cli/pull/19254)
- refactor(cli): code review cleanup fix for tab+tab by @jacob314 in
[#18967](https://github.com/google-gemini/gemini-cli/pull/18967)
- feat(plan): support project exploration without planning when in plan mode by
@Adib234 in [#18992](https://github.com/google-gemini/gemini-cli/pull/18992)
- feat: add role-specific statistics to telemetry and UI (cont. #15234) by
@yunaseoul in [#18824](https://github.com/google-gemini/gemini-cli/pull/18824)
- feat(cli): remove Plan Mode from rotation when actively working by @jerop in
[#19262](https://github.com/google-gemini/gemini-cli/pull/19262)
- Fix side breakage where anchors don't work in slugs. by @g-samroberts in
[#19261](https://github.com/google-gemini/gemini-cli/pull/19261)
- feat(config): add setting to make directory tree context configurable by
@kevin-ramdass in
[#19053](https://github.com/google-gemini/gemini-cli/pull/19053)
- fix(acp): Wait for mcp initialization in acp (#18893) by @Mervap in
[#18894](https://github.com/google-gemini/gemini-cli/pull/18894)
- docs: format UTC times in releases doc by @pavan-sh in
[#18169](https://github.com/google-gemini/gemini-cli/pull/18169)
- Docs: Clarify extensions documentation. by @jkcinouye in
[#19277](https://github.com/google-gemini/gemini-cli/pull/19277)
- refactor(core): modularize tool definitions by model family by @aishaneeshah
in [#19269](https://github.com/google-gemini/gemini-cli/pull/19269)
- fix(paths): Add cross-platform path normalization by @spencer426 in
[#18939](https://github.com/google-gemini/gemini-cli/pull/18939)
- feat(core): experimental in-progress steering hints (1 of 3) by @joshualitt in
[#19008](https://github.com/google-gemini/gemini-cli/pull/19008)
- fix(patch): cherry-pick 261788c to release/v0.30.0-preview.0-pr-19453 to patch
version v0.30.0-preview.0 and create version 0.30.0-preview.1 by
[#19056](https://github.com/google-gemini/gemini-cli/pull/19056)
- feat(cli): enhance folder trust with configuration discovery and security
warnings by @galz10 in
[#19492](https://github.com/google-gemini/gemini-cli/pull/19492)
- security: implement deceptive URL detection and disclosure in tool
confirmations by @ehedlund in
[#19288](https://github.com/google-gemini/gemini-cli/pull/19288)
- security: strip deceptive Unicode characters from terminal output by @ehedlund
in [#19026](https://github.com/google-gemini/gemini-cli/pull/19026)
- fix(patch): cherry-pick 32e777f for v0.31.0-preview.3 release by
@gemini-cli-robot in
[#19490](https://github.com/google-gemini/gemini-cli/pull/19490)
- fix(patch): cherry-pick c43500c to release/v0.30.0-preview.1-pr-19502 to patch
version v0.30.0-preview.1 and create version 0.30.0-preview.2 by
@gemini-cli-robot in
[#19521](https://github.com/google-gemini/gemini-cli/pull/19521)
- fix(patch): cherry-pick aa9163d to release/v0.30.0-preview.3-pr-19991 to patch
version v0.30.0-preview.3 and create version 0.30.0-preview.4 by
@gemini-cli-robot in
[#20040](https://github.com/google-gemini/gemini-cli/pull/20040)
- fix(patch): cherry-pick 2c1d6f8 to release/v0.30.0-preview.4-pr-19369 to patch
version v0.30.0-preview.4 and create version 0.30.0-preview.5 by
@gemini-cli-robot in
[#20086](https://github.com/google-gemini/gemini-cli/pull/20086)
- fix(patch): cherry-pick d96bd05 to release/v0.30.0-preview.5-pr-19867 to patch
version v0.30.0-preview.5 and create version 0.30.0-preview.6 by
@gemini-cli-robot in
[#20112](https://github.com/google-gemini/gemini-cli/pull/20112)
[#20621](https://github.com/google-gemini/gemini-cli/pull/20621)
**Full Changelog**:
https://github.com/google-gemini/gemini-cli/compare/v0.29.7...v0.30.1
https://github.com/google-gemini/gemini-cli/compare/v0.30.1...v0.31.0
+40 -397
View File
@@ -1,9 +1,9 @@
# Preview release: v0.31.0-preview.1
# Preview release: v0.32.0-preview.0
Released: February 27, 2026
Our preview release includes the latest, new, and experimental features. This
release may not be as stable as our [latest weekly release](latest.md).
release may not be as stable as our [latest stable release](latest.md).
To install the preview release:
@@ -13,404 +13,47 @@ npm install -g @google/gemini-cli@preview
## Highlights
- **Plan Mode Enhancements**: Numerous additions including automatic model
switching, custom storage directory configuration, message injection upon
manual exit, enforcement of read-only constraints, and centralized tool
visibility in the policy engine.
- **Policy Engine Updates**: Project-level policy support added, alongside MCP
server wildcard support, tool annotation propagation and matching, and
workspace-level "Always Allow" persistence.
- **MCP Integration Improvements**: Better integration through support for MCP
progress updates with input validation and throttling, environment variable
expansion for servers, and full details expansion on tool approval.
- **CLI & Core UX Enhancements**: Several UI and quality-of-life updates such as
Alt+D for forward word deletion, macOS run-event notifications, enhanced
folder trust configurations with security warnings, improved startup warnings,
and a new experimental browser agent.
- **Security & Stability**: Introduced the Conseca framework, deceptive URL and
Unicode character detection, stricter access checks, rate limits on web fetch,
and resolved multiple dependency vulnerabilities.
- **Plan Mode Enhancements**: Support for modifying plans in external editors,
adaptive workflows based on task complexity, and comprehensive integration
tests.
- **Generalist Agent & Core**: Enabled the generalist agent for broader task
handling, introduced sub-agent classification with `Kind.Agent`, and
implemented a new task tracking service.
- **CLI & UX Polish**: Interactive shell autocompletion, parallel loading of
extensions, and new error verbosity modes (low/full) for cleaner UI reporting.
- **Billing & Security**: Initial support for G1 AI credits overage flow with
telemetry and updated authentication handshake to meet current specifications.
- **Stability & Performance**: Resolved an issue where orphaned processes could
consume 100% CPU and improved retry logic for Code Assist API calls.
## What's Changed
- fix(patch): cherry-pick 58df1c6 to release/v0.31.0-preview.0-pr-20374 to patch
version v0.31.0-preview.0 and create version 0.31.0-preview.1 by
@gemini-cli-robot in
[#20568](https://github.com/google-gemini/gemini-cli/pull/20568)
- Use ranged reads and limited searches and fuzzy editing improvements by
@gundermanc in
[#19240](https://github.com/google-gemini/gemini-cli/pull/19240)
- Fix bottom border color by @jacob314 in
[#19266](https://github.com/google-gemini/gemini-cli/pull/19266)
- Release note generator fix by @g-samroberts in
[#19363](https://github.com/google-gemini/gemini-cli/pull/19363)
- test(evals): add behavioral tests for tool output masking by @NTaylorMullen in
[#19172](https://github.com/google-gemini/gemini-cli/pull/19172)
- docs: clarify preflight instructions in GEMINI.md by @NTaylorMullen in
[#19377](https://github.com/google-gemini/gemini-cli/pull/19377)
- feat(cli): add gemini --resume hint on exit by @Mag1ck in
[#16285](https://github.com/google-gemini/gemini-cli/pull/16285)
- fix: optimize height calculations for ask_user dialog by @jackwotherspoon in
[#19017](https://github.com/google-gemini/gemini-cli/pull/19017)
- feat(cli): add Alt+D for forward word deletion by @scidomino in
[#19300](https://github.com/google-gemini/gemini-cli/pull/19300)
- Disable failing eval test by @chrstnb in
[#19455](https://github.com/google-gemini/gemini-cli/pull/19455)
- fix(cli): support legacy onConfirm callback in ToolActionsContext by
@SandyTao520 in
[#19369](https://github.com/google-gemini/gemini-cli/pull/19369)
- chore(deps): bump tar from 7.5.7 to 7.5.8 by dependabot[bot] in
[#19367](https://github.com/google-gemini/gemini-cli/pull/19367)
- fix(plan): allow safe fallback when experiment setting for plan is not enabled
but approval mode at startup is plan by @Adib234 in
[#19439](https://github.com/google-gemini/gemini-cli/pull/19439)
- Add explicit color-convert dependency by @chrstnb in
[#19460](https://github.com/google-gemini/gemini-cli/pull/19460)
- feat(devtools): migrate devtools package into monorepo by @SandyTao520 in
[#18936](https://github.com/google-gemini/gemini-cli/pull/18936)
- fix(core): clarify plan mode constraints and exit mechanism by @jerop in
[#19438](https://github.com/google-gemini/gemini-cli/pull/19438)
- feat(cli): add macOS run-event notifications (interactive only) by
@LyalinDotCom in
[#19056](https://github.com/google-gemini/gemini-cli/pull/19056)
- Changelog for v0.29.0 by @gemini-cli-robot in
[#19361](https://github.com/google-gemini/gemini-cli/pull/19361)
- fix(ui): preventing empty history items from being added by @devr0306 in
[#19014](https://github.com/google-gemini/gemini-cli/pull/19014)
- Changelog for v0.30.0-preview.0 by @gemini-cli-robot in
[#19364](https://github.com/google-gemini/gemini-cli/pull/19364)
- feat(core): add support for MCP progress updates by @NTaylorMullen in
[#19046](https://github.com/google-gemini/gemini-cli/pull/19046)
- fix(core): ensure directory exists before writing conversation file by
@godwiniheuwa in
[#18429](https://github.com/google-gemini/gemini-cli/pull/18429)
- fix(ui): move margin from top to bottom in ToolGroupMessage by @imadraude in
[#17198](https://github.com/google-gemini/gemini-cli/pull/17198)
- fix(cli): treat unknown slash commands as regular input instead of showing
error by @skyvanguard in
[#17393](https://github.com/google-gemini/gemini-cli/pull/17393)
- feat(core): experimental in-progress steering hints (2 of 2) by @joshualitt in
[#19307](https://github.com/google-gemini/gemini-cli/pull/19307)
- docs(plan): add documentation for plan mode command by @Adib234 in
[#19467](https://github.com/google-gemini/gemini-cli/pull/19467)
- fix(core): ripgrep fails when pattern looks like ripgrep flag by @syvb in
[#18858](https://github.com/google-gemini/gemini-cli/pull/18858)
- fix(cli): disable auto-completion on Shift+Tab to preserve mode cycling by
- feat(plan): Support for modifying plans in external editors by @jerop in
[#20348](https://github.com/google-gemini/gemini-cli/pull/20348)
- feat(plan): Adaptive planning workflows based on task complexity by @Adib234
in [#20465](https://github.com/google-gemini/gemini-cli/pull/20465)
- feat(agent): Enabled the generalist agent by @gsquared94 in
[#19665](https://github.com/google-gemini/gemini-cli/pull/19665)
- feat(agent): Introduced `Kind.Agent` for sub-agent classification by @jerop in
[#20369](https://github.com/google-gemini/gemini-cli/pull/20369)
- feat(core): Implemented task tracking foundation and service by @SandyTao520
in [#19464](https://github.com/google-gemini/gemini-cli/pull/19464)
- feat(cli): Interactive shell autocompletion by @scidomino in
[#20082](https://github.com/google-gemini/gemini-cli/pull/20082)
- feat(cli): Parallel loading of extensions by @galz10 in
[#20229](https://github.com/google-gemini/gemini-cli/pull/20229)
- feat(cli): New low/full error verbosity modes for cleaner UI by @sehoon38 in
[#20399](https://github.com/google-gemini/gemini-cli/pull/20399)
- feat(billing): G1 AI credits overage flow with billing telemetry by
@abhipatel12 in
[#18590](https://github.com/google-gemini/gemini-cli/pull/18590)
- feat(security): Updated authentication handshake to specification by @ehedlund
in [#19725](https://github.com/google-gemini/gemini-cli/pull/19725)
- fix(core): Prevent orphaned processes from consuming 100% CPU by @braddux in
[#16965](https://github.com/google-gemini/gemini-cli/pull/16965)
- fix(mcp): Reduced intrusive MCP errors and deduplicated diagnostics by
@NTaylorMullen in
[#19451](https://github.com/google-gemini/gemini-cli/pull/19451)
- use issuer instead of authorization_endpoint for oauth discovery by
@garrettsparks in
[#17332](https://github.com/google-gemini/gemini-cli/pull/17332)
- feat(cli): include `/dir add` directories in @ autocomplete suggestions by
@jasmeetsb in [#19246](https://github.com/google-gemini/gemini-cli/pull/19246)
- feat(admin): Admin settings should only apply if adminControlsApplicable =
true and fetch errors should be fatal by @skeshive in
[#19453](https://github.com/google-gemini/gemini-cli/pull/19453)
- Format strict-development-rules command by @g-samroberts in
[#19484](https://github.com/google-gemini/gemini-cli/pull/19484)
- feat(core): centralize compatibility checks and add TrueColor detection by
@spencer426 in
[#19478](https://github.com/google-gemini/gemini-cli/pull/19478)
- Remove unused files and update index and sidebar. by @g-samroberts in
[#19479](https://github.com/google-gemini/gemini-cli/pull/19479)
- Migrate core render util to use xterm.js as part of the rendering loop. by
@jacob314 in [#19044](https://github.com/google-gemini/gemini-cli/pull/19044)
- Changelog for v0.30.0-preview.1 by @gemini-cli-robot in
[#19496](https://github.com/google-gemini/gemini-cli/pull/19496)
- build: replace deprecated built-in punycode with userland package by @jacob314
in [#19502](https://github.com/google-gemini/gemini-cli/pull/19502)
- Speculative fixes to try to fix react error. by @jacob314 in
[#19508](https://github.com/google-gemini/gemini-cli/pull/19508)
- fix spacing by @jacob314 in
[#19494](https://github.com/google-gemini/gemini-cli/pull/19494)
- fix(core): ensure user rejections update tool outcome for telemetry by
@abhiasap in [#18982](https://github.com/google-gemini/gemini-cli/pull/18982)
- fix(acp): Initialize config (#18897) by @Mervap in
[#18898](https://github.com/google-gemini/gemini-cli/pull/18898)
- fix(core): add error logging for IDE fetch failures by @yuvrajangadsingh in
[#17981](https://github.com/google-gemini/gemini-cli/pull/17981)
- feat(acp): support set_mode interface (#18890) by @Mervap in
[#18891](https://github.com/google-gemini/gemini-cli/pull/18891)
- fix(core): robust workspace-based IDE connection discovery by @ehedlund in
[#18443](https://github.com/google-gemini/gemini-cli/pull/18443)
- Deflake windows tests. by @jacob314 in
[#19511](https://github.com/google-gemini/gemini-cli/pull/19511)
- Fix: Avoid tool confirmation timeout when no UI listeners are present by
@pdHaku0 in [#17955](https://github.com/google-gemini/gemini-cli/pull/17955)
- format md file by @scidomino in
[#19474](https://github.com/google-gemini/gemini-cli/pull/19474)
- feat(cli): add experimental.useOSC52Copy setting by @scidomino in
[#19488](https://github.com/google-gemini/gemini-cli/pull/19488)
- feat(cli): replace loading phrases boolean with enum setting by @LyalinDotCom
in [#19347](https://github.com/google-gemini/gemini-cli/pull/19347)
- Update skill to adjust for generated results. by @g-samroberts in
[#19500](https://github.com/google-gemini/gemini-cli/pull/19500)
- Fix message too large issue. by @gundermanc in
[#19499](https://github.com/google-gemini/gemini-cli/pull/19499)
- fix(core): prevent duplicate tool approval entries in auto-saved.toml by
@Abhijit-2592 in
[#19487](https://github.com/google-gemini/gemini-cli/pull/19487)
- fix(core): resolve crash in ClearcutLogger when os.cpus() is empty by @Adib234
in [#19555](https://github.com/google-gemini/gemini-cli/pull/19555)
- chore(core): improve encapsulation and remove unused exports by @adamfweidman
in [#19556](https://github.com/google-gemini/gemini-cli/pull/19556)
- Revert "Add generic searchable list to back settings and extensions (… by
@chrstnb in [#19434](https://github.com/google-gemini/gemini-cli/pull/19434)
- fix(core): improve error type extraction for telemetry by @yunaseoul in
[#19565](https://github.com/google-gemini/gemini-cli/pull/19565)
- fix: remove extra padding in Composer by @jackwotherspoon in
[#19529](https://github.com/google-gemini/gemini-cli/pull/19529)
- feat(plan): support configuring custom plans storage directory by @jerop in
[#19577](https://github.com/google-gemini/gemini-cli/pull/19577)
- Migrate files to resource or references folder. by @g-samroberts in
[#19503](https://github.com/google-gemini/gemini-cli/pull/19503)
- feat(policy): implement project-level policy support by @Abhijit-2592 in
[#18682](https://github.com/google-gemini/gemini-cli/pull/18682)
- feat(core): Implement parallel FC for read only tools. by @joshualitt in
[#18791](https://github.com/google-gemini/gemini-cli/pull/18791)
- chore(skills): adds pr-address-comments skill to work on PR feedback by
@mbleigh in [#19576](https://github.com/google-gemini/gemini-cli/pull/19576)
- refactor(sdk): introduce session-based architecture by @mbleigh in
[#19180](https://github.com/google-gemini/gemini-cli/pull/19180)
- fix(ci): add fallback JSON extraction to issue triage workflow by @bdmorgan in
[#19593](https://github.com/google-gemini/gemini-cli/pull/19593)
- feat(core): refine Edit and WriteFile tool schemas for Gemini 3 by
@SandyTao520 in
[#19476](https://github.com/google-gemini/gemini-cli/pull/19476)
- Changelog for v0.30.0-preview.3 by @gemini-cli-robot in
[#19585](https://github.com/google-gemini/gemini-cli/pull/19585)
- fix(plan): exclude EnterPlanMode tool from YOLO mode by @Adib234 in
[#19570](https://github.com/google-gemini/gemini-cli/pull/19570)
- chore: resolve build warnings and update dependencies by @mattKorwel in
[#18880](https://github.com/google-gemini/gemini-cli/pull/18880)
- feat(ui): add source indicators to slash commands by @ehedlund in
[#18839](https://github.com/google-gemini/gemini-cli/pull/18839)
- docs: refine Plan Mode documentation structure and workflow by @jerop in
[#19644](https://github.com/google-gemini/gemini-cli/pull/19644)
- Docs: Update release information regarding Gemini 3.1 by @jkcinouye in
[#19568](https://github.com/google-gemini/gemini-cli/pull/19568)
- fix(security): rate limit web_fetch tool to mitigate DDoS via prompt injection
by @mattKorwel in
[#19567](https://github.com/google-gemini/gemini-cli/pull/19567)
- Add initial implementation of /extensions explore command by @chrstnb in
[#19029](https://github.com/google-gemini/gemini-cli/pull/19029)
- fix: use discoverOAuthFromWWWAuthenticate for reactive OAuth flow (#18760) by
@maximus12793 in
[#19038](https://github.com/google-gemini/gemini-cli/pull/19038)
- Search updates by @alisa-alisa in
[#19482](https://github.com/google-gemini/gemini-cli/pull/19482)
- feat(cli): add support for numpad SS3 sequences by @scidomino in
[#19659](https://github.com/google-gemini/gemini-cli/pull/19659)
- feat(cli): enhance folder trust with configuration discovery and security
warnings by @galz10 in
[#19492](https://github.com/google-gemini/gemini-cli/pull/19492)
- feat(ui): improve startup warnings UX with dismissal and show-count limits by
@spencer426 in
[#19584](https://github.com/google-gemini/gemini-cli/pull/19584)
- feat(a2a): Add API key authentication provider by @adamfweidman in
[#19548](https://github.com/google-gemini/gemini-cli/pull/19548)
- Send accepted/removed lines with ACCEPT_FILE telemetry. by @gundermanc in
[#19670](https://github.com/google-gemini/gemini-cli/pull/19670)
- feat(models): support Gemini 3.1 Pro Preview and fixes by @sehoon38 in
[#19676](https://github.com/google-gemini/gemini-cli/pull/19676)
- feat(plan): enforce read-only constraints in Plan Mode by @mattKorwel in
[#19433](https://github.com/google-gemini/gemini-cli/pull/19433)
- fix(cli): allow perfect match @scripts/test-windows-paths.js completions to
submit on Enter by @spencer426 in
[#19562](https://github.com/google-gemini/gemini-cli/pull/19562)
- fix(core): treat 503 Service Unavailable as retryable quota error by @sehoon38
in [#19642](https://github.com/google-gemini/gemini-cli/pull/19642)
- Update sidebar.json for to allow top nav tabs. by @g-samroberts in
[#19595](https://github.com/google-gemini/gemini-cli/pull/19595)
- security: strip deceptive Unicode characters from terminal output by @ehedlund
in [#19026](https://github.com/google-gemini/gemini-cli/pull/19026)
- Fixes 'input.on' is not a function error in Gemini CLI by @gundermanc in
[#19691](https://github.com/google-gemini/gemini-cli/pull/19691)
- Revert "feat(ui): add source indicators to slash commands" by @ehedlund in
[#19695](https://github.com/google-gemini/gemini-cli/pull/19695)
- security: implement deceptive URL detection and disclosure in tool
confirmations by @ehedlund in
[#19288](https://github.com/google-gemini/gemini-cli/pull/19288)
- fix(core): restore auth consent in headless mode and add unit tests by
@ehedlund in [#19689](https://github.com/google-gemini/gemini-cli/pull/19689)
- Fix unsafe assertions in code_assist folder. by @gundermanc in
[#19706](https://github.com/google-gemini/gemini-cli/pull/19706)
- feat(cli): make JetBrains warning more specific by @jacob314 in
[#19687](https://github.com/google-gemini/gemini-cli/pull/19687)
- fix(cli): extensions dialog UX polish by @jacob314 in
[#19685](https://github.com/google-gemini/gemini-cli/pull/19685)
- fix(cli): use getDisplayString for manual model selection in dialog by
@sehoon38 in [#19726](https://github.com/google-gemini/gemini-cli/pull/19726)
- feat(policy): repurpose "Always Allow" persistence to workspace level by
@Abhijit-2592 in
[#19707](https://github.com/google-gemini/gemini-cli/pull/19707)
- fix(cli): re-enable CLI banner by @sehoon38 in
[#19741](https://github.com/google-gemini/gemini-cli/pull/19741)
- Disallow and suppress unsafe assignment by @gundermanc in
[#19736](https://github.com/google-gemini/gemini-cli/pull/19736)
- feat(core): migrate read_file to 1-based start_line/end_line parameters by
@adamfweidman in
[#19526](https://github.com/google-gemini/gemini-cli/pull/19526)
- feat(cli): improve CTRL+O experience for both standard and alternate screen
buffer (ASB) modes by @jwhelangoog in
[#19010](https://github.com/google-gemini/gemini-cli/pull/19010)
- Utilize pipelining of grep_search -> read_file to eliminate turns by
@gundermanc in
[#19574](https://github.com/google-gemini/gemini-cli/pull/19574)
- refactor(core): remove unsafe type assertions in error utils (Phase 1.1) by
@mattKorwel in
[#19750](https://github.com/google-gemini/gemini-cli/pull/19750)
- Disallow unsafe returns. by @gundermanc in
[#19767](https://github.com/google-gemini/gemini-cli/pull/19767)
- fix(cli): filter subagent sessions from resume history by @abhipatel12 in
[#19698](https://github.com/google-gemini/gemini-cli/pull/19698)
- chore(lint): fix lint errors seen when running npm run lint by @abhipatel12 in
[#19844](https://github.com/google-gemini/gemini-cli/pull/19844)
- feat(core): remove unnecessary login verbiage from Code Assist auth by
@NTaylorMullen in
[#19861](https://github.com/google-gemini/gemini-cli/pull/19861)
- fix(plan): time share by approval mode dashboard reporting negative time
shares by @Adib234 in
[#19847](https://github.com/google-gemini/gemini-cli/pull/19847)
- fix(core): allow any preview model in quota access check by @bdmorgan in
[#19867](https://github.com/google-gemini/gemini-cli/pull/19867)
- fix(core): prevent omission placeholder deletions in replace/write_file by
@nsalerni in [#19870](https://github.com/google-gemini/gemini-cli/pull/19870)
- fix(core): add uniqueness guard to edit tool by @Shivangisharma4 in
[#19890](https://github.com/google-gemini/gemini-cli/pull/19890)
- refactor(config): remove enablePromptCompletion from settings by @sehoon38 in
[#19974](https://github.com/google-gemini/gemini-cli/pull/19974)
- refactor(core): move session conversion logic to core by @abhipatel12 in
[#19972](https://github.com/google-gemini/gemini-cli/pull/19972)
- Fix: Persist manual model selection on restart #19864 by @Nixxx19 in
[#19891](https://github.com/google-gemini/gemini-cli/pull/19891)
- fix(core): increase default retry attempts and add quota error backoff by
@sehoon38 in [#19949](https://github.com/google-gemini/gemini-cli/pull/19949)
- feat(core): add policy chain support for Gemini 3.1 by @sehoon38 in
[#19991](https://github.com/google-gemini/gemini-cli/pull/19991)
- Updates command reference and /stats command. by @g-samroberts in
[#19794](https://github.com/google-gemini/gemini-cli/pull/19794)
- Fix for silent failures in non-interactive mode by @owenofbrien in
[#19905](https://github.com/google-gemini/gemini-cli/pull/19905)
- fix(plan): allow plan mode writes on Windows and fix prompt paths by @Adib234
in [#19658](https://github.com/google-gemini/gemini-cli/pull/19658)
- fix(core): prevent OAuth server crash on unexpected requests by @reyyanxahmed
in [#19668](https://github.com/google-gemini/gemini-cli/pull/19668)
- feat: Map tool kinds to explicit ACP.ToolKind values and update test … by
@sripasg in [#19547](https://github.com/google-gemini/gemini-cli/pull/19547)
- chore: restrict gemini-automted-issue-triage to only allow echo by @galz10 in
[#20047](https://github.com/google-gemini/gemini-cli/pull/20047)
- Allow ask headers longer than 16 chars by @scidomino in
[#20041](https://github.com/google-gemini/gemini-cli/pull/20041)
- fix(core): prevent state corruption in McpClientManager during collis by @h30s
in [#19782](https://github.com/google-gemini/gemini-cli/pull/19782)
- fix(bundling): copy devtools package to bundle for runtime resolution by
@SandyTao520 in
[#19766](https://github.com/google-gemini/gemini-cli/pull/19766)
- feat(policy): Support MCP Server Wildcards in Policy Engine by @jerop in
[#20024](https://github.com/google-gemini/gemini-cli/pull/20024)
- docs(CONTRIBUTING): update React DevTools version to 6 by @mmgok in
[#20014](https://github.com/google-gemini/gemini-cli/pull/20014)
- feat(core): optimize tool descriptions and schemas for Gemini 3 by
@aishaneeshah in
[#19643](https://github.com/google-gemini/gemini-cli/pull/19643)
- feat(core): implement experimental direct web fetch by @mbleigh in
[#19557](https://github.com/google-gemini/gemini-cli/pull/19557)
- feat(core): replace expected_replacements with allow_multiple in replace tool
by @SandyTao520 in
[#20033](https://github.com/google-gemini/gemini-cli/pull/20033)
- fix(sandbox): harden image packaging integrity checks by @aviralgarg05 in
[#19552](https://github.com/google-gemini/gemini-cli/pull/19552)
- fix(core): allow environment variable expansion and explicit overrides for MCP
servers by @galz10 in
[#18837](https://github.com/google-gemini/gemini-cli/pull/18837)
- feat(policy): Implement Tool Annotation Matching in Policy Engine by @jerop in
[#20029](https://github.com/google-gemini/gemini-cli/pull/20029)
- fix(core): prevent utility calls from changing session active model by
@adamfweidman in
[#20035](https://github.com/google-gemini/gemini-cli/pull/20035)
- fix(cli): skip workspace policy loading when in home directory by
@Abhijit-2592 in
[#20054](https://github.com/google-gemini/gemini-cli/pull/20054)
- fix(scripts): Add Windows (win32/x64) support to lint.js by @ZafeerMahmood in
[#16193](https://github.com/google-gemini/gemini-cli/pull/16193)
- fix(a2a-server): Remove unsafe type assertions in agent by @Nixxx19 in
[#19723](https://github.com/google-gemini/gemini-cli/pull/19723)
- Fix: Handle corrupted token file gracefully when switching auth types (#19845)
by @Nixxx19 in
[#19850](https://github.com/google-gemini/gemini-cli/pull/19850)
- fix critical dep vulnerability by @scidomino in
[#20087](https://github.com/google-gemini/gemini-cli/pull/20087)
- Add new setting to configure maxRetries by @kevinjwang1 in
[#20064](https://github.com/google-gemini/gemini-cli/pull/20064)
- Stabilize tests. by @gundermanc in
[#20095](https://github.com/google-gemini/gemini-cli/pull/20095)
- make windows tests mandatory by @scidomino in
[#20096](https://github.com/google-gemini/gemini-cli/pull/20096)
- Add 3.1 pro preview to behavioral evals. by @gundermanc in
[#20088](https://github.com/google-gemini/gemini-cli/pull/20088)
- feat:PR-rate-limit by @JagjeevanAK in
[#19804](https://github.com/google-gemini/gemini-cli/pull/19804)
- feat(cli): allow expanding full details of MCP tool on approval by @y-okt in
[#19916](https://github.com/google-gemini/gemini-cli/pull/19916)
- feat(security): Introduce Conseca framework by @shrishabh in
[#13193](https://github.com/google-gemini/gemini-cli/pull/13193)
- fix(cli): Remove unsafe type assertions in activityLogger #19713 by @Nixxx19
in [#19745](https://github.com/google-gemini/gemini-cli/pull/19745)
- feat: implement AfterTool tail tool calls by @googlestrobe in
[#18486](https://github.com/google-gemini/gemini-cli/pull/18486)
- ci(actions): fix PR rate limiter excluding maintainers by @scidomino in
[#20117](https://github.com/google-gemini/gemini-cli/pull/20117)
- Shortcuts: Move SectionHeader title below top line and refine styling by
@keithguerin in
[#18721](https://github.com/google-gemini/gemini-cli/pull/18721)
- refactor(ui): Update and simplify use of gray colors in themes by @keithguerin
in [#20141](https://github.com/google-gemini/gemini-cli/pull/20141)
- fix punycode2 by @jacob314 in
[#20154](https://github.com/google-gemini/gemini-cli/pull/20154)
- feat(ide): add GEMINI_CLI_IDE_PID env var to override IDE process detection by
@kiryltech in [#15842](https://github.com/google-gemini/gemini-cli/pull/15842)
- feat(policy): Propagate Tool Annotations for MCP Servers by @jerop in
[#20083](https://github.com/google-gemini/gemini-cli/pull/20083)
- fix(a2a-server): pass allowedTools settings to core Config by @reyyanxahmed in
[#19680](https://github.com/google-gemini/gemini-cli/pull/19680)
- feat(mcp): add progress bar, throttling, and input validation for MCP tool
progress by @jasmeetsb in
[#19772](https://github.com/google-gemini/gemini-cli/pull/19772)
- feat(policy): centralize plan mode tool visibility in policy engine by @jerop
in [#20178](https://github.com/google-gemini/gemini-cli/pull/20178)
- feat(browser): implement experimental browser agent by @gsquared94 in
[#19284](https://github.com/google-gemini/gemini-cli/pull/19284)
- feat(plan): summarize work after executing a plan by @jerop in
[#19432](https://github.com/google-gemini/gemini-cli/pull/19432)
- fix(core): create new McpClient on restart to apply updated config by @h30s in
[#20126](https://github.com/google-gemini/gemini-cli/pull/20126)
- Changelog for v0.30.0-preview.5 by @gemini-cli-robot in
[#20107](https://github.com/google-gemini/gemini-cli/pull/20107)
- Update packages. by @jacob314 in
[#20152](https://github.com/google-gemini/gemini-cli/pull/20152)
- Fix extension env dir loading issue by @chrstnb in
[#20198](https://github.com/google-gemini/gemini-cli/pull/20198)
- restrict /assign to help-wanted issues by @scidomino in
[#20207](https://github.com/google-gemini/gemini-cli/pull/20207)
- feat(plan): inject message when user manually exits Plan mode by @jerop in
[#20203](https://github.com/google-gemini/gemini-cli/pull/20203)
- feat(extensions): enforce folder trust for local extension install by @galz10
in [#19703](https://github.com/google-gemini/gemini-cli/pull/19703)
- feat(hooks): adds support for RuntimeHook functions. by @mbleigh in
[#19598](https://github.com/google-gemini/gemini-cli/pull/19598)
- Docs: Update UI links. by @jkcinouye in
[#20224](https://github.com/google-gemini/gemini-cli/pull/20224)
- feat: prompt users to run /terminal-setup with yes/no by @ishaanxgupta in
[#16235](https://github.com/google-gemini/gemini-cli/pull/16235)
- fix: additional high vulnerabilities (minimatch, cross-spawn) by @adamfweidman
in [#20221](https://github.com/google-gemini/gemini-cli/pull/20221)
- feat(telemetry): Add context breakdown to API response event by @SandyTao520
in [#19699](https://github.com/google-gemini/gemini-cli/pull/19699)
- Docs: Add nested sub-folders for related topics by @g-samroberts in
[#20235](https://github.com/google-gemini/gemini-cli/pull/20235)
- feat(plan): support automatic model switching for Plan Mode by @jerop in
[#20240](https://github.com/google-gemini/gemini-cli/pull/20240)
[#20232](https://github.com/google-gemini/gemini-cli/pull/20232)
**Full Changelog**:
https://github.com/google-gemini/gemini-cli/compare/v0.30.0-preview.6...v0.31.0-preview.1
https://github.com/google-gemini/gemini-cli/compare/v0.31.0...v0.32.0-preview.0
@@ -11,50 +11,6 @@ Enter to submit · Esc to cancel
"
`;
exports[`AskUserDialog > Choice question placeholder > uses default placeholder when not provided 2`] = `
"
ERROR Cannot read properties of undefined (reading '$$typeof')
/Users/spencertang/Workspace/gemini-cli/node_modules/react/cjs/react.developme
nt.js:1208:15
1205: };
1206: exports.useContext = function (Context) {
1207: var dispatcher = resolveDispatcher();
1208: Context.$$typeof === REACT_CONSUMER_TYPE &&
1209: console.error(
1210 "Calling useContext(Context.Consumer) is not supported and will
: cause bugs. Did you mean to call useContext(Context) instead?"
1211: );
-process.env.NODE_ENV.expo
ts.useContext (/Users/spencertang/Workspace/gemini-cli/node_module
s/react/cjs/react.development.js:1208:15)
- useTerminalCapabilities (src/ui/hooks/useTerminalCapabilities.ts:15:19)
- useAlternateBuffer (src/ui/hooks/useAlternateBuffer.ts:15:24)
- ChoiceQuestionView (src/ui/components/AskUserDialog.tsx:484:29)
-Object.react-stack-bot
om-frame (/Users/spencertang/Workspace/gemini-cli/node_modules/r
eact-reconciler/cjs/react-reconciler.development.js:158
59:20)
-renderWithHo
ks (/Users/spencertang/Workspace/gemini-cli/node_modules/react-recon
ciler/cjs/react-reconciler.development.js:3221:22)
-updateFunctionCom
onent (/Users/spencertang/Workspace/gemini-cli/node_modules/react-
reconciler/cjs/react-reconciler.development.js:6475:19)
-beginWor
(/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconcile
r/cjs/react-reconciler.development.js:8009:18)
-runWithFiberIn
EV (/Users/spencertang/Workspace/gemini-cli/node_modules/react-rec
onciler/cjs/react-reconciler.development.js:1738:13)
-performUnitOfW
rk (/Users/spencertang/Workspace/gemini-cli/node_modules/react-rec
onciler/cjs/react-reconciler.development.js:12834:22)
"
`;
exports[`AskUserDialog > Choice question placeholder > uses placeholder for "Other" option when provided 1`] = `
"Select your preferred language:
@@ -66,50 +22,6 @@ Enter to submit · Esc to cancel
"
`;
exports[`AskUserDialog > Choice question placeholder > uses placeholder for "Other" option when provided 2`] = `
"
ERROR Cannot read properties of undefined (reading '$$typeof')
/Users/spencertang/Workspace/gemini-cli/node_modules/react/cjs/react.developme
nt.js:1208:15
1205: };
1206: exports.useContext = function (Context) {
1207: var dispatcher = resolveDispatcher();
1208: Context.$$typeof === REACT_CONSUMER_TYPE &&
1209: console.error(
1210 "Calling useContext(Context.Consumer) is not supported and will
: cause bugs. Did you mean to call useContext(Context) instead?"
1211: );
-process.env.NODE_ENV.expo
ts.useContext (/Users/spencertang/Workspace/gemini-cli/node_module
s/react/cjs/react.development.js:1208:15)
- useTerminalCapabilities (src/ui/hooks/useTerminalCapabilities.ts:15:19)
- useAlternateBuffer (src/ui/hooks/useAlternateBuffer.ts:15:24)
- ChoiceQuestionView (src/ui/components/AskUserDialog.tsx:484:29)
-Object.react-stack-bot
om-frame (/Users/spencertang/Workspace/gemini-cli/node_modules/r
eact-reconciler/cjs/react-reconciler.development.js:158
59:20)
-renderWithHo
ks (/Users/spencertang/Workspace/gemini-cli/node_modules/react-recon
ciler/cjs/react-reconciler.development.js:3221:22)
-updateFunctionCom
onent (/Users/spencertang/Workspace/gemini-cli/node_modules/react-
reconciler/cjs/react-reconciler.development.js:6475:19)
-beginWor
(/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconcile
r/cjs/react-reconciler.development.js:8009:18)
-runWithFiberIn
EV (/Users/spencertang/Workspace/gemini-cli/node_modules/react-rec
onciler/cjs/react-reconciler.development.js:1738:13)
-performUnitOfW
rk (/Users/spencertang/Workspace/gemini-cli/node_modules/react-rec
onciler/cjs/react-reconciler.development.js:12834:22)
"
`;
exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: false) > shows scroll arrows correctly when useAlternateBuffer is false 1`] = `
"Choose an option
@@ -163,48 +75,6 @@ Enter to select · ↑/↓ to navigate · Esc to cancel
"
`;
exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: true) > shows scroll arrows correctly when useAlternateBuffer is true 2`] = `
"
ERROR Cannot read properties of undefined (reading '$$typeof')
/Users/spencertang/Workspace/gemini-cli/node_modules/react/cjs/react.development.js:1208:15
1205: };
1206: exports.useContext = function (Context) {
1207: var dispatcher = resolveDispatcher();
1208: Context.$$typeof === REACT_CONSUMER_TYPE &&
1209: console.error(
1210 "Calling useContext(Context.Consumer) is not supported and will cause bugs. Did you
: mean to call useContext(Context) instead?"
1211: );
-process.env.NODE_ENV.exports
useContext (/Users/spencertang/Workspace/gemini-cli/node_modules/react/cjs/react
.development.js:1208:15)
- useTerminalCapabilities (src/ui/hooks/useTerminalCapabilities.ts:15:19)
- useAlternateBuffer (src/ui/hooks/useAlternateBuffer.ts:15:24)
- ChoiceQuestionView (src/ui/components/AskUserDialog.tsx:484:29)
-Object.react-stack-bott
m-frame (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs
/react-reconciler.development.js:15859:20)
-renderWithHoo
s (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-rec
onciler.development.js:3221:22)
-updateFunctionComp
nent (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/reac
t-reconciler.development.js:6475:19)
-beginWor
(/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-reconcil
er.development.js:8009:18)
-runWithFiberIn
EV (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-re
conciler.development.js:1738:13)
-performUnitOfW
rk (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-re
conciler.development.js:12834:22)
"
`;
exports[`AskUserDialog > Text type questions > renders text input for type: "text" 1`] = `
"What should we name this component?
@@ -331,45 +201,3 @@ README → (not answered)
Enter to submit · Tab/Shift+Tab to edit answers · Esc to cancel
"
`;
exports[`AskUserDialog > shows warning for unanswered questions on Review tab 2`] = `
"
ERROR Cannot read properties of undefined (reading '$$typeof')
/Users/spencertang/Workspace/gemini-cli/node_modules/react/cjs/react.development.js:1208:15
1205: };
1206: exports.useContext = function (Context) {
1207: var dispatcher = resolveDispatcher();
1208: Context.$$typeof === REACT_CONSUMER_TYPE &&
1209: console.error(
1210: "Calling useContext(Context.Consumer) is not supported and will cause bugs. Did you mean to call
useContext(Context) instead?"
1211: );
-process.env.NODE_ENV.exports.useCo
text (/Users/spencertang/Workspace/gemini-cli/node_modules/react/cjs/react.development.j
s:1208:15)
- useTerminalCapabilities (src/ui/hooks/useTerminalCapabilities.ts:15:19)
- useAlternateBuffer (src/ui/hooks/useAlternateBuffer.ts:15:24)
- ChoiceQuestionView (src/ui/components/AskUserDialog.tsx:484:29)
-Object.react-stack-botto
-frame (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-reconciler.d
evelopment.js:15859:20)
-renderWithHook
(/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-reconciler.development
.js:3221:22)
-updateFunctionCompo
ent (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-reconciler.develo
pment.js:6475:19)
-beginWork
(/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-reconciler.development.js:8
009:18)
-runWithFiberInD
V (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-reconciler.developmen
t.js:1738:13)
-performUnitOfWo
k (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-reconciler.developmen
t.js:12834:22)
"
`;
@@ -6,51 +6,6 @@ Spinner Initializing...
"
`;
exports[`ConfigInitDisplay > handles empty clients map 2`] = `
"
ERROR Cannot read properties of undefined (reading 'isKittyProtocolEnabled')
src/ui/contexts/KeypressContext.tsx:797:36
794: process.stdin.setEncoding('utf8'); // Make data events emit strings
795:
796: let processor = nonKeyboardEventFilter(broadcast);
797: if (!terminalCapabilityManager.isKittyProtocolEnabled()) {
798: processor = bufferFastReturn(processor);
799: }
800: processor = bufferBackslashEnter(processor);
- (src/ui/contexts/KeypressContext.tsx:797:36)
-Object.react-stack-bott
m-frame (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs
/react-reconciler.development.js:15945:20)
-runWithFiberIn
EV (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-re
conciler.development.js:1738:13)
-commitHookEffectList
ount (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
act-reconciler.development.js:9516:29)
-commitHookPassiveMount
ffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/
react-reconciler.development.js:9639:11)
-commitPassiveMountOn
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
act-reconciler.development.js:11364:13)
-recursivelyTraversePassiveM
untEffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler
/cjs/react-reconciler.development.js:11338:11)
-commitPassiveMountOn
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
act-reconciler.development.js:11479:11)
-recursivelyTraversePassiveM
untEffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler
/cjs/react-reconciler.development.js:11338:11)
-commitPassiveMountOn
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
act-reconciler.development.js:11357:11)
"
`;
exports[`ConfigInitDisplay > renders initial state 1`] = `
"
Spinner Initializing...
@@ -63,98 +18,8 @@ Spinner Connecting to MCP servers... (0/5) - Waiting for: s1, s2, s3, +2 more
"
`;
exports[`ConfigInitDisplay > truncates list of waiting servers if too many 2`] = `
"
ERROR Cannot read properties of undefined (reading 'isKittyProtocolEnabled')
src/ui/contexts/KeypressContext.tsx:797:36
794: process.stdin.setEncoding('utf8'); // Make data events emit strings
795:
796: let processor = nonKeyboardEventFilter(broadcast);
797: if (!terminalCapabilityManager.isKittyProtocolEnabled()) {
798: processor = bufferFastReturn(processor);
799: }
800: processor = bufferBackslashEnter(processor);
- (src/ui/contexts/KeypressContext.tsx:797:36)
-Object.react-stack-bott
m-frame (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs
/react-reconciler.development.js:15945:20)
-runWithFiberIn
EV (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-re
conciler.development.js:1738:13)
-commitHookEffectList
ount (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
act-reconciler.development.js:9516:29)
-commitHookPassiveMount
ffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/
react-reconciler.development.js:9639:11)
-commitPassiveMountOn
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
act-reconciler.development.js:11364:13)
-recursivelyTraversePassiveM
untEffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler
/cjs/react-reconciler.development.js:11338:11)
-commitPassiveMountOn
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
act-reconciler.development.js:11479:11)
-recursivelyTraversePassiveM
untEffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler
/cjs/react-reconciler.development.js:11338:11)
-commitPassiveMountOn
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
act-reconciler.development.js:11357:11)
"
`;
exports[`ConfigInitDisplay > updates message on McpClientUpdate event 1`] = `
"
Spinner Connecting to MCP servers... (1/2) - Waiting for: server2
"
`;
exports[`ConfigInitDisplay > updates message on McpClientUpdate event 2`] = `
"
ERROR Cannot read properties of undefined (reading 'isKittyProtocolEnabled')
src/ui/contexts/KeypressContext.tsx:797:36
794: process.stdin.setEncoding('utf8'); // Make data events emit strings
795:
796: let processor = nonKeyboardEventFilter(broadcast);
797: if (!terminalCapabilityManager.isKittyProtocolEnabled()) {
798: processor = bufferFastReturn(processor);
799: }
800: processor = bufferBackslashEnter(processor);
- (src/ui/contexts/KeypressContext.tsx:797:36)
-Object.react-stack-bott
m-frame (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs
/react-reconciler.development.js:15945:20)
-runWithFiberIn
EV (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/react-re
conciler.development.js:1738:13)
-commitHookEffectList
ount (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
act-reconciler.development.js:9516:29)
-commitHookPassiveMount
ffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/
react-reconciler.development.js:9639:11)
-commitPassiveMountOn
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
act-reconciler.development.js:11364:13)
-recursivelyTraversePassiveM
untEffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler
/cjs/react-reconciler.development.js:11338:11)
-commitPassiveMountOn
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
act-reconciler.development.js:11479:11)
-recursivelyTraversePassiveM
untEffects (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler
/cjs/react-reconciler.development.js:11338:11)
-commitPassiveMountOn
iber (/Users/spencertang/Workspace/gemini-cli/node_modules/react-reconciler/cjs/re
act-reconciler.development.js:11357:11)
"
`;
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,378 @@
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { TerminalCapabilityManager } from './terminalCapabilityManager.js';
import { EventEmitter } from 'node:events';
import {
enableKittyKeyboardProtocol,
enableModifyOtherKeys,
} from '@google/gemini-cli-core';
import * as fs from 'node:fs';
// Mock fs
vi.mock('node:fs', () => ({
writeSync: vi.fn(),
}));
// Mock core
vi.mock('@google/gemini-cli-core', () => ({
debugLogger: {
log: vi.fn(),
warn: vi.fn(),
},
enableKittyKeyboardProtocol: vi.fn(),
disableKittyKeyboardProtocol: vi.fn(),
enableModifyOtherKeys: vi.fn(),
disableModifyOtherKeys: vi.fn(),
enableBracketedPasteMode: vi.fn(),
disableBracketedPasteMode: vi.fn(),
}));
describe('TerminalCapabilityManager', () => {
let stdin: EventEmitter & {
isTTY?: boolean;
isRaw?: boolean;
setRawMode?: (mode: boolean) => void;
removeListener?: (
event: string,
listener: (...args: unknown[]) => void,
) => void;
};
let stdout: { isTTY?: boolean; fd?: number };
// Save original process properties
const originalStdin = process.stdin;
const originalStdout = process.stdout;
beforeEach(() => {
vi.resetAllMocks();
// Reset singleton
TerminalCapabilityManager.resetInstanceForTesting();
// Setup process mocks
stdin = new EventEmitter();
stdin.isTTY = true;
stdin.isRaw = false;
stdin.setRawMode = vi.fn();
stdin.removeListener = vi.fn();
stdout = { isTTY: true, fd: 1 };
// Use defineProperty to mock process.stdin/stdout
Object.defineProperty(process, 'stdin', {
value: stdin,
configurable: true,
});
Object.defineProperty(process, 'stdout', {
value: stdout,
configurable: true,
});
vi.useFakeTimers();
});
afterEach(() => {
vi.useRealTimers();
// Restore original process properties
Object.defineProperty(process, 'stdin', {
value: originalStdin,
configurable: true,
});
Object.defineProperty(process, 'stdout', {
value: originalStdout,
configurable: true,
});
});
it('should detect Kitty support when u response is received', async () => {
const manager = TerminalCapabilityManager.getInstance();
const promise = manager.detectCapabilities();
// Simulate Kitty response: \x1b[?1u
stdin.emit('data', Buffer.from('\x1b[?1u'));
// Complete detection with DA1
stdin.emit('data', Buffer.from('\x1b[?62c'));
await promise;
expect(manager.isKittyProtocolEnabled()).toBe(true);
});
it('should detect Background Color', async () => {
const manager = TerminalCapabilityManager.getInstance();
const promise = manager.detectCapabilities();
// Simulate OSC 11 response
// \x1b]11;rgb:0000/ff00/0000\x1b\
// RGB: 0, 255, 0 -> #00ff00
stdin.emit('data', Buffer.from('\x1b]11;rgb:0000/ffff/0000\x1b\\'));
// Complete detection with DA1
stdin.emit('data', Buffer.from('\x1b[?62c'));
await promise;
expect(manager.getTerminalBackgroundColor()).toBe('#00ff00');
});
it('should detect Terminal Name', async () => {
const manager = TerminalCapabilityManager.getInstance();
const promise = manager.detectCapabilities();
// Simulate Terminal Name response
stdin.emit('data', Buffer.from('\x1bP>|WezTerm 20240203\x1b\\'));
// Complete detection with DA1
stdin.emit('data', Buffer.from('\x1b[?62c'));
await promise;
expect(manager.getTerminalName()).toBe('WezTerm 20240203');
});
it('should complete early if sentinel (DA1) is found', async () => {
const manager = TerminalCapabilityManager.getInstance();
const promise = manager.detectCapabilities();
stdin.emit('data', Buffer.from('\x1b[?1u'));
stdin.emit('data', Buffer.from('\x1b]11;rgb:0000/0000/0000\x1b\\'));
// Sentinel
stdin.emit('data', Buffer.from('\x1b[?62c'));
// Should resolve without waiting for timeout
await promise;
expect(manager.isKittyProtocolEnabled()).toBe(true);
expect(manager.getTerminalBackgroundColor()).toBe('#000000');
});
it('should timeout if no DA1 (c) is received', async () => {
const manager = TerminalCapabilityManager.getInstance();
const promise = manager.detectCapabilities();
// Simulate only Kitty response
stdin.emit('data', Buffer.from('\x1b[?1u'));
// Advance to timeout
vi.advanceTimersByTime(1000);
await promise;
expect(manager.isKittyProtocolEnabled()).toBe(true);
});
it('should not detect Kitty if only DA1 (c) is received', async () => {
const manager = TerminalCapabilityManager.getInstance();
const promise = manager.detectCapabilities();
// Simulate DA1 response only: \x1b[?62;c
stdin.emit('data', Buffer.from('\x1b[?62c'));
await promise;
expect(manager.isKittyProtocolEnabled()).toBe(false);
});
it('should handle split chunks', async () => {
const manager = TerminalCapabilityManager.getInstance();
const promise = manager.detectCapabilities();
// Split response: \x1b[? 1u
stdin.emit('data', Buffer.from('\x1b[?'));
stdin.emit('data', Buffer.from('1u'));
// Complete with DA1
stdin.emit('data', Buffer.from('\x1b[?62c'));
await promise;
expect(manager.isKittyProtocolEnabled()).toBe(true);
});
describe('modifyOtherKeys detection', () => {
it('should detect modifyOtherKeys support (level 2)', async () => {
const manager = TerminalCapabilityManager.getInstance();
const promise = manager.detectCapabilities();
// Simulate modifyOtherKeys level 2 response: \x1b[>4;2m
stdin.emit('data', Buffer.from('\x1b[>4;2m'));
// Complete detection with DA1
stdin.emit('data', Buffer.from('\x1b[?62c'));
await promise;
expect(enableModifyOtherKeys).toHaveBeenCalled();
});
it('should not enable modifyOtherKeys for level 0', async () => {
const manager = TerminalCapabilityManager.getInstance();
const promise = manager.detectCapabilities();
// Simulate modifyOtherKeys level 0 response: \x1b[>4;0m
stdin.emit('data', Buffer.from('\x1b[>4;0m'));
// Complete detection with DA1
stdin.emit('data', Buffer.from('\x1b[?62c'));
await promise;
expect(enableModifyOtherKeys).not.toHaveBeenCalled();
});
it('should prefer Kitty over modifyOtherKeys', async () => {
const manager = TerminalCapabilityManager.getInstance();
const promise = manager.detectCapabilities();
// Simulate both Kitty and modifyOtherKeys responses
stdin.emit('data', Buffer.from('\x1b[?1u'));
stdin.emit('data', Buffer.from('\x1b[>4;2m'));
// Complete detection with DA1
stdin.emit('data', Buffer.from('\x1b[?62c'));
await promise;
expect(manager.isKittyProtocolEnabled()).toBe(true);
expect(enableKittyKeyboardProtocol).toHaveBeenCalled();
expect(enableModifyOtherKeys).not.toHaveBeenCalled();
});
it('should enable modifyOtherKeys when Kitty not supported', async () => {
const manager = TerminalCapabilityManager.getInstance();
const promise = manager.detectCapabilities();
// Simulate only modifyOtherKeys response (no Kitty)
stdin.emit('data', Buffer.from('\x1b[>4;2m'));
// Complete detection with DA1
stdin.emit('data', Buffer.from('\x1b[?62c'));
await promise;
expect(manager.isKittyProtocolEnabled()).toBe(false);
expect(enableModifyOtherKeys).toHaveBeenCalled();
});
it('should handle split modifyOtherKeys response chunks', async () => {
const manager = TerminalCapabilityManager.getInstance();
const promise = manager.detectCapabilities();
// Split response: \x1b[>4;2m
stdin.emit('data', Buffer.from('\x1b[>4;'));
stdin.emit('data', Buffer.from('2m'));
// Complete detection with DA1
stdin.emit('data', Buffer.from('\x1b[?62c'));
await promise;
expect(enableModifyOtherKeys).toHaveBeenCalled();
});
it('should detect modifyOtherKeys with other capabilities', async () => {
const manager = TerminalCapabilityManager.getInstance();
const promise = manager.detectCapabilities();
stdin.emit('data', Buffer.from('\x1b]11;rgb:1a1a/1a1a/1a1a\x1b\\')); // background color
stdin.emit('data', Buffer.from('\x1bP>|tmux\x1b\\')); // Terminal name
stdin.emit('data', Buffer.from('\x1b[>4;2m')); // modifyOtherKeys
// Complete detection with DA1
stdin.emit('data', Buffer.from('\x1b[?62c'));
await promise;
expect(manager.getTerminalBackgroundColor()).toBe('#1a1a1a');
expect(manager.getTerminalName()).toBe('tmux');
expect(enableModifyOtherKeys).toHaveBeenCalled();
});
it('should not enable modifyOtherKeys without explicit response', async () => {
const manager = TerminalCapabilityManager.getInstance();
const promise = manager.detectCapabilities();
// Simulate only DA1 response (no specific MOK or Kitty response)
stdin.emit('data', Buffer.from('\x1b[?62c'));
await promise;
expect(manager.isKittyProtocolEnabled()).toBe(false);
expect(enableModifyOtherKeys).not.toHaveBeenCalled();
});
it('should wrap queries in hidden/clear sequence', async () => {
const manager = TerminalCapabilityManager.getInstance();
void manager.detectCapabilities();
expect(fs.writeSync).toHaveBeenCalledWith(
expect.anything(),
// eslint-disable-next-line no-control-regex
expect.stringMatching(/^\x1b\[8m.*\x1b\[2K\r\x1b\[0m$/s),
);
});
});
describe('supportsOsc9Notifications', () => {
const manager = TerminalCapabilityManager.getInstance();
it.each([
{
name: 'WezTerm (terminal name)',
terminalName: 'WezTerm',
env: {},
expected: true,
},
{
name: 'iTerm.app (terminal name)',
terminalName: 'iTerm.app',
env: {},
expected: true,
},
{
name: 'ghostty (terminal name)',
terminalName: 'ghostty',
env: {},
expected: true,
},
{
name: 'kitty (terminal name)',
terminalName: 'kitty',
env: {},
expected: true,
},
{
name: 'some-other-term (terminal name)',
terminalName: 'some-other-term',
env: {},
expected: false,
},
{
name: 'iTerm.app (TERM_PROGRAM)',
terminalName: undefined,
env: { TERM_PROGRAM: 'iTerm.app' },
expected: true,
},
{
name: 'vscode (TERM_PROGRAM)',
terminalName: undefined,
env: { TERM_PROGRAM: 'vscode' },
expected: false,
},
{
name: 'xterm-kitty (TERM)',
terminalName: undefined,
env: { TERM: 'xterm-kitty' },
expected: true,
},
{
name: 'xterm-256color (TERM)',
terminalName: undefined,
env: { TERM: 'xterm-256color' },
expected: false,
},
{
name: 'Windows Terminal (WT_SESSION)',
terminalName: 'iTerm.app',
env: { WT_SESSION: 'some-guid' },
expected: false,
},
])(
'should return $expected for $name',
({ terminalName, env, expected }) => {
vi.spyOn(manager, 'getTerminalName').mockReturnValue(terminalName);
expect(manager.supportsOsc9Notifications(env)).toBe(expected);
},
);
});
});
@@ -84,7 +84,6 @@ describe('SubAgentInvocation', () => {
params: {},
getDescription: vi.fn(),
toolLocations: vi.fn(),
isSensitive: false,
};
MockSubagentToolWrapper.prototype.build = vi
@@ -121,7 +121,6 @@ export interface UpdatePolicy {
argsPattern?: string;
commandPrefix?: string | string[];
mcpName?: string;
isSensitive?: boolean;
}
export interface ToolPolicyRejection {
+2 -11
View File
@@ -43,15 +43,7 @@ class ActivateSkillToolInvocation extends BaseToolInvocation<
_toolName?: string,
_toolDisplayName?: string,
) {
super(
params,
messageBus,
_toolName,
_toolDisplayName,
undefined,
undefined,
true, // ActivateSkill is always sensitive
);
super(params, messageBus, _toolName, _toolDisplayName);
}
getDescription(): string {
@@ -193,14 +185,13 @@ export class ActivateSkillTool extends BaseDeclarativeTool<
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
_isSensitive?: boolean,
): ToolInvocation<ActivateSkillToolParams, ToolResult> {
return new ActivateSkillToolInvocation(
this.config,
params,
messageBus,
_toolName,
_toolDisplayName,
_toolDisplayName ?? 'Activate Skill',
);
}
-1
View File
@@ -293,7 +293,6 @@ describe('AskUserTool', () => {
getDescription: vi.fn().mockReturnValue(''),
toolLocations: vi.fn().mockReturnValue([]),
shouldConfirmExecute: vi.fn().mockResolvedValue(false),
isSensitive: false,
};
const buildSpy = vi.spyOn(tool, 'build').mockReturnValue(mockInvocation);
-15
View File
@@ -202,21 +202,6 @@ describe('EditTool', () => {
fs.rmSync(tempDir, { recursive: true, force: true });
});
it('should be marked as sensitive and pass the flag to its invocations', () => {
// Check the tool definition itself
expect(tool.isSensitive).toBe(true);
// Build an invocation and check the instance
const params: EditToolParams = {
file_path: path.join(rootDir, 'test.txt'),
instruction: 'An instruction',
old_string: 'old',
new_string: 'new',
};
const invocation = tool.build(params);
expect(invocation.isSensitive).toBe(true);
});
describe('applyReplacement', () => {
it('should return newString if isNewFile is true', () => {
expect(applyReplacement(null, 'old', 'new', true)).toBe('new');
+1 -17
View File
@@ -434,17 +434,8 @@ class EditToolInvocation
messageBus: MessageBus,
toolName?: string,
displayName?: string,
isSensitive?: boolean,
) {
super(
params,
messageBus,
toolName,
displayName,
undefined,
undefined,
isSensitive,
);
super(params, messageBus, toolName, displayName);
}
override toolLocations(): ToolLocation[] {
@@ -965,9 +956,6 @@ export class EditTool
messageBus,
true, // isOutputMarkdown
false, // canUpdateOutput
undefined,
undefined,
true,
);
}
@@ -1013,9 +1001,6 @@ export class EditTool
protected createInvocation(
params: EditToolParams,
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
): ToolInvocation<EditToolParams, ToolResult> {
return new EditToolInvocation(
this.config,
@@ -1023,7 +1008,6 @@ export class EditTool
messageBus,
this.name,
this.displayName,
isSensitive,
);
}
+1 -15
View File
@@ -79,17 +79,8 @@ class GetInternalDocsInvocation extends BaseToolInvocation<
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
) {
super(
params,
messageBus,
_toolName,
_toolDisplayName,
undefined,
undefined,
isSensitive,
);
super(params, messageBus, _toolName, _toolDisplayName);
}
override async shouldConfirmExecute(
@@ -174,9 +165,6 @@ export class GetInternalDocsTool extends BaseDeclarativeTool<
messageBus,
/* isOutputMarkdown */ true,
/* canUpdateOutput */ false,
undefined,
undefined,
true,
);
}
@@ -185,14 +173,12 @@ export class GetInternalDocsTool extends BaseDeclarativeTool<
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
): ToolInvocation<GetInternalDocsParams, ToolResult> {
return new GetInternalDocsInvocation(
params,
messageBus,
_toolName ?? GetInternalDocsTool.Name,
_toolDisplayName,
isSensitive,
);
}
+1 -15
View File
@@ -96,17 +96,8 @@ class GlobToolInvocation extends BaseToolInvocation<
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
) {
super(
params,
messageBus,
_toolName,
_toolDisplayName,
undefined,
undefined,
isSensitive,
);
super(params, messageBus, _toolName, _toolDisplayName);
}
getDescription(): string {
@@ -287,9 +278,6 @@ export class GlobTool extends BaseDeclarativeTool<GlobToolParams, ToolResult> {
messageBus,
true,
false,
undefined,
undefined,
true,
);
}
@@ -340,7 +328,6 @@ export class GlobTool extends BaseDeclarativeTool<GlobToolParams, ToolResult> {
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
): ToolInvocation<GlobToolParams, ToolResult> {
return new GlobToolInvocation(
this.config,
@@ -348,7 +335,6 @@ export class GlobTool extends BaseDeclarativeTool<GlobToolParams, ToolResult> {
messageBus,
_toolName,
_toolDisplayName,
isSensitive,
);
}
+1 -15
View File
@@ -83,17 +83,8 @@ class GrepToolInvocation extends BaseToolInvocation<
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
) {
super(
params,
messageBus,
_toolName,
_toolDisplayName,
undefined,
undefined,
isSensitive,
);
super(params, messageBus, _toolName, _toolDisplayName);
this.fileExclusions = config.getFileExclusions();
}
@@ -610,9 +601,6 @@ export class GrepTool extends BaseDeclarativeTool<GrepToolParams, ToolResult> {
messageBus,
true,
false,
undefined,
undefined,
true,
);
}
@@ -688,7 +676,6 @@ export class GrepTool extends BaseDeclarativeTool<GrepToolParams, ToolResult> {
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
): ToolInvocation<GrepToolParams, ToolResult> {
return new GrepToolInvocation(
this.config,
@@ -696,7 +683,6 @@ export class GrepTool extends BaseDeclarativeTool<GrepToolParams, ToolResult> {
messageBus,
_toolName,
_toolDisplayName,
isSensitive,
);
}
+2 -16
View File
@@ -78,17 +78,8 @@ class LSToolInvocation extends BaseToolInvocation<LSToolParams, ToolResult> {
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
) {
super(
params,
messageBus,
_toolName,
_toolDisplayName,
undefined,
undefined,
isSensitive,
);
super(params, messageBus, _toolName, _toolDisplayName);
}
/**
@@ -302,9 +293,6 @@ export class LSTool extends BaseDeclarativeTool<LSToolParams, ToolResult> {
messageBus,
true,
false,
undefined,
undefined,
true,
);
}
@@ -328,15 +316,13 @@ export class LSTool extends BaseDeclarativeTool<LSToolParams, ToolResult> {
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
): ToolInvocation<LSToolParams, ToolResult> {
return new LSToolInvocation(
this.config,
params,
messageBus,
messageBus ?? this.messageBus,
_toolName,
_toolDisplayName,
isSensitive,
);
}
-5
View File
@@ -93,7 +93,6 @@ export class DiscoveredMCPToolInvocation extends BaseToolInvocation<
private readonly toolDescription?: string,
private readonly toolParameterSchema?: unknown,
toolAnnotationsData?: Record<string, unknown>,
isSensitive: boolean = false,
) {
// Use composite format for policy checks: serverName__toolName
// This enables server wildcards (e.g., "google-workspace__*")
@@ -106,7 +105,6 @@ export class DiscoveredMCPToolInvocation extends BaseToolInvocation<
displayName,
serverName,
toolAnnotationsData,
isSensitive,
);
}
@@ -285,7 +283,6 @@ export class DiscoveredMCPTool extends BaseDeclarativeTool<
false, // canUpdateOutput,
extensionName,
extensionId,
true, // isSensitive
);
this._isReadOnly = isReadOnly;
}
@@ -334,7 +331,6 @@ export class DiscoveredMCPTool extends BaseDeclarativeTool<
messageBus: MessageBus,
_toolName?: string,
_displayName?: string,
isSensitive?: boolean,
): ToolInvocation<ToolParams, ToolResult> {
return new DiscoveredMCPToolInvocation(
this.mcpTool,
@@ -348,7 +344,6 @@ export class DiscoveredMCPTool extends BaseDeclarativeTool<
this.description,
this.parameterSchema,
this._toolAnnotations,
isSensitive,
);
}
}
-3
View File
@@ -285,9 +285,6 @@ export class MemoryTool
messageBus,
true,
false,
undefined,
undefined,
true,
);
}
+1 -15
View File
@@ -114,17 +114,8 @@ class ReadManyFilesToolInvocation extends BaseToolInvocation<
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
) {
super(
params,
messageBus,
_toolName,
_toolDisplayName,
undefined,
undefined,
isSensitive,
);
super(params, messageBus, _toolName, _toolDisplayName);
}
getDescription(): string {
@@ -483,9 +474,6 @@ export class ReadManyFilesTool extends BaseDeclarativeTool<
messageBus,
true, // isOutputMarkdown
false, // canUpdateOutput
undefined,
undefined,
true,
);
}
@@ -494,7 +482,6 @@ export class ReadManyFilesTool extends BaseDeclarativeTool<
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
): ToolInvocation<ReadManyFilesParams, ToolResult> {
return new ReadManyFilesToolInvocation(
this.config,
@@ -502,7 +489,6 @@ export class ReadManyFilesTool extends BaseDeclarativeTool<
messageBus,
_toolName,
_toolDisplayName,
isSensitive,
);
}
+2 -16
View File
@@ -167,17 +167,8 @@ class GrepToolInvocation extends BaseToolInvocation<
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
) {
super(
params,
messageBus,
_toolName,
_toolDisplayName,
undefined,
undefined,
isSensitive,
);
super(params, messageBus, _toolName, _toolDisplayName);
}
async execute(signal: AbortSignal): Promise<ToolResult> {
@@ -593,9 +584,6 @@ export class RipGrepTool extends BaseDeclarativeTool<
messageBus,
true, // isOutputMarkdown
false, // canUpdateOutput
undefined,
undefined,
true,
);
this.fileDiscoveryService = new FileDiscoveryService(
config.getTargetDir(),
@@ -677,16 +665,14 @@ export class RipGrepTool extends BaseDeclarativeTool<
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
): ToolInvocation<RipGrepToolParams, ToolResult> {
return new GrepToolInvocation(
this.config,
this.fileDiscoveryService,
params,
messageBus,
messageBus ?? this.messageBus,
_toolName,
_toolDisplayName,
isSensitive,
);
}
+1 -15
View File
@@ -68,17 +68,8 @@ export class ShellToolInvocation extends BaseToolInvocation<
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
) {
super(
params,
messageBus,
_toolName,
_toolDisplayName,
undefined,
undefined,
isSensitive,
);
super(params, messageBus, _toolName, _toolDisplayName);
}
getDescription(): string {
@@ -488,9 +479,6 @@ export class ShellTool extends BaseDeclarativeTool<
messageBus,
false, // output is not markdown
true, // output can be updated
undefined,
undefined,
true,
);
}
@@ -516,7 +504,6 @@ export class ShellTool extends BaseDeclarativeTool<
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
): ToolInvocation<ShellToolParams, ToolResult> {
return new ShellToolInvocation(
this.config,
@@ -524,7 +511,6 @@ export class ShellTool extends BaseDeclarativeTool<
messageBus,
_toolName,
_toolDisplayName,
isSensitive,
);
}
-1
View File
@@ -16,7 +16,6 @@ class TestToolInvocation implements ToolInvocation<object, ToolResult> {
constructor(
readonly params: object,
private readonly executeFn: () => Promise<ToolResult>,
readonly isSensitive: boolean = false,
) {}
getDescription(): string {
-46
View File
@@ -33,11 +33,6 @@ export interface ToolInvocation<
*/
params: TParams;
/**
* Whether the tool is sensitive and requires specific policy approvals.
*/
isSensitive: boolean;
/**
* Gets a pre-execution description of the tool operation.
*
@@ -80,7 +75,6 @@ export interface ToolInvocation<
export interface PolicyUpdateOptions {
commandPrefix?: string | string[];
mcpName?: string;
argsPattern?: string;
}
/**
@@ -98,7 +92,6 @@ export abstract class BaseToolInvocation<
readonly _toolDisplayName?: string,
readonly _serverName?: string,
readonly _toolAnnotations?: Record<string, unknown>,
readonly isSensitive: boolean = false,
) {}
abstract getDescription(): string;
@@ -159,7 +152,6 @@ export abstract class BaseToolInvocation<
type: MessageBusType.UPDATE_POLICY,
toolName: this._toolName,
persist: outcome === ToolConfirmationOutcome.ProceedAlwaysAndSave,
isSensitive: this.isSensitive,
...options,
});
}
@@ -348,11 +340,6 @@ export interface ToolBuilder<
*/
isReadOnly: boolean;
/**
* Whether the tool is sensitive and requires specific policy approvals.
*/
isSensitive: boolean;
/**
* Validates raw parameters and builds a ready-to-execute invocation.
* @param params The raw, untrusted parameters from the model.
@@ -381,7 +368,6 @@ export abstract class DeclarativeTool<
readonly canUpdateOutput: boolean = false,
readonly extensionName?: string,
readonly extensionId?: string,
readonly isSensitive: boolean = false,
) {}
get isReadOnly(): boolean {
@@ -512,34 +498,6 @@ export abstract class BaseDeclarativeTool<
TParams extends object,
TResult extends ToolResult,
> extends DeclarativeTool<TParams, TResult> {
constructor(
name: string,
displayName: string,
description: string,
kind: Kind,
parameterSchema: unknown,
messageBus: MessageBus,
isOutputMarkdown: boolean = true,
canUpdateOutput: boolean = false,
extensionName?: string,
extensionId?: string,
isSensitive: boolean = false,
) {
super(
name,
displayName,
description,
kind,
parameterSchema,
messageBus,
isOutputMarkdown,
canUpdateOutput,
extensionName,
extensionId,
isSensitive,
);
}
build(params: TParams): ToolInvocation<TParams, TResult> {
const validationError = this.validateToolParams(params);
if (validationError) {
@@ -550,7 +508,6 @@ export abstract class BaseDeclarativeTool<
this.messageBus,
this.name,
this.displayName,
this.isSensitive,
);
}
@@ -576,7 +533,6 @@ export abstract class BaseDeclarativeTool<
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
): ToolInvocation<TParams, TResult>;
}
@@ -870,7 +826,6 @@ export enum ToolConfirmationOutcome {
export enum Kind {
Read = 'read',
Write = 'write',
Edit = 'edit',
Delete = 'delete',
Move = 'move',
@@ -887,7 +842,6 @@ export enum Kind {
// Function kinds that have side effects
export const MUTATOR_KINDS: Kind[] = [
Kind.Write,
Kind.Edit,
Kind.Delete,
Kind.Move,
+1 -15
View File
@@ -178,17 +178,8 @@ class WebFetchToolInvocation extends BaseToolInvocation<
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
) {
super(
params,
messageBus,
_toolName,
_toolDisplayName,
undefined,
undefined,
isSensitive,
);
super(params, messageBus, _toolName, _toolDisplayName);
}
private async executeFallback(signal: AbortSignal): Promise<ToolResult> {
@@ -698,9 +689,6 @@ export class WebFetchTool extends BaseDeclarativeTool<
messageBus,
true, // isOutputMarkdown
false, // canUpdateOutput
undefined,
undefined,
true,
);
}
@@ -741,7 +729,6 @@ export class WebFetchTool extends BaseDeclarativeTool<
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
): ToolInvocation<WebFetchToolParams, ToolResult> {
return new WebFetchToolInvocation(
this.config,
@@ -749,7 +736,6 @@ export class WebFetchTool extends BaseDeclarativeTool<
messageBus,
_toolName,
_toolDisplayName,
isSensitive,
);
}
+1 -15
View File
@@ -71,17 +71,8 @@ class WebSearchToolInvocation extends BaseToolInvocation<
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
) {
super(
params,
messageBus,
_toolName,
_toolDisplayName,
undefined,
undefined,
isSensitive,
);
super(params, messageBus, _toolName, _toolDisplayName);
}
override getDescription(): string {
@@ -217,9 +208,6 @@ export class WebSearchTool extends BaseDeclarativeTool<
messageBus,
true, // isOutputMarkdown
false, // canUpdateOutput
undefined,
undefined,
true,
);
}
@@ -242,7 +230,6 @@ export class WebSearchTool extends BaseDeclarativeTool<
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
): ToolInvocation<WebSearchToolParams, WebSearchToolResult> {
return new WebSearchToolInvocation(
this.config,
@@ -250,7 +237,6 @@ export class WebSearchTool extends BaseDeclarativeTool<
messageBus ?? this.messageBus,
_toolName,
_toolDisplayName,
isSensitive,
);
}
+2 -18
View File
@@ -136,17 +136,8 @@ class WriteFileToolInvocation extends BaseToolInvocation<
messageBus: MessageBus,
toolName?: string,
displayName?: string,
isSensitive?: boolean,
) {
super(
params,
messageBus,
toolName,
displayName,
undefined,
undefined,
isSensitive,
);
super(params, messageBus, toolName, displayName);
this.resolvedPath = path.resolve(
this.config.getTargetDir(),
this.params.file_path,
@@ -438,14 +429,11 @@ export class WriteFileTool
WriteFileTool.Name,
WRITE_FILE_DISPLAY_NAME,
WRITE_FILE_DEFINITION.base.description!,
Kind.Write,
Kind.Edit,
WRITE_FILE_DEFINITION.base.parametersJsonSchema,
messageBus,
true,
false,
undefined,
undefined,
true,
);
}
@@ -489,9 +477,6 @@ export class WriteFileTool
protected createInvocation(
params: WriteFileToolParams,
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
): ToolInvocation<WriteFileToolParams, ToolResult> {
return new WriteFileToolInvocation(
this.config,
@@ -499,7 +484,6 @@ export class WriteFileTool
messageBus ?? this.messageBus,
this.name,
this.displayName,
isSensitive,
);
}
+1 -15
View File
@@ -34,17 +34,8 @@ class WriteTodosToolInvocation extends BaseToolInvocation<
messageBus: MessageBus,
_toolName?: string,
_toolDisplayName?: string,
isSensitive?: boolean,
) {
super(
params,
messageBus,
_toolName,
_toolDisplayName,
undefined,
undefined,
isSensitive,
);
super(params, messageBus, _toolName, _toolDisplayName);
}
getDescription(): string {
@@ -94,9 +85,6 @@ export class WriteTodosTool extends BaseDeclarativeTool<
messageBus,
true, // isOutputMarkdown
false, // canUpdateOutput
undefined,
undefined,
true,
);
}
@@ -140,14 +128,12 @@ export class WriteTodosTool extends BaseDeclarativeTool<
messageBus: MessageBus,
_toolName?: string,
_displayName?: string,
isSensitive?: boolean,
): ToolInvocation<WriteTodosToolParams, ToolResult> {
return new WriteTodosToolInvocation(
params,
messageBus,
_toolName,
_displayName,
isSensitive,
);
}
}