mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-07 18:01:23 +00:00
refactor: rename to openclaw
This commit is contained in:
@@ -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",
|
||||
* });
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MarkdownConfigSchema } from "clawdbot/plugin-sdk";
|
||||
import { MarkdownConfigSchema } from "openclaw/plugin-sdk";
|
||||
import { z } from "zod";
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { PluginRuntime } from "clawdbot/plugin-sdk";
|
||||
import type { PluginRuntime } from "openclaw/plugin-sdk";
|
||||
|
||||
let runtime: PluginRuntime | null = null;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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" });
|
||||
|
||||
|
||||
@@ -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" };
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user