mirror of
https://github.com/farcasclaudiu/openclaw.git
synced 2026-06-29 01:02:03 +03:00
refactor: rename clawdbot to moltbot with legacy compat
This commit is contained in:
@@ -3,7 +3,7 @@ import path from "node:path";
|
||||
import { DEFAULT_AGENT_ID, normalizeAgentId } from "../routing/session-key.js";
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import { resolveStateDir } from "./paths.js";
|
||||
import type { ClawdbotConfig } from "./types.js";
|
||||
import type { MoltbotConfig } from "./types.js";
|
||||
|
||||
export type DuplicateAgentDir = {
|
||||
agentDir: string;
|
||||
@@ -28,7 +28,7 @@ function canonicalizeAgentDir(agentDir: string): string {
|
||||
return resolved;
|
||||
}
|
||||
|
||||
function collectReferencedAgentIds(cfg: ClawdbotConfig): string[] {
|
||||
function collectReferencedAgentIds(cfg: MoltbotConfig): string[] {
|
||||
const ids = new Set<string>();
|
||||
|
||||
const agents = Array.isArray(cfg.agents?.list) ? cfg.agents?.list : [];
|
||||
@@ -54,7 +54,7 @@ function collectReferencedAgentIds(cfg: ClawdbotConfig): string[] {
|
||||
}
|
||||
|
||||
function resolveEffectiveAgentDir(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
agentId: string,
|
||||
deps?: { env?: NodeJS.ProcessEnv; homedir?: () => string },
|
||||
): string {
|
||||
@@ -69,7 +69,7 @@ function resolveEffectiveAgentDir(
|
||||
}
|
||||
|
||||
export function findDuplicateAgentDirs(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
deps?: { env?: NodeJS.ProcessEnv; homedir?: () => string },
|
||||
): DuplicateAgentDir[] {
|
||||
const byDir = new Map<string, { agentDir: string; agentIds: string[] }>();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import type { ClawdbotConfig } from "./types.js";
|
||||
import type { MoltbotConfig } from "./types.js";
|
||||
|
||||
export const DEFAULT_AGENT_MAX_CONCURRENT = 4;
|
||||
export const DEFAULT_SUBAGENT_MAX_CONCURRENT = 8;
|
||||
|
||||
export function resolveAgentMaxConcurrent(cfg?: ClawdbotConfig): number {
|
||||
export function resolveAgentMaxConcurrent(cfg?: MoltbotConfig): number {
|
||||
const raw = cfg?.agents?.defaults?.maxConcurrent;
|
||||
if (typeof raw === "number" && Number.isFinite(raw)) {
|
||||
return Math.max(1, Math.floor(raw));
|
||||
@@ -11,7 +11,7 @@ export function resolveAgentMaxConcurrent(cfg?: ClawdbotConfig): number {
|
||||
return DEFAULT_AGENT_MAX_CONCURRENT;
|
||||
}
|
||||
|
||||
export function resolveSubagentMaxConcurrent(cfg?: ClawdbotConfig): number {
|
||||
export function resolveSubagentMaxConcurrent(cfg?: MoltbotConfig): number {
|
||||
const raw = cfg?.agents?.defaults?.subagents?.maxConcurrent;
|
||||
if (typeof raw === "number" && Number.isFinite(raw)) {
|
||||
return Math.max(1, Math.floor(raw));
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { ChannelPlugin } from "../channels/plugins/types.js";
|
||||
import type { PluginRegistry } from "../plugins/registry.js";
|
||||
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
||||
import { resolveChannelCapabilities } from "./channel-capabilities.js";
|
||||
import type { ClawdbotConfig } from "./config.js";
|
||||
import type { MoltbotConfig } from "./config.js";
|
||||
|
||||
describe("resolveChannelCapabilities", () => {
|
||||
beforeEach(() => {
|
||||
@@ -32,7 +32,7 @@ describe("resolveChannelCapabilities", () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies Partial<ClawdbotConfig>;
|
||||
} satisfies Partial<MoltbotConfig>;
|
||||
|
||||
expect(
|
||||
resolveChannelCapabilities({
|
||||
@@ -53,7 +53,7 @@ describe("resolveChannelCapabilities", () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies Partial<ClawdbotConfig>;
|
||||
} satisfies Partial<MoltbotConfig>;
|
||||
|
||||
expect(
|
||||
resolveChannelCapabilities({
|
||||
@@ -73,7 +73,7 @@ describe("resolveChannelCapabilities", () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies Partial<ClawdbotConfig>;
|
||||
} satisfies Partial<MoltbotConfig>;
|
||||
|
||||
expect(
|
||||
resolveChannelCapabilities({
|
||||
@@ -96,7 +96,7 @@ describe("resolveChannelCapabilities", () => {
|
||||
);
|
||||
const cfg = {
|
||||
channels: { msteams: { capabilities: [" polls ", ""] } },
|
||||
} satisfies Partial<ClawdbotConfig>;
|
||||
} satisfies Partial<MoltbotConfig>;
|
||||
|
||||
expect(
|
||||
resolveChannelCapabilities({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { normalizeChannelId } from "../channels/plugins/index.js";
|
||||
import { normalizeAccountId } from "../routing/session-key.js";
|
||||
import type { ClawdbotConfig } from "./config.js";
|
||||
import type { MoltbotConfig } from "./config.js";
|
||||
import type { TelegramCapabilitiesConfig } from "./types.telegram.js";
|
||||
|
||||
type CapabilitiesConfig = TelegramCapabilitiesConfig;
|
||||
@@ -45,7 +45,7 @@ function resolveAccountCapabilities(params: {
|
||||
}
|
||||
|
||||
export function resolveChannelCapabilities(params: {
|
||||
cfg?: Partial<ClawdbotConfig>;
|
||||
cfg?: Partial<MoltbotConfig>;
|
||||
channel?: string | null;
|
||||
accountId?: string | null;
|
||||
}): string[] | undefined {
|
||||
|
||||
@@ -46,7 +46,7 @@ describe("agent concurrency defaults", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify({}, null, 2),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
@@ -3,17 +3,17 @@ import fs from "node:fs/promises";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { withTempHome } from "./test-helpers.js";
|
||||
import type { ClawdbotConfig } from "./types.js";
|
||||
import type { MoltbotConfig } from "./types.js";
|
||||
|
||||
describe("config backup rotation", () => {
|
||||
it("keeps a 5-deep backup ring for config writes", async () => {
|
||||
await withTempHome(async () => {
|
||||
const { resolveConfigPath, writeConfigFile } = await import("./config.js");
|
||||
const configPath = resolveConfigPath();
|
||||
const buildConfig = (version: number): ClawdbotConfig =>
|
||||
const buildConfig = (version: number): MoltbotConfig =>
|
||||
({
|
||||
agents: { list: [{ id: `v${version}` }] },
|
||||
}) as ClawdbotConfig;
|
||||
}) as MoltbotConfig;
|
||||
|
||||
for (let version = 0; version <= 6; version += 1) {
|
||||
await writeConfigFile(buildConfig(version));
|
||||
|
||||
@@ -9,7 +9,7 @@ describe("config compaction settings", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
agents: {
|
||||
@@ -51,7 +51,7 @@ describe("config compaction settings", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
agents: {
|
||||
|
||||
@@ -19,7 +19,7 @@ describe("config discord", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
channels: {
|
||||
|
||||
@@ -9,7 +9,7 @@ describe("config env vars", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
env: { vars: { OPENROUTER_API_KEY: "config-key" } },
|
||||
@@ -33,7 +33,7 @@ describe("config env vars", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
env: { vars: { OPENROUTER_API_KEY: "config-key" } },
|
||||
@@ -57,7 +57,7 @@ describe("config env vars", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
env: { vars: { GROQ_API_KEY: "gsk-config" } },
|
||||
|
||||
@@ -20,7 +20,7 @@ describe("config identity defaults", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
agents: {
|
||||
@@ -57,7 +57,7 @@ describe("config identity defaults", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
agents: {
|
||||
@@ -94,7 +94,7 @@ describe("config identity defaults", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
messages: {},
|
||||
@@ -119,7 +119,7 @@ describe("config identity defaults", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
agents: {
|
||||
@@ -159,11 +159,11 @@ describe("config identity defaults", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
messages: {
|
||||
messagePrefix: "[clawdbot]",
|
||||
messagePrefix: "[moltbot]",
|
||||
responsePrefix: "🦞",
|
||||
},
|
||||
channels: {
|
||||
@@ -205,7 +205,7 @@ describe("config identity defaults", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
models: {
|
||||
@@ -254,7 +254,7 @@ describe("config identity defaults", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
agents: {
|
||||
@@ -290,7 +290,7 @@ describe("config identity defaults", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
messages: {},
|
||||
@@ -319,7 +319,7 @@ describe("config identity defaults", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
agents: {
|
||||
|
||||
@@ -176,7 +176,7 @@ describe("legacy config detection", () => {
|
||||
});
|
||||
it("flags legacy config in snapshot", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const configPath = path.join(home, ".clawdbot", "clawdbot.json");
|
||||
const configPath = path.join(home, ".clawdbot", "moltbot.json");
|
||||
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
||||
await fs.writeFile(
|
||||
configPath,
|
||||
@@ -202,7 +202,7 @@ describe("legacy config detection", () => {
|
||||
});
|
||||
it("does not auto-migrate claude-cli auth profile mode on load", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const configPath = path.join(home, ".clawdbot", "clawdbot.json");
|
||||
const configPath = path.join(home, ".clawdbot", "moltbot.json");
|
||||
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
||||
await fs.writeFile(
|
||||
configPath,
|
||||
@@ -234,7 +234,7 @@ describe("legacy config detection", () => {
|
||||
});
|
||||
it("flags legacy provider sections in snapshot", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const configPath = path.join(home, ".clawdbot", "clawdbot.json");
|
||||
const configPath = path.join(home, ".clawdbot", "moltbot.json");
|
||||
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
||||
await fs.writeFile(
|
||||
configPath,
|
||||
@@ -260,7 +260,7 @@ describe("legacy config detection", () => {
|
||||
});
|
||||
it("flags routing.allowFrom in snapshot", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const configPath = path.join(home, ".clawdbot", "clawdbot.json");
|
||||
const configPath = path.join(home, ".clawdbot", "moltbot.json");
|
||||
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
||||
await fs.writeFile(
|
||||
configPath,
|
||||
@@ -286,7 +286,7 @@ describe("legacy config detection", () => {
|
||||
});
|
||||
it("rejects bindings[].match.provider on load", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const configPath = path.join(home, ".clawdbot", "clawdbot.json");
|
||||
const configPath = path.join(home, ".clawdbot", "moltbot.json");
|
||||
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
||||
await fs.writeFile(
|
||||
configPath,
|
||||
@@ -316,7 +316,7 @@ describe("legacy config detection", () => {
|
||||
});
|
||||
it("rejects bindings[].match.accountID on load", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const configPath = path.join(home, ".clawdbot", "clawdbot.json");
|
||||
const configPath = path.join(home, ".clawdbot", "moltbot.json");
|
||||
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
||||
await fs.writeFile(
|
||||
configPath,
|
||||
@@ -346,7 +346,7 @@ describe("legacy config detection", () => {
|
||||
});
|
||||
it("rejects session.sendPolicy.rules[].match.provider on load", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const configPath = path.join(home, ".clawdbot", "clawdbot.json");
|
||||
const configPath = path.join(home, ".clawdbot", "moltbot.json");
|
||||
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
||||
await fs.writeFile(
|
||||
configPath,
|
||||
@@ -380,7 +380,7 @@ describe("legacy config detection", () => {
|
||||
});
|
||||
it("rejects messages.queue.byProvider on load", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const configPath = path.join(home, ".clawdbot", "clawdbot.json");
|
||||
const configPath = path.join(home, ".clawdbot", "moltbot.json");
|
||||
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
||||
await fs.writeFile(
|
||||
configPath,
|
||||
|
||||
@@ -8,7 +8,7 @@ describe("multi-agent agentDir validation", () => {
|
||||
it("rejects shared agents.list agentDir", async () => {
|
||||
vi.resetModules();
|
||||
const { validateConfigObject } = await import("./config.js");
|
||||
const shared = path.join(tmpdir(), "clawdbot-shared-agentdir");
|
||||
const shared = path.join(tmpdir(), "moltbot-shared-agentdir");
|
||||
const res = validateConfigObject({
|
||||
agents: {
|
||||
list: [
|
||||
@@ -29,7 +29,7 @@ describe("multi-agent agentDir validation", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
agents: {
|
||||
|
||||
@@ -35,57 +35,55 @@ describe("Nix integration (U3, U5, U9)", () => {
|
||||
});
|
||||
|
||||
describe("U5: CONFIG_PATH and STATE_DIR env var overrides", () => {
|
||||
it("STATE_DIR_CLAWDBOT defaults to ~/.clawdbot when env not set", async () => {
|
||||
it("STATE_DIR defaults to ~/.clawdbot when env not set", async () => {
|
||||
await withEnvOverride({ CLAWDBOT_STATE_DIR: undefined }, async () => {
|
||||
const { STATE_DIR_CLAWDBOT } = await import("./config.js");
|
||||
expect(STATE_DIR_CLAWDBOT).toMatch(/\.clawdbot$/);
|
||||
const { STATE_DIR } = await import("./config.js");
|
||||
expect(STATE_DIR).toMatch(/\.clawdbot$/);
|
||||
});
|
||||
});
|
||||
|
||||
it("STATE_DIR_CLAWDBOT respects CLAWDBOT_STATE_DIR override", async () => {
|
||||
it("STATE_DIR respects CLAWDBOT_STATE_DIR override", async () => {
|
||||
await withEnvOverride({ CLAWDBOT_STATE_DIR: "/custom/state/dir" }, async () => {
|
||||
const { STATE_DIR_CLAWDBOT } = await import("./config.js");
|
||||
expect(STATE_DIR_CLAWDBOT).toBe(path.resolve("/custom/state/dir"));
|
||||
const { STATE_DIR } = await import("./config.js");
|
||||
expect(STATE_DIR).toBe(path.resolve("/custom/state/dir"));
|
||||
});
|
||||
});
|
||||
|
||||
it("CONFIG_PATH_CLAWDBOT defaults to ~/.clawdbot/clawdbot.json when env not set", async () => {
|
||||
it("CONFIG_PATH defaults to ~/.clawdbot/moltbot.json when env not set", async () => {
|
||||
await withEnvOverride(
|
||||
{ CLAWDBOT_CONFIG_PATH: undefined, CLAWDBOT_STATE_DIR: undefined },
|
||||
async () => {
|
||||
const { CONFIG_PATH_CLAWDBOT } = await import("./config.js");
|
||||
expect(CONFIG_PATH_CLAWDBOT).toMatch(/\.clawdbot[\\/]clawdbot\.json$/);
|
||||
const { CONFIG_PATH } = await import("./config.js");
|
||||
expect(CONFIG_PATH).toMatch(/\.clawdbot[\\/]moltbot\.json$/);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("CONFIG_PATH_CLAWDBOT respects CLAWDBOT_CONFIG_PATH override", async () => {
|
||||
await withEnvOverride({ CLAWDBOT_CONFIG_PATH: "/nix/store/abc/clawdbot.json" }, async () => {
|
||||
const { CONFIG_PATH_CLAWDBOT } = await import("./config.js");
|
||||
expect(CONFIG_PATH_CLAWDBOT).toBe(path.resolve("/nix/store/abc/clawdbot.json"));
|
||||
it("CONFIG_PATH respects CLAWDBOT_CONFIG_PATH override", async () => {
|
||||
await withEnvOverride({ CLAWDBOT_CONFIG_PATH: "/nix/store/abc/moltbot.json" }, async () => {
|
||||
const { CONFIG_PATH } = await import("./config.js");
|
||||
expect(CONFIG_PATH).toBe(path.resolve("/nix/store/abc/moltbot.json"));
|
||||
});
|
||||
});
|
||||
|
||||
it("CONFIG_PATH_CLAWDBOT expands ~ in CLAWDBOT_CONFIG_PATH override", async () => {
|
||||
it("CONFIG_PATH expands ~ in CLAWDBOT_CONFIG_PATH override", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
await withEnvOverride({ CLAWDBOT_CONFIG_PATH: "~/.clawdbot/custom.json" }, async () => {
|
||||
const { CONFIG_PATH_CLAWDBOT } = await import("./config.js");
|
||||
expect(CONFIG_PATH_CLAWDBOT).toBe(path.join(home, ".clawdbot", "custom.json"));
|
||||
const { CONFIG_PATH } = await import("./config.js");
|
||||
expect(CONFIG_PATH).toBe(path.join(home, ".clawdbot", "custom.json"));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("CONFIG_PATH_CLAWDBOT uses STATE_DIR_CLAWDBOT when only state dir is overridden", async () => {
|
||||
it("CONFIG_PATH uses STATE_DIR when only state dir is overridden", async () => {
|
||||
await withEnvOverride(
|
||||
{
|
||||
CLAWDBOT_CONFIG_PATH: undefined,
|
||||
CLAWDBOT_STATE_DIR: "/custom/state",
|
||||
},
|
||||
async () => {
|
||||
const { CONFIG_PATH_CLAWDBOT } = await import("./config.js");
|
||||
expect(CONFIG_PATH_CLAWDBOT).toBe(
|
||||
path.join(path.resolve("/custom/state"), "clawdbot.json"),
|
||||
);
|
||||
const { CONFIG_PATH } = await import("./config.js");
|
||||
expect(CONFIG_PATH).toBe(path.join(path.resolve("/custom/state"), "moltbot.json"));
|
||||
},
|
||||
);
|
||||
});
|
||||
@@ -104,7 +102,7 @@ describe("Nix integration (U3, U5, U9)", () => {
|
||||
"utf-8",
|
||||
);
|
||||
await fs.writeFile(
|
||||
path.join(pluginDir, "clawdbot.plugin.json"),
|
||||
path.join(pluginDir, "moltbot.plugin.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
id: "demo-plugin",
|
||||
@@ -116,7 +114,7 @@ describe("Nix integration (U3, U5, U9)", () => {
|
||||
"utf-8",
|
||||
);
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
plugins: {
|
||||
@@ -198,7 +196,7 @@ describe("Nix integration (U3, U5, U9)", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify({
|
||||
channels: { telegram: { botToken: "123:ABC" } },
|
||||
}),
|
||||
@@ -218,7 +216,7 @@ describe("Nix integration (U3, U5, U9)", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify({
|
||||
channels: { telegram: { tokenFile: "/run/agenix/telegram-token" } },
|
||||
}),
|
||||
@@ -238,7 +236,7 @@ describe("Nix integration (U3, U5, U9)", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify({
|
||||
channels: {
|
||||
telegram: {
|
||||
|
||||
@@ -25,7 +25,7 @@ async function writePluginFixture(params: {
|
||||
manifest.channels = params.channels;
|
||||
}
|
||||
await fs.writeFile(
|
||||
path.join(params.dir, "clawdbot.plugin.json"),
|
||||
path.join(params.dir, "moltbot.plugin.json"),
|
||||
JSON.stringify(manifest, null, 2),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
@@ -19,7 +19,7 @@ describe("config strict validation", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify({
|
||||
agents: { list: [{ id: "pi" }] },
|
||||
routing: { allowFrom: ["+15555550123"] },
|
||||
|
||||
@@ -13,7 +13,7 @@ describe("config pruning defaults", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify({ agents: { defaults: {} } }, null, 2),
|
||||
"utf-8",
|
||||
);
|
||||
@@ -41,7 +41,7 @@ describe("config pruning defaults", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
auth: {
|
||||
@@ -72,7 +72,7 @@ describe("config pruning defaults", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
auth: {
|
||||
@@ -110,7 +110,7 @@ describe("config pruning defaults", () => {
|
||||
const configDir = path.join(home, ".clawdbot");
|
||||
await fs.mkdir(configDir, { recursive: true });
|
||||
await fs.writeFile(
|
||||
path.join(configDir, "clawdbot.json"),
|
||||
path.join(configDir, "moltbot.json"),
|
||||
JSON.stringify({ agents: { defaults: { contextPruning: { mode: "off" } } } }, null, 2),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { ClawdbotSchema } from "./zod-schema.js";
|
||||
import { MoltbotSchema } from "./zod-schema.js";
|
||||
|
||||
describe("skills entries config schema", () => {
|
||||
it("accepts custom fields under config", () => {
|
||||
const res = ClawdbotSchema.safeParse({
|
||||
const res = MoltbotSchema.safeParse({
|
||||
skills: {
|
||||
entries: {
|
||||
"custom-skill": {
|
||||
@@ -22,7 +22,7 @@ describe("skills entries config schema", () => {
|
||||
});
|
||||
|
||||
it("rejects unknown top-level fields", () => {
|
||||
const res = ClawdbotSchema.safeParse({
|
||||
const res = MoltbotSchema.safeParse({
|
||||
skills: {
|
||||
entries: {
|
||||
"custom-skill": {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { ClawdbotSchema } from "./zod-schema.js";
|
||||
import { MoltbotSchema } from "./zod-schema.js";
|
||||
|
||||
describe("telegram custom commands schema", () => {
|
||||
it("normalizes custom commands", () => {
|
||||
const res = ClawdbotSchema.safeParse({
|
||||
const res = MoltbotSchema.safeParse({
|
||||
channels: {
|
||||
telegram: {
|
||||
customCommands: [{ command: "/Backup", description: " Git backup " }],
|
||||
@@ -21,7 +21,7 @@ describe("telegram custom commands schema", () => {
|
||||
});
|
||||
|
||||
it("rejects custom commands with invalid names", () => {
|
||||
const res = ClawdbotSchema.safeParse({
|
||||
const res = MoltbotSchema.safeParse({
|
||||
channels: {
|
||||
telegram: {
|
||||
customCommands: [{ command: "Bad-Name", description: "Override status" }],
|
||||
|
||||
@@ -11,4 +11,4 @@ export * from "./paths.js";
|
||||
export * from "./runtime-overrides.js";
|
||||
export * from "./types.js";
|
||||
export { validateConfigObject, validateConfigObjectWithPlugins } from "./validation.js";
|
||||
export { ClawdbotSchema } from "./zod-schema.js";
|
||||
export { MoltbotSchema } from "./zod-schema.js";
|
||||
|
||||
+12
-12
@@ -1,7 +1,7 @@
|
||||
import { DEFAULT_CONTEXT_TOKENS } from "../agents/defaults.js";
|
||||
import { parseModelRef } from "../agents/model-selection.js";
|
||||
import { resolveTalkApiKey } from "./talk.js";
|
||||
import type { ClawdbotConfig } from "./types.js";
|
||||
import type { MoltbotConfig } from "./types.js";
|
||||
import { DEFAULT_AGENT_MAX_CONCURRENT, DEFAULT_SUBAGENT_MAX_CONCURRENT } from "./agent-limits.js";
|
||||
import type { ModelDefinitionConfig } from "./types.models.js";
|
||||
|
||||
@@ -53,7 +53,7 @@ function resolveModelCost(
|
||||
};
|
||||
}
|
||||
|
||||
function resolveAnthropicDefaultAuthMode(cfg: ClawdbotConfig): AnthropicAuthDefaultsMode | null {
|
||||
function resolveAnthropicDefaultAuthMode(cfg: MoltbotConfig): AnthropicAuthDefaultsMode | null {
|
||||
const profiles = cfg.auth?.profiles ?? {};
|
||||
const anthropicProfiles = Object.entries(profiles).filter(
|
||||
([, profile]) => profile?.provider === "anthropic",
|
||||
@@ -92,7 +92,7 @@ export type SessionDefaultsOptions = {
|
||||
warnState?: WarnState;
|
||||
};
|
||||
|
||||
export function applyMessageDefaults(cfg: ClawdbotConfig): ClawdbotConfig {
|
||||
export function applyMessageDefaults(cfg: MoltbotConfig): MoltbotConfig {
|
||||
const messages = cfg.messages;
|
||||
const hasAckScope = messages?.ackReactionScope !== undefined;
|
||||
if (hasAckScope) return cfg;
|
||||
@@ -106,9 +106,9 @@ export function applyMessageDefaults(cfg: ClawdbotConfig): ClawdbotConfig {
|
||||
}
|
||||
|
||||
export function applySessionDefaults(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
options: SessionDefaultsOptions = {},
|
||||
): ClawdbotConfig {
|
||||
): MoltbotConfig {
|
||||
const session = cfg.session;
|
||||
if (!session || session.mainKey === undefined) return cfg;
|
||||
|
||||
@@ -116,7 +116,7 @@ export function applySessionDefaults(
|
||||
const warn = options.warn ?? console.warn;
|
||||
const warnState = options.warnState ?? defaultWarnState;
|
||||
|
||||
const next: ClawdbotConfig = {
|
||||
const next: MoltbotConfig = {
|
||||
...cfg,
|
||||
session: { ...session, mainKey: "main" },
|
||||
};
|
||||
@@ -129,7 +129,7 @@ export function applySessionDefaults(
|
||||
return next;
|
||||
}
|
||||
|
||||
export function applyTalkApiKey(config: ClawdbotConfig): ClawdbotConfig {
|
||||
export function applyTalkApiKey(config: MoltbotConfig): MoltbotConfig {
|
||||
const resolved = resolveTalkApiKey();
|
||||
if (!resolved) return config;
|
||||
const existing = config.talk?.apiKey?.trim();
|
||||
@@ -143,7 +143,7 @@ export function applyTalkApiKey(config: ClawdbotConfig): ClawdbotConfig {
|
||||
};
|
||||
}
|
||||
|
||||
export function applyModelDefaults(cfg: ClawdbotConfig): ClawdbotConfig {
|
||||
export function applyModelDefaults(cfg: MoltbotConfig): MoltbotConfig {
|
||||
let mutated = false;
|
||||
let nextCfg = cfg;
|
||||
|
||||
@@ -238,7 +238,7 @@ export function applyModelDefaults(cfg: ClawdbotConfig): ClawdbotConfig {
|
||||
};
|
||||
}
|
||||
|
||||
export function applyAgentDefaults(cfg: ClawdbotConfig): ClawdbotConfig {
|
||||
export function applyAgentDefaults(cfg: MoltbotConfig): MoltbotConfig {
|
||||
const agents = cfg.agents;
|
||||
const defaults = agents?.defaults;
|
||||
const hasMax =
|
||||
@@ -275,7 +275,7 @@ export function applyAgentDefaults(cfg: ClawdbotConfig): ClawdbotConfig {
|
||||
};
|
||||
}
|
||||
|
||||
export function applyLoggingDefaults(cfg: ClawdbotConfig): ClawdbotConfig {
|
||||
export function applyLoggingDefaults(cfg: MoltbotConfig): MoltbotConfig {
|
||||
const logging = cfg.logging;
|
||||
if (!logging) return cfg;
|
||||
if (logging.redactSensitive) return cfg;
|
||||
@@ -288,7 +288,7 @@ export function applyLoggingDefaults(cfg: ClawdbotConfig): ClawdbotConfig {
|
||||
};
|
||||
}
|
||||
|
||||
export function applyContextPruningDefaults(cfg: ClawdbotConfig): ClawdbotConfig {
|
||||
export function applyContextPruningDefaults(cfg: MoltbotConfig): MoltbotConfig {
|
||||
const defaults = cfg.agents?.defaults;
|
||||
if (!defaults) return cfg;
|
||||
|
||||
@@ -369,7 +369,7 @@ export function applyContextPruningDefaults(cfg: ClawdbotConfig): ClawdbotConfig
|
||||
};
|
||||
}
|
||||
|
||||
export function applyCompactionDefaults(cfg: ClawdbotConfig): ClawdbotConfig {
|
||||
export function applyCompactionDefaults(cfg: MoltbotConfig): MoltbotConfig {
|
||||
const defaults = cfg.agents?.defaults;
|
||||
if (!defaults) return cfg;
|
||||
const compaction = defaults?.compaction;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { ClawdbotConfig } from "./types.js";
|
||||
import type { MoltbotConfig } from "./types.js";
|
||||
|
||||
export function collectConfigEnvVars(cfg?: ClawdbotConfig): Record<string, string> {
|
||||
export function collectConfigEnvVars(cfg?: MoltbotConfig): Record<string, string> {
|
||||
const envConfig = cfg?.env;
|
||||
if (!envConfig) return {};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { ChannelId } from "../channels/plugins/types.js";
|
||||
import { normalizeAccountId } from "../routing/session-key.js";
|
||||
import type { ClawdbotConfig } from "./config.js";
|
||||
import type { MoltbotConfig } from "./config.js";
|
||||
import type { GroupToolPolicyBySenderConfig, GroupToolPolicyConfig } from "./types.tools.js";
|
||||
|
||||
export type GroupPolicyChannel = ChannelId;
|
||||
@@ -80,7 +80,7 @@ export function resolveToolsBySender(
|
||||
}
|
||||
|
||||
function resolveChannelGroups(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
channel: GroupPolicyChannel,
|
||||
accountId?: string | null,
|
||||
): ChannelGroups | undefined {
|
||||
@@ -103,7 +103,7 @@ function resolveChannelGroups(
|
||||
}
|
||||
|
||||
export function resolveChannelGroupPolicy(params: {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
channel: GroupPolicyChannel;
|
||||
groupId?: string | null;
|
||||
accountId?: string | null;
|
||||
@@ -128,7 +128,7 @@ export function resolveChannelGroupPolicy(params: {
|
||||
}
|
||||
|
||||
export function resolveChannelGroupRequireMention(params: {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
channel: GroupPolicyChannel;
|
||||
groupId?: string | null;
|
||||
accountId?: string | null;
|
||||
@@ -156,7 +156,7 @@ export function resolveChannelGroupRequireMention(params: {
|
||||
|
||||
export function resolveChannelGroupToolsPolicy(
|
||||
params: {
|
||||
cfg: ClawdbotConfig;
|
||||
cfg: MoltbotConfig;
|
||||
channel: GroupPolicyChannel;
|
||||
groupId?: string | null;
|
||||
accountId?: string | null;
|
||||
|
||||
@@ -11,16 +11,16 @@ import {
|
||||
|
||||
const ROOT_DIR = path.parse(process.cwd()).root;
|
||||
const CONFIG_DIR = path.join(ROOT_DIR, "config");
|
||||
const ETC_CLAWDBOT_DIR = path.join(ROOT_DIR, "etc", "clawdbot");
|
||||
const ETC_CLAWDBOT_DIR = path.join(ROOT_DIR, "etc", "moltbot");
|
||||
const SHARED_DIR = path.join(ROOT_DIR, "shared");
|
||||
|
||||
const DEFAULT_BASE_PATH = path.join(CONFIG_DIR, "clawdbot.json");
|
||||
const DEFAULT_BASE_PATH = path.join(CONFIG_DIR, "moltbot.json");
|
||||
|
||||
function configPath(...parts: string[]) {
|
||||
return path.join(CONFIG_DIR, ...parts);
|
||||
}
|
||||
|
||||
function etcClawdbotPath(...parts: string[]) {
|
||||
function etcMoltbotPath(...parts: string[]) {
|
||||
return path.join(ETC_CLAWDBOT_DIR, ...parts);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ describe("resolveConfigIncludes", () => {
|
||||
});
|
||||
|
||||
it("resolves absolute path $include", () => {
|
||||
const absolute = etcClawdbotPath("agents.json");
|
||||
const absolute = etcMoltbotPath("agents.json");
|
||||
const files = { [absolute]: { list: [{ id: "main" }] } };
|
||||
const obj = { agents: { $include: absolute } };
|
||||
expect(resolve(obj, files)).toEqual({
|
||||
@@ -283,7 +283,7 @@ describe("resolveConfigIncludes", () => {
|
||||
it("resolves parent directory references", () => {
|
||||
const files = { [sharedPath("common.json")]: { shared: true } };
|
||||
const obj = { $include: "../../shared/common.json" };
|
||||
expect(resolve(obj, files, configPath("sub", "clawdbot.json"))).toEqual({
|
||||
expect(resolve(obj, files, configPath("sub", "moltbot.json"))).toEqual({
|
||||
shared: true,
|
||||
});
|
||||
});
|
||||
|
||||
+17
-17
@@ -30,9 +30,9 @@ import { findLegacyConfigIssues } from "./legacy.js";
|
||||
import { normalizeConfigPaths } from "./normalize-paths.js";
|
||||
import { resolveConfigPath, resolveStateDir } from "./paths.js";
|
||||
import { applyConfigOverrides } from "./runtime-overrides.js";
|
||||
import type { ClawdbotConfig, ConfigFileSnapshot, LegacyConfigIssue } from "./types.js";
|
||||
import type { MoltbotConfig, ConfigFileSnapshot, LegacyConfigIssue } from "./types.js";
|
||||
import { validateConfigObjectWithPlugins } from "./validation.js";
|
||||
import { compareClawdbotVersions } from "./version.js";
|
||||
import { compareMoltbotVersions } from "./version.js";
|
||||
|
||||
// Re-export for backwards compatibility
|
||||
export { CircularIncludeError, ConfigIncludeError } from "./includes.js";
|
||||
@@ -81,11 +81,11 @@ export function resolveConfigSnapshotHash(snapshot: {
|
||||
return hashConfigRaw(snapshot.raw);
|
||||
}
|
||||
|
||||
function coerceConfig(value: unknown): ClawdbotConfig {
|
||||
function coerceConfig(value: unknown): MoltbotConfig {
|
||||
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
||||
return {};
|
||||
}
|
||||
return value as ClawdbotConfig;
|
||||
return value as MoltbotConfig;
|
||||
}
|
||||
|
||||
async function rotateConfigBackups(configPath: string, ioFs: typeof fs.promises): Promise<void> {
|
||||
@@ -125,7 +125,7 @@ function warnOnConfigMiskeys(raw: unknown, logger: Pick<typeof console, "warn">)
|
||||
}
|
||||
}
|
||||
|
||||
function stampConfigVersion(cfg: ClawdbotConfig): ClawdbotConfig {
|
||||
function stampConfigVersion(cfg: MoltbotConfig): MoltbotConfig {
|
||||
const now = new Date().toISOString();
|
||||
return {
|
||||
...cfg,
|
||||
@@ -137,19 +137,19 @@ function stampConfigVersion(cfg: ClawdbotConfig): ClawdbotConfig {
|
||||
};
|
||||
}
|
||||
|
||||
function warnIfConfigFromFuture(cfg: ClawdbotConfig, logger: Pick<typeof console, "warn">): void {
|
||||
function warnIfConfigFromFuture(cfg: MoltbotConfig, logger: Pick<typeof console, "warn">): void {
|
||||
const touched = cfg.meta?.lastTouchedVersion;
|
||||
if (!touched) return;
|
||||
const cmp = compareClawdbotVersions(VERSION, touched);
|
||||
const cmp = compareMoltbotVersions(VERSION, touched);
|
||||
if (cmp === null) return;
|
||||
if (cmp < 0) {
|
||||
logger.warn(
|
||||
`Config was last written by a newer Clawdbot (${touched}); current version is ${VERSION}.`,
|
||||
`Config was last written by a newer Moltbot (${touched}); current version is ${VERSION}.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function applyConfigEnv(cfg: ClawdbotConfig, env: NodeJS.ProcessEnv): void {
|
||||
function applyConfigEnv(cfg: MoltbotConfig, env: NodeJS.ProcessEnv): void {
|
||||
const entries = collectConfigEnvVars(cfg);
|
||||
for (const [key, value] of Object.entries(entries)) {
|
||||
if (env[key]?.trim()) continue;
|
||||
@@ -188,7 +188,7 @@ export function createConfigIO(overrides: ConfigIoDeps = {}) {
|
||||
const deps = normalizeDeps(overrides);
|
||||
const configPath = resolveConfigPathForDeps(deps);
|
||||
|
||||
function loadConfig(): ClawdbotConfig {
|
||||
function loadConfig(): MoltbotConfig {
|
||||
try {
|
||||
if (!deps.fs.existsSync(configPath)) {
|
||||
if (shouldEnableShellEnvFallback(deps.env) && !shouldDeferShellEnvFallback(deps.env)) {
|
||||
@@ -213,7 +213,7 @@ export function createConfigIO(overrides: ConfigIoDeps = {}) {
|
||||
|
||||
// Apply config.env to process.env BEFORE substitution so ${VAR} can reference config-defined vars
|
||||
if (resolved && typeof resolved === "object" && "env" in resolved) {
|
||||
applyConfigEnv(resolved as ClawdbotConfig, deps.env);
|
||||
applyConfigEnv(resolved as MoltbotConfig, deps.env);
|
||||
}
|
||||
|
||||
// Substitute ${VAR} env var references
|
||||
@@ -222,7 +222,7 @@ export function createConfigIO(overrides: ConfigIoDeps = {}) {
|
||||
const resolvedConfig = substituted;
|
||||
warnOnConfigMiskeys(resolvedConfig, deps.logger);
|
||||
if (typeof resolvedConfig !== "object" || resolvedConfig === null) return {};
|
||||
const preValidationDuplicates = findDuplicateAgentDirs(resolvedConfig as ClawdbotConfig, {
|
||||
const preValidationDuplicates = findDuplicateAgentDirs(resolvedConfig as MoltbotConfig, {
|
||||
env: deps.env,
|
||||
homedir: deps.homedir,
|
||||
});
|
||||
@@ -372,7 +372,7 @@ export function createConfigIO(overrides: ConfigIoDeps = {}) {
|
||||
|
||||
// Apply config.env to process.env BEFORE substitution so ${VAR} can reference config-defined vars
|
||||
if (resolved && typeof resolved === "object" && "env" in resolved) {
|
||||
applyConfigEnv(resolved as ClawdbotConfig, deps.env);
|
||||
applyConfigEnv(resolved as MoltbotConfig, deps.env);
|
||||
}
|
||||
|
||||
// Substitute ${VAR} env var references
|
||||
@@ -454,7 +454,7 @@ export function createConfigIO(overrides: ConfigIoDeps = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
async function writeConfigFile(cfg: ClawdbotConfig) {
|
||||
async function writeConfigFile(cfg: MoltbotConfig) {
|
||||
clearConfigCache();
|
||||
const validated = validateConfigObjectWithPlugins(cfg);
|
||||
if (!validated.ok) {
|
||||
@@ -528,7 +528,7 @@ const DEFAULT_CONFIG_CACHE_MS = 200;
|
||||
let configCache: {
|
||||
configPath: string;
|
||||
expiresAt: number;
|
||||
config: ClawdbotConfig;
|
||||
config: MoltbotConfig;
|
||||
} | null = null;
|
||||
|
||||
function resolveConfigCacheMs(env: NodeJS.ProcessEnv): number {
|
||||
@@ -549,7 +549,7 @@ function clearConfigCache(): void {
|
||||
configCache = null;
|
||||
}
|
||||
|
||||
export function loadConfig(): ClawdbotConfig {
|
||||
export function loadConfig(): MoltbotConfig {
|
||||
const configPath = resolveConfigPath();
|
||||
const now = Date.now();
|
||||
if (shouldUseConfigCache(process.env)) {
|
||||
@@ -578,7 +578,7 @@ export async function readConfigFileSnapshot(): Promise<ConfigFileSnapshot> {
|
||||
}).readConfigFileSnapshot();
|
||||
}
|
||||
|
||||
export async function writeConfigFile(cfg: ClawdbotConfig): Promise<void> {
|
||||
export async function writeConfigFile(cfg: MoltbotConfig): Promise<void> {
|
||||
clearConfigCache();
|
||||
await createConfigIO({ configPath: resolveConfigPath() }).writeConfigFile(cfg);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { applyLegacyMigrations } from "./legacy.js";
|
||||
import type { ClawdbotConfig } from "./types.js";
|
||||
import type { MoltbotConfig } from "./types.js";
|
||||
import { validateConfigObjectWithPlugins } from "./validation.js";
|
||||
|
||||
export function migrateLegacyConfig(raw: unknown): {
|
||||
config: ClawdbotConfig | null;
|
||||
config: MoltbotConfig | null;
|
||||
changes: string[];
|
||||
} {
|
||||
const { next, changes } = applyLegacyMigrations(raw);
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import type { RuntimeEnv } from "../runtime.js";
|
||||
import { displayPath } from "../utils.js";
|
||||
import { CONFIG_PATH_CLAWDBOT } from "./paths.js";
|
||||
import { CONFIG_PATH } from "./paths.js";
|
||||
|
||||
type LogConfigUpdatedOptions = {
|
||||
path?: string;
|
||||
suffix?: string;
|
||||
};
|
||||
|
||||
export function formatConfigPath(path: string = CONFIG_PATH_CLAWDBOT): string {
|
||||
export function formatConfigPath(path: string = CONFIG_PATH): string {
|
||||
return displayPath(path);
|
||||
}
|
||||
|
||||
export function logConfigUpdated(runtime: RuntimeEnv, opts: LogConfigUpdatedOptions = {}): void {
|
||||
const path = formatConfigPath(opts.path ?? CONFIG_PATH_CLAWDBOT);
|
||||
const path = formatConfigPath(opts.path ?? CONFIG_PATH);
|
||||
const suffix = opts.suffix ? ` ${opts.suffix}` : "";
|
||||
runtime.log(`Updated ${path}${suffix}`);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { normalizeChannelId } from "../channels/plugins/index.js";
|
||||
import { normalizeAccountId } from "../routing/session-key.js";
|
||||
import type { ClawdbotConfig } from "./config.js";
|
||||
import type { MoltbotConfig } from "./config.js";
|
||||
import type { MarkdownTableMode } from "./types.base.js";
|
||||
|
||||
type MarkdownConfigEntry = {
|
||||
@@ -44,7 +44,7 @@ function resolveMarkdownModeFromSection(
|
||||
}
|
||||
|
||||
export function resolveMarkdownTableMode(params: {
|
||||
cfg?: Partial<ClawdbotConfig>;
|
||||
cfg?: Partial<MoltbotConfig>;
|
||||
channel?: string | null;
|
||||
accountId?: string | null;
|
||||
}): MarkdownTableMode {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotConfig } from "./config.js";
|
||||
import type { MoltbotConfig } from "./config.js";
|
||||
import type { WhatsAppConfig } from "./types.js";
|
||||
|
||||
export type MergeSectionOptions<T> = {
|
||||
@@ -24,10 +24,10 @@ export function mergeConfigSection<T extends Record<string, unknown>>(
|
||||
}
|
||||
|
||||
export function mergeWhatsAppConfig(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
patch: Partial<WhatsAppConfig>,
|
||||
options?: MergeSectionOptions<WhatsAppConfig>,
|
||||
): ClawdbotConfig {
|
||||
): MoltbotConfig {
|
||||
return {
|
||||
...cfg,
|
||||
channels: {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { DEFAULT_CONTEXT_TOKENS } from "../agents/defaults.js";
|
||||
import { applyModelDefaults } from "./defaults.js";
|
||||
import type { ClawdbotConfig } from "./types.js";
|
||||
import type { MoltbotConfig } from "./types.js";
|
||||
|
||||
describe("applyModelDefaults", () => {
|
||||
it("adds default aliases when models are present", () => {
|
||||
@@ -14,7 +14,7 @@ describe("applyModelDefaults", () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies ClawdbotConfig;
|
||||
} satisfies MoltbotConfig;
|
||||
const next = applyModelDefaults(cfg);
|
||||
|
||||
expect(next.agents?.defaults?.models?.["anthropic/claude-opus-4-5"]?.alias).toBe("opus");
|
||||
@@ -30,7 +30,7 @@ describe("applyModelDefaults", () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies ClawdbotConfig;
|
||||
} satisfies MoltbotConfig;
|
||||
|
||||
const next = applyModelDefaults(cfg);
|
||||
|
||||
@@ -47,7 +47,7 @@ describe("applyModelDefaults", () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies ClawdbotConfig;
|
||||
} satisfies MoltbotConfig;
|
||||
|
||||
const next = applyModelDefaults(cfg);
|
||||
|
||||
@@ -69,7 +69,7 @@ describe("applyModelDefaults", () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
} satisfies ClawdbotConfig;
|
||||
} satisfies MoltbotConfig;
|
||||
|
||||
const next = applyModelDefaults(cfg);
|
||||
const model = next.models?.providers?.myproxy?.models?.[0];
|
||||
|
||||
@@ -13,7 +13,7 @@ describe("normalizeConfigPaths", () => {
|
||||
const cfg = normalizeConfigPaths({
|
||||
tools: { exec: { pathPrepend: ["~/bin"] } },
|
||||
plugins: { load: { paths: ["~/plugins/a"] } },
|
||||
logging: { file: "~/.clawdbot/logs/clawdbot.log" },
|
||||
logging: { file: "~/.clawdbot/logs/moltbot.log" },
|
||||
hooks: {
|
||||
path: "~/.clawdbot/hooks.json5",
|
||||
transformsDir: "~/hooks-xform",
|
||||
@@ -47,7 +47,7 @@ describe("normalizeConfigPaths", () => {
|
||||
});
|
||||
|
||||
expect(cfg.plugins?.load?.paths?.[0]).toBe(path.join(home, "plugins", "a"));
|
||||
expect(cfg.logging?.file).toBe(path.join(home, ".clawdbot", "logs", "clawdbot.log"));
|
||||
expect(cfg.logging?.file).toBe(path.join(home, ".clawdbot", "logs", "moltbot.log"));
|
||||
expect(cfg.hooks?.path).toBe(path.join(home, ".clawdbot", "hooks.json5"));
|
||||
expect(cfg.hooks?.transformsDir).toBe(path.join(home, "hooks-xform"));
|
||||
expect(cfg.tools?.exec?.pathPrepend?.[0]).toBe(path.join(home, "bin"));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import type { ClawdbotConfig } from "./types.js";
|
||||
import type { MoltbotConfig } from "./types.js";
|
||||
|
||||
const PATH_VALUE_RE = /^~(?=$|[\\/])/;
|
||||
|
||||
@@ -50,7 +50,7 @@ function normalizeAny(key: string | undefined, value: unknown): unknown {
|
||||
* Goal: accept `~/...` consistently across config file + env overrides, while
|
||||
* keeping the surface area small and predictable.
|
||||
*/
|
||||
export function normalizeConfigPaths(cfg: ClawdbotConfig): ClawdbotConfig {
|
||||
export function normalizeConfigPaths(cfg: MoltbotConfig): MoltbotConfig {
|
||||
if (!cfg || typeof cfg !== "object") return cfg;
|
||||
normalizeAny(undefined, cfg);
|
||||
return cfg;
|
||||
|
||||
+8
-8
@@ -1,6 +1,6 @@
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import type { ClawdbotConfig } from "./types.js";
|
||||
import type { MoltbotConfig } from "./types.js";
|
||||
|
||||
/**
|
||||
* Nix mode detection: When CLAWDBOT_NIX_MODE=1, the gateway is running under Nix.
|
||||
@@ -39,12 +39,12 @@ function resolveUserPath(input: string): string {
|
||||
return path.resolve(trimmed);
|
||||
}
|
||||
|
||||
export const STATE_DIR_CLAWDBOT = resolveStateDir();
|
||||
export const STATE_DIR = resolveStateDir();
|
||||
|
||||
/**
|
||||
* Config file path (JSON5).
|
||||
* Can be overridden via CLAWDBOT_CONFIG_PATH environment variable.
|
||||
* Default: ~/.clawdbot/clawdbot.json (or $CLAWDBOT_STATE_DIR/clawdbot.json)
|
||||
* Default: ~/.clawdbot/moltbot.json (or $CLAWDBOT_STATE_DIR/moltbot.json)
|
||||
*/
|
||||
export function resolveConfigPath(
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
@@ -52,21 +52,21 @@ export function resolveConfigPath(
|
||||
): string {
|
||||
const override = env.CLAWDBOT_CONFIG_PATH?.trim();
|
||||
if (override) return resolveUserPath(override);
|
||||
return path.join(stateDir, "clawdbot.json");
|
||||
return path.join(stateDir, "moltbot.json");
|
||||
}
|
||||
|
||||
export const CONFIG_PATH_CLAWDBOT = resolveConfigPath();
|
||||
export const CONFIG_PATH = resolveConfigPath();
|
||||
|
||||
export const DEFAULT_GATEWAY_PORT = 18789;
|
||||
|
||||
/**
|
||||
* Gateway lock directory (ephemeral).
|
||||
* Default: os.tmpdir()/clawdbot-<uid> (uid suffix when available).
|
||||
* Default: os.tmpdir()/moltbot-<uid> (uid suffix when available).
|
||||
*/
|
||||
export function resolveGatewayLockDir(tmpdir: () => string = os.tmpdir): string {
|
||||
const base = tmpdir();
|
||||
const uid = typeof process.getuid === "function" ? process.getuid() : undefined;
|
||||
const suffix = uid != null ? `clawdbot-${uid}` : "clawdbot";
|
||||
const suffix = uid != null ? `moltbot-${uid}` : "moltbot";
|
||||
return path.join(base, suffix);
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ export function resolveOAuthPath(
|
||||
}
|
||||
|
||||
export function resolveGatewayPort(
|
||||
cfg?: ClawdbotConfig,
|
||||
cfg?: MoltbotConfig,
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): number {
|
||||
const envRaw = env.CLAWDBOT_GATEWAY_PORT?.trim();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ClawdbotConfig } from "./config.js";
|
||||
import type { MoltbotConfig } from "./config.js";
|
||||
import {
|
||||
getChatChannelMeta,
|
||||
listChatChannels,
|
||||
@@ -17,7 +17,7 @@ type PluginEnableChange = {
|
||||
};
|
||||
|
||||
export type PluginAutoEnableResult = {
|
||||
config: ClawdbotConfig;
|
||||
config: MoltbotConfig;
|
||||
changes: string[];
|
||||
};
|
||||
|
||||
@@ -59,7 +59,7 @@ function accountsHaveKeys(value: unknown, keys: string[]): boolean {
|
||||
}
|
||||
|
||||
function resolveChannelConfig(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
channelId: string,
|
||||
): Record<string, unknown> | null {
|
||||
const channels = cfg.channels as Record<string, unknown> | undefined;
|
||||
@@ -67,7 +67,7 @@ function resolveChannelConfig(
|
||||
return isRecord(entry) ? entry : null;
|
||||
}
|
||||
|
||||
function isTelegramConfigured(cfg: ClawdbotConfig, env: NodeJS.ProcessEnv): boolean {
|
||||
function isTelegramConfigured(cfg: MoltbotConfig, env: NodeJS.ProcessEnv): boolean {
|
||||
if (hasNonEmptyString(env.TELEGRAM_BOT_TOKEN)) return true;
|
||||
const entry = resolveChannelConfig(cfg, "telegram");
|
||||
if (!entry) return false;
|
||||
@@ -76,7 +76,7 @@ function isTelegramConfigured(cfg: ClawdbotConfig, env: NodeJS.ProcessEnv): bool
|
||||
return recordHasKeys(entry);
|
||||
}
|
||||
|
||||
function isDiscordConfigured(cfg: ClawdbotConfig, env: NodeJS.ProcessEnv): boolean {
|
||||
function isDiscordConfigured(cfg: MoltbotConfig, env: NodeJS.ProcessEnv): boolean {
|
||||
if (hasNonEmptyString(env.DISCORD_BOT_TOKEN)) return true;
|
||||
const entry = resolveChannelConfig(cfg, "discord");
|
||||
if (!entry) return false;
|
||||
@@ -85,7 +85,7 @@ function isDiscordConfigured(cfg: ClawdbotConfig, env: NodeJS.ProcessEnv): boole
|
||||
return recordHasKeys(entry);
|
||||
}
|
||||
|
||||
function isSlackConfigured(cfg: ClawdbotConfig, env: NodeJS.ProcessEnv): boolean {
|
||||
function isSlackConfigured(cfg: MoltbotConfig, env: NodeJS.ProcessEnv): boolean {
|
||||
if (
|
||||
hasNonEmptyString(env.SLACK_BOT_TOKEN) ||
|
||||
hasNonEmptyString(env.SLACK_APP_TOKEN) ||
|
||||
@@ -106,7 +106,7 @@ function isSlackConfigured(cfg: ClawdbotConfig, env: NodeJS.ProcessEnv): boolean
|
||||
return recordHasKeys(entry);
|
||||
}
|
||||
|
||||
function isSignalConfigured(cfg: ClawdbotConfig): boolean {
|
||||
function isSignalConfigured(cfg: MoltbotConfig): boolean {
|
||||
const entry = resolveChannelConfig(cfg, "signal");
|
||||
if (!entry) return false;
|
||||
if (
|
||||
@@ -122,27 +122,27 @@ function isSignalConfigured(cfg: ClawdbotConfig): boolean {
|
||||
return recordHasKeys(entry);
|
||||
}
|
||||
|
||||
function isIMessageConfigured(cfg: ClawdbotConfig): boolean {
|
||||
function isIMessageConfigured(cfg: MoltbotConfig): boolean {
|
||||
const entry = resolveChannelConfig(cfg, "imessage");
|
||||
if (!entry) return false;
|
||||
if (hasNonEmptyString(entry.cliPath)) return true;
|
||||
return recordHasKeys(entry);
|
||||
}
|
||||
|
||||
function isWhatsAppConfigured(cfg: ClawdbotConfig): boolean {
|
||||
function isWhatsAppConfigured(cfg: MoltbotConfig): boolean {
|
||||
if (hasAnyWhatsAppAuth(cfg)) return true;
|
||||
const entry = resolveChannelConfig(cfg, "whatsapp");
|
||||
if (!entry) return false;
|
||||
return recordHasKeys(entry);
|
||||
}
|
||||
|
||||
function isGenericChannelConfigured(cfg: ClawdbotConfig, channelId: string): boolean {
|
||||
function isGenericChannelConfigured(cfg: MoltbotConfig, channelId: string): boolean {
|
||||
const entry = resolveChannelConfig(cfg, channelId);
|
||||
return recordHasKeys(entry);
|
||||
}
|
||||
|
||||
export function isChannelConfigured(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
channelId: string,
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): boolean {
|
||||
@@ -164,7 +164,7 @@ export function isChannelConfigured(
|
||||
}
|
||||
}
|
||||
|
||||
function collectModelRefs(cfg: ClawdbotConfig): string[] {
|
||||
function collectModelRefs(cfg: MoltbotConfig): string[] {
|
||||
const refs: string[] = [];
|
||||
const pushModelRef = (value: unknown) => {
|
||||
if (typeof value === "string" && value.trim()) refs.push(value.trim());
|
||||
@@ -208,7 +208,7 @@ function extractProviderFromModelRef(value: string): string | null {
|
||||
return normalizeProviderId(trimmed.slice(0, slash));
|
||||
}
|
||||
|
||||
function isProviderConfigured(cfg: ClawdbotConfig, providerId: string): boolean {
|
||||
function isProviderConfigured(cfg: MoltbotConfig, providerId: string): boolean {
|
||||
const normalized = normalizeProviderId(providerId);
|
||||
|
||||
const profiles = cfg.auth?.profiles;
|
||||
@@ -237,7 +237,7 @@ function isProviderConfigured(cfg: ClawdbotConfig, providerId: string): boolean
|
||||
}
|
||||
|
||||
function resolveConfiguredPlugins(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
env: NodeJS.ProcessEnv,
|
||||
): PluginEnableChange[] {
|
||||
const changes: PluginEnableChange[] = [];
|
||||
@@ -269,12 +269,12 @@ function resolveConfiguredPlugins(
|
||||
return changes;
|
||||
}
|
||||
|
||||
function isPluginExplicitlyDisabled(cfg: ClawdbotConfig, pluginId: string): boolean {
|
||||
function isPluginExplicitlyDisabled(cfg: MoltbotConfig, pluginId: string): boolean {
|
||||
const entry = cfg.plugins?.entries?.[pluginId];
|
||||
return entry?.enabled === false;
|
||||
}
|
||||
|
||||
function isPluginDenied(cfg: ClawdbotConfig, pluginId: string): boolean {
|
||||
function isPluginDenied(cfg: MoltbotConfig, pluginId: string): boolean {
|
||||
const deny = cfg.plugins?.deny;
|
||||
return Array.isArray(deny) && deny.includes(pluginId);
|
||||
}
|
||||
@@ -289,7 +289,7 @@ function resolvePreferredOverIds(pluginId: string): string[] {
|
||||
}
|
||||
|
||||
function shouldSkipPreferredPluginAutoEnable(
|
||||
cfg: ClawdbotConfig,
|
||||
cfg: MoltbotConfig,
|
||||
entry: PluginEnableChange,
|
||||
configured: PluginEnableChange[],
|
||||
): boolean {
|
||||
@@ -305,7 +305,7 @@ function shouldSkipPreferredPluginAutoEnable(
|
||||
return false;
|
||||
}
|
||||
|
||||
function ensureAllowlisted(cfg: ClawdbotConfig, pluginId: string): ClawdbotConfig {
|
||||
function ensureAllowlisted(cfg: MoltbotConfig, pluginId: string): MoltbotConfig {
|
||||
const allow = cfg.plugins?.allow;
|
||||
if (!Array.isArray(allow) || allow.includes(pluginId)) return cfg;
|
||||
return {
|
||||
@@ -317,7 +317,7 @@ function ensureAllowlisted(cfg: ClawdbotConfig, pluginId: string): ClawdbotConfi
|
||||
};
|
||||
}
|
||||
|
||||
function enablePluginEntry(cfg: ClawdbotConfig, pluginId: string): ClawdbotConfig {
|
||||
function enablePluginEntry(cfg: MoltbotConfig, pluginId: string): MoltbotConfig {
|
||||
const entries = {
|
||||
...cfg.plugins?.entries,
|
||||
[pluginId]: {
|
||||
@@ -346,7 +346,7 @@ function formatAutoEnableChange(entry: PluginEnableChange): string {
|
||||
}
|
||||
|
||||
export function applyPluginAutoEnable(params: {
|
||||
config: ClawdbotConfig;
|
||||
config: MoltbotConfig;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
}): PluginAutoEnableResult {
|
||||
const env = params.env ?? process.env;
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
setConfigOverride,
|
||||
unsetConfigOverride,
|
||||
} from "./runtime-overrides.js";
|
||||
import type { ClawdbotConfig } from "./types.js";
|
||||
import type { MoltbotConfig } from "./types.js";
|
||||
|
||||
describe("runtime overrides", () => {
|
||||
beforeEach(() => {
|
||||
@@ -15,8 +15,8 @@ describe("runtime overrides", () => {
|
||||
|
||||
it("sets and applies nested overrides", () => {
|
||||
const cfg = {
|
||||
messages: { responsePrefix: "[clawdbot]" },
|
||||
} as ClawdbotConfig;
|
||||
messages: { responsePrefix: "[moltbot]" },
|
||||
} as MoltbotConfig;
|
||||
setConfigOverride("messages.responsePrefix", "[debug]");
|
||||
const next = applyConfigOverrides(cfg);
|
||||
expect(next.messages?.responsePrefix).toBe("[debug]");
|
||||
@@ -25,7 +25,7 @@ describe("runtime overrides", () => {
|
||||
it("merges object overrides without clobbering siblings", () => {
|
||||
const cfg = {
|
||||
channels: { whatsapp: { dmPolicy: "pairing", allowFrom: ["+1"] } },
|
||||
} as ClawdbotConfig;
|
||||
} as MoltbotConfig;
|
||||
setConfigOverride("channels.whatsapp.dmPolicy", "open");
|
||||
const next = applyConfigOverrides(cfg);
|
||||
expect(next.channels?.whatsapp?.dmPolicy).toBe("open");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { parseConfigPath, setConfigValueAtPath, unsetConfigValueAtPath } from "./config-paths.js";
|
||||
import type { ClawdbotConfig } from "./types.js";
|
||||
import type { MoltbotConfig } from "./types.js";
|
||||
|
||||
type OverrideTree = Record<string, unknown>;
|
||||
|
||||
@@ -64,7 +64,7 @@ export function unsetConfigOverride(pathRaw: string): {
|
||||
return { ok: true, removed };
|
||||
}
|
||||
|
||||
export function applyConfigOverrides(cfg: ClawdbotConfig): ClawdbotConfig {
|
||||
export function applyConfigOverrides(cfg: MoltbotConfig): MoltbotConfig {
|
||||
if (!overrides || Object.keys(overrides).length === 0) return cfg;
|
||||
return mergeOverrides(cfg, overrides) as ClawdbotConfig;
|
||||
return mergeOverrides(cfg, overrides) as MoltbotConfig;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CHANNEL_IDS } from "../channels/registry.js";
|
||||
import { VERSION } from "../version.js";
|
||||
import { ClawdbotSchema } from "./zod-schema.js";
|
||||
import { MoltbotSchema } from "./zod-schema.js";
|
||||
|
||||
export type ConfigUiHint = {
|
||||
label?: string;
|
||||
@@ -15,7 +15,7 @@ export type ConfigUiHint = {
|
||||
|
||||
export type ConfigUiHints = Record<string, ConfigUiHint>;
|
||||
|
||||
export type ConfigSchema = ReturnType<typeof ClawdbotSchema.toJSONSchema>;
|
||||
export type ConfigSchema = ReturnType<typeof MoltbotSchema.toJSONSchema>;
|
||||
|
||||
type JsonSchemaNode = Record<string, unknown>;
|
||||
|
||||
@@ -364,7 +364,7 @@ const FIELD_LABELS: Record<string, string> = {
|
||||
};
|
||||
|
||||
const FIELD_HELP: Record<string, string> = {
|
||||
"meta.lastTouchedVersion": "Auto-set when Clawdbot writes the config.",
|
||||
"meta.lastTouchedVersion": "Auto-set when Moltbot writes the config.",
|
||||
"meta.lastTouchedAt": "ISO timestamp of the last config write (auto-set).",
|
||||
"update.channel": 'Update channel for git + npm installs ("stable", "beta", or "dev").',
|
||||
"update.checkOnStart": "Check for npm updates when the gateway starts (default: true).",
|
||||
@@ -382,7 +382,7 @@ const FIELD_HELP: Record<string, string> = {
|
||||
"Required by default for gateway access (unless using Tailscale Serve identity); required for non-loopback binds.",
|
||||
"gateway.auth.password": "Required for Tailscale funnel.",
|
||||
"gateway.controlUi.basePath":
|
||||
"Optional URL prefix where the Control UI is served (e.g. /clawdbot).",
|
||||
"Optional URL prefix where the Control UI is served (e.g. /moltbot).",
|
||||
"gateway.controlUi.allowInsecureAuth":
|
||||
"Allow Control UI auth over insecure HTTP (token-only; not recommended).",
|
||||
"gateway.controlUi.dangerouslyDisableDeviceAuth":
|
||||
@@ -557,7 +557,7 @@ const FIELD_HELP: Record<string, string> = {
|
||||
"plugins.entries.*.enabled": "Overrides plugin enable/disable for this entry (restart required).",
|
||||
"plugins.entries.*.config": "Plugin-defined config payload (schema is provided by the plugin).",
|
||||
"plugins.installs":
|
||||
"CLI-managed install metadata (used by `clawdbot plugins update` to locate install sources).",
|
||||
"CLI-managed install metadata (used by `moltbot plugins update` to locate install sources).",
|
||||
"plugins.installs.*.source": 'Install source ("npm", "archive", or "path").',
|
||||
"plugins.installs.*.spec": "Original npm spec used for install (if source is npm).",
|
||||
"plugins.installs.*.sourcePath": "Original archive/path used for install (if any).",
|
||||
@@ -679,7 +679,7 @@ const FIELD_PLACEHOLDERS: Record<string, string> = {
|
||||
"gateway.remote.url": "ws://host:18789",
|
||||
"gateway.remote.tlsFingerprint": "sha256:ab12cd34…",
|
||||
"gateway.remote.sshTarget": "user@host",
|
||||
"gateway.controlUi.basePath": "/clawdbot",
|
||||
"gateway.controlUi.basePath": "/moltbot",
|
||||
"channels.mattermost.baseUrl": "https://chat.example.com",
|
||||
"agents.list[].identity.avatar": "avatars/clawd.png",
|
||||
};
|
||||
@@ -948,11 +948,11 @@ function stripChannelSchema(schema: ConfigSchema): ConfigSchema {
|
||||
|
||||
function buildBaseConfigSchema(): ConfigSchemaResponse {
|
||||
if (cachedBase) return cachedBase;
|
||||
const schema = ClawdbotSchema.toJSONSchema({
|
||||
const schema = MoltbotSchema.toJSONSchema({
|
||||
target: "draft-07",
|
||||
unrepresentable: "any",
|
||||
});
|
||||
schema.title = "ClawdbotConfig";
|
||||
schema.title = "MoltbotConfig";
|
||||
const hints = applySensitiveHints(buildBaseHints());
|
||||
const next = {
|
||||
schema: stripChannelSchema(schema),
|
||||
|
||||
+10
-10
@@ -95,7 +95,7 @@ describe("sessions", () => {
|
||||
|
||||
it("updateLastRoute persists channel and target", async () => {
|
||||
const mainSessionKey = "agent:main:main";
|
||||
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");
|
||||
await fs.writeFile(
|
||||
storePath,
|
||||
@@ -148,7 +148,7 @@ describe("sessions", () => {
|
||||
|
||||
it("updateLastRoute prefers explicit deliveryContext", async () => {
|
||||
const mainSessionKey = "agent:main:main";
|
||||
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");
|
||||
await fs.writeFile(storePath, "{}", "utf-8");
|
||||
|
||||
@@ -178,7 +178,7 @@ describe("sessions", () => {
|
||||
|
||||
it("updateLastRoute records origin + group metadata when ctx is provided", async () => {
|
||||
const sessionKey = "agent:main:whatsapp:group:123@g.us";
|
||||
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");
|
||||
await fs.writeFile(storePath, "{}", "utf-8");
|
||||
|
||||
@@ -208,7 +208,7 @@ describe("sessions", () => {
|
||||
|
||||
it("updateSessionStoreEntry preserves existing fields when patching", async () => {
|
||||
const sessionKey = "agent:main:main";
|
||||
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");
|
||||
await fs.writeFile(
|
||||
storePath,
|
||||
@@ -238,7 +238,7 @@ describe("sessions", () => {
|
||||
});
|
||||
|
||||
it("updateSessionStore preserves concurrent additions", 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");
|
||||
await fs.writeFile(storePath, "{}", "utf-8");
|
||||
|
||||
@@ -257,7 +257,7 @@ describe("sessions", () => {
|
||||
});
|
||||
|
||||
it("recovers from array-backed session stores", 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");
|
||||
await fs.writeFile(storePath, "[]", "utf-8");
|
||||
|
||||
@@ -273,7 +273,7 @@ describe("sessions", () => {
|
||||
});
|
||||
|
||||
it("normalizes last route fields on write", 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");
|
||||
await fs.writeFile(storePath, "{}", "utf-8");
|
||||
|
||||
@@ -299,7 +299,7 @@ describe("sessions", () => {
|
||||
});
|
||||
|
||||
it("updateSessionStore keeps deletions when concurrent writes happen", 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");
|
||||
await fs.writeFile(
|
||||
storePath,
|
||||
@@ -331,7 +331,7 @@ describe("sessions", () => {
|
||||
|
||||
it("loadSessionStore auto-migrates legacy provider keys to channel keys", async () => {
|
||||
const mainSessionKey = "agent:main:main";
|
||||
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");
|
||||
await fs.writeFile(
|
||||
storePath,
|
||||
@@ -411,7 +411,7 @@ describe("sessions", () => {
|
||||
|
||||
it("updateSessionStoreEntry merges concurrent patches", async () => {
|
||||
const mainSessionKey = "agent:main:main";
|
||||
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");
|
||||
await fs.writeFile(
|
||||
storePath,
|
||||
|
||||
@@ -99,7 +99,7 @@ export async function appendAssistantMessageToSessionTranscript(params: {
|
||||
role: "assistant",
|
||||
content: [{ type: "text", text: mirrorText }],
|
||||
api: "openai-responses",
|
||||
provider: "clawdbot",
|
||||
provider: "moltbot",
|
||||
model: "delivery-mirror",
|
||||
usage: {
|
||||
input: 0,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { vi } from "vitest";
|
||||
import { withTempHome as withTempHomeBase } from "../../test/helpers/temp-home.js";
|
||||
|
||||
export async function withTempHome<T>(fn: (home: string) => Promise<T>): Promise<T> {
|
||||
return withTempHomeBase(fn, { prefix: "clawdbot-config-" });
|
||||
return withTempHomeBase(fn, { prefix: "moltbot-config-" });
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,9 +24,9 @@ import type { PluginsConfig } from "./types.plugins.js";
|
||||
import type { SkillsConfig } from "./types.skills.js";
|
||||
import type { ToolsConfig } from "./types.tools.js";
|
||||
|
||||
export type ClawdbotConfig = {
|
||||
export type MoltbotConfig = {
|
||||
meta?: {
|
||||
/** Last clawdbot version that wrote this config. */
|
||||
/** Last moltbot version that wrote this config. */
|
||||
lastTouchedVersion?: string;
|
||||
/** ISO timestamp when this config was last written. */
|
||||
lastTouchedAt?: string;
|
||||
@@ -65,7 +65,7 @@ export type ClawdbotConfig = {
|
||||
};
|
||||
browser?: BrowserConfig;
|
||||
ui?: {
|
||||
/** Accent color for Clawdbot UI chrome (hex). */
|
||||
/** Accent color for Moltbot UI chrome (hex). */
|
||||
seamColor?: string;
|
||||
assistant?: {
|
||||
/** Assistant display name for UI surfaces. */
|
||||
@@ -113,7 +113,7 @@ export type ConfigFileSnapshot = {
|
||||
raw: string | null;
|
||||
parsed: unknown;
|
||||
valid: boolean;
|
||||
config: ClawdbotConfig;
|
||||
config: MoltbotConfig;
|
||||
hash?: string;
|
||||
issues: ConfigValidationIssue[];
|
||||
warnings: ConfigValidationIssue[];
|
||||
|
||||
@@ -62,7 +62,7 @@ export type TalkConfig = {
|
||||
export type GatewayControlUiConfig = {
|
||||
/** If false, the Gateway will not serve the Control UI (default /). */
|
||||
enabled?: boolean;
|
||||
/** Optional base path prefix for the Control UI (e.g. "/clawdbot"). */
|
||||
/** Optional base path prefix for the Control UI (e.g. "/moltbot"). */
|
||||
basePath?: string;
|
||||
/** Allow token-only auth over insecure HTTP (default: false). */
|
||||
allowInsecureAuth?: boolean;
|
||||
|
||||
@@ -23,7 +23,7 @@ export type IMessageAccountConfig = {
|
||||
cliPath?: string;
|
||||
/** Optional Messages db path override. */
|
||||
dbPath?: string;
|
||||
/** Remote host for SCP when attachments live on a different machine (e.g., clawdbot@192.168.64.3). */
|
||||
/** Remote host for SCP when attachments live on a different machine (e.g., moltbot@192.168.64.3). */
|
||||
remoteHost?: string;
|
||||
/** Optional default send service (imessage|sms|auto). */
|
||||
service?: "imessage" | "sms" | "auto";
|
||||
|
||||
@@ -27,7 +27,7 @@ export type WhatsAppConfig = {
|
||||
sendReadReceipts?: boolean;
|
||||
/**
|
||||
* Inbound message prefix (WhatsApp only).
|
||||
* Default: `[{agents.list[].identity.name}]` (or `[clawdbot]`) when allowFrom is empty, else `""`.
|
||||
* Default: `[{agents.list[].identity.name}]` (or `[moltbot]`) when allowFrom is empty, else `""`.
|
||||
*/
|
||||
messagePrefix?: string;
|
||||
/** Direct message access policy (default: pairing). */
|
||||
|
||||
@@ -12,8 +12,8 @@ import { validateJsonSchemaValue } from "../plugins/schema-validator.js";
|
||||
import { findDuplicateAgentDirs, formatDuplicateAgentDirError } from "./agent-dirs.js";
|
||||
import { applyAgentDefaults, applyModelDefaults, applySessionDefaults } from "./defaults.js";
|
||||
import { findLegacyConfigIssues } from "./legacy.js";
|
||||
import type { ClawdbotConfig, ConfigValidationIssue } from "./types.js";
|
||||
import { ClawdbotSchema } from "./zod-schema.js";
|
||||
import type { MoltbotConfig, ConfigValidationIssue } from "./types.js";
|
||||
import { MoltbotSchema } from "./zod-schema.js";
|
||||
|
||||
const AVATAR_SCHEME_RE = /^[a-z][a-z0-9+.-]*:/i;
|
||||
const AVATAR_DATA_RE = /^data:/i;
|
||||
@@ -29,7 +29,7 @@ function isWorkspaceAvatarPath(value: string, workspaceDir: string): boolean {
|
||||
return !path.isAbsolute(relative);
|
||||
}
|
||||
|
||||
function validateIdentityAvatar(config: ClawdbotConfig): ConfigValidationIssue[] {
|
||||
function validateIdentityAvatar(config: MoltbotConfig): ConfigValidationIssue[] {
|
||||
const agents = config.agents?.list;
|
||||
if (!Array.isArray(agents) || agents.length === 0) return [];
|
||||
const issues: ConfigValidationIssue[] = [];
|
||||
@@ -71,7 +71,7 @@ function validateIdentityAvatar(config: ClawdbotConfig): ConfigValidationIssue[]
|
||||
|
||||
export function validateConfigObject(
|
||||
raw: unknown,
|
||||
): { ok: true; config: ClawdbotConfig } | { ok: false; issues: ConfigValidationIssue[] } {
|
||||
): { ok: true; config: MoltbotConfig } | { ok: false; issues: ConfigValidationIssue[] } {
|
||||
const legacyIssues = findLegacyConfigIssues(raw);
|
||||
if (legacyIssues.length > 0) {
|
||||
return {
|
||||
@@ -82,7 +82,7 @@ export function validateConfigObject(
|
||||
})),
|
||||
};
|
||||
}
|
||||
const validated = ClawdbotSchema.safeParse(raw);
|
||||
const validated = MoltbotSchema.safeParse(raw);
|
||||
if (!validated.success) {
|
||||
return {
|
||||
ok: false,
|
||||
@@ -92,7 +92,7 @@ export function validateConfigObject(
|
||||
})),
|
||||
};
|
||||
}
|
||||
const duplicates = findDuplicateAgentDirs(validated.data as ClawdbotConfig);
|
||||
const duplicates = findDuplicateAgentDirs(validated.data as MoltbotConfig);
|
||||
if (duplicates.length > 0) {
|
||||
return {
|
||||
ok: false,
|
||||
@@ -104,14 +104,14 @@ export function validateConfigObject(
|
||||
],
|
||||
};
|
||||
}
|
||||
const avatarIssues = validateIdentityAvatar(validated.data as ClawdbotConfig);
|
||||
const avatarIssues = validateIdentityAvatar(validated.data as MoltbotConfig);
|
||||
if (avatarIssues.length > 0) {
|
||||
return { ok: false, issues: avatarIssues };
|
||||
}
|
||||
return {
|
||||
ok: true,
|
||||
config: applyModelDefaults(
|
||||
applyAgentDefaults(applySessionDefaults(validated.data as ClawdbotConfig)),
|
||||
applyAgentDefaults(applySessionDefaults(validated.data as MoltbotConfig)),
|
||||
),
|
||||
};
|
||||
}
|
||||
@@ -123,7 +123,7 @@ function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
export function validateConfigObjectWithPlugins(raw: unknown):
|
||||
| {
|
||||
ok: true;
|
||||
config: ClawdbotConfig;
|
||||
config: MoltbotConfig;
|
||||
warnings: ConfigValidationIssue[];
|
||||
}
|
||||
| {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export type ClawdbotVersion = {
|
||||
export type MoltbotVersion = {
|
||||
major: number;
|
||||
minor: number;
|
||||
patch: number;
|
||||
@@ -7,7 +7,7 @@ export type ClawdbotVersion = {
|
||||
|
||||
const VERSION_RE = /^v?(\d+)\.(\d+)\.(\d+)(?:-(\d+))?/;
|
||||
|
||||
export function parseClawdbotVersion(raw: string | null | undefined): ClawdbotVersion | null {
|
||||
export function parseMoltbotVersion(raw: string | null | undefined): MoltbotVersion | null {
|
||||
if (!raw) return null;
|
||||
const match = raw.trim().match(VERSION_RE);
|
||||
if (!match) return null;
|
||||
@@ -20,12 +20,12 @@ export function parseClawdbotVersion(raw: string | null | undefined): ClawdbotVe
|
||||
};
|
||||
}
|
||||
|
||||
export function compareClawdbotVersions(
|
||||
export function compareMoltbotVersions(
|
||||
a: string | null | undefined,
|
||||
b: string | null | undefined,
|
||||
): number | null {
|
||||
const parsedA = parseClawdbotVersion(a);
|
||||
const parsedB = parseClawdbotVersion(b);
|
||||
const parsedA = parseMoltbotVersion(a);
|
||||
const parsedB = parseMoltbotVersion(b);
|
||||
if (!parsedA || !parsedB) return null;
|
||||
if (parsedA.major !== parsedB.major) return parsedA.major < parsedB.major ? -1 : 1;
|
||||
if (parsedA.minor !== parsedB.minor) return parsedA.minor < parsedB.minor ? -1 : 1;
|
||||
|
||||
@@ -27,7 +27,7 @@ const NodeHostSchema = z
|
||||
.strict()
|
||||
.optional();
|
||||
|
||||
export const ClawdbotSchema = z
|
||||
export const MoltbotSchema = z
|
||||
.object({
|
||||
meta: z
|
||||
.object({
|
||||
|
||||
Reference in New Issue
Block a user