|
|
|
|
@@ -6,7 +6,7 @@ import { execFileSync } from "node:child_process";
|
|
|
|
|
|
|
|
|
|
const modeArg = process.argv[2];
|
|
|
|
|
if (modeArg !== "--install" && modeArg !== "--uninstall") {
|
|
|
|
|
console.error("Usage: install-whispergate-openclaw.mjs --install | --uninstall");
|
|
|
|
|
console.error("Usage: install-dirigent-openclaw.mjs --install | --uninstall");
|
|
|
|
|
process.exit(2);
|
|
|
|
|
}
|
|
|
|
|
const mode = modeArg === "--install" ? "install" : "uninstall";
|
|
|
|
|
@@ -14,7 +14,7 @@ const mode = modeArg === "--install" ? "install" : "uninstall";
|
|
|
|
|
const env = process.env;
|
|
|
|
|
const OPENCLAW_CONFIG_PATH = env.OPENCLAW_CONFIG_PATH || path.join(os.homedir(), ".openclaw", "openclaw.json");
|
|
|
|
|
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
|
|
|
|
const PLUGIN_PATH = env.PLUGIN_PATH || path.resolve(__dirname, "..", "dist", "whispergate");
|
|
|
|
|
const PLUGIN_PATH = env.PLUGIN_PATH || path.resolve(__dirname, "..", "dist", "dirigent");
|
|
|
|
|
const NO_REPLY_PROVIDER_ID = env.NO_REPLY_PROVIDER_ID || "whisper-gateway";
|
|
|
|
|
const NO_REPLY_MODEL_ID = env.NO_REPLY_MODEL_ID || "no-reply";
|
|
|
|
|
const NO_REPLY_BASE_URL = env.NO_REPLY_BASE_URL || "http://127.0.0.1:8787/v1";
|
|
|
|
|
@@ -22,19 +22,19 @@ const NO_REPLY_API_KEY = env.NO_REPLY_API_KEY || "wg-local-test-token";
|
|
|
|
|
const LIST_MODE = env.LIST_MODE || "human-list";
|
|
|
|
|
const HUMAN_LIST_JSON = env.HUMAN_LIST_JSON || '["561921120408698910","1474088632750047324"]';
|
|
|
|
|
const AGENT_LIST_JSON = env.AGENT_LIST_JSON || "[]";
|
|
|
|
|
const CHANNEL_POLICIES_FILE = (env.CHANNEL_POLICIES_FILE || "~/.openclaw/whispergate-channel-policies.json").replace(/^~(?=$|\/)/, os.homedir());
|
|
|
|
|
const CHANNEL_POLICIES_FILE = (env.CHANNEL_POLICIES_FILE || "~/.openclaw/dirigent-channel-policies.json").replace(/^~(?=$|\/)/, os.homedir());
|
|
|
|
|
const CHANNEL_POLICIES_JSON = env.CHANNEL_POLICIES_JSON || "{}";
|
|
|
|
|
const END_SYMBOLS_JSON = env.END_SYMBOLS_JSON || '["🔚"]';
|
|
|
|
|
|
|
|
|
|
const STATE_DIR = (env.STATE_DIR || "~/.openclaw/whispergate-install-records").replace(/^~(?=$|\/)/, os.homedir());
|
|
|
|
|
const LATEST_RECORD_LINK = (env.LATEST_RECORD_LINK || "~/.openclaw/whispergate-install-record-latest.json").replace(/^~(?=$|\/)/, os.homedir());
|
|
|
|
|
const STATE_DIR = (env.STATE_DIR || "~/.openclaw/dirigent-install-records").replace(/^~(?=$|\/)/, os.homedir());
|
|
|
|
|
const LATEST_RECORD_LINK = (env.LATEST_RECORD_LINK || "~/.openclaw/dirigent-install-record-latest.json").replace(/^~(?=$|\/)/, os.homedir());
|
|
|
|
|
|
|
|
|
|
const ts = new Date().toISOString().replace(/[-:TZ.]/g, "").slice(0, 14);
|
|
|
|
|
const BACKUP_PATH = `${OPENCLAW_CONFIG_PATH}.bak-whispergate-${mode}-${ts}`;
|
|
|
|
|
const RECORD_PATH = path.join(STATE_DIR, `whispergate-${ts}.json`);
|
|
|
|
|
const BACKUP_PATH = `${OPENCLAW_CONFIG_PATH}.bak-dirigent-${mode}-${ts}`;
|
|
|
|
|
const RECORD_PATH = path.join(STATE_DIR, `dirigent-${ts}.json`);
|
|
|
|
|
|
|
|
|
|
const PATH_PLUGINS_LOAD = "plugins.load.paths";
|
|
|
|
|
const PATH_PLUGIN_ENTRY = "plugins.entries.whispergate";
|
|
|
|
|
const PATH_PLUGIN_ENTRY = "plugins.entries.dirigent";
|
|
|
|
|
const PATH_PROVIDERS = "models.providers";
|
|
|
|
|
|
|
|
|
|
function runOpenclaw(args, { allowFail = false } = {}) {
|
|
|
|
|
@@ -83,7 +83,7 @@ function findLatestInstallRecord() {
|
|
|
|
|
if (!fs.existsSync(STATE_DIR)) return "";
|
|
|
|
|
const files = fs
|
|
|
|
|
.readdirSync(STATE_DIR)
|
|
|
|
|
.filter((f) => /^whispergate-\d+\.json$/.test(f))
|
|
|
|
|
.filter((f) => /^dirigent-\d+\.json$/.test(f))
|
|
|
|
|
.sort()
|
|
|
|
|
.reverse();
|
|
|
|
|
for (const f of files) {
|
|
|
|
|
@@ -99,18 +99,18 @@ function findLatestInstallRecord() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!fs.existsSync(OPENCLAW_CONFIG_PATH)) {
|
|
|
|
|
console.error(`[whispergate] config not found: ${OPENCLAW_CONFIG_PATH}`);
|
|
|
|
|
console.error(`[dirigent] config not found: ${OPENCLAW_CONFIG_PATH}`);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mode === "install") {
|
|
|
|
|
fs.copyFileSync(OPENCLAW_CONFIG_PATH, BACKUP_PATH);
|
|
|
|
|
console.log(`[whispergate] backup: ${BACKUP_PATH}`);
|
|
|
|
|
console.log(`[dirigent] backup: ${BACKUP_PATH}`);
|
|
|
|
|
|
|
|
|
|
if (!fs.existsSync(CHANNEL_POLICIES_FILE)) {
|
|
|
|
|
fs.mkdirSync(path.dirname(CHANNEL_POLICIES_FILE), { recursive: true });
|
|
|
|
|
fs.writeFileSync(CHANNEL_POLICIES_FILE, `${CHANNEL_POLICIES_JSON}\n`);
|
|
|
|
|
console.log(`[whispergate] initialized channel policies file: ${CHANNEL_POLICIES_FILE}`);
|
|
|
|
|
console.log(`[dirigent] initialized channel policies file: ${CHANNEL_POLICIES_FILE}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const before = {
|
|
|
|
|
@@ -127,7 +127,7 @@ if (mode === "install") {
|
|
|
|
|
if (!paths.includes(PLUGIN_PATH)) paths.push(PLUGIN_PATH);
|
|
|
|
|
plugins.load.paths = paths;
|
|
|
|
|
plugins.entries = plugins.entries && typeof plugins.entries === "object" ? plugins.entries : {};
|
|
|
|
|
plugins.entries.whispergate = {
|
|
|
|
|
plugins.entries.dirigent = {
|
|
|
|
|
enabled: true,
|
|
|
|
|
config: {
|
|
|
|
|
enabled: true,
|
|
|
|
|
@@ -169,23 +169,23 @@ if (mode === "install") {
|
|
|
|
|
[PATH_PROVIDERS]: getJson(PATH_PROVIDERS),
|
|
|
|
|
};
|
|
|
|
|
writeRecord("install", before, after);
|
|
|
|
|
console.log("[whispergate] install ok (config written)");
|
|
|
|
|
console.log(`[whispergate] record: ${RECORD_PATH}`);
|
|
|
|
|
console.log("[whispergate] >>> restart gateway to apply: openclaw gateway restart");
|
|
|
|
|
console.log("[dirigent] install ok (config written)");
|
|
|
|
|
console.log(`[dirigent] record: ${RECORD_PATH}`);
|
|
|
|
|
console.log("[dirigent] >>> restart gateway to apply: openclaw gateway restart");
|
|
|
|
|
} catch (e) {
|
|
|
|
|
fs.copyFileSync(BACKUP_PATH, OPENCLAW_CONFIG_PATH);
|
|
|
|
|
console.error(`[whispergate] install failed; rollback complete: ${String(e)}`);
|
|
|
|
|
console.error(`[dirigent] install failed; rollback complete: ${String(e)}`);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
const recFile = env.RECORD_FILE || findLatestInstallRecord();
|
|
|
|
|
if (!recFile || !fs.existsSync(recFile)) {
|
|
|
|
|
console.error("[whispergate] no install record found. set RECORD_FILE=<path> to an install record.");
|
|
|
|
|
console.error("[dirigent] no install record found. set RECORD_FILE=<path> to an install record.");
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fs.copyFileSync(OPENCLAW_CONFIG_PATH, BACKUP_PATH);
|
|
|
|
|
console.log(`[whispergate] backup before uninstall: ${BACKUP_PATH}`);
|
|
|
|
|
console.log(`[dirigent] backup before uninstall: ${BACKUP_PATH}`);
|
|
|
|
|
|
|
|
|
|
const rec = readRecord(recFile);
|
|
|
|
|
const before = rec.applied || {};
|
|
|
|
|
@@ -200,8 +200,8 @@ if (mode === "install") {
|
|
|
|
|
if (target[PATH_PLUGINS_LOAD]?.exists) plugins.load.paths = target[PATH_PLUGINS_LOAD].value;
|
|
|
|
|
else delete plugins.load.paths;
|
|
|
|
|
|
|
|
|
|
if (target[PATH_PLUGIN_ENTRY]?.exists) plugins.entries.whispergate = target[PATH_PLUGIN_ENTRY].value;
|
|
|
|
|
else delete plugins.entries.whispergate;
|
|
|
|
|
if (target[PATH_PLUGIN_ENTRY]?.exists) plugins.entries.dirigent = target[PATH_PLUGIN_ENTRY].value;
|
|
|
|
|
else delete plugins.entries.dirigent;
|
|
|
|
|
|
|
|
|
|
setJson("plugins", plugins);
|
|
|
|
|
|
|
|
|
|
@@ -214,11 +214,11 @@ if (mode === "install") {
|
|
|
|
|
[PATH_PROVIDERS]: getJson(PATH_PROVIDERS),
|
|
|
|
|
};
|
|
|
|
|
writeRecord("uninstall", before, after);
|
|
|
|
|
console.log("[whispergate] uninstall ok");
|
|
|
|
|
console.log(`[whispergate] record: ${RECORD_PATH}`);
|
|
|
|
|
console.log("[dirigent] uninstall ok");
|
|
|
|
|
console.log(`[dirigent] record: ${RECORD_PATH}`);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
fs.copyFileSync(BACKUP_PATH, OPENCLAW_CONFIG_PATH);
|
|
|
|
|
console.error(`[whispergate] uninstall failed; rollback complete: ${String(e)}`);
|
|
|
|
|
console.error(`[dirigent] uninstall failed; rollback complete: ${String(e)}`);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
}
|
|
|
|
|
}
|