diff --git a/public/scripts/slash-commands.js b/public/scripts/slash-commands.js index 8b9f084c4..24a2382a7 100644 --- a/public/scripts/slash-commands.js +++ b/public/scripts/slash-commands.js @@ -166,7 +166,7 @@ parser.addCommand('memberdown', moveGroupMemberDownCallback, ['downmember'], '(message index or range) – shows a group member character card without switching chats', true, true); parser.addCommand('delswipe', deleteSwipeCallback, ['swipedel'], '(optional 1-based id) – deletes a swipe from the last chat message. If swipe id not provided - deletes the current swipe.', true, true); parser.addCommand('echo', echoCallback, [], '(title=string severity=info/warning/error/success [text]) – echoes the text to toast message. Useful for pipes debugging.', true, true); -// '(text) – echoes the text to toast message. Useful for pipes debugging.', true, true); +//parser.addCommand('#', (_, value) => '', [], ' – a comment, does nothing, e.g. /# the next three commands switch variables a and b', true, true); parser.addCommand('gen', generateCallback, [], '(lock=on/off [prompt]) – generates text using the provided prompt and passes it to the next command through the pipe, optionally locking user input while generating.', true, true); parser.addCommand('genraw', generateRawCallback, [], '(lock=on/off [prompt]) – generates text using the provided prompt and passes it to the next command through the pipe, optionally locking user input while generating. Does not include chat history or character card. Use instruct=off to skip instruct formatting, e.g. /genraw instruct=off Why is the sky blue?. Use stop=... with a JSON-serialized array to add one-time custom stop strings, e.g. /genraw stop=["\\n"] Say hi', true, true); parser.addCommand('addswipe', addSwipeCallback, ['swipeadd'], '(text) – adds a swipe to the last chat message.', true, true); diff --git a/public/scripts/variables.js b/public/scripts/variables.js index 99175d9c4..14020101b 100644 --- a/public/scripts/variables.js +++ b/public/scripts/variables.js @@ -28,12 +28,33 @@ function getLocalVariable(name, args = {}) { return (localVariable === '' || isNaN(Number(localVariable))) ? (localVariable || '') : Number(localVariable); } -function setLocalVariable(name, value) { +function setLocalVariable(name, value, args = {}) { if (!chat_metadata.variables) { chat_metadata.variables = {}; } - chat_metadata.variables[name] = value; + if (args.index !== undefined) { + try { + let localVariable = JSON.parse(chat_metadata.variables[name] ?? 'null'); + const numIndex = Number(args.index); + if (Number.isNaN(numIndex)) { + if (localVariable === null) { + localVariable = {}; + } + localVariable[args.index] = value; + } else { + if (localVariable === null) { + localVariable = []; + } + localVariable[numIndex] = value; + } + chat_metadata.variables[name] = JSON.stringify(localVariable); + } catch { + // that didn't work + } + } else { + chat_metadata.variables[name] = value; + } saveMetadataDebounced(); return value; } @@ -60,13 +81,44 @@ function getGlobalVariable(name, args = {}) { return (globalVariable === '' || isNaN(Number(globalVariable))) ? (globalVariable || '') : Number(globalVariable); } -function setGlobalVariable(name, value) { - extension_settings.variables.global[name] = value; +function setGlobalVariable(name, value, args = {}) { + if (args.index !== undefined) { + try { + let globalVariable = JSON.parse(extension_settings.variables.global[name] ?? 'null'); + const numIndex = Number(args.index); + if (Number.isNaN(numIndex)) { + if (globalVariable === null) { + globalVariable = {}; + } + globalVariable[args.index] = value; + } else { + if (globalVariable === null) { + globalVariable = []; + } + globalVariable[numIndex] = value; + } + extension_settings.variables.global[name] = JSON.stringify(globalVariable); + } catch { + // that didn't work + } + } else { + extension_settings.variables.global[name] = value; + } saveSettingsDebounced(); } function addLocalVariable(name, value) { const currentValue = getLocalVariable(name) || 0; + try { + const parsedValue = JSON.parse(currentValue); + if (Array.isArray(parsedValue)) { + parsedValue.push(value); + setGlobalVariable(name, JSON.stringify(parsedValue)); + return parsedValue; + } + } catch { + // ignore non-array values + } const increment = Number(value); if (isNaN(increment) || isNaN(Number(currentValue))) { @@ -87,6 +139,16 @@ function addLocalVariable(name, value) { function addGlobalVariable(name, value) { const currentValue = getGlobalVariable(name) || 0; + try { + const parsedValue = JSON.parse(currentValue); + if (Array.isArray(parsedValue)) { + parsedValue.push(value); + setGlobalVariable(name, JSON.stringify(parsedValue)); + return parsedValue; + } + } catch { + // ignore non-array values + } const increment = Number(value); if (isNaN(increment) || isNaN(Number(currentValue))) { @@ -577,10 +639,10 @@ function lenValuesCallback(value) { export function registerVariableCommands() { registerSlashCommand('listvar', listVariablesCallback, [], ' – list registered chat variables', true, true); - registerSlashCommand('setvar', (args, value) => setLocalVariable(args.key || args.name, value), [], 'key=varname (value) – set a local variable value and pass it down the pipe, e.g. /setvar key=color green', true, true); + registerSlashCommand('setvar', (args, value) => setLocalVariable(args.key || args.name, value, args), [], 'key=varname index=listIndex (value) – set a local variable value and pass it down the pipe, index is optional, e.g. /setvar key=color green', true, true); registerSlashCommand('getvar', (args, value) => getLocalVariable(value, args), [], 'index=listIndex (key) – get a local variable value and pass it down the pipe, index is optional, e.g. /getvar height or /getvar index=3 costumes', true, true); registerSlashCommand('addvar', (args, value) => addLocalVariable(args.key || args.name, value), [], 'key=varname (increment) – add a value to a local variable and pass the result down the pipe, e.g. /addvar score 10', true, true); - registerSlashCommand('setglobalvar', (args, value) => setGlobalVariable(args.key || args.name, value), [], 'key=varname (value) – set a global variable value and pass it down the pipe, e.g. /setglobalvar key=color green', true, true); + registerSlashCommand('setglobalvar', (args, value) => setGlobalVariable(args.key || args.name, value, args), [], 'key=varname index=listIndex (value) – set a global variable value and pass it down the pipe, index is optional, e.g. /setglobalvar key=color green', true, true); registerSlashCommand('getglobalvar', (args, value) => getGlobalVariable(value, args), [], 'index=listIndex (key) – get a global variable value and pass it down the pipe, index is optional, e.g. /getglobalvar height or /getglobalvar index=3 costumes', true, true); registerSlashCommand('addglobalvar', (args, value) => addGlobalVariable(args.key || args.name, value), [], 'key=varname (increment) – add a value to a global variable and pass the result down the pipe, e.g. /addglobalvar score 10', true, true); registerSlashCommand('incvar', (_, value) => incrementLocalVariable(value), [], '(key) – increment a local variable by 1 and pass the result down the pipe, e.g. /incvar score', true, true);