Merge pull request #49 from VE-FORBRYDERNE/gui-and-scripting
Scripting and GUI improvements
This commit is contained in:
commit
726b42889b
138
aiserver.py
138
aiserver.py
|
@ -82,6 +82,7 @@ class vars:
|
||||||
submission = "" # Same as above, but after applying input formatting
|
submission = "" # Same as above, but after applying input formatting
|
||||||
lastctx = "" # The last context submitted to the generator
|
lastctx = "" # The last context submitted to the generator
|
||||||
model = "" # Model ID string chosen at startup
|
model = "" # Model ID string chosen at startup
|
||||||
|
model_orig = "" # Original model string before being changed by auto model type detection
|
||||||
model_type = "" # Model Type (Automatically taken from the model config)
|
model_type = "" # Model Type (Automatically taken from the model config)
|
||||||
noai = False # Runs the script without starting up the transformers pipeline
|
noai = False # Runs the script without starting up the transformers pipeline
|
||||||
aibusy = False # Stops submissions while the AI is working
|
aibusy = False # Stops submissions while the AI is working
|
||||||
|
@ -113,9 +114,12 @@ class vars:
|
||||||
lua_kobold = None # `kobold` from` bridge.lua
|
lua_kobold = None # `kobold` from` bridge.lua
|
||||||
lua_koboldcore = None # `koboldcore` from bridge.lua
|
lua_koboldcore = None # `koboldcore` from bridge.lua
|
||||||
lua_logname = ... # Name of previous userscript that logged to terminal
|
lua_logname = ... # Name of previous userscript that logged to terminal
|
||||||
|
lua_running = False # Whether or not Lua is running (i.e. wasn't stopped due to an error)
|
||||||
lua_edited = set() # Set of chunk numbers that were edited from a Lua generation modifier
|
lua_edited = set() # Set of chunk numbers that were edited from a Lua generation modifier
|
||||||
lua_deleted = set() # Set of chunk numbers that were deleted from a Lua generation modifier
|
lua_deleted = set() # Set of chunk numbers that were deleted from a Lua generation modifier
|
||||||
|
spfilename = "" # Filename of soft prompt to load, or an empty string if not using a soft prompt
|
||||||
userscripts = [] # List of userscripts to load
|
userscripts = [] # List of userscripts to load
|
||||||
|
last_userscripts = [] # List of previous userscript filenames from the previous time userscripts were send via usstatitems
|
||||||
corescript = "default.lua" # Filename of corescript to load
|
corescript = "default.lua" # Filename of corescript to load
|
||||||
# badwords = [] # Array of str/chr values that should be removed from output
|
# 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
|
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
|
||||||
|
@ -140,6 +144,7 @@ class vars:
|
||||||
importjs = {} # Temporary storage for import data
|
importjs = {} # Temporary storage for import data
|
||||||
loadselect = "" # Temporary storage for story filename to load
|
loadselect = "" # Temporary storage for story filename to load
|
||||||
spselect = "" # Temporary storage for soft prompt filename to load
|
spselect = "" # Temporary storage for soft prompt filename to load
|
||||||
|
spmeta = None # Metadata of current soft prompt, or None if not using a soft prompt
|
||||||
sp = None # Current soft prompt tensor (as a NumPy array)
|
sp = None # Current soft prompt tensor (as a NumPy array)
|
||||||
sp_length = 0 # Length of current soft prompt in tokens, or 0 if not using a soft prompt
|
sp_length = 0 # Length of current soft prompt in tokens, or 0 if not using a soft prompt
|
||||||
svowname = "" # Filename that was flagged for overwrite confirm
|
svowname = "" # Filename that was flagged for overwrite confirm
|
||||||
|
@ -180,7 +185,7 @@ def getModelSelection():
|
||||||
while(vars.model == ''):
|
while(vars.model == ''):
|
||||||
modelsel = input("Model #> ")
|
modelsel = input("Model #> ")
|
||||||
if(modelsel.isnumeric() and int(modelsel) > 0 and int(modelsel) <= len(modellist)):
|
if(modelsel.isnumeric() and int(modelsel) > 0 and int(modelsel) <= len(modellist)):
|
||||||
vars.model = modellist[int(modelsel)-1][1]
|
vars.model = vars.model_orig = modellist[int(modelsel)-1][1]
|
||||||
else:
|
else:
|
||||||
print("{0}Please enter a valid selection.{1}".format(colors.RED, colors.END))
|
print("{0}Please enter a valid selection.{1}".format(colors.RED, colors.END))
|
||||||
|
|
||||||
|
@ -361,7 +366,7 @@ parser.add_argument("--override_rename", action='store_true', help="Renaming sto
|
||||||
parser.add_argument("--configname", help="Force a fixed configuration name to aid with config management.")
|
parser.add_argument("--configname", help="Force a fixed configuration name to aid with config management.")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
vars.model = args.model;
|
vars.model = vars.model_orig = args.model;
|
||||||
|
|
||||||
if args.remote:
|
if args.remote:
|
||||||
vars.remote = True;
|
vars.remote = True;
|
||||||
|
@ -646,7 +651,22 @@ if(not vars.model in ["InferKit", "Colab", "OAI", "ReadOnly", "TPUMeshTransforme
|
||||||
|
|
||||||
|
|
||||||
# Patch transformers to use our custom logit warpers
|
# Patch transformers to use our custom logit warpers
|
||||||
from transformers import LogitsProcessorList, LogitsWarper, LogitsProcessor, TopKLogitsWarper, TopPLogitsWarper, TemperatureLogitsWarper
|
from transformers import LogitsProcessorList, LogitsWarper, LogitsProcessor, TopKLogitsWarper, TopPLogitsWarper, TemperatureLogitsWarper, RepetitionPenaltyLogitsProcessor
|
||||||
|
|
||||||
|
def dynamic_processor_wrap(cls, field_name, var_name, cond=None):
|
||||||
|
old_call = cls.__call__
|
||||||
|
def new_call(self, *args, **kwargs):
|
||||||
|
setattr(self, field_name, getattr(vars, var_name))
|
||||||
|
assert len(args) == 2
|
||||||
|
if(cond is None or cond(getattr(vars, var_name))):
|
||||||
|
return old_call(self, *args, **kwargs)
|
||||||
|
return args[1]
|
||||||
|
cls.__call__ = new_call
|
||||||
|
dynamic_processor_wrap(RepetitionPenaltyLogitsProcessor, "penalty", "rep_pen", cond=lambda x: x != 1.0)
|
||||||
|
dynamic_processor_wrap(TopKLogitsWarper, "top_k", "top_k", cond=lambda x: x > 0)
|
||||||
|
dynamic_processor_wrap(TopPLogitsWarper, "top_p", "top_p", cond=lambda x: x < 1.0)
|
||||||
|
dynamic_processor_wrap(TemperatureLogitsWarper, "temperature", "temp", cond=lambda x: x != 1.0)
|
||||||
|
|
||||||
class TailFreeLogitsWarper(LogitsWarper):
|
class TailFreeLogitsWarper(LogitsWarper):
|
||||||
|
|
||||||
def __init__(self, tfs: float, filter_value: float = -float("Inf"), min_tokens_to_keep: int = 1):
|
def __init__(self, tfs: float, filter_value: float = -float("Inf"), min_tokens_to_keep: int = 1):
|
||||||
|
@ -658,6 +678,8 @@ if(not vars.model in ["InferKit", "Colab", "OAI", "ReadOnly", "TPUMeshTransforme
|
||||||
self.min_tokens_to_keep = min_tokens_to_keep
|
self.min_tokens_to_keep = min_tokens_to_keep
|
||||||
|
|
||||||
def __call__(self, input_ids: torch.LongTensor, scores: torch.FloatTensor) -> torch.FloatTensor:
|
def __call__(self, input_ids: torch.LongTensor, scores: torch.FloatTensor) -> torch.FloatTensor:
|
||||||
|
self.tfs = vars.tfs
|
||||||
|
|
||||||
if self.filter_value >= 1.0:
|
if self.filter_value >= 1.0:
|
||||||
return scores
|
return scores
|
||||||
sorted_logits, sorted_indices = torch.sort(scores, descending=True)
|
sorted_logits, sorted_indices = torch.sort(scores, descending=True)
|
||||||
|
@ -725,31 +747,17 @@ if(not vars.model in ["InferKit", "Colab", "OAI", "ReadOnly", "TPUMeshTransforme
|
||||||
new_get_logits_processor.old_get_logits_processor = transformers.generation_utils.GenerationMixin._get_logits_processor
|
new_get_logits_processor.old_get_logits_processor = transformers.generation_utils.GenerationMixin._get_logits_processor
|
||||||
transformers.generation_utils.GenerationMixin._get_logits_processor = new_get_logits_processor
|
transformers.generation_utils.GenerationMixin._get_logits_processor = new_get_logits_processor
|
||||||
|
|
||||||
def new_get_logits_warper(
|
def new_get_logits_warper(beams: int = 1,) -> LogitsProcessorList:
|
||||||
top_k: int = None,
|
|
||||||
top_p: float = None,
|
|
||||||
tfs: float = None,
|
|
||||||
temp: float = None,
|
|
||||||
beams: int = 1,
|
|
||||||
) -> LogitsProcessorList:
|
|
||||||
warper_list = LogitsProcessorList()
|
warper_list = LogitsProcessorList()
|
||||||
if(top_k is not None and top_k > 0):
|
warper_list.append(TopKLogitsWarper(top_k=1, min_tokens_to_keep=1 + (beams > 1)))
|
||||||
warper_list.append(TopKLogitsWarper(top_k=top_k, min_tokens_to_keep=1 + (beams > 1)))
|
warper_list.append(TopPLogitsWarper(top_p=0.5, min_tokens_to_keep=1 + (beams > 1)))
|
||||||
if(top_p is not None and top_p < 1.0):
|
warper_list.append(TailFreeLogitsWarper(tfs=0.5, min_tokens_to_keep=1 + (beams > 1)))
|
||||||
warper_list.append(TopPLogitsWarper(top_p=top_p, min_tokens_to_keep=1 + (beams > 1)))
|
warper_list.append(TemperatureLogitsWarper(temperature=0.5))
|
||||||
if(tfs is not None and tfs < 1.0):
|
|
||||||
warper_list.append(TailFreeLogitsWarper(tfs=tfs, min_tokens_to_keep=1 + (beams > 1)))
|
|
||||||
if(temp is not None and temp != 1.0):
|
|
||||||
warper_list.append(TemperatureLogitsWarper(temperature=temp))
|
|
||||||
return warper_list
|
return warper_list
|
||||||
|
|
||||||
def new_sample(self, *args, **kwargs):
|
def new_sample(self, *args, **kwargs):
|
||||||
assert kwargs.pop("logits_warper", None) is not None
|
assert kwargs.pop("logits_warper", None) is not None
|
||||||
kwargs["logits_warper"] = new_get_logits_warper(
|
kwargs["logits_warper"] = new_get_logits_warper(
|
||||||
top_k=vars.top_k,
|
|
||||||
top_p=vars.top_p,
|
|
||||||
tfs=vars.tfs,
|
|
||||||
temp=vars.temp,
|
|
||||||
beams=1,
|
beams=1,
|
||||||
)
|
)
|
||||||
return new_sample.old_sample(self, *args, **kwargs)
|
return new_sample.old_sample(self, *args, **kwargs)
|
||||||
|
@ -1048,10 +1056,13 @@ def load_lua_scripts():
|
||||||
vars.lua_koboldbridge.obliterate_multiverse()
|
vars.lua_koboldbridge.obliterate_multiverse()
|
||||||
tpool.execute(vars.lua_koboldbridge.load_corescript, vars.corescript)
|
tpool.execute(vars.lua_koboldbridge.load_corescript, vars.corescript)
|
||||||
tpool.execute(vars.lua_koboldbridge.load_userscripts, filenames, modulenames, descriptions)
|
tpool.execute(vars.lua_koboldbridge.load_userscripts, filenames, modulenames, descriptions)
|
||||||
|
vars.lua_running = True
|
||||||
except lupa.LuaError as e:
|
except lupa.LuaError as e:
|
||||||
vars.lua_koboldbridge.obliterate_multiverse()
|
vars.lua_koboldbridge.obliterate_multiverse()
|
||||||
|
vars.lua_running = False
|
||||||
if(vars.serverstarted):
|
if(vars.serverstarted):
|
||||||
emit('from_server', {'cmd': 'errmsg', 'data': 'Lua script error, please check console.'}, broadcast=True)
|
emit('from_server', {'cmd': 'errmsg', 'data': 'Lua script error, please check console.'}, broadcast=True)
|
||||||
|
sendUSStatItems()
|
||||||
print("{0}{1}{2}".format(colors.RED, "***LUA ERROR***: ", colors.END), end="", file=sys.stderr)
|
print("{0}{1}{2}".format(colors.RED, "***LUA ERROR***: ", colors.END), end="", file=sys.stderr)
|
||||||
print("{0}{1}{2}".format(colors.RED, str(e).replace("\033", ""), colors.END), file=sys.stderr)
|
print("{0}{1}{2}".format(colors.RED, str(e).replace("\033", ""), colors.END), file=sys.stderr)
|
||||||
print("{0}{1}{2}".format(colors.YELLOW, "Lua engine stopped; please open 'Userscripts' and press Load to reinitialize scripts.", colors.END), file=sys.stderr)
|
print("{0}{1}{2}".format(colors.YELLOW, "Lua engine stopped; please open 'Userscripts' and press Load to reinitialize scripts.", colors.END), file=sys.stderr)
|
||||||
|
@ -1376,23 +1387,23 @@ def lua_get_modeltype():
|
||||||
return "readonly"
|
return "readonly"
|
||||||
if(vars.model in ("Colab", "OAI", "InferKit")):
|
if(vars.model in ("Colab", "OAI", "InferKit")):
|
||||||
return "api"
|
return "api"
|
||||||
if(vars.model in ("GPT2Custom", "NeoCustom")):
|
if(vars.model not in ("TPUMeshTransformerGPTJ",) and (vars.model in ("GPT2Custom", "NeoCustom") or vars.model_type in ("gpt2", "gpt_neo", "gptj"))):
|
||||||
hidden_size = get_hidden_size_from_model(model)
|
hidden_size = get_hidden_size_from_model(model)
|
||||||
if(vars.model in ("gpt2",) or (vars.model == "GPT2Custom" and hidden_size == 768)):
|
if(vars.model in ("gpt2",) or (vars.model_type == "gpt2" and hidden_size == 768)):
|
||||||
return "gpt2"
|
return "gpt2"
|
||||||
if(vars.model in ("gpt2-medium",) or (vars.model == "GPT2Custom" and hidden_size == 1024)):
|
if(vars.model in ("gpt2-medium",) or (vars.model_type == "gpt2" and hidden_size == 1024)):
|
||||||
return "gpt2-medium"
|
return "gpt2-medium"
|
||||||
if(vars.model in ("gpt2-large",) or (vars.model == "GPT2Custom" and hidden_size == 1280)):
|
if(vars.model in ("gpt2-large",) or (vars.model_type == "gpt2" and hidden_size == 1280)):
|
||||||
return "gpt2-large"
|
return "gpt2-large"
|
||||||
if(vars.model in ("gpt2-xl",) or (vars.model == "GPT2Custom" and hidden_size == 1600)):
|
if(vars.model in ("gpt2-xl",) or (vars.model_type == "gpt2" and hidden_size == 1600)):
|
||||||
return "gpt2-xl"
|
return "gpt2-xl"
|
||||||
if(vars.model == "NeoCustom" and hidden_size == 768):
|
if(vars.model_type == "gpt_neo" and hidden_size == 768):
|
||||||
return "gpt-neo-125M"
|
return "gpt-neo-125M"
|
||||||
if(vars.model in ("EleutherAI/gpt-neo-1.3B",) or (vars.model == "NeoCustom" and hidden_size == 2048)):
|
if(vars.model in ("EleutherAI/gpt-neo-1.3B",) or (vars.model_type == "gpt_neo" and hidden_size == 2048)):
|
||||||
return "gpt-neo-1.3B"
|
return "gpt-neo-1.3B"
|
||||||
if(vars.model in ("EleutherAI/gpt-neo-2.7B",) or (vars.model == "NeoCustom" and hidden_size == 2560)):
|
if(vars.model in ("EleutherAI/gpt-neo-2.7B",) or (vars.model_type == "gpt_neo" and hidden_size == 2560)):
|
||||||
return "gpt-neo-2.7B"
|
return "gpt-neo-2.7B"
|
||||||
if(vars.model in ("EleutherAI/gpt-j-6B",) or (vars.model == "NeoCustom" and hidden_size == 4096) or (vars.model == "TPUMeshTransformerGPTJ" and tpu_mtj_backend.params["d_model"] == 4096)):
|
if(vars.model in ("EleutherAI/gpt-j-6B",) or (vars.model == "TPUMeshTransformerGPTJ" and tpu_mtj_backend.params["d_model"] == 4096) or (vars.model_type in ("gpt_neo", "gptj") and hidden_size == 4096)):
|
||||||
return "gpt-j-6B"
|
return "gpt-j-6B"
|
||||||
return "unknown"
|
return "unknown"
|
||||||
|
|
||||||
|
@ -1423,7 +1434,9 @@ def execute_inmod():
|
||||||
tpool.execute(vars.lua_koboldbridge.execute_inmod)
|
tpool.execute(vars.lua_koboldbridge.execute_inmod)
|
||||||
except lupa.LuaError as e:
|
except lupa.LuaError as e:
|
||||||
vars.lua_koboldbridge.obliterate_multiverse()
|
vars.lua_koboldbridge.obliterate_multiverse()
|
||||||
|
vars.lua_running = False
|
||||||
emit('from_server', {'cmd': 'errmsg', 'data': 'Lua script error, please check console.'}, broadcast=True)
|
emit('from_server', {'cmd': 'errmsg', 'data': 'Lua script error, please check console.'}, broadcast=True)
|
||||||
|
sendUSStatItems()
|
||||||
print("{0}{1}{2}".format(colors.RED, "***LUA ERROR***: ", colors.END), end="", file=sys.stderr)
|
print("{0}{1}{2}".format(colors.RED, "***LUA ERROR***: ", colors.END), end="", file=sys.stderr)
|
||||||
print("{0}{1}{2}".format(colors.RED, str(e).replace("\033", ""), colors.END), file=sys.stderr)
|
print("{0}{1}{2}".format(colors.RED, str(e).replace("\033", ""), colors.END), file=sys.stderr)
|
||||||
print("{0}{1}{2}".format(colors.YELLOW, "Lua engine stopped; please open 'Userscripts' and press Load to reinitialize scripts.", colors.END), file=sys.stderr)
|
print("{0}{1}{2}".format(colors.YELLOW, "Lua engine stopped; please open 'Userscripts' and press Load to reinitialize scripts.", colors.END), file=sys.stderr)
|
||||||
|
@ -1439,7 +1452,9 @@ def execute_outmod():
|
||||||
tpool.execute(vars.lua_koboldbridge.execute_outmod)
|
tpool.execute(vars.lua_koboldbridge.execute_outmod)
|
||||||
except lupa.LuaError as e:
|
except lupa.LuaError as e:
|
||||||
vars.lua_koboldbridge.obliterate_multiverse()
|
vars.lua_koboldbridge.obliterate_multiverse()
|
||||||
|
vars.lua_running = False
|
||||||
emit('from_server', {'cmd': 'errmsg', 'data': 'Lua script error, please check console.'}, broadcast=True)
|
emit('from_server', {'cmd': 'errmsg', 'data': 'Lua script error, please check console.'}, broadcast=True)
|
||||||
|
sendUSStatItems()
|
||||||
print("{0}{1}{2}".format(colors.RED, "***LUA ERROR***: ", colors.END), end="", file=sys.stderr)
|
print("{0}{1}{2}".format(colors.RED, "***LUA ERROR***: ", colors.END), end="", file=sys.stderr)
|
||||||
print("{0}{1}{2}".format(colors.RED, str(e).replace("\033", ""), colors.END), file=sys.stderr)
|
print("{0}{1}{2}".format(colors.RED, str(e).replace("\033", ""), colors.END), file=sys.stderr)
|
||||||
print("{0}{1}{2}".format(colors.YELLOW, "Lua engine stopped; please open 'Userscripts' and press Load to reinitialize scripts.", colors.END), file=sys.stderr)
|
print("{0}{1}{2}".format(colors.YELLOW, "Lua engine stopped; please open 'Userscripts' and press Load to reinitialize scripts.", colors.END), file=sys.stderr)
|
||||||
|
@ -1465,7 +1480,8 @@ vars.lua_state = lupa.LuaRuntime(unpack_returned_tuples=True)
|
||||||
bridged = {
|
bridged = {
|
||||||
"corescript_path": os.path.join(os.path.dirname(os.path.realpath(__file__)), "cores"),
|
"corescript_path": os.path.join(os.path.dirname(os.path.realpath(__file__)), "cores"),
|
||||||
"userscript_path": os.path.join(os.path.dirname(os.path.realpath(__file__)), "userscripts"),
|
"userscript_path": os.path.join(os.path.dirname(os.path.realpath(__file__)), "userscripts"),
|
||||||
"lib_path": os.path.join(os.path.dirname(os.path.realpath(__file__)), "extern", "lualibs"),
|
"config_path": os.path.join(os.path.dirname(os.path.realpath(__file__)), "userscripts"),
|
||||||
|
"lib_paths": vars.lua_state.table(os.path.join(os.path.dirname(os.path.realpath(__file__)), "lualibs"), os.path.join(os.path.dirname(os.path.realpath(__file__)), "extern", "lualibs")),
|
||||||
"load_callback": load_callback,
|
"load_callback": load_callback,
|
||||||
"print": lua_print,
|
"print": lua_print,
|
||||||
"warn": lua_warn,
|
"warn": lua_warn,
|
||||||
|
@ -1524,6 +1540,9 @@ def do_connect():
|
||||||
if(vars.allowsp):
|
if(vars.allowsp):
|
||||||
emit('from_server', {'cmd': 'allowsp', 'data': vars.allowsp})
|
emit('from_server', {'cmd': 'allowsp', 'data': vars.allowsp})
|
||||||
|
|
||||||
|
sendUSStatItems()
|
||||||
|
emit('from_server', {'cmd': 'spstatitems', 'data': {vars.spfilename: vars.spmeta} if vars.allowsp and len(vars.spfilename) else {}}, broadcast=True)
|
||||||
|
|
||||||
if(not vars.gamestarted):
|
if(not vars.gamestarted):
|
||||||
setStartState()
|
setStartState()
|
||||||
sendsettings()
|
sendsettings()
|
||||||
|
@ -1714,6 +1733,12 @@ def get_message(msg):
|
||||||
elif(msg['cmd'] == 'wiexpandfolder'):
|
elif(msg['cmd'] == 'wiexpandfolder'):
|
||||||
assert 0 <= int(msg['data']) < len(vars.worldinfo)
|
assert 0 <= int(msg['data']) < len(vars.worldinfo)
|
||||||
emit('from_server', {'cmd': 'wiexpandfolder', 'data': msg['data']}, broadcast=True)
|
emit('from_server', {'cmd': 'wiexpandfolder', 'data': msg['data']}, broadcast=True)
|
||||||
|
elif(msg['cmd'] == 'wifoldercollapsecontent'):
|
||||||
|
vars.wifolders_d[msg['data']]['collapsed'] = True
|
||||||
|
emit('from_server', {'cmd': 'wifoldercollapsecontent', 'data': msg['data']}, broadcast=True)
|
||||||
|
elif(msg['cmd'] == 'wifolderexpandcontent'):
|
||||||
|
vars.wifolders_d[msg['data']]['collapsed'] = False
|
||||||
|
emit('from_server', {'cmd': 'wifolderexpandcontent', 'data': msg['data']}, broadcast=True)
|
||||||
elif(msg['cmd'] == 'wiupdate'):
|
elif(msg['cmd'] == 'wiupdate'):
|
||||||
num = int(msg['num'])
|
num = int(msg['num'])
|
||||||
fields = ("key", "keysecondary", "content", "comment")
|
fields = ("key", "keysecondary", "content", "comment")
|
||||||
|
@ -1753,7 +1778,8 @@ def get_message(msg):
|
||||||
elif(msg['cmd'] == 'splistrequest'):
|
elif(msg['cmd'] == 'splistrequest'):
|
||||||
getsplist()
|
getsplist()
|
||||||
elif(msg['cmd'] == 'uslistrequest'):
|
elif(msg['cmd'] == 'uslistrequest'):
|
||||||
getuslist()
|
unloaded, loaded = getuslist()
|
||||||
|
emit('from_server', {'cmd': 'buildus', 'data': {"unloaded": unloaded, "loaded": loaded}})
|
||||||
elif(msg['cmd'] == 'usloaded'):
|
elif(msg['cmd'] == 'usloaded'):
|
||||||
vars.userscripts = []
|
vars.userscripts = []
|
||||||
for userscript in msg['data']:
|
for userscript in msg['data']:
|
||||||
|
@ -1765,8 +1791,8 @@ def get_message(msg):
|
||||||
settingschanged()
|
settingschanged()
|
||||||
elif(msg['cmd'] == 'usload'):
|
elif(msg['cmd'] == 'usload'):
|
||||||
load_lua_scripts()
|
load_lua_scripts()
|
||||||
elif(msg['cmd'] == 'usload'):
|
unloaded, loaded = getuslist()
|
||||||
getuslist()
|
sendUSStatItems()
|
||||||
elif(msg['cmd'] == 'loadselect'):
|
elif(msg['cmd'] == 'loadselect'):
|
||||||
vars.loadselect = msg["data"]
|
vars.loadselect = msg["data"]
|
||||||
elif(msg['cmd'] == 'spselect'):
|
elif(msg['cmd'] == 'spselect'):
|
||||||
|
@ -1775,6 +1801,7 @@ def get_message(msg):
|
||||||
loadRequest(fileops.storypath(vars.loadselect))
|
loadRequest(fileops.storypath(vars.loadselect))
|
||||||
elif(msg['cmd'] == 'sprequest'):
|
elif(msg['cmd'] == 'sprequest'):
|
||||||
spRequest(vars.spselect)
|
spRequest(vars.spselect)
|
||||||
|
emit('from_server', {'cmd': 'spstatitems', 'data': {vars.spfilename: vars.spmeta} if vars.allowsp and len(vars.spfilename) else {}}, broadcast=True)
|
||||||
elif(msg['cmd'] == 'deletestory'):
|
elif(msg['cmd'] == 'deletestory'):
|
||||||
deletesave(msg['data'])
|
deletesave(msg['data'])
|
||||||
elif(msg['cmd'] == 'renamestory'):
|
elif(msg['cmd'] == 'renamestory'):
|
||||||
|
@ -1813,6 +1840,16 @@ def get_message(msg):
|
||||||
elif(not vars.remote and msg['cmd'] == 'importwi'):
|
elif(not vars.remote and msg['cmd'] == 'importwi'):
|
||||||
wiimportrequest()
|
wiimportrequest()
|
||||||
|
|
||||||
|
#==================================================================#
|
||||||
|
# Send userscripts list to client
|
||||||
|
#==================================================================#
|
||||||
|
def sendUSStatItems():
|
||||||
|
_, loaded = getuslist()
|
||||||
|
loaded = loaded if vars.lua_running else []
|
||||||
|
last_userscripts = [e["filename"] for e in loaded]
|
||||||
|
emit('from_server', {'cmd': 'usstatitems', 'data': loaded, 'flash': last_userscripts != vars.last_userscripts}, broadcast=True)
|
||||||
|
vars.last_userscripts = last_userscripts
|
||||||
|
|
||||||
#==================================================================#
|
#==================================================================#
|
||||||
# Send start message and tell Javascript to set UI state
|
# Send start message and tell Javascript to set UI state
|
||||||
#==================================================================#
|
#==================================================================#
|
||||||
|
@ -1870,6 +1907,7 @@ def savesettings():
|
||||||
|
|
||||||
js["userscripts"] = vars.userscripts
|
js["userscripts"] = vars.userscripts
|
||||||
js["corescript"] = vars.corescript
|
js["corescript"] = vars.corescript
|
||||||
|
js["softprompt"] = vars.spfilename
|
||||||
|
|
||||||
# Write it
|
# Write it
|
||||||
if not os.path.exists('settings'):
|
if not os.path.exists('settings'):
|
||||||
|
@ -1939,6 +1977,11 @@ def loadsettings():
|
||||||
else:
|
else:
|
||||||
vars.corescript = "default.lua"
|
vars.corescript = "default.lua"
|
||||||
|
|
||||||
|
if(vars.allowsp and "softprompt" in js and type(js["softprompt"]) is str and all(q not in js["softprompt"] for q in ("..", ":")) and all(js["softprompt"][0] not in q for q in ("/", "\\"))):
|
||||||
|
spRequest(js["softprompt"])
|
||||||
|
else:
|
||||||
|
vars.spfilename = ""
|
||||||
|
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
#==================================================================#
|
#==================================================================#
|
||||||
|
@ -2445,7 +2488,9 @@ def generate(txt, minimum, maximum, found_entries=None):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if(issubclass(type(e), lupa.LuaError)):
|
if(issubclass(type(e), lupa.LuaError)):
|
||||||
vars.lua_koboldbridge.obliterate_multiverse()
|
vars.lua_koboldbridge.obliterate_multiverse()
|
||||||
|
vars.lua_running = False
|
||||||
emit('from_server', {'cmd': 'errmsg', 'data': 'Lua script error, please check console.'}, broadcast=True)
|
emit('from_server', {'cmd': 'errmsg', 'data': 'Lua script error, please check console.'}, broadcast=True)
|
||||||
|
sendUSStatItems()
|
||||||
print("{0}{1}{2}".format(colors.RED, "***LUA ERROR***: ", colors.END), end="", file=sys.stderr)
|
print("{0}{1}{2}".format(colors.RED, "***LUA ERROR***: ", colors.END), end="", file=sys.stderr)
|
||||||
print("{0}{1}{2}".format(colors.RED, str(e).replace("\033", ""), colors.END), file=sys.stderr)
|
print("{0}{1}{2}".format(colors.RED, str(e).replace("\033", ""), colors.END), file=sys.stderr)
|
||||||
print("{0}{1}{2}".format(colors.YELLOW, "Lua engine stopped; please open 'Userscripts' and press Load to reinitialize scripts.", colors.END), file=sys.stderr)
|
print("{0}{1}{2}".format(colors.YELLOW, "Lua engine stopped; please open 'Userscripts' and press Load to reinitialize scripts.", colors.END), file=sys.stderr)
|
||||||
|
@ -2672,7 +2717,9 @@ def tpumtjgenerate(txt, minimum, maximum, found_entries=None):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if(issubclass(type(e), lupa.LuaError)):
|
if(issubclass(type(e), lupa.LuaError)):
|
||||||
vars.lua_koboldbridge.obliterate_multiverse()
|
vars.lua_koboldbridge.obliterate_multiverse()
|
||||||
|
vars.lua_running = False
|
||||||
emit('from_server', {'cmd': 'errmsg', 'data': 'Lua script error, please check console.'}, broadcast=True)
|
emit('from_server', {'cmd': 'errmsg', 'data': 'Lua script error, please check console.'}, broadcast=True)
|
||||||
|
sendUSStatItems()
|
||||||
print("{0}{1}{2}".format(colors.RED, "***LUA ERROR***: ", colors.END), end="", file=sys.stderr)
|
print("{0}{1}{2}".format(colors.RED, "***LUA ERROR***: ", colors.END), end="", file=sys.stderr)
|
||||||
print("{0}{1}{2}".format(colors.RED, str(e).replace("\033", ""), colors.END), file=sys.stderr)
|
print("{0}{1}{2}".format(colors.RED, str(e).replace("\033", ""), colors.END), file=sys.stderr)
|
||||||
print("{0}{1}{2}".format(colors.YELLOW, "Lua engine stopped; please open 'Userscripts' and press Load to reinitialize scripts.", colors.END), file=sys.stderr)
|
print("{0}{1}{2}".format(colors.YELLOW, "Lua engine stopped; please open 'Userscripts' and press Load to reinitialize scripts.", colors.END), file=sys.stderr)
|
||||||
|
@ -3550,7 +3597,7 @@ def getsplist():
|
||||||
emit('from_server', {'cmd': 'buildsp', 'data': fileops.getspfiles(vars.modeldim)})
|
emit('from_server', {'cmd': 'buildsp', 'data': fileops.getspfiles(vars.modeldim)})
|
||||||
|
|
||||||
#==================================================================#
|
#==================================================================#
|
||||||
# Show list of userscripts
|
# Get list of userscripts
|
||||||
#==================================================================#
|
#==================================================================#
|
||||||
def getuslist():
|
def getuslist():
|
||||||
files = {i: v for i, v in enumerate(fileops.getusfiles())}
|
files = {i: v for i, v in enumerate(fileops.getusfiles())}
|
||||||
|
@ -3558,11 +3605,14 @@ def getuslist():
|
||||||
unloaded = []
|
unloaded = []
|
||||||
userscripts = set(vars.userscripts)
|
userscripts = set(vars.userscripts)
|
||||||
for i in range(len(files)):
|
for i in range(len(files)):
|
||||||
if files[i]["filename"] in userscripts:
|
if files[i]["filename"] not in userscripts:
|
||||||
loaded.append(files[i])
|
|
||||||
else:
|
|
||||||
unloaded.append(files[i])
|
unloaded.append(files[i])
|
||||||
emit('from_server', {'cmd': 'buildus', 'data': {"unloaded": unloaded, "loaded": loaded}})
|
files = {files[k]["filename"]: files[k] for k in files}
|
||||||
|
userscripts = set(files.keys())
|
||||||
|
for filename in vars.userscripts:
|
||||||
|
if filename in userscripts:
|
||||||
|
loaded.append(files[filename])
|
||||||
|
return unloaded, loaded
|
||||||
|
|
||||||
#==================================================================#
|
#==================================================================#
|
||||||
# Load a saved story via file browser
|
# Load a saved story via file browser
|
||||||
|
@ -3684,6 +3734,9 @@ def loadRequest(loadpath, filename=None):
|
||||||
# Load a soft prompt from a file
|
# Load a soft prompt from a file
|
||||||
#==================================================================#
|
#==================================================================#
|
||||||
def spRequest(filename):
|
def spRequest(filename):
|
||||||
|
vars.spfilename = ""
|
||||||
|
settingschanged()
|
||||||
|
|
||||||
if(len(filename) == 0):
|
if(len(filename) == 0):
|
||||||
vars.sp = None
|
vars.sp = None
|
||||||
vars.sp_length = 0
|
vars.sp_length = 0
|
||||||
|
@ -3695,6 +3748,8 @@ def spRequest(filename):
|
||||||
|
|
||||||
z, version, shape, fortran_order, dtype = fileops.checksp(filename, vars.modeldim)
|
z, version, shape, fortran_order, dtype = fileops.checksp(filename, vars.modeldim)
|
||||||
assert isinstance(z, zipfile.ZipFile)
|
assert isinstance(z, zipfile.ZipFile)
|
||||||
|
with z.open('meta.json') as f:
|
||||||
|
vars.spmeta = json.load(f)
|
||||||
z.close()
|
z.close()
|
||||||
|
|
||||||
with np.load(fileops.sppath(filename), allow_pickle=False) as f:
|
with np.load(fileops.sppath(filename), allow_pickle=False) as f:
|
||||||
|
@ -3725,6 +3780,9 @@ def spRequest(filename):
|
||||||
else:
|
else:
|
||||||
vars.sp = torch.from_numpy(tensor)
|
vars.sp = torch.from_numpy(tensor)
|
||||||
|
|
||||||
|
vars.spfilename = filename
|
||||||
|
settingschanged()
|
||||||
|
|
||||||
#==================================================================#
|
#==================================================================#
|
||||||
# Import an AIDungon game exported with Mimi's tool
|
# Import an AIDungon game exported with Mimi's tool
|
||||||
#==================================================================#
|
#==================================================================#
|
||||||
|
|
226
bridge.lua
226
bridge.lua
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
---@param _python? table<string, any>
|
---@param _python? table<string, any>
|
||||||
---@param _bridged? table<string, any>
|
---@param _bridged? table<string, any>
|
||||||
---@return KoboldLib, KoboldCoreLib|nil
|
---@return KoboldLib, KoboldCoreLib?
|
||||||
return function(_python, _bridged)
|
return function(_python, _bridged)
|
||||||
|
|
||||||
--==========================================================================
|
--==========================================================================
|
||||||
|
@ -14,7 +14,7 @@ return function(_python, _bridged)
|
||||||
---@generic K, V
|
---@generic K, V
|
||||||
---@param t table<K, V>
|
---@param t table<K, V>
|
||||||
---@param k? K
|
---@param k? K
|
||||||
---@return K|nil, V|nil
|
---@return K?, V?
|
||||||
function next(t, k)
|
function next(t, k)
|
||||||
local meta = getmetatable(t)
|
local meta = getmetatable(t)
|
||||||
return ((meta ~= nil and type(rawget(t, "_name")) == "string" and string.match(rawget(t, "_name"), "^Kobold") and type(meta._kobold_next) == "function") and meta._kobold_next or old_next)(t, k)
|
return ((meta ~= nil and type(rawget(t, "_name")) == "string" and string.match(rawget(t, "_name"), "^Kobold") and type(meta._kobold_next) == "function") and meta._kobold_next or old_next)(t, k)
|
||||||
|
@ -40,23 +40,30 @@ return function(_python, _bridged)
|
||||||
return original
|
return original
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param path string
|
---@param paths string|table<integer, string>
|
||||||
---@return nil
|
---@return nil
|
||||||
function set_require_path(path)
|
local function set_require_path(paths)
|
||||||
|
if type(paths) == "string" then
|
||||||
|
paths = {paths}
|
||||||
|
end
|
||||||
local config = {}
|
local config = {}
|
||||||
local i = 1
|
local i = 1
|
||||||
for substring in string.gmatch(package.config, "[^\n]+") do
|
for substring in string.gmatch(package.config, "[^\n]+") do
|
||||||
config[i] = substring
|
config[i] = substring
|
||||||
i = i + 1
|
i = i + 1
|
||||||
end
|
end
|
||||||
package.path = path .. config[1] .. config[3] .. ".lua" .. config[2] .. path .. config[1] .. config[3] .. config[1] .. "init.lua"
|
local _paths = {}
|
||||||
|
for i, path in ipairs(paths) do
|
||||||
|
_paths[i] = path .. config[1] .. config[3] .. ".lua" .. config[2] .. path .. config[1] .. config[3] .. config[1] .. "init.lua"
|
||||||
|
end
|
||||||
|
package.path = table.concat(_paths, config[2])
|
||||||
package.cpath = ""
|
package.cpath = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param path string
|
---@param path string
|
||||||
---@param filename string
|
---@param filename string
|
||||||
---@return string
|
---@return string
|
||||||
function join_folder_and_filename(path, filename)
|
local function join_folder_and_filename(path, filename)
|
||||||
return path .. string.match(package.config, "[^\n]+") .. filename
|
return path .. string.match(package.config, "[^\n]+") .. filename
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -67,10 +74,10 @@ return function(_python, _bridged)
|
||||||
|
|
||||||
local bridged = {}
|
local bridged = {}
|
||||||
for k in _python.iter(_bridged) do
|
for k in _python.iter(_bridged) do
|
||||||
v = _bridged[k]
|
local v = _bridged[k]
|
||||||
bridged[k] = type(v) == "userdata" and _python.as_attrgetter(v) or v
|
bridged[k] = type(v) == "userdata" and _python.as_attrgetter(v) or v
|
||||||
end
|
end
|
||||||
set_require_path(bridged.lib_path)
|
set_require_path(bridged.lib_paths)
|
||||||
|
|
||||||
|
|
||||||
--==========================================================================
|
--==========================================================================
|
||||||
|
@ -120,12 +127,12 @@ return function(_python, _bridged)
|
||||||
_needs_unwrap = true
|
_needs_unwrap = true
|
||||||
wrapped = true
|
wrapped = true
|
||||||
end
|
end
|
||||||
local r = {wrapped_func(...)}
|
local r = table.pack(wrapped_func(...))
|
||||||
if _needs_unwrap then
|
if _needs_unwrap then
|
||||||
metatables:restore()
|
metatables:restore()
|
||||||
wrapped = false
|
wrapped = false
|
||||||
end
|
end
|
||||||
return table.unpack(r)
|
return table.unpack(r, 1, r.n)
|
||||||
end)
|
end)
|
||||||
else
|
else
|
||||||
return rawset(t, k, wrapped_func)
|
return rawset(t, k, wrapped_func)
|
||||||
|
@ -153,6 +160,8 @@ return function(_python, _bridged)
|
||||||
---@field generated_cols integer
|
---@field generated_cols integer
|
||||||
---@field outputs table<integer, string>
|
---@field outputs table<integer, string>
|
||||||
---@field num_outputs integer
|
---@field num_outputs integer
|
||||||
|
---@field feedback string
|
||||||
|
---@field is_config_file_open boolean
|
||||||
local kobold = setmetatable({}, metawrapper)
|
local kobold = setmetatable({}, metawrapper)
|
||||||
local KoboldLib_mt = setmetatable({}, metawrapper)
|
local KoboldLib_mt = setmetatable({}, metawrapper)
|
||||||
local KoboldLib_getters = setmetatable({}, metawrapper)
|
local KoboldLib_getters = setmetatable({}, metawrapper)
|
||||||
|
@ -214,7 +223,12 @@ return function(_python, _bridged)
|
||||||
koboldbridge.generated = {}
|
koboldbridge.generated = {}
|
||||||
koboldbridge.generated_cols = 0
|
koboldbridge.generated_cols = 0
|
||||||
koboldbridge.outputs = {}
|
koboldbridge.outputs = {}
|
||||||
koboldbridge.feedback = nil ---@type string|nil
|
koboldbridge.feedback = nil ---@type string?
|
||||||
|
|
||||||
|
function koboldbridge:clear_userscript_metadata()
|
||||||
|
self.logging_name = nil
|
||||||
|
self.filename = nil
|
||||||
|
end
|
||||||
|
|
||||||
---@return nil
|
---@return nil
|
||||||
local function maybe_require_regeneration()
|
local function maybe_require_regeneration()
|
||||||
|
@ -224,6 +238,84 @@ return function(_python, _bridged)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--==========================================================================
|
||||||
|
-- Userscript API: Configuration
|
||||||
|
--==========================================================================
|
||||||
|
|
||||||
|
local config_files = {} ---@type table<string, file*>
|
||||||
|
local config_file_filename_map = {} ---@type table<file*, string>
|
||||||
|
|
||||||
|
---@return file*?
|
||||||
|
local function open_and_handle_errors(...)
|
||||||
|
local file, err_msg = io.open(...)
|
||||||
|
if err_msg ~= nil then
|
||||||
|
koboldbridge.obliterate_multiverse()
|
||||||
|
error(err_msg)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
return file
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param file? file*
|
||||||
|
local function new_close_pre(file)
|
||||||
|
if file == nil then
|
||||||
|
file = io.output()
|
||||||
|
end
|
||||||
|
local filename = config_file_filename_map[file]
|
||||||
|
if filename ~= nil then
|
||||||
|
config_file_filename_map[file] = nil
|
||||||
|
config_files[filename] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param f fun(file?: file*)
|
||||||
|
local function _new_close(f)
|
||||||
|
---@param file? file*
|
||||||
|
return function(file)
|
||||||
|
new_close_pre(file)
|
||||||
|
return f(file)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
debug.getmetatable(io.stdout).__index.close = _new_close(io.stdout.close)
|
||||||
|
|
||||||
|
---@param filename string
|
||||||
|
---@return boolean
|
||||||
|
local function is_config_file_open(filename)
|
||||||
|
return config_files[filename] ~= nil
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param filename string
|
||||||
|
---@param clear? boolean
|
||||||
|
---@return file*
|
||||||
|
local function get_config_file(filename, clear)
|
||||||
|
if not is_config_file_open(filename) then
|
||||||
|
local config_filepath = join_folder_and_filename(bridged.config_path, filename .. ".conf")
|
||||||
|
open_and_handle_errors(config_filepath, "a"):close()
|
||||||
|
config_files[filename] = open_and_handle_errors(config_filepath, clear and "w+b" or "r+b")
|
||||||
|
config_file_filename_map[config_files[filename]] = filename
|
||||||
|
end
|
||||||
|
return config_files[filename]
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param clear? boolean
|
||||||
|
---@return file*
|
||||||
|
function kobold.get_config_file(clear)
|
||||||
|
return get_config_file(koboldbridge.filename, clear)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param t KoboldLib
|
||||||
|
---@return boolean
|
||||||
|
function KoboldLib_getters.is_config_file_open(t)
|
||||||
|
return is_config_file_open(koboldbridge.filename)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param t KoboldLib
|
||||||
|
---@param v boolean
|
||||||
|
function KoboldLib_setters.is_config_file_open(t, v)
|
||||||
|
error("`KoboldLib.is_config_file_open` is a read-only attribute")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--==========================================================================
|
--==========================================================================
|
||||||
-- Userscript API: World Info
|
-- Userscript API: World Info
|
||||||
--==========================================================================
|
--==========================================================================
|
||||||
|
@ -373,7 +465,7 @@ return function(_python, _bridged)
|
||||||
local KoboldWorldInfoFolder_mt = setmetatable({}, metawrapper)
|
local KoboldWorldInfoFolder_mt = setmetatable({}, metawrapper)
|
||||||
|
|
||||||
---@param u integer
|
---@param u integer
|
||||||
---@return KoboldWorldInfoEntry|nil
|
---@return KoboldWorldInfoEntry?
|
||||||
function KoboldWorldInfoFolder:finduid(u)
|
function KoboldWorldInfoFolder:finduid(u)
|
||||||
if not check_validity(self) or type(u) ~= "number" then
|
if not check_validity(self) or type(u) ~= "number" then
|
||||||
return
|
return
|
||||||
|
@ -440,7 +532,7 @@ return function(_python, _bridged)
|
||||||
KoboldWorldInfoFolder_mt.__pairs = KoboldWorldInfoEntry_mt.__pairs
|
KoboldWorldInfoFolder_mt.__pairs = KoboldWorldInfoEntry_mt.__pairs
|
||||||
|
|
||||||
---@param t KoboldWorldInfoFolder|KoboldWorldInfo
|
---@param t KoboldWorldInfoFolder|KoboldWorldInfo
|
||||||
---@return KoboldWorldInfoEntry|nil
|
---@return KoboldWorldInfoEntry?
|
||||||
function KoboldWorldInfoFolder_mt.__index(t, k)
|
function KoboldWorldInfoFolder_mt.__index(t, k)
|
||||||
if not check_validity(t) then
|
if not check_validity(t) then
|
||||||
return
|
return
|
||||||
|
@ -495,7 +587,7 @@ return function(_python, _bridged)
|
||||||
local KoboldWorldInfoFolderSelector_mt = setmetatable({}, metawrapper)
|
local KoboldWorldInfoFolderSelector_mt = setmetatable({}, metawrapper)
|
||||||
|
|
||||||
---@param u integer
|
---@param u integer
|
||||||
---@return KoboldWorldInfoFolder|nil
|
---@return KoboldWorldInfoFolder?
|
||||||
function KoboldWorldInfoFolderSelector:finduid(u)
|
function KoboldWorldInfoFolderSelector:finduid(u)
|
||||||
if not check_validity(self) or type(u) ~= "number" then
|
if not check_validity(self) or type(u) ~= "number" then
|
||||||
return
|
return
|
||||||
|
@ -528,7 +620,7 @@ return function(_python, _bridged)
|
||||||
KoboldWorldInfoFolderSelector_mt.__pairs = KoboldWorldInfoEntry_mt.__pairs
|
KoboldWorldInfoFolderSelector_mt.__pairs = KoboldWorldInfoEntry_mt.__pairs
|
||||||
|
|
||||||
---@param t KoboldWorldInfoFolderSelector
|
---@param t KoboldWorldInfoFolderSelector
|
||||||
---@return KoboldWorldInfoFolder|nil
|
---@return KoboldWorldInfoFolder?
|
||||||
function KoboldWorldInfoFolderSelector_mt.__index(t, k)
|
function KoboldWorldInfoFolderSelector_mt.__index(t, k)
|
||||||
if not check_validity(t) or type(k) ~= "number" or math.tointeger(k) == nil or k < 1 or k > #t then
|
if not check_validity(t) or type(k) ~= "number" or math.tointeger(k) == nil or k < 1 or k > #t then
|
||||||
return
|
return
|
||||||
|
@ -681,7 +773,7 @@ return function(_python, _bridged)
|
||||||
local actions = koboldbridge.userstate == "genmod" and bridged.vars._actions or bridged.vars.actions
|
local actions = koboldbridge.userstate == "genmod" and bridged.vars._actions or bridged.vars.actions
|
||||||
local nxt, iterator = _python.iter(actions)
|
local nxt, iterator = _python.iter(actions)
|
||||||
local run_once = false
|
local run_once = false
|
||||||
local f = function()
|
local function f()
|
||||||
if not bridged.vars.gamestarted then
|
if not bridged.vars.gamestarted then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -709,7 +801,7 @@ return function(_python, _bridged)
|
||||||
local actions = koboldbridge.userstate == "genmod" and bridged.vars._actions or bridged.vars.actions
|
local actions = koboldbridge.userstate == "genmod" and bridged.vars._actions or bridged.vars.actions
|
||||||
local nxt, iterator = _python.iter(_python.builtins.reversed(actions))
|
local nxt, iterator = _python.iter(_python.builtins.reversed(actions))
|
||||||
local last_run = false
|
local last_run = false
|
||||||
local f = function()
|
local function f()
|
||||||
if not bridged.vars.gamestarted or last_run then
|
if not bridged.vars.gamestarted or last_run then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -946,7 +1038,7 @@ return function(_python, _bridged)
|
||||||
---@param t KoboldLib
|
---@param t KoboldLib
|
||||||
---@return string
|
---@return string
|
||||||
function KoboldLib_getters.model(t)
|
function KoboldLib_getters.model(t)
|
||||||
return bridged.vars.model
|
return bridged.vars.model_orig
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param t KoboldLib
|
---@param t KoboldLib
|
||||||
|
@ -1257,21 +1349,22 @@ return function(_python, _bridged)
|
||||||
-- Core script API
|
-- Core script API
|
||||||
--==========================================================================
|
--==========================================================================
|
||||||
|
|
||||||
koboldbridge.userscripts = {} ---@type table<integer, string>
|
koboldbridge.userscripts = {} ---@type table<integer, KoboldUserScriptModule>
|
||||||
|
koboldbridge.userscriptmodule_filename_map = {} ---@type table<KoboldUserScriptModule, string>
|
||||||
koboldbridge.num_userscripts = 0
|
koboldbridge.num_userscripts = 0
|
||||||
koboldbridge.inmod = nil ---@type function|nil
|
koboldbridge.inmod = nil ---@type function?
|
||||||
koboldbridge.genmod = nil ---@type function|nil
|
koboldbridge.genmod = nil ---@type function?
|
||||||
koboldbridge.outmod = nil ---@type function|nil
|
koboldbridge.outmod = nil ---@type function?
|
||||||
|
|
||||||
---@class KoboldUserScript
|
---@class KoboldUserScript
|
||||||
---@field inmod function|nil
|
---@field inmod? function
|
||||||
---@field genmod function|nil
|
---@field genmod? function
|
||||||
---@field outmod function|nil
|
---@field outmod? function
|
||||||
|
|
||||||
---@class KoboldCoreScript
|
---@class KoboldCoreScript
|
||||||
---@field inmod function|nil
|
---@field inmod? function
|
||||||
---@field genmod function|nil
|
---@field genmod? function
|
||||||
---@field outmod function|nil
|
---@field outmod? function
|
||||||
|
|
||||||
|
|
||||||
----------------------------------------------------------------------------
|
----------------------------------------------------------------------------
|
||||||
|
@ -1280,9 +1373,10 @@ return function(_python, _bridged)
|
||||||
---@field filename string
|
---@field filename string
|
||||||
---@field modulename string
|
---@field modulename string
|
||||||
---@field description string
|
---@field description string
|
||||||
---@field inmod function|nil
|
---@field is_config_file_open boolean
|
||||||
---@field genmod function|nil
|
---@field inmod? function
|
||||||
---@field outmod function|nil
|
---@field genmod? function
|
||||||
|
---@field outmod? function
|
||||||
local KoboldUserScriptModule = setmetatable({
|
local KoboldUserScriptModule = setmetatable({
|
||||||
_name = "KoboldUserScriptModule",
|
_name = "KoboldUserScriptModule",
|
||||||
}, metawrapper)
|
}, metawrapper)
|
||||||
|
@ -1297,6 +1391,12 @@ return function(_python, _bridged)
|
||||||
outmod = false,
|
outmod = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---@param clear? boolean
|
||||||
|
---@return file*
|
||||||
|
function KoboldUserScriptModule:get_config_file(clear)
|
||||||
|
return get_config_file(koboldbridge.userscriptmodule_filename_map[self], clear)
|
||||||
|
end
|
||||||
|
|
||||||
---@generic K
|
---@generic K
|
||||||
---@param t KoboldUserScriptModule
|
---@param t KoboldUserScriptModule
|
||||||
---@param k K
|
---@param k K
|
||||||
|
@ -1316,6 +1416,8 @@ return function(_python, _bridged)
|
||||||
function KoboldUserScriptModule_mt.__index(t, k)
|
function KoboldUserScriptModule_mt.__index(t, k)
|
||||||
if type(k) == "string" and KoboldUserScriptModule_fields[k] ~= nil then
|
if type(k) == "string" and KoboldUserScriptModule_fields[k] ~= nil then
|
||||||
return rawget(t, "_" .. k)
|
return rawget(t, "_" .. k)
|
||||||
|
elseif k == "is_config_file_open" then
|
||||||
|
return is_config_file_open(koboldbridge.userscriptmodule_filename_map[t])
|
||||||
end
|
end
|
||||||
return rawget(t, k)
|
return rawget(t, k)
|
||||||
end
|
end
|
||||||
|
@ -1346,7 +1448,7 @@ return function(_python, _bridged)
|
||||||
|
|
||||||
---@param t KoboldUserScriptList
|
---@param t KoboldUserScriptList
|
||||||
---@param k integer
|
---@param k integer
|
||||||
---@return KoboldUserScriptModule|nil
|
---@return KoboldUserScriptModule?
|
||||||
function KoboldUserScriptList_mt.__index(t, k)
|
function KoboldUserScriptList_mt.__index(t, k)
|
||||||
if type(k) == "number" and math.tointeger(k) ~= nil then
|
if type(k) == "number" and math.tointeger(k) ~= nil then
|
||||||
return koboldbridge.userscripts[k]
|
return koboldbridge.userscripts[k]
|
||||||
|
@ -1405,6 +1507,7 @@ return function(_python, _bridged)
|
||||||
|
|
||||||
local envs = {}
|
local envs = {}
|
||||||
koboldbridge.logging_name = nil
|
koboldbridge.logging_name = nil
|
||||||
|
koboldbridge.filename = nil
|
||||||
|
|
||||||
local old_load = load
|
local old_load = load
|
||||||
local function _safe_load(_g)
|
local function _safe_load(_g)
|
||||||
|
@ -1427,11 +1530,11 @@ return function(_python, _bridged)
|
||||||
local old_package_searchers = package.searchers
|
local old_package_searchers = package.searchers
|
||||||
---@param modname string
|
---@param modname string
|
||||||
---@param env table<string, any>
|
---@param env table<string, any>
|
||||||
---@param search_path? string
|
---@param search_paths? string|table<integer, string>
|
||||||
---@return any, string|nil
|
---@return any, string?
|
||||||
local function requirex(modname, env, search_path)
|
local function requirex(modname, env, search_paths)
|
||||||
if search_path == nil then
|
if search_paths == nil then
|
||||||
search_path = bridged.lib_path
|
search_paths = bridged.lib_paths
|
||||||
end
|
end
|
||||||
if modname == "bridge" then
|
if modname == "bridge" then
|
||||||
return function() return env.kobold, env.koboldcore end
|
return function() return env.kobold, env.koboldcore end
|
||||||
|
@ -1449,7 +1552,7 @@ return function(_python, _bridged)
|
||||||
local loader, path
|
local loader, path
|
||||||
local errors = {}
|
local errors = {}
|
||||||
local n_errors = 0
|
local n_errors = 0
|
||||||
set_require_path(search_path)
|
set_require_path(search_paths)
|
||||||
for k, v in ipairs(old_package_searchers) do
|
for k, v in ipairs(old_package_searchers) do
|
||||||
loader, path = v(modname)
|
loader, path = v(modname)
|
||||||
if allowsearch and type(loader) == "function" then
|
if allowsearch and type(loader) == "function" then
|
||||||
|
@ -1459,7 +1562,7 @@ return function(_python, _bridged)
|
||||||
errors[n_errors] = "\n\t" .. loader
|
errors[n_errors] = "\n\t" .. loader
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
set_require_path(bridged.lib_path)
|
set_require_path(bridged.lib_paths)
|
||||||
if not allowsearch or type(loader) ~= "function" then
|
if not allowsearch or type(loader) ~= "function" then
|
||||||
error("module '" .. modname .. "' not found:" .. table.concat(errors))
|
error("module '" .. modname .. "' not found:" .. table.concat(errors))
|
||||||
return
|
return
|
||||||
|
@ -1470,7 +1573,7 @@ return function(_python, _bridged)
|
||||||
end
|
end
|
||||||
local function _safe_require(_g)
|
local function _safe_require(_g)
|
||||||
---@param modname string
|
---@param modname string
|
||||||
---@return any, string|nil
|
---@return any, string?
|
||||||
return function(modname)
|
return function(modname)
|
||||||
return requirex(modname, _g)
|
return requirex(modname, _g)
|
||||||
end
|
end
|
||||||
|
@ -1610,6 +1713,8 @@ return function(_python, _bridged)
|
||||||
output = io.output,
|
output = io.output,
|
||||||
read = io.read,
|
read = io.read,
|
||||||
write = io.write,
|
write = io.write,
|
||||||
|
close = _new_close(io.close),
|
||||||
|
lines = io.lines,
|
||||||
flush = io.flush,
|
flush = io.flush,
|
||||||
type = io.type,
|
type = io.type,
|
||||||
},
|
},
|
||||||
|
@ -1654,7 +1759,11 @@ return function(_python, _bridged)
|
||||||
end
|
end
|
||||||
|
|
||||||
function koboldbridge.obliterate_multiverse()
|
function koboldbridge.obliterate_multiverse()
|
||||||
|
for k, v in pairs(config_files) do
|
||||||
|
pcall(v.close, v)
|
||||||
|
end
|
||||||
envs = {}
|
envs = {}
|
||||||
|
koboldbridge.userscripts = {}
|
||||||
koboldbridge.num_userscripts = 0
|
koboldbridge.num_userscripts = 0
|
||||||
koboldbridge.inmod = nil
|
koboldbridge.inmod = nil
|
||||||
koboldbridge.genmod = nil
|
koboldbridge.genmod = nil
|
||||||
|
@ -1668,23 +1777,49 @@ return function(_python, _bridged)
|
||||||
|
|
||||||
---@return nil
|
---@return nil
|
||||||
function koboldbridge.load_userscripts(filenames, modulenames, descriptions)
|
function koboldbridge.load_userscripts(filenames, modulenames, descriptions)
|
||||||
set_require_path(bridged.userscript_path)
|
config_files = {}
|
||||||
|
config_file_filename_map = {}
|
||||||
koboldbridge.userscripts = {}
|
koboldbridge.userscripts = {}
|
||||||
|
koboldbridge.userscriptmodule_filename_map = {}
|
||||||
koboldbridge.num_userscripts = 0
|
koboldbridge.num_userscripts = 0
|
||||||
for i, filename in _python.enumerate(filenames) do
|
for i, filename in _python.enumerate(filenames) do
|
||||||
bridged.load_callback(filename, modulenames[i])
|
bridged.load_callback(filename, modulenames[i])
|
||||||
koboldbridge.logging_name = modulenames[i]
|
koboldbridge.logging_name = modulenames[i]
|
||||||
|
koboldbridge.filename = filename
|
||||||
---@type KoboldUserScript
|
---@type KoboldUserScript
|
||||||
local _userscript = old_loadfile(join_folder_and_filename(bridged.userscript_path, filename), "t", koboldbridge.get_universe(filename))()
|
local _userscript = old_loadfile(join_folder_and_filename(bridged.userscript_path, filename), "t", koboldbridge.get_universe(filename))()
|
||||||
koboldbridge.logging_name = nil
|
koboldbridge.logging_name = nil
|
||||||
|
koboldbridge.filename = nil
|
||||||
local userscript = deepcopy(KoboldUserScriptModule)
|
local userscript = deepcopy(KoboldUserScriptModule)
|
||||||
rawset(userscript, "_inmod", function() koboldbridge.logging_name = modulenames[i]; if _userscript.inmod ~= nil then _userscript.inmod() end end)
|
rawset(userscript, "_inmod", function()
|
||||||
rawset(userscript, "_genmod", function() koboldbridge.logging_name = modulenames[i]; if _userscript.genmod ~= nil then _userscript.genmod() end end)
|
koboldbridge.logging_name = modulenames[i]
|
||||||
rawset(userscript, "_outmod", function() koboldbridge.logging_name = modulenames[i]; if _userscript.outmod ~= nil then _userscript.outmod() end end)
|
koboldbridge.filename = filename
|
||||||
|
if _userscript.inmod ~= nil then
|
||||||
|
_userscript.inmod()
|
||||||
|
end
|
||||||
|
koboldbridge:clear_userscript_metadata()
|
||||||
|
end)
|
||||||
|
rawset(userscript, "_genmod", function()
|
||||||
|
koboldbridge.logging_name = modulenames[i]
|
||||||
|
koboldbridge.filename = filename
|
||||||
|
if _userscript.genmod ~= nil then
|
||||||
|
_userscript.genmod()
|
||||||
|
end
|
||||||
|
koboldbridge:clear_userscript_metadata()
|
||||||
|
end)
|
||||||
|
rawset(userscript, "_outmod", function()
|
||||||
|
koboldbridge.logging_name = modulenames[i]
|
||||||
|
koboldbridge.filename = filename
|
||||||
|
if _userscript.outmod ~= nil then
|
||||||
|
_userscript.outmod()
|
||||||
|
end
|
||||||
|
koboldbridge:clear_userscript_metadata()
|
||||||
|
end)
|
||||||
rawset(userscript, "_filename", filename)
|
rawset(userscript, "_filename", filename)
|
||||||
rawset(userscript, "_modulename", modulenames[i])
|
rawset(userscript, "_modulename", modulenames[i])
|
||||||
rawset(userscript, "_description", descriptions[i])
|
rawset(userscript, "_description", descriptions[i])
|
||||||
koboldbridge.userscripts[i+1] = userscript
|
koboldbridge.userscripts[i+1] = userscript
|
||||||
|
koboldbridge.userscriptmodule_filename_map[userscript] = filename
|
||||||
koboldbridge.num_userscripts = i + 1
|
koboldbridge.num_userscripts = i + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1700,6 +1835,7 @@ return function(_python, _bridged)
|
||||||
|
|
||||||
function koboldbridge.execute_inmod()
|
function koboldbridge.execute_inmod()
|
||||||
local r
|
local r
|
||||||
|
koboldbridge:clear_userscript_metadata()
|
||||||
koboldbridge.restart_sequence = nil
|
koboldbridge.restart_sequence = nil
|
||||||
koboldbridge.userstate = "inmod"
|
koboldbridge.userstate = "inmod"
|
||||||
koboldbridge.regeneration_required = false
|
koboldbridge.regeneration_required = false
|
||||||
|
@ -1722,6 +1858,7 @@ return function(_python, _bridged)
|
||||||
---@return any, boolean
|
---@return any, boolean
|
||||||
function koboldbridge.execute_genmod()
|
function koboldbridge.execute_genmod()
|
||||||
local r
|
local r
|
||||||
|
koboldbridge:clear_userscript_metadata()
|
||||||
koboldbridge.generating = true
|
koboldbridge.generating = true
|
||||||
koboldbridge.userstate = "genmod"
|
koboldbridge.userstate = "genmod"
|
||||||
if koboldbridge.genmod ~= nil then
|
if koboldbridge.genmod ~= nil then
|
||||||
|
@ -1758,6 +1895,7 @@ return function(_python, _bridged)
|
||||||
|
|
||||||
function koboldbridge.execute_outmod()
|
function koboldbridge.execute_outmod()
|
||||||
local r
|
local r
|
||||||
|
koboldbridge:clear_userscript_metadata()
|
||||||
koboldbridge.generating = false
|
koboldbridge.generating = false
|
||||||
koboldbridge.userstate = "outmod"
|
koboldbridge.userstate = "outmod"
|
||||||
koboldbridge.num_outputs = kobold.settings.numseqs
|
koboldbridge.num_outputs = kobold.settings.numseqs
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
return require("lulpeg")
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -419,7 +419,7 @@ function addWiLine(ob) {
|
||||||
function addWiFolder(uid, ob) {
|
function addWiFolder(uid, ob) {
|
||||||
if(uid !== null) {
|
if(uid !== null) {
|
||||||
var uninitialized = $("#wilistfoldercontainer"+null);
|
var uninitialized = $("#wilistfoldercontainer"+null);
|
||||||
var html = "<div class=\"wisortable-container\" id=\"wilistfoldercontainer"+uid+"\" folder-uid=\""+uid+"\">\
|
var html = "<div class=\"wisortable-container "+(ob.collapsed ? "" : "folder-expanded")+"\" id=\"wilistfoldercontainer"+uid+"\" folder-uid=\""+uid+"\">\
|
||||||
<div class=\"wilistfolder\" id=\"wilistfolder"+uid+"\">\
|
<div class=\"wilistfolder\" id=\"wilistfolder"+uid+"\">\
|
||||||
<div class=\"wiremove\">\
|
<div class=\"wiremove\">\
|
||||||
<button type=\"button\" class=\"btn btn-primary heightfull\" id=\"btn_wifolder"+uid+"\">X</button>\
|
<button type=\"button\" class=\"btn btn-primary heightfull\" id=\"btn_wifolder"+uid+"\">X</button>\
|
||||||
|
@ -428,7 +428,7 @@ function addWiFolder(uid, ob) {
|
||||||
</div>\
|
</div>\
|
||||||
<div class=\"wifoldericon\">\
|
<div class=\"wifoldericon\">\
|
||||||
<div class=\"wicentered\">\
|
<div class=\"wicentered\">\
|
||||||
<span class=\"oi oi-folder\" aria-hidden=\"true\"></span>\
|
<span class=\"oi oi-folder folder-expand "+(ob.collapsed ? "" : "folder-expanded")+"\" id=\"btn_wifolderexpand"+uid+"\" aria-hidden=\"true\"></span>\
|
||||||
</div>\
|
</div>\
|
||||||
</div>\
|
</div>\
|
||||||
<div class=\"wifoldername\">\
|
<div class=\"wifoldername\">\
|
||||||
|
@ -461,7 +461,7 @@ function addWiFolder(uid, ob) {
|
||||||
var onfocusout = function () {
|
var onfocusout = function () {
|
||||||
socket.send({'cmd': 'wifolderupdate', 'uid': uid, 'data': {
|
socket.send({'cmd': 'wifolderupdate', 'uid': uid, 'data': {
|
||||||
name: $("#wifoldername"+uid).val(),
|
name: $("#wifoldername"+uid).val(),
|
||||||
collapsed: false,
|
collapsed: !$("#btn_wifolderexpand"+uid).hasClass("folder-expanded"),
|
||||||
}});
|
}});
|
||||||
};
|
};
|
||||||
$("#wifoldergutter"+uid).on("click", function () {
|
$("#wifoldergutter"+uid).on("click", function () {
|
||||||
|
@ -488,9 +488,22 @@ function addWiFolder(uid, ob) {
|
||||||
$(this).parent().parent().find(".wisortable-body").removeClass("hidden");
|
$(this).parent().parent().find(".wisortable-body").removeClass("hidden");
|
||||||
$(this).parent().css("max-height", "").find(".wifoldername").find(".form-control").css("max-height", "");
|
$(this).parent().css("max-height", "").find(".wifoldername").find(".form-control").css("max-height", "");
|
||||||
});
|
});
|
||||||
adjustWiFolderNameHeight($("#wifoldername"+uid)[0]);
|
$("#btn_wifolderexpand"+uid).on("click", function () {
|
||||||
|
if($(this).hasClass("folder-expanded")) {
|
||||||
|
socket.send({'cmd': 'wifoldercollapsecontent', 'data': uid});
|
||||||
} else {
|
} else {
|
||||||
wi_menu.append("<div class=\"wisortable-container\" id=\"wilistfoldercontainer"+uid+"\">\
|
socket.send({'cmd': 'wifolderexpandcontent', 'data': uid});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
adjustWiFolderNameHeight($("#wifoldername"+uid)[0]);
|
||||||
|
if(ob.collapsed) {
|
||||||
|
setTimeout(function() {
|
||||||
|
var container = $("#wilistfoldercontainer"+uid);
|
||||||
|
hide([container.find(".wifoldergutter-container"), container.find(".wisortable-body")]);
|
||||||
|
}, 2);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wi_menu.append("<div class=\"wisortable-container folder-expanded\" id=\"wilistfoldercontainer"+uid+"\">\
|
||||||
<div class=\"wilistfolder\" id=\"wilistfolder"+uid+"\">\
|
<div class=\"wilistfolder\" id=\"wilistfolder"+uid+"\">\
|
||||||
<div class=\"wiremove\">\
|
<div class=\"wiremove\">\
|
||||||
<button type=\"button\" class=\"btn btn-primary heightfull\" id=\"btn_wifolder"+uid+"\">+</button>\
|
<button type=\"button\" class=\"btn btn-primary heightfull\" id=\"btn_wifolder"+uid+"\">+</button>\
|
||||||
|
@ -499,7 +512,7 @@ function addWiFolder(uid, ob) {
|
||||||
</div>\
|
</div>\
|
||||||
<div class=\"wifoldericon\">\
|
<div class=\"wifoldericon\">\
|
||||||
<div class=\"wicentered\">\
|
<div class=\"wicentered\">\
|
||||||
<span class=\"oi oi-folder\" aria-hidden=\"true\"></span>\
|
<span class=\"oi oi-folder folder-expand folder-expanded\" id=\"btn_wifolderexpand"+uid+"\" aria-hidden=\"true\"></span>\
|
||||||
</div>\
|
</div>\
|
||||||
</div>\
|
</div>\
|
||||||
<div class=\"wifoldername\">\
|
<div class=\"wifoldername\">\
|
||||||
|
@ -564,6 +577,18 @@ function hideWiFolderDeleteConfirm(num) {
|
||||||
hide([$("#btn_wifolderdel"+num), $("#btn_wifoldercan"+num)]);
|
hide([$("#btn_wifolderdel"+num), $("#btn_wifoldercan"+num)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function collapseWiFolderContent(uid) {
|
||||||
|
hide([$("#wifoldergutter"+uid), $(".wisortable-body[folder-uid="+uid+"]")]);
|
||||||
|
$("#btn_wifolderexpand"+uid).removeClass("folder-expanded");
|
||||||
|
$("#wilistfoldercontainer"+uid).removeClass("folder-expanded");
|
||||||
|
}
|
||||||
|
|
||||||
|
function expandWiFolderContent(uid) {
|
||||||
|
show([$("#wifoldergutter"+uid), $(".wisortable-body[folder-uid="+uid+"]")]);
|
||||||
|
$("#btn_wifolderexpand"+uid).addClass("folder-expanded");
|
||||||
|
$("#wilistfoldercontainer"+uid).addClass("folder-expanded");
|
||||||
|
}
|
||||||
|
|
||||||
function enableWiSelective(num) {
|
function enableWiSelective(num) {
|
||||||
hide([$("#wikey"+num)]);
|
hide([$("#wikey"+num)]);
|
||||||
$("#wikeyprimary"+num).val($("#wikey"+num).val());
|
$("#wikeyprimary"+num).val($("#wikey"+num).val());
|
||||||
|
@ -1028,6 +1053,59 @@ function hideRandomStoryPopup() {
|
||||||
rspopup.addClass("hidden");
|
rspopup.addClass("hidden");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function statFlash(ref) {
|
||||||
|
ref.addClass("status-flash");
|
||||||
|
setTimeout(function () {
|
||||||
|
ref.addClass("colorfade");
|
||||||
|
ref.removeClass("status-flash");
|
||||||
|
setTimeout(function () {
|
||||||
|
ref.removeClass("colorfade");
|
||||||
|
}, 1000);
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateUSStatItems(items, flash) {
|
||||||
|
var stat_us = $("#stat-us");
|
||||||
|
var stat_usactive = $("#stat-usactive");
|
||||||
|
if(flash || stat_usactive.find("li").length != items.length) {
|
||||||
|
statFlash(stat_us.closest(".statusicon").add("#usiconlabel"));
|
||||||
|
}
|
||||||
|
stat_usactive.html("");
|
||||||
|
if(items.length == 0) {
|
||||||
|
stat_us.html("No userscripts active");
|
||||||
|
$("#usiconlabel").html("");
|
||||||
|
stat_us.closest(".statusicon").removeClass("active");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stat_us.html("Active userscripts:");
|
||||||
|
stat_us.closest(".statusicon").addClass("active");
|
||||||
|
var i;
|
||||||
|
for(i = 0; i < items.length; i++) {
|
||||||
|
stat_usactive.append($("<li filename=\""+items[i].filename+"\">"+items[i].modulename+" <"+items[i].filename+"></li>"));
|
||||||
|
}
|
||||||
|
$("#usiconlabel").html(items.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSPStatItems(items) {
|
||||||
|
var stat_sp = $("#stat-sp");
|
||||||
|
var stat_spactive = $("#stat-spactive");
|
||||||
|
var key = null;
|
||||||
|
var old_val = stat_spactive.html();
|
||||||
|
Object.keys(items).forEach(function(k) {key = k;});
|
||||||
|
if(key === null) {
|
||||||
|
stat_sp.html("No soft prompt active");
|
||||||
|
stat_sp.closest(".statusicon").removeClass("active");
|
||||||
|
stat_spactive.html("");
|
||||||
|
} else {
|
||||||
|
stat_sp.html("Active soft prompt:");
|
||||||
|
stat_sp.closest(".statusicon").addClass("active");
|
||||||
|
stat_spactive.html((items[key].name || key)+" <"+key+">");
|
||||||
|
}
|
||||||
|
if(stat_spactive.html() !== old_val) {
|
||||||
|
statFlash(stat_sp.closest(".statusicon"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function setStartState() {
|
function setStartState() {
|
||||||
enableSendBtn();
|
enableSendBtn();
|
||||||
enableButtons([button_actmem, button_actwi]);
|
enableButtons([button_actmem, button_actwi]);
|
||||||
|
@ -1398,14 +1476,59 @@ function syncAllModifiedChunks(including_selected_chunks=false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function restorePrompt() {
|
function restorePrompt() {
|
||||||
if(game_text[0].firstChild && game_text[0].firstChild.nodeType === 3) {
|
if($("#n0").length && formatChunkInnerText($("#n0")[0]).length === 0) {
|
||||||
saved_prompt = formatChunkInnerText(game_text[0].firstChild);
|
$("#n0").remove();
|
||||||
|
}
|
||||||
|
var shadow_text = $("<b>" + game_text.html() + "</b>");
|
||||||
|
var detected = false;
|
||||||
|
var ref = null;
|
||||||
|
try {
|
||||||
|
if(shadow_text.length && shadow_text[0].firstChild && (shadow_text[0].firstChild.nodeType === 3 || shadow_text[0].firstChild.tagName === "BR")) {
|
||||||
|
detected = true;
|
||||||
|
ref = shadow_text;
|
||||||
|
} else if(game_text.length && game_text[0].firstChild && game_text[0].firstChild.nodeType === 3 || game_text[0].firstChild.tagName === "BR") {
|
||||||
|
detected = true;
|
||||||
|
ref = game_text;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
detected = false;
|
||||||
|
}
|
||||||
|
if(detected) {
|
||||||
unbindGametext();
|
unbindGametext();
|
||||||
game_text[0].innerText = "";
|
var text = [];
|
||||||
|
while(true) {
|
||||||
|
if(ref.length && ref[0].firstChild && ref[0].firstChild.nodeType === 3) {
|
||||||
|
text.push(ref[0].firstChild.textContent.replace(/\u00a0/g, " "));
|
||||||
|
} else if(ref.length && ref[0].firstChild && ref[0].firstChild.tagName === "BR") {
|
||||||
|
text.push("\n");
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ref[0].removeChild(ref[0].firstChild);
|
||||||
|
}
|
||||||
|
text = text.join("").trim();
|
||||||
|
if(text.length) {
|
||||||
|
saved_prompt = text;
|
||||||
|
}
|
||||||
|
game_text[0].innerHTML = "";
|
||||||
bindGametext();
|
bindGametext();
|
||||||
}
|
}
|
||||||
if($("#n0").length) {
|
game_text.children().each(function() {
|
||||||
$("#n0").remove();
|
if(this.tagName !== "CHUNK") {
|
||||||
|
this.parentNode.removeChild(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(!detected) {
|
||||||
|
game_text.children().each(function() {
|
||||||
|
if(this.innerText.trim().length) {
|
||||||
|
saved_prompt = this.innerText.trim();
|
||||||
|
socket.send({'cmd': 'inlinedelete', 'data': this.getAttribute("n")});
|
||||||
|
this.parentNode.removeChild(this);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
socket.send({'cmd': 'inlinedelete', 'data': this.getAttribute("n")});
|
||||||
|
this.parentNode.removeChild(this);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
var prompt_chunk = document.createElement("chunk");
|
var prompt_chunk = document.createElement("chunk");
|
||||||
prompt_chunk.setAttribute("n", "0");
|
prompt_chunk.setAttribute("n", "0");
|
||||||
|
@ -1880,6 +2003,10 @@ $(document).ready(function(){
|
||||||
} else if(msg.cmd == "allowtoggle") {
|
} else if(msg.cmd == "allowtoggle") {
|
||||||
// Allow toggle change states to propagate
|
// Allow toggle change states to propagate
|
||||||
allowtoggle = msg.data;
|
allowtoggle = msg.data;
|
||||||
|
} else if(msg.cmd == "usstatitems") {
|
||||||
|
updateUSStatItems(msg.data, msg.flash);
|
||||||
|
} else if(msg.cmd == "spstatitems") {
|
||||||
|
updateSPStatItems(msg.data);
|
||||||
} else if(msg.cmd == "popupshow") {
|
} else if(msg.cmd == "popupshow") {
|
||||||
// Show/Hide Popup
|
// Show/Hide Popup
|
||||||
popupShow(msg.data);
|
popupShow(msg.data);
|
||||||
|
@ -1922,6 +2049,10 @@ $(document).ready(function(){
|
||||||
expandWiLine(msg.data);
|
expandWiLine(msg.data);
|
||||||
} else if(msg.cmd == "wiexpandfolder") {
|
} else if(msg.cmd == "wiexpandfolder") {
|
||||||
expandWiFolderLine(msg.data);
|
expandWiFolderLine(msg.data);
|
||||||
|
} else if(msg.cmd == "wifoldercollapsecontent") {
|
||||||
|
collapseWiFolderContent(msg.data);
|
||||||
|
} else if(msg.cmd == "wifolderexpandcontent") {
|
||||||
|
expandWiFolderContent(msg.data);
|
||||||
} else if(msg.cmd == "wiselon") {
|
} else if(msg.cmd == "wiselon") {
|
||||||
enableWiSelective(msg.data);
|
enableWiSelective(msg.data);
|
||||||
} else if(msg.cmd == "wiseloff") {
|
} else if(msg.cmd == "wiseloff") {
|
||||||
|
@ -2031,6 +2162,8 @@ $(document).ready(function(){
|
||||||
connect_status.html("<b>Lost connection...</b>");
|
connect_status.html("<b>Lost connection...</b>");
|
||||||
connect_status.removeClass("color_green");
|
connect_status.removeClass("color_green");
|
||||||
connect_status.addClass("color_orange");
|
connect_status.addClass("color_orange");
|
||||||
|
updateUSStatItems([], false);
|
||||||
|
updateSPStatItems({});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Register editing events
|
// Register editing events
|
||||||
|
@ -2062,6 +2195,7 @@ $(document).ready(function(){
|
||||||
|
|
||||||
// Make the userscripts menu sortable
|
// Make the userscripts menu sortable
|
||||||
var us_sortable_settings = {
|
var us_sortable_settings = {
|
||||||
|
placeholder: "ussortable-placeholder",
|
||||||
delay: 2,
|
delay: 2,
|
||||||
cursor: "move",
|
cursor: "move",
|
||||||
tolerance: "pointer",
|
tolerance: "pointer",
|
||||||
|
@ -2205,6 +2339,7 @@ $(document).ready(function(){
|
||||||
});
|
});
|
||||||
|
|
||||||
load_accept.on("click", function(ev) {
|
load_accept.on("click", function(ev) {
|
||||||
|
hideMessage();
|
||||||
newly_loaded = true;
|
newly_loaded = true;
|
||||||
socket.send({'cmd': 'loadrequest', 'data': ''});
|
socket.send({'cmd': 'loadrequest', 'data': ''});
|
||||||
hideLoadPopup();
|
hideLoadPopup();
|
||||||
|
@ -2215,6 +2350,7 @@ $(document).ready(function(){
|
||||||
});
|
});
|
||||||
|
|
||||||
sp_accept.on("click", function(ev) {
|
sp_accept.on("click", function(ev) {
|
||||||
|
hideMessage();
|
||||||
socket.send({'cmd': 'sprequest', 'data': ''});
|
socket.send({'cmd': 'sprequest', 'data': ''});
|
||||||
hideSPPopup();
|
hideSPPopup();
|
||||||
});
|
});
|
||||||
|
@ -2225,6 +2361,7 @@ $(document).ready(function(){
|
||||||
});
|
});
|
||||||
|
|
||||||
us_accept.on("click", function(ev) {
|
us_accept.on("click", function(ev) {
|
||||||
|
hideMessage();
|
||||||
socket.send({'cmd': 'usloaded', 'data': usloaded.find(".uslistitem").map(function() { return $(this).attr("name"); }).toArray()});
|
socket.send({'cmd': 'usloaded', 'data': usloaded.find(".uslistitem").map(function() { return $(this).attr("name"); }).toArray()});
|
||||||
socket.send({'cmd': 'usload', 'data': ''});
|
socket.send({'cmd': 'usload', 'data': ''});
|
||||||
hideUSPopup();
|
hideUSPopup();
|
||||||
|
@ -2235,6 +2372,7 @@ $(document).ready(function(){
|
||||||
});
|
});
|
||||||
|
|
||||||
ns_accept.on("click", function(ev) {
|
ns_accept.on("click", function(ev) {
|
||||||
|
hideMessage();
|
||||||
socket.send({'cmd': 'newgame', 'data': ''});
|
socket.send({'cmd': 'newgame', 'data': ''});
|
||||||
hideNewStoryPopup();
|
hideNewStoryPopup();
|
||||||
});
|
});
|
||||||
|
@ -2267,6 +2405,7 @@ $(document).ready(function(){
|
||||||
});
|
});
|
||||||
|
|
||||||
rs_accept.on("click", function(ev) {
|
rs_accept.on("click", function(ev) {
|
||||||
|
hideMessage();
|
||||||
socket.send({'cmd': 'rndgame', 'data': topic.val()});
|
socket.send({'cmd': 'rndgame', 'data': topic.val()});
|
||||||
hideRandomStoryPopup();
|
hideRandomStoryPopup();
|
||||||
});
|
});
|
||||||
|
|
|
@ -29,11 +29,12 @@ chunk.editing, chunk.editing * {
|
||||||
#topmenu {
|
#topmenu {
|
||||||
background-color: #337ab7;
|
background-color: #337ab7;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
#menuitems {
|
#menuitems {
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-template-columns: 80% 20%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#navbar {
|
#navbar {
|
||||||
|
@ -66,10 +67,7 @@ chunk.editing, chunk.editing * {
|
||||||
|
|
||||||
#connectstatusdiv {
|
#connectstatusdiv {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
text-align: right;
|
||||||
|
|
||||||
#connectstatusdiv span {
|
|
||||||
align-self: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#gamescreen {
|
#gamescreen {
|
||||||
|
@ -437,10 +435,10 @@ chunk.editing, chunk.editing * {
|
||||||
}
|
}
|
||||||
|
|
||||||
.colorfade, .colorfade * {
|
.colorfade, .colorfade * {
|
||||||
-moz-transition:color 1s ease-in;
|
-moz-transition: color 1s ease-in, text-shadow 1s ease-in;
|
||||||
-o-transition:color 1s ease-in;
|
-o-transition: color 1s ease-in, text-shadow 1s ease-in;
|
||||||
-webkit-transition:color 1s ease-in;
|
-webkit-transition: color 1s ease-in, text-shadow 1s ease-in;
|
||||||
transition:color 1s ease-in;
|
transition: color 1s ease-in, text-shadow 1s ease-in;
|
||||||
}
|
}
|
||||||
|
|
||||||
.color_orange {
|
.color_orange {
|
||||||
|
@ -484,6 +482,11 @@ chunk.editing, chunk.editing * {
|
||||||
color: #3bf723 !important;
|
color: #3bf723 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.status-flash, .status-flash {
|
||||||
|
color: #fce94f !important;
|
||||||
|
text-shadow: 0 0 50px #fce94f, 0 0 50px #fce94f, 0 0 10px #fce94f, 0 0 10px #fce94f, 0 0 10px #fce94f, 0 0 10px #fce94f, 0 0 10px #fce94f;
|
||||||
|
}
|
||||||
|
|
||||||
.flex {
|
.flex {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -603,7 +606,12 @@ chunk.editing, chunk.editing * {
|
||||||
background-color: #3bf723;
|
background-color: #3bf723;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wisortable-container {
|
.ussortable-placeholder {
|
||||||
|
height: 4px;
|
||||||
|
background-color: #3bf723;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wisortable-container.folder-expanded {
|
||||||
padding-bottom: 50px;
|
padding-bottom: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -651,11 +659,30 @@ chunk.editing, chunk.editing * {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.helpicon:hover {
|
.statusicon {
|
||||||
|
display: inline-block;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
|
font-size: 30px !important;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.4ex;
|
||||||
|
line-height: 1.8ex;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #68a2d4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statusicon.active {
|
||||||
|
color: #3bf723;
|
||||||
|
}
|
||||||
|
|
||||||
|
.helpicon:hover, .statusicon:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.helpicon:hover .helptext {
|
.helpicon:hover .helptext, .statusicon:hover .statustext, .statusicon.statustoggled .statustext {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 250px;
|
width: 250px;
|
||||||
background-color: #1f2931;
|
background-color: #1f2931;
|
||||||
|
@ -667,13 +694,59 @@ chunk.editing, chunk.editing * {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
margin-left:10px;
|
margin-left:10px;
|
||||||
border: 1px solid #337ab7;
|
border: 1px solid #337ab7;
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.helptext {
|
.statusicon:hover .statustext.statustext-wide, .statusicon.statustoggled .statustext.statustext-wide {
|
||||||
|
width: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statusiconlabel {
|
||||||
|
pointer-events: none;
|
||||||
|
color: #337ab7;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#usiconlabel {
|
||||||
|
transform: translate(-3px, 10px);
|
||||||
|
-moz-transform: translate(-3px, 10px);
|
||||||
|
-webkit-transform: translate(-3px, 10px);
|
||||||
|
-ms-transform: translate(-3px, 10px);
|
||||||
|
-o-transform: translate(-3px, 10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-container {
|
||||||
|
z-index: 1;
|
||||||
|
text-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.helptext, .statustext {
|
||||||
display: none;
|
display: none;
|
||||||
|
font-family: sans-serif;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
text-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.statustext {
|
||||||
|
transform: translate(-105%, 30px);
|
||||||
|
-moz-transform: translate(-105%, 30px);
|
||||||
|
-webkit-transform: translate(-105%, 30px);
|
||||||
|
-ms-transform: translate(-105%, 30px);
|
||||||
|
-o-transform: translate(-105%, 30px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.statusheader {
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#stat-usactive {
|
||||||
|
text-align: left;
|
||||||
|
height: 270px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
position: relative;
|
||||||
|
padding-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.justifyleft {
|
.justifyleft {
|
||||||
|
@ -702,6 +775,23 @@ chunk.editing, chunk.editing * {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.folder-expand {
|
||||||
|
opacity: 20%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder-expand:hover {
|
||||||
|
opacity: 44%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder-expand.folder-expanded {
|
||||||
|
opacity: 80% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.folder-expand.folder-expanded:hover {
|
||||||
|
opacity: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
.selective-key-icon {
|
.selective-key-icon {
|
||||||
position: absolute !important;
|
position: absolute !important;
|
||||||
top: 5px !important;
|
top: 5px !important;
|
||||||
|
@ -893,7 +983,7 @@ chunk.editing, chunk.editing * {
|
||||||
}
|
}
|
||||||
|
|
||||||
.navcontainer {
|
.navcontainer {
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nowrap {
|
.nowrap {
|
||||||
|
|
|
@ -10,12 +10,12 @@
|
||||||
<script src="static/bootstrap.min.js"></script>
|
<script src="static/bootstrap.min.js"></script>
|
||||||
<script src="static/bootstrap-toggle.min.js"></script>
|
<script src="static/bootstrap-toggle.min.js"></script>
|
||||||
<script src="static/rangy-core.min.js"></script>
|
<script src="static/rangy-core.min.js"></script>
|
||||||
<script src="static/application.js?ver=1.16.4i"></script>
|
<script src="static/application.js?ver=1.16.4m"></script>
|
||||||
|
|
||||||
<link rel="stylesheet" href="static/jquery-ui.sortable.min.css">
|
<link rel="stylesheet" href="static/jquery-ui.sortable.min.css">
|
||||||
<link rel="stylesheet" href="static/bootstrap.min.css">
|
<link rel="stylesheet" href="static/bootstrap.min.css">
|
||||||
<link rel="stylesheet" href="static/bootstrap-toggle.min.css">
|
<link rel="stylesheet" href="static/bootstrap-toggle.min.css">
|
||||||
<link rel="stylesheet" href="static/custom.css?ver=1.16.4e">
|
<link rel="stylesheet" href="static/custom.css?ver=1.16.4g">
|
||||||
<link rel="stylesheet" href="static/open-iconic-bootstrap.min.css">
|
<link rel="stylesheet" href="static/open-iconic-bootstrap.min.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
@ -80,8 +80,23 @@
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
<div id="connectstatusdiv">
|
<div id="connectstatusdiv" class="flex-row-container">
|
||||||
<span id="connectstatus" class="color_orange">Waiting for connection...</span>
|
<span id="connectstatus" class="color_orange flex-row">Waiting for connection...</span>
|
||||||
|
<div class="layer-container status-container flex-push-right">
|
||||||
|
<span class="oi oi-puzzle-piece statusicon layer-bottom" aria-hidden="true">
|
||||||
|
<div class="statustext statustext-wide">
|
||||||
|
<div id="stat-us" class="statusheader">No userscripts active</div>
|
||||||
|
<div id="stat-usactive"></div>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
<div class="layer-top statusiconlabel" id="usiconlabel"></div>
|
||||||
|
</div>
|
||||||
|
<span class="oi oi-lightbulb statusicon" aria-hidden="true">
|
||||||
|
<div class="statustext">
|
||||||
|
<div id="stat-sp" class="statusheader">No soft prompt active</div>
|
||||||
|
<div id="stat-spactive"></div>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue