/** * Cross-Machine Message Service * * Enables Crewly instances on different machines to communicate * via the CloudSync HTTP-polling transport layer. Messages are routed * through the CrewlyAI Cloud message queue (heartbeat-based device * discovery + HTTP-polled delivery), providing built-in auth, persistence, * and offline tolerance without requiring WebSocket connections. * * @module services/slack/cross-machine-message */ import { EventEmitter } from 'events'; import { DeviceIdentityService, type DeviceIdentity } from '../cloud/device-identity.service.js'; import type { SlackIncomingMessage } from '../../types/slack.types.js'; import { type CrossMachineMessage, type CrossMachineMessageType, type CrossMachineConfig, type CrossMachineSendResult } from '../../types/cross-machine.types.js'; /** * Events emitted by CrossMachineMessageService. */ export interface CrossMachineEvents { /** Fired when a cross-machine message addressed to this machine is received */ message: (message: CrossMachineMessage) => void; /** Fired when a broadcast message is received */ broadcast: (message: CrossMachineMessage) => void; /** Fired on errors */ error: (error: Error) => void; } /** * CrossMachineMessageService * * Singleton service managing cross-machine communication via CloudSync. * On send: constructs a CrossMachineMessage and posts it through the * Cloud message queue (CloudSyncService.sendMessage). * On receive: the SlackOrchestratorBridge detects the prefix and calls * handleIncomingMessage(), which filters by target and emits events. * * @example * ```typescript * const service = getCrossMachineMessageService(); * await service.initialize(); * * // Send a task to another machine * await service.sendMessage('device-uuid-of-remote', 'delegate-task', { * task: 'Run tests on feature branch', * priority: 'high', * }); * * // Listen for incoming messages * service.on('message', (msg) => { * console.log(`Received ${msg.type} from ${msg.fromName}`); * }); * ``` */ export declare class CrossMachineMessageService extends EventEmitter { private readonly logger; private deviceIdentity; private config; private identity; private initialized; /** Track processed message IDs to prevent duplicate handling */ private processedMessageIds; /** Maximum number of tracked message IDs before pruning */ private readonly maxTrackedMessages; /** * Create a new CrossMachineMessageService. * * @param deviceIdentity - Optional DeviceIdentityService override (for testing) */ constructor(deviceIdentity?: DeviceIdentityService); /** * Initialize the service. * Loads device identity and cross-machine config from disk. * * @returns Promise that resolves when initialized */ initialize(): Promise; /** * Check if the service is initialized and enabled. * * Returns true when initialized AND enabled, and either: * - A Slack channelId is configured (legacy path), OR * - CloudSyncService is started (new cloud transport path). * * @returns True if ready to send/receive messages */ isEnabled(): boolean; /** * Get the current configuration. * * @returns Cross-machine config or null */ getConfig(): CrossMachineConfig | null; /** * Get the local device identity. * * @returns Device identity or null if not initialized */ getIdentity(): DeviceIdentity | null; /** * Configure cross-machine messaging. * Persists the config to ~/.crewly/cross-machine.json. * * @param config - Configuration with Slack channel ID * @returns Promise that resolves when saved */ configure(config: CrossMachineConfig): Promise; /** * Send a cross-machine message via CloudSync API. * * All inter-device communication goes through the Cloud message queue. * Devices are identified by deviceId — no pairing required. * * @param targetDeviceId - Target machine's device ID (or "*" for broadcast) * @param type - Message type * @param payload - Message payload * @returns Send result with success status */ sendMessage(targetDeviceId: string, type: CrossMachineMessageType, payload?: Record): Promise; /** * Handle an incoming Slack message that has been identified as a * cross-machine message by the SlackOrchestratorBridge. * * Checks if the message is addressed to this machine, deduplicates, * and emits appropriate events. * * @param slackMessage - The raw Slack incoming message * @returns True if the message was handled (addressed to us), false if ignored */ handleIncomingMessage(slackMessage: SlackIncomingMessage): boolean; /** * Load cross-machine config from disk. * * @returns Config or null if not configured */ private loadConfig; /** * Save cross-machine config to disk. * * @param config - Configuration to persist */ private saveConfig; /** * Reset the singleton instance (for testing). */ static resetInstance(): void; } /** * Get the singleton CrossMachineMessageService instance. * * @returns The service instance */ export declare function getCrossMachineMessageService(): CrossMachineMessageService; //# sourceMappingURL=cross-machine-message.service.d.ts.map