224 lines
9.8 KiB
Markdown
224 lines
9.8 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Build & Run Commands
|
|
|
|
```bash
|
|
# Install dependencies
|
|
pip install -r requirements.txt
|
|
|
|
# Install in development mode (required for testing)
|
|
pip install -e .
|
|
|
|
# Run the bot (requires .env with DISCORD_TOKEN and AI provider key)
|
|
python -m loyal_companion
|
|
|
|
# Run with Docker (includes PostgreSQL)
|
|
docker-compose up -d
|
|
|
|
# Syntax check all Python files
|
|
python -m py_compile src/loyal_companion/**/*.py
|
|
```
|
|
|
|
## Testing
|
|
|
|
```bash
|
|
# Install dev dependencies
|
|
pip install -e ".[dev]"
|
|
|
|
# Run all tests
|
|
python -m pytest tests/ -v
|
|
|
|
# Run tests with coverage
|
|
python -m pytest tests/ --cov=loyal_companion --cov-report=term-missing
|
|
|
|
# Run specific test file
|
|
python -m pytest tests/test_models.py -v
|
|
|
|
# Run specific test class
|
|
python -m pytest tests/test_services.py::TestMoodService -v
|
|
```
|
|
|
|
The test suite uses:
|
|
- `pytest` with `pytest-asyncio` for async test support
|
|
- SQLite in-memory database for testing (via `aiosqlite`)
|
|
- Mock fixtures for Discord objects and AI providers in `tests/conftest.py`
|
|
|
|
## Architecture
|
|
|
|
Loyal Companion is a Discord bot companion for those who love deeply and feel intensely. It features a "Living AI" system called Bartender - a wise, steady presence who listens without judgment, understands attachment theory, and knows when to offer perspective versus when to just hold space.
|
|
|
|
### Provider Pattern
|
|
The AI system uses a provider abstraction pattern:
|
|
- `services/providers/base.py` defines `AIProvider` abstract class with `generate()` method
|
|
- `services/providers/openai.py`, `openrouter.py`, `anthropic.py`, `gemini.py` implement the interface
|
|
- `services/ai_service.py` is the factory that creates the correct provider based on `AI_PROVIDER` env var
|
|
- OpenRouter uses OpenAI's client with a different base URL
|
|
- Gemini uses the `google-genai` SDK
|
|
|
|
### Cog System
|
|
Discord functionality is in `cogs/`:
|
|
- `ai_chat.py` - `@mention` handler (responds when bot is mentioned)
|
|
- `memory.py` - Memory management commands (`!setname`, `!remember`, etc.)
|
|
- `status.py` - Bot health and status commands
|
|
|
|
Cogs are auto-loaded by `bot.py` from the `cogs/` directory.
|
|
|
|
### Database & Memory System
|
|
The bot uses PostgreSQL for persistent memory (optional, falls back to in-memory):
|
|
- `models/` - SQLAlchemy models (User, UserFact, Conversation, Message, Guild, GuildMember)
|
|
- `models/living_ai.py` - Living AI models (BotState, BotOpinion, UserRelationship, etc.)
|
|
- `services/database.py` - Connection pool and async session management
|
|
- `services/user_service.py` - User CRUD, custom names, facts management
|
|
- `services/persistent_conversation.py` - Database-backed conversation history
|
|
|
|
Key features:
|
|
- Custom names: Set preferred names for users so the bot knows "who is who"
|
|
- User facts: Bot remembers things about users (hobbies, preferences, attachment patterns, grief context)
|
|
- Persistent conversations: Chat history survives restarts
|
|
- Conversation timeout: New conversation starts after 60 minutes of inactivity
|
|
|
|
### Living AI System
|
|
The bot implements a "Living AI" system with emotional depth and relationship tracking:
|
|
|
|
#### Services (`services/`)
|
|
- `mood_service.py` - Valence-arousal mood model with time decay
|
|
- `relationship_service.py` - Relationship scoring (new face to close friend)
|
|
- `fact_extraction_service.py` - Autonomous fact learning from conversations (including attachment patterns, grief context, coping mechanisms)
|
|
- `opinion_service.py` - Bot develops opinions on topics over time
|
|
- `self_awareness_service.py` - Bot statistics and self-reflection
|
|
- `communication_style_service.py` - Learns user communication preferences
|
|
- `proactive_service.py` - Scheduled events (birthdays, follow-ups)
|
|
- `association_service.py` - Cross-user memory associations
|
|
|
|
#### Models (`models/living_ai.py`)
|
|
- `BotState` - Global mood state and statistics per guild
|
|
- `BotOpinion` - Topic sentiments and preferences
|
|
- `UserRelationship` - Per-user relationship scores and metrics
|
|
- `UserCommunicationStyle` - Learned communication preferences
|
|
- `ScheduledEvent` - Birthdays, follow-ups, reminders
|
|
- `FactAssociation` - Cross-user memory links
|
|
- `MoodHistory` - Mood changes over time
|
|
|
|
#### Mood System
|
|
Uses a valence-arousal model:
|
|
- Valence: -1 (sad) to +1 (happy)
|
|
- Arousal: -1 (calm) to +1 (excited)
|
|
- Labels: excited, happy, calm, neutral, bored, annoyed, curious
|
|
- Time decay: Mood gradually returns to neutral (slower decay = steadier presence)
|
|
|
|
#### Relationship Levels
|
|
- New Face (0-20): Warm but observant - "Pull up a seat" energy
|
|
- Getting to Know You (21-40): Building trust, remembering details
|
|
- Regular (41-60): Comfortable familiarity - "Your usual?"
|
|
- Good Friend (61-80): Real trust, can be honest even when hard
|
|
- Close Friend (81-100): Deep bond, full honesty, reflects patterns with love
|
|
|
|
### Configuration
|
|
All config flows through `config.py` using pydantic-settings. The `settings` singleton is created at module load, so env vars must be set before importing.
|
|
|
|
### Web Search
|
|
The bot can search the web for current information via SearXNG:
|
|
- `services/searxng.py` provides `SearXNGService` for web queries
|
|
- `ai_chat.py` uses a two-step approach: first asks AI if search is needed, then provides results as context
|
|
- Search is triggered automatically when the AI determines the query needs current information
|
|
- Configured via `SEARXNG_URL`, `SEARXNG_ENABLED`, and `SEARXNG_MAX_RESULTS` env vars
|
|
|
|
### Key Design Decisions
|
|
- `PersistentConversationManager` stores conversations in PostgreSQL when `DATABASE_URL` is set
|
|
- `ConversationManager` is the in-memory fallback when database is not configured
|
|
- Long AI responses are split via `split_message()` in `ai_chat.py` to respect Discord's 2000 char limit
|
|
- The bot responds only to @mentions via `on_message` listener
|
|
- Web search uses AI to decide when to search, avoiding unnecessary API calls for general knowledge questions
|
|
- User context (custom name + known facts) is included in AI prompts for personalized responses
|
|
- `PortableJSON` type in `models/base.py` allows models to work with both PostgreSQL (JSONB) and SQLite (JSON)
|
|
- `ensure_utc()` helper handles timezone-naive datetimes from SQLite
|
|
|
|
## Environment Variables
|
|
|
|
Required: `DISCORD_TOKEN`, plus one of `OPENAI_API_KEY`, `OPENROUTER_API_KEY`, `ANTHROPIC_API_KEY`, or `GEMINI_API_KEY` depending on `AI_PROVIDER` setting.
|
|
|
|
Optional:
|
|
- `DATABASE_URL` - PostgreSQL connection string (e.g., `postgresql+asyncpg://user:pass@host:5432/db`)
|
|
- `POSTGRES_PASSWORD` - Used by docker-compose for the PostgreSQL container
|
|
- `SEARXNG_URL` - SearXNG instance URL for web search capability
|
|
|
|
### Living AI Configuration
|
|
- `LIVING_AI_ENABLED` - Master switch for Living AI features (default: true)
|
|
- `MOOD_ENABLED` - Enable mood system (default: true)
|
|
- `RELATIONSHIP_ENABLED` - Enable relationship tracking (default: true)
|
|
- `FACT_EXTRACTION_ENABLED` - Enable autonomous fact extraction (default: true)
|
|
- `FACT_EXTRACTION_RATE` - Probability of extracting facts (default: 0.4)
|
|
- `PROACTIVE_ENABLED` - Enable proactive messages (default: true)
|
|
- `CROSS_USER_ENABLED` - Enable cross-user memory associations (default: false)
|
|
- `OPINION_FORMATION_ENABLED` - Enable bot opinion formation (default: true)
|
|
- `STYLE_LEARNING_ENABLED` - Enable communication style learning (default: true)
|
|
- `MOOD_DECAY_RATE` - How fast mood returns to neutral per hour (default: 0.05)
|
|
|
|
### Command Toggles
|
|
- `COMMANDS_ENABLED` - Master switch for all commands (default: true)
|
|
- `CMD_RELATIONSHIP_ENABLED` - Enable `!relationship` command
|
|
- `CMD_MOOD_ENABLED` - Enable `!mood` command
|
|
- `CMD_BOTSTATS_ENABLED` - Enable `!botstats` command
|
|
- `CMD_OURHISTORY_ENABLED` - Enable `!ourhistory` command
|
|
- `CMD_BIRTHDAY_ENABLED` - Enable `!birthday` command
|
|
- `CMD_REMEMBER_ENABLED` - Enable `!remember` command
|
|
- `CMD_SETNAME_ENABLED` - Enable `!setname` command
|
|
- `CMD_WHATDOYOUKNOW_ENABLED` - Enable `!whatdoyouknow` command
|
|
- `CMD_FORGETME_ENABLED` - Enable `!forgetme` command
|
|
|
|
## Commands
|
|
|
|
### User commands
|
|
- `!setname <name>` - Set your preferred name
|
|
- `!clearname` - Reset to Discord display name
|
|
- `!remember <fact>` - Tell the bot something about you
|
|
- `!whatdoyouknow` - See what the bot remembers about you
|
|
- `!forgetme` - Clear all facts about you
|
|
- `!relationship` - See your relationship level with the bot
|
|
- `!mood` - See the bot's current emotional state
|
|
- `!botstats` - Bot shares its self-awareness statistics
|
|
- `!ourhistory` - See your history with the bot
|
|
- `!birthday <date>` - Set your birthday for the bot to remember
|
|
|
|
### Admin commands
|
|
- `!setusername @user <name>` - Set name for another user
|
|
- `!teachbot @user <fact>` - Add a fact about a user
|
|
|
|
## Development Guidelines
|
|
|
|
### When Adding New Features
|
|
1. **Always write tests** - New services need corresponding test files in `tests/`
|
|
2. **Update documentation** - README.md and relevant docs/ files must be updated
|
|
3. **Update CLAUDE.md** - Add new services, models, and config options here
|
|
4. **Follow existing patterns** - Match the style of existing services
|
|
|
|
### Planned Features (In Progress)
|
|
The following features are being implemented:
|
|
|
|
1. **Attachment Pattern Tracking** (`attachment_service.py`)
|
|
- Detect anxious/avoidant/disorganized patterns
|
|
- Adapt responses based on attachment state
|
|
- Track what helps regulate each person
|
|
|
|
2. **Grief Journey Tracking** (`grief_service.py`)
|
|
- Track grief context and phase
|
|
- Recognize anniversaries and hard dates
|
|
- Adjust support style based on grief phase
|
|
|
|
3. **Grounding & Coping Tools** (`grounding_service.py`)
|
|
- Breathing exercises, sensory grounding
|
|
- Spiral detection and intervention
|
|
- Session pacing and intensity tracking
|
|
|
|
4. **Enhanced Support Memory**
|
|
- Learn HOW someone wants to be supported
|
|
- Track effective vs ineffective approaches
|
|
- Remember comfort topics for breaks
|
|
|
|
5. **Communication Style Matching**
|
|
- Energy matching (playful vs serious)
|
|
- Directness calibration
|
|
- Real-time tone adaptation
|