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

745453264160344a2a52accdcad4c5afc71ec027

Wolfsblvt <wolfsblvt@gmail.com>

2 files changed, +81 -18Ignore whitespace
public/scripts/personas.js+16 -7
@@ -740,7 +740,7 @@ function isPersonaConnectionLocked(connection) {
740 * @param {PersonaLockType} type - Lock type740 * @param {PersonaLockType} type - Lock type
741 * @returns {boolean} Whether the persona is locked741 * @returns {boolean} Whether the persona is locked
742 */742 */
743function isPersonaLocked(type = 'chat') {743export function isPersonaLocked(type = 'chat') {
744 switch (type) {744 switch (type) {
745 case 'default':745 case 'default':
746 return power_user.default_persona === user_avatar;746 return power_user.default_persona === user_avatar;
@@ -756,21 +756,26 @@ function isPersonaLocked(type = 'chat') {
756/**756/**
757 * Locks or unlocks the persona757 * Locks or unlocks the persona
758 * @param {boolean} state Desired lock state758 * @param {boolean} state Desired lock state
759 * @param {PersonaLockType} type - Lock type
759 * @returns {Promise<void>}760 * @returns {Promise<void>}
760 */761 */
761export async function setPersonaLockState(state) {762export async function setPersonaLockState(state, type = 'chat') {
762 return state ? await lockPersona() : await unlockPersona();763 return state ? await lockPersona(type) : await unlockPersona(type);
763}764}
764765
765/**766/**
766 * Toggle the persona lock state767 * Toggle the persona lock state
767 * @param {PersonaLockType} type - Lock type768 * @param {PersonaLockType} type - Lock type
768 * @returns {Promise<void>}769 * @returns {Promise<boolean>} - Whether the persona was locked
769 */770 */
770export async function togglePersonaLock(type = 'chat') {771export async function togglePersonaLock(type = 'chat') {
771 return isPersonaLocked(type)772 if (isPersonaLocked(type)) {
772 ? await unlockPersona(type)773 await unlockPersona(type);
773 : await lockPersona(type);774 return false;
775 } else {
776 await lockPersona(type);
777 return true;
778 }
774}779}
775780
776/**781/**
@@ -810,6 +815,8 @@ async function unlockPersona(type = 'chat') {
810 }815 }
811 break;816 break;
812 }817 }
818 default:
819 throw new Error(`Unknown persona lock type: ${type}`);
813 }820 }
814821
815 updatePersonaLockIcons();822 updatePersonaLockIcons();
@@ -889,6 +896,8 @@ async function lockPersona(type = 'chat') {
889 }896 }
890 break;897 break;
891 }898 }
899 default:
900 throw new Error(`Unknown persona lock type: ${type}`);
892 }901 }
893902
894 updatePersonaLockIcons();903 updatePersonaLockIcons();
public/scripts/slash-commands.js+65 -11
@@ -54,7 +54,7 @@ import { getContext, saveMetadataDebounced } from './extensions.js';
54import { getRegexedString, regex_placement } from './extensions/regex/engine.js';54import { getRegexedString, regex_placement } from './extensions/regex/engine.js';
55import { findGroupMemberId, groups, is_group_generating, openGroupById, resetSelectedGroup, saveGroupChat, selected_group } from './group-chats.js';55import { findGroupMemberId, groups, is_group_generating, openGroupById, resetSelectedGroup, saveGroupChat, selected_group } from './group-chats.js';
56import { chat_completion_sources, oai_settings, promptManager } from './openai.js';56import { chat_completion_sources, oai_settings, promptManager } from './openai.js';
57import { autoSelectPersona, retriggerFirstMessageOnEmptyChat, setPersonaLockState, togglePersonaLock, user_avatar } from './personas.js';57import { autoSelectPersona, isPersonaLocked, retriggerFirstMessageOnEmptyChat, setPersonaLockState, togglePersonaLock, user_avatar } from './personas.js';
58import { addEphemeralStoppingString, chat_styles, flushEphemeralStoppingStrings, power_user } from './power-user.js';58import { addEphemeralStoppingString, chat_styles, flushEphemeralStoppingStrings, power_user } from './power-user.js';
59import { SERVER_INPUTS, textgen_types, textgenerationwebui_settings } from './textgen-settings.js';59import { SERVER_INPUTS, textgen_types, textgenerationwebui_settings } from './textgen-settings.js';
60import { decodeTextTokens, getAvailableTokenizers, getFriendlyTokenizerName, getTextTokens, getTokenCountAsync, selectTokenizer } from './tokenizers.js';60import { decodeTextTokens, getAvailableTokenizers, getFriendlyTokenizerName, getTextTokens, getTokenCountAsync, selectTokenizer } from './tokenizers.js';
@@ -74,6 +74,7 @@ import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCom
74import { SlashCommandBreakController } from './slash-commands/SlashCommandBreakController.js';74import { SlashCommandBreakController } from './slash-commands/SlashCommandBreakController.js';
75import { SlashCommandExecutionError } from './slash-commands/SlashCommandExecutionError.js';75import { SlashCommandExecutionError } from './slash-commands/SlashCommandExecutionError.js';
76import { slashCommandReturnHelper } from './slash-commands/SlashCommandReturnHelper.js';76import { slashCommandReturnHelper } from './slash-commands/SlashCommandReturnHelper.js';
77import { t } from './i18n.js';
77export {78export {
78 executeSlashCommands, executeSlashCommandsWithOptions, getSlashCommandsHelp, registerSlashCommand,79 executeSlashCommands, executeSlashCommandsWithOptions, getSlashCommandsHelp, registerSlashCommand,
79};80};
@@ -147,15 +148,62 @@ export function initDefaultSlashCommands() {
147 helpString: 'Syncs the user persona in user-attributed messages in the current chat.',148 helpString: 'Syncs the user persona in user-attributed messages in the current chat.',
148 }));149 }));
149 SlashCommandParser.addCommandObject(SlashCommand.fromProps({150 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
150 name: 'lock',151 name: 'persona-lock',
151 callback: lockPersonaCallback,152 callback: lockPersonaCallback,
153 returns: 'The current lock state for the given type',
154 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.',
155 namedArgumentList: [
156 SlashCommandNamedArgument.fromProps({
157 name: 'type',
158 description: 'The type of the lock, where it should apply to',
159 typeList: [ARGUMENT_TYPE.STRING],
160 defaultValue: 'chat',
161 enumList: [
162 new SlashCommandEnumValue('chat', 'Lock the persona to the current chat.'),
163 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.'),
164 new SlashCommandEnumValue('default', 'Lock this persona as the default persona for all new chats.'),
165 ],
166 }),
167 ],
168 unnamedArgumentList: [
169 SlashCommandArgument.fromProps({
170 description: 'state',
171 typeList: [ARGUMENT_TYPE.STRING],
172 enumProvider: commonEnumProviders.boolean('onOffToggle'),
173 }),
174 ],
175 }));
176 // TODO: Legacy command. Might be removed in the future and replaced by /persona-lock with aliases.
177 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
178 name: 'lock',
179 callback: (args, value) => {
180 if (!value) {
181 value = 'toggle';
182 toastr.warning(t`Using /lock without a provided state to toggle the persona is deprecated. Please use /persona-lock instead.
183 In the future this command with no state provided will return the current state, instead of toggling it.`, t`Deprecation Warning`);
184 }
185 return lockPersonaCallback(args, value);
186 },
187 returns: 'The current lock state for the given type',
152 aliases: ['bind'],188 aliases: ['bind'],
153 helpString: 'Locks/unlocks a persona (name and avatar) to the current chat',189 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.',
190 namedArgumentList: [
191 SlashCommandNamedArgument.fromProps({
192 name: 'type',
193 description: 'The type of the lock, where it should apply to',
194 typeList: [ARGUMENT_TYPE.STRING],
195 defaultValue: 'chat',
196 enumList: [
197 new SlashCommandEnumValue('chat', 'Lock the persona to the current chat.'),
198 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.'),
199 new SlashCommandEnumValue('default', 'Lock this persona as the default persona for all new chats.'),
200 ],
201 }),
202 ],
154 unnamedArgumentList: [203 unnamedArgumentList: [
155 SlashCommandArgument.fromProps({204 SlashCommandArgument.fromProps({
156 description: 'state',205 description: 'state',
157 typeList: [ARGUMENT_TYPE.STRING],206 typeList: [ARGUMENT_TYPE.STRING],
158 isRequired: true,
159 defaultValue: 'toggle',207 defaultValue: 'toggle',
160 enumProvider: commonEnumProviders.boolean('onOffToggle'),208 enumProvider: commonEnumProviders.boolean('onOffToggle'),
161 }),209 }),
@@ -3346,19 +3394,25 @@ function syncCallback() {
3346}3394}
33473395
3348async function lockPersonaCallback(_args, value) {3396async function lockPersonaCallback(_args, value) {
3349 if (['toggle', 't', ''].includes(value.trim().toLowerCase())) {3397 const type = _args.type ?? 'chat';
3350 await togglePersonaLock();3398
3351 return '';3399 if (!value) {
3400 return String(isPersonaLocked(type));
3401 }
3402
3403 if (['toggle', 't'].includes(value.trim().toLowerCase())) {
3404 const result = await togglePersonaLock(type);
3405 return String(result);
3352 }3406 }
33533407
3354 if (isTrueBoolean(value)) {3408 if (isTrueBoolean(value)) {
3355 await setPersonaLockState(true);3409 await setPersonaLockState(true, type);
3356 return '';3410 return 'true';
3357 }3411 }
33583412
3359 if (isFalseBoolean(value)) {3413 if (isFalseBoolean(value)) {
3360 await setPersonaLockState(false);3414 await setPersonaLockState(false, type);
3361 return '';3415 return 'false';
33623416
3363 }3417 }
33643418