feat(hooks): add rules-injector hook for .cursor/rules and .claude/rules support
Implements adaptive rule injection similar to Claude Code's rule system: - Searches .cursor/rules and .claude/rules directories recursively - Supports YAML frontmatter with globs, paths, alwaysApply, description - Adaptive project root detection (finds markers even outside ctx.directory) - Symlink duplicate detection via realpath comparison - Content hash deduplication (SHA-256) to avoid re-injecting same rules - picomatch-based glob pattern matching for file-specific rules 🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
import {
|
||||
existsSync,
|
||||
mkdirSync,
|
||||
readFileSync,
|
||||
writeFileSync,
|
||||
unlinkSync,
|
||||
} from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { RULES_INJECTOR_STORAGE } from "./constants";
|
||||
import type { InjectedRulesData } from "./types";
|
||||
|
||||
function getStoragePath(sessionID: string): string {
|
||||
return join(RULES_INJECTOR_STORAGE, `${sessionID}.json`);
|
||||
}
|
||||
|
||||
export function loadInjectedRules(sessionID: string): {
|
||||
contentHashes: Set<string>;
|
||||
realPaths: Set<string>;
|
||||
} {
|
||||
const filePath = getStoragePath(sessionID);
|
||||
if (!existsSync(filePath))
|
||||
return { contentHashes: new Set(), realPaths: new Set() };
|
||||
|
||||
try {
|
||||
const content = readFileSync(filePath, "utf-8");
|
||||
const data: InjectedRulesData = JSON.parse(content);
|
||||
return {
|
||||
contentHashes: new Set(data.injectedHashes),
|
||||
realPaths: new Set(data.injectedRealPaths ?? []),
|
||||
};
|
||||
} catch {
|
||||
return { contentHashes: new Set(), realPaths: new Set() };
|
||||
}
|
||||
}
|
||||
|
||||
export function saveInjectedRules(
|
||||
sessionID: string,
|
||||
data: { contentHashes: Set<string>; realPaths: Set<string> }
|
||||
): void {
|
||||
if (!existsSync(RULES_INJECTOR_STORAGE)) {
|
||||
mkdirSync(RULES_INJECTOR_STORAGE, { recursive: true });
|
||||
}
|
||||
|
||||
const storageData: InjectedRulesData = {
|
||||
sessionID,
|
||||
injectedHashes: [...data.contentHashes],
|
||||
injectedRealPaths: [...data.realPaths],
|
||||
updatedAt: Date.now(),
|
||||
};
|
||||
|
||||
writeFileSync(getStoragePath(sessionID), JSON.stringify(storageData, null, 2));
|
||||
}
|
||||
|
||||
export function clearInjectedRules(sessionID: string): void {
|
||||
const filePath = getStoragePath(sessionID);
|
||||
if (existsSync(filePath)) {
|
||||
unlinkSync(filePath);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user