"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>
Signed| @@ -38,6 +38,7 @@ declare global { | |||
| 38 | avatar_url?: string; | 38 | avatar_url?: string; |
| 39 | hideMutedSprites?: boolean; | 39 | hideMutedSprites?: boolean; |
| 40 | fav?: boolean; | 40 | fav?: boolean; |
| 41 | date_last_chat?: MessageTimestamp; | ||
| 41 | } | 42 | } |
| 42 | 43 | ||
| 43 | interface ChatFile extends Array<ChatMessage> { | 44 | interface ChatFile extends Array<ChatMessage> { |
| @@ -235,3 +236,11 @@ declare global { | |||
| 235 | 236 | ||
| 236 | type SwipeEvent = JQuery.TriggeredEvent<any, any, HTMLElement, HTMLElement>; | 237 | type SwipeEvent = JQuery.TriggeredEvent<any, any, HTMLElement, HTMLElement>; |
| 237 | } | 238 | } |
| 239 | |||
| 240 | //Overrides for public/scripts/chats.js | ||
| 241 | declare module 'dompurify' { | ||
| 242 | interface Config { | ||
| 243 | MESSAGE_SANITIZE?: boolean; | ||
| 244 | MESSAGE_ALLOW_SYSTEM_UI?: boolean; | ||
| 245 | } | ||
| 246 | } | ||
| @@ -1176,8 +1176,8 @@ export async function getOneCharacter(avatarUrl) { | |||
| 1176 | 1176 | ||
| 1177 | if (response.ok) { | 1177 | if (response.ok) { |
| 1178 | const getData = await response.json(); | 1178 | const getData = await response.json(); |
| 1179 | getData['name'] = DOMPurify.sanitize(getData['name']); | 1179 | getData.name = DOMPurify.sanitize(getData.name); |
| 1180 | getData['chat'] = String(getData['chat']); | 1180 | getData.chat = String(getData.chat); |
| 1181 | 1181 | ||
| 1182 | const indexOf = characters.findIndex(x => x.avatar === avatarUrl); | 1182 | const indexOf = characters.findIndex(x => x.avatar === avatarUrl); |
| 1183 | 1183 | ||
| @@ -1248,14 +1248,14 @@ export async function getCharacters() { | |||
| 1248 | const getData = await response.json(); | 1248 | const getData = await response.json(); |
| 1249 | for (let i = 0; i < getData.length; i++) { | 1249 | for (let i = 0; i < getData.length; i++) { |
| 1250 | characters[i] = getData[i]; | 1250 | characters[i] = getData[i]; |
| 1251 | characters[i]['name'] = DOMPurify.sanitize(characters[i]['name']); | 1251 | characters[i].name = DOMPurify.sanitize(characters[i].name); |
| 1252 | 1252 | ||
| 1253 | // For dropped-in cards | 1253 | // For dropped-in cards |
| 1254 | if (!characters[i]['chat']) { | 1254 | if (!characters[i].chat) { |
| 1255 | characters[i]['chat'] = `${characters[i]['name']} - ${humanizedDateTime()}`; | 1255 | characters[i].chat = `${characters[i].name} - ${humanizedDateTime()}`; |
| 1256 | } | 1256 | } |
| 1257 | 1257 | ||
| 1258 | characters[i]['chat'] = String(characters[i]['chat']); | 1258 | characters[i].chat = String(characters[i].chat); |
| 1259 | } | 1259 | } |
| 1260 | 1260 | ||
| 1261 | if (previousAvatar) { | 1261 | if (previousAvatar) { |
| @@ -1555,7 +1555,7 @@ export async function deleteMessage(id, swipeDeletionIndex = undefined, askConfi | |||
| 1555 | chat.splice(id, 1); | 1555 | chat.splice(id, 1); |
| 1556 | messageElement.remove(); | 1556 | messageElement.remove(); |
| 1557 | 1557 | ||
| 1558 | chat_metadata['tainted'] = true; | 1558 | chat_metadata.tainted = true; |
| 1559 | 1559 | ||
| 1560 | const startIndex = [0, minId].includes(id) ? id : null; | 1560 | const startIndex = [0, minId].includes(id) ? id : null; |
| 1561 | updateViewMessageIds(startIndex); | 1561 | updateViewMessageIds(startIndex); |
| @@ -1625,8 +1625,8 @@ export async function sendTextareaMessage() { | |||
| 1625 | !textareaText && | 1625 | !textareaText && |
| 1626 | !selected_group && | 1626 | !selected_group && |
| 1627 | chat.length && | 1627 | chat.length && |
| 1628 | !lastMessage['is_user'] && | 1628 | !lastMessage.is_user && |
| 1629 | !lastMessage['is_system'] | 1629 | !lastMessage.is_system |
| 1630 | ) { | 1630 | ) { |
| 1631 | generateType = 'continue'; | 1631 | generateType = 'continue'; |
| 1632 | } | 1632 | } |
| @@ -2406,7 +2406,7 @@ export function addCopyToCodeBlocks(messageElement) { | |||
| 2406 | * @returns {void} | 2406 | * @returns {void} |
| 2407 | */ | 2407 | */ |
| 2408 | export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll = true, insertBefore = null, forceId = null, showSwipes = true } = {}) { | 2408 | export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll = true, insertBefore = null, forceId = null, showSwipes = true } = {}) { |
| 2409 | let messageText = mes['mes']; | 2409 | let messageText = mes.mes; |
| 2410 | const momentDate = timestampToMoment(mes.send_date); | 2410 | const momentDate = timestampToMoment(mes.send_date); |
| 2411 | const timestamp = momentDate.isValid() ? momentDate.format('LL LT') : ''; | 2411 | const timestamp = momentDate.isValid() ? momentDate.format('LL LT') : ''; |
| 2412 | 2412 | ||
| @@ -2425,8 +2425,8 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll | |||
| 2425 | const isSystem = mes.is_system; | 2425 | const isSystem = mes.is_system; |
| 2426 | const title = mes.title; | 2426 | const title = mes.title; |
| 2427 | 2427 | ||
| 2428 | //for non-user mesages | 2428 | //for non-user messages |
| 2429 | if (!mes['is_user']) { | 2429 | if (!mes.is_user) { |
| 2430 | if (mes.force_avatar) { | 2430 | if (mes.force_avatar) { |
| 2431 | avatarImg = mes.force_avatar; | 2431 | avatarImg = mes.force_avatar; |
| 2432 | } else if (this_chid === undefined) { | 2432 | } else if (this_chid === undefined) { |
| @@ -2442,9 +2442,9 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll | |||
| 2442 | //if messge is from sytem, use the name provided in the message JSONL to proceed, | 2442 | //if messge is from sytem, use the name provided in the message JSONL to proceed, |
| 2443 | //if not system message, use name2 (char's name) to proceed | 2443 | //if not system message, use name2 (char's name) to proceed |
| 2444 | //characterName = mes.is_system || mes.force_avatar ? mes.name : name2; | 2444 | //characterName = mes.is_system || mes.force_avatar ? mes.name : name2; |
| 2445 | } else if (mes['is_user'] && mes['force_avatar']) { | 2445 | } else if (mes.is_user && mes.force_avatar) { |
| 2446 | // Special case for persona images. | 2446 | // Special case for persona images. |
| 2447 | avatarImg = mes['force_avatar']; | 2447 | avatarImg = mes.force_avatar; |
| 2448 | } | 2448 | } |
| 2449 | 2449 | ||
| 2450 | // if mes.extra.uses_system_ui is true, set an override on the sanitizer options | 2450 | // if mes.extra.uses_system_ui is true, set an override on the sanitizer options |
| @@ -3265,7 +3265,7 @@ export function getCharacterCardFieldsLazy({ chid = undefined } = {}) { | |||
| 3265 | persona: () => baseChatReplace(power_user.persona_description?.trim()), | 3265 | persona: () => baseChatReplace(power_user.persona_description?.trim()), |
| 3266 | system: () => { | 3266 | system: () => { |
| 3267 | if (!character) return ''; | 3267 | if (!character) return ''; |
| 3268 | const systemPrompt = chat_metadata['system_prompt'] || character.data?.system_prompt || ''; | 3268 | const systemPrompt = chat_metadata.system_prompt || character.data?.system_prompt || ''; |
| 3269 | return power_user.prefer_character_prompt ? baseChatReplace(systemPrompt.trim()) : ''; | 3269 | return power_user.prefer_character_prompt ? baseChatReplace(systemPrompt.trim()) : ''; |
| 3270 | }, | 3270 | }, |
| 3271 | jailbreak: () => { | 3271 | jailbreak: () => { |
| @@ -3295,13 +3295,13 @@ export function getCharacterCardFieldsLazy({ chid = undefined } = {}) { | |||
| 3295 | scenario: () => { | 3295 | scenario: () => { |
| 3296 | if (groupCardsLazy) return groupCardsLazy.scenario; | 3296 | if (groupCardsLazy) return groupCardsLazy.scenario; |
| 3297 | if (!character) return ''; | 3297 | if (!character) return ''; |
| 3298 | const scenarioText = chat_metadata['scenario'] || character.scenario || ''; | 3298 | const scenarioText = chat_metadata.scenario || character.scenario || ''; |
| 3299 | return baseChatReplace(scenarioText.trim()); | 3299 | return baseChatReplace(scenarioText.trim()); |
| 3300 | }, | 3300 | }, |
| 3301 | mesExamples: () => { | 3301 | mesExamples: () => { |
| 3302 | if (groupCardsLazy) return groupCardsLazy.mesExamples; | 3302 | if (groupCardsLazy) return groupCardsLazy.mesExamples; |
| 3303 | if (!character) return ''; | 3303 | if (!character) return ''; |
| 3304 | const exampleDialog = chat_metadata['mes_example'] || character.mes_example || ''; | 3304 | const exampleDialog = chat_metadata.mes_example || character.mes_example || ''; |
| 3305 | return baseChatReplace(exampleDialog.trim()); | 3305 | return baseChatReplace(exampleDialog.trim()); |
| 3306 | }, | 3306 | }, |
| 3307 | }; | 3307 | }; |
| @@ -3516,39 +3516,39 @@ class StreamingProcessor { | |||
| 3516 | this.sendTextarea.value = processedText; | 3516 | this.sendTextarea.value = processedText; |
| 3517 | this.sendTextarea.dispatchEvent(new Event('input', { bubbles: true })); | 3517 | this.sendTextarea.dispatchEvent(new Event('input', { bubbles: true })); |
| 3518 | } else { | 3518 | } else { |
| 3519 | const mesChanged = chat[messageId]['mes'] !== processedText; | 3519 | const mesChanged = chat[messageId].mes !== processedText; |
| 3520 | await this.#checkDomElements(messageId); | 3520 | await this.#checkDomElements(messageId); |
| 3521 | this.#updateMessageBlockVisibility(); | 3521 | this.#updateMessageBlockVisibility(); |
| 3522 | const currentTime = new Date(); | 3522 | const currentTime = new Date(); |
| 3523 | chat[messageId]['mes'] = processedText; | 3523 | chat[messageId].mes = processedText; |
| 3524 | chat[messageId]['gen_started'] = this.timeStarted; | 3524 | chat[messageId].gen_started = this.timeStarted; |
| 3525 | chat[messageId]['gen_finished'] = currentTime; | 3525 | chat[messageId].gen_finished = currentTime; |
| 3526 | if (!chat[messageId]['extra']) { | 3526 | if (!chat[messageId].extra) { |
| 3527 | chat[messageId]['extra'] = {}; | 3527 | chat[messageId].extra = {}; |
| 3528 | } | 3528 | } |
| 3529 | chat[messageId]['extra']['time_to_first_token'] = this.timeToFirstToken; | 3529 | chat[messageId].extra.time_to_first_token = this.timeToFirstToken; |
| 3530 | 3530 | ||
| 3531 | // Update reasoning | 3531 | // Update reasoning |
| 3532 | await this.reasoningHandler.process(messageId, mesChanged, this.promptReasoning); | 3532 | await this.reasoningHandler.process(messageId, mesChanged, this.promptReasoning); |
| 3533 | processedText = chat[messageId]['mes']; | 3533 | processedText = chat[messageId].mes; |
| 3534 | 3534 | ||
| 3535 | // Token count update. | 3535 | // Token count update. |
| 3536 | const tokenCountText = this.reasoningHandler.reasoning + processedText; | 3536 | const tokenCountText = this.reasoningHandler.reasoning + processedText; |
| 3537 | const currentTokenCount = isFinal && power_user.message_token_count_enabled ? await getTokenCountAsync(tokenCountText, 0) : 0; | 3537 | const currentTokenCount = isFinal && power_user.message_token_count_enabled ? await getTokenCountAsync(tokenCountText, 0) : 0; |
| 3538 | if (currentTokenCount) { | 3538 | if (currentTokenCount) { |
| 3539 | chat[messageId]['extra']['token_count'] = currentTokenCount; | 3539 | chat[messageId].extra.token_count = currentTokenCount; |
| 3540 | if (this.messageTokenCounterDom instanceof HTMLElement) { | 3540 | if (this.messageTokenCounterDom instanceof HTMLElement) { |
| 3541 | this.messageTokenCounterDom.textContent = `${currentTokenCount}t`; | 3541 | this.messageTokenCounterDom.textContent = `${currentTokenCount}t`; |
| 3542 | } | 3542 | } |
| 3543 | } | 3543 | } |
| 3544 | 3544 | ||
| 3545 | if ((this.type == 'swipe' || this.type === 'continue') && Array.isArray(chat[messageId]['swipes'])) { | 3545 | if ((this.type == 'swipe' || this.type === 'continue') && Array.isArray(chat[messageId].swipes)) { |
| 3546 | chat[messageId]['swipes'][chat[messageId]['swipe_id']] = processedText; | 3546 | chat[messageId].swipes[chat[messageId].swipe_id] = processedText; |
| 3547 | chat[messageId]['swipe_info'][chat[messageId]['swipe_id']] = { | 3547 | chat[messageId].swipe_info[chat[messageId].swipe_id] = { |
| 3548 | 'send_date': chat[messageId]['send_date'], | 3548 | 'send_date': chat[messageId].send_date, |
| 3549 | 'gen_started': chat[messageId]['gen_started'], | 3549 | 'gen_started': chat[messageId].gen_started, |
| 3550 | 'gen_finished': chat[messageId]['gen_finished'], | 3550 | 'gen_finished': chat[messageId].gen_finished, |
| 3551 | 'extra': structuredClone(chat[messageId]['extra']), | 3551 | 'extra': structuredClone(chat[messageId].extra), |
| 3552 | }; | 3552 | }; |
| 3553 | } | 3553 | } |
| 3554 | 3554 | ||
| @@ -3657,13 +3657,13 @@ class StreamingProcessor { | |||
| 3657 | 3657 | ||
| 3658 | setFirstSwipe(messageId) { | 3658 | setFirstSwipe(messageId) { |
| 3659 | if (this.type !== 'swipe' && this.type !== 'impersonate') { | 3659 | if (this.type !== 'swipe' && this.type !== 'impersonate') { |
| 3660 | if (Array.isArray(chat[messageId]['swipes']) && chat[messageId]['swipes'].length === 1 && chat[messageId]['swipe_id'] === 0) { | 3660 | if (Array.isArray(chat[messageId].swipes) && chat[messageId].swipes.length === 1 && chat[messageId].swipe_id === 0) { |
| 3661 | chat[messageId]['swipes'][0] = chat[messageId]['mes']; | 3661 | chat[messageId].swipes[0] = chat[messageId].mes; |
| 3662 | chat[messageId]['swipe_info'][0] = { | 3662 | chat[messageId].swipe_info[0] = { |
| 3663 | 'send_date': chat[messageId]['send_date'], | 3663 | 'send_date': chat[messageId].send_date, |
| 3664 | 'gen_started': chat[messageId]['gen_started'], | 3664 | 'gen_started': chat[messageId].gen_started, |
| 3665 | 'gen_finished': chat[messageId]['gen_finished'], | 3665 | 'gen_finished': chat[messageId].gen_finished, |
| 3666 | 'extra': structuredClone(chat[messageId]['extra']), | 3666 | 'extra': structuredClone(chat[messageId].extra), |
| 3667 | }; | 3667 | }; |
| 3668 | } | 3668 | } |
| 3669 | } | 3669 | } |
| @@ -4143,7 +4143,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 4143 | // Hide swipes if not in a dry run. | 4143 | // Hide swipes if not in a dry run. |
| 4144 | hideSwipeButtons(); | 4144 | hideSwipeButtons(); |
| 4145 | // If generated any message, set the flag to indicate it can't be recreated again. | 4145 | // If generated any message, set the flag to indicate it can't be recreated again. |
| 4146 | chat_metadata['tainted'] = true; | 4146 | chat_metadata.tainted = true; |
| 4147 | } | 4147 | } |
| 4148 | 4148 | ||
| 4149 | if (selected_group && !is_group_generating) { | 4149 | if (selected_group && !is_group_generating) { |
| @@ -4201,7 +4201,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 4201 | $('#send_textarea').val('')[0].dispatchEvent(new Event('input', { bubbles: true })); | 4201 | $('#send_textarea').val('')[0].dispatchEvent(new Event('input', { bubbles: true })); |
| 4202 | } else { | 4202 | } else { |
| 4203 | textareaText = ''; | 4203 | textareaText = ''; |
| 4204 | if (chat.length && lastMessage['is_user']) { | 4204 | if (chat.length && lastMessage.is_user) { |
| 4205 | //do nothing? why does this check exist? | 4205 | //do nothing? why does this check exist? |
| 4206 | } | 4206 | } |
| 4207 | else if (type !== 'quiet' && type !== 'swipe' && !isImpersonate && !dryRun && chat.length) { | 4207 | 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 | |||
| 4215 | 4215 | ||
| 4216 | // Rewrite the generation timer to account for the time passed for all the continuations. | 4216 | // Rewrite the generation timer to account for the time passed for all the continuations. |
| 4217 | if (isContinue && chat.length) { | 4217 | if (isContinue && chat.length) { |
| 4218 | const prevFinished = lastMessage['gen_finished']; | 4218 | const prevFinished = lastMessage.gen_finished; |
| 4219 | const prevStarted = lastMessage['gen_started']; | 4219 | const prevStarted = lastMessage.gen_started; |
| 4220 | 4220 | ||
| 4221 | if (prevFinished && prevStarted) { | 4221 | if (prevFinished && prevStarted) { |
| 4222 | const timePassed = Number(prevFinished) - Number(prevStarted); | 4222 | const timePassed = Number(prevFinished) - Number(prevStarted); |
| 4223 | generation_started = new Date(Date.now() - timePassed); | 4223 | generation_started = new Date(Date.now() - timePassed); |
| 4224 | lastMessage['gen_started'] = generation_started; | 4224 | lastMessage.gen_started = generation_started; |
| 4225 | } | 4225 | } |
| 4226 | } | 4226 | } |
| 4227 | 4227 | ||
| @@ -4903,7 +4903,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 4903 | let thisPromptContextSize = await getTokenCountAsync(prompt, power_user.token_padding); | 4903 | let thisPromptContextSize = await getTokenCountAsync(prompt, power_user.token_padding); |
| 4904 | 4904 | ||
| 4905 | if (thisPromptContextSize > this_max_context) { //if the prepared prompt is larger than the max context size... | 4905 | if (thisPromptContextSize > this_max_context) { //if the prepared prompt is larger than the max context size... |
| 4906 | if (count_exm_add > 0) { // ..and we have example mesages.. | 4906 | if (count_exm_add > 0) { // ..and we have example messages.. |
| 4907 | count_exm_add--; // remove the example messages... | 4907 | count_exm_add--; // remove the example messages... |
| 4908 | await checkPromptSize(); // and try agin... | 4908 | await checkPromptSize(); // and try agin... |
| 4909 | } else if (mesSend.length > 0) { // if the chat history is longer than 0 | 4909 | } else if (mesSend.length > 0) { // if the chat history is longer than 0 |
| @@ -5631,7 +5631,7 @@ export function getBiasStrings(textareaText, type) { | |||
| 5631 | function formatMessageHistoryItem(chatItem, isInstruct, forceOutputSequence) { | 5631 | function formatMessageHistoryItem(chatItem, isInstruct, forceOutputSequence) { |
| 5632 | const isNarratorType = chatItem?.extra?.type === system_message_types.NARRATOR; | 5632 | const isNarratorType = chatItem?.extra?.type === system_message_types.NARRATOR; |
| 5633 | const characterName = chatItem?.name ? chatItem.name : name2; | 5633 | const characterName = chatItem?.name ? chatItem.name : name2; |
| 5634 | const itemName = chatItem.is_user ? chatItem['name'] : characterName; | 5634 | const itemName = chatItem.is_user ? chatItem.name : characterName; |
| 5635 | const shouldPrependName = !isNarratorType; | 5635 | const shouldPrependName = !isNarratorType; |
| 5636 | 5636 | ||
| 5637 | // If this symbol flag is set, completely ignore the message. | 5637 | // If this symbol flag is set, completely ignore the message. |
| @@ -5700,7 +5700,7 @@ export async function sendMessageAsUser(messageText, messageBias, insertAt = nul | |||
| 5700 | await populateFileAttachment(message); | 5700 | await populateFileAttachment(message); |
| 5701 | statMesProcess(message, 'user', characters, this_chid, ''); | 5701 | statMesProcess(message, 'user', characters, this_chid, ''); |
| 5702 | 5702 | ||
| 5703 | chat_metadata['tainted'] = true; | 5703 | chat_metadata.tainted = true; |
| 5704 | 5704 | ||
| 5705 | if (typeof insertAt === 'number' && insertAt >= 0 && insertAt <= chat.length) { | 5705 | if (typeof insertAt === 'number' && insertAt >= 0 && insertAt <= chat.length) { |
| 5706 | chat.splice(insertAt, 0, message); | 5706 | chat.splice(insertAt, 0, message); |
| @@ -5851,7 +5851,7 @@ function setInContextMessages(msgInContextCount, type) { | |||
| 5851 | 5851 | ||
| 5852 | // Update last id to chat. No metadata save on purpose, gets hopefully saved via another call | 5852 | // Update last id to chat. No metadata save on purpose, gets hopefully saved via another call |
| 5853 | const lastMessageId = Math.max(0, chat.length - msgInContextCount); | 5853 | const lastMessageId = Math.max(0, chat.length - msgInContextCount); |
| 5854 | chat_metadata['lastInContextMessageId'] = lastMessageId; | 5854 | chat_metadata.lastInContextMessageId = lastMessageId; |
| 5855 | } | 5855 | } |
| 5856 | 5856 | ||
| 5857 | /** | 5857 | /** |
| @@ -6392,18 +6392,18 @@ export async function saveReply({ type, getMessage, fromStreaming = false, title | |||
| 6392 | 6392 | ||
| 6393 | const lastMessage = chat[chat.length - 1]; | 6393 | const lastMessage = chat[chat.length - 1]; |
| 6394 | 6394 | ||
| 6395 | if (type != 'append' && type != 'continue' && type != 'appendFinal' && chat.length && (lastMessage['swipe_id'] === undefined || | 6395 | if (type != 'append' && type != 'continue' && type != 'appendFinal' && chat.length && (lastMessage.swipe_id === undefined || |
| 6396 | lastMessage['is_user'])) { | 6396 | lastMessage.is_user)) { |
| 6397 | type = 'normal'; | 6397 | type = 'normal'; |
| 6398 | } | 6398 | } |
| 6399 | 6399 | ||
| 6400 | if (chat.length && (!lastMessage['extra'] || typeof lastMessage['extra'] !== 'object')) { | 6400 | if (chat.length && (!lastMessage.extra || typeof lastMessage.extra !== 'object')) { |
| 6401 | lastMessage['extra'] = {}; | 6401 | lastMessage.extra = {}; |
| 6402 | } | 6402 | } |
| 6403 | 6403 | ||
| 6404 | // Coerce null/undefined to empty string | 6404 | // Coerce null/undefined to empty string |
| 6405 | if (chat.length && !lastMessage['extra']['reasoning']) { | 6405 | if (chat.length && !lastMessage.extra.reasoning) { |
| 6406 | lastMessage['extra']['reasoning'] = ''; | 6406 | lastMessage.extra.reasoning = ''; |
| 6407 | } | 6407 | } |
| 6408 | 6408 | ||
| 6409 | if (!reasoning) { | 6409 | if (!reasoning) { |
| @@ -6413,70 +6413,70 @@ export async function saveReply({ type, getMessage, fromStreaming = false, title | |||
| 6413 | let oldMessage = ''; | 6413 | let oldMessage = ''; |
| 6414 | const generationFinished = new Date(); | 6414 | const generationFinished = new Date(); |
| 6415 | if (type === 'swipe') { | 6415 | if (type === 'swipe') { |
| 6416 | oldMessage = lastMessage['mes']; | 6416 | oldMessage = lastMessage.mes; |
| 6417 | lastMessage['swipes'].length++; | 6417 | lastMessage.swipes.length++; |
| 6418 | if (lastMessage['swipe_id'] === lastMessage['swipes'].length - 1) { | 6418 | if (lastMessage.swipe_id === lastMessage.swipes.length - 1) { |
| 6419 | lastMessage['title'] = title; | 6419 | lastMessage.title = title; |
| 6420 | lastMessage['mes'] = getMessage; | 6420 | lastMessage.mes = getMessage; |
| 6421 | lastMessage['gen_started'] = generation_started; | 6421 | lastMessage.gen_started = generation_started; |
| 6422 | lastMessage['gen_finished'] = generationFinished; | 6422 | lastMessage.gen_finished = generationFinished; |
| 6423 | lastMessage['send_date'] = getMessageTimeStamp(); | 6423 | lastMessage.send_date = getMessageTimeStamp(); |
| 6424 | lastMessage['extra']['api'] = getGeneratingApi(); | 6424 | lastMessage.extra.api = getGeneratingApi(); |
| 6425 | lastMessage['extra']['model'] = getGeneratingModel(); | 6425 | lastMessage.extra.model = getGeneratingModel(); |
| 6426 | lastMessage['extra']['reasoning'] = reasoning; | 6426 | lastMessage.extra.reasoning = reasoning; |
| 6427 | lastMessage['extra']['reasoning_duration'] = null; | 6427 | lastMessage.extra.reasoning_duration = null; |
| 6428 | lastMessage['extra']['reasoning_signature'] = reasoningSignature; | 6428 | lastMessage.extra.reasoning_signature = reasoningSignature; |
| 6429 | await processImageAttachment(lastMessage, { imageUrls }); | 6429 | await processImageAttachment(lastMessage, { imageUrls }); |
| 6430 | if (power_user.message_token_count_enabled) { | 6430 | if (power_user.message_token_count_enabled) { |
| 6431 | const tokenCountText = (reasoning || '') + lastMessage['mes']; | 6431 | const tokenCountText = (reasoning || '') + lastMessage.mes; |
| 6432 | lastMessage['extra']['token_count'] = await getTokenCountAsync(tokenCountText, 0); | 6432 | lastMessage.extra.token_count = await getTokenCountAsync(tokenCountText, 0); |
| 6433 | } | 6433 | } |
| 6434 | const chat_id = (chat.length - 1); | 6434 | const chat_id = (chat.length - 1); |
| 6435 | !fromStreaming && await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id, type); | 6435 | !fromStreaming && await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id, type); |
| 6436 | addOneMessage(chat[chat_id], { type: 'swipe' }); | 6436 | addOneMessage(chat[chat_id], { type: 'swipe' }); |
| 6437 | !fromStreaming && await eventSource.emit(event_types.CHARACTER_MESSAGE_RENDERED, chat_id, type); | 6437 | !fromStreaming && await eventSource.emit(event_types.CHARACTER_MESSAGE_RENDERED, chat_id, type); |
| 6438 | } else { | 6438 | } else { |
| 6439 | lastMessage['mes'] = getMessage; | 6439 | lastMessage.mes = getMessage; |
| 6440 | } | 6440 | } |
| 6441 | } else if (type === 'append' || type === 'continue') { | 6441 | } else if (type === 'append' || type === 'continue') { |
| 6442 | console.debug('Trying to append.'); | 6442 | console.debug('Trying to append.'); |
| 6443 | oldMessage = lastMessage['mes']; | 6443 | oldMessage = lastMessage.mes; |
| 6444 | lastMessage['title'] = title; | 6444 | lastMessage.title = title; |
| 6445 | lastMessage['mes'] += getMessage; | 6445 | lastMessage.mes += getMessage; |
| 6446 | lastMessage['gen_started'] = generation_started; | 6446 | lastMessage.gen_started = generation_started; |
| 6447 | lastMessage['gen_finished'] = generationFinished; | 6447 | lastMessage.gen_finished = generationFinished; |
| 6448 | lastMessage['send_date'] = getMessageTimeStamp(); | 6448 | lastMessage.send_date = getMessageTimeStamp(); |
| 6449 | lastMessage['extra']['api'] = getGeneratingApi(); | 6449 | lastMessage.extra.api = getGeneratingApi(); |
| 6450 | lastMessage['extra']['model'] = getGeneratingModel(); | 6450 | lastMessage.extra.model = getGeneratingModel(); |
| 6451 | lastMessage['extra']['reasoning'] = reasoning; | 6451 | lastMessage.extra.reasoning = reasoning; |
| 6452 | lastMessage['extra']['reasoning_duration'] = null; | 6452 | lastMessage.extra.reasoning_duration = null; |
| 6453 | lastMessage['extra']['reasoning_signature'] = reasoningSignature; | 6453 | lastMessage.extra.reasoning_signature = reasoningSignature; |
| 6454 | await processImageAttachment(lastMessage, { imageUrls }); | 6454 | await processImageAttachment(lastMessage, { imageUrls }); |
| 6455 | if (power_user.message_token_count_enabled) { | 6455 | if (power_user.message_token_count_enabled) { |
| 6456 | const tokenCountText = (reasoning || '') + lastMessage['mes']; | 6456 | const tokenCountText = (reasoning || '') + lastMessage.mes; |
| 6457 | lastMessage['extra']['token_count'] = await getTokenCountAsync(tokenCountText, 0); | 6457 | lastMessage.extra.token_count = await getTokenCountAsync(tokenCountText, 0); |
| 6458 | } | 6458 | } |
| 6459 | const chat_id = (chat.length - 1); | 6459 | const chat_id = (chat.length - 1); |
| 6460 | !fromStreaming && await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id, type); | 6460 | !fromStreaming && await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id, type); |
| 6461 | addOneMessage(chat[chat_id], { type: 'swipe' }); | 6461 | addOneMessage(chat[chat_id], { type: 'swipe' }); |
| 6462 | !fromStreaming && await eventSource.emit(event_types.CHARACTER_MESSAGE_RENDERED, chat_id, type); | 6462 | !fromStreaming && await eventSource.emit(event_types.CHARACTER_MESSAGE_RENDERED, chat_id, type); |
| 6463 | } else if (type === 'appendFinal') { | 6463 | } else if (type === 'appendFinal') { |
| 6464 | oldMessage = lastMessage['mes']; | 6464 | oldMessage = lastMessage.mes; |
| 6465 | console.debug('Trying to appendFinal.'); | 6465 | console.debug('Trying to appendFinal.'); |
| 6466 | lastMessage['title'] = title; | 6466 | lastMessage.title = title; |
| 6467 | lastMessage['mes'] = getMessage; | 6467 | lastMessage.mes = getMessage; |
| 6468 | lastMessage['gen_started'] = generation_started; | 6468 | lastMessage.gen_started = generation_started; |
| 6469 | lastMessage['gen_finished'] = generationFinished; | 6469 | lastMessage.gen_finished = generationFinished; |
| 6470 | lastMessage['send_date'] = getMessageTimeStamp(); | 6470 | lastMessage.send_date = getMessageTimeStamp(); |
| 6471 | lastMessage['extra']['api'] = getGeneratingApi(); | 6471 | lastMessage.extra.api = getGeneratingApi(); |
| 6472 | lastMessage['extra']['model'] = getGeneratingModel(); | 6472 | lastMessage.extra.model = getGeneratingModel(); |
| 6473 | lastMessage['extra']['reasoning'] += reasoning; | 6473 | lastMessage.extra.reasoning += reasoning; |
| 6474 | lastMessage['extra']['reasoning_signature'] = reasoningSignature; | 6474 | lastMessage.extra.reasoning_signature = reasoningSignature; |
| 6475 | await processImageAttachment(lastMessage, { imageUrls }); | 6475 | await processImageAttachment(lastMessage, { imageUrls }); |
| 6476 | // We don't know if the reasoning duration extended, so we don't update it here on purpose. | 6476 | // We don't know if the reasoning duration extended, so we don't update it here on purpose. |
| 6477 | if (power_user.message_token_count_enabled) { | 6477 | if (power_user.message_token_count_enabled) { |
| 6478 | const tokenCountText = (reasoning || '') + lastMessage['mes']; | 6478 | const tokenCountText = (reasoning || '') + lastMessage.mes; |
| 6479 | lastMessage['extra']['token_count'] = await getTokenCountAsync(tokenCountText, 0); | 6479 | lastMessage.extra.token_count = await getTokenCountAsync(tokenCountText, 0); |
| 6480 | } | 6480 | } |
| 6481 | const chat_id = (chat.length - 1); | 6481 | const chat_id = (chat.length - 1); |
| 6482 | !fromStreaming && await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id, type); | 6482 | !fromStreaming && await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id, type); |
| @@ -6487,26 +6487,26 @@ export async function saveReply({ type, getMessage, fromStreaming = false, title | |||
| 6487 | console.debug('entering chat update routine for non-swipe post'); | 6487 | console.debug('entering chat update routine for non-swipe post'); |
| 6488 | const newMessage = {}; | 6488 | const newMessage = {}; |
| 6489 | chat.push(newMessage); | 6489 | chat.push(newMessage); |
| 6490 | newMessage['extra'] = {}; | 6490 | newMessage.extra = {}; |
| 6491 | newMessage['name'] = name2; | 6491 | newMessage.name = name2; |
| 6492 | newMessage['is_user'] = false; | 6492 | newMessage.is_user = false; |
| 6493 | newMessage['send_date'] = getMessageTimeStamp(); | 6493 | newMessage.send_date = getMessageTimeStamp(); |
| 6494 | newMessage['extra']['api'] = getGeneratingApi(); | 6494 | newMessage.extra.api = getGeneratingApi(); |
| 6495 | newMessage['extra']['model'] = getGeneratingModel(); | 6495 | newMessage.extra.model = getGeneratingModel(); |
| 6496 | newMessage['extra']['reasoning'] = reasoning; | 6496 | newMessage.extra.reasoning = reasoning; |
| 6497 | newMessage['extra']['reasoning_duration'] = null; | 6497 | newMessage.extra.reasoning_duration = null; |
| 6498 | newMessage['extra']['reasoning_signature'] = reasoningSignature; | 6498 | newMessage.extra.reasoning_signature = reasoningSignature; |
| 6499 | if (power_user.trim_spaces) { | 6499 | if (power_user.trim_spaces) { |
| 6500 | getMessage = getMessage.trim(); | 6500 | getMessage = getMessage.trim(); |
| 6501 | } | 6501 | } |
| 6502 | newMessage['mes'] = getMessage; | 6502 | newMessage.mes = getMessage; |
| 6503 | newMessage['title'] = title; | 6503 | newMessage.title = title; |
| 6504 | newMessage['gen_started'] = generation_started; | 6504 | newMessage.gen_started = generation_started; |
| 6505 | newMessage['gen_finished'] = generationFinished; | 6505 | newMessage.gen_finished = generationFinished; |
| 6506 | 6506 | ||
| 6507 | if (power_user.message_token_count_enabled) { | 6507 | if (power_user.message_token_count_enabled) { |
| 6508 | const tokenCountText = (reasoning || '') + newMessage['mes']; | 6508 | const tokenCountText = (reasoning || '') + newMessage.mes; |
| 6509 | newMessage['extra']['token_count'] = await getTokenCountAsync(tokenCountText, 0); | 6509 | newMessage.extra.token_count = await getTokenCountAsync(tokenCountText, 0); |
| 6510 | } | 6510 | } |
| 6511 | 6511 | ||
| 6512 | if (selected_group) { | 6512 | if (selected_group) { |
| @@ -6515,9 +6515,9 @@ export async function saveReply({ type, getMessage, fromStreaming = false, title | |||
| 6515 | if (characters[this_chid].avatar != 'none') { | 6515 | if (characters[this_chid].avatar != 'none') { |
| 6516 | avatarImg = getThumbnailUrl('avatar', characters[this_chid].avatar); | 6516 | avatarImg = getThumbnailUrl('avatar', characters[this_chid].avatar); |
| 6517 | } | 6517 | } |
| 6518 | newMessage['force_avatar'] = avatarImg; | 6518 | newMessage.force_avatar = avatarImg; |
| 6519 | newMessage['original_avatar'] = characters[this_chid].avatar; | 6519 | newMessage.original_avatar = characters[this_chid].avatar; |
| 6520 | newMessage['extra']['gen_id'] = group_generation_id; | 6520 | newMessage.extra.gen_id = group_generation_id; |
| 6521 | } | 6521 | } |
| 6522 | 6522 | ||
| 6523 | await processImageAttachment(newMessage, { imageUrls }); | 6523 | await processImageAttachment(newMessage, { imageUrls }); |
| @@ -6529,27 +6529,27 @@ export async function saveReply({ type, getMessage, fromStreaming = false, title | |||
| 6529 | } | 6529 | } |
| 6530 | 6530 | ||
| 6531 | const item = chat[chat.length - 1]; | 6531 | const item = chat[chat.length - 1]; |
| 6532 | if (item['swipe_info'] === undefined) { | 6532 | if (item.swipe_info === undefined) { |
| 6533 | item['swipe_info'] = []; | 6533 | item.swipe_info = []; |
| 6534 | } | 6534 | } |
| 6535 | if (item['swipe_id'] !== undefined) { | 6535 | if (item.swipe_id !== undefined) { |
| 6536 | const swipeId = item['swipe_id']; | 6536 | const swipeId = item.swipe_id; |
| 6537 | item['swipes'][swipeId] = item['mes']; | 6537 | item.swipes[swipeId] = item.mes; |
| 6538 | item['swipe_info'][swipeId] = { | 6538 | item.swipe_info[swipeId] = { |
| 6539 | send_date: item['send_date'], | 6539 | send_date: item.send_date, |
| 6540 | gen_started: item['gen_started'], | 6540 | gen_started: item.gen_started, |
| 6541 | gen_finished: item['gen_finished'], | 6541 | gen_finished: item.gen_finished, |
| 6542 | extra: structuredClone(item['extra']), | 6542 | extra: structuredClone(item.extra), |
| 6543 | }; | 6543 | }; |
| 6544 | } else { | 6544 | } else { |
| 6545 | item['swipe_id'] = 0; | 6545 | item.swipe_id = 0; |
| 6546 | item['swipes'] = []; | 6546 | item.swipes = []; |
| 6547 | item['swipes'][0] = item['mes']; | 6547 | item.swipes[0] = item.mes; |
| 6548 | item['swipe_info'][0] = { | 6548 | item.swipe_info[0] = { |
| 6549 | send_date: item['send_date'], | 6549 | send_date: item.send_date, |
| 6550 | gen_started: item['gen_started'], | 6550 | gen_started: item.gen_started, |
| 6551 | gen_finished: item['gen_finished'], | 6551 | gen_finished: item.gen_finished, |
| 6552 | extra: structuredClone(item['extra']), | 6552 | extra: structuredClone(item.extra), |
| 6553 | }; | 6553 | }; |
| 6554 | } | 6554 | } |
| 6555 | 6555 | ||
| @@ -7155,7 +7155,7 @@ export async function saveChat({ chatName, withMetadata, mesId, force = false } | |||
| 7155 | return; | 7155 | return; |
| 7156 | } | 7156 | } |
| 7157 | 7157 | ||
| 7158 | characters[this_chid]['date_last_chat'] = Date.now(); | 7158 | characters[this_chid].date_last_chat = Date.now(); |
| 7159 | 7159 | ||
| 7160 | const trimmedChat = (mesId !== undefined && mesId >= 0 && mesId < chat.length) | 7160 | const trimmedChat = (mesId !== undefined && mesId >= 0 && mesId < chat.length) |
| 7161 | ? chat.slice(0, Number(mesId) + 1) | 7161 | ? chat.slice(0, Number(mesId) + 1) |
| @@ -7387,15 +7387,19 @@ export async function getChat() { | |||
| 7387 | dataType: 'json', | 7387 | dataType: 'json', |
| 7388 | contentType: 'application/json', | 7388 | contentType: 'application/json', |
| 7389 | }); | 7389 | }); |
| 7390 | if (response[0] !== undefined) { | 7390 | if (Array.isArray(response) && response.length > 0) { |
| 7391 | /** @type {ChatHeader} */ | ||
| 7392 | const chatHeader = response.shift(); | ||
| 7393 | chat_metadata = chatHeader?.chat_metadata ?? {}; | ||
| 7391 | chat.splice(0, chat.length, ...response); | 7394 | chat.splice(0, chat.length, ...response); |
| 7392 | chat_metadata = chat[0]['chat_metadata'] ?? {}; | ||
| 7393 | |||
| 7394 | chat.shift(); | ||
| 7395 | chat.forEach(ensureMessageMediaIsArray); | 7395 | chat.forEach(ensureMessageMediaIsArray); |
| 7396 | } else { | ||
| 7397 | // An empty/corrupted chat file | ||
| 7398 | chat.splice(0, chat.length); | ||
| 7399 | chat_metadata = {}; | ||
| 7396 | } | 7400 | } |
| 7397 | if (!chat_metadata['integrity']) { | 7401 | if (!chat_metadata.integrity) { |
| 7398 | chat_metadata['integrity'] = uuidv4(); | 7402 | chat_metadata.integrity = uuidv4(); |
| 7399 | } | 7403 | } |
| 7400 | await getChatResult(); | 7404 | await getChatResult(); |
| 7401 | eventSource.emit('chatLoaded', { detail: { id: this_chid, character: characters[this_chid] } }); | 7405 | eventSource.emit('chatLoaded', { detail: { id: this_chid, character: characters[this_chid] } }); |
| @@ -7460,9 +7464,9 @@ function getFirstMessage() { | |||
| 7460 | message.mes = swipes[0]; | 7464 | message.mes = swipes[0]; |
| 7461 | } | 7465 | } |
| 7462 | 7466 | ||
| 7463 | message['swipe_id'] = 0; | 7467 | message.swipe_id = 0; |
| 7464 | message['swipes'] = swipes; | 7468 | message.swipes = swipes; |
| 7465 | message['swipe_info'] = swipes.map(_ => ({ | 7469 | message.swipe_info = swipes.map(_ => ({ |
| 7466 | send_date: message.send_date, | 7470 | send_date: message.send_date, |
| 7467 | gen_started: void 0, | 7471 | gen_started: void 0, |
| 7468 | gen_finished: void 0, | 7472 | gen_finished: void 0, |
| @@ -7476,7 +7480,7 @@ function getFirstMessage() { | |||
| 7476 | export async function openCharacterChat(file_name) { | 7480 | export async function openCharacterChat(file_name) { |
| 7477 | await waitUntilCondition(() => !isChatSaving, debounce_timeout.extended, 10); | 7481 | await waitUntilCondition(() => !isChatSaving, debounce_timeout.extended, 10); |
| 7478 | await clearChat(); | 7482 | await clearChat(); |
| 7479 | characters[this_chid]['chat'] = file_name; | 7483 | characters[this_chid].chat = file_name; |
| 7480 | chat.length = 0; | 7484 | chat.length = 0; |
| 7481 | chat_metadata = {}; | 7485 | chat_metadata = {}; |
| 7482 | await getChat(); | 7486 | await getChat(); |
| @@ -7862,7 +7866,7 @@ function updateMessage(div) { | |||
| 7862 | const mes = chat[mesElement.attr('mesid')]; | 7866 | const mes = chat[mesElement.attr('mesid')]; |
| 7863 | 7867 | ||
| 7864 | // editing old messages | 7868 | // editing old messages |
| 7865 | mes['extra'] ??= {}; | 7869 | mes.extra ??= {}; |
| 7866 | 7870 | ||
| 7867 | let regexPlacement; | 7871 | let regexPlacement; |
| 7868 | if (mes?.is_user) { | 7872 | if (mes?.is_user) { |
| @@ -7893,10 +7897,10 @@ function updateMessage(div) { | |||
| 7893 | if (bias) { | 7897 | if (bias) { |
| 7894 | text = removeMacros(text); | 7898 | text = removeMacros(text); |
| 7895 | } | 7899 | } |
| 7896 | mes['mes'] = text; | 7900 | mes.mes = text; |
| 7897 | if (mes['swipe_id'] !== undefined) { | 7901 | if (mes.swipe_id !== undefined) { |
| 7898 | ensureSwipes(mes); | 7902 | ensureSwipes(mes); |
| 7899 | mes['swipes'][mes['swipe_id']] = text; | 7903 | mes.swipes[mes.swipe_id] = text; |
| 7900 | } | 7904 | } |
| 7901 | 7905 | ||
| 7902 | if (mes?.is_system || mes?.is_user || mes.extra?.type === system_message_types.NARRATOR) { | 7906 | if (mes?.is_system || mes?.is_user || mes.extra?.type === system_message_types.NARRATOR) { |
| @@ -7905,7 +7909,7 @@ function updateMessage(div) { | |||
| 7905 | mes.extra.bias = null; | 7909 | mes.extra.bias = null; |
| 7906 | } | 7910 | } |
| 7907 | 7911 | ||
| 7908 | chat_metadata['tainted'] = true; | 7912 | chat_metadata.tainted = true; |
| 7909 | 7913 | ||
| 7910 | return { mesBlock, text, mes, bias }; | 7914 | return { mesBlock, text, mes, bias }; |
| 7911 | } | 7915 | } |
| @@ -8019,7 +8023,7 @@ export async function messageEdit(editMessageId) { | |||
| 8019 | * @param {number} [messageId=this_edit_mes_id] | 8023 | * @param {number} [messageId=this_edit_mes_id] |
| 8020 | */ | 8024 | */ |
| 8021 | async function messageEditCancel(messageId = this_edit_mes_id) { | 8025 | async function messageEditCancel(messageId = this_edit_mes_id) { |
| 8022 | let text = chat[messageId]['mes']; | 8026 | let text = chat[messageId].mes; |
| 8023 | let thisMesDiv; | 8027 | let thisMesDiv; |
| 8024 | // If this is the button then select it's parent. Otherwise, select by messageId. | 8028 | // If this is the button then select it's parent. Otherwise, select by messageId. |
| 8025 | if (this?.classList?.contains('mes_edit_cancel')) { | 8029 | if (this?.classList?.contains('mes_edit_cancel')) { |
| @@ -8167,7 +8171,7 @@ async function messageEditDone(div) { | |||
| 8167 | export async function getChatsFromFiles(data, isGroupChat) { | 8171 | export async function getChatsFromFiles(data, isGroupChat) { |
| 8168 | const context = getContext(); | 8172 | const context = getContext(); |
| 8169 | let chat_dict = {}; | 8173 | let chat_dict = {}; |
| 8170 | let chat_list = Object.values(data).sort((a, b) => a['file_name'].localeCompare(b['file_name'])).reverse(); | 8174 | let chat_list = Object.values(data).sort((a, b) => a.file_name.localeCompare(b.file_name)).reverse(); |
| 8171 | 8175 | ||
| 8172 | let chat_promise = chat_list.map(({ file_name }) => { | 8176 | let chat_promise = chat_list.map(({ file_name }) => { |
| 8173 | return new Promise(async (res, rej) => { | 8177 | return new Promise(async (res, rej) => { |
| @@ -8244,7 +8248,7 @@ export async function getPastCharacterChats(characterId = null) { | |||
| 8244 | } | 8248 | } |
| 8245 | 8249 | ||
| 8246 | const chats = Object.values(data); | 8250 | const chats = Object.values(data); |
| 8247 | return chats.sort((a, b) => a['file_name'].localeCompare(b['file_name'])).reverse(); | 8251 | return chats.sort((a, b) => a.file_name.localeCompare(b.file_name)).reverse(); |
| 8248 | } | 8252 | } |
| 8249 | 8253 | ||
| 8250 | /** | 8254 | /** |
| @@ -8256,9 +8260,9 @@ export function getCurrentChatDetails() { | |||
| 8256 | } | 8260 | } |
| 8257 | 8261 | ||
| 8258 | const group = selected_group ? groups.find(x => x.id === selected_group) : null; | 8262 | const group = selected_group ? groups.find(x => x.id === selected_group) : null; |
| 8259 | const currentChat = selected_group ? group?.chat_id : characters[this_chid]['chat']; | 8263 | const currentChat = selected_group ? group?.chat_id : characters[this_chid].chat; |
| 8260 | const displayName = selected_group ? group?.name : characters[this_chid].name; | 8264 | const displayName = selected_group ? group?.name : characters[this_chid].name; |
| 8261 | const avatarImg = selected_group ? group?.avatar_url : getThumbnailUrl('avatar', characters[this_chid]['avatar']); | 8265 | const avatarImg = selected_group ? group?.avatar_url : getThumbnailUrl('avatar', characters[this_chid].avatar); |
| 8262 | return { sessionName: currentChat, group: group, characterName: displayName, avatarImgURL: avatarImg }; | 8266 | return { sessionName: currentChat, group: group, characterName: displayName, avatarImgURL: avatarImg }; |
| 8263 | } | 8267 | } |
| 8264 | 8268 | ||
| @@ -8722,9 +8726,9 @@ export async function setCharacterSettingsOverrides() { | |||
| 8722 | return; | 8726 | return; |
| 8723 | } | 8727 | } |
| 8724 | 8728 | ||
| 8725 | const scenarioOverrideValue = chat_metadata['scenario'] || ''; | 8729 | const scenarioOverrideValue = chat_metadata.scenario || ''; |
| 8726 | const exampleMessagesValue = chat_metadata['mes_example'] || ''; | 8730 | const exampleMessagesValue = chat_metadata.mes_example || ''; |
| 8727 | const systemPromptValue = chat_metadata['system_prompt'] || ''; | 8731 | const systemPromptValue = chat_metadata.system_prompt || ''; |
| 8728 | const isGroup = !!selected_group; | 8732 | const isGroup = !!selected_group; |
| 8729 | 8733 | ||
| 8730 | const $template = $(await renderTemplateAsync('scenarioOverride')); | 8734 | const $template = $(await renderTemplateAsync('scenarioOverride')); |
| @@ -8771,9 +8775,9 @@ export async function setCharacterSettingsOverrides() { | |||
| 8771 | allowVerticalScrolling: true, | 8775 | allowVerticalScrolling: true, |
| 8772 | }); | 8776 | }); |
| 8773 | 8777 | ||
| 8774 | chat_metadata['scenario'] = pendingChanges.scenario; | 8778 | chat_metadata.scenario = pendingChanges.scenario; |
| 8775 | chat_metadata['mes_example'] = pendingChanges.examples; | 8779 | chat_metadata.mes_example = pendingChanges.examples; |
| 8776 | chat_metadata['system_prompt'] = pendingChanges.system_prompt; | 8780 | chat_metadata.system_prompt = pendingChanges.system_prompt; |
| 8777 | await saveMetadata(); | 8781 | await saveMetadata(); |
| 8778 | } | 8782 | } |
| 8779 | 8783 | ||
| @@ -9071,7 +9075,7 @@ export async function deleteSwipe(swipeId = null, messageId = chat.length - 1) { | |||
| 9071 | // Select the next swipe, or the one before if it was the last one | 9075 | // Select the next swipe, or the one before if it was the last one |
| 9072 | const newSwipeId = Math.min(swipeId, message.swipes.length - 1); | 9076 | const newSwipeId = Math.min(swipeId, message.swipes.length - 1); |
| 9073 | 9077 | ||
| 9074 | chat_metadata['tainted'] = true; | 9078 | chat_metadata.tainted = true; |
| 9075 | 9079 | ||
| 9076 | messageId = Number(messageId); | 9080 | messageId = Number(messageId); |
| 9077 | swipeId = Number(swipeId); | 9081 | swipeId = Number(swipeId); |
| @@ -9585,7 +9589,7 @@ export async function createOrEditCharacter(e) { | |||
| 9585 | !isNewChat && | 9589 | !isNewChat && |
| 9586 | message.mes && | 9590 | message.mes && |
| 9587 | !selected_group && | 9591 | !selected_group && |
| 9588 | !chat_metadata['tainted'] && | 9592 | !chat_metadata.tainted && |
| 9589 | (chat.length === 0 || (chat.length === 1 && !chat[0].is_user && !chat[0].is_system)); | 9593 | (chat.length === 0 || (chat.length === 1 && !chat[0].is_user && !chat[0].is_system)); |
| 9590 | 9594 | ||
| 9591 | if (shouldRegenerateMessage) { | 9595 | if (shouldRegenerateMessage) { |
| @@ -9745,7 +9749,7 @@ export async function swipe(event, direction, { source, repeated, message = chat | |||
| 9745 | } | 9749 | } |
| 9746 | 9750 | ||
| 9747 | //Clamp Id between swipes. | 9751 | //Clamp Id between swipes. |
| 9748 | let clampedId = clamp(chat[mesId]['swipe_id'], 0, Math.max(0, chat[mesId]['swipes'].length - 1)); | 9752 | let clampedId = clamp(chat[mesId].swipe_id, 0, Math.max(0, chat[mesId].swipes.length - 1)); |
| 9749 | 9753 | ||
| 9750 | await updateSwipeCounter(mesId); | 9754 | await updateSwipeCounter(mesId); |
| 9751 | //Fallback. | 9755 | //Fallback. |
| @@ -9837,7 +9841,7 @@ export async function swipe(event, direction, { source, repeated, message = chat | |||
| 9837 | */ | 9841 | */ |
| 9838 | async function loadFromSwipeId(mesId, newSwipeId) { | 9842 | async function loadFromSwipeId(mesId, newSwipeId) { |
| 9839 | //Update the swipe_id. | 9843 | //Update the swipe_id. |
| 9840 | chat[mesId]['swipe_id'] = newSwipeId; | 9844 | chat[mesId].swipe_id = newSwipeId; |
| 9841 | 9845 | ||
| 9842 | clearMessageData(chat[mesId]); | 9846 | clearMessageData(chat[mesId]); |
| 9843 | 9847 | ||
| @@ -9909,7 +9913,8 @@ export async function swipe(event, direction, { source, repeated, message = chat | |||
| 9909 | return true; | 9913 | return true; |
| 9910 | }; | 9914 | }; |
| 9911 | //Wait for the animation's end. https://developer.mozilla.org/en-US/docs/Web/API/Animation/finished | 9915 | //Wait for the animation's end. https://developer.mozilla.org/en-US/docs/Web/API/Animation/finished |
| 9912 | const animation = swipedElementsDiv[0]?.getAnimations().filter((a) => a['animationName'] == 'slide')[0]; | 9916 | const animations = swipedElementsDiv[0]?.getAnimations() ?? []; |
| 9917 | const animation = animations.filter((a) => a instanceof globalThis.CSSAnimation && a.animationName == 'slide')[0]; | ||
| 9913 | try { | 9918 | try { |
| 9914 | 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)); | 9919 | 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)); |
| 9915 | } catch (error) { | 9920 | } catch (error) { |
| @@ -9997,7 +10002,7 @@ export async function swipe(event, direction, { source, repeated, message = chat | |||
| 9997 | 10002 | ||
| 9998 | const tokenCountText = (chat[mesId]?.extra?.reasoning || '') + chat[mesId].mes; | 10003 | const tokenCountText = (chat[mesId]?.extra?.reasoning || '') + chat[mesId].mes; |
| 9999 | const tokenCount = await getTokenCountAsync(tokenCountText, 0); | 10004 | const tokenCount = await getTokenCountAsync(tokenCountText, 0); |
| 10000 | chat[mesId]['extra']['token_count'] = tokenCount; | 10005 | chat[mesId].extra.token_count = tokenCount; |
| 10001 | thisMesDiv.find('.tokenCounterDisplay').text(`${tokenCount}t`); | 10006 | thisMesDiv.find('.tokenCounterDisplay').text(`${tokenCount}t`); |
| 10002 | } | 10007 | } |
| 10003 | } | 10008 | } |
| @@ -10036,20 +10041,20 @@ export async function swipe(event, direction, { source, repeated, message = chat | |||
| 10036 | // Make sure ad-hoc changes to extras are saved before swiping away | 10041 | // Make sure ad-hoc changes to extras are saved before swiping away |
| 10037 | syncMesToSwipe(mesId); | 10042 | syncMesToSwipe(mesId); |
| 10038 | 10043 | ||
| 10039 | if (chat[mesId]['swipe_id'] === undefined) { // if there is no swipe-message in the last spot of the chat array | 10044 | if (chat[mesId].swipe_id === undefined) { // if there is no swipe-message in the last spot of the chat array |
| 10040 | chat[mesId]['swipe_id'] = 0; // set it to id 0 | 10045 | chat[mesId].swipe_id = 0; // set it to id 0 |
| 10041 | chat[mesId]['swipes'] = []; // empty the array | 10046 | chat[mesId].swipes = []; // empty the array |
| 10042 | chat[mesId]['swipe_info'] = []; | 10047 | chat[mesId].swipe_info = []; |
| 10043 | chat[mesId]['swipes'][0] = chat[mesId]['mes']; //assign swipe array with last chat[mesId] from chat | 10048 | chat[mesId].swipes[0] = chat[mesId].mes; //assign swipe array with last chat[mesId] from chat |
| 10044 | chat[mesId]['swipe_info'][0] = { | 10049 | chat[mesId].swipe_info[0] = { |
| 10045 | 'send_date': chat[mesId]['send_date'], | 10050 | 'send_date': chat[mesId].send_date, |
| 10046 | 'gen_started': chat[mesId]['gen_started'], | 10051 | 'gen_started': chat[mesId].gen_started, |
| 10047 | 'gen_finished': chat[mesId]['gen_finished'], | 10052 | 'gen_finished': chat[mesId].gen_finished, |
| 10048 | 'extra': structuredClone(chat[mesId]['extra']), | 10053 | 'extra': structuredClone(chat[mesId].extra), |
| 10049 | }; | 10054 | }; |
| 10050 | } | 10055 | } |
| 10051 | // If the user is holding down the key and we're at the last or first swipe, don't do anything. | 10056 | // If the user is holding down the key and we're at the last or first swipe, don't do anything. |
| 10052 | let isLastSwipe = (direction === SWIPE_DIRECTION.RIGHT) ? (chat[mesId].swipe_id === Math.max(0, chat[mesId]['swipes'].length - 1)) : chat[mesId].swipe_id === 0; | 10057 | let isLastSwipe = (direction === SWIPE_DIRECTION.RIGHT) ? (chat[mesId].swipe_id === Math.max(0, chat[mesId].swipes.length - 1)) : chat[mesId].swipe_id === 0; |
| 10053 | if (source === SWIPE_SOURCE.KEYBOARD && repeated && isLastSwipe) { | 10058 | if (source === SWIPE_SOURCE.KEYBOARD && repeated && isLastSwipe) { |
| 10054 | await endSwipe(); | 10059 | await endSwipe(); |
| 10055 | return; | 10060 | return; |
| @@ -10065,12 +10070,12 @@ export async function swipe(event, direction, { source, repeated, message = chat | |||
| 10065 | if (forceSwipeId == null) newSwipeId--; | 10070 | if (forceSwipeId == null) newSwipeId--; |
| 10066 | //Loop to last swipe if negative. | 10071 | //Loop to last swipe if negative. |
| 10067 | if (newSwipeId < 0) { | 10072 | if (newSwipeId < 0) { |
| 10068 | newSwipeId = Math.max(0, chat[mesId]['swipes'].length - 1); | 10073 | newSwipeId = Math.max(0, chat[mesId].swipes.length - 1); |
| 10069 | } | 10074 | } |
| 10070 | //Limit swipe_id to swipes. | 10075 | //Limit swipe_id to swipes. |
| 10071 | if (newSwipeId > chat[mesId]['swipes'].length - 1) { | 10076 | if (newSwipeId > chat[mesId].swipes.length - 1) { |
| 10072 | toastr.warning(`The swipe_id for message #${mesId} was ${newSwipeId}. It has been reset to ${chat[mesId]['swipes'].length - 1}.`); | 10077 | toastr.warning(`The swipe_id for message #${mesId} was ${newSwipeId}. It has been reset to ${chat[mesId].swipes.length - 1}.`); |
| 10073 | chat[mesId]['swipe_id'] = chat[mesId]['swipes'].length - 1; | 10078 | chat[mesId].swipe_id = chat[mesId].swipes.length - 1; |
| 10074 | await endSwipe(); | 10079 | await endSwipe(); |
| 10075 | return; | 10080 | return; |
| 10076 | } | 10081 | } |
| @@ -10085,24 +10090,24 @@ export async function swipe(event, direction, { source, repeated, message = chat | |||
| 10085 | //Minimum of zero. | 10090 | //Minimum of zero. |
| 10086 | if (newSwipeId < 0) { | 10091 | if (newSwipeId < 0) { |
| 10087 | toastr.warning(`The swipe_id for message #${mesId} was ${newSwipeId}. It has been reset to zero.`); | 10092 | toastr.warning(`The swipe_id for message #${mesId} was ${newSwipeId}. It has been reset to zero.`); |
| 10088 | chat[mesId]['swipe_id'] = 0; | 10093 | chat[mesId].swipe_id = 0; |
| 10089 | await endSwipe(); | 10094 | await endSwipe(); |
| 10090 | return; | 10095 | return; |
| 10091 | } | 10096 | } |
| 10092 | 10097 | ||
| 10093 | //If overswiping. | 10098 | //If overswiping. |
| 10094 | if (newSwipeId >= chat[mesId]['swipes'].length) { | 10099 | if (newSwipeId >= chat[mesId].swipes.length) { |
| 10095 | newSwipeId = chat[mesId]['swipes'].length; | 10100 | newSwipeId = chat[mesId].swipes.length; |
| 10096 | 10101 | ||
| 10097 | //Update the swipe_id. | 10102 | //Update the swipe_id. |
| 10098 | chat[mesId]['swipe_id'] = newSwipeId; | 10103 | chat[mesId].swipe_id = newSwipeId; |
| 10099 | 10104 | ||
| 10100 | const overswipe = getOverswipeBehavior(mesId); | 10105 | const overswipe = getOverswipeBehavior(mesId); |
| 10101 | 10106 | ||
| 10102 | //Cancel the generation. | 10107 | //Cancel the generation. |
| 10103 | if (overswipe == OVERSWIPE_BEHAVIOR.NONE) { | 10108 | if (overswipe == OVERSWIPE_BEHAVIOR.NONE) { |
| 10104 | //Cancel swipe. | 10109 | //Cancel swipe. |
| 10105 | chat[mesId]['swipe_id'] = originalSwipeId; | 10110 | chat[mesId].swipe_id = originalSwipeId; |
| 10106 | await endSwipe(); | 10111 | await endSwipe(); |
| 10107 | return; | 10112 | return; |
| 10108 | } | 10113 | } |
| @@ -11430,7 +11435,7 @@ jQuery(async function () { | |||
| 11430 | chatElement.find(`.mes[mesid="${this_del_mes}"]`).nextAll('div').remove(); | 11435 | chatElement.find(`.mes[mesid="${this_del_mes}"]`).nextAll('div').remove(); |
| 11431 | chatElement.find(`.mes[mesid="${this_del_mes}"]`).remove(); | 11436 | chatElement.find(`.mes[mesid="${this_del_mes}"]`).remove(); |
| 11432 | chat.length = this_del_mes; | 11437 | chat.length = this_del_mes; |
| 11433 | chat_metadata['tainted'] = true; | 11438 | chat_metadata.tainted = true; |
| 11434 | await saveChatConditional(); | 11439 | await saveChatConditional(); |
| 11435 | chatElement.scrollTop(chatElement[0].scrollHeight); | 11440 | chatElement.scrollTop(chatElement[0].scrollHeight); |
| 11436 | await eventSource.emit(event_types.MESSAGE_DELETED, chat.length); | 11441 | await eventSource.emit(event_types.MESSAGE_DELETED, chat.length); |
| @@ -11517,7 +11522,7 @@ jQuery(async function () { | |||
| 11517 | if (this_chid !== undefined || selected_group || name2 === neutralCharacterName) { | 11522 | if (this_chid !== undefined || selected_group || name2 === neutralCharacterName) { |
| 11518 | try { | 11523 | try { |
| 11519 | const messageId = $(this).closest('.mes').attr('mesid'); | 11524 | const messageId = $(this).closest('.mes').attr('mesid'); |
| 11520 | const text = chat[messageId]['mes']; | 11525 | const text = chat[messageId].mes; |
| 11521 | await copyText(text); | 11526 | await copyText(text); |
| 11522 | toastr.info('Copied!', '', { timeOut: 2000 }); | 11527 | toastr.info('Copied!', '', { timeOut: 2000 }); |
| 11523 | } catch (err) { | 11528 | } catch (err) { |
| @@ -11544,8 +11549,8 @@ jQuery(async function () { | |||
| 11544 | let mes_edited = chatElement.find(`[mesid="${this_edit_mes_id}"]`).find('.mes_edit_done'); | 11549 | let mes_edited = chatElement.find(`[mesid="${this_edit_mes_id}"]`).find('.mes_edit_done'); |
| 11545 | if (Number(edit_mes_id) == chat.length - 1) { //if the generating swipe (...) | 11550 | if (Number(edit_mes_id) == chat.length - 1) { //if the generating swipe (...) |
| 11546 | let run_edit = true; | 11551 | let run_edit = true; |
| 11547 | if (chat[edit_mes_id]['swipe_id'] !== undefined) { | 11552 | if (chat[edit_mes_id].swipe_id !== undefined) { |
| 11548 | if (chat[edit_mes_id]['swipes'].length === chat[edit_mes_id]['swipe_id']) { | 11553 | if (chat[edit_mes_id].swipes.length === chat[edit_mes_id].swipe_id) { |
| 11549 | run_edit = false; | 11554 | run_edit = false; |
| 11550 | } | 11555 | } |
| 11551 | } | 11556 | } |
| @@ -11684,8 +11689,8 @@ jQuery(async function () { | |||
| 11684 | $(document).on('click', '.mes_edit_delete', async function (event, customData) { | 11689 | $(document).on('click', '.mes_edit_delete', async function (event, customData) { |
| 11685 | const fromSlashCommand = customData?.fromSlashCommand || false; | 11690 | const fromSlashCommand = customData?.fromSlashCommand || false; |
| 11686 | const message = chat[this_edit_mes_id]; | 11691 | const message = chat[this_edit_mes_id]; |
| 11687 | const selectedSwipe = message['swipe_id'] ?? undefined; | 11692 | const selectedSwipe = message.swipe_id ?? undefined; |
| 11688 | const swipesArray = Array.isArray(message['swipes']) ? message['swipes'] : []; | 11693 | const swipesArray = Array.isArray(message.swipes) ? message.swipes : []; |
| 11689 | const canDeleteSwipe = power_user.confirm_message_delete && !fromSlashCommand && !message.is_user && swipesArray.length > 1 && this_edit_mes_id === chat.length - 1 && selectedSwipe !== undefined; | 11694 | const canDeleteSwipe = power_user.confirm_message_delete && !fromSlashCommand && !message.is_user && swipesArray.length > 1 && this_edit_mes_id === chat.length - 1 && selectedSwipe !== undefined; |
| 11690 | await deleteMessage(Number(this_edit_mes_id), canDeleteSwipe ? selectedSwipe : undefined, power_user.confirm_message_delete && fromSlashCommand !== true); | 11695 | await deleteMessage(Number(this_edit_mes_id), canDeleteSwipe ? selectedSwipe : undefined, power_user.confirm_message_delete && fromSlashCommand !== true); |
| 11691 | }); | 11696 | }); |
| @@ -12102,7 +12107,7 @@ jQuery(async function () { | |||
| 12102 | }); | 12107 | }); |
| 12103 | 12108 | ||
| 12104 | // Remember the chat currently selected, so we can reload it after the replacement | 12109 | // Remember the chat currently selected, so we can reload it after the replacement |
| 12105 | const currentChatFile = characters[this_chid]['chat']; | 12110 | const currentChatFile = characters[this_chid].chat; |
| 12106 | async function postReplace() { | 12111 | async function postReplace() { |
| 12107 | await openCharacterChat(currentChatFile); | 12112 | await openCharacterChat(currentChatFile); |
| 12108 | } | 12113 | } |
| @@ -996,7 +996,7 @@ export function initRossMods() { | |||
| 996 | } | 996 | } |
| 997 | 997 | ||
| 998 | //Enter to send when send_textarea in focus | 998 | //Enter to send when send_textarea in focus |
| 999 | if (document.activeElement == hotkeyTargets['send_textarea']) { | 999 | if (document.activeElement == hotkeyTargets.send_textarea) { |
| 1000 | const sendOnEnter = shouldSendOnEnter(); | 1000 | const sendOnEnter = shouldSendOnEnter(); |
| 1001 | if (!event.isComposing && !event.shiftKey && !event.ctrlKey && !event.altKey && event.key == 'Enter' && sendOnEnter) { | 1001 | if (!event.isComposing && !event.shiftKey && !event.ctrlKey && !event.altKey && event.key == 'Enter' && sendOnEnter) { |
| 1002 | event.preventDefault(); | 1002 | event.preventDefault(); |
| @@ -1004,7 +1004,7 @@ export function initRossMods() { | |||
| 1004 | return; | 1004 | return; |
| 1005 | } | 1005 | } |
| 1006 | } | 1006 | } |
| 1007 | if (document.activeElement == hotkeyTargets['dialogue_popup_input'] && !isMobile()) { | 1007 | if (document.activeElement == hotkeyTargets.dialogue_popup_input && !isMobile()) { |
| 1008 | if (!event.shiftKey && !event.ctrlKey && event.key == 'Enter') { | 1008 | if (!event.shiftKey && !event.ctrlKey && event.key == 'Enter') { |
| 1009 | event.preventDefault(); | 1009 | event.preventDefault(); |
| 1010 | $('#dialogue_popup_ok').trigger('click'); | 1010 | $('#dialogue_popup_ok').trigger('click'); |
| @@ -1139,7 +1139,7 @@ export function initRossMods() { | |||
| 1139 | 1139 | ||
| 1140 | if (event.ctrlKey && event.key == 'ArrowUp') { //edits last USER message if chatbar is empty and focused | 1140 | if (event.ctrlKey && event.key == 'ArrowUp') { //edits last USER message if chatbar is empty and focused |
| 1141 | if ( | 1141 | if ( |
| 1142 | hotkeyTargets['send_textarea'].value === '' && | 1142 | hotkeyTargets.send_textarea.value === '' && |
| 1143 | chatbarInFocus === true && | 1143 | chatbarInFocus === true && |
| 1144 | ($('.swipe_right:last').css('display') === 'flex' || $('.last_mes').attr('is_system') === 'true') && | 1144 | ($('.swipe_right:last').css('display') === 'flex' || $('.last_mes').attr('is_system') === 'true') && |
| 1145 | $('#character_popup').css('display') === 'none' && | 1145 | $('#character_popup').css('display') === 'none' && |
| @@ -1158,7 +1158,7 @@ export function initRossMods() { | |||
| 1158 | if (event.key == 'ArrowUp') { //edits last message if chatbar is empty and focused | 1158 | if (event.key == 'ArrowUp') { //edits last message if chatbar is empty and focused |
| 1159 | console.log('got uparrow input'); | 1159 | console.log('got uparrow input'); |
| 1160 | if ( | 1160 | if ( |
| 1161 | hotkeyTargets['send_textarea'].value === '' && | 1161 | hotkeyTargets.send_textarea.value === '' && |
| 1162 | chatbarInFocus === true && | 1162 | chatbarInFocus === true && |
| 1163 | //$('.swipe_right:last').css('display') === 'flex' && | 1163 | //$('.swipe_right:last').css('display') === 'flex' && |
| 1164 | $('.last_mes .mes_buttons').is(':visible') && | 1164 | $('.last_mes .mes_buttons').is(':visible') && |
| @@ -103,8 +103,8 @@ async function getBookmarkName({ isReplace = false, forceName = null } = {}) { | |||
| 103 | 103 | ||
| 104 | function getMainChatName() { | 104 | function getMainChatName() { |
| 105 | if (chat_metadata) { | 105 | if (chat_metadata) { |
| 106 | if (chat_metadata['main_chat']) { | 106 | if (chat_metadata.main_chat) { |
| 107 | return chat_metadata['main_chat']; | 107 | return chat_metadata.main_chat; |
| 108 | } | 108 | } |
| 109 | // groups didn't support bookmarks before chat metadata was introduced | 109 | // groups didn't support bookmarks before chat metadata was introduced |
| 110 | else if (selected_group) { | 110 | else if (selected_group) { |
| @@ -112,8 +112,8 @@ function getMainChatName() { | |||
| 112 | } | 112 | } |
| 113 | else if (characters[this_chid].chat && characters[this_chid].chat.includes(bookmarkNameToken)) { | 113 | else if (characters[this_chid].chat && characters[this_chid].chat.includes(bookmarkNameToken)) { |
| 114 | const tokenIndex = characters[this_chid].chat.lastIndexOf(bookmarkNameToken); | 114 | const tokenIndex = characters[this_chid].chat.lastIndexOf(bookmarkNameToken); |
| 115 | chat_metadata['main_chat'] = characters[this_chid].chat.substring(0, tokenIndex).trim(); | 115 | chat_metadata.main_chat = characters[this_chid].chat.substring(0, tokenIndex).trim(); |
| 116 | return chat_metadata['main_chat']; | 116 | return chat_metadata.main_chat; |
| 117 | } | 117 | } |
| 118 | } | 118 | } |
| 119 | return null; | 119 | return null; |
| @@ -127,7 +127,7 @@ export function showBookmarksButtons() { | |||
| 127 | $('#option_convert_to_group').show(); | 127 | $('#option_convert_to_group').show(); |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | if (chat_metadata['main_chat']) { | 130 | if (chat_metadata.main_chat) { |
| 131 | // In bookmark chat | 131 | // In bookmark chat |
| 132 | $('#option_back_to_main').show(); | 132 | $('#option_back_to_main').show(); |
| 133 | $('#option_new_bookmark').show(); | 133 | $('#option_new_bookmark').show(); |
| @@ -184,10 +184,10 @@ export async function createBranch(mesId) { | |||
| 184 | if (typeof lastMes.extra !== 'object') { | 184 | if (typeof lastMes.extra !== 'object') { |
| 185 | lastMes.extra = {}; | 185 | lastMes.extra = {}; |
| 186 | } | 186 | } |
| 187 | if (typeof lastMes.extra['branches'] !== 'object') { | 187 | if (typeof lastMes.extra.branches !== 'object') { |
| 188 | lastMes.extra['branches'] = []; | 188 | lastMes.extra.branches = []; |
| 189 | } | 189 | } |
| 190 | lastMes.extra['branches'].push(name); | 190 | lastMes.extra.branches.push(name); |
| 191 | return name; | 191 | return name; |
| 192 | } | 192 | } |
| 193 | 193 | ||
| @@ -236,7 +236,7 @@ export async function createNewBookmark(mesId, { forceName = null } = {}) { | |||
| 236 | await saveChat({ chatName: name, withMetadata: newMetadata, mesId }); | 236 | await saveChat({ chatName: name, withMetadata: newMetadata, mesId }); |
| 237 | } | 237 | } |
| 238 | 238 | ||
| 239 | lastMes.extra['bookmark_link'] = name; | 239 | lastMes.extra.bookmark_link = name; |
| 240 | 240 | ||
| 241 | const mes = $(`.mes[mesid="${mesId}"]`); | 241 | const mes = $(`.mes[mesid="${mesId}"]`); |
| 242 | updateBookmarkDisplay(mes, name); | 242 | updateBookmarkDisplay(mes, name); |
| @@ -42,13 +42,13 @@ function setCharCfg(tempValue, setting) { | |||
| 42 | 42 | ||
| 43 | switch (setting) { | 43 | switch (setting) { |
| 44 | case settingType.guidance_scale: | 44 | case settingType.guidance_scale: |
| 45 | tempCharaCfg['guidance_scale'] = Number(tempValue); | 45 | tempCharaCfg.guidance_scale = Number(tempValue); |
| 46 | break; | 46 | break; |
| 47 | case settingType.negative_prompt: | 47 | case settingType.negative_prompt: |
| 48 | tempCharaCfg['negative_prompt'] = tempValue; | 48 | tempCharaCfg.negative_prompt = tempValue; |
| 49 | break; | 49 | break; |
| 50 | case settingType.positive_prompt: | 50 | case settingType.positive_prompt: |
| 51 | tempCharaCfg['positive_prompt'] = tempValue; | 51 | tempCharaCfg.positive_prompt = tempValue; |
| 52 | break; | 52 | break; |
| 53 | default: | 53 | default: |
| 54 | return false; | 54 | return false; |
| @@ -239,31 +239,31 @@ function migrateSettings() { | |||
| 239 | 239 | ||
| 240 | if (power_user.guidance_scale) { | 240 | if (power_user.guidance_scale) { |
| 241 | extension_settings.cfg.global.guidance_scale = power_user.guidance_scale; | 241 | extension_settings.cfg.global.guidance_scale = power_user.guidance_scale; |
| 242 | delete power_user['guidance_scale']; | 242 | delete power_user.guidance_scale; |
| 243 | performSettingsSave = true; | 243 | performSettingsSave = true; |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | if (power_user.negative_prompt) { | 246 | if (power_user.negative_prompt) { |
| 247 | extension_settings.cfg.global.negative_prompt = power_user.negative_prompt; | 247 | extension_settings.cfg.global.negative_prompt = power_user.negative_prompt; |
| 248 | delete power_user['negative_prompt']; | 248 | delete power_user.negative_prompt; |
| 249 | performSettingsSave = true; | 249 | performSettingsSave = true; |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | if (chat_metadata['cfg_negative_combine']) { | 252 | if (chat_metadata.cfg_negative_combine) { |
| 253 | chat_metadata[metadataKeys.prompt_combine] = chat_metadata['cfg_negative_combine']; | 253 | chat_metadata[metadataKeys.prompt_combine] = chat_metadata.cfg_negative_combine; |
| 254 | chat_metadata['cfg_negative_combine'] = undefined; | 254 | chat_metadata.cfg_negative_combine = undefined; |
| 255 | performMetaSave = true; | 255 | performMetaSave = true; |
| 256 | } | 256 | } |
| 257 | 257 | ||
| 258 | if (chat_metadata['cfg_negative_insertion_depth']) { | 258 | if (chat_metadata.cfg_negative_insertion_depth) { |
| 259 | chat_metadata[metadataKeys.prompt_insertion_depth] = chat_metadata['cfg_negative_insertion_depth']; | 259 | chat_metadata[metadataKeys.prompt_insertion_depth] = chat_metadata.cfg_negative_insertion_depth; |
| 260 | chat_metadata['cfg_negative_insertion_depth'] = undefined; | 260 | chat_metadata.cfg_negative_insertion_depth = undefined; |
| 261 | performMetaSave = true; | 261 | performMetaSave = true; |
| 262 | } | 262 | } |
| 263 | 263 | ||
| 264 | if (chat_metadata['cfg_negative_separator']) { | 264 | if (chat_metadata.cfg_negative_separator) { |
| 265 | chat_metadata[metadataKeys.prompt_separator] = chat_metadata['cfg_negative_separator']; | 265 | chat_metadata[metadataKeys.prompt_separator] = chat_metadata.cfg_negative_separator; |
| 266 | chat_metadata['cfg_negative_separator'] = undefined; | 266 | chat_metadata.cfg_negative_separator = undefined; |
| 267 | performMetaSave = true; | 267 | performMetaSave = true; |
| 268 | } | 268 | } |
| 269 | 269 | ||
| @@ -148,8 +148,8 @@ export async function bindModelTemplates(power_user, online_status) { | |||
| 148 | ?? power_user.model_templates_mappings[chatTemplateHash] | 148 | ?? power_user.model_templates_mappings[chatTemplateHash] |
| 149 | ?? {}; | 149 | ?? {}; |
| 150 | const bindingsMatch = bindModelTemplates | 150 | const bindingsMatch = bindModelTemplates |
| 151 | && power_user.context.preset == bindModelTemplates['context'] | 151 | && power_user.context.preset == bindModelTemplates.context |
| 152 | && (!power_user.instruct.enabled || power_user.instruct.preset === bindModelTemplates['instruct']); | 152 | && (!power_user.instruct.enabled || power_user.instruct.preset === bindModelTemplates.instruct); |
| 153 | 153 | ||
| 154 | const bound = []; | 154 | const bound = []; |
| 155 | 155 | ||
| @@ -160,21 +160,21 @@ export async function bindModelTemplates(power_user, online_status) { | |||
| 160 | toastr.info(t`Context preset for ${online_status} will use defaults when loaded the next time.`); | 160 | toastr.info(t`Context preset for ${online_status} will use defaults when loaded the next time.`); |
| 161 | } else { | 161 | } else { |
| 162 | if (power_user.context_derived) { | 162 | if (power_user.context_derived) { |
| 163 | if (power_user.context.preset !== bindModelTemplates['context']) { | 163 | if (power_user.context.preset !== bindModelTemplates.context) { |
| 164 | bound.push(`${power_user.context.preset} context preset`); | 164 | bound.push(`${power_user.context.preset} context preset`); |
| 165 | // toastr.info(`Bound ${power_user.context.preset} preset to currently loaded model and all models that share its chat template.`); | 165 | // toastr.info(`Bound ${power_user.context.preset} preset to currently loaded model and all models that share its chat template.`); |
| 166 | 166 | ||
| 167 | // map current preset to current chat template hash | 167 | // map current preset to current chat template hash |
| 168 | bindModelTemplates['context'] = power_user.context.preset; | 168 | bindModelTemplates.context = power_user.context.preset; |
| 169 | } | 169 | } |
| 170 | } else { | 170 | } else { |
| 171 | toastr.warning(t`Note: Context derivation is disabled. Not including context preset.`); | 171 | toastr.warning(t`Note: Context derivation is disabled. Not including context preset.`); |
| 172 | } | 172 | } |
| 173 | if (power_user.instruct.enabled) { | 173 | if (power_user.instruct.enabled) { |
| 174 | if (power_user.instruct_derived) { | 174 | if (power_user.instruct_derived) { |
| 175 | if (power_user.instruct.preset !== bindModelTemplates['instruct']) { | 175 | if (power_user.instruct.preset !== bindModelTemplates.instruct) { |
| 176 | bound.push(`${power_user.instruct.preset} instruct preset`); | 176 | bound.push(`${power_user.instruct.preset} instruct preset`); |
| 177 | bindModelTemplates['instruct'] = power_user.instruct.preset; | 177 | bindModelTemplates.instruct = power_user.instruct.preset; |
| 178 | } | 178 | } |
| 179 | } else { | 179 | } else { |
| 180 | toastr.warning(t`Note: Instruct derivation is disabled. Not including instruct preset.`); | 180 | toastr.warning(t`Note: Instruct derivation is disabled. Not including instruct preset.`); |
| @@ -685,7 +685,7 @@ export function formatCreatorNotes(text, avatarId) { | |||
| 685 | const preference = new StylesPreference(avatarId); | 685 | const preference = new StylesPreference(avatarId); |
| 686 | const sanitizeStyles = !preference.get(); | 686 | const sanitizeStyles = !preference.get(); |
| 687 | const decodeStyleParam = { prefix: sanitizeStyles ? '#creator_notes_spoiler ' : '' }; | 687 | const decodeStyleParam = { prefix: sanitizeStyles ? '#creator_notes_spoiler ' : '' }; |
| 688 | /** @type {import('dompurify').Config & { MESSAGE_SANITIZE: boolean }} */ | 688 | /** @type {import('dompurify').Config} */ |
| 689 | const config = { | 689 | const config = { |
| 690 | RETURN_DOM: false, | 690 | RETURN_DOM: false, |
| 691 | RETURN_DOM_FRAGMENT: false, | 691 | RETURN_DOM_FRAGMENT: false, |
| @@ -1911,13 +1911,13 @@ export function addDOMPurifyHooks() { | |||
| 1911 | }); | 1911 | }); |
| 1912 | 1912 | ||
| 1913 | DOMPurify.addHook('uponSanitizeAttribute', (node, data, config) => { | 1913 | DOMPurify.addHook('uponSanitizeAttribute', (node, data, config) => { |
| 1914 | if (!config['MESSAGE_SANITIZE']) { | 1914 | if (!config.MESSAGE_SANITIZE) { |
| 1915 | return; | 1915 | return; |
| 1916 | } | 1916 | } |
| 1917 | 1917 | ||
| 1918 | /* Retain the classes on UI elements of messages that interact with the main UI */ | 1918 | /* Retain the classes on UI elements of messages that interact with the main UI */ |
| 1919 | const permittedNodeTypes = ['BUTTON', 'DIV']; | 1919 | const permittedNodeTypes = ['BUTTON', 'DIV']; |
| 1920 | if (config['MESSAGE_ALLOW_SYSTEM_UI'] && node.classList.contains('menu_button') && permittedNodeTypes.includes(node.nodeName)) { | 1920 | if (config.MESSAGE_ALLOW_SYSTEM_UI && node.classList.contains('menu_button') && permittedNodeTypes.includes(node.nodeName)) { |
| 1921 | return; | 1921 | return; |
| 1922 | } | 1922 | } |
| 1923 | 1923 | ||
| @@ -1938,7 +1938,7 @@ export function addDOMPurifyHooks() { | |||
| 1938 | }); | 1938 | }); |
| 1939 | 1939 | ||
| 1940 | DOMPurify.addHook('uponSanitizeElement', (node, _, config) => { | 1940 | DOMPurify.addHook('uponSanitizeElement', (node, _, config) => { |
| 1941 | if (!config['MESSAGE_SANITIZE']) { | 1941 | if (!config.MESSAGE_SANITIZE) { |
| 1942 | return; | 1942 | return; |
| 1943 | } | 1943 | } |
| 1944 | 1944 | ||
| @@ -103,10 +103,10 @@ async function downloadAssetsList(url) { | |||
| 103 | 103 | ||
| 104 | for (const i of json) { | 104 | for (const i of json) { |
| 105 | //console.log(DEBUG_PREFIX,i) | 105 | //console.log(DEBUG_PREFIX,i) |
| 106 | if (availableAssets[i['type']] === undefined) | 106 | if (availableAssets[i.type] === undefined) |
| 107 | availableAssets[i['type']] = []; | 107 | availableAssets[i.type] = []; |
| 108 | 108 | ||
| 109 | availableAssets[i['type']].push(i); | 109 | availableAssets[i.type].push(i); |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | console.debug(DEBUG_PREFIX, 'Updated available assets to', availableAssets); | 112 | console.debug(DEBUG_PREFIX, 'Updated available assets to', availableAssets); |
| @@ -139,7 +139,7 @@ async function downloadAssetsList(url) { | |||
| 139 | assetTypeMenu.append(await renderExtensionTemplateAsync('assets', 'installation')); | 139 | assetTypeMenu.append(await renderExtensionTemplateAsync('assets', 'installation')); |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | for (const asset of availableAssets[assetType].sort((a, b) => a?.name && b?.name && a['name'].localeCompare(b['name']))) { | 142 | for (const asset of availableAssets[assetType].sort((a, b) => a?.name && b?.name && a.name.localeCompare(b.name))) { |
| 143 | const i = availableAssets[assetType].indexOf(asset); | 143 | const i = availableAssets[assetType].indexOf(asset); |
| 144 | const elemId = `assets_install_${assetType}_${i}`; | 144 | const elemId = `assets_install_${assetType}_${i}`; |
| 145 | let element = $('<div />', { id: elemId, class: 'asset-download-button right_menu_button' }); | 145 | let element = $('<div />', { id: elemId, class: 'asset-download-button right_menu_button' }); |
| @@ -149,13 +149,13 @@ async function downloadAssetsList(url) { | |||
| 149 | //if (DEBUG_TONY_SAMA_FORK_MODE) | 149 | //if (DEBUG_TONY_SAMA_FORK_MODE) |
| 150 | // asset["url"] = asset["url"].replace("https://github.com/SillyTavern/","https://github.com/Tony-sama/"); // DBG | 150 | // asset["url"] = asset["url"].replace("https://github.com/SillyTavern/","https://github.com/Tony-sama/"); // DBG |
| 151 | 151 | ||
| 152 | console.debug(DEBUG_PREFIX, 'Checking asset', asset['id'], asset['url']); | 152 | console.debug(DEBUG_PREFIX, 'Checking asset', asset.id, asset.url); |
| 153 | 153 | ||
| 154 | const assetInstall = async function () { | 154 | const assetInstall = async function () { |
| 155 | element.off('click'); | 155 | element.off('click'); |
| 156 | label.removeClass('fa-download'); | 156 | label.removeClass('fa-download'); |
| 157 | this.classList.add('asset-download-button-loading'); | 157 | this.classList.add('asset-download-button-loading'); |
| 158 | await installAsset(asset['url'], assetType, asset['id']); | 158 | await installAsset(asset.url, assetType, asset.id); |
| 159 | label.addClass('fa-check'); | 159 | label.addClass('fa-check'); |
| 160 | this.classList.remove('asset-download-button-loading'); | 160 | this.classList.remove('asset-download-button-loading'); |
| 161 | element.on('click', assetDelete); | 161 | element.on('click', assetDelete); |
| @@ -173,11 +173,11 @@ async function downloadAssetsList(url) { | |||
| 173 | const assetDelete = async function () { | 173 | const assetDelete = async function () { |
| 174 | if (assetType === 'character') { | 174 | if (assetType === 'character') { |
| 175 | toastr.error('Go to the characters menu to delete a character.', 'Character deletion not supported'); | 175 | toastr.error('Go to the characters menu to delete a character.', 'Character deletion not supported'); |
| 176 | await executeSlashCommandsWithOptions(`/go ${asset['id']}`); | 176 | await executeSlashCommandsWithOptions(`/go ${asset.id}`); |
| 177 | return; | 177 | return; |
| 178 | } | 178 | } |
| 179 | element.off('click'); | 179 | element.off('click'); |
| 180 | await deleteAsset(assetType, asset['id']); | 180 | await deleteAsset(assetType, asset.id); |
| 181 | label.removeClass('fa-check'); | 181 | label.removeClass('fa-check'); |
| 182 | label.removeClass('redOverlayGlow'); | 182 | label.removeClass('redOverlayGlow'); |
| 183 | label.removeClass('fa-trash'); | 183 | label.removeClass('fa-trash'); |
| @@ -186,7 +186,7 @@ async function downloadAssetsList(url) { | |||
| 186 | element.on('click', assetInstall); | 186 | element.on('click', assetInstall); |
| 187 | }; | 187 | }; |
| 188 | 188 | ||
| 189 | if (isAssetInstalled(assetType, asset['id'])) { | 189 | if (isAssetInstalled(assetType, asset.id)) { |
| 190 | console.debug(DEBUG_PREFIX, 'installed, checked'); | 190 | console.debug(DEBUG_PREFIX, 'installed, checked'); |
| 191 | label.toggleClass('fa-download'); | 191 | label.toggleClass('fa-download'); |
| 192 | label.toggleClass('fa-check'); | 192 | label.toggleClass('fa-check'); |
| @@ -207,14 +207,14 @@ async function downloadAssetsList(url) { | |||
| 207 | element.on('click', assetInstall); | 207 | element.on('click', assetInstall); |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | console.debug(DEBUG_PREFIX, 'Created element for ', asset['id']); | 210 | console.debug(DEBUG_PREFIX, 'Created element for ', asset.id); |
| 211 | 211 | ||
| 212 | const displayName = DOMPurify.sanitize(asset['name'] || asset['id']); | 212 | const displayName = DOMPurify.sanitize(asset.name || asset.id); |
| 213 | const description = DOMPurify.sanitize(asset['description'] || ''); | 213 | const description = DOMPurify.sanitize(asset.description || ''); |
| 214 | const url = isValidUrl(asset['url']) ? asset['url'] : ''; | 214 | const url = isValidUrl(asset.url) ? asset.url : ''; |
| 215 | const title = assetType === 'extension' ? t`Extension repo/guide:` + ` ${url}` : t`Preview in browser`; | 215 | const title = assetType === 'extension' ? t`Extension repo/guide:` + ` ${url}` : t`Preview in browser`; |
| 216 | const previewIcon = (assetType === 'extension' || assetType === 'character') ? 'fa-arrow-up-right-from-square' : 'fa-headphones-simple'; | 216 | const previewIcon = (assetType === 'extension' || assetType === 'character') ? 'fa-arrow-up-right-from-square' : 'fa-headphones-simple'; |
| 217 | const toolTag = assetType === 'extension' && asset['tool']; | 217 | const toolTag = assetType === 'extension' && asset.tool; |
| 218 | const author = url && assetType === 'extension' ? getAuthorFromUrl(url) : EMPTY_AUTHOR; | 218 | const author = url && assetType === 'extension' ? getAuthorFromUrl(url) : EMPTY_AUTHOR; |
| 219 | 219 | ||
| 220 | const assetBlock = $('<i></i>') | 220 | const assetBlock = $('<i></i>') |
| @@ -246,7 +246,7 @@ async function downloadAssetsList(url) { | |||
| 246 | if (asset.highlight) { | 246 | if (asset.highlight) { |
| 247 | assetBlock.find('.asset-name').append('<i class="fa-solid fa-sm fa-trophy"></i>'); | 247 | assetBlock.find('.asset-name').append('<i class="fa-solid fa-sm fa-trophy"></i>'); |
| 248 | } | 248 | } |
| 249 | assetBlock.find('.asset-name').prepend(`<div class="avatar"><img src="${asset['url']}" alt="${displayName}"></div>`); | 249 | assetBlock.find('.asset-name').prepend(`<div class="avatar"><img src="${asset.url}" alt="${displayName}"></div>`); |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | assetBlock.addClass('asset-block'); | 252 | assetBlock.addClass('asset-block'); |
| @@ -204,7 +204,7 @@ async function sendCaptionedMessage(caption, image, mimeType) { | |||
| 204 | inline_image: !!extension_settings.caption.show_in_chat, | 204 | inline_image: !!extension_settings.caption.show_in_chat, |
| 205 | }, | 205 | }, |
| 206 | }; | 206 | }; |
| 207 | chat_metadata['tainted'] = true; | 207 | chat_metadata.tainted = true; |
| 208 | context.chat.push(message); | 208 | context.chat.push(message); |
| 209 | const messageId = context.chat.length - 1; | 209 | const messageId = context.chat.length - 1; |
| 210 | await eventSource.emit(event_types.MESSAGE_SENT, messageId); | 210 | await eventSource.emit(event_types.MESSAGE_SENT, messageId); |
| @@ -456,7 +456,7 @@ async function onChatEvent() { | |||
| 456 | .catch(console.error) | 456 | .catch(console.error) |
| 457 | .finally(() => { | 457 | .finally(() => { |
| 458 | lastMessageId = context.chat?.length ?? null; | 458 | lastMessageId = context.chat?.length ?? null; |
| 459 | lastMessageHash = getStringHash((context.chat.length && context.chat[context.chat.length - 1]['mes']) ?? ''); | 459 | lastMessageHash = getStringHash((context.chat.length && context.chat[context.chat.length - 1].mes) ?? ''); |
| 460 | }); | 460 | }); |
| 461 | } | 461 | } |
| 462 | 462 | ||
| @@ -185,7 +185,7 @@ const init = async () => { | |||
| 185 | buttons.show(); | 185 | buttons.show(); |
| 186 | settings.onSave = ()=>buttons.refresh(); | 186 | settings.onSave = ()=>buttons.refresh(); |
| 187 | 187 | ||
| 188 | window['executeQuickReplyByName'] = async(name, args = {}, options = {}) => { | 188 | globalThis.executeQuickReplyByName = async(name, args = {}, options = {}) => { |
| 189 | let qr = [ | 189 | let qr = [ |
| 190 | ...settings.config.setList, | 190 | ...settings.config.setList, |
| 191 | ...(settings.chatConfig?.setList ?? []), | 191 | ...(settings.chatConfig?.setList ?? []), |
| @@ -77,7 +77,7 @@ export class SlashCommandHandler { | |||
| 77 | }, | 77 | }, |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
| 80 | window['qrEnumProviderExecutables'] = localEnumProviders.qrExecutables; | 80 | globalThis.qrEnumProviderExecutables = localEnumProviders.qrExecutables; |
| 81 | 81 | ||
| 82 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'qr', | 82 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'qr', |
| 83 | callback: (_, value) => this.executeQuickReplyByIndex(Number(value)), | 83 | callback: (_, value) => this.executeQuickReplyByIndex(Number(value)), |
| @@ -426,7 +426,7 @@ function processTriggers(chat, _, abort, type) { | |||
| 426 | } | 426 | } |
| 427 | } | 427 | } |
| 428 | 428 | ||
| 429 | window['SD_ProcessTriggers'] = processTriggers; | 429 | globalThis.SD_ProcessTriggers = processTriggers; |
| 430 | 430 | ||
| 431 | function getSdRequestBody() { | 431 | function getSdRequestBody() { |
| 432 | switch (extension_settings.sd.source) { | 432 | switch (extension_settings.sd.source) { |
| @@ -207,13 +207,13 @@ class CoquiTtsProvider { | |||
| 207 | this.settings.customVoices = {}; | 207 | this.settings.customVoices = {}; |
| 208 | for (let voiceName in this.settings.voiceMapDict) { | 208 | for (let voiceName in this.settings.voiceMapDict) { |
| 209 | const voiceId = this.settings.voiceMapDict[voiceName]; | 209 | const voiceId = this.settings.voiceMapDict[voiceName]; |
| 210 | this.settings.customVoices[voiceName] = voiceId['model_id']; | 210 | this.settings.customVoices[voiceName] = voiceId.model_id; |
| 211 | 211 | ||
| 212 | if (voiceId['model_language'] != null) | 212 | if (voiceId.model_language != null) |
| 213 | this.settings.customVoices[voiceName] += '[' + voiceId['model_language'] + ']'; | 213 | this.settings.customVoices[voiceName] += '[' + voiceId.model_language + ']'; |
| 214 | 214 | ||
| 215 | if (voiceId['model_speaker'] != null) | 215 | if (voiceId.model_speaker != null) |
| 216 | this.settings.customVoices[voiceName] += '[' + voiceId['model_speaker'] + ']'; | 216 | this.settings.customVoices[voiceName] += '[' + voiceId.model_speaker + ']'; |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | // Update UI select list with voices | 219 | // Update UI select list with voices |
| @@ -493,8 +493,8 @@ class CoquiTtsProvider { | |||
| 493 | .append('<option value="none">Select language</option>') | 493 | .append('<option value="none">Select language</option>') |
| 494 | .val('none'); | 494 | .val('none'); |
| 495 | 495 | ||
| 496 | for (let i = 0; i < model_settings['languages'].length; i++) { | 496 | for (let i = 0; i < model_settings.languages.length; i++) { |
| 497 | const language_label = JSON.stringify(model_settings['languages'][i]).replaceAll('"', ''); | 497 | const language_label = JSON.stringify(model_settings.languages[i]).replaceAll('"', ''); |
| 498 | $('#coqui_api_model_settings_language').append(new Option(language_label, i)); | 498 | $('#coqui_api_model_settings_language').append(new Option(language_label, i)); |
| 499 | } | 499 | } |
| 500 | } | 500 | } |
| @@ -512,8 +512,8 @@ class CoquiTtsProvider { | |||
| 512 | .append('<option value="none">Select speaker</option>') | 512 | .append('<option value="none">Select speaker</option>') |
| 513 | .val('none'); | 513 | .val('none'); |
| 514 | 514 | ||
| 515 | for (let i = 0; i < model_settings['speakers'].length; i++) { | 515 | for (let i = 0; i < model_settings.speakers.length; i++) { |
| 516 | const speaker_label = JSON.stringify(model_settings['speakers'][i]).replaceAll('"', ''); | 516 | const speaker_label = JSON.stringify(model_settings.speakers[i]).replaceAll('"', ''); |
| 517 | $('#coqui_api_model_settings_speaker').append(new Option(speaker_label, i)); | 517 | $('#coqui_api_model_settings_speaker').append(new Option(speaker_label, i)); |
| 518 | } | 518 | } |
| 519 | } | 519 | } |
| @@ -525,7 +525,7 @@ class CoquiTtsProvider { | |||
| 525 | $('#coqui_api_model_install_status').show(); | 525 | $('#coqui_api_model_install_status').show(); |
| 526 | 526 | ||
| 527 | // Check if already installed and propose to do it otherwise | 527 | // Check if already installed and propose to do it otherwise |
| 528 | const model_id = modelDict[model_language][model_dataset][model_name]['id']; | 528 | const model_id = modelDict[model_language][model_dataset][model_name].id; |
| 529 | console.debug(DEBUG_PREFIX,'Check if model is already installed',model_id); | 529 | console.debug(DEBUG_PREFIX,'Check if model is already installed',model_id); |
| 530 | let result = await CoquiTtsProvider.checkmodel_state(model_id); | 530 | let result = await CoquiTtsProvider.checkmodel_state(model_id); |
| 531 | result = await result.json(); | 531 | result = await result.json(); |
| @@ -175,7 +175,7 @@ class CosyVoiceProvider { | |||
| 175 | }; | 175 | }; |
| 176 | 176 | ||
| 177 | if (streaming) { | 177 | if (streaming) { |
| 178 | params['streaming'] = 1; | 178 | params.streaming = 1; |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | const url = `${this.settings.provider_endpoint}/`; | 181 | const url = `${this.settings.provider_endpoint}/`; |
| @@ -126,16 +126,16 @@ class ElevenLabsTtsProvider { | |||
| 126 | this.settings = this.defaultSettings; | 126 | this.settings = this.defaultSettings; |
| 127 | 127 | ||
| 128 | // Migrate old settings | 128 | // Migrate old settings |
| 129 | if (settings['multilingual'] !== undefined) { | 129 | if (settings.multilingual !== undefined) { |
| 130 | settings.model = settings.multilingual ? 'eleven_multilingual_v1' : 'eleven_monolingual_v1'; | 130 | settings.model = settings.multilingual ? 'eleven_multilingual_v1' : 'eleven_monolingual_v1'; |
| 131 | delete settings['multilingual']; | 131 | delete settings.multilingual; |
| 132 | } | 132 | } |
| 133 | 133 | ||
| 134 | if (Object.hasOwn(settings, 'apiKey')) { | 134 | if (Object.hasOwn(settings, 'apiKey')) { |
| 135 | if (settings.apiKey && !secret_state[SECRET_KEYS.ELEVENLABS]){ | 135 | if (settings.apiKey && !secret_state[SECRET_KEYS.ELEVENLABS]){ |
| 136 | await writeSecret(SECRET_KEYS.ELEVENLABS, settings.apiKey); | 136 | await writeSecret(SECRET_KEYS.ELEVENLABS, settings.apiKey); |
| 137 | } | 137 | } |
| 138 | delete settings['apiKey']; | 138 | delete settings.apiKey; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | $('#elevenlabs_tts_key').toggleClass('success', !!secret_state[SECRET_KEYS.ELEVENLABS]); | 141 | $('#elevenlabs_tts_key').toggleClass('success', !!secret_state[SECRET_KEYS.ELEVENLABS]); |
| @@ -284,7 +284,7 @@ function debugTtsPlayback() { | |||
| 284 | }, | 284 | }, |
| 285 | )); | 285 | )); |
| 286 | } | 286 | } |
| 287 | window['debugTtsPlayback'] = debugTtsPlayback; | 287 | globalThis.debugTtsPlayback = debugTtsPlayback; |
| 288 | 288 | ||
| 289 | //##################// | 289 | //##################// |
| 290 | // Audio Control // | 290 | // Audio Control // |
| @@ -321,8 +321,8 @@ async function playAudioData(audioJob) { | |||
| 321 | const srcUrl = await getBase64Async(audioBlob); | 321 | const srcUrl = await getBase64Async(audioBlob); |
| 322 | 322 | ||
| 323 | // VRM lip sync | 323 | // VRM lip sync |
| 324 | if (extension_settings.vrm?.enabled && typeof window['vrmLipSync'] === 'function') { | 324 | if (extension_settings.vrm?.enabled && typeof globalThis.vrmLipSync === 'function') { |
| 325 | await window['vrmLipSync'](audioBlob, char); | 325 | await globalThis.vrmLipSync(audioBlob, char); |
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | audioElement.src = srcUrl; | 328 | audioElement.src = srcUrl; |
| @@ -339,7 +339,7 @@ async function playAudioData(audioJob) { | |||
| 339 | }); | 339 | }); |
| 340 | } | 340 | } |
| 341 | 341 | ||
| 342 | window['tts_preview'] = function (id) { | 342 | globalThis.tts_preview = function (id) { |
| 343 | const audio = document.getElementById(id); | 343 | const audio = document.getElementById(id); |
| 344 | 344 | ||
| 345 | if (audio instanceof HTMLAudioElement && !$(audio).data('disabled')) { | 345 | if (audio instanceof HTMLAudioElement && !$(audio).data('disabled')) { |
| @@ -474,8 +474,8 @@ function completeTtsJob() { | |||
| 474 | async function tts(text, voiceId, char, voiceMapKey = null) { | 474 | async function tts(text, voiceId, char, voiceMapKey = null) { |
| 475 | async function processResponse(response) { | 475 | async function processResponse(response) { |
| 476 | // RVC injection | 476 | // RVC injection |
| 477 | if (typeof window['rvcVoiceConversion'] === 'function' && extension_settings.rvc.enabled) | 477 | if (typeof globalThis.rvcVoiceConversion === 'function' && extension_settings.rvc.enabled) |
| 478 | response = await window['rvcVoiceConversion'](response, char, text); | 478 | response = await globalThis.rvcVoiceConversion(response, char, text); |
| 479 | 479 | ||
| 480 | await addAudioJob(response, char); | 480 | await addAudioJob(response, char); |
| 481 | } | 481 | } |
| @@ -806,7 +806,7 @@ async function playFullConversation() { | |||
| 806 | ttsJobQueue = chat; | 806 | ttsJobQueue = chat; |
| 807 | } | 807 | } |
| 808 | 808 | ||
| 809 | window['playFullConversation'] = playFullConversation; | 809 | globalThis.playFullConversation = playFullConversation; |
| 810 | 810 | ||
| 811 | //#############################// | 811 | //#############################// |
| 812 | // Extension UI and Settings // | 812 | // Extension UI and Settings // |
| @@ -746,7 +746,7 @@ function overlapChunks(chunk, index, chunks, overlapSize) { | |||
| 746 | return overlappedChunk; | 746 | return overlappedChunk; |
| 747 | } | 747 | } |
| 748 | 748 | ||
| 749 | window['vectors_rearrangeChat'] = rearrangeChat; | 749 | globalThis.vectors_rearrangeChat = rearrangeChat; |
| 750 | 750 | ||
| 751 | const onChatEvent = debounce(async () => await moduleWorker.update(), debounce_timeout.relaxed); | 751 | const onChatEvent = debounce(async () => await moduleWorker.update(), debounce_timeout.relaxed); |
| 752 | 752 | ||
| @@ -1620,7 +1620,7 @@ jQuery(async () => { | |||
| 1620 | } | 1620 | } |
| 1621 | 1621 | ||
| 1622 | // Migrate from old settings | 1622 | // Migrate from old settings |
| 1623 | if (settings['enabled']) { | 1623 | if (settings.enabled) { |
| 1624 | settings.enabled_chats = true; | 1624 | settings.enabled_chats = true; |
| 1625 | } | 1625 | } |
| 1626 | 1626 | ||
| @@ -274,8 +274,8 @@ export async function getGroupChat(groupId, reload = false) { | |||
| 274 | } | 274 | } |
| 275 | 275 | ||
| 276 | // Add integrity slug if missing | 276 | // Add integrity slug if missing |
| 277 | if (!metadata['integrity']) { | 277 | if (!metadata.integrity) { |
| 278 | metadata['integrity'] = uuidv4(); | 278 | metadata.integrity = uuidv4(); |
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | await loadItemizedPrompts(getCurrentChatId()); | 281 | await loadItemizedPrompts(getCurrentChatId()); |
| @@ -559,8 +559,8 @@ export function getGroupCharacterCardsLazy(groupId, characterId) { | |||
| 559 | return values.filter(x => x.length).join('\n'); | 559 | return values.filter(x => x.length).join('\n'); |
| 560 | } | 560 | } |
| 561 | 561 | ||
| 562 | const scenarioOverride = String(chat_metadata['scenario'] || ''); | 562 | const scenarioOverride = String(chat_metadata.scenario || ''); |
| 563 | const mesExamplesOverride = String(chat_metadata['mes_example'] || ''); | 563 | const mesExamplesOverride = String(chat_metadata.mes_example || ''); |
| 564 | 564 | ||
| 565 | return createLazyFields({ | 565 | return createLazyFields({ |
| 566 | description: () => collectField('Description', c => c.description), | 566 | description: () => collectField('Description', c => c.description), |
| @@ -593,16 +593,16 @@ async function getFirstCharacterMessage(character) { | |||
| 593 | } | 593 | } |
| 594 | 594 | ||
| 595 | const mes = {}; | 595 | const mes = {}; |
| 596 | mes['is_user'] = false; | 596 | mes.is_user = false; |
| 597 | mes['is_system'] = false; | 597 | mes.is_system = false; |
| 598 | mes['name'] = character.name; | 598 | mes.name = character.name; |
| 599 | mes['send_date'] = getMessageTimeStamp(); | 599 | mes.send_date = getMessageTimeStamp(); |
| 600 | mes['original_avatar'] = character.avatar; | 600 | mes.original_avatar = character.avatar; |
| 601 | mes['extra'] = { 'gen_id': Date.now() * Math.random() * 1000000 }; | 601 | mes.extra = { 'gen_id': Date.now() * Math.random() * 1000000 }; |
| 602 | mes['mes'] = messageText | 602 | mes.mes = messageText |
| 603 | ? substituteParams(messageText.trim(), { name2Override: character.name }) | 603 | ? substituteParams(messageText.trim(), { name2Override: character.name }) |
| 604 | : ''; | 604 | : ''; |
| 605 | mes['force_avatar'] = | 605 | mes.force_avatar = |
| 606 | character.avatar != 'none' | 606 | character.avatar != 'none' |
| 607 | ? getThumbnailUrl('avatar', character.avatar) | 607 | ? getThumbnailUrl('avatar', character.avatar) |
| 608 | : default_avatar; | 608 | : default_avatar; |
| @@ -628,7 +628,7 @@ async function saveGroupChat(groupId, shouldSaveGroup, force = false) { | |||
| 628 | return; | 628 | return; |
| 629 | } | 629 | } |
| 630 | const chatId = group.chat_id; | 630 | const chatId = group.chat_id; |
| 631 | group['date_last_chat'] = Date.now(); | 631 | group.date_last_chat = Date.now(); |
| 632 | /** @type {ChatHeader} */ | 632 | /** @type {ChatHeader} */ |
| 633 | const chatHeader = { | 633 | const chatHeader = { |
| 634 | chat_metadata: { ...chat_metadata }, | 634 | chat_metadata: { ...chat_metadata }, |
| @@ -2179,7 +2179,7 @@ export async function openGroupChat(groupId, chatId) { | |||
| 2179 | await clearChat(); | 2179 | await clearChat(); |
| 2180 | chat.length = 0; | 2180 | chat.length = 0; |
| 2181 | group.chat_id = chatId; | 2181 | group.chat_id = chatId; |
| 2182 | group['date_last_chat'] = Date.now(); | 2182 | group.date_last_chat = Date.now(); |
| 2183 | updateChatMetadata({}, true); | 2183 | updateChatMetadata({}, true); |
| 2184 | 2184 | ||
| 2185 | await editGroup(groupId, true, false); | 2185 | await editGroup(groupId, true, false); |
| @@ -205,11 +205,11 @@ export async function generateHorde(prompt, params, signal, reportProgress) { | |||
| 205 | delete params.prompt; | 205 | delete params.prompt; |
| 206 | 206 | ||
| 207 | // No idea what these do | 207 | // No idea what these do |
| 208 | params['n'] = 1; | 208 | params.n = 1; |
| 209 | params['frmtadsnsp'] = false; | 209 | params.frmtadsnsp = false; |
| 210 | params['frmtrmblln'] = false; | 210 | params.frmtrmblln = false; |
| 211 | params['frmtrmspch'] = false; | 211 | params.frmtrmspch = false; |
| 212 | params['frmttriminc'] = false; | 212 | params.frmttriminc = false; |
| 213 | 213 | ||
| 214 | const payload = { | 214 | const payload = { |
| 215 | 'prompt': prompt, | 215 | 'prompt': prompt, |
| @@ -258,8 +258,8 @@ function addLanguagesToDropdown() { | |||
| 258 | const uiLanguageSelects = $('#ui_language_select, #onboarding_ui_language_select'); | 258 | const uiLanguageSelects = $('#ui_language_select, #onboarding_ui_language_select'); |
| 259 | for (const langObj of langs) { // Set the value to the language code | 259 | for (const langObj of langs) { // Set the value to the language code |
| 260 | const option = document.createElement('option'); | 260 | const option = document.createElement('option'); |
| 261 | option.value = langObj['lang']; // Set the value to the language code | 261 | option.value = langObj.lang; // Set the value to the language code |
| 262 | option.innerText = langObj['display']; // Set the display text to the language name | 262 | option.innerText = langObj.display; // Set the display text to the language name |
| 263 | uiLanguageSelects.append(option); | 263 | uiLanguageSelects.append(option); |
| 264 | } | 264 | } |
| 265 | 265 | ||
| @@ -161,7 +161,7 @@ export async function loadInstructMode(data) { | |||
| 161 | */ | 161 | */ |
| 162 | export function updateBindModelTemplatesState() { | 162 | export function updateBindModelTemplatesState() { |
| 163 | const bindModelTemplates = power_user.model_templates_mappings[online_status] ?? power_user.model_templates_mappings[power_user.chat_template_hash]; | 163 | const bindModelTemplates = power_user.model_templates_mappings[online_status] ?? power_user.model_templates_mappings[power_user.chat_template_hash]; |
| 164 | const bindingsMatch = (bindModelTemplates && power_user.context.preset === bindModelTemplates['context'] && (!power_user.instruct.enabled || power_user.instruct.preset === bindModelTemplates['instruct'])) ?? false; | 164 | const bindingsMatch = (bindModelTemplates && power_user.context.preset === bindModelTemplates.context && (!power_user.instruct.enabled || power_user.instruct.preset === bindModelTemplates.instruct)) ?? false; |
| 165 | const currentState = $('#bind_model_templates').prop('checked'); | 165 | const currentState = $('#bind_model_templates').prop('checked'); |
| 166 | if (bindingsMatch === currentState) { | 166 | if (bindingsMatch === currentState) { |
| 167 | // No change needed | 167 | // No change needed |
| @@ -312,14 +312,14 @@ export class MacrosParser { | |||
| 312 | * @returns {number} The hashed chat id | 312 | * @returns {number} The hashed chat id |
| 313 | */ | 313 | */ |
| 314 | function getChatIdHash() { | 314 | function getChatIdHash() { |
| 315 | const cachedIdHash = chat_metadata['chat_id_hash']; | 315 | const cachedIdHash = chat_metadata.chat_id_hash; |
| 316 | 316 | ||
| 317 | // If chat_id_hash is not already set, calculate it | 317 | // If chat_id_hash is not already set, calculate it |
| 318 | if (!cachedIdHash) { | 318 | if (!cachedIdHash) { |
| 319 | // Use the main_chat if it's available, otherwise get the current chat ID | 319 | // Use the main_chat if it's available, otherwise get the current chat ID |
| 320 | const chatId = chat_metadata['main_chat'] ?? getCurrentChatId(); | 320 | const chatId = chat_metadata.main_chat ?? getCurrentChatId(); |
| 321 | const chatIdHash = getStringHash(chatId); | 321 | const chatIdHash = getStringHash(chatId); |
| 322 | chat_metadata['chat_id_hash'] = chatIdHash; | 322 | chat_metadata.chat_id_hash = chatIdHash; |
| 323 | return chatIdHash; | 323 | return chatIdHash; |
| 324 | } | 324 | } |
| 325 | 325 | ||
| @@ -361,7 +361,7 @@ export function getLastMessageId({ exclude_swipe_in_propress = true, filter = nu | |||
| 361 | * @returns {number|null} The ID of the first message in the context | 361 | * @returns {number|null} The ID of the first message in the context |
| 362 | */ | 362 | */ |
| 363 | function getFirstIncludedMessageId() { | 363 | function getFirstIncludedMessageId() { |
| 364 | return chat_metadata['lastInContextMessageId']; | 364 | return chat_metadata.lastInContextMessageId; |
| 365 | } | 365 | } |
| 366 | 366 | ||
| 367 | /** | 367 | /** |
| @@ -104,7 +104,7 @@ function getLastCharMessage() { | |||
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | function getFirstIncludedMessageId() { | 106 | function getFirstIncludedMessageId() { |
| 107 | const value = chat_metadata['lastInContextMessageId']; | 107 | const value = chat_metadata.lastInContextMessageId; |
| 108 | return typeof value === 'number' ? value : null; | 108 | return typeof value === 'number' ? value : null; |
| 109 | } | 109 | } |
| 110 | 110 | ||
| @@ -433,13 +433,13 @@ export function registerCoreMacros() { | |||
| 433 | } | 433 | } |
| 434 | 434 | ||
| 435 | function getChatIdHash() { | 435 | function getChatIdHash() { |
| 436 | const cachedIdHash = chat_metadata['chat_id_hash']; | 436 | const cachedIdHash = chat_metadata.chat_id_hash; |
| 437 | if (typeof cachedIdHash === 'number') { | 437 | if (typeof cachedIdHash === 'number') { |
| 438 | return cachedIdHash; | 438 | return cachedIdHash; |
| 439 | } | 439 | } |
| 440 | 440 | ||
| 441 | const chatId = chat_metadata['main_chat'] ?? getCurrentChatId(); | 441 | const chatId = chat_metadata.main_chat ?? getCurrentChatId(); |
| 442 | const chatIdHash = getStringHash(chatId); | 442 | const chatIdHash = getStringHash(chatId); |
| 443 | chat_metadata['chat_id_hash'] = chatIdHash; | 443 | chat_metadata.chat_id_hash = chatIdHash; |
| 444 | return chatIdHash; | 444 | return chatIdHash; |
| 445 | } | 445 | } |
| @@ -529,8 +529,8 @@ function setOpenAIMessages(chat) { | |||
| 529 | const currentModel = getChatCompletionModel(); | 529 | const currentModel = getChatCompletionModel(); |
| 530 | 530 | ||
| 531 | for (let i = chat.length - 1; i >= 0; i--) { | 531 | for (let i = chat.length - 1; i >= 0; i--) { |
| 532 | let role = chat[j]['is_user'] ? 'user' : 'assistant'; | 532 | let role = chat[j].is_user ? 'user' : 'assistant'; |
| 533 | let content = chat[j]['mes']; | 533 | let content = chat[j].mes; |
| 534 | 534 | ||
| 535 | // If this symbol flag is set, completely ignore the message. | 535 | // If this symbol flag is set, completely ignore the message. |
| 536 | // This can be used to hide messages without affecting the number of messages in the chat. | 536 | // This can be used to hide messages without affecting the number of messages in the chat. |
| @@ -567,7 +567,7 @@ function setOpenAIMessages(chat) { | |||
| 567 | // remove caret return (waste of tokens) | 567 | // remove caret return (waste of tokens) |
| 568 | content = content.replace(/\r/gm, ''); | 568 | content = content.replace(/\r/gm, ''); |
| 569 | 569 | ||
| 570 | const name = chat[j]['name']; | 570 | const name = chat[j].name; |
| 571 | const media = chat[j]?.extra?.media; | 571 | const media = chat[j]?.extra?.media; |
| 572 | const mediaDisplay = getMediaDisplay(chat[j]); | 572 | const mediaDisplay = getMediaDisplay(chat[j]); |
| 573 | const mediaIndex = getMediaIndex(chat[j]); | 573 | const mediaIndex = getMediaIndex(chat[j]); |
| @@ -2588,14 +2588,14 @@ export async function createGenerationParameters(settings, model, type, messages | |||
| 2588 | 2588 | ||
| 2589 | if (settings.reverse_proxy && proxySupportedSources.includes(settings.chat_completion_source)) { | 2589 | if (settings.reverse_proxy && proxySupportedSources.includes(settings.chat_completion_source)) { |
| 2590 | await validateReverseProxy(); | 2590 | await validateReverseProxy(); |
| 2591 | generate_data['reverse_proxy'] = settings.reverse_proxy; | 2591 | generate_data.reverse_proxy = settings.reverse_proxy; |
| 2592 | generate_data['proxy_password'] = settings.proxy_password; | 2592 | generate_data.proxy_password = settings.proxy_password; |
| 2593 | } | 2593 | } |
| 2594 | 2594 | ||
| 2595 | // Add logprobs request (max 5 per OpenAI docs) | 2595 | // Add logprobs request (max 5 per OpenAI docs) |
| 2596 | const useLogprobs = !!power_user.request_token_probabilities; | 2596 | const useLogprobs = !!power_user.request_token_probabilities; |
| 2597 | if (useLogprobs && logprobsSupportedSources.includes(settings.chat_completion_source)) { | 2597 | if (useLogprobs && logprobsSupportedSources.includes(settings.chat_completion_source)) { |
| 2598 | generate_data['logprobs'] = 5; | 2598 | generate_data.logprobs = 5; |
| 2599 | } | 2599 | } |
| 2600 | 2600 | ||
| 2601 | // Remove logit bias/logprobs/stop-strings if not supported by the model | 2601 | // Remove logit bias/logprobs/stop-strings if not supported by the model |
| @@ -2610,67 +2610,67 @@ export async function createGenerationParameters(settings, model, type, messages | |||
| 2610 | } | 2610 | } |
| 2611 | 2611 | ||
| 2612 | if (settings.chat_completion_source === chat_completion_sources.CLAUDE) { | 2612 | if (settings.chat_completion_source === chat_completion_sources.CLAUDE) { |
| 2613 | generate_data['top_k'] = Number(settings.top_k_openai); | 2613 | generate_data.top_k = Number(settings.top_k_openai); |
| 2614 | generate_data['use_sysprompt'] = settings.use_sysprompt; | 2614 | generate_data.use_sysprompt = settings.use_sysprompt; |
| 2615 | generate_data['stop'] = getCustomStoppingStrings(); // Claude shouldn't have limits on stop strings. | 2615 | generate_data.stop = getCustomStoppingStrings(); // Claude shouldn't have limits on stop strings. |
| 2616 | // Don't add a prefill on quiet gens (summarization) and when using continue prefill. | 2616 | // Don't add a prefill on quiet gens (summarization) and when using continue prefill. |
| 2617 | if (type !== 'quiet' && !(type === 'continue' && settings.continue_prefill)) { | 2617 | if (type !== 'quiet' && !(type === 'continue' && settings.continue_prefill)) { |
| 2618 | generate_data['assistant_prefill'] = type === 'impersonate' | 2618 | generate_data.assistant_prefill = type === 'impersonate' |
| 2619 | ? substituteParams(settings.assistant_impersonation) | 2619 | ? substituteParams(settings.assistant_impersonation) |
| 2620 | : substituteParams(settings.assistant_prefill); | 2620 | : substituteParams(settings.assistant_prefill); |
| 2621 | } | 2621 | } |
| 2622 | } | 2622 | } |
| 2623 | 2623 | ||
| 2624 | if (settings.chat_completion_source === chat_completion_sources.OPENROUTER) { | 2624 | if (settings.chat_completion_source === chat_completion_sources.OPENROUTER) { |
| 2625 | generate_data['top_k'] = Number(settings.top_k_openai); | 2625 | generate_data.top_k = Number(settings.top_k_openai); |
| 2626 | generate_data['min_p'] = Number(settings.min_p_openai); | 2626 | generate_data.min_p = Number(settings.min_p_openai); |
| 2627 | generate_data['repetition_penalty'] = Number(settings.repetition_penalty_openai); | 2627 | generate_data.repetition_penalty = Number(settings.repetition_penalty_openai); |
| 2628 | generate_data['top_a'] = Number(settings.top_a_openai); | 2628 | generate_data.top_a = Number(settings.top_a_openai); |
| 2629 | generate_data['use_fallback'] = settings.openrouter_use_fallback; | 2629 | generate_data.use_fallback = settings.openrouter_use_fallback; |
| 2630 | generate_data['provider'] = settings.openrouter_providers; | 2630 | generate_data.provider = settings.openrouter_providers; |
| 2631 | generate_data['allow_fallbacks'] = settings.openrouter_allow_fallbacks; | 2631 | generate_data.allow_fallbacks = settings.openrouter_allow_fallbacks; |
| 2632 | generate_data['middleout'] = settings.openrouter_middleout; | 2632 | generate_data.middleout = settings.openrouter_middleout; |
| 2633 | } | 2633 | } |
| 2634 | 2634 | ||
| 2635 | if ([chat_completion_sources.MAKERSUITE, chat_completion_sources.VERTEXAI].includes(settings.chat_completion_source)) { | 2635 | if ([chat_completion_sources.MAKERSUITE, chat_completion_sources.VERTEXAI].includes(settings.chat_completion_source)) { |
| 2636 | const stopStringsLimit = 5; | 2636 | const stopStringsLimit = 5; |
| 2637 | generate_data['top_k'] = Number(settings.top_k_openai); | 2637 | generate_data.top_k = Number(settings.top_k_openai); |
| 2638 | generate_data['stop'] = getCustomStoppingStrings(stopStringsLimit).slice(0, stopStringsLimit).filter(x => x.length >= 1 && x.length <= 16); | 2638 | generate_data.stop = getCustomStoppingStrings(stopStringsLimit).slice(0, stopStringsLimit).filter(x => x.length >= 1 && x.length <= 16); |
| 2639 | generate_data['use_sysprompt'] = settings.use_sysprompt; | 2639 | generate_data.use_sysprompt = settings.use_sysprompt; |
| 2640 | if (settings.chat_completion_source === chat_completion_sources.VERTEXAI) { | 2640 | if (settings.chat_completion_source === chat_completion_sources.VERTEXAI) { |
| 2641 | generate_data['vertexai_auth_mode'] = settings.vertexai_auth_mode; | 2641 | generate_data.vertexai_auth_mode = settings.vertexai_auth_mode; |
| 2642 | generate_data['vertexai_region'] = settings.vertexai_region; | 2642 | generate_data.vertexai_region = settings.vertexai_region; |
| 2643 | generate_data['vertexai_express_project_id'] = settings.vertexai_express_project_id; | 2643 | generate_data.vertexai_express_project_id = settings.vertexai_express_project_id; |
| 2644 | } | 2644 | } |
| 2645 | } | 2645 | } |
| 2646 | 2646 | ||
| 2647 | if (settings.chat_completion_source === chat_completion_sources.MISTRALAI) { | 2647 | if (settings.chat_completion_source === chat_completion_sources.MISTRALAI) { |
| 2648 | generate_data['safe_prompt'] = false; // already defaults to false, but just incase they change that in the future. | 2648 | generate_data.safe_prompt = false; // already defaults to false, but just incase they change that in the future. |
| 2649 | generate_data['stop'] = getCustomStoppingStrings(); // Mistral shouldn't have limits on stop strings. | 2649 | generate_data.stop = getCustomStoppingStrings(); // Mistral shouldn't have limits on stop strings. |
| 2650 | } | 2650 | } |
| 2651 | 2651 | ||
| 2652 | if (settings.chat_completion_source === chat_completion_sources.CUSTOM) { | 2652 | if (settings.chat_completion_source === chat_completion_sources.CUSTOM) { |
| 2653 | generate_data['custom_url'] = settings.custom_url; | 2653 | generate_data.custom_url = settings.custom_url; |
| 2654 | generate_data['custom_include_body'] = settings.custom_include_body; | 2654 | generate_data.custom_include_body = settings.custom_include_body; |
| 2655 | generate_data['custom_exclude_body'] = settings.custom_exclude_body; | 2655 | generate_data.custom_exclude_body = settings.custom_exclude_body; |
| 2656 | generate_data['custom_include_headers'] = settings.custom_include_headers; | 2656 | generate_data.custom_include_headers = settings.custom_include_headers; |
| 2657 | } | 2657 | } |
| 2658 | 2658 | ||
| 2659 | if (settings.chat_completion_source === chat_completion_sources.COHERE) { | 2659 | if (settings.chat_completion_source === chat_completion_sources.COHERE) { |
| 2660 | // Clamp to 0.01 -> 0.99 | 2660 | // Clamp to 0.01 -> 0.99 |
| 2661 | generate_data['top_p'] = Math.min(Math.max(Number(settings.top_p_openai), 0.01), 0.99); | 2661 | generate_data.top_p = Math.min(Math.max(Number(settings.top_p_openai), 0.01), 0.99); |
| 2662 | generate_data['top_k'] = Number(settings.top_k_openai); | 2662 | generate_data.top_k = Number(settings.top_k_openai); |
| 2663 | // Clamp to 0 -> 1 | 2663 | // Clamp to 0 -> 1 |
| 2664 | generate_data['frequency_penalty'] = Math.min(Math.max(Number(settings.freq_pen_openai), 0), 1); | 2664 | generate_data.frequency_penalty = Math.min(Math.max(Number(settings.freq_pen_openai), 0), 1); |
| 2665 | generate_data['presence_penalty'] = Math.min(Math.max(Number(settings.pres_pen_openai), 0), 1); | 2665 | generate_data.presence_penalty = Math.min(Math.max(Number(settings.pres_pen_openai), 0), 1); |
| 2666 | generate_data['stop'] = getCustomStoppingStrings(5); | 2666 | generate_data.stop = getCustomStoppingStrings(5); |
| 2667 | } | 2667 | } |
| 2668 | 2668 | ||
| 2669 | if (settings.chat_completion_source === chat_completion_sources.PERPLEXITY) { | 2669 | if (settings.chat_completion_source === chat_completion_sources.PERPLEXITY) { |
| 2670 | generate_data['top_k'] = Number(settings.top_k_openai); | 2670 | generate_data.top_k = Number(settings.top_k_openai); |
| 2671 | generate_data['frequency_penalty'] = Number(settings.freq_pen_openai); | 2671 | generate_data.frequency_penalty = Number(settings.freq_pen_openai); |
| 2672 | generate_data['presence_penalty'] = Number(settings.pres_pen_openai); | 2672 | generate_data.presence_penalty = Number(settings.pres_pen_openai); |
| 2673 | delete generate_data['stop']; | 2673 | delete generate_data.stop; |
| 2674 | } | 2674 | } |
| 2675 | 2675 | ||
| 2676 | // https://console.groq.com/docs/openai | 2676 | // https://console.groq.com/docs/openai |
| @@ -2713,35 +2713,35 @@ export async function createGenerationParameters(settings, model, type, messages | |||
| 2713 | 2713 | ||
| 2714 | // https://docs.electronhub.ai/api-reference/chat/completions | 2714 | // https://docs.electronhub.ai/api-reference/chat/completions |
| 2715 | if (settings.chat_completion_source === chat_completion_sources.ELECTRONHUB) { | 2715 | if (settings.chat_completion_source === chat_completion_sources.ELECTRONHUB) { |
| 2716 | generate_data['top_k'] = Number(settings.top_k_openai); | 2716 | generate_data.top_k = Number(settings.top_k_openai); |
| 2717 | } | 2717 | } |
| 2718 | 2718 | ||
| 2719 | if (settings.chat_completion_source === chat_completion_sources.CHUTES) { | 2719 | if (settings.chat_completion_source === chat_completion_sources.CHUTES) { |
| 2720 | generate_data['min_p'] = Number(settings.min_p_openai); | 2720 | generate_data.min_p = Number(settings.min_p_openai); |
| 2721 | generate_data['top_k'] = settings.top_k_openai > 0 ? Number(settings.top_k_openai) : undefined; | 2721 | generate_data.top_k = settings.top_k_openai > 0 ? Number(settings.top_k_openai) : undefined; |
| 2722 | generate_data['repetition_penalty'] = Number(settings.repetition_penalty_openai); | 2722 | generate_data.repetition_penalty = Number(settings.repetition_penalty_openai); |
| 2723 | generate_data['stop'] = getCustomStoppingStrings(); | 2723 | generate_data.stop = getCustomStoppingStrings(); |
| 2724 | } | 2724 | } |
| 2725 | 2725 | ||
| 2726 | // https://docs.z.ai/api-reference/llm/chat-completion | 2726 | // https://docs.z.ai/api-reference/llm/chat-completion |
| 2727 | if (settings.chat_completion_source === chat_completion_sources.ZAI) { | 2727 | if (settings.chat_completion_source === chat_completion_sources.ZAI) { |
| 2728 | generate_data['top_p'] = generate_data.top_p || 0.01; | 2728 | generate_data.top_p = generate_data.top_p || 0.01; |
| 2729 | generate_data['stop'] = getCustomStoppingStrings(1); | 2729 | generate_data.stop = getCustomStoppingStrings(1); |
| 2730 | generate_data['zai_endpoint'] = settings.zai_endpoint || ZAI_ENDPOINT.COMMON; | 2730 | generate_data.zai_endpoint = settings.zai_endpoint || ZAI_ENDPOINT.COMMON; |
| 2731 | delete generate_data.presence_penalty; | 2731 | delete generate_data.presence_penalty; |
| 2732 | delete generate_data.frequency_penalty; | 2732 | delete generate_data.frequency_penalty; |
| 2733 | } | 2733 | } |
| 2734 | 2734 | ||
| 2735 | // https://docs.nano-gpt.com/api-reference/endpoint/chat-completion#temperature-&-nucleus | 2735 | // https://docs.nano-gpt.com/api-reference/endpoint/chat-completion#temperature-&-nucleus |
| 2736 | if (settings.chat_completion_source === chat_completion_sources.NANOGPT) { | 2736 | if (settings.chat_completion_source === chat_completion_sources.NANOGPT) { |
| 2737 | generate_data['top_k'] = Number(settings.top_k_openai); | 2737 | generate_data.top_k = Number(settings.top_k_openai); |
| 2738 | generate_data['min_p'] = Number(settings.min_p_openai); | 2738 | generate_data.min_p = Number(settings.min_p_openai); |
| 2739 | generate_data['repetition_penalty'] = Number(settings.repetition_penalty_openai); | 2739 | generate_data.repetition_penalty = Number(settings.repetition_penalty_openai); |
| 2740 | generate_data['top_a'] = Number(settings.top_a_openai); | 2740 | generate_data.top_a = Number(settings.top_a_openai); |
| 2741 | } | 2741 | } |
| 2742 | 2742 | ||
| 2743 | if (seedSupportedSources.includes(settings.chat_completion_source) && settings.seed >= 0) { | 2743 | if (seedSupportedSources.includes(settings.chat_completion_source) && settings.seed >= 0) { |
| 2744 | generate_data['seed'] = settings.seed; | 2744 | generate_data.seed = settings.seed; |
| 2745 | } | 2745 | } |
| 2746 | 2746 | ||
| 2747 | if ([chat_completion_sources.OPENAI, chat_completion_sources.AZURE_OPENAI].includes(settings.chat_completion_source) && /^(o1|o3|o4)/.test(model) || | 2747 | 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() { | |||
| 6162 | } | 6162 | } |
| 6163 | 6163 | ||
| 6164 | // Save to backend secret storage | 6164 | // Save to backend secret storage |
| 6165 | const keyLabel = serviceAccount['client_email'] || ''; | 6165 | const keyLabel = serviceAccount.client_email || ''; |
| 6166 | await writeSecret(SECRET_KEYS.VERTEXAI_SERVICE_ACCOUNT, jsonContent, keyLabel); | 6166 | await writeSecret(SECRET_KEYS.VERTEXAI_SERVICE_ACCOUNT, jsonContent, keyLabel); |
| 6167 | 6167 | ||
| 6168 | // Show success status | 6168 | // Show success status |
| @@ -835,7 +835,7 @@ async function renamePersona(avatarId) { | |||
| 835 | async function selectCurrentPersona({ toastPersonaNameChange = true } = {}) { | 835 | async function selectCurrentPersona({ toastPersonaNameChange = true } = {}) { |
| 836 | const personaName = power_user.personas[user_avatar]; | 836 | const personaName = power_user.personas[user_avatar]; |
| 837 | if (personaName) { | 837 | if (personaName) { |
| 838 | const shouldAutoLock = power_user.persona_auto_lock && user_avatar !== chat_metadata['persona']; | 838 | const shouldAutoLock = power_user.persona_auto_lock && user_avatar !== chat_metadata.persona; |
| 839 | 839 | ||
| 840 | if (personaName !== name1) { | 840 | if (personaName !== name1) { |
| 841 | console.log(`Auto-updating user name to ${personaName}`); | 841 | console.log(`Auto-updating user name to ${personaName}`); |
| @@ -871,7 +871,7 @@ async function selectCurrentPersona({ toastPersonaNameChange = true } = {}) { | |||
| 871 | 871 | ||
| 872 | // Update the locked persona if setting is enabled | 872 | // Update the locked persona if setting is enabled |
| 873 | if (shouldAutoLock) { | 873 | if (shouldAutoLock) { |
| 874 | chat_metadata['persona'] = user_avatar; | 874 | chat_metadata.persona = user_avatar; |
| 875 | console.log(`Auto locked persona to ${user_avatar}`); | 875 | console.log(`Auto locked persona to ${user_avatar}`); |
| 876 | if (toastPersonaNameChange && power_user.persona_show_notifications) { | 876 | if (toastPersonaNameChange && power_user.persona_show_notifications) { |
| 877 | toastr.success(t`Persona ${personaName} selected and auto-locked to current chat`, t`Persona Selected`); | 877 | toastr.success(t`Persona ${personaName} selected and auto-locked to current chat`, t`Persona Selected`); |
| @@ -914,7 +914,7 @@ export function isPersonaLocked(type = 'chat') { | |||
| 914 | case 'default': | 914 | case 'default': |
| 915 | return power_user.default_persona === user_avatar; | 915 | return power_user.default_persona === user_avatar; |
| 916 | case 'chat': | 916 | case 'chat': |
| 917 | return chat_metadata['persona'] == user_avatar; | 917 | return chat_metadata.persona == user_avatar; |
| 918 | case 'character': { | 918 | case 'character': { |
| 919 | return !!power_user.persona_descriptions[user_avatar]?.connections?.some(isPersonaConnectionLocked); | 919 | return !!power_user.persona_descriptions[user_avatar]?.connections?.some(isPersonaConnectionLocked); |
| 920 | } | 920 | } |
| @@ -960,9 +960,9 @@ async function unlockPersona(type = 'chat') { | |||
| 960 | break; | 960 | break; |
| 961 | } | 961 | } |
| 962 | case 'chat': { | 962 | case 'chat': { |
| 963 | if (chat_metadata['persona']) { | 963 | if (chat_metadata.persona) { |
| 964 | console.log(`Unlocking persona ${user_avatar} from this chat`); | 964 | console.log(`Unlocking persona ${user_avatar} from this chat`); |
| 965 | delete chat_metadata['persona']; | 965 | delete chat_metadata.persona; |
| 966 | await saveMetadata(); | 966 | await saveMetadata(); |
| 967 | if (power_user.persona_show_notifications && !isPersonaPanelOpen()) { | 967 | if (power_user.persona_show_notifications && !isPersonaPanelOpen()) { |
| 968 | toastr.info(t`Persona ${name1} is now unlocked from this chat.`, t`Persona Unlocked`); | 968 | toastr.info(t`Persona ${name1} is now unlocked from this chat.`, t`Persona Unlocked`); |
| @@ -1021,7 +1021,7 @@ async function lockPersona(type = 'chat') { | |||
| 1021 | } | 1021 | } |
| 1022 | case 'chat': { | 1022 | case 'chat': { |
| 1023 | console.log(`Locking persona ${user_avatar} to this chat`); | 1023 | console.log(`Locking persona ${user_avatar} to this chat`); |
| 1024 | chat_metadata['persona'] = user_avatar; | 1024 | chat_metadata.persona = user_avatar; |
| 1025 | saveMetadataDebounced(); | 1025 | saveMetadataDebounced(); |
| 1026 | if (power_user.persona_show_notifications && !isPersonaPanelOpen()) { | 1026 | if (power_user.persona_show_notifications && !isPersonaPanelOpen()) { |
| 1027 | toastr.success(t`User persona ${name1} is locked to ${name2} in this chat`, t`Persona Locked`); | 1027 | toastr.success(t`User persona ${name1} is locked to ${name2} in this chat`, t`Persona Locked`); |
| @@ -1105,9 +1105,9 @@ async function deleteUserAvatar() { | |||
| 1105 | power_user.default_persona = null; | 1105 | power_user.default_persona = null; |
| 1106 | } | 1106 | } |
| 1107 | 1107 | ||
| 1108 | if (avatarId === chat_metadata['persona']) { | 1108 | if (avatarId === chat_metadata.persona) { |
| 1109 | toastr.warning(t`The locked persona was deleted. You will need to set a new persona for this chat.`, t`Persona Deleted`); | 1109 | toastr.warning(t`The locked persona was deleted. You will need to set a new persona for this chat.`, t`Persona Deleted`); |
| 1110 | delete chat_metadata['persona']; | 1110 | delete chat_metadata.persona; |
| 1111 | await saveMetadata(); | 1111 | await saveMetadata(); |
| 1112 | } | 1112 | } |
| 1113 | 1113 | ||
| @@ -1317,7 +1317,7 @@ async function toggleDefaultPersona(avatarId, { quiet = false } = {}) { | |||
| 1317 | */ | 1317 | */ |
| 1318 | function getPersonaStates(avatarId) { | 1318 | function getPersonaStates(avatarId) { |
| 1319 | const isDefaultPersona = power_user.default_persona === avatarId; | 1319 | const isDefaultPersona = power_user.default_persona === avatarId; |
| 1320 | const hasChatLock = chat_metadata['persona'] == avatarId; | 1320 | const hasChatLock = chat_metadata.persona == avatarId; |
| 1321 | 1321 | ||
| 1322 | /** @type {PersonaConnection[]} */ | 1322 | /** @type {PersonaConnection[]} */ |
| 1323 | const connections = power_user.persona_descriptions[avatarId]?.connections; | 1323 | const connections = power_user.persona_descriptions[avatarId]?.connections; |
| @@ -1413,13 +1413,13 @@ function updatePersonaUIStates({ navigateToCurrent = false } = {}) { | |||
| 1413 | * @returns {PersonaLockInfo} An object containing flags and a message describing the persona lock status. | 1413 | * @returns {PersonaLockInfo} An object containing flags and a message describing the persona lock status. |
| 1414 | */ | 1414 | */ |
| 1415 | function getPersonaTemporaryLockInfo() { | 1415 | function getPersonaTemporaryLockInfo() { |
| 1416 | const hasDifferentChatLock = !!chat_metadata['persona'] && chat_metadata['persona'] !== user_avatar; | 1416 | const hasDifferentChatLock = !!chat_metadata.persona && chat_metadata.persona !== user_avatar; |
| 1417 | const hasDifferentDefaultLock = power_user.default_persona && power_user.default_persona !== user_avatar; | 1417 | const hasDifferentDefaultLock = power_user.default_persona && power_user.default_persona !== user_avatar; |
| 1418 | const isTemporary = hasDifferentChatLock || (!chat_metadata['persona'] && hasDifferentDefaultLock); | 1418 | const isTemporary = hasDifferentChatLock || (!chat_metadata.persona && hasDifferentDefaultLock); |
| 1419 | 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.` | 1419 | 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.` |
| 1420 | + '\n\n' | 1420 | + '\n\n' |
| 1421 | + t`Current Persona: ${power_user.personas[user_avatar]}` | 1421 | + t`Current Persona: ${power_user.personas[user_avatar]}` |
| 1422 | + (hasDifferentChatLock ? '\n' + t`Chat persona: ${power_user.personas[chat_metadata['persona']]}` : '') | 1422 | + (hasDifferentChatLock ? '\n' + t`Chat persona: ${power_user.personas[chat_metadata.persona]}` : '') |
| 1423 | + (hasDifferentDefaultLock ? '\n' + t`Default persona: ${power_user.personas[power_user.default_persona]}` : '') : ''; | 1423 | + (hasDifferentDefaultLock ? '\n' + t`Default persona: ${power_user.personas[power_user.default_persona]}` : '') : ''; |
| 1424 | 1424 | ||
| 1425 | return { | 1425 | return { |
| @@ -1458,14 +1458,14 @@ async function loadPersonaForCurrentChat({ doRender = false } = {}) { | |||
| 1458 | let connectType = null; | 1458 | let connectType = null; |
| 1459 | 1459 | ||
| 1460 | // If persona is locked in chat metadata, select it | 1460 | // If persona is locked in chat metadata, select it |
| 1461 | if (chat_metadata['persona']) { | 1461 | if (chat_metadata.persona) { |
| 1462 | console.log(`Using locked persona ${chat_metadata['persona']}`); | 1462 | console.log(`Using locked persona ${chat_metadata.persona}`); |
| 1463 | chatPersona = chat_metadata['persona']; | 1463 | chatPersona = chat_metadata.persona; |
| 1464 | 1464 | ||
| 1465 | // Verify it exists | 1465 | // Verify it exists |
| 1466 | if (!userAvatars.includes(chatPersona)) { | 1466 | if (!userAvatars.includes(chatPersona)) { |
| 1467 | console.warn('Chat-locked persona avatar not found, unlocking persona'); | 1467 | console.warn('Chat-locked persona avatar not found, unlocking persona'); |
| 1468 | delete chat_metadata['persona']; | 1468 | delete chat_metadata.persona; |
| 1469 | saveSettingsDebounced(); | 1469 | saveSettingsDebounced(); |
| 1470 | chatPersona = ''; | 1470 | chatPersona = ''; |
| 1471 | } | 1471 | } |
| @@ -1528,9 +1528,9 @@ async function loadPersonaForCurrentChat({ doRender = false } = {}) { | |||
| 1528 | } | 1528 | } |
| 1529 | 1529 | ||
| 1530 | // Whatever way we selected a persona, if it doesn't exist, unlock this chat | 1530 | // Whatever way we selected a persona, if it doesn't exist, unlock this chat |
| 1531 | if (chat_metadata['persona'] && !userAvatars.includes(chat_metadata['persona'])) { | 1531 | if (chat_metadata.persona && !userAvatars.includes(chat_metadata.persona)) { |
| 1532 | console.warn('Persona avatar not found, unlocking persona'); | 1532 | console.warn('Persona avatar not found, unlocking persona'); |
| 1533 | delete chat_metadata['persona']; | 1533 | delete chat_metadata.persona; |
| 1534 | } | 1534 | } |
| 1535 | 1535 | ||
| 1536 | // Default persona missing | 1536 | // Default persona missing |
| @@ -1542,7 +1542,7 @@ async function loadPersonaForCurrentChat({ doRender = false } = {}) { | |||
| 1542 | 1542 | ||
| 1543 | // Persona avatar found, select it | 1543 | // Persona avatar found, select it |
| 1544 | if (chatPersona && user_avatar !== chatPersona) { | 1544 | if (chatPersona && user_avatar !== chatPersona) { |
| 1545 | const willAutoLock = power_user.persona_auto_lock && user_avatar !== chat_metadata['persona']; | 1545 | const willAutoLock = power_user.persona_auto_lock && user_avatar !== chat_metadata.persona; |
| 1546 | await setUserAvatar(chatPersona, { toastPersonaNameChange: false, navigateToCurrent: true }); | 1546 | await setUserAvatar(chatPersona, { toastPersonaNameChange: false, navigateToCurrent: true }); |
| 1547 | 1547 | ||
| 1548 | if (power_user.persona_show_notifications) { | 1548 | if (power_user.persona_show_notifications) { |
| @@ -1554,7 +1554,7 @@ async function loadPersonaForCurrentChat({ doRender = false } = {}) { | |||
| 1554 | } | 1554 | } |
| 1555 | } | 1555 | } |
| 1556 | // Even if it's the same persona, we still might need to auto-lock to chat if that's enabled | 1556 | // Even if it's the same persona, we still might need to auto-lock to chat if that's enabled |
| 1557 | else if (chatPersona && power_user.persona_auto_lock && !chat_metadata['persona']) { | 1557 | else if (chatPersona && power_user.persona_auto_lock && !chat_metadata.persona) { |
| 1558 | await lockPersona('chat'); | 1558 | await lockPersona('chat'); |
| 1559 | } | 1559 | } |
| 1560 | 1560 | ||
| @@ -163,7 +163,7 @@ class PresetManager { | |||
| 163 | const manager = getPresetManager('textgenerationwebui'); | 163 | const manager = getPresetManager('textgenerationwebui'); |
| 164 | const name = manager.getSelectedPresetName(); | 164 | const name = manager.getSelectedPresetName(); |
| 165 | const data = manager.getPresetSettings(name); | 165 | const data = manager.getPresetSettings(name); |
| 166 | data['name'] = name; | 166 | data.name = name; |
| 167 | return data; | 167 | return data; |
| 168 | }, | 168 | }, |
| 169 | setData: (data) => { | 169 | setData: (data) => { |
| @@ -652,22 +652,22 @@ class PresetManager { | |||
| 652 | return textgen_settings; | 652 | return textgen_settings; |
| 653 | case 'context': { | 653 | case 'context': { |
| 654 | const context_preset = getContextSettings(); | 654 | const context_preset = getContextSettings(); |
| 655 | context_preset['name'] = name || power_user.context.preset; | 655 | context_preset.name = name || power_user.context.preset; |
| 656 | return context_preset; | 656 | return context_preset; |
| 657 | } | 657 | } |
| 658 | case 'instruct': { | 658 | case 'instruct': { |
| 659 | const instruct_preset = structuredClone(power_user.instruct); | 659 | const instruct_preset = structuredClone(power_user.instruct); |
| 660 | instruct_preset['name'] = name || power_user.instruct.preset; | 660 | instruct_preset.name = name || power_user.instruct.preset; |
| 661 | return instruct_preset; | 661 | return instruct_preset; |
| 662 | } | 662 | } |
| 663 | case 'sysprompt': { | 663 | case 'sysprompt': { |
| 664 | const sysprompt_preset = structuredClone(power_user.sysprompt); | 664 | const sysprompt_preset = structuredClone(power_user.sysprompt); |
| 665 | sysprompt_preset['name'] = name || power_user.sysprompt.preset; | 665 | sysprompt_preset.name = name || power_user.sysprompt.preset; |
| 666 | return sysprompt_preset; | 666 | return sysprompt_preset; |
| 667 | } | 667 | } |
| 668 | case 'reasoning': { | 668 | case 'reasoning': { |
| 669 | const reasoning_preset = structuredClone(power_user.reasoning); | 669 | const reasoning_preset = structuredClone(power_user.reasoning); |
| 670 | reasoning_preset['name'] = name || power_user.reasoning.preset; | 670 | reasoning_preset.name = name || power_user.reasoning.preset; |
| 671 | return reasoning_preset; | 671 | return reasoning_preset; |
| 672 | } | 672 | } |
| 673 | default: | 673 | default: |
| @@ -1115,7 +1115,7 @@ export async function initPresetManager() { | |||
| 1115 | const fileName = file.name.replace('.json', '').replace('.settings', ''); | 1115 | const fileName = file.name.replace('.json', '').replace('.settings', ''); |
| 1116 | const data = await parseJsonFile(file); | 1116 | const data = await parseJsonFile(file); |
| 1117 | const name = data?.name ?? fileName; | 1117 | const name = data?.name ?? fileName; |
| 1118 | data['name'] = name; | 1118 | data.name = name; |
| 1119 | 1119 | ||
| 1120 | await presetManager.savePreset(name, data); | 1120 | await presetManager.savePreset(name, data); |
| 1121 | const successToast = !presetManager.isAdvancedFormatting() ? t`Preset imported` : t`Template imported`; | 1121 | const successToast = !presetManager.isAdvancedFormatting() ? t`Preset imported` : t`Template imported`; |
| @@ -2120,7 +2120,7 @@ export function initDefaultSlashCommands() { | |||
| 2120 | isRequired: true, | 2120 | isRequired: true, |
| 2121 | enumProvider: (executor, scope) => [ | 2121 | enumProvider: (executor, scope) => [ |
| 2122 | ...commonEnumProviders.variables('scope')(executor, scope), | 2122 | ...commonEnumProviders.variables('scope')(executor, scope), |
| 2123 | ...(typeof window['qrEnumProviderExecutables'] === 'function') ? window['qrEnumProviderExecutables']() : [], | 2123 | ...(typeof globalThis.qrEnumProviderExecutables === 'function') ? globalThis.qrEnumProviderExecutables() : [], |
| 2124 | ], | 2124 | ], |
| 2125 | }), | 2125 | }), |
| 2126 | ], | 2126 | ], |
| @@ -3572,7 +3572,7 @@ async function runCallback(args, name) { | |||
| 3572 | return result.pipe; | 3572 | return result.pipe; |
| 3573 | } | 3573 | } |
| 3574 | 3574 | ||
| 3575 | if (typeof window['executeQuickReplyByName'] !== 'function') { | 3575 | if (typeof globalThis.executeQuickReplyByName !== 'function') { |
| 3576 | throw new Error(t`Quick Reply extension is not loaded`); | 3576 | throw new Error(t`Quick Reply extension is not loaded`); |
| 3577 | } | 3577 | } |
| 3578 | 3578 | ||
| @@ -3583,7 +3583,7 @@ async function runCallback(args, name) { | |||
| 3583 | abortController: args._abortController, | 3583 | abortController: args._abortController, |
| 3584 | debugController: args._debugController, | 3584 | debugController: args._debugController, |
| 3585 | }; | 3585 | }; |
| 3586 | return await window['executeQuickReplyByName'](name, args, options); | 3586 | return await globalThis.executeQuickReplyByName(name, args, options); |
| 3587 | } catch (error) { | 3587 | } catch (error) { |
| 3588 | throw new Error(t`Error running Quick Reply "${name}": ${error.message}`); | 3588 | throw new Error(t`Error running Quick Reply "${name}": ${error.message}`); |
| 3589 | } | 3589 | } |
| @@ -4788,7 +4788,7 @@ export async function sendMessageAs(args, text) { | |||
| 4788 | insertAt = chat.length + insertAt; | 4788 | insertAt = chat.length + insertAt; |
| 4789 | } | 4789 | } |
| 4790 | 4790 | ||
| 4791 | chat_metadata['tainted'] = true; | 4791 | chat_metadata.tainted = true; |
| 4792 | 4792 | ||
| 4793 | if (!isNaN(insertAt) && insertAt >= 0 && insertAt <= chat.length) { | 4793 | if (!isNaN(insertAt) && insertAt >= 0 && insertAt <= chat.length) { |
| 4794 | chat.splice(insertAt, 0, message); | 4794 | chat.splice(insertAt, 0, message); |
| @@ -4840,7 +4840,7 @@ export async function sendNarratorMessage(args, text) { | |||
| 4840 | insertAt = chat.length + insertAt; | 4840 | insertAt = chat.length + insertAt; |
| 4841 | } | 4841 | } |
| 4842 | 4842 | ||
| 4843 | chat_metadata['tainted'] = true; | 4843 | chat_metadata.tainted = true; |
| 4844 | 4844 | ||
| 4845 | if (!isNaN(insertAt) && insertAt >= 0 && insertAt <= chat.length) { | 4845 | if (!isNaN(insertAt) && insertAt >= 0 && insertAt <= chat.length) { |
| 4846 | chat.splice(insertAt, 0, message); | 4846 | chat.splice(insertAt, 0, message); |
| @@ -4892,7 +4892,7 @@ export async function promptQuietForLoudResponse(who, text) { | |||
| 4892 | }, | 4892 | }, |
| 4893 | }; | 4893 | }; |
| 4894 | 4894 | ||
| 4895 | chat_metadata['tainted'] = true; | 4895 | chat_metadata.tainted = true; |
| 4896 | 4896 | ||
| 4897 | chat.push(message); | 4897 | chat.push(message); |
| 4898 | await eventSource.emit(event_types.MESSAGE_SENT, (chat.length - 1)); | 4898 | await eventSource.emit(event_types.MESSAGE_SENT, (chat.length - 1)); |
| @@ -4928,7 +4928,7 @@ async function sendCommentMessage(args, text) { | |||
| 4928 | insertAt = chat.length + insertAt; | 4928 | insertAt = chat.length + insertAt; |
| 4929 | } | 4929 | } |
| 4930 | 4930 | ||
| 4931 | chat_metadata['tainted'] = true; | 4931 | chat_metadata.tainted = true; |
| 4932 | 4932 | ||
| 4933 | if (!isNaN(insertAt) && insertAt >= 0 && insertAt <= chat.length) { | 4933 | if (!isNaN(insertAt) && insertAt >= 0 && insertAt <= chat.length) { |
| 4934 | chat.splice(insertAt, 0, message); | 4934 | chat.splice(insertAt, 0, message); |
| @@ -880,8 +880,8 @@ async function downloadTabbyModel() { | |||
| 880 | } | 880 | } |
| 881 | 881 | ||
| 882 | // Params for the server side of ST | 882 | // Params for the server side of ST |
| 883 | params['api_server'] = serverUrl; | 883 | params.api_server = serverUrl; |
| 884 | params['api_type'] = textgen_settings.type; | 884 | params.api_type = textgen_settings.type; |
| 885 | 885 | ||
| 886 | toastr.info('Downloading. Check the Tabby console for progress reports.'); | 886 | toastr.info('Downloading. Check the Tabby console for progress reports.'); |
| 887 | 887 | ||
| @@ -755,7 +755,7 @@ async function getStatusTextgen() { | |||
| 755 | power_user.chat_template_hash = chat_template_hash; | 755 | power_user.chat_template_hash = chat_template_hash; |
| 756 | 756 | ||
| 757 | if (wantsContextSize && 'default_generation_settings' in data) { | 757 | if (wantsContextSize && 'default_generation_settings' in data) { |
| 758 | const backend_max_context = data['default_generation_settings']['n_ctx']; | 758 | const backend_max_context = data.default_generation_settings.n_ctx; |
| 759 | if (backend_max_context && typeof backend_max_context === 'number') { | 759 | if (backend_max_context && typeof backend_max_context === 'number') { |
| 760 | const old_value = max_context; | 760 | const old_value = max_context; |
| 761 | if (max_context !== backend_max_context) { | 761 | if (max_context !== backend_max_context) { |
| @@ -913,16 +913,16 @@ export function initTextGenSettings() { | |||
| 913 | $('#ban_eos_token_textgenerationwebui').prop('checked', false); //Aphro should not ban EOS, just ignore it; 'add token '2' to ban list do to this' | 913 | $('#ban_eos_token_textgenerationwebui').prop('checked', false); //Aphro should not ban EOS, just ignore it; 'add token '2' to ban list do to this' |
| 914 | //special handling for vLLM/Aphrodite topK -1 disable state | 914 | //special handling for vLLM/Aphrodite topK -1 disable state |
| 915 | $('#top_k_textgenerationwebui').attr('min', -1); | 915 | $('#top_k_textgenerationwebui').attr('min', -1); |
| 916 | if ($('#top_k_textgenerationwebui').val() === '0' || textgenerationwebui_settings['top_k'] === 0) { | 916 | if ($('#top_k_textgenerationwebui').val() === '0' || textgenerationwebui_settings.top_k === 0) { |
| 917 | textgenerationwebui_settings['top_k'] = -1; | 917 | textgenerationwebui_settings.top_k = -1; |
| 918 | $('#top_k_textgenerationwebui').val('-1').trigger('input'); | 918 | $('#top_k_textgenerationwebui').val('-1').trigger('input'); |
| 919 | } | 919 | } |
| 920 | } else { | 920 | } else { |
| 921 | $('#mirostat_mode_textgenerationwebui').attr('step', 1); | 921 | $('#mirostat_mode_textgenerationwebui').attr('step', 1); |
| 922 | //undo special vLLM/Aphrodite setup for topK | 922 | //undo special vLLM/Aphrodite setup for topK |
| 923 | $('#top_k_textgenerationwebui').attr('min', 0); | 923 | $('#top_k_textgenerationwebui').attr('min', 0); |
| 924 | if ($('#top_k_textgenerationwebui').val() === '-1' || textgenerationwebui_settings['top_k'] === -1) { | 924 | if ($('#top_k_textgenerationwebui').val() === '-1' || textgenerationwebui_settings.top_k === -1) { |
| 925 | textgenerationwebui_settings['top_k'] = 0; | 925 | textgenerationwebui_settings.top_k = 0; |
| 926 | $('#top_k_textgenerationwebui').val('0').trigger('input'); | 926 | $('#top_k_textgenerationwebui').val('0').trigger('input'); |
| 927 | } | 927 | } |
| 928 | } | 928 | } |
| @@ -410,8 +410,8 @@ export class ToolManager { | |||
| 410 | if (tools.length) { | 410 | if (tools.length) { |
| 411 | console.log('[ToolManager] Registered function tools:', tools); | 411 | console.log('[ToolManager] Registered function tools:', tools); |
| 412 | 412 | ||
| 413 | data['tools'] = tools; | 413 | data.tools = tools; |
| 414 | data['tool_choice'] = 'auto'; | 414 | data.tool_choice = 'auto'; |
| 415 | } | 415 | } |
| 416 | } | 416 | } |
| 417 | 417 | ||
| @@ -36,10 +36,16 @@ export const localizePagination = function (container) { | |||
| 36 | 36 | ||
| 37 | /** | 37 | /** |
| 38 | * Checks if the current environment supports negative lookbehind in regular expressions. | 38 | * Checks if the current environment supports negative lookbehind in regular expressions. |
| 39 | * @type {{ (): boolean; result?: boolean }} Defines the function as a memoized object with a cached result. | ||
| 39 | * @returns {boolean} True if negative lookbehind is supported, false otherwise. | 40 | * @returns {boolean} True if negative lookbehind is supported, false otherwise. |
| 40 | */ | 41 | */ |
| 41 | export function canUseNegativeLookbehind() { | 42 | export function canUseNegativeLookbehind() { |
| 42 | let result = canUseNegativeLookbehind['result']; | 43 | /** |
| 44 | * A reference to the function itself, typed as a callable object with a cache property. | ||
| 45 | * @type {{ (): boolean; result?: boolean }} | ||
| 46 | */ | ||
| 47 | const fn = canUseNegativeLookbehind; | ||
| 48 | let result = fn.result; | ||
| 43 | if (typeof result !== 'boolean') { | 49 | if (typeof result !== 'boolean') { |
| 44 | try { | 50 | try { |
| 45 | new RegExp('(?<!_)'); | 51 | new RegExp('(?<!_)'); |
| @@ -47,7 +53,7 @@ export function canUseNegativeLookbehind() { | |||
| 47 | } catch (e) { | 53 | } catch (e) { |
| 48 | result = false; | 54 | result = false; |
| 49 | } | 55 | } |
| 50 | canUseNegativeLookbehind['result'] = result; | 56 | fn.result = result; |
| 51 | } | 57 | } |
| 52 | return result; | 58 | return result; |
| 53 | } | 59 | } |
| @@ -2440,8 +2446,8 @@ export async function fetchFaFile(name) { | |||
| 2440 | const sheet = style.sheet; | 2446 | const sheet = style.sheet; |
| 2441 | style.remove(); | 2447 | style.remove(); |
| 2442 | return [...sheet.cssRules] | 2448 | return [...sheet.cssRules] |
| 2443 | .filter(rule => rule.style?.content) | 2449 | .filter(rule => rule['style']?.content) |
| 2444 | .map(rule => rule.selectorText.split(/,\s*/).map(selector => selector.split('::').shift().slice(1))) | 2450 | .map(rule => rule['selectorText'].split(/,\s*/).map(selector => selector.split('::').shift().slice(1))) |
| 2445 | ; | 2451 | ; |
| 2446 | } | 2452 | } |
| 2447 | 2453 | ||
| @@ -3271,7 +3271,7 @@ export async function getWorldEntry(name, data, entry) { | |||
| 3271 | const commentInput = headerTemplate.find('textarea[name="comment"]'); | 3271 | const commentInput = headerTemplate.find('textarea[name="comment"]'); |
| 3272 | 3272 | ||
| 3273 | //Update the commentInput's placeholder. | 3273 | //Update the commentInput's placeholder. |
| 3274 | const keys = entry['key'].join(', '); | 3274 | const keys = entry.key.join(', '); |
| 3275 | setCommentPlaceholder(keys, commentInput); | 3275 | setCommentPlaceholder(keys, commentInput); |
| 3276 | 3276 | ||
| 3277 | commentInput.data('uid', entry.uid); | 3277 | commentInput.data('uid', entry.uid); |
| @@ -145,7 +145,7 @@ router.post('/get', async (request, response) => { | |||
| 145 | for (let file of files) { | 145 | for (let file of files) { |
| 146 | if (!file.endsWith('.placeholder')) { | 146 | if (!file.endsWith('.placeholder')) { |
| 147 | //console.debug("Asset VRM model found:",file) | 147 | //console.debug("Asset VRM model found:",file) |
| 148 | output['vrm']['model'].push(clientRelativePath(request.user.directories.root, file)); | 148 | output.vrm.model.push(clientRelativePath(request.user.directories.root, file)); |
| 149 | } | 149 | } |
| 150 | } | 150 | } |
| 151 | 151 | ||
| @@ -156,7 +156,7 @@ router.post('/get', async (request, response) => { | |||
| 156 | for (let file of files) { | 156 | for (let file of files) { |
| 157 | if (!file.endsWith('.placeholder')) { | 157 | if (!file.endsWith('.placeholder')) { |
| 158 | //console.debug("Asset VRM animation found:",file) | 158 | //console.debug("Asset VRM animation found:",file) |
| 159 | output['vrm']['animation'].push(clientRelativePath(request.user.directories.root, file)); | 159 | output.vrm.animation.push(clientRelativePath(request.user.directories.root, file)); |
| 160 | } | 160 | } |
| 161 | } | 161 | } |
| 162 | continue; | 162 | continue; |
| @@ -245,7 +245,7 @@ async function sendClaudeRequest(request, response) { | |||
| 245 | }; | 245 | }; |
| 246 | if (useSystemPrompt) { | 246 | if (useSystemPrompt) { |
| 247 | if (enableSystemPromptCache && Array.isArray(convertedPrompt.systemPrompt) && convertedPrompt.systemPrompt.length) { | 247 | if (enableSystemPromptCache && Array.isArray(convertedPrompt.systemPrompt) && convertedPrompt.systemPrompt.length) { |
| 248 | convertedPrompt.systemPrompt[convertedPrompt.systemPrompt.length - 1]['cache_control'] = { type: 'ephemeral', ttl: cacheTTL }; | 248 | convertedPrompt.systemPrompt[convertedPrompt.systemPrompt.length - 1].cache_control = { type: 'ephemeral', ttl: cacheTTL }; |
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | requestBody.system = convertedPrompt.systemPrompt; | 251 | requestBody.system = convertedPrompt.systemPrompt; |
| @@ -261,7 +261,7 @@ async function sendClaudeRequest(request, response) { | |||
| 261 | .map(fn => ({ name: fn.name, description: fn.description, input_schema: flattenSchema(fn.parameters, request.body.chat_completion_source) })); | 261 | .map(fn => ({ name: fn.name, description: fn.description, input_schema: flattenSchema(fn.parameters, request.body.chat_completion_source) })); |
| 262 | 262 | ||
| 263 | if (enableSystemPromptCache && requestBody.tools.length) { | 263 | if (enableSystemPromptCache && requestBody.tools.length) { |
| 264 | requestBody.tools[requestBody.tools.length - 1]['cache_control'] = { type: 'ephemeral', ttl: cacheTTL }; | 264 | requestBody.tools[requestBody.tools.length - 1].cache_control = { type: 'ephemeral', ttl: cacheTTL }; |
| 265 | } | 265 | } |
| 266 | } | 266 | } |
| 267 | 267 | ||
| @@ -76,7 +76,7 @@ router.post('/generate', async function (request, response_generate) { | |||
| 76 | sampler_seed: request.body.sampler_seed, | 76 | sampler_seed: request.body.sampler_seed, |
| 77 | }; | 77 | }; |
| 78 | if (request.body.stop_sequence) { | 78 | if (request.body.stop_sequence) { |
| 79 | this_settings['stop_sequence'] = request.body.stop_sequence; | 79 | this_settings.stop_sequence = request.body.stop_sequence; |
| 80 | } | 80 | } |
| 81 | } | 81 | } |
| 82 | 82 | ||
| @@ -257,10 +257,10 @@ router.post('/props', async function (request, response) { | |||
| 257 | /** @type {any} */ | 257 | /** @type {any} */ |
| 258 | const props = await propsReply.json(); | 258 | const props = await propsReply.json(); |
| 259 | // TEMPORARY: llama.cpp's /props endpoint has a bug which replaces the last newline with a \0 | 259 | // TEMPORARY: llama.cpp's /props endpoint has a bug which replaces the last newline with a \0 |
| 260 | if (apiType === TEXTGEN_TYPES.LLAMACPP && props['chat_template'] && props['chat_template'].endsWith('\u0000')) { | 260 | if (apiType === TEXTGEN_TYPES.LLAMACPP && props.chat_template && props.chat_template.endsWith('\u0000')) { |
| 261 | props['chat_template'] = props['chat_template'].slice(0, -1) + '\n'; | 261 | props.chat_template = props.chat_template.slice(0, -1) + '\n'; |
| 262 | } | 262 | } |
| 263 | props['chat_template_hash'] = createHash('sha256').update(props['chat_template']).digest('hex'); | 263 | props.chat_template_hash = createHash('sha256').update(props.chat_template).digest('hex'); |
| 264 | console.debug(`Model properties: ${JSON.stringify(props)}`); | 264 | console.debug(`Model properties: ${JSON.stringify(props)}`); |
| 265 | return response.send(props); | 265 | return response.send(props); |
| 266 | } catch (error) { | 266 | } catch (error) { |
| @@ -380,7 +380,7 @@ router.post('/generate', async function (request, response) { | |||
| 380 | const keepAlive = Number(getConfigValue('ollama.keepAlive', -1, 'number')); | 380 | const keepAlive = Number(getConfigValue('ollama.keepAlive', -1, 'number')); |
| 381 | const numBatch = Number(getConfigValue('ollama.batchSize', -1, 'number')); | 381 | const numBatch = Number(getConfigValue('ollama.batchSize', -1, 'number')); |
| 382 | if (numBatch > 0) { | 382 | if (numBatch > 0) { |
| 383 | request.body['num_batch'] = numBatch; | 383 | request.body.num_batch = numBatch; |
| 384 | } | 384 | } |
| 385 | args.body = JSON.stringify({ | 385 | args.body = JSON.stringify({ |
| 386 | model: request.body.model, | 386 | model: request.body.model, |
| @@ -410,7 +410,7 @@ router.post('/generate', async function (request, response) { | |||
| 410 | 410 | ||
| 411 | // Map InfermaticAI response to OAI completions format | 411 | // Map InfermaticAI response to OAI completions format |
| 412 | if (apiType === TEXTGEN_TYPES.INFERMATICAI) { | 412 | if (apiType === TEXTGEN_TYPES.INFERMATICAI) { |
| 413 | data['choices'] = (data?.choices || []).map(choice => ({ text: choice?.message?.content || choice.text, logprobs: choice?.logprobs, index: choice?.index })); | 413 | data.choices = (data?.choices || []).map(choice => ({ text: choice?.message?.content || choice.text, logprobs: choice?.logprobs, index: choice?.index })); |
| 414 | } | 414 | } |
| 415 | 415 | ||
| 416 | return response.send(data); | 416 | return response.send(data); |
| @@ -616,7 +616,7 @@ tabby.post('/download', async function (request, response) { | |||
| 616 | /** @type {any} */ | 616 | /** @type {any} */ |
| 617 | const permissionJson = await permissionResponse.json(); | 617 | const permissionJson = await permissionResponse.json(); |
| 618 | 618 | ||
| 619 | if (permissionJson['permission'] !== 'admin') { | 619 | if (permissionJson.permission !== 'admin') { |
| 620 | return response.status(403).send({ error: true }); | 620 | return response.status(403).send({ error: true }); |
| 621 | } | 621 | } |
| 622 | } else { | 622 | } else { |
| @@ -412,16 +412,16 @@ const processCharacter = async (item, directories, { shallow }) => { | |||
| 412 | let jsonObject = getCharaCardV2(JSON.parse(imgData), directories, false); | 412 | let jsonObject = getCharaCardV2(JSON.parse(imgData), directories, false); |
| 413 | jsonObject.avatar = item; | 413 | jsonObject.avatar = item; |
| 414 | const character = jsonObject; | 414 | const character = jsonObject; |
| 415 | character['json_data'] = imgData; | 415 | character.json_data = imgData; |
| 416 | const charStat = fs.statSync(path.join(directories.characters, item)); | 416 | const charStat = fs.statSync(path.join(directories.characters, item)); |
| 417 | character['date_added'] = charStat.ctimeMs; | 417 | character.date_added = charStat.ctimeMs; |
| 418 | character['create_date'] = jsonObject['create_date'] || new Date(Math.round(charStat.ctimeMs)).toISOString(); | 418 | character.create_date = jsonObject.create_date || new Date(Math.round(charStat.ctimeMs)).toISOString(); |
| 419 | const chatsDirectory = path.join(directories.chats, item.replace('.png', '')); | 419 | const chatsDirectory = path.join(directories.chats, item.replace('.png', '')); |
| 420 | 420 | ||
| 421 | const { chatSize, dateLastChat } = calculateChatSize(chatsDirectory); | 421 | const { chatSize, dateLastChat } = calculateChatSize(chatsDirectory); |
| 422 | character['chat_size'] = chatSize; | 422 | character.chat_size = chatSize; |
| 423 | character['date_last_chat'] = dateLastChat; | 423 | character.date_last_chat = dateLastChat; |
| 424 | character['data_size'] = calculateDataSize(jsonObject?.data); | 424 | character.data_size = calculateDataSize(jsonObject?.data); |
| 425 | return shallow ? toShallow(character) : character; | 425 | return shallow ? toShallow(character) : character; |
| 426 | } | 426 | } |
| 427 | catch (err) { | 427 | catch (err) { |
| @@ -504,7 +504,7 @@ function unsetPrivateFields(char) { | |||
| 504 | 504 | ||
| 505 | function readFromV2(char) { | 505 | function readFromV2(char) { |
| 506 | if (_.isUndefined(char.data)) { | 506 | if (_.isUndefined(char.data)) { |
| 507 | console.warn(`Char ${char['name']} has Spec v2 data missing`); | 507 | console.warn(`Char ${char.name} has Spec v2 data missing`); |
| 508 | return char; | 508 | return char; |
| 509 | } | 509 | } |
| 510 | 510 | ||
| @@ -542,17 +542,17 @@ function readFromV2(char) { | |||
| 542 | //console.warn(`Spec v2 extension data missing for field: ${charField}, using default value: ${defaultValue}`); | 542 | //console.warn(`Spec v2 extension data missing for field: ${charField}, using default value: ${defaultValue}`); |
| 543 | char[charField] = defaultValue; | 543 | char[charField] = defaultValue; |
| 544 | } else { | 544 | } else { |
| 545 | console.warn(`Char ${char['name']} has Spec v2 data missing for unknown field: ${charField}`); | 545 | console.warn(`Char ${char.name} has Spec v2 data missing for unknown field: ${charField}`); |
| 546 | return; | 546 | return; |
| 547 | } | 547 | } |
| 548 | } | 548 | } |
| 549 | if (!_.isUndefined(char[charField]) && !_.isUndefined(v2Value) && String(char[charField]) !== String(v2Value)) { | 549 | if (!_.isUndefined(char[charField]) && !_.isUndefined(v2Value) && String(char[charField]) !== String(v2Value)) { |
| 550 | console.warn(`Char ${char['name']} has Spec v2 data mismatch with Spec v1 for field: ${charField}`, char[charField], v2Value); | 550 | console.warn(`Char ${char.name} has Spec v2 data mismatch with Spec v1 for field: ${charField}`, char[charField], v2Value); |
| 551 | } | 551 | } |
| 552 | char[charField] = v2Value; | 552 | char[charField] = v2Value; |
| 553 | }); | 553 | }); |
| 554 | 554 | ||
| 555 | char['chat'] = char['chat'] ?? `${char.name} - ${humanizedDateTime()}`; | 555 | char.chat = char.chat ?? `${char.name} - ${humanizedDateTime()}`; |
| 556 | 556 | ||
| 557 | return char; | 557 | return char; |
| 558 | } | 558 | } |
| @@ -779,7 +779,7 @@ async function importFromCharX(uploadPath, { request }, preservedFileName) { | |||
| 779 | // Apply standard character transformations | 779 | // Apply standard character transformations |
| 780 | let processedCard = readFromV2(card); | 780 | let processedCard = readFromV2(card); |
| 781 | unsetPrivateFields(processedCard); | 781 | unsetPrivateFields(processedCard); |
| 782 | processedCard['create_date'] = new Date().toISOString(); | 782 | processedCard.create_date = new Date().toISOString(); |
| 783 | processedCard.name = sanitize(processedCard.name); | 783 | processedCard.name = sanitize(processedCard.name); |
| 784 | 784 | ||
| 785 | const fileName = preservedFileName || getPngName(processedCard.name, request.user.directories); | 785 | const fileName = preservedFileName || getPngName(processedCard.name, request.user.directories); |
| @@ -893,7 +893,7 @@ async function importFromJson(uploadPath, { request }, preservedFileName) { | |||
| 893 | importRisuSprites(request.user.directories, jsonData); | 893 | importRisuSprites(request.user.directories, jsonData); |
| 894 | unsetPrivateFields(jsonData); | 894 | unsetPrivateFields(jsonData); |
| 895 | jsonData = readFromV2(jsonData); | 895 | jsonData = readFromV2(jsonData); |
| 896 | jsonData['create_date'] = new Date().toISOString(); | 896 | jsonData.create_date = new Date().toISOString(); |
| 897 | const pngName = preservedFileName || getPngName(jsonData.data?.name || jsonData.name, request.user.directories); | 897 | const pngName = preservedFileName || getPngName(jsonData.data?.name || jsonData.name, request.user.directories); |
| 898 | const char = JSON.stringify(jsonData); | 898 | const char = JSON.stringify(jsonData); |
| 899 | const result = await writeCharacterData(DEFAULT_AVATAR_PATH, char, pngName, request); | 899 | const result = await writeCharacterData(DEFAULT_AVATAR_PATH, char, pngName, request); |
| @@ -976,7 +976,7 @@ async function importFromPng(uploadPath, { request }, preservedFileName) { | |||
| 976 | importRisuSprites(request.user.directories, jsonData); | 976 | importRisuSprites(request.user.directories, jsonData); |
| 977 | unsetPrivateFields(jsonData); | 977 | unsetPrivateFields(jsonData); |
| 978 | jsonData = readFromV2(jsonData); | 978 | jsonData = readFromV2(jsonData); |
| 979 | jsonData['create_date'] = new Date().toISOString(); | 979 | jsonData.create_date = new Date().toISOString(); |
| 980 | const char = JSON.stringify(jsonData); | 980 | const char = JSON.stringify(jsonData); |
| 981 | const result = await writeCharacterData(uploadPath, char, pngName, request); | 981 | const result = await writeCharacterData(uploadPath, char, pngName, request); |
| 982 | fs.unlinkSync(uploadPath); | 982 | fs.unlinkSync(uploadPath); |
| @@ -397,8 +397,8 @@ export async function getChatInfo(pathToFile, additionalData = {}, withMetadata | |||
| 397 | const jsonData = tryParse(lastLine); | 397 | const jsonData = tryParse(lastLine); |
| 398 | if (jsonData && (jsonData.name || jsonData.character_name || jsonData.chat_metadata)) { | 398 | if (jsonData && (jsonData.name || jsonData.character_name || jsonData.chat_metadata)) { |
| 399 | chatData.chat_items = (itemCounter - 1); | 399 | chatData.chat_items = (itemCounter - 1); |
| 400 | chatData.mes = jsonData['mes'] || '[The message is empty]'; | 400 | chatData.mes = jsonData.mes || '[The message is empty]'; |
| 401 | chatData.last_mes = jsonData['send_date'] || new Date(Math.round(stats.mtimeMs)).toISOString(); | 401 | chatData.last_mes = jsonData.send_date || new Date(Math.round(stats.mtimeMs)).toISOString(); |
| 402 | 402 | ||
| 403 | res(chatData); | 403 | res(chatData); |
| 404 | } else { | 404 | } else { |
| @@ -126,8 +126,8 @@ router.post('/all', (request, response) => { | |||
| 126 | const fileContents = fs.readFileSync(filePath, 'utf8'); | 126 | const fileContents = fs.readFileSync(filePath, 'utf8'); |
| 127 | const group = JSON.parse(fileContents); | 127 | const group = JSON.parse(fileContents); |
| 128 | const groupStat = fs.statSync(filePath); | 128 | const groupStat = fs.statSync(filePath); |
| 129 | group['date_added'] = groupStat.birthtimeMs; | 129 | group.date_added = groupStat.birthtimeMs; |
| 130 | group['create_date'] = new Date(groupStat.birthtimeMs).toISOString(); | 130 | group.create_date = new Date(groupStat.birthtimeMs).toISOString(); |
| 131 | 131 | ||
| 132 | let chat_size = 0; | 132 | let chat_size = 0; |
| 133 | let date_last_chat = 0; | 133 | let date_last_chat = 0; |
| @@ -142,8 +142,8 @@ router.post('/all', (request, response) => { | |||
| 142 | } | 142 | } |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | group['date_last_chat'] = date_last_chat; | 145 | group.date_last_chat = date_last_chat; |
| 146 | group['chat_size'] = chat_size; | 146 | group.chat_size = chat_size; |
| 147 | groups.push(group); | 147 | groups.push(group); |
| 148 | } | 148 | } |
| 149 | catch (error) { | 149 | catch (error) { |
| @@ -228,7 +228,7 @@ router.post('/get-model', async (request, response) => { | |||
| 228 | }); | 228 | }); |
| 229 | /** @type {any} */ | 229 | /** @type {any} */ |
| 230 | const data = await result.json(); | 230 | const data = await result.json(); |
| 231 | return response.send(data['sd_model_checkpoint']); | 231 | return response.send(data.sd_model_checkpoint); |
| 232 | } catch (error) { | 232 | } catch (error) { |
| 233 | console.error(error); | 233 | console.error(error); |
| 234 | return response.sendStatus(500); | 234 | return response.sendStatus(500); |
| @@ -277,8 +277,8 @@ router.post('/set-model', async (request, response) => { | |||
| 277 | /** @type {any} */ | 277 | /** @type {any} */ |
| 278 | const progressState = await getProgress(); | 278 | const progressState = await getProgress(); |
| 279 | 279 | ||
| 280 | const progress = progressState['progress']; | 280 | const progress = progressState.progress; |
| 281 | const jobCount = progressState['state']['job_count']; | 281 | const jobCount = progressState.state.job_count; |
| 282 | if (progress === 0.0 && jobCount === 0) { | 282 | if (progress === 0.0 && jobCount === 0) { |
| 283 | break; | 283 | break; |
| 284 | } | 284 | } |
| @@ -834,7 +834,7 @@ drawthings.post('/get-model', async (request, response) => { | |||
| 834 | /** @type {any} */ | 834 | /** @type {any} */ |
| 835 | const data = await result.json(); | 835 | const data = await result.json(); |
| 836 | 836 | ||
| 837 | return response.send(data['model']); | 837 | return response.send(data.model); |
| 838 | } catch (error) { | 838 | } catch (error) { |
| 839 | console.error(error); | 839 | console.error(error); |
| 840 | return response.sendStatus(500); | 840 | return response.sendStatus(500); |
| @@ -853,7 +853,7 @@ drawthings.post('/get-upscaler', async (request, response) => { | |||
| 853 | /** @type {any} */ | 853 | /** @type {any} */ |
| 854 | const data = await result.json(); | 854 | const data = await result.json(); |
| 855 | 855 | ||
| 856 | return response.send(data['upscaler']); | 856 | return response.send(data.upscaler); |
| 857 | } catch (error) { | 857 | } catch (error) { |
| 858 | console.error(error); | 858 | console.error(error); |
| 859 | return response.sendStatus(500); | 859 | return response.sendStatus(500); |
| @@ -1052,8 +1052,8 @@ router.post('/remote/kobold/count', async function (request, response) { | |||
| 1052 | 1052 | ||
| 1053 | /** @type {any} */ | 1053 | /** @type {any} */ |
| 1054 | const data = await result.json(); | 1054 | const data = await result.json(); |
| 1055 | const count = data['value']; | 1055 | const count = data.value; |
| 1056 | const ids = data['ids'] ?? []; | 1056 | const ids = data.ids ?? []; |
| 1057 | return response.send({ count, ids }); | 1057 | return response.send({ count, ids }); |
| 1058 | } catch (error) { | 1058 | } catch (error) { |
| 1059 | console.error(error); | 1059 | console.error(error); |
| @@ -639,8 +639,8 @@ test.describe('MacroEngine', () => { | |||
| 639 | await page.evaluate(async ([originalHash]) => { | 639 | await page.evaluate(async ([originalHash]) => { |
| 640 | /** @type {import('../../public/script.js')} */ | 640 | /** @type {import('../../public/script.js')} */ |
| 641 | const { chat_metadata } = await import('./script.js'); | 641 | const { chat_metadata } = await import('./script.js'); |
| 642 | originalHash = chat_metadata['chat_id_hash']; | 642 | originalHash = chat_metadata.chat_id_hash; |
| 643 | chat_metadata['chat_id_hash'] = 123456; | 643 | chat_metadata.chat_id_hash = 123456; |
| 644 | }, [originalHash]); | 644 | }, [originalHash]); |
| 645 | 645 | ||
| 646 | const input = 'Choices: {{pick::red::green::blue}}, {{pick::red::green::blue}}.'; | 646 | const input = 'Choices: {{pick::red::green::blue}}, {{pick::red::green::blue}}.'; |
| @@ -668,7 +668,7 @@ test.describe('MacroEngine', () => { | |||
| 668 | await page.evaluate(async ([originalHash]) => { | 668 | await page.evaluate(async ([originalHash]) => { |
| 669 | /** @type {import('../../public/script.js')} */ | 669 | /** @type {import('../../public/script.js')} */ |
| 670 | const { chat_metadata } = await import('./script.js'); | 670 | const { chat_metadata } = await import('./script.js'); |
| 671 | chat_metadata['chat_id_hash'] = originalHash; | 671 | chat_metadata.chat_id_hash = originalHash; |
| 672 | }, [originalHash]); | 672 | }, [originalHash]); |
| 673 | }); | 673 | }); |
| 674 | }); | 674 | }); |