UNPKG

@mastra/core

Version:
90 lines 4.15 kB
import type { Adapter, Thread } from 'chat'; import type { IMastraLogger } from '../logger/logger.js'; import type { ProcessOutputStreamArgs } from '../processors/index.js'; import type { AgentChunkType, ChunkType } from '../stream/types.js'; import type { AgentChannels } from './agent-channels.js'; import type { PendingApprovalRecord } from './stream-helpers.js'; import type { ToolDisplay, ToolDisplayFn } from './types.js'; /** * Per-run render dependencies stashed onto `requestContext` by * `AgentChannels.processChatMessage` (and the slash-command / resume paths * once those migrate). The output processor reads this on the first chunk * and routes subsequent chunks through the resolved chat-SDK driver. * * Kept separate from `ChannelContext` (which is part of the public LLM * surface) so we don't leak runtime handles into prompts or persisted * provider metadata. * * @internal */ export interface ChatChannelRenderContext { adapter: Adapter; chatThread: Thread; platform: string; streaming: { enabled: boolean; options?: { updateIntervalMs?: number; }; }; toolDisplay: ToolDisplay; toolDisplayFn?: ToolDisplayFn; channelToolNames: Set<string>; logger?: IMastraLogger; onApprovalPosted: (toolCallId: string, record: PendingApprovalRecord) => void; getPendingApproval: (toolCallId: string) => PendingApprovalRecord | undefined; takePendingApproval: (toolCallId: string) => PendingApprovalRecord | undefined; wrapStream: (stream: AsyncIterable<AgentChunkType<any>>) => AsyncIterable<AgentChunkType<any>>; typingGate: { active: boolean; }; formatError?: (error: Error) => unknown; approvalContext?: { toolCallId: string; messageId: string; }; } /** Key the processor reads off `requestContext` to locate its render deps. */ export declare const CHAT_CHANNEL_RENDER_CONTEXT_KEY = "__mastra_chat_channel_render"; /** * Output processor that mirrors the agent's stream to the originating chat * platform (Slack/Discord/etc.) via the existing streaming/static drivers. * * On the first chunk of a run, the processor opens a render session: it spins * up an async queue, hands the queue's iterable to `runStreamingDriver` (or * `runStaticDriver`), and stores the session on the per-run `state` arg. * Subsequent chunks push into the queue and return immediately — the driver * pumps chunks to the platform in the background, never blocking the agent * loop. * * On `finish` / `error` chunks the queue is closed and the driver promise is * awaited so the run doesn't end (and a serverless invocation isn't allowed * to freeze) before the last `chat.update` lands. * * Render context is resolved in two ways, in order: * * 1. Fast path — `CHAT_CHANNEL_RENDER_CONTEXT_KEY` on `requestContext`, stashed * by `AgentChannels` on inbound platform events (`processChatMessage`, * approve/decline). This is the original webhook path and is unchanged. * 2. Fallback — when no render context is on `requestContext` (schedule fire, * Studio, custom UI, user code) but the processor is bound to its owning * `AgentChannels`, it reconstructs the render context from the run's * `threadId` via `agentChannels.buildRenderContextForThread(threadId)`, * which reads the thread's persisted channel coordinates. The `threadId` is * taken from the memory context the framework stashes on `requestContext` * under the `MastraMemory` key. * * Runs that resolve no render context at all — non-channel threads, or an * unbound processor with no `requestContext` key — pass through untouched. * * @internal */ export declare class ChatChannelOutputProcessor { #private; readonly id = "chat-channel-render"; /** Need data-* chunks because some drivers (`hidden`/`grouped`) inspect them. */ readonly processDataParts = true; constructor(agentChannels?: AgentChannels); processOutputStream({ part, state, requestContext, }: ProcessOutputStreamArgs): Promise<ChunkType | null | undefined>; } //# sourceMappingURL=output-processor.d.ts.map