| 8841 | 8844 | /** |
| 8842 | 8845 | * Deletes a character completely, including associated chats if specified |
| 8843 | 8846 | * |
| 8844 | 8847 | * @param {string|string[]} characterKey - The key (avatar) of the character to be deleted |
| 8845 | 8848 | * @param {Object} [options] - Optional parameters for the deletion |
| 8846 | 8849 | * @param {boolean} [options.deleteChats=true] - Whether to delete associated chats or not |
| 8847 | 8850 | * @return {Promise<void>} - A promise that resolves when the character is successfully deleted |
| 8848 | 8851 | */ |
| 8849 | 8852 | export async function deleteCharacter(characterKey, { deleteChats = true } = {}) { |
| 8850 | | - const character = characters.find(x => x.avatar == characterKey); |
| 8853 | + if (!Array.isArray(characterKey)) { |
| 8851 | | - if (!character) { |
| 8854 | + characterKey = [characterKey]; |
| 8852 | | - toastr.warning(`Character ${characterKey} not found. Cannot be deleted.`); |
| 8853 | | - return; |
| 8854 | 8855 | } |
| 8855 | 8856 | |
| 8856 | | - const chid = characters.indexOf(character); |
| 8857 | + for (const key of characterKey) { |
| 8857 | | - const pastChats = await getPastCharacterChats(chid); |
| 8858 | + const character = characters.find(x => x.avatar == key); |
| 8859 | + if (!character) { |
| 8860 | + toastr.warning(`Character ${key} not found. Skipping deletion.`); |
| 8861 | + continue; |
| 8862 | + } |
| 8858 | 8863 | |
| 8859 | | - const msg = { avatar_url: character.avatar, delete_chats: deleteChats }; |
| 8864 | + const chid = characters.indexOf(character); |
| 8865 | + const pastChats = await getPastCharacterChats(chid); |
| 8860 | 8866 | |
| 8861 | | - const response = await fetch('/api/characters/delete', { |
| 8867 | + const msg = { avatar_url: character.avatar, delete_chats: deleteChats }; |
| 8862 | | - method: 'POST', |
| 8863 | | - headers: getRequestHeaders(), |
| 8864 | | - body: JSON.stringify(msg), |
| 8865 | | - cache: 'no-cache', |
| 8866 | | - }); |
| 8867 | 8868 | |
| 8868 | | - if (!response.ok) { |
| 8869 | + const response = await fetch('/api/characters/delete', { |
| 8869 | | - throw new Error(`Failed to delete character: ${response.status} ${response.statusText}`); |
| 8870 | + method: 'POST', |
| 8870 | | - } |
| 8871 | + headers: getRequestHeaders(), |
| 8872 | + body: JSON.stringify(msg), |
| 8873 | + cache: 'no-cache', |
| 8874 | + }); |
| 8875 | + |
| 8876 | + if (!response.ok) { |
| 8877 | + toastr.error(`${response.status} ${response.statusText}`, 'Failed to delete character'); |
| 8878 | + continue; |
| 8879 | + } |
| 8871 | 8880 | |
| 8872 | | - await removeCharacterFromUI(character.name, character.avatar); |
| 8881 | + delete tag_map[character.avatar]; |
| 8882 | + select_rm_info('char_delete', character.name); |
| 8873 | 8883 | |
| 8874 | 8884 | if (deleteChats) { |
| 8875 | 8885 | for (const chat of pastChats) { |
| 8876 | 8886 | const name = chat.file_name.replace('.jsonl', ''); |
| 8877 | 8887 | await eventSource.emit(event_types.CHAT_DELETED, name); |
| 8888 | + } |
| 8878 | 8889 | } |
| 8890 | + |
| 8891 | + await eventSource.emit(event_types.CHARACTER_DELETED, { id: chid, character: character }); |
| 8879 | 8892 | } |
| 8880 | 8893 | |
| 8881 | | - eventSource.emit(event_types.CHARACTER_DELETED, { id: this_chid, character: characters[this_chid] }); |
| 8894 | + await removeCharacterFromUI(); |
| 8882 | 8895 | } |
| 8883 | 8896 | |
| 8884 | 8897 | /** |
| 8885 | 8898 | * Function to delete a character from UI after character deletion API success. |
| 8886 | 8899 | * It manages necessary UI changes such as closing advanced editing popup, unsetting |
| 8887 | 8900 | * character ID, resetting characters array and chat metadata, deselecting character's tab |
| 8888 | 8901 | * panel, removing character name from navigation tabs, clearing chat, removingfetching character'supdated list of characters. |
| 8889 | | - * avatar from tag_map, fetching updated list of characters and updating the 'deleted |
| 8890 | | - * character' message. |
| 8891 | 8902 | * It also ensures to save the settings after all the operations. |
| 8892 | | - * |
| 8893 | | - * @param {string} name - The name of the character to be deleted. |
| 8894 | | - * @param {string} avatar - The avatar URL of the character to be deleted. |
| 8895 | | - * @param {boolean} reloadCharacters - Whether the character list should be refreshed after deletion. |
| 8896 | 8903 | */ |
| 8897 | 8904 | async function removeCharacterFromUI(name, avatar, reloadCharacters = true) { |
| 8898 | 8905 | await clearChat(); |
| 8899 | 8906 | $('#character_cross').click(); |
| 8900 | 8907 | this_chid = undefined; |
| 8901 | 8908 | characters.length = 0; |
| 8902 | 8909 | name2 = systemUserName; |
| 8903 | 8910 | chat.splice(0, =chat.length, [...safetychat]SAFETY_CHAT); |
| 8904 | 8911 | chat_metadata = {}; |
| 8905 | 8912 | $(document.getElementById('rm_button_selected_ch')).children('h2').text(''); |
| 8906 | 8913 | this_chid = undefined; |
| 8907 | | - delete tag_map[avatar]; |
| 8914 | + await getCharacters(); |
| 8908 | | - if (reloadCharacters) await getCharacters(); |
| 8909 | | - select_rm_info('char_delete', name); |
| 8910 | 8915 | await printMessages(); |
| 8911 | 8916 | saveSettingsDebounced(); |
| 8912 | 8917 | } |