mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-04-18 12:47:27 +02:00
Persona settings for auto-lock & multi connection
- Add setting to auto-lock persona to chat. Triggered on chat changed (creation/loaded) and on persona selection. - Add setting to allow multiple persona<->char connections, which then triggers the popup to select one - If no multi connections allowed, the connect toggle will remove all existing connections from personas to that character
This commit is contained in:
parent
08a4cee48f
commit
776dedea82
@ -4984,7 +4984,7 @@
|
|||||||
<div class="persona_management_global_settings">
|
<div class="persona_management_global_settings">
|
||||||
<h4 class="standoutHeader" data-i18n="Global Settings">Global Settings</h4>
|
<h4 class="standoutHeader" data-i18n="Global Settings">Global Settings</h4>
|
||||||
|
|
||||||
<div class="persona_management_show_notifications range-block">
|
<div class="range-block">
|
||||||
<label for="persona_show_notifications" class="checkbox_label">
|
<label for="persona_show_notifications" class="checkbox_label">
|
||||||
<input id="persona_show_notifications" type="checkbox" />
|
<input id="persona_show_notifications" type="checkbox" />
|
||||||
<span data-i18n="Show notifications on switching personas">
|
<span data-i18n="Show notifications on switching personas">
|
||||||
@ -4992,6 +4992,22 @@
|
|||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="range-block">
|
||||||
|
<label for="persona_allow_multi_connections" class="checkbox_label" title="When multiple personas are connected to a character, a popup will appear to select which one to use." data-i18n="[title]When multiple personas are connected to a character, a popup will appear to select which one to use">
|
||||||
|
<input id="persona_allow_multi_connections" type="checkbox" />
|
||||||
|
<span data-i18n="Allow multiple persona connections per character">
|
||||||
|
Allow multiple persona connections per character
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="range-block">
|
||||||
|
<label for="persona_auto_lock" class="checkbox_label" title="Whenever a persona is selected, it will be locked to the current chat and automatically selected when the chat is opened." data-i18n="[title]Whenever a persona is selected, it will be locked to the current chat and automatically selected when the chat is opened.">
|
||||||
|
<input id="persona_auto_lock" type="checkbox" />
|
||||||
|
<span data-i18n="Auto-lock a chosen persona to the chat">
|
||||||
|
Auto-lock a chosen persona to the chat
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -30,6 +30,7 @@ import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup } from './popup.js';
|
|||||||
import { t } from './i18n.js';
|
import { t } from './i18n.js';
|
||||||
import { openWorldInfoEditor, world_names } from './world-info.js';
|
import { openWorldInfoEditor, world_names } from './world-info.js';
|
||||||
import { renderTemplateAsync } from './templates.js';
|
import { renderTemplateAsync } from './templates.js';
|
||||||
|
import { saveMetadataDebounced } from './extensions.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {object} PersonaConnection A connection between a character and a character or group entity
|
* @typedef {object} PersonaConnection A connection between a character and a character or group entity
|
||||||
@ -552,6 +553,7 @@ export async function askForPersonaSelection(title, text, personas) {
|
|||||||
content.appendChild(titleElement);
|
content.appendChild(titleElement);
|
||||||
|
|
||||||
const textElement = document.createElement('div');
|
const textElement = document.createElement('div');
|
||||||
|
textElement.classList.add('m-b-1');
|
||||||
textElement.textContent = text;
|
textElement.textContent = text;
|
||||||
content.appendChild(textElement);
|
content.appendChild(textElement);
|
||||||
|
|
||||||
@ -567,7 +569,7 @@ export async function askForPersonaSelection(title, text, personas) {
|
|||||||
block.dataset.result = String(100 + personas.indexOf(block.dataset.pid));
|
block.dataset.result = String(100 + personas.indexOf(block.dataset.pid));
|
||||||
});
|
});
|
||||||
|
|
||||||
const popup = new Popup(content, POPUP_TYPE.TEXT, '', {});
|
const popup = new Popup(content, POPUP_TYPE.TEXT, '', { okButton: 'None' });
|
||||||
const result = await popup.show();
|
const result = await popup.show();
|
||||||
return Number(result) > 100 ? personas[Number(result) - 100] : null;
|
return Number(result) > 100 ? personas[Number(result) - 100] : null;
|
||||||
}
|
}
|
||||||
@ -702,10 +704,21 @@ function selectCurrentPersona() {
|
|||||||
depth: DEFAULT_DEPTH,
|
depth: DEFAULT_DEPTH,
|
||||||
role: DEFAULT_ROLE,
|
role: DEFAULT_ROLE,
|
||||||
lorebook: '',
|
lorebook: '',
|
||||||
|
connections: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
setPersonaDescription();
|
setPersonaDescription();
|
||||||
|
|
||||||
|
// Update the locked persona if setting is enabled
|
||||||
|
if (power_user.persona_auto_lock && personaName && user_avatar !== chat_metadata['persona']) {
|
||||||
|
chat_metadata['persona'] = user_avatar;
|
||||||
|
console.log(`Auto locked persona to ${user_avatar}`);
|
||||||
|
if (power_user.persona_show_notifications) {
|
||||||
|
toastr.info(`Auto locked persona ${personaName} to current chat`);
|
||||||
|
}
|
||||||
|
saveMetadataDebounced();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -834,8 +847,7 @@ async function lockPersona(type = 'chat') {
|
|||||||
case 'chat': {
|
case 'chat': {
|
||||||
console.log(`Locking persona ${user_avatar} to this chat`);
|
console.log(`Locking persona ${user_avatar} to this chat`);
|
||||||
chat_metadata['persona'] = user_avatar;
|
chat_metadata['persona'] = user_avatar;
|
||||||
await saveMetadata();
|
saveMetadataDebounced();
|
||||||
saveSettingsDebounced();
|
|
||||||
if (power_user.persona_show_notifications) {
|
if (power_user.persona_show_notifications) {
|
||||||
toastr.success(t`User persona ${name1} is locked to ${name2} in this chat`);
|
toastr.success(t`User persona ${name1} is locked to ${name2} in this chat`);
|
||||||
}
|
}
|
||||||
@ -849,10 +861,27 @@ async function lockPersona(type = 'chat') {
|
|||||||
if (newConnection && newConnection.id) {
|
if (newConnection && newConnection.id) {
|
||||||
console.log(`Locking persona ${user_avatar} to this character ${name2}`);
|
console.log(`Locking persona ${user_avatar} to this character ${name2}`);
|
||||||
power_user.persona_descriptions[user_avatar].connections = [...connections, newConnection];
|
power_user.persona_descriptions[user_avatar].connections = [...connections, newConnection];
|
||||||
|
|
||||||
|
const unlinkedCharacters = [];
|
||||||
|
if (!power_user.persona_allow_multi_connections) {
|
||||||
|
for (const [avatarId, description] of Object.entries(power_user.persona_descriptions)) {
|
||||||
|
if (avatarId === user_avatar) continue;
|
||||||
|
|
||||||
|
const filteredConnections = description.connections?.filter(c => !(c.type === newConnection.type && c.id === newConnection.id)) ?? [];
|
||||||
|
if (filteredConnections.length !== description.connections?.length) {
|
||||||
|
description.connections = filteredConnections;
|
||||||
|
unlinkedCharacters.push(power_user.personas[avatarId]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
updatePersonaConnectionsAvatarList();
|
updatePersonaConnectionsAvatarList();
|
||||||
if (power_user.persona_show_notifications) {
|
if (power_user.persona_show_notifications) {
|
||||||
toastr.success(t`User persona ${name1} is locked to character ${name2}`);
|
let additional = '';
|
||||||
|
if (unlinkedCharacters.length)
|
||||||
|
additional += `<br /><br />${t`Unlinked existing persona${unlinkedCharacters.length > 1 ? 's' : ''}: ${unlinkedCharacters.join(', ')}`}`;
|
||||||
|
toastr.success(t`User persona ${name1} is locked to character ${name2}${additional}`, null, { escapeHtml: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1136,6 +1165,9 @@ async function setChatLockedPersona() {
|
|||||||
// Define a persona for this chat
|
// Define a persona for this chat
|
||||||
let chatPersona = '';
|
let chatPersona = '';
|
||||||
|
|
||||||
|
/** @type {'chat' | 'character' | 'default' | null} */
|
||||||
|
let connectType = null;
|
||||||
|
|
||||||
// If persona is locked in chat metadata, select it
|
// If persona is locked in chat metadata, select it
|
||||||
if (chat_metadata['persona']) {
|
if (chat_metadata['persona']) {
|
||||||
console.log(`Using locked persona ${chat_metadata['persona']}`);
|
console.log(`Using locked persona ${chat_metadata['persona']}`);
|
||||||
@ -1145,15 +1177,12 @@ async function setChatLockedPersona() {
|
|||||||
if (!userAvatars.includes(chatPersona)) {
|
if (!userAvatars.includes(chatPersona)) {
|
||||||
console.warn('Chat-locked persona avatar not found, unlocking persona');
|
console.warn('Chat-locked persona avatar not found, unlocking persona');
|
||||||
delete chat_metadata['persona'];
|
delete chat_metadata['persona'];
|
||||||
updatePersonaLockIcons();
|
saveSettingsDebounced();
|
||||||
chatPersona = '';
|
chatPersona = '';
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
if (chatPersona) connectType = 'chat';
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: TEMP
|
|
||||||
power_user.persona_allow_multi_connections = true;
|
|
||||||
|
|
||||||
// Check if we have any persona connected to the current character
|
// Check if we have any persona connected to the current character
|
||||||
if (!chatPersona) {
|
if (!chatPersona) {
|
||||||
const characterKey = menu_type === 'group_edit' ? selected_group : characters[this_chid]?.avatar;
|
const characterKey = menu_type === 'group_edit' ? selected_group : characters[this_chid]?.avatar;
|
||||||
@ -1171,12 +1200,16 @@ async function setChatLockedPersona() {
|
|||||||
connectedPersonas);
|
connectedPersonas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (chatPersona) connectType = 'character';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Last check if default persona is set, select it
|
// Last check if default persona is set, select it
|
||||||
if (!chatPersona && power_user.default_persona) {
|
if (!chatPersona && power_user.default_persona) {
|
||||||
console.log(`Using default persona ${power_user.default_persona}`);
|
console.log(`Using default persona ${power_user.default_persona}`);
|
||||||
chatPersona = power_user.default_persona;
|
chatPersona = power_user.default_persona;
|
||||||
|
|
||||||
|
if (chatPersona) connectType = 'default';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whatever way we selected a persona, if it doesn't exist, unlock this chat
|
// Whatever way we selected a persona, if it doesn't exist, unlock this chat
|
||||||
@ -1195,6 +1228,10 @@ async function setChatLockedPersona() {
|
|||||||
// Persona avatar found, select it
|
// Persona avatar found, select it
|
||||||
if (chatPersona) {
|
if (chatPersona) {
|
||||||
setUserAvatar(chatPersona);
|
setUserAvatar(chatPersona);
|
||||||
|
|
||||||
|
if (power_user.persona_show_notifications) {
|
||||||
|
toastr.info(t`Auto-selected persona ${power_user.personas[chatPersona]} based on ${connectType} connection.`, t`Persona Management`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePersonaLockIcons();
|
updatePersonaLockIcons();
|
||||||
|
@ -1477,6 +1477,8 @@ async function loadPowerUserSettings(settings, data) {
|
|||||||
$('#custom_stopping_strings_macro').prop('checked', power_user.custom_stopping_strings_macro);
|
$('#custom_stopping_strings_macro').prop('checked', power_user.custom_stopping_strings_macro);
|
||||||
$('#fuzzy_search_checkbox').prop('checked', power_user.fuzzy_search);
|
$('#fuzzy_search_checkbox').prop('checked', power_user.fuzzy_search);
|
||||||
$('#persona_show_notifications').prop('checked', power_user.persona_show_notifications);
|
$('#persona_show_notifications').prop('checked', power_user.persona_show_notifications);
|
||||||
|
$('#persona_allow_multi_connections').prop('checked', power_user.persona_allow_multi_connections);
|
||||||
|
$('#persona_auto_lock').prop('checked', power_user.persona_auto_lock);
|
||||||
$('#encode_tags').prop('checked', power_user.encode_tags);
|
$('#encode_tags').prop('checked', power_user.encode_tags);
|
||||||
$('#example_messages_behavior').val(getExampleMessagesBehavior());
|
$('#example_messages_behavior').val(getExampleMessagesBehavior());
|
||||||
$(`#example_messages_behavior option[value="${getExampleMessagesBehavior()}"]`).prop('selected', true);
|
$(`#example_messages_behavior option[value="${getExampleMessagesBehavior()}"]`).prop('selected', true);
|
||||||
@ -3652,6 +3654,16 @@ $(document).ready(() => {
|
|||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#persona_allow_multi_connections').on('input', function () {
|
||||||
|
power_user.persona_allow_multi_connections = !!$(this).prop('checked');
|
||||||
|
saveSettingsDebounced();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#persona_auto_lock').on('input', function () {
|
||||||
|
power_user.persona_auto_lock = !!$(this).prop('checked');
|
||||||
|
saveSettingsDebounced();
|
||||||
|
});
|
||||||
|
|
||||||
$('#encode_tags').on('input', async function () {
|
$('#encode_tags').on('input', async function () {
|
||||||
power_user.encode_tags = !!$(this).prop('checked');
|
power_user.encode_tags = !!$(this).prop('checked');
|
||||||
await reloadCurrentChat();
|
await reloadCurrentChat();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user