Skip to content

feat(settings): multi-select model deletion, regex search, dual-area model list#467

Open
Jacobinwwey wants to merge 10 commits into
TouchAI-org:mainfrom
Jacobinwwey:feat/model-list-multi-select-regex-search
Open

feat(settings): multi-select model deletion, regex search, dual-area model list#467
Jacobinwwey wants to merge 10 commits into
TouchAI-org:mainfrom
Jacobinwwey:feat/model-list-multi-select-regex-search

Conversation

@Jacobinwwey

@Jacobinwwey Jacobinwwey commented Jun 13, 2026

Copy link
Copy Markdown

Summary

  • Split model list into "Model Selection Area" (user-added) and "Model Support Area" (all provider models)
  • Add multi-select mode with checkbox selection, select-all, and batch delete
  • Add regex search toggle in search bar with validation error display

1. Context & Motivation (Context)

  • Problem: The model list in Settings currently adds all fetched models directly to the user's active list. Users can only delete models one at a time. Search only supports plain-text substring matching. There is no distinction between "available models" and "models the user actually wants to use."
  • Trade-offs: Added is_selected column to the models table (schema migration required). This is a lightweight boolean flag approach rather than a separate "wishlist" table — chosen for simplicity and to avoid JOIN overhead. New models from provider refresh default to is_selected=0, requiring an explicit user action to add them to the selection area.

2. Implementation Details (Implementation)

  • DB schema: Added is_selected integer column (default 1) to models table with CHECK(is_selected IN (0,1)) constraint. Existing models retain is_selected=1 to preserve backward compatibility.
  • DB queries: Added deleteModels(ids[]) batch delete and updateModelsSelected(ids[], isSelected) batch update. Both accept optional DatabaseExecutor for transaction participation.
  • ModelCard.vue: Added multiSelectMode, isSelected, area props. In multi-select mode: checkbox replaces radio, card click toggles selection. In support area: shows "+" (add-to-selection). In selection area: shows "−" (remove-from-selection).
  • ModelGroup.vue: Group-level checkbox with indeterminate state for partial selection. Hides group delete in multi-select mode.
  • ModelList.vue: Split into Selection Area (is_selected=1) and Support Area (is_selected=0). Regex toggle (".*" button) with validation. Multi-select state resets on provider switch via watch(providerId). Batch delete blocks default model.
  • AiServices/index.vue: Wires batch-delete, add-to-selection, remove-from-selection (blocks default model). Split showEditDialog into showEditProviderDialog.

3. Testing Strategies (Validation)

  • TypeScript type-check passes (vue-tsc --noEmit)
  • ESLint passes (0 errors)
  • Prettier formatting verified
  • Unit tests pass (976/976, including updated ModelCard and AiServices i18n tests)
  • Backward compatibility: existing models retain is_selected=1

Related issue or RFC

Related to #467 - User-requested feature for better model management workflow

AI assistance disclosure

This PR was developed with assistance from Claude Code (Claude Opus 4.8).

Testing evidence

  • All 976 unit tests pass
  • TypeScript type-check passes
  • ESLint passes with 0 errors
  • Manual testing of multi-select, batch delete, regex search, and dual-area model list

Risk notes

  • Database migration adds is_selected column with CHECK constraint
  • Existing models default to is_selected=1 for backward compatibility
  • New models from provider refresh default to is_selected=0
  • Default model is protected from removal in both single and batch operations

Screenshots or recordings

N/A - Backend/logic feature with UI state changes visible in existing Settings view

Checklist

  • Code follows project style guidelines
  • Self-reviewed the code
  • Commented code in hard-to-understand areas
  • Updated documentation as needed
  • Changes generate no new warnings
  • Added tests that prove the fix is effective or the feature works
  • New and existing unit tests pass locally
  • Any dependent changes have been merged and published

🤖 Generated with Claude Code

…models

Add is_selected column to models table (default 1) to distinguish
provider-supported models from user-selected models. Add deleteModels
batch delete and updateModelsSelected batch update queries. New models
fetched via refresh default to is_selected=0 (support area only).

