Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
"""Gateway response filtering helpers.
|
||||
|
||||
These helpers operate at the gateway boundary: they decide whether a completed
|
||||
agent turn should be delivered to the chat, not what should be persisted in the
|
||||
conversation history.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import unicodedata
|
||||
from typing import Any
|
||||
|
||||
# Canonical model-emitted control token for intentional silence.
|
||||
SILENT_REPLY_TOKEN = "NO_REPLY"
|
||||
|
||||
# Exact whole-response markers that mean "the agent intentionally chose not to
|
||||
# reply". Keep this list small and explicit; arbitrary empty output remains an
|
||||
# error/empty-response path, not silence.
|
||||
LIVE_GATEWAY_SILENT_MARKERS = frozenset({
|
||||
"[SILENT]",
|
||||
"SILENT",
|
||||
"NO_REPLY",
|
||||
"NO REPLY",
|
||||
})
|
||||
|
||||
|
||||
def _canonical_silence_candidate(text: str) -> str:
|
||||
return " ".join(text.strip().upper().split())
|
||||
|
||||
|
||||
def _strip_edge_silence_punctuation(text: str) -> str:
|
||||
"""Strip stray edge punctuation without erasing marker structure.
|
||||
|
||||
Models sometimes emit ``.NO_REPLY`` or ``*NO_REPLY*`` instead of the exact
|
||||
marker. Keep square brackets structural so malformed ``[SILENT`` does not
|
||||
become ``SILENT``.
|
||||
"""
|
||||
start = 0
|
||||
end = len(text)
|
||||
while start < end and text[start] not in "[]" and unicodedata.category(text[start]).startswith("P"):
|
||||
start += 1
|
||||
while end > start and text[end - 1] not in "[]" and unicodedata.category(text[end - 1]).startswith("P"):
|
||||
end -= 1
|
||||
return text[start:end].strip()
|
||||
|
||||
|
||||
def _canonical_silence_candidates(text: str) -> tuple[str, ...]:
|
||||
exact = _canonical_silence_candidate(text)
|
||||
stripped = _strip_edge_silence_punctuation(text.strip())
|
||||
if stripped == text.strip():
|
||||
return (exact,)
|
||||
fallback = _canonical_silence_candidate(stripped)
|
||||
return (exact, fallback)
|
||||
|
||||
|
||||
def is_intentional_silence_response(response: Any) -> bool:
|
||||
"""Return True only when ``response`` is exactly a silence marker.
|
||||
|
||||
Substantive prose that merely mentions ``NO_REPLY`` or ``[SILENT]`` must be
|
||||
delivered normally. A blank response is also not silence; blank output is
|
||||
handled by the empty-response failure path.
|
||||
"""
|
||||
if not isinstance(response, str):
|
||||
return False
|
||||
stripped = response.strip()
|
||||
if not stripped:
|
||||
return False
|
||||
if len(stripped) > 64:
|
||||
return False
|
||||
return any(candidate in LIVE_GATEWAY_SILENT_MARKERS for candidate in _canonical_silence_candidates(stripped))
|
||||
|
||||
|
||||
def is_autonomous_silence_response(response: Any) -> bool:
|
||||
"""Loose silence matcher for autonomous lanes (cron, webhook).
|
||||
|
||||
Autonomous lanes instruct the agent to emit ``[SILENT]`` when a tick
|
||||
produced nothing worth a human's attention, and models reliably bracket
|
||||
the marker with a short note explaining why they stayed quiet. Unlike
|
||||
:func:`is_intentional_silence_response` (the interactive-chat rule, which
|
||||
demands the response be EXACTLY a marker), this suppresses when a marker
|
||||
is the whole response, sits on its own first or last line, or the
|
||||
bracketed sentinel opens the response (the documented
|
||||
``[SILENT] No changes detected`` pattern). A token buried mid-sentence
|
||||
in a genuine report is still delivered.
|
||||
|
||||
Shares :data:`LIVE_GATEWAY_SILENT_MARKERS` so the interactive and
|
||||
autonomous marker sets can never drift apart.
|
||||
"""
|
||||
if not isinstance(response, str):
|
||||
return False
|
||||
stripped = response.strip()
|
||||
if not stripped:
|
||||
return False
|
||||
|
||||
def _is_token(line: str) -> bool:
|
||||
return _canonical_silence_candidate(line) in LIVE_GATEWAY_SILENT_MARKERS
|
||||
|
||||
# Whole response is exactly a token.
|
||||
if _is_token(stripped):
|
||||
return True
|
||||
# Marker on its own first or last line (leading/trailing note on a
|
||||
# separate line — e.g. "2 deals filtered\n\n[SILENT]").
|
||||
lines = [ln for ln in stripped.splitlines() if ln.strip()]
|
||||
if lines and (_is_token(lines[0]) or _is_token(lines[-1])):
|
||||
return True
|
||||
# Bracketed sentinel used as a same-line prefix — the documented pattern
|
||||
# "[SILENT] No changes detected". Restricted to the bracketed form so a
|
||||
# bare word like "Silent retry succeeded" is NOT swallowed.
|
||||
if stripped.upper().startswith("[SILENT]"):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def is_intentional_silence_agent_result(agent_result: dict | None, response: Any) -> bool:
|
||||
"""Silence markers suppress delivery only for successful agent turns."""
|
||||
if not isinstance(agent_result, dict):
|
||||
return False
|
||||
if agent_result.get("failed"):
|
||||
return False
|
||||
return is_intentional_silence_response(response)
|
||||
|
||||
|
||||
def is_partial_silence_marker(text: Any) -> bool:
|
||||
"""Return True while ``text`` could still resolve to a silence marker.
|
||||
|
||||
The streaming path accumulates the reply delta-by-delta and must decide,
|
||||
before the whole response is known, whether to show what it has so far.
|
||||
A buffer whose canonical form is a non-empty *prefix* of a silence marker
|
||||
(e.g. ``"NO"`` on the way to ``"NO_REPLY"``, or an exact marker that has
|
||||
not yet been terminated by stream-end) is held back so a raw marker is
|
||||
never edited onto the screen and then belatedly retracted.
|
||||
|
||||
Anything that has already diverged from every marker (ordinary prose) —
|
||||
and anything longer than the marker cap — returns False so normal
|
||||
streaming resumes immediately. This is the streaming counterpart to
|
||||
:func:`is_intentional_silence_response`, sharing the same marker set and
|
||||
canonicalization so the two never drift.
|
||||
"""
|
||||
if not isinstance(text, str):
|
||||
return False
|
||||
stripped = text.strip()
|
||||
if not stripped or len(stripped) > 64:
|
||||
return False
|
||||
for candidate in _canonical_silence_candidates(stripped):
|
||||
if candidate and any(marker.startswith(candidate) for marker in LIVE_GATEWAY_SILENT_MARKERS):
|
||||
return True
|
||||
return False
|
||||
Reference in New Issue
Block a user