Files
Moltbot/src/agents/glob-pattern.ts
2026-02-14 15:39:44 +00:00

57 lines
1.5 KiB
TypeScript

export type CompiledGlobPattern =
| { kind: "all" }
| { kind: "exact"; value: string }
| { kind: "regex"; value: RegExp };
function escapeRegex(value: string) {
// Standard "escape string for regex literal" pattern.
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
export function compileGlobPattern(params: {
raw: string;
normalize: (value: string) => string;
}): CompiledGlobPattern {
const normalized = params.normalize(params.raw);
if (!normalized) {
return { kind: "exact", value: "" };
}
if (normalized === "*") {
return { kind: "all" };
}
if (!normalized.includes("*")) {
return { kind: "exact", value: normalized };
}
return {
kind: "regex",
value: new RegExp(`^${escapeRegex(normalized).replaceAll("\\*", ".*")}$`),
};
}
export function compileGlobPatterns(params: {
raw?: string[] | undefined;
normalize: (value: string) => string;
}): CompiledGlobPattern[] {
if (!Array.isArray(params.raw)) {
return [];
}
return params.raw
.map((raw) => compileGlobPattern({ raw, normalize: params.normalize }))
.filter((pattern) => pattern.kind !== "exact" || pattern.value);
}
export function matchesAnyGlobPattern(value: string, patterns: CompiledGlobPattern[]): boolean {
for (const pattern of patterns) {
if (pattern.kind === "all") {
return true;
}
if (pattern.kind === "exact" && value === pattern.value) {
return true;
}
if (pattern.kind === "regex" && pattern.value.test(value)) {
return true;
}
}
return false;
}