Signed-off-by: Jacob <jacob@example.com>
Signed-off-by: Jacobinwwey <jacob.hxx.cn@outlook.com>
Add zh-CN and en-US translation keys for: multi-select mode toggle,
batch delete confirmation/success, regex search toggle and validation,
model support/selection area titles and descriptions, add-to-selection
and remove-from-selection actions.

Signed-off-by: Jacob <jacob@example.com>
Signed-off-by: Jacobinwwey <jacob.hxx.cn@outlook.com>
…rea model list

ModelList now splits into:
- Model Selection Area: models the user has explicitly added (is_selected=1)
- Model Support Area: all provider-supported models (is_selected=0)

Features added:
- Multi-select mode with checkbox selection, select-all, and batch delete
- Regex search toggle (.* button in search bar) with error validation
- Add-to-selection / remove-from-selection buttons on ModelCard
- Batch delete with confirmation dialog blocks default model deletion

ModelCard gains multiSelectMode/isSelected/area props and toggle-select,
add-to-selection, remove-from-selection events. ModelGroup passes through
multi-select state with group-level select/deselect.

AiServices orchestrator wires batch-delete, add-to-selection, and
remove-from-selection events to the new deleteModels and
updateModelsSelected database queries.

Signed-off-by: Jacob <jacob@example.com>
Signed-off-by: Jacobinwwey <jacob.hxx.cn@outlook.com>
@CLAassistant

CLAassistant commented Jun 13, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@github-actions github-actions Bot added area:frontend Frontend UI or view-layer changes area:database Schema, persistence, or migration changes labels Jun 13, 2026
@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds an is_selected column via database migration and updates schema/types/queries with batch helpers, implements multi-select UI with regex search and batch delete across ModelCard/ModelGroup/ModelList components, integrates handlers in AiServices parent component, adds i18n messages, and updates tests.

Changes

Model Multi-Select Feature

Layer / File(s) Summary
Database schema, types, and batch query helpers
apps/desktop/src/database/drizzle/0004_model_is_selected.sql, apps/desktop/src/database/drizzle/meta/_journal.json, apps/desktop/src/database/schema.ts, apps/desktop/src/database/queries/models.ts, apps/desktop/src/database/types/index.ts
Migration adds is_selected integer column (default 1) with journal entry. Schema, type definitions (ModelEntity, ModelCreateData, ModelWithProvider), and query projection updated; new batch helpers deleteModels and updateModelsSelected enable bulk operations.
Internationalization for multi-select UI
apps/desktop/src/i18n/messages.ts
New i18n entries for multi-select controls, batch-delete confirmation/success messages, selection counters, regex search UI, support vs selection area labels, and add/remove selection actions (English and Chinese with pluralization variants).
ModelCard multi-select enhancements
apps/desktop/src/views/SettingsView/components/AiServices/components/ModelCard.vue
Props and emits extended with multiSelectMode, isSelected, and contextual area. Card click toggles selection in multi-select mode; template conditionally renders checkbox and contextual add/remove selection buttons based on area.
ModelGroup selection controls
apps/desktop/src/views/SettingsView/components/AiServices/components/ModelGroup.vue
Adds group-level checkbox with checked/indeterminate states, computed flags for partial/full selection, toggleGroupSelect logic, hides delete button during multi-select mode, and forwards selection events from child ModelCard instances.
ModelList multi-select state, regex search, and batch actions
apps/desktop/src/views/SettingsView/components/AiServices/components/ModelList.vue
Introduces multi-select state and selectedModelIds, dual-mode search (regex/plain with error handling), splits models into selection vs support computed lists, implements select-all/none and confirmed batch-delete with default-model inclusion guard, updates toolbar with search/multi-select/batch controls and refactored template layout.
AiServices parent component integration
apps/desktop/src/views/SettingsView/components/AiServices/index.vue
Imports deleteModels/updateModelsSelected and tp for messages, initializes new models with is_selected: 0, adds handlers for batch deletion and per-model selection toggling (patch cache, broadcast AI_MODELS_UPDATED, prevent removing default model from selection), refactors provider edit dialog state, and wires ModelList batch/selection events.
Test fixtures and interactions
apps/desktop/tests/SettingsView/ai-services-i18n.test.ts, apps/desktop/tests/SettingsView/model-card-i18n.test.ts, apps/desktop/tests/composables/SearchView/SearchBar/useModelSelection.test.ts, apps/desktop/tests/services/AgentService/attachment-capability-preflight.test.ts, apps/desktop/tests/services/AgentService/catalog/providers.test.ts, apps/desktop/tests/services/AgentService/execution/executor.test.ts, apps/desktop/tests/services/BuiltInToolService/tools/upgradeModel/i18n.test.ts
Test helpers across multiple test files updated to include is_selected: 1 in model mocks, refresh test made async and selector refined to target specific refresh button, and button indices adjusted (0–2) to match expanded multi-select button layout.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Poem

