diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..b512c09d4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+node_modules
\ No newline at end of file
diff --git a/public/KoboldAI Worlds/Sample.json b/public/KoboldAI Worlds/Sample.json
new file mode 100644
index 000000000..082684e84
--- /dev/null
+++ b/public/KoboldAI Worlds/Sample.json
@@ -0,0 +1,30 @@
+{
+ "folders": {
+ "Sample Folder": [
+ 0,
+ 1
+ ]
+ },
+ "entries": {
+ "0": {
+ "uid": 0,
+ "title": "AAA",
+ "key": [ "AAA" ],
+ "keysecondary": [ ],
+ "constant": false,
+ "content": "AAA is a city where BBB lives.",
+ "comment": "AAA definition",
+ "selective": true
+ },
+ "1": {
+ "uid": 1,
+ "title": "BBB",
+ "key": [ "BBB" ],
+ "keysecondary": [ ],
+ "constant": false,
+ "content": "BBB is a 21-year old female student of CCC academy.",
+ "comment": "BBB definition",
+ "selective": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/public/index.html b/public/index.html
index 7d4b0f3fa..b16c1cabf 100644
--- a/public/index.html
+++ b/public/index.html
@@ -1,6 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -37,7 +48,7 @@
create_date: 0,
mes: '\n*You went inside. The air smelled of fried meat, tobacco and a hint of wine. A dim light was cast by candles, and a fire crackled in the fireplace. It seems to be a very pleasant place. Behind the wooden bar is an elf waitress, she is smiling. Her ears are very pointy, and there is a twinkle in her eye. She wears glasses and a white apron. As soon as she noticed you, she immediately came right up close to you.*\n\n' +
' Hello there! How is your evening going?\n' +
- ' \n@@@TavernAI v'+VERSION+'@@@ Cloud
'
+ ' \n@@@TavernAI v'+VERSION+'@@@ Cloud
'
}];
var chat_create_date = 0;
@@ -54,6 +65,7 @@
var is_mes_reload_avatar = false;
var is_advanced_char_open = false;
+ var is_world_edit_open = false;
var menu_type = '';//what is selected in the menu
var selected_button = '';//which button pressed
@@ -67,6 +79,8 @@
var create_save_mes_example = '';
var timerSaveEdit;
+ var timerKoboldSync;
+ var timerWorldSave;
var durationSaveEdit = 200;
//animation right menu
var animation_rm_duration = 200;
@@ -102,6 +116,13 @@
var user_avatar = 'you.png';
var temp = 0.5;
var amount_gen = 80;
+ var kobold_world = null;
+ var koboldai_world_names;
+ var kobold_world_synced = false;
+ var kobold_sync_failed = false;
+ var kobold_is_united = false;
+ var kobold_world_data = null;
+ var imported_world_name = '';
var max_context = 2048;//2048;
var rep_pen = 1;
var rep_pen_size = 100;
@@ -136,6 +157,29 @@
var css_send_form_display = $('
').css('display');
var colab_ini_step = 1;
+
+ // VARIABLES DONE NOW THE REAL CODE
+ //
+ //
+ //
+
+ // Dealing with Textarea Height
+
+ //function textAreaAdjust(element) {
+ // element.style.height = "1px";
+ // element.style.height = (25+element.scrollHeight)+"px";
+ //}
+ //function calcHeight(value) {
+ // let numberOfLineBreaks = (value.match(/\n/g) || []).length;
+ // // min-height + lines x line-height + padding + border
+ // let newHeight = 25 + numberOfLineBreaks * 25 + 6 + 1;
+ // return newHeight;
+ //}
+ //let textarea = document.querySelector(".resize-ta");
+ //textarea.addEventListener("keyup", () => {
+ //textarea.style.height = calcHeight(textarea.value) + "px";
+ //});
+
setInterval(function() {
switch(colab_ini_step){
case 0:
@@ -157,6 +201,9 @@
}
}, 500);
/////////////
+
+
+
getSettings("def");
getLastVersion();
@@ -197,14 +244,13 @@
is_get_status_novel = false;
}else{
$("#online_status_indicator").css("background-color", "black");
- $("#online_status").css("opacity", 0.0);
+ $("#online_status").css("display", "none");
$("#online_status_text").html("");
$("#online_status_indicator2").css("background-color", "green");
$("#online_status_text2").html(online_status);
$("#online_status_indicator3").css("background-color", "green");
$("#online_status_text3").html(online_status);
}
-
}
async function getLastVersion(){
@@ -264,6 +310,9 @@
online_status = data.result;
if(online_status == undefined){
online_status = 'no_connection';
+
+ kobold_world_synced = false;
+ updateWorldStatus();
}
if(online_status.toLowerCase().indexOf('pygmalion') != -1){
is_pygmalion = true;
@@ -276,6 +325,7 @@
resultCheckStatus();
if(online_status !== 'no_connection'){
var checkStatusNow = setTimeout(getStatus, 3000);//getStatus();
+ syncKoboldWorldInfo(false);
}
},
error: function (jqXHR, exception) {
@@ -283,12 +333,18 @@
console.log(jqXHR);
online_status = 'no_connection';
+ // invalidate world info when losing connection to kobold
+ kobold_world_synced = false;
+ updateWorldStatus();
+
resultCheckStatus();
}
});
}else{
if(is_get_status_novel != true){
online_status = 'no_connection';
+ kobold_world_synced = false;
+ updateWorldStatus();
}
}
}
@@ -591,7 +647,7 @@
//$("#send_textarea").blur();
$( "#send_but" ).css("display", "none");
- $( "#loading_mes" ).css("display", "block");
+ $( "#loading_mes" ).css("display", "inline-block");
var storyString = "";
@@ -909,7 +965,8 @@
var generate_data;
if(main_api == 'kobold'){
- var generate_data = {prompt: finalPromt, gui_settings: true,max_length: amount_gen,temperature: temp, max_context_length: max_context};
+ const use_world_info = Boolean(kobold_world && kobold_world_synced);
+ var generate_data = {prompt: finalPromt, gui_settings: true,max_length: amount_gen,temperature: temp, max_context_length: max_context, use_world_info};
if(preset_settings != 'gui'){
var this_settings = koboldai_settings[koboldai_setting_names[preset_settings]];
@@ -950,7 +1007,8 @@
s4:this_settings.sampler_order[3],
s5:this_settings.sampler_order[4],
s6:this_settings.sampler_order[5],
- s7:this_settings.sampler_order[6]
+ s7:this_settings.sampler_order[6],
+ use_world_info: use_world_info,
};
}
}
@@ -1048,7 +1106,7 @@
getMessage = $.trim(getMessage);
chat[chat.length-1]['mes'] = getMessage;
addOneMessage(chat[chat.length-1]);
- $( "#send_but" ).css("display", "block");
+ $( "#send_but" ).css("display", "inline");
$( "#loading_mes" ).css("display", "none");
saveChat();
}else{
@@ -1056,7 +1114,7 @@
Generate('force_name2');
}
}else{
- $( "#send_but" ).css("display", "block");
+ $( "#send_but" ).css("display", "inline");
$( "#loading_mes" ).css("display", "none");
}
},
@@ -1064,7 +1122,7 @@
$("#send_textarea").removeAttr('disabled');
is_send_press = false;
- $( "#send_but" ).css("display", "block");
+ $( "#send_but" ).css("display", "inline");
$( "#loading_mes" ).css("display", "none");
console.log(exception);
console.log(jqXHR);
@@ -1212,6 +1270,9 @@
$( "#rm_button_characters" ).children("h2").css(deselected_button_style);
$( "#rm_button_settings" ).children("h2").css(seleced_button_style);
$( "#rm_button_selected_ch" ).children("h2").css(deselected_button_style);
+
+ // Dumb call, but won't need an interval
+ updateWorldStatus();
});
$( "#rm_button_characters" ).click(function() {
selected_button = 'characters';
@@ -1517,6 +1578,17 @@
}
});
}
+ if (popup_type === 'world_imported' && imported_world_name) {
+ koboldai_world_names.forEach((item, i) => {
+ if (item === imported_world_name) {
+ $('#world_info').val(i).change();
+ }
+ })
+ imported_world_name = '';
+ }
+ if (popup_type === 'del_world' && kobold_world) {
+ deleteWorldInfo(kobold_world);
+ }
if(popup_type == 'new_chat' && this_chid != undefined && menu_type != "create"){//Fix it; New chat doesn't create while open create character menu
clearChat();
chat.length = 0;
@@ -1542,11 +1614,13 @@
$("#dialogue_popup_cancel").css("display", "none");
break;
+ case 'world_imported':
case 'new_chat':
$("#dialogue_popup_ok").css("background-color", "#191b31CC");
$("#dialogue_popup_ok").text("Yes");
break;
+ case 'del_world':
default:
$("#dialogue_popup_ok").css("background-color", "#791b31");
$("#dialogue_popup_ok").text("Delete");
@@ -1842,6 +1916,7 @@
is_get_status = true;
is_api_button_press = true;
getStatus();
+ detectUnitedKobold();
}
});
@@ -1940,6 +2015,23 @@
});
+ $("#world_info").change(function() {
+ const selectedWorld = $('#world_info').find(":selected").val();
+ kobold_world_synced = false;
+ kobold_sync_failed = false;
+ kobold_world = null;
+
+ if (selectedWorld !== 'None') {
+ const worldIndex = Number(selectedWorld);
+ kobold_world = !isNaN(worldIndex) ? koboldai_world_names[worldIndex] : null;
+ }
+
+ hideWorldEditor();
+ syncKoboldWorldInfo(true);
+ saveSettings();
+ updateWorldStatus();
+ });
+
$( "#settings_perset" ).change(function() {
if($('#settings_perset').find(":selected").val() != 'gui'){
@@ -2018,6 +2110,7 @@
main_api = 'kobold';
$('#max_context_block').css('display', 'block');
$('#amount_gen_block').css('display', 'block');
+ $('#world_info_block').css('display', 'flex');
}
if($('#main_api').find(":selected").val() == 'novel'){
$('#kobold_api').css("display", "none");
@@ -2025,7 +2118,10 @@
main_api = 'novel';
$('#max_context_block').css('display', 'none');
$('#amount_gen_block').css('display', 'none');
+ $('#world_info_block').css('display', 'none');
}
+
+ updateWorldStatus();
}
async function getUserAvatars(){
const response = await fetch("/getuseravatars", {
@@ -2050,7 +2146,100 @@
}
}
-
+
+ function updateWorldStatus() {
+ if($('#world_info_block').is(':visible') && kobold_world) {
+ $('#world_info_edit_button').show();
+ $('#world_status').show();
+
+ if (kobold_world_synced) {
+ $("#world_status_indicator").css("background-color", "green");
+ $("#world_status_text").html("Synchronized with KoboldAI")
+ }
+ else {
+ let statusText = online_status === 'no_connection'
+ ? "Waiting for connection"
+ : "Synchronizing...";
+
+ if (kobold_sync_failed) {
+ statusText = "Synchronization failed (see console)";
+ }
+
+ $("#world_status_text").html(statusText);
+ $("#world_status_indicator").css("background-color", "red");
+ }
+
+ if (kobold_is_united) {
+ $("#world_status_text").html('KoboldAI United detected. WI may not work as intended. If experiencing issues, please select "None". ');
+ }
+ } else {
+ $('#world_status').hide();
+ $('#world_info_edit_button').hide();
+ }
+ }
+
+ async function detectUnitedKobold() {
+ if (!api_server || main_api !== 'kobold') {
+ return;
+ }
+
+ // If we can reach Kobold's new ui, then it should be United branch
+ kobold_is_united = false;
+ try {
+ const kobold_united_ui2 = api_server.replace('/api', '/new_ui');
+ const response = await fetch(kobold_united_ui2, { method: 'HEAD'});
+
+ if (response.ok && response.status == 200) {
+ kobold_is_united = true;
+ }
+ }
+ catch {
+ // empty catch
+ }
+ }
+
+ async function syncKoboldWorldInfo(force) {
+ // Don't sync if no world selected or if synced and not forcing
+ if (online_status === 'no_connection' || (!kobold_world && !force) || (kobold_world_synced && !force)) {
+ updateWorldStatus();
+ return;
+ }
+
+ const response = await fetch("/synckoboldworld", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ "name": kobold_world })
+ });
+
+ if (response.ok) {
+ const syncData = await response.json();
+
+ if (syncData.ok) {
+ kobold_world_synced = true;
+ kobold_sync_failed = false;
+ }
+
+ if (syncData.busy) {
+ // console.log('Sync API is busy. Retrying in 3sec');
+ clearTimeout(timerKoboldSync);
+ timerKoboldSync = setTimeout(() => syncKoboldWorldInfo(force), 3000);
+ return;
+ }
+ } else {
+ kobold_sync_failed = true;
+ let responseLog = response.statusText;
+
+ try {
+ var responseBody = await response.text();
+ responseLog += ('\n' + responseBody);
+ } catch {
+ // empty catch
+ }
+ console.error(`Sync API response: ${responseLog}`);
+ }
+
+ updateWorldStatus();
+ }
$(document).on('input', '#temp', function() {
temp = $(this).val();
@@ -2269,7 +2458,6 @@
preset_settings = 'gui';
$("#settings_perset option[value=gui]").attr('selected', 'true');
}
-
}
//User
@@ -2282,6 +2470,26 @@
api_server = settings.api_server;
$('#api_url_text').val(api_server);
+
+ // world info settings
+ koboldai_world_names = data.koboldai_world_names?.length ? data.koboldai_world_names : [];
+
+ if(settings.kobold_world != undefined) {
+ if (koboldai_world_names.includes(settings.kobold_world)) {
+ kobold_world = settings.kobold_world;
+ kobold_world_synced = false;
+ kobold_sync_failed = false;
+ }
+ }
+
+ koboldai_world_names.forEach((item, i) => {
+ $('#world_info').append(`${item} `);
+ // preselect world if saved
+ if (item == kobold_world) {
+ $('#world_info').val(i).change();
+ }
+ });
+ // end world info settings
}
if(!is_checked_colab) isColab();
@@ -2319,7 +2527,8 @@
model_novel: model_novel,
temp_novel: temp_novel,
rep_pen_novel: rep_pen_novel,
- rep_pen_size_novel: rep_pen_size_novel
+ rep_pen_size_novel: rep_pen_size_novel,
+ kobold_world: kobold_world,
}),
beforeSend: function(){
@@ -2334,7 +2543,8 @@
if(type === 'change_name'){
location.reload();
}
-
+
+ syncKoboldWorldInfo(false);
},
error: function (jqXHR, exception) {
console.log(exception);
@@ -2752,8 +2962,421 @@
$('#load_select_chat_div').css('display', 'block');
});
+
+ //**************************WORLD INFO IMPORT EXPORT*************************//
+ $("#world_import_button" ).click(function() {
+ $("#world_import_file").click();
+ });
+
+ $("#world_import_file").on("change", function(e) {
+ var file = e.target.files[0];
+
+ if (!file) {
+ return;
+ }
+
+ const ext = file.name.match(/\.(\w+)$/);
+ if (!ext || (ext[1].toLowerCase() !== "json")){
+ return;
+ }
+
+ var formData = new FormData($("#form_world_import").get(0));
+
+ jQuery.ajax({
+ type: 'POST',
+ url: '/importworldinfo',
+ data: formData,
+ beforeSend: () => {},
+ cache: false,
+ contentType: false,
+ processData: false,
+ success: function(data){
+ if (data.name) {
+ imported_world_name = data.name;
+ updateWorldInfoList(imported_world_name);
+ }
+ },
+ error: (jqXHR, exception) => {},
+ });
+
+ // Will allow to select the same file twice in a row
+ $('#form_world_import').trigger("reset");
+ });
+
+ async function updateWorldInfoList(importedWorldName) {
+ var result = await fetch('/getsettings', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({})
+ });
+
+ if (result.ok) {
+ var data = await result.json();
+ koboldai_world_names = data.koboldai_world_names?.length ? data.koboldai_world_names : [];
+ $('#world_info').find('option[value!="None"]').remove();
+
+ koboldai_world_names.forEach((item, i) => {
+ $('#world_info').append(`${item} `);
+ });
+
+ if (importedWorldName) {
+ const indexOf = koboldai_world_names.indexOf(kobold_world);
+ $('#world_info').val(indexOf);
+
+ popup_type = 'world_imported';
+ callPopup('World imported successfully! Select it now? ');
+ }
+ }
+ }
+
+ function download(content, fileName, contentType) {
+ var a = document.createElement("a");
+ var file = new Blob([content], {type: contentType});
+ a.href = URL.createObjectURL(file);
+ a.download = fileName;
+ a.click();
+ }
+
+ // World Info Editor
+ async function showWorldEditor() {
+ is_world_edit_open = true;
+ $('#world_popup_name').val(kobold_world);
+ $('#world_popup').css('display', 'flex');
+
+ if (kobold_world) {
+ const response = await fetch("/getworldinfo", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ name: kobold_world })
+ });
+
+ if (response.ok) {
+ kobold_world_data = await response.json();
+ displayWorldEntries(kobold_world_data);
+ }
+ }
+ }
+
+ function hideWorldEditor() {
+ is_world_edit_open = false;
+ $('#world_popup').css('display', 'none');
+ syncKoboldWorldInfo(true);
+ }
+
+ function displayWorldEntries(data) {
+ $('#world_popup_entries_list').empty();
+
+ if (!data || !('entries' in data)) {
+ return;
+ }
+
+ for (const entryUid in data.entries) {
+ const entry = data.entries[entryUid];
+ appendWorldEntry(entry);
+ }
+ }
+
+ function appendWorldEntry(entry) {
+ const template = $('#entry_edit_template .world_entry').clone();
+ template.data('uid', entry.uid);
+
+ // key
+ const keyInput = template.find('input[name="key"]');
+ keyInput.data('uid', entry.uid);
+ keyInput.on('input', function () {
+ const uid = $(this).data('uid');
+ const value = $(this).val();
+ kobold_world_data.entries[uid].key = value.split(',').map(x => x.trim()).filter(x => x);
+ saveWorldInfo();
+ });
+ keyInput.val(entry.key.join(',')).trigger('input');
+
+ // keysecondary
+ const keySecondaryInput = template.find('input[name="keysecondary"]');
+ keySecondaryInput.data('uid', entry.uid);
+ keySecondaryInput.on('input', function() {
+ const uid = $(this).data('uid');
+ const value = $(this).val();
+ kobold_world_data.entries[uid].keysecondary = value.split(',').map(x => x.trim()).filter(x => x);
+ saveWorldInfo();
+ });
+ keySecondaryInput.val(entry.keysecondary.join(',')).trigger('input');
+
+ // comment
+ const commentInput = template.find('input[name="comment"]');
+ commentInput.data('uid', entry.uid);
+ commentInput.on('input', function() {
+ const uid = $(this).data('uid');
+ const value = $(this).val();
+ kobold_world_data.entries[uid].comment = value;
+ saveWorldInfo();
+ });
+ commentInput.val(entry.comment).trigger('input');
+
+ // content
+ const contentInput = template.find('textarea[name="content"]');
+ contentInput.data('uid', entry.uid);
+ contentInput.on('input', function() {
+ const uid = $(this).data('uid');
+ const value = $(this).val();
+ kobold_world_data.entries[uid].content = value;
+ saveWorldInfo();
+
+ // count tokens
+ const numberOfTokens = encode(value).length;
+ $(this).closest('.world_entry').find('.world_entry_form_token_counter').html(numberOfTokens);
+ });
+ contentInput.val(entry.content).trigger('input');
+
+ // selective
+ const selectiveInput = template.find('input[name="selective"]')
+ selectiveInput.data('uid', entry.uid);
+ selectiveInput.on('input', function() {
+ const uid = $(this).data('uid');
+ const value = $(this).prop('checked');
+ kobold_world_data.entries[uid].selective = value;
+ saveWorldInfo();
+
+ const keysecondary = $(this).closest('.world_entry').find('.keysecondary');
+ value ? keysecondary.show() : keysecondary.hide();
+ });
+ selectiveInput.prop('checked', entry.selective).trigger('input');
+ selectiveInput.siblings('.checkbox_fancy').click(function() {
+ $(this).siblings('input').click();
+ });
+
+
+ // constant
+ const constantInput = template.find('input[name="constant"]')
+ constantInput.data('uid', entry.uid);
+ constantInput.on('input', function() {
+ const uid = $(this).data('uid');
+ const value = $(this).prop('checked');
+ kobold_world_data.entries[uid].constant = value;
+ saveWorldInfo();
+ });
+ constantInput.prop('checked', entry.constant).trigger('input');
+ constantInput.siblings('.checkbox_fancy').click(function() {
+ $(this).siblings('input').click();
+ });
+
+ // display uid
+ template.find('.world_entry_form_uid_value').html(entry.uid);
+
+ // delete button
+ const deleteButton = template.find('input.delete_entry_button');
+ deleteButton.data('uid', entry.uid);
+ deleteButton.on('click', function() {
+ const uid = $(this).data('uid');
+ deleteWorldInfoEntry(uid);
+ $(this).closest('.world_entry').remove();
+ saveWorldInfo();
+ });
+
+ template.appendTo('#world_popup_entries_list');
+ return template;
+ }
+
+ async function deleteWorldInfoEntry(uid) {
+ if (!kobold_world_data || !('entries' in kobold_world_data)) {
+ return;
+ }
+
+ delete kobold_world_data.entries[uid];
+
+ if ('folders' in kobold_world_data) {
+ for (const folderName in kobold_world_data.folders) {
+ const folder = kobold_world_data.folders[folderName]
+ const index = folder.indexOf(Number(uid));
+
+ if (index !== -1) {
+ folder.splice(index, 1);
+ }
+ }
+ }
+ }
+
+ function createWorldInfoEntry() {
+ const newEntryTemplate = {
+ key: [],
+ keysecondary: [],
+ comment: '',
+ content: '',
+ constant: false,
+ selective: false,
+ };
+ const newUid = getFreeWorldEntryUid();
+
+ if (!Number.isInteger(newUid)) {
+ console.error("Couldn't assign UID to a new entry");
+ return;
+ }
+
+ const newEntry = { uid: newUid, ...newEntryTemplate };
+ kobold_world_data.entries[newUid] = newEntry;
+
+ if ('folders' in kobold_world_data) {
+ if (kobold_world in kobold_world_data.folders && Array.isArray(kobold_world_data.folders)) {
+ kobold_world_data.folders[kobold_world].push(newUid);
+ } else {
+ kobold_world_data.folders[kobold_world] = [newUid];
+ }
+ }
+
+ const entryTemplate = appendWorldEntry(newEntry);
+ entryTemplate.get(0).scrollIntoView({behavior: 'smooth'});
+ }
+
+ async function saveWorldInfo(immediately) {
+ if (!kobold_world || !kobold_world_data) {
+ return;
+ }
+
+ async function _save() {
+ const response = await fetch("/editworldinfo", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ name: kobold_world, data: kobold_world_data })
+ });
+
+ if (response.ok) {
+ kobold_world_synced = false;
+ }
+ }
+
+ if (immediately) {
+ return await _save();
+ }
+
+ clearTimeout(timerWorldSave);
+ timerWorldSave = setTimeout(async () => await _save(), durationSaveEdit);
+ }
+
+ async function renameWorldInfo() {
+ const oldName = kobold_world;
+ const newName = $('#world_popup_name').val();
+
+ if (oldName === newName) {
+ return;
+ }
+
+ kobold_world = newName;
+ await saveWorldInfo(true);
+ await deleteWorldInfo(oldName, newName);
+ }
+
+ async function deleteWorldInfo(worldInfoName, selectWorldName) {
+ if (!koboldai_world_names.includes(worldInfoName)) {
+ return;
+ }
+
+ const response = await fetch("/deleteworldinfo", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ name: worldInfoName })
+ });
+
+ if (response.ok) {
+ await updateWorldInfoList();
+
+ const selectedIndex = koboldai_world_names.indexOf(selectWorldName);
+ if (selectedIndex !== -1) {
+ $('#world_info').val(selectedIndex).change();
+ }
+ else {
+ $('#world_info').val('None').change();
+ }
+
+ hideWorldEditor();
+ }
+ }
+
+ function getFreeWorldEntryUid() {
+ if (!kobold_world_data || !('entries' in kobold_world_data)) {
+ return null;
+ }
+
+ const MAX_UID = 1_000_000; // <- should be safe enough :)
+ for (let uid = 0; uid < MAX_UID; uid++) {
+ if (uid in kobold_world_data.entries) {
+ continue;
+ }
+ return uid;
+ }
+
+ return null;
+ }
+
+ function getFreeWorldName() {
+ const MAX_FREE_NAME = 100_000;
+ for (let index = 1; index < MAX_FREE_NAME; index++) {
+ const newName = `New World (${index})`;
+ if (koboldai_world_names.includes(newName)) {
+ continue;
+ }
+ return newName;
+ }
+
+ return undefined;
+ }
+
+ async function createNewWorldInfo() {
+ const worldInfoTemplate = { folders: {}, entries: {} };
+ const worldInfoName = getFreeWorldName();
+
+ if (!worldInfoName) {
+ return;
+ }
+
+ kobold_world = worldInfoName;
+ kobold_world_data = { ...worldInfoTemplate };
+ await saveWorldInfo(true);
+ await updateWorldInfoList();
+
+ const selectedIndex = koboldai_world_names.indexOf(worldInfoName);
+ if (selectedIndex !== -1) {
+ $('#world_info').val(selectedIndex).change();
+ }
+ else {
+ $('#world_info').val('None').change();
+ }
+ }
+
+ $('#world_info_edit_button').click(() => {
+ is_world_edit_open ? hideWorldEditor() : showWorldEditor();
+ });
+
+ $('#world_popup_export').click(() => {
+ if (kobold_world && kobold_world_data) {
+ const jsonValue = JSON.stringify(kobold_world_data);
+ const fileName = `${kobold_world}.json`;
+ download(jsonValue, fileName, 'application/json');
+ }
+ });
+
+ $('#world_popup_delete').click(() => {
+ popup_type = 'del_world';
+ callPopup('Delete the World Info? ');
+ });
+
+ $('#world_popup_new').click(() => {
+ createWorldInfoEntry();
+ });
+
+ $('#world_cross').click(() => {
+ hideWorldEditor();
+ });
+
+ $('#world_popup_name_button').click(() => {
+ renameWorldInfo();
+ });
+
+ $('#world_create_button').click(() => {
+ createNewWorldInfo();
+ });
});
+
Tavern.AI
@@ -2809,6 +3432,95 @@
+
+
+