On ACP v2, changing the model of an idle session left the session
reporting `running` with no work in progress, and it never reported
`idle` again until some later turn ended. A client that refuses prompts
while the session is `running` could then never send the prompt that
would end it.
## Cause
After `setModel`, Claude Code echoes a user message that carries only
the local command's output:
```json
{
"type": "user",
"message": {
"role": "user",
"content": "<local-command-stdout>Set model to `haiku (claude-haiku-5-5)`</local-command-stdout>"
},
"parent_tool_use_id": null,
"uuid": "…",
"isReplay": true
}
```
The v2 session read every top-level echo as a prompt that Claude Code
took in, and opened a turn for it. A model change runs no turn: no
`command_lifecycle` frame, `result` or `session_state_changed` follows
the echo, so nothing closed that turn.
Captured against the bundled CLI (adapter 0.104.1): `state_update
running` went out 18 ms after `session/set_config_option`, and no `idle`
followed in the next 75 seconds.
## Fix
An echo whose content is only local command output, and whose uuid is
not one of the session's pending prompts, no longer opens a turn. The
check is `isLocalCommandOutput` in `message-filters.ts`, next to the
helpers that already recognize these markers.
The pending-prompt exception keeps a client's own prompt working with a
CLI that sends no `command_lifecycle` frames, where the echo is the only
sign that the prompt was inserted.
## Scope
- v2 only. The v1 core takes its state from `session_state_changed` and
does not open turns at echoes.
- I captured a model change. Other local commands that Claude Code runs
outside a turn and echoes the same way are covered by the same check,
but I did not capture them.
## Testing
- New case in `src/tests/v2/v2.test.ts` sends the echo as the CLI sent
it. Without the fix it fails with `expected [ 'running' ] to deeply
equal []`.
- Reran the capture against the bundled CLI with the fix: no `running`
after either model change, and the next prompt ran `running` then
`idle`.
- `npm run check` and `npm run test:run` pass.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.