refactor: rename to openclaw

This commit is contained in:
Peter Steinberger
2026-01-30 03:15:10 +01:00
parent 4583f88626
commit 9a7160786a
2357 changed files with 16688 additions and 16788 deletions

View File

@@ -208,7 +208,7 @@ function resolveBrowserBaseUrl(params: {
}
if (!resolved.enabled) {
throw new Error(
"Browser control is disabled. Set browser.enabled=true in ~/.clawdbot/moltbot.json.",
"Browser control is disabled. Set browser.enabled=true in ~/.openclaw/openclaw.json.",
);
}
return undefined;
@@ -225,11 +225,11 @@ export function createBrowserTool(opts?: {
label: "Browser",
name: "browser",
description: [
"Control the browser via Moltbot's browser control server (status/start/stop/profiles/tabs/open/snapshot/screenshot/actions).",
'Profiles: use profile="chrome" for Chrome extension relay takeover (your existing Chrome tabs). Use profile="clawd" for the isolated clawd-managed browser.',
"Control the browser via OpenClaw's browser control server (status/start/stop/profiles/tabs/open/snapshot/screenshot/actions).",
'Profiles: use profile="chrome" for Chrome extension relay takeover (your existing Chrome tabs). Use profile="openclaw" for the isolated openclaw-managed browser.',
'If the user mentions the Chrome extension / Browser Relay / toolbar button / “attach tab”, ALWAYS use profile="chrome" (do not ask which profile).',
'When a node-hosted browser proxy is available, the tool may auto-route to it. Pin a node with node=<id|name> or target="node".',
"Chrome extension relay needs an attached tab: user must click the Moltbot Browser Relay toolbar icon on the tab (badge ON). If no tab is connected, ask them to attach it.",
"Chrome extension relay needs an attached tab: user must click the OpenClaw Browser Relay toolbar icon on the tab (badge ON). If no tab is connected, ask them to attach it.",
"When using refs from snapshot (e.g. e12), keep the same tab: prefer passing targetId from the snapshot response into subsequent actions (act/click/type/etc).",
'For stable, self-resolving refs across calls, use snapshot with refs="aria" (Playwright aria-ref ids). Default refs="role" are role+name-based.',
"Use snapshot+act for UI automation. Avoid act:wait by default; use only in exceptional cases when no reliable UI state exists.",
@@ -696,7 +696,7 @@ export function createBrowserTool(opts?: {
: await browserTabs(baseUrl, { profile }).catch(() => []);
if (!tabs.length) {
throw new Error(
"No Chrome tabs are attached via the Moltbot Browser Relay extension. Click the toolbar icon on the tab you want to control (badge ON), then retry.",
"No Chrome tabs are attached via the OpenClaw Browser Relay extension. Click the toolbar icon on the tab you want to control (badge ON), then retry.",
);
}
throw new Error(

View File

@@ -1,5 +1,5 @@
import type { AgentToolResult } from "@mariozechner/pi-agent-core";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import { createActionGate, readStringParam } from "./common.js";
import { handleDiscordGuildAction } from "./discord-actions-guild.js";
import { handleDiscordMessagingAction } from "./discord-actions-messaging.js";
@@ -53,7 +53,7 @@ const moderationActions = new Set(["timeout", "kick", "ban"]);
export async function handleDiscordAction(
params: Record<string, unknown>,
cfg: MoltbotConfig,
cfg: OpenClawConfig,
): Promise<AgentToolResult<unknown>> {
const action = readStringParam(params, "action", { required: true });
const isActionEnabled = createActionGate(cfg.channels?.discord?.actions);

View File

@@ -1,6 +1,6 @@
import { Type } from "@sinclair/typebox";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import { loadConfig, resolveConfigSnapshotHash } from "../../config/io.js";
import { loadSessionStore, resolveStorePath } from "../../config/sessions.js";
import { scheduleGatewaySigusr1Restart } from "../../infra/restart.js";
@@ -60,7 +60,7 @@ const GatewayToolSchema = Type.Object({
export function createGatewayTool(opts?: {
agentSessionKey?: string;
config?: MoltbotConfig;
config?: OpenClawConfig;
}): AnyAgentTool {
return {
label: "Gateway",

View File

@@ -1,6 +1,6 @@
import type { AssistantMessage } from "@mariozechner/pi-ai";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import { extractAssistantText } from "../pi-embedded-utils.js";
export type ImageModelConfig = { primary?: string; fallbacks?: string[] };
@@ -47,7 +47,7 @@ export function coerceImageAssistantText(params: {
throw new Error(`Image model returned no text (${params.provider}/${params.model}).`);
}
export function coerceImageModelConfig(cfg?: MoltbotConfig): ImageModelConfig {
export function coerceImageModelConfig(cfg?: OpenClawConfig): ImageModelConfig {
const imageModel = cfg?.agents?.defaults?.imageModel as
| { primary?: string; fallbacks?: string[] }
| string
@@ -61,7 +61,7 @@ export function coerceImageModelConfig(cfg?: MoltbotConfig): ImageModelConfig {
}
export function resolveProviderVisionModelFromConfig(params: {
cfg?: MoltbotConfig;
cfg?: OpenClawConfig;
provider: string;
}): string | null {
const providerCfg = params.cfg?.models?.providers?.[params.provider] as unknown as

View File

@@ -4,7 +4,7 @@ import path from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import { __testing, createImageTool, resolveImageModelConfigForTool } from "./image-tool.js";
async function writeAuthProfiles(agentDir: string, profiles: unknown) {
@@ -37,8 +37,8 @@ describe("image tool implicit imageModel config", () => {
});
it("stays disabled without auth when no pairing is possible", async () => {
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-image-"));
const cfg: MoltbotConfig = {
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-image-"));
const cfg: OpenClawConfig = {
agents: { defaults: { model: { primary: "openai/gpt-5.2" } } },
};
expect(resolveImageModelConfigForTool({ cfg, agentDir })).toBeNull();
@@ -46,11 +46,11 @@ describe("image tool implicit imageModel config", () => {
});
it("pairs minimax primary with MiniMax-VL-01 (and fallbacks) when auth exists", async () => {
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-image-"));
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-image-"));
vi.stubEnv("MINIMAX_API_KEY", "minimax-test");
vi.stubEnv("OPENAI_API_KEY", "openai-test");
vi.stubEnv("ANTHROPIC_API_KEY", "anthropic-test");
const cfg: MoltbotConfig = {
const cfg: OpenClawConfig = {
agents: { defaults: { model: { primary: "minimax/MiniMax-M2.1" } } },
};
expect(resolveImageModelConfigForTool({ cfg, agentDir })).toEqual({
@@ -61,14 +61,14 @@ describe("image tool implicit imageModel config", () => {
});
it("pairs a custom provider when it declares an image-capable model", async () => {
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-image-"));
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-image-"));
await writeAuthProfiles(agentDir, {
version: 1,
profiles: {
"acme:default": { type: "api_key", provider: "acme", key: "sk-test" },
},
});
const cfg: MoltbotConfig = {
const cfg: OpenClawConfig = {
agents: { defaults: { model: { primary: "acme/text-1" } } },
models: {
providers: {
@@ -88,8 +88,8 @@ describe("image tool implicit imageModel config", () => {
});
it("prefers explicit agents.defaults.imageModel", async () => {
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-image-"));
const cfg: MoltbotConfig = {
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-image-"));
const cfg: OpenClawConfig = {
agents: {
defaults: {
model: { primary: "minimax/MiniMax-M2.1" },
@@ -107,8 +107,8 @@ describe("image tool implicit imageModel config", () => {
// because images are auto-injected into prompts. The tool description is
// adjusted via modelHasVision to discourage redundant usage.
vi.stubEnv("OPENAI_API_KEY", "test-key");
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-image-"));
const cfg: MoltbotConfig = {
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-image-"));
const cfg: OpenClawConfig = {
agents: {
defaults: {
model: { primary: "acme/vision-1" },
@@ -135,7 +135,7 @@ describe("image tool implicit imageModel config", () => {
});
it("sandboxes image paths like the read tool", async () => {
const stateDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-image-sandbox-"));
const stateDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-image-sandbox-"));
const agentDir = path.join(stateDir, "agent");
const sandboxRoot = path.join(stateDir, "sandbox");
await fs.mkdir(agentDir, { recursive: true });
@@ -143,7 +143,7 @@ describe("image tool implicit imageModel config", () => {
await fs.writeFile(path.join(sandboxRoot, "img.png"), "fake", "utf8");
vi.stubEnv("OPENAI_API_KEY", "openai-test");
const cfg: MoltbotConfig = {
const cfg: OpenClawConfig = {
agents: { defaults: { model: { primary: "minimax/MiniMax-M2.1" } } },
};
const tool = createImageTool({ config: cfg, agentDir, sandboxRoot });
@@ -160,7 +160,7 @@ describe("image tool implicit imageModel config", () => {
});
it("rewrites inbound absolute paths into sandbox media/inbound", async () => {
const stateDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-image-sandbox-"));
const stateDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-image-sandbox-"));
const agentDir = path.join(stateDir, "agent");
const sandboxRoot = path.join(stateDir, "sandbox");
await fs.mkdir(agentDir, { recursive: true });
@@ -188,7 +188,7 @@ describe("image tool implicit imageModel config", () => {
global.fetch = fetch;
vi.stubEnv("MINIMAX_API_KEY", "minimax-test");
const cfg: MoltbotConfig = {
const cfg: OpenClawConfig = {
agents: {
defaults: {
model: { primary: "minimax/MiniMax-M2.1" },
@@ -202,7 +202,7 @@ describe("image tool implicit imageModel config", () => {
const res = await tool.execute("t1", {
prompt: "Describe the image.",
image: "@/Users/steipete/.clawdbot/media/inbound/photo.png",
image: "@/Users/steipete/.openclaw/media/inbound/photo.png",
});
expect(fetch).toHaveBeenCalledTimes(1);
@@ -259,9 +259,9 @@ describe("image tool MiniMax VLM routing", () => {
// @ts-expect-error partial global
global.fetch = fetch;
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-minimax-vlm-"));
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-minimax-vlm-"));
vi.stubEnv("MINIMAX_API_KEY", "minimax-test");
const cfg: MoltbotConfig = {
const cfg: OpenClawConfig = {
agents: { defaults: { model: { primary: "minimax/MiniMax-M2.1" } } },
};
const tool = createImageTool({ config: cfg, agentDir });
@@ -301,9 +301,9 @@ describe("image tool MiniMax VLM routing", () => {
// @ts-expect-error partial global
global.fetch = fetch;
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-minimax-vlm-"));
const agentDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-minimax-vlm-"));
vi.stubEnv("MINIMAX_API_KEY", "minimax-test");
const cfg: MoltbotConfig = {
const cfg: OpenClawConfig = {
agents: { defaults: { model: { primary: "minimax/MiniMax-M2.1" } } },
};
const tool = createImageTool({ config: cfg, agentDir });

View File

@@ -11,7 +11,7 @@ import {
import { discoverAuthStorage, discoverModels } from "@mariozechner/pi-coding-agent";
import { Type } from "@sinclair/typebox";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import { resolveUserPath } from "../../utils.js";
import { loadWebMedia } from "../../web/media.js";
import { ensureAuthProfileStore, listProfilesForProvider } from "../auth-profiles.js";
@@ -20,7 +20,7 @@ import { minimaxUnderstandImage } from "../minimax-vlm.js";
import { getApiKeyForModel, requireApiKey, resolveEnvApiKey } from "../model-auth.js";
import { runWithImageModelFallback } from "../model-fallback.js";
import { resolveConfiguredModelRef } from "../model-selection.js";
import { ensureMoltbotModelsJson } from "../models-config.js";
import { ensureOpenClawModelsJson } from "../models-config.js";
import { assertSandboxPath } from "../sandbox-paths.js";
import type { AnyAgentTool } from "./common.js";
import {
@@ -38,7 +38,7 @@ export const __testing = {
coerceImageAssistantText,
} as const;
function resolveDefaultModelRef(cfg?: MoltbotConfig): {
function resolveDefaultModelRef(cfg?: OpenClawConfig): {
provider: string;
model: string;
} {
@@ -70,7 +70,7 @@ function hasAuthForProvider(params: { provider: string; agentDir: string }): boo
* - fall back to OpenAI/Anthropic when available
*/
export function resolveImageModelConfigForTool(params: {
cfg?: MoltbotConfig;
cfg?: OpenClawConfig;
agentDir: string;
}): ImageModelConfig | null {
// Note: We intentionally do NOT gate based on primarySupportsImages here.
@@ -148,7 +148,7 @@ export function resolveImageModelConfigForTool(params: {
return null;
}
function pickMaxBytes(cfg?: MoltbotConfig, maxBytesMb?: number): number | undefined {
function pickMaxBytes(cfg?: OpenClawConfig, maxBytesMb?: number): number | undefined {
if (typeof maxBytesMb === "number" && Number.isFinite(maxBytesMb) && maxBytesMb > 0) {
return Math.floor(maxBytesMb * 1024 * 1024);
}
@@ -206,7 +206,7 @@ async function resolveSandboxedImagePath(params: {
}
async function runImagePrompt(params: {
cfg?: MoltbotConfig;
cfg?: OpenClawConfig;
agentDir: string;
imageModelConfig: ImageModelConfig;
modelOverride?: string;
@@ -219,7 +219,7 @@ async function runImagePrompt(params: {
model: string;
attempts: Array<{ provider: string; model: string; error: string }>;
}> {
const effectiveCfg: MoltbotConfig | undefined = params.cfg
const effectiveCfg: OpenClawConfig | undefined = params.cfg
? {
...params.cfg,
agents: {
@@ -232,7 +232,7 @@ async function runImagePrompt(params: {
}
: undefined;
await ensureMoltbotModelsJson(effectiveCfg, params.agentDir);
await ensureOpenClawModelsJson(effectiveCfg, params.agentDir);
const authStorage = discoverAuthStorage(params.agentDir);
const modelRegistry = discoverModels(authStorage, params.agentDir);
@@ -293,7 +293,7 @@ async function runImagePrompt(params: {
}
export function createImageTool(options?: {
config?: MoltbotConfig;
config?: OpenClawConfig;
agentDir?: string;
sandboxRoot?: string;
/** If true, the model has native vision capability and images in the prompt are auto-injected */

View File

@@ -1,6 +1,6 @@
import { Type } from "@sinclair/typebox";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import { getMemorySearchManager } from "../../memory/index.js";
import { resolveSessionAgentId } from "../agent-scope.js";
import { resolveMemorySearchConfig } from "../memory-search.js";
@@ -20,7 +20,7 @@ const MemoryGetSchema = Type.Object({
});
export function createMemorySearchTool(options: {
config?: MoltbotConfig;
config?: OpenClawConfig;
agentSessionKey?: string;
}): AnyAgentTool | null {
const cfg = options.config;
@@ -69,7 +69,7 @@ export function createMemorySearchTool(options: {
}
export function createMemoryGetTool(options: {
config?: MoltbotConfig;
config?: OpenClawConfig;
agentSessionKey?: string;
}): AnyAgentTool | null {
const cfg = options.config;

View File

@@ -9,7 +9,7 @@ import {
type ChannelMessageActionName,
} from "../../channels/plugins/types.js";
import { BLUEBUBBLES_GROUP_ACTIONS } from "../../channels/plugins/bluebubbles-actions.js";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import { loadConfig } from "../../config/config.js";
import { GATEWAY_CLIENT_IDS, GATEWAY_CLIENT_MODES } from "../../gateway/protocol/client-info.js";
import { normalizeTargetForProvider } from "../../infra/outbound/target-normalization.js";
@@ -242,7 +242,7 @@ const MessageToolSchema = buildMessageToolSchemaFromActions(AllMessageActions, {
type MessageToolOptions = {
agentAccountId?: string;
agentSessionKey?: string;
config?: MoltbotConfig;
config?: OpenClawConfig;
currentChannelId?: string;
currentChannelProvider?: string;
currentThreadTs?: string;
@@ -250,7 +250,7 @@ type MessageToolOptions = {
hasRepliedRef?: { value: boolean };
};
function buildMessageToolSchema(cfg: MoltbotConfig) {
function buildMessageToolSchema(cfg: OpenClawConfig) {
const actions = listChannelMessageActions(cfg);
const includeButtons = supportsChannelMessageButtons(cfg);
const includeCards = supportsChannelMessageCards(cfg);
@@ -288,7 +288,7 @@ function filterActionsForContext(params: {
}
function buildMessageToolDescription(options?: {
config?: MoltbotConfig;
config?: OpenClawConfig;
currentChannel?: string;
currentChannelId?: string;
}): string {

View File

@@ -17,7 +17,7 @@ import {
writeScreenRecordToFile,
} from "../../cli/nodes-screen.js";
import { parseDurationMs } from "../../cli/parse-duration.js";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import { imageMimeFromFormat } from "../../media/mime.js";
import { resolveSessionAgentId } from "../agent-scope.js";
import { optionalStringEnum, stringEnum } from "../schema/typebox.js";
@@ -90,7 +90,7 @@ const NodesToolSchema = Type.Object({
export function createNodesTool(options?: {
agentSessionKey?: string;
config?: MoltbotConfig;
config?: OpenClawConfig;
}): AnyAgentTool {
const sessionKey = options?.agentSessionKey?.trim() || undefined;
const agentId = resolveSessionAgentId({

View File

@@ -19,7 +19,7 @@ import { formatUserTime, resolveUserTimeFormat, resolveUserTimezone } from "../d
import { normalizeGroupActivation } from "../../auto-reply/group-activation.js";
import { getFollowupQueueDepth, resolveQueueSettings } from "../../auto-reply/reply/queue.js";
import { buildStatusMessage } from "../../auto-reply/status.js";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import { loadConfig } from "../../config/config.js";
import {
loadSessionStore,
@@ -64,7 +64,7 @@ function formatApiKeySnippet(apiKey: string): string {
function resolveModelAuthLabel(params: {
provider?: string;
cfg: MoltbotConfig;
cfg: OpenClawConfig;
sessionEntry?: SessionEntry;
agentDir?: string;
}): string | undefined {
@@ -156,7 +156,7 @@ function resolveSessionEntry(params: {
}
function resolveSessionKeyFromSessionId(params: {
cfg: MoltbotConfig;
cfg: OpenClawConfig;
sessionId: string;
agentId?: string;
}): string | null {
@@ -172,7 +172,7 @@ function resolveSessionKeyFromSessionId(params: {
}
async function resolveModelOverride(params: {
cfg: MoltbotConfig;
cfg: OpenClawConfig;
raw: string;
sessionEntry?: SessionEntry;
agentId: string;
@@ -232,7 +232,7 @@ async function resolveModelOverride(params: {
export function createSessionStatusTool(opts?: {
agentSessionKey?: string;
config?: MoltbotConfig;
config?: OpenClawConfig;
}): AnyAgentTool {
return {
label: "Session Status",

View File

@@ -1,4 +1,4 @@
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import { callGateway } from "../../gateway/call.js";
import { sanitizeUserFacingText } from "../pi-embedded-helpers.js";
import {
@@ -45,7 +45,7 @@ function normalizeKey(value?: string) {
return trimmed ? trimmed : undefined;
}
export function resolveMainSessionAlias(cfg: MoltbotConfig) {
export function resolveMainSessionAlias(cfg: OpenClawConfig) {
const mainKey = normalizeMainKey(cfg.session?.mainKey);
const scope = cfg.session?.scope ?? "per-sender";
const alias = scope === "global" ? "global" : mainKey;
@@ -69,7 +69,7 @@ export type AgentToAgentPolicy = {
isAllowed: (requesterAgentId: string, targetAgentId: string) => boolean;
};
export function createAgentToAgentPolicy(cfg: MoltbotConfig): AgentToAgentPolicy {
export function createAgentToAgentPolicy(cfg: OpenClawConfig): AgentToAgentPolicy {
const routingA2A = cfg.tools?.agentToAgent;
const enabled = routingA2A?.enabled === true;
const allowPatterns = Array.isArray(routingA2A?.allow) ? routingA2A.allow : [];

View File

@@ -3,7 +3,7 @@ import {
normalizeChannelId as normalizeAnyChannelId,
} from "../../channels/plugins/index.js";
import { normalizeChannelId as normalizeChatChannelId } from "../../channels/registry.js";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
const ANNOUNCE_SKIP_TOKEN = "ANNOUNCE_SKIP";
const REPLY_SKIP_TOKEN = "REPLY_SKIP";
@@ -145,7 +145,7 @@ export function isReplySkip(text?: string) {
return (text ?? "").trim() === REPLY_SKIP_TOKEN;
}
export function resolvePingPongTurns(cfg?: MoltbotConfig) {
export function resolvePingPongTurns(cfg?: OpenClawConfig) {
const raw = cfg?.session?.agentToAgent?.maxPingPongTurns;
const fallback = DEFAULT_PING_PONG_TURNS;
if (typeof raw !== "number" || !Number.isFinite(raw)) return fallback;

View File

@@ -148,7 +148,7 @@ export function createSessionsSendTool(opts?: {
return jsonResult({
runId: crypto.randomUUID(),
status: "forbidden",
error: `Session not visible from this sandboxed agent session: label=${labelParam}`,
error: "Session not visible from this sandboxed agent session.",
});
}
return jsonResult({
@@ -163,7 +163,7 @@ export function createSessionsSendTool(opts?: {
return jsonResult({
runId: crypto.randomUUID(),
status: "forbidden",
error: `Session not visible from this sandboxed agent session: label=${labelParam}`,
error: "Session not visible from this sandboxed agent session.",
});
}
return jsonResult({

View File

@@ -1,6 +1,6 @@
import { describe, expect, it, vi } from "vitest";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import { handleSlackAction } from "./slack-actions.js";
const deleteSlackMessage = vi.fn(async () => ({}));
@@ -35,7 +35,7 @@ vi.mock("../../slack/actions.js", () => ({
describe("handleSlackAction", () => {
it("adds reactions", async () => {
const cfg = { channels: { slack: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { slack: { botToken: "tok" } } } as OpenClawConfig;
await handleSlackAction(
{
action: "react",
@@ -49,7 +49,7 @@ describe("handleSlackAction", () => {
});
it("strips channel: prefix for channelId params", async () => {
const cfg = { channels: { slack: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { slack: { botToken: "tok" } } } as OpenClawConfig;
await handleSlackAction(
{
action: "react",
@@ -63,7 +63,7 @@ describe("handleSlackAction", () => {
});
it("removes reactions on empty emoji", async () => {
const cfg = { channels: { slack: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { slack: { botToken: "tok" } } } as OpenClawConfig;
await handleSlackAction(
{
action: "react",
@@ -77,7 +77,7 @@ describe("handleSlackAction", () => {
});
it("removes reactions when remove flag set", async () => {
const cfg = { channels: { slack: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { slack: { botToken: "tok" } } } as OpenClawConfig;
await handleSlackAction(
{
action: "react",
@@ -92,7 +92,7 @@ describe("handleSlackAction", () => {
});
it("rejects removes without emoji", async () => {
const cfg = { channels: { slack: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { slack: { botToken: "tok" } } } as OpenClawConfig;
await expect(
handleSlackAction(
{
@@ -110,7 +110,7 @@ describe("handleSlackAction", () => {
it("respects reaction gating", async () => {
const cfg = {
channels: { slack: { botToken: "tok", actions: { reactions: false } } },
} as MoltbotConfig;
} as OpenClawConfig;
await expect(
handleSlackAction(
{
@@ -125,7 +125,7 @@ describe("handleSlackAction", () => {
});
it("passes threadTs to sendSlackMessage for thread replies", async () => {
const cfg = { channels: { slack: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { slack: { botToken: "tok" } } } as OpenClawConfig;
await handleSlackAction(
{
action: "sendMessage",
@@ -142,7 +142,7 @@ describe("handleSlackAction", () => {
});
it("auto-injects threadTs from context when replyToMode=all", async () => {
const cfg = { channels: { slack: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { slack: { botToken: "tok" } } } as OpenClawConfig;
sendSlackMessage.mockClear();
await handleSlackAction(
{
@@ -164,7 +164,7 @@ describe("handleSlackAction", () => {
});
it("replyToMode=first threads first message then stops", async () => {
const cfg = { channels: { slack: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { slack: { botToken: "tok" } } } as OpenClawConfig;
sendSlackMessage.mockClear();
const hasRepliedRef = { value: false };
const context = {
@@ -199,7 +199,7 @@ describe("handleSlackAction", () => {
});
it("replyToMode=first marks hasRepliedRef even when threadTs is explicit", async () => {
const cfg = { channels: { slack: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { slack: { botToken: "tok" } } } as OpenClawConfig;
sendSlackMessage.mockClear();
const hasRepliedRef = { value: false };
const context = {
@@ -237,7 +237,7 @@ describe("handleSlackAction", () => {
});
it("replyToMode=first without hasRepliedRef does not thread", async () => {
const cfg = { channels: { slack: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { slack: { botToken: "tok" } } } as OpenClawConfig;
sendSlackMessage.mockClear();
await handleSlackAction({ action: "sendMessage", to: "channel:C123", content: "No ref" }, cfg, {
currentChannelId: "C123",
@@ -252,7 +252,7 @@ describe("handleSlackAction", () => {
});
it("does not auto-inject threadTs when replyToMode=off", async () => {
const cfg = { channels: { slack: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { slack: { botToken: "tok" } } } as OpenClawConfig;
sendSlackMessage.mockClear();
await handleSlackAction(
{
@@ -274,7 +274,7 @@ describe("handleSlackAction", () => {
});
it("does not auto-inject threadTs when sending to different channel", async () => {
const cfg = { channels: { slack: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { slack: { botToken: "tok" } } } as OpenClawConfig;
sendSlackMessage.mockClear();
await handleSlackAction(
{
@@ -296,7 +296,7 @@ describe("handleSlackAction", () => {
});
it("explicit threadTs overrides context threadTs", async () => {
const cfg = { channels: { slack: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { slack: { botToken: "tok" } } } as OpenClawConfig;
sendSlackMessage.mockClear();
await handleSlackAction(
{
@@ -319,7 +319,7 @@ describe("handleSlackAction", () => {
});
it("handles channel target without prefix when replyToMode=all", async () => {
const cfg = { channels: { slack: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { slack: { botToken: "tok" } } } as OpenClawConfig;
sendSlackMessage.mockClear();
await handleSlackAction(
{
@@ -341,7 +341,7 @@ describe("handleSlackAction", () => {
});
it("adds normalized timestamps to readMessages payloads", async () => {
const cfg = { channels: { slack: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { slack: { botToken: "tok" } } } as OpenClawConfig;
readSlackMessages.mockResolvedValueOnce({
messages: [{ ts: "1735689600.456", text: "hi" }],
hasMore: false,
@@ -358,7 +358,7 @@ describe("handleSlackAction", () => {
});
it("passes threadId through to readSlackMessages", async () => {
const cfg = { channels: { slack: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { slack: { botToken: "tok" } } } as OpenClawConfig;
readSlackMessages.mockClear();
readSlackMessages.mockResolvedValueOnce({ messages: [], hasMore: false });
@@ -372,7 +372,7 @@ describe("handleSlackAction", () => {
});
it("adds normalized timestamps to pin payloads", async () => {
const cfg = { channels: { slack: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { slack: { botToken: "tok" } } } as OpenClawConfig;
listSlackPins.mockResolvedValueOnce([
{
type: "message",
@@ -393,7 +393,7 @@ describe("handleSlackAction", () => {
it("uses user token for reads when available", async () => {
const cfg = {
channels: { slack: { botToken: "xoxb-1", userToken: "xoxp-1" } },
} as MoltbotConfig;
} as OpenClawConfig;
readSlackMessages.mockClear();
readSlackMessages.mockResolvedValueOnce({ messages: [], hasMore: false });
await handleSlackAction({ action: "readMessages", channelId: "C1" }, cfg);
@@ -404,7 +404,7 @@ describe("handleSlackAction", () => {
it("falls back to bot token for reads when user token missing", async () => {
const cfg = {
channels: { slack: { botToken: "xoxb-1" } },
} as MoltbotConfig;
} as OpenClawConfig;
readSlackMessages.mockClear();
readSlackMessages.mockResolvedValueOnce({ messages: [], hasMore: false });
await handleSlackAction({ action: "readMessages", channelId: "C1" }, cfg);
@@ -415,7 +415,7 @@ describe("handleSlackAction", () => {
it("uses bot token for writes when userTokenReadOnly is true", async () => {
const cfg = {
channels: { slack: { botToken: "xoxb-1", userToken: "xoxp-1" } },
} as MoltbotConfig;
} as OpenClawConfig;
sendSlackMessage.mockClear();
await handleSlackAction({ action: "sendMessage", to: "channel:C1", content: "Hello" }, cfg);
const [, , opts] = sendSlackMessage.mock.calls[0] ?? [];
@@ -427,7 +427,7 @@ describe("handleSlackAction", () => {
channels: {
slack: { userToken: "xoxp-1", userTokenReadOnly: false },
},
} as MoltbotConfig;
} as OpenClawConfig;
sendSlackMessage.mockClear();
await handleSlackAction({ action: "sendMessage", to: "channel:C1", content: "Hello" }, cfg);
const [, , opts] = sendSlackMessage.mock.calls[0] ?? [];

View File

@@ -1,6 +1,6 @@
import type { AgentToolResult } from "@mariozechner/pi-agent-core";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import { resolveSlackAccount } from "../../slack/accounts.js";
import {
deleteSlackMessage,
@@ -73,7 +73,7 @@ function resolveThreadTsFromContext(
export async function handleSlackAction(
params: Record<string, unknown>,
cfg: MoltbotConfig,
cfg: OpenClawConfig,
context?: SlackActionContext,
): Promise<AgentToolResult<unknown>> {
const resolveChannelId = () =>

View File

@@ -1,6 +1,6 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import { handleTelegramAction, readTelegramButtons } from "./telegram-actions.js";
const reactMessageTelegram = vi.fn(async () => ({ ok: true }));
@@ -42,7 +42,7 @@ describe("handleTelegramAction", () => {
it("adds reactions when reactionLevel is minimal", async () => {
const cfg = {
channels: { telegram: { botToken: "tok", reactionLevel: "minimal" } },
} as MoltbotConfig;
} as OpenClawConfig;
await handleTelegramAction(
{
action: "react",
@@ -63,7 +63,7 @@ describe("handleTelegramAction", () => {
it("adds reactions when reactionLevel is extensive", async () => {
const cfg = {
channels: { telegram: { botToken: "tok", reactionLevel: "extensive" } },
} as MoltbotConfig;
} as OpenClawConfig;
await handleTelegramAction(
{
action: "react",
@@ -84,7 +84,7 @@ describe("handleTelegramAction", () => {
it("removes reactions on empty emoji", async () => {
const cfg = {
channels: { telegram: { botToken: "tok", reactionLevel: "minimal" } },
} as MoltbotConfig;
} as OpenClawConfig;
await handleTelegramAction(
{
action: "react",
@@ -103,7 +103,7 @@ describe("handleTelegramAction", () => {
});
it("rejects sticker actions when disabled by default", async () => {
const cfg = { channels: { telegram: { botToken: "tok" } } } as MoltbotConfig;
const cfg = { channels: { telegram: { botToken: "tok" } } } as OpenClawConfig;
await expect(
handleTelegramAction(
{
@@ -120,7 +120,7 @@ describe("handleTelegramAction", () => {
it("sends stickers when enabled", async () => {
const cfg = {
channels: { telegram: { botToken: "tok", actions: { sticker: true } } },
} as MoltbotConfig;
} as OpenClawConfig;
await handleTelegramAction(
{
action: "sendSticker",
@@ -139,7 +139,7 @@ describe("handleTelegramAction", () => {
it("removes reactions when remove flag set", async () => {
const cfg = {
channels: { telegram: { botToken: "tok", reactionLevel: "extensive" } },
} as MoltbotConfig;
} as OpenClawConfig;
await handleTelegramAction(
{
action: "react",
@@ -161,7 +161,7 @@ describe("handleTelegramAction", () => {
it("blocks reactions when reactionLevel is off", async () => {
const cfg = {
channels: { telegram: { botToken: "tok", reactionLevel: "off" } },
} as MoltbotConfig;
} as OpenClawConfig;
await expect(
handleTelegramAction(
{
@@ -178,7 +178,7 @@ describe("handleTelegramAction", () => {
it("blocks reactions when reactionLevel is ack", async () => {
const cfg = {
channels: { telegram: { botToken: "tok", reactionLevel: "ack" } },
} as MoltbotConfig;
} as OpenClawConfig;
await expect(
handleTelegramAction(
{
@@ -201,7 +201,7 @@ describe("handleTelegramAction", () => {
actions: { reactions: false },
},
},
} as MoltbotConfig;
} as OpenClawConfig;
await expect(
handleTelegramAction(
{
@@ -218,7 +218,7 @@ describe("handleTelegramAction", () => {
it("sends a text message", async () => {
const cfg = {
channels: { telegram: { botToken: "tok" } },
} as MoltbotConfig;
} as OpenClawConfig;
const result = await handleTelegramAction(
{
action: "sendMessage",
@@ -241,7 +241,7 @@ describe("handleTelegramAction", () => {
it("sends a message with media", async () => {
const cfg = {
channels: { telegram: { botToken: "tok" } },
} as MoltbotConfig;
} as OpenClawConfig;
await handleTelegramAction(
{
action: "sendMessage",
@@ -264,7 +264,7 @@ describe("handleTelegramAction", () => {
it("passes quoteText when provided", async () => {
const cfg = {
channels: { telegram: { botToken: "tok" } },
} as MoltbotConfig;
} as OpenClawConfig;
await handleTelegramAction(
{
action: "sendMessage",
@@ -289,7 +289,7 @@ describe("handleTelegramAction", () => {
it("allows media-only messages without content", async () => {
const cfg = {
channels: { telegram: { botToken: "tok" } },
} as MoltbotConfig;
} as OpenClawConfig;
await handleTelegramAction(
{
action: "sendMessage",
@@ -311,7 +311,7 @@ describe("handleTelegramAction", () => {
it("requires content when no mediaUrl is provided", async () => {
const cfg = {
channels: { telegram: { botToken: "tok" } },
} as MoltbotConfig;
} as OpenClawConfig;
await expect(
handleTelegramAction(
{
@@ -328,7 +328,7 @@ describe("handleTelegramAction", () => {
channels: {
telegram: { botToken: "tok", actions: { sendMessage: false } },
},
} as MoltbotConfig;
} as OpenClawConfig;
await expect(
handleTelegramAction(
{
@@ -344,7 +344,7 @@ describe("handleTelegramAction", () => {
it("deletes a message", async () => {
const cfg = {
channels: { telegram: { botToken: "tok" } },
} as MoltbotConfig;
} as OpenClawConfig;
await handleTelegramAction(
{
action: "deleteMessage",
@@ -365,7 +365,7 @@ describe("handleTelegramAction", () => {
channels: {
telegram: { botToken: "tok", actions: { deleteMessage: false } },
},
} as MoltbotConfig;
} as OpenClawConfig;
await expect(
handleTelegramAction(
{
@@ -380,7 +380,7 @@ describe("handleTelegramAction", () => {
it("throws on missing bot token for sendMessage", async () => {
delete process.env.TELEGRAM_BOT_TOKEN;
const cfg = {} as MoltbotConfig;
const cfg = {} as OpenClawConfig;
await expect(
handleTelegramAction(
{
@@ -396,7 +396,7 @@ describe("handleTelegramAction", () => {
it("allows inline buttons by default (allowlist)", async () => {
const cfg = {
channels: { telegram: { botToken: "tok" } },
} as MoltbotConfig;
} as OpenClawConfig;
await handleTelegramAction(
{
action: "sendMessage",
@@ -414,7 +414,7 @@ describe("handleTelegramAction", () => {
channels: {
telegram: { botToken: "tok", capabilities: { inlineButtons: "off" } },
},
} as MoltbotConfig;
} as OpenClawConfig;
await expect(
handleTelegramAction(
{
@@ -433,7 +433,7 @@ describe("handleTelegramAction", () => {
channels: {
telegram: { botToken: "tok", capabilities: { inlineButtons: "dm" } },
},
} as MoltbotConfig;
} as OpenClawConfig;
await expect(
handleTelegramAction(
{
@@ -452,7 +452,7 @@ describe("handleTelegramAction", () => {
channels: {
telegram: { botToken: "tok", capabilities: { inlineButtons: "dm" } },
},
} as MoltbotConfig;
} as OpenClawConfig;
await handleTelegramAction(
{
action: "sendMessage",
@@ -470,7 +470,7 @@ describe("handleTelegramAction", () => {
channels: {
telegram: { botToken: "tok", capabilities: { inlineButtons: "group" } },
},
} as MoltbotConfig;
} as OpenClawConfig;
await handleTelegramAction(
{
action: "sendMessage",
@@ -488,7 +488,7 @@ describe("handleTelegramAction", () => {
channels: {
telegram: { botToken: "tok", capabilities: { inlineButtons: "all" } },
},
} as MoltbotConfig;
} as OpenClawConfig;
await handleTelegramAction(
{
action: "sendMessage",

View File

@@ -1,5 +1,5 @@
import type { AgentToolResult } from "@mariozechner/pi-agent-core";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import { resolveTelegramReactionLevel } from "../../telegram/reaction-level.js";
import {
deleteMessageTelegram,
@@ -69,7 +69,7 @@ export function readTelegramButtons(
export async function handleTelegramAction(
params: Record<string, unknown>,
cfg: MoltbotConfig,
cfg: OpenClawConfig,
): Promise<AgentToolResult<unknown>> {
const action = readStringParam(params, "action", { required: true });
const accountId = readStringParam(params, "accountId");

View File

@@ -1,7 +1,7 @@
import { Type } from "@sinclair/typebox";
import { loadConfig } from "../../config/config.js";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import type { GatewayMessageChannel } from "../../utils/message-channel.js";
import { textToSpeech } from "../../tts/tts.js";
import type { AnyAgentTool } from "./common.js";
@@ -15,7 +15,7 @@ const TtsToolSchema = Type.Object({
});
export function createTtsTool(opts?: {
config?: MoltbotConfig;
config?: OpenClawConfig;
agentChannel?: GatewayMessageChannel;
}): AnyAgentTool {
return {

View File

@@ -1,6 +1,6 @@
import { Type } from "@sinclair/typebox";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import {
closeDispatcher,
createPinnedDispatcher,
@@ -61,7 +61,7 @@ const WebFetchSchema = Type.Object({
),
});
type WebFetchConfig = NonNullable<MoltbotConfig["tools"]>["web"] extends infer Web
type WebFetchConfig = NonNullable<OpenClawConfig["tools"]>["web"] extends infer Web
? Web extends { fetch?: infer Fetch }
? Fetch
: undefined
@@ -78,7 +78,7 @@ type FirecrawlFetchConfig =
}
| undefined;
function resolveFetchConfig(cfg?: MoltbotConfig): WebFetchConfig {
function resolveFetchConfig(cfg?: OpenClawConfig): WebFetchConfig {
const fetch = cfg?.tools?.web?.fetch;
if (!fetch || typeof fetch !== "object") return undefined;
return fetch as WebFetchConfig;
@@ -570,7 +570,7 @@ function resolveFirecrawlEndpoint(baseUrl: string): string {
}
export function createWebFetchTool(options?: {
config?: MoltbotConfig;
config?: OpenClawConfig;
sandboxed?: boolean;
}): AnyAgentTool | null {
const fetch = resolveFetchConfig(options?.config);

View File

@@ -1,6 +1,6 @@
import { Type } from "@sinclair/typebox";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import { formatCliCommand } from "../../cli/command-format.js";
import type { AnyAgentTool } from "./common.js";
import { jsonResult, readNumberParam, readStringParam } from "./common.js";
@@ -65,7 +65,7 @@ const WebSearchSchema = Type.Object({
),
});
type WebSearchConfig = NonNullable<MoltbotConfig["tools"]>["web"] extends infer Web
type WebSearchConfig = NonNullable<OpenClawConfig["tools"]>["web"] extends infer Web
? Web extends { search?: infer Search }
? Search
: undefined
@@ -103,7 +103,7 @@ type PerplexitySearchResponse = {
type PerplexityBaseUrlHint = "direct" | "openrouter";
function resolveSearchConfig(cfg?: MoltbotConfig): WebSearchConfig {
function resolveSearchConfig(cfg?: OpenClawConfig): WebSearchConfig {
const search = cfg?.tools?.web?.search;
if (!search || typeof search !== "object") return undefined;
return search as WebSearchConfig;
@@ -128,13 +128,13 @@ function missingSearchKeyPayload(provider: (typeof SEARCH_PROVIDERS)[number]) {
error: "missing_perplexity_api_key",
message:
"web_search (perplexity) needs an API key. Set PERPLEXITY_API_KEY or OPENROUTER_API_KEY in the Gateway environment, or configure tools.web.search.perplexity.apiKey.",
docs: "https://docs.molt.bot/tools/web",
docs: "https://docs.openclaw.ai/tools/web",
};
}
return {
error: "missing_brave_api_key",
message: `web_search needs a Brave Search API key. Run \`${formatCliCommand("moltbot configure --section web")}\` to store it, or set BRAVE_API_KEY in the Gateway environment.`,
docs: "https://docs.molt.bot/tools/web",
message: `web_search needs a Brave Search API key. Run \`${formatCliCommand("openclaw configure --section web")}\` to store it, or set BRAVE_API_KEY in the Gateway environment.`,
docs: "https://docs.openclaw.ai/tools/web",
};
}
@@ -279,8 +279,8 @@ async function runPerplexitySearch(params: {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${params.apiKey}`,
"HTTP-Referer": "https://molt.bot",
"X-Title": "Moltbot Web Search",
"HTTP-Referer": "https://openclaw.ai",
"X-Title": "OpenClaw Web Search",
},
body: JSON.stringify({
model: params.model,
@@ -407,7 +407,7 @@ async function runWebSearch(params: {
}
export function createWebSearchTool(options?: {
config?: MoltbotConfig;
config?: OpenClawConfig;
sandboxed?: boolean;
}): AnyAgentTool | null {
const search = resolveSearchConfig(options?.config);
@@ -447,7 +447,7 @@ export function createWebSearchTool(options?: {
return jsonResult({
error: "unsupported_freshness",
message: "freshness is only supported by the Brave web_search provider.",
docs: "https://docs.molt.bot/tools/web",
docs: "https://docs.openclaw.ai/tools/web",
});
}
const freshness = rawFreshness ? normalizeFreshness(rawFreshness) : undefined;
@@ -456,7 +456,7 @@ export function createWebSearchTool(options?: {
error: "invalid_freshness",
message:
"freshness must be one of pd, pw, pm, py, or a range like YYYY-MM-DDtoYYYY-MM-DD.",
docs: "https://docs.molt.bot/tools/web",
docs: "https://docs.openclaw.ai/tools/web",
});
}
const result = await runWebSearch({

View File

@@ -1,6 +1,6 @@
import { describe, expect, it, vi } from "vitest";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import { handleWhatsAppAction } from "./whatsapp-actions.js";
const sendReactionWhatsApp = vi.fn(async () => undefined);
@@ -13,7 +13,7 @@ vi.mock("../../web/outbound.js", () => ({
const enabledConfig = {
channels: { whatsapp: { actions: { reactions: true } } },
} as MoltbotConfig;
} as OpenClawConfig;
describe("handleWhatsAppAction", () => {
it("adds reactions", async () => {
@@ -95,7 +95,7 @@ describe("handleWhatsAppAction", () => {
it("respects reaction gating", async () => {
const cfg = {
channels: { whatsapp: { actions: { reactions: false } } },
} as MoltbotConfig;
} as OpenClawConfig;
await expect(
handleWhatsAppAction(
{

View File

@@ -1,12 +1,12 @@
import type { AgentToolResult } from "@mariozechner/pi-agent-core";
import type { MoltbotConfig } from "../../config/config.js";
import type { OpenClawConfig } from "../../config/config.js";
import { sendReactionWhatsApp } from "../../web/outbound.js";
import { createActionGate, jsonResult, readReactionParams, readStringParam } from "./common.js";
export async function handleWhatsAppAction(
params: Record<string, unknown>,
cfg: MoltbotConfig,
cfg: OpenClawConfig,
): Promise<AgentToolResult<unknown>> {
const action = readStringParam(params, "action", { required: true });
const isActionEnabled = createActionGate(cfg.channels?.whatsapp?.actions);