mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-03-15 11:30:09 +01:00
Merge branch 'staging' of https://github.com/Cohee1207/SillyTavern into staging
This commit is contained in:
commit
4558f856b5
@ -1742,6 +1742,10 @@
|
||||
<optgroup id="openai_external_category" label="External">
|
||||
</optgroup>
|
||||
</select>
|
||||
<label for="openai_bypass_status_check" class="checkbox_label">
|
||||
<input id="openai_bypass_status_check" type="checkbox" />
|
||||
<span data-i18n="Bypass API status check">Bypass API status check</span>
|
||||
</label>
|
||||
<label for="openai_show_external_models" class="checkbox_label">
|
||||
<input id="openai_show_external_models" type="checkbox" />
|
||||
<span data-i18n="Show External models (provided by API)">Show "External" models (provided by API)</span>
|
||||
@ -4676,4 +4680,4 @@
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
@ -143,6 +143,7 @@ import {
|
||||
escapeRegex,
|
||||
resetScrollHeight,
|
||||
onlyUnique,
|
||||
getBase64Async,
|
||||
} from "./scripts/utils.js";
|
||||
|
||||
import { ModuleWorkerWrapper, doDailyExtensionUpdatesCheck, extension_settings, getContext, loadExtensionSettings, processExtensionHelpers, registerExtensionHelper, renderExtensionTemplate, runGenerationInterceptors, saveMetadataDebounced } from "./scripts/extensions.js";
|
||||
@ -184,7 +185,7 @@ import {
|
||||
} from "./scripts/instruct-mode.js";
|
||||
import { applyLocale } from "./scripts/i18n.js";
|
||||
import { getFriendlyTokenizerName, getTokenCount, getTokenizerModel, initTokenizers, saveTokenCache } from "./scripts/tokenizers.js";
|
||||
import { initPersonas, selectCurrentPersona, setPersonaDescription } from "./scripts/personas.js";
|
||||
import { createPersona, initPersonas, selectCurrentPersona, setPersonaDescription } from "./scripts/personas.js";
|
||||
import { getBackgrounds, initBackgrounds } from "./scripts/backgrounds.js";
|
||||
import { hideLoader, showLoader } from "./scripts/loader.js";
|
||||
import { CharacterContextMenu, BulkEditOverlay } from "./scripts/BulkEditOverlay.js";
|
||||
@ -1014,7 +1015,7 @@ function getBackBlock() {
|
||||
function getEmptyBlock() {
|
||||
const icons = ['fa-dragon', 'fa-otter', 'fa-kiwi-bird', 'fa-crow', 'fa-frog'];
|
||||
const texts = ['Here be dragons', 'Otterly empty', 'Kiwibunga', 'Pump-a-Rum', 'Croak it'];
|
||||
const roll = Math.floor(Math.random() * icons.length);
|
||||
const roll = new Date().getMinutes() % icons.length;
|
||||
const emptyBlock = `
|
||||
<div class="empty_block">
|
||||
<i class="fa-solid ${icons[roll]} fa-4x"></i>
|
||||
@ -4785,22 +4786,21 @@ async function read_avatar_load(input) {
|
||||
create_save.avatar = input.files;
|
||||
}
|
||||
|
||||
const e = await new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = resolve;
|
||||
reader.onerror = reject;
|
||||
reader.readAsDataURL(input.files[0]);
|
||||
})
|
||||
const file = input.files[0];
|
||||
const fileData = await getBase64Async(file);
|
||||
|
||||
$('#dialogue_popup').addClass('large_dialogue_popup wide_dialogue_popup');
|
||||
if (!power_user.never_resize_avatars) {
|
||||
$('#dialogue_popup').addClass('large_dialogue_popup wide_dialogue_popup');
|
||||
const croppedImage = await callPopup(getCropPopup(fileData), 'avatarToCrop');
|
||||
if (!croppedImage) {
|
||||
return;
|
||||
}
|
||||
|
||||
const croppedImage = await callPopup(getCropPopup(e.target.result), 'avatarToCrop');
|
||||
if (!croppedImage) {
|
||||
return;
|
||||
$("#avatar_load_preview").attr("src", croppedImage);
|
||||
} else {
|
||||
$("#avatar_load_preview").attr("src", fileData);
|
||||
}
|
||||
|
||||
$("#avatar_load_preview").attr("src", croppedImage || e.target.result);
|
||||
|
||||
if (menu_type == "create") {
|
||||
return;
|
||||
}
|
||||
@ -5162,24 +5162,19 @@ async function uploadUserAvatar(e) {
|
||||
}
|
||||
|
||||
const formData = new FormData($("#form_upload_avatar").get(0));
|
||||
|
||||
const dataUrl = await new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = resolve;
|
||||
reader.onerror = reject;
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
|
||||
$('#dialogue_popup').addClass('large_dialogue_popup wide_dialogue_popup');
|
||||
const confirmation = await callPopup(getCropPopup(dataUrl.target.result), 'avatarToCrop');
|
||||
if (!confirmation) {
|
||||
return;
|
||||
}
|
||||
|
||||
const dataUrl = await getBase64Async(file);
|
||||
let url = "/uploaduseravatar";
|
||||
|
||||
if (crop_data !== undefined) {
|
||||
url += `?crop=${encodeURIComponent(JSON.stringify(crop_data))}`;
|
||||
if (!power_user.never_resize_avatars) {
|
||||
$('#dialogue_popup').addClass('large_dialogue_popup wide_dialogue_popup');
|
||||
const confirmation = await callPopup(getCropPopup(dataUrl), 'avatarToCrop');
|
||||
if (!confirmation) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (crop_data !== undefined) {
|
||||
url += `?crop=${encodeURIComponent(JSON.stringify(crop_data))}`;
|
||||
}
|
||||
}
|
||||
|
||||
jQuery.ajax({
|
||||
@ -5190,7 +5185,7 @@ async function uploadUserAvatar(e) {
|
||||
cache: false,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
success: async function () {
|
||||
success: async function (data) {
|
||||
// If the user uploaded a new avatar, we want to make sure it's not cached
|
||||
const name = formData.get("overwrite_name");
|
||||
if (name) {
|
||||
@ -5198,6 +5193,12 @@ async function uploadUserAvatar(e) {
|
||||
reloadUserAvatar(true);
|
||||
}
|
||||
|
||||
if (data.path) {
|
||||
await getUserAvatars();
|
||||
await delay(500);
|
||||
await createPersona(data.path);
|
||||
}
|
||||
|
||||
crop_data = undefined;
|
||||
await getUserAvatars();
|
||||
},
|
||||
|
@ -223,6 +223,7 @@ const default_settings = {
|
||||
use_alt_scale: false,
|
||||
squash_system_messages: false,
|
||||
image_inlining: false,
|
||||
bypass_status_check: false,
|
||||
};
|
||||
|
||||
const oai_settings = {
|
||||
@ -270,6 +271,7 @@ const oai_settings = {
|
||||
use_alt_scale: false,
|
||||
squash_system_messages: false,
|
||||
image_inlining: false,
|
||||
bypass_status_check: false,
|
||||
};
|
||||
|
||||
let openai_setting_names;
|
||||
@ -1242,7 +1244,7 @@ function saveModelList(data) {
|
||||
$('#model_openrouter_select').empty();
|
||||
$('#model_openrouter_select').append($('<option>', { value: openrouter_website_model, text: 'Use OpenRouter website setting' }));
|
||||
model_list.forEach((model) => {
|
||||
let tokens_dollar = Number(1 / (1000 * model.pricing.prompt));
|
||||
let tokens_dollar = Number(1 / (1000 * model.pricing?.prompt));
|
||||
let tokens_rounded = (Math.round(tokens_dollar * 1000) / 1000).toFixed(0);
|
||||
let model_description = `${model.id} | ${tokens_rounded}k t/$ | ${model.context_length} ctx`;
|
||||
$('#model_openrouter_select').append(
|
||||
@ -2209,6 +2211,7 @@ function loadOpenAISettings(data, settings) {
|
||||
oai_settings.proxy_password = settings.proxy_password ?? default_settings.proxy_password;
|
||||
oai_settings.assistant_prefill = settings.assistant_prefill ?? default_settings.assistant_prefill;
|
||||
oai_settings.image_inlining = settings.image_inlining ?? default_settings.image_inlining;
|
||||
oai_settings.bypass_status_check = settings.bypass_status_check ?? default_settings.bypass_status_check;
|
||||
|
||||
oai_settings.prompts = settings.prompts ?? default_settings.prompts;
|
||||
oai_settings.prompt_order = settings.prompt_order ?? default_settings.prompt_order;
|
||||
@ -2230,6 +2233,7 @@ function loadOpenAISettings(data, settings) {
|
||||
$('#openai_proxy_password').val(oai_settings.proxy_password);
|
||||
$('#claude_assistant_prefill').val(oai_settings.assistant_prefill);
|
||||
$('#openai_image_inlining').prop('checked', oai_settings.image_inlining);
|
||||
$('#openai_bypass_status_check').prop('checked', oai_settings.bypass_status_check);
|
||||
|
||||
$('#model_openai_select').val(oai_settings.openai_model);
|
||||
$(`#model_openai_select option[value="${oai_settings.openai_model}"`).attr('selected', true);
|
||||
@ -2354,8 +2358,12 @@ async function getStatusOpen() {
|
||||
|
||||
const responseData = await response.json();
|
||||
|
||||
if (!('error' in responseData))
|
||||
if (responseData.error && responseData.can_bypass && oai_settings.bypass_status_check) {
|
||||
setOnlineStatus('Status check bypassed. Proceed with caution.');
|
||||
}
|
||||
if (!('error' in responseData)) {
|
||||
setOnlineStatus('Valid');
|
||||
}
|
||||
if ('data' in responseData && Array.isArray(responseData.data)) {
|
||||
saveModelList(responseData.data);
|
||||
}
|
||||
@ -3504,6 +3512,11 @@ $(document).ready(async function () {
|
||||
saveSettingsDebounced();
|
||||
});
|
||||
|
||||
$('#openai_bypass_status_check').on('input', function () {
|
||||
oai_settings.bypass_status_check = !!$(this).prop('checked');
|
||||
saveSettingsDebounced();
|
||||
})
|
||||
|
||||
$('#chat_completion_source').on('change', function () {
|
||||
oai_settings.chat_completion_source = String($(this).find(":selected").val());
|
||||
toggleChatCompletionForms();
|
||||
|
@ -1,7 +1,3 @@
|
||||
/**
|
||||
* This is a placeholder file for all the Persona Management code. Will be refactored into a separate file soon.
|
||||
*/
|
||||
|
||||
import { callPopup, characters, chat_metadata, default_avatar, eventSource, event_types, getRequestHeaders, getThumbnailUrl, getUserAvatars, name1, saveMetadata, saveSettingsDebounced, setUserName, this_chid, user_avatar } from "../script.js";
|
||||
import { persona_description_positions, power_user } from "./power-user.js";
|
||||
import { getTokenCount } from "./tokenizers.js";
|
||||
@ -38,6 +34,28 @@ async function uploadUserAvatar(url, name) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts the user to create a persona for the uploaded avatar.
|
||||
* @param {string} avatarId User avatar id
|
||||
* @returns {Promise} Promise that resolves when the persona is set
|
||||
*/
|
||||
export async function createPersona(avatarId) {
|
||||
const personaName = await callPopup('<h3>Enter a name for this persona:</h3>Cancel if you\'re just uploading an avatar.', 'input', '');
|
||||
|
||||
if (!personaName) {
|
||||
console.debug('User cancelled creating a persona');
|
||||
return;
|
||||
}
|
||||
|
||||
await delay(500);
|
||||
const personaDescription = await callPopup('<h3>Enter a description for this persona:</h3>You can always add or change it later.', 'input', '', { rows: 4 });
|
||||
|
||||
initPersona(avatarId, personaName, personaDescription);
|
||||
if (power_user.persona_show_notifications) {
|
||||
toastr.success(`You can now pick ${personaName} as a persona in the Persona Management menu.`, 'Persona Created');
|
||||
}
|
||||
}
|
||||
|
||||
async function createDummyPersona() {
|
||||
const personaName = await callPopup('<h3>Enter a name for this persona:</h3>', 'input', '');
|
||||
|
||||
@ -48,18 +66,28 @@ async function createDummyPersona() {
|
||||
|
||||
// Date + name (only ASCII) to make it unique
|
||||
const avatarId = `${Date.now()}-${personaName.replace(/[^a-zA-Z0-9]/g, '')}.png`;
|
||||
initPersona(avatarId, personaName, '');
|
||||
await uploadUserAvatar(default_avatar, avatarId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a persona for the given avatar id.
|
||||
* @param {string} avatarId User avatar id
|
||||
* @param {string} personaName Name for the persona
|
||||
* @param {string} personaDescription Optional description for the persona
|
||||
* @returns {void}
|
||||
*/
|
||||
export function initPersona(avatarId, personaName, personaDescription) {
|
||||
power_user.personas[avatarId] = personaName;
|
||||
power_user.persona_descriptions[avatarId] = {
|
||||
description: '',
|
||||
description: personaDescription || '',
|
||||
position: persona_description_positions.IN_PROMPT,
|
||||
};
|
||||
|
||||
await uploadUserAvatar(default_avatar, avatarId);
|
||||
saveSettingsDebounced();
|
||||
}
|
||||
|
||||
export async function convertCharacterToPersona(characterId = null) {
|
||||
|
||||
if (null === characterId) characterId = this_chid;
|
||||
|
||||
const avatarUrl = characters[characterId]?.avatar;
|
||||
|
@ -2743,7 +2743,7 @@ app.post("/getstatus_openai", jsonParser, async function (request, response_gets
|
||||
|
||||
data.data.forEach(model => {
|
||||
const context_length = model.context_length;
|
||||
const tokens_dollar = Number(1 / (1000 * model.pricing.prompt));
|
||||
const tokens_dollar = Number(1 / (1000 * model.pricing?.prompt));
|
||||
const tokens_rounded = (Math.round(tokens_dollar * 1000) / 1000).toFixed(0);
|
||||
models[model.id] = {
|
||||
tokens_per_dollar: tokens_rounded + 'k',
|
||||
@ -2764,8 +2764,8 @@ app.post("/getstatus_openai", jsonParser, async function (request, response_gets
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.log('Access Token is incorrect.');
|
||||
response_getstatus_openai.send({ error: true });
|
||||
console.log('OpenAI status check failed. Either Access Token is incorrect or API endpoint is down.');
|
||||
response_getstatus_openai.send({ error: true, can_bypass: true, data: { data: [] } });
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
Loading…
x
Reference in New Issue
Block a user