Skip to content

feat: add MiMo upstream support with Responses/Chat switching#248

Merged
james-6-23 merged 2 commits into
james-6-23:mainfrom
fadten:feat/mimo-upstream-support
Jun 15, 2026
Merged

feat: add MiMo upstream support with Responses/Chat switching#248
james-6-23 merged 2 commits into
james-6-23:mainfrom
fadten:feat/mimo-upstream-support

Conversation

@fadten

@fadten fadten commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Add MiMo upstream integration supporting both Responses API and Chat Completions API, with automatic client type detection and format translation.

Features

  • MiMo upstream executor (Responses + Chat Completions endpoints)
  • MiMo format translator (OpenAI Responses <-> MiMo wire format)
  • MiMo provider detection (API key pattern, base_url, upstream_type)
  • Account-level model mapping for MiMo accounts
  • Automatic client type switching (Responses API vs Chat Completions)

Fixes found during integration

  • Fix gjson.Result.Get() returning 0 after json.Unmarshal
  • Fix int64 type assertion in convertUsageToResponsesFormat
  • Support prompt_tokens/input_tokens and completion_tokens/output_tokens formats
  • Extract cached_tokens and reasoning_tokens in MiMo usage path
  • Add User-Agent to all upstream requests
  • Pass ReasoningTokens to logUsageForRequest in MiMo path

Files changed

  • proxy/mimo_executor.go (new) - MiMo upstream request executor
  • proxy/mimo_translator.go (new) - MiMo format translation layer
  • proxy/executor.go - User-Agent header for all upstream requests
  • proxy/handler.go - MiMo routing, account-level mapping, usage tracking

Summary by CodeRabbit

  • New Features
    • Added MiMo upstream routing with per-account model mapping and configurable upstream settings
    • Automatically inject web search results for Token Plan accounts
    • Translated MiMo Chat Completions to Responses, including full streaming event support
    • Improved tool/function calling support across routed backends
  • Bug Fixes
    • Improved request-body handling for Responses, Responses Compact, and Chat Completions
    • Refreshed Codex usage snapshot handling to ensure correct 5h reset tracking

@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds complete MiMo upstream provider support to the proxy. The feature implements bidirectional protocol translation between OpenAI Responses/Chat Completions APIs and MiMo's chat protocol, including request routing, streaming response handling, per-account model mapping, and auto web search integration for Token Plan accounts.

Changes

MiMo Upstream Integration

Layer / File(s) Summary
MiMo data models and upstream configuration
proxy/mimo_translator.go, proxy/mimo_executor.go
MiMo request/response data structures (MimoChatRequest, MimoChatMessage, MimoChatTool); MimoUpstreamConfig with base URL, API key, token-plan flag, and serialized per-account model mapping; cryptographic response ID generation with fallback.
Responses to MiMo translation
proxy/mimo_translator.go
ResponsesToMimoChat converts Responses instructions→system message and inputs→chat messages with role/content normalization; translates tools (function, shell, gated web_search, tool_search, namespace, custom) and deduplicates; normalizes tool_choice, parallel_tool_calls, temperature, reasoning.effort; injects MiMo thinking defaults; performs Token Plan auto web search with result injection and web_search tool removal.
Chat Completions to MiMo translation
proxy/mimo_translator.go
TranslateChatCompletionsToMimo normalizes model, injects/enforces thinking when absent, removes temperature when thinking enabled, injects stream_options.include_usage=true for streaming, performs optional Token Plan auto web search by extracting user query, calling PerformSearch, injecting formatted results into system message, and removing web_search tools.
MiMo response to Responses conversion
proxy/mimo_translator.go
ChatChunkToResponsesEvent and translateChatCompletion convert MiMo streaming chunks and non-streamed completions into Responses SSE events with reasoning/text/tool-call deltas and usage; SSE serialization helpers emit response.created, reasoning/text/tool-call events, and response.completed with token accounting.
MiMo request execution and streaming
proxy/mimo_executor.go
HandleMimoResponsesAPI and HandleMimoChatCompletionsAPI translate inbound requests, apply per-account model mapping, POST to MiMo /v1/chat/completions, rewrite "webSearchEnabled is false" 400 errors; handleMimoStreamResponse handles Responses streaming with buffering and incremental translation; handleMimoNonStreamResponse translates full-body responses; handleMimoPassthroughStream forwards Chat Completions SSE directly.
MiMo upstream routing and dispatch
proxy/mimo_executor.go
HandleMimoUpstream routes by path (Responses vs Chat Completions); DetermineUpstreamType uses account upstream type if set, else routes by IsMimoModel(model) and defaults to Codex; HandleUpstreamRequest dispatches to MiMo or returns unsupported upstream error.
Handler integration and request body refactoring
proxy/handler.go
Adds os import for environment variables; introduces marshalModelMapping for per-account model mapping serialization; updates accountFilterForResponsesModel to allow MiMo accounts with rate-limit checks; removes readRawRequestBody and setRawRequestBody helpers; refactors Responses/ResponsesCompact/ChatCompletions to read request bodies with io.ReadAll and set mapped raw_body in gin context; injects early MiMo routing in Responses and ChatCompletions using account-level config or MIMO_API_KEY/MIMO_BASE_URL environment variables; updates Codex 5h usage snapshot call from SetUsageSnapshot5hAt(..., now) to SetUsageSnapshot5h(usedPct, resetAt).

