diff options
| author | Adam Malczewski <[email protected]> | 2026-05-23 19:07:21 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-05-23 19:07:21 +0900 |
| commit | 997b00034435440d412f955e05e53f09bae83f9e (patch) | |
| tree | 22d1f530e9e1a97bd19286456d2f06793bd030f7 /packages/frontend/src/lib/components/ModelSelector.svelte | |
| parent | ff00dec6ae2971bee38c74cb00fe034de9a839ee (diff) | |
| download | dispatch-997b00034435440d412f955e05e53f09bae83f9e.tar.gz dispatch-997b00034435440d412f955e05e53f09bae83f9e.zip | |
feat: google gemini provider, adaptive thinking for opus 4.7, model search filter
- Added Google (Gemini) as a provider: add-key UI, env var resolution via resolveApiKey, usage tracking via native models endpoint + gemini.google.com cookie scraping
- @ai-sdk/anthropic upgraded to v3 (adaptive thinking support) with LanguageModelV1 cast for ai v4 compat
- Claude Opus 4.7 uses adaptive thinking (type: adaptive); all other models keep explicit budget tokens
- Model selector modal: search filter with space matching dash/underscore
- Copy button: all tool results truncated at 300 chars
- Sidebar layout fix: Claude Reset panel removed from flex-1 fill to prevent overlap
Diffstat (limited to 'packages/frontend/src/lib/components/ModelSelector.svelte')
| -rw-r--r-- | packages/frontend/src/lib/components/ModelSelector.svelte | 46 |
1 files changed, 35 insertions, 11 deletions
diff --git a/packages/frontend/src/lib/components/ModelSelector.svelte b/packages/frontend/src/lib/components/ModelSelector.svelte index bbbf036..235cf3b 100644 --- a/packages/frontend/src/lib/components/ModelSelector.svelte +++ b/packages/frontend/src/lib/components/ModelSelector.svelte @@ -62,6 +62,7 @@ const modelCache = new Map<string, string[]>(); let loadingModels = $state(false); let modelError = $state<string | null>(null); let sliderDragging = $state<number | null>(null); + let modelSearch = $state(""); let cwdExists = $state<boolean | null>(null); let cwdCheckTimer: ReturnType<typeof setTimeout> | null = null; @@ -126,6 +127,7 @@ const modelCache = new Map<string, string[]>(); if (!keyId) return; showModelModal = true; modelError = null; + modelSearch = ""; // Check session cache if (modelCache.has(keyId)) { @@ -393,17 +395,39 @@ const modelCache = new Map<string, string[]>(); <span>{modelError}</span> </div> {:else} - <div class="mt-4 flex flex-col gap-1 max-h-96 overflow-y-auto"> - {#each availableModels as model} - <button - class="btn {model === activeModelId - ? 'btn-primary' - : 'btn-ghost'} justify-start font-mono text-base" - onclick={() => selectModel(model)} - > - {model} - </button> - {/each} + {@const search = modelSearch.toLowerCase().trim()} + {@const searchRegex = search + ? new RegExp( + search.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/ /g, "[ _-]"), + ) + : null} + {@const filteredModels = searchRegex + ? availableModels.filter((m) => searchRegex.test(m.toLowerCase())) + : availableModels} + <div class="mt-4 flex flex-col gap-1"> + <input + type="text" + class="input input-bordered input-sm w-full" + placeholder="Filter models..." + bind:value={modelSearch} + /> + <div class="mt-2 max-h-96 overflow-y-auto flex flex-col gap-1"> + {#each filteredModels as model} + <button + class="btn {model === activeModelId + ? 'btn-primary' + : 'btn-ghost'} justify-start font-mono text-base" + onclick={() => selectModel(model)} + > + {model} + </button> + {/each} + {#if filteredModels.length === 0} + <p class="text-xs text-base-content/50 py-2 text-center"> + {search ? 'No models match your search.' : 'No models available.'} + </p> + {/if} + </div> </div> {/if} <div class="modal-action"> |
