chore(wi): Add logSlashCommandWarn utility and integrate into world-info slash commands (#5096)

34688f849345968615e0ea43d298103f65b7feb1

Wolfsblvt <wolfsblvt@gmail.com>

Signed
2 files changed, +52 -6Ignore whitespace
public/scripts/utils.js+27 -0
@@ -2752,6 +2752,33 @@ export function versionCompare(srcVersion, minVersion) {
2752}2752}
27532753
2754/**2754/**
2755 * Logs a warning to the console for slash command executions.
2756 * Strips internal arguments (starting with '_') from the args object for cleaner logging.
2757 * @param {string} message - The warning message to log.
2758 * @param {Object} args - The arguments object from the slash command, including named arguments and internal values.
2759 * @param {{[unnamedArgName: string]: string}} [valueObj=null] - The user-built object containing context for the warning (e.g., { uid: uid }).
2760 * @returns {void}
2761 */
2762export function logSlashCommandWarn(message, args, valueObj = null) {
2763 if (valueObj !== null && valueObj !== undefined) {
2764 console.warn(message, valueObj, stripInternalArgs(args));
2765 } else {
2766 console.warn(message, stripInternalArgs(args));
2767 }
2768 return;
2769 function stripInternalArgs(args) {
2770 // strip all args/properties that start with an underscore
2771 const result = {};
2772 for (const [key, value] of Object.entries(args)) {
2773 if (!key.startsWith('_')) {
2774 result[key] = value;
2775 }
2776 }
2777 return result;
2778 }
2779}
2780
2781/**
2755 * Sets up the scroll-to-top button functionality.2782 * Sets up the scroll-to-top button functionality.
2756 * @param {object} params Parameters object2783 * @param {object} params Parameters object
2757 * @param {string} params.scrollContainerId Scrollable container element ID2784 * @param {string} params.scrollContainerId Scrollable container element ID
public/scripts/world-info.js+25 -6
@@ -1,7 +1,7 @@
1import { Fuse } from '../lib.js';1import { Fuse } from '../lib.js';
22
3import { saveSettings, substituteParams, getRequestHeaders, chat_metadata, this_chid, characters, saveCharacterDebounced, menu_type, eventSource, event_types, getExtensionPromptByName, saveMetadata, getCurrentChatId, extension_prompt_roles, create_save, createOrEditCharacter, name1 } from '../script.js';3import { saveSettings, substituteParams, getRequestHeaders, chat_metadata, this_chid, characters, saveCharacterDebounced, menu_type, eventSource, event_types, getExtensionPromptByName, saveMetadata, getCurrentChatId, extension_prompt_roles, create_save, createOrEditCharacter, name1 } from '../script.js';
4import { download, debounce, initScrollHeight, resetScrollHeight, parseJsonFile, extractDataFromPng, getFileBuffer, getCharaFilename, getSortableDelay, escapeRegex, PAGINATION_TEMPLATE, navigation_option, waitUntilCondition, isTrueBoolean, setValueByPath, flashHighlight, select2ModifyOptions, getSelect2OptionId, dynamicSelect2DataViaAjax, highlightRegex, select2ChoiceClickSubscribe, isFalseBoolean, getSanitizedFilename, checkOverwriteExistingData, getStringHash, parseStringArray, cancelDebounce, findChar, onlyUnique, equalsIgnoreCaseAndAccents, uuidv4, normalizeArray, getUniqueName } from './utils.js';4import { download, debounce, initScrollHeight, resetScrollHeight, parseJsonFile, extractDataFromPng, getFileBuffer, getCharaFilename, getSortableDelay, escapeRegex, PAGINATION_TEMPLATE, navigation_option, waitUntilCondition, isTrueBoolean, setValueByPath, flashHighlight, select2ModifyOptions, getSelect2OptionId, dynamicSelect2DataViaAjax, highlightRegex, select2ChoiceClickSubscribe, isFalseBoolean, getSanitizedFilename, checkOverwriteExistingData, getStringHash, parseStringArray, cancelDebounce, findChar, onlyUnique, equalsIgnoreCaseAndAccents, uuidv4, normalizeArray, getUniqueName, logSlashCommandWarn } from './utils.js';
5import { extension_settings, getContext } from './extensions.js';5import { extension_settings, getContext } from './extensions.js';
6import { NOTE_MODULE_NAME, metadata_keys, shouldWIAddPrompt } from './authors-note.js';6import { NOTE_MODULE_NAME, metadata_keys, shouldWIAddPrompt } from './authors-note.js';
7import { isMobile } from './RossAscends-mods.js';7import { isMobile } from './RossAscends-mods.js';
@@ -1059,9 +1059,10 @@ function registerWorldInfoSlashCommands() {
1059 return getContext().chat.filter(x => !x.is_system).map(x => x.mes);1059 return getContext().chat.filter(x => !x.is_system).map(x => x.mes);
1060 }1060 }
10611061
1062 async function getEntriesFromFile(file) {1062 async function getEntriesFromFile(file, { args = {}, unnamed = null, callbackName = 'getEntriesFromFile' } = {}) {
1063 if (!file || !world_names.includes(file)) {1063 if (!file || !world_names.includes(file)) {
1064 toastr.warning(t`Valid World Info file name is required`);1064 toastr.warning(t`Valid World Info file name is required`);
1065 logSlashCommandWarn(`${callbackName}: Valid World Info file name is required`, args, unnamed);
1065 return '';1066 return '';
1066 }1067 }
10671068
@@ -1069,6 +1070,7 @@ function registerWorldInfoSlashCommands() {
10691070
1070 if (!data || !('entries' in data)) {1071 if (!data || !('entries' in data)) {
1071 toastr.warning(t`World Info file has an invalid format`);1072 toastr.warning(t`World Info file has an invalid format`);
1073 logSlashCommandWarn(`${callbackName}: World Info file has an invalid format`, args, unnamed);
1072 return '';1074 return '';
1073 }1075 }
10741076
@@ -1076,6 +1078,7 @@ function registerWorldInfoSlashCommands() {
10761078
1077 if (!entries || entries.length === 0) {1079 if (!entries || entries.length === 0) {
1078 toastr.warning(t`World Info file has no entries`);1080 toastr.warning(t`World Info file has no entries`);
1081 logSlashCommandWarn(`${callbackName}: World Info file has no entries`, args, unnamed);
1079 return '';1082 return '';
1080 }1083 }
10811084
@@ -1119,6 +1122,7 @@ function registerWorldInfoSlashCommands() {
1119 const character = findChar({ name: characterIdentifier });1122 const character = findChar({ name: characterIdentifier });
1120 if (!character) {1123 if (!character) {
1121 toastr.error(t`Character not found.`);1124 toastr.error(t`Character not found.`);
1125 logSlashCommandWarn('getCharBookCallback: Character not found', { type, name, create }, { characterIdentifier });
1122 return '';1126 return '';
1123 }1127 }
1124 const books = [];1128 const books = [];
@@ -1160,6 +1164,7 @@ function registerWorldInfoSlashCommands() {
11601164
1161 if (!chatId) {1165 if (!chatId) {
1162 toastr.warning(t`Open a chat to get a name of the chat-bound lorebook`);1166 toastr.warning(t`Open a chat to get a name of the chat-bound lorebook`);
1167 logSlashCommandWarn('getChatBookCallback: Open a chat to get a name of the chat-bound lorebook', args);
1163 return '';1168 return '';
1164 }1169 }
11651170
@@ -1205,7 +1210,7 @@ function registerWorldInfoSlashCommands() {
1205 const file = args.file;1210 const file = args.file;
1206 const field = args.field || 'key';1211 const field = args.field || 'key';
12071212
1208 const entries = await getEntriesFromFile(file);1213 const entries = await getEntriesFromFile(file, { args, unnamed: { value }, callbackName: 'findBookEntryCallback' });
12091214
1210 if (!entries) {1215 if (!entries) {
1211 return '';1216 return '';
@@ -1250,7 +1255,7 @@ function registerWorldInfoSlashCommands() {
1250 const field = args.field || 'content';1255 const field = args.field || 'content';
1251 const tags = getContext().tags;1256 const tags = getContext().tags;
12521257
1253 const entries = await getEntriesFromFile(file);1258 const entries = await getEntriesFromFile(file, { args, unnamed: { uid }, callbackName: 'getEntryFieldCallback' });
12541259
1255 if (!entries) {1260 if (!entries) {
1256 return '';1261 return '';
@@ -1260,11 +1265,14 @@ function registerWorldInfoSlashCommands() {
12601265
1261 if (!entry) {1266 if (!entry) {
1262 toastr.warning('Valid UID is required');1267 toastr.warning('Valid UID is required');
1268 logSlashCommandWarn('getEntryFieldCallback: Valid UID is required', args, { uid });
1269 console.warn();
1263 return '';1270 return '';
1264 }1271 }
12651272
1266 if (!Object.hasOwn(newWorldInfoEntryDefinition, field)) {1273 if (!Object.hasOwn(newWorldInfoEntryDefinition, field)) {
1267 toastr.warning('Valid field name is required');1274 toastr.warning('Valid field name is required');
1275 logSlashCommandWarn('getEntryFieldCallback: Valid field name is required', args, { uid });
1268 return '';1276 return '';
1269 }1277 }
12701278
@@ -1313,6 +1321,7 @@ function registerWorldInfoSlashCommands() {
13131321
1314 if (!data || !('entries' in data)) {1322 if (!data || !('entries' in data)) {
1315 toastr.warning('Valid World Info file name is required');1323 toastr.warning('Valid World Info file name is required');
1324 logSlashCommandWarn('createEntryCallback: Valid World Info file name is required', args);
1316 return '';1325 return '';
1317 }1326 }
13181327
@@ -1358,6 +1367,7 @@ function registerWorldInfoSlashCommands() {
13581367
1359 if (value === undefined) {1368 if (value === undefined) {
1360 toastr.warning('Value is required');1369 toastr.warning('Value is required');
1370 logSlashCommandWarn('setEntryFieldCallback: Value is required', args, { value });
1361 return '';1371 return '';
1362 }1372 }
13631373
@@ -1367,6 +1377,7 @@ function registerWorldInfoSlashCommands() {
13671377
1368 if (!data || !('entries' in data)) {1378 if (!data || !('entries' in data)) {
1369 toastr.warning('Valid World Info file name is required');1379 toastr.warning('Valid World Info file name is required');
1380 logSlashCommandWarn('setEntryFieldCallback: Valid World Info file name is required', args, { value });
1370 return '';1381 return '';
1371 }1382 }
13721383
@@ -1374,11 +1385,13 @@ function registerWorldInfoSlashCommands() {
13741385
1375 if (!entry) {1386 if (!entry) {
1376 toastr.warning('Valid UID is required');1387 toastr.warning('Valid UID is required');
1388 logSlashCommandWarn('setEntryFieldCallback: Valid UID is required', args, { value });
1377 return '';1389 return '';
1378 }1390 }
13791391
1380 if (!Object.hasOwn(newWorldInfoEntryDefinition, field)) {1392 if (!Object.hasOwn(newWorldInfoEntryDefinition, field)) {
1381 toastr.warning('Valid field name is required');1393 toastr.warning('Valid field name is required');
1394 logSlashCommandWarn('setEntryFieldCallback: Valid field name is required', args, { value });
1382 return '';1395 return '';
1383 }1396 }
13841397
@@ -1445,7 +1458,7 @@ function registerWorldInfoSlashCommands() {
1445 const uid = value;1458 const uid = value;
1446 const effect = args.effect;1459 const effect = args.effect;
14471460
1448 const entries = await getEntriesFromFile(file);1461 const entries = await getEntriesFromFile(file, { args, unnamed: { uid }, callbackName: 'getTimedEffectCallback' });
14491462
1450 if (!entries) {1463 if (!entries) {
1451 return '';1464 return '';
@@ -1456,6 +1469,7 @@ function registerWorldInfoSlashCommands() {
14561469
1457 if (!entry) {1470 if (!entry) {
1458 toastr.warning('Valid UID is required');1471 toastr.warning('Valid UID is required');
1472 logSlashCommandWarn('getTimedEffectCallback: Valid UID is required', args, { uid });
1459 return '';1473 return '';
1460 }1474 }
14611475
@@ -1465,6 +1479,7 @@ function registerWorldInfoSlashCommands() {
14651479
1466 if (!timedEffects.isValidEffectType(effect)) {1480 if (!timedEffects.isValidEffectType(effect)) {
1467 toastr.warning('Valid effect type is required');1481 toastr.warning('Valid effect type is required');
1482 logSlashCommandWarn('getTimedEffectCallback: Valid effect type is required', args, { uid });
1468 return '';1483 return '';
1469 }1484 }
14701485
@@ -1488,10 +1503,11 @@ function registerWorldInfoSlashCommands() {
14881503
1489 if (value === undefined) {1504 if (value === undefined) {
1490 toastr.warning('New state is required');1505 toastr.warning('New state is required');
1506 logSlashCommandWarn('setTimedEffectCallback: New state is required', args, { value });
1491 return '';1507 return '';
1492 }1508 }
14931509
1494 const entries = await getEntriesFromFile(file);1510 const entries = await getEntriesFromFile(file, { args, unnamed: { value }, callbackName: 'setTimedEffectCallback' });
14951511
1496 if (!entries) {1512 if (!entries) {
1497 return '';1513 return '';
@@ -1502,6 +1518,7 @@ function registerWorldInfoSlashCommands() {
15021518
1503 if (!entry) {1519 if (!entry) {
1504 toastr.warning('Valid UID is required');1520 toastr.warning('Valid UID is required');
1521 logSlashCommandWarn('setTimedEffectCallback: Valid UID is required', args, { value });
1505 return '';1522 return '';
1506 }1523 }
15071524
@@ -1511,11 +1528,13 @@ function registerWorldInfoSlashCommands() {
15111528
1512 if (!timedEffects.isValidEffectType(effect)) {1529 if (!timedEffects.isValidEffectType(effect)) {
1513 toastr.warning('Valid effect type is required');1530 toastr.warning('Valid effect type is required');
1531 logSlashCommandWarn('setTimedEffectCallback: Valid effect type is required', args, { value });
1514 return '';1532 return '';
1515 }1533 }
15161534
1517 if (!entry[effect]) {1535 if (!entry[effect]) {
1518 toastr.warning('This entry does not have the selected effect. Configure it in the editor first.');1536 toastr.warning('This entry does not have the selected effect. Configure it in the editor first.');
1537 logSlashCommandWarn('setTimedEffectCallback: This entry does not have the selected effect', args, { value });
1519 return '';1538 return '';
1520 }1539 }
15211540