continuedev / continuedev/continue
Tracking: make Google Gemini work end-to-end (config, security, errors, docs)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 36k
- Forks
- 5.4k
- PR merge metrics
- No merged PRs in 30d
Description
Summary
Gemini is nominally supported in Continue, but several independent defects make it fail in practice — most visibly for users behind corporate proxies, users on newly created API keys, and anyone relying on embeddings. A common report is "the Gemini API works fine in Google's Python sample, but the same key fails when I put it in my Continue config."
This issue tracks a set of small, independently reviewable PRs that fix each layer. I've split the work into four scoped PRs rather than one large change, since they touch different packages and some overlap with existing (currently stalled) PRs — I'd be glad to coordinate with those authors before merge. This issue is the shared anchor; each PR links back here.
Changes reviewers will want to know about up front
- Token usage — non-breaking:
completion_tokensnow counts reasoning ("thoughts") tokens for thinking models, matching the OpenAI-compatible usage spec. No shape change; values rise for thinking-enabled models, which were previously undercounted (Google'stotalTokenCountalready included them). - Live-test model IDs — non-breaking:
main.test.ts's live suite moves fromgemini-2.5-*to the-latestaliases so it runs for newly created API keys; the trade-off is the suite is no longer pinned to a fixed model. - New public export — additive:
getProxyFromEnvis re-exported from@continuedev/fetch(an existing internal helper) so the adapter shares one source of truth for env-proxy interpretation.
Root causes (each verified against the source)
- Config silently ignored on the chat path. The Gemini adapter built the
@google/genaiclient with onlyapiKey—apiBase,requestOptions.headers,timeout, and all proxy/TLS options were dropped for chat/stream whileembed()honored them. Python'srequestshonorsHTTPS_PROXY/REQUESTS_CA_BUNDLEout of the box, which is why a plain sample works where a gateway-fronted Continue config does not. - API key leaked into a URL.
core/llm/fetchModels.tspassed the Gemini key as a?key=query parameter when listing models — keys in URLs leak via server logs, proxies, and referer headers. - Errors rendered as raw JSON / "Unknown error." Gemini quota/
RESOURCE_EXHAUSTEDresponses carry the real message double-nested in JSON that nothing extracted, so failures were undiagnosable. embed()broken for bare model names.new URL("<model>:batchEmbedContents", apiBase)parsed the model name as a URL scheme and discardedapiBase; the response was also read from the wrong field (batchEmbedContentsvs Google'sembeddings). Anyone enabling@codebase/embeddings hit this.- Docs pointed at gated model IDs. New API keys cannot invoke
gemini-2.5-*("no longer available to new users") even though the API still lists them; examples now use the-latestaliases (checked against the live API).
The four PRs
| PR | Scope | Files | Related upstream work | Depends on |
|---|---|---|---|---|
| 1 — Gemini adapter | Honor apiBase/headers/timeout/proxy/TLS on all paths; surface nested errors; SDK-native embed; thinking-token accounting; serialize the fetch swap |
packages/openai-adapters/**, one export line in packages/fetch/src/index.ts |
Addresses #12008; builds on #12014 (credit to its author) and extends it to proxy/TLS on all paths; incorporates the embed fix from #12517 | — |
| 2 — Key-in-URL | Send x-goog-api-key header instead of ?key= in fetchModels |
core/llm/fetchModels.ts (+ test) |
Same fix as #12190 (credit to its author) | — |
| 3 — CLI errors | Extract nested provider error messages in formatError |
extensions/cli/src/util/formatError.ts (+ test) |
Adapter/CLI counterpart to #13014 (which fixes the GUI layer) | — |
| 4 — Docs | Provider pages + a new end-to-end Gemini guide, real model IDs, role matrix, proxy/gateway config | docs/** |
— | PR 1 (documents its behavior) |
PRs 1–3 share no files and can be reviewed and merged in any order. PR 4 follows PR 1. The Closes #12008 keyword will live in PR 1's own description (a tracking issue doesn't auto-close).
Verification
Every behavioral change is backed by tests that run against a no-mocks local rig, plus manual runs against the real Google API (with a real key, outside CI):
- Automated, no mocks: proxy routing (real local proxy, request hit-counters), TLS and mutual-TLS (self-signed mini-CA, passphrase-protected key), custom headers on the wire,
embedthrough a proxy, env-var-proxy engagement withNO_PROXYbypass, config-over-env precedence, timeout abort, and cross-config credential isolation. - Manual, against the live API: Google's own live model tests pass once pointed at current model IDs (including tool calls, on two models);
fetchModelsreturns real models with the key absent from the URL.
Other notes for reviewers
- openssl is used by the TLS test rig at
beforeAll(present on the CI image; same approach aspackages/fetch's existing e2e tests). - The "Supported roles" table is a new docs convention applied to the Gemini and Vertex pages; happy to extend it to the other providers if that's wanted.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Choose one of the four independently scoped PRs and start with its listed files: packages/openai-adapters, core/llm/fetchModels.ts, extensions/cli/src/util/formatError.ts, or docs/**. Read the existing tests and run the relevant no-mocks suite first. Done means the selected behavior is fixed, covered by tests, and remains compatible with the stated dependencies and verification steps.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- ai, backend-api-design, cli, documentation, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 42/100