mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-12 03:42:08 +00:00
Fix three regressions introduced by PR #18370 (lazy session creation): 1. _finalize_session() uses stale session_key after compression (#20001) 2. session_key not synced after auto-compression in run_conversation (#20001) 3. pending_title ValueError leaves title wedged forever (#19029) 4. Gateway silently swallows null responses when agent did work (#18765) 5. One-time cleanup for accumulated ghost compression continuations (#20001) Changes: - tui_gateway/server.py: _finalize_session() now uses agent.session_id (falls back to session_key when agent is None). Refactor _sync_session_key_after_compress() with clear_pending_title and restart_slash_worker policy flags. Call it post-run_conversation() to sync session_key after auto-compression. Add ValueError handler to pending_title flush. - gateway/run.py: Extract _normalize_empty_agent_response() helper that consolidates failed/partial/null response handling. Surfaces user-facing error when agent did work (api_calls > 0) but returned no text. - hermes_state.py: Add finalize_orphaned_compression_sessions() — marks ghost continuation sessions as ended (non-destructive, preserves data). - cli.py: One-time startup migration for orphaned compression sessions. Test changes: - tests/test_tui_gateway_server.py: Update pending_title ValueError test for post-#18370 architecture (title applied post-message, not at create). - tests/test_lazy_session_regressions.py: 14 new regression tests covering all fixed paths.
This commit is contained in:
parent
0397be5939
commit
3b750715a3
6 changed files with 809 additions and 74 deletions
|
|
@ -718,6 +718,45 @@ class SessionDB:
|
|||
self._remove_session_files(sessions_dir, sid)
|
||||
return len(removed_ids)
|
||||
|
||||
def finalize_orphaned_compression_sessions(self) -> int:
|
||||
"""Mark orphaned compression continuation sessions as ended.
|
||||
|
||||
Targets child sessions that were never finalized: parent is ended
|
||||
with reason='compression', child has messages but no end_reason/ended_at
|
||||
and api_call_count=0. Non-destructive: preserves all messages and sets
|
||||
end_reason='orphaned_compression'. Fix for #20001.
|
||||
"""
|
||||
cutoff = time.time() - 604800 # 7 days
|
||||
|
||||
def _do(conn):
|
||||
now = time.time()
|
||||
result = conn.execute(
|
||||
"""
|
||||
UPDATE sessions
|
||||
SET ended_at = ?,
|
||||
end_reason = 'orphaned_compression'
|
||||
WHERE api_call_count = 0
|
||||
AND end_reason IS NULL
|
||||
AND ended_at IS NULL
|
||||
AND started_at < ?
|
||||
AND parent_session_id IS NOT NULL
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM sessions p
|
||||
WHERE p.id = sessions.parent_session_id
|
||||
AND p.end_reason = 'compression'
|
||||
AND p.ended_at IS NOT NULL
|
||||
)
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM messages m
|
||||
WHERE m.session_id = sessions.id
|
||||
)
|
||||
""",
|
||||
(now, cutoff),
|
||||
)
|
||||
return result.rowcount
|
||||
|
||||
return self._execute_write(_do) or 0
|
||||
|
||||
def get_session(self, session_id: str) -> Optional[Dict[str, Any]]:
|
||||
"""Get a session by ID."""
|
||||
with self._lock:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue