refactor(rules): delegate injectors to rules-core
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import { constants, promises as fsPromises } from "node:fs";
|
||||
import { dirname, isAbsolute, join, resolve } from "node:path";
|
||||
|
||||
import { AGENTS_FILENAME } from "./constants";
|
||||
import { findAgentsMdUp as findAgentsMdUpCore } from "@oh-my-opencode/rules-core";
|
||||
import type { AgentsMdCache } from "@oh-my-opencode/rules-core";
|
||||
import { isAbsolute, resolve } from "node:path";
|
||||
|
||||
export function resolveFilePath(rootDirectory: string, path: string): string | null {
|
||||
if (!path) return null;
|
||||
@@ -10,33 +9,9 @@ export function resolveFilePath(rootDirectory: string, path: string): string | n
|
||||
}
|
||||
|
||||
export async function findAgentsMdUp(input: {
|
||||
startDir: string;
|
||||
rootDir: string;
|
||||
readonly startDir: string;
|
||||
readonly rootDir: string;
|
||||
readonly cache?: AgentsMdCache;
|
||||
}): Promise<string[]> {
|
||||
const found: string[] = [];
|
||||
let current = input.startDir;
|
||||
|
||||
while (true) {
|
||||
// Skip root AGENTS.md - OpenCode's system.ts already loads it via custom()
|
||||
// See: https://github.com/code-yeongyu/oh-my-openagent/issues/379
|
||||
const isRootDir = current === input.rootDir;
|
||||
if (!isRootDir) {
|
||||
const agentsPath = join(current, AGENTS_FILENAME);
|
||||
const exists = await fsPromises
|
||||
.access(agentsPath, constants.F_OK)
|
||||
.then(() => true)
|
||||
.catch(() => false);
|
||||
if (exists) {
|
||||
found.push(agentsPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (isRootDir) break;
|
||||
const parent = dirname(current);
|
||||
if (parent === current) break;
|
||||
if (!parent.startsWith(input.rootDir)) break;
|
||||
current = parent;
|
||||
}
|
||||
|
||||
return found.reverse();
|
||||
return findAgentsMdUpCore({ startDir: input.startDir, rootDir: input.rootDir, cache: input.cache });
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { createAgentsMdCache } from "@oh-my-opencode/rules-core";
|
||||
import type { PluginInput } from "@opencode-ai/plugin";
|
||||
|
||||
import { createDynamicTruncator } from "../../shared/dynamic-truncator";
|
||||
@@ -35,6 +36,7 @@ export function createDirectoryAgentsInjectorHook(
|
||||
modelCacheState?: { anthropicContext1MEnabled: boolean },
|
||||
): DirectoryAgentsInjectorHook {
|
||||
const sessionCaches = new Map<string, Set<string>>();
|
||||
const agentsMdCache = createAgentsMdCache();
|
||||
const truncator = createDynamicTruncator(ctx, modelCacheState);
|
||||
|
||||
const toolExecuteAfter = async (input: ToolExecuteInput, output: ToolExecuteOutput) => {
|
||||
@@ -45,6 +47,7 @@ export function createDirectoryAgentsInjectorHook(
|
||||
ctx,
|
||||
truncator,
|
||||
sessionCaches,
|
||||
agentsMdCache,
|
||||
filePath: output.title,
|
||||
sessionID: input.sessionID,
|
||||
output,
|
||||
@@ -54,21 +57,21 @@ export function createDirectoryAgentsInjectorHook(
|
||||
};
|
||||
|
||||
const eventHandler = async ({ event }: EventInput) => {
|
||||
const props = event.properties as Record<string, unknown> | undefined;
|
||||
|
||||
if (event.type === "session.deleted") {
|
||||
const sessionID = resolveSessionEventID(props);
|
||||
const sessionID = resolveSessionEventID(event.properties);
|
||||
if (sessionID) {
|
||||
sessionCaches.delete(sessionID);
|
||||
clearInjectedPaths(sessionID);
|
||||
agentsMdCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (event.type === "session.compacted") {
|
||||
const sessionID = resolveSessionEventID(props);
|
||||
const sessionID = resolveSessionEventID(event.properties);
|
||||
if (sessionID) {
|
||||
sessionCaches.delete(sessionID);
|
||||
clearInjectedPaths(sessionID);
|
||||
agentsMdCache.clear();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { PluginInput } from "@opencode-ai/plugin";
|
||||
import type { AgentsMdCache } from "@oh-my-opencode/rules-core";
|
||||
import { promises as fsPromises } from "node:fs";
|
||||
import { dirname } from "node:path";
|
||||
|
||||
@@ -15,13 +16,18 @@ function getSessionCache(
|
||||
if (!sessionCaches.has(sessionID)) {
|
||||
sessionCaches.set(sessionID, loadInjectedPaths(sessionID));
|
||||
}
|
||||
return sessionCaches.get(sessionID)!;
|
||||
const cache = sessionCaches.get(sessionID);
|
||||
if (cache) return cache;
|
||||
const loaded = loadInjectedPaths(sessionID);
|
||||
sessionCaches.set(sessionID, loaded);
|
||||
return loaded;
|
||||
}
|
||||
|
||||
export async function processFilePathForAgentsInjection(input: {
|
||||
ctx: PluginInput;
|
||||
truncator: DynamicTruncator;
|
||||
sessionCaches: Map<string, Set<string>>;
|
||||
agentsMdCache?: AgentsMdCache;
|
||||
filePath: string;
|
||||
sessionID: string;
|
||||
output: { title: string; output: string; metadata: unknown };
|
||||
@@ -35,26 +41,29 @@ export async function processFilePathForAgentsInjection(input: {
|
||||
|
||||
const dir = dirname(resolved);
|
||||
const cache = getSessionCache(input.sessionCaches, input.sessionID);
|
||||
const agentsPaths = await findAgentsMdUp({ startDir: dir, rootDir: input.ctx.directory });
|
||||
const agentsPaths = await findAgentsMdUp({
|
||||
startDir: dir,
|
||||
rootDir: input.ctx.directory,
|
||||
cache: input.agentsMdCache,
|
||||
});
|
||||
|
||||
let dirty = false;
|
||||
for (const agentsPath of agentsPaths) {
|
||||
const agentsDir = dirname(agentsPath);
|
||||
if (cache.has(agentsDir)) continue;
|
||||
|
||||
try {
|
||||
const content = await fsPromises.readFile(agentsPath, "utf-8");
|
||||
cache.add(agentsDir);
|
||||
const { result, truncated } = await input.truncator.truncate(
|
||||
input.sessionID,
|
||||
content,
|
||||
);
|
||||
const truncationNotice = truncated
|
||||
? `\n\n[Note: Content was truncated to save context window space. For full context, please read the file directly: ${agentsPath}]`
|
||||
: "";
|
||||
input.output.output += `\n\n[Directory Context: ${agentsPath}]\n${result}${truncationNotice}`;
|
||||
dirty = true;
|
||||
} catch {}
|
||||
const content = await fsPromises.readFile(agentsPath, "utf-8").catch(() => null);
|
||||
if (content === null) continue;
|
||||
cache.add(agentsDir);
|
||||
const { result, truncated } = await input.truncator.truncate(
|
||||
input.sessionID,
|
||||
content,
|
||||
);
|
||||
const truncationNotice = truncated
|
||||
? `\n\n[Note: Content was truncated to save context window space. For full context, please read the file directly: ${agentsPath}]`
|
||||
: "";
|
||||
input.output.output += `\n\n[Directory Context: ${agentsPath}]\n${result}${truncationNotice}`;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
if (dirty) {
|
||||
|
||||
Reference in New Issue
Block a user