MCPcopy Create free account
hub / github.com/QodeXcli/QodeX / runNative

Method runNative

src/tools/filesystem/grep.ts:97–185  ·  view source on GitHub ↗
(
    args: z.infer<typeof ArgsSchema>,
    target: string,
    maxResults: number,
    outputMode: 'content' | 'files_only' | 'count',
  )

Source from the content-addressed store, hash-verified

95 }
96
97 private async runNative(
98 args: z.infer<typeof ArgsSchema>,
99 target: string,
100 maxResults: number,
101 outputMode: 'content' | 'files_only' | 'count',
102 ): Promise<ToolResult> {
103 const flags = args.case_insensitive ? 'gi' : 'g';
104 let regex: RegExp;
105 try {
106 regex = new RegExp(args.pattern, flags);
107 } catch (e: any) {
108 return { content: `[REGEX_ERROR] Invalid pattern: ${e.message}`, isError: true };
109 }
110
111 const fileFilter = args.glob ? new RegExp(this.globToRegex(args.glob)) : null;
112 const IGNORED_DIRS = new Set([
113 'node_modules', '.git', 'dist', 'build', '__pycache__', 'target', '.next', '.cache', 'venv', '.venv',
114 ]);
115
116 const fileMatches: Array<{ file: string; lines: Array<{ num: number; text: string }> }> = [];
117 let totalMatches = 0;
118
119 async function walk(dir: string): Promise<void> {
120 if (totalMatches >= maxResults) return;
121 let entries: any[];
122 try {
123 const stat = await fs.stat(dir);
124 if (stat.isFile()) {
125 entries = [{ name: path.basename(dir), isDirectory: () => false }];
126 dir = path.dirname(dir);
127 } else {
128 entries = await fs.readdir(dir, { withFileTypes: true });
129 }
130 } catch { return; }
131
132 for (const entry of entries) {
133 if (totalMatches >= maxResults) return;
134 if (entry.name.startsWith('.') && entry.name !== '.env') continue;
135 if (entry.isDirectory()) {
136 if (IGNORED_DIRS.has(entry.name)) continue;
137 await walk(path.join(dir, entry.name));
138 } else {
139 const full = path.join(dir, entry.name);
140 if (fileFilter && !fileFilter.test(entry.name)) continue;
141 let content: string;
142 try {
143 const stat = await fs.stat(full);
144 if (stat.size > 2 * 1024 * 1024) continue; // skip huge files
145 content = await fs.readFile(full, 'utf-8');
146 } catch { continue; }
147
148 const lines = content.split('\n');
149 const matches: Array<{ num: number; text: string }> = [];
150 for (let i = 0; i < lines.length; i++) {
151 if (regex.test(lines[i]!)) {
152 matches.push({ num: i + 1, text: lines[i]! });
153 totalMatches++;
154 if (totalMatches >= maxResults) break;

Callers 1

executeMethod · 0.95

Calls 3

globToRegexMethod · 0.95
walkFunction · 0.70
pushMethod · 0.45

Tested by

no test coverage detected