diff --git a/public/script.js b/public/script.js index 78e989a0c..453c23915 100644 --- a/public/script.js +++ b/public/script.js @@ -867,21 +867,19 @@ export async function clearItemizedPrompts() { } } -async function getStatusKobold() { - if (main_api == 'koboldhorde') { - try { - const hordeStatus = await checkHordeStatus(); - online_status = hordeStatus ? 'Connected' : 'no_connection'; - } - catch { - online_status = 'no_connection'; - } - - return resultCheckStatus(); +async function getStatusHorde() { + try { + const hordeStatus = await checkHordeStatus(); + online_status = hordeStatus ? 'Connected' : 'no_connection'; + } + catch { + online_status = 'no_connection'; } - const url = '/getstatus'; + return resultCheckStatus(); +} +async function getStatusKobold() { let endpoint = api_server; if (!endpoint) { @@ -890,7 +888,7 @@ async function getStatusKobold() { } try { - const response = await fetch(url, { + const response = await fetch('/getstatus', { method: 'POST', headers: getRequestHeaders(), body: JSON.stringify({ @@ -902,18 +900,17 @@ async function getStatusKobold() { const data = await response.json(); + online_status = data?.model ?? 'no_connection'; - online_status = data?.result; - - if (!online_status) { - online_status = 'no_connection'; + if (!data.koboldUnitedVersion) { + throw new Error('Missing mandatory Kobold version in data:', data); } // Determine instruct mode preset autoSelectInstructPreset(online_status); // determine if we can use stop sequence and streaming - setKoboldFlags(data.version, data.koboldVersion); + setKoboldFlags(data.koboldUnitedVersion, data.koboldCppVersion); // We didn't get a 200 status code, but the endpoint has an explanation. Which means it DID connect, but I digress. if (online_status === 'no_connection' && data.response) { @@ -5362,7 +5359,7 @@ function changeMainAPI() { } if (main_api == 'koboldhorde') { - getStatusKobold(); + getStatusHorde(); getHordeModels(); } @@ -7268,7 +7265,7 @@ const swipe_right = () => { } if (isHordeGenerationNotAllowed()) { - return; + return unblockGeneration(); } const swipe_duration = 200; diff --git a/public/scripts/kai-settings.js b/public/scripts/kai-settings.js index 9183a8b0d..7bdfc5f26 100644 --- a/public/scripts/kai-settings.js +++ b/public/scripts/kai-settings.js @@ -317,87 +317,24 @@ const sliders = [ }, ]; -export function setKoboldFlags(version, koboldVersion) { - kai_flags.can_use_stop_sequence = canUseKoboldStopSequence(version); - kai_flags.can_use_streaming = canUseKoboldStreaming(koboldVersion); - kai_flags.can_use_tokenization = canUseKoboldTokenization(koboldVersion); - kai_flags.can_use_default_badwordsids = canUseDefaultBadwordIds(version); - kai_flags.can_use_mirostat = canUseMirostat(koboldVersion); - kai_flags.can_use_grammar = canUseGrammar(koboldVersion); - kai_flags.can_use_min_p = canUseMinP(koboldVersion); +export function setKoboldFlags(koboldUnitedVersion, koboldCppVersion) { + kai_flags.can_use_stop_sequence = versionCompare(koboldUnitedVersion, MIN_STOP_SEQUENCE_VERSION); + kai_flags.can_use_streaming = versionCompare(koboldCppVersion, MIN_STREAMING_KCPPVERSION); + kai_flags.can_use_tokenization = versionCompare(koboldCppVersion, MIN_TOKENIZATION_KCPPVERSION); + kai_flags.can_use_default_badwordsids = versionCompare(koboldUnitedVersion, MIN_UNBAN_VERSION); + kai_flags.can_use_mirostat = versionCompare(koboldCppVersion, MIN_MIROSTAT_KCPPVERSION); + kai_flags.can_use_grammar = versionCompare(koboldCppVersion, MIN_GRAMMAR_KCPPVERSION); + kai_flags.can_use_min_p = versionCompare(koboldCppVersion, MIN_MIN_P_KCPPVERSION); } /** - * Determines if the Kobold stop sequence can be used with the given version. - * @param {string} version KoboldAI version to check. - * @returns {boolean} True if the Kobold stop sequence can be used, false otherwise. + * Compares two version numbers, returning true if srcVersion >= minVersion + * @param {string} srcVersion The current version. + * @param {string} minVersion The target version number to test against + * @returns {boolean} True if srcVersion >= minVersion, false if not */ -function canUseKoboldStopSequence(version) { - return (version || '0.0.0').localeCompare(MIN_STOP_SEQUENCE_VERSION, undefined, { numeric: true, sensitivity: 'base' }) > -1; -} - -/** - * Determines if the Kobold default badword ids can be used with the given version. - * @param {string} version KoboldAI version to check. - * @returns {boolean} True if the Kobold default badword ids can be used, false otherwise. - */ -function canUseDefaultBadwordIds(version) { - return (version || '0.0.0').localeCompare(MIN_UNBAN_VERSION, undefined, { numeric: true, sensitivity: 'base' }) > -1; -} - -/** - * Determines if the Kobold streaming API can be used with the given version. - * @param {{ result: string; version: string; }} koboldVersion KoboldAI version object. - * @returns {boolean} True if the Kobold streaming API can be used, false otherwise. - */ -function canUseKoboldStreaming(koboldVersion) { - if (koboldVersion && koboldVersion.result == 'KoboldCpp') { - return (koboldVersion.version || '0.0').localeCompare(MIN_STREAMING_KCPPVERSION, undefined, { numeric: true, sensitivity: 'base' }) > -1; - } else return false; -} - -/** - * Determines if the Kobold tokenization API can be used with the given version. - * @param {{ result: string; version: string; }} koboldVersion KoboldAI version object. - * @returns {boolean} True if the Kobold tokenization API can be used, false otherwise. - */ -function canUseKoboldTokenization(koboldVersion) { - if (koboldVersion && koboldVersion.result == 'KoboldCpp') { - return (koboldVersion.version || '0.0').localeCompare(MIN_TOKENIZATION_KCPPVERSION, undefined, { numeric: true, sensitivity: 'base' }) > -1; - } else return false; -} - -/** - * Determines if the Kobold mirostat can be used with the given version. - * @param {{result: string; version: string;}} koboldVersion KoboldAI version object. - * @returns {boolean} True if the Kobold mirostat API can be used, false otherwise. - */ -function canUseMirostat(koboldVersion) { - if (koboldVersion && koboldVersion.result == 'KoboldCpp') { - return (koboldVersion.version || '0.0').localeCompare(MIN_MIROSTAT_KCPPVERSION, undefined, { numeric: true, sensitivity: 'base' }) > -1; - } else return false; -} - -/** - * Determines if the Kobold grammar can be used with the given version. - * @param {{result: string; version:string;}} koboldVersion KoboldAI version object. - * @returns {boolean} True if the Kobold grammar can be used, false otherwise. - */ -function canUseGrammar(koboldVersion) { - if (koboldVersion && koboldVersion.result == 'KoboldCpp') { - return (koboldVersion.version || '0.0').localeCompare(MIN_GRAMMAR_KCPPVERSION, undefined, { numeric: true, sensitivity: 'base' }) > -1; - } else return false; -} - -/** - * Determines if the Kobold min_p can be used with the given version. - * @param {{result:string, version:string;}} koboldVersion KoboldAI version object. - * @returns {boolean} True if the Kobold min_p can be used, false otherwise. - */ -function canUseMinP(koboldVersion) { - if (koboldVersion && koboldVersion.result == 'KoboldCpp') { - return (koboldVersion.version || '0.0').localeCompare(MIN_MIN_P_KCPPVERSION, undefined, { numeric: true, sensitivity: 'base' }) > -1; - } else return false; +function versionCompare(srcVersion, minVersion) { + return (srcVersion || '0.0.0').localeCompare(minVersion, undefined, { numeric: true, sensitivity: 'base' }) > -1; } /** diff --git a/server.js b/server.js index a2ca26d6c..ec9fb03aa 100644 --- a/server.js +++ b/server.js @@ -657,47 +657,37 @@ app.post('/getstatus', jsonParser, async function (request, response) { setAdditionalHeaders(request, args, api_server); - const url = api_server + '/v1/model'; - let version = ''; - let koboldVersion = {}; + const result = {}; - if (request.body.main_api == 'kobold') { - try { - version = (await fetchJSON(api_server + '/v1/info/version')).result; - } - catch { - version = '0.0.0'; - } - try { - koboldVersion = (await fetchJSON(api_server + '/extra/version')); - } - catch { - koboldVersion = { - result: 'Kobold', - version: '0.0', - }; - } - } + const [koboldUnitedResponse, koboldExtraResponse, koboldModelResponse] = await Promise.all([ + // We catch errors both from the response not having a successful HTTP status and from JSON parsing failing - try { - let data = await fetchJSON(url, args); + // Kobold United API version + fetch(`${api_server}/v1/info/version`).then(response => { + if (!response.ok) throw new Error(`Kobold API error: ${response.status, response.statusText}`); + return response.json(); + }).catch(() => ({ result: '0.0.0' })), - if (!data || typeof data !== 'object') { - data = {}; - } + // KoboldCpp version + fetch(`${api_server}/extra/version`).then(response => { + if (!response.ok) throw new Error(`Kobold API error: ${response.status, response.statusText}`); + return response.json(); + }).catch(() => ({ version: '0.0' })), - if (data.result == 'ReadOnly') { - data.result = 'no_connection'; - } + // Current model + fetch(`${api_server}/v1/model`).then(response => { + if (!response.ok) throw new Error(`Kobold API error: ${response.status, response.statusText}`); + return response.json(); + }).catch(() => null), + ]); - data.version = version; - data.koboldVersion = koboldVersion; + result.koboldUnitedVersion = koboldUnitedResponse.result; + result.koboldCppVersion = koboldExtraResponse.result; + result.model = !koboldModelResponse || koboldModelResponse.result === 'ReadOnly' ? + 'no_connection' : + koboldModelResponse.result; - return response.send(data); - } catch (error) { - console.log(error); - return response.send({ result: 'no_connection' }); - } + response.send(result); }); @@ -1753,27 +1743,6 @@ redirect('/delbackground', '/api/backgrounds/delete'); redirect('/renamebackground', '/api/backgrounds/rename'); redirect('/downloadbackground', '/api/backgrounds/upload'); // yes, the downloadbackground endpoint actually uploads one -// ** REST CLIENT ASYNC WRAPPERS ** - -/** - * Convenience function for fetch requests (default GET) returning as JSON. - * @param {string} url - * @param {import('node-fetch').RequestInit} args - */ -async function fetchJSON(url, args = {}) { - if (args.method === undefined) args.method = 'GET'; - const response = await fetch(url, args); - - if (response.ok) { - const data = await response.json(); - return data; - } - - throw response; -} - -// ** END ** - // OpenAI API app.use('/api/openai', require('./src/endpoints/openai').router);