From d36aa17bcd2d043a94d66a8b623cca46209b1f71 Mon Sep 17 00:00:00 2001 From: Anirban Kar Date: Thu, 14 Nov 2024 15:39:29 +0530 Subject: [PATCH] refactor: added ignore patterns to remove or redact files from context --- app/components/chat/Chat.client.tsx | 2 -- app/lib/stores/tool.ts | 40 ++++++++++++++++++++++++++--- app/utils/matchPatterns.ts | 28 ++++++++++++++++++++ 3 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 app/utils/matchPatterns.ts diff --git a/app/components/chat/Chat.client.tsx b/app/components/chat/Chat.client.tsx index 357012187..1d33373ac 100644 --- a/app/components/chat/Chat.client.tsx +++ b/app/components/chat/Chat.client.tsx @@ -115,12 +115,10 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp toolCallId: toolCall.toolCallId, }); logger.info('Tool Call Complete', toolCall.toolName, `${result}`.split('---')[0]); - // addToolResult({ toolCallId: toolCall.toolCallId, result: result }); return result; } catch (error) { logger.error('Error calling tool:', toolCall.toolName, error); toast.error('There was an error processing your request'); - // addToolResult({ toolCallId: toolCall.toolCallId, result: 'Error calling tool:' + error }); return 'Error calling tool'; } }, diff --git a/app/lib/stores/tool.ts b/app/lib/stores/tool.ts index 8c2b1c252..c0fbce1cd 100644 --- a/app/lib/stores/tool.ts +++ b/app/lib/stores/tool.ts @@ -6,6 +6,7 @@ import { webcontainer } from '../webcontainer'; import { map, type MapStore } from 'nanostores'; import type { IToolsConfig } from '~/utils/types'; import Cookies from 'js-cookie'; +import { matchPatterns } from '~/utils/matchPatterns'; export class ToolStore { #webcontainer: Promise; @@ -78,7 +79,40 @@ export class ToolStore { await workbenchStore.updateFile(fullPath, file.content) await workbenchStore.saveFile(file.path) } - let templatePromptFile = files.filter(x => x.path.startsWith(".bolt")).filter(x => x.name == 'prompt') + + let filteredFiles = files; + + // ignoring common unwanted files + // exclude .git + filteredFiles = filteredFiles.filter(x => x.path.startsWith(".git") == false) + // exclude lock files + let comminLockFiles = ["package-lock.json", "yarn.lock", "pnpm-lock.yaml"] + filteredFiles = filteredFiles.filter(x => comminLockFiles.includes(x.name) == false) + // exclude .bolt + filteredFiles = filteredFiles.filter(x => x.path.startsWith(".bolt") == false) + + + // check for ignore file in .bolt folder + let templateIgnoreFile = files.find(x => x.path.startsWith(".bolt") && x.name == "ignore") + if (templateIgnoreFile) { + // redacting files specified in ignore file + let ignorepatterns = templateIgnoreFile.content.split("\n").map(x => x.trim()) + filteredFiles = filteredFiles.filter(x => matchPatterns(x.path, ignorepatterns) == false) + let redactedFiles = filteredFiles.filter(x => matchPatterns(x.path, ignorepatterns)) + redactedFiles = redactedFiles.map(x => { + return { + ...x, + content: "redacted" + } + }) + filteredFiles = [ + ...filteredFiles, + ...redactedFiles + ] + } + + let templatePromptFile = files.filter(x => x.path.startsWith(".bolt")).find(x => x.name == 'prompt') + return this.generateFormattedResult(`template imported successfully`, ` here is the imported content, these files are loaded into the bolt. to not write them again, if it don't require changes @@ -87,13 +121,13 @@ export class ToolStore { ${templatePromptFile ? ` - ${templatePromptFile[0].content} + ${templatePromptFile.content} `: '' } - ${JSON.stringify(files.filter(x => !(x.path.endsWith(".svg") || x.path.endsWith(".md"))), null, 2)} + ${JSON.stringify(filteredFiles, null, 2)} `) } catch (error) { diff --git a/app/utils/matchPatterns.ts b/app/utils/matchPatterns.ts new file mode 100644 index 000000000..9c80c1c2d --- /dev/null +++ b/app/utils/matchPatterns.ts @@ -0,0 +1,28 @@ +/** + * A utility to match glob patterns in the browser + * Supports basic glob features like * and ** + */ +export function isMatch(path: string, pattern: string): boolean { + // Convert glob pattern to regex + const regex = pattern + // Escape special regex characters except * and / + .replace(/[.+?^${}()|[\]\\]/g, '\\$&') + // Replace ** with special marker + .replace(/\*\*/g, '{{GLOBSTAR}}') + // Replace single * with non-slash matcher + .replace(/\*/g, '[^/]*') + // Replace globstar marker with proper pattern + .replace(/{{GLOBSTAR}}/g, '.*') + // Anchor pattern to full path match + .replace(/^/, '^') + .replace(/$/, '$'); + + return new RegExp(regex).test(path); +} + +/** + * Match multiple patterns against a path + */ +export function matchPatterns(path: string, patterns: string[]): boolean { + return patterns.some(pattern => isMatch(path, pattern)); +} \ No newline at end of file