Skip to content

feat(tui): add search/filter to provider picker in setup wizard#400

Open
Ashwinhegde19 wants to merge 2 commits into
Gitlawb:mainfrom
Ashwinhegde19:feat/provider-search-filter
Open

feat(tui): add search/filter to provider picker in setup wizard#400
Ashwinhegde19 wants to merge 2 commits into
Gitlawb:mainfrom
Ashwinhegde19:feat/provider-search-filter

Conversation

@Ashwinhegde19

@Ashwinhegde19 Ashwinhegde19 commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add a search input to the provider step of the setup wizard
  • Filters providers in real-time via case-insensitive substring matching on name, ID, and aliases
  • Consistent with the existing model picker search UX (/model command)

Changes

  • internal/tui/provider_wizard.go: 92 additions, 6 deletions

What changed

  • Added providerSearch field to providerWizardState struct
  • Added appendProviderSearch(), deleteProviderSearchRune(), filteredProviders(), providerMatchesQuery() methods
  • Updated renderProviderStep() to show search input and render filtered results
  • Updated currentProvider() to use filtered list when on provider step
  • Updated move() to navigate within filtered results
  • Added key handling: printable chars → search, backspace → delete, Ctrl+U → clear
  • Added paste support for provider search
  • Search is cleared when advancing/retreating from provider step

Motivation

With 28+ providers now in the catalog, scrolling through the full list is tedious. The model picker already has search — this brings the same UX to the provider picker.

Testing

  • go build ./... passes
  • go test ./internal/tui/... passes
  • go vet ./internal/tui/... passes

Fixes #392

Summary by CodeRabbit

  • New Features

    • Added provider search and filtering in the setup wizard.
    • The provider step now shows a search field and updates results as you type.
  • Bug Fixes

    • Improved navigation so selection stays in sync with the filtered provider list.
    • Clear feedback now appears when no providers match the search.
  • Chores

    • Search input supports backspace, delete, paste, and quick clearing with Ctrl+u.

Add a search input to the provider step of the setup wizard, matching
the existing model picker search UX. Typing filters the provider list
in real-time via case-insensitive substring matching on name, ID, and
aliases.

Fixes Gitlawb#392
Copilot AI review requested due to automatic review settings July 2, 2026 16: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.

Pull request overview

This PR adds an interactive search/filter input to the provider selection step in the TUI setup wizard, bringing the provider picker UX in line with the existing model picker search behavior.

Changes:

  • Adds providerSearch state plus helper methods for updating and filtering the provider list.
  • Updates provider-step rendering and navigation to operate on the filtered provider list and display a search input.
  • Adds key and paste handling for provider search (printable chars, backspace, Ctrl+U), and clears search when leaving/entering the provider step.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 463 to 467
if wizard.oauthMode {
return
}
wizard.providerSearch = ""
wizard.refreshModels()
Comment on lines +1349 to +1352
func (wizard *providerWizardState) renderProviderSearch(width int) string {
query := strings.TrimSpace(wizard.providerSearch)
return providerWizardInputLine("search > ", query, "provider name...", width)
}
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fc34b06c-bff4-404a-9342-d55e955b4442

📥 Commits

Reviewing files that changed from the base of the PR and between 9c27412 and 236195b.

📒 Files selected for processing (1)
  • internal/tui/provider_wizard.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/tui/provider_wizard.go

Walkthrough

The provider setup wizard now filters the provider-selection step with a search query. It tracks the query in state, filters by provider ID/name/aliases, updates selection and step transitions around the filtered list, and renders the search line plus filtered or empty results.

Changes

Provider search/filter feature

Layer / File(s) Summary
Search state and filtering utilities
internal/tui/provider_wizard.go
Adds providerSearch state and helper functions to mutate the query and filter providers by ID, name, and aliases.
Navigation and selection against filtered list
internal/tui/provider_wizard.go
currentProvider() and move() use the filtered provider list, and step transitions clear providerSearch when leaving the provider step.
Keyboard and paste input handling
internal/tui/provider_wizard.go
Typed characters, backspace, Ctrl+u, and pasted text are routed into providerSearch on the provider step.
Search input and filtered rows
internal/tui/provider_wizard.go
renderProviderStep() shows the search line, renders the filtered provider rows, and displays the empty-state when no providers match.

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

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant providerWizard as providerWizardState
  participant filteredProviders as filteredProviders()
  participant renderProviderStep as renderProviderStep()

  User->>providerWizard: type, paste, or press arrow keys
  providerWizard->>providerWizard: update providerSearch / selectedProvider
  providerWizard->>filteredProviders: compute matching providers
  providerWizard->>renderProviderStep: redraw provider step
  renderProviderStep->>filteredProviders: read filtered list
  renderProviderStep->>User: show search input, matches, or empty-state
