148 lines
6.2 KiB
Python
148 lines
6.2 KiB
Python
import aiosqlite
|
|
import os
|
|
|
|
DB_PATH = os.getenv("DB_PATH", "data/chat.db")
|
|
|
|
|
|
async def init_db():
|
|
os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
|
|
async with aiosqlite.connect(DB_PATH) as db:
|
|
await db.executescript("""
|
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
session_id TEXT PRIMARY KEY,
|
|
persona_id TEXT DEFAULT 'default',
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
title TEXT DEFAULT 'Новый чат',
|
|
rpg_enabled INTEGER DEFAULT 0,
|
|
facts_json TEXT DEFAULT '[]',
|
|
global_plot TEXT DEFAULT '',
|
|
status_quo TEXT DEFAULT '',
|
|
plot_arc_json TEXT DEFAULT '{}',
|
|
rng_seed INTEGER
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS messages (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
session_id TEXT NOT NULL,
|
|
role TEXT NOT NULL,
|
|
content TEXT NOT NULL,
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
FOREIGN KEY (session_id) REFERENCES sessions(session_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_messages_session
|
|
ON messages(session_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS personas (
|
|
persona_id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
emoji TEXT DEFAULT '🤖',
|
|
description TEXT DEFAULT '',
|
|
prompt TEXT NOT NULL,
|
|
custom INTEGER DEFAULT 1,
|
|
sd_enabled INTEGER DEFAULT 0,
|
|
lora_name TEXT DEFAULT '',
|
|
lora_weight REAL DEFAULT 0.8,
|
|
appearance_tags TEXT DEFAULT '',
|
|
personality TEXT DEFAULT '',
|
|
scenario TEXT DEFAULT '',
|
|
first_mes TEXT DEFAULT '',
|
|
mes_example TEXT DEFAULT '',
|
|
lorebook_json TEXT DEFAULT '[]',
|
|
avatar_path TEXT DEFAULT ''
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS characters (
|
|
card_id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
description TEXT DEFAULT '',
|
|
personality TEXT DEFAULT '',
|
|
scenario TEXT DEFAULT '',
|
|
first_mes TEXT DEFAULT '',
|
|
mes_example TEXT DEFAULT '',
|
|
raw_json TEXT NOT NULL,
|
|
lora_name TEXT DEFAULT '',
|
|
lora_weight REAL DEFAULT 0.8,
|
|
appearance_tags TEXT DEFAULT '',
|
|
lorebook_json TEXT DEFAULT '[]',
|
|
avatar_path TEXT DEFAULT '',
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
""")
|
|
await _migrate_messages_columns(db)
|
|
await _migrate_personas_columns(db)
|
|
await _migrate_sessions_columns(db)
|
|
await _migrate_characters_columns(db)
|
|
await _migrate_action_resolutions(db)
|
|
await db.commit()
|
|
|
|
|
|
async def _migrate_messages_columns(db):
|
|
async with db.execute("PRAGMA table_info(messages)") as cur:
|
|
cols = {row[1] for row in await cur.fetchall()}
|
|
if "image_prompt" not in cols:
|
|
await db.execute("ALTER TABLE messages ADD COLUMN image_prompt TEXT")
|
|
if "image_path" not in cols:
|
|
await db.execute("ALTER TABLE messages ADD COLUMN image_path TEXT")
|
|
|
|
|
|
async def _migrate_personas_columns(db):
|
|
async with db.execute("PRAGMA table_info(personas)") as cur:
|
|
cols = {row[1] for row in await cur.fetchall()}
|
|
if "personality" not in cols:
|
|
await db.execute("ALTER TABLE personas ADD COLUMN personality TEXT DEFAULT ''")
|
|
if "scenario" not in cols:
|
|
await db.execute("ALTER TABLE personas ADD COLUMN scenario TEXT DEFAULT ''")
|
|
if "first_mes" not in cols:
|
|
await db.execute("ALTER TABLE personas ADD COLUMN first_mes TEXT DEFAULT ''")
|
|
if "mes_example" not in cols:
|
|
await db.execute("ALTER TABLE personas ADD COLUMN mes_example TEXT DEFAULT ''")
|
|
if "lorebook_json" not in cols:
|
|
await db.execute("ALTER TABLE personas ADD COLUMN lorebook_json TEXT DEFAULT '[]'")
|
|
if "avatar_path" not in cols:
|
|
await db.execute("ALTER TABLE personas ADD COLUMN avatar_path TEXT DEFAULT ''")
|
|
|
|
|
|
async def _migrate_sessions_columns(db):
|
|
async with db.execute("PRAGMA table_info(sessions)") as cur:
|
|
cols = {row[1] for row in await cur.fetchall()}
|
|
if "rpg_enabled" not in cols:
|
|
await db.execute("ALTER TABLE sessions ADD COLUMN rpg_enabled INTEGER DEFAULT 0")
|
|
if "facts_json" not in cols:
|
|
await db.execute("ALTER TABLE sessions ADD COLUMN facts_json TEXT DEFAULT '[]'")
|
|
if "global_plot" not in cols:
|
|
await db.execute("ALTER TABLE sessions ADD COLUMN global_plot TEXT DEFAULT ''")
|
|
if "status_quo" not in cols:
|
|
await db.execute("ALTER TABLE sessions ADD COLUMN status_quo TEXT DEFAULT ''")
|
|
if "plot_arc_json" not in cols:
|
|
await db.execute("ALTER TABLE sessions ADD COLUMN plot_arc_json TEXT DEFAULT '{}'")
|
|
if "rng_seed" not in cols:
|
|
await db.execute("ALTER TABLE sessions ADD COLUMN rng_seed INTEGER")
|
|
|
|
|
|
async def _migrate_action_resolutions(db):
|
|
await db.executescript(
|
|
"""
|
|
CREATE TABLE IF NOT EXISTS action_resolutions (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
session_id TEXT NOT NULL,
|
|
message_id INTEGER,
|
|
intent_text TEXT NOT NULL,
|
|
roll INTEGER NOT NULL,
|
|
outcome TEXT NOT NULL,
|
|
resolution_text TEXT NOT NULL,
|
|
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_action_resolutions_session
|
|
ON action_resolutions(session_id);
|
|
"""
|
|
)
|
|
|
|
|
|
async def _migrate_characters_columns(db):
|
|
async with db.execute("PRAGMA table_info(characters)") as cur:
|
|
cols = {row[1] for row in await cur.fetchall()}
|
|
if "avatar_path" not in cols:
|
|
await db.execute("ALTER TABLE characters ADD COLUMN avatar_path TEXT DEFAULT ''")
|