Files
codex-telegram-bot/PLAN.md
2026-05-21 08:40:16 +00:00

98 lines
5.6 KiB
Markdown

# Codex Telegram Bot Hybrid Host/App-Server Plan
## Summary
Create `codex-telegram-bot/` as a Docker Compose managed Go Telegram bot that connects to a **host-launched Codex CLI app-server**. Codex is not containerized: it runs from the installed host `codex` binary, using the host user's `~/.codex`, sandboxing, and workspace paths. The bot runs in Docker Compose, stores state in SQLite, and communicates with Codex through a bind-mounted Unix socket.
## Research
Before implementation, carefully read the official docs and check against the guidelines below. Create/Update them properly if discrepancies or new findings occur. If you are not sure, ask the user for advice/instruction.
- Codex App Server official docs: https://developers.openai.com/codex/app-server
- App-server is intended for rich clients with authentication, conversation history, approvals, and streamed agent events.
- Protocol is JSON-RPC 2.0 with the `jsonrpc` field omitted.
- Important: `unix://` transport is WebSocket over Unix socket using HTTP Upgrade, not raw newline JSON.
- Start flow: connect, send `initialize`, send `initialized`, then `thread/start` and `turn/start`.
- Generate version-matched protocol schemas with `codex app-server generate-json-schema --out ./schemas`.
- Telegram Bot API official docs: https://core.telegram.org/bots/api
- `sendMessage` and `editMessageText` are limited to 1-4096 chars after entity parsing.
- Callback buttons require `answerCallbackQuery`.
- `getFile` downloads are limited to 20 MB via cloud Bot API.
- `sendDocument` supports bot-sent files up to 50 MB via cloud Bot API.
- Use long polling for MVP unless webhook deployment is explicitly needed.
- Telegram bot feature docs: https://core.telegram.org/bots/features
- Validate commands server-side regardless of BotFather command scopes.
- Reject group/supergroup/channel updates in code even if group joining is disabled.
- Use inline keyboards for approve/deny/details actions.
## Key requirements
- Scaffold a Go bot project:
- `cmd/bot` for the bot process.
- `internal/telegram` for commands, callbacks, message rendering, and Telegram file downloads.
- `internal/codexapp` for app-server WebSocket-over-Unix-socket JSON-RPC.
- `internal/store` for SQLite state and migrations.
- `scripts/start-codex-app-server`, `scripts/allow-user`, `scripts/remove-user`, `scripts/list-users`, `scripts/add-workspace`, `scripts/list-workspaces`.
- Docker Compose runs only the bot:
- Build the Go bot image locally.
- Mount persistent SQLite data.
- Bind-mount the host socket path into the bot container.
- Bind-mount an upload staging directory at the same absolute path visible to host Codex.
- Do not install or run Codex CLI inside the bot container.
- Host Codex app-server:
- Started outside Compose with `scripts/start-codex-app-server`.
- Default command: `codex app-server --listen unix://$HOST_CODEX_SOCKET`.
- Uses host `~/.codex`, host workspaces, and host sandbox behavior.
- Socket defaults to an absolute path under the project, e.g. `/home/.../codex-telegram-bot/run/codex.sock`.
- Telegram UX:
- One-to-one chats only; reject groups, supergroups, and channels.
- Allowlisted Telegram user IDs only.
- Commands: `/start`, `/help`, `/new`, `/threads`, `/resume`, `/fork`, `/archive`, `/status`, `/cancel`, `/workspaces`, `/workspace`, `/model`, `/sandbox`, `/diff`.
- Plain text continues the active Codex thread, creating one if needed.
- Send assistant messages and rendered tool/status blocks as separate Telegram messages; chunk only when a single message exceeds Telegram limits.
- Send long output, logs, and diffs as chunked messages.
- Consider using HTML to render if markdown is weak/awkward.
- Render Codex approval requests as inline keyboards with approve, deny, and details actions.
- SQLite state:
- `allowed_users`, `workspaces`, `sessions`, `threads`, `pending_approvals`, `audit_log`.
- Workspace paths are host absolute paths used as Codex `cwd`.
- The bot does not need direct workspace access except for upload staging.
## Test Plan
Any interactive related test that requires user action should be done properly - ask the user to do X in telegram, then verify.
- Unit tests:
- Allowlist enforcement and group-chat rejection.
- Workspace path validation.
- Telegram escaping, chunking, document fallback, and callback validation.
- WebSocket-over-Unix-socket JSON-RPC request correlation and reconnect behavior.
- SQLite migrations and admin scripts.
- Integration tests:
- Use a low/mini model in codex for testing.
- Verify initialize, thread start, turn start, streamed output, approval, and cancellation.
- Verify `/start`, `/new`, `/threads`, `/resume`, `/workspace`, `/cancel`, image input, and document staging.
- Verify non-allowlisted users are rejected and logged.
- Manual acceptance:
- Start host Codex app-server with `scripts/start-codex-app-server`.
- Run `docker compose up --build`.
- Add an allowlisted user and workspace with scripts.
- In a one-to-one Telegram chat, run `/start`, select workspace, create a thread, send a prompt, approve a Codex request, inspect output, and cancel a running turn.
## Assumptions
- Bot runtime is Docker Compose.
- Codex CLI app-server is launched from the installed host binary, outside Docker.
- The Unix socket is the only v1 connection between bot and Codex.
- Go is used for the bot.
- SQLite is used for state and admin-managed allowlist/workspaces.
- Codex-in-container and `codex exec` are both out of scope for MVP.
- This computer is resource limited. Use docker/docker compose for large tools/SDKs to avoid installing locally.