mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Merge branch 'staging' into timed-wi
This commit is contained in:
@@ -13,6 +13,10 @@ import { getRegexedString, regex_placement } from './extensions/regex/engine.js'
|
||||
import { SlashCommandParser } from './slash-commands/SlashCommandParser.js';
|
||||
import { SlashCommand } from './slash-commands/SlashCommand.js';
|
||||
import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './slash-commands/SlashCommandArgument.js';
|
||||
import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandEnumValue.js';
|
||||
import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js';
|
||||
import { SlashCommandExecutor } from './slash-commands/SlashCommandExecutor.js';
|
||||
import { SlashCommandClosure } from './slash-commands/SlashCommandClosure.js';
|
||||
|
||||
export {
|
||||
world_info,
|
||||
@@ -962,21 +966,56 @@ function registerWorldInfoSlashCommands() {
|
||||
return '';
|
||||
}
|
||||
|
||||
/** A collection of local enum providers for this context of world info */
|
||||
const localEnumProviders = {
|
||||
/** All possible fields that can be set in a WI entry */
|
||||
wiEntryFields: () => Object.entries(newEntryDefinition).map(([key, value]) =>
|
||||
new SlashCommandEnumValue(key, `[${value.type}] default: ${(typeof value.default === 'string' ? `'${value.default}'` : value.default)}`,
|
||||
enumTypes.enum, enumIcons.getDataTypeIcon(value.type))),
|
||||
|
||||
/** All existing UIDs based on the file argument as world name */
|
||||
wiUids: (/** @type {SlashCommandExecutor} */ executor) => {
|
||||
const file = executor.namedArgumentList.find(it => it.name == 'file')?.value;
|
||||
if (file instanceof SlashCommandClosure) throw new Error('Argument \'file\' does not support closures');
|
||||
// Try find world from cache
|
||||
const world = worldInfoCache[file];
|
||||
if (!world) return [];
|
||||
return Object.entries(world.entries).map(([uid, data]) =>
|
||||
new SlashCommandEnumValue(uid, `${data.comment ? `${data.comment}: ` : ''}${data.key.join(', ')}${data.keysecondary?.length ? ` [${Object.entries(world_info_logic).find(([_, value]) => value == data.selectiveLogic)[0]}] ${data.keysecondary.join(', ')}` : ''} [${getWiPositionString(data)}]`,
|
||||
enumTypes.enum, enumIcons.getWiStatusIcon(data)));
|
||||
},
|
||||
};
|
||||
|
||||
function getWiPositionString(entry) {
|
||||
switch (entry.position) {
|
||||
case world_info_position.before: return '↑Char';
|
||||
case world_info_position.after: return '↓Char';
|
||||
case world_info_position.EMTop: return '↑EM';
|
||||
case world_info_position.EMBottom: return '↓EM';
|
||||
case world_info_position.ANTop: return '↑AT';
|
||||
case world_info_position.ANBottom: return '↓AT';
|
||||
case world_info_position.atDepth: return `@D${enumIcons.getRoleIcon(entry.role)}`;
|
||||
default: return '<Unknown>';
|
||||
}
|
||||
}
|
||||
|
||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||
name: 'world',
|
||||
callback: onWorldInfoChange,
|
||||
namedArgumentList: [
|
||||
new SlashCommandNamedArgument(
|
||||
'state', 'set world state', [ARGUMENT_TYPE.STRING], false, false, null, ['off', 'toggle'],
|
||||
'state', 'set world state', [ARGUMENT_TYPE.STRING], false, false, null, commonEnumProviders.boolean('onOffToggle')(),
|
||||
),
|
||||
new SlashCommandNamedArgument(
|
||||
'silent', 'suppress toast messages', [ARGUMENT_TYPE.BOOLEAN], false,
|
||||
),
|
||||
],
|
||||
unnamedArgumentList: [
|
||||
new SlashCommandArgument(
|
||||
'name', [ARGUMENT_TYPE.STRING], false,
|
||||
),
|
||||
SlashCommandArgument.fromProps({
|
||||
description: 'world name',
|
||||
typeList: [ARGUMENT_TYPE.STRING],
|
||||
enumProvider: commonEnumProviders.worlds,
|
||||
}),
|
||||
],
|
||||
helpString: `
|
||||
<div>
|
||||
@@ -992,18 +1031,27 @@ function registerWorldInfoSlashCommands() {
|
||||
helpString: 'Get a name of the chat-bound lorebook or create a new one if was unbound, and pass it down the pipe.',
|
||||
aliases: ['getchatlore', 'getchatwi'],
|
||||
}));
|
||||
|
||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||
name: 'findentry',
|
||||
aliases: ['findlore', 'findwi'],
|
||||
returns: 'UID',
|
||||
callback: findBookEntryCallback,
|
||||
namedArgumentList: [
|
||||
new SlashCommandNamedArgument(
|
||||
'file', 'bookName', ARGUMENT_TYPE.STRING, true,
|
||||
),
|
||||
new SlashCommandNamedArgument(
|
||||
'field', 'field value for fuzzy match (default: key)', ARGUMENT_TYPE.STRING, false, false, 'key',
|
||||
),
|
||||
SlashCommandNamedArgument.fromProps({
|
||||
name: 'file',
|
||||
description: 'book name',
|
||||
typeList: [ARGUMENT_TYPE.STRING],
|
||||
isRequired: true,
|
||||
enumProvider: commonEnumProviders.worlds,
|
||||
}),
|
||||
SlashCommandNamedArgument.fromProps({
|
||||
name: 'field',
|
||||
description: 'field value for fuzzy match (default: key)',
|
||||
typeList: [ARGUMENT_TYPE.STRING],
|
||||
defaultValue: 'key',
|
||||
enumList: localEnumProviders.wiEntryFields(),
|
||||
}),
|
||||
],
|
||||
unnamedArgumentList: [
|
||||
new SlashCommandArgument(
|
||||
@@ -1030,17 +1078,28 @@ function registerWorldInfoSlashCommands() {
|
||||
callback: getEntryFieldCallback,
|
||||
returns: 'field value',
|
||||
namedArgumentList: [
|
||||
new SlashCommandNamedArgument(
|
||||
'file', 'bookName', ARGUMENT_TYPE.STRING, true,
|
||||
),
|
||||
new SlashCommandNamedArgument(
|
||||
'field', 'field to retrieve (default: content)', ARGUMENT_TYPE.STRING, false, false, 'content',
|
||||
),
|
||||
SlashCommandNamedArgument.fromProps({
|
||||
name: 'file',
|
||||
description: 'book name',
|
||||
typeList: [ARGUMENT_TYPE.STRING],
|
||||
isRequired: true,
|
||||
enumProvider: commonEnumProviders.worlds,
|
||||
}),
|
||||
SlashCommandNamedArgument.fromProps({
|
||||
name: 'field',
|
||||
description: 'field to retrieve (default: content)',
|
||||
typeList: [ARGUMENT_TYPE.STRING],
|
||||
defaultValue: 'content',
|
||||
enumList: localEnumProviders.wiEntryFields(),
|
||||
}),
|
||||
],
|
||||
unnamedArgumentList: [
|
||||
new SlashCommandArgument(
|
||||
'UID', ARGUMENT_TYPE.STRING, true,
|
||||
),
|
||||
SlashCommandArgument.fromProps({
|
||||
description: 'record UID',
|
||||
typeList: [ARGUMENT_TYPE.STRING],
|
||||
isRequired: true,
|
||||
enumProvider: localEnumProviders.wiUids,
|
||||
}),
|
||||
],
|
||||
helpString: `
|
||||
<div>
|
||||
@@ -1062,9 +1121,13 @@ function registerWorldInfoSlashCommands() {
|
||||
aliases: ['createlore', 'createwi'],
|
||||
returns: 'UID of the new record',
|
||||
namedArgumentList: [
|
||||
new SlashCommandNamedArgument(
|
||||
'file', 'book name', [ARGUMENT_TYPE.STRING], true,
|
||||
),
|
||||
SlashCommandNamedArgument.fromProps({
|
||||
name: 'file',
|
||||
description: 'book name',
|
||||
typeList: [ARGUMENT_TYPE.STRING],
|
||||
isRequired: true,
|
||||
enumProvider: commonEnumProviders.worlds,
|
||||
}),
|
||||
new SlashCommandNamedArgument(
|
||||
'key', 'record key', [ARGUMENT_TYPE.STRING], false,
|
||||
),
|
||||
@@ -1093,15 +1156,27 @@ function registerWorldInfoSlashCommands() {
|
||||
callback: setEntryFieldCallback,
|
||||
aliases: ['setlorefield', 'setwifield'],
|
||||
namedArgumentList: [
|
||||
new SlashCommandNamedArgument(
|
||||
'file', 'book name', [ARGUMENT_TYPE.STRING], true,
|
||||
),
|
||||
new SlashCommandNamedArgument(
|
||||
'uid', 'record UID', [ARGUMENT_TYPE.STRING], true,
|
||||
),
|
||||
new SlashCommandNamedArgument(
|
||||
'field', 'field name', [ARGUMENT_TYPE.STRING], true, false, 'content',
|
||||
),
|
||||
SlashCommandNamedArgument.fromProps({
|
||||
name: 'file',
|
||||
description: 'book name',
|
||||
typeList: [ARGUMENT_TYPE.STRING],
|
||||
isRequired: true,
|
||||
enumProvider: commonEnumProviders.worlds,
|
||||
}),
|
||||
SlashCommandNamedArgument.fromProps({
|
||||
name: 'uid',
|
||||
description: 'record UID',
|
||||
typeList: [ARGUMENT_TYPE.STRING],
|
||||
isRequired: true,
|
||||
enumProvider: localEnumProviders.wiUids,
|
||||
}),
|
||||
SlashCommandNamedArgument.fromProps({
|
||||
name: 'field',
|
||||
description: 'field name (default: content)',
|
||||
typeList: [ARGUMENT_TYPE.STRING],
|
||||
defaultValue: 'content',
|
||||
enumList: localEnumProviders.wiEntryFields(),
|
||||
}),
|
||||
],
|
||||
unnamedArgumentList: [
|
||||
new SlashCommandArgument(
|
||||
@@ -2748,38 +2823,49 @@ function deleteWorldInfoEntry(data, uid) {
|
||||
delete data.entries[uid];
|
||||
}
|
||||
|
||||
const newEntryTemplate = {
|
||||
key: [],
|
||||
keysecondary: [],
|
||||
comment: '',
|
||||
content: '',
|
||||
constant: false,
|
||||
vectorized: false,
|
||||
selective: true,
|
||||
selectiveLogic: world_info_logic.AND_ANY,
|
||||
addMemo: false,
|
||||
order: 100,
|
||||
position: 0,
|
||||
disable: false,
|
||||
excludeRecursion: false,
|
||||
preventRecursion: false,
|
||||
delayUntilRecursion: false,
|
||||
probability: 100,
|
||||
useProbability: true,
|
||||
depth: DEFAULT_DEPTH,
|
||||
group: '',
|
||||
groupOverride: false,
|
||||
groupWeight: DEFAULT_WEIGHT,
|
||||
scanDepth: null,
|
||||
caseSensitive: null,
|
||||
matchWholeWords: null,
|
||||
useGroupScoring: null,
|
||||
automationId: '',
|
||||
role: 0,
|
||||
sticky: null,
|
||||
cooldown: null,
|
||||
/**
|
||||
* Definitions of types for new WI entries
|
||||
*
|
||||
* Use `newEntryTemplate` if you just need the template that contains default values
|
||||
*
|
||||
* @type {{[key: string]: { default: any, type: string }}}
|
||||
*/
|
||||
const newEntryDefinition = {
|
||||
key: { default: [], type: 'array' },
|
||||
keysecondary: { default: [], type: 'array' },
|
||||
comment: { default: '', type: 'string' },
|
||||
content: { default: '', type: 'string' },
|
||||
constant: { default: false, type: 'boolean' },
|
||||
vectorized: { default: false, type: 'boolean' },
|
||||
selective: { default: true, type: 'boolean' },
|
||||
selectiveLogic: { default: world_info_logic.AND_ANY, type: 'enum' },
|
||||
addMemo: { default: false, type: 'boolean' },
|
||||
order: { default: 100, type: 'number' },
|
||||
position: { default: 0, type: 'number' },
|
||||
disable: { default: false, type: 'boolean' },
|
||||
excludeRecursion: { default: false, type: 'boolean' },
|
||||
preventRecursion: { default: false, type: 'boolean' },
|
||||
delayUntilRecursion: { default: false, type: 'boolean' },
|
||||
probability: { default: 100, type: 'number' },
|
||||
useProbability: { default: true, type: 'boolean' },
|
||||
depth: { default: DEFAULT_DEPTH, type: 'number' },
|
||||
group: { default: '', type: 'string' },
|
||||
groupOverride: { default: false, type: 'boolean' },
|
||||
groupWeight: { default: DEFAULT_WEIGHT, type: 'number' },
|
||||
scanDepth: { default: null, type: 'number?' },
|
||||
caseSensitive: { default: null, type: 'boolean?' },
|
||||
matchWholeWords: { default: null, type: 'boolean?' },
|
||||
useGroupScoring: { default: null, type: 'boolean?' },
|
||||
automationId: { default: '', type: 'string' },
|
||||
role: { default: 0, type: 'enum' },
|
||||
sticky: { default: null, type: 'number?' },
|
||||
cooldown: { default: null, type: 'number?' },
|
||||
};
|
||||
|
||||
const newEntryTemplate = Object.fromEntries(
|
||||
Object.entries(newEntryDefinition).map(([key, value]) => [key, value.default]),
|
||||
);
|
||||
|
||||
function createWorldInfoEntry(_name, data) {
|
||||
const newUid = getFreeWorldEntryUid(data);
|
||||
|
||||
@@ -3829,6 +3915,7 @@ function onWorldInfoChange(args, text) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'on':
|
||||
default: {
|
||||
selected_world_info.push(name);
|
||||
wiElement.prop('selected', true);
|
||||
|
Reference in New Issue
Block a user