feat(coding-agent): Vertex Model Garden open models via ADC
Summary
Adds the builtin vertex-model-garden extension for Vertex Model Garden open models via Google Application Default Credentials only. Configure ADC (gcloud auth application-default login); the lane joins the same shared credential chain the builtin google-vertex provider already uses — no token script or local proxy.
The vertex-garden starter list is exactly:
deepseek-ai/deepseek-v4.1-flash-maas— DeepSeek V4.1 Flash (Vertex), global-only, reasoning enabled, 1,000,000-token context from senpi's existingdeepseek-v4-1-flashmodel data. Published list price $0.30/$1.20 per 1M tokens, cache hit $0.03 (promotional: at no charge through 2026-10-16).zai-org/glm-5.2-maas— GLM 5.2 (Vertex), published list price $1.40/$4.40 per 1M tokens, cached input $0.14.
Marketplace partner models, including Claude and Grok, are excluded because they are card-billed and promotional credits do not apply.
Request path: global OpenAI-compatible endpoint, ADC bearer auth, x-goog-user-project quota header, existing OpenAI streaming. The project comes from GOOGLE_CLOUD_PROJECT/GCLOUD_PROJECT, else the ADC quota project, else getProjectId() — never from an API-key slot. google-auth-library stays a pinned direct dependency, reached through a Node-only lazy boundary.
Maintainer review fixes (head 4a0780618, merged with origin/main 2fc705f55)
- The provider is ambient, not configured.
vertex-gardenno longer registersapiKey: "$GOOGLE_CLOUD_PROJECT". It declares anambientAuthhook on the extension provider config (packages/coding-agent/src/core/provider-composer.ts,.../extensions/types.ts, composed into an ambientApiKeyAuthin.../core/provider-api-key-auth.ts), mirroring the builtin google-vertex ADC lane (packages/ai/src/providers/google-vertex.ts:92). Availability is the resolution of the ADC chain itself (.../vertex-model-garden/auth.ts), so the models are no longer listed without ADC, the auth status carriesambient: true, and the lane never outranks a provider the user configured nor becomes the automatic default over it.fallbackEligible: () => falseis unchanged. - The project no longer travels through the API-key slot.
.../vertex-model-garden/transport.ts(defaultResolveVertexAccess) passesoptions.envonly, so the ADC quota-project andgetProjectId()fallbacks are reachable and a stored secret can never reach the request URL. - Offline tests for the real ADC path.
packages/ai/test/google-vertex-adc.test.ts(5 cases: token minted by the file's own token endpoint,GOOGLE_CLOUD_PROJECT/GCLOUD_PROJECTprecedence, explicit-option precedence, ADC quota-project fallback, empty-token error).packages/coding-agent/test/suite/vertex-model-garden-extension.test.tsadds: default resolver ignores the apiKey slot, quota fallback reachable, registration/availability gating (ambient + available with ADC, unavailable without), and default-model selection unchanged for a user with only Vertex ADC +GOOGLE_CLOUD_PROJECT(+ location for google-vertex). The fixture is a workload-identityexternal_accountADC file whosetoken_urland subject-token URL point at a loopback server — aservice_accountfile cannot be used offline because that flow hardcodes Google's token endpoint — so no request leaves the machine. No network, no real credentials. - Paid models no longer show $0. Both models carry the prices published on the Agent Platform pricing page ("Deepseek's models" and "GLM's models"; cited in
.../builtin/changes.md).
Also, since the optional note applied: every thinking level is marked unsupported (thinkingLevelMap all null) because these endpoints accept no thinking parameters, so no level is offered that would be silently ignored. The 403/404 hint suggestion was left out to keep the diff scoped; it needs a wire-error seam the transport does not own today.
Validation at 4a0780618
- Scoped vitest green:
packages/ai5/5 (test/google-vertex-adc.test.ts),packages/coding-agent7/7 (test/suite/vertex-model-garden-extension.test.ts). Provider/auth-adjacent files also run green (82 + 33 tests). - Failing-first proof: the new default-selection/gating cases fail on the pre-fix extension code (4 failed | 3 passed, exit 1) —
red-pre-fix.txt. node scripts/check-pr-changelog.mjsexactly as CI runs it (CHANGELOG_GATE_BASE= PR base322c56ef…, no label): exit 0, 16 production paths covered;node scripts/audit-changes-md.mjs: 489/489 covered, exit 0.NODE_OPTIONS=--max-old-space-size=6144 bun run check: exit 2 — the only failures are two pre-existingtscerrors fromorigin/main's catalog regeneration (packages/ai/test/context-overflow.test.ts:581andpackages/ai/test/total-tokens.test.ts:749still nameanthropic/claude-sonnet-4, which main's regeneration dropped from the OpenRouter catalog). A cleanorigin/mainworktree fails identically, and both files are untouched by this branch. Every other step (biome, pinned deps, ts-imports, lockfiles, platform lock, browser smoke) passed; full receipt inroot-check.txt.- Live QA through ADC project
able-brace-426917-c5on the global endpoint, isolated senpi sandbox, real auth asserted unchanged: both IDs exist and answer —
deepseek-ai/deepseek-v4.1-flash-maas: exit=0 timedOut=false ok=true output=VERTEX_DEEPSEEK_OK
zai-org/glm-5.2-maas: exit=0 timedOut=false ok=true output=VERTEX_GLM_OK
real auth.json unchanged: PASS
git diffscan for home paths, tokens and credential patterns: clean. Evidence stays ignored and uncommitted.
Receipt excerpts:
Test Files 1 passed (1) Tests 5 passed (5)
Test Files 1 passed (1) Tests 7 passed (7)
RED_PRE_FIX_EXIT_CODE=1
changelog-gate: PASS - changes.md coverage complete (16 production path(s) covered); changelog entry updated (packages/ai/CHANGELOG.md, packages/coding-agent/CHANGELOG.md)
CHANGELOG_GATE_EXIT_CODE=0
ROOT_CHECK_EXIT_CODE=2
Receipt hashes (local-ignore/qa-evidence/20261016-vertex-garden-maintainer-fixes/, also archived in the shared checkout):
7124df60afe64b94edb0788d79721e60f4d4ee035850809acb7fa70a1110b6e7 red-pre-fix.txt
751ad236007c9c4e75631e02687f501a989bced44365c4f16358dafa5341a7af root-check.txt
bd114cf0e15d284444f64459b4c7e29f7e9da9d3e5abacfcedf1dbf06ad6fc41 deepseek-cli.json
f1d8c3b4d2a2ae018f0542d4c79b8d9ac2e175df04074a0b752ada2a47d035e8 glm-cli.json
7ec903ab55ea715fcee7a38746c690e4cecf447ee9b32d1ebc36be485119f68b live-cli.txt
Branch history
a638f4dfa: mergedorigin/main(earlier base) with a merge commit, preserving both sides of both tracker conflicts.ada7c709f: trimmed the implementation to the two ADC open models.308fc3f7: earlier gate fixes (changelog entries, tracker coverage, duplicate-test removal).cd403e1b7: merge oforigin/mainat2fc705f55; tracker conflicts resolved by keeping both sides.4a0780618: this review round — ambient registration, project off the key slot, offline ADC tests, published prices, thinking-level consistency.
Normal push; no force-push or rebase. Do not merge: maintainer re-review is required.