🐰 Hopping through lists with cheer so bright,
Checkboxes gleam—multi-select delight,
Regex sniffs names with careful care,
Batch-delete clears what we don't share,
Selection sorted, support's there!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main features added: multi-select model deletion, regex search, and the dual-area model list structure, following conventional commits format.
Description check ✅ Passed The description is comprehensive, addressing all required sections: clear summary of changes, related issue reference, AI assistance disclosure, testing evidence, risk notes, and a completed checklist.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 and usage tips.

@github-actions

Copy link
Copy Markdown
Contributor

Thanks for your first pull request to TouchAI.

感谢你向 TouchAI 提交第一条 Pull Request。

A few quick checks before review:
评审前请先快速确认以下几点:

  • Link the related issue or RFC.
    请关联对应的 issue 或 RFC。
  • If this PR is still evolving, keep it as a Draft PR.
    如果这条 PR 还在演进中,请保持为 Draft PR。
  • Pull request titles should follow Conventional Commits.
    Pull Request 标题需要符合 Conventional Commits 规范。
  • If AI tools materially assisted this change, disclose that in the PR description.
    如果本次改动有实质性的 AI 辅助,请在 PR 描述中披露。
  • Add testing evidence for the commands you ran.
    请补充你实际执行过的测试验证信息。
  • If the CLA Assistant check appears, please complete signature before merge.
    如果出现 CLA Assistant 检查,请先完成签署再进入合并流程。

Helpful links:
相关链接:

Thanks for contributing.
感谢贡献。

@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: 3

🤖 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 `@apps/desktop/src/database/drizzle/0004_model_is_selected.sql`:
- Line 1: Add a DB-level constraint and tighten the TypeScript types/callers:
change the migration that adds is_selected so the column is a 1-byte integer and
has a CHECK constraint limiting values to (0,1) (e.g. make it TINYINT/INTEGER
NOT NULL DEFAULT 1 and add CHECK(is_selected IN (0,1))); then update the code
types and caller to only allow 0|1: in the DB model types narrow
is_selected/isSelected to the union type 0 | 1 (ModelEntity, ModelCreateData,
ModelWithProvider) and adjust the updateModelsSelected function
signature/implementation to accept and persist only 0 or 1. Ensure any runtime
code that sets isSelected validates/coerces to 0 or 1 before persisting.

In
`@apps/desktop/src/views/SettingsView/components/AiServices/components/ModelList.vue`:
- Around line 159-163: The component keeps multiSelectMode and selectedModelIds
across provider switches causing hidden selections to persist; add a watcher on
the providerId prop inside ModelList (or the setup where
regexMode/multiSelectMode/selectedModelIds are declared) that resets
multiSelectMode.value = false and selectedModelIds.value = new Set() whenever
providerId changes (alternatively force a remount keyed by providerId), and
apply the same reset in the other place where those refs are declared so
selections are cleared when the parent switches providers.

In `@apps/desktop/src/views/SettingsView/components/AiServices/index.vue`:
- Around line 674-682: The handler handleRemoveFromSelection currently allows
clearing is_selected for any model id, including the protected defaultModelId;
change it to first check whether id === defaultModelId (or compare against the
current default model variable) and if so abort with a user-facing error (e.g.,
alert.error with a message asking to choose a new default first) without calling
updateModelsSelected/patchCachedModel/broadcastModelsUpdated; otherwise proceed
as before calling updateModelsSelected([id], 0), patchCachedModel(id, {
is_selected: 0 }), and broadcastModelsUpdated(). Ensure the check uses the same
defaultModelId reference used elsewhere so behavior matches the batch-delete
protection.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 079ba0ad-6c35-44fa-b45f-499b2c72462a

📥 Commits

