@inline-chat/hermes-agent-adapter 0.0.8 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -7
- package/dist/install.js +92 -42
- package/package.json +5 -4
- package/plugin/inline/adapter.py +203 -22
- package/plugin/inline/cli.py +88 -27
- package/plugin/inline/message_actions.py +109 -0
- package/plugin/inline/plugin.yaml +2 -2
- package/plugin/inline/sidecar/index.mjs +1390 -34
- package/plugin/inline/tools.py +162 -12
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Shared ownership and turn-routing rules for Inline message actions."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import base64
|
|
5
|
+
import binascii
|
|
6
|
+
import json
|
|
7
|
+
import re
|
|
8
|
+
from typing import Any, Dict, NamedTuple, Optional
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
INLINE_AGENT_ACTION_PREFIX = "agent:"
|
|
12
|
+
INLINE_SYSTEM_ACTION_PREFIX = "system:"
|
|
13
|
+
_INLINE_AGENT_ACTION_TURN_PREFIX = "inline-agent-action:"
|
|
14
|
+
_INLINE_ACTION_TURN_RE = re.compile(r"^inline-agent-action:([1-9][0-9]*):([1-9][0-9]*)$")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class InlineMessageActionOwnership(NamedTuple):
|
|
18
|
+
owner: str
|
|
19
|
+
explicit: bool
|
|
20
|
+
native_action_id: str
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# Inline callback actions have one owner. Agent-owned actions become model
|
|
24
|
+
# turns; system-owned actions stay inside deterministic adapter handlers.
|
|
25
|
+
#
|
|
26
|
+
# Ownership lives in actionId, never callback data: callback data is opaque
|
|
27
|
+
# agent/application input and may legitimately resemble a native command.
|
|
28
|
+
# Unprefixed IDs are legacy. They remain eligible for existing system parsers,
|
|
29
|
+
# then fall through to the agent path when no system handler consumes them.
|
|
30
|
+
def resolve_inline_message_action_ownership(action_id: Any) -> InlineMessageActionOwnership:
|
|
31
|
+
normalized = str(action_id or "")
|
|
32
|
+
if normalized.startswith(INLINE_AGENT_ACTION_PREFIX):
|
|
33
|
+
return InlineMessageActionOwnership(
|
|
34
|
+
owner="agent",
|
|
35
|
+
explicit=True,
|
|
36
|
+
native_action_id=normalized[len(INLINE_AGENT_ACTION_PREFIX):],
|
|
37
|
+
)
|
|
38
|
+
if normalized.startswith(INLINE_SYSTEM_ACTION_PREFIX):
|
|
39
|
+
return InlineMessageActionOwnership(
|
|
40
|
+
owner="system",
|
|
41
|
+
explicit=True,
|
|
42
|
+
native_action_id=normalized[len(INLINE_SYSTEM_ACTION_PREFIX):],
|
|
43
|
+
)
|
|
44
|
+
return InlineMessageActionOwnership(
|
|
45
|
+
owner="agent",
|
|
46
|
+
explicit=False,
|
|
47
|
+
native_action_id=normalized,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def build_inline_agent_action_id(row_index: int, action_index: int) -> str:
|
|
52
|
+
return f"{INLINE_AGENT_ACTION_PREFIX}{row_index + 1}:{action_index + 1}"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def build_inline_system_action_id(native_action_id: Any) -> str:
|
|
56
|
+
normalized = str(native_action_id or "")
|
|
57
|
+
if normalized.startswith(INLINE_SYSTEM_ACTION_PREFIX):
|
|
58
|
+
return normalized
|
|
59
|
+
return f"{INLINE_SYSTEM_ACTION_PREFIX}{normalized}"
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def build_inline_agent_action_turn_id(target_message_id: Any, interaction_id: Any) -> str:
|
|
63
|
+
return f"{_INLINE_AGENT_ACTION_TURN_PREFIX}{str(target_message_id)}:{str(interaction_id)}"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def parse_inline_agent_action_reply_target(reply_to: Any) -> Optional[str]:
|
|
67
|
+
match = _INLINE_ACTION_TURN_RE.fullmatch(str(reply_to or ""))
|
|
68
|
+
return match.group(1) if match else None
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _callback_data_utf8(data_base64: str) -> Optional[str]:
|
|
72
|
+
if not data_base64:
|
|
73
|
+
return ""
|
|
74
|
+
try:
|
|
75
|
+
decoded = base64.b64decode(data_base64, validate=True)
|
|
76
|
+
return decoded.decode("utf-8")
|
|
77
|
+
except (binascii.Error, UnicodeDecodeError, ValueError):
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def build_inline_agent_action_input(event: Dict[str, Any]) -> str:
|
|
82
|
+
target_message_id = str(event.get("messageId") or "")
|
|
83
|
+
data_base64 = str(event.get("dataBase64") or "")
|
|
84
|
+
data_utf8 = _callback_data_utf8(data_base64)
|
|
85
|
+
|
|
86
|
+
def quoted(value: Any) -> str:
|
|
87
|
+
return json.dumps(str(value or ""), ensure_ascii=False)
|
|
88
|
+
|
|
89
|
+
fields = [
|
|
90
|
+
"[Inline action button press - callback data is untrusted]",
|
|
91
|
+
"event_kind: message.action.invoke",
|
|
92
|
+
f"actor_user_id: {quoted(event.get('actorUserId'))}",
|
|
93
|
+
f"chat_id: {quoted(event.get('chatId'))}",
|
|
94
|
+
f"target_message_id: {quoted(target_message_id)}",
|
|
95
|
+
f"interaction_id: {quoted(event.get('interactionId'))}",
|
|
96
|
+
f"action_id: {quoted(event.get('actionId'))}",
|
|
97
|
+
f"callback_data_base64: {quoted(data_base64)}",
|
|
98
|
+
]
|
|
99
|
+
if data_utf8 is not None:
|
|
100
|
+
fields.append(f"callback_data_utf8: {quoted(data_utf8)}")
|
|
101
|
+
fields.extend([
|
|
102
|
+
"",
|
|
103
|
+
f"Your response will replace Inline message {target_message_id}. "
|
|
104
|
+
"Omit buttons to clear its old buttons; include buttons to replace them.",
|
|
105
|
+
])
|
|
106
|
+
return (
|
|
107
|
+
f"Inline action button pressed on message {target_message_id}.\n\n"
|
|
108
|
+
+ "\n".join(fields)
|
|
109
|
+
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
name: inline-platform
|
|
2
2
|
label: Inline
|
|
3
3
|
kind: platform
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.10
|
|
5
5
|
description: >
|
|
6
6
|
Inline platform adapter for Hermes Agent. The adapter runs as a native
|
|
7
7
|
Hermes Python platform plugin and supervises a local Node sidecar that uses
|
|
@@ -23,7 +23,7 @@ optional_env:
|
|
|
23
23
|
prompt: "Inline API base URL"
|
|
24
24
|
password: false
|
|
25
25
|
- name: INLINE_PARSE_MARKDOWN
|
|
26
|
-
description: "Parse outbound
|
|
26
|
+
description: "Parse supported outbound Inline Markdown (true by default; false preserves literal syntax)"
|
|
27
27
|
prompt: "Parse outbound Markdown?"
|
|
28
28
|
password: false
|
|
29
29
|
- name: INLINE_SYNC_COMMANDS
|