hermes-kanban-miniapp/backend/app/models.py

54 lines
1.5 KiB
Python
Raw Normal View History

2026-07-09 17:19:33 +03:00
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)