Files
ulfbot/CLAUDE.md
sarah cfa281e676 Load system prompt from persistent file
- Load system prompt from data/system-prompt.txt (persistent)
- Fallback to AI_SYSTEM_PROMPT env variable
- Fallback to hardcoded default
- File can be edited without rebuilding container
- Includes default UlfBot/SchrottBot personality

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 10:54:36 +01:00

3.9 KiB

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. 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

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

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