refactor: rename clawdbot to moltbot with legacy compat

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

View File

@@ -116,7 +116,7 @@ export const twitchMessageActions: ChannelMessageActionAdapter = {
* const result = await twitchMessageActions.handleAction!({
* action: "send",
* params: { message: "Hello Twitch!", to: "#mychannel" },
* cfg: clawdbotConfig,
* cfg: moltbotConfig,
* accountId: "default",
* });
*/

View File

@@ -1,4 +1,4 @@
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
import type { TwitchAccountConfig } from "./types.js";
/**
@@ -24,7 +24,7 @@ export function getAccountConfig(
return null;
}
const cfg = coreConfig as ClawdbotConfig;
const cfg = coreConfig as MoltbotConfig;
const twitch = cfg.channels?.twitch;
// Access accounts via unknown to handle union type (single-account vs multi-account)
const twitchRaw = twitch as Record<string, unknown> | undefined;
@@ -88,7 +88,7 @@ export function getAccountConfig(
*
* Includes both explicit accounts and implicit "default" from base-level config
*/
export function listAccountIds(cfg: ClawdbotConfig): string[] {
export function listAccountIds(cfg: MoltbotConfig): string[] {
const twitch = cfg.channels?.twitch;
// Access accounts via unknown to handle union type (single-account vs multi-account)
const twitchRaw = twitch as Record<string, unknown> | undefined;

View File

@@ -5,7 +5,7 @@
* resolves agent routes, and handles replies.
*/
import type { ReplyPayload, ClawdbotConfig } from "clawdbot/plugin-sdk";
import type { ReplyPayload, MoltbotConfig } from "clawdbot/plugin-sdk";
import type { TwitchAccountConfig, TwitchChatMessage } from "./types.js";
import { checkTwitchAccessControl } from "./access-control.js";
import { getTwitchRuntime } from "./runtime.js";
@@ -20,7 +20,7 @@ export type TwitchRuntimeEnv = {
export type TwitchMonitorOptions = {
account: TwitchAccountConfig;
accountId: string;
config: unknown; // ClawdbotConfig
config: unknown; // MoltbotConfig
runtime: TwitchRuntimeEnv;
abortSignal: AbortSignal;
statusSink?: (patch: { lastInboundAt?: number; lastOutboundAt?: number }) => void;
@@ -45,7 +45,7 @@ async function processTwitchMessage(params: {
statusSink?: (patch: { lastInboundAt?: number; lastOutboundAt?: number }) => void;
}): Promise<void> {
const { message, account, accountId, config, runtime, core, statusSink } = params;
const cfg = config as ClawdbotConfig;
const cfg = config as MoltbotConfig;
const route = core.channel.routing.resolveAgentRoute({
cfg,

View File

@@ -12,7 +12,7 @@ import {
import { DEFAULT_ACCOUNT_ID, getAccountConfig } from "./config.js";
import { isAccountConfigured } from "./utils/twitch.js";
import type { TwitchAccountConfig, TwitchRole } from "./types.js";
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
const channel = "twitch" as const;
@@ -20,9 +20,9 @@ const channel = "twitch" as const;
* Set Twitch account configuration
*/
function setTwitchAccount(
cfg: ClawdbotConfig,
cfg: MoltbotConfig,
account: Partial<TwitchAccountConfig>,
): ClawdbotConfig {
): MoltbotConfig {
const existing = getAccountConfig(cfg, DEFAULT_ACCOUNT_ID);
const merged: TwitchAccountConfig = {
username: account.username ?? existing?.username ?? "",
@@ -205,13 +205,13 @@ async function promptRefreshTokenSetup(
* Configure with env token path (returns early if user chooses env token).
*/
async function configureWithEnvToken(
cfg: ClawdbotConfig,
cfg: MoltbotConfig,
prompter: WizardPrompter,
account: TwitchAccountConfig | null,
envToken: string,
forceAllowFrom: boolean,
dmPolicy: ChannelOnboardingDmPolicy,
): Promise<{ cfg: ClawdbotConfig } | null> {
): Promise<{ cfg: MoltbotConfig } | null> {
const useEnv = await prompter.confirm({
message: "Twitch env var CLAWDBOT_TWITCH_ACCESS_TOKEN detected. Use env token?",
initialValue: true,
@@ -241,10 +241,10 @@ async function configureWithEnvToken(
* Set Twitch access control (role-based)
*/
function setTwitchAccessControl(
cfg: ClawdbotConfig,
cfg: MoltbotConfig,
allowedRoles: TwitchRole[],
requireMention: boolean,
): ClawdbotConfig {
): MoltbotConfig {
const account = getAccountConfig(cfg, DEFAULT_ACCOUNT_ID);
if (!account) {
return cfg;
@@ -272,7 +272,7 @@ const dmPolicy: ChannelOnboardingDmPolicy = {
setPolicy: (cfg, policy) => {
const allowedRoles: TwitchRole[] =
policy === "open" ? ["all"] : policy === "allowlist" ? [] : ["moderator"];
return setTwitchAccessControl(cfg as ClawdbotConfig, allowedRoles, true);
return setTwitchAccessControl(cfg as MoltbotConfig, allowedRoles, true);
},
promptAllowFrom: async ({ cfg, prompter }) => {
const account = getAccountConfig(cfg, DEFAULT_ACCOUNT_ID);
@@ -289,7 +289,7 @@ const dmPolicy: ChannelOnboardingDmPolicy = {
.map((s) => s.trim())
.filter(Boolean);
return setTwitchAccount(cfg as ClawdbotConfig, {
return setTwitchAccount(cfg as MoltbotConfig, {
...(account ?? undefined),
allowFrom,
});

View File

@@ -11,7 +11,7 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { twitchOutbound } from "./outbound.js";
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
// Mock dependencies
vi.mock("./config.js", () => ({
@@ -49,7 +49,7 @@ describe("outbound", () => {
},
},
},
} as unknown as ClawdbotConfig;
} as unknown as MoltbotConfig;
beforeEach(() => {
vi.clearAllMocks();

View File

@@ -99,7 +99,7 @@ export const twitchOutbound: ChannelOutboundAdapter = {
*
* @example
* const result = await twitchOutbound.sendText({
* cfg: clawdbotConfig,
* cfg: moltbotConfig,
* to: "#mychannel",
* text: "Hello Twitch!",
* accountId: "default",
@@ -159,7 +159,7 @@ export const twitchOutbound: ChannelOutboundAdapter = {
*
* @example
* const result = await twitchOutbound.sendMedia({
* cfg: clawdbotConfig,
* cfg: moltbotConfig,
* to: "#mychannel",
* text: "Check this out!",
* mediaUrl: "https://example.com/image.png",

View File

@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
import { twitchPlugin } from "./plugin.js";
describe("twitchPlugin.status.buildAccountSnapshot", () => {
@@ -27,7 +27,7 @@ describe("twitchPlugin.status.buildAccountSnapshot", () => {
},
},
},
} as ClawdbotConfig;
} as MoltbotConfig;
const snapshot = await twitchPlugin.status?.buildAccountSnapshot?.({
account: secondary,

View File

@@ -1,11 +1,11 @@
/**
* Twitch channel plugin for Clawdbot.
* Twitch channel plugin for Moltbot.
*
* Main plugin export combining all adapters (outbound, actions, status, gateway).
* This is the primary entry point for the Twitch channel integration.
*/
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
import { buildChannelConfigSchema } from "clawdbot/plugin-sdk";
import { twitchMessageActions } from "./actions.js";
import { TwitchConfigSchema } from "./config-schema.js";
@@ -33,7 +33,7 @@ import type {
* Twitch channel plugin.
*
* Implements the ChannelPlugin interface to provide Twitch chat integration
* for Clawdbot. Supports message sending, receiving, access control, and
* for Moltbot. Supports message sending, receiving, access control, and
* status monitoring.
*/
export const twitchPlugin: ChannelPlugin<TwitchAccountConfig> = {
@@ -75,10 +75,10 @@ export const twitchPlugin: ChannelPlugin<TwitchAccountConfig> = {
/** Account configuration management */
config: {
/** List all configured account IDs */
listAccountIds: (cfg: ClawdbotConfig): string[] => listAccountIds(cfg),
listAccountIds: (cfg: MoltbotConfig): string[] => listAccountIds(cfg),
/** Resolve an account config by ID */
resolveAccount: (cfg: ClawdbotConfig, accountId?: string | null): TwitchAccountConfig => {
resolveAccount: (cfg: MoltbotConfig, accountId?: string | null): TwitchAccountConfig => {
const account = getAccountConfig(cfg, accountId ?? DEFAULT_ACCOUNT_ID);
if (!account) {
// Return a default/empty account if not configured
@@ -96,7 +96,7 @@ export const twitchPlugin: ChannelPlugin<TwitchAccountConfig> = {
defaultAccountId: (): string => DEFAULT_ACCOUNT_ID,
/** Check if an account is configured */
isConfigured: (_account: unknown, cfg: ClawdbotConfig): boolean => {
isConfigured: (_account: unknown, cfg: MoltbotConfig): boolean => {
const account = getAccountConfig(cfg, DEFAULT_ACCOUNT_ID);
const tokenResolution = resolveTwitchToken(cfg, { accountId: DEFAULT_ACCOUNT_ID });
return account ? isAccountConfigured(account, tokenResolution.token) : false;
@@ -130,7 +130,7 @@ export const twitchPlugin: ChannelPlugin<TwitchAccountConfig> = {
kind,
runtime,
}: {
cfg: ClawdbotConfig;
cfg: MoltbotConfig;
accountId?: string | null;
inputs: string[];
kind: ChannelResolveKind;
@@ -198,7 +198,7 @@ export const twitchPlugin: ChannelPlugin<TwitchAccountConfig> = {
probe,
}: {
account: TwitchAccountConfig;
cfg: ClawdbotConfig;
cfg: MoltbotConfig;
runtime?: ChannelAccountSnapshot;
probe?: unknown;
}): ChannelAccountSnapshot => {

View File

@@ -12,7 +12,7 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { sendMessageTwitchInternal } from "./send.js";
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
// Mock dependencies
vi.mock("./config.js", () => ({
@@ -57,7 +57,7 @@ describe("send", () => {
},
},
},
} as unknown as ClawdbotConfig;
} as unknown as MoltbotConfig;
beforeEach(() => {
vi.clearAllMocks();

View File

@@ -7,7 +7,7 @@
import { DEFAULT_ACCOUNT_ID, getAccountConfig } from "./config.js";
import { getClientManager as getRegistryClientManager } from "./client-manager-registry.js";
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
import { resolveTwitchToken } from "./token.js";
import { stripMarkdownForTwitch } from "./utils/markdown.js";
import { generateMessageId, isAccountConfigured, normalizeTwitchChannel } from "./utils/twitch.js";
@@ -27,12 +27,12 @@ export interface SendMessageResult {
/**
* Internal send function used by the outbound adapter.
*
* This function has access to the full Clawdbot config and handles
* This function has access to the full Moltbot config and handles
* account resolution, markdown stripping, and actual message sending.
*
* @param channel - The channel name
* @param text - The message text
* @param cfg - Full Clawdbot configuration
* @param cfg - Full Moltbot configuration
* @param accountId - Account ID to use
* @param stripMarkdown - Whether to strip markdown (default: true)
* @param logger - Logger instance
@@ -42,7 +42,7 @@ export interface SendMessageResult {
* const result = await sendMessageTwitchInternal(
* "#mychannel",
* "Hello Twitch!",
* clawdbotConfig,
* moltbotConfig,
* "default",
* true,
* console,
@@ -51,7 +51,7 @@ export interface SendMessageResult {
export async function sendMessageTwitchInternal(
channel: string,
text: string,
cfg: ClawdbotConfig,
cfg: MoltbotConfig,
accountId: string = DEFAULT_ACCOUNT_ID,
stripMarkdown: boolean = true,
logger: Console = console,

View File

@@ -10,7 +10,7 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { resolveTwitchToken, type TwitchTokenSource } from "./token.js";
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
describe("token", () => {
// Multi-account config for testing non-default accounts
@@ -29,7 +29,7 @@ describe("token", () => {
},
},
},
} as unknown as ClawdbotConfig;
} as unknown as MoltbotConfig;
// Simplified single-account config
const mockSimplifiedConfig = {
@@ -39,7 +39,7 @@ describe("token", () => {
accessToken: "oauth:config-token",
},
},
} as unknown as ClawdbotConfig;
} as unknown as MoltbotConfig;
beforeEach(() => {
vi.clearAllMocks();
@@ -85,7 +85,7 @@ describe("token", () => {
accessToken: "",
},
},
} as unknown as ClawdbotConfig;
} as unknown as MoltbotConfig;
const result = resolveTwitchToken(configWithEmptyToken, { accountId: "default" });
@@ -101,7 +101,7 @@ describe("token", () => {
accessToken: "",
},
},
} as unknown as ClawdbotConfig;
} as unknown as MoltbotConfig;
const result = resolveTwitchToken(configWithoutToken, { accountId: "default" });
@@ -123,7 +123,7 @@ describe("token", () => {
},
},
},
} as unknown as ClawdbotConfig;
} as unknown as MoltbotConfig;
const result = resolveTwitchToken(configWithoutToken, { accountId: "secondary" });
@@ -139,7 +139,7 @@ describe("token", () => {
accounts: {},
},
},
} as unknown as ClawdbotConfig;
} as unknown as MoltbotConfig;
const result = resolveTwitchToken(configWithoutAccount, { accountId: "nonexistent" });
@@ -150,7 +150,7 @@ describe("token", () => {
it("should handle missing Twitch config section", () => {
const configWithoutSection = {
channels: {},
} as unknown as ClawdbotConfig;
} as unknown as MoltbotConfig;
const result = resolveTwitchToken(configWithoutSection, { accountId: "default" });

View File

@@ -9,7 +9,7 @@
* 2. Environment variable: CLAWDBOT_TWITCH_ACCESS_TOKEN (default account only)
*/
import type { ClawdbotConfig } from "../../../src/config/config.js";
import type { MoltbotConfig } from "../../../src/config/config.js";
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../../src/routing/session-key.js";
export type TwitchTokenSource = "env" | "config" | "none";
@@ -40,12 +40,12 @@ function normalizeTwitchToken(raw?: string | null): string | undefined {
* The getAccountConfig function handles merging base-level config with accounts.default,
* so this logic works for both simplified and multi-account patterns.
*
* @param cfg - Clawdbot config
* @param cfg - Moltbot config
* @param opts - Options including accountId and optional envToken override
* @returns Token resolution with source
*/
export function resolveTwitchToken(
cfg?: ClawdbotConfig,
cfg?: MoltbotConfig,
opts: { accountId?: string | null; envToken?: string | null } = {},
): TwitchTokenResolution {
const accountId = normalizeAccountId(opts.accountId);

View File

@@ -1,6 +1,6 @@
import { RefreshingAuthProvider, StaticAuthProvider } from "@twurple/auth";
import { ChatClient, LogLevel } from "@twurple/chat";
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
import type { ChannelLogSink, TwitchAccountConfig, TwitchChatMessage } from "./types.js";
import { resolveTwitchToken } from "./token.js";
import { normalizeToken } from "./utils/twitch.js";
@@ -76,7 +76,7 @@ export class TwitchClientManager {
*/
async getClient(
account: TwitchAccountConfig,
cfg?: ClawdbotConfig,
cfg?: MoltbotConfig,
accountId?: string,
): Promise<ChatClient> {
const key = this.getAccountKey(account);
@@ -236,7 +236,7 @@ export class TwitchClientManager {
account: TwitchAccountConfig,
channel: string,
message: string,
cfg?: ClawdbotConfig,
cfg?: MoltbotConfig,
accountId?: string,
): Promise<{ ok: boolean; error?: string; messageId?: string }> {
try {

View File

@@ -2,7 +2,7 @@
* Twitch channel plugin types.
*
* This file defines Twitch-specific types. Generic channel types are imported
* from Clawdbot core.
* from Moltbot core.
*/
import type {
@@ -22,7 +22,7 @@ import type {
ChannelResolveResult,
ChannelStatusAdapter,
} from "../../../src/channels/plugins/types.adapters.js";
import type { ClawdbotConfig } from "../../../src/config/config.js";
import type { MoltbotConfig } from "../../../src/config/config.js";
import type { OutboundDeliveryResult } from "../../../src/infra/outbound/deliver.js";
import type { RuntimeEnv } from "../../../src/runtime.js";
@@ -137,5 +137,5 @@ import type { TwitchConfigSchema } from "./config-schema.js";
import type { z } from "zod";
export type TwitchConfig = z.infer<typeof TwitchConfigSchema>;
export type { ClawdbotConfig };
export type { MoltbotConfig };
export type { RuntimeEnv };

View File

@@ -2,7 +2,7 @@
* Markdown utilities for Twitch chat
*
* Twitch chat doesn't support markdown formatting, so we strip it before sending.
* Based on Clawdbot's markdownToText in src/agents/tools/web-fetch-utils.ts.
* Based on Moltbot's markdownToText in src/agents/tools/web-fetch-utils.ts.
*/
/**