MagicCode/packages/ext-claudecode/src/tools/glob.ts
2026-10-11 02:11:20 +02:00

62 lines
2.3 KiB
TypeScript

import { stat } from "node:fs/promises";
import { relative, sep } from "node:path";
import picomatch from "picomatch";
import type { Tool } from "@magiccode/core";
import { displayPath, optStr, resolvePath, str } from "./helpers";
import { walkFiles } from "./walk";
const MAX_RESULTS = 100;
export const globTool: Tool = {
spec: {
name: "Glob",
description:
'Trouve des fichiers par motif glob (ex. "**/*.ts", "src/**/*.test.ts", "*.json"). ' +
"Le motif est relatif au dossier de recherche. Résultats triés par date de modification " +
"(les plus récents d'abord), limités à 100. Ignore .git, node_modules et les fichiers exclus par .gitignore.",
inputSchema: {
type: "object",
properties: {
pattern: { type: "string", description: "Motif glob à rechercher" },
path: {
type: "string",
description: "Dossier de recherche : complet ou relatif au dossier de lancement (défaut : ce dossier).",
},
},
required: ["pattern"],
},
},
permission: "auto",
describe: (i) => `${String(i.pattern ?? "")}${i.path ? ` dans ${String(i.path)}` : ""}`,
async execute(input, ctx) {
const pattern = str(input, "pattern");
const root = resolvePath(ctx.cwd, optStr(input, "path") ?? ".");
try {
if (!(await stat(root)).isDirectory()) throw new Error();
} catch {
throw new Error(`Dossier de recherche introuvable : ${root}`);
}
const isMatch = picomatch(pattern, { dot: true });
const matched: string[] = [];
for await (const abs of walkFiles(root, ctx.signal)) {
if (isMatch(relative(root, abs).split(sep).join("/"))) matched.push(abs);
}
if (matched.length === 0) return `Aucun fichier ne correspond au motif "${pattern}"`;
const withTime = await Promise.all(
matched.map(async (abs) => ({
abs,
mtime: await stat(abs).then((s) => s.mtimeMs, () => 0),
})),
);
withTime.sort((a, b) => b.mtime - a.mtime);
const shown = withTime.slice(0, MAX_RESULTS).map((f) => displayPath(ctx.cwd, f.abs));
const extra = withTime.length - shown.length;
return extra > 0
? `${shown.join("\n")}\n(${extra} résultat(s) supplémentaire(s) non affiché(s) : affinez le motif)`
: shown.join("\n");
},
};