"gradually replacing property access with a dot operator" (#4965)

* "gradually replacing property access with a dot operator"
https://github.com/SillyTavern/SillyTavern/pull/4963#discussion_r2663003561

(?<=\w|\])\['([a-zA-Z]\w+)'\]
My regex found 593 matches across 47 files.
Also, two typos.

* Fixed chat[0].chat_metadata type error.
https://github.com/SillyTavern/SillyTavern/pull/4965#discussion_r2664275854

* Fixed `swipedElementsDiv[0]?.getAnimations().filter((a) => a.animationName` type error.
https://github.com/SillyTavern/SillyTavern/pull/4965#discussion_r2664274593

* Fixed config.MESSAGE_SANITIZE and config.MESSAGE_ALLOW_SYSTEM_UI type errors.
https://github.com/SillyTavern/SillyTavern/pull/4965#discussion_r2664266271

* Fixed group.date_last_chat type error.
https://github.com/SillyTavern/SillyTavern/pull/4965#discussion_r2664295652

* Reverted SlashCommandParser dot property access.
https://github.com/SillyTavern/SillyTavern/pull/4965#discussion_r2664310931

* LLM fixed canUseNegativeLookbehind.result; type error.
https://github.com/SillyTavern/SillyTavern/pull/4965#discussion_r2664314288

* Reverted chat-completions.js bodyParams and headers dot property access.

https://github.com/SillyTavern/SillyTavern/pull/4965#discussion_r2664317848
https://github.com/SillyTavern/SillyTavern/pull/4965#discussion_r2664320088
https://github.com/SillyTavern/SillyTavern/pull/4965#discussion_r2664324438

* Reverted openai.js data dot property access.

https://github.com/SillyTavern/SillyTavern/pull/4965#discussion_r2664326244

* Reverted tests/frontend/MacroEnvBuilder.e2e.js env.dynamicMacros dot property access.

https://github.com/SillyTavern/SillyTavern/pull/4965#discussion_r2664330990

* Partially reverted `window` dot property access.

* Reverted result.json() and settings dot property access.

* Reverted google.js headers dot property access.

* Fixed regex: `(?<=\w|\])\['([a-zA-Z]\w*)'\]`

* Swapped window to globalThis with dot property access.

* LLM fixed canUseNegativeLookbehind type.

* Refactor property access

* Consistency

---------

