Move reasoning stuff to reasoning.js

06303bb62fc895446264cbf004e2dc042a09e49a

Wolfsblvt <wolfsblvt@gmail.com>

2 files changed, +81 -77Ignore whitespace
public/script.js+2 -75
@@ -225,7 +225,7 @@ import {
225225 instruct_presets,
226226 selectContextPreset,
227227} from './scripts/instruct-mode.js';
228228import { getCurrentLocale, initLocales, t } from './scripts/i18n.js';
229229import { getFriendlyTokenizerName, getTokenCount, getTokenCountAsync, initTokenizers, saveTokenCache, TOKENIZER_SUPPORTED_KEY } from './scripts/tokenizers.js';
230230import {
231231 user_avatar,
@@ -269,7 +269,7 @@ import { initSettingsSearch } from './scripts/setting-search.js';
269269import { initBulkEdit } from './scripts/bulk-edit.js';
270270import { deriveTemplatesFromChatTemplate } from './scripts/chat-templates.js';
271271import { getContext } from './scripts/st-context.js';
272272import { extractReasoningFromData, initReasoning, PromptReasoning, updateReasoningTimeUI } from './scripts/reasoning.js';
273273
274274// API OBJECT FOR EXTERNAL WIRING
275275globalThis.SillyTavern = {
@@ -5764,56 +5764,6 @@ function extractMessageFromData(data) {
57645764}
57655765
57665766/**
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-/**
58175767 * Extracts multiswipe swipes from the response data.
58185768 * @param {Object} data Response data
58195769 * @param {string} type Type of generation
@@ -10872,18 +10822,6 @@ jQuery(async function () {
1087210822 }
1087310823 });
1087410824
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-
1088710825 $(document).on('input', '#curEditTextarea', function () {
1088810826 if (power_user.auto_save_msg_edits === true) {
1088910827 messageEditAuto($(this));
@@ -11438,17 +11376,6 @@ jQuery(async function () {
1143811376 }
1143911377 });
1144011378
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-
1145211379 $(document).keyup(function (e) {
1145311380 if (e.key === 'Escape') {
1145411381 const isEditVisible = $('#curEditTextarea').is(':visible') || $('.reasoning_edit_textarea').length > 0;
public/scripts/reasoning.js+79 -2
@@ -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';
25import { getRegexedString, regex_placement } from './extensions/regex/engine.js';
36import { getCurrentLocale, t } from './i18n.js';
47import { MacrosParser } from './macros.js';
8+import { chat_completion_sources, oai_settings } from './openai.js';
59import { Popup } from './popup.js';
610import { power_user } from './power-user.js';
711import { SlashCommand } from './slash-commands/SlashCommand.js';
812import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './slash-commands/SlashCommandArgument.js';
913import { commonEnumProviders } from './slash-commands/SlashCommandCommonEnumsProvider.js';
1014import { SlashCommandParser } from './slash-commands/SlashCommandParser.js';
15+import { textgen_types, textgenerationwebui_settings } from './textgen-settings.js';
1116import { copyText, escapeRegex, isFalseBoolean } from './utils.js';
1217
1318/**
@@ -35,6 +40,55 @@ function toggleReasoningAutoExpand() {
3540}
3641
3742/**
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+/**
3892 * Helper class for adding reasoning to messages.
3993 * Keeps track of the number of reasoning additions.
4094 */
@@ -247,6 +301,29 @@ function registerReasoningMacros() {
247301}
248302
249303function 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+
250327 $(document).on('click', '.mes_reasoning_copy', (e) => {
251328 e.stopPropagation();
252329 e.preventDefault();