feat: improve config provider TUI interaction#213
Conversation
- Support wrap-around navigation in provider, custom provider, and model lists (up at first item jumps to last, down at last item jumps to first) - Add d key to delete custom models in model selection step with confirmation prompt - Add protocol selection (anthropic/openai) to manual configuration flow and respect UseAnthropic setting in saved config - Preserve manual protocol selection when re-entering the form - Fix manual form input fields losing focus after returning from next step - Use safe slice removal in removeFromSlice to avoid backing array corruption
| m.manualStep = manualStepProtocol | ||
| return m, nil | ||
| case manualStepProtocol: | ||
| m.manualStep = manualStepModel | ||
| return m, m.manualModelInput.Focus() |
There was a problem hiding this comment.
Bug: When transitioning from manualStepURL to manualStepProtocol, the URL input is never blurred. The old code called m.manualURLInput.Blur() before advancing, but this was removed. Since the protocol step has no input widget and focusManualStep() returns nil for it, the URL text input retains focus state. This can cause visual artifacts (e.g., cursor still blinking in the URL field) while the protocol selector is displayed.
Similarly, the transition from manualStepModel to manualStepAuthToken also lost its m.manualModelInput.Blur() call.
You should blur the current step's input before advancing to the next step.
Suggestion:
| m.manualStep = manualStepProtocol | |
| return m, nil | |
| case manualStepProtocol: | |
| m.manualStep = manualStepModel | |
| return m, m.manualModelInput.Focus() | |
| m.manualURLInput.Blur() | |
| m.manualStep = manualStepProtocol | |
| return m, nil | |
| case manualStepProtocol: | |
| m.manualStep = manualStepModel | |
| return m, m.manualModelInput.Focus() |
| m.manualStep = manualStepAuthToken | ||
| return m, m.manualTokenInput.Focus() |
There was a problem hiding this comment.
Same issue: the model input should be blurred before transitioning to the auth token step, otherwise the model input may retain visual focus artifacts.
Suggestion:
| m.manualStep = manualStepAuthToken | |
| return m, m.manualTokenInput.Focus() | |
| m.manualModelInput.Blur() | |
| m.manualStep = manualStepAuthToken | |
| return m, m.manualTokenInput.Focus() |
| } else { | ||
| m.officialIdx = len(m.providers) - 1 | ||
| } |
There was a problem hiding this comment.
Potential issue: If len(m.providers) is 0 (e.g., llm.ListProviders() returns empty), then len(m.providers) - 1 evaluates to -1, setting officialIdx to an invalid negative index. While unlikely in practice, adding a guard would make this more robust. The same applies to customListCount() and modelCount() which always return at least 1 due to the +1 sentinel item, so those are safe.
Suggestion:
| } else { | |
| m.officialIdx = len(m.providers) - 1 | |
| } | |
| } else if len(m.providers) > 0 { | |
| m.officialIdx = len(m.providers) - 1 | |
| } |
| for i, proto := range cpProtocols { | ||
| cur := " " | ||
| if i == m.manualProtocolIdx { | ||
| cur = " " + tuiCursorStyle.Render(tuiCursor) + " " | ||
| } | ||
| if i == m.manualProtocolIdx { | ||
| s.WriteString(cur + tuiSelectedItemStyle.Render(proto) + "\n") | ||
| } else { | ||
| s.WriteString(cur + tuiItemStyle.Render(proto) + "\n") | ||
| } | ||
| } |
There was a problem hiding this comment.
Minor readability issue: The condition i == m.manualProtocolIdx is checked twice in succession — once to set the cursor prefix and again to choose the rendering style. These can be consolidated into a single if/else block for clarity.
Suggestion:
| for i, proto := range cpProtocols { | |
| cur := " " | |
| if i == m.manualProtocolIdx { | |
| cur = " " + tuiCursorStyle.Render(tuiCursor) + " " | |
| } | |
| if i == m.manualProtocolIdx { | |
| s.WriteString(cur + tuiSelectedItemStyle.Render(proto) + "\n") | |
| } else { | |
| s.WriteString(cur + tuiItemStyle.Render(proto) + "\n") | |
| } | |
| } | |
| for i, proto := range cpProtocols { | |
| if i == m.manualProtocolIdx { | |
| cur := " " + tuiCursorStyle.Render(tuiCursor) + " " | |
| s.WriteString(cur + tuiSelectedItemStyle.Render(proto) + "\n") | |
| } else { | |
| s.WriteString(" " + tuiItemStyle.Render(proto) + "\n") | |
| } | |
| } |
- Restore Blur() calls in handleManualFormEnter to prevent visual focus artifacts when transitioning between manual form steps - Add empty-providers guard in handleUp/handleDown to avoid negative index - Consolidate redundant protocolIdx checks into single if/else in viewManualTab and viewCustomProviderForm for clarity
…ting - Track deleted custom models in TUI and apply them on exit (both confirm and cancel paths) to keep config.json in sync - Clear custom provider's active Model field when that model is deleted, preventing stale "model" reference in the provider list label - Add masked display for manual config Auth Token to allow easy re-entry, matching the official provider flow (any key clears and starts fresh)
Update TestProviderTUI_ManualFormPrefilledValues, TestProviderTUI_ManualFormEscRestoresOriginalValues, and TestProviderTUI_ManualFormPrefilledWhenProviderSet to assert the new masked display state (manualTokenMasked + manualTokenOriginal) instead of the raw token value.
Custom provider interactions: - Simplify create/edit form to Name → Protocol → URL → API Key → Auth Header - After create or edit save, jump straight into the model list for that provider - Support comma-separated model names in the custom model input - Show masked API key in edit form; empty Auth Header defaults to (Authorization) - Populate edit form from existingCfg to avoid stale list data after in-session saves Model selection and highlight: - Green highlight follows the persisted active model, not the cursor position - Prefer provider entry.model over global cfg.model when resolving active model - Deleting a non-active model keeps the current green highlight unchanged Delete and navigation: - Delete custom providers (d) and custom models (d) with confirmation prompts - Persist create/edit/model-select/add/delete changes to disk during the session - Fix custom provider deletion not surviving Esc exe-entry Tests: - Add coverage for model highlight, delete-model behavior, and create→model-list flow - Update manual/custom form tests for masked token and session save behavior
Code Review FindingsHi! I spotted a few things while reviewing — please take a look and let me know if you agree they're worth addressing. 1. Indentation / brace alignment in
|
- Remove dead helper removeFromSlice (superseded by removeModels) - Move misplaced doc comment to applyEditCustomProviderSave - Drop redundant applyProviderDeletions post-TUI call so provider deletions rely solely on the in-session save - Fix brace/indent drift in updateDeleteModelConfirm and cache the model list instead of recomputing m.models() twice
Description
Type of Change
How Has This Been Tested?
make testpasses locallyChecklist
go fmt,go vet)Related Issues