chore: align with moltbot rename (upstream moltbot/moltbot)
- package.json: name moltbot, bin moltbot + clawdbot (compat shim) - paths.ts: MOLTBOT_* preferred, CLAWDBOT_* legacy; default ~/.clawdbot; config moltbot.json; export STATE_DIR/CONFIG_PATH - render.yaml: service name moltbot, disk moltbot-data; CLAWDBOT_* env vars and /data/.clawdbot (match upstream) - render-start.sh: support CLAWDBOT_* and MOLTBOT_* for state/token; write moltbot.json - Dockerfile: MOLTBOT_DOCKER_APT_PACKAGES, MOLTBOT_PREFER_PNPM - config/io.ts: MOLTBOT_* env for gateway token and config cache - Replace STATE_DIR_CLAWDBOT/CONFIG_PATH_CLAWDBOT with STATE_DIR_MOLTBOT/CONFIG_PATH_MOLTBOT across src; paths exports both for compat
This commit is contained in:
parent
ed70785316
commit
3518abc344
@ -8,10 +8,10 @@ RUN corepack enable
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
ARG CLAWDBOT_DOCKER_APT_PACKAGES=""
|
||||
RUN if [ -n "$CLAWDBOT_DOCKER_APT_PACKAGES" ]; then \
|
||||
ARG MOLTBOT_DOCKER_APT_PACKAGES=""
|
||||
RUN if [ -n "$MOLTBOT_DOCKER_APT_PACKAGES" ]; then \
|
||||
apt-get update && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends $CLAWDBOT_DOCKER_APT_PACKAGES && \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends $MOLTBOT_DOCKER_APT_PACKAGES && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/*; \
|
||||
fi
|
||||
@ -28,7 +28,7 @@ RUN pnpm install --frozen-lockfile
|
||||
COPY . .
|
||||
RUN pnpm build
|
||||
# Force pnpm for UI build (Bun may fail on ARM/Synology architectures)
|
||||
ENV CLAWDBOT_PREFER_PNPM=1
|
||||
ENV MOLTBOT_PREFER_PNPM=1
|
||||
RUN pnpm ui:install
|
||||
RUN pnpm ui:build
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "clawdbot",
|
||||
"name": "moltbot",
|
||||
"version": "2026.1.25",
|
||||
"description": "WhatsApp gateway CLI (Baileys web) with Pi RPC agent",
|
||||
"type": "module",
|
||||
@ -10,6 +10,7 @@
|
||||
"./plugin-sdk/*": "./dist/plugin-sdk/*"
|
||||
},
|
||||
"bin": {
|
||||
"moltbot": "dist/entry.js",
|
||||
"clawdbot": "dist/entry.js"
|
||||
},
|
||||
"files": [
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
services:
|
||||
- type: web
|
||||
name: clawdbot
|
||||
name: moltbot
|
||||
runtime: docker
|
||||
plan: starter
|
||||
dockerCommand: /bin/sh scripts/render-start.sh
|
||||
@ -34,6 +34,6 @@ services:
|
||||
- key: DEEPGRAM_API_KEY
|
||||
sync: false
|
||||
disk:
|
||||
name: clawdbot-data
|
||||
name: moltbot-data
|
||||
mountPath: /data
|
||||
sizeGB: 1
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
echo "=== Render startup script ==="
|
||||
echo "HOME=${HOME:-not set}"
|
||||
echo "CLAWDBOT_STATE_DIR=${CLAWDBOT_STATE_DIR:-not set}"
|
||||
echo "MOLTBOT_STATE_DIR=${MOLTBOT_STATE_DIR:-not set}"
|
||||
echo "User: $(whoami 2>/dev/null || echo unknown)"
|
||||
echo "UID: $(id -u 2>/dev/null || echo unknown)"
|
||||
echo "PWD: $(pwd)"
|
||||
@ -19,29 +20,30 @@ if [ -z "${HOME}" ]; then
|
||||
echo "Set HOME to: ${HOME}"
|
||||
fi
|
||||
|
||||
# Use CLAWDBOT_STATE_DIR if set and writable, otherwise use HOME/.clawdbot
|
||||
CONFIG_DIR="${HOME}/.clawdbot"
|
||||
if [ -n "${CLAWDBOT_STATE_DIR}" ]; then
|
||||
# Test if we can write to it (disable exit on error for this test)
|
||||
set +e
|
||||
mkdir -p "${CLAWDBOT_STATE_DIR}" 2>/dev/null
|
||||
touch "${CLAWDBOT_STATE_DIR}/.test" 2>/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
rm -f "${CLAWDBOT_STATE_DIR}/.test" 2>/dev/null
|
||||
CONFIG_DIR="${CLAWDBOT_STATE_DIR}"
|
||||
echo "Using CLAWDBOT_STATE_DIR: ${CONFIG_DIR}"
|
||||
else
|
||||
echo "Warning: ${CLAWDBOT_STATE_DIR} not writable, using ${CONFIG_DIR}"
|
||||
# Prefer MOLTBOT_STATE_DIR or CLAWDBOT_STATE_DIR (legacy), else HOME/.moltbot then HOME/.clawdbot
|
||||
CONFIG_DIR="${HOME}/.moltbot"
|
||||
for var in MOLTBOT_STATE_DIR CLAWDBOT_STATE_DIR; do
|
||||
eval "val=\${${var}:-}"
|
||||
if [ -n "$val" ]; then
|
||||
set +e
|
||||
mkdir -p "$val" 2>/dev/null
|
||||
touch "$val/.test" 2>/dev/null
|
||||
if [ $? -eq 0 ]; then
|
||||
rm -f "$val/.test" 2>/dev/null
|
||||
CONFIG_DIR="$val"
|
||||
echo "Using ${var}: ${CONFIG_DIR}"
|
||||
fi
|
||||
set -e
|
||||
break
|
||||
fi
|
||||
set -e
|
||||
fi
|
||||
done
|
||||
|
||||
CONFIG_FILE="${CONFIG_DIR}/clawdbot.json"
|
||||
CONFIG_FILE="${CONFIG_DIR}/moltbot.json"
|
||||
|
||||
echo "Config dir: ${CONFIG_DIR}"
|
||||
echo "Config file: ${CONFIG_FILE}"
|
||||
|
||||
# Create config directory (this should always work for HOME/.clawdbot)
|
||||
# Create config directory (fallback: HOME/.moltbot or HOME/.clawdbot)
|
||||
if ! mkdir -p "${CONFIG_DIR}" 2>/dev/null; then
|
||||
echo "ERROR: Failed to create config directory: ${CONFIG_DIR}"
|
||||
exit 1
|
||||
@ -73,14 +75,17 @@ if [ ! -f "${CONFIG_FILE}" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set environment variables for gateway
|
||||
# Set environment variables for gateway (app accepts MOLTBOT_* or CLAWDBOT_*)
|
||||
export CLAWDBOT_STATE_DIR="${CONFIG_DIR}"
|
||||
export CLAWDBOT_CONFIG_PATH="${CONFIG_FILE}"
|
||||
export CLAWDBOT_CONFIG_CACHE_MS=0
|
||||
export MOLTBOT_STATE_DIR="${CONFIG_DIR}"
|
||||
export MOLTBOT_CONFIG_PATH="${CONFIG_FILE}"
|
||||
export MOLTBOT_CONFIG_CACHE_MS=0
|
||||
|
||||
echo "=== Starting gateway ==="
|
||||
echo "CLAWDBOT_STATE_DIR=${CLAWDBOT_STATE_DIR}"
|
||||
echo "CLAWDBOT_CONFIG_PATH=${CLAWDBOT_CONFIG_PATH}"
|
||||
echo "CONFIG_DIR=${CONFIG_DIR}"
|
||||
echo "CONFIG_FILE=${CONFIG_FILE}"
|
||||
|
||||
# Verify node is available
|
||||
if ! command -v node >/dev/null 2>&1; then
|
||||
@ -103,13 +108,14 @@ fi
|
||||
|
||||
echo "Found dist/index.js"
|
||||
|
||||
# Check if token is set
|
||||
if [ -z "${CLAWDBOT_GATEWAY_TOKEN}" ]; then
|
||||
echo "ERROR: CLAWDBOT_GATEWAY_TOKEN is not set"
|
||||
# Token: CLAWDBOT_GATEWAY_TOKEN (legacy) or MOLTBOT_GATEWAY_TOKEN
|
||||
GATEWAY_TOKEN="${CLAWDBOT_GATEWAY_TOKEN:-${MOLTBOT_GATEWAY_TOKEN}}"
|
||||
if [ -z "${GATEWAY_TOKEN}" ]; then
|
||||
echo "ERROR: CLAWDBOT_GATEWAY_TOKEN or MOLTBOT_GATEWAY_TOKEN must be set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Token is set (length: ${#CLAWDBOT_GATEWAY_TOKEN})"
|
||||
echo "Token is set (length: ${#GATEWAY_TOKEN})"
|
||||
|
||||
# Enable strict error handling for the final exec
|
||||
set -e
|
||||
@ -120,5 +126,5 @@ exec node dist/index.js gateway \
|
||||
--port 8080 \
|
||||
--bind lan \
|
||||
--auth token \
|
||||
--token "${CLAWDBOT_GATEWAY_TOKEN}" \
|
||||
--token "${GATEWAY_TOKEN}" \
|
||||
--allow-unconfigured
|
||||
|
||||
@ -2,9 +2,9 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
|
||||
import { CHANNEL_IDS } from "../../channels/registry.js";
|
||||
import { STATE_DIR_CLAWDBOT } from "../../config/config.js";
|
||||
import { STATE_DIR_MOLTBOT } from "../../config/config.js";
|
||||
|
||||
export const DEFAULT_SANDBOX_WORKSPACE_ROOT = path.join(os.homedir(), ".clawdbot", "sandboxes");
|
||||
export const DEFAULT_SANDBOX_WORKSPACE_ROOT = path.join(os.homedir(), ".moltbot", "sandboxes");
|
||||
|
||||
export const DEFAULT_SANDBOX_IMAGE = "clawdbot-sandbox:bookworm-slim";
|
||||
export const DEFAULT_SANDBOX_CONTAINER_PREFIX = "clawdbot-sbx-";
|
||||
@ -48,7 +48,7 @@ export const DEFAULT_SANDBOX_BROWSER_AUTOSTART_TIMEOUT_MS = 12_000;
|
||||
|
||||
export const SANDBOX_AGENT_WORKSPACE_MOUNT = "/agent";
|
||||
|
||||
const resolvedSandboxStateDir = STATE_DIR_CLAWDBOT ?? path.join(os.homedir(), ".clawdbot");
|
||||
const resolvedSandboxStateDir = STATE_DIR_MOLTBOT ?? path.join(os.homedir(), ".moltbot");
|
||||
export const SANDBOX_STATE_DIR = path.join(resolvedSandboxStateDir, "sandbox");
|
||||
export const SANDBOX_REGISTRY_PATH = path.join(SANDBOX_STATE_DIR, "containers.json");
|
||||
export const SANDBOX_BROWSER_REGISTRY_PATH = path.join(SANDBOX_STATE_DIR, "browsers.json");
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import path from "node:path";
|
||||
|
||||
import { STATE_DIR_CLAWDBOT } from "../config/paths.js";
|
||||
import { STATE_DIR_MOLTBOT } from "../config/paths.js";
|
||||
import { loadJsonFile, saveJsonFile } from "../infra/json-file.js";
|
||||
import { normalizeDeliveryContext } from "../utils/delivery-context.js";
|
||||
import type { SubagentRunRecord } from "./subagent-registry.js";
|
||||
@ -31,7 +31,7 @@ type LegacySubagentRunRecord = PersistedSubagentRunRecord & {
|
||||
};
|
||||
|
||||
export function resolveSubagentRegistryPath(): string {
|
||||
return path.join(STATE_DIR_CLAWDBOT, "subagents", "runs.json");
|
||||
return path.join(STATE_DIR_MOLTBOT, "subagents", "runs.json");
|
||||
}
|
||||
|
||||
export function loadSubagentRegistryFromDisk(): Map<string, SubagentRunRecord> {
|
||||
|
||||
@ -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_MOLTBOT } 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_MOLTBOT, "browser", "chrome-extension");
|
||||
}
|
||||
|
||||
function hasManifest(dir: string) {
|
||||
@ -36,7 +36,7 @@ export async function installChromeExtension(opts?: {
|
||||
throw new Error("Bundled Chrome extension is missing. Reinstall Clawdbot and try again.");
|
||||
}
|
||||
|
||||
const stateDir = opts?.stateDir ?? STATE_DIR_CLAWDBOT;
|
||||
const stateDir = opts?.stateDir ?? STATE_DIR_MOLTBOT;
|
||||
const dest = path.join(stateDir, "browser", "chrome-extension");
|
||||
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
||||
|
||||
|
||||
@ -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_MOLTBOT, writeConfigFile } from "../../config/config.js";
|
||||
import { defaultRuntime } from "../../runtime.js";
|
||||
import { resolveUserPath, shortenHomePath } from "../../utils.js";
|
||||
|
||||
@ -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_MOLTBOT);
|
||||
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_MOLTBOT)}`);
|
||||
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_MOLTBOT,
|
||||
loadConfig,
|
||||
readConfigFileSnapshot,
|
||||
resolveGatewayPort,
|
||||
@ -157,7 +157,7 @@ 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_MOLTBOT);
|
||||
const mode = cfg.gateway?.mode;
|
||||
if (!opts.allowUnconfigured && mode !== "local") {
|
||||
if (!configExists) {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { getChannelPlugin, listChannelPlugins } from "../channels/plugins/index.js";
|
||||
import { formatCliCommand } from "../cli/command-format.js";
|
||||
import type { ClawdbotConfig } from "../config/config.js";
|
||||
import { CONFIG_PATH_CLAWDBOT } from "../config/config.js";
|
||||
import { CONFIG_PATH_MOLTBOT } from "../config/config.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { note } from "../terminal/note.js";
|
||||
import { shortenHomePath } from "../utils.js";
|
||||
@ -52,7 +52,7 @@ export async function removeChannelConfigWizard(
|
||||
const label = getChannelPlugin(channel)?.meta.label ?? channel;
|
||||
const confirmed = guardCancel(
|
||||
await confirm({
|
||||
message: `Delete ${label} configuration from ${shortenHomePath(CONFIG_PATH_CLAWDBOT)}?`,
|
||||
message: `Delete ${label} configuration from ${shortenHomePath(CONFIG_PATH_MOLTBOT)}?`,
|
||||
initialValue: false,
|
||||
}),
|
||||
runtime,
|
||||
|
||||
@ -30,7 +30,7 @@ vi.mock("@clack/prompts", () => ({
|
||||
}));
|
||||
|
||||
vi.mock("../config/config.js", () => ({
|
||||
CONFIG_PATH_CLAWDBOT: "~/.clawdbot/clawdbot.json",
|
||||
CONFIG_PATH_MOLTBOT: "~/.moltbot/moltbot.json",
|
||||
readConfigFileSnapshot: mocks.readConfigFileSnapshot,
|
||||
writeConfigFile: mocks.writeConfigFile,
|
||||
resolveGatewayPort: mocks.resolveGatewayPort,
|
||||
|
||||
@ -3,7 +3,7 @@ import type { ZodIssue } from "zod";
|
||||
import type { ClawdbotConfig } from "../config/config.js";
|
||||
import {
|
||||
ClawdbotSchema,
|
||||
CONFIG_PATH_CLAWDBOT,
|
||||
CONFIG_PATH_MOLTBOT,
|
||||
migrateLegacyConfig,
|
||||
readConfigFileSnapshot,
|
||||
} from "../config/config.js";
|
||||
@ -214,5 +214,5 @@ export async function loadAndMaybeMigrateDoctorConfig(params: {
|
||||
|
||||
noteOpencodeProviderOverrides(cfg);
|
||||
|
||||
return { cfg, path: snapshot.path ?? CONFIG_PATH_CLAWDBOT, shouldWriteConfig };
|
||||
return { cfg, path: snapshot.path ?? CONFIG_PATH_MOLTBOT, shouldWriteConfig };
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ beforeEach(() => {
|
||||
durationMs: 0,
|
||||
});
|
||||
legacyReadConfigFileSnapshot.mockReset().mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: false,
|
||||
raw: null,
|
||||
parsed: {},
|
||||
@ -135,7 +135,7 @@ const ensureAuthProfileStore = vi.fn().mockReturnValue({ version: 1, profiles: {
|
||||
const loadClawdbotPlugins = vi.fn().mockReturnValue({ plugins: [], diagnostics: [] });
|
||||
|
||||
const legacyReadConfigFileSnapshot = vi.fn().mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: false,
|
||||
raw: null,
|
||||
parsed: {},
|
||||
@ -181,7 +181,7 @@ vi.mock("../config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal();
|
||||
return {
|
||||
...actual,
|
||||
CONFIG_PATH_CLAWDBOT: "/tmp/clawdbot.json",
|
||||
CONFIG_PATH_MOLTBOT: "/tmp/moltbot.json",
|
||||
createConfigIO,
|
||||
readConfigFileSnapshot,
|
||||
writeConfigFile,
|
||||
@ -327,7 +327,7 @@ vi.mock("./doctor-state-migrations.js", () => ({
|
||||
describe("doctor command", () => {
|
||||
it("runs legacy state migrations in non-interactive mode without prompting", async () => {
|
||||
readConfigFileSnapshot.mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: true,
|
||||
raw: "{}",
|
||||
parsed: {},
|
||||
|
||||
@ -34,7 +34,7 @@ beforeEach(() => {
|
||||
durationMs: 0,
|
||||
});
|
||||
legacyReadConfigFileSnapshot.mockReset().mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: false,
|
||||
raw: null,
|
||||
parsed: {},
|
||||
@ -133,7 +133,7 @@ const runCommandWithTimeout = vi.fn().mockResolvedValue({
|
||||
const ensureAuthProfileStore = vi.fn().mockReturnValue({ version: 1, profiles: {} });
|
||||
|
||||
const legacyReadConfigFileSnapshot = vi.fn().mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: false,
|
||||
raw: null,
|
||||
parsed: {},
|
||||
@ -180,7 +180,7 @@ vi.mock("../config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal();
|
||||
return {
|
||||
...actual,
|
||||
CONFIG_PATH_CLAWDBOT: "/tmp/clawdbot.json",
|
||||
CONFIG_PATH_MOLTBOT: "/tmp/moltbot.json",
|
||||
createConfigIO,
|
||||
readConfigFileSnapshot,
|
||||
writeConfigFile,
|
||||
@ -326,7 +326,7 @@ vi.mock("./doctor-state-migrations.js", () => ({
|
||||
describe("doctor command", () => {
|
||||
it("migrates routing.allowFrom to channels.whatsapp.allowFrom", { timeout: 60_000 }, async () => {
|
||||
readConfigFileSnapshot.mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: true,
|
||||
raw: "{}",
|
||||
parsed: { routing: { allowFrom: ["+15555550123"] } },
|
||||
@ -370,7 +370,7 @@ describe("doctor command", () => {
|
||||
|
||||
it("migrates legacy gateway services", { timeout: 60_000 }, async () => {
|
||||
readConfigFileSnapshot.mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: true,
|
||||
raw: "{}",
|
||||
parsed: {},
|
||||
@ -424,7 +424,7 @@ describe("doctor command", () => {
|
||||
});
|
||||
|
||||
readConfigFileSnapshot.mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: true,
|
||||
raw: "{}",
|
||||
parsed: {},
|
||||
|
||||
@ -34,7 +34,7 @@ beforeEach(() => {
|
||||
durationMs: 0,
|
||||
});
|
||||
legacyReadConfigFileSnapshot.mockReset().mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: false,
|
||||
raw: null,
|
||||
parsed: {},
|
||||
@ -133,7 +133,7 @@ const runCommandWithTimeout = vi.fn().mockResolvedValue({
|
||||
const ensureAuthProfileStore = vi.fn().mockReturnValue({ version: 1, profiles: {} });
|
||||
|
||||
const legacyReadConfigFileSnapshot = vi.fn().mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: false,
|
||||
raw: null,
|
||||
parsed: {},
|
||||
@ -180,7 +180,7 @@ vi.mock("../config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal();
|
||||
return {
|
||||
...actual,
|
||||
CONFIG_PATH_CLAWDBOT: "/tmp/clawdbot.json",
|
||||
CONFIG_PATH_MOLTBOT: "/tmp/moltbot.json",
|
||||
createConfigIO,
|
||||
readConfigFileSnapshot,
|
||||
writeConfigFile,
|
||||
@ -326,7 +326,7 @@ vi.mock("./doctor-state-migrations.js", () => ({
|
||||
describe("doctor command", () => {
|
||||
it("runs legacy state migrations in yes mode without prompting", async () => {
|
||||
readConfigFileSnapshot.mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: true,
|
||||
raw: "{}",
|
||||
parsed: {},
|
||||
@ -385,7 +385,7 @@ describe("doctor command", () => {
|
||||
|
||||
it("skips gateway restarts in non-interactive mode", async () => {
|
||||
readConfigFileSnapshot.mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: true,
|
||||
raw: "{}",
|
||||
parsed: {},
|
||||
@ -417,7 +417,7 @@ describe("doctor command", () => {
|
||||
|
||||
it("migrates anthropic oauth config profile id when only email profile exists", async () => {
|
||||
readConfigFileSnapshot.mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: true,
|
||||
raw: "{}",
|
||||
parsed: {},
|
||||
|
||||
@ -11,7 +11,7 @@ import {
|
||||
} from "../agents/model-selection.js";
|
||||
import { formatCliCommand } from "../cli/command-format.js";
|
||||
import type { ClawdbotConfig } from "../config/config.js";
|
||||
import { CONFIG_PATH_CLAWDBOT, readConfigFileSnapshot, writeConfigFile } from "../config/config.js";
|
||||
import { CONFIG_PATH_MOLTBOT, readConfigFileSnapshot, writeConfigFile } from "../config/config.js";
|
||||
import { logConfigUpdated } from "../config/logging.js";
|
||||
import { resolveGatewayService } from "../daemon/service.js";
|
||||
import { resolveGatewayAuth } from "../gateway/auth.js";
|
||||
@ -90,7 +90,7 @@ export async function doctorCommand(
|
||||
});
|
||||
let cfg: ClawdbotConfig = configResult.cfg;
|
||||
|
||||
const configPath = configResult.path ?? CONFIG_PATH_CLAWDBOT;
|
||||
const configPath = configResult.path ?? CONFIG_PATH_MOLTBOT;
|
||||
if (!cfg.gateway?.mode) {
|
||||
const lines = [
|
||||
"gateway.mode is unset; gateway start will be blocked.",
|
||||
@ -174,7 +174,7 @@ export async function doctorCommand(
|
||||
}
|
||||
}
|
||||
|
||||
await noteStateIntegrity(cfg, prompter, configResult.path ?? CONFIG_PATH_CLAWDBOT);
|
||||
await noteStateIntegrity(cfg, prompter, configResult.path ?? CONFIG_PATH_MOLTBOT);
|
||||
|
||||
cfg = await maybeRepairSandboxImages(cfg, runtime, prompter);
|
||||
noteSandboxScopeWarnings(cfg);
|
||||
@ -272,7 +272,7 @@ export async function doctorCommand(
|
||||
cfg = applyWizardMetadata(cfg, { command: "doctor", mode: resolveMode(cfg) });
|
||||
await writeConfigFile(cfg);
|
||||
logConfigUpdated(runtime);
|
||||
const backupPath = `${CONFIG_PATH_CLAWDBOT}.bak`;
|
||||
const backupPath = `${CONFIG_PATH_MOLTBOT}.bak`;
|
||||
if (fs.existsSync(backupPath)) {
|
||||
runtime.log(`Backup: ${shortenHomePath(backupPath)}`);
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ beforeEach(() => {
|
||||
durationMs: 0,
|
||||
});
|
||||
legacyReadConfigFileSnapshot.mockReset().mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: false,
|
||||
raw: null,
|
||||
parsed: {},
|
||||
@ -133,7 +133,7 @@ const runCommandWithTimeout = vi.fn().mockResolvedValue({
|
||||
const ensureAuthProfileStore = vi.fn().mockReturnValue({ version: 1, profiles: {} });
|
||||
|
||||
const legacyReadConfigFileSnapshot = vi.fn().mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: false,
|
||||
raw: null,
|
||||
parsed: {},
|
||||
@ -180,7 +180,7 @@ vi.mock("../config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal();
|
||||
return {
|
||||
...actual,
|
||||
CONFIG_PATH_CLAWDBOT: "/tmp/clawdbot.json",
|
||||
CONFIG_PATH_MOLTBOT: "/tmp/moltbot.json",
|
||||
createConfigIO,
|
||||
readConfigFileSnapshot,
|
||||
writeConfigFile,
|
||||
@ -326,7 +326,7 @@ vi.mock("./doctor-state-migrations.js", () => ({
|
||||
describe("doctor command", () => {
|
||||
it("warns when per-agent sandbox docker/browser/prune overrides are ignored under shared scope", async () => {
|
||||
readConfigFileSnapshot.mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: true,
|
||||
raw: "{}",
|
||||
parsed: {},
|
||||
@ -383,7 +383,7 @@ describe("doctor command", () => {
|
||||
|
||||
it("warns when extra workspace directories exist", async () => {
|
||||
readConfigFileSnapshot.mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: true,
|
||||
raw: "{}",
|
||||
parsed: {},
|
||||
|
||||
@ -34,7 +34,7 @@ beforeEach(() => {
|
||||
durationMs: 0,
|
||||
});
|
||||
legacyReadConfigFileSnapshot.mockReset().mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: false,
|
||||
raw: null,
|
||||
parsed: {},
|
||||
@ -133,7 +133,7 @@ const runCommandWithTimeout = vi.fn().mockResolvedValue({
|
||||
const ensureAuthProfileStore = vi.fn().mockReturnValue({ version: 1, profiles: {} });
|
||||
|
||||
const legacyReadConfigFileSnapshot = vi.fn().mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: false,
|
||||
raw: null,
|
||||
parsed: {},
|
||||
@ -180,7 +180,7 @@ vi.mock("../config/config.js", async (importOriginal) => {
|
||||
const actual = await importOriginal();
|
||||
return {
|
||||
...actual,
|
||||
CONFIG_PATH_CLAWDBOT: "/tmp/clawdbot.json",
|
||||
CONFIG_PATH_MOLTBOT: "/tmp/moltbot.json",
|
||||
createConfigIO,
|
||||
readConfigFileSnapshot,
|
||||
writeConfigFile,
|
||||
@ -330,7 +330,7 @@ vi.mock("./doctor-update.js", () => ({
|
||||
describe("doctor command", () => {
|
||||
it("warns when the state directory is missing", async () => {
|
||||
readConfigFileSnapshot.mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: true,
|
||||
raw: "{}",
|
||||
parsed: {},
|
||||
@ -358,7 +358,7 @@ describe("doctor command", () => {
|
||||
|
||||
it("warns about opencode provider overrides", async () => {
|
||||
readConfigFileSnapshot.mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: true,
|
||||
raw: "{}",
|
||||
parsed: {},
|
||||
@ -392,7 +392,7 @@ describe("doctor command", () => {
|
||||
|
||||
it("skips gateway auth warning when CLAWDBOT_GATEWAY_TOKEN is set", async () => {
|
||||
readConfigFileSnapshot.mockResolvedValue({
|
||||
path: "/tmp/clawdbot.json",
|
||||
path: "/tmp/moltbot.json",
|
||||
exists: true,
|
||||
raw: "{}",
|
||||
parsed: {},
|
||||
|
||||
@ -17,8 +17,8 @@ const discoverAuthStorage = vi.fn().mockReturnValue({});
|
||||
const discoverModels = vi.fn();
|
||||
|
||||
vi.mock("../config/config.js", () => ({
|
||||
CONFIG_PATH_CLAWDBOT: "/tmp/clawdbot.json",
|
||||
STATE_DIR_CLAWDBOT: "/tmp/clawdbot-state",
|
||||
CONFIG_PATH_MOLTBOT: "/tmp/moltbot.json",
|
||||
STATE_DIR_MOLTBOT: "/tmp/moltbot-state",
|
||||
loadConfig,
|
||||
}));
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ const writeConfigFile = vi.fn().mockResolvedValue(undefined);
|
||||
const loadConfig = vi.fn().mockReturnValue({});
|
||||
|
||||
vi.mock("../config/config.js", () => ({
|
||||
CONFIG_PATH_CLAWDBOT: "/tmp/clawdbot.json",
|
||||
CONFIG_PATH_MOLTBOT: "/tmp/clawdbot.json",
|
||||
readConfigFileSnapshot,
|
||||
writeConfigFile,
|
||||
loadConfig,
|
||||
|
||||
@ -17,7 +17,7 @@ import {
|
||||
resolveConfiguredModelRef,
|
||||
resolveModelRefFromString,
|
||||
} from "../../agents/model-selection.js";
|
||||
import { CONFIG_PATH_CLAWDBOT, loadConfig } from "../../config/config.js";
|
||||
import { CONFIG_PATH_MOLTBOT, loadConfig } from "../../config/config.js";
|
||||
import { getShellEnvAppliedKeys, shouldEnableShellEnvFallback } from "../../infra/shell-env.js";
|
||||
import { withProgressTotals } from "../../cli/progress.js";
|
||||
import {
|
||||
@ -294,7 +294,7 @@ export async function modelsStatusCommand(
|
||||
runtime.log(
|
||||
JSON.stringify(
|
||||
{
|
||||
configPath: CONFIG_PATH_CLAWDBOT,
|
||||
configPath: CONFIG_PATH_MOLTBOT,
|
||||
agentDir,
|
||||
defaultModel: defaultLabel,
|
||||
resolvedDefault: resolvedLabel,
|
||||
@ -341,7 +341,7 @@ export async function modelsStatusCommand(
|
||||
rawModel && rawModel !== resolvedLabel ? `${resolvedLabel} (from ${rawModel})` : resolvedLabel;
|
||||
|
||||
runtime.log(
|
||||
`${label("Config")}${colorize(rich, theme.muted, ":")} ${colorize(rich, theme.info, shortenHomePath(CONFIG_PATH_CLAWDBOT))}`,
|
||||
`${label("Config")}${colorize(rich, theme.muted, ":")} ${colorize(rich, theme.info, shortenHomePath(CONFIG_PATH_MOLTBOT))}`,
|
||||
);
|
||||
runtime.log(
|
||||
`${label("Agent dir")}${colorize(rich, theme.muted, ":")} ${colorize(
|
||||
|
||||
@ -7,7 +7,7 @@ import { cancel, isCancel } from "@clack/prompts";
|
||||
|
||||
import { DEFAULT_AGENT_WORKSPACE_DIR, ensureAgentWorkspace } from "../agents/workspace.js";
|
||||
import type { ClawdbotConfig } from "../config/config.js";
|
||||
import { CONFIG_PATH_CLAWDBOT } from "../config/config.js";
|
||||
import { CONFIG_PATH_MOLTBOT } from "../config/config.js";
|
||||
import { resolveSessionTranscriptsDirForAgent } from "../config/sessions.js";
|
||||
import { callGateway } from "../gateway/call.js";
|
||||
import { normalizeControlUiBasePath } from "../gateway/control-ui-shared.js";
|
||||
@ -274,7 +274,7 @@ export async function moveToTrash(pathname: string, runtime: RuntimeEnv): Promis
|
||||
}
|
||||
|
||||
export async function handleReset(scope: ResetScope, workspaceDir: string, runtime: RuntimeEnv) {
|
||||
await moveToTrash(CONFIG_PATH_CLAWDBOT, runtime);
|
||||
await moveToTrash(CONFIG_PATH_MOLTBOT, runtime);
|
||||
if (scope === "config") return;
|
||||
await moveToTrash(path.join(CONFIG_DIR, "credentials"), runtime);
|
||||
await moveToTrash(resolveSessionTranscriptsDirForAgent(), runtime);
|
||||
|
||||
@ -56,8 +56,8 @@ describe("onboard (non-interactive): Vercel AI Gateway", () => {
|
||||
runtime,
|
||||
);
|
||||
|
||||
const { CONFIG_PATH_CLAWDBOT } = await import("../config/config.js");
|
||||
const cfg = JSON.parse(await fs.readFile(CONFIG_PATH_CLAWDBOT, "utf8")) as {
|
||||
const { CONFIG_PATH_MOLTBOT } = await import("../config/config.js");
|
||||
const cfg = JSON.parse(await fs.readFile(CONFIG_PATH_MOLTBOT, "utf8")) as {
|
||||
auth?: {
|
||||
profiles?: Record<string, { provider?: string; mode?: string }>;
|
||||
};
|
||||
|
||||
@ -59,8 +59,8 @@ describe("onboard (non-interactive): token auth", () => {
|
||||
runtime,
|
||||
);
|
||||
|
||||
const { CONFIG_PATH_CLAWDBOT } = await import("../config/config.js");
|
||||
const cfg = JSON.parse(await fs.readFile(CONFIG_PATH_CLAWDBOT, "utf8")) as {
|
||||
const { CONFIG_PATH_MOLTBOT } = await import("../config/config.js");
|
||||
const cfg = JSON.parse(await fs.readFile(CONFIG_PATH_MOLTBOT, "utf8")) as {
|
||||
auth?: {
|
||||
profiles?: Record<string, { provider?: string; mode?: string }>;
|
||||
};
|
||||
|
||||
@ -3,7 +3,7 @@ import fs from "node:fs/promises";
|
||||
import JSON5 from "json5";
|
||||
|
||||
import { DEFAULT_AGENT_WORKSPACE_DIR, ensureAgentWorkspace } from "../agents/workspace.js";
|
||||
import { type ClawdbotConfig, CONFIG_PATH_CLAWDBOT, writeConfigFile } from "../config/config.js";
|
||||
import { type ClawdbotConfig, CONFIG_PATH_MOLTBOT, writeConfigFile } from "../config/config.js";
|
||||
import { formatConfigPath, logConfigUpdated } from "../config/logging.js";
|
||||
import { resolveSessionTranscriptsDir } from "../config/sessions.js";
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
@ -15,7 +15,7 @@ async function readConfigFileRaw(): Promise<{
|
||||
parsed: ClawdbotConfig;
|
||||
}> {
|
||||
try {
|
||||
const raw = await fs.readFile(CONFIG_PATH_CLAWDBOT, "utf-8");
|
||||
const raw = await fs.readFile(CONFIG_PATH_MOLTBOT, "utf-8");
|
||||
const parsed = JSON5.parse(raw);
|
||||
if (parsed && typeof parsed === "object") {
|
||||
return { exists: true, parsed: parsed as ClawdbotConfig };
|
||||
|
||||
@ -35,56 +35,56 @@ describe("Nix integration (U3, U5, U9)", () => {
|
||||
});
|
||||
|
||||
describe("U5: CONFIG_PATH and STATE_DIR env var overrides", () => {
|
||||
it("STATE_DIR_CLAWDBOT defaults to ~/.clawdbot when env not set", async () => {
|
||||
await withEnvOverride({ CLAWDBOT_STATE_DIR: undefined }, async () => {
|
||||
const { STATE_DIR_CLAWDBOT } = await import("./config.js");
|
||||
expect(STATE_DIR_CLAWDBOT).toMatch(/\.clawdbot$/);
|
||||
it("STATE_DIR_MOLTBOT defaults to ~/.moltbot when env not set", async () => {
|
||||
await withEnvOverride({ MOLTBOT_STATE_DIR: undefined }, async () => {
|
||||
const { STATE_DIR_MOLTBOT } = await import("./config.js");
|
||||
expect(STATE_DIR_MOLTBOT).toMatch(/\.moltbot$/);
|
||||
});
|
||||
});
|
||||
|
||||
it("STATE_DIR_CLAWDBOT respects CLAWDBOT_STATE_DIR override", async () => {
|
||||
await withEnvOverride({ CLAWDBOT_STATE_DIR: "/custom/state/dir" }, async () => {
|
||||
const { STATE_DIR_CLAWDBOT } = await import("./config.js");
|
||||
expect(STATE_DIR_CLAWDBOT).toBe(path.resolve("/custom/state/dir"));
|
||||
it("STATE_DIR_MOLTBOT respects MOLTBOT_STATE_DIR override", async () => {
|
||||
await withEnvOverride({ MOLTBOT_STATE_DIR: "/custom/state/dir" }, async () => {
|
||||
const { STATE_DIR_MOLTBOT } = await import("./config.js");
|
||||
expect(STATE_DIR_MOLTBOT).toBe(path.resolve("/custom/state/dir"));
|
||||
});
|
||||
});
|
||||
|
||||
it("CONFIG_PATH_CLAWDBOT defaults to ~/.clawdbot/clawdbot.json when env not set", async () => {
|
||||
it("CONFIG_PATH_MOLTBOT defaults to ~/.moltbot/moltbot.json when env not set", async () => {
|
||||
await withEnvOverride(
|
||||
{ CLAWDBOT_CONFIG_PATH: undefined, CLAWDBOT_STATE_DIR: undefined },
|
||||
{ MOLTBOT_CONFIG_PATH: undefined, MOLTBOT_STATE_DIR: undefined },
|
||||
async () => {
|
||||
const { CONFIG_PATH_CLAWDBOT } = await import("./config.js");
|
||||
expect(CONFIG_PATH_CLAWDBOT).toMatch(/\.clawdbot[\\/]clawdbot\.json$/);
|
||||
const { CONFIG_PATH_MOLTBOT } = await import("./config.js");
|
||||
expect(CONFIG_PATH_MOLTBOT).toMatch(/\.moltbot[\\/]clawdbot\.json$/);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("CONFIG_PATH_CLAWDBOT respects CLAWDBOT_CONFIG_PATH override", async () => {
|
||||
await withEnvOverride({ CLAWDBOT_CONFIG_PATH: "/nix/store/abc/clawdbot.json" }, async () => {
|
||||
const { CONFIG_PATH_CLAWDBOT } = await import("./config.js");
|
||||
expect(CONFIG_PATH_CLAWDBOT).toBe(path.resolve("/nix/store/abc/clawdbot.json"));
|
||||
it("CONFIG_PATH_MOLTBOT respects MOLTBOT_CONFIG_PATH override", async () => {
|
||||
await withEnvOverride({ MOLTBOT_CONFIG_PATH: "/nix/store/abc/moltbot.json" }, async () => {
|
||||
const { CONFIG_PATH_MOLTBOT } = await import("./config.js");
|
||||
expect(CONFIG_PATH_MOLTBOT).toBe(path.resolve("/nix/store/abc/moltbot.json"));
|
||||
});
|
||||
});
|
||||
|
||||
it("CONFIG_PATH_CLAWDBOT expands ~ in CLAWDBOT_CONFIG_PATH override", async () => {
|
||||
it("CONFIG_PATH_MOLTBOT expands ~ in MOLTBOT_CONFIG_PATH override", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
await withEnvOverride({ CLAWDBOT_CONFIG_PATH: "~/.clawdbot/custom.json" }, async () => {
|
||||
const { CONFIG_PATH_CLAWDBOT } = await import("./config.js");
|
||||
expect(CONFIG_PATH_CLAWDBOT).toBe(path.join(home, ".clawdbot", "custom.json"));
|
||||
await withEnvOverride({ MOLTBOT_CONFIG_PATH: "~/.moltbot/custom.json" }, async () => {
|
||||
const { CONFIG_PATH_MOLTBOT } = await import("./config.js");
|
||||
expect(CONFIG_PATH_MOLTBOT).toBe(path.join(home, ".moltbot", "custom.json"));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("CONFIG_PATH_CLAWDBOT uses STATE_DIR_CLAWDBOT when only state dir is overridden", async () => {
|
||||
it("CONFIG_PATH_MOLTBOT uses STATE_DIR_MOLTBOT when only state dir is overridden", async () => {
|
||||
await withEnvOverride(
|
||||
{
|
||||
CLAWDBOT_CONFIG_PATH: undefined,
|
||||
CLAWDBOT_STATE_DIR: "/custom/state",
|
||||
MOLTBOT_CONFIG_PATH: undefined,
|
||||
MOLTBOT_STATE_DIR: "/custom/state",
|
||||
},
|
||||
async () => {
|
||||
const { CONFIG_PATH_CLAWDBOT } = await import("./config.js");
|
||||
expect(CONFIG_PATH_CLAWDBOT).toBe(
|
||||
path.join(path.resolve("/custom/state"), "clawdbot.json"),
|
||||
const { CONFIG_PATH_MOLTBOT } = await import("./config.js");
|
||||
expect(CONFIG_PATH_MOLTBOT).toBe(
|
||||
path.join(path.resolve("/custom/state"), "moltbot.json"),
|
||||
);
|
||||
},
|
||||
);
|
||||
@ -94,7 +94,7 @@ describe("Nix integration (U3, U5, U9)", () => {
|
||||
describe("U5b: tilde expansion for config paths", () => {
|
||||
it("expands ~ in common path-ish config fields", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
const configDir = path.join(home, ".moltbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
const pluginDir = path.join(home, "plugins", "demo-plugin");
|
||||
await fs.mkdir(pluginDir, { recursive: true });
|
||||
@ -116,7 +116,7 @@ describe("Nix integration (U3, U5, U9)", () => {
|
||||
"utf-8",
|
||||
);
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
plugins: {
|
||||
@ -130,7 +130,7 @@ describe("Nix integration (U3, U5, U9)", () => {
|
||||
{
|
||||
id: "main",
|
||||
workspace: "~/ws-agent",
|
||||
agentDir: "~/.clawdbot/agents/main",
|
||||
agentDir: "~/.moltbot/agents/main",
|
||||
sandbox: { workspaceRoot: "~/sandbox-root" },
|
||||
},
|
||||
],
|
||||
@ -139,7 +139,7 @@ describe("Nix integration (U3, U5, U9)", () => {
|
||||
whatsapp: {
|
||||
accounts: {
|
||||
personal: {
|
||||
authDir: "~/.clawdbot/credentials/wa-personal",
|
||||
authDir: "~/.moltbot/credentials/wa-personal",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -159,11 +159,11 @@ describe("Nix integration (U3, U5, U9)", () => {
|
||||
expect(cfg.agents?.defaults?.workspace).toBe(path.join(home, "ws-default"));
|
||||
expect(cfg.agents?.list?.[0]?.workspace).toBe(path.join(home, "ws-agent"));
|
||||
expect(cfg.agents?.list?.[0]?.agentDir).toBe(
|
||||
path.join(home, ".clawdbot", "agents", "main"),
|
||||
path.join(home, ".moltbot", "agents", "main"),
|
||||
);
|
||||
expect(cfg.agents?.list?.[0]?.sandbox?.workspaceRoot).toBe(path.join(home, "sandbox-root"));
|
||||
expect(cfg.channels?.whatsapp?.accounts?.personal?.authDir).toBe(
|
||||
path.join(home, ".clawdbot", "credentials", "wa-personal"),
|
||||
path.join(home, ".moltbot", "credentials", "wa-personal"),
|
||||
);
|
||||
});
|
||||
});
|
||||
@ -195,10 +195,10 @@ describe("Nix integration (U3, U5, U9)", () => {
|
||||
describe("U9: telegram.tokenFile schema validation", () => {
|
||||
it("accepts config with only botToken", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
const configDir = path.join(home, ".moltbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify({
|
||||
channels: { telegram: { botToken: "123:ABC" } },
|
||||
}),
|
||||
@ -215,10 +215,10 @@ describe("Nix integration (U3, U5, U9)", () => {
|
||||
|
||||
it("accepts config with only tokenFile", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
const configDir = path.join(home, ".moltbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify({
|
||||
channels: { telegram: { tokenFile: "/run/agenix/telegram-token" } },
|
||||
}),
|
||||
@ -235,10 +235,10 @@ describe("Nix integration (U3, U5, U9)", () => {
|
||||
|
||||
it("accepts config with both botToken and tokenFile", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
const configDir = path.join(home, ".moltbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify({
|
||||
channels: {
|
||||
telegram: {
|
||||
|
||||
@ -53,8 +53,8 @@ const SHELL_ENV_EXPECTED_KEYS = [
|
||||
"DISCORD_BOT_TOKEN",
|
||||
"SLACK_BOT_TOKEN",
|
||||
"SLACK_APP_TOKEN",
|
||||
"CLAWDBOT_GATEWAY_TOKEN",
|
||||
"CLAWDBOT_GATEWAY_PASSWORD",
|
||||
"MOLTBOT_GATEWAY_TOKEN",
|
||||
"MOLTBOT_GATEWAY_PASSWORD",
|
||||
];
|
||||
|
||||
const CONFIG_BACKUP_COUNT = 5;
|
||||
@ -522,7 +522,7 @@ export function createConfigIO(overrides: ConfigIoDeps = {}) {
|
||||
}
|
||||
|
||||
// NOTE: These wrappers intentionally do *not* cache the resolved config path at
|
||||
// module scope. `CLAWDBOT_CONFIG_PATH` (and friends) are expected to work even
|
||||
// module scope. `MOLTBOT_CONFIG_PATH` (and friends) are expected to work even
|
||||
// when set after the module has been imported (tests, one-off scripts, etc.).
|
||||
const DEFAULT_CONFIG_CACHE_MS = 200;
|
||||
let configCache: {
|
||||
@ -532,7 +532,7 @@ let configCache: {
|
||||
} | null = null;
|
||||
|
||||
function resolveConfigCacheMs(env: NodeJS.ProcessEnv): number {
|
||||
const raw = env.CLAWDBOT_CONFIG_CACHE_MS?.trim();
|
||||
const raw = env.MOLTBOT_CONFIG_CACHE_MS?.trim();
|
||||
if (raw === "" || raw === "0") return 0;
|
||||
if (!raw) return DEFAULT_CONFIG_CACHE_MS;
|
||||
const parsed = Number.parseInt(raw, 10);
|
||||
@ -541,7 +541,7 @@ function resolveConfigCacheMs(env: NodeJS.ProcessEnv): number {
|
||||
}
|
||||
|
||||
function shouldUseConfigCache(env: NodeJS.ProcessEnv): boolean {
|
||||
if (env.CLAWDBOT_DISABLE_CONFIG_CACHE?.trim()) return false;
|
||||
if (env.MOLTBOT_DISABLE_CONFIG_CACHE?.trim()) return false;
|
||||
return resolveConfigCacheMs(env) > 0;
|
||||
}
|
||||
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { displayPath } from "../utils.js";
|
||||
import { CONFIG_PATH_CLAWDBOT } from "./paths.js";
|
||||
import { CONFIG_PATH_MOLTBOT } from "./paths.js";
|
||||
|
||||
type LogConfigUpdatedOptions = {
|
||||
path?: string;
|
||||
suffix?: string;
|
||||
};
|
||||
|
||||
export function formatConfigPath(path: string = CONFIG_PATH_CLAWDBOT): string {
|
||||
export function formatConfigPath(path: string = CONFIG_PATH_MOLTBOT): string {
|
||||
return displayPath(path);
|
||||
}
|
||||
|
||||
export function logConfigUpdated(runtime: RuntimeEnv, opts: LogConfigUpdatedOptions = {}): void {
|
||||
const path = formatConfigPath(opts.path ?? CONFIG_PATH_CLAWDBOT);
|
||||
const path = formatConfigPath(opts.path ?? CONFIG_PATH_MOLTBOT);
|
||||
const suffix = opts.suffix ? ` ${opts.suffix}` : "";
|
||||
runtime.log(`Updated ${path}${suffix}`);
|
||||
}
|
||||
|
||||
@ -15,18 +15,30 @@ export function resolveIsNixMode(env: NodeJS.ProcessEnv = process.env): boolean
|
||||
|
||||
export const isNixMode = resolveIsNixMode();
|
||||
|
||||
const LEGACY_STATE_DIRNAME = ".clawdbot";
|
||||
const NEW_STATE_DIRNAME = ".moltbot";
|
||||
const CONFIG_FILENAME = "moltbot.json";
|
||||
|
||||
function legacyStateDir(homedir: () => string = os.homedir): string {
|
||||
return path.join(homedir(), LEGACY_STATE_DIRNAME);
|
||||
}
|
||||
|
||||
function newStateDir(homedir: () => string = os.homedir): string {
|
||||
return path.join(homedir(), NEW_STATE_DIRNAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* State directory for mutable data (sessions, logs, caches).
|
||||
* Can be overridden via CLAWDBOT_STATE_DIR environment variable.
|
||||
* Default: ~/.clawdbot
|
||||
* Can be overridden via MOLTBOT_STATE_DIR (preferred) or CLAWDBOT_STATE_DIR (legacy).
|
||||
* Default: ~/.clawdbot (legacy default for compatibility)
|
||||
*/
|
||||
export function resolveStateDir(
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
homedir: () => string = os.homedir,
|
||||
): string {
|
||||
const override = env.CLAWDBOT_STATE_DIR?.trim();
|
||||
const override = env.MOLTBOT_STATE_DIR?.trim() || env.CLAWDBOT_STATE_DIR?.trim();
|
||||
if (override) return resolveUserPath(override);
|
||||
return path.join(homedir(), ".clawdbot");
|
||||
return legacyStateDir(homedir);
|
||||
}
|
||||
|
||||
function resolveUserPath(input: string): string {
|
||||
@ -39,34 +51,64 @@ function resolveUserPath(input: string): string {
|
||||
return path.resolve(trimmed);
|
||||
}
|
||||
|
||||
export const STATE_DIR_CLAWDBOT = resolveStateDir();
|
||||
/** @deprecated Use STATE_DIR. Kept for compatibility during migration. */
|
||||
export const STATE_DIR_MOLTBOT = resolveStateDir();
|
||||
export const STATE_DIR = resolveStateDir();
|
||||
|
||||
/**
|
||||
* Config file path (JSON5).
|
||||
* Can be overridden via CLAWDBOT_CONFIG_PATH environment variable.
|
||||
* Default: ~/.clawdbot/clawdbot.json (or $CLAWDBOT_STATE_DIR/clawdbot.json)
|
||||
* Can be overridden via MOLTBOT_CONFIG_PATH (preferred) or CLAWDBOT_CONFIG_PATH (legacy).
|
||||
* Default: ~/.clawdbot/moltbot.json (or $*_STATE_DIR/moltbot.json)
|
||||
*/
|
||||
export function resolveConfigPath(
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
stateDir: string = resolveStateDir(env, os.homedir),
|
||||
): string {
|
||||
const override = env.CLAWDBOT_CONFIG_PATH?.trim();
|
||||
const override = env.MOLTBOT_CONFIG_PATH?.trim() || env.CLAWDBOT_CONFIG_PATH?.trim();
|
||||
if (override) return resolveUserPath(override);
|
||||
return path.join(stateDir, "clawdbot.json");
|
||||
return path.join(stateDir, CONFIG_FILENAME);
|
||||
}
|
||||
|
||||
export const CONFIG_PATH_CLAWDBOT = resolveConfigPath();
|
||||
/** @deprecated Use CONFIG_PATH. Kept for compatibility during migration. */
|
||||
export const CONFIG_PATH_MOLTBOT = resolveConfigPath();
|
||||
export const CONFIG_PATH = resolveConfigPath();
|
||||
|
||||
/**
|
||||
* Resolve default config path candidates across new + legacy locations.
|
||||
* Order: explicit config path → state-dir-derived paths → new default → legacy default.
|
||||
*/
|
||||
export function resolveDefaultConfigCandidates(
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
homedir: () => string = os.homedir,
|
||||
): string[] {
|
||||
const explicit = env.MOLTBOT_CONFIG_PATH?.trim() || env.CLAWDBOT_CONFIG_PATH?.trim();
|
||||
if (explicit) return [resolveUserPath(explicit)];
|
||||
|
||||
const candidates: string[] = [];
|
||||
const moltbotStateDir = env.MOLTBOT_STATE_DIR?.trim();
|
||||
if (moltbotStateDir) {
|
||||
candidates.push(path.join(resolveUserPath(moltbotStateDir), CONFIG_FILENAME));
|
||||
}
|
||||
const legacyStateDirOverride = env.CLAWDBOT_STATE_DIR?.trim();
|
||||
if (legacyStateDirOverride) {
|
||||
candidates.push(path.join(resolveUserPath(legacyStateDirOverride), CONFIG_FILENAME));
|
||||
}
|
||||
|
||||
candidates.push(path.join(newStateDir(homedir), CONFIG_FILENAME));
|
||||
candidates.push(path.join(legacyStateDir(homedir), CONFIG_FILENAME));
|
||||
return candidates;
|
||||
}
|
||||
|
||||
export const DEFAULT_GATEWAY_PORT = 18789;
|
||||
|
||||
/**
|
||||
* Gateway lock directory (ephemeral).
|
||||
* Default: os.tmpdir()/clawdbot-<uid> (uid suffix when available).
|
||||
* Default: os.tmpdir()/moltbot-<uid> (uid suffix when available).
|
||||
*/
|
||||
export function resolveGatewayLockDir(tmpdir: () => string = os.tmpdir): string {
|
||||
const base = tmpdir();
|
||||
const uid = typeof process.getuid === "function" ? process.getuid() : undefined;
|
||||
const suffix = uid != null ? `clawdbot-${uid}` : "clawdbot";
|
||||
const suffix = uid != null ? `moltbot-${uid}` : "moltbot";
|
||||
return path.join(base, suffix);
|
||||
}
|
||||
|
||||
@ -77,7 +119,7 @@ const OAUTH_FILENAME = "oauth.json";
|
||||
*
|
||||
* Precedence:
|
||||
* - `CLAWDBOT_OAUTH_DIR` (explicit override)
|
||||
* - `CLAWDBOT_STATE_DIR/credentials` (canonical server/default)
|
||||
* - `$*_STATE_DIR/credentials` (canonical server/default)
|
||||
* - `~/.clawdbot/credentials` (legacy default)
|
||||
*/
|
||||
export function resolveOAuthDir(
|
||||
|
||||
@ -2,7 +2,7 @@ import path from "node:path";
|
||||
import { pathToFileURL } from "node:url";
|
||||
|
||||
import {
|
||||
CONFIG_PATH_CLAWDBOT,
|
||||
CONFIG_PATH_MOLTBOT,
|
||||
type HookMappingConfig,
|
||||
type HooksConfig,
|
||||
} from "../config/config.js";
|
||||
@ -125,7 +125,7 @@ export function resolveHookMappings(hooks?: HooksConfig): HookMappingResolved[]
|
||||
}
|
||||
if (mappings.length === 0) return [];
|
||||
|
||||
const configDir = path.dirname(CONFIG_PATH_CLAWDBOT);
|
||||
const configDir = path.dirname(CONFIG_PATH_MOLTBOT);
|
||||
const transformsDir = hooks?.transformsDir
|
||||
? resolvePath(configDir, hooks.transformsDir)
|
||||
: configDir;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../agents/agent-scope.js";
|
||||
import {
|
||||
CONFIG_PATH_CLAWDBOT,
|
||||
CONFIG_PATH_MOLTBOT,
|
||||
loadConfig,
|
||||
parseConfigJson5,
|
||||
readConfigFileSnapshot,
|
||||
@ -186,7 +186,7 @@ export const configHandlers: GatewayRequestHandlers = {
|
||||
true,
|
||||
{
|
||||
ok: true,
|
||||
path: CONFIG_PATH_CLAWDBOT,
|
||||
path: CONFIG_PATH_MOLTBOT,
|
||||
config: validated.config,
|
||||
},
|
||||
undefined,
|
||||
@ -284,7 +284,7 @@ export const configHandlers: GatewayRequestHandlers = {
|
||||
doctorHint: formatDoctorNonInteractiveHint(),
|
||||
stats: {
|
||||
mode: "config.patch",
|
||||
root: CONFIG_PATH_CLAWDBOT,
|
||||
root: CONFIG_PATH_MOLTBOT,
|
||||
},
|
||||
};
|
||||
let sentinelPath: string | null = null;
|
||||
@ -301,7 +301,7 @@ export const configHandlers: GatewayRequestHandlers = {
|
||||
true,
|
||||
{
|
||||
ok: true,
|
||||
path: CONFIG_PATH_CLAWDBOT,
|
||||
path: CONFIG_PATH_MOLTBOT,
|
||||
config: validated.config,
|
||||
restart,
|
||||
sentinel: {
|
||||
@ -381,7 +381,7 @@ export const configHandlers: GatewayRequestHandlers = {
|
||||
doctorHint: formatDoctorNonInteractiveHint(),
|
||||
stats: {
|
||||
mode: "config.apply",
|
||||
root: CONFIG_PATH_CLAWDBOT,
|
||||
root: CONFIG_PATH_MOLTBOT,
|
||||
},
|
||||
};
|
||||
let sentinelPath: string | null = null;
|
||||
@ -398,7 +398,7 @@ export const configHandlers: GatewayRequestHandlers = {
|
||||
true,
|
||||
{
|
||||
ok: true,
|
||||
path: CONFIG_PATH_CLAWDBOT,
|
||||
path: CONFIG_PATH_MOLTBOT,
|
||||
config: validated.config,
|
||||
restart,
|
||||
sentinel: {
|
||||
|
||||
@ -66,7 +66,7 @@ describe("gateway server auth/connect", () => {
|
||||
});
|
||||
|
||||
test("connect (req) handshake returns hello-ok payload", async () => {
|
||||
const { CONFIG_PATH_CLAWDBOT, STATE_DIR_CLAWDBOT } = await import("../config/config.js");
|
||||
const { CONFIG_PATH_MOLTBOT, STATE_DIR_MOLTBOT } = await import("../config/config.js");
|
||||
const ws = await openWs(port);
|
||||
|
||||
const res = await connectReq(ws);
|
||||
@ -78,8 +78,8 @@ describe("gateway server auth/connect", () => {
|
||||
}
|
||||
| undefined;
|
||||
expect(payload?.type).toBe("hello-ok");
|
||||
expect(payload?.snapshot?.configPath).toBe(CONFIG_PATH_CLAWDBOT);
|
||||
expect(payload?.snapshot?.stateDir).toBe(STATE_DIR_CLAWDBOT);
|
||||
expect(payload?.snapshot?.configPath).toBe(CONFIG_PATH_MOLTBOT);
|
||||
expect(payload?.snapshot?.stateDir).toBe(STATE_DIR_MOLTBOT);
|
||||
|
||||
ws.close();
|
||||
});
|
||||
|
||||
@ -6,7 +6,7 @@ import { type ChannelId, listChannelPlugins } from "../channels/plugins/index.js
|
||||
import { createDefaultDeps } from "../cli/deps.js";
|
||||
import { formatCliCommand } from "../cli/command-format.js";
|
||||
import {
|
||||
CONFIG_PATH_CLAWDBOT,
|
||||
CONFIG_PATH_MOLTBOT,
|
||||
isNixMode,
|
||||
loadConfig,
|
||||
migrateLegacyConfig,
|
||||
@ -541,7 +541,7 @@ export async function startGatewayServer(
|
||||
warn: (msg) => logReload.warn(msg),
|
||||
error: (msg) => logReload.error(msg),
|
||||
},
|
||||
watchPath: CONFIG_PATH_CLAWDBOT,
|
||||
watchPath: CONFIG_PATH_MOLTBOT,
|
||||
});
|
||||
|
||||
const close = createGatewayCloseHandler({
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { resolveDefaultAgentId } from "../../agents/agent-scope.js";
|
||||
import { getHealthSnapshot, type HealthSummary } from "../../commands/health.js";
|
||||
import { CONFIG_PATH_CLAWDBOT, STATE_DIR_CLAWDBOT, loadConfig } from "../../config/config.js";
|
||||
import { CONFIG_PATH_MOLTBOT, STATE_DIR_MOLTBOT, loadConfig } from "../../config/config.js";
|
||||
import { resolveMainSessionKey } from "../../config/sessions.js";
|
||||
import { normalizeMainKey } from "../../routing/session-key.js";
|
||||
import { listSystemPresence } from "../../infra/system-presence.js";
|
||||
@ -28,8 +28,8 @@ export function buildGatewaySnapshot(): Snapshot {
|
||||
stateVersion: { presence: presenceVersion, health: healthVersion },
|
||||
uptimeMs,
|
||||
// Surface resolved paths so UIs can display the true config location.
|
||||
configPath: CONFIG_PATH_CLAWDBOT,
|
||||
stateDir: STATE_DIR_CLAWDBOT,
|
||||
configPath: CONFIG_PATH_MOLTBOT,
|
||||
stateDir: STATE_DIR_MOLTBOT,
|
||||
sessionDefaults: {
|
||||
defaultAgentId,
|
||||
mainKey,
|
||||
|
||||
@ -350,10 +350,10 @@ vi.mock("../config/config.js", async () => {
|
||||
|
||||
return {
|
||||
...actual,
|
||||
get CONFIG_PATH_CLAWDBOT() {
|
||||
get CONFIG_PATH_MOLTBOT() {
|
||||
return resolveConfigPath();
|
||||
},
|
||||
get STATE_DIR_CLAWDBOT() {
|
||||
get STATE_DIR_MOLTBOT() {
|
||||
return path.dirname(resolveConfigPath());
|
||||
},
|
||||
get isNixMode() {
|
||||
|
||||
@ -2,7 +2,7 @@ import { spawn } from "node:child_process";
|
||||
|
||||
import {
|
||||
type ClawdbotConfig,
|
||||
CONFIG_PATH_CLAWDBOT,
|
||||
CONFIG_PATH_MOLTBOT,
|
||||
loadConfig,
|
||||
readConfigFileSnapshot,
|
||||
resolveGatewayPort,
|
||||
@ -99,7 +99,7 @@ export async function runGmailSetup(opts: GmailSetupOptions) {
|
||||
|
||||
const configSnapshot = await readConfigFileSnapshot();
|
||||
if (!configSnapshot.valid) {
|
||||
throw new Error(`Config invalid: ${CONFIG_PATH_CLAWDBOT}`);
|
||||
throw new Error(`Config invalid: ${CONFIG_PATH_MOLTBOT}`);
|
||||
}
|
||||
|
||||
const baseConfig = configSnapshot.config;
|
||||
@ -277,7 +277,7 @@ export async function runGmailSetup(opts: GmailSetupOptions) {
|
||||
defaultRuntime.log(`- subscription: ${subscription}`);
|
||||
defaultRuntime.log(`- push endpoint: ${pushEndpoint}`);
|
||||
defaultRuntime.log(`- hook url: ${hookUrl}`);
|
||||
defaultRuntime.log(`- config: ${displayPath(CONFIG_PATH_CLAWDBOT)}`);
|
||||
defaultRuntime.log(`- config: ${displayPath(CONFIG_PATH_MOLTBOT)}`);
|
||||
defaultRuntime.log(`Next: ${formatCliCommand("clawdbot webhooks gmail run")}`);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import type { ClawdbotConfig } from "../config/config.js";
|
||||
import { STATE_DIR_CLAWDBOT } from "../config/paths.js";
|
||||
import { STATE_DIR_MOLTBOT } from "../config/paths.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import type { PluginRegistry } from "./registry.js";
|
||||
|
||||
@ -25,7 +25,7 @@ export async function startPluginServices(params: {
|
||||
await service.start({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
stateDir: STATE_DIR_CLAWDBOT,
|
||||
stateDir: STATE_DIR_MOLTBOT,
|
||||
logger: {
|
||||
info: (msg) => log.info(msg),
|
||||
warn: (msg) => log.warn(msg),
|
||||
@ -40,7 +40,7 @@ export async function startPluginServices(params: {
|
||||
service.stop?.({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
stateDir: STATE_DIR_CLAWDBOT,
|
||||
stateDir: STATE_DIR_MOLTBOT,
|
||||
logger: {
|
||||
info: (msg) => log.info(msg),
|
||||
warn: (msg) => log.warn(msg),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user