dsh上modlens的自动GeminiAPI密钥轮换
Automatic Gemini API key rotation for modlens on DeepSeek Harness (dsh) — when one key hits its quota (HTTP 429), the read
automatically switches to the next key in the pool and retries, with zero
intervention. Works everywhere modlens reads an image: the dsh GUI paste flow,
the modlens_read_image tool, and the CLI.
⚠️ Unofficial: this patches the installed modlens package. The patch is
wiped by any modlens upgrade;patch.ps1re-applies it in one command.
If modlens upstream ever ships native multi-key support, drop this project.
Why
modlens reads images through a single Gemini API key stored in ~/.modlens/config.json. Free-tier keys hit daily quota (429 RESOURCE_EXHAUSTED) / rate limits quickly, and modlens has no retry or
failover for that. This project adds:
- a key pool (
~/.modlens/api-keys.json) — list, add, rotate, inspect - an engine patch — 429 triggers an automatic switch to the next pool key,
persisted to the config, then a retry of the same request (up to 8 rotations) - a CLI wrapper — 429 → rotate + retry; 5xx → backoff retry on the same key
- a re-patch script — re-applies the engine patch after a modlens upgrade
Requirements
- DeepSeek Harness (dsh) with the modlens plugin installed:
npx -y @deepseek-ai/dsh plugin --profile web add @liustack/modlens@<version> - Node 22.19+ (modlens requirement)
- PowerShell (Windows) — the scripts are
.ps1
Install
Clone this repo (or copy scripts/), then:
1 | # 1. copy scripts next to the modlens config |
The active key is the one modlens uses: if you already configured a key via modlens config set gemini-api.apiKey, add it to the pool too so rotation can
cycle back to it.
Usage
1 | # manage the pool |
The engine patch makes rotation automatic for every read path (GUI paste, modlens_read_image tool, CLI), so rotate.ps1 rotate is mainly for manual
override or diagnosis.
If you use a proxy
modlens itself supports it — no changes needed here:
1 | modlens config set proxy http://127.0.0.1:<port> |
Note: Google’s Gemini API is region-restricted. A proxy exit in an unsupported
region (e.g. mainland China, Thailand) fails with 400 User location is not supported for all keys — rotation cannot fix
that; switch the proxy node instead.
After a modlens upgrade
1 | powershell -ExecutionPolicy Bypass -File "$env:USERPROFILE\.modlens\patch.ps1" |
It detects whether the patch is still present; if a new version changed the
targeted code and the hunks no longer match, it reports which hunk failed and
tells you to file a new patch.
How it works
modlens ships two components in one package:
dsh/index.js— the dsh plugin shell: registersmodlens_read_image,
handles paste-to-path. It contains no image-reading logic; it spawns a
child process running the CLI engine.dist/main.js— the CLI engine: reads the image, calls Gemini
(executeGeminiApi), parses structured JSON. Every read path funnels
through this file.
The patch lives in executeGeminiApi: a single request becomes a loop that
rotates the pool on 429. See PATCH.md for the exact change.
Security
- Keys are stored in plain text at
~/.modlens/api-keys.json(same trust
level as modlens’s ownconfig.json, which also stores the key in plain
text). Do not share your home directory. - This repo contains no keys, no credentials, no machine-specific paths —
all paths derive from$env:USERPROFILE.
Credits & license
- modlens by Leon Liu (liustack) — the vision engine this project wraps and patches. MIT licensed
(Copyright © 2026 Leon Liu), seeLICENSE.modlens.
The patch hunks in this repo are a derivative modification of modlens
source and carry its MIT notice as required. - This project is not endorsed by upstream — it is an independent utility
that depends on modlens. - Our own scripts and docs: MIT (see
LICENSE). - Full attribution:
ACKNOWLEDGMENTS.md— please star
the upstream project, the real work lives there.