feat(chat): show live background tasks under the composer
Renders the AIR async-task channel as a strip docked beside the session-failure banner: one row per running or paused task, with the tool it last ran, its token cost, a link to its output file, and a stop button. Only non-terminal tasks show. A settled task leaves at once — its outcome belongs to the transcript, and a permanent list of finished jobs under the composer would grow all session. The reducer still keeps the settled row, since the adapter goes on revising it. The reducer mirrors the backend merge (partial deltas, absent means unchanged, only a spawn frame creates), and hydrates whole rows from the snapshot so a client attaching mid-episode learns about work already running. Two affordances are gated on being able to honour them: the stop button needs a live owned connection, and the output link needs a local desktop window — `openPath` silently no-ops in web and remote-desktop windows, where the path belongs to another host. A declined stop is surfaced, because a successful one announces itself by the row disappearing and silence would look identical to a click that did nothing.
X
xintaofei committed
6a0a79d438a45b3c008a7c8b8d5277aa9f200234
Parent: 52818ca