aaif-goose / aaif-goose/goose

ACP: refining tool_call_update is discarded — a running tool call never shows its command

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

Description

**Describe the bug**

ACP agents emit a `tool_call` as soon as a tool starts, while its input is still streaming, and then refine it with a `tool_call_update` carrying the finished `rawInput` and a real `title`. goose surfaces the first notification and ignores the refinement, so a running tool call is displayed with whatever placeholder the pre-refinement notification had — and never gets its command text.

With `claude-acp` this means every shell command in progress renders as an untitled `Terminal` call with no arguments. While a long command runs there is nothing on screen saying what it is. A build, a test run, and a poll loop are indistinguishable from each other and from a hang.

`ToolCallUpdate` in `crates/goose/src/acp/provider.rs` merges only `raw_output` and `content`, and forwards nothing at all until a terminal status arrives:

```rust
SessionUpdate::ToolCallUpdate(update) => {
let id = update.tool_call_id.0.to_string();
// Merge patch-like fields; only emit on terminal status.
let terminal_status = update.fields.status.filter(...);
```

`update.fields.title` and `update.fields.raw_input` are never read. The adapter side is doing its part — claude-agent-acp 0.63.0 documents the contract explicitly:

> The initial `tool_call` carries `status: "pending"` and, for Bash, the `terminal_info` _meta that the later `terminal_output`/`terminal_exit` updates key off of; a refining `tool_call_update` carries neither.

and `streamedInputRefinement` sends `rawInput`, `title`, `kind` and `locations` in that refinement.

---

**To Reproduce**

1. Use the `claude-acp` provider in Desktop.
2. Ask for anything that runs a shell command taking more than a few seconds.
3. While it runs, the call shows as `Terminal` with no command and no description.
4. Only when the command finishes does its description and output appear.

A diagnostics bundle confirms goose never receives the refined values: across 175 messages of one session, every persisted `toolRequest` has `arguments: {}`, and no command text appears anywhere outside tool *results*.

---

**Expected behavior**

A refining `tool_call_update` updates the pending call in place, so its title and input are visible while it runs. Desktop's chat store already handles `tool_call_update` notifications, so the missing link is goose keeping the refinement and forwarding it rather than discarding non-terminal updates.

An alternative shape, if updating an already-emitted `tool_request` is awkward in the agent loop: hold the `tool_call` briefly and emit once the refinement lands, since it follows within milliseconds. That trades a small delay in the "started" indicator for a call that is correct when it appears.

---

**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**

This is what makes a long-running agent turn unreadable: with no visible command, a user cannot tell a slow build from a stuck one. Live output during the call is a separate matter and is not available through this adapter — claude-agent-acp emits `terminal_output` from the `tool_result`, i.e. at completion — but the *title and command* are available at start and are simply being dropped.

Related: #11320 (agent updates arriving outside a prompt are dropped) is a different notification goose receives and discards.

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.