Sequence Diagram

sequenceDiagram
  participant Client
  participant Handler as Responses/Chat Handler
  participant Router as MiMo Router
  participant Executor as MiMo Executor
  participant Upstream as MiMo /v1/chat/completions
  participant Translator as Response Translator
  
  Client->>Handler: Responses/Chat Completions request
  Handler->>Handler: io.ReadAll body, apply model mapping
  Handler->>Router: Check if MiMo account or MiMo model
  alt MiMo Route Detected
    Router->>Executor: Request body + MimoUpstreamConfig
    Executor->>Translator: Convert to MiMo format
    Translator->>Upstream: POST /v1/chat/completions
    Upstream->>Translator: Streaming or full response
    Translator->>Executor: Responses SSE events
    Executor->>Client: response.created / deltas / response.completed
  else Legacy Route
    Router->>Handler: Continue Codex flow
    Handler->>Client: Codex response
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

Poem

🐰 A rabbit hops through MiMo's door,
Translating chat like never before,
With streaming chunks and models mapped,
Responses flow—no tokens trapped!
Web searches glow, thinking takes flight,
Upstream bridged in quantum delight. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately describes the main change: adding MiMo upstream support with automatic API type switching between Responses and Chat Completions formats.
Docstring Coverage ✅ Passed Docstring coverage is 88.14% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

🧹 Nitpick comments (1)
proxy/mimo_executor.go (1)

353-363: 💤 Low value

Consider passing the actual model name.

The model field is hardcoded as "mimo" but the actual model name is available in the calling context. Clients may benefit from seeing the specific model (e.g., mimo-v2.5-pro).

