mirror of
https://github.com/nesquena/hermes-webui.git
synced 2026-05-22 10:20:14 +00:00
78 lines
2.9 KiB
Python
78 lines
2.9 KiB
Python
"""
|
|
Shared helpers for session compression anchor metadata.
|
|
"""
|
|
|
|
|
|
def _content_text(content, *, part_types):
|
|
if isinstance(content, list):
|
|
return "\n".join(
|
|
str(part.get("text") or part.get("content") or "")
|
|
for part in content
|
|
if isinstance(part, dict) and part.get("type") in part_types
|
|
).strip()
|
|
return str(content or "").strip()
|
|
|
|
|
|
def _content_has_part_type(content, part_types):
|
|
if not isinstance(content, list):
|
|
return False
|
|
return any(
|
|
isinstance(part, dict) and part.get("type") in part_types
|
|
for part in content
|
|
)
|
|
|
|
|
|
def visible_messages_for_anchor(messages, *, auto_compression: bool = False):
|
|
"""Return transcript messages that can anchor compression UI metadata.
|
|
|
|
Manual compression historically only counted plain ``text`` content parts
|
|
for non-assistant messages, while the streaming auto-compression path also
|
|
accepted provider-style ``input_text`` / ``output_text`` parts and metadata
|
|
markers on any non-tool role. Keep that difference explicit at the call site
|
|
instead of carrying two near-identical helper implementations.
|
|
"""
|
|
out = []
|
|
text_part_types = {"text", "input_text", "output_text"} if auto_compression else {"text"}
|
|
for message in messages or []:
|
|
if not isinstance(message, dict):
|
|
continue
|
|
role = message.get("role")
|
|
if not role or role == "tool":
|
|
continue
|
|
|
|
content = message.get("content", "")
|
|
has_attachments = bool(message.get("attachments"))
|
|
text = _content_text(content, part_types=text_part_types)
|
|
|
|
if auto_compression:
|
|
has_tool_calls = bool(
|
|
isinstance(message.get("tool_calls"), list) and message.get("tool_calls")
|
|
)
|
|
has_tool_use = _content_has_part_type(content, {"tool_use"})
|
|
has_reasoning = bool(message.get("reasoning"))
|
|
if not text:
|
|
has_reasoning = has_reasoning or _content_has_part_type(
|
|
content,
|
|
{"thinking", "reasoning"},
|
|
)
|
|
if text or has_attachments or has_tool_calls or has_tool_use or has_reasoning:
|
|
out.append(message)
|
|
continue
|
|
|
|
if role == "assistant":
|
|
has_tool_calls = bool(
|
|
isinstance(message.get("tool_calls"), list) and message.get("tool_calls")
|
|
)
|
|
has_tool_use = _content_has_part_type(content, {"tool_use"})
|
|
has_reasoning = bool(message.get("reasoning")) or _content_has_part_type(
|
|
content,
|
|
{"thinking", "reasoning"},
|
|
)
|
|
if text or has_attachments or has_tool_calls or has_tool_use or has_reasoning:
|
|
out.append(message)
|
|
continue
|
|
|
|
if text or has_attachments:
|
|
out.append(message)
|
|
return out
|