Environment
- Kimi Code CLI 2.0.0 (native single-file install; manually upgraded from 0.41.0 earlier the same day)
- macOS 26.6.2
kimi web served locally; accessed over LAN with two browser pages attached to the same session
- Session:
08ae755d-53a1-467a-b61b-db244c967b5c
Summary
In the web UI, when a message is queued with Ctrl+S ("insert into queue") while the agent is busy ("请求中…"), the newest queued message is rendered twice:
- once as the normal transcript bubble with the correct send time, and
- once more as a trailing "phantom" bubble pinned to the bottom of the transcript.
The phantom always tracks the latest queued message: when a newer message is queued, the older phantom disappears and the phantom moves to the new one. The phantom's timestamp is refreshed on each re-render, so it drifts later than the real bubble (observed: real 12:14 → phantom 12:16; real 12:16 → phantom 12:17 local time).
Session storage is not duplicated — this is a client-side rendering bug only (see Evidence).
Steps to reproduce
- Start a session and open the web UI in two browser pages on the same session (LAN setup).
- Make the agent busy with a long-running turn.
- Type a message and press Ctrl+S to queue it.
- Observe: the message appears twice in the transcript.
- Queue another message: the previous phantom disappears; the new latest message now shows its own phantom.
Reproduced 3/3 in this session (all while the agent was busy, two pages attached).
Expected
Each queued message renders exactly once. Any queue-tail indicator should be visually distinct and deduplicated against the transcript bubble by message id.
Actual
The newest queued message renders twice; the phantom keeps updating its timestamp on re-render, apparently on cross-client sync events.
Evidence (server-side storage is clean)
From ~/.kimi-code/sessions/<wd>/session_08ae755d-…/agents/main/wire.jsonl, each affected message appears in exactly one lifecycle chain:
prompt.steered ×1 → turn.steer ×1 → context.append_message ×1 → agent.message.appended ×1
No duplicate user messages exist in storage, and the model consumed each message exactly once. Example message id: msg_01M2R22GRJKT60BJXPTD5KPY54.
Attachments
Notes
Environment
kimi webserved locally; accessed over LAN with two browser pages attached to the same session08ae755d-53a1-467a-b61b-db244c967b5cSummary
In the web UI, when a message is queued with Ctrl+S ("insert into queue") while the agent is busy ("请求中…"), the newest queued message is rendered twice:
The phantom always tracks the latest queued message: when a newer message is queued, the older phantom disappears and the phantom moves to the new one. The phantom's timestamp is refreshed on each re-render, so it drifts later than the real bubble (observed: real 12:14 → phantom 12:16; real 12:16 → phantom 12:17 local time).
Session storage is not duplicated — this is a client-side rendering bug only (see Evidence).
Steps to reproduce
Reproduced 3/3 in this session (all while the agent was busy, two pages attached).
Expected
Each queued message renders exactly once. Any queue-tail indicator should be visually distinct and deduplicated against the transcript bubble by message id.
Actual
The newest queued message renders twice; the phantom keeps updating its timestamp on re-render, apparently on cross-client sync events.
Evidence (server-side storage is clean)
From
~/.kimi-code/sessions/<wd>/session_08ae755d-…/agents/main/wire.jsonl, each affected message appears in exactly one lifecycle chain:prompt.steered×1 →turn.steer×1 →context.append_message×1 →agent.message.appended×1No duplicate user messages exist in storage, and the model consumed each message exactly once. Example message id:
msg_01M2R22GRJKT60BJXPTD5KPY54.Attachments
kimi export) available privately on request — it contains complete conversation content, so I would rather not attach it to a public issue (same practice as [Desktop] Transcript API serves stale turns in long sessions (post-compaction); turn-list rebuild renders duplicates / drops latest turns #3866).Notes
wire.jsonl), different surface and trigger (Desktop transcript API serving stale turns post-compaction vs. web queue-tail rendering here).