mirror of
https://github.com/KoboldAI/KoboldAI-Client.git
synced 2025-06-05 21:59:24 +02:00
332 lines
11 KiB
JavaScript
332 lines
11 KiB
JavaScript
var socket;
|
|
socket = io.connect(window.location.origin, {transports: ['polling', 'websocket'], closeOnBeforeunload: false, query:{"ui": "2"}});
|
|
|
|
//Let's register our server communications
|
|
socket.on('connect', function(){connect();});
|
|
socket.on("disconnect", (reason, details) => {
|
|
console.log("Lost connection from: "+reason); // "transport error"
|
|
});
|
|
socket.on('reset_story', function(){reset_story();});
|
|
socket.on('var_changed', function(data){var_changed(data);});
|
|
socket.onAny(function(event_name, data) {console.log({"event": event_name, "class": data.classname, "data": data});});
|
|
|
|
var backend_vars = {};
|
|
var presets = {}
|
|
var ai_busy_start = Date.now();
|
|
//-----------------------------------Server to UI Functions-----------------------------------------------
|
|
function connect() {
|
|
console.log("connected");
|
|
}
|
|
|
|
function disconnect() {
|
|
console.log("disconnected");
|
|
}
|
|
|
|
function reset_story() {
|
|
console.log("Resetting story");
|
|
var story_area = document.getElementById('Selected Text');
|
|
while (story_area.firstChild) {
|
|
story_area.removeChild(story_area.firstChild);
|
|
}
|
|
var option_area = document.getElementById("Select Options");
|
|
while (option_area.firstChild) {
|
|
option_area.removeChild(option_area.firstChild);
|
|
}
|
|
}
|
|
|
|
function fix_text(val) {
|
|
if (typeof val === 'string' || val instanceof String) {
|
|
if (val.includes("{")) {
|
|
return JSON.stringify(val);
|
|
} else {
|
|
return val;
|
|
}
|
|
} else {
|
|
return val;
|
|
}
|
|
}
|
|
|
|
function create_options(data) {
|
|
//Set all options before the next chunk to hidden
|
|
var option_container = document.getElementById("Select Options");
|
|
var current_chunk = parseInt(document.getElementById("action_count").textContent)+1;
|
|
var children = option_container.children;
|
|
for (var i = 0; i < children.length; i++) {
|
|
var chunk = children[i];
|
|
if (chunk.id == "Select Options Chunk " + current_chunk) {
|
|
chunk.classList.remove("hidden");
|
|
} else {
|
|
chunk.classList.add("hidden");
|
|
}
|
|
}
|
|
|
|
if (document.getElementById("Select Options Chunk "+data.value.id)) {
|
|
var option_chunk = document.getElementById("Select Options Chunk "+data.value.id)
|
|
} else {
|
|
var option_area = document.getElementById("Select Options");
|
|
var option_chunk = document.createElement("div");
|
|
option_chunk.id = "Select Options Chunk "+data.value.id;
|
|
option_area.append(option_chunk);
|
|
}
|
|
//first, let's clear out our existing data
|
|
while (option_chunk.firstChild) {
|
|
option_chunk.removeChild(option_chunk.firstChild);
|
|
}
|
|
var table = document.createElement("table");
|
|
table.classList.add("sequence");
|
|
table.style = "border-spacing: 0;";
|
|
//Add Redo options
|
|
i=0;
|
|
for (item of data.value.options) {
|
|
if ((item['Previous Selection'])) {
|
|
var row = document.createElement("tr");
|
|
row.classList.add("sequence");
|
|
var textcell = document.createElement("td");
|
|
textcell.textContent = item.text;
|
|
textcell.classList.add("sequence");
|
|
textcell.setAttribute("option_id", i);
|
|
textcell.setAttribute("option_chunk", data.value.id);
|
|
var iconcell = document.createElement("td");
|
|
iconcell.setAttribute("option_id", i);
|
|
iconcell.setAttribute("option_chunk", data.value.id);
|
|
var icon = document.createElement("span");
|
|
icon.id = "Pin_"+i;
|
|
icon.classList.add("oi");
|
|
icon.setAttribute('data-glyph', "loop-circular");
|
|
iconcell.append(icon);
|
|
textcell.onclick = function () {
|
|
socket.emit("Set Selected Text", {"chunk": this.getAttribute("option_chunk"), "option": this.getAttribute("option_id")});
|
|
};
|
|
row.append(textcell);
|
|
row.append(iconcell);
|
|
table.append(row);
|
|
}
|
|
i+=1;
|
|
}
|
|
//Add general options
|
|
i=0;
|
|
for (item of data.value.options) {
|
|
if (!(item.Edited) && !(item['Previous Selection'])) {
|
|
var row = document.createElement("tr");
|
|
row.classList.add("sequence");
|
|
var textcell = document.createElement("td");
|
|
textcell.textContent = item.text;
|
|
textcell.classList.add("sequence");
|
|
textcell.setAttribute("option_id", i);
|
|
textcell.setAttribute("option_chunk", data.value.id);
|
|
var iconcell = document.createElement("td");
|
|
iconcell.setAttribute("option_id", i);
|
|
iconcell.setAttribute("option_chunk", data.value.id);
|
|
var icon = document.createElement("span");
|
|
icon.id = "Pin_"+i;
|
|
icon.classList.add("oi");
|
|
icon.setAttribute('data-glyph', "pin");
|
|
if (!(item.Pinned)) {
|
|
icon.setAttribute('style', "filter: brightness(50%);");
|
|
}
|
|
iconcell.append(icon);
|
|
iconcell.onclick = function () {
|
|
socket.emit("Pinning", {"chunk": this.getAttribute("option_chunk"), "option": this.getAttribute("option_id")});
|
|
};
|
|
textcell.onclick = function () {
|
|
socket.emit("Set Selected Text", {"chunk": this.getAttribute("option_chunk"), "option": this.getAttribute("option_id")});
|
|
};
|
|
row.append(textcell);
|
|
row.append(iconcell);
|
|
table.append(row);
|
|
}
|
|
i+=1;
|
|
}
|
|
option_chunk.append(table);
|
|
}
|
|
|
|
function do_story_text_updates(data) {
|
|
story_area = document.getElementById('Selected Text');
|
|
if (document.getElementById('Selected Text Chunk '+data.value.id)) {
|
|
document.getElementById('Selected Text Chunk '+data.value.id).textContent = data.value.text;
|
|
} else {
|
|
var span = document.createElement("span");
|
|
span.id = 'Selected Text Chunk '+data.value.id;
|
|
span.chunk = data.value.id;
|
|
span.original_text = data.value.text;
|
|
span.setAttribute("contenteditable", true);
|
|
span.onblur = function () {
|
|
if (this.textContent != this.original_text) {
|
|
socket.emit("Set Selected Text", {"id": this.chunk, "text": this.textContent});
|
|
}
|
|
}
|
|
span.textContent = data.value.text;
|
|
|
|
story_area.append(span);
|
|
}
|
|
}
|
|
|
|
function do_presets(data) {
|
|
console.log(data);
|
|
var select = document.getElementById('presets');
|
|
//clear out the preset list
|
|
while (select.firstChild) {
|
|
select.removeChild(select.firstChild);
|
|
}
|
|
//add our blank option
|
|
var option = document.createElement("option");
|
|
option.value="";
|
|
option.text="presets";
|
|
select.append(option);
|
|
for (const [key, value] of Object.entries(data.value)) {
|
|
presets[key] = value;
|
|
var option = document.createElement("option");
|
|
option.value=key;
|
|
option.text=key;
|
|
select.append(option);
|
|
}
|
|
}
|
|
|
|
function selected_preset(data) {
|
|
if ((data.value == undefined) || (presets[data.value] == undefined)) {
|
|
return;
|
|
}
|
|
for (const [key, value] of Object.entries(presets[data.value])) {
|
|
if (key.charAt(0) != '_') {
|
|
var elements_to_change = document.getElementsByClassName("var_sync_model_"+key);
|
|
for (item of elements_to_change) {
|
|
if (item.tagName.toLowerCase() === 'input') {
|
|
item.value = fix_text(value);
|
|
} else {
|
|
item.textContent = fix_text(value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function update_status_bar(data) {
|
|
var total_tokens = document.getElementById('model_genamt').value;
|
|
var percent_complete = data.value;
|
|
var percent_bar = document.getElementsByClassName("statusbar_inner");
|
|
for (item of percent_bar) {
|
|
item.setAttribute("style", "width:"+percent_complete+"%");
|
|
item.textContent = Math.round(percent_complete)+"%"
|
|
if ((percent_complete == 0) || (percent_complete == 100)) {
|
|
item.parentElement.classList.add("hidden");
|
|
document.getElementById("inputrow_container").classList.remove("status_bar");
|
|
} else {
|
|
item.parentElement.classList.remove("hidden");
|
|
document.getElementById("inputrow_container").classList.add("status_bar");
|
|
}
|
|
}
|
|
if ((percent_complete == 0) || (percent_complete == 100)) {
|
|
document.title = "KoboldAI Client";
|
|
} else {
|
|
document.title = "KoboldAI Client Generating (" + percent_complete + "%)";
|
|
}
|
|
}
|
|
|
|
function do_ai_busy(data) {
|
|
if (data.value) {
|
|
ai_busy_start = Date.now();
|
|
favicon.start_swap()
|
|
} else {
|
|
runtime = Date.now() - ai_busy_start;
|
|
if (document.getElementById("Execution Time")) {
|
|
document.getElementById("Execution Time").textContent = Math.round(runtime/1000).toString().toHHMMSS();
|
|
}
|
|
favicon.stop_swap()
|
|
}
|
|
}
|
|
|
|
function var_changed(data) {
|
|
//Special Case for Story Text
|
|
if ((data.classname == "actions") && (data.name == "Selected Text")) {
|
|
do_story_text_updates(data);
|
|
//Special Case for Story Options
|
|
} else if ((data.classname == "actions") && (data.name == "Options")) {
|
|
create_options(data);
|
|
//Special Case for Presets
|
|
} else if ((data.classname == 'model') && (data.name == 'presets')) {
|
|
do_presets(data);
|
|
} else if ((data.classname == "model") && (data.name == "selected_preset")) {
|
|
selected_preset(data);
|
|
//Basic Data Syncing
|
|
} else {
|
|
var elements_to_change = document.getElementsByClassName("var_sync_"+data.classname.replace(" ", "_")+"_"+data.name.replace(" ", "_"));
|
|
for (item of elements_to_change) {
|
|
if ((item.tagName.toLowerCase() === 'input') || (item.tagName.toLowerCase() === 'select')) {
|
|
item.value = fix_text(data.value);
|
|
} else {
|
|
item.textContent = fix_text(data.value);
|
|
}
|
|
}
|
|
//alternative syncing method
|
|
var elements_to_change = document.getElementsByClassName("var_sync_alt_"+data.classname.replace(" ", "_")+"_"+data.name.replace(" ", "_"));
|
|
for (item of elements_to_change) {
|
|
item.setAttribute(data.classname.replace(" ", "_")+"_"+data.name.replace(" ", "_"), fix_text(data.value));
|
|
}
|
|
}
|
|
|
|
//if we're updating generated tokens, let's show that in our status bar
|
|
if ((data.classname == 'model') && (data.name == 'tqdm_progress')) {
|
|
update_status_bar(data);
|
|
}
|
|
|
|
//If we have ai_busy, start the favicon swapping
|
|
if ((data.classname == 'system') && (data.name == 'aibusy')) {
|
|
do_ai_busy(data);
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------UI to Server Functions----------------------------------
|
|
|
|
|
|
//--------------------------------------------General UI Functions------------------------------------
|
|
String.prototype.toHHMMSS = function () {
|
|
var sec_num = parseInt(this, 10); // don't forget the second param
|
|
var hours = Math.floor(sec_num / 3600);
|
|
var minutes = Math.floor((sec_num - (hours * 3600)) / 60);
|
|
var seconds = sec_num - (hours * 3600) - (minutes * 60);
|
|
|
|
if (hours < 10) {hours = "0"+hours;}
|
|
if (minutes < 10) {minutes = "0"+minutes;}
|
|
if (seconds < 10) {seconds = "0"+seconds;}
|
|
return hours+':'+minutes+':'+seconds;
|
|
}
|
|
|
|
function toggle_flyout(x) {
|
|
if (document.getElementById("SideMenu").classList.contains("open")) {
|
|
x.classList.remove("change");
|
|
document.getElementById("SideMenu").classList.remove("open");
|
|
document.getElementById("main-grid").classList.remove("menu-open");
|
|
//if pinned
|
|
if (document.getElementById("SideMenu").classList.contains("pinned")) {
|
|
document.getElementById("menu_pin").classList.remove("hidden");
|
|
} else {
|
|
document.getElementById("menu_pin").classList.add("hidden");
|
|
}
|
|
} else {
|
|
x.classList.add("change");
|
|
document.getElementById("SideMenu").classList.add("open");
|
|
document.getElementById("main-grid").classList.add("menu-open");
|
|
document.getElementById("menu_pin").classList.remove("hidden");
|
|
}
|
|
}
|
|
|
|
function toggle_flyout_right(x) {
|
|
if (document.getElementById("rightSideMenu").classList.contains("open")) {
|
|
document.getElementById("rightSideMenu").classList.remove("open");
|
|
x.setAttribute("data-glyph", "chevron-left");
|
|
} else {
|
|
document.getElementById("rightSideMenu").classList.add("open");
|
|
x.setAttribute("data-glyph", "chevron-right");
|
|
}
|
|
}
|
|
|
|
function toggle_pin_flyout() {
|
|
if (document.getElementById("SideMenu").classList.contains("pinned")) {
|
|
document.getElementById("SideMenu").classList.remove("pinned");
|
|
document.getElementById("main-grid").classList.remove("pinned");
|
|
} else {
|
|
document.getElementById("SideMenu").classList.add("pinned");
|
|
document.getElementById("main-grid").classList.add("pinned");
|
|
}
|
|
}
|