focus, brain dump, speech recognition and some argus implementation
This commit is contained in:
343
LockInBro/Models.swift
Normal file
343
LockInBro/Models.swift
Normal file
@@ -0,0 +1,343 @@
|
||||
// Models.swift — LockInBro data models
|
||||
|
||||
import Foundation
|
||||
|
||||
// MARK: - Auth
|
||||
|
||||
struct User: Codable, Identifiable {
|
||||
let id: String
|
||||
let email: String?
|
||||
let displayName: String?
|
||||
let createdAt: String
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, email
|
||||
case displayName = "display_name"
|
||||
case createdAt = "created_at"
|
||||
}
|
||||
}
|
||||
|
||||
struct AuthResponse: Codable {
|
||||
let accessToken: String
|
||||
let refreshToken: String
|
||||
let expiresIn: Int
|
||||
let user: User
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case accessToken = "access_token"
|
||||
case refreshToken = "refresh_token"
|
||||
case expiresIn = "expires_in"
|
||||
case user
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Tasks
|
||||
|
||||
struct AppTask: Identifiable, Codable, Hashable {
|
||||
let id: String
|
||||
var title: String
|
||||
var description: String?
|
||||
var priority: Int
|
||||
var status: String
|
||||
var deadline: String?
|
||||
var estimatedMinutes: Int?
|
||||
let source: String
|
||||
var tags: [String]
|
||||
var planType: String?
|
||||
let createdAt: String
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, title, description, priority, status, deadline, tags, source
|
||||
case estimatedMinutes = "estimated_minutes"
|
||||
case planType = "plan_type"
|
||||
case createdAt = "created_at"
|
||||
}
|
||||
|
||||
var priorityLabel: String {
|
||||
switch priority {
|
||||
case 4: return "Urgent"
|
||||
case 3: return "High"
|
||||
case 2: return "Medium"
|
||||
case 1: return "Low"
|
||||
default: return "Unset"
|
||||
}
|
||||
}
|
||||
|
||||
var priorityColor: String {
|
||||
switch priority {
|
||||
case 4: return "red"
|
||||
case 3: return "orange"
|
||||
case 2: return "yellow"
|
||||
case 1: return "green"
|
||||
default: return "gray"
|
||||
}
|
||||
}
|
||||
|
||||
var isActive: Bool { status == "in_progress" }
|
||||
var isDone: Bool { status == "done" }
|
||||
}
|
||||
|
||||
// MARK: - Steps
|
||||
|
||||
struct Step: Identifiable, Codable, Hashable {
|
||||
let id: String
|
||||
let taskId: String
|
||||
let sortOrder: Int
|
||||
var title: String
|
||||
var description: String?
|
||||
var estimatedMinutes: Int?
|
||||
var status: String
|
||||
var checkpointNote: String?
|
||||
var lastCheckedAt: String?
|
||||
var completedAt: String?
|
||||
let createdAt: String
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, title, description, status
|
||||
case taskId = "task_id"
|
||||
case sortOrder = "sort_order"
|
||||
case estimatedMinutes = "estimated_minutes"
|
||||
case checkpointNote = "checkpoint_note"
|
||||
case lastCheckedAt = "last_checked_at"
|
||||
case completedAt = "completed_at"
|
||||
case createdAt = "created_at"
|
||||
}
|
||||
|
||||
var isDone: Bool { status == "done" }
|
||||
var isActive: Bool { status == "in_progress" }
|
||||
}
|
||||
|
||||
// MARK: - Focus Session
|
||||
|
||||
struct FocusSession: Identifiable, Codable {
|
||||
let id: String
|
||||
let userId: String
|
||||
var taskId: String?
|
||||
let platform: String
|
||||
let startedAt: String
|
||||
var endedAt: String?
|
||||
var status: String
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, platform, status
|
||||
case userId = "user_id"
|
||||
case taskId = "task_id"
|
||||
case startedAt = "started_at"
|
||||
case endedAt = "ended_at"
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Brain Dump
|
||||
|
||||
struct BrainDumpResponse: Codable {
|
||||
let parsedTasks: [ParsedTask]
|
||||
let unparseableFragments: [String]
|
||||
let askForPlans: Bool
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case parsedTasks = "parsed_tasks"
|
||||
case unparseableFragments = "unparseable_fragments"
|
||||
case askForPlans = "ask_for_plans"
|
||||
}
|
||||
}
|
||||
|
||||
struct ParsedTask: Codable, Identifiable {
|
||||
// local UUID for list identity before saving
|
||||
var localId: String = UUID().uuidString
|
||||
var id: String { localId }
|
||||
|
||||
let title: String
|
||||
let description: String?
|
||||
let priority: Int
|
||||
let deadline: String?
|
||||
let estimatedMinutes: Int?
|
||||
let tags: [String]
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case title, description, priority, deadline, tags
|
||||
case estimatedMinutes = "estimated_minutes"
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Step Planning
|
||||
|
||||
struct StepPlanResponse: Codable {
|
||||
let taskId: String
|
||||
let planType: String
|
||||
let steps: [Step]
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case taskId = "task_id"
|
||||
case planType = "plan_type"
|
||||
case steps
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Distraction Analysis
|
||||
|
||||
/// A single action the proactive agent can take on the user's behalf.
|
||||
struct ProposedAction: Codable {
|
||||
let label: String // e.g. "Extract all 14 events"
|
||||
let actionType: String // e.g. "auto_extract", "brain_dump"
|
||||
let details: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case label, details
|
||||
case actionType = "action_type"
|
||||
}
|
||||
}
|
||||
|
||||
/// Friction pattern detected by the upgraded Argus VLM prompt.
|
||||
struct FrictionInfo: Codable {
|
||||
/// repetitive_loop | stalled | tedious_manual | context_overhead | task_resumption | none
|
||||
let type: String
|
||||
let confidence: Double
|
||||
let description: String?
|
||||
let proposedActions: [ProposedAction]
|
||||
let sourceContext: String?
|
||||
let targetContext: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case type, confidence, description
|
||||
case proposedActions = "proposed_actions"
|
||||
case sourceContext = "source_context"
|
||||
case targetContext = "target_context"
|
||||
}
|
||||
|
||||
var isActionable: Bool { type != "none" && confidence > 0.5 }
|
||||
var isResumption: Bool { type == "task_resumption" }
|
||||
}
|
||||
|
||||
struct DistractionAnalysisResponse: Codable {
|
||||
let onTask: Bool
|
||||
let currentStepId: String?
|
||||
let checkpointNoteUpdate: String?
|
||||
let stepsCompleted: [String]
|
||||
// Upgraded Argus prompt fields (nil when backend uses legacy prompt)
|
||||
let friction: FrictionInfo?
|
||||
let intent: String? // skimming | engaged | unclear | null
|
||||
let distractionType: String?
|
||||
let appName: String?
|
||||
let confidence: Double
|
||||
let gentleNudge: String?
|
||||
let vlmSummary: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case onTask = "on_task"
|
||||
case currentStepId = "current_step_id"
|
||||
case checkpointNoteUpdate = "checkpoint_note_update"
|
||||
case stepsCompleted = "steps_completed"
|
||||
case friction, intent
|
||||
case distractionType = "distraction_type"
|
||||
case appName = "app_name"
|
||||
case confidence
|
||||
case gentleNudge = "gentle_nudge"
|
||||
case vlmSummary = "vlm_summary"
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Session Resume
|
||||
|
||||
struct ResumeCard: Codable {
|
||||
let welcomeBack: String
|
||||
let youWereDoing: String
|
||||
let nextStep: String
|
||||
let motivation: String
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case welcomeBack = "welcome_back"
|
||||
case youWereDoing = "you_were_doing"
|
||||
case nextStep = "next_step"
|
||||
case motivation
|
||||
}
|
||||
}
|
||||
|
||||
struct StepSummary: Codable {
|
||||
let id: String
|
||||
let title: String
|
||||
let checkpointNote: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, title
|
||||
case checkpointNote = "checkpoint_note"
|
||||
}
|
||||
}
|
||||
|
||||
struct ProgressSummary: Codable {
|
||||
let completed: Int
|
||||
let total: Int
|
||||
let attentionScore: Int?
|
||||
let distractionCount: Int?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case completed, total
|
||||
case attentionScore = "attention_score"
|
||||
case distractionCount = "distraction_count"
|
||||
}
|
||||
}
|
||||
|
||||
struct ResumeResponse: Codable {
|
||||
let sessionId: String
|
||||
let resumeCard: ResumeCard
|
||||
let currentStep: StepSummary?
|
||||
let progress: ProgressSummary?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case sessionId = "session_id"
|
||||
case resumeCard = "resume_card"
|
||||
case currentStep = "current_step"
|
||||
case progress
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Proactive Agent
|
||||
|
||||
struct ProactiveCard: Identifiable {
|
||||
enum Source {
|
||||
/// VLM detected a friction pattern (primary signal — from upgraded Argus prompt).
|
||||
case vlmFriction(frictionType: String, description: String?, actions: [ProposedAction])
|
||||
/// Heuristic app-switch loop detected by NSWorkspace observer (fallback when VLM hasn't returned friction yet).
|
||||
case appSwitchLoop(apps: [String], switchCount: Int)
|
||||
}
|
||||
|
||||
let id = UUID()
|
||||
let source: Source
|
||||
|
||||
/// Human-readable title for the card header.
|
||||
var title: String {
|
||||
switch source {
|
||||
case .vlmFriction(let frictionType, _, _):
|
||||
switch frictionType {
|
||||
case "repetitive_loop": return "Repetitive Pattern Detected"
|
||||
case "stalled": return "Looks Like You're Stuck"
|
||||
case "tedious_manual": return "I Can Help With This"
|
||||
case "context_overhead": return "Too Many Windows?"
|
||||
default: return "I Noticed Something"
|
||||
}
|
||||
case .appSwitchLoop:
|
||||
return "Repetitive Pattern Detected"
|
||||
}
|
||||
}
|
||||
|
||||
/// SF Symbol name for the card icon.
|
||||
var icon: String {
|
||||
switch source {
|
||||
case .vlmFriction(let frictionType, _, _):
|
||||
switch frictionType {
|
||||
case "repetitive_loop": return "arrow.triangle.2.circlepath"
|
||||
case "stalled": return "pause.circle"
|
||||
case "tedious_manual": return "wand.and.stars"
|
||||
case "context_overhead": return "macwindow"
|
||||
default: return "sparkles"
|
||||
}
|
||||
case .appSwitchLoop:
|
||||
return "arrow.triangle.2.circlepath"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - API Error
|
||||
|
||||
struct APIErrorResponse: Codable {
|
||||
let detail: String
|
||||
}
|
||||
Reference in New Issue
Block a user