dsh-vertex-gemini
Use Gemini on Google Cloud Vertex AI from DeepSeek Harness (dsh), signed in with your own Google account. No API key is created or stored: the plugin uses the Google login already on your machine (Application Default Credentials) and bills the Google Cloud project you name.
It works with the official npx @deepseek-ai/dsh — no fork and no build.
What you need
- Node.js 22.19+ or 24+.
- The gcloud CLI.
- pnpm on your PATH (
npm install -g pnpm): thedsh plugincommand runs it inside the profile. - Read access to this repository and the GitHub CLI signed in (
gh auth login), to download releases. - A Google Cloud project with the Vertex AI API enabled, and permission to call it (
roles/aiplatform.user).
Set up (about two minutes)
Sign in once. This stores a Google login that the plugin refreshes on its own:
gcloud auth application-default loginDownload the latest release into a folder you will keep, then install it into the Web profile. The profile records the tarball's absolute path, so a file deleted from Downloads breaks the next profile install;
~/.dsh/pluginsis a safe home for it:mkdir -p ~/.dsh/plugins gh release download --repo mn288/dsh-vertex-gemini --pattern '*.tgz' --dir ~/.dsh/plugins npx @deepseek-ai/dsh plugin --profile web add ~/.dsh/plugins/dsh-vertex-gemini-0.1.0.tgzpnpm ends with a block of
missing peer @deepseek-ai/...warnings. They are expected: those packages live one directory up in the profile tree, where Node finds them at run time. The line to look for is+ dsh-vertex-geminiunderdependencies.To use the plugin from the terminal as well, repeat the
addcommand with--profile headless. To update later, download the newer release into the same folder and run the sameaddcommand with the new file.Name your Google Cloud project. Either export it in the shell that starts
dsh:export GOOGLE_CLOUD_PROJECT=my-gcp-projector save it in
$DSH_HOME/settings.yaml(by default~/.dsh/settings.yaml):llm-vertex: project: my-gcp-projectStart the Web UI and pick the model:
npx @deepseek-ai/dsh webIf
dsh webwas already running, stop it and start it again: plugins are loaded at startup. Then open the model picker and choose Google Vertex AI → Gemini 3.8 Flash. The choice becomes the default for new sessions.The picker offers the reasoning levels Low, Medium and High. A default of
xhighormaxleft over from another provider insettings.yamlmakes every request fail withUNSUPPORTED_REASONING_EFFORT; pick a level in the picker or setreasoningEffort: highunderagent-default-model.
Until a project is set, the provider is listed under Settings → Models but no model appears in the picker. That is expected: the route stays off until it knows which project to call.
To remove the plugin: npx @deepseek-ai/dsh plugin --profile web remove dsh-vertex-gemini.
Settings
Every field is optional and goes under llm-vertex: in settings.yaml. Changes apply to the next request; no restart is needed.
| Field | Default | Meaning |
|---|---|---|
project |
$GOOGLE_CLOUD_PROJECT, then $GCLOUD_PROJECT |
Google Cloud project that is called and billed |
location |
global |
Vertex AI location; a region such as europe-west1 uses that region's endpoint |
reasoningEffort |
high |
Default thinking level: low, medium, or high |
models |
Gemini 3.8 Flash | Models shown in the picker; each entry takes id, and optionally name, description, contextWindow, maxTokens |
maxTokens |
65536 |
Output cap for a model that names none |
defaultContextWindow |
1048576 |
Context size for a model that names none |
publisher |
google |
Prefix added to a bare model id on the wire (gemini-3.8-flash is sent as google/gemini-3.8-flash) |
baseURL |
computed from project and location | Full OpenAI-compatible endpoint root, for a company gateway |
auth |
adc |
adc uses the Google login; access-token reads a bearer you supply |
accessTokenEnv |
GOOGLE_OAUTH_ACCESS_TOKEN |
Where the bearer comes from with auth: access-token (for CI jobs that mint their own token) |
streamIdleTimeoutMs |
300000 |
How long one silent stretch of a response may last before the request fails |
retryPolicy |
five retries | Retry behaviour for failed model requests |
Adding a second model:
llm-vertex:
project: my-gcp-project
models:
- id: gemini-3.8-flash
name: Gemini 3.8 Flash
- id: another-gemini-model-id # any model id your project can call
name: Shown in the picker
Any Gemini model id your project can call works even when it is not listed; the list only feeds the picker.
When something fails
| Message | Cause and fix |
|---|---|
MISSING_CREDENTIAL … run "gcloud auth application-default login" |
No Google login on this machine, or it expired. Run the command and retry; no restart needed. |
AUTH |
The login exists but Google refused it (revoked, or the account lacks access). Sign in again, and check the account has roles/aiplatform.user on the project. |
NOT_FOUND |
The project cannot use that model, or the model id or location is wrong. Check the id, try location: global, and confirm the Vertex AI API is enabled. |
QUOTA / RATE_LIMIT |
The project's Gemini quota is exhausted or throttled. The harness retries on its own; raise the quota in the Cloud console if it persists. |
| No Vertex model in the picker | No project is configured. See step 3. |
UNSUPPORTED_CONTENT |
You attached an image. This plugin sends text only. |
Verification status
Verified on 2026-09-21 against the real Vertex AI API (project common-ai-tooling-prd, location global, Gemini 3.8 Flash): the real-API test below (a text answer, then one tool-call round trip with the signature replayed) passes, and a headless dsh session installed from the release tarball read a file through a tool and answered correctly. Unit tests, a Loader boot test, and an install-and-run smoke against a local mock also pass.
Re-run the real-API test with a valid Google login whenever the adapter or the harness version changes:
DSH_VERTEX_E2E=1 DSH_VERTEX_PROJECT=my-gcp-project pnpm exec vitest run tests/adapter.e2e.ts
Gemini 3.8 Flash counts its thinking tokens against the output cap: a request with a very small maxTokens can finish with max-tokens and no text. Leave the cap at the default (65536) or at least in the low thousands.
Limitations
- Text only. Image input is refused rather than silently dropped.
- No settings form. The Models page lists the provider but has no dedicated card for it; configure it through the environment variable or
settings.yamlas shown above. - Tested against
@deepseek-ai/dsh0.1.5-rc.2. The harness APIs are pre-stable, so a later release may need a plugin update.
How it works
The plugin registers one provider route, vertex-ai, and talks to Vertex AI's OpenAI-compatible chat-completions endpoint with streaming. Two details matter for agent work:
- Thought signatures. Gemini 3 attaches an opaque signature to a tool call and rejects the follow-up request if it is not sent back. The plugin stores each signature next to the tool call in the session log and echoes it on later requests, so multi-step tool use survives restarts and resumed sessions. History produced by another model or provider is sent with Google's documented skip marker instead.
- Credentials.
google-auth-libraryfinds the login in Google's standard order (GOOGLE_APPLICATION_CREDENTIALS, the gcloud user login, then the metadata server), caches the hourly token, and refreshes it. The library is loaded on the first request only, so the plugin costs nothing at startup when you are using another provider.
Development
pnpm install
pnpm test # unit tests, no network or Google login needed
pnpm run typecheck
pnpm run smoke # packs the plugin, installs it with the published dsh CLI, and runs one prompt against a local mock endpoint
tests/adapter.e2e.ts calls the real API. Run it with a valid Google login:
DSH_VERTEX_E2E=1 DSH_VERTEX_PROJECT=my-gcp-project pnpm exec vitest run tests/adapter.e2e.ts
Sharing it
The repository is private and package.json carries "private": true, so an accidental npm publish is refused. Colleagues need read access first: add them under the repository's Settings → Collaborators. To hand the plugin to them:
- As a release (current setup): bump
version, runnpm pack, and attach the.tgzto a new release withgh release create v<version> dsh-vertex-gemini-<version>.tgz. Colleagues with read access to the repository install it as shown in the setup steps. - Through an internal registry: remove
"private": true, pointpublishConfig.registryat the registry, and publish there; colleagues then install it by name.
License
MIT. The adapter follows the structure of the DeepSeek Harness LLM adapters, which are MIT licensed by DeepSeek; see LICENSE.
No comments yet. Be the first to write one.