♻️ Proposed refactor
-func buildResponsesCreatedEvent(responseID string) string {
+func buildResponsesCreatedEvent(responseID, model string) string {
 	resp := map[string]any{
 		"id":         responseID,
 		"object":     "response",
 		"status":     "in_progress",
-		"model":      "mimo",
+		"model":      model,
 		"output":     []any{},
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@proxy/mimo_executor.go` around lines 353 - 363, The
buildResponsesCreatedEvent function currently hardcodes "model":"mimo"; change
its signature to accept a model string (e.g., func
buildResponsesCreatedEvent(responseID, model string) string), set the "model"
field to that parameter when building resp, and update every call site to pass
the actual model name from the caller (so callers supply values like
"mimo-v2.5-pro"); no other behavior changes required.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@proxy/handler.go`:
- Around line 1505-1533: At both locations (proxy/handler.go:1505-1533 and
proxy/handler.go:2852-2878) the MiMo routing paths return early after acquiring
an account and so leak the account lease; before calling HandleMimoResponsesAPI
(first site) and HandleMimoChatCompletionsAPI (second site) release the acquired
account using the same release call used elsewhere in this file (i.e., invoke
the pool/account release helper just prior to the early return), and rename the
local shadowed apiKey variable to mimoAPIKey to avoid shadowing the outer
account.APIKey; the first site (1505-1533) requires inserting the release call
then calling HandleMimoResponsesAPI with mimoCfg and returning, and the second
site (2852-2878) requires the same change before calling
HandleMimoChatCompletionsAPI.

In `@proxy/mimo_executor.go`:
- Around line 265-280: translateChatStreamChunk already emits a
response.completed event for finish_reason "stop" or "tool_calls", so the
unconditional send of buildResponsesCompletedEvent(responseID) in the
currentData flush path can cause duplicate completion events; add a completion
flag (e.g., responseCompleted bool) in the mimo_executor.go handler scope or on
the connection context, set it to true whenever translateChatStreamChunk or
ChatChunkToResponsesEvent produces a response.completed event, and before
calling fmt.Fprintf(c.Writer, "%s\n\n",
buildResponsesCompletedEvent(responseID)) check that flag and only emit the
completed event if responseCompleted is false (no other change to event
formatting); ensure the flag is updated wherever
translateChatStreamChunk/ChatChunkToResponsesEvent emits completion so
duplicates are suppressed.
- Around line 30-35: The GenerateMimoResponseID function currently ignores
errors from rand.Read; update GenerateMimoResponseID to check the returned n and
err from rand.Read(b) and handle failures — if err == nil ensure n == len(b) and
then return "resp_mimo_"+hex.EncodeToString(b); if rand.Read returns an error,
fall back to a safe alternative (for example, generate a unique ID using a
timestamp + crypto/sha256 or seed math/rand with time.Now().UnixNano() and
produce hex bytes) or return an error upstream (change signature to (string,
error)) — choose one consistent approach and implement the error-path code,
keeping the function name GenerateMimoResponseID and ensuring the fallback
produces reasonably unique IDs.

In `@proxy/mimo_translator.go`:
- Around line 869-905: injectSearchResultsToChatBody currently only detects
existence of a system message but always appends to messages.0, corrupting the
wrong item; update the function to record the actual index of the system message
during the messages.ForEach loop (e.g., store an int sysIdx initialized to -1
and set it when msg.Get("role").String() == "system"), then when sysIdx >= 0
append searchResults to "messages.<sysIdx>.content" using sjson.SetBytes; keep
the existing insertion branch unchanged for the case where no system message
exists.

---

Nitpick comments:
In `@proxy/mimo_executor.go`:
- Around line 353-363: The buildResponsesCreatedEvent function currently
hardcodes "model":"mimo"; change its signature to accept a model string (e.g.,
func buildResponsesCreatedEvent(responseID, model string) string), set the
"model" field to that parameter when building resp, and update every call site
to pass the actual model name from the caller (so callers supply values like
"mimo-v2.5-pro"); no other behavior changes required.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 99795126-43dc-4be8-bbc0-389091157db2

📥 Commits

Reviewing files that changed from the base of the PR and between 8b8dc52 and 4e10bb4.

📒 Files selected for processing (3)
  • proxy/handler.go
  • proxy/mimo_executor.go
  • proxy/mimo_translator.go

Comment thread proxy/handler.go
Comment on lines +1505 to +1533
// ============================================================
// MiMo 上游路由
// ============================================================
// 方式1: 账号级别配置(推荐)- 支持 base_url 自动检测
if IsMimoAccount(account.UpstreamType, account.BaseURL, account.APIKey) {
mimoCfg := &MimoUpstreamConfig{
BaseURL: account.BaseURL,
APIKey: account.APIKey,
IsTokenPlan: IsMimoTokenPlanKey(account.APIKey),
ModelMapping: marshalModelMapping(account.ModelMapping),
}
HandleMimoResponsesAPI(c, rawBody, mimoCfg)
return
}

// 方式2: 根据模型名称自动检测 + 全局环境变量
if IsMimoModel(model) {
apiKey := os.Getenv("MIMO_API_KEY")
if apiKey != "" {
mimoCfg := &MimoUpstreamConfig{
BaseURL: os.Getenv("MIMO_BASE_URL"),
APIKey: apiKey,
IsTokenPlan: IsMimoTokenPlanKey(apiKey),
}
HandleMimoResponsesAPI(c, rawBody, mimoCfg)
return
}
}
// ============================================================

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Account resource leak in MiMo routing paths across both handlers. Both Responses and ChatCompletions handlers have MiMo routing blocks placed inside their retry loops after acquiring an account from the pool. When routing to MiMo upstream, the handlers return early without releasing the acquired account, causing pool lease leaks.

  • proxy/handler.go#L1505-L1533: Release account before calling HandleMimoResponsesAPI in both the account-level and environment variable routing paths; rename shadowed apiKey to mimoAPIKey.
  • proxy/handler.go#L2852-L2878: Apply the same fix before calling HandleMimoChatCompletionsAPI; rename shadowed apiKey to mimoAPIKey.
📍 Affects 1 file
  • proxy/handler.go#L1505-L1533 (this comment)
  • proxy/handler.go#L2852-L2878
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@proxy/handler.go` around lines 1505 - 1533, At both locations
(proxy/handler.go:1505-1533 and proxy/handler.go:2852-2878) the MiMo routing
paths return early after acquiring an account and so leak the account lease;
before calling HandleMimoResponsesAPI (first site) and
HandleMimoChatCompletionsAPI (second site) release the acquired account using
the same release call used elsewhere in this file (i.e., invoke the pool/account
release helper just prior to the early return), and rename the local shadowed
apiKey variable to mimoAPIKey to avoid shadowing the outer account.APIKey; the
first site (1505-1533) requires inserting the release call then calling
HandleMimoResponsesAPI with mimoCfg and returning, and the second site
(2852-2878) requires the same change before calling
HandleMimoChatCompletionsAPI.

Comment thread proxy/mimo_executor.go
Comment thread proxy/mimo_executor.go
Comment thread proxy/mimo_translator.go
@james-6-23

Copy link
Copy Markdown
Owner

感谢 PR!在最新 main 上 rebase 后本地编译,发现这个 PR 缺少了一批被引用但未提交的源码,导致 go build ./proxy/ 失败(CI 的 backend-security/govulncheck 也因此挂掉)。看起来是有几个文件没有 push 上来。

完整的未定义符号清单(已去重,rebase 到最新 main 后):

A. MiMo 配置/判别函数(疑似缺少一个 mimo_config.go 之类的文件)

  • IsMimoAccount(upstreamType, baseURL, apiKey)handler.go:241,1509,2947
  • IsMimoModel(model)handler.go:1521,2958mimo_executor.go:442
  • IsMimoTokenPlanKey(apiKey)handler.go:1513,1527,2951,2964
  • ResolveMimoBaseURL(baseURL, apiKey)mimo_executor.go:64,148
  • NormalizeMimoModelID(model)mimo_translator.go:92,785
  • MimoModelSupportsImages(model)mimo_translator.go:223
  • UpstreamTypeMimo(常量)— mimo_executor.go:443,453
  • MimoDefaultModel(常量)— mimo_translator.go:94,787
  • MimoThinkingDefaultDisabled(map)— mimo_translator.go:537,801
  • MimoThinkingFixesTemperature(map)— mimo_translator.go:186,806

B. 联网搜索相关(疑似缺少一个 mimo_search.go 之类的文件)

  • IsSearchEnabled()
  • ExtractSearchQuery(messages)
  • GetSearchProvider()
  • PerformSearch(query, n)
  • FormatSearchResultsForPrompt(results)
  • InjectSearchResults(messages, text)
  • RemoveWebSearchTool(tools)

(均位于 mimo_translator.go:131-149, 832-856

C. auth.Account 缺少 ModelMapping 字段

  • handler.go:1514,2952 使用了 account.ModelMapping,但 auth/store.goAccount 结构里没有这个字段。需要给 Account 加上 ModelMapping(看用法应为 map[string]string)并补上从 DB 凭据加载的逻辑。

麻烦把上面缺失的文件 / 字段补 push 上来~ 另外建议本地先跑一遍 go build ./... && go test ./... 确认通过。mimo_translator.go(924 行)和 mimo_executor.go(461 行)目前也没有配套测试,如果方便的话补一些单测会更有信心合入。

我们这边帮你确认:当前分支已能干净 rebase 到最新 main,只要补齐上述符号即可编译通过。

Based on v2.3.2, fix 3 issues found in CodeRabbit review:

1. injectSearchResultsToChatBody index bug (mimo_translator.go)
   - Issue: Hardcoded messages.0 assumes system message is always first
   - Fix: Dynamically find system message actual index

2. GenerateMimoResponseID error handling (mimo_executor.go)
   - Issue: Ignored rand.Read error return value
   - Fix: Add error check, use timestamp as fallback

3. buildResponsesCreatedEvent model hardcoded (mimo_executor.go)
   - Issue: Model name fixed as 'mimo'
   - Fix: Pass model name as parameter

Backward compatible, no API changes.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
proxy/mimo_translator.go (2)

1400-1404: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Missing isTokenPlan parameter in TranslateChatCompletionsToMimo causes inconsistent auto-search behavior.

TranslateChatCompletionsToMimo doesn't receive an isTokenPlan parameter, unlike ResponsesToMimoChat which uses it to gate auto-search (line 181). The comment at line 1452 states "Token Plan 账号 + 搜索已启用 = 自动搜索注入" but the condition at line 1453 only checks hasWebSearch && IsSearchEnabled(). This causes Chat Completions requests to trigger auto-search for all accounts, not just Token Plan accounts.

  • proxy/mimo_translator.go#L1400-L1404: Add isTokenPlan bool parameter to the function signature and include it in the condition at line 1453: if hasWebSearch && isTokenPlan && IsSearchEnabled().
  • proxy/mimo_executor.go#L147-L147: Update call site to pass cfg.IsTokenPlan as the second argument.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@proxy/mimo_translator.go` around lines 1400 - 1404, The
TranslateChatCompletionsToMimo function in proxy/mimo_translator.go at lines
1400-1404 lacks an isTokenPlan boolean parameter, causing inconsistent
auto-search behavior across different account types. Add the isTokenPlan bool
parameter to the TranslateChatCompletionsToMimo function signature, then locate
the auto-search condition at line 1453 and update it to check hasWebSearch AND
isTokenPlan AND IsSearchEnabled() instead of only checking hasWebSearch and
IsSearchEnabled(). Additionally, update the function call site in
proxy/mimo_executor.go at line 147 to pass cfg.IsTokenPlan as the second
argument when calling TranslateChatCompletionsToMimo.

1452-1453: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Inconsistent Token Plan check for auto search.

ResponsesToMimoChat (line 181) checks hasWebSearch && isTokenPlan && IsSearchEnabled() before triggering auto search, but TranslateChatCompletionsToMimo only checks hasWebSearch && IsSearchEnabled() despite the comment on line 1452 stating "Token Plan 账号 + 搜索已启用 = 自动搜索注入".

This inconsistency means Chat Completions requests will trigger auto search for all accounts with web_search tools, not just Token Plan accounts.

🐛 Proposed fix to add isTokenPlan parameter
-func TranslateChatCompletionsToMimo(chatBody []byte) ([]byte, string, error) {
+func TranslateChatCompletionsToMimo(chatBody []byte, isTokenPlan bool) ([]byte, string, error) {
 	// ... existing code ...
 
 	// Token Plan 账号 + 搜索已启用 = 自动搜索注入
-	if hasWebSearch && IsSearchEnabled() {
+	if hasWebSearch && isTokenPlan && IsSearchEnabled() {

Also update the call site in HandleMimoChatCompletionsAPI to pass cfg.IsTokenPlan.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@proxy/mimo_translator.go` around lines 1452 - 1453, The
`TranslateChatCompletionsToMimo` function at line 1452-1453 is missing the
`isTokenPlan` check in its auto search condition, causing inconsistency with the
`ResponsesToMimoChat` function which correctly checks `hasWebSearch &&
isTokenPlan && IsSearchEnabled()`. Update the condition in
`TranslateChatCompletionsToMimo` to include the `isTokenPlan` parameter check
alongside `hasWebSearch && IsSearchEnabled()` to match the logic in
`ResponsesToMimoChat`. Additionally, modify the call site in
`HandleMimoChatCompletionsAPI` to pass the `isTokenPlan` parameter (likely from
`cfg.IsTokenPlan`) when invoking `TranslateChatCompletionsToMimo` so that the
function has access to the required value.
🧹 Nitpick comments (2)
proxy/mimo_executor.go (2)

586-589: 💤 Low value

Inconsistent logging: uses log.Printf while rest of file uses slog.

Lines 586 and 588 use log.Printf while the rest of the file consistently uses structured logging via slog. Consider using slog.Info or slog.Debug for consistency.

♻️ Suggested change
-		log.Printf("[MIMO-USAGE] input=%d, output=%d, total=%d, cached=%d, reasoning=%d", usageResult.InputTokens, usageResult.OutputTokens, usageResult.TotalTokens, usageResult.CachedTokens, usageResult.ReasoningTokens)
+		slog.Debug("mimo usage",
+			"input", usageResult.InputTokens,
+			"output", usageResult.OutputTokens,
+			"total", usageResult.TotalTokens,
+			"cached", usageResult.CachedTokens,
+			"reasoning", usageResult.ReasoningTokens)
 	} else {
-		log.Printf("[MIMO-USAGE] lastUsageData is EMPTY")
+		slog.Debug("mimo usage: lastUsageData is empty")
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@proxy/mimo_executor.go` around lines 586 - 589, Replace the two log.Printf
calls in the MIMO-USAGE logging block (the one logging usageResult.InputTokens,
usageResult.OutputTokens, etc., and the one logging "lastUsageData is EMPTY")
with slog.Info or slog.Debug calls to maintain consistency with the structured
logging approach used throughout the rest of the file. Convert the format string
parameters into structured key-value pairs that slog expects, preserving all the
logged information.

689-757: 💤 Low value

Code duplication with buildResponsesCompletedEventWithData in mimo_translator.go.

buildResponsesCompletedEventWithDataWithSeq duplicates most of the logic from buildResponsesCompletedEventWithData (lines 1137-1205 in mimo_translator.go), only adding a sequence_number field. Consider refactoring to share the common logic.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@proxy/mimo_executor.go` around lines 689 - 757, The function
buildResponsesCompletedEventWithDataWithSeq duplicates the logic of
buildResponsesCompletedEventWithData (which exists in mimo_translator.go) with
the only difference being the addition of a sequence_number field. Refactor by
modifying buildResponsesCompletedEventWithData to accept an optional sequence
number parameter, then have buildResponsesCompletedEventWithDataWithSeq call
this refactored function with the sequence number provided. This way you avoid
duplicating the entire response and event construction logic, and the
sequence_number field is only added to the event map when a non-zero or non-nil
sequence value is passed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@proxy/mimo_executor.go`:
- Around line 565-568: The json.Unmarshal function cannot populate a
gjson.Result type as gjson.Result is not a standard JSON unmarshaler type.
Replace the json.Unmarshal(usageBytes, &usageJSON) call with
gjson.ParseBytes(usageBytes) which is the correct gjson library function to
parse bytes into a gjson.Result, assigning the return value directly to the
usageJSON variable. This will ensure buildResponsesUsageEvent receives a
properly populated gjson.Result instead of an empty/zero state.

---

Outside diff comments:
In `@proxy/mimo_translator.go`:
- Around line 1400-1404: The TranslateChatCompletionsToMimo function in
proxy/mimo_translator.go at lines 1400-1404 lacks an isTokenPlan boolean
parameter, causing inconsistent auto-search behavior across different account
types. Add the isTokenPlan bool parameter to the TranslateChatCompletionsToMimo
function signature, then locate the auto-search condition at line 1453 and
update it to check hasWebSearch AND isTokenPlan AND IsSearchEnabled() instead of
only checking hasWebSearch and IsSearchEnabled(). Additionally, update the
function call site in proxy/mimo_executor.go at line 147 to pass cfg.IsTokenPlan
as the second argument when calling TranslateChatCompletionsToMimo.
- Around line 1452-1453: The `TranslateChatCompletionsToMimo` function at line
1452-1453 is missing the `isTokenPlan` check in its auto search condition,
causing inconsistency with the `ResponsesToMimoChat` function which correctly
checks `hasWebSearch && isTokenPlan && IsSearchEnabled()`. Update the condition
in `TranslateChatCompletionsToMimo` to include the `isTokenPlan` parameter check
alongside `hasWebSearch && IsSearchEnabled()` to match the logic in
`ResponsesToMimoChat`. Additionally, modify the call site in
`HandleMimoChatCompletionsAPI` to pass the `isTokenPlan` parameter (likely from
`cfg.IsTokenPlan`) when invoking `TranslateChatCompletionsToMimo` so that the
function has access to the required value.

---

Nitpick comments:
In `@proxy/mimo_executor.go`:
- Around line 586-589: Replace the two log.Printf calls in the MIMO-USAGE
logging block (the one logging usageResult.InputTokens,
usageResult.OutputTokens, etc., and the one logging "lastUsageData is EMPTY")
with slog.Info or slog.Debug calls to maintain consistency with the structured
logging approach used throughout the rest of the file. Convert the format string
parameters into structured key-value pairs that slog expects, preserving all the
logged information.
- Around line 689-757: The function buildResponsesCompletedEventWithDataWithSeq
duplicates the logic of buildResponsesCompletedEventWithData (which exists in
mimo_translator.go) with the only difference being the addition of a
sequence_number field. Refactor by modifying
buildResponsesCompletedEventWithData to accept an optional sequence number
parameter, then have buildResponsesCompletedEventWithDataWithSeq call this
refactored function with the sequence number provided. This way you avoid
duplicating the entire response and event construction logic, and the
sequence_number field is only added to the event map when a non-zero or non-nil
sequence value is passed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1a12a4d3-ba20-4696-a8ed-c2e6cf1f22b9

📥 Commits

Reviewing files that changed from the base of the PR and between 4e10bb4 and a3a53db.

📒 Files selected for processing (2)
  • proxy/mimo_executor.go
  • proxy/mimo_translator.go

Comment thread proxy/mimo_executor.go
Comment on lines +565 to +568
var usageJSON gjson.Result
json.Unmarshal(usageBytes, &usageJSON)
seq = state.NextSeq()
emit(buildResponsesUsageEvent(usageJSON, responseID, seq))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Bug: json.Unmarshal into gjson.Result doesn't work.

gjson.Result is a struct used by the gjson library for query results, not a type that json.Unmarshal can populate. The unmarshal will effectively leave usageJSON in an empty/zero state, causing buildResponsesUsageEvent to receive an invalid result.

🐛 Proposed fix
 	// usage 事件
 	if lastUsageData != "" {
-		usageBytes := []byte(lastUsageData)
-		var usageJSON gjson.Result
-		json.Unmarshal(usageBytes, &usageJSON)
+		usageJSON := gjson.Parse(lastUsageData)
 		seq = state.NextSeq()
 		emit(buildResponsesUsageEvent(usageJSON, responseID, seq))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
var usageJSON gjson.Result
json.Unmarshal(usageBytes, &usageJSON)
seq = state.NextSeq()
emit(buildResponsesUsageEvent(usageJSON, responseID, seq))
usageJSON := gjson.Parse(lastUsageData)
seq = state.NextSeq()
emit(buildResponsesUsageEvent(usageJSON, responseID, seq))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@proxy/mimo_executor.go` around lines 565 - 568, The json.Unmarshal function
cannot populate a gjson.Result type as gjson.Result is not a standard JSON
unmarshaler type. Replace the json.Unmarshal(usageBytes, &usageJSON) call with
gjson.ParseBytes(usageBytes) which is the correct gjson library function to
parse bytes into a gjson.Result, assigning the return value directly to the
usageJSON variable. This will ensure buildResponsesUsageEvent receives a
properly populated gjson.Result instead of an empty/zero state.

@james-6-23 james-6-23 merged commit 0bc3119 into james-6-23:main Jun 15, 2026
3 of 6 checks passed
james-6-23 added a commit that referenced this pull request Jun 15, 2026
@james-6-23

Copy link
Copy Markdown
Owner

⚠️ 该 PR 已被回滚(main 编译失败)

合并后发现 main 分支无法编译,CI 三项检查(test / golangci-lint / backend-security)全部失败。原因是本 PR 漏提交了大量被引用的符号定义——mimo_executor.gomimo_translator.go 引用了一批函数/常量/类型,但它们的定义文件没有包含在 PR 中。

为恢复主分支可编译状态,已通过 git revert -m 1 回滚合并提交(revert commit: 50bd7aa)。

缺失的符号清单(共 ~17 个 + 1 个结构体字段)

配置 / 常量 / helper(疑似漏交 mimo_config.go 之类的文件):

  • UpstreamTypeMimo
  • MimoDefaultModel
  • ResolveMimoBaseURL
  • NormalizeMimoModelID
  • IsMimoModel
  • IsMimoAccount
  • IsMimoTokenPlanKey
  • MimoModelSupportsImages
  • MimoThinkingDefaultDisabled
  • MimoThinkingFixesTemperature

整个搜索子系统(疑似漏交 mimo_search.go 之类的文件):

  • IsSearchEnabled
  • PerformSearch
  • ExtractSearchQuery
  • GetSearchProvider
  • FormatSearchResultsForPrompt
  • InjectSearchResults
  • RemoveWebSearchTool

auth 包改动缺失:

  • auth.Account 结构体缺少 ModelMapping 字段(handler.goaccount.ModelMapping 引用失败)

麻烦你

  1. 补提交上述缺失的文件 / 字段;
  2. 本地确认 go build ./...go test ./... 均通过;
  3. 确认 CI 全绿后我们再重新合并。

复现:git build ./proxy/ 会报 undefined: IsMimoAccount 等错误。

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants