Merge pull request #256 from devin-open-source/devin/1733521206-add-exclude-patterns-to-search-files
Add excludePatterns to search_files in filesystem server
This commit is contained in:
commit
0968e431f3
4 changed files with 49 additions and 8 deletions
26
package-lock.json
generated
26
package-lock.json
generated
|
|
@ -1565,6 +1565,13 @@
|
||||||
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
|
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/minimatch": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "22.9.0",
|
"version": "22.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz",
|
||||||
|
|
@ -5185,6 +5192,7 @@
|
||||||
"@modelcontextprotocol/sdk": "0.5.0",
|
"@modelcontextprotocol/sdk": "0.5.0",
|
||||||
"diff": "^5.1.0",
|
"diff": "^5.1.0",
|
||||||
"glob": "^10.3.10",
|
"glob": "^10.3.10",
|
||||||
|
"minimatch": "^10.0.1",
|
||||||
"zod-to-json-schema": "^3.23.5"
|
"zod-to-json-schema": "^3.23.5"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
@ -5192,6 +5200,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/diff": "^5.0.9",
|
"@types/diff": "^5.0.9",
|
||||||
|
"@types/minimatch": "^5.1.2",
|
||||||
"@types/node": "^20.11.0",
|
"@types/node": "^20.11.0",
|
||||||
"shx": "^0.3.4",
|
"shx": "^0.3.4",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
|
|
@ -5246,7 +5255,7 @@
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"src/filesystem/node_modules/minimatch": {
|
"src/filesystem/node_modules/glob/node_modules/minimatch": {
|
||||||
"version": "9.0.5",
|
"version": "9.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||||
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
||||||
|
|
@ -5261,6 +5270,21 @@
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"src/filesystem/node_modules/minimatch": {
|
||||||
|
"version": "10.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
|
||||||
|
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "20 || >=22"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"src/gdrive": {
|
"src/gdrive": {
|
||||||
"name": "@modelcontextprotocol/server-gdrive",
|
"name": "@modelcontextprotocol/server-gdrive",
|
||||||
"version": "0.6.2",
|
"version": "0.6.2",
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ Node.js server implementing Model Context Protocol (MCP) for filesystem operatio
|
||||||
- Inputs:
|
- Inputs:
|
||||||
- `path` (string): Starting directory
|
- `path` (string): Starting directory
|
||||||
- `pattern` (string): Search pattern
|
- `pattern` (string): Search pattern
|
||||||
|
- `excludePatterns` (string[]): Exclude any patterns. Glob formats are supported.
|
||||||
- Case-insensitive matching
|
- Case-insensitive matching
|
||||||
- Returns full paths to matches
|
- Returns full paths to matches
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import os from 'os';
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { zodToJsonSchema } from "zod-to-json-schema";
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
||||||
import { diffLines, createTwoFilesPatch } from 'diff';
|
import { diffLines, createTwoFilesPatch } from 'diff';
|
||||||
|
import { minimatch } from 'minimatch';
|
||||||
|
|
||||||
// Command line argument parsing
|
// Command line argument parsing
|
||||||
const args = process.argv.slice(2);
|
const args = process.argv.slice(2);
|
||||||
|
|
@ -134,6 +135,7 @@ const MoveFileArgsSchema = z.object({
|
||||||
const SearchFilesArgsSchema = z.object({
|
const SearchFilesArgsSchema = z.object({
|
||||||
path: z.string(),
|
path: z.string(),
|
||||||
pattern: z.string(),
|
pattern: z.string(),
|
||||||
|
excludePatterns: z.array(z.string()).optional().default([])
|
||||||
});
|
});
|
||||||
|
|
||||||
const GetFileInfoArgsSchema = z.object({
|
const GetFileInfoArgsSchema = z.object({
|
||||||
|
|
@ -183,6 +185,7 @@ async function getFileStats(filePath: string): Promise<FileInfo> {
|
||||||
async function searchFiles(
|
async function searchFiles(
|
||||||
rootPath: string,
|
rootPath: string,
|
||||||
pattern: string,
|
pattern: string,
|
||||||
|
excludePatterns: string[] = []
|
||||||
): Promise<string[]> {
|
): Promise<string[]> {
|
||||||
const results: string[] = [];
|
const results: string[] = [];
|
||||||
|
|
||||||
|
|
@ -196,6 +199,17 @@ async function searchFiles(
|
||||||
// Validate each path before processing
|
// Validate each path before processing
|
||||||
await validatePath(fullPath);
|
await validatePath(fullPath);
|
||||||
|
|
||||||
|
// Check if path matches any exclude pattern
|
||||||
|
const relativePath = path.relative(rootPath, fullPath);
|
||||||
|
const shouldExclude = excludePatterns.some(pattern => {
|
||||||
|
const globPattern = pattern.includes('*') ? pattern : `**/${pattern}/**`;
|
||||||
|
return minimatch(relativePath, globPattern, { dot: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
if (shouldExclude) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (entry.name.toLowerCase().includes(pattern.toLowerCase())) {
|
if (entry.name.toLowerCase().includes(pattern.toLowerCase())) {
|
||||||
results.push(fullPath);
|
results.push(fullPath);
|
||||||
}
|
}
|
||||||
|
|
@ -522,7 +536,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||||
throw new Error(`Invalid arguments for search_files: ${parsed.error}`);
|
throw new Error(`Invalid arguments for search_files: ${parsed.error}`);
|
||||||
}
|
}
|
||||||
const validPath = await validatePath(parsed.data.path);
|
const validPath = await validatePath(parsed.data.path);
|
||||||
const results = await searchFiles(validPath, parsed.data.pattern);
|
const results = await searchFiles(validPath, parsed.data.pattern, parsed.data.excludePatterns);
|
||||||
return {
|
return {
|
||||||
content: [{ type: "text", text: results.length > 0 ? results.join("\n") : "No matches found" }],
|
content: [{ type: "text", text: results.length > 0 ? results.join("\n") : "No matches found" }],
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,12 @@
|
||||||
"@modelcontextprotocol/sdk": "0.5.0",
|
"@modelcontextprotocol/sdk": "0.5.0",
|
||||||
"diff": "^5.1.0",
|
"diff": "^5.1.0",
|
||||||
"glob": "^10.3.10",
|
"glob": "^10.3.10",
|
||||||
|
"minimatch": "^10.0.1",
|
||||||
"zod-to-json-schema": "^3.23.5"
|
"zod-to-json-schema": "^3.23.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/diff": "^5.0.9",
|
"@types/diff": "^5.0.9",
|
||||||
|
"@types/minimatch": "^5.1.2",
|
||||||
"@types/node": "^20.11.0",
|
"@types/node": "^20.11.0",
|
||||||
"shx": "^0.3.4",
|
"shx": "^0.3.4",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue