+
diff --git a/public/script.js b/public/script.js
index 5f6588688..6a5c8c61c 100644
--- a/public/script.js
+++ b/public/script.js
@@ -833,6 +833,13 @@ async function getCharacters() {
characters[i] = [];
characters[i] = getData[i];
characters[i]['name'] = DOMPurify.sanitize(characters[i]['name']);
+
+ // For dropped-in cards
+ if (!characters[i]['chat']) {
+ characters[i]['chat'] = `${characters[i]['name']} - ${humanizedDateTime()}`;
+ }
+
+ characters[i]['chat'] = String(characters[i]['chat']);
}
if (this_chid != undefined && this_chid != "invalid-safety-id") {
$("#avatar_url_pole").val(characters[this_chid].avatar);
@@ -1062,9 +1069,15 @@ function messageFormatting(mes, ch_name, isSystem, isUser) {
return mes;
}
-function getMessageFromTemplate({ mesId, characterName, isUser, avatarImg, bias, isSystem, title, timerValue, timerTitle } = {}) {
+function getMessageFromTemplate({ mesId, characterName, isUser, avatarImg, bias, isSystem, title, timerValue, timerTitle, bookmarkLink } = {}) {
const mes = $('#message_template .mes').clone();
- mes.attr({ 'mesid': mesId, 'ch_name': characterName, 'is_user': isUser, 'is_system': !!isSystem });
+ mes.attr({
+ 'mesid': mesId,
+ 'ch_name': characterName,
+ 'is_user': isUser,
+ 'is_system': !!isSystem,
+ 'bookmark_link': bookmarkLink,
+ });
mes.find('.avatar img').attr('src', avatarImg);
mes.find('.ch_name .name_text').text(characterName);
mes.find('.mes_bias').html(bias);
@@ -1098,15 +1111,7 @@ function addCopyToCodeBlocks(messageElement) {
codeBlocks.get(i).appendChild(copyButton);
copyButton.addEventListener('pointerup', function (event) {
navigator.clipboard.writeText(codeBlocks.get(i).innerText);
- const copiedMsg = document.createElement("div");
- copiedMsg.classList.add('code-copied');
- copiedMsg.innerText = "Copied!";
- copiedMsg.style.top = `${event.clientY - 55}px`;
- copiedMsg.style.left = `${event.clientX - 55}px`;
- document.body.append(copiedMsg);
- setTimeout(() => {
- document.body.removeChild(copiedMsg);
- }, 1000);
+ toastr.info('Copied!', '', { timeOut: 2000 });
});
}
}
@@ -1158,6 +1163,7 @@ function addOneMessage(mes, { type = "normal", insertAfter = null, scroll = true
mes.is_user,
);
const bias = messageFormatting(mes.extra?.bias ?? "");
+ const bookmarkLink = mes?.extra?.bookmark_link ?? '';
let params = {
mesId: count_view_mes,
@@ -1167,6 +1173,7 @@ function addOneMessage(mes, { type = "normal", insertAfter = null, scroll = true
bias: bias,
isSystem: isSystem,
title: title,
+ bookmarkLink: bookmarkLink,
...formatGenerationTimer(mes.gen_started, mes.gen_finished),
};
@@ -1496,7 +1503,7 @@ class StreamingProcessor {
return;
}
- $(`#chat .mes[mesid="${messageId}"] .mes_stop`).css({ 'display': 'block' });
+ $(`#chat .mes[mesid="${messageId}"] .mes_stop`).css({ 'display': '' });
$(`#chat .mes[mesid="${messageId}"] .mes_buttons`).css({ 'display': 'none' });
}
@@ -1506,7 +1513,7 @@ class StreamingProcessor {
}
$(`#chat .mes[mesid="${messageId}"] .mes_stop`).css({ 'display': 'none' });
- $(`#chat .mes[mesid="${messageId}"] .mes_buttons`).css({ 'display': 'block' });
+ $(`#chat .mes[mesid="${messageId}"] .mes_buttons`).css({ 'display': '' });
}
onStartStreaming(text) {
@@ -3990,7 +3997,7 @@ function messageEditDone(div) {
mesBlock.find(".mes_text").empty();
mesBlock.find(".mes_edit_buttons").css("display", "none");
- mesBlock.find(".mes_buttons").css("display", "inline-block");
+ mesBlock.find(".mes_buttons").css("display", "");
mesBlock.find(".mes_text").append(
messageFormatting(
text,
@@ -6019,15 +6026,7 @@ $(document).ready(function () {
var edit_mes_id = $(this).closest(".mes").attr("mesid");
var text = chat[edit_mes_id]["mes"];
navigator.clipboard.writeText(text);
- const copiedMsg = document.createElement("div");
- copiedMsg.classList.add('code-copied');
- copiedMsg.innerText = "Copied!";
- copiedMsg.style.top = `${event.clientY - 55}px`;
- copiedMsg.style.left = `${event.clientX - 55}px`;
- document.body.append(copiedMsg);
- setTimeout(() => {
- document.body.removeChild(copiedMsg);
- }, 1000);
+ toastr.info('Copied!', '', { timeOut: 2000 });
} catch (err) {
console.error('Failed to copy: ', err);
}
@@ -6140,7 +6139,7 @@ $(document).ready(function () {
$(this).closest(".mes_block").find(".mes_text").empty();
$(this).closest(".mes_edit_buttons").css("display", "none");
- $(this).closest(".mes_block").find(".mes_buttons").css("display", "inline-block");
+ $(this).closest(".mes_block").find(".mes_buttons").css("display", "");
$(this)
.closest(".mes_block")
.find(".mes_text")
@@ -6213,8 +6212,9 @@ $(document).ready(function () {
showSwipeButtons();
});
- $(document).on("click", ".mes_edit_copy", function () {
- if (!confirm('Create a copy of this message?')) {
+ $(document).on("click", ".mes_edit_copy", async function () {
+ const confirmation = await callPopup('Create a copy of this message?', 'confirm');
+ if (!confirmation) {
return;
}
@@ -6234,8 +6234,9 @@ $(document).ready(function () {
});
- $(document).on("click", ".mes_edit_delete", function () {
- if (!confirm("Are you sure you want to delete this message?")) {
+ $(document).on("click", ".mes_edit_delete", async function () {
+ const confirmation = await callPopup("Are you sure you want to delete this message?", 'confirm');
+ if (!confirmation) {
return;
}
@@ -6432,8 +6433,14 @@ $(document).ready(function () {
select_rm_characters();
});
- $(document).on("click", ".select_chat_block, .bookmark_link", async function () {
- let file_name = $(this).attr("file_name").replace(".jsonl", "");
+ $(document).on("click", ".select_chat_block, .bookmark_link, .mes_bookmark", async function () {
+ let file_name = $(this).hasClass('mes_bookmark')
+ ? $(this).closest('.mes').attr('bookmark_link')
+ : $(this).attr("file_name").replace(".jsonl", "");
+
+ if (!file_name) {
+ return;
+ }
if (selected_group) {
await openGroupChat(selected_group, file_name);
@@ -6598,10 +6605,6 @@ $(document).ready(function () {
});
});
- $('#chat').on('scroll', () => {
- $('.code-copied').css({ 'display': 'none' });
- });
-
$(document).on('click', '.mes_img_enlarge', enlargeMessageImage);
$(document).on('click', '.mes_img_delete', deleteMessageImage);
diff --git a/public/scripts/bookmarks.js b/public/scripts/bookmarks.js
index cf39397c6..9496a38bc 100644
--- a/public/scripts/bookmarks.js
+++ b/public/scripts/bookmarks.js
@@ -124,6 +124,26 @@ function showBookmarksButtons() {
}
async function createNewBookmark() {
+ if (!chat.length) {
+ toastr.warning('The chat is empty.', 'Bookmark creation failed');
+ return;
+ }
+
+ const mesId = chat.length - 1;
+ const lastMes = chat[mesId];
+
+ if (typeof lastMes.extra !== 'object') {
+ lastMes.extra = {};
+ }
+
+ if (lastMes.extra.bookmark_link) {
+ const confirm = await callPopup('Bookmark checkpoint for the last message already exists. Would you like to replace it?', 'confirm');
+
+ if (!confirm) {
+ return;
+ }
+ }
+
let name = await getBookmarkName();
if (!name) {
@@ -139,9 +159,11 @@ async function createNewBookmark() {
await saveChat(name, newMetadata);
}
- let mainMessage = stringFormat(system_messages[system_message_types.BOOKMARK_CREATED].mes, name, name);
- sendSystemMessage(system_message_types.BOOKMARK_CREATED, mainMessage);
+ lastMes.extra['bookmark_link'] = name;
+ $(`.mes[mesid="${mesId}"]`).attr('bookmark_link', name);
+
await saveChatConditional();
+ toastr.success('Click the bookmark icon in the last message to open the checkpoint chat.', 'Bookmark created', { timeOut: 10000 });
}
async function backToMainChat() {
diff --git a/public/scripts/context-template.js b/public/scripts/context-template.js
index d7480b1dc..a59c908ab 100644
--- a/public/scripts/context-template.js
+++ b/public/scripts/context-template.js
@@ -11,15 +11,7 @@ function openContextTemplateEditor() {
function copyTemplateParameter(event) {
const text = $(event.target).text();
navigator.clipboard.writeText(text);
- const copiedMsg = document.createElement("div");
- copiedMsg.classList.add('code-copied');
- copiedMsg.innerText = "Copied!";
- copiedMsg.style.top = `${event.clientY - 55}px`;
- copiedMsg.style.left = `${event.clientX - 55}px`;
- document.body.append(copiedMsg);
- setTimeout(() => {
- document.body.removeChild(copiedMsg);
- }, 1000);
+ toastr.info('Copied!', '', { timeOut: 2000 });
}
jQuery(() => {
diff --git a/public/scripts/extensions/tts/index.js b/public/scripts/extensions/tts/index.js
index d7664e4d2..52722712a 100644
--- a/public/scripts/extensions/tts/index.js
+++ b/public/scripts/extensions/tts/index.js
@@ -174,6 +174,7 @@ function debugTtsPlayback() {
"audioQueueProcessorReady": audioQueueProcessorReady,
"ttsJobQueue": ttsJobQueue,
"currentTtsJob": currentTtsJob,
+ "ttsConfig": extension_settings.tts
}
))
}
@@ -372,6 +373,7 @@ async function processTtsQueue() {
try {
if (!text) {
console.warn('Got empty text in TTS queue job.');
+ completeTtsJob()
return;
}
diff --git a/public/style.css b/public/style.css
index 3bacb52bc..cb3c04013 100644
--- a/public/style.css
+++ b/public/style.css
@@ -2297,25 +2297,25 @@ input[type="range"]::-webkit-slider-thumb {
margin-right: 30px;
}
-.mes_prompt,
-.mes_narrate,
-.sd_message_gen,
-.mes_copy,
-.mes_edit {
+.mes_buttons>div {
cursor: pointer;
transition: 0.3s ease-in-out;
filter: drop-shadow(0px 0px 2px black);
opacity: 0.2;
}
-.mes_edit:hover,
-.mes_copy:hover,
-.sd_message_gen:hover,
-.mes_narrate:hover,
-.mes_stop:hover {
+.mes_buttons>div:hover {
opacity: 1;
}
+.mes_bookmark {
+ display: none;
+}
+
+.mes:not([bookmark_link='']) .mes_bookmark {
+ display: inline-block;
+}
+
.mes_edit_buttons {
display: none;
flex-direction: row;
@@ -3611,17 +3611,6 @@ label[for="extensions_autoconnect"] {
opacity: 0.8;
}
-.code-copied {
- position: absolute;
- z-index: 10000;
- font-size: var(--mainFontSize);
- color: var(--SmartThemeBodyColor);
- background-color: var(--SmartThemeFastUIBGColor);
- border-radius: 5px;
- padding: 6px;
- border: 1px solid var(--grey30a);
-}
-
.inline-drawer-icon {
display: block;
cursor: pointer;
diff --git a/server.js b/server.js
index 96522bbc4..2a40f7e60 100644
--- a/server.js
+++ b/server.js
@@ -515,65 +515,51 @@ app.post("/generate_textgenerationwebui", jsonParser, async function (request, r
app.post("/savechat", jsonParser, function (request, response) {
- var dir_name = String(request.body.avatar_url).replace('.png', '');
- let chat_data = request.body.chat;
- let jsonlData = chat_data.map(JSON.stringify).join('\n');
- fs.writeFile(`${chatsPath + dir_name}/${sanitize(request.body.file_name)}.jsonl`, jsonlData, 'utf8', function (err) {
- if (err) {
- response.send(err);
- return console.log(err);
- } else {
- response.send({ result: "ok" });
- }
- });
-
+ try {
+ var dir_name = String(request.body.avatar_url).replace('.png', '');
+ let chat_data = request.body.chat;
+ let jsonlData = chat_data.map(JSON.stringify).join('\n');
+ fs.writeFileSync(`${chatsPath + dir_name}/${sanitize(String(request.body.file_name))}.jsonl`, jsonlData, 'utf8');
+ return response.send({ result: "ok" });
+ } catch (error) {
+ response.send(error);
+ return console.log(error);
+ }
});
+
app.post("/getchat", jsonParser, function (request, response) {
- var dir_name = String(request.body.avatar_url).replace('.png', '');
+ try {
+ const dirName = String(request.body.avatar_url).replace('.png', '');
+ const chatDirExists = fs.existsSync(chatsPath + dirName);
- fs.stat(chatsPath + dir_name, function (err, stat) {
-
- if (stat === undefined) { //if no chat dir for the character is found, make one with the character name
-
- fs.mkdirSync(chatsPath + dir_name);
- response.send({});
- return;
- } else {
-
- if (err === null) { //if there is a dir, then read the requested file from the JSON call
-
- fs.stat(`${chatsPath + dir_name}/${sanitize(request.body.file_name)}.jsonl`, function (err, stat) {
- if (err === null) { //if no error (the file exists), read the file
- if (stat !== undefined) {
- fs.readFile(`${chatsPath + dir_name}/${sanitize(request.body.file_name)}.jsonl`, 'utf8', (err, data) => {
- if (err) {
- console.error(err);
- response.send(err);
- return;
- }
- //console.log(data);
- const lines = data.split('\n');
-
- // Iterate through the array of strings and parse each line as JSON
- const jsonData = lines.map(tryParse).filter(x => x);
- response.send(jsonData);
- //console.log('read the requested file')
-
- });
- }
- } else {
- response.send({});
- //return console.log(err);
- return;
- }
- });
- } else {
- console.error(err);
- response.send({});
- return;
- }
+ //if no chat dir for the character is found, make one with the character name
+ if (!chatDirExists) {
+ fs.mkdirSync(chatsPath + dirName);
+ return response.send({});
}
- });
+
+
+ if (!request.body.file_name) {
+ return response.send({});
+ }
+
+ const fileName = `${chatsPath + dirName}/${sanitize(String(request.body.file_name))}.jsonl`;
+ const chatFileExists = fs.existsSync(fileName);
+
+ if (!chatFileExists) {
+ return response.send({});
+ }
+
+ const data = fs.readFileSync(fileName, 'utf8');
+ const lines = data.split('\n');
+
+ // Iterate through the array of strings and parse each line as JSON
+ const jsonData = lines.map(tryParse).filter(x => x);
+ return response.send(jsonData);
+ } catch (error) {
+ console.error(error);
+ return response.send({});
+ }
});
app.post("/getstatus", jsonParser, async function (request, response_getstatus = response) {