Skip to content

refactor: drive usage pills from a provider registry - #617

Open
1AdityaX wants to merge 2 commits into
Octane0411:mainfrom
1AdityaX:pr/usage-provider-registry
Open

refactor: drive usage pills from a provider registry#617
1AdityaX wants to merge 2 commits into
Octane0411:mainfrom
1AdityaX:pr/usage-provider-registry

Conversation

@1AdityaX

@1AdityaX 1AdityaX commented Jul 24, 2026

Copy link
Copy Markdown

Closes #501.

Overlaps with #613. That PR restructures the same UsageProviderPresentation and UsageWindowPresentation types in IslandPanelView.swift to show Codex usage as remaining percentage instead of used percentage. This PR takes a different approach (a UsageProvider registry instead of string IDs) and also fixes stale/expired windows still being displayed, which #613 does not address. Whichever merges first, the other needs a rebase.

Problem

Usage was written as two hardcoded pipelines. Provider identity lived in raw "claude" / "codex" strings that had to agree across the selection helper, the pill IDs, and a shortTitle switch. The island rebuilt each snapshot shape by hand, summary text was duplicated per provider, and the Codex toggle only persisted, so switching it on mid-session left the pill blank until the next launch.

Usage caches are also only rewritten while a harness runs, so a cache that outlives its window kept reporting the previous window's number. A 12h-old Claude cache whose 5h window had reset 7h earlier still headlined the pill as "5h 10%", reading like the weekly figure in the wrong slot, since the peak picker promotes the stale value over the live 7d window.

Changes

  • UsageProvider is the single registry now: labels, which harness draws down the quota, the Settings opt-in key, poll interval.
  • UsageSnapshotSummarizing (Core) normalizes Claude's five_hour/seven_day and Codex's primary/secondary into one UsageWindowSummary shape.
  • Windows past their resets_at are dropped from both the pill and the Settings summary. A provider disappears once every window has rolled over instead of showing dead numbers.
  • Toggling a provider in Settings starts or stops its poll loop immediately instead of only persisting.

Testing

swift build, swift test. Pre-existing failures in AppModelSessionListTests and AgentsGridRightSlotTests reproduce identically against a clean main with none of this branch's changes applied. Unrelated flakiness, not introduced here.

Summary by CodeRabbit

  • New Features

    • Added support for usage monitoring across multiple providers with individual opt-in settings.
    • Added a provider selector to switch between available usage summaries.
    • Usage displays now show active limits, reset times, and stale-data indicators.
    • Provider selection can follow the active tool or a manual override.
  • Bug Fixes

    • Usage windows now disappear after their reset time.
    • Improved session detail and notification badge presentation.
  • Tests

    • Added coverage for provider selection, opt-in behavior, usage expiry, and summary formatting.

1AdityaX added 2 commits July 24, 2026 05:38
Usage was written as two hardcoded pipelines. Provider identity lived in
raw "claude" / "codex" strings that had to agree across the selection
helper, the pill IDs and a shortTitle switch. The island rebuilt each
snapshot shape by hand, the summary text was duplicated per provider, and
the Codex toggle only persisted, so switching it on mid-session left the
pill blank until the next launch.

Introduce UsageProvider as the single registry (labels, harness mapping,
opt-in key, poll interval) and UsageSnapshotSummarizing in Core so both
snapshot shapes normalize into UsageWindowSummary. The island, Settings
and the monitor loops now iterate providers instead of naming them, and
toggling a provider starts or stops its poll loop immediately.

Claude and Codex stay the two registered providers. They are now covered
by tests rather than being what the code is shaped around.
Usage caches are only rewritten while a harness runs. Claude Code's
status line writes on each turn, Codex on each rollout append. A cache
that outlives its window keeps reporting the previous window's number:
a 12h-old cache whose 5h window reset 7h earlier still headlined the
pill as "5h 10%", which read like the weekly figure sitting in the
wrong slot because the peak picker promoted it over the live 7d window.

Filter windows whose resets_at has passed out of both the island pill
and the Settings summary, drop the provider entirely once every window
has rolled over, and note the cache age in the pill tooltip once the
numbers stop tracking the live quota.

Adds AppModel-level coverage for the usage pipeline the island reads:
opt-in gating, provider ordering, peak selection, and opt-in persistence
across launches.
@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR replaces Codex-specific usage settings and monitoring with a generalized UsageProvider system. It normalizes Claude and Codex snapshots, persists per-provider opt-ins, manages provider-specific polling, and adds selectable usage-provider presentation in the island UI.

Changes

Usage provider system

