"""Initial schema -- all application tables. Revision ID: a1b2c3d4e5f6 Revises: Create Date: 2026-04-06 """ from __future__ import annotations from alembic import op revision: str = "a1b2c3d4e5f6" down_revision: str | None = None branch_labels: tuple[str, ...] | None = None depends_on: tuple[str, ...] | None = None def upgrade() -> None: op.execute( """ CREATE TABLE IF NOT EXISTS conversations ( thread_id TEXT PRIMARY KEY, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), last_activity TIMESTAMPTZ NOT NULL DEFAULT NOW(), total_tokens INTEGER NOT NULL DEFAULT 0, total_cost_usd DOUBLE PRECISION NOT NULL DEFAULT 0.0, status TEXT NOT NULL DEFAULT 'active' ) """ ) op.execute( """ CREATE TABLE IF NOT EXISTS active_interrupts ( interrupt_id TEXT PRIMARY KEY, thread_id TEXT NOT NULL REFERENCES conversations(thread_id), action TEXT NOT NULL, params JSONB NOT NULL DEFAULT '{}', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), resolved_at TIMESTAMPTZ, resolution TEXT ) """ ) op.execute( """ CREATE TABLE IF NOT EXISTS sessions ( thread_id TEXT PRIMARY KEY, last_activity TIMESTAMPTZ NOT NULL DEFAULT NOW(), has_pending_interrupt BOOLEAN NOT NULL DEFAULT FALSE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ) """ ) op.execute( """ CREATE TABLE IF NOT EXISTS analytics_events ( id BIGSERIAL PRIMARY KEY, thread_id TEXT NOT NULL, event_type TEXT NOT NULL, agent_name TEXT, tool_name TEXT, tokens_used INTEGER NOT NULL DEFAULT 0, cost_usd DOUBLE PRECISION NOT NULL DEFAULT 0.0, duration_ms INTEGER, success BOOLEAN, error_message TEXT, metadata JSONB NOT NULL DEFAULT '{}', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ) """ ) # Migration columns added in Phase 4 op.execute( """ ALTER TABLE conversations ADD COLUMN IF NOT EXISTS resolution_type TEXT, ADD COLUMN IF NOT EXISTS agents_used TEXT[], ADD COLUMN IF NOT EXISTS turn_count INTEGER NOT NULL DEFAULT 0, ADD COLUMN IF NOT EXISTS ended_at TIMESTAMPTZ """ ) def downgrade() -> None: op.execute("DROP TABLE IF EXISTS analytics_events") op.execute("DROP TABLE IF EXISTS sessions") op.execute("DROP TABLE IF EXISTS active_interrupts") op.execute("DROP TABLE IF EXISTS conversations")