Skip to content

Enable modern thinking parameters for OpenAI-compatible endpoint from Google #210

@Erudition

Description

@Erudition

I wanted to use gemini-3-flash-preview. Entering the model name manually works during setup, but there's empty replies.

Gemini-generated fix that works for at least getting replies when no thought is required:

   diff --git a/src/llm.rs b/src/llm.rs
   --- a/src/llm.rs
   +++ b/src/llm.rs
   @@ -556,6 +556,12 @@ fn process_openai_stream_event(
            }
        }
    
   +    if let Some(piece) = delta.get("thought").and_then(|t| t.as_str()).or_else(||
   delta.get("thinking").and_then(|t| t.as_str())) {
   +        if !piece.is_empty() {
   +            reasoning_text.push_str(piece);
   +        }
   +    }
   +
        if let Some(piece) = delta.get("reasoning_content").and_then(|t| t.as_str()) {
            if !piece.is_empty() {
                if reasoning_text.is_empty() {
   @@ -815,8 +821,8 @@ impl OpenAiProvider {
        pub fn new(config: &Config) -> Self {
            let is_openai_codex = is_openai_codex_provider(&config.llm_provider);
            let is_deepseek_provider = config.llm_provider.eq_ignore_ascii_case("deepseek");
   -        let enable_reasoning_content_bridge = is_deepseek_provider;
   -        let enable_thinking_param = is_deepseek_provider && config.show_thinking;
   +        let enable_reasoning_content_bridge = is_deepseek_provider ||
   config.llm_provider.eq_ignore_ascii_case("google");
   +        let enable_thinking_param = (is_deepseek_provider || config.llm_provider.eq_ignore_ascii_case("google"))
   && config.show_thinking;
            let configured_base = config.llm_base_url.as_deref().unwrap_or("");
            let base = resolve_openai_compat_base(&config.llm_provider, configured_base);
    
   @@ -869,9 +875,21 @@ impl OpenAiProvider {
    fn maybe_enable_thinking_param(body: &mut serde_json::Value, enabled: bool) {
        if !enabled {
            return;
        }
   +    let is_gemini_3 = body
   +        .get("model")
   +        .and_then(|m| m.as_str())
   +        .map_or(false, |m| m.contains("gemini-3"));
   +
        if let Some(obj) = body.as_object_mut() {
   -        obj.insert("thinking".to_string(), json!({"type": "enabled"}));
   +        if is_gemini_3 {
   +            obj.insert(
   +                "thinking_config".to_string(),
   +                json!({"include_thoughts": true, "max_thought_tokens": 0}),
   +            );
   +        } else {
   +            obj.insert("thinking".to_string(), json!({"type": "enabled"}));
   +        }
        }
    }

  1. Reasoning Bridge: Enabled for the google provider.
  2. Streaming Delta Parsing: Adds thought and thinking fields to process_openai_stream_event.
  3. Thinking Param Logic: Updates maybe_enable_thinking_param to use thinking_config with max_thought_tokens: 0
    for Gemini 3 models.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions