Skip to content

feat: per-account disable/enable toggle for multi-account providers#251

Merged
ranaroussi merged 1 commit intoautomazeio:mainfrom
jason-dark:feat/routing-strategy-picker
Mar 14, 2026
Merged

feat: per-account disable/enable toggle for multi-account providers#251
ranaroussi merged 1 commit intoautomazeio:mainfrom
jason-dark:feat/routing-strategy-picker

Conversation

@jason-dark
Copy link
Copy Markdown
Contributor

@jason-dark jason-dark commented Feb 27, 2026

Summary

When multiple accounts are connected for the same provider (e.g., two Claude accounts), users currently have no way to control which accounts are active -- all accounts participate in round-robin. This PR adds a per-account Disable/Enable toggle so users can selectively deactivate individual accounts without removing them.

What it does

  • Adds a Disable/Enable button on each account row (only shown when 2+ accounts exist for a provider)
  • Disabled accounts show visual indicators: gray status dot, strikethrough name, "(disabled)" label
  • Toggling writes "disabled": true/false to the account's credential JSON file, which CLIProxyAPIPlus already respects (disabled auths are skipped during credential selection)
  • Guard: the last remaining enabled account cannot be disabled, preventing accidental lockout
  • Single-account providers are unaffected (the existing provider-level toggle already handles that case)

Files changed

File Change
SettingsView.swift AccountRowView gains disable toggle + visual states; ServiceRow computes enabled count and passes guard flag
AuthStatus.swift AuthAccount gains isDisabled field; AuthManager gains toggleAccountDisabled() that reads/writes the credential JSON

Use cases

  • "I want to use only my work account" -- disable personal account, keep work account enabled
  • "One account is rate-limited" -- disable it temporarily, re-enable later
  • Pairs with round-robin -- round-robin only rotates across enabled accounts

Summary by CodeRabbit

  • New Features
    • Users can disable and re-enable individual accounts from Settings.
    • Disabled accounts are marked "(disabled)" and visually styled (status color, text/strikethrough).
    • Disable/Enable buttons added per account with hover and accessibility text.
    • Prevents disabling the last enabled account and shows helper text when applicable.
    • Disabled state is saved and persists across sessions.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 27, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f6e7c2f and febd84a.

📒 Files selected for processing (2)
  • src/Sources/AuthStatus.swift
  • src/Sources/SettingsView.swift
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Sources/AuthStatus.swift

📝 Walkthrough

Walkthrough

Added per-account disabled state with persistence and UI controls. AuthAccount gained isDisabled, AuthManager can toggle and persist the flag, and Settings UI (AccountRowView / ServiceRow) was extended to render and handle disable/enable actions wired to a new toggle handler.

Changes

Cohort / File(s) Summary
Auth model & manager
src/Sources/AuthStatus.swift
Added isDisabled property to AuthAccount, populated from account JSON. Implemented toggleAccountDisabled(_ account: AuthAccount) -> Bool in AuthManager to read, flip, persist the disabled flag in the account JSON and refresh status with error logging.
Settings UI & wiring
src/Sources/SettingsView.swift
Extended AccountRowView signature with showDisableToggle, isLastEnabled, onToggleDisabled. Added Disable/Enable button, disabled-state visuals (label, color, strikethrough), and helper text when last-enabled constraint applies. ServiceRow now accepts onToggleDisabled: (AuthAccount) -> Void. SettingsView wires per-account toggle handlers and adds a private toggleAccountDisabled(_:) helper mirroring existing auth-result flows.

Sequence Diagram(s)

sequenceDiagram
  participant UI as "SettingsView / AccountRowView"
  participant Manager as "AuthManager"
  participant FS as "File (account JSON)"
  participant Status as "StatusRefresher"

  UI->>Manager: toggleAccountDisabled(account)
  Manager->>FS: read account JSON
  FS-->>Manager: account JSON (including disabled)
  Manager->>Manager: flip `disabled` flag
  Manager->>FS: write updated JSON
  FS-->>Manager: write result (ok / error)
  Manager->>Status: refresh auth status
  Status-->>UI: updated status (success / failure)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 A little switch in a file so small,
I nudge a flag and watch the UI call,
Enable or snooze—one hop, one click,
Persisted in JSON, tidy and quick.
Hooray for toggles, one rabbit's trick!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 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 feature: adding per-account disable/enable toggle functionality for multi-account providers, which is the core focus of the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Sources/AuthStatus.swift`:
- Around line 164-175: In toggleAccountDisabled(_ account: AuthAccount) enforce
the "last enabled account" guardrail inside AuthManager by atomically reading
all accounts (via AuthManager's account list) and refusing to flip an account
from enabled->disabled if it's the only enabled account, returning false;
perform the enable/disable toggle only after that check and write the updated
JSON to disk using an atomic write (e.g., Data.write(to:options: .atomic) or
equivalent) to avoid partial/corrupt files, and ensure the function returns
appropriate failure on race/guardrail violation.

In `@src/Sources/SettingsView.swift`:
- Around line 205-209: The per-provider round-robin logic is using total
accounts instead of only active (non-disabled) accounts; update the UI to use
the computed enabledCount for decisions: replace usages of accounts.count (e.g.,
the showDisableToggle flag passed into AccountRowView and any other place
computing round-robin/summary indicators) with enabledCount and ensure
isLastEnabled logic remains based on enabledCount (e.g., isLastEnabled:
!account.isDisabled && enabledCount <= 1) so the summary/round-robin indicator
reflects only enabled accounts.
- Around line 559-566: The toggleAccountDisabled(_) method currently only
updates the UI on success; update it so when
authManager.toggleAccountDisabled(account) returns false you also set
authResultSuccess = false, set authResultMessage to a clear failure string like
"✗ Failed to toggle \(account.displayName)" (or a localized equivalent), and set
showingAuthResult = true so the user sees an error; keep the existing success
branch unchanged and use the same state variables (authResultSuccess,
authResultMessage, showingAuthResult) to surface the failure.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cb3e59c and f6e7c2f.

📒 Files selected for processing (2)
  • src/Sources/AuthStatus.swift
  • src/Sources/SettingsView.swift

When multiple accounts are connected for the same provider, each account
row now shows a Disable/Enable button. Disabled accounts have their
JSON credential file updated with "disabled": true, which CLIProxyAPIPlus
already respects by skipping disabled auths during credential selection.

- Only shown when 2+ accounts exist (single account uses provider toggle)
- Last enabled account cannot be disabled to prevent lockout
- Visual indicators: gray dot, strikethrough, "(disabled)" label
- Round-robin label shown when multiple accounts are active
@jason-dark
Copy link
Copy Markdown
Contributor Author

@ranaroussi any thoughts on this?

@ranaroussi ranaroussi merged commit 2d25f4f into automazeio:main Mar 14, 2026
1 check passed
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.

2 participants