Files
oh-my-openagent/src/hooks/rules-injector/storage.ts
YeonGyu-Kim fcdfcd3186 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)
2025-12-13 00:35:34 +09:00

60 lines
1.6 KiB
TypeScript

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);
}
}