mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-29 06:31:32 +00:00
fix(telegram): default streaming transport to edit
This commit is contained in:
parent
ab11d0998c
commit
7fad501f08
6 changed files with 26 additions and 14 deletions
|
|
@ -358,12 +358,13 @@ class StreamingConfig:
|
|||
# Transport selection:
|
||||
# "auto" — prefer native streaming-draft updates when the platform
|
||||
# supports them (Telegram sendMessageDraft, Bot API 9.5+);
|
||||
# fall back to edit-based when not. Recommended.
|
||||
# fall back to edit-based when not.
|
||||
# "draft" — explicitly request native drafts; falls back to edit when
|
||||
# the platform/chat doesn't support them.
|
||||
# "edit" — progressive editMessageText only (legacy behaviour).
|
||||
# "edit" — progressive editMessageText only (legacy/default
|
||||
# behaviour).
|
||||
# "off" — disable streaming entirely.
|
||||
transport: str = "auto"
|
||||
transport: str = "edit"
|
||||
edit_interval: float = DEFAULT_STREAMING_EDIT_INTERVAL
|
||||
buffer_threshold: int = DEFAULT_STREAMING_BUFFER_THRESHOLD
|
||||
cursor: str = DEFAULT_STREAMING_CURSOR
|
||||
|
|
@ -392,7 +393,7 @@ class StreamingConfig:
|
|||
return cls()
|
||||
return cls(
|
||||
enabled=_coerce_bool(data.get("enabled"), False),
|
||||
transport=data.get("transport", "auto"),
|
||||
transport=data.get("transport", "edit"),
|
||||
edit_interval=_coerce_float(
|
||||
data.get("edit_interval"), DEFAULT_STREAMING_EDIT_INTERVAL,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -14809,7 +14809,7 @@ class GatewayRunner:
|
|||
cursor=_effective_cursor,
|
||||
buffer_only=_buffer_only,
|
||||
fresh_final_after_seconds=_fresh_final_secs,
|
||||
transport=_scfg.transport or "auto",
|
||||
transport=_scfg.transport or "edit",
|
||||
chat_type=getattr(source, "chat_type", "") or "",
|
||||
)
|
||||
_stream_consumer = GatewayStreamConsumer(
|
||||
|
|
@ -15632,7 +15632,7 @@ class GatewayRunner:
|
|||
cursor=_effective_cursor,
|
||||
buffer_only=_buffer_only,
|
||||
fresh_final_after_seconds=_fresh_final_secs,
|
||||
transport=_scfg.transport or "auto",
|
||||
transport=_scfg.transport or "edit",
|
||||
chat_type=getattr(source, "chat_type", "") or "",
|
||||
)
|
||||
_stream_consumer = GatewayStreamConsumer(
|
||||
|
|
|
|||
|
|
@ -65,9 +65,9 @@ class StreamConsumerConfig:
|
|||
# when the adapter + chat supports it; fall back to edit.
|
||||
# "draft" — explicitly request native draft streaming; fall back to
|
||||
# edit when unsupported.
|
||||
# "edit" — progressive editMessageText (legacy behavior).
|
||||
# "edit" — progressive editMessageText (legacy/default behavior).
|
||||
# "off" — handled by the gateway before the consumer is even built.
|
||||
transport: str = "auto"
|
||||
transport: str = "edit"
|
||||
# Hint for the consumer about the originating chat type (e.g. "dm",
|
||||
# "group", "supergroup", "forum"). Used to gate native draft streaming,
|
||||
# which is platform-specific (Telegram drafts are DM-only).
|
||||
|
|
@ -846,7 +846,7 @@ class GatewayStreamConsumer:
|
|||
the chat type (e.g. Telegram drafts are DM-only) and platform-version
|
||||
gates (e.g. python-telegram-bot 22.6+).
|
||||
"""
|
||||
transport = (self.cfg.transport or "auto").lower()
|
||||
transport = (self.cfg.transport or "edit").lower()
|
||||
if transport == "edit":
|
||||
return False
|
||||
# "off" is filtered upstream by the gateway; treat as edit defensively.
|
||||
|
|
|
|||
|
|
@ -164,6 +164,10 @@ class TestSessionResetPolicy:
|
|||
|
||||
|
||||
class TestStreamingConfig:
|
||||
def test_defaults_to_edit_transport(self):
|
||||
restored = StreamingConfig.from_dict({"enabled": "true"})
|
||||
assert restored.transport == "edit"
|
||||
|
||||
def test_from_dict_coerces_quoted_false_enabled(self):
|
||||
restored = StreamingConfig.from_dict({"enabled": "false"})
|
||||
assert restored.enabled is False
|
||||
|
|
|
|||
|
|
@ -80,6 +80,11 @@ def _make_draft_capable_adapter(
|
|||
class TestDraftTransportSelection:
|
||||
"""Verify _resolve_draft_streaming picks the right transport."""
|
||||
|
||||
def test_default_transport_stays_on_edit(self):
|
||||
adapter = _make_draft_capable_adapter()
|
||||
consumer = GatewayStreamConsumer(adapter, "12345", StreamConsumerConfig(chat_type="dm"))
|
||||
assert consumer._resolve_draft_streaming() is False
|
||||
|
||||
def test_auto_dm_with_draft_capable_adapter_picks_draft(self):
|
||||
adapter = _make_draft_capable_adapter()
|
||||
cfg = StreamConsumerConfig(transport="auto", chat_type="dm")
|
||||
|
|
|
|||
|
|
@ -611,7 +611,7 @@ To find a topic's `thread_id`, open the topic in Telegram Web or Desktop and loo
|
|||
|
||||
- **Bot API 9.4 (Feb 2026):** Private Chat Topics — bots can create forum topics in 1-on-1 DM chats via `createForumTopic`. Hermes uses this for two distinct features: operator-curated [Private Chat Topics](#private-chat-topics-bot-api-94) (config-driven, fixed topic list) and user-driven [Multi-session DM mode](#multi-session-dm-mode-topic) (activated by `/topic`, unlimited user-created topics).
|
||||
- **Privacy policy:** Telegram now requires bots to have a privacy policy. Set one via BotFather with `/setprivacy_policy`, or Telegram may auto-generate a placeholder. This is particularly important if your bot is public-facing.
|
||||
- **Bot API 9.5 (Mar 2026): Native streaming via `sendMessageDraft`.** Hermes uses Telegram's native streaming-draft API to render an animated preview of the agent's reply as tokens arrive in private chats. Drops the per-edit jitter you used to see with the legacy `editMessageText` polling path on slow models.
|
||||
- **Bot API 9.5 (Mar 2026): Native streaming via `sendMessageDraft`.** Hermes supports Telegram's native streaming-draft API as an opt-in transport for private chats. The default remains the legacy `editMessageText` path because draft previews can visibly collapse and re-render on some Telegram clients.
|
||||
|
||||
### Streaming transport (`gateway.streaming.transport`)
|
||||
|
||||
|
|
@ -619,9 +619,9 @@ When streaming is enabled (`gateway.streaming.enabled: true`), Hermes picks one
|
|||
|
||||
| Value | Behaviour |
|
||||
|---|---|
|
||||
| `auto` (default) | Native draft streaming on supported chats (currently Telegram DMs); legacy edit-based path otherwise. Falls back gracefully if a draft frame fails. |
|
||||
| `auto` | Native draft streaming on supported chats (currently Telegram DMs); legacy edit-based path otherwise. Falls back gracefully if a draft frame fails. |
|
||||
| `draft` | Force native drafts. Logs a downgrade and falls back to edit if the chat doesn't support drafts (e.g. groups/topics). |
|
||||
| `edit` | Legacy progressive `editMessageText` polling for every chat type. |
|
||||
| `edit` (default) | Legacy progressive `editMessageText` polling for every chat type. |
|
||||
| `off` | Disable streaming entirely (final reply only, no progressive updates). |
|
||||
|
||||
In `~/.hermes/config.yaml`:
|
||||
|
|
@ -630,10 +630,12 @@ In `~/.hermes/config.yaml`:
|
|||
gateway:
|
||||
streaming:
|
||||
enabled: true
|
||||
transport: auto # auto | draft | edit | off
|
||||
transport: edit # edit | auto | draft | off
|
||||
```
|
||||
|
||||
**What you'll see in DMs with `auto` (default)** — when the agent generates a reply, Telegram shows an animated draft preview that updates token-by-token. When the reply finishes, it's delivered as a regular message and the draft preview clears naturally on the client. Drafts have no message id, so the final answer is what stays in your chat history.
|
||||
**What you'll see in DMs with `edit` (default)** — the gateway sends a normal preview message and progressively updates it via `editMessageText`, avoiding Telegram's draft-preview collapse/rollback effect.
|
||||
|
||||
**What you'll see in DMs with `auto` or `draft`** — Telegram shows an animated draft preview that updates token-by-token. When the reply finishes, it's delivered as a regular message and the draft preview clears naturally on the client. Drafts have no message id, so the final answer is what stays in your chat history.
|
||||
|
||||
**What about groups, supergroups, forum topics?** Telegram restricts `sendMessageDraft` to private chats (DMs). The gateway transparently falls back to the edit-based path for everything else — same UX as before.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue