Skip to content

fix(provider-wizard): allow multiple custom OpenAI-compatible providers#389

Open
KunjShah95 wants to merge 3 commits into
Gitlawb:mainfrom
KunjShah95:fix/multiple-custom-openai-providers
Open

fix(provider-wizard): allow multiple custom OpenAI-compatible providers#389
KunjShah95 wants to merge 3 commits into
Gitlawb:mainfrom
KunjShah95:fix/multiple-custom-openai-providers

Conversation

@KunjShah95

@KunjShah95 KunjShah95 commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Fixes #375

Problem: \wizardProviderStoredKey\ matched saved providers by CatalogID. Since ALL custom OpenAI-compatible providers share CatalogID \custom-openai-compatible, setting up one blocked configuring a second.

Fix:

  1. Skip CatalogID matching for generic/custom providers (they all share the same ID)
  2. When replacing a key for a generic provider, route through endpoint/name steps so the user enters a new base URL and name

Summary by CodeRabbit

  • Bug Fixes
    • Improved saved provider matching to better handle generic/custom OpenAI-compatible provider IDs, reducing incorrect keep/replace/remove prompts.
    • Updated the “Replace” flow to clear additional connection details and route to the correct next step (endpoint vs. credentials) based on the provider’s needs.
  • Tests
    • Extended OAuth login timing tolerances and added coverage for the generic OpenAI-compatible replace routing behavior.

Copilot AI review requested due to automatic review settings July 2, 2026 12:59

Copilot AI 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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Provider wizard saved-key matching now skips CatalogID checks for generic provider IDs, and the Replace action clears more state before routing to the next wizard step. MCP OAuth login tests also allow longer time for callback and completion.

Changes

Provider Wizard Fix

Layer / File(s) Summary
Stored key matching and replace routing
internal/tui/provider_wizard.go
CatalogID matching is skipped for generic provider IDs, and the Replace path clears baseURL and profileName before routing to the endpoint step when needed or the credential step otherwise.
Generic replace path test
internal/tui/provider_wizard_test.go
Adds coverage for replacing a generic OpenAI-compatible provider and advancing the wizard to the endpoint step.

MCP OAuth Login Test Timing

Layer / File(s) Summary
Login timeout adjustments
internal/cli/mcp_oauth_test.go
Extends the callback polling deadline and the overall completion timeout in the login-token test.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • Gitlawb/zero#161: Related provider wizard onboarding work in the same TUI flow and saved-key handling area.

Suggested reviewers: anandh8x, Vasanthdev2004

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The MCP OAuth test timeout changes are unrelated to the provider-wizard issue and appear out of scope. Move the MCP OAuth test timeout adjustment to a separate PR unless it is required for this issue.
✅ 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 clearly matches the main change: enabling multiple custom OpenAI-compatible providers.
Linked Issues check ✅ Passed The provider-wizard changes and tests address #375 by skipping generic CatalogID matching and allowing a second custom provider setup.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ 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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/tui/provider_wizard.go (1)

939-952: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add coverage for the Replace → endpoint path

TestProviderWizardManageKeyReplaceAndKeep still only hits the credential-step branch because the test builds providerWizardState without providers, so currentProvider() is zero-value and providerWizardNeedsEndpoint(...) stays false. Add a case with a custom-openai-compatible or custom-anthropic-compatible provider so Replace exercises the new endpoint routing too.

🤖 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 `@internal/tui/provider_wizard.go` around lines 939 - 952, Add test coverage
for the Replace flow’s endpoint-routing path in the provider wizard. Update
TestProviderWizardManageKeyReplaceAndKeep so it doesn’t only exercise the
credential-step branch: build providerWizardState with a real provider entry so
currentProvider() is populated and providerWizardNeedsEndpoint(...) can become
true. Add a Replace case using a custom-openai-compatible or
custom-anthropic-compatible provider and assert wizardProviderStoredKey/current
provider handling covers the endpoint path too.
🤖 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 `@internal/tui/provider_wizard.go`:
- Around line 964-974: The Replace branch in providerWizardUpdate now routes to
providerWizardStepEndpoint when providerWizardNeedsEndpoint(currentProvider())
is true, but the existing TestProviderWizardManageKeyReplaceAndKeep never sets
wizard.providers so currentProvider() stays zero-value and only the
credential-step path is covered. Update
TestProviderWizardManageKeyReplaceAndKeep in provider_wizard_test.go, or add a
dedicated case, to populate wizard.providers with a custom-openai-compatible
descriptor and assert that the Replace flow reaches providerWizardStepEndpoint
instead of only providerWizardStepCredential.

---

Outside diff comments:
In `@internal/tui/provider_wizard.go`:
- Around line 939-952: Add test coverage for the Replace flow’s endpoint-routing
path in the provider wizard. Update TestProviderWizardManageKeyReplaceAndKeep so
it doesn’t only exercise the credential-step branch: build providerWizardState
with a real provider entry so currentProvider() is populated and
providerWizardNeedsEndpoint(...) can become true. Add a Replace case using a
custom-openai-compatible or custom-anthropic-compatible provider and assert
wizardProviderStoredKey/current provider handling covers the endpoint path too.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2547d457-edd5-4768-a06b-40c8caf72953

📥 Commits

Reviewing files that changed from the base of the PR and between 39e7100 and 7f681d9.

