/** * Type definitions for Message Gateway system */ import type { PrincipalContext } from './principal.js'; /** * Supported messenger platforms */ export type MessageSource = 'discord' | 'slack' | 'telegram' | 'chatwork' | 'mobile' | 'viewer' | 'system'; /** * Content block for multimodal input (OpenClaw-style) */ export interface ContentBlock { type: 'text' | 'image' | 'document'; text?: string; localPath?: string; source?: { type: 'base64'; media_type: string; data: string; }; } /** * Normalized message format for cross-platform handling */ export interface NormalizedMessage { /** Source messenger platform */ source: MessageSource; /** Channel or DM identifier */ channelId: string; /** Human-readable channel name (e.g., "#general", "DM with User") */ channelName?: string; /** User identifier on the platform */ userId: string; /** Message text content */ text: string; /** Host-resolved sender identity and admission lane. */ principal?: PrincipalContext; /** Multimodal content blocks (images, etc.) */ contentBlocks?: ContentBlock[]; /** Platform-specific metadata */ metadata?: MessageMetadata; } /** * Message attachment (image, file, etc.) */ export interface MessageAttachment { /** Attachment type */ type: 'image' | 'file'; /** Original network URL when the source exposes a non-secret URL */ url?: string; /** Opaque source reference for attachments whose authenticated URL must stay secret */ sourceRef?: string; /** Local file path (after download) */ localPath?: string; /** File name */ filename: string; /** MIME type */ contentType?: string; /** File size in bytes */ size?: number; } /** * Platform-specific metadata */ export interface MessageMetadata { /** Discord guild ID */ guildId?: string; /** Slack thread timestamp */ threadTs?: string; /** User display name */ username?: string; /** Original message ID */ messageId?: string; /** Message attachments */ attachments?: MessageAttachment[]; /** Telegram chat type (private, group, supergroup, channel) */ chatType?: string; /** Set by the gateway when IT wrapped third-party (forwarded) content in * untrusted markers - the only provenance downstream trusts for stripping. */ untrustedWrapped?: boolean; /** Channel history context (OpenClaw-style) */ historyContext?: string; /** Session ID (for WebSocket/viewer) */ sessionId?: string; /** OS Agent mode flag */ osAgentMode?: boolean; } /** * Session data for messenger conversations */ export interface Session { /** Unique session ID */ id: string; /** Source platform */ source: MessageSource; /** Channel ID */ channelId: string; /** Human-readable channel name (e.g., "#general", "DM with User") */ channelName?: string; /** User ID (optional, for DMs) */ userId?: string; /** Rolling conversation context (JSON) */ context: string; /** Session creation timestamp */ createdAt: number; /** Last activity timestamp */ lastActive: number; } /** * Conversation turn in rolling context */ export interface ConversationTurn { /** User message */ user: string; /** Bot response (truncated) */ bot: string; /** Timestamp */ timestamp?: number; /** * TG-05: globally unique inbound reference (`telegram::`) * binding this turn to its report-consumption receipt. */ sourceMessageRef?: string; /** * TG-05: `provisional` while streaming, `final` after the atomic * turn/receipt commit. Legacy turns without a state are treated as final. */ state?: 'provisional' | 'final'; /** Lowercase hex SHA-256 of the exact final response (set with state=final). */ finalResponseSha256?: string; } /** * Decision from MAMA memory for context injection */ export interface RelatedDecision { /** Decision ID */ id: string; /** Topic identifier */ topic: string; /** Decision text */ decision: string; /** Reasoning */ reasoning?: string; /** Outcome status */ outcome?: 'success' | 'failed' | 'partial' | 'pending'; /** Similarity score (0-1) */ similarity: number; } /** * Message router configuration */ export interface MessageRouterConfig { /** Minimum similarity threshold for context injection (default: 0.7) */ similarityThreshold?: number; /** Maximum number of decisions to inject (default: 3) */ maxDecisions?: number; /** Maximum conversation turns to keep (default: 5) */ maxTurns?: number; /** Maximum response length for context storage (default: 200) */ maxResponseLength?: number; /** Target language for auto-translation prompts (default: Korean) */ translationTargetLanguage?: string; /** Backend type for backend-specific AGENTS.md injection */ backend?: 'claude' | 'codex' | 'cline'; /** Opt into implicit recallMemory injection for new CLI session startup prompts. Default: false. */ implicitMemoryRecall?: boolean; /** Opt into legacy decision-search context injection for new CLI session startup prompts. Default: false. */ implicitLegacyContextSearch?: boolean; } /** * Gateway configuration base */ export interface GatewayConfig { /** Whether the gateway is enabled */ enabled: boolean; } /** * Discord gateway configuration */ export interface DiscordGatewayConfig extends GatewayConfig { /** Discord bot token */ token: string; /** Guild-specific settings */ guilds?: Record; } /** * Discord guild configuration */ export interface DiscordGuildConfig { /** Channel-specific settings */ channels?: Record; /** Default: require mention to respond */ requireMention?: boolean; } /** * Discord channel configuration */ export interface DiscordChannelConfig { /** Whether mention is required (overrides guild setting) */ requireMention?: boolean; } /** * Slack gateway configuration */ export interface SlackGatewayConfig extends GatewayConfig { /** Slack bot token */ botToken: string; /** Slack app token (for Socket Mode) */ appToken: string; /** Channel-specific settings */ channels?: Record; } /** * Slack channel configuration */ export interface SlackChannelConfig { /** Whether mention is required */ requireMention?: boolean; } /** * Chatwork gateway configuration */ export interface ChatworkGatewayConfig extends GatewayConfig { /** Chatwork API token */ apiToken: string; /** Room IDs to monitor */ roomIds?: string[]; /** Polling interval in milliseconds */ pollInterval?: number; /** Whether mention is required */ mentionRequired?: boolean; } /** * Gateway event types */ export type GatewayEventType = 'connected' | 'disconnected' | 'message_received' | 'message_sent' | 'error'; /** * Gateway event */ export interface GatewayEvent { type: GatewayEventType; source: MessageSource; timestamp: Date; data?: unknown; error?: Error; } /** * Gateway event handler */ export type GatewayEventHandler = (event: GatewayEvent) => void; /** * Gateway interface that all platform gateways must implement */ export interface Gateway { /** Platform identifier */ readonly source: MessageSource; /** Start the gateway */ start(): Promise; /** Stop the gateway */ stop(): Promise; /** Check if gateway is connected */ isConnected(): boolean; /** Register event handler */ onEvent(handler: GatewayEventHandler): void; } /** * Plugin manifest (plugin.json) */ export interface PluginManifest { /** Host/plugin contract version. Versions below 2 are refused before registration. */ apiVersion: number; /** Unique plugin ID */ id: string; /** Display name */ name: string; /** Plugin version */ version: string; /** Description */ description?: string; /** Entry point (relative to plugin directory) */ main: string; /** Plugin type */ type: 'gateway'; /** Gateway-specific metadata */ gateway: { /** Gateway source ID (e.g., 'discord', 'slack') */ sourceId: MessageSource; /** Display label */ label: string; /** Config schema (JSON Schema) */ configSchema?: Record; }; /** Required dependencies */ dependencies?: Record; } /** Plugin-supplied message data accepted by the host-owned ingress boundary. */ export interface PluginInboundInput { channelId: string; userId: string; text: string; contentBlocks?: ContentBlock[]; metadata?: MessageMetadata; } /** A diverted inbound has no response by construction. */ export interface PluginInboundResult { response?: string; } /** * Plugin API provided to plugins */ export interface PluginApi { /** Logger */ logger: PluginLogger; /** Get config for this plugin */ getConfig(): T | undefined; /** Submit an inbound message through host-owned identity resolution and routing. */ processInbound(input: PluginInboundInput): Promise; /** Register a message handler */ onMessage(handler: MessageHandler): void; /** Send a response to a channel */ sendResponse(channelId: string, text: string, metadata?: MessageMetadata): Promise; } /** * Plugin logger interface */ export interface PluginLogger { info(message: string, ...args: unknown[]): void; warn(message: string, ...args: unknown[]): void; error(message: string, ...args: unknown[]): void; debug(message: string, ...args: unknown[]): void; } /** * Message handler function type */ export type MessageHandler = (message: NormalizedMessage) => Promise; /** * Gateway plugin registration function */ export type GatewayPluginRegister = (api: PluginApi) => Gateway | Promise; /** * Gateway plugin module export */ export interface GatewayPluginModule { /** Plugin ID (optional, uses manifest id if not provided) */ id?: string; /** Plugin display name */ name?: string; /** Registration function */ register: GatewayPluginRegister; } /** * Loaded plugin info */ export interface LoadedPlugin { /** Plugin manifest */ manifest: PluginManifest; /** Plugin directory path */ path: string; /** Gateway instance (after registration) */ gateway?: Gateway; /** Is plugin enabled */ enabled: boolean; } //# sourceMappingURL=types.d.ts.map