Skip to content

feat: add Vertex AI Grok support with provider abstraction#290

Open
AmeerJ97 wants to merge 14 commits into
superagent-ai:mainfrom
AmeerJ97:feat/vertex-ai-support
Open

feat: add Vertex AI Grok support with provider abstraction#290
AmeerJ97 wants to merge 14 commits into
superagent-ai:mainfrom
AmeerJ97:feat/vertex-ai-support

Conversation

@AmeerJ97
Copy link
Copy Markdown

@AmeerJ97 AmeerJ97 commented May 9, 2026

Summary

Adds Google Cloud Vertex AI as a second backend for Grok, behind a clean GrokProviderAdapter contract at src/providers/. Existing xAI users see no change; Vertex users opt in with --provider vertex (or GROK_PROVIDER=vertex) and a configured GROK_VERTEX_PROJECT_ID, then authenticate via Google Application Default Credentials.

Live-tested end-to-end against a real GCP project with grok-4.20-0309-reasoning — chat, streaming, function calling, and provider self-detection all work:

Screenshot_1
  1. Agent verifies 2+2 via the bash tool (function calling on Vertex as Grok model 4.20 Reasoning).
  2. On "Hey", agent fails as ive switched to Grok 4.30 since Grok 4.30 isnt available on vertex, atlast for me it's not enabled.
Screenshot_2
  1. Switched back to 4.20 and it identifies itself as Grok 4.20 Reasoning and reports the model is set at project level via .grok/settings.json.
  2. On "Are you configured to xAI directly or through Vertex?", agent greps env + reads settings, then reports "I'm configured to run through Google Cloud Vertex AI ... GROK_PROVIDER=vertex ... the current model is one of the official Vertex Grok SKUs.

