mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-02-26 17:07:46 +01:00
Merge branch 'staging' of https://github.com/SillyTavern/SillyTavern into staging
This commit is contained in:
commit
50924a0672
@ -3548,7 +3548,7 @@ export function getBiasStrings(textareaText, type) {
|
|||||||
*/
|
*/
|
||||||
function formatMessageHistoryItem(chatItem, isInstruct, forceOutputSequence) {
|
function formatMessageHistoryItem(chatItem, isInstruct, forceOutputSequence) {
|
||||||
const isNarratorType = chatItem?.extra?.type === system_message_types.NARRATOR;
|
const isNarratorType = chatItem?.extra?.type === system_message_types.NARRATOR;
|
||||||
const characterName = (selected_group || chatItem.force_avatar) ? chatItem.name : name2;
|
const characterName = chatItem?.name ? chatItem.name : name2;
|
||||||
const itemName = chatItem.is_user ? chatItem['name'] : characterName;
|
const itemName = chatItem.is_user ? chatItem['name'] : characterName;
|
||||||
const shouldPrependName = !isNarratorType;
|
const shouldPrependName = !isNarratorType;
|
||||||
|
|
||||||
|
9
public/scripts/extensions/assets/confirm.html
Normal file
9
public/scripts/extensions/assets/confirm.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<div class="m-b-1">
|
||||||
|
Are you sure you want to connect to '{{url}}'?
|
||||||
|
</div>
|
||||||
|
<div class="flex-container justifyCenter">
|
||||||
|
<label class="checkbox_label" for="assets-remember">
|
||||||
|
<input type="checkbox" id="assets-remember">
|
||||||
|
Don't ask again for this URL
|
||||||
|
</label>
|
||||||
|
</div>
|
@ -4,11 +4,11 @@ TODO:
|
|||||||
//const DEBUG_TONY_SAMA_FORK_MODE = true
|
//const DEBUG_TONY_SAMA_FORK_MODE = true
|
||||||
|
|
||||||
import { getRequestHeaders, callPopup } from "../../../script.js";
|
import { getRequestHeaders, callPopup } from "../../../script.js";
|
||||||
import { deleteExtension, extensionNames, installExtension } from "../../extensions.js";
|
import { deleteExtension, extensionNames, installExtension, renderExtensionTemplate } from "../../extensions.js";
|
||||||
import { isValidUrl } from "../../utils.js";
|
import { getStringHash, isValidUrl } from "../../utils.js";
|
||||||
export { MODULE_NAME };
|
export { MODULE_NAME };
|
||||||
|
|
||||||
const MODULE_NAME = 'Assets';
|
const MODULE_NAME = 'assets';
|
||||||
const DEBUG_PREFIX = "<Assets module> ";
|
const DEBUG_PREFIX = "<Assets module> ";
|
||||||
let previewAudio = null;
|
let previewAudio = null;
|
||||||
let ASSETS_JSON_URL = "https://raw.githubusercontent.com/SillyTavern/SillyTavern-Content/main/index.json"
|
let ASSETS_JSON_URL = "https://raw.githubusercontent.com/SillyTavern/SillyTavern-Content/main/index.json"
|
||||||
@ -75,18 +75,18 @@ function downloadAssetsList(url) {
|
|||||||
label.addClass("fa-check");
|
label.addClass("fa-check");
|
||||||
this.classList.remove('asset-download-button-loading');
|
this.classList.remove('asset-download-button-loading');
|
||||||
element.on("click", assetDelete);
|
element.on("click", assetDelete);
|
||||||
element.on("mouseenter", function(){
|
element.on("mouseenter", function () {
|
||||||
label.removeClass("fa-check");
|
label.removeClass("fa-check");
|
||||||
label.addClass("fa-trash");
|
label.addClass("fa-trash");
|
||||||
label.addClass("redOverlayGlow");
|
label.addClass("redOverlayGlow");
|
||||||
}).on("mouseleave", function(){
|
}).on("mouseleave", function () {
|
||||||
label.addClass("fa-check");
|
label.addClass("fa-check");
|
||||||
label.removeClass("fa-trash");
|
label.removeClass("fa-trash");
|
||||||
label.removeClass("redOverlayGlow");
|
label.removeClass("redOverlayGlow");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const assetDelete = async function() {
|
const assetDelete = async function () {
|
||||||
element.off("click");
|
element.off("click");
|
||||||
await deleteAsset(assetType, asset["id"]);
|
await deleteAsset(assetType, asset["id"]);
|
||||||
label.removeClass("fa-check");
|
label.removeClass("fa-check");
|
||||||
@ -102,11 +102,11 @@ function downloadAssetsList(url) {
|
|||||||
label.toggleClass("fa-download");
|
label.toggleClass("fa-download");
|
||||||
label.toggleClass("fa-check");
|
label.toggleClass("fa-check");
|
||||||
element.on("click", assetDelete);
|
element.on("click", assetDelete);
|
||||||
element.on("mouseenter", function(){
|
element.on("mouseenter", function () {
|
||||||
label.removeClass("fa-check");
|
label.removeClass("fa-check");
|
||||||
label.addClass("fa-trash");
|
label.addClass("fa-trash");
|
||||||
label.addClass("redOverlayGlow");
|
label.addClass("redOverlayGlow");
|
||||||
}).on("mouseleave", function(){
|
}).on("mouseleave", function () {
|
||||||
label.addClass("fa-check");
|
label.addClass("fa-check");
|
||||||
label.removeClass("fa-trash");
|
label.removeClass("fa-trash");
|
||||||
label.removeClass("redOverlayGlow");
|
label.removeClass("redOverlayGlow");
|
||||||
@ -274,24 +274,35 @@ async function updateCurrentAssets() {
|
|||||||
// This function is called when the extension is loaded
|
// This function is called when the extension is loaded
|
||||||
jQuery(async () => {
|
jQuery(async () => {
|
||||||
// This is an example of loading HTML from a file
|
// This is an example of loading HTML from a file
|
||||||
const windowHtml = $(await $.get(`${extensionFolderPath}/window.html`));
|
const windowHtml = $(renderExtensionTemplate(MODULE_NAME, 'window', {}));
|
||||||
|
|
||||||
const assetsJsonUrl = windowHtml.find('#assets-json-url-field');
|
const assetsJsonUrl = windowHtml.find('#assets-json-url-field');
|
||||||
assetsJsonUrl.val(ASSETS_JSON_URL);
|
assetsJsonUrl.val(ASSETS_JSON_URL);
|
||||||
|
|
||||||
const connectButton = windowHtml.find('#assets-connect-button');
|
const connectButton = windowHtml.find('#assets-connect-button');
|
||||||
connectButton.on("click", async function () {
|
connectButton.on("click", async function () {
|
||||||
const confirmation = await callPopup(`Are you sure you want to connect to '${assetsJsonUrl.val()}'?`, 'confirm')
|
const url = String(assetsJsonUrl.val());
|
||||||
|
const rememberKey = `Assets_SkipConfirm_${getStringHash(url)}`;
|
||||||
|
const skipConfirm = localStorage.getItem(rememberKey) === 'true';
|
||||||
|
|
||||||
|
const template = renderExtensionTemplate(MODULE_NAME, 'confirm', { url });
|
||||||
|
const confirmation = skipConfirm || await callPopup(template, 'confirm');
|
||||||
|
|
||||||
if (confirmation) {
|
if (confirmation) {
|
||||||
try {
|
try {
|
||||||
|
if (!skipConfirm) {
|
||||||
|
const rememberValue = Boolean($('#assets-remember').prop('checked'));
|
||||||
|
localStorage.setItem(rememberKey, String(rememberValue));
|
||||||
|
}
|
||||||
|
|
||||||
console.debug(DEBUG_PREFIX, "Confimation, loading assets...");
|
console.debug(DEBUG_PREFIX, "Confimation, loading assets...");
|
||||||
downloadAssetsList(assetsJsonUrl.val());
|
downloadAssetsList(url);
|
||||||
connectButton.removeClass("fa-plug-circle-exclamation");
|
connectButton.removeClass("fa-plug-circle-exclamation");
|
||||||
connectButton.removeClass("redOverlayGlow");
|
connectButton.removeClass("redOverlayGlow");
|
||||||
connectButton.addClass("fa-plug-circle-check");
|
connectButton.addClass("fa-plug-circle-check");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error:', error);
|
console.error('Error:', error);
|
||||||
toastr.error(`Cannot get assets list from ${assetsJsonUrl.val()}`);
|
toastr.error(`Cannot get assets list from ${url}`);
|
||||||
connectButton.removeClass("fa-plug-circle-check");
|
connectButton.removeClass("fa-plug-circle-check");
|
||||||
connectButton.addClass("fa-plug-circle-exclamation");
|
connectButton.addClass("fa-plug-circle-exclamation");
|
||||||
connectButton.removeClass("redOverlayGlow");
|
connectButton.removeClass("redOverlayGlow");
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { callPopup, eventSource, event_types, getRequestHeaders, saveSettingsDebounced } from "../../../script.js";
|
import { callPopup, eventSource, event_types, getRequestHeaders, saveSettingsDebounced, this_chid } from "../../../script.js";
|
||||||
import { dragElement, isMobile } from "../../RossAscends-mods.js";
|
import { dragElement, isMobile } from "../../RossAscends-mods.js";
|
||||||
import { getContext, getApiUrl, modules, extension_settings, ModuleWorkerWrapper, doExtrasFetch, renderExtensionTemplate } from "../../extensions.js";
|
import { getContext, getApiUrl, modules, extension_settings, ModuleWorkerWrapper, doExtrasFetch, renderExtensionTemplate } from "../../extensions.js";
|
||||||
import { loadMovingUIState, power_user } from "../../power-user.js";
|
import { loadMovingUIState, power_user } from "../../power-user.js";
|
||||||
@ -493,24 +493,6 @@ async function moduleWorker() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// character changed
|
|
||||||
if (context.groupId !== lastCharacter && context.characterId !== lastCharacter) {
|
|
||||||
removeExpression();
|
|
||||||
spriteCache = {};
|
|
||||||
|
|
||||||
//clear expression
|
|
||||||
let imgElement = document.getElementById('expression-image');
|
|
||||||
if (imgElement && imgElement instanceof HTMLImageElement) {
|
|
||||||
imgElement.src = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
//set checkbox to global var
|
|
||||||
$('#image_type_toggle').prop('checked', extension_settings.expressions.talkinghead);
|
|
||||||
if (extension_settings.expressions.talkinghead) {
|
|
||||||
setTalkingHeadState(extension_settings.expressions.talkinghead);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const vnMode = isVisualNovelMode();
|
const vnMode = isVisualNovelMode();
|
||||||
const vnWrapperVisible = $('#visual-novel-wrapper').is(':visible');
|
const vnWrapperVisible = $('#visual-novel-wrapper').is(':visible');
|
||||||
|
|
||||||
@ -531,7 +513,7 @@ async function moduleWorker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const currentLastMessage = getLastCharacterMessage();
|
const currentLastMessage = getLastCharacterMessage();
|
||||||
let spriteFolderName = getSpriteFolderName(currentLastMessage, currentLastMessage.name);
|
let spriteFolderName = context.groupId ? getSpriteFolderName(currentLastMessage, currentLastMessage.name) : getSpriteFolderName();
|
||||||
|
|
||||||
// character has no expressions or it is not loaded
|
// character has no expressions or it is not loaded
|
||||||
if (Object.keys(spriteCache).length === 0) {
|
if (Object.keys(spriteCache).length === 0) {
|
||||||
@ -1492,6 +1474,25 @@ function setExpressionOverrideHtml(forceClear = false) {
|
|||||||
moduleWorker();
|
moduleWorker();
|
||||||
dragElement($("#expression-holder"))
|
dragElement($("#expression-holder"))
|
||||||
eventSource.on(event_types.CHAT_CHANGED, () => {
|
eventSource.on(event_types.CHAT_CHANGED, () => {
|
||||||
|
// character changed
|
||||||
|
const context = getContext();
|
||||||
|
if (context.groupId !== lastCharacter && context.characterId !== lastCharacter) {
|
||||||
|
removeExpression();
|
||||||
|
spriteCache = {};
|
||||||
|
|
||||||
|
//clear expression
|
||||||
|
let imgElement = document.getElementById('expression-image');
|
||||||
|
if (imgElement && imgElement instanceof HTMLImageElement) {
|
||||||
|
imgElement.src = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
//set checkbox to global var
|
||||||
|
$('#image_type_toggle').prop('checked', extension_settings.expressions.talkinghead);
|
||||||
|
if (extension_settings.expressions.talkinghead) {
|
||||||
|
setTalkingHeadState(extension_settings.expressions.talkinghead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setExpressionOverrideHtml();
|
setExpressionOverrideHtml();
|
||||||
|
|
||||||
if (isVisualNovelMode()) {
|
if (isVisualNovelMode()) {
|
||||||
|
@ -21,9 +21,12 @@ import {
|
|||||||
reloadCurrentChat,
|
reloadCurrentChat,
|
||||||
sendMessageAsUser,
|
sendMessageAsUser,
|
||||||
name1,
|
name1,
|
||||||
|
Generate,
|
||||||
|
this_chid,
|
||||||
|
setCharacterName,
|
||||||
} from "../script.js";
|
} from "../script.js";
|
||||||
import { getMessageTimeStamp } from "./RossAscends-mods.js";
|
import { getMessageTimeStamp } from "./RossAscends-mods.js";
|
||||||
import { resetSelectedGroup } from "./group-chats.js";
|
import { resetSelectedGroup, selected_group } from "./group-chats.js";
|
||||||
import { getRegexedString, regex_placement } from "./extensions/regex/engine.js";
|
import { getRegexedString, regex_placement } from "./extensions/regex/engine.js";
|
||||||
import { chat_styles, power_user } from "./power-user.js";
|
import { chat_styles, power_user } from "./power-user.js";
|
||||||
import { autoSelectPersona } from "./personas.js";
|
import { autoSelectPersona } from "./personas.js";
|
||||||
@ -131,6 +134,7 @@ parser.addCommand('flat', setFlatModeCallback, ['default'], ' – sets the messa
|
|||||||
parser.addCommand('continue', continueChatCallback, ['cont'], ' – continues the last message in the chat', true, true);
|
parser.addCommand('continue', continueChatCallback, ['cont'], ' – continues the last message in the chat', true, true);
|
||||||
parser.addCommand('go', goToCharacterCallback, ['char'], '<span class="monospace">(name)</span> – opens up a chat with the character by its name', true, true);
|
parser.addCommand('go', goToCharacterCallback, ['char'], '<span class="monospace">(name)</span> – opens up a chat with the character by its name', true, true);
|
||||||
parser.addCommand('sysgen', generateSystemMessage, [], '<span class="monospace">(prompt)</span> – generates a system message using a specified prompt', true, true);
|
parser.addCommand('sysgen', generateSystemMessage, [], '<span class="monospace">(prompt)</span> – generates a system message using a specified prompt', true, true);
|
||||||
|
parser.addCommand('ask', askCharacter, [], '<span class="monospace">(prompt)</span> – asks a specified character card a prompt', true, true);
|
||||||
parser.addCommand('delname', deleteMessagesByNameCallback, ['cancel'], '<span class="monospace">(name)</span> – deletes all messages attributed to a specified name', true, true);
|
parser.addCommand('delname', deleteMessagesByNameCallback, ['cancel'], '<span class="monospace">(name)</span> – deletes all messages attributed to a specified name', true, true);
|
||||||
parser.addCommand('send', sendUserMessageCallback, ['add'], '<span class="monospace">(text)</span> – adds a user message to the chat log without triggering a generation', true, true);
|
parser.addCommand('send', sendUserMessageCallback, ['add'], '<span class="monospace">(text)</span> – adds a user message to the chat log without triggering a generation', true, true);
|
||||||
|
|
||||||
@ -138,6 +142,88 @@ const NARRATOR_NAME_KEY = 'narrator_name';
|
|||||||
const NARRATOR_NAME_DEFAULT = 'System';
|
const NARRATOR_NAME_DEFAULT = 'System';
|
||||||
export const COMMENT_NAME_DEFAULT = 'Note';
|
export const COMMENT_NAME_DEFAULT = 'Note';
|
||||||
|
|
||||||
|
async function askCharacter(_, text) {
|
||||||
|
// Prevent generate recursion
|
||||||
|
$('#send_textarea').val('');
|
||||||
|
|
||||||
|
// Not supported in group chats
|
||||||
|
// TODO: Maybe support group chats?
|
||||||
|
if (selected_group) {
|
||||||
|
toastr.error("Cannot run this command in a group chat!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!text) {
|
||||||
|
console.warn('WARN: No text provided for /ask command')
|
||||||
|
}
|
||||||
|
|
||||||
|
const parts = text.split('\n');
|
||||||
|
if (parts.length <= 1) {
|
||||||
|
toastr.warning('Both character name and message are required. Separate them with a new line.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grabbing the message
|
||||||
|
const name = parts.shift().trim();
|
||||||
|
let mesText = parts.join('\n').trim();
|
||||||
|
const prevChId = this_chid;
|
||||||
|
|
||||||
|
// Find the character
|
||||||
|
const chId = characters.findIndex((e) => e.name === name);
|
||||||
|
if (!characters[chId] || chId === -1) {
|
||||||
|
toastr.error("Character not found.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override character and send a user message
|
||||||
|
setCharacterId(chId);
|
||||||
|
|
||||||
|
// TODO: Maybe look up by filename instead of name
|
||||||
|
const character = characters[chId];
|
||||||
|
let force_avatar, original_avatar;
|
||||||
|
|
||||||
|
if (character && character.avatar !== 'none') {
|
||||||
|
force_avatar = getThumbnailUrl('avatar', character.avatar);
|
||||||
|
original_avatar = character.avatar;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
force_avatar = default_avatar;
|
||||||
|
original_avatar = default_avatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCharacterName(character.name);
|
||||||
|
|
||||||
|
sendMessageAsUser(mesText)
|
||||||
|
|
||||||
|
const restoreCharacter = () => {
|
||||||
|
setCharacterId(prevChId);
|
||||||
|
setCharacterName(characters[prevChId].name);
|
||||||
|
|
||||||
|
// Only force the new avatar if the character name is the same
|
||||||
|
// This skips if an error was fired
|
||||||
|
const lastMessage = chat[chat.length - 1];
|
||||||
|
if (lastMessage && lastMessage?.name === character.name) {
|
||||||
|
lastMessage.force_avatar = force_avatar;
|
||||||
|
lastMessage.original_avatar = original_avatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Kill this callback once the event fires
|
||||||
|
eventSource.removeListener(event_types.CHARACTER_MESSAGE_RENDERED, restoreCharacter)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run generate and restore previous character on error
|
||||||
|
try {
|
||||||
|
toastr.info(`Asking ${character.name} something...`);
|
||||||
|
await Generate('ask_command')
|
||||||
|
} catch {
|
||||||
|
restoreCharacter()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore previous character once message renders
|
||||||
|
// Hack for generate
|
||||||
|
eventSource.on(event_types.CHARACTER_MESSAGE_RENDERED, restoreCharacter);
|
||||||
|
}
|
||||||
|
|
||||||
async function sendUserMessageCallback(_, text) {
|
async function sendUserMessageCallback(_, text) {
|
||||||
if (!text) {
|
if (!text) {
|
||||||
console.warn('WARN: No text provided for /send command');
|
console.warn('WARN: No text provided for /send command');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user