openskynet / src /channels /plugins /types.adapters.ts
Darochin's picture
Mirror OpenSkyNet workspace snapshot from Git HEAD
fc93158 verified
import type { ReplyPayload } from "../../auto-reply/types.js";
import type { OpenClawConfig } from "../../config/config.js";
import type { GroupToolPolicyConfig } from "../../config/types.tools.js";
import type { OutboundDeliveryResult, OutboundSendDeps } from "../../infra/outbound/deliver.js";
import type { OutboundIdentity } from "../../infra/outbound/identity.js";
import type { PluginRuntime } from "../../plugins/runtime/types.js";
import type { RuntimeEnv } from "../../runtime.js";
import type {
ChannelAccountSnapshot,
ChannelAccountState,
ChannelDirectoryEntry,
ChannelGroupContext,
ChannelHeartbeatDeps,
ChannelLogSink,
ChannelOutboundTargetMode,
ChannelPollContext,
ChannelPollResult,
ChannelSecurityContext,
ChannelSecurityDmPolicy,
ChannelSetupInput,
ChannelStatusIssue,
} from "./types.core.js";
export type ChannelSetupAdapter = {
resolveAccountId?: (params: {
cfg: OpenClawConfig;
accountId?: string;
input?: ChannelSetupInput;
}) => string;
resolveBindingAccountId?: (params: {
cfg: OpenClawConfig;
agentId: string;
accountId?: string;
}) => string | undefined;
applyAccountName?: (params: {
cfg: OpenClawConfig;
accountId: string;
name?: string;
}) => OpenClawConfig;
applyAccountConfig: (params: {
cfg: OpenClawConfig;
accountId: string;
input: ChannelSetupInput;
}) => OpenClawConfig;
validateInput?: (params: {
cfg: OpenClawConfig;
accountId: string;
input: ChannelSetupInput;
}) => string | null;
};
export type ChannelConfigAdapter<ResolvedAccount> = {
listAccountIds: (cfg: OpenClawConfig) => string[];
resolveAccount: (cfg: OpenClawConfig, accountId?: string | null) => ResolvedAccount;
inspectAccount?: (cfg: OpenClawConfig, accountId?: string | null) => unknown;
defaultAccountId?: (cfg: OpenClawConfig) => string;
setAccountEnabled?: (params: {
cfg: OpenClawConfig;
accountId: string;
enabled: boolean;
}) => OpenClawConfig;
deleteAccount?: (params: { cfg: OpenClawConfig; accountId: string }) => OpenClawConfig;
isEnabled?: (account: ResolvedAccount, cfg: OpenClawConfig) => boolean;
disabledReason?: (account: ResolvedAccount, cfg: OpenClawConfig) => string;
isConfigured?: (account: ResolvedAccount, cfg: OpenClawConfig) => boolean | Promise<boolean>;
unconfiguredReason?: (account: ResolvedAccount, cfg: OpenClawConfig) => string;
describeAccount?: (account: ResolvedAccount, cfg: OpenClawConfig) => ChannelAccountSnapshot;
resolveAllowFrom?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
}) => Array<string | number> | undefined;
formatAllowFrom?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
allowFrom: Array<string | number>;
}) => string[];
resolveDefaultTo?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
}) => string | undefined;
};
export type ChannelGroupAdapter = {
resolveRequireMention?: (params: ChannelGroupContext) => boolean | undefined;
resolveGroupIntroHint?: (params: ChannelGroupContext) => string | undefined;
resolveToolPolicy?: (params: ChannelGroupContext) => GroupToolPolicyConfig | undefined;
};
export type ChannelOutboundContext = {
cfg: OpenClawConfig;
to: string;
text: string;
mediaUrl?: string;
mediaLocalRoots?: readonly string[];
gifPlayback?: boolean;
replyToId?: string | null;
threadId?: string | number | null;
accountId?: string | null;
identity?: OutboundIdentity;
deps?: OutboundSendDeps;
silent?: boolean;
};
export type ChannelOutboundPayloadContext = ChannelOutboundContext & {
payload: ReplyPayload;
};
export type ChannelOutboundAdapter = {
deliveryMode: "direct" | "gateway" | "hybrid";
chunker?: ((text: string, limit: number) => string[]) | null;
chunkerMode?: "text" | "markdown";
textChunkLimit?: number;
pollMaxOptions?: number;
resolveTarget?: (params: {
cfg?: OpenClawConfig;
to?: string;
allowFrom?: string[];
accountId?: string | null;
mode?: ChannelOutboundTargetMode;
}) => { ok: true; to: string } | { ok: false; error: Error };
sendPayload?: (ctx: ChannelOutboundPayloadContext) => Promise<OutboundDeliveryResult>;
sendText?: (ctx: ChannelOutboundContext) => Promise<OutboundDeliveryResult>;
sendMedia?: (ctx: ChannelOutboundContext) => Promise<OutboundDeliveryResult>;
sendPoll?: (ctx: ChannelPollContext) => Promise<ChannelPollResult>;
};
export type ChannelStatusAdapter<ResolvedAccount, Probe = unknown, Audit = unknown> = {
defaultRuntime?: ChannelAccountSnapshot;
buildChannelSummary?: (params: {
account: ResolvedAccount;
cfg: OpenClawConfig;
defaultAccountId: string;
snapshot: ChannelAccountSnapshot;
}) => Record<string, unknown> | Promise<Record<string, unknown>>;
probeAccount?: (params: {
account: ResolvedAccount;
timeoutMs: number;
cfg: OpenClawConfig;
}) => Promise<Probe>;
auditAccount?: (params: {
account: ResolvedAccount;
timeoutMs: number;
cfg: OpenClawConfig;
probe?: Probe;
}) => Promise<Audit>;
buildAccountSnapshot?: (params: {
account: ResolvedAccount;
cfg: OpenClawConfig;
runtime?: ChannelAccountSnapshot;
probe?: Probe;
audit?: Audit;
}) => ChannelAccountSnapshot | Promise<ChannelAccountSnapshot>;
logSelfId?: (params: {
account: ResolvedAccount;
cfg: OpenClawConfig;
runtime: RuntimeEnv;
includeChannelPrefix?: boolean;
}) => void;
resolveAccountState?: (params: {
account: ResolvedAccount;
cfg: OpenClawConfig;
configured: boolean;
enabled: boolean;
}) => ChannelAccountState;
collectStatusIssues?: (accounts: ChannelAccountSnapshot[]) => ChannelStatusIssue[];
};
export type ChannelGatewayContext<ResolvedAccount = unknown> = {
cfg: OpenClawConfig;
accountId: string;
account: ResolvedAccount;
runtime: RuntimeEnv;
abortSignal: AbortSignal;
log?: ChannelLogSink;
getStatus: () => ChannelAccountSnapshot;
setStatus: (next: ChannelAccountSnapshot) => void;
/**
* Optional channel runtime helpers for external channel plugins.
*
* This field provides access to advanced Plugin SDK features that are
* available to external plugins but not to built-in channels (which can
* directly import internal modules).
*
* ## Available Features
*
* - **reply**: AI response dispatching, formatting, and delivery
* - **routing**: Agent route resolution and matching
* - **text**: Text chunking, markdown processing, and control command detection
* - **session**: Session management and metadata tracking
* - **media**: Remote media fetching and buffer saving
* - **commands**: Command authorization and control command handling
* - **groups**: Group policy resolution and mention requirements
* - **pairing**: Channel pairing and allow-from management
*
* ## Use Cases
*
* External channel plugins (e.g., email, SMS, custom integrations) that need:
* - AI-powered response generation and delivery
* - Advanced text processing and formatting
* - Session tracking and management
* - Agent routing and policy resolution
*
* ## Example
*
* ```typescript
* const emailGatewayAdapter: ChannelGatewayAdapter<EmailAccount> = {
* startAccount: async (ctx) => {
* // Check availability (for backward compatibility)
* if (!ctx.channelRuntime) {
* ctx.log?.warn?.("channelRuntime not available - skipping AI features");
* return;
* }
*
* // Use AI dispatch
* await ctx.channelRuntime.reply.dispatchReplyWithBufferedBlockDispatcher({
* ctx: { ... },
* cfg: ctx.cfg,
* dispatcherOptions: {
* deliver: async (payload) => {
* // Send reply via email
* },
* },
* });
* },
* };
* ```
*
* ## Backward Compatibility
*
* - This field is **optional** - channels that don't need it can ignore it
* - Built-in channels (slack, discord, etc.) typically don't use this field
* because they can directly import internal modules
* - External plugins should check for undefined before using
*
* @since Plugin SDK 2026.2.19
* @see {@link https://docs.openclaw.ai/plugins/developing-plugins | Plugin SDK documentation}
*/
channelRuntime?: PluginRuntime["channel"];
};
export type ChannelLogoutResult = {
cleared: boolean;
loggedOut?: boolean;
[key: string]: unknown;
};
export type ChannelLoginWithQrStartResult = {
qrDataUrl?: string;
message: string;
};
export type ChannelLoginWithQrWaitResult = {
connected: boolean;
message: string;
};
export type ChannelLogoutContext<ResolvedAccount = unknown> = {
cfg: OpenClawConfig;
accountId: string;
account: ResolvedAccount;
runtime: RuntimeEnv;
log?: ChannelLogSink;
};
export type ChannelPairingAdapter = {
idLabel: string;
normalizeAllowEntry?: (entry: string) => string;
notifyApproval?: (params: {
cfg: OpenClawConfig;
id: string;
runtime?: RuntimeEnv;
}) => Promise<void>;
};
export type ChannelGatewayAdapter<ResolvedAccount = unknown> = {
startAccount?: (ctx: ChannelGatewayContext<ResolvedAccount>) => Promise<unknown>;
stopAccount?: (ctx: ChannelGatewayContext<ResolvedAccount>) => Promise<void>;
loginWithQrStart?: (params: {
accountId?: string;
force?: boolean;
timeoutMs?: number;
verbose?: boolean;
}) => Promise<ChannelLoginWithQrStartResult>;
loginWithQrWait?: (params: {
accountId?: string;
timeoutMs?: number;
}) => Promise<ChannelLoginWithQrWaitResult>;
logoutAccount?: (ctx: ChannelLogoutContext<ResolvedAccount>) => Promise<ChannelLogoutResult>;
};
export type ChannelAuthAdapter = {
login?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
runtime: RuntimeEnv;
verbose?: boolean;
channelInput?: string | null;
}) => Promise<void>;
};
export type ChannelHeartbeatAdapter = {
checkReady?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
deps?: ChannelHeartbeatDeps;
}) => Promise<{ ok: boolean; reason: string }>;
resolveRecipients?: (params: { cfg: OpenClawConfig; opts?: { to?: string; all?: boolean } }) => {
recipients: string[];
source: string;
};
};
type ChannelDirectorySelfParams = {
cfg: OpenClawConfig;
accountId?: string | null;
runtime: RuntimeEnv;
};
type ChannelDirectoryListParams = {
cfg: OpenClawConfig;
accountId?: string | null;
query?: string | null;
limit?: number | null;
runtime: RuntimeEnv;
};
type ChannelDirectoryListGroupMembersParams = {
cfg: OpenClawConfig;
accountId?: string | null;
groupId: string;
limit?: number | null;
runtime: RuntimeEnv;
};
export type ChannelDirectoryAdapter = {
self?: (params: ChannelDirectorySelfParams) => Promise<ChannelDirectoryEntry | null>;
listPeers?: (params: ChannelDirectoryListParams) => Promise<ChannelDirectoryEntry[]>;
listPeersLive?: (params: ChannelDirectoryListParams) => Promise<ChannelDirectoryEntry[]>;
listGroups?: (params: ChannelDirectoryListParams) => Promise<ChannelDirectoryEntry[]>;
listGroupsLive?: (params: ChannelDirectoryListParams) => Promise<ChannelDirectoryEntry[]>;
listGroupMembers?: (
params: ChannelDirectoryListGroupMembersParams,
) => Promise<ChannelDirectoryEntry[]>;
};
export type ChannelResolveKind = "user" | "group";
export type ChannelResolveResult = {
input: string;
resolved: boolean;
id?: string;
name?: string;
note?: string;
};
export type ChannelResolverAdapter = {
resolveTargets: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
inputs: string[];
kind: ChannelResolveKind;
runtime: RuntimeEnv;
}) => Promise<ChannelResolveResult[]>;
};
export type ChannelElevatedAdapter = {
allowFromFallback?: (params: {
cfg: OpenClawConfig;
accountId?: string | null;
}) => Array<string | number> | undefined;
};
export type ChannelCommandAdapter = {
enforceOwnerForCommands?: boolean;
skipWhenConfigEmpty?: boolean;
};
export type ChannelSecurityAdapter<ResolvedAccount = unknown> = {
resolveDmPolicy?: (
ctx: ChannelSecurityContext<ResolvedAccount>,
) => ChannelSecurityDmPolicy | null;
collectWarnings?: (ctx: ChannelSecurityContext<ResolvedAccount>) => Promise<string[]> | string[];
};