mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-29 09:37:37 +08:00
feat: add MiMo reasoning_content support for Claude Code proxy (#2990)
* feat: add MiMo reasoning_content support for Claude Code proxy MiMo requires reasoning_content to be passed back in multi-turn conversations with tool calls. Add "mimo" and "xiaomimimo" to the preserve_reasoning_content whitelist so thinking blocks are converted to reasoning_content when proxying Claude Code → MiMo. Also handle redacted_thinking blocks (encrypted by Claude Code across turns) by injecting a placeholder to prevent MiMo 400 errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: support MiMo reasoning histories - Fix the PR CI clippy failure for redacted thinking handling. - Preserve MiMo reasoning content on the OpenAI Chat proxy path. - Normalize Claude Desktop Anthropic thinking history for MiMo local routes. - Reject unsupported Claude Desktop direct model remaps. --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Jason <farion1231@gmail.com>
This commit is contained in:
@@ -84,7 +84,11 @@ pub fn claude_api_format_needs_transform(api_format: &str) -> bool {
|
||||
|
||||
fn is_reasoning_content_compatible_identifier(value: &str) -> bool {
|
||||
let value = value.to_ascii_lowercase();
|
||||
value.contains("moonshot") || value.contains("kimi") || value.contains("deepseek")
|
||||
value.contains("moonshot")
|
||||
|| value.contains("kimi")
|
||||
|| value.contains("deepseek")
|
||||
|| value.contains("mimo")
|
||||
|| value.contains("xiaomimimo")
|
||||
}
|
||||
|
||||
fn should_preserve_reasoning_content_for_openai_chat(
|
||||
@@ -1801,4 +1805,39 @@ mod tests {
|
||||
assert_eq!(msg["reasoning_content"], "I should call the tool.");
|
||||
assert!(msg.get("tool_calls").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transform_openai_chat_preserves_reasoning_content_for_mimo_provider() {
|
||||
let provider = create_provider_with_meta(
|
||||
json!({
|
||||
"env": {
|
||||
"ANTHROPIC_BASE_URL": "https://api.xiaomimimo.com/v1",
|
||||
"ANTHROPIC_API_KEY": "test-key"
|
||||
}
|
||||
}),
|
||||
ProviderMeta {
|
||||
api_format: Some("openai_chat".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
let body = json!({
|
||||
"model": "mimo-v2.5-pro",
|
||||
"max_tokens": 64,
|
||||
"messages": [{
|
||||
"role": "assistant",
|
||||
"content": [
|
||||
{"type": "thinking", "thinking": "I should call the tool."},
|
||||
{"type": "tool_use", "id": "call_123", "name": "get_weather", "input": {"location": "Tokyo"}}
|
||||
]
|
||||
}]
|
||||
});
|
||||
|
||||
let transformed =
|
||||
transform_claude_request_for_api_format(body, &provider, "openai_chat", None, None)
|
||||
.unwrap();
|
||||
|
||||
let msg = &transformed["messages"][0];
|
||||
assert_eq!(msg["reasoning_content"], "I should call the tool.");
|
||||
assert!(msg.get("tool_calls").is_some());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,6 +438,14 @@ fn convert_message_to_openai(
|
||||
}
|
||||
}
|
||||
}
|
||||
"redacted_thinking" if preserve_reasoning_content => {
|
||||
// Claude Code encrypts historical thinking into redacted_thinking blocks.
|
||||
// MiMo/DeepSeek require non-empty reasoning_content on assistant tool-call
|
||||
// messages, so inject a minimal placeholder when the real content is
|
||||
// unavailable. Skip when preserve_reasoning_content is off (generic
|
||||
// OpenAI-compatible path).
|
||||
reasoning_parts.push("[redacted thinking]".to_string());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -950,6 +958,26 @@ mod tests {
|
||||
assert_eq!(msg["tool_calls"][0]["id"], "call_123");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_anthropic_to_openai_tool_use_uses_redacted_thinking_placeholder() {
|
||||
let input = json!({
|
||||
"model": "mimo-v2.5-pro",
|
||||
"max_tokens": 1024,
|
||||
"messages": [{
|
||||
"role": "assistant",
|
||||
"content": [
|
||||
{"type": "redacted_thinking", "data": "opaque"},
|
||||
{"type": "tool_use", "id": "call_123", "name": "get_weather", "input": {"location": "Tokyo"}}
|
||||
]
|
||||
}]
|
||||
});
|
||||
|
||||
let result = anthropic_to_openai_with_reasoning_content(input, true).unwrap();
|
||||
let msg = &result["messages"][0];
|
||||
assert_eq!(msg["reasoning_content"], "[redacted thinking]");
|
||||
assert_eq!(msg["tool_calls"][0]["id"], "call_123");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_anthropic_to_openai_does_not_emit_reasoning_content_by_default() {
|
||||
let input = json!({
|
||||
|
||||
Reference in New Issue
Block a user