Add generation type triggers to world info (#4286)
* Add generation type triggers to world info * Simplify includes check * Refactor getEntryField validation and default value handling * Remove invalid attribute * Check for a valid trigger
This commit is contained in:
@@ -286,6 +286,13 @@ select.keyselect+span.select2-container .select2-selection--multiple {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.world_entry label[for="__invisible"] {
|
||||||
|
visibility: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
#WIMultiSelector .select2-container .select2-selection--multiple {
|
#WIMultiSelector .select2-container .select2-selection--multiple {
|
||||||
max-height: 25vh;
|
max-height: 25vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|||||||
@@ -6494,6 +6494,30 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex4">
|
||||||
|
<div class="flex-container justifySpaceBetween">
|
||||||
|
<small>
|
||||||
|
<span data-i18n="Filter to Generation Triggers">
|
||||||
|
Filter to Generation Triggers
|
||||||
|
</span>
|
||||||
|
</small>
|
||||||
|
<!-- Not a real control. Used to make label heights even. -->
|
||||||
|
<label class="checkbox_label" for="__invisible">
|
||||||
|
<input type="checkbox" name="__invisible">
|
||||||
|
<span><small> </small></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="range-block-range">
|
||||||
|
<select name="triggers" multiple>
|
||||||
|
<option data-i18n="Normal" value="normal">Normal</option>
|
||||||
|
<option data-i18n="Continue" value="continue">Continue</option>
|
||||||
|
<option data-i18n="Impersonate" value="impersonate">Impersonate</option>
|
||||||
|
<option data-i18n="Swipe" value="swipe">Swipe</option>
|
||||||
|
<option data-i18n="Regenerate" value="regenerate">Regenerate</option>
|
||||||
|
<option data-i18n="Quiet" value="quiet">Quiet</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div name="WIEntryBottomControls" class="flex-container flex1 justifySpaceBetween world_entry_form_horizontal">
|
<div name="WIEntryBottomControls" class="flex-container flex1 justifySpaceBetween world_entry_form_horizontal">
|
||||||
<div class="flex-container flexFlowColumn flexNoGap wi-enter-footer-text">
|
<div class="flex-container flexFlowColumn flexNoGap wi-enter-footer-text">
|
||||||
|
|||||||
+3
-1
@@ -176,7 +176,7 @@ import {
|
|||||||
renderPaginationDropdown,
|
renderPaginationDropdown,
|
||||||
paginationDropdownChangeHandler,
|
paginationDropdownChangeHandler,
|
||||||
} from './scripts/utils.js';
|
} from './scripts/utils.js';
|
||||||
import { debounce_timeout, IGNORE_SYMBOL } from './scripts/constants.js';
|
import { debounce_timeout, GENERATION_TYPE_TRIGGERS, IGNORE_SYMBOL } from './scripts/constants.js';
|
||||||
|
|
||||||
import { cancelDebouncedMetadataSave, doDailyExtensionUpdatesCheck, extension_settings, initExtensions, loadExtensionSettings, runGenerationInterceptors, saveMetadataDebounced } from './scripts/extensions.js';
|
import { cancelDebouncedMetadataSave, doDailyExtensionUpdatesCheck, extension_settings, initExtensions, loadExtensionSettings, runGenerationInterceptors, saveMetadataDebounced } from './scripts/extensions.js';
|
||||||
import { COMMENT_NAME_DEFAULT, CONNECT_API_MAP, executeSlashCommandsOnChatInput, initDefaultSlashCommands, isExecutingCommandsFromChatInput, pauseScriptExecution, stopScriptExecution, UNIQUE_APIS } from './scripts/slash-commands.js';
|
import { COMMENT_NAME_DEFAULT, CONNECT_API_MAP, executeSlashCommandsOnChatInput, initDefaultSlashCommands, isExecutingCommandsFromChatInput, pauseScriptExecution, stopScriptExecution, UNIQUE_APIS } from './scripts/slash-commands.js';
|
||||||
@@ -3721,6 +3721,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
|
|||||||
// Make quiet prompt available for WIAN
|
// Make quiet prompt available for WIAN
|
||||||
setExtensionPrompt('QUIET_PROMPT', quiet_prompt || '', extension_prompt_types.IN_PROMPT, 0, true);
|
setExtensionPrompt('QUIET_PROMPT', quiet_prompt || '', extension_prompt_types.IN_PROMPT, 0, true);
|
||||||
const chatForWI = coreChat.map(x => world_info_include_names ? `${x.name}: ${x.mes}` : x.mes).reverse();
|
const chatForWI = coreChat.map(x => world_info_include_names ? `${x.name}: ${x.mes}` : x.mes).reverse();
|
||||||
|
/** @type {import('./scripts/world-info.js').WIGlobalScanData} */
|
||||||
const globalScanData = {
|
const globalScanData = {
|
||||||
personaDescription: persona,
|
personaDescription: persona,
|
||||||
characterDescription: description,
|
characterDescription: description,
|
||||||
@@ -3728,6 +3729,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
|
|||||||
characterDepthPrompt: charDepthPrompt,
|
characterDepthPrompt: charDepthPrompt,
|
||||||
scenario: scenario,
|
scenario: scenario,
|
||||||
creatorNotes: creatorNotes,
|
creatorNotes: creatorNotes,
|
||||||
|
trigger: GENERATION_TYPE_TRIGGERS.includes(type) ? type : 'normal',
|
||||||
};
|
};
|
||||||
const { worldInfoString, worldInfoBefore, worldInfoAfter, worldInfoExamples, worldInfoDepth } = await getWorldInfoPrompt(chatForWI, this_max_context, dryRun, globalScanData);
|
const { worldInfoString, worldInfoBefore, worldInfoAfter, worldInfoExamples, worldInfoDepth } = await getWorldInfoPrompt(chatForWI, this_max_context, dryRun, globalScanData);
|
||||||
setExtensionPrompt('QUIET_PROMPT', '', extension_prompt_types.IN_PROMPT, 0, true);
|
setExtensionPrompt('QUIET_PROMPT', '', extension_prompt_types.IN_PROMPT, 0, true);
|
||||||
|
|||||||
@@ -28,3 +28,15 @@ export const IGNORE_SYMBOL = Symbol.for('ignore');
|
|||||||
* https://ai.google.dev/gemini-api/docs/video-understanding#supported-formats
|
* https://ai.google.dev/gemini-api/docs/video-understanding#supported-formats
|
||||||
*/
|
*/
|
||||||
export const VIDEO_EXTENSIONS = ['mp4', 'avi', 'mov', 'wmv', 'flv', 'webm', '3gp', 'mkv', 'mpg'];
|
export const VIDEO_EXTENSIONS = ['mp4', 'avi', 'mov', 'wmv', 'flv', 'webm', '3gp', 'mkv', 'mpg'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Known generation triggers that can be passed to Generate function.
|
||||||
|
*/
|
||||||
|
export const GENERATION_TYPE_TRIGGERS = [
|
||||||
|
'normal',
|
||||||
|
'continue',
|
||||||
|
'impersonate',
|
||||||
|
'swipe',
|
||||||
|
'regenerate',
|
||||||
|
'quiet',
|
||||||
|
];
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { FILTER_TYPES, FilterHelper } from './filters.js';
|
|||||||
import { getTokenCountAsync } from './tokenizers.js';
|
import { getTokenCountAsync } from './tokenizers.js';
|
||||||
import { power_user } from './power-user.js';
|
import { power_user } from './power-user.js';
|
||||||
import { getTagKeyForEntity } from './tags.js';
|
import { getTagKeyForEntity } from './tags.js';
|
||||||
import { debounce_timeout } from './constants.js';
|
import { debounce_timeout, GENERATION_TYPE_TRIGGERS } from './constants.js';
|
||||||
import { getRegexedString, regex_placement } from './extensions/regex/engine.js';
|
import { getRegexedString, regex_placement } from './extensions/regex/engine.js';
|
||||||
import { SlashCommandParser } from './slash-commands/SlashCommandParser.js';
|
import { SlashCommandParser } from './slash-commands/SlashCommandParser.js';
|
||||||
import { SlashCommand } from './slash-commands/SlashCommand.js';
|
import { SlashCommand } from './slash-commands/SlashCommand.js';
|
||||||
@@ -107,6 +107,7 @@ const KNOWN_DECORATORS = ['@@activate', '@@dont_activate'];
|
|||||||
* @property {string} characterDepthPrompt Character depth prompt (sometimes referred to as character notes)
|
* @property {string} characterDepthPrompt Character depth prompt (sometimes referred to as character notes)
|
||||||
* @property {string} scenario Character defined scenario
|
* @property {string} scenario Character defined scenario
|
||||||
* @property {string} creatorNotes Character creator notes
|
* @property {string} creatorNotes Character creator notes
|
||||||
|
* @property {string} trigger The type that triggered the scan, e.g. 'normal', 'continue', etc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -145,6 +146,36 @@ const KNOWN_DECORATORS = ['@@activate', '@@dont_activate'];
|
|||||||
* @typedef TimedEffectType Type of timed effect
|
* @typedef TimedEffectType Type of timed effect
|
||||||
* @type {'sticky'|'cooldown'|'delay'}
|
* @type {'sticky'|'cooldown'|'delay'}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} WIEntryFieldDefinition
|
||||||
|
* @property {any} default - Default value for the field
|
||||||
|
* @property {string} type - Type of the field, can be 'string', 'number', 'boolean', 'array', 'enum'
|
||||||
|
* @property {boolean} [excludeFromTemplate=false] - Whether to exclude this field from the template
|
||||||
|
* @property {(value: any) => boolean} [arrayFilter] - Optional filter function for array fields to filter out unwanted values
|
||||||
|
*/
|
||||||
// End typedef area
|
// End typedef area
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -801,14 +832,6 @@ export const worldInfoCache = new StructuredCloneMap({ cloneOnGet: true, cloneOn
|
|||||||
* @param {number} maxContext - The maximum context size of the generation.
|
* @param {number} maxContext - The maximum context size of the generation.
|
||||||
* @param {boolean} isDryRun - If true, the function will not emit any events.
|
* @param {boolean} isDryRun - If true, the function will not emit any events.
|
||||||
* @param {WIGlobalScanData} globalScanData Chat independent context to be scanned
|
* @param {WIGlobalScanData} globalScanData Chat independent context to be scanned
|
||||||
* @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.
|
* @returns {Promise<WIPromptResult>} The world info string and depth.
|
||||||
*/
|
*/
|
||||||
export async function getWorldInfoPrompt(chat, maxContext, isDryRun, globalScanData) {
|
export async function getWorldInfoPrompt(chat, maxContext, isDryRun, globalScanData) {
|
||||||
@@ -1139,7 +1162,7 @@ function registerWorldInfoSlashCommands() {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newWorldInfoEntryTemplate[field] === undefined) {
|
if (!Object.hasOwn(newWorldInfoEntryDefinition, field)) {
|
||||||
toastr.warning('Valid field name is required');
|
toastr.warning('Valid field name is required');
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@@ -1167,7 +1190,7 @@ function registerWorldInfoSlashCommands() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fieldValue = entry[field];
|
fieldValue = entry[field] ?? newWorldInfoEntryDefinition[field]?.default;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldValue === undefined) {
|
if (fieldValue === undefined) {
|
||||||
@@ -1253,11 +1276,19 @@ function registerWorldInfoSlashCommands() {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newWorldInfoEntryTemplate[field] === undefined) {
|
if (!Object.hasOwn(newWorldInfoEntryDefinition, field)) {
|
||||||
toastr.warning('Valid field name is required');
|
toastr.warning('Valid field name is required');
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init a default value for the field if it does not exist
|
||||||
|
if (!Object.hasOwn(entry, field)) {
|
||||||
|
entry[field] = newWorldInfoEntryDefinition[field].default;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use an array filter if it exists for the field
|
||||||
|
const arrayFilter = newWorldInfoEntryDefinition[field]?.arrayFilter || (() => true);
|
||||||
|
|
||||||
// handle special cases, otherwise execute default logic
|
// handle special cases, otherwise execute default logic
|
||||||
let tagNames;
|
let tagNames;
|
||||||
let charNames;
|
let charNames;
|
||||||
@@ -1285,7 +1316,7 @@ function registerWorldInfoSlashCommands() {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (Array.isArray(entry[field])) {
|
if (Array.isArray(entry[field])) {
|
||||||
entry[field] = parseStringArray(value);
|
entry[field] = parseStringArray(value).filter(arrayFilter);
|
||||||
} else if (typeof entry[field] === 'boolean') {
|
} else if (typeof entry[field] === 'boolean') {
|
||||||
entry[field] = isTrueBoolean(value);
|
entry[field] = isTrueBoolean(value);
|
||||||
} else if (typeof entry[field] === 'number') {
|
} else if (typeof entry[field] === 'number') {
|
||||||
@@ -2438,6 +2469,7 @@ export const originalWIDataKeyMap = {
|
|||||||
'sticky': 'extensions.sticky',
|
'sticky': 'extensions.sticky',
|
||||||
'cooldown': 'extensions.cooldown',
|
'cooldown': 'extensions.cooldown',
|
||||||
'delay': 'extensions.delay',
|
'delay': 'extensions.delay',
|
||||||
|
'triggers': 'extensions.triggers',
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Checks the state of the current search, and adds/removes the search sorting option accordingly */
|
/** Checks the state of the current search, and adds/removes the search sorting option accordingly */
|
||||||
@@ -3496,6 +3528,29 @@ export async function getWorldEntry(name, data, entry) {
|
|||||||
automationIdInput.val(entry.automationId ?? '').trigger('input', { noSave: true });
|
automationIdInput.val(entry.automationId ?? '').trigger('input', { noSave: true });
|
||||||
setTimeout(() => createEntryInputAutocomplete(automationIdInput, getAutomationIdCallback(data)), 1);
|
setTimeout(() => createEntryInputAutocomplete(automationIdInput, getAutomationIdCallback(data)), 1);
|
||||||
|
|
||||||
|
// Generation Type Triggers
|
||||||
|
const generationTypeTriggers = editTemplate.find('select[name="triggers"]');
|
||||||
|
generationTypeTriggers.data('uid', entry.uid);
|
||||||
|
generationTypeTriggers.on('input', async function (_, { noSave = false } = {}) {
|
||||||
|
const uid = $(this).data('uid');
|
||||||
|
const value = $(this).val();
|
||||||
|
data.entries[uid].triggers = Array.isArray(value) ? value : [];
|
||||||
|
setWIOriginalDataValue(data, uid, 'extensions.triggers', data.entries[uid].triggers);
|
||||||
|
!noSave && await saveWorldInfo(name, data);
|
||||||
|
});
|
||||||
|
if (!isMobile()) {
|
||||||
|
generationTypeTriggers.select2({
|
||||||
|
placeholder: t`All types (default)`,
|
||||||
|
width: '100%',
|
||||||
|
closeOnSelect: false,
|
||||||
|
allowClear: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
generationTypeTriggers
|
||||||
|
.val(Array.isArray(entry.triggers) ? entry.triggers : [])
|
||||||
|
.trigger('input', { noSave: true })
|
||||||
|
.trigger('change');
|
||||||
|
|
||||||
countTokensDebounced(counter, contentInput.val());
|
countTokensDebounced(counter, contentInput.val());
|
||||||
|
|
||||||
editTemplate.find('.inline-drawer-content').css('display', 'none');
|
editTemplate.find('.inline-drawer-content').css('display', 'none');
|
||||||
@@ -3652,7 +3707,7 @@ export async function deleteWorldInfoEntry(data, uid, { silent = false } = {}) {
|
|||||||
*
|
*
|
||||||
* Use `newEntryTemplate` if you just need the template that contains default values
|
* Use `newEntryTemplate` if you just need the template that contains default values
|
||||||
*
|
*
|
||||||
* @type {{[key: string]: { default: any, type: string, excludeFromTemplate?: boolean }}}
|
* @type {{[key: string]: WIEntryFieldDefinition}}
|
||||||
*/
|
*/
|
||||||
export const newWorldInfoEntryDefinition = {
|
export const newWorldInfoEntryDefinition = {
|
||||||
key: { default: [], type: 'array' },
|
key: { default: [], type: 'array' },
|
||||||
@@ -3694,6 +3749,7 @@ export const newWorldInfoEntryDefinition = {
|
|||||||
characterFilterNames: { default: [], type: 'array', excludeFromTemplate: true },
|
characterFilterNames: { default: [], type: 'array', excludeFromTemplate: true },
|
||||||
characterFilterTags: { default: [], type: 'array', excludeFromTemplate: true },
|
characterFilterTags: { default: [], type: 'array', excludeFromTemplate: true },
|
||||||
characterFilterExclude: { default: false, type: 'boolean', excludeFromTemplate: true },
|
characterFilterExclude: { default: false, type: 'boolean', excludeFromTemplate: true },
|
||||||
|
triggers: { default: [], type: 'array', arrayFilter: (value) => GENERATION_TYPE_TRIGGERS.includes(value) },
|
||||||
};
|
};
|
||||||
|
|
||||||
export const newWorldInfoEntryTemplate = Object.fromEntries(
|
export const newWorldInfoEntryTemplate = Object.fromEntries(
|
||||||
@@ -4143,23 +4199,14 @@ function parseDecorators(content) {
|
|||||||
* @param {number} maxContext The maximum context size of the generation.
|
* @param {number} maxContext The maximum context size of the generation.
|
||||||
* @param {boolean} isDryRun Whether to perform a dry run.
|
* @param {boolean} isDryRun Whether to perform a dry run.
|
||||||
* @param {WIGlobalScanData} globalScanData Chat independent context to be scanned
|
* @param {WIGlobalScanData} globalScanData Chat independent context to be scanned
|
||||||
* @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.
|
* @returns {Promise<WIActivated>} The world info activated.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//MARK: checkWorldInfo
|
//MARK: checkWorldInfo
|
||||||
export async function checkWorldInfo(chat, maxContext, isDryRun, globalScanData) {
|
export async function checkWorldInfo(chat, maxContext, isDryRun, globalScanData) {
|
||||||
const context = getContext();
|
const context = getContext();
|
||||||
const buffer = new WorldInfoBuffer(chat, globalScanData);
|
const buffer = new WorldInfoBuffer(chat, globalScanData);
|
||||||
|
|
||||||
console.debug(`[WI] --- START WI SCAN (on ${chat.length} messages)${isDryRun ? ' (DRY RUN)' : ''} ---`);
|
console.debug(`[WI] --- START WI SCAN (on ${chat.length} messages, trigger = ${globalScanData.trigger})${isDryRun ? ' (DRY RUN)' : ''} ---`);
|
||||||
|
|
||||||
// Combine the chat
|
// Combine the chat
|
||||||
|
|
||||||
@@ -4231,7 +4278,7 @@ export async function checkWorldInfo(chat, maxContext, isDryRun, globalScanData)
|
|||||||
// Loop and find all entries that can activate here
|
// Loop and find all entries that can activate here
|
||||||
let activatedNow = new Set();
|
let activatedNow = new Set();
|
||||||
|
|
||||||
for (let entry of sortedEntries) {
|
for (const entry of sortedEntries) {
|
||||||
// Logging preparation
|
// Logging preparation
|
||||||
let headerLogged = false;
|
let headerLogged = false;
|
||||||
function log(...args) {
|
function log(...args) {
|
||||||
@@ -4252,6 +4299,15 @@ export async function checkWorldInfo(chat, maxContext, isDryRun, globalScanData)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for generation type trigger filter
|
||||||
|
if (Array.isArray(entry.triggers) && entry.triggers.length > 0) {
|
||||||
|
const isTriggered = entry.triggers.includes(globalScanData.trigger);
|
||||||
|
if (!isTriggered) {
|
||||||
|
log(`skipped by generation type trigger filter (${globalScanData.trigger} ∉ ${entry.triggers})`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if this entry applies to the character or if it's excluded
|
// Check if this entry applies to the character or if it's excluded
|
||||||
if (entry.characterFilter && entry.characterFilter?.names?.length > 0) {
|
if (entry.characterFilter && entry.characterFilter?.names?.length > 0) {
|
||||||
const nameIncluded = entry.characterFilter.names.includes(getCharaFilename());
|
const nameIncluded = entry.characterFilter.names.includes(getCharaFilename());
|
||||||
@@ -4877,6 +4933,7 @@ function convertAgnaiMemoryBook(inputObj) {
|
|||||||
sticky: null,
|
sticky: null,
|
||||||
cooldown: null,
|
cooldown: null,
|
||||||
delay: null,
|
delay: null,
|
||||||
|
triggers: [],
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -4919,6 +4976,7 @@ function convertRisuLorebook(inputObj) {
|
|||||||
sticky: null,
|
sticky: null,
|
||||||
cooldown: null,
|
cooldown: null,
|
||||||
delay: null,
|
delay: null,
|
||||||
|
triggers: [],
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -4966,6 +5024,7 @@ function convertNovelLorebook(inputObj) {
|
|||||||
sticky: null,
|
sticky: null,
|
||||||
cooldown: null,
|
cooldown: null,
|
||||||
delay: null,
|
delay: null,
|
||||||
|
triggers: [],
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -5022,6 +5081,7 @@ export function convertCharacterBook(characterBook) {
|
|||||||
matchScenario: entry.extensions?.match_scenario ?? false,
|
matchScenario: entry.extensions?.match_scenario ?? false,
|
||||||
matchCreatorNotes: entry.extensions?.match_creator_notes ?? false,
|
matchCreatorNotes: entry.extensions?.match_creator_notes ?? false,
|
||||||
extensions: entry.extensions ?? {},
|
extensions: entry.extensions ?? {},
|
||||||
|
triggers: entry.extensions?.triggers || [],
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -707,6 +707,7 @@ function convertWorldInfoToCharacterBook(name, entries) {
|
|||||||
match_character_depth_prompt: entry.matchCharacterDepthPrompt ?? false,
|
match_character_depth_prompt: entry.matchCharacterDepthPrompt ?? false,
|
||||||
match_scenario: entry.matchScenario ?? false,
|
match_scenario: entry.matchScenario ?? false,
|
||||||
match_creator_notes: entry.matchCreatorNotes ?? false,
|
match_creator_notes: entry.matchCreatorNotes ?? false,
|
||||||
|
triggers: entry.triggers ?? [],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user