53 lines
1.5 KiB
Python
53 lines
1.5 KiB
Python
from typing import Literal
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
|
|
STATUSES = ("triage", "todo", "ready", "running", "blocked", "done", "archived")
|
|
WorkspaceKind = Literal["scratch", "dir", "worktree"]
|
|
|
|
|
|
class Task(BaseModel):
|
|
model_config = ConfigDict(extra="allow")
|
|
|
|
id: str
|
|
title: str = ""
|
|
status: str = "todo"
|
|
assignee: str | None = None
|
|
priority: int | None = None
|
|
body: str | None = None
|
|
age: str | None = None
|
|
created_at: int | None = None
|
|
started_at: int | None = None
|
|
|
|
|
|
class TaskCreate(BaseModel):
|
|
title: str = Field(min_length=1, max_length=200)
|
|
body: str = ""
|
|
assignee: str | None = Field(default=None, max_length=80)
|
|
priority: int = Field(default=0, ge=-1000, le=1000)
|
|
workspace_kind: WorkspaceKind = "scratch"
|
|
workspace_path: str | None = None
|
|
goal_mode: bool = False
|
|
max_runtime_seconds: int | None = Field(default=None, ge=30, le=86400)
|
|
|
|
@field_validator("title")
|
|
@classmethod
|
|
def clean_title(cls, value: str) -> str:
|
|
value = value.strip()
|
|
if not value:
|
|
raise ValueError("title is required")
|
|
if "\x00" in value:
|
|
raise ValueError("title contains unsafe null byte")
|
|
return value
|
|
|
|
|
|
class CommentPayload(BaseModel):
|
|
body: str = Field(min_length=1, max_length=10000)
|
|
|
|
|
|
class AssignPayload(BaseModel):
|
|
assignee: str = Field(min_length=1, max_length=80)
|
|
|
|
|
|
class BlockPayload(BaseModel):
|
|
reason: str = Field(min_length=1, max_length=1000)
|