feat(conversations,api,ui): rewind takes the last turns of a thread back, the cut session stays in the store

This commit is contained in:
hh committed 2026-10-13 02:10:03 +02:00
1 parent b0e5aaf599
commit 2a47c6771d
14 files changed
+583 -9

No files matched your search

+30 -1
View File
@@ -20,13 +20,14 @@ except ImportError: # pragma: no cover
_cli_version = "2.1.248"
if TYPE_CHECKING:
from collections.abc import Iterable
from collections.abc import Iterable, Sequence
__all__ = [
"CLI_VERSION",
"build_entries",
"close_open_tool_uses",
"fingerprint",
"last_message_before",
"messages_from_entries",
"open_tool_uses",
"prompt_count",
@@ -35,6 +36,7 @@ __all__ = [
"spoken_text",
"strip_tool_entries",
"text_of",
"turn_starts",
"window_entries",
]
@@ -438,6 +440,33 @@ def prompt_count(entries: Iterable[Mapping[str, Any]]) -> int:
return sum(1 for e in entries if _is_prompt_entry(e))
def turn_starts(entries: Iterable[Mapping[str, Any]]) -> list[int]:
"""Where each turn opens: the index of every prompt the SDK was handed.
The CLI stamps only those with ``promptSource``; what it writes as a
user on its own (an interruption note, a skill body) stays inside the
turn it belongs to.
"""
return [
index
for index, entry in enumerate(entries)
if entry.get("promptSource") and _is_prompt_entry(entry)
]
def last_message_before(entries: Sequence[Mapping[str, Any]], index: int) -> str | None:
"""Uuid of the last ``user``/``assistant`` entry ahead of ``index``."""
for entry in reversed(entries[:index]):
uuid = entry.get("uuid")
if (
entry.get("type") in _PROMPT_TYPES
and isinstance(uuid, str)
and not entry.get("isSidechain")
):
return uuid
return None
def spoken_text(block: Any, *, thinking_is_progress: bool) -> str:
"""What a content block (dict or model) says to the human.