67 lines
4 KiB
Swift
67 lines
4 KiB
Swift
import Foundation
|
|
|
|
// The data seam. CockpitModel loads through CockpitAPI, so the UI is source-
|
|
// agnostic: MockCockpitAPI now, LiveCockpitAPI (→ platform-api on black:3060)
|
|
// when the engine is up. Pattern mirrors v2's MessagingAPIClient.
|
|
|
|
public protocol CockpitAPI: Sendable {
|
|
func fetchDrops() async throws -> [ContentDrop]
|
|
func fetchPending() async throws -> [PendingApproval]
|
|
func fetchAssets() async throws -> [Asset]
|
|
func fetchActions() async throws -> [AgentAction]
|
|
func fetchSpecialists() async throws -> [Specialist]
|
|
func fetchMetrics() async throws -> [SurfaceMetric]
|
|
func fetchIngestStatus() async throws -> IngestStatus
|
|
func controlIngestion(_ action: IngestControlAction) async throws -> IngestStatus
|
|
func approve(_ approvalId: UUID, edited: Bool) async throws
|
|
func setAside(_ approvalId: UUID) async throws
|
|
/// Persist a composed drop (title + arc + scheduled time) and link the selected
|
|
/// assets. Returns the created drop as a Kit model so the optimistic row can be
|
|
/// reconciled with the server's. Legs are not part of create — they fan out
|
|
/// separately (live drops carry no legs in the cockpit today).
|
|
func createDrop(title: String, arc: String, assetIds: [UUID], dropAt: Date) async throws -> ContentDrop
|
|
/// Best-effort fetch of an asset's image bytes (authenticated proxy). Returns
|
|
/// nil when the asset has no backing media (mock/composed) or the fetch fails —
|
|
/// the tile falls back to its placeholder swatch, never errors.
|
|
func fetchImageData(for asset: Asset) async -> Data?
|
|
/// Best-effort fetch of the newest availability-bump overlay screenshot for a
|
|
/// surface (authenticated proxy). Returns nil when none has been captured yet
|
|
/// or the fetch fails — the card simply doesn't render, never errors.
|
|
func fetchBumpScreenshot(surface: String) async -> Data?
|
|
}
|
|
|
|
public enum CockpitAPIError: Error, Sendable {
|
|
// Endpoint not yet on platform.api. Transport/HTTP/decoding failures surface
|
|
// as CocottePlatformAPIClient.APIError from the shared client.
|
|
case unavailable(String)
|
|
}
|
|
|
|
// Local / demo source — returns the mock dataset; approve/set-aside are no-ops (the
|
|
// model mutates its own state optimistically). `createDrop` echoes the composed drop
|
|
// back so the live reconcile path is exercised against the mock too.
|
|
public struct MockCockpitAPI: CockpitAPI {
|
|
public init() {}
|
|
public func fetchDrops() async throws -> [ContentDrop] { Mock.drops }
|
|
public func fetchPending() async throws -> [PendingApproval] { Mock.pending }
|
|
public func fetchAssets() async throws -> [Asset] { Mock.assets }
|
|
public func fetchActions() async throws -> [AgentAction] { Mock.actions }
|
|
public func fetchSpecialists() async throws -> [Specialist] { Mock.specialists }
|
|
public func fetchMetrics() async throws -> [SurfaceMetric] { Mock.metrics }
|
|
public func fetchIngestStatus() async throws -> IngestStatus {
|
|
IngestStatus(enabled: true, state: .running, totalPhotos: 11_123, processed: 4_200,
|
|
hotCount: 380, stockedCount: 3_820, explicitCount: 1_290, failedCount: 12)
|
|
}
|
|
public func controlIngestion(_ action: IngestControlAction) async throws -> IngestStatus {
|
|
try await fetchIngestStatus()
|
|
}
|
|
public func approve(_ approvalId: UUID, edited: Bool) async throws {}
|
|
public func setAside(_ approvalId: UUID) async throws {}
|
|
public func createDrop(title: String, arc: String, assetIds: [UUID], dropAt: Date) async throws -> ContentDrop {
|
|
ContentDrop(title: title, arc: arc, assetCount: assetIds.count, clusterSource: "composed",
|
|
legs: [], teaseAt: nil, dropAt: dropAt, followupAt: nil, state: .scheduled)
|
|
}
|
|
// No real media in the demo dataset — tiles render their placeholder swatch.
|
|
public func fetchImageData(for asset: Asset) async -> Data? { nil }
|
|
// No live browser in the demo — the bump screenshot card stays hidden.
|
|
public func fetchBumpScreenshot(surface: String) async -> Data? { nil }
|
|
}
|