Repository navigation
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/server
Steps to reproduce
- Use a thread on the pi adapter (not a Claude thread), with Settings › General › Follow-up behavior set to Steer.
- Let the agent start a foreground Bash tool call that blocks for minutes — in my case a poll loop of the shape
sleep 540; date -u; <poll command>. - While that call is still blocked, send a follow-up (text plus an image).
- Watch the thread until the blocked command returns.
Expected behavior
Either of these would be enough:
- Until the agent has actually taken the message, say so — e.g. the marker reads "waiting for the agent to read this", and only flips to "Steered the active turn" once it has been read. Right now the marker means "offered", not "delivered".
- Keep the blocked command looking alive (elapsed time, a heartbeat, partial stdout), so "my message is waiting behind a command" can be told apart from "the thread is hung".
Actual behavior
The message is marked steered immediately, and the thread then emits nothing at all until the blocked command returns. Event log for the thread (relative clock, t+0 = the send):
t+0:00.0 send: text + image. A foreground Bash call is already blocked
(`sleep 540; date -u; <poll command>`).
t+0:05.1 server creates a run for the message, then cancels it before start
(status=cancelled, startedAt=null) and re-attaches the message to
the live run as a steered user_message turn item, written with
status=completed.
t+0:05.1 → t+1:38.8 zero events for this thread. 93.7 s of nothing.
t+1:38.8 the blocked command returns; command_execution starts streaming.
t+2:17.1 one short follow-up command completes.
t+2:42.5 assistant reply that reads the steer (same run).
t+2:52.4 run completes.
So the message does land — 2 m 42 s after it was sent, at the next step boundary. What is missing is any state between "offered" and "read". From the outside the thread is indistinguishable from a hung session, and the natural reaction is Stop + resend, which drops the unread steer (#15708) — that is how the duplicate sends in this thread started.
On the pi adapter I could not find a delivery/acknowledgement event for the steer at all: the only trace is the user_message turn item, which is completed at offer time, before the model has seen it. This looks like the pi-side counterpart of #23948, whose diagnosis is Claude-specific (tool_progress heartbeats stop after a priority: "now" offer), so it does not explain the pi path.
Impact
Major degradation or frequent failure
Version or commit
T3 Code desktop 0.1.7 (Beta), Windows x64; server 0.1.7.
Environment
Windows x64 desktop app; pi adapter with a third-party OpenAI-compatible model configured as a provider instance (not Claude, Codex, Cursor or Grok); Follow-up behavior = Steer. The normal working pattern here is sleep-then-poll Bash loops, so multi-minute blocked tool calls are routine rather than pathological.
Logs or stack traces
blocked call sleep 540; date -u; <poll command> ~9 min
next call date -u; <inspect command> ~2 sNo stack traces: the timeline above is the whole signal. Workspace paths, repository names and command bodies are redacted.
Related observation (possibly a separate bug)
In the same thread an earlier turn ran 83 minutes. Sends during it resolved two different ways: three became runs that were created and stayed queued (the oldest was still queued 80 minutes later, so it will execute long after it was written), while other sends in the same window were folded into the live turn as steers. Both paths coexisting in one thread may be #23271 / #23403.
Workaround
None clean. Pressing Stop ends the blocked turn and lets the next turn start, but drops the unread steer (#15708). Switching Follow-up behavior to Queue gives each send its own run, but the send then waits for the whole turn — 83 minutes, in the case above.
Activity