refactor: restructure PrismFacet per OpenClaw plugin spec
- plugin/ directory structure: hooks/, tools/, core/
- export default { id, name, register } entry format
- globalThis state management with lifecycle protection
- WeakSet dedup on before_prompt_build hook
- Tool uses inputSchema + execute (not parameters + handler)
- additionalProperties: false in config schema
- Core logic in plugin/core/ (no plugin-sdk dependency)
- Install/uninstall script (scripts/install.mjs)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
66
plugin/index.ts
Normal file
66
plugin/index.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
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<string, unknown>;
|
||||
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");
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user