kcode-tg-kennedy-bot
kcode-tg-kennedy-bot is a host-integrated Rust library for Telegram transport. It owns Telegram long polling, bounded message and media persistence, fail-closed group security, and availability-first per-principal dispatch. It deliberately owns no HTTP listener, Kennedy users, whitelist entries, application capabilities, secrets vault, Kmap roots, prompts, model execution, or downstream object store.
The directory is a standalone Rust 2024 Cargo package with no workspace-inherited metadata or dependencies. Documentation.md is the integration and behavioral guide, and the literal package version in Cargo.toml is canonical.
Host contract
The host passes an optional bot token to open and implements IdentitySink:
observe_identityreceives a numeric Telegram ID, current handle when present, and display name.whitelistreturns the numeric Telegram user IDs authorized at that moment.request_add_userauthorizes and performs the private/adduser @handleworkflow outside the transport.observe_groupreceives the transport's stable opaque group ID so the host can associate application-owned state independently.
use ;
use ;
async
# async
open validates storage and a configured Telegram token before returning. Runtime::run owns the continuous polling driver. Runtime::service returns a cloneable Service handle for same-process host calls. With no token, the service remains usable for stored-state inspection while the runtime waits without polling.
max_voice_bytes is retained as a source-compatible field name, but it limits every inbound and outbound media payload and must be nonzero. Tokens are rejected when empty, redacted from Debug, never serialized, and zeroized on drop.
Call migrate_storage(path) to apply idempotent SQLite migrations without opening the service or starting the poller.
Boundary
This crate intentionally opens no local or public server socket. The host owns any browser or network API, its authentication and origin policy, and its health endpoint. Same-process orchestration calls typed Service methods directly; only the Telegram Bot API remains an HTTP boundary.
Service::status reports whether Telegram is ready or disabled and reports inbound/outbound media kinds and the configured byte limit. The host may incorporate this status into its own health response.
Finite Telegram request and download retries are delegated to the exact-pinned kcode-telegram-request-policy 0.1.0 leaf. The bot retains its existing call sites, safe log classes, and local SQLite error classification.
Behavior
Telegram polling is availability-first and at-most-once-leaning. Its next offset is durable in SQLite. Work is FIFO per private user or group-user principal while independent principals can run concurrently. Malformed input, saturation, processor errors, and panics remain local to the affected stream rather than freezing later updates.
Private messages and messages from the sole active human in an eligible two-person group are durably gathered until 20 seconds of stream inactivity, then exposed to the host as one ordered batch. Two-person groups invoke Kennedy on every human message without requiring a ping; larger groups retain explicit invocation behavior.
Group delivery fails closed. The bot must be an administrator, Telegram's member count must match the observed active-human ledger plus the bot, and every human ever observed in the group must be in the host's current whitelist. Ineligible groups are quarantined before content inspection or media download.
Cold private text and attachment sends resolve an established chat without creating or changing its conversation binding. Existing session-bound private delivery and active-event reply methods retain their prior behavior.
The transport retains bounded voice notes, documents, photos, videos, animations, audio, video notes, and stickers. Service::event_media and Service::group_message_media return stored bytes and media type. Attachment supplies owned bytes plus optional safe filename, media type, native-media kind, and caption for private, group, or active-event delivery.
Text is checked for non-whitespace without changing its exact contents. Long replies are split at Telegram's UTF-16 limit so concatenating the chunks reconstructs the original text exactly.
See Documentation.md for the full service surface and persistence, validation, retry, reconciliation, and side-effect semantics.