mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Compare commits
20 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
7277622c24 | ||
|
9127c690a7 | ||
|
f2d7f74d5a | ||
|
defa7f357e | ||
|
d1fb575243 | ||
|
adc4f4b29d | ||
|
44dc5a6bb3 | ||
|
8a1f3a7f04 | ||
|
9bcb10adf1 | ||
|
d09e81cb94 | ||
|
b78c74aeff | ||
|
93e1d4b39e | ||
|
63a9d3ded1 | ||
|
66f7d55f76 | ||
|
64b1485070 | ||
|
25759ebe0b | ||
|
c101368109 | ||
|
e4c3c552d7 | ||
|
8f531832e5 | ||
|
915de0b41a |
@@ -3,7 +3,7 @@
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable-no">
|
||||
<meta name="viewport" content="width=device-width, viewport-fit=cover, initial-scale=1, maximum-scale=1.0, user-scalable=no">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<!--<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD" crossorigin="anonymous">-->
|
||||
<!-- <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN" crossorigin="anonymous"></script>-->
|
||||
@@ -245,6 +245,18 @@
|
||||
</div>
|
||||
</div>
|
||||
<div id="range_block_openai">
|
||||
<div class="range-block">
|
||||
<div class="range-block-title">
|
||||
OpenAI Reverse Proxy
|
||||
</div>
|
||||
<div class="range-block-counter">
|
||||
Alternative server URL (leave empty to use the default value).<br>
|
||||
<b class="failure">Don't expose your real API keys to reverse proxies!</b>
|
||||
</div>
|
||||
<div class="range-block-range">
|
||||
<input id="openai_reverse_proxy" type="text" class="text_pole" placeholder="https://api.openai.com/v1" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="range-block">
|
||||
<div class="range-block-title">
|
||||
OpenAI Context Size
|
||||
@@ -694,7 +706,7 @@
|
||||
Text to be send as a character nudge
|
||||
</div>
|
||||
<div class="range-block-range">
|
||||
<input id="poe_nudge_text" class="text_pole" type="text" />
|
||||
<textarea id="poe_nudge_text" class="text_pole" rows="3"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -751,7 +763,7 @@
|
||||
</div>
|
||||
</h4>
|
||||
<select id="horde_model">
|
||||
<option>-- Not connected to Horde --</option>
|
||||
<option>-- Horde models not loaded --</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="online_status2">
|
||||
@@ -1084,9 +1096,25 @@
|
||||
<div id="power-user-options-block">
|
||||
<h3>Power User Options</h3>
|
||||
<div id="power-user-option-checkboxes">
|
||||
<label for="swipes-checkbox">
|
||||
<input id="swipes-checkbox" type="checkbox" />
|
||||
Swipes
|
||||
</label>
|
||||
|
||||
<label for="auto-load-chat-checkbox"><input id="auto-load-chat-checkbox" type="checkbox" />
|
||||
Auto-load Last Chat
|
||||
<label for="play_message_sound" class="checkbox_label">
|
||||
<input id="play_message_sound" type="checkbox" />
|
||||
<audio id="audio_message_sound" src="sounds/message.mp3" hidden></audio>
|
||||
<span>
|
||||
Play a sound on new message
|
||||
<a href="/notes/message_sound" class="notes-link" target="_blank">
|
||||
<span class="note-link-span">?</span>
|
||||
</a>
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<label for="play_sound_unfocused" class="checkbox_label">
|
||||
<input id="play_sound_unfocused" type="checkbox" />
|
||||
Sound only for unfocused window
|
||||
</label>
|
||||
|
||||
<label for="fast_ui_mode" class="checkbox_label" title="Blur can cause browser lag, especially in Bubble Chat mode. To fix: Turn on your browser's Hardware Acceleration, and restart your browser or simply disable the blur effect with this toggle.">
|
||||
@@ -1094,8 +1122,8 @@
|
||||
No Blur Effect
|
||||
</label>
|
||||
|
||||
<label for="swipes-checkbox"><input id="swipes-checkbox" type="checkbox" />
|
||||
Swipes
|
||||
<label for="auto-load-chat-checkbox"><input id="auto-load-chat-checkbox" type="checkbox" />
|
||||
Auto-load Last Chat
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1346,6 +1374,15 @@
|
||||
</div>
|
||||
<form id="form_character_search_form" action="javascript:void(null);">
|
||||
<input id="character_search_bar" class="text_pole" type="search" placeholder="Character search..." />
|
||||
<select id="character_sort_order" title="Characters sorting order">
|
||||
<option data-field="name" data-order="asc">Name, A-Z</option>
|
||||
<option data-field="name" data-order="desc">Name, Z-A</option>
|
||||
<option data-field="date_added" data-order="desc">Date added, newer first</option>
|
||||
<option data-field="date_added" data-order="asc">Date added, older first</option>
|
||||
<option data-field="date_last_chat" data-order="desc">Recently chatted</option>
|
||||
<option data-field="chat_size" data-order="desc">Most chatted</option>
|
||||
<option data-field="chat_size" data-order="asc">Least chatted</option>
|
||||
</select>
|
||||
</form>
|
||||
<div id="rm_print_characters_block"></div>
|
||||
</div>
|
||||
@@ -1399,7 +1436,7 @@
|
||||
<hr>
|
||||
<h4>Personality summary</h4>
|
||||
<h5>A brief description of the personality <a href="/notes/2" class="notes-link" target="_blank"><span class="note-link-span">?</span></a></h5>
|
||||
<input id="personality_textarea" name="personality" placeholder="" form="form_create" class="text_pole" autocomplete="off">
|
||||
<textarea id="personality_textarea" name="personality" placeholder="" form="form_create" class="text_pole" autocomplete="off" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<div id="scenario_div">
|
||||
@@ -1409,7 +1446,7 @@
|
||||
<span class="note-link-span">?</span>
|
||||
</a>
|
||||
</h5>
|
||||
<input id="scenario_pole" name="scenario" class="text_pole" maxlength="9999" value="" autocomplete="off" form="form_create">
|
||||
<textarea id="scenario_pole" name="scenario" class="text_pole" maxlength="9999" value="" autocomplete="off" form="form_create" rows="3"></textarea>
|
||||
</div>
|
||||
|
||||
<div id="talkativeness_div">
|
||||
|
33
public/notes/message_sound.html
Normal file
33
public/notes/message_sound.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Message Sound</title>
|
||||
<link rel="stylesheet" href="/css/notes.css">
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
|
||||
rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="main">
|
||||
<div id="content">
|
||||
<h2>Message Sound</h2>
|
||||
<p>To play your own custom sound on receiving a new message from bot, replace the following MP3 file in your TavernAI folder:</p>
|
||||
<code>
|
||||
public/sounds/message.mp3
|
||||
</code>
|
||||
<p>
|
||||
Plays at 80% volume.
|
||||
</p>
|
||||
<p>
|
||||
If "Sound only for unfocused window" option is enabled, the sound plays only if TavernAI window is <b>unfocused</b>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
108
public/script.js
108
public/script.js
@@ -41,6 +41,8 @@ import {
|
||||
import {
|
||||
collapseNewlines,
|
||||
loadPowerUserSettings,
|
||||
playMessageSound,
|
||||
sortCharactersList,
|
||||
power_user,
|
||||
} from "./scripts/power-user.js";
|
||||
|
||||
@@ -71,6 +73,7 @@ import {
|
||||
loadHordeSettings,
|
||||
generateHorde,
|
||||
checkHordeStatus,
|
||||
getHordeModels,
|
||||
adjustHordeGenerationParams,
|
||||
} from "./scripts/horde.js";
|
||||
|
||||
@@ -236,7 +239,9 @@ const system_messages = {
|
||||
'<li>Connect to one of the supported generation APIs</li>',
|
||||
'<li>Create or pick a character from the list</li>',
|
||||
'</ul>',
|
||||
'Still have questions left?\n',
|
||||
"<h4>Running on Colab and can't get an answer from the AI or getting Out of Memory errors?</h4>",
|
||||
'Set a lower Context Size in AI generation settings.<br>Values in range of 1400-1600 Tokens would be the safest choice.',
|
||||
'<h4>Still have questions left?</h4>',
|
||||
'Check out built-in help or type <tt>/?</tt> in any chat.'
|
||||
].join('')
|
||||
},
|
||||
@@ -605,7 +610,7 @@ function printCharacters() {
|
||||
//console.log('printcharacters() -- printing -- ChID '+i+' ('+item.name+')');
|
||||
});
|
||||
printGroups();
|
||||
sortCharactersList('name', 'asc');
|
||||
sortCharactersList();
|
||||
}
|
||||
|
||||
async function getCharacters() {
|
||||
@@ -1114,6 +1119,11 @@ async function Generate(type, automatic_trigger, force_name2) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isHordeGenerationNotAllowed()) {
|
||||
is_send_press = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (selected_group && !is_group_generating) {
|
||||
generateGroupWrapper(false, type = type);
|
||||
return;
|
||||
@@ -1796,6 +1806,7 @@ async function Generate(type, automatic_trigger, force_name2) {
|
||||
//getMessage = getMessage.replace(/^\s+/g, '');
|
||||
if (getMessage.length > 0) {
|
||||
({ type, getMessage } = saveReply(type, getMessage, this_mes_is_name));
|
||||
playMessageSound();
|
||||
generate_loop_counter = 0;
|
||||
} else {
|
||||
++generate_loop_counter;
|
||||
@@ -2192,6 +2203,7 @@ function changeMainAPI() {
|
||||
if (main_api == "kobold" && horde_settings.use_horde) {
|
||||
is_get_status = true;
|
||||
getStatus();
|
||||
getHordeModels();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2276,27 +2288,6 @@ async function getSettings(type) {
|
||||
changeMainAPI();
|
||||
}
|
||||
|
||||
novelai_setting_names = data.novelai_setting_names;
|
||||
novelai_settings = data.novelai_settings;
|
||||
novelai_settings.forEach(function (item, i, arr) {
|
||||
novelai_settings[i] = JSON.parse(item);
|
||||
});
|
||||
let arr_holder = {};
|
||||
|
||||
$("#settings_perset_novel").empty();
|
||||
|
||||
novelai_setting_names.forEach(function (item, i, arr) {
|
||||
arr_holder[item] = i;
|
||||
$("#settings_perset_novel").append(`<option value=${i}>${item}</option>`);
|
||||
});
|
||||
novelai_setting_names = {};
|
||||
novelai_setting_names = arr_holder;
|
||||
|
||||
nai_settings.preset_settings_novel = settings.preset_settings_novel;
|
||||
$(
|
||||
`#settings_perset_novel option[value=${novelai_setting_names[nai_settings.preset_settings_novel]}]`
|
||||
).attr("selected", "true");
|
||||
|
||||
//Load KoboldAI settings
|
||||
koboldai_setting_names = data.koboldai_setting_names;
|
||||
koboldai_settings = data.koboldai_settings;
|
||||
@@ -2304,7 +2295,7 @@ async function getSettings(type) {
|
||||
koboldai_settings[i] = JSON.parse(item);
|
||||
});
|
||||
|
||||
arr_holder = {};
|
||||
let arr_holder = {};
|
||||
|
||||
$("#settings_perset").empty(); //RossAscends: uncommented this to prevent settings selector from doubling preset list on refresh
|
||||
$("#settings_perset").append(
|
||||
@@ -2320,6 +2311,39 @@ async function getSettings(type) {
|
||||
koboldai_setting_names = arr_holder;
|
||||
preset_settings = settings.preset_settings;
|
||||
|
||||
if (preset_settings == "gui") {
|
||||
selectKoboldGuiPreset();
|
||||
} else {
|
||||
if (typeof koboldai_setting_names[preset_settings] !== "undefined") {
|
||||
$(`#settings_perset option[value=${koboldai_setting_names[preset_settings]}]`)
|
||||
.attr("selected", "true");
|
||||
} else {
|
||||
preset_settings = "gui";
|
||||
selectKoboldGuiPreset();
|
||||
}
|
||||
}
|
||||
|
||||
novelai_setting_names = data.novelai_setting_names;
|
||||
novelai_settings = data.novelai_settings;
|
||||
novelai_settings.forEach(function (item, i, arr) {
|
||||
novelai_settings[i] = JSON.parse(item);
|
||||
});
|
||||
arr_holder = {};
|
||||
|
||||
$("#settings_perset_novel").empty();
|
||||
|
||||
novelai_setting_names.forEach(function (item, i, arr) {
|
||||
arr_holder[item] = i;
|
||||
$("#settings_perset_novel").append(`<option value=${i}>${item}</option>`);
|
||||
});
|
||||
novelai_setting_names = {};
|
||||
novelai_setting_names = arr_holder;
|
||||
|
||||
nai_settings.preset_settings_novel = settings.preset_settings_novel;
|
||||
$(
|
||||
`#settings_perset_novel option[value=${novelai_setting_names[nai_settings.preset_settings_novel]}]`
|
||||
).attr("selected", "true");
|
||||
|
||||
//Load AI model config settings (temp, context length, anchors, and anchor order)
|
||||
|
||||
amount_gen = settings.amount_gen;
|
||||
@@ -2376,21 +2400,6 @@ async function getSettings(type) {
|
||||
|
||||
//Enable GUI deference settings if GUI is selected for Kobold
|
||||
if (main_api === "kobold") {
|
||||
if (preset_settings == "gui") {
|
||||
$("#settings_perset option[value=gui]")
|
||||
.attr("selected", "true")
|
||||
.trigger("change");
|
||||
} else {
|
||||
if (typeof koboldai_setting_names[preset_settings] !== "undefined") {
|
||||
$(`#settings_perset option[value=${koboldai_setting_names[preset_settings]}]`)
|
||||
.attr("selected", "true");
|
||||
} else {
|
||||
preset_settings = "gui";
|
||||
$("#settings_perset option[value=gui]")
|
||||
.attr("selected", "true")
|
||||
.trigger("change");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Load User's Name and Avatar
|
||||
@@ -2448,6 +2457,12 @@ async function getSettings(type) {
|
||||
});
|
||||
}
|
||||
|
||||
function selectKoboldGuiPreset() {
|
||||
$("#settings_perset option[value=gui]")
|
||||
.attr("selected", "true")
|
||||
.trigger("change");
|
||||
}
|
||||
|
||||
async function saveSettings(type) {
|
||||
//console.log('Entering settings with name1 = '+name1);
|
||||
jQuery.ajax({
|
||||
@@ -3052,12 +3067,13 @@ function setGenerationProgress(progress) {
|
||||
}
|
||||
}
|
||||
|
||||
function sortCharactersList(field, order) {
|
||||
let orderedList = characters.slice().sort((a, b) => order == 'asc' ? a[field].localeCompare(b[field]) : b[field].localeCompare(a[field]));
|
||||
|
||||
for (let i = 0; i < characters.length; i++) {
|
||||
$(`.character_select[chid="${i}"]`).css({ 'order': orderedList.indexOf(characters[i]) });
|
||||
function isHordeGenerationNotAllowed() {
|
||||
if (main_api == "kobold" && horde_settings.use_horde && preset_settings == "gui") {
|
||||
callPopup('GUI Settings preset is not supported for Horde. Please select another preset.', 'text');
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
window["TavernAI"].getContext = function () {
|
||||
@@ -3109,6 +3125,10 @@ $(document).ready(function () {
|
||||
closeMessageEditor();
|
||||
}
|
||||
|
||||
if (isHordeGenerationNotAllowed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const swipe_duration = 120;
|
||||
const swipe_range = 700;
|
||||
//console.log(swipe_range);
|
||||
|
@@ -7,6 +7,7 @@ export {
|
||||
checkHordeStatus,
|
||||
loadHordeSettings,
|
||||
adjustHordeGenerationParams,
|
||||
getHordeModels,
|
||||
}
|
||||
|
||||
let models = [];
|
||||
@@ -154,6 +155,16 @@ async function getHordeModels() {
|
||||
option.selected = horde_settings.model === model.name;
|
||||
$('#horde_model').append(option);
|
||||
}
|
||||
|
||||
// if previously selected is no longer available
|
||||
if (horde_settings.model && !models.find(m => m.name == horde_settings.model)) {
|
||||
horde_settings.model = null;
|
||||
}
|
||||
|
||||
// if no models preselected - select a first one in dropdown
|
||||
if (!horde_settings.model) {
|
||||
horde_settings.model = $('#horde_model').find(":selected").val();
|
||||
}
|
||||
}
|
||||
|
||||
function loadHordeSettings(settings) {
|
||||
@@ -182,9 +193,6 @@ $(document).ready(function () {
|
||||
// Trigger status check
|
||||
changeMainAPI();
|
||||
saveSettingsDebounced();
|
||||
if (main_api === 'kobold' && horde_settings.use_horde) {
|
||||
await getHordeModels();
|
||||
}
|
||||
});
|
||||
|
||||
$("#horde_model").on("change", function () {
|
||||
|
@@ -78,6 +78,7 @@ const default_settings = {
|
||||
jailbreak_prompt: default_jailbreak_prompt,
|
||||
openai_model: 'gpt-3.5-turbo-0301',
|
||||
jailbreak_system: false,
|
||||
reverse_proxy: '',
|
||||
};
|
||||
|
||||
const oai_settings = {
|
||||
@@ -98,11 +99,28 @@ const oai_settings = {
|
||||
jailbreak_prompt: default_jailbreak_prompt,
|
||||
openai_model: 'gpt-3.5-turbo-0301',
|
||||
jailbreak_system: false,
|
||||
reverse_proxy: '',
|
||||
};
|
||||
|
||||
let openai_setting_names;
|
||||
let openai_settings;
|
||||
|
||||
function validateReverseProxy() {
|
||||
if (!oai_settings.reverse_proxy) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
new URL(oai_settings.reverse_proxy);
|
||||
}
|
||||
catch (err) {
|
||||
callPopup('Entered reverse proxy address is not a valid URL', 'text');
|
||||
setOnlineStatus('no_connection');
|
||||
resultCheckStatusOpen();
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
function setOpenAIOnlineStatus(value) {
|
||||
is_get_status_openai = value;
|
||||
}
|
||||
@@ -396,6 +414,10 @@ async function prepareOpenAIMessages(name2, storyString, worldInfoBefore, worldI
|
||||
}
|
||||
|
||||
async function sendOpenAIRequest(openai_msgs_tosend) {
|
||||
if (oai_settings.reverse_proxy) {
|
||||
validateReverseProxy();
|
||||
}
|
||||
|
||||
const generate_data = {
|
||||
"messages": openai_msgs_tosend,
|
||||
"model": oai_settings.openai_model,
|
||||
@@ -404,6 +426,7 @@ async function sendOpenAIRequest(openai_msgs_tosend) {
|
||||
"presence_penalty": parseFloat(oai_settings.pres_pen_openai),
|
||||
"max_tokens": oai_settings.openai_max_tokens,
|
||||
"stream": false, //oai_settings.stream_openai,
|
||||
"reverse_proxy": oai_settings.reverse_proxy,
|
||||
};
|
||||
|
||||
const generate_url = '/generate_openai';
|
||||
@@ -589,17 +612,28 @@ function loadOpenAISettings(data, settings) {
|
||||
|
||||
$('#pres_pen_openai').val(oai_settings.pres_pen_openai);
|
||||
$('#pres_pen_counter_openai').text(Number(oai_settings.pres_pen_openai).toFixed(2));
|
||||
|
||||
if (settings.reverse_proxy !== undefined) oai_settings.reverse_proxy = settings.reverse_proxy;
|
||||
$('#openai_reverse_proxy').val(oai_settings.reverse_proxy);
|
||||
}
|
||||
|
||||
async function getStatusOpen() {
|
||||
if (is_get_status_openai) {
|
||||
let data = { key: oai_settings.api_key_openai };
|
||||
|
||||
let data = {
|
||||
key: oai_settings.api_key_openai,
|
||||
reverse_proxy: oai_settings.reverse_proxy,
|
||||
};
|
||||
|
||||
jQuery.ajax({
|
||||
type: 'POST', //
|
||||
url: '/getstatus_openai', //
|
||||
data: JSON.stringify(data),
|
||||
beforeSend: function () { },
|
||||
beforeSend: function () {
|
||||
if (oai_settings.reverse_proxy) {
|
||||
validateReverseProxy();
|
||||
}
|
||||
},
|
||||
cache: false,
|
||||
dataType: "json",
|
||||
contentType: "application/json",
|
||||
@@ -902,4 +936,9 @@ $(document).ready(function () {
|
||||
$('#jailbreak_prompt_textarea').val(oai_settings.jailbreak_prompt);
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$("#openai_reverse_proxy").on('input', function () {
|
||||
oai_settings.reverse_proxy = $(this).val();
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
});
|
||||
|
@@ -1,8 +1,10 @@
|
||||
import { saveSettingsDebounced } from "../script.js";
|
||||
import { saveSettingsDebounced, characters } from "../script.js";
|
||||
|
||||
export {
|
||||
loadPowerUserSettings,
|
||||
collapseNewlines,
|
||||
playMessageSound,
|
||||
sortCharactersList,
|
||||
power_user,
|
||||
};
|
||||
|
||||
@@ -35,6 +37,10 @@ let power_user = {
|
||||
avatar_style: avatar_styles.ROUND,
|
||||
chat_display: chat_styles.DEFAULT,
|
||||
sheld_width: sheld_width.DEFAULT,
|
||||
play_message_sound: false,
|
||||
play_sound_unfocused: true,
|
||||
sort_field: 'name',
|
||||
sort_order: 'asc',
|
||||
};
|
||||
|
||||
const storage_keys = {
|
||||
@@ -53,6 +59,25 @@ const storage_keys = {
|
||||
sheld_width: "TavernAI_sheld_width"
|
||||
};
|
||||
|
||||
//Updated at the bottom of this script document based on 'focus' and 'blur' events
|
||||
let browser_has_focus = true;
|
||||
|
||||
function playMessageSound() {
|
||||
if (!power_user.play_message_sound) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (power_user.play_sound_unfocused && browser_has_focus) {
|
||||
return;
|
||||
}
|
||||
|
||||
const audio = document.getElementById('audio_message_sound');
|
||||
audio.volume = 0.8;
|
||||
audio.pause();
|
||||
audio.currentTime = 0;
|
||||
audio.play();
|
||||
}
|
||||
|
||||
function collapseNewlines(x) {
|
||||
return x.replaceAll(/\n+/g, "\n");
|
||||
}
|
||||
@@ -129,9 +154,30 @@ function loadPowerUserSettings(settings) {
|
||||
$("#custom_chat_separator").val(power_user.custom_chat_separator);
|
||||
$("#fast_ui_mode").prop("checked", power_user.fast_ui_mode);
|
||||
$("#multigen").prop("checked", power_user.multigen);
|
||||
$("#play_message_sound").prop("checked", power_user.play_message_sound);
|
||||
$("#play_sound_unfocused").prop("checked", power_user.play_sound_unfocused);
|
||||
$(`input[name="avatar_style"][value="${power_user.avatar_style}"]`).prop("checked", true);
|
||||
$(`input[name="chat_display"][value="${power_user.chat_display}"]`).prop("checked", true);
|
||||
$(`input[name="sheld_width"][value="${power_user.sheld_width}"]`).prop("checked", true);
|
||||
$(`#character_sort_order option[data-order="${power_user.sort_order}"][data-field="${power_user.sort_field}"]`).prop("selected", true);
|
||||
sortCharactersList();
|
||||
}
|
||||
|
||||
function sortCharactersList() {
|
||||
const sortFunc = (a, b) => power_user.sort_order == 'asc' ? compareFunc(a, b) : compareFunc(b, a);
|
||||
const compareFunc = (first, second) => typeof first[power_user.sort_field] == "string"
|
||||
? first[power_user.sort_field].localeCompare(second[power_user.sort_field])
|
||||
: first[power_user.sort_field] - second[power_user.sort_field];
|
||||
|
||||
if (power_user.sort_field == undefined || characters.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let orderedList = characters.slice().sort(sortFunc);
|
||||
|
||||
for (let i = 0; i < characters.length; i++) {
|
||||
$(`.character_select[chid="${i}"]`).css({ 'order': orderedList.indexOf(characters[i]) });
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(() => {
|
||||
@@ -199,10 +245,36 @@ $(document).ready(() => {
|
||||
localStorage.setItem(storage_keys.chat_display, power_user.chat_display);
|
||||
applyChatDisplay();
|
||||
});
|
||||
|
||||
$(`input[name="sheld_width"]`).on('input', function (e) {
|
||||
power_user.sheld_width = Number(e.target.value);
|
||||
localStorage.setItem(storage_keys.sheld_width, power_user.sheld_width);
|
||||
console.log("sheld width changing now");
|
||||
applySheldWidth();
|
||||
});
|
||||
});
|
||||
|
||||
$("#play_message_sound").on('input', function () {
|
||||
power_user.play_message_sound = !!$(this).prop('checked');
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$("#play_sound_unfocused").on('input', function () {
|
||||
power_user.play_sound_unfocused = !!$(this).prop('checked');
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$("#character_sort_order").on('change', function () {
|
||||
power_user.sort_field = $(this).find(":selected").data('field');
|
||||
power_user.sort_order = $(this).find(":selected").data('order');
|
||||
sortCharactersList();
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$(window).on('focus', function() {
|
||||
browser_has_focus = true;
|
||||
});
|
||||
|
||||
$(window).on('blur', function() {
|
||||
browser_has_focus = false;
|
||||
});
|
||||
});
|
||||
|
BIN
public/sounds/message.mp3
Normal file
BIN
public/sounds/message.mp3
Normal file
Binary file not shown.
235
public/style.css
235
public/style.css
@@ -58,7 +58,7 @@ body {
|
||||
width: 100%;
|
||||
/*fallback for JS load*/
|
||||
height: 100svh;
|
||||
/*defaults as 100%, then reassigned via JS as pixels*/
|
||||
/*defaults as 100%, then reassigned via JS as pixels, will work on PC and Android*/
|
||||
height: var(--doc-height);
|
||||
background-color: var(--greyCAIbg);
|
||||
background-repeat: no-repeat;
|
||||
@@ -859,17 +859,20 @@ img[src="img/load.svg"] {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
padding-left: 5px;
|
||||
margin: 10px 5px;
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
#character_sort_order {
|
||||
margin: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
#character_search_bar {
|
||||
flex: 1;
|
||||
font-size: 1em;
|
||||
padding-left: 0.75em;
|
||||
margin-left: 0;
|
||||
margin-right: 0.5rem;
|
||||
margin-bottom: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
input[type=search]::-webkit-search-cancel-button {
|
||||
@@ -1018,7 +1021,8 @@ input[type=search]:focus::-webkit-search-cancel-button {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#user-settings-block h4, #user-settings-block h3 {
|
||||
#user-settings-block h4,
|
||||
#user-settings-block h3 {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
@@ -1945,7 +1949,7 @@ input[type="range"]::-webkit-slider-thumb {
|
||||
background-color: var(--black30a);
|
||||
backdrop-filter: blur(50px);
|
||||
-webkit-backdrop-filter: blur(30px);
|
||||
grid-template-rows: 50px 100px 100px 100px auto;
|
||||
grid-template-rows: 50px 1fr 1fr 1fr 5fr;
|
||||
grid-gap: 10px;
|
||||
max-width: var(--sheldWidth);
|
||||
height: calc(100svh - 40px);
|
||||
@@ -3149,149 +3153,9 @@ label[for="extensions_autoconnect"] {
|
||||
|
||||
/* ---------- @media queries must always go at the bottom ------------*/
|
||||
|
||||
@media screen and (max-width: 450px) {
|
||||
/*styles for mobile phones (tested on iPhone 13 Pro)*/
|
||||
/*will apply to anything 1000px or less. this catches ipads, horizontal phones, and vertical phones)*/
|
||||
|
||||
body {
|
||||
font-size: 16px;
|
||||
position: fixed;
|
||||
touch-action: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.drawer-content {
|
||||
min-width: unset;
|
||||
width: 100svw;
|
||||
max-height: calc(100svh - 45px);
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 5px;
|
||||
border: 1px solid var(--grey30);
|
||||
}
|
||||
|
||||
#select_chat_popup {
|
||||
align-items: start;
|
||||
height: min-content;
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
#top-settings-holder {
|
||||
width: 100svw;
|
||||
position: fixed;
|
||||
|
||||
}
|
||||
|
||||
#bg1,
|
||||
#bg2 {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
#sheld,
|
||||
#character_popup,
|
||||
#world_popup {
|
||||
/*margin around the sides, and a larger one on bottom to avoid iOS Home bar*/
|
||||
height: calc(100svh - 45px);
|
||||
width: 100svw;
|
||||
margin: 0 auto;
|
||||
margin-left: 0px;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
#character_popup,
|
||||
#world_popup,
|
||||
#send_form {
|
||||
border: 1px solid var(--grey30);
|
||||
}
|
||||
|
||||
#chat {
|
||||
border-left: 1px solid var(--grey30);
|
||||
border-right: 1px solid var(--grey30);
|
||||
border-bottom: 1px solid var(--grey30);
|
||||
align-items: start;
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
#sheld,
|
||||
#character_popup {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.mes-text {
|
||||
padding-right: 25px;
|
||||
}
|
||||
|
||||
#right-nav-panel,
|
||||
#left-nav-panel {
|
||||
height: calc(100svh - 45px);
|
||||
min-width: 0px;
|
||||
width: 100svw;
|
||||
max-width: 100svw;
|
||||
overflow-y: auto;
|
||||
border-left: 1px solid var(--grey30);
|
||||
border-right: 1px solid var(--grey30);
|
||||
border-bottom: 1px solid var(--grey30);
|
||||
border-radius: 0 0 20px 20px;
|
||||
top: 40px;
|
||||
}
|
||||
|
||||
#right-nav-panel h4 {
|
||||
margin: 5px auto;
|
||||
}
|
||||
|
||||
#form_create {
|
||||
grid-template-rows:
|
||||
[avatar] min-content [hr] min-content [descriptionHeader] min-content [description] auto [firstmessageHeader] min-content [firstMessage] auto;
|
||||
}
|
||||
|
||||
#result_info {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.avatar_div {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
#character_popup {
|
||||
width: calc(100svw - 5px);
|
||||
border-radius: 0 0 0 20px;
|
||||
margin-top: -35px;
|
||||
height: calc(100svh - 30px);
|
||||
}
|
||||
|
||||
|
||||
#send_textarea {
|
||||
/*larger input bar for mobile screens, easier to tap*/
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.5rem;
|
||||
min-height: calc(2rem + 0.75rem + 2px);
|
||||
max-height: 200px;
|
||||
word-wrap: break-word;
|
||||
height: 40px;
|
||||
resize: vertical;
|
||||
display: block;
|
||||
background-color: rgba(255, 0, 0, 0);
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
padding: 6px 0 6px 0;
|
||||
font-family: "Noto Sans", "Noto Color Emoji", sans-serif;
|
||||
margin: 0;
|
||||
text-shadow: #000 0 0 3px;
|
||||
}
|
||||
|
||||
#rm_ch_create_block textarea {
|
||||
/*without this the text areas display far too large*/
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
#talkativeness_hint span {
|
||||
min-width: 33%;
|
||||
}
|
||||
|
||||
/*for debug purposes*/
|
||||
/* div {border: 1px solid purple;} */
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
@media (max-width: 1000px) {
|
||||
.mes img.img_extra {
|
||||
max-width: 100%;
|
||||
}
|
||||
@@ -3305,7 +3169,7 @@ label[for="extensions_autoconnect"] {
|
||||
|
||||
.drawer-content {
|
||||
min-width: unset;
|
||||
width: 100svw;
|
||||
width: 100%;
|
||||
max-height: calc(100svh - 45px);
|
||||
position: fixed;
|
||||
left: 0;
|
||||
@@ -3333,11 +3197,9 @@ label[for="extensions_autoconnect"] {
|
||||
#sheld,
|
||||
#character_popup,
|
||||
#world_popup {
|
||||
/*margin around the sides, and a larger one on bottom to avoid iOS Home bar*/
|
||||
height: calc(100svh - 45px);
|
||||
width: 100svw;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
margin-left: 0px;
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
@@ -3367,9 +3229,9 @@ label[for="extensions_autoconnect"] {
|
||||
#right-nav-panel,
|
||||
#left-nav-panel {
|
||||
height: calc(100svh - 45px);
|
||||
min-width: 0px;
|
||||
width: 100svw;
|
||||
max-width: 100svw;
|
||||
min-width: 100%;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
overflow-y: auto;
|
||||
border-left: 1px solid var(--grey30);
|
||||
border-right: 1px solid var(--grey30);
|
||||
@@ -3396,10 +3258,10 @@ label[for="extensions_autoconnect"] {
|
||||
}
|
||||
|
||||
#character_popup {
|
||||
width: calc(100svw - 5px);
|
||||
border-radius: 0 0 0 20px;
|
||||
margin-top: -35px;
|
||||
height: calc(100svh - 30px);
|
||||
width: 100%;
|
||||
border-radius: 0 0 20px 20px;
|
||||
margin-top: 0px;
|
||||
height: calc(100% - 40px);
|
||||
}
|
||||
|
||||
|
||||
@@ -3484,4 +3346,55 @@ body.no-blur #world_popup,
|
||||
body.no-blur #dialogue_popup,
|
||||
body.no-blur #select_chat_popup {
|
||||
background-color: var(--black90a) !important;
|
||||
}
|
||||
|
||||
/*this part only only applies to iOS devices*/
|
||||
@supports (-webkit-touch-callout: none) {
|
||||
body {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#top-bar {
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
#sheld {
|
||||
margin: unset;
|
||||
padding: unset;
|
||||
width: unset;
|
||||
height: unset;
|
||||
min-width: unset;
|
||||
max-width: unset;
|
||||
min-height: unset;
|
||||
max-height: unset;
|
||||
|
||||
width: 100svw !important;
|
||||
height: calc(100svh - 40px) !important;
|
||||
padding-right: max(env(safe-area-inset-right), 5px) !important;
|
||||
padding-left: max(env(safe-area-inset-left), 5px) !important;
|
||||
padding-bottom: max(env(safe-area-inset-bottom), 15px) !important;
|
||||
}
|
||||
|
||||
#character_popup,
|
||||
#world_popup,
|
||||
#left-nav-panel,
|
||||
#right-nav-panel,
|
||||
.drawer-content {
|
||||
width: unset;
|
||||
height: unset;
|
||||
min-width: unset;
|
||||
max-width: unset;
|
||||
min-height: unset;
|
||||
max-height: unset;
|
||||
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
max-height: calc(100svh - env(safe-area-inset-bottom));
|
||||
max-width: min(calc(100% - env(safe-area-inset-right) - env(safe-area-inset-left)), calc(100% - 5px));
|
||||
margin: 0 auto;
|
||||
margin-top: 40px;
|
||||
|
||||
|
||||
}
|
||||
}
|
40
server.js
40
server.js
@@ -739,6 +739,36 @@ app.post("/getcharacters", jsonParser, function (request, response) {
|
||||
//console.log(jsonObject);
|
||||
characters[i] = {};
|
||||
characters[i] = jsonObject;
|
||||
|
||||
try {
|
||||
const charStat = fs.statSync(path.join(charactersPath, item));
|
||||
characters[i]['date_added'] = charStat.birthtimeMs;
|
||||
const char_dir = path.join(chatsPath, item.replace('.png', ''));
|
||||
|
||||
let chat_size = 0;
|
||||
let date_last_chat = 0;
|
||||
|
||||
if (fs.existsSync(char_dir)) {
|
||||
const chats = fs.readdirSync(char_dir);
|
||||
|
||||
if (Array.isArray(chats) && chats.length) {
|
||||
for (const chat of chats) {
|
||||
const chatStat = fs.statSync(path.join(char_dir, chat));
|
||||
chat_size += chatStat.size;
|
||||
date_last_chat = Math.max(date_last_chat, chatStat.mtimeMs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
characters[i]['date_last_chat'] = date_last_chat;
|
||||
characters[i]['chat_size'] = chat_size;
|
||||
}
|
||||
catch {
|
||||
characters[i]['date_added'] = 0;
|
||||
characters[i]['date_last_chat'] = 0;
|
||||
characters[i]['chat_size'] = 0;
|
||||
}
|
||||
|
||||
i++;
|
||||
} catch (error) {
|
||||
console.log(`Could not read character: ${item}`);
|
||||
@@ -1893,10 +1923,11 @@ app.get('/thumbnail', jsonParser, async function (request, response) {
|
||||
app.post("/getstatus_openai", jsonParser, function (request, response_getstatus_openai = response) {
|
||||
if (!request.body) return response_getstatus_openai.sendStatus(400);
|
||||
api_key_openai = request.body.key;
|
||||
const api_url = new URL(request.body.reverse_proxy || api_openai).toString();
|
||||
const args = {
|
||||
headers: { "Authorization": "Bearer " + api_key_openai }
|
||||
};
|
||||
client.get(api_openai + "/models", args, function (data, response) {
|
||||
client.get(api_url + "/models", args, function (data, response) {
|
||||
if (response.statusCode == 200) {
|
||||
console.log(data);
|
||||
response_getstatus_openai.send(data);//data);
|
||||
@@ -1905,6 +1936,10 @@ app.post("/getstatus_openai", jsonParser, function (request, response_getstatus_
|
||||
console.log('Access Token is incorrect.');
|
||||
response_getstatus_openai.send({ error: true });
|
||||
}
|
||||
if (response.statusCode == 404) {
|
||||
console.log('Endpoint not found.');
|
||||
response_getstatus_openai.send({ error: true });
|
||||
}
|
||||
if (response.statusCode == 500 || response.statusCode == 501 || response.statusCode == 501 || response.statusCode == 503 || response.statusCode == 507) {
|
||||
console.log(data);
|
||||
response_getstatus_openai.send({ error: true });
|
||||
@@ -1916,11 +1951,12 @@ app.post("/getstatus_openai", jsonParser, function (request, response_getstatus_
|
||||
|
||||
app.post("/generate_openai", jsonParser, function (request, response_generate_openai) {
|
||||
if (!request.body) return response_generate_openai.sendStatus(400);
|
||||
const api_url = new URL(request.body.reverse_proxy || api_openai).toString();
|
||||
|
||||
console.log(request.body);
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: api_openai + '/chat/completions',
|
||||
url: api_url + '/chat/completions',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + api_key_openai
|
||||
|
Reference in New Issue
Block a user