Live agent todo list: compact scrollable strip above the composer
CI / Gateway plugin tests (push) Successful in 5m5s
CI / Kotlin tests (android host + desktop) (push) Successful in 6m47s

Add a todo.update frame (server->app) carrying the agent's full current
todo list. The gateway emits it whenever the hermes todo tool completes
(the tool result is authoritative even for merge writes) and re-sends a
snapshot right after hello so a reconnecting device re-learns the plan.
Ephemeral: never outboxed.

The app renders it as a compact strip above the composer (max 3 lines,
the rest scrollable) mirroring the hermes desktop composer status stack:
pending = hollow ring, in_progress = spinner, completed = green check,
cancelled = struck through. It auto-scrolls to the current task whenever
the active task changes, and hides itself once the list is empty or fully
resolved.
This commit is contained in:
ARIA committed 2026-08-23 00:23:02 +02:00
1 parent 1ff2ef380c
commit 742916903b
10 files changed
+447 -3

No files matched your search

+25
View File
@@ -140,6 +140,31 @@ short tail (full output is not streamed — it lives in agent history).
`emoji` — e.g. `read_file` 📖, `write_file` ✍️, `terminal` 💻). Omitted when
the tool is unknown, so the app falls back to its own default glyph.
### `todo.update`
The agent's **full current todo list** for a chat/thread lane (last-write-wins).
Emitted whenever the `todo` tool completes — the tool *result* is the
authoritative list, which also covers `merge` writes (whose args carry only
the changed items) and read-only calls — and, as a **snapshot**, right after
`hello` when a device opens its event stream.
```json
{"type":"todo.update","chat_id":"default","thread_id":null,"payload":{
"todos":[
{"id":"1","content":"Scaffold the module","status":"completed"},
{"id":"2","content":"Wire the store","status":"in_progress"},
{"id":"3","content":"Add tests","status":"pending"}
]}}
```
`status` is one of `pending | in_progress | completed | cancelled`. The frame
is **ephemeral**: it is never outboxed, so a reconnecting device learns the
current list from the snapshot (not a replay), and a gateway restart drops it
(the agent re-emits on the next `todo` call). The app renders it as a compact
scrollable strip above the composer (max 3 lines; auto-scrolls to the item
whose status just changed) and hides it once the list is empty or fully
resolved.
### `typing` / `typing.stop`
```json