feat: split initial social schema migration chain
replace monolithic migration with ordered scripts, include profiles/sessions in migration, and verify full downgrade/upgrade cycle for clean Supabase bootstrap
This commit is contained in:
@@ -2,14 +2,34 @@ from __future__ import annotations
|
||||
|
||||
from models.agent_chat_message import AgentChatMessage
|
||||
from models.agent_chat_session import AgentChatSession
|
||||
from models.automation_jobs import AutomationJob
|
||||
from models.group_members import GroupMember
|
||||
from models.groups import Group
|
||||
from models.inbox_messages import InboxMessage
|
||||
from models.llm import Llm
|
||||
from models.llm_factory import LlmFactory
|
||||
from models.memories import Memory
|
||||
from models.profile import Profile
|
||||
from models.schedule_items import ScheduleItem
|
||||
from models.schedule_subscriptions import ScheduleSubscription
|
||||
from models.todos import Todo
|
||||
from models.todo_sources import TodoSource
|
||||
from models.user_agents import UserAgent
|
||||
|
||||
__all__ = [
|
||||
"AgentChatMessage",
|
||||
"AgentChatSession",
|
||||
"AutomationJob",
|
||||
"GroupMember",
|
||||
"Group",
|
||||
"InboxMessage",
|
||||
"Llm",
|
||||
"LlmFactory",
|
||||
"Memory",
|
||||
"Profile",
|
||||
"ScheduleItem",
|
||||
"ScheduleSubscription",
|
||||
"Todo",
|
||||
"TodoSource",
|
||||
"UserAgent",
|
||||
]
|
||||
|
||||
@@ -8,7 +8,6 @@ from enum import Enum
|
||||
from sqlalchemy import (
|
||||
DateTime,
|
||||
Enum as SqlEnum,
|
||||
ForeignKey,
|
||||
Integer,
|
||||
Numeric,
|
||||
String,
|
||||
@@ -28,18 +27,32 @@ class AgentChatSessionStatus(str, Enum):
|
||||
FAILED = "failed"
|
||||
|
||||
|
||||
class SessionType(str, Enum):
|
||||
CHAT = "chat"
|
||||
AUTOMATION = "automation"
|
||||
|
||||
|
||||
class AgentChatSession(TimestampMixin, SoftDeleteMixin, Base):
|
||||
__tablename__: str = "sessions"
|
||||
__table_args__ = {"extend_existing": True}
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
)
|
||||
user_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
ForeignKey("auth.users.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
index=True,
|
||||
)
|
||||
session_type: Mapped[SessionType] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
default=SessionType.CHAT,
|
||||
)
|
||||
job_id: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
title: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
status: Mapped[AgentChatSessionStatus] = mapped_column(
|
||||
SqlEnum(
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
|
||||
from sqlalchemy import DateTime, String, Text
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from core.db.base import Base, SoftDeleteMixin, TimestampMixin
|
||||
|
||||
|
||||
class AutomationJobStatus(str, Enum):
|
||||
ACTIVE = "active"
|
||||
DISABLED = "disabled"
|
||||
|
||||
|
||||
class ScheduleType(str, Enum):
|
||||
DAILY = "daily"
|
||||
WEEKLY = "weekly"
|
||||
|
||||
|
||||
class AutomationJob(TimestampMixin, SoftDeleteMixin, Base):
|
||||
__tablename__: str = "automation_jobs"
|
||||
__table_args__ = {"extend_existing": True}
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
)
|
||||
owner_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=False,
|
||||
)
|
||||
title: Mapped[str] = mapped_column(
|
||||
String(255),
|
||||
nullable=False,
|
||||
)
|
||||
prompt: Mapped[str] = mapped_column(
|
||||
Text,
|
||||
nullable=False,
|
||||
)
|
||||
schedule_type: Mapped[ScheduleType] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
)
|
||||
run_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True),
|
||||
nullable=False,
|
||||
)
|
||||
next_run_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True),
|
||||
nullable=False,
|
||||
)
|
||||
timezone: Mapped[str] = mapped_column(
|
||||
String(50),
|
||||
nullable=False,
|
||||
default="UTC",
|
||||
)
|
||||
last_run_at: Mapped[datetime | None] = mapped_column(
|
||||
DateTime(timezone=True),
|
||||
nullable=True,
|
||||
)
|
||||
status: Mapped[AutomationJobStatus] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
default=AutomationJobStatus.ACTIVE,
|
||||
)
|
||||
created_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
@@ -0,0 +1,64 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from enum import Enum
|
||||
|
||||
from sqlalchemy import String
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from core.db.base import Base, SoftDeleteMixin, TimestampMixin
|
||||
|
||||
|
||||
class FriendshipStatus(str, Enum):
|
||||
PENDING = "pending"
|
||||
ACCEPTED = "accepted"
|
||||
BLOCKED = "blocked"
|
||||
DECLINED = "declined"
|
||||
CANCELED = "canceled"
|
||||
|
||||
|
||||
class Friendship(TimestampMixin, SoftDeleteMixin, Base):
|
||||
__tablename__: str = "friendships"
|
||||
__table_args__ = {"extend_existing": True}
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
)
|
||||
user_low_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=False,
|
||||
)
|
||||
user_high_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=False,
|
||||
)
|
||||
initiator_id: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
status: Mapped[FriendshipStatus] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
default=FriendshipStatus.PENDING,
|
||||
)
|
||||
requested_at: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
accepted_at: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
blocked_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
created_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
updated_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
@@ -0,0 +1,77 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from enum import Enum
|
||||
|
||||
from sqlalchemy import String
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from core.db.base import Base, SoftDeleteMixin, TimestampMixin
|
||||
|
||||
|
||||
class GroupMemberRole(str, Enum):
|
||||
OWNER = "owner"
|
||||
ADMIN = "admin"
|
||||
MEMBER = "member"
|
||||
|
||||
|
||||
class GroupMemberSource(str, Enum):
|
||||
INVITED = "invited"
|
||||
JOINED = "joined"
|
||||
|
||||
|
||||
class GroupMemberStatus(str, Enum):
|
||||
ACTIVE = "active"
|
||||
MUTED = "muted"
|
||||
REMOVED = "removed"
|
||||
|
||||
|
||||
class GroupMember(TimestampMixin, SoftDeleteMixin, Base):
|
||||
__tablename__: str = "group_members"
|
||||
__table_args__ = {"extend_existing": True}
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
)
|
||||
group_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=False,
|
||||
)
|
||||
user_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=False,
|
||||
)
|
||||
role: Mapped[GroupMemberRole] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
)
|
||||
join_source: Mapped[GroupMemberSource] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
)
|
||||
invited_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
joined_at: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
removed_at: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
status: Mapped[GroupMemberStatus] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
default=GroupMemberStatus.ACTIVE,
|
||||
)
|
||||
created_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
updated_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
@@ -0,0 +1,49 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from enum import Enum
|
||||
|
||||
from sqlalchemy import String, Text
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from core.db.base import Base, SoftDeleteMixin, TimestampMixin
|
||||
|
||||
|
||||
class GroupStatus(str, Enum):
|
||||
ACTIVE = "active"
|
||||
ARCHIVED = "archived"
|
||||
|
||||
|
||||
class Group(TimestampMixin, SoftDeleteMixin, Base):
|
||||
__tablename__: str = "groups"
|
||||
__table_args__ = {"extend_existing": True}
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
)
|
||||
name: Mapped[str] = mapped_column(
|
||||
String(100),
|
||||
nullable=False,
|
||||
)
|
||||
description: Mapped[str | None] = mapped_column(
|
||||
Text,
|
||||
nullable=True,
|
||||
)
|
||||
owner_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=False,
|
||||
)
|
||||
status: Mapped[GroupStatus] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
default=GroupStatus.ACTIVE,
|
||||
)
|
||||
created_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
updated_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
@@ -0,0 +1,75 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from enum import Enum
|
||||
|
||||
from sqlalchemy import String, Text
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from core.db.base import Base, TimestampMixin
|
||||
|
||||
|
||||
class InboxMessageType(str, Enum):
|
||||
FRIEND_REQUEST = "friend_request"
|
||||
CALENDAR = "calendar"
|
||||
SYSTEM = "system"
|
||||
GROUP = "group"
|
||||
|
||||
|
||||
class InboxMessageStatus(str, Enum):
|
||||
PENDING = "pending"
|
||||
ACCEPTED = "accepted"
|
||||
REJECTED = "rejected"
|
||||
DISMISSED = "dismissed"
|
||||
|
||||
|
||||
class InboxMessage(TimestampMixin, Base):
|
||||
__tablename__: str = "inbox_messages"
|
||||
__table_args__ = {"extend_existing": True}
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
)
|
||||
recipient_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=False,
|
||||
)
|
||||
sender_id: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
message_type: Mapped[InboxMessageType] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
)
|
||||
friendship_id: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
schedule_item_id: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
group_id: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
content: Mapped[str | None] = mapped_column(
|
||||
Text,
|
||||
nullable=True,
|
||||
)
|
||||
is_read: Mapped[bool] = mapped_column(
|
||||
String(10),
|
||||
nullable=False,
|
||||
default=False,
|
||||
)
|
||||
status: Mapped[InboxMessageStatus] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
default=InboxMessageStatus.PENDING,
|
||||
)
|
||||
created_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
@@ -0,0 +1,61 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from enum import Enum
|
||||
|
||||
from sqlalchemy import String
|
||||
from sqlalchemy.dialects.postgresql import JSONB, UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from core.db.base import Base, TimestampMixin
|
||||
|
||||
|
||||
class MemoryType(str, Enum):
|
||||
USER = "user"
|
||||
WORK = "work"
|
||||
|
||||
|
||||
class MemorySource(str, Enum):
|
||||
MANUAL = "manual"
|
||||
AGENT = "agent"
|
||||
IMPORTED = "imported"
|
||||
|
||||
|
||||
class MemoryStatus(str, Enum):
|
||||
ACTIVE = "active"
|
||||
DISABLED = "disabled"
|
||||
|
||||
|
||||
class Memory(TimestampMixin, Base):
|
||||
__tablename__: str = "memories"
|
||||
__table_args__ = {"extend_existing": True}
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
)
|
||||
owner_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=False,
|
||||
)
|
||||
agent_id: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
memory_type: Mapped[MemoryType] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
)
|
||||
title: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
content: Mapped[dict] = mapped_column(
|
||||
JSONB,
|
||||
nullable=False,
|
||||
)
|
||||
source: Mapped[MemorySource] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
)
|
||||
status: Mapped[MemoryStatus] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
default=MemoryStatus.ACTIVE,
|
||||
)
|
||||
@@ -2,8 +2,8 @@ from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
|
||||
from sqlalchemy import ForeignKey, String, Text
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy import String, Text
|
||||
from sqlalchemy.dialects.postgresql import JSONB, UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from core.db.base import Base, SoftDeleteMixin, TimestampMixin
|
||||
@@ -18,10 +18,10 @@ class Profile(TimestampMixin, SoftDeleteMixin, Base):
|
||||
"""
|
||||
|
||||
__tablename__: str = "profiles"
|
||||
__table_args__ = {"extend_existing": True}
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
ForeignKey("auth.users.id", ondelete="CASCADE"),
|
||||
primary_key=True,
|
||||
)
|
||||
username: Mapped[str] = mapped_column(
|
||||
@@ -37,3 +37,8 @@ class Profile(TimestampMixin, SoftDeleteMixin, Base):
|
||||
String(200),
|
||||
nullable=True,
|
||||
)
|
||||
settings: Mapped[dict] = mapped_column(
|
||||
JSONB,
|
||||
nullable=False,
|
||||
server_default="{}",
|
||||
)
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
|
||||
from sqlalchemy import DateTime, String, Text
|
||||
from sqlalchemy.dialects.postgresql import JSONB, UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from core.db.base import Base, SoftDeleteMixin, TimestampMixin
|
||||
|
||||
|
||||
class ScheduleItemStatus(str, Enum):
|
||||
ACTIVE = "active"
|
||||
COMPLETED = "completed"
|
||||
CANCELED = "canceled"
|
||||
ARCHIVED = "archived"
|
||||
|
||||
|
||||
class ScheduleItemSourceType(str, Enum):
|
||||
MANUAL = "manual"
|
||||
IMPORTED = "imported"
|
||||
AGENT_GENERATED = "agent_generated"
|
||||
|
||||
|
||||
class ScheduleItem(TimestampMixin, SoftDeleteMixin, Base):
|
||||
__tablename__: str = "schedule_items"
|
||||
__table_args__ = {"extend_existing": True}
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
)
|
||||
owner_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=False,
|
||||
)
|
||||
title: Mapped[str] = mapped_column(
|
||||
String(255),
|
||||
nullable=False,
|
||||
)
|
||||
description: Mapped[str | None] = mapped_column(
|
||||
Text,
|
||||
nullable=True,
|
||||
)
|
||||
start_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True),
|
||||
nullable=False,
|
||||
)
|
||||
end_at: Mapped[datetime | None] = mapped_column(
|
||||
DateTime(timezone=True),
|
||||
nullable=True,
|
||||
)
|
||||
timezone: Mapped[str] = mapped_column(
|
||||
String(50),
|
||||
nullable=False,
|
||||
default="UTC",
|
||||
)
|
||||
extra_metadata: Mapped[dict] = mapped_column(
|
||||
"metadata",
|
||||
JSONB,
|
||||
nullable=False,
|
||||
server_default="{}",
|
||||
)
|
||||
recurrence_rule: Mapped[str | None] = mapped_column(
|
||||
String(255),
|
||||
nullable=True,
|
||||
)
|
||||
source_type: Mapped[ScheduleItemSourceType] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
default=ScheduleItemSourceType.MANUAL,
|
||||
)
|
||||
status: Mapped[ScheduleItemStatus] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
default=ScheduleItemStatus.ACTIVE,
|
||||
)
|
||||
created_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
@@ -0,0 +1,58 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from enum import Enum
|
||||
|
||||
from sqlalchemy import Integer, String
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from core.db.base import Base, TimestampMixin
|
||||
|
||||
|
||||
class SubscriptionStatus(str, Enum):
|
||||
ACTIVE = "active"
|
||||
PAUSED = "paused"
|
||||
UNSUBSCRIBED = "unsubscribed"
|
||||
|
||||
|
||||
class NotifyLevel(str, Enum):
|
||||
ALL = "all"
|
||||
MENTIONS = "mentions"
|
||||
NONE = "none"
|
||||
|
||||
|
||||
class ScheduleSubscription(TimestampMixin, Base):
|
||||
__tablename__: str = "schedule_subscriptions"
|
||||
__table_args__ = {"extend_existing": True}
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
)
|
||||
item_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=False,
|
||||
)
|
||||
subscriber_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=False,
|
||||
)
|
||||
permission: Mapped[int] = mapped_column(
|
||||
Integer,
|
||||
nullable=False,
|
||||
default=1,
|
||||
)
|
||||
notify_level: Mapped[NotifyLevel] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
default=NotifyLevel.ALL,
|
||||
)
|
||||
status: Mapped[SubscriptionStatus] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
default=SubscriptionStatus.ACTIVE,
|
||||
)
|
||||
created_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
@@ -0,0 +1,25 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from core.db.base import Base, TimestampMixin
|
||||
|
||||
|
||||
class TodoSource(TimestampMixin, Base):
|
||||
__tablename__: str = "todo_sources"
|
||||
__table_args__ = {"extend_existing": True}
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
)
|
||||
todo_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=False,
|
||||
)
|
||||
schedule_item_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=False,
|
||||
)
|
||||
@@ -0,0 +1,67 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
|
||||
from sqlalchemy import DateTime, Integer, String
|
||||
from sqlalchemy.dialects.postgresql import UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from core.db.base import Base, SoftDeleteMixin, TimestampMixin
|
||||
|
||||
|
||||
class TodoStatus(str, Enum):
|
||||
PENDING = "pending"
|
||||
DONE = "done"
|
||||
CANCELED = "canceled"
|
||||
|
||||
|
||||
class TodoPriority(int, Enum):
|
||||
IMPORTANT_URGENT = 1
|
||||
IMPORTANT_NOT_URGENT = 2
|
||||
NOT_IMPORTANT_URGENT = 3
|
||||
NOT_IMPORTANT_NOT_URGENT = 4
|
||||
|
||||
|
||||
class Todo(TimestampMixin, SoftDeleteMixin, Base):
|
||||
__tablename__: str = "todos"
|
||||
__table_args__ = {"extend_existing": True}
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
)
|
||||
owner_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=False,
|
||||
)
|
||||
title: Mapped[str] = mapped_column(
|
||||
String(255),
|
||||
nullable=False,
|
||||
)
|
||||
description: Mapped[str | None] = mapped_column(
|
||||
String(1000),
|
||||
nullable=True,
|
||||
)
|
||||
due_at: Mapped[datetime | None] = mapped_column(
|
||||
DateTime(timezone=True),
|
||||
nullable=True,
|
||||
)
|
||||
priority: Mapped[int] = mapped_column(
|
||||
Integer,
|
||||
nullable=False,
|
||||
default=TodoPriority.NOT_IMPORTANT_NOT_URGENT,
|
||||
)
|
||||
completed_at: Mapped[datetime | None] = mapped_column(
|
||||
DateTime(timezone=True),
|
||||
nullable=True,
|
||||
)
|
||||
status: Mapped[TodoStatus] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
default=TodoStatus.PENDING,
|
||||
)
|
||||
created_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
@@ -0,0 +1,62 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
from enum import Enum
|
||||
|
||||
from sqlalchemy import String
|
||||
from sqlalchemy.dialects.postgresql import JSONB, UUID
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
from core.db.base import Base, SoftDeleteMixin, TimestampMixin
|
||||
|
||||
|
||||
class UserAgentStatus(str, Enum):
|
||||
ACTIVE = "active"
|
||||
PAUSED = "paused"
|
||||
MIGRATING = "migrating"
|
||||
|
||||
|
||||
class AgentType(str, Enum):
|
||||
INTENT_RECOGNITION = "INTENT_RECOGNITION"
|
||||
TASK_EXECUTION = "TASK_EXECUTION"
|
||||
RESULT_REPORTING = "RESULT_REPORTING"
|
||||
|
||||
|
||||
class UserAgent(TimestampMixin, SoftDeleteMixin, Base):
|
||||
__tablename__: str = "user_agents"
|
||||
__table_args__ = {"extend_existing": True}
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
||||
)
|
||||
user_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=False,
|
||||
unique=True,
|
||||
)
|
||||
llm_id: Mapped[uuid.UUID] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=False,
|
||||
)
|
||||
agent_type: Mapped[AgentType] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
)
|
||||
config: Mapped[dict] = mapped_column(
|
||||
JSONB,
|
||||
nullable=False,
|
||||
server_default="{}",
|
||||
)
|
||||
status: Mapped[UserAgentStatus] = mapped_column(
|
||||
String(20),
|
||||
nullable=False,
|
||||
default=UserAgentStatus.ACTIVE,
|
||||
)
|
||||
created_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
updated_by: Mapped[uuid.UUID | None] = mapped_column(
|
||||
UUID(as_uuid=True),
|
||||
nullable=True,
|
||||
)
|
||||
Reference in New Issue
Block a user