Merge branch 'staging' into timed-wi

This commit is contained in:
Cohee
2024-06-23 18:31:40 +03:00
37 changed files with 2019 additions and 734 deletions

View File

@@ -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);