1→import SwiftUI 2→import Charts 3→ 4→// MARK: - Live Consumption Widget (Compact) 5→ 6→struct LiveConsumptionWidget: View { 7→ @StateObject private var tracker = ConsumptionTracker.shared 8→ @State private var showDetailSheet = false 9→ 10→ var body: some View { 11→ GroupBox { 12→ VStack(spacing: 12) { 13→ // Header with live indicator 14→ HStack { 15→ HStack(spacing: 6) { 16→ PulsingDot(isActive: !tracker.isPaused) 17→ Text("Live Consumption") 18→ .font(.subheadline.bold()) 19→ } 20→ 21→ Spacer() 22→ 23→ Button { 24→ showDetailSheet = true 25→ } label: { 26→ Image(systemName: "arrow.up.right.square") 27→ } 28→ .buttonStyle(.plain) 29→ .help("Open detailed view") 30→ } 31→ 32→ // Quick metrics 33→ HStack(spacing: 16) { 34→ VStack(alignment: .leading, spacing: 2) { 35→ Text("Session Cost") 36→ .font(.caption) 37→ .foregroundStyle(.secondary) 38→ Text(String(format: "$%.4f", tracker.sessionCost)) 39→ .font(.title3.bold().monospacedDigit()) 40→ .foregroundStyle(.green) 41→ } 42→ 43→ Divider() 44→ .frame(height: 40) 45→ 46→ VStack(alignment: .leading, spacing: 2) { 47→ Text("Rate") 48→ .font(.caption) 49→ .foregroundStyle(.secondary) 50→ Text(String(format: "$%.2f/hr", tracker.costPerHour)) 51→ .font(.title3.bold().monospacedDigit()) 52→ .foregroundStyle(rateColor) 53→ } 54→ 55→ Spacer() 56→ 57→ // Mini chart 58→ if !tracker.consumptionHistory.isEmpty { 59→ MiniConsumptionChart(dataPoints: tracker.consumptionHistory) 60→ .frame(width: 80, height: 40) 61→ } 62→ } 63→ 64→ // Token summary bar 65→ HStack(spacing: 4) { 66→ TokenPill(label: "In", count: tracker.sessionInputTokens, color: .blue) 67→ TokenPill(label: "Out", count: tracker.sessionOutputTokens, color: .purple) 68→ TokenPill(label: "Cache", count: tracker.sessionCacheTokens, color: .cyan) 69→ } 70→ 71→ // Active processes indicator 72→ if !tracker.activeProcesses.isEmpty { 73→ HStack { 74→ Image(systemName: "terminal.fill") 75→ .foregroundStyle(.orange) 76→ Text("\(tracker.activeProcesses.count) Claude process\(tracker.activeProcesses.count > 1 ? "es" : "") active") 77→ .font(.caption) 78→ .foregroundStyle(.secondary) 79→ Spacer() 80→ Text(tracker.sessionDuration) 81→ .font(.caption.monospacedDigit()) 82→ .foregroundStyle(.tertiary) 83→ } 84→ } 85→ } 86→ } label: { 87→ Label("Real-time Monitor", systemImage: "waveform.path.ecg") 88→ } 89→ .sheet(isPresented: $showDetailSheet) { 90→ NavigationStack { 91→ RealtimeConsumptionView() 92→ .frame(minWidth: 700, minHeight: 600) 93→ .toolbar { 94→ ToolbarItem(placement: .cancellationAction) { 95→ Button("Close") { 96→ showDetailSheet = false 97→ } 98→ } 99→ } 100→ } 101→ } 102→ } 103→ 104→ private var rateColor: Color { 105→ if tracker.costPerHour > 5.0 { return .red } 106→ if tracker.costPerHour > 2.0 { return .orange } 107→ return .green 108→ } 109→} 110→ 111→// MARK: - Pulsing Dot 112→ 113→struct PulsingDot: View { 114→ let isActive: Bool 115→ @State private var isPulsing = false 116→ 117→ var body: some View { 118→ Circle() 119→ .fill(isActive ? .green : .orange) 120→ .frame(width: 8, height: 8) 121→ .scaleEffect(isPulsing && isActive ? 1.3 : 1.0) 122→ .animation( 123→ isActive ? .easeInOut(duration: 1).repeatForever(autoreverses: true) : .default, 124→ value: isPulsing 125→ ) 126→ .onAppear { 127→ isPulsing = true 128→ } 129→ } 130→} 131→ 132→// MARK: - Token Pill 133→ 134→struct TokenPill: View { 135→ let label: String 136→ let count: Int 137→ let color: Color 138→ 139→ var body: some View { 140→ HStack(spacing: 4) { 141→ Circle() 142→ .fill(color) 143→ .frame(width: 6, height: 6) 144→ Text(label) 145→ .font(.caption2) 146→ Text(formatCount(count)) 147→ .font(.caption2.monospacedDigit().bold()) 148→ } 149→ .padding(.horizontal, 8) 150→ .padding(.vertical, 4) 151→ .background(color.opacity(0.15)) 152→ .clipShape(Capsule()) 153→ } 154→ 155→ private func formatCount(_ count: Int) -> String { 156→ if count >= 1_000_000 { 157→ return String(format: "%.1fM", Double(count) / 1_000_000) 158→ } else if count >= 1_000 { 159→ return String(format: "%.1fK", Double(count) / 1_000) 160→ } 161→ return "\(count)" 162→ } 163→} 164→ 165→// MARK: - Mini Consumption Chart 166→ 167→struct MiniConsumptionChart: View { 168→ let dataPoints: [ConsumptionDataPoint] 169→ 170→ var body: some View { 171→ Chart { 172→ ForEach(dataPoints.suffix(20)) { point in 173→ LineMark( 174→ x: .value("Time", point.timestamp), 175→ y: .value("Cost", point.cumulativeCost) 176→ ) 177→ .foregroundStyle(.green) 178→ .interpolationMethod(.catmullRom) 179→ } 180→ } 181→ .chartXAxis(.hidden) 182→ .chartYAxis(.hidden) 183→ .chartLegend(.hidden) 184→ } 185→} 186→ 187→// MARK: - Menu Bar Consumption View 188→ 189→struct MenuBarConsumptionView: View { 190→ @StateObject private var tracker = ConsumptionTracker.shared 191→ 192→ var body: some View { 193→ VStack(alignment: .leading, spacing: 8) { 194→ HStack { 195→ PulsingDot(isActive: !tracker.isPaused) 196→ Text("Live Tracking") 197→ .font(.caption.bold()) 198→ Spacer() 199→ Text(tracker.sessionDuration) 200→ .font(.caption.monospacedDigit()) 201→ .foregroundStyle(.secondary) 202→ } 203→ 204→ Divider() 205→ 206→ HStack { 207→ VStack(alignment: .leading, spacing: 2) { 208→ Text("Session") 209→ .font(.caption2) 210→ .foregroundStyle(.secondary) 211→ Text(String(format: "$%.4f", tracker.sessionCost)) 212→ .font(.caption.bold().monospacedDigit()) 213→ } 214→ 215→ Spacer() 216→ 217→ VStack(alignment: .trailing, spacing: 2) { 218→ Text("Rate") 219→ .font(.caption2) 220→ .foregroundStyle(.secondary) 221→ Text(String(format: "$%.2f/hr", tracker.costPerHour)) 222→ .font(.caption.bold().monospacedDigit()) 223→ .foregroundStyle(tracker.costPerHour > 2.0 ? .orange : .green) 224→ } 225→ } 226→ 227→ // Compact token display 228→ HStack(spacing: 8) { 229→ Label(formatTokens(tracker.sessionInputTokens), systemImage: "arrow.down") 230→ .foregroundStyle(.blue) 231→ Label(formatTokens(tracker.sessionOutputTokens), systemImage: "arrow.up") 232→ .foregroundStyle(.purple) 233→ } 234→ .font(.caption2.monospacedDigit()) 235→ 236→ if !tracker.activeProcesses.isEmpty { 237→ HStack { 238→ Image(systemName: "terminal.fill") 239→ .foregroundStyle(.orange) 240→ Text("\(tracker.activeProcesses.count) active") 241→ } 242→ .font(.caption2) 243→ .foregroundStyle(.secondary) 244→ } 245→ } 246→ .padding(8) 247→ } 248→ 249→ private func formatTokens(_ count: Int) -> String { 250→ if count >= 1_000_000 { 251→ return String(format: "%.1fM", Double(count) / 1_000_000) 252→ } else if count >= 1_000 { 253→ return String(format: "%.0fK", Double(count) / 1_000) 254→ } 255→ return "\(count)" 256→ } 257→} 258→ 259→// MARK: - Preview 260→ 261→#Preview("Widget") { 262→ LiveConsumptionWidget() 263→ .frame(width: 400) 264→ .padding() 265→} 266→ 267→#Preview("Menu Bar") { 268→ MenuBarConsumptionView() 269→ .frame(width: 200) 270→} 271→ Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.