Skip to content

feat(bot): Telegram + Discord front-end with a transport-agnostic gateway#29

Merged
QodeXcli merged 1 commit into
mainfrom
feat/bot-telegram-discord
Jun 27, 2026
Merged

feat(bot): Telegram + Discord front-end with a transport-agnostic gateway#29
QodeXcli merged 1 commit into
mainfrom
feat/bot-telegram-discord

Conversation

@QodeXcli

Copy link
Copy Markdown
Owner

Drive the QodeX agent from chat. All behaviour lives in one transport-agnostic gateway; the Telegram/Discord adapters are thin. The bug-classes that wreck chat-agent UIs are each solved once, for both platforms:

  • StreamPump — throttled + coalesced message editing (at most one edit per platform rate-window, only when content changed). Kills the edit-flood/429s and the half-rendered "oscillation" — same class as the TUI streaming jitter.
  • splitForStream — code-fence-aware spill across messages under each platform's length cap (Telegram 4096 / Discord 2000). An open code fence is closed at a cut and re-opened with the same language; sum(consumed) === input, so finalized text is never re-sent or corrupted.
  • BotGateway — one agent turn per chat at a time (later messages queue — no interleaving), permission prompts surfaced as inline buttons (tap or typed reply), /new + /stop commands.
  • auth — deny-by-default allowlist. A coding agent runs shell on the host, so an empty allowlist admits nobody; literal "*" opts a platform into public access deliberately.

Adapters: Telegram over the Bot API via long-polling (zero new deps; plain-text send to dodge MarkdownV2 escaping bugs). Discord via lazily-imported discord.js (optional — only needed for Discord, friendly error if absent). QodexAgentRunner bridges to AgentLoop exactly like headless.ts (fresh loop per turn, durable SessionStore session per chat via SessionMap, thinking/tool syntax filtered, final de-duped against the stream).

Config/secrets: tokens from ~/.qodex/.env (TELEGRAM_BOT_TOKEN / DISCORD_TOKEN); non-secret allowlists from a new optional bot.* config section. New qodex bot command (--telegram / --discord).

Tests: 22 new vitest specs — chunk fence-safety + sum(consumed), pump throttle/spill/no-op-edit, gateway auth/serialization/approval-buttons/stop, auth deny-by-default. tsc clean.

…eway

Drive the QodeX agent from chat. The design puts ALL behaviour in one transport-agnostic
gateway and keeps the platform adapters dumb, so the bug-classes that wreck chat-agent UIs
are each solved exactly once for both platforms:

- StreamPump: throttled + coalesced message editing (at most one edit per platform rate
  window, only when content changed) — kills the edit-flood/429s and the half-rendered
  'oscillation', the same class of bug as the TUI streaming jitter.
- splitForStream: code-fence-aware spill across messages under each platform's length cap
  (Telegram 4096 / Discord 2000) — an open ``` is closed at a cut and re-opened with the
  same language next message; Σconsumed === input so finalized text is never re-sent.
- BotGateway: one agent turn per chat at a time (later messages queue — no interleaving),
  permission prompts surfaced as inline buttons (tap or typed reply), /new + /stop commands.
- auth: deny-by-default allowlist — a coding agent runs shell on the host, so an empty
  allowlist admits nobody; literal '*' opts a platform into public access deliberately.

Adapters: Telegram over the Bot API via long-polling (zero new deps, plain-text send to
dodge MarkdownV2 escaping bugs); Discord via lazily-imported discord.js (optional — only
needed for Discord, friendly error if absent). QodexAgentRunner bridges to AgentLoop exactly
like headless.ts (fresh loop per turn, durable SessionStore session per chat via SessionMap,
thinking/tool syntax filtered, final de-duped against the stream). Tokens come from
~/.qodex/.env; non-secret allowlists from config (new optional bot.* section). New `qodex bot`
command (--telegram/--discord).

Tests: 22 new vitest specs (chunk fence-safety + Σconsumed, pump throttle/spill/no-op-edit,
gateway auth/serialization/approval-buttons/stop, auth deny-by-default). tsc clean.
@QodeXcli QodeXcli merged commit 676eb24 into main Jun 27, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant