feat(01-02): create Project, Discussion, Round, Message, Consensus models
- Add Project model: id, name, created/updated_at, models (JSON), settings (JSON) - Add Discussion model: id, project_id (FK), question, type, status, created_at - Add Round model: id, discussion_id (FK), round_number, type - Add Message model: id, round_id (FK), model, content, timestamp, is_direct - Add Consensus model: id, discussion_id (FK unique), agreements, disagreements, generated_at/by - Configure bidirectional relationships with cascade delete-orphan - All FKs reference correct tables, all type hints present
This commit is contained in:
parent
61da27c7d5
commit
a0de94141b
1 changed files with 153 additions and 2 deletions
|
|
@ -8,9 +8,16 @@ All IDs use UUID stored as String(36) for SQLite compatibility.
|
||||||
Enums are stored as strings for database portability.
|
Enums are stored as strings for database portability.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from enum import Enum
|
from __future__ import annotations
|
||||||
|
|
||||||
from sqlalchemy.orm import DeclarativeBase
|
from datetime import datetime
|
||||||
|
from enum import Enum
|
||||||
|
from typing import Any
|
||||||
|
from uuid import uuid4
|
||||||
|
|
||||||
|
from sqlalchemy import JSON, DateTime, ForeignKey, String, Text
|
||||||
|
from sqlalchemy import Enum as SAEnum
|
||||||
|
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship
|
||||||
|
|
||||||
|
|
||||||
class Base(DeclarativeBase):
|
class Base(DeclarativeBase):
|
||||||
|
|
@ -38,3 +45,147 @@ class RoundType(str, Enum):
|
||||||
|
|
||||||
PARALLEL = "parallel"
|
PARALLEL = "parallel"
|
||||||
SEQUENTIAL = "sequential"
|
SEQUENTIAL = "sequential"
|
||||||
|
|
||||||
|
|
||||||
|
def _uuid() -> str:
|
||||||
|
"""Generate a new UUID string."""
|
||||||
|
return str(uuid4())
|
||||||
|
|
||||||
|
|
||||||
|
class Project(Base):
|
||||||
|
"""A project container for related discussions.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
id: Unique identifier (UUID).
|
||||||
|
name: Human-readable project name.
|
||||||
|
created_at: When the project was created.
|
||||||
|
updated_at: When the project was last modified.
|
||||||
|
models: List of AI model identifiers (e.g., ["claude", "gpt", "gemini"]).
|
||||||
|
settings: Configuration dict (default_rounds, consensus_threshold, system_prompt_override).
|
||||||
|
discussions: Related discussions in this project.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = "project"
|
||||||
|
|
||||||
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=_uuid)
|
||||||
|
name: Mapped[str] = mapped_column(String(255))
|
||||||
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||||
|
updated_at: Mapped[datetime] = mapped_column(
|
||||||
|
DateTime, default=datetime.utcnow, onupdate=datetime.utcnow
|
||||||
|
)
|
||||||
|
models: Mapped[Any] = mapped_column(JSON, default=list)
|
||||||
|
settings: Mapped[Any] = mapped_column(JSON, default=dict)
|
||||||
|
|
||||||
|
discussions: Mapped[list[Discussion]] = relationship(
|
||||||
|
back_populates="project", cascade="all, delete-orphan"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Discussion(Base):
|
||||||
|
"""A discussion within a project.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
id: Unique identifier (UUID).
|
||||||
|
project_id: FK to parent project.
|
||||||
|
question: The question or topic being discussed.
|
||||||
|
type: Whether this is an "open" or "discuss" mode discussion.
|
||||||
|
status: Current status (active or completed).
|
||||||
|
created_at: When the discussion started.
|
||||||
|
project: Parent project relationship.
|
||||||
|
rounds: Discussion rounds.
|
||||||
|
consensus: Generated consensus (if any).
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = "discussion"
|
||||||
|
|
||||||
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=_uuid)
|
||||||
|
project_id: Mapped[str] = mapped_column(ForeignKey("project.id"))
|
||||||
|
question: Mapped[str] = mapped_column(Text)
|
||||||
|
type: Mapped[DiscussionType] = mapped_column(SAEnum(DiscussionType))
|
||||||
|
status: Mapped[DiscussionStatus] = mapped_column(
|
||||||
|
SAEnum(DiscussionStatus), default=DiscussionStatus.ACTIVE
|
||||||
|
)
|
||||||
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||||
|
|
||||||
|
project: Mapped[Project] = relationship(back_populates="discussions")
|
||||||
|
rounds: Mapped[list[Round]] = relationship(
|
||||||
|
back_populates="discussion", cascade="all, delete-orphan"
|
||||||
|
)
|
||||||
|
consensus: Mapped[Consensus | None] = relationship(
|
||||||
|
back_populates="discussion", uselist=False, cascade="all, delete-orphan"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Round(Base):
|
||||||
|
"""A round within a discussion.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
id: Unique identifier (UUID).
|
||||||
|
discussion_id: FK to parent discussion.
|
||||||
|
round_number: Sequential round number within the discussion.
|
||||||
|
type: Whether this round is parallel or sequential.
|
||||||
|
discussion: Parent discussion relationship.
|
||||||
|
messages: Messages from AI models in this round.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = "round"
|
||||||
|
|
||||||
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=_uuid)
|
||||||
|
discussion_id: Mapped[str] = mapped_column(ForeignKey("discussion.id"))
|
||||||
|
round_number: Mapped[int]
|
||||||
|
type: Mapped[RoundType] = mapped_column(SAEnum(RoundType))
|
||||||
|
|
||||||
|
discussion: Mapped[Discussion] = relationship(back_populates="rounds")
|
||||||
|
messages: Mapped[list[Message]] = relationship(
|
||||||
|
back_populates="round", cascade="all, delete-orphan"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Message(Base):
|
||||||
|
"""A message from an AI model within a round.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
id: Unique identifier (UUID).
|
||||||
|
round_id: FK to parent round.
|
||||||
|
model: AI model identifier (e.g., "claude", "gpt", "gemini").
|
||||||
|
content: The message content.
|
||||||
|
timestamp: When the message was created.
|
||||||
|
is_direct: True if this was a direct @mention to this model.
|
||||||
|
round: Parent round relationship.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = "message"
|
||||||
|
|
||||||
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=_uuid)
|
||||||
|
round_id: Mapped[str] = mapped_column(ForeignKey("round.id"))
|
||||||
|
model: Mapped[str] = mapped_column(String(50))
|
||||||
|
content: Mapped[str] = mapped_column(Text)
|
||||||
|
timestamp: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||||
|
is_direct: Mapped[bool] = mapped_column(default=False)
|
||||||
|
|
||||||
|
round: Mapped[Round] = relationship(back_populates="messages")
|
||||||
|
|
||||||
|
|
||||||
|
class Consensus(Base):
|
||||||
|
"""Generated consensus summary for a discussion.
|
||||||
|
|
||||||
|
Attributes:
|
||||||
|
id: Unique identifier (UUID).
|
||||||
|
discussion_id: FK to parent discussion (unique - one consensus per discussion).
|
||||||
|
agreements: List of bullet point strings for agreed items.
|
||||||
|
disagreements: List of {topic, positions: {model: position}} dicts.
|
||||||
|
generated_at: When the consensus was generated.
|
||||||
|
generated_by: Which model generated this summary.
|
||||||
|
discussion: Parent discussion relationship.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__tablename__ = "consensus"
|
||||||
|
|
||||||
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=_uuid)
|
||||||
|
discussion_id: Mapped[str] = mapped_column(ForeignKey("discussion.id"), unique=True)
|
||||||
|
agreements: Mapped[Any] = mapped_column(JSON, default=list)
|
||||||
|
disagreements: Mapped[Any] = mapped_column(JSON, default=list)
|
||||||
|
generated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||||
|
generated_by: Mapped[str] = mapped_column(String(50))
|
||||||
|
|
||||||
|
discussion: Mapped[Discussion] = relationship(back_populates="consensus")
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue