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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- Quota warnings: add opt-in predictive pace alerts for Codex and Claude session and weekly limits, with one alert per risk episode. Thanks @vincent-peng!

### Fixed
- Agent Sessions: keep local and remote session discovery off by default while preserving the General setting for explicit opt-in.
- Menus: stop completed provider cards and plan-utilization rows from remaining in “Refreshing…” while unrelated provider or token-cost work is still running. Thanks @Yuxin-Qiao!
- Codex accounts: isolate authenticated OAuth and browser-cookie requests from shared URL caches and cookie stores, preventing one account's cached quota or identity response from appearing under another account and triggering false reset alerts (#1987, #2019). Thanks @harjothkhara!
- Claude OAuth: honor the app's never-prompt policy in the bundled CLI and defer stale cache cleanup without touching Keychain until access is re-enabled. Thanks @Yuxin-Qiao!
Expand Down
2 changes: 1 addition & 1 deletion Sources/CodexBar/SettingsStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ extension SettingsStore {
let providersSortedAlphabetically = userDefaults.object(
forKey: "providersSortedAlphabetically") as? Bool ?? false
let appLanguageRaw = userDefaults.string(forKey: "appLanguage")
let agentSessionsEnabled = userDefaults.object(forKey: "agentSessionsEnabled") as? Bool ?? true
let agentSessionsEnabled = userDefaults.object(forKey: "agentSessionsEnabled") as? Bool ?? false

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve manually configured session hosts

For existing installs that saved agentSessionsManualHosts while the old default kept Agent Sessions enabled, the agentSessionsEnabled key can still be absent because editing the host field does not write this Boolean. After this change, that same state loads as disabled, and AgentSessionsStore ignores the configured hosts until the user rediscovers and re-enables the toggle, so manual remote session discovery silently regresses for those users. Consider treating non-empty manual hosts as an opt-in during this default migration or writing a one-time migrated value.

Useful? React with 👍 / 👎.

let agentSessionsManualHosts = userDefaults.string(forKey: "agentSessionsManualHosts") ?? ""
return SettingsDefaultsState(
refreshFrequency: refreshFrequency,
Expand Down
41 changes: 41 additions & 0 deletions Tests/CodexBarTests/AgentSessionMenuDescriptorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,40 @@ import Testing

@MainActor
struct AgentSessionMenuDescriptorTests {
@Test
func `fresh settings omit agent sessions until explicitly enabled`() {
let settings = testSettingsStore(suiteName: "AgentSessionMenuDescriptorTests-default-off")
settings.statusChecksEnabled = false
let store = UsageStore(
fetcher: UsageFetcher(environment: [:]),
browserDetection: BrowserDetection(cacheTTL: 0),
settings: settings)
let session = Self.session(id: "local", host: "local-mac", activity: Date())

let buildDescriptor = {
MenuDescriptor.build(
provider: .codex,
store: store,
settings: settings,
account: AccountInfo(email: nil, plan: nil),
updateReady: false,
agentSessionsEnabled: settings.agentSessionsEnabled,
localAgentSessions: [session])
}

let disabledEntries = buildDescriptor().sections.flatMap(\.entries)
#expect(!Self.containsAgentSessions(in: disabledEntries))

settings.agentSessionsEnabled = true

let enabledEntries = buildDescriptor().sections.flatMap(\.entries)
#expect(Self.containsAgentSessions(in: enabledEntries))
#expect(enabledEntries.contains { entry in
guard case .action(_, .focusAgentSession) = entry else { return false }
return true
})
}

@Test
func `session section counts groups and renders unreachable hosts`() {
let now = Date(timeIntervalSince1970: 1000)
Expand Down Expand Up @@ -87,4 +121,11 @@ struct AgentSessionMenuDescriptorTests {
transcriptPath: nil,
host: host)
}

private static func containsAgentSessions(in entries: [MenuDescriptor.Entry]) -> Bool {
entries.contains { entry in
guard case let .text(title, .headline) = entry else { return false }
return title.hasPrefix("Agent Sessions (")
}
}
}
18 changes: 18 additions & 0 deletions Tests/CodexBarTests/SettingsStoreCoverageTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,24 @@ struct SettingsStoreCoverageTests {
#expect(reloaded.copilotSettingsSnapshot(tokenOverride: nil).budgetExtrasEnabled)
}

@Test
func `agent sessions default off and persist explicit opt in`() throws {
let suite = "SettingsStoreCoverageTests-agent-sessions"
let defaults = try #require(UserDefaults(suiteName: suite))
defaults.removePersistentDomain(forName: suite)
let configStore = testConfigStore(suiteName: suite)

let initial = Self.makeSettingsStore(userDefaults: defaults, configStore: configStore)
#expect(initial.agentSessionsEnabled == false)
#expect(defaults.object(forKey: "agentSessionsEnabled") == nil)

initial.agentSessionsEnabled = true
#expect(defaults.object(forKey: "agentSessionsEnabled") as? Bool == true)

let reloaded = Self.makeSettingsStore(userDefaults: defaults, configStore: configStore)
#expect(reloaded.agentSessionsEnabled)
}

@Test
func `multi account menu layout persists and bridges legacy show all token accounts`() throws {
let suite = "SettingsStoreCoverageTests-multi-account-layout"
Expand Down