Fix markdown preprocessing

This commit is contained in:
Saoud Rizwan
2024-10-05 21:57:43 -04:00
parent 636e6927f7
commit 6c03fdfbb9
2 changed files with 24 additions and 22 deletions

View File

@@ -771,20 +771,38 @@ export class ClaudeDev {
break
}
let content = block.content
if (block.partial && content) {
// Remove partial XML tag at the very end of the content
if (content) {
// (have to do this for partial and complete since sending content in thinking tags to markdown renderer will automatically be removed)
// Remove end substrings of <thinking or </thinking (below xml parsing is only for opening tags)
// (this is done with the xml parsing below now, but keeping here for reference)
// content = content.replace(/<\/?t(?:h(?:i(?:n(?:k(?:i(?:n(?:g)?)?)?)?)?)?)?$/, "")
// Remove all instances of <thinking> (with optional line break after) and </thinking> (with optional line break before)
// - Needs to be separate since we dont want to remove the line break before the first tag
// - Needs to happen before the xml parsing below
content = content.replace(/<thinking>\s?/g, "")
content = content.replace(/\s?<\/thinking>/g, "")
// Remove partial XML tag at the very end of the content (for tool use and thinking tags)
// (prevents scrollview from jumping when tags are automatically removed)
const lastOpenBracketIndex = content.lastIndexOf("<")
if (lastOpenBracketIndex !== -1) {
const possibleTag = content.slice(lastOpenBracketIndex)
// Check if there's a '>' after the last '<' (i.e., if the tag is complete)
// Check if there's a '>' after the last '<' (i.e., if the tag is complete) (complete thinking and tool tags will have been removed by now)
const hasCloseBracket = possibleTag.includes(">")
if (!hasCloseBracket) {
// Extract the potential tag name
const tagContent = possibleTag.slice(1).trim()
let tagContent: string
if (possibleTag.startsWith("</")) {
tagContent = possibleTag.slice(2).trim()
} else {
tagContent = possibleTag.slice(1).trim()
}
// Check if tagContent is likely an incomplete tag name (letters and underscores only)
const isLikelyTagName = /^[a-zA-Z_]+$/.test(tagContent)
// Preemptively remove < or </ to keep from these artifacts showing up in chat (also handles closing thinking tags)
const isOpeningOrClosing = possibleTag === "<" || possibleTag === "</"
// If the tag is incomplete and at the end, remove it from the content
if (isLikelyTagName) {
if (isOpeningOrClosing || isLikelyTagName) {
content = content.slice(0, lastOpenBracketIndex).trim()
}
}

View File

@@ -800,25 +800,9 @@ const ProgressIndicator = () => (
)
const Markdown = memo(({ markdown }: { markdown?: string }) => {
const withoutThinkingTags = useMemo(() => {
if (!markdown) return ""
let processed = markdown
// Remove end substrings of <thinking or </thinking
processed = processed.replace(/<\/?t(?:h(?:i(?:n(?:k(?:i(?:n(?:g)?)?)?)?)?)?)?$/, "")
// Remove all instances of <thinking> (with optional line break after) and </thinking> (with optional line break before)
// Needs to be separate since we dont want to remove the line break before the first tag
processed = processed.replace(/<thinking>\s?/g, "")
processed = processed.replace(/\s?<\/thinking>/g, "")
return processed
}, [markdown])
return (
<div style={{ wordBreak: "break-word", overflowWrap: "anywhere", marginBottom: -15, marginTop: -15 }}>
<MarkdownBlock markdown={withoutThinkingTags} />
<MarkdownBlock markdown={markdown} />
</div>
)
})