Live Activity Content Density
Nucleic-Session: B3643133-163C-4C5D-BE20-1A6B7FB83DA9 Co-authored-by: Nucleic <[email protected]>
This commit is contained in:
@@ -2,19 +2,74 @@ import ActivityKit
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
/// The one aggregate Live Activity (UX_IOS §5.3, aggregate per §11.4 — a single Activity
|
/// The one aggregate Live Activity (UX_IOS §5.3, aggregate per §11.4 — a single Activity
|
||||||
/// respects iOS's budget better than one per session): "N running, M waiting" plus the most
|
/// respects iOS's budget better than one per session). It answers "what is Nucleic doing right
|
||||||
/// urgent session's title. Shared between the app (which starts/updates it) and the widget
|
/// now?" at a glance: the headline counts (running / waiting / approvals), the total churn in
|
||||||
/// extension (which renders it).
|
/// flight, and a few of the most urgent sessions with their state and diff. Shared between the
|
||||||
|
/// app (which starts/updates it) and the widget extension (which renders it).
|
||||||
|
///
|
||||||
|
/// Deliberately free of `NucleicProtocol` types — the widget extension links only this file, so
|
||||||
|
/// the state carries plain value types and its own small `Backend`/`Kind` enums rather than the
|
||||||
|
/// wire `BackendID`/`SessionStatus`.
|
||||||
struct NucleicSessionAttributes: ActivityAttributes {
|
struct NucleicSessionAttributes: ActivityAttributes {
|
||||||
|
/// The agent behind a session — drives a row's provider tag/tint.
|
||||||
|
enum Backend: String, Codable, Hashable {
|
||||||
|
case claude, codex, grok, other
|
||||||
|
|
||||||
|
var label: String {
|
||||||
|
switch self {
|
||||||
|
case .claude: "Claude"
|
||||||
|
case .codex: "Codex"
|
||||||
|
case .grok: "Grok"
|
||||||
|
case .other: "Agent"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A session's live state, collapsed to what the glance needs — drives each row's glyph/tint.
|
||||||
|
enum Kind: String, Codable, Hashable {
|
||||||
|
case running // agent actively working a turn
|
||||||
|
case provisioning // worktree/setup spinning up
|
||||||
|
case approval // blocked on a human approval decision (loudest)
|
||||||
|
case needsInput // turn ended asking the user something
|
||||||
|
case done // turn finished its work; nothing required
|
||||||
|
case error // errored / interrupted
|
||||||
|
case idle // created, not yet working
|
||||||
|
}
|
||||||
|
|
||||||
|
/// One agent session surfaced in the activity's detail rows.
|
||||||
|
struct SessionLine: Codable, Hashable, Identifiable {
|
||||||
|
var id: String
|
||||||
|
/// The session's title (falls back to the project name upstream).
|
||||||
|
var title: String
|
||||||
|
/// Project the session belongs to.
|
||||||
|
var project: String
|
||||||
|
var backend: Backend
|
||||||
|
var kind: Kind
|
||||||
|
/// A compact right-aligned status: its diff ("3 files +42 −7"), "2 to approve",
|
||||||
|
/// "Waiting on you", "Working…", etc.
|
||||||
|
var detail: String
|
||||||
|
}
|
||||||
|
|
||||||
struct ContentState: Codable, Hashable {
|
struct ContentState: Codable, Hashable {
|
||||||
/// Sessions actively working a turn.
|
/// Sessions actively working a turn.
|
||||||
var runningCount: Int
|
var runningCount: Int
|
||||||
/// Sessions blocked on the user (approval or next prompt) — the loud number.
|
/// Sessions blocked on the user (approval or next prompt) — the loud number.
|
||||||
var needsYouCount: Int
|
var needsYouCount: Int
|
||||||
/// The most urgent session's title: the top waiting one, else the busiest running.
|
/// Total individual approval decisions waiting across all sessions — the "act now" count.
|
||||||
var topTitle: String?
|
var approvalCount: Int
|
||||||
/// Whether `topTitle` is waiting on the user (amber) vs just running (blue).
|
/// Aggregate worktree churn across the active sessions.
|
||||||
var topNeedsYou: Bool
|
var filesChanged: Int
|
||||||
|
var linesAdded: Int
|
||||||
|
var linesRemoved: Int
|
||||||
|
/// The most urgent sessions, attention-first (capped, typically ≤3): the detail rows.
|
||||||
|
var lines: [SessionLine]
|
||||||
|
|
||||||
|
/// The single most urgent session (drives the compact/minimal regions).
|
||||||
|
var top: SessionLine? { lines.first }
|
||||||
|
/// Whether anything needs the user (waiting session or a pending approval).
|
||||||
|
var needsAttention: Bool { needsYouCount > 0 || approvalCount > 0 }
|
||||||
|
/// Whether any worktree has uncommitted changes to summarize.
|
||||||
|
var hasChurn: Bool { filesChanged > 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The paired Mac's name (static for the Activity's lifetime).
|
/// The paired Mac's name (static for the Activity's lifetime).
|
||||||
|
|||||||
Reference in New Issue
Block a user