summaryrefslogtreecommitdiff
path: root/packages/server/src/tools/glob.ts
diff options
context:
space:
mode:
authorTaylor Mullen <[email protected]>2025-05-18 00:04:32 -0700
committerN. Taylor Mullen <[email protected]>2025-05-18 00:10:56 -0700
commita0eb8e67c7786f5dbd49ce79e43ae4f039d080b5 (patch)
treefa2e1ba8280db330b2b980edb73ea77fcaa309dd /packages/server/src/tools/glob.ts
parentf0b9199a772d23f8c9375c8cd627da345bc205ae (diff)
fix(glob): Improve glob tool accuracy and output
This commit enhances the glob tool by: - Ensuring that glob patterns are used effectively. Previously, simple file names without glob syntax (e.g., "file.ts") would only search the root directory. This change encourages more precise glob patterns (e.g., "**\/file.ts") for broader searches. - Returning absolute file paths instead of relative paths. This provides clearer, less ambiguous output and avoids encouraging the use of relative paths in subsequent operations. - Adding comprehensive tests for various globbing scenarios, including case sensitivity and path specifications. These changes address an issue where the glob tool could not find an expected item when a specific path was provided without appropriate glob syntax, and improve the overall reliability and usability of the tool. Fixes https://b.corp.google.com/issues/418486553
Diffstat (limited to 'packages/server/src/tools/glob.ts')
-rw-r--r--packages/server/src/tools/glob.ts44
1 files changed, 22 insertions, 22 deletions
diff --git a/packages/server/src/tools/glob.ts b/packages/server/src/tools/glob.ts
index b1b9d0cf..86aef44f 100644
--- a/packages/server/src/tools/glob.ts
+++ b/packages/server/src/tools/glob.ts
@@ -24,6 +24,11 @@ export interface GlobToolParams {
* The directory to search in (optional, defaults to current directory)
*/
path?: string;
+
+ /**
+ * Whether the search should be case-sensitive (optional, defaults to false)
+ */
+ case_sensitive?: boolean;
}
/**
@@ -44,7 +49,7 @@ export class GlobTool extends BaseTool<GlobToolParams, ToolResult> {
properties: {
pattern: {
description:
- "The glob pattern to match against (e.g., '*.py', 'src/**/*.js', 'docs/*.md').",
+ "The glob pattern to match against (e.g., '**/*.py', 'docs/*.md').",
type: 'string',
},
path: {
@@ -52,6 +57,11 @@ export class GlobTool extends BaseTool<GlobToolParams, ToolResult> {
'Optional: The absolute path to the directory to search within. If omitted, searches the root directory.',
type: 'string',
},
+ case_sensitive: {
+ description:
+ 'Optional: Whether the search should be case-sensitive. Defaults to false.',
+ type: 'boolean',
+ },
},
required: ['pattern'],
type: 'object',
@@ -88,7 +98,7 @@ export class GlobTool extends BaseTool<GlobToolParams, ToolResult> {
params,
)
) {
- return "Parameters failed schema validation. Ensure 'pattern' is a string and 'path' (if provided) is a string.";
+ return "Parameters failed schema validation. Ensure 'pattern' is a string, 'path' (if provided) is a string, and 'case_sensitive' (if provided) is a boolean.";
}
const searchDirAbsolute = path.resolve(
@@ -100,12 +110,13 @@ export class GlobTool extends BaseTool<GlobToolParams, ToolResult> {
return `Search path ("${searchDirAbsolute}") resolves outside the tool's root directory ("${this.rootDirectory}").`;
}
+ const targetDir = searchDirAbsolute || this.rootDirectory;
try {
- if (!fs.existsSync(searchDirAbsolute)) {
- return `Search path does not exist: ${shortenPath(makeRelative(searchDirAbsolute, this.rootDirectory))} (absolute: ${searchDirAbsolute})`;
+ if (!fs.existsSync(targetDir)) {
+ return `Search path does not exist ${targetDir}`;
}
- if (!fs.statSync(searchDirAbsolute).isDirectory()) {
- return `Search path is not a directory: ${shortenPath(makeRelative(searchDirAbsolute, this.rootDirectory))} (absolute: ${searchDirAbsolute})`;
+ if (!fs.statSync(targetDir).isDirectory()) {
+ return `Search path is not a directory: ${targetDir}`;
}
} catch (e: unknown) {
return `Error accessing search path: ${e}`;
@@ -162,15 +173,15 @@ export class GlobTool extends BaseTool<GlobToolParams, ToolResult> {
onlyFiles: true,
stats: true,
dot: true,
+ caseSensitiveMatch: params.case_sensitive ?? false,
ignore: ['**/node_modules/**', '**/.git/**'],
followSymbolicLinks: false,
suppressErrors: true,
});
if (!entries || entries.length === 0) {
- const displayPath = makeRelative(searchDirAbsolute, this.rootDirectory);
return {
- llmContent: `No files found matching pattern "${params.pattern}" within ${displayPath || '.'}.`,
+ llmContent: `No files found matching pattern "${params.pattern}" within ${searchDirAbsolute}.`,
returnDisplay: `No files found`,
};
}
@@ -182,22 +193,11 @@ export class GlobTool extends BaseTool<GlobToolParams, ToolResult> {
});
const sortedAbsolutePaths = entries.map((entry) => entry.path);
- const sortedRelativePaths = sortedAbsolutePaths.map((absPath) =>
- makeRelative(absPath, this.rootDirectory),
- );
-
- const fileListDescription = sortedRelativePaths.join('\n');
- const fileCount = sortedRelativePaths.length;
- const relativeSearchDir = makeRelative(
- searchDirAbsolute,
- this.rootDirectory,
- );
- const displayPath = shortenPath(
- relativeSearchDir === '.' ? 'root directory' : relativeSearchDir,
- );
+ const fileListDescription = sortedAbsolutePaths.join('\n');
+ const fileCount = sortedAbsolutePaths.length;
return {
- llmContent: `Found ${fileCount} file(s) matching "${params.pattern}" within ${displayPath}, sorted by modification time (newest first):\n${fileListDescription}`,
+ llmContent: `Found ${fileCount} file(s) matching "${params.pattern}" within ${searchDirAbsolute}, sorted by modification time (newest first):\n${fileListDescription}`,
returnDisplay: `Found ${fileCount} matching file(s)`,
};
} catch (error) {