summaryrefslogtreecommitdiff
path: root/packages/cli/src/ui/hooks/atCommandProcessor.ts
diff options
context:
space:
mode:
authorDeWitt Clinton <[email protected]>2025-05-21 12:22:18 -0700
committerGitHub <[email protected]>2025-05-21 12:22:18 -0700
commit01c28df8b2bcdb34d5a4ee5f330bbb8d1df0b334 (patch)
tree299bee70aa5f1575dbb408a6be08595b65c68baf /packages/cli/src/ui/hooks/atCommandProcessor.ts
parente1a64b41e854182991cac265ba3c0335e500918c (diff)
Add globbing support to @-command file suggestions and resolution. (#462)
Implements recursive glob-based file search for both suggestions and execution of the `@` command. - When typing `@filename`, suggestions will now include files matching `filename` in nested directories. - Suggestions are sorted by path depth (shallowest first), then directories before files, then alphabetically. - The maximum recursion depth for suggestions is set to 10. - When executing an `@filename` command, if the file is not found directly, a recursive search (using the glob tool) is performed to locate the file. This addresses the first request in issue #461 by allowing users to quickly reference deeply nested files without typing the full path. Also addresses b/416292478.
Diffstat (limited to 'packages/cli/src/ui/hooks/atCommandProcessor.ts')
-rw-r--r--packages/cli/src/ui/hooks/atCommandProcessor.ts63
1 files changed, 60 insertions, 3 deletions
diff --git a/packages/cli/src/ui/hooks/atCommandProcessor.ts b/packages/cli/src/ui/hooks/atCommandProcessor.ts
index a5b602ad..dd97a0d6 100644
--- a/packages/cli/src/ui/hooks/atCommandProcessor.ts
+++ b/packages/cli/src/ui/hooks/atCommandProcessor.ts
@@ -150,10 +150,67 @@ export async function handleAtCommand({
onDebugMessage(`Path resolved to file: ${pathSpec}`);
}
} catch (error) {
- // If stat fails (e.g., not found), proceed with original path.
- // The tool itself will handle the error during execution.
if (isNodeError(error) && error.code === 'ENOENT') {
- onDebugMessage(`Path not found, proceeding with original: ${pathSpec}`);
+ onDebugMessage(
+ `Path ${pathPart} not found directly, attempting glob search.`,
+ );
+ const globTool = toolRegistry.getTool('glob');
+ if (globTool) {
+ try {
+ const globResult = await globTool.execute(
+ {
+ pattern: `**/*${pathPart}*`,
+ path: config.getTargetDir(), // Ensure glob searches from the root
+ },
+ signal,
+ );
+ // Assuming llmContent contains the list of files or a "no files found" message.
+ // And that paths are absolute.
+ if (
+ globResult.llmContent &&
+ typeof globResult.llmContent === 'string' &&
+ !globResult.llmContent.startsWith('No files found') &&
+ !globResult.llmContent.startsWith('Error:')
+ ) {
+ // Extract the first line after the header
+ const lines = globResult.llmContent.split('\n');
+ if (lines.length > 1 && lines[1]) {
+ const firstMatchAbsolute = lines[1].trim();
+ // Convert absolute path from glob to relative path for read_many_files
+ pathSpec = path.relative(
+ config.getTargetDir(),
+ firstMatchAbsolute,
+ );
+ onDebugMessage(
+ `Glob search found ${firstMatchAbsolute}, using relative path: ${pathSpec}`,
+ );
+ } else {
+ onDebugMessage(
+ `Glob search for '**/*${pathPart}*' did not return a usable path. Proceeding with original: ${pathPart}`,
+ );
+ // pathSpec remains pathPart
+ }
+ } else {
+ onDebugMessage(
+ `Glob search for '**/*${pathPart}*' found no files or an error occurred. Proceeding with original: ${pathPart}`,
+ );
+ // pathSpec remains pathPart
+ }
+ } catch (globError) {
+ console.error(
+ `Error during glob search: ${getErrorMessage(globError)}`,
+ );
+ onDebugMessage(
+ `Error during glob search. Proceeding with original: ${pathPart}`,
+ );
+ // pathSpec remains pathPart
+ }
+ } else {
+ onDebugMessage(
+ 'Glob tool not found. Proceeding with original path: ${pathPart}',
+ );
+ // pathSpec remains pathPart
+ }
} else {
console.error(
`Error stating path ${pathPart}: ${getErrorMessage(error)}`,