Skip to content

[Bug][Desktop] Continuing a gateway-created session from desktop sends only the first N messages to the model — UI shows full transcript, request body truncated (stale live-history snapshot) #81951

Description

@n1majne3

Summary

When a session is created and processed by the gateway (messaging platform) and the user then continues the same session from the desktop app, the model receives only the first N messages of the conversation plus the new user message — the middle of the transcript is silently missing from the API request, with no summary and no compression involved. The desktop UI shows the full transcript (it reads from state.db), but the request body sent to the model provider is truncated.

Data is not lost (all rows are intact in state.db) — this is a stale in-memory session["history"] snapshot in the hermes serve backend that never caught up with the gateway's concurrent writes.

Environment

  • macOS, Hermes desktop app (Electron, backend via hermes serve)
  • Messaging-platform gateway (a reply-quote is routed as a new thread session)
  • Model with 1M context window, compression threshold ~512K — compression was never triggered (session was only ~67K tokens)

Timeline (from agent.log / gateway.log / state.db / provider request log)

Time Event
01:47:04 User sends a reply-quote on the messaging platform; it is routed as a new thread session; the gateway creates the session.
01:47–01:52 Gateway process handles the session: 44 messages written to state.db, 15 API calls, last request in=66890 tokens (full history). Turn ends normally.
01:54:16 User sends a new message from the desktop app (platform=desktop history=9; log: "Stored system prompt ... has stale runtime identity; rebuilding"). The desktop serve process takes over the gateway-created session.
01:54:36 Desktop's API call #1: in=41547~25K tokens (~35 messages) less than the gateway's last request.

Hard evidence

1. The actual request body captured at the provider gateway (15 messages total; contents elided):

[0]  system    (stale: carries the pre-update memory snapshot — memory was persisted after the gateway turn)
[1]  user      (first user turn)                          <- msg #808
[2]  assistant (tool_calls: session_search, skill_view x2) <- msg #809
[3-5] tool   x3                                            <- msgs #810-812
[6]  assistant (tool_calls: terminal x3, initial probing)  <- msg #813
[7-9] tool   x3 (probe outputs)                            <- msgs #814-816
[10] user     (NEW message)                                <- msg #852
[11-14] assistant + tool (follow-up calls)                 <- msgs #853-856
  • The request contains the session's first 9 messages (one complete probing turn) + the new user message + its follow-up tool calls.
  • Messages Add Hermes Research Agent #817fix: accept metadata in gateway helper signatures #851 (35 messages: the actual work performed, persistence updates, completion summary) are completely absent from the request. No summary/handoff message exists.
  • The system prompt still carries the pre-update memory snapshot (memory was persisted after the gateway turn).

2. agent.log token accounting

01:52:52 gateway: API call #15 in=66890  (full 44-msg history)
01:54:36 desktop: API call #1  in=41547  (9-msg history + new msg; ~25K tokens missing)

3. state.db is complete

  • All rows active=1, zero compacted=1 rows, no summary message, no session rotation (compression locks empty, no child session).
  • get_messages_as_conversation(<session>) returns the full transcript.
  • sessions.compression_ineffective_count=39 — compression never actually produced a summary.

Root cause hypothesis

The desktop serve backend registers a live session record (session["history"] in _sessions) while the session is still young (the desktop app watches sessions.changed events and picks up the gateway-created session early — when only the first 9 messages existed in DB). The gateway then writes 35 more messages + updates memory + rebuilds the system prompt, but the desktop live record's history snapshot is never refreshed.

  • UI display reads from state.db (get_resume_conversations / get_messages_as_conversation) → full transcript shown to the user.
  • Model inference uses session["history"] (run_kwargs["conversation_history"] = list(history) in tui_gateway/server.py) → stale 9-message snapshot sent to the provider.

Result: the user sees the complete conversation in the desktop UI while the model is blind to the middle 35 messages — and since nothing signals the truncation (no summary, no compaction notice), the model confidently answers from incomplete context. In our case it even invented a plausible-sounding mechanism to explain state changes it couldn't account for, which is how the bug surfaced.

Related

Expected behavior

A session resumed by the desktop backend must present the same conversation to the model as the user sees — i.e. conversation_history should be (re)loaded from state.db (or the live record refreshed on gateway writes / on resume), never a stale early snapshot. At minimum, a mismatch between the live record and the DB (e.g. DB row count > live history length) should force a reload or emit a visible warning instead of silently truncating the provider request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existsarea/sessionsSession lifecycle, resume, persistence, historycomp/desktopElectron desktop app (apps/desktop/*)comp/gatewayGateway runner, session dispatch, deliveryplatform/feishuFeishu / Lark adaptersweeper:risk-session-stateSweeper risk: may lose/corrupt/mis-associate session or context statetype/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions