mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-07 00:11:36 +00:00
refactor: rename clawdbot to moltbot with legacy compat
This commit is contained in:
@@ -15,119 +15,117 @@ import {
|
||||
|
||||
describe("argv helpers", () => {
|
||||
it("detects help/version flags", () => {
|
||||
expect(hasHelpOrVersion(["node", "clawdbot", "--help"])).toBe(true);
|
||||
expect(hasHelpOrVersion(["node", "clawdbot", "-V"])).toBe(true);
|
||||
expect(hasHelpOrVersion(["node", "clawdbot", "status"])).toBe(false);
|
||||
expect(hasHelpOrVersion(["node", "moltbot", "--help"])).toBe(true);
|
||||
expect(hasHelpOrVersion(["node", "moltbot", "-V"])).toBe(true);
|
||||
expect(hasHelpOrVersion(["node", "moltbot", "status"])).toBe(false);
|
||||
});
|
||||
|
||||
it("extracts command path ignoring flags and terminator", () => {
|
||||
expect(getCommandPath(["node", "clawdbot", "status", "--json"], 2)).toEqual(["status"]);
|
||||
expect(getCommandPath(["node", "clawdbot", "agents", "list"], 2)).toEqual(["agents", "list"]);
|
||||
expect(getCommandPath(["node", "clawdbot", "status", "--", "ignored"], 2)).toEqual(["status"]);
|
||||
expect(getCommandPath(["node", "moltbot", "status", "--json"], 2)).toEqual(["status"]);
|
||||
expect(getCommandPath(["node", "moltbot", "agents", "list"], 2)).toEqual(["agents", "list"]);
|
||||
expect(getCommandPath(["node", "moltbot", "status", "--", "ignored"], 2)).toEqual(["status"]);
|
||||
});
|
||||
|
||||
it("returns primary command", () => {
|
||||
expect(getPrimaryCommand(["node", "clawdbot", "agents", "list"])).toBe("agents");
|
||||
expect(getPrimaryCommand(["node", "clawdbot"])).toBeNull();
|
||||
expect(getPrimaryCommand(["node", "moltbot", "agents", "list"])).toBe("agents");
|
||||
expect(getPrimaryCommand(["node", "moltbot"])).toBeNull();
|
||||
});
|
||||
|
||||
it("parses boolean flags and ignores terminator", () => {
|
||||
expect(hasFlag(["node", "clawdbot", "status", "--json"], "--json")).toBe(true);
|
||||
expect(hasFlag(["node", "clawdbot", "--", "--json"], "--json")).toBe(false);
|
||||
expect(hasFlag(["node", "moltbot", "status", "--json"], "--json")).toBe(true);
|
||||
expect(hasFlag(["node", "moltbot", "--", "--json"], "--json")).toBe(false);
|
||||
});
|
||||
|
||||
it("extracts flag values with equals and missing values", () => {
|
||||
expect(getFlagValue(["node", "clawdbot", "status", "--timeout", "5000"], "--timeout")).toBe(
|
||||
expect(getFlagValue(["node", "moltbot", "status", "--timeout", "5000"], "--timeout")).toBe(
|
||||
"5000",
|
||||
);
|
||||
expect(getFlagValue(["node", "clawdbot", "status", "--timeout=2500"], "--timeout")).toBe(
|
||||
"2500",
|
||||
);
|
||||
expect(getFlagValue(["node", "clawdbot", "status", "--timeout"], "--timeout")).toBeNull();
|
||||
expect(getFlagValue(["node", "clawdbot", "status", "--timeout", "--json"], "--timeout")).toBe(
|
||||
expect(getFlagValue(["node", "moltbot", "status", "--timeout=2500"], "--timeout")).toBe("2500");
|
||||
expect(getFlagValue(["node", "moltbot", "status", "--timeout"], "--timeout")).toBeNull();
|
||||
expect(getFlagValue(["node", "moltbot", "status", "--timeout", "--json"], "--timeout")).toBe(
|
||||
null,
|
||||
);
|
||||
expect(getFlagValue(["node", "clawdbot", "--", "--timeout=99"], "--timeout")).toBeUndefined();
|
||||
expect(getFlagValue(["node", "moltbot", "--", "--timeout=99"], "--timeout")).toBeUndefined();
|
||||
});
|
||||
|
||||
it("parses verbose flags", () => {
|
||||
expect(getVerboseFlag(["node", "clawdbot", "status", "--verbose"])).toBe(true);
|
||||
expect(getVerboseFlag(["node", "clawdbot", "status", "--debug"])).toBe(false);
|
||||
expect(getVerboseFlag(["node", "clawdbot", "status", "--debug"], { includeDebug: true })).toBe(
|
||||
expect(getVerboseFlag(["node", "moltbot", "status", "--verbose"])).toBe(true);
|
||||
expect(getVerboseFlag(["node", "moltbot", "status", "--debug"])).toBe(false);
|
||||
expect(getVerboseFlag(["node", "moltbot", "status", "--debug"], { includeDebug: true })).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
it("parses positive integer flag values", () => {
|
||||
expect(getPositiveIntFlagValue(["node", "clawdbot", "status"], "--timeout")).toBeUndefined();
|
||||
expect(getPositiveIntFlagValue(["node", "moltbot", "status"], "--timeout")).toBeUndefined();
|
||||
expect(
|
||||
getPositiveIntFlagValue(["node", "clawdbot", "status", "--timeout"], "--timeout"),
|
||||
getPositiveIntFlagValue(["node", "moltbot", "status", "--timeout"], "--timeout"),
|
||||
).toBeNull();
|
||||
expect(
|
||||
getPositiveIntFlagValue(["node", "clawdbot", "status", "--timeout", "5000"], "--timeout"),
|
||||
getPositiveIntFlagValue(["node", "moltbot", "status", "--timeout", "5000"], "--timeout"),
|
||||
).toBe(5000);
|
||||
expect(
|
||||
getPositiveIntFlagValue(["node", "clawdbot", "status", "--timeout", "nope"], "--timeout"),
|
||||
getPositiveIntFlagValue(["node", "moltbot", "status", "--timeout", "nope"], "--timeout"),
|
||||
).toBeUndefined();
|
||||
});
|
||||
|
||||
it("builds parse argv from raw args", () => {
|
||||
const nodeArgv = buildParseArgv({
|
||||
programName: "clawdbot",
|
||||
rawArgs: ["node", "clawdbot", "status"],
|
||||
programName: "moltbot",
|
||||
rawArgs: ["node", "moltbot", "status"],
|
||||
});
|
||||
expect(nodeArgv).toEqual(["node", "clawdbot", "status"]);
|
||||
expect(nodeArgv).toEqual(["node", "moltbot", "status"]);
|
||||
|
||||
const versionedNodeArgv = buildParseArgv({
|
||||
programName: "clawdbot",
|
||||
rawArgs: ["node-22", "clawdbot", "status"],
|
||||
programName: "moltbot",
|
||||
rawArgs: ["node-22", "moltbot", "status"],
|
||||
});
|
||||
expect(versionedNodeArgv).toEqual(["node-22", "clawdbot", "status"]);
|
||||
expect(versionedNodeArgv).toEqual(["node-22", "moltbot", "status"]);
|
||||
|
||||
const versionedNodeWindowsArgv = buildParseArgv({
|
||||
programName: "clawdbot",
|
||||
rawArgs: ["node-22.2.0.exe", "clawdbot", "status"],
|
||||
programName: "moltbot",
|
||||
rawArgs: ["node-22.2.0.exe", "moltbot", "status"],
|
||||
});
|
||||
expect(versionedNodeWindowsArgv).toEqual(["node-22.2.0.exe", "clawdbot", "status"]);
|
||||
expect(versionedNodeWindowsArgv).toEqual(["node-22.2.0.exe", "moltbot", "status"]);
|
||||
|
||||
const versionedNodePatchlessArgv = buildParseArgv({
|
||||
programName: "clawdbot",
|
||||
rawArgs: ["node-22.2", "clawdbot", "status"],
|
||||
programName: "moltbot",
|
||||
rawArgs: ["node-22.2", "moltbot", "status"],
|
||||
});
|
||||
expect(versionedNodePatchlessArgv).toEqual(["node-22.2", "clawdbot", "status"]);
|
||||
expect(versionedNodePatchlessArgv).toEqual(["node-22.2", "moltbot", "status"]);
|
||||
|
||||
const versionedNodeWindowsPatchlessArgv = buildParseArgv({
|
||||
programName: "clawdbot",
|
||||
rawArgs: ["node-22.2.exe", "clawdbot", "status"],
|
||||
programName: "moltbot",
|
||||
rawArgs: ["node-22.2.exe", "moltbot", "status"],
|
||||
});
|
||||
expect(versionedNodeWindowsPatchlessArgv).toEqual(["node-22.2.exe", "clawdbot", "status"]);
|
||||
expect(versionedNodeWindowsPatchlessArgv).toEqual(["node-22.2.exe", "moltbot", "status"]);
|
||||
|
||||
const versionedNodeWithPathArgv = buildParseArgv({
|
||||
programName: "clawdbot",
|
||||
rawArgs: ["/usr/bin/node-22.2.0", "clawdbot", "status"],
|
||||
programName: "moltbot",
|
||||
rawArgs: ["/usr/bin/node-22.2.0", "moltbot", "status"],
|
||||
});
|
||||
expect(versionedNodeWithPathArgv).toEqual(["/usr/bin/node-22.2.0", "clawdbot", "status"]);
|
||||
expect(versionedNodeWithPathArgv).toEqual(["/usr/bin/node-22.2.0", "moltbot", "status"]);
|
||||
|
||||
const nodejsArgv = buildParseArgv({
|
||||
programName: "clawdbot",
|
||||
rawArgs: ["nodejs", "clawdbot", "status"],
|
||||
programName: "moltbot",
|
||||
rawArgs: ["nodejs", "moltbot", "status"],
|
||||
});
|
||||
expect(nodejsArgv).toEqual(["nodejs", "clawdbot", "status"]);
|
||||
expect(nodejsArgv).toEqual(["nodejs", "moltbot", "status"]);
|
||||
|
||||
const nonVersionedNodeArgv = buildParseArgv({
|
||||
programName: "clawdbot",
|
||||
rawArgs: ["node-dev", "clawdbot", "status"],
|
||||
programName: "moltbot",
|
||||
rawArgs: ["node-dev", "moltbot", "status"],
|
||||
});
|
||||
expect(nonVersionedNodeArgv).toEqual(["node", "clawdbot", "node-dev", "clawdbot", "status"]);
|
||||
expect(nonVersionedNodeArgv).toEqual(["node", "moltbot", "node-dev", "moltbot", "status"]);
|
||||
|
||||
const directArgv = buildParseArgv({
|
||||
programName: "clawdbot",
|
||||
rawArgs: ["clawdbot", "status"],
|
||||
programName: "moltbot",
|
||||
rawArgs: ["moltbot", "status"],
|
||||
});
|
||||
expect(directArgv).toEqual(["node", "clawdbot", "status"]);
|
||||
expect(directArgv).toEqual(["node", "moltbot", "status"]);
|
||||
|
||||
const bunArgv = buildParseArgv({
|
||||
programName: "clawdbot",
|
||||
programName: "moltbot",
|
||||
rawArgs: ["bun", "src/entry.ts", "status"],
|
||||
});
|
||||
expect(bunArgv).toEqual(["bun", "src/entry.ts", "status"]);
|
||||
@@ -135,20 +133,20 @@ describe("argv helpers", () => {
|
||||
|
||||
it("builds parse argv from fallback args", () => {
|
||||
const fallbackArgv = buildParseArgv({
|
||||
programName: "clawdbot",
|
||||
programName: "moltbot",
|
||||
fallbackArgv: ["status"],
|
||||
});
|
||||
expect(fallbackArgv).toEqual(["node", "clawdbot", "status"]);
|
||||
expect(fallbackArgv).toEqual(["node", "moltbot", "status"]);
|
||||
});
|
||||
|
||||
it("decides when to migrate state", () => {
|
||||
expect(shouldMigrateState(["node", "clawdbot", "status"])).toBe(false);
|
||||
expect(shouldMigrateState(["node", "clawdbot", "health"])).toBe(false);
|
||||
expect(shouldMigrateState(["node", "clawdbot", "sessions"])).toBe(false);
|
||||
expect(shouldMigrateState(["node", "clawdbot", "memory", "status"])).toBe(false);
|
||||
expect(shouldMigrateState(["node", "clawdbot", "agent", "--message", "hi"])).toBe(false);
|
||||
expect(shouldMigrateState(["node", "clawdbot", "agents", "list"])).toBe(true);
|
||||
expect(shouldMigrateState(["node", "clawdbot", "message", "send"])).toBe(true);
|
||||
expect(shouldMigrateState(["node", "moltbot", "status"])).toBe(false);
|
||||
expect(shouldMigrateState(["node", "moltbot", "health"])).toBe(false);
|
||||
expect(shouldMigrateState(["node", "moltbot", "sessions"])).toBe(false);
|
||||
expect(shouldMigrateState(["node", "moltbot", "memory", "status"])).toBe(false);
|
||||
expect(shouldMigrateState(["node", "moltbot", "agent", "--message", "hi"])).toBe(false);
|
||||
expect(shouldMigrateState(["node", "moltbot", "agents", "list"])).toBe(true);
|
||||
expect(shouldMigrateState(["node", "moltbot", "message", "send"])).toBe(true);
|
||||
});
|
||||
|
||||
it("reuses command path for migrate state decisions", () => {
|
||||
|
||||
@@ -91,14 +91,14 @@ export function buildParseArgv(params: {
|
||||
const normalizedArgv =
|
||||
programName && baseArgv[0] === programName
|
||||
? baseArgv.slice(1)
|
||||
: baseArgv[0]?.endsWith("clawdbot")
|
||||
: baseArgv[0]?.endsWith("moltbot")
|
||||
? baseArgv.slice(1)
|
||||
: baseArgv;
|
||||
const executable = (normalizedArgv[0]?.split(/[/\\]/).pop() ?? "").toLowerCase();
|
||||
const looksLikeNode =
|
||||
normalizedArgv.length >= 2 && (isNodeExecutable(executable) || isBunExecutable(executable));
|
||||
if (looksLikeNode) return normalizedArgv;
|
||||
return ["node", programName || "clawdbot", ...normalizedArgv];
|
||||
return ["node", programName || "moltbot", ...normalizedArgv];
|
||||
}
|
||||
|
||||
const nodeExecutablePattern = /^node-\d+(?:\.\d+)*(?:\.exe)?$/;
|
||||
|
||||
@@ -39,7 +39,7 @@ export function formatCliBannerLine(version: string, options: BannerOptions = {}
|
||||
const tagline = pickTagline(options);
|
||||
const rich = options.richTty ?? isRich();
|
||||
const cliName = resolveCliName(options.argv ?? process.argv, options.env);
|
||||
const title = cliName === "clawdbot" ? "🦞 Clawdbot" : "🦞 Moltbot";
|
||||
const title = cliName === "moltbot" ? "🦞 Moltbot" : "🦞 Moltbot";
|
||||
const prefix = "🦞 ";
|
||||
const columns = options.columns ?? process.stdout.columns ?? 120;
|
||||
const plainFullLine = `${title} ${version} (${commitLabel}) — ${tagline}`;
|
||||
|
||||
@@ -57,7 +57,7 @@ export function registerBrowserFilesAndDownloadsCommands(
|
||||
browser
|
||||
.command("waitfordownload")
|
||||
.description("Wait for the next download (and save it)")
|
||||
.argument("[path]", "Save path (default: /tmp/clawdbot/downloads/...)")
|
||||
.argument("[path]", "Save path (default: /tmp/moltbot/downloads/...)")
|
||||
.option("--target-id <id>", "CDP target id (or unique prefix)")
|
||||
.option(
|
||||
"--timeout-ms <ms>",
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
export const browserCoreExamples = [
|
||||
"clawdbot browser status",
|
||||
"clawdbot browser start",
|
||||
"clawdbot browser stop",
|
||||
"clawdbot browser tabs",
|
||||
"clawdbot browser open https://example.com",
|
||||
"clawdbot browser focus abcd1234",
|
||||
"clawdbot browser close abcd1234",
|
||||
"clawdbot browser screenshot",
|
||||
"clawdbot browser screenshot --full-page",
|
||||
"clawdbot browser screenshot --ref 12",
|
||||
"clawdbot browser snapshot",
|
||||
"clawdbot browser snapshot --format aria --limit 200",
|
||||
"clawdbot browser snapshot --efficient",
|
||||
"clawdbot browser snapshot --labels",
|
||||
"moltbot browser status",
|
||||
"moltbot browser start",
|
||||
"moltbot browser stop",
|
||||
"moltbot browser tabs",
|
||||
"moltbot browser open https://example.com",
|
||||
"moltbot browser focus abcd1234",
|
||||
"moltbot browser close abcd1234",
|
||||
"moltbot browser screenshot",
|
||||
"moltbot browser screenshot --full-page",
|
||||
"moltbot browser screenshot --ref 12",
|
||||
"moltbot browser snapshot",
|
||||
"moltbot browser snapshot --format aria --limit 200",
|
||||
"moltbot browser snapshot --efficient",
|
||||
"moltbot browser snapshot --labels",
|
||||
];
|
||||
|
||||
export const browserActionExamples = [
|
||||
"clawdbot browser navigate https://example.com",
|
||||
"clawdbot browser resize 1280 720",
|
||||
"clawdbot browser click 12 --double",
|
||||
'clawdbot browser type 23 "hello" --submit',
|
||||
"clawdbot browser press Enter",
|
||||
"clawdbot browser hover 44",
|
||||
"clawdbot browser drag 10 11",
|
||||
"clawdbot browser select 9 OptionA OptionB",
|
||||
"clawdbot browser upload /tmp/file.pdf",
|
||||
'clawdbot browser fill --fields \'[{"ref":"1","value":"Ada"}]\'',
|
||||
"clawdbot browser dialog --accept",
|
||||
'clawdbot browser wait --text "Done"',
|
||||
"clawdbot browser evaluate --fn '(el) => el.textContent' --ref 7",
|
||||
"clawdbot browser console --level error",
|
||||
"clawdbot browser pdf",
|
||||
"moltbot browser navigate https://example.com",
|
||||
"moltbot browser resize 1280 720",
|
||||
"moltbot browser click 12 --double",
|
||||
'moltbot browser type 23 "hello" --submit',
|
||||
"moltbot browser press Enter",
|
||||
"moltbot browser hover 44",
|
||||
"moltbot browser drag 10 11",
|
||||
"moltbot browser select 9 OptionA OptionB",
|
||||
"moltbot browser upload /tmp/file.pdf",
|
||||
'moltbot browser fill --fields \'[{"ref":"1","value":"Ada"}]\'',
|
||||
"moltbot browser dialog --accept",
|
||||
'moltbot browser wait --text "Done"',
|
||||
"moltbot browser evaluate --fn '(el) => el.textContent' --ref 7",
|
||||
"moltbot browser console --level error",
|
||||
"moltbot browser pdf",
|
||||
];
|
||||
|
||||
@@ -21,7 +21,7 @@ vi.mock("../runtime.js", () => ({
|
||||
|
||||
describe("browser extension install", () => {
|
||||
it("installs into the state dir (never node_modules)", async () => {
|
||||
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "clawdbot-ext-"));
|
||||
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "moltbot-ext-"));
|
||||
const { installChromeExtension } = await import("./browser-cli-extension.js");
|
||||
|
||||
const sourceDir = path.resolve(process.cwd(), "assets/chrome-extension");
|
||||
@@ -34,7 +34,7 @@ describe("browser extension install", () => {
|
||||
|
||||
it("copies extension path to clipboard", async () => {
|
||||
const prev = process.env.CLAWDBOT_STATE_DIR;
|
||||
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "clawdbot-ext-path-"));
|
||||
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "moltbot-ext-path-"));
|
||||
process.env.CLAWDBOT_STATE_DIR = tmp;
|
||||
|
||||
try {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { fileURLToPath } from "node:url";
|
||||
|
||||
import type { Command } from "commander";
|
||||
|
||||
import { STATE_DIR_CLAWDBOT } from "../config/paths.js";
|
||||
import { STATE_DIR } from "../config/paths.js";
|
||||
import { danger, info } from "../globals.js";
|
||||
import { copyToClipboard } from "../infra/clipboard.js";
|
||||
import { defaultRuntime } from "../runtime.js";
|
||||
@@ -20,7 +20,7 @@ function bundledExtensionRootDir() {
|
||||
}
|
||||
|
||||
function installedExtensionRootDir() {
|
||||
return path.join(STATE_DIR_CLAWDBOT, "browser", "chrome-extension");
|
||||
return path.join(STATE_DIR, "browser", "chrome-extension");
|
||||
}
|
||||
|
||||
function hasManifest(dir: string) {
|
||||
@@ -33,10 +33,10 @@ export async function installChromeExtension(opts?: {
|
||||
}): Promise<{ path: string }> {
|
||||
const src = opts?.sourceDir ?? bundledExtensionRootDir();
|
||||
if (!hasManifest(src)) {
|
||||
throw new Error("Bundled Chrome extension is missing. Reinstall Clawdbot and try again.");
|
||||
throw new Error("Bundled Chrome extension is missing. Reinstall Moltbot and try again.");
|
||||
}
|
||||
|
||||
const stateDir = opts?.stateDir ?? STATE_DIR_CLAWDBOT;
|
||||
const stateDir = opts?.stateDir ?? STATE_DIR;
|
||||
const dest = path.join(stateDir, "browser", "chrome-extension");
|
||||
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
||||
|
||||
@@ -88,7 +88,7 @@ export function registerBrowserExtensionCommands(
|
||||
"Next:",
|
||||
`- Chrome → chrome://extensions → enable “Developer mode”`,
|
||||
`- “Load unpacked” → select: ${displayPath}`,
|
||||
`- Pin “Clawdbot Browser Relay”, then click it on the tab (badge shows ON)`,
|
||||
`- Pin “Moltbot Browser Relay”, then click it on the tab (badge shows ON)`,
|
||||
"",
|
||||
`${theme.muted("Docs:")} ${formatDocsLink("/tools/chrome-extension", "docs.molt.bot/tools/chrome-extension")}`,
|
||||
].join("\n"),
|
||||
@@ -106,7 +106,7 @@ export function registerBrowserExtensionCommands(
|
||||
defaultRuntime.error(
|
||||
danger(
|
||||
[
|
||||
`Chrome extension is not installed. Run: "${formatCliCommand("clawdbot browser extension install")}"`,
|
||||
`Chrome extension is not installed. Run: "${formatCliCommand("moltbot browser extension install")}"`,
|
||||
`Docs: ${formatDocsLink("/tools/chrome-extension", "docs.molt.bot/tools/chrome-extension")}`,
|
||||
].join("\n"),
|
||||
),
|
||||
|
||||
@@ -37,7 +37,7 @@ export function registerBrowserCli(program: Command) {
|
||||
.action(() => {
|
||||
browser.outputHelp();
|
||||
defaultRuntime.error(
|
||||
danger(`Missing subcommand. Try: "${formatCliCommand("clawdbot browser status")}"`),
|
||||
danger(`Missing subcommand. Try: "${formatCliCommand("moltbot browser status")}"`),
|
||||
);
|
||||
defaultRuntime.exit(1);
|
||||
});
|
||||
|
||||
28
src/cli/cli-name.ts
Normal file
28
src/cli/cli-name.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import path from "node:path";
|
||||
|
||||
export const DEFAULT_CLI_NAME = "moltbot";
|
||||
export const LEGACY_CLI_NAME = "moltbot";
|
||||
|
||||
const KNOWN_CLI_NAMES = new Set([DEFAULT_CLI_NAME, LEGACY_CLI_NAME]);
|
||||
const CLI_PREFIX_RE = /^(?:((?:pnpm|npm|bunx|npx)\s+))?(moltbot|moltbot)\b/;
|
||||
|
||||
export function resolveCliName(
|
||||
argv: string[] = process.argv,
|
||||
env: Record<string, string | undefined> = process.env as Record<string, string | undefined>,
|
||||
): string {
|
||||
const override = env.MOLTBOT_CLI_NAME?.trim() || env.CLAWDBOT_CLI_NAME?.trim();
|
||||
if (override) return override;
|
||||
const argv1 = argv[1];
|
||||
if (!argv1) return DEFAULT_CLI_NAME;
|
||||
const base = path.basename(argv1).trim();
|
||||
if (KNOWN_CLI_NAMES.has(base)) return base;
|
||||
return DEFAULT_CLI_NAME;
|
||||
}
|
||||
|
||||
export function replaceCliName(command: string, cliName = resolveCliName()): string {
|
||||
if (!command.trim()) return command;
|
||||
if (!CLI_PREFIX_RE.test(command)) return command;
|
||||
return command.replace(CLI_PREFIX_RE, (_match, runner: string | undefined) => {
|
||||
return `${runner ?? ""}${cliName}`;
|
||||
});
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { normalizeProfileName } from "./profile-utils.js";
|
||||
import { replaceCliName, resolveCliName } from "./cli-name.js";
|
||||
|
||||
const CLI_PREFIX_RE = /^(?:pnpm|npm|bunx|npx)\s+(?:clawdbot|moltbot)\b|^(?:clawdbot|moltbot)\b/;
|
||||
const CLI_PREFIX_RE = /^(?:pnpm|npm|bunx|npx)\s+(?:moltbot|moltbot)\b|^(?:moltbot|moltbot)\b/;
|
||||
const PROFILE_FLAG_RE = /(?:^|\s)--profile(?:\s|=|$)/;
|
||||
const DEV_FLAG_RE = /(?:^|\s)--dev(?:\s|$)/;
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ async function loadValidConfig() {
|
||||
for (const issue of snapshot.issues) {
|
||||
defaultRuntime.error(`- ${issue.path || "<root>"}: ${issue.message}`);
|
||||
}
|
||||
defaultRuntime.error(`Run \`${formatCliCommand("clawdbot doctor")}\` to repair, then retry.`);
|
||||
defaultRuntime.error(`Run \`${formatCliCommand("moltbot doctor")}\` to repair, then retry.`);
|
||||
defaultRuntime.exit(1);
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
@@ -88,8 +88,8 @@ describe("daemon-cli coverage", () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
process.env.CLAWDBOT_STATE_DIR = "/tmp/clawdbot-cli-state";
|
||||
process.env.CLAWDBOT_CONFIG_PATH = "/tmp/clawdbot-cli-state/clawdbot.json";
|
||||
process.env.CLAWDBOT_STATE_DIR = "/tmp/moltbot-cli-state";
|
||||
process.env.CLAWDBOT_CONFIG_PATH = "/tmp/moltbot-cli-state/moltbot.json";
|
||||
delete process.env.CLAWDBOT_GATEWAY_PORT;
|
||||
delete process.env.CLAWDBOT_PROFILE;
|
||||
serviceReadCommand.mockResolvedValue(null);
|
||||
@@ -141,8 +141,8 @@ describe("daemon-cli coverage", () => {
|
||||
programArguments: ["/bin/node", "cli", "gateway", "--port", "19001"],
|
||||
environment: {
|
||||
CLAWDBOT_PROFILE: "dev",
|
||||
CLAWDBOT_STATE_DIR: "/tmp/clawdbot-daemon-state",
|
||||
CLAWDBOT_CONFIG_PATH: "/tmp/clawdbot-daemon-state/clawdbot.json",
|
||||
CLAWDBOT_STATE_DIR: "/tmp/moltbot-daemon-state",
|
||||
CLAWDBOT_CONFIG_PATH: "/tmp/moltbot-daemon-state/moltbot.json",
|
||||
CLAWDBOT_GATEWAY_PORT: "19001",
|
||||
},
|
||||
sourcePath: "/tmp/com.clawdbot.gateway.plist",
|
||||
|
||||
@@ -84,7 +84,7 @@ export async function runDaemonInstall(opts: DaemonInstallOptions) {
|
||||
if (!json) {
|
||||
defaultRuntime.log(`Gateway service already ${service.loadedText}.`);
|
||||
defaultRuntime.log(
|
||||
`Reinstall with: ${formatCliCommand("clawdbot gateway install --force")}`,
|
||||
`Reinstall with: ${formatCliCommand("moltbot gateway install --force")}`,
|
||||
);
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -129,7 +129,7 @@ export function renderRuntimeHints(
|
||||
}
|
||||
})();
|
||||
if (runtime.missingUnit) {
|
||||
hints.push(`Service not installed. Run: ${formatCliCommand("clawdbot gateway install", env)}`);
|
||||
hints.push(`Service not installed. Run: ${formatCliCommand("moltbot gateway install", env)}`);
|
||||
if (fileLog) hints.push(`File logs: ${fileLog}`);
|
||||
return hints;
|
||||
}
|
||||
@@ -152,8 +152,8 @@ export function renderRuntimeHints(
|
||||
|
||||
export function renderGatewayServiceStartHints(env: NodeJS.ProcessEnv = process.env): string[] {
|
||||
const base = [
|
||||
formatCliCommand("clawdbot gateway install", env),
|
||||
formatCliCommand("clawdbot gateway", env),
|
||||
formatCliCommand("moltbot gateway install", env),
|
||||
formatCliCommand("moltbot gateway", env),
|
||||
];
|
||||
const profile = env.CLAWDBOT_PROFILE;
|
||||
switch (process.platform) {
|
||||
|
||||
@@ -100,7 +100,7 @@ export function printDaemonStatus(status: DaemonStatus, opts: { json: boolean })
|
||||
}
|
||||
defaultRuntime.error(
|
||||
warnText(
|
||||
`Recommendation: run "${formatCliCommand("clawdbot doctor")}" (or "${formatCliCommand("clawdbot doctor --repair")}").`,
|
||||
`Recommendation: run "${formatCliCommand("moltbot doctor")}" (or "${formatCliCommand("moltbot doctor --repair")}").`,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -134,7 +134,7 @@ export function printDaemonStatus(status: DaemonStatus, opts: { json: boolean })
|
||||
);
|
||||
defaultRuntime.error(
|
||||
errorText(
|
||||
`Fix: rerun \`${formatCliCommand("clawdbot gateway install --force")}\` from the same --profile / CLAWDBOT_STATE_DIR you expect.`,
|
||||
`Fix: rerun \`${formatCliCommand("moltbot gateway install --force")}\` from the same --profile / CLAWDBOT_STATE_DIR you expect.`,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -237,7 +237,7 @@ export function printDaemonStatus(status: DaemonStatus, opts: { json: boolean })
|
||||
),
|
||||
);
|
||||
defaultRuntime.error(
|
||||
errorText(`Then reinstall: ${formatCliCommand("clawdbot gateway install")}`),
|
||||
errorText(`Then reinstall: ${formatCliCommand("moltbot gateway install")}`),
|
||||
);
|
||||
spacer();
|
||||
}
|
||||
@@ -292,7 +292,7 @@ export function printDaemonStatus(status: DaemonStatus, opts: { json: boolean })
|
||||
for (const svc of legacyServices) {
|
||||
defaultRuntime.error(`- ${errorText(svc.label)} (${svc.detail})`);
|
||||
}
|
||||
defaultRuntime.error(errorText(`Cleanup: ${formatCliCommand("clawdbot doctor")}`));
|
||||
defaultRuntime.error(errorText(`Cleanup: ${formatCliCommand("moltbot doctor")}`));
|
||||
spacer();
|
||||
}
|
||||
|
||||
@@ -321,6 +321,6 @@ export function printDaemonStatus(status: DaemonStatus, opts: { json: boolean })
|
||||
spacer();
|
||||
}
|
||||
|
||||
defaultRuntime.log(`${label("Troubles:")} run ${formatCliCommand("clawdbot status")}`);
|
||||
defaultRuntime.log(`${label("Troubles:")} run ${formatCliCommand("moltbot status")}`);
|
||||
defaultRuntime.log(`${label("Troubleshooting:")} https://docs.molt.bot/troubleshooting`);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,6 @@ describe("dns cli", () => {
|
||||
await program.parseAsync(["dns", "setup"], { from: "user" });
|
||||
const output = log.mock.calls.map((call) => call.join(" ")).join("\n");
|
||||
expect(output).toContain("DNS setup");
|
||||
expect(output).toContain("clawdbot.internal");
|
||||
expect(output).toContain("moltbot.internal");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -102,7 +102,7 @@ export function registerDnsCli(program: Command) {
|
||||
|
||||
dns
|
||||
.command("setup")
|
||||
.description("Set up CoreDNS to serve clawdbot.internal for unicast DNS-SD (Wide-Area Bonjour)")
|
||||
.description("Set up CoreDNS to serve moltbot.internal for unicast DNS-SD (Wide-Area Bonjour)")
|
||||
.option(
|
||||
"--apply",
|
||||
"Install/update CoreDNS config and (re)start the service (requires sudo)",
|
||||
@@ -134,7 +134,7 @@ export function registerDnsCli(program: Command) {
|
||||
}).trimEnd(),
|
||||
);
|
||||
defaultRuntime.log("");
|
||||
defaultRuntime.log(theme.heading("Recommended ~/.clawdbot/clawdbot.json:"));
|
||||
defaultRuntime.log(theme.heading("Recommended ~/.clawdbot/moltbot.json:"));
|
||||
defaultRuntime.log(
|
||||
JSON.stringify(
|
||||
{
|
||||
@@ -150,7 +150,7 @@ export function registerDnsCli(program: Command) {
|
||||
defaultRuntime.log(
|
||||
theme.muted(`- Add nameserver: ${tailnetIPv4 ?? "<this machine's tailnet IPv4>"}`),
|
||||
);
|
||||
defaultRuntime.log(theme.muted("- Restrict to domain (Split DNS): clawdbot.internal"));
|
||||
defaultRuntime.log(theme.muted("- Restrict to domain (Split DNS): moltbot.internal"));
|
||||
|
||||
if (!opts.apply) {
|
||||
defaultRuntime.log("");
|
||||
@@ -170,7 +170,7 @@ export function registerDnsCli(program: Command) {
|
||||
const corefilePath = path.join(etcDir, "Corefile");
|
||||
const confDir = path.join(etcDir, "conf.d");
|
||||
const importGlob = path.join(confDir, "*.server");
|
||||
const serverPath = path.join(confDir, "clawdbot.internal.server");
|
||||
const serverPath = path.join(confDir, "moltbot.internal.server");
|
||||
|
||||
run("brew", ["list", "coredns"], { allowFailure: true });
|
||||
run("brew", ["install", "coredns"], {
|
||||
@@ -210,7 +210,7 @@ export function registerDnsCli(program: Command) {
|
||||
const serial = `${y}${m}${d}01`;
|
||||
|
||||
const zoneLines = [
|
||||
`; created by clawdbot dns setup (will be overwritten by the gateway when wide-area discovery is enabled)`,
|
||||
`; created by moltbot dns setup (will be overwritten by the gateway when wide-area discovery is enabled)`,
|
||||
`$ORIGIN ${WIDE_AREA_DISCOVERY_DOMAIN}`,
|
||||
`$TTL 60`,
|
||||
`@ IN SOA ns1 hostmaster ${serial} 7200 3600 1209600 60`,
|
||||
@@ -233,7 +233,7 @@ export function registerDnsCli(program: Command) {
|
||||
defaultRuntime.log("");
|
||||
defaultRuntime.log(
|
||||
theme.muted(
|
||||
"Note: enable discovery.wideArea.enabled in ~/.clawdbot/clawdbot.json on the gateway and restart the gateway so it writes the DNS-SD zone.",
|
||||
"Note: enable discovery.wideArea.enabled in ~/.clawdbot/moltbot.json on the gateway and restart the gateway so it writes the DNS-SD zone.",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { runCommandWithRuntime } from "./cli-utils.js";
|
||||
export function registerDocsCli(program: Command) {
|
||||
program
|
||||
.command("docs")
|
||||
.description("Search the live Clawdbot docs")
|
||||
.description("Search the live Moltbot docs")
|
||||
.argument("[query...]", "Search query")
|
||||
.addHelpText(
|
||||
"after",
|
||||
|
||||
@@ -326,16 +326,16 @@ export function registerExecApprovalsCli(program: Command) {
|
||||
"after",
|
||||
() =>
|
||||
`\n${theme.heading("Examples:")}\n${formatExample(
|
||||
'clawdbot approvals allowlist add "~/Projects/**/bin/rg"',
|
||||
'moltbot approvals allowlist add "~/Projects/**/bin/rg"',
|
||||
"Allowlist a local binary pattern for the main agent.",
|
||||
)}\n${formatExample(
|
||||
'clawdbot approvals allowlist add --agent main --node <id|name|ip> "/usr/bin/uptime"',
|
||||
'moltbot approvals allowlist add --agent main --node <id|name|ip> "/usr/bin/uptime"',
|
||||
"Allowlist on a specific node/agent.",
|
||||
)}\n${formatExample(
|
||||
'clawdbot approvals allowlist add --agent "*" "/usr/bin/uname"',
|
||||
'moltbot approvals allowlist add --agent "*" "/usr/bin/uname"',
|
||||
"Allowlist for all agents (wildcard).",
|
||||
)}\n${formatExample(
|
||||
'clawdbot approvals allowlist remove "~/Projects/**/bin/rg"',
|
||||
'moltbot approvals allowlist remove "~/Projects/**/bin/rg"',
|
||||
"Remove an allowlist pattern.",
|
||||
)}\n\n${theme.muted("Docs:")} ${formatDocsLink("/cli/approvals", "docs.molt.bot/cli/approvals")}\n`,
|
||||
);
|
||||
|
||||
@@ -139,7 +139,7 @@ describe("gateway-cli coverage", () => {
|
||||
discoverGatewayBeacons.mockReset();
|
||||
discoverGatewayBeacons.mockResolvedValueOnce([
|
||||
{
|
||||
instanceName: "Studio (Clawdbot)",
|
||||
instanceName: "Studio (Moltbot)",
|
||||
displayName: "Studio",
|
||||
domain: "local.",
|
||||
host: "studio.local",
|
||||
@@ -171,9 +171,9 @@ describe("gateway-cli coverage", () => {
|
||||
discoverGatewayBeacons.mockReset();
|
||||
discoverGatewayBeacons.mockResolvedValueOnce([
|
||||
{
|
||||
instanceName: "Studio (Clawdbot)",
|
||||
instanceName: "Studio (Moltbot)",
|
||||
displayName: "Studio",
|
||||
domain: "clawdbot.internal.",
|
||||
domain: "moltbot.internal.",
|
||||
host: "studio.clawdbot.internal",
|
||||
lanHost: "studio.local",
|
||||
tailnetDns: "studio.tailnet.ts.net",
|
||||
@@ -194,7 +194,7 @@ describe("gateway-cli coverage", () => {
|
||||
const out = runtimeLogs.join("\n");
|
||||
expect(out).toContain("Gateway Discovery");
|
||||
expect(out).toContain("Found 1 gateway(s)");
|
||||
expect(out).toContain("- Studio clawdbot.internal.");
|
||||
expect(out).toContain("- Studio moltbot.internal.");
|
||||
expect(out).toContain(" tailnet: studio.tailnet.ts.net");
|
||||
expect(out).toContain(" host: studio.clawdbot.internal");
|
||||
expect(out).toContain(" ws: ws://studio.tailnet.ts.net:18789");
|
||||
|
||||
@@ -4,7 +4,7 @@ import path from "node:path";
|
||||
|
||||
import { resolveDefaultAgentWorkspaceDir } from "../../agents/workspace.js";
|
||||
import { handleReset } from "../../commands/onboard-helpers.js";
|
||||
import { CONFIG_PATH_CLAWDBOT, writeConfigFile } from "../../config/config.js";
|
||||
import { CONFIG_PATH, writeConfigFile } from "../../config/config.js";
|
||||
import { defaultRuntime } from "../../runtime.js";
|
||||
import { resolveUserPath, shortenHomePath } from "../../utils.js";
|
||||
|
||||
@@ -56,7 +56,7 @@ async function ensureDevWorkspace(dir: string) {
|
||||
const [agents, soul, tools, identity, user] = await Promise.all([
|
||||
loadDevTemplate(
|
||||
"AGENTS.dev.md",
|
||||
`# AGENTS.md - Clawdbot Dev Workspace\n\nDefault dev workspace for clawdbot gateway --dev.\n`,
|
||||
`# AGENTS.md - Moltbot Dev Workspace\n\nDefault dev workspace for moltbot gateway --dev.\n`,
|
||||
),
|
||||
loadDevTemplate(
|
||||
"SOUL.dev.md",
|
||||
@@ -89,7 +89,7 @@ export async function ensureDevGatewayConfig(opts: { reset?: boolean }) {
|
||||
await handleReset("full", workspace, defaultRuntime);
|
||||
}
|
||||
|
||||
const configExists = fs.existsSync(CONFIG_PATH_CLAWDBOT);
|
||||
const configExists = fs.existsSync(CONFIG_PATH);
|
||||
if (!opts.reset && configExists) return;
|
||||
|
||||
await writeConfigFile({
|
||||
@@ -117,6 +117,6 @@ export async function ensureDevGatewayConfig(opts: { reset?: boolean }) {
|
||||
},
|
||||
});
|
||||
await ensureDevWorkspace(workspace);
|
||||
defaultRuntime.log(`Dev config ready: ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
defaultRuntime.log(`Dev config ready: ${shortenHomePath(CONFIG_PATH)}`);
|
||||
defaultRuntime.log(`Dev workspace ready: ${shortenHomePath(resolveUserPath(workspace))}`);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import fs from "node:fs";
|
||||
import type { Command } from "commander";
|
||||
import type { GatewayAuthMode } from "../../config/config.js";
|
||||
import {
|
||||
CONFIG_PATH_CLAWDBOT,
|
||||
CONFIG_PATH,
|
||||
loadConfig,
|
||||
readConfigFileSnapshot,
|
||||
resolveGatewayPort,
|
||||
@@ -157,12 +157,12 @@ async function runGatewayCommand(opts: GatewayRunOpts) {
|
||||
const passwordRaw = toOptionString(opts.password);
|
||||
const tokenRaw = toOptionString(opts.token);
|
||||
|
||||
const configExists = fs.existsSync(CONFIG_PATH_CLAWDBOT);
|
||||
const configExists = fs.existsSync(CONFIG_PATH);
|
||||
const mode = cfg.gateway?.mode;
|
||||
if (!opts.allowUnconfigured && mode !== "local") {
|
||||
if (!configExists) {
|
||||
defaultRuntime.error(
|
||||
`Missing config. Run \`${formatCliCommand("clawdbot setup")}\` or set gateway.mode=local (or pass --allow-unconfigured).`,
|
||||
`Missing config. Run \`${formatCliCommand("moltbot setup")}\` or set gateway.mode=local (or pass --allow-unconfigured).`,
|
||||
);
|
||||
} else {
|
||||
defaultRuntime.error(
|
||||
@@ -286,7 +286,7 @@ async function runGatewayCommand(opts: GatewayRunOpts) {
|
||||
) {
|
||||
const errMessage = describeUnknownError(err);
|
||||
defaultRuntime.error(
|
||||
`Gateway failed to start: ${errMessage}\nIf the gateway is supervised, stop it with: ${formatCliCommand("clawdbot gateway stop")}`,
|
||||
`Gateway failed to start: ${errMessage}\nIf the gateway is supervised, stop it with: ${formatCliCommand("moltbot gateway stop")}`,
|
||||
);
|
||||
try {
|
||||
const diagnostics = await inspectPortUsage(port);
|
||||
|
||||
@@ -68,21 +68,21 @@ export function renderGatewayServiceStopHints(env: NodeJS.ProcessEnv = process.e
|
||||
switch (process.platform) {
|
||||
case "darwin":
|
||||
return [
|
||||
`Tip: ${formatCliCommand("clawdbot gateway stop")}`,
|
||||
`Tip: ${formatCliCommand("moltbot gateway stop")}`,
|
||||
`Or: launchctl bootout gui/$UID/${resolveGatewayLaunchAgentLabel(profile)}`,
|
||||
];
|
||||
case "linux":
|
||||
return [
|
||||
`Tip: ${formatCliCommand("clawdbot gateway stop")}`,
|
||||
`Tip: ${formatCliCommand("moltbot gateway stop")}`,
|
||||
`Or: systemctl --user stop ${resolveGatewaySystemdServiceName(profile)}.service`,
|
||||
];
|
||||
case "win32":
|
||||
return [
|
||||
`Tip: ${formatCliCommand("clawdbot gateway stop")}`,
|
||||
`Tip: ${formatCliCommand("moltbot gateway stop")}`,
|
||||
`Or: schtasks /End /TN "${resolveGatewayWindowsTaskName(profile)}"`,
|
||||
];
|
||||
default:
|
||||
return [`Tip: ${formatCliCommand("clawdbot gateway stop")}`];
|
||||
return [`Tip: ${formatCliCommand("moltbot gateway stop")}`];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ describe("gateway SIGTERM", () => {
|
||||
});
|
||||
|
||||
it("exits 0 on SIGTERM", { timeout: 180_000 }, async () => {
|
||||
const stateDir = fs.mkdtempSync(path.join(os.tmpdir(), "clawdbot-gateway-test-"));
|
||||
const stateDir = fs.mkdtempSync(path.join(os.tmpdir(), "moltbot-gateway-test-"));
|
||||
const out: string[] = [];
|
||||
const err: string[] = [];
|
||||
|
||||
@@ -92,7 +92,7 @@ describe("gateway SIGTERM", () => {
|
||||
CLAWDBOT_SKIP_BROWSER_CONTROL_SERVER: "1",
|
||||
CLAWDBOT_SKIP_CANVAS_HOST: "1",
|
||||
};
|
||||
const bootstrapPath = path.join(stateDir, "clawdbot-entry-bootstrap.mjs");
|
||||
const bootstrapPath = path.join(stateDir, "moltbot-entry-bootstrap.mjs");
|
||||
const runLoopPath = path.resolve("src/cli/gateway-cli/run-loop.ts");
|
||||
const runtimePath = path.resolve("src/runtime.ts");
|
||||
fs.writeFileSync(
|
||||
|
||||
@@ -9,7 +9,7 @@ const report: HookStatusReport = {
|
||||
{
|
||||
name: "session-memory",
|
||||
description: "Save session context to memory",
|
||||
source: "clawdbot-bundled",
|
||||
source: "moltbot-bundled",
|
||||
pluginId: undefined,
|
||||
filePath: "/tmp/hooks/session-memory/HOOK.md",
|
||||
baseDir: "/tmp/hooks/session-memory",
|
||||
@@ -62,7 +62,7 @@ describe("hooks cli formatting", () => {
|
||||
{
|
||||
name: "plugin-hook",
|
||||
description: "Hook from plugin",
|
||||
source: "clawdbot-plugin",
|
||||
source: "moltbot-plugin",
|
||||
pluginId: "voice-call",
|
||||
filePath: "/tmp/hooks/plugin-hook/HOOK.md",
|
||||
baseDir: "/tmp/hooks/plugin-hook",
|
||||
|
||||
@@ -3,7 +3,7 @@ import fsp from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import type { Command } from "commander";
|
||||
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent-scope.js";
|
||||
import type { ClawdbotConfig } from "../config/config.js";
|
||||
import type { MoltbotConfig } from "../config/config.js";
|
||||
import { resolveArchiveKind } from "../infra/archive.js";
|
||||
import {
|
||||
buildWorkspaceHookStatus,
|
||||
@@ -57,7 +57,7 @@ function mergeHookEntries(pluginEntries: HookEntry[], workspaceEntries: HookEntr
|
||||
return Array.from(merged.values());
|
||||
}
|
||||
|
||||
function buildHooksReport(config: ClawdbotConfig): HookStatusReport {
|
||||
function buildHooksReport(config: MoltbotConfig): HookStatusReport {
|
||||
const workspaceDir = resolveAgentWorkspaceDir(config, resolveDefaultAgentId(config));
|
||||
const workspaceEntries = loadWorkspaceHookEntries(workspaceDir, { config });
|
||||
const pluginReport = buildPluginStatusReport({ config, workspaceDir });
|
||||
@@ -141,7 +141,7 @@ export function formatHooksList(report: HookStatusReport, opts: HooksListOptions
|
||||
|
||||
if (hooks.length === 0) {
|
||||
const message = opts.eligible
|
||||
? `No eligible hooks found. Run \`${formatCliCommand("clawdbot hooks list")}\` to see all hooks.`
|
||||
? `No eligible hooks found. Run \`${formatCliCommand("moltbot hooks list")}\` to see all hooks.`
|
||||
: "No hooks found.";
|
||||
return message;
|
||||
}
|
||||
@@ -197,7 +197,7 @@ export function formatHookInfo(
|
||||
if (opts.json) {
|
||||
return JSON.stringify({ error: "not found", hook: hookName }, null, 2);
|
||||
}
|
||||
return `Hook "${hookName}" not found. Run \`${formatCliCommand("clawdbot hooks list")}\` to see available hooks.`;
|
||||
return `Hook "${hookName}" not found. Run \`${formatCliCommand("moltbot hooks list")}\` to see available hooks.`;
|
||||
}
|
||||
|
||||
if (opts.json) {
|
||||
@@ -533,7 +533,7 @@ export function registerHooksCli(program: Command): void {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let next: ClawdbotConfig = {
|
||||
let next: MoltbotConfig = {
|
||||
...cfg,
|
||||
hooks: {
|
||||
...cfg.hooks,
|
||||
@@ -594,7 +594,7 @@ export function registerHooksCli(program: Command): void {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let next: ClawdbotConfig = {
|
||||
let next: MoltbotConfig = {
|
||||
...cfg,
|
||||
hooks: {
|
||||
...cfg.hooks,
|
||||
@@ -674,7 +674,7 @@ export function registerHooksCli(program: Command): void {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let next: ClawdbotConfig = {
|
||||
let next: MoltbotConfig = {
|
||||
...cfg,
|
||||
hooks: {
|
||||
...cfg.hooks,
|
||||
|
||||
@@ -18,7 +18,7 @@ describe("logs cli", () => {
|
||||
|
||||
it("writes output directly to stdout/stderr", async () => {
|
||||
callGatewayFromCli.mockResolvedValueOnce({
|
||||
file: "/tmp/clawdbot.log",
|
||||
file: "/tmp/moltbot.log",
|
||||
cursor: 1,
|
||||
size: 123,
|
||||
lines: ["raw line"],
|
||||
@@ -55,7 +55,7 @@ describe("logs cli", () => {
|
||||
|
||||
it("warns when the output pipe closes", async () => {
|
||||
callGatewayFromCli.mockResolvedValueOnce({
|
||||
file: "/tmp/clawdbot.log",
|
||||
file: "/tmp/moltbot.log",
|
||||
lines: ["line one"],
|
||||
});
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ function createLogWriters() {
|
||||
onBrokenPipe: (err, stream) => {
|
||||
const code = err.code ?? "EPIPE";
|
||||
const target = stream === process.stdout ? "stdout" : "stderr";
|
||||
const message = `clawdbot logs: output ${target} closed (${code}). Stopping tail.`;
|
||||
const message = `moltbot logs: output ${target} closed (${code}). Stopping tail.`;
|
||||
try {
|
||||
clearActiveProgressLine();
|
||||
process.stderr.write(`${message}\n`);
|
||||
@@ -141,7 +141,7 @@ function emitGatewayError(
|
||||
) {
|
||||
const details = buildGatewayConnectionDetails({ url: opts.url });
|
||||
const message = "Gateway not reachable. Is it running and accessible?";
|
||||
const hint = `Hint: run \`${formatCliCommand("clawdbot doctor")}\`.`;
|
||||
const hint = `Hint: run \`${formatCliCommand("moltbot doctor")}\`.`;
|
||||
const errorText = err instanceof Error ? err.message : String(err);
|
||||
|
||||
if (mode === "json") {
|
||||
|
||||
@@ -47,7 +47,7 @@ type NodeDaemonStatusOptions = {
|
||||
};
|
||||
|
||||
function renderNodeServiceStartHints(): string[] {
|
||||
const base = [formatCliCommand("clawdbot node install"), formatCliCommand("clawdbot node start")];
|
||||
const base = [formatCliCommand("moltbot node install"), formatCliCommand("moltbot node start")];
|
||||
switch (process.platform) {
|
||||
case "darwin":
|
||||
return [
|
||||
@@ -169,7 +169,7 @@ export async function runNodeDaemonInstall(opts: NodeDaemonInstallOptions) {
|
||||
});
|
||||
if (!json) {
|
||||
defaultRuntime.log(`Node service already ${service.loadedText}.`);
|
||||
defaultRuntime.log(`Reinstall with: ${formatCliCommand("clawdbot node install --force")}`);
|
||||
defaultRuntime.log(`Reinstall with: ${formatCliCommand("moltbot node install --force")}`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ export function registerNodesCanvasCommands(nodes: Command) {
|
||||
const { version, messageCount } = validateA2UIJsonl(jsonl);
|
||||
if (version === "v0.9") {
|
||||
throw new Error(
|
||||
"Detected A2UI v0.9 JSONL (createSurface). Clawdbot currently supports v0.8 only.",
|
||||
"Detected A2UI v0.9 JSONL (createSurface). Moltbot currently supports v0.8 only.",
|
||||
);
|
||||
}
|
||||
await invokeCanvas(opts, "canvas.a2ui.pushJSONL", { jsonl });
|
||||
|
||||
@@ -33,6 +33,6 @@ describe("nodes screen helpers", () => {
|
||||
tmpDir: "/tmp",
|
||||
id: "id1",
|
||||
});
|
||||
expect(p).toBe(path.join("/tmp", "clawdbot-screen-record-id1.mp4"));
|
||||
expect(p).toBe(path.join("/tmp", "moltbot-screen-record-id1.mp4"));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -42,7 +42,7 @@ export function screenRecordTempPath(opts: { ext: string; tmpDir?: string; id?:
|
||||
const tmpDir = opts.tmpDir ?? os.tmpdir();
|
||||
const id = opts.id ?? randomUUID();
|
||||
const ext = opts.ext.startsWith(".") ? opts.ext : `.${opts.ext}`;
|
||||
return path.join(tmpDir, `clawdbot-screen-record-${id}${ext}`);
|
||||
return path.join(tmpDir, `moltbot-screen-record-${id}${ext}`);
|
||||
}
|
||||
|
||||
export async function writeScreenRecordToFile(filePath: string, base64: string) {
|
||||
|
||||
@@ -115,12 +115,12 @@ export function registerPairingCli(program: Command) {
|
||||
const resolvedCode = opts.channel ? codeOrChannel : code;
|
||||
if (!opts.channel && !code) {
|
||||
throw new Error(
|
||||
`Usage: ${formatCliCommand("clawdbot pairing approve <channel> <code>")} (or: ${formatCliCommand("clawdbot pairing approve --channel <channel> <code>")})`,
|
||||
`Usage: ${formatCliCommand("moltbot pairing approve <channel> <code>")} (or: ${formatCliCommand("moltbot pairing approve --channel <channel> <code>")})`,
|
||||
);
|
||||
}
|
||||
if (opts.channel && code != null) {
|
||||
throw new Error(
|
||||
`Too many arguments. Use: ${formatCliCommand("clawdbot pairing approve --channel <channel> <code>")}`,
|
||||
`Too many arguments. Use: ${formatCliCommand("moltbot pairing approve --channel <channel> <code>")}`,
|
||||
);
|
||||
}
|
||||
const channel = parseChannel(channelRaw, channels);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent-scope.js";
|
||||
import { loadConfig } from "../config/config.js";
|
||||
import { createSubsystemLogger } from "../logging.js";
|
||||
import { loadClawdbotPlugins } from "../plugins/loader.js";
|
||||
import { loadMoltbotPlugins } from "../plugins/loader.js";
|
||||
import type { PluginLogger } from "../plugins/types.js";
|
||||
|
||||
const log = createSubsystemLogger("plugins");
|
||||
@@ -17,7 +17,7 @@ export function ensurePluginRegistryLoaded(): void {
|
||||
error: (msg) => log.error(msg),
|
||||
debug: (msg) => log.debug(msg),
|
||||
};
|
||||
loadClawdbotPlugins({
|
||||
loadMoltbotPlugins({
|
||||
config,
|
||||
workspaceDir,
|
||||
logger,
|
||||
|
||||
@@ -3,7 +3,7 @@ import path from "node:path";
|
||||
import type { Command } from "commander";
|
||||
|
||||
import { loadConfig, writeConfigFile } from "../config/config.js";
|
||||
import type { ClawdbotConfig } from "../config/config.js";
|
||||
import type { MoltbotConfig } from "../config/config.js";
|
||||
import { resolveArchiveKind } from "../infra/archive.js";
|
||||
import { installPluginFromNpmSpec, installPluginFromPath } from "../plugins/install.js";
|
||||
import { recordPluginInstall } from "../plugins/installs.js";
|
||||
@@ -67,9 +67,9 @@ function formatPluginLine(plugin: PluginRecord, verbose = false): string {
|
||||
}
|
||||
|
||||
function applySlotSelectionForPlugin(
|
||||
config: ClawdbotConfig,
|
||||
config: MoltbotConfig,
|
||||
pluginId: string,
|
||||
): { config: ClawdbotConfig; warnings: string[] } {
|
||||
): { config: MoltbotConfig; warnings: string[] } {
|
||||
const report = buildPluginStatusReport({ config });
|
||||
const plugin = report.plugins.find((entry) => entry.id === pluginId);
|
||||
if (!plugin) {
|
||||
@@ -94,7 +94,7 @@ function logSlotWarnings(warnings: string[]) {
|
||||
export function registerPluginsCli(program: Command) {
|
||||
const plugins = program
|
||||
.command("plugins")
|
||||
.description("Manage Clawdbot plugins/extensions")
|
||||
.description("Manage Moltbot plugins/extensions")
|
||||
.addHelpText(
|
||||
"after",
|
||||
() =>
|
||||
@@ -246,7 +246,7 @@ export function registerPluginsCli(program: Command) {
|
||||
.argument("<id>", "Plugin id")
|
||||
.action(async (id: string) => {
|
||||
const cfg = loadConfig();
|
||||
let next: ClawdbotConfig = {
|
||||
let next: MoltbotConfig = {
|
||||
...cfg,
|
||||
plugins: {
|
||||
...cfg.plugins,
|
||||
@@ -308,7 +308,7 @@ export function registerPluginsCli(program: Command) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let next: ClawdbotConfig = {
|
||||
let next: MoltbotConfig = {
|
||||
...cfg,
|
||||
plugins: {
|
||||
...cfg.plugins,
|
||||
@@ -353,7 +353,7 @@ export function registerPluginsCli(program: Command) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let next: ClawdbotConfig = {
|
||||
let next: MoltbotConfig = {
|
||||
...cfg,
|
||||
plugins: {
|
||||
...cfg.plugins,
|
||||
@@ -417,7 +417,7 @@ export function registerPluginsCli(program: Command) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let next: ClawdbotConfig = {
|
||||
let next: MoltbotConfig = {
|
||||
...cfg,
|
||||
plugins: {
|
||||
...cfg.plugins,
|
||||
|
||||
@@ -7,42 +7,42 @@ describe("parseCliProfileArgs", () => {
|
||||
it("leaves gateway --dev for subcommands", () => {
|
||||
const res = parseCliProfileArgs([
|
||||
"node",
|
||||
"clawdbot",
|
||||
"moltbot",
|
||||
"gateway",
|
||||
"--dev",
|
||||
"--allow-unconfigured",
|
||||
]);
|
||||
if (!res.ok) throw new Error(res.error);
|
||||
expect(res.profile).toBeNull();
|
||||
expect(res.argv).toEqual(["node", "clawdbot", "gateway", "--dev", "--allow-unconfigured"]);
|
||||
expect(res.argv).toEqual(["node", "moltbot", "gateway", "--dev", "--allow-unconfigured"]);
|
||||
});
|
||||
|
||||
it("still accepts global --dev before subcommand", () => {
|
||||
const res = parseCliProfileArgs(["node", "clawdbot", "--dev", "gateway"]);
|
||||
const res = parseCliProfileArgs(["node", "moltbot", "--dev", "gateway"]);
|
||||
if (!res.ok) throw new Error(res.error);
|
||||
expect(res.profile).toBe("dev");
|
||||
expect(res.argv).toEqual(["node", "clawdbot", "gateway"]);
|
||||
expect(res.argv).toEqual(["node", "moltbot", "gateway"]);
|
||||
});
|
||||
|
||||
it("parses --profile value and strips it", () => {
|
||||
const res = parseCliProfileArgs(["node", "clawdbot", "--profile", "work", "status"]);
|
||||
const res = parseCliProfileArgs(["node", "moltbot", "--profile", "work", "status"]);
|
||||
if (!res.ok) throw new Error(res.error);
|
||||
expect(res.profile).toBe("work");
|
||||
expect(res.argv).toEqual(["node", "clawdbot", "status"]);
|
||||
expect(res.argv).toEqual(["node", "moltbot", "status"]);
|
||||
});
|
||||
|
||||
it("rejects missing profile value", () => {
|
||||
const res = parseCliProfileArgs(["node", "clawdbot", "--profile"]);
|
||||
const res = parseCliProfileArgs(["node", "moltbot", "--profile"]);
|
||||
expect(res.ok).toBe(false);
|
||||
});
|
||||
|
||||
it("rejects combining --dev with --profile (dev first)", () => {
|
||||
const res = parseCliProfileArgs(["node", "clawdbot", "--dev", "--profile", "work", "status"]);
|
||||
const res = parseCliProfileArgs(["node", "moltbot", "--dev", "--profile", "work", "status"]);
|
||||
expect(res.ok).toBe(false);
|
||||
});
|
||||
|
||||
it("rejects combining --dev with --profile (profile first)", () => {
|
||||
const res = parseCliProfileArgs(["node", "clawdbot", "--profile", "work", "--dev", "status"]);
|
||||
const res = parseCliProfileArgs(["node", "moltbot", "--profile", "work", "--dev", "status"]);
|
||||
expect(res.ok).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -58,7 +58,7 @@ describe("applyCliProfileEnv", () => {
|
||||
const expectedStateDir = path.join("/home/peter", ".clawdbot-dev");
|
||||
expect(env.CLAWDBOT_PROFILE).toBe("dev");
|
||||
expect(env.CLAWDBOT_STATE_DIR).toBe(expectedStateDir);
|
||||
expect(env.CLAWDBOT_CONFIG_PATH).toBe(path.join(expectedStateDir, "clawdbot.json"));
|
||||
expect(env.CLAWDBOT_CONFIG_PATH).toBe(path.join(expectedStateDir, "moltbot.json"));
|
||||
expect(env.CLAWDBOT_GATEWAY_PORT).toBe("19001");
|
||||
});
|
||||
|
||||
@@ -74,65 +74,65 @@ describe("applyCliProfileEnv", () => {
|
||||
});
|
||||
expect(env.CLAWDBOT_STATE_DIR).toBe("/custom");
|
||||
expect(env.CLAWDBOT_GATEWAY_PORT).toBe("19099");
|
||||
expect(env.CLAWDBOT_CONFIG_PATH).toBe(path.join("/custom", "clawdbot.json"));
|
||||
expect(env.CLAWDBOT_CONFIG_PATH).toBe(path.join("/custom", "moltbot.json"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatCliCommand", () => {
|
||||
it("returns command unchanged when no profile is set", () => {
|
||||
expect(formatCliCommand("clawdbot doctor --fix", {})).toBe("moltbot doctor --fix");
|
||||
expect(formatCliCommand("moltbot doctor --fix", {})).toBe("moltbot doctor --fix");
|
||||
});
|
||||
|
||||
it("returns command unchanged when profile is default", () => {
|
||||
expect(formatCliCommand("clawdbot doctor --fix", { CLAWDBOT_PROFILE: "default" })).toBe(
|
||||
expect(formatCliCommand("moltbot doctor --fix", { CLAWDBOT_PROFILE: "default" })).toBe(
|
||||
"moltbot doctor --fix",
|
||||
);
|
||||
});
|
||||
|
||||
it("returns command unchanged when profile is Default (case-insensitive)", () => {
|
||||
expect(formatCliCommand("clawdbot doctor --fix", { CLAWDBOT_PROFILE: "Default" })).toBe(
|
||||
expect(formatCliCommand("moltbot doctor --fix", { CLAWDBOT_PROFILE: "Default" })).toBe(
|
||||
"moltbot doctor --fix",
|
||||
);
|
||||
});
|
||||
|
||||
it("returns command unchanged when profile is invalid", () => {
|
||||
expect(formatCliCommand("clawdbot doctor --fix", { CLAWDBOT_PROFILE: "bad profile" })).toBe(
|
||||
expect(formatCliCommand("moltbot doctor --fix", { CLAWDBOT_PROFILE: "bad profile" })).toBe(
|
||||
"moltbot doctor --fix",
|
||||
);
|
||||
});
|
||||
|
||||
it("returns command unchanged when --profile is already present", () => {
|
||||
expect(
|
||||
formatCliCommand("clawdbot --profile work doctor --fix", { CLAWDBOT_PROFILE: "work" }),
|
||||
formatCliCommand("moltbot --profile work doctor --fix", { CLAWDBOT_PROFILE: "work" }),
|
||||
).toBe("moltbot --profile work doctor --fix");
|
||||
});
|
||||
|
||||
it("returns command unchanged when --dev is already present", () => {
|
||||
expect(formatCliCommand("clawdbot --dev doctor", { CLAWDBOT_PROFILE: "dev" })).toBe(
|
||||
expect(formatCliCommand("moltbot --dev doctor", { CLAWDBOT_PROFILE: "dev" })).toBe(
|
||||
"moltbot --dev doctor",
|
||||
);
|
||||
});
|
||||
|
||||
it("inserts --profile flag when profile is set", () => {
|
||||
expect(formatCliCommand("clawdbot doctor --fix", { CLAWDBOT_PROFILE: "work" })).toBe(
|
||||
expect(formatCliCommand("moltbot doctor --fix", { CLAWDBOT_PROFILE: "work" })).toBe(
|
||||
"moltbot --profile work doctor --fix",
|
||||
);
|
||||
});
|
||||
|
||||
it("trims whitespace from profile", () => {
|
||||
expect(formatCliCommand("clawdbot doctor --fix", { CLAWDBOT_PROFILE: " jbclawd " })).toBe(
|
||||
expect(formatCliCommand("moltbot doctor --fix", { CLAWDBOT_PROFILE: " jbclawd " })).toBe(
|
||||
"moltbot --profile jbclawd doctor --fix",
|
||||
);
|
||||
});
|
||||
|
||||
it("handles command with no args after clawdbot", () => {
|
||||
expect(formatCliCommand("clawdbot", { CLAWDBOT_PROFILE: "test" })).toBe(
|
||||
it("handles command with no args after moltbot", () => {
|
||||
expect(formatCliCommand("moltbot", { CLAWDBOT_PROFILE: "test" })).toBe(
|
||||
"moltbot --profile test",
|
||||
);
|
||||
});
|
||||
|
||||
it("handles pnpm wrapper", () => {
|
||||
expect(formatCliCommand("pnpm clawdbot doctor", { CLAWDBOT_PROFILE: "work" })).toBe(
|
||||
expect(formatCliCommand("pnpm moltbot doctor", { CLAWDBOT_PROFILE: "work" })).toBe(
|
||||
"pnpm moltbot --profile work doctor",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -102,7 +102,7 @@ export function applyCliProfileEnv(params: {
|
||||
if (!env.CLAWDBOT_STATE_DIR?.trim()) env.CLAWDBOT_STATE_DIR = stateDir;
|
||||
|
||||
if (!env.CLAWDBOT_CONFIG_PATH?.trim()) {
|
||||
env.CLAWDBOT_CONFIG_PATH = path.join(stateDir, "clawdbot.json");
|
||||
env.CLAWDBOT_CONFIG_PATH = path.join(stateDir, "moltbot.json");
|
||||
}
|
||||
|
||||
if (profile === "dev" && !env.CLAWDBOT_GATEWAY_PORT?.trim()) {
|
||||
|
||||
@@ -71,9 +71,7 @@ export async function ensureConfigReady(params: {
|
||||
params.runtime.error(legacyIssues.map((issue) => ` ${error(issue)}`).join("\n"));
|
||||
}
|
||||
params.runtime.error("");
|
||||
params.runtime.error(
|
||||
`${muted("Run:")} ${commandText(formatCliCommand("clawdbot doctor --fix"))}`,
|
||||
);
|
||||
params.runtime.error(`${muted("Run:")} ${commandText(formatCliCommand("moltbot doctor --fix"))}`);
|
||||
if (!allowInvalid) {
|
||||
params.runtime.exit(1);
|
||||
}
|
||||
|
||||
@@ -8,24 +8,21 @@ import type { ProgramContext } from "./context.js";
|
||||
const CLI_NAME = resolveCliName();
|
||||
|
||||
const EXAMPLES = [
|
||||
["moltbot channels login --verbose", "Link personal WhatsApp Web and show QR + connection logs."],
|
||||
[
|
||||
"clawdbot channels login --verbose",
|
||||
"Link personal WhatsApp Web and show QR + connection logs.",
|
||||
],
|
||||
[
|
||||
'clawdbot message send --target +15555550123 --message "Hi" --json',
|
||||
'moltbot message send --target +15555550123 --message "Hi" --json',
|
||||
"Send via your web session and print JSON result.",
|
||||
],
|
||||
["clawdbot gateway --port 18789", "Run the WebSocket Gateway locally."],
|
||||
["clawdbot --dev gateway", "Run a dev Gateway (isolated state/config) on ws://127.0.0.1:19001."],
|
||||
["clawdbot gateway --force", "Kill anything bound to the default gateway port, then start it."],
|
||||
["clawdbot gateway ...", "Gateway control via WebSocket."],
|
||||
["moltbot gateway --port 18789", "Run the WebSocket Gateway locally."],
|
||||
["moltbot --dev gateway", "Run a dev Gateway (isolated state/config) on ws://127.0.0.1:19001."],
|
||||
["moltbot gateway --force", "Kill anything bound to the default gateway port, then start it."],
|
||||
["moltbot gateway ...", "Gateway control via WebSocket."],
|
||||
[
|
||||
'clawdbot agent --to +15555550123 --message "Run summary" --deliver',
|
||||
'moltbot agent --to +15555550123 --message "Run summary" --deliver',
|
||||
"Talk directly to the agent using the Gateway; optionally send the WhatsApp reply.",
|
||||
],
|
||||
[
|
||||
'clawdbot message send --channel telegram --target @mychat --message "Hi"',
|
||||
'moltbot message send --channel telegram --target @mychat --message "Hi"',
|
||||
"Send via your Telegram bot.",
|
||||
],
|
||||
] as const;
|
||||
|
||||
@@ -51,19 +51,19 @@ export function registerAgentCommands(program: Command, args: { agentChannelOpti
|
||||
`
|
||||
${theme.heading("Examples:")}
|
||||
${formatHelpExamples([
|
||||
['clawdbot agent --to +15555550123 --message "status update"', "Start a new session."],
|
||||
['clawdbot agent --agent ops --message "Summarize logs"', "Use a specific agent."],
|
||||
['moltbot agent --to +15555550123 --message "status update"', "Start a new session."],
|
||||
['moltbot agent --agent ops --message "Summarize logs"', "Use a specific agent."],
|
||||
[
|
||||
'clawdbot agent --session-id 1234 --message "Summarize inbox" --thinking medium',
|
||||
'moltbot agent --session-id 1234 --message "Summarize inbox" --thinking medium',
|
||||
"Target a session with explicit thinking level.",
|
||||
],
|
||||
[
|
||||
'clawdbot agent --to +15555550123 --message "Trace logs" --verbose on --json',
|
||||
'moltbot agent --to +15555550123 --message "Trace logs" --verbose on --json',
|
||||
"Enable verbose logging and JSON output.",
|
||||
],
|
||||
['clawdbot agent --to +15555550123 --message "Summon reply" --deliver', "Deliver reply."],
|
||||
['moltbot agent --to +15555550123 --message "Summon reply" --deliver', "Deliver reply."],
|
||||
[
|
||||
'clawdbot agent --agent ops --message "Generate report" --deliver --reply-channel slack --reply-to "#reports"',
|
||||
'moltbot agent --agent ops --message "Generate report" --deliver --reply-channel slack --reply-to "#reports"',
|
||||
"Send reply to a different channel/target.",
|
||||
],
|
||||
])}
|
||||
@@ -155,11 +155,11 @@ ${theme.muted("Docs:")} ${formatDocsLink("/cli/agent", "docs.molt.bot/cli/agent"
|
||||
`
|
||||
${theme.heading("Examples:")}
|
||||
${formatHelpExamples([
|
||||
['clawdbot agents set-identity --agent main --name "Clawd" --emoji "🦞"', "Set name + emoji."],
|
||||
["clawdbot agents set-identity --agent main --avatar avatars/clawd.png", "Set avatar path."],
|
||||
["clawdbot agents set-identity --workspace ~/clawd --from-identity", "Load from IDENTITY.md."],
|
||||
['moltbot agents set-identity --agent main --name "Clawd" --emoji "🦞"', "Set name + emoji."],
|
||||
["moltbot agents set-identity --agent main --avatar avatars/clawd.png", "Set avatar path."],
|
||||
["moltbot agents set-identity --workspace ~/clawd --from-identity", "Load from IDENTITY.md."],
|
||||
[
|
||||
"clawdbot agents set-identity --identity-file ~/clawd/IDENTITY.md --agent main",
|
||||
"moltbot agents set-identity --identity-file ~/clawd/IDENTITY.md --agent main",
|
||||
"Use a specific IDENTITY.md.",
|
||||
],
|
||||
])}
|
||||
|
||||
@@ -31,17 +31,17 @@ export function registerMessageCommands(program: Command, ctx: ProgramContext) {
|
||||
`
|
||||
${theme.heading("Examples:")}
|
||||
${formatHelpExamples([
|
||||
['clawdbot message send --target +15555550123 --message "Hi"', "Send a text message."],
|
||||
['moltbot message send --target +15555550123 --message "Hi"', "Send a text message."],
|
||||
[
|
||||
'clawdbot message send --target +15555550123 --message "Hi" --media photo.jpg',
|
||||
'moltbot message send --target +15555550123 --message "Hi" --media photo.jpg',
|
||||
"Send a message with media.",
|
||||
],
|
||||
[
|
||||
'clawdbot message poll --channel discord --target channel:123 --poll-question "Snack?" --poll-option Pizza --poll-option Sushi',
|
||||
'moltbot message poll --channel discord --target channel:123 --poll-question "Snack?" --poll-option Pizza --poll-option Sushi',
|
||||
"Create a Discord poll.",
|
||||
],
|
||||
[
|
||||
'clawdbot message react --channel discord --target 123 --message-id 456 --emoji "✅"',
|
||||
'moltbot message react --channel discord --target 123 --message-id 456 --emoji "✅"',
|
||||
"React to a message.",
|
||||
],
|
||||
])}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { runCommandWithRuntime } from "../cli-utils.js";
|
||||
export function registerSetupCommand(program: Command) {
|
||||
program
|
||||
.command("setup")
|
||||
.description("Initialize ~/.clawdbot/clawdbot.json and the agent workspace")
|
||||
.description("Initialize ~/.clawdbot/moltbot.json and the agent workspace")
|
||||
.addHelpText(
|
||||
"after",
|
||||
() =>
|
||||
|
||||
@@ -39,15 +39,15 @@ export function registerStatusHealthSessionsCommands(program: Command) {
|
||||
"after",
|
||||
() =>
|
||||
`\n${theme.heading("Examples:")}\n${formatHelpExamples([
|
||||
["clawdbot status", "Show channel health + session summary."],
|
||||
["clawdbot status --all", "Full diagnosis (read-only)."],
|
||||
["clawdbot status --json", "Machine-readable output."],
|
||||
["clawdbot status --usage", "Show model provider usage/quota snapshots."],
|
||||
["moltbot status", "Show channel health + session summary."],
|
||||
["moltbot status --all", "Full diagnosis (read-only)."],
|
||||
["moltbot status --json", "Machine-readable output."],
|
||||
["moltbot status --usage", "Show model provider usage/quota snapshots."],
|
||||
[
|
||||
"clawdbot status --deep",
|
||||
"moltbot status --deep",
|
||||
"Run channel probes (WA + Telegram + Discord + Slack + Signal).",
|
||||
],
|
||||
["clawdbot status --deep --timeout 5000", "Tighten probe timeout."],
|
||||
["moltbot status --deep --timeout 5000", "Tighten probe timeout."],
|
||||
])}`,
|
||||
)
|
||||
.addHelpText(
|
||||
@@ -119,10 +119,10 @@ export function registerStatusHealthSessionsCommands(program: Command) {
|
||||
"after",
|
||||
() =>
|
||||
`\n${theme.heading("Examples:")}\n${formatHelpExamples([
|
||||
["clawdbot sessions", "List all sessions."],
|
||||
["clawdbot sessions --active 120", "Only last 2 hours."],
|
||||
["clawdbot sessions --json", "Machine-readable output."],
|
||||
["clawdbot sessions --store ./tmp/sessions.json", "Use a specific session store."],
|
||||
["moltbot sessions", "List all sessions."],
|
||||
["moltbot sessions --active 120", "Only last 2 hours."],
|
||||
["moltbot sessions --json", "Machine-readable output."],
|
||||
["moltbot sessions --store ./tmp/sessions.json", "Use a specific session store."],
|
||||
])}\n\n${theme.muted(
|
||||
"Shows token usage per session when the agent reports it; set agents.defaults.contextTokens to see % of your model window.",
|
||||
)}`,
|
||||
|
||||
@@ -42,7 +42,7 @@ describe("registerSubCliCommands", () => {
|
||||
});
|
||||
|
||||
it("registers only the primary placeholder and dispatches", async () => {
|
||||
process.argv = ["node", "clawdbot", "acp"];
|
||||
process.argv = ["node", "moltbot", "acp"];
|
||||
const program = new Command();
|
||||
registerSubCliCommands(program, process.argv);
|
||||
|
||||
@@ -55,7 +55,7 @@ describe("registerSubCliCommands", () => {
|
||||
});
|
||||
|
||||
it("registers placeholders for all subcommands when no primary", () => {
|
||||
process.argv = ["node", "clawdbot"];
|
||||
process.argv = ["node", "moltbot"];
|
||||
const program = new Command();
|
||||
registerSubCliCommands(program, process.argv);
|
||||
|
||||
@@ -66,9 +66,9 @@ describe("registerSubCliCommands", () => {
|
||||
});
|
||||
|
||||
it("re-parses argv for lazy subcommands", async () => {
|
||||
process.argv = ["node", "clawdbot", "nodes", "list"];
|
||||
process.argv = ["node", "moltbot", "nodes", "list"];
|
||||
const program = new Command();
|
||||
program.name("clawdbot");
|
||||
program.name("moltbot");
|
||||
registerSubCliCommands(program, process.argv);
|
||||
|
||||
expect(program.commands.map((cmd) => cmd.name())).toEqual(["nodes"]);
|
||||
@@ -80,9 +80,9 @@ describe("registerSubCliCommands", () => {
|
||||
});
|
||||
|
||||
it("replaces placeholder when registering a subcommand by name", async () => {
|
||||
process.argv = ["node", "clawdbot", "acp", "--help"];
|
||||
process.argv = ["node", "moltbot", "acp", "--help"];
|
||||
const program = new Command();
|
||||
program.name("clawdbot");
|
||||
program.name("moltbot");
|
||||
registerSubCliCommands(program, process.argv);
|
||||
|
||||
await registerSubCliByName(program, "acp");
|
||||
@@ -90,7 +90,7 @@ describe("registerSubCliCommands", () => {
|
||||
const names = program.commands.map((cmd) => cmd.name());
|
||||
expect(names.filter((name) => name === "acp")).toHaveLength(1);
|
||||
|
||||
await program.parseAsync(["node", "clawdbot", "acp"], { from: "user" });
|
||||
await program.parseAsync(["node", "moltbot", "acp"], { from: "user" });
|
||||
expect(registerAcpCli).toHaveBeenCalledTimes(1);
|
||||
expect(acpAction).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { Command } from "commander";
|
||||
import type { ClawdbotConfig } from "../../config/config.js";
|
||||
import type { MoltbotConfig } from "../../config/config.js";
|
||||
import { isTruthyEnvValue } from "../../infra/env.js";
|
||||
import { buildParseArgv, getPrimaryCommand, hasHelpOrVersion } from "../argv.js";
|
||||
import { resolveActionArgs } from "./helpers.js";
|
||||
@@ -22,7 +22,7 @@ const shouldEagerRegisterSubcommands = (_argv: string[]) => {
|
||||
return isTruthyEnvValue(process.env.CLAWDBOT_DISABLE_LAZY_SUBCOMMANDS);
|
||||
};
|
||||
|
||||
const loadConfig = async (): Promise<ClawdbotConfig> => {
|
||||
const loadConfig = async (): Promise<MoltbotConfig> => {
|
||||
const mod = await import("../../config/config.js");
|
||||
return mod.loadConfig();
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url";
|
||||
import { loadDotEnv } from "../infra/dotenv.js";
|
||||
import { normalizeEnv } from "../infra/env.js";
|
||||
import { isMainModule } from "../infra/is-main.js";
|
||||
import { ensureClawdbotCliOnPath } from "../infra/path-env.js";
|
||||
import { ensureMoltbotCliOnPath } from "../infra/path-env.js";
|
||||
import { assertSupportedRuntime } from "../infra/runtime-guard.js";
|
||||
import { formatUncaughtError } from "../infra/errors.js";
|
||||
import { installUnhandledRejectionHandler } from "../infra/unhandled-rejections.js";
|
||||
@@ -27,7 +27,7 @@ export async function runCli(argv: string[] = process.argv) {
|
||||
const normalizedArgv = stripWindowsNodeExec(argv);
|
||||
loadDotEnv({ quiet: true });
|
||||
normalizeEnv();
|
||||
ensureClawdbotCliOnPath();
|
||||
ensureMoltbotCliOnPath();
|
||||
|
||||
// Enforce the minimum supported runtime before doing any work.
|
||||
assertSupportedRuntime();
|
||||
@@ -45,7 +45,7 @@ export async function runCli(argv: string[] = process.argv) {
|
||||
installUnhandledRejectionHandler();
|
||||
|
||||
process.on("uncaughtException", (error) => {
|
||||
console.error("[clawdbot] Uncaught exception:", formatUncaughtError(error));
|
||||
console.error("[moltbot] Uncaught exception:", formatUncaughtError(error));
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
|
||||
@@ -15,30 +15,30 @@ type CommandOptions = Record<string, unknown>;
|
||||
|
||||
const SANDBOX_EXAMPLES = {
|
||||
main: [
|
||||
["clawdbot sandbox list", "List all sandbox containers."],
|
||||
["clawdbot sandbox list --browser", "List only browser containers."],
|
||||
["clawdbot sandbox recreate --all", "Recreate all containers."],
|
||||
["clawdbot sandbox recreate --session main", "Recreate a specific session."],
|
||||
["clawdbot sandbox recreate --agent mybot", "Recreate agent containers."],
|
||||
["clawdbot sandbox explain", "Explain effective sandbox config."],
|
||||
["moltbot sandbox list", "List all sandbox containers."],
|
||||
["moltbot sandbox list --browser", "List only browser containers."],
|
||||
["moltbot sandbox recreate --all", "Recreate all containers."],
|
||||
["moltbot sandbox recreate --session main", "Recreate a specific session."],
|
||||
["moltbot sandbox recreate --agent mybot", "Recreate agent containers."],
|
||||
["moltbot sandbox explain", "Explain effective sandbox config."],
|
||||
],
|
||||
list: [
|
||||
["clawdbot sandbox list", "List all sandbox containers."],
|
||||
["clawdbot sandbox list --browser", "List only browser containers."],
|
||||
["clawdbot sandbox list --json", "JSON output."],
|
||||
["moltbot sandbox list", "List all sandbox containers."],
|
||||
["moltbot sandbox list --browser", "List only browser containers."],
|
||||
["moltbot sandbox list --json", "JSON output."],
|
||||
],
|
||||
recreate: [
|
||||
["clawdbot sandbox recreate --all", "Recreate all containers."],
|
||||
["clawdbot sandbox recreate --session main", "Recreate a specific session."],
|
||||
["clawdbot sandbox recreate --agent mybot", "Recreate a specific agent (includes sub-agents)."],
|
||||
["clawdbot sandbox recreate --browser --all", "Recreate only browser containers."],
|
||||
["clawdbot sandbox recreate --all --force", "Skip confirmation."],
|
||||
["moltbot sandbox recreate --all", "Recreate all containers."],
|
||||
["moltbot sandbox recreate --session main", "Recreate a specific session."],
|
||||
["moltbot sandbox recreate --agent mybot", "Recreate a specific agent (includes sub-agents)."],
|
||||
["moltbot sandbox recreate --browser --all", "Recreate only browser containers."],
|
||||
["moltbot sandbox recreate --all --force", "Skip confirmation."],
|
||||
],
|
||||
explain: [
|
||||
["clawdbot sandbox explain", "Show effective sandbox config."],
|
||||
["clawdbot sandbox explain --session agent:main:main", "Explain a specific session."],
|
||||
["clawdbot sandbox explain --agent work", "Explain an agent sandbox."],
|
||||
["clawdbot sandbox explain --json", "JSON output."],
|
||||
["moltbot sandbox explain", "Show effective sandbox config."],
|
||||
["moltbot sandbox explain --session agent:main:main", "Explain a specific session."],
|
||||
["moltbot sandbox explain --agent work", "Explain an agent sandbox."],
|
||||
["moltbot sandbox explain --json", "JSON output."],
|
||||
],
|
||||
} as const;
|
||||
|
||||
|
||||
@@ -66,12 +66,12 @@ export function registerSecurityCli(program: Command) {
|
||||
const muted = (text: string) => (rich ? theme.muted(text) : text);
|
||||
|
||||
const lines: string[] = [];
|
||||
lines.push(heading("Clawdbot security audit"));
|
||||
lines.push(heading("Moltbot security audit"));
|
||||
lines.push(muted(`Summary: ${formatSummary(report.summary)}`));
|
||||
lines.push(muted(`Run deeper: ${formatCliCommand("clawdbot security audit --deep")}`));
|
||||
lines.push(muted(`Run deeper: ${formatCliCommand("moltbot security audit --deep")}`));
|
||||
|
||||
if (opts.fix) {
|
||||
lines.push(muted(`Fix: ${formatCliCommand("clawdbot security audit --fix")}`));
|
||||
lines.push(muted(`Fix: ${formatCliCommand("moltbot security audit --fix")}`));
|
||||
if (!fixResult) {
|
||||
lines.push(muted("Fixes: failed to apply (unexpected error)"));
|
||||
} else if (
|
||||
|
||||
@@ -92,7 +92,7 @@ export function formatSkillsList(report: SkillStatusReport, opts: SkillsListOpti
|
||||
|
||||
if (skills.length === 0) {
|
||||
const message = opts.eligible
|
||||
? `No eligible skills found. Run \`${formatCliCommand("clawdbot skills list")}\` to see all skills.`
|
||||
? `No eligible skills found. Run \`${formatCliCommand("moltbot skills list")}\` to see all skills.`
|
||||
: "No skills found.";
|
||||
return appendClawdHubHint(message, opts.json);
|
||||
}
|
||||
@@ -150,7 +150,7 @@ export function formatSkillInfo(
|
||||
return JSON.stringify({ error: "not found", skill: skillName }, null, 2);
|
||||
}
|
||||
return appendClawdHubHint(
|
||||
`Skill "${skillName}" not found. Run \`${formatCliCommand("clawdbot skills list")}\` to see available skills.`,
|
||||
`Skill "${skillName}" not found. Run \`${formatCliCommand("moltbot skills list")}\` to see available skills.`,
|
||||
opts.json,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const DEFAULT_TAGLINE = "All your chats, one Clawdbot.";
|
||||
const DEFAULT_TAGLINE = "All your chats, one Moltbot.";
|
||||
|
||||
const HOLIDAY_TAGLINES = {
|
||||
newYear:
|
||||
|
||||
@@ -22,8 +22,8 @@ vi.mock("../infra/update-runner.js", () => ({
|
||||
runGatewayUpdate: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../infra/clawdbot-root.js", () => ({
|
||||
resolveClawdbotPackageRoot: vi.fn(),
|
||||
vi.mock("../infra/moltbot-root.js", () => ({
|
||||
resolveMoltbotPackageRoot: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock("../config/config.js", () => ({
|
||||
@@ -88,12 +88,12 @@ describe("update-cli", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
vi.clearAllMocks();
|
||||
const { resolveClawdbotPackageRoot } = await import("../infra/clawdbot-root.js");
|
||||
const { resolveMoltbotPackageRoot } = await import("../infra/moltbot-root.js");
|
||||
const { readConfigFileSnapshot } = await import("../config/config.js");
|
||||
const { checkUpdateStatus, fetchNpmTagVersion, resolveNpmChannelTag } =
|
||||
await import("../infra/update-check.js");
|
||||
const { runCommandWithTimeout } = await import("../process/exec.js");
|
||||
vi.mocked(resolveClawdbotPackageRoot).mockResolvedValue(process.cwd());
|
||||
vi.mocked(resolveMoltbotPackageRoot).mockResolvedValue(process.cwd());
|
||||
vi.mocked(readConfigFileSnapshot).mockResolvedValue(baseSnapshot);
|
||||
vi.mocked(fetchNpmTagVersion).mockResolvedValue({
|
||||
tag: "latest",
|
||||
@@ -185,7 +185,7 @@ describe("update-cli", () => {
|
||||
await updateStatusCommand({ json: false });
|
||||
|
||||
const logs = vi.mocked(defaultRuntime.log).mock.calls.map((call) => call[0]);
|
||||
expect(logs.join("\n")).toContain("Clawdbot update status");
|
||||
expect(logs.join("\n")).toContain("Moltbot update status");
|
||||
});
|
||||
|
||||
it("updateStatusCommand emits JSON", async () => {
|
||||
@@ -218,20 +218,20 @@ describe("update-cli", () => {
|
||||
});
|
||||
|
||||
it("defaults to stable channel for package installs when unset", async () => {
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-update-"));
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-update-"));
|
||||
try {
|
||||
await fs.writeFile(
|
||||
path.join(tempDir, "package.json"),
|
||||
JSON.stringify({ name: "clawdbot", version: "1.0.0" }),
|
||||
JSON.stringify({ name: "moltbot", version: "1.0.0" }),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
const { resolveClawdbotPackageRoot } = await import("../infra/clawdbot-root.js");
|
||||
const { resolveMoltbotPackageRoot } = await import("../infra/moltbot-root.js");
|
||||
const { runGatewayUpdate } = await import("../infra/update-runner.js");
|
||||
const { checkUpdateStatus } = await import("../infra/update-check.js");
|
||||
const { updateCommand } = await import("./update-cli.js");
|
||||
|
||||
vi.mocked(resolveClawdbotPackageRoot).mockResolvedValue(tempDir);
|
||||
vi.mocked(resolveMoltbotPackageRoot).mockResolvedValue(tempDir);
|
||||
vi.mocked(checkUpdateStatus).mockResolvedValue({
|
||||
root: tempDir,
|
||||
installKind: "package",
|
||||
@@ -283,22 +283,22 @@ describe("update-cli", () => {
|
||||
});
|
||||
|
||||
it("falls back to latest when beta tag is older than release", async () => {
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-update-"));
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-update-"));
|
||||
try {
|
||||
await fs.writeFile(
|
||||
path.join(tempDir, "package.json"),
|
||||
JSON.stringify({ name: "clawdbot", version: "1.0.0" }),
|
||||
JSON.stringify({ name: "moltbot", version: "1.0.0" }),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
const { resolveClawdbotPackageRoot } = await import("../infra/clawdbot-root.js");
|
||||
const { resolveMoltbotPackageRoot } = await import("../infra/moltbot-root.js");
|
||||
const { readConfigFileSnapshot } = await import("../config/config.js");
|
||||
const { resolveNpmChannelTag } = await import("../infra/update-check.js");
|
||||
const { runGatewayUpdate } = await import("../infra/update-runner.js");
|
||||
const { updateCommand } = await import("./update-cli.js");
|
||||
const { checkUpdateStatus } = await import("../infra/update-check.js");
|
||||
|
||||
vi.mocked(resolveClawdbotPackageRoot).mockResolvedValue(tempDir);
|
||||
vi.mocked(resolveMoltbotPackageRoot).mockResolvedValue(tempDir);
|
||||
vi.mocked(readConfigFileSnapshot).mockResolvedValue({
|
||||
...baseSnapshot,
|
||||
config: { update: { channel: "beta" } },
|
||||
@@ -336,19 +336,19 @@ describe("update-cli", () => {
|
||||
});
|
||||
|
||||
it("honors --tag override", async () => {
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-update-"));
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-update-"));
|
||||
try {
|
||||
await fs.writeFile(
|
||||
path.join(tempDir, "package.json"),
|
||||
JSON.stringify({ name: "clawdbot", version: "1.0.0" }),
|
||||
JSON.stringify({ name: "moltbot", version: "1.0.0" }),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
const { resolveClawdbotPackageRoot } = await import("../infra/clawdbot-root.js");
|
||||
const { resolveMoltbotPackageRoot } = await import("../infra/moltbot-root.js");
|
||||
const { runGatewayUpdate } = await import("../infra/update-runner.js");
|
||||
const { updateCommand } = await import("./update-cli.js");
|
||||
|
||||
vi.mocked(resolveClawdbotPackageRoot).mockResolvedValue(tempDir);
|
||||
vi.mocked(resolveMoltbotPackageRoot).mockResolvedValue(tempDir);
|
||||
vi.mocked(runGatewayUpdate).mockResolvedValue({
|
||||
status: "ok",
|
||||
mode: "npm",
|
||||
@@ -514,23 +514,23 @@ describe("update-cli", () => {
|
||||
});
|
||||
|
||||
it("requires confirmation on downgrade when non-interactive", async () => {
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-update-"));
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-update-"));
|
||||
try {
|
||||
setTty(false);
|
||||
await fs.writeFile(
|
||||
path.join(tempDir, "package.json"),
|
||||
JSON.stringify({ name: "clawdbot", version: "2.0.0" }),
|
||||
JSON.stringify({ name: "moltbot", version: "2.0.0" }),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
const { resolveClawdbotPackageRoot } = await import("../infra/clawdbot-root.js");
|
||||
const { resolveMoltbotPackageRoot } = await import("../infra/moltbot-root.js");
|
||||
const { resolveNpmChannelTag } = await import("../infra/update-check.js");
|
||||
const { runGatewayUpdate } = await import("../infra/update-runner.js");
|
||||
const { defaultRuntime } = await import("../runtime.js");
|
||||
const { updateCommand } = await import("./update-cli.js");
|
||||
const { checkUpdateStatus } = await import("../infra/update-check.js");
|
||||
|
||||
vi.mocked(resolveClawdbotPackageRoot).mockResolvedValue(tempDir);
|
||||
vi.mocked(resolveMoltbotPackageRoot).mockResolvedValue(tempDir);
|
||||
vi.mocked(checkUpdateStatus).mockResolvedValue({
|
||||
root: tempDir,
|
||||
installKind: "package",
|
||||
@@ -567,23 +567,23 @@ describe("update-cli", () => {
|
||||
});
|
||||
|
||||
it("allows downgrade with --yes in non-interactive mode", async () => {
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-update-"));
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-update-"));
|
||||
try {
|
||||
setTty(false);
|
||||
await fs.writeFile(
|
||||
path.join(tempDir, "package.json"),
|
||||
JSON.stringify({ name: "clawdbot", version: "2.0.0" }),
|
||||
JSON.stringify({ name: "moltbot", version: "2.0.0" }),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
const { resolveClawdbotPackageRoot } = await import("../infra/clawdbot-root.js");
|
||||
const { resolveMoltbotPackageRoot } = await import("../infra/moltbot-root.js");
|
||||
const { resolveNpmChannelTag } = await import("../infra/update-check.js");
|
||||
const { runGatewayUpdate } = await import("../infra/update-runner.js");
|
||||
const { defaultRuntime } = await import("../runtime.js");
|
||||
const { updateCommand } = await import("./update-cli.js");
|
||||
const { checkUpdateStatus } = await import("../infra/update-check.js");
|
||||
|
||||
vi.mocked(resolveClawdbotPackageRoot).mockResolvedValue(tempDir);
|
||||
vi.mocked(resolveMoltbotPackageRoot).mockResolvedValue(tempDir);
|
||||
vi.mocked(checkUpdateStatus).mockResolvedValue({
|
||||
root: tempDir,
|
||||
installKind: "package",
|
||||
@@ -636,7 +636,7 @@ describe("update-cli", () => {
|
||||
});
|
||||
|
||||
it("updateWizardCommand offers dev checkout and forwards selections", async () => {
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-update-wizard-"));
|
||||
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-update-wizard-"));
|
||||
const previousGitDir = process.env.CLAWDBOT_GIT_DIR;
|
||||
try {
|
||||
setTty(true);
|
||||
|
||||
@@ -5,7 +5,7 @@ import path from "node:path";
|
||||
import type { Command } from "commander";
|
||||
|
||||
import { readConfigFileSnapshot, writeConfigFile } from "../config/config.js";
|
||||
import { resolveClawdbotPackageRoot } from "../infra/clawdbot-root.js";
|
||||
import { resolveMoltbotPackageRoot } from "../infra/moltbot-root.js";
|
||||
import {
|
||||
checkUpdateStatus,
|
||||
compareSemverStrings,
|
||||
@@ -81,7 +81,6 @@ const STEP_LABELS: Record<string, string> = {
|
||||
"deps install": "Installing dependencies",
|
||||
build: "Building",
|
||||
"ui:build": "Building UI",
|
||||
"clawdbot doctor": "Running doctor checks",
|
||||
"moltbot doctor": "Running doctor checks",
|
||||
"git rev-parse HEAD (after)": "Verifying update",
|
||||
"global update": "Updating via package manager",
|
||||
@@ -113,16 +112,16 @@ const UPDATE_QUIPS = [
|
||||
|
||||
const MAX_LOG_CHARS = 8000;
|
||||
const DEFAULT_PACKAGE_NAME = "moltbot";
|
||||
const CORE_PACKAGE_NAMES = new Set([DEFAULT_PACKAGE_NAME, "clawdbot"]);
|
||||
const CORE_PACKAGE_NAMES = new Set([DEFAULT_PACKAGE_NAME, "moltbot"]);
|
||||
const CLI_NAME = resolveCliName();
|
||||
const CLAWDBOT_REPO_URL = "https://github.com/clawdbot/clawdbot.git";
|
||||
const DEFAULT_GIT_DIR = path.join(os.homedir(), "clawdbot");
|
||||
const CLAWDBOT_REPO_URL = "https://github.com/moltbot/moltbot.git";
|
||||
const DEFAULT_GIT_DIR = path.join(os.homedir(), "moltbot");
|
||||
|
||||
function normalizeTag(value?: string | null): string | null {
|
||||
if (!value) return null;
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed) return null;
|
||||
if (trimmed.startsWith("clawdbot@")) return trimmed.slice("clawdbot@".length);
|
||||
if (trimmed.startsWith("moltbot@")) return trimmed.slice("moltbot@".length);
|
||||
if (trimmed.startsWith(`${DEFAULT_PACKAGE_NAME}@`)) {
|
||||
return trimmed.slice(`${DEFAULT_PACKAGE_NAME}@`.length);
|
||||
}
|
||||
@@ -272,7 +271,7 @@ async function ensureGitCheckout(params: {
|
||||
const empty = await isEmptyDir(params.dir);
|
||||
if (!empty) {
|
||||
throw new Error(
|
||||
`CLAWDBOT_GIT_DIR points at a non-git directory: ${params.dir}. Set CLAWDBOT_GIT_DIR to an empty folder or a clawdbot checkout.`,
|
||||
`CLAWDBOT_GIT_DIR points at a non-git directory: ${params.dir}. Set CLAWDBOT_GIT_DIR to an empty folder or a moltbot checkout.`,
|
||||
);
|
||||
}
|
||||
return await runUpdateStep({
|
||||
@@ -337,7 +336,7 @@ export async function updateStatusCommand(opts: UpdateStatusOptions): Promise<vo
|
||||
}
|
||||
|
||||
const root =
|
||||
(await resolveClawdbotPackageRoot({
|
||||
(await resolveMoltbotPackageRoot({
|
||||
moduleUrl: import.meta.url,
|
||||
argv1: process.argv[1],
|
||||
cwd: process.cwd(),
|
||||
@@ -412,7 +411,7 @@ export async function updateStatusCommand(opts: UpdateStatusOptions): Promise<vo
|
||||
},
|
||||
];
|
||||
|
||||
defaultRuntime.log(theme.heading("Clawdbot update status"));
|
||||
defaultRuntime.log(theme.heading("Moltbot update status"));
|
||||
defaultRuntime.log("");
|
||||
defaultRuntime.log(
|
||||
renderTable({
|
||||
@@ -577,7 +576,7 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise<void> {
|
||||
}
|
||||
|
||||
const root =
|
||||
(await resolveClawdbotPackageRoot({
|
||||
(await resolveMoltbotPackageRoot({
|
||||
moduleUrl: import.meta.url,
|
||||
argv1: process.argv[1],
|
||||
cwd: process.cwd(),
|
||||
@@ -686,7 +685,7 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise<void> {
|
||||
const showProgress = !opts.json && process.stdout.isTTY;
|
||||
|
||||
if (!opts.json) {
|
||||
defaultRuntime.log(theme.heading("Updating Clawdbot..."));
|
||||
defaultRuntime.log(theme.heading("Updating Moltbot..."));
|
||||
defaultRuntime.log("");
|
||||
}
|
||||
|
||||
@@ -824,12 +823,12 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise<void> {
|
||||
if (result.reason === "not-git-install") {
|
||||
defaultRuntime.log(
|
||||
theme.warn(
|
||||
`Skipped: this Clawdbot install isn't a git checkout, and the package manager couldn't be detected. Update via your package manager, then run \`${replaceCliName(formatCliCommand("clawdbot doctor"), CLI_NAME)}\` and \`${replaceCliName(formatCliCommand("clawdbot gateway restart"), CLI_NAME)}\`.`,
|
||||
`Skipped: this Moltbot install isn't a git checkout, and the package manager couldn't be detected. Update via your package manager, then run \`${replaceCliName(formatCliCommand("moltbot doctor"), CLI_NAME)}\` and \`${replaceCliName(formatCliCommand("moltbot gateway restart"), CLI_NAME)}\`.`,
|
||||
),
|
||||
);
|
||||
defaultRuntime.log(
|
||||
theme.muted(
|
||||
`Examples: \`${replaceCliName("npm i -g clawdbot@latest", CLI_NAME)}\` or \`${replaceCliName("pnpm add -g clawdbot@latest", CLI_NAME)}\``,
|
||||
`Examples: \`${replaceCliName("npm i -g moltbot@latest", CLI_NAME)}\` or \`${replaceCliName("pnpm add -g moltbot@latest", CLI_NAME)}\``,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -946,7 +945,7 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise<void> {
|
||||
defaultRuntime.log(theme.warn(`Daemon restart failed: ${String(err)}`));
|
||||
defaultRuntime.log(
|
||||
theme.muted(
|
||||
`You may need to restart the service manually: ${replaceCliName(formatCliCommand("clawdbot gateway restart"), CLI_NAME)}`,
|
||||
`You may need to restart the service manually: ${replaceCliName(formatCliCommand("moltbot gateway restart"), CLI_NAME)}`,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -956,13 +955,13 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise<void> {
|
||||
if (result.mode === "npm" || result.mode === "pnpm") {
|
||||
defaultRuntime.log(
|
||||
theme.muted(
|
||||
`Tip: Run \`${replaceCliName(formatCliCommand("clawdbot doctor"), CLI_NAME)}\`, then \`${replaceCliName(formatCliCommand("clawdbot gateway restart"), CLI_NAME)}\` to apply updates to a running gateway.`,
|
||||
`Tip: Run \`${replaceCliName(formatCliCommand("moltbot doctor"), CLI_NAME)}\`, then \`${replaceCliName(formatCliCommand("moltbot gateway restart"), CLI_NAME)}\` to apply updates to a running gateway.`,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
defaultRuntime.log(
|
||||
theme.muted(
|
||||
`Tip: Run \`${replaceCliName(formatCliCommand("clawdbot gateway restart"), CLI_NAME)}\` to apply updates to a running gateway.`,
|
||||
`Tip: Run \`${replaceCliName(formatCliCommand("moltbot gateway restart"), CLI_NAME)}\` to apply updates to a running gateway.`,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -976,7 +975,7 @@ export async function updateCommand(opts: UpdateCommandOptions): Promise<void> {
|
||||
export async function updateWizardCommand(opts: UpdateWizardOptions = {}): Promise<void> {
|
||||
if (!process.stdin.isTTY) {
|
||||
defaultRuntime.error(
|
||||
"Update wizard requires a TTY. Use `clawdbot update --channel <stable|beta|dev>` instead.",
|
||||
"Update wizard requires a TTY. Use `moltbot update --channel <stable|beta|dev>` instead.",
|
||||
);
|
||||
defaultRuntime.exit(1);
|
||||
return;
|
||||
@@ -990,7 +989,7 @@ export async function updateWizardCommand(opts: UpdateWizardOptions = {}): Promi
|
||||
}
|
||||
|
||||
const root =
|
||||
(await resolveClawdbotPackageRoot({
|
||||
(await resolveMoltbotPackageRoot({
|
||||
moduleUrl: import.meta.url,
|
||||
argv1: process.argv[1],
|
||||
cwd: process.cwd(),
|
||||
@@ -1067,7 +1066,7 @@ export async function updateWizardCommand(opts: UpdateWizardOptions = {}): Promi
|
||||
const empty = await isEmptyDir(gitDir);
|
||||
if (!empty) {
|
||||
defaultRuntime.error(
|
||||
`CLAWDBOT_GIT_DIR points at a non-git directory: ${gitDir}. Set CLAWDBOT_GIT_DIR to an empty folder or a clawdbot checkout.`,
|
||||
`CLAWDBOT_GIT_DIR points at a non-git directory: ${gitDir}. Set CLAWDBOT_GIT_DIR to an empty folder or a moltbot checkout.`,
|
||||
);
|
||||
defaultRuntime.exit(1);
|
||||
return;
|
||||
@@ -1112,7 +1111,7 @@ export async function updateWizardCommand(opts: UpdateWizardOptions = {}): Promi
|
||||
export function registerUpdateCli(program: Command) {
|
||||
const update = program
|
||||
.command("update")
|
||||
.description("Update Clawdbot to the latest version")
|
||||
.description("Update Moltbot to the latest version")
|
||||
.option("--json", "Output result as JSON", false)
|
||||
.option("--no-restart", "Skip restarting the gateway service after a successful update")
|
||||
.option("--channel <stable|beta|dev>", "Persist update channel (git + npm)")
|
||||
@@ -1121,15 +1120,15 @@ export function registerUpdateCli(program: Command) {
|
||||
.option("--yes", "Skip confirmation prompts (non-interactive)", false)
|
||||
.addHelpText("after", () => {
|
||||
const examples = [
|
||||
["clawdbot update", "Update a source checkout (git)"],
|
||||
["clawdbot update --channel beta", "Switch to beta channel (git + npm)"],
|
||||
["clawdbot update --channel dev", "Switch to dev channel (git + npm)"],
|
||||
["clawdbot update --tag beta", "One-off update to a dist-tag or version"],
|
||||
["clawdbot update --no-restart", "Update without restarting the service"],
|
||||
["clawdbot update --json", "Output result as JSON"],
|
||||
["clawdbot update --yes", "Non-interactive (accept downgrade prompts)"],
|
||||
["clawdbot update wizard", "Interactive update wizard"],
|
||||
["clawdbot --update", "Shorthand for clawdbot update"],
|
||||
["moltbot update", "Update a source checkout (git)"],
|
||||
["moltbot update --channel beta", "Switch to beta channel (git + npm)"],
|
||||
["moltbot update --channel dev", "Switch to dev channel (git + npm)"],
|
||||
["moltbot update --tag beta", "One-off update to a dist-tag or version"],
|
||||
["moltbot update --no-restart", "Update without restarting the service"],
|
||||
["moltbot update --json", "Output result as JSON"],
|
||||
["moltbot update --yes", "Non-interactive (accept downgrade prompts)"],
|
||||
["moltbot update wizard", "Interactive update wizard"],
|
||||
["moltbot --update", "Shorthand for moltbot update"],
|
||||
] as const;
|
||||
const fmtExamples = examples
|
||||
.map(([cmd, desc]) => ` ${theme.command(cmd)} ${theme.muted(`# ${desc}`)}`)
|
||||
@@ -1141,7 +1140,7 @@ ${theme.heading("What this does:")}
|
||||
|
||||
${theme.heading("Switch channels:")}
|
||||
- Use --channel stable|beta|dev to persist the update channel in config
|
||||
- Run clawdbot update status to see the active channel and source
|
||||
- Run moltbot update status to see the active channel and source
|
||||
- Use --tag <dist-tag|version> for a one-off npm update without persisting
|
||||
|
||||
${theme.heading("Non-interactive:")}
|
||||
@@ -1201,9 +1200,9 @@ ${theme.muted("Docs:")} ${formatDocsLink("/cli/update", "docs.molt.bot/cli/updat
|
||||
"after",
|
||||
() =>
|
||||
`\n${theme.heading("Examples:")}\n${formatHelpExamples([
|
||||
["clawdbot update status", "Show channel + version status."],
|
||||
["clawdbot update status --json", "JSON output."],
|
||||
["clawdbot update status --timeout 10", "Custom timeout."],
|
||||
["moltbot update status", "Show channel + version status."],
|
||||
["moltbot update status --json", "JSON output."],
|
||||
["moltbot update status --timeout 10", "Custom timeout."],
|
||||
])}\n\n${theme.heading("Notes:")}\n${theme.muted(
|
||||
"- Shows current update channel (stable/beta/dev) and source",
|
||||
)}\n${theme.muted("- Includes git tag/branch/SHA for source checkouts")}\n\n${theme.muted(
|
||||
|
||||
@@ -35,14 +35,14 @@ export function registerWebhooksCli(program: Command) {
|
||||
|
||||
gmail
|
||||
.command("setup")
|
||||
.description("Configure Gmail watch + Pub/Sub + Clawdbot hooks")
|
||||
.description("Configure Gmail watch + Pub/Sub + Moltbot hooks")
|
||||
.requiredOption("--account <email>", "Gmail account to watch")
|
||||
.option("--project <id>", "GCP project id (OAuth client owner)")
|
||||
.option("--topic <name>", "Pub/Sub topic name", DEFAULT_GMAIL_TOPIC)
|
||||
.option("--subscription <name>", "Pub/Sub subscription name", DEFAULT_GMAIL_SUBSCRIPTION)
|
||||
.option("--label <label>", "Gmail label to watch", DEFAULT_GMAIL_LABEL)
|
||||
.option("--hook-url <url>", "Clawdbot hook URL")
|
||||
.option("--hook-token <token>", "Clawdbot hook token")
|
||||
.option("--hook-url <url>", "Moltbot hook URL")
|
||||
.option("--hook-token <token>", "Moltbot hook token")
|
||||
.option("--push-token <token>", "Push token for gog watch serve")
|
||||
.option("--bind <host>", "gog watch serve bind host", DEFAULT_GMAIL_SERVE_BIND)
|
||||
.option("--port <port>", "gog watch serve port", String(DEFAULT_GMAIL_SERVE_PORT))
|
||||
@@ -79,8 +79,8 @@ export function registerWebhooksCli(program: Command) {
|
||||
.option("--topic <topic>", "Pub/Sub topic path (projects/.../topics/..)")
|
||||
.option("--subscription <name>", "Pub/Sub subscription name")
|
||||
.option("--label <label>", "Gmail label to watch")
|
||||
.option("--hook-url <url>", "Clawdbot hook URL")
|
||||
.option("--hook-token <token>", "Clawdbot hook token")
|
||||
.option("--hook-url <url>", "Moltbot hook URL")
|
||||
.option("--hook-token <token>", "Moltbot hook token")
|
||||
.option("--push-token <token>", "Push token for gog watch serve")
|
||||
.option("--bind <host>", "gog watch serve bind host")
|
||||
.option("--port <port>", "gog watch serve port")
|
||||
|
||||
Reference in New Issue
Block a user