mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-22 16:25:58 +00:00
Enable streaming when only streaming.mode is set
- StreamingConfig.from_dict now treats `mode` as an alias for `transport`
that also implies `enabled`, so `streaming: {mode: auto}` turns streaming
on instead of being silently ignored (enabled defaulted to False, which
buffered the whole reply and sent it in one message)
- `mode: off` disables streaming; an explicit `enabled` key still wins; an
explicit `transport` takes precedence over `mode`
- Add regression tests covering mode/transport/enabled precedence and the
real-world `mode + preloader_frames` block
This commit is contained in:
parent
ed3a0b3948
commit
62cdb3e1be
2 changed files with 96 additions and 2 deletions
|
|
@ -717,9 +717,35 @@ class StreamingConfig:
|
|||
def from_dict(cls, data: Dict[str, Any]) -> "StreamingConfig":
|
||||
if not isinstance(data, dict) or not data:
|
||||
return cls()
|
||||
|
||||
# ``mode`` is an ergonomic alias for the transport that ALSO implies
|
||||
# ``enabled``. A config like ``streaming: {mode: auto}`` reads as
|
||||
# "turn streaming on, transport=auto" — matching the natural intent
|
||||
# of someone enabling streaming without also spelling out
|
||||
# ``enabled: true``. Without this, ``mode`` was silently ignored and
|
||||
# streaming stayed disabled (``enabled`` defaults to False), which is
|
||||
# a surprising footgun: the whole reply buffers and sends at once.
|
||||
# ``mode: off`` disables streaming; an explicit ``enabled`` key always
|
||||
# wins so callers can force either state.
|
||||
raw_transport = data.get("transport")
|
||||
raw_mode = data.get("mode")
|
||||
transport = raw_transport if raw_transport is not None else raw_mode
|
||||
if transport is None:
|
||||
transport = "auto"
|
||||
transport = str(transport).strip().lower() or "auto"
|
||||
|
||||
if "enabled" in data:
|
||||
enabled = _coerce_bool(data.get("enabled"), False)
|
||||
elif raw_mode is not None or raw_transport is not None:
|
||||
# A mode/transport was given without an explicit enabled flag:
|
||||
# infer enabled from the transport ("off" = disabled, else on).
|
||||
enabled = transport != "off"
|
||||
else:
|
||||
enabled = False
|
||||
|
||||
return cls(
|
||||
enabled=_coerce_bool(data.get("enabled"), False),
|
||||
transport=data.get("transport", "auto"),
|
||||
enabled=enabled,
|
||||
transport=transport,
|
||||
edit_interval=_coerce_float(
|
||||
data.get("edit_interval"), DEFAULT_STREAMING_EDIT_INTERVAL,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -41,3 +41,71 @@ class TestStreamingConfigNested:
|
|||
})
|
||||
assert cfg.streaming.enabled is True
|
||||
assert cfg.streaming.transport == "edit"
|
||||
|
||||
|
||||
class TestStreamingModeAlias:
|
||||
"""``streaming: {mode: ...}`` is an alias that also implies ``enabled``.
|
||||
|
||||
Regression for a live config footgun: ``streaming: {mode: auto}`` was
|
||||
silently ignored (mode was never read), so streaming stayed disabled and
|
||||
the whole reply buffered before the first Telegram send.
|
||||
"""
|
||||
|
||||
def test_mode_auto_enables_streaming(self):
|
||||
from gateway.config import StreamingConfig
|
||||
|
||||
sc = StreamingConfig.from_dict({"mode": "auto"})
|
||||
assert sc.enabled is True
|
||||
assert sc.transport == "auto"
|
||||
|
||||
def test_mode_edit_enables_streaming(self):
|
||||
from gateway.config import StreamingConfig
|
||||
|
||||
sc = StreamingConfig.from_dict({"mode": "edit"})
|
||||
assert sc.enabled is True
|
||||
assert sc.transport == "edit"
|
||||
|
||||
def test_mode_off_disables_streaming(self):
|
||||
from gateway.config import StreamingConfig
|
||||
|
||||
sc = StreamingConfig.from_dict({"mode": "off"})
|
||||
assert sc.enabled is False
|
||||
assert sc.transport == "off"
|
||||
|
||||
def test_mode_with_extra_keys_still_enables(self):
|
||||
"""Real-world block: mode plus unrelated preloader_frames."""
|
||||
from gateway.config import StreamingConfig
|
||||
|
||||
sc = StreamingConfig.from_dict(
|
||||
{"mode": "auto", "preloader_frames": ["a", "b"]}
|
||||
)
|
||||
assert sc.enabled is True
|
||||
assert sc.transport == "auto"
|
||||
|
||||
def test_explicit_enabled_overrides_mode(self):
|
||||
from gateway.config import StreamingConfig
|
||||
|
||||
sc = StreamingConfig.from_dict({"mode": "auto", "enabled": False})
|
||||
assert sc.enabled is False
|
||||
# transport still resolves from mode
|
||||
assert sc.transport == "auto"
|
||||
|
||||
def test_transport_takes_precedence_over_mode(self):
|
||||
from gateway.config import StreamingConfig
|
||||
|
||||
sc = StreamingConfig.from_dict({"mode": "off", "transport": "draft"})
|
||||
assert sc.transport == "draft"
|
||||
assert sc.enabled is True
|
||||
|
||||
def test_empty_block_stays_disabled(self):
|
||||
from gateway.config import StreamingConfig
|
||||
|
||||
sc = StreamingConfig.from_dict({})
|
||||
assert sc.enabled is False
|
||||
|
||||
def test_transport_only_enables(self):
|
||||
from gateway.config import StreamingConfig
|
||||
|
||||
sc = StreamingConfig.from_dict({"transport": "edit"})
|
||||
assert sc.enabled is True
|
||||
assert sc.transport == "edit"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue