Skip to content

Conversation

@sogoiii
Copy link
Contributor

@sogoiii sogoiii commented Jan 4, 2026

Summary

Implement automatic provider switching after successful OAuth authentication. When a user logs in with a specific provider via the /auth <provider> command, the active provider is automatically switched to that authenticated provider.

Changes

  • Added switchActiveProvider function to update the active provider after authentication
  • Added getEphemeralSetting to check the auth.autoSwitchProvider setting (defaults to true)
  • Modified auth command flow to trigger provider switch on successful OAuth login
  • Added integration tests covering auto-switch behavior and edge cases

Features

  • Auto-switches provider when OAuth login succeeds
  • Gracefully degrades if switch fails - auth succeeds, user informed to switch manually
  • Skips message when provider already active - shows standard success
  • Controlled by auth.autoSwitchProvider setting

Testing

  • 191 new integration test cases for auto-switch behavior
  • Covers success scenarios, provider already active, switch failures
  • Validates error handling and user feedback

Breaking Changes

None

Files Changed

  • packages/cli/src/ui/commands/authCommand.ts - Core implementation
  • packages/cli/src/ui/commands/__tests__/authCommand.autoswitch.spec.ts - Test suite

Summary by CodeRabbit

  • New Features
    • Auto-switch now optionally switches to the newly authenticated provider after login (enabled by default, can be disabled). Provides clear user messages and does not fail authentication if switching errors occur.
  • Tests
    • Added tests covering auto-switch behavior across success, disabled/default, error, bucket, and provider-change scenarios.

✏️ Tip: You can customize this high-level summary in your review settings.

Implement REQ-001: After successful OAuth authentication via /auth <provider> login,
automatically switch the active provider to the authenticated provider.

- Add switchActiveProvider and getEphemeralSetting imports
- Check auth.autoSwitchProvider setting (defaults to true)
- On successful auth + switch: show "[OK] Authenticated with X and set as active provider"
- If switch fails: gracefully degrade, still report auth success with manual switch hint
- If provider already active: just show standard auth success message
Comprehensive tests covering:
- Auto-switch after successful OAuth login
- Bucket info in success messages
- Configurable setting (enable/disable)
- Graceful error handling when switch fails
- Override behavior for existing provider
@sogoiii sogoiii requested a review from acoliver as a code owner January 4, 2026 22:26
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 4, 2026

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description provides a comprehensive summary, detailed changes, features, testing coverage, and breaking changes assessment. However, it lacks the template structure (TLDR, Dive Deeper, Reviewer Test Plan, Testing Matrix, Linked issues) required by the repository template. Restructure the description to follow the repository template: add TLDR, Dive Deeper, Reviewer Test Plan, Testing Matrix table, and Linked issues sections with issue references or #1008 closure statement.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main feature: automatic provider switching after successful OAuth login, which is the primary objective of the PR.
✨ Finishing touches
  • 📝 Generate docstrings

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.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 4, 2026

⚠️ LLxprt PR Review blocked

  • No linked issues were detected in this PR's description.
  • Please reference an existing issue with text such as Fixes #123 so the automated review knows what problem to evaluate.
  • The PR has been returned to draft to prevent accidental merges without an issue.

Copy link
Contributor

@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: 0

🧹 Nitpick comments (3)
packages/cli/src/ui/commands/__tests__/authCommand.autoswitch.spec.ts (3)

30-33: Consider more specific mock types for better type safety.

While using ReturnType<typeof vi.fn> works, more specific typing would provide better type checking. Consider typing the mocks with their actual function signatures:

const mockSwitchActiveProvider = switchActiveProvider as unknown as vi.MockedFunction<typeof switchActiveProvider>;
const mockGetEphemeralSetting = getEphemeralSetting as unknown as vi.MockedFunction<typeof getEphemeralSetting>;

This provides better autocomplete and type checking in tests while still allowing for mock configuration.


43-48: Consider creating a test helper type for better type safety.

The cast as unknown as OAuthManager bypasses TypeScript's type checking. While this is common in tests, consider creating a dedicated test helper type:

