mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Author's Notes: Add per-character author's note
Adds the option to override the chat's author's note with one set for each character. This saves the pain of having to copy and paste author's notes for every chat. Signed-off-by: kingbri <bdashore3@proton.me>
This commit is contained in:
@ -50,6 +50,7 @@ const extension_settings = {
|
|||||||
memory: {},
|
memory: {},
|
||||||
note: {
|
note: {
|
||||||
default: '',
|
default: '',
|
||||||
|
chara: [],
|
||||||
},
|
},
|
||||||
caption: {},
|
caption: {},
|
||||||
expressions: {},
|
expressions: {},
|
||||||
|
@ -2,7 +2,7 @@ import { callPopup, eventSource, event_types, getRequestHeaders, saveSettingsDeb
|
|||||||
import { dragElement, isMobile } from "../../RossAscends-mods.js";
|
import { dragElement, isMobile } from "../../RossAscends-mods.js";
|
||||||
import { getContext, getApiUrl, modules, extension_settings, ModuleWorkerWrapper, doExtrasFetch } from "../../extensions.js";
|
import { getContext, getApiUrl, modules, extension_settings, ModuleWorkerWrapper, doExtrasFetch } from "../../extensions.js";
|
||||||
import { power_user } from "../../power-user.js";
|
import { power_user } from "../../power-user.js";
|
||||||
import { onlyUnique, debounce } from "../../utils.js";
|
import { onlyUnique, debounce, getCharaFilename } from "../../utils.js";
|
||||||
export { MODULE_NAME };
|
export { MODULE_NAME };
|
||||||
|
|
||||||
const MODULE_NAME = 'expressions';
|
const MODULE_NAME = 'expressions';
|
||||||
@ -437,7 +437,7 @@ function getSpriteFolderName(message) {
|
|||||||
avatarPath = message.original_avatar || context.characters.find(x => message.force_avatar && message.force_avatar.includes(encodeURIComponent(x.avatar)))?.avatar;
|
avatarPath = message.original_avatar || context.characters.find(x => message.force_avatar && message.force_avatar.includes(encodeURIComponent(x.avatar)))?.avatar;
|
||||||
}
|
}
|
||||||
else if (context.characterId) {
|
else if (context.characterId) {
|
||||||
avatarPath = context.characters[context.characterId].avatar;
|
avatarPath = getCharaFilename();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!avatarPath) {
|
if (!avatarPath) {
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
import { selected_group } from "../../group-chats.js";
|
import { selected_group } from "../../group-chats.js";
|
||||||
import { ModuleWorkerWrapper, extension_settings, getContext, saveMetadataDebounced } from "../../extensions.js";
|
import { ModuleWorkerWrapper, extension_settings, getContext, saveMetadataDebounced } from "../../extensions.js";
|
||||||
import { registerSlashCommand } from "../../slash-commands.js";
|
import { registerSlashCommand } from "../../slash-commands.js";
|
||||||
|
import { getCharaFilename } from "../../utils.js";
|
||||||
export { MODULE_NAME };
|
export { MODULE_NAME };
|
||||||
|
|
||||||
const MODULE_NAME = '2_floating_prompt'; // <= Deliberate, for sorting lower than memory
|
const MODULE_NAME = '2_floating_prompt'; // <= Deliberate, for sorting lower than memory
|
||||||
@ -99,6 +100,63 @@ async function onExtensionFloatingPositionInput(e) {
|
|||||||
saveMetadataDebounced();
|
saveMetadataDebounced();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onExtensionFloatingCharaPromptInput() {
|
||||||
|
const tempPrompt = $(this).val();
|
||||||
|
const avatarName = getCharaFilename();
|
||||||
|
let tempCharaNote = {
|
||||||
|
name: avatarName,
|
||||||
|
prompt: tempPrompt
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#extension_floating_chara_token_counter').text(getTokenCount(tempPrompt));
|
||||||
|
|
||||||
|
let existingCharaNoteIndex;
|
||||||
|
let existingCharaNote;
|
||||||
|
|
||||||
|
if (extension_settings.note.chara) {
|
||||||
|
existingCharaNoteIndex = extension_settings.note.chara.findIndex((e) => e.name === avatarName);
|
||||||
|
existingCharaNote = extension_settings.note.chara[existingCharaNoteIndex]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tempPrompt.length === 0 &&
|
||||||
|
extension_settings.note.chara &&
|
||||||
|
existingCharaNote &&
|
||||||
|
!existingCharaNote.useChara
|
||||||
|
) {
|
||||||
|
extension_settings.note.chara.splice(existingCharaNoteIndex, 1);
|
||||||
|
}
|
||||||
|
else if (extension_settings.note.chara && existingCharaNote) {
|
||||||
|
Object.assign(existingCharaNote, tempCharaNote);
|
||||||
|
}
|
||||||
|
else if (avatarName && tempPrompt.length > 0) {
|
||||||
|
if (!extension_settings.note.chara) {
|
||||||
|
extension_settings.note.chara = []
|
||||||
|
}
|
||||||
|
Object.assign(tempCharaNote, { useChara: false })
|
||||||
|
|
||||||
|
extension_settings.note.chara.push(tempCharaNote);
|
||||||
|
} else {
|
||||||
|
console.log("Character author's note error: No avatar name key could be found.");
|
||||||
|
toastr.error("Something went wrong. Could not save character's author's note.");
|
||||||
|
|
||||||
|
// Don't save settings if something went wrong
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
saveSettingsDebounced();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onExtensionFloatingCharaCheckboxChanged() {
|
||||||
|
const value = !!$(this).prop('checked');
|
||||||
|
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename());
|
||||||
|
|
||||||
|
if (charaNote) {
|
||||||
|
charaNote.useChara = value;
|
||||||
|
|
||||||
|
saveSettingsDebounced();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function onExtensionFloatingDefaultInput() {
|
function onExtensionFloatingDefaultInput() {
|
||||||
extension_settings.note.default = $(this).val();
|
extension_settings.note.default = $(this).val();
|
||||||
$('#extension_floating_default_token_counter').text(getTokenCount(extension_settings.note.default));
|
$('#extension_floating_default_token_counter').text(getTokenCount(extension_settings.note.default));
|
||||||
@ -114,6 +172,14 @@ function loadSettings() {
|
|||||||
$('#extension_floating_interval').val(chat_metadata[metadata_keys.interval]);
|
$('#extension_floating_interval').val(chat_metadata[metadata_keys.interval]);
|
||||||
$('#extension_floating_depth').val(chat_metadata[metadata_keys.depth]);
|
$('#extension_floating_depth').val(chat_metadata[metadata_keys.depth]);
|
||||||
$(`input[name="extension_floating_position"][value="${chat_metadata[metadata_keys.position]}"]`).prop('checked', true);
|
$(`input[name="extension_floating_position"][value="${chat_metadata[metadata_keys.position]}"]`).prop('checked', true);
|
||||||
|
|
||||||
|
if (extension_settings.note.chara) {
|
||||||
|
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename());
|
||||||
|
|
||||||
|
$('#extension_floating_chara').val(charaNote ? charaNote.prompt : '');
|
||||||
|
$('#extension_use_floating_chara').prop('checked', charaNote ? charaNote.useChara : false);
|
||||||
|
}
|
||||||
|
|
||||||
$('#extension_floating_default').val(extension_settings.note.default);
|
$('#extension_floating_default').val(extension_settings.note.default);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +210,17 @@ async function moduleWorker() {
|
|||||||
? (lastMessageNumber % chat_metadata[metadata_keys.interval])
|
? (lastMessageNumber % chat_metadata[metadata_keys.interval])
|
||||||
: (chat_metadata[metadata_keys.interval] - lastMessageNumber);
|
: (chat_metadata[metadata_keys.interval] - lastMessageNumber);
|
||||||
const shouldAddPrompt = messagesTillInsertion == 0;
|
const shouldAddPrompt = messagesTillInsertion == 0;
|
||||||
const prompt = shouldAddPrompt ? $('#extension_floating_prompt').val() : '';
|
|
||||||
|
let prompt = shouldAddPrompt ? $('#extension_floating_prompt').val() : '';
|
||||||
|
if (shouldAddPrompt && extension_settings.note.chara) {
|
||||||
|
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename());
|
||||||
|
|
||||||
|
// Only replace with the chara note if the user checked the box
|
||||||
|
if (charaNote && charaNote.useChara) {
|
||||||
|
prompt = charaNote.prompt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
context.setExtensionPrompt(MODULE_NAME, prompt, chat_metadata[metadata_keys.position], chat_metadata[metadata_keys.depth]);
|
context.setExtensionPrompt(MODULE_NAME, prompt, chat_metadata[metadata_keys.position], chat_metadata[metadata_keys.depth]);
|
||||||
$('#extension_floating_counter').text(shouldAddPrompt ? '0' : messagesTillInsertion);
|
$('#extension_floating_counter').text(shouldAddPrompt ? '0' : messagesTillInsertion);
|
||||||
}
|
}
|
||||||
@ -184,9 +260,23 @@ function onANMenuItemClick() {
|
|||||||
|
|
||||||
function onChatChanged() {
|
function onChatChanged() {
|
||||||
const tokenCounter1 = chat_metadata[metadata_keys.prompt] ? getTokenCount(chat_metadata[metadata_keys.prompt]) : 0;
|
const tokenCounter1 = chat_metadata[metadata_keys.prompt] ? getTokenCount(chat_metadata[metadata_keys.prompt]) : 0;
|
||||||
const tokenCounter2 = extension_settings.note.default ? getTokenCount(extension_settings.note.default) : 0;
|
|
||||||
$('#extension_floating_prompt_token_counter').text(tokenCounter1);
|
$('#extension_floating_prompt_token_counter').text(tokenCounter1);
|
||||||
$('#extension_floating_default_token_counter').text(tokenCounter2);
|
|
||||||
|
let tokenCounter2;
|
||||||
|
if (extension_settings.note.chara) {
|
||||||
|
const charaNote = extension_settings.note.chara.find((e) => e.name === getCharaFilename());
|
||||||
|
|
||||||
|
if (charaNote) {
|
||||||
|
tokenCounter2 = getTokenCount(charaNote.prompt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenCounter2) {
|
||||||
|
$('#extension_floating_chara_token_counter').text(tokenCounter2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const tokenCounter3 = extension_settings.note.default ? getTokenCount(extension_settings.note.default) : 0;
|
||||||
|
$('#extension_floating_default_token_counter').text(tokenCounter3);
|
||||||
}
|
}
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
@ -235,6 +325,25 @@ function onChatChanged() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr class="sysHR">
|
<hr class="sysHR">
|
||||||
|
<div class="inline-drawer">
|
||||||
|
<div id="charaANBlockToggle" class="inline-drawer-toggle inline-drawer-header">
|
||||||
|
<b>Character Author's Note</b>
|
||||||
|
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
|
||||||
|
</div>
|
||||||
|
<div class="inline-drawer-content">
|
||||||
|
<small>Will be automatically added as the author's note for this character.</small>
|
||||||
|
|
||||||
|
<textarea id="extension_floating_chara" class="text_pole" rows="8" maxlength="10000"
|
||||||
|
placeholder="Example:\n[Scenario: wacky adventures; Genre: romantic comedy; Style: verbose, creative]"></textarea>
|
||||||
|
<div class="extension_token_counter">Tokens: <span id="extension_floating_chara_token_counter">0</small></div>
|
||||||
|
|
||||||
|
<label for="extension_use_floating_chara">
|
||||||
|
<input id="extension_use_floating_chara" type="checkbox" />
|
||||||
|
<span data-i18n="Use character author's note">Use character author's note</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr class="sysHR">
|
||||||
<div class="inline-drawer">
|
<div class="inline-drawer">
|
||||||
<div id="defaultANBlockToggle" class="inline-drawer-toggle inline-drawer-header">
|
<div id="defaultANBlockToggle" class="inline-drawer-toggle inline-drawer-header">
|
||||||
<b>Default Author's Note</b>
|
<b>Default Author's Note</b>
|
||||||
@ -263,6 +372,8 @@ function onChatChanged() {
|
|||||||
$('#extension_floating_prompt').on('input', onExtensionFloatingPromptInput);
|
$('#extension_floating_prompt').on('input', onExtensionFloatingPromptInput);
|
||||||
$('#extension_floating_interval').on('input', onExtensionFloatingIntervalInput);
|
$('#extension_floating_interval').on('input', onExtensionFloatingIntervalInput);
|
||||||
$('#extension_floating_depth').on('input', onExtensionFloatingDepthInput);
|
$('#extension_floating_depth').on('input', onExtensionFloatingDepthInput);
|
||||||
|
$('#extension_floating_chara').on('input', onExtensionFloatingCharaPromptInput);
|
||||||
|
$('#extension_use_floating_chara').on('input', onExtensionFloatingCharaCheckboxChanged);
|
||||||
$('#extension_floating_default').on('input', onExtensionFloatingDefaultInput);
|
$('#extension_floating_default').on('input', onExtensionFloatingDefaultInput);
|
||||||
$('input[name="extension_floating_position"]').on('change', onExtensionFloatingPositionInput);
|
$('input[name="extension_floating_position"]').on('change', onExtensionFloatingPositionInput);
|
||||||
$('#ANClose').on('click', function () {
|
$('#ANClose').on('click', function () {
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { getContext } from "./extensions.js";
|
||||||
|
|
||||||
export function onlyUnique(value, index, array) {
|
export function onlyUnique(value, index, array) {
|
||||||
return array.indexOf(value) === index;
|
return array.indexOf(value) === index;
|
||||||
}
|
}
|
||||||
@ -420,3 +422,12 @@ export function isDataURL(str) {
|
|||||||
const regex = /^data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)*;?)?(base64)?,([a-z0-9!$&',()*+;=\-_%.~:@\/?#]+)?$/i;
|
const regex = /^data:([a-z]+\/[a-z0-9-+.]+(;[a-z-]+=[a-z0-9-]+)*;?)?(base64)?,([a-z0-9!$&',()*+;=\-_%.~:@\/?#]+)?$/i;
|
||||||
return regex.test(str);
|
return regex.test(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getCharaFilename() {
|
||||||
|
const context = getContext();
|
||||||
|
const fileName = context.characters[context.characterId].avatar;
|
||||||
|
|
||||||
|
if (fileName) {
|
||||||
|
return fileName.replace(/\.[^/.]+$/, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user