📒 Files selected for processing (1)
  • internal/tui/provider_wizard.go

Comment on lines 964 to 974
case 1: // Replace
wizard.apiKey = ""
wizard.err = ""
wizard.step = providerWizardStepCredential
wizard.baseURL = ""
wizard.profileName = ""
if providerWizardNeedsEndpoint(wizard.currentProvider()) {
wizard.step = providerWizardStepEndpoint
} else {
wizard.step = providerWizardStepCredential
}
return m, nil

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Add test coverage for the new endpoint-step routing.

The Replace branch's conditional routing to providerWizardStepEndpoint (Lines 969-970) is the core fix enabling users to enter a new base URL for a second custom provider, but TestProviderWizardManageKeyReplaceAndKeep in provider_wizard_test.go (context snippet 4) never populates wizard.providers, so currentProvider() returns a zero-value descriptor and providerWizardNeedsEndpoint always evaluates to false there — only the else credential-step path is exercised. The behavior this PR is meant to add is currently unverified by tests.

Consider extending the test (or adding a new case) with wizard.providers set to a custom-openai-compatible-ID descriptor so the Replace path to providerWizardStepEndpoint is asserted.

🤖 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 `@internal/tui/provider_wizard.go` around lines 964 - 974, The Replace branch
in providerWizardUpdate now routes to providerWizardStepEndpoint when
providerWizardNeedsEndpoint(currentProvider()) is true, but the existing
TestProviderWizardManageKeyReplaceAndKeep never sets wizard.providers so
currentProvider() stays zero-value and only the credential-step path is covered.
Update TestProviderWizardManageKeyReplaceAndKeep in provider_wizard_test.go, or
add a dedicated case, to populate wizard.providers with a
custom-openai-compatible descriptor and assert that the Replace flow reaches
providerWizardStepEndpoint instead of only providerWizardStepCredential.

@Vasanthdev2004

Copy link
Copy Markdown
Collaborator

fix coderabbit issues @KunjShah95

@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.

🧹 Nitpick comments (1)
internal/tui/provider_wizard_test.go (1)

1170-1189: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Strengthen test to also verify state-clearing on Replace.

Test only checks the step transition to providerWizardStepEndpoint, but the underlying fix (per PR summary) is that Replace now clears apiKey, baseURL, profileName, and err before routing. Pre-seeding those fields with stale values and asserting they're cleared would directly cover the behavior this fix targets — without it, a regression that stops clearing state (letting a second provider inherit the first provider's baseURL) would slip through undetected.

♻️ Suggested strengthening
 	m.providerWizard = &providerWizardState{
 		step:               providerWizardStepManageKey,
 		manageProviderName: "my-custom-openai",
 		manageKeyCursor:    1,
+		apiKey:             "stale-key",
+		baseURL:            "https://stale.example.com",
+		profileName:        "stale-profile",
+		err:                "stale error",
 		providers: []providercatalog.Descriptor{
 			{
 				ID:        "custom-openai-compatible",
 				Transport: providercatalog.TransportOpenAICompatible,
 			},
 		},
 		selectedProvider: 0,
 	}
 	next, _ := m.applyManageKeyChoice()
 	if next.providerWizard == nil || next.providerWizard.step != providerWizardStepEndpoint {
 		t.Fatalf("replace for generic provider should route to the endpoint step, got step: %v", next.providerWizard.step)
 	}
+	if next.providerWizard.apiKey != "" || next.providerWizard.baseURL != "" || next.providerWizard.profileName != "" || next.providerWizard.err != "" {
+		t.Fatal("replace should clear stale apiKey/baseURL/profileName/err before routing")
+	}
 }
🤖 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 `@internal/tui/provider_wizard_test.go` around lines 1170 - 1189, Strengthen
TestProviderWizardManageKeyReplaceGeneric to cover the Replace state-reset
behavior in applyManageKeyChoice, not just the providerWizardStepEndpoint
transition. Pre-seed providerWizardState fields like apiKey, baseURL,
profileName, and err with stale values before calling applyManageKeyChoice, then
assert those fields are cleared in the returned state when manageKeyCursor
selects Replace. Use the existing providerWizardState,
providerWizardStepManageKey, and providerWizardStepEndpoint symbols to locate
the test and verify the generic-provider Replace path.
🤖 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.

Nitpick comments:
In `@internal/tui/provider_wizard_test.go`:
- Around line 1170-1189: Strengthen TestProviderWizardManageKeyReplaceGeneric to
cover the Replace state-reset behavior in applyManageKeyChoice, not just the
providerWizardStepEndpoint transition. Pre-seed providerWizardState fields like
apiKey, baseURL, profileName, and err with stale values before calling
applyManageKeyChoice, then assert those fields are cleared in the returned state
when manageKeyCursor selects Replace. Use the existing providerWizardState,
providerWizardStepManageKey, and providerWizardStepEndpoint symbols to locate
the test and verify the generic-provider Replace path.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7ef1c56c-41c5-4e0b-9db9-989d6326ebc7

📥 Commits

Reviewing files that changed from the base of the PR and between 7f681d9 and 74d61e0.

📒 Files selected for processing (2)
  • internal/cli/mcp_oauth_test.go
  • internal/tui/provider_wizard_test.go

@KunjShah95

Copy link
Copy Markdown
Contributor Author

@Vasanthdev2004

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.

Not able to setup multiple openai comp providers

3 participants