Merge pull request #3413 from SillyTavern/thinking-is-stylish Thinking is stylish - if you are not cool, I don't know how to help you
Signed| @@ -3789,6 +3789,12 @@ | |||
| 3789 | Auto-Parse Reasoning | 3789 | Auto-Parse Reasoning |
| 3790 | </small> | 3790 | </small> |
| 3791 | </label> | 3791 | </label> |
| 3792 | <label class="checkbox_label" for="reasoning_auto_expand" title="Automatically expand reasoning blocks." data-i18n="[title]reasoning_auto_expand"> | ||
| 3793 | <input id="reasoning_auto_expand" type="checkbox" /> | ||
| 3794 | <small data-i18n="Auto-Expand Reasoning"> | ||
| 3795 | Auto-Expand Reasoning | ||
| 3796 | </small> | ||
| 3797 | </label> | ||
| 3792 | <label class="checkbox_label" for="reasoning_add_to_prompts" title="Add existing reasoning blocks to prompts. To add a new reasoning block, use the message edit menu." data-i18n="[title]reasoning_add_to_prompts"> | 3798 | <label class="checkbox_label" for="reasoning_add_to_prompts" title="Add existing reasoning blocks to prompts. To add a new reasoning block, use the message edit menu." data-i18n="[title]reasoning_add_to_prompts"> |
| 3793 | <input id="reasoning_add_to_prompts" type="checkbox" /> | 3799 | <input id="reasoning_add_to_prompts" type="checkbox" /> |
| 3794 | <small data-i18n="Add Reasoning to Prompts"> | 3800 | <small data-i18n="Add Reasoning to Prompts"> |
| @@ -6248,14 +6254,19 @@ | |||
| 6248 | </div> | 6254 | </div> |
| 6249 | </div> | 6255 | </div> |
| 6250 | <details class="mes_reasoning_details"> | 6256 | <details class="mes_reasoning_details"> |
| 6251 | <summary class="mes_reasoning_summary"> | 6257 | <summary class="mes_reasoning_summary flex-container"> |
| 6252 | <span data-i18n="Reasoning">Reasoning</span> | 6258 | <div class="mes_reasoning_header_block flex-container"> |
| 6253 | <div class="mes_reasoning_actions"> | 6259 | <div class="mes_reasoning_header flex-container"> |
| 6254 | <div class="mes_reasoning_edit_done mes_button fa-solid fa-check" title="Confirm" data-i18n="[title]Confirmedit"></div> | 6260 | <span class="mes_reasoning_header_title" data-i18n="Thought for some time">Thought for some time</span> |
| 6255 | <div class="mes_reasoning_edit_cancel mes_button fa-solid fa-xmark" title="Cancel edit" data-i18n="[title]Cancel edit"></div> | 6261 | <div class="mes_reasoning_arrow fa-solid fa-chevron-up"></div> |
| 6256 | <div class="mes_reasoning_edit mes_button fa-solid fa-pencil" title="Edit reasoning" data-i18n="[title]Edit reasoning"></div> | 6262 | </div> |
| 6263 | </div> | ||
| 6264 | <div class="mes_reasoning_actions flex-container"> | ||
| 6265 | <div class="mes_reasoning_edit_done menu_button edit_button fa-solid fa-check" title="Confirm" data-i18n="[title]Confirmedit"></div> | ||
| 6266 | <div class="mes_reasoning_delete menu_button edit_button fa-solid fa-trash-can" title="Remove reasoning" data-i18n="[title]Remove reasoning"></div> | ||
| 6267 | <div class="mes_reasoning_edit_cancel menu_button edit_button fa-solid fa-xmark" title="Cancel edit" data-i18n="[title]Cancel edit"></div> | ||
| 6257 | <div class="mes_reasoning_copy mes_button fa-solid fa-copy" title="Copy reasoning" data-i18n="[title]Copy reasoning"></div> | 6268 | <div class="mes_reasoning_copy mes_button fa-solid fa-copy" title="Copy reasoning" data-i18n="[title]Copy reasoning"></div> |
| 6258 | <div class="mes_reasoning_delete mes_button fa-solid fa-trash-can" title="Remove reasoning" data-i18n="[title]Remove reasoning"></div> | 6269 | <div class="mes_reasoning_edit mes_button fa-solid fa-pencil" title="Edit reasoning" data-i18n="[title]Edit reasoning"></div> |
| 6259 | </div> | 6270 | </div> |
| 6260 | </summary> | 6271 | </summary> |
| 6261 | <div class="mes_reasoning"></div> | 6272 | <div class="mes_reasoning"></div> |
| @@ -225,7 +225,7 @@ import { | |||
| 225 | instruct_presets, | 225 | instruct_presets, |
| 226 | selectContextPreset, | 226 | selectContextPreset, |
| 227 | } from './scripts/instruct-mode.js'; | 227 | } from './scripts/instruct-mode.js'; |
| 228 | import { initLocales, t } from './scripts/i18n.js'; | 228 | import { getCurrentLocale, initLocales, t } from './scripts/i18n.js'; |
| 229 | import { getFriendlyTokenizerName, getTokenCount, getTokenCountAsync, initTokenizers, saveTokenCache, TOKENIZER_SUPPORTED_KEY } from './scripts/tokenizers.js'; | 229 | import { getFriendlyTokenizerName, getTokenCount, getTokenCountAsync, initTokenizers, saveTokenCache, TOKENIZER_SUPPORTED_KEY } from './scripts/tokenizers.js'; |
| 230 | import { | 230 | import { |
| 231 | user_avatar, | 231 | user_avatar, |
| @@ -495,6 +495,7 @@ export const event_types = { | |||
| 495 | /** @deprecated The event is aliased to STREAM_TOKEN_RECEIVED. */ | 495 | /** @deprecated The event is aliased to STREAM_TOKEN_RECEIVED. */ |
| 496 | SMOOTH_STREAM_TOKEN_RECEIVED: 'stream_token_received', | 496 | SMOOTH_STREAM_TOKEN_RECEIVED: 'stream_token_received', |
| 497 | STREAM_TOKEN_RECEIVED: 'stream_token_received', | 497 | STREAM_TOKEN_RECEIVED: 'stream_token_received', |
| 498 | STREAM_REASONING_DONE: 'stream_reasoning_done', | ||
| 498 | FILE_ATTACHMENT_DELETED: 'file_attachment_deleted', | 499 | FILE_ATTACHMENT_DELETED: 'file_attachment_deleted', |
| 499 | WORLDINFO_FORCE_ACTIVATE: 'worldinfo_force_activate', | 500 | WORLDINFO_FORCE_ACTIVATE: 'worldinfo_force_activate', |
| 500 | OPEN_CHARACTER_LIBRARY: 'open_character_library', | 501 | OPEN_CHARACTER_LIBRARY: 'open_character_library', |
| @@ -2189,26 +2190,29 @@ function insertSVGIcon(mes, extra) { | |||
| 2189 | modelName = extra.api; | 2190 | modelName = extra.api; |
| 2190 | } | 2191 | } |
| 2191 | 2192 | ||
| 2192 | const image = new Image(); | 2193 | const insertOrReplaceSVG = (image, className, targetSelector, insertBefore) => { |
| 2193 | // Add classes for styling and identification | 2194 | image.onload = async function () { |
| 2194 | image.classList.add('icon-svg', 'timestamp-icon'); | 2195 | let existingSVG = insertBefore ? mes.find(targetSelector).prev(`.${className}`) : mes.find(targetSelector).next(`.${className}`); |
| 2195 | image.src = `/img/${modelName}.svg`; | 2196 | if (existingSVG.length) { |
| 2196 | image.title = `${extra?.api ? extra.api + ' - ' : ''}${extra?.model ?? ''}`; | 2197 | existingSVG.replaceWith(image); |
| 2197 | 2198 | } else { | |
| 2198 | image.onload = async function () { | 2199 | if (insertBefore) mes.find(targetSelector).before(image); |
| 2199 | // Check if an SVG already exists adjacent to the timestamp | 2200 | else mes.find(targetSelector).after(image); |
| 2200 | let existingSVG = mes.find('.timestamp').next('.timestamp-icon'); | 2201 | } |
| 2201 | 2202 | await SVGInject(image); | |
| 2202 | if (existingSVG.length) { | 2203 | }; |
| 2203 | // Replace existing SVG | 2204 | }; |
| 2204 | existingSVG.replaceWith(image); | ||
| 2205 | } else { | ||
| 2206 | // Append the new SVG if none exists | ||
| 2207 | mes.find('.timestamp').after(image); | ||
| 2208 | } | ||
| 2209 | 2205 | ||
| 2210 | await SVGInject(image); | 2206 | const createModelImage = (className, targetSelector, insertBefore) => { |
| 2207 | const image = new Image(); | ||
| 2208 | image.classList.add('icon-svg', className); | ||
| 2209 | image.src = `/img/${modelName}.svg`; | ||
| 2210 | image.title = `${extra?.api ? extra.api + ' - ' : ''}${extra?.model ?? ''}`; | ||
| 2211 | insertOrReplaceSVG(image, className, targetSelector, insertBefore); | ||
| 2211 | }; | 2212 | }; |
| 2213 | |||
| 2214 | createModelImage('timestamp-icon', '.timestamp'); | ||
| 2215 | createModelImage('thinking-icon', '.mes_reasoning_header_title', true); | ||
| 2212 | } | 2216 | } |
| 2213 | 2217 | ||
| 2214 | 2218 | ||
| @@ -2220,6 +2224,7 @@ function getMessageFromTemplate({ | |||
| 2220 | avatarImg, | 2224 | avatarImg, |
| 2221 | bias, | 2225 | bias, |
| 2222 | reasoning, | 2226 | reasoning, |
| 2227 | reasoningDuration, | ||
| 2223 | isSystem, | 2228 | isSystem, |
| 2224 | title, | 2229 | title, |
| 2225 | timerValue, | 2230 | timerValue, |
| @@ -2252,6 +2257,13 @@ function getMessageFromTemplate({ | |||
| 2252 | timerValue && mes.find('.mes_timer').attr('title', timerTitle).text(timerValue); | 2257 | timerValue && mes.find('.mes_timer').attr('title', timerTitle).text(timerValue); |
| 2253 | bookmarkLink && updateBookmarkDisplay(mes); | 2258 | bookmarkLink && updateBookmarkDisplay(mes); |
| 2254 | 2259 | ||
| 2260 | if (reasoning) { | ||
| 2261 | mes.addClass('reasoning'); | ||
| 2262 | } | ||
| 2263 | if (reasoningDuration) { | ||
| 2264 | updateReasoningTimeUI(mes.find('.mes_reasoning_header_title')[0], reasoningDuration, { forceEnd: true }); | ||
| 2265 | } | ||
| 2266 | |||
| 2255 | if (power_user.timestamp_model_icon && extra?.api) { | 2267 | if (power_user.timestamp_model_icon && extra?.api) { |
| 2256 | insertSVGIcon(mes, extra); | 2268 | insertSVGIcon(mes, extra); |
| 2257 | } | 2269 | } |
| @@ -2269,6 +2281,7 @@ export function updateMessageBlock(messageId, message) { | |||
| 2269 | const text = message?.extra?.display_text ?? message.mes; | 2281 | const text = message?.extra?.display_text ?? message.mes; |
| 2270 | messageElement.find('.mes_text').html(messageFormatting(text, message.name, message.is_system, message.is_user, messageId, {}, false)); | 2282 | messageElement.find('.mes_text').html(messageFormatting(text, message.name, message.is_system, message.is_user, messageId, {}, false)); |
| 2271 | messageElement.find('.mes_reasoning').html(messageFormatting(message.extra?.reasoning ?? '', '', false, false, messageId, {}, true)); | 2283 | messageElement.find('.mes_reasoning').html(messageFormatting(message.extra?.reasoning ?? '', '', false, false, messageId, {}, true)); |
| 2284 | messageElement.toggleClass('reasoning', !!message.extra?.reasoning); | ||
| 2272 | addCopyToCodeBlocks(messageElement); | 2285 | addCopyToCodeBlocks(messageElement); |
| 2273 | appendMediaToMessage(message, messageElement); | 2286 | appendMediaToMessage(message, messageElement); |
| 2274 | } | 2287 | } |
| @@ -2439,6 +2452,7 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll | |||
| 2439 | avatarImg: avatarImg, | 2452 | avatarImg: avatarImg, |
| 2440 | bias: bias, | 2453 | bias: bias, |
| 2441 | reasoning: reasoning, | 2454 | reasoning: reasoning, |
| 2455 | reasoningDuration: mes.extra?.reasoning_duration, | ||
| 2442 | isSystem: isSystem, | 2456 | isSystem: isSystem, |
| 2443 | title: title, | 2457 | title: title, |
| 2444 | bookmarkLink: bookmarkLink, | 2458 | bookmarkLink: bookmarkLink, |
| @@ -3108,8 +3122,12 @@ class StreamingProcessor { | |||
| 3108 | this.messageDom = null; | 3122 | this.messageDom = null; |
| 3109 | this.messageTextDom = null; | 3123 | this.messageTextDom = null; |
| 3110 | this.messageTimerDom = null; | 3124 | this.messageTimerDom = null; |
| 3125 | /** @type {HTMLElement} */ | ||
| 3111 | this.messageTokenCounterDom = null; | 3126 | this.messageTokenCounterDom = null; |
| 3127 | /** @type {HTMLElement} */ | ||
| 3112 | this.messageReasoningDom = null; | 3128 | this.messageReasoningDom = null; |
| 3129 | /** @type {HTMLElement} */ | ||
| 3130 | this.messageReasoningHeaderDom = null; | ||
| 3113 | /** @type {HTMLTextAreaElement} */ | 3131 | /** @type {HTMLTextAreaElement} */ |
| 3114 | this.sendTextarea = document.querySelector('#send_textarea'); | 3132 | this.sendTextarea = document.querySelector('#send_textarea'); |
| 3115 | this.type = type; | 3133 | this.type = type; |
| @@ -3126,6 +3144,15 @@ class StreamingProcessor { | |||
| 3126 | this.messageLogprobs = []; | 3144 | this.messageLogprobs = []; |
| 3127 | this.toolCalls = []; | 3145 | this.toolCalls = []; |
| 3128 | this.reasoning = ''; | 3146 | this.reasoning = ''; |
| 3147 | this.reasoningStartTime = null; | ||
| 3148 | this.reasoningEndTime = null; | ||
| 3149 | } | ||
| 3150 | |||
| 3151 | #reasoningDuration() { | ||
| 3152 | if (this.reasoningStartTime && this.reasoningEndTime) { | ||
| 3153 | return (this.reasoningEndTime - this.reasoningStartTime); | ||
| 3154 | } | ||
| 3155 | return null; | ||
| 3129 | } | 3156 | } |
| 3130 | 3157 | ||
| 3131 | #checkDomElements(messageId) { | 3158 | #checkDomElements(messageId) { |
| @@ -3135,6 +3162,7 @@ class StreamingProcessor { | |||
| 3135 | this.messageTimerDom = this.messageDom?.querySelector('.mes_timer'); | 3162 | this.messageTimerDom = this.messageDom?.querySelector('.mes_timer'); |
| 3136 | this.messageTokenCounterDom = this.messageDom?.querySelector('.tokenCounterDisplay'); | 3163 | this.messageTokenCounterDom = this.messageDom?.querySelector('.tokenCounterDisplay'); |
| 3137 | this.messageReasoningDom = this.messageDom?.querySelector('.mes_reasoning'); | 3164 | this.messageReasoningDom = this.messageDom?.querySelector('.mes_reasoning'); |
| 3165 | this.messageReasoningHeaderDom = this.messageDom?.querySelector('.mes_reasoning_header_title'); | ||
| 3138 | } | 3166 | } |
| 3139 | } | 3167 | } |
| 3140 | 3168 | ||
| @@ -3182,7 +3210,7 @@ class StreamingProcessor { | |||
| 3182 | return messageId; | 3210 | return messageId; |
| 3183 | } | 3211 | } |
| 3184 | 3212 | ||
| 3185 | onProgressStreaming(messageId, text, isFinal) { | 3213 | async onProgressStreaming(messageId, text, isFinal) { |
| 3186 | const isImpersonate = this.type == 'impersonate'; | 3214 | const isImpersonate = this.type == 'impersonate'; |
| 3187 | const isContinue = this.type == 'continue'; | 3215 | const isContinue = this.type == 'continue'; |
| 3188 | 3216 | ||
| @@ -3209,6 +3237,8 @@ class StreamingProcessor { | |||
| 3209 | this.sendTextarea.dispatchEvent(new Event('input', { bubbles: true })); | 3237 | this.sendTextarea.dispatchEvent(new Event('input', { bubbles: true })); |
| 3210 | } | 3238 | } |
| 3211 | else { | 3239 | else { |
| 3240 | const mesChanged = chat[messageId]['mes'] !== processedText; | ||
| 3241 | |||
| 3212 | this.#checkDomElements(messageId); | 3242 | this.#checkDomElements(messageId); |
| 3213 | this.#updateMessageBlockVisibility(); | 3243 | this.#updateMessageBlockVisibility(); |
| 3214 | const currentTime = new Date(); | 3244 | const currentTime = new Date(); |
| @@ -3221,11 +3251,25 @@ class StreamingProcessor { | |||
| 3221 | } | 3251 | } |
| 3222 | 3252 | ||
| 3223 | if (this.reasoning) { | 3253 | if (this.reasoning) { |
| 3224 | chat[messageId]['extra']['reasoning'] = power_user.trim_spaces ? this.reasoning.trim() : this.reasoning; | 3254 | const reasoning = power_user.trim_spaces ? this.reasoning.trim() : this.reasoning; |
| 3255 | const reasoningChanged = chat[messageId]['extra']['reasoning'] !== reasoning; | ||
| 3256 | chat[messageId]['extra']['reasoning'] = reasoning; | ||
| 3257 | |||
| 3258 | if (reasoningChanged && this.reasoningStartTime === null) { | ||
| 3259 | this.reasoningStartTime = Date.now(); | ||
| 3260 | } | ||
| 3261 | if (!reasoningChanged && mesChanged && this.reasoningStartTime !== null && this.reasoningEndTime === null) { | ||
| 3262 | this.reasoningEndTime = Date.now(); | ||
| 3263 | } | ||
| 3264 | await this.#updateReasoningTime(messageId); | ||
| 3265 | |||
| 3225 | if (this.messageReasoningDom instanceof HTMLElement) { | 3266 | if (this.messageReasoningDom instanceof HTMLElement) { |
| 3226 | const formattedReasoning = messageFormatting(this.reasoning, '', false, false, messageId, {}, true); | 3267 | const formattedReasoning = messageFormatting(this.reasoning, '', false, false, messageId, {}, true); |
| 3227 | this.messageReasoningDom.innerHTML = formattedReasoning; | 3268 | this.messageReasoningDom.innerHTML = formattedReasoning; |
| 3228 | } | 3269 | } |
| 3270 | if (this.messageDom instanceof HTMLElement) { | ||
| 3271 | this.messageDom.classList.add('reasoning'); | ||
| 3272 | } | ||
| 3229 | } | 3273 | } |
| 3230 | 3274 | ||
| 3231 | // Don't waste time calculating token count for streaming | 3275 | // Don't waste time calculating token count for streaming |
| @@ -3271,11 +3315,24 @@ class StreamingProcessor { | |||
| 3271 | } | 3315 | } |
| 3272 | } | 3316 | } |
| 3273 | 3317 | ||
| 3318 | async #updateReasoningTime(messageId, { forceEnd = false } = {}) { | ||
| 3319 | const duration = this.#reasoningDuration(); | ||
| 3320 | chat[messageId]['extra']['reasoning_duration'] = duration; | ||
| 3321 | updateReasoningTimeUI(this.messageReasoningHeaderDom, duration, { forceEnd: forceEnd }); | ||
| 3322 | await eventSource.emit(event_types.STREAM_REASONING_DONE, this.reasoning, duration); | ||
| 3323 | } | ||
| 3324 | |||
| 3274 | async onFinishStreaming(messageId, text) { | 3325 | async onFinishStreaming(messageId, text) { |
| 3275 | this.hideMessageButtons(this.messageId); | 3326 | this.hideMessageButtons(this.messageId); |
| 3276 | this.onProgressStreaming(messageId, text, true); | 3327 | await this.onProgressStreaming(messageId, text, true); |
| 3277 | addCopyToCodeBlocks($(`#chat .mes[mesid="${messageId}"]`)); | 3328 | addCopyToCodeBlocks($(`#chat .mes[mesid="${messageId}"]`)); |
| 3278 | 3329 | ||
| 3330 | // Ensure reasoning finish time is recorded if not already | ||
| 3331 | if (this.reasoningStartTime !== null && this.reasoningEndTime === null) { | ||
| 3332 | this.reasoningEndTime = Date.now(); | ||
| 3333 | await this.#updateReasoningTime(messageId, { forceEnd: true }); | ||
| 3334 | } | ||
| 3335 | |||
| 3279 | if (Array.isArray(this.swipes) && this.swipes.length > 0) { | 3336 | if (Array.isArray(this.swipes) && this.swipes.length > 0) { |
| 3280 | const message = chat[messageId]; | 3337 | const message = chat[messageId]; |
| 3281 | const swipeInfo = { | 3338 | const swipeInfo = { |
| @@ -3377,7 +3434,7 @@ class StreamingProcessor { | |||
| 3377 | } | 3434 | } |
| 3378 | this.reasoning = getRegexedString(state?.reasoning ?? '', regex_placement.REASONING); | 3435 | this.reasoning = getRegexedString(state?.reasoning ?? '', regex_placement.REASONING); |
| 3379 | await eventSource.emit(event_types.STREAM_TOKEN_RECEIVED, text); | 3436 | await eventSource.emit(event_types.STREAM_TOKEN_RECEIVED, text); |
| 3380 | await sw.tick(() => this.onProgressStreaming(this.messageId, this.continueMessage + text)); | 3437 | await sw.tick(async () => await this.onProgressStreaming(this.messageId, this.continueMessage + text)); |
| 3381 | } | 3438 | } |
| 3382 | const seconds = (timestamps[timestamps.length - 1] - timestamps[0]) / 1000; | 3439 | const seconds = (timestamps[timestamps.length - 1] - timestamps[0]) / 1000; |
| 3383 | console.warn(`Stream stats: ${timestamps.length} tokens, ${seconds.toFixed(2)} seconds, rate: ${Number(timestamps.length / seconds).toFixed(2)} TPS`); | 3440 | console.warn(`Stream stats: ${timestamps.length} tokens, ${seconds.toFixed(2)} seconds, rate: ${Number(timestamps.length / seconds).toFixed(2)} TPS`); |
| @@ -5738,6 +5795,25 @@ function extractReasoningFromData(data) { | |||
| 5738 | } | 5795 | } |
| 5739 | 5796 | ||
| 5740 | /** | 5797 | /** |
| 5798 | * Updates the Reasoning controls | ||
| 5799 | * @param {HTMLElement} element The element to update | ||
| 5800 | * @param {number?} duration The duration of the reasoning in milliseconds | ||
| 5801 | * @param {object} [options={}] Options for the function | ||
| 5802 | * @param {boolean} [options.forceEnd=false] If true, there will be no "Thinking..." when no duration exists | ||
| 5803 | */ | ||
| 5804 | function updateReasoningTimeUI(element, duration, { forceEnd = false } = {}) { | ||
| 5805 | if (duration) { | ||
| 5806 | const durationStr = moment.duration(duration).locale(getCurrentLocale()).humanize({ s: 50, ss: 9 }); | ||
| 5807 | element.textContent = t`Thought for ${durationStr}`; | ||
| 5808 | } else if (forceEnd) { | ||
| 5809 | element.textContent = t`Thought for some time`; | ||
| 5810 | } else { | ||
| 5811 | element.textContent = t`Thinking...`; | ||
| 5812 | } | ||
| 5813 | } | ||
| 5814 | |||
| 5815 | |||
| 5816 | /** | ||
| 5741 | * Extracts multiswipe swipes from the response data. | 5817 | * Extracts multiswipe swipes from the response data. |
| 5742 | * @param {Object} data Response data | 5818 | * @param {Object} data Response data |
| 5743 | * @param {string} type Type of generation | 5819 | * @param {string} type Type of generation |
| @@ -7118,8 +7194,10 @@ export function setGenerationParamsFromPreset(preset) { | |||
| 7118 | // Common code for message editor done and auto-save | 7194 | // Common code for message editor done and auto-save |
| 7119 | function updateMessage(div) { | 7195 | function updateMessage(div) { |
| 7120 | const mesBlock = div.closest('.mes_block'); | 7196 | const mesBlock = div.closest('.mes_block'); |
| 7121 | let text = mesBlock.find('.edit_textarea').val(); | 7197 | let text = mesBlock.find('.edit_textarea').val() |
| 7122 | const mes = chat[this_edit_mes_id]; | 7198 | ?? mesBlock.find('.mes_text').text(); |
| 7199 | const mesElement = div.closest('.mes'); | ||
| 7200 | const mes = chat[mesElement.attr('mesid')]; | ||
| 7123 | 7201 | ||
| 7124 | let regexPlacement; | 7202 | let regexPlacement; |
| 7125 | if (mes.is_user) { | 7203 | if (mes.is_user) { |
| @@ -7238,6 +7316,11 @@ async function messageEditDone(div) { | |||
| 7238 | appendMediaToMessage(mes, div.closest('.mes')); | 7316 | appendMediaToMessage(mes, div.closest('.mes')); |
| 7239 | addCopyToCodeBlocks(div.closest('.mes')); | 7317 | addCopyToCodeBlocks(div.closest('.mes')); |
| 7240 | 7318 | ||
| 7319 | const reasoningEditDone = mesBlock.find('.mes_reasoning_edit_done:visible'); | ||
| 7320 | if (reasoningEditDone.length > 0) { | ||
| 7321 | reasoningEditDone.trigger('click'); | ||
| 7322 | } | ||
| 7323 | |||
| 7241 | await eventSource.emit(event_types.MESSAGE_UPDATED, this_edit_mes_id); | 7324 | await eventSource.emit(event_types.MESSAGE_UPDATED, this_edit_mes_id); |
| 7242 | this_edit_mes_id = undefined; | 7325 | this_edit_mes_id = undefined; |
| 7243 | await saveChatConditional(); | 7326 | await saveChatConditional(); |
| @@ -10745,6 +10828,12 @@ jQuery(async function () { | |||
| 10745 | var edit_mes_id = $(this).closest('.mes').attr('mesid'); | 10828 | var edit_mes_id = $(this).closest('.mes').attr('mesid'); |
| 10746 | this_edit_mes_id = edit_mes_id; | 10829 | this_edit_mes_id = edit_mes_id; |
| 10747 | 10830 | ||
| 10831 | // Also edit reasoning, if it exists | ||
| 10832 | const reasoningEdit = $(this).closest('.mes_block').find('.mes_reasoning_edit:visible'); | ||
| 10833 | if (reasoningEdit.length > 0) { | ||
| 10834 | reasoningEdit.trigger('click'); | ||
| 10835 | } | ||
| 10836 | |||
| 10748 | var text = chat[edit_mes_id]['mes']; | 10837 | var text = chat[edit_mes_id]['mes']; |
| 10749 | if (chat[edit_mes_id]['is_user']) { | 10838 | if (chat[edit_mes_id]['is_user']) { |
| 10750 | this_edit_mes_chname = name1; | 10839 | this_edit_mes_chname = name1; |
| @@ -10783,6 +10872,18 @@ jQuery(async function () { | |||
| 10783 | } | 10872 | } |
| 10784 | }); | 10873 | }); |
| 10785 | 10874 | ||
| 10875 | $(document).on('click', '.mes_reasoning_header', function () { | ||
| 10876 | // If we are in message edit mode and reasoning area is closed, a click opens and edits it | ||
| 10877 | const mes = $(this).closest('.mes'); | ||
| 10878 | const mesEditArea = mes.find('#curEditTextarea'); | ||
| 10879 | if (mesEditArea.length) { | ||
| 10880 | const summary = $(mes).find('.mes_reasoning_summary'); | ||
| 10881 | if (!summary.attr('open')) { | ||
| 10882 | summary.find('.mes_reasoning_edit').trigger('click'); | ||
| 10883 | } | ||
| 10884 | } | ||
| 10885 | }); | ||
| 10886 | |||
| 10786 | $(document).on('input', '#curEditTextarea', function () { | 10887 | $(document).on('input', '#curEditTextarea', function () { |
| 10787 | if (power_user.auto_save_msg_edits === true) { | 10888 | if (power_user.auto_save_msg_edits === true) { |
| 10788 | messageEditAuto($(this)); | 10889 | messageEditAuto($(this)); |
| @@ -10878,6 +10979,11 @@ jQuery(async function () { | |||
| 10878 | appendMediaToMessage(chat[this_edit_mes_id], $(this).closest('.mes')); | 10979 | appendMediaToMessage(chat[this_edit_mes_id], $(this).closest('.mes')); |
| 10879 | addCopyToCodeBlocks($(this).closest('.mes')); | 10980 | addCopyToCodeBlocks($(this).closest('.mes')); |
| 10880 | 10981 | ||
| 10982 | const reasoningEditDone = $(this).closest('.mes_block').find('.mes_reasoning_edit_cancel:visible'); | ||
| 10983 | if (reasoningEditDone.length > 0) { | ||
| 10984 | reasoningEditDone.trigger('click'); | ||
| 10985 | } | ||
| 10986 | |||
| 10881 | await eventSource.emit(event_types.MESSAGE_UPDATED, this_edit_mes_id); | 10987 | await eventSource.emit(event_types.MESSAGE_UPDATED, this_edit_mes_id); |
| 10882 | this_edit_mes_id = undefined; | 10988 | this_edit_mes_id = undefined; |
| 10883 | }); | 10989 | }); |
| @@ -11332,6 +11438,17 @@ jQuery(async function () { | |||
| 11332 | } | 11438 | } |
| 11333 | }); | 11439 | }); |
| 11334 | 11440 | ||
| 11441 | $(document).on('click', '.mes_reasoning_summary', function () { | ||
| 11442 | // If you toggle summary header while editing reasoning, yup - we just cancel it | ||
| 11443 | $(this).closest('.mes').find('.mes_reasoning_edit_cancel:visible').trigger('click'); | ||
| 11444 | }); | ||
| 11445 | |||
| 11446 | $(document).on('click', '.mes_reasoning_details', function (e) { | ||
| 11447 | if (!e.target.closest('.mes_reasoning_actions') && !e.target.closest('.mes_reasoning_header')) { | ||
| 11448 | e.preventDefault(); | ||
| 11449 | } | ||
| 11450 | }); | ||
| 11451 | |||
| 11335 | $(document).keyup(function (e) { | 11452 | $(document).keyup(function (e) { |
| 11336 | if (e.key === 'Escape') { | 11453 | if (e.key === 'Escape') { |
| 11337 | const isEditVisible = $('#curEditTextarea').is(':visible') || $('.reasoning_edit_textarea').length > 0; | 11454 | const isEditVisible = $('#curEditTextarea').is(':visible') || $('.reasoning_edit_textarea').length > 0; |
| @@ -1063,12 +1063,19 @@ export function initRossMods() { | |||
| 1063 | // Ctrl+Enter for Regeneration Last Response. If editing, accept the edits instead | 1063 | // Ctrl+Enter for Regeneration Last Response. If editing, accept the edits instead |
| 1064 | if (event.ctrlKey && event.key == 'Enter') { | 1064 | if (event.ctrlKey && event.key == 'Enter') { |
| 1065 | const editMesDone = $('.mes_edit_done:visible'); | 1065 | const editMesDone = $('.mes_edit_done:visible'); |
| 1066 | const reasoningMesDone = $('.mes_reasoning_edit_done:visible'); | ||
| 1066 | if (editMesDone.length > 0) { | 1067 | if (editMesDone.length > 0) { |
| 1067 | console.debug('Accepting edits with Ctrl+Enter'); | 1068 | console.debug('Accepting edits with Ctrl+Enter'); |
| 1068 | $('#send_textarea').focus(); | 1069 | $('#send_textarea').trigger('focus'); |
| 1069 | editMesDone.trigger('click'); | 1070 | editMesDone.trigger('click'); |
| 1070 | return; | 1071 | return; |
| 1071 | } else if (is_send_press == false) { | 1072 | } else if (reasoningMesDone.length > 0) { |
| 1073 | console.debug('Accepting edits with Ctrl+Enter'); | ||
| 1074 | $('#send_textarea').trigger('focus'); | ||
| 1075 | reasoningMesDone.trigger('click'); | ||
| 1076 | return; | ||
| 1077 | } | ||
| 1078 | else if (is_send_press == false) { | ||
| 1072 | const skipConfirmKey = 'RegenerateWithCtrlEnter'; | 1079 | const skipConfirmKey = 'RegenerateWithCtrlEnter'; |
| 1073 | const skipConfirm = LoadLocalBool(skipConfirmKey); | 1080 | const skipConfirm = LoadLocalBool(skipConfirmKey); |
| 1074 | function doRegenerate() { | 1081 | function doRegenerate() { |
| @@ -1082,7 +1089,9 @@ export function initRossMods() { | |||
| 1082 | let regenerateWithCtrlEnter = false; | 1089 | let regenerateWithCtrlEnter = false; |
| 1083 | const result = await Popup.show.confirm('Regenerate Message', 'Are you sure you want to regenerate the latest message?', { | 1090 | const result = await Popup.show.confirm('Regenerate Message', 'Are you sure you want to regenerate the latest message?', { |
| 1084 | customInputs: [{ id: 'regenerateWithCtrlEnter', label: 'Don\'t ask again' }], | 1091 | customInputs: [{ id: 'regenerateWithCtrlEnter', label: 'Don\'t ask again' }], |
| 1085 | onClose: (popup) => regenerateWithCtrlEnter = popup.inputResults.get('regenerateWithCtrlEnter') ?? false, | 1092 | onClose: (popup) => { |
| 1093 | regenerateWithCtrlEnter = popup.inputResults.get('regenerateWithCtrlEnter') ?? false; | ||
| 1094 | }, | ||
| 1086 | }); | 1095 | }); |
| 1087 | if (!result) { | 1096 | if (!result) { |
| 1088 | return; | 1097 | return; |
| @@ -256,6 +256,7 @@ let power_user = { | |||
| 256 | reasoning: { | 256 | reasoning: { |
| 257 | auto_parse: false, | 257 | auto_parse: false, |
| 258 | add_to_prompts: false, | 258 | add_to_prompts: false, |
| 259 | auto_expand: false, | ||
| 259 | prefix: '<think>\n', | 260 | prefix: '<think>\n', |
| 260 | suffix: '\n</think>', | 261 | suffix: '\n</think>', |
| 261 | separator: '\n\n', | 262 | separator: '\n\n', |
| @@ -23,6 +23,18 @@ function getMessageFromJquery(element) { | |||
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | /** | 25 | /** |
| 26 | * Toggles the auto-expand state of reasoning blocks. | ||
| 27 | */ | ||
| 28 | function toggleReasoningAutoExpand() { | ||
| 29 | const reasoningBlocks = document.querySelectorAll('details.mes_reasoning_details'); | ||
| 30 | reasoningBlocks.forEach((block) => { | ||
| 31 | if (block instanceof HTMLDetailsElement) { | ||
| 32 | block.open = power_user.reasoning.auto_expand; | ||
| 33 | } | ||
| 34 | }); | ||
| 35 | } | ||
| 36 | |||
| 37 | /** | ||
| 26 | * Helper class for adding reasoning to messages. | 38 | * Helper class for adding reasoning to messages. |
| 27 | * Keeps track of the number of reasoning additions. | 39 | * Keeps track of the number of reasoning additions. |
| 28 | */ | 40 | */ |
| @@ -118,6 +130,13 @@ function loadReasoningSettings() { | |||
| 118 | power_user.reasoning.auto_parse = !!$(this).prop('checked'); | 130 | power_user.reasoning.auto_parse = !!$(this).prop('checked'); |
| 119 | saveSettingsDebounced(); | 131 | saveSettingsDebounced(); |
| 120 | }); | 132 | }); |
| 133 | |||
| 134 | $('#reasoning_auto_expand').prop('checked', power_user.reasoning.auto_expand); | ||
| 135 | $('#reasoning_auto_expand').on('change', function () { | ||
| 136 | power_user.reasoning.auto_expand = !!$(this).prop('checked'); | ||
| 137 | toggleReasoningAutoExpand(); | ||
| 138 | saveSettingsDebounced(); | ||
| 139 | }); | ||
| 121 | } | 140 | } |
| 122 | 141 | ||
| 123 | function registerReasoningSlashCommands() { | 142 | function registerReasoningSlashCommands() { |
| @@ -288,6 +307,8 @@ function setReasoningEventHandlers() { | |||
| 288 | await saveChatConditional(); | 307 | await saveChatConditional(); |
| 289 | updateMessageBlock(messageId, message); | 308 | updateMessageBlock(messageId, message); |
| 290 | textarea.remove(); | 309 | textarea.remove(); |
| 310 | |||
| 311 | messageBlock.find('.mes_edit_done:visible').trigger('click'); | ||
| 291 | }); | 312 | }); |
| 292 | 313 | ||
| 293 | $(document).on('click', '.mes_reasoning_edit_cancel', function (e) { | 314 | $(document).on('click', '.mes_reasoning_edit_cancel', function (e) { |
| @@ -297,6 +318,8 @@ function setReasoningEventHandlers() { | |||
| 297 | const { messageBlock } = getMessageFromJquery(this); | 318 | const { messageBlock } = getMessageFromJquery(this); |
| 298 | const textarea = messageBlock.find('.reasoning_edit_textarea'); | 319 | const textarea = messageBlock.find('.reasoning_edit_textarea'); |
| 299 | textarea.remove(); | 320 | textarea.remove(); |
| 321 | |||
| 322 | messageBlock.find('.mes_reasoning_edit_cancel:visible').trigger('click'); | ||
| 300 | }); | 323 | }); |
| 301 | 324 | ||
| 302 | $(document).on('click', '.mes_edit_add_reasoning', async function () { | 325 | $(document).on('click', '.mes_edit_add_reasoning', async function () { |
| @@ -311,9 +334,8 @@ function setReasoningEventHandlers() { | |||
| 311 | } | 334 | } |
| 312 | 335 | ||
| 313 | message.extra.reasoning = PromptReasoning.REASONING_PLACEHOLDER; | 336 | message.extra.reasoning = PromptReasoning.REASONING_PLACEHOLDER; |
| 314 | await saveChatConditional(); | ||
| 315 | closeMessageEditor(); | ||
| 316 | updateMessageBlock(messageId, message); | 337 | updateMessageBlock(messageId, message); |
| 338 | await saveChatConditional(); | ||
| 317 | }); | 339 | }); |
| 318 | 340 | ||
| 319 | $(document).on('click', '.mes_reasoning_delete', async function (e) { | 341 | $(document).on('click', '.mes_reasoning_delete', async function (e) { |
| @@ -441,6 +463,7 @@ function registerReasoningAppEvents() { | |||
| 441 | 463 | ||
| 442 | export function initReasoning() { | 464 | export function initReasoning() { |
| 443 | loadReasoningSettings(); | 465 | loadReasoningSettings(); |
| 466 | toggleReasoningAutoExpand(); | ||
| 444 | setReasoningEventHandlers(); | 467 | setReasoningEventHandlers(); |
| 445 | registerReasoningSlashCommands(); | 468 | registerReasoningSlashCommands(); |
| 446 | registerReasoningMacros(); | 469 | registerReasoningMacros(); |
| @@ -106,6 +106,8 @@ | |||
| 106 | --tool-cool-color-picker-btn-bg: transparent; | 106 | --tool-cool-color-picker-btn-bg: transparent; |
| 107 | --tool-cool-color-picker-btn-border-color: transparent; | 107 | --tool-cool-color-picker-btn-border-color: transparent; |
| 108 | 108 | ||
| 109 | --mes-right-spacing: 30px; | ||
| 110 | |||
| 109 | --avatar-base-height: 50px; | 111 | --avatar-base-height: 50px; |
| 110 | --avatar-base-width: 50px; | 112 | --avatar-base-width: 50px; |
| 111 | --avatar-base-border-radius: 2px; | 113 | --avatar-base-border-radius: 2px; |
| @@ -342,18 +344,59 @@ input[type='checkbox']:focus-visible { | |||
| 342 | 344 | ||
| 343 | .mes_reasoning { | 345 | .mes_reasoning { |
| 344 | display: block; | 346 | display: block; |
| 345 | border: 1px solid var(--SmartThemeBorderColor); | 347 | border-left: 2px solid var(--SmartThemeEmColor); |
| 346 | background-color: var(--black30a); | 348 | border-radius: 2px; |
| 347 | border-radius: 5px; | ||
| 348 | padding: 5px; | 349 | padding: 5px; |
| 349 | margin: 5px 0; | 350 | padding-left: 14px; |
| 351 | margin-bottom: 0.5em; | ||
| 350 | overflow-y: auto; | 352 | overflow-y: auto; |
| 353 | color: var(--SmartThemeEmColor); | ||
| 354 | } | ||
| 355 | |||
| 356 | .mes_reasoning_details { | ||
| 357 | margin-right: var(--mes-right-spacing); | ||
| 358 | } | ||
| 359 | |||
| 360 | .mes_reasoning_details .mes_reasoning_summary { | ||
| 361 | margin-right: calc(var(--mes-right-spacing) * -1); | ||
| 362 | } | ||
| 363 | |||
| 364 | .mes_reasoning *:last-child { | ||
| 365 | margin-bottom: 0; | ||
| 366 | } | ||
| 367 | |||
| 368 | .mes_reasoning em, | ||
| 369 | .mes_reasoning i, | ||
| 370 | .mes_reasoning u, | ||
| 371 | .mes_reasoning q, | ||
| 372 | .mes_reasoning blockquote { | ||
| 373 | filter: saturate(0.5); | ||
| 374 | } | ||
| 375 | |||
| 376 | .mes_reasoning_details .mes_reasoning em { | ||
| 377 | color: color-mix(in srgb, var(--SmartThemeEmColor) 67%, var(--SmartThemeBlurTintColor) 33%) | ||
| 378 | } | ||
| 379 | |||
| 380 | .mes_reasoning_header_block { | ||
| 381 | flex-grow: 1; | ||
| 351 | } | 382 | } |
| 352 | 383 | ||
| 353 | .mes_reasoning_summary { | 384 | .mes_reasoning_header { |
| 354 | cursor: pointer; | 385 | cursor: pointer; |
| 355 | position: relative; | 386 | position: relative; |
| 356 | margin: 2px; | 387 | user-select: none; |
| 388 | margin: 0.5em 2px; | ||
| 389 | padding: 7px 14px; | ||
| 390 | padding-right: calc(0.7em + 14px); | ||
| 391 | border-radius: 10px; | ||
| 392 | background-color: var(--grey30); | ||
| 393 | font-size: calc(var(--mainFontSize) * 0.9); | ||
| 394 | align-items: baseline; | ||
| 395 | } | ||
| 396 | |||
| 397 | /* TWIMC: Remove with custom CSS to show the icon */ | ||
| 398 | .mes_reasoning_header > .icon-svg { | ||
| 399 | display: none; | ||
| 357 | } | 400 | } |
| 358 | 401 | ||
| 359 | @supports not selector(:has(*)) { | 402 | @supports not selector(:has(*)) { |
| @@ -365,27 +408,27 @@ input[type='checkbox']:focus-visible { | |||
| 365 | .mes_bias:empty, | 408 | .mes_bias:empty, |
| 366 | .mes_reasoning:empty, | 409 | .mes_reasoning:empty, |
| 367 | .mes_reasoning_details:has(.mes_reasoning:empty), | 410 | .mes_reasoning_details:has(.mes_reasoning:empty), |
| 368 | .mes_block:has(.edit_textarea) .mes_reasoning_details, | ||
| 369 | .mes_reasoning_details:not([open]) .mes_reasoning_actions, | 411 | .mes_reasoning_details:not([open]) .mes_reasoning_actions, |
| 370 | .mes_reasoning_details:has(.reasoning_edit_textarea) .mes_reasoning, | 412 | .mes_reasoning_details:has(.reasoning_edit_textarea) .mes_reasoning, |
| 371 | .mes_reasoning_details:not(:has(.reasoning_edit_textarea)) .mes_reasoning_actions .mes_button.mes_reasoning_edit_done, | 413 | .mes_reasoning_details:has(.reasoning_edit_textarea) .mes_reasoning_header, |
| 372 | .mes_reasoning_details:not(:has(.reasoning_edit_textarea)) .mes_reasoning_actions .mes_button.mes_reasoning_edit_cancel, | 414 | .mes_reasoning_details:not(:has(.reasoning_edit_textarea)) .mes_reasoning_actions .edit_button, |
| 373 | .mes_reasoning_details:has(.reasoning_edit_textarea) .mes_reasoning_actions .mes_button:not(.mes_reasoning_edit_done, .mes_reasoning_edit_cancel) { | 415 | .mes_reasoning_details:has(.reasoning_edit_textarea) .mes_reasoning_actions .mes_button:not(.edit_button), |
| 416 | .mes_block:has(.edit_textarea):has(.reasoning_edit_textarea) .mes_reasoning_actions { | ||
| 374 | display: none; | 417 | display: none; |
| 375 | } | 418 | } |
| 376 | 419 | ||
| 377 | .mes_reasoning_actions { | 420 | .mes_reasoning_details .mes_reasoning_arrow { |
| 378 | position: absolute; | 421 | position: absolute; |
| 379 | right: 0; | 422 | top: 50%; |
| 380 | top: 0; | 423 | right: 7px; |
| 424 | transform: translateY(-50%); | ||
| 425 | font-size: calc(var(--mainFontSize) * 0.7); | ||
| 426 | width: calc(var(--mainFontSize) * 0.7); | ||
| 427 | height: calc(var(--mainFontSize) * 0.7); | ||
| 428 | } | ||
| 381 | 429 | ||
| 382 | display: flex; | 430 | .mes_reasoning_details:not([open]) .mes_reasoning_arrow { |
| 383 | gap: 4px; | 431 | transform: translateY(-50%) rotate(180deg); |
| 384 | flex-wrap: nowrap; | ||
| 385 | justify-content: flex-end; | ||
| 386 | transition: all 200ms; | ||
| 387 | overflow-x: hidden; | ||
| 388 | padding: 1px; | ||
| 389 | } | 432 | } |
| 390 | 433 | ||
| 391 | .mes_reasoning_summary>span { | 434 | .mes_reasoning_summary>span { |
| @@ -1100,13 +1143,8 @@ body .panelControlBar { | |||
| 1100 | /*only affects bubblechat to make it sit nicely at the bottom*/ | 1143 | /*only affects bubblechat to make it sit nicely at the bottom*/ |
| 1101 | } | 1144 | } |
| 1102 | 1145 | ||
| 1103 | .last_mes:has(.mes_text:empty):has(.mes_reasoning_details[open]) .mes_reasoning:not(:empty) { | 1146 | .last_mes:has(.mes_text:empty):has(.mes_reasoning_details) .mes_reasoning:not(:empty) { |
| 1104 | margin-bottom: 30px; | 1147 | margin-bottom: var(--mes-right-spacing); |
| 1105 | } | ||
| 1106 | |||
| 1107 | .last_mes .mes_reasoning, | ||
| 1108 | .last_mes .mes_text { | ||
| 1109 | padding-right: 30px; | ||
| 1110 | } | 1148 | } |
| 1111 | 1149 | ||
| 1112 | /* SWIPE RELATED STYLES*/ | 1150 | /* SWIPE RELATED STYLES*/ |
| @@ -1330,6 +1368,7 @@ body.swipeAllMessages .mes:not(.last_mes) .swipes-counter { | |||
| 1330 | padding-left: 0; | 1368 | padding-left: 0; |
| 1331 | padding-top: 5px; | 1369 | padding-top: 5px; |
| 1332 | padding-bottom: 5px; | 1370 | padding-bottom: 5px; |
| 1371 | padding-right: var(--mes-right-spacing); | ||
| 1333 | } | 1372 | } |
| 1334 | 1373 | ||
| 1335 | br { | 1374 | br { |
| @@ -3000,6 +3039,7 @@ input[type=search]:focus::-webkit-search-cancel-button { | |||
| 3000 | .mes_block .ch_name { | 3039 | .mes_block .ch_name { |
| 3001 | max-width: 100%; | 3040 | max-width: 100%; |
| 3002 | min-height: 22px; | 3041 | min-height: 22px; |
| 3042 | align-items: flex-start; | ||
| 3003 | } | 3043 | } |
| 3004 | 3044 | ||
| 3005 | /*applies to both groups and solos chars in the char list*/ | 3045 | /*applies to both groups and solos chars in the char list*/ |
| @@ -4224,7 +4264,13 @@ input[type="range"]::-webkit-slider-thumb { | |||
| 4224 | transition: 0.3s ease-in-out; | 4264 | transition: 0.3s ease-in-out; |
| 4225 | } | 4265 | } |
| 4226 | 4266 | ||
| 4227 | .mes_edit_buttons .menu_button { | 4267 | .mes_reasoning_actions { |
| 4268 | margin: 0; | ||
| 4269 | margin-top: 0.5em; | ||
| 4270 | } | ||
| 4271 | |||
| 4272 | .mes_edit_buttons .menu_button, | ||
| 4273 | .mes_reasoning_actions .edit_button { | ||
| 4228 | opacity: 0.5; | 4274 | opacity: 0.5; |
| 4229 | padding: 0px; | 4275 | padding: 0px; |
| 4230 | font-size: 1rem; | 4276 | font-size: 1rem; |
| @@ -4237,6 +4283,12 @@ input[type="range"]::-webkit-slider-thumb { | |||
| 4237 | align-items: center; | 4283 | align-items: center; |
| 4238 | } | 4284 | } |
| 4239 | 4285 | ||
| 4286 | .mes_reasoning_actions .edit_button { | ||
| 4287 | margin-bottom: 0.5em; | ||
| 4288 | opacity: 1; | ||
| 4289 | filter: brightness(0.7); | ||
| 4290 | } | ||
| 4291 | |||
| 4240 | .mes_reasoning_edit_cancel, | 4292 | .mes_reasoning_edit_cancel, |
| 4241 | .mes_edit_cancel.menu_button { | 4293 | .mes_edit_cancel.menu_button { |
| 4242 | background-color: var(--crimson70a); | 4294 | background-color: var(--crimson70a); |
| @@ -4263,6 +4315,10 @@ input[type="range"]::-webkit-slider-thumb { | |||
| 4263 | field-sizing: content; | 4315 | field-sizing: content; |
| 4264 | } | 4316 | } |
| 4265 | 4317 | ||
| 4318 | .mes.reasoning .mes_edit_add_reasoning { | ||
| 4319 | display: none; | ||
| 4320 | } | ||
| 4321 | |||
| 4266 | #anchor_order { | 4322 | #anchor_order { |
| 4267 | margin-bottom: 15px; | 4323 | margin-bottom: 15px; |
| 4268 | } | 4324 | } |