mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Merge branch 'staging' into parser-followup-2
This commit is contained in:
@@ -93,6 +93,11 @@ openai:
|
|||||||
deepl:
|
deepl:
|
||||||
# Available options: default, more, less, prefer_more, prefer_less
|
# Available options: default, more, less, prefer_more, prefer_less
|
||||||
formality: default
|
formality: default
|
||||||
|
# -- MISTRAL API CONFIGURATION --
|
||||||
|
mistral:
|
||||||
|
# Enables prefilling of the reply with the last assistant message in the prompt
|
||||||
|
# CAUTION: The prefix is echoed into the completion. You may want to use regex to trim it out.
|
||||||
|
enablePrefix: false
|
||||||
# -- SERVER PLUGIN CONFIGURATION --
|
# -- SERVER PLUGIN CONFIGURATION --
|
||||||
enableServerPlugins: false
|
enableServerPlugins: false
|
||||||
# User session timeout *in seconds* (defaults to 24 hours).
|
# User session timeout *in seconds* (defaults to 24 hours).
|
||||||
|
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "sillytavern",
|
"name": "sillytavern",
|
||||||
"version": "1.12.3",
|
"version": "1.12.4",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "sillytavern",
|
"name": "sillytavern",
|
||||||
"version": "1.12.3",
|
"version": "1.12.4",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@@ -70,7 +70,7 @@
|
|||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/SillyTavern/SillyTavern.git"
|
"url": "https://github.com/SillyTavern/SillyTavern.git"
|
||||||
},
|
},
|
||||||
"version": "1.12.3",
|
"version": "1.12.4",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node server.js",
|
"start": "node server.js",
|
||||||
"start:no-csrf": "node server.js --disableCsrf",
|
"start:no-csrf": "node server.js --disableCsrf",
|
||||||
|
@@ -89,7 +89,7 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
height: 100svh;
|
height: 100dvh;
|
||||||
z-index: 9998;
|
z-index: 9998;
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,8 @@
|
|||||||
background-color: green;
|
background-color: green;
|
||||||
}
|
}
|
||||||
|
|
||||||
.extensions_block input[type="checkbox"] {
|
.extensions_block input[type="checkbox"],
|
||||||
|
.extensions_block input[type="radio"] {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
@@ -7,8 +7,8 @@
|
|||||||
z-index: 999999;
|
z-index: 999999;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
width: 100svw;
|
width: 100dvw;
|
||||||
height: 100svh;
|
height: 100dvh;
|
||||||
background-color: var(--SmartThemeBlurTintColor);
|
background-color: var(--SmartThemeBlurTintColor);
|
||||||
color: var(--SmartThemeBodyColor);
|
color: var(--SmartThemeBodyColor);
|
||||||
/*for some reason the full screen blur does not work on iOS*/
|
/*for some reason the full screen blur does not work on iOS*/
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
#logprobsViewer {
|
#logprobsViewer {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
max-width: 90svw;
|
max-width: 90dvw;
|
||||||
max-height: 90svh;
|
max-height: 90dvh;
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
min-height: 50px;
|
min-height: 50px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
top: 0;
|
top: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
right: unset;
|
right: unset;
|
||||||
width: calc(((100svw - var(--sheldWidth)) / 2) - 1px);
|
width: calc(((100dvw - var(--sheldWidth)) / 2) - 1px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.logprobs_panel_header {
|
.logprobs_panel_header {
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
/*will apply to anything 1000px or less. this catches ipads, horizontal phones, and vertical phones)*/
|
/*will apply to anything 1000px or less. this catches ipads, horizontal phones, and vertical phones)*/
|
||||||
@media screen and (max-width: 1000px) {
|
@media screen and (max-width: 1000px) {
|
||||||
#send_form.compact #leftSendForm, #send_form.compact #rightSendForm {
|
|
||||||
|
#send_form.compact #leftSendForm,
|
||||||
|
#send_form.compact #rightSendForm {
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
width: unset;
|
width: unset;
|
||||||
}
|
}
|
||||||
@@ -34,9 +36,9 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
max-height: calc(60vh - 60px);
|
max-height: calc(60vh - 60px);
|
||||||
max-height: calc(60svh - 60px);
|
max-height: calc(60dvh - 60px);
|
||||||
max-width: 90vw;
|
max-width: 90vw;
|
||||||
max-width: 90svw;
|
max-width: 90dvw;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translateX(-50%) translateY(-50%);
|
transform: translateX(-50%) translateY(-50%);
|
||||||
@@ -102,7 +104,7 @@
|
|||||||
min-width: unset;
|
min-width: unset;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-height: calc(100vh - 45px);
|
max-height: calc(100vh - 45px);
|
||||||
max-height: calc(100svh - 45px);
|
max-height: calc(100dvh - 45px);
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 5px;
|
top: 5px;
|
||||||
@@ -130,15 +132,15 @@
|
|||||||
#top-bar {
|
#top-bar {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
width: 100svw;
|
width: 100dvw;
|
||||||
}
|
}
|
||||||
|
|
||||||
#bg1,
|
#bg1,
|
||||||
#bg_custom {
|
#bg_custom {
|
||||||
height: 100vh !important;
|
height: 100vh !important;
|
||||||
height: 100svh !important;
|
height: 100dvh !important;
|
||||||
width: 100vw !important;
|
width: 100vw !important;
|
||||||
width: 100svw !important;
|
width: 100dvw !important;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -146,13 +148,7 @@
|
|||||||
|
|
||||||
#sheld,
|
#sheld,
|
||||||
#character_popup,
|
#character_popup,
|
||||||
.drawer-content
|
.drawer-content {
|
||||||
|
|
||||||
/* ,
|
|
||||||
#world_popup */
|
|
||||||
{
|
|
||||||
/*max-height: calc(100vh - 36px);
|
|
||||||
max-height: calc(100svh - 36px);*/
|
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
@@ -223,10 +219,10 @@
|
|||||||
#floatingPrompt,
|
#floatingPrompt,
|
||||||
#cfgConfig,
|
#cfgConfig,
|
||||||
#logprobsViewer,
|
#logprobsViewer,
|
||||||
#movingDivs > div {
|
#movingDivs>div {
|
||||||
/* 100vh are fallback units for browsers that don't support svh */
|
/* 100vh are fallback units for browsers that don't support dvh */
|
||||||
height: calc(100vh - 45px);
|
height: calc(100vh - 45px);
|
||||||
height: calc(100svh - 45px);
|
height: calc(100dvh - 45px);
|
||||||
min-width: 100% !important;
|
min-width: 100% !important;
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
max-width: 100% !important;
|
max-width: 100% !important;
|
||||||
@@ -249,7 +245,7 @@
|
|||||||
#floatingPrompt,
|
#floatingPrompt,
|
||||||
#cfgConfig,
|
#cfgConfig,
|
||||||
#logprobsViewer,
|
#logprobsViewer,
|
||||||
#movingDivs > div {
|
#movingDivs>div {
|
||||||
height: min-content;
|
height: min-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -286,9 +282,9 @@
|
|||||||
|
|
||||||
body.waifuMode #sheld {
|
body.waifuMode #sheld {
|
||||||
height: 40vh;
|
height: 40vh;
|
||||||
height: 40svh;
|
height: 40dvh;
|
||||||
top: 60vh;
|
top: 60vh;
|
||||||
top: 60svh;
|
top: 60dvh;
|
||||||
bottom: 0 !important;
|
bottom: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -325,16 +321,16 @@
|
|||||||
body.waifuMode .zoomed_avatar {
|
body.waifuMode .zoomed_avatar {
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
max-height: calc(60vh - 60px);
|
max-height: calc(60vh - 60px);
|
||||||
max-height: calc(60svh - 60px);
|
max-height: calc(60dvh - 60px);
|
||||||
max-width: 90vw;
|
max-width: 90vw;
|
||||||
max-width: 90svw;
|
max-width: 90dvw;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollableInner {
|
.scrollableInner {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
max-height: calc(100vh - 90px);
|
max-height: calc(100vh - 90px);
|
||||||
max-height: calc(100svh - 90px);
|
max-height: calc(100dvh - 90px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.horde_multiple_hint {
|
.horde_multiple_hint {
|
||||||
@@ -370,9 +366,9 @@
|
|||||||
|
|
||||||
body:not(.waifuMode) .zoomed_avatar {
|
body:not(.waifuMode) .zoomed_avatar {
|
||||||
max-height: calc(60vh - 60px);
|
max-height: calc(60vh - 60px);
|
||||||
max-height: calc(60svh - 60px);
|
max-height: calc(60dvh - 60px);
|
||||||
max-width: 90vw;
|
max-width: 90vw;
|
||||||
max-width: 90svw;
|
max-width: 90dvw;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translateX(-50%) translateY(-50%);
|
transform: translateX(-50%) translateY(-50%);
|
||||||
@@ -453,9 +449,9 @@
|
|||||||
min-height: unset;
|
min-height: unset;
|
||||||
max-height: unset;
|
max-height: unset;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
width: 100svw;
|
width: 100dvw;
|
||||||
height: calc(100vh - 36px);
|
height: calc(100vh - 36px);
|
||||||
height: calc(100svh - 36px);
|
height: calc(100dvh - 36px);
|
||||||
padding-right: max(env(safe-area-inset-right), 0px);
|
padding-right: max(env(safe-area-inset-right), 0px);
|
||||||
padding-left: max(env(safe-area-inset-left), 0px);
|
padding-left: max(env(safe-area-inset-left), 0px);
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
@@ -485,10 +481,10 @@
|
|||||||
top: 0;
|
top: 0;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
height: calc(100vh - 70px);
|
height: calc(100vh - 70px);
|
||||||
height: calc(100svh - 70px);
|
height: calc(100dvh - 70px);
|
||||||
width: calc(100% - 5px);
|
width: calc(100% - 5px);
|
||||||
max-height: calc(100vh - 70px);
|
max-height: calc(100vh - 70px);
|
||||||
max-height: calc(100svh - 70px);
|
max-height: calc(100dvh - 70px);
|
||||||
max-width: calc(100% - 5px);
|
max-width: calc(100% - 5px);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -7,5 +7,5 @@ body.safari .popup.large_dialogue_popup .popup-body {
|
|||||||
body.safari .popup .popup-body {
|
body.safari .popup .popup-body {
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
max-height: 90vh;
|
max-height: 90vh;
|
||||||
max-height: 90svh;
|
max-height: 90dvh;
|
||||||
}
|
}
|
||||||
|
@@ -16,8 +16,8 @@ dialog {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
max-height: calc(100svh - 2em);
|
max-height: calc(100dvh - 2em);
|
||||||
max-width: calc(100svw - 2em);
|
max-width: calc(100dvw - 2em);
|
||||||
min-height: fit-content;
|
min-height: fit-content;
|
||||||
|
|
||||||
/* Overflow visible so elements (like toasts) can appear outside of the dialog. '.popup-body' is hiding overflow for the real content. */
|
/* Overflow visible so elements (like toasts) can appear outside of the dialog. '.popup-body' is hiding overflow for the real content. */
|
||||||
@@ -103,7 +103,7 @@ body.no-blur .popup[open]::backdrop {
|
|||||||
|
|
||||||
.popup #toast-container {
|
.popup #toast-container {
|
||||||
/* Fix toastr in dialogs by actually placing it at the top of the screen via transform */
|
/* Fix toastr in dialogs by actually placing it at the top of the screen via transform */
|
||||||
height: 100svh;
|
height: 100dvh;
|
||||||
top: calc(50% + var(--topBarBlockSize));
|
top: calc(50% + var(--topBarBlockSize));
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
@@ -115,7 +115,7 @@ body.no-blur .popup[open]::backdrop {
|
|||||||
.popup-crop-wrap {
|
.popup-crop-wrap {
|
||||||
margin: 10px auto;
|
margin: 10px auto;
|
||||||
max-height: 75vh;
|
max-height: 75vh;
|
||||||
max-height: 75svh;
|
max-height: 75dvh;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -364,7 +364,7 @@ body.waifuMode #top-bar {
|
|||||||
|
|
||||||
body.waifuMode #sheld {
|
body.waifuMode #sheld {
|
||||||
height: 40vh;
|
height: 40vh;
|
||||||
height: 40svh;
|
height: 40dvh;
|
||||||
top: calc(100% - 40vh);
|
top: calc(100% - 40vh);
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
|
2
public/global.d.ts
vendored
2
public/global.d.ts
vendored
@@ -16,6 +16,8 @@ declare var ai;
|
|||||||
|
|
||||||
// Jquery plugins
|
// Jquery plugins
|
||||||
interface JQuery {
|
interface JQuery {
|
||||||
|
nanogallery2(options?: any): JQuery;
|
||||||
|
nanogallery2(method: string, options?: any): JQuery;
|
||||||
pagination(method: 'getCurrentPageNum'): number;
|
pagination(method: 'getCurrentPageNum'): number;
|
||||||
pagination(method: string, options?: any): JQuery;
|
pagination(method: string, options?: any): JQuery;
|
||||||
pagination(options?: any): JQuery;
|
pagination(options?: any): JQuery;
|
||||||
|
@@ -3296,6 +3296,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex-container">
|
||||||
|
<div class="flex1" title="Inserted before the first User's message." data-i18n="[title]Inserted before the first User's message.">
|
||||||
|
<label for="instruct_first_input_sequence">
|
||||||
|
<small data-i18n="First User Prefix">First User Prefix</small>
|
||||||
|
</label>
|
||||||
|
<div>
|
||||||
|
<textarea id="instruct_first_input_sequence" class="text_pole textarea_compact autoSetHeight" maxlength="2000" placeholder="—" rows="1"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex1" title="Inserted before the last User's message." data-i18n="[title]instruct_last_input_sequence">
|
||||||
|
<label for="instruct_last_input_sequence">
|
||||||
|
<small data-i18n="Last User Prefix">Last User Prefix</small>
|
||||||
|
</label>
|
||||||
|
<div>
|
||||||
|
<textarea id="instruct_last_input_sequence" class="text_pole wide100p textarea_compact autoSetHeight" maxlength="2000" placeholder="—" rows="1"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="flex-container">
|
<div class="flex-container">
|
||||||
<div class="flex1" title="Will be inserted as a last prompt line when using system/neutral generation." data-i18n="[title]Will be inserted as a last prompt line when using system/neutral generation.">
|
<div class="flex1" title="Will be inserted as a last prompt line when using system/neutral generation." data-i18n="[title]Will be inserted as a last prompt line when using system/neutral generation.">
|
||||||
<label for="instruct_last_system_sequence">
|
<label for="instruct_last_system_sequence">
|
||||||
@@ -3644,8 +3662,8 @@
|
|||||||
<div id="OpenAllWIEntries" class="menu_button fa-solid fa-expand" title="Open all Entries" data-i18n="[title]Open all Entries"></div>
|
<div id="OpenAllWIEntries" class="menu_button fa-solid fa-expand" title="Open all Entries" data-i18n="[title]Open all Entries"></div>
|
||||||
<div id="CloseAllWIEntries" class="menu_button fa-solid fa-compress" title="Close all Entries" data-i18n="[title]Close all Entries"></div>
|
<div id="CloseAllWIEntries" class="menu_button fa-solid fa-compress" title="Close all Entries" data-i18n="[title]Close all Entries"></div>
|
||||||
<div id="world_popup_new" class="menu_button fa-solid fa-plus" title="New Entry" data-i18n="[title]New Entry"></div>
|
<div id="world_popup_new" class="menu_button fa-solid fa-plus" title="New Entry" data-i18n="[title]New Entry"></div>
|
||||||
<div id="world_backfill_memos" class="menu_button fa-solid fa-notes-medical" title="Fill empty Memo/Titles with Keywords" data-i18n="[title]Fill empty Memo/Titles with Keywords"></div><div id="world_apply_custom_sorting" class="menu_button fa-solid fa-solid fa-arrow-down-9-1"
|
<div id="world_backfill_memos" class="menu_button fa-solid fa-notes-medical" title="Fill empty Memo/Titles with Keywords" data-i18n="[title]Fill empty Memo/Titles with Keywords"></div>
|
||||||
title="Apply custom sorting as Order" data-i18n="[title]Apply custom sorting as Order"></div>
|
<div id="world_apply_current_sorting" class="menu_button fa-solid fa-solid fa-arrow-down-9-1" title="Apply current sorting as Order" data-i18n="[title]Apply current sorting as Order"></div>
|
||||||
<div id="world_import_button" class="menu_button fa-solid fa-file-import" title="Import World Info" data-i18n="[title]Import World Info"></div>
|
<div id="world_import_button" class="menu_button fa-solid fa-file-import" title="Import World Info" data-i18n="[title]Import World Info"></div>
|
||||||
<div id="world_popup_export" class="menu_button fa-solid fa-file-export" title="Export World Info" data-i18n="[title]Export World Info"></div>
|
<div id="world_popup_export" class="menu_button fa-solid fa-file-export" title="Export World Info" data-i18n="[title]Export World Info"></div>
|
||||||
<div id="world_duplicate" class="menu_button fa-solid fa-paste" title="Duplicate World Info" data-i18n="[title]Duplicate World Info"></div>
|
<div id="world_duplicate" class="menu_button fa-solid fa-paste" title="Duplicate World Info" data-i18n="[title]Duplicate World Info"></div>
|
||||||
@@ -4008,7 +4026,7 @@
|
|||||||
<input type="range" id="smooth_streaming_speed" name="smooth_streaming_speed" min="0" max="100" step="10" value="50">
|
<input type="range" id="smooth_streaming_speed" name="smooth_streaming_speed" min="0" max="100" step="10" value="50">
|
||||||
<div class="slider_hint">
|
<div class="slider_hint">
|
||||||
<span data-i18n="Slow">Slow</span>
|
<span data-i18n="Slow">Slow</span>
|
||||||
<span data-i18n=""></span>
|
<span></span>
|
||||||
<span data-i18n="Fast">Fast</span>
|
<span data-i18n="Fast">Fast</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -6450,6 +6468,9 @@
|
|||||||
<button class="menu_button set_default_persona" title="Select this as default persona for the new chats." data-i18n="[title]Select this as default persona for the new chats.">
|
<button class="menu_button set_default_persona" title="Select this as default persona for the new chats." data-i18n="[title]Select this as default persona for the new chats.">
|
||||||
<i class="fa-fw fa-solid fa-crown"></i>
|
<i class="fa-fw fa-solid fa-crown"></i>
|
||||||
</button>
|
</button>
|
||||||
|
<button class="menu_button duplicate_persona" title="Duplicate persona" data-i18n="[title]Duplicate persona">
|
||||||
|
<i class="fa-fw fa-solid fa-clone"></i>
|
||||||
|
</button>
|
||||||
<button class="menu_button delete_avatar" title="Delete persona" data-i18n="[title]Delete persona">
|
<button class="menu_button delete_avatar" title="Delete persona" data-i18n="[title]Delete persona">
|
||||||
<i class="fa-fw fa-solid fa-trash-alt"></i>
|
<i class="fa-fw fa-solid fa-trash-alt"></i>
|
||||||
</button>
|
</button>
|
||||||
|
@@ -217,9 +217,11 @@
|
|||||||
"Character Names Behavior": "角色名称行为",
|
"Character Names Behavior": "角色名称行为",
|
||||||
"Helps the model to associate messages with characters.": "有助于模型将消息与角色关联起来。",
|
"Helps the model to associate messages with characters.": "有助于模型将消息与角色关联起来。",
|
||||||
"None": "无",
|
"None": "无",
|
||||||
|
"character_names_none": "不添加角色名称前缀。在群聊中可能导致错误行为,谨慎勾选。",
|
||||||
|
"Never add character names.": "不添加角色名称。",
|
||||||
"character_names_default": "群聊和过去的角色除外。否则,请确保在提示词中提供了姓名。",
|
"character_names_default": "群聊和过去的角色除外。否则,请确保在提示词中提供了姓名。",
|
||||||
"Don't add character names.": "不添加角色名称。",
|
"Don't add character names unless necessary.": "如非必要,否则不添加角色名称。",
|
||||||
"Completion": "补全对象",
|
"Completion Object": "补全对象",
|
||||||
"character_names_completion": "适用限制:仅限拉丁字母数字和下划线。不适用于所有补全源,尤其是:Claude、MistralAI、Google。",
|
"character_names_completion": "适用限制:仅限拉丁字母数字和下划线。不适用于所有补全源,尤其是:Claude、MistralAI、Google。",
|
||||||
"Add character names to completion objects.": "在补全对象中添加角色名称。",
|
"Add character names to completion objects.": "在补全对象中添加角色名称。",
|
||||||
"Message Content": "消息内容",
|
"Message Content": "消息内容",
|
||||||
@@ -489,6 +491,10 @@
|
|||||||
"First Assistant Prefix": "第一个助理前缀",
|
"First Assistant Prefix": "第一个助理前缀",
|
||||||
"instruct_last_output_sequence": "插入到最后一条助手消息之前或作为生成 AI 回复时的最后一行提示词(中立/系统角色除外)。",
|
"instruct_last_output_sequence": "插入到最后一条助手消息之前或作为生成 AI 回复时的最后一行提示词(中立/系统角色除外)。",
|
||||||
"Last Assistant Prefix": "最后一个助理前缀",
|
"Last Assistant Prefix": "最后一个助理前缀",
|
||||||
|
"Inserted before the first User's message.": "插入在第一个用户的消息之前。",
|
||||||
|
"First User Prefix": "第一个用户前缀",
|
||||||
|
"instruct_last_input_sequence": "插入到最后一条用户消息之前。",
|
||||||
|
"Last User Prefix": "上次用户前缀",
|
||||||
"Will be inserted as a last prompt line when using system/neutral generation.": "当使用系统/中性生成时将作为最后的一行提示词插入。",
|
"Will be inserted as a last prompt line when using system/neutral generation.": "当使用系统/中性生成时将作为最后的一行提示词插入。",
|
||||||
"System Instruction Prefix": "系统指令前缀",
|
"System Instruction Prefix": "系统指令前缀",
|
||||||
"If a stop sequence is generated, everything past it will be removed from the output (inclusive).": "如果生成了停止序列,则该序列之后的所有内容都将从输出中删除(包括在内)。",
|
"If a stop sequence is generated, everything past it will be removed from the output (inclusive).": "如果生成了停止序列,则该序列之后的所有内容都将从输出中删除(包括在内)。",
|
||||||
@@ -555,7 +561,7 @@
|
|||||||
"Close all Entries": "关闭所有条目",
|
"Close all Entries": "关闭所有条目",
|
||||||
"New Entry": "新条目",
|
"New Entry": "新条目",
|
||||||
"Fill empty Memo/Titles with Keywords": "使用关键字填充空的备忘录/标题",
|
"Fill empty Memo/Titles with Keywords": "使用关键字填充空的备忘录/标题",
|
||||||
"Apply custom sorting as Order": "应用自定义排序作为顺序",
|
"Apply current sorting as Order": "应用当前排序作为顺序",
|
||||||
"Import World Info": "导入世界书",
|
"Import World Info": "导入世界书",
|
||||||
"Export World Info": "导出世界书",
|
"Export World Info": "导出世界书",
|
||||||
"Duplicate World Info": "复制世界书",
|
"Duplicate World Info": "复制世界书",
|
||||||
@@ -1187,6 +1193,7 @@
|
|||||||
"Bind user name to that avatar": "将用户名称绑定到该头像",
|
"Bind user name to that avatar": "将用户名称绑定到该头像",
|
||||||
"Change persona image": "更改用户角色头像",
|
"Change persona image": "更改用户角色头像",
|
||||||
"Select this as default persona for the new chats.": "选择此项作为新聊天的默认用户角色。",
|
"Select this as default persona for the new chats.": "选择此项作为新聊天的默认用户角色。",
|
||||||
|
"Duplicate persona": "复制用户角色",
|
||||||
"Delete persona": "删除用户角色",
|
"Delete persona": "删除用户角色",
|
||||||
"These characters are the winners of character design contests and have outstandable quality.": "这些角色都是角色设计大赛的获奖者,品质非常出色。",
|
"These characters are the winners of character design contests and have outstandable quality.": "这些角色都是角色设计大赛的获奖者,品质非常出色。",
|
||||||
"Contest Winners": "比赛获胜者",
|
"Contest Winners": "比赛获胜者",
|
||||||
@@ -1327,6 +1334,10 @@
|
|||||||
"ext_sum_injection_template": "插入模板",
|
"ext_sum_injection_template": "插入模板",
|
||||||
"ext_sum_memory_template_placeholder": "{{summary}} 将解析当前摘要内容。",
|
"ext_sum_memory_template_placeholder": "{{summary}} 将解析当前摘要内容。",
|
||||||
"ext_sum_injection_position": "插入位置",
|
"ext_sum_injection_position": "插入位置",
|
||||||
|
"ext_sum_include_wi_scan_desc": "在 WI 扫描中包括最新摘要。",
|
||||||
|
"ext_sum_include_wi_scan": "纳入世界信息扫描",
|
||||||
|
"None (not injected)": "无(未注入)",
|
||||||
|
"ext_sum_injection_position_none": "摘要不会被注入到提示中。您仍然可以通过 {{summary}} 宏访问它。",
|
||||||
"How many messages before the current end of the chat.": "当前聊天结束前还有多少条消息。",
|
"How many messages before the current end of the chat.": "当前聊天结束前还有多少条消息。",
|
||||||
"Labels and Message": "标签和信息",
|
"Labels and Message": "标签和信息",
|
||||||
"Label": "标签",
|
"Label": "标签",
|
||||||
@@ -1757,6 +1768,8 @@
|
|||||||
"help_macros_56": "指示系统指令前缀",
|
"help_macros_56": "指示系统指令前缀",
|
||||||
"help_macros_57": "指示第一个用户消息填充器",
|
"help_macros_57": "指示第一个用户消息填充器",
|
||||||
"help_macros_58": "指示停止顺序",
|
"help_macros_58": "指示停止顺序",
|
||||||
|
"help_macros_first_user": "指示用户第一个输入序列",
|
||||||
|
"help_macros_last_user": "指示用户最后输入序列",
|
||||||
"Chat variables Macros:": "聊天变量宏:",
|
"Chat variables Macros:": "聊天变量宏:",
|
||||||
"Local variables = unique to the current chat": "局部变量 = 当前聊天所独有",
|
"Local variables = unique to the current chat": "局部变量 = 当前聊天所独有",
|
||||||
"Global variables = works in any chat for any character": "全局变量 = 适用于任何角色的任何聊天",
|
"Global variables = works in any chat for any character": "全局变量 = 适用于任何角色的任何聊天",
|
||||||
@@ -1794,6 +1807,7 @@
|
|||||||
"Record a snapshot of your current settings.": "记录当前设置的快照。",
|
"Record a snapshot of your current settings.": "记录当前设置的快照。",
|
||||||
"Make a Snapshot": "制作快照",
|
"Make a Snapshot": "制作快照",
|
||||||
"Restore this snapshot": "恢复此快照",
|
"Restore this snapshot": "恢复此快照",
|
||||||
|
"Download Model": "下载模型",
|
||||||
"Downloader Options": "下载器选项",
|
"Downloader Options": "下载器选项",
|
||||||
"Extra parameters for downloading/HuggingFace API": "下载/HuggingFace API 的额外参数。如果不确定,请将其留空。",
|
"Extra parameters for downloading/HuggingFace API": "下载/HuggingFace API 的额外参数。如果不确定,请将其留空。",
|
||||||
"Revision": "修订",
|
"Revision": "修订",
|
||||||
|
@@ -570,6 +570,7 @@ export const system_message_types = {
|
|||||||
* @enum {number} Extension prompt types
|
* @enum {number} Extension prompt types
|
||||||
*/
|
*/
|
||||||
export const extension_prompt_types = {
|
export const extension_prompt_types = {
|
||||||
|
NONE: -1,
|
||||||
IN_PROMPT: 0,
|
IN_PROMPT: 0,
|
||||||
IN_CHAT: 1,
|
IN_CHAT: 1,
|
||||||
BEFORE_PROMPT: 2,
|
BEFORE_PROMPT: 2,
|
||||||
@@ -929,10 +930,17 @@ async function firstLoadInit() {
|
|||||||
initCfg();
|
initCfg();
|
||||||
initLogprobs();
|
initLogprobs();
|
||||||
doDailyExtensionUpdatesCheck();
|
doDailyExtensionUpdatesCheck();
|
||||||
hideLoader();
|
await hideLoader();
|
||||||
|
await fixViewport();
|
||||||
await eventSource.emit(event_types.APP_READY);
|
await eventSource.emit(event_types.APP_READY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fixViewport() {
|
||||||
|
document.body.style.position = 'absolute';
|
||||||
|
await delay(1);
|
||||||
|
document.body.style.position = '';
|
||||||
|
}
|
||||||
|
|
||||||
function cancelStatusCheck() {
|
function cancelStatusCheck() {
|
||||||
abortStatusCheck?.abort();
|
abortStatusCheck?.abort();
|
||||||
abortStatusCheck = new AbortController();
|
abortStatusCheck = new AbortController();
|
||||||
@@ -3611,6 +3619,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
|
|||||||
let chat2 = [];
|
let chat2 = [];
|
||||||
let continue_mag = '';
|
let continue_mag = '';
|
||||||
const userMessageIndices = [];
|
const userMessageIndices = [];
|
||||||
|
const lastUserMessageIndex = coreChat.findLastIndex(x => x.is_user);
|
||||||
|
|
||||||
for (let i = coreChat.length - 1, j = 0; i >= 0; i--, j++) {
|
for (let i = coreChat.length - 1, j = 0; i >= 0; i--, j++) {
|
||||||
if (main_api == 'openai') {
|
if (main_api == 'openai') {
|
||||||
@@ -3629,6 +3638,11 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
|
|||||||
chat2[i] = formatMessageHistoryItem(coreChat[j], isInstruct, force_output_sequence.FIRST);
|
chat2[i] = formatMessageHistoryItem(coreChat[j], isInstruct, force_output_sequence.FIRST);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lastUserMessageIndex >= 0 && j === lastUserMessageIndex && isInstruct) {
|
||||||
|
// Reformat with the last input sequence (if any)
|
||||||
|
chat2[i] = formatMessageHistoryItem(coreChat[j], isInstruct, force_output_sequence.LAST);
|
||||||
|
}
|
||||||
|
|
||||||
// Do not suffix the message for continuation
|
// Do not suffix the message for continuation
|
||||||
if (i === 0 && isContinue) {
|
if (i === 0 && isContinue) {
|
||||||
if (isInstruct) {
|
if (isInstruct) {
|
||||||
@@ -3654,7 +3668,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
|
|||||||
mes: power_user.instruct.user_alignment_message,
|
mes: power_user.instruct.user_alignment_message,
|
||||||
is_user: true,
|
is_user: true,
|
||||||
};
|
};
|
||||||
userAlignmentMessage = formatMessageHistoryItem(alignmentMessage, isInstruct, false);
|
userAlignmentMessage = formatMessageHistoryItem(alignmentMessage, isInstruct, force_output_sequence.FIRST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call combined AN into Generate
|
// Call combined AN into Generate
|
||||||
@@ -6053,9 +6067,10 @@ async function getChatResult() {
|
|||||||
const message = getFirstMessage();
|
const message = getFirstMessage();
|
||||||
if (message.mes) {
|
if (message.mes) {
|
||||||
chat.push(message);
|
chat.push(message);
|
||||||
await saveChatConditional();
|
|
||||||
freshChat = true;
|
freshChat = true;
|
||||||
}
|
}
|
||||||
|
// Make sure the chat appears on the server
|
||||||
|
await saveChatConditional();
|
||||||
}
|
}
|
||||||
await loadItemizedPrompts(getCurrentChatId());
|
await loadItemizedPrompts(getCurrentChatId());
|
||||||
await printMessages();
|
await printMessages();
|
||||||
@@ -6107,7 +6122,7 @@ export async function openCharacterChat(file_name) {
|
|||||||
chat_metadata = {};
|
chat_metadata = {};
|
||||||
await getChat();
|
await getChat();
|
||||||
$('#selected_chat_pole').val(file_name);
|
$('#selected_chat_pole').val(file_name);
|
||||||
await createOrEditCharacter();
|
await createOrEditCharacter(new CustomEvent('newChat'));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////// OPTIMZED MAIN API CHANGE FUNCTION ////////////
|
////////// OPTIMZED MAIN API CHANGE FUNCTION ////////////
|
||||||
@@ -6809,6 +6824,11 @@ export async function displayPastChats() {
|
|||||||
const fileName = chat['file_name'];
|
const fileName = chat['file_name'];
|
||||||
const chatContent = rawChats[fileName];
|
const chatContent = rawChats[fileName];
|
||||||
|
|
||||||
|
// Make sure empty chats are displayed when there is no search query
|
||||||
|
if (Array.isArray(chatContent) && !chatContent.length && !searchQuery) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// // Uncomment this to return to old behavior (classical full-substring search).
|
// // Uncomment this to return to old behavior (classical full-substring search).
|
||||||
// return chatContent && Object.values(chatContent).some(message => message?.mes?.toLowerCase()?.includes(searchQuery.toLowerCase()));
|
// return chatContent && Object.values(chatContent).some(message => message?.mes?.toLowerCase()?.includes(searchQuery.toLowerCase()));
|
||||||
|
|
||||||
@@ -8436,6 +8456,11 @@ const CONNECT_API_MAP = {
|
|||||||
button: '#api_button_textgenerationwebui',
|
button: '#api_button_textgenerationwebui',
|
||||||
type: textgen_types.OPENROUTER,
|
type: textgen_types.OPENROUTER,
|
||||||
},
|
},
|
||||||
|
'featherless': {
|
||||||
|
selected: 'textgenerationwebui',
|
||||||
|
button: '#api_button_textgenerationwebui',
|
||||||
|
type: textgen_types.FEATHERLESS,
|
||||||
|
},
|
||||||
'huggingface': {
|
'huggingface': {
|
||||||
selected: 'textgenerationwebui',
|
selected: 'textgenerationwebui',
|
||||||
button: '#api_button_textgenerationwebui',
|
button: '#api_button_textgenerationwebui',
|
||||||
@@ -9837,8 +9862,8 @@ jQuery(async function () {
|
|||||||
hideMenu();
|
hideMenu();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#newChatFromManageScreenButton').on('click', function () {
|
$('#newChatFromManageScreenButton').on('click', async function () {
|
||||||
doNewChat({ deleteCurrentChat: false });
|
await doNewChat({ deleteCurrentChat: false });
|
||||||
$('#select_chat_cross').trigger('click');
|
$('#select_chat_cross').trigger('click');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -10810,7 +10835,7 @@ jQuery(async function () {
|
|||||||
//newSlider.val(manualInput)
|
//newSlider.val(manualInput)
|
||||||
//handleSlideEvent.call(newSlider, null, { value: parseFloat(manualInput) }, 'manual');
|
//handleSlideEvent.call(newSlider, null, { value: parseFloat(manualInput) }, 'manual');
|
||||||
valueBeforeManualInput = manualInput;
|
valueBeforeManualInput = manualInput;
|
||||||
$(masterElement).val($(this).val()).trigger('input');
|
$(masterElement).val($(this).val()).trigger('input', { forced: true });
|
||||||
} else {
|
} else {
|
||||||
//if value not ok, warn and reset to last known valid value
|
//if value not ok, warn and reset to last known valid value
|
||||||
toastr.warning(`Invalid value. Must be between ${$(this).attr('min')} and ${$(this).attr('max')}`);
|
toastr.warning(`Invalid value. Must be between ${$(this).attr('min')} and ${$(this).attr('max')}`);
|
||||||
@@ -10836,7 +10861,7 @@ jQuery(async function () {
|
|||||||
if (manualInput >= Number($(this).attr('min')) && manualInput <= Number($(this).attr('max'))) {
|
if (manualInput >= Number($(this).attr('min')) && manualInput <= Number($(this).attr('max'))) {
|
||||||
valueBeforeManualInput = manualInput;
|
valueBeforeManualInput = manualInput;
|
||||||
//set the slider value to input value
|
//set the slider value to input value
|
||||||
$(masterElement).val($(this).val()).trigger('input');
|
$(masterElement).val($(this).val()).trigger('input', { forced: true });
|
||||||
} else {
|
} else {
|
||||||
//if value not ok, warn and reset to last known valid value
|
//if value not ok, warn and reset to last known valid value
|
||||||
toastr.warning(`Invalid value. Must be between ${$(this).attr('min')} and ${$(this).attr('max')}`);
|
toastr.warning(`Invalid value. Must be between ${$(this).attr('min')} and ${$(this).attr('max')}`);
|
||||||
|
@@ -1387,7 +1387,8 @@ async function getExpressionsList() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If there was no specific list, or an error, just return the default expressions
|
// If there was no specific list, or an error, just return the default expressions
|
||||||
return DEFAULT_EXPRESSIONS;
|
expressionsList = DEFAULT_EXPRESSIONS.filter(e => e !== 'talkinghead').slice();
|
||||||
|
return expressionsList;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await resolveExpressionsList();
|
const result = await resolveExpressionsList();
|
||||||
@@ -1618,11 +1619,13 @@ async function onClickExpressionRemoveCustom() {
|
|||||||
moduleWorker();
|
moduleWorker();
|
||||||
}
|
}
|
||||||
|
|
||||||
function onExperesionApiChanged() {
|
function onExpressionApiChanged() {
|
||||||
const tempApi = this.value;
|
const tempApi = this.value;
|
||||||
if (tempApi) {
|
if (tempApi) {
|
||||||
extension_settings.expressions.api = Number(tempApi);
|
extension_settings.expressions.api = Number(tempApi);
|
||||||
$('.expression_llm_prompt_block').toggle(extension_settings.expressions.api === EXPRESSION_API.llm);
|
$('.expression_llm_prompt_block').toggle(extension_settings.expressions.api === EXPRESSION_API.llm);
|
||||||
|
expressionsList = null;
|
||||||
|
spriteCache = {};
|
||||||
moduleWorker();
|
moduleWorker();
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
}
|
}
|
||||||
@@ -1972,7 +1975,7 @@ function migrateSettings() {
|
|||||||
$('#expression_custom_add').on('click', onClickExpressionAddCustom);
|
$('#expression_custom_add').on('click', onClickExpressionAddCustom);
|
||||||
$('#expression_custom_remove').on('click', onClickExpressionRemoveCustom);
|
$('#expression_custom_remove').on('click', onClickExpressionRemoveCustom);
|
||||||
$('#expression_fallback').on('change', onExpressionFallbackChanged);
|
$('#expression_fallback').on('change', onExpressionFallbackChanged);
|
||||||
$('#expression_api').on('change', onExperesionApiChanged);
|
$('#expression_api').on('change', onExpressionApiChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pause Talkinghead to save resources when the ST tab is not visible or the window is minimized.
|
// Pause Talkinghead to save resources when the ST tab is not visible or the window is minimized.
|
||||||
|
@@ -3,6 +3,7 @@ import {
|
|||||||
this_chid,
|
this_chid,
|
||||||
characters,
|
characters,
|
||||||
getRequestHeaders,
|
getRequestHeaders,
|
||||||
|
event_types,
|
||||||
} from '../../../script.js';
|
} from '../../../script.js';
|
||||||
import { groups, selected_group } from '../../group-chats.js';
|
import { groups, selected_group } from '../../group-chats.js';
|
||||||
import { loadFileToDocument, delay } from '../../utils.js';
|
import { loadFileToDocument, delay } from '../../utils.js';
|
||||||
@@ -25,6 +26,27 @@ let paginationVisiblePages = 10;
|
|||||||
let paginationMaxLinesPerPage = 2;
|
let paginationMaxLinesPerPage = 2;
|
||||||
let galleryMaxRows = 3;
|
let galleryMaxRows = 3;
|
||||||
|
|
||||||
|
$('body').on('click', '.dragClose', function () {
|
||||||
|
const relatedId = $(this).data('related-id'); // Get the ID of the related draggable
|
||||||
|
$(`body > .draggable[id="${relatedId}"]`).remove(); // Remove the associated draggable
|
||||||
|
});
|
||||||
|
|
||||||
|
const CUSTOM_GALLERY_REMOVED_EVENT = 'galleryRemoved';
|
||||||
|
|
||||||
|
const mutationObserver = new MutationObserver((mutations) => {
|
||||||
|
mutations.forEach((mutation) => {
|
||||||
|
mutation.removedNodes.forEach((node) => {
|
||||||
|
if (node instanceof HTMLElement && node.tagName === 'DIV' && node.id === 'gallery') {
|
||||||
|
eventSource.emit(CUSTOM_GALLERY_REMOVED_EVENT);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
mutationObserver.observe(document.body, {
|
||||||
|
childList: true,
|
||||||
|
subtree: false,
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a list of gallery items based on a given URL. This function calls an API endpoint
|
* Retrieves a list of gallery items based on a given URL. This function calls an API endpoint
|
||||||
@@ -59,7 +81,9 @@ async function getGalleryItems(url) {
|
|||||||
* @returns {Promise<void>} - Promise representing the completion of the gallery initialization.
|
* @returns {Promise<void>} - Promise representing the completion of the gallery initialization.
|
||||||
*/
|
*/
|
||||||
async function initGallery(items, url) {
|
async function initGallery(items, url) {
|
||||||
|
const nonce = `nonce-${Math.random().toString(36).substring(2, 15)}`;
|
||||||
const gallery = $('#dragGallery');
|
const gallery = $('#dragGallery');
|
||||||
|
gallery.addClass(nonce);
|
||||||
gallery.nanogallery2({
|
gallery.nanogallery2({
|
||||||
'items': items,
|
'items': items,
|
||||||
thumbnailWidth: 'auto',
|
thumbnailWidth: 'auto',
|
||||||
@@ -82,16 +106,26 @@ async function initGallery(items, url) {
|
|||||||
fnThumbnailOpen: viewWithDragbox,
|
fnThumbnailOpen: viewWithDragbox,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const dragDropHandler = new DragAndDropHandler(`#dragGallery.${nonce}`, async (files, event) => {
|
||||||
eventSource.on('resizeUI', function (elmntName) {
|
|
||||||
gallery.nanogallery2('resize');
|
|
||||||
});
|
|
||||||
|
|
||||||
const dragDropHandler = new DragAndDropHandler('#dragGallery', async (files, event) => {
|
|
||||||
let file = files[0];
|
let file = files[0];
|
||||||
uploadFile(file, url); // Added url parameter to know where to upload
|
uploadFile(file, url); // Added url parameter to know where to upload
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const resizeHandler = function () {
|
||||||
|
gallery.nanogallery2('resize');
|
||||||
|
};
|
||||||
|
|
||||||
|
eventSource.on('resizeUI', resizeHandler);
|
||||||
|
|
||||||
|
eventSource.once(event_types.CHAT_CHANGED, function () {
|
||||||
|
gallery.closest('#gallery').remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
eventSource.once(CUSTOM_GALLERY_REMOVED_EVENT, function () {
|
||||||
|
gallery.nanogallery2('destroy');
|
||||||
|
dragDropHandler.destroy();
|
||||||
|
eventSource.removeListener('resizeUI', resizeHandler);
|
||||||
|
});
|
||||||
|
|
||||||
// Set dropzone height to be the same as the parent
|
// Set dropzone height to be the same as the parent
|
||||||
gallery.css('height', gallery.parent().css('height'));
|
gallery.css('height', gallery.parent().css('height'));
|
||||||
@@ -140,16 +174,10 @@ async function showCharGallery() {
|
|||||||
|
|
||||||
const items = await getGalleryItems(url);
|
const items = await getGalleryItems(url);
|
||||||
// if there already is a gallery, destroy it and place this one in its place
|
// if there already is a gallery, destroy it and place this one in its place
|
||||||
if ($('#dragGallery').length) {
|
$('#dragGallery').closest('#gallery').remove();
|
||||||
$('#dragGallery').nanogallery2('destroy');
|
makeMovable();
|
||||||
initGallery(items, url);
|
await delay(100);
|
||||||
} else {
|
await initGallery(items, url);
|
||||||
makeMovable();
|
|
||||||
setTimeout(async () => {
|
|
||||||
await initGallery(items, url);
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.trace();
|
console.trace();
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@@ -202,11 +230,11 @@ async function uploadFile(file, url) {
|
|||||||
toastr.success('File uploaded successfully. Saved at: ' + result.path);
|
toastr.success('File uploaded successfully. Saved at: ' + result.path);
|
||||||
|
|
||||||
// Refresh the gallery
|
// Refresh the gallery
|
||||||
$('#dragGallery').nanogallery2('destroy'); // Destroy old gallery
|
|
||||||
const newItems = await getGalleryItems(url); // Fetch the latest items
|
const newItems = await getGalleryItems(url); // Fetch the latest items
|
||||||
initGallery(newItems, url); // Reinitialize the gallery with new items and pass 'url'
|
$('#dragGallery').closest('#gallery').remove(); // Destroy old gallery
|
||||||
|
makeMovable();
|
||||||
|
await delay(100);
|
||||||
|
await initGallery(newItems, url); // Reinitialize the gallery with new items and pass 'url'
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('There was an issue uploading the file:', error);
|
console.error('There was an issue uploading the file:', error);
|
||||||
|
|
||||||
@@ -273,11 +301,6 @@ function makeMovable(id = 'gallery') {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
$('body').on('click', '.dragClose', function () {
|
|
||||||
const relatedId = $(this).data('related-id'); // Get the ID of the related draggable
|
|
||||||
$(`#${relatedId}`).remove(); // Remove the associated draggable
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -358,11 +381,6 @@ function makeDragImg(id, url) {
|
|||||||
} else {
|
} else {
|
||||||
console.error('Failed to append the template content or retrieve the appended content.');
|
console.error('Failed to append the template content or retrieve the appended content.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$('body').on('click', '.dragClose', function () {
|
|
||||||
const relatedId = $(this).data('related-id'); // Get the ID of the related draggable
|
|
||||||
$(`#${relatedId}`).remove(); // Remove the associated draggable
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -401,7 +419,8 @@ function viewWithDragbox(items) {
|
|||||||
|
|
||||||
|
|
||||||
// Registers a simple command for opening the char gallery.
|
// Registers a simple command for opening the char gallery.
|
||||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'show-gallery',
|
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||||
|
name: 'show-gallery',
|
||||||
aliases: ['sg'],
|
aliases: ['sg'],
|
||||||
callback: () => {
|
callback: () => {
|
||||||
showCharGallery();
|
showCharGallery();
|
||||||
@@ -409,7 +428,8 @@ SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'show-gallery
|
|||||||
},
|
},
|
||||||
helpString: 'Shows the gallery.',
|
helpString: 'Shows the gallery.',
|
||||||
}));
|
}));
|
||||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'list-gallery',
|
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||||
|
name: 'list-gallery',
|
||||||
aliases: ['lg'],
|
aliases: ['lg'],
|
||||||
callback: listGalleryCommand,
|
callback: listGalleryCommand,
|
||||||
returns: 'list of images',
|
returns: 'list of images',
|
||||||
@@ -432,14 +452,14 @@ SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'list-gallery
|
|||||||
|
|
||||||
async function listGalleryCommand(args) {
|
async function listGalleryCommand(args) {
|
||||||
try {
|
try {
|
||||||
let url = args.char ?? (args.group ? groups.find(it=>it.name == args.group)?.id : null) ?? (selected_group || this_chid);
|
let url = args.char ?? (args.group ? groups.find(it => it.name == args.group)?.id : null) ?? (selected_group || this_chid);
|
||||||
if (!args.char && !args.group && !selected_group && this_chid) {
|
if (!args.char && !args.group && !selected_group && this_chid) {
|
||||||
const char = characters[this_chid];
|
const char = characters[this_chid];
|
||||||
url = char.avatar.replace('.png', '');
|
url = char.avatar.replace('.png', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
const items = await getGalleryItems(url);
|
const items = await getGalleryItems(url);
|
||||||
return JSON.stringify(items.map(it=>it.src));
|
return JSON.stringify(items.map(it => it.src));
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.trace();
|
console.trace();
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
"optional": [
|
"optional": [
|
||||||
],
|
],
|
||||||
"js": "index.js",
|
"js": "index.js",
|
||||||
"css": "",
|
"css": "style.css",
|
||||||
"author": "City-Unit",
|
"author": "City-Unit",
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
"homePage": "https://github.com/SillyTavern/SillyTavern"
|
"homePage": "https://github.com/SillyTavern/SillyTavern"
|
||||||
|
5
public/scripts/extensions/gallery/style.css
Normal file
5
public/scripts/extensions/gallery/style.css
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.nGY2 .nGY2GalleryBottom {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
@@ -14,6 +14,7 @@ import {
|
|||||||
substituteParamsExtended,
|
substituteParamsExtended,
|
||||||
generateRaw,
|
generateRaw,
|
||||||
getMaxContextSize,
|
getMaxContextSize,
|
||||||
|
setExtensionPrompt,
|
||||||
} from '../../../script.js';
|
} from '../../../script.js';
|
||||||
import { is_group_generating, selected_group } from '../../group-chats.js';
|
import { is_group_generating, selected_group } from '../../group-chats.js';
|
||||||
import { loadMovingUIState } from '../../power-user.js';
|
import { loadMovingUIState } from '../../power-user.js';
|
||||||
@@ -73,6 +74,7 @@ const defaultSettings = {
|
|||||||
template: defaultTemplate,
|
template: defaultTemplate,
|
||||||
position: extension_prompt_types.IN_PROMPT,
|
position: extension_prompt_types.IN_PROMPT,
|
||||||
role: extension_prompt_roles.SYSTEM,
|
role: extension_prompt_roles.SYSTEM,
|
||||||
|
scan: false,
|
||||||
depth: 2,
|
depth: 2,
|
||||||
promptWords: 200,
|
promptWords: 200,
|
||||||
promptMinWords: 25,
|
promptMinWords: 25,
|
||||||
@@ -122,6 +124,7 @@ function loadSettings() {
|
|||||||
$(`input[name="memory_prompt_builder"][value="${extension_settings.memory.prompt_builder}"]`).prop('checked', true).trigger('input');
|
$(`input[name="memory_prompt_builder"][value="${extension_settings.memory.prompt_builder}"]`).prop('checked', true).trigger('input');
|
||||||
$('#memory_override_response_length').val(extension_settings.memory.overrideResponseLength).trigger('input');
|
$('#memory_override_response_length').val(extension_settings.memory.overrideResponseLength).trigger('input');
|
||||||
$('#memory_max_messages_per_request').val(extension_settings.memory.maxMessagesPerRequest).trigger('input');
|
$('#memory_max_messages_per_request').val(extension_settings.memory.maxMessagesPerRequest).trigger('input');
|
||||||
|
$('#memory_include_wi_scan').prop('checked', extension_settings.memory.scan).trigger('input');
|
||||||
switchSourceControls(extension_settings.memory.source);
|
switchSourceControls(extension_settings.memory.source);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,6 +282,13 @@ function onMemoryPositionChange(e) {
|
|||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onMemoryIncludeWIScanInput() {
|
||||||
|
const value = !!$(this).prop('checked');
|
||||||
|
extension_settings.memory.scan = value;
|
||||||
|
reinsertMemory();
|
||||||
|
saveSettingsDebounced();
|
||||||
|
}
|
||||||
|
|
||||||
function onMemoryPromptWordsForceInput() {
|
function onMemoryPromptWordsForceInput() {
|
||||||
const value = $(this).val();
|
const value = $(this).val();
|
||||||
extension_settings.memory.promptForceWords = Number(value);
|
extension_settings.memory.promptForceWords = Number(value);
|
||||||
@@ -800,8 +810,7 @@ function reinsertMemory() {
|
|||||||
* @param {number|null} index Index of the chat message to save the summary to. If null, the pre-last message is used.
|
* @param {number|null} index Index of the chat message to save the summary to. If null, the pre-last message is used.
|
||||||
*/
|
*/
|
||||||
function setMemoryContext(value, saveToMessage, index = null) {
|
function setMemoryContext(value, saveToMessage, index = null) {
|
||||||
const context = getContext();
|
setExtensionPrompt(MODULE_NAME, formatMemoryValue(value), extension_settings.memory.position, extension_settings.memory.depth, extension_settings.memory.scan, extension_settings.memory.role);
|
||||||
context.setExtensionPrompt(MODULE_NAME, formatMemoryValue(value), extension_settings.memory.position, extension_settings.memory.depth, false, extension_settings.memory.role);
|
|
||||||
$('#memory_contents').val(value);
|
$('#memory_contents').val(value);
|
||||||
|
|
||||||
const summaryLog = value
|
const summaryLog = value
|
||||||
@@ -809,6 +818,7 @@ function setMemoryContext(value, saveToMessage, index = null) {
|
|||||||
: 'Summary has no content';
|
: 'Summary has no content';
|
||||||
console.debug(summaryLog);
|
console.debug(summaryLog);
|
||||||
|
|
||||||
|
const context = getContext();
|
||||||
if (saveToMessage && context.chat.length) {
|
if (saveToMessage && context.chat.length) {
|
||||||
const idx = index ?? context.chat.length - 2;
|
const idx = index ?? context.chat.length - 2;
|
||||||
const mes = context.chat[idx < 0 ? 0 : idx];
|
const mes = context.chat[idx < 0 ? 0 : idx];
|
||||||
@@ -894,6 +904,7 @@ function setupListeners() {
|
|||||||
$('#memory_prompt_words_auto').off('click').on('click', onPromptForceWordsAutoClick);
|
$('#memory_prompt_words_auto').off('click').on('click', onPromptForceWordsAutoClick);
|
||||||
$('#memory_override_response_length').off('click').on('input', onOverrideResponseLengthInput);
|
$('#memory_override_response_length').off('click').on('input', onOverrideResponseLengthInput);
|
||||||
$('#memory_max_messages_per_request').off('click').on('input', onMaxMessagesPerRequestInput);
|
$('#memory_max_messages_per_request').off('click').on('input', onMaxMessagesPerRequestInput);
|
||||||
|
$('#memory_include_wi_scan').off('input').on('input', onMemoryIncludeWIScanInput);
|
||||||
$('#summarySettingsBlockToggle').off('click').on('click', function () {
|
$('#summarySettingsBlockToggle').off('click').on('click', function () {
|
||||||
console.log('saw settings button click');
|
console.log('saw settings button click');
|
||||||
$('#summarySettingsBlock').slideToggle(200, 'swing'); //toggleClass("hidden");
|
$('#summarySettingsBlock').slideToggle(200, 'swing'); //toggleClass("hidden");
|
||||||
|
@@ -109,7 +109,16 @@
|
|||||||
<textarea id="memory_template" class="text_pole textarea_compact" rows="2" data-i18n="[placeholder]ext_sum_memory_template_placeholder" placeholder="{{summary}} will resolve to the current summary contents."></textarea>
|
<textarea id="memory_template" class="text_pole textarea_compact" rows="2" data-i18n="[placeholder]ext_sum_memory_template_placeholder" placeholder="{{summary}} will resolve to the current summary contents."></textarea>
|
||||||
</div>
|
</div>
|
||||||
<label for="memory_position" data-i18n="ext_sum_injection_position">Injection Position</label>
|
<label for="memory_position" data-i18n="ext_sum_injection_position">Injection Position</label>
|
||||||
|
<label class="checkbox_label" for="memory_include_wi_scan" data-i18n="[title]ext_sum_include_wi_scan_desc" title="Include the latest summary in the WI scan.">
|
||||||
|
<input id="memory_include_wi_scan" type="checkbox" />
|
||||||
|
<span data-i18n="ext_sum_include_wi_scan">Include in World Info Scanning</span>
|
||||||
|
</label>
|
||||||
<div class="radio_group">
|
<div class="radio_group">
|
||||||
|
<label>
|
||||||
|
<input type="radio" name="memory_position" value="-1" />
|
||||||
|
<span data-i18n="None (not injected)">None (not injected)</span>
|
||||||
|
<i class="fa-solid fa-info-circle" title="The summary will not be injected into the prompt. You can still access it via the {{summary}} macro." data-i18n="[title]ext_sum_injection_position_none"></i>
|
||||||
|
</label>
|
||||||
<label>
|
<label>
|
||||||
<input type="radio" name="memory_position" value="2" />
|
<input type="radio" name="memory_position" value="2" />
|
||||||
<span data-i18n="Before Main Prompt / Story String">Before Main Prompt / Story String</span>
|
<span data-i18n="Before Main Prompt / Story String">Before Main Prompt / Story String</span>
|
||||||
|
@@ -335,8 +335,8 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
body .popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder {
|
body .popup:has(#qr--modalEditor) .popup-content > #qr--modalEditor > #qr--main > .qr--modal-messageContainer > #qr--modal-messageHolder {
|
||||||
min-height: 50svh;
|
min-height: 50dvh;
|
||||||
height: 50svh;
|
height: 50dvh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.popup:has(#qr--modalEditor) {
|
.popup:has(#qr--modalEditor) {
|
||||||
|
@@ -395,8 +395,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
>#qr--main>.qr--modal-messageContainer>#qr--modal-messageHolder {
|
>#qr--main>.qr--modal-messageContainer>#qr--modal-messageHolder {
|
||||||
min-height: 50svh;
|
min-height: 50dvh;
|
||||||
height: 50svh;
|
height: 50dvh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -34,6 +34,8 @@ const controls = [
|
|||||||
{ id: 'instruct_names_force_groups', property: 'names_force_groups', isCheckbox: true },
|
{ id: 'instruct_names_force_groups', property: 'names_force_groups', isCheckbox: true },
|
||||||
{ id: 'instruct_first_output_sequence', property: 'first_output_sequence', isCheckbox: false },
|
{ id: 'instruct_first_output_sequence', property: 'first_output_sequence', isCheckbox: false },
|
||||||
{ id: 'instruct_last_output_sequence', property: 'last_output_sequence', isCheckbox: false },
|
{ id: 'instruct_last_output_sequence', property: 'last_output_sequence', isCheckbox: false },
|
||||||
|
{ id: 'instruct_first_input_sequence', property: 'first_input_sequence', isCheckbox: false },
|
||||||
|
{ id: 'instruct_last_input_sequence', property: 'last_input_sequence', isCheckbox: false },
|
||||||
{ id: 'instruct_activation_regex', property: 'activation_regex', isCheckbox: false },
|
{ id: 'instruct_activation_regex', property: 'activation_regex', isCheckbox: false },
|
||||||
{ id: 'instruct_bind_to_context', property: 'bind_to_context', isCheckbox: true },
|
{ id: 'instruct_bind_to_context', property: 'bind_to_context', isCheckbox: true },
|
||||||
{ id: 'instruct_skip_examples', property: 'skip_examples', isCheckbox: true },
|
{ id: 'instruct_skip_examples', property: 'skip_examples', isCheckbox: true },
|
||||||
@@ -58,6 +60,8 @@ function migrateInstructModeSettings(settings) {
|
|||||||
system_suffix: '',
|
system_suffix: '',
|
||||||
user_alignment_message: '',
|
user_alignment_message: '',
|
||||||
last_system_sequence: '',
|
last_system_sequence: '',
|
||||||
|
first_input_sequence: '',
|
||||||
|
last_input_sequence: '',
|
||||||
names_force_groups: true,
|
names_force_groups: true,
|
||||||
skip_examples: false,
|
skip_examples: false,
|
||||||
system_same_as_user: false,
|
system_same_as_user: false,
|
||||||
@@ -253,7 +257,15 @@ export function getInstructStoppingSequences() {
|
|||||||
const system_sequence = power_user.instruct.system_sequence?.replace(/{{name}}/gi, 'System') || '';
|
const system_sequence = power_user.instruct.system_sequence?.replace(/{{name}}/gi, 'System') || '';
|
||||||
const last_system_sequence = power_user.instruct.last_system_sequence?.replace(/{{name}}/gi, 'System') || '';
|
const last_system_sequence = power_user.instruct.last_system_sequence?.replace(/{{name}}/gi, 'System') || '';
|
||||||
|
|
||||||
const combined_sequence = `${stop_sequence}\n${input_sequence}\n${output_sequence}\n${first_output_sequence}\n${last_output_sequence}\n${system_sequence}\n${last_system_sequence}`;
|
const combined_sequence = [
|
||||||
|
stop_sequence,
|
||||||
|
input_sequence,
|
||||||
|
output_sequence,
|
||||||
|
first_output_sequence,
|
||||||
|
last_output_sequence,
|
||||||
|
system_sequence,
|
||||||
|
last_system_sequence,
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
combined_sequence.split('\n').filter((line, index, self) => self.indexOf(line) === index).forEach(addInstructSequence);
|
combined_sequence.split('\n').filter((line, index, self) => self.indexOf(line) === index).forEach(addInstructSequence);
|
||||||
}
|
}
|
||||||
@@ -301,6 +313,14 @@ export function formatInstructModeChat(name, mes, isUser, isNarrator, forceAvata
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isUser) {
|
if (isUser) {
|
||||||
|
if (forceOutputSequence === force_output_sequence.FIRST) {
|
||||||
|
return power_user.instruct.first_input_sequence || power_user.instruct.input_sequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (forceOutputSequence === force_output_sequence.LAST) {
|
||||||
|
return power_user.instruct.last_input_sequence || power_user.instruct.input_sequence;
|
||||||
|
}
|
||||||
|
|
||||||
return power_user.instruct.input_sequence;
|
return power_user.instruct.input_sequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,6 +572,8 @@ export function replaceInstructMacros(input, env) {
|
|||||||
'instructStop': power_user.instruct.stop_sequence,
|
'instructStop': power_user.instruct.stop_sequence,
|
||||||
'instructUserFiller': power_user.instruct.user_alignment_message,
|
'instructUserFiller': power_user.instruct.user_alignment_message,
|
||||||
'instructSystemInstructionPrefix': power_user.instruct.last_system_sequence,
|
'instructSystemInstructionPrefix': power_user.instruct.last_system_sequence,
|
||||||
|
'instructFirstInput|instructFirstUserPrefix': power_user.instruct.first_input_sequence || power_user.instruct.input_sequence,
|
||||||
|
'instructLastInput|instructLastUserPrefix': power_user.instruct.last_input_sequence || power_user.instruct.input_sequence,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const [placeholder, value] of Object.entries(instructMacros)) {
|
for (const [placeholder, value] of Object.entries(instructMacros)) {
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
callPopup,
|
|
||||||
characters,
|
characters,
|
||||||
chat,
|
chat,
|
||||||
chat_metadata,
|
chat_metadata,
|
||||||
@@ -22,7 +21,7 @@ import { PAGINATION_TEMPLATE, debounce, delay, download, ensureImageFormatSuppor
|
|||||||
import { debounce_timeout } from './constants.js';
|
import { debounce_timeout } from './constants.js';
|
||||||
import { FILTER_TYPES, FilterHelper } from './filters.js';
|
import { FILTER_TYPES, FilterHelper } from './filters.js';
|
||||||
import { selected_group } from './group-chats.js';
|
import { selected_group } from './group-chats.js';
|
||||||
import { POPUP_TYPE, Popup } from './popup.js';
|
import { POPUP_RESULT, POPUP_TYPE, Popup } from './popup.js';
|
||||||
|
|
||||||
let savePersonasPage = 0;
|
let savePersonasPage = 0;
|
||||||
const GRID_STORAGE_KEY = 'Personas_GridView';
|
const GRID_STORAGE_KEY = 'Personas_GridView';
|
||||||
@@ -332,15 +331,14 @@ async function changeUserAvatar(e) {
|
|||||||
* @returns {Promise} Promise that resolves when the persona is set
|
* @returns {Promise} Promise that resolves when the persona is set
|
||||||
*/
|
*/
|
||||||
export async function createPersona(avatarId) {
|
export async function createPersona(avatarId) {
|
||||||
const personaName = await callPopup('<h3>Enter a name for this persona:</h3>Cancel if you\'re just uploading an avatar.', 'input', '');
|
const personaName = await Popup.show.input('Enter a name for this persona:', 'Cancel if you\'re just uploading an avatar.', '');
|
||||||
|
|
||||||
if (!personaName) {
|
if (!personaName) {
|
||||||
console.debug('User cancelled creating a persona');
|
console.debug('User cancelled creating a persona');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await delay(500);
|
const personaDescription = await Popup.show.input('Enter a description for this persona:', 'You can always add or change it later.', '', { rows: 4 });
|
||||||
const personaDescription = await callPopup('<h3>Enter a description for this persona:</h3>You can always add or change it later.', 'input', '', { rows: 4 });
|
|
||||||
|
|
||||||
initPersona(avatarId, personaName, personaDescription);
|
initPersona(avatarId, personaName, personaDescription);
|
||||||
if (power_user.persona_show_notifications) {
|
if (power_user.persona_show_notifications) {
|
||||||
@@ -349,7 +347,7 @@ export async function createPersona(avatarId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function createDummyPersona() {
|
async function createDummyPersona() {
|
||||||
const personaName = await callPopup('<h3>Enter a name for this persona:</h3>', 'input', '');
|
const personaName = await Popup.show.input('Enter a name for this persona:', null);
|
||||||
|
|
||||||
if (!personaName) {
|
if (!personaName) {
|
||||||
console.debug('User cancelled creating dummy persona');
|
console.debug('User cancelled creating dummy persona');
|
||||||
@@ -508,15 +506,20 @@ async function bindUserNameToPersona(e) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let personaUnbind = false;
|
||||||
const existingPersona = power_user.personas[avatarId];
|
const existingPersona = power_user.personas[avatarId];
|
||||||
const personaName = await callPopup('<h3>Enter a name for this persona:</h3>(If empty name is provided, this will unbind the name from this avatar)', 'input', existingPersona || '');
|
const personaName = await Popup.show.input(
|
||||||
|
'Enter a name for this persona:',
|
||||||
|
'(If empty name is provided, this will unbind the name from this avatar)',
|
||||||
|
existingPersona || '',
|
||||||
|
{ onClose: (p) => { personaUnbind = p.value === '' && p.result === POPUP_RESULT.AFFIRMATIVE; } });
|
||||||
|
|
||||||
// If the user clicked cancel, don't do anything
|
// If the user clicked cancel, don't do anything
|
||||||
if (personaName === false) {
|
if (personaName === null && !personaUnbind) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (personaName.length > 0) {
|
if (personaName && personaName.length > 0) {
|
||||||
// If the user clicked ok and entered a name, bind the name to the persona
|
// If the user clicked ok and entered a name, bind the name to the persona
|
||||||
console.log(`Binding persona ${avatarId} to name ${personaName}`);
|
console.log(`Binding persona ${avatarId} to name ${personaName}`);
|
||||||
power_user.personas[avatarId] = personaName;
|
power_user.personas[avatarId] = personaName;
|
||||||
@@ -643,7 +646,12 @@ async function lockPersona() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
power_user.personas[user_avatar] = name1;
|
power_user.personas[user_avatar] = name1;
|
||||||
power_user.persona_descriptions[user_avatar] = { description: '', position: persona_description_positions.IN_PROMPT };
|
power_user.persona_descriptions[user_avatar] = {
|
||||||
|
description: '',
|
||||||
|
position: persona_description_positions.IN_PROMPT,
|
||||||
|
depth: DEFAULT_DEPTH,
|
||||||
|
role: DEFAULT_ROLE,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
chat_metadata['persona'] = user_avatar;
|
chat_metadata['persona'] = user_avatar;
|
||||||
@@ -672,7 +680,7 @@ async function deleteUserAvatar(e) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const confirm = await callPopup('<h3>Are you sure you want to delete this avatar?</h3>All information associated with its linked persona will be lost.', 'confirm');
|
const confirm = await Popup.show.confirm('Are you sure you want to delete this avatar?', 'All information associated with its linked persona will be lost.');
|
||||||
|
|
||||||
if (!confirm) {
|
if (!confirm) {
|
||||||
console.debug('User cancelled deleting avatar');
|
console.debug('User cancelled deleting avatar');
|
||||||
@@ -806,7 +814,7 @@ async function setDefaultPersona(e) {
|
|||||||
const personaName = power_user.personas[avatarId];
|
const personaName = power_user.personas[avatarId];
|
||||||
|
|
||||||
if (avatarId === currentDefault) {
|
if (avatarId === currentDefault) {
|
||||||
const confirm = await callPopup('Are you sure you want to remove the default persona?', 'confirm');
|
const confirm = await Popup.show.confirm('Are you sure you want to remove the default persona?', personaName);
|
||||||
|
|
||||||
if (!confirm) {
|
if (!confirm) {
|
||||||
console.debug('User cancelled removing default persona');
|
console.debug('User cancelled removing default persona');
|
||||||
@@ -819,8 +827,7 @@ async function setDefaultPersona(e) {
|
|||||||
}
|
}
|
||||||
delete power_user.default_persona;
|
delete power_user.default_persona;
|
||||||
} else {
|
} else {
|
||||||
const confirm = await callPopup(`<h3>Are you sure you want to set "${personaName}" as the default persona?</h3>
|
const confirm = await Popup.show.confirm(`Are you sure you want to set "${personaName}" as the default persona?`, 'This name and avatar will be used for all new chats, as well as existing chats where the user persona is not locked.');
|
||||||
This name and avatar will be used for all new chats, as well as existing chats where the user persona is not locked.`, 'confirm');
|
|
||||||
|
|
||||||
if (!confirm) {
|
if (!confirm) {
|
||||||
console.debug('User cancelled setting default persona');
|
console.debug('User cancelled setting default persona');
|
||||||
@@ -978,7 +985,7 @@ async function onPersonasRestoreInput(e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function syncUserNameToPersona() {
|
async function syncUserNameToPersona() {
|
||||||
const confirmation = await callPopup(`<h3>Are you sure?</h3>All user-sent messages in this chat will be attributed to ${name1}.`, 'confirm');
|
const confirmation = await Popup.show.confirm('Are you sure?', `All user-sent messages in this chat will be attributed to ${name1}.`);
|
||||||
|
|
||||||
if (!confirmation) {
|
if (!confirmation) {
|
||||||
return;
|
return;
|
||||||
@@ -1001,6 +1008,42 @@ export function retriggerFirstMessageOnEmptyChat() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duplicates a persona.
|
||||||
|
* @param {string} avatarId
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async function duplicatePersona(avatarId) {
|
||||||
|
const personaName = power_user.personas[avatarId];
|
||||||
|
|
||||||
|
if (!personaName) {
|
||||||
|
toastr.warning('Chosen avatar is not a persona');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirm = await Popup.show.confirm('Are you sure you want to duplicate this persona?', personaName);
|
||||||
|
|
||||||
|
if (!confirm) {
|
||||||
|
console.debug('User cancelled duplicating persona');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newAvatarId = `${Date.now()}-${personaName.replace(/[^a-zA-Z0-9]/g, '')}.png`;
|
||||||
|
const descriptor = power_user.persona_descriptions[avatarId];
|
||||||
|
|
||||||
|
power_user.personas[newAvatarId] = personaName;
|
||||||
|
power_user.persona_descriptions[newAvatarId] = {
|
||||||
|
description: descriptor?.description ?? '',
|
||||||
|
position: descriptor?.position ?? persona_description_positions.IN_PROMPT,
|
||||||
|
depth: descriptor?.depth ?? DEFAULT_DEPTH,
|
||||||
|
role: descriptor?.role ?? DEFAULT_ROLE,
|
||||||
|
};
|
||||||
|
|
||||||
|
await uploadUserAvatar(getUserAvatar(avatarId), newAvatarId);
|
||||||
|
await getUserAvatars(true, newAvatarId);
|
||||||
|
saveSettingsDebounced();
|
||||||
|
}
|
||||||
|
|
||||||
export function initPersonas() {
|
export function initPersonas() {
|
||||||
$(document).on('click', '.bind_user_name', bindUserNameToPersona);
|
$(document).on('click', '.bind_user_name', bindUserNameToPersona);
|
||||||
$(document).on('click', '.set_default_persona', setDefaultPersona);
|
$(document).on('click', '.set_default_persona', setDefaultPersona);
|
||||||
@@ -1059,6 +1102,18 @@ export function initPersonas() {
|
|||||||
$('#avatar_upload_file').trigger('click');
|
$('#avatar_upload_file').trigger('click');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '#user_avatar_block .duplicate_persona', function (e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
const avatarId = $(this).closest('.avatar-container').find('.avatar').attr('imgfile');
|
||||||
|
|
||||||
|
if (!avatarId) {
|
||||||
|
console.log('no imgfile');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
duplicatePersona(avatarId);
|
||||||
|
});
|
||||||
|
|
||||||
$(document).on('click', '#user_avatar_block .set_persona_image', function (e) {
|
$(document).on('click', '#user_avatar_block .set_persona_image', function (e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
const avatarId = $(this).closest('.avatar-container').find('.avatar').attr('imgfile');
|
const avatarId = $(this).closest('.avatar-container').find('.avatar').attr('imgfile');
|
||||||
|
@@ -73,8 +73,8 @@ const showPopupHelper = {
|
|||||||
/**
|
/**
|
||||||
* Asynchronously displays an input popup with the given header and text, and returns the user's input.
|
* Asynchronously displays an input popup with the given header and text, and returns the user's input.
|
||||||
*
|
*
|
||||||
* @param {string} header - The header text for the popup.
|
* @param {string?} header - The header text for the popup.
|
||||||
* @param {string} text - The main text for the popup.
|
* @param {string?} text - The main text for the popup.
|
||||||
* @param {string} [defaultValue=''] - The default value for the input field.
|
* @param {string} [defaultValue=''] - The default value for the input field.
|
||||||
* @param {PopupOptions} [popupOptions={}] - Options for the popup.
|
* @param {PopupOptions} [popupOptions={}] - Options for the popup.
|
||||||
* @return {Promise<string?>} A Promise that resolves with the user's input.
|
* @return {Promise<string?>} A Promise that resolves with the user's input.
|
||||||
@@ -600,15 +600,15 @@ class PopupUtils {
|
|||||||
/**
|
/**
|
||||||
* Builds popup content with header and text below
|
* Builds popup content with header and text below
|
||||||
*
|
*
|
||||||
* @param {string} header - The header to be added to the text
|
* @param {string?} header - The header to be added to the text
|
||||||
* @param {string} text - The main text content
|
* @param {string?} text - The main text content
|
||||||
*/
|
*/
|
||||||
static BuildTextWithHeader(header, text) {
|
static BuildTextWithHeader(header, text) {
|
||||||
if (!header) {
|
if (!header) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
return `<h3>${header}</h3>
|
return `<h3>${header}</h3>
|
||||||
${text}`;
|
${text ?? ''}`; // Convert no text to empty string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2180,7 +2180,7 @@ function validateStoryString(storyString, params) {
|
|||||||
validateMissingField('personality');
|
validateMissingField('personality');
|
||||||
validateMissingField('persona');
|
validateMissingField('persona');
|
||||||
validateMissingField('scenario');
|
validateMissingField('scenario');
|
||||||
validateMissingField('system');
|
// validateMissingField('system');
|
||||||
validateMissingField('wiBefore', 'loreBefore');
|
validateMissingField('wiBefore', 'loreBefore');
|
||||||
validateMissingField('wiAfter', 'loreAfter');
|
validateMissingField('wiAfter', 'loreAfter');
|
||||||
|
|
||||||
@@ -2973,7 +2973,13 @@ function setAvgBG() {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setThemeCallback(_, text) {
|
async function setThemeCallback(_, themeName) {
|
||||||
|
if (!themeName) {
|
||||||
|
// allow reporting of the theme name if called without args
|
||||||
|
// for use in ST Scripts via pipe
|
||||||
|
return power_user.theme;
|
||||||
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const fuse = new Fuse(themes, {
|
const fuse = new Fuse(themes, {
|
||||||
keys: [
|
keys: [
|
||||||
@@ -2981,12 +2987,12 @@ async function setThemeCallback(_, text) {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
const results = fuse.search(text);
|
const results = fuse.search(themeName);
|
||||||
console.debug('Theme fuzzy search results for ' + text, results);
|
console.debug('Theme fuzzy search results for ' + themeName, results);
|
||||||
const theme = results[0]?.item;
|
const theme = results[0]?.item;
|
||||||
|
|
||||||
if (!theme) {
|
if (!theme) {
|
||||||
toastr.warning(`Could not find theme with name: ${text}`);
|
toastr.warning(`Could not find theme with name: ${themeName}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3333,10 +3339,11 @@ $(document).ready(() => {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#chat_width_slider').on('input', function (e) {
|
$('#chat_width_slider').on('input', function (e, data) {
|
||||||
|
const applyMode = data?.forced ? 'forced' : 'normal';
|
||||||
power_user.chat_width = Number(e.target.value);
|
power_user.chat_width = Number(e.target.value);
|
||||||
localStorage.setItem(storage_keys.chat_width, power_user.chat_width);
|
localStorage.setItem(storage_keys.chat_width, power_user.chat_width);
|
||||||
applyChatWidth();
|
applyChatWidth(applyMode);
|
||||||
setHotswapsDebounced();
|
setHotswapsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -3362,11 +3369,12 @@ $(document).ready(() => {
|
|||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
$('input[name="font_scale"]').on('input', async function (e) {
|
$('input[name="font_scale"]').on('input', async function (e, data) {
|
||||||
|
const applyMode = data?.forced ? 'forced' : 'normal';
|
||||||
power_user.font_scale = Number(e.target.value);
|
power_user.font_scale = Number(e.target.value);
|
||||||
$('#font_scale_counter').val(power_user.font_scale);
|
$('#font_scale_counter').val(power_user.font_scale);
|
||||||
localStorage.setItem(storage_keys.font_scale, power_user.font_scale);
|
localStorage.setItem(storage_keys.font_scale, power_user.font_scale);
|
||||||
await applyFontScale();
|
await applyFontScale(applyMode);
|
||||||
saveSettingsDebounced();
|
saveSettingsDebounced();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -4065,13 +4073,30 @@ $(document).ready(() => {
|
|||||||
callback: setThemeCallback,
|
callback: setThemeCallback,
|
||||||
unnamedArgumentList: [
|
unnamedArgumentList: [
|
||||||
SlashCommandArgument.fromProps({
|
SlashCommandArgument.fromProps({
|
||||||
description: 'name',
|
description: 'theme name',
|
||||||
typeList: [ARGUMENT_TYPE.STRING],
|
typeList: [ARGUMENT_TYPE.STRING],
|
||||||
isRequired: true,
|
|
||||||
enumProvider: () => themes.map(theme => new SlashCommandEnumValue(theme.name)),
|
enumProvider: () => themes.map(theme => new SlashCommandEnumValue(theme.name)),
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
helpString: 'sets a UI theme by name',
|
helpString: `
|
||||||
|
<div>
|
||||||
|
Sets a UI theme by name.
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
If no theme name is is provided, this will return the currently active theme.
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<strong>Example:</strong>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<pre><code>/theme Cappuccino</code></pre>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<pre><code>/theme</code></pre>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
}));
|
}));
|
||||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||||
name: 'movingui',
|
name: 'movingui',
|
||||||
|
@@ -142,9 +142,8 @@ export function initDefaultSlashCommands() {
|
|||||||
returns: 'the current background',
|
returns: 'the current background',
|
||||||
unnamedArgumentList: [
|
unnamedArgumentList: [
|
||||||
SlashCommandArgument.fromProps({
|
SlashCommandArgument.fromProps({
|
||||||
description: 'filename',
|
description: 'background filename',
|
||||||
typeList: [ARGUMENT_TYPE.STRING],
|
typeList: [ARGUMENT_TYPE.STRING],
|
||||||
isRequired: true,
|
|
||||||
enumProvider: () => [...document.querySelectorAll('.bg_example')]
|
enumProvider: () => [...document.querySelectorAll('.bg_example')]
|
||||||
.map(it => new SlashCommandEnumValue(it.getAttribute('bgfile')))
|
.map(it => new SlashCommandEnumValue(it.getAttribute('bgfile')))
|
||||||
.filter(it => it.value?.length),
|
.filter(it => it.value?.length),
|
||||||
@@ -154,12 +153,18 @@ export function initDefaultSlashCommands() {
|
|||||||
<div>
|
<div>
|
||||||
Sets a background according to the provided filename. Partial names allowed.
|
Sets a background according to the provided filename. Partial names allowed.
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
If no background is provided, this will return the currently selected background.
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<strong>Example:</strong>
|
<strong>Example:</strong>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<pre><code>/bg beach.jpg</code></pre>
|
<pre><code>/bg beach.jpg</code></pre>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<pre><code>/bg</code></pre>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
@@ -1359,7 +1364,7 @@ export function initDefaultSlashCommands() {
|
|||||||
enumProvider: commonEnumProviders.injects,
|
enumProvider: commonEnumProviders.injects,
|
||||||
}),
|
}),
|
||||||
new SlashCommandNamedArgument(
|
new SlashCommandNamedArgument(
|
||||||
'position', 'injection position', [ARGUMENT_TYPE.STRING], false, false, 'after', ['before', 'after', 'chat'],
|
'position', 'injection position', [ARGUMENT_TYPE.STRING], false, false, 'after', ['before', 'after', 'chat', 'none'],
|
||||||
),
|
),
|
||||||
new SlashCommandNamedArgument(
|
new SlashCommandNamedArgument(
|
||||||
'depth', 'injection depth', [ARGUMENT_TYPE.NUMBER], false, false, '4',
|
'depth', 'injection depth', [ARGUMENT_TYPE.NUMBER], false, false, '4',
|
||||||
@@ -1387,7 +1392,7 @@ export function initDefaultSlashCommands() {
|
|||||||
'text', [ARGUMENT_TYPE.STRING], false,
|
'text', [ARGUMENT_TYPE.STRING], false,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
helpString: 'Injects a text into the LLM prompt for the current chat. Requires a unique injection ID. Positions: "before" main prompt, "after" main prompt, in-"chat" (default: after). Depth: injection depth for the prompt (default: 4). Role: role for in-chat injections (default: system). Scan: include injection content into World Info scans (default: false).',
|
helpString: 'Injects a text into the LLM prompt for the current chat. Requires a unique injection ID. Positions: "before" main prompt, "after" main prompt, in-"chat", hidden with "none" (default: after). Depth: injection depth for the prompt (default: 4). Role: role for in-chat injections (default: system). Scan: include injection content into World Info scans (default: false). Hidden injects in "none" position are not inserted into the prompt but can be used for triggering WI entries.',
|
||||||
}));
|
}));
|
||||||
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
|
||||||
name: 'listinjects',
|
name: 'listinjects',
|
||||||
@@ -1504,6 +1509,7 @@ function injectCallback(args, value) {
|
|||||||
'before': extension_prompt_types.BEFORE_PROMPT,
|
'before': extension_prompt_types.BEFORE_PROMPT,
|
||||||
'after': extension_prompt_types.IN_PROMPT,
|
'after': extension_prompt_types.IN_PROMPT,
|
||||||
'chat': extension_prompt_types.IN_CHAT,
|
'chat': extension_prompt_types.IN_CHAT,
|
||||||
|
'none': extension_prompt_types.NONE,
|
||||||
};
|
};
|
||||||
const roles = {
|
const roles = {
|
||||||
'system': extension_prompt_roles.SYSTEM,
|
'system': extension_prompt_roles.SYSTEM,
|
||||||
@@ -2879,7 +2885,6 @@ export async function sendMessageAs(args, text) {
|
|||||||
|
|
||||||
if (args.name) {
|
if (args.name) {
|
||||||
name = args.name.trim();
|
name = args.name.trim();
|
||||||
mesText = text.trim();
|
|
||||||
|
|
||||||
if (!name && !text) {
|
if (!name && !text) {
|
||||||
toastr.warning('You must specify a name and text to send as');
|
toastr.warning('You must specify a name and text to send as');
|
||||||
@@ -2892,8 +2897,14 @@ export async function sendMessageAs(args, text) {
|
|||||||
localStorage.setItem(namelessWarningKey, 'true');
|
localStorage.setItem(namelessWarningKey, 'true');
|
||||||
}
|
}
|
||||||
name = name2;
|
name = name2;
|
||||||
|
if (!text) {
|
||||||
|
toastr.warning('You must specify text to send as');
|
||||||
|
return '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mesText = text.trim();
|
||||||
|
|
||||||
// Requires a regex check after the slash command is pushed to output
|
// Requires a regex check after the slash command is pushed to output
|
||||||
mesText = getRegexedString(mesText, regex_placement.SLASH_COMMAND, { characterOverride: name });
|
mesText = getRegexedString(mesText, regex_placement.SLASH_COMMAND, { characterOverride: name });
|
||||||
|
|
||||||
|
@@ -72,6 +72,8 @@
|
|||||||
<li><tt>{{instructSystemInstructionPrefix}}</tt> – <span data-i18n="help_macros_56">instruct system instruction prefix</span></li>
|
<li><tt>{{instructSystemInstructionPrefix}}</tt> – <span data-i18n="help_macros_56">instruct system instruction prefix</span></li>
|
||||||
<li><tt>{{instructUserFiller}}</tt> – <span data-i18n="help_macros_57">instruct first user message filler</span></li>
|
<li><tt>{{instructUserFiller}}</tt> – <span data-i18n="help_macros_57">instruct first user message filler</span></li>
|
||||||
<li><tt>{{instructStop}}</tt> – <span data-i18n="help_macros_58">instruct stop sequence</span></li>
|
<li><tt>{{instructStop}}</tt> – <span data-i18n="help_macros_58">instruct stop sequence</span></li>
|
||||||
|
<li><tt>{{instructFirstUserPrefix}}</tt> – <span data-i18n="help_macros_first_user">instruct user first input sequence</span></li>
|
||||||
|
<li><tt>{{instructLastUserPrefix}}</tt> – <span data-i18n="help_macros_last_user">instruct user last input sequence</span></li>
|
||||||
</ul>
|
</ul>
|
||||||
<div data-i18n="Chat variables Macros:">
|
<div data-i18n="Chat variables Macros:">
|
||||||
Chat variables Macros:
|
Chat variables Macros:
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
<div id="tabby_downloader_popup">
|
<div id="tabby_downloader_popup">
|
||||||
<div>
|
<div>
|
||||||
<h3><strong data-i18n="">Download Model</strong>
|
<h3><strong data-i18n="Download Model">Download Model</strong>
|
||||||
<a href="https://github.com/theroyallab/async-hf-downloader" class="notes-link" target="_blank">
|
<a href="https://github.com/theroyallab/async-hf-downloader" class="notes-link" target="_blank">
|
||||||
<span class="note-link-span">?</span>
|
<span class="note-link-span">?</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -58,4 +58,4 @@
|
|||||||
<textarea class="text_pole textarea_compact" name="tabby_download_exclude" placeholder="Ex. *.txt"></textarea>
|
<textarea class="text_pole textarea_compact" name="tabby_download_exclude" placeholder="Ex. *.txt"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -31,7 +31,7 @@
|
|||||||
<h3 data-i18n="Confused or lost?">Confused or lost?</h3>
|
<h3 data-i18n="Confused or lost?">Confused or lost?</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<span class="note-link-span"><a class="fa-solid fa-circle-question" target="_blank" href="https://docs.sillytavern.app/" data-i18n=""></a></span> - <span data-i18n="click these icons!">click these icons!</span>
|
<span class="note-link-span"><a class="fa-solid fa-circle-question" target="_blank" href="https://docs.sillytavern.app/"></a></span> - <span data-i18n="click these icons!">click these icons!</span>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span data-i18n="Enter">Enter </span><code>/?</code><span data-i18n="in the chat bar"> in the chat bar</span>
|
<span data-i18n="Enter">Enter </span><code>/?</code><span data-i18n="in the chat bar"> in the chat bar</span>
|
||||||
|
@@ -1184,7 +1184,7 @@ export function getTextGenGenerationData(finalPrompt, maxTokens, isImpersonate,
|
|||||||
if (settings.type === HUGGINGFACE) {
|
if (settings.type === HUGGINGFACE) {
|
||||||
params.top_p = Math.min(Math.max(Number(params.top_p), 0.0), 0.999);
|
params.top_p = Math.min(Math.max(Number(params.top_p), 0.0), 0.999);
|
||||||
params.stop = Array.isArray(params.stop) ? params.stop.slice(0, 4) : [];
|
params.stop = Array.isArray(params.stop) ? params.stop.slice(0, 4) : [];
|
||||||
nonAphroditeParams.seed = settings.seed >= 0 ? settings.seed : undefined;
|
nonAphroditeParams.seed = settings.seed >= 0 ? settings.seed : Math.floor(Math.random() * Math.pow(2, 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.type === MANCER) {
|
if (settings.type === MANCER) {
|
||||||
|
@@ -704,6 +704,22 @@ export function isOdd(number) {
|
|||||||
return number % 2 !== 0;
|
return number % 2 !== 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two moment objects for sorting.
|
||||||
|
* @param {moment.Moment} a The first moment object.
|
||||||
|
* @param {moment.Moment} b The second moment object.
|
||||||
|
* @returns {number} A negative number if a is before b, a positive number if a is after b, or 0 if they are equal.
|
||||||
|
*/
|
||||||
|
export function sortMoments(a, b) {
|
||||||
|
if (a.isBefore(b)) {
|
||||||
|
return 1;
|
||||||
|
} else if (a.isAfter(b)) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const dateCache = new Map();
|
const dateCache = new Map();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -717,26 +733,27 @@ export function timestampToMoment(timestamp) {
|
|||||||
return dateCache.get(timestamp);
|
return dateCache.get(timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
const moment = parseTimestamp(timestamp);
|
const iso8601 = parseTimestamp(timestamp);
|
||||||
dateCache.set(timestamp, moment);
|
const objMoment = iso8601 ? moment(iso8601) : moment.invalid();
|
||||||
return moment;
|
|
||||||
|
dateCache.set(timestamp, objMoment);
|
||||||
|
return objMoment;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a timestamp and returns a moment object representing the parsed date and time.
|
* Parses a timestamp and returns a moment object representing the parsed date and time.
|
||||||
* @param {string|number} timestamp - The timestamp to parse. It can be a string or a number.
|
* @param {string|number} timestamp - The timestamp to parse. It can be a string or a number.
|
||||||
* @returns {moment.Moment} - A moment object representing the parsed date and time. If the timestamp is invalid, an invalid moment object is returned.
|
* @returns {string} - If the timestamp is valid, returns an ISO 8601 string.
|
||||||
*/
|
*/
|
||||||
function parseTimestamp(timestamp) {
|
function parseTimestamp(timestamp) {
|
||||||
if (!timestamp) return moment.invalid();
|
if (!timestamp) return;
|
||||||
|
|
||||||
// Unix time (legacy TAI / tags)
|
// Unix time (legacy TAI / tags)
|
||||||
if (typeof timestamp === 'number' || /^\d+$/.test(timestamp)) {
|
if (typeof timestamp === 'number' || /^\d+$/.test(timestamp)) {
|
||||||
const number = Number(timestamp);
|
const unixTime = Number(timestamp);
|
||||||
if (isNaN(number)) return moment.invalid();
|
const isValid = Number.isFinite(unixTime) && !Number.isNaN(unixTime) && unixTime >= 0;
|
||||||
if (!isFinite(number)) return moment.invalid();
|
if (!isValid) return;
|
||||||
if (number < 0) return moment.invalid();
|
return new Date(unixTime).toISOString();
|
||||||
return moment(number);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let dtFmt = [];
|
let dtFmt = [];
|
||||||
@@ -760,32 +777,12 @@ function parseTimestamp(timestamp) {
|
|||||||
// 2024-6-5 @14h 56m 50s 682ms
|
// 2024-6-5 @14h 56m 50s 682ms
|
||||||
dtFmt.push({ callback: convertFromHumanized, pattern: /(\d{4})-(\d{1,2})-(\d{1,2}) @(\d{1,2})h (\d{1,2})m (\d{1,2})s (\d{1,3})ms/ });
|
dtFmt.push({ callback: convertFromHumanized, pattern: /(\d{4})-(\d{1,2})-(\d{1,2}) @(\d{1,2})h (\d{1,2})m (\d{1,2})s (\d{1,3})ms/ });
|
||||||
|
|
||||||
let iso8601;
|
|
||||||
for (const x of dtFmt) {
|
for (const x of dtFmt) {
|
||||||
let rgxMatch = timestamp.match(x.pattern);
|
let rgxMatch = timestamp.match(x.pattern);
|
||||||
if (!rgxMatch) continue;
|
if (!rgxMatch) continue;
|
||||||
iso8601 = x.callback(...rgxMatch);
|
return x.callback(...rgxMatch);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If one of the patterns matched, return a valid moment object, otherwise return an invalid moment object
|
|
||||||
return iso8601 ? moment(iso8601) : moment.invalid();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compare two moment objects for sorting.
|
|
||||||
* @param {moment.Moment} a The first moment object.
|
|
||||||
* @param {moment.Moment} b The second moment object.
|
|
||||||
* @returns {number} A negative number if a is before b, a positive number if a is after b, or 0 if they are equal.
|
|
||||||
*/
|
|
||||||
export function sortMoments(a, b) {
|
|
||||||
if (a.isBefore(b)) {
|
|
||||||
return 1;
|
|
||||||
} else if (a.isAfter(b)) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Split string to parts no more than length in size.
|
/** Split string to parts no more than length in size.
|
||||||
|
@@ -893,7 +893,7 @@ function registerWorldInfoSlashCommands() {
|
|||||||
* @param {boolean} [loadIfNotSelected=false] - Indicates whether to load the file even if it's not currently selected
|
* @param {boolean} [loadIfNotSelected=false] - Indicates whether to load the file even if it's not currently selected
|
||||||
*/
|
*/
|
||||||
function reloadEditor(file, loadIfNotSelected = false) {
|
function reloadEditor(file, loadIfNotSelected = false) {
|
||||||
const currentIndex = $('#world_editor_select').val();
|
const currentIndex = Number($('#world_editor_select').val());
|
||||||
const selectedIndex = world_names.indexOf(file);
|
const selectedIndex = world_names.indexOf(file);
|
||||||
if (selectedIndex !== -1 && (loadIfNotSelected || currentIndex === selectedIndex)) {
|
if (selectedIndex !== -1 && (loadIfNotSelected || currentIndex === selectedIndex)) {
|
||||||
$('#world_editor_select').val(selectedIndex).trigger('change');
|
$('#world_editor_select').val(selectedIndex).trigger('change');
|
||||||
@@ -1647,32 +1647,38 @@ function sortEntries(data) {
|
|||||||
|
|
||||||
if (!data.length) return data;
|
if (!data.length) return data;
|
||||||
|
|
||||||
|
/** @type {(a: any, b: any) => number} */
|
||||||
|
let primarySort;
|
||||||
|
|
||||||
|
// Secondary and tertiary it will always be sorted by Order descending, and last UID ascending
|
||||||
|
// This is the most sensible approach for sorts where the primary sort has a lot of equal values
|
||||||
|
const secondarySort = (a, b) => b.order - a.order;
|
||||||
|
const tertiarySort = (a, b) => a.uid - b.uid;
|
||||||
|
|
||||||
// If we have a search term for WI, we are sorting by weighting scores
|
// If we have a search term for WI, we are sorting by weighting scores
|
||||||
if (sortRule === 'search') {
|
if (sortRule === 'search') {
|
||||||
data.sort((a, b) => {
|
primarySort = (a, b) => {
|
||||||
const aScore = worldInfoFilter.getScore(FILTER_TYPES.WORLD_INFO_SEARCH, a.uid);
|
const aScore = worldInfoFilter.getScore(FILTER_TYPES.WORLD_INFO_SEARCH, a.uid);
|
||||||
const bScore = worldInfoFilter.getScore(FILTER_TYPES.WORLD_INFO_SEARCH, b.uid);
|
const bScore = worldInfoFilter.getScore(FILTER_TYPES.WORLD_INFO_SEARCH, b.uid);
|
||||||
return (aScore - bScore);
|
return aScore - bScore;
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
else if (sortRule === 'custom') {
|
else if (sortRule === 'custom') {
|
||||||
// First by display index, then by order, then by uid
|
// First by display index
|
||||||
data.sort((a, b) => {
|
primarySort = (a, b) => {
|
||||||
const aValue = a.displayIndex;
|
const aValue = a.displayIndex;
|
||||||
const bValue = b.displayIndex;
|
const bValue = b.displayIndex;
|
||||||
|
return aValue - bValue;
|
||||||
return (aValue - bValue || b.order - a.order || a.uid - b.uid);
|
};
|
||||||
});
|
|
||||||
} else if (sortRule === 'priority') {
|
} else if (sortRule === 'priority') {
|
||||||
// First constant, then normal, then disabled. Then sort by order
|
// First constant, then normal, then disabled.
|
||||||
data.sort((a, b) => {
|
primarySort = (a, b) => {
|
||||||
const aValue = a.constant ? 0 : a.disable ? 2 : 1;
|
const aValue = a.constant ? 0 : a.disable ? 2 : 1;
|
||||||
const bValue = b.constant ? 0 : b.disable ? 2 : 1;
|
const bValue = b.constant ? 0 : b.disable ? 2 : 1;
|
||||||
|
return aValue - bValue;
|
||||||
return (aValue - bValue || b.order - a.order);
|
};
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
const primarySort = (a, b) => {
|
primarySort = (a, b) => {
|
||||||
const aValue = a[sortField];
|
const aValue = a[sortField];
|
||||||
const bValue = b[sortField];
|
const bValue = b[sortField];
|
||||||
|
|
||||||
@@ -1690,26 +1696,12 @@ function sortEntries(data) {
|
|||||||
// Sort numbers
|
// Sort numbers
|
||||||
return orderSign * (Number(aValue) - Number(bValue));
|
return orderSign * (Number(aValue) - Number(bValue));
|
||||||
};
|
};
|
||||||
const secondarySort = (a, b) => a.order - b.order;
|
|
||||||
const tertiarySort = (a, b) => a.uid - b.uid;
|
|
||||||
|
|
||||||
data.sort((a, b) => {
|
|
||||||
const primary = primarySort(a, b);
|
|
||||||
|
|
||||||
if (primary !== 0) {
|
|
||||||
return primary;
|
|
||||||
}
|
|
||||||
|
|
||||||
const secondary = secondarySort(a, b);
|
|
||||||
|
|
||||||
if (secondary !== 0) {
|
|
||||||
return secondary;
|
|
||||||
}
|
|
||||||
|
|
||||||
return tertiarySort(a, b);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.sort((a, b) => {
|
||||||
|
return primarySort(a, b) || secondarySort(a, b) || tertiarySort(a, b);
|
||||||
|
});
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1939,39 +1931,43 @@ function displayWorldEntries(name, data, navigation = navigation_option.none, fl
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#world_apply_custom_sorting').off('click').on('click', async () => {
|
$('#world_apply_current_sorting').off('click').on('click', async () => {
|
||||||
const entryCount = Object.keys(data.entries).length;
|
const entryCount = Object.keys(data.entries).length;
|
||||||
const moreThan100 = entryCount > 100;
|
const moreThan100 = entryCount > 100;
|
||||||
|
|
||||||
let content = '<span>Apply your custom sorting to the "Order" field. The Order values will go down from the chosen number.</span>';
|
let content = '<span>Apply your current sorting to the "Order" field. The Order values will go down from the chosen number.</span>';
|
||||||
if (moreThan100) {
|
if (moreThan100) {
|
||||||
content += `<div class="m-t-1"><i class="fa-solid fa-triangle-exclamation" style="color: #FFD43B;"></i> More than 100 entries in this world. If you don't choose a number higher than that, the lower entries will default to 0.<br />(Usual default: 100)<br />Minimum: ${entryCount}</div>`;
|
content += `<div class="m-t-1"><i class="fa-solid fa-triangle-exclamation" style="color: #FFD43B;"></i> More than 100 entries in this world. If you don't choose a number higher than that, the lower entries will default to 0.<br />(Usual default: 100)<br />Minimum: ${entryCount}</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await Popup.show.input('Apply Custom Sorting', content, '100', { okButton: 'Apply', cancelButton: 'Cancel' });
|
const result = await Popup.show.input('Apply Current Sorting', content, '100', { okButton: 'Apply', cancelButton: 'Cancel' });
|
||||||
if (!result) return;
|
if (!result) return;
|
||||||
|
|
||||||
const start = Number(result);
|
const start = Number(result);
|
||||||
if (isNaN(start) || start < 0) {
|
if (isNaN(start) || start < 0) {
|
||||||
toastr.error('Invalid number: ' + result, 'Apply Custom Sorting');
|
toastr.error('Invalid number: ' + result, 'Apply Current Sorting');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (start < entryCount) {
|
if (start < entryCount) {
|
||||||
toastr.warning('A number lower than the entry count has been chosen. All entries below that will default to 0.', 'Apply Custom Sorting');
|
toastr.warning('A number lower than the entry count has been chosen. All entries below that will default to 0.', 'Apply Current Sorting');
|
||||||
}
|
}
|
||||||
|
|
||||||
let counter = 0;
|
// We need to sort the entries here, as the data source isn't sorted
|
||||||
for (const entry of Object.values(data.entries)) {
|
const entries = Object.values(data.entries);
|
||||||
const newOrder = Math.max(start - (entry.displayIndex ?? 0), 0);
|
sortEntries(entries);
|
||||||
|
|
||||||
|
let updated = 0, current = start;
|
||||||
|
for (const entry of entries) {
|
||||||
|
const newOrder = Math.max(current--, 0);
|
||||||
if (entry.order === newOrder) continue;
|
if (entry.order === newOrder) continue;
|
||||||
|
|
||||||
entry.order = newOrder;
|
entry.order = newOrder;
|
||||||
setOriginalDataValue(data, entry.order, 'order', entry.order);
|
setOriginalDataValue(data, entry.order, 'order', entry.order);
|
||||||
counter++;
|
updated++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (counter > 0) {
|
if (updated > 0) {
|
||||||
toastr.info(`Updated ${counter} Order values`, 'Apply Custom Sorting');
|
toastr.info(`Updated ${updated} Order values`, 'Apply Custom Sorting');
|
||||||
await saveWorldInfo(name, data, true);
|
await saveWorldInfo(name, data, true);
|
||||||
updateEditor(navigation_option.previous);
|
updateEditor(navigation_option.previous);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -137,7 +137,6 @@ body {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
/*fallback for JS load*/
|
/*fallback for JS load*/
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
height: 100svh;
|
|
||||||
height: 100dvh;
|
height: 100dvh;
|
||||||
/*defaults as 100%, then reassigned via JS as pixels, will work on PC and Android*/
|
/*defaults as 100%, then reassigned via JS as pixels, will work on PC and Android*/
|
||||||
/*height: calc(var(--doc-height) - 1px);*/
|
/*height: calc(var(--doc-height) - 1px);*/
|
||||||
@@ -451,7 +450,7 @@ code {
|
|||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
background-color: var(--black70a);
|
background-color: var(--black70a);
|
||||||
padding: 0 3px;
|
padding: 0 3px;
|
||||||
/* max-width: calc(100svw - 95px); */
|
/* max-width: calc(100dvw - 95px); */
|
||||||
line-height: var(--mainFontSize);
|
line-height: var(--mainFontSize);
|
||||||
color: var(--white70a);
|
color: var(--white70a);
|
||||||
}
|
}
|
||||||
@@ -535,13 +534,13 @@ body.reduced-motion #bg_custom {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
/* -1px to give sheld some wiggle room to bounce off tobar when moving*/
|
/* -1px to give sheld some wiggle room to bounce off tobar when moving*/
|
||||||
height: calc(100vh - var(--topBarBlockSize) - 1px);
|
height: calc(100vh - var(--topBarBlockSize) - 1px);
|
||||||
height: calc(100svh - var(--topBarBlockSize) - 1px);
|
height: calc(100dvh - var(--topBarBlockSize) - 1px);
|
||||||
max-height: calc(100svh - var(--topBarBlockSize) - 1px);
|
max-height: calc(100dvh - var(--topBarBlockSize) - 1px);
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
/* max-width: 50vw; */
|
/* max-width: 50vw; */
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: calc((100vw - var(--sheldWidth))/2);
|
left: calc((100vw - var(--sheldWidth))/2);
|
||||||
left: calc((100svw - var(--sheldWidth))/2);
|
left: calc((100dvw - var(--sheldWidth))/2);
|
||||||
top: var(--topBarBlockSize);
|
top: var(--topBarBlockSize);
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
left: 0;
|
left: 0;
|
||||||
@@ -1160,12 +1159,12 @@ textarea {
|
|||||||
font-family: var(--mainFontFamily);
|
font-family: var(--mainFontFamily);
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
max-height: 90vh;
|
max-height: 90vh;
|
||||||
max-height: 90svh;
|
max-height: 90dvh;
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea.autoSetHeight {
|
textarea.autoSetHeight {
|
||||||
max-height: 50vh;
|
max-height: 50vh;
|
||||||
max-height: 50svh;
|
max-height: 50dvh;
|
||||||
}
|
}
|
||||||
|
|
||||||
input,
|
input,
|
||||||
@@ -1179,7 +1178,7 @@ select {
|
|||||||
min-height: calc(var(--bottomFormBlockSize) + 2px);
|
min-height: calc(var(--bottomFormBlockSize) + 2px);
|
||||||
height: calc(var(--bottomFormBlockSize) + 2px);
|
height: calc(var(--bottomFormBlockSize) + 2px);
|
||||||
max-height: 50vh;
|
max-height: 50vh;
|
||||||
max-height: 50svh;
|
max-height: 50dvh;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
display: block;
|
display: block;
|
||||||
@@ -2159,14 +2158,14 @@ textarea::placeholder {
|
|||||||
@media screen and (max-width: 1000px) {
|
@media screen and (max-width: 1000px) {
|
||||||
#form_create textarea {
|
#form_create textarea {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
min-height: 20svh;
|
min-height: 20dvh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 1001px) {
|
@media screen and (min-width: 1001px) {
|
||||||
#description_textarea {
|
#description_textarea {
|
||||||
height: 29vh;
|
height: 29vh;
|
||||||
height: 29svh;
|
height: 29dvh;
|
||||||
}
|
}
|
||||||
|
|
||||||
#firstmessage_textarea {
|
#firstmessage_textarea {
|
||||||
@@ -2442,8 +2441,8 @@ input[type="file"] {
|
|||||||
#floatingPrompt,
|
#floatingPrompt,
|
||||||
#cfgConfig {
|
#cfgConfig {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
max-width: 90svw;
|
max-width: 90dvw;
|
||||||
max-height: 90svh;
|
max-height: 90dvh;
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
@@ -2459,7 +2458,7 @@ input[type="file"] {
|
|||||||
top: 0;
|
top: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
right: unset;
|
right: unset;
|
||||||
width: calc(((100svw - var(--sheldWidth)) / 2) - 1px);
|
width: calc(((100dvw - var(--sheldWidth)) / 2) - 1px);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2816,7 +2815,7 @@ input[type=search]:focus::-webkit-search-cancel-button {
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
width: calc(var(--sheldWidth) - 10px);
|
width: calc(var(--sheldWidth) - 10px);
|
||||||
max-width: 100vw;
|
max-width: 100vw;
|
||||||
max-width: 100svw;
|
max-width: 100dvw;
|
||||||
justify-content: space-evenly;
|
justify-content: space-evenly;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3080,6 +3079,10 @@ grammarly-extension {
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.avatar-container .avatar-buttons .menu_button {
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
/* Ross should be able to handle this later */
|
/* Ross should be able to handle this later */
|
||||||
/*.big-avatars .avatar-buttons{
|
/*.big-avatars .avatar-buttons{
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -3171,7 +3174,7 @@ grammarly-extension {
|
|||||||
#dialogue_popup {
|
#dialogue_popup {
|
||||||
width: 500px;
|
width: 500px;
|
||||||
max-width: 90vw;
|
max-width: 90vw;
|
||||||
max-width: 90svw;
|
max-width: 90dvw;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
@@ -3187,7 +3190,7 @@ grammarly-extension {
|
|||||||
background-color: var(--SmartThemeBlurTintColor);
|
background-color: var(--SmartThemeBlurTintColor);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
max-height: 90vh;
|
max-height: 90vh;
|
||||||
max-height: 90svh;
|
max-height: 90dvh;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
@@ -3201,9 +3204,9 @@ grammarly-extension {
|
|||||||
|
|
||||||
.large_dialogue_popup {
|
.large_dialogue_popup {
|
||||||
height: 90vh !important;
|
height: 90vh !important;
|
||||||
height: 90svh !important;
|
height: 90dvh !important;
|
||||||
max-width: 90vw !important;
|
max-width: 90vw !important;
|
||||||
max-width: 90svw !important;
|
max-width: 90dvw !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wide_dialogue_popup {
|
.wide_dialogue_popup {
|
||||||
@@ -3360,7 +3363,7 @@ grammarly-extension {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
height: 100svh;
|
height: 100dvh;
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
@@ -3368,9 +3371,9 @@ grammarly-extension {
|
|||||||
#bgtest {
|
#bgtest {
|
||||||
display: none;
|
display: none;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
width: 100svw;
|
width: 100dvw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
height: 100svh;
|
height: 100dvh;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: -100;
|
z-index: -100;
|
||||||
background-color: red;
|
background-color: red;
|
||||||
@@ -4007,7 +4010,7 @@ input[type="range"]::-webkit-slider-thumb {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
height: 100svh;
|
height: 100dvh;
|
||||||
z-index: 2058;
|
z-index: 2058;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4020,11 +4023,11 @@ input[type="range"]::-webkit-slider-thumb {
|
|||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
max-width: var(--sheldWidth);
|
max-width: var(--sheldWidth);
|
||||||
height: calc(100vh - 84px);
|
height: calc(100vh - 84px);
|
||||||
height: calc(100svh - 84px);
|
height: calc(100dvh - 84px);
|
||||||
min-height: calc(100vh - 84px);
|
min-height: calc(100vh - 84px);
|
||||||
min-height: calc(100svh - 84px);
|
min-height: calc(100dvh - 84px);
|
||||||
max-height: calc(100vh - 84px);
|
max-height: calc(100vh - 84px);
|
||||||
max-height: calc(100svh - 84px);
|
max-height: calc(100dvh - 84px);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 4001;
|
z-index: 4001;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
@@ -4103,7 +4106,7 @@ h5 {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
height: 100svh;
|
height: 100dvh;
|
||||||
z-index: 4100;
|
z-index: 4100;
|
||||||
top: 0;
|
top: 0;
|
||||||
background-color: var(--black70a);
|
background-color: var(--black70a);
|
||||||
@@ -4117,7 +4120,7 @@ h5 {
|
|||||||
max-width: var(--sheldWidth);
|
max-width: var(--sheldWidth);
|
||||||
height: min-content;
|
height: min-content;
|
||||||
max-height: calc(100vh - var(--topBarBlockSize));
|
max-height: calc(100vh - var(--topBarBlockSize));
|
||||||
max-height: calc(100svh - var(--topBarBlockSize));
|
max-height: calc(100dvh - var(--topBarBlockSize));
|
||||||
min-height: 100px;
|
min-height: 100px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 2066;
|
z-index: 2066;
|
||||||
@@ -4437,14 +4440,14 @@ a {
|
|||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
max-width: calc(((100vw - 500px) / 2) - 10px);
|
max-width: calc(((100vw - 500px) / 2) - 10px);
|
||||||
max-width: calc(((100svw - 500px) / 2) - 10px);
|
max-width: calc(((100dvw - 500px) / 2) - 10px);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
z-index: 9999;
|
z-index: 9999;
|
||||||
max-height: 90vh;
|
max-height: 90vh;
|
||||||
max-height: 90svh;
|
max-height: 90dvh;
|
||||||
/*unsure why, but this prevents scrollbars*/
|
/*unsure why, but this prevents scrollbars*/
|
||||||
height: 49vh;
|
height: 49vh;
|
||||||
height: 49svh;
|
height: 49dvh;
|
||||||
|
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
@@ -4480,11 +4483,11 @@ a {
|
|||||||
|
|
||||||
#right-nav-panel {
|
#right-nav-panel {
|
||||||
width: calc((100vw - var(--sheldWidth) - 2px) /2);
|
width: calc((100vw - var(--sheldWidth) - 2px) /2);
|
||||||
width: calc((100svw - var(--sheldWidth) - 2px) /2);
|
width: calc((100dvw - var(--sheldWidth) - 2px) /2);
|
||||||
max-height: calc(100vh - var(--topBarBlockSize));
|
max-height: calc(100vh - var(--topBarBlockSize));
|
||||||
max-height: calc(100svh - var(--topBarBlockSize));
|
max-height: calc(100dvh - var(--topBarBlockSize));
|
||||||
height: calc(100vh - var(--topBarBlockSize));
|
height: calc(100vh - var(--topBarBlockSize));
|
||||||
height: calc(100svh - var(--topBarBlockSize));
|
height: calc(100dvh - var(--topBarBlockSize));
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -4537,7 +4540,7 @@ a {
|
|||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
max-height: 40vh;
|
max-height: 40vh;
|
||||||
max-height: 40svh;
|
max-height: 40dvh;
|
||||||
image-rendering: -webkit-optimize-contrast;
|
image-rendering: -webkit-optimize-contrast;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4629,18 +4632,18 @@ body:not(.caption) .mes_img_caption {
|
|||||||
|
|
||||||
.img_enlarged_container pre {
|
.img_enlarged_container pre {
|
||||||
max-height: 25vh;
|
max-height: 25vh;
|
||||||
max-height: 25svh;
|
max-height: 25dvh;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup:has(.img_enlarged.zoomed).large_dialogue_popup {
|
.popup:has(.img_enlarged.zoomed).large_dialogue_popup {
|
||||||
height: 100vh !important;
|
height: 100vh !important;
|
||||||
height: 100svh !important;
|
height: 100dvh !important;
|
||||||
max-height: 100vh !important;
|
max-height: 100vh !important;
|
||||||
max-height: 100svh !important;
|
max-height: 100dvh !important;
|
||||||
max-width: 100vw !important;
|
max-width: 100vw !important;
|
||||||
max-width: 100svw !important;
|
max-width: 100dvw !important;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4827,7 +4830,7 @@ body:has(#character_popup.open) #top-settings-holder:has(.drawer-content.openDra
|
|||||||
width: var(--sheldWidth);
|
width: var(--sheldWidth);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
max-height: calc(100vh - calc(var(--topBarBlockSize) + var(--bottomFormBlockSize)));
|
max-height: calc(100vh - calc(var(--topBarBlockSize) + var(--bottomFormBlockSize)));
|
||||||
max-height: calc(100svh - calc(var(--topBarBlockSize) + var(--bottomFormBlockSize)));
|
max-height: calc(100dvh - calc(var(--topBarBlockSize) + var(--bottomFormBlockSize)));
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: var(--topBarBlockSize);
|
top: var(--topBarBlockSize);
|
||||||
@@ -4862,11 +4865,11 @@ body:not(.movingUI) .drawer-content.maximized {
|
|||||||
|
|
||||||
.fillLeft {
|
.fillLeft {
|
||||||
width: calc((100vw - var(--sheldWidth) - 2px) /2);
|
width: calc((100vw - var(--sheldWidth) - 2px) /2);
|
||||||
width: calc((100svw - var(--sheldWidth) - 2px) /2);
|
width: calc((100dvw - var(--sheldWidth) - 2px) /2);
|
||||||
height: calc(100vh - var(--topBarBlockSize));
|
height: calc(100vh - var(--topBarBlockSize));
|
||||||
height: calc(100svh - var(--topBarBlockSize));
|
height: calc(100dvh - var(--topBarBlockSize));
|
||||||
max-height: calc(100vh - var(--topBarBlockSize));
|
max-height: calc(100vh - var(--topBarBlockSize));
|
||||||
max-height: calc(100svh - var(--topBarBlockSize));
|
max-height: calc(100dvh - var(--topBarBlockSize));
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -5116,7 +5119,7 @@ body:not(.movingUI) .drawer-content.maximized {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
/* margin-inline: 10px; */
|
/* margin-inline: 10px; */
|
||||||
max-height: 90vh;
|
max-height: 90vh;
|
||||||
max-width: 90svh;
|
max-width: 90dvh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.zoomed_avatar img {
|
.zoomed_avatar img {
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
require('./polyfill.js');
|
require('./polyfill.js');
|
||||||
|
const { getConfigValue } = require('./util.js');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a prompt from the ChatML objects to the format used by Claude.
|
* Convert a prompt from the ChatML objects to the format used by Claude.
|
||||||
@@ -373,8 +374,9 @@ function convertMistralMessages(messages, charName = '', userName = '') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make the last assistant message a prefill
|
// Make the last assistant message a prefill
|
||||||
|
const prefixEnabled = getConfigValue('mistral.enablePrefix', false);
|
||||||
const lastMsg = messages[messages.length - 1];
|
const lastMsg = messages[messages.length - 1];
|
||||||
if (messages.length > 0 && lastMsg && (lastMsg.role === 'assistant')) {
|
if (prefixEnabled && messages.length > 0 && lastMsg?.role === 'assistant') {
|
||||||
lastMsg.prefix = true;
|
lastMsg.prefix = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user