aaif-goose / aaif-goose/goose

ACP: agent updates that arrive outside a prompt are dropped — background-task turns never reach the user

Aperta
#11,320 0 commenti 0 reazioni 1 assegnatario Rivendicata da @alexhancock Vedi su GitHub
Lingua principale
Rust
Stelle
54.2k
Fork
6.2k
Merge medio
3g 2h
PR unite (30g)
262

Descrizione

**Describe the bug**

An ACP backend can send `session/update` notifications when no `session/prompt` is in flight. goose receives them and throws them away, so any work the backend does after the turn it was asked for is lost — silently, apart from a `WARN` line.

This is routine with `claude-acp`. Claude Code answers, ends the turn, and later resumes itself when a backgrounded task completes (a build, a test run) — producing a full turn of text and tool calls that the user asked for and never sees. The session simply stops at "waiting on the build" and nothing more arrives, so it reads as the model hanging.

The drop is in the notification dispatch handler (`crates/goose/src/acp/provider.rs`). `AcpProvider::stream` breaks out of its consumer loop at `AcpUpdate::Complete` and drops the receiver, so a chunk arriving afterwards fails to send and is discarded:

```rust
if let Err(e) = tx.send(AcpUpdate::Text(text)).await {
tracing::warn!(error = %e, "undelivered ACP agent message chunk");
}
```

There is no path in goose for an assistant message that is not a response to a prompt goose sent.

---

**To Reproduce**

1. Configure the `claude-acp` provider and start a session.
2. Ask for something that makes Claude Code start a long task in the background and end its turn — e.g. "kick off a release build in the background and tell me when it finishes".
3. The turn ends with a message like "I'll report when it finishes".
4. When the build finishes, Claude Code produces its report. Nothing appears in goose.
5. `~/.local/state/goose/logs/cli//*.log` shows one `undelivered ACP agent message chunk` warning per lost chunk.

The backend's own transcript (`~/.claude/projects//*.jsonl`) contains the complete lost turn, which is how I confirmed the content exists and only goose discards it.

---

**Expected behavior**

Updates that arrive for the active session outside a prompt are surfaced as a new assistant message: persisted to the session and pushed to the UI, so the session shows the late turn as it arrives.

`set_session_title_callback` is the existing precedent for a provider pushing something into the session outside the reply stream — the same shape would work here:

- a `Provider` hook alongside `set_session_title_callback` in `crates/goose-provider-types/src/base.rs`
- the ACP provider routing `Text`/`Thought`/tool-call updates to it when no turn is live, instead of warning and dropping
- `Agent::update_provider` persisting the message and emitting it on the session update channel
- a notifier in `crates/goose/src/acp/server.rs` alongside `spawn_session_name_update_notifier` to send `agent_message_chunk` to Desktop

Whatever the mechanism, the requirement is that goose stop discarding content it has already received.

---

**Please provide the following information**
- **OS & Arch:** macOS 26.6.1 arm64
- **Interface:** UI (Desktop)
- **Version:** v2.0-rc-04-27-0 (desktop 1.45.0)
- **Extensions enabled:** developer, context7, playwright, goose docs
- **Provider & Model:** claude-acp — claude-agent-acp 0.63.0 — claude-opus-5

---

**Additional context**

Evidence from a diagnostics bundle for one affected session: the goose transcript's last message is `"Waiting on just make-ui ... I'll report as soon as it lands."`, and the log carries twelve `undelivered ACP agent message chunk` warnings over the following six seconds — the whole report turn, dropped chunk by chunk.

The warning itself only exists because of the fix for #11178, which keeps `prompt_response_tx` registered past the prompt response; before that the drop was completely silent. That fix is about chunks racing the *end* of a turn, and its bounded grace window is deliberately short. This is the separate case of chunks belonging to no turn at all, which no grace window can cover.

Related but distinct: #10433 (a dropped MCP `notifications/tools/list_changed`) is the same class of defect — a notification goose receives and discards — on a different channel.

Guida per i contributori

Apri la guida per i contributori

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.