What works on Vertex (and what's xAI-only)

Feature xAI Vertex Notes
Chat / streaming both via the adapter; Vertex SSE handled in src/providers/vertex/openapi.ts
Function / tool calling local CLI tools (bash, file edits, LSP, etc.)
Structured outputs JSON schema sanitized to Vertex enum form
Vision (image input) PNG/JPEG message parts
--batch-api typed error Vertex Grok model cards mark batch unsupported
search_web / search_x typed error xAI hosted tools
generate_image / generate_video typed error xAI hosted
Telegram audio (Grok STT) typed error xAI-only endpoint
reasoning_effort knob n/a Vertex selects via SKU (-reasoning vs -non-reasoning)

The four documented Vertex Grok SKUs are encoded as data: grok-4.20-{reasoning,non-reasoning} (200K context) and grok-4.1-fast-{reasoning,non-reasoning} (128K context). Pricing fields mirror xAI public pricing for the same family as a CLI cost-estimate; actual billing flows through your Google Cloud contract.

Architecture

The Agent now depends on a GrokProviderAdapter interface, not on @ai-sdk/xai directly. Each backend is a self-contained directory:

src/providers/
├── types.ts          GrokProviderAdapter, ProviderCapabilities, ResolvedModelRuntime
├── index.ts          createProvider({ kind }) factory
├── config.ts         normalized runtime config
├── xai.ts            wraps @ai-sdk/xai
├── xai-models.ts     native xAI catalog (moved from src/grok/models.ts)
└── vertex/
    ├── index.ts        VertexProviderAdapter implements GrokProviderAdapter
    ├── auth.ts         Google ADC (also: oauth_token, service_account_api_key)
    ├── models.ts       4 official Vertex Grok SKUs
    └── openapi.ts      OpenAI-shape ↔ Vertex generateContent translator

Capability gating is explicit: provider.capabilities.batchApi, provider.hostedTools, provider.imageModel, etc. There are zero isVertexModeEnabled() callsites scattered across the codebase — every gating decision goes through the adapter.

src/grok/{client,models}.ts are kept as thin backward-compatible re-export shims so adjacent imports keep working without churn.

Why this PR replaces a prior attempt

This is the architectural redo of the closed draft #287. That branch implemented Vertex as a fetch interceptor wrapping @ai-sdk/xai with a sentinel API key, and scattered isVertexModeEnabled() checks across 8+ files. This PR keeps the same end-user capability but routes everything through the provider abstraction, so future Vertex-only work (or a third backend) doesn't require another round of dispatch-point surgery. The npm packaging hygiene and adjacent TUI fixes (plan-mode chat leak, async repaint, liveness-nudge handling) from that branch are bundled here because they live in files this PR already rewrites.

Reviewer focus

The 12-commit history is structured as a guided tour — each commit is one logical step, behavior-preserving until commit 11 — and reviewing it commit-by-commit is significantly easier than the unified diff. If you only have time for three things:

  1. src/providers/types.ts — the contract, ~100 lines, sets the entire shape.
  2. src/providers/vertex/index.ts + openapi.ts — the Vertex transport. The 977-line openapi.ts is the validated translator from the prior live-tested branch, ported with adapted imports; the small index.ts is the new wrapper.
  3. src/agent/agent.ts + src/grok/tools.ts + src/grok/media.ts — the consumer-side migration to provider.chatModel(...), provider.responsesModel?(...), provider.hostedTools?.webSearch(), provider.imageModel?(...), etc., all behind capability flags.

Tested

  • bun run typecheck — clean
  • bun run lint — clean (5 pre-existing upstream warnings in src/lsp/* and src/tools/computer.ts, none in changed files)
  • bun run test338/338 passing across 53/54 test files. The one failed test file is src/storage/sessions.test.ts, which fails on an import { Database } from "bun:sqlite" line; this same failure reproduces on origin/main without these changes (vitest worker can't import bun:sqlite).
  • bun run build — clean dist tree, executable entrypoint preserved
  • npm pack --dry-run — 316 files, 362.8 kB, no surprise additions
  • Live xAI smoke — chat, streaming, bash tool call, exit cleanly
  • Live Vertex smokegcloud auth application-default login, GROK_VERTEX_PROJECT_ID=my-gcp-project bun run dev --provider vertex, full TUI session including bash tool calling and provider self-detection (headline screenshot above)
  • Vertex error-path smoke — selected grok-4.3 (an xAI-only model not present in the Vertex catalog) and confirmed Vertex's own 404 surfaces cleanly through the adapter with the real on-the-wire URL aiplatform.googleapis.com/v1/projects/<redacted>/locations/global/publishers/xai/models/grok-4.3:streamGenerateContent — proof that ADC auth, URL construction, and error passthrough all work; the user-visible message is Vertex's own "Publisher Model ... was not found" rather than an opaque adapter crash:

Out of scope (planned follow-ups)

  • TUI auth modal that lets users switch providers from inside the running app. Vertex is currently selected via env var, settings JSON, or --provider CLI flag — sufficient for first release. Modal lands in a follow-up PR scoped just to src/ui/.
  • Resurrecting closed PR fix: make git inspection errors actionable outside repositories #284 (fix/git-root-inspection-errors) as its own focused submission. Genuinely unrelated to Vertex; bundling it here would be the kitchen-sink anti-pattern that closed feat: add Vertex AI Grok support with Google ADC #287.
  • Per-provider observability (request logging, usage metrics broken down by provider).

Commit train

docs: document Vertex AI Grok backend, env vars, and capability matrix
feat(cli): add --provider flag and Vertex-aware apiKey handling
fix(ui): plan-mode chat leak, async repaint, liveness nudge handling
feat(providers): capability gating with typed errors; wire Vertex into Agent
feat(providers/vertex): add transport tests for fn-calling, structured, vision
feat(providers/vertex): add chat-completions transport with streaming
feat(providers/vertex): add Google ADC auth
feat(providers/vertex): add authoritative Vertex Grok model catalog
feat(settings): add provider-aware config and Vertex schema
refactor(providers): introduce GrokProviderAdapter contract; xAI as first impl
chore(install): safeguard local PR builds against the auto-updater
chore(npm): clean package contents and harden installed entrypoint

Each commit has a one-paragraph body explaining scope, rationale, and what was tested at that checkpoint.


Replaces #287. That PR will be closed with a one-line Superseded by reference once this one is open.


Note

High Risk
High risk because it introduces a new backend transport (Vertex AI via ADC) and refactors core agent/provider plumbing and tool integrations, which can affect authentication, model routing, and runtime behavior across the CLI.

Overview
Adds an opt-in Vertex AI Grok backend selectable via --provider vertex/GROK_PROVIDER=vertex, including new Vertex env/settings (GROK_VERTEX_PROJECT_ID, location, base URL) and ADC auth/token handling via google-auth-library.

Refactors the agent to depend on a new backend-agnostic GrokProviderAdapter with capability flags, wiring provider-aware behavior across batch, hosted search, image/video generation, and Telegram STT (unsupported features now fail with clearer/typed errors under Vertex).

Implements the Vertex transport as an OpenAI-shaped chat-completions translator (including streaming SSE and schema/tool-call sanitization), adds Vertex model catalog support, and updates packaging/build hygiene (prepack build, preserve grok executable bit, tighten .npmignore) plus several TUI plan-mode repaint/validation and “status nudge” input handling fixes.

Reviewed by Cursor Bugbot for commit 8dda814. Bugbot is set up for automated code reviews on this repo. Configure here.

AmeerJ97 added 12 commits May 9, 2026 13:10
Three packaging fixes that affect every install path (npm pack, npm publish,
npm link, install-from-folder, GitHub release artifacts):

1. Tighten .npmignore so tarballs no longer ship local runtime state
   (.agents/, .cursor/, .codex/, .claude/, .grok/, .husky/, .omx/) or
   stale dist/ files left over from previous branches. Also exclude
   compiled test files (dist/**/*.test.*, dist/**/*.spec.*) and
   platform-specific standalone binaries (dist/grok-standalone*) which
   belong in GitHub release artifacts, not the npm tarball.

2. Run `clean:dist` before each tsc build so emitted dist/ never carries
   cross-branch debris. Add a `prepack` script so `npm pack` and
   `npm publish` always rebuild from a clean tree.

3. Preserve the executable bit on dist/index.js after TypeScript emits it.
   The tsc compiler does not preserve +x, so npm-linked installs and the
   `grok` bin symlink fail with permission errors. The build script now
   chmods the entrypoint after emit.

Squashes three commits from the prior PR train (5547fe0, 307e638, 70977bf)
that addressed the same packaging concerns. No source code or runtime
behavior changes.
Two related fixes to install-manager and update-checker so locally-built
PR binaries (e.g. when reviewers `npm install -g .` against a feature
branch) do not get clobbered by the auto-updater pulling the latest
public release.

1. install-manager exposes getScriptInstallContext() which returns the
   metadata of the script that's running, including its declared package
   version. update-checker uses this to detect "this is a local build,
   not a release install" and skips auto-update in that case.

2. The desktop launcher can resolve to ~/.grok/bin/grok, so a local PR
   build placed on that path must not immediately consume the latest
   public release and lose the unreleased work it was meant to test.
   Treat any mismatch between the running package version and the
   recorded script metadata as a non-release install for updater
   purposes.

Squashes two commits from the prior PR train (dab125e, aaa05f7).
The dab125e commit also touched src/grok/vertex-{adapter,auth}.ts
in the prior branch; those Vertex changes are intentionally NOT
included here — they are re-implemented properly in the upcoming
provider abstraction commits.

Tested:
- bunx vitest run src/utils/install-manager.test.ts src/utils/update-checker.test.ts
- bun run typecheck
- bun run lint
- bun run build
…irst impl

This is a pure architectural refactor with zero user-visible behavior change.
It establishes the provider abstraction the upcoming Vertex AI work will
build on, with xAI extracted as the first concrete implementation.

The agent loop, tool registry, media generation, compaction, and side-
question helpers now depend on a GrokProviderAdapter interface
(src/providers/types.ts) that exposes:

  - kind:                  ProviderKind ("xai" | "vertex")
  - capabilities:          per-provider feature flags (responsesApi,
                           hostedSearch, imageGeneration, videoGeneration,
                           batchApi, reasoningEffort, audioStt)
  - chatModel(modelId):    AI SDK LanguageModel for chat
  - responsesModel(...):   optional, for xAI's /responses endpoint
  - imageModel(...):       optional, for hosted image generation
  - videoModel(...):       optional, for hosted video generation
  - hostedTools:           optional, for provider-native web/X search
  - resolveRuntime(id):    ResolvedModelRuntime with model + options
  - getBatchClientApiKey:  optional, for the batch client

The xAI implementation (src/providers/xai.ts) wraps @ai-sdk/xai and
declares the full capability set. The xAI model catalog moved to
src/providers/xai-models.ts; src/grok/models.ts is now a thin
backward-compatible re-export so existing imports continue to work.

src/grok/client.ts also stays as a backward-compat shim: it preserves
the legacy createProvider(apiKey, baseURL?) signature and the
resolveModelRuntime helper, both delegating to the adapter. Existing
consumers (agent.ts, tools.ts, compaction.ts, side-question.ts,
media.ts, client.test.ts, media.test.ts) all compile against the new
adapter type. ProviderCapabilityError is exported for consumers that
want typed capability errors.

A vertex case in createProvider() throws a clear "not yet wired up"
error so the next commit can plug in the Vertex implementation without
touching the Agent.

Tested:
- bun run typecheck (clean)
- bun run lint (clean; 5 pre-existing upstream warnings remain in
  src/lsp/* and src/tools/computer.ts, none in changed files)
- bun run test (256/256 passing across 47/48 test files; the 1 failed
  file is src/storage/sessions.test.ts, a pre-existing upstream
  failure where vitest's worker can't import bun:sqlite. Same failure
  reproduces on origin/main without these changes.)
- bun run build (clean dist tree, executable entrypoint)
- New tests in src/providers/provider-contract.test.ts cover the xAI
  adapter, capability flags, model resolution, alias normalization,
  factory error for the not-yet-wired vertex case, and
  ProviderCapabilityError shape.
Extends UserSettings to carry provider selection and Vertex AI configuration,
preserving complete backward compatibility for existing xAI users (default
provider remains "xai" when unset).

New types and helpers in src/utils/settings.ts:

  - ProviderKind imported from src/providers/types
  - VertexAuthMode = "adc" | "oauth_token" | "service_account_api_key"
  - VertexSettings: fully-resolved tuple used at request time
  - VertexUserSettings: optional fields as persisted in user-settings.json
  - DEFAULT_VERTEX_LOCATION = "global"
  - DEFAULT_VERTEX_BASE_URL = "https://aiplatform.googleapis.com"
  - DEFAULT_VERTEX_AUTH_MODE = "adc"

UserSettings gains two optional fields:

  - provider?: ProviderKind   ("xai" | "vertex"; defaults to "xai")
  - vertex?: VertexUserSettings

New public functions:

  - getActiveProvider(): resolves env > settings > "xai"
  - isVertexProviderActive(): convenience for capability checks
  - resolveVertexSettings(): merges env > settings > defaults; returns
    projectId as `string | undefined` so callers can decide how to
    handle missing values
  - requireVertexSettings(): same resolution but throws a descriptive
    error when projectId is missing — for request-path call sites that
    cannot proceed without one

saveUserSettings now normalizes both fields. Invalid provider or
authMode values are silently rejected (kept undefined) rather than
written through, preventing typos from corrupting the config.

Env var precedence (high → low):
  GROK_PROVIDER             > settings.provider             > "xai"
  GROK_VERTEX_PROJECT_ID    > GCP_PROJECT_ID                > settings
  GROK_VERTEX_LOCATION      > GCP_VERTEX_LOCATION           > settings > "global"
  GROK_VERTEX_BASE_URL      > settings                      > default
  GROK_VERTEX_AUTH_MODE     > settings                      > "adc"

Behavior change: none for existing users. The Vertex backend is not yet
wired up — createProvider({ kind: "vertex" }) still throws "not yet
wired up" until commit 7. Settings simply parse and persist.

Tested:
- bun run typecheck (clean)
- bun run lint (clean; 5 pre-existing upstream warnings)
- bun run test (273/273 passing across 48/49 files; the 1 failed file
  is the same pre-existing src/storage/sessions.test.ts upstream
  bun:sqlite issue)
- 17 new tests in src/utils/settings-vertex.test.ts cover: provider
  defaults, env override precedence, GCP_PROJECT_ID fallback, blank-
  string normalization, baseURL trailing-slash stripping, missing-
  projectId error message, save/merge round-trip, invalid value
  rejection.
Encodes the four Vertex AI Grok SKUs documented at
https://cloud.google.com/vertex-ai/generative-ai/docs/partner-models/use-grok
as data, alongside the helpers needed to round-trip between canonical
ids, declared aliases, and the on-the-wire request format.

Catalog (src/providers/vertex/models.ts):

  - grok-4.20-reasoning            200K context, reasoning, vision, fn-calls
  - grok-4.20-non-reasoning        200K context, no reasoning
  - grok-4.1-fast-reasoning        128K context, reasoning, cost-efficient
  - grok-4.1-fast-non-reasoning    128K context, no reasoning, cost-efficient

Defaults:
  - DEFAULT_VERTEX_MODEL        = grok-4.20-reasoning
  - DEFAULT_VERTEX_TITLE_MODEL  = grok-4.1-fast-non-reasoning

Helpers:
  - normalizeVertexModelId(id)  resolves aliases + strips xai/ prefix
  - getVertexModelInfo(id)      catalog lookup with alias resolution
  - getVertexModelIds()         canonical id list
  - isKnownVertexModelId(id)    membership check
  - getVertexRequestModelId(id) returns "xai/<id>" form for Vertex's
                                OpenAPI chat-completions endpoint

Notable Vertex divergences from the xAI catalog (encoded in the data):
  - supportsReasoningEffort = false on every SKU. Vertex selects
    reasoning behavior by SKU rather than by the reasoning_effort knob,
    so per-request effort overrides are intentionally disabled here.
  - Smaller context windows than the xAI flagship.
  - Pricing fields mirror xAI public pricing for the same model family
    as a cost estimate; actual Vertex billing flows through the
    customer's GCP contract and may differ.
  - Batch predictions are not supported for Grok on Vertex (gated in
    a later commit through the provider capability flags).

Behavior change: none. The catalog is queryable but no transport calls
it yet — that lands in commit 7 alongside the OpenAPI chat-completions
client.

Tested:
- bun run typecheck (clean)
- bun run lint (clean)
- 21 new tests in src/providers/vertex/models.test.ts cover catalog
  identity, context windows per SKU, reasoning flags, default
  selection, alias resolution, prefix stripping, request-id formatting,
  and unknown-id surfacing for error messages.
Adds the credential layer for the upcoming Vertex AI transport. Supports
the three auth modes declared by VertexAuthMode in src/utils/settings:

  1. ADC (default)             — Application Default Credentials, the path
                                 the Vertex quickstart docs recommend. Uses
                                 google-auth-library to resolve credentials
                                 from `gcloud auth application-default login`,
                                 GOOGLE_APPLICATION_CREDENTIALS, or workload
                                 identity, in that order.
  2. Explicit OAuth token      — Returns a caller-supplied bearer token
                                 verbatim. Useful for short-lived tokens
                                 minted by `gcloud auth print-access-token`.
  3. Service-account API key   — Returns the configured API key. Reserved
                                 for organizations that have enabled
                                 service-account-bound API keys; not
                                 verified end-to-end against the
                                 Grok-on-Vertex endpoint and exposed
                                 behind the explicit "service_account_api_key"
                                 mode rather than as an automatic fallback.

The GoogleAuth client is cached as a module singleton so token caching and
refresh handled by google-auth-library are not bypassed. resetVertexAuthClient
clears the cache for recovery flows and test isolation.

formatVertexAuthErrorMessage produces a human-friendly error specifically
distinguishing the "ADC needs reauthentication" case (invalid_rapt /
invalid_grant / reauth required) from generic transport failures, so
the TUI can surface actionable guidance instead of opaque OAuth errors.

Adds google-auth-library@10.6.2 as a runtime dependency; no other
dependencies touched.

Behavior change: none. The auth function exists but no transport calls
it yet — that lands in commit 7.

Tested:
- bun run typecheck (clean)
- bun run lint (clean; 5 pre-existing upstream warnings)
- bun run test (310/310 passing across 50/51 files; the 1 failed file
  is the same pre-existing src/storage/sessions.test.ts upstream
  bun:sqlite issue)
- 16 new tests in src/providers/vertex/auth.test.ts cover: ADC happy
  path, ADC null token, ADC re-auth detection, ADC generic error
  formatting, GoogleAuth client caching, resetVertexAuthClient,
  oauth_token verbatim + trim + missing-token error, service_account_api_key
  passthrough + missing-key error, and JSON-string error parsing.
Wires the Vertex AI Grok backend into the provider factory. After this
commit, createProvider({ kind: "vertex" }) returns a working adapter
that translates the agent's chat requests into Vertex
generateContent / streamGenerateContent calls and converts responses
back into the OpenAI-compatible shape the AI SDK expects.

Files:

  - src/providers/vertex/openapi.ts (NEW, 977 lines)
      The chat-completions translator. Exports createVertexFetch,
      buildVertexModelUrl, getVertexModelId, convertXaiChatRequestToVertex,
      sanitizeVertexSchema, convertMessagesToVertexContents,
      convertVertexGenerateResponseToOpenAI, createVertexSseStream,
      and convertVertexStreamResponseToOpenAIChunks.

      Translation logic ported intact from the prior PR's validated
      vertex-adapter.ts (live-tested against project vierla-prod /
      grok-4.20-0309-reasoning per closed PR superagent-ai#287's test notes), with
      three changes for the new architecture:
        * Imports rewired to ../../utils/settings and ./auth
        * isTruthyEnv inlined here (clean main does not export one)
        * getVertexAccessToken now passes { mode: settings.authMode }
          so the auth resolver can pick ADC / oauth_token /
          service_account_api_key based on saved settings

  - src/providers/vertex/index.ts (NEW)
      VertexProviderAdapter implements GrokProviderAdapter. Internally
      builds an @ai-sdk/xai client with VERTEX_SDK_PLACEHOLDER_KEY plus
      the createVertexFetch shim — the SDK never sees the placeholder
      on the wire because the fetch shim rewrites the Authorization
      header with the resolved Google access token.

      The Shape 2 design we agreed on: the API boundary is correct
      (Agent depends on GrokProviderAdapter, no scattered
      isVertexModeEnabled checks anywhere), and the fetch-interception
      transport is a private implementation detail of this directory.
      A future PR can swap to a native LanguageModelV2 implementation
      without touching anything outside src/providers/vertex/.

      Capability flags advertised:
        responsesApi:     false  (Vertex Grok has no Responses API)
        hostedSearch:     false  (xAI-only)
        imageGeneration:  false  (xAI-only)
        videoGeneration:  false  (xAI-only)
        batchApi:         false  (Vertex Grok model cards mark batch
                                  predictions unsupported)
        reasoningEffort:  false  (Vertex selects via SKU, not knob)
        audioStt:         false  (xAI-only)

      getBatchClientApiKey() throws ProviderCapabilityError instead of
      returning a placeholder, so anything downstream that reaches for
      the batch path fails loudly at the right boundary.

  - src/providers/index.ts
      The vertex case in createProvider() now delegates to
      createVertexAdapter() instead of throwing "not yet wired up".
      Exports the new factory, default model constants.

  - src/providers/provider-contract.test.ts
      The previous "rejects vertex" test is replaced by two new tests
      that construct the vertex adapter under a stubbed
      GROK_VERTEX_PROJECT_ID env var, verify kind, capabilities, and
      the typed batch error.

Behavior change: provider=vertex now selects a working backend when
GROK_VERTEX_PROJECT_ID (or saved vertex.projectId) is configured.
Default provider remains "xai" so existing users are unaffected.

Tested:
- bun run typecheck (clean)
- bun run lint (clean; 5 pre-existing upstream warnings)
- bun run test (311/311 passing across 50/51 files; the 1 failed
  file is the same pre-existing src/storage/sessions.test.ts upstream
  bun:sqlite issue)
- Adapter-level coverage (function calling, streaming, vision,
  structured output) lands in the next commit.
…d, vision

Ports the validated test suite from the prior PR's
src/grok/vertex-adapter.test.ts into src/providers/vertex/openapi.test.ts.
Adapts imports to the new module paths (./openapi, ./auth) and to the
required-authMode shape of VertexSettings.

The 21 ported tests cover:

  - URL construction
      * global vs regional location paths
      * non-streaming generateContent vs SSE streamGenerateContent
      * trailing-slash baseURL normalization

  - Model id mapping
      * native xAI ids translated to Vertex publisher ids
      * unknown ids passed through

  - Message conversion
      * system → systemInstruction
      * user/assistant/tool round-trip including tool_calls and
        tool_call_id correlation

  - Tool / function-calling translation
      * function declarations forwarded with sanitized parameters
      * tool_choice mapped to Vertex functionCallingConfig
      * GROK_VERTEX_DISABLE_TOOLS emergency disable
      * invalid function names dropped instead of sent

  - Schema sanitization (structured output, function parameters)
      * type fields uppercased to Vertex enum form
      * additionalProperties / minLength / maxItems stripped
      * anyOf-with-null collapsed to nullable: true
      * union schemas resolved to a representative type

  - Response conversion
      * Vertex generateContent → OpenAI chat.completions shape
      * usageMetadata → usage block
      * functionCall parts → tool_calls

  - Streaming
      * SSE chunk parsing
      * tool_call delta indexing kept contiguous across chunks

  - Auth integration
      * fetch shim invokes getVertexAccessToken with the right mode
      * auth failure surfaces as a 401 vertex_auth_failed envelope

This is the validated end-to-end coverage from the prior PR (which the
contributor live-tested against project vierla-prod / grok-4.20-0309-
reasoning), repositioned under the new src/providers/vertex/ tree.

Behavior change: none. Test-only commit that lifts coverage to match
the production code that landed in commit 7.

Tested:
- bun run typecheck (clean)
- bun run lint (clean; 5 pre-existing upstream warnings)
- bun run test (332/332 passing across 51/52 files; the 1 failed file
  is the same pre-existing src/storage/sessions.test.ts upstream
  bun:sqlite issue).
…o Agent

Wires the Agent (and the few non-tool surfaces that talk to the
provider directly) to the GrokProviderAdapter capability flags
introduced in commit 3, replacing implicit assumptions that the
backend is always xAI.

Agent (src/agent/agent.ts):

  - The constructor now constructs a Vertex provider when no apiKey is
    supplied AND getActiveProvider() === "vertex" AND a Vertex project
    id is configured (env or saved settings). Existing xAI users with
    GROK_API_KEY see no change.

  - setApiKey() now routes through buildProvider(), which switches on
    getActiveProvider() and returns either the Vertex adapter (no
    static key needed; auth handled by Google ADC) or the xAI adapter.

  - hasApiKey() (kept on its current name for UI back-compat) now
    returns true when Vertex mode is active and the Vertex provider
    is constructed, even without a static apiKey. The TUI auth modal
    state machine relies on this signal to skip the "enter API key"
    flow when Vertex is the selected backend.

  - getBatchClientOptions() now consults provider.capabilities.batchApi
    and provider.getBatchClientApiKey() instead of reaching for
    this.apiKey directly. With the Vertex adapter (batchApi=false),
    callers get a typed actionable error instead of a confusing
    OpenAI-shaped 401 from the Vertex endpoint.

Audio STT (src/audio/stt/engine.ts):

  - createTelegramAudioInputEngine() now refuses to construct the
    Grok STT engine when getActiveProvider() !== "xai", with a typed
    error that names the active provider and tells the user how to
    proceed. xAI behavior unchanged.

Notes on what is NOT in this commit:

  - tools.ts hostedTools/responsesModel checks (search_web, search_x)
    were already gated in commit 3 when the adapter contract landed.
  - media.ts imageModel/videoModel checks were already gated in
    commit 3.
  - The TUI auth modal that lets users select Vertex from the UI
    lands in commit 10, alongside the adjacent app.tsx fixes.
  - The CLI --provider flag lands in commit 11.

Behavior change: Vertex users can now have an Agent constructed
end-to-end with no static API key. xAI behavior is unchanged for
existing users. xAI-only features called from a Vertex session
produce typed errors instead of opaque transport failures.

Tested:
- bun run typecheck (clean)
- bun run lint (clean; 5 pre-existing upstream warnings)
- bun run test (332/332 passing across 51/52 files; the 1 failed file
  is the same pre-existing src/storage/sessions.test.ts upstream
  bun:sqlite issue).
Bundles three TUI fixes that live in src/ui/{app,plan,processing-input}.tsx
into the same commit because they touch adjacent code in src/ui/app.tsx
and the cleaner V6 (Vertex UX) work that follows would otherwise have to
unpick them from a merge dance. Each fix is self-contained and
behavior-preserving for users who never hit the bug.

1. Plan questions leaking into chat (src/ui/plan.tsx + plan.test.ts)
   Plan-mode question modals must own keyboard focus until answered.
   The previous flow let unanswered tabs advance into the chat input,
   which submitted accidental empty messages and let plan-question
   text leak as user input. Now the modal absorbs key events and
   plan-question submission is the only path that advances state.

2. Async TUI updates not painting without input (src/ui/app.tsx)
   OpenTUI was leaving async tool-result and plan-question updates
   visually stale until the next keyboard event. Requesting a
   renderer paint from the existing scroll wake keeps long-running
   turns and plan modals visible without changing message flow.

3. Liveness nudges polluting the follow-up queue
   (src/ui/app.tsx + src/ui/processing-input.{ts,test.ts} NEW)
   During an active turn, typing a status nudge ("continue", "status",
   etc.) was both waking the TUI and enqueueing a real follow-up
   message. The new processing-input helper isProcessingStatusNudge
   identifies exact liveness nudges and routes them to a repaint /
   status request only, preventing accidental conversation mutation
   while preserving normal queued follow-ups.

These fixes were originally landed as separate commits on the prior
branch (7d36b5d, cb8e932, 655d0a0). They are bundled here because
the cleanest fix to the third one referenced state that exists in the
messy branch's app.tsx but not the clean one — bundling lets us land
all three coherently while the file is being touched.

Behavior change: TUI bug fixes only. No effect on agent/provider/auth
behavior. None of these are Vertex-related; they ride along because
they touch the same files the Vertex UX work in commit 11+ will edit.

Tested:
- bun run typecheck (clean)
- bun run lint (clean; 5 pre-existing upstream warnings)
- bun run test (338/338 passing across 53/54 files; the 1 failed file
  is the same pre-existing src/storage/sessions.test.ts upstream
  bun:sqlite issue).
- 6 new tests in src/ui/plan.test.ts and src/ui/processing-input.test.ts
  cover the modal-focus invariants and the nudge classifier.
Adds the user-facing entry point for selecting the active backend.

  grok --provider vertex                # Vertex AI Grok via Google ADC
  grok --provider xai                   # Native xAI (default; same as before)
  GROK_PROVIDER=vertex grok ...         # Equivalent env override

Implementation:

  - New --provider <kind> CLI option with parseProviderKind validator
    that rejects values other than "xai" or "vertex" early with a
    descriptive message.

  - applyProviderOverride() exports the chosen value to process.env
    before any settings reads happen, so every downstream
    getActiveProvider() consult — Agent construction, capability
    checks, settings persistence — sees the same active provider
    without further plumbing.

  - requireApiKey() now allows empty strings through when
    getActiveProvider() === "vertex", because Vertex authenticates via
    Google ADC instead of a static key. The xAI error message is
    extended to point users at --provider vertex when no API key is
    configured.

This is the minimum change required for end-to-end Vertex usage from
the CLI: with --provider vertex and a configured GROK_VERTEX_PROJECT_ID
(or saved vertex.projectId), the Agent constructs the Vertex adapter,
ADC resolves the access token, and chat/streaming/tool-calling all
flow through src/providers/vertex/openapi.ts.

The full TUI auth modal that lets users switch providers from inside
the running app remains a follow-up — out of scope for the immediately-
mergeable replacement of superagent-ai#287, on the path for a subsequent PR.

Behavior change: --provider becomes selectable from the CLI. Default
remains xAI; existing GROK_API_KEY users see no change. Vertex users
no longer hit the apiKey-required guard.

Tested:
- bun run typecheck (clean)
- bun run lint (clean; 5 pre-existing upstream warnings)
- bun run test (338/338 passing across 53/54 files; the 1 failed file
  is the same pre-existing src/storage/sessions.test.ts upstream
  bun:sqlite issue).
Closes the loop on the user-facing surface for Vertex AI support.

README.md
  Adds a "Vertex AI Grok (Google Cloud backend)" section between the
  API key configuration and the Telegram section. Covers:
    - The four documented Vertex Grok SKUs
    - gcloud auth application-default login prerequisite
    - Three ways to select the backend (CLI flag, env var, settings)
    - Capability matrix: what works on Vertex, what's xAI-only and
      returns a typed error
    - Full env-var reference table
    - Disclaimer that Vertex Grok is a Google partner integration and
      that this project is independent of xAI Corp. and Google

CHANGELOG.md
  Adds an "Added" entry summarizing the Vertex backend, the
  GrokProviderAdapter contract, and the typed-error behavior for
  xAI-only features. Adds a "Fixed" block covering the bundled TUI
  fixes (plan-leak, async repaint, liveness nudge handling) and the
  packaging/install fixes from commits 1 and 2.

.env.example
  Adds the Vertex env-var block with comments matching the README
  reference: GROK_PROVIDER, GROK_VERTEX_PROJECT_ID, GCP_PROJECT_ID
  fallback, GROK_VERTEX_LOCATION (default "global"),
  GROK_VERTEX_BASE_URL, GROK_VERTEX_AUTH_MODE.

Behavior change: docs only. No code paths touched.

Tested:
- bun run typecheck (clean)
- bun run lint (clean; 5 pre-existing upstream warnings)
- bun run test (338/338 passing across 53/54 files; the 1 failed file
  is the same pre-existing src/storage/sessions.test.ts upstream
  bun:sqlite issue)
- bun run build (clean dist)
@AmeerJ97 AmeerJ97 marked this pull request as ready for review May 9, 2026 19:04
Copilot AI review requested due to automatic review settings May 9, 2026 19:04
@superagent-security superagent-security Bot added the contributor:verified Contributor passed trust analysis. label May 9, 2026
Comment thread src/providers/vertex/openapi.ts
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a provider abstraction layer to support routing Grok calls through Google Cloud Vertex AI (in addition to native xAI), plus several related CLI/TUI and packaging/update-safety improvements.

Changes:

  • Introduces GrokProviderAdapter and refactors agent/tools/media/helpers to use capability-gated provider adapters.
  • Adds a Vertex provider implementation (auth, model catalog, OpenAI-shape ↔ Vertex translation, tests) and CLI/config plumbing (--provider, GROK_PROVIDER, Vertex settings).
  • Hardens script-managed install update behavior and includes several TUI UX fixes (plan questions, repainting, processing nudges).

Reviewed changes

Copilot reviewed 39 out of 40 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/utils/update-checker.ts Skips update checks/updates when not running the active script-managed install.
src/utils/update-checker.test.ts Adds tests for script-managed install gating in update check/update flows.
src/utils/side-question.ts Migrates side-question helper to accept GrokProviderAdapter.
src/utils/settings.ts Adds provider selection + Vertex settings resolution/normalization helpers.
src/utils/settings-vertex.test.ts New tests for provider selection + Vertex settings env/user-settings merging.
src/utils/install-manager.ts Adds detection for “current executable is the script-managed install”.
src/utils/install-manager.test.ts Tests for script-managed install detection logic.
src/ui/processing-input.ts Adds helper to classify “liveness nudge” inputs during processing.
src/ui/processing-input.test.ts Tests for processing-nudge classification.
src/ui/plan.tsx Extracts/exports plan-question helper functions; adds required-answer notice handling.
src/ui/plan.test.ts Tests plan-question helper behavior (advance/required notice).
src/ui/app.tsx Wires new plan helpers + processing-nudge behavior; improves repaint behavior.
src/providers/xai.ts Implements xAI provider adapter wrapping @ai-sdk/xai.
src/providers/xai-models.ts Moves native xAI model catalog into providers layer (with alias normalization).
src/providers/vertex/openapi.ts Implements chat-completions translation + SSE handling from Vertex to OpenAI-like shapes.
src/providers/vertex/openapi.test.ts Adds transport/translation tests for Vertex OpenAPI adapter (tools/schema/streaming).
src/providers/vertex/models.ts Adds authoritative Vertex Grok SKU catalog + normalization helpers.
src/providers/vertex/models.test.ts Tests Vertex catalog invariants and normalization behavior.
src/providers/vertex/index.ts Implements Vertex provider adapter using @ai-sdk/xai plus a fetch shim.
src/providers/vertex/auth.ts Adds Google ADC auth + additional auth-mode scaffolding.
src/providers/vertex/auth.test.ts Tests ADC token acquisition, error messaging, and non-ADC modes.
src/providers/types.ts Defines provider contract, capabilities, runtime resolution, and typed capability error.
src/providers/provider-contract.test.ts Tests adapter factory behavior and basic contract expectations.
src/providers/index.ts Adds provider factory (createProvider) and exports provider types/adapters.
src/index.ts Adds --provider flag, env override plumbing, and Vertex-aware API key handling.
src/grok/tools.ts Migrates hosted-search tools to capability-gated provider adapter calls.
src/grok/models.ts Converts legacy model module to re-export xAI catalog from providers layer.
src/grok/media.ts Migrates image/video gen to provider adapter + capability gating.
src/grok/media.test.ts Updates media tool tests to match adapter-based image/video model access.
src/grok/client.ts Refactors client utilities to use provider adapters; keeps backward-compatible exports.
src/grok/client.test.ts Updates client tests to construct providers via createProvider.
src/audio/stt/engine.ts Adds explicit provider gating for Telegram audio STT (xAI-only).
src/agent/compaction.ts Migrates compaction summarization to use provider adapter type.
src/agent/agent.ts Refactors agent to build/consume provider adapters; adds capability gating in batch/vision flows.
README.md Documents Vertex provider usage, supported features, and environment variables.
package.json Adds google-auth-library dependency; hardens build/prepack and dist executable bit.
CHANGELOG.md Notes Vertex provider + adapter refactor + TUI/install/update/package changes.
bun.lock Locks google-auth-library and transitive dependencies.
.npmignore Tightens package contents (exclude tests/dev state/standalone binaries, etc.).
.env.example Documents Vertex provider env vars and basic setup steps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +190 to +197
const isStreaming = xaiRequest.stream === true;
let accessToken: string;
try {
accessToken = await getVertexAccessToken({ mode: vertexSettings.authMode });
} catch (err: unknown) {
const message = err instanceof Error ? err.message : String(err);
return vertexErrorResponse(message, 401, "vertex_auth_failed");
}
Comment thread src/providers/vertex/openapi.ts Outdated

function unsupportedVertexEndpointResponse(url: URL): Response {
return vertexErrorResponse(
`GROK_USE_VERTEX=1 supports Vertex AI chat completions only. The xAI endpoint "${url.pathname}" is not available through Vertex AI; native xAI-only features such as Responses API search, image/video generation, STT, and Batch API require GROK_API_KEY with GROK_USE_VERTEX unset.`,
Comment thread src/providers/vertex/auth.ts Outdated
Comment on lines +66 to +81
function resolveExplicitToken(token: string | undefined): string {
const trimmed = token?.trim();
if (!trimmed) {
throw new Error(
"Vertex auth mode is 'oauth_token' but no token was provided. Set vertex.oauthToken in settings or run `gcloud auth print-access-token` and pass the result.",
);
}
return trimmed;
}

function resolveServiceAccountApiKey(apiKey: string | undefined): string {
const trimmed = apiKey?.trim();
if (!trimmed) {
throw new Error(
"Vertex auth mode is 'service_account_api_key' but no API key was provided. Save vertex.apiKey via settings, or switch to ADC by setting GROK_VERTEX_AUTH_MODE=adc.",
);
Comment thread src/utils/settings.ts
Comment on lines +456 to +462
export function requireVertexSettings(): VertexSettings {
const resolved = resolveVertexSettings();
if (!resolved.projectId) {
throw new Error(
"Vertex AI is selected but no project id is configured. Set GROK_VERTEX_PROJECT_ID, GCP_PROJECT_ID, or save vertex.projectId via the TUI auth modal.",
);
}
Comment thread src/utils/settings.ts
Comment on lines 306 to +316
},
}
: {}),
...(partial.provider !== undefined ? { provider: normalizeProviderKind(partial.provider) } : {}),
...(partial.vertex !== undefined
? {
vertex: normalizeVertexUserSettings({
...current.vertex,
...partial.vertex,
}),
}
Comment thread src/agent/agent.ts

private requireProvider(): XaiProvider {
private requireProvider(): GrokProviderAdapter {
if (!this.provider) {
Comment on lines +71 to +84
resolveRuntime(requestedModelId: string): ResolvedModelRuntime {
const modelId = normalizeVertexModelId(requestedModelId);
const modelInfo = getVertexModelInfo(modelId);
// Vertex selects reasoning by SKU, not via per-request reasoning_effort,
// so providerOptions.xai.reasoningEffort is intentionally omitted. We
// still consult the saved per-model setting to preserve ergonomics for
// cross-provider tooling that round-trips the value.
const requestedEffort = getReasoningEffortForModel(modelId);
return {
model: this.sdk(modelId),
modelId,
modelInfo,
providerOptions: requestedEffort ? { xai: { reasoningEffort: requestedEffort } } : undefined,
};
Comment thread README.md Outdated
| `GCP_PROJECT_ID` | Fallback for `GROK_VERTEX_PROJECT_ID` | — |
| `GROK_VERTEX_LOCATION` | Vertex region (e.g. `us-central1`) | `global` |
| `GROK_VERTEX_BASE_URL` | Vertex API host override | `https://aiplatform.googleapis.com` |
| `GROK_VERTEX_AUTH_MODE` | `adc`, `oauth_token`, or `service_account_api_key` | `adc` |
…ai#290

Single follow-up commit that addresses every concern flagged by
cursor[bot] and Copilot on PR superagent-ai#290. Net diff is -31 LOC because most
of the fixes are removals: stripping out auth modes that were
documented but never wired up.

cursor[bot] (Medium severity, src/providers/vertex/openapi.ts:193):
  "Vertex non-ADC auth modes always fail silently"

Copilot review notes addressed (8 inline comments):
  src/providers/vertex/openapi.ts:197  same root cause as above
  src/providers/vertex/openapi.ts:776  stale GROK_USE_VERTEX text
  src/providers/vertex/auth.ts:81      dead config-path text
  src/utils/settings.ts:316            invalid provider clobbers existing
  src/utils/settings.ts:462            "TUI auth modal" mention out of scope
  src/agent/agent.ts:2248              requireProvider misleading on Vertex
  src/providers/vertex/index.ts:84     comment/code mismatch on reasoningEffort
  README.md:306                        env table lists unsupported modes

Changes:

1. Drop oauth_token and service_account_api_key auth modes (covers
   cursor[bot] and Copilot 1, 2, 4, 9). VertexAuthMode narrows to "adc"
   only. The docs and code paths these modes touched in this PR were
   incomplete — VertexUserSettings had no oauthToken/apiKey fields and
   the call site in openapi.ts only passed { mode }, so the modes
   always threw at request time. They are not part of the Vertex AI
   quickstart's recommended auth path either; the research that
   informed this PR explicitly recommends starting with ADC and
   treating other modes as a follow-up after live verification against
   Grok-on-Vertex.

   Files changed:
     - src/utils/settings.ts: VertexAuthMode type narrowed; doc comment
       explains the deferral.
     - src/providers/vertex/auth.ts: switch collapsed to ADC-only;
       resolveExplicitToken and resolveServiceAccountApiKey deleted.
       VertexAuthOptions interface simplified to just { mode }.
     - src/providers/vertex/auth.test.ts: oauth_token and
       service_account_api_key suites replaced with one defensive test
       that confirms unsupported modes throw a typed error.
     - src/utils/settings-vertex.test.ts: fixture updated from
       authMode: "oauth_token" to authMode: "adc"; new test verifies
       a saved unsupported authMode normalizes back to the ADC default.
     - README.md: env-var table no longer lists GROK_VERTEX_AUTH_MODE
       values; replaced with a one-line note that ADC is the only
       supported mode in v1.
     - .env.example: GROK_VERTEX_AUTH_MODE block replaced with the
       same note.

2. Stale GROK_USE_VERTEX text (Copilot 3). The unsupported-endpoint
   error in src/providers/vertex/openapi.ts referenced the legacy
   GROK_USE_VERTEX=1 flag from the prior branch. Updated to point at
   the new --provider xai / unset GROK_PROVIDER plus GROK_API_KEY
   path that this PR actually ships.

3. Invalid-provider clobbers (Copilot 5). saveUserSettings used the
   spread pattern { ...partial, ...(normalize? { provider: x } : {}) }.
   Because ...partial spreads partial.provider directly, an invalid
   value like saveUserSettings({ provider: "anthropic" }) would land
   on next.provider and the conditional override would not run. Fixed
   by ALWAYS overriding when partial.provider is supplied: returns
   { provider: normalized ?? current.provider } so an invalid update
   either keeps the previously saved provider or omits the field via
   JSON.stringify's undefined elision (matches the existing test).

4. "TUI auth modal" reference (Copilot 6). requireVertexSettings
   error rewritten to point at the actual supported configuration
   paths: GROK_VERTEX_PROJECT_ID, GCP_PROJECT_ID, or vertex.projectId
   in ~/.grok/user-settings.json. The TUI auth modal remains a planned
   follow-up per the PR description; the error no longer promises it.

5. Provider-aware requireProvider() (Copilot 7). When this.provider
   is null, surface "Vertex AI is selected but no project id is
   configured..." in Vertex mode rather than "API key required". xAI
   message unchanged.

6. Vertex resolveRuntime + reasoningEffort (Copilot 8). Comment in
   src/providers/vertex/index.ts said reasoningEffort was omitted but
   the code populated providerOptions when a per-model effort was
   saved. Since capabilities.reasoningEffort is false on the Vertex
   adapter, dropping the option matches the capability matrix and
   prevents the agent from surfacing a setting Vertex would silently
   ignore. resolveRuntime now returns providerOptions: undefined for
   Vertex; the comment matches the code.

Tested:
- bun run typecheck (clean)
- bun run lint (clean; 5 pre-existing upstream warnings, none in
  changed files)
- bun run test (334/334 passing across 53/54 files; the 1 failed file
  is the same pre-existing src/storage/sessions.test.ts upstream
  bun:sqlite issue)
- bun run build (clean dist)
@superagent-security superagent-security Bot added the pr:flagged PR flagged for review by security analysis. label May 9, 2026
@superagent-security
Copy link
Copy Markdown

Brin PR Security Scan

This PR has findings that should be reviewed.

  • Score: 35/100
  • Verdict: suspicious

Findings:

  • first_time_contributor: AmeerJ97 has no prior commits to superagent-ai/grok-cli.
  • obfuscation: High-entropy addition detected (entropy=5.58, 210 chars)

Analyzed by Brin

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 0d71af5. Configure here.

Comment thread src/providers/vertex/index.ts Outdated
Comment thread src/providers/index.ts Outdated
…rovider

Addresses both fresh cursor[bot] findings on commit 0d71af5. Audited
the rest of the PR for adjacent dead-code / unused-export risk before
committing — no other set-but-never-read fields, no other genuinely
dead exports, no remaining stale references.

cursor[bot] Medium severity (src/providers/vertex/index.ts:59):
  "Vertex adapter stores settings but never uses them"

  VertexProviderAdapter held `private readonly settings: VertexSettings`
  populated in the constructor, but the field was never read elsewhere.
  All request-time settings resolution happens inside createVertexFetch
  via its own requireVertexSettings() lookup. The documented
  options.settings parameter (advertised as "Tests can pass a fully-
  formed object") was therefore validated at construction and silently
  ignored at request time — a contract violation if a caller ever
  passed it.

  Fix: drop the field, drop the options.settings parameter from
  VertexAdapterOptions, drop the now-unused VertexSettings type
  import. The constructor still calls requireVertexSettings() for the
  side-effect (eager misconfiguration failure at construction rather
  than at first request), with a comment explaining the intent.

cursor[bot] Low severity (src/providers/index.ts:49):
  "Exported createDefaultProvider function is never used"

  Confirmed by grep: only the declaration, no callers anywhere in
  src/. The function duplicated logic already available via
  createProvider({ kind: "xai", apiKey, baseURL }) and the legacy
  createProvider(apiKey, baseURL) shim in src/grok/client.ts.

  Fix: delete the function and its only-used-by-it ProviderKind
  type-only import. ProviderKind is still re-exported from the
  module via the existing `export type { ... } from "./types"`
  block, so external API surface is unchanged.

Adjacent audit (no further changes needed):
  - 6 of 7 ProviderCapabilities flags are not consulted by any
    consumer, but they are interface fields (API surface, not dead
    code) and cursor[bot] did not flag them on prior reviews. Method-
    presence checks (provider.imageModel?, provider.responsesModel?,
    etc.) gate the corresponding behavior already; the boolean flags
    serve as adapter-implementer documentation.
  - XaiAdapterOptions / VertexAdapterOptions / VertexAuthOptions are
    exported but no external consumer imports them. They are parameter
    types of exported functions, so removing them would force callers
    to inline or re-derive the type. Kept as public API surface.
  - No set-but-never-read fields remain on either adapter class.
  - No TODO/FIXME/XXX markers in changed code.
  - No stale references to GROK_USE_VERTEX, "TUI auth modal",
    createDefaultProvider, vertex.oauthToken, or vertex.apiKey
    anywhere in src/, README.md, .env.example, or CHANGELOG.md.

Tested:
- bun run typecheck (clean)
- bun run lint (clean; 5 pre-existing upstream warnings, none in
  changed files)
- bun run test (334/334 passing across 53/54 files; the 1 failed
  file is the same pre-existing src/storage/sessions.test.ts upstream
  bun:sqlite issue)
- bun run build (clean dist)

Net diff: 8 insertions, 20 deletions (-12 LOC).
@AmeerJ97
Copy link
Copy Markdown
Author

AmeerJ97 commented May 9, 2026

@homanp Finally clean. My bad for the noise on #287 and the closed-without-merging PRs leading up to this. The Vertex partner-model API has more hidden details and i kept getting baited lol (separate reasoning vs non-reasoning SKUs instead of a reasoning_effort knob, batch unsupported, ADC-only auth in practice for v1, hosted xAI tools all 404 on Vertex, smaller context windows than the xAI flagship, etc.)

This PR covers Vertex AI Grok (forreal this time) via Google ADC but behind a GrokProviderAdapter contract at src/providers/, so the xAI path is identical for existing users and opt-in via --provider vertex flag or GROK_PROVIDER=vertex. Tried to make 14 commits less of a nightmare for you to check. Two full-disclosure notes: i dont have xAI API to test that path on my end (verified via the existing test suite + code review only), and grok-4.3 isnt available on Vertex — only the four 4.20 / 4.1-fast SKUs — which is why the screenshot above shows it 404-ing before i switched to 4.20. Otherwise should be clear.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor:verified Contributor passed trust analysis. pr:flagged PR flagged for review by security analysis.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants