import { useCallback, useEffect, useMemo, useState } from 'preact/hooks'; import styles from './header.module.css'; import { Connection, HORDE_ANON_KEY, type IConnection, type IHordeModel } from '../../tools/connection'; import { useInputState } from '@common/hooks/useInputState'; import { useInputCallback } from '@common/hooks/useInputCallback'; import { Huggingface } from '../../tools/huggingface'; import { INSTRUCTS } from '../../contexts/state'; interface IProps { connection: IConnection; setConnection: (c: IConnection) => void; } export const ConnectionEditor = ({ connection, setConnection }: IProps) => { // kobold const [connectionUrl, setConnectionUrl] = useInputState(''); // horde const [apiKey, setApiKey] = useInputState(HORDE_ANON_KEY); const [modelName, setModelName] = useInputState(''); const [instruct, setInstruct] = useInputState(''); const [modelTemplate, setModelTemplate] = useInputState(''); const [hordeModels, setHordeModels] = useState([]); const [contextLength, setContextLength] = useState(0); const isOnline = useMemo(() => contextLength > 0, [contextLength]); useEffect(() => { setInstruct(connection.instruct); connection.url && setConnectionUrl(connection.url); connection.model && setModelName(connection.model); setApiKey(connection.apiKey || HORDE_ANON_KEY); if (connection.type === 'kobold') { Connection.getContextLength(connection).then(setContextLength); } else if (connection.type === 'horde') { Connection.getHordeModels() .then(m => setHordeModels(Array.from( m.values()) .sort((a, b) => b.maxContext - a.maxContext || a.name.localeCompare(b.name) ) )); } }, [connection]); useEffect(() => { if (modelName) { Huggingface.findModelTemplate(modelName) .then(template => { if (template) { setModelTemplate(template); } }); } }, [modelName]); const setBackendType = useInputCallback((type) => { switch (type) { case 'kobold': case 'horde': setConnection({ type, instruct, url: connectionUrl, apiKey, model: modelName, }); break; } }, [setConnection, connectionUrl, apiKey, modelName, instruct]); const handleSetInstruct = useInputCallback((instruct: string) => { setConnection({ ...connection, instruct }); }, [setConnection, connection]); const handleBlurUrl = useCallback(() => { const regex = /^(?:http(s?):\/\/)?(.*?)\/?$/i; const url = connectionUrl.replace(regex, 'http$1://$2'); setConnection({ type: 'kobold', instruct, url, apiKey, model: modelName, }); }, [connectionUrl, instruct, setConnection]); const handleBlurHorde = useCallback(() => { setConnection({ type: 'horde', instruct, url: connectionUrl, apiKey, model: modelName, }); }, [apiKey, modelName, instruct, setConnection]); return (
{connection.type === 'kobold' && } {connection.type === 'horde' && <> }
); };