Files
LockInBroAPI/app/models.py

369 lines
7.9 KiB
Python
Raw Normal View History

2026-03-29 06:57:34 -04:00
from datetime import datetime
from uuid import UUID
from pydantic import BaseModel, EmailStr, Field
# ── Auth ──
class RegisterRequest(BaseModel):
email: EmailStr
password: str = Field(min_length=8)
display_name: str | None = None
timezone: str = "America/Chicago"
class LoginRequest(BaseModel):
email: EmailStr
password: str
class AppleAuthRequest(BaseModel):
identity_token: str
authorization_code: str
full_name: str | None = None
class RefreshRequest(BaseModel):
refresh_token: str
class AuthResponse(BaseModel):
access_token: str
refresh_token: str
expires_in: int
user: "UserOut"
class UserOut(BaseModel):
id: UUID
email: str | None
display_name: str | None
timezone: str
created_at: datetime
# ── Tasks ──
class TaskCreate(BaseModel):
title: str
description: str | None = None
priority: int = Field(0, ge=0, le=4)
deadline: datetime | None = None
estimated_minutes: int | None = None
tags: list[str] = []
class TaskUpdate(BaseModel):
title: str | None = None
description: str | None = None
priority: int | None = Field(None, ge=0, le=4)
status: str | None = None
deadline: datetime | None = None
estimated_minutes: int | None = None
tags: list[str] | None = None
class TaskOut(BaseModel):
id: UUID
user_id: UUID
title: str
description: str | None
priority: int
status: str
deadline: datetime | None
estimated_minutes: int | None
source: str
tags: list[str]
plan_type: str | None
brain_dump_raw: str | None
created_at: datetime
updated_at: datetime
class BrainDumpRequest(BaseModel):
raw_text: str
source: str = "manual"
timezone: str = "America/Chicago"
class ParsedSubtask(BaseModel):
title: str
description: str | None = None
deadline: datetime | None = None
estimated_minutes: int | None = None
suggested: bool = False
class ParsedTask(BaseModel):
task_id: str | None = None
title: str
description: str | None = None
priority: int = 0
deadline: datetime | None = None
estimated_minutes: int | None = None
tags: list[str] = []
subtasks: list[ParsedSubtask] = []
class BrainDumpResponse(BaseModel):
parsed_tasks: list[ParsedTask]
unparseable_fragments: list[str] = []
ask_for_plans: bool = True
class PlanRequest(BaseModel):
plan_type: str = "llm_generated"
# ── Steps ──
class StepOut(BaseModel):
id: UUID
task_id: UUID
sort_order: int
title: str
description: str | None
estimated_minutes: int | None
status: str
checkpoint_note: str | None
last_checked_at: datetime | None
completed_at: datetime | None
created_at: datetime
class StepUpdate(BaseModel):
title: str | None = None
description: str | None = None
estimated_minutes: int | None = None
sort_order: int | None = None
status: str | None = None
checkpoint_note: str | None = None
class PlanResponse(BaseModel):
task_id: UUID
plan_type: str
steps: list[StepOut]
# ── Sessions ──
class SessionStartRequest(BaseModel):
task_id: UUID | None = None
platform: str = "mac"
work_app_bundle_ids: list[str] | None = None
class SessionCheckpointRequest(BaseModel):
current_step_id: UUID | None = None
last_action_summary: str | None = None
next_up: str | None = None
goal: str | None = None
active_app: str | None = None
last_screenshot_analysis: str | None = None
attention_score: int | None = None
distraction_count: int | None = None
class SessionEndRequest(BaseModel):
status: str = "completed"
class OpenSessionOut(BaseModel):
id: UUID
task_id: UUID | None
task: dict | None
status: str
platform: str
started_at: datetime
ended_at: datetime | None
checkpoint: dict
class SessionJoinRequest(BaseModel):
platform: str = "ipad"
work_app_bundle_ids: list[str] | None = None
class SessionJoinResponse(BaseModel):
session_id: UUID
joined: bool
task: dict | None
current_step: dict | None
all_steps: list[StepOut]
suggested_app_scheme: str | None
suggested_app_name: str | None
class SessionOut(BaseModel):
id: UUID
user_id: UUID
task_id: UUID | None
platform: str
started_at: datetime
ended_at: datetime | None
status: str
checkpoint: dict
created_at: datetime
class ResumeCard(BaseModel):
welcome_back: str
you_were_doing: str
next_step: str
motivation: str
class SessionResumeResponse(BaseModel):
session_id: UUID
task: dict | None
current_step: dict | None
progress: dict
resume_card: ResumeCard
# ── Distractions ──
class ScreenshotAnalysisResponse(BaseModel):
on_task: bool
current_step_id: UUID | None
checkpoint_note_update: str | None
steps_completed: list[UUID] = []
distraction_type: str | None
app_name: str | None
confidence: float
gentle_nudge: str | None
vlm_summary: str | None
class AppActivityRequest(BaseModel):
session_id: UUID
app_bundle_id: str
app_name: str
duration_seconds: int
returned_to_task: bool = False
class AppActivityResponse(BaseModel):
distraction_logged: bool
session_distraction_count: int
gentle_nudge: str | None
class AppCheckRequest(BaseModel):
app_bundle_id: str
class AppCheckResponse(BaseModel):
is_distraction_app: bool
pending_task_count: int
most_urgent_task: dict | None
nudge: str | None
# ── Analyze Result (Device-Side VLM) ──
class ProposedAction(BaseModel):
label: str
action_type: str
details: str | None = None
class FrictionDetection(BaseModel):
type: str = "none"
confidence: float = 0.0
description: str | None = None
proposed_actions: list[ProposedAction] = []
source_context: str | None = None
target_context: str | None = None
class SessionAction(BaseModel):
type: str = "none" # resume | switch | complete | start_new | none
session_id: UUID | None = None
reason: str | None = None
class AnalyzeResultRequest(BaseModel):
session_id: UUID | None = None # optional — VLM can run without an active session
on_task: bool
current_step_id: UUID | None = None
inferred_task: str | None = None
checkpoint_note_update: str | None = None
steps_completed: list[UUID] = []
friction: FrictionDetection = FrictionDetection()
session_action: SessionAction = SessionAction()
intent: str | None = None
distraction_type: str | None = None
app_name: str | None = None
confidence: float = 0.0
gentle_nudge: str | None = None
vlm_summary: str | None = None
class AnalyzeResultResponse(BaseModel):
side_effects_applied: bool
steps_updated: int
distraction_logged: bool
proactive_action_id: UUID | None = None
# ── Proactive Actions ──
class ProactiveRespondRequest(BaseModel):
proactive_action_id: UUID
user_choice: str # accepted | declined | alternative_chosen
chosen_action: str | None = None
class ProactiveRespondResponse(BaseModel):
logged: bool
should_execute: bool
class ProactiveExecuteRequest(BaseModel):
proactive_action_id: UUID
action_type: str
execution_params: dict = {}
class ProactiveExecuteResponse(BaseModel):
executed: bool
result: str | None = None
class ProactivePreference(BaseModel):
preferred_action: str | None
total_choices: int
acceptance_rate: float
class ProactivePreferencesResponse(BaseModel):
preferences: dict[str, ProactivePreference]
# ── Device Token ──
class DeviceTokenRequest(BaseModel):
platform: str
token: str
# ── Analytics ──
class AnalyticsSummary(BaseModel):
total_focus_minutes: float
sessions_completed: int
tasks_completed: int
top_distractors: list[dict]
avg_attention_score: float | None