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

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

View File

@@ -1,4 +1,4 @@
import { MarkdownConfigSchema } from "clawdbot/plugin-sdk";
import { MarkdownConfigSchema } from "openclaw/plugin-sdk";
import { z } from "zod";
/**

View File

@@ -1,4 +1,4 @@
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
import type { OpenClawConfig } from "openclaw/plugin-sdk";
import type { TwitchAccountConfig } from "./types.js";
/**
@@ -24,7 +24,7 @@ export function getAccountConfig(
return null;
}
const cfg = coreConfig as MoltbotConfig;
const cfg = coreConfig as OpenClawConfig;
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: MoltbotConfig): string[] {
export function listAccountIds(cfg: OpenClawConfig): 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, MoltbotConfig } from "clawdbot/plugin-sdk";
import type { ReplyPayload, OpenClawConfig } from "openclaw/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; // MoltbotConfig
config: unknown; // OpenClawConfig
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 MoltbotConfig;
const cfg = config as OpenClawConfig;
const route = core.channel.routing.resolveAgentRoute({
cfg,

View File

@@ -12,7 +12,7 @@
*/
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { WizardPrompter } from "clawdbot/plugin-sdk";
import type { WizardPrompter } from "openclaw/plugin-sdk";
import type { TwitchAccountConfig } from "./types.js";
// Mock the helpers we're testing

View File

