/model: Better support for write-in controls

c76fc7d23c95ea663d22b594d23a965d33dd7a8c

Cohee <18619528+Cohee1207@users.noreply.github.com>

1 files changed, +37 -10Showing whitespace changes
public/scripts/slash-commands.js+37 -10
@@ -55,7 +55,7 @@ import { autoSelectPersona, retriggerFirstMessageOnEmptyChat, setPersonaLockStat
5555import { addEphemeralStoppingString, chat_styles, flushEphemeralStoppingStrings, power_user } from './power-user.js';
5656import { SERVER_INPUTS, textgen_types, textgenerationwebui_settings } from './textgen-settings.js';
5757import { decodeTextTokens, getAvailableTokenizers, getFriendlyTokenizerName, getTextTokens, getTokenCountAsync, selectTokenizer } from './tokenizers.js';
5858import { debounce, delay, equalsIgnoreCaseAndAccents, findChar, getCharIndex, isFalseBoolean, isTrueBoolean, onlyUnique, showFontAwesomePicker, stringToRange, trimToEndSentence, trimToStartSentence, waitUntilCondition } from './utils.js';
5959import { registerVariableCommands, resolveVariable } from './variables.js';
6060import { background_settings } from './backgrounds.js';
6161import { SlashCommandClosure } from './slash-commands/SlashCommandClosure.js';
@@ -3542,11 +3542,12 @@ function setBackgroundCallback(_, bg) {
35423542 * Retrieves the available model options based on the currently selected main API and its subtype
35433543 * @param {boolean} quiet - Whether to suppress toasts
35443544 *
35453545 * @returns {{control: HTMLSelectElement|HTMLInputElement, options: HTMLOptionElement[]}?} An array of objects representing the available model options, or null if not supported
35463546 */
35473547function getModelOptions(quiet) {
35483548 const nullResult = { control: null, options: null };
35493549 const modelSelectMap = [
3550+ { id: 'custom_model_textgenerationwebui', api: 'textgenerationwebui', type: textgen_types.OOBA },
35503551 { id: 'model_togetherai_select', api: 'textgenerationwebui', type: textgen_types.TOGETHERAI },
35513552 { id: 'openrouter_model', api: 'textgenerationwebui', type: textgen_types.OPENROUTER },
35523553 { id: 'model_infermaticai_select', api: 'textgenerationwebui', type: textgen_types.INFERMATICAI },
@@ -3563,7 +3564,7 @@ function getModelOptions(quiet) {
35633564 { id: 'model_ai21_select', api: 'openai', type: chat_completion_sources.AI21 },
35643565 { id: 'model_google_select', api: 'openai', type: chat_completion_sources.MAKERSUITE },
35653566 { id: 'model_mistralai_select', api: 'openai', type: chat_completion_sources.MISTRALAI },
35663567 { id: 'model_custom_selectcustom_model_id', api: 'openai', type: chat_completion_sources.CUSTOM },
35673568 { id: 'model_cohere_select', api: 'openai', type: chat_completion_sources.COHERE },
35683569 { id: 'model_perplexity_select', api: 'openai', type: chat_completion_sources.PERPLEXITY },
35693570 { id: 'model_groq_select', api: 'openai', type: chat_completion_sources.GROQ },
@@ -3594,12 +3595,31 @@ function getModelOptions(quiet) {
35943595
35953596 const modelSelectControl = document.getElementById(modelSelectItem);
35963597
35973598 if (!(modelSelectControl instanceof HTMLSelectElement) && !(modelSelectControl instanceof HTMLInputElement)) {
35983599 !quiet && toastr.error(`Model select control not found: ${main_api}[${apiSubType}]`);
35993600 return nullResult;
36003601 }
36013602
3602- const options = Array.from(modelSelectControl.options).filter(x => x.value);
3603+ /**
3604+ * Get options from a HTMLSelectElement or HTMLInputElement with a list.
3605+ * @param {HTMLSelectElement | HTMLInputElement} control Control containing the options
3606+ * @returns {HTMLOptionElement[]} Array of options
3607+ */
3608+ const getOptions = (control) => {
3609+ if (control instanceof HTMLSelectElement) {
3610+ return Array.from(control.options);
3611+ }
3612+
3613+ const valueOption = new Option(control.value, control.value);
3614+
3615+ if (control instanceof HTMLInputElement && control.list instanceof HTMLDataListElement) {
3616+ return [valueOption, ...Array.from(control.list.options)];
3617+ }
3618+
3619+ return [valueOption];
3620+ };
3621+
3622+ const options = getOptions(modelSelectControl).filter(x => x.value).filter(onlyUnique);
36033623 return { control: modelSelectControl, options };
36043624}
36053625
@@ -3618,11 +3638,6 @@ function modelCallback(args, model) {
36183638 return '';
36193639 }
36203640
3621- if (!options.length) {
3622- !quiet && toastr.warning('No model options found. Check your API settings.');
3623- return '';
3624- }
3625-
36263641 model = String(model || '').trim();
36273642
36283643 if (!model) {
@@ -3631,6 +3646,18 @@ function modelCallback(args, model) {
36313646
36323647 console.log('Set model to ' + model);
36333648
3649+ if (modelSelectControl instanceof HTMLInputElement) {
3650+ modelSelectControl.value = model;
3651+ $(modelSelectControl).trigger('input');
3652+ !quiet && toastr.success(`Model set to "${model}"`);
3653+ return model;
3654+ }
3655+
3656+ if (!options.length) {
3657+ !quiet && toastr.warning('No model options found. Check your API settings.');
3658+ return '';
3659+ }
3660+
36343661 let newSelectedOption = null;
36353662
36363663 const fuse = new Fuse(options, { keys: ['text', 'value'] });