mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Add {{lastMessageId}} macro, make async slash command handlers wait for completion
This commit is contained in:
@ -1661,6 +1661,20 @@ function scrollChatToBottom() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ID of the last message in the chat.
|
||||||
|
* @returns {string} The ID of the last message in the chat.
|
||||||
|
*/
|
||||||
|
function getLastMessageId() {
|
||||||
|
const index = chat?.length - 1;
|
||||||
|
|
||||||
|
if (!isNaN(index) && index >= 0) {
|
||||||
|
return String(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Substitutes {{macro}} parameters in a string.
|
* Substitutes {{macro}} parameters in a string.
|
||||||
* @param {string} content - The string to substitute parameters in.
|
* @param {string} content - The string to substitute parameters in.
|
||||||
@ -1690,6 +1704,7 @@ function substituteParams(content, _name1, _name2, _original, _group) {
|
|||||||
content = content.replace(/{{char}}/gi, _name2);
|
content = content.replace(/{{char}}/gi, _name2);
|
||||||
content = content.replace(/{{charIfNotGroup}}/gi, _group);
|
content = content.replace(/{{charIfNotGroup}}/gi, _group);
|
||||||
content = content.replace(/{{group}}/gi, _group);
|
content = content.replace(/{{group}}/gi, _group);
|
||||||
|
content = content.replace(/{{lastMessageId}}/gi, getLastMessageId());
|
||||||
|
|
||||||
content = content.replace(/<USER>/gi, _name1);
|
content = content.replace(/<USER>/gi, _name1);
|
||||||
content = content.replace(/<BOT>/gi, _name2);
|
content = content.replace(/<BOT>/gi, _name2);
|
||||||
@ -1885,12 +1900,12 @@ export async function generateQuietPrompt(quiet_prompt, quietToLoud, skipWIAN) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function processCommands(message, type) {
|
async function processCommands(message, type) {
|
||||||
if (type == "regenerate" || type == "swipe" || type == 'quiet') {
|
if (type == "regenerate" || type == "swipe" || type == 'quiet') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = executeSlashCommands(message);
|
const result = await executeSlashCommands(message);
|
||||||
$("#send_textarea").val(result.newText).trigger('input');
|
$("#send_textarea").val(result.newText).trigger('input');
|
||||||
|
|
||||||
// interrupt generation if the input was nothing but a command
|
// interrupt generation if the input was nothing but a command
|
||||||
@ -2405,7 +2420,7 @@ async function Generate(type, { automatic_trigger, force_name2, resolve, reject,
|
|||||||
|
|
||||||
message_already_generated = isImpersonate ? `${name1}: ` : `${name2}: `;
|
message_already_generated = isImpersonate ? `${name1}: ` : `${name2}: `;
|
||||||
|
|
||||||
const interruptedByCommand = processCommands($("#send_textarea").val(), type);
|
const interruptedByCommand = await processCommands($("#send_textarea").val(), type);
|
||||||
|
|
||||||
if (interruptedByCommand) {
|
if (interruptedByCommand) {
|
||||||
$("#send_textarea").val('').trigger('input');
|
$("#send_textarea").val('').trigger('input');
|
||||||
@ -4457,7 +4472,13 @@ function saveChatDebounced() {
|
|||||||
|
|
||||||
async function saveChat(chat_name, withMetadata, mesId) {
|
async function saveChat(chat_name, withMetadata, mesId) {
|
||||||
const metadata = { ...chat_metadata, ...(withMetadata || {}) };
|
const metadata = { ...chat_metadata, ...(withMetadata || {}) };
|
||||||
let file_name = chat_name ?? characters[this_chid].chat;
|
let file_name = chat_name ?? characters[this_chid]?.chat;
|
||||||
|
|
||||||
|
if (!file_name) {
|
||||||
|
console.warn('saveChat called without chat_name and no chat file found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
characters[this_chid]['date_last_chat'] = Date.now();
|
characters[this_chid]['date_last_chat'] = Date.now();
|
||||||
chat.forEach(function (item, i) {
|
chat.forEach(function (item, i) {
|
||||||
if (item["is_group"]) {
|
if (item["is_group"]) {
|
||||||
|
@ -681,7 +681,7 @@ function setBackgroundCallback(_, bg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function executeSlashCommands(text) {
|
async function executeSlashCommands(text) {
|
||||||
if (!text) {
|
if (!text) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -706,8 +706,12 @@ function executeSlashCommands(text) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.value && typeof result.value === 'string') {
|
||||||
|
result.value = substituteParams(result.value.trim());
|
||||||
|
}
|
||||||
|
|
||||||
console.debug('Slash command executing:', result);
|
console.debug('Slash command executing:', result);
|
||||||
result.command.callback(result.args, result.value);
|
await result.command.callback(result.args, result.value);
|
||||||
|
|
||||||
if (result.command.interruptsGeneration) {
|
if (result.command.interruptsGeneration) {
|
||||||
interrupt = true;
|
interrupt = true;
|
||||||
|
@ -4,6 +4,7 @@ System-wide Replacement Macros:
|
|||||||
<li><tt>{{char}}</tt> - the Character's name</li>
|
<li><tt>{{char}}</tt> - the Character's name</li>
|
||||||
<li><tt>{{input}}</tt> - the user input</li>
|
<li><tt>{{input}}</tt> - the user input</li>
|
||||||
<li><tt>{{// (note)}}</tt> - you can leave a note here, and the macro will be replaced with blank content. Not visible for the AI.</li>
|
<li><tt>{{// (note)}}</tt> - you can leave a note here, and the macro will be replaced with blank content. Not visible for the AI.</li>
|
||||||
|
<li><tt>{{lastMessageId}}</tt> - index # of the latest chat message. Useful for slash command batching.</li>
|
||||||
<li><tt>{{time}}</tt> - the current time</li>
|
<li><tt>{{time}}</tt> - the current time</li>
|
||||||
<li><tt>{{date}}</tt> - the current date</li>
|
<li><tt>{{date}}</tt> - the current date</li>
|
||||||
<li><tt>{{weekday}}</tt> - the current weekday</li>
|
<li><tt>{{weekday}}</tt> - the current weekday</li>
|
||||||
|
Reference in New Issue
Block a user