diff --git a/public/script.js b/public/script.js index a9ebde08c..2ed1110df 100644 --- a/public/script.js +++ b/public/script.js @@ -3135,8 +3135,9 @@ class StreamingProcessor { * @param {boolean} forceName2 If true, force the use of name2 * @param {Date} timeStarted Date when generation was started * @param {string} continueMessage Previous message if the type is 'continue' + * @param {PromptReasoning} promptReasoning Prompt reasoning instance */ - constructor(type, forceName2, timeStarted, continueMessage) { + constructor(type, forceName2, timeStarted, continueMessage, promptReasoning) { this.result = ''; this.messageId = -1; /** @type {HTMLElement} */ @@ -3164,6 +3165,8 @@ class StreamingProcessor { this.toolCalls = []; // Initialize reasoning in its own handler this.reasoningHandler = new ReasoningHandler(timeStarted); + /** @type {PromptReasoning} */ + this.promptReasoning = promptReasoning; } #checkDomElements(messageId) { @@ -3192,6 +3195,10 @@ class StreamingProcessor { } async onStartStreaming(text) { + if (this.type === 'continue' && this.promptReasoning.prefixReasoning) { + this.reasoningHandler.initContinue(this.promptReasoning); + } + let messageId = -1; if (this.type == 'impersonate') { @@ -3882,13 +3889,13 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro }; })); - const reasoning = new PromptReasoning(); + const promptReasoning = new PromptReasoning(); for (let i = coreChat.length - 1; i >= 0; i--) { const depth = coreChat.length - i - 1; const isPrefix = isContinue && i === coreChat.length - 1; coreChat[i] = { ...coreChat[i], - mes: reasoning.addToMessage( + mes: promptReasoning.addToMessage( coreChat[i].mes, getRegexedString( String(coreChat[i].extra?.reasoning ?? ''), @@ -3896,9 +3903,10 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro { isPrompt: true, depth: depth }, ), isPrefix, + coreChat[i].extra?.reasoning_duration, ), }; - if (reasoning.isLimitReached()) { + if (promptReasoning.isLimitReached()) { break; } } @@ -4723,7 +4731,8 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro console.debug(`pushed prompt bits to itemizedPrompts array. Length is now: ${itemizedPrompts.length}`); if (isStreamingEnabled() && type !== 'quiet') { - streamingProcessor = new StreamingProcessor(type, force_name2, generation_started, continue_mag); + continue_mag = promptReasoning.removePrefix(continue_mag); + streamingProcessor = new StreamingProcessor(type, force_name2, generation_started, continue_mag, promptReasoning); if (isContinue) { // Save reply does add cycle text to the prompt, so it's not needed here streamingProcessor.firstMessageText = ''; @@ -4824,6 +4833,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro } if (isContinue) { + continue_mag = promptReasoning.removePrefix(continue_mag); getMessage = continue_mag + getMessage; } diff --git a/public/scripts/reasoning.js b/public/scripts/reasoning.js index dc047b776..5e846e4d8 100644 --- a/public/scripts/reasoning.js +++ b/public/scripts/reasoning.js @@ -188,6 +188,17 @@ export class ReasoningHandler { this.messageReasoningHeaderDom = null; } + /** + * Sets the reasoning state when continuing a prompt. + * @param {PromptReasoning} promptReasoning Prompt reasoning object + */ + initContinue(promptReasoning) { + this.reasoning = promptReasoning.prefixReasoning; + this.state = ReasoningState.Done; + this.startTime = this.initialTime; + this.endTime = promptReasoning.prefixDuration ? new Date(this.initialTime.getTime() + promptReasoning.prefixDuration) : null; + } + /** * Initializes the reasoning handler for a specific message. * @@ -514,6 +525,9 @@ export class PromptReasoning { constructor() { this.counter = 0; + this.prefixLength = -1; + this.prefixReasoning = ''; + this.prefixDuration = null; } /** @@ -533,9 +547,10 @@ export class PromptReasoning { * @param {string} content Message content * @param {string} reasoning Message reasoning * @param {boolean} isPrefix Whether this is the last message prefix + * @param {number?} duration Duration of the reasoning * @returns {string} Message content with reasoning */ - addToMessage(content, reasoning, isPrefix) { + addToMessage(content, reasoning, isPrefix, duration) { // Disabled or reached limit of additions if (!isPrefix && (!power_user.reasoning.add_to_prompts || this.counter >= power_user.reasoning.max_additions)) { return content; @@ -556,11 +571,35 @@ export class PromptReasoning { // Combine parts with reasoning only if (isPrefix && !content) { - return `${prefix}${reasoning}`; + const formattedReasoning = `${prefix}${reasoning}`; + if (isPrefix) { + this.prefixReasoning = reasoning; + this.prefixLength = formattedReasoning.length; + this.prefixDuration = duration; + } + return formattedReasoning; } // Combine parts with reasoning and content - return `${prefix}${reasoning}${suffix}${separator}${content}`; + const formattedReasoning = `${prefix}${reasoning}${suffix}${separator}`; + if (isPrefix) { + this.prefixReasoning = reasoning; + this.prefixLength = formattedReasoning.length; + this.prefixDuration = duration; + } + return `${formattedReasoning}${content}`; + } + + /** + * Removes the reasoning prefix from the content. + * @param {string} content Content with the reasoning prefix + * @returns {string} Content without the reasoning prefix + */ + removePrefix(content) { + if (this.prefixLength > 0) { + return content.slice(this.prefixLength); + } + return content; } }