[verified] fix: preserve timestamps in chat history
This commit is contained in:
@@ -9,6 +9,7 @@ so the module can be imported by unit tests without a Hermes install.
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import datetime as dt
|
||||||
import logging
|
import logging
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
@@ -206,8 +207,10 @@ async def list_conversations(server: Any = None) -> List[Dict[str, Any]]:
|
|||||||
|
|
||||||
def _iso(value: Any) -> Optional[str]:
|
def _iso(value: Any) -> Optional[str]:
|
||||||
try:
|
try:
|
||||||
|
if isinstance(value, (int, float)):
|
||||||
|
return dt.datetime.fromtimestamp(value, tz=dt.timezone.utc).isoformat()
|
||||||
return value.isoformat() if value else None
|
return value.isoformat() if value else None
|
||||||
except AttributeError:
|
except (AttributeError, OSError, OverflowError, TypeError, ValueError):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@@ -254,8 +257,7 @@ async def conversation_history(conversation_id: str, limit: int
|
|||||||
if isinstance(row.get("_row_id"), (int, str)) else None,
|
if isinstance(row.get("_row_id"), (int, str)) else None,
|
||||||
"role": role,
|
"role": role,
|
||||||
"text": text,
|
"text": text,
|
||||||
"ts": row.get("timestamp") if isinstance(
|
"ts": _iso(row.get("timestamp")),
|
||||||
row.get("timestamp"), str) else None,
|
|
||||||
})
|
})
|
||||||
found = True
|
found = True
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
@@ -432,6 +432,32 @@ class TestAttachments:
|
|||||||
# Tool events / approvals / clarifications / cancellation (bridge)
|
# Tool events / approvals / clarifications / cancellation (bridge)
|
||||||
# ═══════════════════════════════════════════════════════════════════════════
|
# ═══════════════════════════════════════════════════════════════════════════
|
||||||
class TestBridge:
|
class TestBridge:
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_history_converts_numeric_hermes_timestamps_to_iso(self, monkeypatch):
|
||||||
|
from pheby import hermes_bridge as hb
|
||||||
|
|
||||||
|
class Store:
|
||||||
|
def peek_session_id(self, _key):
|
||||||
|
return "session-1"
|
||||||
|
|
||||||
|
class DB:
|
||||||
|
def get_messages_as_conversation(self, _session_id, include_row_ids=False):
|
||||||
|
assert include_row_ids is True
|
||||||
|
return [
|
||||||
|
{"_row_id": 10, "role": "user", "content": "hello", "timestamp": 1_789_000_000.25},
|
||||||
|
{"_row_id": 11, "role": "assistant", "content": "reply", "timestamp": 1_789_000_001.5},
|
||||||
|
]
|
||||||
|
|
||||||
|
monkeypatch.setattr(hb, "_session_store", lambda: Store())
|
||||||
|
monkeypatch.setattr(hb, "_session_db", lambda: DB())
|
||||||
|
|
||||||
|
history, found = await hb.conversation_history("conv", 20)
|
||||||
|
|
||||||
|
assert found is True
|
||||||
|
assert [message["message_id"] for message in history] == ["m10", "m11"]
|
||||||
|
assert history[0]["ts"] == "2026-09-10T00:26:40.250000+00:00"
|
||||||
|
assert history[1]["ts"] == "2026-09-10T00:26:41.500000+00:00"
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_tool_start_event_is_structured_not_text(self, tmp_path,
|
async def test_tool_start_event_is_structured_not_text(self, tmp_path,
|
||||||
monkeypatch):
|
monkeypatch):
|
||||||
|
|||||||
Reference in New Issue
Block a user