Auto-threading, history pagination, streaming toggle + tool/reasoning display settings

- Auto-threading (Telegram topic-mode workflow): message.send {auto_thread}
  mints a fresh AI-named thread (instant derived title, LLM upgrade via
  channel.renamed); channel.created {auto:true}; the app jumps into the new
  thread and relocates the optimistic pending bubble.
- history frame: paged full message history for initial channel open /
  scroll-up pagination (reconstructed from the outbox log).
- Streaming on/off: gateway side (display.platforms.android.streaming) plus a
  per-device app toggle (Settings → Streaming); reasoning/model/tokens carried
  on message frames.
- Context menu: long-press (touch) / right-click (desktop) thread affordances
  via a KMP rightClick expect/actual.
- Settings → Reasoning: auto-collapse long reasoning blocks (default on).
- Tool detail: the gateway now always supplies full tool data — it forces
  verbose tool progress (full args → tool.start.args) and captures each
  completed call via the post_tool_call hook (output/duration/ok → tool.end).
  The app reveals the full call + output on expand (Truncated) and
  auto-expands cards in Everything mode.
This commit is contained in:
ARIA committed 2026-08-20 16:26:52 +02:00
1 parent e678caafdc
commit efecf2732e
24 files changed
+1115 -81

No files matched your search

+31
View File
@@ -45,6 +45,34 @@ gateway identity concepts**.
- The gateway's `create_handoff_thread` is used where hermes wants to open a
named thread (e.g. continuable cron).
### 6.3.1 Auto-threading (Telegram topic-mode workflow)
With **Threads ON**, a message sent in a channel's flat lane (no active
thread) gets its **own fresh thread**, the way Telegram topic mode mints a
topic per new conversation — and the **AI names it** instead of the user:
1. The app sends `message.send {…, auto_thread:true}` (only from a flat lane,
with non-empty text, never for slash commands).
2. The gateway mints a thread (`channel.create`-equivalent, `kind:thread`)
under the channel, **named instantly** from the user's opening message via
hermes' session-title derivation (`agent/title_generator.derive_title` —
a deterministic slice of the user's own words, no model call), and
broadcasts `channel.created {auto:true}`.
3. The user echo, the agent turn, and all streaming frames carry the new
`thread_id` — the whole conversation lives in the thread.
4. In the background, the gateway upgrades the name with the model's title
(`agent/title_generator.generate_title`, the `title_generation` auxiliary
task) and broadcasts `channel.renamed`. This is hermes' two-stage session
titling (derived < llm < user) applied to the thread name; failures leave
the derived name in place.
App side: on `channel.created {auto:true}` under the flat lane it is viewing,
the app **jumps into the new thread** and relocates the optimistic pending
bubble from the flat lane into it (the echo arrives in the thread lane).
Follow-ups sent inside the thread stay there; the next flat-lane message
starts another thread. Media-only sends and slash commands stay in the flat
lane (nothing to title / session-scoped, not conversation starters).
## 6.4 User-created channels (for cron delegation)
- **Requirement:** the user creates new channels so **cron job outputs can be
@@ -55,6 +83,9 @@ gateway identity concepts**.
- **`channel.rename` / `channel.set_default` / `channel.delete`** manage the
directory (rename broadcasts `channel.renamed`; delete is soft — marks
archived, keeps history for search).
- **App affordance for threads:** long-press (touch) / right-click (desktop) a
topic chip → "Rename" (`channel.rename`) or "Delete" (`channel.delete`).
Deleting the open thread falls the app back to the channel's flat lane.
- **Cron targeting** (the key payoff): because the plugin registers
`parse_target_ref_fn` and `cron_deliver_env_var`, cron jobs and the
`send_message` tool can target any channel/thread: