refactor: Transform daemon_boyfriend into Loyal Companion

Rebrand and personalize the bot as 'Bartender' - a companion for those
who love deeply and feel intensely.

Major changes:
- Rename package: daemon_boyfriend -> loyal_companion
- New default personality: Bartender - wise, steady, non-judgmental
- Grief-aware system prompt (no toxic positivity, attachment-informed)
- New relationship levels: New Face -> Close Friend progression
- Bartender-style mood modifiers (steady presence)
- New fact types: attachment_pattern, grief_context, coping_mechanism
- Lower mood decay (0.05) for emotional stability
- Higher fact extraction rate (0.4) - Bartender pays attention

Updated all imports, configs, Docker files, and documentation.
This commit is contained in:
2026-01-14 18:08:35 +01:00
parent 3d939201f0
commit dbd534d860
60 changed files with 310 additions and 381 deletions

View File

@@ -142,7 +142,7 @@ OPENAI_API_KEY=your_key
### 3. Run
```bash
python -m daemon_boyfriend
python -m loyal_companion
```
### 4. Interact

View File

@@ -61,8 +61,8 @@ This document provides a comprehensive overview of the Daemon Boyfriend Discord
## Directory Structure
```
daemon-boyfriend/
├── src/daemon_boyfriend/
loyal-companion/
├── src/loyal_companion/
│ ├── __main__.py # Entry point
│ ├── bot.py # Discord bot setup & cog loading
│ ├── config.py # Pydantic settings configuration

View File

@@ -172,7 +172,7 @@ Custom system prompt. If not set, one is generated from `BOT_NAME` and `BOT_PERS
### DATABASE_URL
```bash
DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/daemon_boyfriend
DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/loyal_companion
```
**Default:** `None` (in-memory mode)
@@ -453,7 +453,7 @@ Logging verbosity level.
### LOG_FILE
```bash
LOG_FILE=/var/log/daemon_boyfriend.log
LOG_FILE=/var/log/loyal_companion.log
```
**Default:** `None` (console only)
@@ -522,7 +522,7 @@ BOT_STATUS=for @mentions
# DATABASE (Optional - runs in-memory if not set)
# -----------------------------------------------------------------------------
DATABASE_URL=postgresql+asyncpg://daemon:password@localhost:5432/daemon_boyfriend
DATABASE_URL=postgresql+asyncpg://daemon:password@localhost:5432/loyal_companion
# DATABASE_ECHO=false
# DATABASE_POOL_SIZE=5
# DATABASE_MAX_OVERFLOW=10
@@ -579,7 +579,7 @@ COMMANDS_ENABLED=true
# -----------------------------------------------------------------------------
LOG_LEVEL=INFO
# LOG_FILE=/var/log/daemon_boyfriend.log
# LOG_FILE=/var/log/loyal_companion.log
```
---

View File

@@ -32,7 +32,7 @@ This document describes the database schema used by Daemon Boyfriend.
```bash
# PostgreSQL connection string
DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/daemon_boyfriend
DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/loyal_companion
# Optional settings
DATABASE_ECHO=false # Log SQL queries
@@ -499,7 +499,7 @@ All indexes are created with `IF NOT EXISTS` for idempotency.
### From Code
```python
from daemon_boyfriend.services.database import db
from loyal_companion.services.database import db
# Initialize connection
await db.init()
@@ -512,10 +512,10 @@ await db.create_tables()
```bash
# Create database
createdb daemon_boyfriend
createdb loyal_companion
# Run schema
psql -U postgres -d daemon_boyfriend -f schema.sql
psql -U postgres -d loyal_companion -f schema.sql
```
### Docker
@@ -552,7 +552,7 @@ alembic downgrade -1
For JSONB (PostgreSQL) and JSON (SQLite) compatibility:
```python
from daemon_boyfriend.models.base import PortableJSON
from loyal_companion.models.base import PortableJSON
class MyModel(Base):
settings = Column(PortableJSON, default={})
@@ -563,7 +563,7 @@ class MyModel(Base):
Handles timezone-naive datetimes from SQLite:
```python
from daemon_boyfriend.models.base import ensure_utc
from loyal_companion.models.base import ensure_utc
# Safe for both PostgreSQL (already UTC) and SQLite (naive)
utc_time = ensure_utc(model.created_at)

View File

@@ -27,7 +27,7 @@ Practical guides for extending and working with the Daemon Boyfriend codebase.
```bash
# Clone repository
git clone <repository-url>
cd daemon-boyfriend
cd loyal-companion
# Create virtual environment
python -m venv venv
@@ -61,7 +61,7 @@ OPENAI_API_KEY=your_key
```bash
# Run the bot
python -m daemon_boyfriend
python -m loyal_companion
# Or with Docker
docker-compose up -d
@@ -73,7 +73,7 @@ docker-compose up -d
### Step 1: Create Provider Class
Create `src/daemon_boyfriend/services/providers/new_provider.py`:
Create `src/loyal_companion/services/providers/new_provider.py`:
```python
"""New Provider implementation."""
@@ -197,7 +197,7 @@ class Settings(BaseSettings):
# In tests/test_providers.py
import pytest
from daemon_boyfriend.services.providers import NewProvider
from loyal_companion.services.providers import NewProvider
@pytest.mark.asyncio
async def test_new_provider():
@@ -250,8 +250,8 @@ import logging
import discord
from discord.ext import commands
from daemon_boyfriend.config import settings
from daemon_boyfriend.services.database import db
from loyal_companion.config import settings
from loyal_companion.services.database import db
logger = logging.getLogger(__name__)
@@ -313,7 +313,7 @@ from datetime import datetime, timezone
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from daemon_boyfriend.models import User
from loyal_companion.models import User
logger = logging.getLogger(__name__)
@@ -399,7 +399,7 @@ class Settings(BaseSettings):
```python
# In cogs/ai_chat.py
from daemon_boyfriend.services.new_feature_service import NewFeatureService
from loyal_companion.services.new_feature_service import NewFeatureService
class AIChatCog(commands.Cog):
async def _build_enhanced_prompt(self, ...):
@@ -427,7 +427,7 @@ pip install -e ".[dev]"
python -m pytest tests/ -v
# Run with coverage
python -m pytest tests/ --cov=daemon_boyfriend --cov-report=term-missing
python -m pytest tests/ --cov=loyal_companion --cov-report=term-missing
# Run specific test file
python -m pytest tests/test_models.py -v
@@ -442,7 +442,7 @@ python -m pytest tests/test_services.py::TestMoodService -v
# In tests/test_new_feature.py
import pytest
from daemon_boyfriend.services.new_feature_service import NewFeatureService
from loyal_companion.services.new_feature_service import NewFeatureService
class TestNewFeatureService:
@@ -517,7 +517,7 @@ docker-compose down
pip install -r requirements.txt
# Run with process manager (e.g., systemd)
# Create /etc/systemd/system/daemon-boyfriend.service:
# Create /etc/systemd/system/loyal-companion.service:
[Unit]
Description=Daemon Boyfriend Discord Bot
@@ -526,10 +526,10 @@ After=network.target postgresql.service
[Service]
Type=simple
User=daemon
WorkingDirectory=/opt/daemon-boyfriend
Environment="PATH=/opt/daemon-boyfriend/venv/bin"
EnvironmentFile=/opt/daemon-boyfriend/.env
ExecStart=/opt/daemon-boyfriend/venv/bin/python -m daemon_boyfriend
WorkingDirectory=/opt/loyal-companion
Environment="PATH=/opt/loyal-companion/venv/bin"
EnvironmentFile=/opt/loyal-companion/.env
ExecStart=/opt/loyal-companion/venv/bin/python -m loyal_companion
Restart=always
RestartSec=10
@@ -539,18 +539,18 @@ WantedBy=multi-user.target
```bash
# Enable and start
sudo systemctl enable daemon-boyfriend
sudo systemctl start daemon-boyfriend
sudo systemctl enable loyal-companion
sudo systemctl start loyal-companion
```
### Database Setup
```bash
# Create database
sudo -u postgres createdb daemon_boyfriend
sudo -u postgres createdb loyal_companion
# Run schema
psql -U postgres -d daemon_boyfriend -f schema.sql
psql -U postgres -d loyal_companion -f schema.sql
# Or let the bot create tables
# (tables are created automatically on first run)

