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

View File

@ -7,7 +7,7 @@ import { BaseChat } from '~/components/chat/BaseChat';
import { Chat } from '~/components/chat/Chat.client'; import { Chat } from '~/components/chat/Chat.client';
import { useGit } from '~/lib/hooks/useGit'; import { useGit } from '~/lib/hooks/useGit';
import { useChatHistory } from '~/lib/persistence'; 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 { LoadingOverlay } from '~/components/ui/LoadingOverlay';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
@ -79,7 +79,7 @@ ${fileContents
.map( .map(
(file) => (file) =>
`<boltAction type="file" filePath="${file.path}"> `<boltAction type="file" filePath="${file.path}">
${file.content} ${escapeBoltTags(file.content)}
</boltAction>`, </boltAction>`,
) )
.join('\n')} .join('\n')}

View File

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

View File

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

View File

@ -78,3 +78,39 @@ ${commands.setupCommand}
createdAt: new Date(), 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));
}