feat(agents,backends,conversations,frontends,ui): progress thinking is told apart by its agent, raycast reasoning stays collapsed, read_conversation keeps progress

This commit is contained in:
hh committed 2026-09-22 20:51:23 +02:00
1 parent 13873f857b
commit 120985deab
18 files changed
+374 -110

No files matched your search

@@ -1,7 +1,7 @@
"""Render Anthropic ``Message`` (and user turns) into markdown.
One-way: produces the human-facing artifact only. The parser strips
the tool/thinking callouts of older files when reshaping history for replay.
tool/thinking callouts separately when reshaping history for backend replay.
"""
from __future__ import annotations
@@ -43,17 +43,25 @@ def render_assistant_text(text: str) -> str:
return f"### Assistant:\n\n{text.strip()}\n"
def render_assistant_message(message: Message) -> str:
def render_assistant_message(message: Message, *, thinking_is_progress: bool) -> str:
"""Render an assistant ``Message`` into a turn block.
Tool-use blocks and empty thinking render to nothing; a non-empty thinking
block is what the model wrote between tool calls and renders as text.
Tool-use blocks render to nothing. Progress thinking renders as text in
place and vanishes when empty; reasoning renders as a collapsed callout,
of which only the first between two texts reaches the file.
"""
parts: list[str] = ["### Assistant:", ""]
after_reasoning = False
for block in message.content:
if isinstance(block, ThinkingBlock) and not thinking_is_progress:
if not after_reasoning:
parts.extend((*_render_reasoning(block.thinking or ""), ""))
after_reasoning = True
continue
text = _spoken(block)
if text:
parts.extend((text, ""))
after_reasoning = False
return "\n".join(parts).rstrip() + "\n"
@@ -99,6 +107,11 @@ def summarize_tool_input(name: str, tool_input: object) -> str:
return name
def _render_reasoning(text: str) -> tuple[str, ...]:
lines = text.strip().splitlines() or [""]
return ("> [!thinking]-", *(f"> {line}" if line else ">" for line in lines))
def _spoken(block: object) -> str:
if isinstance(block, TextBlock):
return (block.text or "").strip()