fb7d47f1b7
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
45 lines
1.6 KiB
TypeScript
45 lines
1.6 KiB
TypeScript
import { existsSync, readdirSync, realpathSync } from "node:fs";
|
|
import { join } from "node:path";
|
|
import { EXCLUDED_DIRS, GITHUB_INSTRUCTIONS_PATTERN, RULE_EXTENSIONS } from "./constants";
|
|
import type { DirectoryScanEntry } from "./types";
|
|
|
|
function isGitHubInstructionsDir(dir: string): boolean {
|
|
return dir.includes(".github/instructions") || dir.endsWith(".github/instructions");
|
|
}
|
|
|
|
function isRuleFile(fileName: string, dir: string): boolean {
|
|
if (isGitHubInstructionsDir(dir)) return GITHUB_INSTRUCTIONS_PATTERN.test(fileName);
|
|
return RULE_EXTENSIONS.some((extension) => fileName.endsWith(extension));
|
|
}
|
|
|
|
export function safeRealpathSync(filePath: string): string {
|
|
try {
|
|
return realpathSync.native(filePath);
|
|
} catch {
|
|
return filePath;
|
|
}
|
|
}
|
|
|
|
export function findRuleFilesRecursive(dir: string, results: DirectoryScanEntry[], visited = new Set<string>()): void {
|
|
if (!existsSync(dir)) return;
|
|
const realDir = safeRealpathSync(dir);
|
|
if (visited.has(realDir)) return;
|
|
visited.add(realDir);
|
|
let entries;
|
|
try {
|
|
entries = readdirSync(dir, { withFileTypes: true, encoding: "utf8" }).sort((left, right) => left.name.localeCompare(right.name));
|
|
} catch {
|
|
return;
|
|
}
|
|
for (const entry of entries) {
|
|
const fullPath = join(dir, entry.name);
|
|
if (entry.isDirectory()) {
|
|
if (!EXCLUDED_DIRS.has(entry.name)) findRuleFilesRecursive(fullPath, results, visited);
|
|
continue;
|
|
}
|
|
if (entry.isFile() && isRuleFile(entry.name, dir)) {
|
|
results.push({ path: fullPath, realPath: safeRealpathSync(fullPath), relativePath: entry.name });
|
|
}
|
|
}
|
|
}
|