mirror of
https://github.com/wu736139669/hapi.git
synced 2026-11-07 01:21:37 +00:00
Track readable content revisions and durable read cursors in the hub. Acknowledge only rendered foreground tails, persist offline read operations, and preserve newer manual unread choices across devices. Migrate existing history to a read baseline and cover pagination receipts with shared native conformance fixtures.
179 lines
6.0 KiB
Swift
179 lines
6.0 KiB
Swift
import Foundation
|
|
|
|
/// Classification of a pending request for list badges.
|
|
public enum PendingRequestKind: String, Codable, Sendable {
|
|
case permission
|
|
case input
|
|
}
|
|
|
|
/// A capped, list-friendly view of one pending tool request.
|
|
///
|
|
/// Mirrors `PendingRequest` (`shared/src/sessionSummary.ts`).
|
|
public struct PendingRequest: Codable, Equatable, Sendable {
|
|
public var id: String
|
|
public var kind: PendingRequestKind
|
|
public var tool: String
|
|
/// Epoch ms when the request was raised (falls back server-side to the
|
|
/// session's `updatedAt` for requests stored without `createdAt`).
|
|
public var since: Int
|
|
|
|
public init(id: String, kind: PendingRequestKind, tool: String, since: Int) {
|
|
self.id = id
|
|
self.kind = kind
|
|
self.tool = tool
|
|
self.since = since
|
|
}
|
|
}
|
|
|
|
/// Todo completion counters shown on the session row.
|
|
public struct TodoProgress: Codable, Equatable, Sendable {
|
|
public var completed: Int
|
|
public var total: Int
|
|
|
|
public init(completed: Int, total: Int) {
|
|
self.completed = completed
|
|
self.total = total
|
|
}
|
|
}
|
|
|
|
/// Metadata subset embedded in a session-list row.
|
|
///
|
|
/// Mirrors `SessionSummaryMetadata` (`shared/src/sessionSummary.ts`).
|
|
public struct SessionSummaryMetadata: Codable, Equatable, Sendable {
|
|
/// The `summary` field carries only the text in list rows.
|
|
public struct Summary: Codable, Equatable, Sendable {
|
|
public var text: String
|
|
|
|
public init(text: String) {
|
|
self.text = text
|
|
}
|
|
}
|
|
|
|
public var name: String?
|
|
public var path: String
|
|
public var machineId: String?
|
|
public var summary: Summary?
|
|
public var flavor: String?
|
|
public var worktree: WorktreeMetadata?
|
|
/// Native agent session id resolved per flavor by the hub.
|
|
public var agentSessionId: String?
|
|
public var lifecycleState: String?
|
|
public var hapiMcpUrl: String?
|
|
|
|
public init(
|
|
name: String? = nil,
|
|
path: String,
|
|
machineId: String? = nil,
|
|
summary: Summary? = nil,
|
|
flavor: String? = nil,
|
|
worktree: WorktreeMetadata? = nil,
|
|
agentSessionId: String? = nil,
|
|
lifecycleState: String? = nil,
|
|
hapiMcpUrl: String? = nil
|
|
) {
|
|
self.name = name
|
|
self.path = path
|
|
self.machineId = machineId
|
|
self.summary = summary
|
|
self.flavor = flavor
|
|
self.worktree = worktree
|
|
self.agentSessionId = agentSessionId
|
|
self.lifecycleState = lifecycleState
|
|
self.hapiMcpUrl = hapiMcpUrl
|
|
}
|
|
}
|
|
|
|
/// One row of `GET /api/sessions`.
|
|
///
|
|
/// Mirrors `SessionSummary` (`shared/src/sessionSummary.ts`). The summary is
|
|
/// hub-derived: badges must use `pendingRequestsCount` (authoritative total),
|
|
/// never `pendingRequests.count` (capped at 5, oldest first).
|
|
public struct SessionSummary: Codable, Equatable, Sendable {
|
|
public var contentRevision: Int?
|
|
public var readState: SessionReadState?
|
|
/// Server-side cap on `pendingRequests` entries
|
|
/// (`PENDING_REQUEST_SUMMARY_CAP`, `shared/src/sessionSummary.ts`).
|
|
public static let pendingRequestSummaryCap = 5
|
|
|
|
public var id: String
|
|
public var active: Bool
|
|
public var thinking: Bool
|
|
public var activeAt: Int
|
|
public var createdAt: Int?
|
|
public var lastUserMessageAt: Int?
|
|
public var updatedAt: Int
|
|
public var pinned: Bool?
|
|
public var globalPinned: Bool?
|
|
public var metadata: SessionSummaryMetadata?
|
|
/// Watermark mirrors of the detail record so structured SSE patches can
|
|
/// be gated without a detail fetch.
|
|
public var metadataVersion: Int
|
|
public var agentStateVersion: Int
|
|
public var todosUpdatedAt: Int
|
|
public var todoProgress: TodoProgress?
|
|
public var pendingRequestsCount: Int
|
|
public var pendingRequestKinds: [PendingRequestKind]
|
|
public var pendingRequests: [PendingRequest]
|
|
public var backgroundTaskCount: Int
|
|
public var futureScheduledMessageCount: Int
|
|
/// Epoch ms of the soonest uninvoked scheduled message, or `nil`.
|
|
public var nextScheduledAt: Int?
|
|
public var model: String?
|
|
public var modelReasoningEffort: String?
|
|
public var effort: String?
|
|
|
|
public init(
|
|
contentRevision: Int? = nil,
|
|
readState: SessionReadState? = nil,
|
|
id: String,
|
|
active: Bool,
|
|
thinking: Bool,
|
|
activeAt: Int,
|
|
updatedAt: Int,
|
|
createdAt: Int? = nil,
|
|
lastUserMessageAt: Int? = nil,
|
|
pinned: Bool? = nil,
|
|
globalPinned: Bool? = nil,
|
|
metadata: SessionSummaryMetadata? = nil,
|
|
metadataVersion: Int,
|
|
agentStateVersion: Int,
|
|
todosUpdatedAt: Int,
|
|
todoProgress: TodoProgress? = nil,
|
|
pendingRequestsCount: Int,
|
|
pendingRequestKinds: [PendingRequestKind] = [],
|
|
pendingRequests: [PendingRequest] = [],
|
|
backgroundTaskCount: Int = 0,
|
|
futureScheduledMessageCount: Int = 0,
|
|
nextScheduledAt: Int? = nil,
|
|
model: String? = nil,
|
|
modelReasoningEffort: String? = nil,
|
|
effort: String? = nil
|
|
) {
|
|
self.id = id
|
|
self.contentRevision = contentRevision
|
|
self.readState = readState
|
|
self.active = active
|
|
self.thinking = thinking
|
|
self.activeAt = activeAt
|
|
self.updatedAt = updatedAt
|
|
self.lastUserMessageAt = lastUserMessageAt
|
|
self.createdAt = createdAt
|
|
self.pinned = pinned
|
|
self.globalPinned = globalPinned
|
|
self.metadata = metadata
|
|
self.metadataVersion = metadataVersion
|
|
self.agentStateVersion = agentStateVersion
|
|
self.todosUpdatedAt = todosUpdatedAt
|
|
self.todoProgress = todoProgress
|
|
self.pendingRequestsCount = pendingRequestsCount
|
|
self.pendingRequestKinds = pendingRequestKinds
|
|
self.pendingRequests = pendingRequests
|
|
self.backgroundTaskCount = backgroundTaskCount
|
|
self.futureScheduledMessageCount = futureScheduledMessageCount
|
|
self.nextScheduledAt = nextScheduledAt
|
|
self.model = model
|
|
self.modelReasoningEffort = modelReasoningEffort
|
|
self.effort = effort
|
|
}
|
|
}
|