View File

@@ -328,7 +328,7 @@ class FactExtractionService:
## Example Usage
```python
from daemon_boyfriend.services.fact_extraction_service import FactExtractionService
from loyal_companion.services.fact_extraction_service import FactExtractionService
async with get_session() as session:
fact_service = FactExtractionService(session, ai_service)

View File

@@ -311,7 +311,7 @@ class MoodState:
## Example Usage
```python
from daemon_boyfriend.services.mood_service import MoodService
from loyal_companion.services.mood_service import MoodService
async with get_session() as session:
mood_service = MoodService(session)

View File

@@ -322,7 +322,7 @@ def extract_topics_from_message(message: str) -> list[str]
## Example Usage
```python
from daemon_boyfriend.services.opinion_service import (
from loyal_companion.services.opinion_service import (
OpinionService,
extract_topics_from_message
)

View File

@@ -334,7 +334,7 @@ class RelationshipLevel(Enum):
## Example Usage
```python
from daemon_boyfriend.services.relationship_service import RelationshipService
from loyal_companion.services.relationship_service import RelationshipService
async with get_session() as session:
rel_service = RelationshipService(session)

View File

@@ -28,8 +28,8 @@ Factory and facade for AI providers. Manages provider creation, switching, and p
#### Initialization
```python
from daemon_boyfriend.services.ai_service import AIService
from daemon_boyfriend.config import settings
from loyal_companion.services.ai_service import AIService
from loyal_companion.config import settings
# Use default settings
ai_service = AIService()
@@ -53,7 +53,7 @@ ai_service = AIService(config=custom_settings)
Generate a chat response.
```python
from daemon_boyfriend.services.providers import Message
from loyal_companion.services.providers import Message
response = await ai_service.chat(
messages=[
@@ -109,7 +109,7 @@ Manages database connections and sessions.
#### Global Instance
```python
from daemon_boyfriend.services.database import db, get_db
from loyal_companion.services.database import db, get_db
# Get global instance
db_service = get_db()
@@ -170,7 +170,7 @@ Service for user-related operations.
#### Initialization
```python
from daemon_boyfriend.services.user_service import UserService
from loyal_companion.services.user_service import UserService
async with db.session() as session:
user_service = UserService(session)
@@ -297,7 +297,7 @@ In-memory conversation history manager (used when no database).
#### Initialization
```python
from daemon_boyfriend.services.conversation import ConversationManager
from loyal_companion.services.conversation import ConversationManager
conversation_manager = ConversationManager(max_history=50)
```
@@ -397,7 +397,7 @@ Web search integration using SearXNG.
#### Initialization
```python
from daemon_boyfriend.services.searxng import SearXNGService
from loyal_companion.services.searxng import SearXNGService
searxng = SearXNGService()
```
@@ -444,7 +444,7 @@ Health checks and metrics tracking.
#### Usage
```python
from daemon_boyfriend.services.monitoring import MonitoringService
from loyal_companion.services.monitoring import MonitoringService
monitoring = MonitoringService()
@@ -479,7 +479,7 @@ print(status)
### Base Classes
```python
from daemon_boyfriend.services.providers import (
from loyal_companion.services.providers import (
AIProvider, # Abstract base class
Message, # Chat message
AIResponse, # Response from provider
@@ -541,7 +541,7 @@ class AIProvider(ABC):
### Example: Direct Provider Usage
```python
from daemon_boyfriend.services.providers import OpenAIProvider, Message
from loyal_companion.services.providers import OpenAIProvider, Message
provider = OpenAIProvider(
api_key="sk-...",