81 lines
2.3 KiB
TypeScript
81 lines
2.3 KiB
TypeScript
// @ts-nocheck
|
|
|
|
|
|
export function createThinkSplitter(enabled) {
|
|
let buf = '';
|
|
let inThink = false;
|
|
|
|
function drain(final = false) {
|
|
let thinking = '';
|
|
let content = '';
|
|
|
|
while (buf.length > 0) {
|
|
if (inThink) {
|
|
const endIdx = buf.indexOf('</think>');
|
|
if (endIdx === -1) {
|
|
const hold = holdPartialClose(buf);
|
|
if (!final && hold > 0) {
|
|
const safe = buf.slice(0, buf.length - hold);
|
|
if (enabled) thinking += safe;
|
|
buf = buf.slice(buf.length - hold);
|
|
break;
|
|
}
|
|
if (enabled) thinking += buf;
|
|
buf = '';
|
|
break;
|
|
}
|
|
if (enabled) thinking += buf.slice(0, endIdx);
|
|
buf = buf.slice(endIdx + '</think>'.length);
|
|
inThink = false;
|
|
continue;
|
|
}
|
|
|
|
const startIdx = buf.indexOf('<think>');
|
|
if (startIdx === -1) {
|
|
const hold = holdPartialOpen(buf);
|
|
if (!final && hold > 0) {
|
|
content += buf.slice(0, buf.length - hold);
|
|
buf = buf.slice(buf.length - hold);
|
|
break;
|
|
}
|
|
content += buf;
|
|
buf = '';
|
|
break;
|
|
}
|
|
content += buf.slice(0, startIdx);
|
|
buf = buf.slice(startIdx + '<think>'.length);
|
|
inThink = true;
|
|
}
|
|
|
|
return { thinking, content };
|
|
}
|
|
|
|
return {
|
|
push(chunk) {
|
|
if (!chunk) return { thinking: '', content: '' };
|
|
buf += chunk;
|
|
return drain(false);
|
|
},
|
|
flush() {
|
|
return drain(true);
|
|
},
|
|
};
|
|
}
|
|
|
|
function holdPartialOpen(s) {
|
|
const m = s.match(/<t(?:h(?:i(?:n(?:k(?:>)?)?)?)?)?$/);
|
|
return m ? m[0].length : 0;
|
|
}
|
|
|
|
function holdPartialClose(s) {
|
|
const m = s.match(/<\/?(?:t(?:h(?:i(?:n(?:k)?)?)?)?)?$/);
|
|
return m ? m[0].length : 0;
|
|
}
|
|
|
|
export function stripThinkTags(text) {
|
|
return String(text || '')
|
|
.replace(/<think>[\s\S]*?<\/think>/g, '')
|
|
.replace(/<think>[\s\S]*$/g, '')
|
|
.replace(/<\/think>/g, '');
|
|
}
|