fix: git import issue when importing bolt on bolt (#1020)

* fix: import bolt on bolt fix

* added escape on folder import

* type fix
This commit is contained in:
Anirban Kar 2025-01-27 18:05:55 +05:30 committed by GitHub
parent 6d4196a2b4
commit bbae032a37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 49 additions and 7 deletions

View File

@ -1,7 +1,7 @@
import ignore from 'ignore';
import { useGit } from '~/lib/hooks/useGit';
import type { Message } from 'ai';
import { detectProjectCommands, createCommandsMessage } from '~/utils/projectCommands';
import { detectProjectCommands, createCommandsMessage, escapeBoltTags } from '~/utils/projectCommands';
import { generateId } from '~/utils/fileUtils';
import { useState } from 'react';
import { toast } from 'react-toastify';
@ -84,7 +84,7 @@ ${fileContents
.map(
(file) =>
`<boltAction type="file" filePath="${file.path}">
${file.content}
${escapeBoltTags(file.content)}
</boltAction>`,
)
.join('\n')}

View File

@ -7,7 +7,7 @@ import { BaseChat } from '~/components/chat/BaseChat';
import { Chat } from '~/components/chat/Chat.client';
import { useGit } from '~/lib/hooks/useGit';
import { useChatHistory } from '~/lib/persistence';
import { createCommandsMessage, detectProjectCommands } from '~/utils/projectCommands';
import { createCommandsMessage, detectProjectCommands, escapeBoltTags } from '~/utils/projectCommands';
import { LoadingOverlay } from '~/components/ui/LoadingOverlay';
import { toast } from 'react-toastify';
@ -74,12 +74,12 @@ export function GitUrlImport() {
const filesMessage: Message = {
role: 'assistant',
content: `Cloning the repo ${repoUrl} into ${workdir}
<boltArtifact id="imported-files" title="Git Cloned Files" type="bundled">
<boltArtifact id="imported-files" title="Git Cloned Files" type="bundled">
${fileContents
.map(
(file) =>
`<boltAction type="file" filePath="${file.path}">
${file.content}
${escapeBoltTags(file.content)}
</boltAction>`,
)
.join('\n')}

View File

@ -64,6 +64,10 @@ function cleanoutMarkdownSyntax(content: string) {
return content;
}
}
function cleanEscapedTags(content: string) {
return content.replace(/&lt;/g, '<').replace(/&gt;/g, '>');
}
export class StreamingMessageParser {
#messages = new Map<string, MessageState>();
@ -110,6 +114,7 @@ export class StreamingMessageParser {
// Remove markdown code block syntax if present and file is not markdown
if (!currentAction.filePath.endsWith('.md')) {
content = cleanoutMarkdownSyntax(content);
content = cleanEscapedTags(content);
}
content += '\n';
@ -141,6 +146,7 @@ export class StreamingMessageParser {
if (!currentAction.filePath.endsWith('.md')) {
content = cleanoutMarkdownSyntax(content);
content = cleanEscapedTags(content);
}
this._options.callbacks?.onActionStream?.({

View File

@ -1,6 +1,6 @@
import type { Message } from 'ai';
import { generateId } from './fileUtils';
import { detectProjectCommands, createCommandsMessage } from './projectCommands';
import { detectProjectCommands, createCommandsMessage, escapeBoltTags } from './projectCommands';
export const createChatFromFolder = async (
files: File[],
@ -42,7 +42,7 @@ export const createChatFromFolder = async (
${fileArtifacts
.map(
(file) => `<boltAction type="file" filePath="${file.path}">
${file.content}
${escapeBoltTags(file.content)}
</boltAction>`,
)
.join('\n\n')}

View File

@ -78,3 +78,39 @@ ${commands.setupCommand}
createdAt: new Date(),
};
}
export function escapeBoltArtifactTags(input: string) {
// Regular expression to match boltArtifact tags and their content
const regex = /(<boltArtifact[^>]*>)([\s\S]*?)(<\/boltArtifact>)/g;
return input.replace(regex, (match, openTag, content, closeTag) => {
// Escape the opening tag
const escapedOpenTag = openTag.replace(/</g, '&lt;').replace(/>/g, '&gt;');
// Escape the closing tag
const escapedCloseTag = closeTag.replace(/</g, '&lt;').replace(/>/g, '&gt;');
// Return the escaped version
return `${escapedOpenTag}${content}${escapedCloseTag}`;
});
}
export function escapeBoltAActionTags(input: string) {
// Regular expression to match boltArtifact tags and their content
const regex = /(<boltAction[^>]*>)([\s\S]*?)(<\/boltAction>)/g;
return input.replace(regex, (match, openTag, content, closeTag) => {
// Escape the opening tag
const escapedOpenTag = openTag.replace(/</g, '&lt;').replace(/>/g, '&gt;');
// Escape the closing tag
const escapedCloseTag = closeTag.replace(/</g, '&lt;').replace(/>/g, '&gt;');
// Return the escaped version
return `${escapedOpenTag}${content}${escapedCloseTag}`;
});
}
export function escapeBoltTags(input: string) {
return escapeBoltArtifactTags(escapeBoltAActionTags(input));
}