369 lines
7.9 KiB
Python
369 lines
7.9 KiB
Python
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
|