🔎 Proposed refactor for improved type safety
+type MockOAuthManager = Pick<OAuthManager, 'authenticate' | 'getSupportedProviders'>;
+
 beforeEach(() => {
   vi.clearAllMocks();
 
   mockOAuthManager = {
     authenticate: vi.fn().mockResolvedValue(undefined),
     getSupportedProviders: vi
       .fn()
       .mockReturnValue(['gemini', 'qwen', 'anthropic', 'codex']),
-  } as unknown as OAuthManager;
+  } as MockOAuthManager as OAuthManager;

This makes the intended partial mock explicit and easier to maintain.


52-61: Context mock uses as never casts, which bypasses type safety.

While the minimal mock works for these focused tests, the as never casts can mask issues if the implementation starts using these properties. Consider creating a test helper that provides a more complete mock:

🔎 Proposed refactor for a more robust context mock
function createMockContext(): CommandContext {
  return {
    services: {
      config: null,
      settings: {} as LoadedSettings,
      git: undefined,
      logger: {
        log: vi.fn(),
        error: vi.fn(),
        warn: vi.fn(),
        debug: vi.fn(),
      } as unknown as Logger,
    },
    ui: {
      addItem: vi.fn(),
      clear: vi.fn(),
      // ... other required properties
    } as unknown as CommandContext['ui'],
    session: {
      stats: {} as SessionStatsState,
      sessionShellAllowlist: new Set(),
    },
  };
}

This makes the mock more maintainable and catches usage of unexpected properties.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f9d76e1 and 7fc20de.

📒 Files selected for processing (2)
  • packages/cli/src/ui/commands/__tests__/authCommand.autoswitch.spec.ts
  • packages/cli/src/ui/commands/authCommand.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Don't use any - Always specify proper types. Use unknown if the type is truly unknown and add proper type guards.
Do not use console.log or console.debug - Use the sophisticated logging system instead. Log files are written to ~/.llxprt/debug/
Fix all linting errors, including warnings about any types

Files:

  • packages/cli/src/ui/commands/authCommand.ts
  • packages/cli/src/ui/commands/__tests__/authCommand.autoswitch.spec.ts
🧠 Learnings (1)
📚 Learning: 2025-12-13T16:04:07.079Z
Learnt from: acoliver
Repo: vybestack/llxprt-code PR: 0
File: :0-0
Timestamp: 2025-12-13T16:04:07.079Z
Learning: Auth commands UX: /auth <provider> login [bucket] (eager device flow), /auth <provider> logout <default|bucket|all>, /auth <provider> status; all arguments autocomplete bucket names (including "default").

Applied to files:

  • packages/cli/src/ui/commands/authCommand.ts
🧬 Code graph analysis (1)
packages/cli/src/ui/commands/__tests__/authCommand.autoswitch.spec.ts (3)
packages/cli/src/runtime/runtimeSettings.ts (1)
  • switchActiveProvider (1478-1962)
packages/cli/src/ui/commands/authCommand.ts (1)
  • AuthCommandExecutor (184-687)
packages/cli/src/ui/commands/types.ts (1)
  • CommandContext (32-98)
⏰ Context from checks skipped due to timeout of 270000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Test (windows-latest, 24.x)
  • GitHub Check: Test (ubuntu-latest, 24.x)
  • GitHub Check: Test (macos-latest, 24.x)
🔇 Additional comments (5)
packages/cli/src/ui/commands/authCommand.ts (3)

29-32: LGTM! Imports are properly structured.

The new imports for switchActiveProvider and getEphemeralSetting are correctly added and used in the auto-switch implementation.


427-457: LGTM! Auto-switch logic is well-structured with proper error handling.

The implementation correctly:

  • Attempts the provider switch after successful authentication
  • Differentiates between changed/unchanged provider states with appropriate messaging
  • Gracefully handles switch failures without failing the authentication
  • Uses the debug logger instead of console.log (per coding guidelines)

The error handling ensures authentication success is preserved even if the auto-switch fails, which is the correct behavior.


423-425: The type safety is already properly implemented. getEphemeralSetting returns unknown (not any), and the usage with ?? true provides an explicit type guard that narrows the result to boolean. No changes are required.

packages/cli/src/ui/commands/__tests__/authCommand.autoswitch.spec.ts (2)

12-23: LGTM! Partial mock setup is well-structured.

The use of importOriginal with proper TypeScript typing ensures that only the necessary functions are mocked while preserving the rest of the module's behavior. This is a good testing practice.


76-191: LGTM! Excellent test coverage with clear requirement mapping.

The test suite demonstrates:

  • Clear organization by requirements (REQ-001, REQ-008, REQ-010, REQ-004.2)
  • Comprehensive coverage of success scenarios, configuration options, error handling, and edge cases
  • Proper verification of both function calls and return values
  • Good use of descriptive test names that explain the behavior being tested

The tests effectively validate the auto-switch functionality and its integration with the authentication flow.

… mock runtime context

- Add continueSession: false to Config constructor in gemini render options tests
- Add mock for runtimeSettings module in auth bucket tests to bypass CLI runtime context requirements
Copy link
Contributor

@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: 0

🧹 Nitpick comments (1)
packages/cli/src/ui/commands/__tests__/authCommand.bucket.spec.ts (1)

21-36: Consider making the mock more flexible for future test scenarios.

The hardcoded mock return values (previousProvider: 'anthropic', nextProvider: 'anthropic', changed: false) work for the current test suite since all tests use the 'anthropic' provider. However, this approach could be brittle if tests are added for other providers or scenarios requiring different mock behaviors.

Consider one of these alternatives:

  1. Make the mock functions configurable per test by exposing them and allowing tests to override behavior when needed
  2. Use dynamic return values that adapt to the provider being tested
  3. Add a comment explaining why these specific hardcoded values are safe for this test suite
🔎 Example: Exposing mock for per-test configuration
+// Export mocks for per-test customization
+export const mockSwitchActiveProvider = vi.fn().mockResolvedValue({
+  changed: false,
+  previousProvider: 'anthropic',
+  nextProvider: 'anthropic',
+});
+export const mockGetEphemeralSetting = vi.fn().mockReturnValue(true);
+
 vi.mock('../../../runtime/runtimeSettings.js', async (importOriginal) => {
   const actual =
     await importOriginal<
       typeof import('../../../runtime/runtimeSettings.js')
     >();
   return {
     ...actual,
-    switchActiveProvider: vi.fn().mockResolvedValue({
-      changed: false,
-      previousProvider: 'anthropic',
-      nextProvider: 'anthropic',
-    }),
-    getEphemeralSetting: vi.fn().mockReturnValue(true),
+    switchActiveProvider: mockSwitchActiveProvider,
+    getEphemeralSetting: mockGetEphemeralSetting,
   };
 });

Then tests can customize behavior:

beforeEach(() => {
  mockSwitchActiveProvider.mockResolvedValue({
    changed: true,
    previousProvider: 'gemini',
    nextProvider: 'anthropic',
  });
});
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7fc20de and 467d196.

📒 Files selected for processing (2)
  • packages/cli/src/gemini.renderOptions.test.tsx
  • packages/cli/src/ui/commands/__tests__/authCommand.bucket.spec.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Don't use any - Always specify proper types. Use unknown if the type is truly unknown and add proper type guards.
Do not use console.log or console.debug - Use the sophisticated logging system instead. Log files are written to ~/.llxprt/debug/
Fix all linting errors, including warnings about any types

Files:

  • packages/cli/src/gemini.renderOptions.test.tsx
  • packages/cli/src/ui/commands/__tests__/authCommand.bucket.spec.ts
⏰ Context from checks skipped due to timeout of 270000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Test (ubuntu-latest, 24.x)
  • GitHub Check: Test (windows-latest, 24.x)
  • GitHub Check: Test (macos-latest, 24.x)
🔇 Additional comments (2)
packages/cli/src/gemini.renderOptions.test.tsx (2)

86-94: LGTM! Test configuration updated appropriately.

The addition of continueSession: false aligns the test with the Config constructor requirements without affecting test behavior.


114-122: LGTM! Consistent with the first test case.

The configuration parameter is correctly added here as well.

@acoliver
Copy link
Collaborator

acoliver commented Jan 6, 2026

@CodeRabbit

discussed in the discord channel with the author. Because we generally want to auth in advance for bucket failover profiles and load balancer profiles and we may auth for GoogleWebSearch and for subagents -- we may not want to switch providers. There is a severe documentation gap after 0.7.0 on how to use

  1. Profiles + Oauth
  2. Profiles + Oauth Bucket Failover
  3. Profiles + Load Balancers
  4. Profiles + Subagents

and a general gap on how to set up your workflow. We should address that. I think there is some version of this PR that could be merged once the workflow is figured out with the topics above. For now, I'm converting it to a draft.

@acoliver acoliver marked this pull request as draft January 6, 2026 03:14
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 6, 2026

Tip

For best results, initiate chat on the files or code changes.

@acoliver, thank you for the thoughtful analysis. You've identified a critical UX issue with auto-switching in multi-provider workflows.

The Core Concern

You're absolutely right—auto-switching conflicts with several legitimate use cases:

  1. Pre-authenticating backup providers for bucket failover: If you're setting up provider B as a fallback while provider A is active, you don't want to suddenly switch to B
  2. Load balancer profiles: When authenticating multiple providers for distribution, you need explicit control over which one is active
  3. Service-specific auth (GoogleWebSearch): Authenticating a provider for a specific service shouldn't change your primary working provider
  4. Subagent auth: When setting up providers for subagents, the parent session's active provider should remain stable

Current State & Potential Paths Forward

The PR does include auth.autoSwitchProvider setting (defaults to true), but this may not be sufficient:

Option 1: Change the default

  • Set auth.autoSwitchProvider to false by default, making it opt-in rather than opt-out
  • More conservative for advanced workflows

Option 2: Context-aware behavior

  • Add command flags like /auth <provider> --no-switch or /auth <provider> --for-failover
  • Detect context (e.g., authenticating non-primary providers in bucket/load balancer configs)

Option 3: Explicit switch command

  • Keep auto-switch disabled and require explicit /provider set <name> or similar command
  • Clearest separation of concerns

Documentation Gap

The identified documentation needs are critical:

  1. Profiles + OAuth: How to authenticate providers within profile contexts
  2. Bucket Failover + OAuth: Best practices for pre-authenticating backup providers
  3. Load Balancers + OAuth: Managing multiple authenticated providers
  4. Subagents + OAuth: Provider authentication patterns for subagent scenarios
  5. Workflow Setup: End-to-end guide for common configurations

I can help draft documentation outlines or examples for these workflows once the desired behavior is settled.

Recommendation

Converting to draft is the right call. I'd suggest:

  1. Discuss with the author whether auto-switch should be opt-in (default false) vs opt-out (current default true)
  2. Consider adding a --switch / --no-switch flag for per-command control
  3. Once the behavior is decided, merge a version that aligns with the multi-provider workflow needs
  4. Create follow-up issues for documentation of the identified workflow gaps

Would you like me to help create documentation issues for the workflow gaps, or would you prefer to coordinate that after the auth behavior is finalized?


✏️ Learnings added
Learnt from: acoliver
URL: https://github.com/vybestack/llxprt-code/pull/1008

Timestamp: 2026-01-06T03:14:42.588Z
Learning: Auto-switching the active provider after OAuth authentication can conflict with multi-provider workflows: pre-authenticating backup providers for bucket failover, setting up load balancer profiles, authenticating GoogleWebSearch, and authenticating subagents. Users need explicit control in these scenarios.

Learnt from: acoliver
URL: https://github.com/vybestack/llxprt-code/pull/1008

Timestamp: 2026-01-06T03:14:42.588Z
Learning: Documentation is needed post-0.7.0 for: Profiles + OAuth, Profiles + OAuth Bucket Failover, Profiles + Load Balancers, Profiles + Subagents, and general workflow setup patterns.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: acoliver
Repo: vybestack/llxprt-code PR: 0
File: :0-0
Timestamp: 2025-12-13T16:04:07.079Z
Learning: Support multi-bucket failover on a single profile: ordered buckets tried in sequence; on 429 or 402 advance to next bucket; on 401 attempt auto-renew then retry once before advancing.

@acoliver
Copy link
Collaborator

acoliver commented Jan 9, 2026

closing for now (feel free to reopen if we come up with a workflow for this)

@acoliver acoliver closed this Jan 9, 2026
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