Add example extension for chat variables. Allow registering custom text processing functions for extensions

This commit is contained in:
Cohee
2023-08-22 17:46:37 +03:00
parent 0ffb3a8dda
commit 41cc86af9f
8 changed files with 149 additions and 34 deletions

View File

@@ -1,5 +1,5 @@
import { callPopup, eventSource, event_types, saveSettings, saveSettingsDebounced, getRequestHeaders } from "../script.js";
import { isSubsetOf, debounce } from "./utils.js";
import { isSubsetOf, debounce, waitUntilCondition } from "./utils.js";
export {
getContext,
getApiUrl,
@@ -16,6 +16,42 @@ let manifests = [];
const defaultUrl = "http://localhost:5100";
export const saveMetadataDebounced = debounce(async () => await getContext().saveMetadata(), 1000);
export const extensionsHandlebars = Handlebars.create();
/**
* Registers a Handlebars helper for use in extensions.
* @param {string} name Handlebars helper name
* @param {function} helper Handlebars helper function
*/
export function registerExtensionHelper(name, helper) {
extensionsHandlebars.registerHelper(name, helper);
}
/**
* Applies handlebars extension helpers to a message.
* @param {number} messageId Message index in the chat.
*/
function processExtensionHelpers(messageId) {
const context = getContext();
const message = context.chat[messageId];
if (!message?.mes || typeof message.mes !== 'string') {
return;
}
// Don't waste time if there are no mustaches
if (!message.mes.includes('{{')) {
return;
}
try {
const template = extensionsHandlebars.compile(message.mes, { noEscape: true });
message.mes = template({});
} catch {
// Ignore
}
}
// Disables parallel updates
class ModuleWorkerWrapper {
constructor(callback) {
@@ -629,10 +665,13 @@ async function runGenerationInterceptors(chat, contextSize) {
}
}
$(document).ready(async function () {
setTimeout(function () {
jQuery(function () {
setTimeout(async function () {
addExtensionsButtonAndMenu();
$("#extensionsMenuButton").css("display", "flex");
await waitUntilCondition(() => eventSource !== undefined, 1000, 100);
eventSource.on(event_types.MESSAGE_RECEIVED, processExtensionHelpers);
eventSource.on(event_types.MESSAGE_SENT, processExtensionHelpers);
}, 100)
$("#extensions_connect").on('click', connectClickHandler);

View File

@@ -0,0 +1,62 @@
import { getContext } from "../../extensions.js";
/**
* Gets a chat variable from the current chat metadata.
* @param {string} name The name of the variable to get.
* @returns {string} The value of the variable.
*/
function getChatVariable(name) {
const metadata = getContext().chatMetadata;
if (!metadata) {
return '';
}
if (!metadata.variables) {
metadata.variables = {};
return '';
}
return metadata.variables[name] || '';
}
/**
* Sets a chat variable in the current chat metadata.
* @param {string} name The name of the variable to set.
* @param {any} value The value of the variable to set.
*/
function setChatVariable(name, value) {
const metadata = getContext().chatMetadata;
if (!metadata) {
return;
}
if (!metadata.variables) {
metadata.variables = {};
}
metadata.variables[name] = value;
}
function listChatVariables() {
const metadata = getContext().chatMetadata;
if (!metadata) {
return '';
}
if (!metadata.variables) {
metadata.variables = {};
return '';
}
return Object.keys(metadata.variables).map(key => `${key}=${metadata.variables[key]}`).join(';');
}
jQuery(() => {
const context = getContext();
context.registerHelper('getvar', getChatVariable);
context.registerHelper('setvar', setChatVariable);
context.registerHelper('listvar', listChatVariables);
});

View File

@@ -0,0 +1,11 @@
{
"display_name": "Chat Variables",
"loading_order": 100,
"requires": [],
"optional": [],
"js": "index.js",
"css": "",
"author": "Cohee#1207",
"version": "1.0.0",
"homePage": "https://github.com/SillyTavern/SillyTavern"
}

View File

@@ -1088,8 +1088,8 @@ async function sendAltScaleRequest(openai_msgs_tosend, logit_bias, signal) {
const generate_url = '/generate_altscale';
let firstSysMsgs = []
for(let msg of openai_msgs_tosend){
if(msg.role === 'system') {
for (let msg of openai_msgs_tosend) {
if (msg.role === 'system') {
firstSysMsgs.push(substituteParams(msg.name ? msg.name + ": " + msg.content : msg.content));
} else {
break;
@@ -2587,7 +2587,7 @@ function onSettingsPresetChange() {
use_ai21_tokenizer: ['#use_ai21_tokenizer', 'use_ai21_tokenizer', false],
exclude_assistant: ['#exclude_assistant', 'exclude_assistant', false],
use_alt_scale: ['#use_alt_scale', 'use_alt_scale', false],
};
};
const presetName = $('#settings_perset_openai').find(":selected").text();
oai_settings.preset_settings_openai = presetName;

View File

@@ -338,8 +338,8 @@ async function sendMessageAs(_, text) {
};
chat.push(message);
addOneMessage(message);
await eventSource.emit(event_types.MESSAGE_SENT, (chat.length - 1));
addOneMessage(message);
saveChatConditional();
}
@@ -369,8 +369,8 @@ async function sendNarratorMessage(_, text) {
};
chat.push(message);
addOneMessage(message);
await eventSource.emit(event_types.MESSAGE_SENT, (chat.length - 1));
addOneMessage(message);
saveChatConditional();
}
@@ -394,8 +394,8 @@ async function sendCommentMessage(_, text) {
};
chat.push(message);
addOneMessage(message);
await eventSource.emit(event_types.MESSAGE_SENT, (chat.length - 1));
addOneMessage(message);
saveChatConditional();
}