refactor(reasoning): unify reasoning extraction across providers
Reasoning surfacing was split across three branches in runner.py plus two separate streaming buffers (loop hook and runner progress stream), with three independent display-side gates in the CLI. This collapsed the policy into one source of truth and fixed two real bugs: - Structured `reasoning_content` was suppressed whenever the answer was streamed, because the runner gated emission on `streamed_content`. Providers don't stream `reasoning_content`; it only arrives on the final response, so the answer stream and the reasoning channel are independent. Added `streamed_reasoning` to `AgentHookContext` to track the right bit. - `channels.showReasoning` was subordinated to `sendProgress`. They are orthogonal — turning off progress streaming shouldn't silence reasoning. Reworked the CLI gates accordingly. Single-helper consolidation: - `extract_reasoning(reasoning_content, thinking_blocks, content)` returns `(reasoning_text, cleaned_content)` with a defined fallback order: dedicated field → Anthropic thinking_blocks → inline `<think>`/`<thought>` tags. Models that expose none of these short-circuit to `(None, content)` — zero overhead. - `IncrementalThinkExtractor` replaces the ad-hoc `emit_incremental_think` function and its hand-rolled "emitted cursor" state in both the loop hook and the runner progress stream. Also documented the new `showReasoning` channel option in docs/configuration.md and noted its independence from sendProgress. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+12
-12
@@ -275,17 +275,17 @@ async def _maybe_print_interactive_progress(
|
||||
|
||||
is_tool_hint = metadata.get("_tool_hint", False)
|
||||
is_reasoning = metadata.get("_reasoning", False)
|
||||
if is_reasoning:
|
||||
if channels_config and not channels_config.show_reasoning:
|
||||
return True
|
||||
_print_cli_reasoning(msg.content, thinking, renderer)
|
||||
return True
|
||||
if channels_config and is_tool_hint and not channels_config.send_tool_hints:
|
||||
return True
|
||||
if channels_config and not is_tool_hint and not channels_config.send_progress:
|
||||
return True
|
||||
if is_reasoning and channels_config and not channels_config.show_reasoning:
|
||||
return True
|
||||
|
||||
if is_reasoning:
|
||||
_print_cli_reasoning(msg.content, thinking, renderer)
|
||||
else:
|
||||
await _print_interactive_progress_line(msg.content, thinking, renderer)
|
||||
await _print_interactive_progress_line(msg.content, thinking, renderer)
|
||||
return True
|
||||
|
||||
|
||||
@@ -1147,16 +1147,16 @@ def agent(
|
||||
def _make_progress(renderer: StreamRenderer | None = None):
|
||||
async def _cli_progress(content: str, *, tool_hint: bool = False, reasoning: bool = False, **_kwargs: Any) -> None:
|
||||
ch = agent_loop.channels_config
|
||||
if reasoning:
|
||||
if ch and not ch.show_reasoning:
|
||||
return
|
||||
_print_cli_reasoning(content, _thinking, renderer)
|
||||
return
|
||||
if ch and tool_hint and not ch.send_tool_hints:
|
||||
return
|
||||
if ch and not tool_hint and not ch.send_progress:
|
||||
return
|
||||
if reasoning and ch and not ch.show_reasoning:
|
||||
return
|
||||
if reasoning:
|
||||
_print_cli_reasoning(content, _thinking, renderer)
|
||||
else:
|
||||
_print_cli_progress_line(content, _thinking, renderer)
|
||||
_print_cli_progress_line(content, _thinking, renderer)
|
||||
return _cli_progress
|
||||
|
||||
if message:
|
||||
|
||||
Reference in New Issue
Block a user