98 lines
5.6 KiB
Markdown
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.
|