Merge pull request #3152 from SillyTavern/getcontext-typed Add types for SillyTavern.getContext

51f89aaf7be1f8d2a71674b466f02c3be5933cac

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

Signed
8 files changed, +232 -148Showing whitespace changes
.eslintrc.cjs+1 -0
@@ -54,6 +54,7 @@ module.exports = {
54 },54 },
55 // These scripts are loaded in HTML; tell ESLint not to complain about them being undefined55 // These scripts are loaded in HTML; tell ESLint not to complain about them being undefined
56 globals: {56 globals: {
57 globalThis: 'readonly',
57 ePub: 'readonly',58 ePub: 'readonly',
58 pdfjsLib: 'readonly',59 pdfjsLib: 'readonly',
59 toastr: 'readonly',60 toastr: 'readonly',
public/global.d.ts+2 -1
@@ -1,4 +1,5 @@
1import libs from './lib';1import libs from './lib';
2import getContext from './scripts/st-context';
23
3// Global namespace modules4// Global namespace modules
4declare var ai;5declare var ai;
@@ -6,7 +7,7 @@ declare var pdfjsLib;
6declare var ePub;7declare var ePub;
78
8declare var SillyTavern: {9declare var SillyTavern: {
9 getContext(): any;10 getContext(): typeof getContext;
10 llm: any;11 llm: any;
11 libs: typeof libs;12 libs: typeof libs;
12};13};
public/jsconfig.json+2 -1
@@ -5,7 +5,8 @@
5 "module": "ESNext",5 "module": "ESNext",
6 "moduleResolution": "node",6 "moduleResolution": "node",
7 "allowUmdGlobalAccess": true,7 "allowUmdGlobalAccess": true,
8 "allowSyntheticDefaultImports": true8 "allowSyntheticDefaultImports": true,
9 "strictBindCallApply": true
9 },10 },
10 "exclude": [11 "exclude": [
11 "**/node_modules/**",12 "**/node_modules/**",
public/script.js+30 -127
@@ -13,7 +13,7 @@ import {
13 default as libs,13 default as libs,
14} from './lib.js';14} from './lib.js';
1515
16import { humanizedDateTime, favsToHotswap, getMessageTimeStamp, dragElement, isMobile, initRossMods, shouldSendOnEnter } from './scripts/RossAscends-mods.js';16import { humanizedDateTime, favsToHotswap, getMessageTimeStamp, dragElement, isMobile, initRossMods } from './scripts/RossAscends-mods.js';
17import { userStatsHandler, statMesProcess, initStats } from './scripts/stats.js';17import { userStatsHandler, statMesProcess, initStats } from './scripts/stats.js';
18import {18import {
19 generateKoboldWithStreaming,19 generateKoboldWithStreaming,
@@ -37,8 +37,6 @@ import {
37 parseTabbyLogprobs,37 parseTabbyLogprobs,
38} from './scripts/textgen-settings.js';38} from './scripts/textgen-settings.js';
3939
40const { MANCER, TOGETHERAI, OOBA, VLLM, APHRODITE, TABBY, OLLAMA, INFERMATICAI, DREAMGEN, OPENROUTER, FEATHERLESS } = textgen_types;
41
42import {40import {
43 world_info,41 world_info,
44 getWorldInfoPrompt,42 getWorldInfoPrompt,
@@ -67,9 +65,7 @@ import {
67 getGroupChat,65 getGroupChat,
68 renameGroupMember,66 renameGroupMember,
69 createNewGroupChat,67 createNewGroupChat,
70 getGroupPastChats,
71 getGroupAvatar,68 getGroupAvatar,
72 openGroupChat,
73 editGroup,69 editGroup,
74 deleteGroupChat,70 deleteGroupChat,
75 renameGroupChat,71 renameGroupChat,
@@ -173,8 +169,8 @@ import {
173} from './scripts/utils.js';169} from './scripts/utils.js';
174import { debounce_timeout } from './scripts/constants.js';170import { debounce_timeout } from './scripts/constants.js';
175171
176import { ModuleWorkerWrapper, doDailyExtensionUpdatesCheck, extension_settings, getContext, initExtensions, loadExtensionSettings, renderExtensionTemplate, renderExtensionTemplateAsync, runGenerationInterceptors, saveMetadataDebounced, writeExtensionField } from './scripts/extensions.js';172import { doDailyExtensionUpdatesCheck, extension_settings, initExtensions, loadExtensionSettings, runGenerationInterceptors, saveMetadataDebounced } from './scripts/extensions.js';
177import { COMMENT_NAME_DEFAULT, executeSlashCommands, executeSlashCommandsOnChatInput, executeSlashCommandsWithOptions, getSlashCommandsHelp, initDefaultSlashCommands, isExecutingCommandsFromChatInput, pauseScriptExecution, processChatSlashCommands, registerSlashCommand, stopScriptExecution } from './scripts/slash-commands.js';173import { COMMENT_NAME_DEFAULT, executeSlashCommandsOnChatInput, getSlashCommandsHelp, initDefaultSlashCommands, isExecutingCommandsFromChatInput, pauseScriptExecution, processChatSlashCommands, stopScriptExecution } from './scripts/slash-commands.js';
178import {174import {
179 tag_map,175 tag_map,
180 tags,176 tags,
@@ -224,8 +220,8 @@ import {
224 instruct_presets,220 instruct_presets,
225 selectContextPreset,221 selectContextPreset,
226} from './scripts/instruct-mode.js';222} from './scripts/instruct-mode.js';
227import { initLocales, t, translate } from './scripts/i18n.js';223import { initLocales, t } from './scripts/i18n.js';
228import { getFriendlyTokenizerName, getTokenCount, getTokenCountAsync, getTokenizerModel, initTokenizers, saveTokenCache, TOKENIZER_SUPPORTED_KEY } from './scripts/tokenizers.js';224import { getFriendlyTokenizerName, getTokenCount, getTokenCountAsync, initTokenizers, saveTokenCache, TOKENIZER_SUPPORTED_KEY } from './scripts/tokenizers.js';
229import {225import {
230 user_avatar,226 user_avatar,
231 getUserAvatars,227 getUserAvatars,
@@ -241,11 +237,11 @@ import { BulkEditOverlay, CharacterContextMenu } from './scripts/BulkEditOverlay
241import { loadFeatherlessModels, loadMancerModels, loadOllamaModels, loadTogetherAIModels, loadInfermaticAIModels, loadOpenRouterModels, loadVllmModels, loadAphroditeModels, loadDreamGenModels, initTextGenModels, loadTabbyModels } from './scripts/textgen-models.js';237import { loadFeatherlessModels, loadMancerModels, loadOllamaModels, loadTogetherAIModels, loadInfermaticAIModels, loadOpenRouterModels, loadVllmModels, loadAphroditeModels, loadDreamGenModels, initTextGenModels, loadTabbyModels } from './scripts/textgen-models.js';
242import { appendFileContent, hasPendingFileAttachment, populateFileAttachment, decodeStyleTags, encodeStyleTags, isExternalMediaAllowed, getCurrentEntityId, preserveNeutralChat, restoreNeutralChat } from './scripts/chats.js';238import { appendFileContent, hasPendingFileAttachment, populateFileAttachment, decodeStyleTags, encodeStyleTags, isExternalMediaAllowed, getCurrentEntityId, preserveNeutralChat, restoreNeutralChat } from './scripts/chats.js';
243import { getPresetManager, initPresetManager } from './scripts/preset-manager.js';239import { getPresetManager, initPresetManager } from './scripts/preset-manager.js';
244import { MacrosParser, evaluateMacros, getLastMessageId, initMacros } from './scripts/macros.js';240import { evaluateMacros, getLastMessageId, initMacros } from './scripts/macros.js';
245import { currentUser, setUserControls } from './scripts/user.js';241import { currentUser, setUserControls } from './scripts/user.js';
246import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup, fixToastrForDialogs } from './scripts/popup.js';242import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup, fixToastrForDialogs } from './scripts/popup.js';
247import { renderTemplate, renderTemplateAsync } from './scripts/templates.js';243import { renderTemplate, renderTemplateAsync } from './scripts/templates.js';
248import { initScrapers, ScraperManager } from './scripts/scrapers.js';244import { initScrapers } from './scripts/scrapers.js';
249import { SlashCommandParser } from './scripts/slash-commands/SlashCommandParser.js';245import { SlashCommandParser } from './scripts/slash-commands/SlashCommandParser.js';
250import { SlashCommand } from './scripts/slash-commands/SlashCommand.js';246import { SlashCommand } from './scripts/slash-commands/SlashCommand.js';
251import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './scripts/slash-commands/SlashCommandArgument.js';247import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './scripts/slash-commands/SlashCommandArgument.js';
@@ -267,6 +263,13 @@ import { initServerHistory } from './scripts/server-history.js';
267import { initSettingsSearch } from './scripts/setting-search.js';263import { initSettingsSearch } from './scripts/setting-search.js';
268import { initBulkEdit } from './scripts/bulk-edit.js';264import { initBulkEdit } from './scripts/bulk-edit.js';
269import { deriveTemplatesFromChatTemplate } from './scripts/chat-templates.js';265import { deriveTemplatesFromChatTemplate } from './scripts/chat-templates.js';
266import { getContext } from './scripts/st-context.js';
267
268// API OBJECT FOR EXTERNAL WIRING
269globalThis.SillyTavern = {
270 libs,
271 getContext,
272};
270273
271//exporting functions and vars for mods274//exporting functions and vars for mods
272export {275export {
@@ -426,10 +429,6 @@ DOMPurify.addHook('uponSanitizeElement', (node, _, config) => {
426 }429 }
427});430});
428431
429// API OBJECT FOR EXTERNAL WIRING
430window['SillyTavern'] = {};
431window['SillyTavern'].libs = libs;
432
433// Event source init432// Event source init
434export const event_types = {433export const event_types = {
435 APP_READY: 'app_ready',434 APP_READY: 'app_ready',
@@ -535,7 +534,7 @@ let displayVersion = 'SillyTavern';
535534
536let generatedPromptCache = '';535let generatedPromptCache = '';
537let generation_started = new Date();536let generation_started = new Date();
538/** @type {import('scripts/char-data.js').v1CharData[]} */537/** @type {import('./scripts/char-data.js').v1CharData[]} */
539export let characters = [];538export let characters = [];
540export let this_chid;539export let this_chid;
541let saveCharactersPage = 0;540let saveCharactersPage = 0;
@@ -811,7 +810,7 @@ export let menu_type = '';
811export let selected_button = ''; //which button pressed810export let selected_button = ''; //which button pressed
812811
813//create pole save812//create pole save
814let create_save = {813export let create_save = {
815 name: '',814 name: '',
816 description: '',815 description: '',
817 creator_notes: '',816 creator_notes: '',
@@ -863,7 +862,7 @@ export let amount_gen = 80; //default max length of AI generated responses
863export let max_context = 2048;862export let max_context = 2048;
864863
865var swipes = true;864var swipes = true;
866let extension_prompts = {};865export let extension_prompts = {};
867866
868export let main_api;// = "kobold";867export let main_api;// = "kobold";
869//novel settings868//novel settings
@@ -1174,7 +1173,7 @@ async function getStatusTextgen() {
1174 return resultCheckStatus();1173 return resultCheckStatus();
1175 }1174 }
11761175
1177 if (textgen_settings.type == OOBA && textgen_settings.bypass_status_check) {1176 if (textgen_settings.type == textgen_types.OOBA && textgen_settings.bypass_status_check) {
1178 setOnlineStatus('Status check bypassed');1177 setOnlineStatus('Status check bypassed');
1179 return resultCheckStatus();1178 return resultCheckStatus();
1180 }1179 }
@@ -1192,34 +1191,34 @@ async function getStatusTextgen() {
11921191
1193 const data = await response.json();1192 const data = await response.json();
11941193
1195 if (textgen_settings.type === MANCER) {1194 if (textgen_settings.type === textgen_types.MANCER) {
1196 loadMancerModels(data?.data);1195 loadMancerModels(data?.data);
1197 setOnlineStatus(textgen_settings.mancer_model);1196 setOnlineStatus(textgen_settings.mancer_model);
1198 } else if (textgen_settings.type === TOGETHERAI) {1197 } else if (textgen_settings.type === textgen_types.TOGETHERAI) {
1199 loadTogetherAIModels(data?.data);1198 loadTogetherAIModels(data?.data);
1200 setOnlineStatus(textgen_settings.togetherai_model);1199 setOnlineStatus(textgen_settings.togetherai_model);
1201 } else if (textgen_settings.type === OLLAMA) {1200 } else if (textgen_settings.type === textgen_types.OLLAMA) {
1202 loadOllamaModels(data?.data);1201 loadOllamaModels(data?.data);
1203 setOnlineStatus(textgen_settings.ollama_model || 'Connected');1202 setOnlineStatus(textgen_settings.ollama_model || 'Connected');
1204 } else if (textgen_settings.type === INFERMATICAI) {1203 } else if (textgen_settings.type === textgen_types.INFERMATICAI) {
1205 loadInfermaticAIModels(data?.data);1204 loadInfermaticAIModels(data?.data);
1206 setOnlineStatus(textgen_settings.infermaticai_model);1205 setOnlineStatus(textgen_settings.infermaticai_model);
1207 } else if (textgen_settings.type === DREAMGEN) {1206 } else if (textgen_settings.type === textgen_types.DREAMGEN) {
1208 loadDreamGenModels(data?.data);1207 loadDreamGenModels(data?.data);
1209 setOnlineStatus(textgen_settings.dreamgen_model);1208 setOnlineStatus(textgen_settings.dreamgen_model);
1210 } else if (textgen_settings.type === OPENROUTER) {1209 } else if (textgen_settings.type === textgen_types.OPENROUTER) {
1211 loadOpenRouterModels(data?.data);1210 loadOpenRouterModels(data?.data);
1212 setOnlineStatus(textgen_settings.openrouter_model);1211 setOnlineStatus(textgen_settings.openrouter_model);
1213 } else if (textgen_settings.type === VLLM) {1212 } else if (textgen_settings.type === textgen_types.VLLM) {
1214 loadVllmModels(data?.data);1213 loadVllmModels(data?.data);
1215 setOnlineStatus(textgen_settings.vllm_model);1214 setOnlineStatus(textgen_settings.vllm_model);
1216 } else if (textgen_settings.type === APHRODITE) {1215 } else if (textgen_settings.type === textgen_types.APHRODITE) {
1217 loadAphroditeModels(data?.data);1216 loadAphroditeModels(data?.data);
1218 setOnlineStatus(textgen_settings.aphrodite_model);1217 setOnlineStatus(textgen_settings.aphrodite_model);
1219 } else if (textgen_settings.type === FEATHERLESS) {1218 } else if (textgen_settings.type === textgen_types.FEATHERLESS) {
1220 loadFeatherlessModels(data?.data);1219 loadFeatherlessModels(data?.data);
1221 setOnlineStatus(textgen_settings.featherless_model);1220 setOnlineStatus(textgen_settings.featherless_model);
1222 } else if (textgen_settings.type === TABBY) {1221 } else if (textgen_settings.type === textgen_types.TABBY) {
1223 loadTabbyModels(data?.data);1222 loadTabbyModels(data?.data);
1224 setOnlineStatus(textgen_settings.tabby_model || data?.result);1223 setOnlineStatus(textgen_settings.tabby_model || data?.result);
1225 } else {1224 } else {
@@ -5541,7 +5540,7 @@ function extractMultiSwipes(data, type) {
5541 return swipes;5540 return swipes;
5542 }5541 }
55435542
5544 if (main_api === 'openai' || (main_api === 'textgenerationwebui' && [MANCER, VLLM, APHRODITE, TABBY, INFERMATICAI].includes(textgen_settings.type))) {5543 if (main_api === 'openai' || (main_api === 'textgenerationwebui' && [textgen_types.MANCER, textgen_types.VLLM, textgen_types.APHRODITE, textgen_types.TABBY, textgen_types.INFERMATICAI].includes(textgen_settings.type))) {
5545 if (!Array.isArray(data.choices)) {5544 if (!Array.isArray(data.choices)) {
5546 return swipes;5545 return swipes;
5547 }5546 }
@@ -5704,7 +5703,7 @@ export function cleanUpMessage(getMessage, isImpersonate, isContinue, displayInc
5704 return getMessage;5703 return getMessage;
5705}5704}
57065705
5707async function saveReply(type, getMessage, fromStreaming, title, swipes) {5706export async function saveReply(type, getMessage, fromStreaming, title, swipes) {
5708 if (type != 'append' && type != 'continue' && type != 'appendFinal' && chat.length && (chat[chat.length - 1]['swipe_id'] === undefined ||5707 if (type != 'append' && type != 'continue' && type != 'appendFinal' && chat.length && (chat[chat.length - 1]['swipe_id'] === undefined ||
5709 chat[chat.length - 1]['is_user'])) {5708 chat[chat.length - 1]['is_user'])) {
5710 type = 'normal';5709 type = 'normal';
@@ -8234,102 +8233,6 @@ async function createOrEditCharacter(e) {
8234 }8233 }
8235}8234}
82368235
8237window['SillyTavern'].getContext = function () {
8238 return {
8239 chat: chat,
8240 characters: characters,
8241 groups: groups,
8242 name1: name1,
8243 name2: name2,
8244 characterId: this_chid,
8245 groupId: selected_group,
8246 chatId: selected_group
8247 ? groups.find(x => x.id == selected_group)?.chat_id
8248 : (this_chid && characters[this_chid] && characters[this_chid].chat),
8249 getCurrentChatId: getCurrentChatId,
8250 getRequestHeaders: getRequestHeaders,
8251 reloadCurrentChat: reloadCurrentChat,
8252 renameChat: renameChat,
8253 saveSettingsDebounced: saveSettingsDebounced,
8254 onlineStatus: online_status,
8255 maxContext: Number(max_context),
8256 chatMetadata: chat_metadata,
8257 streamingProcessor,
8258 eventSource: eventSource,
8259 eventTypes: event_types,
8260 addOneMessage: addOneMessage,
8261 generate: Generate,
8262 sendStreamingRequest: sendStreamingRequest,
8263 sendGenerationRequest: sendGenerationRequest,
8264 stopGeneration: stopGeneration,
8265 getTokenCount: getTokenCount,
8266 extensionPrompts: extension_prompts,
8267 setExtensionPrompt: setExtensionPrompt,
8268 updateChatMetadata: updateChatMetadata,
8269 saveChat: saveChatConditional,
8270 openCharacterChat: openCharacterChat,
8271 openGroupChat: openGroupChat,
8272 saveMetadata: saveMetadata,
8273 sendSystemMessage: sendSystemMessage,
8274 activateSendButtons,
8275 deactivateSendButtons,
8276 saveReply,
8277 substituteParams,
8278 substituteParamsExtended,
8279 SlashCommandParser,
8280 SlashCommand,
8281 SlashCommandArgument,
8282 SlashCommandNamedArgument,
8283 ARGUMENT_TYPE,
8284 executeSlashCommandsWithOptions,
8285 /** @deprecated Use SlashCommandParser.addCommandObject() instead */
8286 registerSlashCommand: registerSlashCommand,
8287 /** @deprecated Use executeSlashCommandWithOptions instead */
8288 executeSlashCommands: executeSlashCommands,
8289 timestampToMoment: timestampToMoment,
8290 /** @deprecated Handlebars for extensions are no longer supported. */
8291 registerHelper: () => { },
8292 registerMacro: MacrosParser.registerMacro.bind(MacrosParser),
8293 unregisterMacro: MacrosParser.unregisterMacro.bind(MacrosParser),
8294 registerFunctionTool: ToolManager.registerFunctionTool.bind(ToolManager),
8295 unregisterFunctionTool: ToolManager.unregisterFunctionTool.bind(ToolManager),
8296 isToolCallingSupported: ToolManager.isToolCallingSupported.bind(ToolManager),
8297 canPerformToolCalls: ToolManager.canPerformToolCalls.bind(ToolManager),
8298 registerDebugFunction: registerDebugFunction,
8299 /** @deprecated Use renderExtensionTemplateAsync instead. */
8300 renderExtensionTemplate: renderExtensionTemplate,
8301 renderExtensionTemplateAsync: renderExtensionTemplateAsync,
8302 registerDataBankScraper: ScraperManager.registerDataBankScraper,
8303 /** @deprecated Use callGenericPopup or Popup instead. */
8304 callPopup: callPopup,
8305 callGenericPopup: callGenericPopup,
8306 showLoader: showLoader,
8307 hideLoader: hideLoader,
8308 mainApi: main_api,
8309 extensionSettings: extension_settings,
8310 ModuleWorkerWrapper: ModuleWorkerWrapper,
8311 getTokenizerModel: getTokenizerModel,
8312 generateQuietPrompt: generateQuietPrompt,
8313 writeExtensionField: writeExtensionField,
8314 getThumbnailUrl: getThumbnailUrl,
8315 selectCharacterById: selectCharacterById,
8316 messageFormatting: messageFormatting,
8317 shouldSendOnEnter: shouldSendOnEnter,
8318 isMobile: isMobile,
8319 t: t,
8320 translate: translate,
8321 tags: tags,
8322 tagMap: tag_map,
8323 menuType: menu_type,
8324 createCharacterData: create_save,
8325 /** @deprecated Legacy snake-case naming, compatibility with old extensions */
8326 event_types: event_types,
8327 Popup: Popup,
8328 POPUP_TYPE: POPUP_TYPE,
8329 POPUP_RESULT: POPUP_RESULT,
8330 };
8331};
8332
8333/**8236/**
8334 * Formats a counter for a swipe view.8237 * Formats a counter for a swipe view.
8335 * @param {number} current The current number of items.8238 * @param {number} current The current number of items.
public/scripts/extensions.js+1 -1
@@ -5,6 +5,7 @@ import { showLoader } from './loader.js';
5import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup } from './popup.js';5import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup } from './popup.js';
6import { renderTemplate, renderTemplateAsync } from './templates.js';6import { renderTemplate, renderTemplateAsync } from './templates.js';
7import { isSubsetOf, setValueByPath } from './utils.js';7import { isSubsetOf, setValueByPath } from './utils.js';
8import { getContext } from './st-context.js';
8export {9export {
9 getContext,10 getContext,
10 getApiUrl,11 getApiUrl,
@@ -174,7 +175,6 @@ const extension_settings = {
174let modules = [];175let modules = [];
175let activeExtensions = new Set();176let activeExtensions = new Set();
176177
177const getContext = () => window['SillyTavern'].getContext();
178const getApiUrl = () => extension_settings.apiUrl;178const getApiUrl = () => extension_settings.apiUrl;
179let connectedToApi = false;179let connectedToApi = false;
180180
public/scripts/st-context.js+171 -0
@@ -0,0 +1,171 @@
1import {
2 activateSendButtons,
3 addOneMessage,
4 callPopup,
5 characters,
6 chat,
7 chat_metadata,
8 create_save,
9 deactivateSendButtons,
10 event_types,
11 eventSource,
12 extension_prompts,
13 Generate,
14 generateQuietPrompt,
15 getCurrentChatId,
16 getRequestHeaders,
17 getThumbnailUrl,
18 main_api,
19 max_context,
20 menu_type,
21 messageFormatting,
22 name1,
23 name2,
24 online_status,
25 openCharacterChat,
26 reloadCurrentChat,
27 renameChat,
28 saveChatConditional,
29 saveMetadata,
30 saveReply,
31 saveSettingsDebounced,
32 selectCharacterById,
33 sendGenerationRequest,
34 sendStreamingRequest,
35 sendSystemMessage,
36 setExtensionPrompt,
37 stopGeneration,
38 streamingProcessor,
39 substituteParams,
40 substituteParamsExtended,
41 this_chid,
42 updateChatMetadata,
43} from '../script.js';
44import {
45 extension_settings,
46 ModuleWorkerWrapper,
47 renderExtensionTemplate,
48 renderExtensionTemplateAsync,
49 writeExtensionField,
50} from './extensions.js';
51import { groups, openGroupChat, selected_group } from './group-chats.js';
52import { t, translate } from './i18n.js';
53import { hideLoader, showLoader } from './loader.js';
54import { MacrosParser } from './macros.js';
55import { oai_settings } from './openai.js';
56import { callGenericPopup, Popup, POPUP_RESULT, POPUP_TYPE } from './popup.js';
57import { power_user, registerDebugFunction } from './power-user.js';
58import { isMobile, shouldSendOnEnter } from './RossAscends-mods.js';
59import { ScraperManager } from './scrapers.js';
60import { executeSlashCommands, executeSlashCommandsWithOptions, registerSlashCommand } from './slash-commands.js';
61import { SlashCommand } from './slash-commands/SlashCommand.js';
62import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './slash-commands/SlashCommandArgument.js';
63import { SlashCommandParser } from './slash-commands/SlashCommandParser.js';
64import { tag_map, tags } from './tags.js';
65import { textgenerationwebui_settings } from './textgen-settings.js';
66import { getTokenCount, getTokenCountAsync, getTokenizerModel } from './tokenizers.js';
67import { ToolManager } from './tool-calling.js';
68import { timestampToMoment } from './utils.js';
69
70export function getContext() {
71 return {
72 chat,
73 characters,
74 groups,
75 name1,
76 name2,
77 characterId: this_chid,
78 groupId: selected_group,
79 chatId: selected_group
80 ? groups.find(x => x.id == selected_group)?.chat_id
81 : (characters[this_chid]?.chat),
82 getCurrentChatId,
83 getRequestHeaders,
84 reloadCurrentChat,
85 renameChat,
86 saveSettingsDebounced,
87 onlineStatus: online_status,
88 maxContext: Number(max_context),
89 chatMetadata: chat_metadata,
90 streamingProcessor,
91 eventSource,
92 eventTypes: event_types,
93 addOneMessage,
94 generate: Generate,
95 sendStreamingRequest,
96 sendGenerationRequest,
97 stopGeneration,
98 /** @deprecated Use getTokenCountAsync instead */
99 getTokenCount,
100 getTokenCountAsync,
101 extensionPrompts: extension_prompts,
102 setExtensionPrompt,
103 updateChatMetadata,
104 saveChat: saveChatConditional,
105 openCharacterChat,
106 openGroupChat,
107 saveMetadata,
108 sendSystemMessage,
109 activateSendButtons,
110 deactivateSendButtons,
111 saveReply,
112 substituteParams,
113 substituteParamsExtended,
114 SlashCommandParser,
115 SlashCommand,
116 SlashCommandArgument,
117 SlashCommandNamedArgument,
118 ARGUMENT_TYPE,
119 executeSlashCommandsWithOptions,
120 /** @deprecated Use SlashCommandParser.addCommandObject() instead */
121 registerSlashCommand,
122 /** @deprecated Use executeSlashCommandWithOptions instead */
123 executeSlashCommands,
124 timestampToMoment,
125 /** @deprecated Handlebars for extensions are no longer supported. */
126 registerHelper: () => { },
127 registerMacro: MacrosParser.registerMacro.bind(MacrosParser),
128 unregisterMacro: MacrosParser.unregisterMacro.bind(MacrosParser),
129 registerFunctionTool: ToolManager.registerFunctionTool.bind(ToolManager),
130 unregisterFunctionTool: ToolManager.unregisterFunctionTool.bind(ToolManager),
131 isToolCallingSupported: ToolManager.isToolCallingSupported.bind(ToolManager),
132 canPerformToolCalls: ToolManager.canPerformToolCalls.bind(ToolManager),
133 registerDebugFunction,
134 /** @deprecated Use renderExtensionTemplateAsync instead. */
135 renderExtensionTemplate,
136 renderExtensionTemplateAsync,
137 registerDataBankScraper: ScraperManager.registerDataBankScraper.bind(ScraperManager),
138 /** @deprecated Use callGenericPopup or Popup instead. */
139 callPopup,
140 callGenericPopup,
141 showLoader,
142 hideLoader,
143 mainApi: main_api,
144 extensionSettings: extension_settings,
145 ModuleWorkerWrapper,
146 getTokenizerModel,
147 generateQuietPrompt,
148 writeExtensionField,
149 getThumbnailUrl,
150 selectCharacterById,
151 messageFormatting,
152 shouldSendOnEnter,
153 isMobile,
154 t,
155 translate,
156 tags,
157 tagMap: tag_map,
158 menuType: menu_type,
159 createCharacterData: create_save,
160 /** @deprecated Legacy snake-case naming, compatibility with old extensions */
161 event_types: event_types,
162 Popup,
163 POPUP_TYPE,
164 POPUP_RESULT,
165 chatCompletionSettings: oai_settings,
166 textCompletionSettings: textgenerationwebui_settings,
167 powerUserSettings: power_user,
168 };
169}
170
171export default getContext;
public/scripts/textgen-settings.js+7 -10
@@ -18,13 +18,6 @@ import { getCurrentDreamGenModelTokenizer, getCurrentOpenRouterModelTokenizer }
18import { ENCODE_TOKENIZERS, TEXTGEN_TOKENIZERS, getTextTokens, tokenizers } from './tokenizers.js';18import { ENCODE_TOKENIZERS, TEXTGEN_TOKENIZERS, getTextTokens, tokenizers } from './tokenizers.js';
19import { getSortableDelay, onlyUnique } from './utils.js';19import { getSortableDelay, onlyUnique } from './utils.js';
2020
21export {
22 settings as textgenerationwebui_settings,
23 loadTextGenSettings,
24 generateTextGenWithStreaming,
25 formatTextGenURL,
26};
27
28export const textgen_types = {21export const textgen_types = {
29 OOBA: 'ooba',22 OOBA: 'ooba',
30 MANCER: 'mancer',23 MANCER: 'mancer',
@@ -197,6 +190,10 @@ const settings = {
197 featherless_model: '',190 featherless_model: '',
198};191};
199192
193export {
194 settings as textgenerationwebui_settings,
195};
196
200export let textgenerationwebui_banned_in_macros = [];197export let textgenerationwebui_banned_in_macros = [];
201198
202export let textgenerationwebui_presets = [];199export let textgenerationwebui_presets = [];
@@ -327,7 +324,7 @@ async function selectPreset(name) {
327 saveSettingsDebounced();324 saveSettingsDebounced();
328}325}
329326
330function formatTextGenURL(value) {327export function formatTextGenURL(value) {
331 try {328 try {
332 const noFormatTypes = [MANCER, TOGETHERAI, INFERMATICAI, DREAMGEN, OPENROUTER];329 const noFormatTypes = [MANCER, TOGETHERAI, INFERMATICAI, DREAMGEN, OPENROUTER];
333 if (noFormatTypes.includes(settings.type)) {330 if (noFormatTypes.includes(settings.type)) {
@@ -465,7 +462,7 @@ function calculateLogitBias() {
465 return result;462 return result;
466}463}
467464
468function loadTextGenSettings(data, loadedSettings) {465export function loadTextGenSettings(data, loadedSettings) {
469 textgenerationwebui_presets = convertPresets(data.textgenerationwebui_presets);466 textgenerationwebui_presets = convertPresets(data.textgenerationwebui_presets);
470 textgenerationwebui_preset_names = data.textgenerationwebui_preset_names ?? [];467 textgenerationwebui_preset_names = data.textgenerationwebui_preset_names ?? [];
471 Object.assign(settings, loadedSettings.textgenerationwebui_settings ?? {});468 Object.assign(settings, loadedSettings.textgenerationwebui_settings ?? {});
@@ -889,7 +886,7 @@ function setSettingByName(setting, value, trigger) {
889 * @returns {Promise<(function(): AsyncGenerator<{swipes: [], text: string, toolCalls: [], logprobs: {token: string, topLogprobs: Candidate[]}|null}, void, *>)|*>}886 * @returns {Promise<(function(): AsyncGenerator<{swipes: [], text: string, toolCalls: [], logprobs: {token: string, topLogprobs: Candidate[]}|null}, void, *>)|*>}
890 * @throws {Error} - If the response status is not OK, or from within the generator887 * @throws {Error} - If the response status is not OK, or from within the generator
891 */888 */
892async function generateTextGenWithStreaming(generate_data, signal) {889export async function generateTextGenWithStreaming(generate_data, signal) {
893 generate_data.stream = true;890 generate_data.stream = true;
894891
895 const response = await fetch('/api/backends/text-completions/generate', {892 const response = await fetch('/api/backends/text-completions/generate', {
public/scripts/tokenizers.js+18 -8
@@ -8,8 +8,6 @@ import { kai_flags } from './kai-settings.js';
8import { textgen_types, textgenerationwebui_settings as textgen_settings, getTextGenServer, getTextGenModel } from './textgen-settings.js';8import { textgen_types, textgenerationwebui_settings as textgen_settings, getTextGenServer, getTextGenModel } from './textgen-settings.js';
9import { getCurrentDreamGenModelTokenizer, getCurrentOpenRouterModelTokenizer, openRouterModels } from './textgen-models.js';9import { getCurrentDreamGenModelTokenizer, getCurrentOpenRouterModelTokenizer, openRouterModels } from './textgen-models.js';
1010
11const { OOBA, TABBY, KOBOLDCPP, VLLM, APHRODITE, LLAMACPP, OPENROUTER, DREAMGEN } = textgen_types;
12
13export const CHARACTERS_PER_TOKEN_RATIO = 3.35;11export const CHARACTERS_PER_TOKEN_RATIO = 3.35;
14export const TOKENIZER_WARNING_KEY = 'tokenizationWarningShown';12export const TOKENIZER_WARNING_KEY = 'tokenizationWarningShown';
15export const TOKENIZER_SUPPORTED_KEY = 'tokenizationSupported';13export const TOKENIZER_SUPPORTED_KEY = 'tokenizationSupported';
@@ -52,8 +50,12 @@ export const ENCODE_TOKENIZERS = [
52 //tokenizers.NERD2,50 //tokenizers.NERD2,
53];51];
5452
55// A list of Text Completion sources that support remote tokenization.53/**
56export const TEXTGEN_TOKENIZERS = [OOBA, TABBY, KOBOLDCPP, LLAMACPP, VLLM, APHRODITE];54 * A list of Text Completion sources that support remote tokenization.
55 * Populated in initTokenziers due to circular dependencies.
56 * @type {string[]}
57 */
58export const TEXTGEN_TOKENIZERS = [];
5759
58const TOKENIZER_URLS = {60const TOKENIZER_URLS = {
59 [tokenizers.GPT2]: {61 [tokenizers.GPT2]: {
@@ -287,7 +289,7 @@ export function getTokenizerBestMatch(forApi) {
287 const hasTokenizerError = sessionStorage.getItem(TOKENIZER_WARNING_KEY);289 const hasTokenizerError = sessionStorage.getItem(TOKENIZER_WARNING_KEY);
288 const hasValidEndpoint = sessionStorage.getItem(TOKENIZER_SUPPORTED_KEY);290 const hasValidEndpoint = sessionStorage.getItem(TOKENIZER_SUPPORTED_KEY);
289 const isConnected = online_status !== 'no_connection';291 const isConnected = online_status !== 'no_connection';
290 const isTokenizerSupported = TEXTGEN_TOKENIZERS.includes(textgen_settings.type) && (textgen_settings.type !== OOBA || hasValidEndpoint);292 const isTokenizerSupported = TEXTGEN_TOKENIZERS.includes(textgen_settings.type) && (textgen_settings.type !== textgen_types.OOBA || hasValidEndpoint);
291293
292 if (!hasTokenizerError && isConnected) {294 if (!hasTokenizerError && isConnected) {
293 if (forApi === 'kobold' && kai_flags.can_use_tokenization) {295 if (forApi === 'kobold' && kai_flags.can_use_tokenization) {
@@ -297,10 +299,10 @@ export function getTokenizerBestMatch(forApi) {
297 if (forApi === 'textgenerationwebui' && isTokenizerSupported) {299 if (forApi === 'textgenerationwebui' && isTokenizerSupported) {
298 return tokenizers.API_TEXTGENERATIONWEBUI;300 return tokenizers.API_TEXTGENERATIONWEBUI;
299 }301 }
300 if (forApi === 'textgenerationwebui' && textgen_settings.type === OPENROUTER) {302 if (forApi === 'textgenerationwebui' && textgen_settings.type === textgen_types.OPENROUTER) {
301 return getCurrentOpenRouterModelTokenizer();303 return getCurrentOpenRouterModelTokenizer();
302 }304 }
303 if (forApi === 'textgenerationwebui' && textgen_settings.type === DREAMGEN) {305 if (forApi === 'textgenerationwebui' && textgen_settings.type === textgen_types.DREAMGEN) {
304 return getCurrentDreamGenModelTokenizer();306 return getCurrentDreamGenModelTokenizer();
305 }307 }
306 }308 }
@@ -576,7 +578,7 @@ export function getTokenizerModel() {
576578
577 // And for OpenRouter (if not a site model, then it's impossible to determine the tokenizer)579 // And for OpenRouter (if not a site model, then it's impossible to determine the tokenizer)
578 if (main_api == 'openai' && oai_settings.chat_completion_source == chat_completion_sources.OPENROUTER && oai_settings.openrouter_model ||580 if (main_api == 'openai' && oai_settings.chat_completion_source == chat_completion_sources.OPENROUTER && oai_settings.openrouter_model ||
579 main_api == 'textgenerationwebui' && textgen_settings.type === OPENROUTER && textgen_settings.openrouter_model) {581 main_api == 'textgenerationwebui' && textgen_settings.type === textgen_types.OPENROUTER && textgen_settings.openrouter_model) {
580 const model = main_api == 'openai'582 const model = main_api == 'openai'
581 ? model_list.find(x => x.id === oai_settings.openrouter_model)583 ? model_list.find(x => x.id === oai_settings.openrouter_model)
582 : openRouterModels.find(x => x.id === textgen_settings.openrouter_model);584 : openRouterModels.find(x => x.id === textgen_settings.openrouter_model);
@@ -1121,6 +1123,14 @@ export function decodeTextTokens(tokenizerType, ids) {
1121}1123}
11221124
1123export async function initTokenizers() {1125export async function initTokenizers() {
1126 TEXTGEN_TOKENIZERS.push(
1127 textgen_types.OOBA,
1128 textgen_types.TABBY,
1129 textgen_types.KOBOLDCPP,
1130 textgen_types.LLAMACPP,
1131 textgen_types.VLLM,
1132 textgen_types.APHRODITE,
1133 );
1124 await loadTokenCache();1134 await loadTokenCache();
1125 registerDebugFunction('resetTokenCache', 'Reset token cache', 'Purges the calculated token counts. Use this if you want to force a full re-tokenization of all chats or suspect the token counts are wrong.', resetTokenCache);1135 registerDebugFunction('resetTokenCache', 'Reset token cache', 'Purges the calculated token counts. Use this if you want to force a full re-tokenization of all chats or suspect the token counts are wrong.', resetTokenCache);
1126}1136}