aaif-goose / aaif-goose/goose

Desktop shows a slash-command message twice (agent echoes the prompt into the ACP stream)

Open
#11,670 2 comments 0 reactions 2 assignees Claimed by @alexhancock View on GitHub
Dominant language
Rust
Stars
54.2k
Forks
6.2k
Avg merge
3d 2h
Merged PRs (30d)
262

Description

## Summary

In the desktop app, sending any slash command (`/plan ...`, `/goal ...`, `/summarize`, ...) shows the user's message twice in the thread.

- On builds before #10716 the two copies are glued into one user bubble with no separator, e.g. `/plan add tests/plan add tests`.
- On current `main` (after #10716) the echo carries a server-generated id, so it renders as a second, identical user bubble directly under the first.

Plain (non-slash) messages are not affected.

## Root cause

1. Every slash-command branch in `Agent::reply_impl` yields the user's own prompt back into the reply stream: `command_preamble = vec![AgentEvent::Message(user_message.clone()), ...]` and `yield AgentEvent::Message(user_message)` in `crates/goose/src/agents/agent.rs`. The normal prompt path never does this.
2. The ACP server forwards that message as a `user_message_chunk` (`handle_message_content` in `crates/goose/src/acp/server.rs`). Since #10716 the chunk carries the generated message id; before that it had none.
3. The desktop already appended the typed message to the store with a local id before calling `session/prompt` (`useChatSession.ts`). In `applyContentChunk` (`ui/desktop/src/acp/adapter/messages.ts`):
- an id-less user chunk resolves to `lastMergeableMessageWithRole(state, 'user')`, i.e. the local message, and `lastContent.text += content.text` doubles the text;
- a chunk with an unknown id is not adopted by the local message (it already has an id), so a new user message is pushed.

## Proposed fix

Client side, in `applyContentChunk`: ignore a non-steer `user_message_chunk` whose text equals the single text block of the last locally rendered user message. This covers both the id-less and the server-id shapes, leaves steer confirmation untouched (steer chunks are reconciled by id and replace text rather than append), and keeps the agent stream unchanged for the CLI and other ACP clients.

Removing the echo on the agent side would also fix it but changes what the CLI and third-party ACP clients receive, so it seems better handled separately (see #9261 for the structured-lifecycle direction).

## Verification plan

- Unit tests in `sessionNotificationAdapter.test.ts`: the echo is dropped in both shapes, a following agent chunk still lands as a separate message, and a genuine id-less user delta still merges.
- Manual: send `/plan add tests` in the desktop; the command appears once.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.