fix(macos-bar): correct set-default key, lead account, asset name

Send the composite provider:accountId (row.id) for Set as default so the server
can resolve the CLIProxy account; feature the account closest to exhaustion
(lowest remaining quota) in the title instead of the healthiest; rename the
packaged asset to CCS-Bar.app.zip to match what 'ccs bar install' downloads.
This commit is contained in:
Tam Nhu Tran
2026-06-07 16:38:38 -04:00
parent df4554fe1f
commit 8350c24733
4 changed files with 24 additions and 7 deletions
+2 -2
View File
@@ -54,10 +54,10 @@ case "$SIGNING" in
;;
esac
ZIP="$DIST/CCS-Bar.zip"
ZIP="$DIST/CCS-Bar.app.zip"
echo "[i] Zipping -> $ZIP"
rm -f "$ZIP"
( cd "$DIST" && ditto -c -k --keepParent "$APP_NAME.app" "CCS-Bar.zip" )
( cd "$DIST" && ditto -c -k --keepParent "$APP_NAME.app" "CCS-Bar.app.zip" )
echo "[OK] Packaged: $APP"
echo "[OK] Asset: $ZIP"
@@ -83,7 +83,10 @@ final class BarViewModel: ObservableObject {
perform { try await $0.solo(provider: row.provider, accountId: row.accountId) }
}
func setDefault(_ row: BarSummaryRow) {
perform { try await $0.setDefault(name: row.accountId) }
// The server's /api/accounts/default parses CLIProxy accounts as the
// composite "provider:accountId" key; row.id already has that shape.
// Sending the bare accountId fails parseCliproxyKey and 500s / no-ops.
perform { try await $0.setDefault(name: row.id) }
}
func tierLock(_ row: BarSummaryRow, tier: String?) {
perform { try await $0.tierLock(provider: row.provider, tier: tier) }
+10
View File
@@ -127,6 +127,16 @@ do {
check(title.contains("$3.20"), "title shows total cost")
}
// leadRow features the account CLOSEST TO EXHAUSTION (lowest remaining %),
// not the healthiest. quota_percentage is REMAINING quota.
let twoActive = [
BarSummaryRow(accountId: "a", provider: "agy", quotaPercentage: 90, health: "ok"),
BarSummaryRow(accountId: "b", provider: "agy", quotaPercentage: 30, health: "ok"),
]
let twoTitle = BarFormatting.statusTitle(rows: twoActive)
check(twoTitle.contains("30%"), "title features lowest-remaining (closest to exhaustion)")
check(!twoTitle.contains("90%"), "title does not feature the healthiest account")
// MARK: RefreshDebouncer (arms at decision time)
var deb = RefreshDebouncer(interval: 15)
@@ -30,12 +30,16 @@ public enum BarFormatting {
return parts.joined(separator: " \u{00B7} ")
}
/// The row to surface in the compact title: the one closest to exhaustion
/// (highest quota used). Rows without a known percentage sort last.
/// The row to surface in the compact title: the one closest to exhaustion.
/// `quota_percentage` is REMAINING quota (higher = more left), so the lead is
/// the LOWEST remaining percentage. Rows without a known percentage are not
/// chosen unless no row has one.
static func leadRow(_ rows: [BarSummaryRow]) -> BarSummaryRow? {
rows.max { lhs, rhs in
(lhs.quotaPercentage ?? -1) < (rhs.quotaPercentage ?? -1)
let withPct = rows.filter { $0.quotaPercentage != nil }
if let lead = withPct.min(by: { ($0.quotaPercentage ?? 0) < ($1.quotaPercentage ?? 0) }) {
return lead
}
return rows.first
}
}