from __future__ import annotations import sqlite3 from backend.database.migrations.runner import Migration def upgrade(connection: sqlite3.Connection) -> None: statements = ( """ CREATE TABLE mentor_preferences ( user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, mentor_id TEXT NOT NULL, pinned INTEGER NOT NULL DEFAULT 0 CHECK (pinned IN (0, 1)), sort_order INTEGER NOT NULL DEFAULT 0, updated_at TEXT NOT NULL, PRIMARY KEY (user_id, mentor_id) ) """, """ CREATE TABLE llm_requests ( id TEXT PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, feature TEXT NOT NULL, business_id TEXT NOT NULL, prompt_version TEXT NOT NULL, status TEXT NOT NULL CHECK ( status IN ('reserved', 'streaming', 'success', 'failed', 'stopped') ), started_at TEXT NOT NULL, completed_at TEXT, duration_ms INTEGER NOT NULL DEFAULT 0, error_type TEXT NOT NULL DEFAULT '', input_chars INTEGER NOT NULL DEFAULT 0, output_chars INTEGER NOT NULL DEFAULT 0 ) """, "CREATE INDEX llm_requests_user_started_idx ON llm_requests(user_id, started_at)", """ CREATE TABLE llm_attempts ( id INTEGER PRIMARY KEY AUTOINCREMENT, request_id TEXT NOT NULL REFERENCES llm_requests(id) ON DELETE CASCADE, model_id INTEGER REFERENCES llm_models(id) ON DELETE SET NULL, role TEXT NOT NULL CHECK (role IN ('primary', 'fallback')), status TEXT NOT NULL CHECK (status IN ('streaming', 'success', 'failed', 'stopped')), started_at TEXT NOT NULL, completed_at TEXT, duration_ms INTEGER NOT NULL DEFAULT 0, error_type TEXT NOT NULL DEFAULT '', input_chars INTEGER NOT NULL DEFAULT 0, output_chars INTEGER NOT NULL DEFAULT 0 ) """, "CREATE INDEX llm_attempts_request_idx ON llm_attempts(request_id, id)", """ CREATE TABLE mentor_messages ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, mentor_id TEXT NOT NULL, trade_date TEXT NOT NULL, role TEXT NOT NULL CHECK (role IN ('user', 'assistant')), content TEXT NOT NULL, request_id TEXT REFERENCES llm_requests(id) ON DELETE SET NULL, status TEXT NOT NULL CHECK (status IN ('complete', 'stopped', 'error')), created_at TEXT NOT NULL ) """, """ CREATE INDEX mentor_messages_scope_idx ON mentor_messages(user_id, mentor_id, trade_date, id) """, ) for statement in statements: connection.execute(statement) def downgrade(connection: sqlite3.Connection) -> None: for table in ( "mentor_messages", "llm_attempts", "llm_requests", "mentor_preferences", ): connection.execute(f"DROP TABLE {table}") MIGRATION = Migration( version=8, name="create_mentor_and_llm_audit", signature="mentor-llm:v1:preferences-messages-requests-attempts", upgrade=upgrade, downgrade=downgrade, )