feat(ui): manage visible provider models - #637
Conversation
Extend the provider settings screen with searchable, virtualized per-provider model visibility controls so large plugin catalogs can be reduced to the models users actually need. Persist exact model allowlists as CodeNomad UI preferences without rewriting OpenCode configuration. Serialize optimistic preference updates across manager remounts, retain unavailable selections, respect visibility during default selection, and keep active session models usable. Add localized UI and failure states for every supported locale, pure normalization/filtering coverage, and the regression test to PR CI. Typecheck, the changed-behavior suite, browser-condition tests, and the production UI build pass.
Keep the floating provider manager focused on quick connection and refresh actions. Expose the large-catalog visibility workflow only from the embedded Providers settings section, where the virtualized management view has sufficient context and space.
|
PR builds are available as GitHub Actions artifacts: https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/31010099081 Artifacts expire in 7 days.
|
Replace the virtualized allowlist workflow with a plain searchable checkbox list inspired by OpenChamber and OpenCode Desktop. Users can show or hide all models, while new provider models remain visible by default. Treat hiding as presentation state only: hidden models no longer affect defaults, execution, prompts, or commands, and an active hidden model remains usable. Persist exact hidden model IDs with the existing serialized optimistic writer. Update every locale and focused tests for hidden-model semantics. Root typecheck, targeted tests, production UI build, diff checks, and two Gatekeeper reviews pass.
|
PR builds for commit TauriElectronArtifacts expire on August 14, 2026. |
Expose the existing model visibility manager from both the embedded provider settings and the floating provider dialog. This keeps model hiding accessible from the model picker without duplicating state or UI logic. Validated with workspace typechecking, the focused model visibility tests, and the UI production build.
pascalandr
left a comment
There was a problem hiding this comment.
Gatekeeper review — FAIL
Reviewed current head de7e7a11e46cc878aded3841d3e1450dd60ecfb1 against dev.
Findings
- High — blocking: The new provider Refresh path calls
global.dispose()before reloading providers (provider-manager-modal.tsx:366-374). An ordinary refresh can dispose OpenCode runtime instances and interrupt active work. - Medium: A hidden active model remains the controlled Combobox value but is absent from its options (
model-selector.tsx:83-88, 118-121, 158-162, 290-302), risking inconsistent keyboard/screen-reader state. - Medium: Model-visibility persistence can appear successful when the server cannot write the YAML file because server write errors are logged but not returned (
preferences.tsx:653-696;yaml-doc-store.ts:101-108). - Low — test gap: Pure visibility helpers are covered, but not the serialized writer, hidden-current Combobox integration, bulk actions, or floating-dialog focus restoration.
Validation
- Focused model-visibility tests: 5 passed
- UI typecheck: passed
- UI production build: passed
git diff --check: passed- i18n keys present in all nine locales
Gatekeeper should be rerun after the blocking refresh behavior is corrected.
|
PR builds are available as GitHub Actions artifacts: https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/31197511650 Artifacts expire in 7 days.
|
1 similar comment
|
PR builds are available as GitHub Actions artifacts: https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/31197511650 Artifacts expire in 7 days.
|
Refresh provider metadata without disposing active OpenCode instances. Keep the Combobox selection aligned with its visible collection while preserving an accessible current-model label when that model is hidden. Propagate YAML persistence failures and roll back the in-memory document so model visibility does not appear saved when disk writes fail. Add a focused regression test for the write-failure boundary. Validated with UI, Electron, and server typechecks; focused visibility and YAML-store tests; the UI production build; and the server suite apart from an unrelated local default-branch assertion in git-worktrees.test.ts.
Refresh both the shared provider catalog and modal-local provider details without disposing active OpenCode instances. Add collection-safe picker selection coverage and source-level contracts for the refresh and accessibility wiring. Limit strict YAML persistence errors to SettingsService stores and make sidecar create, update, and delete operations roll back their runtime state when persistence fails. Add focused rollback coverage for those operations. Validated with UI, Electron, and server typechecks; ten focused regression tests; the UI production build; and git diff checks.
Apply config merge patches in memory, normalize the result, and persist it once. This prevents a failed normalization write from leaving an earlier intermediate write on disk while callers roll back runtime state. Add focused tests that fail if document or server-owner patches perform an intermediate persistence operation.
Write YAML updates to a same-directory temporary file and rename it over the live document. Failed writes or replacements now leave the prior on-disk and cached settings intact. Treat settings-change events as post-commit notifications so listener errors are logged without making a successful persisted request look failed. Add regression coverage for failed replacement, successful Windows replacement, and listener exceptions.
Serialize model visibility writes across providers so full server snapshots cannot resolve out of order. Include provider and exact model identifiers in the localized accessible picker label. Preserve existing settings-file permissions during atomic replacement, create new settings files privately, and update symlink targets without replacing the links. Add POSIX regression coverage for permissions and symlinks plus UI wiring checks. Validated with workspace and server typechecks, focused persistence and visibility tests, the UI production build, and git diff checks.
Resolve complete symlink chains before atomic replacement and apply the original mode after temporary-file creation so umask cannot silently change existing permissions. Expand POSIX coverage to assert exact nontrivial mode preservation and multi-hop symlink retention.
pascalandr
left a comment
There was a problem hiding this comment.
Gatekeeper re-review — PASS
Reviewed current head 19e5d1318b393f26e390955a4975945bbacdc8c0 against dev.
No actionable PR-caused findings remain.
Verified
- provider Refresh updates shared and modal catalogs without disposing active OpenCode instances
- hidden active models remain usable with collection-safe and provider/ID-aware accessible picker state
- visibility writes are serialized across providers
- settings persistence is single-write and atomic, with rollback, exact mode preservation, private new files, and symlink-chain retention
- SideCar runtime state rolls back on persistence failure; post-commit listener errors are contained
- all nine locales include the accessible label
Validation
- focused regression tests: 15 passed; 2 POSIX-only tests skipped on Windows
- UI, Electron, and server typechecks: passed
- UI production build: passed
git diff --check: passed
|
PR builds are available as GitHub Actions artifacts: https://github.com/NeuralNomadsAI/CodeNomad/actions/runs/31214225371 Artifacts expire in 7 days.
|
Give configured-provider cards enough responsive width for their model-management and disconnect actions, and keep button labels on one line. This avoids the narrow vertical text shown in the provider authentication dialog while retaining a single-column layout on small screens. Validated with the UI production build and git diff --check.
|
@shantur LGTM |
Summary
Behavior
This intentionally mirrors OpenChamber/OpenCode Desktop client-side hiding. It does not rewrite OpenCode configuration or change model execution/default semantics.
Validation
Closes #636