feat: add Vertex AI Grok support with Google ADC#287
Conversation
Package tarballs should contain the current built CLI and public package metadata, not local agent state, editor rules, hooks, stale build outputs, or generated test artifacts. Tighten npm ignore rules and clean dist before TypeScript builds so normal installs are smaller and do not leak workspace runtime or branch-stale files. Constraint: npm pack includes untracked files unless .npmignore excludes them, and tsc does not remove stale dist files from previously built branches. Rejected: Leaving package hygiene to developer worktrees | local runtime files and stale branch outputs can be accidentally shipped by any pack/install-from-folder flow. Confidence: high Scope-risk: narrow Directive: Keep package contents explicit; update this ignore list whenever new local agent/runtime directories are introduced, and keep dist cleaning ahead of package builds. Tested: git diff --check; bun run build; npm pack --dry-run --json with zero .omx/.cursor/.codex/.agents/.husky/test-artifact/stale-vertex matches. Not-tested: Published npm release from CI. Co-authored-by: OmX <omx@oh-my-codex.dev>
2d692ab to
e748da3
Compare
Brin PR Security ScanThis PR has findings that should be reviewed.
Findings:
Analyzed by Brin |
There was a problem hiding this comment.
Pull request overview
This PR extends Grok CLI’s authentication and provider plumbing to support Google Cloud Vertex AI (ADC) as a first-class alternative to the native xAI API key, including an updated TUI auth modal that can configure and persist Vertex settings in ~/.grok/user-settings.json.
Changes:
- Replaces the API-key-only TUI modal with a tabbed auth modal (xAI key vs Vertex AI) and persists Vertex settings (
projectId,location,baseURL) in user settings. - Adds Vertex runtime support pieces needed by the CLI/TUI flow: ADC access-token acquisition, a fetch adapter that translates xAI-style
/chat/completionscalls to VertexgenerateContent/streamGenerateContent, and Vertex-mode gating for unsupported native xAI endpoints. - Updates tests and documentation to cover Vertex auth/config behavior and the new TUI/CLI flows.
Reviewed changes
Copilot reviewed 23 out of 24 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
vitest.config.ts |
Adds a global Vitest setup file for test isolation. |
src/test/setup.ts |
Forces tests to use a temp GROK_USER_SETTINGS_PATH to avoid touching real user config. |
src/utils/settings.ts |
Introduces Vertex settings + mode detection, user-settings path override, and model-auth status helpers. |
src/utils/settings-vertex.test.ts |
Adds unit tests for Vertex settings resolution and auth status logic. |
src/ui/app.tsx |
Implements the new tabbed auth modal and routes auth failures back to the appropriate tab. |
src/index.ts |
Updates CLI flows to allow Vertex mode in headless runs and blocks batch API in Vertex mode. |
src/telegram/headless-bridge.ts |
Switches Telegram bridge auth checks to “model auth” (xAI or Vertex). |
src/grok/vertex-auth.ts |
Adds ADC token acquisition via google-auth-library with actionable error formatting. |
src/grok/vertex-auth.test.ts |
Tests ADC error formatting and GoogleAuth fetch configuration. |
src/grok/vertex-adapter.ts |
Adds the Vertex adapter translating xAI chat requests/streams to Vertex and back. |
src/grok/vertex-adapter.test.ts |
Adds coverage for URL building, schema sanitization, streaming conversion, and adapter fetch behavior. |
src/grok/client.ts |
Routes provider creation through the Vertex adapter when Vertex mode is enabled. |
src/grok/client.test.ts |
Adds a regression test ensuring chat tool support selection stays compatible in Vertex mode. |
src/grok/tools.ts |
Disables certain native xAI-only tools (search/media) when Vertex mode is enabled. |
src/audio/stt/engine.ts |
Improves error messaging for Telegram STT when only Vertex ADC is configured. |
test-vertex-integration.ts |
Adds a live smoke script for Vertex mode (dev/test only). |
package.json |
Adds google-auth-library, clean:dist, and test:vertex. |
bun.lock |
Locks new dependency graph for google-auth-library. |
README.md |
Documents Vertex auth setup, limitations, and troubleshooting. |
.env.example |
Adds Vertex-related env var examples. |
.npmignore |
Excludes new dev/test artifacts (including Vertex smoke script) from npm package. |
CHANGELOG.md |
Documents new Vertex support and the TUI auth flow update. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Ensure pack and publish paths rebuild from a clean dist directory under Bun and keep platform-specific standalone binaries out of the npm tarball.\n\nConstraint: Review feedback showed npm packaging could include stale generated files when contributors skipped build or had binary artifacts in dist.\nRejected: Relying on reviewer discipline to run build manually | publish should enforce the package boundary.\nConfidence: high\nScope-risk: narrow\nDirective: Keep npm package contents generated from tsc output; standalone binaries belong in release artifacts, not the npm package.\nTested: bun run build; bun run build:binary; npm pack --dry-run --ignore-scripts --json; npm pack --dry-run --json\nNot-tested: actual npm publish
Grok on Vertex uses Google ADC, the global Vertex API host, and Google-native generateContent endpoints instead of xAI API-key chat completions. Add a fetch adapter that preserves the existing xAI provider surface while translating auth, URLs, messages, streaming chunks, and local tool schemas for Vertex. Constraint: Grok partner models require https://aiplatform.googleapis.com as the host while keeping a normal location path such as us-central1; Vertex also rejects OpenAI message/tool schemas that are not converted. Rejected: Using regional Vertex hosts | Grok partner models return bad requests there. Rejected: Replacing the xAI provider wholesale | the CLI already depends on @ai-sdk/xai behavior, so a fetch adapter keeps the blast radius smaller. Confidence: medium Scope-risk: broad Directive: Keep native xAI behavior gated behind GROK_USE_VERTEX=false; keep Vertex smoke tests deterministic by disabling tools for exact text-response checks and use separate tool smokes for local tool access. Tested: git diff --check; bun run typecheck; bun run test; bun run lint; bun run build; bun run test:vertex; Vertex targeted tests; npm pack --dry-run --json; normal tarball install Not-tested: Google Cloud projects without xAI partner model access; manual OpenTUI auth modal walkthrough Co-authored-by: OmX <omx@oh-my-codex.dev>
Address review findings around ADC reuse, unsupported request handling, nullable schema translation, and auth validation paths while keeping the native xAI flow unchanged.\n\nConstraint: Vertex mode must bridge OpenAI-style Vercel AI SDK requests into Google generateContent without leaking conversion exceptions into fetch callers.\nRejected: Validating ADC during simple configuration checks | token refresh can require network and belongs in request-time/test-auth paths.\nConfidence: high\nScope-risk: moderate\nDirective: Keep Vertex compatibility shims returning OpenAI-shaped JSON errors; do not let adapter conversion exceptions escape fetch.\nTested: bunx vitest run src/grok/vertex-auth.test.ts src/grok/vertex-adapter.test.ts src/telegram/headless-bridge.test.ts src/agent/auth.test.ts; bun run build\nNot-tested: live Vertex request after these review fixes
e748da3 to
524d645
Compare
Vertex streams may interleave text and function-call parts. Count only function calls when emitting OpenAI streaming tool_call indexes so downstream AI SDK parsing can correlate deltas correctly. Constraint: Cursor review identified part-position indexes as incompatible with OpenAI streaming tool-call semantics. Rejected: Keeping Vertex part positions in delta indexes | text parts can create sparse indexes and dropped tool calls. Confidence: high Scope-risk: narrow Directive: Preserve OpenAI tool-call index semantics independently from Vertex part array positions. Tested: bunx vitest run src/grok/vertex-adapter.test.ts; bun run build Not-tested: Live Vertex stream containing multiple function calls in one candidate.
Interactive users should not be forced through the xAI API-key prompt when their intended auth path is Google Cloud ADC. Add a two-tab authentication modal that keeps xAI as the default path while saving Vertex project, location, and base URL through Grok-specific user settings. Constraint: Vertex ADC itself is configured outside the CLI, but project/location/base URL should be saved through Grok-specific settings so users are not forced into xAI API-key entry. Rejected: Hiding Vertex behind env-only setup | it keeps interactive users trapped at the API-key modal. Confidence: high Scope-risk: moderate Directive: Keep the headless env path working and keep the xAI key path as the default when Vertex is not active. Tested: git diff --check; git diff --cached --check; bun run typecheck; bun run test; bun run lint; bun run build; bun run test:vertex. Not-tested: Manual OpenTUI rendering and keyboard walkthrough in a real terminal. Co-authored-by: OmX <omx@oh-my-codex.dev>
Avoid disabling saved Vertex auth until the replacement xAI key has passed local validation, so failed key entry leaves the existing Vertex setup intact.\n\nConstraint: Review feedback identified a TUI auth-mode switch path that could clear working Vertex auth before validating the new xAI key.\nRejected: Disabling Vertex as soon as the xAI tab submits | invalid input should not mutate existing auth state.\nConfidence: high\nScope-risk: narrow\nDirective: Auth-mode switches should commit only after the target mode has validated its required fields.\nTested: bunx vitest run src/grok/vertex-auth.test.ts src/grok/vertex-adapter.test.ts src/telegram/headless-bridge.test.ts src/agent/auth.test.ts src/utils/settings-vertex.test.ts; bun run build\nNot-tested: manual OpenTUI key modal interaction
The auth modal should use Tab to switch between xAI and Vertex setup. Left and right arrows belong to focused text inputs, especially when editing project IDs, locations, base URLs, or API keys. Constraint: Cursor review identified left/right tab switching as conflicting with normal text editing inside the auth modal. Rejected: Keeping arrow-key tab switching | it steals cursor movement from every modal text field. Confidence: high Scope-risk: narrow Directive: Avoid global modal keybindings that conflict with focused text input editing. Tested: bun run build; inspected auth-modal key handler after change Not-tested: Manual OpenTUI keyboard interaction in a real terminal.
524d645 to
de45dec
Compare
Keep Vertex and xAI auth failures visible after the TUI opens or switches the auth modal from an error path. Constraint: PR superagent-ai#287 had an unresolved review finding where modal helper calls cleared freshly set auth errors. Rejected: Rendering a full OpenTUI component test | importing the full app pulls terminal-runtime dependencies into Vitest, so the state policy is covered in an isolated helper test. Confidence: high Scope-risk: narrow Directive: Keep normal auth modal opens clearing stale errors; preserve errors only for error-driven modal flows. Tested: git diff --cached --check; bunx vitest run src/ui/app-auth-modal.test.ts; bunx vitest run src/grok/vertex-adapter.test.ts src/grok/vertex-auth.test.ts src/utils/settings-vertex.test.ts src/agent/auth.test.ts src/grok/client.test.ts src/telegram/headless-bridge.test.ts src/ui/app-auth-modal.test.ts; bun run typecheck; bun run test; bun run lint; bun run build; bun run test:vertex; npm pack --dry-run --json; npm pack --dry-run --ignore-scripts --json Not-tested: Manual OpenTUI keyboard walkthrough. Co-authored-by: OmX <omx@oh-my-codex.dev>
|
Thanks for this. Looking into merging. |
Keep PR superagent-ai#287 review-ready by aligning Vertex request shape with dedicated system instructions, using SSE streaming, and avoiding redundant settings reads. Constraint: Cursor Bugbot flagged unresolved PR superagent-ai#287 review findings on settings reads, system prompt transport, and streaming URL shape. Rejected: Treating the findings as advisory only | they are small, concrete, and improve production behavior before maintainer merge review. Confidence: high Scope-risk: moderate Directive: Keep Vertex request translation explicit; do not reintroduce system prompts as user content. Tested: git diff --check; bun run typecheck; bunx vitest run src/grok/vertex-adapter.test.ts src/utils/settings-vertex.test.ts; bunx vitest run src/grok/vertex-adapter.test.ts src/grok/vertex-auth.test.ts src/grok/client.test.ts src/agent/auth.test.ts src/telegram/headless-bridge.test.ts src/ui/app-auth-modal.test.ts src/utils/settings-vertex.test.ts; bun run test:vertex; bun run test; bun run lint; bun run build Not-tested: Manual OpenTUI keyboard walkthrough. Co-authored-by: OmX <omx@oh-my-codex.dev>
Local and npm-linked installs should launch the built CLI directly from dist. Preserve the executable bit after TypeScript emits dist/index.js so the grok bin symlink and existing local wrapper do not fail with permission errors. Constraint: tsc emits dist/index.js without executable mode even though package.json exposes it as the grok binary. Rejected: Fixing only the current machine with chmod | the next build would recreate a non-executable entrypoint. Confidence: high Scope-risk: narrow Directive: Keep the compiled bin entrypoint executable whenever the build script changes. Tested: git diff --check; bun run build; ls -l dist/index.js; /home/aj/.npm-global/bin/grok --help; npm pack --dry-run --ignore-scripts --json confirmed dist/index.js mode 493; bun run typecheck; bun run test; bun run lint; grok --version; grok --help Not-tested: Windows npm global install. Co-authored-by: OmX <omx@oh-my-codex.dev>
Vertex can deliver an error payload inside a streaming response. Emit that error as an OpenAI-style SSE event instead of treating the stream as empty and ending with only [DONE]. Constraint: Cursor Bugbot flagged PR superagent-ai#287 thread PRRT_kwDOPMI0Xs5_cnR8 on the latest head. Rejected: Ignoring error-only stream chunks | it hides provider failures from callers. Confidence: high Scope-risk: narrow Directive: Keep streaming and non-streaming Vertex error propagation aligned. Tested: git diff --check; bun run typecheck; bunx vitest run src/grok/vertex-adapter.test.ts; bunx vitest run src/grok/vertex-adapter.test.ts src/grok/vertex-auth.test.ts src/utils/settings-vertex.test.ts src/agent/auth.test.ts src/grok/client.test.ts src/telegram/headless-bridge.test.ts src/ui/app-auth-modal.test.ts; bun run test; bun run build; bun run lint; bun run test:vertex; npm pack --dry-run --ignore-scripts --json Not-tested: Live Vertex stream with embedded provider error. Co-authored-by: OmX <omx@oh-my-codex.dev>
|
@AmeerJ97 did you test this locally? |
Yes, it was functional but i had realized the fragility of this PR only after using it after the fact, il be updating it later today with something more robust |
Vertex ADC failures should fail before the provider wrapper emits stack-shaped internals, and read-only planning modes need tool-boundary enforcement rather than prompt-only discipline. Preflight Vertex ADC in agent streaming, make headless error chunks set a failing exit code, block obvious Plan/Ask shell mutations, and stop retrying unavailable LSP extensions within a session. Constraint: PR superagent-ai#287 is under maintainer scrutiny after a tested-locally question; changes must stay local-only until final verification and explicit push approval. Rejected: Letting headless smokes return 0 on auth errors | it creates false-green local evidence. Rejected: Relying on Plan-mode instructions alone | bash can still mutate the workspace unless the tool boundary blocks it. Confidence: high Scope-risk: moderate Directive: Do not push this commit until the interactive terminal matrix and PR body update are ready together. Tested: git diff --check; bunx vitest run src/grok/vertex-adapter.test.ts src/grok/vertex-auth.test.ts src/grok/lsp-tools.test.ts src/grok/tools.test.ts; bunx vitest run src/agent/auth.test.ts src/grok/vertex-auth.test.ts src/grok/vertex-adapter.test.ts src/grok/lsp-tools.test.ts src/grok/tools.test.ts; bun run typecheck; bun run build; bun run test; bun run lint; installed launcher ADC-failure smoke exits 1 with clean JSON error. Not-tested: Successful live Vertex generation; current machine ADC requires reauthentication.
Keep Vertex ADC failures inside the CLI's own recoverable path and expose long-running model waits as explicit status updates instead of an ambiguous spinner. Constraint: PR superagent-ai#287 remains public; keep this as an additive local-only commit until final review. Rejected: Requiring a full Grok restart after gcloud ADC login | stale GoogleAuth clients can be reset locally and retried from the TUI. Confidence: high Scope-risk: moderate Directive: Do not push this commit until the PR branch is ready to publish all local robustness fixes together. Tested: bun run typecheck; bunx vitest run src/grok/vertex-auth.test.ts src/ui/app-auth-modal.test.ts src/headless/output.test.ts src/agent/auth.test.ts; bun run test; bun run lint; bun run build; installed launcher smoke with live Vertex ADC returned OK. Not-tested: Manual interactive auth-modal retry after intentionally revoked ADC; full terminal matrix.
|
|
||
| const mutationPatterns: Array<{ pattern: RegExp; reason: string }> = [ | ||
| { | ||
| pattern: /\b(?:rm|rmdir|mv|cp|touch|mkdir|chmod|chown|ln)\b/, |
There was a problem hiding this comment.
Read-only mode regex matches command names in arguments/filenames
Medium Severity
The regex /\b(?:rm|rmdir|mv|cp|touch|mkdir|chmod|chown|ln)\b/ matches these command names anywhere in the shell string, including inside filenames, quoted arguments, and grep patterns. For example, cat touch.log, grep "rm" file.txt, ls cp_output/notes.md, or file --mime-type ln.conf would all be incorrectly blocked in plan mode. The pattern needs positional anchoring (e.g., requiring the match at the start of a pipeline segment) rather than a bare word-boundary check across the entire command.
Reviewed by Cursor Bugbot for commit 655d0a0. Configure here.
655d0a0 to
6367208
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6367208. Configure here.
| setApiKeyError("Enter GROK_VERTEX_LOCATION, for example us-central1 or europe-west1."); | ||
| selectVertexAuthField("location"); | ||
| return; | ||
| } |
There was a problem hiding this comment.
Unreachable location validation due to prior default assignment
Low Severity
In submitVertexSettings, location is assigned ... || DEFAULT_VERTEX_LOCATION on the line above, guaranteeing it's always the non-empty string "us-central1" when the input is blank. The subsequent if (!location) check can never be true, making the validation error message unreachable. Users who clear the location field won't see the intended validation prompt — instead, the default is silently applied.
Reviewed by Cursor Bugbot for commit 6367208. Configure here.
|
Superseded by #290 |


Purpose
This PR adds native Google Cloud Vertex AI support for Grok using Application Default Credentials while preserving the existing xAI API-key flow for users who do not enable Vertex mode.
This is the consolidated review target for Vertex AI support and should be reviewed directly against
main.Scope
GROK_USE_VERTEX=1and saved Grok user settings, using Google ADC viagoogle-auth-library.https://aiplatform.googleapis.comwith a configurable location path, defaulting tous-central1.generateContent/streamGenerateContentrequests.xAI API keyvsVertex AI, including project/location/base URL validation, saved settings, and visible auth-error handling.Review Notes
Primary review focus:
google-auth-library,prepack,distcleanup, and.npmignore.Tested
git diff --check origin/main...HEADbunx vitest run src/grok/vertex-adapter.test.ts src/grok/vertex-auth.test.ts src/utils/settings-vertex.test.ts src/agent/auth.test.ts src/grok/client.test.ts src/telegram/headless-bridge.test.ts src/ui/app-auth-modal.test.ts(7 files, 52 tests)bun run typecheckbun run test(48 files, 269 tests)bun run lint(passes; reports 7 pre-existing unrelated warnings outside this PR changed files)bun run buildbun run test:vertexpassed for projectvierla-prod, locationus-central1, modelgrok-4.20-0309-reasoningnpm pack --dry-run --json(295 entries;dist/index.jsmode 493)npm pack --dry-run --ignore-scripts --json(295 entries;dist/index.jsmode 493; includesdist/ui/auth-modal-state.js)npm install -g . && grok --version && grok --help(installed PATH command reports1.1.5)Not Tested
Note
High Risk
High risk because it adds a new authentication mode and a request/stream translation layer that intercepts
chat/completions, which can affect core runtime behavior and error handling across the CLI.Overview
Adds an opt-in Vertex AI authentication/runtime mode (
GROK_USE_VERTEX=1or saveduser-settings.jsonvertex.enabled) that uses Google Application Default Credentials viagoogle-auth-library, with newVertexSettingsresolution/validation and clearer auth-status reporting.Routes xAI/OpenAI-style
chat/completionstraffic through a newvertex-adapterfetch shim that builds VertexgenerateContent/streamGenerateContentrequests (including model-id mapping), sanitizes/forwards tool function schemas (withGROK_VERTEX_DISABLE_TOOLSfallback), and converts Vertex responses + JSON streaming chunks back into OpenAI-compatible JSON/SSE.Updates the agent/CLI/TUI to treat Vertex as “configured auth” without an xAI key, adds an interactive TUI auth modal for xAI vs Vertex settings, and blocks/returns explicit errors for xAI-only features in Vertex mode (Batch API, web/X search, image/video gen, Telegram STT). Packaging/docs/tests are updated accordingly (new build/prepack flow,
.npmignorehygiene, Vertex integration test, and extensive unit tests).Reviewed by Cursor Bugbot for commit 6367208. Bugbot is set up for automated code reviews on this repo. Configure here.