Loading

Possibly related PRs

  • Gitlawb/zero#161: Earlier provider-wizard work in the same area of internal/tui/provider_wizard.go; this PR extends the provider-selection flow with search/filtering.
  • Suggested reviewers: Vasanthdev2004
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 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 change: adding search/filter to the provider picker in the setup wizard.
Linked Issues check ✅ Passed The PR implements the requested real-time provider search, clear filter UI, backspace editing, and filtered arrow-key navigation for #392.
Out of Scope Changes check ✅ Passed The changes stay focused on the provider picker search/filter UX in internal/tui/provider_wizard.go and do not add unrelated scope.
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.

Caution

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

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

639-659: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

OAuth "d" device-login shortcut swallows the letter "d" in search.

When oauthMode is true and the currently selected (filtered) provider has OAuthDeviceFlow, pressing "d"/"D" always triggers startProviderDeviceLogin() (lines 641-645) before falling through to the search-typing handler added at Line 648. This makes it impossible to type "d" into the provider search box in that state — e.g. searching for a provider whose name contains "d" while an unrelated device-capable provider is currently selected.

Consider gating the shortcut behind an explicit modifier (e.g. Ctrl+D) or only intercepting it when providerSearch is empty, so typed search text always wins once the user starts typing.

🤖 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 639 - 659, The provider wizard
key handler in provider_wizard.go is intercepting plain “d”/“D” before the
search input logic, so typing into the provider search can accidentally start
device login. Update the key handling in the providerWizardStepProvider branch
so the device-login shortcut in startProviderDeviceLogin only triggers with an
explicit modifier or when providerSearch is empty, and let the
appendProviderSearch path win for normal typed characters. Keep the change
localized around the existing oauthMode/currentProvider().OAuthDeviceFlow check
and the search-handling switch.

460-476: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

providerSearch not cleared on retreat back to the Method step.