Reviewing files that changed from the base of the PR and between ebc3494 and 3506f1b.

📒 Files selected for processing (10)
  • apps/desktop/src/database/drizzle/0004_model_is_selected.sql
  • apps/desktop/src/database/drizzle/meta/_journal.json
  • apps/desktop/src/database/queries/models.ts
  • apps/desktop/src/database/schema.ts
  • apps/desktop/src/database/types/index.ts
  • apps/desktop/src/i18n/messages.ts
  • apps/desktop/src/views/SettingsView/components/AiServices/components/ModelCard.vue
  • apps/desktop/src/views/SettingsView/components/AiServices/components/ModelGroup.vue
  • apps/desktop/src/views/SettingsView/components/AiServices/components/ModelList.vue
  • apps/desktop/src/views/SettingsView/components/AiServices/index.vue
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Desktop E2E Smoke (Windows)
  • GitHub Check: CodeQL (rust)
  • GitHub Check: Frontend Tests
  • GitHub Check: Rust Checks
🔇 Additional comments (5)
apps/desktop/src/database/drizzle/meta/_journal.json (1)

32-38: LGTM!

apps/desktop/src/database/schema.ts (1)

271-271: LGTM!

apps/desktop/src/database/queries/models.ts (1)

3-3: LGTM!

Also applies to: 40-40, 191-218

apps/desktop/src/database/types/index.ts (1)

228-228: LGTM!

Also applies to: 250-250, 285-285

apps/desktop/src/i18n/messages.ts (1)

1417-1419: Use tp() (not t()) for pipe-delimited plural keys
apps/desktop/src/i18n/messages.ts defines settings.ai.confirmBatchDelete and settings.ai.batchDeleteSucceeded as pipe-delimited plural strings (en-US), but ModelList.vue and AiServices/index.vue call t(..., { count: ids.length }) for those keys. This repo provides a plural-count helper tp() in apps/desktop/src/i18n/index.ts and uses it for other count-based plural messages, so these call sites should switch to tp() (or make the message definitions single-form).

Comment thread apps/desktop/src/database/drizzle/0004_model_is_selected.sql Outdated
Comment thread apps/desktop/src/views/SettingsView/components/AiServices/index.vue
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 13, 2026
@Jacobinwwey Jacobinwwey force-pushed the feat/model-list-multi-select-regex-search branch from 6892df1 to 7d11a8f Compare June 13, 2026 11:46
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 13, 2026
- Add CHECK(is_selected IN (0,1)) constraint to migration
- Revert is_selected from 0|1 to number (matching Drizzle inference)
- Reset multiSelectMode and selectedModelIds when providerId changes
- Block remove-from-selection for the default model
- Switch confirmBatchDelete/batchDeleteSucceeded to tp() for plurals
- Update ModelCard test for new button order (remove-from-selection first)
- Add is_selected field to test model factories

Signed-off-by: Jacob <jacob@example.com>
Signed-off-by: Jacobinwwey <jacob.hxx.cn@outlook.com>
@Jacobinwwey Jacobinwwey force-pushed the feat/model-list-multi-select-regex-search branch from 7d11a8f to 384249e Compare June 14, 2026 10:59
Add is_selected: 1 to all ModelWithProvider factory functions in test files.
This field was added in migration 0004 but test mocks were not updated,
causing test:typecheck to fail in CI.
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jun 14, 2026
@hiqiancheng

hiqiancheng commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

Thank you for your contribution; this is a very useful feature. However, in manual testing I found that even though it has not been added to the selection area by the provider, it still appears in the model selection popup, which seems inconsistent with expectations.

@hiqiancheng

hiqiancheng commented Jun 14, 2026

Copy link
Copy Markdown
Collaborator

And another bug: the model of supporting areas can be set as default directly, but they won’t automatically transition into the selection area.

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.

This database migration should be automatically generated by drizzle-kit rather than manually added, as manual additions often miss snapshot files belike now.

<span class="text-xs text-neutral-400">({{ selectionModels.length }})</span>
</div>
<p class="text-xs text-neutral-400">
{{ t('settings.ai.modelSelectionAreaDescription') }}

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.

I don’t think this description is necessary.

