Merge branch 'staging' into persona-improvements
| @@ -274,7 +274,7 @@ You will need two mandatory directory mappings and a port mapping to allow Silly | |||
| 274 | 1. Open your Command Line | 274 | 1. Open your Command Line |
| 275 | 2. Run the following command | 275 | 2. Run the following command |
| 276 | 276 | ||
| 277 | `docker create --name='sillytavern' --net='[DockerNet]' -p '8000:8000/tcp' -v '[plugins]':'/home/node/app/plugins':'rw' -v '[config]':'/home/node/app/config':'rw' -v '[data]':'/home/node/app/data':'rw' -v '[extensions]':'/home/node/app/public/scripts/extensions/third-party':'rw' 'ghcr.io/sillytavern/sillytavern:[version]'` | 277 | `docker run --name='sillytavern' --net='[DockerNet]' -p '8000:8000/tcp' -v '[plugins]':'/home/node/app/plugins':'rw' -v '[config]':'/home/node/app/config':'rw' -v '[data]':'/home/node/app/data':'rw' -v '[extensions]':'/home/node/app/public/scripts/extensions/third-party':'rw' 'ghcr.io/sillytavern/sillytavern:[version]'` |
| 278 | 278 | ||
| 279 | > Note that 8000 is a default listening port. Don't forget to use an appropriate port if you change it in the config. | 279 | > Note that 8000 is a default listening port. Don't forget to use an appropriate port if you change it in the config. |
| 280 | 280 | ||
| @@ -1977,11 +1977,11 @@ | |||
| 1977 | </span> | 1977 | </span> |
| 1978 | </div> | 1978 | </div> |
| 1979 | </div> | 1979 | </div> |
| 1980 | <div class="range-block" data-source="makersuite,deepseek"> | 1980 | <div class="range-block" data-source="makersuite,deepseek,openrouter"> |
| 1981 | <label for="openai_show_thoughts" class="checkbox_label widthFreeExpand"> | 1981 | <label for="openai_show_thoughts" class="checkbox_label widthFreeExpand"> |
| 1982 | <input id="openai_show_thoughts" type="checkbox" /> | 1982 | <input id="openai_show_thoughts" type="checkbox" /> |
| 1983 | <span> | 1983 | <span> |
| 1984 | <span data-i18n="Show model thoughts">Show model thoughts</span> | 1984 | <span data-i18n="Show model reasoning">Show model reasoning</span> |
| 1985 | <i class="opacity50p fa-solid fa-circle-info" title="Gemini 2.0 Thinking / DeepSeek Reasoner"></i> | 1985 | <i class="opacity50p fa-solid fa-circle-info" title="Gemini 2.0 Thinking / DeepSeek Reasoner"></i> |
| 1986 | </span> | 1986 | </span> |
| 1987 | </label> | 1987 | </label> |
| @@ -3800,6 +3800,39 @@ | |||
| 3800 | </div> | 3800 | </div> |
| 3801 | </div> | 3801 | </div> |
| 3802 | <div> | 3802 | <div> |
| 3803 | <h4 class="standoutHeader"> | ||
| 3804 | <span data-i18n="Reasoning">Reasoning</span> | ||
| 3805 | </h4> | ||
| 3806 | <div> | ||
| 3807 | <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"> | ||
| 3808 | <input id="reasoning_add_to_prompts" type="checkbox" /> | ||
| 3809 | <small data-i18n="Add Reasoning to Prompts"> | ||
| 3810 | Add Reasoning to Prompts | ||
| 3811 | </small> | ||
| 3812 | </label> | ||
| 3813 | <div class="flex-container"> | ||
| 3814 | <div class="flex1" title="Inserted before the reasoning content." data-i18n="[title]reasoning_prefix"> | ||
| 3815 | <small data-i18n="Prefix">Prefix</small> | ||
| 3816 | <textarea id="reasoning_prefix" class="text_pole textarea_compact autoSetHeight"></textarea> | ||
| 3817 | </div> | ||
| 3818 | <div class="flex1" title="Inserted after the reasoning content." data-i18n="[title]reasoning_suffix"> | ||
| 3819 | <small data-i18n="Suffix">Suffix</small> | ||
| 3820 | <textarea id="reasoning_suffix" class="text_pole textarea_compact autoSetHeight"></textarea> | ||
| 3821 | </div> | ||
| 3822 | </div> | ||
| 3823 | <div class="flex-container"> | ||
| 3824 | <div class="flex1" title="Inserted between the reasoning and the message content." data-i18n="[title]reasoning_separator"> | ||
| 3825 | <small data-i18n="Separator">Separator</small> | ||
| 3826 | <textarea id="reasoning_separator" class="text_pole textarea_compact autoSetHeight"></textarea> | ||
| 3827 | </div> | ||
| 3828 | <div class="flex1" title="Maximum number of reasoning blocks to be added per prompt, counting from the last message." data-i18n="[title]reasoning_max_additions"> | ||
| 3829 | <small data-i18n="Max Additions">Max Additions</small> | ||
| 3830 | <input id="reasoning_max_additions" class="text_pole textarea_compact" type="number" min="0" max="999"></textarea> | ||
| 3831 | </div> | ||
| 3832 | </div> | ||
| 3833 | </div> | ||
| 3834 | </div> | ||
| 3835 | <div> | ||
| 3803 | <h4 class="standoutHeader" data-i18n="Miscellaneous">Miscellaneous</h4> | 3836 | <h4 class="standoutHeader" data-i18n="Miscellaneous">Miscellaneous</h4> |
| 3804 | <div> | 3837 | <div> |
| 3805 | <small> | 3838 | <small> |
| @@ -6265,14 +6298,26 @@ | |||
| 6265 | <div class="mes_edit_buttons"> | 6298 | <div class="mes_edit_buttons"> |
| 6266 | <div class="mes_edit_done menu_button fa-solid fa-check" title="Confirm" data-i18n="[title]Confirm"></div> | 6299 | <div class="mes_edit_done menu_button fa-solid fa-check" title="Confirm" data-i18n="[title]Confirm"></div> |
| 6267 | <div class="mes_edit_copy menu_button fa-solid fa-copy" title="Copy this message" data-i18n="[title]Copy this message"></div> | 6300 | <div class="mes_edit_copy menu_button fa-solid fa-copy" title="Copy this message" data-i18n="[title]Copy this message"></div> |
| 6268 | <div class="mes_edit_delete menu_button fa-solid fa-trash-can" title="Delete this message" data-i18n="[title]Delete this message"> | 6301 | <div class="mes_edit_add_reasoning menu_button fa-solid fa-lightbulb" title="Add a reasoning block" data-i18n="[title]Add a reasoning block"></div> |
| 6269 | </div> | 6302 | <div class="mes_edit_delete menu_button fa-solid fa-trash-can" title="Delete this message" data-i18n="[title]Delete this message"></div> |
| 6270 | <div class="mes_edit_up menu_button fa-solid fa-chevron-up " title="Move message up" data-i18n="[title]Move message up"></div> | 6303 | <div class="mes_edit_up menu_button fa-solid fa-chevron-up " title="Move message up" data-i18n="[title]Move message up"></div> |
| 6271 | <div class="mes_edit_down menu_button fa-solid fa-chevron-down" title="Move message down" data-i18n="[title]Move message down"> | 6304 | <div class="mes_edit_down menu_button fa-solid fa-chevron-down" title="Move message down" data-i18n="[title]Move message down"></div> |
| 6272 | </div> | ||
| 6273 | <div class="mes_edit_cancel menu_button fa-solid fa-xmark" title="Cancel" data-i18n="[title]Cancel"></div> | 6305 | <div class="mes_edit_cancel menu_button fa-solid fa-xmark" title="Cancel" data-i18n="[title]Cancel"></div> |
| 6274 | </div> | 6306 | </div> |
| 6275 | </div> | 6307 | </div> |
| 6308 | <details class="mes_reasoning_details"> | ||
| 6309 | <summary class="mes_reasoning_summary"> | ||
| 6310 | <span data-i18n="Reasoning">Reasoning</span> | ||
| 6311 | <div class="mes_reasoning_actions"> | ||
| 6312 | <div class="mes_reasoning_edit_done mes_button fa-solid fa-check" title="Confirm" data-i18n="[title]Confirmedit"></div> | ||
| 6313 | <div class="mes_reasoning_edit_cancel mes_button fa-solid fa-xmark" title="Cancel edit" data-i18n="[title]Cancel edit"></div> | ||
| 6314 | <div class="mes_reasoning_edit mes_button fa-solid fa-pencil" title="Edit reasoning" data-i18n="[title]Edit reasoning"></div> | ||
| 6315 | <div class="mes_reasoning_copy mes_button fa-solid fa-copy" title="Copy reasoning" data-i18n="[title]Copy reasoning"></div> | ||
| 6316 | <div class="mes_reasoning_delete mes_button fa-solid fa-trash-can" title="Remove reasoning" data-i18n="[title]Remove reasoning"></div> | ||
| 6317 | </div> | ||
| 6318 | </summary> | ||
| 6319 | <div class="mes_reasoning"></div> | ||
| 6320 | </details> | ||
| 6276 | <div class="mes_text"></div> | 6321 | <div class="mes_text"></div> |
| 6277 | <div class="mes_img_container"> | 6322 | <div class="mes_img_container"> |
| 6278 | <div class="mes_img_controls"> | 6323 | <div class="mes_img_controls"> |
| @@ -1385,7 +1385,7 @@ | |||
| 1385 | "enable_functions_desc_1": "Autorise l'utilisation", | 1385 | "enable_functions_desc_1": "Autorise l'utilisation", |
| 1386 | "enable_functions_desc_2": "outils de fonction", | 1386 | "enable_functions_desc_2": "outils de fonction", |
| 1387 | "enable_functions_desc_3": "Peut être utilisé par diverses extensions pour fournir des fonctionnalités supplémentaires.", | 1387 | "enable_functions_desc_3": "Peut être utilisé par diverses extensions pour fournir des fonctionnalités supplémentaires.", |
| 1388 | "Show model thoughts": "Afficher les pensées du modèle", | 1388 | "Show model reasoning": "Afficher les pensées du modèle", |
| 1389 | "Display the model's internal thoughts in the response.": "Afficher les pensées internes du modèle dans la réponse.", | 1389 | "Display the model's internal thoughts in the response.": "Afficher les pensées internes du modèle dans la réponse.", |
| 1390 | "Confirm token parsing with": "Confirmer l'analyse des tokens avec", | 1390 | "Confirm token parsing with": "Confirmer l'analyse des tokens avec", |
| 1391 | "openai_logit_bias_no_items": "Aucun élément", | 1391 | "openai_logit_bias_no_items": "Aucun élément", |
| @@ -266,7 +266,7 @@ | |||
| 266 | "Use system prompt": "使用系统提示词", | 266 | "Use system prompt": "使用系统提示词", |
| 267 | "Merges_all_system_messages_desc_1": "合并所有系统消息,直到第一条具有非系统角色的消息,然后通过", | 267 | "Merges_all_system_messages_desc_1": "合并所有系统消息,直到第一条具有非系统角色的消息,然后通过", |
| 268 | "Merges_all_system_messages_desc_2": "字段发送。", | 268 | "Merges_all_system_messages_desc_2": "字段发送。", |
| 269 | "Show model thoughts": "展示思维链", | 269 | "Show model reasoning": "展示思维链", |
| 270 | "Display the model's internal thoughts in the response.": "展示模型在回复时的内部思维链。", | 270 | "Display the model's internal thoughts in the response.": "展示模型在回复时的内部思维链。", |
| 271 | "Assistant Prefill": "AI预填", | 271 | "Assistant Prefill": "AI预填", |
| 272 | "Expand the editor": "展开编辑器", | 272 | "Expand the editor": "展开编辑器", |
| @@ -2357,7 +2357,7 @@ | |||
| 2357 | "Forbid": "禁止", | 2357 | "Forbid": "禁止", |
| 2358 | "Aphrodite only. Determines the order of samplers. Skew is always applied post-softmax, so it's not included here.": "僅限 Aphrodite 使用。決定採樣器的順序。偏移總是在 softmax 後應用,因此不包括在此。", | 2358 | "Aphrodite only. Determines the order of samplers. Skew is always applied post-softmax, so it's not included here.": "僅限 Aphrodite 使用。決定採樣器的順序。偏移總是在 softmax 後應用,因此不包括在此。", |
| 2359 | "Aphrodite only. Determines the order of samplers.": "僅限 Aphrodite 使用。決定採樣器的順序。", | 2359 | "Aphrodite only. Determines the order of samplers.": "僅限 Aphrodite 使用。決定採樣器的順序。", |
| 2360 | "Show model thoughts": "顯示模型思維鏈", | 2360 | "Show model reasoning": "顯示模型思維鏈", |
| 2361 | "Display the model's internal thoughts in the response.": "在回應中顯示模型的思維鏈(內部思考過程)。", | 2361 | "Display the model's internal thoughts in the response.": "在回應中顯示模型的思維鏈(內部思考過程)。", |
| 2362 | "Generic (OpenAI-compatible) [LM Studio, LiteLLM, etc.]": "通用(兼容 OpenAI)[LM Studio, LiteLLM 等]", | 2362 | "Generic (OpenAI-compatible) [LM Studio, LiteLLM, etc.]": "通用(兼容 OpenAI)[LM Studio, LiteLLM 等]", |
| 2363 | "Model ID (optional)": "模型 ID(可選)", | 2363 | "Model ID (optional)": "模型 ID(可選)", |
| @@ -271,6 +271,7 @@ import { initSettingsSearch } from './scripts/setting-search.js'; | |||
| 271 | import { initBulkEdit } from './scripts/bulk-edit.js'; | 271 | import { initBulkEdit } from './scripts/bulk-edit.js'; |
| 272 | import { deriveTemplatesFromChatTemplate } from './scripts/chat-templates.js'; | 272 | import { deriveTemplatesFromChatTemplate } from './scripts/chat-templates.js'; |
| 273 | import { getContext } from './scripts/st-context.js'; | 273 | import { getContext } from './scripts/st-context.js'; |
| 274 | import { initReasoning, PromptReasoning } from './scripts/reasoning.js'; | ||
| 274 | 275 | ||
| 275 | // API OBJECT FOR EXTERNAL WIRING | 276 | // API OBJECT FOR EXTERNAL WIRING |
| 276 | globalThis.SillyTavern = { | 277 | globalThis.SillyTavern = { |
| @@ -986,6 +987,7 @@ async function firstLoadInit() { | |||
| 986 | initServerHistory(); | 987 | initServerHistory(); |
| 987 | initSettingsSearch(); | 988 | initSettingsSearch(); |
| 988 | initBulkEdit(); | 989 | initBulkEdit(); |
| 990 | initReasoning(); | ||
| 989 | await initScrapers(); | 991 | await initScrapers(); |
| 990 | doDailyExtensionUpdatesCheck(); | 992 | doDailyExtensionUpdatesCheck(); |
| 991 | await hideLoader(); | 993 | await hideLoader(); |
| @@ -2213,6 +2215,7 @@ function getMessageFromTemplate({ | |||
| 2213 | isUser, | 2215 | isUser, |
| 2214 | avatarImg, | 2216 | avatarImg, |
| 2215 | bias, | 2217 | bias, |
| 2218 | reasoning, | ||
| 2216 | isSystem, | 2219 | isSystem, |
| 2217 | title, | 2220 | title, |
| 2218 | timerValue, | 2221 | timerValue, |
| @@ -2237,6 +2240,7 @@ function getMessageFromTemplate({ | |||
| 2237 | mes.find('.avatar img').attr('src', avatarImg); | 2240 | mes.find('.avatar img').attr('src', avatarImg); |
| 2238 | mes.find('.ch_name .name_text').text(characterName); | 2241 | mes.find('.ch_name .name_text').text(characterName); |
| 2239 | mes.find('.mes_bias').html(bias); | 2242 | mes.find('.mes_bias').html(bias); |
| 2243 | mes.find('.mes_reasoning').html(reasoning); | ||
| 2240 | mes.find('.timestamp').text(timestamp).attr('title', `${extra?.api ? extra.api + ' - ' : ''}${extra?.model ?? ''}`); | 2244 | mes.find('.timestamp').text(timestamp).attr('title', `${extra?.api ? extra.api + ' - ' : ''}${extra?.model ?? ''}`); |
| 2241 | mes.find('.mesIDDisplay').text(`#${mesId}`); | 2245 | mes.find('.mesIDDisplay').text(`#${mesId}`); |
| 2242 | tokenCount && mes.find('.tokenCounterDisplay').text(`${tokenCount}t`); | 2246 | tokenCount && mes.find('.tokenCounterDisplay').text(`${tokenCount}t`); |
| @@ -2251,10 +2255,16 @@ function getMessageFromTemplate({ | |||
| 2251 | return mes; | 2255 | return mes; |
| 2252 | } | 2256 | } |
| 2253 | 2257 | ||
| 2258 | /** | ||
| 2259 | * Re-renders a message block with updated content. | ||
| 2260 | * @param {number} messageId Message ID | ||
| 2261 | * @param {object} message Message object | ||
| 2262 | */ | ||
| 2254 | export function updateMessageBlock(messageId, message) { | 2263 | export function updateMessageBlock(messageId, message) { |
| 2255 | const messageElement = $(`#chat [mesid="${messageId}"]`); | 2264 | const messageElement = $(`#chat [mesid="${messageId}"]`); |
| 2256 | const text = message?.extra?.display_text ?? message.mes; | 2265 | const text = message?.extra?.display_text ?? message.mes; |
| 2257 | messageElement.find('.mes_text').html(messageFormatting(text, message.name, message.is_system, message.is_user, messageId)); | 2266 | messageElement.find('.mes_text').html(messageFormatting(text, message.name, message.is_system, message.is_user, messageId)); |
| 2267 | messageElement.find('.mes_reasoning').html(messageFormatting(message.extra?.reasoning ?? '', '', false, false, -1)); | ||
| 2258 | addCopyToCodeBlocks(messageElement); | 2268 | addCopyToCodeBlocks(messageElement); |
| 2259 | appendMediaToMessage(message, messageElement); | 2269 | appendMediaToMessage(message, messageElement); |
| 2260 | } | 2270 | } |
| @@ -2413,6 +2423,7 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll | |||
| 2413 | sanitizerOverrides, | 2423 | sanitizerOverrides, |
| 2414 | ); | 2424 | ); |
| 2415 | const bias = messageFormatting(mes.extra?.bias ?? '', '', false, false, -1); | 2425 | const bias = messageFormatting(mes.extra?.bias ?? '', '', false, false, -1); |
| 2426 | const reasoning = messageFormatting(mes.extra?.reasoning ?? '', '', false, false, -1); | ||
| 2416 | let bookmarkLink = mes?.extra?.bookmark_link ?? ''; | 2427 | let bookmarkLink = mes?.extra?.bookmark_link ?? ''; |
| 2417 | 2428 | ||
| 2418 | let params = { | 2429 | let params = { |
| @@ -2422,6 +2433,7 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll | |||
| 2422 | isUser: mes.is_user, | 2433 | isUser: mes.is_user, |
| 2423 | avatarImg: avatarImg, | 2434 | avatarImg: avatarImg, |
| 2424 | bias: bias, | 2435 | bias: bias, |
| 2436 | reasoning: reasoning, | ||
| 2425 | isSystem: isSystem, | 2437 | isSystem: isSystem, |
| 2426 | title: title, | 2438 | title: title, |
| 2427 | bookmarkLink: bookmarkLink, | 2439 | bookmarkLink: bookmarkLink, |
| @@ -2481,6 +2493,7 @@ export function addOneMessage(mes, { type = 'normal', insertAfter = null, scroll | |||
| 2481 | const swipeMessage = chatElement.find(`[mesid="${chat.length - 1}"]`); | 2493 | const swipeMessage = chatElement.find(`[mesid="${chat.length - 1}"]`); |
| 2482 | swipeMessage.attr('swipeid', params.swipeId); | 2494 | swipeMessage.attr('swipeid', params.swipeId); |
| 2483 | swipeMessage.find('.mes_text').html(messageText).attr('title', title); | 2495 | swipeMessage.find('.mes_text').html(messageText).attr('title', title); |
| 2496 | swipeMessage.find('.mes_reasoning').html(reasoning); | ||
| 2484 | swipeMessage.find('.timestamp').text(timestamp).attr('title', `${params.extra.api} - ${params.extra.model}`); | 2497 | swipeMessage.find('.timestamp').text(timestamp).attr('title', `${params.extra.api} - ${params.extra.model}`); |
| 2485 | appendMediaToMessage(mes, swipeMessage); | 2498 | appendMediaToMessage(mes, swipeMessage); |
| 2486 | if (power_user.timestamp_model_icon && params.extra?.api) { | 2499 | if (power_user.timestamp_model_icon && params.extra?.api) { |
| @@ -3091,6 +3104,7 @@ class StreamingProcessor { | |||
| 3091 | this.messageTextDom = null; | 3104 | this.messageTextDom = null; |
| 3092 | this.messageTimerDom = null; | 3105 | this.messageTimerDom = null; |
| 3093 | this.messageTokenCounterDom = null; | 3106 | this.messageTokenCounterDom = null; |
| 3107 | this.messageReasoningDom = null; | ||
| 3094 | /** @type {HTMLTextAreaElement} */ | 3108 | /** @type {HTMLTextAreaElement} */ |
| 3095 | this.sendTextarea = document.querySelector('#send_textarea'); | 3109 | this.sendTextarea = document.querySelector('#send_textarea'); |
| 3096 | this.type = type; | 3110 | this.type = type; |
| @@ -3106,6 +3120,7 @@ class StreamingProcessor { | |||
| 3106 | /** @type {import('./scripts/logprobs.js').TokenLogprobs[]} */ | 3120 | /** @type {import('./scripts/logprobs.js').TokenLogprobs[]} */ |
| 3107 | this.messageLogprobs = []; | 3121 | this.messageLogprobs = []; |
| 3108 | this.toolCalls = []; | 3122 | this.toolCalls = []; |
| 3123 | this.reasoning = ''; | ||
| 3109 | } | 3124 | } |
| 3110 | 3125 | ||
| 3111 | #checkDomElements(messageId) { | 3126 | #checkDomElements(messageId) { |
| @@ -3114,6 +3129,7 @@ class StreamingProcessor { | |||
| 3114 | this.messageTextDom = this.messageDom?.querySelector('.mes_text'); | 3129 | this.messageTextDom = this.messageDom?.querySelector('.mes_text'); |
| 3115 | this.messageTimerDom = this.messageDom?.querySelector('.mes_timer'); | 3130 | this.messageTimerDom = this.messageDom?.querySelector('.mes_timer'); |
| 3116 | this.messageTokenCounterDom = this.messageDom?.querySelector('.tokenCounterDisplay'); | 3131 | this.messageTokenCounterDom = this.messageDom?.querySelector('.tokenCounterDisplay'); |
| 3132 | this.messageReasoningDom = this.messageDom?.querySelector('.mes_reasoning'); | ||
| 3117 | } | 3133 | } |
| 3118 | } | 3134 | } |
| 3119 | 3135 | ||
| @@ -3191,18 +3207,27 @@ class StreamingProcessor { | |||
| 3191 | this.#checkDomElements(messageId); | 3207 | this.#checkDomElements(messageId); |
| 3192 | this.#updateMessageBlockVisibility(); | 3208 | this.#updateMessageBlockVisibility(); |
| 3193 | const currentTime = new Date(); | 3209 | const currentTime = new Date(); |
| 3194 | // Don't waste time calculating token count for streaming | ||
| 3195 | const currentTokenCount = isFinal && power_user.message_token_count_enabled ? getTokenCount(processedText, 0) : 0; | ||
| 3196 | const timePassed = formatGenerationTimer(this.timeStarted, currentTime, currentTokenCount); | ||
| 3197 | chat[messageId]['mes'] = processedText; | 3210 | chat[messageId]['mes'] = processedText; |
| 3198 | chat[messageId]['gen_started'] = this.timeStarted; | 3211 | chat[messageId]['gen_started'] = this.timeStarted; |
| 3199 | chat[messageId]['gen_finished'] = currentTime; | 3212 | chat[messageId]['gen_finished'] = currentTime; |
| 3200 | 3213 | ||
| 3201 | if (currentTokenCount) { | 3214 | if (!chat[messageId]['extra']) { |
| 3202 | if (!chat[messageId]['extra']) { | 3215 | chat[messageId]['extra'] = {}; |
| 3203 | chat[messageId]['extra'] = {}; | 3216 | } |
| 3217 | |||
| 3218 | if (this.reasoning) { | ||
| 3219 | chat[messageId]['extra']['reasoning'] = this.reasoning; | ||
| 3220 | if (this.messageReasoningDom instanceof HTMLElement) { | ||
| 3221 | const formattedReasoning = messageFormatting(this.reasoning, '', false, false, -1); | ||
| 3222 | this.messageReasoningDom.innerHTML = formattedReasoning; | ||
| 3204 | } | 3223 | } |
| 3224 | } | ||
| 3225 | |||
| 3226 | // Don't waste time calculating token count for streaming | ||
| 3227 | const tokenCountText = (this.reasoning || '') + processedText; | ||
| 3228 | const currentTokenCount = isFinal && power_user.message_token_count_enabled ? getTokenCount(tokenCountText, 0) : 0; | ||
| 3205 | 3229 | ||
| 3230 | if (currentTokenCount) { | ||
| 3206 | chat[messageId]['extra']['token_count'] = currentTokenCount; | 3231 | chat[messageId]['extra']['token_count'] = currentTokenCount; |
| 3207 | if (this.messageTokenCounterDom instanceof HTMLElement) { | 3232 | if (this.messageTokenCounterDom instanceof HTMLElement) { |
| 3208 | this.messageTokenCounterDom.textContent = `${currentTokenCount}t`; | 3233 | this.messageTokenCounterDom.textContent = `${currentTokenCount}t`; |
| @@ -3224,10 +3249,13 @@ class StreamingProcessor { | |||
| 3224 | if (this.messageTextDom instanceof HTMLElement) { | 3249 | if (this.messageTextDom instanceof HTMLElement) { |
| 3225 | this.messageTextDom.innerHTML = formattedText; | 3250 | this.messageTextDom.innerHTML = formattedText; |
| 3226 | } | 3251 | } |
| 3252 | |||
| 3253 | const timePassed = formatGenerationTimer(this.timeStarted, currentTime, currentTokenCount); | ||
| 3227 | if (this.messageTimerDom instanceof HTMLElement) { | 3254 | if (this.messageTimerDom instanceof HTMLElement) { |
| 3228 | this.messageTimerDom.textContent = timePassed.timerValue; | 3255 | this.messageTimerDom.textContent = timePassed.timerValue; |
| 3229 | this.messageTimerDom.title = timePassed.timerTitle; | 3256 | this.messageTimerDom.title = timePassed.timerTitle; |
| 3230 | } | 3257 | } |
| 3258 | |||
| 3231 | this.setFirstSwipe(messageId); | 3259 | this.setFirstSwipe(messageId); |
| 3232 | } | 3260 | } |
| 3233 | 3261 | ||
| @@ -3334,7 +3362,7 @@ class StreamingProcessor { | |||
| 3334 | } | 3362 | } |
| 3335 | 3363 | ||
| 3336 | /** | 3364 | /** |
| 3337 | * @returns {Generator<{ text: string, swipes: string[], logprobs: import('./scripts/logprobs.js').TokenLogprobs, toolCalls: any[] }, void, void>} | 3365 | * @returns {Generator<{ text: string, swipes: string[], logprobs: import('./scripts/logprobs.js').TokenLogprobs, toolCalls: any[], state: any }, void, void>} |
| 3338 | */ | 3366 | */ |
| 3339 | *nullStreamingGeneration() { | 3367 | *nullStreamingGeneration() { |
| 3340 | throw new Error('Generation function for streaming is not hooked up'); | 3368 | throw new Error('Generation function for streaming is not hooked up'); |
| @@ -3356,7 +3384,7 @@ class StreamingProcessor { | |||
| 3356 | try { | 3384 | try { |
| 3357 | const sw = new Stopwatch(1000 / power_user.streaming_fps); | 3385 | const sw = new Stopwatch(1000 / power_user.streaming_fps); |
| 3358 | const timestamps = []; | 3386 | const timestamps = []; |
| 3359 | for await (const { text, swipes, logprobs, toolCalls } of this.generator()) { | 3387 | for await (const { text, swipes, logprobs, toolCalls, state } of this.generator()) { |
| 3360 | timestamps.push(Date.now()); | 3388 | timestamps.push(Date.now()); |
| 3361 | if (this.isStopped) { | 3389 | if (this.isStopped) { |
| 3362 | return; | 3390 | return; |
| @@ -3368,6 +3396,7 @@ class StreamingProcessor { | |||
| 3368 | if (logprobs) { | 3396 | if (logprobs) { |
| 3369 | this.messageLogprobs.push(...(Array.isArray(logprobs) ? logprobs : [logprobs])); | 3397 | this.messageLogprobs.push(...(Array.isArray(logprobs) ? logprobs : [logprobs])); |
| 3370 | } | 3398 | } |
| 3399 | this.reasoning = state?.reasoning ?? ''; | ||
| 3371 | await eventSource.emit(event_types.STREAM_TOKEN_RECEIVED, text); | 3400 | await eventSource.emit(event_types.STREAM_TOKEN_RECEIVED, text); |
| 3372 | await sw.tick(() => this.onProgressStreaming(this.messageId, this.continueMessage + text)); | 3401 | await sw.tick(() => this.onProgressStreaming(this.messageId, this.continueMessage + text)); |
| 3373 | } | 3402 | } |
| @@ -3834,6 +3863,14 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 3834 | coreChat.pop(); | 3863 | coreChat.pop(); |
| 3835 | } | 3864 | } |
| 3836 | 3865 | ||
| 3866 | const reasoning = new PromptReasoning(); | ||
| 3867 | for (let i = coreChat.length - 1; i >= 0; i--) { | ||
| 3868 | if (reasoning.isLimitReached()) { | ||
| 3869 | break; | ||
| 3870 | } | ||
| 3871 | coreChat[i] = { ...coreChat[i], mes: reasoning.addToMessage(coreChat[i].mes, coreChat[i].extra?.reasoning) }; | ||
| 3872 | } | ||
| 3873 | |||
| 3837 | coreChat = await Promise.all(coreChat.map(async (chatItem, index) => { | 3874 | coreChat = await Promise.all(coreChat.map(async (chatItem, index) => { |
| 3838 | let message = chatItem.mes; | 3875 | let message = chatItem.mes; |
| 3839 | let regexType = chatItem.is_user ? regex_placement.USER_INPUT : regex_placement.AI_OUTPUT; | 3876 | let regexType = chatItem.is_user ? regex_placement.USER_INPUT : regex_placement.AI_OUTPUT; |
| @@ -4755,6 +4792,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 4755 | //const getData = await response.json(); | 4792 | //const getData = await response.json(); |
| 4756 | let getMessage = extractMessageFromData(data); | 4793 | let getMessage = extractMessageFromData(data); |
| 4757 | let title = extractTitleFromData(data); | 4794 | let title = extractTitleFromData(data); |
| 4795 | let reasoning = extractReasoningFromData(data); | ||
| 4758 | kobold_horde_model = title; | 4796 | kobold_horde_model = title; |
| 4759 | 4797 | ||
| 4760 | const swipes = extractMultiSwipes(data, type); | 4798 | const swipes = extractMultiSwipes(data, type); |
| @@ -4781,10 +4819,10 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro | |||
| 4781 | else { | 4819 | else { |
| 4782 | // Without streaming we'll be having a full message on continuation. Treat it as a last chunk. | 4820 | // Without streaming we'll be having a full message on continuation. Treat it as a last chunk. |
| 4783 | if (originalType !== 'continue') { | 4821 | if (originalType !== 'continue') { |
| 4784 | ({ type, getMessage } = await saveReply(type, getMessage, false, title, swipes)); | 4822 | ({ type, getMessage } = await saveReply(type, getMessage, false, title, swipes, reasoning)); |
| 4785 | } | 4823 | } |
| 4786 | else { | 4824 | else { |
| 4787 | ({ type, getMessage } = await saveReply('appendFinal', getMessage, false, title, swipes)); | 4825 | ({ type, getMessage } = await saveReply('appendFinal', getMessage, false, title, swipes, reasoning)); |
| 4788 | } | 4826 | } |
| 4789 | 4827 | ||
| 4790 | // This relies on `saveReply` having been called to add the message to the chat, so it must be last. | 4828 | // This relies on `saveReply` having been called to add the message to the chat, so it must be last. |
| @@ -5672,31 +5710,40 @@ function extractMessageFromData(data) { | |||
| 5672 | return data; | 5710 | return data; |
| 5673 | } | 5711 | } |
| 5674 | 5712 | ||
| 5675 | function getTextContext() { | 5713 | switch (main_api) { |
| 5676 | switch (main_api) { | 5714 | case 'kobold': |
| 5677 | case 'kobold': | 5715 | return data.results[0].text; |
| 5678 | return data.results[0].text; | 5716 | case 'koboldhorde': |
| 5679 | case 'koboldhorde': | 5717 | return data.text; |
| 5680 | return data.text; | 5718 | case 'textgenerationwebui': |
| 5681 | case 'textgenerationwebui': | 5719 | return data.choices?.[0]?.text ?? data.content ?? data.response ?? ''; |
| 5682 | return data.choices?.[0]?.text ?? data.content ?? data.response ?? ''; | 5720 | case 'novel': |
| 5683 | case 'novel': | 5721 | return data.output; |
| 5684 | return data.output; | 5722 | case 'openai': |
| 5685 | case 'openai': | 5723 | return data?.choices?.[0]?.message?.content ?? data?.choices?.[0]?.text ?? data?.text ?? data?.message?.content?.[0]?.text ?? data?.message?.tool_plan ?? ''; |
| 5686 | return data?.choices?.[0]?.message?.content ?? data?.choices?.[0]?.text ?? data?.text ?? data?.message?.content?.[0]?.text ?? data?.message?.tool_plan ?? ''; | 5724 | default: |
| 5687 | default: | 5725 | return ''; |
| 5688 | return ''; | ||
| 5689 | } | ||
| 5690 | } | 5726 | } |
| 5727 | } | ||
| 5691 | 5728 | ||
| 5692 | const content = getTextContext(); | 5729 | /** |
| 5693 | 5730 | * Extracts the reasoning from the response data. | |
| 5694 | if (main_api === 'openai' && oai_settings.chat_completion_source === chat_completion_sources.DEEPSEEK && oai_settings.show_thoughts) { | 5731 | * @param {object} data Response data |
| 5695 | const thoughts = data?.choices?.[0]?.message?.reasoning_content ?? ''; | 5732 | * @returns {string} Extracted reasoning |
| 5696 | return [thoughts, content].filter(x => x).join('\n\n'); | 5733 | */ |
| 5734 | function extractReasoningFromData(data) { | ||
| 5735 | if (main_api === 'openai' && oai_settings.show_thoughts) { | ||
| 5736 | switch (oai_settings.chat_completion_source) { | ||
| 5737 | case chat_completion_sources.DEEPSEEK: | ||
| 5738 | return data?.choices?.[0]?.message?.reasoning_content ?? ''; | ||
| 5739 | case chat_completion_sources.OPENROUTER: | ||
| 5740 | return data?.choices?.[0]?.message?.reasoning ?? ''; | ||
| 5741 | case chat_completion_sources.MAKERSUITE: | ||
| 5742 | return data?.responseContent?.parts?.filter(part => part.thought)?.map(part => part.text)?.join('\n\n') ?? ''; | ||
| 5743 | } | ||
| 5697 | } | 5744 | } |
| 5698 | 5745 | ||
| 5699 | return content; | 5746 | return ''; |
| 5700 | } | 5747 | } |
| 5701 | 5748 | ||
| 5702 | /** | 5749 | /** |
| @@ -5879,7 +5926,7 @@ export function cleanUpMessage(getMessage, isImpersonate, isContinue, displayInc | |||
| 5879 | return getMessage; | 5926 | return getMessage; |
| 5880 | } | 5927 | } |
| 5881 | 5928 | ||
| 5882 | export async function saveReply(type, getMessage, fromStreaming, title, swipes) { | 5929 | export async function saveReply(type, getMessage, fromStreaming, title, swipes, reasoning) { |
| 5883 | if (type != 'append' && type != 'continue' && type != 'appendFinal' && chat.length && (chat[chat.length - 1]['swipe_id'] === undefined || | 5930 | if (type != 'append' && type != 'continue' && type != 'appendFinal' && chat.length && (chat[chat.length - 1]['swipe_id'] === undefined || |
| 5884 | chat[chat.length - 1]['is_user'])) { | 5931 | chat[chat.length - 1]['is_user'])) { |
| 5885 | type = 'normal'; | 5932 | type = 'normal'; |
| @@ -5904,8 +5951,10 @@ export async function saveReply(type, getMessage, fromStreaming, title, swipes) | |||
| 5904 | chat[chat.length - 1]['send_date'] = getMessageTimeStamp(); | 5951 | chat[chat.length - 1]['send_date'] = getMessageTimeStamp(); |
| 5905 | chat[chat.length - 1]['extra']['api'] = getGeneratingApi(); | 5952 | chat[chat.length - 1]['extra']['api'] = getGeneratingApi(); |
| 5906 | chat[chat.length - 1]['extra']['model'] = getGeneratingModel(); | 5953 | chat[chat.length - 1]['extra']['model'] = getGeneratingModel(); |
| 5954 | chat[chat.length - 1]['extra']['reasoning'] = reasoning; | ||
| 5907 | if (power_user.message_token_count_enabled) { | 5955 | if (power_user.message_token_count_enabled) { |
| 5908 | chat[chat.length - 1]['extra']['token_count'] = await getTokenCountAsync(chat[chat.length - 1]['mes'], 0); | 5956 | const tokenCountText = (reasoning || '') + chat[chat.length - 1]['mes']; |
| 5957 | chat[chat.length - 1]['extra']['token_count'] = await getTokenCountAsync(tokenCountText, 0); | ||
| 5909 | } | 5958 | } |
| 5910 | const chat_id = (chat.length - 1); | 5959 | const chat_id = (chat.length - 1); |
| 5911 | await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id); | 5960 | await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id); |
| @@ -5924,8 +5973,10 @@ export async function saveReply(type, getMessage, fromStreaming, title, swipes) | |||
| 5924 | chat[chat.length - 1]['send_date'] = getMessageTimeStamp(); | 5973 | chat[chat.length - 1]['send_date'] = getMessageTimeStamp(); |
| 5925 | chat[chat.length - 1]['extra']['api'] = getGeneratingApi(); | 5974 | chat[chat.length - 1]['extra']['api'] = getGeneratingApi(); |
| 5926 | chat[chat.length - 1]['extra']['model'] = getGeneratingModel(); | 5975 | chat[chat.length - 1]['extra']['model'] = getGeneratingModel(); |
| 5976 | chat[chat.length - 1]['extra']['reasoning'] += reasoning; | ||
| 5927 | if (power_user.message_token_count_enabled) { | 5977 | if (power_user.message_token_count_enabled) { |
| 5928 | chat[chat.length - 1]['extra']['token_count'] = await getTokenCountAsync(chat[chat.length - 1]['mes'], 0); | 5978 | const tokenCountText = (reasoning || '') + chat[chat.length - 1]['mes']; |
| 5979 | chat[chat.length - 1]['extra']['token_count'] = await getTokenCountAsync(tokenCountText, 0); | ||
| 5929 | } | 5980 | } |
| 5930 | const chat_id = (chat.length - 1); | 5981 | const chat_id = (chat.length - 1); |
| 5931 | await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id); | 5982 | await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id); |
| @@ -5941,8 +5992,10 @@ export async function saveReply(type, getMessage, fromStreaming, title, swipes) | |||
| 5941 | chat[chat.length - 1]['send_date'] = getMessageTimeStamp(); | 5992 | chat[chat.length - 1]['send_date'] = getMessageTimeStamp(); |
| 5942 | chat[chat.length - 1]['extra']['api'] = getGeneratingApi(); | 5993 | chat[chat.length - 1]['extra']['api'] = getGeneratingApi(); |
| 5943 | chat[chat.length - 1]['extra']['model'] = getGeneratingModel(); | 5994 | chat[chat.length - 1]['extra']['model'] = getGeneratingModel(); |
| 5995 | chat[chat.length - 1]['extra']['reasoning'] += reasoning; | ||
| 5944 | if (power_user.message_token_count_enabled) { | 5996 | if (power_user.message_token_count_enabled) { |
| 5945 | chat[chat.length - 1]['extra']['token_count'] = await getTokenCountAsync(chat[chat.length - 1]['mes'], 0); | 5997 | const tokenCountText = (reasoning || '') + chat[chat.length - 1]['mes']; |
| 5998 | chat[chat.length - 1]['extra']['token_count'] = await getTokenCountAsync(tokenCountText, 0); | ||
| 5946 | } | 5999 | } |
| 5947 | const chat_id = (chat.length - 1); | 6000 | const chat_id = (chat.length - 1); |
| 5948 | await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id); | 6001 | await eventSource.emit(event_types.MESSAGE_RECEIVED, chat_id); |
| @@ -5958,6 +6011,7 @@ export async function saveReply(type, getMessage, fromStreaming, title, swipes) | |||
| 5958 | chat[chat.length - 1]['send_date'] = getMessageTimeStamp(); | 6011 | chat[chat.length - 1]['send_date'] = getMessageTimeStamp(); |
| 5959 | chat[chat.length - 1]['extra']['api'] = getGeneratingApi(); | 6012 | chat[chat.length - 1]['extra']['api'] = getGeneratingApi(); |
| 5960 | chat[chat.length - 1]['extra']['model'] = getGeneratingModel(); | 6013 | chat[chat.length - 1]['extra']['model'] = getGeneratingModel(); |
| 6014 | chat[chat.length - 1]['extra']['reasoning'] = reasoning; | ||
| 5961 | if (power_user.trim_spaces) { | 6015 | if (power_user.trim_spaces) { |
| 5962 | getMessage = getMessage.trim(); | 6016 | getMessage = getMessage.trim(); |
| 5963 | } | 6017 | } |
| @@ -5967,7 +6021,8 @@ export async function saveReply(type, getMessage, fromStreaming, title, swipes) | |||
| 5967 | chat[chat.length - 1]['gen_finished'] = generationFinished; | 6021 | chat[chat.length - 1]['gen_finished'] = generationFinished; |
| 5968 | 6022 | ||
| 5969 | if (power_user.message_token_count_enabled) { | 6023 | if (power_user.message_token_count_enabled) { |
| 5970 | chat[chat.length - 1]['extra']['token_count'] = await getTokenCountAsync(chat[chat.length - 1]['mes'], 0); | 6024 | const tokenCountText = (reasoning || '') + chat[chat.length - 1]['mes']; |
| 6025 | chat[chat.length - 1]['extra']['token_count'] = await getTokenCountAsync(tokenCountText, 0); | ||
| 5971 | } | 6026 | } |
| 5972 | 6027 | ||
| 5973 | if (selected_group) { | 6028 | if (selected_group) { |
| @@ -6032,6 +6087,19 @@ export async function saveReply(type, getMessage, fromStreaming, title, swipes) | |||
| 6032 | return { type, getMessage }; | 6087 | return { type, getMessage }; |
| 6033 | } | 6088 | } |
| 6034 | 6089 | ||
| 6090 | export function syncCurrentSwipeInfoExtras() { | ||
| 6091 | if (!chat.length) { | ||
| 6092 | return; | ||
| 6093 | } | ||
| 6094 | const currentMessage = chat[chat.length - 1]; | ||
| 6095 | if (currentMessage && Array.isArray(currentMessage.swipe_info) && typeof currentMessage.swipe_id === 'number') { | ||
| 6096 | const swipeInfo = currentMessage.swipe_info[currentMessage.swipe_id]; | ||
| 6097 | if (swipeInfo && typeof swipeInfo === 'object') { | ||
| 6098 | swipeInfo.extra = structuredClone(currentMessage.extra); | ||
| 6099 | } | ||
| 6100 | } | ||
| 6101 | } | ||
| 6102 | |||
| 6035 | function saveImageToMessage(img, mes) { | 6103 | function saveImageToMessage(img, mes) { |
| 6036 | if (mes && img.image) { | 6104 | if (mes && img.image) { |
| 6037 | if (!mes.extra || typeof mes.extra !== 'object') { | 6105 | if (!mes.extra || typeof mes.extra !== 'object') { |
| @@ -8016,9 +8084,23 @@ function updateEditArrowClasses() { | |||
| 8016 | } | 8084 | } |
| 8017 | } | 8085 | } |
| 8018 | 8086 | ||
| 8019 | function closeMessageEditor() { | 8087 | /** |
| 8020 | if (this_edit_mes_id) { | 8088 | * Closes the message editor. |
| 8021 | $(`#chat .mes[mesid="${this_edit_mes_id}"] .mes_edit_cancel`).click(); | 8089 | * @param {'message'|'reasoning'|'all'} what What to close. Default is 'all'. |
| 8090 | */ | ||
| 8091 | export function closeMessageEditor(what = 'all') { | ||
| 8092 | if (what === 'message' || what === 'all') { | ||
| 8093 | if (this_edit_mes_id) { | ||
| 8094 | $(`#chat .mes[mesid="${this_edit_mes_id}"] .mes_edit_cancel`).click(); | ||
| 8095 | } | ||
| 8096 | } | ||
| 8097 | if (what === 'reasoning' || what === 'all') { | ||
| 8098 | document.querySelectorAll('.reasoning_edit_textarea').forEach((el) => { | ||
| 8099 | const cancelButton = el.closest('.mes')?.querySelector('.mes_reasoning_edit_cancel'); | ||
| 8100 | if (cancelButton instanceof HTMLElement) { | ||
| 8101 | cancelButton.click(); | ||
| 8102 | } | ||
| 8103 | }); | ||
| 8022 | } | 8104 | } |
| 8023 | } | 8105 | } |
| 8024 | 8106 | ||
| @@ -8451,6 +8533,9 @@ function swipe_left() { // when we swipe left..but no generation. | |||
| 8451 | streamingProcessor.onStopStreaming(); | 8533 | streamingProcessor.onStopStreaming(); |
| 8452 | } | 8534 | } |
| 8453 | 8535 | ||
| 8536 | // Make sure ad-hoc changes to extras are saved before swiping away | ||
| 8537 | syncCurrentSwipeInfoExtras(); | ||
| 8538 | |||
| 8454 | const swipe_duration = 120; | 8539 | const swipe_duration = 120; |
| 8455 | const swipe_range = '700px'; | 8540 | const swipe_range = '700px'; |
| 8456 | chat[chat.length - 1]['swipe_id']--; | 8541 | chat[chat.length - 1]['swipe_id']--; |
| @@ -8502,7 +8587,8 @@ function swipe_left() { // when we swipe left..but no generation. | |||
| 8502 | } | 8587 | } |
| 8503 | 8588 | ||
| 8504 | const swipeMessage = $('#chat').find(`[mesid="${chat.length - 1}"]`); | 8589 | const swipeMessage = $('#chat').find(`[mesid="${chat.length - 1}"]`); |
| 8505 | const tokenCount = await getTokenCountAsync(chat[chat.length - 1].mes, 0); | 8590 | const tokenCountText = (chat[chat.length - 1]?.extra?.reasoning || '') + chat[chat.length - 1].mes; |
| 8591 | const tokenCount = await getTokenCountAsync(tokenCountText, 0); | ||
| 8506 | chat[chat.length - 1]['extra']['token_count'] = tokenCount; | 8592 | chat[chat.length - 1]['extra']['token_count'] = tokenCount; |
| 8507 | swipeMessage.find('.tokenCounterDisplay').text(`${tokenCount}t`); | 8593 | swipeMessage.find('.tokenCounterDisplay').text(`${tokenCount}t`); |
| 8508 | } | 8594 | } |
| @@ -8585,6 +8671,9 @@ const swipe_right = () => { | |||
| 8585 | return unblockGeneration(); | 8671 | return unblockGeneration(); |
| 8586 | } | 8672 | } |
| 8587 | 8673 | ||
| 8674 | // Make sure ad-hoc changes to extras are saved before swiping away | ||
| 8675 | syncCurrentSwipeInfoExtras(); | ||
| 8676 | |||
| 8588 | const swipe_duration = 200; | 8677 | const swipe_duration = 200; |
| 8589 | const swipe_range = 700; | 8678 | const swipe_range = 700; |
| 8590 | //console.log(swipe_range); | 8679 | //console.log(swipe_range); |
| @@ -8666,6 +8755,7 @@ const swipe_right = () => { | |||
| 8666 | // resets the timer | 8755 | // resets the timer |
| 8667 | swipeMessage.find('.mes_timer').html(''); | 8756 | swipeMessage.find('.mes_timer').html(''); |
| 8668 | swipeMessage.find('.tokenCounterDisplay').text(''); | 8757 | swipeMessage.find('.tokenCounterDisplay').text(''); |
| 8758 | swipeMessage.find('.mes_reasoning').html(''); | ||
| 8669 | } else { | 8759 | } else { |
| 8670 | //console.log('showing previously generated swipe candidate, or "..."'); | 8760 | //console.log('showing previously generated swipe candidate, or "..."'); |
| 8671 | //console.log('onclick right swipe calling addOneMessage'); | 8761 | //console.log('onclick right swipe calling addOneMessage'); |
| @@ -8676,7 +8766,8 @@ const swipe_right = () => { | |||
| 8676 | chat[chat.length - 1].extra = {}; | 8766 | chat[chat.length - 1].extra = {}; |
| 8677 | } | 8767 | } |
| 8678 | 8768 | ||
| 8679 | const tokenCount = await getTokenCountAsync(chat[chat.length - 1].mes, 0); | 8769 | const tokenCountText = (chat[chat.length - 1]?.extra?.reasoning || '') + chat[chat.length - 1].mes; |
| 8770 | const tokenCount = await getTokenCountAsync(tokenCountText, 0); | ||
| 8680 | chat[chat.length - 1]['extra']['token_count'] = tokenCount; | 8771 | chat[chat.length - 1]['extra']['token_count'] = tokenCount; |
| 8681 | swipeMessage.find('.tokenCounterDisplay').text(`${tokenCount}t`); | 8772 | swipeMessage.find('.tokenCounterDisplay').text(`${tokenCount}t`); |
| 8682 | } | 8773 | } |
| @@ -9478,7 +9569,8 @@ function addDebugFunctions() { | |||
| 9478 | message.extra = {}; | 9569 | message.extra = {}; |
| 9479 | } | 9570 | } |
| 9480 | 9571 | ||
| 9481 | message.extra.token_count = await getTokenCountAsync(message.mes, 0); | 9572 | const tokenCountText = (message?.extra?.reasoning || '') + message.mes; |
| 9573 | message.extra.token_count = await getTokenCountAsync(tokenCountText, 0); | ||
| 9482 | } | 9574 | } |
| 9483 | 9575 | ||
| 9484 | await saveChatConditional(); | 9576 | await saveChatConditional(); |
| @@ -11290,14 +11382,15 @@ jQuery(async function () { | |||
| 11290 | 11382 | ||
| 11291 | $(document).keyup(function (e) { | 11383 | $(document).keyup(function (e) { |
| 11292 | if (e.key === 'Escape') { | 11384 | if (e.key === 'Escape') { |
| 11293 | const isEditVisible = $('#curEditTextarea').is(':visible'); | 11385 | const isEditVisible = $('#curEditTextarea').is(':visible') || $('.reasoning_edit_textarea').length > 0; |
| 11294 | if (isEditVisible && power_user.auto_save_msg_edits === false) { | 11386 | if (isEditVisible && power_user.auto_save_msg_edits === false) { |
| 11295 | closeMessageEditor(); | 11387 | closeMessageEditor('all'); |
| 11296 | $('#send_textarea').focus(); | 11388 | $('#send_textarea').focus(); |
| 11297 | return; | 11389 | return; |
| 11298 | } | 11390 | } |
| 11299 | if (isEditVisible && power_user.auto_save_msg_edits === true) { | 11391 | if (isEditVisible && power_user.auto_save_msg_edits === true) { |
| 11300 | $(`#chat .mes[mesid="${this_edit_mes_id}"] .mes_edit_done`).click(); | 11392 | $(`#chat .mes[mesid="${this_edit_mes_id}"] .mes_edit_done`).click(); |
| 11393 | closeMessageEditor('reasoning'); | ||
| 11301 | $('#send_textarea').focus(); | 11394 | $('#send_textarea').focus(); |
| 11302 | return; | 11395 | return; |
| 11303 | } | 11396 | } |
| @@ -482,10 +482,10 @@ function highlightNewBackground(bg) { | |||
| 482 | */ | 482 | */ |
| 483 | function setFittingClass(fitting) { | 483 | function setFittingClass(fitting) { |
| 484 | const backgrounds = $('#bg1, #bg_custom'); | 484 | const backgrounds = $('#bg1, #bg_custom'); |
| 485 | backgrounds.toggleClass('cover', fitting === 'cover'); | 485 | for (const option of ['cover', 'contain', 'stretch', 'center']) { |
| 486 | backgrounds.toggleClass('contain', fitting === 'contain'); | 486 | backgrounds.toggleClass(option, option === fitting); |
| 487 | backgrounds.toggleClass('stretch', fitting === 'stretch'); | 487 | } |
| 488 | backgrounds.toggleClass('center', fitting === 'center'); | 488 | background_settings.fitting = fitting; |
| 489 | } | 489 | } |
| 490 | 490 | ||
| 491 | function onBackgroundFilterInput() { | 491 | function onBackgroundFilterInput() { |
| @@ -466,7 +466,7 @@ async function processTtsQueue() { | |||
| 466 | } | 466 | } |
| 467 | 467 | ||
| 468 | if (extension_settings.tts.skip_tags) { | 468 | if (extension_settings.tts.skip_tags) { |
| 469 | text = text.replace(/<.*?>.*?<\/.*?>/g, '').trim(); | 469 | text = text.replace(/<.*?>[\s\S]*?<\/.*?>/g, '').trim(); |
| 470 | } | 470 | } |
| 471 | 471 | ||
| 472 | if (!extension_settings.tts.pass_asterisks) { | 472 | if (!extension_settings.tts.pass_asterisks) { |
| @@ -188,7 +188,7 @@ export async function generateKoboldWithStreaming(generate_data, signal) { | |||
| 188 | if (data?.token) { | 188 | if (data?.token) { |
| 189 | text += data.token; | 189 | text += data.token; |
| 190 | } | 190 | } |
| 191 | yield { text, swipes: [], toolCalls: [] }; | 191 | yield { text, swipes: [], toolCalls: [], state: {} }; |
| 192 | } | 192 | } |
| 193 | }; | 193 | }; |
| 194 | } | 194 | } |
| @@ -746,7 +746,7 @@ export async function generateNovelWithStreaming(generate_data, signal) { | |||
| 746 | text += data.token; | 746 | text += data.token; |
| 747 | } | 747 | } |
| 748 | 748 | ||
| 749 | yield { text, swipes: [], logprobs: parseNovelAILogprobs(data.logprobs), toolCalls: [] }; | 749 | yield { text, swipes: [], logprobs: parseNovelAILogprobs(data.logprobs), toolCalls: [], state: {} }; |
| 750 | } | 750 | } |
| 751 | }; | 751 | }; |
| 752 | } | 752 | } |
| @@ -1096,8 +1096,8 @@ async function preparePromptsForChatCompletion({ Scenario, charPersonality, name | |||
| 1096 | // Unordered prompts without marker | 1096 | // Unordered prompts without marker |
| 1097 | { role: 'system', content: impersonationPrompt, identifier: 'impersonate' }, | 1097 | { role: 'system', content: impersonationPrompt, identifier: 'impersonate' }, |
| 1098 | { role: 'system', content: quietPrompt, identifier: 'quietPrompt' }, | 1098 | { role: 'system', content: quietPrompt, identifier: 'quietPrompt' }, |
| 1099 | { role: 'system', content: bias, identifier: 'bias' }, | ||
| 1100 | { role: 'system', content: groupNudge, identifier: 'groupNudge' }, | 1099 | { role: 'system', content: groupNudge, identifier: 'groupNudge' }, |
| 1100 | { role: 'assistant', content: bias, identifier: 'bias' }, | ||
| 1101 | ]; | 1101 | ]; |
| 1102 | 1102 | ||
| 1103 | // Tavern Extras - Summary | 1103 | // Tavern Extras - Summary |
| @@ -2095,7 +2095,7 @@ async function sendOpenAIRequest(type, messages, signal) { | |||
| 2095 | let text = ''; | 2095 | let text = ''; |
| 2096 | const swipes = []; | 2096 | const swipes = []; |
| 2097 | const toolCalls = []; | 2097 | const toolCalls = []; |
| 2098 | const state = {}; | 2098 | const state = { reasoning: '' }; |
| 2099 | while (true) { | 2099 | while (true) { |
| 2100 | const { done, value } = await reader.read(); | 2100 | const { done, value } = await reader.read(); |
| 2101 | if (done) return; | 2101 | if (done) return; |
| @@ -2113,7 +2113,7 @@ async function sendOpenAIRequest(type, messages, signal) { | |||
| 2113 | 2113 | ||
| 2114 | ToolManager.parseToolCalls(toolCalls, parsed); | 2114 | ToolManager.parseToolCalls(toolCalls, parsed); |
| 2115 | 2115 | ||
| 2116 | yield { text, swipes: swipes, logprobs: parseChatCompletionLogprobs(parsed), toolCalls: toolCalls }; | 2116 | yield { text, swipes: swipes, logprobs: parseChatCompletionLogprobs(parsed), toolCalls: toolCalls, state: state }; |
| 2117 | } | 2117 | } |
| 2118 | }; | 2118 | }; |
| 2119 | } | 2119 | } |
| @@ -2150,16 +2150,22 @@ function getStreamingReply(data, state) { | |||
| 2150 | if (oai_settings.chat_completion_source === chat_completion_sources.CLAUDE) { | 2150 | if (oai_settings.chat_completion_source === chat_completion_sources.CLAUDE) { |
| 2151 | return data?.delta?.text || ''; | 2151 | return data?.delta?.text || ''; |
| 2152 | } else if (oai_settings.chat_completion_source === chat_completion_sources.MAKERSUITE) { | 2152 | } else if (oai_settings.chat_completion_source === chat_completion_sources.MAKERSUITE) { |
| 2153 | return data?.candidates?.[0]?.content?.parts?.filter(x => oai_settings.show_thoughts || !x.thought)?.map(x => x.text)?.filter(x => x)?.join('\n\n') || ''; | 2153 | if (oai_settings.show_thoughts) { |
| 2154 | state.reasoning += (data?.candidates?.[0]?.content?.parts?.filter(x => x.thought)?.map(x => x.text)?.[0] || ''); | ||
| 2155 | } | ||
| 2156 | return data?.candidates?.[0]?.content?.parts?.filter(x => !x.thought)?.map(x => x.text)?.[0] || ''; | ||
| 2154 | } else if (oai_settings.chat_completion_source === chat_completion_sources.COHERE) { | 2157 | } else if (oai_settings.chat_completion_source === chat_completion_sources.COHERE) { |
| 2155 | return data?.delta?.message?.content?.text || data?.delta?.message?.tool_plan || ''; | 2158 | return data?.delta?.message?.content?.text || data?.delta?.message?.tool_plan || ''; |
| 2156 | } else if (oai_settings.chat_completion_source === chat_completion_sources.DEEPSEEK) { | 2159 | } else if (oai_settings.chat_completion_source === chat_completion_sources.DEEPSEEK) { |
| 2157 | const hadThoughts = state.hadThoughts; | 2160 | if (oai_settings.show_thoughts) { |
| 2158 | const thoughts = data.choices?.filter(x => oai_settings.show_thoughts || !x?.delta?.reasoning_content)?.[0]?.delta?.reasoning_content || ''; | 2161 | state.reasoning += (data.choices?.filter(x => x?.delta?.reasoning_content)?.[0]?.delta?.reasoning_content || ''); |
| 2159 | const content = data.choices?.[0]?.delta?.content || ''; | 2162 | } |
| 2160 | state.hadThoughts = !!thoughts; | 2163 | return data.choices?.[0]?.delta?.content || ''; |
| 2161 | const separator = hadThoughts && !thoughts ? '\n\n' : ''; | 2164 | } else if (oai_settings.chat_completion_source === chat_completion_sources.OPENROUTER) { |
| 2162 | return [thoughts, separator, content].filter(x => x).join('\n\n'); | 2165 | if (oai_settings.show_thoughts) { |
| 2166 | state.reasoning += (data.choices?.filter(x => x?.delta?.reasoning)?.[0]?.delta?.reasoning || ''); | ||
| 2167 | } | ||
| 2168 | return data.choices?.[0]?.delta?.content ?? data.choices?.[0]?.message?.content ?? data.choices?.[0]?.text ?? ''; | ||
| 2163 | } else { | 2169 | } else { |
| 2164 | return data.choices?.[0]?.delta?.content ?? data.choices?.[0]?.message?.content ?? data.choices?.[0]?.text ?? ''; | 2170 | return data.choices?.[0]?.delta?.content ?? data.choices?.[0]?.message?.content ?? data.choices?.[0]?.text ?? ''; |
| 2165 | } | 2171 | } |
| @@ -253,6 +253,14 @@ let power_user = { | |||
| 253 | content: 'Write {{char}}\'s next reply in a fictional chat between {{char}} and {{user}}.', | 253 | content: 'Write {{char}}\'s next reply in a fictional chat between {{char}} and {{user}}.', |
| 254 | }, | 254 | }, |
| 255 | 255 | ||
| 256 | reasoning: { | ||
| 257 | add_to_prompts: false, | ||
| 258 | prefix: '<think>\n', | ||
| 259 | suffix: '\n</think>', | ||
| 260 | separator: '\n\n', | ||
| 261 | max_additions: 1, | ||
| 262 | }, | ||
| 263 | |||
| 256 | personas: {}, | 264 | personas: {}, |
| 257 | default_persona: null, | 265 | default_persona: null, |
| 258 | persona_descriptions: {}, | 266 | persona_descriptions: {}, |
| @@ -0,0 +1,297 @@ | |||
| 1 | import { chat, closeMessageEditor, saveChatConditional, saveSettingsDebounced, substituteParams, updateMessageBlock } from '../script.js'; | ||
| 2 | import { t } from './i18n.js'; | ||
| 3 | import { MacrosParser } from './macros.js'; | ||
| 4 | import { Popup } from './popup.js'; | ||
| 5 | import { power_user } from './power-user.js'; | ||
| 6 | import { SlashCommand } from './slash-commands/SlashCommand.js'; | ||
| 7 | import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './slash-commands/SlashCommandArgument.js'; | ||
| 8 | import { commonEnumProviders } from './slash-commands/SlashCommandCommonEnumsProvider.js'; | ||
| 9 | import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; | ||
| 10 | import { copyText } from './utils.js'; | ||
| 11 | |||
| 12 | /** | ||
| 13 | * Gets a message from a jQuery element. | ||
| 14 | * @param {Element} element | ||
| 15 | * @returns {{messageId: number, message: object, messageBlock: JQuery<HTMLElement>}} | ||
| 16 | */ | ||
| 17 | function getMessageFromJquery(element) { | ||
| 18 | const messageBlock = $(element).closest('.mes'); | ||
| 19 | const messageId = Number(messageBlock.attr('mesid')); | ||
| 20 | const message = chat[messageId]; | ||
| 21 | return { messageId: messageId, message, messageBlock }; | ||
| 22 | } | ||
| 23 | |||
| 24 | /** | ||
| 25 | * Helper class for adding reasoning to messages. | ||
| 26 | * Keeps track of the number of reasoning additions. | ||
| 27 | */ | ||
| 28 | export class PromptReasoning { | ||
| 29 | static REASONING_PLACEHOLDER = '\u200B'; | ||
| 30 | static REASONING_PLACEHOLDER_REGEX = new RegExp(`${PromptReasoning.REASONING_PLACEHOLDER}$`); | ||
| 31 | |||
| 32 | constructor() { | ||
| 33 | this.counter = 0; | ||
| 34 | } | ||
| 35 | |||
| 36 | /** | ||
| 37 | * Checks if the limit of reasoning additions has been reached. | ||
| 38 | * @returns {boolean} True if the limit of reasoning additions has been reached, false otherwise. | ||
| 39 | */ | ||
| 40 | isLimitReached() { | ||
| 41 | if (!power_user.reasoning.add_to_prompts) { | ||
| 42 | return true; | ||
| 43 | } | ||
| 44 | |||
| 45 | return this.counter >= power_user.reasoning.max_additions; | ||
| 46 | } | ||
| 47 | |||
| 48 | /** | ||
| 49 | * Add reasoning to a message according to the power user settings. | ||
| 50 | * @param {string} content Message content | ||
| 51 | * @param {string} reasoning Message reasoning | ||
| 52 | * @returns {string} Message content with reasoning | ||
| 53 | */ | ||
| 54 | addToMessage(content, reasoning) { | ||
| 55 | // Disabled or reached limit of additions | ||
| 56 | if (!power_user.reasoning.add_to_prompts || this.counter >= power_user.reasoning.max_additions) { | ||
| 57 | return content; | ||
| 58 | } | ||
| 59 | |||
| 60 | // No reasoning provided or a placeholder | ||
| 61 | if (!reasoning || reasoning === PromptReasoning.REASONING_PLACEHOLDER) { | ||
| 62 | return content; | ||
| 63 | } | ||
| 64 | |||
| 65 | // Increment the counter | ||
| 66 | this.counter++; | ||
| 67 | |||
| 68 | // Substitute macros in variable parts | ||
| 69 | const prefix = substituteParams(power_user.reasoning.prefix || ''); | ||
| 70 | const separator = substituteParams(power_user.reasoning.separator || ''); | ||
| 71 | const suffix = substituteParams(power_user.reasoning.suffix || ''); | ||
| 72 | |||
| 73 | // Combine parts with reasoning and content | ||
| 74 | return `${prefix}${reasoning}${suffix}${separator}${content}`; | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 78 | function loadReasoningSettings() { | ||
| 79 | $('#reasoning_add_to_prompts').prop('checked', power_user.reasoning.add_to_prompts); | ||
| 80 | $('#reasoning_add_to_prompts').on('change', function () { | ||
| 81 | power_user.reasoning.add_to_prompts = !!$(this).prop('checked'); | ||
| 82 | saveSettingsDebounced(); | ||
| 83 | }); | ||
| 84 | |||
| 85 | $('#reasoning_prefix').val(power_user.reasoning.prefix); | ||
| 86 | $('#reasoning_prefix').on('input', function () { | ||
| 87 | power_user.reasoning.prefix = String($(this).val()); | ||
| 88 | saveSettingsDebounced(); | ||
| 89 | }); | ||
| 90 | |||
| 91 | $('#reasoning_suffix').val(power_user.reasoning.suffix); | ||
| 92 | $('#reasoning_suffix').on('input', function () { | ||
| 93 | power_user.reasoning.suffix = String($(this).val()); | ||
| 94 | saveSettingsDebounced(); | ||
| 95 | }); | ||
| 96 | |||
| 97 | $('#reasoning_separator').val(power_user.reasoning.separator); | ||
| 98 | $('#reasoning_separator').on('input', function () { | ||
| 99 | power_user.reasoning.separator = String($(this).val()); | ||
| 100 | saveSettingsDebounced(); | ||
| 101 | }); | ||
| 102 | |||
| 103 | $('#reasoning_max_additions').val(power_user.reasoning.max_additions); | ||
| 104 | $('#reasoning_max_additions').on('input', function () { | ||
| 105 | power_user.reasoning.max_additions = Number($(this).val()); | ||
| 106 | saveSettingsDebounced(); | ||
| 107 | }); | ||
| 108 | } | ||
| 109 | |||
| 110 | function registerReasoningSlashCommands() { | ||
| 111 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | ||
| 112 | name: 'reasoning-get', | ||
| 113 | returns: ARGUMENT_TYPE.STRING, | ||
| 114 | helpString: t`Get the contents of a reasoning block of a message. Returns an empty string if the message does not have a reasoning block.`, | ||
| 115 | unnamedArgumentList: [ | ||
| 116 | SlashCommandArgument.fromProps({ | ||
| 117 | description: 'Message ID. If not provided, the message ID of the last message is used.', | ||
| 118 | typeList: ARGUMENT_TYPE.NUMBER, | ||
| 119 | enumProvider: commonEnumProviders.messages(), | ||
| 120 | }), | ||
| 121 | ], | ||
| 122 | callback: (_args, value) => { | ||
| 123 | const messageId = !isNaN(Number(value)) ? Number(value) : chat.length - 1; | ||
| 124 | const message = chat[messageId]; | ||
| 125 | const reasoning = String(message?.extra?.reasoning ?? ''); | ||
| 126 | return reasoning.replace(PromptReasoning.REASONING_PLACEHOLDER_REGEX, ''); | ||
| 127 | }, | ||
| 128 | })); | ||
| 129 | |||
| 130 | SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | ||
| 131 | name: 'reasoning-set', | ||
| 132 | returns: ARGUMENT_TYPE.STRING, | ||
| 133 | helpString: t`Set the reasoning block of a message. Returns the reasoning block content.`, | ||
| 134 | namedArgumentList: [ | ||
| 135 | SlashCommandNamedArgument.fromProps({ | ||
| 136 | name: 'at', | ||
| 137 | description: 'Message ID. If not provided, the message ID of the last message is used.', | ||
| 138 | typeList: ARGUMENT_TYPE.NUMBER, | ||
| 139 | enumProvider: commonEnumProviders.messages(), | ||
| 140 | }), | ||
| 141 | ], | ||
| 142 | unnamedArgumentList: [ | ||
| 143 | SlashCommandArgument.fromProps({ | ||
| 144 | description: 'Reasoning block content.', | ||
| 145 | typeList: ARGUMENT_TYPE.STRING, | ||
| 146 | }), | ||
| 147 | ], | ||
| 148 | callback: async (args, value) => { | ||
| 149 | const messageId = !isNaN(Number(args[0])) ? Number(args[0]) : chat.length - 1; | ||
| 150 | const message = chat[messageId]; | ||
| 151 | if (!message?.extra) { | ||
| 152 | return ''; | ||
| 153 | } | ||
| 154 | |||
| 155 | message.extra.reasoning = String(value ?? ''); | ||
| 156 | await saveChatConditional(); | ||
| 157 | |||
| 158 | closeMessageEditor('reasoning'); | ||
| 159 | updateMessageBlock(messageId, message); | ||
| 160 | return message.extra.reasoning; | ||
| 161 | }, | ||
| 162 | })); | ||
| 163 | } | ||
| 164 | |||
| 165 | function registerReasoningMacros() { | ||
| 166 | MacrosParser.registerMacro('reasoningPrefix', () => power_user.reasoning.prefix, t`Reasoning Prefix`); | ||
| 167 | MacrosParser.registerMacro('reasoningSuffix', () => power_user.reasoning.suffix, t`Reasoning Suffix`); | ||
| 168 | MacrosParser.registerMacro('reasoningSeparator', () => power_user.reasoning.separator, t`Reasoning Separator`); | ||
| 169 | } | ||
| 170 | |||
| 171 | function setReasoningEventHandlers(){ | ||
| 172 | $(document).on('click', '.mes_reasoning_copy', (e) => { | ||
| 173 | e.stopPropagation(); | ||
| 174 | e.preventDefault(); | ||
| 175 | }); | ||
| 176 | |||
| 177 | $(document).on('click', '.mes_reasoning_edit', function (e) { | ||
| 178 | e.stopPropagation(); | ||
| 179 | e.preventDefault(); | ||
| 180 | const { message, messageBlock } = getMessageFromJquery(this); | ||
| 181 | if (!message?.extra) { | ||
| 182 | return; | ||
| 183 | } | ||
| 184 | |||
| 185 | const reasoning = String(message?.extra?.reasoning ?? ''); | ||
| 186 | const chatElement = document.getElementById('chat'); | ||
| 187 | const textarea = document.createElement('textarea'); | ||
| 188 | const reasoningBlock = messageBlock.find('.mes_reasoning'); | ||
| 189 | textarea.classList.add('reasoning_edit_textarea'); | ||
| 190 | textarea.value = reasoning.replace(PromptReasoning.REASONING_PLACEHOLDER_REGEX, ''); | ||
| 191 | $(textarea).insertBefore(reasoningBlock); | ||
| 192 | |||
| 193 | if (!CSS.supports('field-sizing', 'content')) { | ||
| 194 | const resetHeight = function () { | ||
| 195 | const scrollTop = chatElement.scrollTop; | ||
| 196 | textarea.style.height = '0px'; | ||
| 197 | textarea.style.height = `${textarea.scrollHeight}px`; | ||
| 198 | chatElement.scrollTop = scrollTop; | ||
| 199 | }; | ||
| 200 | |||
| 201 | textarea.addEventListener('input', resetHeight); | ||
| 202 | resetHeight(); | ||
| 203 | } | ||
| 204 | |||
| 205 | textarea.focus(); | ||
| 206 | textarea.setSelectionRange(textarea.value.length, textarea.value.length); | ||
| 207 | |||
| 208 | const textareaRect = textarea.getBoundingClientRect(); | ||
| 209 | const chatRect = chatElement.getBoundingClientRect(); | ||
| 210 | |||
| 211 | // Scroll if textarea bottom is below visible area | ||
| 212 | if (textareaRect.bottom > chatRect.bottom) { | ||
| 213 | const scrollOffset = textareaRect.bottom - chatRect.bottom; | ||
| 214 | chatElement.scrollTop += scrollOffset; | ||
| 215 | } | ||
| 216 | }); | ||
| 217 | |||
| 218 | $(document).on('click', '.mes_reasoning_edit_done', async function (e) { | ||
| 219 | e.stopPropagation(); | ||
| 220 | e.preventDefault(); | ||
| 221 | const { message, messageId, messageBlock } = getMessageFromJquery(this); | ||
| 222 | if (!message?.extra) { | ||
| 223 | return; | ||
| 224 | } | ||
| 225 | |||
| 226 | const textarea = messageBlock.find('.reasoning_edit_textarea'); | ||
| 227 | const reasoning = String(textarea.val()); | ||
| 228 | message.extra.reasoning = reasoning; | ||
| 229 | await saveChatConditional(); | ||
| 230 | updateMessageBlock(messageId, message); | ||
| 231 | textarea.remove(); | ||
| 232 | }); | ||
| 233 | |||
| 234 | $(document).on('click', '.mes_reasoning_edit_cancel', function (e) { | ||
| 235 | e.stopPropagation(); | ||
| 236 | e.preventDefault(); | ||
| 237 | |||
| 238 | const { messageBlock } = getMessageFromJquery(this); | ||
| 239 | const textarea = messageBlock.find('.reasoning_edit_textarea'); | ||
| 240 | textarea.remove(); | ||
| 241 | }); | ||
| 242 | |||
| 243 | $(document).on('click', '.mes_edit_add_reasoning', async function () { | ||
| 244 | const { message, messageId } = getMessageFromJquery(this); | ||
| 245 | if (!message?.extra) { | ||
| 246 | return; | ||
| 247 | } | ||
| 248 | |||
| 249 | if (message.extra.reasoning) { | ||
| 250 | toastr.info(t`Reasoning already exists.`, t`Edit Message`); | ||
| 251 | return; | ||
| 252 | } | ||
| 253 | |||
| 254 | message.extra.reasoning = PromptReasoning.REASONING_PLACEHOLDER; | ||
| 255 | await saveChatConditional(); | ||
| 256 | closeMessageEditor(); | ||
| 257 | updateMessageBlock(messageId, message); | ||
| 258 | }); | ||
| 259 | |||
| 260 | $(document).on('click', '.mes_reasoning_delete', async function (e) { | ||
| 261 | e.stopPropagation(); | ||
| 262 | e.preventDefault(); | ||
| 263 | |||
| 264 | const confirm = await Popup.show.confirm(t`Are you sure you want to clear the reasoning?`, t`Visible message contents will stay intact.`); | ||
| 265 | |||
| 266 | if (!confirm) { | ||
| 267 | return; | ||
| 268 | } | ||
| 269 | |||
| 270 | const { message, messageId } = getMessageFromJquery(this); | ||
| 271 | if (!message?.extra) { | ||
| 272 | return; | ||
| 273 | } | ||
| 274 | message.extra.reasoning = ''; | ||
| 275 | await saveChatConditional(); | ||
| 276 | updateMessageBlock(messageId, message); | ||
| 277 | }); | ||
| 278 | |||
| 279 | $(document).on('pointerup', '.mes_reasoning_copy', async function () { | ||
| 280 | const { message } = getMessageFromJquery(this); | ||
| 281 | const reasoning = String(message?.extra?.reasoning ?? '').replace(PromptReasoning.REASONING_PLACEHOLDER_REGEX, ''); | ||
| 282 | |||
| 283 | if (!reasoning) { | ||
| 284 | return; | ||
| 285 | } | ||
| 286 | |||
| 287 | await copyText(reasoning); | ||
| 288 | toastr.info(t`Copied!`, '', { timeOut: 2000 }); | ||
| 289 | }); | ||
| 290 | } | ||
| 291 | |||
| 292 | export function initReasoning() { | ||
| 293 | loadReasoningSettings(); | ||
| 294 | setReasoningEventHandlers(); | ||
| 295 | registerReasoningSlashCommands(); | ||
| 296 | registerReasoningMacros(); | ||
| 297 | } | ||
| @@ -42,6 +42,7 @@ import { | |||
| 42 | showMoreMessages, | 42 | showMoreMessages, |
| 43 | stopGeneration, | 43 | stopGeneration, |
| 44 | substituteParams, | 44 | substituteParams, |
| 45 | syncCurrentSwipeInfoExtras, | ||
| 45 | system_avatar, | 46 | system_avatar, |
| 46 | system_message_types, | 47 | system_message_types, |
| 47 | this_chid, | 48 | this_chid, |
| @@ -2862,8 +2863,11 @@ async function addSwipeCallback(args, value) { | |||
| 2862 | const newSwipeId = lastMessage.swipes.length - 1; | 2863 | const newSwipeId = lastMessage.swipes.length - 1; |
| 2863 | 2864 | ||
| 2864 | if (isTrueBoolean(args.switch)) { | 2865 | if (isTrueBoolean(args.switch)) { |
| 2866 | // Make sure ad-hoc changes to extras are saved before swiping away | ||
| 2867 | syncCurrentSwipeInfoExtras(); | ||
| 2865 | lastMessage.swipe_id = newSwipeId; | 2868 | lastMessage.swipe_id = newSwipeId; |
| 2866 | lastMessage.mes = lastMessage.swipes[newSwipeId]; | 2869 | lastMessage.mes = lastMessage.swipes[newSwipeId]; |
| 2870 | lastMessage.extra = structuredClone(lastMessage.swipe_info?.[newSwipeId]?.extra ?? lastMessage.extra ?? {}); | ||
| 2867 | } | 2871 | } |
| 2868 | 2872 | ||
| 2869 | await saveChatConditional(); | 2873 | await saveChatConditional(); |
| @@ -235,6 +235,21 @@ async function* parseStreamData(json) { | |||
| 235 | } | 235 | } |
| 236 | return; | 236 | return; |
| 237 | } | 237 | } |
| 238 | else if (typeof json.choices[0].delta.reasoning === 'string' && json.choices[0].delta.reasoning.length > 0) { | ||
| 239 | for (let j = 0; j < json.choices[0].delta.reasoning.length; j++) { | ||
| 240 | const str = json.choices[0].delta.reasoning[j]; | ||
| 241 | const isLastSymbol = j === json.choices[0].delta.reasoning.length - 1; | ||
| 242 | const choiceClone = structuredClone(json.choices[0]); | ||
| 243 | choiceClone.delta.reasoning = str; | ||
| 244 | choiceClone.delta.content = isLastSymbol ? choiceClone.delta.content : ''; | ||
| 245 | const choices = [choiceClone]; | ||
| 246 | yield { | ||
| 247 | data: { ...json, choices }, | ||
| 248 | chunk: str, | ||
| 249 | }; | ||
| 250 | } | ||
| 251 | return; | ||
| 252 | } | ||
| 238 | else if (typeof json.choices[0].delta.content === 'string' && json.choices[0].delta.content.length > 0) { | 253 | else if (typeof json.choices[0].delta.content === 'string' && json.choices[0].delta.content.length > 0) { |
| 239 | for (let j = 0; j < json.choices[0].delta.content.length; j++) { | 254 | for (let j = 0; j < json.choices[0].delta.content.length; j++) { |
| 240 | const str = json.choices[0].delta.content[j]; | 255 | const str = json.choices[0].delta.content[j]; |
| @@ -1,6 +1,7 @@ | |||
| 1 | import { | 1 | import { |
| 2 | activateSendButtons, | 2 | activateSendButtons, |
| 3 | addOneMessage, | 3 | addOneMessage, |
| 4 | appendMediaToMessage, | ||
| 4 | callPopup, | 5 | callPopup, |
| 5 | characters, | 6 | characters, |
| 6 | chat, | 7 | chat, |
| @@ -41,6 +42,7 @@ import { | |||
| 41 | substituteParamsExtended, | 42 | substituteParamsExtended, |
| 42 | this_chid, | 43 | this_chid, |
| 43 | updateChatMetadata, | 44 | updateChatMetadata, |
| 45 | updateMessageBlock, | ||
| 44 | } from '../script.js'; | 46 | } from '../script.js'; |
| 45 | import { | 47 | import { |
| 46 | extension_settings, | 48 | extension_settings, |
| @@ -171,6 +173,8 @@ export function getContext() { | |||
| 171 | getCharacters, | 173 | getCharacters, |
| 172 | uuidv4, | 174 | uuidv4, |
| 173 | humanizedDateTime, | 175 | humanizedDateTime, |
| 176 | updateMessageBlock, | ||
| 177 | appendMediaToMessage, | ||
| 174 | }; | 178 | }; |
| 175 | } | 179 | } |
| 176 | 180 | ||
| @@ -986,6 +986,7 @@ export async function generateTextGenWithStreaming(generate_data, signal) { | |||
| 986 | let logprobs = null; | 986 | let logprobs = null; |
| 987 | const swipes = []; | 987 | const swipes = []; |
| 988 | const toolCalls = []; | 988 | const toolCalls = []; |
| 989 | const state = {}; | ||
| 989 | while (true) { | 990 | while (true) { |
| 990 | const { done, value } = await reader.read(); | 991 | const { done, value } = await reader.read(); |
| 991 | if (done) return; | 992 | if (done) return; |
| @@ -1004,7 +1005,7 @@ export async function generateTextGenWithStreaming(generate_data, signal) { | |||
| 1004 | logprobs = parseTextgenLogprobs(newText, data.choices?.[0]?.logprobs || data?.completion_probabilities); | 1005 | logprobs = parseTextgenLogprobs(newText, data.choices?.[0]?.logprobs || data?.completion_probabilities); |
| 1005 | } | 1006 | } |
| 1006 | 1007 | ||
| 1007 | yield { text, swipes, logprobs, toolCalls }; | 1008 | yield { text, swipes, logprobs, toolCalls, state }; |
| 1008 | } | 1009 | } |
| 1009 | }; | 1010 | }; |
| 1010 | } | 1011 | } |
| @@ -292,36 +292,44 @@ input[type='checkbox']:focus-visible { | |||
| 292 | filter: grayscale(25%); | 292 | filter: grayscale(25%); |
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | .mes_text table { | 295 | .mes_text table, |
| 296 | .mes_reasoning table { | ||
| 296 | border-spacing: 0; | 297 | border-spacing: 0; |
| 297 | border-collapse: collapse; | 298 | border-collapse: collapse; |
| 298 | margin-bottom: 10px; | 299 | margin-bottom: 10px; |
| 299 | } | 300 | } |
| 300 | 301 | ||
| 301 | .mes_text td, | 302 | .mes_text td, |
| 302 | .mes_text th { | 303 | .mes_text th, |
| 304 | .mes_reasoning td, | ||
| 305 | .mes_reasoning th { | ||
| 303 | border: 1px solid; | 306 | border: 1px solid; |
| 304 | border-collapse: collapse; | 307 | border-collapse: collapse; |
| 305 | padding: 0.25em; | 308 | padding: 0.25em; |
| 306 | } | 309 | } |
| 307 | 310 | ||
| 308 | .mes_text p { | 311 | .mes_text p, |
| 312 | .mes_reasoning p { | ||
| 309 | margin-top: 0; | 313 | margin-top: 0; |
| 310 | margin-bottom: 10px; | 314 | margin-bottom: 10px; |
| 311 | } | 315 | } |
| 312 | 316 | ||
| 313 | .mes_text li tt { | 317 | .mes_text li tt, |
| 318 | .mes_reasoning li tt { | ||
| 314 | display: inline-block; | 319 | display: inline-block; |
| 315 | } | 320 | } |
| 316 | 321 | ||
| 317 | .mes_text ol, | 322 | .mes_text ol, |
| 318 | .mes_text ul { | 323 | .mes_text ul, |
| 324 | .mes_reasoning ol, | ||
| 325 | .mes_reasoning ul { | ||
| 319 | margin-top: 5px; | 326 | margin-top: 5px; |
| 320 | margin-bottom: 5px; | 327 | margin-bottom: 5px; |
| 321 | } | 328 | } |
| 322 | 329 | ||
| 323 | .mes_text br, | 330 | .mes_text br, |
| 324 | .mes_bias br { | 331 | .mes_bias br, |
| 332 | .mes_reasoning br { | ||
| 325 | content: ' '; | 333 | content: ' '; |
| 326 | } | 334 | } |
| 327 | 335 | ||
| @@ -332,25 +340,83 @@ input[type='checkbox']:focus-visible { | |||
| 332 | color: var(--SmartThemeQuoteColor); | 340 | color: var(--SmartThemeQuoteColor); |
| 333 | } | 341 | } |
| 334 | 342 | ||
| 343 | .mes_reasoning { | ||
| 344 | display: block; | ||
| 345 | border: 1px solid var(--SmartThemeBorderColor); | ||
| 346 | background-color: var(--black30a); | ||
| 347 | border-radius: 5px; | ||
| 348 | padding: 5px; | ||
| 349 | margin: 5px 0; | ||
| 350 | overflow-y: auto; | ||
| 351 | } | ||
| 352 | |||
| 353 | .mes_reasoning_summary { | ||
| 354 | cursor: pointer; | ||
| 355 | position: relative; | ||
| 356 | margin: 2px; | ||
| 357 | } | ||
| 358 | |||
| 359 | @supports not selector(:has(*)) { | ||
| 360 | .mes_reasoning_details { | ||
| 361 | display: none !important; | ||
| 362 | } | ||
| 363 | } | ||
| 364 | |||
| 365 | .mes_bias:empty, | ||
| 366 | .mes_reasoning:empty, | ||
| 367 | .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, | ||
| 370 | .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, | ||
| 372 | .mes_reasoning_details:not(:has(.reasoning_edit_textarea)) .mes_reasoning_actions .mes_button.mes_reasoning_edit_cancel, | ||
| 373 | .mes_reasoning_details:has(.reasoning_edit_textarea) .mes_reasoning_actions .mes_button:not(.mes_reasoning_edit_done, .mes_reasoning_edit_cancel) { | ||
| 374 | display: none; | ||
| 375 | } | ||
| 376 | |||
| 377 | .mes_reasoning_actions { | ||
| 378 | position: absolute; | ||
| 379 | right: 0; | ||
| 380 | top: 0; | ||
| 381 | |||
| 382 | display: flex; | ||
| 383 | gap: 4px; | ||
| 384 | flex-wrap: nowrap; | ||
| 385 | justify-content: flex-end; | ||
| 386 | transition: all 200ms; | ||
| 387 | overflow-x: hidden; | ||
| 388 | padding: 1px; | ||
| 389 | } | ||
| 390 | |||
| 391 | .mes_reasoning_summary>span { | ||
| 392 | margin-left: 0.5em; | ||
| 393 | } | ||
| 394 | |||
| 335 | .mes_text i, | 395 | .mes_text i, |
| 336 | .mes_text em { | 396 | .mes_text em, |
| 397 | .mes_reasoning i, | ||
| 398 | .mes_reasoning em { | ||
| 337 | color: var(--SmartThemeEmColor); | 399 | color: var(--SmartThemeEmColor); |
| 338 | } | 400 | } |
| 339 | 401 | ||
| 340 | .mes_text u { | 402 | .mes_text u, |
| 403 | .mes_reasoning u { | ||
| 341 | color: var(--SmartThemeUnderlineColor); | 404 | color: var(--SmartThemeUnderlineColor); |
| 342 | } | 405 | } |
| 343 | 406 | ||
| 344 | .mes_text q { | 407 | .mes_text q, |
| 408 | .mes_reasoning q { | ||
| 345 | color: var(--SmartThemeQuoteColor); | 409 | color: var(--SmartThemeQuoteColor); |
| 346 | } | 410 | } |
| 347 | 411 | ||
| 348 | .mes_text font[color] em, | 412 | .mes_text font[color] em, |
| 349 | .mes_text font[color] i { | 413 | .mes_text font[color] i, |
| 350 | color: inherit; | 414 | .mes_text font[color] u, |
| 351 | } | 415 | .mes_text font[color] q, |
| 352 | 416 | .mes_reasoning font[color] em, | |
| 353 | .mes_text font[color] q { | 417 | .mes_reasoning font[color] i, |
| 418 | .mes_reasoning font[color] u, | ||
| 419 | .mes_reasoning font[color] q { | ||
| 354 | color: inherit; | 420 | color: inherit; |
| 355 | } | 421 | } |
| 356 | 422 | ||
| @@ -358,7 +424,8 @@ input[type='checkbox']:focus-visible { | |||
| 358 | display: block; | 424 | display: block; |
| 359 | } | 425 | } |
| 360 | 426 | ||
| 361 | .mes_text blockquote { | 427 | .mes_text blockquote, |
| 428 | .mes_reasoning blockquote { | ||
| 362 | border-left: 3px solid var(--SmartThemeQuoteColor); | 429 | border-left: 3px solid var(--SmartThemeQuoteColor); |
| 363 | padding-left: 10px; | 430 | padding-left: 10px; |
| 364 | background-color: var(--black30a); | 431 | background-color: var(--black30a); |
| @@ -368,18 +435,24 @@ input[type='checkbox']:focus-visible { | |||
| 368 | .mes_text strong em, | 435 | .mes_text strong em, |
| 369 | .mes_text strong, | 436 | .mes_text strong, |
| 370 | .mes_text h2, | 437 | .mes_text h2, |
| 371 | .mes_text h1 { | 438 | .mes_text h1, |
| 439 | .mes_reasoning strong em, | ||
| 440 | .mes_reasoning strong, | ||
| 441 | .mes_reasoning h2, | ||
| 442 | .mes_reasoning h1 { | ||
| 372 | font-weight: bold; | 443 | font-weight: bold; |
| 373 | } | 444 | } |
| 374 | 445 | ||
| 375 | .mes_text pre code { | 446 | .mes_text pre code, |
| 447 | .mes_reasoning pre code { | ||
| 376 | position: relative; | 448 | position: relative; |
| 377 | display: block; | 449 | display: block; |
| 378 | overflow-x: auto; | 450 | overflow-x: auto; |
| 379 | padding: 1em; | 451 | padding: 1em; |
| 380 | } | 452 | } |
| 381 | 453 | ||
| 382 | .mes_text img:not(.mes_img) { | 454 | .mes_text img:not(.mes_img), |
| 455 | .mes_reasoning img:not(.mes_img) { | ||
| 383 | max-width: 100%; | 456 | max-width: 100%; |
| 384 | max-height: var(--doc-height); | 457 | max-height: var(--doc-height); |
| 385 | } | 458 | } |
| @@ -1022,6 +1095,11 @@ body .panelControlBar { | |||
| 1022 | /*only affects bubblechat to make it sit nicely at the bottom*/ | 1095 | /*only affects bubblechat to make it sit nicely at the bottom*/ |
| 1023 | } | 1096 | } |
| 1024 | 1097 | ||
| 1098 | .last_mes:has(.mes_text:empty):has(.mes_reasoning_details[open]) .mes_reasoning:not(:empty) { | ||
| 1099 | margin-bottom: 30px; | ||
| 1100 | } | ||
| 1101 | |||
| 1102 | .last_mes .mes_reasoning, | ||
| 1025 | .last_mes .mes_text { | 1103 | .last_mes .mes_text { |
| 1026 | padding-right: 30px; | 1104 | padding-right: 30px; |
| 1027 | } | 1105 | } |
| @@ -1242,14 +1320,18 @@ body.swipeAllMessages .mes:not(.last_mes) .swipes-counter { | |||
| 1242 | overflow-y: clip; | 1320 | overflow-y: clip; |
| 1243 | } | 1321 | } |
| 1244 | 1322 | ||
| 1245 | .mes_text { | 1323 | .mes_text, |
| 1324 | .mes_reasoning { | ||
| 1246 | font-weight: 500; | 1325 | font-weight: 500; |
| 1247 | line-height: calc(var(--mainFontSize) + .5rem); | 1326 | line-height: calc(var(--mainFontSize) + .5rem); |
| 1327 | max-width: 100%; | ||
| 1328 | overflow-wrap: anywhere; | ||
| 1329 | } | ||
| 1330 | |||
| 1331 | .mes_text { | ||
| 1248 | padding-left: 0; | 1332 | padding-left: 0; |
| 1249 | padding-top: 5px; | 1333 | padding-top: 5px; |
| 1250 | padding-bottom: 5px; | 1334 | padding-bottom: 5px; |
| 1251 | max-width: 100%; | ||
| 1252 | overflow-wrap: anywhere; | ||
| 1253 | } | 1335 | } |
| 1254 | 1336 | ||
| 1255 | br { | 1337 | br { |
| @@ -4169,10 +4251,12 @@ input[type="range"]::-webkit-slider-thumb { | |||
| 4169 | align-items: center; | 4251 | align-items: center; |
| 4170 | } | 4252 | } |
| 4171 | 4253 | ||
| 4254 | .mes_reasoning_edit_cancel, | ||
| 4172 | .mes_edit_cancel.menu_button { | 4255 | .mes_edit_cancel.menu_button { |
| 4173 | background-color: var(--crimson70a); | 4256 | background-color: var(--crimson70a); |
| 4174 | } | 4257 | } |
| 4175 | 4258 | ||
| 4259 | .mes_reasoning_edit_done, | ||
| 4176 | .mes_edit_done.menu_button { | 4260 | .mes_edit_done.menu_button { |
| 4177 | background-color: var(--okGreen70a); | 4261 | background-color: var(--okGreen70a); |
| 4178 | } | 4262 | } |
| @@ -4181,6 +4265,7 @@ input[type="range"]::-webkit-slider-thumb { | |||
| 4181 | opacity: 1; | 4265 | opacity: 1; |
| 4182 | } | 4266 | } |
| 4183 | 4267 | ||
| 4268 | .reasoning_edit_textarea, | ||
| 4184 | .edit_textarea { | 4269 | .edit_textarea { |
| 4185 | padding: 5px; | 4270 | padding: 5px; |
| 4186 | margin: 0; | 4271 | margin: 0; |
| @@ -289,6 +289,7 @@ async function sendMakerSuiteRequest(request, response) { | |||
| 289 | const model = String(request.body.model); | 289 | const model = String(request.body.model); |
| 290 | const stream = Boolean(request.body.stream); | 290 | const stream = Boolean(request.body.stream); |
| 291 | const showThoughts = Boolean(request.body.show_thoughts); | 291 | const showThoughts = Boolean(request.body.show_thoughts); |
| 292 | const isThinking = model.includes('thinking'); | ||
| 292 | 293 | ||
| 293 | const generationConfig = { | 294 | const generationConfig = { |
| 294 | stopSequences: request.body.stop, | 295 | stopSequences: request.body.stop, |
| @@ -329,6 +330,12 @@ async function sendMakerSuiteRequest(request, response) { | |||
| 329 | body.systemInstruction = prompt.system_instruction; | 330 | body.systemInstruction = prompt.system_instruction; |
| 330 | } | 331 | } |
| 331 | 332 | ||
| 333 | if (isThinking && showThoughts) { | ||
| 334 | generationConfig.thinkingConfig = { | ||
| 335 | includeThoughts: true, | ||
| 336 | }; | ||
| 337 | } | ||
| 338 | |||
| 332 | return body; | 339 | return body; |
| 333 | } | 340 | } |
| 334 | 341 | ||
| @@ -342,7 +349,6 @@ async function sendMakerSuiteRequest(request, response) { | |||
| 342 | controller.abort(); | 349 | controller.abort(); |
| 343 | }); | 350 | }); |
| 344 | 351 | ||
| 345 | const isThinking = model.includes('thinking'); | ||
| 346 | const apiVersion = isThinking ? 'v1alpha' : 'v1beta'; | 352 | const apiVersion = isThinking ? 'v1alpha' : 'v1beta'; |
| 347 | const responseType = (stream ? 'streamGenerateContent' : 'generateContent'); | 353 | const responseType = (stream ? 'streamGenerateContent' : 'generateContent'); |
| 348 | 354 | ||
| @@ -387,11 +393,7 @@ async function sendMakerSuiteRequest(request, response) { | |||
| 387 | const responseContent = candidates[0].content ?? candidates[0].output; | 393 | const responseContent = candidates[0].content ?? candidates[0].output; |
| 388 | console.log('Google AI Studio response:', responseContent); | 394 | console.log('Google AI Studio response:', responseContent); |
| 389 | 395 | ||
| 390 | if (Array.isArray(responseContent?.parts) && isThinking && !showThoughts) { | 396 | const responseText = typeof responseContent === 'string' ? responseContent : responseContent?.parts?.filter(part => !part.thought)?.map(part => part.text)?.join('\n\n'); |
| 391 | responseContent.parts = responseContent.parts.filter(part => !part.thought); | ||
| 392 | } | ||
| 393 | |||
| 394 | const responseText = typeof responseContent === 'string' ? responseContent : responseContent?.parts?.map(part => part.text)?.join('\n\n'); | ||
| 395 | if (!responseText) { | 397 | if (!responseText) { |
| 396 | let message = 'Google AI Studio Candidate text empty'; | 398 | let message = 'Google AI Studio Candidate text empty'; |
| 397 | console.log(message, generateResponseJson); | 399 | console.log(message, generateResponseJson); |
| @@ -399,7 +401,7 @@ async function sendMakerSuiteRequest(request, response) { | |||
| 399 | } | 401 | } |
| 400 | 402 | ||
| 401 | // Wrap it back to OAI format | 403 | // Wrap it back to OAI format |
| 402 | const reply = { choices: [{ 'message': { 'content': responseText } }] }; | 404 | const reply = { choices: [{ 'message': { 'content': responseText } }], responseContent }; |
| 403 | return response.send(reply); | 405 | return response.send(reply); |
| 404 | } | 406 | } |
| 405 | } catch (error) { | 407 | } catch (error) { |
| @@ -996,6 +998,10 @@ router.post('/generate', jsonParser, function (request, response) { | |||
| 996 | bodyParams['route'] = 'fallback'; | 998 | bodyParams['route'] = 'fallback'; |
| 997 | } | 999 | } |
| 998 | 1000 | ||
| 1001 | if (request.body.show_thoughts) { | ||
| 1002 | bodyParams['include_reasoning'] = true; | ||
| 1003 | } | ||
| 1004 | |||
| 999 | let cachingAtDepth = getConfigValue('claude.cachingAtDepth', -1); | 1005 | let cachingAtDepth = getConfigValue('claude.cachingAtDepth', -1); |
| 1000 | if (Number.isInteger(cachingAtDepth) && cachingAtDepth >= 0 && request.body.model?.startsWith('anthropic/claude-3')) { | 1006 | if (Number.isInteger(cachingAtDepth) && cachingAtDepth >= 0 && request.body.model?.startsWith('anthropic/claude-3')) { |
| 1001 | cachingAtDepthForOpenRouterClaude(request.body.messages, cachingAtDepth); | 1007 | cachingAtDepthForOpenRouterClaude(request.body.messages, cachingAtDepth); |