refactor: rename clawdbot to moltbot with legacy compat

This commit is contained in:
Peter Steinberger
2026-01-27 12:19:58 +00:00
parent 83460df96f
commit 6d16a658e5
1839 changed files with 11250 additions and 11199 deletions

View File

@@ -1,7 +1,7 @@
import fs from "node:fs";
import path from "node:path";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import { resolveOAuthDir } from "../config/paths.js";
import type { DmPolicy, GroupPolicy, WhatsAppAccountConfig } from "../config/types.js";
import { DEFAULT_ACCOUNT_ID } from "../routing/session-key.js";
@@ -30,13 +30,13 @@ export type ResolvedWhatsAppAccount = {
debounceMs?: number;
};
function listConfiguredAccountIds(cfg: ClawdbotConfig): string[] {
function listConfiguredAccountIds(cfg: MoltbotConfig): string[] {
const accounts = cfg.channels?.whatsapp?.accounts;
if (!accounts || typeof accounts !== "object") return [];
return Object.keys(accounts).filter(Boolean);
}
export function listWhatsAppAuthDirs(cfg: ClawdbotConfig): string[] {
export function listWhatsAppAuthDirs(cfg: MoltbotConfig): string[] {
const oauthDir = resolveOAuthDir();
const whatsappDir = path.join(oauthDir, "whatsapp");
const authDirs = new Set<string>([oauthDir, path.join(whatsappDir, DEFAULT_ACCOUNT_ID)]);
@@ -59,24 +59,24 @@ export function listWhatsAppAuthDirs(cfg: ClawdbotConfig): string[] {
return Array.from(authDirs);
}
export function hasAnyWhatsAppAuth(cfg: ClawdbotConfig): boolean {
export function hasAnyWhatsAppAuth(cfg: MoltbotConfig): boolean {
return listWhatsAppAuthDirs(cfg).some((authDir) => hasWebCredsSync(authDir));
}
export function listWhatsAppAccountIds(cfg: ClawdbotConfig): string[] {
export function listWhatsAppAccountIds(cfg: MoltbotConfig): string[] {
const ids = listConfiguredAccountIds(cfg);
if (ids.length === 0) return [DEFAULT_ACCOUNT_ID];
return ids.sort((a, b) => a.localeCompare(b));
}
export function resolveDefaultWhatsAppAccountId(cfg: ClawdbotConfig): string {
export function resolveDefaultWhatsAppAccountId(cfg: MoltbotConfig): string {
const ids = listWhatsAppAccountIds(cfg);
if (ids.includes(DEFAULT_ACCOUNT_ID)) return DEFAULT_ACCOUNT_ID;
return ids[0] ?? DEFAULT_ACCOUNT_ID;
}
function resolveAccountConfig(
cfg: ClawdbotConfig,
cfg: MoltbotConfig,
accountId: string,
): WhatsAppAccountConfig | undefined {
const accounts = cfg.channels?.whatsapp?.accounts;
@@ -102,7 +102,7 @@ function legacyAuthExists(authDir: string): boolean {
}
}
export function resolveWhatsAppAuthDir(params: { cfg: ClawdbotConfig; accountId: string }): {
export function resolveWhatsAppAuthDir(params: { cfg: MoltbotConfig; accountId: string }): {
authDir: string;
isLegacy: boolean;
} {
@@ -125,7 +125,7 @@ export function resolveWhatsAppAuthDir(params: { cfg: ClawdbotConfig; accountId:
}
export function resolveWhatsAppAccount(params: {
cfg: ClawdbotConfig;
cfg: MoltbotConfig;
accountId?: string | null;
}): ResolvedWhatsAppAccount {
const rootCfg = params.cfg.channels?.whatsapp;
@@ -160,7 +160,7 @@ export function resolveWhatsAppAccount(params: {
};
}
export function listEnabledWhatsAppAccounts(cfg: ClawdbotConfig): ResolvedWhatsAppAccount[] {
export function listEnabledWhatsAppAccounts(cfg: MoltbotConfig): ResolvedWhatsAppAccount[] {
return listWhatsAppAccountIds(cfg)
.map((accountId) => resolveWhatsAppAccount({ cfg, accountId }))
.filter((account) => account.enabled);

View File

@@ -16,7 +16,7 @@ describe("hasAnyWhatsAppAuth", () => {
beforeEach(() => {
previousOauthDir = process.env.CLAWDBOT_OAUTH_DIR;
tempOauthDir = fs.mkdtempSync(path.join(os.tmpdir(), "clawdbot-oauth-"));
tempOauthDir = fs.mkdtempSync(path.join(os.tmpdir(), "moltbot-oauth-"));
process.env.CLAWDBOT_OAUTH_DIR = tempOauthDir;
});
@@ -47,7 +47,7 @@ describe("hasAnyWhatsAppAuth", () => {
});
it("includes authDir overrides", () => {
const customDir = fs.mkdtempSync(path.join(os.tmpdir(), "clawdbot-wa-auth-"));
const customDir = fs.mkdtempSync(path.join(os.tmpdir(), "moltbot-wa-auth-"));
try {
writeCreds(customDir);
const cfg = {

View File

@@ -43,7 +43,7 @@ export function requireActiveWebListener(accountId?: string | null): {
const listener = listeners.get(id) ?? null;
if (!listener) {
throw new Error(
`No active WhatsApp Web listener (account: ${id}). Start the gateway, then link WhatsApp with: ${formatCliCommand(`clawdbot channels login --channel whatsapp --account ${id}`)}.`,
`No active WhatsApp Web listener (account: ${id}). Start the gateway, then link WhatsApp with: ${formatCliCommand(`moltbot channels login --channel whatsapp --account ${id}`)}.`,
);
}
return { accountId: id, listener };

View File

@@ -177,7 +177,7 @@ export async function pickWebChannel(
const hasWeb = await webAuthExists(authDir);
if (!hasWeb) {
throw new Error(
`No WhatsApp Web session found. Run \`${formatCliCommand("clawdbot channels login --channel whatsapp --verbose")}\` to link.`,
`No WhatsApp Web session found. Run \`${formatCliCommand("moltbot channels login --channel whatsapp --verbose")}\` to link.`,
);
}
return choice;

View File

@@ -14,7 +14,7 @@ vi.mock("../agents/pi-embedded.js", () => ({
}));
import { resetInboundDedupe } from "../auto-reply/reply/inbound-dedupe.js";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import { monitorWebChannel } from "./auto-reply.js";
import { resetLoadConfigMock, setLoadConfigMock } from "./test-helpers.js";
@@ -46,7 +46,7 @@ const rmDirWithRetries = async (dir: string): Promise<void> => {
beforeEach(async () => {
resetInboundDedupe();
previousHome = process.env.HOME;
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-web-home-"));
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-web-home-"));
process.env.HOME = tempHome;
});
@@ -61,7 +61,7 @@ afterEach(async () => {
const _makeSessionStore = async (
entries: Record<string, unknown> = {},
): Promise<{ storePath: string; cleanup: () => Promise<void> }> => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-session-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-session-"));
const storePath = path.join(dir, "sessions.json");
await fs.writeFile(storePath, JSON.stringify(entries));
const cleanup = async () => {
@@ -104,7 +104,7 @@ describe("broadcast groups", () => {
strategy: "sequential",
"+1000": ["alfred", "baerbel"],
},
} satisfies ClawdbotConfig);
} satisfies MoltbotConfig);
const sendMedia = vi.fn();
const reply = vi.fn().mockResolvedValue(undefined);
@@ -158,7 +158,7 @@ describe("broadcast groups", () => {
strategy: "sequential",
"123@g.us": ["alfred", "baerbel"],
},
} satisfies ClawdbotConfig);
} satisfies MoltbotConfig);
const sendMedia = vi.fn();
const reply = vi.fn().mockResolvedValue(undefined);
@@ -269,7 +269,7 @@ describe("broadcast groups", () => {
strategy: "parallel",
"+1000": ["alfred", "baerbel"],
},
} satisfies ClawdbotConfig);
} satisfies MoltbotConfig);
const sendMedia = vi.fn();
const reply = vi.fn().mockResolvedValue(undefined);

View File

@@ -14,7 +14,7 @@ vi.mock("../agents/pi-embedded.js", () => ({
}));
import { resetInboundDedupe } from "../auto-reply/reply/inbound-dedupe.js";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import { monitorWebChannel } from "./auto-reply.js";
import { resetLoadConfigMock, setLoadConfigMock } from "./test-helpers.js";
@@ -46,7 +46,7 @@ const rmDirWithRetries = async (dir: string): Promise<void> => {
beforeEach(async () => {
resetInboundDedupe();
previousHome = process.env.HOME;
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-web-home-"));
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-web-home-"));
process.env.HOME = tempHome;
});
@@ -61,7 +61,7 @@ afterEach(async () => {
const _makeSessionStore = async (
entries: Record<string, unknown> = {},
): Promise<{ storePath: string; cleanup: () => Promise<void> }> => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-session-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-session-"));
const storePath = path.join(dir, "sessions.json");
await fs.writeFile(storePath, JSON.stringify(entries));
const cleanup = async () => {
@@ -103,7 +103,7 @@ describe("broadcast groups", () => {
broadcast: {
"+1000": ["alfred", "missing"],
},
} satisfies ClawdbotConfig);
} satisfies MoltbotConfig);
const sendMedia = vi.fn();
const reply = vi.fn().mockResolvedValue(undefined);

View File

@@ -16,7 +16,7 @@ vi.mock("../agents/pi-embedded.js", () => ({
import { runEmbeddedPiAgent } from "../agents/pi-embedded.js";
import { resetInboundDedupe } from "../auto-reply/reply/inbound-dedupe.js";
import { getReplyFromConfig } from "../auto-reply/reply.js";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import { monitorWebChannel } from "./auto-reply.js";
import { resetLoadConfigMock, setLoadConfigMock } from "./test-helpers.js";
@@ -48,7 +48,7 @@ const rmDirWithRetries = async (dir: string): Promise<void> => {
beforeEach(async () => {
resetInboundDedupe();
previousHome = process.env.HOME;
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-web-home-"));
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-web-home-"));
process.env.HOME = tempHome;
});
@@ -63,7 +63,7 @@ afterEach(async () => {
const makeSessionStore = async (
entries: Record<string, unknown> = {},
): Promise<{ storePath: string; cleanup: () => Promise<void> }> => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-session-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-session-"));
const storePath = path.join(dir, "sessions.json");
await fs.writeFile(storePath, JSON.stringify(entries));
const cleanup = async () => {
@@ -102,7 +102,7 @@ describe("partial reply gating", () => {
const replyResolver = vi.fn().mockResolvedValue({ text: "final reply" });
const mockConfig: ClawdbotConfig = {
const mockConfig: MoltbotConfig = {
channels: { whatsapp: { allowFrom: ["*"] } },
};
@@ -145,7 +145,7 @@ describe("partial reply gating", () => {
const replyResolver = vi.fn().mockResolvedValue({ text: "final reply" });
const mockConfig: ClawdbotConfig = {
const mockConfig: MoltbotConfig = {
channels: {
whatsapp: {
allowFrom: ["*"],
@@ -195,7 +195,7 @@ describe("partial reply gating", () => {
const replyResolver = vi.fn().mockResolvedValue(undefined);
const mockConfig: ClawdbotConfig = {
const mockConfig: MoltbotConfig = {
channels: { whatsapp: { allowFrom: ["*"] } },
session: { store: store.storePath },
};
@@ -249,7 +249,7 @@ describe("partial reply gating", () => {
const replyResolver = vi.fn().mockResolvedValue(undefined);
const mockConfig: ClawdbotConfig = {
const mockConfig: MoltbotConfig = {
channels: { whatsapp: { allowFrom: ["*"] } },
session: { store: store.storePath },
};

View File

@@ -14,7 +14,7 @@ vi.mock("../agents/pi-embedded.js", () => ({
}));
import { resetInboundDedupe } from "../auto-reply/reply/inbound-dedupe.js";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import { monitorWebChannel } from "./auto-reply.js";
import { resetLoadConfigMock, setLoadConfigMock } from "./test-helpers.js";
@@ -46,7 +46,7 @@ const rmDirWithRetries = async (dir: string): Promise<void> => {
beforeEach(async () => {
resetInboundDedupe();
previousHome = process.env.HOME;
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-web-home-"));
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-web-home-"));
process.env.HOME = tempHome;
});
@@ -61,7 +61,7 @@ afterEach(async () => {
const _makeSessionStore = async (
entries: Record<string, unknown> = {},
): Promise<{ storePath: string; cleanup: () => Promise<void> }> => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-session-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-session-"));
const storePath = path.join(dir, "sessions.json");
await fs.writeFile(storePath, JSON.stringify(entries));
const cleanup = async () => {
@@ -114,7 +114,7 @@ describe("typing controller idle", () => {
return { text: "final reply" };
});
const mockConfig: ClawdbotConfig = {
const mockConfig: MoltbotConfig = {
channels: { whatsapp: { allowFrom: ["*"] } },
};

View File

@@ -48,7 +48,7 @@ const rmDirWithRetries = async (dir: string): Promise<void> => {
beforeEach(async () => {
resetInboundDedupe();
previousHome = process.env.HOME;
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-web-home-"));
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-web-home-"));
process.env.HOME = tempHome;
});
@@ -63,7 +63,7 @@ afterEach(async () => {
const _makeSessionStore = async (
entries: Record<string, unknown> = {},
): Promise<{ storePath: string; cleanup: () => Promise<void> }> => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-session-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-session-"));
const storePath = path.join(dir, "sessions.json");
await fs.writeFile(storePath, JSON.stringify(entries));
const cleanup = async () => {

View File

@@ -47,7 +47,7 @@ const rmDirWithRetries = async (dir: string): Promise<void> => {
beforeEach(async () => {
resetInboundDedupe();
previousHome = process.env.HOME;
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-web-home-"));
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-web-home-"));
process.env.HOME = tempHome;
});
@@ -62,7 +62,7 @@ afterEach(async () => {
const _makeSessionStore = async (
entries: Record<string, unknown> = {},
): Promise<{ storePath: string; cleanup: () => Promise<void> }> => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-session-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-session-"));
const storePath = path.join(dir, "sessions.json");
await fs.writeFile(storePath, JSON.stringify(entries));
const cleanup = async () => {

View File

@@ -46,7 +46,7 @@ const rmDirWithRetries = async (dir: string): Promise<void> => {
beforeEach(async () => {
resetInboundDedupe();
previousHome = process.env.HOME;
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-web-home-"));
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-web-home-"));
process.env.HOME = tempHome;
});
@@ -61,7 +61,7 @@ afterEach(async () => {
const _makeSessionStore = async (
entries: Record<string, unknown> = {},
): Promise<{ storePath: string; cleanup: () => Promise<void> }> => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-session-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-session-"));
const storePath = path.join(dir, "sessions.json");
await fs.writeFile(storePath, JSON.stringify(entries));
const cleanup = async () => {

View File

@@ -47,7 +47,7 @@ const rmDirWithRetries = async (dir: string): Promise<void> => {
beforeEach(async () => {
resetInboundDedupe();
previousHome = process.env.HOME;
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-web-home-"));
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-web-home-"));
process.env.HOME = tempHome;
});
@@ -62,7 +62,7 @@ afterEach(async () => {
const makeSessionStore = async (
entries: Record<string, unknown> = {},
): Promise<{ storePath: string; cleanup: () => Promise<void> }> => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-session-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-session-"));
const storePath = path.join(dir, "sessions.json");
await fs.writeFile(storePath, JSON.stringify(entries));
const cleanup = async () => {
@@ -339,11 +339,11 @@ describe("web auto-reply", () => {
const firstPattern = escapeRegExp(firstTimestamp);
const secondPattern = escapeRegExp(secondTimestamp);
expect(firstArgs.Body).toMatch(
new RegExp(`\\[WhatsApp \\+1 (\\+\\d+[smhd] )?${firstPattern}\\] \\[clawdbot\\] first`),
new RegExp(`\\[WhatsApp \\+1 (\\+\\d+[smhd] )?${firstPattern}\\] \\[moltbot\\] first`),
);
expect(firstArgs.Body).not.toContain("second");
expect(secondArgs.Body).toMatch(
new RegExp(`\\[WhatsApp \\+1 (\\+\\d+[smhd] )?${secondPattern}\\] \\[clawdbot\\] second`),
new RegExp(`\\[WhatsApp \\+1 (\\+\\d+[smhd] )?${secondPattern}\\] \\[moltbot\\] second`),
);
expect(secondArgs.Body).not.toContain("first");

View File

@@ -46,7 +46,7 @@ const rmDirWithRetries = async (dir: string): Promise<void> => {
beforeEach(async () => {
resetInboundDedupe();
previousHome = process.env.HOME;
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-web-home-"));
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-web-home-"));
process.env.HOME = tempHome;
});
@@ -61,7 +61,7 @@ afterEach(async () => {
const _makeSessionStore = async (
entries: Record<string, unknown> = {},
): Promise<{ storePath: string; cleanup: () => Promise<void> }> => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-session-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-session-"));
const storePath = path.join(dir, "sessions.json");
await fs.writeFile(storePath, JSON.stringify(entries));
const cleanup = async () => {
@@ -366,7 +366,7 @@ describe("web auto-reply", () => {
return { close: vi.fn() };
};
const authDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-wa-auth-"));
const authDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-wa-auth-"));
try {
await fs.writeFile(
@@ -444,7 +444,7 @@ describe("web auto-reply", () => {
return { close: vi.fn() };
};
const authDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-wa-auth-"));
const authDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-wa-auth-"));
try {
await fs.writeFile(

View File

@@ -46,7 +46,7 @@ const rmDirWithRetries = async (dir: string): Promise<void> => {
beforeEach(async () => {
resetInboundDedupe();
previousHome = process.env.HOME;
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-web-home-"));
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-web-home-"));
process.env.HOME = tempHome;
});
@@ -61,7 +61,7 @@ afterEach(async () => {
const _makeSessionStore = async (
entries: Record<string, unknown> = {},
): Promise<{ storePath: string; cleanup: () => Promise<void> }> => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-session-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-session-"));
const storePath = path.join(dir, "sessions.json");
await fs.writeFile(storePath, JSON.stringify(entries));
const cleanup = async () => {
@@ -200,7 +200,7 @@ describe("web auto-reply", () => {
expect(resolver).toHaveBeenCalled();
const resolverArg = resolver.mock.calls[0][0];
expect(resolverArg.Body).toContain("[Richbot]");
expect(resolverArg.Body).not.toContain("[clawdbot]");
expect(resolverArg.Body).not.toContain("[moltbot]");
resetLoadConfigMock();
});
it("does not derive responsePrefix from identity.name when unset", async () => {

View File

@@ -48,7 +48,7 @@ const rmDirWithRetries = async (dir: string): Promise<void> => {
beforeEach(async () => {
resetInboundDedupe();
previousHome = process.env.HOME;
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-web-home-"));
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-web-home-"));
process.env.HOME = tempHome;
});
@@ -63,7 +63,7 @@ afterEach(async () => {
const makeSessionStore = async (
entries: Record<string, unknown> = {},
): Promise<{ storePath: string; cleanup: () => Promise<void> }> => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-session-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-session-"));
const storePath = path.join(dir, "sessions.json");
await fs.writeFile(storePath, JSON.stringify(entries));
const cleanup = async () => {
@@ -272,7 +272,7 @@ describe("web auto-reply", () => {
});
it("emits heartbeat logs with connection metadata", async () => {
vi.useFakeTimers();
const logPath = `/tmp/clawdbot-heartbeat-${crypto.randomUUID()}.log`;
const logPath = `/tmp/moltbot-heartbeat-${crypto.randomUUID()}.log`;
setLoggerOverride({ level: "trace", file: logPath });
const runtime = {
@@ -313,7 +313,7 @@ describe("web auto-reply", () => {
expect(content).toMatch(/messagesHandled/);
});
it("logs outbound replies to file", async () => {
const logPath = `/tmp/clawdbot-log-test-${crypto.randomUUID()}.log`;
const logPath = `/tmp/moltbot-log-test-${crypto.randomUUID()}.log`;
setLoggerOverride({ level: "trace", file: logPath });
let capturedOnMessage:

View File

@@ -46,7 +46,7 @@ const rmDirWithRetries = async (dir: string): Promise<void> => {
beforeEach(async () => {
resetInboundDedupe();
previousHome = process.env.HOME;
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-web-home-"));
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-web-home-"));
process.env.HOME = tempHome;
});
@@ -61,7 +61,7 @@ afterEach(async () => {
const _makeSessionStore = async (
entries: Record<string, unknown> = {},
): Promise<{ storePath: string; cleanup: () => Promise<void> }> => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-session-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-session-"));
const storePath = path.join(dir, "sessions.json");
await fs.writeFile(storePath, JSON.stringify(entries));
const cleanup = async () => {

View File

@@ -376,7 +376,7 @@ export async function monitorWebChannel(
if (loggedOut) {
runtime.error(
`WhatsApp session logged out. Run \`${formatCliCommand("clawdbot channels login --channel web")}\` to relink.`,
`WhatsApp session logged out. Run \`${formatCliCommand("moltbot channels login --channel web")}\` to relink.`,
);
await closeListener();
break;

View File

@@ -9,7 +9,7 @@ const baseConfig = {
groups: { "*": { requireMention: true } },
},
},
session: { store: "/tmp/clawdbot-sessions.json" },
session: { store: "/tmp/moltbot-sessions.json" },
} as const;
describe("applyGroupGating", () => {

View File

@@ -252,7 +252,7 @@ export async function processMessage(params: {
const responsePrefix =
prefixContext.responsePrefix ??
(configuredResponsePrefix === undefined && isSelfChat
? (resolveIdentityNamePrefix(params.cfg, params.route.agentId) ?? "[clawdbot]")
? (resolveIdentityNamePrefix(params.cfg, params.route.agentId) ?? "[moltbot]")
: undefined);
const ctxPayload = finalizeInboundContext({

View File

@@ -12,7 +12,7 @@ describe("getSessionSnapshot", () => {
vi.useFakeTimers();
vi.setSystemTime(new Date(2026, 0, 18, 5, 0, 0));
try {
const root = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-snapshot-"));
const root = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-snapshot-"));
const storePath = path.join(root, "sessions.json");
const sessionKey = "agent:main:whatsapp:dm:s1";

View File

@@ -43,7 +43,7 @@ vi.mock("../media/store.js", async (importOriginal) => {
};
});
const HOME = path.join(os.tmpdir(), `clawdbot-inbound-media-${crypto.randomUUID()}`);
const HOME = path.join(os.tmpdir(), `moltbot-inbound-media-${crypto.randomUUID()}`);
process.env.HOME = HOME;
vi.mock("@whiskeysockets/baileys", async () => {

View File

@@ -57,7 +57,7 @@ export async function loginWeb(
});
console.error(
danger(
`WhatsApp reported the session is logged out. Cleared cached web session; please rerun ${formatCliCommand("clawdbot channels login")} and scan the QR again.`,
`WhatsApp reported the session is logged out. Cleared cached web session; please rerun ${formatCliCommand("moltbot channels login")} and scan the QR again.`,
),
);
throw new Error("Session logged out; cache cleared. Re-run login.");

View File

@@ -13,7 +13,7 @@ const tmpFiles: string[] = [];
async function writeTempFile(buffer: Buffer, ext: string): Promise<string> {
const file = path.join(
os.tmpdir(),
`clawdbot-media-${Date.now()}-${Math.random().toString(16).slice(2)}${ext}`,
`moltbot-media-${Date.now()}-${Math.random().toString(16).slice(2)}${ext}`,
);
tmpFiles.push(file);
await fs.writeFile(file, buffer);

View File

@@ -88,7 +88,7 @@ describe("web monitor inbox", () => {
created: true,
});
resetWebInboundDedupe();
authDir = fsSync.mkdtempSync(path.join(os.tmpdir(), "clawdbot-auth-"));
authDir = fsSync.mkdtempSync(path.join(os.tmpdir(), "moltbot-auth-"));
});
afterEach(() => {

View File

@@ -88,7 +88,7 @@ describe("web monitor inbox", () => {
created: true,
});
resetWebInboundDedupe();
authDir = fsSync.mkdtempSync(path.join(os.tmpdir(), "clawdbot-auth-"));
authDir = fsSync.mkdtempSync(path.join(os.tmpdir(), "moltbot-auth-"));
});
afterEach(() => {

View File

@@ -88,7 +88,7 @@ describe("web monitor inbox", () => {
created: true,
});
resetWebInboundDedupe();
authDir = fsSync.mkdtempSync(path.join(os.tmpdir(), "clawdbot-auth-"));
authDir = fsSync.mkdtempSync(path.join(os.tmpdir(), "moltbot-auth-"));
});
afterEach(() => {
@@ -171,7 +171,7 @@ describe("web monitor inbox", () => {
});
it("logs inbound bodies to file", async () => {
const logPath = path.join(os.tmpdir(), `clawdbot-log-test-${crypto.randomUUID()}.log`);
const logPath = path.join(os.tmpdir(), `moltbot-log-test-${crypto.randomUUID()}.log`);
setLoggerOverride({ level: "trace", file: logPath });
const onMessage = vi.fn();

View File

@@ -87,7 +87,7 @@ describe("web monitor inbox", () => {
created: true,
});
resetWebInboundDedupe();
authDir = fsSync.mkdtempSync(path.join(os.tmpdir(), "clawdbot-auth-"));
authDir = fsSync.mkdtempSync(path.join(os.tmpdir(), "moltbot-auth-"));
});
afterEach(() => {

View File

@@ -7,7 +7,7 @@ import { renderQrPngBase64 } from "./qr-image.js";
describe("renderQrPngBase64", () => {
it("renders a PNG data payload", async () => {
const b64 = await renderQrPngBase64("clawdbot");
const b64 = await renderQrPngBase64("moltbot");
const buf = Buffer.from(b64, "base64");
expect(buf.subarray(0, 8).toString("hex")).toBe("89504e470d0a1a0a");
});

View File

@@ -1,6 +1,6 @@
import { describe, expect, it } from "vitest";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import {
computeBackoff,
DEFAULT_HEARTBEAT_SECONDS,
@@ -11,7 +11,7 @@ import {
} from "./reconnect.js";
describe("web reconnect helpers", () => {
const cfg: ClawdbotConfig = {};
const cfg: MoltbotConfig = {};
it("resolves sane reconnect defaults with clamps", () => {
const policy = resolveReconnectPolicy(cfg, {

View File

@@ -1,6 +1,6 @@
import { randomUUID } from "node:crypto";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import type { BackoffPolicy } from "../infra/backoff.js";
import { computeBackoff, sleepWithAbort } from "../infra/backoff.js";
@@ -19,14 +19,14 @@ export const DEFAULT_RECONNECT_POLICY: ReconnectPolicy = {
const clamp = (val: number, min: number, max: number) => Math.max(min, Math.min(max, val));
export function resolveHeartbeatSeconds(cfg: ClawdbotConfig, overrideSeconds?: number): number {
export function resolveHeartbeatSeconds(cfg: MoltbotConfig, overrideSeconds?: number): number {
const candidate = overrideSeconds ?? cfg.web?.heartbeatSeconds;
if (typeof candidate === "number" && candidate > 0) return candidate;
return DEFAULT_HEARTBEAT_SECONDS;
}
export function resolveReconnectPolicy(
cfg: ClawdbotConfig,
cfg: MoltbotConfig,
overrides?: Partial<ReconnectPolicy>,
): ReconnectPolicy {
const reconnectOverrides = cfg.web?.reconnect ?? {};

View File

@@ -114,7 +114,7 @@ export async function createWaSocket(
version,
logger,
printQRInTerminal: false,
browser: ["clawdbot", "cli", VERSION],
browser: ["moltbot", "cli", VERSION],
syncFullHistory: false,
markOnlineOnConnect: false,
});
@@ -137,7 +137,7 @@ export async function createWaSocket(
if (status === DisconnectReason.loggedOut) {
console.error(
danger(
`WhatsApp session logged out. Run: ${formatCliCommand("clawdbot channels login")}`,
`WhatsApp session logged out. Run: ${formatCliCommand("moltbot channels login")}`,
),
);
}

View File

@@ -4,7 +4,7 @@ import type { MockBaileysSocket } from "../../test/mocks/baileys.js";
import { createMockBaileys } from "../../test/mocks/baileys.js";
// Use globalThis to store the mock config so it survives vi.mock hoisting
const CONFIG_KEY = Symbol.for("clawdbot:testConfigMock");
const CONFIG_KEY = Symbol.for("moltbot:testConfigMock");
const DEFAULT_CONFIG = {
channels: {
whatsapp: {
@@ -54,7 +54,7 @@ vi.mock("../media/store.js", () => ({
vi.mock("@whiskeysockets/baileys", () => {
const created = createMockBaileys();
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("clawdbot:lastSocket")] =
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("moltbot:lastSocket")] =
created.lastSocket;
return created.mod;
});
@@ -74,7 +74,7 @@ export const baileys =
export function resetBaileysMocks() {
const recreated = createMockBaileys();
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("clawdbot:lastSocket")] =
(globalThis as Record<PropertyKey, unknown>)[Symbol.for("moltbot:lastSocket")] =
recreated.lastSocket;
baileys.makeWASocket.mockImplementation(recreated.mod.makeWASocket);
baileys.useMultiFileAuthState.mockImplementation(recreated.mod.useMultiFileAuthState);
@@ -83,7 +83,7 @@ export function resetBaileysMocks() {
}
export function getLastSocket(): MockBaileysSocket {
const getter = (globalThis as Record<PropertyKey, unknown>)[Symbol.for("clawdbot:lastSocket")];
const getter = (globalThis as Record<PropertyKey, unknown>)[Symbol.for("moltbot:lastSocket")];
if (typeof getter === "function") return (getter as () => MockBaileysSocket)();
if (!getter) throw new Error("Baileys mock not initialized");
throw new Error("Invalid Baileys socket getter");