openclaw-manager 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/commands/reset.js +66 -0
- package/bin/commands/stop-all.js +2 -19
- package/bin/lib/args.js +4 -3
- package/bin/lib/banner.js +4 -9
- package/bin/lib/color.js +16 -0
- package/bin/lib/help.js +2 -2
- package/bin/lib/sandbox.js +29 -0
- package/bin/openclaw-manager.js +8 -0
- package/package.json +1 -1
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import { resolveConfigPaths } from "../lib/config.js";
|
|
5
|
+
import { stopAll } from "./stop-all.js";
|
|
6
|
+
import { listSandboxDirs, removeSandboxDir } from "../lib/sandbox.js";
|
|
7
|
+
export function resetManager(flags) {
|
|
8
|
+
const messages = [];
|
|
9
|
+
const errors = [];
|
|
10
|
+
const stopResult = stopAll(flags);
|
|
11
|
+
messages.push(...stopResult.messages);
|
|
12
|
+
if (!stopResult.ok && stopResult.error) {
|
|
13
|
+
messages.push(`warn: stop-all failed (${stopResult.error})`);
|
|
14
|
+
}
|
|
15
|
+
const configPath = resolveConfigPaths(flags);
|
|
16
|
+
if (isSafeConfigDir(configPath.configDir)) {
|
|
17
|
+
try {
|
|
18
|
+
if (fs.existsSync(configPath.configDir)) {
|
|
19
|
+
fs.rmSync(configPath.configDir, { recursive: true, force: true });
|
|
20
|
+
messages.push(`config: removed (${configPath.configDir})`);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
messages.push(`config: not found (${configPath.configDir})`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
errors.push(`config: failed to remove (${configPath.configDir}): ${String(err)}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
errors.push(`config: refuse remove unsafe path (${configPath.configDir})`);
|
|
32
|
+
}
|
|
33
|
+
const sandboxes = listSandboxDirs();
|
|
34
|
+
if (!sandboxes.length) {
|
|
35
|
+
messages.push("sandbox: none");
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
for (const dir of sandboxes) {
|
|
39
|
+
const result = removeSandboxDir(dir);
|
|
40
|
+
if (result.ok) {
|
|
41
|
+
messages.push(`sandbox: ${result.message}`);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
errors.push(`sandbox: ${result.error ?? "remove failed"}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (errors.length) {
|
|
49
|
+
return { ok: false, messages, error: errors.join("; ") };
|
|
50
|
+
}
|
|
51
|
+
return { ok: true, messages };
|
|
52
|
+
}
|
|
53
|
+
function isSafeConfigDir(target) {
|
|
54
|
+
const resolved = path.resolve(target);
|
|
55
|
+
const home = os.homedir();
|
|
56
|
+
if (!resolved.startsWith(home))
|
|
57
|
+
return false;
|
|
58
|
+
const base = path.basename(resolved);
|
|
59
|
+
if (base.includes("openclaw-manager") || base.includes("clawdbot-manager")) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
return (resolved.endsWith(".openclaw-manager") ||
|
|
63
|
+
resolved.endsWith(".clawdbot-manager") ||
|
|
64
|
+
resolved.includes(`${path.sep}.openclaw-manager${path.sep}`) ||
|
|
65
|
+
resolved.includes(`${path.sep}.clawdbot-manager${path.sep}`));
|
|
66
|
+
}
|
package/bin/commands/stop-all.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
-
import os from "node:os";
|
|
3
2
|
import path from "node:path";
|
|
4
3
|
import { listGatewayProcesses } from "../lib/system.js";
|
|
5
4
|
import { stopManager } from "./stop.js";
|
|
6
5
|
import { readPid } from "../lib/pids.js";
|
|
6
|
+
import { listSandboxDirs } from "../lib/sandbox.js";
|
|
7
7
|
export function stopAll(flags) {
|
|
8
8
|
const messages = [];
|
|
9
9
|
const errors = [];
|
|
@@ -11,7 +11,7 @@ export function stopAll(flags) {
|
|
|
11
11
|
messages.push(...managerResult.messages);
|
|
12
12
|
if (!managerResult.ok && managerResult.error)
|
|
13
13
|
errors.push(managerResult.error);
|
|
14
|
-
const sandboxes =
|
|
14
|
+
const sandboxes = listSandboxDirs();
|
|
15
15
|
if (!sandboxes.length) {
|
|
16
16
|
messages.push("sandbox: none");
|
|
17
17
|
}
|
|
@@ -46,23 +46,6 @@ export function stopAll(flags) {
|
|
|
46
46
|
}
|
|
47
47
|
return { ok: true, messages };
|
|
48
48
|
}
|
|
49
|
-
function listSandboxInstances() {
|
|
50
|
-
const dir = os.tmpdir();
|
|
51
|
-
let entries = [];
|
|
52
|
-
try {
|
|
53
|
-
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
54
|
-
}
|
|
55
|
-
catch {
|
|
56
|
-
return [];
|
|
57
|
-
}
|
|
58
|
-
return entries
|
|
59
|
-
.filter((entry) => {
|
|
60
|
-
return (entry.isDirectory() &&
|
|
61
|
-
(entry.name.startsWith("openclaw-manager-sandbox-") ||
|
|
62
|
-
entry.name.startsWith("clawdbot-manager-sandbox-")));
|
|
63
|
-
})
|
|
64
|
-
.map((entry) => path.join(dir, entry.name));
|
|
65
|
-
}
|
|
66
49
|
function stopSandboxDir(rootDir) {
|
|
67
50
|
const pidFile = path.join(rootDir, "manager-api.pid");
|
|
68
51
|
if (!fs.existsSync(pidFile)) {
|
package/bin/lib/args.js
CHANGED
|
@@ -19,6 +19,7 @@ const shortKeyMap = {
|
|
|
19
19
|
u: "user",
|
|
20
20
|
p: "pass"
|
|
21
21
|
};
|
|
22
|
+
const validKeys = new Set(Object.values(longKeyMap));
|
|
22
23
|
export function parseArgs(argv) {
|
|
23
24
|
const flags = {};
|
|
24
25
|
const positionals = [];
|
|
@@ -74,6 +75,8 @@ export function parseArgs(argv) {
|
|
|
74
75
|
return { command, flags };
|
|
75
76
|
}
|
|
76
77
|
function setFlag(flags, key, value) {
|
|
78
|
+
if (!validKeys.has(key))
|
|
79
|
+
return;
|
|
77
80
|
if (key === "apiPort") {
|
|
78
81
|
const num = Number(value);
|
|
79
82
|
if (Number.isFinite(num)) {
|
|
@@ -81,7 +84,5 @@ function setFlag(flags, key, value) {
|
|
|
81
84
|
return;
|
|
82
85
|
}
|
|
83
86
|
}
|
|
84
|
-
|
|
85
|
-
flags[key] = value;
|
|
86
|
-
}
|
|
87
|
+
flags[key] = value;
|
|
87
88
|
}
|
package/bin/lib/banner.js
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
+
import { cyan, dim } from "./color.js";
|
|
1
2
|
import { readPackageVersion } from "./version.js";
|
|
2
|
-
const BANNER_LINES = [
|
|
3
|
-
" ____ __ __ __ ___ ",
|
|
4
|
-
" / __ \\____ ___ ____/ /___ _/ /___ _____/ |/ /___ _____ ____ _____ _____ ",
|
|
5
|
-
" / / / / __ \\/ _ \\/ __ / __ `/ / __ \\___/ /|_/ / __ `/ __ \\/ __ `/ __ \\/ ___/ ",
|
|
6
|
-
"/ /_/ / /_/ / __/ /_/ / /_/ / / / / / /__/ / / / /_/ / / / / /_/ / /_/ / / ",
|
|
7
|
-
"\\____/ .___/\\___/\\__,_/\\__,_/_/_/ /_/\\___/_/ /_/\\__,_/_/ /_/\\__,_/\\____/_/ ",
|
|
8
|
-
" /_/ "
|
|
9
|
-
];
|
|
10
3
|
export function printBanner() {
|
|
11
4
|
const version = readPackageVersion();
|
|
12
|
-
|
|
5
|
+
const title = cyan("OpenClaw Manager");
|
|
6
|
+
const ver = dim(`v${version}`);
|
|
7
|
+
console.log(`${title} ${ver}`);
|
|
13
8
|
}
|
package/bin/lib/color.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function colorize(text, code) {
|
|
2
|
+
if (!shouldColor())
|
|
3
|
+
return text;
|
|
4
|
+
return `\u001b[${code}m${text}\u001b[0m`;
|
|
5
|
+
}
|
|
6
|
+
export function cyan(text) {
|
|
7
|
+
return colorize(text, 36);
|
|
8
|
+
}
|
|
9
|
+
export function dim(text) {
|
|
10
|
+
return colorize(text, 90);
|
|
11
|
+
}
|
|
12
|
+
function shouldColor() {
|
|
13
|
+
if (process.env.NO_COLOR)
|
|
14
|
+
return false;
|
|
15
|
+
return Boolean(process.stdout.isTTY);
|
|
16
|
+
}
|
package/bin/lib/help.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { printBanner } from "./banner.js";
|
|
2
2
|
export function printHelp() {
|
|
3
3
|
printBanner();
|
|
4
|
-
console.log(`\nUsage:\n openclaw-manager <command> [options]\n\nCommands:\n start Start OpenClaw Manager\n stop Stop the running Manager process\n stop-all Stop Manager, sandboxes, and gateway processes\n\nOptions:\n -h, --help Show help\n -v, --version Show version\n -u, --user <name> Admin username (start)\n -p, --pass <value> Admin password (start)\n --non-interactive Fail instead of prompting for credentials\n --api-port <port> API port (default: 17321)\n --api-host <host> API host (default: 0.0.0.0)\n --config-dir <dir> Config directory\n --config-path <path> Config file path\n`);
|
|
4
|
+
console.log(`\nUsage:\n openclaw-manager <command> [options]\n\nCommands:\n start Start OpenClaw Manager\n stop Stop the running Manager process\n stop-all Stop Manager, sandboxes, and gateway processes\n reset Stop all and remove local manager data\n\nOptions:\n -h, --help Show help\n -v, --version Show version\n -u, --user <name> Admin username (start)\n -p, --pass <value> Admin password (start)\n --non-interactive Fail instead of prompting for credentials\n --api-port <port> API port (default: 17321)\n --api-host <host> API host (default: 0.0.0.0)\n --config-dir <dir> Config directory\n --config-path <path> Config file path\n`);
|
|
5
5
|
}
|
|
6
6
|
export function printWelcome() {
|
|
7
7
|
printBanner();
|
|
8
|
-
console.log(`\nQuick start:\n openclaw-manager start\n\nCommon commands:\n openclaw-manager stop\n openclaw-manager stop-all\n\nTip: First start will ask for admin username/password.\nDocs: https://openclaw-manager.com\n`);
|
|
8
|
+
console.log(`\nQuick start:\n openclaw-manager start\n\nCommon commands:\n openclaw-manager stop\n openclaw-manager stop-all\n openclaw-manager reset\n\nTip: First start will ask for admin username/password.\nDocs: https://openclaw-manager.com\n`);
|
|
9
9
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
export function listSandboxDirs() {
|
|
5
|
+
const dir = os.tmpdir();
|
|
6
|
+
let entries = [];
|
|
7
|
+
try {
|
|
8
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
return entries
|
|
14
|
+
.filter((entry) => {
|
|
15
|
+
return (entry.isDirectory() &&
|
|
16
|
+
(entry.name.startsWith("openclaw-manager-sandbox-") ||
|
|
17
|
+
entry.name.startsWith("clawdbot-manager-sandbox-")));
|
|
18
|
+
})
|
|
19
|
+
.map((entry) => path.join(dir, entry.name));
|
|
20
|
+
}
|
|
21
|
+
export function removeSandboxDir(rootDir) {
|
|
22
|
+
try {
|
|
23
|
+
fs.rmSync(rootDir, { recursive: true, force: true });
|
|
24
|
+
return { ok: true, message: `removed (${rootDir})` };
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
return { ok: false, error: `failed to remove ${rootDir}: ${String(err)}` };
|
|
28
|
+
}
|
|
29
|
+
}
|
package/bin/openclaw-manager.js
CHANGED
|
@@ -6,6 +6,7 @@ import { readPackageVersion } from "./lib/version.js";
|
|
|
6
6
|
import { startManager } from "./commands/start.js";
|
|
7
7
|
import { stopManager } from "./commands/stop.js";
|
|
8
8
|
import { stopAll } from "./commands/stop-all.js";
|
|
9
|
+
import { resetManager } from "./commands/reset.js";
|
|
9
10
|
const args = process.argv.slice(2);
|
|
10
11
|
const parsed = parseArgs(args);
|
|
11
12
|
const cmd = parsed.command;
|
|
@@ -39,6 +40,13 @@ try {
|
|
|
39
40
|
if (!result.ok)
|
|
40
41
|
process.exit(1);
|
|
41
42
|
}
|
|
43
|
+
else if (cmd === "reset") {
|
|
44
|
+
const result = resetManager(parsed.flags);
|
|
45
|
+
for (const line of result.messages)
|
|
46
|
+
console.log(line);
|
|
47
|
+
if (!result.ok)
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
42
50
|
else {
|
|
43
51
|
console.error(`[manager] Unknown command: ${cmd}`);
|
|
44
52
|
printHelp();
|