Merge branch 'dev' into dev

This commit is contained in:
Cohee
2023-06-12 23:13:16 +03:00
committed by GitHub
15 changed files with 537 additions and 279 deletions

View File

@ -104,7 +104,7 @@
<div id="lm_button_panel_pin_div" title="Locked = AI Configuration panel will stay open">
<input type="checkbox" id="lm_button_panel_pin">
<label for="lm_button_panel_pin">
<div class="unchecked fa-solid fa-lock-open "></div>
<div class="unchecked fa-solid fa-unlock "></div>
<div class="checked fa-solid fa-lock "></div>
</label>
</div>
@ -116,7 +116,7 @@
<div id="respective-presets-block" class="width100p">
<div id="kobold_api-presets">
<h3><span data-i18n="kobldpresets">Kobold Presets</span>
<a href="https://docs.sillytavern.app/usage/guidebook/#koboldai" class="notes-link" target="_blank">
<a href="https://docs.sillytavern.app/usage/api-connections/koboldai/" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</h3>
@ -127,7 +127,7 @@
<div id="novel_api-presets">
<h3>
<span data-i18n="novelaipreserts">NovelAI Presets</span>
<a href="https://docs.sillytavern.app/usage/guidebook/#novelai" class="notes-link" target="_blank">
<a href="https://docs.sillytavern.app/usage/api-connections/novelai/" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</h3>
@ -340,7 +340,7 @@
</div>
<div class="range-block-range-and-counter">
<div class="range-block-range">
<input type="range" id="rep_pen_slope_novel" name="volume" min="0" max="10" step="0.01">
<input type="range" id="rep_pen_slope_novel" name="volume" min="0.01" max="10" step="0.01">
</div>
<div class="range-block-counter">
<div contenteditable="true" data-for="rep_pen_slope_novel" id="rep_pen_slope_counter_novel">
@ -625,6 +625,12 @@
Use "Unlocked Context" to enable chunked generation.
It extends the context window in exchange for reply generation speed.
</div>
<h4>Safe Context Size values for Poe bots:</h4>
<ul class="margin0auto">
<li>ChatGPT / Sage = 3600-4000 tokens</li>
<li>Claude-instant / Claude+ = 5000-5500 tokens</li>
<li>GPT-4 = 7600-8000 tokens</li>
</ul>
<div class="flex-container spaceEvenly">
<div id="poe_send_jailbreak" class="menu_button widthFitContent" title="Attempts to automatically jailbreak the bot">
Send Jailbreak
@ -1293,12 +1299,12 @@
</label>
<h4>API key</h4>
<h5>Get it here: <a target="_blank" href="https://horde.koboldai.net/register">Register</a><br>
<small>Get it here: <a target="_blank" href="https://horde.koboldai.net/register">Register</a> (<a id="horde_kudos" href="javascript:void(0);">View my Kudos</a>)<br>
Enter <span class="monospace">0000000000</span> to use anonymous mode.
</h5>
<div>
</small>
<!-- <div>
<a id="horde_kudos" href="javascript:void(0);">View my Kudos</a>
</div>
</div> -->
<div class="flex-container">
<input id="horde_api_key" name="horde_api_key" class="text_pole flex1" maxlength="500" type="text" placeholder="0000000000" autocomplete="off">
<div title="Clear your API key" class="menu_button fa-solid fa-circle-xmark clear-api-key" data-key="api_key_horde"></div>
@ -1312,7 +1318,7 @@
</div>
</h4>
<small class="horde_multiple_hint">You can select multiple models.<br>Avoid sending
sensitive information to the Horde. <a id="horde_privacy_disclaimer" target="_blank" href="https://docs.sillytavern.app/usage/guidebook/#horde">Learn more</a></small>
sensitive information to the Horde. <a id="horde_privacy_disclaimer" target="_blank" href="https://docs.sillytavern.app/usage/api-connections/koboldai/">Learn more</a></small>
<select id="horde_model" multiple>
<option>-- Horde models not loaded --</option>
</select>
@ -1327,7 +1333,7 @@
<form action="javascript:void(null);" method="post" enctype="multipart/form-data">
<div id="kobold_api_block">
<h4>API url</h4>
<h5>Example: http://127.0.0.1:5000/api </h5>
<small>Example: http://127.0.0.1:5000/api </small>
<input id="api_url_text" name="api_url" class="text_pole" placeholder="http://127.0.0.1:5000/api" maxlength="500" value="" autocomplete="off">
<input id="api_button" class="menu_button" type="submit" value="Connect">
<div id="api_loading" class="api-load-icon fa-solid fa-hourglass fa-spin"></div>
@ -1345,9 +1351,7 @@
<span>
<ol>
<li>
<span data-i18n="Follow">Follow</span> <a href="https://docs.sillytavern.app/usage/guidebook/#api-key" class="notes-link" target="_blank"> <span data-i18n="these directions">these
directions</span> </a> <span data-i18n="to get your NovelAI API key.">to
get your NovelAI API key.</span>
<a href="https://docs.sillytavern.app/usage/api-connections/novelai/" class="notes-link" target="_blank"> <span data-i18n="Get your NovelAI API Key">Get your NovelAI API key</span></a>
</li>
<li><span data-i18n="Enter it in the box below">Enter it in the box below:</span>
</li>
@ -1363,7 +1367,7 @@
<input id="api_button_novel" class="menu_button" type="submit" value="Connect">
<div id="api_loading_novel" class="api-load-icon fa-solid fa-hourglass fa-spin"></div>
<h4><span data-i18n="Novel AI Model">Novel AI Model</span>
<a href="https://docs.sillytavern.app/usage/guidebook/#models" class="notes-link" target="_blank">
<a href="https://docs.sillytavern.app/usage/api-connections/novelai/#models" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</h4>
@ -1379,7 +1383,7 @@
</div>
</div>
<div id="textgenerationwebui_api" style="display: none;position: relative;">
<div class="oobabooga_logo flex-container">
<div class="flex-container">
<a href="https://github.com/oobabooga/text-generation-webui" target="_blank">
oobabooga/text-generation-webui
</a>
@ -1388,15 +1392,15 @@
</span>
</div>
<div>
<div class="flex-container">
<div class="flex-container flexFlowColumn">
<div class="flex1">
<h4 data-i18n="Blocking API url">Blocking API url</h4>
<h5>Example: http://127.0.0.1:5000/</h5>
<small>Example: http://127.0.0.1:5000/</small>
<input id="textgenerationwebui_api_url_text" name="textgenerationwebui_api_url" class="text_pole wide100p" maxlength="500" value="" autocomplete="off">
</div>
<div class="flex1">
<h4 data-i18n="Streaming API url">Streaming API url</h4>
<h5>Example: ws://127.0.0.1:5005/api/v1/stream</h5>
<small>Example: ws://127.0.0.1:5005/api/v1/stream</small>
<input id="streaming_url_textgenerationwebui" type="text" class="text_pole wide100p" maxlength="500" value="" autocomplete="off">
</div>
</div>
@ -1422,7 +1426,7 @@
<span>
<ol>
<li>
Follow<a href="https://docs.sillytavern.app/usage/guidebook/#api-key-1" class="notes-link" target="_blank"> these directions </a> to get your OpenAI
Follow<a href="https://docs.sillytavern.app/usage/api-connections/openai/" class="notes-link" target="_blank"> these directions </a> to get your OpenAI
API key.
</li>
<li>Enter it in the box below:</li>
@ -1521,7 +1525,7 @@
<span>
<ol>
<li>
Follow <a href="https://docs.sillytavern.app/usage/guidebook/#api-key-2" class="notes-link" target="_blank">these directions</a> to get your 'p-b cookie'
Follow <a href="https://docs.sillytavern.app/usage/api-connections/poe/" class="notes-link" target="_blank">these directions</a> to get your 'p-b cookie'
</li>
<li>Enter it in the box below:</li>
</ol>
@ -1570,7 +1574,7 @@
</div>
<div class="drawer-content">
<h3>Advanced Formatting
<a href="https://docs.sillytavern.app/usage/guidebook/#advanced-formatting" class="notes-link" target="_blank">
<a href="https://docs.sillytavern.app/usage/core-concepts/advancedformatting/" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</h3>
@ -1616,7 +1620,7 @@
</div>
<div>
<h4 data-i18n="Instruct mode">Instruct mode
<a href="https://docs.sillytavern.app/usage/guidebook/#instruct-mode" class="notes-link" target="_blank">
<a href="https://docs.sillytavern.app/usage/core-concepts/instructmode/" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</h4>
@ -1693,7 +1697,7 @@
<h4><span data-i18n="Context Formatting">Context Formatting</span></h4>
<div>
<h4><span data-i18n="Tokenizer">Tokenizer</span>
<a href="https://docs.sillytavern.app/usage/guidebook/#tokenizer" class="notes-link" target="_blank">
<a href="https://docs.sillytavern.app/usage/core-concepts/advancedformatting/#tokenizer" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</h4>
@ -1709,7 +1713,7 @@
<div class="range-block">
<div class="range-block-title justifyLeft">
Token Padding
<a href="https://docs.sillytavern.app/usage/guidebook/#token-padding" class="notes-link" target="_blank">
<a href="https://docs.sillytavern.app/usage/core-concepts/advancedformatting/#token-padding" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</div>
@ -1772,7 +1776,7 @@
<div>
<h4>
<span data-i18n="Multigen">Multigen</span>
<a href="https://docs.sillytavern.app/usage/guidebook/#multigen" class="notes-link" target="_blank">
<a href="https://docs.sillytavern.app/usage/core-concepts/advancedformatting/#multigen" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</h4>
@ -1807,14 +1811,14 @@
<div id="WI_panel_pin_div" title="Locked = World Editor will stay open">
<input type="checkbox" id="WI_panel_pin">
<label for="WI_panel_pin">
<div class="unchecked fa-solid fa-lock-open "></div>
<div class="unchecked fa-solid fa-unlock "></div>
<div class="checked fa-solid fa-lock "></div>
</label>
</div>
<div id="wi-holder">
<div id="wi-holder" class="margin5">
<h3>
World Info / Lorebooks
<a href="https://docs.sillytavern.app/usage/guidebook/#world-info" class="notes-link" target="_blank">
<a href="https://docs.sillytavern.app/usage/core-concepts/worldinfo/" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</h3>
@ -1832,6 +1836,7 @@
</div>
<div class="flex-container alignitemscenter">
<div name="WIScanAndTokens" class="flex1 flex-container flexFlowColumn">
<div class="flex1 range-block">
<div class="range-block-title">
<span data-i18n="Scan Depth">Scan Depth</span>
@ -1863,8 +1868,8 @@
</div>
</div>
</div>
<div class="flex1 range-block flex-container">
</div>
<div class="range-block flex-container flexFlowColumn">
<label title="Entries can activate other entries by mentioning their keywords" class="checkbox_label">
<input id="world_info_recursive" type="checkbox" />
<span>
@ -1892,7 +1897,7 @@
<div class="world_popup_logo_block">
<h3>
World Info Editor
<a href="https://docs.sillytavern.app/usage/guidebook/#world-info-entry" class="notes-link" target="_blank"><span class="note-link-span">?</span></a>
<a href="https://docs.sillytavern.app/usage/core-concepts/worldinfo/#world-info-entry" class="notes-link" target="_blank"><span class="note-link-span">?</span></a>
</h3>
</div>
<div id="OpenAllWIEntries" class="menu_button fa-solid fa-expand"></div>
@ -1917,7 +1922,7 @@
</div>
<div id="softprompt_block">
<h4>Soft Prompt</h4>
<h5>About soft prompts <a href="https://docs.sillytavern.app/usage/guidebook/#soft-prompts" class="notes-link" target="_blank"><span class="note-link-span">?</span></a></h5>
<h5>About soft prompts <a href="https://docs.sillytavern.app/usage/api-connections/koboldai/#soft-prompts" class="notes-link" target="_blank"><span class="note-link-span">?</span></a></h5>
<select id="softprompt">
<option value="">None</option>
</select>
@ -1977,7 +1982,7 @@
<audio id="audio_message_sound" src="sounds/message.mp3" hidden></audio>
<span>
<span data-i18n="Message Sound">Message Sound</span>
<a href="https://docs.sillytavern.app/usage/guidebook/#message-sound" class="notes-link" target="_blank">
<a href="https://docs.sillytavern.app/usage/core-concepts/uicustomization/#message-sound" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</span>
@ -2154,7 +2159,7 @@
<label for="render_formulas">
<input id="render_formulas" type="checkbox" />
<span data-i18n="Render Formulas">Render Formulas</span>
<a href="https://docs.sillytavern.app/usage/guidebook/#formulas-rendering" class="notes-link" target="_blank">
<a href="https://docs.sillytavern.app/usage/core-concepts/uicustomization/#formulas-rendering" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</label>
@ -2210,7 +2215,7 @@
<input id="your_name" name="your_name" placeholder="Enter your name" class="text_pole wide100p" maxlength="50" value="" autocomplete="off">
<div id="your_name_button" class="menu_button fa-solid fa-check" title="Click to set a new User Name">
</div>
<div id="lock_user_name" class="menu_button fa-solid fa-user-lock" title="Click to bind your selected persona to the current chat. Click again to remove the binding.">
<div id="lock_user_name" class="menu_button fa-solid fa-lock" title="Click to lock your selected persona to the current chat. Click again to remove the lock.">
</div>
<div id="sync_name_button" class="menu_button fa-solid fa-sync" title="Click to set user name for all messages">
</div>
@ -2256,18 +2261,20 @@
</div>
<div id="rm_extensions_block" class="drawer-content closedDrawer">
<div class="extensions_block flex-container">
<div class="alignitemscenter flex-container justify wide100p" style="justify-content: space-between;">
<h3 class="margin0 flex1">Extensions API:
<div class="alignitemscenter flex-container justifyCenter wide100p" style="justify-content: space-between;">
<h3 class="margin0">Extensions API:
<a target="_blank" href="https://github.com/SillyTavern/SillyTavern-extras">
SillyTavern-extras
</a>
</h3>
<div class="flex-container">
<div id="extensions_status">Not Connected</div>
<label for="extensions_autoconnect">
<input id="extensions_autoconnect" type="checkbox">
Auto-connect
</label>
</div>
</div>
<div class="alignitemsflexstart flex-container wide100p">
<input id="extensions_url" type="text" class="flex1 heightFitContent text_pole widthNatural" maxlength="250" placeholder="Extensions URL">
<input id="extensions_api_key" type="text" class="flex1 heightFitContent text_pole widthNatural" maxlength="250" placeholder="API key">
@ -2293,26 +2300,38 @@
</div>
</div>
<nav id="right-nav-panel" class="drawer-content closedDrawer fillRight gap5px">
<div id="right-nav-panelheader" class="fa-solid fa-grip drag-grabber"></div>
<div id="right-nav-panelheader" class="fa-solid fa-grip drag-grabber">
<div id="rm_PinAndTabs">
<div id="rm_button_panel_pin_div" title="Locked = Character Management panel will stay open">
</div>
<div id="CharListButtonAndHotSwaps" class="flex-container flexnowrap">
<div class="flexFlowColumn flex-container">
<div id="rm_button_panel_pin_div" class="alignitemsflexstart" title="Locked = Character Management panel will stay open">
<input type="checkbox" id="rm_button_panel_pin">
<label for="rm_button_panel_pin">
<div class="fa-solid unchecked fa-lock-open" alt=""></div>
<div class="fa-solid unchecked fa-unlock" alt=""></div>
<div class="fa-solid checked fa-lock" alt=""></div>
</label>
</div>
<div id="right-nav-panel-tabs">
<div class="right_menu_button fa-solid fa-list-ul" id="rm_button_characters" title="Select/Create Characters"></div>
</div>
<div name="HotSwapWrapper" class="alignitemscenter flex-container margin0auto">
<div class="hotswap flex-container flex1"></div>
</div>
</div>
<hr>
<!-- this div structure must be preserved until group peeking can adjust -->
<div id="rm_PinAndTabs">
<div id="right-nav-panel-tabs" class="">
<div id="rm_button_selected_ch">
<h2></h2>
</div>
</div>
</div>
<div class="hotswap flex-container justifyCenter">
</div>
</div>
<!-- end group peeking cope structure-->
<div name="Solo Char Create/Edit Panel" id="rm_ch_create_block" class="right_menu flex-container flexFlowColumn" style="display: none;">
<form id="form_create" action="javascript:void(null);" method="post" enctype="multipart/form-data">
@ -2322,10 +2341,11 @@
<input id="character_name_pole" name="ch_name" class="text_pole" placeholder="Name this character" maxlength="50" value="" autocomplete="off">
</div>
<div id="avatar_div" class="avatar_div">
<div id="avatar_div" class="avatar_div alignitemsflexstart justifySpaceBetween">
<div id="avatar_div_div" class="avatar">
<img id="avatar_load_preview" src="img/ai4.png" alt="avatar">
</div>
<div class="flex-container flexFlowColumn">
<div class="form_create_bottom_buttons_block">
<label for="add_avatar_button" class="menu_button fa-solid fa-file-image " title="Click to select a new avatar for this character">
<input type="file" id="add_avatar_button" name="avatar" accept="image/png, image/jpeg, image/jpg, image/gif, image/bmp">
@ -2342,8 +2362,10 @@
</label>
<div id="delete_button" class="menu_button fa-solid fa-skull " title="Delete Character"></div>
</div>
<div id="result_info" class="justifyCenter flex-container" title="Token counts may be inaccurate and provided just for reference.">&nbsp;</div>
</div>
<div title="Token counts may be inaccurate and provided just for reference." id="result_info">&nbsp;</div>
</div>
</div>
<hr>
@ -2357,7 +2379,7 @@
<div id="description_div" class="marginBot5">
<span data-i18n="Description">Description</span>
<a href="https://docs.sillytavern.app/usage/guidebook/#character-description" class="notes-link" target="_blank">
<a href="https://docs.sillytavern.app/usage/core-concepts/characterdesign/#character-description" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</div>
@ -2367,7 +2389,7 @@
<div id="first_message_div" class="marginBot5 title_restorable">
<span>
<span data-i18n="First message">First message</span>
<a href="https://docs.sillytavern.app/usage/guidebook/#first-message" class="notes-link" target="_blank">
<a href="https://docs.sillytavern.app/usage/core-concepts/characterdesign/#first-message" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</span>
@ -2412,7 +2434,7 @@
<div class="">
<div class="flex-container flexnowrap width100p whitespacenowrap">
<span data-i18n="Group reply strategy">Group reply strategy</span>
<a href="https://docs.sillytavern.app/usage/guidebook/#group-chats" class="notes-link" target="_blank">
<a href="https://docs.sillytavern.app/usage/core-concepts/groupchats/" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</div>
@ -2597,7 +2619,7 @@
<div id="personality_div">
<h4>
<span data-i18n="Personality summary">Personality summary</span>
<a href="https://docs.sillytavern.app/usage/guidebook/#personality-summary" class="notes-link" target="_blank"><span class="note-link-span">?</span></a>
<a href="https://docs.sillytavern.app/usage/core-concepts/characterdesign/#personality-summary" class="notes-link" target="_blank"><span class="note-link-span">?</span></a>
</h4>
<textarea id="personality_textarea" name="personality" placeholder="(A brief description of the personality)" form="form_create" class="text_pole" autocomplete="off" rows="1" maxlength="20000"></textarea>
</div>
@ -2605,7 +2627,7 @@
<div id="scenario_div">
<h4>
<span data-i18n="Scenario">Scenario</span>
<a href="https://docs.sillytavern.app/usage/guidebook/#scenario" class="notes-link" target="_blank">
<a href="https://docs.sillytavern.app/usage/core-concepts/characterdesign/#scenario" class="notes-link" target="_blank">
<span class="note-link-span">?</span>
</a>
</h4>
@ -2627,7 +2649,7 @@
<div id="mes_example_div" class="flex-container flexFlowColumn">
<div>
<h4><span data-i18n="Examples of dialogue">Examples of dialogue</span></h4>
<h5>Important to set the character's writing style. <a href="https://docs.sillytavern.app/usage/guidebook/#examples-of-dialogue" class="notes-link" target="_blank"><span class="note-link-span">?</span></a></h5>
<h5>Important to set the character's writing style. <a href="https://docs.sillytavern.app/usage/core-concepts/characterdesign/#examples-of-dialogue" class="notes-link" target="_blank"><span class="note-link-span">?</span></a></h5>
</div>
<textarea id="mes_example_textarea" class="flexGrow" name="mes_example" placeholder="(Examples of chat dialog. Begin each example with <start> on a new line.)" form="form_create" maxlength="20000" rows="6"></textarea>
</div>
@ -2643,7 +2665,7 @@
<span id="ChatHistoryCharName"></span>
<br>
<span data-i18n="Chat History">Chat History</span>
<a href="https://docs.sillytavern.app/usage/guidebook/#chat-import" class="notes-link" target="_blank"><span class="note-link-span">?</span></a>
<a href="https://docs.sillytavern.app/usage/core-concepts/chatfilemanagement/#chat-import" class="notes-link" target="_blank"><span class="note-link-span">?</span></a>
</div>
<form id="form_import_chat" action="javascript:void(null);" method="post" enctype="multipart/form-data" style="display: none;">
<input type="file" id="chat_import_file" accept=".json, .jsonl" name="avatar">
@ -2777,11 +2799,11 @@
<form class="world_entry_form">
<div class="inline-drawer wide100p">
<div class="inline-drawer-toggle inline-drawer-header">
<div class="world_entry_thin_controls wide100p">
<div class="gap5px world_entry_thin_controls wide100p">
<div class="world_entry_form_control">
<label for="key">
<h4><span data-i18n="Keywords">Keywords</span></h4>
<h5><span data-i18n="Separate with commas">Separate with commas</span></h5>
<small><span data-i18n="Separate with commas">Separate with commas</span></small>
</label>
<textarea class="text_pole keyprimarytextpole" name="key" rows="1" placeholder="" maxlength="250"></textarea>
</div>
@ -2789,20 +2811,20 @@
<label for="keysecondary">
<h4><span data-i18n="Secondary Required Keywords">Secondary Required Keywords</span>
</h4>
<h5><span data-i18n="Separate with commas">Separate with commas</span></h5>
<small><span data-i18n="Separate with commas">Separate with commas</span></small>
</label>
<textarea class="text_pole keysecondarytextpole" name="keysecondary" rows="1" placeholder="(secondary keywords here)" maxlength="250"></textarea>
</div>
</div>
<div class="fa-solid fa-circle-chevron-down inline-drawer-icon down"></div>
</div>
<div class="inline-drawer-content">
<div class="inline-drawer-content flex-container">
<div class="world_entry_thin_controls wide100p">
<div class="world_entry_form_control">
<label for="content ">
<h4><span data-i18n="Content">Content</span></h4>
<h5><span data-i18n="What this keyword should mean to the AI">What this keyword
should mean to the AI</span></h5>
<small><span data-i18n="What this keyword should mean to the AI">What this keyword
should mean to the AI</span></small>
</label>
<textarea class="text_pole" name="content" rows="4" placeholder=""></textarea>
</div>
@ -2812,15 +2834,13 @@
<div class="world_entry_form_control">
<label for="comment">
<h4><span data-i18n="Memo/Note">Memo/Note</span></h4>
<h5><span data-i18n="Not sent to AI">Not sent to AI</span></h5>
<small><span data-i18n="Not sent to AI">Not sent to AI</span></small>
</label>
<textarea class="text_pole" rows="1" name="comment" maxlength="250"></textarea>
</div>
</div>
<div class="world_entry_form_control world_entry_form_horizontal">
<div class="flex-container flexFlowColumn flexNoGap wi-enter-footer-text flex1 ">
<div class="flex-container flex1 justifySpaceBetween world_entry_form_horizontal">
<div class="flex-container flexFlowColumn flexNoGap wi-enter-footer-text ">
<label class="checkbox">
<input type="checkbox" name="constant" />
<span data-i18n="Constant">Constant</span>
@ -2830,7 +2850,7 @@
<span data-i18n="Selective">Selective</span>
</label>
</div>
<div class="world_entry_form_control world_entry_form_radios wi-enter-footer-text flex1">
<div class="world_entry_form_control world_entry_form_radios wi-enter-footer-text ">
<div>
<label><input type="radio" name="position" value="0">
<span data-i18n="Before Char">Before Char</span>
@ -2842,19 +2862,13 @@
</label>
</div>
</div>
<div class="world_entry_form_control wi-enter-footer-text flex1 flex-container flexNoGap ">
<!-- world_entry_form_control -->
<!-- <label for="order"> -->
<div class="world_entry_form_control wi-enter-footer-text flex-container flexNoGap ">
Insertion Order
<!-- Bigger number = inserted earlier -->
<!-- </label> -->
<input class="text_pole" type="number" name="order" placeholder="" />
<input class="text_pole wideMax100px" type="number" name="order" placeholder="" />
</div>
<div class="flex-container flexFlowColumn flexNoGap wi-enter-footer-text flex1">
<div class="flex-container flexFlowColumn flexNoGap wi-enter-footer-text ">
<div class="world_entry_form_uid">
UID:
&nbsp;
@ -2866,13 +2880,12 @@
<span class="world_entry_form_token_counter">0</span>
</div>
</div>
<div>
<label class="checkbox">
<div class="wi-enter-footer-text">
<label class="checkbox flex-container alignitemscenter">
<input type="checkbox" name="disable" />
<span data-i18n="Disable">Disable</span>
</label>
</div>
<span class="world_popup_expander">&nbsp;</span>
<input class="menu_button delete_entry_button" type="submit" value="Delete Entry" />
</div>
</div>
@ -3138,10 +3151,19 @@
<div imgfile="" class="avatar">
<img src="" alt="User Avatar">
</div>
<div class="avatar-buttons">
<div class="avatar-buttons avatar-buttons-top">
<button class="menu_button bind_user_name" title="Bind user name to that avatar">
<i class="fa-solid fa-user-edit"></i>
</button>
<button class="menu_button set_default_persona" title="Select this as default persona for the new chats.">
<i class="fa-solid fa-crown"></i>
</button>
</div>
<div class="avatar-buttons avatar-buttons-bottom">
<button class="menu_button set_user_info" title="Under construction">
<i class="fa-solid fa-circle-user"></i>
</button>
<button class="menu_button delete_avatar" title="Delete persona">
<i class="fa-solid fa-trash-alt"></i>
</button>

