sillytavern 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +4 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +35 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- package/.github/workflows/npm-publish.yml +32 -0
- package/Dockerfile +49 -0
- package/Start.bat +3 -0
- package/colab/GPU.ipynb +339 -0
- package/colab/extras_server.py +40 -0
- package/colab/globals.py +2 -0
- package/colab/models.py +77 -0
- package/docker/docker-compose.yml +12 -0
- package/docker/docker-entrypoint.sh +28 -0
- package/faq.md +208 -0
- package/package.json +49 -0
- package/poe-client.js +638 -0
- package/poe-test.js +21 -0
- package/poe_graphql/AddHumanMessageMutation.graphql +52 -0
- package/poe_graphql/AddMessageBreakMutation.graphql +17 -0
- package/poe_graphql/AutoSubscriptionMutation.graphql +7 -0
- package/poe_graphql/BioFragment.graphql +8 -0
- package/poe_graphql/ChatAddedSubscription.graphql +5 -0
- package/poe_graphql/ChatFragment.graphql +6 -0
- package/poe_graphql/ChatListPaginationQuery.graphql +316 -0
- package/poe_graphql/ChatPaginationQuery.graphql +26 -0
- package/poe_graphql/ChatViewQuery.graphql +8 -0
- package/poe_graphql/DeleteHumanMessagesMutation.graphql +7 -0
- package/poe_graphql/DeleteMessageMutation.graphql +7 -0
- package/poe_graphql/HandleFragment.graphql +8 -0
- package/poe_graphql/LoginWithVerificationCodeMutation.graphql +13 -0
- package/poe_graphql/MessageAddedSubscription.graphql +115 -0
- package/poe_graphql/MessageDeletedSubscription.graphql +8 -0
- package/poe_graphql/MessageFragment.graphql +13 -0
- package/poe_graphql/MessageRemoveVoteMutation.graphql +7 -0
- package/poe_graphql/MessageSetVoteMutation.graphql +7 -0
- package/poe_graphql/SendVerificationCodeForLoginMutation.graphql +12 -0
- package/poe_graphql/ShareMessagesMutation.graphql +9 -0
- package/poe_graphql/SignupWithVerificationCodeMutation.graphql +13 -0
- package/poe_graphql/StaleChatUpdateMutation.graphql +7 -0
- package/poe_graphql/SubscriptionsMutation.graphql +9 -0
- package/poe_graphql/SummarizePlainPostQuery.graphql +3 -0
- package/poe_graphql/SummarizeQuotePostQuery.graphql +3 -0
- package/poe_graphql/SummarizeSharePostQuery.graphql +3 -0
- package/poe_graphql/UserSnippetFragment.graphql +14 -0
- package/poe_graphql/ViewerInfoQuery.graphql +21 -0
- package/poe_graphql/ViewerMessageLimitUpdatedSubscription.graphql +81 -0
- package/poe_graphql/ViewerStateFragment.graphql +30 -0
- package/poe_graphql/ViewerStateUpdatedSubscription.graphql +63 -0
- package/public/KoboldAI Settings/Ace of Spades 13B.settings +22 -0
- package/public/KoboldAI Settings/Adventurer-NeoX-20B-Erebus.settings +54 -0
- package/public/KoboldAI Settings/Basic Coherence 13B.settings +22 -0
- package/public/KoboldAI Settings/Best Guess 6B.settings +22 -0
- package/public/KoboldAI Settings/Calibrated-Pygmalion-6b.settings +47 -0
- package/public/KoboldAI Settings/Classic-Pygmalion-2.7b.settings +46 -0
- package/public/KoboldAI Settings/Classic-Pygmalion-6b.settings +47 -0
- package/public/KoboldAI Settings/Coherent Creativity 6B.settings +22 -0
- package/public/KoboldAI Settings/Default-TavernAI.settings +22 -0
- package/public/KoboldAI Settings/DragonSlayer-Pygmalion-6b.settings +47 -0
- package/public/KoboldAI Settings/GPU-Pygmalion-6b.settings +47 -0
- package/public/KoboldAI Settings/Genesis 13B.settings +22 -0
- package/public/KoboldAI Settings/Godlike.settings +22 -0
- package/public/KoboldAI Settings/Good Winds.settings +22 -0
- package/public/KoboldAI Settings/Lancer-OPT-2.7B-Erebus.settings +54 -0
- package/public/KoboldAI Settings/Liminal Drift.settings +22 -0
- package/public/KoboldAI Settings/Low Rider 13B.settings +22 -0
- package/public/KoboldAI Settings/Luna Moth 6B.settings +22 -0
- package/public/KoboldAI Settings/Mayday.settings +22 -0
- package/public/KoboldAI Settings/Ouroboros.settings +22 -0
- package/public/KoboldAI Settings/Pleasing Results 6B.settings +22 -0
- package/public/KoboldAI Settings/Pro Writer 13B.settings +22 -0
- package/public/KoboldAI Settings/RA - Pygmalion-1.3b.settings +46 -0
- package/public/KoboldAI Settings/Storywriter 6B.settings +22 -0
- package/public/NovelAI Settings/Classic-Euterpe.settings +14 -0
- package/public/NovelAI Settings/Classic-Krake.settings +14 -0
- package/public/OpenAI Settings/Default.settings +15 -0
- package/public/TextGen Settings/Beam Search.settings +15 -0
- package/public/TextGen Settings/Contrastive Search.settings +15 -0
- package/public/TextGen Settings/Default.settings +15 -0
- package/public/TextGen Settings/Deterministic.settings +15 -0
- package/public/TextGen Settings/Kobold (Godlike).settings +15 -0
- package/public/TextGen Settings/Kobold (Liminal Drift).settings +15 -0
- package/public/TextGen Settings/Naive.settings +15 -0
- package/public/TextGen Settings/NovelAI (Best Guess).settings +15 -0
- package/public/TextGen Settings/NovelAI (Decadence).settings +15 -0
- package/public/TextGen Settings/NovelAI (Genesis).settings +15 -0
- package/public/TextGen Settings/NovelAI (Lycaenidae).settings +15 -0
- package/public/TextGen Settings/NovelAI (Ouroboros).settings +15 -0
- package/public/TextGen Settings/NovelAI (Pleasing Results).settings +15 -0
- package/public/TextGen Settings/NovelAI (Sphinx Moth).settings +15 -0
- package/public/TextGen Settings/NovelAI (Storywriter).settings +15 -0
- package/public/TextGen Settings/Pygmalion.settings +15 -0
- package/public/css/fontawesome.css +8488 -0
- package/public/css/notes.css +46 -0
- package/public/css/solid.css +24 -0
- package/public/favicon.ico +0 -0
- package/public/img/No-Image-Placeholder.svg +309 -0
- package/public/img/addbg3.png +0 -0
- package/public/img/ai4.png +0 -0
- package/public/img/apple-icon-114x114.png +0 -0
- package/public/img/apple-icon-144x144.png +0 -0
- package/public/img/apple-icon-57x57.png +0 -0
- package/public/img/apple-icon-72x72.png +0 -0
- package/public/img/book2.png +0 -0
- package/public/img/default-expressions/admiration.png +0 -0
- package/public/img/default-expressions/amusement.png +0 -0
- package/public/img/default-expressions/anger.png +0 -0
- package/public/img/default-expressions/annoyance.png +0 -0
- package/public/img/default-expressions/approval.png +0 -0
- package/public/img/default-expressions/caring.png +0 -0
- package/public/img/default-expressions/confusion.png +0 -0
- package/public/img/default-expressions/curiosity.png +0 -0
- package/public/img/default-expressions/desire.png +0 -0
- package/public/img/default-expressions/desire1.png +0 -0
- package/public/img/default-expressions/desire2.png +0 -0
- package/public/img/default-expressions/disappointment.png +0 -0
- package/public/img/default-expressions/disapproval.png +0 -0
- package/public/img/default-expressions/disgust.png +0 -0
- package/public/img/default-expressions/embarrassment.png +0 -0
- package/public/img/default-expressions/excitement.png +0 -0
- package/public/img/default-expressions/fear.png +0 -0
- package/public/img/default-expressions/gratitude.png +0 -0
- package/public/img/default-expressions/grief.png +0 -0
- package/public/img/default-expressions/joy.png +0 -0
- package/public/img/default-expressions/love.png +0 -0
- package/public/img/default-expressions/nervousness.png +0 -0
- package/public/img/default-expressions/neutral.png +0 -0
- package/public/img/default-expressions/optimism.png +0 -0
- package/public/img/default-expressions/pride.png +0 -0
- package/public/img/default-expressions/realization.png +0 -0
- package/public/img/default-expressions/relief.png +0 -0
- package/public/img/default-expressions/remorse.png +0 -0
- package/public/img/default-expressions/sadness.png +0 -0
- package/public/img/default-expressions/surprise.png +0 -0
- package/public/img/five.png +0 -0
- package/public/img/times-circle.svg +1 -0
- package/public/img/you.png +0 -0
- package/public/index.html +1899 -0
- package/public/notes/1.html +44 -0
- package/public/notes/1.png +0 -0
- package/public/notes/10.html +20 -0
- package/public/notes/11.html +33 -0
- package/public/notes/12.html +27 -0
- package/public/notes/13.html +29 -0
- package/public/notes/13_1.html +24 -0
- package/public/notes/13_2.html +25 -0
- package/public/notes/13_3.html +89 -0
- package/public/notes/14.html +30 -0
- package/public/notes/2.html +37 -0
- package/public/notes/2.png +0 -0
- package/public/notes/3.html +37 -0
- package/public/notes/4.html +105 -0
- package/public/notes/6.html +33 -0
- package/public/notes/7.html +40 -0
- package/public/notes/8.html +19 -0
- package/public/notes/9.html +46 -0
- package/public/notes/advanced_formatting.html +91 -0
- package/public/notes/group_reply_strategy.html +63 -0
- package/public/notes/message_sound.html +33 -0
- package/public/notes/multigen.html +36 -0
- package/public/notes/oai_api_key.html +37 -0
- package/public/notes/textgen_streaming.html +29 -0
- package/public/notes/token-limits.html +68 -0
- package/public/script.js +5131 -0
- package/public/scripts/RossAscends-mods.js +750 -0
- package/public/scripts/bookmarks.js +130 -0
- package/public/scripts/extensions/backgrounds/index.js +129 -0
- package/public/scripts/extensions/backgrounds/manifest.json +11 -0
- package/public/scripts/extensions/backgrounds/style.css +45 -0
- package/public/scripts/extensions/caption/index.js +117 -0
- package/public/scripts/extensions/caption/manifest.json +13 -0
- package/public/scripts/extensions/caption/style.css +23 -0
- package/public/scripts/extensions/dice/droll.js +108 -0
- package/public/scripts/extensions/dice/index.js +96 -0
- package/public/scripts/extensions/dice/manifest.json +11 -0
- package/public/scripts/extensions/dice/style.css +26 -0
- package/public/scripts/extensions/expressions/index.js +387 -0
- package/public/scripts/extensions/expressions/manifest.json +13 -0
- package/public/scripts/extensions/expressions/style.css +115 -0
- package/public/scripts/extensions/floating-prompt/index.js +151 -0
- package/public/scripts/extensions/floating-prompt/manifest.json +11 -0
- package/public/scripts/extensions/floating-prompt/style.css +19 -0
- package/public/scripts/extensions/memory/index.js +358 -0
- package/public/scripts/extensions/memory/manifest.json +13 -0
- package/public/scripts/extensions/memory/style.css +34 -0
- package/public/scripts/extensions.js +288 -0
- package/public/scripts/f-localStorage.js +27 -0
- package/public/scripts/gpt-2-3-tokenizer/README.md +28 -0
- package/public/scripts/gpt-2-3-tokenizer/encoder.js +1 -0
- package/public/scripts/gpt-2-3-tokenizer/mod.js +169 -0
- package/public/scripts/gpt-2-3-tokenizer/vocab.bpe.js +1 -0
- package/public/scripts/gpt-3-tokenizer/array-keyed-map.js +210 -0
- package/public/scripts/gpt-3-tokenizer/gpt3-tokenizer.js +271 -0
- package/public/scripts/gpt-3-tokenizer/gpt3-tokenizer.js.map +1 -0
- package/public/scripts/group-chats.js +899 -0
- package/public/scripts/horde.js +214 -0
- package/public/scripts/jquery-3.5.1.min.js +2 -0
- package/public/scripts/jquery-cookie-1.4.1.min.js +2 -0
- package/public/scripts/jquery.transit.min.js +1 -0
- package/public/scripts/kai-settings.js +179 -0
- package/public/scripts/nai-settings.js +108 -0
- package/public/scripts/openai.js +973 -0
- package/public/scripts/poe.js +360 -0
- package/public/scripts/popper.js +2008 -0
- package/public/scripts/popper.js.map +1 -0
- package/public/scripts/power-user.js +571 -0
- package/public/scripts/purify.min.js +3 -0
- package/public/scripts/purify.min.js.map +1 -0
- package/public/scripts/showdown.min.js +3 -0
- package/public/scripts/showdown.min.js.map +1 -0
- package/public/scripts/swiped-events.js +165 -0
- package/public/scripts/textgen-settings.js +194 -0
- package/public/scripts/toolcool-color-picker.js +87 -0
- package/public/scripts/utils.js +109 -0
- package/public/scripts/world-info.js +661 -0
- package/public/sounds/message.mp3 +0 -0
- package/public/style.css +3633 -0
- package/public/webfonts/NotoSans/NotoSans-Black.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-Black.woff2 +0 -0
- package/public/webfonts/NotoSans/NotoSans-BlackItalic.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-BlackItalic.woff2 +0 -0
- package/public/webfonts/NotoSans/NotoSans-Bold.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-Bold.woff2 +0 -0
- package/public/webfonts/NotoSans/NotoSans-BoldItalic.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-BoldItalic.woff2 +0 -0
- package/public/webfonts/NotoSans/NotoSans-ExtraBold.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-ExtraBold.woff2 +0 -0
- package/public/webfonts/NotoSans/NotoSans-ExtraBoldItalic.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-ExtraBoldItalic.woff2 +0 -0
- package/public/webfonts/NotoSans/NotoSans-ExtraLight.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-ExtraLight.woff2 +0 -0
- package/public/webfonts/NotoSans/NotoSans-ExtraLightItalic.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-ExtraLightItalic.woff2 +0 -0
- package/public/webfonts/NotoSans/NotoSans-Italic.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-Italic.woff2 +0 -0
- package/public/webfonts/NotoSans/NotoSans-Light.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-Light.woff2 +0 -0
- package/public/webfonts/NotoSans/NotoSans-LightItalic.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-LightItalic.woff2 +0 -0
- package/public/webfonts/NotoSans/NotoSans-Medium.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-Medium.woff2 +0 -0
- package/public/webfonts/NotoSans/NotoSans-MediumItalic.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-MediumItalic.woff2 +0 -0
- package/public/webfonts/NotoSans/NotoSans-Regular.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-Regular.woff2 +0 -0
- package/public/webfonts/NotoSans/NotoSans-SemiBold.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-SemiBold.woff2 +0 -0
- package/public/webfonts/NotoSans/NotoSans-SemiBoldItalic.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-SemiBoldItalic.woff2 +0 -0
- package/public/webfonts/NotoSans/NotoSans-Thin.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-Thin.woff2 +0 -0
- package/public/webfonts/NotoSans/NotoSans-ThinItalic.woff +0 -0
- package/public/webfonts/NotoSans/NotoSans-ThinItalic.woff2 +0 -0
- package/public/webfonts/NotoSans/stylesheet.css +162 -0
- package/public/webfonts/fa-solid-900.ttf +0 -0
- package/public/webfonts/fa-solid-900.woff2 +0 -0
- package/readme.md +187 -0
- package/server.js +2593 -0
- package/start.sh +24 -0
- package/tools/charaverter/main.mjs +110 -0
- package/tools/charaverter/package.json +10 -0
|
@@ -0,0 +1,661 @@
|
|
|
1
|
+
import { saveSettings, callPopup, token, substituteParams, getTokenCount } from "../script.js";
|
|
2
|
+
import { download, debounce } from "./utils.js";
|
|
3
|
+
|
|
4
|
+
export {
|
|
5
|
+
world_info,
|
|
6
|
+
world_info_data,
|
|
7
|
+
world_info_budget,
|
|
8
|
+
world_info_depth,
|
|
9
|
+
world_names,
|
|
10
|
+
imported_world_name,
|
|
11
|
+
checkWorldInfo,
|
|
12
|
+
deleteWorldInfo,
|
|
13
|
+
selectImportedWorldInfo,
|
|
14
|
+
setWorldInfoSettings,
|
|
15
|
+
getWorldInfoPrompt,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let world_info = null;
|
|
19
|
+
let world_names;
|
|
20
|
+
let world_info_data = null;
|
|
21
|
+
let world_info_depth = 2;
|
|
22
|
+
let world_info_budget = 128;
|
|
23
|
+
let is_world_edit_open = false;
|
|
24
|
+
let imported_world_name = "";
|
|
25
|
+
const saveWorldDebounced = debounce(async () => await _save(), 500);
|
|
26
|
+
const saveSettingsDebounced = debounce(() => saveSettings(), 500);
|
|
27
|
+
|
|
28
|
+
const world_info_position = {
|
|
29
|
+
before: 0,
|
|
30
|
+
after: 1,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
function getWorldInfoPrompt(chat2) {
|
|
34
|
+
let worldInfoString = "", worldInfoBefore = "", worldInfoAfter = "";
|
|
35
|
+
|
|
36
|
+
if (world_info && world_info_data) {
|
|
37
|
+
const activatedWorldInfo = checkWorldInfo(chat2);
|
|
38
|
+
worldInfoBefore = activatedWorldInfo.worldInfoBefore;
|
|
39
|
+
worldInfoAfter = activatedWorldInfo.worldInfoAfter;
|
|
40
|
+
worldInfoString = worldInfoBefore + worldInfoAfter;
|
|
41
|
+
}
|
|
42
|
+
return { worldInfoString, worldInfoBefore, worldInfoAfter };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function setWorldInfoSettings(settings, data) {
|
|
46
|
+
if (settings.world_info_depth !== undefined)
|
|
47
|
+
world_info_depth = Number(settings.world_info_depth);
|
|
48
|
+
if (settings.world_info_budget !== undefined)
|
|
49
|
+
world_info_budget = Number(settings.world_info_budget);
|
|
50
|
+
|
|
51
|
+
$("#world_info_depth_counter").html(`${world_info_depth} Messages`);
|
|
52
|
+
$("#world_info_depth").val(world_info_depth);
|
|
53
|
+
|
|
54
|
+
$("#world_info_budget_counter").html(`${world_info_budget} Tokens`);
|
|
55
|
+
$("#world_info_budget").val(world_info_budget);
|
|
56
|
+
|
|
57
|
+
world_names = data.world_names?.length ? data.world_names : [];
|
|
58
|
+
|
|
59
|
+
if (settings.world_info != undefined) {
|
|
60
|
+
if (world_names.includes(settings.world_info)) {
|
|
61
|
+
world_info = settings.world_info;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
world_names.forEach((item, i) => {
|
|
66
|
+
$("#world_info").append(`<option value='${i}'>${item}</option>`);
|
|
67
|
+
// preselect world if saved
|
|
68
|
+
if (item == world_info) {
|
|
69
|
+
$("#world_info").val(i).change();
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// World Info Editor
|
|
75
|
+
async function showWorldEditor() {
|
|
76
|
+
if (!world_info) {
|
|
77
|
+
callPopup("<h3>Select a world info first!</h3>", "text");
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
is_world_edit_open = true;
|
|
82
|
+
$("#world_popup_name").val(world_info);
|
|
83
|
+
$("#world_popup").css("display", "flex");
|
|
84
|
+
await loadWorldInfoData();
|
|
85
|
+
displayWorldEntries(world_info_data);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function loadWorldInfoData() {
|
|
89
|
+
if (!world_info) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const response = await fetch("/getworldinfo", {
|
|
94
|
+
method: "POST",
|
|
95
|
+
headers: {
|
|
96
|
+
"Content-Type": "application/json",
|
|
97
|
+
"X-CSRF-Token": token,
|
|
98
|
+
},
|
|
99
|
+
body: JSON.stringify({ name: world_info }),
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
if (response.ok) {
|
|
103
|
+
world_info_data = await response.json();
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function updateWorldInfoList(importedWorldName) {
|
|
108
|
+
var result = await fetch("/getsettings", {
|
|
109
|
+
method: "POST",
|
|
110
|
+
headers: {
|
|
111
|
+
"Content-Type": "application/json",
|
|
112
|
+
"X-CSRF-Token": token,
|
|
113
|
+
},
|
|
114
|
+
body: JSON.stringify({}),
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
if (result.ok) {
|
|
118
|
+
var data = await result.json();
|
|
119
|
+
world_names = data.world_names?.length ? data.world_names : [];
|
|
120
|
+
$("#world_info").find('option[value!="None"]').remove();
|
|
121
|
+
|
|
122
|
+
world_names.forEach((item, i) => {
|
|
123
|
+
$("#world_info").append(`<option value='${i}'>${item}</option>`);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
if (importedWorldName) {
|
|
127
|
+
const indexOf = world_names.indexOf(world_info);
|
|
128
|
+
$("#world_info").val(indexOf);
|
|
129
|
+
|
|
130
|
+
callPopup("<h3>World imported successfully! Select it now?</h3>", "world_imported");
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function hideWorldEditor() {
|
|
136
|
+
is_world_edit_open = false;
|
|
137
|
+
$("#world_popup").css("display", "none");
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function displayWorldEntries(data) {
|
|
141
|
+
$("#world_popup_entries_list").empty();
|
|
142
|
+
|
|
143
|
+
if (!data || !("entries" in data)) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
for (const entryUid in data.entries) {
|
|
148
|
+
const entry = data.entries[entryUid];
|
|
149
|
+
appendWorldEntry(entry);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function appendWorldEntry(entry) {
|
|
154
|
+
const template = $("#entry_edit_template .world_entry").clone();
|
|
155
|
+
template.data("uid", entry.uid);
|
|
156
|
+
|
|
157
|
+
// key
|
|
158
|
+
const keyInput = template.find('textarea[name="key"]');
|
|
159
|
+
keyInput.data("uid", entry.uid);
|
|
160
|
+
keyInput.on("input", function () {
|
|
161
|
+
const uid = $(this).data("uid");
|
|
162
|
+
const value = $(this).val();
|
|
163
|
+
$(this).css("height", ""); //reset the height
|
|
164
|
+
$(this).css("height", $(this).prop("scrollHeight") + "px");
|
|
165
|
+
world_info_data.entries[uid].key = value
|
|
166
|
+
.split(",")
|
|
167
|
+
.map((x) => x.trim())
|
|
168
|
+
.filter((x) => x);
|
|
169
|
+
saveWorldInfo();
|
|
170
|
+
});
|
|
171
|
+
keyInput.val(entry.key.join(",")).trigger("input");
|
|
172
|
+
keyInput.css("height", ""); //reset the height
|
|
173
|
+
keyInput.css("height", $(this).prop("scrollHeight") + "px");
|
|
174
|
+
|
|
175
|
+
// keysecondary
|
|
176
|
+
const keySecondaryInput = template.find('textarea[name="keysecondary"]');
|
|
177
|
+
keySecondaryInput.data("uid", entry.uid);
|
|
178
|
+
keySecondaryInput.on("input", function () {
|
|
179
|
+
const uid = $(this).data("uid");
|
|
180
|
+
const value = $(this).val();
|
|
181
|
+
$(this).css("height", ""); //reset the height
|
|
182
|
+
$(this).css("height", $(this).prop("scrollHeight") + "px");
|
|
183
|
+
world_info_data.entries[uid].keysecondary = value
|
|
184
|
+
.split(",")
|
|
185
|
+
.map((x) => x.trim())
|
|
186
|
+
.filter((x) => x);
|
|
187
|
+
saveWorldInfo();
|
|
188
|
+
});
|
|
189
|
+
keySecondaryInput.val(entry.keysecondary.join(",")).trigger("input");
|
|
190
|
+
keySecondaryInput.css("height", ""); //reset the height
|
|
191
|
+
keySecondaryInput.css("height", $(this).prop("scrollHeight") + "px");
|
|
192
|
+
|
|
193
|
+
// comment
|
|
194
|
+
const commentInput = template.find('textarea[name="comment"]');
|
|
195
|
+
commentInput.data("uid", entry.uid);
|
|
196
|
+
commentInput.on("input", function () {
|
|
197
|
+
const uid = $(this).data("uid");
|
|
198
|
+
const value = $(this).val();
|
|
199
|
+
$(this).css("height", ""); //reset the height
|
|
200
|
+
$(this).css("height", $(this).prop("scrollHeight") + "px");
|
|
201
|
+
world_info_data.entries[uid].comment = value;
|
|
202
|
+
saveWorldInfo();
|
|
203
|
+
});
|
|
204
|
+
commentInput.val(entry.comment).trigger("input");
|
|
205
|
+
commentInput.css("height", ""); //reset the height
|
|
206
|
+
commentInput.css("height", $(this).prop("scrollHeight") + "px");
|
|
207
|
+
|
|
208
|
+
// content
|
|
209
|
+
const contentInput = template.find('textarea[name="content"]');
|
|
210
|
+
contentInput.data("uid", entry.uid);
|
|
211
|
+
contentInput.on("input", function () {
|
|
212
|
+
const uid = $(this).data("uid");
|
|
213
|
+
const value = $(this).val();
|
|
214
|
+
world_info_data.entries[uid].content = value;
|
|
215
|
+
$(this).css("height", ""); //reset the height
|
|
216
|
+
$(this).css("height", $(this).prop("scrollHeight") + "px");
|
|
217
|
+
saveWorldInfo();
|
|
218
|
+
|
|
219
|
+
// count tokens
|
|
220
|
+
const numberOfTokens = getTokenCount(value);
|
|
221
|
+
$(this)
|
|
222
|
+
.closest(".world_entry")
|
|
223
|
+
.find(".world_entry_form_token_counter")
|
|
224
|
+
.html(numberOfTokens);
|
|
225
|
+
});
|
|
226
|
+
contentInput.val(entry.content).trigger("input");
|
|
227
|
+
contentInput.css("height", ""); //reset the height
|
|
228
|
+
contentInput.css("height", $(this).prop("scrollHeight") + "px");
|
|
229
|
+
|
|
230
|
+
// selective
|
|
231
|
+
const selectiveInput = template.find('input[name="selective"]');
|
|
232
|
+
selectiveInput.data("uid", entry.uid);
|
|
233
|
+
selectiveInput.on("input", function () {
|
|
234
|
+
const uid = $(this).data("uid");
|
|
235
|
+
const value = $(this).prop("checked");
|
|
236
|
+
world_info_data.entries[uid].selective = value;
|
|
237
|
+
saveWorldInfo();
|
|
238
|
+
|
|
239
|
+
const keysecondary = $(this)
|
|
240
|
+
.closest(".world_entry")
|
|
241
|
+
.find(".keysecondary");
|
|
242
|
+
value ? keysecondary.show() : keysecondary.hide();
|
|
243
|
+
});
|
|
244
|
+
selectiveInput.prop("checked", entry.selective).trigger("input");
|
|
245
|
+
selectiveInput.siblings(".checkbox_fancy").click(function () {
|
|
246
|
+
$(this).siblings("input").click();
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// constant
|
|
250
|
+
const constantInput = template.find('input[name="constant"]');
|
|
251
|
+
constantInput.data("uid", entry.uid);
|
|
252
|
+
constantInput.on("input", function () {
|
|
253
|
+
const uid = $(this).data("uid");
|
|
254
|
+
const value = $(this).prop("checked");
|
|
255
|
+
world_info_data.entries[uid].constant = value;
|
|
256
|
+
saveWorldInfo();
|
|
257
|
+
});
|
|
258
|
+
constantInput.prop("checked", entry.constant).trigger("input");
|
|
259
|
+
constantInput.siblings(".checkbox_fancy").click(function () {
|
|
260
|
+
$(this).siblings("input").click();
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// order
|
|
264
|
+
const orderInput = template.find('input[name="order"]');
|
|
265
|
+
orderInput.data("uid", entry.uid);
|
|
266
|
+
orderInput.on("input", function () {
|
|
267
|
+
const uid = $(this).data("uid");
|
|
268
|
+
const value = Number($(this).val());
|
|
269
|
+
|
|
270
|
+
world_info_data.entries[uid].order = !isNaN(value) ? value : 0;
|
|
271
|
+
saveWorldInfo();
|
|
272
|
+
});
|
|
273
|
+
orderInput.val(entry.order).trigger("input");
|
|
274
|
+
|
|
275
|
+
// position
|
|
276
|
+
if (entry.position === undefined) {
|
|
277
|
+
entry.position = 0;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const positionInput = template.find('input[name="position"]');
|
|
281
|
+
positionInput.data("uid", entry.uid);
|
|
282
|
+
positionInput.on("input", function () {
|
|
283
|
+
const uid = $(this).data("uid");
|
|
284
|
+
const value = Number($(this).val());
|
|
285
|
+
world_info_data.entries[uid].position = !isNaN(value) ? value : 0;
|
|
286
|
+
saveWorldInfo();
|
|
287
|
+
});
|
|
288
|
+
template
|
|
289
|
+
.find(`input[name="position"][value=${entry.position}]`)
|
|
290
|
+
.prop("checked", true)
|
|
291
|
+
.trigger("input");
|
|
292
|
+
|
|
293
|
+
// display uid
|
|
294
|
+
template.find(".world_entry_form_uid_value").html(entry.uid);
|
|
295
|
+
|
|
296
|
+
// delete button
|
|
297
|
+
const deleteButton = template.find("input.delete_entry_button");
|
|
298
|
+
deleteButton.data("uid", entry.uid);
|
|
299
|
+
deleteButton.on("click", function () {
|
|
300
|
+
const uid = $(this).data("uid");
|
|
301
|
+
deleteWorldInfoEntry(uid);
|
|
302
|
+
$(this).closest(".world_entry").remove();
|
|
303
|
+
saveWorldInfo();
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
template.appendTo("#world_popup_entries_list");
|
|
307
|
+
return template;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
async function deleteWorldInfoEntry(uid) {
|
|
311
|
+
if (!world_info_data || !("entries" in world_info_data)) {
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
delete world_info_data.entries[uid];
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function createWorldInfoEntry() {
|
|
319
|
+
const newEntryTemplate = {
|
|
320
|
+
key: [],
|
|
321
|
+
keysecondary: [],
|
|
322
|
+
comment: "",
|
|
323
|
+
content: "",
|
|
324
|
+
constant: false,
|
|
325
|
+
selective: false,
|
|
326
|
+
order: 100,
|
|
327
|
+
position: 0,
|
|
328
|
+
};
|
|
329
|
+
const newUid = getFreeWorldEntryUid();
|
|
330
|
+
|
|
331
|
+
if (!Number.isInteger(newUid)) {
|
|
332
|
+
console.error("Couldn't assign UID to a new entry");
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const newEntry = { uid: newUid, ...newEntryTemplate };
|
|
337
|
+
world_info_data.entries[newUid] = newEntry;
|
|
338
|
+
|
|
339
|
+
const entryTemplate = appendWorldEntry(newEntry);
|
|
340
|
+
entryTemplate.get(0).scrollIntoView({ behavior: "smooth" });
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
async function _save() {
|
|
344
|
+
const response = await fetch("/editworldinfo", {
|
|
345
|
+
method: "POST",
|
|
346
|
+
headers: {
|
|
347
|
+
"Content-Type": "application/json",
|
|
348
|
+
"X-CSRF-Token": token,
|
|
349
|
+
},
|
|
350
|
+
body: JSON.stringify({ name: world_info, data: world_info_data }),
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
async function saveWorldInfo(immediately) {
|
|
355
|
+
if (!world_info || !world_info_data) {
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
if (immediately) {
|
|
361
|
+
return await _save();
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
saveWorldDebounced();
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
async function renameWorldInfo() {
|
|
368
|
+
const oldName = world_info;
|
|
369
|
+
const newName = $("#world_popup_name").val();
|
|
370
|
+
|
|
371
|
+
if (oldName === newName) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
world_info = newName;
|
|
376
|
+
await saveWorldInfo(true);
|
|
377
|
+
await deleteWorldInfo(oldName, newName);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
async function deleteWorldInfo(worldInfoName, selectWorldName) {
|
|
381
|
+
if (!world_names.includes(worldInfoName)) {
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const response = await fetch("/deleteworldinfo", {
|
|
386
|
+
method: "POST",
|
|
387
|
+
headers: {
|
|
388
|
+
"Content-Type": "application/json",
|
|
389
|
+
"X-CSRF-Token": token,
|
|
390
|
+
},
|
|
391
|
+
body: JSON.stringify({ name: worldInfoName }),
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
if (response.ok) {
|
|
395
|
+
await updateWorldInfoList();
|
|
396
|
+
|
|
397
|
+
const selectedIndex = world_names.indexOf(selectWorldName);
|
|
398
|
+
if (selectedIndex !== -1) {
|
|
399
|
+
$("#world_info").val(selectedIndex).change();
|
|
400
|
+
} else {
|
|
401
|
+
$("#world_info").val("None").change();
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
hideWorldEditor();
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
function getFreeWorldEntryUid() {
|
|
409
|
+
if (!world_info_data || !("entries" in world_info_data)) {
|
|
410
|
+
return null;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
const MAX_UID = 1_000_000; // <- should be safe enough :)
|
|
414
|
+
for (let uid = 0; uid < MAX_UID; uid++) {
|
|
415
|
+
if (uid in world_info_data.entries) {
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
return uid;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
return null;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
function getFreeWorldName() {
|
|
425
|
+
const MAX_FREE_NAME = 100_000;
|
|
426
|
+
for (let index = 1; index < MAX_FREE_NAME; index++) {
|
|
427
|
+
const newName = `New World (${index})`;
|
|
428
|
+
if (world_names.includes(newName)) {
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
return newName;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
return undefined;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
async function createNewWorldInfo() {
|
|
438
|
+
const worldInfoTemplate = { entries: {} };
|
|
439
|
+
const worldInfoName = getFreeWorldName();
|
|
440
|
+
|
|
441
|
+
if (!worldInfoName) {
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
world_info = worldInfoName;
|
|
446
|
+
world_info_data = { ...worldInfoTemplate };
|
|
447
|
+
await saveWorldInfo(true);
|
|
448
|
+
await updateWorldInfoList();
|
|
449
|
+
|
|
450
|
+
const selectedIndex = world_names.indexOf(worldInfoName);
|
|
451
|
+
if (selectedIndex !== -1) {
|
|
452
|
+
$("#world_info").val(selectedIndex).change();
|
|
453
|
+
} else {
|
|
454
|
+
$("#world_info").val("None").change();
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
function checkWorldInfo(chat) {
|
|
459
|
+
if (world_info_data.entries.length == 0) {
|
|
460
|
+
return "";
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const messagesToLookBack = world_info_depth * 2;
|
|
464
|
+
let textToScan = chat.slice(0, messagesToLookBack).join("").toLowerCase();
|
|
465
|
+
let worldInfoBefore = "";
|
|
466
|
+
let worldInfoAfter = "";
|
|
467
|
+
let needsToScan = true;
|
|
468
|
+
let allActivatedEntries = new Set();
|
|
469
|
+
|
|
470
|
+
const sortedEntries = Object.keys(world_info_data.entries)
|
|
471
|
+
.map((x) => world_info_data.entries[x])
|
|
472
|
+
.sort((a, b) => b.order - a.order);
|
|
473
|
+
while (needsToScan) {
|
|
474
|
+
let activatedNow = new Set();
|
|
475
|
+
|
|
476
|
+
for (let entry of sortedEntries) {
|
|
477
|
+
if (allActivatedEntries.has(entry.uid)) {
|
|
478
|
+
continue;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (entry.constant) {
|
|
482
|
+
activatedNow.add(entry.uid);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (Array.isArray(entry.key) && entry.key.length) {
|
|
486
|
+
primary: for (let key of entry.key) {
|
|
487
|
+
if (key && textToScan.includes(key.trim().toLowerCase())) {
|
|
488
|
+
if (
|
|
489
|
+
entry.selective &&
|
|
490
|
+
Array.isArray(entry.keysecondary) &&
|
|
491
|
+
entry.keysecondary.length
|
|
492
|
+
) {
|
|
493
|
+
secondary: for (let keysecondary of entry.keysecondary) {
|
|
494
|
+
if (
|
|
495
|
+
keysecondary &&
|
|
496
|
+
textToScan.includes(keysecondary.trim().toLowerCase())
|
|
497
|
+
) {
|
|
498
|
+
activatedNow.add(entry.uid);
|
|
499
|
+
break secondary;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
} else {
|
|
503
|
+
activatedNow.add(entry.uid);
|
|
504
|
+
break primary;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
needsToScan = activatedNow.size > 0;
|
|
512
|
+
const newEntries = [...activatedNow]
|
|
513
|
+
.map((x) => world_info_data.entries[x])
|
|
514
|
+
.sort((a, b) => sortedEntries.indexOf(a) - sortedEntries.indexOf(b));
|
|
515
|
+
|
|
516
|
+
for (const entry of newEntries) {
|
|
517
|
+
if (entry.position === world_info_position.after) {
|
|
518
|
+
worldInfoAfter = `${substituteParams(
|
|
519
|
+
entry.content
|
|
520
|
+
)}\n${worldInfoAfter}`;
|
|
521
|
+
} else {
|
|
522
|
+
worldInfoBefore = `${substituteParams(
|
|
523
|
+
entry.content
|
|
524
|
+
)}\n${worldInfoBefore}`;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
if (
|
|
528
|
+
getTokenCount(worldInfoBefore + worldInfoAfter) >= world_info_budget
|
|
529
|
+
) {
|
|
530
|
+
needsToScan = false;
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
if (needsToScan) {
|
|
536
|
+
textToScan =
|
|
537
|
+
newEntries
|
|
538
|
+
.map((x) => x.content)
|
|
539
|
+
.join("\n")
|
|
540
|
+
.toLowerCase() + textToScan;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
allActivatedEntries = new Set([...allActivatedEntries, ...activatedNow]);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
return { worldInfoBefore, worldInfoAfter };
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
function selectImportedWorldInfo() {
|
|
550
|
+
if (!imported_world_name) {
|
|
551
|
+
return;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
world_names.forEach((item, i) => {
|
|
555
|
+
if (item === imported_world_name) {
|
|
556
|
+
$("#world_info").val(i).change();
|
|
557
|
+
}
|
|
558
|
+
});
|
|
559
|
+
imported_world_name = "";
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
$(document).ready(() => {
|
|
563
|
+
$("#world_info").change(async function () {
|
|
564
|
+
const selectedWorld = $("#world_info").find(":selected").val();
|
|
565
|
+
world_info = null;
|
|
566
|
+
world_info_data = null;
|
|
567
|
+
|
|
568
|
+
if (selectedWorld !== "None") {
|
|
569
|
+
const worldIndex = Number(selectedWorld);
|
|
570
|
+
world_info = !isNaN(worldIndex) ? world_names[worldIndex] : null;
|
|
571
|
+
await loadWorldInfoData();
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
hideWorldEditor();
|
|
575
|
+
saveSettingsDebounced();
|
|
576
|
+
});
|
|
577
|
+
|
|
578
|
+
//**************************WORLD INFO IMPORT EXPORT*************************//
|
|
579
|
+
$("#world_import_button").click(function () {
|
|
580
|
+
$("#world_import_file").click();
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
$("#world_import_file").on("change", function (e) {
|
|
584
|
+
var file = e.target.files[0];
|
|
585
|
+
|
|
586
|
+
if (!file) {
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
const ext = file.name.match(/\.(\w+)$/);
|
|
591
|
+
if (!ext || ext[1].toLowerCase() !== "json") {
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
const formData = new FormData($("#form_world_import").get(0));
|
|
596
|
+
|
|
597
|
+
jQuery.ajax({
|
|
598
|
+
type: "POST",
|
|
599
|
+
url: "/importworldinfo",
|
|
600
|
+
data: formData,
|
|
601
|
+
beforeSend: () => { },
|
|
602
|
+
cache: false,
|
|
603
|
+
contentType: false,
|
|
604
|
+
processData: false,
|
|
605
|
+
success: function (data) {
|
|
606
|
+
if (data.name) {
|
|
607
|
+
imported_world_name = data.name;
|
|
608
|
+
updateWorldInfoList(imported_world_name);
|
|
609
|
+
}
|
|
610
|
+
},
|
|
611
|
+
error: (jqXHR, exception) => { },
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
// Will allow to select the same file twice in a row
|
|
615
|
+
$("#form_world_import").trigger("reset");
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
$("#world_info_edit_button").click(() => {
|
|
619
|
+
is_world_edit_open ? hideWorldEditor() : showWorldEditor();
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
$("#world_popup_export").click(() => {
|
|
623
|
+
if (world_info && world_info_data) {
|
|
624
|
+
const jsonValue = JSON.stringify(world_info_data);
|
|
625
|
+
const fileName = `${world_info}.json`;
|
|
626
|
+
download(jsonValue, fileName, "application/json");
|
|
627
|
+
}
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
$("#world_popup_delete").click(() => {
|
|
631
|
+
callPopup("<h3>Delete the World Info?</h3>", "del_world");
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
$("#world_popup_new").click(() => {
|
|
635
|
+
createWorldInfoEntry();
|
|
636
|
+
});
|
|
637
|
+
|
|
638
|
+
$("#world_cross").click(() => {
|
|
639
|
+
hideWorldEditor();
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
$("#world_popup_name_button").click(() => {
|
|
643
|
+
renameWorldInfo();
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
$("#world_create_button").click(() => {
|
|
647
|
+
createNewWorldInfo();
|
|
648
|
+
});
|
|
649
|
+
|
|
650
|
+
$(document).on("input", "#world_info_depth", function () {
|
|
651
|
+
world_info_depth = Number($(this).val());
|
|
652
|
+
$("#world_info_depth_counter").html(`${$(this).val()} Messages`);
|
|
653
|
+
saveSettingsDebounced();
|
|
654
|
+
});
|
|
655
|
+
|
|
656
|
+
$(document).on("input", "#world_info_budget", function () {
|
|
657
|
+
world_info_budget = Number($(this).val());
|
|
658
|
+
$("#world_info_budget_counter").html(`${$(this).val()} Tokens`);
|
|
659
|
+
saveSettingsDebounced();
|
|
660
|
+
});
|
|
661
|
+
});
|
|
Binary file
|