120 lines
5.7 KiB
Markdown
120 lines
5.7 KiB
Markdown
---
|
|
phase: 02-telegram-integration
|
|
plan: 02
|
|
subsystem: telegram
|
|
tags: [telegram, bot, typing-indicator, batching, file-handling, systemd, markdownv2]
|
|
|
|
# Dependency graph
|
|
requires:
|
|
- phase: 02-telegram-integration
|
|
plan: 01
|
|
provides: Persistent subprocess and telegram utils
|
|
provides:
|
|
- End-to-end Telegram-Claude Code messaging with typing indicators
|
|
- Message batching with debounce for rapid sequential messages
|
|
- Photo/document handling with auto-analysis
|
|
- Tool call progress notifications
|
|
- Systemd user service for reliability
|
|
affects: [03-lifecycle-management, bot-reliability]
|
|
|
|
# Tech tracking
|
|
tech-stack:
|
|
added:
|
|
- MessageBatcher (asyncio.Queue + debounce timer)
|
|
- systemd user service (KillMode=mixed)
|
|
patterns:
|
|
- "Dynamic typing event lookup via session name in typing_tasks dict"
|
|
- "Debounce-based message batching with asyncio.Queue"
|
|
- "--append-system-prompt preserves Claude Code defaults while adding persona"
|
|
- "--dangerously-skip-permissions for full tool access in non-interactive mode"
|
|
|
|
key-files:
|
|
created:
|
|
- telegram/message_batcher.py
|
|
- ~/.config/systemd/user/telegram-bot.service
|
|
modified:
|
|
- telegram/bot.py
|
|
- telegram/claude_subprocess.py
|
|
- telegram/telegram_utils.py
|
|
- telegram/personas/default.json
|
|
|
|
key-decisions:
|
|
- "Dynamic typing event lookup: callbacks reference typing_tasks dict by session name, not captured event"
|
|
- "--append-system-prompt instead of --system-prompt: preserves Claude Code model identity"
|
|
- "--dangerously-skip-permissions: allows all tools in non-interactive subprocess"
|
|
- "Full model ID in persona (claude-sonnet-4-5-20250929) instead of alias"
|
|
- "Stream-json NDJSON format: {type: user, message: {role: user, content: text}}"
|
|
|
|
patterns-established:
|
|
- "Pattern 1: Dynamic callback binding - closures look up mutable state by key instead of capturing immutable reference"
|
|
- "Pattern 2: Stale task cleanup - check task.done() and delete from dict before creating replacement"
|
|
- "Pattern 3: Persona via append - use --append-system-prompt to layer persona on top of CLI defaults"
|
|
|
|
# Metrics
|
|
duration: ~90min (including interactive debugging with user)
|
|
completed: 2026-02-04
|
|
---
|
|
|
|
# Phase 2 Plan 2: Bot Integration Summary
|
|
|
|
**End-to-end Telegram-Claude Code messaging with typing, batching, file handling, and systemd service**
|
|
|
|
## Performance
|
|
|
|
- **Duration:** ~90 minutes (including interactive testing and bug fixes)
|
|
- **Started:** 2026-02-04T19:30:00Z
|
|
- **Completed:** 2026-02-04T22:10:00Z
|
|
- **Tasks:** 3 (2 auto + 1 human-verify checkpoint)
|
|
- **Files created:** 2
|
|
- **Files modified:** 4
|
|
|
|
## Accomplishments
|
|
|
|
- Created MessageBatcher with debounce-based batching (2s timer, asyncio.Queue)
|
|
- Overhauled bot.py: typing indicators, tool call progress, message batching, file handling
|
|
- Created systemd user service with KillMode=mixed for subprocess cleanup
|
|
- Fixed stream-json NDJSON input format (nested message object required)
|
|
- Fixed typing indicator lifecycle (stale task cleanup + dynamic event lookup)
|
|
- Switched to --append-system-prompt to preserve Claude Code model identity
|
|
- Added --dangerously-skip-permissions for full tool access
|
|
- Set full model ID (claude-sonnet-4-5-20250929) in default persona
|
|
- Human-verified: messages flow, typing indicators show, model identifies correctly
|
|
|
|
## Task Commits
|
|
|
|
1. **Task 1: MessageBatcher + bot.py overhaul** - `f246d18` (feat)
|
|
2. **Task 2: Systemd user service** - created during same executor run
|
|
3. **Task 3: Human verification** - bugs found and fixed:
|
|
- `2d0d4da` - typing indicator lifecycle, model identity, tool permissions
|
|
|
|
## Bugs Found During Testing
|
|
|
|
1. **Stream-json input format**: `{"type":"user","content":"..."}` rejected by Claude Code; correct format is `{"type":"user","message":{"role":"user","content":"..."}}`
|
|
2. **Typing indicator stale tasks**: After completion, typing task stayed in dict with set event; next message reused dead task and typing never started
|
|
3. **Typing indicator event mismatch**: Subprocess callbacks captured specific stop_typing event at creation time; new messages created new events but callbacks still set the old one
|
|
4. **Model identity lost**: `--system-prompt` overwrote Claude Code's built-in system prompt (which includes model version); fixed with `--append-system-prompt`
|
|
5. **Tool permissions blocked**: Non-interactive `-p` mode blocked tools requiring permission prompts; fixed with `--dangerously-skip-permissions`
|
|
6. **Model alias resolution**: `sonnet` alias resolved to 3.5 Sonnet in CLI; fixed by using full model ID
|
|
|
|
## Files Created/Modified
|
|
|
|
**Created:**
|
|
- `telegram/message_batcher.py` - Debounce-based message batching with asyncio.Queue
|
|
- `~/.config/systemd/user/telegram-bot.service` - Systemd user service with KillMode=mixed
|
|
|
|
**Modified:**
|
|
- `telegram/bot.py` - Full overhaul: dynamic typing callbacks, stale task cleanup, batching, file handling
|
|
- `telegram/claude_subprocess.py` - NDJSON fix, --dangerously-skip-permissions, --append-system-prompt, full cmd logging
|
|
- `telegram/telegram_utils.py` - Debug logging for typing indicator
|
|
- `telegram/personas/default.json` - Full model ID instead of alias
|
|
|
|
## Deviations from Plan
|
|
|
|
1. **Typing indicator architecture changed**: Plan assumed capturing stop_typing event in callbacks; changed to dynamic lookup from typing_tasks dict by session name to fix lifecycle bugs
|
|
2. **System prompt approach changed**: Plan used `--system-prompt`; changed to `--append-system-prompt` to preserve Claude Code defaults
|
|
3. **Added --dangerously-skip-permissions**: Not in original plan; needed for tool access in non-interactive mode
|
|
4. **Model ID changed**: Plan used `sonnet` alias; changed to full ID after alias resolution issues
|
|
|
|
---
|
|
*Phase: 02-telegram-integration*
|
|
*Completed: 2026-02-04*
|