mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-02-12 10:00:36 +01:00
Merge remote-tracking branch 'upstream/staging' into staging
This commit is contained in:
commit
940da09fd4
@ -55,7 +55,7 @@ openai:
|
|||||||
# Will send a random user ID to OpenAI completion API
|
# Will send a random user ID to OpenAI completion API
|
||||||
randomizeUserId: false
|
randomizeUserId: false
|
||||||
# If not empty, will add this as a system message to the start of every caption completion prompt
|
# If not empty, will add this as a system message to the start of every caption completion prompt
|
||||||
# Example: "Perform the instructions to the best of your ability.\n\n" (for LLaVA)
|
# Example: "Perform the instructions to the best of your ability.\n" (for LLaVA)
|
||||||
# Not used in image inlining mode
|
# Not used in image inlining mode
|
||||||
captionSystemPrompt: ""
|
captionSystemPrompt: ""
|
||||||
# -- DEEPL TRANSLATION CONFIGURATION --
|
# -- DEEPL TRANSLATION CONFIGURATION --
|
||||||
|
24
public/img/tabby.svg
Normal file
24
public/img/tabby.svg
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||||
|
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="176.000000pt" height="176.000000pt" viewBox="0 0 176.000000 176.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
|
||||||
|
<g transform="translate(0.000000,176.000000) scale(0.100000,-0.100000)"
|
||||||
|
fill="#ffffff" stroke="none">
|
||||||
|
<path d="M197 1670 c-16 -19 -32 -58 -43 -107 -19 -87 -16 -222 11 -422 21
|
||||||
|
-162 19 -218 -10 -306 -49 -144 -43 -332 14 -443 54 -106 160 -180 297 -207
|
||||||
|
164 -33 202 -44 270 -77 59 -28 80 -33 144 -33 66 0 84 4 154 38 53 25 110 43
|
||||||
|
170 53 122 21 177 38 241 74 158 90 225 282 180 515 -8 42 -21 90 -30 107 -20
|
||||||
|
41 -19 144 1 284 9 60 17 177 17 259 1 134 -1 156 -21 206 -31 77 -50 93 -104
|
||||||
|
85 -84 -13 -183 -89 -319 -243 l-54 -62 -75 19 c-100 26 -224 26 -321 0 l-74
|
||||||
|
-20 -54 63 c-95 109 -182 186 -244 217 -79 39 -117 39 -150 0z m1121 -897 c2
|
||||||
|
-18 -5 -52 -16 -76 -25 -55 -61 -73 -171 -83 l-84 -7 5 51 c7 74 45 114 138
|
||||||
|
146 8 3 40 4 70 3 54 -2 55 -2 58 -34z m-693 16 c24 -7 55 -27 78 -51 33 -34
|
||||||
|
37 -45 37 -88 0 -57 5 -56 -119 -40 -96 13 -136 48 -141 125 -5 64 -4 65 53
|
||||||
|
65 28 0 70 -5 92 -11z m391 -384 c21 -28 18 -33 -31 -63 -32 -19 -48 -36 -53
|
||||||
|
-57 -6 -23 -14 -30 -32 -30 -18 0 -26 7 -32 32 -6 24 -19 38 -48 53 -31 16
|
||||||
|
-40 26 -40 46 0 34 27 42 134 40 73 -2 91 -6 102 -21z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
1
public/lib/css-parser.map
Normal file
1
public/lib/css-parser.map
Normal file
File diff suppressed because one or more lines are too long
765
public/lib/css-parser.mjs
Normal file
765
public/lib/css-parser.mjs
Normal file
@ -0,0 +1,765 @@
|
|||||||
|
|
||||||
|
function $parcel$defineInteropFlag(a) {
|
||||||
|
Object.defineProperty(a, '__esModule', {value: true, configurable: true});
|
||||||
|
}
|
||||||
|
|
||||||
|
function $parcel$export(e, n, v, s) {
|
||||||
|
Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
|
||||||
|
}
|
||||||
|
var $009ddb00d3ec72b8$exports = {};
|
||||||
|
|
||||||
|
$parcel$defineInteropFlag($009ddb00d3ec72b8$exports);
|
||||||
|
|
||||||
|
$parcel$export($009ddb00d3ec72b8$exports, "default", () => $009ddb00d3ec72b8$export$2e2bcd8739ae039);
|
||||||
|
class $009ddb00d3ec72b8$export$2e2bcd8739ae039 extends Error {
|
||||||
|
constructor(filename, msg, lineno, column, css){
|
||||||
|
super(filename + ":" + lineno + ":" + column + ": " + msg);
|
||||||
|
this.reason = msg;
|
||||||
|
this.filename = filename;
|
||||||
|
this.line = lineno;
|
||||||
|
this.column = column;
|
||||||
|
this.source = css;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var $0865a9fb4cc365fe$exports = {};
|
||||||
|
|
||||||
|
$parcel$defineInteropFlag($0865a9fb4cc365fe$exports);
|
||||||
|
|
||||||
|
$parcel$export($0865a9fb4cc365fe$exports, "default", () => $0865a9fb4cc365fe$export$2e2bcd8739ae039);
|
||||||
|
/**
|
||||||
|
* Store position information for a node
|
||||||
|
*/ class $0865a9fb4cc365fe$export$2e2bcd8739ae039 {
|
||||||
|
constructor(start, end, source){
|
||||||
|
this.start = start;
|
||||||
|
this.end = end;
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var $b2e137848b48cf4f$exports = {};
|
||||||
|
|
||||||
|
$parcel$export($b2e137848b48cf4f$exports, "CssTypes", () => $b2e137848b48cf4f$export$9be5dd6e61d5d73a);
|
||||||
|
var $b2e137848b48cf4f$export$9be5dd6e61d5d73a;
|
||||||
|
(function(CssTypes) {
|
||||||
|
CssTypes["stylesheet"] = "stylesheet";
|
||||||
|
CssTypes["rule"] = "rule";
|
||||||
|
CssTypes["declaration"] = "declaration";
|
||||||
|
CssTypes["comment"] = "comment";
|
||||||
|
CssTypes["container"] = "container";
|
||||||
|
CssTypes["charset"] = "charset";
|
||||||
|
CssTypes["document"] = "document";
|
||||||
|
CssTypes["customMedia"] = "custom-media";
|
||||||
|
CssTypes["fontFace"] = "font-face";
|
||||||
|
CssTypes["host"] = "host";
|
||||||
|
CssTypes["import"] = "import";
|
||||||
|
CssTypes["keyframes"] = "keyframes";
|
||||||
|
CssTypes["keyframe"] = "keyframe";
|
||||||
|
CssTypes["layer"] = "layer";
|
||||||
|
CssTypes["media"] = "media";
|
||||||
|
CssTypes["namespace"] = "namespace";
|
||||||
|
CssTypes["page"] = "page";
|
||||||
|
CssTypes["supports"] = "supports";
|
||||||
|
})($b2e137848b48cf4f$export$9be5dd6e61d5d73a || ($b2e137848b48cf4f$export$9be5dd6e61d5d73a = {}));
|
||||||
|
|
||||||
|
|
||||||
|
// http://www.w3.org/TR/CSS21/grammar.html
|
||||||
|
// https://github.com/visionmedia/css-parse/pull/49#issuecomment-30088027
|
||||||
|
// New rule => https://www.w3.org/TR/CSS22/syndata.html#comments
|
||||||
|
// [^] is equivalent to [.\n\r]
|
||||||
|
const $d708735ed1303b43$var$commentre = /\/\*[^]*?(?:\*\/|$)/g;
|
||||||
|
const $d708735ed1303b43$export$98e6a39c04603d36 = (css, options)=>{
|
||||||
|
options = options || {};
|
||||||
|
/**
|
||||||
|
* Positional.
|
||||||
|
*/ let lineno = 1;
|
||||||
|
let column = 1;
|
||||||
|
/**
|
||||||
|
* Update lineno and column based on `str`.
|
||||||
|
*/ function updatePosition(str) {
|
||||||
|
const lines = str.match(/\n/g);
|
||||||
|
if (lines) lineno += lines.length;
|
||||||
|
const i = str.lastIndexOf("\n");
|
||||||
|
column = ~i ? str.length - i : column + str.length;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Mark position and patch `node.position`.
|
||||||
|
*/ function position() {
|
||||||
|
const start = {
|
||||||
|
line: lineno,
|
||||||
|
column: column
|
||||||
|
};
|
||||||
|
return function(node) {
|
||||||
|
node.position = new (0, $0865a9fb4cc365fe$export$2e2bcd8739ae039)(start, {
|
||||||
|
line: lineno,
|
||||||
|
column: column
|
||||||
|
}, options?.source || "");
|
||||||
|
whitespace();
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Error `msg`.
|
||||||
|
*/ const errorsList = [];
|
||||||
|
function error(msg) {
|
||||||
|
const err = new (0, $009ddb00d3ec72b8$export$2e2bcd8739ae039)(options?.source || "", msg, lineno, column, css);
|
||||||
|
if (options?.silent) errorsList.push(err);
|
||||||
|
else throw err;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse stylesheet.
|
||||||
|
*/ function stylesheet() {
|
||||||
|
const rulesList = rules();
|
||||||
|
const result = {
|
||||||
|
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).stylesheet,
|
||||||
|
stylesheet: {
|
||||||
|
source: options?.source,
|
||||||
|
rules: rulesList,
|
||||||
|
parsingErrors: errorsList
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Opening brace.
|
||||||
|
*/ function open() {
|
||||||
|
return match(/^{\s*/);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Closing brace.
|
||||||
|
*/ function close() {
|
||||||
|
return match(/^}/);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse ruleset.
|
||||||
|
*/ function rules() {
|
||||||
|
let node;
|
||||||
|
const rules = [];
|
||||||
|
whitespace();
|
||||||
|
comments(rules);
|
||||||
|
while(css.length && css.charAt(0) !== "}" && (node = atrule() || rule()))if (node) {
|
||||||
|
rules.push(node);
|
||||||
|
comments(rules);
|
||||||
|
}
|
||||||
|
return rules;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Match `re` and return captures.
|
||||||
|
*/ function match(re) {
|
||||||
|
const m = re.exec(css);
|
||||||
|
if (!m) return;
|
||||||
|
const str = m[0];
|
||||||
|
updatePosition(str);
|
||||||
|
css = css.slice(str.length);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse whitespace.
|
||||||
|
*/ function whitespace() {
|
||||||
|
match(/^\s*/);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse comments;
|
||||||
|
*/ function comments(rules) {
|
||||||
|
let c;
|
||||||
|
rules = rules || [];
|
||||||
|
while(c = comment())if (c) rules.push(c);
|
||||||
|
return rules;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse comment.
|
||||||
|
*/ function comment() {
|
||||||
|
const pos = position();
|
||||||
|
if ("/" !== css.charAt(0) || "*" !== css.charAt(1)) return;
|
||||||
|
const m = match(/^\/\*[^]*?\*\//);
|
||||||
|
if (!m) return error("End of comment missing");
|
||||||
|
return pos({
|
||||||
|
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).comment,
|
||||||
|
comment: m[0].slice(2, -2)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function findClosingParenthese(str, start, depth) {
|
||||||
|
let ptr = start + 1;
|
||||||
|
let found = false;
|
||||||
|
let closeParentheses = str.indexOf(")", ptr);
|
||||||
|
while(!found && closeParentheses !== -1){
|
||||||
|
const nextParentheses = str.indexOf("(", ptr);
|
||||||
|
if (nextParentheses !== -1 && nextParentheses < closeParentheses) {
|
||||||
|
const nextSearch = findClosingParenthese(str, nextParentheses + 1, depth + 1);
|
||||||
|
ptr = nextSearch + 1;
|
||||||
|
closeParentheses = str.indexOf(")", ptr);
|
||||||
|
} else found = true;
|
||||||
|
}
|
||||||
|
if (found && closeParentheses !== -1) return closeParentheses;
|
||||||
|
else return -1;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse selector.
|
||||||
|
*/ function selector() {
|
||||||
|
const m = match(/^([^{]+)/);
|
||||||
|
if (!m) return;
|
||||||
|
// remove comment in selector;
|
||||||
|
let res = $d708735ed1303b43$var$trim(m[0]).replace($d708735ed1303b43$var$commentre, "");
|
||||||
|
// Optimisation: If there is no ',' no need to split or post-process (this is less costly)
|
||||||
|
if (res.indexOf(",") === -1) return [
|
||||||
|
res
|
||||||
|
];
|
||||||
|
// Replace all the , in the parentheses by \u200C
|
||||||
|
let ptr = 0;
|
||||||
|
let startParentheses = res.indexOf("(", ptr);
|
||||||
|
while(startParentheses !== -1){
|
||||||
|
const closeParentheses = findClosingParenthese(res, startParentheses, 0);
|
||||||
|
if (closeParentheses === -1) break;
|
||||||
|
ptr = closeParentheses + 1;
|
||||||
|
res = res.substring(0, startParentheses) + res.substring(startParentheses, closeParentheses).replace(/,/g, "\u200C") + res.substring(closeParentheses);
|
||||||
|
startParentheses = res.indexOf("(", ptr);
|
||||||
|
}
|
||||||
|
// Replace all the , in ' and " by \u200C
|
||||||
|
res = res/**
|
||||||
|
* replace ',' by \u200C for data selector (div[data-lang="fr,de,us"])
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
* div[data-lang="fr,\"de,us"]
|
||||||
|
* div[data-lang='fr,\'de,us']
|
||||||
|
*
|
||||||
|
* Regex logic:
|
||||||
|
* ("|')(?:\\\1|.)*?\1 => Handle the " and '
|
||||||
|
*
|
||||||
|
* Optimization 1:
|
||||||
|
* No greedy capture (see docs about the difference between .* and .*?)
|
||||||
|
*
|
||||||
|
* Optimization 2:
|
||||||
|
* ("|')(?:\\\1|.)*?\1 this use reference to capture group, it work faster.
|
||||||
|
*/ .replace(/("|')(?:\\\1|.)*?\1/g, (m)=>m.replace(/,/g, "\u200C"));
|
||||||
|
// Split all the left , and replace all the \u200C by ,
|
||||||
|
return res// Split the selector by ','
|
||||||
|
.split(",")// Replace back \u200C by ','
|
||||||
|
.map((s)=>{
|
||||||
|
return $d708735ed1303b43$var$trim(s.replace(/\u200C/g, ","));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse declaration.
|
||||||
|
*/ function declaration() {
|
||||||
|
const pos = position();
|
||||||
|
// prop
|
||||||
|
const propMatch = match(/^(\*?[-#/*\\\w]+(\[[0-9a-z_-]+\])?)\s*/);
|
||||||
|
if (!propMatch) return;
|
||||||
|
const propValue = $d708735ed1303b43$var$trim(propMatch[0]);
|
||||||
|
// :
|
||||||
|
if (!match(/^:\s*/)) return error("property missing ':'");
|
||||||
|
// val
|
||||||
|
const val = match(/^((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};])+)/);
|
||||||
|
const ret = pos({
|
||||||
|
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).declaration,
|
||||||
|
property: propValue.replace($d708735ed1303b43$var$commentre, ""),
|
||||||
|
value: val ? $d708735ed1303b43$var$trim(val[0]).replace($d708735ed1303b43$var$commentre, "") : ""
|
||||||
|
});
|
||||||
|
// ;
|
||||||
|
match(/^[;\s]*/);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse declarations.
|
||||||
|
*/ function declarations() {
|
||||||
|
const decls = [];
|
||||||
|
if (!open()) return error("missing '{'");
|
||||||
|
comments(decls);
|
||||||
|
// declarations
|
||||||
|
let decl;
|
||||||
|
while(decl = declaration())if (decl) {
|
||||||
|
decls.push(decl);
|
||||||
|
comments(decls);
|
||||||
|
}
|
||||||
|
if (!close()) return error("missing '}'");
|
||||||
|
return decls;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse keyframe.
|
||||||
|
*/ function keyframe() {
|
||||||
|
let m;
|
||||||
|
const vals = [];
|
||||||
|
const pos = position();
|
||||||
|
while(m = match(/^((\d+\.\d+|\.\d+|\d+)%?|[a-z]+)\s*/)){
|
||||||
|
vals.push(m[1]);
|
||||||
|
match(/^,\s*/);
|
||||||
|
}
|
||||||
|
if (!vals.length) return;
|
||||||
|
return pos({
|
||||||
|
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).keyframe,
|
||||||
|
values: vals,
|
||||||
|
declarations: declarations() || []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse keyframes.
|
||||||
|
*/ function atkeyframes() {
|
||||||
|
const pos = position();
|
||||||
|
const m1 = match(/^@([-\w]+)?keyframes\s*/);
|
||||||
|
if (!m1) return;
|
||||||
|
const vendor = m1[1];
|
||||||
|
// identifier
|
||||||
|
const m2 = match(/^([-\w]+)\s*/);
|
||||||
|
if (!m2) return error("@keyframes missing name");
|
||||||
|
const name = m2[1];
|
||||||
|
if (!open()) return error("@keyframes missing '{'");
|
||||||
|
let frame;
|
||||||
|
let frames = comments();
|
||||||
|
while(frame = keyframe()){
|
||||||
|
frames.push(frame);
|
||||||
|
frames = frames.concat(comments());
|
||||||
|
}
|
||||||
|
if (!close()) return error("@keyframes missing '}'");
|
||||||
|
return pos({
|
||||||
|
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).keyframes,
|
||||||
|
name: name,
|
||||||
|
vendor: vendor,
|
||||||
|
keyframes: frames
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse supports.
|
||||||
|
*/ function atsupports() {
|
||||||
|
const pos = position();
|
||||||
|
const m = match(/^@supports *([^{]+)/);
|
||||||
|
if (!m) return;
|
||||||
|
const supports = $d708735ed1303b43$var$trim(m[1]);
|
||||||
|
if (!open()) return error("@supports missing '{'");
|
||||||
|
const style = comments().concat(rules());
|
||||||
|
if (!close()) return error("@supports missing '}'");
|
||||||
|
return pos({
|
||||||
|
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).supports,
|
||||||
|
supports: supports,
|
||||||
|
rules: style
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse host.
|
||||||
|
*/ function athost() {
|
||||||
|
const pos = position();
|
||||||
|
const m = match(/^@host\s*/);
|
||||||
|
if (!m) return;
|
||||||
|
if (!open()) return error("@host missing '{'");
|
||||||
|
const style = comments().concat(rules());
|
||||||
|
if (!close()) return error("@host missing '}'");
|
||||||
|
return pos({
|
||||||
|
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).host,
|
||||||
|
rules: style
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse container.
|
||||||
|
*/ function atcontainer() {
|
||||||
|
const pos = position();
|
||||||
|
const m = match(/^@container *([^{]+)/);
|
||||||
|
if (!m) return;
|
||||||
|
const container = $d708735ed1303b43$var$trim(m[1]);
|
||||||
|
if (!open()) return error("@container missing '{'");
|
||||||
|
const style = comments().concat(rules());
|
||||||
|
if (!close()) return error("@container missing '}'");
|
||||||
|
return pos({
|
||||||
|
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).container,
|
||||||
|
container: container,
|
||||||
|
rules: style
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse container.
|
||||||
|
*/ function atlayer() {
|
||||||
|
const pos = position();
|
||||||
|
const m = match(/^@layer *([^{;@]+)/);
|
||||||
|
if (!m) return;
|
||||||
|
const layer = $d708735ed1303b43$var$trim(m[1]);
|
||||||
|
if (!open()) {
|
||||||
|
match(/^[;\s]*/);
|
||||||
|
return pos({
|
||||||
|
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).layer,
|
||||||
|
layer: layer
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const style = comments().concat(rules());
|
||||||
|
if (!close()) return error("@layer missing '}'");
|
||||||
|
return pos({
|
||||||
|
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).layer,
|
||||||
|
layer: layer,
|
||||||
|
rules: style
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse media.
|
||||||
|
*/ function atmedia() {
|
||||||
|
const pos = position();
|
||||||
|
const m = match(/^@media *([^{]+)/);
|
||||||
|
if (!m) return;
|
||||||
|
const media = $d708735ed1303b43$var$trim(m[1]);
|
||||||
|
if (!open()) return error("@media missing '{'");
|
||||||
|
const style = comments().concat(rules());
|
||||||
|
if (!close()) return error("@media missing '}'");
|
||||||
|
return pos({
|
||||||
|
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).media,
|
||||||
|
media: media,
|
||||||
|
rules: style
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse custom-media.
|
||||||
|
*/ function atcustommedia() {
|
||||||
|
const pos = position();
|
||||||
|
const m = match(/^@custom-media\s+(--\S+)\s*([^{;\s][^{;]*);/);
|
||||||
|
if (!m) return;
|
||||||
|
return pos({
|
||||||
|
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).customMedia,
|
||||||
|
name: $d708735ed1303b43$var$trim(m[1]),
|
||||||
|
media: $d708735ed1303b43$var$trim(m[2])
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse paged media.
|
||||||
|
*/ function atpage() {
|
||||||
|
const pos = position();
|
||||||
|
const m = match(/^@page */);
|
||||||
|
if (!m) return;
|
||||||
|
const sel = selector() || [];
|
||||||
|
if (!open()) return error("@page missing '{'");
|
||||||
|
let decls = comments();
|
||||||
|
// declarations
|
||||||
|
let decl;
|
||||||
|
while(decl = declaration()){
|
||||||
|
decls.push(decl);
|
||||||
|
decls = decls.concat(comments());
|
||||||
|
}
|
||||||
|
if (!close()) return error("@page missing '}'");
|
||||||
|
return pos({
|
||||||
|
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).page,
|
||||||
|
selectors: sel,
|
||||||
|
declarations: decls
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse document.
|
||||||
|
*/ function atdocument() {
|
||||||
|
const pos = position();
|
||||||
|
const m = match(/^@([-\w]+)?document *([^{]+)/);
|
||||||
|
if (!m) return;
|
||||||
|
const vendor = $d708735ed1303b43$var$trim(m[1]);
|
||||||
|
const doc = $d708735ed1303b43$var$trim(m[2]);
|
||||||
|
if (!open()) return error("@document missing '{'");
|
||||||
|
const style = comments().concat(rules());
|
||||||
|
if (!close()) return error("@document missing '}'");
|
||||||
|
return pos({
|
||||||
|
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).document,
|
||||||
|
document: doc,
|
||||||
|
vendor: vendor,
|
||||||
|
rules: style
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse font-face.
|
||||||
|
*/ function atfontface() {
|
||||||
|
const pos = position();
|
||||||
|
const m = match(/^@font-face\s*/);
|
||||||
|
if (!m) return;
|
||||||
|
if (!open()) return error("@font-face missing '{'");
|
||||||
|
let decls = comments();
|
||||||
|
// declarations
|
||||||
|
let decl;
|
||||||
|
while(decl = declaration()){
|
||||||
|
decls.push(decl);
|
||||||
|
decls = decls.concat(comments());
|
||||||
|
}
|
||||||
|
if (!close()) return error("@font-face missing '}'");
|
||||||
|
return pos({
|
||||||
|
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).fontFace,
|
||||||
|
declarations: decls
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse import
|
||||||
|
*/ const atimport = _compileAtrule("import");
|
||||||
|
/**
|
||||||
|
* Parse charset
|
||||||
|
*/ const atcharset = _compileAtrule("charset");
|
||||||
|
/**
|
||||||
|
* Parse namespace
|
||||||
|
*/ const atnamespace = _compileAtrule("namespace");
|
||||||
|
/**
|
||||||
|
* Parse non-block at-rules
|
||||||
|
*/ function _compileAtrule(name) {
|
||||||
|
const re = new RegExp("^@" + name + "\\s*((?::?[^;'\"]|\"(?:\\\\\"|[^\"])*?\"|'(?:\\\\'|[^'])*?')+)(?:;|$)");
|
||||||
|
// ^@import\s*([^;"']|("|')(?:\\\2|.)*?\2)+(;|$)
|
||||||
|
return function() {
|
||||||
|
const pos = position();
|
||||||
|
const m = match(re);
|
||||||
|
if (!m) return;
|
||||||
|
const ret = {
|
||||||
|
type: name
|
||||||
|
};
|
||||||
|
ret[name] = m[1].trim();
|
||||||
|
return pos(ret);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse at rule.
|
||||||
|
*/ function atrule() {
|
||||||
|
if (css[0] !== "@") return;
|
||||||
|
return atkeyframes() || atmedia() || atcustommedia() || atsupports() || atimport() || atcharset() || atnamespace() || atdocument() || atpage() || athost() || atfontface() || atcontainer() || atlayer();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Parse rule.
|
||||||
|
*/ function rule() {
|
||||||
|
const pos = position();
|
||||||
|
const sel = selector();
|
||||||
|
if (!sel) return error("selector missing");
|
||||||
|
comments();
|
||||||
|
return pos({
|
||||||
|
type: (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).rule,
|
||||||
|
selectors: sel,
|
||||||
|
declarations: declarations() || []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return $d708735ed1303b43$var$addParent(stylesheet());
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Trim `str`.
|
||||||
|
*/ function $d708735ed1303b43$var$trim(str) {
|
||||||
|
return str ? str.trim() : "";
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Adds non-enumerable parent node reference to each node.
|
||||||
|
*/ function $d708735ed1303b43$var$addParent(obj, parent) {
|
||||||
|
const isNode = obj && typeof obj.type === "string";
|
||||||
|
const childParent = isNode ? obj : parent;
|
||||||
|
for(const k in obj){
|
||||||
|
const value = obj[k];
|
||||||
|
if (Array.isArray(value)) value.forEach((v)=>{
|
||||||
|
$d708735ed1303b43$var$addParent(v, childParent);
|
||||||
|
});
|
||||||
|
else if (value && typeof value === "object") $d708735ed1303b43$var$addParent(value, childParent);
|
||||||
|
}
|
||||||
|
if (isNode) Object.defineProperty(obj, "parent", {
|
||||||
|
configurable: true,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
value: parent || null
|
||||||
|
});
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
var $d708735ed1303b43$export$2e2bcd8739ae039 = $d708735ed1303b43$export$98e6a39c04603d36;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class $de9540138ed1fd01$var$Compiler {
|
||||||
|
constructor(options){
|
||||||
|
this.level = 0;
|
||||||
|
this.indentation = " ";
|
||||||
|
this.compress = false;
|
||||||
|
if (typeof options?.indent === "string") this.indentation = options?.indent;
|
||||||
|
if (options?.compress) this.compress = true;
|
||||||
|
}
|
||||||
|
// We disable no-unused-vars for _position. We keep position for potential reintroduction of source-map
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
emit(str, _position) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Increase, decrease or return current indentation.
|
||||||
|
*/ indent(level) {
|
||||||
|
this.level = this.level || 1;
|
||||||
|
if (level) {
|
||||||
|
this.level += level;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return Array(this.level).join(this.indentation);
|
||||||
|
}
|
||||||
|
visit(node) {
|
||||||
|
switch(node.type){
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).stylesheet:
|
||||||
|
return this.stylesheet(node);
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).rule:
|
||||||
|
return this.rule(node);
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).declaration:
|
||||||
|
return this.declaration(node);
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).comment:
|
||||||
|
return this.comment(node);
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).container:
|
||||||
|
return this.container(node);
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).charset:
|
||||||
|
return this.charset(node);
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).document:
|
||||||
|
return this.document(node);
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).customMedia:
|
||||||
|
return this.customMedia(node);
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).fontFace:
|
||||||
|
return this.fontFace(node);
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).host:
|
||||||
|
return this.host(node);
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).import:
|
||||||
|
return this.import(node);
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).keyframes:
|
||||||
|
return this.keyframes(node);
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).keyframe:
|
||||||
|
return this.keyframe(node);
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).layer:
|
||||||
|
return this.layer(node);
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).media:
|
||||||
|
return this.media(node);
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).namespace:
|
||||||
|
return this.namespace(node);
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).page:
|
||||||
|
return this.page(node);
|
||||||
|
case (0, $b2e137848b48cf4f$export$9be5dd6e61d5d73a).supports:
|
||||||
|
return this.supports(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mapVisit(nodes, delim) {
|
||||||
|
let buf = "";
|
||||||
|
delim = delim || "";
|
||||||
|
for(let i = 0, length = nodes.length; i < length; i++){
|
||||||
|
buf += this.visit(nodes[i]);
|
||||||
|
if (delim && i < length - 1) buf += this.emit(delim);
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
compile(node) {
|
||||||
|
if (this.compress) return node.stylesheet.rules.map(this.visit, this).join("");
|
||||||
|
return this.stylesheet(node);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit stylesheet node.
|
||||||
|
*/ stylesheet(node) {
|
||||||
|
return this.mapVisit(node.stylesheet.rules, "\n\n");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit comment node.
|
||||||
|
*/ comment(node) {
|
||||||
|
if (this.compress) return this.emit("", node.position);
|
||||||
|
return this.emit(this.indent() + "/*" + node.comment + "*/", node.position);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit container node.
|
||||||
|
*/ container(node) {
|
||||||
|
if (this.compress) return this.emit("@container " + node.container, node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
||||||
|
return this.emit(this.indent() + "@container " + node.container, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit("\n" + this.indent(-1) + this.indent() + "}");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit container node.
|
||||||
|
*/ layer(node) {
|
||||||
|
if (this.compress) return this.emit("@layer " + node.layer, node.position) + (node.rules ? this.emit("{") + this.mapVisit(node.rules) + this.emit("}") : ";");
|
||||||
|
return this.emit(this.indent() + "@layer " + node.layer, node.position) + (node.rules ? this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit("\n" + this.indent(-1) + this.indent() + "}") : ";");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit import node.
|
||||||
|
*/ import(node) {
|
||||||
|
return this.emit("@import " + node.import + ";", node.position);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit media node.
|
||||||
|
*/ media(node) {
|
||||||
|
if (this.compress) return this.emit("@media " + node.media, node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
||||||
|
return this.emit(this.indent() + "@media " + node.media, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit("\n" + this.indent(-1) + this.indent() + "}");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit document node.
|
||||||
|
*/ document(node) {
|
||||||
|
const doc = "@" + (node.vendor || "") + "document " + node.document;
|
||||||
|
if (this.compress) return this.emit(doc, node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
||||||
|
return this.emit(doc, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit(this.indent(-1) + "\n}");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit charset node.
|
||||||
|
*/ charset(node) {
|
||||||
|
return this.emit("@charset " + node.charset + ";", node.position);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit namespace node.
|
||||||
|
*/ namespace(node) {
|
||||||
|
return this.emit("@namespace " + node.namespace + ";", node.position);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit supports node.
|
||||||
|
*/ supports(node) {
|
||||||
|
if (this.compress) return this.emit("@supports " + node.supports, node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
||||||
|
return this.emit(this.indent() + "@supports " + node.supports, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit("\n" + this.indent(-1) + this.indent() + "}");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit keyframes node.
|
||||||
|
*/ keyframes(node) {
|
||||||
|
if (this.compress) return this.emit("@" + (node.vendor || "") + "keyframes " + node.name, node.position) + this.emit("{") + this.mapVisit(node.keyframes) + this.emit("}");
|
||||||
|
return this.emit("@" + (node.vendor || "") + "keyframes " + node.name, node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.keyframes, "\n") + this.emit(this.indent(-1) + "}");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit keyframe node.
|
||||||
|
*/ keyframe(node) {
|
||||||
|
const decls = node.declarations;
|
||||||
|
if (this.compress) return this.emit(node.values.join(","), node.position) + this.emit("{") + this.mapVisit(decls) + this.emit("}");
|
||||||
|
return this.emit(this.indent()) + this.emit(node.values.join(", "), node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(decls, "\n") + this.emit(this.indent(-1) + "\n" + this.indent() + "}\n");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit page node.
|
||||||
|
*/ page(node) {
|
||||||
|
if (this.compress) {
|
||||||
|
const sel = node.selectors.length ? node.selectors.join(", ") : "";
|
||||||
|
return this.emit("@page " + sel, node.position) + this.emit("{") + this.mapVisit(node.declarations) + this.emit("}");
|
||||||
|
}
|
||||||
|
const sel = node.selectors.length ? node.selectors.join(", ") + " " : "";
|
||||||
|
return this.emit("@page " + sel, node.position) + this.emit("{\n") + this.emit(this.indent(1)) + this.mapVisit(node.declarations, "\n") + this.emit(this.indent(-1)) + this.emit("\n}");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit font-face node.
|
||||||
|
*/ fontFace(node) {
|
||||||
|
if (this.compress) return this.emit("@font-face", node.position) + this.emit("{") + this.mapVisit(node.declarations) + this.emit("}");
|
||||||
|
return this.emit("@font-face ", node.position) + this.emit("{\n") + this.emit(this.indent(1)) + this.mapVisit(node.declarations, "\n") + this.emit(this.indent(-1)) + this.emit("\n}");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit host node.
|
||||||
|
*/ host(node) {
|
||||||
|
if (this.compress) return this.emit("@host", node.position) + this.emit("{") + this.mapVisit(node.rules) + this.emit("}");
|
||||||
|
return this.emit("@host", node.position) + this.emit(" {\n" + this.indent(1)) + this.mapVisit(node.rules, "\n\n") + this.emit(this.indent(-1) + "\n}");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit custom-media node.
|
||||||
|
*/ customMedia(node) {
|
||||||
|
return this.emit("@custom-media " + node.name + " " + node.media + ";", node.position);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit rule node.
|
||||||
|
*/ rule(node) {
|
||||||
|
const decls = node.declarations;
|
||||||
|
if (!decls.length) return "";
|
||||||
|
if (this.compress) return this.emit(node.selectors.join(","), node.position) + this.emit("{") + this.mapVisit(decls) + this.emit("}");
|
||||||
|
const indent = this.indent();
|
||||||
|
return this.emit(node.selectors.map((s)=>{
|
||||||
|
return indent + s;
|
||||||
|
}).join(",\n"), node.position) + this.emit(" {\n") + this.emit(this.indent(1)) + this.mapVisit(decls, "\n") + this.emit(this.indent(-1)) + this.emit("\n" + this.indent() + "}");
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Visit declaration node.
|
||||||
|
*/ declaration(node) {
|
||||||
|
if (this.compress) return this.emit(node.property + ":" + node.value, node.position) + this.emit(";");
|
||||||
|
return this.emit(this.indent()) + this.emit(node.property + ": " + node.value, node.position) + this.emit(";");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var $de9540138ed1fd01$export$2e2bcd8739ae039 = $de9540138ed1fd01$var$Compiler;
|
||||||
|
|
||||||
|
|
||||||
|
var $fdf773ab87e20450$export$2e2bcd8739ae039 = (node, options)=>{
|
||||||
|
const compiler = new (0, $de9540138ed1fd01$export$2e2bcd8739ae039)(options || {});
|
||||||
|
return compiler.compile(node);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const $149c1bd638913645$export$98e6a39c04603d36 = (0, $d708735ed1303b43$export$2e2bcd8739ae039);
|
||||||
|
const $149c1bd638913645$export$fac44ee5b035f737 = (0, $fdf773ab87e20450$export$2e2bcd8739ae039);
|
||||||
|
var $149c1bd638913645$export$2e2bcd8739ae039 = {
|
||||||
|
parse: $149c1bd638913645$export$98e6a39c04603d36,
|
||||||
|
stringify: $149c1bd638913645$export$fac44ee5b035f737
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export {$149c1bd638913645$export$98e6a39c04603d36 as parse, $149c1bd638913645$export$fac44ee5b035f737 as stringify, $149c1bd638913645$export$2e2bcd8739ae039 as default, $b2e137848b48cf4f$export$9be5dd6e61d5d73a as CssTypes};
|
||||||
|
//# sourceMappingURL=index.mjs.map
|
@ -69,6 +69,27 @@ EventEmitter.prototype.emit = async function (event) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
EventEmitter.prototype.emitAndWait = function (event) {
|
||||||
|
console.debug('Event emitted: ' + event);
|
||||||
|
|
||||||
|
var i, listeners, length, args = [].slice.call(arguments, 1);
|
||||||
|
|
||||||
|
if (typeof this.events[event] === 'object') {
|
||||||
|
listeners = this.events[event].slice();
|
||||||
|
length = listeners.length;
|
||||||
|
|
||||||
|
for (i = 0; i < length; i++) {
|
||||||
|
try {
|
||||||
|
listeners[i].apply(this, args);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
console.trace('Error in event listener');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
EventEmitter.prototype.once = function (event, listener) {
|
EventEmitter.prototype.once = function (event, listener) {
|
||||||
this.on(event, function g () {
|
this.on(event, function g () {
|
||||||
this.removeListener(event, g);
|
this.removeListener(event, g);
|
||||||
|
@ -189,7 +189,7 @@ import { getBackgrounds, initBackgrounds, loadBackgroundSettings, background_set
|
|||||||
import { hideLoader, showLoader } from './scripts/loader.js';
|
import { hideLoader, showLoader } from './scripts/loader.js';
|
||||||
import { BulkEditOverlay, CharacterContextMenu } from './scripts/BulkEditOverlay.js';
|
import { BulkEditOverlay, CharacterContextMenu } from './scripts/BulkEditOverlay.js';
|
||||||
import { loadMancerModels, loadOllamaModels, loadTogetherAIModels } from './scripts/textgen-models.js';
|
import { loadMancerModels, loadOllamaModels, loadTogetherAIModels } from './scripts/textgen-models.js';
|
||||||
import { appendFileContent, hasPendingFileAttachment, populateFileAttachment } from './scripts/chats.js';
|
import { appendFileContent, hasPendingFileAttachment, populateFileAttachment, decodeStyleTags, encodeStyleTags } from './scripts/chats.js';
|
||||||
import { replaceVariableMacros } from './scripts/variables.js';
|
import { replaceVariableMacros } from './scripts/variables.js';
|
||||||
import { initPresetManager } from './scripts/preset-manager.js';
|
import { initPresetManager } from './scripts/preset-manager.js';
|
||||||
|
|
||||||
@ -275,6 +275,26 @@ DOMPurify.addHook('afterSanitizeAttributes', function (node) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
DOMPurify.addHook("uponSanitizeAttribute", (_, data, config) => {
|
||||||
|
if (!config['MESSAGE_SANITIZE']) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switch (data.attrName) {
|
||||||
|
case 'class': {
|
||||||
|
if (data.attrValue) {
|
||||||
|
data.attrValue = data.attrValue.split(' ').map((v) => {
|
||||||
|
if (v.startsWith('fa-') || v.startsWith('note-') || v === 'monospace') {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "custom-" + v;
|
||||||
|
}).join(' ');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// API OBJECT FOR EXTERNAL WIRING
|
// API OBJECT FOR EXTERNAL WIRING
|
||||||
window['SillyTavern'] = {};
|
window['SillyTavern'] = {};
|
||||||
|
|
||||||
@ -313,6 +333,7 @@ export const event_types = {
|
|||||||
FORCE_SET_BACKGROUND: 'force_set_background',
|
FORCE_SET_BACKGROUND: 'force_set_background',
|
||||||
CHAT_DELETED: 'chat_deleted',
|
CHAT_DELETED: 'chat_deleted',
|
||||||
GROUP_CHAT_DELETED: 'group_chat_deleted',
|
GROUP_CHAT_DELETED: 'group_chat_deleted',
|
||||||
|
GENERATE_BEFORE_COMBINE_PROMPTS: 'generate_before_combine_prompts',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const eventSource = new EventEmitter();
|
export const eventSource = new EventEmitter();
|
||||||
@ -1549,7 +1570,11 @@ function messageFormatting(mes, ch_name, isSystem, isUser) {
|
|||||||
mes = mes.replace(new RegExp(`(^|\n)${ch_name}:`, 'g'), '$1');
|
mes = mes.replace(new RegExp(`(^|\n)${ch_name}:`, 'g'), '$1');
|
||||||
}
|
}
|
||||||
|
|
||||||
mes = DOMPurify.sanitize(mes, { FORBID_TAGS: ['style'] });
|
/** @type {any} */
|
||||||
|
const config = { MESSAGE_SANITIZE: true, ADD_TAGS: ['custom-style'] };
|
||||||
|
mes = encodeStyleTags(mes);
|
||||||
|
mes = DOMPurify.sanitize(mes, config);
|
||||||
|
mes = decodeStyleTags(mes);
|
||||||
|
|
||||||
return mes;
|
return mes;
|
||||||
}
|
}
|
||||||
@ -3621,30 +3646,57 @@ async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, qu
|
|||||||
generatedPromptCache = cleanupPromptCache(generatedPromptCache);
|
generatedPromptCache = cleanupPromptCache(generatedPromptCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Right now, everything is suffixed with a newline
|
// Flattens the multiple prompt objects to a string.
|
||||||
mesSendString = finalMesSend.map((e) => `${e.extensionPrompts.join('')}${e.message}`).join('');
|
const combine = () => {
|
||||||
|
// Right now, everything is suffixed with a newline
|
||||||
|
mesSendString = finalMesSend.map((e) => `${e.extensionPrompts.join('')}${e.message}`).join('');
|
||||||
|
|
||||||
// add chat preamble
|
// add a custom dingus (if defined)
|
||||||
mesSendString = addChatsPreamble(mesSendString);
|
mesSendString = addChatsSeparator(mesSendString);
|
||||||
|
|
||||||
// add a custom dingus (if defined)
|
// add chat preamble
|
||||||
mesSendString = addChatsSeparator(mesSendString);
|
mesSendString = addChatsPreamble(mesSendString);
|
||||||
|
|
||||||
let combinedPrompt =
|
let combinedPrompt = beforeScenarioAnchor +
|
||||||
beforeScenarioAnchor +
|
storyString +
|
||||||
storyString +
|
afterScenarioAnchor +
|
||||||
afterScenarioAnchor +
|
mesExmString +
|
||||||
mesExmString +
|
mesSendString +
|
||||||
mesSendString +
|
generatedPromptCache;
|
||||||
generatedPromptCache;
|
|
||||||
|
|
||||||
combinedPrompt = combinedPrompt.replace(/\r/gm, '');
|
combinedPrompt = combinedPrompt.replace(/\r/gm, '');
|
||||||
|
|
||||||
if (power_user.collapse_newlines) {
|
if (power_user.collapse_newlines) {
|
||||||
combinedPrompt = collapseNewlines(combinedPrompt);
|
combinedPrompt = collapseNewlines(combinedPrompt);
|
||||||
}
|
}
|
||||||
|
|
||||||
return combinedPrompt;
|
return combinedPrompt;
|
||||||
|
};
|
||||||
|
|
||||||
|
let data = {
|
||||||
|
api: main_api,
|
||||||
|
combinedPrompt: null,
|
||||||
|
description,
|
||||||
|
personality,
|
||||||
|
persona,
|
||||||
|
scenario,
|
||||||
|
char: name2,
|
||||||
|
user: name1,
|
||||||
|
beforeScenarioAnchor,
|
||||||
|
afterScenarioAnchor,
|
||||||
|
mesExmString,
|
||||||
|
finalMesSend,
|
||||||
|
generatedPromptCache,
|
||||||
|
main: system,
|
||||||
|
jailbreak,
|
||||||
|
naiPreamble: nai_settings.preamble,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Before returning the combined prompt, give available context related information to all subscribers.
|
||||||
|
eventSource.emitAndWait(event_types.GENERATE_BEFORE_COMBINE_PROMPTS, data);
|
||||||
|
|
||||||
|
// If one or multiple subscribers return a value, forfeit the responsibillity of flattening the context.
|
||||||
|
return !data.combinedPrompt ? combine() : data.combinedPrompt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the negative prompt first since it has the unmodified mesSend array
|
// Get the negative prompt first since it has the unmodified mesSend array
|
||||||
@ -7854,7 +7906,7 @@ jQuery(async function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
registerSlashCommand('dupe', DupeChar, [], '– duplicates the currently selected character', true, true);
|
registerSlashCommand('dupe', DupeChar, [], '– duplicates the currently selected character', true, true);
|
||||||
registerSlashCommand('api', connectAPISlash, [], `<span class="monospace">(${Object.keys(CONNECT_API_MAP)})</span> – connect to an API`, true, true);
|
registerSlashCommand('api', connectAPISlash, [], `<span class="monospace">(${Object.keys(CONNECT_API_MAP).join(', ')})</span> – connect to an API`, true, true);
|
||||||
registerSlashCommand('impersonate', doImpersonate, ['imp'], '– calls an impersonation response', true, true);
|
registerSlashCommand('impersonate', doImpersonate, ['imp'], '– calls an impersonation response', true, true);
|
||||||
registerSlashCommand('delchat', doDeleteChat, [], '– deletes the current chat', true, true);
|
registerSlashCommand('delchat', doDeleteChat, [], '– deletes the current chat', true, true);
|
||||||
registerSlashCommand('closechat', doCloseChat, [], '– closes the current chat', true, true);
|
registerSlashCommand('closechat', doCloseChat, [], '– closes the current chat', true, true);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
// Move chat functions here from script.js (eventually)
|
// Move chat functions here from script.js (eventually)
|
||||||
|
|
||||||
|
import css from '../lib/css-parser.mjs';
|
||||||
import {
|
import {
|
||||||
addCopyToCodeBlocks,
|
addCopyToCodeBlocks,
|
||||||
appendMediaToMessage,
|
appendMediaToMessage,
|
||||||
@ -360,6 +361,61 @@ export async function appendFileContent(message, messageText) {
|
|||||||
return messageText;
|
return messageText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces style tags in the message text with custom tags with encoded content.
|
||||||
|
* @param {string} text
|
||||||
|
* @returns {string} Encoded message text
|
||||||
|
* @copyright https://github.com/kwaroran/risuAI
|
||||||
|
*/
|
||||||
|
export function encodeStyleTags(text) {
|
||||||
|
const styleRegex = /<style>(.+?)<\/style>/gms;
|
||||||
|
return text.replaceAll(styleRegex, (_, match) => {
|
||||||
|
return `<custom-style>${escape(match)}</custom-style>`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sanitizes custom style tags in the message text to prevent DOM pollution.
|
||||||
|
* @param {string} text Message text
|
||||||
|
* @returns {string} Sanitized message text
|
||||||
|
* @copyright https://github.com/kwaroran/risuAI
|
||||||
|
*/
|
||||||
|
export function decodeStyleTags(text) {
|
||||||
|
const styleDecodeRegex = /<custom-style>(.+?)<\/custom-style>/gms;
|
||||||
|
|
||||||
|
return text.replaceAll(styleDecodeRegex, (_, style) => {
|
||||||
|
try {
|
||||||
|
const ast = css.parse(unescape(style));
|
||||||
|
const rules = ast?.stylesheet?.rules;
|
||||||
|
if (rules) {
|
||||||
|
for (const rule of rules) {
|
||||||
|
|
||||||
|
if (rule.type === 'rule') {
|
||||||
|
if (rule.selectors) {
|
||||||
|
for (let i = 0; i < rule.selectors.length; i++) {
|
||||||
|
let selector = rule.selectors[i];
|
||||||
|
if (selector) {
|
||||||
|
let selectors = (selector.split(' ') ?? []).map((v) => {
|
||||||
|
if (v.startsWith('.')) {
|
||||||
|
return '.custom-' + v.substring(1);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}).join(' ');
|
||||||
|
|
||||||
|
rule.selectors[i] = '.mes_text ' + selectors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return `<style>${css.stringify(ast)}</style>`;
|
||||||
|
} catch (error) {
|
||||||
|
return `CSS ERROR: ${error}`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
jQuery(function () {
|
jQuery(function () {
|
||||||
$(document).on('click', '.mes_hide', async function () {
|
$(document).on('click', '.mes_hide', async function () {
|
||||||
const messageBlock = $(this).closest('.mes');
|
const messageBlock = $(this).closest('.mes');
|
||||||
|
@ -4,6 +4,7 @@ import { callPopup, getRequestHeaders, saveSettingsDebounced, substituteParams }
|
|||||||
import { getMessageTimeStamp } from '../../RossAscends-mods.js';
|
import { getMessageTimeStamp } from '../../RossAscends-mods.js';
|
||||||
import { SECRET_KEYS, secret_state } from '../../secrets.js';
|
import { SECRET_KEYS, secret_state } from '../../secrets.js';
|
||||||
import { getMultimodalCaption } from '../shared.js';
|
import { getMultimodalCaption } from '../shared.js';
|
||||||
|
import { textgen_types, textgenerationwebui_settings } from '../../textgen-settings.js';
|
||||||
export { MODULE_NAME };
|
export { MODULE_NAME };
|
||||||
|
|
||||||
const MODULE_NAME = 'caption';
|
const MODULE_NAME = 'caption';
|
||||||
@ -134,7 +135,7 @@ async function doCaptionRequest(base64Img, fileData) {
|
|||||||
case 'horde':
|
case 'horde':
|
||||||
return await captionHorde(base64Img);
|
return await captionHorde(base64Img);
|
||||||
case 'multimodal':
|
case 'multimodal':
|
||||||
return await captionMultimodal(extension_settings.caption.multimodal_api === 'google' ? base64Img : fileData);
|
return await captionMultimodal(fileData);
|
||||||
default:
|
default:
|
||||||
throw new Error('Unknown caption source.');
|
throw new Error('Unknown caption source.');
|
||||||
}
|
}
|
||||||
@ -271,9 +272,11 @@ jQuery(function () {
|
|||||||
$(sendButton).on('click', () => {
|
$(sendButton).on('click', () => {
|
||||||
const hasCaptionModule =
|
const hasCaptionModule =
|
||||||
(modules.includes('caption') && extension_settings.caption.source === 'extras') ||
|
(modules.includes('caption') && extension_settings.caption.source === 'extras') ||
|
||||||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'openai' && secret_state[SECRET_KEYS.OPENAI]) ||
|
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'openai' && (secret_state[SECRET_KEYS.OPENAI] || extension_settings.caption.allow_reverse_proxy)) ||
|
||||||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'openrouter' && secret_state[SECRET_KEYS.OPENROUTER]) ||
|
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'openrouter' && secret_state[SECRET_KEYS.OPENROUTER]) ||
|
||||||
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'google' && secret_state[SECRET_KEYS.MAKERSUITE]) ||
|
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'google' && secret_state[SECRET_KEYS.MAKERSUITE]) ||
|
||||||
|
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'ollama' && textgenerationwebui_settings.server_urls[textgen_types.OLLAMA]) ||
|
||||||
|
(extension_settings.caption.source === 'multimodal' && extension_settings.caption.multimodal_api === 'llamacpp' && textgenerationwebui_settings.server_urls[textgen_types.LLAMACPP]) ||
|
||||||
extension_settings.caption.source === 'local' ||
|
extension_settings.caption.source === 'local' ||
|
||||||
extension_settings.caption.source === 'horde';
|
extension_settings.caption.source === 'horde';
|
||||||
|
|
||||||
@ -329,7 +332,7 @@ jQuery(function () {
|
|||||||
<label for="caption_source">Source</label>
|
<label for="caption_source">Source</label>
|
||||||
<select id="caption_source" class="text_pole">
|
<select id="caption_source" class="text_pole">
|
||||||
<option value="local">Local</option>
|
<option value="local">Local</option>
|
||||||
<option value="multimodal">Multimodal (OpenAI / OpenRouter / Google)</option>
|
<option value="multimodal">Multimodal (OpenAI / llama / Google)</option>
|
||||||
<option value="extras">Extras</option>
|
<option value="extras">Extras</option>
|
||||||
<option value="horde">Horde</option>
|
<option value="horde">Horde</option>
|
||||||
</select>
|
</select>
|
||||||
@ -337,9 +340,11 @@ jQuery(function () {
|
|||||||
<div class="flex1 flex-container flexFlowColumn flexNoGap">
|
<div class="flex1 flex-container flexFlowColumn flexNoGap">
|
||||||
<label for="caption_multimodal_api">API</label>
|
<label for="caption_multimodal_api">API</label>
|
||||||
<select id="caption_multimodal_api" class="flex1 text_pole">
|
<select id="caption_multimodal_api" class="flex1 text_pole">
|
||||||
|
<option value="llamacpp">llama.cpp</option>
|
||||||
|
<option value="ollama">Ollama</option>
|
||||||
<option value="openai">OpenAI</option>
|
<option value="openai">OpenAI</option>
|
||||||
<option value="openrouter">OpenRouter</option>
|
<option value="openrouter">OpenRouter</option>
|
||||||
<option value="google">Google</option>
|
<option value="google">Google MakerSuite</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex1 flex-container flexFlowColumn flexNoGap">
|
<div class="flex1 flex-container flexFlowColumn flexNoGap">
|
||||||
@ -349,12 +354,19 @@ jQuery(function () {
|
|||||||
<option data-type="google" value="gemini-pro-vision">gemini-pro-vision</option>
|
<option data-type="google" value="gemini-pro-vision">gemini-pro-vision</option>
|
||||||
<option data-type="openrouter" value="openai/gpt-4-vision-preview">openai/gpt-4-vision-preview</option>
|
<option data-type="openrouter" value="openai/gpt-4-vision-preview">openai/gpt-4-vision-preview</option>
|
||||||
<option data-type="openrouter" value="haotian-liu/llava-13b">haotian-liu/llava-13b</option>
|
<option data-type="openrouter" value="haotian-liu/llava-13b">haotian-liu/llava-13b</option>
|
||||||
|
<option data-type="ollama" value="ollama_current">[Currently selected]</option>
|
||||||
|
<option data-type="ollama" value="bakllava:latest">bakllava:latest</option>
|
||||||
|
<option data-type="ollama" value="llava:latest">llava:latest</option>
|
||||||
|
<option data-type="llamacpp" value="llamacpp_current">[Currently loaded]</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<label data-type="openai" class="checkbox_label flexBasis100p" for="caption_allow_reverse_proxy" title="Allow using reverse proxy if defined and valid.">
|
<label data-type="openai" class="checkbox_label flexBasis100p" for="caption_allow_reverse_proxy" title="Allow using reverse proxy if defined and valid.">
|
||||||
<input id="caption_allow_reverse_proxy" type="checkbox" class="checkbox">
|
<input id="caption_allow_reverse_proxy" type="checkbox" class="checkbox">
|
||||||
Allow reverse proxy
|
Allow reverse proxy
|
||||||
</label>
|
</label>
|
||||||
|
<div class="flexBasis100p m-b-1">
|
||||||
|
<small><b>Hint:</b> Set your API keys and endpoints in the 'API Connections' tab first.</small>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="caption_prompt_block">
|
<div id="caption_prompt_block">
|
||||||
<label for="caption_prompt">Caption Prompt</label>
|
<label for="caption_prompt">Caption Prompt</label>
|
||||||
|
@ -5,6 +5,7 @@ import { is_group_generating, selected_group } from '../../group-chats.js';
|
|||||||
import { registerSlashCommand } from '../../slash-commands.js';
|
import { registerSlashCommand } from '../../slash-commands.js';
|
||||||
import { loadMovingUIState } from '../../power-user.js';
|
import { loadMovingUIState } from '../../power-user.js';
|
||||||
import { dragElement } from '../../RossAscends-mods.js';
|
import { dragElement } from '../../RossAscends-mods.js';
|
||||||
|
import { getTextTokens, tokenizers } from '../../tokenizers.js';
|
||||||
export { MODULE_NAME };
|
export { MODULE_NAME };
|
||||||
|
|
||||||
const MODULE_NAME = '1_memory';
|
const MODULE_NAME = '1_memory';
|
||||||
@ -42,26 +43,6 @@ const defaultPrompt = '[Pause your roleplay. Summarize the most important facts
|
|||||||
const defaultTemplate = '[Summary: {{summary}}]';
|
const defaultTemplate = '[Summary: {{summary}}]';
|
||||||
|
|
||||||
const defaultSettings = {
|
const defaultSettings = {
|
||||||
minLongMemory: 16,
|
|
||||||
maxLongMemory: 1024,
|
|
||||||
longMemoryLength: 128,
|
|
||||||
shortMemoryLength: 512,
|
|
||||||
minShortMemory: 128,
|
|
||||||
maxShortMemory: 1024,
|
|
||||||
shortMemoryStep: 16,
|
|
||||||
longMemoryStep: 8,
|
|
||||||
repetitionPenaltyStep: 0.05,
|
|
||||||
repetitionPenalty: 1.2,
|
|
||||||
maxRepetitionPenalty: 2.0,
|
|
||||||
minRepetitionPenalty: 1.0,
|
|
||||||
temperature: 1.0,
|
|
||||||
minTemperature: 0.1,
|
|
||||||
maxTemperature: 2.0,
|
|
||||||
temperatureStep: 0.05,
|
|
||||||
lengthPenalty: 1,
|
|
||||||
minLengthPenalty: -4,
|
|
||||||
maxLengthPenalty: 4,
|
|
||||||
lengthPenaltyStep: 0.1,
|
|
||||||
memoryFrozen: false,
|
memoryFrozen: false,
|
||||||
SkipWIAN: false,
|
SkipWIAN: false,
|
||||||
source: summary_sources.extras,
|
source: summary_sources.extras,
|
||||||
@ -95,11 +76,6 @@ function loadSettings() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$('#summary_source').val(extension_settings.memory.source).trigger('change');
|
$('#summary_source').val(extension_settings.memory.source).trigger('change');
|
||||||
$('#memory_long_length').val(extension_settings.memory.longMemoryLength).trigger('input');
|
|
||||||
$('#memory_short_length').val(extension_settings.memory.shortMemoryLength).trigger('input');
|
|
||||||
$('#memory_repetition_penalty').val(extension_settings.memory.repetitionPenalty).trigger('input');
|
|
||||||
$('#memory_temperature').val(extension_settings.memory.temperature).trigger('input');
|
|
||||||
$('#memory_length_penalty').val(extension_settings.memory.lengthPenalty).trigger('input');
|
|
||||||
$('#memory_frozen').prop('checked', extension_settings.memory.memoryFrozen).trigger('input');
|
$('#memory_frozen').prop('checked', extension_settings.memory.memoryFrozen).trigger('input');
|
||||||
$('#memory_skipWIAN').prop('checked', extension_settings.memory.SkipWIAN).trigger('input');
|
$('#memory_skipWIAN').prop('checked', extension_settings.memory.SkipWIAN).trigger('input');
|
||||||
$('#memory_prompt').val(extension_settings.memory.prompt).trigger('input');
|
$('#memory_prompt').val(extension_settings.memory.prompt).trigger('input');
|
||||||
@ -126,51 +102,6 @@ function switchSourceControls(value) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMemoryShortInput() {
|
|
||||||
const value = $(this).val();
|
|
||||||
extension_settings.memory.shortMemoryLength = Number(value);
|
|
||||||
$('#memory_short_length_tokens').text(value);
|
|
||||||
saveSettingsDebounced();
|
|
||||||
|
|
||||||
// Don't let long buffer be bigger than short
|
|
||||||
if (extension_settings.memory.longMemoryLength > extension_settings.memory.shortMemoryLength) {
|
|
||||||
$('#memory_long_length').val(extension_settings.memory.shortMemoryLength).trigger('input');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMemoryLongInput() {
|
|
||||||
const value = $(this).val();
|
|
||||||
extension_settings.memory.longMemoryLength = Number(value);
|
|
||||||
$('#memory_long_length_tokens').text(value);
|
|
||||||
saveSettingsDebounced();
|
|
||||||
|
|
||||||
// Don't let long buffer be bigger than short
|
|
||||||
if (extension_settings.memory.longMemoryLength > extension_settings.memory.shortMemoryLength) {
|
|
||||||
$('#memory_short_length').val(extension_settings.memory.longMemoryLength).trigger('input');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMemoryRepetitionPenaltyInput() {
|
|
||||||
const value = $(this).val();
|
|
||||||
extension_settings.memory.repetitionPenalty = Number(value);
|
|
||||||
$('#memory_repetition_penalty_value').text(extension_settings.memory.repetitionPenalty.toFixed(2));
|
|
||||||
saveSettingsDebounced();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMemoryTemperatureInput() {
|
|
||||||
const value = $(this).val();
|
|
||||||
extension_settings.memory.temperature = Number(value);
|
|
||||||
$('#memory_temperature_value').text(extension_settings.memory.temperature.toFixed(2));
|
|
||||||
saveSettingsDebounced();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMemoryLengthPenaltyInput() {
|
|
||||||
const value = $(this).val();
|
|
||||||
extension_settings.memory.lengthPenalty = Number(value);
|
|
||||||
$('#memory_length_penalty_value').text(extension_settings.memory.lengthPenalty.toFixed(2));
|
|
||||||
saveSettingsDebounced();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onMemoryFrozenInput() {
|
function onMemoryFrozenInput() {
|
||||||
const value = Boolean($(this).prop('checked'));
|
const value = Boolean($(this).prop('checked'));
|
||||||
extension_settings.memory.memoryFrozen = value;
|
extension_settings.memory.memoryFrozen = value;
|
||||||
@ -444,33 +375,36 @@ async function summarizeChatExtras(context) {
|
|||||||
const longMemory = getLatestMemoryFromChat(chat);
|
const longMemory = getLatestMemoryFromChat(chat);
|
||||||
const reversedChat = chat.slice().reverse();
|
const reversedChat = chat.slice().reverse();
|
||||||
reversedChat.shift();
|
reversedChat.shift();
|
||||||
let memoryBuffer = [];
|
const memoryBuffer = [];
|
||||||
|
const CONTEXT_SIZE = 1024 - 64;
|
||||||
|
|
||||||
for (let mes of reversedChat) {
|
for (const message of reversedChat) {
|
||||||
// we reached the point of latest memory
|
// we reached the point of latest memory
|
||||||
if (longMemory && mes.extra && mes.extra.memory == longMemory) {
|
if (longMemory && message.extra && message.extra.memory == longMemory) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't care about system
|
// don't care about system
|
||||||
if (mes.is_system) {
|
if (message.is_system) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine the sender's name
|
// determine the sender's name
|
||||||
const name = mes.is_user ? (context.name1 ?? 'You') : (mes.force_avatar ? mes.name : context.name2);
|
const entry = `${message.name}:\n${message.mes}`;
|
||||||
const entry = `${name}:\n${mes['mes']}`;
|
|
||||||
memoryBuffer.push(entry);
|
memoryBuffer.push(entry);
|
||||||
|
|
||||||
// check if token limit was reached
|
// check if token limit was reached
|
||||||
if (context.getTokenCount(getMemoryString()) >= extension_settings.memory.shortMemoryLength) {
|
const tokens = getTextTokens(tokenizers.GPT2, getMemoryString()).length;
|
||||||
|
if (tokens >= CONTEXT_SIZE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const resultingString = getMemoryString();
|
const resultingString = getMemoryString();
|
||||||
|
const resultingTokens = getTextTokens(tokenizers.GPT2, resultingString).length;
|
||||||
|
|
||||||
if (context.getTokenCount(resultingString) < extension_settings.memory.shortMemoryLength) {
|
if (!resultingString || resultingTokens < CONTEXT_SIZE) {
|
||||||
|
console.debug('Not enough context to summarize');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -488,13 +422,7 @@ async function summarizeChatExtras(context) {
|
|||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
text: resultingString,
|
text: resultingString,
|
||||||
params: {
|
params: {},
|
||||||
min_length: extension_settings.memory.longMemoryLength * 0, // testing how it behaves 0 min length
|
|
||||||
max_length: extension_settings.memory.longMemoryLength,
|
|
||||||
repetition_penalty: extension_settings.memory.repetitionPenalty,
|
|
||||||
temperature: extension_settings.memory.temperature,
|
|
||||||
length_penalty: extension_settings.memory.lengthPenalty,
|
|
||||||
},
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -623,11 +551,6 @@ function setupListeners() {
|
|||||||
//setup shared listeners for popout and regular ext menu
|
//setup shared listeners for popout and regular ext menu
|
||||||
$('#memory_restore').off('click').on('click', onMemoryRestoreClick);
|
$('#memory_restore').off('click').on('click', onMemoryRestoreClick);
|
||||||
$('#memory_contents').off('click').on('input', onMemoryContentInput);
|
$('#memory_contents').off('click').on('input', onMemoryContentInput);
|
||||||
$('#memory_long_length').off('click').on('input', onMemoryLongInput);
|
|
||||||
$('#memory_short_length').off('click').on('input', onMemoryShortInput);
|
|
||||||
$('#memory_repetition_penalty').off('click').on('input', onMemoryRepetitionPenaltyInput);
|
|
||||||
$('#memory_temperature').off('click').on('input', onMemoryTemperatureInput);
|
|
||||||
$('#memory_length_penalty').off('click').on('input', onMemoryLengthPenaltyInput);
|
|
||||||
$('#memory_frozen').off('click').on('input', onMemoryFrozenInput);
|
$('#memory_frozen').off('click').on('input', onMemoryFrozenInput);
|
||||||
$('#memory_skipWIAN').off('click').on('input', onMemorySkipWIANInput);
|
$('#memory_skipWIAN').off('click').on('input', onMemorySkipWIANInput);
|
||||||
$('#summary_source').off('click').on('change', onSummarySourceChange);
|
$('#summary_source').off('click').on('change', onSummarySourceChange);
|
||||||
@ -720,18 +643,6 @@ jQuery(function () {
|
|||||||
<input id="memory_prompt_words_force" type="range" value="${defaultSettings.promptForceWords}" min="${defaultSettings.promptMinForceWords}" max="${defaultSettings.promptMaxForceWords}" step="${defaultSettings.promptForceWordsStep}" />
|
<input id="memory_prompt_words_force" type="range" value="${defaultSettings.promptForceWords}" min="${defaultSettings.promptMinForceWords}" max="${defaultSettings.promptMaxForceWords}" step="${defaultSettings.promptForceWordsStep}" />
|
||||||
<small>If both sliders are non-zero, then both will trigger summary updates a their respective intervals.</small>
|
<small>If both sliders are non-zero, then both will trigger summary updates a their respective intervals.</small>
|
||||||
</div>
|
</div>
|
||||||
<div data-source="extras">
|
|
||||||
<label for="memory_short_length">Chat to Summarize buffer length (<span id="memory_short_length_tokens"></span> tokens)</label>
|
|
||||||
<input id="memory_short_length" type="range" value="${defaultSettings.shortMemoryLength}" min="${defaultSettings.minShortMemory}" max="${defaultSettings.maxShortMemory}" step="${defaultSettings.shortMemoryStep}" />
|
|
||||||
<label for="memory_long_length">Summary output length (<span id="memory_long_length_tokens"></span> tokens)</label>
|
|
||||||
<input id="memory_long_length" type="range" value="${defaultSettings.longMemoryLength}" min="${defaultSettings.minLongMemory}" max="${defaultSettings.maxLongMemory}" step="${defaultSettings.longMemoryStep}" />
|
|
||||||
<label for="memory_temperature">Temperature (<span id="memory_temperature_value"></span>)</label>
|
|
||||||
<input id="memory_temperature" type="range" value="${defaultSettings.temperature}" min="${defaultSettings.minTemperature}" max="${defaultSettings.maxTemperature}" step="${defaultSettings.temperatureStep}" />
|
|
||||||
<label for="memory_repetition_penalty">Repetition penalty (<span id="memory_repetition_penalty_value"></span>)</label>
|
|
||||||
<input id="memory_repetition_penalty" type="range" value="${defaultSettings.repetitionPenalty}" min="${defaultSettings.minRepetitionPenalty}" max="${defaultSettings.maxRepetitionPenalty}" step="${defaultSettings.repetitionPenaltyStep}" />
|
|
||||||
<label for="memory_length_penalty">Length preference <small>[higher = longer summaries]</small> (<span id="memory_length_penalty_value"></span>)</label>
|
|
||||||
<input id="memory_length_penalty" type="range" value="${defaultSettings.lengthPenalty}" min="${defaultSettings.minLengthPenalty}" max="${defaultSettings.maxLengthPenalty}" step="${defaultSettings.lengthPenaltyStep}" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,6 +2,7 @@ import { getRequestHeaders } from '../../script.js';
|
|||||||
import { extension_settings } from '../extensions.js';
|
import { extension_settings } from '../extensions.js';
|
||||||
import { oai_settings } from '../openai.js';
|
import { oai_settings } from '../openai.js';
|
||||||
import { SECRET_KEYS, secret_state } from '../secrets.js';
|
import { SECRET_KEYS, secret_state } from '../secrets.js';
|
||||||
|
import { textgen_types, textgenerationwebui_settings } from '../textgen-settings.js';
|
||||||
import { createThumbnail, isValidUrl } from '../utils.js';
|
import { createThumbnail, isValidUrl } from '../utils.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11,20 +12,18 @@ import { createThumbnail, isValidUrl } from '../utils.js';
|
|||||||
* @returns {Promise<string>} Generated caption
|
* @returns {Promise<string>} Generated caption
|
||||||
*/
|
*/
|
||||||
export async function getMultimodalCaption(base64Img, prompt) {
|
export async function getMultimodalCaption(base64Img, prompt) {
|
||||||
if (extension_settings.caption.multimodal_api === 'openai' && !secret_state[SECRET_KEYS.OPENAI]) {
|
throwIfInvalidModel();
|
||||||
throw new Error('OpenAI API key is not set.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extension_settings.caption.multimodal_api === 'openrouter' && !secret_state[SECRET_KEYS.OPENROUTER]) {
|
const noPrefix = ['google', 'ollama', 'llamacpp'].includes(extension_settings.caption.multimodal_api);
|
||||||
throw new Error('OpenRouter API key is not set.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extension_settings.caption.multimodal_api === 'google' && !secret_state[SECRET_KEYS.MAKERSUITE]) {
|
if (noPrefix && base64Img.startsWith('data:image/')) {
|
||||||
throw new Error('MakerSuite API key is not set.');
|
base64Img = base64Img.split(',')[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenRouter has a payload limit of ~2MB. Google is 4MB, but we love democracy.
|
// OpenRouter has a payload limit of ~2MB. Google is 4MB, but we love democracy.
|
||||||
const isGoogle = extension_settings.caption.multimodal_api === 'google';
|
const isGoogle = extension_settings.caption.multimodal_api === 'google';
|
||||||
|
const isOllama = extension_settings.caption.multimodal_api === 'ollama';
|
||||||
|
const isLlamaCpp = extension_settings.caption.multimodal_api === 'llamacpp';
|
||||||
const base64Bytes = base64Img.length * 0.75;
|
const base64Bytes = base64Img.length * 0.75;
|
||||||
const compressionLimit = 2 * 1024 * 1024;
|
const compressionLimit = 2 * 1024 * 1024;
|
||||||
if (['google', 'openrouter'].includes(extension_settings.caption.multimodal_api) && base64Bytes > compressionLimit) {
|
if (['google', 'openrouter'].includes(extension_settings.caption.multimodal_api) && base64Bytes > compressionLimit) {
|
||||||
@ -45,27 +44,79 @@ export async function getMultimodalCaption(base64Img, prompt) {
|
|||||||
const proxyUrl = useReverseProxy ? oai_settings.reverse_proxy : '';
|
const proxyUrl = useReverseProxy ? oai_settings.reverse_proxy : '';
|
||||||
const proxyPassword = useReverseProxy ? oai_settings.proxy_password : '';
|
const proxyPassword = useReverseProxy ? oai_settings.proxy_password : '';
|
||||||
|
|
||||||
const apiResult = await fetch(`/api/${isGoogle ? 'google' : 'openai'}/caption-image`, {
|
const requestBody = {
|
||||||
|
image: base64Img,
|
||||||
|
prompt: prompt,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!isGoogle) {
|
||||||
|
requestBody.api = extension_settings.caption.multimodal_api || 'openai';
|
||||||
|
requestBody.model = extension_settings.caption.multimodal_model || 'gpt-4-vision-preview';
|
||||||
|
requestBody.reverse_proxy = proxyUrl;
|
||||||
|
requestBody.proxy_password = proxyPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isOllama) {
|
||||||
|
if (extension_settings.caption.multimodal_model === 'ollama_current') {
|
||||||
|
requestBody.model = textgenerationwebui_settings.ollama_model;
|
||||||
|
}
|
||||||
|
|
||||||
|
requestBody.server_url = textgenerationwebui_settings.server_urls[textgen_types.OLLAMA];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLlamaCpp) {
|
||||||
|
requestBody.server_url = textgenerationwebui_settings.server_urls[textgen_types.LLAMACPP];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEndpointUrl() {
|
||||||
|
switch (extension_settings.caption.multimodal_api) {
|
||||||
|
case 'google':
|
||||||
|
return '/api/google/caption-image';
|
||||||
|
case 'llamacpp':
|
||||||
|
return '/api/backends/text-completions/llamacpp/caption-image';
|
||||||
|
case 'ollama':
|
||||||
|
return '/api/backends/text-completions/ollama/caption-image';
|
||||||
|
default:
|
||||||
|
return '/api/openai/caption-image';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiResult = await fetch(getEndpointUrl(), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getRequestHeaders(),
|
headers: getRequestHeaders(),
|
||||||
body: JSON.stringify({
|
body: JSON.stringify(requestBody),
|
||||||
image: base64Img,
|
|
||||||
prompt: prompt,
|
|
||||||
...(isGoogle
|
|
||||||
? {}
|
|
||||||
: {
|
|
||||||
api: extension_settings.caption.multimodal_api || 'openai',
|
|
||||||
model: extension_settings.caption.multimodal_model || 'gpt-4-vision-preview',
|
|
||||||
reverse_proxy: proxyUrl,
|
|
||||||
proxy_password: proxyPassword,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!apiResult.ok) {
|
if (!apiResult.ok) {
|
||||||
throw new Error('Failed to caption image via OpenAI.');
|
throw new Error('Failed to caption image via Multimodal API.');
|
||||||
}
|
}
|
||||||
|
|
||||||
const { caption } = await apiResult.json();
|
const { caption } = await apiResult.json();
|
||||||
return caption;
|
return String(caption).trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
function throwIfInvalidModel() {
|
||||||
|
if (extension_settings.caption.multimodal_api === 'openai' && !secret_state[SECRET_KEYS.OPENAI]) {
|
||||||
|
throw new Error('OpenAI API key is not set.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extension_settings.caption.multimodal_api === 'openrouter' && !secret_state[SECRET_KEYS.OPENROUTER]) {
|
||||||
|
throw new Error('OpenRouter API key is not set.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extension_settings.caption.multimodal_api === 'google' && !secret_state[SECRET_KEYS.MAKERSUITE]) {
|
||||||
|
throw new Error('MakerSuite API key is not set.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extension_settings.caption.multimodal_api === 'ollama' && !textgenerationwebui_settings.server_urls[textgen_types.OLLAMA]) {
|
||||||
|
throw new Error('Ollama server URL is not set.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extension_settings.caption.multimodal_api === 'ollama' && extension_settings.caption.multimodal_model === 'ollama_current' && !textgenerationwebui_settings.ollama_model) {
|
||||||
|
throw new Error('Ollama model is not set.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extension_settings.caption.multimodal_api === 'llamacpp' && !textgenerationwebui_settings.server_urls[textgen_types.LLAMACPP]) {
|
||||||
|
throw new Error('LlamaCPP server URL is not set.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
substituteParams,
|
substituteParams,
|
||||||
} from '../script.js';
|
} from '../script.js';
|
||||||
import { getCfgPrompt } from './cfg-scale.js';
|
import { getCfgPrompt } from './cfg-scale.js';
|
||||||
import { MAX_CONTEXT_DEFAULT, MAX_RESPONSE_DEFAULT } from './power-user.js';
|
import { MAX_CONTEXT_DEFAULT, MAX_RESPONSE_DEFAULT, power_user } from './power-user.js';
|
||||||
import { getTextTokens, tokenizers } from './tokenizers.js';
|
import { getTextTokens, tokenizers } from './tokenizers.js';
|
||||||
import EventSourceStream from './sse-stream.js';
|
import EventSourceStream from './sse-stream.js';
|
||||||
import {
|
import {
|
||||||
@ -437,6 +437,10 @@ export function getNovelGenerationData(finalPrompt, settings, maxLength, isImper
|
|||||||
BIAS_CACHE.set(BIAS_KEY, logitBias);
|
BIAS_CACHE.set(BIAS_KEY, logitBias);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (power_user.console_log_prompts) {
|
||||||
|
console.log(finalPrompt);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'input': finalPrompt,
|
'input': finalPrompt,
|
||||||
'model': nai_settings.model_novel,
|
'model': nai_settings.model_novel,
|
||||||
|
@ -304,7 +304,12 @@ class PresetManager {
|
|||||||
'streaming_kobold',
|
'streaming_kobold',
|
||||||
'enabled',
|
'enabled',
|
||||||
'seed',
|
'seed',
|
||||||
|
'legacy_api',
|
||||||
'mancer_model',
|
'mancer_model',
|
||||||
|
'togetherai_model',
|
||||||
|
'ollama_model',
|
||||||
|
'server_urls',
|
||||||
|
'type',
|
||||||
];
|
];
|
||||||
const settings = Object.assign({}, getSettingsByApiId(this.apiId));
|
const settings = Object.assign({}, getSettingsByApiId(this.apiId));
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<h3>Confused or lost?</h3>
|
<h3>Confused or lost?</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<span class="note-link-span">?</span> - click these icons!
|
<span class="note-link-span"><a class="fa-solid fa-circle-question" target="_blank" href="https://docs.sillytavern.app/"></a></span> - click these icons!
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Enter <code>/?</code> in the chat bar
|
Enter <code>/?</code> in the chat bar
|
||||||
|
@ -310,11 +310,12 @@ ollama.post('/download', jsonParser, async function (request, response) {
|
|||||||
|
|
||||||
const fetchResponse = await fetch(`${url}/api/pull`, {
|
const fetchResponse = await fetch(`${url}/api/pull`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
name: name,
|
name: name,
|
||||||
stream: false,
|
stream: false,
|
||||||
}),
|
}),
|
||||||
headers: { 'Content-Type': 'application/json' },
|
timeout: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!fetchResponse.ok) {
|
if (!fetchResponse.ok) {
|
||||||
@ -329,6 +330,99 @@ ollama.post('/download', jsonParser, async function (request, response) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ollama.post('/caption-image', jsonParser, async function (request, response) {
|
||||||
|
try {
|
||||||
|
if (!request.body.server_url || !request.body.model) {
|
||||||
|
return response.sendStatus(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Ollama caption request:', request.body);
|
||||||
|
// Convert to string + remove trailing slash + /v1 suffix
|
||||||
|
const baseUrl = String(request.body.server_url).replace(/\/$/, '').replace(/\/v1$/, '');
|
||||||
|
|
||||||
|
const fetchResponse = await fetch(`${baseUrl}/api/generate`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
model: request.body.model,
|
||||||
|
prompt: request.body.prompt,
|
||||||
|
images: [request.body.image],
|
||||||
|
stream: false,
|
||||||
|
}),
|
||||||
|
timeout: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!fetchResponse.ok) {
|
||||||
|
console.log('Ollama caption error:', fetchResponse.status, fetchResponse.statusText);
|
||||||
|
return response.status(500).send({ error: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await fetchResponse.json();
|
||||||
|
console.log('Ollama caption response:', data);
|
||||||
|
|
||||||
|
const caption = data?.response || '';
|
||||||
|
|
||||||
|
if (!caption) {
|
||||||
|
console.log('Ollama caption is empty.');
|
||||||
|
return response.status(500).send({ error: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.send({ caption });
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return response.status(500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const llamacpp = express.Router();
|
||||||
|
|
||||||
|
llamacpp.post('/caption-image', jsonParser, async function (request, response) {
|
||||||
|
try {
|
||||||
|
if (!request.body.server_url) {
|
||||||
|
return response.sendStatus(400);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('LlamaCpp caption request:', request.body);
|
||||||
|
// Convert to string + remove trailing slash + /v1 suffix
|
||||||
|
const baseUrl = String(request.body.server_url).replace(/\/$/, '').replace(/\/v1$/, '');
|
||||||
|
|
||||||
|
const fetchResponse = await fetch(`${baseUrl}/completion`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
timeout: 0,
|
||||||
|
body: JSON.stringify({
|
||||||
|
prompt: `USER:[img-1]${String(request.body.prompt).trim()}\nASSISTANT:`,
|
||||||
|
image_data: [{ data: request.body.image, id: 1 }],
|
||||||
|
temperature: 0.1,
|
||||||
|
stream: false,
|
||||||
|
stop: ['USER:', '</s>'],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!fetchResponse.ok) {
|
||||||
|
console.log('LlamaCpp caption error:', fetchResponse.status, fetchResponse.statusText);
|
||||||
|
return response.status(500).send({ error: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await fetchResponse.json();
|
||||||
|
console.log('LlamaCpp caption response:', data);
|
||||||
|
|
||||||
|
const caption = data?.content || '';
|
||||||
|
|
||||||
|
if (!caption) {
|
||||||
|
console.log('LlamaCpp caption is empty.');
|
||||||
|
return response.status(500).send({ error: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.send({ caption });
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return response.status(500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
router.use('/ollama', ollama);
|
router.use('/ollama', ollama);
|
||||||
|
router.use('/llamacpp', llamacpp);
|
||||||
|
|
||||||
module.exports = { router };
|
module.exports = { router };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user