Two kill/relaunch predicates decided identity by argv substring, the bug class root AGENTS.md forbids: hermes_cli/dashboard_procs.py::_is_desktop_local_serve_cmdline (`"serve" not in cmd`, on the orphan-reap KILL path) and hermes_cli/update_cmd_windows.py::_is_backend_argv (`" serve" in argv_low`, in the very file that defines _hermes_holder_subcommand). Both now ask the canonical token classifier; host/port are read as flag values, not substrings. hermes_cli/profiles.py::_check_gateway_running open-coded rungs 1/3 of gateway.status.resolve_gateway_liveness and skipped the multiplexer rung; it is now that ladder scoped to the profile dir (pid probe keeps cleanup_stale=False so a probe for another profile never unlinks its PID file). The gateway/status.py ladder itself is untouched. Behavior change: `hermes kanban --preserve-cache --host 127.0.0.1 --port 0` and `-m dashboard serve`-style argv are no longer classified as serve backends (never killed / relaunched as one); a named profile served by the live default multiplexer now reads as running from _check_gateway_running (previously only via the separate _served_by_running_multiplexer OR at some call sites).
29 lines
1.2 KiB
Python
29 lines
1.2 KiB
Python
"""Session-id minting: the ONE place that knows the ``YYYYMMDD_HHMMSS_<hex>`` shape.
|
|
|
|
stdlib-only on purpose: ``agent/``, ``cli.py``, ``gateway/`` and ``tui_gateway/`` all mint ids and
|
|
must not pull the SessionDB import graph in to do it. ``hermes_cli/session_lost_and_found.py``
|
|
classifies schema-less salvage rows by ``SESSION_ID_PATTERN``, so a shape change here is a
|
|
recovery-classification change — keep the prefix stable.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
import uuid
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
SESSION_ID_PATTERN = re.compile(r"^\d{8}_\d{6}_")
|
|
|
|
# Interactive surfaces (CLI, TUI, agent, branches, imports) share 6 hex chars — the Desktop's
|
|
# session-id candidate regex is pinned to that width. Gateway keys are 8, portability imports 12
|
|
# (many rows minted in the same second).
|
|
DEFAULT_HEX_LEN = 6
|
|
|
|
|
|
def new_session_id(now: Optional[datetime] = None, *, hex_len: int = DEFAULT_HEX_LEN) -> str:
|
|
"""``<timestamp>_<random hex>`` for a fresh session; ``now`` pins the timestamp to a clock the
|
|
caller already captured (``agent.session_start``) so the id and the row agree to the second."""
|
|
stamp = (now or datetime.now()).strftime("%Y%m%d_%H%M%S")
|
|
return f"{stamp}_{uuid.uuid4().hex[:hex_len]}"
|