← Back to PRs

#13104: fix: persist user command message in chat transcript

by mcaxtr open 2026-02-10 04:11 View on GitHub →
app: web-ui gateway size: M trusted-contributor experienced-contributor
## Summary Fixes #12934 When the Control UI sends a slash command (e.g. `/status`) via `chat.send`, the server processes the command without starting an agent run. In this code path, only the assistant's response was appended to the session transcript — the user's command message was never persisted. When the UI received the `final` chat event and called `loadChatHistory()`, it replaced its local messages with the server transcript, causing the user's command message to disappear. ### Root cause In `src/gateway/server-methods/chat.ts`, the `.then()` handler for the `dispatchInboundMessage` promise (when `!agentRunStarted`) called `appendAssistantTranscriptMessage` for the command reply but never stored the user's input. ### Fix Replace the single `appendAssistantTranscriptMessage` call with a new `appendCommandTranscriptMessages` function that appends **both** the user message and the assistant reply through a single `SessionManager` instance. Using one instance guarantees the `parentId` chain stays intact and both messages are written atomically. ## Test plan - [x] New test `chat.command-user-message.test.ts` verifies that after `chat.send` handles a command without an agent run, the transcript contains both user and assistant messages in correct order - [x] Test fails before the fix (only assistant message in transcript), passes after - [x] `pnpm build` passes - [x] `pnpm check` passes (format, types, lint) - [x] Existing `appendAssistantTranscriptMessage` still used by `chat.inject` — not modified <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR fixes missing persistence of slash-command user messages in the `chat.send` path when no agent run is started. It introduces `appendCommandTranscriptMessages()` in `src/gateway/server-methods/chat.ts` to append both the user’s command message (including parsed image attachments) and the assistant’s final reply to the session transcript using a single `SessionManager` instance, preserving the parentId chain. It also adds a regression test (`src/gateway/server-methods/chat.command-user-message.test.ts`) that simulates a command-only dispatch and asserts that the transcript JSONL contains both the user and assistant messages in the correct order after the `final` broadcast. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk. - Changes are narrowly scoped to the command-only `chat.send` code path, follow the established transcript append pattern via `SessionManager`, and include a regression test exercising the exact bug scenario (user command disappearing after history refresh). No broken integrations or inconsistencies were found after tracing how `chat.history` reads transcript entries and comparing to existing `appendAssistantTranscriptMessage` behavior. - No files require special attention. <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs