/** * Message Router for unified messenger handling * * Routes messages from different platforms through a unified pipeline: * 1. Normalize message format * 2. Load/create session context * 3. Create AgentContext with role permissions * 4. Inject proactive context (related decisions) * 5. Call Agent Loop with context * 6. Update session context * 7. Return response */ import { SessionStore } from './session-store.js'; import { type MamaApiClient } from './context-injector.js'; import type { NormalizedMessage, MessageRouterConfig, Session, ContentBlock } from './types.js'; import type { AgentLoopOptions, ModelRunProvenance } from '../agent/types.js'; import type { ProcessingResult, ProcessOptions, TurnProcessor } from './turn-contract.js'; import { type MemoryAuditAckLike } from '../memory/audit-task-queue.js'; import type { ReportCarryPort } from '../operator/report-carry.js'; import type { OwnerReportInboxPort } from './owner-report-inbox.js'; import { EnvelopeAuthority } from '../envelope/index.js'; import { type ReactiveEnvelopeConfig } from '../envelope/reactive-config.js'; import type { PrivateConnectorPolicy } from '../connectors/private-connector-policy.js'; export type { AgentLoopOptions } from '../agent/types.js'; export type { ReactiveEnvelopeConfig } from '../envelope/reactive-config.js'; export interface MessageRouterDependencies { privateConnectorPolicy?: PrivateConnectorPolicy; reportCarry?: ReportCarryPort; /** TG-05/TG-06: delivered-pending owner reports consumed by verified owner turns. */ ownerReportInbox?: OwnerReportInboxPort; } /** * The owner's message, as the cause of whatever the turn it started changes. * * Returns the run option to spread, or null when there is nothing honest to cite. * * `sourceTurnId` is the platform's own message id when it gave one, and * `generated:` when it did not. A generated id names nothing any reader could * resolve, and the effect ledger's whole point is that a cited cause be resolvable - so an * unattributed change is the correct answer there, not a synthetic citation. */ export declare function causeFromOwnerMessage(sourceTurnId: string, sourceMessageRef: string): { causeEventIds: readonly string[]; } | null; export declare function protectImageAnalysis(message: NormalizedMessage, analysisText: string): string; export declare function buildUploadedMediaInstructions(message: NormalizedMessage, allowedTools?: readonly string[], allowPrivateMediaPaths?: boolean): string; interface SessionPolicyFingerprintInput { baseInstructions: string; agentsContent?: string; rulesContent?: string; model: string; stableRolePolicy?: string; } export declare function hashSessionPolicyFingerprint({ baseInstructions, agentsContent, rulesContent, model, stableRolePolicy, }: SessionPolicyFingerprintInput): string; /** Channel-less host alarms (workorder failures) park here; every resumed * owner turn reads this key in addition to its own channel key. */ export declare const OPERATOR_BROADCAST_NOTICE_KEY = "operator:broadcast"; /** * Agent Loop interface for message processing */ export interface AgentLoopClient { /** True when a construction-wide child runtime can invoke native or MCP tools. */ readonly childRuntimeToolCapable: boolean; /** * Run the agent loop with a prompt */ run(prompt: string, options?: AgentLoopOptions): Promise<{ response: string; modelRunId?: string | null; modelRunProvenance?: ModelRunProvenance; }>; /** * Run the agent loop with multimodal content */ runWithContent?(content: ContentBlock[], options?: AgentLoopOptions): Promise<{ response: string; modelRunId?: string | null; modelRunProvenance?: ModelRunProvenance; }>; } export interface MemoryAgentProcessLike { sendMessage(content: string, options?: { sourceTurnId?: string; sourceMessageRef?: string; parentModelRunId?: string; }): Promise<{ response?: string; ack?: MemoryAuditAckLike; } | { response?: string; }>; } export interface MemoryAgentProcessManagerLike { getSharedProcess(agentId: 'memory'): Promise; } export interface GatewayRegistry { sendMessage(source: string, channelId: string, text: string): Promise; } export type { BlockedTurn, CompletedTurn, DivertedTurn, ProcessingResult, ProcessOptions, SessionDirectory, TurnOutcomeBase, TurnProcessor, TurnProvenance, } from './turn-contract.js'; export declare const PUBLIC_LANE_SYSTEM_PROMPT = "You are MAMA's public chat assistant. Answer directly and concisely using only the public conversation. You have no tools."; /** * True when the agent persisted memory during THIS turn (gateway mama_save in * the reasoning header) - the extractor safety net then skips to avoid the * dual-save duplicate proven live on 2026-07-17. */ export declare function agentSavedInTurn(response: string | null | undefined): boolean; /** * Message Router class * * Central hub for processing messages from all messenger platforms. */ export declare class MessageRouter implements TurnProcessor { private sessionStore; private contextInjector; private mamaApi; private agentLoop; private config; private envelopeConfig?; private envelopeAuthority?; private readonly privateConnectorPolicy; private readonly reportCarry?; private readonly ownerReportInbox?; private roleManager; private promptEnhancer; private gatewayRegistry; private memoryAgentProcessManager?; private memoryAuditQueue?; private memoryNoticeQueue; private memoryAuditCooldowns; private channelTails; private memoryAgentStats; private sessionsDb; setSessionsDb(db: import('../sqlite.js').default): void; private uiCommandQueue; setUICommandQueue(queue: import('../api/ui-command-handler.js').UICommandQueue): void; private validationService; setValidationService(svc: import('../validation/session-service.js').ValidationSessionService): void; private getPageContextPrefix; setGatewayRegistry(registry: GatewayRegistry): void; setMemoryAgent(processManager: MemoryAgentProcessManagerLike): void; getMemoryAgentStats(): { turnsObserved: number; candidatesDetected: number; factsExtracted: number; factsSaved: number; acksApplied: number; acksSkipped: number; acksFailed: number; lastExtraction: number | null; recentExtractions: Array<{ topic: string; timestamp: number; channelKey?: string; status: "applied" | "skipped" | "failed"; }>; }; /** * Host-code enqueue into the owner notice surface (Stage-2 workorder * failures). The queue stays router-owned; this is the accessor plan C5 * requires - the consumer lives in start.ts host code and cannot reach the * private field. Keyed under the operator BROADCAST key: host alarms have * no conversation channel, and per-channel keys would dead-letter (review * M1). Delivered on the owner's next resumed chat turn on ANY channel. */ enqueueOperatorNotice(summary: string): void; /** * Public API for auditing a conversation via the memory agent. * Used by the /api/mama/audit-conversation endpoint for benchmarking. * Bypasses cooldown and candidate detection — caller provides conversation + optional candidates. */ auditConversation(job: { conversation: string; scopes: Array<{ kind: string; id: string; }>; candidates?: Array<{ kind: string; topicHint?: string; confidence: number; summary: string; }>; }): Promise; constructor(sessionStore: SessionStore, agentLoop: AgentLoopClient, mamaApi: MamaApiClient, config?: MessageRouterConfig, envelopeConfig?: ReactiveEnvelopeConfig, envelopeAuthority?: EnvelopeAuthority, dependencies?: MessageRouterDependencies); private buildReactiveEnvelope; /** * Create AgentContext for a message * Determines role based on message source and builds context */ private createAgentContext; /** * Check if message should trigger auto-translation * Returns true for short messages or image-related text */ private shouldAutoTranslate; /** * Process a normalized message and return response * @param message - The normalized message to process * @param processOptions - Optional callbacks for async notifications * @param processOptions.onQueued - Called immediately if session is busy (message queued) */ /** * TurnProcessor entry point. Delegates exactly once to `process` - this is a boundary, * not a behaviour change, and anything it did before it still does. */ processTurn(message: NormalizedMessage, options?: ProcessOptions): Promise; process(message: NormalizedMessage, processOptions?: ProcessOptions): Promise; private processInChannel; private buildPublicLaneSystemPrompt; /** * Build system prompt with session context, injected decisions, and AgentContext * Note: With --no-session-persistence mode, history is ALWAYS injected * because CLI doesn't persist sessions between calls. */ private buildSystemPrompt; private buildSessionPolicyFingerprint; /** Remove only a complete, structurally valid host-generated private overlay. */ private projectPrivatePromptText; /** * Build minimal prompt for resumed CLI sessions. * CLI already has full system prompt from initial request. * Only inject per-message context (related decisions) to avoid context overflow. */ private buildMinimalResumePrompt; /** * Post-process agent response: detect image file paths and copy to outbound. * Rewrites paths to ~/.mama/workspace/media/outbound/filename so format.js renders them. */ private resolveMediaPaths; /** * List all sessions for a source */ listSessions(source: NormalizedMessage['source']): Session[]; /** * Get session for a channel */ getSession(source: NormalizedMessage['source'], channelId: string): Session | null; /** * Clear session context (start fresh conversation) */ clearSession(sessionId: string): boolean; /** * Delete a session entirely */ deleteSession(sessionId: string): boolean; /** * Update configuration */ setConfig(config: Partial): void; /** * Get current configuration */ getConfig(): Required; /** * Update channel name for a session (used to backfill channel names) */ updateChannelName(source: NormalizedMessage['source'], channelId: string, channelName: string): boolean; /** * Trigger memory agent to extract facts (fire-and-forget). * Uses AgentProcessManager persistent process. */ private static readonly EXTRACT_COOLDOWN_MS; private static readonly MIN_CONTENT_LENGTH; private static readonly MAX_CONTENT_LENGTH; private getRuntimeProjectId; private buildMemoryAuditPrompt; private classifyMemoryAuditResponse; private recordMemoryAuditAck; private getPerTurnMemoryPrefix; private triggerMemoryAgent; private resolveFrontdoorAgentId; private logFrontdoorActivity; private logAgentActivity; } /** * Create a mock agent loop for testing */ export declare function createMockAgentLoop(responseGenerator?: (prompt: string) => string): AgentLoopClient; //# sourceMappingURL=message-router.d.ts.map