codacus commited on
Commit
bbae032
·
unverified ·
1 Parent(s): 6d4196a

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

Browse files

* fix: import bolt on bolt fix

* added escape on folder import

* type fix

app/components/chat/GitCloneButton.tsx CHANGED
@@ -1,7 +1,7 @@
1
  import ignore from 'ignore';
2
  import { useGit } from '~/lib/hooks/useGit';
3
  import type { Message } from 'ai';
4
- import { detectProjectCommands, createCommandsMessage } from '~/utils/projectCommands';
5
  import { generateId } from '~/utils/fileUtils';
6
  import { useState } from 'react';
7
  import { toast } from 'react-toastify';
@@ -84,7 +84,7 @@ ${fileContents
84
  .map(
85
  (file) =>
86
  `<boltAction type="file" filePath="${file.path}">
87
- ${file.content}
88
  </boltAction>`,
89
  )
90
  .join('\n')}
 
1
  import ignore from 'ignore';
2
  import { useGit } from '~/lib/hooks/useGit';
3
  import type { Message } from 'ai';
4
+ import { detectProjectCommands, createCommandsMessage, escapeBoltTags } from '~/utils/projectCommands';
5
  import { generateId } from '~/utils/fileUtils';
6
  import { useState } from 'react';
7
  import { toast } from 'react-toastify';
 
84
  .map(
85
  (file) =>
86
  `<boltAction type="file" filePath="${file.path}">
87
+ ${escapeBoltTags(file.content)}
88
  </boltAction>`,
89
  )
90
  .join('\n')}
app/components/git/GitUrlImport.client.tsx CHANGED
@@ -7,7 +7,7 @@ import { BaseChat } from '~/components/chat/BaseChat';
7
  import { Chat } from '~/components/chat/Chat.client';
8
  import { useGit } from '~/lib/hooks/useGit';
9
  import { useChatHistory } from '~/lib/persistence';
10
- import { createCommandsMessage, detectProjectCommands } from '~/utils/projectCommands';
11
  import { LoadingOverlay } from '~/components/ui/LoadingOverlay';
12
  import { toast } from 'react-toastify';
13
 
