Agent management - add select all/none checkbox#250
Conversation
- Add setAllProvidersEnabled() domain function for bulk provider enable/disable - Add SET_ALL_PROVIDERS_ENABLED action to state reducer - Wire up select-all checkbox in ProvidersTab header - Update Checkbox component to support indeterminate state - Checkbox operates on filtered providers only for performance - Tri-state: checked (all), unchecked (none), indeterminate (some)
…r-manager-select-all
Add checkbox to select or deselect all models at once in the Models tab. Implement sentinel value pattern to distinguish between "all models allowed" (empty list) and "no models allowed" (sentinel value). Add validation to prevent saving with zero models selected. - Add select all checkbox with indeterminate state support - Implement MODEL_ALLOW_NONE_SENTINEL for explicit empty selection - Disable save button and show error when no models selected - Add sanitization layer to remove sentinel before persistence - Add comprehensive test coverage for new selection logic
…odel lists Change the "select all models" checkbox to operate on the currently filtered/visible models instead of all models globally. The checkbox now: - Reflects the selection state of only the filtered models - Allows selecting/deselecting all visible models when filters are active - Properly merges selections when working with filtered subsets - Maintains correct indeterminate state based on filtered results Updated the setAllModelsAllowed function to accept targetModelIds parameter, enabling granular control over which models are affected by bulk operations. Added comprehensive test coverage for filtered subset operations.
| <Checkbox | ||
| checked={allSelected} | ||
| indeterminate={selectAllIndeterminate} | ||
| disabled={!canEdit} |
There was a problem hiding this comment.
SUGGESTION: Disable “select all” when there are zero models
If totalModelCount is 0 (e.g. empty dataset or failed load that still renders), clicking this checkbox could dispatch a state change with an empty allModelIds, which is surprising UX.
| disabled={!canEdit} | |
| disabled={!canEdit || totalModelCount === 0} |
| export function sanitizeModelAllowListForPersistence( | ||
| modelAllowList: ReadonlyArray<string> | ||
| ): string[] { | ||
| return modelAllowList.filter(entry => entry !== MODEL_ALLOW_NONE_SENTINEL); |
There was a problem hiding this comment.
WARNING: sanitizeModelAllowListForPersistence() can flip "none allowed" into "all allowed"
If modelAllowList is [MODEL_ALLOW_NONE_SENTINEL], this returns [], but elsewhere [] is treated as "all models allowed" (see computeAllowedModelIds()). If persisting "no models allowed" isn’t a supported backend state, consider making sanitizeModelAllowListForPersistence() explicitly reject the sentinel (or encoding it in a way the backend understands) rather than silently converting it.
| return !targetSet.has(providerSlug); | ||
| }); | ||
| } | ||
| nextModelAllowList = canonicalizeModelAllowList(nextModelAllowList); |
There was a problem hiding this comment.
WARNING: MODEL_ALLOW_NONE_SENTINEL may be normalized away by canonicalizeModelAllowList()
draftModelAllowList can become [MODEL_ALLOW_NONE_SENTINEL] (e.g. via setAllModelsAllowed()). Passing that through canonicalizeModelAllowList() will call normalizeModelId() on '__none__', so sentinel checks like draftModelAllowList[0] === MODEL_ALLOW_NONE_SENTINEL and the sentinel short-circuit in computeAllowedModelIds() may stop working.
Consider preserving the sentinel inside canonicalizeModelAllowList(), or guarding canonicalization sites to skip/handle the exact-sentinel state.
| return canonicalizeModelAllowList(remaining); | ||
| } | ||
|
|
||
| const remaining = draftModelAllowList.filter( |
There was a problem hiding this comment.
WARNING: Bulk deselect doesn’t account for provider wildcards
In setAllModelsAllowed() when nextAllowed is false, the removal logic only filters out entries that exactly match targetModelIds. If a target model is effectively allowed via a provider wildcard like "provider/*", that wildcard remains and the model may still be allowed after “deselect all” on a filtered subset.
This differs from toggleModelAllowed(), which explicitly removes provider wildcards for providers offering the model when disabling. Consider extending the bulk path to also remove relevant provider/* entries (e.g., by passing provider slugs per model / rows, or computing from openRouterProviders).
Overview
Adds a "select all / select none" checkbox to the header of the Models table on the organisation Providers & Models settings page so it's easier to choose less models. Also prevents saving when zero models are selected.