2023-11-26 18:56:19 +01:00
import {
callPopup ,
characters ,
chat _metadata ,
default _avatar ,
eventSource ,
event _types ,
getRequestHeaders ,
getThumbnailUrl ,
getUserAvatars ,
name1 ,
saveMetadata ,
saveSettingsDebounced ,
2024-01-30 18:12:56 +01:00
setUserAvatar ,
2023-11-26 18:56:19 +01:00
setUserName ,
this _chid ,
user _avatar ,
2023-12-02 19:04:51 +01:00
} from '../script.js' ;
import { getContext } from './extensions.js' ;
import { persona _description _positions , power _user } from './power-user.js' ;
import { getTokenCount } from './tokenizers.js' ;
import { debounce , delay , download , parseJsonFile } from './utils.js' ;
2023-08-29 00:54:11 +02:00
2024-01-31 11:13:01 +01:00
const GRID _STORAGE _KEY = 'Personas_GridView' ;
function switchPersonaGridView ( ) {
const state = localStorage . getItem ( GRID _STORAGE _KEY ) === 'true' ;
$ ( '#user_avatar_block' ) . toggleClass ( 'gridView' , state ) ;
}
2023-08-29 00:54:11 +02:00
/ * *
* Uploads an avatar file to the server
* @ param { string } url URL for the avatar file
* @ param { string } [ name ] Optional name for the avatar file
* @ returns { Promise } Promise object representing the AJAX request
* /
async function uploadUserAvatar ( url , name ) {
const fetchResult = await fetch ( url ) ;
const blob = await fetchResult . blob ( ) ;
2023-12-02 19:04:51 +01:00
const file = new File ( [ blob ] , 'avatar.png' , { type : 'image/png' } ) ;
2023-08-29 00:54:11 +02:00
const formData = new FormData ( ) ;
2023-12-02 19:04:51 +01:00
formData . append ( 'avatar' , file ) ;
2023-08-29 00:54:11 +02:00
if ( name ) {
2023-12-02 19:04:51 +01:00
formData . append ( 'overwrite_name' , name ) ;
2023-08-29 00:54:11 +02:00
}
return jQuery . ajax ( {
2023-12-02 19:04:51 +01:00
type : 'POST' ,
url : '/uploaduseravatar' ,
2023-08-29 00:54:11 +02:00
data : formData ,
beforeSend : ( ) => { } ,
cache : false ,
contentType : false ,
processData : false ,
success : async function ( ) {
2024-01-31 10:01:50 +01:00
await getUserAvatars ( true , name ) ;
2023-08-29 00:54:11 +02:00
} ,
} ) ;
}
2023-11-12 14:47:52 +01:00
/ * *
* Prompts the user to create a persona for the uploaded avatar .
* @ param { string } avatarId User avatar id
* @ returns { Promise } Promise that resolves when the persona is set
* /
export async function createPersona ( avatarId ) {
const personaName = await callPopup ( '<h3>Enter a name for this persona:</h3>Cancel if you\'re just uploading an avatar.' , 'input' , '' ) ;
if ( ! personaName ) {
console . debug ( 'User cancelled creating a persona' ) ;
return ;
}
await delay ( 500 ) ;
const personaDescription = await callPopup ( '<h3>Enter a description for this persona:</h3>You can always add or change it later.' , 'input' , '' , { rows : 4 } ) ;
initPersona ( avatarId , personaName , personaDescription ) ;
if ( power _user . persona _show _notifications ) {
toastr . success ( ` You can now pick ${ personaName } as a persona in the Persona Management menu. ` , 'Persona Created' ) ;
}
}
2023-08-29 00:54:11 +02:00
async function createDummyPersona ( ) {
2023-11-11 15:39:54 +01:00
const personaName = await callPopup ( '<h3>Enter a name for this persona:</h3>' , 'input' , '' ) ;
if ( ! personaName ) {
console . debug ( 'User cancelled creating dummy persona' ) ;
return ;
}
// Date + name (only ASCII) to make it unique
const avatarId = ` ${ Date . now ( ) } - ${ personaName . replace ( /[^a-zA-Z0-9]/g , '' ) } .png ` ;
2023-11-12 14:47:52 +01:00
initPersona ( avatarId , personaName , '' ) ;
await uploadUserAvatar ( default _avatar , avatarId ) ;
}
/ * *
* Initializes a persona for the given avatar id .
* @ param { string } avatarId User avatar id
* @ param { string } personaName Name for the persona
* @ param { string } personaDescription Optional description for the persona
* @ returns { void }
* /
export function initPersona ( avatarId , personaName , personaDescription ) {
2023-11-11 15:39:54 +01:00
power _user . personas [ avatarId ] = personaName ;
power _user . persona _descriptions [ avatarId ] = {
2023-11-12 14:47:52 +01:00
description : personaDescription || '' ,
2023-11-11 15:39:54 +01:00
position : persona _description _positions . IN _PROMPT ,
} ;
saveSettingsDebounced ( ) ;
2023-08-29 00:54:11 +02:00
}
2023-10-21 15:12:09 +02:00
export async function convertCharacterToPersona ( characterId = null ) {
if ( null === characterId ) characterId = this _chid ;
const avatarUrl = characters [ characterId ] ? . avatar ;
2023-08-29 00:54:11 +02:00
if ( ! avatarUrl ) {
2023-12-02 19:04:51 +01:00
console . log ( 'No avatar found for this character' ) ;
2023-08-29 00:54:11 +02:00
return ;
}
2023-10-21 15:12:09 +02:00
const name = characters [ characterId ] ? . name ;
let description = characters [ characterId ] ? . description ;
2023-08-29 00:54:11 +02:00
const overwriteName = ` ${ name } (Persona).png ` ;
if ( overwriteName in power _user . personas ) {
2023-12-02 19:04:51 +01:00
const confirmation = await callPopup ( 'This character exists as a persona already. Are you sure want to overwrite it?' , 'confirm' , '' , { okButton : 'Yes' } ) ;
2023-08-29 00:54:11 +02:00
if ( confirmation === false ) {
2023-12-02 19:04:51 +01:00
console . log ( 'User cancelled the overwrite of the persona' ) ;
2023-08-29 00:54:11 +02:00
return ;
}
}
if ( description . includes ( '{{char}}' ) || description . includes ( '{{user}}' ) ) {
await delay ( 500 ) ;
2023-12-02 19:04:51 +01:00
const confirmation = await callPopup ( 'This character has a description that uses {{char}} or {{user}} macros. Do you want to swap them in the persona description?' , 'confirm' , '' , { okButton : 'Yes' } ) ;
2023-08-29 00:54:11 +02:00
if ( confirmation ) {
description = description . replace ( /{{char}}/gi , '{{personaChar}}' ) . replace ( /{{user}}/gi , '{{personaUser}}' ) ;
description = description . replace ( /{{personaUser}}/gi , '{{char}}' ) . replace ( /{{personaChar}}/gi , '{{user}}' ) ;
}
}
const thumbnailAvatar = getThumbnailUrl ( 'avatar' , avatarUrl ) ;
await uploadUserAvatar ( thumbnailAvatar , overwriteName ) ;
power _user . personas [ overwriteName ] = name ;
power _user . persona _descriptions [ overwriteName ] = {
description : description ,
position : persona _description _positions . IN _PROMPT ,
} ;
// If the user is currently using this persona, update the description
if ( user _avatar === overwriteName ) {
power _user . persona _description = description ;
}
saveSettingsDebounced ( ) ;
2023-12-02 19:04:51 +01:00
console . log ( 'Persona for character created' ) ;
2023-08-29 00:54:11 +02:00
toastr . success ( ` You can now select ${ name } as a persona in the Persona Management menu. ` , 'Persona Created' ) ;
// Refresh the persona selector
2024-01-31 10:01:50 +01:00
await getUserAvatars ( true , overwriteName ) ;
2023-08-29 00:54:11 +02:00
// Reload the persona description
setPersonaDescription ( ) ;
}
/ * *
* Counts the number of tokens in a persona description .
* /
const countPersonaDescriptionTokens = debounce ( ( ) => {
2023-12-02 19:04:51 +01:00
const description = String ( $ ( '#persona_description' ) . val ( ) ) ;
2023-08-29 00:54:11 +02:00
const count = getTokenCount ( description ) ;
2023-12-02 19:04:51 +01:00
$ ( '#persona_description_token_count' ) . text ( String ( count ) ) ;
2023-08-29 00:54:11 +02:00
} , 1000 ) ;
export function setPersonaDescription ( ) {
if ( power _user . persona _description _position === persona _description _positions . AFTER _CHAR ) {
power _user . persona _description _position = persona _description _positions . IN _PROMPT ;
}
2023-12-02 19:04:51 +01:00
$ ( '#persona_description' ) . val ( power _user . persona _description ) ;
$ ( '#persona_description_position' )
2023-08-29 00:54:11 +02:00
. val ( power _user . persona _description _position )
. find ( ` option[value=' ${ power _user . persona _description _position } '] ` )
2023-12-02 19:04:51 +01:00
. attr ( 'selected' , String ( true ) ) ;
2023-08-29 00:54:11 +02:00
countPersonaDescriptionTokens ( ) ;
}
export function autoSelectPersona ( name ) {
for ( const [ key , value ] of Object . entries ( power _user . personas ) ) {
if ( value === name ) {
console . log ( ` Auto-selecting persona ${ key } for name ${ name } ` ) ;
2024-01-30 18:12:56 +01:00
setUserAvatar ( key ) ;
2023-08-29 00:54:11 +02:00
return ;
}
}
}
2023-12-21 13:56:32 +01:00
/ * *
* Updates the name of a persona if it exists .
* @ param { string } avatarId User avatar id
* @ param { string } newName New name for the persona
* /
export async function updatePersonaNameIfExists ( avatarId , newName ) {
if ( avatarId in power _user . personas ) {
power _user . personas [ avatarId ] = newName ;
2024-01-31 10:01:50 +01:00
await getUserAvatars ( true , avatarId ) ;
2023-12-21 13:56:32 +01:00
saveSettingsDebounced ( ) ;
console . log ( ` Updated persona name for ${ avatarId } to ${ newName } ` ) ;
} else {
console . log ( ` Persona name ${ avatarId } was not updated because it does not exist ` ) ;
}
}
2024-01-30 19:16:48 +01:00
async function bindUserNameToPersona ( e ) {
e ? . stopPropagation ( ) ;
2023-08-29 00:54:11 +02:00
const avatarId = $ ( this ) . closest ( '.avatar-container' ) . find ( '.avatar' ) . attr ( 'imgfile' ) ;
if ( ! avatarId ) {
console . warn ( 'No avatar id found' ) ;
return ;
}
const existingPersona = power _user . personas [ avatarId ] ;
const personaName = await callPopup ( '<h3>Enter a name for this persona:</h3>(If empty name is provided, this will unbind the name from this avatar)' , 'input' , existingPersona || '' ) ;
// If the user clicked cancel, don't do anything
if ( personaName === false ) {
return ;
}
if ( personaName . length > 0 ) {
// If the user clicked ok and entered a name, bind the name to the persona
console . log ( ` Binding persona ${ avatarId } to name ${ personaName } ` ) ;
power _user . personas [ avatarId ] = personaName ;
const descriptor = power _user . persona _descriptions [ avatarId ] ;
const isCurrentPersona = avatarId === user _avatar ;
// Create a description object if it doesn't exist
if ( ! descriptor ) {
// If the user is currently using this persona, set the description to the current description
power _user . persona _descriptions [ avatarId ] = {
description : isCurrentPersona ? power _user . persona _description : '' ,
position : isCurrentPersona ? power _user . persona _description _position : persona _description _positions . IN _PROMPT ,
} ;
}
// If the user is currently using this persona, update the name
if ( isCurrentPersona ) {
console . log ( ` Auto-updating user name to ${ personaName } ` ) ;
setUserName ( personaName ) ;
}
} else {
// If the user clicked ok, but didn't enter a name, delete the persona
console . log ( ` Unbinding persona ${ avatarId } ` ) ;
delete power _user . personas [ avatarId ] ;
delete power _user . persona _descriptions [ avatarId ] ;
}
saveSettingsDebounced ( ) ;
2024-01-31 10:01:50 +01:00
await getUserAvatars ( true , avatarId ) ;
2023-08-29 00:54:11 +02:00
setPersonaDescription ( ) ;
}
export function selectCurrentPersona ( ) {
const personaName = power _user . personas [ user _avatar ] ;
2023-10-23 22:20:49 +02:00
if ( personaName ) {
2023-08-29 00:54:11 +02:00
const lockedPersona = chat _metadata [ 'persona' ] ;
if ( lockedPersona && lockedPersona !== user _avatar && power _user . persona _show _notifications ) {
toastr . info (
` To permanently set " ${ personaName } " as the selected persona, unlock and relock it using the "Lock" button. Otherwise, the selection resets upon reloading the chat. ` ,
` This chat is locked to a different persona ( ${ power _user . personas [ lockedPersona ] } ). ` ,
2023-12-02 21:06:57 +01:00
{ timeOut : 10000 , extendedTimeOut : 20000 , preventDuplicates : true } ,
2023-08-29 00:54:11 +02:00
) ;
}
2023-10-23 22:20:49 +02:00
if ( personaName !== name1 ) {
console . log ( ` Auto-updating user name to ${ personaName } ` ) ;
setUserName ( personaName ) ;
}
2023-08-29 00:54:11 +02:00
const descriptor = power _user . persona _descriptions [ user _avatar ] ;
if ( descriptor ) {
power _user . persona _description = descriptor . description ;
power _user . persona _description _position = descriptor . position ;
} else {
power _user . persona _description = '' ;
power _user . persona _description _position = persona _description _positions . IN _PROMPT ;
power _user . persona _descriptions [ user _avatar ] = { description : '' , position : persona _description _positions . IN _PROMPT } ;
}
setPersonaDescription ( ) ;
2023-11-26 18:56:19 +01:00
// force firstMes {{user}} update on persona switch
const context = getContext ( ) ;
if ( context . characterId >= 0 && ! context . groupId && context . chat . length === 1 ) {
2023-12-02 20:11:06 +01:00
$ ( '#firstmessage_textarea' ) . trigger ( 'input' ) ;
2023-11-26 18:56:19 +01:00
}
2023-08-29 00:54:11 +02:00
}
}
async function lockUserNameToChat ( ) {
if ( chat _metadata [ 'persona' ] ) {
console . log ( ` Unlocking persona for this chat ${ chat _metadata [ 'persona' ] } ` ) ;
delete chat _metadata [ 'persona' ] ;
await saveMetadata ( ) ;
if ( power _user . persona _show _notifications ) {
toastr . info ( 'User persona is now unlocked for this chat. Click the "Lock" again to revert.' , 'Persona unlocked' ) ;
}
updateUserLockIcon ( ) ;
return ;
}
if ( ! ( user _avatar in power _user . personas ) ) {
console . log ( ` Creating a new persona ${ user _avatar } ` ) ;
if ( power _user . persona _show _notifications ) {
toastr . info (
'Creating a new persona for currently selected user name and avatar...' ,
'Persona not set for this avatar' ,
2023-12-02 21:06:57 +01:00
{ timeOut : 10000 , extendedTimeOut : 20000 } ,
2023-08-29 00:54:11 +02:00
) ;
}
power _user . personas [ user _avatar ] = name1 ;
power _user . persona _descriptions [ user _avatar ] = { description : '' , position : persona _description _positions . IN _PROMPT } ;
}
chat _metadata [ 'persona' ] = user _avatar ;
await saveMetadata ( ) ;
saveSettingsDebounced ( ) ;
console . log ( ` Locking persona for this chat ${ user _avatar } ` ) ;
if ( power _user . persona _show _notifications ) {
toastr . success ( ` User persona is locked to ${ name1 } in this chat ` ) ;
}
updateUserLockIcon ( ) ;
}
2024-01-30 19:16:48 +01:00
async function deleteUserAvatar ( e ) {
e ? . stopPropagation ( ) ;
2023-08-29 00:54:11 +02:00
const avatarId = $ ( this ) . closest ( '.avatar-container' ) . find ( '.avatar' ) . attr ( 'imgfile' ) ;
if ( ! avatarId ) {
console . warn ( 'No avatar id found' ) ;
return ;
}
if ( avatarId == user _avatar ) {
console . warn ( ` User tried to delete their current avatar ${ avatarId } ` ) ;
toastr . warning ( 'You cannot delete the avatar you are currently using' , 'Warning' ) ;
return ;
}
const confirm = await callPopup ( '<h3>Are you sure you want to delete this avatar?</h3>All information associated with its linked persona will be lost.' , 'confirm' ) ;
if ( ! confirm ) {
console . debug ( 'User cancelled deleting avatar' ) ;
return ;
}
2023-12-02 19:04:51 +01:00
const request = await fetch ( '/deleteuseravatar' , {
method : 'POST' ,
2023-08-29 00:54:11 +02:00
headers : getRequestHeaders ( ) ,
body : JSON . stringify ( {
2023-12-02 19:04:51 +01:00
'avatar' : avatarId ,
2023-08-29 00:54:11 +02:00
} ) ,
} ) ;
if ( request . ok ) {
console . log ( ` Deleted avatar ${ avatarId } ` ) ;
delete power _user . personas [ avatarId ] ;
delete power _user . persona _descriptions [ avatarId ] ;
if ( avatarId === power _user . default _persona ) {
toastr . warning ( 'The default persona was deleted. You will need to set a new default persona.' , 'Default persona deleted' ) ;
power _user . default _persona = null ;
}
if ( avatarId === chat _metadata [ 'persona' ] ) {
toastr . warning ( 'The locked persona was deleted. You will need to set a new persona for this chat.' , 'Persona deleted' ) ;
delete chat _metadata [ 'persona' ] ;
await saveMetadata ( ) ;
}
saveSettingsDebounced ( ) ;
await getUserAvatars ( ) ;
updateUserLockIcon ( ) ;
}
}
function onPersonaDescriptionInput ( ) {
2023-12-02 19:04:51 +01:00
power _user . persona _description = String ( $ ( '#persona_description' ) . val ( ) ) ;
2023-08-29 00:54:11 +02:00
countPersonaDescriptionTokens ( ) ;
if ( power _user . personas [ user _avatar ] ) {
let object = power _user . persona _descriptions [ user _avatar ] ;
if ( ! object ) {
object = {
description : power _user . persona _description ,
2023-12-02 19:04:51 +01:00
position : Number ( $ ( '#persona_description_position' ) . find ( ':selected' ) . val ( ) ) ,
2023-08-29 00:54:11 +02:00
} ;
power _user . persona _descriptions [ user _avatar ] = object ;
}
object . description = power _user . persona _description ;
}
2024-01-30 18:12:56 +01:00
$ ( ` .avatar-container[imgfile=" ${ user _avatar } "] .ch_description ` )
. text ( power _user . persona _description || '[No description]' )
. toggleClass ( 'text_muted' , ! power _user . persona _description ) ;
2023-08-29 00:54:11 +02:00
saveSettingsDebounced ( ) ;
}
function onPersonaDescriptionPositionInput ( ) {
power _user . persona _description _position = Number (
2023-12-02 21:06:57 +01:00
$ ( '#persona_description_position' ) . find ( ':selected' ) . val ( ) ,
2023-08-29 00:54:11 +02:00
) ;
if ( power _user . personas [ user _avatar ] ) {
let object = power _user . persona _descriptions [ user _avatar ] ;
if ( ! object ) {
object = {
description : power _user . persona _description ,
position : power _user . persona _description _position ,
} ;
power _user . persona _descriptions [ user _avatar ] = object ;
}
object . position = power _user . persona _description _position ;
}
saveSettingsDebounced ( ) ;
}
2024-01-30 19:16:48 +01:00
async function setDefaultPersona ( e ) {
e ? . stopPropagation ( ) ;
2023-08-29 00:54:11 +02:00
const avatarId = $ ( this ) . closest ( '.avatar-container' ) . find ( '.avatar' ) . attr ( 'imgfile' ) ;
if ( ! avatarId ) {
console . warn ( 'No avatar id found' ) ;
return ;
}
const currentDefault = power _user . default _persona ;
if ( power _user . personas [ avatarId ] === undefined ) {
console . warn ( ` No persona name found for avatar ${ avatarId } ` ) ;
toastr . warning ( 'You must bind a name to this persona before you can set it as the default.' , 'Persona name not set' ) ;
return ;
}
const personaName = power _user . personas [ avatarId ] ;
if ( avatarId === currentDefault ) {
const confirm = await callPopup ( 'Are you sure you want to remove the default persona?' , 'confirm' ) ;
if ( ! confirm ) {
console . debug ( 'User cancelled removing default persona' ) ;
return ;
}
console . log ( ` Removing default persona ${ avatarId } ` ) ;
if ( power _user . persona _show _notifications ) {
2023-12-02 19:04:51 +01:00
toastr . info ( 'This persona will no longer be used by default when you open a new chat.' , 'Default persona removed' ) ;
2023-08-29 00:54:11 +02:00
}
delete power _user . default _persona ;
} else {
const confirm = await callPopup ( ` <h3>Are you sure you want to set " ${ personaName } " as the default persona?</h3>
This name and avatar will be used for all new chats , as well as existing chats where the user persona is not locked . ` , 'confirm');
if ( ! confirm ) {
console . debug ( 'User cancelled setting default persona' ) ;
return ;
}
power _user . default _persona = avatarId ;
if ( power _user . persona _show _notifications ) {
toastr . success ( 'This persona will be used by default when you open a new chat.' , ` Default persona set to ${ personaName } ` ) ;
}
}
saveSettingsDebounced ( ) ;
2024-01-31 10:01:50 +01:00
await getUserAvatars ( true , avatarId ) ;
2023-08-29 00:54:11 +02:00
}
function updateUserLockIcon ( ) {
const hasLock = ! ! chat _metadata [ 'persona' ] ;
$ ( '#lock_user_name' ) . toggleClass ( 'fa-unlock' , ! hasLock ) ;
$ ( '#lock_user_name' ) . toggleClass ( 'fa-lock' , hasLock ) ;
}
2024-01-30 18:12:56 +01:00
async function setChatLockedPersona ( ) {
2023-08-29 00:54:11 +02:00
// Define a persona for this chat
let chatPersona = '' ;
if ( chat _metadata [ 'persona' ] ) {
// If persona is locked in chat metadata, select it
console . log ( ` Using locked persona ${ chat _metadata [ 'persona' ] } ` ) ;
chatPersona = chat _metadata [ 'persona' ] ;
} else if ( power _user . default _persona ) {
// If default persona is set, select it
console . log ( ` Using default persona ${ power _user . default _persona } ` ) ;
chatPersona = power _user . default _persona ;
}
// No persona set: user current settings
if ( ! chatPersona ) {
console . debug ( 'No default or locked persona set for this chat' ) ;
return ;
}
// Find the avatar file
2024-01-30 18:12:56 +01:00
const userAvatars = await getUserAvatars ( false ) ;
2023-08-29 00:54:11 +02:00
// Avatar missing (persona deleted)
2024-01-30 18:12:56 +01:00
if ( chat _metadata [ 'persona' ] && ! userAvatars . includes ( chatPersona ) ) {
2023-08-29 00:54:11 +02:00
console . warn ( 'Persona avatar not found, unlocking persona' ) ;
delete chat _metadata [ 'persona' ] ;
updateUserLockIcon ( ) ;
return ;
}
// Default persona missing
2024-01-30 18:12:56 +01:00
if ( power _user . default _persona && ! userAvatars . includes ( power _user . default _persona ) ) {
2023-08-29 00:54:11 +02:00
console . warn ( 'Default persona avatar not found, clearing default persona' ) ;
power _user . default _persona = null ;
saveSettingsDebounced ( ) ;
return ;
}
// Persona avatar found, select it
2024-01-30 18:12:56 +01:00
setUserAvatar ( chatPersona ) ;
2023-08-29 00:54:11 +02:00
updateUserLockIcon ( ) ;
}
2023-11-15 01:09:40 +01:00
function onBackupPersonas ( ) {
const timestamp = new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] . replace ( /-/g , '' ) ;
const filename = ` personas_ ${ timestamp } .json ` ;
const data = JSON . stringify ( {
2023-12-02 19:04:51 +01:00
'personas' : power _user . personas ,
'persona_descriptions' : power _user . persona _descriptions ,
'default_persona' : power _user . default _persona ,
2023-11-15 01:09:40 +01:00
} , null , 2 ) ;
const blob = new Blob ( [ data ] , { type : 'application/json' } ) ;
download ( blob , filename , 'application/json' ) ;
}
async function onPersonasRestoreInput ( e ) {
const file = e . target . files [ 0 ] ;
if ( ! file ) {
console . debug ( 'No file selected' ) ;
return ;
}
const data = await parseJsonFile ( file ) ;
if ( ! data ) {
toastr . warning ( 'Invalid file selected' , 'Persona Management' ) ;
console . debug ( 'Invalid file selected' ) ;
return ;
}
if ( ! data . personas || ! data . persona _descriptions || typeof data . personas !== 'object' || typeof data . persona _descriptions !== 'object' ) {
toastr . warning ( 'Invalid file format' , 'Persona Management' ) ;
console . debug ( 'Invalid file selected' ) ;
return ;
}
2024-01-30 18:12:56 +01:00
const avatarsList = await getUserAvatars ( false ) ;
2023-11-15 01:09:40 +01:00
const warnings = [ ] ;
// Merge personas with existing ones
for ( const [ key , value ] of Object . entries ( data . personas ) ) {
if ( key in power _user . personas ) {
warnings . push ( ` Persona " ${ key } " ( ${ value } ) already exists, skipping ` ) ;
continue ;
}
power _user . personas [ key ] = value ;
// If the avatar is missing, upload it
if ( ! avatarsList . includes ( key ) ) {
warnings . push ( ` Persona image " ${ key } " ( ${ value } ) is missing, uploading default avatar ` ) ;
await uploadUserAvatar ( default _avatar , key ) ;
}
}
// Merge persona descriptions with existing ones
for ( const [ key , value ] of Object . entries ( data . persona _descriptions ) ) {
if ( key in power _user . persona _descriptions ) {
warnings . push ( ` Persona description for " ${ key } " ( ${ power _user . personas [ key ] } ) already exists, skipping ` ) ;
continue ;
}
if ( ! power _user . personas [ key ] ) {
warnings . push ( ` Persona for " ${ key } " does not exist, skipping ` ) ;
continue ;
}
power _user . persona _descriptions [ key ] = value ;
}
if ( data . default _persona ) {
if ( data . default _persona in power _user . personas ) {
power _user . default _persona = data . default _persona ;
} else {
warnings . push ( ` Default persona " ${ data . default _persona } " does not exist, skipping ` ) ;
}
}
if ( warnings . length ) {
toastr . success ( 'Personas restored with warnings. Check console for details.' ) ;
console . warn ( ` PERSONA RESTORE REPORT \n ==================== \n ${ warnings . join ( '\n' ) } ` ) ;
} else {
toastr . success ( 'Personas restored successfully.' ) ;
}
await getUserAvatars ( ) ;
setPersonaDescription ( ) ;
saveSettingsDebounced ( ) ;
$ ( '#personas_restore_input' ) . val ( '' ) ;
}
2023-08-29 00:54:11 +02:00
export function initPersonas ( ) {
$ ( document ) . on ( 'click' , '.bind_user_name' , bindUserNameToPersona ) ;
$ ( document ) . on ( 'click' , '.set_default_persona' , setDefaultPersona ) ;
$ ( document ) . on ( 'click' , '.delete_avatar' , deleteUserAvatar ) ;
$ ( '#lock_user_name' ) . on ( 'click' , lockUserNameToChat ) ;
2023-12-02 19:04:51 +01:00
$ ( '#create_dummy_persona' ) . on ( 'click' , createDummyPersona ) ;
2023-08-29 00:54:11 +02:00
$ ( '#persona_description' ) . on ( 'input' , onPersonaDescriptionInput ) ;
$ ( '#persona_description_position' ) . on ( 'input' , onPersonaDescriptionPositionInput ) ;
2023-11-15 01:09:40 +01:00
$ ( '#personas_backup' ) . on ( 'click' , onBackupPersonas ) ;
$ ( '#personas_restore' ) . on ( 'click' , ( ) => $ ( '#personas_restore_input' ) . trigger ( 'click' ) ) ;
$ ( '#personas_restore_input' ) . on ( 'change' , onPersonasRestoreInput ) ;
2024-02-02 03:07:51 +01:00
$ ( '#persona_sort_order' ) . val ( power _user . persona _sort _order ) . on ( 'input' , function ( ) {
power _user . persona _sort _order = String ( $ ( this ) . val ( ) ) ;
getUserAvatars ( true , user _avatar ) ;
saveSettingsDebounced ( ) ;
} ) ;
2024-01-31 11:13:01 +01:00
$ ( '#persona_grid_toggle' ) . on ( 'click' , ( ) => {
const state = localStorage . getItem ( GRID _STORAGE _KEY ) === 'true' ;
localStorage . setItem ( GRID _STORAGE _KEY , String ( ! state ) ) ;
switchPersonaGridView ( ) ;
} ) ;
2023-08-29 00:54:11 +02:00
2023-12-02 19:04:51 +01:00
eventSource . on ( 'charManagementDropdown' , ( target ) => {
2023-08-29 00:54:11 +02:00
if ( target === 'convert_to_persona' ) {
convertCharacterToPersona ( ) ;
}
} ) ;
eventSource . on ( event _types . CHAT _CHANGED , setChatLockedPersona ) ;
2024-01-31 11:13:01 +01:00
switchPersonaGridView ( ) ;
2023-08-29 00:54:11 +02:00
}