Merge branch 'staging' of https://github.com/Tony-sama/SillyTavern into staging

This commit is contained in:
Tony Ribeiro
2023-08-23 05:11:07 +02:00
48 changed files with 2362 additions and 1336 deletions

View File

@ -1,6 +1,7 @@
import { getBase64Async } from "../../utils.js";
import { getContext, getApiUrl, doExtrasFetch, extension_settings } from "../../extensions.js";
import { callPopup, saveSettingsDebounced } from "../../../script.js";
import { getMessageTimeStamp } from "../../RossAscends-mods.js";
export { MODULE_NAME };
const MODULE_NAME = 'caption';
@ -52,7 +53,7 @@ async function sendCaptionedMessage(caption, image) {
name: context.name1,
is_user: true,
is_name: true,
send_date: Date.now(),
send_date: getMessageTimeStamp(),
mes: messageText,
extra: {
image: image,

View File

@ -23,7 +23,8 @@ const defaultSettings = {
};
const settingType = {
guidance_scale: 0,
negative_prompt: 1
negative_prompt: 1,
positive_prompt: 2
}
// Used for character and chat CFG values
@ -36,19 +37,19 @@ function setCharCfg(tempValue, setting) {
const avatarName = getCharaFilename();
// Assign temp object
let tempCharaCfg;
let tempCharaCfg = {
name: avatarName
};
switch(setting) {
case settingType.guidance_scale:
tempCharaCfg = {
"name": avatarName,
"guidance_scale": Number(tempValue)
}
tempCharaCfg["guidance_scale"] = Number(tempValue);
break;
case settingType.negative_prompt:
tempCharaCfg = {
"name": avatarName,
"negative_prompt": tempValue
}
tempCharaCfg["negative_prompt"] = tempValue;
break;
case settingType.positive_prompt:
tempCharaCfg["positive_prompt"] = tempValue;
break;
default:
return false;
@ -66,7 +67,11 @@ function setCharCfg(tempValue, setting) {
const tempAssign = Object.assign(existingCharaCfg, tempCharaCfg);
// If both values are default, remove the entry
if (!existingCharaCfg.useChara && (tempAssign.guidance_scale ?? 1.00) === 1.00 && (tempAssign.negative_prompt?.length ?? 0) === 0) {
if (!existingCharaCfg.useChara &&
(tempAssign.guidance_scale ?? 1.00) === 1.00 &&
(tempAssign.negative_prompt?.length ?? 0) === 0 &&
(tempAssign.positive_prompt?.length ?? 0) === 0)
{
extension_settings.cfg.chara.splice(existingCharaCfgIndex, 1);
}
} else if (avatarName && tempValue.length > 0) {
@ -95,6 +100,9 @@ function setChatCfg(tempValue, setting) {
case settingType.negative_prompt:
chat_metadata[metadataKeys.negative_prompt] = tempValue;
break;
case settingType.positive_prompt:
chat_metadata[metadataKeys.positive_prompt] = tempValue;
break;
default:
return false;
}
@ -174,20 +182,40 @@ function loadSettings() {
$('#chat_cfg_guidance_scale').val(chat_metadata[metadataKeys.guidance_scale] ?? 1.0.toFixed(2));
$('#chat_cfg_guidance_scale_counter').text(chat_metadata[metadataKeys.guidance_scale]?.toFixed(2) ?? 1.0.toFixed(2));
$('#chat_cfg_negative_prompt').val(chat_metadata[metadataKeys.negative_prompt] ?? '');
$('#chat_cfg_positive_prompt').val(chat_metadata[metadataKeys.positive_prompt] ?? '');
$('#groupchat_cfg_use_chara').prop('checked', chat_metadata[metadataKeys.groupchat_individual_chars] ?? false);
if (chat_metadata[metadataKeys.negative_combine]?.length > 0) {
chat_metadata[metadataKeys.negative_combine].forEach((element) => {
$(`input[name="cfg_negative_combine"][value="${element}"]`)
if (chat_metadata[metadataKeys.prompt_combine]?.length > 0) {
chat_metadata[metadataKeys.prompt_combine].forEach((element) => {
$(`input[name="cfg_prompt_combine"][value="${element}"]`)
.prop("checked", true);
});
}
// Display the negative separator in quotes if not quoted already
let promptSeparatorDisplay = [];
const promptSeparator = chat_metadata[metadataKeys.prompt_separator];
if (promptSeparator) {
promptSeparatorDisplay.push(promptSeparator);
if (!promptSeparator.startsWith(`"`)) {
promptSeparatorDisplay.unshift(`"`);
}
if (!promptSeparator.endsWith(`"`)) {
promptSeparatorDisplay.push(`"`);
}
}
$('#cfg_prompt_separator').val(promptSeparatorDisplay.length === 0 ? '' : promptSeparatorDisplay.join(''));
$('#cfg_prompt_insertion_depth').val(chat_metadata[metadataKeys.prompt_insertion_depth] ?? 1);
// Set character CFG if it exists
if (!selected_group) {
const charaCfg = extension_settings.cfg.chara.find((e) => e.name === getCharaFilename());
$('#chara_cfg_guidance_scale').val(charaCfg?.guidance_scale ?? 1.00);
$('#chara_cfg_guidance_scale_counter').text(charaCfg?.guidance_scale?.toFixed(2) ?? 1.0.toFixed(2));
$('#chara_cfg_negative_prompt').val(charaCfg?.negative_prompt ?? '');
$('#chara_cfg_positive_prompt').val(charaCfg?.positive_prompt ?? '');
}
}
@ -204,26 +232,50 @@ async function initialLoadSettings() {
$('#global_cfg_guidance_scale').val(extension_settings.cfg.global.guidance_scale);
$('#global_cfg_guidance_scale_counter').text(extension_settings.cfg.global.guidance_scale.toFixed(2));
$('#global_cfg_negative_prompt').val(extension_settings.cfg.global.negative_prompt);
$('#global_cfg_positive_prompt').val(extension_settings.cfg.global.positive_prompt);
}
function migrateSettings() {
let performSave = false;
let performSettingsSave = false;
let performMetaSave = false;
if (power_user.guidance_scale) {
extension_settings.cfg.global.guidance_scale = power_user.guidance_scale;
delete power_user['guidance_scale'];
performSave = true;
performSettingsSave = true;
}
if (power_user.negative_prompt) {
extension_settings.cfg.global.negative_prompt = power_user.negative_prompt;
delete power_user['negative_prompt'];
performSave = true;
performSettingsSave = true;
}
if (performSave) {
if (chat_metadata["cfg_negative_combine"]) {
chat_metadata[metadataKeys.prompt_combine] = chat_metadata["cfg_negative_combine"];
chat_metadata["cfg_negative_combine"] = undefined;
performMetaSave = true;
}
if (chat_metadata["cfg_negative_insertion_depth"]) {
chat_metadata[metadataKeys.prompt_insertion_depth] = chat_metadata["cfg_negative_insertion_depth"];
chat_metadata["cfg_negative_insertion_depth"] = undefined;
performMetaSave = true;
}
if (chat_metadata["cfg_negative_separator"]) {
chat_metadata[metadataKeys.prompt_separator] = chat_metadata["cfg_negative_separator"];
chat_metadata["cfg_negative_separator"] = undefined;
performMetaSave = true;
}
if (performSettingsSave) {
saveSettingsDebounced();
}
if (performMetaSave) {
saveMetadataDebounced();
}
}
// This function is called when the extension is loaded
@ -255,6 +307,10 @@ jQuery(async () => {
setChatCfg($(this).val(), settingType.negative_prompt);
});
windowHtml.find('#chat_cfg_positive_prompt').on('input', function() {
setChatCfg($(this).val(), settingType.positive_prompt);
});
windowHtml.find('#chara_cfg_guidance_scale').on('input', function() {
const value = $(this).val();
const success = setCharCfg(value, settingType.guidance_scale);
@ -267,6 +323,10 @@ jQuery(async () => {
setCharCfg($(this).val(), settingType.negative_prompt);
});
windowHtml.find('#chara_cfg_positive_prompt').on('input', function() {
setCharCfg($(this).val(), settingType.positive_prompt);
});
windowHtml.find('#global_cfg_guidance_scale').on('input', function() {
extension_settings.cfg.global.guidance_scale = Number($(this).val());
$('#global_cfg_guidance_scale_counter').text(extension_settings.cfg.global.guidance_scale.toFixed(2));
@ -278,14 +338,29 @@ jQuery(async () => {
saveSettingsDebounced();
});
windowHtml.find(`input[name="cfg_negative_combine"]`).on('input', function() {
const values = windowHtml.find(`input[name="cfg_negative_combine"]`)
windowHtml.find('#global_cfg_positive_prompt').on('input', function() {
extension_settings.cfg.global.positive_prompt = $(this).val();
saveSettingsDebounced();
});
windowHtml.find(`input[name="cfg_prompt_combine"]`).on('input', function() {
const values = windowHtml.find(`input[name="cfg_prompt_combine"]`)
.filter(":checked")
.map(function() { return parseInt($(this).val()) })
.get()
.filter((e) => e !== NaN) || [];
chat_metadata[metadataKeys.negative_combine] = values;
chat_metadata[metadataKeys.prompt_combine] = values;
saveMetadataDebounced();
});
windowHtml.find(`#cfg_prompt_insertion_depth`).on('input', function() {
chat_metadata[metadataKeys.prompt_insertion_depth] = Number($(this).val());
saveMetadataDebounced();
});
windowHtml.find(`#cfg_prompt_separator`).on('input', function() {
chat_metadata[metadataKeys.prompt_separator] = $(this).val();
saveMetadataDebounced();
});

View File

@ -1,4 +1,4 @@
import { chat_metadata, this_chid } from "../../../script.js";
import { chat_metadata, substituteParams, this_chid } from "../../../script.js";
import { extension_settings, getContext } from "../../extensions.js"
import { selected_group } from "../../group-chats.js";
import { getCharaFilename } from "../../utils.js";
@ -11,46 +11,20 @@ export const cfgType = {
export const metadataKeys = {
guidance_scale: "cfg_guidance_scale",
negative_prompt: "cfg_negative_prompt",
negative_combine: "cfg_negative_combine",
groupchat_individual_chars: "cfg_groupchat_individual_chars"
positive_prompt: "cfg_positive_prompt",
prompt_combine: "cfg_prompt_combine",
groupchat_individual_chars: "cfg_groupchat_individual_chars",
prompt_insertion_depth: "cfg_prompt_insertion_depth",
prompt_separator: "cfg_prompt_separator"
}
// Gets the CFG value from hierarchy of chat -> character -> global
// Returns undefined values which should be handled in the respective backend APIs
export function getCfg() {
let splitNegativePrompt = [];
// Gets the CFG guidance scale
// If the guidance scale is 1, ignore the CFG prompt(s) since it won't be used anyways
export function getGuidanceScale() {
const charaCfg = extension_settings.cfg.chara?.find((e) => e.name === getCharaFilename(this_chid));
const guidanceScale = getGuidanceScale(charaCfg);
const chatNegativeCombine = chat_metadata[metadataKeys.negative_combine] ?? [];
// If there's a guidance scale, continue. Otherwise assume undefined
if (guidanceScale?.value && guidanceScale?.value !== 1) {
if (guidanceScale.type === cfgType.chat || chatNegativeCombine.includes(cfgType.chat)) {
splitNegativePrompt.push(chat_metadata[metadataKeys.negative_prompt]?.trim());
}
if (guidanceScale.type === cfgType.chara || chatNegativeCombine.includes(cfgType.chara)) {
splitNegativePrompt.push(charaCfg.negative_prompt?.trim())
}
if (guidanceScale.type === cfgType.global || chatNegativeCombine.includes(cfgType.global)) {
splitNegativePrompt.push(extension_settings.cfg.global.negative_prompt?.trim());
}
const combinedNegatives = splitNegativePrompt.filter((e) => e.length > 0).join(", ");
console.debug(`Setting CFG with guidance scale: ${guidanceScale.value}, negatives: ${combinedNegatives}`)
return {
guidanceScale: guidanceScale.value,
negativePrompt: combinedNegatives
}
}
}
// If the guidance scale is 1, ignore the CFG negative prompt since it won't be used anyways
function getGuidanceScale(charaCfg) {
const chatGuidanceScale = chat_metadata[metadataKeys.guidance_scale];
const groupchatCharOverride = chat_metadata[metadataKeys.groupchat_individual_chars] ?? false;
if (chatGuidanceScale && chatGuidanceScale !== 1 && !groupchatCharOverride) {
return {
type: cfgType.chat,
@ -70,3 +44,48 @@ function getGuidanceScale(charaCfg) {
value: extension_settings.cfg.global.guidance_scale
};
}
// Gets the CFG prompt
export function getCfgPrompt(guidanceScale, isNegative) {
let splitCfgPrompt = [];
const cfgPromptCombine = chat_metadata[metadataKeys.prompt_combine] ?? [];
if (guidanceScale.type === cfgType.chat || cfgPromptCombine.includes(cfgType.chat)) {
splitCfgPrompt.unshift(
substituteParams(
chat_metadata[isNegative ? metadataKeys.negative_prompt : metadataKeys.positive_prompt]
)
?.trim()
);
}
const charaCfg = extension_settings.cfg.chara?.find((e) => e.name === getCharaFilename(this_chid));
if (guidanceScale.type === cfgType.chara || cfgPromptCombine.includes(cfgType.chara)) {
splitCfgPrompt.unshift(
substituteParams(
isNegative ? charaCfg.negative_prompt : charaCfg.positive_prompt
)
?.trim()
);
}
if (guidanceScale.type === cfgType.global || cfgPromptCombine.includes(cfgType.global)) {
splitCfgPrompt.unshift(
substituteParams(
isNegative ? extension_settings.cfg.global.negative_prompt : extension_settings.cfg.global.positive_prompt
)
?.trim()
);
}
// This line is a bit hacky with a JSON.stringify and JSON.parse. Fix this if possible.
const customSeparator = JSON.parse(chat_metadata[metadataKeys.prompt_separator] || JSON.stringify("\n")) ?? "\n";
const combinedCfgPrompt = splitCfgPrompt.filter((e) => e.length > 0).join(customSeparator);
const insertionDepth = chat_metadata[metadataKeys.prompt_insertion_depth] ?? 1;
console.log(`Setting CFG with guidance scale: ${guidanceScale.value}, negatives: ${combinedCfgPrompt}`);
return {
value: combinedCfgPrompt,
depth: insertionDepth
};
}

View File

@ -14,7 +14,7 @@
<small>
<b>Unique to this chat.</b><br>
</small>
<label for="chat_cfg_negative_prompt">
<label for="chat_cfg_guidance_scale">
<span data-i18n="Scale">Scale</span>
<small data-i18n="1 = disabled">1 = disabled</small>
</label>
@ -33,6 +33,11 @@
<span data-i18n="Negative Prompt">Negative Prompt</span>
</label>
<textarea id="chat_cfg_negative_prompt" rows="2" class="text_pole textarea_compact" data-i18n="[placeholder]write short replies, write replies using past tense" placeholder="write short replies, write replies using past tense"></textarea>
<label for="chat_cfg_positive_prompt">
<span data-i18n="Positive Prompt">Positive Prompt</span>
</label>
<textarea id="chat_cfg_positive_prompt" rows="2" class="text_pole textarea_compact" data-i18n="[placeholder]write short replies, write replies using past tense" placeholder="write short replies, write replies using past tense"></textarea>
</div>
<div id="groupchat_cfg_use_chara_container">
<label class="checkbox_label" for="groupchat_cfg_use_chara">
@ -53,7 +58,7 @@
<div class="inline-drawer-content">
<small><b>Will be automatically added as the CFG for this character.</b></small>
<br />
<label for="chara_cfg_negative_prompt">
<label for="chara_cfg_guidance_scale">
<span data-i18n="Scale">Scale</span>
<small data-i18n="1 = disabled">1 = disabled</small>
</label>
@ -72,6 +77,11 @@
<span data-i18n="Negative Prompt">Negative Prompt</span>
</label>
<textarea id="chara_cfg_negative_prompt" rows="2" class="text_pole textarea_compact" data-i18n="[placeholder]write short replies, write replies using past tense" placeholder="write short replies, write replies using past tense"></textarea>
<label for="chara_cfg_positive_prompt">
<span data-i18n="Positive Prompt">Positive Prompt</span>
</label>
<textarea id="chara_cfg_positive_prompt" rows="2" class="text_pole textarea_compact" data-i18n="[placeholder]write short replies, write replies using past tense" placeholder="write short replies, write replies using past tense"></textarea>
</div>
</div>
</div>
@ -86,7 +96,7 @@
<div class="inline-drawer-content">
<small><b>Will be used as the default CFG options for every chat unless overridden.</b></small>
<br />
<label for="global_cfg_negative_prompt">
<label for="global_cfg_guidance_scale">
<span data-i18n="Scale">Scale</span>
<small data-i18n="1 = disabled">1 = disabled</small>
</label>
@ -105,39 +115,56 @@
<span data-i18n="Negative Prompt">Negative Prompt</span>
</label>
<textarea id="global_cfg_negative_prompt" rows="2" class="text_pole textarea_compact" data-i18n="[placeholder]write short replies, write replies using past tense" placeholder="write short replies, write replies using past tense"></textarea>
<label for="global_cfg_positive_prompt">
<span data-i18n="Positive Prompt">Positive Prompt</span>
</label>
<textarea id="global_cfg_positive_prompt" rows="2" class="text_pole textarea_compact" data-i18n="[placeholder]write short replies, write replies using past tense" placeholder="write short replies, write replies using past tense"></textarea>
</div>
</div>
</div>
</div>
<div id="cfg_negative_combine_container">
<div id="cfg_prompt_combine_container">
<hr class="sysHR">
<div class="inline-drawer">
<div id="defaultANBlockToggle" class="inline-drawer-toggle inline-drawer-header">
<b>Negative Cascading</b>
<b>CFG Prompt Cascading</b>
<div class="inline-drawer-icon fa-solid fa-circle-chevron-down down"></div>
</div>
<div class="inline-drawer-content">
<small>
<b>Combine negative prompts from other boxes.</b>
<br />
For example, ticking the chat, global, and character boxes combine all negative prompts into a comma-separated string.
</small>
<div class="flex-container flexFlowColumn">
<small>
<b>Combine positive/negative prompts from other boxes.</b>
<br />
For example, ticking the chat, global, and character boxes combine all negative prompts into a comma-separated string.
</small>
</div>
<br />
<label for="cfg_negative_combine">
<span data-i18n="Scale">Always Include</span>
</label>
<label class="checkbox_label">
<input type="checkbox" name="cfg_negative_combine" value="0" />
<span data-i18n="Chat Negatives">Chat Negatives</span>
</label>
<label class="checkbox_label">
<input type="checkbox" name="cfg_negative_combine" value="1" />
<span data-i18n="Character Negatives">Character Negatives</span>
</label>
<label class="checkbox_label">
<input type="checkbox" name="cfg_negative_combine" value="2" />
<span data-i18n="Global Negatives">Global Negatives</span>
</label>
<div class="flex-container flexFlowColumn">
<label for="cfg_prompt_combine">
<span data-i18n="Scale">Always Include</span>
</label>
<label class="checkbox_label">
<input type="checkbox" name="cfg_prompt_combine" value="0" />
<span data-i18n="Chat Negatives">Chat Negatives</span>
</label>
<label class="checkbox_label">
<input type="checkbox" name="cfg_prompt_combine" value="1" />
<span data-i18n="Character Negatives">Character Negatives</span>
</label>
<label class="checkbox_label">
<input type="checkbox" name="cfg_prompt_combine" value="2" />
<span data-i18n="Global Negatives">Global Negatives</span>
</label>
</div>
<div class="flex-container flexFlowColumn">
<label>
Custom Separator: <input id="cfg_prompt_separator" class="text_pole textarea_compact widthUnset" placeholder="&quot;\n&quot;" type="text" />
</label>
<label>
Insertion Depth: <input id="cfg_prompt_insertion_depth" class="text_pole widthUnset" type="number" min="0" max="99" />
</label>
</div>
</div>
</div>
</div>

View File

@ -1,6 +1,7 @@
import { saveSettingsDebounced, getCurrentChatId, system_message_types, extension_prompt_types, eventSource, event_types, getRequestHeaders, CHARACTERS_PER_TOKEN_RATIO, substituteParams, max_context, } from "../../../script.js";
import { saveSettingsDebounced, getCurrentChatId, system_message_types, extension_prompt_types, eventSource, event_types, getRequestHeaders, substituteParams, } from "../../../script.js";
import { humanizedDateTime } from "../../RossAscends-mods.js";
import { getApiUrl, extension_settings, getContext, doExtrasFetch } from "../../extensions.js";
import { CHARACTERS_PER_TOKEN_RATIO } from "../../tokenizers.js";
import { getFileText, onlyUnique, splitRecursive } from "../../utils.js";
export { MODULE_NAME };

View File

@ -28,7 +28,7 @@ async function updateQuickReplyPresetList() {
if (result.ok) {
var data = await result.json();
presets = data.quickReplyPresets?.length ? data.quickReplyPresets : [];
console.log(presets)
console.debug('Quick Reply presets', presets);
$("#quickReplyPresets").find('option[value!=""]').remove();
@ -284,7 +284,7 @@ async function doQR(_, text) {
}
text = Number(text)
//use scale starting with 0
//use scale starting with 0
//ex: user inputs "/qr 2" >> qr with data-index 1 (but 2nd item displayed) gets triggered
let QRnum = Number(text - 1)
if (QRnum <= 0) { QRnum = 0 }

View File

@ -4,11 +4,12 @@ TODO:
*/
import { saveSettingsDebounced } from "../../../script.js";
import { getContext, getApiUrl, modules, extension_settings, ModuleWorkerWrapper, doExtrasFetch } from "../../extensions.js";
import { getContext, extension_settings, ModuleWorkerWrapper } from "../../extensions.js";
import { VoskSttProvider } from './vosk.js'
import { WhisperSttProvider } from './whisper.js'
import { BrowserSttProvider } from './browser.js'
import { StreamingSttProvider } from './streaming.js'
import { getMessageTimeStamp } from "../../RossAscends-mods.js";
export { MODULE_NAME };
const MODULE_NAME = 'Speech Recognition';
@ -61,10 +62,10 @@ async function moduleWorker() {
let messageStart = -1;
if (extension_settings.speech_recognition.Streaming.triggerWordsEnabled) {
for (const triggerWord of extension_settings.speech_recognition.Streaming.triggerWords) {
const triggerPos = userMessageRaw.indexOf(triggerWord.toLowerCase());
// Trigger word not found or not starting message and just a substring
if (triggerPos == -1){ // | (triggerPos > 0 & userMessageFormatted[triggerPos-1] != " ")) {
console.debug(DEBUG_PREFIX+"trigger word not found: ", triggerWord);
@ -152,12 +153,12 @@ async function processTranscript(transcript) {
name: context.name1,
is_user: true,
is_name: true,
send_date: Date.now(),
send_date: getMessageTimeStamp(),
mes: messageText,
};
context.chat.push(message);
context.addOneMessage(message);
await context.generate();
$('#debug_output').text("<SST-module DEBUG>: message sent: \""+ transcriptFormatted +"\"");
@ -191,10 +192,10 @@ async function processTranscript(transcript) {
function loadNavigatorAudioRecording() {
if (navigator.mediaDevices.getUserMedia) {
console.debug(DEBUG_PREFIX+' getUserMedia supported by browser.');
let onSuccess = function(stream) {
const mediaRecorder = new MediaRecorder(stream);
$("#microphone_button").off('click').on("click", function() {
if (!audioRecording) {
mediaRecorder.start();
@ -211,30 +212,30 @@ function loadNavigatorAudioRecording() {
$("#microphone_button").toggleClass('fa-microphone fa-microphone-slash');
}
});
mediaRecorder.onstop = async function() {
console.debug(DEBUG_PREFIX+"data available after MediaRecorder.stop() called: ", audioChunks.length, " chunks");
const audioBlob = new Blob(audioChunks, { type: "audio/wav; codecs=0" });
audioChunks = [];
const transcript = await sttProvider.processAudio(audioBlob);
// TODO: lock and release recording while processing?
console.debug(DEBUG_PREFIX+"received transcript:", transcript);
processTranscript(transcript);
}
mediaRecorder.ondataavailable = function(e) {
audioChunks.push(e.data);
}
}
let onError = function(err) {
console.debug(DEBUG_PREFIX+"The following error occured: " + err);
}
navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);
} else {
console.debug(DEBUG_PREFIX+"getUserMedia not supported on your browser!");
toastr.error("getUserMedia not supported", DEBUG_PREFIX+"not supported for your browser.", { timeOut: 10000, extendedTimeOut: 20000, preventDuplicates: true });
@ -257,7 +258,7 @@ function loadSttProvider(provider) {
console.warn(`Provider ${sttProviderName} not in Extension Settings, initiatilizing provider in settings`);
extension_settings.speech_recognition[sttProviderName] = {};
}
$('#speech_recognition_provider').val(sttProviderName);
if (sttProviderName == "None") {
@ -287,13 +288,13 @@ function loadSttProvider(provider) {
loadNavigatorAudioRecording();
$("#microphone_button").show();
}
if (sttProviderName == "Streaming") {
sttProvider.loadSettings(extension_settings.speech_recognition[sttProviderName]);
$("#microphone_button").off('click');
$("#microphone_button").hide();
}
}
function onSttProviderChange() {
@ -365,7 +366,7 @@ async function onMessageMappingChange() {
console.debug(DEBUG_PREFIX+"Wrong syntax for message mapping, no '=' found in:", text);
}
}
$("#speech_recognition_message_mapping_status").text("Message mapping updated to: "+JSON.stringify(extension_settings.speech_recognition.messageMapping))
console.debug(DEBUG_PREFIX+"Updated message mapping", extension_settings.speech_recognition.messageMapping);
extension_settings.speech_recognition.messageMappingText = $('#speech_recognition_message_mapping').val()
@ -425,7 +426,7 @@ $(document).ready(function () {
$('#speech_recognition_message_mode').on('change', onMessageModeChange);
$('#speech_recognition_message_mapping').on('change', onMessageMappingChange);
$('#speech_recognition_message_mapping_enabled').on('click', onMessageMappingEnabledClick);
const $button = $('<div id="microphone_button" class="fa-solid fa-microphone speech-toggle" title="Click to speak"></div>');
$('#send_but_sheld').prepend($button);

View File

@ -14,7 +14,7 @@ import {
import { getApiUrl, getContext, extension_settings, doExtrasFetch, modules } from "../../extensions.js";
import { selected_group } from "../../group-chats.js";
import { stringFormat, initScrollHeight, resetScrollHeight, timestampToMoment, getCharaFilename, saveBase64AsFile } from "../../utils.js";
import { humanizedDateTime } from "../../RossAscends-mods.js";
import { getMessageTimeStamp, humanizedDateTime } from "../../RossAscends-mods.js";
export { MODULE_NAME };
// Wraps a string into monospace font-face span
@ -755,11 +755,10 @@ async function sendMessage(prompt, image) {
const messageText = `[${context.name2} sends a picture that contains: ${prompt}]`;
const message = {
name: context.groupId ? systemUserName : context.name2,
is_system: context.groupId ? true : false,
is_user: false,
is_system: true,
is_name: true,
send_date: timestampToMoment(Date.now()).format('LL LT'),
send_date: getMessageTimeStamp(),
mes: context.groupId ? p(messageText) : messageText,
extra: {
image: image,

View File

@ -1,6 +1,6 @@
import { callPopup, main_api } from "../../../script.js";
import { getContext } from "../../extensions.js";
import { getTokenizerModel } from "../../openai.js";
import { getTokenizerModel } from "../../tokenizers.js";
async function doTokenCounter() {
const selectedTokenizer = main_api == 'openai'

View File

@ -421,9 +421,9 @@ jQuery(() => {
loadSettings();
eventSource.on(event_types.MESSAGE_RECEIVED, handleIncomingMessage);
eventSource.on(event_types.CHARACTER_MESSAGE_RENDERED, handleIncomingMessage);
eventSource.on(event_types.MESSAGE_SWIPED, handleIncomingMessage);
eventSource.on(event_types.MESSAGE_SENT, handleOutgoingMessage);
eventSource.on(event_types.USER_MESSAGE_RENDERED, handleOutgoingMessage);
eventSource.on(event_types.IMPERSONATE_READY, handleImpersonateReady);
eventSource.on(event_types.MESSAGE_EDITED, handleMessageEdit);

View File

@ -0,0 +1,66 @@
import { getContext } from "../../extensions.js";
/**
* Gets a chat variable from the current chat metadata.
* @param {string} name The name of the variable to get.
* @returns {string} The value of the variable.
*/
function getChatVariable(name) {
const metadata = getContext().chatMetadata;
if (!metadata) {
return '';
}
if (!metadata.variables) {
metadata.variables = {};
return '';
}
return metadata.variables[name] || '';
}
/**
* Sets a chat variable in the current chat metadata.
* @param {string} name The name of the variable to set.
* @param {any} value The value of the variable to set.
*/
function setChatVariable(name, value) {
if (name === undefined || value === undefined) {
return;
}
const metadata = getContext().chatMetadata;
if (!metadata) {
return;
}
if (!metadata.variables) {
metadata.variables = {};
}
metadata.variables[name] = value;
}
function listChatVariables() {
const metadata = getContext().chatMetadata;
if (!metadata) {
return '';
}
if (!metadata.variables) {
metadata.variables = {};
return '';
}
return Object.keys(metadata.variables).map(key => `${key}=${metadata.variables[key]}`).join(';');
}
jQuery(() => {
const context = getContext();
context.registerHelper('getvar', getChatVariable);
context.registerHelper('setvar', setChatVariable);
context.registerHelper('listvar', listChatVariables);
});

View File

@ -0,0 +1,11 @@
{
"display_name": "Chat Variables",
"loading_order": 100,
"requires": [],
"optional": [],
"js": "index.js",
"css": "",
"author": "Cohee#1207",
"version": "1.0.0",
"homePage": "https://github.com/SillyTavern/SillyTavern"
}