Layer / File(s) Summary
Normalized provider contracts
Sources/OpenIslandApp/UsageProvider.swift, Sources/OpenIslandCore/UsageSnapshot.swift, Tests/OpenIslandAppTests/AgentSessionPresentationTests.swift
Adds provider metadata, selection rules, display statuses, normalized usage windows, snapshot expiry filtering, and coverage for registry and normalization behavior.
Provider monitoring and application state
Sources/OpenIslandApp/AppModel.swift, Sources/OpenIslandApp/HookInstallationCoordinator.swift, Tests/OpenIslandAppTests/AppModelUsageProviderTests.swift
Persists provider opt-ins, derives live statuses, starts monitoring for enabled providers, and replaces provider-specific tasks with provider-keyed monitoring.
Usage provider settings and panel presentation
Sources/OpenIslandApp/Views/SettingsView.swift, Sources/OpenIslandApp/Views/IslandPanelView.swift
Replaces the Codex-only toggle with dynamic provider toggles and adds provider selection, dropdown presentation, stale-cache text, and updated header sizing.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant SettingsView
  participant AppModel
  participant HookInstallationCoordinator
  participant IslandPanelView
  User->>SettingsView: enable or disable provider
  SettingsView->>AppModel: setUsageProvider(provider, enabled:)
  AppModel->>HookInstallationCoordinator: start or stopUsageMonitoring(for:)
  HookInstallationCoordinator->>AppModel: refresh provider snapshot
  IslandPanelView->>AppModel: read usageProviderStatuses
  AppModel-->>IslandPanelView: return live provider status
Loading

Possibly related PRs

Suggested reviewers: octane0411

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main refactor: usage pills now come from a provider registry.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
Sources/OpenIslandCore/UsageSnapshot.swift (1)

11-45: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

New usage model types violate the Sendable + Codable model rule. The guideline "All models must be Sendable and Codable" is unmet by the usage models added in this PR; conformances chain through these three simple, trivially-conformable types.

  • Sources/OpenIslandCore/UsageSnapshot.swift#L11-L45: add Codable to UsageWindowSummary.
  • Sources/OpenIslandApp/UsageProvider.swift#L112-L141: add Sendable, Codable to UsageProviderStatus, and add Codable to the UsageProvider enum (needed for UsageProviderStatus's synthesized Codable).

As per coding guidelines: "All models must be Sendable and Codable".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Sources/OpenIslandCore/UsageSnapshot.swift` around lines 11 - 45, Update
UsageWindowSummary in Sources/OpenIslandCore/UsageSnapshot.swift:11-45 to
conform to Codable. In Sources/OpenIslandApp/UsageProvider.swift:112-141, add
Sendable and Codable to UsageProviderStatus, and add Codable to the
UsageProvider enum so synthesized Codable conformance succeeds.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/OpenIslandApp/AppModel.swift`:
- Around line 1166-1168: Update the startup usage-monitoring loop around
isUsageProviderEnabled so the Claude provider is monitored only when
claudeUsageInstalled is true, while preserving existing behavior for other
providers. Ensure installClaudeUsageBridge() starts Claude provider monitoring
after a successful bridge installation so the usage pill populates immediately.

---

Nitpick comments:
In `@Sources/OpenIslandCore/UsageSnapshot.swift`:
- Around line 11-45: Update UsageWindowSummary in
Sources/OpenIslandCore/UsageSnapshot.swift:11-45 to conform to Codable. In
Sources/OpenIslandApp/UsageProvider.swift:112-141, add Sendable and Codable to
UsageProviderStatus, and add Codable to the UsageProvider enum so synthesized
Codable conformance succeeds.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 382f7866-301c-40be-b87b-cd9edd72cfb0

📥 Commits

Reviewing files that changed from the base of the PR and between 6e5e7a6 and 8cdb5ed.

📒 Files selected for processing (8)
  • Sources/OpenIslandApp/AppModel.swift
  • Sources/OpenIslandApp/HookInstallationCoordinator.swift
  • Sources/OpenIslandApp/UsageProvider.swift
  • Sources/OpenIslandApp/Views/IslandPanelView.swift
  • Sources/OpenIslandApp/Views/SettingsView.swift
  • Sources/OpenIslandCore/UsageSnapshot.swift
  • Tests/OpenIslandAppTests/AgentSessionPresentationTests.swift
  • Tests/OpenIslandAppTests/AppModelUsageProviderTests.swift

Comment thread Sources/OpenIslandApp/AppModel.swift
@1AdityaX

1AdityaX commented Jul 24, 2026

Copy link
Copy Markdown
Author
image

Screenshot of the dropdown to see usage across multiple AI coding assistants

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CC 用量 & 刷新时间 显示不完整

1 participant