Update persona.js code documentation for exported

e27e045054e19d120fa26690cdcea07d09b9d375

Wolfsblvt <wolfsblvt@gmail.com>

1 files changed, +86 -17Ignore whitespace
public/scripts/personas.js+86 -17
@@ -61,7 +61,11 @@ let savePersonasPage = 0;
6161const GRID_STORAGE_KEY = 'Personas_GridView';
6262const DEFAULT_DEPTH = 2;
6363const DEFAULT_ROLE = 0;
64+
65+/** @type {string} The currently selected persona (identified by its avatar) */
6466export let user_avatar = '';
67+
68+/** @type {FilterHelper} Filter helper for the persona list */
6569export const personasFilter = new FilterHelper(debounce(getUserAvatars, debounce_timeout.quick));
6670
6771
@@ -441,13 +445,25 @@ export function initPersona(avatarId, personaName, personaDescription) {
441445 saveSettingsDebounced();
442446}
443447
448+/**
449+ * Converts a character given character (either by character id or the current character) to a persona.
450+ *
451+ * If a persona with the same name already exists, the user is prompted to confirm whether or not to overwrite it.
452+ * If the character description contains {{char}} or {{user}} macros, the user is prompted to confirm whether or not to swap them for persona macros.
453+ *
454+ * The function creates a new persona with the same name as the character, and sets the persona description to the character description with the macros swapped.
455+ * The function also saves the settings and refreshes the persona selector.
456+ *
457+ * @param {number} [characterId] - The ID of the character to convert to a persona. Defaults to the current character ID.
458+ * @returns {Promise<boolean>} A promise that resolves to true if the character was converted, false otherwise.
459+ */
444460export async function convertCharacterToPersona(characterId = null) {
445461 if (null === characterId) characterId = this_chid;
446462
447463 const avatarUrl = characters[characterId]?.avatar;
448464 if (!avatarUrl) {
449465 console.log('No avatar found for this character');
450466 return false;
451467 }
452468
453469 const name = characters[characterId]?.name;
@@ -458,7 +474,7 @@ export async function convertCharacterToPersona(characterId = null) {
458474 const confirm = await Popup.show.confirm(t`Overwrite Existing Persona`, t`This character exists as a persona already. Do you want to overwrite it?`);
459475 if (!confirm) {
460476 console.log('User cancelled the overwrite of the persona');
461477 return false;
462478 }
463479 }
464480
@@ -496,6 +512,7 @@ export async function convertCharacterToPersona(characterId = null) {
496512 await getUserAvatars(true, overwriteName);
497513 // Reload the persona description
498514 setPersonaDescription();
515+ return true;
499516}
500517
501518/**
@@ -507,6 +524,9 @@ const countPersonaDescriptionTokens = debounce(async () => {
507524 $('#persona_description_token_count').text(String(count));
508525}, debounce_timeout.relaxed);
509526
527+/**
528+ * Updates the UI for the Persona Management page with the current persona values
529+ */
510530export function setPersonaDescription() {
511531 $('#your_name').text(name1);
512532
@@ -683,22 +703,33 @@ export async function askForPersonaSelection(title, text, personas, { okButton =
683703 return Number(result) >= 100 ? personas[Number(result) - 100] : null;
684704}
685705
706+/**
707+ * Automatically selects a persona based on the given name if a matching persona exists.
708+ * @param {string} name - The name to search for
709+ * @returns {boolean} True if a matching persona was found and selected, false otherwise
710+ */
686711export function autoSelectPersona(name) {
687712 for (const [key, value] of Object.entries(power_user.personas)) {
688713 if (value === name) {
689714 console.log(`Auto-selecting persona ${key} for name ${name}`);
690715 setUserAvatar(key);
691716 return true;
692717 }
693718 }
719+ return false;
694720}
695721
722+/**
723+ * Renames the persona with the given avatar ID by showing a popup to enter a new name.
724+ * @param {string} avatarId - ID of the avatar to rename
725+ * @returns {Promise<boolean>} A promise that resolves to true if the persona was renamed, false otherwise
726+ */
696727async function renamePersona(avatarId) {
697728 const currentName = power_user.personas[avatarId];
698729 const newName = await Popup.show.input(t`Rename Persona`, t`Enter a new name for this persona:`, currentName);
699730 if (!newName || newName === currentName) {
700731 console.debug('User cancelled renaming persona or name is unchanged');
701732 return false;
702733 }
703734
704735 power_user.personas[avatarId] = newName;
@@ -712,9 +743,16 @@ async function renamePersona(avatarId) {
712743 await getUserAvatars(true, avatarId);
713744 updatePersonaUIStates();
714745 setPersonaDescription();
746+ return true;
715747}
716748
717-function selectCurrentPersona({ toastPersonaNameChange = true } = {}) {
749+/**
750+ * Selects the persona with the currently set avatar ID by updating the user name and persona description, and updating the locked persona if the setting is enabled.
751+ * @param {object} [options={}] - Optional settings
752+ * @param {boolean} [options.toastPersonaNameChange=true] - Whether to show a toast when the persona name is changed
753+ * @returns {Promise<void>}
754+ */
755+async function selectCurrentPersona({ toastPersonaNameChange = true } = {}) {
718756 const personaName = power_user.personas[user_avatar];
719757 if (personaName) {
720758 const shouldAutoLock = power_user.persona_auto_lock && user_avatar !== chat_metadata['persona'];
@@ -1211,6 +1249,14 @@ function getPersonaStates(avatarId) {
12111249 };
12121250}
12131251
1252+/**
1253+ * Updates the UI to reflect the current states of all personas and the selected user's persona.
1254+ * This includes updating class states on avatar containers to indicate default status, chat lock,
1255+ * and character lock, as well as updating icons and labels in the persona management panel to reflect
1256+ * the current state of the user's persona.
1257+ * Additionally, it manages the display of temporary persona lock information.
1258+ */
1259+
12141260function updatePersonaUIStates() {
12151261 // Update the persona list
12161262 $('#user_avatar_block .avatar-container').each(function () {
@@ -1258,15 +1304,21 @@ function updatePersonaUIStates() {
12581304}
12591305
12601306/**
1261- * Checks if the currently selected persona is temporary due to either a different default persona
1307+ * @typedef {Object} PersonaLockInfo
1262- * or a different persona being locked to the current chat. If so, it also returns a string that
1308+ * @property {boolean} isTemporary - Whether the selected persona is temporary based on current locks.
1263- * can be used to describe this situation to the user.
1309+ * @property {boolean} hasDifferentChatLock - True if the chat persona is set and differs from the user avatar.
1310+ * @property {boolean} hasDifferentDefaultLock - True if the default persona is set and differs from the user avatar.
1311+ * @property {string} info - Detailed information about the current, chat, and default personas.
1312+ */
1313+
1314+/**
1315+ * Computes temporary lock information for the current persona.
1316+ *
1317+ * This function checks whether the currently selected persona is temporary by comparing
1318+ * the chat persona and the default persona to the user avatar. If either is different,
1319+ * the currently selected persona is considered temporary and a detailed message is generated.
12641320 *
1265- * @returns {{isTemporary: boolean, hasDifferentChatLock: boolean, hasDifferentDefaultLock: boolean, info: string?}} An object containing 4 properties:
1321+ * @returns {PersonaLockInfo} An object containing flags and a message describing the persona lock status.
1266- * - isTemporary: A boolean indicating if the current persona is temporary
1267- * - hasDifferentChatLock: A boolean indicating if the current chat has a different persona locked to it
1268- * - hasDifferentDefaultLock: A boolean indicating if there is a different default persona set
1269- * - info: A string describing the situation, or an empty if not temporary
12701322 */
12711323function getPersonaTemporaryLockInfo() {
12721324 const hasDifferentChatLock = !!chat_metadata['persona'] && chat_metadata['persona'] !== user_avatar;
@@ -1286,6 +1338,13 @@ function getPersonaTemporaryLockInfo() {
12861338 };
12871339}
12881340
1341+/**
1342+ * Loads the appropriate persona for the current chat session based on locks (chat lock, char lock, default persona)
1343+ *
1344+ * @param {Object} [options={}] - Optional arguments
1345+ * @param {boolean} [options.doRender=false] - Whether to render the persona immediately
1346+ * @returns {Promise<boolean>} - A promise that resolves to a boolean indicating whether a persona was selected
1347+ */
12891348async function loadPersonaForCurrentChat({ doRender = false } = {}) {
12901349 // Cache persona list to check if they exist
12911350 const userAvatars = await getUserAvatars(doRender);
@@ -1317,7 +1376,7 @@ async function loadPersonaForCurrentChat({ doRender = false } = {}) {
13171376 if (chatPersona) {
13181377 // If the chat-bound persona is the currently selected one, we can simply exit out
13191378 if (chatPersona === user_avatar) {
13201379 return false;
13211380 }
13221381 // Otherwise ask if we want to switch
13231382 const autoLock = power_user.persona_auto_lock;
@@ -1328,11 +1387,11 @@ async function loadPersonaForCurrentChat({ doRender = false } = {}) {
13281387 if (autoLock) {
13291388 lockPersona('chat');
13301389 }
13311390 return false;
13321391 }
13331392 } else {
13341393 // If we don't have a chat-bound persona, we simply return and keep the current one we have
13351394 return false;
13361395 }
13371396 }
13381397
@@ -1392,6 +1451,8 @@ async function loadPersonaForCurrentChat({ doRender = false } = {}) {
13921451 }
13931452
13941453 updatePersonaUIStates();
1454+
1455+ return !!chatPersona;
13951456}
13961457
13971458/**
@@ -1462,7 +1523,6 @@ export async function showCharConnections() {
14621523 *
14631524 * @returns {PersonaConnection} An object representing the current connection
14641525 */
1465-
14661526export function getCurrentConnectionObj() {
14671527 if (selected_group)
14681528 return { type: 'group', id: selected_group };
@@ -1579,6 +1639,11 @@ async function syncUserNameToPersona() {
15791639 await reloadCurrentChat();
15801640}
15811641
1642+/**
1643+ * Retriggers the first message to reload it from the char definition.
1644+ *
1645+ * Only works if only the first message is present, and not in group mode.
1646+ */
15821647export function retriggerFirstMessageOnEmptyChat() {
15831648 if (this_chid >= 0 && !selected_group && chat.length === 1) {
15841649 $('#firstmessage_textarea').trigger('input');
@@ -1812,6 +1877,10 @@ function registerPersonaSlashCommands() {
18121877 }));
18131878}
18141879
1880+/**
1881+ * Initializes the persona management and all its functionality.
1882+ * This is called during the initialization of the page.
1883+ */
18151884export async function initPersonas() {
18161885 await migrateNonPersonaUser();
18171886 registerPersonaSlashCommands();