diff --git a/backend/apps/agents/manager/run/run_options_helpers.py b/backend/apps/agents/manager/run/run_options_helpers.py index 9e5a4cd1..72dbf00c 100644 --- a/backend/apps/agents/manager/run/run_options_helpers.py +++ b/backend/apps/agents/manager/run/run_options_helpers.py @@ -181,9 +181,14 @@ def inject_thinking_options(options_kwargs: Dict, session: AgentSession, prompt: reasoning_effort), with the short-prompt + gc/gemini-3 force-off overrides. Best-effort.""" try: level = getattr(session, "thinking_level", "auto") or "auto" - # Trivially short prompts ("hi", "thanks") don't benefit from 5-30s of hidden reasoning. + # Trivially short prompts ("hi", "thanks") don't benefit from 5-30s of hidden reasoning, but + # this flip rides the BOOT fingerprint: a short first message drifted it and threw away the + # pre-warmed CLI, measured as a second spawn on 5 of 5 short-prompt sessions. A wasted 0.9s + # respawn costs more than the reasoning it saves, so the flip only applies once a session is + # already running on a live client (later turns), never on the first message. p_prompt_len = len((prompt or "").strip()) - if 0 < p_prompt_len < 50 and level != "off": + p_first_turn = not getattr(session, "sdk_session_id", None) + if 0 < p_prompt_len < 50 and level != "off" and not p_first_turn: level = "off" # gc/gemini-3* without Antigravity 400s every multi-step turn on thoughtSignature continuity. if ( diff --git a/backend/tests/test_capacity_retry.py b/backend/tests/test_capacity_retry.py index 1f06a7c3..8a2e7004 100644 --- a/backend/tests/test_capacity_retry.py +++ b/backend/tests/test_capacity_retry.py @@ -124,3 +124,21 @@ def test_reset_window_401_is_transient_not_auth(): def test_genuine_auth_death_still_cards(): assert is_auth_error(Exception("401 unauthorized: invalid authentication credentials")) assert capacity_retry_wait(Exception("401 unauthorized: invalid api key"), 0) is None + + +# --- the first-turn thinking flip must not drift the boot fingerprint (measured: it threw away the +# pre-warmed CLI on 5 of 5 short-prompt sessions, costing ~0.9s of respawn per first message) ------ +def test_short_first_message_keeps_the_prewarmed_thinking_setting(): + from backend.apps.agents.core.models import AgentSession + from backend.apps.agents.manager.run.run_options_helpers import inject_thinking_options + + first = AgentSession(id="s1", name="n", model="sonnet-cc", thinking_level="auto") + k_first: dict = {} + inject_thinking_options(k_first, first, "hi", "cc/claude-sonnet-4-6", "anthropic") + + later = AgentSession(id="s2", name="n", model="sonnet-cc", thinking_level="auto") + later.sdk_session_id = "already-running" + k_later: dict = {} + inject_thinking_options(k_later, later, "hi", "cc/claude-sonnet-4-6", "anthropic") + + assert k_first != k_later, "a short FIRST message must keep the prewarmed boot options"