| const ARTIFACT_START = ':::artifact'; |
| const ARTIFACT_END = ':::'; |
|
|
| |
| |
| |
| |
| |
| const findAllArtifacts = (message) => { |
| const artifacts = []; |
|
|
| |
| 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); |
| } |
| } |
| }); |
| } |
|
|
| |
| 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 contentStart = artifactContent.indexOf('\n', artifactContent.indexOf(ARTIFACT_START)) + 1; |
| let contentEnd = artifactContent.lastIndexOf(ARTIFACT_END); |
|
|
| |
| |
| |
| if (contentEnd === 0 && artifactContent.indexOf(ARTIFACT_START) === 0) { |
| contentEnd = artifactContent.length; |
| } |
|
|
| if (contentStart === -1 || contentEnd === -1) { |
| return null; |
| } |
|
|
| |
| const codeBlockStart = artifactContent.indexOf('```\n', contentStart); |
| const codeBlockEnd = artifactContent.lastIndexOf('\n```', contentEnd); |
|
|
| |
| let searchStart, searchEnd; |
| if (codeBlockStart !== -1) { |
| |
| searchStart = codeBlockStart + 4; |
|
|
| if (codeBlockEnd !== -1 && codeBlockEnd > codeBlockStart) { |
| |
| searchEnd = codeBlockEnd; |
| } else { |
| |
| |
| searchEnd = contentEnd; |
| } |
| } else { |
| |
| searchStart = contentStart; |
| searchEnd = contentEnd; |
| } |
|
|
| const innerContent = artifactContent.substring(searchStart, searchEnd); |
| |
| const originalTrimmed = original.replace(/\n$/, ''); |
| const relativeIndex = innerContent.indexOf(originalTrimmed); |
|
|
| if (relativeIndex === -1) { |
| return null; |
| } |
|
|
| const absoluteIndex = artifact.start + searchStart + relativeIndex; |
| const endText = originalText.substring(absoluteIndex + originalTrimmed.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, |
| }; |
|
|