mirror of
https://github.com/KoboldAI/KoboldAI-Client.git
synced 2025-06-05 21:59:24 +02:00
Merge pull request #416 from one-some/wi-fixes
(mostly) wi fixes and polish
This commit is contained in:
13
aiserver.py
13
aiserver.py
@@ -4396,8 +4396,8 @@ def requestwi():
|
|||||||
# and items in different folders are sorted based on the order of the folders
|
# and items in different folders are sorted based on the order of the folders
|
||||||
#==================================================================#
|
#==================================================================#
|
||||||
def stablesortwi():
|
def stablesortwi():
|
||||||
mapping = {uid: index for index, uid in enumerate(koboldai_vars.wifolders_l)}
|
mapping = {int(uid): index for index, uid in enumerate(koboldai_vars.wifolders_l)}
|
||||||
koboldai_vars.worldinfo.sort(key=lambda x: mapping[str(x["folder"])] if x["folder"] is not None else float("inf"))
|
koboldai_vars.worldinfo.sort(key=lambda x: mapping[int(x["folder"])] if x["folder"] is not None else float("inf"))
|
||||||
last_folder = ...
|
last_folder = ...
|
||||||
last_wi = None
|
last_wi = None
|
||||||
for i, wi in enumerate(koboldai_vars.worldinfo):
|
for i, wi in enumerate(koboldai_vars.worldinfo):
|
||||||
@@ -6692,11 +6692,18 @@ def UI_2_set_wi_image(uid):
|
|||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
try:
|
||||||
# Otherwise assign image
|
# Otherwise assign image
|
||||||
with open(path, "wb") as file:
|
with open(path, "wb") as file:
|
||||||
file.write(data)
|
file.write(data)
|
||||||
|
except FileNotFoundError:
|
||||||
|
show_error_notification(
|
||||||
|
"Unable to write image",
|
||||||
|
"Please save the game before uploading images."
|
||||||
|
)
|
||||||
|
return ":(", 500
|
||||||
koboldai_vars.gamesaved = False
|
koboldai_vars.gamesaved = False
|
||||||
return ":)"
|
return ":)", 200
|
||||||
|
|
||||||
@app.route("/get_wi_image/<int(signed=True):uid>", methods=["GET"])
|
@app.route("/get_wi_image/<int(signed=True):uid>", methods=["GET"])
|
||||||
@require_allowed_ip
|
@require_allowed_ip
|
||||||
|
@@ -296,7 +296,7 @@ gensettingstf = [
|
|||||||
"max": 1,
|
"max": 1,
|
||||||
"step": 1,
|
"step": 1,
|
||||||
"default": 0,
|
"default": 0,
|
||||||
"tooltip": "Scans the AI's output for World Info keys as it is generating the one.",
|
"tooltip": "Look for World Info keys in the AI's response while it is still being generated.",
|
||||||
"menu_path": "World Info",
|
"menu_path": "World Info",
|
||||||
"sub_path": "",
|
"sub_path": "",
|
||||||
"classname": "story",
|
"classname": "story",
|
||||||
@@ -756,7 +756,7 @@ gensettingstf = [
|
|||||||
"max": 1,
|
"max": 1,
|
||||||
"step": 1,
|
"step": 1,
|
||||||
"default": 0,
|
"default": 0,
|
||||||
"tooltip": "If enabled, experimental features will be displayed in the UI.",
|
"tooltip": "If enabled, experimental features will be displayed in the UI. Note: These features have been determined to be too unstable for standard use, and may corrupt your data. You're on your own from here.",
|
||||||
"menu_path": "Interface",
|
"menu_path": "Interface",
|
||||||
"sub_path": "UI",
|
"sub_path": "UI",
|
||||||
"classname": "system",
|
"classname": "system",
|
||||||
|
@@ -637,7 +637,12 @@ class InferenceModel:
|
|||||||
)
|
)
|
||||||
|
|
||||||
time_end = round(time.time() - time_start, 2)
|
time_end = round(time.time() - time_start, 2)
|
||||||
|
|
||||||
|
try:
|
||||||
tokens_per_second = round(len(result.encoded[0]) / time_end, 2)
|
tokens_per_second = round(len(result.encoded[0]) / time_end, 2)
|
||||||
|
except ZeroDivisionError:
|
||||||
|
# Introducing KoboldAI's fastest model: ReadOnly!
|
||||||
|
tokens_per_second = 0
|
||||||
|
|
||||||
if not utils.koboldai_vars.quiet:
|
if not utils.koboldai_vars.quiet:
|
||||||
logger.info(
|
logger.info(
|
||||||
|
@@ -1,12 +1,10 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import torch
|
import torch
|
||||||
import requests
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from typing import List, Optional, Union
|
from typing import List, Optional, Union
|
||||||
|
|
||||||
import utils
|
import utils
|
||||||
from logger import logger
|
|
||||||
from modeling.inference_model import (
|
from modeling.inference_model import (
|
||||||
GenerationResult,
|
GenerationResult,
|
||||||
GenerationSettings,
|
GenerationSettings,
|
||||||
@@ -15,26 +13,43 @@ from modeling.inference_model import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
model_backend_name = "Read Only"
|
model_backend_name = "Read Only"
|
||||||
model_backend_type = "Read Only" #This should be a generic name in case multiple model backends are compatible (think Hugging Face Custom and Basic Hugging Face)
|
model_backend_type = "Read Only" # This should be a generic name in case multiple model backends are compatible (think Hugging Face Custom and Basic Hugging Face)
|
||||||
|
|
||||||
class BasicAPIException(Exception):
|
|
||||||
"""To be used for errors when using the Basic API as an interface."""
|
class DummyHFTokenizerOut:
|
||||||
|
input_ids = np.array([[]])
|
||||||
|
|
||||||
|
|
||||||
|
class FacadeTokenizer:
|
||||||
|
def __init__(self):
|
||||||
|
self._koboldai_header = []
|
||||||
|
|
||||||
|
def decode(self, _input):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def encode(self, input_text):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def __call__(self, *args, **kwargs) -> DummyHFTokenizerOut:
|
||||||
|
return DummyHFTokenizerOut()
|
||||||
|
|
||||||
|
|
||||||
class model_backend(InferenceModel):
|
class model_backend(InferenceModel):
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
# Do not allow API to be served over the API
|
# Do not allow ReadOnly to be served over the API
|
||||||
self.capabilties = ModelCapabilities(api_host=False)
|
self.capabilties = ModelCapabilities(api_host=False)
|
||||||
self.tokenizer = self._tokenizer()
|
self.tokenizer: FacadeTokenizer = None
|
||||||
self.model = None
|
self.model = None
|
||||||
self.model_name = "Read Only"
|
self.model_name = "Read Only"
|
||||||
|
|
||||||
def is_valid(self, model_name, model_path, menu_path):
|
def is_valid(self, model_name, model_path, menu_path):
|
||||||
return model_name == "ReadOnly"
|
return model_name == "ReadOnly"
|
||||||
|
|
||||||
def get_requested_parameters(self, model_name, model_path, menu_path, parameters = {}):
|
def get_requested_parameters(
|
||||||
|
self, model_name, model_path, menu_path, parameters={}
|
||||||
|
):
|
||||||
requested_parameters = []
|
requested_parameters = []
|
||||||
return requested_parameters
|
return requested_parameters
|
||||||
|
|
||||||
@@ -47,16 +62,8 @@ class model_backend(InferenceModel):
|
|||||||
def _initialize_model(self):
|
def _initialize_model(self):
|
||||||
return
|
return
|
||||||
|
|
||||||
class _tokenizer():
|
|
||||||
def __init__(self):
|
|
||||||
self._koboldai_header = []
|
|
||||||
def decode(self, _input):
|
|
||||||
return ""
|
|
||||||
def encode(self, input_text):
|
|
||||||
return []
|
|
||||||
|
|
||||||
def _load(self, save_model: bool = False, initial_load: bool = False) -> None:
|
def _load(self, save_model: bool = False, initial_load: bool = False) -> None:
|
||||||
self.tokenizer = self.tokenizer
|
self.tokenizer = FacadeTokenizer()
|
||||||
self.model = None
|
self.model = None
|
||||||
utils.koboldai_vars.noai = True
|
utils.koboldai_vars.noai = True
|
||||||
|
|
||||||
@@ -72,7 +79,7 @@ class model_backend(InferenceModel):
|
|||||||
):
|
):
|
||||||
return GenerationResult(
|
return GenerationResult(
|
||||||
model=self,
|
model=self,
|
||||||
out_batches=np.array([]),
|
out_batches=np.array([[]]),
|
||||||
prompt=prompt_tokens,
|
prompt=prompt_tokens,
|
||||||
is_whole_generation=True,
|
is_whole_generation=True,
|
||||||
single_line=single_line,
|
single_line=single_line,
|
||||||
|
@@ -1259,17 +1259,46 @@ td.server_vars {
|
|||||||
.world_info_label_container > .generate-button:hover { opacity: 1.0; }
|
.world_info_label_container > .generate-button:hover { opacity: 1.0; }
|
||||||
|
|
||||||
.tag {
|
.tag {
|
||||||
|
display: inline-block;
|
||||||
background-color: var(--wi_tag_color);
|
background-color: var(--wi_tag_color);
|
||||||
color: var(--wi_tag_text_color);
|
color: var(--wi_tag_text_color);
|
||||||
|
|
||||||
|
margin-right: 3px;
|
||||||
|
margin-top: 3px;
|
||||||
|
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
margin-right: 2px;
|
padding-left: 3px;
|
||||||
|
padding-right: 3px;
|
||||||
|
|
||||||
border-radius: var(--radius_wi_card);
|
border-radius: var(--radius_wi_card);
|
||||||
border: solid;
|
}
|
||||||
border-color: var(--wi_tag_color);
|
|
||||||
|
.tag .tag_button {
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0.4;
|
||||||
|
font-size: 16px;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tag .delete_icon {
|
.tag .delete_icon {
|
||||||
cursor: pointer;
|
top: 3px;
|
||||||
|
right: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag .add_icon {
|
||||||
|
top: 3px;
|
||||||
|
right: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag .tag_text {
|
||||||
|
display: inline-block;
|
||||||
|
outline: none;
|
||||||
|
position: relative;
|
||||||
|
right: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder_tag .tag_text:empty {
|
||||||
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.oi[folder] {
|
.oi[folder] {
|
||||||
@@ -2851,6 +2880,10 @@ body {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#welcome_text a {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
.welcome_text {
|
.welcome_text {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -3569,10 +3602,15 @@ h2 .material-icons-outlined {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.section_header {
|
.section_header {
|
||||||
|
font-weight: bold;
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.story_category_area > * > label {
|
||||||
|
user-select: none
|
||||||
|
}
|
||||||
|
|
||||||
.help_text {
|
.help_text {
|
||||||
margin-left: 6px;
|
margin-left: 6px;
|
||||||
margin-bottom: 0.7em;
|
margin-bottom: 0.7em;
|
||||||
|
@@ -23,7 +23,13 @@ socket.on('error_popup', function(data){error_popup(data);});
|
|||||||
socket.on("world_info_entry", function(data){process_world_info_entry(data);});
|
socket.on("world_info_entry", function(data){process_world_info_entry(data);});
|
||||||
socket.on("world_info_entry_used_in_game", function(data){world_info_entry_used_in_game(data);});
|
socket.on("world_info_entry_used_in_game", function(data){world_info_entry_used_in_game(data);});
|
||||||
socket.on("world_info_folder", function(data){world_info_folder(data);});
|
socket.on("world_info_folder", function(data){world_info_folder(data);});
|
||||||
socket.on("delete_new_world_info_entry", function(data){document.getElementById("world_info_-1").remove();});
|
socket.on("delete_new_world_info_entry", function(data) {
|
||||||
|
const card = $el("#world_info_-1");
|
||||||
|
// Prevent weird race condition/strange event call order where blur event
|
||||||
|
// fires before removal is finished on Chrome
|
||||||
|
card.removing = true
|
||||||
|
card.remove();
|
||||||
|
});
|
||||||
socket.on("delete_world_info_entry", function(data){document.getElementById("world_info_"+data).remove();});
|
socket.on("delete_world_info_entry", function(data){document.getElementById("world_info_"+data).remove();});
|
||||||
socket.on("delete_world_info_folder", function(data){document.getElementById("world_info_folder_"+data).remove();});
|
socket.on("delete_world_info_folder", function(data){document.getElementById("world_info_folder_"+data).remove();});
|
||||||
socket.on("error", function(data){show_error_message(data);});
|
socket.on("error", function(data){show_error_message(data);});
|
||||||
@@ -87,6 +93,7 @@ var initial_socketio_connection_occured = false;
|
|||||||
var selected_model_data;
|
var selected_model_data;
|
||||||
var supported_gen_modes = [];
|
var supported_gen_modes = [];
|
||||||
var privacy_mode_enabled = false;
|
var privacy_mode_enabled = false;
|
||||||
|
var attention_wanting_wi_bar = null;
|
||||||
var ai_busy = false;
|
var ai_busy = false;
|
||||||
var can_show_options = false;
|
var can_show_options = false;
|
||||||
|
|
||||||
@@ -1281,7 +1288,7 @@ function redrawPopup() {
|
|||||||
delete_icon.setAttribute("tooltip", "Delete");
|
delete_icon.setAttribute("tooltip", "Delete");
|
||||||
delete_icon.id = row.path;
|
delete_icon.id = row.path;
|
||||||
delete_icon.setAttribute("folder", row.isFolder);
|
delete_icon.setAttribute("folder", row.isFolder);
|
||||||
delete_icon.onclick = function () {
|
delete_icon.addEventListener("click", function(event) {
|
||||||
const message = this.getAttribute("folder") == "true" ? "Do you really want to delete this folder and ALL files under it?" : "Do you really want to delete this file?";
|
const message = this.getAttribute("folder") == "true" ? "Do you really want to delete this folder and ALL files under it?" : "Do you really want to delete this file?";
|
||||||
const delId = this.id;
|
const delId = this.id;
|
||||||
|
|
||||||
@@ -1291,9 +1298,11 @@ function redrawPopup() {
|
|||||||
denyText="I've changed my mind!",
|
denyText="I've changed my mind!",
|
||||||
confirmCallback=function() {
|
confirmCallback=function() {
|
||||||
socket.emit("popup_delete", delId);
|
socket.emit("popup_delete", delId);
|
||||||
}
|
},
|
||||||
|
null,
|
||||||
|
event.shiftKey
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
icon_area.append(delete_icon);
|
icon_area.append(delete_icon);
|
||||||
tr.append(icon_area);
|
tr.append(icon_area);
|
||||||
@@ -2203,6 +2212,7 @@ function world_info_entry(data) {
|
|||||||
} else {
|
} else {
|
||||||
world_info_card.classList.remove("used_in_game");
|
world_info_card.classList.remove("used_in_game");
|
||||||
}
|
}
|
||||||
|
|
||||||
const title = world_info_card.querySelector('.world_info_title');
|
const title = world_info_card.querySelector('.world_info_title');
|
||||||
title.id = "world_info_title_"+data.uid;
|
title.id = "world_info_title_"+data.uid;
|
||||||
title.textContent = data.title;
|
title.textContent = data.title;
|
||||||
@@ -2210,7 +2220,7 @@ function world_info_entry(data) {
|
|||||||
title.setAttribute("original_text", data.title);
|
title.setAttribute("original_text", data.title);
|
||||||
title.setAttribute("contenteditable", true);
|
title.setAttribute("contenteditable", true);
|
||||||
title.classList.remove("pulse");
|
title.classList.remove("pulse");
|
||||||
title.ondragstart=function() {event.preventDefault();event.stopPropagation();};
|
title.ondragstart=function(event) {event.preventDefault();event.stopPropagation();};
|
||||||
title.onblur = function () {
|
title.onblur = function () {
|
||||||
this.parentElement.parentElement.setAttribute('draggable', 'true');
|
this.parentElement.parentElement.setAttribute('draggable', 'true');
|
||||||
this.setAttribute('draggable', 'true');
|
this.setAttribute('draggable', 'true');
|
||||||
@@ -2220,20 +2230,31 @@ function world_info_entry(data) {
|
|||||||
this.classList.add("pulse");
|
this.classList.add("pulse");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
world_info_card.addEventListener('dragstart', dragStart);
|
|
||||||
world_info_card.addEventListener('dragend', dragend);
|
title.addEventListener("keydown", function(event) {
|
||||||
|
if (event.key === "Enter") {
|
||||||
|
event.preventDefault();
|
||||||
|
this.blur();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
title.addEventListener('dragenter', dragEnter)
|
title.addEventListener('dragenter', dragEnter)
|
||||||
title.addEventListener('dragover', dragOver);
|
title.addEventListener('dragover', dragOver);
|
||||||
title.addEventListener('dragleave', dragLeave);
|
title.addEventListener('dragleave', dragLeave);
|
||||||
title.addEventListener('drop', drop);
|
title.addEventListener('drop', drop);
|
||||||
delete_icon = world_info_card.querySelector('.world_info_delete');
|
|
||||||
|
world_info_card.addEventListener('dragstart', dragStart);
|
||||||
|
world_info_card.addEventListener('dragend', dragend);
|
||||||
|
|
||||||
|
const delete_icon = world_info_card.querySelector('.world_info_delete');
|
||||||
delete_icon.id = "world_info_delete_"+data.uid;
|
delete_icon.id = "world_info_delete_"+data.uid;
|
||||||
delete_icon.setAttribute("uid", data.uid);
|
delete_icon.setAttribute("uid", data.uid);
|
||||||
delete_icon.setAttribute("wi-title", data.title);
|
delete_icon.setAttribute("wi-title", data.title);
|
||||||
delete_icon.onclick = function () {
|
delete_icon.addEventListener("click", function (event) {
|
||||||
const wiTitle = this.getAttribute("wi-title");
|
const wiTitle = this.getAttribute("wi-title");
|
||||||
const wiUid = parseInt(this.getAttribute("uid"));
|
const wiUid = parseInt(this.getAttribute("uid"));
|
||||||
const wiElement = this.parentElement.parentElement;
|
const wiElement = this.parentElement.parentElement;
|
||||||
|
|
||||||
deleteConfirmation([
|
deleteConfirmation([
|
||||||
{text: "You're about to delete World Info entry "},
|
{text: "You're about to delete World Info entry "},
|
||||||
{text: wiTitle, format: "bold"},
|
{text: wiTitle, format: "bold"},
|
||||||
@@ -2247,9 +2268,11 @@ function world_info_entry(data) {
|
|||||||
} else {
|
} else {
|
||||||
socket.emit("delete_world_info", wiUid);
|
socket.emit("delete_world_info", wiUid);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
null,
|
||||||
|
event.shiftKey
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
const wiImgContainer = world_info_card.querySelector(".world_info_image_container");
|
const wiImgContainer = world_info_card.querySelector(".world_info_image_container");
|
||||||
const wiImg = wiImgContainer.querySelector(".world_info_image");
|
const wiImg = wiImgContainer.querySelector(".world_info_image");
|
||||||
@@ -2342,15 +2365,16 @@ function world_info_entry(data) {
|
|||||||
this.classList.add("pulse");
|
this.classList.add("pulse");
|
||||||
})
|
})
|
||||||
|
|
||||||
tags = world_info_card.querySelector('.world_info_tag_primary_area');
|
const tags = world_info_card.querySelector('.world_info_tag_primary_area');
|
||||||
tags.id = "world_info_tags_"+data.uid;
|
tags.id = "world_info_tags_"+data.uid;
|
||||||
//add tag content here
|
//add tag content here
|
||||||
add_tags(tags, data);
|
add_tags(tags, data, "primary");
|
||||||
|
|
||||||
secondarytags = world_info_card.querySelector('.world_info_tag_secondary_area');
|
const secondarytags = world_info_card.querySelector('.world_info_tag_secondary_area');
|
||||||
secondarytags.id = "world_info_secondtags_"+data.uid;
|
secondarytags.id = "world_info_secondtags_"+data.uid;
|
||||||
//add second tag content here
|
//add second tag content here
|
||||||
add_secondary_tags(secondarytags, data);
|
add_tags(secondarytags, data, "secondary");
|
||||||
|
|
||||||
//w++ toggle
|
//w++ toggle
|
||||||
wpp_toggle_area = world_info_card.querySelector('.world_info_wpp_toggle_area');
|
wpp_toggle_area = world_info_card.querySelector('.world_info_wpp_toggle_area');
|
||||||
wpp_toggle_area.id = "world_info_wpp_toggle_area_"+data.uid;
|
wpp_toggle_area.id = "world_info_wpp_toggle_area_"+data.uid;
|
||||||
@@ -2723,8 +2747,9 @@ function world_info_folder(data) {
|
|||||||
delete_button.classList.add("cursor");
|
delete_button.classList.add("cursor");
|
||||||
delete_button.setAttribute("folder", folder_name);
|
delete_button.setAttribute("folder", folder_name);
|
||||||
delete_button.textContent = "delete";
|
delete_button.textContent = "delete";
|
||||||
delete_button.onclick = function () {
|
delete_button.addEventListener("click", function (event) {
|
||||||
const folderName = this.getAttribute("folder");
|
const folderName = this.getAttribute("folder");
|
||||||
|
|
||||||
deleteConfirmation([
|
deleteConfirmation([
|
||||||
{text: "You're about to delete World Info folder "},
|
{text: "You're about to delete World Info folder "},
|
||||||
{text: folderName, format: "bold"},
|
{text: folderName, format: "bold"},
|
||||||
@@ -2734,9 +2759,11 @@ function world_info_folder(data) {
|
|||||||
],
|
],
|
||||||
confirmText="Go for it.",
|
confirmText="Go for it.",
|
||||||
denyText="I've changed my mind!",
|
denyText="I've changed my mind!",
|
||||||
confirmCallback=function() { socket.emit("delete_wi_folder", folderName); }
|
confirmCallback=function() { socket.emit("delete_wi_folder", folderName); },
|
||||||
|
null,
|
||||||
|
event.shiftKey
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
delete_button.classList.add("delete");
|
delete_button.classList.add("delete");
|
||||||
title.append(delete_button);
|
title.append(delete_button);
|
||||||
|
|
||||||
@@ -3241,6 +3268,8 @@ function upload_file_without_save(file_box) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function send_world_info(uid) {
|
function send_world_info(uid) {
|
||||||
|
const cardEl = document.getElementById(`world_info_${uid}`);
|
||||||
|
if (cardEl.removing) return;
|
||||||
socket.emit("edit_world_info", world_info_data[uid]);
|
socket.emit("edit_world_info", world_info_data[uid]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4443,159 +4472,137 @@ function removeA(arr) {
|
|||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
function add_tags(tags, data) {
|
function create_tag_element(tagText, uid, tagType) {
|
||||||
while (tags.firstChild) {
|
// tagText is string, or null for empty tag at end.
|
||||||
tags.removeChild(tags.firstChild);
|
// barType should be "primary" or "secondary"
|
||||||
}
|
const isPlaceholderTag = tagText === null;
|
||||||
for (tag of data.key) {
|
|
||||||
tag_item = document.createElement("span");
|
const wiCardEl = document.querySelector(`.world_info_card[uid="${uid}"]`)
|
||||||
tag_item.classList.add("tag");
|
const keyField = {primary: "key", secondary: "keysecondary"}[tagType];
|
||||||
x = document.createElement("span");
|
const tagClassFragment = {primary: "tags", primary: "secondtags"}[tagType];
|
||||||
x.textContent = "x ";
|
|
||||||
x.classList.add("delete_icon");
|
const tagEl = document.createElement("span");
|
||||||
x.setAttribute("uid", data.uid);
|
tagEl.classList.add("tag");
|
||||||
x.setAttribute("tag", tag);
|
if (isPlaceholderTag) tagEl.classList.add("placeholder_tag");
|
||||||
x.onclick = function () {
|
|
||||||
removeA(world_info_data[this.getAttribute('uid')]['key'], this.getAttribute('tag'));
|
const xEl = document.createElement("span");
|
||||||
send_world_info(this.getAttribute('uid'));
|
xEl.classList.add("material-icons-outlined");
|
||||||
this.classList.add("pulse");
|
xEl.classList.add("tag_button");
|
||||||
};
|
|
||||||
text = document.createElement("span");
|
if (!isPlaceholderTag) {
|
||||||
text.textContent = tag;
|
xEl.classList.add("delete_icon");
|
||||||
text.setAttribute("contenteditable", true);
|
xEl.textContent = "close";
|
||||||
text.setAttribute("uid", data.uid);
|
|
||||||
text.setAttribute("tag", tag);
|
|
||||||
text.id = "world_info_tags_text_"+data.uid+"_"+tag;
|
|
||||||
text.ondragstart=function() {event.preventDefault();event.stopPropagation();};
|
|
||||||
text.setAttribute("draggable", "true");
|
|
||||||
text.onfocus=function() {this.parentElement.parentElement.parentElement.setAttribute('draggable', 'false');this.setAttribute('draggable', 'false');};
|
|
||||||
text.onblur = function () {
|
|
||||||
this.parentElement.parentElement.parentElement.setAttribute('draggable', 'true');
|
|
||||||
this.setAttribute('draggable', 'true');
|
|
||||||
for (var i = 0; i < world_info_data[this.getAttribute('uid')]['key'].length; i++) {
|
|
||||||
if (world_info_data[this.getAttribute('uid')]['key'][i] == this.getAttribute("tag")) {
|
|
||||||
world_info_data[this.getAttribute('uid')]['key'][i] = this.textContent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
send_world_info(this.getAttribute('uid'));
|
|
||||||
this.classList.add("pulse");
|
|
||||||
};
|
|
||||||
tag_item.append(x);
|
|
||||||
tag_item.append(text);
|
|
||||||
tag_item.id = "world_info_tags_"+data.uid+"_"+tag;
|
|
||||||
tags.append(tag_item);
|
|
||||||
}
|
|
||||||
//add the blank tag
|
|
||||||
tag_item = document.createElement("span");
|
|
||||||
tag_item.classList.add("tag");
|
|
||||||
x = document.createElement("span");
|
|
||||||
x.textContent = "+ ";
|
|
||||||
tag_item.append(x);
|
|
||||||
text = document.createElement("span");
|
|
||||||
text.classList.add("rawtext");
|
|
||||||
text.textContent = " ";
|
|
||||||
text.setAttribute("uid", data.uid);
|
|
||||||
text.setAttribute("contenteditable", true);
|
|
||||||
text.id = "world_info_tags_text_"+data.uid+"_blank";
|
|
||||||
text.ondragstart=function() {event.preventDefault();event.stopPropagation();};
|
|
||||||
text.setAttribute("draggable", "true");
|
|
||||||
text.onfocus=function() {this.parentElement.parentElement.parentElement.setAttribute('draggable', 'false');this.setAttribute('draggable', 'false');};
|
|
||||||
text.onblur = function () {
|
|
||||||
this.parentElement.parentElement.parentElement.setAttribute('draggable', 'true');
|
|
||||||
this.setAttribute('draggable', 'true');
|
|
||||||
if (this.textContent.trim() != "") {
|
|
||||||
//console.log(this.textContent);
|
|
||||||
on_new_wi_item = this.id;
|
|
||||||
world_info_data[this.getAttribute('uid')]['key'].push(this.textContent);
|
|
||||||
send_world_info(this.getAttribute('uid'));
|
|
||||||
this.classList.add("pulse");
|
|
||||||
} else {
|
} else {
|
||||||
this.textContent = " ";
|
xEl.classList.add("add_icon");
|
||||||
|
xEl.textContent = "add";
|
||||||
}
|
}
|
||||||
};
|
|
||||||
text.onclick = function () {
|
xEl.setAttribute("uid", uid);
|
||||||
this.textContent = "";
|
xEl.setAttribute("tag", tagText);
|
||||||
};
|
xEl.addEventListener("click", function() {
|
||||||
tag_item.append(text);
|
removeA(
|
||||||
tag_item.id = "world_info_secondtags_"+data.uid+"_new";
|
world_info_data[uid][keyField],
|
||||||
tags.append(tag_item);
|
tagText
|
||||||
|
);
|
||||||
|
send_world_info(uid);
|
||||||
|
this.classList.add("pulse");
|
||||||
|
});
|
||||||
|
|
||||||
|
const textEl = document.createElement("span");
|
||||||
|
textEl.classList.add("tag_text");
|
||||||
|
textEl.textContent = tagText;
|
||||||
|
|
||||||
|
textEl.setAttribute("data-placeholder", "Tag")
|
||||||
|
textEl.setAttribute("contenteditable", true);
|
||||||
|
textEl.setAttribute("uid", uid);
|
||||||
|
textEl.setAttribute("tag", tagText);
|
||||||
|
textEl.setAttribute("draggable", "true");
|
||||||
|
textEl.id = `world_info_${tagClassFragment}_text_${uid}_${tagText || "blank"}`;
|
||||||
|
|
||||||
|
textEl.addEventListener("dragstart", function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
});
|
||||||
|
|
||||||
|
textEl.addEventListener("focus", function(event) {
|
||||||
|
wiCardEl.setAttribute('draggable', 'false');
|
||||||
|
this.setAttribute('draggable', 'false');
|
||||||
|
});
|
||||||
|
|
||||||
|
textEl.addEventListener("blur", function () {
|
||||||
|
wiCardEl.setAttribute('draggable', 'true');
|
||||||
|
this.setAttribute('draggable', 'true');
|
||||||
|
|
||||||
|
if (!isPlaceholderTag) {
|
||||||
|
// Normal tag
|
||||||
|
for (var i = 0; i < world_info_data[uid][keyField].length; i++) {
|
||||||
|
if (world_info_data[uid][keyField][i] !== tagText) {
|
||||||
|
world_info_data[uid][keyField][i] = this.innerText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Placeholder tag
|
||||||
|
if (!this.textContent.trim()) return;
|
||||||
|
|
||||||
|
on_new_wi_item = this.id;
|
||||||
|
world_info_data[uid][keyField].push(this.textContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
send_world_info(uid);
|
||||||
|
this.classList.add("pulse");
|
||||||
|
});
|
||||||
|
|
||||||
|
textEl.addEventListener("keydown", function(event) {
|
||||||
|
if (event.key === "Enter") {
|
||||||
|
// Press Enter to save tag and focus next one
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
// HACK: Work around the fact that the server is in control of
|
||||||
|
// placing these elements
|
||||||
|
attention_wanting_wi_bar = tagType;
|
||||||
|
// And don't wait for like 10000 years to randomly take focus from
|
||||||
|
// the user
|
||||||
|
setTimeout(() => attention_wanting_wi_bar = null, 500);
|
||||||
|
|
||||||
|
this.blur();
|
||||||
|
} else if (event.key === "Escape") {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
tagEl.append(xEl);
|
||||||
|
tagEl.append(textEl);
|
||||||
|
tagEl.id = `world_info_${tagClassFragment}_${uid}_${tagText || "new"}`;
|
||||||
|
|
||||||
|
return tagEl;
|
||||||
}
|
}
|
||||||
|
|
||||||
function add_secondary_tags(tags, data) {
|
function add_tags(tagBarEl, data, tagType) {
|
||||||
while (tags.firstChild) {
|
// tagType is either "primary" or "secondary"
|
||||||
tags.removeChild(tags.firstChild);
|
|
||||||
|
// Remove existing tags
|
||||||
|
while (tagBarEl.firstChild) {
|
||||||
|
tagBarEl.removeChild(tagBarEl.firstChild);
|
||||||
}
|
}
|
||||||
for (tag of data.keysecondary) {
|
|
||||||
tag_item = document.createElement("span");
|
const tagList = {
|
||||||
tag_item.classList.add("tag");
|
primary: data.key,
|
||||||
x = document.createElement("span");
|
secondary: data.keysecondary
|
||||||
x.textContent = "x ";
|
}[tagType];
|
||||||
x.classList.add("delete_icon");
|
|
||||||
x.setAttribute("uid", data.uid);
|
for (tag of tagList) {
|
||||||
x.setAttribute("tag", tag);
|
tagBarEl.append(create_tag_element(tag, data.uid, tagType));
|
||||||
x.onclick = function () {
|
|
||||||
removeA(world_info_data[this.getAttribute('uid')]['keysecondary'], this.getAttribute('tag'));
|
|
||||||
send_world_info(this.getAttribute('uid'));
|
|
||||||
this.classList.add("pulse");
|
|
||||||
};
|
|
||||||
text = document.createElement("span");
|
|
||||||
text.textContent = tag;
|
|
||||||
text.setAttribute("contenteditable", true);
|
|
||||||
text.setAttribute("uid", data.uid);
|
|
||||||
text.setAttribute("tag", tag);
|
|
||||||
text.id = "world_info_secondtags_text_"+data.uid+"_"+tag;
|
|
||||||
text.ondragstart=function() {event.preventDefault();event.stopPropagation();};
|
|
||||||
text.setAttribute("draggable", "true");
|
|
||||||
text.onfocus=function() {this.parentElement.parentElement.parentElement.setAttribute('draggable', 'false');this.setAttribute('draggable', 'false');};
|
|
||||||
text.onblur = function () {
|
|
||||||
this.parentElement.parentElement.parentElement.setAttribute('draggable', 'true');
|
|
||||||
this.setAttribute('draggable', 'true');
|
|
||||||
for (var i = 0; i < world_info_data[this.getAttribute('uid')]['keysecondary'].length; i++) {
|
|
||||||
if (world_info_data[this.getAttribute('uid')]['keysecondary'][i] == this.getAttribute("tag")) {
|
|
||||||
world_info_data[this.getAttribute('uid')]['keysecondary'][i] = this.textContent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
send_world_info(this.getAttribute('uid'));
|
|
||||||
this.classList.add("pulse");
|
|
||||||
};
|
|
||||||
tag_item.append(x);
|
|
||||||
tag_item.append(text);
|
|
||||||
tag_item.id = "world_info_secondtags_"+data.uid+"_"+tag;
|
|
||||||
tags.append(tag_item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//add the blank tag
|
//add the blank tag
|
||||||
tag_item = document.createElement("span");
|
const placeholderTagEl = create_tag_element(null, data.uid, tagType);
|
||||||
tag_item.classList.add("tag");
|
tagBarEl.append(placeholderTagEl);
|
||||||
x = document.createElement("span");
|
|
||||||
x.textContent = "+ ";
|
if (attention_wanting_wi_bar === tagType) {
|
||||||
tag_item.append(x);
|
const textEl = placeholderTagEl.querySelector(".tag_text");
|
||||||
text = document.createElement("span");
|
// HACK: Please don't ask because I do not know
|
||||||
text.classList.add("rawtext");
|
setTimeout(() => textEl.focus(), 1);
|
||||||
text.textContent = " ";
|
|
||||||
text.setAttribute("uid", data.uid);
|
|
||||||
text.setAttribute("contenteditable", true);
|
|
||||||
text.id = "world_info_secondtags_text_"+data.uid+"_blank";
|
|
||||||
text.ondragstart=function() {event.preventDefault();event.stopPropagation();};
|
|
||||||
text.setAttribute("draggable", "true");
|
|
||||||
text.onfocus=function() {this.parentElement.parentElement.parentElement.setAttribute('draggable', 'false');this.setAttribute('draggable', 'false');};
|
|
||||||
text.onblur = function () {
|
|
||||||
this.parentElement.parentElement.parentElement.setAttribute('draggable', 'true');
|
|
||||||
this.setAttribute('draggable', 'true');
|
|
||||||
if (this.textContent.trim() != "") {
|
|
||||||
on_new_wi_item = this.id;
|
|
||||||
world_info_data[this.getAttribute('uid')]['keysecondary'].push(this.textContent);
|
|
||||||
send_world_info(this.getAttribute('uid'));
|
|
||||||
this.classList.add("pulse");
|
|
||||||
} else {
|
|
||||||
this.textContent = " ";
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
text.onclick = function () {
|
|
||||||
this.textContent = "";
|
|
||||||
};
|
|
||||||
tag_item.append(text);
|
|
||||||
tag_item.id = "world_info_secondtags_"+data.uid+"_new";
|
|
||||||
tags.append(tag_item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function create_new_wi_entry(folder) {
|
function create_new_wi_entry(folder) {
|
||||||
@@ -6947,9 +6954,13 @@ function sFormatted2HTML(sFormatted) {
|
|||||||
return outHTML;
|
return outHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteConfirmation(sFormatted, confirmText, denyText, confirmCallback, denyCallback) {
|
function deleteConfirmation(sFormatted, confirmText, denyText, confirmCallback, denyCallback=null, bypass=false) {
|
||||||
$el("#confirm-text").innerHTML = sFormatted2HTML(sFormatted);
|
if (bypass) {
|
||||||
|
confirmCallback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$el("#confirm-text").innerHTML = sFormatted2HTML(sFormatted);
|
||||||
$el("#confirm-confirm-button > .text").innerText = confirmText;
|
$el("#confirm-confirm-button > .text").innerText = confirmText;
|
||||||
$el("#confirm-deny-button > .text").innerText = denyText;
|
$el("#confirm-deny-button > .text").innerText = denyText;
|
||||||
|
|
||||||
|
@@ -97,7 +97,7 @@
|
|||||||
<div id="story_menu_wi" class="story_category_area tab-target tab-target-story hidden">
|
<div id="story_menu_wi" class="story_category_area tab-target tab-target-story hidden">
|
||||||
<h4 class="section_header" style="margin-left: 12px;">World Info</h4>
|
<h4 class="section_header" style="margin-left: 12px;">World Info</h4>
|
||||||
<div class="help_text" style="margin-left: 20px;">
|
<div class="help_text" style="margin-left: 20px;">
|
||||||
Lore information, which the AI recalls by certain words.
|
Lore information, which the AI recalls with the mention of certain words.
|
||||||
<span class="helpicon material-icons-outlined" tooltip="Use this instead of Memory for information on things like characters, objects, events, places, and anything else with detail.">help_icon</span>
|
<span class="helpicon material-icons-outlined" tooltip="Use this instead of Memory for information on things like characters, objects, events, places, and anything else with detail.">help_icon</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting_tile_area wi_settings">
|
<div class="setting_tile_area wi_settings">
|
||||||
|
@@ -22,12 +22,16 @@
|
|||||||
<span
|
<span
|
||||||
class="world_info_item_type"
|
class="world_info_item_type"
|
||||||
contenteditable="true"
|
contenteditable="true"
|
||||||
data-placeholder="Person"
|
data-placeholder="..."
|
||||||
spellcheck="false"
|
spellcheck="false"
|
||||||
></span> <span class="helpicon material-icons-outlined" tooltip="Please enter a noun that describes a person, place or thing." "]">help_icon</span>
|
></span>
|
||||||
|
<span
|
||||||
|
class="helpicon material-icons-outlined"
|
||||||
|
tooltip='Please enter a noun that describes this entry. For example, "person", "weapon", or "building". This will be used with the Generate Content button below.'
|
||||||
|
>help_icon</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span id="world_info_delete_" class="world_info_delete">X</span>
|
<span id="world_info_delete_" class="world_info_delete material-icons-outlined">close</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="world_info_upper_container world_info_tag_area">
|
<div class="world_info_upper_container world_info_tag_area">
|
||||||
|
Reference in New Issue
Block a user