/*
Copyright (C) 2023-2026 QuantumNous
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
For commercial licensing, please contact support@quantumnous.com
*/
interface ParsedThinkTags {
visibleContent: string
reasoning: string
hasUnclosedTag: boolean
}
/**
* Parse content to separate thinking from visible text.
* Handles both complete and incomplete tags.
*/
export function parseThinkTags(content: string): ParsedThinkTags {
if (!content.includes('')) {
return { visibleContent: content, reasoning: '', hasUnclosedTag: false }
}
const visibleParts: string[] = []
const reasoningParts: string[] = []
let currentPos = 0
let hasUnclosedTag = false
while (true) {
const openPos = content.indexOf('', currentPos)
if (openPos === -1) {
if (currentPos < content.length) {
visibleParts.push(content.slice(currentPos))
}
break
}
if (openPos > currentPos) {
visibleParts.push(content.slice(currentPos, openPos))
}
const closePos = content.indexOf('', openPos + 7)
if (closePos === -1) {
reasoningParts.push(content.slice(openPos + 7))
hasUnclosedTag = true
break
}
reasoningParts.push(content.slice(openPos + 7, closePos))
currentPos = closePos + 8
}
return {
visibleContent: visibleParts.join('').trim(),
reasoning: reasoningParts.join('\n\n').trim(),
hasUnclosedTag,
}
}