Co-authored-by: user <user@exmaple.com>
Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
This commit is contained in:
DeclineThyself
2026-01-08 21:58:21 +00:00
committed by GitHub
parent f6a2def403
commit 8372e7bf9d
44 changed files with 462 additions and 442 deletions
+9
View File
@@ -38,6 +38,7 @@ declare global {
avatar_url?: string;
hideMutedSprites?: boolean;
fav?: boolean;
date_last_chat?: MessageTimestamp;
}
interface ChatFile extends Array<ChatMessage> {
@@ -235,3 +236,11 @@ declare global {
type SwipeEvent = JQuery.TriggeredEvent<any, any, HTMLElement, HTMLElement>;
}
//Overrides for public/scripts/chats.js
declare module 'dompurify' {
interface Config {
MESSAGE_SANITIZE?: boolean;
MESSAGE_ALLOW_SYSTEM_UI?: boolean;
}
}
+197 -192
View File
@@ -1176,8 +1176,8 @@ export async function getOneCharacter(avatarUrl) {
if (response.ok) {
const getData = await response.json();
getData['name'] = DOMPurify.sanitize(getData['name']);
getData['chat'] = String(getData['chat']);
getData.name = DOMPurify.sanitize(getData.name);
getData.chat = String(getData.chat);
const indexOf = characters.findIndex(x => x.avatar === avatarUrl);
@@ -1248,14 +1248,14 @@ export async function getCharacters() {
const getData = await response.json();
for (let i = 0; i < getData.length; i++) {
characters[i] = getData[i];
characters[i]['name'] = DOMPurify.sanitize(characters[i]['name']);
characters[i].name = DOMPurify.sanitize(characters[i].name);
// For dropped-in cards
if (!characters[i]['chat']) {
characters[i]['chat'] = `${characters[i]['name']} - ${humanizedDateTime()}`;
if (!characters[i].chat) {
characters[i].chat = `${characters[i].name} - ${humanizedDateTime()}`;
}
characters[i]['chat'] = String(characters[i]['chat']);
characters[i].chat = String(characters[i].chat);
}
if (previousAvatar) {
@@ -1555,7 +1555,7 @@ export async function deleteMessage(id, swipeDeletionIndex = undefined, askConfi
chat.splice(id, 1);
messageElement.remove();
chat_metadata['tainted'] = true;
chat_metadata.tainted = true;
const startIndex = [0, minId].includes(id) ? id : null;
updateViewMessageIds(startIndex);
@@ -1625,8 +1625,8 @@ export async function sendTextareaMessage() {
!textareaText &&
!selected_group &&
chat.length &&
!lastMessage['is_user'] &&
!lastMessage['is_system']
!lastMessage.is_user &&
!lastMessage.is_system
) {
generateType = 'continue';
}
@@ -2406,7 +2406,7 @@ export function addCopyToCodeBlocks(messageElement) {
* @returns {void}
*/
export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll = true, insertBefore = null, forceId = null, showSwipes = true } = {}) {
let messageText = mes['mes'];
let messageText = mes.mes;
const momentDate = timestampToMoment(mes.send_date);
const timestamp = momentDate.isValid() ? momentDate.format('LL LT') : '';
@@ -2425,8 +2425,8 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll
const isSystem = mes.is_system;
const title = mes.title;
//for non-user mesages
if (!mes['is_user']) {
//for non-user messages
if (!mes.is_user) {
if (mes.force_avatar) {
avatarImg = mes.force_avatar;
} else if (this_chid === undefined) {
@@ -2442,9 +2442,9 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll
//if messge is from sytem, use the name provided in the message JSONL to proceed,
//if not system message, use name2 (char's name) to proceed
//characterName = mes.is_system || mes.force_avatar ? mes.name : name2;
} else if (mes['is_user'] && mes['force_avatar']) {
} else if (mes.is_user && mes.force_avatar) {
// Special case for persona images.
avatarImg = mes['force_avatar'];
avatarImg = mes.force_avatar;
}
// if mes.extra.uses_system_ui is true, set an override on the sanitizer options
@@ -3265,7 +3265,7 @@ export function getCharacterCardFieldsLazy({ chid = undefined } = {}) {
persona: () => baseChatReplace(power_user.persona_description?.trim()),
system: () => {
if (!character) return '';
const systemPrompt = chat_metadata['system_prompt'] || character.data?.system_prompt || '';
const systemPrompt = chat_metadata.system_prompt || character.data?.system_prompt || '';
return power_user.prefer_character_prompt ? baseChatReplace(systemPrompt.trim()) : '';
},
jailbreak: () => {
@@ -3295,13 +3295,13 @@ export function getCharacterCardFieldsLazy({ chid = undefined } = {}) {
scenario: () => {
if (groupCardsLazy) return groupCardsLazy.scenario;
if (!character) return '';
const scenarioText = chat_metadata['scenario'] || character.scenario || '';
const scenarioText = chat_metadata.scenario || character.scenario || '';
return baseChatReplace(scenarioText.trim());
},
mesExamples: () => {
if (groupCardsLazy) return groupCardsLazy.mesExamples;
if (!character) return '';
const exampleDialog = chat_metadata['mes_example'] || character.mes_example || '';
const exampleDialog = chat_metadata.mes_example || character.mes_example || '';
return baseChatReplace(exampleDialog.trim());
},
};
@@ -3516,39 +3516,39 @@ class StreamingProcessor {
this.sendTextarea.value = processedText;
this.sendTextarea.dispatchEvent(new Event('input', { bubbles: true }));
} else {
const mesChanged = chat[messageId]['mes'] !== processedText;
const mesChanged = chat[messageId].mes !== processedText;
await this.#checkDomElements(messageId);
this.#updateMessageBlockVisibility();
const currentTime = new Date();
chat[messageId]['mes'] = processedText;
chat[messageId]['gen_started'] = this.timeStarted;
chat[messageId]['gen_finished'] = currentTime;
if (!chat[messageId]['extra']) {
chat[messageId]['extra'] = {};
chat[messageId].mes = processedText;
chat[messageId].gen_started = this.timeStarted;
chat[messageId].gen_finished = currentTime;
if (!chat[messageId].extra) {
chat[messageId].extra = {};
}
chat[messageId]['extra']['time_to_first_token'] = this.timeToFirstToken;
chat[messageId].extra.time_to_first_token = this.timeToFirstToken;
// Update reasoning
await this.reasoningHandler.process(messageId, mesChanged, this.promptReasoning);
processedText = chat[messageId]['mes'];
processedText = chat[messageId].mes;
// Token count update.
const tokenCountText = this.reasoningHandler.reasoning + processedText;
const currentTokenCount = isFinal && power_user.message_token_count_enabled ? await getTokenCountAsync(tokenCountText, 0) : 0;
if (currentTokenCount) {
chat[messageId]['extra']['token_count'] = currentTokenCount;
chat[messageId].extra.token_count = currentTokenCount;
if (this.messageTokenCounterDom instanceof HTMLElement) {
this.messageTokenCounterDom.textContent = `${currentTokenCount}t`;
}
}
if ((this.type == 'swipe' || this.type === 'continue') && Array.isArray(chat[messageId]['swipes'])) {
chat[messageId]['swipes'][chat[messageId]['swipe_id']] = processedText;
chat[messageId]['swipe_info'][chat[messageId]['swipe_id']] = {
'send_date': chat[messageId]['send_date'],
'gen_started': chat[messageId]['gen_started'],
'gen_finished': chat[messageId]['gen_finished'],
'extra': structuredClone(chat[messageId]['extra']),
if ((this.type == 'swipe' || this.type === 'continue') && Array.isArray(chat[messageId].swipes)) {
chat[messageId].swipes[chat[messageId].swipe_id] = processedText;
chat[messageId].swipe_info[chat[messageId].swipe_id] = {
'send_date': chat[messageId].send_date,
'gen_started': chat[messageId].gen_started,
'gen_finished': chat[messageId].gen_finished,
'extra': structuredClone(chat[messageId].extra),
};
}
@@ -3657,13 +3657,13 @@ class StreamingProcessor {
setFirstSwipe(messageId) {
if (this.type !== 'swipe' && this.type !== 'impersonate') {
if (Array.isArray(chat[messageId]['swipes']) && chat[messageId]['swipes'].length === 1 && chat[messageId]['swipe_id'] === 0) {
chat[messageId]['swipes'][0] = chat[messageId]['mes'];
chat[messageId]['swipe_info'][0] = {
'send_date': chat[messageId]['send_date'],
'gen_started': chat[messageId]['gen_started'],
'gen_finished': chat[messageId]['gen_finished'],
'extra': structuredClone(chat[messageId]['extra']),
if (Array.isArray(chat[messageId].swipes) && chat[messageId].swipes.length === 1 && chat[messageId].swipe_id === 0) {
chat[messageId].swipes[0] = chat[messageId].mes;
chat[messageId].swipe_info[0] = {
'send_date': chat[messageId].send_date,
'gen_started': chat[messageId].gen_started,
'gen_finished': chat[messageId].gen_finished,
'extra': structuredClone(chat[messageId].extra),
};
}
}
@@ -4143,7 +4143,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
// Hide swipes if not in a dry run.
hideSwipeButtons();
// If generated any message, set the flag to indicate it can't be recreated again.
chat_metadata['tainted'] = true;
chat_metadata.tainted = true;
}
if (selected_group && !is_group_generating) {
@@ -4201,7 +4201,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
$('#send_textarea').val('')[0].dispatchEvent(new Event('input', { bubbles: true }));
} else {
textareaText = '';
if (chat.length && lastMessage['is_user']) {
if (chat.length && lastMessage.is_user) {
//do nothing? why does this check exist?
}
else if (type !== 'quiet' && type !== 'swipe' && !isImpersonate && !dryRun && chat.length) {
@@ -4215,13 +4215,13 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
// Rewrite the generation timer to account for the time passed for all the continuations.
if (isContinue && chat.length) {
const prevFinished = lastMessage['gen_finished'];
const prevStarted = lastMessage['gen_started'];
const prevFinished = lastMessage.gen_finished;
const prevStarted = lastMessage.gen_started;
if (prevFinished && prevStarted) {
const timePassed = Number(prevFinished) - Number(prevStarted);
generation_started = new Date(Date.now() - timePassed);
lastMessage['gen_started'] = generation_started;
lastMessage.gen_started = generation_started;
}
}
@@ -4903,7 +4903,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
let thisPromptContextSize = await getTokenCountAsync(prompt, power_user.token_padding);
if (thisPromptContextSize > this_max_context) { //if the prepared prompt is larger than the max context size...
if (count_exm_add > 0) { // ..and we have example mesages..
if (count_exm_add > 0) { // ..and we have example messages..
count_exm_add--; // remove the example messages...
await checkPromptSize(); // and try agin...
} else if (mesSend.length > 0) { // if the chat history is longer than 0
@@ -5631,7 +5631,7 @@ export function getBiasStrings(textareaText, type) {
function formatMessageHistoryItem(chatItem, isInstruct, forceOutputSequence) {
const isNarratorType = chatItem?.extra?.type === system_message_types.NARRATOR;
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;
// If this symbol flag is set, completely ignore the message.
@@ -5700,7 +5700,7 @@ export async function sendMessageAsUser(messageText, messageBias, insertAt = nul
await populateFileAttachment(message);
statMesProcess(message, 'user', characters, this_chid, '');
chat_metadata['tainted'] = true;
chat_metadata.tainted = true;
if (typeof insertAt === 'number' && insertAt >= 0 && insertAt <= chat.length) {
chat.splice(insertAt, 0, message);
@@ -5851,7 +5851,7 @@ function setInContextMessages(msgInContextCount, type) {
// Update last id to chat. No metadata save on purpose, gets hopefully saved via another call
const lastMessageId = Math.max(0, chat.length - msgInContextCount);
chat_metadata['lastInContextMessageId'] = lastMessageId;
chat_metadata.lastInContextMessageId = lastMessageId;
}
/**
@@ -6392,18 +6392,18 @@ export async function saveReply({ type, getMessage, fromStreaming = false, title
const lastMessage = chat[chat.length - 1];
if (type != 'append' && type != 'continue' && type != 'appendFinal' && chat.length && (lastMessage['swipe_id'] === undefined ||
lastMessage['is_user'])) {
if (type != 'append' && type != 'continue' && type != 'appendFinal' && chat.length && (lastMessage.swipe_id === undefined ||
lastMessage.is_user)) {
type = 'normal';
}
if (chat.length && (!lastMessage['extra'] || typeof lastMessage['extra'] !== 'object')) {
lastMessage['extra'] = {};
if (chat.length && (!lastMessage.extra || typeof lastMessage.extra !== 'object')) {
lastMessage.extra = {};
}
// Coerce null/undefined to empty string
if (chat.length && !lastMessage['extra']['reasoning']) {
lastMessage['extra']['reasoning'] = '';
if (chat.length && !lastMessage.extra.reasoning) {
lastMessage.extra.reasoning = '';
}
if (!reasoning) {
@@ -6413,70 +6413,70 @@ export async function saveReply({ type, getMessage, fromStreaming = false, title
let oldMessage = '';
const generationFinished = new Date();
if (type === 'swipe') {
oldMessage = lastMessage['mes'];
lastMessage['swipes'].length++;
if (lastMessage['swipe_id'] === lastMessage['swipes'].length - 1) {
lastMessage['title'] = title;
lastMessage['mes'] = getMessage;
lastMessage['gen_started'] = generation_started;
lastMessage['gen_finished'] = generationFinished;
lastMessage['send_date'] = getMessageTimeStamp();
lastMessage['extra']['api'] = getGeneratingApi();
lastMessage['extra']['model'] = getGeneratingModel();
lastMessage['extra']['reasoning'] = reasoning;
lastMessage['extra']['reasoning_duration'] = null;
lastMessage['extra']['reasoning_signature'] = reasoningSignature;
oldMessage = lastMessage.mes;
lastMessage.swipes.length++;
if (lastMessage.swipe_id === lastMessage.swipes.length - 1) {
lastMessage.title = title;
lastMessage.mes = getMessage;
lastMessage.gen_started = generation_started;
lastMessage.gen_finished = generationFinished;
lastMessage.send_date = getMessageTimeStamp();
lastMessage.extra.api = getGeneratingApi();
lastMessage.extra.model = getGeneratingModel();
lastMessage.extra.reasoning = reasoning;
lastMessage.extra.reasoning_duration = null;
lastMessage.extra.reasoning_signature = reasoningSignature;
await processImageAttachment(lastMessage, { imageUrls });
if (power_user.message_token_count_enabled) {
const tokenCountText = (reasoning || '') + lastMessage['mes'];
lastMessage['extra']['token_count'] = await getTokenCountAsync(tokenCountText, 0);
const tokenCountText = (reasoning || '') + lastMessage.mes;
lastMessage.extra.token_count = await getTokenCountAsync(tokenCountText, 0);
}
const chat_id = (chat.length - 1);
!fromStreaming && await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id, type);
addOneMessage(chat[chat_id], { type: 'swipe' });
!fromStreaming && await eventSource.emit(event_types.CHARACTER_MESSAGE_RENDERED, chat_id, type);
} else {
lastMessage['mes'] = getMessage;
lastMessage.mes = getMessage;
}
} else if (type === 'append' || type === 'continue') {
console.debug('Trying to append.');
oldMessage = lastMessage['mes'];
lastMessage['title'] = title;
lastMessage['mes'] += getMessage;
lastMessage['gen_started'] = generation_started;
lastMessage['gen_finished'] = generationFinished;
lastMessage['send_date'] = getMessageTimeStamp();
lastMessage['extra']['api'] = getGeneratingApi();
lastMessage['extra']['model'] = getGeneratingModel();
lastMessage['extra']['reasoning'] = reasoning;
lastMessage['extra']['reasoning_duration'] = null;
lastMessage['extra']['reasoning_signature'] = reasoningSignature;
oldMessage = lastMessage.mes;
lastMessage.title = title;
lastMessage.mes += getMessage;
lastMessage.gen_started = generation_started;
lastMessage.gen_finished = generationFinished;
lastMessage.send_date = getMessageTimeStamp();
lastMessage.extra.api = getGeneratingApi();
lastMessage.extra.model = getGeneratingModel();
lastMessage.extra.reasoning = reasoning;
lastMessage.extra.reasoning_duration = null;
lastMessage.extra.reasoning_signature = reasoningSignature;
await processImageAttachment(lastMessage, { imageUrls });
if (power_user.message_token_count_enabled) {
const tokenCountText = (reasoning || '') + lastMessage['mes'];
lastMessage['extra']['token_count'] = await getTokenCountAsync(tokenCountText, 0);
const tokenCountText = (reasoning || '') + lastMessage.mes;
lastMessage.extra.token_count = await getTokenCountAsync(tokenCountText, 0);
}
const chat_id = (chat.length - 1);
!fromStreaming && await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id, type);
addOneMessage(chat[chat_id], { type: 'swipe' });
!fromStreaming && await eventSource.emit(event_types.CHARACTER_MESSAGE_RENDERED, chat_id, type);
} else if (type === 'appendFinal') {
oldMessage = lastMessage['mes'];
oldMessage = lastMessage.mes;
console.debug('Trying to appendFinal.');
lastMessage['title'] = title;
lastMessage['mes'] = getMessage;
lastMessage['gen_started'] = generation_started;
lastMessage['gen_finished'] = generationFinished;
lastMessage['send_date'] = getMessageTimeStamp();
lastMessage['extra']['api'] = getGeneratingApi();
lastMessage['extra']['model'] = getGeneratingModel();
lastMessage['extra']['reasoning'] += reasoning;
lastMessage['extra']['reasoning_signature'] = reasoningSignature;
lastMessage.title = title;
lastMessage.mes = getMessage;
lastMessage.gen_started = generation_started;
lastMessage.gen_finished = generationFinished;
lastMessage.send_date = getMessageTimeStamp();
lastMessage.extra.api = getGeneratingApi();
lastMessage.extra.model = getGeneratingModel();
lastMessage.extra.reasoning += reasoning;
lastMessage.extra.reasoning_signature = reasoningSignature;
await processImageAttachment(lastMessage, { imageUrls });
// We don't know if the reasoning duration extended, so we don't update it here on purpose.
if (power_user.message_token_count_enabled) {
const tokenCountText = (reasoning || '') + lastMessage['mes'];
lastMessage['extra']['token_count'] = await getTokenCountAsync(tokenCountText, 0);
const tokenCountText = (reasoning || '') + lastMessage.mes;
lastMessage.extra.token_count = await getTokenCountAsync(tokenCountText, 0);
}
const chat_id = (chat.length - 1);
!fromStreaming && await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id, type);
@@ -6487,26 +6487,26 @@ export async function saveReply({ type, getMessage, fromStreaming = false, title
console.debug('entering chat update routine for non-swipe post');
const newMessage = {};
chat.push(newMessage);
newMessage['extra'] = {};
newMessage['name'] = name2;
newMessage['is_user'] = false;
newMessage['send_date'] = getMessageTimeStamp();
newMessage['extra']['api'] = getGeneratingApi();
newMessage['extra']['model'] = getGeneratingModel();
newMessage['extra']['reasoning'] = reasoning;
newMessage['extra']['reasoning_duration'] = null;
newMessage['extra']['reasoning_signature'] = reasoningSignature;
newMessage.extra = {};
newMessage.name = name2;
newMessage.is_user = false;
newMessage.send_date = getMessageTimeStamp();
newMessage.extra.api = getGeneratingApi();
newMessage.extra.model = getGeneratingModel();
newMessage.extra.reasoning = reasoning;
newMessage.extra.reasoning_duration = null;
newMessage.extra.reasoning_signature = reasoningSignature;
if (power_user.trim_spaces) {
getMessage = getMessage.trim();
}
newMessage['mes'] = getMessage;
newMessage['title'] = title;
newMessage['gen_started'] = generation_started;
newMessage['gen_finished'] = generationFinished;
newMessage.mes = getMessage;
newMessage.title = title;
newMessage.gen_started = generation_started;
newMessage.gen_finished = generationFinished;
if (power_user.message_token_count_enabled) {
const tokenCountText = (reasoning || '') + newMessage['mes'];
newMessage['extra']['token_count'] = await getTokenCountAsync(tokenCountText, 0);
const tokenCountText = (reasoning || '') + newMessage.mes;
newMessage.extra.token_count = await getTokenCountAsync(tokenCountText, 0);
}
if (selected_group) {
@@ -6515,9 +6515,9 @@ export async function saveReply({ type, getMessage, fromStreaming = false, title
if (characters[this_chid].avatar != 'none') {
avatarImg = getThumbnailUrl('avatar', characters[this_chid].avatar);
}
newMessage['force_avatar'] = avatarImg;
newMessage['original_avatar'] = characters[this_chid].avatar;
newMessage['extra']['gen_id'] = group_generation_id;
newMessage.force_avatar = avatarImg;
newMessage.original_avatar = characters[this_chid].avatar;
newMessage.extra.gen_id = group_generation_id;
}
await processImageAttachment(newMessage, { imageUrls });
@@ -6529,27 +6529,27 @@ export async function saveReply({ type, getMessage, fromStreaming = false, title
}
const item = chat[chat.length - 1];
if (item['swipe_info'] === undefined) {
item['swipe_info'] = [];
if (item.swipe_info === undefined) {
item.swipe_info = [];
}
if (item['swipe_id'] !== undefined) {
const swipeId = item['swipe_id'];
item['swipes'][swipeId] = item['mes'];
item['swipe_info'][swipeId] = {
send_date: item['send_date'],
gen_started: item['gen_started'],
gen_finished: item['gen_finished'],
extra: structuredClone(item['extra']),
if (item.swipe_id !== undefined) {
const swipeId = item.swipe_id;
item.swipes[swipeId] = item.mes;
item.swipe_info[swipeId] = {
send_date: item.send_date,
gen_started: item.gen_started,
gen_finished: item.gen_finished,
extra: structuredClone(item.extra),
};
} else {
item['swipe_id'] = 0;
item['swipes'] = [];
item['swipes'][0] = item['mes'];
item['swipe_info'][0] = {
send_date: item['send_date'],
gen_started: item['gen_started'],
gen_finished: item['gen_finished'],
extra: structuredClone(item['extra']),
item.swipe_id = 0;
item.swipes = [];
item.swipes[0] = item.mes;
item.swipe_info[0] = {
send_date: item.send_date,
gen_started: item.gen_started,
gen_finished: item.gen_finished,
extra: structuredClone(item.extra),
};
}
@@ -7155,7 +7155,7 @@ export async function saveChat({ chatName, withMetadata, mesId, force = false }
return;
}
characters[this_chid]['date_last_chat'] = Date.now();
characters[this_chid].date_last_chat = Date.now();
const trimmedChat = (mesId !== undefined && mesId >= 0 && mesId < chat.length)
? chat.slice(0, Number(mesId) + 1)
@@ -7387,15 +7387,19 @@ export async function getChat() {
dataType: 'json',
contentType: 'application/json',
});
if (response[0] !== undefined) {
if (Array.isArray(response) && response.length > 0) {
/** @type {ChatHeader} */
const chatHeader = response.shift();
chat_metadata = chatHeader?.chat_metadata ?? {};
chat.splice(0, chat.length, ...response);
chat_metadata = chat[0]['chat_metadata'] ?? {};
chat.shift();
chat.forEach(ensureMessageMediaIsArray);
} else {
// An empty/corrupted chat file
chat.splice(0, chat.length);
chat_metadata = {};
}
if (!chat_metadata['integrity']) {
chat_metadata['integrity'] = uuidv4();
if (!chat_metadata.integrity) {
chat_metadata.integrity = uuidv4();
}
await getChatResult();
eventSource.emit('chatLoaded', { detail: { id: this_chid, character: characters[this_chid] } });
@@ -7460,9 +7464,9 @@ function getFirstMessage() {
message.mes = swipes[0];
}
message['swipe_id'] = 0;
message['swipes'] = swipes;
message['swipe_info'] = swipes.map(_ => ({
message.swipe_id = 0;
message.swipes = swipes;
message.swipe_info = swipes.map(_ => ({
send_date: message.send_date,
gen_started: void 0,
gen_finished: void 0,
@@ -7476,7 +7480,7 @@ function getFirstMessage() {
export async function openCharacterChat(file_name) {
await waitUntilCondition(() => !isChatSaving, debounce_timeout.extended, 10);
await clearChat();
characters[this_chid]['chat'] = file_name;
characters[this_chid].chat = file_name;
chat.length = 0;
chat_metadata = {};
await getChat();
@@ -7862,7 +7866,7 @@ function updateMessage(div) {
const mes = chat[mesElement.attr('mesid')];
// editing old messages
mes['extra'] ??= {};
mes.extra ??= {};
let regexPlacement;
if (mes?.is_user) {
@@ -7893,10 +7897,10 @@ function updateMessage(div) {
if (bias) {
text = removeMacros(text);
}
mes['mes'] = text;
if (mes['swipe_id'] !== undefined) {
mes.mes = text;
if (mes.swipe_id !== undefined) {
ensureSwipes(mes);
mes['swipes'][mes['swipe_id']] = text;
mes.swipes[mes.swipe_id] = text;
}
if (mes?.is_system || mes?.is_user || mes.extra?.type === system_message_types.NARRATOR) {
@@ -7905,7 +7909,7 @@ function updateMessage(div) {
mes.extra.bias = null;
}
chat_metadata['tainted'] = true;
chat_metadata.tainted = true;
return { mesBlock, text, mes, bias };
}
@@ -8019,7 +8023,7 @@ export async function messageEdit(editMessageId) {
* @param {number} [messageId=this_edit_mes_id]
*/
async function messageEditCancel(messageId = this_edit_mes_id) {
let text = chat[messageId]['mes'];
let text = chat[messageId].mes;
let thisMesDiv;
// If this is the button then select it's parent. Otherwise, select by messageId.
if (this?.classList?.contains('mes_edit_cancel')) {
@@ -8167,7 +8171,7 @@ async function messageEditDone(div) {
export async function getChatsFromFiles(data, isGroupChat) {
const context = getContext();
let chat_dict = {};
let chat_list = Object.values(data).sort((a, b) => a['file_name'].localeCompare(b['file_name'])).reverse();
let chat_list = Object.values(data).sort((a, b) => a.file_name.localeCompare(b.file_name)).reverse();
let chat_promise = chat_list.map(({ file_name }) => {
return new Promise(async (res, rej) => {
@@ -8244,7 +8248,7 @@ export async function getPastCharacterChats(characterId = null) {
}
const chats = Object.values(data);
return chats.sort((a, b) => a['file_name'].localeCompare(b['file_name'])).reverse();
return chats.sort((a, b) => a.file_name.localeCompare(b.file_name)).reverse();
}
/**
@@ -8256,9 +8260,9 @@ export function getCurrentChatDetails() {
}
const group = selected_group ? groups.find(x => x.id === selected_group) : null;
const currentChat = selected_group ? group?.chat_id : characters[this_chid]['chat'];
const currentChat = selected_group ? group?.chat_id : characters[this_chid].chat;
const displayName = selected_group ? group?.name : characters[this_chid].name;
const avatarImg = selected_group ? group?.avatar_url : getThumbnailUrl('avatar', characters[this_chid]['avatar']);
const avatarImg = selected_group ? group?.avatar_url : getThumbnailUrl('avatar', characters[this_chid].avatar);
return { sessionName: currentChat, group: group, characterName: displayName, avatarImgURL: avatarImg };
}
@@ -8722,9 +8726,9 @@ export async function setCharacterSettingsOverrides() {
return;
}
const scenarioOverrideValue = chat_metadata['scenario'] || '';
const exampleMessagesValue = chat_metadata['mes_example'] || '';
const systemPromptValue = chat_metadata['system_prompt'] || '';
const scenarioOverrideValue = chat_metadata.scenario || '';
const exampleMessagesValue = chat_metadata.mes_example || '';
const systemPromptValue = chat_metadata.system_prompt || '';
const isGroup = !!selected_group;
const $template = $(await renderTemplateAsync('scenarioOverride'));
@@ -8771,9 +8775,9 @@ export async function setCharacterSettingsOverrides() {
allowVerticalScrolling: true,
});
chat_metadata['scenario'] = pendingChanges.scenario;
chat_metadata['mes_example'] = pendingChanges.examples;
chat_metadata['system_prompt'] = pendingChanges.system_prompt;
chat_metadata.scenario = pendingChanges.scenario;
chat_metadata.mes_example = pendingChanges.examples;
chat_metadata.system_prompt = pendingChanges.system_prompt;
await saveMetadata();
}
@@ -9071,7 +9075,7 @@ export async function deleteSwipe(swipeId = null, messageId = chat.length - 1) {
// Select the next swipe, or the one before if it was the last one
const newSwipeId = Math.min(swipeId, message.swipes.length - 1);
chat_metadata['tainted'] = true;
chat_metadata.tainted = true;
messageId = Number(messageId);
swipeId = Number(swipeId);
@@ -9585,7 +9589,7 @@ export async function createOrEditCharacter(e) {
!isNewChat &&
message.mes &&
!selected_group &&
!chat_metadata['tainted'] &&
!chat_metadata.tainted &&
(chat.length === 0 || (chat.length === 1 && !chat[0].is_user && !chat[0].is_system));
if (shouldRegenerateMessage) {
@@ -9745,7 +9749,7 @@ export async function swipe(event, direction, { source, repeated, message = chat
}
//Clamp Id between swipes.
let clampedId = clamp(chat[mesId]['swipe_id'], 0, Math.max(0, chat[mesId]['swipes'].length - 1));
let clampedId = clamp(chat[mesId].swipe_id, 0, Math.max(0, chat[mesId].swipes.length - 1));
await updateSwipeCounter(mesId);
//Fallback.
@@ -9837,7 +9841,7 @@ export async function swipe(event, direction, { source, repeated, message = chat
*/
async function loadFromSwipeId(mesId, newSwipeId) {
//Update the swipe_id.
chat[mesId]['swipe_id'] = newSwipeId;
chat[mesId].swipe_id = newSwipeId;
clearMessageData(chat[mesId]);
@@ -9909,7 +9913,8 @@ export async function swipe(event, direction, { source, repeated, message = chat
return true;
};
//Wait for the animation's end. https://developer.mozilla.org/en-US/docs/Web/API/Animation/finished
const animation = swipedElementsDiv[0]?.getAnimations().filter((a) => a['animationName'] == 'slide')[0];
const animations = swipedElementsDiv[0]?.getAnimations() ?? [];
const animation = animations.filter((a) => a instanceof globalThis.CSSAnimation && a.animationName == 'slide')[0];
try {
await Promise.race([animation?.finished, createTimeout(duration * 2, `The ${duration}ms swipe animation has not ended after ${duration * 2}ms. It has been skipped.`)].filter(Boolean));
} catch (error) {
@@ -9997,7 +10002,7 @@ export async function swipe(event, direction, { source, repeated, message = chat
const tokenCountText = (chat[mesId]?.extra?.reasoning || '') + chat[mesId].mes;
const tokenCount = await getTokenCountAsync(tokenCountText, 0);
chat[mesId]['extra']['token_count'] = tokenCount;
chat[mesId].extra.token_count = tokenCount;
thisMesDiv.find('.tokenCounterDisplay').text(`${tokenCount}t`);
}
}
@@ -10036,20 +10041,20 @@ export async function swipe(event, direction, { source, repeated, message = chat
// Make sure ad-hoc changes to extras are saved before swiping away
syncMesToSwipe(mesId);
if (chat[mesId]['swipe_id'] === undefined) { // if there is no swipe-message in the last spot of the chat array
chat[mesId]['swipe_id'] = 0; // set it to id 0
chat[mesId]['swipes'] = []; // empty the array
chat[mesId]['swipe_info'] = [];
chat[mesId]['swipes'][0] = chat[mesId]['mes']; //assign swipe array with last chat[mesId] from chat
chat[mesId]['swipe_info'][0] = {
'send_date': chat[mesId]['send_date'],
'gen_started': chat[mesId]['gen_started'],
'gen_finished': chat[mesId]['gen_finished'],
'extra': structuredClone(chat[mesId]['extra']),
if (chat[mesId].swipe_id === undefined) { // if there is no swipe-message in the last spot of the chat array
chat[mesId].swipe_id = 0; // set it to id 0
chat[mesId].swipes = []; // empty the array
chat[mesId].swipe_info = [];
chat[mesId].swipes[0] = chat[mesId].mes; //assign swipe array with last chat[mesId] from chat
chat[mesId].swipe_info[0] = {
'send_date': chat[mesId].send_date,
'gen_started': chat[mesId].gen_started,
'gen_finished': chat[mesId].gen_finished,
'extra': structuredClone(chat[mesId].extra),
};
}
// If the user is holding down the key and we're at the last or first swipe, don't do anything.
let isLastSwipe = (direction === SWIPE_DIRECTION.RIGHT) ? (chat[mesId].swipe_id === Math.max(0, chat[mesId]['swipes'].length - 1)) : chat[mesId].swipe_id === 0;
let isLastSwipe = (direction === SWIPE_DIRECTION.RIGHT) ? (chat[mesId].swipe_id === Math.max(0, chat[mesId].swipes.length - 1)) : chat[mesId].swipe_id === 0;
if (source === SWIPE_SOURCE.KEYBOARD && repeated && isLastSwipe) {
await endSwipe();
return;
@@ -10065,12 +10070,12 @@ export async function swipe(event, direction, { source, repeated, message = chat
if (forceSwipeId == null) newSwipeId--;
//Loop to last swipe if negative.
if (newSwipeId < 0) {
newSwipeId = Math.max(0, chat[mesId]['swipes'].length - 1);
newSwipeId = Math.max(0, chat[mesId].swipes.length - 1);
}
//Limit swipe_id to swipes.
if (newSwipeId > chat[mesId]['swipes'].length - 1) {
toastr.warning(`The swipe_id for message #${mesId} was ${newSwipeId}. It has been reset to ${chat[mesId]['swipes'].length - 1}.`);
chat[mesId]['swipe_id'] = chat[mesId]['swipes'].length - 1;
if (newSwipeId > chat[mesId].swipes.length - 1) {
toastr.warning(`The swipe_id for message #${mesId} was ${newSwipeId}. It has been reset to ${chat[mesId].swipes.length - 1}.`);
chat[mesId].swipe_id = chat[mesId].swipes.length - 1;
await endSwipe();
return;
}
@@ -10085,24 +10090,24 @@ export async function swipe(event, direction, { source, repeated, message = chat
//Minimum of zero.
if (newSwipeId < 0) {
toastr.warning(`The swipe_id for message #${mesId} was ${newSwipeId}. It has been reset to zero.`);
chat[mesId]['swipe_id'] = 0;
chat[mesId].swipe_id = 0;
await endSwipe();
return;
}
//If overswiping.
if (newSwipeId >= chat[mesId]['swipes'].length) {
newSwipeId = chat[mesId]['swipes'].length;
if (newSwipeId >= chat[mesId].swipes.length) {
newSwipeId = chat[mesId].swipes.length;
//Update the swipe_id.
chat[mesId]['swipe_id'] = newSwipeId;
chat[mesId].swipe_id = newSwipeId;
const overswipe = getOverswipeBehavior(mesId);
//Cancel the generation.
if (overswipe == OVERSWIPE_BEHAVIOR.NONE) {
//Cancel swipe.
chat[mesId]['swipe_id'] = originalSwipeId;
chat[mesId].swipe_id = originalSwipeId;
await endSwipe();
return;
}
@@ -11430,7 +11435,7 @@ jQuery(async function () {
chatElement.find(`.mes[mesid="${this_del_mes}"]`).nextAll('div').remove();
chatElement.find(`.mes[mesid="${this_del_mes}"]`).remove();
chat.length = this_del_mes;
chat_metadata['tainted'] = true;
chat_metadata.tainted = true;
await saveChatConditional();
chatElement.scrollTop(chatElement[0].scrollHeight);
await eventSource.emit(event_types.MESSAGE_DELETED, chat.length);
@@ -11517,7 +11522,7 @@ jQuery(async function () {
if (this_chid !== undefined || selected_group || name2 === neutralCharacterName) {
try {
const messageId = $(this).closest('.mes').attr('mesid');
const text = chat[messageId]['mes'];
const text = chat[messageId].mes;
await copyText(text);
toastr.info('Copied!', '', { timeOut: 2000 });
} catch (err) {
@@ -11544,8 +11549,8 @@ jQuery(async function () {
let mes_edited = chatElement.find(`[mesid="${this_edit_mes_id}"]`).find('.mes_edit_done');
if (Number(edit_mes_id) == chat.length - 1) { //if the generating swipe (...)
let run_edit = true;
if (chat[edit_mes_id]['swipe_id'] !== undefined) {
if (chat[edit_mes_id]['swipes'].length === chat[edit_mes_id]['swipe_id']) {
if (chat[edit_mes_id].swipe_id !== undefined) {
if (chat[edit_mes_id].swipes.length === chat[edit_mes_id].swipe_id) {
run_edit = false;
}
}
@@ -11684,8 +11689,8 @@ jQuery(async function () {
$(document).on('click', '.mes_edit_delete', async function (event, customData) {
const fromSlashCommand = customData?.fromSlashCommand || false;
const message = chat[this_edit_mes_id];
const selectedSwipe = message['swipe_id'] ?? undefined;
const swipesArray = Array.isArray(message['swipes']) ? message['swipes'] : [];
const selectedSwipe = message.swipe_id ?? undefined;
const swipesArray = Array.isArray(message.swipes) ? message.swipes : [];
const canDeleteSwipe = power_user.confirm_message_delete && !fromSlashCommand && !message.is_user && swipesArray.length > 1 && this_edit_mes_id === chat.length - 1 && selectedSwipe !== undefined;
await deleteMessage(Number(this_edit_mes_id), canDeleteSwipe ? selectedSwipe : undefined, power_user.confirm_message_delete && fromSlashCommand !== true);
});
@@ -12102,7 +12107,7 @@ jQuery(async function () {
});
// Remember the chat currently selected, so we can reload it after the replacement
const currentChatFile = characters[this_chid]['chat'];
const currentChatFile = characters[this_chid].chat;
async function postReplace() {
await openCharacterChat(currentChatFile);
}
+4 -4
View File
@@ -996,7 +996,7 @@ export function initRossMods() {
}
//Enter to send when send_textarea in focus
if (document.activeElement == hotkeyTargets['send_textarea']) {
if (document.activeElement == hotkeyTargets.send_textarea) {
const sendOnEnter = shouldSendOnEnter();
if (!event.isComposing && !event.shiftKey && !event.ctrlKey && !event.altKey && event.key == 'Enter' && sendOnEnter) {
event.preventDefault();
@@ -1004,7 +1004,7 @@ export function initRossMods() {
return;
}
}
if (document.activeElement == hotkeyTargets['dialogue_popup_input'] && !isMobile()) {
if (document.activeElement == hotkeyTargets.dialogue_popup_input && !isMobile()) {
if (!event.shiftKey && !event.ctrlKey && event.key == 'Enter') {
event.preventDefault();
$('#dialogue_popup_ok').trigger('click');
@@ -1139,7 +1139,7 @@ export function initRossMods() {
if (event.ctrlKey && event.key == 'ArrowUp') { //edits last USER message if chatbar is empty and focused
if (
hotkeyTargets['send_textarea'].value === '' &&
hotkeyTargets.send_textarea.value === '' &&
chatbarInFocus === true &&
($('.swipe_right:last').css('display') === 'flex' || $('.last_mes').attr('is_system') === 'true') &&
$('#character_popup').css('display') === 'none' &&
@@ -1158,7 +1158,7 @@ export function initRossMods() {
if (event.key == 'ArrowUp') { //edits last message if chatbar is empty and focused
console.log('got uparrow input');
if (
hotkeyTargets['send_textarea'].value === '' &&
hotkeyTargets.send_textarea.value === '' &&
chatbarInFocus === true &&
//$('.swipe_right:last').css('display') === 'flex' &&
$('.last_mes .mes_buttons').is(':visible') &&
+9 -9
View File
@@ -103,8 +103,8 @@ async function getBookmarkName({ isReplace = false, forceName = null } = {}) {
function getMainChatName() {
if (chat_metadata) {
if (chat_metadata['main_chat']) {
return chat_metadata['main_chat'];
if (chat_metadata.main_chat) {
return chat_metadata.main_chat;
}
// groups didn't support bookmarks before chat metadata was introduced
else if (selected_group) {
@@ -112,8 +112,8 @@ function getMainChatName() {
}
else if (characters[this_chid].chat && characters[this_chid].chat.includes(bookmarkNameToken)) {
const tokenIndex = characters[this_chid].chat.lastIndexOf(bookmarkNameToken);
chat_metadata['main_chat'] = characters[this_chid].chat.substring(0, tokenIndex).trim();
return chat_metadata['main_chat'];
chat_metadata.main_chat = characters[this_chid].chat.substring(0, tokenIndex).trim();
return chat_metadata.main_chat;
}
}
return null;
@@ -127,7 +127,7 @@ export function showBookmarksButtons() {
$('#option_convert_to_group').show();
}
if (chat_metadata['main_chat']) {
if (chat_metadata.main_chat) {
// In bookmark chat
$('#option_back_to_main').show();
$('#option_new_bookmark').show();
@@ -184,10 +184,10 @@ export async function createBranch(mesId) {
if (typeof lastMes.extra !== 'object') {
lastMes.extra = {};
}
if (typeof lastMes.extra['branches'] !== 'object') {
lastMes.extra['branches'] = [];
if (typeof lastMes.extra.branches !== 'object') {
lastMes.extra.branches = [];
}
lastMes.extra['branches'].push(name);
lastMes.extra.branches.push(name);
return name;
}
@@ -236,7 +236,7 @@ export async function createNewBookmark(mesId, { forceName = null } = {}) {
await saveChat({ chatName: name, withMetadata: newMetadata, mesId });
}
lastMes.extra['bookmark_link'] = name;
lastMes.extra.bookmark_link = name;
const mes = $(`.mes[mesid="${mesId}"]`);
updateBookmarkDisplay(mes, name);
+14 -14
View File
@@ -42,13 +42,13 @@ function setCharCfg(tempValue, setting) {
switch (setting) {
case settingType.guidance_scale:
tempCharaCfg['guidance_scale'] = Number(tempValue);
tempCharaCfg.guidance_scale = Number(tempValue);
break;
case settingType.negative_prompt:
tempCharaCfg['negative_prompt'] = tempValue;
tempCharaCfg.negative_prompt = tempValue;
break;
case settingType.positive_prompt:
tempCharaCfg['positive_prompt'] = tempValue;
tempCharaCfg.positive_prompt = tempValue;
break;
default:
return false;
@@ -239,31 +239,31 @@ function migrateSettings() {
if (power_user.guidance_scale) {
extension_settings.cfg.global.guidance_scale = power_user.guidance_scale;
delete power_user['guidance_scale'];
delete power_user.guidance_scale;
performSettingsSave = true;
}
if (power_user.negative_prompt) {
extension_settings.cfg.global.negative_prompt = power_user.negative_prompt;
delete power_user['negative_prompt'];
delete power_user.negative_prompt;
performSettingsSave = true;
}
if (chat_metadata['cfg_negative_combine']) {
chat_metadata[metadataKeys.prompt_combine] = chat_metadata['cfg_negative_combine'];
chat_metadata['cfg_negative_combine'] = undefined;
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;
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;
if (chat_metadata.cfg_negative_separator) {
chat_metadata[metadataKeys.prompt_separator] = chat_metadata.cfg_negative_separator;
chat_metadata.cfg_negative_separator = undefined;
performMetaSave = true;
}
+6 -6
View File
@@ -148,8 +148,8 @@ export async function bindModelTemplates(power_user, online_status) {
?? power_user.model_templates_mappings[chatTemplateHash]
?? {};
const bindingsMatch = bindModelTemplates
&& power_user.context.preset == bindModelTemplates['context']
&& (!power_user.instruct.enabled || power_user.instruct.preset === bindModelTemplates['instruct']);
&& power_user.context.preset == bindModelTemplates.context
&& (!power_user.instruct.enabled || power_user.instruct.preset === bindModelTemplates.instruct);
const bound = [];
@@ -160,21 +160,21 @@ export async function bindModelTemplates(power_user, online_status) {
toastr.info(t`Context preset for ${online_status} will use defaults when loaded the next time.`);
} else {
if (power_user.context_derived) {
if (power_user.context.preset !== bindModelTemplates['context']) {
if (power_user.context.preset !== bindModelTemplates.context) {
bound.push(`${power_user.context.preset} context preset`);
// toastr.info(`Bound ${power_user.context.preset} preset to currently loaded model and all models that share its chat template.`);
// map current preset to current chat template hash
bindModelTemplates['context'] = power_user.context.preset;
bindModelTemplates.context = power_user.context.preset;
}
} else {
toastr.warning(t`Note: Context derivation is disabled. Not including context preset.`);
}
if (power_user.instruct.enabled) {
if (power_user.instruct_derived) {
if (power_user.instruct.preset !== bindModelTemplates['instruct']) {
if (power_user.instruct.preset !== bindModelTemplates.instruct) {
bound.push(`${power_user.instruct.preset} instruct preset`);
bindModelTemplates['instruct'] = power_user.instruct.preset;
bindModelTemplates.instruct = power_user.instruct.preset;
}
} else {
toastr.warning(t`Note: Instruct derivation is disabled. Not including instruct preset.`);
+4 -4
View File
@@ -685,7 +685,7 @@ export function formatCreatorNotes(text, avatarId) {
const preference = new StylesPreference(avatarId);
const sanitizeStyles = !preference.get();
const decodeStyleParam = { prefix: sanitizeStyles ? '#creator_notes_spoiler ' : '' };
/** @type {import('dompurify').Config & { MESSAGE_SANITIZE: boolean }} */
/** @type {import('dompurify').Config} */
const config = {
RETURN_DOM: false,
RETURN_DOM_FRAGMENT: false,
@@ -1911,13 +1911,13 @@ export function addDOMPurifyHooks() {
});
DOMPurify.addHook('uponSanitizeAttribute', (node, data, config) => {
if (!config['MESSAGE_SANITIZE']) {
if (!config.MESSAGE_SANITIZE) {
return;
}
/* Retain the classes on UI elements of messages that interact with the main UI */
const permittedNodeTypes = ['BUTTON', 'DIV'];
if (config['MESSAGE_ALLOW_SYSTEM_UI'] && node.classList.contains('menu_button') && permittedNodeTypes.includes(node.nodeName)) {
if (config.MESSAGE_ALLOW_SYSTEM_UI && node.classList.contains('menu_button') && permittedNodeTypes.includes(node.nodeName)) {
return;
}
@@ -1938,7 +1938,7 @@ export function addDOMPurifyHooks() {
});
DOMPurify.addHook('uponSanitizeElement', (node, _, config) => {
if (!config['MESSAGE_SANITIZE']) {
if (!config.MESSAGE_SANITIZE) {
return;
}
+15 -15
View File
@@ -103,10 +103,10 @@ async function downloadAssetsList(url) {
for (const i of json) {
//console.log(DEBUG_PREFIX,i)
if (availableAssets[i['type']] === undefined)
availableAssets[i['type']] = [];
if (availableAssets[i.type] === undefined)
availableAssets[i.type] = [];
availableAssets[i['type']].push(i);
availableAssets[i.type].push(i);
}
console.debug(DEBUG_PREFIX, 'Updated available assets to', availableAssets);
@@ -139,7 +139,7 @@ async function downloadAssetsList(url) {
assetTypeMenu.append(await renderExtensionTemplateAsync('assets', 'installation'));
}
for (const asset of availableAssets[assetType].sort((a, b) => a?.name && b?.name && a['name'].localeCompare(b['name']))) {
for (const asset of availableAssets[assetType].sort((a, b) => a?.name && b?.name && a.name.localeCompare(b.name))) {
const i = availableAssets[assetType].indexOf(asset);
const elemId = `assets_install_${assetType}_${i}`;
let element = $('<div />', { id: elemId, class: 'asset-download-button right_menu_button' });
@@ -149,13 +149,13 @@ async function downloadAssetsList(url) {
//if (DEBUG_TONY_SAMA_FORK_MODE)
// asset["url"] = asset["url"].replace("https://github.com/SillyTavern/","https://github.com/Tony-sama/"); // DBG
console.debug(DEBUG_PREFIX, 'Checking asset', asset['id'], asset['url']);
console.debug(DEBUG_PREFIX, 'Checking asset', asset.id, asset.url);
const assetInstall = async function () {
element.off('click');
label.removeClass('fa-download');
this.classList.add('asset-download-button-loading');
await installAsset(asset['url'], assetType, asset['id']);
await installAsset(asset.url, assetType, asset.id);
label.addClass('fa-check');
this.classList.remove('asset-download-button-loading');
element.on('click', assetDelete);
@@ -173,11 +173,11 @@ async function downloadAssetsList(url) {
const assetDelete = async function () {
if (assetType === 'character') {
toastr.error('Go to the characters menu to delete a character.', 'Character deletion not supported');
await executeSlashCommandsWithOptions(`/go ${asset['id']}`);
await executeSlashCommandsWithOptions(`/go ${asset.id}`);
return;
}
element.off('click');
await deleteAsset(assetType, asset['id']);
await deleteAsset(assetType, asset.id);
label.removeClass('fa-check');
label.removeClass('redOverlayGlow');
label.removeClass('fa-trash');
@@ -186,7 +186,7 @@ async function downloadAssetsList(url) {
element.on('click', assetInstall);
};
if (isAssetInstalled(assetType, asset['id'])) {
if (isAssetInstalled(assetType, asset.id)) {
console.debug(DEBUG_PREFIX, 'installed, checked');
label.toggleClass('fa-download');
label.toggleClass('fa-check');
@@ -207,14 +207,14 @@ async function downloadAssetsList(url) {
element.on('click', assetInstall);
}
console.debug(DEBUG_PREFIX, 'Created element for ', asset['id']);
console.debug(DEBUG_PREFIX, 'Created element for ', asset.id);
const displayName = DOMPurify.sanitize(asset['name'] || asset['id']);
const description = DOMPurify.sanitize(asset['description'] || '');
const url = isValidUrl(asset['url']) ? asset['url'] : '';
const displayName = DOMPurify.sanitize(asset.name || asset.id);
const description = DOMPurify.sanitize(asset.description || '');
const url = isValidUrl(asset.url) ? asset.url : '';
const title = assetType === 'extension' ? t`Extension repo/guide:` + ` ${url}` : t`Preview in browser`;
const previewIcon = (assetType === 'extension' || assetType === 'character') ? 'fa-arrow-up-right-from-square' : 'fa-headphones-simple';
const toolTag = assetType === 'extension' && asset['tool'];
const toolTag = assetType === 'extension' && asset.tool;
const author = url && assetType === 'extension' ? getAuthorFromUrl(url) : EMPTY_AUTHOR;
const assetBlock = $('<i></i>')
@@ -246,7 +246,7 @@ async function downloadAssetsList(url) {
if (asset.highlight) {
assetBlock.find('.asset-name').append('<i class="fa-solid fa-sm fa-trophy"></i>');
}
assetBlock.find('.asset-name').prepend(`<div class="avatar"><img src="${asset['url']}" alt="${displayName}"></div>`);
assetBlock.find('.asset-name').prepend(`<div class="avatar"><img src="${asset.url}" alt="${displayName}"></div>`);
}
assetBlock.addClass('asset-block');
+1 -1
View File
@@ -204,7 +204,7 @@ async function sendCaptionedMessage(caption, image, mimeType) {
inline_image: !!extension_settings.caption.show_in_chat,
},
};
chat_metadata['tainted'] = true;
chat_metadata.tainted = true;
context.chat.push(message);
const messageId = context.chat.length - 1;
await eventSource.emit(event_types.MESSAGE_SENT, messageId);
+1 -1
View File
@@ -456,7 +456,7 @@ async function onChatEvent() {
.catch(console.error)
.finally(() => {
lastMessageId = context.chat?.length ?? null;
lastMessageHash = getStringHash((context.chat.length && context.chat[context.chat.length - 1]['mes']) ?? '');
lastMessageHash = getStringHash((context.chat.length && context.chat[context.chat.length - 1].mes) ?? '');
});
}
@@ -185,7 +185,7 @@ const init = async () => {
buttons.show();
settings.onSave = ()=>buttons.refresh();
window['executeQuickReplyByName'] = async(name, args = {}, options = {}) => {
globalThis.executeQuickReplyByName = async(name, args = {}, options = {}) => {
let qr = [
...settings.config.setList,
...(settings.chatConfig?.setList ?? []),
@@ -77,7 +77,7 @@ export class SlashCommandHandler {
},
};
window['qrEnumProviderExecutables'] = localEnumProviders.qrExecutables;
globalThis.qrEnumProviderExecutables = localEnumProviders.qrExecutables;
SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'qr',
callback: (_, value) => this.executeQuickReplyByIndex(Number(value)),
@@ -426,7 +426,7 @@ function processTriggers(chat, _, abort, type) {
}
}
window['SD_ProcessTriggers'] = processTriggers;
globalThis.SD_ProcessTriggers = processTriggers;
function getSdRequestBody() {
switch (extension_settings.sd.source) {
+10 -10
View File
@@ -207,13 +207,13 @@ class CoquiTtsProvider {
this.settings.customVoices = {};
for (let voiceName in this.settings.voiceMapDict) {
const voiceId = this.settings.voiceMapDict[voiceName];
this.settings.customVoices[voiceName] = voiceId['model_id'];
this.settings.customVoices[voiceName] = voiceId.model_id;
if (voiceId['model_language'] != null)
this.settings.customVoices[voiceName] += '[' + voiceId['model_language'] + ']';
if (voiceId.model_language != null)
this.settings.customVoices[voiceName] += '[' + voiceId.model_language + ']';
if (voiceId['model_speaker'] != null)
this.settings.customVoices[voiceName] += '[' + voiceId['model_speaker'] + ']';
if (voiceId.model_speaker != null)
this.settings.customVoices[voiceName] += '[' + voiceId.model_speaker + ']';
}
// Update UI select list with voices
@@ -493,8 +493,8 @@ class CoquiTtsProvider {
.append('<option value="none">Select language</option>')
.val('none');
for (let i = 0; i < model_settings['languages'].length; i++) {
const language_label = JSON.stringify(model_settings['languages'][i]).replaceAll('"', '');
for (let i = 0; i < model_settings.languages.length; i++) {
const language_label = JSON.stringify(model_settings.languages[i]).replaceAll('"', '');
$('#coqui_api_model_settings_language').append(new Option(language_label, i));
}
}
@@ -512,8 +512,8 @@ class CoquiTtsProvider {
.append('<option value="none">Select speaker</option>')
.val('none');
for (let i = 0; i < model_settings['speakers'].length; i++) {
const speaker_label = JSON.stringify(model_settings['speakers'][i]).replaceAll('"', '');
for (let i = 0; i < model_settings.speakers.length; i++) {
const speaker_label = JSON.stringify(model_settings.speakers[i]).replaceAll('"', '');
$('#coqui_api_model_settings_speaker').append(new Option(speaker_label, i));
}
}
@@ -525,7 +525,7 @@ class CoquiTtsProvider {
$('#coqui_api_model_install_status').show();
// Check if already installed and propose to do it otherwise
const model_id = modelDict[model_language][model_dataset][model_name]['id'];
const model_id = modelDict[model_language][model_dataset][model_name].id;
console.debug(DEBUG_PREFIX,'Check if model is already installed',model_id);
let result = await CoquiTtsProvider.checkmodel_state(model_id);
result = await result.json();
+1 -1
View File
@@ -175,7 +175,7 @@ class CosyVoiceProvider {
};
if (streaming) {
params['streaming'] = 1;
params.streaming = 1;
}
const url = `${this.settings.provider_endpoint}/`;
+3 -3
View File
@@ -126,16 +126,16 @@ class ElevenLabsTtsProvider {
this.settings = this.defaultSettings;
// Migrate old settings
if (settings['multilingual'] !== undefined) {
if (settings.multilingual !== undefined) {
settings.model = settings.multilingual ? 'eleven_multilingual_v1' : 'eleven_monolingual_v1';
delete settings['multilingual'];
delete settings.multilingual;
}
if (Object.hasOwn(settings, 'apiKey')) {
if (settings.apiKey && !secret_state[SECRET_KEYS.ELEVENLABS]){
await writeSecret(SECRET_KEYS.ELEVENLABS, settings.apiKey);
}
delete settings['apiKey'];
delete settings.apiKey;
}
$('#elevenlabs_tts_key').toggleClass('success', !!secret_state[SECRET_KEYS.ELEVENLABS]);
+7 -7
View File
@@ -284,7 +284,7 @@ function debugTtsPlayback() {
},
));
}
window['debugTtsPlayback'] = debugTtsPlayback;
globalThis.debugTtsPlayback = debugTtsPlayback;
//##################//
// Audio Control //
@@ -321,8 +321,8 @@ async function playAudioData(audioJob) {
const srcUrl = await getBase64Async(audioBlob);
// VRM lip sync
if (extension_settings.vrm?.enabled && typeof window['vrmLipSync'] === 'function') {
await window['vrmLipSync'](audioBlob, char);
if (extension_settings.vrm?.enabled && typeof globalThis.vrmLipSync === 'function') {
await globalThis.vrmLipSync(audioBlob, char);
}
audioElement.src = srcUrl;
@@ -339,7 +339,7 @@ async function playAudioData(audioJob) {
});
}
window['tts_preview'] = function (id) {
globalThis.tts_preview = function (id) {
const audio = document.getElementById(id);
if (audio instanceof HTMLAudioElement && !$(audio).data('disabled')) {
@@ -474,8 +474,8 @@ function completeTtsJob() {
async function tts(text, voiceId, char, voiceMapKey = null) {
async function processResponse(response) {
// RVC injection
if (typeof window['rvcVoiceConversion'] === 'function' && extension_settings.rvc.enabled)
response = await window['rvcVoiceConversion'](response, char, text);
if (typeof globalThis.rvcVoiceConversion === 'function' && extension_settings.rvc.enabled)
response = await globalThis.rvcVoiceConversion(response, char, text);
await addAudioJob(response, char);
}
@@ -806,7 +806,7 @@ async function playFullConversation() {
ttsJobQueue = chat;
}
window['playFullConversation'] = playFullConversation;
globalThis.playFullConversation = playFullConversation;
//#############################//
// Extension UI and Settings //
+2 -2
View File
@@ -746,7 +746,7 @@ function overlapChunks(chunk, index, chunks, overlapSize) {
return overlappedChunk;
}
window['vectors_rearrangeChat'] = rearrangeChat;
globalThis.vectors_rearrangeChat = rearrangeChat;
const onChatEvent = debounce(async () => await moduleWorker.update(), debounce_timeout.relaxed);
@@ -1620,7 +1620,7 @@ jQuery(async () => {
}
// Migrate from old settings
if (settings['enabled']) {
if (settings.enabled) {
settings.enabled_chats = true;
}
+14 -14
View File
@@ -274,8 +274,8 @@ export async function getGroupChat(groupId, reload = false) {
}
// Add integrity slug if missing
if (!metadata['integrity']) {
metadata['integrity'] = uuidv4();
if (!metadata.integrity) {
metadata.integrity = uuidv4();
}
await loadItemizedPrompts(getCurrentChatId());
@@ -559,8 +559,8 @@ export function getGroupCharacterCardsLazy(groupId, characterId) {
return values.filter(x => x.length).join('\n');
}
const scenarioOverride = String(chat_metadata['scenario'] || '');
const mesExamplesOverride = String(chat_metadata['mes_example'] || '');
const scenarioOverride = String(chat_metadata.scenario || '');
const mesExamplesOverride = String(chat_metadata.mes_example || '');
return createLazyFields({
description: () => collectField('Description', c => c.description),
@@ -593,16 +593,16 @@ async function getFirstCharacterMessage(character) {
}
const mes = {};
mes['is_user'] = false;
mes['is_system'] = false;
mes['name'] = character.name;
mes['send_date'] = getMessageTimeStamp();
mes['original_avatar'] = character.avatar;
mes['extra'] = { 'gen_id': Date.now() * Math.random() * 1000000 };
mes['mes'] = messageText
mes.is_user = false;
mes.is_system = false;
mes.name = character.name;
mes.send_date = getMessageTimeStamp();
mes.original_avatar = character.avatar;
mes.extra = { 'gen_id': Date.now() * Math.random() * 1000000 };
mes.mes = messageText
? substituteParams(messageText.trim(), { name2Override: character.name })
: '';
mes['force_avatar'] =
mes.force_avatar =
character.avatar != 'none'
? getThumbnailUrl('avatar', character.avatar)
: default_avatar;
@@ -628,7 +628,7 @@ async function saveGroupChat(groupId, shouldSaveGroup, force = false) {
return;
}
const chatId = group.chat_id;
group['date_last_chat'] = Date.now();
group.date_last_chat = Date.now();
/** @type {ChatHeader} */
const chatHeader = {
chat_metadata: { ...chat_metadata },
@@ -2179,7 +2179,7 @@ export async function openGroupChat(groupId, chatId) {
await clearChat();
chat.length = 0;
group.chat_id = chatId;
group['date_last_chat'] = Date.now();
group.date_last_chat = Date.now();
updateChatMetadata({}, true);
await editGroup(groupId, true, false);
+5 -5
View File
@@ -205,11 +205,11 @@ export async function generateHorde(prompt, params, signal, reportProgress) {
delete params.prompt;
// No idea what these do
params['n'] = 1;
params['frmtadsnsp'] = false;
params['frmtrmblln'] = false;
params['frmtrmspch'] = false;
params['frmttriminc'] = false;
params.n = 1;
params.frmtadsnsp = false;
params.frmtrmblln = false;
params.frmtrmspch = false;
params.frmttriminc = false;
const payload = {
'prompt': prompt,
+2 -2
View File
@@ -258,8 +258,8 @@ function addLanguagesToDropdown() {
const uiLanguageSelects = $('#ui_language_select, #onboarding_ui_language_select');
for (const langObj of langs) { // Set the value to the language code
const option = document.createElement('option');
option.value = langObj['lang']; // Set the value to the language code
option.innerText = langObj['display']; // Set the display text to the language name
option.value = langObj.lang; // Set the value to the language code
option.innerText = langObj.display; // Set the display text to the language name
uiLanguageSelects.append(option);
}
+1 -1
View File
@@ -161,7 +161,7 @@ export async function loadInstructMode(data) {
*/
export function updateBindModelTemplatesState() {
const bindModelTemplates = power_user.model_templates_mappings[online_status] ?? power_user.model_templates_mappings[power_user.chat_template_hash];
const bindingsMatch = (bindModelTemplates && power_user.context.preset === bindModelTemplates['context'] && (!power_user.instruct.enabled || power_user.instruct.preset === bindModelTemplates['instruct'])) ?? false;
const bindingsMatch = (bindModelTemplates && power_user.context.preset === bindModelTemplates.context && (!power_user.instruct.enabled || power_user.instruct.preset === bindModelTemplates.instruct)) ?? false;
const currentState = $('#bind_model_templates').prop('checked');
if (bindingsMatch === currentState) {
// No change needed
+4 -4
View File
@@ -312,14 +312,14 @@ export class MacrosParser {
* @returns {number} The hashed chat id
*/
function getChatIdHash() {
const cachedIdHash = chat_metadata['chat_id_hash'];
const cachedIdHash = chat_metadata.chat_id_hash;
// If chat_id_hash is not already set, calculate it
if (!cachedIdHash) {
// Use the main_chat if it's available, otherwise get the current chat ID
const chatId = chat_metadata['main_chat'] ?? getCurrentChatId();
const chatId = chat_metadata.main_chat ?? getCurrentChatId();
const chatIdHash = getStringHash(chatId);
chat_metadata['chat_id_hash'] = chatIdHash;
chat_metadata.chat_id_hash = chatIdHash;
return chatIdHash;
}
@@ -361,7 +361,7 @@ export function getLastMessageId({ exclude_swipe_in_propress = true, filter = nu
* @returns {number|null} The ID of the first message in the context
*/
function getFirstIncludedMessageId() {
return chat_metadata['lastInContextMessageId'];
return chat_metadata.lastInContextMessageId;
}
/**
@@ -104,7 +104,7 @@ function getLastCharMessage() {
}
function getFirstIncludedMessageId() {
const value = chat_metadata['lastInContextMessageId'];
const value = chat_metadata.lastInContextMessageId;
return typeof value === 'number' ? value : null;
}
@@ -433,13 +433,13 @@ export function registerCoreMacros() {
}
function getChatIdHash() {
const cachedIdHash = chat_metadata['chat_id_hash'];
const cachedIdHash = chat_metadata.chat_id_hash;
if (typeof cachedIdHash === 'number') {
return cachedIdHash;
}
const chatId = chat_metadata['main_chat'] ?? getCurrentChatId();
const chatId = chat_metadata.main_chat ?? getCurrentChatId();
const chatIdHash = getStringHash(chatId);
chat_metadata['chat_id_hash'] = chatIdHash;
chat_metadata.chat_id_hash = chatIdHash;
return chatIdHash;
}
+53 -53
View File
@@ -529,8 +529,8 @@ function setOpenAIMessages(chat) {
const currentModel = getChatCompletionModel();
for (let i = chat.length - 1; i >= 0; i--) {
let role = chat[j]['is_user'] ? 'user' : 'assistant';
let content = chat[j]['mes'];
let role = chat[j].is_user ? 'user' : 'assistant';
let content = chat[j].mes;
// If this symbol flag is set, completely ignore the message.
// This can be used to hide messages without affecting the number of messages in the chat.
@@ -567,7 +567,7 @@ function setOpenAIMessages(chat) {
// remove caret return (waste of tokens)
content = content.replace(/\r/gm, '');
const name = chat[j]['name'];
const name = chat[j].name;
const media = chat[j]?.extra?.media;
const mediaDisplay = getMediaDisplay(chat[j]);
const mediaIndex = getMediaIndex(chat[j]);
@@ -2588,14 +2588,14 @@ export async function createGenerationParameters(settings, model, type, messages
if (settings.reverse_proxy && proxySupportedSources.includes(settings.chat_completion_source)) {
await validateReverseProxy();
generate_data['reverse_proxy'] = settings.reverse_proxy;
generate_data['proxy_password'] = settings.proxy_password;
generate_data.reverse_proxy = settings.reverse_proxy;
generate_data.proxy_password = settings.proxy_password;
}
// Add logprobs request (max 5 per OpenAI docs)
const useLogprobs = !!power_user.request_token_probabilities;
if (useLogprobs && logprobsSupportedSources.includes(settings.chat_completion_source)) {
generate_data['logprobs'] = 5;
generate_data.logprobs = 5;
}
// Remove logit bias/logprobs/stop-strings if not supported by the model
@@ -2610,67 +2610,67 @@ export async function createGenerationParameters(settings, model, type, messages
}
if (settings.chat_completion_source === chat_completion_sources.CLAUDE) {
generate_data['top_k'] = Number(settings.top_k_openai);
generate_data['use_sysprompt'] = settings.use_sysprompt;
generate_data['stop'] = getCustomStoppingStrings(); // Claude shouldn't have limits on stop strings.
generate_data.top_k = Number(settings.top_k_openai);
generate_data.use_sysprompt = settings.use_sysprompt;
generate_data.stop = getCustomStoppingStrings(); // Claude shouldn't have limits on stop strings.
// Don't add a prefill on quiet gens (summarization) and when using continue prefill.
if (type !== 'quiet' && !(type === 'continue' && settings.continue_prefill)) {
generate_data['assistant_prefill'] = type === 'impersonate'
generate_data.assistant_prefill = type === 'impersonate'
? substituteParams(settings.assistant_impersonation)
: substituteParams(settings.assistant_prefill);
}
}
if (settings.chat_completion_source === chat_completion_sources.OPENROUTER) {
generate_data['top_k'] = Number(settings.top_k_openai);
generate_data['min_p'] = Number(settings.min_p_openai);
generate_data['repetition_penalty'] = Number(settings.repetition_penalty_openai);
generate_data['top_a'] = Number(settings.top_a_openai);
generate_data['use_fallback'] = settings.openrouter_use_fallback;
generate_data['provider'] = settings.openrouter_providers;
generate_data['allow_fallbacks'] = settings.openrouter_allow_fallbacks;
generate_data['middleout'] = settings.openrouter_middleout;
generate_data.top_k = Number(settings.top_k_openai);
generate_data.min_p = Number(settings.min_p_openai);
generate_data.repetition_penalty = Number(settings.repetition_penalty_openai);
generate_data.top_a = Number(settings.top_a_openai);
generate_data.use_fallback = settings.openrouter_use_fallback;
generate_data.provider = settings.openrouter_providers;
generate_data.allow_fallbacks = settings.openrouter_allow_fallbacks;
generate_data.middleout = settings.openrouter_middleout;
}
if ([chat_completion_sources.MAKERSUITE, chat_completion_sources.VERTEXAI].includes(settings.chat_completion_source)) {
const stopStringsLimit = 5;
generate_data['top_k'] = Number(settings.top_k_openai);
generate_data['stop'] = getCustomStoppingStrings(stopStringsLimit).slice(0, stopStringsLimit).filter(x => x.length >= 1 && x.length <= 16);
generate_data['use_sysprompt'] = settings.use_sysprompt;
generate_data.top_k = Number(settings.top_k_openai);
generate_data.stop = getCustomStoppingStrings(stopStringsLimit).slice(0, stopStringsLimit).filter(x => x.length >= 1 && x.length <= 16);
generate_data.use_sysprompt = settings.use_sysprompt;
if (settings.chat_completion_source === chat_completion_sources.VERTEXAI) {
generate_data['vertexai_auth_mode'] = settings.vertexai_auth_mode;
generate_data['vertexai_region'] = settings.vertexai_region;
generate_data['vertexai_express_project_id'] = settings.vertexai_express_project_id;
generate_data.vertexai_auth_mode = settings.vertexai_auth_mode;
generate_data.vertexai_region = settings.vertexai_region;
generate_data.vertexai_express_project_id = settings.vertexai_express_project_id;
}
}
if (settings.chat_completion_source === chat_completion_sources.MISTRALAI) {
generate_data['safe_prompt'] = false; // already defaults to false, but just incase they change that in the future.
generate_data['stop'] = getCustomStoppingStrings(); // Mistral shouldn't have limits on stop strings.
generate_data.safe_prompt = false; // already defaults to false, but just incase they change that in the future.
generate_data.stop = getCustomStoppingStrings(); // Mistral shouldn't have limits on stop strings.
}
if (settings.chat_completion_source === chat_completion_sources.CUSTOM) {
generate_data['custom_url'] = settings.custom_url;
generate_data['custom_include_body'] = settings.custom_include_body;
generate_data['custom_exclude_body'] = settings.custom_exclude_body;
generate_data['custom_include_headers'] = settings.custom_include_headers;
generate_data.custom_url = settings.custom_url;
generate_data.custom_include_body = settings.custom_include_body;
generate_data.custom_exclude_body = settings.custom_exclude_body;
generate_data.custom_include_headers = settings.custom_include_headers;
}
if (settings.chat_completion_source === chat_completion_sources.COHERE) {
// Clamp to 0.01 -> 0.99
generate_data['top_p'] = Math.min(Math.max(Number(settings.top_p_openai), 0.01), 0.99);
generate_data['top_k'] = Number(settings.top_k_openai);
generate_data.top_p = Math.min(Math.max(Number(settings.top_p_openai), 0.01), 0.99);
generate_data.top_k = Number(settings.top_k_openai);
// Clamp to 0 -> 1
generate_data['frequency_penalty'] = Math.min(Math.max(Number(settings.freq_pen_openai), 0), 1);
generate_data['presence_penalty'] = Math.min(Math.max(Number(settings.pres_pen_openai), 0), 1);
generate_data['stop'] = getCustomStoppingStrings(5);
generate_data.frequency_penalty = Math.min(Math.max(Number(settings.freq_pen_openai), 0), 1);
generate_data.presence_penalty = Math.min(Math.max(Number(settings.pres_pen_openai), 0), 1);
generate_data.stop = getCustomStoppingStrings(5);
}
if (settings.chat_completion_source === chat_completion_sources.PERPLEXITY) {
generate_data['top_k'] = Number(settings.top_k_openai);
generate_data['frequency_penalty'] = Number(settings.freq_pen_openai);
generate_data['presence_penalty'] = Number(settings.pres_pen_openai);
delete generate_data['stop'];
generate_data.top_k = Number(settings.top_k_openai);
generate_data.frequency_penalty = Number(settings.freq_pen_openai);
generate_data.presence_penalty = Number(settings.pres_pen_openai);
delete generate_data.stop;
}
// https://console.groq.com/docs/openai
@@ -2713,35 +2713,35 @@ export async function createGenerationParameters(settings, model, type, messages
// https://docs.electronhub.ai/api-reference/chat/completions
if (settings.chat_completion_source === chat_completion_sources.ELECTRONHUB) {
generate_data['top_k'] = Number(settings.top_k_openai);
generate_data.top_k = Number(settings.top_k_openai);
}
if (settings.chat_completion_source === chat_completion_sources.CHUTES) {
generate_data['min_p'] = Number(settings.min_p_openai);
generate_data['top_k'] = settings.top_k_openai > 0 ? Number(settings.top_k_openai) : undefined;
generate_data['repetition_penalty'] = Number(settings.repetition_penalty_openai);
generate_data['stop'] = getCustomStoppingStrings();
generate_data.min_p = Number(settings.min_p_openai);
generate_data.top_k = settings.top_k_openai > 0 ? Number(settings.top_k_openai) : undefined;
generate_data.repetition_penalty = Number(settings.repetition_penalty_openai);
generate_data.stop = getCustomStoppingStrings();
}
// https://docs.z.ai/api-reference/llm/chat-completion
if (settings.chat_completion_source === chat_completion_sources.ZAI) {
generate_data['top_p'] = generate_data.top_p || 0.01;
generate_data['stop'] = getCustomStoppingStrings(1);
generate_data['zai_endpoint'] = settings.zai_endpoint || ZAI_ENDPOINT.COMMON;
generate_data.top_p = generate_data.top_p || 0.01;
generate_data.stop = getCustomStoppingStrings(1);
generate_data.zai_endpoint = settings.zai_endpoint || ZAI_ENDPOINT.COMMON;
delete generate_data.presence_penalty;
delete generate_data.frequency_penalty;
}
// https://docs.nano-gpt.com/api-reference/endpoint/chat-completion#temperature-&-nucleus
if (settings.chat_completion_source === chat_completion_sources.NANOGPT) {
generate_data['top_k'] = Number(settings.top_k_openai);
generate_data['min_p'] = Number(settings.min_p_openai);
generate_data['repetition_penalty'] = Number(settings.repetition_penalty_openai);
generate_data['top_a'] = Number(settings.top_a_openai);
generate_data.top_k = Number(settings.top_k_openai);
generate_data.min_p = Number(settings.min_p_openai);
generate_data.repetition_penalty = Number(settings.repetition_penalty_openai);
generate_data.top_a = Number(settings.top_a_openai);
}
if (seedSupportedSources.includes(settings.chat_completion_source) && settings.seed >= 0) {
generate_data['seed'] = settings.seed;
generate_data.seed = settings.seed;
}
if ([chat_completion_sources.OPENAI, chat_completion_sources.AZURE_OPENAI].includes(settings.chat_completion_source) && /^(o1|o3|o4)/.test(model) ||
@@ -6162,7 +6162,7 @@ async function onVertexAIValidateServiceAccount() {
}
// Save to backend secret storage
const keyLabel = serviceAccount['client_email'] || '';
const keyLabel = serviceAccount.client_email || '';
await writeSecret(SECRET_KEYS.VERTEXAI_SERVICE_ACCOUNT, jsonContent, keyLabel);
// Show success status
+20 -20
View File
@@ -835,7 +835,7 @@ async function renamePersona(avatarId) {
async function selectCurrentPersona({ toastPersonaNameChange = true } = {}) {
const personaName = power_user.personas[user_avatar];
if (personaName) {
const shouldAutoLock = power_user.persona_auto_lock && user_avatar !== chat_metadata['persona'];
const shouldAutoLock = power_user.persona_auto_lock && user_avatar !== chat_metadata.persona;
if (personaName !== name1) {
console.log(`Auto-updating user name to ${personaName}`);
@@ -871,7 +871,7 @@ async function selectCurrentPersona({ toastPersonaNameChange = true } = {}) {
// Update the locked persona if setting is enabled
if (shouldAutoLock) {
chat_metadata['persona'] = user_avatar;
chat_metadata.persona = user_avatar;
console.log(`Auto locked persona to ${user_avatar}`);
if (toastPersonaNameChange && power_user.persona_show_notifications) {
toastr.success(t`Persona ${personaName} selected and auto-locked to current chat`, t`Persona Selected`);
@@ -914,7 +914,7 @@ export function isPersonaLocked(type = 'chat') {
case 'default':
return power_user.default_persona === user_avatar;
case 'chat':
return chat_metadata['persona'] == user_avatar;
return chat_metadata.persona == user_avatar;
case 'character': {
return !!power_user.persona_descriptions[user_avatar]?.connections?.some(isPersonaConnectionLocked);
}
@@ -960,9 +960,9 @@ async function unlockPersona(type = 'chat') {
break;
}
case 'chat': {
if (chat_metadata['persona']) {
if (chat_metadata.persona) {
console.log(`Unlocking persona ${user_avatar} from this chat`);
delete chat_metadata['persona'];
delete chat_metadata.persona;
await saveMetadata();
if (power_user.persona_show_notifications && !isPersonaPanelOpen()) {
toastr.info(t`Persona ${name1} is now unlocked from this chat.`, t`Persona Unlocked`);
@@ -1021,7 +1021,7 @@ async function lockPersona(type = 'chat') {
}
case 'chat': {
console.log(`Locking persona ${user_avatar} to this chat`);
chat_metadata['persona'] = user_avatar;
chat_metadata.persona = user_avatar;
saveMetadataDebounced();
if (power_user.persona_show_notifications && !isPersonaPanelOpen()) {
toastr.success(t`User persona ${name1} is locked to ${name2} in this chat`, t`Persona Locked`);
@@ -1105,9 +1105,9 @@ async function deleteUserAvatar() {
power_user.default_persona = null;
}
if (avatarId === chat_metadata['persona']) {
if (avatarId === chat_metadata.persona) {
toastr.warning(t`The locked persona was deleted. You will need to set a new persona for this chat.`, t`Persona Deleted`);
delete chat_metadata['persona'];
delete chat_metadata.persona;
await saveMetadata();
}
@@ -1317,7 +1317,7 @@ async function toggleDefaultPersona(avatarId, { quiet = false } = {}) {
*/
function getPersonaStates(avatarId) {
const isDefaultPersona = power_user.default_persona === avatarId;
const hasChatLock = chat_metadata['persona'] == avatarId;
const hasChatLock = chat_metadata.persona == avatarId;
/** @type {PersonaConnection[]} */
const connections = power_user.persona_descriptions[avatarId]?.connections;
@@ -1413,13 +1413,13 @@ function updatePersonaUIStates({ navigateToCurrent = false } = {}) {
* @returns {PersonaLockInfo} An object containing flags and a message describing the persona lock status.
*/
function getPersonaTemporaryLockInfo() {
const hasDifferentChatLock = !!chat_metadata['persona'] && chat_metadata['persona'] !== user_avatar;
const hasDifferentChatLock = !!chat_metadata.persona && chat_metadata.persona !== user_avatar;
const hasDifferentDefaultLock = power_user.default_persona && power_user.default_persona !== user_avatar;
const isTemporary = hasDifferentChatLock || (!chat_metadata['persona'] && hasDifferentDefaultLock);
const isTemporary = hasDifferentChatLock || (!chat_metadata.persona && hasDifferentDefaultLock);
const info = isTemporary ? t`A different persona is locked to this chat, or you have a different default persona set. The currently selected persona will only be temporary, and resets on reload. Consider locking this persona to the chat if you want to permanently use it.`
+ '\n\n'
+ t`Current Persona: ${power_user.personas[user_avatar]}`
+ (hasDifferentChatLock ? '\n' + t`Chat persona: ${power_user.personas[chat_metadata['persona']]}` : '')
+ (hasDifferentChatLock ? '\n' + t`Chat persona: ${power_user.personas[chat_metadata.persona]}` : '')
+ (hasDifferentDefaultLock ? '\n' + t`Default persona: ${power_user.personas[power_user.default_persona]}` : '') : '';
return {
@@ -1458,14 +1458,14 @@ async function loadPersonaForCurrentChat({ doRender = false } = {}) {
let connectType = null;
// If persona is locked in chat metadata, select it
if (chat_metadata['persona']) {
console.log(`Using locked persona ${chat_metadata['persona']}`);
chatPersona = chat_metadata['persona'];
if (chat_metadata.persona) {
console.log(`Using locked persona ${chat_metadata.persona}`);
chatPersona = chat_metadata.persona;
// Verify it exists
if (!userAvatars.includes(chatPersona)) {
console.warn('Chat-locked persona avatar not found, unlocking persona');
delete chat_metadata['persona'];
delete chat_metadata.persona;
saveSettingsDebounced();
chatPersona = '';
}
@@ -1528,9 +1528,9 @@ async function loadPersonaForCurrentChat({ doRender = false } = {}) {
}
// Whatever way we selected a persona, if it doesn't exist, unlock this chat
if (chat_metadata['persona'] && !userAvatars.includes(chat_metadata['persona'])) {
if (chat_metadata.persona && !userAvatars.includes(chat_metadata.persona)) {
console.warn('Persona avatar not found, unlocking persona');
delete chat_metadata['persona'];
delete chat_metadata.persona;
}
// Default persona missing
@@ -1542,7 +1542,7 @@ async function loadPersonaForCurrentChat({ doRender = false } = {}) {
// Persona avatar found, select it
if (chatPersona && user_avatar !== chatPersona) {
const willAutoLock = power_user.persona_auto_lock && user_avatar !== chat_metadata['persona'];
const willAutoLock = power_user.persona_auto_lock && user_avatar !== chat_metadata.persona;
await setUserAvatar(chatPersona, { toastPersonaNameChange: false, navigateToCurrent: true });
if (power_user.persona_show_notifications) {
@@ -1554,7 +1554,7 @@ async function loadPersonaForCurrentChat({ doRender = false } = {}) {
}
}
// Even if it's the same persona, we still might need to auto-lock to chat if that's enabled
else if (chatPersona && power_user.persona_auto_lock && !chat_metadata['persona']) {
else if (chatPersona && power_user.persona_auto_lock && !chat_metadata.persona) {
await lockPersona('chat');
}
+6 -6
View File
@@ -163,7 +163,7 @@ class PresetManager {
const manager = getPresetManager('textgenerationwebui');
const name = manager.getSelectedPresetName();
const data = manager.getPresetSettings(name);
data['name'] = name;
data.name = name;
return data;
},
setData: (data) => {
@@ -652,22 +652,22 @@ class PresetManager {
return textgen_settings;
case 'context': {
const context_preset = getContextSettings();
context_preset['name'] = name || power_user.context.preset;
context_preset.name = name || power_user.context.preset;
return context_preset;
}
case 'instruct': {
const instruct_preset = structuredClone(power_user.instruct);
instruct_preset['name'] = name || power_user.instruct.preset;
instruct_preset.name = name || power_user.instruct.preset;
return instruct_preset;
}
case 'sysprompt': {
const sysprompt_preset = structuredClone(power_user.sysprompt);
sysprompt_preset['name'] = name || power_user.sysprompt.preset;
sysprompt_preset.name = name || power_user.sysprompt.preset;
return sysprompt_preset;
}
case 'reasoning': {
const reasoning_preset = structuredClone(power_user.reasoning);
reasoning_preset['name'] = name || power_user.reasoning.preset;
reasoning_preset.name = name || power_user.reasoning.preset;
return reasoning_preset;
}
default:
@@ -1115,7 +1115,7 @@ export async function initPresetManager() {
const fileName = file.name.replace('.json', '').replace('.settings', '');
const data = await parseJsonFile(file);
const name = data?.name ?? fileName;
data['name'] = name;
data.name = name;
await presetManager.savePreset(name, data);
const successToast = !presetManager.isAdvancedFormatting() ? t`Preset imported` : t`Template imported`;
+7 -7
View File
@@ -2120,7 +2120,7 @@ export function initDefaultSlashCommands() {
isRequired: true,
enumProvider: (executor, scope) => [
...commonEnumProviders.variables('scope')(executor, scope),
...(typeof window['qrEnumProviderExecutables'] === 'function') ? window['qrEnumProviderExecutables']() : [],
...(typeof globalThis.qrEnumProviderExecutables === 'function') ? globalThis.qrEnumProviderExecutables() : [],
],
}),
],
@@ -3572,7 +3572,7 @@ async function runCallback(args, name) {
return result.pipe;
}
if (typeof window['executeQuickReplyByName'] !== 'function') {
if (typeof globalThis.executeQuickReplyByName !== 'function') {
throw new Error(t`Quick Reply extension is not loaded`);
}
@@ -3583,7 +3583,7 @@ async function runCallback(args, name) {
abortController: args._abortController,
debugController: args._debugController,
};
return await window['executeQuickReplyByName'](name, args, options);
return await globalThis.executeQuickReplyByName(name, args, options);
} catch (error) {
throw new Error(t`Error running Quick Reply "${name}": ${error.message}`);
}
@@ -4788,7 +4788,7 @@ export async function sendMessageAs(args, text) {
insertAt = chat.length + insertAt;
}
chat_metadata['tainted'] = true;
chat_metadata.tainted = true;
if (!isNaN(insertAt) && insertAt >= 0 && insertAt <= chat.length) {
chat.splice(insertAt, 0, message);
@@ -4840,7 +4840,7 @@ export async function sendNarratorMessage(args, text) {
insertAt = chat.length + insertAt;
}
chat_metadata['tainted'] = true;
chat_metadata.tainted = true;
if (!isNaN(insertAt) && insertAt >= 0 && insertAt <= chat.length) {
chat.splice(insertAt, 0, message);
@@ -4892,7 +4892,7 @@ export async function promptQuietForLoudResponse(who, text) {
},
};
chat_metadata['tainted'] = true;
chat_metadata.tainted = true;
chat.push(message);
await eventSource.emit(event_types.MESSAGE_SENT, (chat.length - 1));
@@ -4928,7 +4928,7 @@ async function sendCommentMessage(args, text) {
insertAt = chat.length + insertAt;
}
chat_metadata['tainted'] = true;
chat_metadata.tainted = true;
if (!isNaN(insertAt) && insertAt >= 0 && insertAt <= chat.length) {
chat.splice(insertAt, 0, message);
+2 -2
View File
@@ -880,8 +880,8 @@ async function downloadTabbyModel() {
}
// Params for the server side of ST
params['api_server'] = serverUrl;
params['api_type'] = textgen_settings.type;
params.api_server = serverUrl;
params.api_type = textgen_settings.type;
toastr.info('Downloading. Check the Tabby console for progress reports.');
+5 -5
View File
@@ -755,7 +755,7 @@ async function getStatusTextgen() {
power_user.chat_template_hash = chat_template_hash;
if (wantsContextSize && 'default_generation_settings' in data) {
const backend_max_context = data['default_generation_settings']['n_ctx'];
const backend_max_context = data.default_generation_settings.n_ctx;
if (backend_max_context && typeof backend_max_context === 'number') {
const old_value = max_context;
if (max_context !== backend_max_context) {
@@ -913,16 +913,16 @@ export function initTextGenSettings() {
$('#ban_eos_token_textgenerationwebui').prop('checked', false); //Aphro should not ban EOS, just ignore it; 'add token '2' to ban list do to this'
//special handling for vLLM/Aphrodite topK -1 disable state
$('#top_k_textgenerationwebui').attr('min', -1);
if ($('#top_k_textgenerationwebui').val() === '0' || textgenerationwebui_settings['top_k'] === 0) {
textgenerationwebui_settings['top_k'] = -1;
if ($('#top_k_textgenerationwebui').val() === '0' || textgenerationwebui_settings.top_k === 0) {
textgenerationwebui_settings.top_k = -1;
$('#top_k_textgenerationwebui').val('-1').trigger('input');
}
} else {
$('#mirostat_mode_textgenerationwebui').attr('step', 1);
//undo special vLLM/Aphrodite setup for topK
$('#top_k_textgenerationwebui').attr('min', 0);
if ($('#top_k_textgenerationwebui').val() === '-1' || textgenerationwebui_settings['top_k'] === -1) {
textgenerationwebui_settings['top_k'] = 0;
if ($('#top_k_textgenerationwebui').val() === '-1' || textgenerationwebui_settings.top_k === -1) {
textgenerationwebui_settings.top_k = 0;
$('#top_k_textgenerationwebui').val('0').trigger('input');
}
}
+2 -2
View File
@@ -410,8 +410,8 @@ export class ToolManager {
if (tools.length) {
console.log('[ToolManager] Registered function tools:', tools);
data['tools'] = tools;
data['tool_choice'] = 'auto';
data.tools = tools;
data.tool_choice = 'auto';
}
}
+10 -4
View File
@@ -36,10 +36,16 @@ export const localizePagination = function (container) {
/**
* Checks if the current environment supports negative lookbehind in regular expressions.
* @type {{ (): boolean; result?: boolean }} Defines the function as a memoized object with a cached result.
* @returns {boolean} True if negative lookbehind is supported, false otherwise.
*/
export function canUseNegativeLookbehind() {
let result = canUseNegativeLookbehind['result'];
/**
* A reference to the function itself, typed as a callable object with a cache property.
* @type {{ (): boolean; result?: boolean }}
*/
const fn = canUseNegativeLookbehind;
let result = fn.result;
if (typeof result !== 'boolean') {
try {
new RegExp('(?<!_)');
@@ -47,7 +53,7 @@ export function canUseNegativeLookbehind() {
} catch (e) {
result = false;
}
canUseNegativeLookbehind['result'] = result;
fn.result = result;
}
return result;
}
@@ -2440,8 +2446,8 @@ export async function fetchFaFile(name) {
const sheet = style.sheet;
style.remove();
return [...sheet.cssRules]
.filter(rule => rule.style?.content)
.map(rule => rule.selectorText.split(/,\s*/).map(selector => selector.split('::').shift().slice(1)))
.filter(rule => rule['style']?.content)
.map(rule => rule['selectorText'].split(/,\s*/).map(selector => selector.split('::').shift().slice(1)))
;
}
+1 -1
View File
@@ -3271,7 +3271,7 @@ export async function getWorldEntry(name, data, entry) {
const commentInput = headerTemplate.find('textarea[name="comment"]');
//Update the commentInput's placeholder.
const keys = entry['key'].join(', ');
const keys = entry.key.join(', ');
setCommentPlaceholder(keys, commentInput);
commentInput.data('uid', entry.uid);
+2 -2
View File
@@ -145,7 +145,7 @@ router.post('/get', async (request, response) => {
for (let file of files) {
if (!file.endsWith('.placeholder')) {
//console.debug("Asset VRM model found:",file)
output['vrm']['model'].push(clientRelativePath(request.user.directories.root, file));
output.vrm.model.push(clientRelativePath(request.user.directories.root, file));
}
}
@@ -156,7 +156,7 @@ router.post('/get', async (request, response) => {
for (let file of files) {
if (!file.endsWith('.placeholder')) {
//console.debug("Asset VRM animation found:",file)
output['vrm']['animation'].push(clientRelativePath(request.user.directories.root, file));
output.vrm.animation.push(clientRelativePath(request.user.directories.root, file));
}
}
continue;
+2 -2
View File
@@ -245,7 +245,7 @@ async function sendClaudeRequest(request, response) {
};
if (useSystemPrompt) {
if (enableSystemPromptCache && Array.isArray(convertedPrompt.systemPrompt) && convertedPrompt.systemPrompt.length) {
convertedPrompt.systemPrompt[convertedPrompt.systemPrompt.length - 1]['cache_control'] = { type: 'ephemeral', ttl: cacheTTL };
convertedPrompt.systemPrompt[convertedPrompt.systemPrompt.length - 1].cache_control = { type: 'ephemeral', ttl: cacheTTL };
}
requestBody.system = convertedPrompt.systemPrompt;
@@ -261,7 +261,7 @@ async function sendClaudeRequest(request, response) {
.map(fn => ({ name: fn.name, description: fn.description, input_schema: flattenSchema(fn.parameters, request.body.chat_completion_source) }));
if (enableSystemPromptCache && requestBody.tools.length) {
requestBody.tools[requestBody.tools.length - 1]['cache_control'] = { type: 'ephemeral', ttl: cacheTTL };
requestBody.tools[requestBody.tools.length - 1].cache_control = { type: 'ephemeral', ttl: cacheTTL };
}
}
+1 -1
View File
@@ -76,7 +76,7 @@ router.post('/generate', async function (request, response_generate) {
sampler_seed: request.body.sampler_seed,
};
if (request.body.stop_sequence) {
this_settings['stop_sequence'] = request.body.stop_sequence;
this_settings.stop_sequence = request.body.stop_sequence;
}
}
+6 -6
View File
@@ -257,10 +257,10 @@ router.post('/props', async function (request, response) {
/** @type {any} */
const props = await propsReply.json();
// TEMPORARY: llama.cpp's /props endpoint has a bug which replaces the last newline with a \0
if (apiType === TEXTGEN_TYPES.LLAMACPP && props['chat_template'] && props['chat_template'].endsWith('\u0000')) {
props['chat_template'] = props['chat_template'].slice(0, -1) + '\n';
if (apiType === TEXTGEN_TYPES.LLAMACPP && props.chat_template && props.chat_template.endsWith('\u0000')) {
props.chat_template = props.chat_template.slice(0, -1) + '\n';
}
props['chat_template_hash'] = createHash('sha256').update(props['chat_template']).digest('hex');
props.chat_template_hash = createHash('sha256').update(props.chat_template).digest('hex');
console.debug(`Model properties: ${JSON.stringify(props)}`);
return response.send(props);
} catch (error) {
@@ -380,7 +380,7 @@ router.post('/generate', async function (request, response) {
const keepAlive = Number(getConfigValue('ollama.keepAlive', -1, 'number'));
const numBatch = Number(getConfigValue('ollama.batchSize', -1, 'number'));
if (numBatch > 0) {
request.body['num_batch'] = numBatch;
request.body.num_batch = numBatch;
}
args.body = JSON.stringify({
model: request.body.model,
@@ -410,7 +410,7 @@ router.post('/generate', async function (request, response) {
// Map InfermaticAI response to OAI completions format
if (apiType === TEXTGEN_TYPES.INFERMATICAI) {
data['choices'] = (data?.choices || []).map(choice => ({ text: choice?.message?.content || choice.text, logprobs: choice?.logprobs, index: choice?.index }));
data.choices = (data?.choices || []).map(choice => ({ text: choice?.message?.content || choice.text, logprobs: choice?.logprobs, index: choice?.index }));
}
return response.send(data);
@@ -616,7 +616,7 @@ tabby.post('/download', async function (request, response) {
/** @type {any} */
const permissionJson = await permissionResponse.json();
if (permissionJson['permission'] !== 'admin') {
if (permissionJson.permission !== 'admin') {
return response.status(403).send({ error: true });
}
} else {
+13 -13
View File
@@ -412,16 +412,16 @@ const processCharacter = async (item, directories, { shallow }) => {
let jsonObject = getCharaCardV2(JSON.parse(imgData), directories, false);
jsonObject.avatar = item;
const character = jsonObject;
character['json_data'] = imgData;
character.json_data = imgData;
const charStat = fs.statSync(path.join(directories.characters, item));
character['date_added'] = charStat.ctimeMs;
character['create_date'] = jsonObject['create_date'] || new Date(Math.round(charStat.ctimeMs)).toISOString();
character.date_added = charStat.ctimeMs;
character.create_date = jsonObject.create_date || new Date(Math.round(charStat.ctimeMs)).toISOString();
const chatsDirectory = path.join(directories.chats, item.replace('.png', ''));
const { chatSize, dateLastChat } = calculateChatSize(chatsDirectory);
character['chat_size'] = chatSize;
character['date_last_chat'] = dateLastChat;
character['data_size'] = calculateDataSize(jsonObject?.data);
character.chat_size = chatSize;
character.date_last_chat = dateLastChat;
character.data_size = calculateDataSize(jsonObject?.data);
return shallow ? toShallow(character) : character;
}
catch (err) {
@@ -504,7 +504,7 @@ function unsetPrivateFields(char) {
function readFromV2(char) {
if (_.isUndefined(char.data)) {
console.warn(`Char ${char['name']} has Spec v2 data missing`);
console.warn(`Char ${char.name} has Spec v2 data missing`);
return char;
}
@@ -542,17 +542,17 @@ function readFromV2(char) {
//console.warn(`Spec v2 extension data missing for field: ${charField}, using default value: ${defaultValue}`);
char[charField] = defaultValue;
} else {
console.warn(`Char ${char['name']} has Spec v2 data missing for unknown field: ${charField}`);
console.warn(`Char ${char.name} has Spec v2 data missing for unknown field: ${charField}`);
return;
}
}
if (!_.isUndefined(char[charField]) && !_.isUndefined(v2Value) && String(char[charField]) !== String(v2Value)) {
console.warn(`Char ${char['name']} has Spec v2 data mismatch with Spec v1 for field: ${charField}`, char[charField], v2Value);
console.warn(`Char ${char.name} has Spec v2 data mismatch with Spec v1 for field: ${charField}`, char[charField], v2Value);
}
char[charField] = v2Value;
});
char['chat'] = char['chat'] ?? `${char.name} - ${humanizedDateTime()}`;
char.chat = char.chat ?? `${char.name} - ${humanizedDateTime()}`;
return char;
}
@@ -779,7 +779,7 @@ async function importFromCharX(uploadPath, { request }, preservedFileName) {
// Apply standard character transformations
let processedCard = readFromV2(card);
unsetPrivateFields(processedCard);
processedCard['create_date'] = new Date().toISOString();
processedCard.create_date = new Date().toISOString();
processedCard.name = sanitize(processedCard.name);
const fileName = preservedFileName || getPngName(processedCard.name, request.user.directories);
@@ -893,7 +893,7 @@ async function importFromJson(uploadPath, { request }, preservedFileName) {
importRisuSprites(request.user.directories, jsonData);
unsetPrivateFields(jsonData);
jsonData = readFromV2(jsonData);
jsonData['create_date'] = new Date().toISOString();
jsonData.create_date = new Date().toISOString();
const pngName = preservedFileName || getPngName(jsonData.data?.name || jsonData.name, request.user.directories);
const char = JSON.stringify(jsonData);
const result = await writeCharacterData(DEFAULT_AVATAR_PATH, char, pngName, request);
@@ -976,7 +976,7 @@ async function importFromPng(uploadPath, { request }, preservedFileName) {
importRisuSprites(request.user.directories, jsonData);
unsetPrivateFields(jsonData);
jsonData = readFromV2(jsonData);
jsonData['create_date'] = new Date().toISOString();
jsonData.create_date = new Date().toISOString();
const char = JSON.stringify(jsonData);
const result = await writeCharacterData(uploadPath, char, pngName, request);
fs.unlinkSync(uploadPath);
+2 -2
View File
@@ -397,8 +397,8 @@ export async function getChatInfo(pathToFile, additionalData = {}, withMetadata
const jsonData = tryParse(lastLine);
if (jsonData && (jsonData.name || jsonData.character_name || jsonData.chat_metadata)) {
chatData.chat_items = (itemCounter - 1);
chatData.mes = jsonData['mes'] || '[The message is empty]';
chatData.last_mes = jsonData['send_date'] || new Date(Math.round(stats.mtimeMs)).toISOString();
chatData.mes = jsonData.mes || '[The message is empty]';
chatData.last_mes = jsonData.send_date || new Date(Math.round(stats.mtimeMs)).toISOString();
res(chatData);
} else {
+4 -4
View File
@@ -126,8 +126,8 @@ router.post('/all', (request, response) => {
const fileContents = fs.readFileSync(filePath, 'utf8');
const group = JSON.parse(fileContents);
const groupStat = fs.statSync(filePath);
group['date_added'] = groupStat.birthtimeMs;
group['create_date'] = new Date(groupStat.birthtimeMs).toISOString();
group.date_added = groupStat.birthtimeMs;
group.create_date = new Date(groupStat.birthtimeMs).toISOString();
let chat_size = 0;
let date_last_chat = 0;
@@ -142,8 +142,8 @@ router.post('/all', (request, response) => {
}
}
group['date_last_chat'] = date_last_chat;
group['chat_size'] = chat_size;
group.date_last_chat = date_last_chat;
group.chat_size = chat_size;
groups.push(group);
}
catch (error) {
+5 -5
View File
@@ -228,7 +228,7 @@ router.post('/get-model', async (request, response) => {
});
/** @type {any} */
const data = await result.json();
return response.send(data['sd_model_checkpoint']);
return response.send(data.sd_model_checkpoint);
} catch (error) {
console.error(error);
return response.sendStatus(500);
@@ -277,8 +277,8 @@ router.post('/set-model', async (request, response) => {
/** @type {any} */
const progressState = await getProgress();
const progress = progressState['progress'];
const jobCount = progressState['state']['job_count'];
const progress = progressState.progress;
const jobCount = progressState.state.job_count;
if (progress === 0.0 && jobCount === 0) {
break;
}
@@ -834,7 +834,7 @@ drawthings.post('/get-model', async (request, response) => {
/** @type {any} */
const data = await result.json();
return response.send(data['model']);
return response.send(data.model);
} catch (error) {
console.error(error);
return response.sendStatus(500);
@@ -853,7 +853,7 @@ drawthings.post('/get-upscaler', async (request, response) => {
/** @type {any} */
const data = await result.json();
return response.send(data['upscaler']);
return response.send(data.upscaler);
} catch (error) {
console.error(error);
return response.sendStatus(500);
+2 -2
View File
@@ -1052,8 +1052,8 @@ router.post('/remote/kobold/count', async function (request, response) {
/** @type {any} */
const data = await result.json();
const count = data['value'];
const ids = data['ids'] ?? [];
const count = data.value;
const ids = data.ids ?? [];
return response.send({ count, ids });
} catch (error) {
console.error(error);
+3 -3
View File
@@ -639,8 +639,8 @@ test.describe('MacroEngine', () => {
await page.evaluate(async ([originalHash]) => {
/** @type {import('../../public/script.js')} */
const { chat_metadata } = await import('./script.js');
originalHash = chat_metadata['chat_id_hash'];
chat_metadata['chat_id_hash'] = 123456;
originalHash = chat_metadata.chat_id_hash;
chat_metadata.chat_id_hash = 123456;
}, [originalHash]);
const input = 'Choices: {{pick::red::green::blue}}, {{pick::red::green::blue}}.';
@@ -668,7 +668,7 @@ test.describe('MacroEngine', () => {
await page.evaluate(async ([originalHash]) => {
/** @type {import('../../public/script.js')} */
const { chat_metadata } = await import('./script.js');
chat_metadata['chat_id_hash'] = originalHash;
chat_metadata.chat_id_hash = originalHash;
}, [originalHash]);
});
});