mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Context template editor. Part 1
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
{
|
||||
"name": "Classic",
|
||||
"storyString": "{{instructSystemPrompt}}\n{{wiBeforeCharacter}}\n{{description}}\n{{char}}'s personality: {{personality}}\nCircumstances and context of the dialogue: {{scenario}}\n{{wiAfterCharacter}}\nThis is how {{char}} should talk\n{{mesExamples}}\nThen the roleplay chat between {{user}} and {{char}} begins\n",
|
||||
"injections": []
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"name": "Pygmalion",
|
||||
"storyString": "{{instructSystemPrompt}}\n{{wiBeforeCharacter}}\n{{char}}'s Persona: {{description}}\nPersonality: {{personality}}\nScenario: {{scenario}}\n{{wiAfterCharacter}}\n<START>\n{{mesExamples}}\n<START>\n",
|
||||
"injections": []
|
||||
}
|
||||
|
@ -1365,13 +1365,11 @@
|
||||
Context Templates
|
||||
</h4>
|
||||
<div class="flex-container flexGap5">
|
||||
<select id="prompt_template" class="flex1 margin0">
|
||||
<option value="None">None (Default)</option>
|
||||
<option value="Classic">Classic</option>
|
||||
<option value="Pygmalion">Pygmalion</option>
|
||||
<select id="context_template" class="flex1 margin0">
|
||||
</select>
|
||||
<div id="context_template_edit" class="menu_button fa-solid fa-pencil margin0" title="Edit"></div>
|
||||
<div id="context_template_new" class="menu_button fa-solid fa-plus margin0" title="Add new"></div>
|
||||
<div id="context_template_new" class="menu_button fa-solid fa-plus margin0" title="Create new"></div>
|
||||
<div id="context_template_edit" class="menu_button fa-solid fa-file-pen margin0" title="Edit"></div>
|
||||
<div id="context_template_rename" class="menu_button fa-solid fa-i-cursor margin0" title="Rename"></div>
|
||||
<div id="context_template_delete" class="menu_button fa-solid fa-trash-can margin0" title="Delete"></div>
|
||||
</div>
|
||||
</div>
|
||||
@ -2223,6 +2221,7 @@
|
||||
<div id="context_editor_template" class="template_element">
|
||||
<div class="context_editor">
|
||||
<h3>Context Template Editor</h3>
|
||||
<h4 class="template_name"></h4>
|
||||
|
||||
<div class="inline-drawer wide100p">
|
||||
<div class="inline-drawer-toggle inline-drawer-header">
|
||||
@ -2256,7 +2255,7 @@
|
||||
<div>
|
||||
<div class="title_restorable">
|
||||
<span>Chat Injections</span>
|
||||
<div title="Add chat injection" class="menu_button">
|
||||
<div title="Add chat injection" class="menu_button chat_injection_add">
|
||||
<div class="fa-solid fa-plus"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -141,6 +141,7 @@ import {
|
||||
} from "./scripts/secrets.js";
|
||||
import uniqolor from "./scripts/uniqolor.js";
|
||||
import { EventEmitter } from './scripts/eventemitter.js';
|
||||
import { context_settings, loadContextTemplatesFromSettings } from "./scripts/context-template.js";
|
||||
|
||||
//exporting functions and vars for mods
|
||||
export {
|
||||
@ -3881,6 +3882,9 @@ async function getSettings(type) {
|
||||
// Load- character tags
|
||||
loadTagsSettings(settings);
|
||||
|
||||
// Load context templates
|
||||
loadContextTemplatesFromSettings(data, settings);
|
||||
|
||||
// Set context size after loading power user (may override the max value)
|
||||
$("#max_context").val(max_context);
|
||||
$("#max_context_counter").text(`${max_context}`);
|
||||
@ -3964,6 +3968,7 @@ async function saveSettings(type) {
|
||||
power_user: power_user,
|
||||
poe_settings: poe_settings,
|
||||
extension_settings: extension_settings,
|
||||
context_settings: context_settings,
|
||||
tags: tags,
|
||||
tag_map: tag_map,
|
||||
...nai_settings,
|
||||
@ -4432,7 +4437,7 @@ function callPopup(text, type, inputValue = '') {
|
||||
$("#dialogue_popup_input").css("display", "none");
|
||||
}
|
||||
|
||||
$("#dialogue_popup_text").html(text);
|
||||
$("#dialogue_popup_text").empty().append(text);
|
||||
$("#shadow_popup").css("display", "block");
|
||||
if (popup_type == 'input') {
|
||||
$("#dialogue_popup_input").focus();
|
||||
|
@ -1,11 +1,165 @@
|
||||
import {
|
||||
callPopup,
|
||||
getRequestHeaders,
|
||||
saveSettingsDebounced,
|
||||
} from '../script.js';
|
||||
import { debounce } from './utils.js';
|
||||
|
||||
export let context_templates = [];
|
||||
export let context_settings = {
|
||||
selected_template: '',
|
||||
};
|
||||
|
||||
const saveTemplateDebounced = debounce((name) => alert('implement me', name), 2000);
|
||||
|
||||
export function loadContextTemplatesFromSettings(data, settings) {
|
||||
context_templates = data.context || [];
|
||||
context_settings = Object.assign(context_settings, (settings.context_settings || {}));
|
||||
|
||||
const dropdown = $('#context_template');
|
||||
dropdown.empty();
|
||||
dropdown.append('<option value="">-- None --</option>')
|
||||
|
||||
for (const template of context_templates) {
|
||||
const name = template.name;
|
||||
const option = document.createElement('option');
|
||||
option.innerText = name;
|
||||
option.value = name;
|
||||
option.selected = context_settings.selected_template == name;
|
||||
dropdown.append(option);
|
||||
}
|
||||
}
|
||||
|
||||
function onContextTemplateChange() {
|
||||
const value = $(this).find(':selected').val();
|
||||
context_settings.selected_template = value;
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
function openContextTemplateEditor() {
|
||||
const template = context_templates.find(x => x.name == context_settings.selected_template);
|
||||
|
||||
if (!template || !context_settings.selected_template) {
|
||||
toastr.info('No context template selected');
|
||||
return;
|
||||
}
|
||||
|
||||
const editor = $('#context_editor_template .context_editor').clone();
|
||||
const injectionsContainer = editor.find('.chat_injections_list');
|
||||
editor.find('.template_name').text(template.name);
|
||||
editor.find('.story_string_template').text(template.storyString).on('input', function () {
|
||||
const value = $(this).val();
|
||||
template.storyString = value;
|
||||
saveTemplateDebounced(template.name);
|
||||
});
|
||||
editor.find('.chat_injection_add').on('click', function () {
|
||||
const injection = { id: Date.now(), text: '', depth: 0 };
|
||||
template.injections.push(injection);
|
||||
addChatInjection(injectionsContainer, injection, template);
|
||||
saveTemplateDebounced(template.name);
|
||||
});
|
||||
|
||||
for (const injection of template.injections) {
|
||||
addChatInjection(injectionsContainer, injection, template);
|
||||
}
|
||||
|
||||
$('#dialogue_popup').addClass('large_dialogue_popup wide_dialogue_popup');
|
||||
callPopup(editor.html(), 'text');
|
||||
callPopup(editor, 'text');
|
||||
}
|
||||
|
||||
async function onRenameContextTemplateClick() {
|
||||
const oldName = context_settings.selected_template;
|
||||
const newName = await inputTemplateName();
|
||||
const template = context_templates.find(x => x.name === oldName);
|
||||
|
||||
if (!template || !newName || oldName === newName) {
|
||||
return;
|
||||
}
|
||||
|
||||
await saveContextTemplate(newName);
|
||||
context_settings.selected_template = newName;
|
||||
saveSettingsDebounced();
|
||||
await deleteContextTemplate(oldName);
|
||||
toastr.success('Context template renamed', newName);
|
||||
}
|
||||
|
||||
async function deleteContextTemplate(name) {
|
||||
const response = await fetch('/delete_context_template', {
|
||||
method: 'POST',
|
||||
headers: getRequestHeaders(),
|
||||
body: JSON.stringify({ name }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Context template not deleted');
|
||||
}
|
||||
}
|
||||
|
||||
async function saveContextTemplate(name) {
|
||||
const template = context_templates.find(x => x.name === name);
|
||||
|
||||
if (!template) {
|
||||
throw new Error(`Context template not found: ${name}`);
|
||||
}
|
||||
|
||||
const response = await fetch('/save_context_template', {
|
||||
method: 'POST',
|
||||
headers: getRequestHeaders(),
|
||||
body: JSON.stringify({ name, template }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Context template not saved');
|
||||
}
|
||||
}
|
||||
|
||||
async function inputTemplateName() {
|
||||
let name = await callPopup('Enter a template name:', 'input');
|
||||
|
||||
if (!name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
name = DOMPurify.sanitize(name.trim());
|
||||
|
||||
if (context_templates.findIndex(x => x.name == name) > -1) {
|
||||
toastr.warning('Template with that name already exists', 'Pick a unique name');
|
||||
return false;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
function addChatInjection(container, model, parent) {
|
||||
const template = $('#chat_injection_template .chat_injection').clone();
|
||||
template.attr('id', model.id);
|
||||
template.find('.chat_injection_text').val(model.text).on('input', function () {
|
||||
const value = $(this).val();
|
||||
model.text = value;
|
||||
saveTemplateDebounced(parent.name);
|
||||
});
|
||||
template.find('.chat_injection_depth').val(model.depth).on('input', function () {
|
||||
const value = Math.abs(Number($(this).val()));
|
||||
model.depth = value;
|
||||
saveTemplateDebounced(parent.name);
|
||||
});
|
||||
template.find('.chat_injection_remove').on('click', function () {
|
||||
if (!confirm('Are you sure?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const index = parent.injections.findIndex(x => x == model);
|
||||
|
||||
if (index === -1) {
|
||||
console.error('Does not compute, injection index was lost');
|
||||
return;
|
||||
}
|
||||
|
||||
parent.injections.splice(index, 1);
|
||||
template.remove();
|
||||
saveTemplateDebounced(parent.name);
|
||||
});
|
||||
container.append(template);
|
||||
}
|
||||
|
||||
function copyTemplateParameter(event) {
|
||||
@ -14,7 +168,47 @@ function copyTemplateParameter(event) {
|
||||
toastr.info('Copied!', '', { timeOut: 2000 });
|
||||
}
|
||||
|
||||
async function onNewContextTemplateClick() {
|
||||
const name = await inputTemplateName();
|
||||
|
||||
if (!name) {
|
||||
return;
|
||||
}
|
||||
|
||||
const template = { name: name, injections: [], storyString: '' };
|
||||
context_templates.push(template);
|
||||
const option = document.createElement('option');
|
||||
option.innerText = name;
|
||||
option.value = name;
|
||||
option.selected = true;
|
||||
$('#context_template').append(option).val(name).trigger('change');
|
||||
saveTemplateDebounced(name);
|
||||
}
|
||||
|
||||
async function onDeleteContextTemplateClick() {
|
||||
const template = context_templates.find(x => x.name == context_settings.selected_template);
|
||||
|
||||
if (!template || !context_settings.selected_template) {
|
||||
toastr.info('No context template selected');
|
||||
return;
|
||||
}
|
||||
|
||||
const confirm = await callPopup('Are you sure?', 'confirm');
|
||||
|
||||
if (!confirm) {
|
||||
return;
|
||||
}
|
||||
|
||||
await deleteContextTemplate(context_settings.selected_template);
|
||||
$(`#context_template option[value="${context_settings.selected_template}"]`).remove();
|
||||
$('#context_template').trigger('change');
|
||||
}
|
||||
|
||||
jQuery(() => {
|
||||
$('#context_template_edit').on('click', openContextTemplateEditor);
|
||||
$('#context_template').on('change', onContextTemplateChange);
|
||||
$('#context_template_new').on('click', onNewContextTemplateClick);
|
||||
$('#context_template_rename').on('click', onRenameContextTemplateClick);
|
||||
$('#context_template_delete').on('click', onDeleteContextTemplateClick);
|
||||
$(document).on('pointerup', '.template_parameters_list code', copyTemplateParameter);
|
||||
})
|
Reference in New Issue
Block a user