from sqlalchemy import text from sqlmodel import SQLModel, Session, create_engine from core.settings import DATABASE_ECHO, DATABASE_URL # Ensure table models are registered in SQLModel metadata before create_all. from models import bot as _bot_models # noqa: F401 engine = create_engine(DATABASE_URL, echo=DATABASE_ECHO) def _ensure_botinstance_columns() -> None: required_columns = { "current_state": "TEXT DEFAULT 'IDLE'", "last_action": "TEXT", "soul_md": "TEXT", "agents_md": "TEXT", "user_md": "TEXT", "tools_md": "TEXT", "tools_config_json": "TEXT", "identity_md": "TEXT", "api_base": "TEXT", "temperature": "REAL DEFAULT 0.2", "top_p": "REAL DEFAULT 1.0", "max_tokens": "INTEGER DEFAULT 8192", "presence_penalty": "REAL DEFAULT 0.0", "frequency_penalty": "REAL DEFAULT 0.0", "send_progress": "BOOLEAN DEFAULT 0", "send_tool_hints": "BOOLEAN DEFAULT 0", } with engine.connect() as conn: existing_rows = conn.execute(text("PRAGMA table_info(botinstance)")).fetchall() existing = {str(row[1]) for row in existing_rows} for col, ddl in required_columns.items(): if col in existing: continue conn.execute(text(f"ALTER TABLE botinstance ADD COLUMN {col} {ddl}")) conn.commit() def _ensure_botmessage_columns() -> None: required_columns = { "media_json": "TEXT", } with engine.connect() as conn: existing_rows = conn.execute(text("PRAGMA table_info(botmessage)")).fetchall() existing = {str(row[1]) for row in existing_rows} for col, ddl in required_columns.items(): if col in existing: continue conn.execute(text(f"ALTER TABLE botmessage ADD COLUMN {col} {ddl}")) conn.commit() def _drop_legacy_skill_tables() -> None: """Drop deprecated skill registry tables (moved to workspace filesystem mode).""" with engine.connect() as conn: conn.execute(text("DROP TABLE IF EXISTS botskillmapping")) conn.execute(text("DROP TABLE IF EXISTS skillregistry")) conn.commit() def _drop_legacy_channel_tables() -> None: """Drop deprecated channel route table (channel config source moved to config.json).""" with engine.connect() as conn: conn.execute(text("DROP TABLE IF EXISTS channelroute")) conn.commit() def init_database() -> None: SQLModel.metadata.create_all(engine) _drop_legacy_skill_tables() _drop_legacy_channel_tables() _ensure_botinstance_columns() _ensure_botmessage_columns() def get_session(): with Session(engine) as session: yield session