import { EventEmitter } from 'events'; import * as Y from 'yjs'; import Database from 'better-sqlite3'; import { Stream } from '@agentclientprotocol/sdk'; export { AnyMessage as AcpAnyMessage, Stream as AcpStream } from '@agentclientprotocol/sdk'; /** * Transport-agnostic peer endpoint information. * Each transport defines how to reach a peer. */ interface PeerEndpoint { /** Peer identifier (transport-agnostic) */ peerId: string; /** Transport-specific address (IP, URL, etc.) */ address: string; /** Optional port (for TCP-based transports) */ port?: number; /** Additional transport-specific metadata */ metadata?: Record; } /** * Connection state for a peer. */ interface PeerConnection$1 { peerId: string; connected: boolean; lastActivity: Date; /** Transport-specific connection handle */ handle?: unknown; } /** * Events emitted by transport adapters. */ interface TransportEvents { /** Emitted when a peer connection is established */ 'peer:connected': (peerId: string, endpoint: PeerEndpoint) => void; /** Emitted when a peer connection is lost */ 'peer:disconnected': (peerId: string, reason?: string) => void; /** Emitted when data is received from a peer */ 'data': (peerId: string, data: Buffer) => void; /** Emitted on transport errors */ 'error': (error: Error) => void; /** Emitted when transport is ready to accept connections */ 'listening': () => void; /** Emitted when transport stops listening */ 'closed': () => void; } /** * Abstract transport adapter interface. * Implementations provide the actual network connectivity. * * The transport layer is responsible for: * - Establishing and managing peer connections * - Sending and receiving raw data * - Emitting connection lifecycle events * * It is NOT responsible for: * - Message framing/parsing (handled by mesh layer) * - Protocol logic (handshakes, hub election, etc.) * - Message routing to channels */ interface TransportAdapter extends EventEmitter { /** Transport type identifier (e.g., 'nebula', 'tailscale', 'tcp') */ readonly type: string; /** Whether the transport is currently active (listening + can connect) */ readonly active: boolean; /** Local endpoint information */ readonly localEndpoint: PeerEndpoint; /** * Start the transport (begin listening for incoming connections). * @throws Error if transport fails to start */ start(): Promise; /** * Stop the transport (close all connections and stop listening). */ stop(): Promise; /** * Connect to a specific peer. * @param endpoint Peer endpoint information * @returns true if connection established or already connected * @throws Error if connection fails */ connect(endpoint: PeerEndpoint): Promise; /** * Disconnect from a specific peer. * @param peerId Peer to disconnect from */ disconnect(peerId: string): Promise; /** * Get all currently connected peer IDs. */ getConnectedPeers(): string[]; /** * Check if a peer is connected. * @param peerId Peer to check */ isConnected(peerId: string): boolean; /** * Get connection info for a peer. * @param peerId Peer to get info for * @returns Connection info or null if not connected */ getConnection(peerId: string): PeerConnection$1 | null; /** * Send data to a specific peer. * @param peerId Target peer * @param data Raw data to send * @returns true if sent successfully, false if peer not connected */ send(peerId: string, data: Buffer): boolean; /** * Send data to all connected peers. * @param data Raw data to send * @returns Map of peerId to send success */ broadcast(data: Buffer): Map; on(event: K, listener: TransportEvents[K]): this; on(event: string | symbol, listener: (...args: unknown[]) => void): this; off(event: K, listener: TransportEvents[K]): this; off(event: string | symbol, listener: (...args: unknown[]) => void): this; emit(event: K, ...args: Parameters): boolean; emit(event: string | symbol, ...args: unknown[]): boolean; } /** * Base transport configuration. */ interface BaseTransportConfig { /** Transport type identifier */ type: string; /** Connection timeout in milliseconds */ connectionTimeout?: number; } /** * Nebula transport configuration. */ interface NebulaTransportConfig extends BaseTransportConfig { type: 'nebula'; /** Nebula tunnel IP address */ nebulaIp: string; /** Port for mesh communication (default: 7946) */ port?: number; /** Path to Nebula config file (for auto-discovery) */ configPath?: string; /** Path to nebula-cert binary */ nebulaCertPath?: string; } /** * Tailscale transport configuration (for future use). */ interface TailscaleTransportConfig extends BaseTransportConfig { type: 'tailscale'; /** Tailscale auth key (for new nodes) */ authKey?: string; /** Hostname to register with */ hostname?: string; /** Control server URL (for Headscale) */ controlUrl?: string; /** State directory */ stateDir?: string; /** Port for mesh communication (default: 7946) */ port?: number; } /** * Headscale transport configuration (for future use). */ interface HeadscaleTransportConfig extends BaseTransportConfig { type: 'headscale'; /** Headscale server URL */ serverUrl: string; /** API key for server operations */ apiKey?: string; /** Pre-auth key for node registration */ preAuthKey?: string; /** Hostname to register with */ hostname?: string; /** Port for mesh communication (default: 7946) */ port?: number; } /** * Plain TCP transport configuration (for testing/development). */ interface TcpTransportConfig extends BaseTransportConfig { type: 'tcp'; /** Local bind address */ bindAddress: string; /** Port for mesh communication */ port: number; } /** * Union type of all transport configurations. */ type TransportConfig = NebulaTransportConfig | TailscaleTransportConfig | HeadscaleTransportConfig | TcpTransportConfig; /** * Factory function type for creating transport adapters. */ type TransportFactory$1 = (config: TransportConfig) => TransportAdapter; /** * Configuration for optional mesh features. * These features can be disabled for simpler deployments or when using * transports that provide their own implementations. */ interface OptionalFeaturesConfig { /** * Enable hub election for centralized coordination. * When disabled, no hub is elected and hub-specific features are skipped. * Default: true */ hubElection?: boolean; /** * Enable health monitoring with heartbeats. * When disabled, no ping/pong health checks are performed. * Use 'transport' to delegate to the transport's built-in health monitoring. * Default: true */ healthMonitoring?: boolean | 'transport'; /** * Enable namespace registry for tracking which peers participate in which namespaces. * When disabled, namespace registration messages are not sent/processed. * Only useful when hub election is also enabled. * Default: true */ namespaceRegistry?: boolean; /** * Enable hub relay for peers that cannot connect directly. * When disabled, messages to unreachable peers will fail. * Requires hub election to be enabled. * Default: true */ hubRelay?: boolean; /** * Enable offline queue for messages to offline peers. * When disabled, messages to offline peers are dropped. * Default: true */ offlineQueue?: boolean; } interface NebulaAutoConfigOptions { /** Local peer ID (required) */ peerId: string; /** Local peer name (optional, defaults to peerId) */ peerName?: string; /** Hub configuration override */ hub?: HubConfig; /** Port for mesh communication (default: 7946) */ port?: number; /** Enable peer discovery (default: true) */ enableDiscovery?: boolean; /** Discovery poll interval in ms (default: 30000) */ discoveryInterval?: number; /** Path to nebula-cert binary (default: 'nebula-cert') */ nebulaCertPath?: string; /** Optional features configuration (Phase 5) */ features?: OptionalFeaturesConfig; } /** * Hub roles define the permission level for hub election. * Higher roles have priority in hub election. * Roles are per-server and determined by deployment configuration. */ declare enum HubRole { /** Cannot become hub - read-only participant */ MEMBER = 0, /** Can become hub if no higher-priority peers available */ COORDINATOR = 1, /** Preferred hub role - highest priority */ ADMIN = 2 } interface HubConfig { /** Role for this peer in hub election */ role: HubRole; /** Tiebreaker within same role (higher = more preferred) */ priority?: number; /** List of peer IDs that can become hub (if empty, all peers can) */ candidates?: string[]; } interface HubState { /** Current hub peer ID (null if no hub elected) */ hubId: string | null; /** Hub peer info */ hub: PeerInfo | null; /** Election term/epoch for consistency */ term: number; /** Timestamp of last election */ electedAt: Date | null; } type PeerStatus = 'online' | 'offline' | 'unknown'; interface PeerInfo { id: string; name?: string; /** * @deprecated Use endpoint.address instead. Kept for backward compatibility. */ nebulaIp: string; /** * @deprecated Use endpoint.port instead. Kept for backward compatibility. */ port?: number; /** * Transport-agnostic endpoint information. * New code should use this instead of nebulaIp/port. */ endpoint?: PeerEndpoint; status: PeerStatus; lastSeen: Date; groups: string[]; activeNamespaces: string[]; isHub: boolean; hubRole?: HubRole; hubPriority?: number; } interface PeerConfig { id: string; /** * @deprecated Use endpoint.address instead. Will be removed in v1.0.0. */ nebulaIp: string; name?: string; /** * @deprecated Use endpoint.port instead. Will be removed in v1.0.0. */ port?: number; /** * Transport-agnostic endpoint information (recommended). * New code should use this instead of nebulaIp/port. */ endpoint?: PeerEndpoint; } interface NebulaMeshConfig { peerId: string; peerName?: string; nebulaIp: string; peers: PeerConfig[]; groups?: string[]; hub?: HubConfig; connectionTimeout?: number; healthCheckInterval?: number; port?: number; /** * Default serialization format for all channels. * - 'json': Always use JSON (backward compatible) * - 'binary': Always use MessagePack (best performance) * - 'auto': Negotiate with peer, prefer binary (default) */ serialization?: 'json' | 'binary' | 'auto'; /** * Enable compression for large messages (>1KB). * Only applies to binary format. * Default: true */ compressionEnabled?: boolean; /** * Optional features configuration (Phase 5). * Configure which optional features are enabled. */ features?: OptionalFeaturesConfig; } interface MessageChannelConfig { enableOfflineQueue?: boolean; offlineQueueTTL?: number; maxQueueSize?: number; retryAttempts?: number; retryDelay?: number; timeout?: number; requiredGroups?: string[]; } interface QueuedMessage { id: string; message: T; targetPeerId: string; createdAt: Date; expiresAt: Date; attempts: number; } interface MessageContext { messageId: string; from: PeerInfo; timestamp: Date; } interface ChannelStats { messagesSent: number; messagesReceived: number; queuedMessages: number; failedDeliveries: number; permissionDenied?: number; } interface WireMessage { id: string; channel: string; type: 'message' | 'request' | 'response'; payload: T; from: string; to: string | null; timestamp: number; requestId?: string; } /** * Stats for hub relay operations. */ interface RelayStats { /** Number of messages relayed */ messagesRelayed: number; /** Number of relay requests received */ relayRequestsReceived: number; /** Number of relay failures */ relayFailures: number; /** Number of messages queued for offline peers */ messagesQueuedForRelay: number; } interface SyncProviderConfig { namespace: string; } interface SyncError { code: string; message: string; peerId?: string; recoverable: boolean; } interface YjsSyncConfig extends SyncProviderConfig { persistence?: { enabled: boolean; path?: string; snapshotInterval?: number; }; awareness?: { enabled: boolean; localState?: Record; }; } type YjsMessageType = 'sync-step-1' | 'sync-step-2' | 'update' | 'awareness'; interface YjsSyncStep1 { type: 'sync-step-1'; stateVector: Uint8Array; } interface YjsSyncStep2 { type: 'sync-step-2'; diff: Uint8Array; stateVector?: Uint8Array; } interface YjsUpdate { type: 'update'; update: Uint8Array; } interface YjsAwareness { type: 'awareness'; changes: Uint8Array; } type YjsMessage = YjsSyncStep1 | YjsSyncStep2 | YjsUpdate | YjsAwareness; type MeshEventType = 'connected' | 'disconnected' | 'peer:joined' | 'peer:left' | 'peer:updated' | 'peer:health' | 'hub:changed' | 'error'; type ChannelEventType = 'message' | 'error'; type SyncEventType = 'synced' | 'syncing' | 'error' | 'update' | 'peer:synced'; /** * Generic channel interface for type-safe channel creation. * This avoids circular imports with MessageChannel. */ interface IMessageChannel { readonly name: string; readonly isOpen: boolean; open(): Promise; close(): Promise; send(peerId: string, message: T): boolean; broadcast(message: T): void; request(peerId: string, message: T, timeout?: number): Promise; onRequest(handler: (message: T, from: PeerInfo) => Promise): void; offRequest(): void; on(event: string | symbol, listener: (...args: any[]) => void): this; off(event: string | symbol, listener: (...args: any[]) => void): this; } /** * MeshContext is the primary interface for interacting with the mesh network. * It provides transport-agnostic access to peer management, hub election, * namespace registry, and channel creation. * * This interface is implemented by NebulaMesh and future transport implementations. * MessageChannel and SyncProviders depend on this interface, not concrete implementations. */ interface MeshContext { /** Get the current hub peer, or null if no hub elected */ getActiveHub(): PeerInfo | null; /** Check if this peer is the current hub */ isHub(): boolean; /** Get all known peers */ getPeers(): PeerInfo[]; /** Get info about the local peer */ getSelf(): PeerInfo; /** Get info about a specific peer by ID */ getPeer?(id: string): PeerInfo | null; /** Register interest in a namespace for sync */ registerNamespace(namespace: string): Promise; /** Unregister from a namespace */ unregisterNamespace(namespace: string): Promise; /** Get all active namespaces and their participating peers */ getActiveNamespaces(): Map; /** * Create or get a message channel by name. * Channels are cached - calling with the same name returns the existing channel. * * @param name Unique channel name * @param config Optional channel configuration * @returns MessageChannel instance */ createChannel(name: string, config?: MessageChannelConfig): IMessageChannel; /** * @internal Send a message to a specific peer on a channel. * @returns true if sent, false if peer not connected */ _sendToPeer(peerId: string, channelName: string, message: T): boolean; /** * @internal Broadcast a message to all connected peers on a channel. */ _broadcast(channelName: string, message: T): void; /** * @internal Send an RPC message (request or response) to a peer. * @returns true if sent, false if peer not connected */ _sendRpc(peerId: string, channelName: string, message: T, type: 'request' | 'response', requestId: string): boolean; /** * @internal Get the local peer ID. */ _getPeerId(): string; on(event: string | symbol, listener: (...args: any[]) => void): this; off(event: string | symbol, listener: (...args: any[]) => void): this; } /** * Events emitted by health monitor adapters. */ interface HealthMonitorEvents { /** Emitted when a peer's health status changes */ 'health:changed': (event: HealthChangeEvent) => void; /** Emitted when a peer becomes suspect (may be offline) */ 'peer:suspect': (event: { peerId: string; missedHeartbeats: number; lastSeen: Date; }) => void; /** Emitted when the hub becomes unhealthy */ 'hub:unhealthy': (hubId: string) => void; /** Emitted when health monitoring starts */ 'started': () => void; /** Emitted when health monitoring stops */ 'stopped': () => void; } /** * Health change event payload. */ interface HealthChangeEvent { peerId: string; previousStatus: PeerStatus; newStatus: PeerStatus; missedHeartbeats: number; } /** * Health status for a peer. */ interface PeerHealth { peerId: string; status: PeerStatus; lastSeen: Date; lastPing: Date | null; missedHeartbeats: number; isHub: boolean; } /** * Abstract interface for health monitoring implementations. * * Different transports can provide their own implementations: * - HealthMonitor: Default TCP ping/pong implementation (for Nebula) * - TailscaleHealthMonitor: Uses Tailscale's built-in health monitoring * - NoopHealthMonitor: Disabled health monitoring * * @example * ```typescript * // Default TCP-based health monitoring * const healthMonitor = new HealthMonitor({ heartbeatInterval: 10000 }) * * // Tailscale-based health monitoring * const healthMonitor = new TailscaleHealthMonitor(tailscaleCli) * * // Disabled health monitoring * const healthMonitor = new NoopHealthMonitor() * ``` */ interface HealthMonitorAdapter extends EventEmitter { /** Whether health monitoring is currently running */ readonly isRunning: boolean; /** * Start health monitoring. * @param pingFn Function to send ping to a peer (for TCP-based implementations) */ start(pingFn?: (peerId: string) => void): void; /** * Stop health monitoring. */ stop(): void; /** * Register a peer for health monitoring. * @param peer Peer info to register */ registerPeer(peer: PeerInfo): void; /** * Unregister a peer from health monitoring. * @param peerId Peer ID to unregister */ unregisterPeer(peerId: string): void; /** * Update the current hub ID. * @param hubId Current hub peer ID, or null if no hub */ setHubId(hubId: string | null): void; /** * Record that traffic was received from a peer. * This serves as an implicit heartbeat. * @param peerId Peer that sent traffic */ recordTraffic(peerId: string): void; /** * Record that a pong (ping response) was received from a peer. * @param peerId Peer that sent pong */ recordPong(peerId: string): void; /** * Get health status for a specific peer. * @param peerId Peer ID to query * @returns Health status or null if not registered */ getPeerHealth(peerId: string): PeerHealth | null; /** * Get health status for all registered peers. * @returns Array of health statuses */ getAllPeerHealth(): PeerHealth[]; /** * Get list of healthy (online) peer IDs. * @returns Array of peer IDs */ getHealthyPeers(): string[]; /** * Get list of unhealthy (offline or unknown) peer IDs. * @returns Array of peer IDs */ getUnhealthyPeers(): string[]; /** * Check if the hub is healthy. * @returns true if hub is online, false otherwise */ isHubHealthy(): boolean; on(event: K, listener: HealthMonitorEvents[K]): this; on(event: string | symbol, listener: (...args: unknown[]) => void): this; off(event: K, listener: HealthMonitorEvents[K]): this; off(event: string | symbol, listener: (...args: unknown[]) => void): this; emit(event: K, ...args: Parameters): boolean; emit(event: string | symbol, ...args: unknown[]): boolean; } /** * No-op health monitor implementation. * Used when health monitoring is disabled. * * All peers are always considered online. */ declare class NoopHealthMonitor extends EventEmitter implements HealthMonitorAdapter { private _running; private peers; private hubId; get isRunning(): boolean; start(): void; stop(): void; registerPeer(peer: PeerInfo): void; unregisterPeer(peerId: string): void; setHubId(hubId: string | null): void; recordTraffic(peerId: string): void; recordPong(peerId: string): void; getPeerHealth(peerId: string): PeerHealth | null; getAllPeerHealth(): PeerHealth[]; getHealthyPeers(): string[]; getUnhealthyPeers(): string[]; isHubHealthy(): boolean; } declare class MessageChannel extends EventEmitter { readonly name: string; private mesh; private config; private _open; private offlineQueue; private stats; private pendingRequests; private requestHandler; private requestCounter; constructor(mesh: MeshContext, name: string, config?: MessageChannelConfig); open(): Promise; close(): Promise; get isOpen(): boolean; private handlePeerJoined; /** * Send a message to a specific peer. * If the peer is offline and queueing is enabled, the message will be queued. */ send(peerId: string, message: T): boolean; /** * Send a message to a specific peer, with automatic queueing if offline. * Returns true if sent or queued, false only if queueing is disabled and send fails. */ sendWithQueue(peerId: string, message: T): boolean; /** * Broadcast a message to all connected peers */ broadcast(message: T): void; /** * Send a message to multiple specific peers */ multicast(peerIds: string[], message: T): Map; /** * Send a request and wait for a response. * @param peerId Target peer to send request to * @param message Request message * @param timeout Timeout in ms (default: from config, typically 30000) * @returns Response from peer * @throws RPCTimeoutError if no response within timeout * @throws RPCError if handler returns an error */ request(peerId: string, message: T, timeout?: number): Promise; /** * Register a handler for incoming requests. * The handler receives the request message and peer info, and returns a response. * Only one handler can be registered per channel. * @param handler Async function that processes requests and returns responses */ onRequest(handler: (message: T, from: PeerInfo) => Promise): void; /** * Remove the request handler. */ offRequest(): void; /** * Check if a request handler is registered. */ hasRequestHandler(): boolean; private generateRequestId; /** @internal - Called by mesh when a message arrives */ _receiveMessage(message: T, from: PeerInfo): void; /** @internal - Called by mesh when an RPC request arrives */ _receiveRequest(message: T, from: PeerInfo, requestId: string): Promise; /** @internal - Called by mesh when an RPC response arrives */ _receiveResponse(response: unknown, from: PeerInfo, requestId: string): void; /** * Check if a peer has permission to send messages on this channel. * Returns true if no required groups are configured or if peer has at least one required group. */ private checkSenderPermission; /** * Get the required groups for this channel. */ getRequiredGroups(): string[]; getStats(): ChannelStats; resetStats(): void; } /** * Parsed Nebula configuration */ interface ParsedNebulaConfig { /** PKI configuration */ pki: { caPath: string; certPath: string; keyPath: string; }; /** Lighthouse configuration */ lighthouse: { amLighthouse: boolean; /** Map of Nebula IP to public endpoints */ hosts: Map; interval: number; }; /** Listen configuration */ listen: { host: string; port: number; }; /** Static host map (Nebula IP to public endpoints) */ staticHostMap: Map; /** Whether this is a lighthouse node */ isLighthouse: boolean; } /** * Parsed certificate information */ interface ParsedCertInfo { /** Certificate name */ name: string; /** Nebula IP (with CIDR) */ nebulaIp: string; /** Groups assigned to this certificate */ groups: string[]; /** Certificate expiration */ notAfter: Date; /** Certificate creation */ notBefore: Date; /** Issuer name */ issuer: string; /** Is this a CA certificate */ isCa: boolean; /** Public key fingerprint */ fingerprint?: string; } /** * Complete parsed Nebula setup */ interface NebulaSetup { config: ParsedNebulaConfig; cert: ParsedCertInfo; configPath: string; } /** * Peer info for discovery protocol */ interface DiscoveryPeerInfo { id: string; name?: string; nebulaIp: string; port?: number; groups: string[]; namespaces: string[]; /** Last seen timestamp */ lastSeen: number; } declare class NebulaMesh extends EventEmitter implements MeshContext { private config; private peers; private channels; private namespaces; private _connected; private _disconnecting; private hubElection; private namespaceRegistry; private healthMonitor; private serializer; private features; private transport; private peerBuffers; private incomingBuffers; private incomingSockets; private peerDiscovery; private discoveryChannel; private nebulaSetup; private relayStats; private hubOfflineQueue; constructor(config: NebulaMeshConfig); private setupTransportHandlers; /** * Handle data from an incoming connection (before handshake). */ private handleIncomingData; /** * Handle data from an identified peer. */ private handlePeerData; /** * Handle handshake from an incoming connection. */ private handleIncomingHandshake; /** * Send handshake to a specific peer via transport. */ private sendHandshakeToPeer; /** * Process handshake data from a peer (shared between incoming and outgoing). */ private processHandshake; /** * Create a NebulaMesh instance from an existing Nebula configuration file. * * This factory method: * - Parses the nebula config.yaml file * - Extracts PKI paths and lighthouse configuration * - Parses the certificate to get Nebula IP and groups * - Auto-configures the mesh based on lighthouse settings * * @param configPath Path to nebula config.yaml (supports ~ for home dir) * @param options Additional configuration options * @returns Configured NebulaMesh instance * * @example * ```typescript * const mesh = await NebulaMesh.fromNebulaConfig('~/.nebula/config.yaml', { * peerId: 'alice', * enableDiscovery: true, * }) * * await mesh.connect() * mesh.startPeerDiscovery() // Start discovering peers via lighthouses * ``` */ static fromNebulaConfig(configPath: string, options: NebulaAutoConfigOptions): Promise; /** * Get the Nebula setup info (if created via fromNebulaConfig). */ getNebulaSetup(): NebulaSetup | null; /** * Get the current optional features configuration. * Returns the merged configuration (defaults + user overrides). */ getFeatures(): Required; connect(): Promise; disconnect(): Promise; get connected(): boolean; getPeers(): PeerInfo[]; getPeer(id: string): PeerInfo | null; getSelf(): PeerInfo; private peerConfigToInfo; getActiveHub(): PeerInfo | null; isHub(): boolean; /** * Get the current hub election state. * Returns null if hub election is disabled. */ getHubState(): HubState | null; /** * Broadcast hub announcement to all connected peers. */ private broadcastHubAnnouncement; registerNamespace(namespace: string): Promise; unregisterNamespace(namespace: string): Promise; getActiveNamespaces(): Map; /** * Get peers participating in a specific namespace. */ getPeersForNamespace(namespace: string): string[]; /** * Send namespace registration/unregistration to hub. */ private sendNamespaceRegistration; /** * Broadcast namespace update to all peers (hub-side). */ private broadcastNamespaceUpdate; /** * Send namespace snapshot to a specific peer (hub-side). */ private sendNamespaceSnapshot; createChannel(name: string, config?: MessageChannelConfig): MessageChannel; private connectToPeers; private connectToPeer; private handlePeerDisconnect; private handleMessage; /** @internal - Used by MessageChannel */ _sendToPeer(peerId: string, channelName: string, message: T): boolean; /** @internal - Used by MessageChannel */ _broadcast(channelName: string, message: T): void; /** @internal - Used by MessageChannel for RPC */ _sendRpc(peerId: string, channelName: string, message: T, type: 'request' | 'response', requestId: string): boolean; /** @internal - Used by MessageChannel for request ID generation */ _getPeerId(): string; /** * Start peer discovery via lighthouses. * * This requires the mesh to be created with `fromNebulaConfig()` with * `enableDiscovery: true` (the default). * * @param pollInterval Optional interval override in ms (default: from config) */ startPeerDiscovery(pollInterval?: number): Promise; /** * Stop peer discovery. */ stopPeerDiscovery(): Promise; /** * Manually trigger peer discovery. * Returns the list of discovered peers. * * @param namespace Optional namespace filter */ discoverPeers(namespace?: string): Promise; /** * Get discovered peers. */ getDiscoveredPeers(): DiscoveryPeerInfo[]; /** * Whether peer discovery is running. */ get discoveryRunning(): boolean; /** * Handle a discovered peer - add to peers if not already known. */ private handleDiscoveredPeer; /** * Send a ping to a peer for health checking. */ private sendPing; /** * Send a pong response to a peer. */ private sendPong; /** * Get health status for all monitored peers. */ getPeerHealth(): PeerHealth[]; /** * Get healthy (online) peer IDs. */ getHealthyPeers(): string[]; /** * Check if the current hub is healthy. */ isHubHealthy(): boolean; /** * Try to relay a message through the hub when direct connection fails. * @internal */ private tryRelay; /** * Handle a relay request (hub-side). * Forwards the message to the target peer if connected, or queues if offline. */ private handleRelayRequest; /** * Forward a relay message to the target peer. */ private forwardRelayMessage; /** * Flush queued relay messages for a peer that has rejoined (hub-side). */ private flushQueuedRelayMessages; /** * Handle a relayed message (peer-side). * Processes the message as if it came directly from the original sender. */ private handleRelayedMessage; /** * Get relay statistics (hub-side stats are most relevant). */ getRelayStats(): RelayStats; /** * Reset relay statistics. */ resetRelayStats(): void; /** * Get hub offline queue stats (hub-side only). */ getHubQueueStats(): { total: number; byChannel: Map; } | null; } /** * Options for streaming execution */ interface StreamingExecutionOptions { /** Working directory for command */ cwd?: string; /** Environment variables */ env?: Record; /** Arguments to pass to command */ args?: string[]; /** Timeout in ms (0 = no timeout, default: 0 for streaming) */ timeout?: number; } /** * ExecutionStream represents a streaming execution session. * * Use this to receive real-time stdout/stderr output from a remote command execution. * * @example * ```typescript * const stream = router.requestExecutionWithStream('peer-id', 'npm test') * * stream.on('stdout', (data) => console.log(data)) * stream.on('stderr', (data) => console.error(data)) * stream.on('exit', (code, signal) => console.log('Exited:', code)) * stream.on('error', (err) => console.error('Error:', err)) * * // Cancel if needed * await stream.cancel() * ``` */ declare class ExecutionStream extends EventEmitter { readonly executionId: string; readonly peerId: string; readonly command: string; private _completed; private _cancelled; private cancelFn; private _stdout; private _stderr; private _exitCode; private _exitSignal; constructor(executionId: string, peerId: string, command: string, cancelFn: () => Promise); /** * Whether the execution has completed (exit or error received) */ get completed(): boolean; /** * Whether the execution was cancelled */ get cancelled(): boolean; /** * Get all stdout output received so far */ get stdout(): string; /** * Get all stderr output received so far */ get stderr(): string; /** * Get the exit code (null if not yet exited) */ get exitCode(): number | null; /** * Get the exit signal (undefined if not killed by signal) */ get exitSignal(): string | undefined; /** * Cancel the execution. * Sends a cancel request to the remote peer. */ cancel(): Promise; /** * Wait for the execution to complete. * Returns the exit code. */ wait(): Promise; /** @internal */ _receiveStdout(data: string): void; /** @internal */ _receiveStderr(data: string): void; /** @internal */ _receiveExit(code: number, signal?: string): void; /** @internal */ _receiveError(error: string): void; } interface ExecutionRequest { /** Unique request ID for correlation */ requestId: string; /** Command to execute */ command: string; /** Optional arguments */ args?: string[]; /** Optional working directory */ cwd?: string; /** Optional environment variables */ env?: Record; /** Optional timeout in ms (default: 30000) */ timeout?: number; } interface ExecutionResponse { /** Request ID for correlation */ requestId: string; /** Whether execution was successful */ success: boolean; /** Exit code (0 for success) */ exitCode?: number; /** Standard output */ stdout?: string; /** Standard error */ stderr?: string; /** Error message if execution failed */ error?: string; } interface ExecutionRequestEvent { /** The execution request */ request: ExecutionRequest; /** The peer that requested execution */ from: PeerInfo; /** Function to send the response */ respond: (response: Omit) => void; } interface ExecutionRouterConfig { /** Default timeout for execution requests in ms (default: 30000) */ defaultTimeout?: number; /** Required groups for execution permission (empty = allow all) */ requiredGroups?: string[]; /** Maximum concurrent executions (default: 10) */ maxConcurrent?: number; } declare class ExecutionRouter extends EventEmitter { private mesh; private config; private channel; private streamChannel; private pendingRequests; private activeExecutions; private _started; private activeStreams; private streamCancelHandlers; constructor(mesh: NebulaMesh, config?: ExecutionRouterConfig); /** * Start the execution router (opens the channels). * Called automatically in constructor, but can be called manually if needed. */ start(): Promise; /** * Stop the execution router and close the channels. */ stop(): Promise; /** * Cancel all active streams. */ private cancelAllStreams; /** * Check if the router is started. */ get started(): boolean; /** * Request execution of a command on a remote peer. * Returns a promise that resolves with the execution result. */ requestExecution(peerId: string, command: string, options?: Omit): Promise; /** * Broadcast an execution request to all peers. * Returns results from all peers that respond before timeout. */ broadcastExecution(command: string, options?: Omit): Promise>; /** * Get the number of pending execution requests. */ get pendingCount(): number; /** * Get the number of active executions on this peer. */ get activeCount(): number; /** * Cancel a pending execution request. */ cancelRequest(requestId: string): boolean; /** * Cancel all pending requests. */ cancelAll(): void; /** * Request streaming execution of a command on a remote peer. * Returns an ExecutionStream that emits stdout/stderr/exit events in real-time. * * @param peerId Target peer to execute on * @param command Command to execute * @param options Execution options * @returns ExecutionStream for receiving output * * @example * ```typescript * const stream = router.requestExecutionWithStream('peer-id', 'npm test') * stream.on('stdout', (data) => console.log(data)) * stream.on('stderr', (data) => console.error(data)) * stream.on('exit', (code) => console.log('Done:', code)) * ``` */ requestExecutionWithStream(peerId: string, command: string, options?: StreamingExecutionOptions): ExecutionStream; /** * Get the number of active streaming executions. */ get activeStreamCount(): number; /** * Cancel a streaming execution by ID. */ cancelStream(executionId: string): boolean; private handleRequest; private handleResponse; private sendResponse; private checkPermission; private handleStreamMessage; private handleStreamStart; private handleStreamOutput; private handleStreamExit; private handleStreamError; private handleStreamCancel; } interface HealthMonitorConfig { /** Heartbeat interval in milliseconds. Default: 10000 (10s) */ heartbeatInterval?: number; /** Number of missed heartbeats before marking peer as suspect. Default: 2 */ suspectThreshold?: number; /** Number of missed heartbeats before marking peer as offline. Default: 3 */ offlineThreshold?: number; } /** * Default TCP ping/pong-based health monitor. * Implements the HealthMonitorAdapter interface. */ declare class HealthMonitor extends EventEmitter implements HealthMonitorAdapter { private readonly heartbeatInterval; private readonly suspectThreshold; private readonly offlineThreshold; private peerHealth; private checkTimer; private pingFn; private running; private hubId; constructor(config?: HealthMonitorConfig); /** * Start health monitoring. * @param pingFn Function to call when a ping should be sent to a peer */ start(pingFn: (peerId: string) => void): void; /** * Stop health monitoring. */ stop(): void; /** * Check if health monitoring is running. */ get isRunning(): boolean; /** * Register a peer for health monitoring. * Called when a peer joins the mesh. */ registerPeer(peer: PeerInfo): void; /** * Unregister a peer from health monitoring. * Called when a peer leaves the mesh. */ unregisterPeer(peerId: string): void; /** * Update the current hub ID for special handling. */ setHubId(hubId: string | null): void; /** * Record that we received traffic from a peer. * Called for any message received from a peer (data or control). * This serves as an implicit heartbeat - no dedicated ping needed. */ recordTraffic(peerId: string): void; /** * Record that we received a pong (ping response) from a peer. */ recordPong(peerId: string): void; /** * Get health status for a specific peer. */ getPeerHealth(peerId: string): PeerHealth | null; /** * Get health status for all peers. */ getAllPeerHealth(): PeerHealth[]; /** * Get list of peers that are currently healthy (online). */ getHealthyPeers(): string[]; /** * Get list of peers that are unhealthy (offline or unknown). */ getUnhealthyPeers(): string[]; /** * Check if the hub is healthy. */ isHubHealthy(): boolean; private checkHealth; private emitHealthChange; } interface QueuedOperation { id: string; channelName: string; message: T; targetPeerId: string | null; createdAt: Date; expiresAt: Date; attempts: number; lastAttempt: Date | null; } interface OfflineQueueConfig { /** Directory to persist queue (optional, uses memory if not set) */ persistPath?: string; /** Time-to-live for queued messages in ms (default: 24h) */ ttl?: number; /** Maximum queue size (default: 1000) */ maxSize?: number; /** Retry delay in ms (default: 1000) */ retryDelay?: number; /** Max retry attempts (default: 3) */ maxRetries?: number; } /** * OfflineQueue provides message queueing for offline/disconnected scenarios. * Implements hybrid mode: nodes operate independently, sync with hub when possible. * * Features: * - Persists queue to disk for crash recovery * - TTL-based message expiration * - Automatic retry with backoff * - CRDT-friendly (messages are idempotent updates) */ declare class OfflineQueue extends EventEmitter { private config; private queue; private flushTimer; private persistTimer; private dirty; constructor(config?: OfflineQueueConfig); /** * Initialize the queue, loading persisted state if available. */ init(): Promise; /** * Stop the queue, persisting final state. */ stop(): Promise; /** * Add an operation to the queue. */ enqueue(channelName: string, message: T, targetPeerId?: string | null): QueuedOperation; /** * Remove an operation from the queue (after successful delivery). */ dequeue(id: string): boolean; /** * Mark an operation as attempted (for retry tracking). */ markAttempted(id: string): boolean; /** * Get all pending operations for a channel. */ getForChannel(channelName: string): QueuedOperation[]; /** * Get all pending operations for a specific target peer. */ getForPeer(peerId: string): QueuedOperation[]; /** * Get operations ready for retry. */ getReadyForRetry(): QueuedOperation[]; /** * Get queue statistics. */ getStats(): { total: number; byChannel: Map; }; /** * Check if queue is empty. */ isEmpty(): boolean; /** * Clear all queued operations. */ clear(): void; /** * Schedule a flush attempt using the provided send function. * Returns a promise that resolves when all messages are sent or failed. */ flush(sendFn: (op: QueuedOperation) => Promise): Promise<{ sent: number; failed: number; }>; private loadFromDisk; private persistToDisk; private pruneExpired; private pruneOldest; } declare abstract class SyncProvider extends EventEmitter { readonly namespace: string; protected mesh: MeshContext; constructor(mesh: MeshContext, config: SyncProviderConfig); abstract start(): Promise; abstract stop(): Promise; abstract get synced(): boolean; abstract get syncing(): boolean; sync?(): Promise; } declare class YjsSyncProvider extends SyncProvider { readonly doc: Y.Doc; private channel; private _synced; private _syncing; private syncedPeers; private config; private persistTimer; private dirty; constructor(mesh: MeshContext, config: YjsSyncConfig); start(): Promise; stop(): Promise; get synced(): boolean; get syncing(): boolean; getMap(name: string): Y.Map; getArray(name: string): Y.Array; getText(name: string): Y.Text; private initSyncWithPeer; private handleMessage; private handleSyncStep1; private handleSyncStep2; private handleUpdate; private broadcastUpdate; private checkSyncStatus; /** * Request a full snapshot from a peer (for late joiner recovery). */ requestSnapshot(peerId: string): void; private handleSnapshotRequest; private handleSnapshotResponse; private getStatePath; private loadPersistedState; private persistState; /** * Manually trigger state persistence. */ saveState(): Promise; /** * Get the current document state as a snapshot. */ getSnapshot(): Uint8Array; /** * Apply a snapshot to the document. */ applySnapshot(snapshot: Uint8Array): void; } interface CrSqliteSyncConfig extends SyncProviderConfig { /** Path to SQLite database file */ dbPath: string; /** Tables to sync (if omitted, sync all CRR tables) */ tables?: string[]; /** Optional scope filter - only sync rows matching criteria */ scope?: Record; /** How often to poll for local changes (ms, default: 100) */ pollInterval?: number; /** Batch size for changeset transmission (default: 1000) */ batchSize?: number; /** Path to cr-sqlite extension (auto-detected if not provided) */ extensionPath?: string; } interface DbSyncMessages { /** Initial sync request */ 'db:sync-request': DbSyncRequest; /** Sync response with changesets */ 'db:sync-response': DbSyncResponse; /** Incremental update broadcast */ 'db:changes': DbChangesMessage; /** Version announcement */ 'db:version': DbVersionMessage; } interface DbSyncRequest { /** Tables to sync */ tables: string[]; /** Request changes since this version (0 for full sync) */ sinceVersion: number; } interface DbSyncResponse { /** Changesets to apply */ changesets: CrSqliteChangeset[]; /** Starting version of these changes */ fromVersion: number; /** Ending version after these changes */ toVersion: number; /** Whether more changesets are available (pagination) */ hasMore: boolean; } interface DbChangesMessage { /** Changesets to apply */ changesets: CrSqliteChangeset[]; /** Version after these changes */ version: number; } interface DbVersionMessage { /** Site ID of the peer */ siteId: string; /** Current version at this peer */ version: number; } interface CrSqliteChangeset { /** Table name */ table: string; /** Primary key value(s) - serialized as JSON string by cr-sqlite */ pk: string; /** Column ID (column name) */ cid: string; /** Column value */ val: unknown; /** Column version (for conflict resolution) */ col_version: number; /** Database version when this change was made */ db_version: number; /** Site ID of the peer that made this change */ site_id: Uint8Array | string; } interface ConflictInfo { /** Table where conflict occurred */ table: string; /** Primary key of conflicting row */ pk: unknown; /** Column that conflicted */ column: string; /** Which value won */ winner: 'local' | 'remote'; /** Local value before resolution */ localValue: unknown; /** Remote value that was merged */ remoteValue: unknown; } type DbSyncErrorCode = 'EXTENSION_NOT_FOUND' | 'DB_OPEN_FAILED' | 'TABLE_NOT_CRR' | 'CHANGESET_INVALID' | 'APPLY_FAILED' | 'SCHEMA_MISMATCH' | 'SYNC_TIMEOUT'; declare class DbSyncError extends Error { readonly code: DbSyncErrorCode; readonly recoverable: boolean; constructor(message: string, code: DbSyncErrorCode, recoverable?: boolean); } declare class CrSqliteSyncProvider extends SyncProvider { private config; private db; private channel; private pollTimer; private snapshotTimer; private localVersion; private siteId; private peerVersions; private _synced; private _syncing; constructor(mesh: MeshContext, config: CrSqliteSyncConfig); get synced(): boolean; get syncing(): boolean; start(): Promise; stop(): Promise; sync(): Promise; /** * Get the underlying better-sqlite3 database instance. * Use this to run queries on the synced database. */ getDb(): Database.Database; /** * Get the cr-sqlite site ID for this peer. */ getSiteId(): string; /** * Get the current local version. */ getLocalVersion(): number; /** * Get versions known for each peer. */ getPeerVersions(): Map; private setupCrrTables; private getCurrentVersion; private setupMessageHandlers; private handleSyncRequest; private startPolling; private checkLocalChanges; private applyChangesets; private initialSync; private setupHubBehavior; private enableSnapshotPersistence; private disableSnapshotPersistence; private saveSnapshot; private buildScopeFilter; private serializeChangeset; } /** * Detect the cr-sqlite extension path. * Searches common locations and returns the first valid path found. * * @returns Path to the cr-sqlite extension * @throws DbSyncError if extension not found */ declare function detectExtensionPath(): string; /** * Get the extension path, either from config or auto-detected. * * @param configPath - Optional path from config * @returns Validated extension path */ declare function getExtensionPath(configPath?: string): string; /** * Get installation instructions for the current platform. */ declare function getInstallInstructions(): string; interface CertManagerConfig { /** Path to certificate storage directory */ certsDir: string; /** Path to nebula-cert binary (auto-detected if not specified) */ nebulaCertPath?: string; /** Path to nebula binary (for validation) */ nebulaPath?: string; /** Auto-renewal configuration */ autoRenewal?: AutoRenewalConfig; } interface AutoRenewalConfig { /** Enable auto-renewal. Default: false */ enabled: boolean; /** Check interval in ms. Default: 3600000 (1 hour) */ checkInterval?: number; /** Renew certificates this many days before expiry. Default: 7 */ renewBeforeDays?: number; } interface CertificateInfo { /** Certificate name/identifier */ name: string; /** Certificate type */ type: 'root-ca' | 'user-ca' | 'server'; /** Nebula IP address (for server certs) */ nebulaIp?: string; /** Groups assigned to this certificate */ groups: string[]; /** Certificate creation time */ createdAt: Date; /** Certificate expiration time */ expiresAt: Date; /** Path to .crt file */ certPath: string; /** Path to .key file */ keyPath: string; /** Parent CA name (for signed certs) */ signedBy?: string; /** Whether this cert has been revoked */ revoked: boolean; /** Additional metadata */ metadata?: Record; } interface CertificateIndex { /** Index version for migrations */ version: number; /** All tracked certificates */ certificates: Record; /** Last modified timestamp */ lastModified: Date; } interface CreateRootCAOptions { /** CA name (used as identifier) */ name: string; /** Validity duration. Default: "8760h" (1 year) */ duration?: string; /** Groups that can be assigned by this CA */ groups?: string[]; } interface CreateUserCAOptions { /** User CA name */ name: string; /** Root CA name to sign with */ rootCAName: string; /** Validity duration. Default: "8760h" (1 year) */ duration?: string; /** Groups this CA can assign (subset of root CA groups) */ groups?: string[]; } interface SignServerCertOptions { /** Server certificate name */ name: string; /** CA name to sign with (root or user CA) */ caName: string; /** Nebula IP address (e.g., "10.42.0.10/24") */ nebulaIp: string; /** Groups to assign */ groups?: string[]; /** Validity duration. Default: "8760h" (1 year) */ duration?: string; /** Subnets this cert can route */ subnets?: string[]; } interface SetupValidation { /** Overall validation passed */ valid: boolean; /** nebula-cert binary found and working */ nebulaCertFound: boolean; /** nebula-cert version (if found) */ nebulaCertVersion?: string; /** nebula binary found (optional) */ nebulaFound: boolean; /** nebula version (if found) */ nebulaVersion?: string; /** Certificates directory exists and writable */ certsDirWritable: boolean; /** Validation errors */ errors: string[]; /** Validation warnings */ warnings: string[]; } interface CertVerification { /** Certificate is valid */ valid: boolean; /** Certificate chain is complete */ chainValid: boolean; /** Certificate is not expired */ notExpired: boolean; /** Certificate is not revoked */ notRevoked: boolean; /** Verification errors */ errors: string[]; } type CertEventType = 'cert:created' | 'cert:renewed' | 'cert:revoked' | 'cert:expiring' | 'cert:expired' | 'error'; interface CertCreatedEvent { cert: CertificateInfo; } interface CertRenewedEvent { oldCert: CertificateInfo; newCert: CertificateInfo; } interface CertExpiringEvent { cert: CertificateInfo; daysUntilExpiry: number; } interface RevocationEntry { /** Certificate name that was revoked */ certName: string; /** Certificate fingerprint (SHA256 of cert content) */ fingerprint: string; /** Time of revocation */ revokedAt: Date; /** Reason for revocation */ reason: string; /** Who revoked (peer ID or 'local') */ revokedBy: string; } interface RevocationList { /** Version for compatibility */ version: number; /** List of revoked certificates */ entries: RevocationEntry[]; /** Last updated timestamp */ lastUpdated: Date; /** Signature from issuing CA (optional) */ signature?: string; } interface RevocationListExport { /** Serialized revocation list */ data: string; /** Format version */ version: number; } interface CertRevokedEvent { cert: CertificateInfo; reason: string; } declare class CertManager extends EventEmitter { private config; private index; private revocationList; private autoRenewalTimer; private initialized; private mesh; private revocationChannel; constructor(config: CertManagerConfig); /** * Initialize the CertManager. Must be called before using other methods. * Loads existing certificate index or creates a new one. */ initialize(): Promise; /** * Shut down the CertManager, stopping auto-renewal. */ shutdown(): Promise; /** * Validate that nebula-cert and optionally nebula are available. */ validateSetup(): Promise; /** * Create a new root CA. */ createRootCA(options: CreateRootCAOptions): Promise; /** * Create a user CA signed by a root CA. */ createUserCA(options: CreateUserCAOptions): Promise; /** * Sign a server certificate. */ signServerCert(options: SignServerCertOptions): Promise; /** * Get certificate by name. */ getCertificate(name: string): CertificateInfo | undefined; /** * List all certificates. */ listCertificates(): CertificateInfo[]; /** * List certificates by type. */ listCertificatesByType(type: CertificateInfo['type']): CertificateInfo[]; /** * Get certificates that need renewal. */ getCertsNeedingRenewal(daysThreshold?: number): CertificateInfo[]; /** * Verify a certificate. */ verifyCert(name: string): Promise; /** * Revoke a certificate. */ revokeCert(name: string, reason?: string): Promise; /** * Check if a certificate is revoked by name. */ isRevoked(name: string): boolean; /** * Check if a certificate is revoked by fingerprint. */ isRevokedByFingerprint(fingerprint: string): boolean; /** * Get all revocation entries. */ getRevocationList(): RevocationEntry[]; /** * Export revocation list for distribution. */ exportRevocationList(): RevocationListExport; /** * Import and merge revocation list from another source. * New entries are added, existing entries are preserved. */ importRevocationList(exported: RevocationListExport): Promise; /** * Start auto-renewal monitoring. */ startAutoRenewal(): void; /** * Stop auto-renewal monitoring. */ stopAutoRenewal(): void; /** * Check for expiring certs and renew them. */ checkAndRenewCerts(): Promise; /** * Renew a server certificate. */ renewServerCert(name: string): Promise; /** * Connect to a mesh for revocation list distribution. * When connected as hub, revocation updates are broadcast to all peers. * When connected as peer, revocation updates are received and imported. * * @param mesh The NebulaMesh instance to connect to * * @example * ```typescript * const mesh = new NebulaMesh(config) * await mesh.connect() * certManager.connectToMesh(mesh) * * // On revoke, hub broadcasts automatically * await certManager.revokeCert(compromisedCert) * ``` */ connectToMesh(mesh: NebulaMesh): void; /** * Disconnect from mesh. */ disconnectFromMesh(): Promise; /** * Check if connected to mesh. */ get meshConnected(): boolean; /** * Broadcast revocation update to all peers (hub only). */ private broadcastRevocationUpdate; private ensureInitialized; private createEmptyIndex; private loadIndex; private saveIndex; private createEmptyRevocationList; private loadRevocationList; private saveRevocationList; private calculateCertFingerprint; private runCommand; private parseCertExpiration; } interface NebulaConfigOptions { /** Path to CA certificate */ caCertPath: string; /** Path to host certificate */ certPath: string; /** Path to host private key */ keyPath: string; /** Lighthouse hosts - map of Nebula IP to public IP:port */ lighthouses: Record; /** This host's Nebula IP (for lighthouse self-identification) */ nebulaIp?: string; /** Listen host for UDP. Default: "0.0.0.0" */ listenHost?: string; /** Listen port for UDP. Default: 4242 */ listenPort?: number; /** TUN device name. Default: "nebula1" */ tunDevice?: string; /** Enable TUN device. Default: true */ tunEnabled?: boolean; /** MTU for TUN device. Default: 1300 */ mtu?: number; /** Cipher to use. Default: "aes" */ cipher?: 'aes' | 'chachapoly'; /** Firewall rules */ firewall?: FirewallConfig; /** Logging config */ logging?: LoggingConfig; /** Additional raw YAML to merge */ extraConfig?: Record; } interface LighthouseConfigOptions extends NebulaConfigOptions { /** Serve DNS. Default: false */ dns?: DnsConfig; /** Answer Lighthouse queries. Default: true */ amLighthouse?: boolean; } interface FirewallConfig { /** Connection tracking timeout. Default: "10m" */ conntrackTimeout?: string; /** Inbound rules */ inbound?: FirewallRule[]; /** Outbound rules */ outbound?: FirewallRule[]; } interface FirewallRule { /** Protocol: any, tcp, udp, icmp */ proto: 'any' | 'tcp' | 'udp' | 'icmp'; /** Port or port range (e.g., "22", "8000-9000", "any") */ port: string; /** Source/dest host: any, group:name, cidr, or specific Nebula IP */ host: string; /** Groups required (optional) */ groups?: string[]; } interface DnsConfig { /** Enable DNS server */ enabled: boolean; /** DNS listen host. Default: "0.0.0.0" */ host?: string; /** DNS listen port. Default: 53 */ port?: number; } interface LoggingConfig { /** Log level: debug, info, warn, error */ level?: 'debug' | 'info' | 'warn' | 'error'; /** Log format: text, json */ format?: 'text' | 'json'; } declare class ConfigGenerator { /** * Generate a peer Nebula configuration. */ generateNebulaConfig(options: NebulaConfigOptions): string; /** * Generate a lighthouse Nebula configuration. */ generateLighthouseConfig(options: LighthouseConfigOptions): string; /** * Generate a minimal peer config for agentic-mesh usage. * Includes firewall rules for mesh communication. */ generateMeshPeerConfig(options: NebulaConfigOptions): string; /** * Write config to file. */ writeConfig(configPath: string, config: string): Promise; private buildBaseConfig; private buildStaticHostMap; private buildFirewallConfig; private formatFirewallRule; private toYaml; private formatValue; private deepMerge; } declare const configGenerator: ConfigGenerator; /** * Permission levels in hierarchical order (higher includes lower) */ declare enum PermissionLevel { NONE = 0, READ = 1, WRITE = 2, ADMIN = 3 } /** * Group hierarchy configuration * Maps permission levels to required groups */ interface GroupHierarchy { admin: string[]; write: string[]; read: string[]; } /** * Permission check result */ interface PermissionCheckResult { allowed: boolean; level: PermissionLevel; matchedGroups: string[]; missingGroups?: string[]; } /** * Configuration for GroupPermissions */ interface GroupPermissionsConfig { /** * Group hierarchy mapping permission levels to group names * Higher levels implicitly include lower levels */ hierarchy?: GroupHierarchy; /** * If true, admin group has all permissions * Default: true */ adminImpliesAll?: boolean; /** * Custom permission resolver for complex scenarios * Return undefined to use default hierarchy check */ customResolver?: (groups: string[], requiredLevel: PermissionLevel) => PermissionCheckResult | undefined; } /** * Permission denied error with details */ declare class PermissionDeniedError extends Error { readonly requiredLevel: PermissionLevel; readonly actualLevel: PermissionLevel; readonly userGroups: string[]; readonly requiredGroups?: string[] | undefined; constructor(requiredLevel: PermissionLevel, actualLevel: PermissionLevel, userGroups: string[], requiredGroups?: string[] | undefined); } /** * GroupPermissions - Helper class for group-based permission checking * * Provides configurable permission hierarchy and enforcement utilities. * Groups are extracted from Nebula certificates and can be used for * access control in mesh operations. * * @example * ```typescript * const permissions = new GroupPermissions({ * hierarchy: { * admin: ['mesh-admins'], * write: ['mesh-writers', 'mesh-editors'], * read: ['mesh-readers', 'mesh-viewers'], * } * }) * * // Check permissions * if (permissions.canWrite(['mesh-writers'])) { * // Allow write operation * } * * // Enforce permissions (throws on failure) * permissions.enforceAdmin(['mesh-readers']) // throws PermissionDeniedError * ``` */ declare class GroupPermissions extends EventEmitter { private readonly config; constructor(config?: GroupPermissionsConfig); /** * Get the hierarchy configuration */ getHierarchy(): GroupHierarchy; /** * Update the hierarchy configuration */ setHierarchy(hierarchy: GroupHierarchy): void; /** * Check if user has a specific group */ hasGroup(userGroups: string[], group: string): boolean; /** * Check if user has any of the specified groups */ hasAnyGroup(userGroups: string[], groups: string[]): boolean; /** * Check if user has all of the specified groups */ hasAllGroups(userGroups: string[], groups: string[]): boolean; /** * Get the effective permission level for a set of groups */ getPermissionLevel(userGroups: string[]): PermissionLevel; /** * Check if user has at least the specified permission level */ hasPermissionLevel(userGroups: string[], requiredLevel: PermissionLevel): boolean; /** * Check permission and return detailed result */ checkPermission(userGroups: string[], requiredLevel: PermissionLevel): PermissionCheckResult; /** * Check if user can read (has READ or higher permission) */ canRead(userGroups: string[]): boolean; /** * Check if user can write (has WRITE or higher permission) */ canWrite(userGroups: string[]): boolean; /** * Check if user can admin (has ADMIN permission) */ canAdmin(userGroups: string[]): boolean; /** * Enforce read permission, throw PermissionDeniedError on failure */ enforceRead(userGroups: string[]): void; /** * Enforce write permission, throw PermissionDeniedError on failure */ enforceWrite(userGroups: string[]): void; /** * Enforce admin permission, throw PermissionDeniedError on failure */ enforceAdmin(userGroups: string[]): void; /** * Enforce a specific permission level, throw on failure */ enforcePermission(userGroups: string[], requiredLevel: PermissionLevel): void; /** * Extract groups from a certificate */ getGroupsFromCert(cert: CertificateInfo): string[]; /** * Check permission for a certificate */ checkCertPermission(cert: CertificateInfo, requiredLevel: PermissionLevel): PermissionCheckResult; /** * Enforce permission for a certificate */ enforceCertPermission(cert: CertificateInfo, requiredLevel: PermissionLevel): void; /** * Check if certificate can read */ certCanRead(cert: CertificateInfo): boolean; /** * Check if certificate can write */ certCanWrite(cert: CertificateInfo): boolean; /** * Check if certificate can admin */ certCanAdmin(cert: CertificateInfo): boolean; /** * Create a permission checker function for a specific level * Useful for middleware patterns */ createChecker(requiredLevel: PermissionLevel): (groups: string[]) => boolean; /** * Create a permission enforcer function for a specific level * Useful for middleware patterns */ createEnforcer(requiredLevel: PermissionLevel): (groups: string[]) => void; /** * Create a certificate permission checker */ createCertChecker(requiredLevel: PermissionLevel): (cert: CertificateInfo) => boolean; /** * Create a certificate permission enforcer */ createCertEnforcer(requiredLevel: PermissionLevel): (cert: CertificateInfo) => void; } /** * Default global instance with standard configuration */ declare const groupPermissions: GroupPermissions; /** * Lighthouse process state */ type LighthouseStatus = 'stopped' | 'starting' | 'running' | 'stopping' | 'error'; /** * Lighthouse info stored in index */ interface LighthouseInfo { name: string; nebulaIp: string; publicEndpoint: string; listenPort: number; configPath: string; caCertPath: string; certPath: string; keyPath: string; status: LighthouseStatus; pid?: number; startedAt?: Date; lastHealthCheck?: Date; healthy?: boolean; error?: string; } /** * Lighthouse index file structure */ interface LighthouseIndex { lighthouses: Record; lastUpdated: Date; } /** * Configuration for LighthouseManager */ interface LighthouseManagerConfig { /** * Directory to store lighthouse configs * Default: ./lighthouses */ lighthousesDir?: string; /** * Path to nebula binary * Default: nebula (assumes in PATH) */ nebulaBinaryPath?: string; /** * Health check interval in ms * Default: 30000 (30 seconds) */ healthCheckInterval?: number; /** * Process startup timeout in ms * Default: 10000 (10 seconds) */ startupTimeout?: number; } /** * Options for creating a lighthouse */ interface CreateLighthouseOptions { name: string; nebulaIp: string; publicEndpoint: string; caCertPath: string; certPath: string; keyPath: string; listenPort?: number; otherLighthouses?: Record; dns?: { enabled: boolean; port?: number; }; } /** * Lighthouse health info */ interface LighthouseHealth { name: string; healthy: boolean; status: LighthouseStatus; pid?: number; uptime?: number; lastCheck: Date; error?: string; } /** * Event types emitted by LighthouseManager */ type LighthouseEventType = 'lighthouse:created' | 'lighthouse:started' | 'lighthouse:stopped' | 'lighthouse:error' | 'lighthouse:health-changed' | 'lighthouse:removed'; /** * LighthouseManager - Manages Nebula lighthouse processes * * Handles the full lifecycle of lighthouse nodes including configuration * generation, process management, and health monitoring. * * @example * ```typescript * const manager = new LighthouseManager({ * lighthousesDir: './lighthouses', * }) * await manager.initialize() * * // Create a lighthouse * await manager.create({ * name: 'lighthouse-1', * nebulaIp: '10.42.0.1/24', * publicEndpoint: 'lighthouse.example.com:4242', * caCertPath: './certs/ca.crt', * certPath: './certs/lighthouse-1.crt', * keyPath: './certs/lighthouse-1.key', * }) * * // Start the lighthouse * await manager.start('lighthouse-1') * * // Check health * const health = await manager.health('lighthouse-1') * ``` */ declare class LighthouseManager extends EventEmitter { private readonly config; private index; private processes; private healthIntervals; private initialized; private readonly configGenerator; constructor(config?: LighthouseManagerConfig); /** * Initialize the manager */ initialize(): Promise; /** * Shutdown the manager and stop all lighthouses */ shutdown(): Promise; /** * Create a new lighthouse configuration */ create(options: CreateLighthouseOptions): Promise; /** * Get lighthouse info */ get(name: string): LighthouseInfo | undefined; /** * List all lighthouses */ list(): LighthouseInfo[]; /** * Remove a lighthouse */ remove(name: string): Promise; /** * Start a lighthouse process */ start(name: string): Promise; /** * Stop a lighthouse process */ stop(name: string): Promise; /** * Restart a lighthouse process */ restart(name: string): Promise; /** * Get lighthouse status */ status(name: string): LighthouseStatus; /** * Get health info for a lighthouse */ health(name: string): Promise; /** * Start health monitoring for a lighthouse */ startHealthMonitor(name: string): void; /** * Stop health monitoring for a lighthouse */ stopHealthMonitor(name: string): void; private ensureInitialized; private get indexPath(); private loadIndex; private saveIndex; private isProcessRunning; private checkHealth; } /** * Filter config for specs. * All conditions are AND'd together. */ interface SpecFilterConfig { /** ID glob patterns (e.g., 's-abc*', 's-???') - OR'd together */ ids?: string[]; /** Only sync specs with these priorities - OR'd together */ priority?: number[]; /** Only sync archived/non-archived specs */ archived?: boolean; /** Only sync specs with any of these tags - OR'd together */ tags?: string[]; } /** * Filter config for issues. * All conditions are AND'd together. */ interface IssueFilterConfig { /** ID glob patterns (e.g., 'i-abc*') - OR'd together */ ids?: string[]; /** Only sync issues with these statuses - OR'd together */ status?: IssueStatus[]; /** Only sync issues with these priorities - OR'd together */ priority?: number[]; /** Only sync archived/non-archived issues */ archived?: boolean; /** Only sync issues with any of these tags - OR'd together */ tags?: string[]; /** Only sync issues assigned to these users - OR'd together */ assignee?: string[]; } /** * Filter config for relationships. * All conditions are AND'd together. */ interface RelationshipFilterConfig { /** Only sync relationships of these types - OR'd together */ types?: RelationshipType[]; /** Only sync relationships from entities matching these patterns - OR'd together */ fromIds?: string[]; /** Only sync relationships to entities matching these patterns - OR'd together */ toIds?: string[]; } /** * Filter config for feedback. * All conditions are AND'd together. */ interface FeedbackFilterConfig { /** ID glob patterns - OR'd together */ ids?: string[]; /** Only sync feedback of these types - OR'd together */ types?: FeedbackType[]; /** Only sync feedback to entities matching these patterns - OR'd together */ toIds?: string[]; /** Only sync dismissed/non-dismissed feedback */ dismissed?: boolean; } /** * Filter shorthand types: * - 'all': sync all entities of this type * - 'none': sync no entities of this type * - string[]: sync entities matching these ID patterns (shorthand for { ids: [...] }) */ type FilterShorthand = 'all' | 'none' | string[]; /** * Complete sync filter configuration. */ interface SyncFilter { specs?: FilterShorthand | SpecFilterConfig; issues?: FilterShorthand | IssueFilterConfig; relationships?: FilterShorthand | RelationshipFilterConfig; feedback?: FilterShorthand | FeedbackFilterConfig; } /** * Entity types that can be partitioned. */ type PartitionableEntityType = 'specs' | 'issues'; /** * Rule for matching entities to partitions. */ interface PartitionRule { /** Name of the partition this rule routes to */ partition: string; /** Match criteria - all specified conditions must match (AND logic) */ match: { /** Only match these entity types */ entityType?: PartitionableEntityType[]; /** ID glob pattern */ idPattern?: string; /** Match entities with any of these tags (OR logic) */ tags?: string[]; /** Match by attribute path and value */ attribute?: { path: string; value: unknown; }; }; /** Priority for rule ordering (higher = checked first, default: 0) */ priority?: number; } /** * Configuration for namespace partitioning. */ interface PartitionConfig { /** Enable partitioning (default: false) */ enabled: boolean; /** Rules for routing entities to partitions */ rules: PartitionRule[]; /** Default partition for entities that don't match any rule */ defaultPartition?: string; /** Which partitions this peer subscribes to (syncs with) */ subscriptions?: string[]; } /** * Result of partition resolution for an entity. */ interface PartitionResult { /** Primary partition for the entity */ partition: string; /** Whether this partition is subscribed to */ subscribed: boolean; /** Rule that matched (null if default partition used) */ matchedRule: PartitionRule | null; } /** * Information about a partition. */ interface PartitionInfo { /** Partition name */ name: string; /** Full namespace including project ID */ namespace: string; /** Whether this partition is subscribed to */ subscribed: boolean; /** Entity count (if tracking enabled) */ entityCount?: number; } /** * Manages namespace partitioning for selective sync. * Routes entities to partitions based on configurable rules. */ declare class PartitionManager extends EventEmitter { private config; private projectId; private sortedRules; private compiledMatchers; private subscriptions; private knownPartitions; constructor(projectId: string, config?: PartitionConfig); /** * Check if partitioning is enabled. */ get enabled(): boolean; /** * Get the default partition name. */ get defaultPartition(): string; /** * Get list of subscribed partitions. */ getSubscriptions(): string[]; /** * Check if a partition is subscribed. */ isSubscribed(partition: string): boolean; /** * Subscribe to a partition. */ subscribe(partition: string): void; /** * Unsubscribe from a partition. */ unsubscribe(partition: string): void; /** * Get all known partitions. */ getKnownPartitions(): PartitionInfo[]; /** * Update partition configuration at runtime. */ setConfig(config: PartitionConfig): void; /** * Get the full namespace for a partition. * Format: sudocode:{projectId}:{partition} */ getNamespace(partition: string): string; /** * Extract partition name from a namespace. */ parseNamespace(namespace: string): string | null; /** * Resolve which partition an entity belongs to. */ resolvePartition(entityType: SudocodeEntityType, entity: SpecCRDT | IssueCRDT | RelationshipCRDT | FeedbackCRDT): PartitionResult; /** * Resolve partition for a spec. */ resolveSpecPartition(spec: SpecCRDT): PartitionResult; /** * Resolve partition for an issue. */ resolveIssuePartition(issue: IssueCRDT): PartitionResult; /** * Resolve partitions for a relationship. * May return multiple partitions if entities are in different partitions. */ resolveRelationshipPartitions(relationship: RelationshipCRDT, fromEntity?: SpecCRDT | IssueCRDT, toEntity?: SpecCRDT | IssueCRDT): string[]; /** * Check if an entity should be synced based on partition subscriptions. */ shouldSync(entityType: SudocodeEntityType, entity: SpecCRDT | IssueCRDT | RelationshipCRDT | FeedbackCRDT): boolean; private compileRules; private matchRule; private getNestedValue; } /** Entity types that can be selectively synced */ type SyncableEntityType = 'specs' | 'issues' | 'relationships' | 'feedback'; interface SudocodeMeshConfig { /** Unique project identifier */ projectId: string; /** Path to .sudocode/ directory */ projectPath: string; /** Mesh connection config */ meshConfig: NebulaMeshConfig; /** Debounce delay for JSONL saves (ms) */ saveDebounceMs?: number; /** Entity types to sync over mesh (default: all types) */ syncEntities?: SyncableEntityType[]; /** Fine-grained sync filter for ID patterns and attributes */ syncFilter?: SyncFilter; /** Namespace partitioning configuration for selective sync */ partitionConfig?: PartitionConfig; /** Permission configuration for group-based access control (Phase 9.5) */ permissionConfig?: SudocodePermissionConfig; } type IssueStatus = 'open' | 'in_progress' | 'blocked' | 'needs_review' | 'closed'; type EntityType = 'spec' | 'issue'; type RelationshipType = 'blocks' | 'related' | 'discovered-from' | 'implements' | 'references' | 'depends-on'; type FeedbackType = 'comment' | 'suggestion' | 'request'; /** * Spec data stored in CRDT Y.Map * Simplified from sudocode Spec type for efficient sync */ interface SpecCRDT { id: string; uuid: string; title: string; content: string; priority: number; archived: boolean; created_at: string; updated_at: string; parent_id?: string; parent_uuid?: string; } /** * Issue data stored in CRDT Y.Map */ interface IssueCRDT { id: string; uuid: string; title: string; status: IssueStatus; content: string; priority: number; assignee?: string; archived: boolean; created_at: string; updated_at: string; closed_at?: string; parent_id?: string; parent_uuid?: string; } /** * Relationship data stored in CRDT Y.Map * Key format: `${from_id}:${to_id}:${type}` */ interface RelationshipCRDT { from_id: string; from_uuid: string; from_type: EntityType; to_id: string; to_uuid: string; to_type: EntityType; relationship_type: RelationshipType; created_at: string; metadata?: string; } /** * Feedback anchor for tracking position in markdown */ interface FeedbackAnchorCRDT { section_heading?: string; section_level?: number; line_number?: number; line_offset?: number; text_snippet?: string; context_before?: string; context_after?: string; content_hash?: string; anchor_status: 'valid' | 'relocated' | 'stale'; last_verified_at?: string; original_location?: { line_number: number; section_heading?: string; }; } /** * Feedback data stored in CRDT Y.Map */ interface FeedbackCRDT { id: string; from_id?: string; from_uuid?: string; to_id: string; to_uuid: string; feedback_type: FeedbackType; content: string; agent?: string; anchor?: FeedbackAnchorCRDT; dismissed: boolean; created_at: string; updated_at: string; } declare function makeRelationshipKey(fromId: string, toId: string, type: RelationshipType): string; declare function parseRelationshipKey(key: string): { fromId: string; toId: string; type: RelationshipType; } | null; type EntityChangeSource = 'local' | 'remote' | 'reconcile'; type SudocodeEntityType = 'spec' | 'issue' | 'relationship' | 'feedback'; interface EntityChangeEvent { entityType: SudocodeEntityType; entity: T; source: EntityChangeSource; action: 'create' | 'update' | 'delete'; } interface SpecJSONL { id: string; uuid: string; title: string; file_path: string; content: string; priority: number; archived?: boolean; archived_at?: string; created_at: string; updated_at: string; parent_id?: string; parent_uuid?: string; relationships: RelationshipJSONL[]; tags: string[]; } interface IssueJSONL { id: string; uuid: string; title: string; status: IssueStatus; content: string; priority: number; assignee?: string; archived?: boolean; archived_at?: string; created_at: string; updated_at: string; closed_at?: string; parent_id?: string; parent_uuid?: string; relationships: RelationshipJSONL[]; tags: string[]; feedback?: FeedbackJSONL[]; } interface RelationshipJSONL { from: string; from_type: EntityType; to: string; to_type: EntityType; type: RelationshipType; } interface FeedbackJSONL { id: string; from_id?: string; to_id: string; feedback_type: FeedbackType; content: string; agent?: string; anchor?: FeedbackAnchorCRDT; dismissed?: boolean; created_at: string; updated_at: string; } /** * Options for requesting issue execution on a remote peer. */ interface IssueExecutionOptions { /** Agent type to use for execution */ agentType?: 'claude-code' | 'custom'; /** Worktree sync strategy */ worktreeSync?: 'none' | 'squash' | 'rebase'; /** Optional timeout in ms */ timeout?: number; /** Whether to stream execution output */ stream?: boolean; } /** * Result of an issue execution request. */ interface IssueExecutionResult { /** Whether execution was successful */ success: boolean; /** Issue ID that was executed */ issueId: string; /** Peer that executed the issue */ peerId: string; /** Exit code (0 for success) */ exitCode?: number; /** Execution output */ output?: string; /** Error message if failed */ error?: string; } /** * Sudocode mesh actions that can be permission-checked. */ type SudocodeAction = 'read' | 'write' | 'execute' | 'admin'; /** * Permission configuration for SudocodeMeshService. */ interface SudocodePermissionConfig { /** Groups that have admin access */ adminGroups?: string[]; /** Groups that have developer (read/write/execute) access */ developerGroups?: string[]; /** Groups that have read-only access */ readonlyGroups?: string[]; } /** * Result of a permission check. */ interface SudocodePermissionResult { allowed: boolean; action: SudocodeAction; peerGroups: string[]; requiredGroups?: string[]; } declare class SudocodeMeshService extends EventEmitter { private config; private mesh; private provider; private mapper; private bridge; private gitReconciler; private executionRouter; private saveDebounceTimer; private _connected; private syncEntities; private filterEngine; private partitionManager; private permissions; private specs; private issues; private relationships; private feedback; constructor(config: SudocodeMeshConfig); /** * Check if a specific entity type should be synced over the mesh. * Returns true if sync is enabled for this type. */ shouldSyncEntityType(entityType: SyncableEntityType): boolean; /** * Get the list of entity types enabled for sync. */ getSyncedEntityTypes(): SyncableEntityType[]; /** * Set or update the sync filter at runtime. * Use this for fine-grained control over which entities sync. */ setSyncFilter(filter: SyncFilter): void; /** * Get the current sync filter configuration. */ getSyncFilter(): SyncFilter; /** * Clear all sync filters (sync everything that passes entity type filter). */ clearSyncFilter(): void; /** * Check if a specific spec passes the sync filter. */ shouldSyncSpec(spec: SpecCRDT): boolean; /** * Check if a specific issue passes the sync filter. */ shouldSyncIssue(issue: IssueCRDT): boolean; /** * Check if a specific relationship passes the sync filter. */ shouldSyncRelationship(rel: RelationshipCRDT): boolean; /** * Check if specific feedback passes the sync filter. */ shouldSyncFeedback(fb: FeedbackCRDT): boolean; /** * Check if partitioning is enabled. */ get partitioningEnabled(): boolean; /** * Get the partition manager for advanced partition operations. */ getPartitionManager(): PartitionManager; /** * Set or update partition configuration at runtime. */ setPartitionConfig(config: PartitionConfig): void; /** * Subscribe to a partition (will sync entities in that partition). */ subscribeToPartition(partition: string): void; /** * Unsubscribe from a partition (will stop syncing entities in that partition). */ unsubscribeFromPartition(partition: string): void; /** * Get list of partitions this peer is subscribed to. */ getSubscribedPartitions(): string[]; /** * Get all known partitions with subscription status. */ getKnownPartitions(): PartitionInfo[]; /** * Check if a spec should be synced (combines type, filter, and partition checks). */ shouldSyncSpecWithPartition(spec: SpecCRDT): boolean; /** * Check if an issue should be synced (combines type, filter, and partition checks). */ shouldSyncIssueWithPartition(issue: IssueCRDT): boolean; /** * Check if a relationship should be synced (combines type, filter, and partition checks). */ shouldSyncRelationshipWithPartition(rel: RelationshipCRDT): boolean; /** * Check if feedback should be synced (combines type, filter, and partition checks). */ shouldSyncFeedbackWithPartition(fb: FeedbackCRDT): boolean; connect(): Promise; /** * Set up execution event forwarding. */ private setupExecutionHandlers; /** * Handle git-induced file changes. * Implements "git wins" reconciliation. */ private handleGitChange; disconnect(): Promise; get connected(): boolean; get synced(): boolean; get peers(): PeerInfo[]; /** * Sync a spec change to CRDT. * Skips sync if 'specs' entity type is not enabled or spec doesn't pass filter. */ syncSpec(spec: SpecCRDT, source?: EntityChangeSource): void; /** * Sync an issue change to CRDT. * Skips sync if 'issues' entity type is not enabled or issue doesn't pass filter. */ syncIssue(issue: IssueCRDT, source?: EntityChangeSource): void; /** * Sync a relationship change to CRDT. * Skips sync if 'relationships' entity type is not enabled or doesn't pass filter. */ syncRelationship(relationship: RelationshipCRDT, source?: EntityChangeSource): void; /** * Sync feedback change to CRDT. * Skips sync if 'feedback' entity type is not enabled or doesn't pass filter. */ syncFeedback(fb: FeedbackCRDT, source?: EntityChangeSource): void; /** * Delete a spec from CRDT. * Skips if 'specs' entity type is not enabled. */ deleteSpec(id: string, source?: EntityChangeSource): void; /** * Delete an issue from CRDT. * Skips if 'issues' entity type is not enabled. */ deleteIssue(id: string, source?: EntityChangeSource): void; /** * Delete a relationship from CRDT. * Skips if 'relationships' entity type is not enabled. */ deleteRelationship(key: string, source?: EntityChangeSource): void; /** * Delete feedback from CRDT. * Skips if 'feedback' entity type is not enabled. */ deleteFeedback(id: string, source?: EntityChangeSource): void; getSpec(id: string): SpecCRDT | undefined; getIssue(id: string): IssueCRDT | undefined; getAllSpecs(): SpecCRDT[]; getAllIssues(): IssueCRDT[]; getAllRelationships(): RelationshipCRDT[]; getAllFeedback(): FeedbackCRDT[]; /** * Trigger "git wins" reconciliation * Called when JSONL files are updated externally (e.g., git pull) */ reconcileFromJSONL(): Promise; private setupObservers; /** * Map SudocodeEntityType to SyncableEntityType for filtering. */ private entityTypeToSyncable; private handleMapChange; private ensureMeshDirectory; private loadInitialState; private loadCRDTSnapshot; private saveCRDTSnapshot; private scheduleSave; private saveToJSONL; /** * Manually trigger git reconciliation check. * Useful after operations like git pull, git checkout, etc. */ checkForGitChanges(): Promise; /** * Request execution of an issue on a remote peer. * * @param peerId Target peer to execute on * @param issueId Issue ID to execute * @param options Execution options * @returns Execution result * * @example * ```typescript * const result = await meshService.requestExecution('bob-workstation', 'i-abc1', { * agentType: 'claude-code', * worktreeSync: 'squash' * }) * ``` */ requestExecution(peerId: string, issueId: string, options?: IssueExecutionOptions): Promise; /** * Request streaming execution of an issue on a remote peer. * Returns an ExecutionStream for real-time output. * * @param peerId Target peer to execute on * @param issueId Issue ID to execute * @param options Execution options * @returns ExecutionStream for receiving output * * @example * ```typescript * const stream = meshService.requestExecutionWithStream('bob-workstation', 'i-abc1') * stream.on('stdout', (data) => console.log(data)) * stream.on('exit', (code) => console.log('Done:', code)) * ``` */ requestExecutionWithStream(peerId: string, issueId: string, options?: IssueExecutionOptions): ExecutionStream; /** * Build the execution command for an issue. */ private buildExecutionCommand; /** * Get the execution router for advanced operations. */ getExecutionRouter(): ExecutionRouter | null; /** * Check if a peer has permission for a specific action. * * Permission model: * - read: All groups can read * - write: developer/admin groups can write * - execute: developer/admin groups can execute * - admin: admin groups only * * @param peer The peer to check permissions for * @param action The action to check * @returns Permission check result * * @example * ```typescript * const result = meshService.checkPermission(peer, 'write') * if (result.allowed) { * // Allow write operation * } * ``` */ checkPermission(peer: PeerInfo, action: SudocodeAction): SudocodePermissionResult; /** * Check if a peer can read entities. */ canRead(peer: PeerInfo): boolean; /** * Check if a peer can write entities. */ canWrite(peer: PeerInfo): boolean; /** * Check if a peer can execute issues. */ canExecute(peer: PeerInfo): boolean; /** * Check if a peer has admin access. */ canAdmin(peer: PeerInfo): boolean; /** * Enforce a permission, throwing an error if denied. */ enforcePermission(peer: PeerInfo, action: SudocodeAction): void; /** * Get the GroupPermissions instance for advanced operations. */ getPermissions(): GroupPermissions; /** * Map action to permission level. */ private actionToPermissionLevel; } interface MultiProjectConfig { /** Mesh configuration (shared across all projects) */ meshConfig: NebulaMeshConfig; } interface ProjectInfo { /** Unique project ID */ projectId: string; /** Local path to project */ projectPath: string; /** Whether this project is currently connected */ connected: boolean; /** Namespace used for sync */ namespace: string; } interface ProjectAddedEvent { projectId: string; projectPath: string; } interface ProjectRemovedEvent { projectId: string; } interface ProjectSyncedEvent { projectId: string; } /** * MultiProjectManager - Manages multiple sudocode projects on a shared mesh. * * This class enables: * - Single mesh connection shared across multiple projects * - Project-scoped sync (each project syncs independently via namespaces) * - Easy project switching and management * - Namespace isolation (projects don't interfere with each other) * * @example * ```typescript * const manager = new MultiProjectManager({ * meshConfig: { * peerId: 'my-peer', * nebulaIp: '10.0.0.1', * peers: [...], * } * }) * * await manager.connect() * * // Add projects * await manager.addProject('project-a', '/path/to/project-a') * await manager.addProject('project-b', '/path/to/project-b') * * // Get project services * const projectA = manager.getProject('project-a') * const specs = projectA?.getSpecs() * * // List all projects * const projects = manager.listProjects() * ``` */ declare class MultiProjectManager extends EventEmitter { private config; private mesh; private projects; private projectPaths; private _connected; constructor(config: MultiProjectConfig); /** * Connect to the mesh network. * Must be called before adding projects. */ connect(): Promise; /** * Disconnect from the mesh and all projects. */ disconnect(): Promise; /** * Check if the manager is connected to the mesh. */ get connected(): boolean; /** * Get the underlying mesh instance. */ getMesh(): NebulaMesh | null; /** * Add and connect a project. * Each project syncs independently via its own namespace. */ addProject(projectId: string, projectPath: string): Promise; /** * Remove and disconnect a project. */ removeProject(projectId: string): Promise; /** * Get a project's service by ID. */ getProject(projectId: string): SudocodeMeshService | undefined; /** * Check if a project exists. */ hasProject(projectId: string): boolean; /** * List all projects with their info. */ listProjects(): ProjectInfo[]; /** * Get all project IDs. */ getProjectIds(): string[]; /** * Get the number of active projects. */ get projectCount(): number; /** * Get projects that a specific peer is participating in. * Uses namespace registry to determine which projects the peer is syncing. */ getProjectsForPeer(peerId: string): string[]; /** * Get peers that are participating in a specific project. */ getPeersForProject(projectId: string): string[]; /** * Get all active sudocode namespaces on the mesh. * Returns project IDs (without the 'sudocode:' prefix). */ getActiveProjectNamespaces(): string[]; } declare class EntityMapper { specToCRDT(spec: SpecJSONL): SpecCRDT; specToJSONL(crdt: SpecCRDT, relationships: RelationshipJSONL[], tags: string[]): SpecJSONL; private generateSpecFilePath; issueToCRDT(issue: IssueJSONL): IssueCRDT; issueToJSONL(crdt: IssueCRDT, relationships: RelationshipJSONL[], tags: string[], feedback?: FeedbackJSONL[]): IssueJSONL; relationshipToCRDT(rel: RelationshipJSONL, fromUuid: string, toUuid: string, createdAt: string): RelationshipCRDT; relationshipToJSONL(crdt: RelationshipCRDT): RelationshipJSONL; feedbackToCRDT(fb: FeedbackJSONL, toUuid: string, fromUuid?: string): FeedbackCRDT; feedbackToJSONL(crdt: FeedbackCRDT): FeedbackJSONL; } interface SudocodeState { specs: SpecCRDT[]; issues: IssueCRDT[]; relationships: RelationshipCRDT[]; feedback: FeedbackCRDT[]; } declare class JSONLBridge { private projectPath; private mapper; private lastHashes; constructor(projectPath: string); loadFromJSONL(): Promise; saveToJSONL(state: SudocodeState): Promise; hasJSONLChanged(): Promise; private updateHashes; private hashString; private readJSONLFile; private writeJSONLFile; private deduplicateRelationships; } interface GitReconcilerConfig { /** Project path containing JSONL files */ projectPath: string; /** Debounce delay for file changes in ms. Default: 100 */ debounceMs?: number; /** Whether to start watching immediately. Default: true */ autoStart?: boolean; } interface FileHashState { path: string; hash: string | null; lastModified: number; } interface ReconcileEvent { changedFiles: string[]; trigger: 'git' | 'external' | 'manual'; timestamp: Date; } declare class GitReconciler extends EventEmitter { private config; private watchers; private fileHashes; private debounceTimer; private pendingChanges; private isReconciling; private running; private ignoredFiles; constructor(config: GitReconcilerConfig); /** * Start watching JSONL files for changes. */ start(): void; /** * Stop watching files. */ stop(): void; /** * Check if reconciler is running. */ get isRunning(): boolean; /** * Update hashes for all watched files. * Call this after writing to JSONL to prevent false positives. */ updateAllHashes(): void; /** * Mark that the next change should be ignored (we're about to write). * Use this before writing to JSONL to prevent triggering reconciliation. */ ignoreNextWrite(): void; /** * Get current hash state for a file. */ getFileHash(filename: string): FileHashState | undefined; /** * Get all file hash states. */ getAllHashes(): FileHashState[]; private updateFileHash; /** * Check if JSONL files have been modified externally (e.g., by git). * Returns list of changed files. */ checkForExternalChanges(): string[]; /** * Manually trigger reconciliation check. */ checkAndReconcile(): Promise; private watchDirectory; private handleFileChange; private processChanges; private detectTriggerType; } /** * ACP JSON-RPC request */ interface AcpRequest { jsonrpc: '2.0'; id: string | number; method: string; params?: unknown; } /** * ACP JSON-RPC response */ interface AcpResponse { jsonrpc: '2.0'; id: string | number; result?: unknown; error?: AcpError; } /** * ACP JSON-RPC notification (no id, no response expected) */ interface AcpNotification { jsonrpc: '2.0'; method: string; params?: unknown; } /** * ACP error object */ interface AcpError { code: number; message: string; data?: unknown; } /** * Union of all ACP message types */ type AcpMessage = AcpRequest | AcpResponse | AcpNotification; /** * Envelope for ACP messages sent over mesh */ interface AcpMeshEnvelope { type: 'acp:message'; message: AcpMessage; /** Target groups for filtered broadcast (optional) */ targetGroups?: string[]; } /** * Broadcast target options */ type BroadcastTarget = { kind: 'all'; } | { kind: 'group'; groups: string[]; }; /** * Configuration for AcpMeshAdapter */ interface AcpMeshAdapterConfig { /** Channel name for ACP messages (default: 'acp') */ channel?: string; /** Default timeout for requests in ms (default: 30000) */ timeout?: number; /** Allow access from any group (default: false - require shared group) */ allowAllGroups?: boolean; } /** * Session metadata returned by list operations */ interface SessionInfo { sessionId: string; mode: string; createdAt: string; active: boolean; /** Optional: current activity description */ activity?: string; } /** * Request to observe a session on a remote peer */ interface SessionObserveRequest extends AcpRequest { method: 'session/observe'; params: { sessionId: string; }; } /** * Response to session/observe request */ interface SessionObserveResponse extends AcpResponse { result?: { success: boolean; /** Error message if not successful */ error?: string; }; } /** * Request to stop observing a session */ interface SessionUnobserveRequest extends AcpRequest { method: 'session/unobserve'; params: { sessionId: string; }; } /** * Request to list sessions on a peer */ interface SessionListRequest extends AcpRequest { method: 'session/list'; params: { /** Include inactive/ended sessions (default: false) */ includeInactive?: boolean; }; } /** * Response with session list */ interface SessionListResponse extends AcpResponse { result?: { sessions: SessionInfo[]; }; } /** * Notification when a session ends */ interface SessionEndedNotification extends AcpNotification { method: 'session/ended'; params: { sessionId: string; reason: 'completed' | 'cancelled' | 'error' | 'timeout'; }; } /** * Check if a message is an ACP request */ declare function isAcpRequest(message: AcpMessage): message is AcpRequest; /** * Check if a message is an ACP response */ declare function isAcpResponse(message: AcpMessage): message is AcpResponse; /** * Check if a message is an ACP notification */ declare function isAcpNotification(message: AcpMessage): message is AcpNotification; /** * Check if a message is a session/observe request */ declare function isSessionObserveRequest(message: AcpMessage): message is SessionObserveRequest; /** * Check if a message is a session/unobserve request */ declare function isSessionUnobserveRequest(message: AcpMessage): message is SessionUnobserveRequest; /** * Check if a message is a session/list request */ declare function isSessionListRequest(message: AcpMessage): message is SessionListRequest; /** * Check if a message is a session/ended notification */ declare function isSessionEndedNotification(message: AcpMessage): message is SessionEndedNotification; /** Response function passed to request handlers */ type RespondFn = (response: AcpResponse) => void; /** Callback for session update notifications */ type SessionUpdateCallback = (update: AcpNotification) => void; /** * Adapter that tunnels ACP messages through the mesh transport. * * Library consumers use this to connect their own ACP server to the mesh. * The adapter handles message routing, request/response correlation, and * group-based broadcast filtering. * * @example * ```typescript * import { NebulaMesh, AcpMeshAdapter } from 'agentic-mesh' * * const mesh = new NebulaMesh(config) * await mesh.start() * * const adapter = new AcpMeshAdapter(mesh) * await adapter.start() * * // Send ACP message to peer * adapter.send('peer-id', { * jsonrpc: '2.0', * method: 'session/update', * params: { status: 'working' } * }) * * // Receive messages from mesh * adapter.onMessage((message, from) => { * // Route to your ACP server * }) * * // Handle requests with response * adapter.onRequest((request, from, respond) => { * respond({ * jsonrpc: '2.0', * id: request.id, * result: { success: true } * }) * }) * ``` */ declare class AcpMeshAdapter extends EventEmitter { private mesh; private config; private channel; private _started; private observers; private peerSessions; private sessionCallbacks; private sessionUpdateListenerSetup; constructor(mesh: NebulaMesh, config?: AcpMeshAdapterConfig); /** * Start the adapter (opens the channel) */ start(): Promise; /** * Stop the adapter (closes the channel) */ stop(): Promise; /** * Check if the adapter is started */ get started(): boolean; /** * Send an ACP message to a specific peer. * * @param peerId Target peer ID * @param message ACP message to send * @returns true if sent successfully, false if peer is offline */ send(peerId: string, message: AcpMessage): boolean; /** * Send an ACP request and wait for response. * * Uses the underlying MessageChannel RPC support for request/response * correlation with timeout. * * @param peerId Target peer ID * @param request ACP request to send * @param timeout Timeout in ms (default: from config) * @returns Promise that resolves with the ACP response * @throws Error if timeout or peer not found */ request(peerId: string, request: AcpRequest, timeout?: number): Promise; /** * Broadcast an ACP message to peers. * * @param message ACP message to broadcast * @param target Optional target filter (default: all peers) */ broadcast(message: AcpMessage, target?: BroadcastTarget): void; /** * Register a handler for incoming ACP messages. * * Called for all message types (requests, responses, notifications). * * @param handler Function to handle messages */ onMessage(handler: (message: AcpMessage, from: PeerInfo) => void): void; /** * Remove a message handler. */ offMessage(handler: (message: AcpMessage, from: PeerInfo) => void): void; /** * Register a handler for incoming ACP requests. * * Called only for messages that are requests (have id and method). * The respond callback should be used to send the response. * * @param handler Function to handle requests */ onRequest(handler: (request: AcpRequest, from: PeerInfo, respond: RespondFn) => void): void; /** * Remove a request handler. */ offRequest(handler: (request: AcpRequest, from: PeerInfo, respond: RespondFn) => void): void; /** * Register a peer as an observer of a session. * * @param peerId The peer ID to register as observer * @param sessionId The session ID to observe */ registerObserver(peerId: string, sessionId: string): void; /** * Unregister a peer from observing a session. * * @param peerId The peer ID to unregister * @param sessionId The session ID to stop observing */ unregisterObserver(peerId: string, sessionId: string): void; /** * Get all observer peer IDs for a session. * * @param sessionId The session ID to get observers for * @returns Array of peer IDs observing the session */ getObservers(sessionId: string): string[]; /** * Handle peer disconnect - cleanup all their observations. * Called automatically on peer:left events. * * @param peerId The peer ID that disconnected */ handlePeerDisconnect(peerId: string): void; /** * Notify all observers that a session has ended. * Sends session/ended notification to all observers and cleans up. * * @param sessionId The session ID that ended * @param reason The reason the session ended */ notifySessionEnded(sessionId: string, reason: 'completed' | 'cancelled' | 'error' | 'timeout'): void; /** * Check if a peer can access this peer's sessions. * * Access is granted if: * - allowAllGroups config is true, OR * - The peer shares at least one group with the local peer * * @param peer The peer requesting access * @returns true if access is allowed */ canAccess(peer: PeerInfo): boolean; /** * Observe a session on a remote peer. * * Sends a session/observe request to the peer and registers a callback * for session/update notifications. The remote peer must accept the * observation request. * * @param peerId Remote peer ID * @param sessionId Session ID to observe * @param callback Called when session updates are received * @throws Error if adapter not started, peer denies access, or request fails * * @example * ```typescript * await adapter.observeSession('peer-b', 'session-1', (update) => { * console.log('Session update:', update.params) * }) * ``` */ observeSession(peerId: string, sessionId: string, callback: SessionUpdateCallback): Promise; /** * Stop observing a session on a remote peer. * * Sends a session/unobserve request and removes the local callback. * * @param peerId Remote peer ID * @param sessionId Session ID to stop observing * @throws Error if adapter not started */ unobserveSession(peerId: string, sessionId: string): Promise; /** * Setup listener for session/update notifications. * Routes updates to registered callbacks. */ private ensureSessionUpdateListener; /** * List sessions on a remote peer. * * Sends a session/list request to the peer and returns session metadata. * * @param peerId Remote peer ID * @param options Optional options * @param options.includeInactive Include inactive/ended sessions (default: false) * @param options.timeout Request timeout in ms (default: from config) * @returns Array of session info objects * @throws Error if adapter not started or request fails * * @example * ```typescript * const sessions = await adapter.listPeerSessions('peer-b') * for (const session of sessions) { * console.log(`Session ${session.sessionId} (${session.mode})`) * } * ``` */ listPeerSessions(peerId: string, options?: { includeInactive?: boolean; timeout?: number; }): Promise; private handleIncomingMessage; } /** * Configuration for mesh stream */ interface MeshStreamConfig { /** Channel name for ACP messages (default: 'acp') */ channel?: string; /** Target peer ID for point-to-point communication */ peerId: string; } /** * Creates an ACP SDK-compatible Stream that communicates over the mesh network. * * This allows using the official ACP SDK (AgentSideConnection, ClientSideConnection) * with mesh-based transport instead of stdio. * * @param mesh The NebulaMesh instance * @param config Stream configuration including target peer ID * @returns An ACP SDK Stream for bidirectional communication * * @example * ```typescript * import { AgentSideConnection } from '@agentclientprotocol/sdk' * import { NebulaMesh, meshStream } from 'agentic-mesh' * * const mesh = new NebulaMesh(config) * await mesh.connect() * * // Create a stream to communicate with a specific peer * const stream = meshStream(mesh, { peerId: 'peer-b' }) * * // Use the stream with the ACP SDK * const connection = new AgentSideConnection( * (conn) => new MyAgent(conn), * stream * ) * ``` */ declare function meshStream(mesh: NebulaMesh, config: MeshStreamConfig): Stream; /** * Creates a pair of connected streams for testing. * * Messages written to one stream's writable appear on the other's readable. * Useful for unit testing without a real mesh network. * * @returns A tuple of [streamA, streamB] that are connected * * @example * ```typescript * const [agentStream, clientStream] = createConnectedStreams() * * const agent = new AgentSideConnection((conn) => new MyAgent(conn), agentStream) * const client = new ClientSideConnection((agent) => new MyClient(agent), clientStream) * ``` */ declare function createConnectedStreams(): [Stream, Stream]; /** * Git Transport Types * * Type definitions for tunneling git protocol through agentic-mesh. * Supports git-upload-pack (fetch) and git-receive-pack (push) operations. */ /** A git reference (branch, tag, etc.) */ interface GitRef { /** SHA-1 hash of the object */ sha: string; /** Full ref name (e.g., refs/heads/main) */ name: string; /** For symrefs like HEAD, the target ref */ symref?: string; /** Whether this ref is peeled (for annotated tags) */ peeled?: string; } /** Git capabilities advertised by the server */ type GitCapability = 'thin-pack' | 'side-band' | 'side-band-64k' | 'shallow' | 'no-progress' | 'include-tag' | 'multi_ack' | 'multi_ack_detailed' | 'no-done' | 'symref' | 'quiet' | 'atomic' | 'push-options' | 'object-format' | 'filter' | 'allow-tip-sha1-in-want' | 'allow-reachable-sha1-in-want' | 'deepen-since' | 'deepen-not' | 'deepen-relative'; /** Request to list refs on a remote repository */ interface ListRefsRequest { /** Optional prefix to filter refs (e.g., "refs/heads/") */ refPrefix?: string; /** Whether this is for a push operation (may affect visibility) */ forPush?: boolean; /** Symrefs to resolve (e.g., ["HEAD"]) */ symrefs?: string[]; } /** Response from listing refs */ interface ListRefsResponse { /** List of refs */ refs: GitRef[]; /** Capabilities supported by the server */ capabilities: GitCapability[]; /** HEAD symref target if available */ head?: string; } /** Request for git-upload-pack (fetch) */ interface UploadPackRequest { /** Object SHAs the client wants */ wants: string[]; /** Object SHAs the client already has (for negotiation) */ haves: string[]; /** Shallow clone depth */ depth?: number; /** Partial clone filter (e.g., "blob:none") */ filter?: string; /** Shallow commits to deepen from */ shallowSince?: string; /** Refs to exclude from deepening */ deepenNot?: string[]; /** Whether to include tags */ includeTags?: boolean; /** Disable progress output */ noProgress?: boolean; } /** Response from git-upload-pack */ interface UploadPackResponse { /** Base64-encoded pack data (for JSON transport) */ packData?: string; /** Shallow commits if depth was specified */ shallows?: string[]; /** Acknowledged commits during negotiation */ acks?: string[]; /** Whether negotiation is complete */ ready?: boolean; } /** A ref update command for push */ interface RefUpdateCommand { /** Source ref or SHA (what to push) */ src: string; /** Destination ref on remote */ dst: string; /** Expected current value on remote (for CAS) */ oldSha?: string; /** New value to set */ newSha?: string; /** Force update even if not fast-forward */ force?: boolean; /** Delete the ref */ delete?: boolean; } /** Request for git-receive-pack (push) */ interface ReceivePackRequest { /** Ref update commands */ commands: RefUpdateCommand[]; /** Base64-encoded pack data containing objects to push */ packData?: string; /** Push options (if server supports push-options) */ pushOptions?: string[]; /** Atomic push - all or nothing */ atomic?: boolean; } /** Result of a single ref update */ interface RefUpdateResult { /** The ref that was updated */ ref: string; /** Whether the update succeeded */ status: 'ok' | 'rejected' | 'error'; /** Reason for rejection/error */ reason?: string; } /** Response from git-receive-pack */ interface ReceivePackResponse { /** Results for each ref update */ results: RefUpdateResult[]; /** Server-side messages */ messages?: string[]; } /** Configuration for the git transport handler */ interface GitTransportConfig { /** Whether git transport is enabled */ enabled: boolean; /** Path to the git repository */ repoPath: string; /** Clone/fetch configuration */ clone: { /** Allow shallow clones */ allowShallow: boolean; /** Maximum depth for shallow clones (0 = unlimited) */ maxDepth?: number; /** Allow partial clones */ allowPartial: boolean; /** Allowed partial clone filters */ allowedFilters?: string[]; }; /** Push configuration */ push: { /** Refs that cannot be force-pushed */ protectedBranches: string[]; /** Require signed commits */ requireSigned: boolean; /** Allow deleting refs */ allowDelete: boolean; /** Allow non-fast-forward pushes */ allowNonFastForward: boolean; }; /** Timeout for git operations in milliseconds */ operationTimeoutMs: number; /** Maximum pack size in bytes (0 = unlimited) */ maxPackSize: number; } /** Default git transport configuration */ declare const DEFAULT_GIT_TRANSPORT_CONFIG: GitTransportConfig; /** Git access level */ type GitAccessLevel = 'none' | 'read' | 'write' | 'admin'; /** Git access check result */ interface GitAccessCheckResult { allowed: boolean; level: GitAccessLevel; reason?: string; } /** Interface for git access control */ interface GitAccessControl { /** Check if peer can read from this repo */ checkRead(peerId: string): Promise; /** Check if peer can write to this repo */ checkWrite(peerId: string): Promise; /** Check if peer can update a specific ref */ checkRefUpdate(peerId: string, ref: string, force: boolean): Promise; /** Check if peer can delete a ref */ checkRefDelete(peerId: string, ref: string): Promise; } /** Interface for handling git protocol operations */ interface GitProtocolHandler { /** List refs in the repository */ listRefs(request: ListRefsRequest): Promise; /** Handle fetch (git-upload-pack) */ uploadPack(request: UploadPackRequest): Promise; /** Handle push (git-receive-pack) */ receivePack(request: ReceivePackRequest): Promise; /** Get the current configuration */ getConfig(): GitTransportConfig; /** Update configuration */ updateConfig(config: Partial): void; } /** Options for streaming pack data */ interface PackStreamOptions { /** Chunk size for streaming (default: 64KB) */ chunkSize?: number; /** Progress callback */ onProgress?: (bytesTransferred: number, totalBytes?: number) => void; /** Abort signal */ signal?: AbortSignal; } /** A streaming pack transfer */ interface PackStream { /** Async iterator for reading pack chunks */ read(): AsyncIterable; /** Total size if known */ totalSize?: number; /** Abort the transfer */ abort(): void; } /** Git protocol message types for MAP routing */ type GitMessageType = 'git/list-refs' | 'git/upload-pack' | 'git/receive-pack' | 'git/pack-stream' | 'git/pack-chunk' | 'git/pack-complete' | 'git/error'; /** Base git protocol message */ interface GitMessage { type: GitMessageType; /** Correlation ID for request/response matching */ correlationId: string; /** Repository path (for multi-repo support) */ repoPath?: string; } /** Git list-refs request message */ interface GitListRefsMessage extends GitMessage { type: 'git/list-refs'; request: ListRefsRequest; } /** Git upload-pack request message */ interface GitUploadPackMessage extends GitMessage { type: 'git/upload-pack'; request: UploadPackRequest; } /** Git receive-pack request message */ interface GitReceivePackMessage extends GitMessage { type: 'git/receive-pack'; request: ReceivePackRequest; } /** Git pack stream initiation message */ interface GitPackStreamMessage extends GitMessage { type: 'git/pack-stream'; /** Direction of the stream */ direction: 'upload' | 'download'; /** Total size if known */ totalSize?: number; } /** Git pack chunk message (for streaming) */ interface GitPackChunkMessage extends GitMessage { type: 'git/pack-chunk'; /** Base64-encoded chunk data */ data: string; /** Chunk sequence number */ sequence: number; /** Whether this is the last chunk */ final: boolean; } /** Git pack complete message */ interface GitPackCompleteMessage extends GitMessage { type: 'git/pack-complete'; /** SHA-256 checksum of complete pack */ checksum: string; /** Total bytes transferred */ totalBytes: number; } /** Git error message */ interface GitErrorMessage extends GitMessage { type: 'git/error'; code: string; message: string; details?: Record; } /** Git list-refs response message */ interface GitListRefsResponseMessage extends GitMessage { type: 'git/list-refs'; response: ListRefsResponse; } /** Git upload-pack response message */ interface GitUploadPackResponseMessage extends GitMessage { type: 'git/upload-pack'; response: UploadPackResponse; } /** Git receive-pack response message */ interface GitReceivePackResponseMessage extends GitMessage { type: 'git/receive-pack'; response: ReceivePackResponse; } /** Union of all git protocol messages (requests and responses) */ type AnyGitMessage = GitListRefsMessage | GitUploadPackMessage | GitReceivePackMessage | GitListRefsResponseMessage | GitUploadPackResponseMessage | GitReceivePackResponseMessage | GitPackStreamMessage | GitPackChunkMessage | GitPackCompleteMessage | GitErrorMessage; /** URL components for mesh:// URLs */ interface MeshGitUrl { /** Protocol (always "mesh") */ protocol: 'mesh'; /** Remote peer ID */ peerId: string; /** Repository path on remote */ repoPath: string; } /** Configuration for the git-remote-mesh helper */ interface GitRemoteHelperConfig { /** URL of the local MeshPeer HTTP server */ meshPeerUrl: string; /** Connection timeout in milliseconds */ connectionTimeoutMs: number; /** Operation timeout in milliseconds */ operationTimeoutMs: number; /** Enable verbose logging */ verbose: boolean; } /** Default git remote helper configuration */ declare const DEFAULT_GIT_REMOTE_HELPER_CONFIG: GitRemoteHelperConfig; /** Unique identifier for any participant (agent, client, system, gateway) */ type ParticipantId = string; /** Unique identifier for an agent */ type AgentId = string; /** Unique identifier for a scope */ type ScopeId = string; /** Unique identifier for a session */ type SessionId = string; /** Unique identifier for a message */ type MessageId = string; /** Unique identifier for a subscription */ type SubscriptionId = string; /** Identifier for correlating related messages */ type CorrelationId = string; /** JSON-RPC request ID */ type RequestId = string | number; /** MAP protocol version */ type ProtocolVersion = 1; /** Protocol version constant */ declare const PROTOCOL_VERSION: ProtocolVersion; /** Unix timestamp in milliseconds */ type Timestamp = number; /** Vendor extension metadata */ type Meta = Record; /** JSON-RPC version constant */ declare const JSONRPC_VERSION: "2.0"; /** JSON-RPC standard error codes */ declare const PROTOCOL_ERROR_CODES: { readonly PARSE_ERROR: -32700; readonly INVALID_REQUEST: -32600; readonly METHOD_NOT_FOUND: -32601; readonly INVALID_PARAMS: -32602; readonly INTERNAL_ERROR: -32603; }; /** Authentication error codes */ declare const AUTH_ERROR_CODES: { readonly AUTH_REQUIRED: 1000; readonly AUTH_FAILED: 1001; readonly TOKEN_EXPIRED: 1002; readonly PERMISSION_DENIED: 1003; }; /** Routing error codes */ declare const ROUTING_ERROR_CODES: { readonly ADDRESS_NOT_FOUND: 2000; readonly AGENT_NOT_FOUND: 2001; readonly SCOPE_NOT_FOUND: 2002; readonly DELIVERY_FAILED: 2003; readonly ADDRESS_AMBIGUOUS: 2004; }; /** Agent error codes */ declare const AGENT_ERROR_CODES: { readonly AGENT_EXISTS: 3000; readonly STATE_INVALID: 3001; readonly NOT_RESPONDING: 3002; readonly TERMINATED: 3003; readonly SPAWN_FAILED: 3004; }; /** Resource error codes */ declare const RESOURCE_ERROR_CODES: { readonly EXHAUSTED: 4000; readonly RATE_LIMITED: 4001; readonly QUOTA_EXCEEDED: 4002; }; /** Federation error codes */ declare const FEDERATION_ERROR_CODES: { readonly FEDERATION_UNAVAILABLE: 5000; readonly FEDERATION_SYSTEM_NOT_FOUND: 5001; readonly FEDERATION_AUTH_FAILED: 5002; readonly FEDERATION_ROUTE_REJECTED: 5003; readonly FEDERATION_LOOP_DETECTED: 5010; readonly FEDERATION_MAX_HOPS_EXCEEDED: 5011; }; /** All error codes */ declare const ERROR_CODES: { readonly FEDERATION_UNAVAILABLE: 5000; readonly FEDERATION_SYSTEM_NOT_FOUND: 5001; readonly FEDERATION_AUTH_FAILED: 5002; readonly FEDERATION_ROUTE_REJECTED: 5003; readonly FEDERATION_LOOP_DETECTED: 5010; readonly FEDERATION_MAX_HOPS_EXCEEDED: 5011; readonly EXHAUSTED: 4000; readonly RATE_LIMITED: 4001; readonly QUOTA_EXCEEDED: 4002; readonly AGENT_EXISTS: 3000; readonly STATE_INVALID: 3001; readonly NOT_RESPONDING: 3002; readonly TERMINATED: 3003; readonly SPAWN_FAILED: 3004; readonly ADDRESS_NOT_FOUND: 2000; readonly AGENT_NOT_FOUND: 2001; readonly SCOPE_NOT_FOUND: 2002; readonly DELIVERY_FAILED: 2003; readonly ADDRESS_AMBIGUOUS: 2004; readonly AUTH_REQUIRED: 1000; readonly AUTH_FAILED: 1001; readonly TOKEN_EXPIRED: 1002; readonly PERMISSION_DENIED: 1003; readonly PARSE_ERROR: -32700; readonly INVALID_REQUEST: -32600; readonly METHOD_NOT_FOUND: -32601; readonly INVALID_PARAMS: -32602; readonly INTERNAL_ERROR: -32603; }; /** Core protocol methods */ declare const CORE_METHODS: { readonly CONNECT: "map/connect"; readonly DISCONNECT: "map/disconnect"; readonly SEND: "map/send"; readonly SUBSCRIBE: "map/subscribe"; readonly UNSUBSCRIBE: "map/unsubscribe"; }; /** Observation methods */ declare const OBSERVATION_METHODS: { readonly AGENTS_LIST: "map/agents.list"; readonly AGENTS_GET: "map/agents.get"; readonly SCOPES_LIST: "map/scopes.list"; readonly SCOPES_GET: "map/scopes.get"; readonly SCOPES_MEMBERS: "map/scopes.members"; readonly STRUCTURE_GRAPH: "map/structure.graph"; }; /** Lifecycle methods */ declare const LIFECYCLE_METHODS: { readonly AGENTS_REGISTER: "map/agents.register"; readonly AGENTS_UNREGISTER: "map/agents.unregister"; readonly AGENTS_SPAWN: "map/agents.spawn"; }; /** State methods */ declare const STATE_METHODS: { readonly AGENTS_UPDATE: "map/agents.update"; readonly SCOPES_CREATE: "map/scopes.create"; readonly SCOPES_DELETE: "map/scopes.delete"; readonly SCOPES_JOIN: "map/scopes.join"; readonly SCOPES_LEAVE: "map/scopes.leave"; }; /** Federation methods */ declare const FEDERATION_METHODS: { readonly ROUTE: "map/federation.route"; readonly ANNOUNCE: "map/federation.announce"; readonly CONNECT: "map/federation.connect"; readonly DISCONNECT: "map/federation.disconnect"; readonly FEDERATION_CONNECT: "map/federation.connect"; readonly FEDERATION_ROUTE: "map/federation.route"; }; /** Notification methods */ declare const NOTIFICATION_METHODS: { readonly EVENT: "map/event"; readonly MESSAGE: "map/message"; readonly SUBSCRIPTION_ACK: "map/subscribe.ack"; readonly REPLAY: "map/events.replay"; }; /** All MAP methods */ declare const MAP_METHODS: { readonly EVENT: "map/event"; readonly MESSAGE: "map/message"; readonly SUBSCRIPTION_ACK: "map/subscribe.ack"; readonly REPLAY: "map/events.replay"; readonly ROUTE: "map/federation.route"; readonly ANNOUNCE: "map/federation.announce"; readonly CONNECT: "map/federation.connect"; readonly DISCONNECT: "map/federation.disconnect"; readonly FEDERATION_CONNECT: "map/federation.connect"; readonly FEDERATION_ROUTE: "map/federation.route"; readonly AGENTS_UPDATE: "map/agents.update"; readonly SCOPES_CREATE: "map/scopes.create"; readonly SCOPES_DELETE: "map/scopes.delete"; readonly SCOPES_JOIN: "map/scopes.join"; readonly SCOPES_LEAVE: "map/scopes.leave"; readonly AGENTS_REGISTER: "map/agents.register"; readonly AGENTS_UNREGISTER: "map/agents.unregister"; readonly AGENTS_SPAWN: "map/agents.spawn"; readonly AGENTS_LIST: "map/agents.list"; readonly AGENTS_GET: "map/agents.get"; readonly SCOPES_LIST: "map/scopes.list"; readonly SCOPES_GET: "map/scopes.get"; readonly SCOPES_MEMBERS: "map/scopes.members"; readonly STRUCTURE_GRAPH: "map/structure.graph"; readonly SEND: "map/send"; readonly SUBSCRIBE: "map/subscribe"; readonly UNSUBSCRIBE: "map/unsubscribe"; }; /** * Channel name prefixes for avoiding collisions on shared meshes. * * Protocol/infrastructure channels use "proto:" prefix. * Application channels use no prefix. * * @example * ```typescript * const channelName = `${CHANNEL_PREFIXES.PROTOCOL}agent-inbox`; // "proto:agent-inbox" * ``` */ declare const CHANNEL_PREFIXES: { /** Prefix for protocol/infrastructure channels */ readonly PROTOCOL: "proto:"; }; /** Category of error for handling decisions */ type ErrorCategory = 'protocol' | 'auth' | 'routing' | 'agent' | 'resource' | 'federation' | 'internal'; /** Structured error data */ interface MAPErrorData { category?: ErrorCategory; retryable?: boolean; retryAfterMs?: number; details?: Record; _meta?: Meta; } /** JSON-RPC 2.0 error object */ interface MAPError { code: number; message: string; data?: MAPErrorData | Record; } /** Type of participant in the protocol */ type ParticipantType = 'agent' | 'client' | 'system' | 'gateway'; /** Transport binding type */ type TransportType = 'websocket' | 'stdio' | 'inprocess' | 'http-sse'; /** Streaming capabilities for backpressure and flow control */ interface StreamingCapabilities { supportsAck?: boolean; supportsFlowControl?: boolean; supportsPause?: boolean; } /** Capabilities of a participant */ interface ParticipantCapabilities { observation?: { canObserve?: boolean; canQuery?: boolean; }; messaging?: { canSend?: boolean; canReceive?: boolean; canBroadcast?: boolean; }; lifecycle?: { canSpawn?: boolean; canRegister?: boolean; canUnregister?: boolean; canSteer?: boolean; canStop?: boolean; }; scopes?: { canCreateScopes?: boolean; canManageScopes?: boolean; }; federation?: { canFederate?: boolean; }; streaming?: StreamingCapabilities; _meta?: Meta; } /** A participant in the MAP protocol */ interface Participant { id: ParticipantId; type: ParticipantType; name?: string; capabilities?: ParticipantCapabilities; transport?: TransportType; sessionId?: SessionId; metadata?: Record; _meta?: Meta; } /** State of an agent */ type AgentState = 'registered' | 'active' | 'busy' | 'idle' | 'suspended' | 'stopping' | 'stopped' | 'failed' | 'orphaned' | `x-${string}`; /** Type of relationship between agents */ type AgentRelationshipType = 'peer' | 'supervisor' | 'supervised' | 'collaborator'; /** A relationship between agents */ interface AgentRelationship { type: AgentRelationshipType; agentId: AgentId; metadata?: Record; _meta?: Meta; } /** Lifecycle metadata for an agent */ interface AgentLifecycle { createdAt?: Timestamp; startedAt?: Timestamp; stoppedAt?: Timestamp; lastActiveAt?: Timestamp; orphanedAt?: Timestamp; exitCode?: number; exitReason?: string; _meta?: Meta; } /** Who can see this agent */ type AgentVisibility = 'public' | 'parent-only' | 'scope' | 'system'; /** Rule for which agents this agent can see */ type AgentVisibilityRule = 'all' | 'hierarchy' | 'scoped' | 'direct' | { include: AgentId[]; }; /** Rule for which scopes this agent can see */ type ScopeVisibilityRule = 'all' | 'member' | { include: ScopeId[]; }; /** Rule for how much agent hierarchy structure this agent can see */ type StructureVisibilityRule = 'full' | 'local' | 'none'; /** Rule for which agents this agent can send messages to */ type AgentMessagingRule = 'all' | 'hierarchy' | 'scoped' | { include: AgentId[]; }; /** Rule for which scopes this agent can send messages to */ type ScopeMessagingRule = 'all' | 'member' | { include: ScopeId[]; }; /** Rule for which agents this agent accepts messages from */ type AgentAcceptanceRule = 'all' | 'hierarchy' | 'scoped' | { include: AgentId[]; }; /** Rule for which clients this agent accepts messages from */ type ClientAcceptanceRule = 'all' | 'none' | { include: ParticipantId[]; }; /** Rule for which federated systems this agent accepts messages from */ type SystemAcceptanceRule = 'all' | 'none' | { include: string[]; }; /** Permission configuration for an agent */ interface AgentPermissions { canSee?: { agents?: AgentVisibilityRule; scopes?: ScopeVisibilityRule; structure?: StructureVisibilityRule; }; canMessage?: { agents?: AgentMessagingRule; scopes?: ScopeMessagingRule; }; acceptsFrom?: { agents?: AgentAcceptanceRule; clients?: ClientAcceptanceRule; systems?: SystemAcceptanceRule; }; } /** An agent in the multi-agent system */ interface Agent { id: AgentId; ownerId: ParticipantId | null; name?: string; description?: string; parent?: AgentId; children?: AgentId[]; relationships?: AgentRelationship[]; state: AgentState; role?: string; scopes?: ScopeId[]; visibility?: AgentVisibility; permissionOverrides?: Partial; lifecycle?: AgentLifecycle; capabilities?: ParticipantCapabilities; metadata?: Record; _meta?: Meta; } /** Address a single agent directly */ interface DirectAddress { agent: AgentId; } /** Address multiple agents */ interface MultiAddress { agents: AgentId[]; } /** Address all agents in a scope */ interface ScopeAddress { scope: ScopeId; } /** Address agents by role, optionally within a scope */ interface RoleAddress { role: string; within?: ScopeId; } /** Address relative to sender in hierarchy */ interface HierarchicalAddress { parent?: true; children?: true; ancestors?: true; descendants?: true; siblings?: true; depth?: number; } /** Address all agents in the system */ interface BroadcastAddress { broadcast: true; } /** Address the system/router itself */ interface SystemAddress { system: true; } /** Address any participant by ID or category */ interface ParticipantAddress { participant?: ParticipantId; participants?: 'all' | 'agents' | 'clients'; } /** Address an agent in a federated system */ interface FederatedAddress { system: string; agent: AgentId; } /** Flexible addressing for any topology */ type Address = string | DirectAddress | MultiAddress | ScopeAddress | RoleAddress | HierarchicalAddress | BroadcastAddress | SystemAddress | ParticipantAddress | FederatedAddress; /** Check if address is a direct agent address */ declare function isDirectAddress(address: Address): address is DirectAddress; /** Check if address is a multi-agent address */ declare function isMultiAddress(address: Address): address is MultiAddress; /** Check if address is a scope address */ declare function isScopeAddress(address: Address): address is ScopeAddress; /** Check if address is a role address */ declare function isRoleAddress(address: Address): address is RoleAddress; /** Check if address is a hierarchical address */ declare function isHierarchicalAddress(address: Address): address is HierarchicalAddress; /** Check if address is a broadcast address */ declare function isBroadcastAddress(address: Address): address is BroadcastAddress; /** Check if address is a system address */ declare function isSystemAddress(address: Address): address is SystemAddress; /** Check if address is a participant address */ declare function isParticipantAddress(address: Address): address is ParticipantAddress; /** Check if address is a federated address */ declare function isFederatedAddress(address: Address): address is FederatedAddress; /** * Parsed result of a federation-prefixed sender ID. * * When a message crosses a FederationGateway, the sender ID is prefixed * with the source system ID: "system-a:alice" instead of "alice". * This provides unambiguous cross-system identity. */ interface ParsedFederatedId { /** The source system ID, if the ID is federation-prefixed */ system?: string; /** The agent ID (without system prefix) */ agent: string; } /** * Parse a potentially federation-prefixed sender ID. * * FederationGateway prefixes sender IDs with the source system to provide * unambiguous cross-system identity: "system-a:alice" instead of "alice". * * @param id - The sender ID, potentially prefixed with "system:" * @returns Parsed system and agent components * * @example * ```typescript * parseFederatedId("system-a:alice") // { system: "system-a", agent: "alice" } * parseFederatedId("alice") // { agent: "alice" } * ``` */ declare function parseFederatedId(id: string): ParsedFederatedId; /** Message priority */ type MessagePriority = 'urgent' | 'high' | 'normal' | 'low'; /** Message delivery guarantees */ type DeliverySemantics = 'fire-and-forget' | 'acknowledged' | 'guaranteed'; /** Relationship context for the message */ type MessageRelationship = 'parent-to-child' | 'child-to-parent' | 'peer' | 'broadcast'; /** Metadata for a message */ interface MessageMeta { timestamp?: Timestamp; relationship?: MessageRelationship; expectsResponse?: boolean; correlationId?: CorrelationId; isResult?: boolean; priority?: MessagePriority; delivery?: DeliverySemantics; ttlMs?: number; _meta?: Meta; } /** A message in the multi-agent system */ interface Message { id: MessageId; from: ParticipantId; to: Address; timestamp: Timestamp; payload?: T; meta?: MessageMeta; _meta?: Meta; } /** Policy for joining a scope */ type JoinPolicy = 'open' | 'invite' | 'role' | 'system'; /** Who can see the scope exists and its members */ type ScopeVisibility = 'public' | 'members' | 'system'; /** Who can see messages sent to this scope */ type MessageVisibility = 'public' | 'members' | 'system'; /** Who can send messages to this scope */ type SendPolicy = 'members' | 'any'; /** A scope for grouping agents */ interface Scope { id: ScopeId; name?: string; description?: string; parent?: ScopeId; joinPolicy?: JoinPolicy; autoJoinRoles?: string[]; visibility?: ScopeVisibility; messageVisibility?: MessageVisibility; sendPolicy?: SendPolicy; persistent?: boolean; autoDelete?: boolean; metadata?: Record; _meta?: Meta; } /** Event type constants */ declare const EVENT_TYPES: { readonly AGENT_REGISTERED: "agent_registered"; readonly AGENT_UNREGISTERED: "agent_unregistered"; readonly AGENT_STATE_CHANGED: "agent_state_changed"; readonly AGENT_ORPHANED: "agent_orphaned"; readonly PARTICIPANT_CONNECTED: "participant_connected"; readonly PARTICIPANT_DISCONNECTED: "participant_disconnected"; readonly MESSAGE_SENT: "message_sent"; readonly MESSAGE_DELIVERED: "message_delivered"; readonly MESSAGE_FAILED: "message_failed"; readonly SCOPE_CREATED: "scope_created"; readonly SCOPE_DELETED: "scope_deleted"; readonly SCOPE_MEMBER_JOINED: "scope_member_joined"; readonly SCOPE_MEMBER_LEFT: "scope_member_left"; readonly FEDERATION_CONNECTED: "federation_connected"; readonly FEDERATION_DISCONNECTED: "federation_disconnected"; readonly SYSTEM_ERROR: "system_error"; }; /** Type of system event */ type EventType = (typeof EVENT_TYPES)[keyof typeof EVENT_TYPES]; /** Input for creating events */ interface EventInput { type: EventType; timestamp?: Timestamp; source?: ParticipantId; data?: Record; causedBy?: string[]; _meta?: Meta; } /** Wire event as sent to clients */ interface Event { id: string; type: EventType; timestamp: Timestamp; source?: ParticipantId; data?: Record; causedBy?: string[]; _meta?: Meta; } /** Helper to create events with auto-generated id and timestamp */ declare function createEvent(input: EventInput): Event; /** Filter for event subscriptions */ interface SubscriptionFilter { agents?: AgentId[]; roles?: string[]; scopes?: ScopeId[]; eventTypes?: EventType[]; priorities?: MessagePriority[]; correlationIds?: CorrelationId[]; fromAgents?: AgentId[]; fromRoles?: string[]; metadataMatch?: Record; _meta?: Meta; } /** Options for subscriptions */ interface SubscriptionOptions { includeMessagePayloads?: boolean; excludeOwnEvents?: boolean; } /** An active event subscription */ interface Subscription { id: SubscriptionId; filter?: SubscriptionFilter; options?: SubscriptionOptions; createdAt?: Timestamp; replayFrom?: Timestamp | string; _meta?: Meta; } type AuthMethod = 'bearer' | 'api-key' | 'mtls' | 'none'; interface AuthParams { method: AuthMethod; token?: string; } interface FederationAuth { method: 'bearer' | 'api-key' | 'mtls'; credentials?: string; } /** Policy for handling unexpected disconnection */ interface DisconnectPolicy { agentBehavior: 'unregister' | 'orphan' | 'grace-period'; gracePeriodMs?: number; notifySubscribers?: boolean; } /** Result from connect request */ interface ConnectResponseResult { protocolVersion: ProtocolVersion; sessionId: SessionId; participantId: ParticipantId; capabilities: ParticipantCapabilities; systemInfo?: { name?: string; version?: string; metadata?: Record; }; resumeToken?: string; reclaimedAgents?: AgentId[]; } /** Result from agents.list request */ interface AgentsListResponseResult { agents: Agent[]; } /** Routing configuration for federation */ interface FederationRoutingConfig { allowIncoming?: boolean; allowOutgoing?: boolean; routeAll?: boolean; agentFilter?: AgentId[]; scopeFilter?: ScopeId[]; maxHops?: number; trackPath?: boolean; allowedSources?: string[]; } /** Buffer configuration for federation during disconnections */ interface FederationBufferConfig { enabled?: boolean; maxSize?: number; maxAgeMs?: number; maxMessages?: number; maxBytes?: number; retentionMs?: number; overflowStrategy?: 'drop-oldest' | 'drop-newest' | 'reject'; } /** Metadata for a federated message */ interface FederationMetadata { sourceSystem: string; targetSystem: string; hopCount: number; maxHops?: number; path?: string[]; timestamp?: Timestamp; originTimestamp?: Timestamp; ttl?: number; correlationId?: CorrelationId; } /** Envelope for a federated message */ interface FederationEnvelope { payload: T; federation: FederationMetadata; } /** Event for gateway reconnection */ interface GatewayReconnectionEvent { type?: 'connected' | 'disconnected' | 'reconnecting' | 'reconnected' | 'failed' | 'reconnect_failed' | 'buffer_overflow'; systemId: string; timestamp?: Timestamp; attempt?: number; delayMs?: number; bufferedCount?: number; } /** * A MAP protocol frame - either a request, response, or notification. */ type MapFrame = MapRequestFrame | MapResponseFrame | MapNotificationFrame; interface MapRequestFrame { jsonrpc: '2.0'; id: string | number; method: string; params?: unknown; } interface MapResponseFrame { jsonrpc: '2.0'; id: string | number; result?: unknown; error?: { code: number; message: string; data?: unknown; }; } interface MapNotificationFrame { jsonrpc: '2.0'; method: string; params?: unknown; } /** * Configuration for a MAP server running on a mesh peer. */ interface MapServerConfig { /** Unique identifier for this peer/system */ systemId: string; /** Human-readable name for this system */ systemName?: string; /** System version */ systemVersion?: string; /** Default capabilities granted to connecting agents */ defaultAgentCapabilities?: ParticipantCapabilities; /** Default capabilities granted to connecting clients */ defaultClientCapabilities?: ParticipantCapabilities; /** Permission configuration for agents */ permissionConfig?: MapPermissionConfig; /** Federation configuration */ federation?: { enabled?: boolean; routing?: FederationRoutingConfig; buffer?: FederationBufferConfig; }; /** Event retention for replay (milliseconds) */ eventRetentionMs?: number; /** Maximum events to retain */ maxRetainedEvents?: number; } /** * Permission configuration for the MAP server. */ interface MapPermissionConfig { defaultPermissions?: AgentPermissions; rolePermissions?: Record; } /** * State of a MAP connection. */ type MapConnectionState = 'connecting' | 'connected' | 'disconnecting' | 'disconnected' | 'error'; /** * Configuration for a peer-to-peer MAP connection over agentic-mesh transport. */ interface MapPeerConnectionConfig { localPeerId: string; remotePeerId: string; remoteEndpoint: PeerEndpoint; transport: TransportAdapter; connectionTimeout?: number; reconnection?: { enabled?: boolean; maxRetries?: number; initialDelayMs?: number; maxDelayMs?: number; backoffMultiplier?: number; }; } /** * Events emitted by a MAP peer connection. */ interface MapPeerConnectionEvents { 'state:changed': (state: MapConnectionState, previousState: MapConnectionState) => void; message: (message: Message) => void; event: (event: Event) => void; error: (error: Error) => void; reconnecting: (attempt: number) => void; reconnected: () => void; } /** * Configuration for a local agent connection to the MAP server. */ interface MapAgentConnectionConfig { agentId?: AgentId; name?: string; description?: string; role?: string; parent?: AgentId; scopes?: ScopeId[]; visibility?: 'public' | 'parent-only' | 'scope' | 'system'; capabilities?: ParticipantCapabilities; metadata?: Record; disconnectPolicy?: DisconnectPolicy; } /** * Events emitted by an agent connection. */ interface MapAgentConnectionEvents { registered: (agent: Agent) => void; unregistered: (agent: Agent) => void; 'state:changed': (state: AgentState, previousState: AgentState) => void; message: (message: Message) => void; 'scope:joined': (scope: Scope) => void; 'scope:left': (scope: Scope) => void; error: (error: Error) => void; } /** * Configuration for the client bridge that exposes MAP to external observers. */ interface MapClientBridgeConfig { port?: number; host?: string; tls?: { cert: string; key: string; ca?: string; }; auth?: { required?: boolean; apiKeys?: string[]; jwt?: { secret: string; issuer?: string; audience?: string; }; }; rateLimit?: { maxRequestsPerMinute?: number; maxSubscriptionsPerClient?: number; }; } /** * Simplified configuration for `MeshPeer.federateWith()`. * * Provides a consumer-friendly subset of gateway options. Internally * mapped to `MapGatewayConfig` by MeshPeer. */ interface FederateConfig { /** Override the local system ID (defaults to MeshPeer.peerId) */ localSystemId?: string; /** The remote system ID (typically matches remoteSystemId param) */ remoteSystemId?: string; /** Message buffering for offline peers */ buffer?: { enabled: boolean; maxMessages?: number; }; /** Routing safety */ routing?: { maxHops?: number; trackPath?: boolean; }; } /** * Configuration for a federation gateway. */ interface MapGatewayConfig { localSystemId: string; remoteEndpoint: string; remoteSystemId: string; auth?: { method: 'bearer' | 'api-key' | 'mtls'; credentials?: string; }; routing?: FederationRoutingConfig; buffer?: FederationBufferConfig; reconnection?: { enabled?: boolean; maxRetries?: number; initialDelayMs?: number; maxDelayMs?: number; }; } /** * Filter for listing agents. */ interface AgentFilter { states?: AgentState[]; roles?: string[]; scopes?: ScopeId[]; parent?: AgentId; hasChildren?: boolean; ownerId?: ParticipantId; } /** * Filter for listing scopes. */ interface ScopeFilter { parent?: ScopeId; visibility?: ScopeVisibility; } /** * Subscription handle returned by the event bus. */ interface EventSubscription { id: string; filter?: SubscriptionFilter; options?: SubscriptionOptions; events(): AsyncIterable; unsubscribe(): void; } /** * Result of sending a message. */ interface SendResult { messageId: string; delivered: ParticipantId[]; failed?: Array<{ participantId: ParticipantId; reason: string; }>; } /** * Resolved address - the actual targets for a message. */ interface ResolvedAddress { localAgents: AgentId[]; remotePeers: Array<{ peerId: string; agentIds: AgentId[]; }>; federatedSystems?: Array<{ systemId: string; agentIds: AgentId[]; }>; } /** * Configuration for a mesh peer with MAP support. */ interface MeshPeerConfig { peerId: string; peerName?: string; /** * When true, the peer runs in-process without binding a server port. * Transport is optional in embedded mode — the MAP server, agent registration, * and local message routing all work without a transport. * Transport can still be provided for P2P connectivity. */ embedded?: boolean; transport?: { type: 'nebula' | 'tailscale' | 'headscale'; config: TransportConfig; }; map?: Omit; clientBridge?: MapClientBridgeConfig; peers?: PeerEndpoint[]; auth?: { certPath?: string; keyPath?: string; groups?: string[]; }; /** Git transport configuration */ git?: { /** Enable git transport (default: false) */ enabled?: boolean; /** HTTP port for git-remote-mesh helper (default: 3456) */ httpPort?: number; /** HTTP host (default: 127.0.0.1) */ httpHost?: string; /** Repository path (default: cwd) */ repoPath?: string; /** Git transport options */ options?: GitTransportConfig; }; } /** * Events emitted by a mesh peer. */ interface MeshPeerEvents { started: () => void; stopped: () => void; 'peer:connected': (peerId: string, endpoint: PeerEndpoint) => void; 'peer:disconnected': (peerId: string, reason?: string) => void; 'agent:registered': (agent: Agent) => void; 'agent:unregistered': (agent: Agent) => void; 'scope:created': (scope: Scope) => void; 'scope:deleted': (scope: Scope) => void; 'federation:connected': (systemId: string) => void; 'federation:disconnected': (systemId: string) => void; error: (error: Error) => void; } /** * Stream Types for MAP Protocol * * Defines the stream interface for MAP communication over various transports. */ /** * A bidirectional stream for MAP JSON-RPC communication. */ interface MapStream { /** Write a frame to the stream */ write(frame: MapFrame): Promise; /** Async iterator for reading frames */ [Symbol.asyncIterator](): AsyncIterator; /** Close the stream */ close(): Promise; /** Whether the stream is currently open */ readonly isOpen: boolean; /** Current connection state */ readonly state: MapConnectionState; /** Stream identifier (for debugging) */ readonly id: string; /** Event handlers */ on(event: 'close', handler: () => void): void; on(event: 'error', handler: (error: Error) => void): void; off(event: 'close', handler: () => void): void; off(event: 'error', handler: (error: Error) => void): void; } /** * Factory for creating MAP streams. */ interface MapStreamFactory { /** Create a stream for an established connection */ createStream(connectionId: string): MapStream; } /** * Options for stream framing. */ interface FramingOptions { /** Maximum frame size in bytes (default: 1MB) */ maxFrameSize?: number; /** Encoding for JSON (default: utf-8) */ encoding?: BufferEncoding; /** Line delimiter (default: \n) */ delimiter?: string; } /** * NDJSON framing utilities. */ interface NdjsonFramer { /** Encode a frame to bytes */ encode(frame: MapFrame): Buffer; /** Decode bytes to frames (handles partial data) */ decode(data: Buffer): { frames: MapFrame[]; remainder: Buffer; }; /** Reset internal state */ reset(): void; } /** * Tunnel Stream Adapter * * Wraps an agentic-mesh TransportAdapter connection as a MAP-compatible stream. * Uses NDJSON (newline-delimited JSON) framing for MAP protocol messages. */ /** * Creates an NDJSON framer for encoding/decoding MAP frames. */ declare function createNdjsonFramer(options?: FramingOptions): NdjsonFramer; /** * Configuration for a tunnel stream. */ interface TunnelStreamConfig { /** The underlying transport adapter */ transport: TransportAdapter; /** Remote peer ID */ peerId: string; /** Stream identifier */ streamId?: string; /** Framing options */ framing?: FramingOptions; } /** * A MAP stream that communicates over an agentic-mesh transport connection. */ declare class TunnelStream extends EventEmitter implements MapStream { readonly id: string; private readonly transport; private readonly peerId; private readonly framer; private _state; private _isOpen; private frameQueue; private waitingReaders; private dataHandler; private disconnectHandler; constructor(config: TunnelStreamConfig); get isOpen(): boolean; get state(): MapConnectionState; private setupHandlers; private enqueueFrame; private handleDisconnect; write(frame: MapFrame): Promise; close(): Promise; [Symbol.asyncIterator](): AsyncIterator; /** * Open the stream (establish connection if needed). */ open(): Promise; } /** * Create a tunnel stream for a peer connection. */ declare function createTunnelStream(config: TunnelStreamConfig): TunnelStream; /** * Base Connection for MAP Protocol * * Provides JSON-RPC 2.0 request/response handling over a MAP stream. */ /** * Pending request awaiting a response. */ interface PendingRequest { resolve: (result: unknown) => void; reject: (error: Error) => void; timeout: ReturnType; method: string; } /** * Handler for incoming requests. */ type RequestHandler = (method: string, params: unknown, requestId: RequestId) => Promise; /** * Handler for incoming notifications. */ type NotificationHandler = (method: string, params: unknown) => void; /** * Configuration for the base connection. */ interface BaseConnectionConfig { /** The underlying MAP stream */ stream: MapStream; /** Default request timeout in milliseconds */ requestTimeout?: number; /** Handler for incoming requests */ onRequest?: RequestHandler; /** Handler for incoming notifications */ onNotification?: NotificationHandler; } /** * Base class for MAP protocol connections. * Handles JSON-RPC 2.0 request/response correlation and timeout management. */ declare class BaseConnection extends EventEmitter { protected readonly stream: MapStream; protected readonly requestTimeout: number; protected readonly pendingRequests: Map; protected requestHandler: RequestHandler | null; protected notificationHandler: NotificationHandler | null; private nextRequestId; private readLoopPromise; private isRunning; constructor(config: BaseConnectionConfig); /** * Current connection state. */ get state(): MapConnectionState; /** * Whether the connection is open and ready. */ get isConnected(): boolean; /** * Start the connection (begin reading from the stream). */ start(): Promise; /** * Stop the connection. */ stop(): Promise; /** * Send a request and wait for a response. */ request(method: string, params?: unknown): Promise; /** * Send a notification (no response expected). */ notify(method: string, params?: unknown): Promise; /** * Send a response to a request. */ respond(requestId: RequestId, result: unknown): Promise; /** * Send an error response to a request. */ respondWithError(requestId: RequestId, error: MAPError): Promise; /** * Set the request handler. */ setRequestHandler(handler: RequestHandler): void; /** * Set the notification handler. */ setNotificationHandler(handler: NotificationHandler): void; /** * Main read loop - processes incoming frames. */ private readLoop; /** * Handle an incoming frame. */ private handleFrame; /** * Handle a response frame. */ private handleResponse; /** * Handle a request frame. */ private handleRequest; /** * Handle a notification frame. */ private handleNotification; /** * Handle stream close. */ private handleClose; } /** * Create a JSON-RPC error object. */ declare function createError(code: number, message: string, data?: Record): MAPError; /** * Agent Registry * * Manages the lifecycle and state of agents within the MAP server. */ /** * Parameters for registering an agent. */ interface AgentRegisterParams { agentId?: AgentId; ownerId: ParticipantId; name?: string; description?: string; role?: string; parent?: AgentId; scopes?: ScopeId[]; visibility?: AgentVisibility; capabilities?: ParticipantCapabilities; metadata?: Record; permissionOverrides?: Partial; } /** * Parameters for updating an agent. */ interface AgentUpdateParams { state?: AgentState; metadata?: Record; permissionOverrides?: Partial; } /** * Events emitted by the agent registry. */ interface AgentRegistryEvents { 'agent:registered': (agent: Agent) => void; 'agent:unregistered': (agent: Agent) => void; 'agent:state:changed': (agent: Agent, previousState: AgentState) => void; 'agent:orphaned': (agent: Agent) => void; } /** * Agent Registry - manages agent lifecycle. */ declare class AgentRegistry extends EventEmitter { private readonly agents; private readonly agentsByOwner; private readonly agentsByScope; private readonly agentsByRole; /** * Generate a unique agent ID. */ private generateAgentId; /** * Register a new agent. */ register(params: AgentRegisterParams): Agent; /** * Unregister an agent. */ unregister(agentId: AgentId, reason?: string): Agent; /** * Get an agent by ID. */ get(agentId: AgentId): Agent | undefined; /** * Check if an agent exists. */ has(agentId: AgentId): boolean; /** * Update an agent. */ update(agentId: AgentId, params: AgentUpdateParams): Agent; /** * List agents with optional filtering. */ list(filter?: AgentFilter): Agent[]; /** * Get agents by owner. */ getByOwner(ownerId: ParticipantId): Agent[]; /** * Get agents by scope. */ getByScope(scopeId: ScopeId): Agent[]; /** * Get agents by role. */ getByRole(role: string): Agent[]; /** * Get children of an agent. */ getChildren(agentId: AgentId): Agent[]; /** * Get the parent of an agent. */ getParent(agentId: AgentId): Agent | undefined; /** * Get ancestors of an agent (parent, grandparent, etc.). */ getAncestors(agentId: AgentId, maxDepth?: number): Agent[]; /** * Get descendants of an agent (children, grandchildren, etc.). */ getDescendants(agentId: AgentId, maxDepth?: number): Agent[]; /** * Get siblings of an agent (same parent). */ getSiblings(agentId: AgentId): Agent[]; /** * Add agent to a scope. */ addToScope(agentId: AgentId, scopeId: ScopeId): void; /** * Remove agent from a scope. */ removeFromScope(agentId: AgentId, scopeId: ScopeId): void; /** * Orphan agents owned by a participant (set ownerId to null). */ orphanByOwner(ownerId: ParticipantId): Agent[]; /** * Reclaim orphaned agents. */ reclaimAgents(ownerId: ParticipantId, agentIds: AgentId[]): Agent[]; /** * Get total agent count. */ get size(): number; /** * Clear all agents. */ clear(): void; } /** * Scope Manager * * Manages scopes for grouping agents in the MAP server. */ /** * Parameters for creating a scope. */ interface ScopeCreateParams { scopeId?: ScopeId; name?: string; description?: string; parent?: ScopeId; joinPolicy?: JoinPolicy; autoJoinRoles?: string[]; visibility?: ScopeVisibility; messageVisibility?: MessageVisibility; sendPolicy?: SendPolicy; persistent?: boolean; autoDelete?: boolean; metadata?: Record; } /** * Events emitted by the scope manager. */ interface ScopeManagerEvents { 'scope:created': (scope: Scope) => void; 'scope:deleted': (scope: Scope) => void; 'scope:member:joined': (scopeId: ScopeId, agentId: AgentId) => void; 'scope:member:left': (scopeId: ScopeId, agentId: AgentId) => void; } /** * Scope Manager - manages scope lifecycle and membership. */ declare class ScopeManager extends EventEmitter { private readonly scopes; private readonly scopeMembers; private readonly agentScopes; /** * Generate a unique scope ID. */ private generateScopeId; /** * Create a new scope. */ create(params: ScopeCreateParams): Scope; /** * Delete a scope. */ delete(scopeId: ScopeId): Scope; /** * Get a scope by ID. */ get(scopeId: ScopeId): Scope | undefined; /** * Check if a scope exists. */ has(scopeId: ScopeId): boolean; /** * List scopes with optional filtering. */ list(filter?: ScopeFilter): Scope[]; /** * Add an agent to a scope. */ join(scopeId: ScopeId, agentId: AgentId): void; /** * Remove an agent from a scope. */ leave(scopeId: ScopeId, agentId: AgentId): void; /** * Get members of a scope. */ getMembers(scopeId: ScopeId): AgentId[]; /** * Get scopes an agent belongs to. */ getAgentScopes(agentId: AgentId): ScopeId[]; /** * Check if an agent is a member of a scope. */ isMember(scopeId: ScopeId, agentId: AgentId): boolean; /** * Get member count for a scope. */ getMemberCount(scopeId: ScopeId): number; /** * Remove agent from all scopes. */ removeAgentFromAllScopes(agentId: AgentId): void; /** * Get child scopes of a parent scope. */ getChildren(parentId: ScopeId): Scope[]; /** * Get or create a scope (useful for ad-hoc scopes). */ getOrCreate(scopeId: ScopeId, params?: Omit): Scope; /** * Get total scope count. */ get size(): number; /** * Clear all scopes. */ clear(): void; } /** * Event Bus * * Manages event distribution and subscriptions in the MAP server. */ /** * Parameters for creating a subscription. */ interface SubscriptionParams { participantId: ParticipantId; filter?: SubscriptionFilter; options?: SubscriptionOptions; } /** * Event Bus - distributes events to subscribers. */ declare class EventBus extends EventEmitter { private readonly subscriptions; private readonly participantSubscriptions; private readonly eventHistory; private readonly maxHistorySize; private readonly retentionMs; constructor(options?: { maxHistorySize?: number; retentionMs?: number; }); /** * Generate a unique subscription ID. */ private generateSubscriptionId; /** * Create a subscription. */ subscribe(params: SubscriptionParams): EventSubscription; /** * Unsubscribe. */ unsubscribe(subscriptionId: SubscriptionId): void; /** * Unsubscribe all subscriptions for a participant. */ unsubscribeAll(participantId: ParticipantId): void; /** * Publish an event. */ publish(event: Event): void; /** * Emit an event (convenience method that creates and publishes). */ emitEvent(type: EventType, data?: Record, source?: ParticipantId, causedBy?: string[]): Event; /** * Check if an event matches a subscription filter. */ private matchesFilter; /** * Deliver an event to a subscription. */ private deliverToSubscription; /** * Create an async iterator for a subscription. */ private createEventIterator; /** * Prune old events from history. */ private pruneHistory; /** * Replay events from history. */ replay(params: { afterEventId?: string; fromTimestamp?: Timestamp; toTimestamp?: Timestamp; filter?: SubscriptionFilter; limit?: number; }): { events: Event[]; hasMore: boolean; }; /** * Get subscription count. */ get subscriptionCount(): number; /** * Get event history size. */ get historySize(): number; /** * Clear all subscriptions and history. */ clear(): void; } /** * Message Router * * Routes messages to their destinations based on MAP addressing. */ /** * Handler for delivering messages to their final destinations. * * Called by MessageRouter after address resolution. Implementations can * intercept delivery to add custom logic (e.g. inbox storage, threading, * read tracking) before or instead of the default delivery path. * * Use `MapServer.setDeliveryHandler()` to install a custom handler. * The previous handler is returned for delegation/fallback. */ interface DeliveryHandler { /** * Deliver a message to a locally registered agent. * Called by MessageRouter after address resolution. */ deliverToAgent(agentId: AgentId, message: Message): Promise; /** * Forward a message to a connected peer (another MeshPeer). * Called when the target agent is on a known peer. */ forwardToPeer(peerId: string, agentIds: AgentId[], message: Message): Promise; /** * Route a message to a federated system. * Called when the target is on a remote MAP system. * Optional — if not implemented, federation routing is unavailable. */ routeToFederation?(systemId: string, agentIds: AgentId[], message: Message): Promise; } /** * Configuration for the message router. */ interface MessageRouterConfig { /** Local system ID */ systemId: string; /** Agent registry */ agentRegistry: AgentRegistry; /** Scope manager */ scopeManager: ScopeManager; /** Event bus */ eventBus: EventBus; /** Delivery handler */ deliveryHandler: DeliveryHandler; /** Map of agent IDs to peer IDs (for remote agents) */ agentPeerMap?: Map; } /** * Message Router - resolves addresses and routes messages. */ declare class MessageRouter extends EventEmitter { private readonly systemId; private readonly agentRegistry; private readonly scopeManager; private readonly eventBus; private deliveryHandler; private readonly agentPeerMap; constructor(config: MessageRouterConfig); /** * Replace the delivery handler. * Returns the previous handler so it can be used as a fallback. */ setDeliveryHandler(handler: DeliveryHandler): DeliveryHandler; /** * Generate a unique message ID. */ private generateMessageId; /** * Send a message. */ send(from: ParticipantId, to: Address, payload: unknown, meta?: MessageMeta): Promise; /** * Resolve an address to actual targets. */ resolveAddress(address: Address, senderId?: ParticipantId): ResolvedAddress; /** * Add an agent to the appropriate resolution bucket. */ private addToResolution; /** * Register a remote agent's location. */ registerRemoteAgent(agentId: AgentId, peerId: string): void; /** * Unregister a remote agent. */ unregisterRemoteAgent(agentId: AgentId): void; /** * Unregister all agents on a peer. */ unregisterPeerAgents(peerId: string): void; /** * Get the peer ID for a remote agent. */ getAgentPeer(agentId: AgentId): string | undefined; } /** * Events emitted by the MAP server. */ interface MapServerEvents { 'started': () => void; 'stopped': () => void; 'agent:registered': (agent: Agent) => void; 'agent:unregistered': (agent: Agent) => void; 'agent:state:changed': (agent: Agent, previousState: AgentState) => void; 'scope:created': (scope: Scope) => void; 'scope:deleted': (scope: Scope) => void; 'message:sent': (messageId: string, from: ParticipantId, to: Address) => void; 'event': (event: Event) => void; 'error': (error: Error) => void; } /** * Message handler for incoming messages to agents. */ type MessageHandler = (agentId: AgentId, message: Message) => Promise | void; /** * MAP Server - the core protocol server. */ declare class MapServer extends EventEmitter { readonly systemId: string; readonly systemName?: string; readonly systemVersion?: string; private readonly agentRegistry; private readonly scopeManager; private readonly eventBus; private readonly messageRouter; private readonly messageHandlers; private readonly config; private running; constructor(config: MapServerConfig); /** * Forward internal events to external listeners. */ private setupEventForwarding; /** * Start the server. */ start(): Promise; /** * Stop the server. */ stop(): Promise; /** * Whether the server is running. */ get isRunning(): boolean; /** * Register an agent. */ registerAgent(params: AgentRegisterParams): Agent; /** * Unregister an agent. */ unregisterAgent(agentId: AgentId, reason?: string): Agent; /** * Get an agent by ID. */ getAgent(agentId: AgentId): Agent | undefined; /** * List agents with optional filtering. */ listAgents(filter?: AgentFilter): Agent[]; /** * Update an agent. */ updateAgent(agentId: AgentId, params: AgentUpdateParams): Agent; /** * Get agent hierarchy. */ getAgentHierarchy(agentId: AgentId, options?: { includeParent?: boolean; includeChildren?: boolean; includeSiblings?: boolean; includeAncestors?: boolean; includeDescendants?: boolean; maxDepth?: number; }): { agent: Agent; parent?: Agent; children?: Agent[]; siblings?: Agent[]; ancestors?: Agent[]; descendants?: Agent[]; }; /** * Orphan all agents owned by a participant. */ orphanAgentsByOwner(ownerId: ParticipantId): Agent[]; /** * Reclaim orphaned agents. */ reclaimAgents(ownerId: ParticipantId, agentIds: AgentId[]): Agent[]; /** * Create a scope. */ createScope(params: ScopeCreateParams): Scope; /** * Delete a scope. */ deleteScope(scopeId: ScopeId): Scope; /** * Get a scope. */ getScope(scopeId: ScopeId): Scope | undefined; /** * List scopes. */ listScopes(filter?: ScopeFilter): Scope[]; /** * Join a scope. */ joinScope(scopeId: ScopeId, agentId: AgentId): Scope; /** * Leave a scope. */ leaveScope(scopeId: ScopeId, agentId: AgentId): Scope; /** * Get scope members. */ getScopeMembers(scopeId: ScopeId): AgentId[]; /** * Send a message. */ send(from: ParticipantId, to: Address, payload: unknown, meta?: MessageMeta): Promise; /** * Register a message handler for an agent. */ setMessageHandler(agentId: AgentId, handler: MessageHandler): void; /** * Remove a message handler for an agent. */ removeMessageHandler(agentId: AgentId): void; /** * Replace the default delivery handler with a custom implementation. * * The custom handler receives all messages after address resolution * and is responsible for final delivery. This allows external systems * (e.g. agent-inbox) to intercept message delivery for custom storage, * threading, read tracking, and other message processing. * * Returns the previous handler so it can be used as a fallback * for operations the custom handler doesn't want to override. * * @param handler - Custom delivery handler * @returns The previous delivery handler * * @example * ```typescript * const previous = server.setDeliveryHandler({ * async deliverToAgent(agentId, message) { * // Custom delivery logic (e.g. store in inbox) * storage.putMessage(message); * return true; * }, * async forwardToPeer(peerId, agentIds, message) { * // Delegate to default handler * return previous.forwardToPeer(peerId, agentIds, message); * }, * async routeToFederation(systemId, agentIds, message) { * return previous.routeToFederation?.(systemId, agentIds, message) ?? false; * }, * }); * ``` */ setDeliveryHandler(handler: DeliveryHandler): DeliveryHandler; /** * Deliver a message to a local agent. */ private deliverToAgent; /** * Forward a message to a remote peer. * This should be overridden by subclasses that support peer connections. */ protected forwardToPeer(peerId: string, agentIds: AgentId[], message: Message): Promise; /** * Route a message to a federated system. * This should be overridden by subclasses that support federation. */ protected routeToFederation(systemId: string, agentIds: AgentId[], message: Message): Promise; /** * Subscribe to events. */ subscribe(participantId: ParticipantId, filter?: SubscriptionFilter, options?: SubscriptionOptions): EventSubscription; /** * Unsubscribe. */ unsubscribe(subscriptionId: string): void; /** * Unsubscribe all subscriptions for a participant. */ unsubscribeAll(participantId: ParticipantId): void; /** * Publish a custom event. */ publishEvent(event: Event): void; /** * Replay events from history. */ replay(params: { afterEventId?: string; fromTimestamp?: number; toTimestamp?: number; filter?: SubscriptionFilter; limit?: number; }): { events: Event[]; hasMore: boolean; }; /** * Register a remote agent's location. */ registerRemoteAgent(agentId: AgentId, peerId: string): void; /** * Unregister a remote agent. */ unregisterRemoteAgent(agentId: AgentId): void; /** * Unregister all agents on a peer. */ unregisterPeerAgents(peerId: string): void; /** * Get system information. */ getSystemInfo(): { systemId: string; systemName?: string; systemVersion?: string; protocolVersion: number; agentCount: number; scopeCount: number; subscriptionCount: number; }; } /** * Agent Connection * * Represents a local agent's connection to the MAP server. */ /** * Events emitted by an agent connection. */ interface AgentConnectionEvents { 'registered': (agent: Agent) => void; 'unregistered': (agent: Agent) => void; 'state:changed': (state: AgentState, previousState: AgentState) => void; 'message': (message: Message) => void; 'scope:joined': (scope: Scope) => void; 'scope:left': (scope: Scope) => void; 'error': (error: Error) => void; } /** * Agent Connection - manages a local agent's lifecycle and communication. */ declare class AgentConnection extends EventEmitter { private readonly server; private readonly config; private _agent; private _registered; private subscription; constructor(server: MapServer, config: MapAgentConnectionConfig); /** * The agent instance (null if not registered). */ get agent(): Agent | null; /** * Agent ID (throws if not registered). */ get agentId(): AgentId; /** * Whether the agent is registered. */ get isRegistered(): boolean; /** * Current agent state. */ get state(): AgentState | undefined; /** * Register the agent with the MAP server. */ register(): Promise; /** * Unregister the agent. */ unregister(reason?: string): Promise; /** * Update agent state. */ updateState(state: AgentState): Promise; /** * Update agent metadata. */ updateMetadata(metadata: Record): Promise; /** * Send a message. */ send(to: Address, payload: unknown, meta?: MessageMeta): Promise; /** * Send a message to parent. */ sendToParent(payload: unknown, meta?: MessageMeta): Promise; /** * Send a message to children. */ sendToChildren(payload: unknown, meta?: MessageMeta): Promise; /** * Broadcast to a scope. */ broadcastToScope(scopeId: ScopeId, payload: unknown, meta?: MessageMeta): Promise; /** * Join a scope. */ joinScope(scopeId: ScopeId): Promise; /** * Leave a scope. */ leaveScope(scopeId: ScopeId): Promise; /** * Get scopes this agent belongs to. */ getScopes(): ScopeId[]; /** * Subscribe to events. */ subscribe(filter?: SubscriptionFilter, options?: SubscriptionOptions): EventSubscription; /** * Get agent hierarchy. */ getHierarchy(options?: { includeParent?: boolean; includeChildren?: boolean; includeSiblings?: boolean; includeAncestors?: boolean; includeDescendants?: boolean; maxDepth?: number; }): ReturnType; /** * Forward events from the subscription to this emitter. */ private forwardEvents; } /** * Create an agent connection. */ declare function createAgentConnection(server: MapServer, config: MapAgentConnectionConfig): AgentConnection; /** * Peer Connection * * Manages a MAP protocol connection to a remote peer over an agentic-mesh transport. */ /** * Events emitted by a peer connection. */ interface PeerConnectionEvents { 'connected': (result: ConnectResponseResult) => void; 'disconnected': (reason?: string) => void; 'message': (message: Message) => void; 'event': (event: Event) => void; 'agent:discovered': (agent: Agent) => void; 'agent:removed': (agentId: AgentId) => void; 'error': (error: Error) => void; 'reconnecting': (attempt: number) => void; 'reconnected': () => void; 'git:message': (message: AnyGitMessage) => void; } /** * Peer Connection - manages communication with a remote mesh peer. */ declare class PeerConnection extends EventEmitter { readonly localPeerId: string; readonly remotePeerId: string; readonly remoteEndpoint: PeerEndpoint; private readonly transport; private readonly config; private connection; private stream; private _state; private remoteAgents; private reconnectAttempts; private reconnectTimer; private sessionId; constructor(config: MapPeerConnectionConfig); /** * Current connection state. */ get state(): MapConnectionState; /** * Whether connected to the remote peer. */ get isConnected(): boolean; /** * Get all discovered remote agents. */ get agents(): Agent[]; /** * Connect to the remote peer. */ connect(): Promise; /** * Disconnect from the remote peer. */ disconnect(reason?: string): Promise; /** * Send a message to a remote agent. */ sendMessage(to: AgentId, payload: unknown, meta?: MessageMeta): Promise; /** * Forward a message to remote agents. */ forwardMessage(agentIds: AgentId[], message: Message): Promise; /** * Send a git protocol message to the remote peer. */ sendGitMessage(message: AnyGitMessage): Promise; /** * Discover agents on the remote peer. */ discoverAgents(): Promise; /** * Get a remote agent by ID. */ getAgent(agentId: AgentId): Agent | undefined; /** * Check if a remote agent exists. */ hasAgent(agentId: AgentId): boolean; /** * Handle incoming notifications from the remote peer. */ private handleNotification; /** * Handle an event from the remote peer. */ private handleEvent; /** * Clean up resources. */ private cleanup; /** * Schedule a reconnection attempt. */ private scheduleReconnect; /** * Attempt reconnection. */ private attemptReconnect; /** * Cancel scheduled reconnection. */ private cancelReconnect; } /** * Create a peer connection. */ declare function createPeerConnection(config: MapPeerConnectionConfig): PeerConnection; /** * Base Agent * * Abstract base class for built-in MAP agents. */ /** * Configuration for a base agent. */ interface BaseAgentConfig { /** Agent name */ name: string; /** Agent role */ role?: string; /** Agent description */ description?: string; /** Initial scopes to join */ scopes?: ScopeId[]; /** Custom metadata */ metadata?: Record; } /** * Base Agent - foundation for built-in agents. */ declare abstract class BaseAgent extends EventEmitter { protected connection: AgentConnection; protected readonly config: BaseAgentConfig; protected running: boolean; constructor(connection: AgentConnection, config: BaseAgentConfig); /** * Agent ID. */ get agentId(): AgentId; /** * Current agent state. */ get state(): AgentState | undefined; /** * Whether the agent is running. */ get isRunning(): boolean; /** * Start the agent. */ start(): Promise; /** * Stop the agent. */ stop(): Promise; /** * Send a message. */ protected send(to: Address, payload: unknown, meta?: MessageMeta): Promise; /** * Send to parent agent. */ protected sendToParent(payload: unknown, meta?: MessageMeta): Promise; /** * Send to child agents. */ protected sendToChildren(payload: unknown, meta?: MessageMeta): Promise; /** * Broadcast to a scope. */ protected broadcastToScope(scopeId: ScopeId, payload: unknown, meta?: MessageMeta): Promise; /** * Join a scope. */ protected joinScope(scopeId: ScopeId): Promise; /** * Leave a scope. */ protected leaveScope(scopeId: ScopeId): Promise; /** * Update metadata. */ protected updateMetadata(metadata: Record): Promise; /** * Called when the agent starts. Override in subclasses. */ protected onStart(): Promise; /** * Called when the agent stops. Override in subclasses. */ protected onStop(): Promise; /** * Handle an incoming message. Override in subclasses. */ protected abstract handleMessage(message: Message): Promise; } /** * Sync Agent * * A built-in agent for CRDT synchronization using Yjs. * Handles state synchronization across mesh peers using MAP messaging. */ /** * Sync message types. */ type SyncMessageType = 'sync:request' | 'sync:state-vector' | 'sync:diff' | 'sync:ack' | 'sync:full'; /** * Sync message payload. */ interface SyncMessage { type: SyncMessageType; namespace: string; data?: Uint8Array | number[]; stateVector?: Uint8Array | number[]; version?: number; } /** * Configuration for the sync agent. */ interface SyncAgentConfig extends BaseAgentConfig { /** Namespace for sync (becomes a scope) */ namespace: string; /** Sync interval in milliseconds */ syncInterval?: number; /** Get current state vector */ getStateVector: () => Uint8Array; /** Get diff from a state vector */ getDiff: (stateVector: Uint8Array) => Uint8Array; /** Apply an update */ applyUpdate: (update: Uint8Array) => void; /** Get full state (for initial sync) */ getFullState: () => Uint8Array; /** Apply full state */ applyFullState: (state: Uint8Array) => void; } /** * Sync Agent - handles CRDT synchronization. */ declare class SyncAgent extends BaseAgent { private readonly syncConfig; private readonly scopeId; private syncTimer; private peerVersions; private localVersion; constructor(connection: AgentConnection, config: SyncAgentConfig); /** * Namespace being synced. */ get namespace(): string; /** * Current local version. */ get version(): number; /** * Called when the agent starts. */ protected onStart(): Promise; /** * Called when the agent stops. */ protected onStop(): Promise; /** * Handle an incoming message. */ protected handleMessage(message: Message): Promise; /** * Request sync from peers. */ requestSync(): Promise; /** * Broadcast current state vector to peers. */ broadcastStateVector(): Promise; /** * Send an update to peers. */ broadcastUpdate(update: Uint8Array): Promise; /** * Handle a sync request. */ private handleSyncRequest; /** * Handle a state vector from a peer. */ private handleStateVector; /** * Handle a diff/update from a peer. */ private handleDiff; /** * Handle full state from a peer. */ private handleFullState; /** * Handle acknowledgment from a peer. */ private handleAck; /** * Get the version known for a peer. */ getPeerVersion(peerId: AgentId): number | undefined; /** * Get all known peer versions. */ getAllPeerVersions(): Map; } /** * Create a sync agent. */ declare function createSyncAgent(connection: AgentConnection, config: SyncAgentConfig): SyncAgent; /** * Client Bridge * * Exposes MAP protocol to external clients via WebSocket. * Allows dashboards and monitoring tools to observe the mesh. */ /** * Events emitted by the client bridge. */ interface ClientBridgeEvents { 'client:connected': (clientId: ParticipantId) => void; 'client:disconnected': (clientId: ParticipantId, reason?: string) => void; 'client:authenticated': (clientId: ParticipantId) => void; 'error': (error: Error) => void; } /** * Client Bridge - WebSocket server for external MAP clients. */ declare class ClientBridge extends EventEmitter { private readonly mapServer; private readonly config; private httpServer; private wss; private readonly clients; private running; constructor(mapServer: MapServer, config?: MapClientBridgeConfig); /** * Whether the bridge is running. */ get isRunning(): boolean; /** * Number of connected clients. */ get clientCount(): number; /** * Get the actual port the server is listening on. */ get port(): number; /** * Start the WebSocket server. */ start(): Promise; /** * Stop the WebSocket server. */ stop(): Promise; /** * Handle a new WebSocket connection. */ private handleConnection; /** * Handle a message from a client. */ private handleMessage; /** * Handle a request from a client. */ private handleRequest; /** * Route a request to the appropriate handler. */ private routeRequest; /** * Handle connect request. */ private handleConnect; /** * Handle disconnect request. */ private handleDisconnectRequest; /** * Handle subscribe request. */ private handleSubscribe; /** * Handle unsubscribe request. */ private handleUnsubscribe; /** * Stream events from a subscription to the client. */ private streamEvents; /** * Handle notification from client. */ private handleNotification; /** * Handle client disconnect. */ private handleDisconnect; /** * Clean up client resources. */ private cleanupClient; /** * Authenticate a client. */ private authenticate; /** * Send a frame to a client. */ private send; /** * Send a response to a client. */ private sendResponse; /** * Send an error response to a client. */ private sendError; /** * Generate a unique client ID. */ private generateClientId; /** * Generate a unique session ID. */ private generateSessionId; /** * Broadcast an event to all connected clients. */ broadcastEvent(event: Event): void; } /** * Create a client bridge. */ declare function createClientBridge(mapServer: MapServer, config?: MapClientBridgeConfig): ClientBridge; /** * Federation Gateway * * Enables cross-mesh communication by routing messages between * separate MAP systems while maintaining visibility boundaries. */ /** * Events emitted by the federation gateway. */ interface FederationGatewayEvents { 'connected': (systemId: string) => void; 'disconnected': (systemId: string, reason?: string) => void; 'reconnecting': (systemId: string, attempt: number) => void; 'reconnected': (systemId: string) => void; 'message:received': (envelope: FederationEnvelope) => void; 'message:routed': (envelope: FederationEnvelope) => void; 'error': (error: Error) => void; } /** * Federation Gateway - routes messages between MAP systems. */ declare class FederationGateway extends EventEmitter { readonly localSystemId: string; readonly remoteSystemId: string; private readonly mapServer; private readonly config; private connection; private stream; private buffer; private connected; private reconnectAttempts; private reconnectTimer; constructor(mapServer: MapServer, config: MapGatewayConfig); /** * Whether connected to the remote system. */ get isConnected(): boolean; /** * Number of buffered messages. */ get bufferedMessageCount(): number; /** * Connect to the remote system. */ connect(stream: MapStream): Promise; /** * Disconnect from the remote system. */ disconnect(reason?: string): Promise; /** * Route a message to the remote system. */ route(message: Message, targetAgentIds: AgentId[]): Promise; /** * Create a federation envelope for a message. */ private createEnvelope; /** * Send an envelope to the remote system. */ private sendEnvelope; /** * Buffer a message for later delivery. */ private bufferMessage; /** * Flush buffered messages to the remote system. */ private flushBuffer; /** * Handle incoming request from remote system. */ private handleRequest; /** * Handle incoming notification from remote system. */ private handleNotification; /** * Validate an incoming federation envelope. */ private validateEnvelope; /** * Process an incoming federation envelope. */ private processIncomingEnvelope; /** * Wrap a legacy message in a federation envelope. */ private wrapLegacyMessage; /** * Clean up resources. */ private cleanup; /** * Schedule a reconnection attempt. */ private scheduleReconnect; /** * Attempt reconnection. */ private attemptReconnect; /** * Cancel scheduled reconnection. */ private cancelReconnect; /** * Emit a reconnection event. */ private emitReconnectionEvent; } /** * Create a federation gateway. */ declare function createFederationGateway(mapServer: MapServer, config: MapGatewayConfig): FederationGateway; /** * Git Sync Client * * High-level API for git sync operations over agentic-mesh. * Provides convenient methods for MAP clients/agents to sync repos with peers. * * Usage: * ```typescript * const client = peer.git.createSyncClient('/path/to/local/repo') * * // Sync with a remote peer (fetch + merge) * await client.sync('peer-id', { branch: 'main' }) * * // Pull changes from peer * await client.pull('peer-id', 'main') * * // Push changes to peer * await client.push('peer-id', 'main') * * // Clone from peer * await client.clone('peer-id', '/path/to/new/repo') * ``` */ /** Options for sync operations */ interface SyncOptions { /** Branch to sync (default: current branch) */ branch?: string; /** Remote name to use (default: mesh-) */ remoteName?: string; /** Whether to push after pulling (bidirectional sync) */ bidirectional?: boolean; /** Force overwrite local changes */ force?: boolean; /** Rebase instead of merge */ rebase?: boolean; } /** Options for clone operations */ interface CloneOptions { /** Branch to clone (default: default branch) */ branch?: string; /** Shallow clone depth */ depth?: number; /** Clone bare repository */ bare?: boolean; } /** Options for push operations */ interface PushOptions { /** Force push */ force?: boolean; /** Set upstream */ setUpstream?: boolean; /** Push all branches */ all?: boolean; /** Push tags */ tags?: boolean; } /** Options for pull operations */ interface PullOptions { /** Rebase instead of merge */ rebase?: boolean; /** Fast-forward only */ ffOnly?: boolean; } /** Result of a sync operation */ interface SyncResult { /** Whether the sync was successful */ success: boolean; /** Operation that was performed */ operation: 'fetch' | 'pull' | 'push' | 'clone' | 'sync'; /** Peer ID involved */ peerId: string; /** Branch involved */ branch?: string; /** Commits fetched/pushed */ commits?: string[]; /** Error message if failed */ error?: string; /** Output from git commands */ output?: string; } /** Events emitted by the sync client */ interface GitSyncClientEvents { 'sync:start': (peerId: string, operation: string) => void; 'sync:progress': (peerId: string, message: string) => void; 'sync:complete': (result: SyncResult) => void; 'sync:error': (error: Error) => void; } declare class GitSyncClient extends EventEmitter { private readonly repoPath; private readonly service; private readonly httpPort; constructor(repoPath: string, service: GitTransportService, httpPort?: number); /** * Sync with a remote peer (fetch + optionally push) */ sync(peerId: string, options?: SyncOptions): Promise; /** * Fetch from a remote peer */ fetch(peerId: string, branch?: string, options?: SyncOptions): Promise; /** * Pull from a remote peer */ pull(peerId: string, branch?: string, options?: PullOptions): Promise; /** * Push to a remote peer */ push(peerId: string, branch?: string, options?: PushOptions): Promise; /** * Clone from a remote peer */ clone(peerId: string, targetPath: string, options?: CloneOptions): Promise; /** * List refs from a remote peer without fetching */ listRemoteRefs(peerId: string): Promise<{ ref: string; sha: string; }[]>; /** * Get the current branch name */ getCurrentBranch(): Promise; /** * Check if there are uncommitted changes */ hasUncommittedChanges(): Promise; private getRemoteName; private getMeshUrl; private ensureRemote; private runGit; private getGitEnv; } /** Create a git sync client */ declare function createGitSyncClient(repoPath: string, service: GitTransportService, httpPort?: number): GitSyncClient; /** * Git Transport Service * * Provides git transport over agentic-mesh. This service: * - Exposes HTTP endpoints for the local git-remote-mesh helper * - Routes git operations to remote peers via MAP messages * - Handles incoming git requests from remote peers * - Supports binary streaming for large pack transfers */ /** Configuration for the git transport service */ interface GitTransportServiceConfig { /** HTTP server port for git-remote-mesh helper */ httpPort: number; /** HTTP server host (default: localhost for security) */ httpHost: string; /** Git protocol handler configuration */ git: Partial; /** Request timeout in milliseconds */ requestTimeoutMs: number; /** Streaming configuration */ streaming: { /** Enable streaming for large packs (default: true) */ enabled: boolean; /** Threshold in bytes above which to use streaming (default: 1MB) */ threshold: number; /** Chunk size for streaming (default: 64KB) */ chunkSize: number; }; } /** Default service configuration */ declare const DEFAULT_GIT_SERVICE_CONFIG: GitTransportServiceConfig; /** Events emitted by the git transport service */ interface GitTransportServiceEvents { started: () => void; stopped: () => void; 'request:list-refs': (peerId: string, request: ListRefsRequest) => void; 'request:upload-pack': (peerId: string, request: UploadPackRequest) => void; 'request:receive-pack': (peerId: string, request: ReceivePackRequest) => void; 'stream:started': (peerId: string, correlationId: string, totalSize: number) => void; 'stream:progress': (peerId: string, correlationId: string, bytesTransferred: number) => void; 'stream:completed': (peerId: string, correlationId: string, totalBytes: number) => void; error: (error: Error) => void; } /** Interface for sending messages to peers */ interface PeerMessageSender { sendToPeer(peerId: string, message: AnyGitMessage): Promise; isConnected(peerId: string): boolean; } declare class GitTransportService extends EventEmitter { private readonly config; private readonly handler; private readonly packStreamer; private httpServer; private peerSender; private readonly pendingRequests; private readonly pendingStreams; private running; constructor(config?: Partial); /** Set up event handlers for pack streaming */ private setupPackStreamerEvents; /** Get the protocol handler */ get protocolHandler(): GitProtocolHandler; /** Whether the service is running */ get isRunning(): boolean; /** Get the HTTP port the service is running on */ get httpPort(): number; /** * Create a sync client for a specific repository. * Use this for high-level git sync operations. * * @example * ```typescript * const client = gitService.createSyncClient('/path/to/repo') * await client.sync('peer-id', { branch: 'main' }) * ``` */ createSyncClient(repoPath: string): GitSyncClient; /** Set the peer message sender (called by MeshPeer) */ setPeerSender(sender: PeerMessageSender): void; /** Start the git transport service */ start(): Promise; /** Stop the git transport service */ stop(): Promise; private startHttpServer; private handleHttpRequest; private readRequestBody; private sendHttpError; private handleListRefs; private handleUploadPack; private handleReceivePack; private getStatus; /** Forward a git request to a remote peer */ private forwardToRemote; /** Handle an incoming git message from a remote peer */ handleRemoteMessage(fromPeerId: string, message: AnyGitMessage): Promise; /** Handle streaming-specific messages */ private handleStreamMessage; /** Start receiving a streamed pack */ private startReceivingStream; /** Check if pack data should be streamed */ private shouldStreamPack; private generateCorrelationId; } /** Create a git transport service */ declare function createGitTransportService(config?: Partial): GitTransportService; /** * Mesh Peer * * The main entry point for agentic-mesh with MAP protocol support. * Integrates the transport layer with the MAP server for a unified experience. */ /** * Factory for creating transport adapters. */ type TransportFactory = (config: NonNullable) => TransportAdapter; /** * Configuration for creating an embedded MeshPeer. * Transport is optional — the peer works fully in-process without one. */ interface EmbeddedMeshPeerConfig { peerId: string; peerName?: string; transport?: MeshPeerConfig['transport']; map?: MeshPeerConfig['map']; } /** * Mesh Peer - the unified mesh node with MAP protocol support. */ declare class MeshPeer extends EventEmitter { readonly peerId: string; readonly peerName: string; private readonly config; private readonly mapServer; private transport; private transportFactory; private readonly peerConnections; private readonly agentConnections; private readonly federationGateways; private gitService; private running; constructor(config: MeshPeerConfig, transportFactory?: TransportFactory); /** * Create an embedded MeshPeer that runs in-process without a transport. * The MAP server, agent registration, and local messaging all work * without binding a server port or requiring a network transport. * * Transport can be added later via `start(transport)` for P2P connectivity. */ static createEmbedded(config: EmbeddedMeshPeerConfig): MeshPeer; /** * Get the MAP server instance. */ get server(): MapServer; /** * Whether the peer is running. */ get isRunning(): boolean; /** * Get all connected peer IDs. */ get connectedPeers(): string[]; /** * Get the git transport service (if enabled). */ get git(): GitTransportService | null; /** * Forward server events to this emitter. */ private setupServerEvents; /** * Start the mesh peer. * * In embedded mode, transport is optional. The MAP server, agent registration, * and local message routing all work without a transport. If a transport is * provided (either as parameter or via factory), it will be started for P2P connectivity. */ start(transport?: TransportAdapter): Promise; /** * Stop the mesh peer. */ stop(): Promise; /** * Create a peer message sender for git transport. */ private createGitPeerSender; /** * Set up transport event handlers. */ private setupTransportHandlers; /** * Handle transport peer connection. */ private handlePeerConnected; /** * Handle transport peer disconnection. */ private handlePeerDisconnected; /** * Handle incoming data from a peer. * Note: This is handled by the TunnelStream in PeerConnection */ private handlePeerData; /** * Connect to a remote peer. */ connectToPeer(endpoint: PeerEndpoint): Promise; /** * Disconnect from a peer. */ disconnectFromPeer(peerId: string, reason?: string): Promise; /** * Get a peer connection. */ getPeerConnection(peerId: string): PeerConnection | undefined; /** * Handle a message from a remote peer. */ private handleRemoteMessage; /** * Create and register a local agent. */ createAgent(config: MapAgentConnectionConfig): Promise; /** * Get an agent connection. */ getAgentConnection(agentId: AgentId): AgentConnection | undefined; /** * Get all local agents. */ getLocalAgents(): Agent[]; /** * Get all known agents (local and remote). */ getAllAgents(): Agent[]; /** * Send a message (convenience method). */ send(from: AgentId, to: Address, payload: unknown, meta?: MessageMeta): Promise; /** * Create a scope. */ createScope(params: Parameters[0]): Scope; /** * Get a scope. */ getScope(scopeId: ScopeId): Scope | undefined; /** * List scopes. */ listScopes(): Scope[]; /** * Establish a federation link with a remote MAP system. * Creates a FederationGateway if one doesn't exist for this system. * * The gateway handles: * - Envelope wrapping (federation headers, system identification) * - Hop counting (configurable maxHops, default 5) * - Loop detection (path tracking to prevent circular routing) * - Message buffering (configurable queue for offline peers) * - JSON-RPC handshake on connect() * * After calling `federateWith()`, the caller must provide a transport * by calling `gateway.connect(stream)` with a MapStream — unless a peer * connection already exists, in which case auto-connect is attempted. * * Accepts either the simplified `FederateConfig` or the full `MapGatewayConfig`. * * @param remoteSystemId - The system ID of the remote MAP system * @param config - Optional gateway configuration * @returns The FederationGateway instance * * @example * ```typescript * // Create gateway with simplified config * const gw = await peer.federateWith("remote-system", { * buffer: { enabled: true, maxMessages: 1000 }, * routing: { maxHops: 5, trackPath: true }, * }); * * // Connect via linked streams (test) or let auto-connect handle it (production) * await gw.connect(stream); * ``` */ federateWith(remoteSystemId: string, config?: FederateConfig | Partial): Promise; /** * Get an existing federation gateway by remote system ID. * Returns undefined if no gateway exists for the given system. */ getFederationGateway(remoteSystemId: string): FederationGateway | undefined; /** * List all active federation gateways. */ getFederationGateways(): FederationGateway[]; /** * Disconnect a federation link and clean up the gateway. * @param remoteSystemId - The system to defederate from * @param reason - Optional reason for defederation */ defederate(remoteSystemId: string, reason?: string): Promise; /** * Normalize FederateConfig or partial MapGatewayConfig to a full MapGatewayConfig. */ private toGatewayConfig; /** * Subscribe to events. */ subscribe(participantId: string, filter?: SubscriptionFilter, options?: SubscriptionOptions): EventSubscription; /** * Get system information. */ getSystemInfo(): ReturnType & { connectedPeers: number; }; } /** * Create a mesh peer. */ declare function createMeshPeer(config: MeshPeerConfig, transportFactory?: TransportFactory): MeshPeer; /** * Git Protocol Handler * * Handles git protocol operations (upload-pack, receive-pack) by delegating * to native git commands. This runs on the remote peer side. */ /** Error class for git protocol errors */ declare class GitProtocolError extends Error { readonly code: string; readonly details?: Record | undefined; constructor(code: string, message: string, details?: Record | undefined); } /** Default access control that allows all operations */ declare class DefaultGitAccessControl implements GitAccessControl { checkRead(_peerId: string): Promise; checkWrite(_peerId: string): Promise; checkRefUpdate(_peerId: string, _ref: string, _force: boolean): Promise; checkRefDelete(_peerId: string, _ref: string): Promise; } interface GitProtocolHandlerOptions { config?: Partial; accessControl?: GitAccessControl; } declare class GitProtocolHandlerImpl extends EventEmitter implements GitProtocolHandler { private config; private accessControl; constructor(options?: GitProtocolHandlerOptions); getConfig(): GitTransportConfig; updateConfig(config: Partial): void; /** * List refs in the repository */ listRefs(request: ListRefsRequest): Promise; /** * Handle fetch operation (git-upload-pack) */ uploadPack(request: UploadPackRequest): Promise; /** * Handle push operation (git-receive-pack) */ receivePack(request: ReceivePackRequest): Promise; private isProtectedBranch; private buildUploadPackInput; private buildReceivePackInput; private pktLine; } /** Create a new git protocol handler */ declare function createGitProtocolHandler(options?: GitProtocolHandlerOptions): GitProtocolHandler; /** * Pack Streamer * * Handles chunked streaming of git pack data over agentic-mesh. * Supports both sending (chunking) and receiving (reassembly) of large packs. */ declare class PackStreamer extends EventEmitter { private readonly incomingStreams; private readonly outgoingStreams; private sendMessage; private readonly defaultTimeout; constructor(options?: { timeoutMs?: number; }); /** * Set the message sender function. */ setSendMessage(fn: (peerId: string, message: AnyGitMessage) => Promise): void; /** * Stream pack data to a remote peer in chunks. */ streamPack(peerId: string, correlationId: string, data: Buffer, options?: PackStreamOptions): Promise; /** * Start receiving a pack stream. * Returns a promise that resolves with the complete pack data. */ receivePack(peerId: string, correlationId: string, totalSize?: number, timeoutMs?: number): Promise; /** * Handle an incoming pack stream message. */ handleMessage(peerId: string, message: AnyGitMessage): boolean; private handleStreamInit; private handleChunk; private handleComplete; /** * Cancel an incoming stream. */ cancelIncoming(correlationId: string): void; /** * Cancel an outgoing stream. */ cancelOutgoing(correlationId: string): void; /** * Get statistics about active streams. */ getStats(): { incoming: number; outgoing: number; }; } /** * A simpler pack receiver that properly collects data. */ declare class PackReceiver { private readonly chunks; private readonly checksum; private expectedSequence; private pendingChunks; private totalSize?; private receivedBytes; private completed; private error; constructor(totalSize?: number); /** * Add a chunk of data. */ addChunk(sequence: number, data: Buffer): void; private processChunk; /** * Mark the stream as complete and verify. */ complete(expectedChecksum: string, expectedBytes: number): Buffer; /** * Get current progress. */ getProgress(): { receivedBytes: number; totalSize?: number; pendingChunks: number; }; } /** Create a new pack streamer */ declare function createPackStreamer(options?: { timeoutMs?: number; }): PackStreamer; /** Create a new pack receiver */ declare function createPackReceiver(totalSize?: number): PackReceiver; export { AGENT_ERROR_CODES, AUTH_ERROR_CODES, type AcpError, AcpMeshAdapter, type AcpMeshAdapterConfig, type AcpMeshEnvelope, type AcpMessage, type AcpNotification, type AcpRequest, type AcpResponse, type Address, type Agent, type AgentAcceptanceRule, AgentConnection, type AgentConnectionEvents, type AgentFilter, type AgentId, type AgentLifecycle, type AgentMessagingRule, type AgentPermissions, type AgentRegisterParams, AgentRegistry, type AgentRegistryEvents, type AgentRelationship, type AgentRelationshipType, type AgentState, type AgentUpdateParams, type AgentVisibility, type AgentVisibilityRule, type AgentsListResponseResult, type AnyGitMessage, type AuthMethod, type AuthParams, type AutoRenewalConfig, BaseAgent, type BaseAgentConfig, BaseConnection, type BaseConnectionConfig, type BaseTransportConfig, type BroadcastAddress, type BroadcastTarget, CHANNEL_PREFIXES, CORE_METHODS, type CertCreatedEvent, type CertEventType, type CertExpiringEvent, CertManager, type CertManagerConfig, type CertRenewedEvent, type CertRevokedEvent, type CertVerification, type CertificateIndex, type CertificateInfo, type ChannelEventType, type ChannelStats, type ClientAcceptanceRule, ClientBridge, type ClientBridgeEvents, type CloneOptions, ConfigGenerator, type ConflictInfo, type ConnectResponseResult, type CorrelationId, type CrSqliteChangeset, type CrSqliteSyncConfig, CrSqliteSyncProvider, type CreateLighthouseOptions, type CreateRootCAOptions, type CreateUserCAOptions, DEFAULT_GIT_REMOTE_HELPER_CONFIG, DEFAULT_GIT_SERVICE_CONFIG, DEFAULT_GIT_TRANSPORT_CONFIG, DbSyncError, type DbSyncErrorCode, type DbSyncMessages, DefaultGitAccessControl, type DeliveryHandler, type DeliverySemantics, type DirectAddress, type DisconnectPolicy, type DnsConfig, ERROR_CODES, EVENT_TYPES, type EmbeddedMeshPeerConfig, type EntityChangeEvent, type EntityChangeSource, EntityMapper, type EntityType, type ErrorCategory, type Event, EventBus, type EventInput, type EventSubscription, type EventType, type ExecutionRequest, type ExecutionRequestEvent, type ExecutionResponse, ExecutionRouter, type ExecutionRouterConfig, FEDERATION_ERROR_CODES, FEDERATION_METHODS, type FederateConfig, type FederatedAddress, type FederationAuth, type FederationBufferConfig, type FederationEnvelope, FederationGateway, type FederationGatewayEvents, type FederationMetadata, type FederationRoutingConfig, type FeedbackAnchorCRDT, type FeedbackCRDT, type FeedbackJSONL, type FeedbackType, type FileHashState, type FirewallConfig, type FirewallRule, type FramingOptions, type GatewayReconnectionEvent, type GitAccessCheckResult, type GitAccessControl, type GitAccessLevel, type GitCapability, type GitErrorMessage, type GitListRefsMessage, type GitListRefsResponseMessage, type GitMessage, type GitMessageType, type GitPackChunkMessage, type GitPackCompleteMessage, type GitPackStreamMessage, GitProtocolError, type GitProtocolHandler, GitProtocolHandlerImpl, type GitProtocolHandlerOptions, type GitReceivePackMessage, type GitReceivePackResponseMessage, GitReconciler, type GitReconcilerConfig, type GitRef, type GitRemoteHelperConfig, GitSyncClient, type GitSyncClientEvents, type GitTransportConfig, GitTransportService, type GitTransportServiceConfig, type GitTransportServiceEvents, type GitUploadPackMessage, type GitUploadPackResponseMessage, type GroupHierarchy, GroupPermissions, type GroupPermissionsConfig, type HeadscaleTransportConfig, type HealthChangeEvent, HealthMonitor, type HealthMonitorAdapter, type HealthMonitorConfig, type HealthMonitorEvents, type HierarchicalAddress, type HubConfig, HubRole, type HubState, type IMessageChannel, type IssueCRDT, type IssueJSONL, type IssueStatus, JSONLBridge, JSONRPC_VERSION, type JoinPolicy, LIFECYCLE_METHODS, type LighthouseConfigOptions, type LighthouseEventType, type LighthouseHealth, type LighthouseIndex, type LighthouseInfo, LighthouseManager, type LighthouseManagerConfig, type LighthouseStatus, type ListRefsRequest, type ListRefsResponse, type LoggingConfig, type MAPError, type MAPErrorData, MAP_METHODS, type MapAgentConnectionConfig, type MapAgentConnectionEvents, type MapClientBridgeConfig, type MapConnectionState, type MapFrame, type MapGatewayConfig, type MapNotificationFrame, type MapPeerConnectionConfig, type MapPeerConnectionEvents, type MapPermissionConfig, type MapRequestFrame, type MapResponseFrame, MapServer, type MapServerConfig, type MapServerEvents, type MapStream, type MapStreamFactory, type MeshContext, type MeshEventType, type MeshGitUrl, MeshPeer, type MeshPeerConfig, type MeshPeerEvents, type MeshStreamConfig, type Message, MessageChannel, type MessageChannelConfig, type MessageContext, type MessageHandler, type MessageId, type MessageMeta, type MessagePriority, type MessageRelationship, MessageRouter, type MessageRouterConfig, type MessageVisibility, type Meta, type MultiAddress, type MultiProjectConfig, MultiProjectManager, NOTIFICATION_METHODS, type NdjsonFramer, type NebulaConfigOptions, NebulaMesh, type NebulaMeshConfig, type NebulaTransportConfig, NoopHealthMonitor, type NotificationHandler, OBSERVATION_METHODS, OfflineQueue, type OfflineQueueConfig, type OptionalFeaturesConfig, PROTOCOL_ERROR_CODES, PROTOCOL_VERSION, PackReceiver, type PackStream, type PackStreamOptions, PackStreamer, type ParsedFederatedId, type Participant, type ParticipantAddress, type ParticipantCapabilities, type ParticipantId, type ParticipantType, type PeerConfig, type PeerConnection$1 as PeerConnection, type PeerConnectionEvents, type PeerEndpoint, type PeerHealth, type PeerInfo, type PeerMessageSender, type PeerStatus, type PermissionCheckResult, PermissionDeniedError, PermissionLevel, type ProjectAddedEvent, type ProjectInfo, type ProjectRemovedEvent, type ProjectSyncedEvent, type ProtocolVersion, type PullOptions, type PushOptions, type QueuedMessage, type QueuedOperation, RESOURCE_ERROR_CODES, ROUTING_ERROR_CODES, type ReceivePackRequest, type ReceivePackResponse, type ReconcileEvent, type RefUpdateCommand, type RefUpdateResult, type RelationshipCRDT, type RelationshipJSONL, type RelationshipType, type RequestHandler, type RequestId, type ResolvedAddress, type RespondFn, type RevocationEntry, type RevocationList, type RevocationListExport, type RoleAddress, STATE_METHODS, type Scope, type ScopeAddress, type ScopeCreateParams, type ScopeFilter, type ScopeId, ScopeManager, type ScopeManagerEvents, type ScopeMessagingRule, type ScopeVisibility, type ScopeVisibilityRule, type SendPolicy, type SendResult, type SessionEndedNotification, type SessionId, type SessionInfo, type SessionListRequest, type SessionListResponse, type SessionObserveRequest, type SessionObserveResponse, type SessionUnobserveRequest, type SessionUpdateCallback, type SetupValidation, type SignServerCertOptions, type SpecCRDT, type SpecJSONL, type StreamingCapabilities, type StructureVisibilityRule, type Subscription, type SubscriptionFilter, type SubscriptionId, type SubscriptionOptions, type SubscriptionParams, type SudocodeEntityType, type SudocodeMeshConfig, SudocodeMeshService, type SudocodeState, SyncAgent, type SyncAgentConfig, type SyncError, type SyncEventType, type SyncMessage, type SyncMessageType, type SyncOptions, SyncProvider, type SyncProviderConfig, type SyncResult, type SystemAcceptanceRule, type SystemAddress, type TailscaleTransportConfig, type TcpTransportConfig, type Timestamp, type TransportAdapter, type TransportConfig, type TransportEvents, type TransportFactory$1 as TransportFactory, type TransportType, TunnelStream, type TunnelStreamConfig, type UploadPackRequest, type UploadPackResponse, type WireMessage, type YjsMessage, type YjsMessageType, type YjsSyncConfig, YjsSyncProvider, configGenerator, createAgentConnection, createClientBridge, createConnectedStreams, createError, createEvent, createFederationGateway, createGitProtocolHandler, createGitSyncClient, createGitTransportService, createMeshPeer, createNdjsonFramer, createPackReceiver, createPackStreamer, createPeerConnection, createSyncAgent, createTunnelStream, detectExtensionPath, getExtensionPath, getInstallInstructions, groupPermissions, isAcpNotification, isAcpRequest, isAcpResponse, isBroadcastAddress, isDirectAddress, isFederatedAddress, isHierarchicalAddress, isMultiAddress, isParticipantAddress, isRoleAddress, isScopeAddress, isSessionEndedNotification, isSessionListRequest, isSessionObserveRequest, isSessionUnobserveRequest, isSystemAddress, makeRelationshipKey, meshStream, parseFederatedId, parseRelationshipKey };