Bug Description
When using hermes --tui, pressing Ctrl-C to exit sometimes prints the "Resume this session with:" summary and sometimes doesn't. This is inconsistent and confusing — the user can't predict whether they'll see the resume command.
Steps to Reproduce
- Run
hermes --tui (fresh session, no --resume)
- Send at least one message so the agent responds
- Press Ctrl-C to exit
- Observe: the "Resume this session with:" banner prints (via
_resolve_last_session fallback)
- Run
hermes --tui again (fresh session)
- Press Ctrl-C immediately without sending any message
- Observe: no resume banner, or resume banner for a different (previous) session
Expected Behavior
The "Resume this session with:" banner should consistently show the correct current session ID after Ctrl-C exit, regardless of whether messages were sent.
Actual Behavior
The resume banner:
- Shows correctly when messages were sent (via
_resolve_last_session(source="tui") fallback)
- Does not show or shows the wrong session when Ctrl-C is pressed before any messages were sent
Root Cause Analysis
Two issues in the active-session-file pipeline:
1. session.create response omits session_key — short UUID written to active session file
In tui_gateway/server.py, session.create (line 1953–2008):
sid = uuid.uuid4().hex[:8] # short 8-char UUID
key = _new_session_key() # DB session key: YYYYMMDD_HHMMSS_xxxxxx
...
return _ok(rid, {
"session_id": sid, # ← only the short UUID, NOT `key`
...
})
In ui-tui/src/app/useSessionLifecycle.ts, newSession (line 148):
writeActiveSessionFile(r.session_id) // r.session_id = short UUID
When _print_tui_exit_summary in hermes_cli/main.py (line 786) reads this file and tries db.get_session(short_uuid), the lookup fails because sessions in the DB are keyed by session_key (the YYYYMMDD_HHMMSS_xxxxxx format), NOT the short UUID.
For comparison, session.resume correctly returns both IDs:
return _ok(rid, {
"session_id": sid, # short UUID
"resumed": target, # DB session key ← used by frontend
...
})
And useSessionLifecycle.ts line 206 correctly prioritizes the DB key:
writeActiveSessionFile(r.resumed ?? r.session_id)
2. Session DB row deferred to first run_conversation() call
In run_agent.py, _ensure_db_session() (line 2155) is only called during run_conversation(). If the user Ctrl-C's before sending any message, the session is never persisted to the DB. This means:
- Priority 1 (
_read_tui_active_session_file): fails (short UUID vs DB key mismatch)
- Priority 2 (
session_id parameter): None for fresh sessions
- Priority 3 (
_resolve_last_session): returns previous session or None
Result: the fallback returns a stale previous session (showing wrong resume info) or nothing (showing no resume info).
Proposed Fix
Minimal fix: Include session_key in the session.create response and use it in the TUI frontend.
Server-side (tui_gateway/server.py, line 1996–2008): add session_key to response:
return _ok(rid, {
"session_id": sid,
"session_key": key, # ← add this
"info": { ... },
})
Client-side (ui-tui/src/app/useSessionLifecycle.ts, line 148): use session_key when available:
writeActiveSessionFile(r.session_key ?? r.session_id)
This mirrors the existing r.resumed ?? r.session_id pattern in resumeById (line 206).
Alternative: Also persist the session DB row eagerly (on session.create) instead of deferring to first run_conversation(), so _resolve_last_session always finds the current session. This would be a larger change and may conflict with the design intent of avoiding empty DB rows.
Affected Files
tui_gateway/server.py — session.create handler (line ~1996)
ui-tui/src/app/useSessionLifecycle.ts — newSession (line 148)
hermes_cli/main.py — _print_tui_exit_summary (line 786)
Bug Description
When using
hermes --tui, pressing Ctrl-C to exit sometimes prints the "Resume this session with:" summary and sometimes doesn't. This is inconsistent and confusing — the user can't predict whether they'll see the resume command.Steps to Reproduce
hermes --tui(fresh session, no--resume)_resolve_last_sessionfallback)hermes --tuiagain (fresh session)Expected Behavior
The "Resume this session with:" banner should consistently show the correct current session ID after Ctrl-C exit, regardless of whether messages were sent.
Actual Behavior
The resume banner:
_resolve_last_session(source="tui")fallback)Root Cause Analysis
Two issues in the active-session-file pipeline:
1.
session.createresponse omitssession_key— short UUID written to active session fileIn
tui_gateway/server.py,session.create(line 1953–2008):In
ui-tui/src/app/useSessionLifecycle.ts,newSession(line 148):When
_print_tui_exit_summaryinhermes_cli/main.py(line 786) reads this file and triesdb.get_session(short_uuid), the lookup fails because sessions in the DB are keyed bysession_key(theYYYYMMDD_HHMMSS_xxxxxxformat), NOT the short UUID.For comparison,
session.resumecorrectly returns both IDs:And
useSessionLifecycle.tsline 206 correctly prioritizes the DB key:2. Session DB row deferred to first
run_conversation()callIn
run_agent.py,_ensure_db_session()(line 2155) is only called duringrun_conversation(). If the user Ctrl-C's before sending any message, the session is never persisted to the DB. This means:_read_tui_active_session_file): fails (short UUID vs DB key mismatch)session_idparameter):Nonefor fresh sessions_resolve_last_session): returns previous session orNoneResult: the fallback returns a stale previous session (showing wrong resume info) or nothing (showing no resume info).
Proposed Fix
Minimal fix: Include
session_keyin thesession.createresponse and use it in the TUI frontend.Server-side (
tui_gateway/server.py, line 1996–2008): addsession_keyto response:Client-side (
ui-tui/src/app/useSessionLifecycle.ts, line 148): usesession_keywhen available:This mirrors the existing
r.resumed ?? r.session_idpattern inresumeById(line 206).Alternative: Also persist the session DB row eagerly (on
session.create) instead of deferring to firstrun_conversation(), so_resolve_last_sessionalways finds the current session. This would be a larger change and may conflict with the design intent of avoiding empty DB rows.Affected Files
tui_gateway/server.py—session.createhandler (line ~1996)ui-tui/src/app/useSessionLifecycle.ts—newSession(line 148)hermes_cli/main.py—_print_tui_exit_summary(line 786)