feat(backend): enhance task and schedule center APIs with expanded endpoints
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
from sqlalchemy import Column, String, Text, Integer, ForeignKey, DateTime, Enum
|
||||
from sqlalchemy.orm import relationship
|
||||
from datetime import datetime
|
||||
from enum import Enum as PyEnum
|
||||
|
||||
from sqlalchemy import Column, DateTime, Enum, ForeignKey, Integer, String, Text
|
||||
from sqlalchemy.orm import relationship
|
||||
|
||||
from app.models.base import BaseModel
|
||||
|
||||
|
||||
@@ -19,26 +20,144 @@ class TaskPriority(str, PyEnum):
|
||||
URGENT = "urgent"
|
||||
|
||||
|
||||
class TaskSource(str, PyEnum):
|
||||
MANUAL = "manual"
|
||||
CHAT = "chat"
|
||||
SCHEDULE_CENTER = "schedule_center"
|
||||
TODAY_STATUS = "today_status"
|
||||
COMMANDER = "commander"
|
||||
|
||||
|
||||
class TaskQuadrant(str, PyEnum):
|
||||
URGENT_IMPORTANT = "urgent-important"
|
||||
NOT_URGENT_IMPORTANT = "not-urgent-important"
|
||||
URGENT_NOT_IMPORTANT = "urgent-not-important"
|
||||
NOT_URGENT_NOT_IMPORTANT = "not-urgent-not-important"
|
||||
|
||||
|
||||
class TaskAssigneeType(str, PyEnum):
|
||||
USER = "user"
|
||||
COMMANDER = "commander"
|
||||
AGENT = "agent"
|
||||
PLANNER = "planner"
|
||||
EXECUTOR = "executor"
|
||||
KNOWLEDGE = "knowledge"
|
||||
ANALYST = "analyst"
|
||||
CODER = "coder"
|
||||
RESEARCHER = "researcher"
|
||||
|
||||
|
||||
class TaskDispatchStatus(str, PyEnum):
|
||||
IDLE = "idle"
|
||||
QUEUED = "queued"
|
||||
RUNNING = "running"
|
||||
COMPLETED = "completed"
|
||||
FAILED = "failed"
|
||||
|
||||
|
||||
DispatchStatus = TaskDispatchStatus
|
||||
|
||||
|
||||
DispatchStatus = TaskDispatchStatus
|
||||
|
||||
|
||||
class TaskHistoryAction(str, PyEnum):
|
||||
CREATED = "created"
|
||||
CREATED_FROM_CHAT = "created_from_chat"
|
||||
UPDATED = "updated"
|
||||
STATUS_CHANGED = "status_changed"
|
||||
ASSIGNED = "assigned"
|
||||
DELETED = "deleted"
|
||||
SUBTASK_CREATED = "subtask_created"
|
||||
SUBTASK_UPDATED = "subtask_updated"
|
||||
SUBTASK_DELETED = "subtask_deleted"
|
||||
SUBTASK_REORDERED = "subtask_reordered"
|
||||
DISPATCHED_TO_COMMANDER = "dispatched_to_commander"
|
||||
DISPATCH_STATUS_CHANGED = "dispatch_status_changed"
|
||||
|
||||
|
||||
def enum_values(enum_cls: type[PyEnum]) -> list[str]:
|
||||
return [item.value for item in enum_cls]
|
||||
|
||||
|
||||
TASK_STATUS_ENUM = Enum(TaskStatus, values_callable=enum_values)
|
||||
TASK_PRIORITY_ENUM = Enum(TaskPriority, values_callable=enum_values)
|
||||
TASK_SOURCE_ENUM = Enum(TaskSource, values_callable=enum_values)
|
||||
TASK_QUADRANT_ENUM = Enum(TaskQuadrant, values_callable=enum_values)
|
||||
TASK_ASSIGNEE_TYPE_ENUM = Enum(TaskAssigneeType, values_callable=enum_values)
|
||||
TASK_DISPATCH_STATUS_ENUM = Enum(TaskDispatchStatus, values_callable=enum_values)
|
||||
|
||||
|
||||
class Task(BaseModel):
|
||||
__tablename__ = "tasks"
|
||||
|
||||
user_id = Column(String(36), ForeignKey("users.id"), nullable=False, index=True)
|
||||
title = Column(String(500), nullable=False)
|
||||
description = Column(Text, nullable=True)
|
||||
status = Column(Enum(TaskStatus), default=TaskStatus.TODO, nullable=False, index=True)
|
||||
priority = Column(Enum(TaskPriority), default=TaskPriority.MEDIUM, nullable=False)
|
||||
due_date = Column(DateTime, nullable=True)
|
||||
status = Column(TASK_STATUS_ENUM, default=TaskStatus.TODO, nullable=False, index=True)
|
||||
priority = Column(TASK_PRIORITY_ENUM, default=TaskPriority.MEDIUM, nullable=False)
|
||||
due_date = Column(DateTime, nullable=True, index=True)
|
||||
completed_at = Column(DateTime, nullable=True)
|
||||
tags = Column(String(1000), nullable=True) # JSON 数组
|
||||
tags = Column(String(1000), nullable=True) # JSON array
|
||||
source = Column(TASK_SOURCE_ENUM, default=TaskSource.MANUAL, nullable=False, index=True)
|
||||
conversation_id = Column(String(36), nullable=True, index=True)
|
||||
quadrant = Column(TASK_QUADRANT_ENUM, nullable=True, index=True)
|
||||
assignee_type = Column(TASK_ASSIGNEE_TYPE_ENUM, nullable=True, index=True)
|
||||
assignee_id = Column(String(255), nullable=True, index=True)
|
||||
dispatch_status = Column(
|
||||
TASK_DISPATCH_STATUS_ENUM,
|
||||
default=TaskDispatchStatus.IDLE,
|
||||
nullable=False,
|
||||
index=True,
|
||||
)
|
||||
dispatch_run_id = Column(String(64), nullable=True, index=True)
|
||||
result_summary = Column(Text, nullable=True)
|
||||
started_at = Column(DateTime, nullable=True)
|
||||
last_synced_at = Column(DateTime, nullable=True)
|
||||
|
||||
history = relationship("TaskHistory", back_populates="task", cascade="all, delete-orphan")
|
||||
subtasks = relationship(
|
||||
"TaskSubTask",
|
||||
back_populates="task",
|
||||
cascade="all, delete-orphan",
|
||||
order_by="TaskSubTask.order_index.asc()",
|
||||
)
|
||||
history = relationship(
|
||||
"TaskHistory",
|
||||
back_populates="task",
|
||||
cascade="all, delete-orphan",
|
||||
order_by="TaskHistory.created_at.desc()",
|
||||
)
|
||||
|
||||
|
||||
class TaskSubTask(BaseModel):
|
||||
__tablename__ = "task_subtasks"
|
||||
|
||||
task_id = Column(String(36), ForeignKey("tasks.id"), nullable=False, index=True)
|
||||
title = Column(String(500), nullable=False)
|
||||
description = Column(Text, nullable=True)
|
||||
status = Column(TASK_STATUS_ENUM, default=TaskStatus.TODO, nullable=False, index=True)
|
||||
order_index = Column(Integer, default=0, nullable=False, index=True)
|
||||
assignee_type = Column(TASK_ASSIGNEE_TYPE_ENUM, nullable=True, index=True)
|
||||
assignee_id = Column(String(255), nullable=True, index=True)
|
||||
dispatch_status = Column(
|
||||
TASK_DISPATCH_STATUS_ENUM,
|
||||
default=TaskDispatchStatus.IDLE,
|
||||
nullable=False,
|
||||
index=True,
|
||||
)
|
||||
dispatch_run_id = Column(String(64), nullable=True, index=True)
|
||||
result_summary = Column(Text, nullable=True)
|
||||
completed_at = Column(DateTime, nullable=True)
|
||||
|
||||
task = relationship("Task", back_populates="subtasks")
|
||||
|
||||
|
||||
class TaskHistory(BaseModel):
|
||||
__tablename__ = "task_histories"
|
||||
|
||||
task_id = Column(String(36), ForeignKey("tasks.id"), nullable=False, index=True)
|
||||
action = Column(String(100), nullable=False) # created, status_changed, updated, deleted
|
||||
subtask_id = Column(String(36), ForeignKey("task_subtasks.id"), nullable=True, index=True)
|
||||
action = Column(String(100), nullable=False)
|
||||
old_value = Column(Text, nullable=True)
|
||||
new_value = Column(Text, nullable=True)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user