Comment thread apps/desktop/src/i18n/messages.ts Outdated
'settings.ai.regexSearch': '正则搜索',
'settings.ai.regexSearchExit': '退出正则',
'settings.ai.invalidRegex': '正则表达式无效:{error}',
'settings.ai.modelSupportArea': '模型支持区域',

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.

Wouldn't it be more appropriate to change it to “已选模型” / “全部模型”? and "添加" rather than "添加到选择区域"

@hiqiancheng

Copy link
Copy Markdown
Collaborator

Additionally, we're discussing a question that should have been addressed during the issue phase: since this PR adds too many buttons, would it be more appropriate to switch to icons? What do you think?

Improvements based on @hiqiancheng's review:

1. **i18n improvements**: Simplified area labels and action text
   - "模型支持区域" → "全部模型" (Model support area → All models)
   - "模型选择区域" → "已选模型" (Model selection area → Selected models)
   - "添加到选择区域" → "添加" (Add to selection → Add)
   - "从选择区域移除" → "移除" (Remove from selection → Remove)
   - Removed unnecessary description text below area headers

2. **Migration metadata**: Added missing snapshot file for 0004
   - Generated 0004_snapshot.json using drizzle-kit
   - Ensures migration metadata is complete and matches drizzle-kit expectations

All previously addressed CodeRabbit feedback remains fixed:
- CHECK constraint in migration (is_selected IN (0,1))
- providerId watcher resets multi-select state
- Default model guard in handleRemoveFromSelection
…text

Update test expectation from "Remove from selection" to "Remove" to match
the simplified i18n text requested by reviewer.
@Jacobinwwey

Copy link
Copy Markdown
Author

✅ All Reviewer Feedback Addressed

Thank you @coderabbitai and @hiqiancheng for the thorough reviews! I've addressed all feedback points:

📝 @hiqiancheng's Feedback

1. ✅ Migration snapshot file (commit c4febbf)

  • Issue: Migration 0004 was manually added without drizzle-kit generated snapshot
  • Fix: Generated 0004_snapshot.json using drizzle-kit to ensure metadata completeness

2. ✅ Simplified i18n labels (commits c4febbf, 40fd833)

  • Issue: Labels were unnecessarily verbose
  • Changes:
    • "模型支持区域""全部模型" (Model support area → All models)
    • "模型选择区域""已选模型" (Model selection area → Selected models)
    • "添加到选择区域""添加" (Add to selection → Add)
    • "从选择区域移除""移除" (Remove from selection → Remove)

3. ✅ Removed unnecessary descriptions (commit c4febbf)

  • Issue: Description text below area headers was redundant
  • Fix: Removed modelSelectionAreaDescription and modelSupportAreaDescription from UI and i18n

🤖 @coderabbitai's Feedback (Previously Addressed)

All three major issues were already fixed in commit 6892df1:

1. ✅ Database CHECK constraint

  • Added CHECK(is_selected IN (0, 1)) to migration 0004

2. ✅ Multi-select state reset on provider switch

  • Added watcher on providerId that calls exitMultiSelect() to reset state

3. ✅ Default model protection in single remove

  • Added guard in handleRemoveFromSelection that blocks removal with error message

🧪 Test Results

All 976 tests pass locally and in CI:

  • ✅ Frontend Quality (type:check + test:typecheck)
  • ✅ Frontend Tests (976/976)
  • ✅ Conventional Commits
  • ✅ Validate PR template
  • ✅ CI Required

📦 Final Commits

  1. 6892df1 - Initial CodeRabbit review fixes (CHECK constraint, watcher, default guard)
  2. 6b34729 - Test type-check fixes (added is_selected to test mocks)
  3. c4febbf - Reviewer feedback on i18n and migration snapshot
  4. 40fd833 - Test expectation update for simplified i18n

Ready for re-review! 🚀

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

@Jacobinwwey Thanks for the detailed summary and the thorough follow-up! Here's a quick acknowledgment of all the fixes:

  • CHECK constraint on is_selected in migration 0004 — properly enforces the 0|1 domain
  • Multi-select state reset via a providerId watcher calling exitMultiSelect() — prevents stale selection state when switching providers
  • Default model protection in single remove — guard in handleRemoveFromSelection with an error message
  • Migration snapshot (0004_snapshot.json) generated by drizzle-kit
  • Simplified i18n labels — cleaner and more concise for users
  • Removed redundant area descriptions — declutters the UI
  • Test mocks updated with is_selected: 1 — TypeScript type-checking passes cleanly

