/api-url slash command to get/set server url

28a9c45c310e787f585eb0ea7351a9e2289458e0

Wolfsblvt <wolfsblvt@gmail.com>

2 files changed, +91 -3Ignore whitespace
public/script.js+90 -2
@@ -20,6 +20,8 @@ import {
20 validateTextGenUrl,20 validateTextGenUrl,
21 parseTextgenLogprobs,21 parseTextgenLogprobs,
22 parseTabbyLogprobs,22 parseTabbyLogprobs,
23 textgenerationwebui_settings,
24 SERVER_INPUTS,
23} from './scripts/textgen-settings.js';25} from './scripts/textgen-settings.js';
2426
25const { MANCER, TOGETHERAI, OOBA, VLLM, APHRODITE, TABBY, OLLAMA, INFERMATICAI, DREAMGEN, OPENROUTER, FEATHERLESS } = textgen_types;27const { MANCER, TOGETHERAI, OOBA, VLLM, APHRODITE, TABBY, OLLAMA, INFERMATICAI, DREAMGEN, OPENROUTER, FEATHERLESS } = textgen_types;
@@ -242,7 +244,7 @@ import { DragAndDropHandler } from './scripts/dragdrop.js';
242import { INTERACTABLE_CONTROL_CLASS, initKeyboard } from './scripts/keyboard.js';244import { INTERACTABLE_CONTROL_CLASS, initKeyboard } from './scripts/keyboard.js';
243import { initDynamicStyles } from './scripts/dynamic-styles.js';245import { initDynamicStyles } from './scripts/dynamic-styles.js';
244import { SlashCommandEnumValue, enumTypes } from './scripts/slash-commands/SlashCommandEnumValue.js';246import { SlashCommandEnumValue, enumTypes } from './scripts/slash-commands/SlashCommandEnumValue.js';
245import { enumIcons } from './scripts/slash-commands/SlashCommandCommonEnumsProvider.js';247import { commonEnumProviders, enumIcons } from './scripts/slash-commands/SlashCommandCommonEnumsProvider.js';
246248
247//exporting functions and vars for mods249//exporting functions and vars for mods
248export {250export {
@@ -8520,6 +8522,56 @@ async function connectAPISlash(_, text) {
8520}8522}
85218523
8522/**8524/**
8525 * Sets the API URL and triggers the text generation web UI button click.
8526 *
8527 * @param {object} args - named args
8528 * @param {string?} [args.api=null] - the API name to set/get the URL for
8529 * @param {string?} [args.connect=true] - whether to connect to the API after setting
8530 * @param {string} url - the API URL to set
8531 * @returns {string}
8532 */
8533function setApiUrlCallback({ api = null, connect = 'true' }, url) {
8534 // Do some checks and get the api type we are targeting with this command
8535 if (api && !Object.values(textgen_types).includes(api)) {
8536 toastr.warning(`API '${api}' is not a valid text_gen API.`);
8537 return '';
8538 }
8539 if (!api && !Object.values(textgen_types).includes(textgenerationwebui_settings.type)) {
8540 toastr.warning(`API '${textgenerationwebui_settings.type}' is not a valid text_gen API.`);
8541 return '';
8542 }
8543 if (api && url && isTrueBoolean(connect) && api !== textgenerationwebui_settings.type) {
8544 toastr.warning(`API '${api}' is not the currently selected API, so we cannot do an auto-connect. Consider switching to it via /api beforehand.`);
8545 return '';
8546 }
8547 const type = api || textgenerationwebui_settings.type;
8548
8549 const inputSelector = SERVER_INPUTS[type];
8550 if (!inputSelector) {
8551 toastr.warning(`API '${type}' does not have a server url input.`);
8552 return '';
8553 }
8554
8555 // If no url was provided, return the current one
8556 if (!url) {
8557 return textgenerationwebui_settings.server_urls[type] ?? '';
8558 }
8559
8560 // else, we want to actually set the url
8561 $(inputSelector).val(url).trigger('input');
8562 // trigger blur debounced, so we hide the autocomplete menu
8563 setTimeout(() => $(inputSelector).trigger('blur'), 1);
8564
8565 // Trigger the auto connect via connect button, if requested
8566 if (isTrueBoolean(connect)) {
8567 $('#api_button_textgenerationwebui').trigger('click');
8568 }
8569
8570 // We still re-acquire the value, as it might have been modified by the validation on connect
8571 return textgenerationwebui_settings.server_urls[type] ?? '';
8572}
8573
8574/**
8523 * Imports supported files dropped into the app window.8575 * Imports supported files dropped into the app window.
8524 * @param {File[]} files Array of files to process8576 * @param {File[]} files Array of files to process
8525 * @param {Map<File, string>} [data] Extra data to pass to the import function8577 * @param {Map<File, string>} [data] Extra data to pass to the import function
@@ -8977,11 +9029,11 @@ jQuery(async function () {
8977 SlashCommandParser.addCommandObject(SlashCommand.fromProps({9029 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
8978 name: 'api',9030 name: 'api',
8979 callback: connectAPISlash,9031 callback: connectAPISlash,
9032 returns: 'the current API',
8980 unnamedArgumentList: [9033 unnamedArgumentList: [
8981 SlashCommandArgument.fromProps({9034 SlashCommandArgument.fromProps({
8982 description: 'API to connect to',9035 description: 'API to connect to',
8983 typeList: [ARGUMENT_TYPE.STRING],9036 typeList: [ARGUMENT_TYPE.STRING],
8984 isRequired: false,
8985 enumList: Object.entries(CONNECT_API_MAP).map(([api, { selected }]) =>9037 enumList: Object.entries(CONNECT_API_MAP).map(([api, { selected }]) =>
8986 new SlashCommandEnumValue(api, selected, enumTypes.getBasedOnIndex(uniqueAPIs.findIndex(x => x === selected)),9038 new SlashCommandEnumValue(api, selected, enumTypes.getBasedOnIndex(uniqueAPIs.findIndex(x => x === selected)),
8987 selected[0].toUpperCase() ?? enumIcons.default)),9039 selected[0].toUpperCase() ?? enumIcons.default)),
@@ -8998,6 +9050,42 @@ jQuery(async function () {
8998 `,9050 `,
8999 }));9051 }));
9000 SlashCommandParser.addCommandObject(SlashCommand.fromProps({9052 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
9053 name: 'api-url',
9054 callback: setApiUrlCallback,
9055 returns: 'the current API url',
9056 aliases: ['server'],
9057 namedArgumentList: [
9058 SlashCommandNamedArgument.fromProps({
9059 name: 'api',
9060 description: 'API to set/get the URL for - if not provided, current API is used',
9061 typeList: [ARGUMENT_TYPE.STRING],
9062 enumList: Object.values(textgen_types).map(api => new SlashCommandEnumValue(api, null, enumTypes.enum)),
9063 }),
9064 SlashCommandNamedArgument.fromProps({
9065 name: 'connect',
9066 description: 'Whether to auto-connect to the API after setting the URL',
9067 typeList: [ARGUMENT_TYPE.BOOLEAN],
9068 defaultValue: 'true',
9069 enumList: commonEnumProviders.boolean('trueFalse')(),
9070 }),
9071 ],
9072 unnamedArgumentList: [
9073 SlashCommandArgument.fromProps({
9074 description: 'API url to connect to',
9075 typeList: [ARGUMENT_TYPE.STRING],
9076 }),
9077 ],
9078 helpString: `
9079 <div>
9080 Set the API url / server url for the currently selected API, including the port. If no argument is provided, it will return the current API url.
9081 </div>
9082 <div>
9083 If a manual API is provided to <b>set</b>the URL, make sure to set <code>connect=false</code>, as auto-connect only works for the currently selected API,
9084 or consider switching to it with <code>/api</code> first.
9085 </div>
9086 `,
9087 }));
9088 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
9001 name: 'impersonate',9089 name: 'impersonate',
9002 callback: doImpersonate,9090 callback: doImpersonate,
9003 aliases: ['imp'],9091 aliases: ['imp'],
public/scripts/textgen-settings.js+1 -1
@@ -94,7 +94,7 @@ let DREAMGEN_SERVER = 'https://dreamgen.com';
94let OPENROUTER_SERVER = 'https://openrouter.ai/api';94let OPENROUTER_SERVER = 'https://openrouter.ai/api';
95let FEATHERLESS_SERVER = 'https://api.featherless.ai/v1';95let FEATHERLESS_SERVER = 'https://api.featherless.ai/v1';
9696
97const SERVER_INPUTS = {97export const SERVER_INPUTS = {
98 [textgen_types.OOBA]: '#textgenerationwebui_api_url_text',98 [textgen_types.OOBA]: '#textgenerationwebui_api_url_text',
99 [textgen_types.VLLM]: '#vllm_api_url_text',99 [textgen_types.VLLM]: '#vllm_api_url_text',
100 [textgen_types.APHRODITE]: '#aphrodite_api_url_text',100 [textgen_types.APHRODITE]: '#aphrodite_api_url_text',