mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Merge branch 'staging' into integrity
This commit is contained in:
@@ -5,6 +5,7 @@ import { saveMetadataDebounced } from './extensions.js';
|
||||
import { SlashCommand } from './slash-commands/SlashCommand.js';
|
||||
import { SlashCommandParser } from './slash-commands/SlashCommandParser.js';
|
||||
import { flashHighlight, stringFormat } from './utils.js';
|
||||
import { t } from './i18n.js';
|
||||
|
||||
const BG_METADATA_KEY = 'custom_background';
|
||||
const LIST_METADATA_KEY = 'chat_backgrounds';
|
||||
@@ -243,7 +244,7 @@ async function getNewBackgroundName(referenceElement) {
|
||||
const fileExtension = oldBg.split('.').pop();
|
||||
const fileNameBase = isCustom ? oldBg.split('/').pop() : oldBg;
|
||||
const oldBgExtensionless = fileNameBase.replace(`.${fileExtension}`, '');
|
||||
const newBgExtensionless = await callPopup('<h3>Enter new background name:</h3>', 'input', oldBgExtensionless);
|
||||
const newBgExtensionless = await callPopup('<h3>' + t`Enter new background name:` + '</h3>', 'input', oldBgExtensionless);
|
||||
|
||||
if (!newBgExtensionless) {
|
||||
console.debug('no new_bg_extensionless');
|
||||
|
@@ -358,7 +358,7 @@ export async function convertSoloToGroupChat() {
|
||||
// Click on the freshly selected group to open it
|
||||
await openGroupById(group.id);
|
||||
|
||||
toastr.success('The chat has been successfully converted!');
|
||||
toastr.success(t`The chat has been successfully converted!`);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -41,6 +41,7 @@ import { formatInstructModeChat, formatInstructModePrompt, names_behavior_types
|
||||
* @property {string} chat_completion_source - Source provider for chat completion
|
||||
* @property {number} max_tokens - Maximum number of tokens to generate
|
||||
* @property {number} [temperature] - Optional temperature parameter for response randomness
|
||||
* @property {string} [custom_url] - Optional custom URL for chat completion
|
||||
*/
|
||||
|
||||
/** @typedef {Record<string, any> & ChatCompletionPayloadBase} ChatCompletionPayload */
|
||||
@@ -264,7 +265,7 @@ export class ChatCompletionService {
|
||||
* @param {ChatCompletionPayload} custom
|
||||
* @returns {ChatCompletionPayload}
|
||||
*/
|
||||
static createRequestData({ messages, model, chat_completion_source, max_tokens, temperature, ...props }) {
|
||||
static createRequestData({ messages, model, chat_completion_source, max_tokens, temperature, custom_url, ...props }) {
|
||||
const payload = {
|
||||
...props,
|
||||
messages,
|
||||
@@ -272,6 +273,7 @@ export class ChatCompletionService {
|
||||
chat_completion_source,
|
||||
max_tokens,
|
||||
temperature,
|
||||
custom_url,
|
||||
stream: false,
|
||||
};
|
||||
|
||||
|
@@ -424,7 +424,7 @@ jQuery(async () => {
|
||||
installHintButton.on('click', async function () {
|
||||
const installButton = $('#third_party_extension_button');
|
||||
flashHighlight(installButton, 5000);
|
||||
toastr.info('Click the flashing button to install extensions.', 'How to install extensions?');
|
||||
toastr.info(t`Click the flashing button to install extensions.`, t`How to install extensions?`);
|
||||
});
|
||||
|
||||
const connectButton = windowHtml.find('#assets-connect-button');
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<div id="attachFile" class="list-group-item flex-container flexGap5" title="Attach a file or image to a current chat.">
|
||||
<div id="attachFile" class="list-group-item flex-container flexGap5" data-i18n="[title]Attach a file or image to a current chat." title="Attach a file or image to a current chat.">
|
||||
<div class="fa-fw fa-solid fa-paperclip extensionsMenuExtensionButton"></div>
|
||||
<span data-i18n="Attach a File">Attach a File</span>
|
||||
</div>
|
||||
|
@@ -39,6 +39,7 @@ const CC_COMMANDS = [
|
||||
'proxy',
|
||||
'stop-strings',
|
||||
'start-reply-with',
|
||||
'reasoning-template',
|
||||
];
|
||||
|
||||
const TC_COMMANDS = [
|
||||
@@ -54,6 +55,7 @@ const TC_COMMANDS = [
|
||||
'tokenizer',
|
||||
'stop-strings',
|
||||
'start-reply-with',
|
||||
'reasoning-template',
|
||||
];
|
||||
|
||||
const FANCY_NAMES = {
|
||||
@@ -70,6 +72,7 @@ const FANCY_NAMES = {
|
||||
'tokenizer': 'Tokenizer',
|
||||
'stop-strings': 'Custom Stopping Strings',
|
||||
'start-reply-with': 'Start Reply With',
|
||||
'reasoning-template': 'Reasoning Template',
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -154,6 +157,7 @@ const profilesProvider = () => [
|
||||
* @property {string} [tokenizer] Tokenizer
|
||||
* @property {string} [stop-strings] Custom Stopping Strings
|
||||
* @property {string} [start-reply-with] Start Reply With
|
||||
* @property {string} [reasoning-template] Reasoning Template
|
||||
* @property {string[]} [exclude] Commands to exclude
|
||||
*/
|
||||
|
||||
|
@@ -2154,7 +2154,7 @@ function migrateSettings() {
|
||||
imgElement.src = '';
|
||||
}
|
||||
|
||||
setExpressionOverrideHtml();
|
||||
setExpressionOverrideHtml(true); // force-clear, as the character might not have an override defined
|
||||
|
||||
if (isVisualNovelMode()) {
|
||||
$('#visual-novel-wrapper').empty();
|
||||
|
@@ -19,7 +19,7 @@
|
||||
<div id="regex_info_block_wrapper">
|
||||
<div id="regex_info_block" class="info-block"></div>
|
||||
<a id="regex_info_block_flags_hint" href="https://docs.sillytavern.app/extensions/regex/#flags" target="_blank" rel="noopener noreferrer">
|
||||
<i class="fa-solid fa-circle-info" title="Click here to learn more about regex flags."></i>
|
||||
<i class="fa-solid fa-circle-info" data-i18n="[title]ext_regex_flags_help" title="Click here to learn more about regex flags."></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
</label>
|
||||
<span>
|
||||
<small data-i18n="ext_regex_other_options" data-i18n="Ephemerality">Ephemerality</small>
|
||||
<span class="fa-solid fa-circle-question note-link-span" title="By default, regex scripts alter the chat file directly and irreversibly. Enabling either (or both) of the options below will prevent chat file alteration, while still altering the specified item(s)."></span>
|
||||
<span class="fa-solid fa-circle-question note-link-span" data-i18n="[title]ext_regex_other_options_desc" title="By default, regex scripts alter the chat file directly and irreversibly. Enabling either (or both) of the options below will prevent chat file alteration, while still altering the specified item(s)."></span>
|
||||
</span>
|
||||
<label class="checkbox flex-container" data-i18n="[title]ext_regex_only_format_visual_desc" title="Chat history file contents won't change, but regex will be applied to the messages displayed in the Chat UI.">
|
||||
<input type="checkbox" name="only_format_display" />
|
||||
|
@@ -398,7 +398,7 @@ function runRegexCallback(args, value) {
|
||||
for (const script of scripts) {
|
||||
if (script.scriptName.toLowerCase() === scriptName.toLowerCase()) {
|
||||
if (script.disabled) {
|
||||
toastr.warning(`Regex script "${scriptName}" is disabled.`);
|
||||
toastr.warning(t`Regex script "${scriptName}" is disabled.`);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@@ -323,6 +323,7 @@ export class ConnectionManagerRequestService {
|
||||
max_tokens: maxTokens,
|
||||
model: profile.model,
|
||||
chat_completion_source: selectedApiMap.source,
|
||||
custom_url: profile['api-url'],
|
||||
}, {
|
||||
presetName: includePreset ? profile.preset : undefined,
|
||||
}, extractData);
|
||||
|
@@ -1207,8 +1207,8 @@ jQuery(async function () {
|
||||
eventSource.on(event_types.GROUP_UPDATED, onChatChanged);
|
||||
eventSource.on(event_types.GENERATION_STARTED, onGenerationStarted);
|
||||
eventSource.on(event_types.GENERATION_ENDED, onGenerationEnded);
|
||||
eventSource.makeLast(event_types.CHARACTER_MESSAGE_RENDERED, onMessageEvent);
|
||||
eventSource.makeLast(event_types.USER_MESSAGE_RENDERED, onMessageEvent);
|
||||
eventSource.makeLast(event_types.CHARACTER_MESSAGE_RENDERED, (messageId) => onMessageEvent(messageId));
|
||||
eventSource.makeLast(event_types.USER_MESSAGE_RENDERED, (messageId) => onMessageEvent(messageId));
|
||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||
name: 'speak',
|
||||
callback: async (args, value) => {
|
||||
|
@@ -696,7 +696,7 @@ export function getGroupBlock(group) {
|
||||
template.find('.group_fav_icon').css('display', 'none');
|
||||
template.addClass(group.fav ? 'is_fav' : '');
|
||||
template.find('.ch_fav').val(group.fav);
|
||||
template.find('.group_select_counter').text(`${count} ${count != 1 ? 'characters' : 'character'}`);
|
||||
template.find('.group_select_counter').text(count + ' ' + (count != 1 ? t`characters` : t`character`));
|
||||
template.find('.group_select_block_list').text(namesList.join(', '));
|
||||
|
||||
// Display inline tags
|
||||
|
@@ -10,6 +10,7 @@ import { SECRET_KEYS, writeSecret } from './secrets.js';
|
||||
import { delay } from './utils.js';
|
||||
import { isMobile } from './RossAscends-mods.js';
|
||||
import { autoSelectInstructPreset } from './instruct-mode.js';
|
||||
import { t } from './i18n.js';
|
||||
|
||||
export {
|
||||
horde_settings,
|
||||
@@ -169,7 +170,7 @@ async function adjustHordeGenerationParams(max_context_length, max_length) {
|
||||
}
|
||||
}
|
||||
console.log(maxContextLength, maxLength);
|
||||
$('#adjustedHordeParams').text(`Context: ${maxContextLength}, Response: ${maxLength}`);
|
||||
$('#adjustedHordeParams').text(t`Context` + `: ${maxContextLength}, ` + t`Response` + `: ${maxLength}`);
|
||||
return { maxContextLength, maxLength };
|
||||
}
|
||||
|
||||
@@ -177,7 +178,7 @@ function setContextSizePreview() {
|
||||
if (horde_settings.models.length) {
|
||||
adjustHordeGenerationParams(max_context, amount_gen);
|
||||
} else {
|
||||
$('#adjustedHordeParams').text('Context: --, Response: --');
|
||||
$('#adjustedHordeParams').text(t`Context` + ': --, ' + t`Response` + ': --');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,7 +405,7 @@ jQuery(function () {
|
||||
if (horde_settings.models.length) {
|
||||
adjustHordeGenerationParams(max_context, amount_gen);
|
||||
} else {
|
||||
$('#adjustedHordeParams').text('Context: --, Response: --');
|
||||
$('#adjustedHordeParams').text(t`Context` + ': --, ' + t`Response` + ': --');
|
||||
}
|
||||
|
||||
saveSettingsDebounced();
|
||||
|
@@ -398,23 +398,26 @@ export function formatInstructModeChat(name, mes, isUser, isNarrator, forceAvata
|
||||
/**
|
||||
* Formats instruct mode system prompt.
|
||||
* @param {string} systemPrompt System prompt string.
|
||||
* @param {InstructSettings} customInstruct Custom instruct mode settings.
|
||||
* @returns {string} Formatted instruct mode system prompt.
|
||||
*/
|
||||
export function formatInstructModeSystemPrompt(systemPrompt) {
|
||||
export function formatInstructModeSystemPrompt(systemPrompt, customInstruct = null) {
|
||||
if (!systemPrompt) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const separator = power_user.instruct.wrap ? '\n' : '';
|
||||
const instruct = structuredClone(customInstruct ?? power_user.instruct);
|
||||
|
||||
if (power_user.instruct.system_sequence_prefix) {
|
||||
const separator = instruct.wrap ? '\n' : '';
|
||||
|
||||
if (instruct.system_sequence_prefix) {
|
||||
// TODO: Replace with a proper 'System' prompt entity name input
|
||||
const prefix = power_user.instruct.system_sequence_prefix.replace(/{{name}}/gi, 'System');
|
||||
const prefix = instruct.system_sequence_prefix.replace(/{{name}}/gi, 'System');
|
||||
systemPrompt = prefix + separator + systemPrompt;
|
||||
}
|
||||
|
||||
if (power_user.instruct.system_sequence_suffix) {
|
||||
systemPrompt = systemPrompt + separator + power_user.instruct.system_sequence_suffix;
|
||||
if (instruct.system_sequence_suffix) {
|
||||
systemPrompt = systemPrompt + separator + instruct.system_sequence_suffix;
|
||||
}
|
||||
|
||||
return systemPrompt;
|
||||
|
@@ -705,16 +705,18 @@ export function parseExampleIntoIndividual(messageExampleString, appendNamesForG
|
||||
return result;
|
||||
}
|
||||
|
||||
function formatWorldInfo(value) {
|
||||
export function formatWorldInfo(value, { wiFormat = null } = {}) {
|
||||
if (!value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!oai_settings.wi_format.trim()) {
|
||||
const format = wiFormat ?? oai_settings.wi_format;
|
||||
|
||||
if (!format.trim()) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return stringFormat(oai_settings.wi_format, value);
|
||||
return stringFormat(format, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -952,7 +954,7 @@ async function populateDialogueExamples(prompts, chatCompletion, messageExamples
|
||||
* @param {number} position - Prompt position in the extensions object.
|
||||
* @returns {string|false} - The prompt position for prompt collection.
|
||||
*/
|
||||
function getPromptPosition(position) {
|
||||
export function getPromptPosition(position) {
|
||||
if (position == extension_prompt_types.BEFORE_PROMPT) {
|
||||
return 'start';
|
||||
}
|
||||
@@ -969,7 +971,7 @@ function getPromptPosition(position) {
|
||||
* @param {number} role Role of the prompt.
|
||||
* @returns {string} Mapped role.
|
||||
*/
|
||||
function getPromptRole(role) {
|
||||
export function getPromptRole(role) {
|
||||
switch (role) {
|
||||
case extension_prompt_roles.SYSTEM:
|
||||
return 'system';
|
||||
@@ -3476,7 +3478,7 @@ async function getStatusOpen() {
|
||||
let status;
|
||||
|
||||
if ('ai' in window) {
|
||||
status = 'Valid';
|
||||
status = t`Valid`;
|
||||
}
|
||||
else {
|
||||
showWindowExtensionError();
|
||||
@@ -3525,7 +3527,7 @@ async function getStatusOpen() {
|
||||
|
||||
const canBypass = (oai_settings.chat_completion_source === chat_completion_sources.OPENAI && oai_settings.bypass_status_check) || oai_settings.chat_completion_source === chat_completion_sources.CUSTOM;
|
||||
if (canBypass) {
|
||||
setOnlineStatus('Status check bypassed');
|
||||
setOnlineStatus(t`Status check bypassed`);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -3547,7 +3549,7 @@ async function getStatusOpen() {
|
||||
saveModelList(responseData.data);
|
||||
}
|
||||
if (!('error' in responseData)) {
|
||||
setOnlineStatus('Valid');
|
||||
setOnlineStatus(t`Valid`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
|
@@ -800,7 +800,7 @@ async function selectCurrentPersona({ toastPersonaNameChange = true } = {}) {
|
||||
chat_metadata['persona'] = user_avatar;
|
||||
console.log(`Auto locked persona to ${user_avatar}`);
|
||||
if (toastPersonaNameChange && power_user.persona_show_notifications) {
|
||||
toastr.success(`Persona ${personaName} selected and auto-locked to current chat`, t`Persona Selected`);
|
||||
toastr.success(t`Persona ${personaName} selected and auto-locked to current chat`, t`Persona Selected`);
|
||||
}
|
||||
saveMetadataDebounced();
|
||||
updatePersonaUIStates();
|
||||
|
@@ -55,6 +55,7 @@ import { POPUP_TYPE, callGenericPopup } from './popup.js';
|
||||
import { loadSystemPrompts } from './sysprompt.js';
|
||||
import { fuzzySearchCategories } from './filters.js';
|
||||
import { accountStorage } from './util/AccountStorage.js';
|
||||
import { DEFAULT_REASONING_TEMPLATE, loadReasoningTemplates } from './reasoning.js';
|
||||
|
||||
export {
|
||||
loadPowerUserSettings,
|
||||
@@ -257,6 +258,7 @@ let power_user = {
|
||||
},
|
||||
|
||||
reasoning: {
|
||||
name: DEFAULT_REASONING_TEMPLATE,
|
||||
auto_parse: false,
|
||||
add_to_prompts: false,
|
||||
auto_expand: false,
|
||||
@@ -1624,6 +1626,7 @@ async function loadPowerUserSettings(settings, data) {
|
||||
await loadInstructMode(data);
|
||||
await loadContextSettings();
|
||||
await loadSystemPrompts(data);
|
||||
await loadReasoningTemplates(data);
|
||||
loadMaxContextUnlocked();
|
||||
switchWaifuMode();
|
||||
switchSpoilerMode();
|
||||
@@ -1985,15 +1988,21 @@ export function fuzzySearchGroups(searchValue, fuzzySearchCaches = null) {
|
||||
/**
|
||||
* Renders a story string template with the given parameters.
|
||||
* @param {object} params Template parameters.
|
||||
* @param {object} [options] Additional options.
|
||||
* @param {string} [options.customStoryString] Custom story string template.
|
||||
* @param {InstructSettings} [options.customInstructSettings] Custom instruct settings.
|
||||
* @returns {string} The rendered story string.
|
||||
*/
|
||||
export function renderStoryString(params) {
|
||||
export function renderStoryString(params, { customStoryString = null, customInstructSettings = null } = {}) {
|
||||
try {
|
||||
const storyString = customStoryString ?? power_user.context.story_string;
|
||||
const instructSettings = structuredClone(customInstructSettings ?? power_user.instruct);
|
||||
|
||||
// Validate and log possible warnings/errors
|
||||
validateStoryString(power_user.context.story_string, params);
|
||||
validateStoryString(storyString, params);
|
||||
|
||||
// compile the story string template into a function, with no HTML escaping
|
||||
const compiledTemplate = Handlebars.compile(power_user.context.story_string, { noEscape: true });
|
||||
const compiledTemplate = Handlebars.compile(storyString, { noEscape: true });
|
||||
|
||||
// render the story string template with the given params
|
||||
let output = compiledTemplate(params);
|
||||
@@ -2006,7 +2015,7 @@ export function renderStoryString(params) {
|
||||
|
||||
// add a newline to the end of the story string if it doesn't have one
|
||||
if (output.length > 0 && !output.endsWith('\n')) {
|
||||
if (!power_user.instruct.enabled || power_user.instruct.wrap) {
|
||||
if (!instructSettings.enabled || instructSettings.wrap) {
|
||||
output += '\n';
|
||||
}
|
||||
}
|
||||
@@ -4229,14 +4238,13 @@ $(document).ready(() => {
|
||||
],
|
||||
callback: (args, value) => {
|
||||
const force = isTrueBoolean(String(args?.force ?? false));
|
||||
value = String(value ?? '').trim();
|
||||
|
||||
// Skip processing if no value and not forced
|
||||
if (!force && !value) {
|
||||
return power_user.user_prompt_bias;
|
||||
}
|
||||
|
||||
power_user.user_prompt_bias = value;
|
||||
power_user.user_prompt_bias = String(value ?? '');
|
||||
$('#start_reply_with').val(power_user.user_prompt_bias);
|
||||
saveSettingsDebounced();
|
||||
|
||||
|
@@ -21,7 +21,7 @@ import { groups, selected_group } from './group-chats.js';
|
||||
import { instruct_presets } from './instruct-mode.js';
|
||||
import { kai_settings } from './kai-settings.js';
|
||||
import { convertNovelPreset } from './nai-settings.js';
|
||||
import { openai_settings, openai_setting_names, oai_settings } from './openai.js';
|
||||
import { openai_settings, openai_setting_names } from './openai.js';
|
||||
import { Popup, POPUP_RESULT, POPUP_TYPE } from './popup.js';
|
||||
import { context_presets, getContextSettings, power_user } from './power-user.js';
|
||||
import { SlashCommand } from './slash-commands/SlashCommand.js';
|
||||
@@ -38,6 +38,7 @@ import {
|
||||
} from './textgen-settings.js';
|
||||
import { download, parseJsonFile, waitUntilCondition } from './utils.js';
|
||||
import { t } from './i18n.js';
|
||||
import { reasoning_templates } from './reasoning.js';
|
||||
|
||||
const presetManagers = {};
|
||||
|
||||
@@ -168,6 +169,20 @@ class PresetManager {
|
||||
},
|
||||
isValid: (data) => PresetManager.isPossiblyTextCompletionData(data),
|
||||
},
|
||||
'reasoning': {
|
||||
name: 'Reasoning Formatting',
|
||||
getData: () => {
|
||||
const manager = getPresetManager('reasoning');
|
||||
const name = manager.getSelectedPresetName();
|
||||
return manager.getPresetSettings(name);
|
||||
},
|
||||
setData: (data) => {
|
||||
const manager = getPresetManager('reasoning');
|
||||
const name = data.name;
|
||||
return manager.savePreset(name, data);
|
||||
},
|
||||
isValid: (data) => PresetManager.isPossiblyReasoningData(data),
|
||||
},
|
||||
};
|
||||
|
||||
static isPossiblyInstructData(data) {
|
||||
@@ -190,6 +205,11 @@ class PresetManager {
|
||||
return data && textCompletionProps.every(prop => Object.keys(data).includes(prop));
|
||||
}
|
||||
|
||||
static isPossiblyReasoningData(data) {
|
||||
const reasoningProps = ['name', 'prefix', 'suffix', 'separator'];
|
||||
return data && reasoningProps.every(prop => Object.keys(data).includes(prop));
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports master settings from JSON data.
|
||||
* @param {object} data Data to import
|
||||
@@ -227,6 +247,12 @@ class PresetManager {
|
||||
return await getPresetManager('textgenerationwebui').savePreset(fileName, data);
|
||||
}
|
||||
|
||||
// 5. Reasoning Template
|
||||
if (this.isPossiblyReasoningData(data)) {
|
||||
toastr.info(t`Importing as reasoning template...`, t`Reasoning template detected`);
|
||||
return await getPresetManager('reasoning').savePreset(data.name, data);
|
||||
}
|
||||
|
||||
const validSections = [];
|
||||
for (const [key, section] of Object.entries(this.masterSections)) {
|
||||
if (key in data && section.isValid(data[key])) {
|
||||
@@ -478,6 +504,10 @@ class PresetManager {
|
||||
presets = system_prompts;
|
||||
preset_names = system_prompts.map(x => x.name);
|
||||
break;
|
||||
case 'reasoning':
|
||||
presets = reasoning_templates;
|
||||
preset_names = reasoning_templates.map(x => x.name);
|
||||
break;
|
||||
default:
|
||||
console.warn(`Unknown API ID ${api}`);
|
||||
}
|
||||
@@ -490,7 +520,7 @@ class PresetManager {
|
||||
}
|
||||
|
||||
isAdvancedFormatting() {
|
||||
return this.apiId == 'context' || this.apiId == 'instruct' || this.apiId == 'sysprompt';
|
||||
return ['context', 'instruct', 'sysprompt', 'reasoning'].includes(this.apiId);
|
||||
}
|
||||
|
||||
updateList(name, preset) {
|
||||
@@ -553,6 +583,11 @@ class PresetManager {
|
||||
sysprompt_preset['name'] = name || power_user.sysprompt.preset;
|
||||
return sysprompt_preset;
|
||||
}
|
||||
case 'reasoning': {
|
||||
const reasoning_preset = structuredClone(power_user.reasoning);
|
||||
reasoning_preset['name'] = name || power_user.reasoning.preset;
|
||||
return reasoning_preset;
|
||||
}
|
||||
default:
|
||||
console.warn(`Unknown API ID ${apiId}`);
|
||||
return {};
|
||||
@@ -599,6 +634,13 @@ class PresetManager {
|
||||
'include_reasoning',
|
||||
'global_banned_tokens',
|
||||
'send_banned_tokens',
|
||||
|
||||
// Reasoning exclusions
|
||||
'auto_parse',
|
||||
'add_to_prompts',
|
||||
'auto_expand',
|
||||
'show_hidden',
|
||||
'max_additions',
|
||||
];
|
||||
const settings = Object.assign({}, getSettingsByApiId(this.apiId));
|
||||
|
||||
|
@@ -7,14 +7,46 @@ import { getCurrentLocale, t, translate } from './i18n.js';
|
||||
import { MacrosParser } from './macros.js';
|
||||
import { chat_completion_sources, getChatCompletionModel, oai_settings } from './openai.js';
|
||||
import { Popup } from './popup.js';
|
||||
import { power_user } from './power-user.js';
|
||||
import { performFuzzySearch, power_user } from './power-user.js';
|
||||
import { getPresetManager } from './preset-manager.js';
|
||||
import { SlashCommand } from './slash-commands/SlashCommand.js';
|
||||
import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './slash-commands/SlashCommandArgument.js';
|
||||
import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js';
|
||||
import { enumTypes, SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js';
|
||||
import { SlashCommandParser } from './slash-commands/SlashCommandParser.js';
|
||||
import { textgen_types, textgenerationwebui_settings } from './textgen-settings.js';
|
||||
import { copyText, escapeRegex, isFalseBoolean, setDatasetProperty, trimSpaces } from './utils.js';
|
||||
import { copyText, escapeRegex, isFalseBoolean, isTrueBoolean, setDatasetProperty, trimSpaces } from './utils.js';
|
||||
|
||||
/**
|
||||
* @typedef {object} ReasoningTemplate
|
||||
* @property {string} name - The name of the template
|
||||
* @property {string} prefix - Reasoning prefix
|
||||
* @property {string} suffix - Reasoning suffix
|
||||
* @property {string} separator - Reasoning separator
|
||||
*/
|
||||
|
||||
/**
|
||||
* @type {ReasoningTemplate[]} List of reasoning templates
|
||||
*/
|
||||
export const reasoning_templates = [];
|
||||
|
||||
export const DEFAULT_REASONING_TEMPLATE = 'DeepSeek';
|
||||
|
||||
/**
|
||||
* @type {Record<string, JQuery<HTMLElement>>} List of UI elements for reasoning settings
|
||||
* @readonly
|
||||
*/
|
||||
const UI = {
|
||||
$select: $('#reasoning_select'),
|
||||
$suffix: $('#reasoning_suffix'),
|
||||
$prefix: $('#reasoning_prefix'),
|
||||
$separator: $('#reasoning_separator'),
|
||||
$autoParse: $('#reasoning_auto_parse'),
|
||||
$autoExpand: $('#reasoning_auto_expand'),
|
||||
$showHidden: $('#reasoning_show_hidden'),
|
||||
$addToPrompts: $('#reasoning_add_to_prompts'),
|
||||
$maxAdditions: $('#reasoning_max_additions'),
|
||||
};
|
||||
|
||||
/**
|
||||
* Enum representing the type of the reasoning for a message (where it came from)
|
||||
@@ -61,7 +93,7 @@ export function extractReasoningFromData(data, {
|
||||
mainApi = null,
|
||||
ignoreShowThoughts = false,
|
||||
textGenType = null,
|
||||
chatCompletionSource = null
|
||||
chatCompletionSource = null,
|
||||
} = {}) {
|
||||
switch (mainApi ?? main_api) {
|
||||
case 'textgenerationwebui':
|
||||
@@ -669,57 +701,102 @@ export class PromptReasoning {
|
||||
}
|
||||
|
||||
function loadReasoningSettings() {
|
||||
$('#reasoning_add_to_prompts').prop('checked', power_user.reasoning.add_to_prompts);
|
||||
$('#reasoning_add_to_prompts').on('change', function () {
|
||||
UI.$addToPrompts.prop('checked', power_user.reasoning.add_to_prompts);
|
||||
UI.$addToPrompts.on('change', function () {
|
||||
power_user.reasoning.add_to_prompts = !!$(this).prop('checked');
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$('#reasoning_prefix').val(power_user.reasoning.prefix);
|
||||
$('#reasoning_prefix').on('input', function () {
|
||||
UI.$prefix.val(power_user.reasoning.prefix);
|
||||
UI.$prefix.on('input', function () {
|
||||
power_user.reasoning.prefix = String($(this).val());
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$('#reasoning_suffix').val(power_user.reasoning.suffix);
|
||||
$('#reasoning_suffix').on('input', function () {
|
||||
UI.$suffix.val(power_user.reasoning.suffix);
|
||||
UI.$suffix.on('input', function () {
|
||||
power_user.reasoning.suffix = String($(this).val());
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$('#reasoning_separator').val(power_user.reasoning.separator);
|
||||
$('#reasoning_separator').on('input', function () {
|
||||
UI.$separator.val(power_user.reasoning.separator);
|
||||
UI.$separator.on('input', function () {
|
||||
power_user.reasoning.separator = String($(this).val());
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$('#reasoning_max_additions').val(power_user.reasoning.max_additions);
|
||||
$('#reasoning_max_additions').on('input', function () {
|
||||
UI.$maxAdditions.val(power_user.reasoning.max_additions);
|
||||
UI.$maxAdditions.on('input', function () {
|
||||
power_user.reasoning.max_additions = Number($(this).val());
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$('#reasoning_auto_parse').prop('checked', power_user.reasoning.auto_parse);
|
||||
$('#reasoning_auto_parse').on('change', function () {
|
||||
UI.$autoParse.prop('checked', power_user.reasoning.auto_parse);
|
||||
UI.$autoParse.on('change', function () {
|
||||
power_user.reasoning.auto_parse = !!$(this).prop('checked');
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$('#reasoning_auto_expand').prop('checked', power_user.reasoning.auto_expand);
|
||||
$('#reasoning_auto_expand').on('change', function () {
|
||||
UI.$autoExpand.prop('checked', power_user.reasoning.auto_expand);
|
||||
UI.$autoExpand.on('change', function () {
|
||||
power_user.reasoning.auto_expand = !!$(this).prop('checked');
|
||||
toggleReasoningAutoExpand();
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
toggleReasoningAutoExpand();
|
||||
|
||||
$('#reasoning_show_hidden').prop('checked', power_user.reasoning.show_hidden);
|
||||
$('#reasoning_show_hidden').on('change', function () {
|
||||
UI.$showHidden.prop('checked', power_user.reasoning.show_hidden);
|
||||
UI.$showHidden.on('change', function () {
|
||||
power_user.reasoning.show_hidden = !!$(this).prop('checked');
|
||||
$('#chat').attr('data-show-hidden-reasoning', power_user.reasoning.show_hidden ? 'true' : null);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
$('#chat').attr('data-show-hidden-reasoning', power_user.reasoning.show_hidden ? 'true' : null);
|
||||
|
||||
UI.$select.on('change', async function () {
|
||||
const name = String($(this).val());
|
||||
const template = reasoning_templates.find(p => p.name === name);
|
||||
if (!template) {
|
||||
return;
|
||||
}
|
||||
|
||||
UI.$prefix.val(template.prefix);
|
||||
UI.$suffix.val(template.suffix);
|
||||
UI.$separator.val(template.separator);
|
||||
|
||||
power_user.reasoning.name = name;
|
||||
power_user.reasoning.prefix = template.prefix;
|
||||
power_user.reasoning.suffix = template.suffix;
|
||||
power_user.reasoning.separator = template.separator;
|
||||
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
}
|
||||
|
||||
function selectReasoningTemplateCallback(args, name) {
|
||||
if (!name) {
|
||||
return power_user.reasoning.name ?? '';
|
||||
}
|
||||
|
||||
const quiet = isTrueBoolean(args?.quiet);
|
||||
const templateNames = reasoning_templates.map(preset => preset.name);
|
||||
let foundName = templateNames.find(x => x.toLowerCase() === name.toLowerCase());
|
||||
|
||||
if (!foundName) {
|
||||
const result = performFuzzySearch('reasoning-templates', templateNames, [], name);
|
||||
|
||||
if (result.length === 0) {
|
||||
!quiet && toastr.warning(`Reasoning template "${name}" not found`);
|
||||
return '';
|
||||
}
|
||||
|
||||
foundName = result[0].item;
|
||||
}
|
||||
|
||||
UI.$select.val(foundName).trigger('change');
|
||||
!quiet && toastr.success(`Reasoning template "${foundName}" selected`);
|
||||
return foundName;
|
||||
|
||||
}
|
||||
|
||||
function registerReasoningSlashCommands() {
|
||||
@@ -853,6 +930,42 @@ function registerReasoningSlashCommands() {
|
||||
: parsedReasoning.reasoning;
|
||||
},
|
||||
}));
|
||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||
name: 'reasoning-template',
|
||||
aliases: ['reasoning-formatting', 'reasoning-preset'],
|
||||
callback: selectReasoningTemplateCallback,
|
||||
returns: 'template name',
|
||||
namedArgumentList: [
|
||||
SlashCommandNamedArgument.fromProps({
|
||||
name: 'quiet',
|
||||
description: 'Suppress the toast message on template change',
|
||||
typeList: [ARGUMENT_TYPE.BOOLEAN],
|
||||
defaultValue: 'false',
|
||||
enumList: commonEnumProviders.boolean('trueFalse')(),
|
||||
}),
|
||||
],
|
||||
unnamedArgumentList: [
|
||||
SlashCommandArgument.fromProps({
|
||||
description: 'reasoning template name',
|
||||
typeList: [ARGUMENT_TYPE.STRING],
|
||||
enumProvider: () => reasoning_templates.map(x => new SlashCommandEnumValue(x.name, null, enumTypes.enum, enumIcons.preset)),
|
||||
}),
|
||||
],
|
||||
helpString: `
|
||||
<div>
|
||||
Selects a reasoning template by name, using fuzzy search to find the closest match.
|
||||
Gets the current template if no name is provided.
|
||||
</div>
|
||||
<div>
|
||||
<strong>Example:</strong>
|
||||
<ul>
|
||||
<li>
|
||||
<pre><code class="language-stscript">/reasoning-template DeepSeek</code></pre>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
}));
|
||||
}
|
||||
|
||||
function registerReasoningMacros() {
|
||||
@@ -1212,6 +1325,53 @@ function registerReasoningAppEvents() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads reasoning templates from the settings data.
|
||||
* @param {object} data Settings data
|
||||
* @param {ReasoningTemplate[]} data.reasoning Reasoning templates
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export async function loadReasoningTemplates(data) {
|
||||
if (data.reasoning !== undefined) {
|
||||
reasoning_templates.splice(0, reasoning_templates.length, ...data.reasoning);
|
||||
}
|
||||
|
||||
for (const template of reasoning_templates) {
|
||||
$('<option>').val(template.name).text(template.name).appendTo(UI.$select);
|
||||
}
|
||||
|
||||
// No template name, need to migrate
|
||||
if (power_user.reasoning.name === undefined) {
|
||||
const defaultTemplate = reasoning_templates.find(p => p.name === DEFAULT_REASONING_TEMPLATE);
|
||||
if (defaultTemplate) {
|
||||
// If the reasoning settings were modified - migrate them to a custom template
|
||||
if (power_user.reasoning.prefix !== defaultTemplate.prefix || power_user.reasoning.suffix !== defaultTemplate.suffix || power_user.reasoning.separator !== defaultTemplate.separator) {
|
||||
/** @type {ReasoningTemplate} */
|
||||
const data = {
|
||||
name: '[Migrated] Custom',
|
||||
prefix: power_user.reasoning.prefix,
|
||||
suffix: power_user.reasoning.suffix,
|
||||
separator: power_user.reasoning.separator,
|
||||
};
|
||||
await getPresetManager('reasoning')?.savePreset(data.name, data);
|
||||
power_user.reasoning.name = data.name;
|
||||
} else {
|
||||
power_user.reasoning.name = defaultTemplate.name;
|
||||
}
|
||||
} else {
|
||||
// Template not found (deleted or content check skipped - leave blank)
|
||||
power_user.reasoning.name = '';
|
||||
}
|
||||
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
UI.$select.val(power_user.reasoning.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes reasoning settings and event handlers.
|
||||
*/
|
||||
export function initReasoning() {
|
||||
loadReasoningSettings();
|
||||
setReasoningEventHandlers();
|
||||
|
@@ -9,6 +9,7 @@ import { power_user } from './power-user.js';
|
||||
//import { getSortableDelay, onlyUnique } from './utils.js';
|
||||
//import { getCfgPrompt } from './cfg-scale.js';
|
||||
import { setting_names } from './textgen-settings.js';
|
||||
import { renderTemplateAsync } from './templates.js';
|
||||
|
||||
|
||||
const TGsamplerNames = setting_names;
|
||||
@@ -25,25 +26,7 @@ async function showSamplerSelectPopup() {
|
||||
const html = $(document.createElement('div'));
|
||||
html.attr('id', 'sampler_view_list')
|
||||
.addClass('flex-container flexFlowColumn');
|
||||
html.append(`
|
||||
<div class="title_restorable flexFlowColumn alignItemsBaseline">
|
||||
<div class="flex-container justifyCenter">
|
||||
<h3>Sampler Select</h3>
|
||||
<div class="flex-container alignItemsBaseline">
|
||||
<div id="resetSelectedSamplers" class="menu_button menu_button_icon" title="Reset custom sampler selection">
|
||||
<i class="fa-solid fa-recycle"></i>
|
||||
</div>
|
||||
</div>
|
||||
<!--<div class="flex-container alignItemsBaseline">
|
||||
<div class="menu_button menu_button_icon" title="Create a new sampler">
|
||||
<i class="fa-solid fa-plus"></i>
|
||||
<span data-i18n="Create">Create</span>
|
||||
</div>
|
||||
</div>-->
|
||||
</div>
|
||||
<small>Here you can toggle the display of individual samplers. (WIP)</small>
|
||||
</div>
|
||||
<hr>`);
|
||||
html.append(await renderTemplateAsync('samplerSelector'));
|
||||
|
||||
const listContainer = $('<div id="apiSamplersList" class="flex-container flexNoGap"></div>');
|
||||
const APISamplers = await listSamplers(main_api);
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import { DOMPurify } from '../lib.js';
|
||||
import { callPopup, getRequestHeaders } from '../script.js';
|
||||
import { t } from './i18n.js';
|
||||
|
||||
export const SECRET_KEYS = {
|
||||
HORDE: 'api_key_horde',
|
||||
@@ -104,7 +105,7 @@ async function viewSecrets() {
|
||||
});
|
||||
|
||||
if (response.status == 403) {
|
||||
callPopup('<h3>Forbidden</h3><p>To view your API keys here, set the value of allowKeysExposure to true in config.yaml file and restart the SillyTavern server.</p>', 'text');
|
||||
callPopup('<h3>' + t`Forbidden` + '</h3><p>' + t`To view your API keys here, set the value of allowKeysExposure to true in config.yaml file and restart the SillyTavern server.` + '</p>', 'text');
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -49,6 +49,7 @@ import {
|
||||
clearChat,
|
||||
unshallowCharacter,
|
||||
deleteLastMessage,
|
||||
getCharacterCardFields,
|
||||
} from '../script.js';
|
||||
import {
|
||||
extension_settings,
|
||||
@@ -78,7 +79,7 @@ import { ToolManager } from './tool-calling.js';
|
||||
import { accountStorage } from './util/AccountStorage.js';
|
||||
import { timestampToMoment, uuidv4 } from './utils.js';
|
||||
import { getGlobalVariable, getLocalVariable, setGlobalVariable, setLocalVariable } from './variables.js';
|
||||
import { convertCharacterBook, loadWorldInfo, saveWorldInfo, updateWorldInfoList } from './world-info.js';
|
||||
import { convertCharacterBook, getWorldInfoPrompt, loadWorldInfo, saveWorldInfo, updateWorldInfoList } from './world-info.js';
|
||||
import { ChatCompletionService, TextCompletionService } from './custom-request.js';
|
||||
import { ConnectionManagerRequestService } from './extensions/shared.js';
|
||||
import { updateReasoningUI, parseReasoningFromString } from './reasoning.js';
|
||||
@@ -189,6 +190,7 @@ export function getContext() {
|
||||
textCompletionSettings: textgenerationwebui_settings,
|
||||
powerUserSettings: power_user,
|
||||
getCharacters,
|
||||
getCharacterCardFields,
|
||||
uuidv4,
|
||||
humanizedDateTime,
|
||||
updateMessageBlock,
|
||||
@@ -207,6 +209,7 @@ export function getContext() {
|
||||
saveWorldInfo,
|
||||
updateWorldInfoList,
|
||||
convertCharacterBook,
|
||||
getWorldInfoPrompt,
|
||||
CONNECT_API_MAP,
|
||||
getTextGenServer,
|
||||
extractMessageFromData,
|
||||
|
@@ -1,9 +1,9 @@
|
||||
<div data-type="assistant_note">
|
||||
<div>
|
||||
<b data-i18n="Note:">Note:</b> <span data-i18n="this chat is temporary and will be deleted as soon as you leave it.">this chat is temporary and will be deleted as soon as you leave it.</span>
|
||||
<span>Click the button to save it as a file.</span>
|
||||
<span data-i18n="Click the button to save it as a file.">Click the button to save it as a file.</span>
|
||||
</div>
|
||||
<div class="assistant_note_export menu_button menu_button_icon" title="Export as JSONL">
|
||||
<div class="assistant_note_export menu_button menu_button_icon" data-i18n="[title]Export as JSONL" title="Export as JSONL">
|
||||
<i class="fa-solid fa-file-export"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
18
public/scripts/templates/samplerSelector.html
Normal file
18
public/scripts/templates/samplerSelector.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<div class="title_restorable flexFlowColumn alignItemsBaseline">
|
||||
<div class="flex-container justifyCenter">
|
||||
<h3 data-i18n="Sampler Select">Sampler Select</h3>
|
||||
<div class="flex-container alignItemsBaseline">
|
||||
<div id="resetSelectedSamplers" class="menu_button menu_button_icon" data-i18n="[title]Reset custom sampler selection" title="Reset custom sampler selection">
|
||||
<i class="fa-solid fa-recycle"></i>
|
||||
</div>
|
||||
</div>
|
||||
<!--<div class="flex-container alignItemsBaseline">
|
||||
<div class="menu_button menu_button_icon" title="Create a new sampler">
|
||||
<i class="fa-solid fa-plus"></i>
|
||||
<span data-i18n="Create">Create</span>
|
||||
</div>
|
||||
</div>-->
|
||||
</div>
|
||||
<small data-i18n="Here you can toggle the display of individual samplers. (WIP)">Here you can toggle the display of individual samplers. (WIP)</small>
|
||||
</div>
|
||||
<hr>
|
@@ -753,10 +753,17 @@ export const worldInfoCache = new StructuredCloneMap({ cloneOnGet: true, cloneOn
|
||||
|
||||
/**
|
||||
* Gets the world info based on chat messages.
|
||||
* @param {string[]} chat The chat messages to scan, in reverse order.
|
||||
* @param {number} maxContext The maximum context size of the generation.
|
||||
* @param {boolean} isDryRun If true, the function will not emit any events.
|
||||
* @typedef {{worldInfoString: string, worldInfoBefore: string, worldInfoAfter: string, worldInfoExamples: any[], worldInfoDepth: any[]}} WIPromptResult
|
||||
* @param {string[]} chat - The chat messages to scan, in reverse order.
|
||||
* @param {number} maxContext - The maximum context size of the generation.
|
||||
* @param {boolean} isDryRun - If true, the function will not emit any events.
|
||||
* @typedef {object} WIPromptResult
|
||||
* @property {string} worldInfoString - Complete world info string
|
||||
* @property {string} worldInfoBefore - World info that goes before the prompt
|
||||
* @property {string} worldInfoAfter - World info that goes after the prompt
|
||||
* @property {Array} worldInfoExamples - Array of example entries
|
||||
* @property {Array} worldInfoDepth - Array of depth entries
|
||||
* @property {Array} anBefore - Array of entries before Author's Note
|
||||
* @property {Array} anAfter - Array of entries after Author's Note
|
||||
* @returns {Promise<WIPromptResult>} The world info string and depth.
|
||||
*/
|
||||
export async function getWorldInfoPrompt(chat, maxContext, isDryRun) {
|
||||
@@ -778,6 +785,8 @@ export async function getWorldInfoPrompt(chat, maxContext, isDryRun) {
|
||||
worldInfoAfter,
|
||||
worldInfoExamples: activatedWorldInfo.EMEntries ?? [],
|
||||
worldInfoDepth: activatedWorldInfo.WIDepthEntries ?? [],
|
||||
anBefore: activatedWorldInfo.ANBeforeEntries ?? [],
|
||||
anAfter: activatedWorldInfo.ANAfterEntries ?? [],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3862,7 +3871,14 @@ function parseDecorators(content) {
|
||||
* @param {string[]} chat The chat messages to scan, in reverse order.
|
||||
* @param {number} maxContext The maximum context size of the generation.
|
||||
* @param {boolean} isDryRun Whether to perform a dry run.
|
||||
* @typedef {{ worldInfoBefore: string, worldInfoAfter: string, EMEntries: any[], WIDepthEntries: any[], allActivatedEntries: Set<any> }} WIActivated
|
||||
* @typedef {object} WIActivated
|
||||
* @property {string} worldInfoBefore The world info before the chat.
|
||||
* @property {string} worldInfoAfter The world info after the chat.
|
||||
* @property {any[]} EMEntries The entries for examples.
|
||||
* @property {any[]} WIDepthEntries The depth entries.
|
||||
* @property {any[]} ANBeforeEntries The entries before Author's Note.
|
||||
* @property {any[]} ANAfterEntries The entries after Author's Note.
|
||||
* @property {Set<any>} allActivatedEntries All entries.
|
||||
* @returns {Promise<WIActivated>} The world info activated.
|
||||
*/
|
||||
export async function checkWorldInfo(chat, maxContext, isDryRun) {
|
||||
@@ -3906,7 +3922,7 @@ export async function checkWorldInfo(chat, maxContext, isDryRun) {
|
||||
timedEffects.checkTimedEffects();
|
||||
|
||||
if (sortedEntries.length === 0) {
|
||||
return { worldInfoBefore: '', worldInfoAfter: '', WIDepthEntries: [], EMEntries: [], allActivatedEntries: new Set() };
|
||||
return { worldInfoBefore: '', worldInfoAfter: '', WIDepthEntries: [], EMEntries: [], ANBeforeEntries: [], ANAfterEntries: [], allActivatedEntries: new Set() };
|
||||
}
|
||||
|
||||
/** @type {number[]} Represents the delay levels for entries that are delayed until recursion */
|
||||
@@ -4355,7 +4371,7 @@ export async function checkWorldInfo(chat, maxContext, isDryRun) {
|
||||
console.log(`[WI] ${isDryRun ? 'Hypothetically adding' : 'Adding'} ${allActivatedEntries.size} entries to prompt`, Array.from(allActivatedEntries.values()));
|
||||
console.debug(`[WI] --- DONE${isDryRun ? ' (DRY RUN)' : ''} ---`);
|
||||
|
||||
return { worldInfoBefore, worldInfoAfter, EMEntries, WIDepthEntries, allActivatedEntries: new Set(allActivatedEntries.values()) };
|
||||
return { worldInfoBefore, worldInfoAfter, EMEntries, WIDepthEntries, ANBeforeEntries: ANTopEntries, ANAfterEntries: ANBottomEntries, allActivatedEntries: new Set(allActivatedEntries.values()) };
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user