from __future__ import annotations from sqlalchemy import ( CheckConstraint, Column, DateTime, ForeignKey, Index, Integer, MetaData, String, Table, UniqueConstraint, ) from sqlalchemy.dialects.postgresql import JSONB def build_session_tables(schema: str) -> tuple[MetaData, dict[str, Table]]: """Build the core Resume Agent tables in the supplied PostgreSQL schema.""" metadata = MetaData(schema=schema) sessions = Table( "sessions", metadata, Column("id", String(128), primary_key=True), Column("stage", String(64), nullable=False), Column("revision", Integer, nullable=False, default=0), Column("profile", JSONB, nullable=False), Column("draft_id", String(128)), Column("resume_id", String(128)), Column("created_at", DateTime(timezone=True), nullable=False), Column("updated_at", DateTime(timezone=True), nullable=False), ) turns = Table( "turns", metadata, Column("id", String(128), primary_key=True), Column("session_id", String(128), ForeignKey(f"{schema}.sessions.id", ondelete="CASCADE"), nullable=False), Column("sequence", Integer, nullable=False), Column("role", String(32), nullable=False), Column("content", String), Column("composer_mode", String(32), nullable=False), Column("created_at", DateTime(timezone=True), nullable=False), UniqueConstraint("session_id", "sequence", name="uq_turn_session_sequence"), ) blocks = Table( "blocks", metadata, Column("id", String(128), primary_key=True), Column("session_id", String(128), ForeignKey(f"{schema}.sessions.id", ondelete="CASCADE"), nullable=False), Column("turn_id", String(128), ForeignKey(f"{schema}.turns.id", ondelete="CASCADE"), nullable=False), Column("block_index", Integer, nullable=False), Column("type", String(32), nullable=False), Column("lifecycle", String(32), nullable=False), Column("data", JSONB, nullable=False), Column("version", Integer, nullable=False, default=1), Column("created_at", DateTime(timezone=True), nullable=False), Column("updated_at", DateTime(timezone=True), nullable=False), UniqueConstraint("turn_id", "block_index", name="uq_block_turn_index"), ) resumes = Table( "resumes", metadata, Column("id", String(128), primary_key=True), Column("session_id", String(128), ForeignKey(f"{schema}.sessions.id", ondelete="CASCADE"), nullable=False, unique=True), Column("idempotency_key", String(128)), Column("revision", Integer, nullable=False, default=1), Column("content", JSONB, nullable=False), Column("created_at", DateTime(timezone=True), nullable=False), Column("updated_at", DateTime(timezone=True), nullable=False), CheckConstraint("revision >= 1", name="ck_resume_revision_positive"), ) resume_imports = Table( "resume_imports", metadata, Column("id", String(128), primary_key=True), Column( "session_id", String(128), ForeignKey(f"{schema}.sessions.id", ondelete="CASCADE"), nullable=False, ), Column("file_name", String(512), nullable=False), Column("mime_type", String(128), nullable=False), Column("size_bytes", Integer, nullable=False), Column("sha256", String(64), nullable=False), Column("object_key", String(512), nullable=False), Column("status", String(32), nullable=False), Column("document", JSONB), Column("field_reviews", JSONB, nullable=False, default=list), Column("error_code", String(128)), Column("created_at", DateTime(timezone=True), nullable=False), Column("updated_at", DateTime(timezone=True), nullable=False), UniqueConstraint("session_id", "sha256", name="uq_resume_import_session_sha256"), CheckConstraint("size_bytes >= 0", name="ck_resume_import_size_nonnegative"), ) Index("ix_resume_imports_session_created", resume_imports.c.session_id, resume_imports.c.created_at) optimization_runs = Table( "optimization_runs", metadata, Column("id", String(128), primary_key=True), Column("session_id", String(128), ForeignKey(f"{schema}.sessions.id", ondelete="CASCADE"), nullable=False), Column("entry_id", String(128), nullable=False), Column("mode", String(32), nullable=False), Column("status", String(32), nullable=False), Column("source_revision", Integer, nullable=False), Column("state", JSONB, nullable=False), Column("proposal", JSONB), Column("created_at", DateTime(timezone=True), nullable=False), Column("updated_at", DateTime(timezone=True), nullable=False), CheckConstraint("source_revision >= 1", name="ck_optimization_source_revision_positive"), ) Index("ix_optimization_runs_active", optimization_runs.c.session_id, optimization_runs.c.entry_id, optimization_runs.c.status) Index("ix_turns_session_sequence", turns.c.session_id, turns.c.sequence) Index("ix_blocks_session_turn_index", blocks.c.session_id, blocks.c.turn_id, blocks.c.block_index) return metadata, { "sessions": sessions, "turns": turns, "blocks": blocks, "resumes": resumes, "resume_imports": resume_imports, "optimization_runs": optimization_runs, }