import type { Chat, Adapter, CardElement, ChatConfig, Message, StateAdapter, Thread } from 'chat'; import type { Agent } from '../agent/agent.js'; import type { IMastraLogger } from '../logger/logger.js'; import type { Mastra } from '../mastra/index.js'; import type { InputProcessor, InputProcessorOrWorkflow } from '../processors/index.js'; import type { ApiRoute } from '../server/types.js'; /** Message content that can be posted to a channel. */ export type PostableMessage = string | CardElement; /** Per-adapter configuration. */ export interface ChannelAdapterConfig { adapter: Adapter; /** * Start a persistent Gateway WebSocket listener for this adapter * (default: `true`). * * Only relevant for adapters that support it (e.g. Discord). * Required for receiving DMs, @mentions, and reactions. Set to `false` for * serverless deployments that only need slash commands via HTTP Interactions. */ gateway?: boolean; /** * Use rich card formatting for tool calls, approvals, and results. * Set to `false` to use plain text formatting instead. * * Some platforms (e.g. Discord) may have rendering issues with cards. * @default true */ cards?: boolean; /** * Override how tool calls are rendered in the chat. * Called once per tool invocation after the result is available. * Return `null` to suppress the message entirely. * * @default - A Card showing the function-call signature and result. */ formatToolCall?: (info: { toolName: string; args: Record; result: unknown; isError?: boolean; }) => PostableMessage | null; /** * Override how errors are rendered in the chat. * Return a user-friendly message instead of exposing the raw error. * * @default `"❌ Error: "` */ formatError?: (error: Error) => PostableMessage; } /** * Handler function for channel events. * Receives the thread, message, and the default handler implementation. * Call `defaultHandler` to run the built-in behavior, or ignore it to fully replace. */ export type ChannelHandler = (thread: Thread, message: Message, defaultHandler: (thread: Thread, message: Message) => Promise) => Promise; /** * Handler configuration for channel events. * - `undefined` or omitted → use default handler * - `false` → disable handler entirely * - function → custom handler (receives defaultHandler as 3rd arg to wrap/extend) */ export type ChannelHandlerConfig = ChannelHandler | false | undefined; /** Handler overrides for built-in channel event handlers. */ export interface ChannelHandlers { /** * Handler for direct messages to the bot. * Default: Routes to agent.stream and posts the response. */ onDirectMessage?: ChannelHandlerConfig; /** * Handler for @mentions of the bot in channels. * Default: Routes to agent.stream and posts the response. */ onMention?: ChannelHandlerConfig; /** * Handler for messages in subscribed threads. * Default: Routes to agent.stream and posts the response. */ onSubscribedMessage?: ChannelHandlerConfig; } /** Configuration for agent chat channels. */ export interface ChannelConfig { /** Platform adapters keyed by name (e.g. 'slack', 'discord'). */ adapters: Record; /** * Override built-in event handlers. * Use this to customize how the agent responds to DMs, mentions, etc. * * @example * ```ts * handlers: { * // Wrap the default handler with logging * onDirectMessage: async (thread, message, defaultHandler) => { * console.log('Received DM:', message.text); * await defaultHandler(thread, message); * }, * // Disable mention handling entirely * onMention: false, * } * ``` */ handlers?: ChannelHandlers; /** * Which media types to send inline to the model (as file parts). * Everything else is described as text metadata so the agent knows about the * file without crashing models that reject unsupported types. * * - **Array of globs** — e.g. `['image/*']` (default), `['image/*', 'video/*']` * - **Function** — `(mimeType: string) => boolean` * * @default `['image/*']` * * @example * ```ts * // Gemini supports video/audio natively * inlineMedia: ['image/*', 'video/*', 'audio/*'] * * // Send everything inline * inlineMedia: () => true * ``` */ inlineMedia?: string[] | ((mimeType: string) => boolean); /** * Promote URLs found in message text to file parts so the model can "see" linked * content (images, videos, PDFs, etc.) instead of just the raw URL text. * * Each entry matches a domain. When a URL in the message matches, it's added as * a `file` part alongside the text. Use a string for domains where a HEAD request * determines the Content-Type, or an object to force a specific mime type (useful * for sites like YouTube where HEAD returns `text/html` but the model treats the * URL as video). * * - **String** — domain to match; HEAD determines the mime type * - **Object** `{ match, mimeType }` — domain + forced mime type (skips HEAD) * - `'*'` — match all URLs (HEAD each one) * - `undefined` (default) — disabled, no URLs are promoted * * For string entries (or `'*'`), the resolved Content-Type is checked against * `inlineMedia` — only matching types become file parts. For object entries with * a forced `mimeType`, the file part is always added. * * @example * ```ts * // Gemini can process YouTube URLs natively as video * inlineLinks: [ * { match: 'youtube.com', mimeType: 'video/*' }, * { match: 'youtu.be', mimeType: 'video/*' }, * ] * * // HEAD-check linked images from any domain * inlineLinks: ['*'] * * // Mix: force YouTube, HEAD-check everything else * inlineLinks: [ * { match: 'youtube.com', mimeType: 'video/*' }, * 'imgur.com', * 'i.redd.it', * ] * ``` */ inlineLinks?: InlineLinkEntry[]; /** State adapter for deduplication, locking, and subscriptions. Defaults to in-memory. */ state?: StateAdapter; /** The bot's display name (default: agent's name, or `'Mastra'`). */ userName?: string; /** * Fetch recent thread messages from the platform to provide context when the agent * is mentioned mid-conversation. Only fetches on the first mention in a thread — * once subscribed, the agent has full history via Mastra's memory system. * * @example * ```ts * threadContext: { maxMessages: 15 } // Fetch more context * threadContext: { maxMessages: 0 } // Disable (opt-out) * ``` */ threadContext?: { /** * Maximum number of recent platform messages to fetch (default: 10). * Only applies to non-DM threads where the agent isn't already subscribed. * Set to 0 to disable. */ maxMessages?: number; }; /** * Whether to include channel tools (add_reaction, remove_reaction). * Set to `false` for models that don't support function calling. * * @default true */ tools?: boolean; /** * Additional options passed directly to the Chat SDK. * Use this for advanced configuration not exposed by Mastra. * * @see https://github.com/vercel/chat * @example * ```ts * chatOptions: { * dedupeTtlMs: 600000, // 10 minute deduplication window * fallbackStreamingPlaceholderText: '⏳', * } * ``` */ chatOptions?: Omit; } /** A single entry in the `inlineLinks` config. */ export type InlineLinkEntry = string | { match: string; mimeType: string; }; /** Check if a URL's hostname matches a domain pattern. @internal */ export declare function matchesDomain(url: string, pattern: string): boolean; export declare function extractUrls(text: string): string[]; /** * Manages a single Chat SDK instance for an agent, wiring all adapters * to the Mastra pipeline (thread mapping → agent.stream → thread.post). * * One AgentChannels = one bot identity across multiple platforms. * * @internal Created automatically by the Agent when `channels` config is provided. */ export declare class AgentChannels { readonly adapters: Record; private chat; /** Stored initialization promise so webhook handlers can await readiness on serverless cold starts. */ private initPromise; private agent; private logger?; private customState; private stateAdapter; private userName; /** Normalized per-adapter configs (gateway flags, hooks, etc.). */ private adapterConfigs; /** Handler overrides from config. */ private handlerOverrides; /** Additional Chat SDK options. */ private chatOptions; /** Thread context config for fetching prior messages. */ private threadContext; /** Determines whether a mime type should be sent inline to the model. */ private shouldInline; /** Inline-link rules for promoting URLs in message text to file parts. */ private inlineLinkRules; /** Whether channel tools (reactions, etc.) are enabled. */ private toolsEnabled; /** Channel tool names whose effects are already visible on the platform (skip rendering cards). */ private channelToolNames; constructor(config: ChannelConfig); /** * Bind this AgentChannels to its owning agent. Called by Agent constructor. * @internal */ __setAgent(agent: Agent): void; /** * Set the logger. Called by Mastra.addAgent. * @internal */ __setLogger(logger: IMastraLogger): void; /** * Get the underlying Chat SDK instance. * Available after Mastra initialization. Use this to register additional * event handlers or access adapter-specific methods. * * @example * ```ts * agent.channels.sdk.onReaction((thread, reaction) => { * console.log('Reaction received:', reaction); * }); * ``` */ get sdk(): Chat | null; /** * Initialize the Chat SDK, register handlers, and start gateway listeners. * Called by Mastra.addAgent after the server is ready. */ initialize(mastra: Mastra): Promise; /** * Returns API routes for receiving webhook events from each adapter. * One POST route per adapter at `/api/agents/{agentId}/channels/{platform}/webhook`. */ getWebhookRoutes(): ApiRoute[]; /** * Returns channel input processors (e.g. system prompt injection). * Skips if the user already added a processor with the same id. */ getInputProcessors(configuredProcessors?: InputProcessorOrWorkflow[]): InputProcessor[]; /** * Returns generic channel tools (send_message, add_reaction, etc.) * that resolve the target adapter from the current request context. */ getTools(): Record; /** * Resolve the adapter for the current conversation from request context. */ private getAdapterFromContext; /** * Core handler wired to Chat SDK's onDirectMessage, onNewMention, * and onSubscribedMessage. Streams the Mastra agent response and * updates the channel message in real-time via edits. */ private handleChatMessage; private processChatMessage; /** * Fetch recent messages from the platform thread to provide context. * Returns messages in chronological order (oldest first), excluding the * current triggering message. */ private fetchThreadHistory; /** * Consume the agent stream and render all chunks to the chat platform. * * Iterates the outer `fullStream` to handle all chunk types: * - `text-delta`: Accumulates text and posts when flushed. * - `tool-call`: Posts a "Running…" card eagerly. * - `tool-result`: Edits the "Running…" card with the result. * - `tool-call-approval`: Edits the card to show Approve/Deny buttons. * - `step-finish` / `finish`: Flushes accumulated text. */ private editOrPost; private consumeAgentStream; /** * Resolves an existing Mastra thread for the given external IDs, or creates one. */ private getOrCreateThread; /** * Generate generic channel tools that resolve the adapter from request context. * Tool names are platform-agnostic (e.g. `send_message`, not `discord_send_message`). */ private makeChannelTools; /** * Persistent reconnection loop for Gateway-based adapters (e.g. Discord). */ private startGatewayLoop; private log; } //# sourceMappingURL=agent-channels.d.ts.map