mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
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.
This commit is contained in:
@@ -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)}`,
|
||||
|
||||
Reference in New Issue
Block a user