mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Merge branch 'staging' into 202411-backend-maxctx
This commit is contained in:
@ -627,6 +627,14 @@
|
|||||||
"filename": "presets/instruct/Synthia.json",
|
"filename": "presets/instruct/Synthia.json",
|
||||||
"type": "instruct"
|
"type": "instruct"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"filename": "presets/instruct/Tulu.json",
|
||||||
|
"type": "instruct"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename": "presets/context/Tulu.json",
|
||||||
|
"type": "context"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"filename": "presets/instruct/Vicuna 1.0.json",
|
"filename": "presets/instruct/Vicuna 1.0.json",
|
||||||
"type": "instruct"
|
"type": "instruct"
|
||||||
|
11
default/content/presets/context/Tulu.json
Normal file
11
default/content/presets/context/Tulu.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"story_string": "<|system|>\n{{#if system}}{{system}}\n{{/if}}{{#if wiBefore}}{{wiBefore}}\n{{/if}}{{#if description}}{{description}}\n{{/if}}{{#if personality}}{{char}}'s personality: {{personality}}\n{{/if}}{{#if scenario}}Scenario: {{scenario}}\n{{/if}}{{#if wiAfter}}{{wiAfter}}\n{{/if}}{{#if persona}}{{persona}}\n{{/if}}{{trim}}\n",
|
||||||
|
"example_separator": "",
|
||||||
|
"chat_start": "",
|
||||||
|
"use_stop_strings": false,
|
||||||
|
"allow_jailbreak": false,
|
||||||
|
"always_force_name2": true,
|
||||||
|
"trim_sentences": false,
|
||||||
|
"single_line": false,
|
||||||
|
"name": "Tulu"
|
||||||
|
}
|
22
default/content/presets/instruct/Tulu.json
Normal file
22
default/content/presets/instruct/Tulu.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"input_sequence": "<|user|>\n",
|
||||||
|
"output_sequence": "<|assistant|>\n",
|
||||||
|
"first_output_sequence": "",
|
||||||
|
"last_output_sequence": "",
|
||||||
|
"system_sequence_prefix": "",
|
||||||
|
"system_sequence_suffix": "",
|
||||||
|
"stop_sequence": "<|end_of_text|>",
|
||||||
|
"wrap": false,
|
||||||
|
"macro": true,
|
||||||
|
"names_behavior": "always",
|
||||||
|
"activation_regex": "",
|
||||||
|
"skip_examples": false,
|
||||||
|
"output_suffix": "<|end_of_text|>\n",
|
||||||
|
"input_suffix": "\n",
|
||||||
|
"system_sequence": "<|system|>\n",
|
||||||
|
"system_suffix": "\n",
|
||||||
|
"user_alignment_message": "",
|
||||||
|
"last_system_sequence": "",
|
||||||
|
"system_same_as_user": false,
|
||||||
|
"name": "Tulu"
|
||||||
|
}
|
@ -230,7 +230,6 @@
|
|||||||
"show_external_models": false,
|
"show_external_models": false,
|
||||||
"assistant_prefill": "",
|
"assistant_prefill": "",
|
||||||
"assistant_impersonation": "",
|
"assistant_impersonation": "",
|
||||||
"human_sysprompt_message": "Let's get started. Please generate your response based on the information and instructions provided above.",
|
|
||||||
"claude_use_sysprompt": false,
|
"claude_use_sysprompt": false,
|
||||||
"use_alt_scale": false,
|
"use_alt_scale": false,
|
||||||
"squash_system_messages": false,
|
"squash_system_messages": false,
|
||||||
|
257
package-lock.json
generated
257
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "sillytavern",
|
"name": "sillytavern",
|
||||||
"version": "1.12.7",
|
"version": "1.12.8",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "sillytavern",
|
"name": "sillytavern",
|
||||||
"version": "1.12.7",
|
"version": "1.12.8",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -67,7 +67,6 @@
|
|||||||
"vectra": "^0.2.2",
|
"vectra": "^0.2.2",
|
||||||
"wavefile": "^11.0.0",
|
"wavefile": "^11.0.0",
|
||||||
"webpack": "^5.95.0",
|
"webpack": "^5.95.0",
|
||||||
"webpack-dev-middleware": "^7.4.2",
|
|
||||||
"write-file-atomic": "^5.0.1",
|
"write-file-atomic": "^5.0.1",
|
||||||
"ws": "^8.17.1",
|
"ws": "^8.17.1",
|
||||||
"yaml": "^2.3.4",
|
"yaml": "^2.3.4",
|
||||||
@ -866,60 +865,6 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@jsonjoy.com/base64": {
|
|
||||||
"version": "1.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz",
|
|
||||||
"integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/streamich"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"tslib": "2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@jsonjoy.com/json-pack": {
|
|
||||||
"version": "1.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.1.0.tgz",
|
|
||||||
"integrity": "sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"@jsonjoy.com/base64": "^1.1.1",
|
|
||||||
"@jsonjoy.com/util": "^1.1.2",
|
|
||||||
"hyperdyperid": "^1.2.0",
|
|
||||||
"thingies": "^1.20.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/streamich"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"tslib": "2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@jsonjoy.com/util": {
|
|
||||||
"version": "1.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.5.0.tgz",
|
|
||||||
"integrity": "sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/streamich"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"tslib": "2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@kwsites/file-exists": {
|
"node_modules/@kwsites/file-exists": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz",
|
||||||
@ -1803,45 +1748,6 @@
|
|||||||
"url": "https://github.com/sponsors/epoberezkin"
|
"url": "https://github.com/sponsors/epoberezkin"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ajv-formats": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
|
|
||||||
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"ajv": "^8.0.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"ajv": "^8.0.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"ajv": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ajv-formats/node_modules/ajv": {
|
|
||||||
"version": "8.17.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
|
||||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"fast-deep-equal": "^3.1.3",
|
|
||||||
"fast-uri": "^3.0.1",
|
|
||||||
"json-schema-traverse": "^1.0.0",
|
|
||||||
"require-from-string": "^2.0.2"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/epoberezkin"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ajv-formats/node_modules/json-schema-traverse": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/ajv-keywords": {
|
"node_modules/ajv-keywords": {
|
||||||
"version": "3.5.2",
|
"version": "3.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
|
||||||
@ -2602,12 +2508,6 @@
|
|||||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/colorette": {
|
|
||||||
"version": "2.0.20",
|
|
||||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
|
|
||||||
"integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/combined-stream": {
|
"node_modules/combined-stream": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
@ -3785,12 +3685,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/fast-uri": {
|
|
||||||
"version": "3.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz",
|
|
||||||
"integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==",
|
|
||||||
"license": "BSD-3-Clause"
|
|
||||||
},
|
|
||||||
"node_modules/fastq": {
|
"node_modules/fastq": {
|
||||||
"version": "1.15.0",
|
"version": "1.15.0",
|
||||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
|
||||||
@ -4541,15 +4435,6 @@
|
|||||||
"ms": "^2.0.0"
|
"ms": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/hyperdyperid": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.18"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/iconv-lite": {
|
"node_modules/iconv-lite": {
|
||||||
"version": "0.6.3",
|
"version": "0.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||||
@ -5176,25 +5061,6 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/memfs": {
|
|
||||||
"version": "4.14.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/memfs/-/memfs-4.14.0.tgz",
|
|
||||||
"integrity": "sha512-JUeY0F/fQZgIod31Ja1eJgiSxLn7BfQlCnqhwXFBzFHEw63OdLK7VJUJ7bnzNsWgCyoUP5tEp1VRY8rDaYzqOA==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"@jsonjoy.com/json-pack": "^1.0.3",
|
|
||||||
"@jsonjoy.com/util": "^1.3.0",
|
|
||||||
"tree-dump": "^1.0.1",
|
|
||||||
"tslib": "^2.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 4.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/streamich"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/merge-descriptors": {
|
"node_modules/merge-descriptors": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
|
||||||
@ -6310,15 +6176,6 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/require-from-string": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
|
||||||
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=0.10.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/resolve-alpn": {
|
"node_modules/resolve-alpn": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
|
||||||
@ -6447,59 +6304,6 @@
|
|||||||
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
|
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/schema-utils": {
|
|
||||||
"version": "4.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
|
|
||||||
"integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/json-schema": "^7.0.9",
|
|
||||||
"ajv": "^8.9.0",
|
|
||||||
"ajv-formats": "^2.1.1",
|
|
||||||
"ajv-keywords": "^5.1.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 12.13.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/webpack"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/schema-utils/node_modules/ajv": {
|
|
||||||
"version": "8.17.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
|
|
||||||
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"fast-deep-equal": "^3.1.3",
|
|
||||||
"fast-uri": "^3.0.1",
|
|
||||||
"json-schema-traverse": "^1.0.0",
|
|
||||||
"require-from-string": "^2.0.2"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/epoberezkin"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/schema-utils/node_modules/ajv-keywords": {
|
|
||||||
"version": "5.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
|
|
||||||
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"fast-deep-equal": "^3.1.3"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"ajv": "^8.8.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/schema-utils/node_modules/json-schema-traverse": {
|
|
||||||
"version": "1.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
|
||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/seedrandom": {
|
"node_modules/seedrandom": {
|
||||||
"version": "3.0.5",
|
"version": "3.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
|
||||||
@ -7038,18 +6842,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/thingies": {
|
|
||||||
"version": "1.21.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz",
|
|
||||||
"integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==",
|
|
||||||
"license": "Unlicense",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.18"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"tslib": "^2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/tiktoken": {
|
"node_modules/tiktoken": {
|
||||||
"version": "1.0.16",
|
"version": "1.0.16",
|
||||||
"resolved": "https://registry.npmjs.org/tiktoken/-/tiktoken-1.0.16.tgz",
|
"resolved": "https://registry.npmjs.org/tiktoken/-/tiktoken-1.0.16.tgz",
|
||||||
@ -7106,22 +6898,6 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tree-dump": {
|
|
||||||
"version": "1.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz",
|
|
||||||
"integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/streamich"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"tslib": "2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/truncate-utf8-bytes": {
|
"node_modules/truncate-utf8-bytes": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz",
|
||||||
@ -7425,35 +7201,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/webpack-dev-middleware": {
|
|
||||||
"version": "7.4.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.2.tgz",
|
|
||||||
"integrity": "sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"colorette": "^2.0.10",
|
|
||||||
"memfs": "^4.6.0",
|
|
||||||
"mime-types": "^2.1.31",
|
|
||||||
"on-finished": "^2.4.1",
|
|
||||||
"range-parser": "^1.2.1",
|
|
||||||
"schema-utils": "^4.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 18.12.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/webpack"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"webpack": "^5.0.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"webpack": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/webpack-sources": {
|
"node_modules/webpack-sources": {
|
||||||
"version": "3.2.3",
|
"version": "3.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
|
||||||
|
@ -57,7 +57,6 @@
|
|||||||
"vectra": "^0.2.2",
|
"vectra": "^0.2.2",
|
||||||
"wavefile": "^11.0.0",
|
"wavefile": "^11.0.0",
|
||||||
"webpack": "^5.95.0",
|
"webpack": "^5.95.0",
|
||||||
"webpack-dev-middleware": "^7.4.2",
|
|
||||||
"write-file-atomic": "^5.0.1",
|
"write-file-atomic": "^5.0.1",
|
||||||
"ws": "^8.17.1",
|
"ws": "^8.17.1",
|
||||||
"yaml": "^2.3.4",
|
"yaml": "^2.3.4",
|
||||||
@ -85,7 +84,7 @@
|
|||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/SillyTavern/SillyTavern.git"
|
"url": "https://github.com/SillyTavern/SillyTavern.git"
|
||||||
},
|
},
|
||||||
"version": "1.12.7",
|
"version": "1.12.8",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node server.js",
|
"start": "node server.js",
|
||||||
"start:deno": "deno run --allow-run --allow-net --allow-read --allow-write --allow-sys --allow-env server.js",
|
"start:deno": "deno run --allow-run --allow-net --allow-read --allow-write --allow-sys --allow-env server.js",
|
||||||
|
@ -42,3 +42,9 @@ body.login .userSelect .userHandle {
|
|||||||
body.login .userSelect:hover {
|
body.login .userSelect:hover {
|
||||||
background-color: var(--black30a);
|
background-color: var(--black30a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
body.login #handleEntryBlock,
|
||||||
|
body.login #passwordEntryBlock,
|
||||||
|
body.login #passwordRecoveryBlock {
|
||||||
|
margin: 2px;
|
||||||
|
}
|
||||||
|
@ -1342,12 +1342,12 @@
|
|||||||
<input class="neo-range-slider" type="range" id="presence_pen_textgenerationwebui" name="volume" min="-2" max="2" step="0.01" />
|
<input class="neo-range-slider" type="range" id="presence_pen_textgenerationwebui" name="volume" min="-2" max="2" step="0.01" />
|
||||||
<input class="neo-range-input" type="number" min="-2" max="2" step="0.01" data-for="presence_pen_textgenerationwebui" id="presence_pen_counter_textgenerationwebui">
|
<input class="neo-range-input" type="number" min="-2" max="2" step="0.01" data-for="presence_pen_textgenerationwebui" id="presence_pen_counter_textgenerationwebui">
|
||||||
</div>
|
</div>
|
||||||
<div data-tg-type="ooba" class="alignitemscenter flex-container flexFlowColumn flexBasis30p flexGrow flexShrink gap0">
|
<div data-tg-type="aphrodite, ooba" class="alignitemscenter flex-container flexFlowColumn flexBasis30p flexGrow flexShrink gap0">
|
||||||
<small data-i18n="No Repeat Ngram Size">No Repeat Ngram Size</small>
|
<small data-i18n="No Repeat Ngram Size">No Repeat Ngram Size</small>
|
||||||
<input class="neo-range-slider" type="range" id="no_repeat_ngram_size_textgenerationwebui" name="volume" min="0" max="20" step="1">
|
<input class="neo-range-slider" type="range" id="no_repeat_ngram_size_textgenerationwebui" name="volume" min="0" max="20" step="1">
|
||||||
<input class="neo-range-input" type="number" min="0" max="20" step="1" data-for="no_repeat_ngram_size_textgenerationwebui" id="no_repeat_ngram_size_counter_textgenerationwebui">
|
<input class="neo-range-input" type="number" min="0" max="20" step="1" data-for="no_repeat_ngram_size_textgenerationwebui" id="no_repeat_ngram_size_counter_textgenerationwebui">
|
||||||
</div>
|
</div>
|
||||||
<div data-tg-type="tabby" class="alignitemscenter flex-container flexFlowColumn flexBasis30p flexGrow flexShrink gap0">
|
<div data-tg-type="tabby, aphrodite" class="alignitemscenter flex-container flexFlowColumn flexBasis30p flexGrow flexShrink gap0">
|
||||||
<small data-i18n="Skew">Skew</small>
|
<small data-i18n="Skew">Skew</small>
|
||||||
<input class="neo-range-slider" type="range" id="skew_textgenerationwebui" name="volume" min="-5" max="5" step="0.01" />
|
<input class="neo-range-slider" type="range" id="skew_textgenerationwebui" name="volume" min="-5" max="5" step="0.01" />
|
||||||
<input class="neo-range-input" type="number" min="-5" max="5" step="0.01" data-for="skew_textgenerationwebui" id="skew_counter_textgenerationwebui">
|
<input class="neo-range-input" type="number" min="-5" max="5" step="0.01" data-for="skew_textgenerationwebui" id="skew_counter_textgenerationwebui">
|
||||||
@ -1402,7 +1402,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div data-tg-type="ooba, koboldcpp, tabby, llamacpp" id="dryBlock" class="wide100p">
|
<div data-tg-type="aphrodite, ooba, koboldcpp, tabby, llamacpp" id="dryBlock" class="wide100p">
|
||||||
<h4 class="wide100p textAlignCenter" title="DRY penalizes tokens that would extend the end of the input into a sequence that has previously occurred in the input. Set multiplier to 0 to disable." data-i18n="[title]DRY_Repetition_Penalty_desc">
|
<h4 class="wide100p textAlignCenter" title="DRY penalizes tokens that would extend the end of the input into a sequence that has previously occurred in the input. Set multiplier to 0 to disable." data-i18n="[title]DRY_Repetition_Penalty_desc">
|
||||||
<label data-i18n="DRY Repetition Penalty">DRY Repetition Penalty</label>
|
<label data-i18n="DRY Repetition Penalty">DRY Repetition Penalty</label>
|
||||||
<a href="https://github.com/oobabooga/text-generation-webui/pull/5677" target="_blank">
|
<a href="https://github.com/oobabooga/text-generation-webui/pull/5677" target="_blank">
|
||||||
@ -1959,15 +1959,6 @@
|
|||||||
Send the system prompt for supported models. If disabled, the user message is added to the beginning of the prompt.
|
Send the system prompt for supported models. If disabled, the user message is added to the beginning of the prompt.
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="claude_human_sysprompt_message_block" class="wide100p">
|
|
||||||
<div class="range-block-title openai_restorable">
|
|
||||||
<span data-i18n="User first message">User first message</span>
|
|
||||||
<div id="claude_human_sysprompt_message_restore" title="Restore User first message" data-i18n="[title]Restore User first message" class="right_menu_button">
|
|
||||||
<div class="fa-solid fa-clock-rotate-left"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<textarea id="claude_human_sysprompt_textarea" class="text_pole textarea_compact autoSetHeight" rows="2" data-i18n="[placeholder]Human message" placeholder="Human message, instruction, etc. Adds nothing when empty, i.e. requires a new prompt with the role 'user'."></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="range-block m-t-1" data-source="openai,openrouter,scale,custom">
|
<div class="range-block m-t-1" data-source="openai,openrouter,scale,custom">
|
||||||
@ -3287,7 +3278,7 @@
|
|||||||
Advanced Formatting
|
Advanced Formatting
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<a href="https://docs.sillytavern.app/usage/prompts/" class="notes-link" target="_blank">
|
<a href="https://docs.sillytavern.app/usage/core-concepts/advancedformatting/" class="notes-link" target="_blank">
|
||||||
<span class="fa-solid fa-circle-question note-link-span"></span>
|
<span class="fa-solid fa-circle-question note-link-span"></span>
|
||||||
</a>
|
</a>
|
||||||
</h3>
|
</h3>
|
||||||
@ -3749,7 +3740,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<h3 class="margin0">
|
<h3 class="margin0">
|
||||||
<span data-i18n="Worlds/Lorebooks">Worlds/Lorebooks</span>
|
<span data-i18n="Worlds/Lorebooks">Worlds/Lorebooks</span>
|
||||||
<a href="https://docs.sillytavern.app/usage/worldinfo/" class="notes-link" target="_blank">
|
<a href="https://docs.sillytavern.app/usage/core-concepts/worldinfo/" class="notes-link" target="_blank">
|
||||||
<span class="fa-solid fa-circle-question note-link-span"></span>
|
<span class="fa-solid fa-circle-question note-link-span"></span>
|
||||||
</a>
|
</a>
|
||||||
</h3>
|
</h3>
|
||||||
@ -3943,7 +3934,13 @@
|
|||||||
<div name="userSettingsRowOne" class="flex-container flexFlowRow alignitemscenter spaceBetween">
|
<div name="userSettingsRowOne" class="flex-container flexFlowRow alignitemscenter spaceBetween">
|
||||||
<div class="flex-container">
|
<div class="flex-container">
|
||||||
<div class="flex-container flexnowrap alignItemsBaseline">
|
<div class="flex-container flexnowrap alignItemsBaseline">
|
||||||
<h3 class="margin0"><span data-i18n="User Settings">User Settings</span></h3>
|
<h3 class="margin0">
|
||||||
|
<span data-i18n="User Settings">User Settings</span>
|
||||||
|
|
||||||
|
<a href="https://docs.sillytavern.app/usage/user_settings/" class="notes-link" target="_blank">
|
||||||
|
<span class="fa-solid fa-circle-question note-link-span"></span>
|
||||||
|
</a>
|
||||||
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="UI-language-block" class="flex-container alignItemsBaseline">
|
<div id="UI-language-block" class="flex-container alignItemsBaseline">
|
||||||
@ -4276,9 +4273,6 @@
|
|||||||
<audio id="audio_message_sound" src="sounds/message.mp3" hidden></audio>
|
<audio id="audio_message_sound" src="sounds/message.mp3" hidden></audio>
|
||||||
<span>
|
<span>
|
||||||
<small data-i18n="Message Sound">Message Sound</small>
|
<small data-i18n="Message Sound">Message Sound</small>
|
||||||
<a href="https://docs.sillytavern.app/usage/user_settings/uicustomization/#message-sound" class="notes-link" target="_blank">
|
|
||||||
<span class="fa-solid fa-circle-question note-link-span"></span>
|
|
||||||
</a>
|
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<label for="play_sound_unfocused" class="checkbox_label" title="Only play a sound when ST's browser tab is unfocused." data-i18n="[title]Only play a sound when ST's browser tab is unfocused">
|
<label for="play_sound_unfocused" class="checkbox_label" title="Only play a sound when ST's browser tab is unfocused." data-i18n="[title]Only play a sound when ST's browser tab is unfocused">
|
||||||
|
@ -1633,7 +1633,7 @@ export function getEntitiesList({ doFilter = false, doSort = true } = {}) {
|
|||||||
subEntities = filterByTagState(entities, { subForEntity: entity });
|
subEntities = filterByTagState(entities, { subForEntity: entity });
|
||||||
if (doFilter) {
|
if (doFilter) {
|
||||||
// sub entities filter "hacked" because folder filter should not be applied there, so even in "only folders" mode characters show up
|
// sub entities filter "hacked" because folder filter should not be applied there, so even in "only folders" mode characters show up
|
||||||
subEntities = entitiesFilter.applyFilters(subEntities, { clearScoreCache: false, tempOverrides: { [FILTER_TYPES.FOLDER]: FILTER_STATES.UNDEFINED } });
|
subEntities = entitiesFilter.applyFilters(subEntities, { clearScoreCache: false, tempOverrides: { [FILTER_TYPES.FOLDER]: FILTER_STATES.UNDEFINED }, clearFuzzySearchCaches: false });
|
||||||
}
|
}
|
||||||
if (doSort) {
|
if (doSort) {
|
||||||
sortEntitiesList(subEntities);
|
sortEntitiesList(subEntities);
|
||||||
@ -1646,11 +1646,11 @@ export function getEntitiesList({ doFilter = false, doSort = true } = {}) {
|
|||||||
// Second run filters, hiding whatever should be filtered later
|
// Second run filters, hiding whatever should be filtered later
|
||||||
if (doFilter) {
|
if (doFilter) {
|
||||||
const beforeFinalEntities = filterByTagState(entities, { globalDisplayFilters: true });
|
const beforeFinalEntities = filterByTagState(entities, { globalDisplayFilters: true });
|
||||||
entities = entitiesFilter.applyFilters(beforeFinalEntities);
|
entities = entitiesFilter.applyFilters(beforeFinalEntities, { clearFuzzySearchCaches: false });
|
||||||
|
|
||||||
// Magic for folder filter. If that one is enabled, and no folders are display anymore, we remove that filter to actually show the characters.
|
// Magic for folder filter. If that one is enabled, and no folders are display anymore, we remove that filter to actually show the characters.
|
||||||
if (isFilterState(entitiesFilter.getFilterData(FILTER_TYPES.FOLDER), FILTER_STATES.SELECTED) && entities.filter(x => x.type == 'tag').length == 0) {
|
if (isFilterState(entitiesFilter.getFilterData(FILTER_TYPES.FOLDER), FILTER_STATES.SELECTED) && entities.filter(x => x.type == 'tag').length == 0) {
|
||||||
entities = entitiesFilter.applyFilters(beforeFinalEntities, { tempOverrides: { [FILTER_TYPES.FOLDER]: FILTER_STATES.UNDEFINED } });
|
entities = entitiesFilter.applyFilters(beforeFinalEntities, { tempOverrides: { [FILTER_TYPES.FOLDER]: FILTER_STATES.UNDEFINED }, clearFuzzySearchCaches: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1666,6 +1666,7 @@ export function getEntitiesList({ doFilter = false, doSort = true } = {}) {
|
|||||||
if (doSort) {
|
if (doSort) {
|
||||||
sortEntitiesList(entities);
|
sortEntitiesList(entities);
|
||||||
}
|
}
|
||||||
|
entitiesFilter.clearFuzzySearchCaches();
|
||||||
return entities;
|
return entities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,12 @@ const hash_derivations = {
|
|||||||
// command-r-08-2024
|
// command-r-08-2024
|
||||||
'Command R'
|
'Command R'
|
||||||
,
|
,
|
||||||
|
|
||||||
|
// Tulu
|
||||||
|
'ac7498a36a719da630e99d48e6ebc4409de85a77556c2b6159eeb735bcbd11df':
|
||||||
|
// Tulu-3-8B
|
||||||
|
// Tulu-3-70B
|
||||||
|
'Tulu'
|
||||||
};
|
};
|
||||||
|
|
||||||
const substr_derivations = {
|
const substr_derivations = {
|
||||||
|
@ -419,30 +419,35 @@ export class SlashCommandHandler {
|
|||||||
namedArgumentList: [
|
namedArgumentList: [
|
||||||
SlashCommandNamedArgument.fromProps({
|
SlashCommandNamedArgument.fromProps({
|
||||||
name: 'set',
|
name: 'set',
|
||||||
description: 'QR set name',
|
description: 'Name of QR set to add the context menu to',
|
||||||
typeList: [ARGUMENT_TYPE.STRING],
|
typeList: [ARGUMENT_TYPE.STRING],
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
enumProvider: localEnumProviders.qrSets,
|
enumProvider: localEnumProviders.qrSets,
|
||||||
}),
|
}),
|
||||||
SlashCommandNamedArgument.fromProps({
|
SlashCommandNamedArgument.fromProps({
|
||||||
name: 'label',
|
name: 'label',
|
||||||
description: 'Quick Reply label',
|
description: 'Label of Quick Reply to add the context menu to',
|
||||||
typeList: [ARGUMENT_TYPE.STRING],
|
typeList: [ARGUMENT_TYPE.STRING],
|
||||||
enumProvider: localEnumProviders.qrEntries,
|
enumProvider: localEnumProviders.qrEntries,
|
||||||
}),
|
}),
|
||||||
SlashCommandNamedArgument.fromProps({
|
SlashCommandNamedArgument.fromProps({
|
||||||
name: 'id',
|
name: 'id',
|
||||||
description: 'numeric ID of the QR, e.g., id=42',
|
description: 'Numeric ID of Quick Reply to add the context menu to, e.g. id=42',
|
||||||
typeList: [ARGUMENT_TYPE.NUMBER],
|
typeList: [ARGUMENT_TYPE.NUMBER],
|
||||||
enumProvider: localEnumProviders.qrIds,
|
enumProvider: localEnumProviders.qrIds,
|
||||||
}),
|
}),
|
||||||
new SlashCommandNamedArgument(
|
new SlashCommandNamedArgument(
|
||||||
'chain', 'boolean', [ARGUMENT_TYPE.BOOLEAN], false, false, 'false',
|
'chain',
|
||||||
|
'If true, button QR is sent together with (before) the clicked QR from the context menu',
|
||||||
|
[ARGUMENT_TYPE.BOOLEAN],
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
'false',
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
unnamedArgumentList: [
|
unnamedArgumentList: [
|
||||||
SlashCommandArgument.fromProps({
|
SlashCommandArgument.fromProps({
|
||||||
description: 'QR set name',
|
description: 'Name of QR set to add as a context menu',
|
||||||
typeList: [ARGUMENT_TYPE.STRING],
|
typeList: [ARGUMENT_TYPE.STRING],
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
enumProvider: localEnumProviders.qrSets,
|
enumProvider: localEnumProviders.qrSets,
|
||||||
@ -450,13 +455,16 @@ export class SlashCommandHandler {
|
|||||||
],
|
],
|
||||||
helpString: `
|
helpString: `
|
||||||
<div>
|
<div>
|
||||||
Add context menu preset to a QR.
|
Add a context menu preset to a QR.
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
If <code>id</code> and <code>label</code> are both provided, <code>id</code> will be used.
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<strong>Example:</strong>
|
<strong>Example:</strong>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<pre><code>/qr-contextadd set=MyPreset label=MyButton chain=true MyOtherPreset</code></pre>
|
<pre><code>/qr-contextadd set=MyQRSetWithTheButton label=MyButton chain=true MyQRSetWithContextItems</code></pre>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@ -470,27 +478,27 @@ export class SlashCommandHandler {
|
|||||||
namedArgumentList: [
|
namedArgumentList: [
|
||||||
SlashCommandNamedArgument.fromProps({
|
SlashCommandNamedArgument.fromProps({
|
||||||
name: 'set',
|
name: 'set',
|
||||||
description: 'QR set name',
|
description: 'Name of QR set to remove the context menu from',
|
||||||
typeList: [ARGUMENT_TYPE.STRING],
|
typeList: [ARGUMENT_TYPE.STRING],
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
enumProvider: localEnumProviders.qrSets,
|
enumProvider: localEnumProviders.qrSets,
|
||||||
}),
|
}),
|
||||||
SlashCommandNamedArgument.fromProps({
|
SlashCommandNamedArgument.fromProps({
|
||||||
name: 'label',
|
name: 'label',
|
||||||
description: 'Quick Reply label',
|
description: 'Label of Quick Reply to remove the context menu from',
|
||||||
typeList: [ARGUMENT_TYPE.STRING],
|
typeList: [ARGUMENT_TYPE.STRING],
|
||||||
enumProvider: localEnumProviders.qrEntries,
|
enumProvider: localEnumProviders.qrEntries,
|
||||||
}),
|
}),
|
||||||
SlashCommandNamedArgument.fromProps({
|
SlashCommandNamedArgument.fromProps({
|
||||||
name: 'id',
|
name: 'id',
|
||||||
description: 'numeric ID of the QR, e.g., id=42',
|
description: 'Numeric ID of Quick Reply to remove the context menu from, e.g. id=42',
|
||||||
typeList: [ARGUMENT_TYPE.NUMBER],
|
typeList: [ARGUMENT_TYPE.NUMBER],
|
||||||
enumProvider: localEnumProviders.qrIds,
|
enumProvider: localEnumProviders.qrIds,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
unnamedArgumentList: [
|
unnamedArgumentList: [
|
||||||
SlashCommandArgument.fromProps({
|
SlashCommandArgument.fromProps({
|
||||||
description: 'QR set name',
|
description: 'Name of QR set to remove',
|
||||||
typeList: [ARGUMENT_TYPE.STRING],
|
typeList: [ARGUMENT_TYPE.STRING],
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
enumProvider: localEnumProviders.qrSets,
|
enumProvider: localEnumProviders.qrSets,
|
||||||
@ -500,6 +508,9 @@ export class SlashCommandHandler {
|
|||||||
<div>
|
<div>
|
||||||
Remove context menu preset from a QR.
|
Remove context menu preset from a QR.
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
If <code>id</code> and <code>label</code> are both provided, <code>id</code> will be used.
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<strong>Example:</strong>
|
<strong>Example:</strong>
|
||||||
<ul>
|
<ul>
|
||||||
@ -541,6 +552,9 @@ export class SlashCommandHandler {
|
|||||||
<div>
|
<div>
|
||||||
Remove all context menu presets from a QR.
|
Remove all context menu presets from a QR.
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
If <code>id</code> and a label are both provided, <code>id</code> will be used.
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<strong>Example:</strong>
|
<strong>Example:</strong>
|
||||||
<ul>
|
<ul>
|
||||||
@ -908,12 +922,11 @@ export class SlashCommandHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
createContextItem(args, name) {
|
createContextItem(args, name) {
|
||||||
try {
|
try {
|
||||||
this.api.createContextItem(
|
this.api.createContextItem(
|
||||||
args.set,
|
args.set,
|
||||||
args.label,
|
args.id !== undefined ? Number(args.id) : args.label,
|
||||||
name,
|
name,
|
||||||
isTrueBoolean(args.chain),
|
isTrueBoolean(args.chain),
|
||||||
);
|
);
|
||||||
@ -923,14 +936,14 @@ export class SlashCommandHandler {
|
|||||||
}
|
}
|
||||||
deleteContextItem(args, name) {
|
deleteContextItem(args, name) {
|
||||||
try {
|
try {
|
||||||
this.api.deleteContextItem(args.set, args.label, name);
|
this.api.deleteContextItem(args.set, args.id !== undefined ? Number(args.id) : args.label, name);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
toastr.error(ex.message);
|
toastr.error(ex.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clearContextMenu(args, label) {
|
clearContextMenu(args, label) {
|
||||||
try {
|
try {
|
||||||
this.api.clearContextMenu(args.set, args.label ?? label);
|
this.api.clearContextMenu(args.set, args.id !== undefined ? Number(args.id) : args.label ?? label);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
toastr.error(ex.message);
|
toastr.error(ex.message);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ export class ContextMenu {
|
|||||||
this.itemList = this.build(qr).children;
|
this.itemList = this.build(qr).children;
|
||||||
this.itemList.forEach(item => {
|
this.itemList.forEach(item => {
|
||||||
item.onExpand = () => {
|
item.onExpand = () => {
|
||||||
this.itemList.filter(it => it != item)
|
this.itemList.filter(it => it !== item)
|
||||||
.forEach(it => it.collapse());
|
.forEach(it => it.collapse());
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -36,6 +36,7 @@ export class ContextMenu {
|
|||||||
icon: qr.icon,
|
icon: qr.icon,
|
||||||
showLabel: qr.showLabel,
|
showLabel: qr.showLabel,
|
||||||
label: qr.label,
|
label: qr.label,
|
||||||
|
title: qr.title,
|
||||||
message: (chainedMessage && qr.message ? `${chainedMessage} | ` : '') + qr.message,
|
message: (chainedMessage && qr.message ? `${chainedMessage} | ` : '') + qr.message,
|
||||||
children: [],
|
children: [],
|
||||||
};
|
};
|
||||||
@ -45,12 +46,29 @@ export class ContextMenu {
|
|||||||
const nextHierarchy = [...hierarchy, cl.set];
|
const nextHierarchy = [...hierarchy, cl.set];
|
||||||
const nextLabelHierarchy = [...labelHierarchy, tree.label];
|
const nextLabelHierarchy = [...labelHierarchy, tree.label];
|
||||||
tree.children.push(new MenuHeader(cl.set.name));
|
tree.children.push(new MenuHeader(cl.set.name));
|
||||||
cl.set.qrList.forEach(subQr => {
|
|
||||||
|
// If the Quick Reply's own set is added as a context menu,
|
||||||
|
// show only the sub-QRs that are Invisible but have an icon
|
||||||
|
// intent: allow a QR set to be assigned to one of its own QR buttons for a "burger" menu
|
||||||
|
// with "UI" QRs either in the bar or in the menu, and "library function" QRs still hidden.
|
||||||
|
// - QRs already visible on the bar are filtered out,
|
||||||
|
// - hidden QRs without an icon are filtered out,
|
||||||
|
// - hidden QRs **with an icon** are shown in the menu
|
||||||
|
// so everybody is happy
|
||||||
|
const qrsOwnSetAddedAsContextMenu = cl.set.qrList.includes(qr);
|
||||||
|
const visible = (subQr) => {
|
||||||
|
return qrsOwnSetAddedAsContextMenu
|
||||||
|
? subQr.isHidden && !!subQr.icon // yes .isHidden gets inverted here
|
||||||
|
: !subQr.isHidden;
|
||||||
|
};
|
||||||
|
|
||||||
|
cl.set.qrList.filter(visible).forEach(subQr => {
|
||||||
const subTree = this.build(subQr, cl.isChained ? tree.message : null, nextHierarchy, nextLabelHierarchy);
|
const subTree = this.build(subQr, cl.isChained ? tree.message : null, nextHierarchy, nextLabelHierarchy);
|
||||||
tree.children.push(new MenuItem(
|
tree.children.push(new MenuItem(
|
||||||
subTree.icon,
|
subTree.icon,
|
||||||
subTree.showLabel,
|
subTree.showLabel,
|
||||||
subTree.label,
|
subTree.label,
|
||||||
|
subTree.title,
|
||||||
subTree.message,
|
subTree.message,
|
||||||
(evt) => {
|
(evt) => {
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
|
@ -2,7 +2,7 @@ import { MenuItem } from './MenuItem.js';
|
|||||||
|
|
||||||
export class MenuHeader extends MenuItem {
|
export class MenuHeader extends MenuItem {
|
||||||
constructor(/**@type {String}*/label) {
|
constructor(/**@type {String}*/label) {
|
||||||
super(null, null, label, null, null);
|
super(null, null, label, null, null, null, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,11 +4,11 @@ export class MenuItem {
|
|||||||
/**@type {string}*/ icon;
|
/**@type {string}*/ icon;
|
||||||
/**@type {boolean}*/ showLabel;
|
/**@type {boolean}*/ showLabel;
|
||||||
/**@type {string}*/ label;
|
/**@type {string}*/ label;
|
||||||
|
/**@type {string}*/ title;
|
||||||
/**@type {object}*/ value;
|
/**@type {object}*/ value;
|
||||||
/**@type {function}*/ callback;
|
/**@type {function}*/ callback;
|
||||||
/**@type {MenuItem[]}*/ childList = [];
|
/**@type {MenuItem[]}*/ childList = [];
|
||||||
/**@type {SubMenu}*/ subMenu;
|
/**@type {SubMenu}*/ subMenu;
|
||||||
/**@type {boolean}*/ isForceExpanded = false;
|
|
||||||
|
|
||||||
/**@type {HTMLElement}*/ root;
|
/**@type {HTMLElement}*/ root;
|
||||||
|
|
||||||
@ -19,17 +19,19 @@ export class MenuItem {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {string} icon
|
* @param {?string} icon
|
||||||
* @param {boolean} showLabel
|
* @param {?boolean} showLabel
|
||||||
* @param {string} label
|
* @param {string} label
|
||||||
|
* @param {?string} title Tooltip
|
||||||
* @param {object} value
|
* @param {object} value
|
||||||
* @param {function} callback
|
* @param {function} callback
|
||||||
* @param {MenuItem[]} children
|
* @param {MenuItem[]} children
|
||||||
*/
|
*/
|
||||||
constructor(icon, showLabel, label, value, callback, children = []) {
|
constructor(icon, showLabel, label, title, value, callback, children = []) {
|
||||||
this.icon = icon;
|
this.icon = icon;
|
||||||
this.showLabel = showLabel;
|
this.showLabel = showLabel;
|
||||||
this.label = label;
|
this.label = label;
|
||||||
|
this.title = title;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.childList = children;
|
this.childList = children;
|
||||||
@ -42,12 +44,15 @@ export class MenuItem {
|
|||||||
this.root = item;
|
this.root = item;
|
||||||
item.classList.add('list-group-item');
|
item.classList.add('list-group-item');
|
||||||
item.classList.add('ctx-item');
|
item.classList.add('ctx-item');
|
||||||
item.title = this.value;
|
|
||||||
|
// if a title/tooltip is set, add it, otherwise use the QR content
|
||||||
|
// same as for the main QR list
|
||||||
|
item.title = this.title || this.value;
|
||||||
|
|
||||||
if (this.callback) {
|
if (this.callback) {
|
||||||
item.addEventListener('click', (evt) => this.callback(evt, this));
|
item.addEventListener('click', (evt) => this.callback(evt, this));
|
||||||
}
|
}
|
||||||
const icon = document.createElement('div'); {
|
const icon = document.createElement('div'); {
|
||||||
this.domIcon = icon;
|
|
||||||
icon.classList.add('qr--button-icon');
|
icon.classList.add('qr--button-icon');
|
||||||
icon.classList.add('fa-solid');
|
icon.classList.add('fa-solid');
|
||||||
if (!this.icon) icon.classList.add('qr--hidden');
|
if (!this.icon) icon.classList.add('qr--hidden');
|
||||||
@ -55,7 +60,6 @@ export class MenuItem {
|
|||||||
item.append(icon);
|
item.append(icon);
|
||||||
}
|
}
|
||||||
const lbl = document.createElement('div'); {
|
const lbl = document.createElement('div'); {
|
||||||
this.domLabel = lbl;
|
|
||||||
lbl.classList.add('qr--button-label');
|
lbl.classList.add('qr--button-label');
|
||||||
if (this.icon && !this.showLabel) lbl.classList.add('qr--hidden');
|
if (this.icon && !this.showLabel) lbl.classList.add('qr--hidden');
|
||||||
lbl.textContent = this.label;
|
lbl.textContent = this.label;
|
||||||
|
@ -174,6 +174,9 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
.ctx-menu .ctx-item .qr--hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
.list-group .list-group-item.ctx-header {
|
.list-group .list-group-item.ctx-header {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
@ -176,6 +176,10 @@
|
|||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ctx-menu .ctx-item .qr--hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.list-group .list-group-item.ctx-header {
|
.list-group .list-group-item.ctx-header {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
@ -55,6 +55,19 @@ export function isFilterState(a, b) {
|
|||||||
return aKey === bKey;
|
return aKey === bKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fuzzy search categories
|
||||||
|
* @type {{ characters: string, worldInfo: string, personas: string, tags: string, groups: string }}
|
||||||
|
*/
|
||||||
|
export const fuzzySearchCategories = Object.freeze({
|
||||||
|
characters: 'characters',
|
||||||
|
worldInfo: 'worldInfo',
|
||||||
|
personas: 'personas',
|
||||||
|
tags: 'tags',
|
||||||
|
groups: 'groups',
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class for filtering data.
|
* Helper class for filtering data.
|
||||||
* @example
|
* @example
|
||||||
@ -72,6 +85,12 @@ export class FilterHelper {
|
|||||||
*/
|
*/
|
||||||
scoreCache;
|
scoreCache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache for fuzzy search results per category.
|
||||||
|
* @type {Object.<string, { resultMap: Map<string, any> }>}
|
||||||
|
*/
|
||||||
|
fuzzySearchCaches;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new FilterHelper
|
* Creates a new FilterHelper
|
||||||
* @param {Function} onDataChanged Callback to trigger when the filter data changes
|
* @param {Function} onDataChanged Callback to trigger when the filter data changes
|
||||||
@ -79,6 +98,13 @@ export class FilterHelper {
|
|||||||
constructor(onDataChanged) {
|
constructor(onDataChanged) {
|
||||||
this.onDataChanged = onDataChanged;
|
this.onDataChanged = onDataChanged;
|
||||||
this.scoreCache = new Map();
|
this.scoreCache = new Map();
|
||||||
|
this.fuzzySearchCaches = {
|
||||||
|
[fuzzySearchCategories.characters]: { resultMap: new Map() },
|
||||||
|
[fuzzySearchCategories.worldInfo]: { resultMap: new Map() },
|
||||||
|
[fuzzySearchCategories.personas]: { resultMap: new Map() },
|
||||||
|
[fuzzySearchCategories.tags]: { resultMap: new Map() },
|
||||||
|
[fuzzySearchCategories.groups]: { resultMap: new Map() },
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -151,7 +177,7 @@ export class FilterHelper {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fuzzySearchResults = fuzzySearchWorldInfo(data, term);
|
const fuzzySearchResults = fuzzySearchWorldInfo(data, term, this.fuzzySearchCaches);
|
||||||
this.cacheScores(FILTER_TYPES.WORLD_INFO_SEARCH, new Map(fuzzySearchResults.map(i => [i.item?.uid, i.score])));
|
this.cacheScores(FILTER_TYPES.WORLD_INFO_SEARCH, new Map(fuzzySearchResults.map(i => [i.item?.uid, i.score])));
|
||||||
|
|
||||||
const filteredData = data.filter(entity => fuzzySearchResults.find(x => x.item === entity));
|
const filteredData = data.filter(entity => fuzzySearchResults.find(x => x.item === entity));
|
||||||
@ -170,7 +196,7 @@ export class FilterHelper {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fuzzySearchResults = fuzzySearchPersonas(data, term);
|
const fuzzySearchResults = fuzzySearchPersonas(data, term, this.fuzzySearchCaches);
|
||||||
this.cacheScores(FILTER_TYPES.PERSONA_SEARCH, new Map(fuzzySearchResults.map(i => [i.item.key, i.score])));
|
this.cacheScores(FILTER_TYPES.PERSONA_SEARCH, new Map(fuzzySearchResults.map(i => [i.item.key, i.score])));
|
||||||
|
|
||||||
const filteredData = data.filter(name => fuzzySearchResults.find(x => x.item.key === name));
|
const filteredData = data.filter(name => fuzzySearchResults.find(x => x.item.key === name));
|
||||||
@ -289,9 +315,9 @@ export class FilterHelper {
|
|||||||
|
|
||||||
// Save fuzzy search results and scores if enabled
|
// Save fuzzy search results and scores if enabled
|
||||||
if (power_user.fuzzy_search) {
|
if (power_user.fuzzy_search) {
|
||||||
const fuzzySearchCharactersResults = fuzzySearchCharacters(searchValue);
|
const fuzzySearchCharactersResults = fuzzySearchCharacters(searchValue, this.fuzzySearchCaches);
|
||||||
const fuzzySearchGroupsResults = fuzzySearchGroups(searchValue);
|
const fuzzySearchGroupsResults = fuzzySearchGroups(searchValue, this.fuzzySearchCaches);
|
||||||
const fuzzySearchTagsResult = fuzzySearchTags(searchValue);
|
const fuzzySearchTagsResult = fuzzySearchTags(searchValue, this.fuzzySearchCaches);
|
||||||
this.cacheScores(FILTER_TYPES.SEARCH, new Map(fuzzySearchCharactersResults.map(i => [`character.${i.refIndex}`, i.score])));
|
this.cacheScores(FILTER_TYPES.SEARCH, new Map(fuzzySearchCharactersResults.map(i => [`character.${i.refIndex}`, i.score])));
|
||||||
this.cacheScores(FILTER_TYPES.SEARCH, new Map(fuzzySearchGroupsResults.map(i => [`group.${i.item.id}`, i.score])));
|
this.cacheScores(FILTER_TYPES.SEARCH, new Map(fuzzySearchGroupsResults.map(i => [`group.${i.item.id}`, i.score])));
|
||||||
this.cacheScores(FILTER_TYPES.SEARCH, new Map(fuzzySearchTagsResult.map(i => [`tag.${i.item.id}`, i.score])));
|
this.cacheScores(FILTER_TYPES.SEARCH, new Map(fuzzySearchTagsResult.map(i => [`tag.${i.item.id}`, i.score])));
|
||||||
@ -343,11 +369,14 @@ export class FilterHelper {
|
|||||||
* @param {object} options - Optional call parameters
|
* @param {object} options - Optional call parameters
|
||||||
* @param {boolean} [options.clearScoreCache=true] - Whether the score cache should be cleared.
|
* @param {boolean} [options.clearScoreCache=true] - Whether the score cache should be cleared.
|
||||||
* @param {Object.<FilterType, any>} [options.tempOverrides={}] - Temporarily override specific filters for this filter application
|
* @param {Object.<FilterType, any>} [options.tempOverrides={}] - Temporarily override specific filters for this filter application
|
||||||
|
* @param {boolean} [options.clearFuzzySearchCaches=true] - Whether the fuzzy search caches should be cleared.
|
||||||
* @returns {any[]} The filtered data.
|
* @returns {any[]} The filtered data.
|
||||||
*/
|
*/
|
||||||
applyFilters(data, { clearScoreCache = true, tempOverrides = {} } = {}) {
|
applyFilters(data, { clearScoreCache = true, tempOverrides = {}, clearFuzzySearchCaches = true } = {}) {
|
||||||
if (clearScoreCache) this.clearScoreCache();
|
if (clearScoreCache) this.clearScoreCache();
|
||||||
|
|
||||||
|
if (clearFuzzySearchCaches) this.clearFuzzySearchCaches();
|
||||||
|
|
||||||
// Save original filter states
|
// Save original filter states
|
||||||
const originalStates = {};
|
const originalStates = {};
|
||||||
for (const key in tempOverrides) {
|
for (const key in tempOverrides) {
|
||||||
@ -411,4 +440,14 @@ export class FilterHelper {
|
|||||||
this.scoreCache = new Map();
|
this.scoreCache = new Map();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears fuzzy search caches
|
||||||
|
*/
|
||||||
|
clearFuzzySearchCaches() {
|
||||||
|
for (const cache of Object.values(this.fuzzySearchCaches)) {
|
||||||
|
cache.resultMap.clear();
|
||||||
|
}
|
||||||
|
console.log('All fuzzy search caches cleared');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,6 @@ const default_wi_format = '{0}';
|
|||||||
const default_new_chat_prompt = '[Start a new Chat]';
|
const default_new_chat_prompt = '[Start a new Chat]';
|
||||||
const default_new_group_chat_prompt = '[Start a new group chat. Group members: {{group}}]';
|
const default_new_group_chat_prompt = '[Start a new group chat. Group members: {{group}}]';
|
||||||
const default_new_example_chat_prompt = '[Example Chat]';
|
const default_new_example_chat_prompt = '[Example Chat]';
|
||||||
const default_claude_human_sysprompt_message = 'Let\'s get started. Please generate your response based on the information and instructions provided above.';
|
|
||||||
const default_continue_nudge_prompt = '[Continue the following message. Do not include ANY parts of the original message. Use capitalization and punctuation as if your reply is a part of the original message: {{lastChatMessage}}]';
|
const default_continue_nudge_prompt = '[Continue the following message. Do not include ANY parts of the original message. Use capitalization and punctuation as if your reply is a part of the original message: {{lastChatMessage}}]';
|
||||||
const default_bias = 'Default (none)';
|
const default_bias = 'Default (none)';
|
||||||
const default_personality_format = '[{{char}}\'s personality: {{personality}}]';
|
const default_personality_format = '[{{char}}\'s personality: {{personality}}]';
|
||||||
@ -276,7 +275,6 @@ const default_settings = {
|
|||||||
proxy_password: '',
|
proxy_password: '',
|
||||||
assistant_prefill: '',
|
assistant_prefill: '',
|
||||||
assistant_impersonation: '',
|
assistant_impersonation: '',
|
||||||
human_sysprompt_message: default_claude_human_sysprompt_message,
|
|
||||||
claude_use_sysprompt: false,
|
claude_use_sysprompt: false,
|
||||||
use_makersuite_sysprompt: true,
|
use_makersuite_sysprompt: true,
|
||||||
use_alt_scale: false,
|
use_alt_scale: false,
|
||||||
@ -353,7 +351,6 @@ const oai_settings = {
|
|||||||
proxy_password: '',
|
proxy_password: '',
|
||||||
assistant_prefill: '',
|
assistant_prefill: '',
|
||||||
assistant_impersonation: '',
|
assistant_impersonation: '',
|
||||||
human_sysprompt_message: default_claude_human_sysprompt_message,
|
|
||||||
claude_use_sysprompt: false,
|
claude_use_sysprompt: false,
|
||||||
use_makersuite_sysprompt: true,
|
use_makersuite_sysprompt: true,
|
||||||
use_alt_scale: false,
|
use_alt_scale: false,
|
||||||
@ -1892,7 +1889,6 @@ async function sendOpenAIRequest(type, messages, signal) {
|
|||||||
generate_data['top_k'] = Number(oai_settings.top_k_openai);
|
generate_data['top_k'] = Number(oai_settings.top_k_openai);
|
||||||
generate_data['claude_use_sysprompt'] = oai_settings.claude_use_sysprompt;
|
generate_data['claude_use_sysprompt'] = oai_settings.claude_use_sysprompt;
|
||||||
generate_data['stop'] = getCustomStoppingStrings(); // Claude shouldn't have limits on stop strings.
|
generate_data['stop'] = getCustomStoppingStrings(); // Claude shouldn't have limits on stop strings.
|
||||||
generate_data['human_sysprompt_message'] = substituteParams(oai_settings.human_sysprompt_message);
|
|
||||||
// Don't add a prefill on quiet gens (summarization) and when using continue prefill.
|
// Don't add a prefill on quiet gens (summarization) and when using continue prefill.
|
||||||
if (!isQuiet && !(isContinue && oai_settings.continue_prefill)) {
|
if (!isQuiet && !(isContinue && oai_settings.continue_prefill)) {
|
||||||
generate_data['assistant_prefill'] = isImpersonate ? substituteParams(oai_settings.assistant_impersonation) : substituteParams(oai_settings.assistant_prefill);
|
generate_data['assistant_prefill'] = isImpersonate ? substituteParams(oai_settings.assistant_impersonation) : substituteParams(oai_settings.assistant_prefill);
|
||||||
@ -3030,7 +3026,6 @@ function loadOpenAISettings(data, settings) {
|
|||||||
oai_settings.proxy_password = settings.proxy_password ?? default_settings.proxy_password;
|
oai_settings.proxy_password = settings.proxy_password ?? default_settings.proxy_password;
|
||||||
oai_settings.assistant_prefill = settings.assistant_prefill ?? default_settings.assistant_prefill;
|
oai_settings.assistant_prefill = settings.assistant_prefill ?? default_settings.assistant_prefill;
|
||||||
oai_settings.assistant_impersonation = settings.assistant_impersonation ?? default_settings.assistant_impersonation;
|
oai_settings.assistant_impersonation = settings.assistant_impersonation ?? default_settings.assistant_impersonation;
|
||||||
oai_settings.human_sysprompt_message = settings.human_sysprompt_message ?? default_settings.human_sysprompt_message;
|
|
||||||
oai_settings.image_inlining = settings.image_inlining ?? default_settings.image_inlining;
|
oai_settings.image_inlining = settings.image_inlining ?? default_settings.image_inlining;
|
||||||
oai_settings.inline_image_quality = settings.inline_image_quality ?? default_settings.inline_image_quality;
|
oai_settings.inline_image_quality = settings.inline_image_quality ?? default_settings.inline_image_quality;
|
||||||
oai_settings.bypass_status_check = settings.bypass_status_check ?? default_settings.bypass_status_check;
|
oai_settings.bypass_status_check = settings.bypass_status_check ?? default_settings.bypass_status_check;
|
||||||
@ -3070,7 +3065,6 @@ function loadOpenAISettings(data, settings) {
|
|||||||
$('#openai_proxy_password').val(oai_settings.proxy_password);
|
$('#openai_proxy_password').val(oai_settings.proxy_password);
|
||||||
$('#claude_assistant_prefill').val(oai_settings.assistant_prefill);
|
$('#claude_assistant_prefill').val(oai_settings.assistant_prefill);
|
||||||
$('#claude_assistant_impersonation').val(oai_settings.assistant_impersonation);
|
$('#claude_assistant_impersonation').val(oai_settings.assistant_impersonation);
|
||||||
$('#claude_human_sysprompt_textarea').val(oai_settings.human_sysprompt_message);
|
|
||||||
$('#openai_image_inlining').prop('checked', oai_settings.image_inlining);
|
$('#openai_image_inlining').prop('checked', oai_settings.image_inlining);
|
||||||
$('#openai_bypass_status_check').prop('checked', oai_settings.bypass_status_check);
|
$('#openai_bypass_status_check').prop('checked', oai_settings.bypass_status_check);
|
||||||
|
|
||||||
@ -3400,7 +3394,6 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) {
|
|||||||
show_external_models: settings.show_external_models,
|
show_external_models: settings.show_external_models,
|
||||||
assistant_prefill: settings.assistant_prefill,
|
assistant_prefill: settings.assistant_prefill,
|
||||||
assistant_impersonation: settings.assistant_impersonation,
|
assistant_impersonation: settings.assistant_impersonation,
|
||||||
human_sysprompt_message: settings.human_sysprompt_message,
|
|
||||||
claude_use_sysprompt: settings.claude_use_sysprompt,
|
claude_use_sysprompt: settings.claude_use_sysprompt,
|
||||||
use_makersuite_sysprompt: settings.use_makersuite_sysprompt,
|
use_makersuite_sysprompt: settings.use_makersuite_sysprompt,
|
||||||
use_alt_scale: settings.use_alt_scale,
|
use_alt_scale: settings.use_alt_scale,
|
||||||
@ -3825,7 +3818,6 @@ function onSettingsPresetChange() {
|
|||||||
proxy_password: ['#openai_proxy_password', 'proxy_password', false],
|
proxy_password: ['#openai_proxy_password', 'proxy_password', false],
|
||||||
assistant_prefill: ['#claude_assistant_prefill', 'assistant_prefill', false],
|
assistant_prefill: ['#claude_assistant_prefill', 'assistant_prefill', false],
|
||||||
assistant_impersonation: ['#claude_assistant_impersonation', 'assistant_impersonation', false],
|
assistant_impersonation: ['#claude_assistant_impersonation', 'assistant_impersonation', false],
|
||||||
human_sysprompt_message: ['#claude_human_sysprompt_textarea', 'human_sysprompt_message', false],
|
|
||||||
claude_use_sysprompt: ['#claude_use_sysprompt', 'claude_use_sysprompt', true],
|
claude_use_sysprompt: ['#claude_use_sysprompt', 'claude_use_sysprompt', true],
|
||||||
use_makersuite_sysprompt: ['#use_makersuite_sysprompt', 'use_makersuite_sysprompt', true],
|
use_makersuite_sysprompt: ['#use_makersuite_sysprompt', 'use_makersuite_sysprompt', true],
|
||||||
use_alt_scale: ['#use_alt_scale', 'use_alt_scale', true],
|
use_alt_scale: ['#use_alt_scale', 'use_alt_scale', true],
|
||||||
@ -4677,10 +4669,6 @@ function toggleChatCompletionForms() {
|
|||||||
const validSources = $(this).data('source').split(',');
|
const validSources = $(this).data('source').split(',');
|
||||||
$(this).toggle(validSources.includes(oai_settings.chat_completion_source));
|
$(this).toggle(validSources.includes(oai_settings.chat_completion_source));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (chat_completion_sources.CLAUDE == oai_settings.chat_completion_source) {
|
|
||||||
$('#claude_human_sysprompt_message_block').toggle(oai_settings.claude_use_sysprompt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function testApiConnection() {
|
async function testApiConnection() {
|
||||||
@ -5036,7 +5024,6 @@ export function initOpenAI() {
|
|||||||
|
|
||||||
$('#claude_use_sysprompt').on('change', function () {
|
$('#claude_use_sysprompt').on('change', function () {
|
||||||
oai_settings.claude_use_sysprompt = !!$('#claude_use_sysprompt').prop('checked');
|
oai_settings.claude_use_sysprompt = !!$('#claude_use_sysprompt').prop('checked');
|
||||||
$('#claude_human_sysprompt_message_block').toggle(oai_settings.claude_use_sysprompt);
|
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -5113,12 +5100,6 @@ export function initOpenAI() {
|
|||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#claude_human_sysprompt_message_restore').on('click', function () {
|
|
||||||
oai_settings.human_sysprompt_message = default_claude_human_sysprompt_message;
|
|
||||||
$('#claude_human_sysprompt_textarea').val(oai_settings.human_sysprompt_message);
|
|
||||||
saveSettingsDebounced();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#newgroupchat_prompt_restore').on('click', function () {
|
$('#newgroupchat_prompt_restore').on('click', function () {
|
||||||
oai_settings.new_group_chat_prompt = default_new_group_chat_prompt;
|
oai_settings.new_group_chat_prompt = default_new_group_chat_prompt;
|
||||||
$('#newgroupchat_prompt_textarea').val(oai_settings.new_group_chat_prompt);
|
$('#newgroupchat_prompt_textarea').val(oai_settings.new_group_chat_prompt);
|
||||||
@ -5210,11 +5191,6 @@ export function initOpenAI() {
|
|||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#claude_human_sysprompt_textarea').on('input', function () {
|
|
||||||
oai_settings.human_sysprompt_message = String($('#claude_human_sysprompt_textarea').val());
|
|
||||||
saveSettingsDebounced();
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#openrouter_use_fallback').on('input', function () {
|
$('#openrouter_use_fallback').on('input', function () {
|
||||||
oai_settings.openrouter_use_fallback = !!$(this).prop('checked');
|
oai_settings.openrouter_use_fallback = !!$(this).prop('checked');
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
|
@ -53,6 +53,7 @@ import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandE
|
|||||||
import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js';
|
import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js';
|
||||||
import { POPUP_TYPE, callGenericPopup } from './popup.js';
|
import { POPUP_TYPE, callGenericPopup } from './popup.js';
|
||||||
import { loadSystemPrompts } from './sysprompt.js';
|
import { loadSystemPrompts } from './sysprompt.js';
|
||||||
|
import { fuzzySearchCategories } from './filters.js';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
loadPowerUserSettings,
|
loadPowerUserSettings,
|
||||||
@ -1831,27 +1832,28 @@ async function loadContextSettings() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fuzzy search characters by a search term
|
* Common function to perform fuzzy search with optional caching
|
||||||
|
* @param {string} type - Type of search from fuzzySearchCategories
|
||||||
|
* @param {any[]} data - Data array to search in
|
||||||
|
* @param {Array<{name: string, weight: number, getFn?: Function}>} keys - Fuse.js keys configuration
|
||||||
* @param {string} searchValue - The search term
|
* @param {string} searchValue - The search term
|
||||||
|
* @param {Object.<string, { resultMap: Map<string, any> }>} [fuzzySearchCaches=null] - Optional fuzzy search caches
|
||||||
* @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
|
* @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
|
||||||
*/
|
*/
|
||||||
export function fuzzySearchCharacters(searchValue) {
|
function performFuzzySearch(type, data, keys, searchValue, fuzzySearchCaches = null) {
|
||||||
|
// Check cache if provided
|
||||||
|
if (fuzzySearchCaches) {
|
||||||
|
const cache = fuzzySearchCaches[type];
|
||||||
|
if (cache?.resultMap.has(searchValue)) {
|
||||||
|
return cache.resultMap.get(searchValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const fuse = new Fuse(characters, {
|
const fuse = new Fuse(data, {
|
||||||
keys: [
|
keys: keys,
|
||||||
{ name: 'data.name', weight: 20 },
|
|
||||||
{ name: '#tags', weight: 10, getFn: (character) => getTagsList(character.avatar).map(x => x.name).join('||') },
|
|
||||||
{ name: 'data.description', weight: 3 },
|
|
||||||
{ name: 'data.mes_example', weight: 3 },
|
|
||||||
{ name: 'data.scenario', weight: 2 },
|
|
||||||
{ name: 'data.personality', weight: 2 },
|
|
||||||
{ name: 'data.first_mes', weight: 2 },
|
|
||||||
{ name: 'data.creator_notes', weight: 2 },
|
|
||||||
{ name: 'data.creator', weight: 1 },
|
|
||||||
{ name: 'data.tags', weight: 1 },
|
|
||||||
{ name: 'data.alternate_greetings', weight: 1 },
|
|
||||||
],
|
|
||||||
includeScore: true,
|
includeScore: true,
|
||||||
ignoreLocation: true,
|
ignoreLocation: true,
|
||||||
useExtendedSearch: true,
|
useExtendedSearch: true,
|
||||||
@ -1859,109 +1861,110 @@ export function fuzzySearchCharacters(searchValue) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const results = fuse.search(searchValue);
|
const results = fuse.search(searchValue);
|
||||||
console.debug('Characters fuzzy search results for ' + searchValue, results);
|
|
||||||
|
// Store in cache if provided
|
||||||
|
if (fuzzySearchCaches) {
|
||||||
|
fuzzySearchCaches[type].resultMap.set(searchValue, results);
|
||||||
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fuzzy search characters by a search term
|
||||||
|
* @param {string} searchValue - The search term
|
||||||
|
* @param {Object.<string, { resultMap: Map<string, any> }>} [fuzzySearchCaches=null] - Optional fuzzy search caches
|
||||||
|
* @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
|
||||||
|
*/
|
||||||
|
export function fuzzySearchCharacters(searchValue, fuzzySearchCaches = null) {
|
||||||
|
const keys = [
|
||||||
|
{ name: 'data.name', weight: 20 },
|
||||||
|
{ name: '#tags', weight: 10, getFn: (character) => getTagsList(character.avatar).map(x => x.name).join('||') },
|
||||||
|
{ name: 'data.description', weight: 3 },
|
||||||
|
{ name: 'data.mes_example', weight: 3 },
|
||||||
|
{ name: 'data.scenario', weight: 2 },
|
||||||
|
{ name: 'data.personality', weight: 2 },
|
||||||
|
{ name: 'data.first_mes', weight: 2 },
|
||||||
|
{ name: 'data.creator_notes', weight: 2 },
|
||||||
|
{ name: 'data.creator', weight: 1 },
|
||||||
|
{ name: 'data.tags', weight: 1 },
|
||||||
|
{ name: 'data.alternate_greetings', weight: 1 },
|
||||||
|
];
|
||||||
|
|
||||||
|
return performFuzzySearch(fuzzySearchCategories.characters, characters, keys, searchValue, fuzzySearchCaches);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fuzzy search world info entries by a search term
|
* Fuzzy search world info entries by a search term
|
||||||
* @param {*[]} data - WI items data array
|
* @param {*[]} data - WI items data array
|
||||||
* @param {string} searchValue - The search term
|
* @param {string} searchValue - The search term
|
||||||
|
* @param {Object.<string, { resultMap: Map<string, any> }>} [fuzzySearchCaches=null] - Optional fuzzy search caches
|
||||||
* @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
|
* @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
|
||||||
*/
|
*/
|
||||||
export function fuzzySearchWorldInfo(data, searchValue) {
|
export function fuzzySearchWorldInfo(data, searchValue, fuzzySearchCaches = null) {
|
||||||
// @ts-ignore
|
const keys = [
|
||||||
const fuse = new Fuse(data, {
|
{ name: 'key', weight: 20 },
|
||||||
keys: [
|
{ name: 'group', weight: 15 },
|
||||||
{ name: 'key', weight: 20 },
|
{ name: 'comment', weight: 10 },
|
||||||
{ name: 'group', weight: 15 },
|
{ name: 'keysecondary', weight: 10 },
|
||||||
{ name: 'comment', weight: 10 },
|
{ name: 'content', weight: 3 },
|
||||||
{ name: 'keysecondary', weight: 10 },
|
{ name: 'uid', weight: 1 },
|
||||||
{ name: 'content', weight: 3 },
|
{ name: 'automationId', weight: 1 },
|
||||||
{ name: 'uid', weight: 1 },
|
];
|
||||||
{ name: 'automationId', weight: 1 },
|
|
||||||
],
|
|
||||||
includeScore: true,
|
|
||||||
ignoreLocation: true,
|
|
||||||
useExtendedSearch: true,
|
|
||||||
threshold: 0.2,
|
|
||||||
});
|
|
||||||
|
|
||||||
const results = fuse.search(searchValue);
|
return performFuzzySearch(fuzzySearchCategories.worldInfo, data, keys, searchValue, fuzzySearchCaches);
|
||||||
console.debug('World Info fuzzy search results for ' + searchValue, results);
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fuzzy search persona entries by a search term
|
* Fuzzy search persona entries by a search term
|
||||||
* @param {*[]} data - persona data array
|
* @param {*[]} data - persona data array
|
||||||
* @param {string} searchValue - The search term
|
* @param {string} searchValue - The search term
|
||||||
|
* @param {Object.<string, { resultMap: Map<string, any> }>} [fuzzySearchCaches=null] - Optional fuzzy search caches
|
||||||
* @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
|
* @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
|
||||||
*/
|
*/
|
||||||
export function fuzzySearchPersonas(data, searchValue) {
|
export function fuzzySearchPersonas(data, searchValue, fuzzySearchCaches = null) {
|
||||||
data = data.map(x => ({ key: x, name: power_user.personas[x] ?? '', description: power_user.persona_descriptions[x]?.description ?? '' }));
|
const mappedData = data.map(x => ({
|
||||||
// @ts-ignore
|
key: x,
|
||||||
const fuse = new Fuse(data, {
|
name: power_user.personas[x] ?? '',
|
||||||
keys: [
|
description: power_user.persona_descriptions[x]?.description ?? ''
|
||||||
{ name: 'name', weight: 20 },
|
}));
|
||||||
{ name: 'description', weight: 3 },
|
|
||||||
],
|
|
||||||
includeScore: true,
|
|
||||||
ignoreLocation: true,
|
|
||||||
useExtendedSearch: true,
|
|
||||||
threshold: 0.2,
|
|
||||||
});
|
|
||||||
|
|
||||||
const results = fuse.search(searchValue);
|
const keys = [
|
||||||
console.debug('Personas fuzzy search results for ' + searchValue, results);
|
{ name: 'name', weight: 20 },
|
||||||
return results;
|
{ name: 'description', weight: 3 },
|
||||||
|
];
|
||||||
|
|
||||||
|
return performFuzzySearch(fuzzySearchCategories.personas, mappedData, keys, searchValue, fuzzySearchCaches);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fuzzy search tags by a search term
|
* Fuzzy search tags by a search term
|
||||||
* @param {string} searchValue - The search term
|
* @param {string} searchValue - The search term
|
||||||
|
* @param {Object.<string, { resultMap: Map<string, any> }>} [fuzzySearchCaches=null] - Optional fuzzy search caches
|
||||||
* @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
|
* @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
|
||||||
*/
|
*/
|
||||||
export function fuzzySearchTags(searchValue) {
|
export function fuzzySearchTags(searchValue, fuzzySearchCaches = null) {
|
||||||
// @ts-ignore
|
const keys = [
|
||||||
const fuse = new Fuse(tags, {
|
{ name: 'name', weight: 1 },
|
||||||
keys: [
|
];
|
||||||
{ name: 'name', weight: 1 },
|
|
||||||
],
|
|
||||||
includeScore: true,
|
|
||||||
ignoreLocation: true,
|
|
||||||
useExtendedSearch: true,
|
|
||||||
threshold: 0.2,
|
|
||||||
});
|
|
||||||
|
|
||||||
const results = fuse.search(searchValue);
|
return performFuzzySearch(fuzzySearchCategories.tags, tags, keys, searchValue, fuzzySearchCaches);
|
||||||
console.debug('Tags fuzzy search results for ' + searchValue, results);
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fuzzy search groups by a search term
|
* Fuzzy search groups by a search term
|
||||||
* @param {string} searchValue - The search term
|
* @param {string} searchValue - The search term
|
||||||
|
* @param {Object.<string, { resultMap: Map<string, any> }>} [fuzzySearchCaches=null] - Optional fuzzy search caches
|
||||||
* @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
|
* @returns {import('fuse.js').FuseResult<any>[]} Results as items with their score
|
||||||
*/
|
*/
|
||||||
export function fuzzySearchGroups(searchValue) {
|
export function fuzzySearchGroups(searchValue, fuzzySearchCaches = null) {
|
||||||
// @ts-ignore
|
const keys = [
|
||||||
const fuse = new Fuse(groups, {
|
{ name: 'name', weight: 20 },
|
||||||
keys: [
|
{ name: 'members', weight: 15 },
|
||||||
{ name: 'name', weight: 20 },
|
{ name: '#tags', weight: 10, getFn: (group) => getTagsList(group.id).map(x => x.name).join('||') },
|
||||||
{ name: 'members', weight: 15 },
|
{ name: 'id', weight: 1 },
|
||||||
{ name: '#tags', weight: 10, getFn: (group) => getTagsList(group.id).map(x => x.name).join('||') },
|
];
|
||||||
{ name: 'id', weight: 1 },
|
|
||||||
],
|
|
||||||
includeScore: true,
|
|
||||||
ignoreLocation: true,
|
|
||||||
useExtendedSearch: true,
|
|
||||||
threshold: 0.2,
|
|
||||||
});
|
|
||||||
|
|
||||||
const results = fuse.search(searchValue);
|
return performFuzzySearch(fuzzySearchCategories.groups, groups, keys, searchValue, fuzzySearchCaches);
|
||||||
console.debug('Groups fuzzy search results for ' + searchValue, results);
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1258,6 +1258,7 @@ export function getTextGenGenerationData(finalPrompt, maxTokens, isImpersonate,
|
|||||||
'xtc_probability': settings.xtc_probability,
|
'xtc_probability': settings.xtc_probability,
|
||||||
'nsigma': settings.nsigma,
|
'nsigma': settings.nsigma,
|
||||||
'custom_token_bans': toIntArray(banned_tokens),
|
'custom_token_bans': toIntArray(banned_tokens),
|
||||||
|
'no_repeat_ngram_size': settings.no_repeat_ngram_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (settings.type === OPENROUTER) {
|
if (settings.type === OPENROUTER) {
|
||||||
|
@ -627,10 +627,6 @@ const tavernUrl = new URL(
|
|||||||
(':' + server_port),
|
(':' + server_port),
|
||||||
);
|
);
|
||||||
|
|
||||||
function prepareFrontendBundle() {
|
|
||||||
return new Promise((resolve) => webpackMiddleware.waitUntilValid(resolve));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tasks that need to be run before the server starts listening.
|
* Tasks that need to be run before the server starts listening.
|
||||||
*/
|
*/
|
||||||
@ -682,7 +678,7 @@ const preSetupTasks = async function () {
|
|||||||
initRequestProxy({ enabled: proxyEnabled, url: proxyUrl, bypass: proxyBypass });
|
initRequestProxy({ enabled: proxyEnabled, url: proxyUrl, bypass: proxyBypass });
|
||||||
|
|
||||||
// Wait for frontend libs to compile
|
// Wait for frontend libs to compile
|
||||||
await prepareFrontendBundle();
|
await webpackMiddleware.runWebpackCompiler();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -102,7 +102,7 @@ async function sendClaudeRequest(request, response) {
|
|||||||
const additionalHeaders = {};
|
const additionalHeaders = {};
|
||||||
const useTools = request.body.model.startsWith('claude-3') && Array.isArray(request.body.tools) && request.body.tools.length > 0;
|
const useTools = request.body.model.startsWith('claude-3') && Array.isArray(request.body.tools) && request.body.tools.length > 0;
|
||||||
const useSystemPrompt = (request.body.model.startsWith('claude-2') || request.body.model.startsWith('claude-3')) && request.body.claude_use_sysprompt;
|
const useSystemPrompt = (request.body.model.startsWith('claude-2') || request.body.model.startsWith('claude-3')) && request.body.claude_use_sysprompt;
|
||||||
const convertedPrompt = convertClaudeMessages(request.body.messages, request.body.assistant_prefill, useSystemPrompt, useTools, request.body.human_sysprompt_message, request.body.char_name, request.body.user_name);
|
const convertedPrompt = convertClaudeMessages(request.body.messages, request.body.assistant_prefill, useSystemPrompt, useTools, request.body.char_name, request.body.user_name);
|
||||||
// Add custom stop sequences
|
// Add custom stop sequences
|
||||||
const stopSequences = [];
|
const stopSequences = [];
|
||||||
if (Array.isArray(request.body.stop)) {
|
if (Array.isArray(request.body.stop)) {
|
||||||
|
@ -14,7 +14,7 @@ import jimp from 'jimp';
|
|||||||
|
|
||||||
import { AVATAR_WIDTH, AVATAR_HEIGHT } from '../constants.js';
|
import { AVATAR_WIDTH, AVATAR_HEIGHT } from '../constants.js';
|
||||||
import { jsonParser, urlencodedParser } from '../express-common.js';
|
import { jsonParser, urlencodedParser } from '../express-common.js';
|
||||||
import { deepMerge, humanizedISO8601DateTime, tryParse, extractFileFromZipBuffer } from '../util.js';
|
import { deepMerge, humanizedISO8601DateTime, tryParse, extractFileFromZipBuffer, MemoryLimitedMap } from '../util.js';
|
||||||
import { TavernCardValidator } from '../validator/TavernCardValidator.js';
|
import { TavernCardValidator } from '../validator/TavernCardValidator.js';
|
||||||
import { parse, write } from '../character-card-parser.js';
|
import { parse, write } from '../character-card-parser.js';
|
||||||
import { readWorldInfoFile } from './worldinfo.js';
|
import { readWorldInfoFile } from './worldinfo.js';
|
||||||
@ -23,7 +23,8 @@ import { importRisuSprites } from './sprites.js';
|
|||||||
const defaultAvatarPath = './public/img/ai4.png';
|
const defaultAvatarPath = './public/img/ai4.png';
|
||||||
|
|
||||||
// KV-store for parsed character data
|
// KV-store for parsed character data
|
||||||
const characterDataCache = new Map();
|
// 100 MB limit. Would take roughly 3000 characters to reach this limit
|
||||||
|
const characterDataCache = new MemoryLimitedMap(1024 * 1024 * 100);
|
||||||
// Some Android devices require tighter memory management
|
// Some Android devices require tighter memory management
|
||||||
const isAndroid = process.platform === 'android';
|
const isAndroid = process.platform === 'android';
|
||||||
|
|
||||||
@ -58,6 +59,9 @@ async function writeCharacterData(inputFile, data, outputFile, request, crop = u
|
|||||||
try {
|
try {
|
||||||
// Reset the cache
|
// Reset the cache
|
||||||
for (const key of characterDataCache.keys()) {
|
for (const key of characterDataCache.keys()) {
|
||||||
|
if (Buffer.isBuffer(inputFile)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (key.startsWith(inputFile)) {
|
if (key.startsWith(inputFile)) {
|
||||||
characterDataCache.delete(key);
|
characterDataCache.delete(key);
|
||||||
break;
|
break;
|
||||||
|
@ -1,20 +1,45 @@
|
|||||||
import process from 'node:process';
|
import path from 'node:path';
|
||||||
import webpack from 'webpack';
|
import webpack from 'webpack';
|
||||||
import middleware from 'webpack-dev-middleware';
|
|
||||||
import { publicLibConfig } from '../../webpack.config.js';
|
import { publicLibConfig } from '../../webpack.config.js';
|
||||||
|
|
||||||
export default function getWebpackServeMiddleware() {
|
export default function getWebpackServeMiddleware() {
|
||||||
|
const outputPath = publicLibConfig.output?.path;
|
||||||
|
const outputFile = publicLibConfig.output?.filename;
|
||||||
const compiler = webpack(publicLibConfig);
|
const compiler = webpack(publicLibConfig);
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'production' || process.platform === 'android') {
|
/**
|
||||||
compiler.hooks.done.tap('serve', () => {
|
* A very spartan recreation of webpack-dev-middleware.
|
||||||
if (compiler.watching) {
|
* @param {import('express').Request} req Request object.
|
||||||
compiler.watching.close(() => { });
|
* @param {import('express').Response} res Response object.
|
||||||
}
|
* @param {import('express').NextFunction} next Next function.
|
||||||
compiler.watchFileSystem = null;
|
* @type {import('express').RequestHandler}
|
||||||
compiler.watchMode = false;
|
*/
|
||||||
});
|
function devMiddleware(req, res, next) {
|
||||||
|
if (req.method === 'GET' && path.parse(req.path).base === outputFile) {
|
||||||
|
return res.sendFile(outputFile, { root: outputPath });
|
||||||
|
}
|
||||||
|
|
||||||
|
next();
|
||||||
}
|
}
|
||||||
|
|
||||||
return middleware(compiler, {});
|
/**
|
||||||
|
* Wait until Webpack is done compiling.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
devMiddleware.runWebpackCompiler = () => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
console.log();
|
||||||
|
console.log('Compiling frontend libraries...');
|
||||||
|
compiler.run((_error, stats) => {
|
||||||
|
const output = stats?.toString(publicLibConfig.stats);
|
||||||
|
if (output) {
|
||||||
|
console.log(output);
|
||||||
|
console.log();
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return devMiddleware;
|
||||||
}
|
}
|
||||||
|
@ -91,11 +91,10 @@ export function convertClaudePrompt(messages, addAssistantPostfix, addAssistantP
|
|||||||
* @param {string} prefillString User determined prefill string
|
* @param {string} prefillString User determined prefill string
|
||||||
* @param {boolean} useSysPrompt See if we want to use a system prompt
|
* @param {boolean} useSysPrompt See if we want to use a system prompt
|
||||||
* @param {boolean} useTools See if we want to use tools
|
* @param {boolean} useTools See if we want to use tools
|
||||||
* @param {string} humanMsgFix Add Human message between system prompt and assistant.
|
|
||||||
* @param {string} charName Character name
|
* @param {string} charName Character name
|
||||||
* @param {string} userName User name
|
* @param {string} userName User name
|
||||||
*/
|
*/
|
||||||
export function convertClaudeMessages(messages, prefillString, useSysPrompt, useTools, humanMsgFix, charName = '', userName = '') {
|
export function convertClaudeMessages(messages, prefillString, useSysPrompt, useTools, charName, userName) {
|
||||||
let systemPrompt = [];
|
let systemPrompt = [];
|
||||||
if (useSysPrompt) {
|
if (useSysPrompt) {
|
||||||
// Collect all the system messages up until the first instance of a non-system message, and then remove them from the messages array.
|
// Collect all the system messages up until the first instance of a non-system message, and then remove them from the messages array.
|
||||||
@ -122,10 +121,10 @@ export function convertClaudeMessages(messages, prefillString, useSysPrompt, use
|
|||||||
|
|
||||||
// Check if the first message in the array is of type user, if not, interject with humanMsgFix or a blank message.
|
// Check if the first message in the array is of type user, if not, interject with humanMsgFix or a blank message.
|
||||||
// Also prevents erroring out if the messages array is empty.
|
// Also prevents erroring out if the messages array is empty.
|
||||||
if (messages.length === 0 || (messages.length > 0 && messages[0].role !== 'user')) {
|
if (messages.length === 0) {
|
||||||
messages.unshift({
|
messages.unshift({
|
||||||
role: 'user',
|
role: 'user',
|
||||||
content: humanMsgFix || PROMPT_PLACEHOLDER,
|
content: PROMPT_PLACEHOLDER,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
179
src/util.js
179
src/util.js
@ -670,3 +670,182 @@ export function isValidUrl(url) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MemoryLimitedMap class that limits the memory usage of string values.
|
||||||
|
*/
|
||||||
|
export class MemoryLimitedMap {
|
||||||
|
/**
|
||||||
|
* Creates an instance of MemoryLimitedMap.
|
||||||
|
* @param {number} maxMemoryInBytes - The maximum allowed memory in bytes for string values.
|
||||||
|
*/
|
||||||
|
constructor(maxMemoryInBytes) {
|
||||||
|
if (typeof maxMemoryInBytes !== 'number' || maxMemoryInBytes <= 0) {
|
||||||
|
throw new Error('maxMemoryInBytes must be a positive number');
|
||||||
|
}
|
||||||
|
this.maxMemory = maxMemoryInBytes;
|
||||||
|
this.currentMemory = 0;
|
||||||
|
this.map = new Map();
|
||||||
|
this.queue = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Estimates the memory usage of a string in bytes.
|
||||||
|
* Assumes each character occupies 2 bytes (UTF-16).
|
||||||
|
* @param {string} str
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
static estimateStringSize(str) {
|
||||||
|
return str ? str.length * 2 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds or updates a key-value pair in the map.
|
||||||
|
* If adding the new value exceeds the memory limit, evicts oldest entries.
|
||||||
|
* @param {string} key
|
||||||
|
* @param {string} value
|
||||||
|
*/
|
||||||
|
set(key, value) {
|
||||||
|
if (typeof key !== 'string' || typeof value !== 'string') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newValueSize = MemoryLimitedMap.estimateStringSize(value);
|
||||||
|
|
||||||
|
// If the new value itself exceeds the max memory, reject it
|
||||||
|
if (newValueSize > this.maxMemory) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the key already exists to adjust memory accordingly
|
||||||
|
if (this.map.has(key)) {
|
||||||
|
const oldValue = this.map.get(key);
|
||||||
|
const oldValueSize = MemoryLimitedMap.estimateStringSize(oldValue);
|
||||||
|
this.currentMemory -= oldValueSize;
|
||||||
|
// Remove the key from its current position in the queue
|
||||||
|
const index = this.queue.indexOf(key);
|
||||||
|
if (index > -1) {
|
||||||
|
this.queue.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evict oldest entries until there's enough space
|
||||||
|
while (this.currentMemory + newValueSize > this.maxMemory && this.queue.length > 0) {
|
||||||
|
const oldestKey = this.queue.shift();
|
||||||
|
const oldestValue = this.map.get(oldestKey);
|
||||||
|
const oldestValueSize = MemoryLimitedMap.estimateStringSize(oldestValue);
|
||||||
|
this.map.delete(oldestKey);
|
||||||
|
this.currentMemory -= oldestValueSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// After eviction, check again if there's enough space
|
||||||
|
if (this.currentMemory + newValueSize > this.maxMemory) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the new key-value pair
|
||||||
|
this.map.set(key, value);
|
||||||
|
this.queue.push(key);
|
||||||
|
this.currentMemory += newValueSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the value associated with the given key.
|
||||||
|
* @param {string} key
|
||||||
|
* @returns {string | undefined}
|
||||||
|
*/
|
||||||
|
get(key) {
|
||||||
|
return this.map.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the map contains the given key.
|
||||||
|
* @param {string} key
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
has(key) {
|
||||||
|
return this.map.has(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes the key-value pair associated with the given key.
|
||||||
|
* @param {string} key
|
||||||
|
* @returns {boolean} - Returns true if the key was found and deleted, else false.
|
||||||
|
*/
|
||||||
|
delete(key) {
|
||||||
|
if (!this.map.has(key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const value = this.map.get(key);
|
||||||
|
const valueSize = MemoryLimitedMap.estimateStringSize(value);
|
||||||
|
this.map.delete(key);
|
||||||
|
this.currentMemory -= valueSize;
|
||||||
|
|
||||||
|
// Remove the key from the queue
|
||||||
|
const index = this.queue.indexOf(key);
|
||||||
|
if (index > -1) {
|
||||||
|
this.queue.splice(index, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears all entries from the map.
|
||||||
|
*/
|
||||||
|
clear() {
|
||||||
|
this.map.clear();
|
||||||
|
this.queue = [];
|
||||||
|
this.currentMemory = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of key-value pairs in the map.
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
size() {
|
||||||
|
return this.map.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current memory usage in bytes.
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
totalMemory() {
|
||||||
|
return this.currentMemory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an iterator over the keys in the map.
|
||||||
|
* @returns {IterableIterator<string>}
|
||||||
|
*/
|
||||||
|
keys() {
|
||||||
|
return this.map.keys();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an iterator over the values in the map.
|
||||||
|
* @returns {IterableIterator<string>}
|
||||||
|
*/
|
||||||
|
values() {
|
||||||
|
return this.map.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Iterates over the map in insertion order.
|
||||||
|
* @param {Function} callback - Function to execute for each element.
|
||||||
|
*/
|
||||||
|
forEach(callback) {
|
||||||
|
this.map.forEach((value, key) => {
|
||||||
|
callback(value, key, this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes the MemoryLimitedMap iterable.
|
||||||
|
* @returns {Iterator} - Iterator over [key, value] pairs.
|
||||||
|
*/
|
||||||
|
[Symbol.iterator]() {
|
||||||
|
return this.map[Symbol.iterator]();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -8,6 +8,8 @@ export const publicLibConfig = {
|
|||||||
cache: {
|
cache: {
|
||||||
type: 'filesystem',
|
type: 'filesystem',
|
||||||
cacheDirectory: path.resolve(process.cwd(), 'dist/webpack'),
|
cacheDirectory: path.resolve(process.cwd(), 'dist/webpack'),
|
||||||
|
store: 'pack',
|
||||||
|
compression: 'gzip',
|
||||||
},
|
},
|
||||||
devtool: false,
|
devtool: false,
|
||||||
watch: false,
|
watch: false,
|
||||||
@ -16,6 +18,8 @@ export const publicLibConfig = {
|
|||||||
preset: 'minimal',
|
preset: 'minimal',
|
||||||
assets: false,
|
assets: false,
|
||||||
modules: false,
|
modules: false,
|
||||||
|
colors: true,
|
||||||
|
timings: true,
|
||||||
},
|
},
|
||||||
experiments: {
|
experiments: {
|
||||||
outputModule: true,
|
outputModule: true,
|
||||||
@ -24,6 +28,7 @@ export const publicLibConfig = {
|
|||||||
hints: false,
|
hints: false,
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
|
path: path.resolve(process.cwd(), 'dist'),
|
||||||
filename: 'lib.js',
|
filename: 'lib.js',
|
||||||
libraryTarget: 'module',
|
libraryTarget: 'module',
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user