Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,20 @@

All notable changes to the **OpenCode Go BYOK Provider** extension are documented here.

## [Unreleased]

### Fixed

- **`[Models]` Free-tier Zen models are hidden from the picker, `opencodego.freeOnly` is deprecated, and every free-Zen claim is removed from the docs (Marketplace review, follow-up to #235/#240).** OpenCode has gated free-tier Zen models to its own app/CLI since Sep 17, 2026 (HTTP 403 for third-party clients — upstream anomalyco/opencode#49580), verified live against all 10 free models in the Zen catalog. With `freeOnly` defaulting to `true`, the Zen picker showed _only_ models that could never serve a request. Free-tier Zen models (`-free` suffix, plus `big-pickle`) are now always filtered out via a vendor-scoped `isZenFreeTierModel()` — the gate is Zen-only: Go's free models (`beam-free`, `minimax-m3.1-flash-free`, `longcat-2.5-preview-free`) are unlimited within a paid Go subscription, explicitly permitted for third-party clients, and remain selectable. `freeOnly` stays registered so existing settings don't error but no longer has any effect. README, extension description, and keywords no longer advertise free Zen models: the free-models table is replaced with a dated policy notice, and stale free claims (quick start, comparison table, FAQ, `free-models` keyword, "free Claude Opus" in the description) are corrected. Documented in `docs/issues/112-20261020-zen-free-tier-policy-followup.md`.

- **`[Errors]` The free-tier / Router.Unavailable hint now renders in the chat, not only the toast (#258 follow-up).** `buildOpenCodeRequestError()` placed the actionable hint in `userMessage`, but VS Code's chat surface renders `error.message` — which carried the raw gateway JSON (`Error from provider (Console): OpenCode's free tier can only be used…`). The hint now replaces the raw detail in both messages; the upstream body is still preserved in the OpenCode output channel (`[http-error-body]`).

## [0.7.10] — unreleased
## [0.7.10] — 2026-10-20

### Added

- **`[Thinking]` Gemini models now get a Thinking Effort picker.** Gemini had no thinking control at all: its registry row declared no thinking family, and the generic `reasoning_effort` fallback is deliberately gated to the chat-completions endpoint (that field is meaningless on the Google wire format), so the picker never rendered and the request went out with `thinkingPayload={}` — the model always answered at its default effort. A new `GeminiThinking` strategy maps the pick to Google's native `generationConfig.thinkingConfig` (`thinkingLevel` + `includeThoughts: true`); verified live on `gemini-4-argon-contributor` that `thinkingLevel: "medium"/"high"` is accepted (HTTP 200) and thinking is actually performed (`usageMetadata.thoughtsTokenCount` billed). Caveat documented in `thinking/gemini.ts`: the gateway relays only an opaque `thoughtSignature`, not thought summaries, so the thinking panel stays empty for Gemini (same class as Muse Spark's `encrypted_content`) — if upstream starts relaying `thought: true` parts the existing Google normalizer maps them with no further client work. Levels come from the model's own models.dev `reasoning_options` (`off`/`on`/`low`/`medium`/`high`), with `opencodego.thinking.gemini` as the workspace default. `off` sends no thinking config at all (model default, unchanged from before).

### Fixed

- **`[Autocomplete]` The default inline-suggestions model no longer 400s silently — `qwen3.5-plus` was removed from the Go gateway, default is now `qwen3.6-plus` (reported by Yannick Huebner).** Inline suggestions send the configured model ID straight to `/chat/completions`, and the old default had vanished from the Go catalog — every request returned HTTP 400 `Model is unavailable`, which the completion engine logs to the output channel and then renders as nothing, so users just saw ghost text never appearing (budget and settings were irrelevant, making it look like a quota bug). Verified live 2026-10-20: gateway validation order is session → model → credential, so a dummy-key probe shows `qwen3.5-plus` rejected with `Model is unavailable` before auth while the new default `qwen3.6-plus` passes model validation (`qwen3.5-plus` also still works on Zen — the removal is Go-only, but suggestions are Go-only too); a real-key run then confirmed `qwen3.6-plus` at 1459ms TTFB with `reasoningChars=0`, matching the old default's latency profile. `DEFAULT_INLINE_MODEL`, the `package.json` settings default/enum, and the README now point at `qwen3.6-plus`; the enum also drops the equally-removed `deepseek-v4-flash` in favor of `deepseek-v4.1-flash`. Note for existing installs: a user-set model is never overwritten, so anyone still on the old default must switch once manually (`"opencodego.inlineSuggestionsModel": "qwen3.6-plus"`). `scripts/probe-completion-latency.ts` refreshed to current model candidates and now sends the required `x-opencode-session` header. Documented in `docs/issues/113-20261020-fim-default-model-removed-upstream.md`.

- **`[Models]` Free-tier Zen models are hidden from the picker, `opencodego.freeOnly` is deprecated, and every free-Zen claim is removed from the docs (Marketplace review, follow-up to #235/#240).** OpenCode has gated free-tier Zen models to its own app/CLI since Sep 17, 2026 (HTTP 403 for third-party clients — upstream anomalyco/opencode#49580), verified live against all 10 free models in the Zen catalog. With `freeOnly` defaulting to `true`, the Zen picker showed _only_ models that could never serve a request. Free-tier Zen models (`-free` suffix, plus `big-pickle`) are now always filtered out via a vendor-scoped `isZenFreeTierModel()` — the gate is Zen-only: Go's free models (`beam-free`, `minimax-m3.1-flash-free`, `longcat-2.5-preview-free`) are unlimited within a paid Go subscription, explicitly permitted for third-party clients, and remain selectable. `freeOnly` stays registered so existing settings don't error but no longer has any effect. README, extension description, and keywords no longer advertise free Zen models: the free-models table is replaced with a dated policy notice, and stale free claims (quick start, comparison table, FAQ, `free-models` keyword, "free Claude Opus" in the description) are corrected. Documented in `docs/issues/112-20261020-zen-free-tier-policy-followup.md`.

- **`[Errors]` The free-tier / Router.Unavailable hint now renders in the chat, not only the toast (#258 follow-up).** `buildOpenCodeRequestError()` placed the actionable hint in `userMessage`, but VS Code's chat surface renders `error.message` — which carried the raw gateway JSON (`Error from provider (Console): OpenCode's free tier can only be used…`). The hint now replaces the raw detail in both messages; the upstream body is still preserved in the OpenCode output channel (`[http-error-body]`).

- **`[Thinking]` MiniMax no longer repeats an identical reasoning preamble before every tool call.** MiniMax is an interleaved thinking model: its official contract (MiniMax-AI/MiniMax-M2 README, "Inference Parameters") requires assistant thinking to be replayed **inline as `<think>...</think>` inside `content`** — the upstream silently drops a separate `reasoning_content` field. The extension replayed MiniMax thinking history as `reasoning_content` (family-gated "tolerated" since PR #123), so prior thinking effectively vanished from context on every follow-up request; in long agent loops the model re-derived the same conclusion at each tool call, producing the same reasoning sentence 15+ times in a row. `shouldEchoThinkingHistory()` now returns `false` for `/^minimax-/i` and `convertMessage()` replays the thinking (plain and tool-call branches, per-tool reasoning included) as a `<think>` prefix on `content` instead. Receive-side `<think>` filtering is untouched. All other families (DeepSeek required-echo, Kimi/GLM/Qwen/Gemini, MiMo omitted, GPT/Claude n/a) keep their existing contracts — the new helpers are gated by `/^minimax-/i` alone. Live E2E against the gateway still pending. Documented in `docs/features/19-20261020-minimax-interleaved-thinking-replay.md`.

- **`[Models]` Gemini models served by OpenCode Go now route to the Google API instead of chat-completions.** Every request to `gemini-4-argon-contributor` failed with `400 Model does not support this protocol.` because the `gemini` row in `core/registry.ts` was restricted to `opencodezen`, so on Go the lookup fell through to the catch-all row and the model was sent to `chat/completions` — while the gateway serves it Google-native (models.dev marks it `@ai-sdk/google`, and OpenCode's own Go endpoint table lists it under `@ai-sdk/google` too). The row now applies to every vendor. Fixing that exposed the second half of the bug: the Google route is built as `{base}/{modelId}:streamGenerateContent?alt=sse`, and Go's built-in `/zen/go/v1` base does not serve that path at all (it answers with the opencode.ai website 404 page), so provider routing gained an optional `googleModelsUrl` — Go's built-in default points at `https://opencode.ai/inference/go/v1/models` (the base OpenCode's own endpoint table documents for the model), while Zen and any configured `apiBaseUrl` gateway keep deriving the route from `modelsUrl` exactly as before (issue #247 contract intact). Every other route (chat/completions, messages, responses, models, usage) is untouched. Routing tests now cover Go, Zen, and both agent-host variants. Registry drift found while investigating (Go/Zen `minimax-m3`, `qwen3.8-max`, `qwen3.8-flash`, `qwen3.7-plus` documented as Anthropic `messages`) is deliberately not changed here — each needs live verification first. Documented in `docs/features/17-20260814-data-driven-model-registry.md`.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ required after toggling.
Ghost-text completions while typing, powered by the OpenCode gateway with **thinking forced off**:

- Opt-in: `"opencodego.inlineSuggestions": true` (requires a window reload).
- Model: `opencodego.inlineSuggestionsModel` defaults to `qwen3.5-plus`, whose `enable_thinking=false` mode is a no-reasoning path (measured ~1.5s TTFB, zero hidden reasoning). Reasoning models (e.g. `deepseek-v4-flash`) burn 100+ reasoning tokens even with thinking off and are not recommended.
- Model: `opencodego.inlineSuggestionsModel` defaults to `qwen3.6-plus` with `enable_thinking=false` (no-reasoning path). Reasoning models burn 100+ reasoning tokens even with thinking off and are not recommended. (The previous default, `qwen3.5-plus`, was removed from the Go gateway — installs on older releases must switch models manually.)
- Tuning knobs (all optional): `inlineSuggestionsDebounceMs` (300), `inlineSuggestionsTimeoutMs` (3000), `inlineSuggestionsMaxTokens` (128), `inlineSuggestionsPrefixLines` (10), `inlineSuggestionsSuffixChars` (300).
- Requests are tiny (10 lines before the cursor + a short suffix by default), debounced 300ms, time out at 3s, and are aborted on the next keystroke.
- The gateway exposes no FIM endpoint, so completions use fill-in-the-middle emulation with FIM tokens over `/chat/completions`.
Expand Down
18 changes: 16 additions & 2 deletions docs/devlog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
# 🧠 OPENCODE COPILOT CHAT DEVLOG

**Branch:** `fix/issue244-followup-id-clobber` (work on `main`) | **Updated:** 2026-09-25 Asia/Jakarta | **Current Phase:** #244 follow-up fix complete + deep-verified (495/495 tests, lint 7/7, retry E2E 9/9, pre-release E2E 17/17); 0.7.8 pending push/PR/build.
**Branch:** `fix/fim-default-model-dead` (work on `main`) | **Updated:** 2026-10-20 Asia/Jakarta | **Current Phase:** FIM default-model fix committed locally (`cb9f4f0`), docs synced (doc 113 + feature doc 15 + CHANGELOG `[Unreleased]`), real-key probe done — `qwen3.6-plus` verified 1459ms TTFB / `reasoningChars=0`; pending: push/PR approval.

---

## ✅ FIM Default Model Removed Upstream — inline suggestions silently dead — 2026-10-20

**Scope:** inline suggestions produced nothing at all (reported via LinkedIn by Yannick Huebner), initially misread as Go budget exhaustion. `DEFAULT_INLINE_MODEL` (`qwen3.5-plus`) had been removed from the Go gateway, so every FIM request returned HTTP 400 `Model is unavailable` which the completion engine logs to the output channel and renders as nothing. The registry's deprecation filter never applied here: FIM sends the raw setting value straight to `/chat/completions`, bypassing the picker. This was the landmine doc 100 flagged on 2026-09-08 ("flagged, unchanged") — upstream finally dropped the model.

**Verification without a paid key:** gateway validates in the order session → model → credential, so a dummy-key probe distinguishes the two failure classes: `qwen3.5-plus` → HTTP 400 `Model is unavailable` (before auth), `qwen3.6-plus` → HTTP 401 `Invalid credential` (model accepted). `qwen3.5-plus` is still served on Zen — the removal is Go-only, and suggestions are Go-only too.

**Fix:** default → `qwen3.6-plus` (direct successor, same `enable_thinking=false` path); `package.json` enum also drops the equally-removed `deepseek-v4-flash` for `deepseek-v4.1-flash`; no settings auto-migration (same call as doc 112 — users on the old default switch manually once). Probe script refreshed to live candidates + required `x-opencode-session` header.

**Real-key probe (2026-10-20, done):** `qwen3.6-plus` + `enable_thinking=false` → HTTP 200, TTFB 1459ms, total 1509ms, `reasoningChars=0` — on par with the old default (1518/1608ms), so the non-thinking rationale carries over; `suffix` field tolerated (HTTP 200); `qwen3.5-plus` re-confirmed HTTP 400.

Docs: `docs/issues/113-20261020-fim-default-model-removed-upstream.md`, feature doc 15 updated, README inline-suggestions section, CHANGELOG `[Unreleased]`.

---

Expand Down Expand Up @@ -62,7 +76,7 @@ Docs: `docs/issues/100-20260923-issue226-thinking-default-echo.md`, `docs/issues

**Verification:** `npm run lint` — all 7 checks, 462/462 tests. Unit-test locks caught 2 stale expectations during the change (metadata kimi context, usage tracker pricing) — both updated as part of the sync.

**Caveats:** 1M context limits not live-verified against the gateway with oversized requests (models.dev is OpenCode's own registry but can lag — #171 precedent). `DEFAULT_INLINE_MODEL` is still upstream-deprecated `qwen3.5-plus` — flagged, unchanged.
**Caveats:** 1M context limits not live-verified against the gateway with oversized requests (models.dev is OpenCode's own registry but can lag — #171 precedent). `DEFAULT_INLINE_MODEL` is still upstream-deprecated `qwen3.5-plus` — flagged, unchanged. _(Resolved 2026-10-20 — doc 113: upstream removed it from Go; default now `qwen3.6-plus`.)_

Docs: `docs/issues/100-20260908-bundled-model-data-sync.md`, CHANGELOG `[Unreleased]`.

Expand Down
Loading
Loading