mirror of
https://github.com/KoboldAI/KoboldAI-Client.git
synced 2025-02-17 04:00:44 +01:00
Add Userscripts menu into GUI
This commit is contained in:
parent
5d13339a52
commit
d2f5544468
83
aiserver.py
83
aiserver.py
@ -105,6 +105,7 @@ class vars:
|
||||
lua_kobold = None # `kobold` from` bridge.lua
|
||||
lua_koboldcore = None # `koboldcore` from bridge.lua
|
||||
lua_warper = None # Transformers logits warper controllable from Lua
|
||||
userscripts = [] # List of userscripts to load
|
||||
# badwords = [] # Array of str/chr values that should be removed from output
|
||||
badwordsids = [[13460], [6880], [50256], [42496], [4613], [17414], [22039], [16410], [27], [29], [38430], [37922], [15913], [24618], [28725], [58], [47175], [36937], [26700], [12878], [16471], [37981], [5218], [29795], [13412], [45160], [3693], [49778], [4211], [20598], [36475], [33409], [44167], [32406], [29847], [29342], [42669], [685], [25787], [7359], [3784], [5320], [33994], [33490], [34516], [43734], [17635], [24293], [9959], [23785], [21737], [28401], [18161], [26358], [32509], [1279], [38155], [18189], [26894], [6927], [14610], [23834], [11037], [14631], [26933], [46904], [22330], [25915], [47934], [38214], [1875], [14692], [41832], [13163], [25970], [29565], [44926], [19841], [37250], [49029], [9609], [44438], [16791], [17816], [30109], [41888], [47527], [42924], [23984], [49074], [33717], [31161], [49082], [30138], [31175], [12240], [14804], [7131], [26076], [33250], [3556], [38381], [36338], [32756], [46581], [17912], [49146]] # Tokenized array of badwords used to prevent AI artifacting
|
||||
deletewi = -1 # Temporary storage for index to delete
|
||||
@ -941,23 +942,51 @@ def download():
|
||||
return(save)
|
||||
|
||||
|
||||
#============================ LUA API =============================#
|
||||
#============================ LUA API =============================#
|
||||
|
||||
if(path.exists("settings/" + getmodelname().replace('/', '_') + ".settings")):
|
||||
file = open("settings/" + getmodelname().replace('/', '_') + ".settings", "r")
|
||||
js = json.load(file)
|
||||
if("userscripts" in js):
|
||||
vars.userscripts = []
|
||||
for userscript in js["userscripts"]:
|
||||
if type(userscript) is not str:
|
||||
continue
|
||||
userscript = userscript.strip()
|
||||
if len(userscript) != 0 and all(q not in userscript for q in ("..", ":")) and all(userscript[0] not in q for q in ("/", "\\")) and os.path.exists(fileops.uspath(userscript)):
|
||||
vars.userscripts.append(userscript)
|
||||
file.close()
|
||||
|
||||
#==================================================================#
|
||||
# Event triggered when a userscript is loaded
|
||||
#==================================================================#
|
||||
def load_callback(filename):
|
||||
print(colors.PURPLE + f"Loading Userscript [USERPLACEHOLDER] <{filename}>" + colors.END)
|
||||
def load_callback(filename, modulename):
|
||||
print(colors.PURPLE + f"Loading Userscript [{modulename}] <{filename}>" + colors.END)
|
||||
|
||||
#==================================================================#
|
||||
# Load all Lua scripts
|
||||
#==================================================================#
|
||||
def load_lua_scripts():
|
||||
print(colors.PURPLE + "Loading Core Script [COREPLACEHOLDER] <default.lua>" + colors.END)
|
||||
|
||||
filenames = []
|
||||
modulenames = []
|
||||
descriptions = []
|
||||
|
||||
lst = fileops.getusfiles(long_desc=True)
|
||||
filenames_dict = {ob["filename"]: i for i, ob in enumerate(lst)}
|
||||
|
||||
for filename in vars.userscripts:
|
||||
if filename in filenames_dict:
|
||||
i = filenames_dict[filename]
|
||||
filenames.append(filename)
|
||||
modulenames.append(lst[i]["modulename"])
|
||||
descriptions.append(lst[i]["description"])
|
||||
|
||||
try:
|
||||
vars.lua_koboldbridge.obliterate_multiverse()
|
||||
vars.lua_koboldbridge.load_corescript("default.lua")
|
||||
vars.lua_koboldbridge.load_userscripts([], [], [])
|
||||
vars.lua_koboldbridge.load_userscripts(filenames, modulenames, descriptions)
|
||||
except lupa.LuaError as e:
|
||||
print(e, file=sys.stderr)
|
||||
exit(1)
|
||||
@ -1534,6 +1563,21 @@ def get_message(msg):
|
||||
getloadlist()
|
||||
elif(msg['cmd'] == 'splistrequest'):
|
||||
getsplist()
|
||||
elif(msg['cmd'] == 'uslistrequest'):
|
||||
getuslist()
|
||||
elif(msg['cmd'] == 'usloaded'):
|
||||
vars.userscripts = []
|
||||
for userscript in msg['data']:
|
||||
if type(userscript) is not str:
|
||||
continue
|
||||
userscript = userscript.strip()
|
||||
if len(userscript) != 0 and all(q not in userscript for q in ("..", ":")) and all(userscript[0] not in q for q in ("/", "\\")) and os.path.exists(fileops.uspath(userscript)):
|
||||
vars.userscripts.append(userscript)
|
||||
settingschanged()
|
||||
elif(msg['cmd'] == 'usload'):
|
||||
load_lua_scripts()
|
||||
elif(msg['cmd'] == 'usload'):
|
||||
getuslist()
|
||||
elif(msg['cmd'] == 'loadselect'):
|
||||
vars.loadselect = msg["data"]
|
||||
elif(msg['cmd'] == 'spselect'):
|
||||
@ -1630,6 +1674,8 @@ def savesettings():
|
||||
js["adventure"] = vars.adventure
|
||||
js["dynamicscan"] = vars.dynamicscan
|
||||
|
||||
js["userscripts"] = vars.userscripts
|
||||
|
||||
# Write it
|
||||
if not os.path.exists('settings'):
|
||||
os.mkdir('settings')
|
||||
@ -1682,6 +1728,15 @@ def loadsettings():
|
||||
if("dynamicscan" in js):
|
||||
vars.dynamicscan = js["dynamicscan"]
|
||||
|
||||
if("userscripts" in js):
|
||||
vars.userscripts = []
|
||||
for userscript in js["userscripts"]:
|
||||
if type(userscript) is not str:
|
||||
continue
|
||||
userscript = userscript.strip()
|
||||
if len(userscript) != 0 and all(q not in userscript for q in ("..", ":")) and all(userscript[0] not in q for q in ("/", "\\")) and os.path.exists(fileops.uspath(userscript)):
|
||||
vars.userscripts.append(userscript)
|
||||
|
||||
file.close()
|
||||
|
||||
#==================================================================#
|
||||
@ -3213,6 +3268,21 @@ def getsplist():
|
||||
if(vars.allowsp):
|
||||
emit('from_server', {'cmd': 'buildsp', 'data': fileops.getspfiles(vars.modeldim)})
|
||||
|
||||
#==================================================================#
|
||||
# Show list of userscripts
|
||||
#==================================================================#
|
||||
def getuslist():
|
||||
files = {i: v for i, v in enumerate(fileops.getusfiles())}
|
||||
loaded = []
|
||||
unloaded = []
|
||||
userscripts = set(vars.userscripts)
|
||||
for i in range(len(files)):
|
||||
if files[i]["filename"] in userscripts:
|
||||
loaded.append(files[i])
|
||||
else:
|
||||
unloaded.append(files[i])
|
||||
emit('from_server', {'cmd': 'buildus', 'data': {"unloaded": unloaded, "loaded": loaded}})
|
||||
|
||||
#==================================================================#
|
||||
# Load a saved story via file browser
|
||||
#==================================================================#
|
||||
@ -3659,11 +3729,6 @@ def randomGameRequest(topic):
|
||||
# Final startup commands to launch Flask app
|
||||
#==================================================================#
|
||||
if __name__ == "__main__":
|
||||
|
||||
# Load settings from client.settings
|
||||
loadmodelsettings()
|
||||
loadsettings()
|
||||
|
||||
# Start Flask/SocketIO (Blocking, so this must be last method!)
|
||||
|
||||
#socketio.run(app, host='0.0.0.0', port=5000)
|
||||
|
@ -1550,7 +1550,7 @@ return function(_python, _bridged)
|
||||
koboldbridge.userscripts = {}
|
||||
koboldbridge.num_userscripts = 0
|
||||
for i, filename in _python.enumerate(filenames) do
|
||||
bridged.load_callback(filename)
|
||||
bridged.load_callback(filename, modulenames[i])
|
||||
---@type KoboldUserScript
|
||||
local _userscript = old_loadfile(join_folder_and_filename(bridged.userscript_path, filename), "t", koboldbridge.get_universe(filename))()
|
||||
local userscript = deepcopy(KoboldUserScriptModule)
|
||||
|
53
fileops.py
53
fileops.py
@ -69,6 +69,12 @@ def storypath(name):
|
||||
def sppath(filename):
|
||||
return path.join(path.dirname(path.realpath(__file__)), "softprompts", filename)
|
||||
|
||||
#==================================================================#
|
||||
# Returns the path (as a string) to the given username by its filename
|
||||
#==================================================================#
|
||||
def uspath(filename):
|
||||
return path.join(path.dirname(path.realpath(__file__)), "userscripts", filename)
|
||||
|
||||
#==================================================================#
|
||||
# Returns an array of dicts containing story files in /stories
|
||||
#==================================================================#
|
||||
@ -158,6 +164,53 @@ def getspfiles(model_dimension: int):
|
||||
lst.append(ob)
|
||||
return lst
|
||||
|
||||
#==================================================================#
|
||||
# Returns an array of dicts containing userscript files in /userscripts
|
||||
#==================================================================#
|
||||
def getusfiles(long_desc=False):
|
||||
lst = []
|
||||
for file in listdir(path.dirname(path.realpath(__file__))+"/userscripts"):
|
||||
if file.endswith(".lua"):
|
||||
ob = {}
|
||||
ob["filename"] = file
|
||||
description = []
|
||||
multiline = False
|
||||
with open(uspath(file)) as f:
|
||||
ob["modulename"] = f.readline().strip().replace("\033", "")
|
||||
if ob["modulename"][:2] != "--":
|
||||
ob["modulename"] = file
|
||||
else:
|
||||
ob["modulename"] = ob["modulename"][2:]
|
||||
if ob["modulename"][:2] == "[[":
|
||||
ob["modulename"] = ob["modulename"][2:]
|
||||
multiline = True
|
||||
ob["modulename"] = ob["modulename"].lstrip("-").strip()
|
||||
for line in f:
|
||||
line = line.strip().replace("\033", "")
|
||||
if multiline:
|
||||
index = line.find("]]")
|
||||
if index > -1:
|
||||
description.append(line[:index])
|
||||
if index != len(line) - 2:
|
||||
break
|
||||
multiline = False
|
||||
else:
|
||||
description.append(line)
|
||||
else:
|
||||
if line[:2] != "--":
|
||||
break
|
||||
line = line[2:]
|
||||
if line[:2] == "[[":
|
||||
multiline = True
|
||||
line = line[2:]
|
||||
description.append(line.strip())
|
||||
ob["description"] = "\n".join(description)
|
||||
if not long_desc:
|
||||
if len(ob["description"]) > 250:
|
||||
ob["description"] = ob["description"][:247] + "..."
|
||||
lst.append(ob)
|
||||
return lst
|
||||
|
||||
#==================================================================#
|
||||
# Returns True if json file exists with requested save name
|
||||
#==================================================================#
|
||||
|
@ -19,6 +19,7 @@ var button_impaidg;
|
||||
var button_settings;
|
||||
var button_format;
|
||||
var button_softprompt;
|
||||
var button_userscripts;
|
||||
var button_mode;
|
||||
var button_mode_label;
|
||||
var button_send;
|
||||
@ -58,6 +59,10 @@ var sppopup;
|
||||
var spcontent;
|
||||
var sp_accept;
|
||||
var sp_close;
|
||||
var uspopup;
|
||||
var uscontent;
|
||||
var us_accept;
|
||||
var us_close;
|
||||
var nspopup;
|
||||
var ns_accept;
|
||||
var ns_close;
|
||||
@ -851,6 +856,17 @@ function hideSPPopup() {
|
||||
spcontent.html("");
|
||||
}
|
||||
|
||||
function showUSPopup() {
|
||||
uspopup.removeClass("hidden");
|
||||
uspopup.addClass("flex");
|
||||
}
|
||||
|
||||
function hideUSPopup() {
|
||||
uspopup.removeClass("flex");
|
||||
uspopup.addClass("hidden");
|
||||
spcontent.html("");
|
||||
}
|
||||
|
||||
function buildLoadList(ar) {
|
||||
disableButtons([load_accept]);
|
||||
loadcontent.html("");
|
||||
@ -954,6 +970,33 @@ function buildSPList(ar) {
|
||||
}
|
||||
}
|
||||
|
||||
function buildUSList(unloaded, loaded) {
|
||||
usunloaded.html("");
|
||||
usloaded.html("");
|
||||
showUSPopup();
|
||||
var i;
|
||||
var j;
|
||||
var el = usunloaded;
|
||||
var ar = unloaded;
|
||||
for(j=0; j<2; j++) {
|
||||
for(i=0; i<ar.length; i++) {
|
||||
el.append("<div class=\"flex\">\
|
||||
<div class=\"uslistitem flex-row-container\" name=\""+ar[i].filename+"\">\
|
||||
<div class=\"flex-row\">\
|
||||
<div>"+ar[i].modulename+"</div>\
|
||||
<div class=\"flex-push-right uslistitemsub\"><"+ar[i].filename+"></div>\
|
||||
</div>\
|
||||
<div class=\"flex-row\">\
|
||||
<div>"+ar[i].description+"</div>\
|
||||
</div>\
|
||||
</div>\
|
||||
</div>");
|
||||
}
|
||||
el = usloaded;
|
||||
ar = loaded;
|
||||
}
|
||||
}
|
||||
|
||||
function highlightLoadLine(ref) {
|
||||
$("#loadlistcontent > div > div.popuplistselected").removeClass("popuplistselected");
|
||||
ref.addClass("popuplistselected");
|
||||
@ -1521,6 +1564,7 @@ $(document).ready(function(){
|
||||
button_settings = $('#btn_settings');
|
||||
button_format = $('#btn_format');
|
||||
button_softprompt = $("#btn_softprompt");
|
||||
button_userscripts= $("#btn_userscripts");
|
||||
button_mode = $('#btnmode')
|
||||
button_mode_label = $('#btnmode_label')
|
||||
button_send = $('#btnsend');
|
||||
@ -1560,6 +1604,11 @@ $(document).ready(function(){
|
||||
spcontent = $("#splistcontent");
|
||||
sp_accept = $("#btn_spaccept");
|
||||
sp_close = $("#btn_spclose");
|
||||
uspopup = $("#uscontainer");
|
||||
usunloaded = $("#uslistunloaded");
|
||||
usloaded = $("#uslistloaded");
|
||||
us_accept = $("#btn_usaccept");
|
||||
us_close = $("#btn_usclose");
|
||||
nspopup = $("#newgamecontainer");
|
||||
ns_accept = $("#btn_nsaccept");
|
||||
ns_close = $("#btn_nsclose");
|
||||
@ -1928,6 +1977,8 @@ $(document).ready(function(){
|
||||
buildLoadList(msg.data);
|
||||
} else if(msg.cmd == "buildsp") {
|
||||
buildSPList(msg.data);
|
||||
} else if(msg.cmd == "buildus") {
|
||||
buildUSList(msg.data.unloaded, msg.data.loaded);
|
||||
} else if(msg.cmd == "askforoverwrite") {
|
||||
// Show overwrite warning
|
||||
show([$(".saveasoverwrite")]);
|
||||
@ -2006,6 +2057,23 @@ $(document).ready(function(){
|
||||
}, 2);
|
||||
});
|
||||
|
||||
// Make the userscripts menu sortable
|
||||
var us_sortable_settings = {
|
||||
delay: 2,
|
||||
cursor: "move",
|
||||
tolerance: "pointer",
|
||||
opacity: 0.21,
|
||||
revert: 173,
|
||||
scrollSensitivity: 64,
|
||||
scrollSpeed: 10,
|
||||
}
|
||||
$(usunloaded).sortable($.extend({
|
||||
connectWith: "#uslistloaded",
|
||||
}, us_sortable_settings));
|
||||
$(usloaded).sortable($.extend({
|
||||
connectWith: "#uslistunloaded",
|
||||
}, us_sortable_settings));
|
||||
|
||||
// Bind actions to UI buttons
|
||||
button_send.on("click", function(ev) {
|
||||
dosubmit();
|
||||
@ -2124,6 +2192,10 @@ $(document).ready(function(){
|
||||
button_softprompt.on("click", function(ev) {
|
||||
socket.send({'cmd': 'splistrequest', 'data': ''});
|
||||
});
|
||||
|
||||
button_userscripts.on("click", function(ev) {
|
||||
socket.send({'cmd': 'uslistrequest', 'data': ''});
|
||||
});
|
||||
|
||||
load_close.on("click", function(ev) {
|
||||
hideLoadPopup();
|
||||
@ -2143,6 +2215,17 @@ $(document).ready(function(){
|
||||
socket.send({'cmd': 'sprequest', 'data': ''});
|
||||
hideSPPopup();
|
||||
});
|
||||
|
||||
us_close.on("click", function(ev) {
|
||||
socket.send({'cmd': 'usloaded', 'data': usloaded.find(".uslistitem").map(function() { return $(this).attr("name"); }).toArray()});
|
||||
hideUSPopup();
|
||||
});
|
||||
|
||||
us_accept.on("click", function(ev) {
|
||||
socket.send({'cmd': 'usloaded', 'data': usloaded.find(".uslistitem").map(function() { return $(this).attr("name"); }).toArray()});
|
||||
socket.send({'cmd': 'usload', 'data': ''});
|
||||
hideUSPopup();
|
||||
});
|
||||
|
||||
button_newgame.on("click", function(ev) {
|
||||
showNewStoryPopup();
|
||||
|
@ -316,13 +316,13 @@ chunk.editing, chunk.editing * {
|
||||
}
|
||||
|
||||
#sppopup {
|
||||
width: 500px;
|
||||
width: 800px;
|
||||
background-color: #262626;
|
||||
margin-top: 100px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
#loadpopup {
|
||||
#sppopup {
|
||||
width: 100%;
|
||||
background-color: #262626;
|
||||
margin-top: 100px;
|
||||
@ -342,7 +342,33 @@ chunk.editing, chunk.editing * {
|
||||
}
|
||||
|
||||
#splistcontent {
|
||||
height: 325px;
|
||||
height: 425px;
|
||||
overflow-y: scroll;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
#uspopup {
|
||||
width: 800px;
|
||||
background-color: #262626;
|
||||
margin-top: 100px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
#uspopup {
|
||||
width: 100%;
|
||||
background-color: #262626;
|
||||
margin-top: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
#uslistunloaded {
|
||||
height: 425px;
|
||||
overflow-y: scroll;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
#uslistloaded {
|
||||
height: 425px;
|
||||
overflow-y: scroll;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
@ -807,6 +833,11 @@ chunk.editing, chunk.editing * {
|
||||
color: #fce94f
|
||||
}
|
||||
|
||||
.uslistgrid {
|
||||
display: grid;
|
||||
grid-template-columns: 50% 50%;
|
||||
}
|
||||
|
||||
.navbar .navbar-nav .nav-link:hover {
|
||||
border-radius: 5px;
|
||||
background-color: #98bcdb;
|
||||
@ -1020,6 +1051,27 @@ chunk.editing, chunk.editing * {
|
||||
background-color: #688f1f;
|
||||
}
|
||||
|
||||
.uslistitem {
|
||||
padding: 12px 10px 12px 10px;
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
color: #ffffff;
|
||||
|
||||
-moz-transition: background-color 0.25s ease-in;
|
||||
-o-transition: background-color 0.25s ease-in;
|
||||
-webkit-transition: background-color 0.25s ease-in;
|
||||
transition: background-color 0.25s ease-in;
|
||||
}
|
||||
|
||||
.uslistitemsub {
|
||||
color: #ba9;
|
||||
}
|
||||
|
||||
.uslistitem:hover {
|
||||
cursor: move;
|
||||
background-color: #688f1f;
|
||||
}
|
||||
|
||||
.width-auto {
|
||||
width: auto;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
<script src="static/jquery-3.6.0.min.js"></script>
|
||||
<script src="static/jquery-ui.sortable.min.js"></script>
|
||||
<script src="static/socket.io.min.js"></script>
|
||||
<script src="static/application.js?ver=1.16.4c"></script>
|
||||
<script src="static/application.js?ver=1.16.4d"></script>
|
||||
<script src="static/bootstrap.min.js"></script>
|
||||
<script src="static/bootstrap-toggle.min.js"></script>
|
||||
<script src="static/rangy-core.min.js"></script>
|
||||
@ -15,7 +15,7 @@
|
||||
<link rel="stylesheet" href="static/jquery-ui.sortable.min.css">
|
||||
<link rel="stylesheet" href="static/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="static/bootstrap-toggle.min.css">
|
||||
<link rel="stylesheet" href="static/custom.css?ver=1.16.4c">
|
||||
<link rel="stylesheet" href="static/custom.css?ver=1.16.4d">
|
||||
<link rel="stylesheet" href="static/open-iconic-bootstrap.min.css">
|
||||
</head>
|
||||
<body>
|
||||
@ -70,6 +70,9 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#" id="btn_format">Formatting</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#" id="btn_userscripts">Userscripts</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link hidden" href="#" id="btn_softprompt">Soft Prompt</a>
|
||||
</li>
|
||||
@ -244,6 +247,23 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="popupcontainer hidden" id="uscontainer">
|
||||
<div id="uspopup">
|
||||
<div class="popuptitlebar">
|
||||
<div class="popuptitletext">Select userscripts to load; drag-and-drop to reorder</div>
|
||||
</div>
|
||||
<div class="uslistgrid">
|
||||
<div id="uslistunloaded">
|
||||
</div>
|
||||
<div id="uslistloaded">
|
||||
</div>
|
||||
</div>
|
||||
<div class="popupfooter">
|
||||
<button type="button" class="btn btn-primary" id="btn_usaccept">Load</button>
|
||||
<button type="button" class="btn btn-primary" id="btn_usclose">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="popupcontainer hidden" id="loadcontainerdelete">
|
||||
<div id="loadpopupdelete">
|
||||
<div class="popuptitlebar">
|
||||
|
Loading…
x
Reference in New Issue
Block a user