mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 08:50:15 +01:00
82 lines
2.5 KiB
JavaScript
82 lines
2.5 KiB
JavaScript
|
|
const ARTIFACT_START = ':::artifact';
|
||
|
|
const ARTIFACT_END = ':::';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Find all artifact boundaries in the message
|
||
|
|
* @param {TMessage} message
|
||
|
|
* @returns {Array<{start: number, end: number, source: 'content'|'text', partIndex?: number}>}
|
||
|
|
*/
|
||
|
|
const findAllArtifacts = (message) => {
|
||
|
|
const artifacts = [];
|
||
|
|
|
||
|
|
// Check content parts first
|
||
|
|
if (message.content?.length) {
|
||
|
|
message.content.forEach((part, partIndex) => {
|
||
|
|
if (part.type === 'text' && typeof part.text === 'string') {
|
||
|
|
let currentIndex = 0;
|
||
|
|
let start = part.text.indexOf(ARTIFACT_START, currentIndex);
|
||
|
|
|
||
|
|
while (start !== -1) {
|
||
|
|
const end = part.text.indexOf(ARTIFACT_END, start + ARTIFACT_START.length);
|
||
|
|
artifacts.push({
|
||
|
|
start,
|
||
|
|
end: end !== -1 ? end + ARTIFACT_END.length : part.text.length,
|
||
|
|
source: 'content',
|
||
|
|
partIndex,
|
||
|
|
text: part.text,
|
||
|
|
});
|
||
|
|
|
||
|
|
currentIndex = end !== -1 ? end + ARTIFACT_END.length : part.text.length;
|
||
|
|
start = part.text.indexOf(ARTIFACT_START, currentIndex);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check message.text if no content parts
|
||
|
|
if (!artifacts.length && message.text) {
|
||
|
|
let currentIndex = 0;
|
||
|
|
let start = message.text.indexOf(ARTIFACT_START, currentIndex);
|
||
|
|
|
||
|
|
while (start !== -1) {
|
||
|
|
const end = message.text.indexOf(ARTIFACT_END, start + ARTIFACT_START.length);
|
||
|
|
artifacts.push({
|
||
|
|
start,
|
||
|
|
end: end !== -1 ? end + ARTIFACT_END.length : message.text.length,
|
||
|
|
source: 'text',
|
||
|
|
text: message.text,
|
||
|
|
});
|
||
|
|
|
||
|
|
currentIndex = end !== -1 ? end + ARTIFACT_END.length : message.text.length;
|
||
|
|
start = message.text.indexOf(ARTIFACT_START, currentIndex);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return artifacts;
|
||
|
|
};
|
||
|
|
|
||
|
|
const replaceArtifactContent = (originalText, artifact, original, updated) => {
|
||
|
|
const artifactContent = artifact.text.substring(artifact.start, artifact.end);
|
||
|
|
const relativeIndex = artifactContent.indexOf(original);
|
||
|
|
|
||
|
|
if (relativeIndex === -1) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
const absoluteIndex = artifact.start + relativeIndex;
|
||
|
|
const endText = originalText.substring(absoluteIndex + original.length);
|
||
|
|
const hasTrailingNewline = endText.startsWith('\n');
|
||
|
|
|
||
|
|
const updatedText =
|
||
|
|
originalText.substring(0, absoluteIndex) + updated + (hasTrailingNewline ? '' : '\n') + endText;
|
||
|
|
|
||
|
|
return updatedText.replace(/\n+(?=```\n:::)/g, '\n');
|
||
|
|
};
|
||
|
|
|
||
|
|
module.exports = {
|
||
|
|
ARTIFACT_START,
|
||
|
|
ARTIFACT_END,
|
||
|
|
findAllArtifacts,
|
||
|
|
replaceArtifactContent,
|
||
|
|
};
|