4b6817381b
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
CI / coverage-report (push) Has been cancelled
CI / test-kubernetes (push) Has been cancelled
CI / should-run-thorough (push) Has been cancelled
CI / test-thorough (cloudwatch-demo) (push) Has been cancelled
CI / test-thorough (flink-ecs) (push) Has been cancelled
CI / test-thorough (upstream-lambda) (push) Has been cancelled
CI / test-thorough (prefect-ecs-fargate) (push) Has been cancelled
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Has been cancelled
Benchmark image — build + push to ECR (any adapter) / build + push (push) Has been cancelled
CI / quality (ubuntu-latest) (push) Has been cancelled
CI / test (tools-runtime) (push) Has been cancelled
CI / test (e2e-general) (push) Has been cancelled
CI / test (cli-runtime) (push) Has been cancelled
CI / test (e2e-provider-and-openclaw) (push) Has been cancelled
CI / test (integrations-and-misc) (push) Has been cancelled
Release / verify (push) Has been cancelled
Release / build-python-dist (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Has been cancelled
Release / publish-release (push) Has been cancelled
Release / publish-main-release (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Has been cancelled
Release / prepare (push) Has been cancelled
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Has been cancelled
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Has been cancelled
81 lines
2.6 KiB
Python
81 lines
2.6 KiB
Python
"""Handlers for polled inbound Telegram messages."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import logging
|
|
from collections.abc import Callable
|
|
from concurrent.futures import ThreadPoolExecutor
|
|
|
|
from core.agent_harness.session import SessionCore
|
|
from gateway.config.get_gateway_settings import GatewaySettings, TelegramInboundMessage
|
|
from gateway.gateway_output_sink import GatewayOutputSink
|
|
from gateway.polling.telegram_poller.client import TelegramBotClient
|
|
from gateway.session.inbound_message_security import (
|
|
enforce_inbound_telegram_message_security,
|
|
)
|
|
from gateway.session.resolve_or_rotate_session import resolve_or_rotate_session
|
|
from gateway.storage import SessionResolver
|
|
|
|
logger = logging.getLogger(__name__)
|
|
GatewayAgentCallback = Callable[[str, SessionCore, GatewayOutputSink, logging.Logger], None]
|
|
|
|
|
|
async def handle_polled_inbound_telegram_message(
|
|
event: TelegramInboundMessage,
|
|
*,
|
|
client: TelegramBotClient,
|
|
session_resolver: SessionResolver,
|
|
settings: GatewaySettings,
|
|
executor: ThreadPoolExecutor,
|
|
chat_locks: dict[str, asyncio.Lock],
|
|
turn_semaphore: asyncio.Semaphore,
|
|
loop: asyncio.AbstractEventLoop | None = None,
|
|
handle_callback_to_gateway_agent: GatewayAgentCallback,
|
|
) -> None:
|
|
"""Process one long-polled inbound Telegram update."""
|
|
user_lock = chat_locks.setdefault(event.user_id, asyncio.Lock())
|
|
decision = enforce_inbound_telegram_message_security(
|
|
user_id=event.user_id,
|
|
chat_id=event.chat_id,
|
|
text=event.text,
|
|
env_allowed_user_ids=settings.allowed_user_ids,
|
|
)
|
|
async with user_lock, turn_semaphore:
|
|
session = resolve_or_rotate_session(
|
|
event,
|
|
decision,
|
|
session_resolver=session_resolver,
|
|
client=client,
|
|
)
|
|
if session is None:
|
|
return
|
|
|
|
preview = event.text.replace("\n", " ").strip()
|
|
if len(preview) > 80:
|
|
preview = f"{preview[:77]}..."
|
|
logger.info(
|
|
"inbound user=%s chat=%s session=%s text=%r",
|
|
event.user_id,
|
|
event.chat_id,
|
|
session.session_id[:8],
|
|
preview,
|
|
)
|
|
|
|
sink = GatewayOutputSink(
|
|
client=client,
|
|
chat_id=event.chat_id,
|
|
edit_interval_seconds=settings.stream_edit_interval_seconds,
|
|
)
|
|
|
|
event_loop = loop or asyncio.get_running_loop()
|
|
await event_loop.run_in_executor(
|
|
executor,
|
|
lambda: handle_callback_to_gateway_agent(
|
|
event.text,
|
|
session,
|
|
sink,
|
|
logger,
|
|
),
|
|
)
|