feat(mac): show context usage bars

This commit is contained in:
Peter Steinberger
2025-12-12 23:33:15 +00:00
parent d5d80f4247
commit 35b7c0f558
4 changed files with 178 additions and 38 deletions

View File

@@ -16,6 +16,7 @@ struct MenuContent: View {
@State private var availableMics: [AudioInputDevice] = []
@State private var loadingMics = false
@State private var sessionMenu: [SessionRow] = []
@State private var mainSessionRow: SessionRow?
var body: some View {
VStack(alignment: .leading, spacing: 8) {
@@ -24,6 +25,7 @@ struct MenuContent: View {
Text(label)
}
self.statusRow
self.mainSessionContextRow
Toggle(isOn: self.heartbeatsBinding) { Text("Send Heartbeats") }
self.heartbeatStatusRow
Toggle(isOn: self.voiceWakeBinding) { Text("Voice Wake") }
@@ -182,6 +184,7 @@ struct MenuContent: View {
}
.task {
await self.reloadSessionMenu()
await self.reloadMainSessionRow()
}
.task {
VoicePushToTalkHotkey.shared.setEnabled(voiceWakeSupported && self.state.voicePushToTalkEnabled)
@@ -247,6 +250,38 @@ struct MenuContent: View {
.disabled(true)
}
@ViewBuilder
private var mainSessionContextRow: some View {
if let row = self.mainSessionRow {
VStack(alignment: .leading, spacing: 6) {
HStack(spacing: 8) {
Text("Context (\(row.key))")
.font(.caption.weight(.semibold))
.foregroundStyle(.secondary)
Spacer()
Text(row.tokens.contextSummaryShort)
.font(.caption.monospacedDigit())
.foregroundStyle(.secondary)
}
ContextUsageBar(
usedTokens: row.tokens.total,
contextTokens: row.tokens.contextTokens)
}
.padding(.vertical, 2)
} else {
HStack(spacing: 8) {
Text("Context (main)")
.font(.caption.weight(.semibold))
.foregroundStyle(.secondary)
Spacer()
Text("")
.font(.caption.monospacedDigit())
.foregroundStyle(.secondary)
}
.padding(.vertical, 2)
}
}
private var heartbeatStatusRow: some View {
let (label, color): (String, Color) = {
if case .degraded = self.controlChannel.state {
@@ -397,4 +432,22 @@ struct MenuContent: View {
let name: String
var id: String { self.uid }
}
private func reloadMainSessionRow() async {
let hints = SessionLoader.configHints()
let store = SessionLoader.resolveStorePath(override: hints.storePath)
let defaults = SessionDefaults(
model: hints.model ?? SessionLoader.fallbackModel,
contextTokens: hints.contextTokens ?? SessionLoader.fallbackContextTokens)
guard let rows = try? await SessionLoader.loadRows(at: store, defaults: defaults) else {
self.mainSessionRow = nil
return
}
let preferred = WebChatManager.shared.preferredSessionKey()
self.mainSessionRow =
rows.first(where: { $0.key == "main" }) ??
rows.first(where: { $0.key == preferred }) ??
rows.first
}
}