From 3a8b85eb7badb6f0829337c0c1ce8f1c80ec6575 Mon Sep 17 00:00:00 2001 From: orion Date: Sat, 7 Mar 2026 22:27:03 +0000 Subject: [PATCH] refactor(plugin): extract dirigent slash command and fix recursive prepare copy --- package.json | 2 +- plugin/commands/dirigent-command.ts | 59 +++++++++++++++++++++++++++++ plugin/index.ts | 49 +++--------------------- 3 files changed, 65 insertions(+), 45 deletions(-) create mode 100644 plugin/commands/dirigent-command.ts diff --git a/package.json b/package.json index 8ce1891..0965160 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "TASKLIST.md" ], "scripts": { - "prepare": "mkdir -p dist/dirigent && cp plugin/* dist/dirigent/", + "prepare": "mkdir -p dist/dirigent && cp -r plugin/* dist/dirigent/", "postinstall": "node scripts/install-dirigent-openclaw.mjs --install", "uninstall": "node scripts/install-dirigent-openclaw.mjs --uninstall", "update": "node scripts/install-dirigent-openclaw.mjs --update" diff --git a/plugin/commands/dirigent-command.ts b/plugin/commands/dirigent-command.ts new file mode 100644 index 0000000..3561253 --- /dev/null +++ b/plugin/commands/dirigent-command.ts @@ -0,0 +1,59 @@ +import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; +import { advanceTurn, getTurnDebugInfo, resetTurn } from "../turn-manager.js"; + +type CommandDeps = { + api: OpenClawPluginApi; + policyState: { channelPolicies: Record }; +}; + +export function registerDirigentCommand(deps: CommandDeps): void { + const { api, policyState } = deps; + + api.registerCommand({ + name: "dirigent", + description: "Dirigent channel policy management", + acceptsArgs: true, + handler: async (cmdCtx) => { + const args = cmdCtx.args || ""; + const parts = args.trim().split(/\s+/); + const subCmd = parts[0] || "help"; + + if (subCmd === "help") { + return { + text: + `Dirigent commands:\n` + + `/dirigent status - Show current channel status\n` + + `/dirigent turn-status - Show turn-based speaking status\n` + + `/dirigent turn-advance - Manually advance turn\n` + + `/dirigent turn-reset - Reset turn order`, + }; + } + + if (subCmd === "status") { + return { text: JSON.stringify({ policies: policyState.channelPolicies }, null, 2) }; + } + + if (subCmd === "turn-status") { + const channelId = cmdCtx.channelId; + if (!channelId) return { text: "Cannot get channel ID", isError: true }; + return { text: JSON.stringify(getTurnDebugInfo(channelId), null, 2) }; + } + + if (subCmd === "turn-advance") { + const channelId = cmdCtx.channelId; + if (!channelId) return { text: "Cannot get channel ID", isError: true }; + const next = advanceTurn(channelId); + return { text: JSON.stringify({ ok: true, nextSpeaker: next }) }; + } + + if (subCmd === "turn-reset") { + const channelId = cmdCtx.channelId; + if (!channelId) return { text: "Cannot get channel ID", isError: true }; + resetTurn(channelId); + return { text: JSON.stringify({ ok: true }) }; + } + + return { text: `Unknown subcommand: ${subCmd}`, isError: true }; + }, + }); +} diff --git a/plugin/index.ts b/plugin/index.ts index 060ff7d..bd5583e 100644 --- a/plugin/index.ts +++ b/plugin/index.ts @@ -3,13 +3,14 @@ import path from "node:path"; import { spawn, type ChildProcess } from "node:child_process"; import type { OpenClawPluginApi } from "openclaw/plugin-sdk"; import { evaluateDecision, resolvePolicy, type ChannelPolicy, type Decision, type DirigentConfig } from "./rules.js"; -import { advanceTurn, resetTurn, initTurnOrder, getTurnDebugInfo } from "./turn-manager.js"; +import { initTurnOrder } from "./turn-manager.js"; import { startModeratorPresence, stopModeratorPresence } from "./moderator-presence.js"; import { registerMessageReceivedHook } from "./hooks/message-received.js"; import { registerBeforeModelResolveHook } from "./hooks/before-model-resolve.js"; import { registerBeforePromptBuildHook } from "./hooks/before-prompt-build.js"; import { registerBeforeMessageWriteHook } from "./hooks/before-message-write.js"; import { registerMessageSentHook } from "./hooks/message-sent.js"; +import { registerDirigentCommand } from "./commands/dirigent-command.js"; // ── No-Reply API child process lifecycle ────────────────────────────── let noReplyProcess: ChildProcess | null = null; @@ -745,49 +746,9 @@ export default { }); // Register slash commands for Discord - api.registerCommand({ - name: "dirigent", - description: "Dirigent channel policy management", - acceptsArgs: true, - handler: async (cmdCtx) => { - const args = cmdCtx.args || ""; - const parts = args.trim().split(/\s+/); - const subCmd = parts[0] || "help"; - - if (subCmd === "help") { - return { text: `Dirigent commands:\n` + - `/dirigent status - Show current channel status\n` + - `/dirigent turn-status - Show turn-based speaking status\n` + - `/dirigent turn-advance - Manually advance turn\n` + - `/dirigent turn-reset - Reset turn order` }; - } - - if (subCmd === "status") { - return { text: JSON.stringify({ policies: policyState.channelPolicies }, null, 2) }; - } - - if (subCmd === "turn-status") { - const channelId = cmdCtx.channelId; - if (!channelId) return { text: "Cannot get channel ID", isError: true }; - return { text: JSON.stringify(getTurnDebugInfo(channelId), null, 2) }; - } - - if (subCmd === "turn-advance") { - const channelId = cmdCtx.channelId; - if (!channelId) return { text: "Cannot get channel ID", isError: true }; - const next = advanceTurn(channelId); - return { text: JSON.stringify({ ok: true, nextSpeaker: next }) }; - } - - if (subCmd === "turn-reset") { - const channelId = cmdCtx.channelId; - if (!channelId) return { text: "Cannot get channel ID", isError: true }; - resetTurn(channelId); - return { text: JSON.stringify({ ok: true }) }; - } - - return { text: `Unknown subcommand: ${subCmd}`, isError: true }; - }, + registerDirigentCommand({ + api, + policyState, }); // Handle NO_REPLY detection before message write