Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
640 changes: 437 additions & 203 deletions CopilotMonitor/CLI/Providers/CopilotCLIProvider.swift

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions CopilotMonitor/CopilotMonitor.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
CLICLAUDE11111111111111 /* ClaudeProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4DDC1B4DE6B5118CE4AE8F82 /* ClaudeProvider.swift */; };
CLICODEX111111111111111 /* CodexProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 76783C44AA2329AE3FA7E981 /* CodexProvider.swift */; };
CLICOPILOT11111111111111 /* CopilotCLIProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = CLICOPILOT22222222222222 /* CopilotCLIProvider.swift */; };
CLICOPILOTUSAGE111111111 /* CopilotUsage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E22222222222222222222222 /* CopilotUsage.swift */; };
CLICOPY111111111111111111 /* opencodebar-cli in Embed CLI */ = {isa = PBXBuildFile; fileRef = CLI5555555555555555555555 /* opencodebar-cli */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
CLIHISTORY11111111111111 /* CopilotHistoryService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B1085A77EF4A58E5B5EC71B /* CopilotHistoryService.swift */; };
CLIKIMI1111111111111111 /* KimiProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = KI2222222222222222222222 /* KimiProvider.swift */; };
Expand Down Expand Up @@ -578,6 +579,7 @@
CLIPROVMGR11111111111111 /* CLIProviderManager.swift in Sources */,
CLICOPILOT11111111111111 /* CopilotCLIProvider.swift in Sources */,
CLIHISTORY11111111111111 /* CopilotHistoryService.swift in Sources */,
CLICOPILOTUSAGE111111111 /* CopilotUsage.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
11 changes: 9 additions & 2 deletions CopilotMonitor/CopilotMonitor/App/StatusBarController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1670,10 +1670,17 @@
let baseName = multiAccountBaseName(for: .copilot)
for account in accounts {
hasQuota = true
var displayName = accounts.count > 1 ? "\(baseName) #\(account.accountIndex + 1)" : baseName
// Use accountId (login) when available, otherwise fall back to index
let accountIdentifier: String
if let accountId = account.accountId?.trimmingCharacters(in: .whitespacesAndNewlines), !accountId.isEmpty {
accountIdentifier = accountId
} else {
accountIdentifier = "#\(account.accountIndex + 1)"
}
var displayName = accounts.count > 1 ? "\(baseName) (\(accountIdentifier))" : baseName
if accounts.count > 1, showCopilotAuthLabel {
let sourceLabel = authSourceLabel(for: account.details?.authSource, provider: .copilot) ?? "Unknown"
displayName += " (\(sourceLabel))"
displayName += " - \(sourceLabel)"
}
if let unavailableLabel = unavailableUsageSuffix(for: account, identifier: .copilot) {
displayName += " (\(unavailableLabel))"
Expand Down Expand Up @@ -3484,7 +3491,7 @@
// 3. OpenRouter - only has current cost, no daily history
// We'll include today's cost if available
if let routerResult = providerResults[.openRouter],
case .payAsYouGo(_, let cost, _) = routerResult.usage,

Check warning on line 3494 in CopilotMonitor/CopilotMonitor/App/StatusBarController.swift

View workflow job for this annotation

GitHub Actions / Build & Test

immutable value 'cost' was never used; consider replacing with '_' or removing it

Check warning on line 3494 in CopilotMonitor/CopilotMonitor/App/StatusBarController.swift

View workflow job for this annotation

GitHub Actions / Build & Test

immutable value 'cost' was never used; consider replacing with '_' or removing it
let dailyCost = routerResult.details?.dailyUsage {
let today = Calendar.current.startOfDay(for: Date())
if aggregatedDailyCosts[today] == nil {
Expand Down
14 changes: 9 additions & 5 deletions CopilotMonitor/CopilotMonitor/Helpers/ProviderMenuBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,18 @@ extension StatusBarController {
case .copilot:
// === Usage ===
if let used = details.copilotUsedRequests, let limit = details.copilotLimitRequests, limit > 0 {
let usageRatio = Double(used) / Double(max(limit, 1))
let isUnlimitedPlan = limit == Int.max
let usageRatio = isUnlimitedPlan ? 0.0 : (Double(used) / Double(max(limit, 1)))
let normalizedUsageRatio = min(max(usageRatio, 0), 1)
let filledBlocks = Int(normalizedUsageRatio * 10)
let emptyBlocks = 10 - filledBlocks
let progressBar = String(repeating: "═", count: filledBlocks) + String(repeating: "░", count: emptyBlocks)
let limitText = isUnlimitedPlan ? "Unlimited" : "\(limit)"
let progressItem = NSMenuItem()
progressItem.view = createDisabledLabelView(text: "[\(progressBar)] \(used)/\(limit)")
progressItem.view = createDisabledLabelView(text: "[\(progressBar)] \(used)/\(limitText)")
submenu.addItem(progressItem)

let usagePercent = (Double(used) / Double(limit)) * 100
let usagePercent = isUnlimitedPlan ? 0.0 : ((Double(used) / Double(limit)) * 100)
let items = createUsageWindowRow(label: "Monthly", usagePercent: usagePercent, resetDate: details.copilotQuotaResetDateUTC, isMonthly: true)
items.forEach { submenu.addItem($0) }
} else {
Expand Down Expand Up @@ -151,7 +153,8 @@ extension StatusBarController {

if let limit = details.copilotLimitRequests {
let freeItem = NSMenuItem()
freeItem.view = createDisabledLabelView(text: "Quota Limit: \(limit)")
let limitText = (limit == Int.max) ? "Unlimited" : "\(limit)"
freeItem.view = createDisabledLabelView(text: "Quota Limit: \(limitText)")
submenu.addItem(freeItem)
}

Expand Down Expand Up @@ -680,7 +683,8 @@ extension StatusBarController {
submenu.addItem(item)
}

if let authSource = details.authSource {
// Skip generic "Token From:" for providers that already render it in their case block above.
if let authSource = details.authSource, identifier != .copilot {
submenu.addItem(NSMenuItem.separator())
let authItem = NSMenuItem()
authItem.view = createDisabledLabelView(
Expand Down
Loading
Loading