Skip to content

Commit 4e87e21

Browse files
authored
Update tui.py
1 parent 1e0805e commit 4e87e21

1 file changed

Lines changed: 28 additions & 16 deletions

File tree

python_agent_harness/tui.py

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,13 @@
3838
from .commands import find_command
3939
from .diffrender import render_diff
4040
from .models import Message
41-
from .session_store import SessionStore, title_from_filename
41+
from .session_store import (
42+
SessionStore,
43+
escape_role_headers,
44+
split_role_header,
45+
title_from_filename,
46+
unescape_role_header,
47+
)
4248

4349
SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]
4450

@@ -1345,7 +1351,8 @@ def _conversation_text(self) -> str:
13451351
msgs = self.session.last_messages or []
13461352
parts = []
13471353
for m in msgs:
1348-
body = m.text()
1354+
# escaped: see session_store.escape_role_headers
1355+
body = escape_role_headers(m.text())
13491356
if body:
13501357
parts.append(f"**{m.role}**: {body}")
13511358
return "\n\n".join(parts)
@@ -1462,27 +1469,32 @@ def _parse_saved_body(body: str) -> list[Message]:
14621469
``tool_calls``). The following assistant reply already
14631470
summarizes the results, so dropping them loses no essential
14641471
context.
1472+
1473+
Body lines that merely look like a block header are escaped by
1474+
the renderer (see `escape_role_headers`) and unescaped here, so
1475+
a message quoting this format no longer splits into extra
1476+
messages. Sessions saved before escaping existed can still
1477+
split — that ambiguity is in the file, not in this parser.
14651478
"""
14661479
messages: list[Message] = []
14671480
current_role: str | None = None
14681481
current_lines: list[str] = []
14691482

14701483
for line in body.splitlines():
14711484
# Check for a role header: **user**: ... or **assistant**: ...
1472-
if line.startswith("**") and "**: " in line:
1473-
prefix, _, rest = line.partition("**: ")
1474-
role = prefix.strip("*").strip()
1475-
if role in ("user", "assistant", "system", "tool"):
1476-
# Save the previous block (tool blocks are dropped:
1477-
# their tool_call_id/name were not persisted)
1478-
if current_role is not None and current_role != "tool":
1479-
content = "\n".join(current_lines).strip()
1480-
if content:
1481-
messages.append(Message(role=current_role, content=content))
1482-
current_role = role
1483-
current_lines = [rest]
1484-
continue
1485-
current_lines.append(line)
1485+
header = split_role_header(line)
1486+
if header is not None:
1487+
role, rest = header
1488+
# Save the previous block (tool blocks are dropped:
1489+
# their tool_call_id/name were not persisted)
1490+
if current_role is not None and current_role != "tool":
1491+
content = "\n".join(current_lines).strip()
1492+
if content:
1493+
messages.append(Message(role=current_role, content=content))
1494+
current_role = role
1495+
current_lines = [unescape_role_header(rest)]
1496+
continue
1497+
current_lines.append(unescape_role_header(line))
14861498

14871499
# Don't forget the last block (tool blocks are dropped)
14881500
if current_role is not None and current_role != "tool":

0 commit comments

Comments
 (0)