API
This commit is contained in:
368
app/models.py
Normal file
368
app/models.py
Normal file
@@ -0,0 +1,368 @@
|
||||
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
|
||||
Reference in New Issue
Block a user