Triggering a fresh review now.

(◕‿◕✿)

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Jacobinwwey Jacobinwwey force-pushed the feat/model-list-multi-select-regex-search branch from 40fd833 to bff5abd Compare June 15, 2026 06:17
This commit fixes two functional bugs identified by @hiqiancheng:

1. **Bug: Unselected models appear in SearchView model picker**
   - Root cause: findModelsWithProvider() didn't filter by is_selected
   - Fix: Added WHERE is_selected = 1 to the query
   - Impact: SearchView model dropdown now only shows models in "selection area"

2. **Bug: Setting support-area model as default doesn't move it to selection area**
   - Root cause: handleSetDefaultModel() only updated is_default, not is_selected
   - Fix: Auto-call updateModelsSelected([id], 1) before setting default
   - Impact: Setting any model as default now ensures it's in selection area

Note: Icon buttons were already implemented in the original PR (commit 3506f1b),
so no changes needed for the "too many buttons" design concern.

All 976 tests pass.
@Jacobinwwey Jacobinwwey force-pushed the feat/model-list-multi-select-regex-search branch from e5cdf74 to 3e96871 Compare June 15, 2026 06:41
@Jacobinwwey

Copy link
Copy Markdown
Author

@hiqiancheng Thank you for the thorough review! I've addressed all three of your comments:

1. Icon Buttons vs Text Buttons

Already implemented in the original PR (commit 3506f1b). All action buttons use AppIcon components:

  • Add to selection: <AppIcon name="plus" />
  • Remove from selection: <AppIcon name="minus" />
  • Edit: <AppIcon name="edit" />
  • Delete: <AppIcon name="delete" />

2. Bug: Unselected models appear in SearchView dropdown

Fixed in commit 3e96871. The issue was in findModelsWithProvider() which didn't filter by is_selected:

// Before: no filtering
const whereConditions = [];
if (providerId !== undefined) {
    whereConditions.push(eq(models.provider_id, providerId));
}

// After: filter out unselected models
const whereConditions = [eq(models.is_selected, 1)];
if (providerId !== undefined) {
    whereConditions.push(eq(models.provider_id, providerId));
}

3. Bug: Setting default from support area doesn't auto-select

Fixed in commit 3e96871. Added auto-selection logic in handleSetDefaultModel():

const handleSetDefaultModel = async (id: number) => {
    try {
        const nextDefaultModel = findCachedModel(id);

        // If the model is not in selection area, add it first
        if (nextDefaultModel && nextDefaultModel.is_selected === 0) {
            await updateModelsSelected([id], 1);
        }

        await setDefaultModel({ modelId: id });
        // ... rest of the logic
    }
}

All 976 tests pass. Ready for re-review!

@hiqiancheng

Copy link
Copy Markdown
Collaborator

@Jacobinwwey Yes, but I’m referring to those buttons that are placed side by side with the search bar. Since several buttons have been added, the original space has been squeezed — using icons seems like a better choice?

I’d like to discuss this with you; please don’t have the agent start coding right away. What do you think?

@Jacobinwwey

Jacobinwwey commented Jun 16, 2026

Copy link
Copy Markdown
Author

@Jacobinwwey Yes, but I’m referring to those buttons that are placed side by side with the search bar. Since several buttons have been added, the original space has been squeezed — using icons seems like a better choice?

I’d like to discuss this with you; please don’t have the agent start coding right away. What do you think?

@hiqiancheng
touchai-branch-compare.html
can you check this. I've tried three ways in three worktrees of ui/toolbar-icon-option-* in my fork repo https://github.com/Jacobinwwey/TouchAI. Main diff is ModelList.vue toolbar section

…ti-select-regex-search

# Conflicts:
#	apps/desktop/tests/services/AgentService/catalog/providers.test.ts
@github-actions github-actions Bot added the area:tauri Tauri shell or desktop runtime changes label Jun 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:database Schema, persistence, or migration changes area:frontend Frontend UI or view-layer changes area:tauri Tauri shell or desktop runtime changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants