diff --git a/src/common/components/ContentEditable.tsx b/src/common/components/ContentEditable.tsx index a4c4c6d..d2ea29d 100644 --- a/src/common/components/ContentEditable.tsx +++ b/src/common/components/ContentEditable.tsx @@ -119,7 +119,7 @@ export const ContentEditable = ({ ref={ref} {...props} contentEditable - data-placeholder={value.replaceAll('\n', '').length ? undefined : placeholder} + data-placeholder={value?.replaceAll('\n', '').length ? undefined : placeholder} class={clsx(styles.root, autoLines && styles.autoLines, externalClass)} onInput={handleInput} /> diff --git a/src/games/storywriter/components/settings/connection.tsx b/src/games/storywriter/components/settings/connection.tsx index eedab87..b2ddb64 100644 --- a/src/games/storywriter/components/settings/connection.tsx +++ b/src/games/storywriter/components/settings/connection.tsx @@ -32,24 +32,19 @@ export const ConnectionSettings = () => { const fetchModels = useMemo(() => async (conn: LLM.Connection | null) => { if (!conn) return []; - const r = await LLM.getTextModels(conn); - return r.data; - }, []); - - const fetchImageModels = useMemo(() => async (conn: LLM.Connection | null) => { - if (!conn) return []; - const r = await LLM.getImageModels(conn); + const r = await LLM.getModels(conn); return r.data; }, []); const modelsData = useQuery(fetchModels, connectionToFetch); - const imageModelsData = useQuery(fetchImageModels, connectionToFetch); - const isLoadingModels = connectionToFetch != null && modelsData == undefined; + const textModelsData = useMemo(() => modelsData?.filter(LLM.isTextModel), [modelsData]); + const imageModelsData = useMemo(() => modelsData?.filter(LLM.isImageModel), [modelsData]); + const isLoadingModels = connectionToFetch != null && textModelsData == undefined; const [modelFilter, setModelFilter] = useInputState(""); const groupedModels = useMemo(() => { - const sorted = (modelsData ?? []).sort((a, b) => { + const sorted = (textModelsData ?? []).sort((a, b) => { const aWeight = Number(a.supported_parameters.includes('tools')) * 2 + Number(a.supported_parameters.includes('reasoning')); const bWeight = Number(b.supported_parameters.includes('tools')) * 2 + Number(b.supported_parameters.includes('reasoning')); if (aWeight !== bWeight) return bWeight - aWeight; @@ -60,7 +55,7 @@ export const ConnectionSettings = () => { return Array.from(groups.entries()) .sort((a, b) => b[0] - a[0]) .map(([context, models]) => ({ context, models })); - }, [modelsData]); + }, [textModelsData]); const filteredGroupedModels = useMemo(() => { if (!modelFilter) return groupedModels; @@ -95,7 +90,7 @@ export const ConnectionSettings = () => { const handleModelChange = (e: Event) => { setSelectedModel(e); const target = e.target as HTMLSelectElement; - const selectedModelInfo = modelsData?.find(m => m.id === target.value) ?? null; + const selectedModelInfo = textModelsData?.find(m => m.id === target.value) ?? null; dispatch({ type: "SET_MODEL", model: selectedModelInfo }); }; diff --git a/src/games/storywriter/components/settings/image.tsx b/src/games/storywriter/components/settings/image.tsx index bcbcd29..0cd2036 100644 --- a/src/games/storywriter/components/settings/image.tsx +++ b/src/games/storywriter/components/settings/image.tsx @@ -105,7 +105,8 @@ export const ImageSettings = () => {
- ('context_length' in model); - const isImageModel = (model: ModelInfo): model is ModelInfoImage => Boolean( + export const isTextModel = (model: ModelInfo): model is ModelInfoText => ('context_length' in model); + export const isImageModel = (model: ModelInfo): model is ModelInfoImage => Boolean( !isTextModel(model) && model.architecture && (model.architecture.output_modalities).includes('image') @@ -313,18 +313,8 @@ namespace LLM { return e != null && typeof e === 'object' && 'data' in e && typeof e.data === 'string'; } - export async function getTextModels(connection: Connection): Promise> { - const response = await request(connection, '/v1/models'); - - response.data = response.data.filter(isTextModel); - return response as ModelsResponse; - } - - export async function getImageModels(connection: Connection): Promise> { - const response = await request(connection, '/v1/models'); - - response.data = response.data.filter(isImageModel); - return response as ModelsResponse; + export async function getModels(connection: Connection): Promise> { + return request(connection, '/v1/models'); } export async function countTokens(connection: Connection, body: CountTokensRequest) {