mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-01-29 05:36:13 +01:00
🏄♂️ refactor: Optimize Reasoning UI & Token Streaming (#5546)
* ✨ feat: Implement Show Thinking feature; refactor: testing thinking render optimizations * ✨ feat: Refactor Thinking component styles and enhance Markdown rendering * chore: add back removed code, revert type changes * chore: Add back resetCounter effect to Markdown component for improved code block indexing * chore: bump @librechat/agents and google langchain packages * WIP: reasoning type updates * WIP: first pass, reasoning content blocks * chore: revert code * chore: bump @librechat/agents * refactor: optimize reasoning tag handling * style: ul indent padding * feat: add Reasoning component to handle reasoning display * feat: first pass, content reasoning part styling * refactor: add content placeholder for endpoints using new stream handler * refactor: only cache messages when requesting stream audio * fix: circular dep. * fix: add default param * refactor: tts, only request after message stream, fix chrome autoplay * style: update label for submitting state and add localization for 'Thinking...' * fix: improve global audio pause logic and reset active run ID * fix: handle artifact edge cases * fix: remove unnecessary console log from artifact update test * feat: add support for continued message handling with new streaming method --------- Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com>
This commit is contained in:
parent
d60a149ad9
commit
591a019766
48 changed files with 1791 additions and 726 deletions
|
|
@ -57,14 +57,42 @@ const findAllArtifacts = (message) => {
|
|||
|
||||
const replaceArtifactContent = (originalText, artifact, original, updated) => {
|
||||
const artifactContent = artifact.text.substring(artifact.start, artifact.end);
|
||||
const relativeIndex = artifactContent.indexOf(original);
|
||||
|
||||
// Find boundaries between ARTIFACT_START and ARTIFACT_END
|
||||
const contentStart = artifactContent.indexOf('\n', artifactContent.indexOf(ARTIFACT_START)) + 1;
|
||||
const contentEnd = artifactContent.lastIndexOf(ARTIFACT_END);
|
||||
|
||||
if (contentStart === -1 || contentEnd === -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if there are code blocks
|
||||
const codeBlockStart = artifactContent.indexOf('```\n', contentStart);
|
||||
const codeBlockEnd = artifactContent.lastIndexOf('\n```', contentEnd);
|
||||
|
||||
// Determine where to look for the original content
|
||||
let searchStart, searchEnd;
|
||||
if (codeBlockStart !== -1 && codeBlockEnd !== -1) {
|
||||
// If code blocks exist, search between them
|
||||
searchStart = codeBlockStart + 4; // after ```\n
|
||||
searchEnd = codeBlockEnd;
|
||||
} else {
|
||||
// Otherwise search in the whole artifact content
|
||||
searchStart = contentStart;
|
||||
searchEnd = contentEnd;
|
||||
}
|
||||
|
||||
const innerContent = artifactContent.substring(searchStart, searchEnd);
|
||||
// Remove trailing newline from original for comparison
|
||||
const originalTrimmed = original.replace(/\n$/, '');
|
||||
const relativeIndex = innerContent.indexOf(originalTrimmed);
|
||||
|
||||
if (relativeIndex === -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const absoluteIndex = artifact.start + relativeIndex;
|
||||
const endText = originalText.substring(absoluteIndex + original.length);
|
||||
const absoluteIndex = artifact.start + searchStart + relativeIndex;
|
||||
const endText = originalText.substring(absoluteIndex + originalTrimmed.length);
|
||||
const hasTrailingNewline = endText.startsWith('\n');
|
||||
|
||||
const updatedText =
|
||||
|
|
|
|||
|
|
@ -260,8 +260,61 @@ console.log(greeting);`;
|
|||
codeExample,
|
||||
'updated content',
|
||||
);
|
||||
console.log(result);
|
||||
expect(result).toMatch(/id="2".*updated content/s);
|
||||
expect(result).toMatch(new RegExp(`${ARTIFACT_START}.*updated content.*${ARTIFACT_END}`, 's'));
|
||||
});
|
||||
|
||||
test('should handle empty content in artifact without code blocks', () => {
|
||||
const artifactText = `${ARTIFACT_START}\n\n${ARTIFACT_END}`;
|
||||
const artifact = {
|
||||
start: 0,
|
||||
end: artifactText.length,
|
||||
text: artifactText,
|
||||
source: 'text',
|
||||
};
|
||||
|
||||
const result = replaceArtifactContent(artifactText, artifact, '', 'new content');
|
||||
expect(result).toBe(`${ARTIFACT_START}\nnew content\n${ARTIFACT_END}`);
|
||||
});
|
||||
|
||||
test('should handle empty content in artifact with code blocks', () => {
|
||||
const artifactText = createArtifactText({ content: '' });
|
||||
const artifact = {
|
||||
start: 0,
|
||||
end: artifactText.length,
|
||||
text: artifactText,
|
||||
source: 'text',
|
||||
};
|
||||
|
||||
const result = replaceArtifactContent(artifactText, artifact, '', 'new content');
|
||||
expect(result).toMatch(/```\nnew content\n```/);
|
||||
});
|
||||
|
||||
test('should handle content with trailing newline in code blocks', () => {
|
||||
const contentWithNewline = 'console.log("test")\n';
|
||||
const message = {
|
||||
text: `Some prefix text\n${createArtifactText({
|
||||
content: contentWithNewline,
|
||||
})}\nSome suffix text`,
|
||||
};
|
||||
|
||||
const artifacts = findAllArtifacts(message);
|
||||
expect(artifacts).toHaveLength(1);
|
||||
|
||||
const result = replaceArtifactContent(
|
||||
message.text,
|
||||
artifacts[0],
|
||||
contentWithNewline,
|
||||
'updated content',
|
||||
);
|
||||
|
||||
// Should update the content and preserve artifact structure
|
||||
expect(result).toContain('```\nupdated content\n```');
|
||||
// Should preserve surrounding text
|
||||
expect(result).toMatch(/^Some prefix text\n/);
|
||||
expect(result).toMatch(/\nSome suffix text$/);
|
||||
// Should not have extra newlines
|
||||
expect(result).not.toContain('\n\n```');
|
||||
expect(result).not.toContain('```\n\n');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue