fix: use AUTOINCREMENT id for message ordering instead of timestamp

On WSL2 (and similar environments), time.time() is not strictly monotonic
due to NTP sync or host clock adjustments. When clock regression occurs
during a multi-tool flush, later-inserted rows get earlier timestamps,
causing ORDER BY timestamp, id to sort them before rows that were written
first. This breaks the tool_calls/tool_response adjacency invariant and
triggers HTTP 400 from the API.

Use ORDER BY id instead, since id (INTEGER PRIMARY KEY AUTOINCREMENT)
always reflects true insertion order regardless of system clock behavior.
This commit is contained in:
yifengingit 2026-05-14 07:57:47 -07:00 committed by Teknium
parent 8ae65d5c8c
commit c03acca508

View file

@ -1597,10 +1597,10 @@ class SessionDB:
self._execute_write(_do) self._execute_write(_do)
def get_messages(self, session_id: str) -> List[Dict[str, Any]]: def get_messages(self, session_id: str) -> List[Dict[str, Any]]:
"""Load all messages for a session, ordered by timestamp.""" """Load all messages for a session, ordered by insertion order."""
with self._lock: with self._lock:
cursor = self._conn.execute( cursor = self._conn.execute(
"SELECT * FROM messages WHERE session_id = ? ORDER BY timestamp, id", "SELECT * FROM messages WHERE session_id = ? ORDER BY id",
(session_id,), (session_id,),
) )
rows = cursor.fetchall() rows = cursor.fetchall()
@ -1700,7 +1700,7 @@ class SessionDB:
"SELECT role, content, tool_call_id, tool_calls, tool_name, " "SELECT role, content, tool_call_id, tool_calls, tool_name, "
"finish_reason, reasoning, reasoning_content, reasoning_details, " "finish_reason, reasoning, reasoning_content, reasoning_details, "
"codex_reasoning_items, codex_message_items " "codex_reasoning_items, codex_message_items "
f"FROM messages WHERE session_id IN ({placeholders}) ORDER BY timestamp, id", f"FROM messages WHERE session_id IN ({placeholders}) ORDER BY id",
tuple(session_ids), tuple(session_ids),
).fetchall() ).fetchall()