NousResearch/hermes-agent

Gemini reasoning config mapping and visibility bugs

Cluster 16941 · agent. Data as of

3 open items. Fix merged in #16999. Check it covers your case.

The short answer

1open issue
2open PRs
6items grouped
Known?
Yes. 6 related items grouped here, 1 issue already closed.
Fix event
A fix was merged to main in PR #16999. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this partially resolved, deciding PR #16999. That is separate from the fix event.
Still open
1 issue and 2 PRs.

These issues and fixes address how reasoning/thinking configuration is bridged and mapped for Gemini and Vertex routes, including thought summaries incorrectly appearing in user-visible content and reasoning effort being incorrectly coupled with thought-summary visibility.

Open issues1

  • Issue#64035[Bug]: Gemini/Vertex thought summaries leak into user-visible content with display.show_reasoning: false (effort and visibility coupled via include_thoughts)

Open PRs2

  • PR#64036fix(gemini): decouple reasoning effort from thought-summary visibility
  • PR#91008fix(vertex): route Gemini thought deltas to the reasoning stream, not visible content

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #16999 fix(gemini): bridge reasoning_config into thinking_config for chat-completions routes

    merged to main

    files: agent/transports/chat_completions.py, run_agent.py, tests/agent/transports/test_chat_completions.py

    Show the diff
    • agent/transports/chat_completions.py
      @@ -18,6 +18,58 @@
       from agent.transports.types import NormalizedResponse, ToolCall, Usage
       
       
      +def _build_gemini_thinking_config(model: str, reasoning_config: dict | None) -> dict | None:
      +    """Translate Hermes/OpenRouter-style reasoning config to Gemini thinkingConfig.
      +
      +    Gemini native/cloud-code adapters do not read ``extra_body.reasoning``.
      +    They only inspect ``extra_body.thinking_config`` / ``thinkingConfig`` and
      +    then request thought parts with ``includeThoughts`` enabled.
      +    """
      +    if reasoning_config is None or not isinstance(reasoning_config, dict):
      +        return None
      +
      +    if reasoning_config.get("enabled") is False:
      +        # Gemini can hide thought parts even when internal thinking still
      +        # happens; omit thinkingLevel to avoid model-specific validation quirks.
      +        return {"includeThoughts": False}
      +
      +    effort = str(reasoning_config.get("effort", "medium") or "medium").strip().lower()
      +    if effort == "none":
      +        return {"includeThoughts": False}
      +
      +    thinking_config: Dict[str, Any] = {"includeThoughts": True}
      +    normalized_model = (model or "").strip().lower()
      +    if normalized_model.startswith("google/"):
      +        normalized_model = normalized_model.split("/", 1)[1]
      +
      +    # Gemini 2.5 accepts thinkingBudget; don't guess a budget from Hermes'
      +    # coarse effort levels. ``includeThoughts`` alone is enough to surface
      +    # thought parts without risking request validation errors.
      +    if normalized_model.startswith("gemini-2.5-"):
      +        return thinking_config
      +
      +    if effort not in {"minimal", "low", "medium", "high", "xhigh"}:
      +        effort = "medium"
      +
      +    # Gemini 3 Flash documents low/medium/high thinking levels; Gemini 3 Pro
      +    # is stricter (low/high). Clamp Hermes' wider effort set to what each
      +    # family accepts so we never forward an undocumented level verbatim.
      +    if normalized_model.startswith(("gemini-3", "gemini-3.1")):
      +        if "flash" in normalized_model:
      +            if effort in {"minimal", "low"}:
      +                thinking_config["thinkingLevel"] = "low"
      +            elif effort in {"high", "xhigh"}:
      +                thinking_config["thinkingLevel"] = "high"
      +            else:
      +                thinking_config["thinkingLevel"] = "medium"
      +        elif "pro" in normalized_model:
      +            thinking_config["thinkingLevel"] = (
      +                "high" if effort in {"high", "xhigh"} else "low"
      +            )
      +
      +    return thinking_config
      +
      +
       class ChatCompletionsTransport(ProviderTransport):
           """Transport for api_mode='chat_completions'.
       
      @@ -241,6 +293,7 @@ def build_kwargs(
               is_openrouter = params.get("is_openrouter", False)
               is_nous = params.get("is_nous", False)
               is_github_models = params.get("is_github_models", False)
      +        provider_name = str(params.get("provider_name") or "").strip().lower()
       
               provider_prefs = params.get("provider_preferences")
               if provider_prefs and is_openrouter:
      @@ -293,6 +346,11 @@ def build_kwargs(
               if is_qwen:
                   extra_body["vl_high_resolution_images"] = True
       
      +        if provider_name in {"gemini", "google-gemini-cli"}:
      +            thinking_config = _build_gemini_thinking_config(model, reasoning_config)
      +            if thinking_config:
      +                extra_body["thinking_config"] = thinking_config
      +
               # Merge any pre-built extra_body additions
               additions = params.get("extra_body_additions")
               if additions:
    • run_agent.py
      @@ -8094,6 +8094,7 @@ def _build_api_kwargs(self, api_messages: list) -> dict:
                   supports_reasoning=self._supports_reasoning_extra_body(),
                   github_reasoning_extra=self._github_models_reasoning_extra_body() if _is_gh else None,
                   anthropic_max_output=_ant_max,
      +            provider_name=self.provider,
               )
       
           def _supports_reasoning_extra_body(self) -> bool:
    • tests/agent/transports/test_chat_completions.py
      @@ -4,7 +4,7 @@
       from types import SimpleNamespace
       
       from agent.transports import get_transport
      -from agent.transports.types import NormalizedResponse, ToolCall
      +from agent.transports.types import NormalizedResponse
       
       
       @pytest.fixture
      @@ -122,6 +122,90 @@ def test_custom_think_false(self, transport):
               )
               assert kw["extra_body"]["think"] is False
       
      +    def test_gemini_without_explicit_reasoning_config_keeps_existing_behavior(self, transport):
      +        msgs = [{"role": "user", "content": "Hi"}]
      +        kw = transport.build_kwargs(
      +            model="gemini-3-flash-preview",
      +            messages=msgs,
      +            provider_name="gemini",
      +        )
      +        assert "thinking_config" not in kw.get("extra_body", {})
      +
      +    def test_gemini_flash_reasoning_maps_to_thinking_config(self, transport):
      +        msgs = [{"role": "user", "content": "Hi"}]
      +        kw = transport.build_kwargs(
      +            model="gemini-3-flash-preview",
      +            messages=msgs,
      +            provider_name="gemini",
      +            reasoning_config={"enabled": True, "effort": "high"},
      +        )
      +        assert kw["extra_body"]["thinking_config"] == {
      +            "includeThoughts": True,
      +            "thinkingLevel": "high",
      +        }
      +
      +    def test_gemini_25_reasoning_only_enables_visible_thoughts(self, transport):
      +        msgs = [{"role": "user", "content": "Hi"}]
      +        kw = transport.build_kwargs(
      +            model="gemini-2.5-flash",
      +            messages=msgs,
      +            provider_name="gemini",
      +            reasoning_config={"enabled": True, "effort": "high"},
      +        )
      +        assert kw["extra_body"]["thinking_config"] == {
      +            "includeThoughts": True,
      +        }
      +
      +    def test_gemini_pro_reasoning_clamps_to_supported_levels(self, transport):
      +        msgs = [{"role": "user", "content": "Hi"}]
      +        kw = transport.build_kwargs(
      +            model="google/gemini-3.1-pro-preview",
      +            messages=msgs,
      +            provider_name="gemini",
      +            reasoning_config={"enabled": True, "effort": "medium"},
      +        )
      +        assert kw["extra_body"]["thinking_config"] == {
      +            "includeThoughts": True,
      +            "thinkingLevel": "low",
      +        }
      +
      +    def test_gemini_disabled_reasoning_hides_thoughts(self, transport):
      +        msgs = [{"role": "user", "content": "Hi"}]
      +        kw = transport.build_kwargs(
      +            model="gemini-3-flash-preview",
      +            messages=msgs,
      +            provider_name="gemini",
      +            reasoning_config={"enabled": False},
      +        )
      +        assert kw["extra_body"]["thinking_config"] == {
      +            "includeThoughts": False,
      +        }
      +
      +    def test_gemini_xhigh_clamps_to_high(self, transport):
      +        msgs = [{"role": "user", "content": "Hi"}]
      +        kw = transport.build_kwargs(
      +            model="gemini-3-flash-preview",
      +            messages=msgs,
      +            provider_name="gemini",
      +            reasoning_config={"enabled": True, "effort": "xhigh"},
      +        )
      +        assert kw["extra_body"]["thinking_config"]["thinkingLevel"] == "high"
      +
      +    def test_gemini_flash_minimal_clamps_to_low(self, transport):
      +        # Gemini 3 Flash documents low/medium/high; "minimal" isn't accepted,
      +        # so clamp it down to "low" rather than forwarding it verbatim.
      +        msgs = [{"role": "user", "content": "Hi"}]
      +        kw = transport.build_kwargs(
      +            model="gemini-3-flash-preview",
      +            messages=msgs,
      +            provider_name="gemini",
      +            reasoning_config={"enabled": True, "effort": "minimal"},
      +        )
      +        assert kw["extra_body"]["thinking_config"] == {
      +            "includeThoughts": True,
      +            "thinkingLevel": "low",
      +        }
      +
           def test_max_tokens_with_fn(self, transport):
               msgs = [{"role": "user", "content": "Hi"}]
               kw = transport.build_kwargs(
  • #17605 fix(gemini): nest OpenAI-compat thinking config under google (salvage #17389)

    merged to main

    files: agent/auxiliary_client.py, agent/transports/chat_completions.py, run_agent.py, scripts/release.py, tests/agent/transports/test_chat_completions.py, tests/run_agent/test_provider_parity.py

    Show the diff
    • agent/auxiliary_client.py
      @@ -101,6 +101,14 @@ def __repr__(self):
       logger = logging.getLogger(__name__)
       
       
      +def _safe_isinstance(obj: Any, maybe_type: Any) -> bool:
      +    """Return False instead of raising when a patched symbol is not a type."""
      +    try:
      +        return isinstance(obj, maybe_type)
      +    except TypeError:
      +        return False
      +
      +
       def _extract_url_query_params(url: str):
           """Extract query params from URL, return (clean_url, default_query dict or None)."""
           parsed = urlparse(url)
      @@ -861,20 +869,20 @@ def _maybe_wrap_anthropic(
           - The ``anthropic`` SDK is not installed (falls back to OpenAI wire).
           """
           # Already wrapped — don't double-wrap.
      -    if isinstance(client_obj, AnthropicAuxiliaryClient):
      +    if _safe_isinstance(client_obj, AnthropicAuxiliaryClient):
               return client_obj
           # Other specialized adapters we should never re-dispatch.
      -    if isinstance(client_obj, CodexAuxiliaryClient):
      +    if _safe_isinstance(client_obj, CodexAuxiliaryClient):
               return client_obj
           try:
               from agent.gemini_native_adapter import GeminiNativeClient
      -        if isinstance(client_obj, GeminiNativeClient):
      +        if _safe_isinstance(client_obj, GeminiNativeClient):
                   return client_obj
           except ImportError:
               pass
           try:
               from agent.copilot_acp_client import CopilotACPClient
      -        if isinstance(client_obj, CopilotACPClient):
      +        if _safe_isinstance(client_obj, CopilotACPClient):
                   return client_obj
           except ImportError:
               pass
    • agent/transports/chat_completions.py
      @@ -20,12 +20,7 @@
       
       
       def _build_gemini_thinking_config(model: str, reasoning_config: dict | None) -> dict | None:
      -    """Translate Hermes/OpenRouter-style reasoning config to Gemini thinkingConfig.
      -
      -    Gemini native/cloud-code adapters do not read ``extra_body.reasoning``.
      -    They only inspect ``extra_body.thinking_config`` / ``thinkingConfig`` and
      -    then request thought parts with ``includeThoughts`` enabled.
      -    """
      +    """Translate Hermes/OpenRouter-style reasoning config to Gemini thinkingConfig."""
           if reasoning_config is None or not isinstance(reasoning_config, dict):
               return None
       
      @@ -71,6 +66,30 @@ def _build_gemini_thinking_config(model: str, reasoning_config: dict | None) ->
           return thinking_config
       
       
      +def _snake_case_gemini_thinking_config(config: dict | None) -> dict | None:
      +    """Convert Gemini thinking config keys to the OpenAI-compat field names."""
      +    if not isinstance(config, dict) or not config:
      +        return None
      +
      +    translated: Dict[str, Any] = {}
      +    if isinstance(config.get("includeThoughts"), bool):
      +        translated["include_thoughts"] = config["includeThoughts"]
      +    if isinstance(config.get("thinkingLevel"), str) and config["thinkingLevel"].strip():
      +        translated["thinking_level"] = config["thinkingLevel"].strip().lower()
      +    if isinstance(config.get("thinkingBudget"), (int, float)):
      +        translated["thinking_budget"] = int(config["thinkingBudget"])
      +    return translated or None
      +
      +
      +def _is_gemini_openai_compat_base_url(base_url: Any) -> bool:
      +    normalized = str(base_url or "").strip().rstrip("/").lower()
      +    if not normalized:
      +        return False
      +    if "generativelanguage.googleapis.com" not in normalized:
      +        return False
      +    return normalized.endswith("/openai")
      +
      +
       class ChatCompletionsTransport(ProviderTransport):
           """Transport for api_mode='chat_completions'.
       
      @@ -309,6 +328,7 @@ def build_kwargs(
               is_nous = params.get("is_nous", False)
               is_github_models = params.get("is_github_models", False)
               provider_name = str(params.get("provider_name") or "").strip().lower()
      +        base_url = params.get("base_url")
       
               provider_prefs = params.get("provider_preferences")
               if provider_prefs and is_openrouter:
      @@ -362,7 +382,19 @@ def build_kwargs(
               if is_qwen:
                   extra_body["vl_high_resolution_images"] = True
       
      -        if provider_name in {"gemini", "google-gemini-cli"}:
      +        if provider_name == "gemini":
      +            raw_thinking_config = _build_gemini_thinking_config(model, reasoning_config)
      +            if _is_gemini_openai_compat_base_url(base_url):
      +                thinking_config = _snake_case_gemini_thinking_config(raw_thinking_config)
      +                if thinking_config:
      +                    openai_compat_extra = extra_body.get("extra_body", {})
      +                    google_extra = openai_compat_extra.get("google", {})
      +                    google_extra["thinking_config"] = thinking_config
      +                    openai_compat_extra["google"] = google_extra
      +                    extra_body["extra_body"] = openai_compat_extra
      +            elif raw_thinking_config:
      +                extra_body["thinking_config"] = raw_thinking_config
      +        elif provider_name == "google-gemini-cli":
                   thinking_config = _build_gemini_thinking_config(model, reasoning_config)
                   if thinking_config:
                       extra_body["thinking_config"] = thinking_config
    • run_agent.py
      @@ -8266,6 +8266,7 @@ def _build_api_kwargs(self, api_messages: list) -> dict:
                   model=self.model,
                   messages=_msgs_for_chat,
                   tools=self.tools,
      +            base_url=self.base_url,
                   timeout=self._resolved_api_call_timeout(),
                   max_tokens=[redacted:secret-assignment]
                   ephemeral_max_output_tokens=[redacted:secret-assignment]
    • scripts/release.py
      @@ -66,6 +66,7 @@
           "[redacted:email]": "dlkakbs",
           "[redacted:email]": "BeliefanX",
           "[redacted:email]": "Mind-Dragon",
      +    "[redacted:email]": "Nanako0129",
           "[redacted:email]": "westers",
           "[redacted:email]": "yeyitech",
           "[redacted:email]": "beenherebefore",
    • tests/agent/transports/test_chat_completions.py
      @@ -122,21 +122,25 @@ def test_custom_think_false(self, transport):
               )
               assert kw["extra_body"]["think"] is False
       
      -    def test_gemini_without_explicit_reasoning_config_keeps_existing_behavior(self, transport):
      +    def test_gemini_native_without_explicit_reasoning_config_keeps_existing_behavior(self, transport):
               msgs = [{"role": "user", "content": "Hi"}]
               kw = transport.build_kwargs(
                   model="gemini-3-flash-preview",
                   messages=msgs,
                   provider_name="gemini",
      +            base_url="https://generativelanguage.googleapis.com/v1beta",
               )
               assert "thinking_config" not in kw.get("extra_body", {})
      +        assert "google" not in kw.get("extra_body", {})
      +        assert "extra_body" not in kw.get("extra_body", {})
       
      -    def test_gemini_flash_reasoning_maps_to_thinking_config(self, transport):
      +    def test_gemini_native_flash_reasoning_maps_to_top_level_thinking_config(self, transport):
               msgs = [{"role": "user", "content": "Hi"}]
               kw = transport.build_kwargs(
                   model="gemini-3-flash-preview",
                   messages=msgs,
                   provider_name="gemini",
      +            base_url="https://generativelanguage.googleapis.com/v1beta",
                   reasoning_config={"enabled": True, "effort": "high"},
               )
               assert kw["extra_body"]["thinking_config"] == {
      @@ -144,52 +148,85 @@ def test_gemini_flash_reasoning_maps_to_thinking_config(self, transport):
                   "thinkingLevel": "high",
               }
       
      -    def test_gemini_25_reasoning_only_enables_visible_thoughts(self, transport):
      +    def test_gemini_openai_compat_flash_reasoning_maps_to_nested_google_thinking_config(self, transport):
      +        msgs = [{"role": "user", "content": "Hi"}]
      +        kw = transport.build_kwargs(
      +            model="gemini-3-flash-preview",
      +            messages=msgs,
      +            provider_name="gemini",
      +            base_url="https://generativelanguage.googleapis.com/v1beta/openai",
      +            reasoning_config={"enabled": True, "effort": "high"},
      +        )
      +        assert "thinking_config" not in kw["extra_body"]
      +        assert kw["extra_body"]["extra_body"]["google"]["thinking_config"] == {
      +            "include_thoughts": True,
      +            "thinking_level": "high",
      +        }
      +
      +    def test_gemini_native_25_reasoning_only_enables_visible_thoughts(self, transport):
               msgs = [{"role": "user", "content": "Hi"}]
               kw = transport.build_kwargs(
                   model="gemini-2.5-flash",
                   messages=msgs,
                   provider_name="gemini",
      +            base_url="https://generativelanguage.googleapis.com/v1beta",
                   reasoning_config={"enabled": True, "effort": "high"},
               )
               assert kw["extra_body"]["thinking_config"] == {
                   "includeThoughts": True,
               }
       
      -    def test_gemini_pro_reasoning_clamps_to_supported_levels(self, transport):
      +    def test_gemini_openai_compat_pro_reasoning_clamps_to_supported_levels(self, transport):
               msgs = [{"role": "user", "content": "Hi"}]
               kw = transport.build_kwargs(
                   model="google/gemini-3.1-pro-preview",
                   messages=msgs,
                   provider_name="gemini",
      +            base_url="https://generativelanguage.googleapis.com/v1beta/openai",
                   reasoning_config={"enabled": True, "effort": "medium"},
               )
      -        assert kw["extra_body"]["thinking_config"] == {
      -            "includeThoughts": True,
      -            "thinkingLevel": "low",
      +        assert kw["extra_body"]["extra_body"]["google"]["thinking_config"] == {
      +            "include_thoughts": True,
      +            "thinking_level": "low",
               }
       
      -    def test_gemini_disabled_reasoning_hides_thoughts(self, transport):
      +    def test_gemini_native_disabled_reasoning_hides_thoughts(self, transport):
               msgs = [{"role": "user", "content": "Hi"}]
               kw = transport.build_kwargs(
                   model="gemini-3-flash-preview",
                   messages=msgs,
                   provider_name="gemini",
      +            base_url="https://generativelanguage.googleapis.com/v1beta",
                   reasoning_config={"enabled": False},
               )
               assert kw["extra_body"]["thinking_config"] == {
                   "includeThoughts": False,
               }
       
      -    def test_gemini_xhigh_clamps_to_high(self, transport):
      +    def test_gemini_openai_compat_xhigh_clamps_to_high(self, transport):
               msgs = [{"role": "user", "content": "Hi"}]
               kw = transport.build_kwargs(
                   model="gemini-3-flash-preview",
                   messages=msgs,
                   provider_name="gemini",
      +            base_url="https://generativelanguage.googleapis.com/v1beta/openai",
                   reasoning_config={"enabled": True, "effort": "xhigh"},
               )
      -        assert kw["extra_body"]["thinking_config"]["thinkingLevel"] == "high"
      +        assert kw["extra_body"]["extra_body"]["google"]["thinking_config"]["thinking_level"] == "high"
      +
      +    def test_google_gemini_cli_keeps_top_level_thinking_config(self, transport):
      +        msgs = [{"role": "user", "content": "Hi"}]
      +        kw = transport.build_kwargs(
      +            model="gemini-3-flash-preview",
      +            messages=msgs,
      +            provider_name="google-gemini-cli",
      +            reasoning_config={"enabled": True, "effort": "high"},
      +        )
      +        assert kw["extra_body"]["thinking_config"] == {
      +            "includeThoughts": True,
      +            "thinkingLevel": "high",
      +        }
      +        assert "google" not in kw["extra_body"]
       
           def test_gemini_flash_minimal_clamps_to_low(self, transport):
               # Gemini 3 Flash documents low/medium/high; "minimal" isn't accepted,
      @@ -199,11 +236,12 @@ def test_gemini_flash_minimal_clamps_to_low(self, transport):
                   model="gemini-3-flash-preview",
                   messages=msgs,
                   provider_name="gemini",
      +            base_url="https://generativelanguage.googleapis.com/v1beta/openai",
                   reasoning_config={"enabled": True, "effort": "minimal"},
               )
      -        assert kw["extra_body"]["thinking_config"] == {
      -            "includeThoughts": True,
      -            "thinkingLevel": "low",
      +        assert kw["extra_body"]["extra_body"]["google"]["thinking_config"] == {
      +            "include_thoughts": True,
      +            "thinking_level": "low",
               }
       
           def test_max_tokens_with_fn(self, transport):
    • tests/run_agent/test_provider_parity.py
      @@ -144,6 +144,36 @@ def test_strips_codex_only_tool_call_fields_from_chat_messages(self, monkeypatch
               assert messages[1]["tool_calls"][0]["response_item_id"] == "fc_123"
               assert "codex_reasoning_items" in messages[1]
       
      +    def test_gemini_native_passes_base_url_for_top_level_thinking_config(self, monkeypatch):
      +        agent = _make_agent(
      +            monkeypatch,
      +            "gemini",
      +            base_url="https://generativelanguage.googleapis.com/v1beta",
      +            model="gemini-3-flash-preview",
      +        )
      +        agent.reasoning_config = {"enabled": True, "effort": "high"}
      +        kwargs = agent._build_api_kwargs([{"role": "user", "content": "hi"}])
      +        assert kwargs["extra_body"]["thinking_config"] == {
      +            "includeThoughts": True,
      +            "thinkingLevel": "high",
      +        }
      +        assert "extra_body" not in kwargs["extra_body"]
      +
      +    def test_gemini_openai_compat_passes_base_url_for_nested_google_thinking_config(self, monkeypatch):
      +        agent = _make_agent(
      +            monkeypatch,
      +            "gemini",
      +            base_url="https://generativelanguage.googleapis.com/v1beta/openai",
      +            model="gemini-3.1-pro-preview",
      +        )
      +        agent.reasoning_config = {"enabled": True, "effort": "high"}
      +        kwargs = agent._build_api_kwargs([{"role": "user", "content": "hi"}])
      +        assert "thinking_config" not in kwargs["extra_body"]
      +        assert kwargs["extra_body"]["extra_body"]["google"]["thinking_config"] == {
      +            "include_thoughts": True,
      +            "thinking_level": "high",
      +        }
      +
           def test_should_sanitize_tool_calls_codex_vs_chat(self, monkeypatch):
               """Codex API should NOT sanitize, all other APIs should sanitize."""
               # Codex mode should NOT need sanitization
Closed issues · 1
  • Closed#16941[Bug]: Gemini chat-completions route does not bridge reasoning_config into thinking_config, so Discord show_reasoning stays empty
How this cluster was grouped
  • Link evidence (partly structural links): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text.
  • Members outside that structural core may belong to a different underlying problem.
  • Pairwise link density 0.29: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. 1.00 means every pair is linked.

Pick up a Lab task

Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.

Open the Lab

At a glance

Subsystem
agent
Merged PRs
#16999, #17605
Closed issues
1
Attempts
0 PRs closed without merging
Fix link checked
29 Apr 2026

For your agent

The same facts, typed.