# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview Telegram bot built with TypeScript and [Telegraf](https://telegraf.js.org/). Uses Markov chains with trigrams to generate sentences from learned messages. Optional KI/LLM integration via OpenAI-compatible API. Each chat has its own isolated data. ## Commands ```bash npm run dev # Development with hot-reload (tsx watch) npm run build # Compile TypeScript to dist/ npm start # Run production build docker compose up -d --build # Docker deployment ``` ## Architecture ``` src/ ├── index.ts # Bot entry point, commands, setup wizard ├── markov.ts # Markov chain with trigram support ├── database.ts # SQLite persistence layer └── ai.ts # OpenAI-compatible client ``` **Data flow (Markov):** 1. Message received → `chain.learn(text)` → SQLite 2. Trigger check (reply/mention/random) 3. If triggered → `chain.generate()` → reply **Data flow (AI):** 1. `/ask-ai` or trigger word detected 2. Load last 50 messages as context 3. Build prompt (global + group prompt) 4. Call OpenAI-compatible API → reply **Per-chat isolation:** - Each chat has separate Markov chain data - Each chat has separate AI settings - Each chat has separate message context (50 messages) ## Key Implementation Details ### Markov Chain (markov.ts) - Uses **trigrams** (order=2): "word1 word2" → "word3" - Weighted random selection based on frequency - Generates sentences up to 20 words ### Database (database.ts) - SQLite with `better-sqlite3` (synchronous API) - Tables: - `chat_settings` - Markov probability - `markov_transitions` - Word transitions - `markov_starts` - Sentence starts - `ai_settings` - KI configuration per chat - `message_context` - Last 50 messages per chat - `setup_sessions` - Setup wizard state - Automatic cleanup every 24h ### AI Client (ai.ts) - OpenAI-compatible API (works with OpenAI, Ollama, OpenRouter, etc.) - Prompt system: - Global: `data/system-prompt.txt` → `.env` fallback → default - Group-specific: stored in DB per chat - API key masking for security - Context: Last 50 messages ### Setup Wizard - Started via `/ai setup` in group - Continues in private chat for security - API keys never shown in full - Steps: Provider → API Key → Model → URL → Trigger/Prob → Group Prompt ## Environment ```env BOT_TOKEN= # Telegram bot token (required) AI_DEFAULT_API_KEY= # Default API key (optional) AI_DEFAULT_BASE_URL= # Default API URL (default: OpenAI) AI_DEFAULT_MODEL= # Default model (default: gpt-4o-mini) AI_SYSTEM_PROMPT= # Global system prompt (fallback, see below) ``` **System Prompt Loading:** 1. `data/system-prompt.txt` (persistent, editable without rebuild) 2. `AI_SYSTEM_PROMPT` env variable (fallback) 3. Hardcoded default (last resort) AI_DEFAULT_MODEL= # Default model (default: gpt-4o-mini) AI_SYSTEM_PROMPT= # Global system prompt ``` ## Database Schema ```sql -- Markov chat_settings (chat_id, probability) markov_transitions (chat_id, key, next_word, count) markov_starts (chat_id, key, count) -- AI ai_settings (chat_id, enabled, trigger_word, random_prob, group_prompt, provider, base_url, model, api_key) message_context (chat_id, role, content, timestamp) setup_sessions (user_id, chat_id, step, data) ``` ## Response Triggers ### Markov (always active) 1. Reply to bot's message → always respond 2. @username mention → always respond 3. Random probability (configurable per chat) ### AI (when enabled) 1. `/ask-ai [text]` command 2. Trigger word (configurable, default: "ask-ai") 3. Random probability (configurable, default: 0%) ## Security - API keys stored in database, never logged - API keys masked in `/ai status` output: `sk-***...***xyz` - Setup only via private chat - Admin-only configuration commands