Skip to content

Comments

tts tts telegram commands with replicate + claude api rate limits + enforce authorized telegram id from env#101

Open
morandalex wants to merge 5 commits intoTinyAGI:mainfrom
morandalex:env-claude-cli-settings-plus-tts-tts-telegram-commands
Open

tts tts telegram commands with replicate + claude api rate limits + enforce authorized telegram id from env#101
morandalex wants to merge 5 commits intoTinyAGI:mainfrom
morandalex:env-claude-cli-settings-plus-tts-tts-telegram-commands

Conversation

@morandalex
Copy link

@morandalex morandalex commented Feb 16, 2026

Summary of Changes

Area Files What changed
Project setup .claudeignore, CLAUDE.md Added Claude Code ignore rules and project documentation
Database layer src/lib/db.ts, db/migrations/*.sql, src/lib/config.ts New SQLite database (better-sqlite3) with WAL mode, token_usage and api_rate_limits tables, dbmate migration support with CREATE TABLE fallback
Token & rate limit tracking src/lib/invoke.ts Pre/post invocation token usage recording, Anthropic rate limit header capture via lightweight API call, tier inference
Speech-to-Text (STT) src/lib/transcribe.ts, src/channels/telegram-client.ts Replicate incredibly-fast-whisper integration, /stton /sttoff toggle commands, voice/audio transcription
Text-to-Speech (TTS) src/lib/synthesize.ts, src/channels/telegram-client.ts Replicate MiniMax Speech-02-Turbo integration, /ttson /ttsoff toggle commands, response voice synthesis
Telegram commands src/channels/telegram-client.ts /help command, user whitelist via TELEGRAM_USERS_ENABLED env var
Agent config src/lib/types.ts, src/lib/invoke.ts env field on AgentConfig, passed to runCommand child process
Visualizer src/visualizer/team-visualizer.tsx Rate limit bars per agent (RPM, input tokens, output tokens), tier badge, rate_limits_updated event handler
Queue processor src/queue-processor.ts dotenv/config import, closeDb() on SIGINT/SIGTERM
Daemon lib/daemon.sh Auto-run dbmate migrations on daemon start
Dependencies package.json, package-lock.json Added better-sqlite3 + @types/better-sqlite3, db:migrate/db:rollback scripts

Pre-requisites

  • Node.js 20+ installed
  • A valid .env file with TELEGRAM_BOT_TOKEN, ANTHROPIC_API_KEY, REPLICATE_API_TOKEN
  • A Telegram account to interact with the bot
  • dbmate fpr the migration

Test Cases

1. Build

  • 1.1 Run npm run build — must compile with zero errors (both main + visualizer)
  • 1.2 Run npm run build:main — must compile with zero errors
  • 1.3 Run npm run build:visualizer — must compile with zero errors
  • 1.4 Verify dist/ output contains channels/telegram-client.js, lib/db.js, lib/transcribe.js, lib/synthesize.js, queue-processor.js

2. Database — with dbmate

  • 2.1 Delete ~/.tinyclaw/tinyclaw.db if it exists
  • 2.2 Run npm run db:migrate — should create the database and apply both migrations
  • 2.3 Verify tables exist: sqlite3 ~/.tinyclaw/tinyclaw.db ".tables" should show token_usage and api_rate_limits
  • 2.4 Run npm run db:rollback twice — should drop both tables cleanly
  • 2.5 Run npm run db:migrate again — idempotent re-apply

3. Database — fallback (no dbmate)

  • 3.1 Temporarily rename/remove dbmate from PATH
  • 3.2 Delete ~/.tinyclaw/tinyclaw.db
  • 3.3 Start the queue processor (npm run queue) — database should be auto-created with both tables via CREATE TABLE IF NOT EXISTS
  • 3.4 Check logs for Database schema created via fallback (dbmate not available)
  • 3.5 Restore dbmate

4. Daemon dbmate auto-migration

  • 4.1 With dbmate installed and a fresh DB, start the daemon via tinyclaw start
  • 4.2 Verify migrations are applied automatically (check logs or verify tables)

5. Telegram — User Whitelist

  • 5.1 Set TELEGRAM_USERS_ENABLED="" (empty) in .env → start bot → all users can send messages (log should show WARN: No TELEGRAM_USERS_ENABLED set)
  • 5.2 Set TELEGRAM_USERS_ENABLED=<your_telegram_id> → restart bot → log should show User whitelist active: 1 user(s) allowed
  • 5.3 Send a message from the whitelisted user → message is queued normally
  • 5.4 Send a message from a non-whitelisted user (or use a different Telegram account) → bot replies Access denied. You are not authorized to use this bot. and log shows WARN: Unauthorized user ... blocked
  • 5.5 Set TELEGRAM_USERS_ENABLED=111,222,333 (multiple IDs with no spaces) → restart → verify 3 user(s) allowed
  • 5.6 Set TELEGRAM_USERS_ENABLED=111, 222, 333 (with spaces) → restart → verify whitespace is trimmed and all 3 IDs work

6. Telegram — /help Command

  • 6.1 Send /help to the bot → should receive the full command list including STT/TTS status
  • 6.2 Send !help to the bot → same result (alternative prefix)
  • 6.3 Verify /help response includes: /agent, /team, /reset, /stton, /sttoff, /ttson, /ttsoff, /help
  • 6.4 Verify STT/TTS status is shown correctly (default: off)

7. Telegram — STT (Speech-to-Text)

  • 7.1 With STT disabled (default), send a voice message → file is downloaded but no transcription (just the audio file is attached to the queue message)
  • 7.2 Send /stton → bot replies Speech-to-text enabled...
  • 7.3 Verify ~/.tinyclaw/stt_enabled_chats.json is created and contains the chat ID
  • 7.4 Send a voice message → log shows Voice transcribed: ... and the queue message contains [voice transcript: ...]
  • 7.5 Send an audio file (.mp3) → same transcription behavior
  • 7.6 Send /sttoff → bot replies Speech-to-text disabled.
  • 7.7 Send another voice message → no transcription
  • 7.8 Restart the Telegram client → STT state is persisted (still off after /sttoff)
  • 7.9 With REPLICATE_API_TOKEN unset or empty, enable STT and send a voice message → transcription silently returns null, no crash

8. Telegram — TTS (Text-to-Speech)

  • 8.1 With TTS disabled (default), send a text message → receive only text response (no voice message)
  • 8.2 Send /ttson → bot replies Text-to-speech enabled...
  • 8.3 Verify ~/.tinyclaw/tts_enabled_chats.json is created and contains the chat ID
  • 8.4 Send a text message and wait for response → receive both a voice message (reply) and the text response
  • 8.5 Verify the voice file is cleaned up after sending (tts_*.mp3 deleted from ~/.tinyclaw/files/)
  • 8.6 Send /ttsoff → bot replies Text-to-speech disabled.
  • 8.7 Next response should be text only (no voice)
  • 8.8 Restart the Telegram client → TTS state is persisted
  • 8.9 With REPLICATE_API_TOKEN unset, enable TTS → response is text-only, log shows TTS failed: ..., no crash

9. Token Usage Tracking

  • 9.1 Send a message through the queue that invokes an agent
  • 9.2 Query sqlite3 ~/.tinyclaw/tinyclaw.db "SELECT * FROM token_usage ORDER BY id DESC LIMIT 1" → row exists with agent_id, provider, model, message_char_count, estimated_input_tokens
  • 9.3 After the agent responds, re-query → same row now has response_char_count, estimated_output_tokens, duration_ms filled in
  • 9.4 Verify estimated_input_tokens ≈ message_char_count / 4 (ceiling)
  • 9.5 Test with an OpenAI/Codex agent → same tracking behavior

10. API Rate Limit Tracking (Anthropic)

  • 10.1 Invoke a Claude (Anthropic) agent
  • 10.2 Query sqlite3 ~/.tinyclaw/tinyclaw.db "SELECT * FROM api_rate_limits ORDER BY id DESC LIMIT 1" → row with rate limit data
  • 10.3 Verify inferred_tier is populated (e.g., Tier 1, Tier 2, etc.)
  • 10.4 Verify log shows Rate limits checked — agent: ..., tier: ..., RPM: ...
  • 10.5 Invoke an OpenAI/Codex agent → no rate limit check should be performed (no new row in api_rate_limits for that agent)
  • 10.6 Configure an agent with custom env (e.g., different API key) → rate limit check is skipped for that agent

11. Agent env Config

  • 11.1 Add "env": { "SOME_VAR": "test" } to an agent in settings.json
  • 11.2 Invoke that agent → the child process should receive SOME_VAR in its environment
  • 11.3 Agent without env field → works as before (inherits parent process env)

12. Visualizer — Rate Limit Display

  • 12.1 Start the visualizer (npm run visualize)
  • 12.2 Before any Claude invocation → rate limits section shows No rate limit data yet
  • 12.3 Trigger a Claude agent invocation → visualizer updates to show rate limit bars for that agent
  • 12.4 Verify the display shows: agent ID, tier badge, model name, RPM bar, Input tokens bar, Output tokens bar, time ago
  • 12.5 Bar colors: green (>50%), yellow (20-50%), red (<20%)
  • 12.6 Multiple agents → each gets their own card in the rate limits row

13. Queue Processor — dotenv & Graceful Shutdown

  • 13.1 Start npm run queue → verify it loads .env (no missing env var errors)
  • 13.2 Send SIGINT (Ctrl+C) → log shows Shutting down queue processor... and database is closed cleanly
  • 13.3 Verify no SQLITE_MISUSE or lock errors in logs after shutdown

14. Existing Functionality (Regression)

  • 14.1 Send a text message to Telegram bot → processed and response received (basic flow still works)
  • 14.2 Send a photo with caption → photo downloaded, caption included in queue message
  • 14.3 Send a document → downloaded correctly
  • 14.4 /agent command still works
  • 14.5 /team command still works
  • 14.6 /reset command still works
  • 14.7 @agent_id routing still works
  • 14.8 @team_id routing still works
  • 14.9 Long messages (>4096 chars) are still split correctly
  • 14.10 Group/channel messages are still ignored (private chat only)

15. Edge Cases

  • 15.1 Database file is locked by another process → graceful error handling, no crash
  • 15.2 REPLICATE_API_TOKEN missing → STT/TTS features degrade silently (return null)
  • 15.3 ANTHROPIC_API_KEY missing → rate limit check skipped, no crash
  • 15.4 Replicate API returns error → TTS/STT return null, logged as error, bot continues
  • 15.5 Very long text (>10k chars) sent to TTS → trimmed to 10k before synthesis
  • 15.6 Multiple rapid messages → token usage rows are unique per invocation
  • 15.7 Bot receives message with no from field → whitelist check handles undefined gracefully

Checklist Before Merge

  • All test cases above pass
  • No console errors or unhandled promise rejections during normal operation
  • .env file is NOT committed (.claudeignore + .gitignore protect it)
  • npm run build succeeds cleanly
  • Database migrations are idempotent
  • Existing Telegram commands (/agent, /team, /reset) still work
  • Bot is stable over 10+ minutes of operation with no memory leaks or crashes

@morandalex
Copy link
Author

reopened from closed pull req #35

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