Compare commits
7 Commits
b9515fe765
...
e6ddbc8186
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6ddbc8186 | ||
|
|
9af20b07c7 | ||
| 3d91d7ed95 | |||
| 92799176bf | |||
| cd0ce6a910 | |||
| a177150554 | |||
| b79cc1eb84 |
@@ -10,17 +10,23 @@ import { startModeratorPresence, stopModeratorPresence } from "./moderator-prese
|
|||||||
let noReplyProcess: ChildProcess | null = null;
|
let noReplyProcess: ChildProcess | null = null;
|
||||||
|
|
||||||
function startNoReplyApi(logger: { info: (m: string) => void; warn: (m: string) => void }, pluginDir: string, port = 8787): void {
|
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) {
|
if (noReplyProcess) {
|
||||||
logger.info("dirigent: no-reply API already running, skipping");
|
logger.info("dirigent: no-reply API already running, skipping");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const serverPath = path.resolve(pluginDir, "..", "no-reply-api", "server.mjs");
|
const serverPath = path.resolve(pluginDir, "..", "no-reply-api", "server.mjs");
|
||||||
|
logger.info(`dirigent: resolved serverPath=${serverPath}`);
|
||||||
|
|
||||||
if (!fs.existsSync(serverPath)) {
|
if (!fs.existsSync(serverPath)) {
|
||||||
logger.warn(`dirigent: no-reply API server not found at ${serverPath}, skipping`);
|
logger.warn(`dirigent: no-reply API server not found at ${serverPath}, skipping`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.info(`dirigent: no-reply API server found, spawning process...`);
|
||||||
|
|
||||||
noReplyProcess = spawn(process.execPath, [serverPath], {
|
noReplyProcess = spawn(process.execPath, [serverPath], {
|
||||||
env: { ...process.env, PORT: String(port) },
|
env: { ...process.env, PORT: String(port) },
|
||||||
stdio: ["ignore", "pipe", "pipe"],
|
stdio: ["ignore", "pipe", "pipe"],
|
||||||
@@ -508,16 +514,28 @@ export default {
|
|||||||
ensurePolicyStateLoaded(api, liveAtRegister);
|
ensurePolicyStateLoaded(api, liveAtRegister);
|
||||||
|
|
||||||
// Resolve plugin directory for locating sibling modules (no-reply-api/)
|
// Resolve plugin directory for locating sibling modules (no-reply-api/)
|
||||||
const pluginDir = path.dirname(new URL(import.meta.url).pathname);
|
// Use api.resolvePath to get the actual plugin directory in OpenClaw environment
|
||||||
|
const pluginDir = api.resolvePath(".");
|
||||||
|
|
||||||
// Gateway lifecycle: start/stop no-reply API and moderator bot with the gateway
|
// Gateway lifecycle: start/stop no-reply API and moderator bot with the gateway
|
||||||
api.on("gateway_start", () => {
|
api.on("gateway_start", () => {
|
||||||
|
api.logger.info(`dirigent: gateway_start event received, pluginDir=${pluginDir}`);
|
||||||
|
|
||||||
|
// Check no-reply-api server file exists
|
||||||
|
const serverPath = path.resolve(pluginDir, "..", "no-reply-api", "server.mjs");
|
||||||
|
api.logger.info(`dirigent: checking no-reply-api server at ${serverPath}, exists=${fs.existsSync(serverPath)}`);
|
||||||
|
|
||||||
startNoReplyApi(api.logger, pluginDir);
|
startNoReplyApi(api.logger, pluginDir);
|
||||||
|
|
||||||
const live = getLivePluginConfig(api, baseConfig as DirigentConfig);
|
const live = getLivePluginConfig(api, baseConfig as DirigentConfig);
|
||||||
|
api.logger.info(`dirigent: config loaded, moderatorBotToken=${live.moderatorBotToken ? "[set]" : "[not set]"}`);
|
||||||
|
|
||||||
if (live.moderatorBotToken) {
|
if (live.moderatorBotToken) {
|
||||||
|
api.logger.info("dirigent: starting moderator bot presence...");
|
||||||
startModeratorPresence(live.moderatorBotToken, api.logger);
|
startModeratorPresence(live.moderatorBotToken, api.logger);
|
||||||
api.logger.info("dirigent: moderator bot presence starting");
|
api.logger.info("dirigent: moderator bot presence started");
|
||||||
|
} else {
|
||||||
|
api.logger.info("dirigent: moderator bot not starting - no moderatorBotToken in config");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -22,12 +22,27 @@ const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|||||||
// Ensure dist/dirigent exists (handles git clone without npm prepare)
|
// Ensure dist/dirigent exists (handles git clone without npm prepare)
|
||||||
const DIST_DIR = path.resolve(__dirname, "..", "dist", "dirigent");
|
const DIST_DIR = path.resolve(__dirname, "..", "dist", "dirigent");
|
||||||
const PLUGIN_SRC_DIR = path.resolve(__dirname, "..", "plugin");
|
const PLUGIN_SRC_DIR = path.resolve(__dirname, "..", "plugin");
|
||||||
if (mode === "install" && !fs.existsSync(DIST_DIR)) {
|
const NO_REPLY_API_SRC_DIR = path.resolve(__dirname, "..", "no-reply-api");
|
||||||
console.log("[dirigent] dist/ not found, syncing from plugin/...");
|
const NO_REPLY_API_DIST_DIR = path.resolve(__dirname, "..", "dist", "no-reply-api");
|
||||||
|
|
||||||
|
if (mode === "install") {
|
||||||
|
// Copy plugin files to dist/dirigent
|
||||||
|
if (!fs.existsSync(DIST_DIR)) {
|
||||||
|
console.log("[dirigent] dist/dirigent/ not found, syncing from plugin/...");
|
||||||
fs.mkdirSync(DIST_DIR, { recursive: true });
|
fs.mkdirSync(DIST_DIR, { recursive: true });
|
||||||
for (const f of fs.readdirSync(PLUGIN_SRC_DIR)) {
|
for (const f of fs.readdirSync(PLUGIN_SRC_DIR)) {
|
||||||
fs.copyFileSync(path.join(PLUGIN_SRC_DIR, f), path.join(DIST_DIR, f));
|
fs.copyFileSync(path.join(PLUGIN_SRC_DIR, f), path.join(DIST_DIR, f));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy no-reply-api files to dist/no-reply-api
|
||||||
|
if (!fs.existsSync(NO_REPLY_API_DIST_DIR)) {
|
||||||
|
console.log("[dirigent] dist/no-reply-api/ not found, syncing from no-reply-api/...");
|
||||||
|
fs.mkdirSync(NO_REPLY_API_DIST_DIR, { recursive: true });
|
||||||
|
for (const f of fs.readdirSync(NO_REPLY_API_SRC_DIR)) {
|
||||||
|
fs.copyFileSync(path.join(NO_REPLY_API_SRC_DIR, f), path.join(NO_REPLY_API_DIST_DIR, f));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const PLUGIN_PATH = env.PLUGIN_PATH || DIST_DIR;
|
const PLUGIN_PATH = env.PLUGIN_PATH || DIST_DIR;
|
||||||
@@ -279,22 +294,25 @@ else {
|
|||||||
const delta = rec.delta || { added: {}, replaced: {}, removed: {} };
|
const delta = rec.delta || { added: {}, replaced: {}, removed: {} };
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// ── Handle ADDED entries: remove them ─────────────────────────────────
|
// ── IMPORTANT: Order matters for OpenClaw config validation ────────────
|
||||||
if (delta.added[PATH_PLUGIN_ENTRY] !== undefined) {
|
// 1. First remove from allow (before deleting entry, otherwise validation fails)
|
||||||
const plugins = getJson("plugins") || {};
|
if (delta.added[PATH_PLUGINS_ALLOW] !== undefined) {
|
||||||
plugins.entries = plugins.entries || {};
|
const allowList = getJson(PATH_PLUGINS_ALLOW) || [];
|
||||||
delete plugins.entries.dirigent;
|
const idx = allowList.indexOf("dirigent");
|
||||||
setJson("plugins", plugins);
|
if (idx !== -1) {
|
||||||
|
allowList.splice(idx, 1);
|
||||||
|
setJson(PATH_PLUGINS_ALLOW, allowList);
|
||||||
|
console.log("[dirigent] removed 'dirigent' from plugins.allow");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Then remove entry
|
||||||
|
if (delta.added[PATH_PLUGIN_ENTRY] !== undefined || delta.replaced[PATH_PLUGIN_ENTRY] !== undefined) {
|
||||||
|
unsetPath(PATH_PLUGIN_ENTRY);
|
||||||
console.log("[dirigent] removed plugins.entries.dirigent");
|
console.log("[dirigent] removed plugins.entries.dirigent");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delta.added[PATH_PROVIDER_ENTRY] !== undefined) {
|
// 3. Then remove plugin path (after entry is gone)
|
||||||
const providers = getJson(PATH_PROVIDERS) || {};
|
|
||||||
delete providers[NO_REPLY_PROVIDER_ID];
|
|
||||||
setJson(PATH_PROVIDERS, providers);
|
|
||||||
console.log(`[dirigent] removed models.providers.${NO_REPLY_PROVIDER_ID}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (delta.added[PATH_PLUGINS_LOAD] !== undefined) {
|
if (delta.added[PATH_PLUGINS_LOAD] !== undefined) {
|
||||||
const plugins = getJson("plugins") || {};
|
const plugins = getJson("plugins") || {};
|
||||||
const paths = plugins.load?.paths || [];
|
const paths = plugins.load?.paths || [];
|
||||||
@@ -307,26 +325,15 @@ else {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Handle plugins.allow ──────────────────────────────────────────────
|
// 4. Finally remove provider
|
||||||
if (delta.added[PATH_PLUGINS_ALLOW] !== undefined) {
|
if (delta.added[PATH_PROVIDER_ENTRY] !== undefined) {
|
||||||
const allowList = getJson(PATH_PLUGINS_ALLOW) || [];
|
const providers = getJson(PATH_PROVIDERS) || {};
|
||||||
const idx = allowList.indexOf("dirigent");
|
delete providers[NO_REPLY_PROVIDER_ID];
|
||||||
if (idx !== -1) {
|
setJson(PATH_PROVIDERS, providers);
|
||||||
allowList.splice(idx, 1);
|
console.log(`[dirigent] removed models.providers.${NO_REPLY_PROVIDER_ID}`);
|
||||||
setJson(PATH_PLUGINS_ALLOW, allowList);
|
|
||||||
console.log("[dirigent] removed 'dirigent' from plugins.allow");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Handle REPLACED entries: restore old value ────────────────────────
|
|
||||||
if (delta.replaced[PATH_PLUGIN_ENTRY] !== undefined) {
|
|
||||||
const plugins = getJson("plugins") || {};
|
|
||||||
plugins.entries = plugins.entries || {};
|
|
||||||
plugins.entries.dirigent = delta.replaced[PATH_PLUGIN_ENTRY];
|
|
||||||
setJson("plugins", plugins);
|
|
||||||
console.log("[dirigent] restored previous plugins.entries.dirigent");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Handle REPLACED provider: restore old value ───────────────────────
|
||||||
if (delta.replaced[PATH_PROVIDER_ENTRY] !== undefined) {
|
if (delta.replaced[PATH_PROVIDER_ENTRY] !== undefined) {
|
||||||
const providers = getJson(PATH_PROVIDERS) || {};
|
const providers = getJson(PATH_PROVIDERS) || {};
|
||||||
providers[NO_REPLY_PROVIDER_ID] = delta.replaced[PATH_PROVIDER_ENTRY];
|
providers[NO_REPLY_PROVIDER_ID] = delta.replaced[PATH_PROVIDER_ENTRY];
|
||||||
|
|||||||
Reference in New Issue
Block a user