View File

@ -1464,6 +1464,7 @@ function sendSystemMessage(type, text, extra = {}) {
if (type == system_message_types.HELP) {
newMessage.mes += getSlashCommandsHelp();
newMessage.mes += `<br><b>Still got questions left? The <a target="_blank" href="https://docs.sillytavern.app/">Official SillyTavern Documentation Website</a> has much more information!</b>`;
}
if (!newMessage.extra) {
@ -3928,8 +3929,11 @@ function appendUserAvatar(name) {
const personaName = power_user.personas[name];
if (personaName) {
template.attr('title', personaName);
} else {
template.attr('title', '[Unnamed Persona]');
}
template.find('.avatar').attr('imgfile', name);
template.toggleClass('default_persona', name === power_user.default_persona)
template.find('img').attr('src', `User Avatars/${name}`);
$("#user_avatar_block").append(template);
highlightSelectedAvatar();
@ -3950,9 +3954,9 @@ export function setUserName(value) {
name1 = value;
if (name1 === undefined || name1 == "")
name1 = default_user_name;
console.log(name1);
console.log(`User name changed to ${name1}`);
$("#your_name").val(name1);
toastr.success(`Your messages will now be sent as ${name1}`, 'User Name updated');
toastr.success(`Your messages will now be sent as ${name1}`, 'Current persona updated');
saveSettings("change_name");
} else {
toastr.warning('You cannot change your name while sending a message', 'Warning');
@ -3962,6 +3966,7 @@ export function setUserName(value) {
export function autoSelectPersona(name) {
for (const [key, value] of Object.entries(power_user.personas)) {
if (value === name) {
console.log(`Auto-selecting persona ${key} for name ${name}`);
$(`.avatar[imgfile="${key}"]`).trigger('click');
return;
}
@ -3978,15 +3983,38 @@ async function bindUserNameToPersona() {
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 || '');
if (personaName) {
// If the user clicked cancel, don't do anything
if (personaName === false) {
return;
}
if (personaName.length > 0) {
// If the user clicked ok and entered a name, bind the name to the persona
console.log(`Binding persona ${avatarId} to name ${personaName}`);
power_user.personas[avatarId] = personaName;
// If the user is currently using this persona, update the name
if (avatarId === user_avatar) {
console.log(`Auto-updating user name to ${personaName}`);
setUserName(personaName);
}
} else {
// If the user clicked ok, but didn't enter a name, delete the persona
console.log(`Unbinding persona ${avatarId}`);
delete power_user.personas[avatarId];
}
saveSettingsDebounced();
await getUserAvatars();
}
function updateUserLockIcon() {
const hasLock = !!chat_metadata['persona'];
$('#lock_user_name').toggleClass('fa-lock', !hasLock);
$('#lock_user_name').toggleClass('fa-unlock', hasLock);
}
function setUserAvatar() {
user_avatar = $(this).attr("imgfile");
reloadUserAvatar();
@ -3997,10 +4025,10 @@ function setUserAvatar() {
if (personaName && name1 !== personaName) {
const lockedPersona = chat_metadata['persona'];
if (lockedPersona && lockedPersona !== user_avatar) {
toastr.warning(
'Click the "Lock" to bind again. Otherwise, the selection will be reset when your reload the chat.',
toastr.info(
`To permanently set "${personaName}" as the selected persona, unlock and relock it using the "Lock" button. Otherwise, the selection resets upon reloading the chat.`,
`This chat is locked to a different persona (${power_user.personas[lockedPersona]}).`,
{ timeOut: 10000, extendedTimeOut: 20000 },
{ timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true },
);
}
@ -4008,6 +4036,57 @@ function setUserAvatar() {
}
}
async function setUserInfo() {
// TODO Replace with actual implementation
callPopup('This functionality is under development.<br>Please check back later.', 'text');
}
async function setDefaultPersona() {
const avatarId = $(this).closest('.avatar-container').find('.avatar').attr('imgfile');
if (!avatarId) {
console.warn('No avatar id found');
return;
}
const currentDefault = power_user.default_persona;
if (power_user.personas[avatarId] === undefined) {
console.warn(`No persona name found for avatar ${avatarId}`);
toastr.warning('You must bind a name to this persona before you can set it as the default.', 'Persona name not set');
return;
}
const personaName = power_user.personas[avatarId];
if (avatarId === currentDefault) {
const confirm = await callPopup('Are you sure you want to remove the default persona?', 'confirm');
if (!confirm) {
console.debug('User cancelled removing default persona');
return;
}
console.log(`Removing default persona ${avatarId}`);
toastr.info('This persona will no longer be used by default when you open a new chat.', `Default persona removed`);
delete power_user.default_persona;
} else {
const confirm = await callPopup(`<h3>Are you sure you want to set "${personaName}" as the default persona?</h3>
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) {
console.debug('User cancelled setting default persona');
return;
}
power_user.default_persona = avatarId;
toastr.success('This persona will be used by default when you open a new chat.', `Default persona set to ${personaName}`);
}
saveSettingsDebounced();
await getUserAvatars();
}
async function deleteUserAvatar() {
const avatarId = $(this).closest('.avatar-container').find('.avatar').attr('imgfile');
@ -4017,6 +4096,7 @@ async function deleteUserAvatar() {
}
if (avatarId == user_avatar) {
console.warn(`User tried to delete their current avatar ${avatarId}`);
toastr.warning('You cannot delete the avatar you are currently using', 'Warning');
return;
}
@ -4024,6 +4104,7 @@ async function deleteUserAvatar() {
const confirm = await callPopup('Are you sure you want to delete this avatar?', 'confirm');
if (!confirm) {
console.debug('User cancelled deleting avatar');
return;
}
@ -4036,46 +4117,96 @@ async function deleteUserAvatar() {
});
if (request.ok) {
console.log(`Deleted avatar ${avatarId}`);
delete power_user.personas[avatarId];
if (avatarId === power_user.default_persona) {
toastr.warning('The default persona was deleted. You will need to set a new default persona.', 'Default persona deleted');
power_user.default_persona = null;
}
if (avatarId === chat_metadata['persona']) {
toastr.warning('The locked persona was deleted. You will need to set a new persona for this chat.', 'Persona deleted');
delete chat_metadata['persona'];
saveMetadata();
}
saveSettingsDebounced();
await getUserAvatars();
updateUserLockIcon();
}
}
function lockUserNameToChat() {
if (chat_metadata['persona']) {
console.log(`Unlocking persona for this chat ${chat_metadata['persona']}`);
delete chat_metadata['persona'];
saveMetadata();
toastr.info('User persona is now unlocked for this chat. Click the "Lock" to bind again.', 'Persona unlocked');
toastr.info('User persona is now unlocked for this chat. Click the "Lock" again to revert.', 'Persona unlocked');
updateUserLockIcon();
return;
}
if (!(user_avatar in power_user.personas)) {
toastr.info('Creating a new persona for currently selected user name and avatar...', 'Persona not set for this avatar');
console.log(`Creating a new persona ${user_avatar}`);
toastr.info(
'Creating a new persona for currently selected user name and avatar...',
'Persona not set for this avatar',
{ timeOut: 10000, extendedTimeOut: 20000, },
);
power_user.personas[user_avatar] = name1;
}
chat_metadata['persona'] = user_avatar;
saveMetadata();
saveSettingsDebounced();
console.log(`Locking persona for this chat ${user_avatar}`);
toastr.success(`User persona is locked to ${name1} in this chat`);
updateUserLockIcon();
}
eventSource.on(event_types.CHAT_CHANGED, () => {
// If persona is locked, select it
if (chat_metadata['persona']) {
// Find the avatar file
const personaAvatar = $(`.avatar[imgfile="${chat_metadata['persona']}"]`).trigger('click');
// Define a persona for this chat
let chatPersona = '';
// Avatar missing (persona deleted)
if (personaAvatar.length == 0) {
console.warn('Persona avatar not found, unlocking persona');
delete chat_metadata['persona'];
if (chat_metadata['persona']) {
// If persona is locked in chat metadata, select it
console.log(`Using locked persona ${chat_metadata['persona']}`);
chatPersona = chat_metadata['persona'];
} else if (power_user.default_persona) {
// If default persona is set, select it
console.log(`Using default persona ${power_user.default_persona}`);
chatPersona = power_user.default_persona;
}
// No persona set: user current settings
if (!chatPersona) {
console.debug('No default or locked persona set for this chat');
return;
}
personaAvatar.trigger('click');
// Find the avatar file
const personaAvatar = $(`.avatar[imgfile="${chatPersona}"]`).trigger('click');
// Avatar missing (persona deleted)
if (chat_metadata['persona'] && personaAvatar.length == 0) {
console.warn('Persona avatar not found, unlocking persona');
delete chat_metadata['persona'];
updateUserLockIcon();
return;
}
// Default persona missing
if (power_user.default_persona && personaAvatar.length == 0) {
console.warn('Default persona avatar not found, clearing default persona');
power_user.default_persona = null;
saveSettingsDebounced();
return;
}
// Persona avatar found, select it
personaAvatar.trigger('click');
updateUserLockIcon();
});
//***************SETTINGS****************//
@ -5024,7 +5155,7 @@ async function deleteMessageImage() {
mesBlock.find('.mes_img_container').removeClass('img_extra');
mesBlock.find('.mes_img').attr('src', '');
saveChatConditional();
updateVisibleDivs('#chat', false);
/*updateVisibleDivs('#chat', false);*/
}
function enlargeMessageImage() {
@ -5704,9 +5835,10 @@ $(document).ready(function () {
updateVisibleDivs('#rm_print_characters_block', true);
}, 5));
$("#chat").on('scroll', debounce(() => {
// This does not actually increase performance.
/*$("#chat").on('scroll', debounce(() => {
updateVisibleDivs('#chat', false);
}, 10));
}, 10));*/
let S_TAFocused = false;
let S_TAPreviouslyFocused = false;
@ -6958,6 +7090,8 @@ $(document).ready(function () {
$(document).on('click', '.bind_user_name', bindUserNameToPersona);
$(document).on('click', '.delete_avatar', deleteUserAvatar);
$(document).on('click', '.set_default_persona', setDefaultPersona);
$(document).on('click', '.set_user_info', setUserInfo);
$('#lock_user_name').on('click', lockUserNameToChat);
//**************************CHARACTER IMPORT EXPORT*************************//

View File

@ -260,16 +260,23 @@ export function RA_CountCharTokens() {
(power_user.pin_examples ? characters[this_chid].mes_example : ''),
].join('\n').replace(/\r/gm, '').trim();
perm_tokens = getTokenCount(perm_string);
} else { console.debug("RA_TC -- no valid char found, closing."); } // if neither, probably safety char or some error in loading
// if neither, probably safety char or some error in loading
} else { console.debug("RA_TC -- no valid char found, closing."); }
}
// display the counted tokens
if (count_tokens < 1024 && perm_tokens < 1024) {
$("#result_info").html(count_tokens + " Tokens (" + perm_tokens + " Permanent)"); //display normal if both counts are under 1024
//display normal if both counts are under 1024
$("#result_info").html(`<small>${count_tokens} Tokens (${perm_tokens} Permanent)</small>`);
} else {
$("#result_info").html(`
<span class="neutral_warning">${count_tokens}</span>&nbsp;Tokens (<span class="neutral_warning">${perm_tokens}</span><span>&nbsp;Permanent Tokens)
<br>
<div id="chartokenwarning" class="menu_button whitespacenowrap"><a href="https://docs.sillytavern.app/usage/guidebook/#character-tokens" target="_blank">Learn More About Token 'Limits'</a></div>`);
<div class="flex-container flexFlowColumn alignitemscenter">
<div class="flex-container flexnowrap flexNoGap">
<small class="flex-container flexnowrap flexNoGap">
<div class="neutral_warning">${count_tokens}</div>&nbsp;Tokens (<div class="neutral_warning">${perm_tokens}</div><div>&nbsp;Permanent)</div>
</small>
</div>
<div id="chartokenwarning" class="menu_button whitespacenowrap"><a href="https://docs.sillytavern.app/usage/core-concepts/characterdesign/#character-tokens" target="_blank">About Token 'Limits'</a></div>
</div>`);
} //warn if either are over 1024
}
//Auto Load Last Charcter -- (fires when active_character is defined and auto_load_chat is true)

View File

@ -1,4 +1,4 @@
import { callPopup, eventSource, event_types, extension_prompt_types, saveSettings, saveSettingsDebounced } from "../script.js";
import { callPopup, eventSource, event_types, saveSettings, saveSettingsDebounced } from "../script.js";
import { isSubsetOf, debounce } from "./utils.js";
export {
getContext,
@ -69,6 +69,20 @@ const getContext = () => window['SillyTavern'].getContext();
const getApiUrl = () => extension_settings.apiUrl;
let connectedToApi = false;
function showHideExtensionsMenu() {
const hasMenuItems = $('#extensionsMenu').children().length > 0;
// We have menu items, so we can stop checking
if (hasMenuItems) {
clearInterval(menuInterval);
}
$('#extensionsMenuButton').toggle(hasMenuItems);
}
// Periodically check for new extensions
const menuInterval = setInterval(showHideExtensionsMenu, 1000);
async function doExtrasFetch(endpoint, args) {
if (!args) {
args = {}
@ -219,7 +233,7 @@ function autoConnectInputHandler() {
function addExtensionsButtonAndMenu() {
const buttonHTML =
`<div id="extensionsMenuButton" class="fa-solid fa-magic-wand-sparkles" title="Extras Extensions" /></div>`;
`<div id="extensionsMenuButton" style="display: none;" class="fa-solid fa-magic-wand-sparkles" title="Extras Extensions" /></div>`;
const extensionsMenuHTML = `<div id="extensionsMenu" class="options-content" style="display: none;"></div>`;
$(document.body).append(extensionsMenuHTML);

View File

@ -166,5 +166,5 @@ $(document).ready(function () {
setInterval(moduleWorker, UPDATE_INTERVAL);
registerSlashCommand('lock', onLockBackgroundClick, [], " locks a background for the currently selected chat", true, true);
registerSlashCommand('unlock', onUnlockBackgroundClick, [], ' unlocks a background for the currently selected chat', true, true);
registerSlashCommand('autobg', autoBackgroundCommand, ['bgauto'], ' automatically changes the background based on the chat context', true, true);
registerSlashCommand('autobg', autoBackgroundCommand, ['bgauto'], ' automatically changes the background based on the chat context using the AI request prompt', true, true);
});

View File

@ -59,7 +59,7 @@ function addDiceRollButton() {
button.hide();
let popper = Popper.createPopper(button.get(0), dropdown.get(0), {
placement: 'bottom',
placement: 'top',
});
$(document).on('click touchend', function (e) {
@ -68,10 +68,10 @@ function addDiceRollButton() {
if (target.is(button) && !dropdown.is(":visible")) {
e.preventDefault();
dropdown.show(200);
dropdown.fadeIn(250);
popper.update();
} else {
dropdown.hide(200);
dropdown.fadeOut(250);
}
});
}

View File

@ -1,4 +1,11 @@
import { chat_metadata, saveSettingsDebounced, this_chid } from "../../../script.js";
import {
chat_metadata,
eventSource,
event_types,
getTokenCount,
saveSettingsDebounced,
this_chid,
} from "../../../script.js";
import { selected_group } from "../../group-chats.js";
import { ModuleWorkerWrapper, extension_settings, getContext, saveMetadataDebounced } from "../../extensions.js";
import { registerSlashCommand } from "../../slash-commands.js";
@ -66,6 +73,7 @@ function setNotePositionCommand(_, text) {
async function onExtensionFloatingPromptInput() {
chat_metadata[metadata_keys.prompt] = $(this).val();
$('#extension_floating_prompt_token_counter').text(getTokenCount(chat_metadata[metadata_keys.prompt]));
saveMetadataDebounced();
}
@ -93,6 +101,7 @@ async function onExtensionFloatingPositionInput(e) {
function onExtensionFloatingDefaultInput() {
extension_settings.note.default = $(this).val();
$('#extension_floating_default_token_counter').text(getTokenCount(extension_settings.note.default));
saveSettingsDebounced();
}
@ -173,6 +182,13 @@ function onANMenuItemClick() {
}
}
function onChatChanged() {
const tokenCounter1 = chat_metadata[metadata_keys.prompt] ? getTokenCount(chat_metadata[metadata_keys.prompt]) : 0;
const tokenCounter2 = extension_settings.note.default ? getTokenCount(extension_settings.note.default) : 0;
$('#extension_floating_prompt_token_counter').text(tokenCounter1);
$('#extension_floating_default_token_counter').text(tokenCounter2);
}
(function () {
function addExtensionsSettings() {
const settingsHtml = `
@ -195,6 +211,7 @@ function onANMenuItemClick() {
</small>
<textarea id="extension_floating_prompt" class="text_pole" rows="8" maxlength="10000"></textarea>
<div class="extension_token_counter">Tokens: <span id="extension_floating_prompt_token_counter">0</small></div>
<div class="floating_prompt_radio_group">
<label>
@ -228,6 +245,7 @@ function onANMenuItemClick() {
<textarea id="extension_floating_default" class="text_pole" rows="8" maxlength="10000"
placeholder="Example:\n[Scenario: wacky adventures; Genre: romantic comedy; Style: verbose, creative]"></textarea>
<div class="extension_token_counter">Tokens: <span id="extension_floating_default_token_counter">0</small></div>
</div>
</div>
</div>
@ -265,4 +283,5 @@ function onANMenuItemClick() {
registerSlashCommand('depth', setNoteDepthCommand, [], "<span class='monospace'>(number)</span> sets an author's note depth for in-chat positioning", true, true);
registerSlashCommand('freq', setNoteIntervalCommand, ['interval'], "<span class='monospace'>(number)</span> sets an author's note insertion frequency", true, true);
registerSlashCommand('pos', setNotePositionCommand, ['position'], "(<span class='monospace'>chat</span> or <span class='monospace'>scenario</span>) sets an author's note position", true, true);
eventSource.on(event_types.CHAT_CHANGED, onChatChanged);
})();

View File

@ -31,6 +31,12 @@
color: orange;
}
.extension_token_counter {
font-size: calc(var(--mainFontSize) * 0.9);
width: 100%;
text-align: right;
}
.floating_prompt_settings textarea {
font-size: calc(var(--mainFontSize) * 0.9);
line-height: 1.2;

View File

@ -547,7 +547,7 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) {
}
// if not swipe - check if message generated already
if (type !== "swipe" && !isMultigenEnabled() && chat.length == messagesBefore) {
if (generateType === "group_chat" && !isMultigenEnabled() && chat.length == messagesBefore) {
await delay(100);
}
// if swipe - see if message changed
@ -1418,6 +1418,14 @@ function onGroupScenarioRemoveClick() {
$(this).closest('.group_scenario').find('.group_chat_scenario').val('').trigger('input');
}
function onSendTextareaInput() {
if (is_group_automode_enabled) {
// Wait for current automode generation to finish
is_group_automode_enabled = false;
$("#rm_group_automode").prop("checked", false);
}
}
function stopAutoModeGeneration() {
if (groupAutoModeAbortController) {
groupAutoModeAbortController.abort();
@ -1440,4 +1448,5 @@ jQuery(() => {
is_group_automode_enabled = value;
eventSource.once(event_types.GENERATION_STOPPED, stopAutoModeGeneration);
});
$("#send_textarea").on("keyup", onSendTextareaInput);
});

View File

@ -44,7 +44,7 @@ If you have any objections to these requirements, please mention them specifical
If you accept the requirements, please confirm this by replying with "${DEFAULT_JAILBREAK_RESPONSE}", and nothing more. Upon receiving your accurate confirmation message, I will specify the context of the scene and {{char}}'s characteristics, background, and personality in the next message.`;
const DEFAULT_CHARACTER_NUDGE_MESSAGE = "[Unless otherwise stated by {{user}}, your the next response shall only be written from the point of view of {{char}}. Do not seek approval of your writing style at the end of the response.]";
const DEFAULT_CHARACTER_NUDGE_MESSAGE = "[Unless otherwise stated by {{user}}, your the next response shall only be written from the point of view of {{char}}. Do not seek approval of your writing style at the end of the response. Don't reply with <ACK>.]";
const DEFAULT_IMPERSONATION_PROMPT = "[Write 1 reply only in internet RP style from the point of view of {{user}}, using the chat history so far as a guideline for the writing style of {{user}}. Don't write as {{char}} or system.]";
const poe_settings = {
@ -265,7 +265,7 @@ async function generatePoe(type, finalPrompt, signal) {
const isQuiet = type === 'quiet';
let reply = '';
if (max_context > POE_TOKEN_LENGTH) {
if (max_context > POE_TOKEN_LENGTH && poe_settings.bot !== 'a2_100k') {
console.debug('Prompt is too long, sending in chunks');
const result = await sendChunkedMessage(finalPrompt, !isQuiet, signal)
reply = result.reply;

View File

@ -146,6 +146,7 @@ let power_user = {
},
personas: {},
default_persona: null,
};
let themes = [];

View File

@ -98,7 +98,7 @@ const getSlashCommandsHelp = parser.getHelpString.bind(parser);
parser.addCommand('help', helpCommandCallback, ['?'], ' displays this help message', true, true);
parser.addCommand('name', setNameCallback, ['persona'], '<span class="monospace">(name)</span> sets user name and persona avatar (if set)', true, true);
parser.addCommand('sync', syncCallback, [], ' syncs user name in user-attributed messages in the current chat', true, true);
parser.addCommand('bind', bindCallback, [], ' binds/unbinds a persona (name and avatar) to the current chat', true, true);
parser.addCommand('lock', bindCallback, ['bind'], ' locks/unlocks a persona (name and avatar) to the current chat', true, true);
parser.addCommand('bg', setBackgroundCallback, ['background'], '<span class="monospace">(filename)</span> sets a background according to filename, partial names allowed, will set the first one alphabetically if multiple files begin with the provided argument string', false, true);
parser.addCommand('sendas', sendMessageAs, [], ` sends message as a specific character.<br>Example:<br><pre><code>/sendas Chloe\nHello, guys!</code></pre>will send "Hello, guys!" from "Chloe".<br>Uses character avatar if it exists in the characters list.`, true, true);
parser.addCommand('sys', sendNarratorMessage, [], '<span class="monospace">(text)</span> sends message as a system narrator', false, true);
@ -262,6 +262,7 @@ function executeSlashCommands(text) {
continue;
}
console.debug('Slash command executing:', result);
result.command.callback(result.args, result.value);
if (result.command.interruptsGeneration) {

View File

@ -34,6 +34,7 @@
--orangered: rgb(255, 90, 0);
--greyCAIbg: rgb(36, 36, 37);
--ivory: rgb(220, 220, 210);
--golden: rgba(212, 175, 55, 1);
/*Default Theme, will be changed by ToolCool Color Picker*/
@ -296,6 +297,7 @@ hr {
background-image: linear-gradient(90deg, var(--transparent), var(--white30a), var(--transparent));
margin: 5px 0;
height: 1px;
min-height: 1px;
border: 0;
}
@ -895,6 +897,10 @@ select {
margin: 5px 0;
}
.margin5 {
margin: 5px;
}
#description_textarea,
#firstmessage_textarea {
height: -webkit-fill-available;
@ -993,10 +999,17 @@ input[type="file"] {
gap: 10px;
}
#right-nav-panel-tabs .right_menu_button {
#right-nav-panel-tabs .right_menu_button,
#CharListButtonAndHotSwaps .right_menu_button {
padding-right: 0;
}
#chartokenwarning.menu_button {
font-size: unset;
height: fit-content;
aspect-ratio: unset;
}
/* ##################################################################### */
/* Right Panel's Upper Tabs */
/* ##################################################################### */
@ -1239,7 +1252,8 @@ select option:not(:checked) {
}
#form_character_search_form .menu_button,
#GroupFavDelOkBack .menu_button {
#GroupFavDelOkBack .menu_button,
.avatar-container .menu_button {
margin: 0;
height: fit-content;
padding: 5px;
@ -1326,6 +1340,10 @@ input[type=search]:focus::-webkit-search-cancel-button {
width: calc(100% - 70px);
}
.wideMax100px {
max-width: 100px;
}
.widthUnset {
width: unset;
}
@ -1432,7 +1450,7 @@ input[type=search]:focus::-webkit-search-cancel-button {
width: 100%;
flex-wrap: wrap;
margin-top: 0px;
margin-bottom: 6px;
/* margin-bottom: 6px; */
align-items: center;
}
@ -1446,7 +1464,7 @@ input[type=search]:focus::-webkit-search-cancel-button {
display: flex;
flex: 0 0 100%;
flex-wrap: wrap;
margin-bottom: 4px;
/* margin-bottom: 4px; */
}
@ -1529,21 +1547,35 @@ input[type=search]:focus::-webkit-search-cancel-button {
pointer-events: all;
}
.avatar-buttons-bottom {
bottom: 0;
left: 0;
}
.avatar-buttons-top {
top: 0;
left: 0;
}
/* Ross should be able to handle this later */
/*.big-avatars .avatar-buttons{
justify-content: center;
width: fit-content;
}*/
.avatar-buttons {
pointer-events: none;
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
justify-content: space-between;
}
.avatar_div .avatar {
margin-left: 4px;
/* margin-left: 4px;
margin-right: 10px;
height: 70px;
width: 70px;
width: 70px; */
display: flex;
justify-content: center;
align-items: center;
@ -1612,7 +1644,7 @@ input[type=search]:focus::-webkit-search-cancel-button {
}
#result_info {
font-size: calc(var(--mainFontSize) - 0.2rem);
font-size: calc(var(--mainFontSize) - 0.1rem);
font-weight: bold;
}
@ -1885,27 +1917,6 @@ input[type=search]:focus::-webkit-search-cancel-button {
opacity: 0.8;
}
#world_popup_bottom_holder div:not(:first-of-type) {
margin-left: 1rem;
}
#world_info_buttons {
margin-left: 1rem;
}
.world_entry {
padding: 0 5px;
}
.world_entry:not(:last-child)::after {
margin-top: 1rem;
height: 1px;
display: block;
width: 100%;
content: '';
background-image: linear-gradient(270deg, rgba(0, 0, 0, 0), rgba(100, 100, 100, 0.75), rgba(0, 0, 0, 0));
}
.world_popup_logo_block {
display: flex;
align-items: center;
@ -1980,7 +1991,7 @@ input[type=search]:focus::-webkit-search-cancel-button {
.world_entry_form_control {
display: flex;
flex-direction: column;
margin: 0 10px;
/* margin: 0 10px; */
}
.world_entry_thin_controls {
@ -1998,7 +2009,7 @@ input[type=search]:focus::-webkit-search-cancel-button {
.world_entry_form_control label h4 {
margin-bottom: 0px;
margin-top: 0.5rem;
margin-top: 5px;
}
.world_entry_form_control label h5 {
@ -2010,12 +2021,13 @@ input[type=search]:focus::-webkit-search-cancel-button {
height: auto;
/* width: auto; */
margin-top: 0;
margin-bottom: 0;
}
.world_entry_form_control.world_entry_form_horizontal {
flex-direction: row;
align-items: center;
margin-top: 5px;
/* margin-top: 5px; */
flex-wrap: wrap;
}
@ -2077,6 +2089,11 @@ input[type=search]:focus::-webkit-search-cancel-button {
margin-right: 12px;
}
/* Override toastr default styles */
body #toast-container>div {
opacity: 0.95;
}
#dialogue_del_mes {
display: none;
}
@ -2152,6 +2169,15 @@ input[type='checkbox']:not(#nav-toggle):not(#rm_button_panel_pin):not(#lm_button
outline: 2px solid transparent;
}
#user_avatar_block .default_persona .avatar {
border: 2px solid var(--golden);
box-sizing: content-box;
}
#user_avatar_block .default_persona .set_default_persona {
color: var(--golden);
}
#user_avatar_block .avatar img {
width: 64px;
height: 64px;
@ -2253,8 +2279,8 @@ input[type="range"]::-webkit-slider-thumb {
/*Notes '?' links*/
.note-link-span {
color: var(--sienna);
border: 1px solid var(--sienna);
color: var(--SmartThemeQuoteColor);
border: 1px solid var(--SmartThemeQuoteColor);
border-radius: 10px;
line-height: var(--mainFontSize);
font-size: var(--mainFontSize);
@ -3852,6 +3878,10 @@ toolcool-color-picker {
margin: 0;
}
.margin0auto {
margin: 0 auto;
}
.margin-r5 {
margin-right: 5px;
}
@ -4321,7 +4351,7 @@ body.waifuMode #avatar_zoom_popup {
}
.world_entry_form_control.world_entry_form_horizontal {
flex-direction: column;
/* flex-direction: column; */
align-items: flex-start;
row-gap: 0.5rem;
}
@ -4462,9 +4492,9 @@ body.waifuMode #avatar_zoom_popup {
font-size: calc(var(--mainFontSize) - .1rem);
}
.avatar_div {
/* .avatar_div {
margin-top: 5px;
}
} */
#character_popup {
width: 100%;
@ -4482,7 +4512,7 @@ body.waifuMode #avatar_zoom_popup {
}
.drawer25pWidth {
flex-basis: max(calc(100% / 4 - 10px), 200px);
flex-basis: max(calc(100% / 4 - 10px), 190px);
}
.expression-holder {
@ -4550,7 +4580,7 @@ body.waifuMode #avatar_zoom_popup {
@media screen and (max-width: 450px) {
.drawer25pWidth {
flex-basis: max(calc(100% / 2 - 10px), 200px);
flex-basis: max(calc(100% / 2 - 10px), 180px);
}
}

View File

@ -385,9 +385,8 @@ app.post("/generate", jsonParser, async function (request, response_generate = r
signal: controller.signal,
};
const MAX_RETRIES = 10;
const delayAmount = 3000;
const MAX_RETRIES = 50;
const delayAmount = 2500;
let fetch, url, response;
for (let i = 0; i < MAX_RETRIES; i++) {
try {
@ -420,15 +419,23 @@ app.post("/generate", jsonParser, async function (request, response_generate = r
}
} catch (error) {
// response
switch (error.statusCode) {
switch (error?.status) {
case 403:
case 503: // retry in case of temporary service issue, possibly caused by a queue failure?
console.debug(`KoboldAI is busy. Retry attempt ${i+1} of ${MAX_RETRIES}...`);
await delay(delayAmount);
break;
default:
if ('status' in error) {
console.log('Status Code from Kobold:', error.status);
}
return response_generate.send({ error: true });
}
}
}
console.log('Max retries exceeded. Giving up.');
return response_generate.send({ error: true });
});
//************** Text generation web UI
@ -685,11 +692,11 @@ function getVersion() {
pkgVersion = pkgJson.version;
if (!process.pkg && commandExistsSync('git')) {
gitRevision = require('child_process')
.execSync('git rev-parse --short HEAD', { cwd: process.cwd() })
.execSync('git rev-parse --short HEAD', { cwd: process.cwd(), stdio: ['ignore', 'pipe', 'ignore'] })
.toString().trim();
gitBranch = require('child_process')
.execSync('git rev-parse --abbrev-ref HEAD', { cwd: process.cwd() })
.execSync('git rev-parse --abbrev-ref HEAD', { cwd: process.cwd(), stdio: ['ignore', 'pipe', 'ignore'] })
.toString().trim();
}
}
@ -2421,7 +2428,7 @@ app.post('/generate_poe', jsonParser, async (request, response) => {
if (streaming) {
try {
let reply = '';
for await (const mes of client.send_message(bot, prompt, false, 30, abortController.signal)) {
for await (const mes of client.send_message(bot, prompt, false, 60, abortController.signal)) {
if (response.headersSent === false) {
response.writeHead(200, {
'Content-Type': 'text/plain;charset=utf-8',
@ -2454,7 +2461,7 @@ app.post('/generate_poe', jsonParser, async (request, response) => {
try {
let reply;
let messageId;
for await (const mes of client.send_message(bot, prompt, false, 30, abortController.signal)) {
for await (const mes of client.send_message(bot, prompt, false, 60, abortController.signal)) {
reply = mes.text;
messageId = mes.messageId;
}
@ -3151,7 +3158,7 @@ async function postAsync(url, args) {
return data;
}
throw new Error(response);
throw response;
}
function getAsync(url, args) {
@ -3179,6 +3186,10 @@ const autorunUrl = new URL(
);
const setupTasks = async function () {
const version = getVersion();
console.log(`SillyTavern ${version.pkgVersion}` + (version.gitBranch ? ` '${version.gitBranch}' (${version.gitRevision})` : ''));
migrateSecrets();
ensurePublicDirectoriesExist();
await ensureThumbnailCache();
@ -3196,6 +3207,10 @@ const setupTasks = async function () {
if (autorun) open(autorunUrl.toString());
console.log('SillyTavern is listening on: ' + tavernUrl);
if (listen) {
console.log('\n0.0.0.0 means SillyTavern is listening on all network interfaces (Wi-Fi, LAN, localhost). If you want to limit it only to internal localhost (127.0.0.1), change the setting in config.conf to “listen=false”\n');
}
}
if (listen && !config.whitelistMode && !config.basicAuthMode) {

View File

@ -608,7 +608,7 @@ class Client {
}
}
async *send_message(chatbot, message, with_chat_break = false, timeout = 30, signal = null) {
async *send_message(chatbot, message, with_chat_break = false, timeout = 60, signal = null) {
await this.ws_ping();
if (this.auto_reconnect) {