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,11 +1,11 @@
import { describe, expect, it } from "vitest";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import { DEFAULT_ASSISTANT_IDENTITY, resolveAssistantIdentity } from "./assistant-identity.js";
describe("resolveAssistantIdentity avatar normalization", () => {
it("drops sentence-like avatar placeholders", () => {
const cfg: ClawdbotConfig = {
const cfg: MoltbotConfig = {
ui: {
assistant: {
avatar: "workspace-relative path, http(s) URL, or data URI",
@@ -19,7 +19,7 @@ describe("resolveAssistantIdentity avatar normalization", () => {
});
it("keeps short text avatars", () => {
const cfg: ClawdbotConfig = {
const cfg: MoltbotConfig = {
ui: {
assistant: {
avatar: "PS",
@@ -31,7 +31,7 @@ describe("resolveAssistantIdentity avatar normalization", () => {
});
it("keeps path avatars", () => {
const cfg: ClawdbotConfig = {
const cfg: MoltbotConfig = {
ui: {
assistant: {
avatar: "avatars/clawd.png",

View File

@@ -1,7 +1,7 @@
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent-scope.js";
import { resolveAgentIdentity } from "../agents/identity.js";
import { loadAgentIdentity } from "../commands/agents.config.js";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import { normalizeAgentId } from "../routing/session-key.js";
const MAX_ASSISTANT_NAME = 50;
@@ -47,7 +47,7 @@ function normalizeAvatarValue(value: string | undefined): string | undefined {
}
export function resolveAssistantIdentity(params: {
cfg: ClawdbotConfig;
cfg: MoltbotConfig;
agentId?: string | null;
workspaceDir?: string | null;
}): AssistantIdentity {

View File

@@ -26,7 +26,7 @@ describe("runBootOnce", () => {
});
it("skips when BOOT.md is missing", async () => {
const workspaceDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-boot-"));
const workspaceDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-boot-"));
await expect(runBootOnce({ cfg: {}, deps: makeDeps(), workspaceDir })).resolves.toEqual({
status: "skipped",
reason: "missing",
@@ -36,7 +36,7 @@ describe("runBootOnce", () => {
});
it("skips when BOOT.md is empty", async () => {
const workspaceDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-boot-"));
const workspaceDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-boot-"));
await fs.writeFile(path.join(workspaceDir, "BOOT.md"), " \n", "utf-8");
await expect(runBootOnce({ cfg: {}, deps: makeDeps(), workspaceDir })).resolves.toEqual({
status: "skipped",
@@ -47,7 +47,7 @@ describe("runBootOnce", () => {
});
it("runs agent command when BOOT.md exists", async () => {
const workspaceDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-boot-"));
const workspaceDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-boot-"));
const content = "Say hello when you wake up.";
await fs.writeFile(path.join(workspaceDir, "BOOT.md"), content, "utf-8");

View File

@@ -3,7 +3,7 @@ import path from "node:path";
import { SILENT_REPLY_TOKEN } from "../auto-reply/tokens.js";
import type { CliDeps } from "../cli/deps.js";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import { resolveMainSessionKey } from "../config/sessions/main-session.js";
import { agentCommand } from "../commands/agent.js";
import { createSubsystemLogger } from "../logging/subsystem.js";
@@ -48,7 +48,7 @@ async function loadBootFile(
}
export async function runBootOnce(params: {
cfg: ClawdbotConfig;
cfg: MoltbotConfig;
deps: CliDeps;
workspaceDir: string;
}): Promise<BootRunResult> {

View File

@@ -1,5 +1,5 @@
import { randomUUID } from "node:crypto";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import {
loadConfig,
resolveConfigPath,
@@ -23,7 +23,7 @@ export type CallGatewayOptions = {
token?: string;
password?: string;
tlsFingerprint?: string;
config?: ClawdbotConfig;
config?: MoltbotConfig;
method: string;
params?: unknown;
expectFinal?: boolean;
@@ -52,7 +52,7 @@ export type GatewayConnectionDetails = {
};
export function buildGatewayConnectionDetails(
options: { config?: ClawdbotConfig; url?: string; configPath?: string } = {},
options: { config?: MoltbotConfig; url?: string; configPath?: string } = {},
): GatewayConnectionDetails {
const config = options.config ?? loadConfig();
const configPath =

View File

@@ -1,7 +1,7 @@
import chokidar from "chokidar";
import { type ChannelId, listChannelPlugins } from "../channels/plugins/index.js";
import { getActivePluginRegistry } from "../plugins/runtime.js";
import type { ClawdbotConfig, ConfigFileSnapshot, GatewayReloadMode } from "../config/config.js";
import type { MoltbotConfig, ConfigFileSnapshot, GatewayReloadMode } from "../config/config.js";
export type GatewayReloadSettings = {
mode: GatewayReloadMode;
@@ -156,7 +156,7 @@ export function diffConfigPaths(prev: unknown, next: unknown, prefix = ""): stri
return [prefix || "<root>"];
}
export function resolveGatewayReloadSettings(cfg: ClawdbotConfig): GatewayReloadSettings {
export function resolveGatewayReloadSettings(cfg: MoltbotConfig): GatewayReloadSettings {
const rawMode = cfg.gateway?.reload?.mode;
const mode =
rawMode === "off" || rawMode === "restart" || rawMode === "hot" || rawMode === "hybrid"
@@ -246,10 +246,10 @@ export type GatewayConfigReloader = {
};
export function startGatewayConfigReloader(opts: {
initialConfig: ClawdbotConfig;
initialConfig: MoltbotConfig;
readSnapshot: () => Promise<ConfigFileSnapshot>;
onHotReload: (plan: GatewayReloadPlan, nextConfig: ClawdbotConfig) => Promise<void>;
onRestart: (plan: GatewayReloadPlan, nextConfig: ClawdbotConfig) => void;
onHotReload: (plan: GatewayReloadPlan, nextConfig: MoltbotConfig) => Promise<void>;
onRestart: (plan: GatewayReloadPlan, nextConfig: MoltbotConfig) => void;
log: {
info: (msg: string) => void;
warn: (msg: string) => void;

View File

@@ -3,7 +3,7 @@ import type { IncomingMessage, ServerResponse } from "node:http";
import path from "node:path";
import { fileURLToPath } from "node:url";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import { DEFAULT_ASSISTANT_IDENTITY, resolveAssistantIdentity } from "./assistant-identity.js";
import {
buildControlUiAvatarUrl,
@@ -16,7 +16,7 @@ const ROOT_PREFIX = "/";
export type ControlUiRequestOptions = {
basePath?: string;
config?: ClawdbotConfig;
config?: MoltbotConfig;
agentId?: string;
};
@@ -195,7 +195,7 @@ function injectControlUiConfig(html: string, opts: ControlUiInjectionOpts): stri
interface ServeIndexHtmlOpts {
basePath: string;
config?: ClawdbotConfig;
config?: MoltbotConfig;
agentId?: string;
}

View File

@@ -246,7 +246,7 @@ describeLive("gateway live (cli backend)", () => {
);
}
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-live-cli-"));
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-live-cli-"));
const disableMcpConfig = process.env.CLAWDBOT_LIVE_CLI_BACKEND_DISABLE_MCP_CONFIG !== "0";
let cliArgs = baseCliArgs;
if (providerId === "claude-cli" && disableMcpConfig) {
@@ -281,7 +281,7 @@ describeLive("gateway live (cli backend)", () => {
},
},
};
const tempConfigPath = path.join(tempDir, "clawdbot.json");
const tempConfigPath = path.join(tempDir, "moltbot.json");
await fs.writeFile(tempConfigPath, `${JSON.stringify(nextCfg, null, 2)}\n`);
process.env.CLAWDBOT_CONFIG_PATH = tempConfigPath;

View File

@@ -7,7 +7,7 @@ import path from "node:path";
import type { Api, Model } from "@mariozechner/pi-ai";
import { discoverAuthStorage, discoverModels } from "@mariozechner/pi-coding-agent";
import { describe, it } from "vitest";
import { resolveClawdbotAgentDir } from "../agents/agent-paths.js";
import { resolveMoltbotAgentDir } from "../agents/agent-paths.js";
import { resolveAgentWorkspaceDir } from "../agents/agent-scope.js";
import {
type AuthProfileStore,
@@ -21,9 +21,9 @@ import {
} from "../agents/live-auth-keys.js";
import { isModernModelRef } from "../agents/live-model-filter.js";
import { getApiKeyForModel } from "../agents/model-auth.js";
import { ensureClawdbotModelsJson } from "../agents/models-config.js";
import { ensureMoltbotModelsJson } from "../agents/models-config.js";
import { loadConfig } from "../config/config.js";
import type { ClawdbotConfig, ModelProviderConfig } from "../config/types.js";
import type { MoltbotConfig, ModelProviderConfig } from "../config/types.js";
import { isTruthyEnvValue } from "../infra/env.js";
import { DEFAULT_AGENT_ID } from "../routing/session-key.js";
import { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } from "../utils/message-channel.js";
@@ -331,7 +331,7 @@ async function connectClient(params: { url: string; token: string }) {
type GatewayModelSuiteParams = {
label: string;
cfg: ClawdbotConfig;
cfg: MoltbotConfig;
candidates: Array<Model<Api>>;
extraToolProbes: boolean;
extraImageProbes: boolean;
@@ -340,10 +340,10 @@ type GatewayModelSuiteParams = {
};
function buildLiveGatewayConfig(params: {
cfg: ClawdbotConfig;
cfg: MoltbotConfig;
candidates: Array<Model<Api>>;
providerOverrides?: Record<string, ModelProviderConfig>;
}): ClawdbotConfig {
}): MoltbotConfig {
const providerOverrides = params.providerOverrides ?? {};
const lmstudioProvider = params.cfg.models?.providers?.lmstudio;
const baseProviders = params.cfg.models?.providers ?? {};
@@ -382,16 +382,16 @@ function buildLiveGatewayConfig(params: {
}
function sanitizeAuthConfig(params: {
cfg: ClawdbotConfig;
cfg: MoltbotConfig;
agentDir: string;
}): ClawdbotConfig["auth"] | undefined {
}): MoltbotConfig["auth"] | undefined {
const auth = params.cfg.auth;
if (!auth) return auth;
const store = ensureAuthProfileStore(params.agentDir, {
allowKeychainPrompt: false,
});
let profiles: NonNullable<ClawdbotConfig["auth"]>["profiles"] | undefined;
let profiles: NonNullable<MoltbotConfig["auth"]>["profiles"] | undefined;
if (auth.profiles) {
profiles = {};
for (const [profileId, profile] of Object.entries(auth.profiles)) {
@@ -421,7 +421,7 @@ function sanitizeAuthConfig(params: {
}
function buildMinimaxProviderOverride(params: {
cfg: ClawdbotConfig;
cfg: MoltbotConfig;
api: "openai-completions" | "anthropic-messages";
baseUrl: string;
}): ModelProviderConfig | null {
@@ -458,7 +458,7 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {
process.env.CLAWDBOT_GATEWAY_TOKEN = token;
const agentId = "dev";
const hostAgentDir = resolveClawdbotAgentDir();
const hostAgentDir = resolveMoltbotAgentDir();
const hostStore = ensureAuthProfileStore(hostAgentDir, {
allowKeychainPrompt: false,
});
@@ -471,7 +471,7 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {
lastGood: hostStore.lastGood ? { ...hostStore.lastGood } : undefined,
usageStats: hostStore.usageStats ? { ...hostStore.usageStats } : undefined,
};
tempStateDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-live-state-"));
tempStateDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-live-state-"));
process.env.CLAWDBOT_STATE_DIR = tempStateDir;
tempAgentDir = path.join(tempStateDir, "agents", DEFAULT_AGENT_ID, "agent");
saveAuthProfileStore(sanitizedStore, tempAgentDir);
@@ -489,8 +489,8 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {
const toolProbePath = path.join(workspaceDir, `.clawdbot-live-tool-probe.${nonceA}.txt`);
await fs.writeFile(toolProbePath, `nonceA=${nonceA}\nnonceB=${nonceB}\n`);
const agentDir = resolveClawdbotAgentDir();
const sanitizedCfg: ClawdbotConfig = {
const agentDir = resolveMoltbotAgentDir();
const sanitizedCfg: MoltbotConfig = {
...params.cfg,
auth: sanitizeAuthConfig({ cfg: params.cfg, agentDir }),
};
@@ -499,12 +499,12 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {
candidates: params.candidates,
providerOverrides: params.providerOverrides,
});
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-live-"));
const tempConfigPath = path.join(tempDir, "clawdbot.json");
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-live-"));
const tempConfigPath = path.join(tempDir, "moltbot.json");
await fs.writeFile(tempConfigPath, `${JSON.stringify(nextCfg, null, 2)}\n`);
process.env.CLAWDBOT_CONFIG_PATH = tempConfigPath;
await ensureClawdbotModelsJson(nextCfg);
await ensureMoltbotModelsJson(nextCfg);
const port = await getFreeGatewayPort();
const server = await startGatewayServer(port, {
@@ -636,7 +636,7 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {
sessionKey,
idempotencyKey: `idem-${runIdTool}-tool`,
message:
"Clawdbot live tool probe (local, safe): " +
"Moltbot live tool probe (local, safe): " +
`use the tool named \`read\` (or \`Read\`) with JSON arguments {"path":"${toolProbePath}"}. ` +
"Then reply with the two nonce values you read (include both).",
thinking: params.thinkingLevel,
@@ -676,7 +676,7 @@ async function runGatewayModelSuite(params: GatewayModelSuiteParams) {
sessionKey,
idempotencyKey: `idem-${runIdTool}-exec-read`,
message:
"Clawdbot live tool probe (local, safe): " +
"Moltbot live tool probe (local, safe): " +
"use the tool named `exec` (or `Exec`) to run this command: " +
`mkdir -p "${tempDir}" && printf '%s' '${nonceC}' > "${toolWritePath}". ` +
`Then use the tool named \`read\` (or \`Read\`) with JSON arguments {"path":"${toolWritePath}"}. ` +
@@ -957,9 +957,9 @@ describeLive("gateway live (dev agent, profile keys)", () => {
"runs meaningful prompts across models with available keys",
async () => {
const cfg = loadConfig();
await ensureClawdbotModelsJson(cfg);
await ensureMoltbotModelsJson(cfg);
const agentDir = resolveClawdbotAgentDir();
const agentDir = resolveMoltbotAgentDir();
const authStore = ensureAuthProfileStore(agentDir, {
allowKeychainPrompt: false,
});
@@ -1061,9 +1061,9 @@ describeLive("gateway live (dev agent, profile keys)", () => {
process.env.CLAWDBOT_GATEWAY_TOKEN = token;
const cfg = loadConfig();
await ensureClawdbotModelsJson(cfg);
await ensureMoltbotModelsJson(cfg);
const agentDir = resolveClawdbotAgentDir();
const agentDir = resolveMoltbotAgentDir();
const authStorage = discoverAuthStorage(agentDir);
const modelRegistry = discoverModels(authStorage, agentDir);
const anthropic = modelRegistry.find("anthropic", "claude-opus-4-5") as Model<Api> | null;

View File

@@ -40,7 +40,7 @@ describe("gateway e2e", () => {
const { baseUrl: openaiBaseUrl, restore } = installOpenAiResponsesMock();
const tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-mock-home-"));
const tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-mock-home-"));
process.env.HOME = tempHome;
process.env.CLAWDBOT_SKIP_CHANNELS = "1";
process.env.CLAWDBOT_SKIP_GMAIL_WATCHER = "1";
@@ -61,7 +61,7 @@ describe("gateway e2e", () => {
const configDir = path.join(tempHome, ".clawdbot");
await fs.mkdir(configDir, { recursive: true });
const configPath = path.join(configDir, "clawdbot.json");
const configPath = path.join(configDir, "moltbot.json");
const cfg = {
agents: { defaults: { workspace: workspaceDir } },
@@ -172,7 +172,7 @@ describe("gateway e2e", () => {
process.env.CLAWDBOT_SKIP_BROWSER_CONTROL_SERVER = "1";
delete process.env.CLAWDBOT_GATEWAY_TOKEN;
const tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-wizard-home-"));
const tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-wizard-home-"));
process.env.HOME = tempHome;
delete process.env.CLAWDBOT_STATE_DIR;
delete process.env.CLAWDBOT_CONFIG_PATH;

View File

@@ -63,7 +63,7 @@ describe("hooks mapping", () => {
});
it("runs transform module", async () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "clawdbot-hooks-"));
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "moltbot-hooks-"));
const modPath = path.join(dir, "transform.mjs");
const placeholder = "${" + "payload.name}";
fs.writeFileSync(
@@ -99,7 +99,7 @@ describe("hooks mapping", () => {
});
it("treats null transform as a handled skip", async () => {
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "clawdbot-hooks-skip-"));
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "moltbot-hooks-skip-"));
const modPath = path.join(dir, "transform.mjs");
fs.writeFileSync(modPath, "export default () => null;");

View File

@@ -1,11 +1,7 @@
import path from "node:path";
import { pathToFileURL } from "node:url";
import {
CONFIG_PATH_CLAWDBOT,
type HookMappingConfig,
type HooksConfig,
} from "../config/config.js";
import { CONFIG_PATH, type HookMappingConfig, type HooksConfig } from "../config/config.js";
import type { HookMessageChannel } from "./hooks.js";
export type HookMappingResolved = {
@@ -125,7 +121,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);
const transformsDir = hooks?.transformsDir
? resolvePath(configDir, hooks.transformsDir)
: configDir;

View File

@@ -1,6 +1,6 @@
import type { IncomingMessage } from "node:http";
import { afterEach, beforeEach, describe, expect, test } from "vitest";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import type { ChannelPlugin } from "../channels/plugins/types.js";
import { setActivePluginRegistry } from "../plugins/runtime.js";
import { createIMessageTestPlugin, createTestRegistry } from "../test-utils/channel-plugins.js";
@@ -26,7 +26,7 @@ describe("gateway hooks helpers", () => {
token: "secret",
path: "hooks///",
},
} as ClawdbotConfig;
} as MoltbotConfig;
const resolved = resolveHooksConfig(base);
expect(resolved?.basePath).toBe("/hooks");
expect(resolved?.token).toBe("secret");
@@ -35,7 +35,7 @@ describe("gateway hooks helpers", () => {
test("resolveHooksConfig rejects root path", () => {
const cfg = {
hooks: { enabled: true, token: "x", path: "/" },
} as ClawdbotConfig;
} as MoltbotConfig;
expect(() => resolveHooksConfig(cfg)).toThrow("hooks.path may not be '/'");
});
@@ -43,7 +43,7 @@ describe("gateway hooks helpers", () => {
const req = {
headers: {
authorization: "Bearer top",
"x-clawdbot-token": "header",
"x-moltbot-token": "header",
},
} as unknown as IncomingMessage;
const url = new URL("http://localhost/hooks/wake?token=query");
@@ -52,7 +52,7 @@ describe("gateway hooks helpers", () => {
expect(result1.fromQuery).toBe(false);
const req2 = {
headers: { "x-clawdbot-token": "header" },
headers: { "x-moltbot-token": "header" },
} as unknown as IncomingMessage;
const result2 = extractHookToken(req2, url);
expect(result2.token).toBe("header");

View File

@@ -2,7 +2,7 @@ import { randomUUID } from "node:crypto";
import type { IncomingMessage } from "node:http";
import { listChannelPlugins } from "../channels/plugins/index.js";
import type { ChannelId } from "../channels/plugins/types.js";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import { normalizeMessageChannel } from "../utils/message-channel.js";
import { type HookMappingResolved, resolveHookMappings } from "./hooks-mapping.js";
@@ -16,7 +16,7 @@ export type HooksConfigResolved = {
mappings: HookMappingResolved[];
};
export function resolveHooksConfig(cfg: ClawdbotConfig): HooksConfigResolved | null {
export function resolveHooksConfig(cfg: MoltbotConfig): HooksConfigResolved | null {
if (cfg.hooks?.enabled !== true) return null;
const token = cfg.hooks?.token?.trim();
if (!token) {
@@ -54,9 +54,7 @@ export function extractHookToken(req: IncomingMessage, url: URL): HookTokenResul
if (token) return { token, fromQuery: false };
}
const headerToken =
typeof req.headers["x-clawdbot-token"] === "string"
? req.headers["x-clawdbot-token"].trim()
: "";
typeof req.headers["x-moltbot-token"] === "string" ? req.headers["x-moltbot-token"].trim() : "";
if (headerToken) return { token: headerToken, fromQuery: false };
const queryToken = url.searchParams.get("token");
if (queryToken) return { token: queryToken.trim(), fromQuery: true };

View File

@@ -19,9 +19,7 @@ export function getBearerToken(req: IncomingMessage): string | undefined {
export function resolveAgentIdFromHeader(req: IncomingMessage): string | undefined {
const raw =
getHeader(req, "x-clawdbot-agent-id")?.trim() ||
getHeader(req, "x-clawdbot-agent")?.trim() ||
"";
getHeader(req, "x-moltbot-agent-id")?.trim() || getHeader(req, "x-moltbot-agent")?.trim() || "";
if (!raw) return undefined;
return normalizeAgentId(raw);
}
@@ -31,7 +29,7 @@ export function resolveAgentIdFromModel(model: string | undefined): string | und
if (!raw) return undefined;
const m =
raw.match(/^clawdbot[:/](?<agentId>[a-z0-9][a-z0-9_-]{0,63})$/i) ??
raw.match(/^moltbot[:/](?<agentId>[a-z0-9][a-z0-9_-]{0,63})$/i) ??
raw.match(/^agent:(?<agentId>[a-z0-9][a-z0-9_-]{0,63})$/i);
const agentId = m?.groups?.agentId;
if (!agentId) return undefined;
@@ -55,7 +53,7 @@ export function resolveSessionKey(params: {
user?: string | undefined;
prefix: string;
}): string {
const explicit = getHeader(params.req, "x-clawdbot-session-key")?.trim();
const explicit = getHeader(params.req, "x-moltbot-session-key")?.trim();
if (explicit) return explicit;
const user = params.user?.trim();

View File

@@ -1,4 +1,4 @@
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import type { NodeSession } from "./node-registry.js";
const CANVAS_COMMANDS = [
@@ -75,7 +75,7 @@ function normalizePlatformId(platform?: string, deviceFamily?: string): string {
}
export function resolveNodeCommandAllowlist(
cfg: ClawdbotConfig,
cfg: MoltbotConfig,
node?: Pick<NodeSession, "platform" | "deviceFamily">,
): Set<string> {
const platformId = normalizePlatformId(node?.platform, node?.deviceFamily);

View File

@@ -67,7 +67,7 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
const server = await startServerWithDefaultConfig(port);
try {
const res = await postChatCompletions(port, {
model: "clawdbot",
model: "moltbot",
messages: [{ role: "user", content: "hi" }],
});
expect(res.status).toBe(404);
@@ -83,7 +83,7 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
});
try {
const res = await postChatCompletions(port, {
model: "clawdbot",
model: "moltbot",
messages: [{ role: "user", content: "hi" }],
});
expect(res.status).toBe(404);
@@ -124,8 +124,8 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
mockAgentOnce([{ text: "hello" }]);
const res = await postChatCompletions(
port,
{ model: "clawdbot", messages: [{ role: "user", content: "hi" }] },
{ "x-clawdbot-agent-id": "beta" },
{ model: "moltbot", messages: [{ role: "user", content: "hi" }] },
{ "x-moltbot-agent-id": "beta" },
);
expect(res.status).toBe(200);
@@ -140,7 +140,7 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
{
mockAgentOnce([{ text: "hello" }]);
const res = await postChatCompletions(port, {
model: "clawdbot:beta",
model: "moltbot:beta",
messages: [{ role: "user", content: "hi" }],
});
expect(res.status).toBe(200);
@@ -158,10 +158,10 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
const res = await postChatCompletions(
port,
{
model: "clawdbot:beta",
model: "moltbot:beta",
messages: [{ role: "user", content: "hi" }],
},
{ "x-clawdbot-agent-id": "alpha" },
{ "x-moltbot-agent-id": "alpha" },
);
expect(res.status).toBe(200);
@@ -177,10 +177,10 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
mockAgentOnce([{ text: "hello" }]);
const res = await postChatCompletions(
port,
{ model: "clawdbot", messages: [{ role: "user", content: "hi" }] },
{ model: "moltbot", messages: [{ role: "user", content: "hi" }] },
{
"x-clawdbot-agent-id": "beta",
"x-clawdbot-session-key": "agent:beta:openai:custom",
"x-moltbot-agent-id": "beta",
"x-moltbot-session-key": "agent:beta:openai:custom",
},
);
expect(res.status).toBe(200);
@@ -196,7 +196,7 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
mockAgentOnce([{ text: "hello" }]);
const res = await postChatCompletions(port, {
user: "alice",
model: "clawdbot",
model: "moltbot",
messages: [{ role: "user", content: "hi" }],
});
expect(res.status).toBe(200);
@@ -211,7 +211,7 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
{
mockAgentOnce([{ text: "hello" }]);
const res = await postChatCompletions(port, {
model: "clawdbot",
model: "moltbot",
messages: [
{
role: "user",
@@ -232,7 +232,7 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
{
mockAgentOnce([{ text: "I am Claude" }]);
const res = await postChatCompletions(port, {
model: "clawdbot",
model: "moltbot",
messages: [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "Hello, who are you?" },
@@ -255,7 +255,7 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
{
mockAgentOnce([{ text: "hello" }]);
const res = await postChatCompletions(port, {
model: "clawdbot",
model: "moltbot",
messages: [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "Hello" },
@@ -274,7 +274,7 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
{
mockAgentOnce([{ text: "hello" }]);
const res = await postChatCompletions(port, {
model: "clawdbot",
model: "moltbot",
messages: [
{ role: "developer", content: "You are a helpful assistant." },
{ role: "user", content: "Hello" },
@@ -292,7 +292,7 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
{
mockAgentOnce([{ text: "ok" }]);
const res = await postChatCompletions(port, {
model: "clawdbot",
model: "moltbot",
messages: [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "What's the weather?" },
@@ -316,7 +316,7 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
mockAgentOnce([{ text: "hello" }]);
const res = await postChatCompletions(port, {
stream: false,
model: "clawdbot",
model: "moltbot",
messages: [{ role: "user", content: "hi" }],
});
expect(res.status).toBe(200);
@@ -331,7 +331,7 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
{
const res = await postChatCompletions(port, {
model: "clawdbot",
model: "moltbot",
messages: [{ role: "system", content: "yo" }],
});
expect(res.status).toBe(400);
@@ -359,7 +359,7 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
const res = await postChatCompletions(port, {
stream: true,
model: "clawdbot",
model: "moltbot",
messages: [{ role: "user", content: "hi" }],
});
expect(res.status).toBe(200);
@@ -392,7 +392,7 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
const repeatedRes = await postChatCompletions(port, {
stream: true,
model: "clawdbot",
model: "moltbot",
messages: [{ role: "user", content: "hi" }],
});
expect(repeatedRes.status).toBe(200);
@@ -417,7 +417,7 @@ describe("OpenAI-compatible HTTP API (e2e)", () => {
const fallbackRes = await postChatCompletions(port, {
stream: true,
model: "clawdbot",
model: "moltbot",
messages: [{ role: "user", content: "hi" }],
});
expect(fallbackRes.status).toBe(200);

View File

@@ -181,7 +181,7 @@ export async function handleOpenAiHttpRequest(
const payload = coerceRequest(body);
const stream = Boolean(payload.stream);
const model = typeof payload.model === "string" ? payload.model : "clawdbot";
const model = typeof payload.model === "string" ? payload.model : "moltbot";
const user = typeof payload.user === "string" ? payload.user : undefined;
const agentId = resolveAgentIdForRequest({ req, model });
@@ -223,7 +223,7 @@ export async function handleOpenAiHttpRequest(
.map((p) => (typeof p.text === "string" ? p.text : ""))
.filter(Boolean)
.join("\n\n")
: "No response from Clawdbot.";
: "No response from Moltbot.";
sendJson(res, 200, {
id: runId,
@@ -344,7 +344,7 @@ export async function handleOpenAiHttpRequest(
.map((p) => (typeof p.text === "string" ? p.text : ""))
.filter(Boolean)
.join("\n\n")
: "No response from Clawdbot.";
: "No response from Moltbot.";
sawAssistantDelta = true;
writeSse(res, {

View File

@@ -87,7 +87,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
const _server = await startServerWithDefaultConfig(port);
try {
const res = await postResponses(port, {
model: "clawdbot",
model: "moltbot",
input: "hi",
});
expect(res.status).toBe(404);
@@ -102,7 +102,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
});
try {
const res = await postResponses(disabledPort, {
model: "clawdbot",
model: "moltbot",
input: "hi",
});
expect(res.status).toBe(404);
@@ -130,7 +130,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
const resMissingAuth = await fetch(`http://127.0.0.1:${port}/v1/responses`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ model: "clawdbot", input: "hi" }),
body: JSON.stringify({ model: "moltbot", input: "hi" }),
});
expect(resMissingAuth.status).toBe(401);
await ensureResponseConsumed(resMissingAuth);
@@ -146,8 +146,8 @@ describe("OpenResponses HTTP API (e2e)", () => {
mockAgentOnce([{ text: "hello" }]);
const resHeader = await postResponses(
port,
{ model: "clawdbot", input: "hi" },
{ "x-clawdbot-agent-id": "beta" },
{ model: "moltbot", input: "hi" },
{ "x-moltbot-agent-id": "beta" },
);
expect(resHeader.status).toBe(200);
const [optsHeader] = agentCommand.mock.calls[0] ?? [];
@@ -157,7 +157,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
await ensureResponseConsumed(resHeader);
mockAgentOnce([{ text: "hello" }]);
const resModel = await postResponses(port, { model: "clawdbot:beta", input: "hi" });
const resModel = await postResponses(port, { model: "moltbot:beta", input: "hi" });
expect(resModel.status).toBe(200);
const [optsModel] = agentCommand.mock.calls[0] ?? [];
expect((optsModel as { sessionKey?: string } | undefined)?.sessionKey ?? "").toMatch(
@@ -168,7 +168,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
mockAgentOnce([{ text: "hello" }]);
const resUser = await postResponses(port, {
user: "alice",
model: "clawdbot",
model: "moltbot",
input: "hi",
});
expect(resUser.status).toBe(200);
@@ -180,7 +180,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
mockAgentOnce([{ text: "hello" }]);
const resString = await postResponses(port, {
model: "clawdbot",
model: "moltbot",
input: "hello world",
});
expect(resString.status).toBe(200);
@@ -190,7 +190,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
mockAgentOnce([{ text: "hello" }]);
const resArray = await postResponses(port, {
model: "clawdbot",
model: "moltbot",
input: [{ type: "message", role: "user", content: "hello there" }],
});
expect(resArray.status).toBe(200);
@@ -200,7 +200,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
mockAgentOnce([{ text: "hello" }]);
const resSystemDeveloper = await postResponses(port, {
model: "clawdbot",
model: "moltbot",
input: [
{ type: "message", role: "system", content: "You are a helpful assistant." },
{ type: "message", role: "developer", content: "Be concise." },
@@ -218,7 +218,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
mockAgentOnce([{ text: "hello" }]);
const resInstructions = await postResponses(port, {
model: "clawdbot",
model: "moltbot",
input: "hi",
instructions: "Always respond in French.",
});
@@ -231,7 +231,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
mockAgentOnce([{ text: "I am Claude" }]);
const resHistory = await postResponses(port, {
model: "clawdbot",
model: "moltbot",
input: [
{ type: "message", role: "system", content: "You are a helpful assistant." },
{ type: "message", role: "user", content: "Hello, who are you?" },
@@ -251,7 +251,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
mockAgentOnce([{ text: "ok" }]);
const resFunctionOutput = await postResponses(port, {
model: "clawdbot",
model: "moltbot",
input: [
{ type: "message", role: "user", content: "What's the weather?" },
{ type: "function_call_output", call_id: "call_1", output: "Sunny, 70F." },
@@ -266,7 +266,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
mockAgentOnce([{ text: "ok" }]);
const resInputFile = await postResponses(port, {
model: "clawdbot",
model: "moltbot",
input: [
{
type: "message",
@@ -297,7 +297,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
mockAgentOnce([{ text: "ok" }]);
const resToolNone = await postResponses(port, {
model: "clawdbot",
model: "moltbot",
input: "hi",
tools: [
{
@@ -316,7 +316,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
mockAgentOnce([{ text: "ok" }]);
const resToolChoice = await postResponses(port, {
model: "clawdbot",
model: "moltbot",
input: "hi",
tools: [
{
@@ -340,7 +340,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
await ensureResponseConsumed(resToolChoice);
const resUnknownTool = await postResponses(port, {
model: "clawdbot",
model: "moltbot",
input: "hi",
tools: [
{
@@ -355,7 +355,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
mockAgentOnce([{ text: "ok" }]);
const resMaxTokens = await postResponses(port, {
model: "clawdbot",
model: "moltbot",
input: "hi",
max_output_tokens: 123,
});
@@ -374,7 +374,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
});
const resUsage = await postResponses(port, {
stream: false,
model: "clawdbot",
model: "moltbot",
input: "hi",
});
expect(resUsage.status).toBe(200);
@@ -385,7 +385,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
mockAgentOnce([{ text: "hello" }]);
const resShape = await postResponses(port, {
stream: false,
model: "clawdbot",
model: "moltbot",
input: "hi",
});
expect(resShape.status).toBe(200);
@@ -407,7 +407,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
await ensureResponseConsumed(resShape);
const resNoUser = await postResponses(port, {
model: "clawdbot",
model: "moltbot",
input: [{ type: "message", role: "system", content: "yo" }],
});
expect(resNoUser.status).toBe(400);
@@ -434,7 +434,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
const resDelta = await postResponses(port, {
stream: true,
model: "clawdbot",
model: "moltbot",
input: "hi",
});
expect(resDelta.status).toBe(200);
@@ -470,7 +470,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
const resFallback = await postResponses(port, {
stream: true,
model: "clawdbot",
model: "moltbot",
input: "hi",
});
expect(resFallback.status).toBe(200);
@@ -485,7 +485,7 @@ describe("OpenResponses HTTP API (e2e)", () => {
const resTypeMatch = await postResponses(port, {
stream: true,
model: "clawdbot",
model: "moltbot",
input: "hi",
});
expect(resTypeMatch.status).toBe(200);

View File

@@ -1,7 +1,7 @@
/**
* OpenResponses HTTP Handler
*
* Implements the OpenResponses `/v1/responses` endpoint for Clawdbot Gateway.
* Implements the OpenResponses `/v1/responses` endpoint for Moltbot Gateway.
*
* @see https://www.open-responses.com/
*/
@@ -552,7 +552,7 @@ export async function handleOpenResponsesHttpRequest(
.map((p) => (typeof p.text === "string" ? p.text : ""))
.filter(Boolean)
.join("\n\n")
: "No response from Clawdbot.";
: "No response from Moltbot.";
const response = createResponseResource({
id: responseId,
@@ -706,7 +706,7 @@ export async function handleOpenResponsesHttpRequest(
if (evt.stream === "lifecycle") {
const phase = evt.data?.phase;
if (phase === "end" || phase === "error") {
const finalText = accumulatedText || "No response from Clawdbot.";
const finalText = accumulatedText || "No response from Moltbot.";
const finalStatus = phase === "error" ? "failed" : "completed";
requestFinalize(finalStatus, finalText);
}
@@ -831,7 +831,7 @@ export async function handleOpenResponsesHttpRequest(
.map((p) => (typeof p.text === "string" ? p.text : ""))
.filter(Boolean)
.join("\n\n")
: "No response from Clawdbot.";
: "No response from Moltbot.";
accumulatedText = content;
sawAssistantDelta = true;

View File

@@ -1,16 +1,16 @@
export const GATEWAY_CLIENT_IDS = {
WEBCHAT_UI: "webchat-ui",
CONTROL_UI: "clawdbot-control-ui",
CONTROL_UI: "moltbot-control-ui",
WEBCHAT: "webchat",
CLI: "cli",
GATEWAY_CLIENT: "gateway-client",
MACOS_APP: "clawdbot-macos",
IOS_APP: "clawdbot-ios",
ANDROID_APP: "clawdbot-android",
MACOS_APP: "moltbot-macos",
IOS_APP: "moltbot-ios",
ANDROID_APP: "moltbot-android",
NODE_HOST: "node-host",
TEST: "test",
FINGERPRINT: "fingerprint",
PROBE: "clawdbot-probe",
PROBE: "moltbot-probe",
} as const;
export type GatewayClientId = (typeof GATEWAY_CLIENT_IDS)[keyof typeof GATEWAY_CLIENT_IDS];

View File

@@ -1,7 +1,7 @@
import { resolveChannelDefaultAccountId } from "../channels/plugins/helpers.js";
import { type ChannelId, getChannelPlugin, listChannelPlugins } from "../channels/plugins/index.js";
import type { ChannelAccountSnapshot } from "../channels/plugins/types.js";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import { formatErrorMessage } from "../infra/errors.js";
import { resetDirectoryCache } from "../infra/outbound/target-resolver.js";
import type { createSubsystemLogger } from "../logging/subsystem.js";
@@ -45,7 +45,7 @@ function cloneDefaultRuntime(channelId: ChannelId, accountId: string): ChannelAc
}
type ChannelManagerOptions = {
loadConfig: () => ClawdbotConfig;
loadConfig: () => MoltbotConfig;
channelLogs: Record<ChannelId, SubsystemLogger>;
channelRuntimeEnvs: Record<ChannelId, RuntimeEnv>;
};

View File

@@ -13,9 +13,9 @@ export type ResolveBonjourCliPathOptions = {
export function formatBonjourInstanceName(displayName: string) {
const trimmed = displayName.trim();
if (!trimmed) return "Clawdbot";
if (/clawdbot/i.test(trimmed)) return trimmed;
return `${trimmed} (Clawdbot)`;
if (!trimmed) return "Moltbot";
if (/moltbot/i.test(trimmed)) return trimmed;
return `${trimmed} (Moltbot)`;
}
export function resolveBonjourCliPath(opts: ResolveBonjourCliPathOptions = {}): string | undefined {
@@ -34,7 +34,7 @@ export function resolveBonjourCliPath(opts: ResolveBonjourCliPathOptions = {}):
const execPath = opts.execPath ?? process.execPath;
const execDir = path.dirname(execPath);
const siblingCli = path.join(execDir, "clawdbot");
const siblingCli = path.join(execDir, "moltbot");
if (isFile(siblingCli)) return siblingCli;
const argv = opts.argv ?? process.argv;
@@ -46,7 +46,7 @@ export function resolveBonjourCliPath(opts: ResolveBonjourCliPathOptions = {}):
const cwd = opts.cwd ?? process.cwd();
const distCli = path.join(cwd, "dist", "index.js");
if (isFile(distCli)) return distCli;
const binCli = path.join(cwd, "bin", "clawdbot.js");
const binCli = path.join(cwd, "bin", "moltbot.js");
if (isFile(binCli)) return binCli;
return undefined;

View File

@@ -87,7 +87,7 @@ export function createHooksRequestHandler(
logHooks.warn(
"Hook token provided via query parameter is deprecated for security reasons. " +
"Tokens in URLs appear in logs, browser history, and referrer headers. " +
"Use Authorization: Bearer <token> or X-Clawdbot-Token header instead.",
"Use Authorization: Bearer <token> or X-Moltbot-Token header instead.",
);
}

View File

@@ -8,7 +8,7 @@ import {
import { buildChannelUiCatalog } from "../../channels/plugins/catalog.js";
import { buildChannelAccountSnapshot } from "../../channels/plugins/status.js";
import type { ChannelAccountSnapshot, ChannelPlugin } from "../../channels/plugins/types.js";
import type { ClawdbotConfig } from "../../config/config.js";
import type { MoltbotConfig } from "../../config/config.js";
import { loadConfig, readConfigFileSnapshot } from "../../config/config.js";
import { getChannelActivity } from "../../infra/channel-activity.js";
import { DEFAULT_ACCOUNT_ID } from "../../routing/session-key.js";
@@ -33,7 +33,7 @@ type ChannelLogoutPayload = {
export async function logoutChannelAccount(params: {
channelId: ChannelId;
accountId?: string | null;
cfg: ClawdbotConfig;
cfg: MoltbotConfig;
context: GatewayRequestContext;
plugin: ChannelPlugin;
}): Promise<ChannelLogoutPayload> {

View File

@@ -1,6 +1,6 @@
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../agents/agent-scope.js";
import {
CONFIG_PATH_CLAWDBOT,
CONFIG_PATH,
loadConfig,
parseConfigJson5,
readConfigFileSnapshot,
@@ -18,7 +18,7 @@ import {
writeRestartSentinel,
} from "../../infra/restart-sentinel.js";
import { listChannelPlugins } from "../../channels/plugins/index.js";
import { loadClawdbotPlugins } from "../../plugins/loader.js";
import { loadMoltbotPlugins } from "../../plugins/loader.js";
import {
ErrorCodes,
errorShape,
@@ -112,7 +112,7 @@ export const configHandlers: GatewayRequestHandlers = {
}
const cfg = loadConfig();
const workspaceDir = resolveAgentWorkspaceDir(cfg, resolveDefaultAgentId(cfg));
const pluginRegistry = loadClawdbotPlugins({
const pluginRegistry = loadMoltbotPlugins({
config: cfg,
workspaceDir,
logger: {
@@ -186,7 +186,7 @@ export const configHandlers: GatewayRequestHandlers = {
true,
{
ok: true,
path: CONFIG_PATH_CLAWDBOT,
path: CONFIG_PATH,
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,
},
};
let sentinelPath: string | null = null;
@@ -301,7 +301,7 @@ export const configHandlers: GatewayRequestHandlers = {
true,
{
ok: true,
path: CONFIG_PATH_CLAWDBOT,
path: CONFIG_PATH,
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,
},
};
let sentinelPath: string | null = null;
@@ -398,7 +398,7 @@ export const configHandlers: GatewayRequestHandlers = {
true,
{
ok: true,
path: CONFIG_PATH_CLAWDBOT,
path: CONFIG_PATH,
config: validated.config,
restart,
sentinel: {

View File

@@ -16,16 +16,16 @@ describe("logs.tail", () => {
});
it("falls back to latest rolling log file when today is missing", async () => {
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-logs-"));
const older = path.join(tempDir, "clawdbot-2026-01-20.log");
const newer = path.join(tempDir, "clawdbot-2026-01-21.log");
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-logs-"));
const older = path.join(tempDir, "moltbot-2026-01-20.log");
const newer = path.join(tempDir, "moltbot-2026-01-21.log");
await fs.writeFile(older, '{"msg":"old"}\n');
await fs.writeFile(newer, '{"msg":"new"}\n');
await fs.utimes(older, new Date(0), new Date(0));
await fs.utimes(newer, new Date(), new Date());
setLoggerOverride({ file: path.join(tempDir, "clawdbot-2026-01-22.log") });
setLoggerOverride({ file: path.join(tempDir, "moltbot-2026-01-22.log") });
const respond = vi.fn();
await logsHandlers["logs.tail"]({

View File

@@ -13,7 +13,7 @@ const DEFAULT_LIMIT = 500;
const DEFAULT_MAX_BYTES = 250_000;
const MAX_LIMIT = 5000;
const MAX_BYTES = 1_000_000;
const ROLLING_LOG_RE = /^clawdbot-\d{4}-\d{2}-\d{2}\.log$/;
const ROLLING_LOG_RE = /^moltbot-\d{4}-\d{2}-\d{2}\.log$/;
function clamp(value: number, min: number, max: number) {
return Math.max(min, Math.min(max, value));

View File

@@ -2,7 +2,7 @@ import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../agents/ag
import { installSkill } from "../../agents/skills-install.js";
import { buildWorkspaceSkillStatus } from "../../agents/skills-status.js";
import { loadWorkspaceSkillEntries, type SkillEntry } from "../../agents/skills.js";
import type { ClawdbotConfig } from "../../config/config.js";
import type { MoltbotConfig } from "../../config/config.js";
import { loadConfig, writeConfigFile } from "../../config/config.js";
import { getRemoteSkillEligibility } from "../../infra/skills-remote.js";
import {
@@ -16,7 +16,7 @@ import {
} from "../protocol/index.js";
import type { GatewayRequestHandlers } from "./types.js";
function listWorkspaceDirs(cfg: ClawdbotConfig): string[] {
function listWorkspaceDirs(cfg: MoltbotConfig): string[] {
const dirs = new Set<string>();
const list = cfg.agents?.list;
if (Array.isArray(list)) {
@@ -33,9 +33,9 @@ function listWorkspaceDirs(cfg: ClawdbotConfig): string[] {
function collectSkillBins(entries: SkillEntry[]): string[] {
const bins = new Set<string>();
for (const entry of entries) {
const required = entry.clawdbot?.requires?.bins ?? [];
const anyBins = entry.clawdbot?.requires?.anyBins ?? [];
const install = entry.clawdbot?.install ?? [];
const required = entry.metadata?.requires?.bins ?? [];
const anyBins = entry.metadata?.requires?.anyBins ?? [];
const install = entry.metadata?.install ?? [];
for (const bin of required) {
const trimmed = bin.trim();
if (trimmed) bins.add(trimmed);
@@ -172,7 +172,7 @@ export const skillsHandlers: GatewayRequestHandlers = {
}
entries[p.skillKey] = current;
skills.entries = entries;
const nextConfig: ClawdbotConfig = {
const nextConfig: MoltbotConfig = {
...cfg,
skills,
};

View File

@@ -1,4 +1,4 @@
import { resolveClawdbotPackageRoot } from "../../infra/clawdbot-root.js";
import { resolveMoltbotPackageRoot } from "../../infra/moltbot-root.js";
import { scheduleGatewaySigusr1Restart } from "../../infra/restart.js";
import {
formatDoctorNonInteractiveHint,
@@ -49,7 +49,7 @@ export const updateHandlers: GatewayRequestHandlers = {
let result: Awaited<ReturnType<typeof runGatewayUpdate>>;
try {
const root =
(await resolveClawdbotPackageRoot({
(await resolveMoltbotPackageRoot({
moduleUrl: import.meta.url,
argv1: process.argv[1],
cwd: process.cwd(),

View File

@@ -3,10 +3,10 @@ import type { PluginRegistry } from "../plugins/registry.js";
import type { PluginDiagnostic } from "../plugins/types.js";
import { loadGatewayPlugins } from "./server-plugins.js";
const loadClawdbotPlugins = vi.hoisted(() => vi.fn());
const loadMoltbotPlugins = vi.hoisted(() => vi.fn());
vi.mock("../plugins/loader.js", () => ({
loadClawdbotPlugins,
loadMoltbotPlugins,
}));
const createRegistry = (diagnostics: PluginDiagnostic[]): PluginRegistry => ({
@@ -34,7 +34,7 @@ describe("loadGatewayPlugins", () => {
message: "failed to load plugin: boom",
},
];
loadClawdbotPlugins.mockReturnValue(createRegistry(diagnostics));
loadMoltbotPlugins.mockReturnValue(createRegistry(diagnostics));
const log = {
info: vi.fn(),

View File

@@ -1,5 +1,5 @@
import type { loadConfig } from "../config/config.js";
import { loadClawdbotPlugins } from "../plugins/loader.js";
import { loadMoltbotPlugins } from "../plugins/loader.js";
import type { GatewayRequestHandler } from "./server-methods/types.js";
export function loadGatewayPlugins(params: {
@@ -14,7 +14,7 @@ export function loadGatewayPlugins(params: {
coreGatewayHandlers: Record<string, GatewayRequestHandler>;
baseMethods: string[];
}) {
const pluginRegistry = loadClawdbotPlugins({
const pluginRegistry = loadMoltbotPlugins({
config: params.cfg,
workspaceDir: params.workspaceDir,
logger: {

View File

@@ -22,7 +22,7 @@ import type { PluginRegistry } from "../plugins/registry.js";
import type { GatewayTlsRuntime } from "./server/tls.js";
export async function createGatewayRuntimeState(params: {
cfg: import("../config/config.js").ClawdbotConfig;
cfg: import("../config/config.js").MoltbotConfig;
bindHost: string;
port: number;
controlUiEnabled: boolean;

View File

@@ -15,7 +15,7 @@ import {
triggerInternalHook,
} from "../hooks/internal-hooks.js";
import { loadInternalHooks } from "../hooks/loader.js";
import type { loadClawdbotPlugins } from "../plugins/loader.js";
import type { loadMoltbotPlugins } from "../plugins/loader.js";
import { type PluginServicesHandle, startPluginServices } from "../plugins/services.js";
import { startBrowserControlServerIfEnabled } from "./server-browser.js";
import {
@@ -25,7 +25,7 @@ import {
export async function startGatewaySidecars(params: {
cfg: ReturnType<typeof loadConfig>;
pluginRegistry: ReturnType<typeof loadClawdbotPlugins>;
pluginRegistry: ReturnType<typeof loadMoltbotPlugins>;
defaultWorkspaceDir: string;
deps: CliDeps;
startChannels: () => Promise<void>;

View File

@@ -167,7 +167,7 @@ describe("gateway server agent", () => {
test("agent marks implicit delivery when lastTo is stale", async () => {
setRegistry(defaultRegistry);
testState.allowFrom = ["+436769770569"];
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {
@@ -199,7 +199,7 @@ describe("gateway server agent", () => {
test("agent forwards sessionKey to agentCommand", async () => {
setRegistry(defaultRegistry);
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {
@@ -227,7 +227,7 @@ describe("gateway server agent", () => {
test("agent derives sessionKey from agentId", async () => {
setRegistry(defaultRegistry);
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
testState.agentsConfig = { list: [{ id: "ops" }] };
await writeSessionStore({
@@ -285,7 +285,7 @@ describe("gateway server agent", () => {
test("agent forwards accountId to agentCommand", async () => {
setRegistry(defaultRegistry);
testState.allowFrom = ["+1555"];
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {
@@ -320,7 +320,7 @@ describe("gateway server agent", () => {
test("agent avoids lastAccountId when explicit to is provided", async () => {
setRegistry(defaultRegistry);
testState.allowFrom = ["+1555"];
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {
@@ -353,7 +353,7 @@ describe("gateway server agent", () => {
test("agent keeps explicit accountId when explicit to is provided", async () => {
setRegistry(defaultRegistry);
testState.allowFrom = ["+1555"];
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {
@@ -387,7 +387,7 @@ describe("gateway server agent", () => {
test("agent falls back to lastAccountId for implicit delivery", async () => {
setRegistry(defaultRegistry);
testState.allowFrom = ["+1555"];
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {
@@ -418,7 +418,7 @@ describe("gateway server agent", () => {
test("agent forwards image attachments as images[]", async () => {
setRegistry(defaultRegistry);
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {
@@ -459,7 +459,7 @@ describe("gateway server agent", () => {
test("agent falls back to whatsapp when delivery requested and no last channel exists", async () => {
setRegistry(defaultRegistry);
testState.allowFrom = ["+1555"];
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {
@@ -488,7 +488,7 @@ describe("gateway server agent", () => {
test("agent routes main last-channel whatsapp", async () => {
setRegistry(defaultRegistry);
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {
@@ -521,7 +521,7 @@ describe("gateway server agent", () => {
test("agent routes main last-channel telegram", async () => {
setRegistry(defaultRegistry);
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {
@@ -553,7 +553,7 @@ describe("gateway server agent", () => {
test("agent routes main last-channel discord", async () => {
setRegistry(defaultRegistry);
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {
@@ -585,7 +585,7 @@ describe("gateway server agent", () => {
test("agent routes main last-channel slack", async () => {
setRegistry(defaultRegistry);
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {
@@ -617,7 +617,7 @@ describe("gateway server agent", () => {
test("agent routes main last-channel signal", async () => {
setRegistry(defaultRegistry);
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {

View File

@@ -137,7 +137,7 @@ describe("gateway server agent", () => {
]);
registryState.registry = registry;
setActivePluginRegistry(registry);
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {
@@ -177,7 +177,7 @@ describe("gateway server agent", () => {
]);
registryState.registry = registry;
setActivePluginRegistry(registry);
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {
@@ -231,7 +231,7 @@ describe("gateway server agent", () => {
test("agent ignores webchat last-channel for routing", async () => {
testState.allowFrom = ["+1555"];
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {
@@ -262,7 +262,7 @@ describe("gateway server agent", () => {
});
test("agent uses webchat for internal runs when last provider is webchat", async () => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {
@@ -395,7 +395,7 @@ describe("gateway server agent", () => {
});
test("agent events stream to webchat clients when run context is registered", async () => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {

View File

@@ -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, STATE_DIR } = 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);
expect(payload?.snapshot?.stateDir).toBe(STATE_DIR);
ws.close();
});
@@ -461,7 +461,7 @@ describe("gateway server auth/connect", () => {
const { GATEWAY_CLIENT_MODES, GATEWAY_CLIENT_NAMES } =
await import("../utils/message-channel.js");
const { server, ws, port, prevToken } = await startServerWithClient("secret");
const identityDir = await mkdtemp(join(tmpdir(), "clawdbot-device-scope-"));
const identityDir = await mkdtemp(join(tmpdir(), "moltbot-device-scope-"));
const identity = loadOrCreateDeviceIdentity(join(identityDir, "device.json"));
const client = {
id: GATEWAY_CLIENT_NAMES.TEST,

View File

@@ -56,7 +56,7 @@ describe("gateway server chat", () => {
const historyMaxBytes = 192 * 1024;
__setMaxChatHistoryMessagesBytesForTest(historyMaxBytes);
await connectOk(ws);
const sessionDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const sessionDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
tempDirs.push(sessionDir);
testState.sessionStorePath = path.join(sessionDir, "sessions.json");
const writeStore = async (

View File

@@ -100,7 +100,7 @@ describe("gateway server chat", () => {
const sessionCall = spy.mock.calls.at(-1)?.[0] as { SessionKey?: string } | undefined;
expect(sessionCall?.SessionKey).toBe("agent:main:subagent:abc");
const sendPolicyDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const sendPolicyDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
tempDirs.push(sendPolicyDir);
testState.sessionStorePath = path.join(sendPolicyDir, "sessions.json");
testState.sessionConfig = {
@@ -139,7 +139,7 @@ describe("gateway server chat", () => {
testState.sessionStorePath = undefined;
testState.sessionConfig = undefined;
const agentBlockedDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const agentBlockedDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
tempDirs.push(agentBlockedDir);
testState.sessionStorePath = path.join(agentBlockedDir, "sessions.json");
testState.sessionConfig = {
@@ -241,7 +241,7 @@ describe("gateway server chat", () => {
| undefined;
expect(imgOnlyOpts?.images).toEqual([{ type: "image", data: pngB64, mimeType: "image/png" }]);
const historyDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const historyDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
tempDirs.push(historyDir);
testState.sessionStorePath = path.join(historyDir, "sessions.json");
await writeSessionStore({
@@ -293,7 +293,7 @@ describe("gateway server chat", () => {
});
test("routes chat.send slash commands without agent runs", async () => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
try {
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
@@ -332,7 +332,7 @@ describe("gateway server chat", () => {
});
test("agent events include sessionKey and agent.wait covers lifecycle flows", async () => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-"));
testState.sessionStorePath = path.join(dir, "sessions.json");
await writeSessionStore({
entries: {

View File

@@ -288,7 +288,7 @@ describe("gateway config.patch", () => {
describe("gateway server sessions", () => {
it("filters sessions by agentId", async () => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-sessions-agents-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-sessions-agents-"));
testState.sessionConfig = {
store: path.join(dir, "{agentId}", "sessions.json"),
};
@@ -349,7 +349,7 @@ describe("gateway server sessions", () => {
});
it("resolves and patches main alias to default agent main key", async () => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-sessions-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-sessions-"));
const storePath = path.join(dir, "sessions.json");
testState.sessionStorePath = storePath;
testState.agentsConfig = { list: [{ id: "ops", default: true }] };

View File

@@ -52,7 +52,7 @@ describe("gateway server cron", () => {
test("handles cron CRUD, normalization, and patch semantics", { timeout: 120_000 }, async () => {
const prevSkipCron = process.env.CLAWDBOT_SKIP_CRON;
process.env.CLAWDBOT_SKIP_CRON = "0";
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-cron-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-cron-"));
testState.cronStorePath = path.join(dir, "cron", "jobs.json");
testState.sessionConfig = { mainKey: "primary" };
testState.cronEnabled = false;
@@ -266,7 +266,7 @@ describe("gateway server cron", () => {
test("writes cron run history and auto-runs due jobs", async () => {
const prevSkipCron = process.env.CLAWDBOT_SKIP_CRON;
process.env.CLAWDBOT_SKIP_CRON = "0";
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gw-cron-log-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gw-cron-log-"));
testState.cronStorePath = path.join(dir, "cron", "jobs.json");
testState.cronEnabled = undefined;
await fs.mkdir(path.dirname(testState.cronStorePath), { recursive: true });

View File

@@ -214,7 +214,7 @@ describe("gateway server health/presence", () => {
});
test("presence includes client fingerprint", async () => {
const identityPath = path.join(os.tmpdir(), `clawdbot-device-${randomUUID()}.json`);
const identityPath = path.join(os.tmpdir(), `moltbot-device-${randomUUID()}.json`);
const identity = loadOrCreateDeviceIdentity(identityPath);
const role = "operator";
const scopes: string[] = [];

View File

@@ -108,7 +108,7 @@ describe("gateway server hooks", () => {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-clawdbot-token": "hook-secret",
"x-moltbot-token": "hook-secret",
},
body: JSON.stringify({ text: "Header auth" }),
});

View File

@@ -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,
isNixMode,
loadConfig,
migrateLegacyConfig,
@@ -20,7 +20,7 @@ import { clearAgentRunContext, onAgentEvent } from "../infra/agent-events.js";
import { onHeartbeatEvent } from "../infra/heartbeat-events.js";
import { startHeartbeatRunner } from "../infra/heartbeat-runner.js";
import { getMachineDisplayName } from "../infra/machine-name.js";
import { ensureClawdbotCliOnPath } from "../infra/path-env.js";
import { ensureMoltbotCliOnPath } from "../infra/path-env.js";
import {
primeRemoteSkillsCache,
refreshRemoteBinsForConnectedNodes,
@@ -73,7 +73,7 @@ import { attachGatewayWsHandlers } from "./server-ws-runtime.js";
export { __resetModelCatalogCacheForTest } from "./server-model-catalog.js";
ensureClawdbotCliOnPath();
ensureMoltbotCliOnPath();
const log = createSubsystemLogger("gateway");
const logCanvas = log.child("canvas");
@@ -169,7 +169,7 @@ export async function startGatewayServer(
const { config: migrated, changes } = migrateLegacyConfig(configSnapshot.parsed);
if (!migrated) {
throw new Error(
`Legacy config entries detected but auto-migration failed. Run "${formatCliCommand("clawdbot doctor")}" to migrate.`,
`Legacy config entries detected but auto-migration failed. Run "${formatCliCommand("moltbot doctor")}" to migrate.`,
);
}
await writeConfigFile(migrated);
@@ -191,7 +191,7 @@ export async function startGatewayServer(
.join("\n")
: "Unknown validation issue.";
throw new Error(
`Invalid config at ${configSnapshot.path}.\n${issues}\nRun "${formatCliCommand("clawdbot doctor")}" to repair, then retry.`,
`Invalid config at ${configSnapshot.path}.\n${issues}\nRun "${formatCliCommand("moltbot doctor")}" to repair, then retry.`,
);
}
@@ -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,
});
const close = createGatewayCloseHandler({

View File

@@ -54,11 +54,11 @@ function connectReq(
);
}
test("accepts clawdbot-ios as a valid gateway client id", async () => {
test("accepts moltbot-ios as a valid gateway client id", async () => {
const ws = new WebSocket(`ws://127.0.0.1:${port}`);
await new Promise<void>((resolve) => ws.once("open", resolve));
const res = await connectReq(ws, { clientId: "clawdbot-ios", platform: "ios" });
const res = await connectReq(ws, { clientId: "moltbot-ios", platform: "ios" });
// We don't care if auth fails here; we only care that schema validation accepts the client id.
// A schema rejection would close the socket before sending a response.
if (!res.ok) {
@@ -73,11 +73,11 @@ test("accepts clawdbot-ios as a valid gateway client id", async () => {
ws.close();
});
test("accepts clawdbot-android as a valid gateway client id", async () => {
test("accepts moltbot-android as a valid gateway client id", async () => {
const ws = new WebSocket(`ws://127.0.0.1:${port}`);
await new Promise<void>((resolve) => ws.once("open", resolve));
const res = await connectReq(ws, { clientId: "clawdbot-android", platform: "android" });
const res = await connectReq(ws, { clientId: "moltbot-android", platform: "android" });
// We don't care if auth fails here; we only care that schema validation accepts the client id.
// A schema rejection would close the socket before sending a response.
if (!res.ok) {

View File

@@ -140,7 +140,7 @@ describe("gateway server models + voicewake", () => {
"voicewake.get returns defaults and voicewake.set broadcasts",
{ timeout: 60_000 },
async () => {
const homeDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-home-"));
const homeDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-home-"));
const restoreHome = setTempHome(homeDir);
const initial = await rpcReq<{ triggers: string[] }>(ws, "voicewake.get");
@@ -181,7 +181,7 @@ describe("gateway server models + voicewake", () => {
);
test("pushes voicewake.changed to nodes on connect and on updates", async () => {
const homeDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-home-"));
const homeDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-home-"));
const restoreHome = setTempHome(homeDir);
const nodeWs = new WebSocket(`ws://127.0.0.1:${port}`);

View File

@@ -1,7 +1,7 @@
import fs from "node:fs/promises";
import path from "node:path";
import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
import { createClawdbotTools } from "../agents/clawdbot-tools.js";
import { createMoltbotTools } from "../agents/moltbot-tools.js";
import { resolveSessionTranscriptPath } from "../config/sessions.js";
import { emitAgentEvent } from "../infra/agent-events.js";
import {
@@ -86,7 +86,7 @@ describe("sessions_send gateway loopback", () => {
});
});
const tool = createClawdbotTools().find((candidate) => candidate.name === "sessions_send");
const tool = createMoltbotTools().find((candidate) => candidate.name === "sessions_send");
if (!tool) throw new Error("missing sessions_send tool");
const result = await tool.execute("call-loopback", {
@@ -151,7 +151,7 @@ describe("sessions_send label lookup", () => {
timeoutMs: 5000,
});
const tool = createClawdbotTools().find((candidate) => candidate.name === "sessions_send");
const tool = createMoltbotTools().find((candidate) => candidate.name === "sessions_send");
if (!tool) throw new Error("missing sessions_send tool");
// Send using label instead of sessionKey
@@ -171,7 +171,7 @@ describe("sessions_send label lookup", () => {
});
it("returns error when label not found", { timeout: 60_000 }, async () => {
const tool = createClawdbotTools().find((candidate) => candidate.name === "sessions_send");
const tool = createMoltbotTools().find((candidate) => candidate.name === "sessions_send");
if (!tool) throw new Error("missing sessions_send tool");
const result = await tool.execute("call-missing-label", {
@@ -185,7 +185,7 @@ describe("sessions_send label lookup", () => {
});
it("returns error when neither sessionKey nor label provided", { timeout: 60_000 }, async () => {
const tool = createClawdbotTools().find((candidate) => candidate.name === "sessions_send");
const tool = createMoltbotTools().find((candidate) => candidate.name === "sessions_send");
if (!tool) throw new Error("missing sessions_send tool");
const result = await tool.execute("call-no-key", {

View File

@@ -74,7 +74,7 @@ describe("gateway server sessions", () => {
});
test("lists and patches session store via sessions.* RPC", async () => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-sessions-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-sessions-"));
const storePath = path.join(dir, "sessions.json");
const now = Date.now();
const recent = now - 30_000;
@@ -370,7 +370,7 @@ describe("gateway server sessions", () => {
});
test("sessions.preview returns transcript previews", async () => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-sessions-preview-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-sessions-preview-"));
const storePath = path.join(dir, "sessions.json");
testState.sessionStorePath = storePath;
const sessionId = "sess-preview";
@@ -415,7 +415,7 @@ describe("gateway server sessions", () => {
});
test("sessions.delete rejects main and aborts active runs", async () => {
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-sessions-"));
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-sessions-"));
const storePath = path.join(dir, "sessions.json");
testState.sessionStorePath = storePath;

View File

@@ -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, STATE_DIR, 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,
stateDir: STATE_DIR,
sessionDefaults: {
defaultAgentId,
mainKey,

View File

@@ -13,7 +13,7 @@ describe("readFirstUserMessageFromTranscript", () => {
let storePath: string;
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "clawdbot-session-fs-test-"));
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "moltbot-session-fs-test-"));
storePath = path.join(tmpDir, "sessions.json");
});
@@ -159,7 +159,7 @@ describe("readLastMessagePreviewFromTranscript", () => {
let storePath: string;
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "clawdbot-session-fs-test-"));
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "moltbot-session-fs-test-"));
storePath = path.join(tmpDir, "sessions.json");
});
@@ -348,7 +348,7 @@ describe("readSessionPreviewItemsFromTranscript", () => {
let storePath: string;
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "clawdbot-session-preview-test-"));
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "moltbot-session-preview-test-"));
storePath = path.join(tmpDir, "sessions.json");
});

View File

@@ -1,7 +1,7 @@
import os from "node:os";
import path from "node:path";
import { describe, expect, test } from "vitest";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import type { SessionEntry } from "../config/sessions.js";
import {
capArrayByJsonBytes,
@@ -46,7 +46,7 @@ describe("gateway session utils", () => {
const cfg = {
session: { mainKey: "work" },
agents: { list: [{ id: "ops", default: true }] },
} as ClawdbotConfig;
} as MoltbotConfig;
expect(resolveSessionStoreKey({ cfg, sessionKey: "main" })).toBe("agent:ops:work");
expect(resolveSessionStoreKey({ cfg, sessionKey: "work" })).toBe("agent:ops:work");
expect(resolveSessionStoreKey({ cfg, sessionKey: "agent:ops:main" })).toBe("agent:ops:work");
@@ -56,7 +56,7 @@ describe("gateway session utils", () => {
const cfg = {
session: { mainKey: "main" },
agents: { list: [{ id: "ops", default: true }] },
} as ClawdbotConfig;
} as MoltbotConfig;
expect(resolveSessionStoreKey({ cfg, sessionKey: "discord:group:123" })).toBe(
"agent:ops:discord:group:123",
);
@@ -69,7 +69,7 @@ describe("gateway session utils", () => {
const cfg = {
session: { scope: "global", mainKey: "work" },
agents: { list: [{ id: "ops", default: true }] },
} as ClawdbotConfig;
} as MoltbotConfig;
expect(resolveSessionStoreKey({ cfg, sessionKey: "main" })).toBe("global");
const target = resolveGatewaySessionStoreTarget({ cfg, key: "main" });
expect(target.canonicalKey).toBe("global");
@@ -79,14 +79,14 @@ describe("gateway session utils", () => {
test("resolveGatewaySessionStoreTarget uses canonical key for main alias", () => {
const storeTemplate = path.join(
os.tmpdir(),
"clawdbot-session-utils",
"moltbot-session-utils",
"{agentId}",
"sessions.json",
);
const cfg = {
session: { mainKey: "main", store: storeTemplate },
agents: { list: [{ id: "ops", default: true }] },
} as ClawdbotConfig;
} as MoltbotConfig;
const target = resolveGatewaySessionStoreTarget({ cfg, key: "main" });
expect(target.canonicalKey).toBe("agent:ops:main");
expect(target.storeKeys).toEqual(expect.arrayContaining(["agent:ops:main", "main"]));
@@ -193,7 +193,7 @@ describe("listSessionsFromStore search", () => {
const baseCfg = {
session: { mainKey: "main" },
agents: { list: [{ id: "main", default: true }] },
} as ClawdbotConfig;
} as MoltbotConfig;
const makeStore = (): Record<string, SessionEntry> => ({
"agent:main:work-project": {

View File

@@ -5,7 +5,7 @@ import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent
import { lookupContextTokens } from "../agents/context.js";
import { DEFAULT_CONTEXT_TOKENS, DEFAULT_MODEL, DEFAULT_PROVIDER } from "../agents/defaults.js";
import { resolveConfiguredModelRef } from "../agents/model-selection.js";
import { type ClawdbotConfig, loadConfig } from "../config/config.js";
import { type MoltbotConfig, loadConfig } from "../config/config.js";
import { resolveStateDir } from "../config/paths.js";
import {
buildGroupDisplayName,
@@ -85,7 +85,7 @@ function isWorkspaceRelativePath(value: string): boolean {
}
function resolveIdentityAvatarUrl(
cfg: ClawdbotConfig,
cfg: MoltbotConfig,
agentId: string,
avatar: string | undefined,
): string | undefined {
@@ -211,7 +211,7 @@ function listExistingAgentIdsFromDisk(): string[] {
}
}
function listConfiguredAgentIds(cfg: ClawdbotConfig): string[] {
function listConfiguredAgentIds(cfg: MoltbotConfig): string[] {
const agents = cfg.agents?.list ?? [];
if (agents.length > 0) {
const ids = new Set<string>();
@@ -239,7 +239,7 @@ function listConfiguredAgentIds(cfg: ClawdbotConfig): string[] {
return sorted;
}
export function listAgentsForGateway(cfg: ClawdbotConfig): {
export function listAgentsForGateway(cfg: MoltbotConfig): {
defaultId: string;
mainKey: string;
scope: SessionScope;
@@ -301,14 +301,11 @@ function canonicalizeSessionKeyForAgent(agentId: string, key: string): string {
return `agent:${normalizeAgentId(agentId)}:${key}`;
}
function resolveDefaultStoreAgentId(cfg: ClawdbotConfig): string {
function resolveDefaultStoreAgentId(cfg: MoltbotConfig): string {
return normalizeAgentId(resolveDefaultAgentId(cfg));
}
export function resolveSessionStoreKey(params: {
cfg: ClawdbotConfig;
sessionKey: string;
}): string {
export function resolveSessionStoreKey(params: { cfg: MoltbotConfig; sessionKey: string }): string {
const raw = params.sessionKey.trim();
if (!raw) return raw;
if (raw === "global" || raw === "unknown") return raw;
@@ -333,7 +330,7 @@ export function resolveSessionStoreKey(params: {
return canonicalizeSessionKeyForAgent(agentId, raw);
}
function resolveSessionStoreAgentId(cfg: ClawdbotConfig, canonicalKey: string): string {
function resolveSessionStoreAgentId(cfg: MoltbotConfig, canonicalKey: string): string {
if (canonicalKey === "global" || canonicalKey === "unknown") {
return resolveDefaultStoreAgentId(cfg);
}
@@ -350,7 +347,7 @@ function canonicalizeSpawnedByForAgent(agentId: string, spawnedBy?: string): str
return `agent:${normalizeAgentId(agentId)}:${raw}`;
}
export function resolveGatewaySessionStoreTarget(params: { cfg: ClawdbotConfig; key: string }): {
export function resolveGatewaySessionStoreTarget(params: { cfg: MoltbotConfig; key: string }): {
agentId: string;
storePath: string;
canonicalKey: string;
@@ -406,7 +403,7 @@ function mergeSessionEntryIntoCombined(params: {
}
}
export function loadCombinedSessionStoreForGateway(cfg: ClawdbotConfig): {
export function loadCombinedSessionStoreForGateway(cfg: MoltbotConfig): {
storePath: string;
store: Record<string, SessionEntry>;
} {
@@ -449,7 +446,7 @@ export function loadCombinedSessionStoreForGateway(cfg: ClawdbotConfig): {
return { storePath, store: combined };
}
export function getSessionDefaults(cfg: ClawdbotConfig): GatewaySessionsDefaults {
export function getSessionDefaults(cfg: MoltbotConfig): GatewaySessionsDefaults {
const resolved = resolveConfiguredModelRef({
cfg,
defaultProvider: DEFAULT_PROVIDER,
@@ -467,7 +464,7 @@ export function getSessionDefaults(cfg: ClawdbotConfig): GatewaySessionsDefaults
}
export function resolveSessionModelRef(
cfg: ClawdbotConfig,
cfg: MoltbotConfig,
entry?: SessionEntry,
): { provider: string; model: string } {
const resolved = resolveConfiguredModelRef({
@@ -486,7 +483,7 @@ export function resolveSessionModelRef(
}
export function listSessionsFromStore(params: {
cfg: ClawdbotConfig;
cfg: MoltbotConfig;
storePath: string;
store: Record<string, SessionEntry>;
opts: import("./protocol/index.js").SessionsListParams;

View File

@@ -1,5 +1,5 @@
import { describe, expect, test } from "vitest";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import type { SessionEntry } from "../config/sessions.js";
import { applySessionsPatchToStore } from "./sessions-patch.js";
@@ -7,7 +7,7 @@ describe("gateway sessions patch", () => {
test("persists elevatedLevel=off (does not clear)", async () => {
const store: Record<string, SessionEntry> = {};
const res = await applySessionsPatchToStore({
cfg: {} as ClawdbotConfig,
cfg: {} as MoltbotConfig,
store,
storeKey: "agent:main:main",
patch: { elevatedLevel: "off" },
@@ -20,7 +20,7 @@ describe("gateway sessions patch", () => {
test("persists elevatedLevel=on", async () => {
const store: Record<string, SessionEntry> = {};
const res = await applySessionsPatchToStore({
cfg: {} as ClawdbotConfig,
cfg: {} as MoltbotConfig,
store,
storeKey: "agent:main:main",
patch: { elevatedLevel: "on" },
@@ -35,7 +35,7 @@ describe("gateway sessions patch", () => {
"agent:main:main": { elevatedLevel: "off" } as SessionEntry,
};
const res = await applySessionsPatchToStore({
cfg: {} as ClawdbotConfig,
cfg: {} as MoltbotConfig,
store,
storeKey: "agent:main:main",
patch: { elevatedLevel: null },
@@ -48,7 +48,7 @@ describe("gateway sessions patch", () => {
test("rejects invalid elevatedLevel values", async () => {
const store: Record<string, SessionEntry> = {};
const res = await applySessionsPatchToStore({
cfg: {} as ClawdbotConfig,
cfg: {} as MoltbotConfig,
store,
storeKey: "agent:main:main",
patch: { elevatedLevel: "maybe" },
@@ -71,7 +71,7 @@ describe("gateway sessions patch", () => {
} as SessionEntry,
};
const res = await applySessionsPatchToStore({
cfg: {} as ClawdbotConfig,
cfg: {} as MoltbotConfig,
store,
storeKey: "agent:main:main",
patch: { model: "openai/gpt-5.2" },

View File

@@ -13,7 +13,7 @@ import {
normalizeUsageDisplay,
supportsXHighThinking,
} from "../auto-reply/thinking.js";
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import type { SessionEntry } from "../config/sessions.js";
import { isSubagentSessionKey } from "../routing/session-key.js";
import { applyVerboseOverride, parseVerboseOverride } from "../sessions/level-overrides.js";
@@ -56,7 +56,7 @@ function normalizeExecAsk(raw: string): "off" | "on-miss" | "always" | undefined
}
export async function applySessionsPatchToStore(params: {
cfg: ClawdbotConfig;
cfg: MoltbotConfig;
store: Record<string, SessionEntry>;
storeKey: string;
patch: SessionsPatchParams;

View File

@@ -1,4 +1,4 @@
import type { ClawdbotConfig } from "../config/config.js";
import type { MoltbotConfig } from "../config/config.js";
import { loadSessionStore } from "../config/sessions.js";
import { parseSessionLabel } from "../sessions/session-label.js";
import {
@@ -16,7 +16,7 @@ import {
export type SessionsResolveResult = { ok: true; key: string } | { ok: false; error: ErrorShape };
export function resolveSessionKeyFromResolveParams(params: {
cfg: ClawdbotConfig;
cfg: MoltbotConfig;
p: SessionsResolveParams;
}): SessionsResolveResult {
const { cfg, p } = params;

View File

@@ -188,12 +188,12 @@ export const resetTestPluginRegistry = () => {
};
const testConfigRoot = {
value: path.join(os.tmpdir(), `clawdbot-gateway-test-${process.pid}-${crypto.randomUUID()}`),
value: path.join(os.tmpdir(), `moltbot-gateway-test-${process.pid}-${crypto.randomUUID()}`),
};
export const setTestConfigRoot = (root: string) => {
testConfigRoot.value = root;
process.env.CLAWDBOT_CONFIG_PATH = path.join(root, "clawdbot.json");
process.env.CLAWDBOT_CONFIG_PATH = path.join(root, "moltbot.json");
};
export const testTailnetIPv4 = hoisted.testTailnetIPv4;
@@ -271,7 +271,7 @@ vi.mock("../config/sessions.js", async () => {
vi.mock("../config/config.js", async () => {
const actual = await vi.importActual<typeof import("../config/config.js")>("../config/config.js");
const resolveConfigPath = () => path.join(testConfigRoot.value, "clawdbot.json");
const resolveConfigPath = () => path.join(testConfigRoot.value, "moltbot.json");
const hashConfigRaw = (raw: string | null) =>
crypto
.createHash("sha256")
@@ -350,10 +350,10 @@ vi.mock("../config/config.js", async () => {
return {
...actual,
get CONFIG_PATH_CLAWDBOT() {
get CONFIG_PATH() {
return resolveConfigPath();
},
get STATE_DIR_CLAWDBOT() {
get STATE_DIR() {
return path.dirname(resolveConfigPath());
},
get isNixMode() {

View File

@@ -83,7 +83,7 @@ async function setupGatewayTestHome() {
previousSkipBrowserControl = process.env.CLAWDBOT_SKIP_BROWSER_CONTROL_SERVER;
previousSkipGmailWatcher = process.env.CLAWDBOT_SKIP_GMAIL_WATCHER;
previousSkipCanvasHost = process.env.CLAWDBOT_SKIP_CANVAS_HOST;
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-gateway-home-"));
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-gateway-home-"));
process.env.HOME = tempHome;
process.env.USERPROFILE = tempHome;
process.env.CLAWDBOT_STATE_DIR = path.join(tempHome, ".clawdbot");
@@ -105,7 +105,7 @@ async function resetGatewayTestState(options: { uniqueConfigRoot: boolean }) {
}
applyGatewaySkipEnv();
tempConfigRoot = options.uniqueConfigRoot
? await fs.mkdtemp(path.join(tempHome, "clawdbot-test-"))
? await fs.mkdtemp(path.join(tempHome, "moltbot-test-"))
: path.join(tempHome, ".clawdbot-test");
setTestConfigRoot(tempConfigRoot);
sessionStoreSaveDelayMs.value = 0;

View File

@@ -7,7 +7,7 @@ import path from "node:path";
import { installGatewayTestHooks, getFreePort, startGatewayServer } from "./test-helpers.server.js";
import { resetTestPluginRegistry, setTestPluginRegistry, testState } from "./test-helpers.mocks.js";
import { createTestRegistry } from "../test-utils/channel-plugins.js";
import { CONFIG_PATH_CLAWDBOT } from "../config/config.js";
import { CONFIG_PATH } from "../config/config.js";
installGatewayTestHooks({ scope: "suite" });
@@ -91,9 +91,9 @@ describe("POST /tools/invoke", () => {
list: [{ id: "main" }],
} as any;
await fs.mkdir(path.dirname(CONFIG_PATH_CLAWDBOT), { recursive: true });
await fs.mkdir(path.dirname(CONFIG_PATH), { recursive: true });
await fs.writeFile(
CONFIG_PATH_CLAWDBOT,
CONFIG_PATH,
JSON.stringify({ tools: { alsoAllow: ["sessions_list"] } }, null, 2),
"utf-8",
);

View File

@@ -1,6 +1,6 @@
import type { IncomingMessage, ServerResponse } from "node:http";
import { createClawdbotTools } from "../agents/clawdbot-tools.js";
import { createMoltbotTools } from "../agents/moltbot-tools.js";
import {
filterToolsByPolicy,
resolveEffectiveToolPolicy,
@@ -117,10 +117,8 @@ export async function handleToolsInvokeHttpRequest(
!rawSessionKey || rawSessionKey === "main" ? resolveMainSessionKey(cfg) : rawSessionKey;
// Resolve message channel/account hints (optional headers) for policy inheritance.
const messageChannel = normalizeMessageChannel(
getHeader(req, "x-clawdbot-message-channel") ?? "",
);
const accountId = getHeader(req, "x-clawdbot-account-id")?.trim() || undefined;
const messageChannel = normalizeMessageChannel(getHeader(req, "x-moltbot-message-channel") ?? "");
const accountId = getHeader(req, "x-moltbot-account-id")?.trim() || undefined;
const {
agentId,
@@ -157,7 +155,7 @@ export async function handleToolsInvokeHttpRequest(
: undefined;
// Build tool list (core + plugin tools).
const allTools = createClawdbotTools({
const allTools = createMoltbotTools({
agentSessionKey: sessionKey,
agentChannel: messageChannel ?? undefined,
agentAccountId: accountId,