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:
19
aiserver.py
19
aiserver.py
@@ -4396,8 +4396,8 @@ def requestwi():
|
||||
# and items in different folders are sorted based on the order of the folders
|
||||
#==================================================================#
|
||||
def stablesortwi():
|
||||
mapping = {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"))
|
||||
mapping = {int(uid): index for index, uid in enumerate(koboldai_vars.wifolders_l)}
|
||||
koboldai_vars.worldinfo.sort(key=lambda x: mapping[int(x["folder"])] if x["folder"] is not None else float("inf"))
|
||||
last_folder = ...
|
||||
last_wi = None
|
||||
for i, wi in enumerate(koboldai_vars.worldinfo):
|
||||
@@ -6692,11 +6692,18 @@ def UI_2_set_wi_image(uid):
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
else:
|
||||
# Otherwise assign image
|
||||
with open(path, "wb") as file:
|
||||
file.write(data)
|
||||
try:
|
||||
# Otherwise assign image
|
||||
with open(path, "wb") as file:
|
||||
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
|
||||
return ":)"
|
||||
return ":)", 200
|
||||
|
||||
@app.route("/get_wi_image/<int(signed=True):uid>", methods=["GET"])
|
||||
@require_allowed_ip
|
||||
|
@@ -296,7 +296,7 @@ gensettingstf = [
|
||||
"max": 1,
|
||||
"step": 1,
|
||||
"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",
|
||||
"sub_path": "",
|
||||
"classname": "story",
|
||||
@@ -756,7 +756,7 @@ gensettingstf = [
|
||||
"max": 1,
|
||||
"step": 1,
|
||||
"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",
|
||||
"sub_path": "UI",
|
||||
"classname": "system",
|
||||
|
@@ -637,7 +637,12 @@ class InferenceModel:
|
||||
)
|
||||
|
||||
time_end = round(time.time() - time_start, 2)
|
||||
tokens_per_second = round(len(result.encoded[0]) / time_end, 2)
|
||||
|
||||
try:
|
||||
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:
|
||||
logger.info(
|
||||
|
@@ -1,12 +1,10 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import torch
|
||||
import requests
|
||||
import numpy as np
|
||||
from typing import List, Optional, Union
|
||||
|
||||
import utils
|
||||
from logger import logger
|
||||
from modeling.inference_model import (
|
||||
GenerationResult,
|
||||
GenerationSettings,
|
||||
@@ -15,29 +13,46 @@ from modeling.inference_model import (
|
||||
)
|
||||
|
||||
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):
|
||||
def __init__(self) -> None:
|
||||
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.tokenizer = self._tokenizer()
|
||||
self.tokenizer: FacadeTokenizer = None
|
||||
self.model = None
|
||||
self.model_name = "Read Only"
|
||||
|
||||
|
||||
def is_valid(self, model_name, model_path, menu_path):
|
||||
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 = []
|
||||
return requested_parameters
|
||||
|
||||
|
||||
def set_input_parameters(self, parameters):
|
||||
return
|
||||
|
||||
@@ -46,17 +61,9 @@ class model_backend(InferenceModel):
|
||||
|
||||
def _initialize_model(self):
|
||||
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:
|
||||
self.tokenizer = self.tokenizer
|
||||
self.tokenizer = FacadeTokenizer()
|
||||
self.model = None
|
||||
utils.koboldai_vars.noai = True
|
||||
|
||||
@@ -72,7 +79,7 @@ class model_backend(InferenceModel):
|
||||
):
|
||||
return GenerationResult(
|
||||
model=self,
|
||||
out_batches=np.array([]),
|
||||
out_batches=np.array([[]]),
|
||||
prompt=prompt_tokens,
|
||||
is_whole_generation=True,
|
||||
single_line=single_line,
|
||||
|
@@ -1259,17 +1259,46 @@ td.server_vars {
|
||||
.world_info_label_container > .generate-button:hover { opacity: 1.0; }
|
||||
|
||||
.tag {
|
||||
display: inline-block;
|
||||
background-color: var(--wi_tag_color);
|
||||
color: var(--wi_tag_text_color);
|
||||
|
||||
margin-right: 3px;
|
||||
margin-top: 3px;
|
||||
|
||||
padding: 2px;
|
||||
margin-right: 2px;
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
|
||||
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 {
|
||||
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] {
|
||||
@@ -2851,6 +2880,10 @@ body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#welcome_text a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.welcome_text {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
@@ -3569,10 +3602,15 @@ h2 .material-icons-outlined {
|
||||
}
|
||||
|
||||
.section_header {
|
||||
font-weight: bold;
|
||||
margin-left: 2px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.story_category_area > * > label {
|
||||
user-select: none
|
||||
}
|
||||
|
||||
.help_text {
|
||||
margin-left: 6px;
|
||||
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_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("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_folder", function(data){document.getElementById("world_info_folder_"+data).remove();});
|
||||
socket.on("error", function(data){show_error_message(data);});
|
||||
@@ -87,6 +93,7 @@ var initial_socketio_connection_occured = false;
|
||||
var selected_model_data;
|
||||
var supported_gen_modes = [];
|
||||
var privacy_mode_enabled = false;
|
||||
var attention_wanting_wi_bar = null;
|
||||
var ai_busy = false;
|
||||
var can_show_options = false;
|
||||
|
||||
@@ -1281,7 +1288,7 @@ function redrawPopup() {
|
||||
delete_icon.setAttribute("tooltip", "Delete");
|
||||
delete_icon.id = row.path;
|
||||
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 delId = this.id;
|
||||
|
||||
@@ -1291,9 +1298,11 @@ function redrawPopup() {
|
||||
denyText="I've changed my mind!",
|
||||
confirmCallback=function() {
|
||||
socket.emit("popup_delete", delId);
|
||||
}
|
||||
},
|
||||
null,
|
||||
event.shiftKey
|
||||
);
|
||||
};
|
||||
});
|
||||
}
|
||||
icon_area.append(delete_icon);
|
||||
tr.append(icon_area);
|
||||
@@ -2203,6 +2212,7 @@ function world_info_entry(data) {
|
||||
} else {
|
||||
world_info_card.classList.remove("used_in_game");
|
||||
}
|
||||
|
||||
const title = world_info_card.querySelector('.world_info_title');
|
||||
title.id = "world_info_title_"+data.uid;
|
||||
title.textContent = data.title;
|
||||
@@ -2210,7 +2220,7 @@ function world_info_entry(data) {
|
||||
title.setAttribute("original_text", data.title);
|
||||
title.setAttribute("contenteditable", true);
|
||||
title.classList.remove("pulse");
|
||||
title.ondragstart=function() {event.preventDefault();event.stopPropagation();};
|
||||
title.ondragstart=function(event) {event.preventDefault();event.stopPropagation();};
|
||||
title.onblur = function () {
|
||||
this.parentElement.parentElement.setAttribute('draggable', 'true');
|
||||
this.setAttribute('draggable', 'true');
|
||||
@@ -2220,20 +2230,31 @@ function world_info_entry(data) {
|
||||
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('dragover', dragOver);
|
||||
title.addEventListener('dragleave', dragLeave);
|
||||
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.setAttribute("uid", data.uid);
|
||||
delete_icon.setAttribute("wi-title", data.title);
|
||||
delete_icon.onclick = function () {
|
||||
delete_icon.addEventListener("click", function (event) {
|
||||
const wiTitle = this.getAttribute("wi-title");
|
||||
const wiUid = parseInt(this.getAttribute("uid"));
|
||||
const wiElement = this.parentElement.parentElement;
|
||||
|
||||
deleteConfirmation([
|
||||
{text: "You're about to delete World Info entry "},
|
||||
{text: wiTitle, format: "bold"},
|
||||
@@ -2247,9 +2268,11 @@ function world_info_entry(data) {
|
||||
} else {
|
||||
socket.emit("delete_world_info", wiUid);
|
||||
}
|
||||
}
|
||||
},
|
||||
null,
|
||||
event.shiftKey
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const wiImgContainer = world_info_card.querySelector(".world_info_image_container");
|
||||
const wiImg = wiImgContainer.querySelector(".world_info_image");
|
||||
@@ -2342,15 +2365,16 @@ function world_info_entry(data) {
|
||||
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;
|
||||
//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;
|
||||
//add second tag content here
|
||||
add_secondary_tags(secondarytags, data);
|
||||
add_tags(secondarytags, data, "secondary");
|
||||
|
||||
//w++ toggle
|
||||
wpp_toggle_area = world_info_card.querySelector('.world_info_wpp_toggle_area');
|
||||
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.setAttribute("folder", folder_name);
|
||||
delete_button.textContent = "delete";
|
||||
delete_button.onclick = function () {
|
||||
delete_button.addEventListener("click", function (event) {
|
||||
const folderName = this.getAttribute("folder");
|
||||
|
||||
deleteConfirmation([
|
||||
{text: "You're about to delete World Info folder "},
|
||||
{text: folderName, format: "bold"},
|
||||
@@ -2734,9 +2759,11 @@ function world_info_folder(data) {
|
||||
],
|
||||
confirmText="Go for it.",
|
||||
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");
|
||||
title.append(delete_button);
|
||||
|
||||
@@ -3241,6 +3268,8 @@ function upload_file_without_save(file_box) {
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
@@ -4443,161 +4472,139 @@ function removeA(arr) {
|
||||
return arr;
|
||||
}
|
||||
|
||||
function add_tags(tags, data) {
|
||||
while (tags.firstChild) {
|
||||
tags.removeChild(tags.firstChild);
|
||||
function create_tag_element(tagText, uid, tagType) {
|
||||
// tagText is string, or null for empty tag at end.
|
||||
// barType should be "primary" or "secondary"
|
||||
const isPlaceholderTag = tagText === null;
|
||||
|
||||
const wiCardEl = document.querySelector(`.world_info_card[uid="${uid}"]`)
|
||||
const keyField = {primary: "key", secondary: "keysecondary"}[tagType];
|
||||
const tagClassFragment = {primary: "tags", primary: "secondtags"}[tagType];
|
||||
|
||||
const tagEl = document.createElement("span");
|
||||
tagEl.classList.add("tag");
|
||||
if (isPlaceholderTag) tagEl.classList.add("placeholder_tag");
|
||||
|
||||
const xEl = document.createElement("span");
|
||||
xEl.classList.add("material-icons-outlined");
|
||||
xEl.classList.add("tag_button");
|
||||
|
||||
if (!isPlaceholderTag) {
|
||||
xEl.classList.add("delete_icon");
|
||||
xEl.textContent = "close";
|
||||
} else {
|
||||
xEl.classList.add("add_icon");
|
||||
xEl.textContent = "add";
|
||||
}
|
||||
for (tag of data.key) {
|
||||
tag_item = document.createElement("span");
|
||||
tag_item.classList.add("tag");
|
||||
x = document.createElement("span");
|
||||
x.textContent = "x ";
|
||||
x.classList.add("delete_icon");
|
||||
x.setAttribute("uid", data.uid);
|
||||
x.setAttribute("tag", tag);
|
||||
x.onclick = function () {
|
||||
removeA(world_info_data[this.getAttribute('uid')]['key'], 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_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 {
|
||||
this.textContent = " ";
|
||||
}
|
||||
};
|
||||
text.onclick = function () {
|
||||
this.textContent = "";
|
||||
};
|
||||
tag_item.append(text);
|
||||
tag_item.id = "world_info_secondtags_"+data.uid+"_new";
|
||||
tags.append(tag_item);
|
||||
|
||||
xEl.setAttribute("uid", uid);
|
||||
xEl.setAttribute("tag", tagText);
|
||||
xEl.addEventListener("click", function() {
|
||||
removeA(
|
||||
world_info_data[uid][keyField],
|
||||
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) {
|
||||
while (tags.firstChild) {
|
||||
tags.removeChild(tags.firstChild);
|
||||
function add_tags(tagBarEl, data, tagType) {
|
||||
// tagType is either "primary" or "secondary"
|
||||
|
||||
// Remove existing tags
|
||||
while (tagBarEl.firstChild) {
|
||||
tagBarEl.removeChild(tagBarEl.firstChild);
|
||||
}
|
||||
for (tag of data.keysecondary) {
|
||||
tag_item = document.createElement("span");
|
||||
tag_item.classList.add("tag");
|
||||
x = document.createElement("span");
|
||||
x.textContent = "x ";
|
||||
x.classList.add("delete_icon");
|
||||
x.setAttribute("uid", data.uid);
|
||||
x.setAttribute("tag", tag);
|
||||
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);
|
||||
|
||||
const tagList = {
|
||||
primary: data.key,
|
||||
secondary: data.keysecondary
|
||||
}[tagType];
|
||||
|
||||
for (tag of tagList) {
|
||||
tagBarEl.append(create_tag_element(tag, data.uid, tagType));
|
||||
}
|
||||
|
||||
//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_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);
|
||||
const placeholderTagEl = create_tag_element(null, data.uid, tagType);
|
||||
tagBarEl.append(placeholderTagEl);
|
||||
|
||||
if (attention_wanting_wi_bar === tagType) {
|
||||
const textEl = placeholderTagEl.querySelector(".tag_text");
|
||||
// HACK: Please don't ask because I do not know
|
||||
setTimeout(() => textEl.focus(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function create_new_wi_entry(folder) {
|
||||
var uid = -1;
|
||||
for (item of document.getElementsByClassName('world_info_card')) {
|
||||
@@ -6947,9 +6954,13 @@ function sFormatted2HTML(sFormatted) {
|
||||
return outHTML;
|
||||
}
|
||||
|
||||
function deleteConfirmation(sFormatted, confirmText, denyText, confirmCallback, denyCallback) {
|
||||
function deleteConfirmation(sFormatted, confirmText, denyText, confirmCallback, denyCallback=null, bypass=false) {
|
||||
if (bypass) {
|
||||
confirmCallback();
|
||||
return;
|
||||
}
|
||||
|
||||
$el("#confirm-text").innerHTML = sFormatted2HTML(sFormatted);
|
||||
|
||||
$el("#confirm-confirm-button > .text").innerText = confirmText;
|
||||
$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">
|
||||
<h4 class="section_header" style="margin-left: 12px;">World Info</h4>
|
||||
<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>
|
||||
</div>
|
||||
<div class="setting_tile_area wi_settings">
|
||||
|
@@ -22,12 +22,16 @@
|
||||
<span
|
||||
class="world_info_item_type"
|
||||
contenteditable="true"
|
||||
data-placeholder="Person"
|
||||
data-placeholder="..."
|
||||
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>
|
||||
<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 class="world_info_upper_container world_info_tag_area">
|
||||
|
Reference in New Issue
Block a user