- Plugin scaffold: manifest, tsconfig, package.json - Router loader with dynamic import + cache busting for hot reload - Rule store: CRUD on rules.json - Prompt injector: resolve routers → match rules → read files → inject - MCP tool: prompt_rules (add/remove/list/test/reload-routers/list-routers) - Built-in routers: agent-id (zero-dep), role, position (ego.json) - before_prompt_build hook for system prompt injection Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
119 lines
3.5 KiB
TypeScript
119 lines
3.5 KiB
TypeScript
import { addRule, removeRule, listRules } from "./rule-store.js";
|
|
import { loadRouters, getRouterNames } from "./router-loader.js";
|
|
import { resolveInjection } from "./prompt-injector.js";
|
|
import type { PluginApi } from "./types.js";
|
|
|
|
export function registerTools(
|
|
api: PluginApi,
|
|
routersDir: string
|
|
): void {
|
|
api.registerTool({
|
|
name: "prompt_rules",
|
|
description:
|
|
"Manage PrismFacet prompt injection rules. " +
|
|
"Actions: add (register a rule), remove (delete a rule), list (show all rules), " +
|
|
"test (preview which prompts would be injected for an agent), " +
|
|
"reload-routers (hot-reload all router functions), list-routers (show loaded routers).",
|
|
parameters: {
|
|
type: "object",
|
|
properties: {
|
|
action: {
|
|
type: "string",
|
|
enum: [
|
|
"add",
|
|
"remove",
|
|
"list",
|
|
"test",
|
|
"reload-routers",
|
|
"list-routers",
|
|
],
|
|
description: "The action to perform",
|
|
},
|
|
router: {
|
|
type: "string",
|
|
description: "Router name (for add/remove)",
|
|
},
|
|
key: {
|
|
type: "string",
|
|
description: "Rule key (for add/remove)",
|
|
},
|
|
file: {
|
|
type: "string",
|
|
description: "Prompt file path (for add)",
|
|
},
|
|
agent: {
|
|
type: "string",
|
|
description: "Agent ID (for test)",
|
|
},
|
|
},
|
|
required: ["action"],
|
|
},
|
|
handler: async (params: {
|
|
action: string;
|
|
router?: string;
|
|
key?: string;
|
|
file?: string;
|
|
agent?: string;
|
|
}) => {
|
|
switch (params.action) {
|
|
case "add": {
|
|
if (!params.router || !params.key || !params.file) {
|
|
return "Error: add requires --router, --key, and --file";
|
|
}
|
|
addRule(params.router, params.key, params.file);
|
|
return `Rule added: ${params.router}:${params.key} → ${params.file}`;
|
|
}
|
|
|
|
case "remove": {
|
|
if (!params.router || !params.key) {
|
|
return "Error: remove requires --router and --key";
|
|
}
|
|
const removed = removeRule(params.router, params.key);
|
|
return removed
|
|
? `Rule removed: ${params.router}:${params.key}`
|
|
: `Rule not found: ${params.router}:${params.key}`;
|
|
}
|
|
|
|
case "list": {
|
|
const rules = listRules();
|
|
const entries = Object.entries(rules);
|
|
if (entries.length === 0) return "No rules registered.";
|
|
return entries
|
|
.map(([k, v]) => `${k} → ${v}`)
|
|
.join("\n");
|
|
}
|
|
|
|
case "test": {
|
|
if (!params.agent) {
|
|
return "Error: test requires --agent";
|
|
}
|
|
const result = await resolveInjection(
|
|
{ agentId: params.agent },
|
|
api.logger
|
|
);
|
|
if (!result.appendSystemContext) {
|
|
return `No prompts matched for agent: ${params.agent}`;
|
|
}
|
|
return `Matched prompts for ${params.agent}:\n\n${result.appendSystemContext}`;
|
|
}
|
|
|
|
case "reload-routers": {
|
|
await loadRouters(routersDir, api.logger);
|
|
const names = getRouterNames();
|
|
return `Routers reloaded: ${names.join(", ") || "(none)"}`;
|
|
}
|
|
|
|
case "list-routers": {
|
|
const names = getRouterNames();
|
|
return names.length > 0
|
|
? `Loaded routers: ${names.join(", ")}`
|
|
: "No routers loaded.";
|
|
}
|
|
|
|
default:
|
|
return `Unknown action: ${params.action}`;
|
|
}
|
|
},
|
|
});
|
|
}
|