mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-06 17:38:35 +00:00
fix: exclude archived keys in heartbeat & fallback missing session timestamps
This commit is contained in:
parent
9c6eaf0bed
commit
de4009efbd
@ -1065,8 +1065,15 @@ def _run_gateway(
|
|||||||
def _pick_heartbeat_target() -> tuple[str, str]:
|
def _pick_heartbeat_target() -> tuple[str, str]:
|
||||||
"""Pick a routable channel/chat target for heartbeat-triggered messages."""
|
"""Pick a routable channel/chat target for heartbeat-triggered messages."""
|
||||||
enabled = set(channels.enabled_channels)
|
enabled = set(channels.enabled_channels)
|
||||||
|
|
||||||
|
from nanobot.webui.sidebar_state import read_webui_sidebar_state
|
||||||
|
sidebar_state = read_webui_sidebar_state()
|
||||||
|
archived_keys = set(sidebar_state.get("archived_keys", []))
|
||||||
|
|
||||||
for item in session_manager.list_sessions():
|
for item in session_manager.list_sessions():
|
||||||
key = item.get("key") or ""
|
key = item.get("key") or ""
|
||||||
|
if key in archived_keys:
|
||||||
|
continue
|
||||||
if ":" not in key:
|
if ":" not in key:
|
||||||
continue
|
continue
|
||||||
channel, chat_id = key.split(":", 1)
|
channel, chat_id = key.split(":", 1)
|
||||||
|
|||||||
@ -843,11 +843,13 @@ class SessionManager:
|
|||||||
if not fallback_preview and item.get("role") == "assistant":
|
if not fallback_preview and item.get("role") == "assistant":
|
||||||
fallback_preview = text
|
fallback_preview = text
|
||||||
preview = preview or fallback_preview
|
preview = preview or fallback_preview
|
||||||
|
from datetime import datetime
|
||||||
|
fallback_time = datetime.fromtimestamp(path.stat().st_mtime).isoformat()
|
||||||
sessions.append(
|
sessions.append(
|
||||||
{
|
{
|
||||||
"key": key,
|
"key": key,
|
||||||
"created_at": data.get("created_at"),
|
"created_at": data.get("created_at") or fallback_time,
|
||||||
"updated_at": data.get("updated_at"),
|
"updated_at": data.get("updated_at") or fallback_time,
|
||||||
"title": title,
|
"title": title,
|
||||||
"preview": preview,
|
"preview": preview,
|
||||||
"path": str(path),
|
"path": str(path),
|
||||||
|
|||||||
@ -269,13 +269,20 @@ def _scan_session_row(session_manager: SessionManager, path: Path) -> dict[str,
|
|||||||
if not fallback_preview and item.get("role") == "assistant":
|
if not fallback_preview and item.get("role") == "assistant":
|
||||||
fallback_preview = text
|
fallback_preview = text
|
||||||
signature = _file_signature(path)
|
signature = _file_signature(path)
|
||||||
|
created_at_s = data.get("created_at")
|
||||||
|
updated_at_s = data.get("updated_at")
|
||||||
|
if not created_at_s or not updated_at_s:
|
||||||
|
from datetime import datetime
|
||||||
|
fallback_time = datetime.fromtimestamp(signature["mtime_ns"] / 1e9).isoformat()
|
||||||
|
created_at_s = created_at_s or fallback_time
|
||||||
|
updated_at_s = updated_at_s or fallback_time
|
||||||
key = data.get("key") or fallback_key
|
key = data.get("key") or fallback_key
|
||||||
activity_signature = _webui_activity_signature(key)
|
activity_signature = _webui_activity_signature(key)
|
||||||
activity_updated_at = _webui_activity_updated_at(activity_signature)
|
activity_updated_at = _webui_activity_updated_at(activity_signature)
|
||||||
return {
|
return {
|
||||||
"key": key,
|
"key": key,
|
||||||
"created_at": data.get("created_at"),
|
"created_at": created_at_s,
|
||||||
"updated_at": _latest_updated_at(data.get("updated_at"), activity_updated_at),
|
"updated_at": _latest_updated_at(updated_at_s, activity_updated_at),
|
||||||
"title": _metadata_title(data.get("metadata", {})),
|
"title": _metadata_title(data.get("metadata", {})),
|
||||||
"preview": preview or fallback_preview,
|
"preview": preview or fallback_preview,
|
||||||
"file": path.name,
|
"file": path.name,
|
||||||
|
|||||||
@ -171,3 +171,40 @@ def test_webui_session_list_rescans_when_transcript_changes(
|
|||||||
|
|
||||||
def list_webui_sessions(manager: SessionManager) -> list[dict]:
|
def list_webui_sessions(manager: SessionManager) -> list[dict]:
|
||||||
return session_list_index.list_webui_sessions(manager)
|
return session_list_index.list_webui_sessions(manager)
|
||||||
|
|
||||||
|
|
||||||
|
def test_webui_session_list_fallback_time_when_missing(tmp_path: Path) -> None:
|
||||||
|
manager = SessionManager(tmp_path)
|
||||||
|
path = manager._get_session_path("websocket:missing-time")
|
||||||
|
path.write_text(
|
||||||
|
'{"_type": "metadata", "key": "websocket:missing-time"}\n'
|
||||||
|
'{"_type": "message", "role": "user", "content": "hello"}\n',
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
|
||||||
|
rows = list_webui_sessions(manager)
|
||||||
|
assert len(rows) == 1
|
||||||
|
assert rows[0]["key"] == "websocket:missing-time"
|
||||||
|
assert rows[0]["created_at"] is not None
|
||||||
|
assert rows[0]["updated_at"] is not None
|
||||||
|
datetime.fromisoformat(rows[0]["created_at"])
|
||||||
|
datetime.fromisoformat(rows[0]["updated_at"])
|
||||||
|
|
||||||
|
|
||||||
|
def test_session_manager_list_sessions_fallback_time_when_missing(tmp_path: Path) -> None:
|
||||||
|
manager = SessionManager(tmp_path)
|
||||||
|
path = manager._get_session_path("websocket:missing-time2")
|
||||||
|
path.write_text(
|
||||||
|
'{"_type": "metadata", "key": "websocket:missing-time2"}\n'
|
||||||
|
'{"_type": "message", "role": "user", "content": "hello"}\n',
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
|
||||||
|
sessions = manager.list_sessions()
|
||||||
|
assert len(sessions) == 1
|
||||||
|
assert sessions[0]["key"] == "websocket:missing-time2"
|
||||||
|
assert sessions[0]["created_at"] is not None
|
||||||
|
assert sessions[0]["updated_at"] is not None
|
||||||
|
datetime.fromisoformat(sessions[0]["created_at"])
|
||||||
|
datetime.fromisoformat(sessions[0]["updated_at"])
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user