diff --git a/hermes_cli/main.py b/hermes_cli/main.py index 0793b6a89e..581b363a9f 100644 --- a/hermes_cli/main.py +++ b/hermes_cli/main.py @@ -44,7 +44,6 @@ Usage: """ import argparse -import json import os import shutil import subprocess @@ -761,20 +760,9 @@ def _resolve_session_by_name_or_id(name_or_id: str) -> Optional[str]: return None -def _read_tui_active_session_file(path: Optional[str]) -> Optional[str]: - if not path: - return None - try: - data = json.loads(Path(path).read_text(encoding="utf-8")) - sid = str(data.get("session_id") or "").strip() - return sid or None - except Exception: - return None - - -def _print_tui_exit_summary(session_id: Optional[str], active_session_file: Optional[str] = None) -> None: +def _print_tui_exit_summary(session_id: Optional[str]) -> None: """Print a shell-visible epilogue after TUI exits.""" - target = _read_tui_active_session_file(active_session_file) or session_id or _resolve_last_session(source="tui") + target = session_id or _resolve_last_session(source="tui") if not target: return @@ -1049,13 +1037,7 @@ def _launch_tui( """Replace current process with the TUI.""" tui_dir = PROJECT_ROOT / "ui-tui" - import tempfile - env = os.environ.copy() - active_session_file = os.path.join( - tempfile.gettempdir(), f"hermes-tui-active-session-{os.getpid()}.json" - ) - env["HERMES_TUI_ACTIVE_SESSION_FILE"] = active_session_file env["HERMES_PYTHON_SRC_ROOT"] = os.environ.get( "HERMES_PYTHON_SRC_ROOT", str(PROJECT_ROOT) ) @@ -1089,12 +1071,7 @@ def _launch_tui( code = 130 if code in (0, 130): - _print_tui_exit_summary(resume_session_id, active_session_file) - - try: - os.unlink(active_session_file) - except OSError: - pass + _print_tui_exit_summary(resume_session_id) sys.exit(code) diff --git a/tests/hermes_cli/test_tui_resume_flow.py b/tests/hermes_cli/test_tui_resume_flow.py index 7187431c82..9678421e7e 100644 --- a/tests/hermes_cli/test_tui_resume_flow.py +++ b/tests/hermes_cli/test_tui_resume_flow.py @@ -178,38 +178,3 @@ def test_print_tui_exit_summary_includes_resume_and_token_totals(monkeypatch, ca assert "hermes --tui --resume 20260409_000001_abc123" in out assert 'hermes --tui -c "demo title"' in out assert "Tokens: 21 (in 10, out 6, cache 4, reasoning 1)" in out - - -def test_print_tui_exit_summary_prefers_actual_active_session_file(monkeypatch, capsys, tmp_path): - import hermes_cli.main as main_mod - - seen = [] - - class _FakeDB: - def get_session(self, session_id): - seen.append(session_id) - return { - "message_count": 1, - "input_tokens": 0, - "output_tokens": 0, - "cache_read_tokens": 0, - "cache_write_tokens": 0, - "reasoning_tokens": 0, - } - - def get_session_title(self, _session_id): - return "actual" - - def close(self): - return None - - active = tmp_path / "active.json" - active.write_text('{"session_id":"actual_session"}', encoding="utf-8") - monkeypatch.setitem(sys.modules, "hermes_state", types.SimpleNamespace(SessionDB=lambda: _FakeDB())) - - main_mod._print_tui_exit_summary("startup_resume", str(active)) - out = capsys.readouterr().out - - assert seen == ["actual_session"] - assert "hermes --tui --resume actual_session" in out - assert "startup_resume" not in out diff --git a/ui-tui/src/__tests__/useSessionLifecycle.test.ts b/ui-tui/src/__tests__/useSessionLifecycle.test.ts deleted file mode 100644 index 8d797742f2..0000000000 --- a/ui-tui/src/__tests__/useSessionLifecycle.test.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { mkdtempSync, readFileSync, rmSync } from 'node:fs' -import { tmpdir } from 'node:os' -import { join } from 'node:path' - -import { afterEach, describe, expect, it } from 'vitest' - -import { writeActiveSessionFile } from '../app/useSessionLifecycle.js' - -describe('writeActiveSessionFile', () => { - let dir = '' - - afterEach(() => { - if (dir) { - rmSync(dir, { force: true, recursive: true }) - dir = '' - } - }) - - it('writes the actual resumed session id for the shell exit summary', () => { - dir = mkdtempSync(join(tmpdir(), 'hermes-tui-active-')) - const path = join(dir, 'active.json') - - writeActiveSessionFile('actual_session', path) - - expect(JSON.parse(readFileSync(path, 'utf8'))).toEqual({ session_id: 'actual_session' }) - }) -}) diff --git a/ui-tui/src/app/useSessionLifecycle.ts b/ui-tui/src/app/useSessionLifecycle.ts index 473c5adb3e..140737af7f 100644 --- a/ui-tui/src/app/useSessionLifecycle.ts +++ b/ui-tui/src/app/useSessionLifecycle.ts @@ -1,6 +1,5 @@ -import { writeFileSync } from 'node:fs' - -import { evictInkCaches, type ScrollBoxHandle } from '@hermes/ink' +import type { ScrollBoxHandle } from '@hermes/ink' +import { evictInkCaches } from '@hermes/ink' import { type RefObject, useCallback } from 'react' import { buildSetupRequiredSections, SETUP_REQUIRED_TITLE } from '../content/setup.js' @@ -24,19 +23,6 @@ import { getUiState, patchUiState } from './uiStore.js' const usageFrom = (info: null | SessionInfo): Usage => (info?.usage ? { ...ZERO, ...info.usage } : ZERO) -export const writeActiveSessionFile = (sessionId: null | string, file = process.env.HERMES_TUI_ACTIVE_SESSION_FILE) => { - if (!file || !sessionId) { - return - } - - // Best-effort shell-epilogue hint; never break live session changes. - try { - writeFileSync(file, JSON.stringify({ session_id: sessionId }), { mode: 0o600 }) - } catch { - /* best-effort */ - } -} - const trimTail = (items: Msg[]) => { const q = [...items] @@ -145,7 +131,6 @@ export function useSessionLifecycle(opts: UseSessionLifecycleOptions) { resetSession() setSessionStartedAt(Date.now()) - writeActiveSessionFile(r.session_id) patchUiState({ info, sid: r.session_id, @@ -203,7 +188,6 @@ export function useSessionLifecycle(opts: UseSessionLifecycleOptions) { const resumed = toTranscriptMessages(r.messages) setHistoryItems(r.info ? [introMsg(r.info), ...resumed] : resumed) - writeActiveSessionFile(r.resumed ?? r.session_id) patchUiState({ info: r.info ?? null, sid: r.session_id,