Fix CLI session CI compatibility

This commit is contained in:
Frank Song authored and test committed 2026-05-05 01:52:42 +00:00
1 parent 79d0762d8c
commit 8981d33543
3 files changed
+28 -10

No files matched your search

+9 -2
View File
@@ -313,7 +313,7 @@ def _project_agent_session_rows(rows: list[dict]) -> list[dict]:
# touched standalone sessions — exactly the inverse of what a user
# expects from "Show agent sessions" sorted by activity.
for key in (
'id', 'model', 'message_count', 'actual_message_count',
'id', 'model', 'message_count', 'actual_message_count', 'actual_user_message_count',
'ended_at', 'end_reason', 'last_activity',
):
if key in tip:
@@ -367,6 +367,8 @@ def read_importable_agent_session_rows(
# source column we cannot safely distinguish WebUI rows from agent rows.
cur.execute("PRAGMA table_info(sessions)")
session_cols = {row[1] for row in cur.fetchall()}
cur.execute("PRAGMA table_info(messages)")
message_cols = {row[1] for row in cur.fetchall()}
if 'source' not in session_cols:
log.warning(
"agent session listing skipped: state.db at %s has no 'source' column "
@@ -387,6 +389,11 @@ def read_importable_agent_session_rows(
origin_chat_id_expr = _optional_col('origin_chat_id', session_cols)
origin_user_id_expr = _optional_col('origin_user_id', session_cols)
platform_expr = _optional_col('platform', session_cols)
user_message_count_expr = (
"COUNT(CASE WHEN LOWER(m.role) = 'user' THEN 1 END)"
if 'role' in message_cols
else "COUNT(m.id)"
)
where_clauses = ["s.source IS NOT NULL"]
params: list[str] = []
@@ -413,7 +420,7 @@ def read_importable_agent_session_rows(
{ended_expr},
{end_reason_expr},
COUNT(m.id) AS actual_message_count,
COUNT(CASE WHEN LOWER(m.role) = 'user' THEN 1 END) AS actual_user_message_count,
{user_message_count_expr} AS actual_user_message_count,
MAX(m.timestamp) AS last_activity
FROM sessions s
LEFT JOIN messages m ON m.session_id = s.id
+9 -8
View File
@@ -226,6 +226,12 @@ def _last_message_timestamp(messages):
return None
def _message_role(message):
if not isinstance(message, dict):
return ''
return str(message.get('role', '')).strip().lower()
def _find_top_level_json_key(text, key):
"""Return the byte offset of a top-level JSON object key, if present."""
depth = 0
@@ -538,11 +544,6 @@ class Session:
last_message_at = _last_message_timestamp(self.messages) or self.updated_at
if has_pending_user_message and self.pending_started_at:
last_message_at = self.pending_started_at
def _role(message):
if not isinstance(message, dict):
return ""
return str(message.get('role', '')).strip().lower()
return {
'session_id': self.session_id,
'title': self.title,
@@ -560,9 +561,6 @@ class Session:
'input_tokens': self.input_tokens,
'output_tokens': self.output_tokens,
'estimated_cost': self.estimated_cost,
'user_message_count': sum(
1 for message in self.messages if _role(message) == 'user'
) if isinstance(self.messages, list) else 0,
'personality': self.personality,
'compression_anchor_visible_idx': self.compression_anchor_visible_idx,
'compression_anchor_message_key': self.compression_anchor_message_key,
@@ -572,6 +570,9 @@ class Session:
# Only emit 'parent_session_id' when set (the /branch fork link, #1342).
# Sessions without a fork must not leak None — see test_session_lineage_metadata_api.
**({'parent_session_id': self.parent_session_id} if self.parent_session_id else {}),
'user_message_count': sum(
1 for message in self.messages if _message_role(message) == 'user'
) if isinstance(self.messages, list) else 0,
'active_stream_id': self.active_stream_id,
'pending_user_message': self.pending_user_message,
'has_pending_user_message': has_pending_user_message,
+10
View File
@@ -142,6 +142,16 @@ def test_non_cron_sessions_unaffected(fake_hermes_home):
_make_state_db(fake_hermes_home / "state.db", [
("cron_cd65df6fc1a8_xx", None, "cli"),
])
# PR #1587 hides one-off default-titled CLI rows. Keep this fixture visible
# so the test remains focused on the cron-name guard rather than sidebar
# filtering.
conn = sqlite3.connect(str(fake_hermes_home / "state.db"))
conn.execute(
"INSERT INTO messages (session_id, timestamp) VALUES (?, ?)",
("cron_cd65df6fc1a8_xx", 1700000002.0),
)
conn.commit()
conn.close()
sessions = models.get_cli_sessions()