"""Pydantic models for beads issue tracker types.""" from datetime import datetime from typing import Literal from pydantic import BaseModel, Field, field_validator # Type aliases for issue statuses, types, and dependencies IssueStatus = Literal["open", "in_progress", "blocked", "closed"] IssueType = Literal["bug", "feature", "task", "epic", "chore"] DependencyType = Literal["blocks", "related", "parent-child", "discovered-from"] class IssueBase(BaseModel): """Base issue model with shared fields.""" id: str title: str description: str = "" design: str | None = None acceptance_criteria: str | None = None notes: str | None = None external_ref: str | None = None status: IssueStatus priority: int = Field(ge=0, le=4) issue_type: IssueType created_at: datetime updated_at: datetime closed_at: datetime | None = None assignee: str | None = None labels: list[str] = Field(default_factory=list) dependency_count: int = 0 dependent_count: int = 0 @field_validator("priority") @classmethod def validate_priority(cls, v: int) -> int: """Validate priority is 0-4.""" if not 0 <= v <= 4: raise ValueError("Priority must be between 0 and 4") return v class LinkedIssue(IssueBase): """Issue reference in dependencies/dependents (avoids recursion).""" dependency_type: DependencyType | None = None class Issue(IssueBase): """Issue model matching bd JSON output.""" dependencies: list[LinkedIssue] = Field(default_factory=list) dependents: list[LinkedIssue] = Field(default_factory=list) class Dependency(BaseModel): """Dependency relationship model.""" from_id: str to_id: str dep_type: DependencyType class CreateIssueParams(BaseModel): """Parameters for creating an issue.""" title: str description: str = "" design: str | None = None acceptance: str | None = None external_ref: str | None = None priority: int = Field(default=2, ge=0, le=4) issue_type: IssueType = "task" assignee: str | None = None labels: list[str] = Field(default_factory=list) id: str | None = None deps: list[str] = Field(default_factory=list) class UpdateIssueParams(BaseModel): """Parameters for updating an issue.""" issue_id: str status: IssueStatus | None = None priority: int | None = Field(default=None, ge=0, le=4) assignee: str | None = None title: str | None = None description: str | None = None design: str | None = None acceptance_criteria: str | None = None notes: str | None = None external_ref: str | None = None class CloseIssueParams(BaseModel): """Parameters for closing an issue.""" issue_id: str reason: str = "Completed" class ReopenIssueParams(BaseModel): """Parameters for reopening issues.""" issue_ids: list[str] reason: str | None = None class AddDependencyParams(BaseModel): """Parameters for adding a dependency.""" issue_id: str depends_on_id: str dep_type: DependencyType = "blocks" class ReadyWorkParams(BaseModel): """Parameters for querying ready work.""" limit: int = Field(default=10, ge=1, le=100) priority: int | None = Field(default=None, ge=0, le=4) assignee: str | None = None class ListIssuesParams(BaseModel): """Parameters for listing issues.""" status: IssueStatus | None = None priority: int | None = Field(default=None, ge=0, le=4) issue_type: IssueType | None = None assignee: str | None = None limit: int = Field(default=20, ge=1, le=100) # Reduced to avoid MCP buffer overflow class ShowIssueParams(BaseModel): """Parameters for showing issue details.""" issue_id: str class Stats(BaseModel): """Beads task statistics.""" total_issues: int open_issues: int in_progress_issues: int closed_issues: int blocked_issues: int ready_issues: int average_lead_time_hours: float class BlockedIssue(Issue): """Blocked issue with blocking information.""" blocked_by_count: int blocked_by: list[str] class InitParams(BaseModel): """Parameters for initializing bd.""" prefix: str | None = None class InitResult(BaseModel): """Result from bd init command.""" database: str prefix: str message: str # Agent Mail Models class MailSendParams(BaseModel): """Parameters for sending mail.""" to: list[str] subject: str body: str urgent: bool = False cc: list[str] | None = None project_key: str | None = None sender_name: str | None = None class MailInboxParams(BaseModel): """Parameters for checking inbox.""" limit: int = 20 urgent_only: bool = False unread_only: bool = False cursor: str | None = None agent_name: str | None = None project_key: str | None = None class MailReadParams(BaseModel): """Parameters for reading mail.""" message_id: int mark_read: bool = True agent_name: str | None = None project_key: str | None = None class MailReplyParams(BaseModel): """Parameters for replying to mail.""" message_id: int body: str subject: str | None = None agent_name: str | None = None project_key: str | None = None class MailAckParams(BaseModel): """Parameters for acknowledging mail.""" message_id: int agent_name: str | None = None project_key: str | None = None class MailDeleteParams(BaseModel): """Parameters for deleting mail.""" message_id: int agent_name: str | None = None project_key: str | None = None