Fix #239 reasoning-echo 400 self-heal, #233 glm tool-image 422, #228 provider toggle - #242
Merged
Merged
Conversation
…fixes #239) DeepSeek V4 thinking mode requires reasoning_content to be passed back on multi-turn requests. When Copilot Chat compaction, history trimming, or a pre-thinking-capture turn removes it from the replayed history, every follow-up turn 400s and retries never recover. Add a recoverable-400 pattern that strips the reasoning_content echo from assistant messages AND turns reasoning_effort off, making the request self-contained. Dropping reasoning_effort stops the cycle: with thinking still on, the next response emits new reasoning that compaction strips again, re-400ing the turn after.
…fixes #233) glm-5.3-flash upstream (Console Go) rejects image_url parts inside role:"tool" content with 422 "[invalid_request_error] Input should be a valid string", while the SAME images in a user message return 200 (reproduced directly against zen/go/v1 chat-completions). The tool result stays in history, so every follow-up turn re-422s. Introduce requiresStringToolContent() mapping per upstream: - "drop" — mimo-*: flatten + placeholder (existing #38 behavior, unchanged) - "defer" — glm-5.3*: flatten the tool message to a string and move the images into a follow-up user message, preserving vision - null — forward multimodal tool content unchanged (kimi, glm-5.2, minimax, qwen)
fixes #228) Two defects in the Remove/Re-add Provider flow: 1. Wrong-key write on agent variants: toggleProviderEnabled() wrote <variant>.enabled (e.g. opencodezen-agent.enabled) for agent-host definitions, but the provider when-clause and settings schema only read opencodezen.enabled. The provider stayed removed while settings looked enabled — the exact workaround in the issue report (manually deleting the stale key). Resolve agent variants to their base vendor before touching configuration. 2. Blind toggle: the command flipped the setting without regard to the desired outcome, so running it twice could never re-add the provider without a reload in between. Replace with a state-aware quick-pick (Remove when enabled / Re-add when disabled, Esc cancels) and retitle the command to 'Toggle Provider Registration in Language Models'.
…chain - Extract the deferred tool-image emission into the pure withDeferredToolImageMessages() helper (request/shared.ts) so the glm-5.3* relocation is testable without a VS Code host; convertMessage now delegates to it (behavior unchanged). - Mock-server retry E2E: new deepseek-v4.1-flash validator scenario + full-loop and healthy-request cases (9/9). - Unit tests for the deferred-message shape and the requiresStringToolContent mapping (480 total).
This was referenced Sep 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Batch of three verified bug fixes: #239, #233, #228.
Fixes #239
Fixes #233
Fixes #228
1. #239 — DeepSeek 400 "reasoning_content must be passed back" (self-heal)
When Copilot Chat compaction, history trimming, or a pre-thinking-capture turn strips prior-turn reasoning from the replayed history,
deepseek-v4.1-flash(thinking on) rejected every follow-up turn with HTTP 400 and retries could never recover.Fix: a new recoverable-400 pattern in
src/retry.ts(executed by the existing 400-patch loop inengine.ts) strips thereasoning_contentecho from assistant messages and turnsreasoning_effortoff — making the request self-contained and stopping the lose-echo→400 cycle. No-ops when there is nothing to strip.2. #233 — glm-5.3-flash 422 on tool-result images
The Console Go upstream rejects
image_urlparts insiderole: "tool"content (422Input should be a valid string) while accepting identical images in user messages (verified with a direct gateway repro matrix in the issue). The tool result stays in history, so every follow-up turn re-422s.Fix: new
requiresStringToolContent()mapping insrc/models/modelCapabilities.ts:mimo-*→ existing drop-with-placeholder behavior (issue fix: add option to turn off reasoning #38, byte-identical)glm-5.3*→ tool message flattened to a string, images moved to a follow-up user message via the new purewithDeferredToolImageMessages()(request/shared.ts) — vision preserved3. #228 — Toggle Provider Registration wrong-key write + blind toggle
Two defects: (a) agent-variant definitions wrote
<variant>.enabled(e.g.opencodezen-agent.enabled) — a key the providerwhenclause never reads — leaving the provider permanently removed while settings looked enabled; (b) the command was a blind toggle behind a "Remove/Re-add" title.Fix:
toggleProviderEnabledresolves agent variants to the base vendor before touching configuration, and derives Remove vs Re-add from the current setting via a confirmable quick-pick (Esc cancels). Command titles reworded to "Toggle Provider Registration in Language Models".Verification
npm run lint— full 7-check gate PASSnpx tsx scripts/test-retry-e2e.ts), incl. the DeepSeek validator scenario (400 → patch → 200)tmp/e2e-issues-233-239-serialization.mjs), incl. MiMo/kimi regression guardsDocs
docs/issues/102-…(OpenCode Go API request failed (400) #239),103-…([BUG] Error loading an image with glm-5.3-flash #233),104-…([BUG] opencodezen.toggleProvider disables provider #228)CHANGELOG.md[Unreleased] entries +ARCHITECTURE-MAP.mdupdated (LoC, flows, shared libs, test table)Merge method: merge commit (no squash) — preserves the per-fix commit history.