@@ -8,11 +8,11 @@ import {
type ChannelOnboardingAdapter,
type ChannelOnboardingDmPolicy,
type WizardPrompter,
} from "clawdbot/plugin-sdk";
} from "openclaw/plugin-sdk";
import { DEFAULT_ACCOUNT_ID, getAccountConfig } from "./config.js";
import { isAccountConfigured } from "./utils/twitch.js";
import type { TwitchAccountConfig, TwitchRole } from "./types.js";
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
import type { OpenClawConfig } from "openclaw/plugin-sdk";
const channel = "twitch" as const;
@@ -20,9 +20,9 @@ const channel = "twitch" as const;
* Set Twitch account configuration
*/
function setTwitchAccount(
cfg: MoltbotConfig,
cfg: OpenClawConfig,
account: Partial<TwitchAccountConfig>,
): MoltbotConfig {
): OpenClawConfig {
const existing = getAccountConfig(cfg, DEFAULT_ACCOUNT_ID);
const merged: TwitchAccountConfig = {
username: account.username ?? existing?.username ?? "",
@@ -70,7 +70,7 @@ async function noteTwitchSetupHelp(prompter: WizardPrompter): Promise<void> {
"2. Generate a token with scopes: chat:read and chat:write",
" Use https://twitchtokengenerator.com/ or https://twitchapps.com/tmi/",
"3. Copy the token (starts with 'oauth:') and Client ID",
"Env vars supported: CLAWDBOT_TWITCH_ACCESS_TOKEN",
"Env vars supported: OPENCLAW_TWITCH_ACCESS_TOKEN",
`Docs: ${formatDocsLink("/channels/twitch", "channels/twitch")}`,
].join("\n"),
"Twitch setup",
@@ -205,15 +205,15 @@ async function promptRefreshTokenSetup(
* Configure with env token path (returns early if user chooses env token).
*/
async function configureWithEnvToken(
cfg: MoltbotConfig,
cfg: OpenClawConfig,
prompter: WizardPrompter,
account: TwitchAccountConfig | null,
envToken: string,
forceAllowFrom: boolean,
dmPolicy: ChannelOnboardingDmPolicy,
): Promise<{ cfg: MoltbotConfig } | null> {
): Promise<{ cfg: OpenClawConfig } | null> {
const useEnv = await prompter.confirm({
message: "Twitch env var CLAWDBOT_TWITCH_ACCESS_TOKEN detected. Use env token?",
message: "Twitch env var OPENCLAW_TWITCH_ACCESS_TOKEN detected. Use env token?",
initialValue: true,
});
if (!useEnv) {
@@ -241,10 +241,10 @@ async function configureWithEnvToken(
* Set Twitch access control (role-based)
*/
function setTwitchAccessControl(
cfg: MoltbotConfig,
cfg: OpenClawConfig,
allowedRoles: TwitchRole[],
requireMention: boolean,
): MoltbotConfig {
): OpenClawConfig {
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 MoltbotConfig, allowedRoles, true);
return setTwitchAccessControl(cfg as OpenClawConfig, 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 MoltbotConfig, {
return setTwitchAccount(cfg as OpenClawConfig, {
...(account ?? undefined),
allowFrom,
});
@@ -316,7 +316,7 @@ export const twitchOnboardingAdapter: ChannelOnboardingAdapter = {
await noteTwitchSetupHelp(prompter);
}
const envToken = process.env.CLAWDBOT_TWITCH_ACCESS_TOKEN?.trim();
const envToken = process.env.OPENCLAW_TWITCH_ACCESS_TOKEN?.trim();
// Check if env var is set and config is empty
if (envToken && !account?.accessToken) {

View File

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

View File

@@ -99,7 +99,7 @@ export const twitchOutbound: ChannelOutboundAdapter = {
*
* @example
* const result = await twitchOutbound.sendText({
* cfg: moltbotConfig,
* cfg: openclawConfig,
* to: "#mychannel",
* text: "Hello Twitch!",
* accountId: "default",
@@ -159,7 +159,7 @@ export const twitchOutbound: ChannelOutboundAdapter = {
*
* @example
* const result = await twitchOutbound.sendMedia({
* cfg: moltbotConfig,
* cfg: openclawConfig,
* 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 { MoltbotConfig } from "clawdbot/plugin-sdk";
import type { OpenClawConfig } from "openclaw/plugin-sdk";
import { twitchPlugin } from "./plugin.js";
describe("twitchPlugin.status.buildAccountSnapshot", () => {
@@ -27,7 +27,7 @@ describe("twitchPlugin.status.buildAccountSnapshot", () => {
},
},
},
} as MoltbotConfig;
} as OpenClawConfig;
const snapshot = await twitchPlugin.status?.buildAccountSnapshot?.({
account: secondary,

View File

@@ -1,12 +1,12 @@
/**
* Twitch channel plugin for Moltbot.
* Twitch channel plugin for OpenClaw.
*
* Main plugin export combining all adapters (outbound, actions, status, gateway).
* This is the primary entry point for the Twitch channel integration.
*/
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
import { buildChannelConfigSchema } from "clawdbot/plugin-sdk";
import type { OpenClawConfig } from "openclaw/plugin-sdk";
import { buildChannelConfigSchema } from "openclaw/plugin-sdk";
import { twitchMessageActions } from "./actions.js";
import { TwitchConfigSchema } from "./config-schema.js";
import { DEFAULT_ACCOUNT_ID, getAccountConfig, listAccountIds } from "./config.js";
@@ -33,7 +33,7 @@ import type {
* Twitch channel plugin.
*
* Implements the ChannelPlugin interface to provide Twitch chat integration
* for Moltbot. Supports message sending, receiving, access control, and
* for OpenClaw. 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: MoltbotConfig): string[] => listAccountIds(cfg),
listAccountIds: (cfg: OpenClawConfig): string[] => listAccountIds(cfg),
/** Resolve an account config by ID */
resolveAccount: (cfg: MoltbotConfig, accountId?: string | null): TwitchAccountConfig => {
resolveAccount: (cfg: OpenClawConfig, 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: MoltbotConfig): boolean => {
isConfigured: (_account: unknown, cfg: OpenClawConfig): 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: MoltbotConfig;
cfg: OpenClawConfig;
accountId?: string | null;
inputs: string[];
kind: ChannelResolveKind;
@@ -198,7 +198,7 @@ export const twitchPlugin: ChannelPlugin<TwitchAccountConfig> = {
probe,
}: {
account: TwitchAccountConfig;
cfg: MoltbotConfig;
cfg: OpenClawConfig;
runtime?: ChannelAccountSnapshot;
probe?: unknown;
}): ChannelAccountSnapshot => {

View File

@@ -1,4 +1,4 @@
import type { PluginRuntime } from "clawdbot/plugin-sdk";
import type { PluginRuntime } from "openclaw/plugin-sdk";
let runtime: PluginRuntime | null = null;

View File

@@ -12,7 +12,7 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { sendMessageTwitchInternal } from "./send.js";
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
import type { OpenClawConfig } from "openclaw/plugin-sdk";
// Mock dependencies
vi.mock("./config.js", () => ({
@@ -57,7 +57,7 @@ describe("send", () => {
},
},
},
} as unknown as MoltbotConfig;
} as unknown as OpenClawConfig;
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 { MoltbotConfig } from "clawdbot/plugin-sdk";
import type { OpenClawConfig } from "openclaw/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 Moltbot config and handles
* This function has access to the full OpenClaw config and handles
* account resolution, markdown stripping, and actual message sending.
*
* @param channel - The channel name
* @param text - The message text
* @param cfg - Full Moltbot configuration
* @param cfg - Full OpenClaw 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!",
* moltbotConfig,
* openclawConfig,
* "default",
* true,
* console,
@@ -51,7 +51,7 @@ export interface SendMessageResult {
export async function sendMessageTwitchInternal(
channel: string,
text: string,
cfg: MoltbotConfig,
cfg: OpenClawConfig,
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 { MoltbotConfig } from "clawdbot/plugin-sdk";
import type { OpenClawConfig } from "openclaw/plugin-sdk";
describe("token", () => {
// Multi-account config for testing non-default accounts
@@ -29,7 +29,7 @@ describe("token", () => {
},
},
},
} as unknown as MoltbotConfig;
} as unknown as OpenClawConfig;
// Simplified single-account config
const mockSimplifiedConfig = {
@@ -39,7 +39,7 @@ describe("token", () => {
accessToken: "oauth:config-token",
},
},
} as unknown as MoltbotConfig;
} as unknown as OpenClawConfig;
beforeEach(() => {
vi.clearAllMocks();
@@ -47,7 +47,7 @@ describe("token", () => {
afterEach(() => {
vi.restoreAllMocks();
delete process.env.CLAWDBOT_TWITCH_ACCESS_TOKEN;
delete process.env.OPENCLAW_TWITCH_ACCESS_TOKEN;
});
describe("resolveTwitchToken", () => {
@@ -66,7 +66,7 @@ describe("token", () => {
});
it("should prioritize config token over env var (simplified config)", () => {
process.env.CLAWDBOT_TWITCH_ACCESS_TOKEN = "oauth:env-token";
process.env.OPENCLAW_TWITCH_ACCESS_TOKEN = "oauth:env-token";
const result = resolveTwitchToken(mockSimplifiedConfig, { accountId: "default" });
@@ -76,7 +76,7 @@ describe("token", () => {
});
it("should use env var when config token is empty (simplified config)", () => {
process.env.CLAWDBOT_TWITCH_ACCESS_TOKEN = "oauth:env-token";
process.env.OPENCLAW_TWITCH_ACCESS_TOKEN = "oauth:env-token";
const configWithEmptyToken = {
channels: {
@@ -85,7 +85,7 @@ describe("token", () => {
accessToken: "",
},
},
} as unknown as MoltbotConfig;
} as unknown as OpenClawConfig;
const result = resolveTwitchToken(configWithEmptyToken, { accountId: "default" });
@@ -101,7 +101,7 @@ describe("token", () => {
accessToken: "",
},
},
} as unknown as MoltbotConfig;
} as unknown as OpenClawConfig;
const result = resolveTwitchToken(configWithoutToken, { accountId: "default" });
@@ -110,7 +110,7 @@ describe("token", () => {
});
it("should not use env var for non-default accounts (multi-account)", () => {
process.env.CLAWDBOT_TWITCH_ACCESS_TOKEN = "oauth:env-token";
process.env.OPENCLAW_TWITCH_ACCESS_TOKEN = "oauth:env-token";
const configWithoutToken = {
channels: {
@@ -123,7 +123,7 @@ describe("token", () => {
},
},
},
} as unknown as MoltbotConfig;
} as unknown as OpenClawConfig;
const result = resolveTwitchToken(configWithoutToken, { accountId: "secondary" });
@@ -139,7 +139,7 @@ describe("token", () => {
accounts: {},
},
},
} as unknown as MoltbotConfig;
} as unknown as OpenClawConfig;
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 MoltbotConfig;
} as unknown as OpenClawConfig;
const result = resolveTwitchToken(configWithoutSection, { accountId: "default" });

View File

@@ -2,14 +2,14 @@
* Twitch access token resolution with environment variable support.
*
* Supports reading Twitch OAuth access tokens from config or environment variable.
* The CLAWDBOT_TWITCH_ACCESS_TOKEN env var is only used for the default account.
* The OPENCLAW_TWITCH_ACCESS_TOKEN env var is only used for the default account.
*
* Token resolution priority:
* 1. Account access token from merged config (accounts.{id} or base-level for default)
* 2. Environment variable: CLAWDBOT_TWITCH_ACCESS_TOKEN (default account only)
* 2. Environment variable: OPENCLAW_TWITCH_ACCESS_TOKEN (default account only)
*/
import type { MoltbotConfig } from "../../../src/config/config.js";
import type { OpenClawConfig } from "../../../src/config/config.js";
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "../../../src/routing/session-key.js";
export type TwitchTokenSource = "env" | "config" | "none";
@@ -35,17 +35,17 @@ function normalizeTwitchToken(raw?: string | null): string | undefined {
*
* Priority:
* 1. Account access token (from merged config - base-level for default, or accounts.{accountId})
* 2. Environment variable: CLAWDBOT_TWITCH_ACCESS_TOKEN (default account only)
* 2. Environment variable: OPENCLAW_TWITCH_ACCESS_TOKEN (default account only)
*
* The getAccountConfig function handles merging base-level config with accounts.default,
* so this logic works for both simplified and multi-account patterns.
*
* @param cfg - Moltbot config
* @param cfg - OpenClaw config
* @param opts - Options including accountId and optional envToken override
* @returns Token resolution with source
*/
export function resolveTwitchToken(
cfg?: MoltbotConfig,
cfg?: OpenClawConfig,
opts: { accountId?: string | null; envToken?: string | null } = {},
): TwitchTokenResolution {
const accountId = normalizeAccountId(opts.accountId);
@@ -77,7 +77,7 @@ export function resolveTwitchToken(
// Environment variable (default account only)
const allowEnv = accountId === DEFAULT_ACCOUNT_ID;
const envToken = allowEnv
? normalizeTwitchToken(opts.envToken ?? process.env.CLAWDBOT_TWITCH_ACCESS_TOKEN)
? normalizeTwitchToken(opts.envToken ?? process.env.OPENCLAW_TWITCH_ACCESS_TOKEN)
: undefined;
if (envToken) {
return { token: envToken, source: "env" };

View File

@@ -1,6 +1,6 @@
import { RefreshingAuthProvider, StaticAuthProvider } from "@twurple/auth";
import { ChatClient, LogLevel } from "@twurple/chat";
import type { MoltbotConfig } from "clawdbot/plugin-sdk";
import type { OpenClawConfig } from "openclaw/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?: MoltbotConfig,
cfg?: OpenClawConfig,
accountId?: string,
): Promise<ChatClient> {
const key = this.getAccountKey(account);
@@ -92,7 +92,7 @@ export class TwitchClientManager {
if (!tokenResolution.token) {
this.logger.error(
`Missing Twitch token for account ${account.username} (set channels.twitch.accounts.${account.username}.token or CLAWDBOT_TWITCH_ACCESS_TOKEN for default)`,
`Missing Twitch token for account ${account.username} (set channels.twitch.accounts.${account.username}.token or OPENCLAW_TWITCH_ACCESS_TOKEN for default)`,
);
throw new Error("Missing Twitch token");
}
@@ -236,7 +236,7 @@ export class TwitchClientManager {
account: TwitchAccountConfig,
channel: string,
message: string,
cfg?: MoltbotConfig,
cfg?: OpenClawConfig,
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 Moltbot core.
* from OpenClaw core.
*/
import type {
@@ -22,7 +22,7 @@ import type {
ChannelResolveResult,
ChannelStatusAdapter,
} from "../../../src/channels/plugins/types.adapters.js";
import type { MoltbotConfig } from "../../../src/config/config.js";
import type { OpenClawConfig } 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 { MoltbotConfig };
export type { OpenClawConfig };
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 Moltbot's markdownToText in src/agents/tools/web-fetch-utils.ts.
* Based on OpenClaw's markdownToText in src/agents/tools/web-fetch-utils.ts.
*/
/**