mirror of
https://github.com/nesquena/hermes-webui.git
synced 2026-05-29 13:10:17 +00:00
+21
-2
@@ -436,7 +436,14 @@ class Session:
|
||||
self.read_only = bool(kwargs.get('read_only', False))
|
||||
self.enabled_toolsets = enabled_toolsets # List[str] or None — per-session toolset override
|
||||
self.composer_draft = composer_draft if isinstance(composer_draft, dict) else {}
|
||||
self._metadata_message_count = None
|
||||
raw_message_count = kwargs.get('message_count')
|
||||
parsed_message_count = None
|
||||
if raw_message_count is not None:
|
||||
try:
|
||||
parsed_message_count = int(raw_message_count)
|
||||
except (TypeError, ValueError):
|
||||
parsed_message_count = None
|
||||
self._metadata_message_count = parsed_message_count if parsed_message_count is not None and parsed_message_count >= 0 else None
|
||||
|
||||
@property
|
||||
def path(self):
|
||||
@@ -601,7 +608,19 @@ class Session:
|
||||
parsed['messages'] = []
|
||||
parsed['tool_calls'] = []
|
||||
session = cls(**parsed)
|
||||
session._metadata_message_count = _lookup_index_message_count(sid)
|
||||
metadata_message_count = _lookup_index_message_count(sid)
|
||||
if metadata_message_count is None:
|
||||
raw_count = parsed.get('message_count')
|
||||
if isinstance(raw_count, int) and raw_count >= 0:
|
||||
metadata_message_count = raw_count
|
||||
else:
|
||||
try:
|
||||
parsed_count = int(raw_count)
|
||||
except (TypeError, ValueError):
|
||||
parsed_count = None
|
||||
if parsed_count is not None and parsed_count >= 0:
|
||||
metadata_message_count = parsed_count
|
||||
session._metadata_message_count = metadata_message_count
|
||||
# Mark this session as a metadata-only stub. save() refuses to write
|
||||
# such a session because doing so would atomically replace the
|
||||
# on-disk JSON with messages=[], wiping the conversation. Any
|
||||
|
||||
@@ -3721,6 +3721,18 @@ def handle_get(handler, parsed) -> bool:
|
||||
_all_msgs = merge_session_messages_append_only(_metadata_sidecar, state_db_messages)
|
||||
if not load_messages:
|
||||
_summary_message_count = len(_all_msgs)
|
||||
if _summary_message_count == 0:
|
||||
# Legacy session with no loaded sidecar and no state.db summary —
|
||||
# fall back to the persisted metadata count from session JSON.
|
||||
# See PR #2605 (LumenYoung): without this, the metadata poll
|
||||
# returns 0 and the active-session external-refresh signal
|
||||
# never trips on legacy sessions.
|
||||
try:
|
||||
metadata_count = getattr(s, "_metadata_message_count", None)
|
||||
if metadata_count is not None:
|
||||
_summary_message_count = max(0, int(metadata_count))
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
try:
|
||||
_summary_last_message_at = max(
|
||||
float((m or {}).get("timestamp") or 0)
|
||||
|
||||
@@ -135,6 +135,32 @@ def test_api_session_includes_state_db_messages_newer_than_webui_sidecar(monkeyp
|
||||
assert payload["session"]["message_count"] == 4
|
||||
|
||||
|
||||
def test_metadata_poll_uses_sidecar_message_count_for_external_updates(monkeypatch, tmp_path):
|
||||
"""Active-session external refresh relies on metadata-only counts.
|
||||
|
||||
When no session index exists, metadata-only loads may fall back to
|
||||
_metadata_message_count=None. The refresh poll must still report the real
|
||||
sidecar message count; otherwise an external session JSON update can be
|
||||
invisible until a full reload.
|
||||
"""
|
||||
import api.routes as routes
|
||||
|
||||
sid = "webui_reconcile_metadata_sidecar"
|
||||
sidecar_messages = [
|
||||
{"role": "user", "content": "before external update", "timestamp": 1000.0},
|
||||
{"role": "assistant", "content": "externally appended", "timestamp": 1001.0},
|
||||
]
|
||||
_install_test_session(monkeypatch, tmp_path, sid, sidecar_messages)
|
||||
|
||||
handler = _GetHandler(f"/api/session?session_id={sid}&messages=0&resolve_model=0")
|
||||
routes.handle_get(handler, urlparse(handler.path))
|
||||
|
||||
assert handler.status == 200
|
||||
session = handler.response_json["session"]
|
||||
assert session["message_count"] == 2
|
||||
assert session["last_message_at"] == 1001.0
|
||||
|
||||
|
||||
def test_state_db_reconciliation_preserves_sidecar_only_messages(monkeypatch, tmp_path):
|
||||
import api.routes as routes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user