Compare commits
1
Commits
9a85c61781
...
telegram
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
279861bdb8 |
@@ -249,6 +249,7 @@ class Channels:
|
||||
})
|
||||
self._trim(state["transcript"])
|
||||
transcript = self._render(state["transcript"])
|
||||
await self.mark_as_read(agent_id, chat_id)
|
||||
await self._run_agent(agent_id, kind, chat_id, chat, sender_name, transcript)
|
||||
|
||||
async def _run_agent(self, agent_id, kind, chat_id, chat, sender_name, transcript):
|
||||
@@ -274,6 +275,9 @@ class Channels:
|
||||
f"Latest message from: {sender_name}",
|
||||
])
|
||||
|
||||
# Signal presence for the lifetime of this run.
|
||||
await self.set_online_status(agent_id, chat_id, online=True)
|
||||
|
||||
tool = ToolSpec(
|
||||
name="send_message",
|
||||
description="Send a text message back to this Telegram conversation.",
|
||||
@@ -338,6 +342,13 @@ class Channels:
|
||||
if len(text) > MAX_MESSAGE_LENGTH:
|
||||
text = text[:MAX_MESSAGE_LENGTH]
|
||||
|
||||
# Typing indicator immediately before the message so the user sees
|
||||
# the three-dot animation right as the reply is ready.
|
||||
try:
|
||||
await self._api(token, "sendAction", {"chat_id": chat_id, "action": "typing"})
|
||||
except Exception as e:
|
||||
print(f"[channel] sendAction typing failed for agent {agent_id}: {e}")
|
||||
|
||||
try:
|
||||
await self._api(token, "sendMessage", {"chat_id": chat_id, "text": text})
|
||||
return "ok"
|
||||
@@ -345,6 +356,43 @@ class Channels:
|
||||
print(f"[channel] sendMessage failed for agent {agent_id}: {e}")
|
||||
return f"error: {e}"
|
||||
|
||||
async def send_typing(self, agent_id, chat_id, typing=True):
|
||||
"""Send a typing action indicator to the chat.
|
||||
|
||||
Telegram exposes this via ``sendAction`` with ``typing`` (start) or
|
||||
``cancel`` (stop). Failures are swallowed: an indicator is cosmetic
|
||||
and must never break a run.
|
||||
"""
|
||||
binding = await self.get_binding(agent_id)
|
||||
if binding is None:
|
||||
return
|
||||
token = (binding.value or {}).get("token")
|
||||
if not token:
|
||||
return
|
||||
action = "typing" if typing else "cancel"
|
||||
try:
|
||||
await self._api(token, "sendAction", {"chat_id": chat_id, "action": action})
|
||||
except Exception as e:
|
||||
print(f"[channel] sendAction failed: {e}")
|
||||
|
||||
async def mark_as_read(self, agent_id, chat_id):
|
||||
"""Mark an inbound message as read.
|
||||
|
||||
Telegram bots have no native read receipt; acceptance is already
|
||||
handled by :meth:`accept_update`. This stays an explicit hook on the
|
||||
inbound path so a provider that does support receipts can be wired in
|
||||
here later.
|
||||
"""
|
||||
pass
|
||||
|
||||
async def set_online_status(self, agent_id, chat_id, online=True):
|
||||
"""Signal presence for the conversation.
|
||||
|
||||
A single ``typing`` action marks the run as online; ``cancel`` clears
|
||||
it. Delegates to :meth:`send_typing`.
|
||||
"""
|
||||
await self.send_typing(agent_id, chat_id, typing=online)
|
||||
|
||||
# --- In-memory transcript ---
|
||||
|
||||
def _state(self, agent_id, chat_id):
|
||||
|
||||
Reference in new issue
Block a user