refactor(plugin): extract no-reply child process lifecycle module

This commit is contained in:
2026-03-08 05:39:27 +00:00
parent 0c06aeb36c
commit ea501ccef8
2 changed files with 52 additions and 46 deletions

View File

@@ -1,6 +1,5 @@
import fs from "node:fs";
import path from "node:path";
import { spawn, type ChildProcess } from "node:child_process";
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
import type { Decision, DirigentConfig } from "./rules.js";
import { startModeratorPresence, stopModeratorPresence } from "./moderator-presence.js";
@@ -18,51 +17,7 @@ import { extractMentionedUserIds, getModeratorUserId } from "./core/mentions.js"
import { ensureTurnOrder, recordChannelAccount } from "./core/turn-bootstrap.js";
import { debugCtxSummary, pickDefined, shouldDebugLog } from "./core/utils.js";
import { resolveDiscordUserId, sendModeratorMessage } from "./core/moderator-discord.js";
// ── No-Reply API child process lifecycle ──────────────────────────────
let noReplyProcess: ChildProcess | null = null;
function startNoReplyApi(logger: { info: (m: string) => void; warn: (m: string) => void }, pluginDir: string, port = 8787): void {
logger.info(`dirigent: startNoReplyApi called, pluginDir=${pluginDir}`);
if (noReplyProcess) {
logger.info("dirigent: no-reply API already running, skipping");
return;
}
const serverPath = path.resolve(pluginDir, "..", "no-reply-api", "server.mjs");
logger.info(`dirigent: resolved serverPath=${serverPath}`);
if (!fs.existsSync(serverPath)) {
logger.warn(`dirigent: no-reply API server not found at ${serverPath}, skipping`);
return;
}
logger.info(`dirigent: no-reply API server found, spawning process...`);
noReplyProcess = spawn(process.execPath, [serverPath], {
env: { ...process.env, PORT: String(port) },
stdio: ["ignore", "pipe", "pipe"],
detached: false,
});
noReplyProcess.stdout?.on("data", (d: Buffer) => logger.info(`dirigent: no-reply-api: ${d.toString().trim()}`));
noReplyProcess.stderr?.on("data", (d: Buffer) => logger.warn(`dirigent: no-reply-api: ${d.toString().trim()}`));
noReplyProcess.on("exit", (code, signal) => {
logger.info(`dirigent: no-reply API exited (code=${code}, signal=${signal})`);
noReplyProcess = null;
});
logger.info(`dirigent: no-reply API started (pid=${noReplyProcess.pid}, port=${port})`);
}
function stopNoReplyApi(logger: { info: (m: string) => void }): void {
if (!noReplyProcess) return;
logger.info("dirigent: stopping no-reply API");
noReplyProcess.kill("SIGTERM");
noReplyProcess = null;
}
import { startNoReplyApi, stopNoReplyApi } from "./core/no-reply-process.js";
type DecisionRecord = {
decision: Decision;