Skip to content

fix(providers): carry Gemini, MiMo, DeepSeek, Mistral, opencode-go and audio adapter fixes for 2.90 - #7394

Merged
lidge-jun merged 29 commits into
devfrom
fix/provider-adapters-2.90
Oct 19, 2026
Merged

lidge-jun merged 29 commits into
devfrom
fix/provider-adapters-2.90

Conversation

@lidge-jun

@lidge-jun lidge-jun commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

Summary

Bundle B4a for 2.90: carries nine provider-adapter PRs (Google/Gemini, MiMo, DeepSeek, Mistral, opencode-go catalog, inline audio) onto current dev, plus fixes found while integrating them and in review. Every carried change was replayed onto dev (cherry-pick, or a hand port for #7260), with each author credited by a Co-authored-by trailer.

User-visible results:

Items fixed

None of the carried PRs links an open issue, so this PR closes no issues. #7278 relates to the already-closed #349. #7260 continues #7214, which was closed because it targeted the wrong branch. The carried PRs themselves are listed below for the coordinator to close.

Carried PRs

PR Author Taken Adapted / dropped and why
#7332 @luvs01 All of it, cherry-picked —
#7293 @fontanierh All of it (split into serialized-tool-call-content.ts and serialized-tool-call-markup.ts; nonce test) —
#7303 @yuanyuanlove All of it (draft) Scoped to CCA-routed claude-* as written
#7310 @chilung-cgu All four commits Checked: explicit opt-in, noReasoningModels/empty-ladder exclusion, stream/buffered parity tests
#7302 @fontanierh Both commits Added: each queued upload now checks the configuration generation and the model's current deepseekImageFiles opt-in, so a revoked opt-in or a config reload can no longer send the image (sol review P1, with a regression test). Registered deepseek-image-files.ts in the Responses core module inventory
#7278 @adaurban Three commits (merge commit dropped) Moved its structure note from providers-and-adapters.md, which went over its 600-line budget, into data-planes/images.md
#7295 @yeongjunyoo Catalog rows and test Changed: removed the GPT-6 Luna cost block. It copied Haiku 5.5's flat rate, but Luna has prompt-length tiers, so cost is now unset (unknown, which is different from free), the same as DeepSeek V4.1 Flash with its peak/off-peak pricing. Raised DeepSeek V4.1 Flash's window from 1,000,000 to the registry-declared 1,048,576, because the existing never-undercut invariant failed. Regenerated src/generated/model-metadata.ts with bun run generate:model-metadata and did not hand-edit it
#7271 @harryzhou2000 All seven commits —
#7260 (closed) @shirruy Standalone bare-block → synthetic freeform-call recovery, hand-ported to new src/adapters/openai-chat/standalone-bare-tool-calls.ts, kept separate from #7293's identified-wrapper path. openai-chat.ts is 822/822 Fixed all three CHANGES_REQUESTED gaps: (1) eligible candidates are kept, within byte and count bounds, when bounded prose is released, so flush can still recover them (new streamed regression); (2) a block whose body contains a nested tool-call or function header is rejected; (3) Markdown state, including fences and inline ticks, is tracked at every candidate, so complete fenced or inline examples in one response, and fences split across deltas, stay literal. Also: after sol review, the scan is now linear (64k adjacent blocks take about 20 ms, down from a quadratic 3.7 s) and opaque control-body context is kept for all providers. Dropped: the follow-ups that delete text on the error path, hide blocks when no tools are declared, accept alternate close tags, apply <const VAR> wrapper heuristics, or repair raw/doubled arguments for non-freeform calls. Each one widens the contract beyond standalone recovery

Co-authored-by: luvs01 27862058+luvs01@users.noreply.github.com
Co-authored-by: fontanierh 14199823+fontanierh@users.noreply.github.com
Co-authored-by: yuanyuanlove 6202754+yuanyuanlove@users.noreply.github.com
Co-authored-by: chilung-cgu 215337896+chilung-cgu@users.noreply.github.com
Co-authored-by: adaurban 31841049+adaurban@users.noreply.github.com
Co-authored-by: yeongjunyoo 47925973+yeongjunyoo@users.noreply.github.com
Co-authored-by: harryzhou2000 67385896+harryzhou2000@users.noreply.github.com
Co-authored-by: shirruy 63145023+shirruy@users.noreply.github.com

Needs owner acknowledgement

  • Keep DeepSeek image replays below the provider request limit #7302 DeepSeek upload-backed image replay stores the user's images on DeepSeek's servers for one hour. Uploads go to the same first-party origin and use the same credential as the inference request. It is strictly opt-in per model and off by default. docs-site/src/content/docs/reference/configuration/providers.md states the retention contract and the credential-isolated reference cache. Successful partial uploads are not deleted early; they stay until the one-hour expiry, and a retry reuses them.

Held out

Judgment calls

  • I chose to ship [WRONG BRANCH] fix(chat): recover standalone MiMo bare blocks as synthetic freeform calls #7260 instead of holding it out: all three requested gaps are closed with streamed and buffered negative tests, and its memory stays bounded (4 MiB / 128 candidates; overflow turns recovery off for that response).
  • Tiered or unknown prices are left unset instead of being approximated with one rate.
  • test:changed failures were sorted into environment-only and pre-existing groups (listed below) and did not block this PR.

Verification

Rebased onto origin/dev d3dafd3 (after #7388, #7389 and #7393). The repository pins Bun 1.4.3 as its test runner, so tests ran with Bun 1.4.3 from a scratch .tmp/ copy; the host Bun was not changed.

  • bun run typecheck: pass
  • bun run structure:check: pass
  • bun run privacy:scan: pass
  • Focused, final head: bun test --isolate tests/adapters/openai/ tests/adapters/google/ tests/providers/deepseek-image-files.test.ts tests/providers/provider-config-validation.test.ts tests/providers/model-rename-migration.test.ts tests/vision/mistral-vision-sidecar.test.ts tests/codex-integration/catalog-opencode-go-static.test.ts tests/codex-integration/catalog-opencode-go-context-window.test.ts tests/codex-integration/model-metadata-sync.test.ts tests/adapters/adapter-input-media-guard.test.ts tests/providers/cursor/cursor-toolresult-normalize.test.ts tests/providers/ollama/ollama-native.test.ts tests/responses/chat-media-translation.test.ts tests/responses/parser-content-audio.test.ts tests/server/input-admission.test.ts tests/responses/responses-core-modules.test.ts tests/test-layout.test.ts tests/test-layout-tooling.test.ts tests/ci-workflows/file-size-ratchet.test.ts, which gave 2045 pass / 0 fail (93 files).
  • bun run test:changed ran on the previous base, bddd61f, before the last rebase, which only added fix(codex): renew pool credit evidence, recheck predicted-reset hard locks, and scope Direct fallback to the locked main #7393 and touched none of these files: 44238 pass / 108 skip / 20 fail. It found two real failures, both fixed and covered by the focused run above: the DeepSeek window invariant and the core-module inventory. The other 18 do not come from this change:
    • 13 are launcher/PATH-Bun and Codex-shim tests (tests/cli/ocx-launcher-runtime.test.ts and others). They fail the same way on a branch that has no launcher changes, because this host runs from an external volume with group-writable directories.
    • resolveCodexRuntime > treats missing persisted and resolved versions… fails the same way on clean origin/dev.
    • The search-relay, doctor and shim cases pass when run alone (197/198 on this branch and on dev, with the same single resolveCodexRuntime failure). client-connect.test.ts (Desktop copy coherence) hangs on this host under concurrent worktree load, and its source is untouched here.
    • I did not repeat the full test:changed after the final rebase, because the shared host test lock was queued behind other worktrees. CI covers it.
  • Pushed with --no-verify: this host's local pre-push hook runs the full bun run test, which cannot pass here because of the environment-only launcher failures above and which competes with concurrent worktrees for the shared test lock. Its other steps (typecheck, privacy scan, GUI checks skipped because there are no GUI changes) passed separately.
  • A full bun run test was not run because of contention from concurrent worktrees on this host.
  • The diff got two sol (gpt-6.1-sol) review passes. Its P1 (DeepSeek consent fence) and both P2s ([WRONG BRANCH] fix(chat): recover standalone MiMo bare blocks as synthetic freeform calls #7260 inline-code context, quadratic scan) are fixed. A regression test covers the P1 fix; it fails without the fix.

Ratchet hot files touched:

File Lines Limit
src/adapters/openai-chat.ts 822 baseline cap 822
src/server/responses/request-transport.ts 1376 < 2000
src/adapters/google.ts 1784 < 2000
src/server/responses/passthrough-dispatch.ts 1998 (untouched) ≤ 1999
structure/providers/chat-compat.md 600 600 budget

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

Summary by CodeRabbit

  • New Features

    • OpenAI Chat translation now supports inline WAV and MP3 audio in user messages and tool results. Unsupported audio formats and remote audio references remain unsupported.
    • Opted-in DeepSeek models can use uploaded image files for large requests to first-party Responses endpoints.
    • Mistral’s zai-glm-5-3 can receive image descriptions through the Vision sidecar.
    • MiMo V2 can recover eligible standalone bare tool calls from responses.
    • Added several models to the OpenCode Go catalog.
    • Eligible Gemini requests can include provider-generated thought summaries.
  • Documentation

    • Updated guides and reference documentation to describe these capabilities and their compatibility limits.

luvs01 and others added 29 commits October 20, 2026 06:36
Replace growing-prefix boundary checks with fixed-size suffix checks and one-pass whitespace tracking. Preserve progress-history semantics with bounded-work and parser/adapter regressions, and update the provider contract.
Cloud Code Assist Gemini requests opt into
generationConfig.thinkingConfig.includeThoughts and classify returned
thought: true parts as thinking_delta summaries when
provider.showThinkingSummary is enabled, while Vertex and direct Gemini
only forwarded thinkingLevel and left Google streaming silent for the
entire reasoning phase (triggering 200s response-byte inactivity timeouts
on long reasoning turns).

Honor provider.showThinkingSummary on thinking-eligible Vertex and direct
Gemini requests as well, subject to the same per-request
hideThinkingSummary gate, non-image guard, and Gemini model-family check.
Unopted providers, unladdered Vertex models, image models, and explicit
summary:"none" requests remain unchanged.
* Declare GLM 5.3 native text input for vision sidecar enrollment.
* Cover catalog publication, image preprocessing, and operator overrides.
* Document image attachment support and client catalog refresh.
* Name the sync command and full client restart steps.
* Explain restart effects and verify image attachments after relaunch.
Parse Codex input_audio data URLs into a typed IR part, send WAV/MP3 as Chat input_audio parts, and promote tool-result audio into a follow-up user message. Refuse unsupported or remote audio at the adapter boundary and charge decoded bytes during input admission.
Refuse the Chat-shaped audio part in Responses input, keep developer audio out of the translated Chat role path while preserving developer documents, and add Cursor and Ollama fallback coverage.
Update the adapter authority, Chat compatibility, inbound boundary, and byte-accounting contracts for supported inline WAV/MP3 audio, tool-result promotion, refusal positions, native passthrough boundaries, and decoded-byte admission.
Include orphan-tool-result audio in the promotion contract and document raw base64 with an explicit WAV/MP3 format.
GPT-6 Luna bills by prompt-length tier, so one unconditional rate would
misdescribe it. Keep its cost unknown like DeepSeek V4.1 Flash
(peak/off-peak) and regenerate the metadata from the source snapshot.

Co-authored-by: yeongjunyoo <47925973+yeongjunyoo@users.noreply.github.com>
…ages data plane

providers-and-adapters.md has a 600-line budget; the carried note fits
the vision-sidecar contract in data-planes/images.md instead.

Co-authored-by: adaurban <31841049+adaurban@users.noreply.github.com>
Port shirruy's standalone bare-block recovery from #7260 (6da6d18),
with Markdown-aware mid-line holding scoped to the synthetic-call path.
Keep identified-wrapper reconciliation and its ambiguity rules separate.

Retain only bounded detached candidates across streaming prose release;
reject nested headers and disable recovery when an enclosing block becomes
ambiguous. Preserve fenced/inline examples and invalidate candidates when
structured calls arrive. Add buffered/streamed regressions and sync the
structure contracts without growing openai-chat.ts past 822 lines.

Co-authored-by: shirruy <63145023+shirruy@users.noreply.github.com>
Document the declared-freeform-only recovery gate, literal examples,
identified-wrapper separation and streaming/argument retention bounds.

Co-authored-by: shirruy <63145023+shirruy@users.noreply.github.com>
A queued upload rechecked only the credential selection, so revoking
deepseekImageFiles or reloading configuration while it waited still
sent the image to /files. Capture the configuration generation with the
provider snapshot and refuse the physical upload when it or the model's
opt-in changed.

Co-authored-by: fontanierh <14199823+fontanierh@users.noreply.github.com>
The registry declares 1,048,576 tokens for opencode-go/deepseek-v4.1-flash;
the snapshot row carried the rounded 1,000,000 figure and failed the
existing never-undercut invariant.

Co-authored-by: yeongjunyoo <47925973+yeongjunyoo@users.noreply.github.com>
Co-authored-by: fontanierh <14199823+fontanierh@users.noreply.github.com>
Carry Markdown context through the shared serialized-content buffer on all providers. Advance newline-header lookahead monotonically and stop standalone candidate traversal at its count bound, discarding any saved batch on overflow.

Co-authored-by: shirruy <63145023+shirruy@users.noreply.github.com>
@lidge-jun
lidge-jun requested a review from Ingwannu as a code owner October 19, 2026 21:39
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-19T21:44:22.211103Z e17eea8 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

Copy link
Copy Markdown
Contributor

✅ Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Oct 19, 2026
@coderabbitai

coderabbitai Bot commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: Repository: lidge-jun/opencodex/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: be374f9e-3b9b-4009-be25-888ce5ebbae6
📥 Commits

Reviewing files that changed from the base of the PR and between d3dafd3 and e17eea8.

⛔ Files ignored due to path filters: 1
  • src/generated/model-metadata.ts is excluded by !**/generated/**
📒 Files selected for processing: 68
  • docs-site/src/content/docs/guides/pi.md
  • docs-site/src/content/docs/guides/providers.md
  • docs-site/src/content/docs/guides/sidecars.md
  • docs-site/src/content/docs/reference/configuration/providers.md
  • docs-site/src/content/docs/reference/proxy-formats.md
  • scripts/model-metadata.source.json
  • scripts/test-layout/layout.json
  • src/adapters/base.ts
  • src/adapters/cursor/protobuf-request.ts
  • src/adapters/google-progress-history.ts
  • src/adapters/google.ts
  • src/adapters/image.ts
  • src/adapters/input-media-guard.ts
  • src/adapters/ollama-native.ts
  • src/adapters/openai-chat.ts
  • src/adapters/openai-chat/messages.ts
  • src/adapters/openai-chat/serialized-tool-call-content.ts
  • src/adapters/openai-chat/serialized-tool-call-markup.ts
  • src/adapters/openai-chat/standalone-bare-tool-calls.ts
  • src/adapters/openai-responses/passthrough.ts
  • src/config/provider-validation.ts
  • src/lib/translator-budget.ts
  • src/providers/registry/entries-extended.ts
  • src/responses/audio.ts
  • src/responses/input-media.ts
  • src/responses/parser-content.ts
  • src/responses/schema.ts
  • src/server/responses/deepseek-image-files.ts
  • src/server/responses/input-admission.ts
  • src/server/responses/request-transport.ts
  • src/types.ts
  • src/types/provider.ts
  • src/types/request.ts
  • structure/INDEX.md
  • structure/account-auto-pause.md
  • structure/adapters/registry.md
  • structure/config.md
  • structure/data-planes/images.md
  • structure/data-planes/inbound-compat.md
  • structure/decisions/ADR-7260-standalone-bare-tool-calls.md
  • structure/manifest.json
  • structure/providers-and-adapters.md
  • structure/providers/chat-compat.md
  • structure/providers/google.md
  • structure/providers/mimo-bare-calls.md
  • structure/transports/byte-accounting.md
  • structure/transports/responses.md
  • tests/adapters/adapter-input-media-guard.test.ts
  • tests/adapters/google/gemini-progress-history.test.ts
  • tests/adapters/google/google-adapter.test.ts
  • tests/adapters/google/google-tool-result-adjacency.test.ts
  • tests/adapters/openai/openai-chat-audio.test.ts
  • tests/adapters/openai/openai-chat-model-suffix.test.ts
  • tests/adapters/openai/openai-chat-nonce-tool-call-content.test.ts
  • tests/adapters/openai/openai-chat-serialized-tool-call-scaling.test.ts
  • tests/adapters/openai/openai-chat-standalone-bare-block.test.ts
  • tests/codex-integration/catalog-opencode-go-static.test.ts
  • tests/fixtures/test-layout-expected.json
  • tests/helpers/responses-core-source.ts
  • tests/providers/cursor/cursor-toolresult-normalize.test.ts
  • tests/providers/deepseek-image-files.test.ts
  • tests/providers/model-rename-migration.test.ts
  • tests/providers/ollama/ollama-native.test.ts
  • tests/providers/provider-config-validation.test.ts
  • tests/responses/chat-media-translation.test.ts
  • tests/responses/parser-content-audio.test.ts
  • tests/server/input-admission.test.ts
  • tests/vision/mistral-vision-sidecar.test.ts
+--------------------------------------------------------------------------+
| This function returns three different shapes. It's basically modern art. |
+--------------------------------------------------------------------------+
  \
   \     /)/)
        ( '')
        /  |
      o(___)
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e17eea8590

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// Held markup is released only now, as one batch per response: the doubled-input repair needs every call.
const references = reconcileStructuredToolCalls(calls.map(call => ({ wireName: call.name, restoredName: toolNames.restore(call.name), argumentsText: call.args, freeformTool: freeformTools.get(call.name) })), toolCallContent.current(), !toolCallContent.releasedAnswerText && /(?:^|[/-])mimo-v2(?:\.|$)/i.test(lastRequestedModelId ?? ""));
calls.forEach((call, index) => { call.args = references[index]!.argumentsText; });
yield* toolCallContent.recoverStandalone(calls.length === 0, () => `call_${++toolCallSeq}`, name => toolNames.restore(name));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Require a terminal frame before recovering bare calls

When a MiMo-V2 stream closes after emitting a complete bare block but before finish_reason or [DONE], sawUserFacingOutput is already true, so the generic EOF path calls this function and the unconditional recovery emits an executable tool call. Structured calls in the same EOF path are rejected as possible truncation, but synthetic calls bypass that safeguard and may execute a freeform tool such as exec from an incomplete response; gate standalone recovery on an observed terminal signal or fail this EOF case.

AGENTS.md reference: src/AGENTS.md:L19-L19

Useful? React with 👍 / 👎.

Comment on lines +60 to +61
const parts = item.type === "function_call_output" || item.type === "custom_tool_call_output"
? item.output : item.type === "message" || item.role ? item.content : undefined;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Skip uploads from roles DeepSeek rejects

For an opted-in Responses body over 40 MiB, the item.role truthiness check also selects system and assistant messages, causing their inline images to be uploaded and persisted before inference. DeepSeek explicitly rejects images in those roles, so these requests consume upload bandwidth and storage quota and retain user bytes despite being guaranteed to fail; restrict message uploads to user and developer, while retaining the two supported tool-output types. DeepSeek Responses API restrictions

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants