fix(compression): preserve steer display identity

(cherry picked from commit a8570878bc848a42cc8029fc45219a57e76be4c4)
This commit is contained in:
fangliquan
2026-09-20 18:04:48 +08:00
committed by Teknium
parent 6d02101fbf
commit bb9058d7e8
3 changed files with 48 additions and 1 deletions

View File

@@ -77,11 +77,13 @@ def _active_assistant_row(conn: sqlite3.Connection, session_id: str, row_id: int
def sync_flushed_message_markers(batch_msgs: List[Dict[str, Any]], batch_rows: List[Dict[str, Any]]) -> None:
"""Stamp _DB_PERSISTED_MARKER and sync canonical row ID / content onto live dicts after commit."""
"""Stamp _DB_PERSISTED_MARKER and sync canonical durable fields onto live dicts after commit."""
for written, row in zip(batch_msgs, batch_rows):
written[_DB_PERSISTED_MARKER] = True
if isinstance(row.get("_row_id"), int):
written["_row_id"] = row["_row_id"]
if isinstance(row.get("timestamp"), (int, float)):
written["timestamp"] = row["timestamp"]
if "_canonical_content" in row:
written["content"] = row["_canonical_content"]

View File

@@ -515,6 +515,11 @@ class SessionMessagesMixin:
message_timestamp = _coerce_timestamp(msg.get("timestamp"), now_ts)
cur = conn.execute(_INSERT_MESSAGE_SQL, self._message_row_params(
session_id, role, msg, tool_calls, message_timestamp, keep_reasoning=role == "assistant"))
# Keep the caller's live row aligned with the durable identity. Rows created without an explicit
# timestamp (notably mid-turn steers) may be carried through several compaction generations; if
# the generated timestamp exists only in SQLite, every copy receives a new identity and renders
# as another logical message.
msg["timestamp"] = message_timestamp
if cur.lastrowid is not None:
msg["_row_id"] = cur.lastrowid
inserted += 1

View File

@@ -0,0 +1,40 @@
"""Regression coverage for steer display identity across compactions (#117137)."""
from unittest.mock import patch
from agent.prompt_builder import steer_user_row
from hermes_state import SessionDB
from run_agent import AIAgent
def test_flushed_steer_keeps_one_display_identity_across_compactions(tmp_path):
db = SessionDB(tmp_path / "state.db")
session_id = "steer-compaction"
with patch.dict("os.environ", {"OPENROUTER_API_KEY": "test-key"}):
agent = AIAgent(
api_key="test-key",
base_url="https://openrouter.ai/api/v1",
model="test/model",
quiet_mode=True,
session_db=db,
session_id=session_id,
skip_context_files=True,
skip_memory=True,
)
agent._ensure_db_session()
steer = steer_user_row("focus on the persistence failure")
agent._flush_messages_to_session_db([steer], [])
durable_timestamp = db.get_messages(session_id)[0]["timestamp"]
assert steer["timestamp"] == durable_timestamp
for _ in range(2):
db.archive_and_compact(session_id, [dict(steer)])
physical = db.get_messages(session_id, include_inactive=True)
assert len([row for row in physical if row["display_kind"] == "steer"]) == 3
visible = db.get_messages(session_id, include_compacted=True)
assert [(row["display_kind"], row["content"]) for row in visible] == [
("steer", steer["content"]),
]