import SwiftUI import WireProtocol /// T-iOS-13 · Telemetry chips for a session-list row — the iOS mirror of the /// web's `renderTelemetryGauge` (public/preview-grid.ts:197): context-usage % /// (warn > 80), $cost to 4 places, model chip, PR badge. /// /// Staleness: chips grey out when `StatusTelemetry.at` is STRICTLY older than /// `Tunables.telemetryStaleTtlMs` (same `>` rule as the web's `tg-stale`). /// The comparison lives in `Model`, computed from an injected `nowMs` so the /// ViewModel tests are deterministic (task RED list). /// /// Security (mirrors SEC-H5/SEC-L5): every telemetry string is server-supplied /// UNTRUSTED input — rendered as plain `Text` only; the PR badge becomes a /// tappable `Link` iff its URL parses as https, otherwise it renders as text. struct TelemetryChips: View { /// Immutable render input, derived once per list rebuild. struct Model: Equatable, Sendable { let contextUsedPct: Double? /// Pre-formatted `$X.XXXX` (mirrors the web's `toFixed(4)`). let costText: String? let modelName: String? /// Pre-formatted `PR #N`. let prText: String? let prReviewState: String? /// Tappable PR destination — https URLs ONLY (SEC-L5 mirror), else nil. let prURL: URL? /// True when `at` is strictly older than `Tunables.telemetryStaleTtlMs`. let isStale: Bool /// nil when the session has no telemetry at all (row renders no chips). init?(telemetry: StatusTelemetry?, nowMs: Int) { guard let telemetry else { return nil } isStale = nowMs - telemetry.at > Tunables.telemetryStaleTtlMs contextUsedPct = telemetry.contextUsedPct costText = telemetry.costUsd.map { String(format: Format.cost, $0) } modelName = telemetry.model if let pr = telemetry.pr { prText = "PR #\(pr.number)" prReviewState = pr.reviewState prURL = Self.httpsOnlyURL(pr.url) } else { prText = nil prReviewState = nil prURL = nil } } /// `ctx NN%` — same rounding as the web label (`Math.round`). var contextText: String? { contextUsedPct.map { "ctx \(Int($0.rounded()))%" } } /// Mirrors the web's `tg-ctx-warn` threshold (strictly > 80). var isContextWarning: Bool { (contextUsedPct ?? 0) > Format.contextWarnPct } var isEmpty: Bool { contextUsedPct == nil && costText == nil && modelName == nil && prText == nil } /// SEC-L5 mirror: only https URLs are ever offered as link targets. static func httpsOnlyURL(_ raw: String) -> URL? { guard let url = URL(string: raw), url.scheme?.lowercased() == Format.httpsScheme else { return nil } return url } } let model: Model /// Composed from the frozen `TelemetryChip` primitive — each chip is /// mono-tabular, greys itself out when `isStale`, and the context chip goes /// amber over the warn threshold. The PR chip becomes a tappable `Link` /// only when the VM handed us an https URL (SEC-L5 boundary stays in Model). var body: some View { HStack(spacing: DS.Space.xs4) { if let contextText = model.contextText { TelemetryChip( systemImage: Symbols.context, text: contextText, isStale: model.isStale, isWarning: model.isContextWarning ) } if let costText = model.costText { TelemetryChip(text: costText, isStale: model.isStale) } if let modelName = model.modelName { TelemetryChip( systemImage: Symbols.model, text: modelName, isStale: model.isStale ) } prBadge } } @ViewBuilder private var prBadge: some View { if let prText = model.prText { let label = model.prReviewState.map { "\(prText) · \($0)" } ?? prText let chip = TelemetryChip( systemImage: Symbols.pr, text: label, isStale: model.isStale ) if let url = model.prURL { Link(destination: url) { chip } } else { chip } } } // MARK: - Chip icons (SF Symbols, no magic numbers/colors — DS owns those) private enum Symbols { static let context = "gauge.medium" static let model = "cpu" static let pr = "arrow.triangle.branch" } private enum Format { /// Mirrors web `$${costUsd.toFixed(4)}`. static let cost = "$%.4f" /// Mirrors web `tg-ctx-warn` (`contextUsedPct > 80`). static let contextWarnPct = 80.0 static let httpsScheme = "https" } }