@@ -74,12 +74,12 @@ export function GitUrlImport() {
74
  const filesMessage: Message = {
75
  role: 'assistant',
76
  content: `Cloning the repo ${repoUrl} into ${workdir}
77
- <boltArtifact id="imported-files" title="Git Cloned Files" type="bundled">
78
  ${fileContents
79
  .map(
80
  (file) =>
81
  `<boltAction type="file" filePath="${file.path}">
82
- ${file.content}
83
  </boltAction>`,
84
  )
85
  .join('\n')}
 
7
  import { Chat } from '~/components/chat/Chat.client';
8
  import { useGit } from '~/lib/hooks/useGit';
9
  import { useChatHistory } from '~/lib/persistence';
10
+ import { createCommandsMessage, detectProjectCommands, escapeBoltTags } from '~/utils/projectCommands';
11
  import { LoadingOverlay } from '~/components/ui/LoadingOverlay';
12
  import { toast } from 'react-toastify';
13
 
 
74
  const filesMessage: Message = {
75
  role: 'assistant',
76
  content: `Cloning the repo ${repoUrl} into ${workdir}
77
+ <boltArtifact id="imported-files" title="Git Cloned Files" type="bundled">
78
  ${fileContents
79
  .map(
80
  (file) =>
81
  `<boltAction type="file" filePath="${file.path}">
82
+ ${escapeBoltTags(file.content)}
83
  </boltAction>`,
84
  )
85
  .join('\n')}
app/lib/runtime/message-parser.ts CHANGED
@@ -64,6 +64,10 @@ function cleanoutMarkdownSyntax(content: string) {
64
  return content;
65
  }
66
  }
 
 
 
 
67
  export class StreamingMessageParser {
68
  #messages = new Map<string, MessageState>();
69
 
@@ -110,6 +114,7 @@ export class StreamingMessageParser {
110
  // Remove markdown code block syntax if present and file is not markdown
111
  if (!currentAction.filePath.endsWith('.md')) {
112
  content = cleanoutMarkdownSyntax(content);
 
113
  }
114
 
115
  content += '\n';
@@ -141,6 +146,7 @@ export class StreamingMessageParser {
141
 
142
  if (!currentAction.filePath.endsWith('.md')) {
143
  content = cleanoutMarkdownSyntax(content);
 
144
  }
145
 
146
  this._options.callbacks?.onActionStream?.({
 
64
  return content;
65
  }
66
  }
67
+
68
+ function cleanEscapedTags(content: string) {
69
+ return content.replace(/&lt;/g, '<').replace(/&gt;/g, '>');
70
+ }
71
  export class StreamingMessageParser {
72
  #messages = new Map<string, MessageState>();
73
 
 
114
  // Remove markdown code block syntax if present and file is not markdown
115
  if (!currentAction.filePath.endsWith('.md')) {
116
  content = cleanoutMarkdownSyntax(content);
117
+ content = cleanEscapedTags(content);
118
  }
119
 
120
  content += '\n';
 
146
 
147
  if (!currentAction.filePath.endsWith('.md')) {
148
  content = cleanoutMarkdownSyntax(content);
149
+ content = cleanEscapedTags(content);
150
  }
151
 
152
  this._options.callbacks?.onActionStream?.({
app/utils/folderImport.ts CHANGED
@@ -1,6 +1,6 @@
1
  import type { Message } from 'ai';
2
  import { generateId } from './fileUtils';
3
- import { detectProjectCommands, createCommandsMessage } from './projectCommands';
4
 
5
  export const createChatFromFolder = async (
6
  files: File[],
@@ -42,7 +42,7 @@ export const createChatFromFolder = async (
42
  ${fileArtifacts
43
  .map(
44
  (file) => `<boltAction type="file" filePath="${file.path}">
45
- ${file.content}
46
  </boltAction>`,
47
  )
48
  .join('\n\n')}
 
1
  import type { Message } from 'ai';
2
  import { generateId } from './fileUtils';
3
+ import { detectProjectCommands, createCommandsMessage, escapeBoltTags } from './projectCommands';
4
 
5
  export const createChatFromFolder = async (
6
  files: File[],
 
42
  ${fileArtifacts
43
  .map(
44
  (file) => `<boltAction type="file" filePath="${file.path}">
45
+ ${escapeBoltTags(file.content)}
46
  </boltAction>`,
47
  )
48
  .join('\n\n')}
app/utils/projectCommands.ts CHANGED
@@ -78,3 +78,39 @@ ${commands.setupCommand}
78
  createdAt: new Date(),
79
  };
80
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  createdAt: new Date(),
79
  };
80
  }
81
+
82
+ export function escapeBoltArtifactTags(input: string) {
83
+ // Regular expression to match boltArtifact tags and their content
84
+ const regex = /(<boltArtifact[^>]*>)([\s\S]*?)(<\/boltArtifact>)/g;
85
+
86
+ return input.replace(regex, (match, openTag, content, closeTag) => {
87
+ // Escape the opening tag
88
+ const escapedOpenTag = openTag.replace(/</g, '&lt;').replace(/>/g, '&gt;');
89
+
90
+ // Escape the closing tag
91
+ const escapedCloseTag = closeTag.replace(/</g, '&lt;').replace(/>/g, '&gt;');
92
+
93
+ // Return the escaped version
94
+ return `${escapedOpenTag}${content}${escapedCloseTag}`;
95
+ });
96
+ }
97
+
98
+ export function escapeBoltAActionTags(input: string) {
99
+ // Regular expression to match boltArtifact tags and their content
100
+ const regex = /(<boltAction[^>]*>)([\s\S]*?)(<\/boltAction>)/g;
101
+
102
+ return input.replace(regex, (match, openTag, content, closeTag) => {
103
+ // Escape the opening tag
104
+ const escapedOpenTag = openTag.replace(/</g, '&lt;').replace(/>/g, '&gt;');
105
+
106
+ // Escape the closing tag
107
+ const escapedCloseTag = closeTag.replace(/</g, '&lt;').replace(/>/g, '&gt;');
108
+
109
+ // Return the escaped version
110
+ return `${escapedOpenTag}${content}${escapedCloseTag}`;
111
+ });
112
+ }
113
+
114
+ export function escapeBoltTags(input: string) {
115
+ return escapeBoltArtifactTags(escapeBoltAActionTags(input));
116
+ }