createGlobTool function
Builds the tool that finds files by glob pattern.
Implementation
Tool<JsonMap, String> createGlobTool(
Genkit ai, {
required ToolRuntime runtime,
}) {
return defineTextTool(
ai,
runtime: runtime,
name: 'glob',
description: _description,
properties: <String, Object?>{
'pattern': stringProperty('The glob pattern to match, e.g. "**/*.dart".'),
'path': stringProperty('Directory to search. Defaults to the current working directory.'),
},
required: <String>['pattern'],
run: (input) async {
final pattern = requireString(input, 'pattern').trim();
final pathInput = readString(input, 'path');
final searchPath = pathInput == null ? runtime.currentWorkingDirectory : runtime.resolvePath(pathInput);
if (!await Directory(searchPath).exists()) {
throw ToolFailure('Directory does not exist: $searchPath');
}
runtime.startTool('glob', '$pattern in ${runtime.displayPath(searchPath)}');
final ProcessResult result;
try {
result = await Process.run(
'rg',
<String>['--files', '--glob', pattern, '--color=never'],
workingDirectory: searchPath,
);
} on ProcessException {
throw const ToolFailure('ripgrep (`rg`) is not installed. Ask the user to install it.');
}
if (result.exitCode > 1) {
throw ToolFailure('rg exited with code ${result.exitCode}: ${'${result.stderr}'.trim()}');
}
final relativePaths = '${result.stdout}'.split('\n').where((line) => line.isNotEmpty);
if (relativePaths.isEmpty) {
return 'No files found.';
}
final files = <(String, DateTime)>[];
for (final relative in relativePaths) {
final path = runtime.resolvePath(relative, fromDirectory: searchPath);
files.add((path, (await FileStat.stat(path)).modified));
}
files.sort((a, b) => b.$2.compareTo(a.$2));
final shown = files.take(_maxResults).map((file) => file.$1).join('\n');
if (files.length > _maxResults) {
return '$shown\n\n(Showing $_maxResults of ${files.length} files. Use a more specific pattern or path.)';
}
return shown;
},
);
}