Export and doc most of wi functions
| @@ -18,33 +18,13 @@ import { SlashCommandClosure } from './slash-commands/SlashCommandClosure.js'; | ||
| 18 | 18 | import { callGenericPopup, Popup, POPUP_TYPE } from './popup.js'; |
| 19 | 19 | import { StructuredCloneMap } from './util/StructuredCloneMap.js'; |
| 20 | 20 | |
| 21 | 21 | export const world_info_insertion_strategy = { |
| 22 | - world_info, | |
| 23 | - world_info_budget, | |
| 24 | - world_info_depth, | |
| 25 | - world_info_min_activations, | |
| 26 | - world_info_min_activations_depth_max, | |
| 27 | - world_info_include_names, | |
| 28 | - world_info_recursive, | |
| 29 | - world_info_overflow_alert, | |
| 30 | - world_info_case_sensitive, | |
| 31 | - world_info_match_whole_words, | |
| 32 | - world_info_character_strategy, | |
| 33 | - world_info_budget_cap, | |
| 34 | - world_names, | |
| 35 | - checkWorldInfo, | |
| 36 | - deleteWorldInfo, | |
| 37 | - setWorldInfoSettings, | |
| 38 | - getWorldInfoPrompt, | |
| 39 | -}; | |
| 40 | - | |
| 41 | -const world_info_insertion_strategy = { | |
| 42 | 22 | evenly: 0, |
| 43 | 23 | character_first: 1, |
| 44 | 24 | global_first: 2, |
| 45 | 25 | }; |
| 46 | 26 | |
| 47 | 27 | export const world_info_logic = { |
| 48 | 28 | AND_ANY: 0, |
| 49 | 29 | NOT_ALL: 1, |
| 50 | 30 | NOT_ANY: 2, |
| @@ -54,7 +34,7 @@ const world_info_logic = { | ||
| 54 | 34 | /** |
| 55 | 35 | * @enum {number} Possible states of the WI evaluation |
| 56 | 36 | */ |
| 57 | 37 | export const scan_state = { |
| 58 | 38 | /** |
| 59 | 39 | * The scan will be stopped. |
| 60 | 40 | */ |
| @@ -75,23 +55,23 @@ const scan_state = { | ||
| 75 | 55 | |
| 76 | 56 | const WI_ENTRY_EDIT_TEMPLATE = $('#entry_edit_template .world_entry'); |
| 77 | 57 | |
| 78 | 58 | export let world_info = {}; |
| 79 | 59 | export let selected_world_info = []; |
| 80 | 60 | /** @type {string[]} */ |
| 81 | 61 | export let world_names; |
| 82 | 62 | export let world_info_depth = 2; |
| 83 | 63 | export let world_info_min_activations = 0; // if > 0, will continue seeking chat until minimum world infos are activated |
| 84 | 64 | export let world_info_min_activations_depth_max = 0; // used when (world_info_min_activations > 0) |
| 85 | 65 | |
| 86 | 66 | export let world_info_budget = 25; |
| 87 | 67 | export let world_info_include_names = true; |
| 88 | 68 | export let world_info_recursive = false; |
| 89 | 69 | export let world_info_overflow_alert = false; |
| 90 | 70 | export let world_info_case_sensitive = false; |
| 91 | 71 | export let world_info_match_whole_words = false; |
| 92 | 72 | export let world_info_use_group_scoring = false; |
| 93 | 73 | export let world_info_character_strategy = world_info_insertion_strategy.character_first; |
| 94 | 74 | export let world_info_budget_cap = 0; |
| 95 | 75 | const saveWorldDebounced = debounce(async (name, data) => await _save(name, data), debounce_timeout.relaxed); |
| 96 | 76 | const saveSettingsDebounced = debounce(() => { |
| 97 | 77 | Object.assign(world_info, { globalSelect: selected_world_info }); |
| @@ -101,13 +81,13 @@ const sortFn = (a, b) => b.order - a.order; | ||
| 101 | 81 | let updateEditor = (navigation, flashOnNav = true) => { console.debug('Triggered WI navigation', navigation, flashOnNav); }; |
| 102 | 82 | |
| 103 | 83 | // Do not optimize. updateEditor is a function that is updated by the displayWorldEntries with new data. |
| 104 | 84 | export const worldInfoFilter = new FilterHelper(() => updateEditor()); |
| 105 | 85 | export const SORT_ORDER_KEY = 'world_info_sort_order'; |
| 106 | 86 | export const METADATA_KEY = 'world_info'; |
| 107 | 87 | |
| 108 | 88 | export const DEFAULT_DEPTH = 4; |
| 109 | 89 | export const DEFAULT_WEIGHT = 100; |
| 110 | 90 | export const MAX_SCAN_DEPTH = 1000; |
| 111 | 91 | const KNOWN_DECORATORS = ['@@activate', '@@dont_activate']; |
| 112 | 92 | |
| 113 | 93 | // Typedef area |
| @@ -732,7 +712,7 @@ export function getWorldInfoSettings() { | ||
| 732 | 712 | }; |
| 733 | 713 | } |
| 734 | 714 | |
| 735 | 715 | export const world_info_position = { |
| 736 | 716 | before: 0, |
| 737 | 717 | after: 1, |
| 738 | 718 | ANTop: 2, |
| @@ -747,8 +727,18 @@ export const wi_anchor_position = { | ||
| 747 | 727 | after: 1, |
| 748 | 728 | }; |
| 749 | 729 | |
| 750 | -/** @type {StructuredCloneMap<string,object>} */ | |
| 730 | +/** | |
| 751 | -const worldInfoCache = new StructuredCloneMap({ cloneOnGet: true, cloneOnSet: false }); | |
| 731 | + * The cache of all world info data that was loaded from the backend. | |
| 732 | + * | |
| 733 | + * Calling `loadWorldInfo` will fill this cache and utilize this cache, so should be the preferred way to load any world info data. | |
| 734 | + * Only use the cache directly if you need synchronous access. | |
| 735 | + * | |
| 736 | + * This will return a deep clone of the data, so no way to modify the data without actually saving it. | |
| 737 | + * Should generally be only used for readonly access. | |
| 738 | + * | |
| 739 | + * @type {StructuredCloneMap<string,object>} | |
| 740 | + * */ | |
| 741 | +export const worldInfoCache = new StructuredCloneMap({ cloneOnGet: true, cloneOnSet: false }); | |
| 752 | 742 | |
| 753 | 743 | /** |
| 754 | 744 | * Gets the world info based on chat messages. |
| @@ -758,7 +748,7 @@ const worldInfoCache = new StructuredCloneMap({ cloneOnGet: true, cloneOnSet: fa | ||
| 758 | 748 | * @typedef {{worldInfoString: string, worldInfoBefore: string, worldInfoAfter: string, worldInfoExamples: any[], worldInfoDepth: any[]}} WIPromptResult |
| 759 | 749 | * @returns {Promise<WIPromptResult>} The world info string and depth. |
| 760 | 750 | */ |
| 761 | 751 | export async function getWorldInfoPrompt(chat, maxContext, isDryRun) { |
| 762 | 752 | let worldInfoString = '', worldInfoBefore = '', worldInfoAfter = ''; |
| 763 | 753 | |
| 764 | 754 | const activatedWorldInfo = await checkWorldInfo(chat, maxContext, isDryRun); |
| @@ -780,7 +770,7 @@ async function getWorldInfoPrompt(chat, maxContext, isDryRun) { | ||
| 780 | 770 | }; |
| 781 | 771 | } |
| 782 | 772 | |
| 783 | 773 | export function setWorldInfoSettings(settings, data) { |
| 784 | 774 | if (settings.world_info_depth !== undefined) |
| 785 | 775 | world_info_depth = Number(settings.world_info_depth); |
| 786 | 776 | if (settings.world_info_min_activations !== undefined) |
| @@ -916,7 +906,7 @@ function registerWorldInfoSlashCommands() { | ||
| 916 | 906 | return ''; |
| 917 | 907 | } |
| 918 | 908 | |
| 919 | 909 | const data = await loadWorldInfoDataloadWorldInfo(file); |
| 920 | 910 | |
| 921 | 911 | if (!data || !('entries' in data)) { |
| 922 | 912 | toastr.warning('World Info file has an invalid format'); |
| @@ -965,7 +955,7 @@ function registerWorldInfoSlashCommands() { | ||
| 965 | 955 | return ''; |
| 966 | 956 | } |
| 967 | 957 | |
| 968 | 958 | if (typeof newEntryTemplatenewWorldInfoEntryTemplate[field] === 'boolean') { |
| 969 | 959 | const isTrue = isTrueBoolean(value); |
| 970 | 960 | const isFalse = isFalseBoolean(value); |
| 971 | 961 | |
| @@ -1016,7 +1006,7 @@ function registerWorldInfoSlashCommands() { | ||
| 1016 | 1006 | return ''; |
| 1017 | 1007 | } |
| 1018 | 1008 | |
| 1019 | 1009 | if (newEntryTemplatenewWorldInfoEntryTemplate[field] === undefined) { |
| 1020 | 1010 | toastr.warning('Valid field name is required'); |
| 1021 | 1011 | return ''; |
| 1022 | 1012 | } |
| @@ -1038,7 +1028,7 @@ function registerWorldInfoSlashCommands() { | ||
| 1038 | 1028 | const file = args.file; |
| 1039 | 1029 | const key = args.key; |
| 1040 | 1030 | |
| 1041 | 1031 | const data = await loadWorldInfoDataloadWorldInfo(file); |
| 1042 | 1032 | |
| 1043 | 1033 | if (!data || !('entries' in data)) { |
| 1044 | 1034 | toastr.warning('Valid World Info file name is required'); |
| @@ -1075,7 +1065,7 @@ function registerWorldInfoSlashCommands() { | ||
| 1075 | 1065 | |
| 1076 | 1066 | value = value.replace(/\\([{}|])/g, '$1'); |
| 1077 | 1067 | |
| 1078 | 1068 | const data = await loadWorldInfoDataloadWorldInfo(file); |
| 1079 | 1069 | |
| 1080 | 1070 | if (!data || !('entries' in data)) { |
| 1081 | 1071 | toastr.warning('Valid World Info file name is required'); |
| @@ -1089,7 +1079,7 @@ function registerWorldInfoSlashCommands() { | ||
| 1089 | 1079 | return ''; |
| 1090 | 1080 | } |
| 1091 | 1081 | |
| 1092 | 1082 | if (newEntryTemplatenewWorldInfoEntryTemplate[field] === undefined) { |
| 1093 | 1083 | toastr.warning('Valid field name is required'); |
| 1094 | 1084 | return ''; |
| 1095 | 1085 | } |
| @@ -1104,8 +1094,8 @@ function registerWorldInfoSlashCommands() { | ||
| 1104 | 1094 | entry[field] = value; |
| 1105 | 1095 | } |
| 1106 | 1096 | |
| 1107 | 1097 | if (originalDataKeyMaporiginalWIDataKeyMap[field]) { |
| 1108 | 1098 | setOriginalDataValuesetWIOriginalDataValue(data, uid, originalDataKeyMaporiginalWIDataKeyMap[field], entry[field]); |
| 1109 | 1099 | } |
| 1110 | 1100 | |
| 1111 | 1101 | await saveWorldInfo(file, data); |
| @@ -1226,7 +1216,7 @@ function registerWorldInfoSlashCommands() { | ||
| 1226 | 1216 | /** A collection of local enum providers for this context of world info */ |
| 1227 | 1217 | const localEnumProviders = { |
| 1228 | 1218 | /** All possible fields that can be set in a WI entry */ |
| 1229 | 1219 | wiEntryFields: () => Object.entries(newEntryDefinitionnewWorldInfoEntryDefinition).map(([key, value]) => |
| 1230 | 1220 | new SlashCommandEnumValue(key, `[${value.type}] default: ${(typeof value.default === 'string' ? `'${value.default}'` : value.default)}`, |
| 1231 | 1221 | enumTypes.enum, enumIcons.getDataTypeIcon(value.type))), |
| 1232 | 1222 | |
| @@ -1566,18 +1556,32 @@ function registerWorldInfoSlashCommands() { | ||
| 1566 | 1556 | })); |
| 1567 | 1557 | } |
| 1568 | 1558 | |
| 1569 | -// World Info Editor | |
| 1559 | + | |
| 1570 | -async function showWorldEditor(name) { | |
| 1560 | +/** | |
| 1561 | + * Loads the given world into the World Editor. | |
| 1562 | + * | |
| 1563 | + * @param {string} name - The name of the world | |
| 1564 | + * @return {Promise<void>} A promise that resolves when the world editor is loaded | |
| 1565 | + */ | |
| 1566 | +export async function showWorldEditor(name) { | |
| 1571 | 1567 | if (!name) { |
| 1572 | 1568 | hideWorldEditor(); |
| 1573 | 1569 | return; |
| 1574 | 1570 | } |
| 1575 | 1571 | |
| 1576 | 1572 | const wiData = await loadWorldInfoDataloadWorldInfo(name); |
| 1577 | 1573 | displayWorldEntries(name, wiData); |
| 1578 | 1574 | } |
| 1579 | 1575 | |
| 1580 | -async function loadWorldInfoData(name) { | |
| 1576 | +/** | |
| 1577 | + * Loads world info from the backend. | |
| 1578 | + * | |
| 1579 | + * This function will return from `worldInfoCache` if it has already been loaded before. | |
| 1580 | + * | |
| 1581 | + * @param {string} name - The name of the world to load | |
| 1582 | + * @return {Promise<Object|null>} A promise that resolves to the loaded world information, or null if the request fails. | |
| 1583 | + */ | |
| 1584 | +export async function loadWorldInfo(name) { | |
| 1581 | 1585 | if (!name) { |
| 1582 | 1586 | return; |
| 1583 | 1587 | } |
| @@ -1635,10 +1639,12 @@ function getWIElement(name) { | ||
| 1635 | 1639 | } |
| 1636 | 1640 | |
| 1637 | 1641 | /** |
| 1642 | + * Sorts the given data based on the selected sort option | |
| 1643 | + * | |
| 1638 | 1644 | * @param {any[]} data WI entries |
| 1639 | 1645 | * @returns {any[]} Sorted data |
| 1640 | 1646 | */ |
| 1641 | 1647 | export function sortEntriessortWorldInfoEntries(data) { |
| 1642 | 1648 | const option = $('#world_info_sort_order').find(':selected'); |
| 1643 | 1649 | const sortField = option.data('field'); |
| 1644 | 1650 | const sortOrder = option.data('order'); |
| @@ -1801,7 +1807,7 @@ function displayWorldEntries(name, data, navigation = navigation_option.none, fl | ||
| 1801 | 1807 | |
| 1802 | 1808 | // Apply the filter and do the chosen sorting |
| 1803 | 1809 | entriesArray = worldInfoFilter.applyFilters(entriesArray); |
| 1804 | 1810 | entriesArray = sortEntriessortWorldInfoEntries(entriesArray); |
| 1805 | 1811 | |
| 1806 | 1812 | // Cache keys |
| 1807 | 1813 | const keys = entriesArray.flatMap(entry => [...entry.key, ...entry.keysecondary]); |
| @@ -1919,7 +1925,7 @@ function displayWorldEntries(name, data, navigation = navigation_option.none, fl | ||
| 1919 | 1925 | for (const entry of Object.values(data.entries)) { |
| 1920 | 1926 | if (!entry.comment && Array.isArray(entry.key) && entry.key.length > 0) { |
| 1921 | 1927 | entry.comment = entry.key[0]; |
| 1922 | 1928 | setOriginalDataValuesetWIOriginalDataValue(data, entry.uid, 'comment', entry.comment); |
| 1923 | 1929 | counter++; |
| 1924 | 1930 | } |
| 1925 | 1931 | } |
| @@ -1954,7 +1960,7 @@ function displayWorldEntries(name, data, navigation = navigation_option.none, fl | ||
| 1954 | 1960 | |
| 1955 | 1961 | // We need to sort the entries here, as the data source isn't sorted |
| 1956 | 1962 | const entries = Object.values(data.entries); |
| 1957 | 1963 | sortEntriessortWorldInfoEntries(entries); |
| 1958 | 1964 | |
| 1959 | 1965 | let updated = 0, current = start; |
| 1960 | 1966 | for (const entry of entries) { |
| @@ -1962,7 +1968,7 @@ function displayWorldEntries(name, data, navigation = navigation_option.none, fl | ||
| 1962 | 1968 | if (entry.order === newOrder) continue; |
| 1963 | 1969 | |
| 1964 | 1970 | entry.order = newOrder; |
| 1965 | 1971 | setOriginalDataValuesetWIOriginalDataValue(data, entry.order, 'order', entry.order); |
| 1966 | 1972 | updated++; |
| 1967 | 1973 | } |
| 1968 | 1974 | |
| @@ -2025,7 +2031,7 @@ function displayWorldEntries(name, data, navigation = navigation_option.none, fl | ||
| 2025 | 2031 | } |
| 2026 | 2032 | |
| 2027 | 2033 | item.displayIndex = minDisplayIndex + index; |
| 2028 | 2034 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.display_index', item.displayIndex); |
| 2029 | 2035 | }); |
| 2030 | 2036 | |
| 2031 | 2037 | console.table(Object.keys(data.entries).map(uid => data.entries[uid]).map(x => ({ uid: x.uid, key: x.key.join(','), displayIndex: x.displayIndex }))); |
| @@ -2036,7 +2042,7 @@ function displayWorldEntries(name, data, navigation = navigation_option.none, fl | ||
| 2036 | 2042 | //$("#world_popup_entries_list").disableSelection(); |
| 2037 | 2043 | } |
| 2038 | 2044 | |
| 2039 | 2045 | export const originalDataKeyMaporiginalWIDataKeyMap = { |
| 2040 | 2046 | 'displayIndex': 'extensions.display_index', |
| 2041 | 2047 | 'excludeRecursion': 'extensions.exclude_recursion', |
| 2042 | 2048 | 'preventRecursion': 'extensions.prevent_recursion', |
| @@ -2087,7 +2093,17 @@ function verifyWorldInfoSearchSortRule() { | ||
| 2087 | 2093 | } |
| 2088 | 2094 | } |
| 2089 | 2095 | |
| 2090 | -function setOriginalDataValue(data, uid, key, value) { | |
| 2096 | +/** | |
| 2097 | + * Sets the value of a specific key in the original data entry corresponding to the given uid | |
| 2098 | + * This needs to be called whenever you update JSON data fields. | |
| 2099 | + * Use `originalWIDataKeyMap` to find the correct value to be set. | |
| 2100 | + * | |
| 2101 | + * @param {object} data - The data object containing the original data entries. | |
| 2102 | + * @param {string} uid - The unique identifier of the data entry. | |
| 2103 | + * @param {string} key - The key of the value to be set. | |
| 2104 | + * @param {any} value - The value to be set. | |
| 2105 | + */ | |
| 2106 | +export function setWIOriginalDataValue(data, uid, key, value) { | |
| 2091 | 2107 | if (data.originalData && Array.isArray(data.originalData.entries)) { |
| 2092 | 2108 | let originalEntry = data.originalData.entries.find(x => x.uid === uid); |
| 2093 | 2109 | |
| @@ -2099,7 +2115,7 @@ function setOriginalDataValue(data, uid, key, value) { | ||
| 2099 | 2115 | } |
| 2100 | 2116 | } |
| 2101 | 2117 | |
| 2102 | 2118 | function deleteOriginalDataValuedeleteWIOriginalDataValue(data, uid) { |
| 2103 | 2119 | if (data.originalData && Array.isArray(data.originalData.entries)) { |
| 2104 | 2120 | const originalIndex = data.originalData.entries.findIndex(x => x.uid === uid); |
| 2105 | 2121 | |
| @@ -2120,7 +2136,7 @@ function deleteOriginalDataValue(data, uid) { | ||
| 2120 | 2136 | * @param {string} input - One or multiple keywords or regexes, separated by commas |
| 2121 | 2137 | * @returns {string[]} An array of keywords and regexes |
| 2122 | 2138 | */ |
| 2123 | 2139 | export function splitKeywordsAndRegexes(input) { |
| 2124 | 2140 | /** @type {string[]} */ |
| 2125 | 2141 | let keywordsAndRegexes = []; |
| 2126 | 2142 | |
| @@ -2224,7 +2240,7 @@ function isValidRegex(input) { | ||
| 2224 | 2240 | * @param {string} input - A delimited regex string |
| 2225 | 2241 | * @returns {RegExp|null} The regex object, or null if not a valid regex |
| 2226 | 2242 | */ |
| 2227 | 2243 | export function parseRegexFromString(input) { |
| 2228 | 2244 | // Extracting the regex pattern and flags |
| 2229 | 2245 | let match = input.match(/^\/([\w\W]+?)\/([gimsuy]*)$/); |
| 2230 | 2246 | if (!match) { |
| @@ -2310,7 +2326,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2310 | 2326 | !skipReset && resetScrollHeight(this); |
| 2311 | 2327 | if (!noSave) { |
| 2312 | 2328 | data.entries[uid][entryPropName] = keys; |
| 2313 | 2329 | setOriginalDataValuesetWIOriginalDataValue(data, uid, originalDataValueName, data.entries[uid][entryPropName]); |
| 2314 | 2330 | await saveWorldInfo(name, data); |
| 2315 | 2331 | } |
| 2316 | 2332 | }); |
| @@ -2348,7 +2364,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2348 | 2364 | !skipReset && resetScrollHeight(this); |
| 2349 | 2365 | if (!noSave) { |
| 2350 | 2366 | data.entries[uid][entryPropName] = splitKeywordsAndRegexes(value); |
| 2351 | 2367 | setOriginalDataValuesetWIOriginalDataValue(data, uid, originalDataValueName, data.entries[uid][entryPropName]); |
| 2352 | 2368 | await saveWorldInfo(name, data); |
| 2353 | 2369 | } |
| 2354 | 2370 | }); |
| @@ -2392,7 +2408,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2392 | 2408 | const uid = $(this).data('uid'); |
| 2393 | 2409 | const value = Number($(this).val()); |
| 2394 | 2410 | data.entries[uid].selectiveLogic = !isNaN(value) ? value : world_info_logic.AND_ANY; |
| 2395 | 2411 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'selectiveLogic', data.entries[uid].selectiveLogic); |
| 2396 | 2412 | await saveWorldInfo(name, data); |
| 2397 | 2413 | }); |
| 2398 | 2414 | |
| @@ -2441,7 +2457,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2441 | 2457 | } |
| 2442 | 2458 | } |
| 2443 | 2459 | |
| 2444 | 2460 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'character_filter', data.entries[uid].characterFilter); |
| 2445 | 2461 | await saveWorldInfo(name, data); |
| 2446 | 2462 | }); |
| 2447 | 2463 | characterExclusionInput.prop('checked', entry.characterFilter?.isExclude ?? false).trigger('input'); |
| @@ -2503,7 +2519,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2503 | 2519 | }, |
| 2504 | 2520 | ); |
| 2505 | 2521 | } |
| 2506 | 2522 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'character_filter', data.entries[uid].characterFilter); |
| 2507 | 2523 | await saveWorldInfo(name, data); |
| 2508 | 2524 | }); |
| 2509 | 2525 | |
| @@ -2517,7 +2533,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2517 | 2533 | !skipReset && resetScrollHeight(this); |
| 2518 | 2534 | data.entries[uid].comment = value; |
| 2519 | 2535 | |
| 2520 | 2536 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'comment', data.entries[uid].comment); |
| 2521 | 2537 | await saveWorldInfo(name, data); |
| 2522 | 2538 | }); |
| 2523 | 2539 | commentToggle.data('uid', entry.uid); |
| @@ -2552,7 +2568,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2552 | 2568 | const value = $(this).val(); |
| 2553 | 2569 | data.entries[uid].content = value; |
| 2554 | 2570 | |
| 2555 | 2571 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'content', data.entries[uid].content); |
| 2556 | 2572 | await saveWorldInfo(name, data); |
| 2557 | 2573 | |
| 2558 | 2574 | if (skipCount) { |
| @@ -2582,7 +2598,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2582 | 2598 | const value = $(this).prop('checked'); |
| 2583 | 2599 | data.entries[uid].selective = value; |
| 2584 | 2600 | |
| 2585 | 2601 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'selective', data.entries[uid].selective); |
| 2586 | 2602 | await saveWorldInfo(name, data); |
| 2587 | 2603 | |
| 2588 | 2604 | const keysecondary = $(this) |
| @@ -2631,7 +2647,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2631 | 2647 | |
| 2632 | 2648 | data.entries[uid].order = !isNaN(value) ? value : 0; |
| 2633 | 2649 | updatePosOrdDisplay(uid); |
| 2634 | 2650 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'insertion_order', data.entries[uid].order); |
| 2635 | 2651 | await saveWorldInfo(name, data); |
| 2636 | 2652 | }); |
| 2637 | 2653 | orderInput.val(entry.order).trigger('input'); |
| @@ -2645,7 +2661,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2645 | 2661 | const value = String($(this).val()).trim(); |
| 2646 | 2662 | |
| 2647 | 2663 | data.entries[uid].group = value; |
| 2648 | 2664 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.group', data.entries[uid].group); |
| 2649 | 2665 | await saveWorldInfo(name, data); |
| 2650 | 2666 | }); |
| 2651 | 2667 | groupInput.val(entry.group ?? '').trigger('input'); |
| @@ -2658,7 +2674,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2658 | 2674 | const uid = $(this).data('uid'); |
| 2659 | 2675 | const value = $(this).prop('checked'); |
| 2660 | 2676 | data.entries[uid].groupOverride = value; |
| 2661 | 2677 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.group_override', data.entries[uid].groupOverride); |
| 2662 | 2678 | await saveWorldInfo(name, data); |
| 2663 | 2679 | }); |
| 2664 | 2680 | groupOverrideInput.prop('checked', entry.groupOverride).trigger('input'); |
| @@ -2682,7 +2698,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2682 | 2698 | } |
| 2683 | 2699 | |
| 2684 | 2700 | data.entries[uid].groupWeight = !isNaN(value) ? Math.abs(value) : 1; |
| 2685 | 2701 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.group_weight', data.entries[uid].groupWeight); |
| 2686 | 2702 | await saveWorldInfo(name, data); |
| 2687 | 2703 | }); |
| 2688 | 2704 | groupWeightInput.val(entry.groupWeight ?? DEFAULT_WEIGHT).trigger('input'); |
| @@ -2695,7 +2711,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2695 | 2711 | const value = Number($(this).val()); |
| 2696 | 2712 | data.entries[uid].sticky = !isNaN(value) ? value : null; |
| 2697 | 2713 | |
| 2698 | 2714 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.sticky', data.entries[uid].sticky); |
| 2699 | 2715 | await saveWorldInfo(name, data); |
| 2700 | 2716 | }); |
| 2701 | 2717 | sticky.val(entry.sticky > 0 ? entry.sticky : '').trigger('input'); |
| @@ -2708,7 +2724,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2708 | 2724 | const value = Number($(this).val()); |
| 2709 | 2725 | data.entries[uid].cooldown = !isNaN(value) ? value : null; |
| 2710 | 2726 | |
| 2711 | 2727 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.cooldown', data.entries[uid].cooldown); |
| 2712 | 2728 | await saveWorldInfo(name, data); |
| 2713 | 2729 | }); |
| 2714 | 2730 | cooldown.val(entry.cooldown > 0 ? entry.cooldown : '').trigger('input'); |
| @@ -2721,7 +2737,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2721 | 2737 | const value = Number($(this).val()); |
| 2722 | 2738 | data.entries[uid].delay = !isNaN(value) ? value : null; |
| 2723 | 2739 | |
| 2724 | 2740 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.delay', data.entries[uid].delay); |
| 2725 | 2741 | await saveWorldInfo(name, data); |
| 2726 | 2742 | }); |
| 2727 | 2743 | delay.val(entry.delay > 0 ? entry.delay : '').trigger('input'); |
| @@ -2741,7 +2757,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2741 | 2757 | |
| 2742 | 2758 | data.entries[uid].depth = !isNaN(value) ? value : 0; |
| 2743 | 2759 | updatePosOrdDisplay(uid); |
| 2744 | 2760 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.depth', data.entries[uid].depth); |
| 2745 | 2761 | await saveWorldInfo(name, data); |
| 2746 | 2762 | }); |
| 2747 | 2763 | depthInput.val(entry.depth ?? DEFAULT_DEPTH).trigger('input'); |
| @@ -2769,7 +2785,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2769 | 2785 | } |
| 2770 | 2786 | } |
| 2771 | 2787 | |
| 2772 | 2788 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.probability', data.entries[uid].probability); |
| 2773 | 2789 | await saveWorldInfo(name, data); |
| 2774 | 2790 | }); |
| 2775 | 2791 | probabilityInput.val(entry.probability).trigger('input'); |
| @@ -2836,10 +2852,10 @@ function getWorldEntry(name, data, entry) { | ||
| 2836 | 2852 | } |
| 2837 | 2853 | updatePosOrdDisplay(uid); |
| 2838 | 2854 | // Spec v2 only supports before_char and after_char |
| 2839 | 2855 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'position', data.entries[uid].position == 0 ? 'before_char' : 'after_char'); |
| 2840 | 2856 | // Write the original value as extensions field |
| 2841 | 2857 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.position', data.entries[uid].position); |
| 2842 | 2858 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.role', data.entries[uid].role); |
| 2843 | 2859 | await saveWorldInfo(name, data); |
| 2844 | 2860 | }); |
| 2845 | 2861 | |
| @@ -2881,36 +2897,36 @@ function getWorldEntry(name, data, entry) { | ||
| 2881 | 2897 | data.entries[uid].constant = true; |
| 2882 | 2898 | data.entries[uid].disable = false; |
| 2883 | 2899 | data.entries[uid].vectorized = false; |
| 2884 | 2900 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'enabled', true); |
| 2885 | 2901 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'constant', true); |
| 2886 | 2902 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.vectorized', false); |
| 2887 | 2903 | template.removeClass('disabledWIEntry'); |
| 2888 | 2904 | break; |
| 2889 | 2905 | case 'normal': |
| 2890 | 2906 | data.entries[uid].constant = false; |
| 2891 | 2907 | data.entries[uid].disable = false; |
| 2892 | 2908 | data.entries[uid].vectorized = false; |
| 2893 | 2909 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'enabled', true); |
| 2894 | 2910 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'constant', false); |
| 2895 | 2911 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.vectorized', false); |
| 2896 | 2912 | template.removeClass('disabledWIEntry'); |
| 2897 | 2913 | break; |
| 2898 | 2914 | case 'vectorized': |
| 2899 | 2915 | data.entries[uid].constant = false; |
| 2900 | 2916 | data.entries[uid].disable = false; |
| 2901 | 2917 | data.entries[uid].vectorized = true; |
| 2902 | 2918 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'enabled', true); |
| 2903 | 2919 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'constant', false); |
| 2904 | 2920 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.vectorized', true); |
| 2905 | 2921 | template.removeClass('disabledWIEntry'); |
| 2906 | 2922 | break; |
| 2907 | 2923 | case 'disabled': |
| 2908 | 2924 | data.entries[uid].constant = false; |
| 2909 | 2925 | data.entries[uid].disable = true; |
| 2910 | 2926 | data.entries[uid].vectorized = false; |
| 2911 | 2927 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'enabled', false); |
| 2912 | 2928 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'constant', false); |
| 2913 | 2929 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.vectorized', false); |
| 2914 | 2930 | template.addClass('disabledWIEntry'); |
| 2915 | 2931 | break; |
| 2916 | 2932 | } |
| @@ -2941,7 +2957,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2941 | 2957 | const uid = $(this).data('uid'); |
| 2942 | 2958 | const value = $(this).prop('checked'); |
| 2943 | 2959 | data.entries[uid].excludeRecursion = value; |
| 2944 | 2960 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.exclude_recursion', data.entries[uid].excludeRecursion); |
| 2945 | 2961 | await saveWorldInfo(name, data); |
| 2946 | 2962 | }); |
| 2947 | 2963 | excludeRecursionInput.prop('checked', entry.excludeRecursion).trigger('input'); |
| @@ -2953,7 +2969,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2953 | 2969 | const uid = $(this).data('uid'); |
| 2954 | 2970 | const value = $(this).prop('checked'); |
| 2955 | 2971 | data.entries[uid].preventRecursion = value; |
| 2956 | 2972 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.prevent_recursion', data.entries[uid].preventRecursion); |
| 2957 | 2973 | await saveWorldInfo(name, data); |
| 2958 | 2974 | }); |
| 2959 | 2975 | preventRecursionInput.prop('checked', entry.preventRecursion).trigger('input'); |
| @@ -2965,7 +2981,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2965 | 2981 | const uid = $(this).data('uid'); |
| 2966 | 2982 | const value = $(this).prop('checked'); |
| 2967 | 2983 | data.entries[uid].delayUntilRecursion = value; |
| 2968 | 2984 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.delay_until_recursion', data.entries[uid].delayUntilRecursion); |
| 2969 | 2985 | await saveWorldInfo(name, data); |
| 2970 | 2986 | }); |
| 2971 | 2987 | delayUntilRecursionInput.prop('checked', entry.delayUntilRecursion).trigger('input'); |
| @@ -2988,7 +3004,7 @@ function getWorldEntry(name, data, entry) { | ||
| 2988 | 3004 | deleteButton.on('click', async function () { |
| 2989 | 3005 | const uid = $(this).data('uid'); |
| 2990 | 3006 | deleteWorldInfoEntry(data, uid); |
| 2991 | 3007 | deleteOriginalDataValuedeleteWIOriginalDataValue(data, uid); |
| 2992 | 3008 | await saveWorldInfo(name, data); |
| 2993 | 3009 | updateEditor(navigation_option.previous); |
| 2994 | 3010 | }); |
| @@ -3015,7 +3031,7 @@ function getWorldEntry(name, data, entry) { | ||
| 3015 | 3031 | } |
| 3016 | 3032 | |
| 3017 | 3033 | data.entries[uid].scanDepth = !isEmpty && !isNaN(value) && value >= 0 && value <= MAX_SCAN_DEPTH ? Math.floor(value) : null; |
| 3018 | 3034 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.scan_depth', data.entries[uid].scanDepth); |
| 3019 | 3035 | await saveWorldInfo(name, data); |
| 3020 | 3036 | }); |
| 3021 | 3037 | scanDepthInput.val(entry.scanDepth ?? null).trigger('input'); |
| @@ -3028,7 +3044,7 @@ function getWorldEntry(name, data, entry) { | ||
| 3028 | 3044 | const value = $(this).val(); |
| 3029 | 3045 | |
| 3030 | 3046 | data.entries[uid].caseSensitive = value === 'null' ? null : value === 'true'; |
| 3031 | 3047 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.case_sensitive', data.entries[uid].caseSensitive); |
| 3032 | 3048 | await saveWorldInfo(name, data); |
| 3033 | 3049 | }); |
| 3034 | 3050 | caseSensitiveSelect.val((entry.caseSensitive === null || entry.caseSensitive === undefined) ? 'null' : entry.caseSensitive ? 'true' : 'false').trigger('input'); |
| @@ -3041,7 +3057,7 @@ function getWorldEntry(name, data, entry) { | ||
| 3041 | 3057 | const value = $(this).val(); |
| 3042 | 3058 | |
| 3043 | 3059 | data.entries[uid].matchWholeWords = value === 'null' ? null : value === 'true'; |
| 3044 | 3060 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.match_whole_words', data.entries[uid].matchWholeWords); |
| 3045 | 3061 | await saveWorldInfo(name, data); |
| 3046 | 3062 | }); |
| 3047 | 3063 | matchWholeWordsSelect.val((entry.matchWholeWords === null || entry.matchWholeWords === undefined) ? 'null' : entry.matchWholeWords ? 'true' : 'false').trigger('input'); |
| @@ -3054,7 +3070,7 @@ function getWorldEntry(name, data, entry) { | ||
| 3054 | 3070 | const value = $(this).val(); |
| 3055 | 3071 | |
| 3056 | 3072 | data.entries[uid].useGroupScoring = value === 'null' ? null : value === 'true'; |
| 3057 | 3073 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.use_group_scoring', data.entries[uid].useGroupScoring); |
| 3058 | 3074 | await saveWorldInfo(name, data); |
| 3059 | 3075 | }); |
| 3060 | 3076 | useGroupScoringSelect.val((entry.useGroupScoring === null || entry.useGroupScoring === undefined) ? 'null' : entry.useGroupScoring ? 'true' : 'false').trigger('input'); |
| @@ -3067,7 +3083,7 @@ function getWorldEntry(name, data, entry) { | ||
| 3067 | 3083 | const value = $(this).val(); |
| 3068 | 3084 | |
| 3069 | 3085 | data.entries[uid].automationId = value; |
| 3070 | 3086 | setOriginalDataValuesetWIOriginalDataValue(data, uid, 'extensions.automation_id', data.entries[uid].automationId); |
| 3071 | 3087 | await saveWorldInfo(name, data); |
| 3072 | 3088 | }); |
| 3073 | 3089 | automationIdInput.val(entry.automationId ?? '').trigger('input'); |
| @@ -3200,12 +3216,12 @@ function createEntryInputAutocomplete(input, callback, { allowMultiple = false } | ||
| 3200 | 3216 | |
| 3201 | 3217 | |
| 3202 | 3218 | /** |
| 3203 | 3219 | * DuplicatedDuplicate a WI entry by copying all of its properties and assigning a new uid |
| 3204 | 3220 | * @param {*} data - The data of the book |
| 3205 | 3221 | * @param {number} uid - The uid of the entry to copy in this book |
| 3206 | 3222 | * @returns {*} The new WI duplicated entry |
| 3207 | 3223 | */ |
| 3208 | 3224 | export function duplicateWorldInfoEntry(data, uid) { |
| 3209 | 3225 | if (!data || !('entries' in data) || !data.entries[uid]) { |
| 3210 | 3226 | return; |
| 3211 | 3227 | } |
| @@ -3226,7 +3242,7 @@ function duplicateWorldInfoEntry(data, uid) { | ||
| 3226 | 3242 | * @param {*[]} data - The data of the book |
| 3227 | 3243 | * @param {number} uid - The uid of the entry to copy in this book |
| 3228 | 3244 | */ |
| 3229 | 3245 | export function deleteWorldInfoEntry(data, uid) { |
| 3230 | 3246 | if (!data || !('entries' in data)) { |
| 3231 | 3247 | return; |
| 3232 | 3248 | } |
| @@ -3245,7 +3261,7 @@ function deleteWorldInfoEntry(data, uid) { | ||
| 3245 | 3261 | * |
| 3246 | 3262 | * @type {{[key: string]: { default: any, type: string }}} |
| 3247 | 3263 | */ |
| 3248 | 3264 | export const newEntryDefinitionnewWorldInfoEntryDefinition = { |
| 3249 | 3265 | key: { default: [], type: 'array' }, |
| 3250 | 3266 | keysecondary: { default: [], type: 'array' }, |
| 3251 | 3267 | comment: { default: '', type: 'string' }, |
| @@ -3278,8 +3294,8 @@ const newEntryDefinition = { | ||
| 3278 | 3294 | delay: { default: null, type: 'number?' }, |
| 3279 | 3295 | }; |
| 3280 | 3296 | |
| 3281 | 3297 | export const newEntryTemplatenewWorldInfoEntryTemplate = Object.fromEntries( |
| 3282 | 3298 | Object.entries(newEntryDefinitionnewWorldInfoEntryDefinition).map(([key, value]) => [key, value.default]), |
| 3283 | 3299 | ); |
| 3284 | 3300 | |
| 3285 | 3301 | /** |
| @@ -3288,7 +3304,7 @@ const newEntryTemplate = Object.fromEntries( | ||
| 3288 | 3304 | * @param {any} data WI data |
| 3289 | 3305 | * @returns {object | undefined} New entry object or undefined if failed |
| 3290 | 3306 | */ |
| 3291 | 3307 | export function createWorldInfoEntry(_name, data) { |
| 3292 | 3308 | const newUid = getFreeWorldEntryUid(data); |
| 3293 | 3309 | |
| 3294 | 3310 | if (!Number.isInteger(newUid)) { |
| @@ -3296,7 +3312,7 @@ function createWorldInfoEntry(_name, data) { | ||
| 3296 | 3312 | return; |
| 3297 | 3313 | } |
| 3298 | 3314 | |
| 3299 | 3315 | const newEntry = { uid: newUid, ...structuredClone(newEntryTemplatenewWorldInfoEntryTemplate) }; |
| 3300 | 3316 | data.entries[newUid] = newEntry; |
| 3301 | 3317 | |
| 3302 | 3318 | return newEntry; |
| @@ -3314,7 +3330,21 @@ async function _save(name, data) { | ||
| 3314 | 3330 | eventSource.emit(event_types.WORLDINFO_UPDATED, name, data); |
| 3315 | 3331 | } |
| 3316 | 3332 | |
| 3317 | -async function saveWorldInfo(name, data, immediately = false) { | |
| 3333 | + | |
| 3334 | +/** | |
| 3335 | + * Saves the world info | |
| 3336 | + * | |
| 3337 | + * This will also refresh the `worldInfoCache`. | |
| 3338 | + * Note, for performance reasons the saved cache will not make a deep clone of the data. | |
| 3339 | + * It is your responsibility to not modify the saved data object after calling this function, or there will be data inconsistencies. | |
| 3340 | + * Call `loadWorldInfoData` or query directly from cache if you need the object again. | |
| 3341 | + * | |
| 3342 | + * @param {string} name - The name of the world info | |
| 3343 | + * @param {any} data - The data to be saved | |
| 3344 | + * @param {boolean} [immediately=false] - Whether to save immediately or use debouncing | |
| 3345 | + * @return {Promise<void>} A promise that resolves when the world info is saved | |
| 3346 | + */ | |
| 3347 | +export async function saveWorldInfo(name, data, immediately = false) { | |
| 3318 | 3348 | if (!name || !data) { |
| 3319 | 3349 | return; |
| 3320 | 3350 | } |
| @@ -3371,7 +3401,7 @@ async function renameWorldInfo(name, data) { | ||
| 3371 | 3401 | * @param {string} worldInfoName - The name of the world info to delete |
| 3372 | 3402 | * @returns {Promise<boolean>} A promise that resolves to true if the world info was successfully deleted, false otherwise |
| 3373 | 3403 | */ |
| 3374 | 3404 | export async function deleteWorldInfo(worldInfoName) { |
| 3375 | 3405 | if (!world_names.includes(worldInfoName)) { |
| 3376 | 3406 | return false; |
| 3377 | 3407 | } |
| @@ -3406,7 +3436,7 @@ async function deleteWorldInfo(worldInfoName) { | ||
| 3406 | 3436 | return true; |
| 3407 | 3437 | } |
| 3408 | 3438 | |
| 3409 | 3439 | export function getFreeWorldEntryUid(data) { |
| 3410 | 3440 | if (!data || !('entries' in data)) { |
| 3411 | 3441 | return null; |
| 3412 | 3442 | } |
| @@ -3422,7 +3452,7 @@ function getFreeWorldEntryUid(data) { | ||
| 3422 | 3452 | return null; |
| 3423 | 3453 | } |
| 3424 | 3454 | |
| 3425 | 3455 | export function getFreeWorldName() { |
| 3426 | 3456 | const MAX_FREE_NAME = 100_000; |
| 3427 | 3457 | for (let index = 1; index < MAX_FREE_NAME; index++) { |
| 3428 | 3458 | const newName = `New World (${index})`; |
| @@ -3444,7 +3474,7 @@ function getFreeWorldName() { | ||
| 3444 | 3474 | * @param {boolean} [options.interactive=false] - Whether to show a confirmation dialog when overwriting an existing world |
| 3445 | 3475 | * @returns {Promise<boolean>} - True if the world info was successfully created, false otherwise |
| 3446 | 3476 | */ |
| 3447 | 3477 | export async function createNewWorldInfo(worldName, { interactive = false } = {}) { |
| 3448 | 3478 | const worldInfoTemplate = { entries: {} }; |
| 3449 | 3479 | |
| 3450 | 3480 | if (!worldName) { |
| @@ -3505,7 +3535,7 @@ async function getCharacterLore() { | ||
| 3505 | 3535 | continue; |
| 3506 | 3536 | } |
| 3507 | 3537 | |
| 3508 | 3538 | const data = await loadWorldInfoDataloadWorldInfo(worldName); |
| 3509 | 3539 | const newEntries = data ? Object.keys(data.entries).map((x) => data.entries[x]).map(({ uid, ...rest }) => ({ uid, world: worldName, ...rest })) : []; |
| 3510 | 3540 | entries = entries.concat(newEntries); |
| 3511 | 3541 | |
| @@ -3525,7 +3555,7 @@ async function getGlobalLore() { | ||
| 3525 | 3555 | |
| 3526 | 3556 | let entries = []; |
| 3527 | 3557 | for (const worldName of selected_world_info) { |
| 3528 | 3558 | const data = await loadWorldInfoDataloadWorldInfo(worldName); |
| 3529 | 3559 | const newEntries = data ? Object.keys(data.entries).map((x) => data.entries[x]).map(({ uid, ...rest }) => ({ uid, world: worldName, ...rest })) : []; |
| 3530 | 3560 | entries = entries.concat(newEntries); |
| 3531 | 3561 | } |
| @@ -3547,7 +3577,7 @@ async function getChatLore() { | ||
| 3547 | 3577 | return []; |
| 3548 | 3578 | } |
| 3549 | 3579 | |
| 3550 | 3580 | const data = await loadWorldInfoDataloadWorldInfo(chatWorld); |
| 3551 | 3581 | const entries = data ? Object.keys(data.entries).map((x) => data.entries[x]).map(({ uid, ...rest }) => ({ uid, world: chatWorld, ...rest })) : []; |
| 3552 | 3582 | |
| 3553 | 3583 | console.debug(`[WI] Chat lore has ${entries.length} entries`, [chatWorld]); |
| @@ -3663,7 +3693,7 @@ function parseDecorators(content) { | ||
| 3663 | 3693 | * @typedef {{ worldInfoBefore: string, worldInfoAfter: string, EMEntries: any[], WIDepthEntries: any[], allActivatedEntries: Set<any> }} WIActivated |
| 3664 | 3694 | * @returns {Promise<WIActivated>} The world info activated. |
| 3665 | 3695 | */ |
| 3666 | 3696 | export async function checkWorldInfo(chat, maxContext, isDryRun) { |
| 3667 | 3697 | const context = getContext(); |
| 3668 | 3698 | const buffer = new WorldInfoBuffer(chat); |
| 3669 | 3699 | |
| @@ -4233,7 +4263,7 @@ function convertAgnaiMemoryBook(inputObj) { | ||
| 4233 | 4263 | |
| 4234 | 4264 | inputObj.entries.forEach((entry, index) => { |
| 4235 | 4265 | outputObj.entries[index] = { |
| 4236 | 4266 | ...newEntryTemplatenewWorldInfoEntryTemplate, |
| 4237 | 4267 | uid: index, |
| 4238 | 4268 | key: entry.keywords, |
| 4239 | 4269 | keysecondary: [], |
| @@ -4275,7 +4305,7 @@ function convertRisuLorebook(inputObj) { | ||
| 4275 | 4305 | |
| 4276 | 4306 | inputObj.data.forEach((entry, index) => { |
| 4277 | 4307 | outputObj.entries[index] = { |
| 4278 | 4308 | ...newEntryTemplatenewWorldInfoEntryTemplate, |
| 4279 | 4309 | uid: index, |
| 4280 | 4310 | key: entry.key.split(',').map(x => x.trim()), |
| 4281 | 4311 | keysecondary: entry.secondkey ? entry.secondkey.split(',').map(x => x.trim()) : [], |
| @@ -4322,7 +4352,7 @@ function convertNovelLorebook(inputObj) { | ||
| 4322 | 4352 | const addMemo = displayName !== undefined && displayName.trim() !== ''; |
| 4323 | 4353 | |
| 4324 | 4354 | outputObj.entries[index] = { |
| 4325 | 4355 | ...newEntryTemplatenewWorldInfoEntryTemplate, |
| 4326 | 4356 | uid: index, |
| 4327 | 4357 | key: entry.keys, |
| 4328 | 4358 | keysecondary: [], |
| @@ -4369,7 +4399,7 @@ function convertCharacterBook(characterBook) { | ||
| 4369 | 4399 | } |
| 4370 | 4400 | |
| 4371 | 4401 | result.entries[entry.id] = { |
| 4372 | 4402 | ...newEntryTemplatenewWorldInfoEntryTemplate, |
| 4373 | 4403 | uid: entry.id, |
| 4374 | 4404 | key: entry.keys, |
| 4375 | 4405 | keysecondary: entry.secondary_keys || [], |
| @@ -4499,7 +4529,7 @@ export async function importEmbeddedWorldInfo(skipPopup = false) { | ||
| 4499 | 4529 | setWorldInfoButtonClass(chid, true); |
| 4500 | 4530 | } |
| 4501 | 4531 | |
| 4502 | 4532 | export function onWorldInfoChange(args, text) { |
| 4503 | 4533 | if (args !== '__notSlashCommand__') { // if it's a slash command |
| 4504 | 4534 | const silent = isTrueBoolean(args.silent); |
| 4505 | 4535 | if (text.trim() !== '') { // and args are provided |
| @@ -4650,7 +4680,7 @@ export async function importWorldInfo(file) { | ||
| 4650 | 4680 | }); |
| 4651 | 4681 | } |
| 4652 | 4682 | |
| 4653 | 4683 | export function assignLorebookToChat() { |
| 4654 | 4684 | const selectedName = chat_metadata[METADATA_KEY]; |
| 4655 | 4685 | const template = $('#chat_world_template .chat_world').clone(); |
| 4656 | 4686 | |