v1.2.0 - pluggable backends, approval mode, native sessions, Windows reliability, timeouts, tests#78
v1.2.0 - pluggable backends, approval mode, native sessions, Windows reliability, timeouts, tests#78jamubc wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request upgrades the server to version 1.2.0, introducing pluggable backends (Gemini CLI and experimental Antigravity CLI), native multi-turn sessions, approval modes, a per-command timeout mechanism, and a comprehensive test suite. It also hardens Windows execution by passing complex prompts via stdin and resolving executable shims. Feedback was provided to prevent potential server crashes by handling stdin write errors, and to ensure that timed-out processes on Windows are fully terminated along with their child trees rather than leaving orphaned background processes.
There was a problem hiding this comment.
Pull request overview
This PR is a v1.2.0 feature release that refactors CLI execution to support pluggable backends (Gemini CLI + experimental Antigravity agy), adds opt-in approval modes and native multi-turn session flags, improves Windows reliability, introduces per-command timeouts, and adds a real node:test-based test suite.
Changes:
- Introduces a backend abstraction (
src/backends/*) and routesexecuteGeminiCLI()through the selected backend (GEMINI_MCP_BACKEND). - Adds approval/session CLI flag plumbing and Windows reliability improvements (stdin routing for complex prompts, executable resolution,
windowsHide). - Adds timeout management + a test runner and updates build/test packaging (new
tsconfig.build.json,npm testruns real tests).
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tsconfig.build.json | Build-only tsconfig excluding tests/scripts from dist/. |
| src/utils/timeoutManager.ts | Adds env-driven per-command timeout parsing. |
| src/utils/timeoutManager.test.ts | Unit tests for timeout parsing behavior. |
| src/utils/geminiExecutor.ts | Refactors execution to a backend-driven model; stdin routing for complex prompts; adds options object. |
| src/utils/geminiExecutor.test.ts | Tests for @file containment guard. |
| src/utils/commandExecutor.ts | Adds Windows executable resolution, stdin support, ENOENT guidance, and per-command timeout kill logic. |
| src/utils/commandExecutor.test.ts | Tests for cmd quoting, resolution no-op off Windows, and ENOENT guidance text. |
| src/tools/simple-tools.ts | Uses CLI constants for echo and fixes Help tool to use --help. |
| src/tools/brainstorm.tool.ts | Adds approvalMode arg and forwards execution via new executeGeminiCLI options. |
| src/tools/ask-gemini.tool.ts | Adds approvalMode + session args; forwards via options object; appends session note. |
| src/index.ts | Reads server version from package.json at runtime. |
| src/constants.ts | Adds approval modes, env var names, and new CLI flags/commands. |
| src/backends/types.ts | Defines backend interface + run options. |
| src/backends/index.ts | Implements backend selection via GEMINI_MCP_BACKEND. |
| src/backends/index.test.ts | Tests backend selection logic. |
| src/backends/gemini.ts | Gemini backend implementation incl. approval/session args and Flash fallback on quota exhaustion. |
| src/backends/gemini.test.ts | Tests approval-mode resolution + arg building. |
| src/backends/agy.ts | Experimental Antigravity CLI backend with transcript-based output recovery. |
| src/backends/agy.test.ts | Tests agy arg mapping. |
| SECURITY-REPORT-2026-05-28.md | Adds security audit report document. |
| scripts/run-tests.mjs | Adds a test discovery + execution script for node:test with tsx. |
| package.json | Bumps version to 1.2.0; adds real tests, build config, prepare script; raises Node floor to >=18. |
| CHANGELOG.md | Documents 1.2.0 release notes and clarifies 1.1.6 entry. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ndows reliability, timeouts, tests A feature release for the 1.2.0 line, on top of the 1.1.6 security patch. Hardens cross-platform execution, adds an opt-in safety control and native multi-turn sessions, makes the CLI backend pluggable ahead of the Gemini CLI retirement (2026-06-18 -> Antigravity agy), and adds a real test suite. - Backend abstraction (src/backends/): the Gemini CLI stays the default; add an experimental Antigravity CLI (agy) backend behind GEMINI_MCP_BACKEND, with a transcript-file fallback for agy's empty-stdout -p bug (Flash-only). - Opt-in approval mode: approvalMode arg + GEMINI_MCP_APPROVAL_MODE env forward gemini --approval-mode. Not forced by default — defaulting to 'plan' turns headless gemini into an autonomous planner that breaks plain Q&A. - Native multi-turn sessions: sessionId/resume forward gemini --session-id/--resume and the active session id is surfaced in the response. - Windows executable resolution: GEMINI_CLI_PATH, then 'where gemini' preferring the .cmd shim; plus platform-aware ENOENT guidance. - Per-command timeout (SIGTERM -> SIGKILL), GEMINI_MCP_TIMEOUT_MS (default 30m, 0 disables); implements the previously-empty timeoutManager. - Fix Help tool: 'gemini --help' (was '-help', mis-parsed by yargs as -h -e -l -p). - Read server version from package.json at runtime (was hardcoded, stale at 1.1.4); engines >=18; prepare script for Git-checkout installs. - Complex prompts (changeMode / @file) are sent on stdin instead of -p; windowsHide suppresses the popup console window on Windows. - node:test suite + tsconfig.build.json so tests are type-checked but not shipped in dist.
- commandExecutor: add an 'error' listener on child stdin so an EPIPE (child exited before reading) is logged instead of crashing the server (gemini-code-assist). - commandExecutor: on Windows, terminate timed-out processes with 'taskkill /pid <pid> /T /F' — with shell:true, kill() only hit cmd.exe and orphaned the real gemini/agy child (gemini-code-assist). - resolveCommandForExecution: prefer .cmd/.exe/.bat and stop preferring .ps1, which cmd.exe (shell:true) can't launch directly (Copilot). - run-tests.mjs: feature-detect the tsx loader — '--import tsx' on Node >=20.6, '--loader tsx' below (the >=18 floor lacks --import) (Copilot). - ask-gemini: don't emit 'latest' as a [session: ...] id and clarify it's the requested id, not one parsed from the CLI (Copilot).
…ent 1.2.0 env vars Closes #49. - GEMINI_MODEL sets the default model when a call doesn't pass one, so the assistant can't silently fall back to an older model (#49; also helps #51). GEMINI_FLASH_MODEL overrides the quota-fallback target. Precedence: per-call model arg > GEMINI_MODEL > Gemini CLI default. - New setup doctor (scripts/doctor.mjs, 'npm run doctor', and a 'gemini-mcp-doctor' bin): reports the active backend, detected gemini/agy installs (path + version), and the effective model/approval/timeout/env configuration with actionable hints. Self-contained, zero-dependency. - Docs: new README 'Environment Variables' + 'Setup Doctor' sections; document GEMINI_MODEL/GEMINI_FLASH_MODEL and the doctor across docs/concepts/ configuration.md, docs/concepts/models.md and docs/api.md; CHANGELOG entries.
…(agy) Maps the concrete divergences between the gemini and agy CLIs that affect a non-interactive MCP caller (empty -p stdout, Flash-only print mode, @file inlining, sandbox/approval semantics, sessions/concurrency, packaging/auth) and proposes phased solutions building on the pluggable backend from #78. Preliminary start to the migration ahead of the 2026-06-18 Gemini CLI retirement. Refs discussion #90.
Summary
First feature release after the 1.1.6 security patch. It hardens cross-platform execution, adds an opt-in safety control and native multi-turn sessions, a configurable default model, a setup doctor, and a real test suite — and it makes the CLI backend pluggable, preparing for the Gemini CLI retirement on 2026-06-18 (free/Pro/Ultra tiers) in favour of the Antigravity CLI (
agy).No default behaviour changes for existing users. Closes #49.
What's new
src/backends/). The executor is now backend-agnostic. The Gemini CLI stays the default; setGEMINI_MCP_BACKEND=agyto use the experimental Antigravity CLI backend. agy print-mode is Flash-only, and becauseagy -phas an empty-stdout bug in 1.0.x we fall back to reading agy's transcript files — verified end-to-end locally.GEMINI_MODELpins the model used when a call doesn't pass one, so the assistant can't silently fall back to an older model (Hope to be able to specify the model in MCP json settings #49; also helps Please update default togemini-3-pro-preview#51).GEMINI_FLASH_MODELoverrides the quota-fallback target. Precedence: per-callmodelarg →GEMINI_MODEL→ Gemini CLI default.npm run doctor(or thegemini-mcp-doctorbin /npx -p gemini-mcp-tool gemini-mcp-doctor) reports the active backend, detectedgemini/agyinstalls (path + version), and your effective model/approval/timeout/env configuration with actionable hints. Self-contained, zero-dependency.approvalModearg onask-gemini/brainstorm(+GEMINI_MCP_APPROVAL_MODE), forwardinggemini --approval-mode {default,auto_edit,yolo,plan}. Opt-in (see note below).sessionId/resumeforwardgemini --session-id/--resume(agy--conversation/--continue); the requested session id is echoed back, using the CLI's own sessions rather than local transcript storage.GEMINI_CLI_PATH, else resolves the realgeminishim viawhere(preferring.cmd/.exe/.bat), fixing "command not found" when the server doesn't inherit your shell PATH.taskkill /Ton Windows),GEMINI_MCP_TIMEOUT_MS(default 30m,0disables).Helpfix — callsgemini --helpinstead of-help(yargs mis-parsed it as-h -e -l -p).package.jsonat runtime (was hardcoded, stale at1.1.4);engines.node→>=18;preparescript for Git-checkout installs.node:testcoverage for the@fileguard, Windows quoting/resolution, approval-mode/model/session arg building, backend selection, and timeout parsing.tsconfig.build.jsonkeeps tests type-checked but out of the publisheddist/.Note: approval mode is opt-in, not defaulted to
planDefaulting
--approval-mode planwas considered but rejected. In headless-pmodeplanturns Gemini into an autonomous planner — for a trivial prompt it ignored the question, started exploring the repo, and errored withInvalid stream: empty response or malformed tool call. Both no flag (today's behaviour) and--approval-mode defaultanswer cleanly. So approval mode is left unset by default and a mode is only forwarded when the caller asks for one.Testing
npm run build(clean) ·npm run lint(type-checks tests too) ·npm test→ 18 passing.gemini(basic Q&A,--help), theagybackend, andnpm run doctor(default + env-override + invalid-value paths).Review feedback
All five findings from the gemini-code-assist and Copilot bot reviews were addressed in
4c9b9b3(stdin EPIPE guard, Windowstaskkillprocess-tree kill,.cmd/.exe/.batresolver ordering, tsx loader feature-detect, and the session-id echo no longer emittinglatest).Related / out of scope
--output-format stream-jsonreal streaming; promoting theagybackend from experimental onceagy -pstdout is fixed upstream.