advance() clears providerSearch only when moving forward off the Provider step (line 466). retreat()'s providerWizardStepProvider case (transitioning back to Method) doesn't clear it, while the providerWizardStepEndpoint case redundantly clears it again on the way back to Provider (it's already empty there since advance() cleared it). Net effect: search text typed on the Provider step survives a Left/Esc-back-to-Method → forward-again round trip, silently filtering the list on re-entry, which contradicts the PR's stated intent to clear search "when leaving the provider step."

🐛 Proposed fix
 	case providerWizardStepProvider:
 		wizard.oauthMode = false
 		wizard.oauthErr = ""
+		wizard.providerSearch = ""
 		wizard.step = providerWizardStepMethod

Also applies to: 518-552

🤖 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 460 - 476, The provider search
text is only being cleared in advance() when leaving providerWizardStepProvider,
so it can survive a retreat() back to the Method step and unexpectedly filter
the list on re-entry. Update the retreat() handling for
providerWizardStepProvider in internal/tui/provider_wizard.go to mirror the
forward path by clearing providerSearch (and keeping the existing refresh/reset
behavior consistent), and remove any redundant clearing from the
providerWizardStepEndpoint backtrack path so providerSearch is reset exactly
when leaving the Provider step.
🧹 Nitpick comments (1)
internal/tui/provider_wizard.go (1)

913-956: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider unit tests for the new filtering helpers.

filteredProviders/providerMatchesQuery are pure and easy to test (ID/name/alias matching, case-insensitivity, empty query, no-match case). No test changes are visible in this diff for them.

🤖 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 913 - 956, Add unit tests for
the new filtering helpers in providerWizardState: cover filteredProviders and
providerMatchesQuery with empty query returning all providers, case-insensitive
matching against ID/name/aliases, and a no-match case. Use the existing symbols
providerMatchesQuery and filteredProviders to locate the logic, and keep the
tests focused on the pure behavior without changing unrelated wizard flow.
🤖 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.

Outside diff comments:
In `@internal/tui/provider_wizard.go`:
- Around line 639-659: The provider wizard key handler in provider_wizard.go is
intercepting plain “d”/“D” before the search input logic, so typing into the
provider search can accidentally start device login. Update the key handling in
the providerWizardStepProvider branch so the device-login shortcut in
startProviderDeviceLogin only triggers with an explicit modifier or when
providerSearch is empty, and let the appendProviderSearch path win for normal
typed characters. Keep the change localized around the existing
oauthMode/currentProvider().OAuthDeviceFlow check and the search-handling
switch.
- Around line 460-476: The provider search text is only being cleared in
advance() when leaving providerWizardStepProvider, so it can survive a retreat()
back to the Method step and unexpectedly filter the list on re-entry. Update the
retreat() handling for providerWizardStepProvider in
internal/tui/provider_wizard.go to mirror the forward path by clearing
providerSearch (and keeping the existing refresh/reset behavior consistent), and
remove any redundant clearing from the providerWizardStepEndpoint backtrack path
so providerSearch is reset exactly when leaving the Provider step.

---

Nitpick comments:
In `@internal/tui/provider_wizard.go`:
- Around line 913-956: Add unit tests for the new filtering helpers in
providerWizardState: cover filteredProviders and providerMatchesQuery with empty
query returning all providers, case-insensitive matching against
ID/name/aliases, and a no-match case. Use the existing symbols
providerMatchesQuery and filteredProviders to locate the logic, and keep the
tests focused on the pure behavior without changing unrelated wizard flow.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fea8c6cc-9e1b-4def-8d3d-936e0ca27aff

📥 Commits

Reviewing files that changed from the base of the PR and between cdf9d83 and 9c27412.

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

Clearing providerSearch before using currentProvider() caused the wrong
provider to be selected — selectedProvider is an index into the filtered
slice, and clearing the search swaps to the full unfiltered list.

Also update placeholder to reflect that search matches ID and aliases.

@Vasanthdev2004 Vasanthdev2004 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Verdict: Request changes — the core is right, but there's one confirmed edge bug and no tests

Good feature, and the hard part is done correctly: advance() remaps the filtered selection index back to the full-list index before clearing the search, so selection is preserved across the filtered→full swap. I verified the happy path locally — filtering anthropic then pressing Enter advances with anthropic (remapped to full index 2), and the existing wizard tests still pass. gofmt/vet clean.

Two things to fix before merge.

🔴 Confirmed bug: Enter on an empty match advances with the wrong provider

Type a query that matches nothing → the list shows no matching providers → press Enter, and the wizard advances off the provider step selecting gitlawb-opengateway (the first full-list provider), not what the user intended. I reproduced it:

after Enter on empty match: step=Endpoint selectedProvider=0 provider="gitlawb-opengateway"

Root cause: in advance()'s providerWizardStepProvider case, when currentProvider() returns the empty descriptor (no match), the remap is skipped, providerSearch is cleared, and currentProvider() then falls back to full-list [selectedProvider] which the last keystroke reset to 0. Enter isn't caught by the search key-switch, so it reaches advance().

Fix: guard the empty case at the top of that advance() branch (right after the oauthMode return):

if len(wizard.filteredProviders()) == 0 {
    return // nothing selectable; Enter is a no-op on an empty filter
}

🟡 No tests for the filter/index logic

The PR changes only provider_wizard.go — no tests. This is exactly the fragile index-mapping surface that PR #402 just had to refactor the wizard tests around, so it needs coverage. Please add table/unit tests for:

  • filtering narrows the list (filteredProviders() / providerMatchesQuery on name, id, alias, case-insensitive),
  • selecting a filtered provider advances to that exact provider (the remap — e.g. filter to a mid/late provider, Enter, assert currentProvider().ID),
  • empty match + Enter is a no-op (guards the bug above — red-green),
  • clearing the search (Ctrl+U / backspace to empty) restores the full list with the selection consistent.

These are pure providerWizardState unit tests — no full TUI run needed (see the probes I used above).

Nit

appendProviderSearch/deleteProviderSearchRune reset selectedProvider = 0 on every edit (good — avoids a stale index past a narrowed filter); just make sure the new tests lock that in so a future refactor can't regress it.

Once the empty-Enter guard and tests are in, this is a clean, welcome UX win. Thanks @Ashwinhegde19!

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.

feat(tui): add search/filter to provider picker in setup wizard

3 participants