Expand /persona-lock command for type

- Add new main alias for /lock, renamed to /persona-lock
- Allow no state to be provided to return the current lock state
- Deprecate the old usage of /lock without state, without breaking it
This commit is contained in:
Wolfsblvt
2025-01-24 23:24:35 +01:00
parent 91dabeff53
commit 7454532641
2 changed files with 82 additions and 19 deletions

View File

@@ -740,7 +740,7 @@ function isPersonaConnectionLocked(connection) {
* @param {PersonaLockType} type - Lock type * @param {PersonaLockType} type - Lock type
* @returns {boolean} Whether the persona is locked * @returns {boolean} Whether the persona is locked
*/ */
function isPersonaLocked(type = 'chat') { export function isPersonaLocked(type = 'chat') {
switch (type) { switch (type) {
case 'default': case 'default':
return power_user.default_persona === user_avatar; return power_user.default_persona === user_avatar;
@@ -756,21 +756,26 @@ function isPersonaLocked(type = 'chat') {
/** /**
* Locks or unlocks the persona * Locks or unlocks the persona
* @param {boolean} state Desired lock state * @param {boolean} state Desired lock state
* @param {PersonaLockType} type - Lock type
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
export async function setPersonaLockState(state) { export async function setPersonaLockState(state, type = 'chat') {
return state ? await lockPersona() : await unlockPersona(); return state ? await lockPersona(type) : await unlockPersona(type);
} }
/** /**
* Toggle the persona lock state * Toggle the persona lock state
* @param {PersonaLockType} type - Lock type * @param {PersonaLockType} type - Lock type
* @returns {Promise<void>} * @returns {Promise<boolean>} - Whether the persona was locked
*/ */
export async function togglePersonaLock(type = 'chat') { export async function togglePersonaLock(type = 'chat') {
return isPersonaLocked(type) if (isPersonaLocked(type)) {
? await unlockPersona(type) await unlockPersona(type);
: await lockPersona(type); return false;
} else {
await lockPersona(type);
return true;
}
} }
/** /**
@@ -810,6 +815,8 @@ async function unlockPersona(type = 'chat') {
} }
break; break;
} }
default:
throw new Error(`Unknown persona lock type: ${type}`);
} }
updatePersonaLockIcons(); updatePersonaLockIcons();
@@ -889,6 +896,8 @@ async function lockPersona(type = 'chat') {
} }
break; break;
} }
default:
throw new Error(`Unknown persona lock type: ${type}`);
} }
updatePersonaLockIcons(); updatePersonaLockIcons();

View File

@@ -54,7 +54,7 @@ import { getContext, saveMetadataDebounced } from './extensions.js';
import { getRegexedString, regex_placement } from './extensions/regex/engine.js'; import { getRegexedString, regex_placement } from './extensions/regex/engine.js';
import { findGroupMemberId, groups, is_group_generating, openGroupById, resetSelectedGroup, saveGroupChat, selected_group } from './group-chats.js'; import { findGroupMemberId, groups, is_group_generating, openGroupById, resetSelectedGroup, saveGroupChat, selected_group } from './group-chats.js';
import { chat_completion_sources, oai_settings, promptManager } from './openai.js'; import { chat_completion_sources, oai_settings, promptManager } from './openai.js';
import { autoSelectPersona, retriggerFirstMessageOnEmptyChat, setPersonaLockState, togglePersonaLock, user_avatar } from './personas.js'; import { autoSelectPersona, isPersonaLocked, retriggerFirstMessageOnEmptyChat, setPersonaLockState, togglePersonaLock, user_avatar } from './personas.js';
import { addEphemeralStoppingString, chat_styles, flushEphemeralStoppingStrings, power_user } from './power-user.js'; import { addEphemeralStoppingString, chat_styles, flushEphemeralStoppingStrings, power_user } from './power-user.js';
import { SERVER_INPUTS, textgen_types, textgenerationwebui_settings } from './textgen-settings.js'; import { SERVER_INPUTS, textgen_types, textgenerationwebui_settings } from './textgen-settings.js';
import { decodeTextTokens, getAvailableTokenizers, getFriendlyTokenizerName, getTextTokens, getTokenCountAsync, selectTokenizer } from './tokenizers.js'; import { decodeTextTokens, getAvailableTokenizers, getFriendlyTokenizerName, getTextTokens, getTokenCountAsync, selectTokenizer } from './tokenizers.js';
@@ -74,6 +74,7 @@ import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCom
import { SlashCommandBreakController } from './slash-commands/SlashCommandBreakController.js'; import { SlashCommandBreakController } from './slash-commands/SlashCommandBreakController.js';
import { SlashCommandExecutionError } from './slash-commands/SlashCommandExecutionError.js'; import { SlashCommandExecutionError } from './slash-commands/SlashCommandExecutionError.js';
import { slashCommandReturnHelper } from './slash-commands/SlashCommandReturnHelper.js'; import { slashCommandReturnHelper } from './slash-commands/SlashCommandReturnHelper.js';
import { t } from './i18n.js';
export { export {
executeSlashCommands, executeSlashCommandsWithOptions, getSlashCommandsHelp, registerSlashCommand, executeSlashCommands, executeSlashCommandsWithOptions, getSlashCommandsHelp, registerSlashCommand,
}; };
@@ -147,15 +148,62 @@ export function initDefaultSlashCommands() {
helpString: 'Syncs the user persona in user-attributed messages in the current chat.', helpString: 'Syncs the user persona in user-attributed messages in the current chat.',
})); }));
SlashCommandParser.addCommandObject(SlashCommand.fromProps({ SlashCommandParser.addCommandObject(SlashCommand.fromProps({
name: 'lock', name: 'persona-lock',
callback: lockPersonaCallback, callback: lockPersonaCallback,
aliases: ['bind'], returns: 'The current lock state for the given type',
helpString: 'Locks/unlocks a persona (name and avatar) to the current chat', helpString: 'Locks/unlocks a persona (name and avatar) to the current chat. Gets the current lock state for the given type if no state is provided.',
namedArgumentList: [
SlashCommandNamedArgument.fromProps({
name: 'type',
description: 'The type of the lock, where it should apply to',
typeList: [ARGUMENT_TYPE.STRING],
defaultValue: 'chat',
enumList: [
new SlashCommandEnumValue('chat', 'Lock the persona to the current chat.'),
new SlashCommandEnumValue('character', 'Lock this persona to the currently selected character. If the setting is enabled, mutliple personas can be locked to the same character.'),
new SlashCommandEnumValue('default', 'Lock this persona as the default persona for all new chats.'),
],
}),
],
unnamedArgumentList: [
SlashCommandArgument.fromProps({
description: 'state',
typeList: [ARGUMENT_TYPE.STRING],
enumProvider: commonEnumProviders.boolean('onOffToggle'),
}),
],
}));
// TODO: Legacy command. Might be removed in the future and replaced by /persona-lock with aliases.
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
name: 'lock',
callback: (args, value) => {
if (!value) {
value = 'toggle';
toastr.warning(t`Using /lock without a provided state to toggle the persona is deprecated. Please use /persona-lock instead.
In the future this command with no state provided will return the current state, instead of toggling it.`, t`Deprecation Warning`);
}
return lockPersonaCallback(args, value);
},
returns: 'The current lock state for the given type',
aliases: ['bind'],
helpString: 'Locks/unlocks a persona (name and avatar) to the current chat. Gets the current lock state for the given type if no state is provided.',
namedArgumentList: [
SlashCommandNamedArgument.fromProps({
name: 'type',
description: 'The type of the lock, where it should apply to',
typeList: [ARGUMENT_TYPE.STRING],
defaultValue: 'chat',
enumList: [
new SlashCommandEnumValue('chat', 'Lock the persona to the current chat.'),
new SlashCommandEnumValue('character', 'Lock this persona to the currently selected character. If the setting is enabled, mutliple personas can be locked to the same character.'),
new SlashCommandEnumValue('default', 'Lock this persona as the default persona for all new chats.'),
],
}),
],
unnamedArgumentList: [ unnamedArgumentList: [
SlashCommandArgument.fromProps({ SlashCommandArgument.fromProps({
description: 'state', description: 'state',
typeList: [ARGUMENT_TYPE.STRING], typeList: [ARGUMENT_TYPE.STRING],
isRequired: true,
defaultValue: 'toggle', defaultValue: 'toggle',
enumProvider: commonEnumProviders.boolean('onOffToggle'), enumProvider: commonEnumProviders.boolean('onOffToggle'),
}), }),
@@ -3346,19 +3394,25 @@ function syncCallback() {
} }
async function lockPersonaCallback(_args, value) { async function lockPersonaCallback(_args, value) {
if (['toggle', 't', ''].includes(value.trim().toLowerCase())) { const type = _args.type ?? 'chat';
await togglePersonaLock();
return ''; if (!value) {
return String(isPersonaLocked(type));
}
if (['toggle', 't'].includes(value.trim().toLowerCase())) {
const result = await togglePersonaLock(type);
return String(result);
} }
if (isTrueBoolean(value)) { if (isTrueBoolean(value)) {
await setPersonaLockState(true); await setPersonaLockState(true, type);
return ''; return 'true';
} }
if (isFalseBoolean(value)) { if (isFalseBoolean(value)) {
await setPersonaLockState(false); await setPersonaLockState(false, type);
return ''; return 'false';
} }