Merge branch 'staging' into feat/xtc
| @@ -246,7 +246,6 @@ You will need two mandatory directory mappings and a port mapping to allow Silly | ||
| 246 | 246 | |
| 247 | 247 | ##### Additional Settings |
| 248 | 248 | |
| 249 | -- [TimeZone] - The timezone your instance should use. This is useful for making logs match your local time for easier troubleshooting. Use your TZ Identifier. (https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) | |
| 250 | 249 | - [DockerNet] - The docker network that the container should be created with a connection to. If you don't know what it is, see the [official Docker documentation](https://docs.docker.com/reference/cli/docker/network/). |
| 251 | 250 | - [version] - On the right-hand side of this GitHub page, you'll see "Packages". Select the "sillytavern" package and you'll see the image versions. The image tag "latest" will keep you up-to-date with the current release. You can also utilize "staging" and "release" tags that point to the nightly images of the respective branches, but this may not be appropriate, if you are utilizing extensions that could be broken, and may need time to update. |
| 252 | 251 | |
| @@ -255,7 +254,7 @@ You will need two mandatory directory mappings and a port mapping to allow Silly | ||
| 255 | 254 | 1. Open your Command Line |
| 256 | 255 | 2. Run the following command |
| 257 | 256 | |
| 258 | 257 | `docker create --name='sillytavern' --net='[DockerNet]' -e TZ="[TimeZone]" -p '8000:8000/tcp' -v '[plugins]':'/home/node/app/plugins':'rw' -v '[config]':'/home/node/app/config':'rw' -v '[data]':'/home/node/app/data':'rw' 'ghcr.io/sillytavern/sillytavern:[version]'` |
| 259 | 258 | |
| 260 | 259 | > Note that 8000 is a default listening port. Don't forget to use an appropriate port if you change it in the config. |
| 261 | 260 | |
| @@ -1,4 +1,4 @@ | ||
| 1 | 1 | FROM node:lts-alpine3.1819 |
| 2 | 2 | |
| 3 | 3 | # Arguments |
| 4 | 4 | ARG APP_HOME=/home/node/app |
| @@ -90,9 +90,11 @@ whitelistImportDomains: | ||
| 90 | 90 | ## headers: |
| 91 | 91 | ## User-Agent: "Googlebot/2.1 (+http://www.google.com/bot.html)" |
| 92 | 92 | requestOverrides: [] |
| 93 | 93 | # -- PLUGINEXTENSIONS CONFIGURATION -- |
| 94 | 94 | # Enable UI extensions |
| 95 | 95 | enableExtensions: true |
| 96 | +# Automatically update extensions when a release version changes | |
| 97 | +enableExtensionsAutoUpdate: true | |
| 96 | 98 | # Extension settings |
| 97 | 99 | extras: |
| 98 | 100 | # Disables automatic model download from HuggingFace |
| @@ -126,7 +128,7 @@ ollama: | ||
| 126 | 128 | # Controls how long the model will stay loaded into memory following the request |
| 127 | 129 | # * -1: Keep the model loaded indefinitely |
| 128 | 130 | # * 0: Unload the model immediately after the request |
| 129 | 131 | # * 5mN (any positive number): Keep the model loaded for 5N minutesseconds after the request. Accepts duration strings (e.g. 5h30m40s) |
| 130 | 132 | keepAlive: -1 |
| 131 | 133 | # -- ANTHROPIC CLAUDE API CONFIGURATION -- |
| 132 | 134 | claude: |
| @@ -8,7 +8,7 @@ | ||
| 8 | 8 | "openrouter_force_instruct": false, |
| 9 | 9 | "openrouter_group_models": false, |
| 10 | 10 | "openrouter_sort_models": "alphabetically", |
| 11 | 11 | "ai21_model": "j2jamba-ultra1.5-large", |
| 12 | 12 | "mistralai_model": "mistral-large-latest", |
| 13 | 13 | "custom_model": "", |
| 14 | 14 | "custom_url": "", |
| @@ -19,7 +19,6 @@ | ||
| 19 | 19 | "temperature": 1, |
| 20 | 20 | "frequency_penalty": 0, |
| 21 | 21 | "presence_penalty": 0, |
| 22 | - "count_penalty": 0, | |
| 23 | 22 | "top_p": 1, |
| 24 | 23 | "top_k": 0, |
| 25 | 24 | "top_a": 0, |
| @@ -233,8 +232,6 @@ | ||
| 233 | 232 | "assistant_prefill": "", |
| 234 | 233 | "assistant_impersonation": "", |
| 235 | 234 | "human_sysprompt_message": "Let's get started. Please generate your response based on the information and instructions provided above.", |
| 236 | - "use_ai21_tokenizer": false, | |
| 237 | - "use_google_tokenizer": false, | |
| 238 | 235 | "claude_use_sysprompt": false, |
| 239 | 236 | "use_alt_scale": false, |
| 240 | 237 | "squash_system_messages": false, |
| @@ -142,6 +142,7 @@ | ||
| 142 | 142 | "timestamps_enabled": true, |
| 143 | 143 | "timestamp_model_icon": true, |
| 144 | 144 | "mesIDDisplay_enabled": false, |
| 145 | + "hideChatAvatars_enabled": false, | |
| 145 | 146 | "max_context_unlocked": false, |
| 146 | 147 | "prefer_character_prompt": true, |
| 147 | 148 | "prefer_character_jailbreak": true, |
| @@ -195,7 +196,15 @@ | ||
| 195 | 196 | "enableLabMode": false, |
| 196 | 197 | "enableZenSliders": false, |
| 197 | 198 | "ui_mode": 1, |
| 198 | 199 | "forbid_external_media": true, |
| 200 | + "stscript": { | |
| 201 | + "parser": { | |
| 202 | + "flags": { | |
| 203 | + "1": true, | |
| 204 | + "2": true | |
| 205 | + } | |
| 206 | + } | |
| 207 | + } | |
| 199 | 208 | }, |
| 200 | 209 | "extension_settings": { |
| 201 | 210 | "apiUrl": "http://localhost:5100", |
| @@ -451,7 +460,6 @@ | ||
| 451 | 460 | "temp_openai": 1.0, |
| 452 | 461 | "freq_pen_openai": 0, |
| 453 | 462 | "pres_pen_openai": 0, |
| 454 | - "count_pen": 0, | |
| 455 | 463 | "top_p_openai": 1, |
| 456 | 464 | "top_k_openai": 0, |
| 457 | 465 | "stream_openai": true, |
| @@ -613,7 +621,7 @@ | ||
| 613 | 621 | "wi_format": "{0}", |
| 614 | 622 | "openai_model": "gpt-4-turbo", |
| 615 | 623 | "claude_model": "claude-3-5-sonnet-20240620", |
| 616 | 624 | "ai21_model": "j2jamba-ultra1.5-large", |
| 617 | 625 | "windowai_model": "", |
| 618 | 626 | "openrouter_model": "OR_Website", |
| 619 | 627 | "jailbreak_system": true, |
| @@ -624,7 +632,6 @@ | ||
| 624 | 632 | "show_external_models": false, |
| 625 | 633 | "proxy_password": "", |
| 626 | 634 | "assistant_prefill": "", |
| 627 | 635 | "assistant_impersonation": "", |
| 628 | - "use_ai21_tokenizer": false | |
| 629 | 636 | } |
| 630 | 637 | } |
| @@ -23,6 +23,7 @@ | ||
| 23 | 23 | "timestamps_enabled": true, |
| 24 | 24 | "timestamp_model_icon": false, |
| 25 | 25 | "mesIDDisplay_enabled": true, |
| 26 | + "hideChatAvatars_enabled": false, | |
| 26 | 27 | "message_token_count_enabled": false, |
| 27 | 28 | "expand_message_actions": false, |
| 28 | 29 | "enableZenSliders": false, |
| @@ -23,6 +23,7 @@ | ||
| 23 | 23 | "timestamps_enabled": true, |
| 24 | 24 | "timestamp_model_icon": true, |
| 25 | 25 | "mesIDDisplay_enabled": true, |
| 26 | + "hideChatAvatars_enabled": false, | |
| 26 | 27 | "message_token_count_enabled": false, |
| 27 | 28 | "expand_message_actions": false, |
| 28 | 29 | "enableZenSliders": false, |
| @@ -23,6 +23,7 @@ | ||
| 23 | 23 | "timestamps_enabled": true, |
| 24 | 24 | "timestamp_model_icon": true, |
| 25 | 25 | "mesIDDisplay_enabled": false, |
| 26 | + "hideChatAvatars_enabled": false, | |
| 26 | 27 | "message_token_count_enabled": false, |
| 27 | 28 | "expand_message_actions": false, |
| 28 | 29 | "enableZenSliders": "", |
Binary file
| @@ -1,12 +1,12 @@ | ||
| 1 | 1 | { |
| 2 | 2 | "name": "sillytavern", |
| 3 | 3 | "version": "1.12.45", |
| 4 | 4 | "lockfileVersion": 3, |
| 5 | 5 | "requires": true, |
| 6 | 6 | "packages": { |
| 7 | 7 | "": { |
| 8 | 8 | "name": "sillytavern", |
| 9 | 9 | "version": "1.12.45", |
| 10 | 10 | "hasInstallScript": true, |
| 11 | 11 | "license": "AGPL-3.0", |
| 12 | 12 | "dependencies": { |
| @@ -71,7 +71,7 @@ | ||
| 71 | 71 | "type": "git", |
| 72 | 72 | "url": "https://github.com/SillyTavern/SillyTavern.git" |
| 73 | 73 | }, |
| 74 | 74 | "version": "1.12.45", |
| 75 | 75 | "scripts": { |
| 76 | 76 | "start": "node server.js", |
| 77 | 77 | "start:no-csrf": "node server.js --disableCsrf", |
Binary file
| @@ -5,7 +5,7 @@ | ||
| 5 | 5 | <title>SillyTavern</title> |
| 6 | 6 | <base href="/"> |
| 7 | 7 | <meta charset="utf-8"> |
| 8 | 8 | <meta name="viewport" content="width=device-width, viewport-fit=cover, initial-scale=1, maximum-scale=1.0, user-scalable=no, interactive-widget=resizes-content"> |
| 9 | 9 | <meta name="apple-mobile-web-app-capable" content="yes"> |
| 10 | 10 | <meta name="darkreader-lock"> |
| 11 | 11 | <meta name="robots" content="noindex, nofollow" /> |
| @@ -436,7 +436,7 @@ | ||
| 436 | 436 | </div> |
| 437 | 437 | </div> |
| 438 | 438 | </div> |
| 439 | 439 | <div data-newbie-hidden class="range-block" data-source="openai,openrouter,ai21,custom,cohere,perplexity,groq"> |
| 440 | 440 | <div class="range-block-title" data-i18n="Frequency Penalty"> |
| 441 | 441 | Frequency Penalty |
| 442 | 442 | </div> |
| @@ -449,7 +449,7 @@ | ||
| 449 | 449 | </div> |
| 450 | 450 | </div> |
| 451 | 451 | </div> |
| 452 | 452 | <div data-newbie-hidden class="range-block" data-source="openai,openrouter,ai21,custom,cohere,perplexity,groq"> |
| 453 | 453 | <div class="range-block-title" data-i18n="Presence Penalty"> |
| 454 | 454 | Presence Penalty |
| 455 | 455 | </div> |
| @@ -462,20 +462,7 @@ | ||
| 462 | 462 | </div> |
| 463 | 463 | </div> |
| 464 | 464 | </div> |
| 465 | 465 | <div data-newbie-hidden class="range-block" data-source="ai21claude,openrouter,makersuite,cohere,perplexity"> |
| 466 | - <div class="range-block-title" data-i18n="Count Penalty"> | |
| 467 | - Count Penalty | |
| 468 | - </div> | |
| 469 | - <div class="range-block-range-and-counter"> | |
| 470 | - <div class="range-block-range"> | |
| 471 | - <input type="range" id="count_pen" name="volume" min="0" max="1" step="0.01"> | |
| 472 | - </div> | |
| 473 | - <div class="range-block-counter"> | |
| 474 | - <input type="number" min="0" max="1" step="0.01" data-for="count_pen" id="count_pen_counter"> | |
| 475 | - </div> | |
| 476 | - </div> | |
| 477 | - </div> | |
| 478 | - <div data-newbie-hidden class="range-block" data-source="claude,openrouter,ai21,makersuite,cohere,perplexity"> | |
| 479 | 466 | <div class="range-block-title" data-i18n="Top K"> |
| 480 | 467 | Top K |
| 481 | 468 | </div> |
| @@ -1814,22 +1801,6 @@ | ||
| 1814 | 1801 | </select> |
| 1815 | 1802 | </div> |
| 1816 | 1803 | </div> |
| 1817 | - <div class="range-block" data-source="ai21"> | |
| 1818 | - <label for="use_ai21_tokenizer" title="Use AI21 Tokenizer" data-i18n="[title]Use AI21 Tokenizer" class="checkbox_label widthFreeExpand"> | |
| 1819 | - <input id="use_ai21_tokenizer" type="checkbox" /><span data-i18n="Use AI21 Tokenizer">Use AI21 Tokenizer</span> | |
| 1820 | - </label> | |
| 1821 | - <div class="toggle-description justifyLeft"> | |
| 1822 | - <span data-i18n="Use the appropriate tokenizer for Jurassic models, which is more efficient than GPT's.">Use the appropriate tokenizer for Jurassic models, which is more efficient than GPT's.</span> | |
| 1823 | - </div> | |
| 1824 | - </div> | |
| 1825 | - <div class="range-block" data-source="makersuite"> | |
| 1826 | - <label for="use_google_tokenizer" title="Use Google Tokenizer" data-i18n="[title]Use Google Tokenizer" class="checkbox_label widthFreeExpand"> | |
| 1827 | - <input id="use_google_tokenizer" type="checkbox" /><span data-i18n="Use Google Tokenizer">Use Google Tokenizer</span> | |
| 1828 | - </label> | |
| 1829 | - <div class="toggle-description justifyLeft"> | |
| 1830 | - <span data-i18n="Use the appropriate tokenizer for Google models via their API. Slower prompt processing, but offers much more accurate token counting.">Use the appropriate tokenizer for Google models via their API. Slower prompt processing, but offers much more accurate token counting.</span> | |
| 1831 | - </div> | |
| 1832 | - </div> | |
| 1833 | 1804 | <div class="range-block" data-source="makersuite"> |
| 1834 | 1805 | <label for="use_makersuite_sysprompt" class="checkbox_label widthFreeExpand"> |
| 1835 | 1806 | <input id="use_makersuite_sysprompt" type="checkbox" /> |
| @@ -1875,7 +1846,7 @@ | ||
| 1875 | 1846 | <div class="fa-solid fa-clock-rotate-left"></div> |
| 1876 | 1847 | </div> |
| 1877 | 1848 | </div> |
| 1878 | 1849 | <textarea id="claude_human_sysprompt_textarea" class="text_pole textarea_compact" rows="4" maxlength="10000" data-i18n="[placeholder]Human message" placeholder="Human message, instruction, etc. Adds nothing when empty, i.e. requires a new prompt with the role 'user'."></textarea> |
| 1879 | 1850 | </div> |
| 1880 | 1851 | </div> |
| 1881 | 1852 | </div> |
| @@ -2460,7 +2431,7 @@ | ||
| 2460 | 2431 | <option value="claude">Claude</option> |
| 2461 | 2432 | <option value="cohere">Cohere</option> |
| 2462 | 2433 | <option value="groq">Groq</option> |
| 2463 | 2434 | <option value="makersuite">Google MakerSuiteAI Studio</option> |
| 2464 | 2435 | <option value="mistralai">MistralAI</option> |
| 2465 | 2436 | <option value="openrouter">OpenRouter</option> |
| 2466 | 2437 | <option value="perplexity">Perplexity</option> |
| @@ -2814,16 +2785,18 @@ | ||
| 2814 | 2785 | <div> |
| 2815 | 2786 | <h4 data-i18n="AI21 Model">AI21 Model</h4> |
| 2816 | 2787 | <select id="model_ai21_select"> |
| 2817 | 2788 | <optgroup label="LatestJamba 1.5"> |
| 2818 | 2789 | <option value="j2jamba-ultra1.5-mini">j2jamba-ultra1.5-mini</option> |
| 2819 | 2790 | <option value="j2jamba-mid1.5-large">j2jamba-mid1.5-large</option> |
| 2820 | - <option value="j2-light">j2-light</option> | |
| 2791 | + </optgroup> | |
| 2792 | + <optgroup label="Jamba-Instruct (Deprecated)"> | |
| 2793 | + <option value="jamba-instruct-preview">jamba-instruct-preview</option> | |
| 2821 | 2794 | </optgroup> |
| 2822 | 2795 | </select> |
| 2823 | 2796 | </div> |
| 2824 | 2797 | </form> |
| 2825 | 2798 | <form id="makersuite_form" data-source="makersuite" action="javascript:void(null);" method="post" enctype="multipart/form-data"> |
| 2826 | 2799 | <h4 data-i18n="MakerSuiteGoogle AI Studio API Key">MakerSuiteGoogle AI Studio API Key</h4> |
| 2827 | 2800 | <div class="flex-container"> |
| 2828 | 2801 | <input id="api_key_makersuite" name="api_key_makersuite" class="text_pole flex1" maxlength="500" value="" type="text" autocomplete="off"> |
| 2829 | 2802 | <div title="Clear your API key" data-i18n="[title]Clear your API key" class="menu_button fa-solid fa-circle-xmark clear-api-key" data-key="api_key_makersuite"></div> |
| @@ -2847,8 +2820,11 @@ | ||
| 2847 | 2820 | </optgroup> |
| 2848 | 2821 | <optgroup label="Subversions"> |
| 2849 | 2822 | <option value="gemini-1.5-pro-exp-0801">Gemini 1.5 Pro Experiment 2024-08-01</option> |
| 2823 | + <option value="gemini-1.5-pro-exp-0827">Gemini 1.5 Pro Experiment 2024-08-27</option> | |
| 2850 | 2824 | <option value="gemini-1.5-pro-latest">Gemini 1.5 Pro [latest]</option> |
| 2851 | 2825 | <option value="gemini-1.5-pro-001">Gemini 1.5 Pro [001]</option> |
| 2826 | + <option value="gemini-1.5-flash-exp-0827">Gemini 1.5 Flash Experiment 2024-08-27</option> | |
| 2827 | + <option value="gemini-1.5-flash-8b-exp-0827">Gemini 1.5 Flash 8B Experiment 2024-08-27</option> | |
| 2852 | 2828 | <option value="gemini-1.5-flash-latest">Gemini 1.5 Flash [latest]</option> |
| 2853 | 2829 | <option value="gemini-1.5-flash-001">Gemini 1.5 Flash [001]</option> |
| 2854 | 2830 | <option value="gemini-1.0-pro-latest">Gemini 1.0 Pro [latest]</option> |
| @@ -2978,6 +2954,8 @@ | ||
| 2978 | 2954 | <option value="command">command</option> |
| 2979 | 2955 | <option value="command-r">command-r</option> |
| 2980 | 2956 | <option value="command-r-plus">command-r-plus</option> |
| 2957 | + <option value="command-r-08-2024">command-r-08-2024</option> | |
| 2958 | + <option value="command-r-plus-08-2024">command-r-plus-08-2024</option> | |
| 2981 | 2959 | </optgroup> |
| 2982 | 2960 | <optgroup label="Nightly"> |
| 2983 | 2961 | <option value="command-light-nightly">command-light-nightly</option> |
| @@ -3473,6 +3451,7 @@ | ||
| 3473 | 3451 | <option value="3">Llama 1/2</option> |
| 3474 | 3452 | <option value="12">Llama 3</option> |
| 3475 | 3453 | <option value="13">Gemma / Gemini</option> |
| 3454 | + <option value="14">Jamba</option> | |
| 3476 | 3455 | <option value="4">NerdStash (NovelAI Clio)</option> |
| 3477 | 3456 | <option value="5">NerdStash v2 (NovelAI Kayra)</option> |
| 3478 | 3457 | <option value="7">Mistral</option> |
| @@ -3645,6 +3624,7 @@ | ||
| 3645 | 3624 | <div class="alignitemscenter flex-container flexFlowColumn flexGrow flexShrink gap0 flexBasis48p" title="Scan chronologically until reached min entries or token budget." data-i18n="[title]Scan chronologically until reached min entries or token budget."> |
| 3646 | 3625 | <small> |
| 3647 | 3626 | <span data-i18n="Min Activations">Min Activations</span> |
| 3627 | + <div class="fa-solid fa-triangle-exclamation opacity50p" data-i18n="[title](disabled when max recursion steps are used)" title="(disabled when max recursion steps are used)"></div> | |
| 3648 | 3628 | </small> |
| 3649 | 3629 | <input class="neo-range-slider" type="range" id="world_info_min_activations" name="world_info_min_activations" min="0" max="100" step="1"> |
| 3650 | 3630 | <input class="neo-range-input" type="number" min="0" max="100" step="1" data-for="world_info_min_activations" id="world_info_min_activations_counter"> |
| @@ -3658,6 +3638,14 @@ | ||
| 3658 | 3638 | <input class="neo-range-slider" type="range" id="world_info_min_activations_depth_max" name="volume" min="0" max="100" step="1"> |
| 3659 | 3639 | <input class="neo-range-input" type="number" min="0" max="100" step="1" data-for="world_info_min_activations_depth_max" id="world_info_min_activations_depth_max_counter"> |
| 3660 | 3640 | </div> |
| 3641 | + <div class="alignitemscenter flex-container flexFlowColumn flexGrow flexShrink gap0 flexBasis48p" title="Cap the number of entry activation recursions" data-i18n="[title]Cap the number of entry activation recursions"> | |
| 3642 | + <small> | |
| 3643 | + <span data-i18n="Max Recursion Steps">Max Recursion Steps</span> | |
| 3644 | + <div class="fa-solid fa-triangle-exclamation opacity50p" data-i18n="[title]0 = unlimited, 1 = scans once and doesn't recurse, 2 = scans once and recurses once, etc\n(disabled when min activations are used)" title="0 = unlimited, 1 = scans once and doesn't recurse, 2 = scans once and recurses once, etc (disabled when min activations are used)"></div> | |
| 3645 | + </small> | |
| 3646 | + <input class="neo-range-slider" type="range" id="world_info_max_recursion_steps" name="world_info_max_recursion_steps" min="0" max="10" step="1"> | |
| 3647 | + <input class="neo-range-input" type="number" min="0" max="10" step="1" data-for="world_info_max_recursion_steps" id="world_info_max_recursion_steps_counter"> | |
| 3648 | + </div> | |
| 3661 | 3649 | |
| 3662 | 3650 | <div class="alignitemscenter flex-container flexFlowColumn flexGrow flexShrink flexBasis48p"> |
| 3663 | 3651 | <small data-i18n="Insertion Strategy"> |
| @@ -3921,8 +3909,8 @@ | ||
| 3921 | 3909 | <span data-i18n="Font Scale">Font Scale</span> |
| 3922 | 3910 | <div class="fa-solid fa-circle-info opacity50p" data-i18n="[title]Font size" title="Font size"></div> |
| 3923 | 3911 | </small> |
| 3924 | 3912 | <input class="neo-range-slider" type="range" id="font_scale" name="font_scale" min="0.85" max="1.25" step="0.01"> |
| 3925 | 3913 | <input class="neo-range-input" type="number" min="0.85" max="1.25" step="0.01" data-for="font_scale" id="font_scale_counter"> |
| 3926 | 3914 | </div> |
| 3927 | 3915 | |
| 3928 | 3916 | <div class="alignitemscenter flex-container flexFlowColumn flexBasis48p flexGrow flexShrink gap0"> |
| @@ -4134,7 +4122,7 @@ | ||
| 4134 | 4122 | <input id="movingUImode" type="checkbox" /> |
| 4135 | 4123 | <small data-i18n="Movable UI Panels">MovingUI <i class="fa-solid fa-desktop"></i></small> |
| 4136 | 4124 | </label> |
| 4137 | 4125 | <div data-newbie-hidden id="movingUIreset" title="Reset MovingUI panel sizes/locations." class="menu_button margin0" data-i18n="[title]Reset MovingUI panel sizes/locations."><i class=" fa-solid fa-recycle margin-r5"></i> <span data-i18n="mui_reset">Reset</span></div> |
| 4138 | 4126 | </div> |
| 4139 | 4127 | <div data-newbie-hidden id="MovingUI-presets-block" class="flex-container alignitemscenter"> |
| 4140 | 4128 | <div class="flex-container alignItemsFlexEnd"> |
| @@ -4590,6 +4578,7 @@ | ||
| 4590 | 4578 | <div data-newbie-hidden> |
| 4591 | 4579 | <label for="persona_description_position" data-i18n="Position:">Position:</label> |
| 4592 | 4580 | <select id="persona_description_position"> |
| 4581 | + <option value="9" data-i18n="None (disabled)">None (disabled)</option> | |
| 4593 | 4582 | <option value="0" data-i18n="In Story String / Prompt Manager">In Story String / Prompt Manager</option> |
| 4594 | 4583 | <option value="2" data-i18n="Top of Author's Note">Top of Author's Note</option> |
| 4595 | 4584 | <option value="3" data-i18n="Bottom of Author's Note">Bottom of Author's Note</option> |
| @@ -5615,13 +5604,16 @@ | ||
| 5615 | 5604 | <div class="flex-container wide100p flexGap10"> |
| 5616 | 5605 | <div class="flex4 flex-container flexFlowColumn flexNoGap"> |
| 5617 | 5606 | <div class="flex-container justifySpaceBetween"> |
| 5618 | 5607 | <small for="characterFilter" data-i18n="Filter to Character(s)Characters or Tags"> |
| 5619 | 5608 | Filter to Character(s)Characters or Tags |
| 5620 | 5609 | </small> |
| 5621 | 5610 | <label class="checkbox_label flexNoGap margin-r5" for="character_exclusion"> |
| 5622 | 5611 | <input type="checkbox" name="character_exclusion" /> |
| 5623 | 5612 | <span> |
| 5624 | - <small data-i18n="Character Exclusion">Character Exclusion</small> | |
| 5613 | + <small title="Switch the Character/Tags filter around to exclude the listed characters and tags from matching for this entry" data-i18n="[title]Switch the Character/Tags filter around to exclude the listed characters and tags from matching for this entry"> | |
| 5614 | + <span data-i18n="Exclude">Exclude</span> | |
| 5615 | + <div class="fa-solid fa-circle-info opacity50p"></div> | |
| 5616 | + </small> | |
| 5625 | 5617 | </span> |
| 5626 | 5618 | </label> |
| 5627 | 5619 | </div> |
| @@ -6577,6 +6569,7 @@ | ||
| 6577 | 6569 | <script src="lib/jquery-cookie-1.4.1.min.js"></script> |
| 6578 | 6570 | <script src="lib/jquery.ui.touch-punch.min.js"></script> |
| 6579 | 6571 | <script src="lib/showdown.min.js"></script> |
| 6572 | + <script src="lib/showdown-patch.js"></script> | |
| 6580 | 6573 | <script src="lib/showdown-katex.min.js"></script> |
| 6581 | 6574 | <script src="lib/popper.js"></script> |
| 6582 | 6575 | <script src="lib/purify.min.js"></script> |
| @@ -0,0 +1,24 @@ | ||
| 1 | +showdown.subParser('unhashHTMLSpans', function (text, options, globals) { | |
| 2 | + 'use strict'; | |
| 3 | + text = globals.converter._dispatch('unhashHTMLSpans.before', text, options, globals); | |
| 4 | + | |
| 5 | + for (var i = 0; i < globals.gHtmlSpans.length; ++i) { | |
| 6 | + var repText = globals.gHtmlSpans[i], | |
| 7 | + // limiter to prevent infinite loop (assume 10 as limit for recurse) | |
| 8 | + limit = 0; | |
| 9 | + | |
| 10 | + while (/¨C(\d+)C/.test(repText)) { | |
| 11 | + var num = RegExp.$1; | |
| 12 | + repText = repText.replace('¨C' + num + 'C', globals.gHtmlSpans[num]); | |
| 13 | + if (limit === 10000) { | |
| 14 | + console.error('maximum nesting of 10000 spans reached!!!'); | |
| 15 | + break; | |
| 16 | + } | |
| 17 | + ++limit; | |
| 18 | + } | |
| 19 | + text = text.replace('¨C' + i + 'C', repText); | |
| 20 | + } | |
| 21 | + | |
| 22 | + text = globals.converter._dispatch('unhashHTMLSpans.after', text, options, globals); | |
| 23 | + return text; | |
| 24 | +}); | |
| @@ -390,7 +390,7 @@ | ||
| 390 | 390 | "Alt Method": "طريقة بديلة", |
| 391 | 391 | "AI21 API Key": "مفتاح API لـ AI21", |
| 392 | 392 | "AI21 Model": "نموذج AI21", |
| 393 | 393 | "MakerSuiteGoogle AI Studio API Key": "مفتاح واجهة برمجة تطبيقات MakerSuiteGoogle AI Studio", |
| 394 | 394 | "Google Model": "نموذج جوجل", |
| 395 | 395 | "MistralAI API Key": "مفتاح واجهة برمجة التطبيقات MistralAI", |
| 396 | 396 | "MistralAI Model": "نموذج ميسترال آي آي", |
| @@ -390,7 +390,7 @@ | ||
| 390 | 390 | "Alt Method": "Alternative Methode", |
| 391 | 391 | "AI21 API Key": "AI21 API-Schlüssel", |
| 392 | 392 | "AI21 Model": "AI21-Modell", |
| 393 | 393 | "MakerSuiteGoogle AI Studio API Key": "MakerSuiteGoogle AI Studio API-Schlüssel", |
| 394 | 394 | "Google Model": "Google-Modell", |
| 395 | 395 | "MistralAI API Key": "MistralAI API-Schlüssel", |
| 396 | 396 | "MistralAI Model": "MistralAI-Modell", |
| @@ -390,7 +390,7 @@ | ||
| 390 | 390 | "Alt Method": "Método alternativo", |
| 391 | 391 | "AI21 API Key": "Clave API de AI21", |
| 392 | 392 | "AI21 Model": "Modelo de AI21", |
| 393 | 393 | "MakerSuiteGoogle AI Studio API Key": "Clave API de MakerSuiteGoogle AI Studio", |
| 394 | 394 | "Google Model": "Modelo de Google", |
| 395 | 395 | "MistralAI API Key": "Clave API de MistralAI", |
| 396 | 396 | "MistralAI Model": "Modelo MistralAI", |
| @@ -390,7 +390,7 @@ | ||
| 390 | 390 | "Alt Method": "Méthode alternative", |
| 391 | 391 | "AI21 API Key": "Clé API AI21", |
| 392 | 392 | "AI21 Model": "Modèle AI21", |
| 393 | 393 | "MakerSuiteGoogle AI Studio API Key": "Clé API MakerSuiteGoogle AI Studio", |
| 394 | 394 | "Google Model": "Modèle Google", |
| 395 | 395 | "MistralAI API Key": "Clé API MistralAI", |
| 396 | 396 | "MistralAI Model": "Modèle MistralAI", |
| @@ -390,7 +390,7 @@ | ||
| 390 | 390 | "Alt Method": "Aðferð Bakmenn", |
| 391 | 391 | "AI21 API Key": "Lykill API fyrir AI21", |
| 392 | 392 | "AI21 Model": "AI21 Módel", |
| 393 | 393 | "MakerSuiteGoogle AI Studio API Key": "MakerSuiteGoogle AI Studio API lykill", |
| 394 | 394 | "Google Model": "Google líkan", |
| 395 | 395 | "MistralAI API Key": "MistralAI API lykill", |
| 396 | 396 | "MistralAI Model": "MistralAI líkan", |
| @@ -390,7 +390,7 @@ | ||
| 390 | 390 | "Alt Method": "Metodo alternativo", |
| 391 | 391 | "AI21 API Key": "Chiave API di AI21", |
| 392 | 392 | "AI21 Model": "Modello AI21", |
| 393 | 393 | "MakerSuiteGoogle AI Studio API Key": "Chiave API MakerSuiteGoogle AI Studio", |
| 394 | 394 | "Google Model": "Modello Google", |
| 395 | 395 | "MistralAI API Key": "Chiave API MistralAI", |
| 396 | 396 | "MistralAI Model": "Modello MistralAI", |
| @@ -390,7 +390,7 @@ | ||
| 390 | 390 | "Alt Method": "代替手法", |
| 391 | 391 | "AI21 API Key": "AI21のAPIキー", |
| 392 | 392 | "AI21 Model": "AI21モデル", |
| 393 | 393 | "MakerSuiteGoogle AI Studio API Key": "MakerSuiteGoogle AI Studio APIキー", |
| 394 | 394 | "Google Model": "Google モデル", |
| 395 | 395 | "MistralAI API Key": "MistralAI API キー", |
| 396 | 396 | "MistralAI Model": "MistralAI モデル", |
| @@ -390,7 +390,7 @@ | ||
| 390 | 390 | "Alt Method": "대체 방법", |
| 391 | 391 | "AI21 API Key": "AI21 API 키", |
| 392 | 392 | "AI21 Model": "AI21 모델", |
| 393 | 393 | "MakerSuiteGoogle AI Studio API Key": "MakerSuiteGoogle AI Studio API 키", |
| 394 | 394 | "Google Model": "구글 모델", |
| 395 | 395 | "MistralAI API Key": "MistralAI API 키", |
| 396 | 396 | "MistralAI Model": "MistralAI 모델", |
| @@ -390,7 +390,7 @@ | ||
| 390 | 390 | "Alt Method": "Método Alternativo", |
| 391 | 391 | "AI21 API Key": "Chave da API AI21", |
| 392 | 392 | "AI21 Model": "Modelo AI21", |
| 393 | 393 | "MakerSuiteGoogle AI Studio API Key": "Chave API MakerSuiteGoogle AI Studio", |
| 394 | 394 | "Google Model": "Modelo Google", |
| 395 | 395 | "MistralAI API Key": "Chave de API MistralAI", |
| 396 | 396 | "MistralAI Model": "Modelo MistralAI", |
| @@ -43,7 +43,7 @@ | ||
| 43 | 43 | "Smoothing Factor": "Коэффициент сглаживания", |
| 44 | 44 | "No Repeat Ngram Size": "Размер no_repeat_ngram", |
| 45 | 45 | "Min Length": "Мин. длина", |
| 46 | 46 | "Alternative server URL (leave empty to use the default value).": "Альтернативный URL альтернативного сервера (оставьте пустым для стандартного значения)", |
| 47 | 47 | "Remove your real OAI API Key from the API panel BEFORE typing anything into this box": "Удалите свой личный OAI API Key из панели API, и ТОЛЬКО ПОСЛЕ ЭТОГО вводите что-то сюда", |
| 48 | 48 | "We cannot provide support for problems encountered while using an unofficial OpenAI proxy": "Мы не сможем предоставить помощь с проблемами, с которыми вы столкнетесь при использовании неофициальных прокси для OpenAI", |
| 49 | 49 | "Context Size (tokens)": "Размер контекста (в токенах)", |
| @@ -186,7 +186,7 @@ | ||
| 186 | 186 | "Generate only one line per request": "Генерировать одну строку на запрос", |
| 187 | 187 | "Misc. Settings": "Доп. настройки", |
| 188 | 188 | "Auto-Continue": "Авто-продолжение", |
| 189 | 189 | "Collapse Consecutive Newlines": "Сворачивать последовательныенеск. новыеновых строкистрок в одну", |
| 190 | 190 | "Allow for Chat Completion APIs": "Разрешить для Chat Completion API", |
| 191 | 191 | "Target length (tokens)": "Целевая длина (в токенах)", |
| 192 | 192 | "World Info": "Информация о мире", |
| @@ -373,7 +373,7 @@ | ||
| 373 | 373 | "Prefer Character Card Prompt": "Приоритет промпту из карточки персонажа", |
| 374 | 374 | "Prefer Character Card Jailbreak": "Приоритет джейлбрейку из карточки персонажа", |
| 375 | 375 | "Press Send to continue": "Кнопка отправки продолжает сообщение", |
| 376 | 376 | "Quick 'Continue' button": "Кнопка быстрогоБыстрое продолженияпродолжение", |
| 377 | 377 | "Log prompts to console": "Выводить промпты в консоль", |
| 378 | 378 | "Never resize avatars": "Не менять размер аватарок", |
| 379 | 379 | "Show avatar filenames": "Показывать названия файлов аватарок", |
| @@ -495,7 +495,7 @@ | ||
| 495 | 495 | "(Write a comma-separated list of tags)": "(Список тегов через запятую)", |
| 496 | 496 | "(A brief description of the personality)": "(Краткое описание личности)", |
| 497 | 497 | "(Circumstances and context of the interaction)": "(Обстоятельства и контекст этого диалога)", |
| 498 | 498 | "(Examples of chat dialog. Begin each example with START on a new line.)": "(Примеры диалога. Начинайте каждый пример с START или новой линиейстрокой.)", |
| 499 | 499 | "Type here...": "Пишите здесь...", |
| 500 | 500 | "Comma separated (required)": "Через запятую (обязательное поле)", |
| 501 | 501 | "What this keyword should mean to the AI, sent verbatim": "Что это ключевое слово должно означать для ИИ, отправляется дословно", |
| @@ -552,7 +552,7 @@ | ||
| 552 | 552 | "Click to set a new User Name": "Нажмите, чтобы задать новое имя пользователя.", |
| 553 | 553 | "Click to lock your selected persona to the current chat. Click again to remove the lock.": "Нажмите, чтобы закрепить выбранную персону для текущего чата. Нажмите еще раз, чтобы открепить.", |
| 554 | 554 | "Click to set user name for all messages": "Нажмите, чтобы задать имя пользователя для всех сообщений.", |
| 555 | 555 | "Create a dummy persona": "Создать пустую персону-болванку", |
| 556 | 556 | "Character Management": "Управление персонажами", |
| 557 | 557 | "Locked = Character Management panel will stay open": "Закреплено = Панель управление персонажами останется открытой", |
| 558 | 558 | "Select/Create Characters": "Выбрать/Создать персонажа", |
| @@ -625,7 +625,7 @@ | ||
| 625 | 625 | "Automatically select a background based on the chat context": "Автоматический выбор фона в зависимости от контекста чата", |
| 626 | 626 | "Filter": "Фильтр", |
| 627 | 627 | "Exclude message from prompts": "Исключить сообщение из промпта", |
| 628 | 628 | "Include message in prompts": "Включить сообщение в подсказкипромпт", |
| 629 | 629 | "Create checkpoint": "Создать чекпоинт", |
| 630 | 630 | "Create Branch": "Создать ветку", |
| 631 | 631 | "Embed file or image": "Вставить файл или изображение", |
| @@ -722,7 +722,7 @@ | ||
| 722 | 722 | "Proxy Server URL": "Адрес прокси-сервера", |
| 723 | 723 | "MistralAI Model": "Модель MistralAI", |
| 724 | 724 | "MistralAI API Key": "Ключ от API MistralAI", |
| 725 | 725 | "MakerSuiteGoogle AI Studio API Key": "Ключ от API MakerSuiteGoogle AI Studio", |
| 726 | 726 | "Google Model": "Модель Google", |
| 727 | 727 | "Cohere API Key": "Ключ от API Cohere", |
| 728 | 728 | "Cohere Model": "Модель Cohere", |
| @@ -1661,5 +1661,52 @@ | ||
| 1661 | 1661 | "ext_regex_ai_output_desc": "Сообщения, полученные от API", |
| 1662 | 1662 | "ext_regex_sts_desc": "Сообщения, отправленные с помощью команд STscript", |
| 1663 | 1663 | "ext_regex_wi_desc": "Содержимое лорбуков и миров. Для работы требует включения флажка \"Только промпт\"!", |
| 1664 | 1664 | "ext_regex_only_format_display_desc": "История чата не изменится, замена будет осуществляться только в отображаемом сообщении (в UI)", |
| 1665 | + "Prefer Character Card Instructions": "Приоритет инструкциям из карточек", | |
| 1666 | + "If checked and the character card contains a Post-History Instructions override, use that instead": "Если в карточке персонажа имеется собственная инструкция после истории, в промпт попадёт именно она", | |
| 1667 | + "Auto-select Input Text": "Автовыделение вводимого текста", | |
| 1668 | + "Enable auto-select of input text in some text fields when clicking/selecting them. Applies to popup input textboxes, and possible other custom input fields.": "Автоматически выделять вводимый текст в некоторых текстовых полях при клике/выборе. Работает для вспл. окон и различных кастомных полей ввода.", | |
| 1669 | + "Reset MovingUI panel sizes/locations.": "Сбросить расположение и размеры панелей MovingUI.", | |
| 1670 | + "mui_reset": "Сброс", | |
| 1671 | + "Quick 'Impersonate' button": "Быстрое перевоплощение", | |
| 1672 | + "Show a button in the input area to ask the AI to impersonate your character for a single message": "Показать в поле ввода кнопку, по нажатии на которую ИИ сгенерирует одно сообщение от лица вашего персонажа.", | |
| 1673 | + "Separators as Stop Strings": "Разделители как стоп-строки", | |
| 1674 | + "Names as Stop Strings": "Имена как стоп-строки", | |
| 1675 | + "Add Character and User names to a list of stopping strings.": "Добавлять имена персонажа и пользователя в список стоп-строк.", | |
| 1676 | + "Allow Post-History Instructions": "Разрешить инструкции после истории", | |
| 1677 | + "context_allow_post_history_instructions": "Добавлять в конец промпта инструкции после истории. Работает только при наличии таких инструкций в карточке И при включенной опции ''Приоритет инструкциям из карточек''.\nНЕ РЕКОМЕНДУЕТСЯ ДЛЯ МОДЕЛЕЙ TEXT COMPLETION, МОЖЕТ ПОРТИТЬ ВЫХОДНОЙ ТЕКСТ.", | |
| 1678 | + "First User Prefix": "Первый префикс пользователя", | |
| 1679 | + "Inserted before the first User's message.": "Вставляется перед первым сообщением пользователя.", | |
| 1680 | + "Last User Prefix": "Последний префикс пользователя", | |
| 1681 | + "instruct_last_input_sequence": "Вставляется перед последним сообщением пользователя.", | |
| 1682 | + "Inserted before a User message and as a last prompt line when impersonating.": "Вставляется перед сообщением пользователя в качестве последней строки промпта при перевоплощении.", | |
| 1683 | + "Inserted before a System (added by slash commands or extensions) message.": "Вставляется перед сообщением системы (может быть добавлено слэш-командой или расширением).", | |
| 1684 | + "Load Asset List": "Загрузить список ресурсов", | |
| 1685 | + "Never add character names.": "Не вставлять имя персонажа.", | |
| 1686 | + "Don't add character names unless necessary.": "Вставлять имя персонажа только когда это необходимо.", | |
| 1687 | + "character_names_none": "Не добавлять имена персонажей в качестве префикса. Может повредить качеству ответов в групповых чатах, используйте с осторожностью.", | |
| 1688 | + "Auxiliary": "Вспомогательный", | |
| 1689 | + "Post-History Instructions": "Инструкции после истории", | |
| 1690 | + "Current persona updated": "Текущая персона изменена", | |
| 1691 | + "Your messages will now be sent as ${0}": "Ваши сообщения будут отправляться от лица ${0}", | |
| 1692 | + "Copied!": "Скопировано!", | |
| 1693 | + "Are you sure you want to delete this message?": "Вы точно хотите удалить это сообщение?", | |
| 1694 | + "Delete Message": "Удалить сообщение", | |
| 1695 | + "Delete Swipe": "Удалить свайп", | |
| 1696 | + "Could not get a reply from API. Check your connection settings / API key and try again.": "Не удалось получить ответ от API. Проверьте настройки соединения и API-ключ и повторите попытку.", | |
| 1697 | + "Connecting To Proxy": "Подключение к прокси", | |
| 1698 | + "Are you sure you want to connect to the following proxy URL?": "Вы точно хотите соединиться с прокси по этому адресу?", | |
| 1699 | + "API connection successful!": "Соединение с API установлено!", | |
| 1700 | + "Proxy Saved": "Прокси сохранена", | |
| 1701 | + "Proxy Deleted": "Прокси удалена", | |
| 1702 | + "Could not find proxy with name '${0}'": "Не удалось найти прокси с названием '${0}'", | |
| 1703 | + "Proxy preset '${0}' not found in proxies array.": "Пресет с названием '${0}' не найден в списке прокси.", | |
| 1704 | + "Please wait for the previous request to complete.": "Пожалуйста, дождитесь окончания обработки предыдущего запроса.", | |
| 1705 | + "Start new chat?": "Начать новый чат?", | |
| 1706 | + "If necessary, you can later restore this chat file from the /backups folder": "При необходимости этот чат можно будет восстановить из папки /backups", | |
| 1707 | + "Also delete the current chat file": "Также удалить текущий чат", | |
| 1708 | + "chat_rename_1": "Введите новое имя чата:", | |
| 1709 | + "chat_rename_2": "!!Не используйте имя уже существующего файла, это приведёт к ошибке!!", | |
| 1710 | + "chat_rename_3": "Будут разрушены связи между чатами-чекпоинтами.", | |
| 1711 | + "chat_rename_4": "Расширение '.jsonl' дописывать не нужно." | |
| 1665 | 1712 | } |
| @@ -390,7 +390,7 @@ | ||
| 390 | 390 | "Alt Method": "Альтернативний метод", |
| 391 | 391 | "AI21 API Key": "Ключ API для AI21", |
| 392 | 392 | "AI21 Model": "Модель AI21", |
| 393 | 393 | "MakerSuiteGoogle AI Studio API Key": "Ключ API MakerSuiteGoogle AI Studio", |
| 394 | 394 | "Google Model": "Модель Google", |
| 395 | 395 | "MistralAI API Key": "Ключ API MistralAI", |
| 396 | 396 | "MistralAI Model": "Модель MistralAI", |
| @@ -390,7 +390,7 @@ | ||
| 390 | 390 | "Alt Method": "Phương pháp thay thế", |
| 391 | 391 | "AI21 API Key": "Khóa API của AI21", |
| 392 | 392 | "AI21 Model": "Mô hình AI21", |
| 393 | 393 | "MakerSuiteGoogle AI Studio API Key": "Khóa API MakerSuiteGoogle AI Studio", |
| 394 | 394 | "Google Model": "Mô hình Google", |
| 395 | 395 | "MistralAI API Key": "Khóa API MistralAI", |
| 396 | 396 | "MistralAI Model": "Mô hình MistralAI", |
| @@ -406,7 +406,7 @@ | ||
| 406 | 406 | "Alt Method": "备用方法", |
| 407 | 407 | "AI21 API Key": "AI21 API 密钥", |
| 408 | 408 | "AI21 Model": "AI21 模型", |
| 409 | 409 | "MakerSuiteGoogle AI Studio API Key": "MakerSuiteGoogle AI Studio API 密钥", |
| 410 | 410 | "Google Model": "Google 模型", |
| 411 | 411 | "MistralAI API Key": "MistralAI API 密钥", |
| 412 | 412 | "MistralAI Model": "MistralAI 模型", |
| @@ -391,7 +391,7 @@ | ||
| 391 | 391 | "Alt Method": "替代方法", |
| 392 | 392 | "AI21 API Key": "AI21 API 金鑰", |
| 393 | 393 | "AI21 Model": "AI21 模型", |
| 394 | 394 | "MakerSuiteGoogle AI Studio API Key": "MakerSuiteGoogle AI Studio API 金鑰", |
| 395 | 395 | "Google Model": "Google 模型", |
| 396 | 396 | "MistralAI API Key": "MistralAI API 金鑰", |
| 397 | 397 | "MistralAI Model": "MistralAI 模型", |
| @@ -84,6 +84,7 @@ import { | ||
| 84 | 84 | context_presets, |
| 85 | 85 | resetMovableStyles, |
| 86 | 86 | forceCharacterEditorTokenize, |
| 87 | + applyPowerUserSettings, | |
| 87 | 88 | } from './scripts/power-user.js'; |
| 88 | 89 | |
| 89 | 90 | import { |
| @@ -242,7 +243,7 @@ import { DragAndDropHandler } from './scripts/dragdrop.js'; | ||
| 242 | 243 | import { INTERACTABLE_CONTROL_CLASS, initKeyboard } from './scripts/keyboard.js'; |
| 243 | 244 | import { initDynamicStyles } from './scripts/dynamic-styles.js'; |
| 244 | 245 | import { SlashCommandEnumValue, enumTypes } from './scripts/slash-commands/SlashCommandEnumValue.js'; |
| 245 | 246 | import { commonEnumProviders, enumIcons } from './scripts/slash-commands/SlashCommandCommonEnumsProvider.js'; |
| 246 | 247 | |
| 247 | 248 | //exporting functions and vars for mods |
| 248 | 249 | export { |
| @@ -415,6 +416,7 @@ export const event_types = { | ||
| 415 | 416 | GENERATION_STOPPED: 'generation_stopped', |
| 416 | 417 | GENERATION_ENDED: 'generation_ended', |
| 417 | 418 | EXTENSIONS_FIRST_LOAD: 'extensions_first_load', |
| 419 | + EXTENSION_SETTINGS_LOADED: 'extension_settings_loaded', | |
| 418 | 420 | SETTINGS_LOADED: 'settings_loaded', |
| 419 | 421 | SETTINGS_UPDATED: 'settings_updated', |
| 420 | 422 | GROUP_UPDATED: 'group_updated', |
| @@ -486,14 +488,6 @@ let default_user_name = 'User'; | ||
| 486 | 488 | export let name1 = default_user_name; |
| 487 | 489 | export let name2 = 'SillyTavern System'; |
| 488 | 490 | export let chat = []; |
| 489 | -let safetychat = [ | |
| 490 | - { | |
| 491 | - name: systemUserName, | |
| 492 | - is_user: false, | |
| 493 | - create_date: 0, | |
| 494 | - mes: 'You deleted a character/chat and arrived back here for safety reasons! Pick another character!', | |
| 495 | - }, | |
| 496 | -]; | |
| 497 | 491 | let chatSaveTimeout; |
| 498 | 492 | let importFlashTimeout; |
| 499 | 493 | export let isChatSaving = false; |
| @@ -592,6 +586,17 @@ export const extension_prompt_roles = { | ||
| 592 | 586 | |
| 593 | 587 | export const MAX_INJECTION_DEPTH = 1000; |
| 594 | 588 | |
| 589 | +const SAFETY_CHAT = [ | |
| 590 | + { | |
| 591 | + name: systemUserName, | |
| 592 | + force_avatar: system_avatar, | |
| 593 | + is_system: true, | |
| 594 | + is_user: false, | |
| 595 | + create_date: 0, | |
| 596 | + mes: 'You deleted a character/chat and arrived back here for safety reasons! Pick another character!', | |
| 597 | + }, | |
| 598 | +]; | |
| 599 | + | |
| 595 | 600 | export let system_messages = {}; |
| 596 | 601 | |
| 597 | 602 | async function getSystemMessages() { |
| @@ -1879,7 +1884,12 @@ export function messageFormatting(mes, ch_name, isSystem, isUser, messageId) { | ||
| 1879 | 1884 | } |
| 1880 | 1885 | |
| 1881 | 1886 | if (Number(messageId) === 0 && !isSystem && !isUser) { |
| 1887 | + const mesBeforeReplace = mes; | |
| 1888 | + const chatMessage = chat[messageId]; | |
| 1882 | 1889 | mes = substituteParams(mes, undefined, ch_name); |
| 1890 | + if (chatMessage && chatMessage.mes === mesBeforeReplace && chatMessage.extra?.display_text !== mesBeforeReplace) { | |
| 1891 | + chatMessage.mes = mes; | |
| 1892 | + } | |
| 1883 | 1893 | } |
| 1884 | 1894 | |
| 1885 | 1895 | mesForShowdownParse = mes; |
| @@ -2185,7 +2195,7 @@ export function addCopyToCodeBlocks(messageElement) { | ||
| 2185 | 2195 | codeBlocks.get(i).appendChild(copyButton); |
| 2186 | 2196 | copyButton.addEventListener('pointerup', function (event) { |
| 2187 | 2197 | navigator.clipboard.writeText(codeBlocks.get(i).innerText); |
| 2188 | 2198 | toastr.info('t`Copied!'`, '', { timeOut: 2000 }); |
| 2189 | 2199 | }); |
| 2190 | 2200 | } |
| 2191 | 2201 | } |
| @@ -2698,7 +2708,7 @@ function addPersonaDescriptionExtensionPrompt() { | ||
| 2698 | 2708 | const INJECT_TAG = 'PERSONA_DESCRIPTION'; |
| 2699 | 2709 | setExtensionPrompt(INJECT_TAG, '', extension_prompt_types.IN_PROMPT, 0); |
| 2700 | 2710 | |
| 2701 | 2711 | if (!power_user.persona_description || power_user.persona_description_position === persona_description_positions.NONE) { |
| 2702 | 2712 | return; |
| 2703 | 2713 | } |
| 2704 | 2714 | |
| @@ -2819,7 +2829,7 @@ export function getCharacterCardFields() { | ||
| 2819 | 2829 | } |
| 2820 | 2830 | |
| 2821 | 2831 | export function isStreamingEnabled() { |
| 2822 | 2832 | const noStreamSources = [chat_completion_sources.SCALE, chat_completion_sources.AI21]; |
| 2823 | 2833 | return ((main_api == 'openai' && oai_settings.stream_openai && !noStreamSources.includes(oai_settings.chat_completion_source) && !(oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE && oai_settings.google_model.includes('bison'))) |
| 2824 | 2834 | || (main_api == 'kobold' && kai_settings.streaming_kobold && kai_flags.can_use_streaming) |
| 2825 | 2835 | || (main_api == 'novel' && nai_settings.streaming_novel) |
| @@ -2839,7 +2849,14 @@ function hideStopButton() { | ||
| 2839 | 2849 | } |
| 2840 | 2850 | |
| 2841 | 2851 | class StreamingProcessor { |
| 2842 | - constructor(type, force_name2, timeStarted, messageAlreadyGenerated) { | |
| 2852 | + /** | |
| 2853 | + * Creates a new streaming processor. | |
| 2854 | + * @param {string} type Generation type | |
| 2855 | + * @param {boolean} forceName2 If true, force the use of name2 | |
| 2856 | + * @param {Date} timeStarted Date when generation was started | |
| 2857 | + * @param {string} continueMessage Previous message if the type is 'continue' | |
| 2858 | + */ | |
| 2859 | + constructor(type, forceName2, timeStarted, continueMessage) { | |
| 2843 | 2860 | this.result = ''; |
| 2844 | 2861 | this.messageId = -1; |
| 2845 | 2862 | this.messageDom = null; |
| @@ -2849,14 +2866,14 @@ class StreamingProcessor { | ||
| 2849 | 2866 | /** @type {HTMLTextAreaElement} */ |
| 2850 | 2867 | this.sendTextarea = document.querySelector('#send_textarea'); |
| 2851 | 2868 | this.type = type; |
| 2852 | 2869 | this.force_name2 = force_name2forceName2; |
| 2853 | 2870 | this.isStopped = false; |
| 2854 | 2871 | this.isFinished = false; |
| 2855 | 2872 | this.generator = this.nullStreamingGeneration; |
| 2856 | 2873 | this.abortController = new AbortController(); |
| 2857 | 2874 | this.firstMessageText = '...'; |
| 2858 | 2875 | this.timeStarted = timeStarted; |
| 2859 | - this.messageAlreadyGenerated = messageAlreadyGenerated; | |
| 2876 | + this.continueMessage = type === 'continue' ? continueMessage : ''; | |
| 2860 | 2877 | this.swipes = []; |
| 2861 | 2878 | /** @type {import('./scripts/logprobs.js').TokenLogprobs[]} */ |
| 2862 | 2879 | this.messageLogprobs = []; |
| @@ -3009,8 +3026,7 @@ class StreamingProcessor { | ||
| 3009 | 3026 | await eventSource.emit(event_types.IMPERSONATE_READY, text); |
| 3010 | 3027 | } |
| 3011 | 3028 | |
| 3012 | - const continueMsg = this.type === 'continue' ? this.messageAlreadyGenerated : undefined; | |
| 3029 | + saveLogprobsForActiveMessage(this.messageLogprobs.filter(Boolean), this.continueMessage); | |
| 3013 | - saveLogprobsForActiveMessage(this.messageLogprobs.filter(Boolean), continueMsg); | |
| 3014 | 3030 | await saveChatConditional(); |
| 3015 | 3031 | unblockGeneration(); |
| 3016 | 3032 | generatedPromptCache = ''; |
| @@ -3106,7 +3122,7 @@ class StreamingProcessor { | ||
| 3106 | 3122 | if (logprobs) { |
| 3107 | 3123 | this.messageLogprobs.push(...(Array.isArray(logprobs) ? logprobs : [logprobs])); |
| 3108 | 3124 | } |
| 3109 | 3125 | await sw.tick(() => this.onProgressStreaming(this.messageId, this.messageAlreadyGeneratedcontinueMessage + text)); |
| 3110 | 3126 | } |
| 3111 | 3127 | const seconds = (timestamps[timestamps.length - 1] - timestamps[0]) / 1000; |
| 3112 | 3128 | console.warn(`Stream stats: ${timestamps.length} tokens, ${seconds.toFixed(2)} seconds, rate: ${Number(timestamps.length / seconds).toFixed(2)} TPS`); |
| @@ -3299,8 +3315,6 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 3299 | 3315 | const isInstruct = power_user.instruct.enabled && main_api !== 'openai'; |
| 3300 | 3316 | const isImpersonate = type == 'impersonate'; |
| 3301 | 3317 | |
| 3302 | - let message_already_generated = isImpersonate ? `${name1}: ` : `${name2}: `; | |
| 3303 | - | |
| 3304 | 3318 | if (!(dryRun || type == 'regenerate' || type == 'swipe' || type == 'quiet')) { |
| 3305 | 3319 | const interruptedByCommand = await processCommands(String($('#send_textarea').val())); |
| 3306 | 3320 | |
| @@ -3715,7 +3729,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 3715 | 3729 | const storyStringParams = { |
| 3716 | 3730 | description: description, |
| 3717 | 3731 | personality: personality, |
| 3718 | - persona: persona, | |
| 3732 | + persona: power_user.persona_description_position == persona_description_positions.IN_PROMPT ? persona : '', | |
| 3719 | 3733 | scenario: scenario, |
| 3720 | 3734 | system: isInstruct ? system : '', |
| 3721 | 3735 | char: name2, |
| @@ -3739,7 +3753,6 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 3739 | 3753 | let oaiMessageExamples = []; |
| 3740 | 3754 | |
| 3741 | 3755 | if (main_api === 'openai') { |
| 3742 | - message_already_generated = ''; | |
| 3743 | 3756 | oaiMessages = setOpenAIMessages(coreChat); |
| 3744 | 3757 | oaiMessageExamples = setOpenAIMessageExamples(mesExamplesArray); |
| 3745 | 3758 | } |
| @@ -3750,7 +3763,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 3750 | 3763 | } |
| 3751 | 3764 | |
| 3752 | 3765 | let examplesString = ''; |
| 3753 | 3766 | let chatString = addChatsPreamble(addChatsSeparator('')); |
| 3754 | 3767 | let cyclePrompt = ''; |
| 3755 | 3768 | |
| 3756 | 3769 | async function getMessagesTokenCount() { |
| @@ -3759,10 +3772,10 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 3759 | 3772 | storyString, |
| 3760 | 3773 | afterScenarioAnchor, |
| 3761 | 3774 | examplesString, |
| 3775 | + userAlignmentMessage, | |
| 3762 | 3776 | chatString, |
| 3763 | - quiet_prompt, | |
| 3777 | + modifyLastPromptLine(''), | |
| 3764 | 3778 | cyclePrompt, |
| 3765 | - userAlignmentMessage, | |
| 3766 | 3779 | ].join('').replace(/\r/gm, ''); |
| 3767 | 3780 | return getTokenCountAsync(encodeString, power_user.token_padding); |
| 3768 | 3781 | } |
| @@ -3793,8 +3806,8 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 3793 | 3806 | } |
| 3794 | 3807 | |
| 3795 | 3808 | tokenCount += await getTokenCountAsync(item.replace(/\r/gm, '')); |
| 3796 | - chatString = item + chatString; | |
| 3797 | 3809 | if (tokenCount < this_max_context) { |
| 3810 | + chatString = chatString + item; | |
| 3798 | 3811 | arrMes[index] = item; |
| 3799 | 3812 | lastAddedIndex = Math.max(lastAddedIndex, index); |
| 3800 | 3813 | } else { |
| @@ -3820,8 +3833,8 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 3820 | 3833 | } |
| 3821 | 3834 | |
| 3822 | 3835 | tokenCount += await getTokenCountAsync(item.replace(/\r/gm, '')); |
| 3823 | - chatString = item + chatString; | |
| 3824 | 3836 | if (tokenCount < this_max_context) { |
| 3837 | + chatString = chatString + item; | |
| 3825 | 3838 | arrMes[i] = item; |
| 3826 | 3839 | lastAddedIndex = Math.max(lastAddedIndex, i); |
| 3827 | 3840 | } else { |
| @@ -3882,7 +3895,6 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 3882 | 3895 | cyclePrompt += oai_settings.continue_postfix; |
| 3883 | 3896 | continue_mag += oai_settings.continue_postfix; |
| 3884 | 3897 | } |
| 3885 | - message_already_generated = continue_mag; | |
| 3886 | 3898 | } |
| 3887 | 3899 | |
| 3888 | 3900 | const originalType = type; |
| @@ -4019,15 +4031,16 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 4019 | 4031 | async function checkPromptSize() { |
| 4020 | 4032 | console.debug('---checking Prompt size'); |
| 4021 | 4033 | setPromptString(); |
| 4034 | + const jointMessages = mesSend.map((e) => `${e.extensionPrompts.join('')}${e.message}`).join(''); | |
| 4022 | 4035 | const prompt = [ |
| 4023 | 4036 | beforeScenarioAnchor, |
| 4024 | 4037 | storyString, |
| 4025 | 4038 | afterScenarioAnchor, |
| 4026 | 4039 | mesExmString, |
| 4027 | - mesSend.map((e) => `${e.extensionPrompts.join('')}${e.message}`).join(''), | |
| 4040 | + addChatsPreamble(addChatsSeparator(jointMessages)), | |
| 4028 | 4041 | '\n', |
| 4042 | + modifyLastPromptLine(''), | |
| 4029 | 4043 | generatedPromptCache, |
| 4030 | - quiet_prompt, | |
| 4031 | 4044 | ].join('').replace(/\r/gm, ''); |
| 4032 | 4045 | let thisPromptContextSize = await getTokenCountAsync(prompt, power_user.token_padding); |
| 4033 | 4046 | |
| @@ -4293,7 +4306,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 4293 | 4306 | padding: power_user.token_padding, |
| 4294 | 4307 | main_api: main_api, |
| 4295 | 4308 | instruction: isInstruct ? substituteParams(power_user.prefer_character_prompt && system ? system : power_user.instruct.system_prompt) : '', |
| 4296 | 4309 | userPersona: (power_user.persona_descriptionpersona_description_position == persona_description_positions.IN_PROMPT ? (persona || '') : ''), |
| 4297 | 4310 | }; |
| 4298 | 4311 | |
| 4299 | 4312 | //console.log(additionalPromptStuff); |
| @@ -4309,7 +4322,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | ||
| 4309 | 4322 | console.debug(`pushed prompt bits to itemizedPrompts array. Length is now: ${itemizedPrompts.length}`); |
| 4310 | 4323 | |
| 4311 | 4324 | if (isStreamingEnabled() && type !== 'quiet') { |
| 4312 | 4325 | streamingProcessor = new StreamingProcessor(type, force_name2, generation_started, message_already_generatedcontinue_mag); |
| 4313 | 4326 | if (isContinue) { |
| 4314 | 4327 | // Save reply does add cycle text to the prompt, so it's not needed here |
| 4315 | 4328 | streamingProcessor.firstMessageText = ''; |
| @@ -5071,7 +5084,7 @@ async function promptItemize(itemizedPrompts, requestedMesId) { | ||
| 5071 | 5084 | } |
| 5072 | 5085 | |
| 5073 | 5086 | navigator.clipboard.writeText(rawPromptValues); |
| 5074 | 5087 | toastr.info('t`Copied!'`); |
| 5075 | 5088 | }); |
| 5076 | 5089 | |
| 5077 | 5090 | popup.dlg.querySelector('#showRawPrompt').addEventListener('click', function () { |
| @@ -5337,17 +5350,10 @@ export function cleanUpMessage(getMessage, isImpersonate, isContinue, displayInc | ||
| 5337 | 5350 | // Regex uses vars, so add before formatting |
| 5338 | 5351 | getMessage = getRegexedString(getMessage, isImpersonate ? regex_placement.USER_INPUT : regex_placement.AI_OUTPUT); |
| 5339 | 5352 | |
| 5340 | - if (!displayIncompleteSentences && power_user.trim_sentences) { | |
| 5341 | - getMessage = trimToEndSentence(getMessage, power_user.include_newline); | |
| 5342 | - } | |
| 5343 | - | |
| 5344 | 5353 | if (power_user.collapse_newlines) { |
| 5345 | 5354 | getMessage = collapseNewlines(getMessage); |
| 5346 | 5355 | } |
| 5347 | 5356 | |
| 5348 | - if (power_user.trim_spaces) { | |
| 5349 | - getMessage = getMessage.trim(); | |
| 5350 | - } | |
| 5351 | 5357 | // trailing invisible whitespace before every newlines, on a multiline string |
| 5352 | 5358 | // "trailing whitespace on newlines \nevery line of the string \n?sample text" -> |
| 5353 | 5359 | // "trailing whitespace on newlines\nevery line of the string\nsample text" |
| @@ -5439,6 +5445,14 @@ export function cleanUpMessage(getMessage, isImpersonate, isContinue, displayInc | ||
| 5439 | 5445 | getMessage = getMessage.trim(); |
| 5440 | 5446 | } |
| 5441 | 5447 | |
| 5448 | + if (!displayIncompleteSentences && power_user.trim_sentences) { | |
| 5449 | + getMessage = trimToEndSentence(getMessage, power_user.include_newline); | |
| 5450 | + } | |
| 5451 | + | |
| 5452 | + if (power_user.trim_spaces) { | |
| 5453 | + getMessage = getMessage.trim(); | |
| 5454 | + } | |
| 5455 | + | |
| 5442 | 5456 | return getMessage; |
| 5443 | 5457 | } |
| 5444 | 5458 | |
| @@ -5669,7 +5683,7 @@ export function resetChatState() { | ||
| 5669 | 5683 | // replaces deleted charcter name with system user since it will be displayed next. |
| 5670 | 5684 | name2 = systemUserName; |
| 5671 | 5685 | // sets up system user to tell user about having deleted a character |
| 5672 | 5686 | chat.splice(0, =chat.length, [...safetychat]SAFETY_CHAT); |
| 5673 | 5687 | // resets chat metadata |
| 5674 | 5688 | chat_metadata = {}; |
| 5675 | 5689 | // resets the characters array, forcing getcharacters to reset |
| @@ -6300,7 +6314,7 @@ export function setUserName(value) { | ||
| 6300 | 6314 | console.log(`User name changed to ${name1}`); |
| 6301 | 6315 | $('#your_name').val(name1); |
| 6302 | 6316 | if (power_user.persona_show_notifications) { |
| 6303 | 6317 | toastr.success(t`Your messages will now be sent as ${name1}`, 't`Current persona updated'`); |
| 6304 | 6318 | } |
| 6305 | 6319 | saveSettingsDebounced(); |
| 6306 | 6320 | } |
| @@ -6452,6 +6466,8 @@ export async function getSettings() { | ||
| 6452 | 6466 | // Load power user settings |
| 6453 | 6467 | await loadPowerUserSettings(settings, data); |
| 6454 | 6468 | |
| 6469 | + applyPowerUserSettings(); | |
| 6470 | + | |
| 6455 | 6471 | // Load character tags |
| 6456 | 6472 | loadTagsSettings(settings); |
| 6457 | 6473 | |
| @@ -6506,9 +6522,10 @@ export async function getSettings() { | ||
| 6506 | 6522 | selected_button = settings.selected_button; |
| 6507 | 6523 | |
| 6508 | 6524 | if (data.enable_extensions) { |
| 6525 | + const enableAutoUpdate = Boolean(data.enable_extensions_auto_update); | |
| 6509 | 6526 | const isVersionChanged = settings.currentVersion !== currentVersion; |
| 6510 | 6527 | await loadExtensionSettings(settings, isVersionChanged, enableAutoUpdate); |
| 6511 | 6528 | await eventSource.emit(event_types.EXTENSION_SETTINGS_LOADED); |
| 6512 | 6529 | } |
| 6513 | 6530 | |
| 6514 | 6531 | firstRun = !!settings.firstRun; |
| @@ -8379,6 +8396,12 @@ const CONNECT_API_MAP = { | ||
| 8379 | 8396 | button: '#api_button_openai', |
| 8380 | 8397 | source: chat_completion_sources.OPENAI, |
| 8381 | 8398 | }, |
| 8399 | + // Google alias | |
| 8400 | + 'google': { | |
| 8401 | + selected: 'openai', | |
| 8402 | + button: '#api_button_openai', | |
| 8403 | + source: chat_completion_sources.MAKERSUITE, | |
| 8404 | + }, | |
| 8382 | 8405 | // OpenRouter special naming, to differentiate between chat comp and text comp |
| 8383 | 8406 | 'openrouter': { |
| 8384 | 8407 | selected: 'openai', |
| @@ -8464,7 +8487,7 @@ async function disableInstructCallback() { | ||
| 8464 | 8487 | /** |
| 8465 | 8488 | * @param {string} text API name |
| 8466 | 8489 | */ |
| 8467 | 8490 | async function connectAPISlash(_args, text) { |
| 8468 | 8491 | if (!text.trim()) { |
| 8469 | 8492 | for (const [key, config] of Object.entries(CONNECT_API_MAP)) { |
| 8470 | 8493 | if (config.selected !== main_api) continue; |
| @@ -8487,12 +8510,15 @@ async function connectAPISlash(_, text) { | ||
| 8487 | 8510 | |
| 8488 | 8511 | return key; |
| 8489 | 8512 | } |
| 8513 | + | |
| 8514 | + console.error('FIXME: The current API is not in the API map'); | |
| 8515 | + return ''; | |
| 8490 | 8516 | } |
| 8491 | 8517 | |
| 8492 | 8518 | const apiConfig = CONNECT_API_MAP[text.toLowerCase()]; |
| 8493 | 8519 | if (!apiConfig) { |
| 8494 | 8520 | toastr.error(`Error: ${text} is not a valid API`); |
| 8495 | 8521 | return ''; |
| 8496 | 8522 | } |
| 8497 | 8523 | |
| 8498 | 8524 | $(`#main_api option[value='${apiConfig.selected || text}']`).prop('selected', true); |
| @@ -8512,14 +8538,18 @@ async function connectAPISlash(_, text) { | ||
| 8512 | 8538 | $(apiConfig.button).trigger('click'); |
| 8513 | 8539 | } |
| 8514 | 8540 | |
| 8515 | - toastr.info(`API set to ${text}, trying to connect..`); | |
| 8541 | + const quiet = isTrueBoolean(args?.quiet); | |
| 8542 | + const toast = quiet ? jQuery() : toastr.info(`API set to ${text}, trying to connect..`); | |
| 8516 | 8543 | |
| 8517 | 8544 | try { |
| 8518 | 8545 | await waitUntilCondition(() => online_status !== 'no_connection', 10000, 100); |
| 8519 | 8546 | console.log('Connection successful'); |
| 8520 | 8547 | } catch { |
| 8521 | 8548 | console.log('Could not connect after 510 seconds, skipping.'); |
| 8522 | 8549 | } |
| 8550 | + | |
| 8551 | + toastr.clear(toast); | |
| 8552 | + return text; | |
| 8523 | 8553 | } |
| 8524 | 8554 | |
| 8525 | 8555 | /** |
| @@ -8814,16 +8844,21 @@ export async function handleDeleteCharacter(this_chid, delete_chats) { | ||
| 8814 | 8844 | /** |
| 8815 | 8845 | * Deletes a character completely, including associated chats if specified |
| 8816 | 8846 | * |
| 8817 | 8847 | * @param {string|string[]} characterKey - The key (avatar) of the character to be deleted |
| 8818 | 8848 | * @param {Object} [options] - Optional parameters for the deletion |
| 8819 | 8849 | * @param {boolean} [options.deleteChats=true] - Whether to delete associated chats or not |
| 8820 | 8850 | * @return {Promise<void>} - A promise that resolves when the character is successfully deleted |
| 8821 | 8851 | */ |
| 8822 | 8852 | export async function deleteCharacter(characterKey, { deleteChats = true } = {}) { |
| 8823 | - const character = characters.find(x => x.avatar == characterKey); | |
| 8853 | + if (!Array.isArray(characterKey)) { | |
| 8854 | + characterKey = [characterKey]; | |
| 8855 | + } | |
| 8856 | + | |
| 8857 | + for (const key of characterKey) { | |
| 8858 | + const character = characters.find(x => x.avatar == key); | |
| 8824 | 8859 | if (!character) { |
| 8825 | 8860 | toastr.warning(`Character ${characterKeykey} not found. Cannot beSkipping deleteddeletion.`); |
| 8826 | - return; | |
| 8861 | + continue; | |
| 8827 | 8862 | } |
| 8828 | 8863 | |
| 8829 | 8864 | const chid = characters.indexOf(character); |
| @@ -8839,10 +8874,12 @@ export async function deleteCharacter(characterKey, { deleteChats = true } = {}) | ||
| 8839 | 8874 | }); |
| 8840 | 8875 | |
| 8841 | 8876 | if (!response.ok) { |
| 8842 | 8877 | throw new Error toastr.error(`Failed to delete character: ${response.status} ${response.statusText}`, 'Failed to delete character'); |
| 8878 | + continue; | |
| 8843 | 8879 | } |
| 8844 | 8880 | |
| 8845 | - await removeCharacterFromUI(character.name, character.avatar); | |
| 8881 | + delete tag_map[character.avatar]; | |
| 8882 | + select_rm_info('char_delete', character.name); | |
| 8846 | 8883 | |
| 8847 | 8884 | if (deleteChats) { |
| 8848 | 8885 | for (const chat of pastChats) { |
| @@ -8851,35 +8888,30 @@ export async function deleteCharacter(characterKey, { deleteChats = true } = {}) | ||
| 8851 | 8888 | } |
| 8852 | 8889 | } |
| 8853 | 8890 | |
| 8854 | 8891 | await eventSource.emit(event_types.CHARACTER_DELETED, { id: this_chidchid, character: characters[this_chid]character }); |
| 8892 | + } | |
| 8893 | + | |
| 8894 | + await removeCharacterFromUI(); | |
| 8855 | 8895 | } |
| 8856 | 8896 | |
| 8857 | 8897 | /** |
| 8858 | 8898 | * Function to delete a character from UI after character deletion API success. |
| 8859 | 8899 | * It manages necessary UI changes such as closing advanced editing popup, unsetting |
| 8860 | 8900 | * character ID, resetting characters array and chat metadata, deselecting character's tab |
| 8861 | 8901 | * panel, removing character name from navigation tabs, clearing chat, removingfetching character'supdated list of characters. |
| 8862 | - * avatar from tag_map, fetching updated list of characters and updating the 'deleted | |
| 8863 | - * character' message. | |
| 8864 | 8902 | * It also ensures to save the settings after all the operations. |
| 8865 | - * | |
| 8866 | - * @param {string} name - The name of the character to be deleted. | |
| 8867 | - * @param {string} avatar - The avatar URL of the character to be deleted. | |
| 8868 | - * @param {boolean} reloadCharacters - Whether the character list should be refreshed after deletion. | |
| 8869 | 8903 | */ |
| 8870 | 8904 | async function removeCharacterFromUI(name, avatar, reloadCharacters = true) { |
| 8871 | 8905 | await clearChat(); |
| 8872 | 8906 | $('#character_cross').click(); |
| 8873 | 8907 | this_chid = undefined; |
| 8874 | 8908 | characters.length = 0; |
| 8875 | 8909 | name2 = systemUserName; |
| 8876 | 8910 | chat.splice(0, =chat.length, [...safetychat]SAFETY_CHAT); |
| 8877 | 8911 | chat_metadata = {}; |
| 8878 | 8912 | $(document.getElementById('rm_button_selected_ch')).children('h2').text(''); |
| 8879 | 8913 | this_chid = undefined; |
| 8880 | - delete tag_map[avatar]; | |
| 8914 | + await getCharacters(); | |
| 8881 | - if (reloadCharacters) await getCharacters(); | |
| 8882 | - select_rm_info('char_delete', name); | |
| 8883 | 8915 | await printMessages(); |
| 8884 | 8916 | saveSettingsDebounced(); |
| 8885 | 8917 | } |
| @@ -8978,6 +9010,15 @@ jQuery(async function () { | ||
| 8978 | 9010 | name: 'api', |
| 8979 | 9011 | callback: connectAPISlash, |
| 8980 | 9012 | returns: 'the current API', |
| 9013 | + namedArgumentList: [ | |
| 9014 | + SlashCommandNamedArgument.fromProps({ | |
| 9015 | + name: 'quiet', | |
| 9016 | + description: 'Suppress the toast message on connection', | |
| 9017 | + typeList: [ARGUMENT_TYPE.BOOLEAN], | |
| 9018 | + defaultValue: 'false', | |
| 9019 | + enumList: commonEnumProviders.boolean('trueFalse')(), | |
| 9020 | + }), | |
| 9021 | + ], | |
| 8981 | 9022 | unnamedArgumentList: [ |
| 8982 | 9023 | SlashCommandArgument.fromProps({ |
| 8983 | 9024 | description: 'API to connect to', |
| @@ -9497,11 +9538,7 @@ jQuery(async function () { | ||
| 9497 | 9538 | const oldFileNameFull = $(this).closest('.select_chat_block_wrapper').find('.select_chat_block_filename').text(); |
| 9498 | 9539 | const oldFileName = oldFileNameFull.replace('.jsonl', ''); |
| 9499 | 9540 | |
| 9500 | - const popupText = `<h3>Enter the new name for the chat:<h3> | |
| 9541 | + const popupText = await renderTemplateAsync('chatRename'); | |
| 9501 | - <small>!!Using an existing filename will produce an error!!<br> | |
| 9502 | - This will break the link between checkpoint chats.<br> | |
| 9503 | - No need to add '.jsonl' at the end.<br> | |
| 9504 | - </small>`; | |
| 9505 | 9542 | const newName = await callPopup(popupText, 'input', oldFileName); |
| 9506 | 9543 | |
| 9507 | 9544 | if (!newName || newName == oldFileName) { |
| @@ -9709,12 +9746,7 @@ jQuery(async function () { | ||
| 9709 | 9746 | else if (id == 'option_start_new_chat') { |
| 9710 | 9747 | if ((selected_group || this_chid !== undefined) && !is_send_press) { |
| 9711 | 9748 | let deleteCurrentChat = false; |
| 9712 | 9749 | const result = await Popup.show.confirm('t`Start new chat?`, await renderTemplateAsync('newChatConfirm'), `{ |
| 9713 | - <label for="del_chat_checkbox" class="checkbox_label justifyCenter" | |
| 9714 | - title="If necessary, you can later restore this chat file from the /backups folder"> | |
| 9715 | - <input type="checkbox" id="del_chat_checkbox" /> | |
| 9716 | - <small>Also delete the current chat file</small> | |
| 9717 | - </label>`, { | |
| 9718 | 9750 | onClose: () => deleteCurrentChat = !!$('#del_chat_checkbox').prop('checked'), |
| 9719 | 9751 | }); |
| 9720 | 9752 | if (!result) { |
| @@ -10226,10 +10258,10 @@ jQuery(async function () { | ||
| 10226 | 10258 | |
| 10227 | 10259 | let deleteOnlySwipe = false; |
| 10228 | 10260 | if (power_user.confirm_message_delete && fromSlashCommand !== true) { |
| 10229 | 10261 | const result = await callGenericPopup('t`Are you sure you want to delete this message?'`, POPUP_TYPE.CONFIRM, null, { |
| 10230 | 10262 | okButton: canDeleteSwipe ? 't`Delete Swipe'` : 't`Delete Message'`, |
| 10231 | 10263 | cancelButton: 'Cancel', |
| 10232 | 10264 | customButtons: canDeleteSwipe ? ['t`Delete Message'`] : null, |
| 10233 | 10265 | }); |
| 10234 | 10266 | if (!result) { |
| 10235 | 10267 | return; |
| @@ -108,14 +108,12 @@ class CharacterContextMenu { | ||
| 108 | 108 | * Delete one or more characters, |
| 109 | 109 | * opens a popup. |
| 110 | 110 | * |
| 111 | 111 | * @param {numberstring|string[]} characterIdcharacterKey |
| 112 | 112 | * @param {boolean} [deleteChats] |
| 113 | 113 | * @returns {Promise<void>} |
| 114 | 114 | */ |
| 115 | 115 | static delete = async (characterIdcharacterKey, deleteChats = false) => { |
| 116 | - const character = CharacterContextMenu.#getCharacter(characterId); | |
| 116 | + await deleteCharacter(characterKey, { deleteChats: deleteChats }); | |
| 117 | - | |
| 118 | - await deleteCharacter(character.avatar, { deleteChats: deleteChats }); | |
| 119 | 117 | }; |
| 120 | 118 | |
| 121 | 119 | static #getCharacter = (characterId) => characters[characterId] ?? null; |
| @@ -599,8 +597,7 @@ class BulkEditOverlay { | ||
| 599 | 597 | |
| 600 | 598 | this.container.removeEventListener('mouseup', cancelHold); |
| 601 | 599 | this.container.removeEventListener('touchend', cancelHold); |
| 602 | 600 | }, BulkEditOverlay.longPressDelay); |
| 603 | - BulkEditOverlay.longPressDelay); | |
| 604 | 601 | }; |
| 605 | 602 | |
| 606 | 603 | handleLongPressEnd = (event) => { |
| @@ -847,11 +844,14 @@ class BulkEditOverlay { | ||
| 847 | 844 | const deleteChats = document.getElementById('del_char_checkbox').checked ?? false; |
| 848 | 845 | |
| 849 | 846 | showLoader(); |
| 850 | 847 | const toast = toastr.info('We\'re deleting your characters, please wait...', 'Working on it'); |
| 851 | - return Promise.allSettled(characterIds.map(async characterId => CharacterContextMenu.delete(characterId, deleteChats))) | |
| 848 | + const avatarList = characterIds.map(id => characters[id]?.avatar).filter(a => a); | |
| 852 | - .then(() => getCharacters()) | |
| 849 | + return CharacterContextMenu.delete(avatarList, deleteChats) | |
| 853 | 850 | .then(() => this.browseState()) |
| 854 | 851 | .finally(() => hideLoader());{ |
| 852 | + toastr.clear(toast); | |
| 853 | + hideLoader(); | |
| 854 | + }); | |
| 855 | 855 | }); |
| 856 | 856 | |
| 857 | 857 | // At this moment the popup is already changed in the dom, but not yet closed/resolved. We build the avatar list here |
| @@ -21,6 +21,7 @@ const defaultUrl = 'http://localhost:5100'; | ||
| 21 | 21 | let saveMetadataTimeout = null; |
| 22 | 22 | |
| 23 | 23 | let requiresReload = false; |
| 24 | +let stateChanged = false; | |
| 24 | 25 | |
| 25 | 26 | export function saveMetadataDebounced() { |
| 26 | 27 | const context = getContext(); |
| @@ -238,6 +239,7 @@ function onEnableExtensionClick() { | ||
| 238 | 239 | |
| 239 | 240 | async function enableExtension(name, reload = true) { |
| 240 | 241 | extension_settings.disabledExtensions = extension_settings.disabledExtensions.filter(x => x !== name); |
| 242 | + stateChanged = true; | |
| 241 | 243 | await saveSettings(); |
| 242 | 244 | if (reload) { |
| 243 | 245 | location.reload(); |
| @@ -248,6 +250,7 @@ async function enableExtension(name, reload = true) { | ||
| 248 | 250 | |
| 249 | 251 | async function disableExtension(name, reload = true) { |
| 250 | 252 | extension_settings.disabledExtensions.push(name); |
| 253 | + stateChanged = true; | |
| 251 | 254 | await saveSettings(); |
| 252 | 255 | if (reload) { |
| 253 | 256 | location.reload(); |
| @@ -304,7 +307,7 @@ async function activateExtensions() { | ||
| 304 | 307 | |
| 305 | 308 | if (!isDisabled) { |
| 306 | 309 | const promise = Promise.all([addExtensionScript(name, manifest), addExtensionStyle(name, manifest)]); |
| 307 | 310 | await promise |
| 308 | 311 | .then(() => activeExtensions.add(name)) |
| 309 | 312 | .catch(err => console.log('Could not activate extension: ' + name, err)); |
| 310 | 313 | promises.push(promise); |
| @@ -657,7 +660,29 @@ async function showExtensionsDetails() { | ||
| 657 | 660 | await oldPopup.complete(POPUP_RESULT.CANCELLED); |
| 658 | 661 | } |
| 659 | 662 | |
| 660 | - const popup = new Popup(html, POPUP_TYPE.TEXT, '', { okButton: 'Close', wide: true, large: true, customButtons: [updateAllButton], allowVerticalScrolling: true }); | |
| 663 | + let waitingForSave = false; | |
| 664 | + | |
| 665 | + const popup = new Popup(html, POPUP_TYPE.TEXT, '', { | |
| 666 | + okButton: 'Close', | |
| 667 | + wide: true, | |
| 668 | + large: true, | |
| 669 | + customButtons: [updateAllButton], | |
| 670 | + allowVerticalScrolling: true, | |
| 671 | + onClosing: async () => { | |
| 672 | + if (waitingForSave) { | |
| 673 | + return false; | |
| 674 | + } | |
| 675 | + if (stateChanged) { | |
| 676 | + waitingForSave = true; | |
| 677 | + const toast = toastr.info('The page will be reloaded shortly...', 'Extensions state changed'); | |
| 678 | + await saveSettings(); | |
| 679 | + toastr.clear(toast); | |
| 680 | + waitingForSave = false; | |
| 681 | + requiresReload = true; | |
| 682 | + } | |
| 683 | + return true; | |
| 684 | + }, | |
| 685 | + }); | |
| 661 | 686 | popupPromise = popup.show(); |
| 662 | 687 | } catch (error) { |
| 663 | 688 | toastr.error('Error loading extensions. See browser console for details.'); |
| @@ -797,16 +822,17 @@ export async function installExtension(url) { | ||
| 797 | 822 | const response = await request.json(); |
| 798 | 823 | toastr.success(`Extension "${response.display_name}" by ${response.author} (version ${response.version}) has been installed successfully!`, 'Extension installation successful'); |
| 799 | 824 | console.debug(`Extension "${response.display_name}" has been installed successfully at ${response.extensionPath}`); |
| 800 | 825 | await loadExtensionSettings({}, false, false); |
| 801 | 826 | await eventSource.emit(event_types.EXTENSION_SETTINGS_LOADED); |
| 802 | 827 | } |
| 803 | 828 | |
| 804 | 829 | /** |
| 805 | 830 | * Loads extension settings from the app settings. |
| 806 | 831 | * @param {object} settings App Settings |
| 807 | 832 | * @param {boolean} versionChanged Is this a version change? |
| 833 | + * @param {boolean} enableAutoUpdate Enable auto-update | |
| 808 | 834 | */ |
| 809 | 835 | async function loadExtensionSettings(settings, versionChanged, enableAutoUpdate) { |
| 810 | 836 | if (settings.extension_settings) { |
| 811 | 837 | Object.assign(extension_settings, settings.extension_settings); |
| 812 | 838 | } |
| @@ -817,11 +843,11 @@ async function loadExtensionSettings(settings, versionChanged) { | ||
| 817 | 843 | $('#extensions_notify_updates').prop('checked', extension_settings.notifyUpdates); |
| 818 | 844 | |
| 819 | 845 | // Activate offline extensions |
| 820 | 846 | await eventSource.emit(event_types.EXTENSIONS_FIRST_LOAD); |
| 821 | 847 | extensionNames = await discoverExtensions(); |
| 822 | 848 | manifests = await getManifests(extensionNames); |
| 823 | 849 | |
| 824 | 850 | if (versionChanged && enableAutoUpdate) { |
| 825 | 851 | await autoUpdateExtensions(false); |
| 826 | 852 | } |
| 827 | 853 | |
| @@ -20,7 +20,7 @@ | ||
| 20 | 20 | <option value="zerooneai">01.AI (Yi)</option> |
| 21 | 21 | <option value="anthropic">Anthropic</option> |
| 22 | 22 | <option value="custom" data-i18n="Custom (OpenAI-compatible)">Custom (OpenAI-compatible)</option> |
| 23 | 23 | <option value="google">Google MakerSuiteAI Studio</option> |
| 24 | 24 | <option value="koboldcpp">KoboldCpp</option> |
| 25 | 25 | <option value="llamacpp">llama.cpp</option> |
| 26 | 26 | <option value="ollama">Ollama</option> |
| @@ -45,8 +45,11 @@ | ||
| 45 | 45 | <option data-type="anthropic" value="claude-3-haiku-20240307">claude-3-haiku-20240307</option> |
| 46 | 46 | <option data-type="google" value="gemini-pro-vision">gemini-pro-vision</option> |
| 47 | 47 | <option data-type="google" value="gemini-1.5-flash-latest">gemini-1.5-flash-latest</option> |
| 48 | + <option data-type="google" value="gemini-1.5-flash-exp-0827">gemini-1.5-flash-exp-0827</option> | |
| 49 | + <option data-type="google" value="gemini-1.5-flash-8b-exp-0827">gemini-1.5-flash-8b-exp-0827</option> | |
| 48 | 50 | <option data-type="google" value="gemini-1.5-pro-latest">gemini-1.5-pro-latest</option> |
| 49 | 51 | <option data-type="google" value="gemini-1.5-pro-exp-0801">gemini-1.5-pro-exp-0801</option> |
| 52 | + <option data-type="google" value="gemini-1.5-pro-exp-0827">gemini-1.5-pro-exp-0827</option> | |
| 50 | 53 | <option data-type="openrouter" value="openai/gpt-4-vision-preview">openai/gpt-4-vision-preview</option> |
| 51 | 54 | <option data-type="openrouter" value="openai/gpt-4o">openai/gpt-4o</option> |
| 52 | 55 | <option data-type="openrouter" value="openai/gpt-4-turbo">openai/gpt-4-turbo</option> |
| @@ -1,4 +1,4 @@ | ||
| 1 | 1 | import { getStringHash, debounce, waitUntilCondition, extractAllWords, isTrueBoolean } from '../../utils.js'; |
| 2 | 2 | import { getContext, getApiUrl, extension_settings, doExtrasFetch, modules, renderExtensionTemplateAsync } from '../../extensions.js'; |
| 3 | 3 | import { |
| 4 | 4 | activateSendButtons, |
| @@ -26,6 +26,7 @@ import { SlashCommand } from '../../slash-commands/SlashCommand.js'; | ||
| 26 | 26 | import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js'; |
| 27 | 27 | import { MacrosParser } from '../../macros.js'; |
| 28 | 28 | import { countWebLlmTokens, generateWebLlmChatPrompt, getWebLlmContextSize, isWebLlmSupported } from '../shared.js'; |
| 29 | +import { commonEnumProviders } from '../../slash-commands/SlashCommandCommonEnumsProvider.js'; | |
| 29 | 30 | export { MODULE_NAME }; |
| 30 | 31 | |
| 31 | 32 | const MODULE_NAME = '1_memory'; |
| @@ -456,7 +457,12 @@ async function onChatEvent() { | ||
| 456 | 457 | } |
| 457 | 458 | } |
| 458 | 459 | |
| 459 | -async function forceSummarizeChat() { | |
| 460 | +/** | |
| 461 | + * Forces a summary generation for the current chat. | |
| 462 | + * @param {boolean} quiet If an informational toast should be displayed | |
| 463 | + * @returns {Promise<string>} Summarized text | |
| 464 | + */ | |
| 465 | +async function forceSummarizeChat(quiet) { | |
| 460 | 466 | if (extension_settings.memory.source === summary_sources.extras) { |
| 461 | 467 | toastr.warning('Force summarization is not supported for Extras API'); |
| 462 | 468 | return; |
| @@ -471,7 +477,7 @@ async function forceSummarizeChat() { | ||
| 471 | 477 | return ''; |
| 472 | 478 | } |
| 473 | 479 | |
| 474 | 480 | const toast = quiet ? jQuery() : toastr.info('Summarizing chat...', 'Please wait', { timeOut: 0, extendedTimeOut: 0 }); |
| 475 | 481 | const value = extension_settings.memory.source === summary_sources.main |
| 476 | 482 | ? await summarizeChatMain(context, true, skipWIAN) |
| 477 | 483 | : await summarizeChatWebLLM(context, true); |
| @@ -494,9 +500,10 @@ async function forceSummarizeChat() { | ||
| 494 | 500 | async function summarizeCallback(args, text) { |
| 495 | 501 | text = text.trim(); |
| 496 | 502 | |
| 497 | 503 | // Using forceSummarizeChat to summarizeSummarize the current chat if no text provided |
| 498 | 504 | if (!text) { |
| 499 | 505 | returnconst awaitquiet forceSummarizeChat= isTrueBoolean(args.quiet); |
| 506 | + return await forceSummarizeChat(quiet); | |
| 500 | 507 | } |
| 501 | 508 | |
| 502 | 509 | const source = args.source || extension_settings.memory.source; |
| @@ -1005,7 +1012,7 @@ function setupListeners() { | ||
| 1005 | 1012 | $('#memory_prompt_words').off('click').on('input', onMemoryPromptWordsInput); |
| 1006 | 1013 | $('#memory_prompt_interval').off('click').on('input', onMemoryPromptIntervalInput); |
| 1007 | 1014 | $('#memory_prompt').off('click').on('input', onMemoryPromptInput); |
| 1008 | 1015 | $('#memory_force_summarize').off('click').on('click', () => forceSummarizeChat(false)); |
| 1009 | 1016 | $('#memory_template').off('click').on('input', onMemoryTemplateInput); |
| 1010 | 1017 | $('#memory_depth').off('click').on('input', onMemoryDepthInput); |
| 1011 | 1018 | $('#memory_role').off('click').on('input', onMemoryRoleInput); |
| @@ -1055,6 +1062,13 @@ jQuery(async function () { | ||
| 1055 | 1062 | typeList: [ARGUMENT_TYPE.STRING], |
| 1056 | 1063 | defaultValue: '', |
| 1057 | 1064 | }), |
| 1065 | + SlashCommandNamedArgument.fromProps({ | |
| 1066 | + name: 'quiet', | |
| 1067 | + description: 'suppress the toast message when summarizing the chat', | |
| 1068 | + typeList: [ARGUMENT_TYPE.BOOLEAN], | |
| 1069 | + defaultValue: 'false', | |
| 1070 | + enumList: commonEnumProviders.boolean('trueFalse')(), | |
| 1071 | + }), | |
| 1058 | 1072 | ], |
| 1059 | 1073 | unnamedArgumentList: [ |
| 1060 | 1074 | new SlashCommandArgument('text to summarize', [ARGUMENT_TYPE.STRING], false, false, ''), |
| @@ -11,6 +11,9 @@ | ||
| 11 | 11 | <label class="flex-container"> |
| 12 | 12 | <input type="checkbox" id="qr--isCombined"><span data-i18n="Combine Quick Replies">Combine Quick Replies</span> |
| 13 | 13 | </label> |
| 14 | + <label class="flex-container"> | |
| 15 | + <input type="checkbox" id="qr--showPopoutButton"><span data-i18n="Show Popout Button">Show Popout Button</span> | |
| 16 | + </label> | |
| 14 | 17 | |
| 15 | 18 | <hr> |
| 16 | 19 | |
| @@ -16,6 +16,7 @@ export class QuickReplySettings { | ||
| 16 | 16 | /**@type {Boolean}*/ isEnabled = false; |
| 17 | 17 | /**@type {Boolean}*/ isCombined = false; |
| 18 | 18 | /**@type {Boolean}*/ isPopout = false; |
| 19 | + /**@type {Boolean}*/ showPopoutButton = true; | |
| 19 | 20 | /**@type {QuickReplyConfig}*/ config; |
| 20 | 21 | /**@type {QuickReplyConfig}*/ _chatConfig; |
| 21 | 22 | get chatConfig() { |
| @@ -79,6 +80,7 @@ export class QuickReplySettings { | ||
| 79 | 80 | isEnabled: this.isEnabled, |
| 80 | 81 | isCombined: this.isCombined, |
| 81 | 82 | isPopout: this.isPopout, |
| 83 | + showPopoutButton: this.showPopoutButton, | |
| 82 | 84 | config: this.config, |
| 83 | 85 | }; |
| 84 | 86 | } |
| @@ -69,6 +69,8 @@ export class ButtonUi { | ||
| 69 | 69 | root.id = 'qr--bar'; |
| 70 | 70 | root.classList.add('flex-container'); |
| 71 | 71 | root.classList.add('flexGap5'); |
| 72 | + if (this.settings.showPopoutButton) { | |
| 73 | + root.classList.add('popoutVisible'); | |
| 72 | 74 | const popout = document.createElement('div'); { |
| 73 | 75 | popout.id = 'qr--popoutTrigger'; |
| 74 | 76 | popout.classList.add('menu_button'); |
| @@ -81,6 +83,7 @@ export class ButtonUi { | ||
| 81 | 83 | }); |
| 82 | 84 | root.append(popout); |
| 83 | 85 | } |
| 86 | + } | |
| 84 | 87 | if (this.settings.isCombined) { |
| 85 | 88 | const buttons = document.createElement('div'); { |
| 86 | 89 | buttonHolder = buttons; |
| @@ -14,6 +14,7 @@ export class SettingsUi { | ||
| 14 | 14 | |
| 15 | 15 | /**@type {HTMLInputElement}*/ isEnabled; |
| 16 | 16 | /**@type {HTMLInputElement}*/ isCombined; |
| 17 | + /**@type {HTMLInputElement}*/ showPopoutButton; | |
| 17 | 18 | |
| 18 | 19 | /**@type {HTMLElement}*/ globalSetList; |
| 19 | 20 | |
| @@ -79,6 +80,10 @@ export class SettingsUi { | ||
| 79 | 80 | this.isCombined = this.dom.querySelector('#qr--isCombined'); |
| 80 | 81 | this.isCombined.checked = this.settings.isCombined; |
| 81 | 82 | this.isCombined.addEventListener('click', ()=>this.onIsCombined()); |
| 83 | + | |
| 84 | + this.showPopoutButton = this.dom.querySelector('#qr--showPopoutButton'); | |
| 85 | + this.showPopoutButton.checked = this.settings.showPopoutButton; | |
| 86 | + this.showPopoutButton.addEventListener('click', ()=>this.onShowPopoutButton()); | |
| 82 | 87 | } |
| 83 | 88 | |
| 84 | 89 | prepareGlobalSetList() { |
| @@ -235,6 +240,11 @@ export class SettingsUi { | ||
| 235 | 240 | this.settings.save(); |
| 236 | 241 | } |
| 237 | 242 | |
| 243 | + async onShowPopoutButton() { | |
| 244 | + this.settings.showPopoutButton = this.showPopoutButton.checked; | |
| 245 | + this.settings.save(); | |
| 246 | + } | |
| 247 | + | |
| 238 | 248 | async onGlobalSetListSort() { |
| 239 | 249 | this.settings.config.setList = Array.from(this.globalSetList.children).map((it,idx)=>{ |
| 240 | 250 | const set = this.settings.config.setList[Number(it.getAttribute('data-order'))]; |
| @@ -27,7 +27,6 @@ | ||
| 27 | 27 | max-width: 100%; |
| 28 | 28 | overflow-x: auto; |
| 29 | 29 | order: 1; |
| 30 | - padding-right: 2.5em; | |
| 31 | 30 | position: relative; |
| 32 | 31 | } |
| 33 | 32 | #qr--bar > #qr--popoutTrigger { |
| @@ -35,6 +34,9 @@ | ||
| 35 | 34 | right: 0.25em; |
| 36 | 35 | top: 0; |
| 37 | 36 | } |
| 37 | +#qr--bar.popoutVisible { | |
| 38 | + padding-right: 2.5em; | |
| 39 | +} | |
| 38 | 40 | #qr--popout { |
| 39 | 41 | display: flex; |
| 40 | 42 | flex-direction: column; |
| @@ -25,7 +25,6 @@ | ||
| 25 | 25 | max-width: 100%; |
| 26 | 26 | overflow-x: auto; |
| 27 | 27 | order: 1; |
| 28 | - padding-right: 2.5em; | |
| 29 | 28 | position: relative; |
| 30 | 29 | |
| 31 | 30 | >#qr--popoutTrigger { |
| @@ -34,6 +33,9 @@ | ||
| 34 | 33 | top: 0; |
| 35 | 34 | } |
| 36 | 35 | } |
| 36 | +#qr--bar.popoutVisible { | |
| 37 | + padding-right: 2.5em; | |
| 38 | +} | |
| 37 | 39 | |
| 38 | 40 | #qr--popout { |
| 39 | 41 | display: flex; |
| @@ -141,7 +141,7 @@ function throwIfInvalidModel(useReverseProxy) { | ||
| 141 | 141 | } |
| 142 | 142 | |
| 143 | 143 | if (extension_settings.caption.multimodal_api === 'google' && !secret_state[SECRET_KEYS.MAKERSUITE] && !useReverseProxy) { |
| 144 | 144 | throw new Error('MakerSuiteGoogle AI Studio API key is not set.'); |
| 145 | 145 | } |
| 146 | 146 | |
| 147 | 147 | if (extension_settings.caption.multimodal_api === 'ollama' && !textgenerationwebui_settings.server_urls[textgen_types.OLLAMA]) { |
| @@ -52,6 +52,7 @@ const sources = { | ||
| 52 | 52 | pollinations: 'pollinations', |
| 53 | 53 | stability: 'stability', |
| 54 | 54 | blockentropy: 'blockentropy', |
| 55 | + huggingface: 'huggingface', | |
| 55 | 56 | }; |
| 56 | 57 | |
| 57 | 58 | const initiators = { |
| @@ -454,6 +455,7 @@ async function loadSettings() { | ||
| 454 | 455 | $('#sd_command_visible').prop('checked', extension_settings.sd.command_visible); |
| 455 | 456 | $('#sd_interactive_visible').prop('checked', extension_settings.sd.interactive_visible); |
| 456 | 457 | $('#sd_stability_style_preset').val(extension_settings.sd.stability_style_preset); |
| 458 | + $('#sd_huggingface_model_id').val(extension_settings.sd.huggingface_model_id); | |
| 457 | 459 | |
| 458 | 460 | for (const style of extension_settings.sd.styles) { |
| 459 | 461 | const option = document.createElement('option'); |
| @@ -1091,6 +1093,11 @@ function onComfyUrlInput() { | ||
| 1091 | 1093 | saveSettingsDebounced(); |
| 1092 | 1094 | } |
| 1093 | 1095 | |
| 1096 | +function onHFModelInput() { | |
| 1097 | + extension_settings.sd.huggingface_model_id = $('#sd_huggingface_model_id').val(); | |
| 1098 | + saveSettingsDebounced(); | |
| 1099 | +} | |
| 1100 | + | |
| 1094 | 1101 | function onComfyWorkflowChange() { |
| 1095 | 1102 | extension_settings.sd.comfy_workflow = $('#sd_comfy_workflow').find(':selected').val(); |
| 1096 | 1103 | saveSettingsDebounced(); |
| @@ -1235,7 +1242,16 @@ async function onModelChange() { | ||
| 1235 | 1242 | extension_settings.sd.model = $('#sd_model').find(':selected').val(); |
| 1236 | 1243 | saveSettingsDebounced(); |
| 1237 | 1244 | |
| 1238 | - const cloudSources = [sources.horde, sources.novel, sources.openai, sources.togetherai, sources.pollinations, sources.stability, sources.blockentropy]; | |
| 1245 | + const cloudSources = [ | |
| 1246 | + sources.horde, | |
| 1247 | + sources.novel, | |
| 1248 | + sources.openai, | |
| 1249 | + sources.togetherai, | |
| 1250 | + sources.pollinations, | |
| 1251 | + sources.stability, | |
| 1252 | + sources.blockentropy, | |
| 1253 | + sources.huggingface, | |
| 1254 | + ]; | |
| 1239 | 1255 | |
| 1240 | 1256 | if (cloudSources.includes(extension_settings.sd.source)) { |
| 1241 | 1257 | return; |
| @@ -1450,6 +1466,9 @@ async function loadSamplers() { | ||
| 1450 | 1466 | case sources.blockentropy: |
| 1451 | 1467 | samplers = ['N/A']; |
| 1452 | 1468 | break; |
| 1469 | + case sources.huggingface: | |
| 1470 | + samplers = ['N/A']; | |
| 1471 | + break; | |
| 1453 | 1472 | } |
| 1454 | 1473 | |
| 1455 | 1474 | for (const sampler of samplers) { |
| @@ -1639,6 +1658,9 @@ async function loadModels() { | ||
| 1639 | 1658 | case sources.blockentropy: |
| 1640 | 1659 | models = await loadBlockEntropyModels(); |
| 1641 | 1660 | break; |
| 1661 | + case sources.huggingface: | |
| 1662 | + models = [{ value: '', text: '<Enter Model ID above>' }]; | |
| 1663 | + break; | |
| 1642 | 1664 | } |
| 1643 | 1665 | |
| 1644 | 1666 | for (const model of models) { |
| @@ -1986,6 +2008,9 @@ async function loadSchedulers() { | ||
| 1986 | 2008 | case sources.blockentropy: |
| 1987 | 2009 | schedulers = ['N/A']; |
| 1988 | 2010 | break; |
| 2011 | + case sources.huggingface: | |
| 2012 | + schedulers = ['N/A']; | |
| 2013 | + break; | |
| 1989 | 2014 | } |
| 1990 | 2015 | |
| 1991 | 2016 | for (const scheduler of schedulers) { |
| @@ -2065,6 +2090,9 @@ async function loadVaes() { | ||
| 2065 | 2090 | case sources.blockentropy: |
| 2066 | 2091 | vaes = ['N/A']; |
| 2067 | 2092 | break; |
| 2093 | + case sources.huggingface: | |
| 2094 | + vaes = ['N/A']; | |
| 2095 | + break; | |
| 2068 | 2096 | } |
| 2069 | 2097 | |
| 2070 | 2098 | for (const vae of vaes) { |
| @@ -2596,6 +2624,9 @@ async function sendGenerationRequest(generationType, prompt, additionalNegativeP | ||
| 2596 | 2624 | case sources.blockentropy: |
| 2597 | 2625 | result = await generateBlockEntropyImage(prefixedPrompt, negativePrompt, signal); |
| 2598 | 2626 | break; |
| 2627 | + case sources.huggingface: | |
| 2628 | + result = await generateHuggingFaceImage(prefixedPrompt, signal); | |
| 2629 | + break; | |
| 2599 | 2630 | } |
| 2600 | 2631 | |
| 2601 | 2632 | if (!result.data) { |
| @@ -3229,6 +3260,34 @@ async function generateComfyImage(prompt, negativePrompt, signal) { | ||
| 3229 | 3260 | return { format: 'png', data: await promptResult.text() }; |
| 3230 | 3261 | } |
| 3231 | 3262 | |
| 3263 | + | |
| 3264 | +/** | |
| 3265 | + * Generates an image in Hugging Face Inference API using the provided prompt and configuration settings (model selected). | |
| 3266 | + * @param {string} prompt - The main instruction used to guide the image generation. | |
| 3267 | + * @param {AbortSignal} signal - An AbortSignal object that can be used to cancel the request. | |
| 3268 | + * @returns {Promise<{format: string, data: string}>} - A promise that resolves when the image generation and processing are complete. | |
| 3269 | + */ | |
| 3270 | +async function generateHuggingFaceImage(prompt, signal) { | |
| 3271 | + const result = await fetch('/api/sd/huggingface/generate', { | |
| 3272 | + method: 'POST', | |
| 3273 | + headers: getRequestHeaders(), | |
| 3274 | + signal: signal, | |
| 3275 | + body: JSON.stringify({ | |
| 3276 | + model: extension_settings.sd.huggingface_model_id, | |
| 3277 | + prompt: prompt, | |
| 3278 | + }), | |
| 3279 | + }); | |
| 3280 | + | |
| 3281 | + if (result.ok) { | |
| 3282 | + const data = await result.json(); | |
| 3283 | + return { format: 'jpg', data: data.image }; | |
| 3284 | + } else { | |
| 3285 | + const text = await result.text(); | |
| 3286 | + throw new Error(text); | |
| 3287 | + } | |
| 3288 | +} | |
| 3289 | + | |
| 3290 | + | |
| 3232 | 3291 | async function onComfyOpenWorkflowEditorClick() { |
| 3233 | 3292 | let workflow = await (await fetch('/api/sd/comfy/workflow', { |
| 3234 | 3293 | method: 'POST', |
| @@ -3508,6 +3567,8 @@ function isValidState() { | ||
| 3508 | 3567 | return secret_state[SECRET_KEYS.STABILITY]; |
| 3509 | 3568 | case sources.blockentropy: |
| 3510 | 3569 | return secret_state[SECRET_KEYS.BLOCKENTROPY]; |
| 3570 | + case sources.huggingface: | |
| 3571 | + return secret_state[SECRET_KEYS.HUGGINGFACE]; | |
| 3511 | 3572 | } |
| 3512 | 3573 | } |
| 3513 | 3574 | |
| @@ -3848,6 +3909,7 @@ jQuery(async () => { | ||
| 3848 | 3909 | $('#sd_swap_dimensions').on('click', onSwapDimensionsClick); |
| 3849 | 3910 | $('#sd_stability_key').on('click', onStabilityKeyClick); |
| 3850 | 3911 | $('#sd_stability_style_preset').on('change', onStabilityStylePresetChange); |
| 3912 | + $('#sd_huggingface_model_id').on('input', onHFModelInput); | |
| 3851 | 3913 | |
| 3852 | 3914 | $('.sd_settings .inline-drawer-toggle').on('click', function () { |
| 3853 | 3915 | initScrollHeight($('#sd_prompt_prefix')); |
| @@ -29,7 +29,8 @@ | ||
| 29 | 29 | </label> |
| 30 | 30 | <label for="sd_expand" class="checkbox_label" data-i18n="[title]sd_expand" title="Automatically extend prompts using text generation model"> |
| 31 | 31 | <input id="sd_expand" type="checkbox" /> |
| 32 | 32 | <span data-i18n="sd_expand_txt">Auto-enhanceextend prompts</span> |
| 33 | + <span class="right_menu_button fa-solid fa-triangle-exclamation" data-i18n="[title]sd_expand_warning" title="May produce unexpected results. Manual prompt editing is recommended."></span> | |
| 33 | 34 | </label> |
| 34 | 35 | <label for="sd_snap" class="checkbox_label" data-i18n="[title]sd_snap" title="Snap generation requests with a forced aspect ratio (portraits, backgrounds) to the nearest known resolution, while trying to preserve the absolute pixel counts (recommended for SDXL)."> |
| 35 | 36 | <input id="sd_snap" type="checkbox" /> |
| @@ -41,6 +42,7 @@ | ||
| 41 | 42 | <option value="comfy">ComfyUI</option> |
| 42 | 43 | <option value="drawthings">DrawThings HTTP API</option> |
| 43 | 44 | <option value="extras">Extras API (local / remote)</option> |
| 45 | + <option value="huggingface">HuggingFace Inference API (serverless)</option> | |
| 44 | 46 | <option value="novel">NovelAI Diffusion</option> |
| 45 | 47 | <option value="openai">OpenAI (DALL-E)</option> |
| 46 | 48 | <option value="pollinations">Pollinations</option> |
| @@ -82,6 +84,11 @@ | ||
| 82 | 84 | <!-- (Original Text)<b>Important:</b> run DrawThings app with HTTP API switch enabled in the UI! The server must be accessible from the SillyTavern host machine. --> |
| 83 | 85 | <i><b data-i18n="Important:">Important:</b></i><i data-i18n="sd_drawthings_auth_txt"> run DrawThings app with HTTP API switch enabled in the UI! The server must be accessible from the SillyTavern host machine.</i> |
| 84 | 86 | </div> |
| 87 | + <div data-sd-source="huggingface"> | |
| 88 | + <i>Hint: Save an API key in the Hugging Face (Text Completion) API settings to use it here.</i> | |
| 89 | + <label for="sd_huggingface_model_id" data-i18n="Model ID">Model ID</label> | |
| 90 | + <input id="sd_huggingface_model_id" type="text" class="text_pole" data-i18n="[placeholder]e.g. black-forest-labs/FLUX.1-dev" placeholder="e.g. black-forest-labs/FLUX.1-dev" value="" /> | |
| 91 | + </div> | |
| 85 | 92 | <div data-sd-source="vlad"> |
| 86 | 93 | <label for="sd_vlad_url">SD.Next API URL</label> |
| 87 | 94 | <div class="flex-container flexnowrap"> |
| @@ -421,7 +421,7 @@ function completeTtsJob() { | ||
| 421 | 421 | async function tts(text, voiceId, char) { |
| 422 | 422 | async function processResponse(response) { |
| 423 | 423 | // RVC injection |
| 424 | 424 | if (extension_settings.rvc.enabled && typeof window['rvcVoiceConversion'] === 'function' && extension_settings.rvc.enabled) |
| 425 | 425 | response = await window['rvcVoiceConversion'](response, char, text); |
| 426 | 426 | |
| 427 | 427 | await addAudioJob(response, char); |
| @@ -755,6 +755,11 @@ async function onMessageEvent(messageId, lastCharIndex) { | ||
| 755 | 755 | const message = structuredClone(context.chat[messageId]); |
| 756 | 756 | const hashNew = getStringHash(message?.mes ?? ''); |
| 757 | 757 | |
| 758 | + // Ignore prompt-hidden messages | |
| 759 | + if (message.is_system) { | |
| 760 | + return; | |
| 761 | + } | |
| 762 | + | |
| 758 | 763 | // if no new messages, or same message, or same message hash, do nothing |
| 759 | 764 | if (hashNew === lastMessageHash) { |
| 760 | 765 | return; |
| @@ -12,7 +12,7 @@ | ||
| 12 | 12 | <select id="vectors_source" class="text_pole"> |
| 13 | 13 | <option value="cohere">Cohere</option> |
| 14 | 14 | <option value="extras">Extras</option> |
| 15 | 15 | <option value="palm">Google MakerSuiteAI Studio</option> |
| 16 | 16 | <option value="llamacpp">llama.cpp</option> |
| 17 | 17 | <option value="transformers" data-i18n="Local (Transformers)">Local (Transformers)</option> |
| 18 | 18 | <option value="mistral">MistralAI</option> |
| @@ -78,6 +78,19 @@ export function getKayraMaxContextTokens() { | ||
| 78 | 78 | return null; |
| 79 | 79 | } |
| 80 | 80 | |
| 81 | +export function getKayraMaxResponseTokens() { | |
| 82 | + switch (novel_data?.tier) { | |
| 83 | + case 1: | |
| 84 | + return 100; | |
| 85 | + case 2: | |
| 86 | + return 100; | |
| 87 | + case 3: | |
| 88 | + return 150; | |
| 89 | + } | |
| 90 | + | |
| 91 | + return maximum_output_length; | |
| 92 | +} | |
| 93 | + | |
| 81 | 94 | export function getNovelTier() { |
| 82 | 95 | return nai_tiers[novel_data?.tier] ?? 'no_connection'; |
| 83 | 96 | } |
| @@ -438,12 +451,14 @@ export function getNovelGenerationData(finalPrompt, settings, maxLength, isImper | ||
| 438 | 451 | console.log(finalPrompt); |
| 439 | 452 | } |
| 440 | 453 | |
| 454 | + const adjustedMaxLength = nai_settings.model_novel.includes('kayra') ? getKayraMaxResponseTokens() : maximum_output_length; | |
| 455 | + | |
| 441 | 456 | return { |
| 442 | 457 | 'input': finalPrompt, |
| 443 | 458 | 'model': nai_settings.model_novel, |
| 444 | 459 | 'use_string': true, |
| 445 | 460 | 'temperature': Number(nai_settings.temperature), |
| 446 | 461 | 'max_length': maxLength < maximum_output_lengthadjustedMaxLength ? maxLength : maximum_output_lengthadjustedMaxLength, |
| 447 | 462 | 'min_length': Number(nai_settings.min_length), |
| 448 | 463 | 'tail_free_sampling': Number(nai_settings.tail_free_sampling), |
| 449 | 464 | 'repetition_penalty': Number(nai_settings.repetition_penalty), |
| @@ -74,6 +74,7 @@ import { ARGUMENT_TYPE, SlashCommandArgument } from './slash-commands/SlashComma | ||
| 74 | 74 | import { renderTemplateAsync } from './templates.js'; |
| 75 | 75 | import { SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js'; |
| 76 | 76 | import { Popup, POPUP_RESULT } from './popup.js'; |
| 77 | +import { t } from './i18n.js'; | |
| 77 | 78 | |
| 78 | 79 | export { |
| 79 | 80 | openai_messages_count, |
| @@ -132,13 +133,9 @@ const max_2mil = 2000 * 1000; | ||
| 132 | 133 | const scale_max = 8191; |
| 133 | 134 | const claude_max = 9000; // We have a proper tokenizer, so theoretically could be larger (up to 9k) |
| 134 | 135 | const claude_100k_max = 99000; |
| 135 | -let ai21_max = 9200; //can easily fit 9k gpt tokens because j2's tokenizer is efficient af | |
| 136 | +const unlocked_max = max_2mil; | |
| 136 | -const unlocked_max = max_200k; | |
| 137 | 137 | const oai_max_temp = 2.0; |
| 138 | 138 | const claude_max_temp = 1.0; //same as j2 |
| 139 | -const j2_max_topk = 10.0; | |
| 140 | -const j2_max_freq = 5.0; | |
| 141 | -const j2_max_pres = 5.0; | |
| 142 | 139 | const openrouter_website_model = 'OR_Website'; |
| 143 | 140 | const openai_max_stop_strings = 4; |
| 144 | 141 | |
| @@ -218,25 +215,11 @@ const sensitiveFields = [ | ||
| 218 | 215 | 'custom_include_headers', |
| 219 | 216 | ]; |
| 220 | 217 | |
| 221 | -function getPrefixMap() { | |
| 222 | - return selected_group ? { | |
| 223 | - assistant: '', | |
| 224 | - user: '', | |
| 225 | - system: 'OOC: ', | |
| 226 | - } | |
| 227 | - : { | |
| 228 | - assistant: '{{char}}:', | |
| 229 | - user: '{{user}}:', | |
| 230 | - system: '', | |
| 231 | - }; | |
| 232 | -} | |
| 233 | - | |
| 234 | 218 | const default_settings = { |
| 235 | 219 | preset_settings_openai: 'Default', |
| 236 | 220 | temp_openai: 1.0, |
| 237 | 221 | freq_pen_openai: 0, |
| 238 | 222 | pres_pen_openai: 0, |
| 239 | - count_pen: 0.0, | |
| 240 | 223 | top_p_openai: 1.0, |
| 241 | 224 | top_k_openai: 0, |
| 242 | 225 | min_p_openai: 0, |
| @@ -264,7 +247,7 @@ const default_settings = { | ||
| 264 | 247 | openai_model: 'gpt-4-turbo', |
| 265 | 248 | claude_model: 'claude-3-5-sonnet-20240620', |
| 266 | 249 | google_model: 'gemini-1.5-pro', |
| 267 | 250 | ai21_model: 'j2jamba-ultra1.5-large', |
| 268 | 251 | mistralai_model: 'mistral-large-latest', |
| 269 | 252 | cohere_model: 'command-r-plus', |
| 270 | 253 | perplexity_model: 'llama-3.1-70b-instruct', |
| @@ -294,8 +277,6 @@ const default_settings = { | ||
| 294 | 277 | assistant_prefill: '', |
| 295 | 278 | assistant_impersonation: '', |
| 296 | 279 | human_sysprompt_message: default_claude_human_sysprompt_message, |
| 297 | - use_ai21_tokenizer: false, | |
| 298 | - use_google_tokenizer: false, | |
| 299 | 280 | claude_use_sysprompt: false, |
| 300 | 281 | use_makersuite_sysprompt: true, |
| 301 | 282 | use_alt_scale: false, |
| @@ -317,7 +298,6 @@ const oai_settings = { | ||
| 317 | 298 | temp_openai: 1.0, |
| 318 | 299 | freq_pen_openai: 0, |
| 319 | 300 | pres_pen_openai: 0, |
| 320 | - count_pen: 0.0, | |
| 321 | 301 | top_p_openai: 1.0, |
| 322 | 302 | top_k_openai: 0, |
| 323 | 303 | min_p_openai: 0, |
| @@ -345,7 +325,7 @@ const oai_settings = { | ||
| 345 | 325 | openai_model: 'gpt-4-turbo', |
| 346 | 326 | claude_model: 'claude-3-5-sonnet-20240620', |
| 347 | 327 | google_model: 'gemini-1.5-pro', |
| 348 | 328 | ai21_model: 'j2jamba-ultra1.5-large', |
| 349 | 329 | mistralai_model: 'mistral-large-latest', |
| 350 | 330 | cohere_model: 'command-r-plus', |
| 351 | 331 | perplexity_model: 'llama-3.1-70b-instruct', |
| @@ -375,8 +355,6 @@ const oai_settings = { | ||
| 375 | 355 | assistant_prefill: '', |
| 376 | 356 | assistant_impersonation: '', |
| 377 | 357 | human_sysprompt_message: default_claude_human_sysprompt_message, |
| 378 | - use_ai21_tokenizer: false, | |
| 379 | - use_google_tokenizer: false, | |
| 380 | 358 | claude_use_sysprompt: false, |
| 381 | 359 | use_makersuite_sysprompt: true, |
| 382 | 360 | use_alt_scale: false, |
| @@ -425,7 +403,7 @@ async function validateReverseProxy() { | ||
| 425 | 403 | const rememberKey = `Proxy_SkipConfirm_${getStringHash(oai_settings.reverse_proxy)}`; |
| 426 | 404 | const skipConfirm = localStorage.getItem(rememberKey) === 'true'; |
| 427 | 405 | |
| 428 | 406 | const confirmation = skipConfirm || await Popup.show.confirm('t`Connecting To Proxy', `<span>Are you sure you want to connect, toawait therenderTemplateAsync('proxyConnectionWarning', following{ proxyproxyURL: URL?</span><var>${DOMPurify.sanitize(oai_settings.reverse_proxy) }</var>`)); |
| 429 | 407 | |
| 430 | 408 | if (!confirmation) { |
| 431 | 409 | toastr.error('Update or remove your reverse proxy settings.'); |
| @@ -1148,7 +1126,6 @@ function preparePromptsForChatCompletion({ Scenario, charPersonality, name2, wor | ||
| 1148 | 1126 | { role: 'system', content: charDescription, identifier: 'charDescription' }, |
| 1149 | 1127 | { role: 'system', content: charPersonalityText, identifier: 'charPersonality' }, |
| 1150 | 1128 | { role: 'system', content: scenarioText, identifier: 'scenario' }, |
| 1151 | - { role: 'system', content: personaDescription, identifier: 'personaDescription' }, | |
| 1152 | 1129 | // Unordered prompts without marker |
| 1153 | 1130 | { role: 'system', content: impersonationPrompt, identifier: 'impersonate' }, |
| 1154 | 1131 | { role: 'system', content: quietPrompt, identifier: 'quietPrompt' }, |
| @@ -1395,6 +1372,11 @@ function tryParseStreamingError(response, decoded) { | ||
| 1395 | 1372 | toastr.error(data.error.message || response.statusText, 'Chat Completion API'); |
| 1396 | 1373 | throw new Error(data); |
| 1397 | 1374 | } |
| 1375 | + | |
| 1376 | + if (data.message) { | |
| 1377 | + toastr.error(data.message, 'Chat Completion API'); | |
| 1378 | + throw new Error(data); | |
| 1379 | + } | |
| 1398 | 1380 | } |
| 1399 | 1381 | catch { |
| 1400 | 1382 | // No JSON. Do nothing. |
| @@ -1802,7 +1784,6 @@ async function sendOpenAIRequest(type, messages, signal) { | ||
| 1802 | 1784 | const isClaude = oai_settings.chat_completion_source == chat_completion_sources.CLAUDE; |
| 1803 | 1785 | const isOpenRouter = oai_settings.chat_completion_source == chat_completion_sources.OPENROUTER; |
| 1804 | 1786 | const isScale = oai_settings.chat_completion_source == chat_completion_sources.SCALE; |
| 1805 | - const isAI21 = oai_settings.chat_completion_source == chat_completion_sources.AI21; | |
| 1806 | 1787 | const isGoogle = oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE; |
| 1807 | 1788 | const isOAI = oai_settings.chat_completion_source == chat_completion_sources.OPENAI; |
| 1808 | 1789 | const isMistral = oai_settings.chat_completion_source == chat_completion_sources.MISTRALAI; |
| @@ -1815,7 +1796,7 @@ async function sendOpenAIRequest(type, messages, signal) { | ||
| 1815 | 1796 | const isQuiet = type === 'quiet'; |
| 1816 | 1797 | const isImpersonate = type === 'impersonate'; |
| 1817 | 1798 | const isContinue = type === 'continue'; |
| 1818 | 1799 | const stream = oai_settings.stream_openai && !isQuiet && !isScale && !isAI21 && !(isGoogle && oai_settings.google_model.includes('bison')); |
| 1819 | 1800 | const useLogprobs = !!power_user.request_token_probabilities; |
| 1820 | 1801 | const canMultiSwipe = oai_settings.n > 1 && !isContinue && !isImpersonate && !isQuiet && (isOAI || isCustom); |
| 1821 | 1802 | |
| @@ -1824,15 +1805,6 @@ async function sendOpenAIRequest(type, messages, signal) { | ||
| 1824 | 1805 | replaceItemizedPromptText(messageId, messages); |
| 1825 | 1806 | } |
| 1826 | 1807 | |
| 1827 | - if (isAI21) { | |
| 1828 | - const joinedMsgs = messages.reduce((acc, obj) => { | |
| 1829 | - const prefix = getPrefixMap()[obj.role]; | |
| 1830 | - return acc + (prefix ? (selected_group ? '\n' : prefix + ' ') : '') + obj.content + '\n'; | |
| 1831 | - }, ''); | |
| 1832 | - messages = substituteParams(joinedMsgs) + (isImpersonate ? `${name1}:` : `${name2}:`); | |
| 1833 | - replaceItemizedPromptText(messageId, messages); | |
| 1834 | - } | |
| 1835 | - | |
| 1836 | 1808 | // If we're using the window.ai extension, use that instead |
| 1837 | 1809 | // Doesn't support logit bias yet |
| 1838 | 1810 | if (oai_settings.chat_completion_source == chat_completion_sources.WINDOWAI) { |
| @@ -1931,12 +1903,6 @@ async function sendOpenAIRequest(type, messages, signal) { | ||
| 1931 | 1903 | generate_data['use_makersuite_sysprompt'] = oai_settings.use_makersuite_sysprompt; |
| 1932 | 1904 | } |
| 1933 | 1905 | |
| 1934 | - if (isAI21) { | |
| 1935 | - generate_data['top_k'] = Number(oai_settings.top_k_openai); | |
| 1936 | - generate_data['count_pen'] = Number(oai_settings.count_pen); | |
| 1937 | - generate_data['stop_tokens'] = [name1 + ':', substituteParams(oai_settings.new_chat_prompt), substituteParams(oai_settings.new_group_chat_prompt)]; | |
| 1938 | - } | |
| 1939 | - | |
| 1940 | 1906 | if (isMistral) { |
| 1941 | 1907 | generate_data['safe_prompt'] = false; // already defaults to false, but just incase they change that in the future. |
| 1942 | 1908 | } |
| @@ -3008,7 +2974,6 @@ function loadOpenAISettings(data, settings) { | ||
| 3008 | 2974 | oai_settings.temp_openai = settings.temp_openai ?? default_settings.temp_openai; |
| 3009 | 2975 | oai_settings.freq_pen_openai = settings.freq_pen_openai ?? default_settings.freq_pen_openai; |
| 3010 | 2976 | oai_settings.pres_pen_openai = settings.pres_pen_openai ?? default_settings.pres_pen_openai; |
| 3011 | - oai_settings.count_pen = settings.count_pen ?? default_settings.count_pen; | |
| 3012 | 2977 | oai_settings.top_p_openai = settings.top_p_openai ?? default_settings.top_p_openai; |
| 3013 | 2978 | oai_settings.top_k_openai = settings.top_k_openai ?? default_settings.top_k_openai; |
| 3014 | 2979 | oai_settings.top_a_openai = settings.top_a_openai ?? default_settings.top_a_openai; |
| @@ -3080,10 +3045,12 @@ function loadOpenAISettings(data, settings) { | ||
| 3080 | 3045 | oai_settings.names_behavior = character_names_behavior.COMPLETION; |
| 3081 | 3046 | } |
| 3082 | 3047 | |
| 3048 | + if (oai_settings.ai21_model.startsWith('j2-')) { | |
| 3049 | + oai_settings.ai21_model = 'jamba-1.5-large'; | |
| 3050 | + } | |
| 3051 | + | |
| 3083 | 3052 | if (settings.wrap_in_quotes !== undefined) oai_settings.wrap_in_quotes = !!settings.wrap_in_quotes; |
| 3084 | 3053 | if (settings.openai_model !== undefined) oai_settings.openai_model = settings.openai_model; |
| 3085 | - if (settings.use_ai21_tokenizer !== undefined) { oai_settings.use_ai21_tokenizer = !!settings.use_ai21_tokenizer; oai_settings.use_ai21_tokenizer ? ai21_max = 8191 : ai21_max = 9200; } | |
| 3086 | - if (settings.use_google_tokenizer !== undefined) oai_settings.use_google_tokenizer = !!settings.use_google_tokenizer; | |
| 3087 | 3054 | if (settings.claude_use_sysprompt !== undefined) oai_settings.claude_use_sysprompt = !!settings.claude_use_sysprompt; |
| 3088 | 3055 | if (settings.use_makersuite_sysprompt !== undefined) oai_settings.use_makersuite_sysprompt = !!settings.use_makersuite_sysprompt; |
| 3089 | 3056 | if (settings.use_alt_scale !== undefined) { oai_settings.use_alt_scale = !!settings.use_alt_scale; updateScaleForm(); } |
| @@ -3133,8 +3100,6 @@ function loadOpenAISettings(data, settings) { | ||
| 3133 | 3100 | $('#jailbreak_system').prop('checked', oai_settings.jailbreak_system); |
| 3134 | 3101 | $('#openai_show_external_models').prop('checked', oai_settings.show_external_models); |
| 3135 | 3102 | $('#openai_external_category').toggle(oai_settings.show_external_models); |
| 3136 | - $('#use_ai21_tokenizer').prop('checked', oai_settings.use_ai21_tokenizer); | |
| 3137 | - $('#use_google_tokenizer').prop('checked', oai_settings.use_google_tokenizer); | |
| 3138 | 3103 | $('#claude_use_sysprompt').prop('checked', oai_settings.claude_use_sysprompt); |
| 3139 | 3104 | $('#use_makersuite_sysprompt').prop('checked', oai_settings.use_makersuite_sysprompt); |
| 3140 | 3105 | $('#scale-alt').prop('checked', oai_settings.use_alt_scale); |
| @@ -3170,9 +3135,6 @@ function loadOpenAISettings(data, settings) { | ||
| 3170 | 3135 | $('#pres_pen_openai').val(oai_settings.pres_pen_openai); |
| 3171 | 3136 | $('#pres_pen_counter_openai').val(Number(oai_settings.pres_pen_openai).toFixed(2)); |
| 3172 | 3137 | |
| 3173 | - $('#count_pen').val(oai_settings.count_pen); | |
| 3174 | - $('#count_pen_counter').val(Number(oai_settings.count_pen).toFixed(2)); | |
| 3175 | - | |
| 3176 | 3138 | $('#top_p_openai').val(oai_settings.top_p_openai); |
| 3177 | 3139 | $('#top_p_counter_openai').val(Number(oai_settings.top_p_openai).toFixed(2)); |
| 3178 | 3140 | |
| @@ -3392,7 +3354,6 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) { | ||
| 3392 | 3354 | temperature: settings.temp_openai, |
| 3393 | 3355 | frequency_penalty: settings.freq_pen_openai, |
| 3394 | 3356 | presence_penalty: settings.pres_pen_openai, |
| 3395 | - count_penalty: settings.count_pen, | |
| 3396 | 3357 | top_p: settings.top_p_openai, |
| 3397 | 3358 | top_k: settings.top_k_openai, |
| 3398 | 3359 | top_a: settings.top_a_openai, |
| @@ -3427,8 +3388,6 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) { | ||
| 3427 | 3388 | assistant_prefill: settings.assistant_prefill, |
| 3428 | 3389 | assistant_impersonation: settings.assistant_impersonation, |
| 3429 | 3390 | human_sysprompt_message: settings.human_sysprompt_message, |
| 3430 | - use_ai21_tokenizer: settings.use_ai21_tokenizer, | |
| 3431 | - use_google_tokenizer: settings.use_google_tokenizer, | |
| 3432 | 3391 | claude_use_sysprompt: settings.claude_use_sysprompt, |
| 3433 | 3392 | use_makersuite_sysprompt: settings.use_makersuite_sysprompt, |
| 3434 | 3393 | use_alt_scale: settings.use_alt_scale, |
| @@ -3799,7 +3758,6 @@ function onSettingsPresetChange() { | ||
| 3799 | 3758 | temperature: ['#temp_openai', 'temp_openai', false], |
| 3800 | 3759 | frequency_penalty: ['#freq_pen_openai', 'freq_pen_openai', false], |
| 3801 | 3760 | presence_penalty: ['#pres_pen_openai', 'pres_pen_openai', false], |
| 3802 | - count_penalty: ['#count_pen', 'count_pen', false], | |
| 3803 | 3761 | top_p: ['#top_p_openai', 'top_p_openai', false], |
| 3804 | 3762 | top_k: ['#top_k_openai', 'top_k_openai', false], |
| 3805 | 3763 | top_a: ['#top_a_openai', 'top_a_openai', false], |
| @@ -3856,8 +3814,6 @@ function onSettingsPresetChange() { | ||
| 3856 | 3814 | assistant_prefill: ['#claude_assistant_prefill', 'assistant_prefill', false], |
| 3857 | 3815 | assistant_impersonation: ['#claude_assistant_impersonation', 'assistant_impersonation', false], |
| 3858 | 3816 | human_sysprompt_message: ['#claude_human_sysprompt_textarea', 'human_sysprompt_message', false], |
| 3859 | - use_ai21_tokenizer: ['#use_ai21_tokenizer', 'use_ai21_tokenizer', true], | |
| 3860 | - use_google_tokenizer: ['#use_google_tokenizer', 'use_google_tokenizer', true], | |
| 3861 | 3817 | claude_use_sysprompt: ['#claude_use_sysprompt', 'claude_use_sysprompt', true], |
| 3862 | 3818 | use_makersuite_sysprompt: ['#use_makersuite_sysprompt', 'use_makersuite_sysprompt', true], |
| 3863 | 3819 | use_alt_scale: ['#use_alt_scale', 'use_alt_scale', true], |
| @@ -4028,6 +3984,11 @@ async function onModelChange() { | ||
| 4028 | 3984 | } |
| 4029 | 3985 | |
| 4030 | 3986 | if ($(this).is('#model_ai21_select')) { |
| 3987 | + if (value === '' || value.startsWith('j2-')) { | |
| 3988 | + value = 'jamba-1.5-large'; | |
| 3989 | + $('#model_ai21_select').val(value); | |
| 3990 | + } | |
| 3991 | + | |
| 4031 | 3992 | console.log('AI21 model changed to', value); |
| 4032 | 3993 | oai_settings.ai21_model = value; |
| 4033 | 3994 | } |
| @@ -4230,7 +4191,7 @@ async function onModelChange() { | ||
| 4230 | 4191 | else if (['command-light-nightly', 'command-nightly'].includes(oai_settings.cohere_model)) { |
| 4231 | 4192 | $('#openai_max_context').attr('max', max_8k); |
| 4232 | 4193 | } |
| 4233 | 4194 | else if (['command-r', oai_settings.cohere_model.includes('command-r-plus'].includes(oai_settings.cohere_model)) { |
| 4234 | 4195 | $('#openai_max_context').attr('max', max_128k); |
| 4235 | 4196 | } |
| 4236 | 4197 | else if (['c4ai-aya-23'].includes(oai_settings.cohere_model)) { |
| @@ -4305,33 +4266,13 @@ async function onModelChange() { | ||
| 4305 | 4266 | if (oai_settings.chat_completion_source == chat_completion_sources.AI21) { |
| 4306 | 4267 | if (oai_settings.max_context_unlocked) { |
| 4307 | 4268 | $('#openai_max_context').attr('max', unlocked_max); |
| 4308 | - } else { | |
| 4269 | + } else if (oai_settings.ai21_model.includes('jamba-1.5') || oai_settings.ai21_model.includes('jamba-instruct')) { | |
| 4309 | 4270 | $('#openai_max_context').attr('max', ai21_maxmax_256k); |
| 4310 | 4271 | } |
| 4311 | 4272 | |
| 4312 | 4273 | oai_settings.openai_max_context = Math.min(oai_settings.openai_max_context, Number($('#openai_max_context').attr('max')), oai_settings.openai_max_context); |
| 4313 | 4274 | $('#openai_max_context').val(oai_settings.openai_max_context).trigger('input'); |
| 4314 | - | |
| 4275 | + $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); | |
| 4315 | - oai_settings.temp_openai = Math.min(claude_max_temp, oai_settings.temp_openai); | |
| 4316 | - $('#temp_openai').attr('max', claude_max_temp).val(oai_settings.temp_openai).trigger('input'); | |
| 4317 | - | |
| 4318 | - oai_settings.freq_pen_openai = Math.min(j2_max_freq, oai_settings.freq_pen_openai < 0 ? 0 : oai_settings.freq_pen_openai); | |
| 4319 | - $('#freq_pen_openai').attr('min', 0).attr('max', j2_max_freq).val(oai_settings.freq_pen_openai).trigger('input'); | |
| 4320 | - | |
| 4321 | - oai_settings.pres_pen_openai = Math.min(j2_max_pres, oai_settings.pres_pen_openai < 0 ? 0 : oai_settings.pres_pen_openai); | |
| 4322 | - $('#pres_pen_openai').attr('min', 0).attr('max', j2_max_pres).val(oai_settings.pres_pen_openai).trigger('input'); | |
| 4323 | - | |
| 4324 | - oai_settings.top_k_openai = Math.min(j2_max_topk, oai_settings.top_k_openai); | |
| 4325 | - $('#top_k_openai').attr('max', j2_max_topk).val(oai_settings.top_k_openai).trigger('input'); | |
| 4326 | - } else if (oai_settings.chat_completion_source != chat_completion_sources.AI21) { | |
| 4327 | - oai_settings.freq_pen_openai = Math.min(2.0, oai_settings.freq_pen_openai); | |
| 4328 | - $('#freq_pen_openai').attr('min', -2.0).attr('max', 2.0).val(oai_settings.freq_pen_openai).trigger('input'); | |
| 4329 | - | |
| 4330 | - oai_settings.pres_pen_openai = Math.min(2.0, oai_settings.pres_pen_openai); | |
| 4331 | - $('#pres_pen_openai').attr('min', -2.0).attr('max', 2.0).val(oai_settings.pres_pen_openai).trigger('input'); | |
| 4332 | - | |
| 4333 | - oai_settings.top_k_openai = Math.min(200, oai_settings.top_k_openai); | |
| 4334 | - $('#top_k_openai').attr('max', 200).val(oai_settings.top_k_openai).trigger('input'); | |
| 4335 | 4276 | } |
| 4336 | 4277 | |
| 4337 | 4278 | if (oai_settings.chat_completion_source == chat_completion_sources.CUSTOM) { |
| @@ -4388,6 +4329,16 @@ async function onModelChange() { | ||
| 4388 | 4329 | $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input'); |
| 4389 | 4330 | } |
| 4390 | 4331 | |
| 4332 | + if (oai_settings.chat_completion_source === chat_completion_sources.COHERE) { | |
| 4333 | + oai_settings.pres_pen_openai = Math.min(Math.max(0, oai_settings.pres_pen_openai), 1); | |
| 4334 | + $('#pres_pen_openai').attr('max', 1).attr('min', 0).val(oai_settings.pres_pen_openai).trigger('input'); | |
| 4335 | + oai_settings.freq_pen_openai = Math.min(Math.max(0, oai_settings.freq_pen_openai), 1); | |
| 4336 | + $('#freq_pen_openai').attr('max', 1).attr('min', 0).val(oai_settings.freq_pen_openai).trigger('input'); | |
| 4337 | + } else { | |
| 4338 | + $('#pres_pen_openai').attr('max', 2).attr('min', -2).val(oai_settings.pres_pen_openai).trigger('input'); | |
| 4339 | + $('#freq_pen_openai').attr('max', 2).attr('min', -2).val(oai_settings.freq_pen_openai).trigger('input'); | |
| 4340 | + } | |
| 4341 | + | |
| 4391 | 4342 | $('#openai_max_context_counter').attr('max', Number($('#openai_max_context').attr('max'))); |
| 4392 | 4343 | |
| 4393 | 4344 | saveSettingsDebounced(); |
| @@ -4473,7 +4424,7 @@ async function onConnectButtonClick(e) { | ||
| 4473 | 4424 | } |
| 4474 | 4425 | |
| 4475 | 4426 | if (!secret_state[SECRET_KEYS.MAKERSUITE] && !oai_settings.reverse_proxy) { |
| 4476 | 4427 | console.log('No secret key saved for MakerSuiteGoogle AI Studio'); |
| 4477 | 4428 | return; |
| 4478 | 4429 | } |
| 4479 | 4430 | } |
| @@ -4673,17 +4624,17 @@ function toggleChatCompletionForms() { | ||
| 4673 | 4624 | async function testApiConnection() { |
| 4674 | 4625 | // Check if the previous request is still in progress |
| 4675 | 4626 | if (is_send_press) { |
| 4676 | 4627 | toastr.info('t`Please wait for the previous request to complete.'`); |
| 4677 | 4628 | return; |
| 4678 | 4629 | } |
| 4679 | 4630 | |
| 4680 | 4631 | try { |
| 4681 | 4632 | const reply = await sendOpenAIRequest('quiet', [{ 'role': 'user', 'content': 'Hi' }]); |
| 4682 | 4633 | console.log(reply); |
| 4683 | 4634 | toastr.success('t`API connection successful!'`); |
| 4684 | 4635 | } |
| 4685 | 4636 | catch (err) { |
| 4686 | 4637 | toastr.error('t`Could not get a reply from API. Check your connection settings / API key and try again.'`); |
| 4687 | 4638 | } |
| 4688 | 4639 | } |
| 4689 | 4640 | |
| @@ -4752,11 +4703,14 @@ export function isImageInliningSupported() { | ||
| 4752 | 4703 | 'gemini-1.5-flash', |
| 4753 | 4704 | 'gemini-1.5-flash-latest', |
| 4754 | 4705 | 'gemini-1.5-flash-001', |
| 4706 | + 'gemini-1.5-flash-exp-0827', | |
| 4707 | + 'gemini-1.5-flash-8b-exp-0827', | |
| 4755 | 4708 | 'gemini-1.0-pro-vision-latest', |
| 4756 | 4709 | 'gemini-1.5-pro', |
| 4757 | 4710 | 'gemini-1.5-pro-latest', |
| 4758 | 4711 | 'gemini-1.5-pro-001', |
| 4759 | 4712 | 'gemini-1.5-pro-exp-0801', |
| 4713 | + 'gemini-1.5-pro-exp-0827', | |
| 4760 | 4714 | 'gemini-pro-vision', |
| 4761 | 4715 | 'claude-3', |
| 4762 | 4716 | 'claude-3-5', |
| @@ -4837,7 +4791,7 @@ function onProxyPresetChange() { | ||
| 4837 | 4791 | if (selectedPreset) { |
| 4838 | 4792 | setProxyPreset(selectedPreset.name, selectedPreset.url, selectedPreset.password); |
| 4839 | 4793 | } else { |
| 4840 | 4794 | console.error(t`Proxy preset "'${value}"' not found in proxies array.`); |
| 4841 | 4795 | } |
| 4842 | 4796 | saveSettingsDebounced(); |
| 4843 | 4797 | } |
| @@ -4849,7 +4803,7 @@ $('#save_proxy').on('click', async function () { | ||
| 4849 | 4803 | |
| 4850 | 4804 | setProxyPreset(presetName, reverseProxy, proxyPassword); |
| 4851 | 4805 | saveSettingsDebounced(); |
| 4852 | 4806 | toastr.success('t`Proxy Saved'`); |
| 4853 | 4807 | if ($('#openai_proxy_preset').val() !== presetName) { |
| 4854 | 4808 | const option = document.createElement('option'); |
| 4855 | 4809 | option.text = presetName; |
| @@ -4883,9 +4837,9 @@ $('#delete_proxy').on('click', async function () { | ||
| 4883 | 4837 | |
| 4884 | 4838 | saveSettingsDebounced(); |
| 4885 | 4839 | $('#openai_proxy_preset').val(selected_proxy.name); |
| 4886 | 4840 | toastr.success('t`Proxy Deleted'`); |
| 4887 | 4841 | } else { |
| 4888 | 4842 | toastr.error(t`Could not find proxy with name "'${presetName}"'`); |
| 4889 | 4843 | } |
| 4890 | 4844 | }); |
| 4891 | 4845 | |
| @@ -4953,12 +4907,6 @@ $(document).ready(async function () { | ||
| 4953 | 4907 | saveSettingsDebounced(); |
| 4954 | 4908 | }); |
| 4955 | 4909 | |
| 4956 | - $('#count_pen').on('input', function () { | |
| 4957 | - oai_settings.count_pen = Number($(this).val()); | |
| 4958 | - $('#count_pen_counter').val(Number($(this).val()).toFixed(2)); | |
| 4959 | - saveSettingsDebounced(); | |
| 4960 | - }); | |
| 4961 | - | |
| 4962 | 4910 | $('#top_p_openai').on('input', function () { |
| 4963 | 4911 | oai_settings.top_p_openai = Number($(this).val()); |
| 4964 | 4912 | $('#top_p_counter_openai').val(Number($(this).val()).toFixed(2)); |
| @@ -5017,20 +4965,6 @@ $(document).ready(async function () { | ||
| 5017 | 4965 | saveSettingsDebounced(); |
| 5018 | 4966 | }); |
| 5019 | 4967 | |
| 5020 | - $('#use_ai21_tokenizer').on('change', function () { | |
| 5021 | - oai_settings.use_ai21_tokenizer = !!$('#use_ai21_tokenizer').prop('checked'); | |
| 5022 | - oai_settings.use_ai21_tokenizer ? ai21_max = 8191 : ai21_max = 9200; | |
| 5023 | - oai_settings.openai_max_context = Math.min(ai21_max, oai_settings.openai_max_context); | |
| 5024 | - $('#openai_max_context').attr('max', ai21_max).val(oai_settings.openai_max_context).trigger('input'); | |
| 5025 | - $('#openai_max_context_counter').attr('max', Number($('#openai_max_context').attr('max'))); | |
| 5026 | - saveSettingsDebounced(); | |
| 5027 | - }); | |
| 5028 | - | |
| 5029 | - $('#use_google_tokenizer').on('change', function () { | |
| 5030 | - oai_settings.use_google_tokenizer = !!$('#use_google_tokenizer').prop('checked'); | |
| 5031 | - saveSettingsDebounced(); | |
| 5032 | - }); | |
| 5033 | - | |
| 5034 | 4968 | $('#claude_use_sysprompt').on('change', function () { |
| 5035 | 4969 | oai_settings.claude_use_sysprompt = !!$('#claude_use_sysprompt').prop('checked'); |
| 5036 | 4970 | $('#claude_human_sysprompt_message_block').toggle(oai_settings.claude_use_sysprompt); |
| @@ -40,8 +40,8 @@ export const POPUP_RESULT = { | ||
| 40 | 40 | * @property {POPUP_RESULT|number?} [defaultResult=POPUP_RESULT.AFFIRMATIVE] - The default result of this popup when Enter is pressed. Can be changed from `POPUP_RESULT.AFFIRMATIVE`. |
| 41 | 41 | * @property {CustomPopupButton[]|string[]?} [customButtons=null] - Custom buttons to add to the popup. If only strings are provided, the buttons will be added with default options, and their result will be in order from `2` onward. |
| 42 | 42 | * @property {CustomPopupInput[]?} [customInputs=null] - Custom inputs to add to the popup. The display below the content and the input box, one by one. |
| 43 | 43 | * @property {(popup: Popup) => Promise<boolean?>|boolean?} [onClosing=null] - Handler called before the popup closes, return `false` to cancel the close |
| 44 | 44 | * @property {(popup: Popup) => Promise<void?>|void?} [onClose=null] - Handler called after the popup closes, but before the DOM is cleaned up |
| 45 | 45 | * @property {number?} [cropAspect=null] - Aspect ratio for the crop popup |
| 46 | 46 | * @property {string?} [cropImage=null] - Image URL to display in the crop popup |
| 47 | 47 | */ |
| @@ -138,8 +138,8 @@ export class Popup { | ||
| 138 | 138 | /** @readonly @type {CustomPopupButton[]|string[]?} */ customButtons; |
| 139 | 139 | /** @readonly @type {CustomPopupInput[]} */ customInputs; |
| 140 | 140 | |
| 141 | 141 | /** @type {(popup: Popup) => Promise<boolean?>|boolean?} */ onClosing; |
| 142 | 142 | /** @type {(popup: Popup) => Promise<void?>|void?} */ onClose; |
| 143 | 143 | |
| 144 | 144 | /** @type {POPUP_RESULT|number} */ result; |
| 145 | 145 | /** @type {any} */ value; |
| @@ -509,7 +509,7 @@ export class Popup { | ||
| 509 | 509 | this.result = result; |
| 510 | 510 | |
| 511 | 511 | if (this.onClosing) { |
| 512 | 512 | const shouldClose = await this.onClosing(this); |
| 513 | 513 | if (!shouldClose) { |
| 514 | 514 | this.#isClosingPrevented = true; |
| 515 | 515 | // Set values back if we cancel out of closing the popup |
| @@ -547,13 +547,13 @@ export class Popup { | ||
| 547 | 547 | fixToastrForDialogs(); |
| 548 | 548 | |
| 549 | 549 | // After the dialog is actually completely closed, remove it from the DOM |
| 550 | 550 | runAfterAnimation(this.dlg, async () => { |
| 551 | 551 | // Call the close on the dialog |
| 552 | 552 | this.dlg.close(); |
| 553 | 553 | |
| 554 | 554 | // Run a possible custom handler right before DOM removal |
| 555 | 555 | if (this.onClose) { |
| 556 | 556 | await this.onClose(this); |
| 557 | 557 | } |
| 558 | 558 | |
| 559 | 559 | // Remove it from the dom |
| @@ -60,6 +60,7 @@ export { | ||
| 60 | 60 | power_user, |
| 61 | 61 | send_on_enter_options, |
| 62 | 62 | getContextSettings, |
| 63 | + applyPowerUserSettings, | |
| 63 | 64 | }; |
| 64 | 65 | |
| 65 | 66 | export const MAX_CONTEXT_DEFAULT = 8192; |
| @@ -106,6 +107,7 @@ export const persona_description_positions = { | ||
| 106 | 107 | TOP_AN: 2, |
| 107 | 108 | BOTTOM_AN: 3, |
| 108 | 109 | AT_DEPTH: 4, |
| 110 | + NONE: 9, | |
| 109 | 111 | }; |
| 110 | 112 | |
| 111 | 113 | let power_user = { |
| @@ -301,45 +303,9 @@ let movingUIPresets = []; | ||
| 301 | 303 | export let context_presets = []; |
| 302 | 304 | |
| 303 | 305 | const storage_keys = { |
| 304 | - fast_ui_mode: 'TavernAI_fast_ui_mode', | |
| 305 | - avatar_style: 'TavernAI_avatar_style', | |
| 306 | - chat_display: 'TavernAI_chat_display', | |
| 307 | - chat_width: 'chat_width', | |
| 308 | - font_scale: 'TavernAI_font_scale', | |
| 309 | - | |
| 310 | - main_text_color: 'TavernAI_main_text_color', | |
| 311 | - italics_text_color: 'TavernAI_italics_text_color', | |
| 312 | - underline_text_color: 'TavernAI_underline_text_color', | |
| 313 | - quote_text_color: 'TavernAI_quote_text_color', | |
| 314 | - blur_tint_color: 'TavernAI_blur_tint_color', | |
| 315 | - chat_tint_color: 'TavernAI_chat_tint_color', | |
| 316 | - user_mes_blur_tint_color: 'TavernAI_user_mes_blur_tint_color', | |
| 317 | - bot_mes_blur_tint_color: 'TavernAI_bot_mes_blur_tint_color', | |
| 318 | - blur_strength: 'TavernAI_blur_strength', | |
| 319 | - shadow_color: 'TavernAI_shadow_color', | |
| 320 | - shadow_width: 'TavernAI_shadow_width', | |
| 321 | - border_color: 'TavernAI_border_color', | |
| 322 | - | |
| 323 | - custom_css: 'TavernAI_custom_css', | |
| 324 | - | |
| 325 | - waifuMode: 'TavernAI_waifuMode', | |
| 326 | - movingUI: 'TavernAI_movingUI', | |
| 327 | - noShadows: 'TavernAI_noShadows', | |
| 328 | - | |
| 329 | - hotswap_enabled: 'HotswapEnabled', | |
| 330 | - timer_enabled: 'TimerEnabled', | |
| 331 | - timestamps_enabled: 'TimestampsEnabled', | |
| 332 | - timestamp_model_icon: 'TimestampModelIcon', | |
| 333 | - mesIDDisplay_enabled: 'mesIDDisplayEnabled', | |
| 334 | - hideChatAvatars_enabled: 'hideChatAvatarsEnabled', | |
| 335 | - message_token_count_enabled: 'MessageTokenCountEnabled', | |
| 336 | - expand_message_actions: 'ExpandMessageActions', | |
| 337 | - enableZenSliders: 'enableZenSliders', | |
| 338 | - enableLabMode: 'enableLabMode', | |
| 339 | - reduced_motion: 'reduced_motion', | |
| 340 | - compact_input_area: 'compact_input_area', | |
| 341 | 306 | auto_connect_legacy: 'AutoConnectEnabled', |
| 342 | 307 | auto_load_chat_legacy: 'AutoLoadChatEnabled', |
| 308 | + hideChatAvatars_legacy: 'hideChatAvatarsEnabled', | |
| 343 | 309 | |
| 344 | 310 | storyStringValidationCache: 'StoryStringValidationCache', |
| 345 | 311 | }; |
| @@ -459,73 +425,47 @@ function fixMarkdown(text, forDisplay) { | ||
| 459 | 425 | } |
| 460 | 426 | |
| 461 | 427 | function switchHotswap() { |
| 462 | - const value = localStorage.getItem(storage_keys.hotswap_enabled); | |
| 463 | - power_user.hotswap_enabled = value === null ? true : value == 'true'; | |
| 464 | 428 | $('body').toggleClass('no-hotswap', !power_user.hotswap_enabled); |
| 465 | 429 | $('#hotswapEnabled').prop('checked', power_user.hotswap_enabled); |
| 466 | 430 | } |
| 467 | 431 | |
| 468 | 432 | function switchTimer() { |
| 469 | - const value = localStorage.getItem(storage_keys.timer_enabled); | |
| 470 | - power_user.timer_enabled = value === null ? true : value == 'true'; | |
| 471 | 433 | $('body').toggleClass('no-timer', !power_user.timer_enabled); |
| 472 | 434 | $('#messageTimerEnabled').prop('checked', power_user.timer_enabled); |
| 473 | 435 | } |
| 474 | 436 | |
| 475 | 437 | function switchTimestamps() { |
| 476 | - const value = localStorage.getItem(storage_keys.timestamps_enabled); | |
| 477 | - power_user.timestamps_enabled = value === null ? true : value == 'true'; | |
| 478 | 438 | $('body').toggleClass('no-timestamps', !power_user.timestamps_enabled); |
| 479 | 439 | $('#messageTimestampsEnabled').prop('checked', power_user.timestamps_enabled); |
| 480 | 440 | } |
| 481 | 441 | |
| 482 | 442 | function switchIcons() { |
| 483 | - const value = localStorage.getItem(storage_keys.timestamp_model_icon); | |
| 484 | - power_user.timestamp_model_icon = value === null ? true : value == 'true'; | |
| 485 | 443 | $('body').toggleClass('no-modelIcons', !power_user.timestamp_model_icon); |
| 486 | 444 | $('#messageModelIconEnabled').prop('checked', power_user.timestamp_model_icon); |
| 487 | 445 | } |
| 488 | 446 | |
| 489 | 447 | function switchTokenCount() { |
| 490 | - const value = localStorage.getItem(storage_keys.message_token_count_enabled); | |
| 491 | - power_user.message_token_count_enabled = value === null ? false : value == 'true'; | |
| 492 | 448 | $('body').toggleClass('no-tokenCount', !power_user.message_token_count_enabled); |
| 493 | 449 | $('#messageTokensEnabled').prop('checked', power_user.message_token_count_enabled); |
| 494 | 450 | } |
| 495 | 451 | |
| 496 | 452 | function switchMesIDDisplay() { |
| 497 | - const value = localStorage.getItem(storage_keys.mesIDDisplay_enabled); | |
| 498 | - power_user.mesIDDisplay_enabled = value === null ? true : value == 'true'; | |
| 499 | - /* console.log(` | |
| 500 | - localstorage value:${value}, | |
| 501 | - poweruser before:${before}, | |
| 502 | - poweruser after:${power_user.mesIDDisplay_enabled}`) */ | |
| 503 | 453 | $('body').toggleClass('no-mesIDDisplay', !power_user.mesIDDisplay_enabled); |
| 504 | 454 | $('#mesIDDisplayEnabled').prop('checked', power_user.mesIDDisplay_enabled); |
| 505 | 455 | } |
| 506 | 456 | |
| 507 | 457 | function switchHideChatAvatars() { |
| 508 | - const value = localStorage.getItem(storage_keys.hideChatAvatars_enabled); | |
| 509 | - power_user.hideChatAvatars_enabled = value === null ? false : value == 'true'; | |
| 510 | - /*console.log(` | |
| 511 | - localstorage value:${value}, | |
| 512 | - poweruser after:${power_user.hideChatAvatars_enabled}`) | |
| 513 | - */ | |
| 514 | 458 | $('body').toggleClass('hideChatAvatars', power_user.hideChatAvatars_enabled); |
| 515 | 459 | $('#hideChatAvatarsEnabled').prop('checked', power_user.hideChatAvatars_enabled); |
| 516 | 460 | } |
| 517 | 461 | |
| 518 | 462 | function switchMessageActions() { |
| 519 | - const value = localStorage.getItem(storage_keys.expand_message_actions); | |
| 520 | - power_user.expand_message_actions = value === null ? false : value == 'true'; | |
| 521 | 463 | $('body').toggleClass('expandMessageActions', power_user.expand_message_actions); |
| 522 | 464 | $('#expandMessageActions').prop('checked', power_user.expand_message_actions); |
| 523 | 465 | $('.extraMesButtons, .extraMesButtonsHint').removeAttr('style'); |
| 524 | 466 | } |
| 525 | 467 | |
| 526 | 468 | function switchReducedMotion() { |
| 527 | - const value = localStorage.getItem(storage_keys.reduced_motion); | |
| 528 | - power_user.reduced_motion = value === null ? false : value == 'true'; | |
| 529 | 469 | jQuery.fx.off = power_user.reduced_motion; |
| 530 | 470 | const overrideDuration = power_user.reduced_motion ? 0 : ANIMATION_DURATION_DEFAULT; |
| 531 | 471 | setAnimationDuration(overrideDuration); |
| @@ -534,8 +474,6 @@ function switchReducedMotion() { | ||
| 534 | 474 | } |
| 535 | 475 | |
| 536 | 476 | function switchCompactInputArea() { |
| 537 | - const value = localStorage.getItem(storage_keys.compact_input_area); | |
| 538 | - power_user.compact_input_area = value === null ? true : value == 'true'; | |
| 539 | 477 | $('#send_form').toggleClass('compact', power_user.compact_input_area); |
| 540 | 478 | $('#compact_input_area').prop('checked', power_user.compact_input_area); |
| 541 | 479 | } |
| @@ -551,8 +489,6 @@ async function switchLabMode() { | ||
| 551 | 489 | } |
| 552 | 490 | */ |
| 553 | 491 | await delay(100); |
| 554 | - const value = localStorage.getItem(storage_keys.enableLabMode); | |
| 555 | - power_user.enableLabMode = value === null ? false : value == 'true'; | |
| 556 | 492 | $('body').toggleClass('enableLabMode', power_user.enableLabMode); |
| 557 | 493 | $('#enableLabMode').prop('checked', power_user.enableLabMode); |
| 558 | 494 | |
| @@ -599,8 +535,6 @@ async function switchLabMode() { | ||
| 599 | 535 | |
| 600 | 536 | async function switchZenSliders() { |
| 601 | 537 | await delay(100); |
| 602 | - const value = localStorage.getItem(storage_keys.enableZenSliders); | |
| 603 | - power_user.enableZenSliders = value === null ? false : value == 'true'; | |
| 604 | 538 | $('body').toggleClass('enableZenSliders', power_user.enableZenSliders); |
| 605 | 539 | $('#enableZenSliders').prop('checked', power_user.enableZenSliders); |
| 606 | 540 | |
| @@ -987,8 +921,6 @@ async function CreateZenSliders(elmnt) { | ||
| 987 | 921 | } |
| 988 | 922 | } |
| 989 | 923 | function switchUiMode() { |
| 990 | - const fastUi = localStorage.getItem(storage_keys.fast_ui_mode); | |
| 991 | - power_user.fast_ui_mode = fastUi === null ? true : fastUi == 'true'; | |
| 992 | 924 | $('body').toggleClass('no-blur', power_user.fast_ui_mode); |
| 993 | 925 | $('#fast_ui_mode').prop('checked', power_user.fast_ui_mode); |
| 994 | 926 | if (power_user.fast_ui_mode) { |
| @@ -1038,8 +970,6 @@ function switchMovingUI() { | ||
| 1038 | 970 | $('.drawer-content.maximized').each(function () { |
| 1039 | 971 | $(this).find('.inline-drawer-maximize').trigger('click'); |
| 1040 | 972 | }); |
| 1041 | - const movingUI = localStorage.getItem(storage_keys.movingUI); | |
| 1042 | - power_user.movingUI = movingUI === null ? false : movingUI == 'true'; | |
| 1043 | 973 | $('body').toggleClass('movingUI', power_user.movingUI); |
| 1044 | 974 | if (power_user.movingUI === true) { |
| 1045 | 975 | initMovingUI(); |
| @@ -1055,9 +985,7 @@ function switchMovingUI() { | ||
| 1055 | 985 | } |
| 1056 | 986 | } |
| 1057 | 987 | |
| 1058 | 988 | function noShadowsapplyNoShadows() { |
| 1059 | - const noShadows = localStorage.getItem(storage_keys.noShadows); | |
| 1060 | - power_user.noShadows = noShadows === null ? false : noShadows == 'true'; | |
| 1061 | 989 | $('body').toggleClass('noShadows', power_user.noShadows); |
| 1062 | 990 | $('#noShadowsmode').prop('checked', power_user.noShadows); |
| 1063 | 991 | if (power_user.noShadows) { |
| @@ -1071,12 +999,9 @@ function noShadows() { | ||
| 1071 | 999 | } |
| 1072 | 1000 | |
| 1073 | 1001 | function applyAvatarStyle() { |
| 1074 | - power_user.avatar_style = Number(localStorage.getItem(storage_keys.avatar_style) ?? avatar_styles.ROUND); | |
| 1075 | 1002 | $('body').toggleClass('big-avatars', power_user.avatar_style === avatar_styles.RECTANGULAR); |
| 1076 | 1003 | $('body').toggleClass('square-avatars', power_user.avatar_style === avatar_styles.SQUARE); |
| 1077 | 1004 | $('#avatar_style').val(power_user.avatar_style).prop('selected', true); |
| 1078 | - //$(`input[name="avatar_style"][value="${power_user.avatar_style}"]`).prop("checked", true); | |
| 1079 | - | |
| 1080 | 1005 | } |
| 1081 | 1006 | |
| 1082 | 1007 | function applyChatDisplay() { |
| @@ -1111,8 +1036,6 @@ function applyChatDisplay() { | ||
| 1111 | 1036 | } |
| 1112 | 1037 | |
| 1113 | 1038 | function applyChatWidth(type) { |
| 1114 | - power_user.chat_width = Number(localStorage.getItem(storage_keys.chat_width) ?? 50); | |
| 1115 | - | |
| 1116 | 1039 | if (type === 'forced') { |
| 1117 | 1040 | let r = document.documentElement; |
| 1118 | 1041 | r.style.setProperty('--sheldWidth', `${power_user.chat_width}vw`); |
| @@ -1174,8 +1097,6 @@ async function applyThemeColor(type) { | ||
| 1174 | 1097 | } |
| 1175 | 1098 | |
| 1176 | 1099 | async function applyCustomCSS() { |
| 1177 | - power_user.custom_css = String(localStorage.getItem(storage_keys.custom_css) ?? ''); | |
| 1178 | - | |
| 1179 | 1100 | $('#customCSS').val(power_user.custom_css); |
| 1180 | 1101 | var styleId = 'custom-style'; |
| 1181 | 1102 | var style = document.getElementById(styleId); |
| @@ -1189,32 +1110,26 @@ async function applyCustomCSS() { | ||
| 1189 | 1110 | } |
| 1190 | 1111 | |
| 1191 | 1112 | async function applyBlurStrength() { |
| 1192 | - power_user.blur_strength = Number(localStorage.getItem(storage_keys.blur_strength) ?? 1); | |
| 1113 | + document.documentElement.style.setProperty('--blurStrength', String(power_user.blur_strength)); | |
| 1193 | - document.documentElement.style.setProperty('--blurStrength', power_user.blur_strength); | |
| 1194 | 1114 | $('#blur_strength_counter').val(power_user.blur_strength); |
| 1195 | 1115 | $('#blur_strength').val(power_user.blur_strength); |
| 1196 | - | |
| 1197 | - | |
| 1198 | 1116 | } |
| 1199 | 1117 | |
| 1200 | 1118 | async function applyShadowWidth() { |
| 1201 | - power_user.shadow_width = Number(localStorage.getItem(storage_keys.shadow_width) ?? 2); | |
| 1119 | + document.documentElement.style.setProperty('--shadowWidth', String(power_user.shadow_width)); | |
| 1202 | - document.documentElement.style.setProperty('--shadowWidth', power_user.shadow_width); | |
| 1203 | 1120 | $('#shadow_width_counter').val(power_user.shadow_width); |
| 1204 | 1121 | $('#shadow_width').val(power_user.shadow_width); |
| 1205 | 1122 | |
| 1206 | 1123 | } |
| 1207 | 1124 | |
| 1208 | 1125 | async function applyFontScale(type) { |
| 1209 | - | |
| 1210 | - power_user.font_scale = Number(localStorage.getItem(storage_keys.font_scale) ?? 1); | |
| 1211 | 1126 | //this is to allow forced setting on page load, theme swap, etc |
| 1212 | 1127 | if (type === 'forced') { |
| 1213 | 1128 | document.documentElement.style.setProperty('--fontScale', String(power_user.font_scale)); |
| 1214 | 1129 | } else { |
| 1215 | 1130 | //this is to prevent the slider from updating page in real time |
| 1216 | 1131 | $('#font_scale').off('mouseup touchend').on('mouseup touchend', () => { |
| 1217 | 1132 | document.documentElement.style.setProperty('--fontScale', String(power_user.font_scale)); |
| 1218 | 1133 | }); |
| 1219 | 1134 | } |
| 1220 | 1135 | |
| @@ -1243,64 +1158,55 @@ async function applyTheme(name) { | ||
| 1243 | 1158 | { |
| 1244 | 1159 | key: 'blur_strength', |
| 1245 | 1160 | action: async () => { |
| 1246 | - localStorage.setItem(storage_keys.blur_strength, power_user.blur_strength); | |
| 1247 | 1161 | await applyBlurStrength(); |
| 1248 | 1162 | }, |
| 1249 | 1163 | }, |
| 1250 | 1164 | { |
| 1251 | 1165 | key: 'custom_css', |
| 1252 | 1166 | action: async () => { |
| 1253 | - localStorage.setItem(storage_keys.custom_css, power_user.custom_css); | |
| 1254 | 1167 | await applyCustomCSS(); |
| 1255 | 1168 | }, |
| 1256 | 1169 | }, |
| 1257 | 1170 | { |
| 1258 | 1171 | key: 'shadow_width', |
| 1259 | 1172 | action: async () => { |
| 1260 | - localStorage.setItem(storage_keys.shadow_width, power_user.shadow_width); | |
| 1261 | 1173 | await applyShadowWidth(); |
| 1262 | 1174 | }, |
| 1263 | 1175 | }, |
| 1264 | 1176 | { |
| 1265 | 1177 | key: 'font_scale', |
| 1266 | 1178 | action: async () => { |
| 1267 | - localStorage.setItem(storage_keys.font_scale, power_user.font_scale); | |
| 1268 | 1179 | await applyFontScale('forced'); |
| 1269 | 1180 | }, |
| 1270 | 1181 | }, |
| 1271 | 1182 | { |
| 1272 | 1183 | key: 'fast_ui_mode', |
| 1273 | 1184 | action: async () => { |
| 1274 | - localStorage.setItem(storage_keys.fast_ui_mode, power_user.fast_ui_mode); | |
| 1275 | 1185 | switchUiMode(); |
| 1276 | 1186 | }, |
| 1277 | 1187 | }, |
| 1278 | 1188 | { |
| 1279 | 1189 | key: 'waifuMode', |
| 1280 | 1190 | action: async () => { |
| 1281 | - localStorage.setItem(storage_keys.waifuMode, power_user.waifuMode); | |
| 1282 | 1191 | switchWaifuMode(); |
| 1283 | 1192 | }, |
| 1284 | 1193 | }, |
| 1285 | 1194 | { |
| 1286 | 1195 | key: 'chat_display', |
| 1287 | 1196 | action: async () => { |
| 1288 | - localStorage.setItem(storage_keys.chat_display, power_user.chat_display); | |
| 1289 | 1197 | applyChatDisplay(); |
| 1290 | 1198 | }, |
| 1291 | 1199 | }, |
| 1292 | 1200 | { |
| 1293 | 1201 | key: 'avatar_style', |
| 1294 | 1202 | action: async () => { |
| 1295 | - localStorage.setItem(storage_keys.avatar_style, power_user.avatar_style); | |
| 1296 | 1203 | applyAvatarStyle(); |
| 1297 | 1204 | }, |
| 1298 | 1205 | }, |
| 1299 | 1206 | { |
| 1300 | 1207 | key: 'noShadows', |
| 1301 | 1208 | action: async () => { |
| 1302 | - localStorage.setItem(storage_keys.noShadows, power_user.noShadows); | |
| 1209 | + applyNoShadows(); | |
| 1303 | - noShadows(); | |
| 1304 | 1210 | }, |
| 1305 | 1211 | }, |
| 1306 | 1212 | { |
| @@ -1310,78 +1216,66 @@ async function applyTheme(name) { | ||
| 1310 | 1216 | if (!power_user.chat_width) { |
| 1311 | 1217 | power_user.chat_width = 50; |
| 1312 | 1218 | } |
| 1313 | - | |
| 1314 | - localStorage.setItem(storage_keys.chat_width, String(power_user.chat_width)); | |
| 1315 | 1219 | applyChatWidth('forced'); |
| 1316 | 1220 | }, |
| 1317 | 1221 | }, |
| 1318 | 1222 | { |
| 1319 | 1223 | key: 'timer_enabled', |
| 1320 | 1224 | action: async () => { |
| 1321 | - localStorage.setItem(storage_keys.timer_enabled, Boolean(power_user.timer_enabled)); | |
| 1322 | 1225 | switchTimer(); |
| 1323 | 1226 | }, |
| 1324 | 1227 | }, |
| 1325 | 1228 | { |
| 1326 | 1229 | key: 'timestamps_enabled', |
| 1327 | 1230 | action: async () => { |
| 1328 | - localStorage.setItem(storage_keys.timestamps_enabled, Boolean(power_user.timestamps_enabled)); | |
| 1329 | 1231 | switchTimestamps(); |
| 1330 | 1232 | }, |
| 1331 | 1233 | }, |
| 1332 | 1234 | { |
| 1333 | 1235 | key: 'timestamp_model_icon', |
| 1334 | 1236 | action: async () => { |
| 1335 | - localStorage.setItem(storage_keys.timestamp_model_icon, Boolean(power_user.timestamp_model_icon)); | |
| 1336 | 1237 | switchIcons(); |
| 1337 | 1238 | }, |
| 1338 | 1239 | }, |
| 1339 | 1240 | { |
| 1340 | 1241 | key: 'message_token_count_enabled', |
| 1341 | 1242 | action: async () => { |
| 1342 | - localStorage.setItem(storage_keys.message_token_count_enabled, Boolean(power_user.message_token_count_enabled)); | |
| 1343 | 1243 | switchTokenCount(); |
| 1344 | 1244 | }, |
| 1345 | 1245 | }, |
| 1346 | 1246 | { |
| 1347 | 1247 | key: 'mesIDDisplay_enabled', |
| 1348 | 1248 | action: async () => { |
| 1349 | - localStorage.setItem(storage_keys.mesIDDisplay_enabled, Boolean(power_user.mesIDDisplay_enabled)); | |
| 1350 | 1249 | switchMesIDDisplay(); |
| 1351 | 1250 | }, |
| 1352 | 1251 | }, |
| 1353 | 1252 | { |
| 1354 | 1253 | key: 'hideChatAvatars_enabled', |
| 1355 | 1254 | action: async () => { |
| 1356 | - localStorage.setItem(storage_keys.hideChatAvatars_enabled, Boolean(power_user.hideChatAvatars_enabled)); | |
| 1357 | 1255 | switchHideChatAvatars(); |
| 1358 | 1256 | }, |
| 1359 | 1257 | }, |
| 1360 | 1258 | { |
| 1361 | 1259 | key: 'expand_message_actions', |
| 1362 | 1260 | action: async () => { |
| 1363 | - localStorage.setItem(storage_keys.expand_message_actions, Boolean(power_user.expand_message_actions)); | |
| 1364 | 1261 | switchMessageActions(); |
| 1365 | 1262 | }, |
| 1366 | 1263 | }, |
| 1367 | 1264 | { |
| 1368 | 1265 | key: 'enableZenSliders', |
| 1369 | 1266 | action: async () => { |
| 1370 | - localStorage.setItem(storage_keys.enableZenSliders, Boolean(power_user.enableZenSliders)); | |
| 1371 | 1267 | switchMessageActions(); |
| 1372 | 1268 | }, |
| 1373 | 1269 | }, |
| 1374 | 1270 | { |
| 1375 | 1271 | key: 'enableLabMode', |
| 1376 | 1272 | action: async () => { |
| 1377 | - localStorage.setItem(storage_keys.enableLabMode, Boolean(power_user.enableLabMode)); | |
| 1378 | 1273 | switchMessageActions(); |
| 1379 | 1274 | }, |
| 1380 | 1275 | }, |
| 1381 | 1276 | { |
| 1382 | 1277 | key: 'hotswap_enabled', |
| 1383 | 1278 | action: async () => { |
| 1384 | - localStorage.setItem(storage_keys.hotswap_enabled, Boolean(power_user.hotswap_enabled)); | |
| 1385 | 1279 | switchHotswap(); |
| 1386 | 1280 | }, |
| 1387 | 1281 | }, |
| @@ -1402,7 +1296,6 @@ async function applyTheme(name) { | ||
| 1402 | 1296 | { |
| 1403 | 1297 | key: 'reduced_motion', |
| 1404 | 1298 | action: async () => { |
| 1405 | - localStorage.setItem(storage_keys.reduced_motion, String(power_user.reduced_motion)); | |
| 1406 | 1299 | $('#reduced_motion').prop('checked', power_user.reduced_motion); |
| 1407 | 1300 | switchReducedMotion(); |
| 1408 | 1301 | }, |
| @@ -1410,7 +1303,6 @@ async function applyTheme(name) { | ||
| 1410 | 1303 | { |
| 1411 | 1304 | key: 'compact_input_area', |
| 1412 | 1305 | action: async () => { |
| 1413 | - localStorage.setItem(storage_keys.compact_input_area, String(power_user.compact_input_area)); | |
| 1414 | 1306 | $('#compact_input_area').prop('checked', power_user.compact_input_area); |
| 1415 | 1307 | switchCompactInputArea(); |
| 1416 | 1308 | }, |
| @@ -1465,6 +1357,7 @@ async function showDebugMenu() { | ||
| 1465 | 1357 | callGenericPopup(template, POPUP_TYPE.TEXT, '', { wide: true, large: true, allowVerticalScrolling: true }); |
| 1466 | 1358 | } |
| 1467 | 1359 | |
| 1360 | +function applyPowerUserSettings() { | |
| 1468 | 1361 | switchUiMode(); |
| 1469 | 1362 | applyFontScale('forced'); |
| 1470 | 1363 | applyThemeColor(); |
| @@ -1474,7 +1367,7 @@ applyBlurStrength(); | ||
| 1474 | 1367 | applyShadowWidth(); |
| 1475 | 1368 | applyCustomCSS(); |
| 1476 | 1369 | switchMovingUI(); |
| 1477 | 1370 | noShadows applyNoShadows(); |
| 1478 | 1371 | switchHotswap(); |
| 1479 | 1372 | switchTimer(); |
| 1480 | 1373 | switchTimestamps(); |
| @@ -1483,6 +1376,7 @@ switchMesIDDisplay(); | ||
| 1483 | 1376 | switchHideChatAvatars(); |
| 1484 | 1377 | switchTokenCount(); |
| 1485 | 1378 | switchMessageActions(); |
| 1379 | +} | |
| 1486 | 1380 | |
| 1487 | 1381 | function getExampleMessagesBehavior() { |
| 1488 | 1382 | if (power_user.strip_examples) { |
| @@ -1545,20 +1439,10 @@ async function loadPowerUserSettings(settings, data) { | ||
| 1545 | 1439 | context_presets = data.context; |
| 1546 | 1440 | } |
| 1547 | 1441 | |
| 1548 | 1442 | // These are still local storage. Delete in 1.12.7 |
| 1549 | - const fastUi = localStorage.getItem(storage_keys.fast_ui_mode); | |
| 1550 | - const movingUI = localStorage.getItem(storage_keys.movingUI); | |
| 1551 | - const noShadows = localStorage.getItem(storage_keys.noShadows); | |
| 1552 | - const hotswap = localStorage.getItem(storage_keys.hotswap_enabled); | |
| 1553 | - const timer = localStorage.getItem(storage_keys.timer_enabled); | |
| 1554 | - const timestamps = localStorage.getItem(storage_keys.timestamps_enabled); | |
| 1555 | - const mesIDDisplay = localStorage.getItem(storage_keys.mesIDDisplay_enabled); | |
| 1556 | - const hideChatAvatars = localStorage.getItem(storage_keys.hideChatAvatars_enabled); | |
| 1557 | - const expandMessageActions = localStorage.getItem(storage_keys.expand_message_actions); | |
| 1558 | - const enableZenSliders = localStorage.getItem(storage_keys.enableZenSliders); | |
| 1559 | - const enableLabMode = localStorage.getItem(storage_keys.enableLabMode); | |
| 1560 | 1443 | const autoLoadChat = localStorage.getItem(storage_keys.auto_load_chat_legacy); |
| 1561 | 1444 | const autoConnect = localStorage.getItem(storage_keys.auto_connect_legacy); |
| 1445 | + const hideChatAvatars = localStorage.getItem(storage_keys.hideChatAvatars_legacy); | |
| 1562 | 1446 | |
| 1563 | 1447 | if (autoLoadChat) { |
| 1564 | 1448 | power_user.auto_load_chat = autoLoadChat === 'true'; |
| @@ -1570,22 +1454,10 @@ async function loadPowerUserSettings(settings, data) { | ||
| 1570 | 1454 | localStorage.removeItem(storage_keys.auto_connect_legacy); |
| 1571 | 1455 | } |
| 1572 | 1456 | |
| 1573 | - power_user.fast_ui_mode = fastUi === null ? true : fastUi == 'true'; | |
| 1457 | + if (hideChatAvatars) { | |
| 1574 | 1458 | power_user.movingUIhideChatAvatars_enabled = movingUIhideChatAvatars === null ? false : movingUI == 'true'; |
| 1575 | - power_user.noShadows = noShadows === null ? false : noShadows == 'true'; | |
| 1459 | + localStorage.removeItem(storage_keys.hideChatAvatars_legacy); | |
| 1576 | - power_user.hotswap_enabled = hotswap === null ? true : hotswap == 'true'; | |
| 1460 | + } | |
| 1577 | - power_user.timer_enabled = timer === null ? true : timer == 'true'; | |
| 1578 | - power_user.timestamps_enabled = timestamps === null ? true : timestamps == 'true'; | |
| 1579 | - power_user.mesIDDisplay_enabled = mesIDDisplay === null ? true : mesIDDisplay == 'true'; | |
| 1580 | - power_user.hideChatAvatars_enabled = hideChatAvatars === null ? true : hideChatAvatars == 'true'; | |
| 1581 | - power_user.expand_message_actions = expandMessageActions === null ? true : expandMessageActions == 'true'; | |
| 1582 | - power_user.enableZenSliders = enableZenSliders === null ? false : enableZenSliders == 'true'; | |
| 1583 | - power_user.enableLabMode = enableLabMode === null ? false : enableLabMode == 'true'; | |
| 1584 | - power_user.avatar_style = Number(localStorage.getItem(storage_keys.avatar_style) ?? avatar_styles.ROUND); | |
| 1585 | - //power_user.chat_display = Number(localStorage.getItem(storage_keys.chat_display) ?? chat_styles.DEFAULT); | |
| 1586 | - power_user.chat_width = Number(localStorage.getItem(storage_keys.chat_width) ?? 50); | |
| 1587 | - power_user.font_scale = Number(localStorage.getItem(storage_keys.font_scale) ?? 1); | |
| 1588 | - power_user.blur_strength = Number(localStorage.getItem(storage_keys.blur_strength) ?? 10); | |
| 1589 | 1461 | |
| 1590 | 1462 | if (power_user.chat_display === '') { |
| 1591 | 1463 | power_user.chat_display = chat_styles.DEFAULT; |
| @@ -1672,7 +1544,7 @@ async function loadPowerUserSettings(settings, data) { | ||
| 1672 | 1544 | $('#messageTimestampsEnabled').prop('checked', power_user.timestamps_enabled); |
| 1673 | 1545 | $('#messageModelIconEnabled').prop('checked', power_user.timestamp_model_icon); |
| 1674 | 1546 | $('#mesIDDisplayEnabled').prop('checked', power_user.mesIDDisplay_enabled); |
| 1675 | 1547 | $('#hideChatAvatarsEndabledhideChatAvatarsEnabled').prop('checked', power_user.hideChatAvatars_enabled); |
| 1676 | 1548 | $('#prefer_character_prompt').prop('checked', power_user.prefer_character_prompt); |
| 1677 | 1549 | $('#prefer_character_jailbreak').prop('checked', power_user.prefer_character_jailbreak); |
| 1678 | 1550 | $('#enableZenSliders').prop('checked', power_user.enableZenSliders).trigger('input'); |
| @@ -3313,10 +3185,8 @@ $(document).ready(() => { | ||
| 3313 | 3185 | saveSettingsDebounced(); |
| 3314 | 3186 | }); |
| 3315 | 3187 | |
| 3316 | - // Settings that go to local storage | |
| 3317 | 3188 | $('#fast_ui_mode').change(function () { |
| 3318 | 3189 | power_user.fast_ui_mode = $(this).prop('checked'); |
| 3319 | - localStorage.setItem(storage_keys.fast_ui_mode, power_user.fast_ui_mode); | |
| 3320 | 3190 | switchUiMode(); |
| 3321 | 3191 | saveSettingsDebounced(); |
| 3322 | 3192 | }); |
| @@ -3329,22 +3199,19 @@ $(document).ready(() => { | ||
| 3329 | 3199 | |
| 3330 | 3200 | $('#customCSS').on('input', () => { |
| 3331 | 3201 | power_user.custom_css = String($('#customCSS').val()); |
| 3332 | - localStorage.setItem(storage_keys.custom_css, power_user.custom_css); | |
| 3333 | 3202 | saveSettingsDebounced(); |
| 3334 | 3203 | applyCustomCSS(); |
| 3335 | 3204 | }); |
| 3336 | 3205 | |
| 3337 | 3206 | $('#movingUImode').change(function () { |
| 3338 | 3207 | power_user.movingUI = $(this).prop('checked'); |
| 3339 | - localStorage.setItem(storage_keys.movingUI, power_user.movingUI); | |
| 3340 | 3208 | switchMovingUI(); |
| 3341 | 3209 | saveSettingsDebounced(); |
| 3342 | 3210 | }); |
| 3343 | 3211 | |
| 3344 | 3212 | $('#noShadowsmode').change(function () { |
| 3345 | 3213 | power_user.noShadows = $(this).prop('checked'); |
| 3346 | - localStorage.setItem(storage_keys.noShadows, power_user.noShadows); | |
| 3214 | + applyNoShadows(); | |
| 3347 | - noShadows(); | |
| 3348 | 3215 | saveSettingsDebounced(); |
| 3349 | 3216 | }); |
| 3350 | 3217 | |
| @@ -3353,7 +3220,6 @@ $(document).ready(() => { | ||
| 3353 | 3220 | $('#avatar_style').on('change', function () { |
| 3354 | 3221 | const value = $(this).find(':selected').val(); |
| 3355 | 3222 | power_user.avatar_style = Number(value); |
| 3356 | - localStorage.setItem(storage_keys.avatar_style, power_user.avatar_style); | |
| 3357 | 3223 | applyAvatarStyle(); |
| 3358 | 3224 | saveSettingsDebounced(); |
| 3359 | 3225 | }); |
| @@ -3361,17 +3227,15 @@ $(document).ready(() => { | ||
| 3361 | 3227 | $('#chat_display').on('change', function () { |
| 3362 | 3228 | const value = $(this).find(':selected').val(); |
| 3363 | 3229 | power_user.chat_display = Number(value); |
| 3364 | - localStorage.setItem(storage_keys.chat_display, power_user.chat_display); | |
| 3365 | 3230 | applyChatDisplay(); |
| 3366 | 3231 | saveSettingsDebounced(); |
| 3367 | - | |
| 3368 | 3232 | }); |
| 3369 | 3233 | |
| 3370 | 3234 | $('#chat_width_slider').on('input', function (e, data) { |
| 3371 | 3235 | const applyMode = data?.forced ? 'forced' : 'normal'; |
| 3372 | 3236 | power_user.chat_width = Number(e.target.value); |
| 3373 | - localStorage.setItem(storage_keys.chat_width, power_user.chat_width); | |
| 3374 | 3237 | applyChatWidth(applyMode); |
| 3238 | + saveSettingsDebounced(); | |
| 3375 | 3239 | setHotswapsDebounced(); |
| 3376 | 3240 | }); |
| 3377 | 3241 | |
| @@ -3401,7 +3265,6 @@ $(document).ready(() => { | ||
| 3401 | 3265 | const applyMode = data?.forced ? 'forced' : 'normal'; |
| 3402 | 3266 | power_user.font_scale = Number(e.target.value); |
| 3403 | 3267 | $('#font_scale_counter').val(power_user.font_scale); |
| 3404 | - localStorage.setItem(storage_keys.font_scale, power_user.font_scale); | |
| 3405 | 3268 | await applyFontScale(applyMode); |
| 3406 | 3269 | saveSettingsDebounced(); |
| 3407 | 3270 | }); |
| @@ -3409,7 +3272,6 @@ $(document).ready(() => { | ||
| 3409 | 3272 | $('input[name="blur_strength"]').on('input', async function (e) { |
| 3410 | 3273 | power_user.blur_strength = Number(e.target.value); |
| 3411 | 3274 | $('#blur_strength_counter').val(power_user.blur_strength); |
| 3412 | - localStorage.setItem(storage_keys.blur_strength, power_user.blur_strength); | |
| 3413 | 3275 | await applyBlurStrength(); |
| 3414 | 3276 | saveSettingsDebounced(); |
| 3415 | 3277 | }); |
| @@ -3417,7 +3279,6 @@ $(document).ready(() => { | ||
| 3417 | 3279 | $('input[name="shadow_width"]').on('input', async function (e) { |
| 3418 | 3280 | power_user.shadow_width = Number(e.target.value); |
| 3419 | 3281 | $('#shadow_width_counter').val(power_user.shadow_width); |
| 3420 | - localStorage.setItem(storage_keys.shadow_width, power_user.shadow_width); | |
| 3421 | 3282 | await applyShadowWidth(); |
| 3422 | 3283 | saveSettingsDebounced(); |
| 3423 | 3284 | }); |
| @@ -3658,36 +3519,36 @@ $(document).ready(() => { | ||
| 3658 | 3519 | $('#messageTimerEnabled').on('input', function () { |
| 3659 | 3520 | const value = !!$(this).prop('checked'); |
| 3660 | 3521 | power_user.timer_enabled = value; |
| 3661 | - localStorage.setItem(storage_keys.timer_enabled, Boolean(power_user.timer_enabled)); | |
| 3662 | 3522 | switchTimer(); |
| 3523 | + saveSettingsDebounced(); | |
| 3663 | 3524 | }); |
| 3664 | 3525 | |
| 3665 | 3526 | $('#messageTimestampsEnabled').on('input', function () { |
| 3666 | 3527 | const value = !!$(this).prop('checked'); |
| 3667 | 3528 | power_user.timestamps_enabled = value; |
| 3668 | - localStorage.setItem(storage_keys.timestamps_enabled, Boolean(power_user.timestamps_enabled)); | |
| 3669 | 3529 | switchTimestamps(); |
| 3530 | + saveSettingsDebounced(); | |
| 3670 | 3531 | }); |
| 3671 | 3532 | |
| 3672 | 3533 | $('#messageModelIconEnabled').on('input', function () { |
| 3673 | 3534 | const value = !!$(this).prop('checked'); |
| 3674 | 3535 | power_user.timestamp_model_icon = value; |
| 3675 | - localStorage.setItem(storage_keys.timestamp_model_icon, Boolean(power_user.timestamp_model_icon)); | |
| 3676 | 3536 | switchIcons(); |
| 3537 | + saveSettingsDebounced(); | |
| 3677 | 3538 | }); |
| 3678 | 3539 | |
| 3679 | 3540 | $('#messageTokensEnabled').on('input', function () { |
| 3680 | 3541 | const value = !!$(this).prop('checked'); |
| 3681 | 3542 | power_user.message_token_count_enabled = value; |
| 3682 | - localStorage.setItem(storage_keys.message_token_count_enabled, Boolean(power_user.message_token_count_enabled)); | |
| 3683 | 3543 | switchTokenCount(); |
| 3544 | + saveSettingsDebounced(); | |
| 3684 | 3545 | }); |
| 3685 | 3546 | |
| 3686 | 3547 | $('#expandMessageActions').on('input', function () { |
| 3687 | 3548 | const value = !!$(this).prop('checked'); |
| 3688 | 3549 | power_user.expand_message_actions = value; |
| 3689 | - localStorage.setItem(storage_keys.expand_message_actions, Boolean(power_user.expand_message_actions)); | |
| 3690 | 3550 | switchMessageActions(); |
| 3551 | + saveSettingsDebounced(); | |
| 3691 | 3552 | }); |
| 3692 | 3553 | |
| 3693 | 3554 | $('#enableZenSliders').on('input', function () { |
| @@ -3699,9 +3560,8 @@ $(document).ready(() => { | ||
| 3699 | 3560 | return; |
| 3700 | 3561 | } |
| 3701 | 3562 | power_user.enableZenSliders = value; |
| 3702 | - localStorage.setItem(storage_keys.enableZenSliders, Boolean(power_user.enableZenSliders)); | |
| 3703 | - saveSettingsDebounced(); | |
| 3704 | 3563 | switchZenSliders(); |
| 3564 | + saveSettingsDebounced(); | |
| 3705 | 3565 | }); |
| 3706 | 3566 | |
| 3707 | 3567 | $('#enableLabMode').on('input', function () { |
| @@ -3714,30 +3574,29 @@ $(document).ready(() => { | ||
| 3714 | 3574 | } |
| 3715 | 3575 | |
| 3716 | 3576 | power_user.enableLabMode = value; |
| 3717 | - localStorage.setItem(storage_keys.enableLabMode, Boolean(power_user.enableLabMode)); | |
| 3718 | - saveSettingsDebounced(); | |
| 3719 | 3577 | switchLabMode(); |
| 3578 | + saveSettingsDebounced(); | |
| 3720 | 3579 | }); |
| 3721 | 3580 | |
| 3722 | 3581 | $('#mesIDDisplayEnabled').on('input', function () { |
| 3723 | 3582 | const value = !!$(this).prop('checked'); |
| 3724 | 3583 | power_user.mesIDDisplay_enabled = value; |
| 3725 | - localStorage.setItem(storage_keys.mesIDDisplay_enabled, Boolean(power_user.mesIDDisplay_enabled)); | |
| 3726 | 3584 | switchMesIDDisplay(); |
| 3585 | + saveSettingsDebounced(); | |
| 3727 | 3586 | }); |
| 3728 | 3587 | |
| 3729 | 3588 | $('#hideChatAvatarsEnabled').on('input', function () { |
| 3730 | 3589 | const value = !!$(this).prop('checked'); |
| 3731 | 3590 | power_user.hideChatAvatars_enabled = value; |
| 3732 | - localStorage.setItem(storage_keys.hideChatAvatars_enabled, Boolean(power_user.hideChatAvatars_enabled)); | |
| 3733 | 3591 | switchHideChatAvatars(); |
| 3592 | + saveSettingsDebounced(); | |
| 3734 | 3593 | }); |
| 3735 | 3594 | |
| 3736 | 3595 | $('#hotswapEnabled').on('input', function () { |
| 3737 | 3596 | const value = !!$(this).prop('checked'); |
| 3738 | 3597 | power_user.hotswap_enabled = value; |
| 3739 | - localStorage.setItem(storage_keys.hotswap_enabled, Boolean(power_user.hotswap_enabled)); | |
| 3740 | 3598 | switchHotswap(); |
| 3599 | + saveSettingsDebounced(); | |
| 3741 | 3600 | }); |
| 3742 | 3601 | |
| 3743 | 3602 | $('#prefer_character_prompt').on('input', function () { |
| @@ -3845,8 +3704,8 @@ $(document).ready(() => { | ||
| 3845 | 3704 | $('#ui_mode_select').on('change', function () { |
| 3846 | 3705 | const value = $(this).find(':selected').val(); |
| 3847 | 3706 | power_user.ui_mode = Number(value); |
| 3848 | - saveSettingsDebounced(); | |
| 3849 | 3707 | switchSimpleMode(); |
| 3708 | + saveSettingsDebounced(); | |
| 3850 | 3709 | }); |
| 3851 | 3710 | |
| 3852 | 3711 | $('#bogus_folders').on('input', function () { |
| @@ -3950,14 +3809,12 @@ $(document).ready(() => { | ||
| 3950 | 3809 | |
| 3951 | 3810 | $('#reduced_motion').on('input', function () { |
| 3952 | 3811 | power_user.reduced_motion = !!$(this).prop('checked'); |
| 3953 | - localStorage.setItem(storage_keys.reduced_motion, String(power_user.reduced_motion)); | |
| 3954 | 3812 | switchReducedMotion(); |
| 3955 | 3813 | saveSettingsDebounced(); |
| 3956 | 3814 | }); |
| 3957 | 3815 | |
| 3958 | 3816 | $('#compact_input_area').on('input', function () { |
| 3959 | 3817 | power_user.compact_input_area = !!$(this).prop('checked'); |
| 3960 | - localStorage.setItem(storage_keys.compact_input_area, String(power_user.compact_input_area)); | |
| 3961 | 3818 | switchCompactInputArea(); |
| 3962 | 3819 | saveSettingsDebounced(); |
| 3963 | 3820 | }); |
| @@ -8,7 +8,7 @@ export const markdownUnderscoreExt = () => { | ||
| 8 | 8 | |
| 9 | 9 | return [{ |
| 10 | 10 | type: 'output', |
| 11 | 11 | regex: new RegExp('(<code(?:\\s+[^>]*)?>[\\s\\S]*?<\\/code>)|\\b(?<!\\S_)_(?!_)([^_\\n]+.*?)(?<!_)_(?!_)\\w)b', 'g'), |
| 12 | 12 | replace: function(match, codeContent, italicContent) { |
| 13 | 13 | if (codeContent) { |
| 14 | 14 | // If it's inside <code> tags, return unchanged |
| @@ -2147,12 +2147,13 @@ async function generateRawCallback(args, value) { | ||
| 2147 | 2147 | } |
| 2148 | 2148 | } |
| 2149 | 2149 | |
| 2150 | +/** | |
| 2151 | + * Callback for the /gen command | |
| 2152 | + * @param {object} args Named arguments | |
| 2153 | + * @param {string} value Unnamed argument | |
| 2154 | + * @returns {Promise<string>} The generated text | |
| 2155 | + */ | |
| 2150 | 2156 | async function generateCallback(args, value) { |
| 2151 | - if (!value) { | |
| 2152 | - console.warn('WARN: No argument provided for /gen command'); | |
| 2153 | - return; | |
| 2154 | - } | |
| 2155 | - | |
| 2156 | 2157 | // Prevent generate recursion |
| 2157 | 2158 | $('#send_textarea').val('')[0].dispatchEvent(new Event('input', { bubbles: true })); |
| 2158 | 2159 | const lock = isTrueBoolean(args?.lock); |
| @@ -445,7 +445,11 @@ export function getTagKeyForEntity(entityOrKey) { | ||
| 445 | 445 | } |
| 446 | 446 | |
| 447 | 447 | // Next lets check if its a valid character or character id, so we can swith it to its tag |
| 448 | - const character = characters.indexOf(x) >= 0 ? x : characters[x]; | |
| 448 | + let character; | |
| 449 | + if (!character && characters.indexOf(x) >= 0) character = x; // Check for char object | |
| 450 | + if (!character && !isNaN(parseInt(entityOrKey))) character = characters[x]; // check if its a char id | |
| 451 | + if (!character) character = characters.find(y => y.avatar === x); // check if its a char key | |
| 452 | + | |
| 449 | 453 | if (character) { |
| 450 | 454 | x = character.avatar; |
| 451 | 455 | } |
| @@ -722,7 +726,11 @@ async function importTags(character, { importSetting = null } = {}) { | ||
| 722 | 726 | const tagsToImport = tagNamesToImport.map(tag => getTag(tag, { createNew: true })); |
| 723 | 727 | const added = addTagsToEntity(tagsToImport, character.avatar); |
| 724 | 728 | |
| 729 | + if (added) { | |
| 725 | 730 | toastr.success(`Imported tags:<br />${tagsToImport.map(x => x.name).join(', ')}`, 'Importing Tags', { escapeHtml: false }); |
| 731 | + } else { | |
| 732 | + toastr.error(`Couldn't import tags:<br />${tagsToImport.map(x => x.name).join(', ')}`, 'Importing Tags', { escapeHtml: false }); | |
| 733 | + } | |
| 726 | 734 | |
| 727 | 735 | return added; |
| 728 | 736 | } |
| @@ -0,0 +1,6 @@ | ||
| 1 | +<h3 data-i18n="chat_rename_1">Enter the new name for the chat:</h3> | |
| 2 | +<small> | |
| 3 | + <span data-i18n="chat_rename_2">!!Using an existing filename will produce an error!!</span><br> | |
| 4 | + <span data-i18n="chat_rename_3">This will break the link between checkpoint chats.</span><br> | |
| 5 | + <span data-i18n="chat_rename_4">No need to add '.jsonl' at the end.</span><br> | |
| 6 | +</small> | |
| 6 | \ No newline at end of file | |
| @@ -0,0 +1,4 @@ | ||
| 1 | +<label for="del_chat_checkbox" class="checkbox_label justifyCenter" data-i18n="[title]If necessary, you can later restore this chat file from the /backups folder" title="If necessary, you can later restore this chat file from the /backups folder"> | |
| 2 | + <input type="checkbox" id="del_chat_checkbox" /> | |
| 3 | + <small data-i18n="Also delete the current chat file">Also delete the current chat file</small> | |
| 4 | +</label> | |
| 4 | \ No newline at end of file | |
| @@ -0,0 +1 @@ | ||
| 1 | +<span data-i18n="Are you sure you want to connect to the following proxy URL?">Are you sure you want to connect to the following proxy URL?</span><var>{{proxyURL}}</var> | |
| 1 | \ No newline at end of file | |
| @@ -27,6 +27,7 @@ export const tokenizers = { | ||
| 27 | 27 | CLAUDE: 11, |
| 28 | 28 | LLAMA3: 12, |
| 29 | 29 | GEMMA: 13, |
| 30 | + JAMBA: 14, | |
| 30 | 31 | BEST_MATCH: 99, |
| 31 | 32 | }; |
| 32 | 33 | |
| @@ -36,6 +37,7 @@ export const SENTENCEPIECE_TOKENIZERS = [ | ||
| 36 | 37 | tokenizers.YI, |
| 37 | 38 | tokenizers.LLAMA3, |
| 38 | 39 | tokenizers.GEMMA, |
| 40 | + tokenizers.JAMBA, | |
| 39 | 41 | // uncomment when NovelAI releases Kayra and Clio weights, lol |
| 40 | 42 | //tokenizers.NERD, |
| 41 | 43 | //tokenizers.NERD2, |
| @@ -98,6 +100,11 @@ const TOKENIZER_URLS = { | ||
| 98 | 100 | decode: '/api/tokenizers/gemma/decode', |
| 99 | 101 | count: '/api/tokenizers/gemma/encode', |
| 100 | 102 | }, |
| 103 | + [tokenizers.JAMBA]: { | |
| 104 | + encode: '/api/tokenizers/jamba/encode', | |
| 105 | + decode: '/api/tokenizers/jamba/decode', | |
| 106 | + count: '/api/tokenizers/jamba/encode', | |
| 107 | + }, | |
| 101 | 108 | [tokenizers.API_TEXTGENERATIONWEBUI]: { |
| 102 | 109 | encode: '/api/tokenizers/remote/textgenerationwebui/encode', |
| 103 | 110 | count: '/api/tokenizers/remote/textgenerationwebui/encode', |
| @@ -164,7 +171,7 @@ export function getAvailableTokenizers() { | ||
| 164 | 171 | tokenizerId: Number(tokenizerOption.value), |
| 165 | 172 | tokenizerKey: Object.entries(tokenizers).find(([_, value]) => value === Number(tokenizerOption.value))[0].toLocaleLowerCase(), |
| 166 | 173 | tokenizerName: tokenizerOption.text, |
| 167 | 174 | })); |
| 168 | 175 | } |
| 169 | 176 | |
| 170 | 177 | /** |
| @@ -280,6 +287,12 @@ export function getTokenizerBestMatch(forApi) { | ||
| 280 | 287 | if (model.includes('gemma')) { |
| 281 | 288 | return tokenizers.GEMMA; |
| 282 | 289 | } |
| 290 | + if (model.includes('yi')) { | |
| 291 | + return tokenizers.YI; | |
| 292 | + } | |
| 293 | + if (model.includes('jamba')) { | |
| 294 | + return tokenizers.JAMBA; | |
| 295 | + } | |
| 283 | 296 | } |
| 284 | 297 | |
| 285 | 298 | return tokenizers.LLAMA; |
| @@ -497,6 +510,7 @@ export function getTokenizerModel() { | ||
| 497 | 510 | const mistralTokenizer = 'mistral'; |
| 498 | 511 | const yiTokenizer = 'yi'; |
| 499 | 512 | const gemmaTokenizer = 'gemma'; |
| 513 | + const jambaTokenizer = 'jamba'; | |
| 500 | 514 | |
| 501 | 515 | // Assuming no one would use it for different models.. right? |
| 502 | 516 | if (oai_settings.chat_completion_source == chat_completion_sources.SCALE) { |
| @@ -562,12 +576,19 @@ export function getTokenizerModel() { | ||
| 562 | 576 | else if (oai_settings.openrouter_model.includes('GPT-NeoXT')) { |
| 563 | 577 | return gpt2Tokenizer; |
| 564 | 578 | } |
| 579 | + else if (oai_settings.openrouter_model.includes('jamba')) { | |
| 580 | + return jambaTokenizer; | |
| 581 | + } | |
| 565 | 582 | } |
| 566 | 583 | |
| 567 | 584 | if (oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE) { |
| 568 | 585 | return gemmaTokenizer; |
| 569 | 586 | } |
| 570 | 587 | |
| 588 | + if (oai_settings.chat_completion_source == chat_completion_sources.AI21) { | |
| 589 | + return jambaTokenizer; | |
| 590 | + } | |
| 591 | + | |
| 571 | 592 | if (oai_settings.chat_completion_source == chat_completion_sources.CLAUDE) { |
| 572 | 593 | return claudeTokenizer; |
| 573 | 594 | } |
| @@ -626,16 +647,7 @@ export function getTokenizerModel() { | ||
| 626 | 647 | * @deprecated Use countTokensOpenAIAsync instead. |
| 627 | 648 | */ |
| 628 | 649 | export function countTokensOpenAI(messages, full = false) { |
| 629 | - const shouldTokenizeAI21 = oai_settings.chat_completion_source === chat_completion_sources.AI21 && oai_settings.use_ai21_tokenizer; | |
| 650 | + const tokenizerEndpoint = `/api/tokenizers/openai/count?model=${getTokenizerModel()}`; | |
| 630 | - const shouldTokenizeGoogle = oai_settings.chat_completion_source === chat_completion_sources.MAKERSUITE && oai_settings.use_google_tokenizer; | |
| 631 | - let tokenizerEndpoint = ''; | |
| 632 | - if (shouldTokenizeAI21) { | |
| 633 | - tokenizerEndpoint = '/api/tokenizers/ai21/count'; | |
| 634 | - } else if (shouldTokenizeGoogle) { | |
| 635 | - tokenizerEndpoint = `/api/tokenizers/google/count?model=${getTokenizerModel()}&reverse_proxy=${oai_settings.reverse_proxy}&proxy_password=${oai_settings.proxy_password}`; | |
| 636 | - } else { | |
| 637 | - tokenizerEndpoint = `/api/tokenizers/openai/count?model=${getTokenizerModel()}`; | |
| 638 | - } | |
| 639 | 651 | const cacheObject = getTokenCacheObject(); |
| 640 | 652 | |
| 641 | 653 | if (!Array.isArray(messages)) { |
| @@ -647,7 +659,7 @@ export function countTokensOpenAI(messages, full = false) { | ||
| 647 | 659 | for (const message of messages) { |
| 648 | 660 | const model = getTokenizerModel(); |
| 649 | 661 | |
| 650 | 662 | if (model === 'claude' || shouldTokenizeAI21 || shouldTokenizeGoogle) { |
| 651 | 663 | full = true; |
| 652 | 664 | } |
| 653 | 665 | |
| @@ -687,16 +699,7 @@ export function countTokensOpenAI(messages, full = false) { | ||
| 687 | 699 | * @returns {Promise<number>} Token count. |
| 688 | 700 | */ |
| 689 | 701 | export async function countTokensOpenAIAsync(messages, full = false) { |
| 690 | - const shouldTokenizeAI21 = oai_settings.chat_completion_source === chat_completion_sources.AI21 && oai_settings.use_ai21_tokenizer; | |
| 702 | + const tokenizerEndpoint = `/api/tokenizers/openai/count?model=${getTokenizerModel()}`; | |
| 691 | - const shouldTokenizeGoogle = oai_settings.chat_completion_source === chat_completion_sources.MAKERSUITE && oai_settings.use_google_tokenizer; | |
| 692 | - let tokenizerEndpoint = ''; | |
| 693 | - if (shouldTokenizeAI21) { | |
| 694 | - tokenizerEndpoint = '/api/tokenizers/ai21/count'; | |
| 695 | - } else if (shouldTokenizeGoogle) { | |
| 696 | - tokenizerEndpoint = `/api/tokenizers/google/count?model=${getTokenizerModel()}`; | |
| 697 | - } else { | |
| 698 | - tokenizerEndpoint = `/api/tokenizers/openai/count?model=${getTokenizerModel()}`; | |
| 699 | - } | |
| 700 | 703 | const cacheObject = getTokenCacheObject(); |
| 701 | 704 | |
| 702 | 705 | if (!Array.isArray(messages)) { |
| @@ -708,7 +711,7 @@ export async function countTokensOpenAIAsync(messages, full = false) { | ||
| 708 | 711 | for (const message of messages) { |
| 709 | 712 | const model = getTokenizerModel(); |
| 710 | 713 | |
| 711 | 714 | if (model === 'claude' || shouldTokenizeAI21 || shouldTokenizeGoogle) { |
| 712 | 715 | full = true; |
| 713 | 716 | } |
| 714 | 717 | |
| @@ -838,6 +841,7 @@ function getTextgenAPITokenizationParams(str) { | ||
| 838 | 841 | url: getTextGenServer(), |
| 839 | 842 | legacy_api: textgen_settings.legacy_api && (textgen_settings.type === OOBA || textgen_settings.type === APHRODITE), |
| 840 | 843 | vllm_model: textgen_settings.vllm_model, |
| 844 | + aphrodite_model: textgen_settings.aphrodite_model, | |
| 841 | 845 | }; |
| 842 | 846 | } |
| 843 | 847 | |
| @@ -73,6 +73,7 @@ export let world_info_match_whole_words = false; | ||
| 73 | 73 | export let world_info_use_group_scoring = false; |
| 74 | 74 | export let world_info_character_strategy = world_info_insertion_strategy.character_first; |
| 75 | 75 | export let world_info_budget_cap = 0; |
| 76 | +export let world_info_max_recursion_steps = 0; | |
| 76 | 77 | const saveWorldDebounced = debounce(async (name, data) => await _save(name, data), debounce_timeout.relaxed); |
| 77 | 78 | const saveSettingsDebounced = debounce(() => { |
| 78 | 79 | Object.assign(world_info, { globalSelect: selected_world_info }); |
| @@ -710,6 +711,7 @@ export function getWorldInfoSettings() { | ||
| 710 | 711 | world_info_character_strategy, |
| 711 | 712 | world_info_budget_cap, |
| 712 | 713 | world_info_use_group_scoring, |
| 714 | + world_info_max_recursion_steps, | |
| 713 | 715 | }; |
| 714 | 716 | } |
| 715 | 717 | |
| @@ -796,6 +798,8 @@ export function setWorldInfoSettings(settings, data) { | ||
| 796 | 798 | world_info_budget_cap = Number(settings.world_info_budget_cap); |
| 797 | 799 | if (settings.world_info_use_group_scoring !== undefined) |
| 798 | 800 | world_info_use_group_scoring = Boolean(settings.world_info_use_group_scoring); |
| 801 | + if (settings.world_info_max_recursion_steps !== undefined) | |
| 802 | + world_info_max_recursion_steps = Number(settings.world_info_max_recursion_steps); | |
| 799 | 803 | |
| 800 | 804 | // Migrate old settings |
| 801 | 805 | if (world_info_budget > 100) { |
| @@ -844,6 +848,9 @@ export function setWorldInfoSettings(settings, data) { | ||
| 844 | 848 | $('#world_info_budget_cap').val(world_info_budget_cap); |
| 845 | 849 | $('#world_info_budget_cap_counter').val(world_info_budget_cap); |
| 846 | 850 | |
| 851 | + $('#world_info_max_recursion_steps').val(world_info_max_recursion_steps); | |
| 852 | + $('#world_info_max_recursion_steps_counter').val(world_info_max_recursion_steps); | |
| 853 | + | |
| 847 | 854 | world_names = data.world_names?.length ? data.world_names : []; |
| 848 | 855 | |
| 849 | 856 | // Add to existing selected WI if it exists |
| @@ -2459,7 +2466,7 @@ async function getWorldEntry(name, data, entry) { | ||
| 2459 | 2466 | if (!isMobile()) { |
| 2460 | 2467 | $(characterFilter).select2({ |
| 2461 | 2468 | width: '100%', |
| 2462 | 2469 | placeholder: 'AllTie this entry to specific characters willor pullcharacters fromwith thisspecific entry.tags', |
| 2463 | 2470 | allowClear: true, |
| 2464 | 2471 | closeOnSelect: false, |
| 2465 | 2472 | }); |
| @@ -3723,6 +3730,12 @@ export async function checkWorldInfo(chat, maxContext, isDryRun) { | ||
| 3723 | 3730 | console.debug(`[WI] --- SEARCHING ENTRIES (on ${sortedEntries.length} entries) ---`); |
| 3724 | 3731 | |
| 3725 | 3732 | while (scanState) { |
| 3733 | + //if world_info_max_recursion_steps is non-zero min activations are disabled, and vice versa | |
| 3734 | + if (world_info_max_recursion_steps && world_info_max_recursion_steps <= count) { | |
| 3735 | + console.debug('[WI] Search stopped by reaching max recursion steps', world_info_max_recursion_steps); | |
| 3736 | + break; | |
| 3737 | + } | |
| 3738 | + | |
| 3726 | 3739 | // Track how many times the loop has run. May be useful for debugging. |
| 3727 | 3740 | count++; |
| 3728 | 3741 | |
| @@ -4762,8 +4775,13 @@ jQuery(() => { | ||
| 4762 | 4775 | |
| 4763 | 4776 | $('#world_info_min_activations').on('input', function () { |
| 4764 | 4777 | world_info_min_activations = Number($(this).val()); |
| 4765 | 4778 | $('#world_info_min_activations_counter').val($(this).val()world_info_min_activations); |
| 4779 | + | |
| 4780 | + if (world_info_min_activations !== 0) { | |
| 4781 | + $('#world_info_max_recursion_steps').val(0).trigger('input'); | |
| 4782 | + } else { | |
| 4766 | 4783 | saveSettings(); |
| 4784 | + } | |
| 4767 | 4785 | }); |
| 4768 | 4786 | |
| 4769 | 4787 | $('#world_info_min_activations_depth_max').on('input', function () { |
| @@ -4819,6 +4837,16 @@ jQuery(() => { | ||
| 4819 | 4837 | saveSettings(); |
| 4820 | 4838 | }); |
| 4821 | 4839 | |
| 4840 | + $('#world_info_max_recursion_steps').on('input', function () { | |
| 4841 | + world_info_max_recursion_steps = Number($(this).val()); | |
| 4842 | + $('#world_info_max_recursion_steps_counter').val(world_info_max_recursion_steps); | |
| 4843 | + if (world_info_max_recursion_steps !== 0) { | |
| 4844 | + $('#world_info_min_activations').val(0).trigger('input'); | |
| 4845 | + } else { | |
| 4846 | + saveSettings(); | |
| 4847 | + } | |
| 4848 | + }); | |
| 4849 | + | |
| 4822 | 4850 | $('#world_button').on('click', async function (event) { |
| 4823 | 4851 | const chid = $('#set_character_world').data('chid'); |
| 4824 | 4852 | |
| @@ -817,7 +817,7 @@ function createHttpsServer(url) { | ||
| 817 | 817 | }, app); |
| 818 | 818 | server.on('error', reject); |
| 819 | 819 | server.on('listening', resolve); |
| 820 | 820 | server.listen(url.port || 443, url.hostname); |
| 821 | 821 | }); |
| 822 | 822 | } |
| 823 | 823 | |
| @@ -832,7 +832,7 @@ function createHttpServer(url) { | ||
| 832 | 832 | const server = http.createServer(app); |
| 833 | 833 | server.on('error', reject); |
| 834 | 834 | server.on('listening', resolve); |
| 835 | 835 | server.listen(url.port || 80, url.hostname); |
| 836 | 836 | }); |
| 837 | 837 | } |
| 838 | 838 | |
| @@ -0,0 +1,126 @@ | ||
| 1 | +const DATA_PREFIX = 'data:'; | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * Borrowed from Cohere SDK (MIT License) | |
| 5 | + * https://github.com/cohere-ai/cohere-typescript/blob/main/src/core/streaming-fetcher/Stream.ts | |
| 6 | + * Copyright (c) 2021 Cohere | |
| 7 | + */ | |
| 8 | +class CohereStream { | |
| 9 | + /** @type {ReadableStream} */ | |
| 10 | + stream; | |
| 11 | + /** @type {string} */ | |
| 12 | + prefix; | |
| 13 | + /** @type {string} */ | |
| 14 | + messageTerminator; | |
| 15 | + /** @type {string|undefined} */ | |
| 16 | + streamTerminator; | |
| 17 | + /** @type {AbortController} */ | |
| 18 | + controller = new AbortController(); | |
| 19 | + | |
| 20 | + constructor({ stream, eventShape }) { | |
| 21 | + this.stream = stream; | |
| 22 | + if (eventShape.type === 'sse') { | |
| 23 | + this.prefix = DATA_PREFIX; | |
| 24 | + this.messageTerminator = '\n'; | |
| 25 | + this.streamTerminator = eventShape.streamTerminator; | |
| 26 | + } else { | |
| 27 | + this.messageTerminator = eventShape.messageTerminator; | |
| 28 | + } | |
| 29 | + } | |
| 30 | + | |
| 31 | + async *iterMessages() { | |
| 32 | + const stream = readableStreamAsyncIterable(this.stream); | |
| 33 | + let buf = ''; | |
| 34 | + let prefixSeen = false; | |
| 35 | + let parsedAnyMessages = false; | |
| 36 | + for await (const chunk of stream) { | |
| 37 | + buf += this.decodeChunk(chunk); | |
| 38 | + | |
| 39 | + let terminatorIndex; | |
| 40 | + // Parse the chunk into as many messages as possible | |
| 41 | + while ((terminatorIndex = buf.indexOf(this.messageTerminator)) >= 0) { | |
| 42 | + // Extract the line from the buffer | |
| 43 | + let line = buf.slice(0, terminatorIndex + 1); | |
| 44 | + buf = buf.slice(terminatorIndex + 1); | |
| 45 | + | |
| 46 | + // Skip empty lines | |
| 47 | + if (line.length === 0) { | |
| 48 | + continue; | |
| 49 | + } | |
| 50 | + | |
| 51 | + // Skip the chunk until the prefix is found | |
| 52 | + if (!prefixSeen && this.prefix != null) { | |
| 53 | + const prefixIndex = line.indexOf(this.prefix); | |
| 54 | + if (prefixIndex === -1) { | |
| 55 | + continue; | |
| 56 | + } | |
| 57 | + prefixSeen = true; | |
| 58 | + line = line.slice(prefixIndex + this.prefix.length); | |
| 59 | + } | |
| 60 | + | |
| 61 | + // If the stream terminator is present, return | |
| 62 | + if (this.streamTerminator != null && line.includes(this.streamTerminator)) { | |
| 63 | + return; | |
| 64 | + } | |
| 65 | + | |
| 66 | + // Otherwise, yield message from the prefix to the terminator | |
| 67 | + const message = JSON.parse(line); | |
| 68 | + yield message; | |
| 69 | + prefixSeen = false; | |
| 70 | + parsedAnyMessages = true; | |
| 71 | + } | |
| 72 | + } | |
| 73 | + | |
| 74 | + if (!parsedAnyMessages && buf.length > 0) { | |
| 75 | + try { | |
| 76 | + yield JSON.parse(buf); | |
| 77 | + } catch (e) { | |
| 78 | + console.error('Error parsing message:', e); | |
| 79 | + } | |
| 80 | + } | |
| 81 | + } | |
| 82 | + | |
| 83 | + async *[Symbol.asyncIterator]() { | |
| 84 | + for await (const message of this.iterMessages()) { | |
| 85 | + yield message; | |
| 86 | + } | |
| 87 | + } | |
| 88 | + | |
| 89 | + decodeChunk(chunk) { | |
| 90 | + const decoder = new TextDecoder('utf8'); | |
| 91 | + return decoder.decode(chunk); | |
| 92 | + } | |
| 93 | +} | |
| 94 | + | |
| 95 | +function readableStreamAsyncIterable(stream) { | |
| 96 | + if (stream[Symbol.asyncIterator]) { | |
| 97 | + return stream; | |
| 98 | + } | |
| 99 | + | |
| 100 | + const reader = stream.getReader(); | |
| 101 | + return { | |
| 102 | + async next() { | |
| 103 | + try { | |
| 104 | + const result = await reader.read(); | |
| 105 | + if (result?.done) { | |
| 106 | + reader.releaseLock(); | |
| 107 | + } // release lock when stream becomes closed | |
| 108 | + return result; | |
| 109 | + } catch (e) { | |
| 110 | + reader.releaseLock(); // release lock when stream becomes errored | |
| 111 | + throw e; | |
| 112 | + } | |
| 113 | + }, | |
| 114 | + async return() { | |
| 115 | + const cancelPromise = reader.cancel(); | |
| 116 | + reader.releaseLock(); | |
| 117 | + await cancelPromise; | |
| 118 | + return { done: true, value: undefined }; | |
| 119 | + }, | |
| 120 | + [Symbol.asyncIterator]() { | |
| 121 | + return this; | |
| 122 | + }, | |
| 123 | + }; | |
| 124 | +} | |
| 125 | + | |
| 126 | +module.exports = CohereStream; | |
| @@ -1,11 +1,11 @@ | ||
| 1 | 1 | const express = require('express'); |
| 2 | 2 | const fetch = require('node-fetch').default; |
| 3 | -const Readable = require('stream').Readable; | |
| 4 | 3 | |
| 5 | 4 | const { jsonParser } = require('../../express-common'); |
| 6 | 5 | const { CHAT_COMPLETION_SOURCES, GEMINI_SAFETY, BISON_SAFETY, OPENROUTER_HEADERS } = require('../../constants'); |
| 7 | 6 | const { forwardFetchResponse, getConfigValue, tryParse, uuidv4, mergeObjectWithYaml, excludeKeysByYaml, color } = require('../../util'); |
| 8 | 7 | const { convertClaudeMessages, convertGooglePrompt, convertTextCompletionPrompt, convertCohereMessages, convertMistralMessages, convertCohereTools, convertAI21Messages } = require('../../prompt-converters'); |
| 8 | +const CohereStream = require('../../cohere-stream'); | |
| 9 | 9 | |
| 10 | 10 | const { readSecret, SECRET_KEYS } = require('../secrets'); |
| 11 | 11 | const { getTokenizerModel, getSentencepiceTokenizer, getTiktokenTokenizer, sentencepieceTokenizers, TEXT_COMPLETION_MODELS } = require('../tokenizers'); |
| @@ -19,6 +19,7 @@ const API_GROQ = 'https://api.groq.com/openai/v1'; | ||
| 19 | 19 | const API_MAKERSUITE = 'https://generativelanguage.googleapis.com'; |
| 20 | 20 | const API_01AI = 'https://api.01.ai/v1'; |
| 21 | 21 | const API_BLOCKENTROPY = 'https://api.blockentropy.ai/v1'; |
| 22 | +const API_AI21 = 'https://api.ai21.com/studio/v1'; | |
| 22 | 23 | |
| 23 | 24 | /** |
| 24 | 25 | * Applies a post-processing step to the generated messages. |
| @@ -40,52 +41,30 @@ function postProcessPrompt(messages, type, charName, userName) { | ||
| 40 | 41 | /** |
| 41 | 42 | * Ollama strikes back. Special boy #2's steaming routine. |
| 42 | 43 | * Wrap this abomination into proper SSE stream, again. |
| 43 | 44 | * @param {import('node-fetch').Response} jsonStream JSON stream |
| 44 | 45 | * @param {import('express').Request} request Express request |
| 45 | 46 | * @param {import('express').Response} response Express response |
| 46 | 47 | * @returns {Promise<any>} Nothing valuable |
| 47 | 48 | */ |
| 48 | 49 | async function parseCohereStream(jsonStream, request, response) { |
| 49 | 50 | try { |
| 50 | - let partialData = ''; | |
| 51 | + const stream = new CohereStream({ stream: jsonStream.body, eventShape: { type: 'json', messageTerminator: '\n' } }); | |
| 51 | - jsonStream.body.on('data', (data) => { | |
| 52 | + | |
| 52 | - const chunk = data.toString(); | |
| 53 | + for await (const json of stream.iterMessages()) { | |
| 53 | - partialData += chunk; | |
| 54 | - while (true) { | |
| 55 | - let json; | |
| 56 | - try { | |
| 57 | - json = JSON.parse(partialData); | |
| 58 | - } catch (e) { | |
| 59 | - break; | |
| 60 | - } | |
| 61 | 54 | if (json.message) { |
| 62 | 55 | const message = json.message || 'Unknown error'; |
| 63 | 56 | const chunk = { error: { message: message } }; |
| 64 | 57 | response.write(`data: ${JSON.stringify(chunk)}\n\n`); |
| 65 | - partialData = ''; | |
| 66 | - break; | |
| 67 | 58 | } else if (json.event_type === 'text-generation') { |
| 68 | 59 | const text = json.text || ''; |
| 69 | 60 | const chunk = { choices: [{ text }] }; |
| 70 | 61 | response.write(`data: ${JSON.stringify(chunk)}\n\n`); |
| 71 | - partialData = ''; | |
| 72 | - } else { | |
| 73 | - partialData = ''; | |
| 74 | - break; | |
| 75 | 62 | } |
| 76 | 63 | } |
| 77 | - }); | |
| 78 | 64 | |
| 79 | - request.socket.on('close', function () { | |
| 80 | - if (jsonStream.body instanceof Readable) jsonStream.body.destroy(); | |
| 81 | - response.end(); | |
| 82 | - }); | |
| 83 | - | |
| 84 | - jsonStream.body.on('end', () => { | |
| 85 | 65 | console.log('Streaming request finished'); |
| 86 | 66 | response.write('data: [DONE]\n\n'); |
| 87 | 67 | response.end(); |
| 88 | - }); | |
| 89 | 68 | } catch (error) { |
| 90 | 69 | console.log('Error forwarding streaming response:', error); |
| 91 | 70 | if (!response.headersSent) { |
| @@ -233,7 +212,7 @@ async function sendScaleRequest(request, response) { | ||
| 233 | 212 | |
| 234 | 213 | if (!generateResponse.ok) { |
| 235 | 214 | console.log(`Scale API returned error: ${generateResponse.status} ${generateResponse.statusText} ${await generateResponse.text()}`); |
| 236 | 215 | return response.status(generateResponse.status500).send({ error: true }); |
| 237 | 216 | } |
| 238 | 217 | |
| 239 | 218 | const generateResponseJson = await generateResponse.json(); |
| @@ -259,7 +238,7 @@ async function sendMakerSuiteRequest(request, response) { | ||
| 259 | 238 | const apiKey = request.body.reverse_proxy ? request.body.proxy_password : readSecret(request.user.directories, SECRET_KEYS.MAKERSUITE); |
| 260 | 239 | |
| 261 | 240 | if (!request.body.reverse_proxy && !apiKey) { |
| 262 | 241 | console.log('MakerSuiteGoogle AI Studio API key is missing.'); |
| 263 | 242 | return response.status(400).send({ error: true }); |
| 264 | 243 | } |
| 265 | 244 | |
| @@ -326,7 +305,7 @@ async function sendMakerSuiteRequest(request, response) { | ||
| 326 | 305 | } |
| 327 | 306 | |
| 328 | 307 | const body = isGemini ? getGeminiBody() : getBisonBody(); |
| 329 | 308 | console.log('MakerSuiteGoogle AI Studio request:', body); |
| 330 | 309 | |
| 331 | 310 | try { |
| 332 | 311 | const controller = new AbortController(); |
| @@ -362,7 +341,7 @@ async function sendMakerSuiteRequest(request, response) { | ||
| 362 | 341 | } |
| 363 | 342 | } else { |
| 364 | 343 | if (!generateResponse.ok) { |
| 365 | 344 | console.log(`MakerSuiteGoogle AI Studio API returned error: ${generateResponse.status} ${generateResponse.statusText} ${await generateResponse.text()}`); |
| 366 | 345 | return response.status(generateResponse.status).send({ error: true }); |
| 367 | 346 | } |
| 368 | 347 | |
| @@ -370,7 +349,7 @@ async function sendMakerSuiteRequest(request, response) { | ||
| 370 | 349 | |
| 371 | 350 | const candidates = generateResponseJson?.candidates; |
| 372 | 351 | if (!candidates || candidates.length === 0) { |
| 373 | 352 | let message = 'MakerSuiteGoogle AI Studio API returned no candidate'; |
| 374 | 353 | console.log(message, generateResponseJson); |
| 375 | 354 | if (generateResponseJson?.promptFeedback?.blockReason) { |
| 376 | 355 | message += `\nPrompt was blocked due to : ${generateResponseJson.promptFeedback.blockReason}`; |
| @@ -381,19 +360,19 @@ async function sendMakerSuiteRequest(request, response) { | ||
| 381 | 360 | const responseContent = candidates[0].content ?? candidates[0].output; |
| 382 | 361 | const responseText = typeof responseContent === 'string' ? responseContent : responseContent?.parts?.[0]?.text; |
| 383 | 362 | if (!responseText) { |
| 384 | 363 | let message = 'MakerSuiteGoogle AI Studio Candidate text empty'; |
| 385 | 364 | console.log(message, generateResponseJson); |
| 386 | 365 | return response.send({ error: { message } }); |
| 387 | 366 | } |
| 388 | 367 | |
| 389 | 368 | console.log('MakerSuiteGoogle AI Studio response:', responseText); |
| 390 | 369 | |
| 391 | 370 | // Wrap it back to OAI format |
| 392 | 371 | const reply = { choices: [{ 'message': { 'content': responseText } }] }; |
| 393 | 372 | return response.send(reply); |
| 394 | 373 | } |
| 395 | 374 | } catch (error) { |
| 396 | 375 | console.log('Error communicating with MakerSuiteGoogle AI Studio API: ', error); |
| 397 | 376 | if (!response.headersSent) { |
| 398 | 377 | return response.status(500).send({ error: true }); |
| 399 | 378 | } |
| @@ -413,6 +392,16 @@ async function sendAI21Request(request, response) { | ||
| 413 | 392 | request.socket.on('close', function () { |
| 414 | 393 | controller.abort(); |
| 415 | 394 | }); |
| 395 | + const convertedPrompt = convertAI21Messages(request.body.messages, request.body.char_name, request.body.user_name); | |
| 396 | + const body = { | |
| 397 | + messages: convertedPrompt, | |
| 398 | + model: request.body.model, | |
| 399 | + max_tokens: request.body.max_tokens, | |
| 400 | + temperature: request.body.temperature, | |
| 401 | + top_p: request.body.top_p, | |
| 402 | + stop: request.body.stop, | |
| 403 | + stream: request.body.stream, | |
| 404 | + }; | |
| 416 | 405 | const options = { |
| 417 | 406 | method: 'POST', |
| 418 | 407 | headers: { |
| @@ -420,59 +409,35 @@ async function sendAI21Request(request, response) { | ||
| 420 | 409 | 'content-type': 'application/json', |
| 421 | 410 | Authorization: `Bearer ${readSecret(request.user.directories, SECRET_KEYS.AI21)}`, |
| 422 | 411 | }, |
| 423 | 412 | body: JSON.stringify({body), |
| 424 | - numResults: 1, | |
| 425 | - maxTokens: request.body.max_tokens, | |
| 426 | - minTokens: 0, | |
| 427 | - temperature: request.body.temperature, | |
| 428 | - topP: request.body.top_p, | |
| 429 | - stopSequences: request.body.stop_tokens, | |
| 430 | - topKReturn: request.body.top_k, | |
| 431 | - frequencyPenalty: { | |
| 432 | - scale: request.body.frequency_penalty * 100, | |
| 433 | - applyToWhitespaces: false, | |
| 434 | - applyToPunctuations: false, | |
| 435 | - applyToNumbers: false, | |
| 436 | - applyToStopwords: false, | |
| 437 | - applyToEmojis: false, | |
| 438 | - }, | |
| 439 | - presencePenalty: { | |
| 440 | - scale: request.body.presence_penalty, | |
| 441 | - applyToWhitespaces: false, | |
| 442 | - applyToPunctuations: false, | |
| 443 | - applyToNumbers: false, | |
| 444 | - applyToStopwords: false, | |
| 445 | - applyToEmojis: false, | |
| 446 | - }, | |
| 447 | - countPenalty: { | |
| 448 | - scale: request.body.count_pen, | |
| 449 | - applyToWhitespaces: false, | |
| 450 | - applyToPunctuations: false, | |
| 451 | - applyToNumbers: false, | |
| 452 | - applyToStopwords: false, | |
| 453 | - applyToEmojis: false, | |
| 454 | - }, | |
| 455 | - prompt: request.body.messages, | |
| 456 | - }), | |
| 457 | 413 | signal: controller.signal, |
| 458 | 414 | }; |
| 459 | 415 | |
| 460 | - fetch(`https://api.ai21.com/studio/v1/${request.body.model}/complete`, options) | |
| 416 | + console.log('AI21 request:', body); | |
| 461 | - .then(r => r.json()) | |
| 417 | + | |
| 462 | - .then(r => { | |
| 418 | + try { | |
| 463 | - if (r.completions === undefined) { | |
| 419 | + const generateResponse = await fetch(API_AI21 + '/chat/completions', options); | |
| 464 | - console.log(r); | |
| 420 | + if (request.body.stream) { | |
| 421 | + forwardFetchResponse(generateResponse, response); | |
| 465 | 422 | } else { |
| 466 | - console.log(r.completions[0].data.text); | |
| 423 | + if (!generateResponse.ok) { | |
| 424 | + const errorText = await generateResponse.text(); | |
| 425 | + console.log(`AI21 API returned error: ${generateResponse.status} ${generateResponse.statusText} ${errorText}`); | |
| 426 | + const errorJson = tryParse(errorText) ?? { error: true }; | |
| 427 | + return response.status(500).send(errorJson); | |
| 428 | + } | |
| 429 | + const generateResponseJson = await generateResponse.json(); | |
| 430 | + console.log('AI21 response:', generateResponseJson); | |
| 431 | + return response.send(generateResponseJson); | |
| 432 | + } | |
| 433 | + } catch (error) { | |
| 434 | + console.log('Error communicating with AI21 API: ', error); | |
| 435 | + if (!response.headersSent) { | |
| 436 | + response.send({ error: true }); | |
| 437 | + } else { | |
| 438 | + response.end(); | |
| 439 | + } | |
| 467 | 440 | } |
| 468 | - const reply = { choices: [{ 'message': { 'content': r.completions?.[0]?.data?.text } }] }; | |
| 469 | - return response.send(reply); | |
| 470 | - }) | |
| 471 | - .catch(err => { | |
| 472 | - console.error(err); | |
| 473 | - return response.send({ error: true }); | |
| 474 | - }); | |
| 475 | - | |
| 476 | 441 | } |
| 477 | 442 | |
| 478 | 443 | /** |
| @@ -531,10 +496,10 @@ async function sendMistralAIRequest(request, response) { | ||
| 531 | 496 | forwardFetchResponse(generateResponse, response); |
| 532 | 497 | } else { |
| 533 | 498 | if (!generateResponse.ok) { |
| 534 | - console.log(`MistralAI API returned error: ${generateResponse.status} ${generateResponse.statusText} ${await generateResponse.text()}`); | |
| 499 | + const errorText = await generateResponse.text(); | |
| 535 | - // a 401 unauthorized response breaks the frontend auth, so return a 500 instead. prob a better way of dealing with this. | |
| 500 | + console.log(`MistralAI API returned error: ${generateResponse.status} ${generateResponse.statusText} ${errorText}`); | |
| 536 | - // 401s are already handled by the streaming processor and dont pop up an error toast, that should probably be fixed too. | |
| 501 | + const errorJson = tryParse(errorText) ?? { error: true }; | |
| 537 | 502 | return response.status(generateResponse.status === 401 ? 500 : generateResponse.status).send({ error: true }errorJson); |
| 538 | 503 | } |
| 539 | 504 | const generateResponseJson = await generateResponse.json(); |
| 540 | 505 | console.log('MistralAI response:', generateResponseJson); |
| @@ -607,6 +572,11 @@ async function sendCohereRequest(request, response) { | ||
| 607 | 572 | search_queries_only: false, |
| 608 | 573 | }; |
| 609 | 574 | |
| 575 | + const canDoSafetyMode = String(request.body.model).endsWith('08-2024'); | |
| 576 | + if (canDoSafetyMode) { | |
| 577 | + requestBody.safety_mode = 'NONE'; | |
| 578 | + } | |
| 579 | + | |
| 610 | 580 | console.log('Cohere request:', requestBody); |
| 611 | 581 | |
| 612 | 582 | const config = { |
| @@ -623,15 +593,15 @@ async function sendCohereRequest(request, response) { | ||
| 623 | 593 | const apiUrl = API_COHERE + '/chat'; |
| 624 | 594 | |
| 625 | 595 | if (request.body.stream) { |
| 626 | 596 | const stream = await global.fetch(apiUrl, config); |
| 627 | 597 | parseCohereStream(stream, request, response); |
| 628 | 598 | } else { |
| 629 | 599 | const generateResponse = await fetch(apiUrl, config); |
| 630 | 600 | if (!generateResponse.ok) { |
| 631 | - console.log(`Cohere API returned error: ${generateResponse.status} ${generateResponse.statusText} ${await generateResponse.text()}`); | |
| 601 | + const errorText = await generateResponse.text(); | |
| 632 | - // a 401 unauthorized response breaks the frontend auth, so return a 500 instead. prob a better way of dealing with this. | |
| 602 | + console.log(`Cohere API returned error: ${generateResponse.status} ${generateResponse.statusText} ${errorText}`); | |
| 633 | - // 401s are already handled by the streaming processor and dont pop up an error toast, that should probably be fixed too. | |
| 603 | + const errorJson = tryParse(errorText) ?? { error: true }; | |
| 634 | 604 | return response.status(generateResponse.status === 401 ? 500 : generateResponse.status).send({ error: true }errorJson); |
| 635 | 605 | } |
| 636 | 606 | const generateResponseJson = await generateResponse.json(); |
| 637 | 607 | console.log('Cohere response:', generateResponseJson); |
| @@ -44,7 +44,7 @@ router.post('/caption-image', jsonParser, async (request, response) => { | ||
| 44 | 44 | |
| 45 | 45 | if (!result.ok) { |
| 46 | 46 | const error = await result.json(); |
| 47 | 47 | console.log(`MakerSuiteGoogle AI Studio API returned error: ${result.status} ${result.statusText}`, error); |
| 48 | 48 | return response.status(result.status).send({ error: true }); |
| 49 | 49 | } |
| 50 | 50 | |
| @@ -6,6 +6,7 @@ const { readAllChunks, extractFileFromZipBuffer, forwardFetchResponse } = requir | ||
| 6 | 6 | const { jsonParser } = require('../express-common'); |
| 7 | 7 | |
| 8 | 8 | const API_NOVELAI = 'https://api.novelai.net'; |
| 9 | +const TEXT_NOVELAI = 'https://text.novelai.net'; | |
| 9 | 10 | const IMAGE_NOVELAI = 'https://image.novelai.net'; |
| 10 | 11 | |
| 11 | 12 | // Ban bracket generation, plus defaults |
| @@ -155,7 +156,7 @@ router.post('/generate', jsonParser, async function (req, res) { | ||
| 155 | 156 | 'repetition_penalty_slope': req.body.repetition_penalty_slope, |
| 156 | 157 | 'repetition_penalty_frequency': req.body.repetition_penalty_frequency, |
| 157 | 158 | 'repetition_penalty_presence': req.body.repetition_penalty_presence, |
| 158 | 159 | 'repetition_penalty_whitelist': isNewModel ? repPenaltyAllowList.flat() : null, |
| 159 | 160 | 'top_a': req.body.top_a, |
| 160 | 161 | 'top_p': req.body.top_p, |
| 161 | 162 | 'top_k': req.body.top_k, |
| @@ -178,9 +179,7 @@ router.post('/generate', jsonParser, async function (req, res) { | ||
| 178 | 179 | }; |
| 179 | 180 | |
| 180 | 181 | // Tells the model to stop generation at '>' |
| 181 | 182 | if ('theme_textadventure' === req.body.prefix && isNewModel) { |
| 182 | - (true === req.body.model.includes('clio') || | |
| 183 | - true === req.body.model.includes('kayra'))) { | |
| 184 | 183 | data.parameters.eos_token_id = 49405; |
| 185 | 184 | } |
| 186 | 185 | |
| @@ -193,7 +192,8 @@ router.post('/generate', jsonParser, async function (req, res) { | ||
| 193 | 192 | }; |
| 194 | 193 | |
| 195 | 194 | try { |
| 196 | 195 | const urlbaseURL = req.body.streamingmodel.includes('kayra') ? `${API_NOVELAI}/ai/generate-stream`TEXT_NOVELAI : `${API_NOVELAI}/ai/generate`; |
| 196 | + const url = req.body.streaming ? `${baseURL}/ai/generate-stream` : `${baseURL}/ai/generate`; | |
| 197 | 197 | const response = await fetch(url, { method: 'POST', timeout: 0, ...args }); |
| 198 | 198 | |
| 199 | 199 | if (req.body.streaming) { |
| @@ -9,6 +9,7 @@ const { jsonParser } = require('../express-common'); | ||
| 9 | 9 | const { getAllUserHandles, getUserDirectories } = require('../users'); |
| 10 | 10 | |
| 11 | 11 | const ENABLE_EXTENSIONS = getConfigValue('enableExtensions', true); |
| 12 | +const ENABLE_EXTENSIONS_AUTO_UPDATE = getConfigValue('enableExtensionsAutoUpdate', true); | |
| 12 | 13 | const ENABLE_ACCOUNTS = getConfigValue('enableUserAccounts', false); |
| 13 | 14 | |
| 14 | 15 | // 10 minutes |
| @@ -268,6 +269,7 @@ router.post('/get', jsonParser, (request, response) => { | ||
| 268 | 269 | instruct, |
| 269 | 270 | context, |
| 270 | 271 | enable_extensions: ENABLE_EXTENSIONS, |
| 272 | + enable_extensions_auto_update: ENABLE_EXTENSIONS_AUTO_UPDATE, | |
| 271 | 273 | enable_accounts: ENABLE_ACCOUNTS, |
| 272 | 274 | }); |
| 273 | 275 | }); |
| @@ -991,11 +991,52 @@ blockentropy.post('/generate', jsonParser, async (request, response) => { | ||
| 991 | 991 | }); |
| 992 | 992 | |
| 993 | 993 | |
| 994 | +const huggingface = express.Router(); | |
| 995 | + | |
| 996 | +huggingface.post('/generate', jsonParser, async (request, response) => { | |
| 997 | + try { | |
| 998 | + const key = readSecret(request.user.directories, SECRET_KEYS.HUGGINGFACE); | |
| 999 | + | |
| 1000 | + if (!key) { | |
| 1001 | + console.log('Hugging Face key not found.'); | |
| 1002 | + return response.sendStatus(400); | |
| 1003 | + } | |
| 1004 | + | |
| 1005 | + console.log('Hugging Face request:', request.body); | |
| 1006 | + | |
| 1007 | + const result = await fetch(`https://api-inference.huggingface.co/models/${request.body.model}`, { | |
| 1008 | + method: 'POST', | |
| 1009 | + body: JSON.stringify({ | |
| 1010 | + inputs: request.body.prompt, | |
| 1011 | + }), | |
| 1012 | + headers: { | |
| 1013 | + 'Content-Type': 'application/json', | |
| 1014 | + 'Authorization': `Bearer ${key}`, | |
| 1015 | + }, | |
| 1016 | + }); | |
| 1017 | + | |
| 1018 | + if (!result.ok) { | |
| 1019 | + console.log('Hugging Face returned an error.'); | |
| 1020 | + return response.sendStatus(500); | |
| 1021 | + } | |
| 1022 | + | |
| 1023 | + const buffer = await result.buffer(); | |
| 1024 | + return response.send({ | |
| 1025 | + image: buffer.toString('base64'), | |
| 1026 | + }); | |
| 1027 | + } catch (error) { | |
| 1028 | + console.log(error); | |
| 1029 | + return response.sendStatus(500); | |
| 1030 | + } | |
| 1031 | +}); | |
| 1032 | + | |
| 1033 | + | |
| 994 | 1034 | router.use('/comfy', comfy); |
| 995 | 1035 | router.use('/together', together); |
| 996 | 1036 | router.use('/drawthings', drawthings); |
| 997 | 1037 | router.use('/pollinations', pollinations); |
| 998 | 1038 | router.use('/stability', stability); |
| 999 | 1039 | router.use('/blockentropy', blockentropy); |
| 1040 | +router.use('/huggingface', huggingface); | |
| 1000 | 1041 | |
| 1001 | 1042 | module.exports = { router }; |
| @@ -144,6 +144,7 @@ const spp_nerd_v2 = new SentencePieceTokenizer('src/tokenizers/nerdstash_v2.mode | ||
| 144 | 144 | const spp_mistral = new SentencePieceTokenizer('src/tokenizers/mistral.model'); |
| 145 | 145 | const spp_yi = new SentencePieceTokenizer('src/tokenizers/yi.model'); |
| 146 | 146 | const spp_gemma = new SentencePieceTokenizer('src/tokenizers/gemma.model'); |
| 147 | +const spp_jamba = new SentencePieceTokenizer('src/tokenizers/jamba.model'); | |
| 147 | 148 | const claude_tokenizer = new WebTokenizer('src/tokenizers/claude.json'); |
| 148 | 149 | const llama3_tokenizer = new WebTokenizer('src/tokenizers/llama3.json'); |
| 149 | 150 | |
| @@ -154,6 +155,7 @@ const sentencepieceTokenizers = [ | ||
| 154 | 155 | 'mistral', |
| 155 | 156 | 'yi', |
| 156 | 157 | 'gemma', |
| 158 | + 'jamba', | |
| 157 | 159 | ]; |
| 158 | 160 | |
| 159 | 161 | /** |
| @@ -186,6 +188,10 @@ function getSentencepiceTokenizer(model) { | ||
| 186 | 188 | return spp_gemma; |
| 187 | 189 | } |
| 188 | 190 | |
| 191 | + if (model.includes('jamba')) { | |
| 192 | + return spp_jamba; | |
| 193 | + } | |
| 194 | + | |
| 189 | 195 | return null; |
| 190 | 196 | } |
| 191 | 197 | |
| @@ -322,6 +328,10 @@ function getTokenizerModel(requestModel) { | ||
| 322 | 328 | return 'gemma'; |
| 323 | 329 | } |
| 324 | 330 | |
| 331 | + if (requestModel.includes('jamba')) { | |
| 332 | + return 'jamba'; | |
| 333 | + } | |
| 334 | + | |
| 325 | 335 | // default |
| 326 | 336 | return 'gpt-3.5-turbo'; |
| 327 | 337 | } |
| @@ -537,59 +547,13 @@ function createWebTokenizerDecodingHandler(tokenizer) { | ||
| 537 | 547 | |
| 538 | 548 | const router = express.Router(); |
| 539 | 549 | |
| 540 | -router.post('/ai21/count', jsonParser, async function (req, res) { | |
| 541 | - if (!req.body) return res.sendStatus(400); | |
| 542 | - const key = readSecret(req.user.directories, SECRET_KEYS.AI21); | |
| 543 | - const options = { | |
| 544 | - method: 'POST', | |
| 545 | - headers: { | |
| 546 | - accept: 'application/json', | |
| 547 | - 'content-type': 'application/json', | |
| 548 | - Authorization: `Bearer ${key}`, | |
| 549 | - }, | |
| 550 | - body: JSON.stringify({ text: req.body[0].content }), | |
| 551 | - }; | |
| 552 | - | |
| 553 | - try { | |
| 554 | - const response = await fetch('https://api.ai21.com/studio/v1/tokenize', options); | |
| 555 | - const data = await response.json(); | |
| 556 | - return res.send({ 'token_count': data?.tokens?.length || 0 }); | |
| 557 | - } catch (err) { | |
| 558 | - console.error(err); | |
| 559 | - return res.send({ 'token_count': 0 }); | |
| 560 | - } | |
| 561 | -}); | |
| 562 | - | |
| 563 | -router.post('/google/count', jsonParser, async function (req, res) { | |
| 564 | - if (!req.body) return res.sendStatus(400); | |
| 565 | - const options = { | |
| 566 | - method: 'POST', | |
| 567 | - headers: { | |
| 568 | - accept: 'application/json', | |
| 569 | - 'content-type': 'application/json', | |
| 570 | - }, | |
| 571 | - body: JSON.stringify({ contents: convertGooglePrompt(req.body, String(req.query.model)).contents }), | |
| 572 | - }; | |
| 573 | - try { | |
| 574 | - const reverseProxy = req.query.reverse_proxy?.toString() || ''; | |
| 575 | - const proxyPassword = req.query.proxy_password?.toString() || ''; | |
| 576 | - const apiKey = reverseProxy ? proxyPassword : readSecret(req.user.directories, SECRET_KEYS.MAKERSUITE); | |
| 577 | - const apiUrl = new URL(reverseProxy || API_MAKERSUITE); | |
| 578 | - const response = await fetch(`${apiUrl.origin}/v1beta/models/${req.query.model}:countTokens?key=${apiKey}`, options); | |
| 579 | - const data = await response.json(); | |
| 580 | - return res.send({ 'token_count': data?.totalTokens || 0 }); | |
| 581 | - } catch (err) { | |
| 582 | - console.error(err); | |
| 583 | - return res.send({ 'token_count': 0 }); | |
| 584 | - } | |
| 585 | -}); | |
| 586 | - | |
| 587 | 550 | router.post('/llama/encode', jsonParser, createSentencepieceEncodingHandler(spp_llama)); |
| 588 | 551 | router.post('/nerdstash/encode', jsonParser, createSentencepieceEncodingHandler(spp_nerd)); |
| 589 | 552 | router.post('/nerdstash_v2/encode', jsonParser, createSentencepieceEncodingHandler(spp_nerd_v2)); |
| 590 | 553 | router.post('/mistral/encode', jsonParser, createSentencepieceEncodingHandler(spp_mistral)); |
| 591 | 554 | router.post('/yi/encode', jsonParser, createSentencepieceEncodingHandler(spp_yi)); |
| 592 | 555 | router.post('/gemma/encode', jsonParser, createSentencepieceEncodingHandler(spp_gemma)); |
| 556 | +router.post('/jamba/encode', jsonParser, createSentencepieceEncodingHandler(spp_jamba)); | |
| 593 | 557 | router.post('/gpt2/encode', jsonParser, createTiktokenEncodingHandler('gpt2')); |
| 594 | 558 | router.post('/claude/encode', jsonParser, createWebTokenizerEncodingHandler(claude_tokenizer)); |
| 595 | 559 | router.post('/llama3/encode', jsonParser, createWebTokenizerEncodingHandler(llama3_tokenizer)); |
| @@ -599,6 +563,7 @@ router.post('/nerdstash_v2/decode', jsonParser, createSentencepieceDecodingHandl | ||
| 599 | 563 | router.post('/mistral/decode', jsonParser, createSentencepieceDecodingHandler(spp_mistral)); |
| 600 | 564 | router.post('/yi/decode', jsonParser, createSentencepieceDecodingHandler(spp_yi)); |
| 601 | 565 | router.post('/gemma/decode', jsonParser, createSentencepieceDecodingHandler(spp_gemma)); |
| 566 | +router.post('/jamba/decode', jsonParser, createSentencepieceDecodingHandler(spp_jamba)); | |
| 602 | 567 | router.post('/gpt2/decode', jsonParser, createTiktokenDecodingHandler('gpt2')); |
| 603 | 568 | router.post('/claude/decode', jsonParser, createWebTokenizerDecodingHandler(claude_tokenizer)); |
| 604 | 569 | router.post('/llama3/decode', jsonParser, createWebTokenizerDecodingHandler(llama3_tokenizer)); |
| @@ -637,6 +602,11 @@ router.post('/openai/encode', jsonParser, async function (req, res) { | ||
| 637 | 602 | return handler(req, res); |
| 638 | 603 | } |
| 639 | 604 | |
| 605 | + if (queryModel.includes('jamba')) { | |
| 606 | + const handler = createSentencepieceEncodingHandler(spp_jamba); | |
| 607 | + return handler(req, res); | |
| 608 | + } | |
| 609 | + | |
| 640 | 610 | const model = getTokenizerModel(queryModel); |
| 641 | 611 | const handler = createTiktokenEncodingHandler(model); |
| 642 | 612 | return handler(req, res); |
| @@ -680,6 +650,11 @@ router.post('/openai/decode', jsonParser, async function (req, res) { | ||
| 680 | 650 | return handler(req, res); |
| 681 | 651 | } |
| 682 | 652 | |
| 653 | + if (queryModel.includes('jamba')) { | |
| 654 | + const handler = createSentencepieceDecodingHandler(spp_jamba); | |
| 655 | + return handler(req, res); | |
| 656 | + } | |
| 657 | + | |
| 683 | 658 | const model = getTokenizerModel(queryModel); |
| 684 | 659 | const handler = createTiktokenDecodingHandler(model); |
| 685 | 660 | return handler(req, res); |
| @@ -731,6 +706,11 @@ router.post('/openai/count', jsonParser, async function (req, res) { | ||
| 731 | 706 | return res.send({ 'token_count': num_tokens }); |
| 732 | 707 | } |
| 733 | 708 | |
| 709 | + if (model === 'jamba') { | |
| 710 | + num_tokens = await countSentencepieceArrayTokens(spp_jamba, req.body); | |
| 711 | + return res.send({ 'token_count': num_tokens }); | |
| 712 | + } | |
| 713 | + | |
| 734 | 714 | const tokensPerName = queryModel.includes('gpt-3.5-turbo-0301') ? -1 : 1; |
| 735 | 715 | const tokensPerMessage = queryModel.includes('gpt-3.5-turbo-0301') ? 4 : 3; |
| 736 | 716 | const tokensPadding = 3; |
| @@ -812,6 +792,7 @@ router.post('/remote/textgenerationwebui/encode', jsonParser, async function (re | ||
| 812 | 792 | const baseUrl = String(request.body.url); |
| 813 | 793 | const legacyApi = Boolean(request.body.legacy_api); |
| 814 | 794 | const vllmModel = String(request.body.vllm_model) || ''; |
| 795 | + const aphroditeModel = String(request.body.aphrodite_model) || ''; | |
| 815 | 796 | |
| 816 | 797 | try { |
| 817 | 798 | const args = { |
| @@ -847,7 +828,7 @@ router.post('/remote/textgenerationwebui/encode', jsonParser, async function (re | ||
| 847 | 828 | break; |
| 848 | 829 | case TEXTGEN_TYPES.APHRODITE: |
| 849 | 830 | url += '/v1/tokenize'; |
| 850 | 831 | args.body = JSON.stringify({ 'model': aphroditeModel, 'prompt': text }); |
| 851 | 832 | break; |
| 852 | 833 | default: |
| 853 | 834 | url += '/v1/internal/encode'; |
| @@ -110,6 +110,7 @@ router.post('/google', jsonParser, async (request, response) => { | ||
| 110 | 110 | }); |
| 111 | 111 | |
| 112 | 112 | router.post('/yandex', jsonParser, async (request, response) => { |
| 113 | + try { | |
| 113 | 114 | const chunks = request.body.chunks; |
| 114 | 115 | const lang = request.body.lang; |
| 115 | 116 | |
| @@ -130,7 +131,6 @@ router.post('/yandex', jsonParser, async (request, response) => { | ||
| 130 | 131 | |
| 131 | 132 | console.log('Input text: ' + inputText); |
| 132 | 133 | |
| 133 | - try { | |
| 134 | 134 | const result = await fetch(`https://translate.yandex.net/api/v1/tr.json/translate?ucid=${ucid}&srv=android&format=text`, { |
| 135 | 135 | method: 'POST', |
| 136 | 136 | body: params, |
| @@ -267,10 +267,13 @@ function convertGooglePrompt(messages, model, useSysPrompt = false, charName = ' | ||
| 267 | 267 | 'gemini-1.5-flash', |
| 268 | 268 | 'gemini-1.5-flash-latest', |
| 269 | 269 | 'gemini-1.5-flash-001', |
| 270 | + 'gemini-1.5-flash-exp-0827', | |
| 271 | + 'gemini-1.5-flash-8b-exp-0827', | |
| 270 | 272 | 'gemini-1.5-pro', |
| 271 | 273 | 'gemini-1.5-pro-latest', |
| 272 | 274 | 'gemini-1.5-pro-001', |
| 273 | 275 | 'gemini-1.5-pro-exp-0801', |
| 276 | + 'gemini-1.5-pro-exp-0827', | |
| 274 | 277 | 'gemini-1.0-pro-vision-latest', |
| 275 | 278 | 'gemini-pro-vision', |
| 276 | 279 | ]; |
| @@ -368,6 +371,78 @@ function convertGooglePrompt(messages, model, useSysPrompt = false, charName = ' | ||
| 368 | 371 | } |
| 369 | 372 | |
| 370 | 373 | /** |
| 374 | + * Convert AI21 prompt. Classic: system message squash, user/assistant message merge. | |
| 375 | + * @param {object[]} messages Array of messages | |
| 376 | + * @param {string} charName Character name | |
| 377 | + * @param {string} userName User name | |
| 378 | + */ | |
| 379 | +function convertAI21Messages(messages, charName = '', userName = '') { | |
| 380 | + if (!Array.isArray(messages)) { | |
| 381 | + return []; | |
| 382 | + } | |
| 383 | + | |
| 384 | + // Collect all the system messages up until the first instance of a non-system message, and then remove them from the messages array. | |
| 385 | + let i = 0, systemPrompt = ''; | |
| 386 | + | |
| 387 | + for (i = 0; i < messages.length; i++) { | |
| 388 | + if (messages[i].role !== 'system') { | |
| 389 | + break; | |
| 390 | + } | |
| 391 | + // Append example names if not already done by the frontend (e.g. for group chats). | |
| 392 | + if (userName && messages[i].name === 'example_user') { | |
| 393 | + if (!messages[i].content.startsWith(`${userName}: `)) { | |
| 394 | + messages[i].content = `${userName}: ${messages[i].content}`; | |
| 395 | + } | |
| 396 | + } | |
| 397 | + if (charName && messages[i].name === 'example_assistant') { | |
| 398 | + if (!messages[i].content.startsWith(`${charName}: `)) { | |
| 399 | + messages[i].content = `${charName}: ${messages[i].content}`; | |
| 400 | + } | |
| 401 | + } | |
| 402 | + systemPrompt += `${messages[i].content}\n\n`; | |
| 403 | + } | |
| 404 | + | |
| 405 | + messages.splice(0, i); | |
| 406 | + | |
| 407 | + // Prevent erroring out if the messages array is empty. | |
| 408 | + if (messages.length === 0) { | |
| 409 | + messages.unshift({ | |
| 410 | + role: 'user', | |
| 411 | + content: '[Start a new chat]', | |
| 412 | + }); | |
| 413 | + } | |
| 414 | + | |
| 415 | + if (systemPrompt) { | |
| 416 | + messages.unshift({ | |
| 417 | + role: 'system', | |
| 418 | + content: systemPrompt.trim(), | |
| 419 | + }); | |
| 420 | + } | |
| 421 | + | |
| 422 | + // Doesn't support completion names, so prepend if not already done by the frontend (e.g. for group chats). | |
| 423 | + messages.forEach(msg => { | |
| 424 | + if ('name' in msg) { | |
| 425 | + if (msg.role !== 'system' && !msg.content.startsWith(`${msg.name}: `)) { | |
| 426 | + msg.content = `${msg.name}: ${msg.content}`; | |
| 427 | + } | |
| 428 | + delete msg.name; | |
| 429 | + } | |
| 430 | + }); | |
| 431 | + | |
| 432 | + // Since the messaging endpoint only supports alternating turns, we have to merge messages with the same role if they follow each other | |
| 433 | + let mergedMessages = []; | |
| 434 | + messages.forEach((message) => { | |
| 435 | + if (mergedMessages.length > 0 && mergedMessages[mergedMessages.length - 1].role === message.role) { | |
| 436 | + mergedMessages[mergedMessages.length - 1].content += '\n\n' + message.content; | |
| 437 | + } else { | |
| 438 | + mergedMessages.push(message); | |
| 439 | + } | |
| 440 | + }); | |
| 441 | + | |
| 442 | + return mergedMessages; | |
| 443 | +} | |
| 444 | + | |
| 445 | +/** | |
| 371 | 446 | * Convert a prompt from the ChatML objects to the format used by MistralAI. |
| 372 | 447 | * @param {object[]} messages Array of messages |
| 373 | 448 | * @param {string} charName Character name |
| @@ -520,4 +595,5 @@ module.exports = { | ||
| 520 | 595 | convertCohereMessages, |
| 521 | 596 | convertMistralMessages, |
| 522 | 597 | convertCohereTools, |
| 598 | + convertAI21Messages, | |
| 523 | 599 | }; |
Binary file
| @@ -35,7 +35,7 @@ const tasks = { | ||
| 35 | 35 | defaultModel: 'Cohee/fooocus_expansion-onnx', |
| 36 | 36 | pipeline: null, |
| 37 | 37 | configField: 'extras.promptExpansionModel', |
| 38 | 38 | quantized: truefalse, |
| 39 | 39 | }, |
| 40 | 40 | 'automatic-speech-recognition': { |
| 41 | 41 | defaultModel: 'Xenova/whisper-small', |
| @@ -34,8 +34,9 @@ function getConfig() { | ||
| 34 | 34 | CACHED_CONFIG = config; |
| 35 | 35 | return config; |
| 36 | 36 | } catch (error) { |
| 37 | 37 | console.warnerror(color.red('FATAL: Failed to read config.yaml. Please check the file for syntax errors.')); |
| 38 | - return {}; | |
| 38 | + console.error(error.message); | |
| 39 | + process.exit(1); | |
| 39 | 40 | } |
| 40 | 41 | } |
| 41 | 42 | |
| @@ -298,8 +299,8 @@ const color = { | ||
| 298 | 299 | * @returns {string} A UUIDv4 string |
| 299 | 300 | */ |
| 300 | 301 | function uuidv4() { |
| 301 | 302 | if ('crypto' in global && 'randomUUID' in global.crypto) { |
| 302 | 303 | return global.crypto.randomUUID(); |
| 303 | 304 | } |
| 304 | 305 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { |
| 305 | 306 | const r = Math.random() * 16 | 0; |
| @@ -23,8 +23,8 @@ async function getMakerSuiteVector(text, directories) { | ||
| 23 | 23 | const key = readSecret(directories, SECRET_KEYS.MAKERSUITE); |
| 24 | 24 | |
| 25 | 25 | if (!key) { |
| 26 | 26 | console.log('No MakerSuiteGoogle AI Studio key found'); |
| 27 | 27 | throw new Error('No MakerSuiteGoogle AI Studio key found'); |
| 28 | 28 | } |
| 29 | 29 | |
| 30 | 30 | const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/embedding-gecko-001:embedText?key=${key}`, { |
| @@ -39,8 +39,8 @@ async function getMakerSuiteVector(text, directories) { | ||
| 39 | 39 | |
| 40 | 40 | if (!response.ok) { |
| 41 | 41 | const text = await response.text(); |
| 42 | 42 | console.log('MakerSuiteGoogle AI Studio request failed', response.statusText, text); |
| 43 | 43 | throw new Error('MakerSuiteGoogle AI Studio request failed'); |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | 46 | const data = await response.json(); |
| @@ -4513,10 +4513,9 @@ | ||
| 4513 | 4513 | } |
| 4514 | 4514 | }, |
| 4515 | 4515 | "node_modules/micromatch": { |
| 4516 | 4516 | "version": "4.0.78", |
| 4517 | 4517 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.78.tgz", |
| 4518 | 4518 | "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqOPXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/QPzEJQxsYsEiFCKo2BA==", |
| 4519 | - "license": "MIT", | |
| 4520 | 4519 | "dependencies": { |
| 4521 | 4520 | "braces": "^3.0.3", |
| 4522 | 4521 | "picomatch": "^2.3.1" |