1
0
Fork 0

Models filter

This commit is contained in:
Pabloader 2026-04-08 10:00:48 +00:00
parent ae0d232331
commit 7eb8e5b870
2 changed files with 63 additions and 17 deletions

View File

@ -116,6 +116,7 @@
.formGroup { .formGroup {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 4px;
} }
.formGroupFill { .formGroupFill {
@ -128,6 +129,20 @@
font-weight: bold; font-weight: bold;
} }
.selectMultiline {
flex: 1;
overflow-y: auto;
}
.selectMultiline optgroup {
padding-block: 4px;
}
.selectMultiline option {
padding-block: 4px;
padding-inline-start: 16px;
}
.input, .input,
.select, .select,
.textarea { .textarea {

View File

@ -2,6 +2,7 @@ import { useBool } from "@common/hooks/useBool";
import { useQuery } from "@common/hooks/useAsyncState"; import { useQuery } from "@common/hooks/useAsyncState";
import { useInputState } from "@common/hooks/useInputState"; import { useInputState } from "@common/hooks/useInputState";
import { useUpdate } from "@common/hooks/useUpdate"; import { useUpdate } from "@common/hooks/useUpdate";
import clsx from "clsx";
import { useMemo, useRef } from "preact/hooks"; import { useMemo, useRef } from "preact/hooks";
import styles from "../../assets/settings-modal.module.css"; import styles from "../../assets/settings-modal.module.css";
import { useAppState } from "../../contexts/state"; import { useAppState } from "../../contexts/state";
@ -36,6 +37,8 @@ export const ConnectionSettings = () => {
const modelsData = useQuery(fetchModels, connectionToFetch); const modelsData = useQuery(fetchModels, connectionToFetch);
const isLoadingModels = connectionToFetch != null && modelsData == undefined; const isLoadingModels = connectionToFetch != null && modelsData == undefined;
const [modelFilter, setModelFilter] = useInputState("");
const groupedModels = useMemo(() => { const groupedModels = useMemo(() => {
const sorted = (modelsData ?? []).sort((a, b) => { const sorted = (modelsData ?? []).sort((a, b) => {
const aWeight = Number(a.support_tools) * 2 + Number(a.support_thinking); const aWeight = Number(a.support_tools) * 2 + Number(a.support_thinking);
@ -52,6 +55,25 @@ export const ConnectionSettings = () => {
.map(([context, models]) => ({ context, models })); .map(([context, models]) => ({ context, models }));
}, [modelsData]); }, [modelsData]);
const filteredGroupedModels = useMemo(() => {
if (!modelFilter) return groupedModels;
const query = modelFilter.toLowerCase();
const fuzzyMatch = (target: string) => {
const t = target.toLowerCase();
let qi = 0;
for (let ti = 0; ti < t.length && qi < query.length; ti++) {
if (t[ti] === query[qi]) qi++;
}
return qi === query.length;
};
return groupedModels
.map(({ context, models }) => ({
context,
models: models.filter(m => m.id === selectedModel || fuzzyMatch(m.id)),
}))
.filter(({ models }) => models.length > 0);
}, [groupedModels, modelFilter, selectedModel]);
const handleBlur = () => { const handleBlur = () => {
if (url && apiKey) { if (url && apiKey) {
dispatch({ type: "SET_CONNECTION", connection: { url, apiKey } }); dispatch({ type: "SET_CONNECTION", connection: { url, apiKey } });
@ -115,19 +137,27 @@ export const ConnectionSettings = () => {
</button> </button>
</div> </div>
</div> </div>
<div class={styles.formGroup}> <div class={clsx(styles.formGroup, styles.formGroupFill)}>
<label class={styles.label}>Model</label> <label class={styles.label}>Model</label>
{connectionToTest ? ( {connectionToTest ? (
isLoadingModels ? ( isLoadingModels ? (
<p>Loading models...</p> <p>Loading models...</p>
) : groupedModels.length > 0 ? ( ) : groupedModels.length > 0 ? (
<>
<input
type="text"
value={modelFilter}
onInput={setModelFilter}
placeholder="Filter models..."
class={styles.input}
/>
<select <select
value={selectedModel} value={selectedModel}
onChange={handleModelChange} onChange={handleModelChange}
class={styles.select} class={clsx(styles.select, styles.selectMultiline)}
size={8}
> >
<option value="">Select a model</option> {filteredGroupedModels.map(({ context, models }) => (
{groupedModels.map(({ context, models }) => (
<optgroup key={context} label={`${context} context`}> <optgroup key={context} label={`${context} context`}>
{models.map(m => ( {models.map(m => (
<option key={m.id} value={m.id}> <option key={m.id} value={m.id}>
@ -137,6 +167,7 @@ export const ConnectionSettings = () => {
</optgroup> </optgroup>
))} ))}
</select> </select>
</>
) : ( ) : (
<p>No models available</p> <p>No models available</p>
) )