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 var body: some View { HStack(spacing: Metrics.chipSpacing) { if let contextText = model.contextText { Text(contextText) .foregroundStyle(model.isContextWarning ? Color.orange : Color.secondary) } if let costText = model.costText { chip(costText) } if let modelName = model.modelName { chip(modelName) } prBadge } .font(.caption2.monospacedDigit()) .lineLimit(1) .opacity(model.isStale ? Metrics.staleOpacity : 1) .grayscale(model.isStale ? 1 : 0) } @ViewBuilder private var prBadge: some View { if let prText = model.prText { let label = model.prReviewState.map { "\(prText) · \($0)" } ?? prText if let url = model.prURL { Link(label, destination: url) } else { chip(label) } } } private func chip(_ text: String) -> some View { Text(text) .foregroundStyle(.secondary) .padding(.horizontal, Metrics.chipHorizontalPadding) .background(.quaternary, in: Capsule()) } // MARK: - Named constants (no magic numbers, plan §4) private enum Metrics { static let chipSpacing: CGFloat = 6 static let chipHorizontalPadding: CGFloat = 5 static let staleOpacity = 0.45 } 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" } }