import path from "node:path"; import { loadRouters } from "./core/router-loader.js"; import { initRuleStore } from "./core/rule-store.js"; import { registerBeforePromptBuild } from "./hooks/before-prompt-build.js"; import { registerPromptRulesTool } from "./tools/prompt-rules.js"; interface PluginConfig { routersDir?: string; rulesFile?: string; } interface OpenClawPluginApi { logger: { info(msg: string): void; warn(msg: string): void; error(msg: string): void; }; on(hook: string, handler: (...args: any[]) => any): void; registerTool(def: any): void; config?: PluginConfig; } const _G = globalThis as Record; const LIFECYCLE_KEY = "_prismFacetGatewayLifecycleRegistered"; function normalizeConfig(api: OpenClawPluginApi): PluginConfig { const raw = (api as any).config ?? {}; return { routersDir: typeof raw.routersDir === "string" ? raw.routersDir : undefined, rulesFile: typeof raw.rulesFile === "string" ? raw.rulesFile : undefined, }; } export default { id: "prism-facet", name: "PrismFacet", register(api: OpenClawPluginApi) { const config = normalizeConfig(api); const pluginDir = path.dirname(new URL(import.meta.url).pathname); const routersDir = config.routersDir || path.resolve(pluginDir, "..", "routers"); const rulesFile = config.rulesFile || path.resolve(pluginDir, "..", "rules.json"); // Gateway lifecycle: init once if (!_G[LIFECYCLE_KEY]) { _G[LIFECYCLE_KEY] = true; initRuleStore(rulesFile); loadRouters(routersDir, api.logger).catch((err) => { api.logger.error(`[prism-facet] failed to load routers: ${String(err)}`); }); api.on("gateway_stop", () => { _G[LIFECYCLE_KEY] = false; }); } // Agent session hooks: register every time (dedup inside handler) registerBeforePromptBuild(api); // Tools registerPromptRulesTool(api, routersDir); api.logger.info("[prism-facet] plugin registered"); }, };