Move reasoning stuff to reasoning.js
| @@ -225,7 +225,7 @@ import { | ||
| 225 | 225 | instruct_presets, |
| 226 | 226 | selectContextPreset, |
| 227 | 227 | } from './scripts/instruct-mode.js'; |
| 228 | 228 | import { getCurrentLocale, initLocales, t } from './scripts/i18n.js'; |
| 229 | 229 | import { getFriendlyTokenizerName, getTokenCount, getTokenCountAsync, initTokenizers, saveTokenCache, TOKENIZER_SUPPORTED_KEY } from './scripts/tokenizers.js'; |
| 230 | 230 | import { |
| 231 | 231 | user_avatar, |
| @@ -269,7 +269,7 @@ import { initSettingsSearch } from './scripts/setting-search.js'; | ||
| 269 | 269 | import { initBulkEdit } from './scripts/bulk-edit.js'; |
| 270 | 270 | import { deriveTemplatesFromChatTemplate } from './scripts/chat-templates.js'; |
| 271 | 271 | import { getContext } from './scripts/st-context.js'; |
| 272 | 272 | import { extractReasoningFromData, initReasoning, PromptReasoning, updateReasoningTimeUI } from './scripts/reasoning.js'; |
| 273 | 273 | |
| 274 | 274 | // API OBJECT FOR EXTERNAL WIRING |
| 275 | 275 | globalThis.SillyTavern = { |
| @@ -5764,56 +5764,6 @@ function extractMessageFromData(data) { | ||
| 5764 | 5764 | } |
| 5765 | 5765 | |
| 5766 | 5766 | /** |
| 5767 | - * Extracts the reasoning from the response data. | |
| 5768 | - * @param {object} data Response data | |
| 5769 | - * @returns {string} Extracted reasoning | |
| 5770 | - */ | |
| 5771 | -function extractReasoningFromData(data) { | |
| 5772 | - switch (main_api) { | |
| 5773 | - case 'textgenerationwebui': | |
| 5774 | - switch (textgen_settings.type) { | |
| 5775 | - case textgen_types.OPENROUTER: | |
| 5776 | - return data?.choices?.[0]?.reasoning ?? ''; | |
| 5777 | - } | |
| 5778 | - break; | |
| 5779 | - | |
| 5780 | - case 'openai': | |
| 5781 | - if (!oai_settings.show_thoughts) break; | |
| 5782 | - | |
| 5783 | - switch (oai_settings.chat_completion_source) { | |
| 5784 | - case chat_completion_sources.DEEPSEEK: | |
| 5785 | - return data?.choices?.[0]?.message?.reasoning_content ?? ''; | |
| 5786 | - case chat_completion_sources.OPENROUTER: | |
| 5787 | - return data?.choices?.[0]?.message?.reasoning ?? ''; | |
| 5788 | - case chat_completion_sources.MAKERSUITE: | |
| 5789 | - return data?.responseContent?.parts?.filter(part => part.thought)?.map(part => part.text)?.join('\n\n') ?? ''; | |
| 5790 | - } | |
| 5791 | - break; | |
| 5792 | - } | |
| 5793 | - | |
| 5794 | - return ''; | |
| 5795 | -} | |
| 5796 | - | |
| 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 | -/** | |
| 5817 | 5767 | * Extracts multiswipe swipes from the response data. |
| 5818 | 5768 | * @param {Object} data Response data |
| 5819 | 5769 | * @param {string} type Type of generation |
| @@ -10872,18 +10822,6 @@ jQuery(async function () { | ||
| 10872 | 10822 | } |
| 10873 | 10823 | }); |
| 10874 | 10824 | |
| 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 | - | |
| 10887 | 10825 | $(document).on('input', '#curEditTextarea', function () { |
| 10888 | 10826 | if (power_user.auto_save_msg_edits === true) { |
| 10889 | 10827 | messageEditAuto($(this)); |
| @@ -11438,17 +11376,6 @@ jQuery(async function () { | ||
| 11438 | 11376 | } |
| 11439 | 11377 | }); |
| 11440 | 11378 | |
| 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 | - | |
| 11452 | 11379 | $(document).keyup(function (e) { |
| 11453 | 11380 | if (e.key === 'Escape') { |
| 11454 | 11381 | const isEditVisible = $('#curEditTextarea').is(':visible') || $('.reasoning_edit_textarea').length > 0; |
| @@ -1,13 +1,18 @@ | ||
| 1 | -import { chat, closeMessageEditor, event_types, eventSource, saveChatConditional, saveSettingsDebounced, substituteParams, updateMessageBlock } from '../script.js'; | |
| 1 | +import { | |
| 2 | + moment, | |
| 3 | +} from '../lib.js'; | |
| 4 | +import { chat, closeMessageEditor, event_types, eventSource, main_api, saveChatConditional, saveSettingsDebounced, substituteParams, updateMessageBlock } from '../script.js'; | |
| 2 | 5 | import { getRegexedString, regex_placement } from './extensions/regex/engine.js'; |
| 3 | 6 | import { getCurrentLocale, t } from './i18n.js'; |
| 4 | 7 | import { MacrosParser } from './macros.js'; |
| 8 | +import { chat_completion_sources, oai_settings } from './openai.js'; | |
| 5 | 9 | import { Popup } from './popup.js'; |
| 6 | 10 | import { power_user } from './power-user.js'; |
| 7 | 11 | import { SlashCommand } from './slash-commands/SlashCommand.js'; |
| 8 | 12 | import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './slash-commands/SlashCommandArgument.js'; |
| 9 | 13 | import { commonEnumProviders } from './slash-commands/SlashCommandCommonEnumsProvider.js'; |
| 10 | 14 | import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; |
| 15 | +import { textgen_types, textgenerationwebui_settings } from './textgen-settings.js'; | |
| 11 | 16 | import { copyText, escapeRegex, isFalseBoolean } from './utils.js'; |
| 12 | 17 | |
| 13 | 18 | /** |
| @@ -35,6 +40,55 @@ function toggleReasoningAutoExpand() { | ||
| 35 | 40 | } |
| 36 | 41 | |
| 37 | 42 | /** |
| 43 | + * Extracts the reasoning from the response data. | |
| 44 | + * @param {object} data Response data | |
| 45 | + * @returns {string} Extracted reasoning | |
| 46 | + */ | |
| 47 | +export function extractReasoningFromData(data) { | |
| 48 | + switch (main_api) { | |
| 49 | + case 'textgenerationwebui': | |
| 50 | + switch (textgenerationwebui_settings.type) { | |
| 51 | + case textgen_types.OPENROUTER: | |
| 52 | + return data?.choices?.[0]?.reasoning ?? ''; | |
| 53 | + } | |
| 54 | + break; | |
| 55 | + | |
| 56 | + case 'openai': | |
| 57 | + if (!oai_settings.show_thoughts) break; | |
| 58 | + | |
| 59 | + switch (oai_settings.chat_completion_source) { | |
| 60 | + case chat_completion_sources.DEEPSEEK: | |
| 61 | + return data?.choices?.[0]?.message?.reasoning_content ?? ''; | |
| 62 | + case chat_completion_sources.OPENROUTER: | |
| 63 | + return data?.choices?.[0]?.message?.reasoning ?? ''; | |
| 64 | + case chat_completion_sources.MAKERSUITE: | |
| 65 | + return data?.responseContent?.parts?.filter(part => part.thought)?.map(part => part.text)?.join('\n\n') ?? ''; | |
| 66 | + } | |
| 67 | + break; | |
| 68 | + } | |
| 69 | + | |
| 70 | + return ''; | |
| 71 | +} | |
| 72 | + | |
| 73 | +/** | |
| 74 | + * Updates the Reasoning controls | |
| 75 | + * @param {HTMLElement} element The element to update | |
| 76 | + * @param {number?} duration The duration of the reasoning in milliseconds | |
| 77 | + * @param {object} [options={}] Options for the function | |
| 78 | + * @param {boolean} [options.forceEnd=false] If true, there will be no "Thinking..." when no duration exists | |
| 79 | + */ | |
| 80 | +export function updateReasoningTimeUI(element, duration, { forceEnd = false } = {}) { | |
| 81 | + if (duration) { | |
| 82 | + const durationStr = moment.duration(duration).locale(getCurrentLocale()).humanize({ s: 50, ss: 9 }); | |
| 83 | + element.textContent = t`Thought for ${durationStr}`; | |
| 84 | + } else if (forceEnd) { | |
| 85 | + element.textContent = t`Thought for some time`; | |
| 86 | + } else { | |
| 87 | + element.textContent = t`Thinking...`; | |
| 88 | + } | |
| 89 | +} | |
| 90 | + | |
| 91 | +/** | |
| 38 | 92 | * Helper class for adding reasoning to messages. |
| 39 | 93 | * Keeps track of the number of reasoning additions. |
| 40 | 94 | */ |
| @@ -247,6 +301,29 @@ function registerReasoningMacros() { | ||
| 247 | 301 | } |
| 248 | 302 | |
| 249 | 303 | function setReasoningEventHandlers() { |
| 304 | + $(document).on('click', '.mes_reasoning_summary', function () { | |
| 305 | + // If you toggle summary header while editing reasoning, yup - we just cancel it | |
| 306 | + $(this).closest('.mes').find('.mes_reasoning_edit_cancel:visible').trigger('click'); | |
| 307 | + }); | |
| 308 | + | |
| 309 | + $(document).on('click', '.mes_reasoning_details', function (e) { | |
| 310 | + if (!e.target.closest('.mes_reasoning_actions') && !e.target.closest('.mes_reasoning_header')) { | |
| 311 | + e.preventDefault(); | |
| 312 | + } | |
| 313 | + }); | |
| 314 | + | |
| 315 | + $(document).on('click', '.mes_reasoning_header', function () { | |
| 316 | + // If we are in message edit mode and reasoning area is closed, a click opens and edits it | |
| 317 | + const mes = $(this).closest('.mes'); | |
| 318 | + const mesEditArea = mes.find('#curEditTextarea'); | |
| 319 | + if (mesEditArea.length) { | |
| 320 | + const summary = $(mes).find('.mes_reasoning_summary'); | |
| 321 | + if (!summary.attr('open')) { | |
| 322 | + summary.find('.mes_reasoning_edit').trigger('click'); | |
| 323 | + } | |
| 324 | + } | |
| 325 | + }); | |
| 326 | + | |
| 250 | 327 | $(document).on('click', '.mes_reasoning_copy', (e) => { |
| 251 | 328 | e.stopPropagation(); |
| 252 | 329 | e.preventDefault(); |