fix: TTS reading thinking content when reasoning has code blocks (#22237)
removeAllDetails() uses replaceOutsideCode() which splits content on triple-backtick code blocks before applying the details-removal regex. When thinking/reasoning content inside a <details> block contained code blocks (backticks survive html.escape), the <details> opening and </details> closing tags ended up in different split segments, making the regex unable to match either. This caused thinking content to leak through to TTS playback. Fix: add a direct <details> strip (without code-block splitting) as the first step of getMessageContentParts(), which is the TTS-specific entry point. This catches the edge case while keeping removeAllDetails safe for copy-to-clipboard (where legitimate <details> inside code blocks should be preserved). Fixes #22197
This commit is contained in:
+17
-7
@@ -362,9 +362,9 @@ export const generateInitialsImage = (name) => {
|
|||||||
const initials =
|
const initials =
|
||||||
sanitizedName.length > 0
|
sanitizedName.length > 0
|
||||||
? sanitizedName[0] +
|
? sanitizedName[0] +
|
||||||
(sanitizedName.split(' ').length > 1
|
(sanitizedName.split(' ').length > 1
|
||||||
? sanitizedName[sanitizedName.lastIndexOf(' ') + 1]
|
? sanitizedName[sanitizedName.lastIndexOf(' ') + 1]
|
||||||
: '')
|
: '')
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
ctx.fillText(initials.toUpperCase(), canvas.width / 2, canvas.height / 2);
|
ctx.fillText(initials.toUpperCase(), canvas.width / 2, canvas.height / 2);
|
||||||
@@ -520,10 +520,10 @@ export const compareVersion = (latest, current) => {
|
|||||||
return current === '0.0.0'
|
return current === '0.0.0'
|
||||||
? false
|
? false
|
||||||
: current.localeCompare(latest, undefined, {
|
: current.localeCompare(latest, undefined, {
|
||||||
numeric: true,
|
numeric: true,
|
||||||
sensitivity: 'case',
|
sensitivity: 'case',
|
||||||
caseFirst: 'upper'
|
caseFirst: 'upper'
|
||||||
}) < 0;
|
}) < 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const extractCurlyBraceWords = (text) => {
|
export const extractCurlyBraceWords = (text) => {
|
||||||
@@ -956,6 +956,16 @@ export const extractSentencesForAudio = (text: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getMessageContentParts = (content: string, splitOn: string = 'punctuation') => {
|
export const getMessageContentParts = (content: string, splitOn: string = 'punctuation') => {
|
||||||
|
// Strip <details> blocks directly on the full string before any
|
||||||
|
// code-block-aware processing. removeAllDetails (which callers use)
|
||||||
|
// applies the regex via replaceOutsideCode, which splits on triple-
|
||||||
|
// backtick code fences first. If a <details> block contains code
|
||||||
|
// fences (e.g. reasoning with code examples), the opening and
|
||||||
|
// closing tags land in separate segments and the regex fails,
|
||||||
|
// leaking thinking content into TTS. Applying the strip here on
|
||||||
|
// the full string catches those cases. (Fixes #22197)
|
||||||
|
content = content.replace(/<details[^>]*>[\s\S]*?<\/details>/gi, '');
|
||||||
|
|
||||||
const messageContentParts: string[] = [];
|
const messageContentParts: string[] = [];
|
||||||
|
|
||||||
switch (splitOn) {
|
switch (splitOn) {
|
||||||
|
|||||||
Reference in New Issue
Block a user