/** * ChannelOutboundSender — single owner of the outbound pipeline: * * 1. Optional TTS rewrite (`maybeApplyTtsToPayload`) * 2. Persist-store enqueue (best-effort durability if a send hangs) * 3. Extension `message_sending` hook (block / mutate) * 4. Internal-channel drop guard * 5. Plugin delivery via `deliverOutboundMessage` * 6. Extension `message_sent` hook * 7. Persist-store ack * * Extracted from `ChannelManager.send` so the lifecycle supervisor and plugin * registry stay focused on plugin start/stop and lookup. The send pipeline is * the highest-traffic path in the channel layer; centralising it makes its * error semantics easier to reason about. */ import type { Config } from '../config/schema.js'; import type { OutboundMessage } from './transport-types.js'; import type { ChannelPluginRegistry } from './plugin-registry.js'; /** Hooks wired from `AgentService` for `message_sending` / `message_sent` on outbound delivery. */ export interface OutboundChannelHooks { runMessageSending: (to: string, content: string, channel: string) => Promise<{ send: boolean; content?: string; reason?: string; }>; runMessageSent: (to: string, content: string, success: boolean, error: string | undefined, channel: string) => Promise; } export interface ChannelOutboundSenderOptions { registry: ChannelPluginRegistry; /** Effective config snapshot (TTS rules + plugin delivery context). */ getConfig: () => Config; } export declare class ChannelOutboundSender { private readonly opts; private hooks?; private persistStore?; constructor(opts: ChannelOutboundSenderOptions); setHooks(hooks: OutboundChannelHooks): void; enablePersistence(agentDir: string): void; /** * Redeliver every queued outbound item (called after channels are started). * Best-effort — may duplicate if the prior send succeeded but ack did not * land on disk. */ replayPending(): Promise; send(msg: OutboundMessage, options?: { skipPersist?: boolean; }): Promise; private applyTtsIfNeeded; }