import { humanizedDateTime } from "./scripts/RossAscends-mods.js";
import { encode } from "../scripts/gpt-2-3-tokenizer/mod.js";
import {
kai_settings,
loadKoboldSettings,
} from "./scripts/kai-settings.js";
import {
textgenerationwebui_settings,
loadTextGenSettings,
} from "./scripts/textgen-settings.js";
import {
world_info_budget,
world_info_data,
world_info_depth,
world_info,
getWorldInfoPrompt,
selectImportedWorldInfo,
setWorldInfoSettings,
deleteWorldInfo,
} from "./scripts/world-info.js";
import {
groups,
selected_group,
saveGroupChat,
getGroups,
generateGroupWrapper,
deleteGroup,
is_group_generating,
printGroups,
resetSelectedGroup,
select_group_chats,
regenerateGroup,
} from "./scripts/group-chats.js";
import {
force_pygmalion_formatting,
collapse_newlines,
pin_examples,
collapseNewlines,
disable_description_formatting,
disable_personality_formatting,
disable_scenario_formatting,
always_force_name2,
custom_chat_separator,
} from "./scripts/power-user.js";
import {
setOpenAIMessageExamples,
setOpenAIMessages,
prepareOpenAIMessages,
sendOpenAIRequest,
loadOpenAISettings,
setOpenAIOnlineStatus,
generateOpenAIPromptCache,
oai_settings,
is_get_status_openai,
openai_msgs,
} from "./scripts/openai.js";
import {
getNovelTier,
loadNovelPreset,
loadNovelSettings,
nai_settings,
} from "./scripts/nai-settings.js";
import { showBookmarksButtons } from "./scripts/bookmarks.js";
import { debounce, delay } from "./scripts/utils.js";
//exporting functions and vars for mods
export {
Generate,
getSettings,
saveSettings,
saveSettingsDebounced,
printMessages,
clearChat,
getChat,
getCharacters,
callPopup,
substituteParams,
sendSystemMessage,
addOneMessage,
deleteLastMessage,
resetChatState,
select_rm_info,
setCharacterId,
setCharacterName,
setOnlineStatus,
checkOnlineStatus,
setEditedMessageId,
setSendButtonState,
selectRightMenuWithAnimation,
setRightTabSelectedClass,
openCharacterChat,
saveChat,
messageFormating,
chat,
this_chid,
settings,
characters,
online_status,
main_api,
api_server,
system_messages,
nai_settings,
token,
name1,
name2,
is_send_press,
api_server_textgenerationwebui,
count_view_mes,
default_avatar,
system_message_types,
talkativeness_default,
default_ch_mes,
}
// API OBJECT FOR EXTERNAL WIRING
window["TavernAI"] = {};
const VERSION = "1.1.1";
let converter = new showdown.Converter({ emoji: "true" });
/* let bg_menu_toggle = false; */
const systemUserName = "TavernAI";
let default_user_name = "You";
let name1 = default_user_name;
let name2 = "TavernAI";
let chat = [];
let safetychat = [
{
name: systemUserName,
is_user: false,
is_name: true,
create_date: 0,
mes: "\n*You deleted a character/chat and arrived back here for safety reasons! Pick another character!*\n\n",
},
];
let chat_create_date = 0;
let prev_selected_char = null;
const default_ch_mes = "Hello";
let count_view_mes = 0;
let mesStr = "";
let generatedPromtCache = "";
let characters = [];
let this_chid;
let active_character;
let backgrounds = [];
const default_avatar = "img/ai4.png";
const system_avatar = "img/five.png";
let is_colab = false;
let is_checked_colab = false;
let is_mes_reload_avatar = false;
let optionsPopper = Popper.createPopper(document.getElementById('options_button'), document.getElementById('options'), {
modifiers: [
{
name: 'offset',
options: {
offset: [-20, -260],
},
},
],
});
const durationSaveEdit = 200;
const saveSettingsDebounced = debounce(() => saveSettings(), durationSaveEdit);
const saveCharacterDebounced = debounce(() => $("#create_button").click(), durationSaveEdit);
const system_message_types = {
HELP: "help",
WELCOME: "welcome",
GROUP: "group",
EMPTY: "empty",
GENERIC: "generic",
BOOKMARK_CREATED: "bookmark_created",
BOOKMARK_BACK: "bookmark_back",
};
const system_messages = {
help: {
name: systemUserName,
force_avatar: system_avatar,
is_user: false,
is_system: true,
is_name: true,
mes: [
'Hi there! The following chat formatting commands are supported:',
'
',
'
*text* – format the actions that your character does
',
'
{*text*} – set the behavioral bias for your character
',
'',
'Need more help? Visit our wiki – TavernAI Wiki!'
].join('')
},
welcome:
{
name: systemUserName,
force_avatar: system_avatar,
is_user: false,
is_name: true,
mes: [
'Welcome to TavernAI! In order to begin chatting:',
'
',
'
Connect to one of the supported generation APIs
',
'
Create or pick a character from the list
',
'
',
'Still have questions left?\n',
'Check out built-in help by typing /? in any chat or visit our ',
'TavernAI Wiki!'
].join('')
},
group: {
name: systemUserName,
force_avatar: system_avatar,
is_user: false,
is_system: true,
is_name: true,
is_group: true,
mes: "Group chat created. Say 'Hi' to lovely people!",
},
empty: {
name: systemUserName,
force_avatar: system_avatar,
is_user: false,
is_system: true,
is_name: true,
mes: "No one hears you. **Hint:** add more members to the group!",
},
generic: {
name: systemUserName,
force_avatar: system_avatar,
is_user: false,
is_system: true,
is_name: true,
mes: "Generic system message. User `text` parameter to override the contents",
},
bookmark_created: {
name: systemUserName,
force_avatar: system_avatar,
is_user: false,
is_system: true,
is_name: true,
mes: `Bookmark created! Click here to open the bookmark chat: {1}`,
},
bookmark_back: {
name: systemUserName,
force_avatar: system_avatar,
is_user: false,
is_system: true,
is_name: true,
mes: `Click here to return to the previous chat: Return`,
},
};
const talkativeness_default = 0.5;
var is_advanced_char_open = false;
var menu_type = ""; //what is selected in the menu
var selected_button = ""; //which button pressed
//create pole save
var create_save_name = "";
var create_save_description = "";
var create_save_personality = "";
var create_save_first_message = "";
var create_save_avatar = "";
var create_save_scenario = "";
var create_save_mes_example = "";
var create_save_talkativeness = talkativeness_default;
//animation right menu
var animation_rm_duration = 500;
var animation_rm_easing = "";
var popup_type = "";
var bg_file_for_del = "";
var chat_file_for_del = "";
var online_status = "no_connection";
var api_server = "";
var api_server_textgenerationwebui = "";
//var interval_timer = setInterval(getStatus, 2000);
var interval_timer_novel = setInterval(getStatusNovel, 3000);
var is_get_status = false;
var is_get_status_novel = false;
var is_api_button_press = false;
var is_api_button_press_novel = false;
var is_send_press = false; //Send generation
var add_mes_without_animation = false;
var this_del_mes = 0;
//message editing and chat scroll posistion persistence
var this_edit_mes_text = "";
var this_edit_mes_chname = "";
var this_edit_mes_id;
var scroll_holder = 0;
var is_use_scroll_holder = false;
//settings
var settings;
var koboldai_settings;
var koboldai_setting_names;
var preset_settings = "gui";
var user_avatar = "you.png";
var amount_gen = 80; //default max length of AI generated responses
var max_context = 2048;
var is_pygmalion = false;
var tokens_already_generated = 0;
var message_already_generated = "";
var if_typing_text = false;
const tokens_cycle_count = 30;
var cycle_count_generation = 0;
var swipes = false;
let anchor_order = 0;
let style_anchor = true;
let character_anchor = true;
let extension_prompts = {};
var main_api;// = "kobold";
//novel settings
let novel_tier;
let novelai_settings;
let novelai_setting_names;
//css
var bg1_toggle = true; // inits the BG as BG1
var css_mes_bg = $('').css("background");
var css_send_form_display = $("").css("display");
var colab_ini_step = 1;
let token;
//////////// Is this needed?
setInterval(function () {
switch (colab_ini_step) {
case 0:
$("#colab_popup_text").html("
Initialization
");
colab_ini_step = 1;
break;
case 1:
$("#colab_popup_text").html("
Initialization.
");
colab_ini_step = 2;
break;
case 2:
$("#colab_popup_text").html("
Initialization..
");
colab_ini_step = 3;
break;
case 3:
$("#colab_popup_text").html("
Initialization...
");
colab_ini_step = 0;
break;
}
}, 500);
/////////////
$.ajaxPrefilter((options, originalOptions, xhr) => {
xhr.setRequestHeader("X-CSRF-Token", token);
});
///// initialization protocol ////////
$.get("/csrf-token").then((data) => {
token = data.token;
getCharacters();
getSettings("def");
getLastVersion();
sendSystemMessage(system_message_types.WELCOME);
getBackgrounds();
getUserAvatars();
});
///////////// UNUSED FUNCTIONS MOVED TO TOP ///////////////
function newMesPattern(name) {
//Patern which denotes a new message
name = name + ":";
return name;
}
//////////////////////////////////////////
function checkOnlineStatus() {
///////// REMOVED LINES THAT DUPLICATE RA_CHeckOnlineStatus FEATURES
if (online_status == "no_connection") {
$("#online_status_indicator2").css("background-color", "red"); //Kobold
$("#online_status_text2").html("No connection...");
$("#online_status_indicator3").css("background-color", "red"); //Novel
$("#online_status_text3").html("No connection...");
$(".online_status_indicator4").css("background-color", "red"); //OAI / ooba
$(".online_status_text4").html("No connection...");
is_get_status = false;
is_get_status_novel = false;
setOpenAIOnlineStatus(false);
} else {
$("#online_status_indicator2").css("background-color", "green"); //kobold
$("#online_status_text2").html(online_status);
$("#online_status_indicator3").css("background-color", "green"); //novel
$("#online_status_text3").html(online_status);
$(".online_status_indicator4").css("background-color", "green"); //OAI / ooba
$(".online_status_text4").html(online_status);
}
}
///// DO WE STILL NEED THIS?
async function getLastVersion() {
jQuery.ajax({
type: "POST", //
url: "/getlastversion", //
data: JSON.stringify({
"": "",
}),
beforeSend: function () { },
cache: false,
dataType: "json",
contentType: "application/json",
//processData: false,
success: function (data) {
var getVersion = data.version;
if (getVersion !== "error" && getVersion != undefined) {
if (compareVersions(getVersion, VERSION) === 1) {
$("#verson").append(" (v." + getVersion + ")");
}
}
},
error: function (jqXHR, exception) {
console.log(exception);
console.log(jqXHR);
},
});
}
async function getStatus() {
if (is_get_status) {
jQuery.ajax({
type: "POST", //
url: "/getstatus", //
data: JSON.stringify({
api_server:
main_api == "kobold" ? api_server : api_server_textgenerationwebui,
main_api: main_api,
}),
beforeSend: function () { },
cache: false,
dataType: "json",
crossDomain: true,
contentType: "application/json",
//processData: false,
success: function (data) {
online_status = data.result;
if (online_status == undefined) {
online_status = "no_connection";
}
if (online_status.toLowerCase().indexOf("pygmalion") != -1 || (online_status !== "no_connection" && force_pygmalion_formatting)) {
is_pygmalion = true;
online_status += " (Pyg. formatting on)";
} else {
is_pygmalion = false;
}
//console.log(online_status);
resultCheckStatus();
if (online_status !== "no_connection") {
var checkStatusNow = setTimeout(getStatus, 3000); //getStatus();
}
},
error: function (jqXHR, exception) {
console.log(exception);
console.log(jqXHR);
online_status = "no_connection";
resultCheckStatus();
},
});
} else {
if (is_get_status_novel != true && is_get_status_openai != true) {
online_status = "no_connection";
}
}
}
function resultCheckStatus() {
is_api_button_press = false;
checkOnlineStatus();
$("#api_loading").css("display", "none");
$("#api_button").css("display", "inline-block");
$("#api_loading_textgenerationwebui").css("display", "none");
$("#api_button_textgenerationwebui").css("display", "inline-block");
}
async function getSoftPromptsList() {
if (!api_server) {
return;
}
const response = await fetch("/getsoftprompts", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": token,
},
body: JSON.stringify({ api_server: api_server }),
});
if (response.ok) {
const data = await response.json();
updateSoftPromptsList(data.soft_prompts);
}
}
function clearSoftPromptsList() {
$('#softprompt option[value!=""]').each(function () {
$(this).remove();
});
}
function updateSoftPromptsList(soft_prompts) {
// Delete SPs removed from Kobold
$("#softprompt option").each(function () {
const value = $(this).attr("value");
if (value == "") {
return;
}
const prompt = soft_prompts.find((x) => x.name === value);
if (!prompt) {
$(this).remove();
}
});
// Add SPs added to Kobold
soft_prompts.forEach((prompt) => {
if ($(`#softprompt option[value="${prompt.name}"]`).length === 0) {
$("#softprompt").append(
``
);
if (prompt.selected) {
$("#softprompt").val(prompt.name);
}
}
});
// No SP selected or no SPs
if (soft_prompts.length === 0 || !soft_prompts.some((x) => x.selected)) {
$("#softprompt").val("");
}
}
function printCharacters() {
//console.log('printCharacters() entered');
$("#rm_print_characters_block").empty();
//console.log('printCharacters() -- sees '+characters.length+' characters.');
characters.forEach(function (item, i, arr) {
let this_avatar = default_avatar;
if (item.avatar != "none") {
this_avatar = `/thumbnail?type=avatar&file=${encodeURIComponent(item.avatar)}&${Date.now()}`;
} //RossAscends: changed 'prepend' to 'append' to make alphabetical sorting display correctly.
$("#rm_print_characters_block").append(
`
${item.name}
`
);
//console.log('printcharacters() -- printing -- ChID '+i+' ('+item.name+')');
});
printGroups();
}
async function getCharacters() {
await getGroups();
var response = await fetch("/getcharacters", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": token,
},
body: JSON.stringify({
"": "",
}),
});
if (response.ok === true) {
var getData = ""; //RossAscends: reset to force array to update to account for deleted character.
getData = await response.json();
const load_ch_count = Object.getOwnPropertyNames(getData);
for (var i = 0; i < load_ch_count.length; i++) {
characters[i] = [];
characters[i] = getData[i];
characters[i]['name'] = DOMPurify.sanitize(characters[i]['name']);
}
if (this_chid != undefined && this_chid != "invalid-safety-id") {
$("#avatar_url_pole").val(characters[this_chid].avatar);
}
printCharacters();
}
}
async function getBackgrounds() {
const response = await fetch("/getbackgrounds", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": token,
},
body: JSON.stringify({
"": "",
}),
});
if (response.ok === true) {
const getData = await response.json();
//background = getData;
//console.log(getData.length);
for (const bg of getData) {
const thumbPath = `/thumbnail?type=bg&file=${encodeURIComponent(bg)}`;
$("#bg_menu_content").append(
`
`
);
}
//var aa = JSON.parse(getData[0]);
//const load_ch_coint = Object.getOwnPropertyNames(getData);
}
}
async function isColab() {
is_checked_colab = true;
const response = await fetch("/iscolab", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": token,
},
body: JSON.stringify({
"": "",
}),
});
if (response.ok === true) {
const getData = await response.json();
if (getData.colaburl != false) {
$("#colab_shadow_popup").css("display", "none");
is_colab = true;
let url = String(getData.colaburl).split("flare.com")[0] + "flare.com";
url = String(url).split("loca.lt")[0] + "loca.lt";
$("#api_url_text").val(url);
setTimeout(function () {
$("#api_button").click();
}, 2000);
}
}
}
async function setBackground(bg) {
jQuery.ajax({
type: "POST", //
url: "/setbackground", //
data: JSON.stringify({
bg: bg,
}),
beforeSend: function () {
//$('#create_button').attr('value','Creating...'); //
},
cache: false,
dataType: "json",
contentType: "application/json",
//processData: false,
success: function (html) { },
error: function (jqXHR, exception) {
console.log(exception);
console.log(jqXHR);
},
});
}
async function delBackground(bg) {
const response = await fetch("/delbackground", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": token,
},
body: JSON.stringify({
bg: bg,
}),
});
if (response.ok === true) {
}
}
async function delChat(chatfile) {
const response = await fetch("/delchat", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": token,
},
body: JSON.stringify({
chatfile: chatfile,
id: characters[this_chid].name
}),
});
if (response.ok === true) {
//close past chat popup
$("#select_chat_cross").click();
//this is a copy of what 'start new chat' does, just without the popup and confirmation
//not an ideal solution, and needs to be smarter
clearChat();
chat.length = 0;
characters[this_chid].chat = name2 + " - " + humanizedDateTime();
$("#selected_chat_pole").val(characters[this_chid].chat);
saveCharacterDebounced();
getChat();
//open the history view again after 100ms
setTimeout(function () { $("#option_select_chat").click() }, 100);
//hide option popup menu
$("#options").hide();
}
}
function printMessages() {
chat.forEach(function (item, i, arr) {
addOneMessage(item);
});
}
function clearChat() {
count_view_mes = 0;
extension_prompts = {};
$("#chat").html("");
}
function deleteLastMessage() {
count_view_mes--;
chat.length = chat.length - 1;
$('#chat').children('.mes').last().remove();
}
function messageFormating(mes, ch_name, isSystem, forceAvatar) {
if (!mes) {
mes = '';
}
if (this_chid != undefined && !isSystem)
mes = mes.replaceAll("<", "<").replaceAll(">", ">"); //for welcome message
if (this_chid === undefined) {
mes = mes
.replace(/\*\*(.+?)\*\*/g, "$1")
.replace(/\*(.+?)\*/g, "$1")
.replace(/\n/g, " ");
} else if (!isSystem) {
mes = converter.makeHtml(mes);
mes = mes.replace(/{([^}]+)}/g, "");
mes = mes.replace(/\n/g, " ");
mes = mes.trim();
}
if (forceAvatar) {
mes = mes.replaceAll(ch_name + ":", "");
}
if (ch_name !== name1) {
mes = mes.replaceAll(name2 + ":", "");
}
return mes;
}
function getMessageFromTemplate(mesId, characterName, isUser, avatarImg, bias, isSystem) {
const mes = $('#message_template .mes').clone();
mes.attr({ 'mesid': mesId, 'ch_name': characterName, 'is_user': isUser, 'is_system': !!isSystem });
mes.find('.avatar img').attr('src', avatarImg);
mes.find('.ch_name .name_text').text(characterName);
mes.find('.mes_bias').html(bias);
return mes;
}
function appendImageToMessage(mes, messageElement) {
if (mes.extra?.image) {
const image = document.createElement("img");
image.src = mes.extra?.image;
image.title = mes.title;
image.classList.add("img_extra");
messageElement.find(".mes_text").prepend(image);
}
}
function addOneMessage(mes, type = "normal") {
var messageText = mes["mes"];
var characterName = name1;
var avatarImg = "User Avatars/" + user_avatar;
const isSystem = mes.is_system;
generatedPromtCache = "";
if (!mes["is_user"]) {
if (mes.force_avatar) {
avatarImg = mes.force_avatar;
} else if (this_chid == undefined || this_chid == "invalid-safety-id") {
avatarImg = system_avatar;
} else {
if (characters[this_chid].avatar != "none") {
avatarImg = `/thumbnail?type=avatar&file=${encodeURIComponent(characters[this_chid].avatar)}`;
if (is_mes_reload_avatar !== false) {
avatarImg += "&" + is_mes_reload_avatar;
}
} else {
avatarImg = default_avatar;
}
}
characterName = mes.is_system || mes.force_avatar ? mes.name : name2;
}
if (count_view_mes == 0) {
messageText = substituteParams(messageText);
}
messageText = messageFormating(
messageText,
characterName,
isSystem,
mes.force_avatar
);
const bias = messageFormating(mes.extra?.bias ?? "");
var HTMLForEachMes = getMessageFromTemplate(count_view_mes, characterName, mes.is_user, avatarImg, bias, isSystem);
if (type !== 'swipe') {
$("#chat").append(HTMLForEachMes);
}
const newMessage = $(`#chat [mesid="${count_view_mes}"]`);
newMessage.data("isSystem", isSystem);
appendImageToMessage(mes, newMessage);
if (isSystem) {
newMessage.find(".mes_edit").hide();
}
newMessage.find('.avatar img').on('error', function () {
$(this).attr("src", "/img/user-slash-solid.svg");
});
if (type === 'swipe') {
$("#chat").children().filter('[mesid="' + (count_view_mes - 1) + '"]').children('.mes_block').children('.mes_text').html('');
$("#chat").children().filter('[mesid="' + (count_view_mes - 1) + '"]').children('.mes_block').children('.mes_text').append(messageText);
//console.log(mes);
} else {
$("#chat").children().filter('[mesid="' + count_view_mes + '"]').children('.mes_block').children('.mes_text').append(messageText);
hideSwipeButtons();
count_view_mes++;
}
$('#chat .mes').last().addClass('last_mes');
$('#chat .mes').eq(-2).removeClass('last_mes');
hideSwipeButtons();
showSwipeButtons();
// TODO: figure out smooth scrolling that wouldn't hit performance much.
var $textchat = $("#chat");
$textchat.scrollTop(($textchat[0].scrollHeight));
//$('#chat .mes').last().get(0).scrollIntoView({ behavior: "smooth" });
}
function substituteParams(content) {
content = content.replace(/{{user}}/gi, name1);
content = content.replace(/{{char}}/gi, name2);
content = content.replace(//gi, name1);
content = content.replace(//gi, name2);
return content;
}
function getSlashCommand(message, type) {
if (type == "regenerate" || type == "swipe") {
return null;
}
const commandMap = {
"/?": system_message_types.HELP,
"/help": system_message_types.HELP
};
const activationText = message.trim().toLowerCase();
if (Object.keys(commandMap).includes(activationText)) {
return commandMap[activationText];
}
return null;
}
function sendSystemMessage(type, text) {
const systemMessage = system_messages[type];
if (!systemMessage) {
return;
}
const newMessage = { ...systemMessage, send_date: humanizedDateTime() };
if (text) {
newMessage.mes = text;
}
if (!newMessage.extras) {
newMessage.extras = {};
}
newMessage.extras.type = type;
chat.push(newMessage);
addOneMessage(newMessage);
is_send_press = false;
}
function extractMessageBias(message) {
if (!message) {
return null;
}
const found = [];
const rxp = /{([^}]+)}/g;
let curMatch;
while ((curMatch = rxp.exec(message))) {
found.push(curMatch[1].trim());
}
if (!found.length) {
return "";
}
return ` ${found.join(" ")} `;
}
function cleanGroupMessage(getMessage) {
const group = groups.find((x) => x.id == selected_group);
if (group && Array.isArray(group.members) && group.members) {
for (let member of group.members) {
// Skip current speaker.
if (member === name2) {
continue;
}
const indexOfMember = getMessage.indexOf(member + ":");
if (indexOfMember != -1) {
getMessage = getMessage.substr(0, indexOfMember);
}
}
}
return getMessage;
}
function getExtensionPrompt() {
let extension_prompt = Object.keys(extension_prompts)
.sort()
.map((x) => extension_prompts[x])
.filter(x => x)
.join("\n");
if (extension_prompt.length && !extension_prompt.endsWith("\n")) {
extension_prompt += "\n";
}
return extension_prompt;
}
function baseChatReplace(value, name1, name2) {
if (value !== undefined && value.length > 0) {
if (is_pygmalion) {
value = value.replace(/{{user}}:/gi, "You:");
value = value.replace(/:/gi, "You:");
}
value = value.replace(/{{user}}/gi, name1);
value = value.replace(/{{char}}/gi, name2);
value = value.replace(//gi, name1);
value = value.replace(//gi, name2);
if (collapse_newlines) {
value = collapseNewlines(value);
}
}
return value;
}
function appendToStoryString(value, prefix) {
if (value !== undefined && value.length > 0) {
return prefix + value + '\n';
}
return '';
}
async function Generate(type, automatic_trigger, force_name2) {//encode("dsfs").length
console.log('Generate entered');
tokens_already_generated = 0;
message_already_generated = name2 + ': ';
const slashCommand = getSlashCommand($("#send_textarea").val(), type);
if (slashCommand == system_message_types.HELP) {
sendSystemMessage(system_message_types.HELP);
$("#send_textarea").val('').trigger('input');
return;
}
if (selected_group && !is_group_generating) {
generateGroupWrapper(false, type = type);
return;
}
if (online_status != 'no_connection' && this_chid != undefined && this_chid !== 'invalid-safety-id') {
if (type !== 'regenerate' && type !== "swipe") {
is_send_press = true;
var textareaText = $("#send_textarea").val();
//console.log('Not a Regenerate call, so posting normall with input of: ' +textareaText);
$("#send_textarea").val('').trigger('input');
} else {
//console.log('Regenerate call detected')
var textareaText = "";
if (chat[chat.length - 1]['is_user']) {//If last message from You
}
else if (type !== "swipe") {
chat.length = chat.length - 1;
count_view_mes -= 1;
openai_msgs.pop();
$('#chat').children().last().hide(500, function () {
$(this).remove();
});
}
}
$("#send_but").css("display", "none");
$("#loading_mes").css("display", "inline-block");
let promptBias = null;
let messageBias = extractMessageBias(textareaText);
// gets bias of the latest message where it was applied
for (let mes of chat) {
if (mes && mes.is_user && mes.extra && mes.extra.bias) {
promptBias = mes.extra.bias;
}
}
// bias from the latest message is top priority//
promptBias = messageBias ?? promptBias ?? '';
var storyString = "";
var userSendString = "";
var finalPromt = "";
var postAnchorChar = "Elaborate speaker";//'Talk a lot with description what is going on around';// in asterisks
var postAnchorStyle = "Writing style: very long messages";//"[Genre: roleplay chat][Tone: very long messages with descriptions]";
var anchorTop = '';
var anchorBottom = '';
var topAnchorDepth = 8;
if (character_anchor && !is_pygmalion) {
console.log('saw not pyg');
if (anchor_order === 0) {
anchorTop = name2 + " " + postAnchorChar;
} else {
console.log('saw pyg, adding anchors')
anchorBottom = "[" + name2 + " " + postAnchorChar + "]";
}
}
if (style_anchor && !is_pygmalion) {
if (anchor_order === 1) {
anchorTop = postAnchorStyle;
} else {
anchorBottom = "[" + postAnchorStyle + "]";
}
}
//*********************************
//PRE FORMATING STRING
//*********************************
if (textareaText != "" && !automatic_trigger) {
chat[chat.length] = {};
chat[chat.length - 1]['name'] = name1;
chat[chat.length - 1]['is_user'] = true;
chat[chat.length - 1]['is_name'] = true;
chat[chat.length - 1]['send_date'] = humanizedDateTime();
chat[chat.length - 1]['mes'] = textareaText;
chat[chat.length - 1]['extra'] = {};
if (messageBias) {
console.log('checking bias');
chat[chat.length - 1]['extra']['bias'] = messageBias;
}
//console.log('Generate calls addOneMessage');
addOneMessage(chat[chat.length - 1]);
}
////////////////////////////////////
let chatString = '';
let arrMes = [];
let mesSend = [];
let charDescription = baseChatReplace($.trim(characters[this_chid].description), name1, name2);
let charPersonality = baseChatReplace($.trim(characters[this_chid].personality), name1, name2);
let Scenario = baseChatReplace($.trim(characters[this_chid].scenario), name1, name2);
let mesExamples = baseChatReplace($.trim(characters[this_chid].mes_example), name1, name2);
if (!mesExamples.startsWith('')) {
mesExamples = '\n' + mesExamples.trim();
}
if (mesExamples.replace(//gi, '').trim().length === 0) {
mesExamples = '';
}
let mesExamplesArray = mesExamples.split(//gi).slice(1).map(block => `\n${block.trim()}\n`);
if (main_api === 'openai') {
const oai_chat = [...chat].filter(x => !x.is_system);
if (type == 'swipe') {
oai_chat.pop();
}
setOpenAIMessages(oai_chat);
setOpenAIMessageExamples(mesExamplesArray);
}
if (is_pygmalion) {
storyString += appendToStoryString(charDescription, disable_description_formatting ? '' : name2 + "'s Persona: ");
storyString += appendToStoryString(charPersonality, disable_personality_formatting ? '' : 'Personality: ');
storyString += appendToStoryString(Scenario, disable_scenario_formatting ? '' : 'Scenario: ');
} else {
if (charDescription !== undefined) {
if (charPersonality.length > 0 && !disable_personality_formatting) {
charPersonality = name2 + "'s personality: " + charPersonality;
}
}
storyString += appendToStoryString(charDescription, '');
if (storyString.endsWith('\n')) {
storyString = storyString.slice(0, -1);
}
if (count_view_mes < topAnchorDepth) {
storyString += '\n' + appendToStoryString(charPersonality, '');
}
}
if (custom_chat_separator && custom_chat_separator.length) {
for (let i = 0; i < mesExamplesArray.length; i++) {
mesExamplesArray[i] = mesExamplesArray[i].replace(//gi, custom_chat_separator);
}
}
if (pin_examples) {
for (let example of mesExamplesArray) {
if (!is_pygmalion) {
if (!storyString.endsWith('\n')) {
storyString += '\n';
}
example = example.replace(//i, 'This is how ' + name2 + ' should talk');//An example of how '+name2+' responds
}
storyString += appendToStoryString(example, '');
}
}
if (always_force_name2) {
force_name2 = true;
}
//////////////////////////////////
var count_exm_add = 0;
console.log('emptying chat2');
var chat2 = [];
var j = 0;
console.log('pre-replace chat.length = ' + chat.length);
for (var i = chat.length - 1; i >= 0; i--) {
if (j == 0) {
chat[j]['mes'] = chat[j]['mes'].replace(/{{user}}/gi, name1);
chat[j]['mes'] = chat[j]['mes'].replace(/{{char}}/gi, name2);
chat[j]['mes'] = chat[j]['mes'].replace(//gi, name1);
chat[j]['mes'] = chat[j]['mes'].replace(//gi, name2);
}
let this_mes_ch_name = '';
if (chat[j]['is_user']) {
this_mes_ch_name = name1;
} else {
this_mes_ch_name = name2;
}
if (chat[j]['is_name']) {
chat2[i] = this_mes_ch_name + ': ' + chat[j]['mes'] + '\n';
} else {
chat2[i] = chat[j]['mes'] + '\n';
}
// system messages produce no text
if (chat[j]['is_system']) {
chat2[i] = '';
}
// replace bias markup
chat2[i] = (chat2[i] ?? '').replace(/{([^}]+)}/g, '');
//console.log('replacing chat2 {}s');
j++;
}
console.log('post replace chat.length = ' + chat.length);
//chat2 = chat2.reverse();
var this_max_context = 1487;
if (main_api == 'kobold') this_max_context = max_context;
if (main_api == 'novel') {
if (novel_tier === 1) {
this_max_context = 1024;
} else {
this_max_context = 2048 - 60;//fix for fat tokens
if (nai_settings.model_novel == 'krake-v2') {
this_max_context -= 160;
}
}
}
if (main_api == 'openai') {
this_max_context = oai_settings.openai_max_context;
}
if (main_api == 'textgenerationwebui') {
this_max_context = (max_context - amount_gen);
}
let { worldInfoString, worldInfoBefore, worldInfoAfter } = getWorldInfoPrompt(chat2);
let extension_prompt = getExtensionPrompt();
/////////////////////// swipecode
if (type == 'swipe') {
console.log('pre swipe shift: ' + chat2.length);
console.log('shifting swipe chat2');
chat2.shift();
}
console.log('post swipe shift:' + chat2.length);
var i = 0;
for (var item of chat2) {//console.log(encode("dsfs").length);
chatString = item + chatString;
if (encode(JSON.stringify(
worldInfoString + storyString + chatString +
anchorTop + anchorBottom +
charPersonality + promptBias + extension_prompt
)).length + 120 < this_max_context) { //(The number of tokens in the entire promt) need fix, it must count correctly (added +120, so that the description of the character does not hide)
//if (is_pygmalion && i == chat2.length-1) item='\n'+item;
arrMes[arrMes.length] = item;
} else {
console.log('reducing chat.length by 1');
i = chat2.length - 1;
}
await delay(1); //For disable slow down (encode gpt-2 need fix)
// console.log(i+' '+chat.length);
count_exm_add = 0;
if (i === chat2.length - 1) {
if (!pin_examples) {
let mesExmString = '';
for (let iii = 0; iii < mesExamplesArray.length; iii++) {
mesExmString += mesExamplesArray[iii];
const prompt = worldInfoString + storyString + mesExmString + chatString + anchorTop + anchorBottom + charPersonality + promptBias + extension_prompt;
if (encode(JSON.stringify(prompt)).length + 120 < this_max_context) {
if (!is_pygmalion) {
mesExamplesArray[iii] = mesExamplesArray[iii].replace(//i, `This is how ${name2} should talk`);
}
count_exm_add++;
await delay(1);
} else {
iii = mesExamplesArray.length;
}
}
}
if (!is_pygmalion && Scenario && Scenario.length > 0) {
if (!storyString.endsWith('\n')) {
storyString += '\n';
}
storyString += !disable_scenario_formatting ? `Circumstances and context of the dialogue: ${Scenario}\n` : `${Scenario}\n`;
}
console.log('calling runGenerate');
runGenerate();
return;
}
i++;
}
function runGenerate(cycleGenerationPromt = '') {
is_send_press = true;
generatedPromtCache += cycleGenerationPromt;
if (generatedPromtCache.length == 0) {
if (main_api === 'openai') {
generateOpenAIPromptCache(charPersonality, topAnchorDepth, anchorTop, anchorBottom);
}
console.log('generating prompt');
chatString = "";
arrMes = arrMes.reverse();
var is_add_personality = false;
arrMes.forEach(function (item, i, arr) {//For added anchors and others
if (i >= arrMes.length - 1 && $.trim(item).substr(0, (name1 + ":").length) != name1 + ":") {
if (textareaText == "") {
item = item.substr(0, item.length - 1);
}
}
if (i === arrMes.length - topAnchorDepth && count_view_mes >= topAnchorDepth && !is_add_personality) {
is_add_personality = true;
//chatString = chatString.substr(0,chatString.length-1);
//anchorAndPersonality = "[Genre: roleplay chat][Tone: very long messages with descriptions]";
if ((anchorTop != "" || charPersonality != "") && !is_pygmalion) {
if (anchorTop != "") charPersonality += ' ';
item += "[" + charPersonality + anchorTop + ']\n';
}
}
if (i >= arrMes.length - 1 && count_view_mes > 8 && $.trim(item).substr(0, (name1 + ":").length) == name1 + ":" && !is_pygmalion) {//For add anchor in end
item = item.substr(0, item.length - 1);
//chatString+=postAnchor+"\n";//"[Writing style: very long messages]\n";
item = item + anchorBottom + "\n";
}
if (is_pygmalion) {
if (i >= arrMes.length - 1 && $.trim(item).substr(0, (name1 + ":").length) == name1 + ":") {//for add name2 when user sent
item = item + name2 + ":";
}
if (i >= arrMes.length - 1 && $.trim(item).substr(0, (name1 + ":").length) != name1 + ":") {//for add name2 when continue
if (textareaText == "") {
item = item + '\n' + name2 + ":";
}
}
if ($.trim(item).indexOf(name1) === 0) {
item = item.replace(name1 + ':', 'You:');
}
}
mesSend[mesSend.length] = item;
});
}
let mesSendString = '';
let mesExmString = '';
function setPromtString() {
mesSendString = '';
mesExmString = '';
for (let j = 0; j < count_exm_add; j++) {
mesExmString += mesExamplesArray[j];
}
for (let j = 0; j < mesSend.length; j++) {
mesSendString += mesSend[j];
if (force_name2 && j === mesSend.length - 1 && tokens_already_generated === 0) {
mesSendString += name2 + ':';
}
}
}
function checkPromtSize() {
setPromtString();
let thisPromtContextSize = encode(JSON.stringify(worldInfoString + storyString + mesExmString + mesSendString + anchorTop + anchorBottom + charPersonality + generatedPromtCache + promptBias + extension_prompt)).length + 120;
if (thisPromtContextSize > this_max_context) { //if the prepared prompt is larger than the max context size...
if (count_exm_add > 0) { // ..and we have example mesages..
//console.log('Context size: '+thisPromtContextSize+' -- too big, removing example message');
//mesExamplesArray.length = mesExamplesArray.length-1;
count_exm_add--; // remove the example messages...
checkPromtSize(); // and try agin...
} else if (mesSend.length > 0) { // if the chat history is longer than 0
//console.log('Context size: '+thisPromtContextSize+' -- too big, removing oldest chat message');
mesSend.shift(); // remove the first (oldest) chat entry..
checkPromtSize(); // and check size again..
} else {
//end
}
}
}
if (generatedPromtCache.length > 0) {
//console.log('Generated Prompt Cache length: '+generatedPromtCache.length);
checkPromtSize();
} else {
console.log('calling setPromtString')
setPromtString();
}
// add a custom dingus (if defined)
if (custom_chat_separator && custom_chat_separator.length) {
mesSendString = custom_chat_separator + '\n' + mesSendString;
}
// add non-pygma dingus
else if (!is_pygmalion) {
mesSendString = '\nThen the roleplay chat between ' + name1 + ' and ' + name2 + ' begins.\n' + mesSendString;
}
// add pygma
else {
mesSendString = '\n' + mesSendString;
//mesSendString = mesSendString; //This edit simply removes the first "" that is prepended to all context prompts
}
finalPromt = worldInfoBefore + storyString + worldInfoAfter + extension_prompt + mesExmString + mesSendString + generatedPromtCache + promptBias;
finalPromt = finalPromt.replace(/\r/gm, '');
if (collapse_newlines) {
finalPromt = collapseNewlines(finalPromt);
}
//console.log('final prompt decided');
//if we aren't using the kobold GUI settings...
if (main_api == 'textgenerationwebui' || main_api == 'kobold' && preset_settings != 'gui') {
var this_settings = koboldai_settings[koboldai_setting_names[preset_settings]];
var this_amount_gen = parseInt(amount_gen); // how many tokens the AI will be requested to generate
if (is_pygmalion) { // if we are using a pygmalion model...
if (tokens_already_generated === 0) { // if nothing has been generated yet..
if (parseInt(amount_gen) >= 50) { // if the max gen setting is > 50...(
this_amount_gen = 50; // then only try to make 50 this cycle..
}
else {
this_amount_gen = parseInt(amount_gen); // otherwise, make as much as the max amount request.
}
}
else { // if we already recieved some generated text...
if (parseInt(amount_gen) - tokens_already_generated < tokens_cycle_count) { // if the remaining tokens to be made is less than next potential cycle count
this_amount_gen = parseInt(amount_gen) - tokens_already_generated; // subtract already generated amount from the desired max gen amount
}
else {
this_amount_gen = tokens_cycle_count; // otherwise make the standard cycle amont (frist 50, and 30 after that)
}
}
}
}
var generate_data;
if (main_api == 'kobold') {
var generate_data = {
prompt: finalPromt,
gui_settings: true,
max_length: amount_gen,
temperature: kai_settings.temp,
max_context_length: max_context,
singleline: kai_settings.single_line,
};
if (preset_settings != 'gui') {
generate_data = {
prompt: finalPromt,
gui_settings: false,
sampler_order: this_settings.sampler_order,
max_context_length: parseInt(max_context),//this_settings.max_length,
max_length: this_amount_gen,//parseInt(amount_gen),
rep_pen: parseFloat(kai_settings.rep_pen),
rep_pen_range: parseInt(kai_settings.rep_pen_range),
rep_pen_slope: kai_settings.rep_pen_slope,
temperature: parseFloat(kai_settings.temp),
tfs: kai_settings.tfs,
top_a: kai_settings.top_a,
top_k: kai_settings.top_k,
top_p: kai_settings.top_p,
typical: kai_settings.typical,
s1: this_settings.sampler_order[0],
s2: this_settings.sampler_order[1],
s3: this_settings.sampler_order[2],
s4: this_settings.sampler_order[3],
s5: this_settings.sampler_order[4],
s6: this_settings.sampler_order[5],
s7: this_settings.sampler_order[6],
use_world_info: false,
singleline: kai_settings.single_line,
};
}
}
if (main_api == 'textgenerationwebui') {
var generate_data = {
data: [
finalPromt,
this_amount_gen, // max new tokens
textgenerationwebui_settings.do_sample, // do_sample
textgenerationwebui_settings.temp, // temperature
textgenerationwebui_settings.top_p, // top_p
textgenerationwebui_settings.typical_p, // typical_p
textgenerationwebui_settings.rep_pen, // repetition_penalty
textgenerationwebui_settings.encoder_rep_pen, // encoder rep pen
textgenerationwebui_settings.top_k, // top_k
textgenerationwebui_settings.min_length, // min_length
textgenerationwebui_settings.no_repeat_ngram_size, // no_repeat_ngram_size
textgenerationwebui_settings.num_beams, // num_beams
textgenerationwebui_settings.penalty_alpha, // penalty_alpha
textgenerationwebui_settings.length_penalty, // length_penalty
textgenerationwebui_settings.early_stopping, // early_stopping
textgenerationwebui_settings.seed, // seed
name1, // name1
name2, // name2
"", // Context
true, // stop at newline
this_max_context, // Maximum prompt size in tokens
1, // num attempts
]
};
}
if (main_api == 'novel') {
const this_settings = novelai_settings[novelai_setting_names[nai_settings.preset_settings_novel]];
generate_data = {
"input": finalPromt,
"model": nai_settings.model_novel,
"use_string": true,
"temperature": parseFloat(nai_settings.temp_novel),
"max_length": this_settings.max_length,
"min_length": this_settings.min_length,
"tail_free_sampling": this_settings.tail_free_sampling,
"repetition_penalty": parseFloat(nai_settings.rep_pen_novel),
"repetition_penalty_range": parseInt(nai_settings.rep_pen_size_novel),
"repetition_penalty_frequency": this_settings.repetition_penalty_frequency,
"repetition_penalty_presence": this_settings.repetition_penalty_presence,
//"stop_sequences": {{187}},
//bad_words_ids = {{50256}, {0}, {1}};
//generate_until_sentence = true;
"use_cache": false,
//use_string = true;
"return_full_text": false,
"prefix": "vanilla",
"order": this_settings.order
};
}
var generate_url = '';
if (main_api == 'kobold') {
generate_url = '/generate';
} else if (main_api == 'textgenerationwebui') {
generate_url = '/generate_textgenerationwebui';
} else if (main_api == 'novel') {
generate_url = '/generate_novelai';
}
console.log('rungenerate calling API');
if (main_api == 'openai') {
let prompt = prepareOpenAIMessages(name2, storyString, worldInfoBefore, worldInfoAfter, extension_prompt, promptBias);
sendOpenAIRequest(prompt).then(onSuccess).catch(onError);
}
else {
jQuery.ajax({
type: 'POST', //
url: generate_url, //
data: JSON.stringify(generate_data),
beforeSend: function () {
//$('#create_button').attr('value','Creating...');
},
cache: false,
dataType: "json",
contentType: "application/json",
success: onSuccess,
error: onError
}); //end of "if not data error"
}
function onSuccess(data) {
tokens_already_generated += this_amount_gen; // add new gen amt to any prev gen counter..
is_send_press = false;
if (!data.error) {
//const getData = await response.json();
var getMessage = "";
if (main_api == 'kobold') {
getMessage = data.results[0].text;
} else if (main_api == 'textgenerationwebui') {
getMessage = data.data[0];
if (getMessage == null || data.error) {
callPopup('
Got empty response from Text generation web UI. Try restarting the API with recommended options.
', 'text');
return;
}
getMessage = getMessage.substring(finalPromt.length);
} else if (main_api == 'novel') {
getMessage = data.output;
}
if (main_api == 'openai') {
getMessage = data;
}
if (collapse_newlines) {
getMessage = collapseNewlines(getMessage);
}
//Pygmalion run again // to make it continue generating so long as it's under max_amount and hasn't signaled
// an end to the character's response via typing "You:" or adding ""
if (is_pygmalion) {
if_typing_text = false;
message_already_generated += getMessage;
promptBias = '';
//console.log('AI Response so far: '+message_already_generated);
if (message_already_generated.indexOf('You:') === -1 && //if there is no 'You:' in the response msg
message_already_generated.indexOf('<|endoftext|>') === -1 && //if there is no stamp in the response msg
tokens_already_generated < parseInt(amount_gen) && //if the gen'd msg is less than the max response length..
getMessage.length > 0) { //if we actually have gen'd text at all...
runGenerate(getMessage);
console.log('returning to make pyg generate again'); //generate again with the 'GetMessage' argument..
return;
}
getMessage = message_already_generated;
}
//Formating
getMessage = $.trim(getMessage);
if (is_pygmalion) {
getMessage = getMessage.replace(//g, name1);
getMessage = getMessage.replace(//g, name2);
getMessage = getMessage.replace(/You:/g, name1 + ':');
}
if (getMessage.indexOf(name1 + ":") != -1) {
getMessage = getMessage.substr(0, getMessage.indexOf(name1 + ":"));
}
if (getMessage.indexOf('<|endoftext|>') != -1) {
getMessage = getMessage.substr(0, getMessage.indexOf('<|endoftext|>'));
}
// clean-up group message from excessive generations
if (selected_group) {
getMessage = cleanGroupMessage(getMessage);
}
let this_mes_is_name = true;
if (getMessage.indexOf(name2 + ":") === 0) {
getMessage = getMessage.replace(name2 + ':', '');
getMessage = getMessage.trimStart();
} else {
this_mes_is_name = false;
}
if (force_name2) this_mes_is_name = true;
//getMessage = getMessage.replace(/^\s+/g, '');
if (getMessage.length > 0) {
if (chat[chat.length - 1]['swipe_id'] === undefined ||
chat[chat.length - 1]['is_user']) { type = 'normal'; }
if (type === 'swipe') {
chat[chat.length - 1]['swipes'][chat[chat.length - 1]['swipes'].length] = getMessage;
if (chat[chat.length - 1]['swipe_id'] === chat[chat.length - 1]['swipes'].length - 1) {
//console.log(getMessage);
chat[chat.length - 1]['mes'] = getMessage;
// console.log('runGenerate calls addOneMessage for swipe');
addOneMessage(chat[chat.length - 1], 'swipe');
} else {
chat[chat.length - 1]['mes'] = getMessage;
}
is_send_press = false;
} else {
console.log('entering chat update routine for non-swipe post');
is_send_press = false;
chat[chat.length] = {};
chat[chat.length - 1]['name'] = name2;
chat[chat.length - 1]['is_user'] = false;
chat[chat.length - 1]['is_name'] = this_mes_is_name;
chat[chat.length - 1]['send_date'] = humanizedDateTime();
getMessage = $.trim(getMessage);
chat[chat.length - 1]['mes'] = getMessage;
if (selected_group) {
console.log('entering chat update for groups');
let avatarImg = 'img/ai4.png';
if (characters[this_chid].avatar != 'none') {
avatarImg = `characters/${characters[this_chid].avatar}?${Date.now()}`;
}
chat[chat.length - 1]['is_name'] = true;
chat[chat.length - 1]['force_avatar'] = avatarImg;
}
//console.log('runGenerate calls addOneMessage');
addOneMessage(chat[chat.length - 1]);
$("#send_but").css("display", "inline");
$("#loading_mes").css("display", "none");
}
} else {
// regenerate with character speech reenforced
// to make sure we leave on swipe type while also adding the name2 appendage
const newType = type == "swipe" ? "swipe" : "force_name2";
Generate(newType, automatic_trigger = false, force_name2 = true);
}
} else {
$("#send_but").css("display", "inline");
$("#loading_mes").css("display", "none");
//console.log('runGenerate calling showSwipeBtns');
showSwipeButtons();
}
console.log('/savechat called by /Generate');
if (selected_group) {
saveGroupChat(selected_group);
} else {
saveChat();
}
//let final_message_length = encode(JSON.stringify(getMessage)).length;
//console.log('AI Response: +'+getMessage+ '('+final_message_length+' tokens)');
$("#send_but").css("display", "inline");
//console.log('runGenerate calling showSwipeBtns pt. 2');
showSwipeButtons();
$("#loading_mes").css("display", "none");
$('.mes_edit:last').show();
};
function onError(jqXHR, exception) {
$("#send_textarea").removeAttr('disabled');
is_send_press = false;
$("#send_but").css("display", "inline");
$("#loading_mes").css("display", "none");
console.log(exception);
console.log(jqXHR);
};
} //rungenerate ends
} else { //generate's primary loop ends, after this is error handling for no-connection or safety-id
if (this_chid == undefined || this_chid == 'invalid-safety-id') {
//send ch sel
popup_type = 'char_not_selected';
callPopup('
Сharacter is not selected
');
}
is_send_press = false;
}
console.log('generate ending');
} //generate ends
function resetChatState() {
active_character = "invalid-safety-id"; //unsets the chid in settings (this prevents AutoLoadChat from trying to load the wrong ChID
this_chid = "invalid-safety-id"; //unsets expected chid before reloading (related to getCharacters/printCharacters from using old arrays)
name2 = systemUserName; // replaces deleted charcter name with system user since it will be displayed next.
chat = [...safetychat]; // sets up system user to tell user about having deleted a character
characters.length = 0; // resets the characters array, forcing getcharacters to reset
}
function setCharacterId(value) {
this_chid = value;
}
function setCharacterName(value) {
name2 = value;
}
function setOnlineStatus(value) {
online_status = value;
}
function setEditedMessageId(value) {
this_edit_mes_id = value;
}
function setSendButtonState(value) {
is_send_press = value;
}
function resultCheckStatusNovel() {
is_api_button_press_novel = false;
checkOnlineStatus();
$("#api_loading_novel").css("display", "none");
$("#api_button_novel").css("display", "inline-block");
}
async function saveChat(chat_name) {
let file_name = chat_name ?? characters[this_chid].chat;
chat.forEach(function (item, i) {
if (item["is_group"]) {
alert('Trying to save group chat with regular saveChat function. Aborting to prevent corruption.');
throw new Error('Group chat saved from saveChat');
}
if (item.is_user) {
var str = item.mes.replace(`${name1}:`, `${default_user_name}:`);
chat[i].mes = str;
chat[i].name = default_user_name;
} else if (i !== chat.length - 1 && chat[i].swipe_id !== undefined) {
delete chat[i].swipes;
delete chat[i].swipe_id;
}
});
var save_chat = [
{
user_name: default_user_name,
character_name: name2,
create_date: chat_create_date,
},
...chat,
];
jQuery.ajax({
type: "POST",
url: "/savechat",
data: JSON.stringify({
ch_name: characters[this_chid].name,
file_name: file_name,
chat: save_chat,
avatar_url: characters[this_chid].avatar,
}),
beforeSend: function () {
//$('#create_button').attr('value','Creating...');
},
cache: false,
dataType: "json",
contentType: "application/json",
success: function (data) { },
error: function (jqXHR, exception) {
console.log(exception);
console.log(jqXHR);
},
});
}
function read_avatar_load(input) {
if (input.files && input.files[0]) {
const reader = new FileReader();
if (selected_button == "create") {
create_save_avatar = input.files;
}
reader.onload = function (e) {
if (selected_button == "character_edit") {
saveCharacterDebounced();
}
$("#avatar_load_preview").attr("src", e.target.result);
//.width(103)
//.height(83);
//console.log(e.target.result.name);
};
reader.readAsDataURL(input.files[0]);
}
}
async function getChat() {
//console.log('/getchat -- entered for -- ' + characters[this_chid].name);
try {
const response = await $.ajax({
type: 'POST',
url: '/getchat',
data: JSON.stringify({
ch_name: characters[this_chid].name,
file_name: characters[this_chid].chat,
avatar_url: characters[this_chid].avatar
}),
dataType: 'json',
contentType: 'application/json',
});
if (response[0] !== undefined) {
chat.push(...response);
chat_create_date = chat[0]['create_date'];
chat.shift();
} else {
chat_create_date = humanizedDateTime();
}
getChatResult();
saveChat();
} catch (error) {
getChatResult();
console.log(error);
}
}
function getChatResult() {
name2 = characters[this_chid].name;
if (chat.length > 1) {
for (let i = 0; i < chat.length; i++) {
const item = chat[i];
if (item["is_user"]) {
item['mes'] = item['mes'].replace(default_user_name + ':', name1 + ':');
item['name'] = name1;
}
}
} else {
const firstMes = characters[this_chid].first_mes || default_ch_mes;
chat[0] = {
name: name2,
is_user: false,
is_name: true,
send_date: humanizedDateTime(),
mes: firstMes
};
}
printMessages();
select_selected_character(this_chid);
}
async function openCharacterChat(file_name) {
characters[this_chid]["chat"] = file_name;
clearChat();
chat.length = 0;
await getChat();
$("#selected_chat_pole").val(file_name);
$("#create_button").click();
$("#shadow_select_chat_popup").css("display", "none");
$("#load_select_chat_div").css("display", "block");
}
/* function openNavToggle() {
if (!$("#nav-toggle").prop("checked")) {
$("#nav-toggle").trigger("click");
}
} */
////////// OPTIMZED MAIN API CHANGE FUNCTION ////////////
function changeMainAPI() {
const selectedVal = $("#main_api").val();
//console.log(selectedVal);
const apiElements = {
"kobold": {
apiSettings: $("#kobold_api-settings"),
apiConnector: $("#kobold_api"),
apiPresets: $('#kobold_api-presets'),
apiRanges: $("#range_block"),
maxContextElem: $("#max_context_block"),
amountGenElem: $("#amount_gen_block"),
softPromptElem: $("#softprompt_block")
},
"textgenerationwebui": {
apiSettings: $("#textgenerationwebui_api-settings"),
apiConnector: $("#textgenerationwebui_api"),
apiPresets: $('#textgenerationwebui_api-presets'),
apiRanges: $("#range_block_textgenerationwebui"),
maxContextElem: $("#max_context_block"),
amountGenElem: $("#amount_gen_block"),
softPromptElem: $("#softprompt_block")
},
"novel": {
apiSettings: $("#novel_api-settings"),
apiConnector: $("#novel_api"),
apiPresets: $('#novel_api-presets'),
apiRanges: $("#range_block_novel"),
maxContextElem: $("#max_context_block"),
amountGenElem: $("#amount_gen_block"),
softPromptElem: $("#softprompt_block")
},
"openai": {
apiSettings: $("#openai_settings"),
apiConnector: $("#openai_api"),
apiPresets: $('#openai_api-presets'),
apiRanges: $("#range_block_openai"),
maxContextElem: $("#max_context_block"),
amountGenElem: $("#amount_gen_block"),
softPromptElem: $("#softprompt_block"),
},
};
//console.log('--- apiElements--- ');
//console.log(apiElements);
for (const apiName in apiElements) {
const apiObj = apiElements[apiName];
const isCurrentApi = selectedVal === apiName;
apiObj.apiSettings.css("display", isCurrentApi ? "block" : "none");
apiObj.apiConnector.css("display", isCurrentApi ? "block" : "none");
apiObj.apiRanges.css("display", isCurrentApi ? "block" : "none");
apiObj.apiPresets.css("display", isCurrentApi ? "block" : "none");
if (isCurrentApi && apiName === "kobold") {
//console.log("enabling SP for kobold");
$("#softprompt_block").css("display", "block");
}
if (isCurrentApi && (apiName === "textgenerationwebui" || apiName === "novel")) {
console.log("enabling amount_gen for ooba/novel");
apiObj.amountGenElem.children().prop("disabled", false);
apiObj.amountGenElem.css("opacity", 1.0);
}
// Hide common settings for OpenAI
if (selectedVal == "openai") {
$("#common-gen-settings-block").css("display", "none");
} else {
$("#common-gen-settings-block").css("display", "block");
}
}
main_api = selectedVal;
online_status = "no_connection";
}
////////////////////////////////////////////////////
async function getUserAvatars() {
$("#user_avatar_block").html(""); //RossAscends: necessary to avoid doubling avatars each refresh.
$("#user_avatar_block").append('