mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-11-06 13:26:40 +00:00
The profile switch reached every turn the gateway ran, so turning it on in Desktop also sent Daybreak on that profile's Telegram, Discord and Slack chats. OpenAI allows Daybreak no third-party or downstream access, and a bot's chats can be other people. - gateway: _load_daybreak(source) is true only for Platform.LOCAL turns (Desktop, TUI, CLI). - standalone hermes serve: agents built for a non-local source (a plugin session tagged telegram) never carry it, and a live flip skips them (agent.session_source.DAYBREAK_SOURCES). - docs: say who gets it and why messaging chats don't. Co-authored-by: BearHuddleston <196404565+BearHuddleston@users.noreply.github.com>
62 lines
3.3 KiB
Python
62 lines
3.3 KiB
Python
"""Session source vocabulary: the ``source`` label a session row carries, and which sources have a
|
|
person reading the turn as it runs. A leaf (its one import is the stdlib-only session context), so
|
|
the ``run_agent`` facade and its siblings import it directly."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Optional
|
|
|
|
from gateway.session_context import get_session_env
|
|
|
|
# Sources that label the human conversation an interactive UI transport hosts. A finite ``hermes chat -q`` /
|
|
# one-shot child spawned from such a session inherits HERMES_SESSION_SOURCE (the terminal tool bridges the
|
|
# session env into child processes) but is NOT that conversation: labelling it ``tui``/``desktop`` lists it
|
|
# in the TUI/WebUI pickers as a resumable chat and lets ``hermes -c`` in the TUI continue it (#112550).
|
|
# Automation sources (tool, a2a, ...) are inherited on purpose; a Kanban worker's descendants drop its
|
|
# gateway-only ``kanban`` label (delegation_context.scrub_kanban_env).
|
|
UI_TRANSPORT_SOURCES = frozenset({"tui", "desktop"})
|
|
|
|
# Finite non-interactive CLI runs (``hermes chat -q``/``--oneshot``, ``hermes -z``) get their own source so human
|
|
# pickers hide them without title/cwd heuristics; ``hermes -c`` still treats them as CLI history.
|
|
ONESHOT_SOURCE = "oneshot"
|
|
CLI_FAMILY_SOURCES = frozenset({"cli", ONESHOT_SOURCE})
|
|
|
|
# The owner's own local surfaces: the only sources that carry OpenAI Daybreak (agent.daybreak). It is the
|
|
# approved account's own access (no third-party or downstream use); a plugin session tagged ``telegram`` is
|
|
# someone else's chat even when a local backend builds its agent.
|
|
DAYBREAK_SOURCES = UI_TRANSPORT_SOURCES | {"cli"}
|
|
|
|
# A person reads the turn as it runs: not cron, batch, a messaging chat, or a one-shot run.
|
|
ATTENDED_SOURCES = UI_TRANSPORT_SOURCES | {"cli", "acp"}
|
|
|
|
|
|
def create_surface(source: str) -> str:
|
|
"""The ``session.create`` label for a session source: ``desktop`` is the Desktop's platform name for
|
|
the ``gui`` surface (gateway.session_policy.SURFACES), which the create contract does not list."""
|
|
return "gui" if source == "desktop" else source
|
|
|
|
|
|
def session_source_for(platform: Optional[str]) -> str:
|
|
source = str(get_session_env("HERMES_SESSION_SOURCE", "") or "").strip()
|
|
single_query = get_session_env("HERMES_SINGLE_QUERY_SESSION", "") == "1"
|
|
explicit = get_session_env("HERMES_SESSION_SOURCE_EXPLICIT", "") == "1"
|
|
if single_query and not explicit and source in UI_TRANSPORT_SOURCES:
|
|
source = ""
|
|
if single_query and not source and (platform or "cli") == "cli":
|
|
return ONESHOT_SOURCE
|
|
return source or platform or "cli"
|
|
|
|
|
|
def is_attended(agent: Any) -> bool:
|
|
"""A delegated child answers its parent, not a person, though its copied context still carries
|
|
the parent's source; a library caller (no platform) has no one reading either."""
|
|
platform = getattr(agent, "platform", None)
|
|
if not platform or platform == "subagent":
|
|
return False
|
|
# A gateway-admitted ``hermes chat -q`` / ``-z`` turn carries its one-shot fact on the admission,
|
|
# not in HERMES_SINGLE_QUERY_SESSION (the daemon never had that env).
|
|
from gateway.session_finite import finite_turn_required
|
|
if finite_turn_required() is True:
|
|
return False
|
|
return session_source_for(platform) in ATTENDED_SOURCES
|