@willjackson/claude-code-bridge 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -644,6 +644,9 @@ function createNotificationMessage(source, notification) {
644
644
  // src/bridge/core.ts
645
645
  import { WebSocketServer } from "ws";
646
646
  import { v4 as uuidv42 } from "uuid";
647
+ import * as fs from "fs";
648
+ import * as path from "path";
649
+ import * as os from "os";
647
650
  var logger2 = createLogger("bridge");
648
651
  var Bridge = class {
649
652
  config;
@@ -708,6 +711,7 @@ var Bridge = class {
708
711
  await this.connectToRemote();
709
712
  }
710
713
  this.started = true;
714
+ this.writeStatusFile();
711
715
  logger2.info({ mode, instanceName: this.config.instanceName }, "Bridge started successfully");
712
716
  } catch (error) {
713
717
  await this.cleanup();
@@ -1355,6 +1359,7 @@ var Bridge = class {
1355
1359
  // Private Methods - Event Notification
1356
1360
  // ============================================================================
1357
1361
  notifyPeerConnected(peer) {
1362
+ this.writeStatusFile();
1358
1363
  for (const handler of this.peerConnectedHandlers) {
1359
1364
  try {
1360
1365
  handler(peer);
@@ -1385,6 +1390,7 @@ var Bridge = class {
1385
1390
  logger2.error({ error: error.message }, "Peer disconnected handler error");
1386
1391
  }
1387
1392
  }
1393
+ this.writeStatusFile();
1388
1394
  }
1389
1395
  notifyMessageReceived(message, peerId) {
1390
1396
  for (const handler of this.messageReceivedHandlers) {
@@ -1471,9 +1477,67 @@ var Bridge = class {
1471
1477
  this.server = null;
1472
1478
  logger2.debug("WebSocket server closed");
1473
1479
  }
1480
+ this.removeStatusFile();
1474
1481
  logger2.debug("Cleanup complete");
1475
1482
  }
1476
1483
  // ============================================================================
1484
+ // Status File Management
1485
+ // ============================================================================
1486
+ /**
1487
+ * Get the status file path
1488
+ */
1489
+ getStatusFilePath() {
1490
+ const bridgeDir = path.join(os.homedir(), ".claude-bridge");
1491
+ return path.join(bridgeDir, "status.json");
1492
+ }
1493
+ /**
1494
+ * Ensure the .claude-bridge directory exists
1495
+ */
1496
+ ensureBridgeDir() {
1497
+ const bridgeDir = path.join(os.homedir(), ".claude-bridge");
1498
+ if (!fs.existsSync(bridgeDir)) {
1499
+ fs.mkdirSync(bridgeDir, { recursive: true });
1500
+ }
1501
+ }
1502
+ /**
1503
+ * Write current status to status file
1504
+ */
1505
+ writeStatusFile() {
1506
+ try {
1507
+ this.ensureBridgeDir();
1508
+ const statusFile = this.getStatusFilePath();
1509
+ const status = {
1510
+ port: this.config.listen?.port,
1511
+ instanceName: this.config.instanceName,
1512
+ mode: this.config.mode,
1513
+ peers: this.getPeers().map((p) => ({
1514
+ id: p.id,
1515
+ name: p.name,
1516
+ connectedAt: new Date(p.connectedAt).toISOString(),
1517
+ lastActivity: new Date(p.lastActivity).toISOString()
1518
+ }))
1519
+ };
1520
+ fs.writeFileSync(statusFile, JSON.stringify(status, null, 2), "utf-8");
1521
+ logger2.debug({ statusFile }, "Status file updated");
1522
+ } catch (error) {
1523
+ logger2.error({ error: error.message }, "Failed to write status file");
1524
+ }
1525
+ }
1526
+ /**
1527
+ * Remove the status file
1528
+ */
1529
+ removeStatusFile() {
1530
+ try {
1531
+ const statusFile = this.getStatusFilePath();
1532
+ if (fs.existsSync(statusFile)) {
1533
+ fs.unlinkSync(statusFile);
1534
+ logger2.debug({ statusFile }, "Status file removed");
1535
+ }
1536
+ } catch (error) {
1537
+ logger2.error({ error: error.message }, "Failed to remove status file");
1538
+ }
1539
+ }
1540
+ // ============================================================================
1477
1541
  // Getters for State Inspection
1478
1542
  // ============================================================================
1479
1543
  /**
@@ -1716,9 +1780,9 @@ function discoverAllPeers() {
1716
1780
  }
1717
1781
 
1718
1782
  // src/environment/detect.ts
1719
- import { existsSync } from "fs";
1783
+ import { existsSync as existsSync2 } from "fs";
1720
1784
  function isInDocker() {
1721
- return existsSync("/.dockerenv");
1785
+ return existsSync2("/.dockerenv");
1722
1786
  }
1723
1787
  function isDocksalEnvironment() {
1724
1788
  return !!process.env.DOCKSAL_STACK;
@@ -1847,9 +1911,9 @@ function getDefaultConfig(env) {
1847
1911
  }
1848
1912
 
1849
1913
  // src/utils/config.ts
1850
- import * as fs from "fs";
1851
- import * as path from "path";
1852
- import * as os from "os";
1914
+ import * as fs2 from "fs";
1915
+ import * as path2 from "path";
1916
+ import * as os2 from "os";
1853
1917
  import { parse as parseYaml } from "yaml";
1854
1918
  var DEFAULT_CONFIG = {
1855
1919
  listen: {
@@ -1893,10 +1957,10 @@ function mergeConfig(partial) {
1893
1957
  }
1894
1958
  function readConfigFile(filePath) {
1895
1959
  try {
1896
- if (!fs.existsSync(filePath)) {
1960
+ if (!fs2.existsSync(filePath)) {
1897
1961
  return null;
1898
1962
  }
1899
- const content = fs.readFileSync(filePath, "utf-8");
1963
+ const content = fs2.readFileSync(filePath, "utf-8");
1900
1964
  const parsed = parseYaml(content);
1901
1965
  return parsed;
1902
1966
  } catch {
@@ -1904,15 +1968,15 @@ function readConfigFile(filePath) {
1904
1968
  }
1905
1969
  }
1906
1970
  function getDefaultConfigPaths() {
1907
- const homeDir = os.homedir();
1971
+ const homeDir = os2.homedir();
1908
1972
  const cwd = process.cwd();
1909
1973
  return [
1910
1974
  // Project-local config takes priority
1911
- path.join(cwd, ".claude-bridge.yml"),
1912
- path.join(cwd, ".claude-bridge.yaml"),
1975
+ path2.join(cwd, ".claude-bridge.yml"),
1976
+ path2.join(cwd, ".claude-bridge.yaml"),
1913
1977
  // User home config as fallback
1914
- path.join(homeDir, ".claude-bridge", "config.yml"),
1915
- path.join(homeDir, ".claude-bridge", "config.yaml")
1978
+ path2.join(homeDir, ".claude-bridge", "config.yml"),
1979
+ path2.join(homeDir, ".claude-bridge", "config.yaml")
1916
1980
  ];
1917
1981
  }
1918
1982
  async function loadConfig(configPath) {
@@ -1990,4 +2054,4 @@ export {
1990
2054
  loadConfig,
1991
2055
  loadConfigSync
1992
2056
  };
1993
- //# sourceMappingURL=chunk-BRH476VK.js.map
2057
+ //# sourceMappingURL=chunk-IMMNNIX7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/logger.ts","../src/bridge/protocol.ts","../src/transport/interface.ts","../src/transport/websocket.ts","../src/bridge/messages.ts","../src/bridge/core.ts","../src/transport/discovery.ts","../src/environment/detect.ts","../src/utils/config.ts"],"sourcesContent":["import pino from 'pino';\n\n/**\n * Log levels supported by the logger\n */\nexport type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\n/**\n * Logger interface (subset of pino.Logger for public API)\n */\nexport type Logger = pino.Logger;\n\n/**\n * Determines if we're in a development environment\n */\nfunction isDevelopment(): boolean {\n return process.env.NODE_ENV !== 'production';\n}\n\n/**\n * Gets the default log level from environment or falls back to 'info'\n */\nfunction getDefaultLevel(): LogLevel {\n const envLevel = process.env.LOG_LEVEL?.toLowerCase() as LogLevel | undefined;\n const validLevels: LogLevel[] = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];\n if (envLevel && validLevels.includes(envLevel)) {\n return envLevel;\n }\n return 'info';\n}\n\n/**\n * Creates a logger instance with the given component name\n *\n * @param name - Component name to include in log output\n * @param level - Optional log level override (defaults to LOG_LEVEL env var or 'info')\n * @returns A pino logger instance configured for the component\n *\n * @example\n * ```typescript\n * const logger = createLogger('bridge');\n * logger.info('Bridge started');\n * logger.error({ err }, 'Connection failed');\n * ```\n */\nexport function createLogger(name: string, level?: LogLevel): Logger {\n const logLevel = level ?? getDefaultLevel();\n\n const options: pino.LoggerOptions = {\n name,\n level: logLevel,\n };\n\n // Use pretty printing in development for better readability\n if (isDevelopment()) {\n options.transport = {\n target: 'pino-pretty',\n options: {\n colorize: true,\n translateTime: 'SYS:standard',\n ignore: 'pid,hostname',\n },\n };\n }\n\n return pino(options);\n}\n\n/**\n * Creates a child logger from an existing logger with additional context\n *\n * @param parent - Parent logger instance\n * @param bindings - Additional context to include in all log messages\n * @returns A child logger instance\n */\nexport function createChildLogger(parent: Logger, bindings: Record<string, unknown>): Logger {\n return parent.child(bindings);\n}\n","/**\n * Protocol definitions for Claude Code Bridge\n * Defines message types, schemas, and serialization utilities\n */\n\nimport { z } from 'zod';\nimport { v4 as uuidv4 } from 'uuid';\n\n// ============================================================================\n// Message Type Enum\n// ============================================================================\n\nexport const MessageType = z.enum([\n 'request',\n 'response',\n 'context_sync',\n 'task_delegate',\n 'notification',\n]);\n\nexport type MessageType = z.infer<typeof MessageType>;\n\n// ============================================================================\n// File and Directory Schemas\n// ============================================================================\n\nexport const FileChunkSchema = z.object({\n path: z.string(),\n content: z.string(),\n startLine: z.number().optional(),\n endLine: z.number().optional(),\n language: z.string().optional(),\n});\n\nexport type FileChunk = z.infer<typeof FileChunkSchema>;\n\nexport const DirectoryTreeSchema: z.ZodType<DirectoryTree> = z.lazy(() =>\n z.object({\n name: z.string(),\n type: z.enum(['file', 'directory']),\n children: z.array(DirectoryTreeSchema).optional(),\n })\n);\n\nexport interface DirectoryTree {\n name: string;\n type: 'file' | 'directory';\n children?: DirectoryTree[];\n}\n\n// ============================================================================\n// Artifact Schema\n// ============================================================================\n\nexport const ArtifactSchema = z.object({\n path: z.string(),\n action: z.enum(['created', 'modified', 'deleted']),\n diff: z.string().optional(),\n});\n\nexport type Artifact = z.infer<typeof ArtifactSchema>;\n\n// ============================================================================\n// Context Schema\n// ============================================================================\n\nexport const ContextSchema = z.object({\n files: z.array(FileChunkSchema).optional(),\n tree: DirectoryTreeSchema.optional(),\n summary: z.string().optional(),\n variables: z.record(z.any()).optional(),\n});\n\nexport type Context = z.infer<typeof ContextSchema>;\n\n// ============================================================================\n// Task Request Schema\n// ============================================================================\n\nexport const TaskRequestSchema = z.object({\n id: z.string(),\n description: z.string(),\n scope: z.enum(['execute', 'analyze', 'suggest']),\n constraints: z.array(z.string()).optional(),\n returnFormat: z.enum(['full', 'summary', 'diff']).optional(),\n timeout: z.number().optional(),\n});\n\nexport type TaskRequest = z.infer<typeof TaskRequestSchema>;\n\n// ============================================================================\n// Task Result Schema\n// ============================================================================\n\nexport const TaskResultSchema = z.object({\n taskId: z.string().optional(),\n success: z.boolean(),\n data: z.any(),\n artifacts: z.array(ArtifactSchema).optional(),\n followUp: z.string().optional(),\n error: z.string().optional(),\n});\n\nexport type TaskResult = z.infer<typeof TaskResultSchema>;\n\n// ============================================================================\n// Bridge Message Schema\n// ============================================================================\n\nexport const BridgeMessageSchema = z.object({\n id: z.string().uuid(),\n type: MessageType,\n source: z.string(),\n timestamp: z.number(),\n context: ContextSchema.optional(),\n task: TaskRequestSchema.optional(),\n result: TaskResultSchema.optional(),\n});\n\nexport type BridgeMessage = z.infer<typeof BridgeMessageSchema>;\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Creates a base message with auto-generated UUID and timestamp\n * @param type The message type\n * @param source The source instance identifier\n * @returns A partial BridgeMessage with id, type, source, and timestamp\n */\nexport function createMessage(\n type: MessageType,\n source: string\n): BridgeMessage {\n return {\n id: uuidv4(),\n type,\n source,\n timestamp: Date.now(),\n };\n}\n\n/**\n * Validates a message against the BridgeMessage schema\n * @param data The data to validate\n * @returns The validated BridgeMessage or throws if invalid\n */\nexport function validateMessage(data: unknown): BridgeMessage {\n return BridgeMessageSchema.parse(data);\n}\n\n/**\n * Safe validation that returns a result object instead of throwing\n * @param data The data to validate\n * @returns A Zod SafeParseReturnType with success/error information\n */\nexport function safeValidateMessage(data: unknown) {\n return BridgeMessageSchema.safeParse(data);\n}\n\n/**\n * Serializes a BridgeMessage to JSON string\n * @param message The message to serialize\n * @returns JSON string representation\n */\nexport function serializeMessage(message: BridgeMessage): string {\n return JSON.stringify(message);\n}\n\n/**\n * Deserializes a JSON string to a validated BridgeMessage\n * @param json The JSON string to deserialize\n * @returns The validated BridgeMessage\n * @throws Error if JSON is invalid or message doesn't match schema\n */\nexport function deserializeMessage(json: string): BridgeMessage {\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch {\n throw new Error('Invalid JSON');\n }\n return validateMessage(parsed);\n}\n\n/**\n * Safe deserialization that returns a result object instead of throwing\n * @param json The JSON string to deserialize\n * @returns A Zod SafeParseReturnType with success/error information\n */\nexport function safeDeserializeMessage(json: string) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch {\n return {\n success: false as const,\n error: new z.ZodError([\n {\n code: 'custom',\n message: 'Invalid JSON',\n path: [],\n },\n ]),\n };\n }\n return BridgeMessageSchema.safeParse(parsed);\n}\n","/**\n * Transport layer interface and types for Claude Code Bridge\n * Defines the abstract transport interface for communication between bridge instances\n */\n\nimport type { BridgeMessage } from '../bridge/protocol.js';\n\n// ============================================================================\n// Connection State Enum\n// ============================================================================\n\n/**\n * Represents the current state of a transport connection\n */\nexport enum ConnectionState {\n /** Not connected to any peer */\n DISCONNECTED = 'DISCONNECTED',\n /** Currently attempting to establish connection */\n CONNECTING = 'CONNECTING',\n /** Successfully connected and ready for communication */\n CONNECTED = 'CONNECTED',\n /** Connection lost, attempting to reconnect */\n RECONNECTING = 'RECONNECTING',\n}\n\n// ============================================================================\n// Connection Configuration\n// ============================================================================\n\n/**\n * Authentication configuration for transport connections\n */\nexport interface AuthConfig {\n /** Authentication type */\n type: 'token' | 'none';\n /** Authentication token (required if type is 'token') */\n token?: string;\n}\n\n/**\n * Configuration for establishing a transport connection\n */\nexport interface ConnectionConfig {\n /** Full WebSocket URL (e.g., ws://localhost:8765) */\n url?: string;\n /** Host to connect to (used if url is not provided) */\n host?: string;\n /** Port to connect to (used if url is not provided) */\n port?: number;\n /** Enable automatic reconnection on disconnect */\n reconnect?: boolean;\n /** Interval between reconnection attempts in milliseconds */\n reconnectInterval?: number;\n /** Maximum number of reconnection attempts before giving up */\n maxReconnectAttempts?: number;\n /** Authentication configuration */\n auth?: AuthConfig;\n}\n\n// ============================================================================\n// Event Handler Types\n// ============================================================================\n\n/**\n * Handler for incoming messages\n */\nexport type MessageHandler = (message: BridgeMessage) => void;\n\n/**\n * Handler for disconnect events\n */\nexport type DisconnectHandler = () => void;\n\n/**\n * Handler for error events\n */\nexport type ErrorHandler = (error: Error) => void;\n\n// ============================================================================\n// Transport Interface\n// ============================================================================\n\n/**\n * Abstract transport interface for bridge communication\n * Implementations handle the actual network protocol (WebSocket, TCP, etc.)\n */\nexport interface Transport {\n /**\n * Establish connection to a remote peer\n * @param config Connection configuration\n * @returns Promise that resolves when connection is established\n * @throws Error if connection fails\n */\n connect(config: ConnectionConfig): Promise<void>;\n\n /**\n * Cleanly close the current connection\n * @returns Promise that resolves when disconnection is complete\n */\n disconnect(): Promise<void>;\n\n /**\n * Send a message to the connected peer\n * @param message The message to send\n * @returns Promise that resolves when message is sent\n * @throws Error if not connected and message cannot be queued\n */\n send(message: BridgeMessage): Promise<void>;\n\n /**\n * Register a handler for incoming messages\n * @param handler Function to call when a message is received\n */\n onMessage(handler: MessageHandler): void;\n\n /**\n * Register a handler for disconnect events\n * @param handler Function to call when connection is lost\n */\n onDisconnect(handler: DisconnectHandler): void;\n\n /**\n * Register a handler for error events\n * @param handler Function to call when an error occurs\n */\n onError(handler: ErrorHandler): void;\n\n /**\n * Check if the transport is currently connected\n * @returns true if connected, false otherwise\n */\n isConnected(): boolean;\n\n /**\n * Get the current connection state\n * @returns The current ConnectionState\n */\n getState(): ConnectionState;\n}\n\n// ============================================================================\n// Transport Events (for EventEmitter pattern)\n// ============================================================================\n\n/**\n * Transport event types for EventEmitter-based implementations\n */\nexport interface TransportEvents {\n /** Emitted when a message is received */\n message: BridgeMessage;\n /** Emitted when connection is established */\n connect: void;\n /** Emitted when connection is closed */\n disconnect: void;\n /** Emitted when an error occurs */\n error: Error;\n /** Emitted when reconnection is attempted */\n reconnecting: { attempt: number; maxAttempts: number };\n}\n","/**\n * WebSocket Transport implementation for Claude Code Bridge\n * Provides WebSocket-based communication between bridge instances\n */\n\nimport WebSocket from 'ws';\nimport type { BridgeMessage } from '../bridge/protocol.js';\nimport { serializeMessage, safeDeserializeMessage } from '../bridge/protocol.js';\nimport {\n ConnectionState,\n type ConnectionConfig,\n type Transport,\n type MessageHandler,\n type DisconnectHandler,\n type ErrorHandler,\n} from './interface.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('websocket-transport');\n\n/** Default reconnection interval in milliseconds */\nconst DEFAULT_RECONNECT_INTERVAL = 1000;\n\n/** Default maximum reconnection attempts */\nconst DEFAULT_MAX_RECONNECT_ATTEMPTS = 10;\n\n/** Default heartbeat interval in milliseconds */\nconst DEFAULT_HEARTBEAT_INTERVAL = 30000;\n\n/** Heartbeat timeout - how long to wait for pong response */\nconst HEARTBEAT_TIMEOUT = 10000;\n\n/**\n * WebSocket-based transport implementation\n * Handles connection lifecycle, message sending/receiving, and event handling\n * Supports auto-reconnection, message queuing, and heartbeat monitoring\n */\nexport class WebSocketTransport implements Transport {\n private ws: WebSocket | null = null;\n private state: ConnectionState = ConnectionState.DISCONNECTED;\n private config: ConnectionConfig | null = null;\n\n // Reconnection state\n private reconnectAttempts: number = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private intentionalDisconnect: boolean = false;\n\n // Message queue for offline messages\n private messageQueue: BridgeMessage[] = [];\n\n // Heartbeat state\n private heartbeatInterval: ReturnType<typeof setInterval> | null = null;\n private heartbeatTimeout: ReturnType<typeof setTimeout> | null = null;\n private awaitingPong: boolean = false;\n\n // Event handlers\n private messageHandlers: MessageHandler[] = [];\n private disconnectHandlers: DisconnectHandler[] = [];\n private errorHandlers: ErrorHandler[] = [];\n private reconnectingHandlers: Array<(attempt: number, maxAttempts: number) => void> = [];\n\n /**\n * Build the WebSocket URL from the connection configuration\n */\n private buildUrl(config: ConnectionConfig): string {\n if (config.url) {\n return config.url;\n }\n\n const host = config.host ?? 'localhost';\n const port = config.port ?? 8765;\n return `ws://${host}:${port}`;\n }\n\n /**\n * Establish connection to a remote peer\n */\n async connect(config: ConnectionConfig): Promise<void> {\n if (this.state === ConnectionState.CONNECTED) {\n throw new Error('Already connected');\n }\n\n this.config = config;\n this.intentionalDisconnect = false;\n this.reconnectAttempts = 0;\n\n return this.establishConnection();\n }\n\n /**\n * Internal method to establish WebSocket connection\n * Used for both initial connection and reconnection attempts\n */\n private async establishConnection(): Promise<void> {\n if (!this.config) {\n throw new Error('No configuration set');\n }\n\n this.state = ConnectionState.CONNECTING;\n\n const url = this.buildUrl(this.config);\n logger.debug({ url, attempt: this.reconnectAttempts }, 'Connecting to WebSocket server');\n\n return new Promise<void>((resolve, reject) => {\n try {\n this.ws = new WebSocket(url);\n\n // Handle connection open\n this.ws.on('open', () => {\n this.state = ConnectionState.CONNECTED;\n this.reconnectAttempts = 0;\n logger.info({ url }, 'WebSocket connection established');\n\n // Start heartbeat monitoring\n this.startHeartbeat();\n\n // Flush queued messages\n this.flushMessageQueue();\n\n resolve();\n });\n\n // Handle incoming messages\n this.ws.on('message', (data: WebSocket.RawData) => {\n this.handleIncomingMessage(data);\n });\n\n // Handle pong responses for heartbeat\n this.ws.on('pong', () => {\n this.handlePong();\n });\n\n // Handle connection close\n this.ws.on('close', (code, reason) => {\n const wasConnected = this.state === ConnectionState.CONNECTED;\n const wasReconnecting = this.state === ConnectionState.RECONNECTING;\n\n // Stop heartbeat\n this.stopHeartbeat();\n\n logger.info({ code, reason: reason.toString() }, 'WebSocket connection closed');\n\n // Notify disconnect handlers only if we were previously connected\n if (wasConnected) {\n this.notifyDisconnect();\n }\n\n // Attempt reconnection if enabled and not intentional disconnect\n if (!this.intentionalDisconnect && this.shouldReconnect()) {\n this.scheduleReconnect();\n } else if (!wasReconnecting) {\n this.state = ConnectionState.DISCONNECTED;\n }\n });\n\n // Handle errors\n this.ws.on('error', (error: Error) => {\n logger.error({ error: error.message }, 'WebSocket error');\n\n // If we're still connecting (initial connection), reject the promise\n if (this.state === ConnectionState.CONNECTING && this.reconnectAttempts === 0) {\n this.state = ConnectionState.DISCONNECTED;\n reject(error);\n return;\n }\n\n // Notify error handlers\n this.notifyError(error);\n });\n } catch (error) {\n this.state = ConnectionState.DISCONNECTED;\n reject(error);\n }\n });\n }\n\n /**\n * Cleanly close the current connection\n */\n async disconnect(): Promise<void> {\n // Mark as intentional to prevent reconnection\n this.intentionalDisconnect = true;\n\n // Clear any pending reconnection timer\n this.clearReconnectTimer();\n\n // Stop heartbeat\n this.stopHeartbeat();\n\n // Clear message queue on intentional disconnect\n this.messageQueue = [];\n\n if (!this.ws || this.state === ConnectionState.DISCONNECTED) {\n this.state = ConnectionState.DISCONNECTED;\n return;\n }\n\n logger.debug('Disconnecting WebSocket');\n\n return new Promise<void>((resolve) => {\n if (!this.ws) {\n this.state = ConnectionState.DISCONNECTED;\n resolve();\n return;\n }\n\n // Set up close handler before closing\n const onClose = () => {\n this.state = ConnectionState.DISCONNECTED;\n this.ws = null;\n resolve();\n };\n\n // If already closed, resolve immediately\n if (this.ws.readyState === WebSocket.CLOSED) {\n onClose();\n return;\n }\n\n // Set up timeout in case close doesn't happen\n const timeout = setTimeout(() => {\n this.state = ConnectionState.DISCONNECTED;\n this.ws = null;\n resolve();\n }, 5000);\n\n this.ws.once('close', () => {\n clearTimeout(timeout);\n onClose();\n });\n\n // Initiate close\n this.ws.close(1000, 'Disconnect requested');\n });\n }\n\n /**\n * Send a message to the connected peer\n * If disconnected and reconnection is enabled, queues the message for later delivery\n */\n async send(message: BridgeMessage): Promise<void> {\n // If connected, send immediately\n if (this.ws && this.state === ConnectionState.CONNECTED) {\n return this.sendImmediate(message);\n }\n\n // If reconnecting and reconnection is enabled, queue the message\n if (this.shouldReconnect() && (this.state === ConnectionState.RECONNECTING || this.state === ConnectionState.DISCONNECTED)) {\n this.queueMessage(message);\n return;\n }\n\n throw new Error('Not connected');\n }\n\n /**\n * Immediately send a message over the WebSocket\n */\n private async sendImmediate(message: BridgeMessage): Promise<void> {\n if (!this.ws || this.state !== ConnectionState.CONNECTED) {\n throw new Error('Not connected');\n }\n\n const serialized = serializeMessage(message);\n logger.debug({ messageId: message.id, type: message.type }, 'Sending message');\n\n return new Promise<void>((resolve, reject) => {\n this.ws!.send(serialized, (error) => {\n if (error) {\n logger.error({ error: error.message, messageId: message.id }, 'Failed to send message');\n reject(error);\n } else {\n resolve();\n }\n });\n });\n }\n\n /**\n * Queue a message for later delivery when reconnected\n */\n private queueMessage(message: BridgeMessage): void {\n this.messageQueue.push(message);\n logger.debug({ messageId: message.id, queueLength: this.messageQueue.length }, 'Message queued for delivery');\n }\n\n /**\n * Flush all queued messages after reconnection\n */\n private async flushMessageQueue(): Promise<void> {\n if (this.messageQueue.length === 0) {\n return;\n }\n\n logger.info({ queueLength: this.messageQueue.length }, 'Flushing message queue');\n\n const messages = [...this.messageQueue];\n this.messageQueue = [];\n\n for (const message of messages) {\n try {\n await this.sendImmediate(message);\n } catch (error) {\n logger.error({ error: (error as Error).message, messageId: message.id }, 'Failed to send queued message');\n // Re-queue the failed message\n this.messageQueue.unshift(message);\n break;\n }\n }\n }\n\n /**\n * Register a handler for incoming messages\n */\n onMessage(handler: MessageHandler): void {\n this.messageHandlers.push(handler);\n }\n\n /**\n * Register a handler for disconnect events\n */\n onDisconnect(handler: DisconnectHandler): void {\n this.disconnectHandlers.push(handler);\n }\n\n /**\n * Register a handler for error events\n */\n onError(handler: ErrorHandler): void {\n this.errorHandlers.push(handler);\n }\n\n /**\n * Register a handler for reconnecting events\n */\n onReconnecting(handler: (attempt: number, maxAttempts: number) => void): void {\n this.reconnectingHandlers.push(handler);\n }\n\n /**\n * Check if the transport is currently connected\n */\n isConnected(): boolean {\n return this.state === ConnectionState.CONNECTED;\n }\n\n /**\n * Get the current connection state\n */\n getState(): ConnectionState {\n return this.state;\n }\n\n /**\n * Handle incoming WebSocket messages\n */\n private handleIncomingMessage(data: WebSocket.RawData): void {\n const messageString = data.toString();\n logger.debug({ dataLength: messageString.length }, 'Received message');\n\n const result = safeDeserializeMessage(messageString);\n\n if (!result.success) {\n logger.warn({ error: result.error.message }, 'Failed to parse incoming message');\n this.notifyError(new Error(`Invalid message format: ${result.error.message}`));\n return;\n }\n\n const message = result.data;\n logger.debug({ messageId: message.id, type: message.type }, 'Parsed message');\n\n // Notify all message handlers\n for (const handler of this.messageHandlers) {\n try {\n handler(message);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Message handler threw error');\n }\n }\n }\n\n /**\n * Notify all disconnect handlers\n */\n private notifyDisconnect(): void {\n for (const handler of this.disconnectHandlers) {\n try {\n handler();\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Disconnect handler threw error');\n }\n }\n }\n\n /**\n * Notify all error handlers\n */\n private notifyError(error: Error): void {\n for (const handler of this.errorHandlers) {\n try {\n handler(error);\n } catch (handlerError) {\n logger.error({ error: (handlerError as Error).message }, 'Error handler threw error');\n }\n }\n }\n\n /**\n * Notify all reconnecting handlers\n */\n private notifyReconnecting(attempt: number, maxAttempts: number): void {\n for (const handler of this.reconnectingHandlers) {\n try {\n handler(attempt, maxAttempts);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Reconnecting handler threw error');\n }\n }\n }\n\n // ============================================================================\n // Reconnection Methods\n // ============================================================================\n\n /**\n * Check if reconnection should be attempted\n */\n private shouldReconnect(): boolean {\n if (!this.config?.reconnect) {\n return false;\n }\n\n const maxAttempts = this.config.maxReconnectAttempts ?? DEFAULT_MAX_RECONNECT_ATTEMPTS;\n return this.reconnectAttempts < maxAttempts;\n }\n\n /**\n * Schedule a reconnection attempt\n */\n private scheduleReconnect(): void {\n if (this.reconnectTimer) {\n return; // Already scheduled\n }\n\n this.state = ConnectionState.RECONNECTING;\n this.reconnectAttempts++;\n\n const maxAttempts = this.config?.maxReconnectAttempts ?? DEFAULT_MAX_RECONNECT_ATTEMPTS;\n const interval = this.config?.reconnectInterval ?? DEFAULT_RECONNECT_INTERVAL;\n\n logger.info(\n { attempt: this.reconnectAttempts, maxAttempts, interval },\n 'Scheduling reconnection attempt'\n );\n\n // Notify reconnecting handlers\n this.notifyReconnecting(this.reconnectAttempts, maxAttempts);\n\n this.reconnectTimer = setTimeout(async () => {\n this.reconnectTimer = null;\n\n try {\n await this.establishConnection();\n logger.info({ attempts: this.reconnectAttempts }, 'Reconnection successful');\n } catch (error) {\n logger.warn({ error: (error as Error).message }, 'Reconnection attempt failed');\n\n // Schedule another attempt if we haven't reached the limit\n if (this.shouldReconnect()) {\n this.scheduleReconnect();\n } else {\n logger.error({ maxAttempts }, 'Max reconnection attempts reached, giving up');\n this.state = ConnectionState.DISCONNECTED;\n this.notifyError(new Error(`Failed to reconnect after ${maxAttempts} attempts`));\n }\n }\n }, interval);\n }\n\n /**\n * Clear any pending reconnection timer\n */\n private clearReconnectTimer(): void {\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n }\n\n // ============================================================================\n // Heartbeat Methods\n // ============================================================================\n\n /**\n * Start the heartbeat monitoring\n */\n private startHeartbeat(): void {\n this.stopHeartbeat(); // Clear any existing heartbeat\n\n this.heartbeatInterval = setInterval(() => {\n this.sendPing();\n }, DEFAULT_HEARTBEAT_INTERVAL);\n\n logger.debug({ interval: DEFAULT_HEARTBEAT_INTERVAL }, 'Heartbeat monitoring started');\n }\n\n /**\n * Stop the heartbeat monitoring\n */\n private stopHeartbeat(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n }\n\n if (this.heartbeatTimeout) {\n clearTimeout(this.heartbeatTimeout);\n this.heartbeatTimeout = null;\n }\n\n this.awaitingPong = false;\n }\n\n /**\n * Send a ping to the peer\n */\n private sendPing(): void {\n if (!this.ws || this.state !== ConnectionState.CONNECTED) {\n return;\n }\n\n if (this.awaitingPong) {\n // We didn't receive a pong for the previous ping - connection may be dead\n logger.warn('No pong received, connection may be dead');\n this.handleHeartbeatTimeout();\n return;\n }\n\n this.awaitingPong = true;\n this.ws.ping();\n\n // Set timeout for pong response\n this.heartbeatTimeout = setTimeout(() => {\n if (this.awaitingPong) {\n this.handleHeartbeatTimeout();\n }\n }, HEARTBEAT_TIMEOUT);\n\n logger.debug('Ping sent');\n }\n\n /**\n * Handle pong response from peer\n */\n private handlePong(): void {\n this.awaitingPong = false;\n\n if (this.heartbeatTimeout) {\n clearTimeout(this.heartbeatTimeout);\n this.heartbeatTimeout = null;\n }\n\n logger.debug('Pong received');\n }\n\n /**\n * Handle heartbeat timeout (no pong received)\n */\n private handleHeartbeatTimeout(): void {\n logger.warn('Heartbeat timeout - closing connection');\n this.awaitingPong = false;\n\n if (this.heartbeatTimeout) {\n clearTimeout(this.heartbeatTimeout);\n this.heartbeatTimeout = null;\n }\n\n // Close the connection to trigger reconnection if enabled\n if (this.ws) {\n this.ws.terminate();\n }\n }\n\n // ============================================================================\n // Getters for testing/debugging\n // ============================================================================\n\n /**\n * Get the current message queue length (for testing)\n */\n getQueueLength(): number {\n return this.messageQueue.length;\n }\n\n /**\n * Get the number of reconnection attempts (for testing)\n */\n getReconnectAttempts(): number {\n return this.reconnectAttempts;\n }\n}\n","/**\n * Message builder factory functions for Claude Code Bridge\n * Provides convenient functions to create specific message types\n */\n\nimport { createMessage, type BridgeMessage, type Context, type TaskRequest, type TaskResult } from './protocol.js';\n\n/**\n * Notification data structure for notification messages\n */\nexport interface NotificationData {\n type: string;\n message: string;\n data?: Record<string, unknown>;\n}\n\n/**\n * Creates a context synchronization message\n * Used to share context (files, tree, summary) with a peer\n * @param source The source instance identifier\n * @param context The context to synchronize\n * @returns A BridgeMessage with type 'context_sync'\n */\nexport function createContextSyncMessage(\n source: string,\n context: Context\n): BridgeMessage {\n const message = createMessage('context_sync', source);\n return {\n ...message,\n context,\n };\n}\n\n/**\n * Creates a task delegation message\n * Used to delegate a task to a peer instance\n * @param source The source instance identifier\n * @param task The task to delegate\n * @returns A BridgeMessage with type 'task_delegate'\n */\nexport function createTaskDelegateMessage(\n source: string,\n task: TaskRequest\n): BridgeMessage {\n const message = createMessage('task_delegate', source);\n return {\n ...message,\n task,\n };\n}\n\n/**\n * Creates a task response message\n * Used to respond to a delegated task\n * @param source The source instance identifier\n * @param taskId The ID of the task being responded to\n * @param result The result of the task execution\n * @returns A BridgeMessage with type 'response'\n */\nexport function createTaskResponseMessage(\n source: string,\n taskId: string,\n result: Omit<TaskResult, 'taskId'>\n): BridgeMessage {\n const message = createMessage('response', source);\n return {\n ...message,\n result: {\n ...result,\n taskId,\n },\n };\n}\n\n/**\n * Creates a context request message\n * Used to request specific context from a peer\n * @param source The source instance identifier\n * @param query A description of what context is being requested\n * @returns A BridgeMessage with type 'request'\n */\nexport function createContextRequestMessage(\n source: string,\n query: string\n): BridgeMessage {\n const message = createMessage('request', source);\n return {\n ...message,\n context: {\n summary: query,\n },\n };\n}\n\n/**\n * Creates a notification message\n * Used to send notifications to peers (events, status updates, etc.)\n * @param source The source instance identifier\n * @param notification The notification data\n * @returns A BridgeMessage with type 'notification'\n */\nexport function createNotificationMessage(\n source: string,\n notification: NotificationData\n): BridgeMessage {\n const message = createMessage('notification', source);\n return {\n ...message,\n context: {\n summary: notification.message,\n variables: {\n notificationType: notification.type,\n ...notification.data,\n },\n },\n };\n}\n","/**\n * Bridge Core - Main orchestration class for Claude Code Bridge\n * Handles peer connections, message routing, and lifecycle management\n */\n\nimport { WebSocketServer, WebSocket as WsWebSocket } from 'ws';\nimport { v4 as uuidv4 } from 'uuid';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { createLogger } from '../utils/logger.js';\nimport { WebSocketTransport } from '../transport/websocket.js';\nimport { ConnectionState, type Transport } from '../transport/interface.js';\nimport {\n type BridgeMessage,\n type TaskRequest,\n type TaskResult,\n type Context,\n type FileChunk,\n safeDeserializeMessage,\n serializeMessage,\n} from './protocol.js';\nimport {\n createTaskDelegateMessage,\n createTaskResponseMessage,\n createContextSyncMessage,\n createContextRequestMessage,\n} from './messages.js';\n\nconst logger = createLogger('bridge');\n\n// ============================================================================\n// Type Definitions\n// ============================================================================\n\n/**\n * Bridge operation mode\n * - 'host': Listen for incoming connections only\n * - 'client': Connect to a remote bridge only\n * - 'peer': Both listen and connect (bidirectional)\n */\nexport type BridgeMode = 'host' | 'client' | 'peer';\n\n/**\n * Configuration for the bridge's listening server\n */\nexport interface BridgeListenConfig {\n /** Port to listen on */\n port: number;\n /** Host to bind to (default: 0.0.0.0) */\n host?: string;\n}\n\n/**\n * Configuration for connecting to a remote bridge\n */\nexport interface BridgeConnectConfig {\n /** Full WebSocket URL (e.g., ws://localhost:8765) */\n url?: string;\n /** Use host.docker.internal for container-to-host connection */\n hostGateway?: boolean;\n /** Port to connect to (used if url is not provided) */\n port?: number;\n}\n\n/**\n * Context sharing configuration\n */\nexport interface ContextSharingConfig {\n /** Enable automatic context synchronization */\n autoSync?: boolean;\n /** Interval in milliseconds for auto-sync (default: 5000) */\n syncInterval?: number;\n}\n\n/**\n * Full configuration for Bridge initialization\n */\nexport interface BridgeConfig {\n /** Operation mode: 'host', 'client', or 'peer' */\n mode: BridgeMode;\n /** Unique identifier for this bridge instance */\n instanceName: string;\n /** Server configuration (required for 'host' and 'peer' modes) */\n listen?: BridgeListenConfig;\n /** Connection configuration (required for 'client' and 'peer' modes) */\n connect?: BridgeConnectConfig;\n /** Task timeout in milliseconds (default: 300000 / 5 minutes) */\n taskTimeout?: number;\n /** Context sharing configuration */\n contextSharing?: ContextSharingConfig;\n}\n\n/**\n * Information about a connected peer\n */\nexport interface PeerInfo {\n /** Unique identifier for the peer connection */\n id: string;\n /** Name of the peer instance */\n name: string;\n /** Environment type of the peer */\n environment?: string;\n /** Timestamp when the peer connected */\n connectedAt: number;\n /** Timestamp of last activity from the peer */\n lastActivity: number;\n}\n\n/**\n * Internal peer connection tracking\n */\ninterface PeerConnection {\n /** Peer information */\n info: PeerInfo;\n /** WebSocket connection (for server-side connections) */\n ws?: WsWebSocket;\n /** Transport instance (for client-side connections) */\n transport?: Transport;\n}\n\n/**\n * Handler for peer connection events\n */\nexport type PeerConnectedHandler = (peer: PeerInfo) => void;\n\n/**\n * Handler for peer disconnection events\n */\nexport type PeerDisconnectedHandler = (peer: PeerInfo) => void;\n\n/**\n * Handler for incoming messages from peers\n */\nexport type MessageReceivedHandler = (message: BridgeMessage, peerId: string) => void;\n\n/**\n * Handler for incoming task delegation requests\n * Returns a TaskResult or Promise<TaskResult>\n */\nexport type TaskReceivedHandler = (task: TaskRequest, peerId: string) => TaskResult | Promise<TaskResult>;\n\n/**\n * Handler for incoming context synchronization\n */\nexport type ContextReceivedHandler = (context: Context, peerId: string) => void;\n\n/**\n * Handler for incoming context requests\n * Returns FileChunk[] or Promise<FileChunk[]>\n */\nexport type ContextRequestedHandler = (query: string, peerId: string) => FileChunk[] | Promise<FileChunk[]>;\n\n/**\n * Pending task tracking for response correlation\n */\ninterface PendingTask {\n taskId: string;\n peerId: string;\n resolve: (result: TaskResult) => void;\n reject: (error: Error) => void;\n timeoutId: ReturnType<typeof setTimeout>;\n}\n\n/**\n * Pending context request tracking for response correlation\n */\ninterface PendingContextRequest {\n requestId: string;\n peerId: string;\n resolve: (chunks: FileChunk[]) => void;\n reject: (error: Error) => void;\n timeoutId: ReturnType<typeof setTimeout>;\n}\n\n// ============================================================================\n// Bridge Class\n// ============================================================================\n\n/**\n * Main Bridge class for managing peer-to-peer communication\n * Supports three modes of operation:\n * - 'host': Acts as a server, accepting incoming connections\n * - 'client': Acts as a client, connecting to a remote server\n * - 'peer': Both listens for connections and connects to a remote peer\n */\nexport class Bridge {\n private config: BridgeConfig;\n private server: WebSocketServer | null = null;\n private clientTransport: WebSocketTransport | null = null;\n private peers: Map<string, PeerConnection> = new Map();\n private started: boolean = false;\n\n // Event handlers\n private peerConnectedHandlers: PeerConnectedHandler[] = [];\n private peerDisconnectedHandlers: PeerDisconnectedHandler[] = [];\n private messageReceivedHandlers: MessageReceivedHandler[] = [];\n private taskReceivedHandler: TaskReceivedHandler | null = null;\n private contextReceivedHandlers: ContextReceivedHandler[] = [];\n private contextRequestedHandler: ContextRequestedHandler | null = null;\n\n // Task correlation\n private pendingTasks: Map<string, PendingTask> = new Map();\n\n // Context request correlation\n private pendingContextRequests: Map<string, PendingContextRequest> = new Map();\n\n // Auto-sync interval timer\n private autoSyncIntervalId: ReturnType<typeof setInterval> | null = null;\n\n /**\n * Create a new Bridge instance\n * @param config Bridge configuration\n */\n constructor(config: BridgeConfig) {\n this.config = config;\n this.validateConfig();\n logger.info({ instanceName: config.instanceName, mode: config.mode }, 'Bridge instance created');\n }\n\n /**\n * Validate the configuration based on mode requirements\n */\n private validateConfig(): void {\n const { mode, listen, connect } = this.config;\n\n if (mode === 'host' && !listen) {\n throw new Error(\"'host' mode requires 'listen' configuration\");\n }\n\n if (mode === 'client' && !connect) {\n throw new Error(\"'client' mode requires 'connect' configuration\");\n }\n\n if (mode === 'peer' && !listen && !connect) {\n throw new Error(\"'peer' mode requires either 'listen' or 'connect' configuration (or both)\");\n }\n }\n\n /**\n * Start the bridge based on configured mode\n * - 'host': Starts WebSocket server\n * - 'client': Connects to remote bridge\n * - 'peer': Both starts server and connects to remote\n */\n async start(): Promise<void> {\n if (this.started) {\n throw new Error('Bridge is already started');\n }\n\n const { mode } = this.config;\n logger.info({ mode }, 'Starting bridge');\n\n try {\n // Start server if in host or peer mode\n if ((mode === 'host' || mode === 'peer') && this.config.listen) {\n await this.startServer();\n }\n\n // Connect to remote if in client or peer mode\n if ((mode === 'client' || mode === 'peer') && this.config.connect) {\n await this.connectToRemote();\n }\n\n this.started = true;\n this.writeStatusFile();\n logger.info({ mode, instanceName: this.config.instanceName }, 'Bridge started successfully');\n } catch (error) {\n // Cleanup on failure\n await this.cleanup();\n throw error;\n }\n }\n\n /**\n * Stop the bridge and close all connections\n */\n async stop(): Promise<void> {\n if (!this.started) {\n return;\n }\n\n logger.info('Stopping bridge');\n await this.cleanup();\n this.started = false;\n logger.info('Bridge stopped');\n }\n\n /**\n * Get list of connected peers\n */\n getPeers(): PeerInfo[] {\n return Array.from(this.peers.values()).map(p => p.info);\n }\n\n /**\n * Connect to a remote bridge\n * @param url WebSocket URL to connect to\n */\n async connectToPeer(url: string): Promise<void> {\n const transport = new WebSocketTransport();\n\n // Set up message handler\n transport.onMessage((message) => {\n this.handleMessage(message, transport);\n });\n\n // Set up disconnect handler\n transport.onDisconnect(() => {\n this.handleClientDisconnect(transport);\n });\n\n try {\n await transport.connect({\n url,\n reconnect: true,\n reconnectInterval: 1000,\n maxReconnectAttempts: 10,\n });\n\n // Create peer info for the connected remote\n const peerId = uuidv4();\n const peerInfo: PeerInfo = {\n id: peerId,\n name: 'remote', // Will be updated when we receive peer info\n connectedAt: Date.now(),\n lastActivity: Date.now(),\n };\n\n this.peers.set(peerId, {\n info: peerInfo,\n transport,\n });\n\n // Store peerId on transport for lookup\n (transport as WebSocketTransport & { _peerId?: string })._peerId = peerId;\n\n this.notifyPeerConnected(peerInfo);\n logger.info({ peerId, url }, 'Connected to remote peer');\n } catch (error) {\n logger.error({ error: (error as Error).message, url }, 'Failed to connect to remote peer');\n throw error;\n }\n }\n\n /**\n * Disconnect from a specific peer\n * @param peerId ID of the peer to disconnect from\n */\n async disconnectFromPeer(peerId: string): Promise<void> {\n const peer = this.peers.get(peerId);\n if (!peer) {\n throw new Error(`Peer not found: ${peerId}`);\n }\n\n if (peer.transport) {\n await peer.transport.disconnect();\n }\n\n if (peer.ws) {\n peer.ws.close(1000, 'Disconnect requested');\n }\n\n this.peers.delete(peerId);\n this.notifyPeerDisconnected(peer.info);\n logger.info({ peerId }, 'Disconnected from peer');\n }\n\n /**\n * Send a message to a specific peer\n * @param peerId ID of the peer to send to\n * @param message Message to send\n */\n async sendToPeer(peerId: string, message: BridgeMessage): Promise<void> {\n const peer = this.peers.get(peerId);\n if (!peer) {\n throw new Error(`Peer not found: ${peerId}`);\n }\n\n if (peer.transport) {\n await peer.transport.send(message);\n } else if (peer.ws) {\n const serialized = serializeMessage(message);\n await new Promise<void>((resolve, reject) => {\n peer.ws!.send(serialized, (error) => {\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n });\n } else {\n throw new Error('No transport available for peer');\n }\n\n logger.debug({ peerId, messageId: message.id, type: message.type }, 'Sent message to peer');\n }\n\n /**\n * Broadcast a message to all connected peers\n * @param message Message to broadcast\n */\n async broadcast(message: BridgeMessage): Promise<void> {\n const sendPromises = Array.from(this.peers.keys()).map(peerId =>\n this.sendToPeer(peerId, message).catch(error => {\n logger.error({ error: (error as Error).message, peerId }, 'Failed to send to peer');\n })\n );\n\n await Promise.all(sendPromises);\n logger.debug({ messageId: message.id, peerCount: this.peers.size }, 'Broadcast message sent');\n }\n\n // ============================================================================\n // Event Registration\n // ============================================================================\n\n /**\n * Register a handler for peer connection events\n */\n onPeerConnected(handler: PeerConnectedHandler): void {\n this.peerConnectedHandlers.push(handler);\n }\n\n /**\n * Register a handler for peer disconnection events\n */\n onPeerDisconnected(handler: PeerDisconnectedHandler): void {\n this.peerDisconnectedHandlers.push(handler);\n }\n\n /**\n * Register a handler for incoming messages\n */\n onMessage(handler: MessageReceivedHandler): void {\n this.messageReceivedHandlers.push(handler);\n }\n\n /**\n * Register a handler for incoming task delegation requests\n * Only one handler can be registered at a time\n * @param handler Function that receives a TaskRequest and returns a TaskResult\n */\n onTaskReceived(handler: TaskReceivedHandler): void {\n this.taskReceivedHandler = handler;\n }\n\n /**\n * Register a handler for incoming context synchronization\n * Multiple handlers can be registered\n * @param handler Function that receives context and peerId\n */\n onContextReceived(handler: ContextReceivedHandler): void {\n this.contextReceivedHandlers.push(handler);\n }\n\n /**\n * Register a handler for incoming context requests\n * Only one handler can be registered at a time\n * @param handler Function that receives a query and returns FileChunk[]\n */\n onContextRequested(handler: ContextRequestedHandler): void {\n this.contextRequestedHandler = handler;\n }\n\n // ============================================================================\n // Task Delegation\n // ============================================================================\n\n /**\n * Delegate a task to a peer and wait for the result\n * @param task The task request to delegate\n * @param peerId Optional peer ID to send to (defaults to first peer)\n * @returns Promise that resolves with the task result\n * @throws Error if no peers are connected or task times out\n */\n async delegateTask(task: TaskRequest, peerId?: string): Promise<TaskResult> {\n // Get target peer\n if (!peerId) {\n const peers = this.getPeers();\n if (peers.length === 0) {\n throw new Error('No peers connected to delegate task to');\n }\n peerId = peers[0].id;\n }\n\n // Validate peer exists\n if (!this.peers.has(peerId)) {\n throw new Error(`Peer not found: ${peerId}`);\n }\n\n // Determine timeout\n const timeout = task.timeout ?? this.config.taskTimeout ?? 300000; // Default 5 minutes\n\n // Create promise to track task completion\n return new Promise<TaskResult>((resolve, reject) => {\n // Create the task delegate message\n const message = createTaskDelegateMessage(this.config.instanceName, task);\n\n // Set up timeout\n const timeoutId = setTimeout(() => {\n const pending = this.pendingTasks.get(task.id);\n if (pending) {\n this.pendingTasks.delete(task.id);\n reject(new Error(`Task '${task.id}' timed out after ${timeout}ms`));\n }\n }, timeout);\n\n // Store pending task for correlation\n this.pendingTasks.set(task.id, {\n taskId: task.id,\n peerId,\n resolve,\n reject,\n timeoutId,\n });\n\n // Send the task\n this.sendToPeer(peerId, message).catch((error) => {\n // Clean up on send error\n clearTimeout(timeoutId);\n this.pendingTasks.delete(task.id);\n reject(error);\n });\n\n logger.debug({ taskId: task.id, peerId, timeout }, 'Task delegated');\n });\n }\n\n // ============================================================================\n // Context Synchronization\n // ============================================================================\n\n /**\n * Synchronize context with connected peers\n * @param context Optional context to sync. If not provided, broadcasts to all peers\n * @param peerId Optional peer ID to send to (defaults to all peers)\n */\n async syncContext(context?: Context, peerId?: string): Promise<void> {\n // Use empty context if not provided\n const contextToSync = context ?? {};\n\n // Create the context sync message\n const message = createContextSyncMessage(this.config.instanceName, contextToSync);\n\n if (peerId) {\n // Send to specific peer\n await this.sendToPeer(peerId, message);\n logger.debug({ peerId, messageId: message.id }, 'Context synced to peer');\n } else {\n // Broadcast to all peers\n await this.broadcast(message);\n logger.debug({ peerCount: this.peers.size, messageId: message.id }, 'Context synced to all peers');\n }\n }\n\n /**\n * Request context from a peer based on a query\n * @param query Description of what context is being requested\n * @param peerId Optional peer ID to request from (defaults to first peer)\n * @param timeout Optional timeout in milliseconds (default: 30000)\n * @returns Promise that resolves with FileChunk[] from the peer\n * @throws Error if no peers are connected or request times out\n */\n async requestContext(query: string, peerId?: string, timeout: number = 30000): Promise<FileChunk[]> {\n // Get target peer\n if (!peerId) {\n const peers = this.getPeers();\n if (peers.length === 0) {\n throw new Error('No peers connected to request context from');\n }\n peerId = peers[0].id;\n }\n\n // Validate peer exists\n if (!this.peers.has(peerId)) {\n throw new Error(`Peer not found: ${peerId}`);\n }\n\n // Create promise to track request completion\n return new Promise<FileChunk[]>((resolve, reject) => {\n // Create the context request message\n const message = createContextRequestMessage(this.config.instanceName, query);\n\n // Set up timeout\n const timeoutId = setTimeout(() => {\n const pending = this.pendingContextRequests.get(message.id);\n if (pending) {\n this.pendingContextRequests.delete(message.id);\n reject(new Error(`Context request timed out after ${timeout}ms`));\n }\n }, timeout);\n\n // Store pending request for correlation\n this.pendingContextRequests.set(message.id, {\n requestId: message.id,\n peerId,\n resolve,\n reject,\n timeoutId,\n });\n\n // Send the request\n this.sendToPeer(peerId, message).catch((error) => {\n // Clean up on send error\n clearTimeout(timeoutId);\n this.pendingContextRequests.delete(message.id);\n reject(error);\n });\n\n logger.debug({ requestId: message.id, peerId, query }, 'Context requested');\n });\n }\n\n /**\n * Start automatic context synchronization\n * Uses interval from config.contextSharing.syncInterval (default: 5000ms)\n * @param contextProvider Optional function that returns context to sync\n */\n startAutoSync(contextProvider?: () => Context | Promise<Context>): void {\n // Stop any existing auto-sync\n this.stopAutoSync();\n\n const interval = this.config.contextSharing?.syncInterval ?? 5000;\n\n this.autoSyncIntervalId = setInterval(async () => {\n try {\n // Get context from provider if available\n const context = contextProvider ? await contextProvider() : undefined;\n await this.syncContext(context);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Auto-sync error');\n }\n }, interval);\n\n logger.info({ interval }, 'Auto-sync started');\n }\n\n /**\n * Stop automatic context synchronization\n */\n stopAutoSync(): void {\n if (this.autoSyncIntervalId) {\n clearInterval(this.autoSyncIntervalId);\n this.autoSyncIntervalId = null;\n logger.info('Auto-sync stopped');\n }\n }\n\n // ============================================================================\n // Private Methods - Server\n // ============================================================================\n\n /**\n * Start the WebSocket server\n */\n private async startServer(): Promise<void> {\n const { listen } = this.config;\n if (!listen) {\n throw new Error('Listen configuration is required');\n }\n\n return new Promise<void>((resolve, reject) => {\n const host = listen.host ?? '0.0.0.0';\n const port = listen.port;\n\n logger.debug({ host, port }, 'Starting WebSocket server');\n\n this.server = new WebSocketServer({ host, port });\n\n this.server.on('listening', () => {\n logger.info({ host, port }, 'WebSocket server listening');\n resolve();\n });\n\n this.server.on('error', (error) => {\n logger.error({ error: (error as Error).message }, 'WebSocket server error');\n reject(error);\n });\n\n this.server.on('connection', (ws, request) => {\n this.handleNewConnection(ws, request);\n });\n });\n }\n\n /**\n * Handle a new incoming connection\n */\n private handleNewConnection(ws: WsWebSocket, request: { url?: string }): void {\n const peerId = uuidv4();\n const peerInfo: PeerInfo = {\n id: peerId,\n name: 'client', // Will be updated when we receive peer info\n connectedAt: Date.now(),\n lastActivity: Date.now(),\n };\n\n this.peers.set(peerId, {\n info: peerInfo,\n ws,\n });\n\n logger.info({ peerId, url: request.url }, 'New peer connected');\n\n // Set up message handler\n ws.on('message', (data) => {\n const messageString = data.toString();\n const result = safeDeserializeMessage(messageString);\n\n if (result.success) {\n peerInfo.lastActivity = Date.now();\n this.handleMessage(result.data, ws, peerId);\n } else {\n logger.warn({ peerId, error: result.error.message }, 'Invalid message received');\n }\n });\n\n // Set up close handler\n ws.on('close', (code, reason) => {\n logger.info({ peerId, code, reason: reason.toString() }, 'Peer disconnected');\n this.peers.delete(peerId);\n this.notifyPeerDisconnected(peerInfo);\n });\n\n // Set up error handler\n ws.on('error', (error) => {\n logger.error({ peerId, error: (error as Error).message }, 'Peer connection error');\n });\n\n // Notify peer connected handlers\n this.notifyPeerConnected(peerInfo);\n }\n\n // ============================================================================\n // Private Methods - Client\n // ============================================================================\n\n /**\n * Connect to a remote bridge as a client\n */\n private async connectToRemote(): Promise<void> {\n const { connect } = this.config;\n if (!connect) {\n throw new Error('Connect configuration is required');\n }\n\n // Build URL from config\n let url = connect.url;\n if (!url) {\n const host = connect.hostGateway ? 'host.docker.internal' : 'localhost';\n const port = connect.port ?? 8765;\n url = `ws://${host}:${port}`;\n }\n\n this.clientTransport = new WebSocketTransport();\n\n // Set up message handler\n this.clientTransport.onMessage((message) => {\n this.handleMessage(message, this.clientTransport!);\n });\n\n // Set up disconnect handler\n this.clientTransport.onDisconnect(() => {\n this.handleClientDisconnect(this.clientTransport!);\n });\n\n try {\n await this.clientTransport.connect({\n url,\n reconnect: true,\n reconnectInterval: 1000,\n maxReconnectAttempts: 10,\n });\n\n // Create peer info for the connected server\n const peerId = uuidv4();\n const peerInfo: PeerInfo = {\n id: peerId,\n name: 'server',\n connectedAt: Date.now(),\n lastActivity: Date.now(),\n };\n\n this.peers.set(peerId, {\n info: peerInfo,\n transport: this.clientTransport,\n });\n\n // Store peerId on transport for lookup\n (this.clientTransport as WebSocketTransport & { _peerId?: string })._peerId = peerId;\n\n this.notifyPeerConnected(peerInfo);\n logger.info({ peerId, url }, 'Connected to remote bridge');\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Failed to connect to remote bridge');\n this.clientTransport = null;\n throw error;\n }\n }\n\n /**\n * Handle client transport disconnect\n */\n private handleClientDisconnect(transport: Transport): void {\n // Find peer by transport\n const typedTransport = transport as WebSocketTransport & { _peerId?: string };\n const peerId = typedTransport._peerId;\n\n if (peerId) {\n const peer = this.peers.get(peerId);\n if (peer) {\n this.peers.delete(peerId);\n this.notifyPeerDisconnected(peer.info);\n logger.info({ peerId }, 'Client transport disconnected');\n }\n }\n }\n\n // ============================================================================\n // Private Methods - Message Handling\n // ============================================================================\n\n /**\n * Handle an incoming message\n */\n private handleMessage(\n message: BridgeMessage,\n source: WsWebSocket | Transport,\n peerId?: string\n ): void {\n // Find peerId if not provided\n if (!peerId) {\n const typedSource = source as WebSocketTransport & { _peerId?: string };\n peerId = typedSource._peerId;\n }\n\n if (!peerId) {\n // Try to find by ws reference\n for (const [id, peer] of this.peers) {\n if (peer.ws === source || peer.transport === source) {\n peerId = id;\n break;\n }\n }\n }\n\n if (!peerId) {\n logger.warn({ messageId: message.id }, 'Received message from unknown peer');\n return;\n }\n\n // Update last activity\n const peer = this.peers.get(peerId);\n if (peer) {\n peer.info.lastActivity = Date.now();\n }\n\n logger.debug({ peerId, messageId: message.id, type: message.type }, 'Received message');\n\n // Handle task delegation messages\n if (message.type === 'task_delegate' && message.task) {\n this.handleTaskDelegate(message, peerId);\n return;\n }\n\n // Handle task response messages\n if (message.type === 'response' && message.result?.taskId) {\n this.handleTaskResponse(message);\n return;\n }\n\n // Handle context sync messages\n if (message.type === 'context_sync' && message.context) {\n this.handleContextSync(message, peerId);\n return;\n }\n\n // Handle context request messages\n if (message.type === 'request' && message.context?.summary) {\n this.handleContextRequest(message, peerId);\n return;\n }\n\n // Handle context response messages (responses to context requests)\n if (message.type === 'response' && message.context?.files !== undefined) {\n this.handleContextResponse(message);\n return;\n }\n\n // Notify message handlers for other message types\n this.notifyMessageReceived(message, peerId);\n }\n\n /**\n * Handle incoming task delegation request\n */\n private async handleTaskDelegate(message: BridgeMessage, peerId: string): Promise<void> {\n const task = message.task!;\n logger.debug({ taskId: task.id, peerId }, 'Received task delegation');\n\n // If no handler registered, send error response\n if (!this.taskReceivedHandler) {\n logger.warn({ taskId: task.id }, 'No task handler registered');\n const response = createTaskResponseMessage(\n this.config.instanceName,\n task.id,\n {\n success: false,\n data: null,\n error: 'No task handler registered on peer',\n }\n );\n await this.sendToPeer(peerId, response).catch((err) => {\n logger.error({ error: (err as Error).message, taskId: task.id }, 'Failed to send error response');\n });\n return;\n }\n\n try {\n // Execute the task handler\n const result = await this.taskReceivedHandler(task, peerId);\n\n // Send successful response\n const response = createTaskResponseMessage(\n this.config.instanceName,\n task.id,\n result\n );\n await this.sendToPeer(peerId, response);\n logger.debug({ taskId: task.id, success: result.success }, 'Task response sent');\n } catch (error) {\n // Send error response\n const response = createTaskResponseMessage(\n this.config.instanceName,\n task.id,\n {\n success: false,\n data: null,\n error: (error as Error).message,\n }\n );\n await this.sendToPeer(peerId, response).catch((err) => {\n logger.error({ error: (err as Error).message, taskId: task.id }, 'Failed to send error response');\n });\n logger.error({ taskId: task.id, error: (error as Error).message }, 'Task handler error');\n }\n }\n\n /**\n * Handle task response message (correlate with pending task)\n */\n private handleTaskResponse(message: BridgeMessage): void {\n const taskId = message.result!.taskId!;\n const pending = this.pendingTasks.get(taskId);\n\n if (!pending) {\n logger.warn({ taskId }, 'Received response for unknown task');\n return;\n }\n\n // Clear timeout and remove from pending\n clearTimeout(pending.timeoutId);\n this.pendingTasks.delete(taskId);\n\n // Resolve the promise with the result\n const result: TaskResult = {\n taskId: message.result!.taskId,\n success: message.result!.success,\n data: message.result!.data,\n artifacts: message.result!.artifacts,\n followUp: message.result!.followUp,\n error: message.result!.error,\n };\n\n logger.debug({ taskId, success: result.success }, 'Task result received');\n pending.resolve(result);\n }\n\n /**\n * Handle incoming context sync message\n */\n private handleContextSync(message: BridgeMessage, peerId: string): void {\n const context = message.context!;\n logger.debug({ peerId, messageId: message.id }, 'Received context sync');\n\n // Notify all context received handlers\n this.notifyContextReceived(context, peerId);\n }\n\n /**\n * Handle incoming context request message\n */\n private async handleContextRequest(message: BridgeMessage, peerId: string): Promise<void> {\n const query = message.context!.summary!;\n logger.debug({ peerId, messageId: message.id, query }, 'Received context request');\n\n // If no handler registered, send empty response\n if (!this.contextRequestedHandler) {\n logger.warn({ messageId: message.id }, 'No context request handler registered');\n const response = createContextSyncMessage(this.config.instanceName, { files: [] });\n // Change type to response and add request ID for correlation\n const responseMessage: BridgeMessage = {\n ...response,\n type: 'response',\n context: {\n ...response.context,\n variables: { requestId: message.id },\n },\n };\n await this.sendToPeer(peerId, responseMessage).catch((err) => {\n logger.error({ error: (err as Error).message, messageId: message.id }, 'Failed to send empty context response');\n });\n return;\n }\n\n try {\n // Execute the context request handler\n const files = await this.contextRequestedHandler(query, peerId);\n\n // Create and send response\n const response = createContextSyncMessage(this.config.instanceName, { files });\n const responseMessage: BridgeMessage = {\n ...response,\n type: 'response',\n context: {\n ...response.context,\n variables: { requestId: message.id },\n },\n };\n await this.sendToPeer(peerId, responseMessage);\n logger.debug({ messageId: message.id, fileCount: files.length }, 'Context response sent');\n } catch (error) {\n // Send error response with empty files\n const response = createContextSyncMessage(this.config.instanceName, {\n files: [],\n summary: (error as Error).message,\n });\n const responseMessage: BridgeMessage = {\n ...response,\n type: 'response',\n context: {\n ...response.context,\n variables: { requestId: message.id, error: (error as Error).message },\n },\n };\n await this.sendToPeer(peerId, responseMessage).catch((err) => {\n logger.error({ error: (err as Error).message, messageId: message.id }, 'Failed to send error context response');\n });\n logger.error({ messageId: message.id, error: (error as Error).message }, 'Context request handler error');\n }\n }\n\n /**\n * Handle context response message (correlate with pending context request)\n */\n private handleContextResponse(message: BridgeMessage): void {\n const requestId = message.context?.variables?.requestId as string;\n if (!requestId) {\n logger.warn({ messageId: message.id }, 'Context response without requestId');\n return;\n }\n\n const pending = this.pendingContextRequests.get(requestId);\n if (!pending) {\n logger.warn({ requestId }, 'Received response for unknown context request');\n return;\n }\n\n // Clear timeout and remove from pending\n clearTimeout(pending.timeoutId);\n this.pendingContextRequests.delete(requestId);\n\n // Check for error\n const error = message.context?.variables?.error as string | undefined;\n if (error) {\n pending.reject(new Error(error));\n return;\n }\n\n // Resolve the promise with the files\n const files = message.context?.files ?? [];\n logger.debug({ requestId, fileCount: files.length }, 'Context response received');\n pending.resolve(files);\n }\n\n // ============================================================================\n // Private Methods - Event Notification\n // ============================================================================\n\n private notifyPeerConnected(peer: PeerInfo): void {\n // Update status file with new peer\n this.writeStatusFile();\n\n for (const handler of this.peerConnectedHandlers) {\n try {\n handler(peer);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Peer connected handler error');\n }\n }\n }\n\n private notifyPeerDisconnected(peer: PeerInfo): void {\n // Reject any pending tasks for this peer\n for (const [taskId, pending] of this.pendingTasks) {\n if (pending.peerId === peer.id) {\n clearTimeout(pending.timeoutId);\n this.pendingTasks.delete(taskId);\n pending.reject(new Error(`Peer '${peer.id}' disconnected while task '${taskId}' was pending`));\n }\n }\n\n // Reject any pending context requests for this peer\n for (const [requestId, pending] of this.pendingContextRequests) {\n if (pending.peerId === peer.id) {\n clearTimeout(pending.timeoutId);\n this.pendingContextRequests.delete(requestId);\n pending.reject(new Error(`Peer '${peer.id}' disconnected while context request '${requestId}' was pending`));\n }\n }\n\n for (const handler of this.peerDisconnectedHandlers) {\n try {\n handler(peer);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Peer disconnected handler error');\n }\n }\n\n // Update status file after peer removed\n this.writeStatusFile();\n }\n\n private notifyMessageReceived(message: BridgeMessage, peerId: string): void {\n for (const handler of this.messageReceivedHandlers) {\n try {\n handler(message, peerId);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Message received handler error');\n }\n }\n }\n\n private notifyContextReceived(context: Context, peerId: string): void {\n for (const handler of this.contextReceivedHandlers) {\n try {\n handler(context, peerId);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Context received handler error');\n }\n }\n }\n\n // ============================================================================\n // Private Methods - Cleanup\n // ============================================================================\n\n /**\n * Clean up all resources\n */\n private async cleanup(): Promise<void> {\n logger.debug('Starting cleanup');\n\n // Stop auto-sync\n this.stopAutoSync();\n logger.debug('Auto-sync stopped');\n\n // Reject all pending tasks\n const pendingTaskCount = this.pendingTasks.size;\n for (const [taskId, pending] of this.pendingTasks) {\n clearTimeout(pending.timeoutId);\n pending.reject(new Error('Bridge is shutting down'));\n }\n this.pendingTasks.clear();\n if (pendingTaskCount > 0) {\n logger.debug({ count: pendingTaskCount }, 'Pending tasks cancelled');\n }\n\n // Reject all pending context requests\n const pendingContextCount = this.pendingContextRequests.size;\n for (const [requestId, pending] of this.pendingContextRequests) {\n clearTimeout(pending.timeoutId);\n pending.reject(new Error('Bridge is shutting down'));\n }\n this.pendingContextRequests.clear();\n if (pendingContextCount > 0) {\n logger.debug({ count: pendingContextCount }, 'Pending context requests cancelled');\n }\n\n // Disconnect client transport\n if (this.clientTransport) {\n logger.debug('Disconnecting client transport');\n try {\n await this.clientTransport.disconnect();\n logger.debug('Client transport disconnected');\n } catch {\n // Ignore disconnect errors during cleanup\n }\n this.clientTransport = null;\n }\n\n // Close all peer WebSocket connections\n const peerCount = this.peers.size;\n if (peerCount > 0) {\n logger.debug({ count: peerCount }, 'Closing peer connections');\n }\n for (const [peerId, peer] of this.peers) {\n if (peer.ws) {\n try {\n peer.ws.close(1000, 'Bridge stopping');\n } catch {\n // Ignore close errors during cleanup\n }\n }\n if (peer.transport) {\n try {\n await peer.transport.disconnect();\n } catch {\n // Ignore disconnect errors during cleanup\n }\n }\n logger.debug({ peerId }, 'Peer disconnected');\n }\n this.peers.clear();\n\n // Close server\n if (this.server) {\n logger.debug('Closing WebSocket server');\n await new Promise<void>((resolve) => {\n this.server!.close(() => {\n resolve();\n });\n });\n this.server = null;\n logger.debug('WebSocket server closed');\n }\n\n // Remove status file\n this.removeStatusFile();\n\n logger.debug('Cleanup complete');\n }\n\n // ============================================================================\n // Status File Management\n // ============================================================================\n\n /**\n * Get the status file path\n */\n private getStatusFilePath(): string {\n const bridgeDir = path.join(os.homedir(), '.claude-bridge');\n return path.join(bridgeDir, 'status.json');\n }\n\n /**\n * Ensure the .claude-bridge directory exists\n */\n private ensureBridgeDir(): void {\n const bridgeDir = path.join(os.homedir(), '.claude-bridge');\n if (!fs.existsSync(bridgeDir)) {\n fs.mkdirSync(bridgeDir, { recursive: true });\n }\n }\n\n /**\n * Write current status to status file\n */\n private writeStatusFile(): void {\n try {\n this.ensureBridgeDir();\n const statusFile = this.getStatusFilePath();\n const status = {\n port: this.config.listen?.port,\n instanceName: this.config.instanceName,\n mode: this.config.mode,\n peers: this.getPeers().map(p => ({\n id: p.id,\n name: p.name,\n connectedAt: new Date(p.connectedAt).toISOString(),\n lastActivity: new Date(p.lastActivity).toISOString(),\n })),\n };\n fs.writeFileSync(statusFile, JSON.stringify(status, null, 2), 'utf-8');\n logger.debug({ statusFile }, 'Status file updated');\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Failed to write status file');\n }\n }\n\n /**\n * Remove the status file\n */\n private removeStatusFile(): void {\n try {\n const statusFile = this.getStatusFilePath();\n if (fs.existsSync(statusFile)) {\n fs.unlinkSync(statusFile);\n logger.debug({ statusFile }, 'Status file removed');\n }\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Failed to remove status file');\n }\n }\n\n // ============================================================================\n // Getters for State Inspection\n // ============================================================================\n\n /**\n * Check if the bridge is started\n */\n isStarted(): boolean {\n return this.started;\n }\n\n /**\n * Get the instance name\n */\n getInstanceName(): string {\n return this.config.instanceName;\n }\n\n /**\n * Get the operation mode\n */\n getMode(): BridgeMode {\n return this.config.mode;\n }\n\n /**\n * Get the number of connected peers\n */\n getPeerCount(): number {\n return this.peers.size;\n }\n}\n","/**\n * Peer Discovery Module\n *\n * Provides functions to discover bridge-enabled Docker containers\n * and development environment projects.\n */\n\nimport { execSync } from 'child_process';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('transport:discovery');\n\n/**\n * Discovered peer information\n */\nexport interface DiscoveredPeer {\n name: string;\n source: 'docker' | 'docksal' | 'ddev' | 'lando';\n url: string;\n containerId?: string;\n status?: string;\n}\n\n/**\n * Bridge label configuration parsed from Docker container labels\n */\nexport interface BridgeLabelConfig {\n enabled: boolean;\n port?: number;\n name?: string;\n}\n\n/**\n * Parse Docker container labels to extract bridge configuration\n *\n * @param labels - Comma-separated label string from Docker\n * @returns Parsed bridge configuration or null if bridge not enabled\n */\nexport function parseDockerLabels(labels: string): BridgeLabelConfig | null {\n if (!labels) {\n return null;\n }\n\n const labelMap: Record<string, string> = {};\n\n // Parse comma-separated labels into map\n for (const label of labels.split(',')) {\n const [key, value] = label.split('=');\n if (key && value) {\n labelMap[key.trim()] = value.trim();\n }\n }\n\n // Check if bridge is enabled\n if (labelMap['claude.bridge.enabled'] !== 'true') {\n return null;\n }\n\n return {\n enabled: true,\n port: labelMap['claude.bridge.port']\n ? parseInt(labelMap['claude.bridge.port'], 10)\n : undefined,\n name: labelMap['claude.bridge.name'],\n };\n}\n\n/**\n * Check if Docker daemon is available and running\n */\nexport function isDockerAvailable(): boolean {\n try {\n execSync('docker info', { stdio: 'pipe', timeout: 5000 });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Discover Docker containers with bridge labels\n *\n * Searches for running containers that have the claude.bridge.enabled=true label\n * and extracts connection information from their labels.\n *\n * @returns Array of discovered peers with connection URLs\n */\nexport function discoverDockerPeers(): DiscoveredPeer[] {\n const peers: DiscoveredPeer[] = [];\n\n if (!isDockerAvailable()) {\n logger.debug('Docker is not available');\n return peers;\n }\n\n try {\n // Get all running containers with their labels and ports\n const output = execSync(\n 'docker ps --format \"{{.ID}}|{{.Names}}|{{.Labels}}|{{.Status}}|{{.Ports}}\"',\n {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: 10000,\n }\n );\n\n const lines = output.trim().split('\\n').filter(Boolean);\n\n for (const line of lines) {\n const [id, names, labels, status, ports] = line.split('|');\n\n if (!id || !names) continue;\n\n const bridgeConfig = parseDockerLabels(labels);\n if (!bridgeConfig) continue;\n\n // Determine port from config or from exposed ports\n let port = bridgeConfig.port;\n if (!port && ports) {\n // Try to extract port from ports string like \"0.0.0.0:8765->8765/tcp\"\n const portMatch = ports.match(/0\\.0\\.0\\.0:(\\d+)/);\n if (portMatch) {\n port = parseInt(portMatch[1], 10);\n }\n }\n\n if (port) {\n peers.push({\n name: bridgeConfig.name || names,\n source: 'docker',\n url: `ws://localhost:${port}`,\n containerId: id,\n status: status,\n });\n\n logger.debug(\n { containerId: id, name: bridgeConfig.name || names, port },\n 'Found bridge-enabled container'\n );\n }\n }\n } catch (error) {\n logger.debug(\n { error: (error as Error).message },\n 'Failed to discover Docker peers'\n );\n }\n\n return peers;\n}\n\n/**\n * Discover Docksal projects with bridges\n *\n * Uses the `fin project list` command to find running Docksal projects.\n *\n * @returns Array of discovered peers with connection URLs\n */\nexport function discoverDocksalProjects(): DiscoveredPeer[] {\n const peers: DiscoveredPeer[] = [];\n\n try {\n // Check if fin command is available\n execSync('which fin', { stdio: 'pipe' });\n\n // List Docksal projects\n const output = execSync('fin project list 2>/dev/null || echo \"\"', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: 10000,\n });\n\n const lines = output.trim().split('\\n').filter(Boolean);\n\n for (const line of lines) {\n // Skip header lines\n if (line.includes('NAME') || line.startsWith('-')) continue;\n\n // Parse project line - format varies but typically: NAME STATUS\n const parts = line.trim().split(/\\s+/);\n const projectName = parts[0];\n const status = parts.slice(1).join(' ');\n\n if (projectName && status.toLowerCase().includes('running')) {\n // Default Docksal bridge port\n peers.push({\n name: projectName,\n source: 'docksal',\n url: `ws://${projectName}.docksal:8765`,\n status: 'running',\n });\n\n logger.debug({ projectName }, 'Found Docksal project');\n }\n }\n } catch (error) {\n logger.debug(\n { error: (error as Error).message },\n 'Docksal not available or no projects found'\n );\n }\n\n return peers;\n}\n\n/**\n * Discover DDEV projects with bridges\n *\n * Uses the `ddev list` command to find running DDEV projects.\n *\n * @returns Array of discovered peers with connection URLs\n */\nexport function discoverDdevProjects(): DiscoveredPeer[] {\n const peers: DiscoveredPeer[] = [];\n\n try {\n // Check if ddev command is available\n execSync('which ddev', { stdio: 'pipe' });\n\n // List DDEV projects in JSON format\n const output = execSync('ddev list --json-output 2>/dev/null || echo \"[]\"', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: 10000,\n });\n\n try {\n const data = JSON.parse(output);\n const projects = data.raw || [];\n\n for (const project of projects) {\n if (project.status === 'running') {\n peers.push({\n name: project.name,\n source: 'ddev',\n url: `ws://${project.name}.ddev.site:8765`,\n status: 'running',\n });\n\n logger.debug({ projectName: project.name }, 'Found DDEV project');\n }\n }\n } catch {\n // JSON parse failed, try text parsing\n logger.debug('Failed to parse DDEV JSON output, trying text parsing');\n\n const lines = output.trim().split('\\n').filter(Boolean);\n for (const line of lines) {\n if (line.includes('running')) {\n const parts = line.trim().split(/\\s+/);\n if (parts[0]) {\n peers.push({\n name: parts[0],\n source: 'ddev',\n url: `ws://${parts[0]}.ddev.site:8765`,\n status: 'running',\n });\n }\n }\n }\n }\n } catch (error) {\n logger.debug(\n { error: (error as Error).message },\n 'DDEV not available or no projects found'\n );\n }\n\n return peers;\n}\n\n/**\n * Discover Lando projects with bridges\n *\n * Uses the `lando list` command to find running Lando apps.\n *\n * @returns Array of discovered peers with connection URLs\n */\nexport function discoverLandoProjects(): DiscoveredPeer[] {\n const peers: DiscoveredPeer[] = [];\n\n try {\n // Check if lando command is available\n execSync('which lando', { stdio: 'pipe' });\n\n // List Lando apps in JSON format\n const output = execSync('lando list --format json 2>/dev/null || echo \"[]\"', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: 10000,\n });\n\n try {\n const apps = JSON.parse(output);\n\n for (const app of apps) {\n if (app.running) {\n peers.push({\n name: app.app || app.name,\n source: 'lando',\n url: `ws://localhost:8765`, // Would need to check app config for actual port\n status: 'running',\n });\n\n logger.debug({ appName: app.app || app.name }, 'Found Lando app');\n }\n }\n } catch {\n logger.debug('Failed to parse Lando JSON output');\n }\n } catch (error) {\n logger.debug(\n { error: (error as Error).message },\n 'Lando not available or no projects found'\n );\n }\n\n return peers;\n}\n\n/**\n * Discover all peers from all sources\n *\n * Aggregates peers from Docker containers and all supported development\n * environments (Docksal, DDEV, Lando).\n *\n * @returns Array of all discovered peers\n */\nexport function discoverAllPeers(): DiscoveredPeer[] {\n const allPeers: DiscoveredPeer[] = [];\n\n // Discover from all sources\n const dockerPeers = discoverDockerPeers();\n allPeers.push(...dockerPeers);\n logger.debug({ count: dockerPeers.length }, 'Docker peers discovered');\n\n const docksalPeers = discoverDocksalProjects();\n allPeers.push(...docksalPeers);\n logger.debug({ count: docksalPeers.length }, 'Docksal peers discovered');\n\n const ddevPeers = discoverDdevProjects();\n allPeers.push(...ddevPeers);\n logger.debug({ count: ddevPeers.length }, 'DDEV peers discovered');\n\n const landoPeers = discoverLandoProjects();\n allPeers.push(...landoPeers);\n logger.debug({ count: landoPeers.length }, 'Lando peers discovered');\n\n return allPeers;\n}\n","/**\n * Environment detection utilities for Claude Code Bridge\n *\n * Detects the runtime environment (Docksal, DDEV, Lando, Docker, or native)\n * and provides appropriate configuration defaults.\n */\n\nimport { existsSync } from 'fs';\nimport type { BridgeConfig } from '../utils/config.js';\n\n/**\n * Supported Docker environment types\n */\nexport type DockerEnvironment =\n | 'docksal'\n | 'ddev'\n | 'lando'\n | 'docker-compose'\n | 'docker'\n | 'native';\n\n/**\n * Information about the detected runtime environment\n */\nexport interface EnvironmentInfo {\n /** The type of environment detected */\n type: DockerEnvironment;\n /** Whether running inside a container */\n isContainer: boolean;\n /** Project name (if applicable) */\n projectName?: string;\n /** Project root path (if applicable) */\n projectRoot?: string;\n /** Host gateway address for container-to-host communication */\n hostGateway?: string;\n /** Operating system platform */\n platform: NodeJS.Platform;\n /** Additional environment-specific metadata */\n meta?: Record<string, string>;\n}\n\n/**\n * Check if running inside a Docker container\n *\n * Checks for the presence of /.dockerenv file which Docker creates\n * in all containers.\n */\nfunction isInDocker(): boolean {\n return existsSync('/.dockerenv');\n}\n\n/**\n * Check if running in a Docksal environment\n *\n * Docksal sets DOCKSAL_STACK environment variable in all CLI containers.\n */\nfunction isDocksalEnvironment(): boolean {\n return !!process.env.DOCKSAL_STACK;\n}\n\n/**\n * Check if running in a DDEV environment\n *\n * DDEV sets IS_DDEV_PROJECT=true in web containers.\n */\nfunction isDdevEnvironment(): boolean {\n return process.env.IS_DDEV_PROJECT === 'true';\n}\n\n/**\n * Check if running in a Lando environment\n *\n * Lando sets LANDO=ON in all service containers.\n */\nfunction isLandoEnvironment(): boolean {\n return process.env.LANDO === 'ON';\n}\n\n/**\n * Check if running in a docker-compose managed container\n *\n * Docker Compose sets COMPOSE_PROJECT_NAME in containers.\n */\nfunction isDockerComposeEnvironment(): boolean {\n return !!process.env.COMPOSE_PROJECT_NAME;\n}\n\n/**\n * Detect the current runtime environment\n *\n * Detection order (first match wins):\n * 1. Docksal (DOCKSAL_STACK env var)\n * 2. DDEV (IS_DDEV_PROJECT=true env var)\n * 3. Lando (LANDO=ON env var)\n * 4. Docker Compose (COMPOSE_PROJECT_NAME env var)\n * 5. Generic Docker (/.dockerenv file exists)\n * 6. Native (fallback)\n *\n * @returns EnvironmentInfo object with detected environment details\n */\nexport function detectEnvironment(): EnvironmentInfo {\n const platform = process.platform;\n const inDocker = isInDocker();\n\n // Check Docksal first (highest priority)\n if (isDocksalEnvironment()) {\n return {\n type: 'docksal',\n isContainer: true,\n projectName: process.env.DOCKSAL_PROJECT,\n projectRoot: process.env.PROJECT_ROOT,\n hostGateway: getHostGateway(),\n platform,\n meta: {\n stack: process.env.DOCKSAL_STACK || '',\n environment: process.env.DOCKSAL_ENVIRONMENT || '',\n },\n };\n }\n\n // Check DDEV\n if (isDdevEnvironment()) {\n return {\n type: 'ddev',\n isContainer: true,\n projectName: process.env.DDEV_PROJECT,\n projectRoot: process.env.DDEV_DOCROOT,\n hostGateway: getHostGateway(),\n platform,\n meta: {\n hostname: process.env.DDEV_HOSTNAME || '',\n primaryUrl: process.env.DDEV_PRIMARY_URL || '',\n },\n };\n }\n\n // Check Lando\n if (isLandoEnvironment()) {\n return {\n type: 'lando',\n isContainer: true,\n projectName: process.env.LANDO_APP_NAME,\n projectRoot: process.env.LANDO_APP_ROOT,\n hostGateway: getHostGateway(),\n platform,\n meta: {\n service: process.env.LANDO_SERVICE_NAME || '',\n type: process.env.LANDO_SERVICE_TYPE || '',\n },\n };\n }\n\n // Check Docker Compose (before generic Docker)\n if (isDockerComposeEnvironment() && inDocker) {\n return {\n type: 'docker-compose',\n isContainer: true,\n projectName: process.env.COMPOSE_PROJECT_NAME,\n hostGateway: getHostGateway(),\n platform,\n meta: {\n service: process.env.COMPOSE_SERVICE || '',\n },\n };\n }\n\n // Check generic Docker\n if (inDocker) {\n return {\n type: 'docker',\n isContainer: true,\n hostGateway: getHostGateway(),\n platform,\n };\n }\n\n // Fallback: Native environment\n return {\n type: 'native',\n isContainer: false,\n platform,\n };\n}\n\n/**\n * Get the host gateway address for container-to-host communication\n *\n * - macOS and Windows: Use host.docker.internal (provided by Docker Desktop)\n * - Linux: May need to use bridge gateway IP or host-gateway flag\n *\n * @returns The hostname or IP to reach the Docker host from inside a container\n */\nexport function getHostGateway(): string {\n // Check for explicit override via environment variable\n if (process.env.DOCKER_HOST_GATEWAY) {\n return process.env.DOCKER_HOST_GATEWAY;\n }\n\n // macOS and Windows Docker Desktop provide host.docker.internal\n if (process.platform === 'darwin' || process.platform === 'win32') {\n return 'host.docker.internal';\n }\n\n // Linux: Modern Docker (20.10+) supports host.docker.internal with --add-host\n // but it needs to be configured. Try it first, fallback to gateway IP.\n // The host-gateway special name resolves to the host's gateway IP.\n\n // Check if running in container on Linux\n if (isInDocker()) {\n // Use host.docker.internal which should work if configured properly\n // This is the recommended approach for Docker 20.10+\n return 'host.docker.internal';\n }\n\n // Native Linux - just use localhost\n return 'localhost';\n}\n\n/**\n * Get default bridge configuration based on the detected environment\n *\n * Different environments may have different port defaults or connection\n * preferences.\n *\n * @param env - The detected environment info\n * @returns Partial BridgeConfig with environment-specific defaults\n */\nexport function getDefaultConfig(env: EnvironmentInfo): Partial<BridgeConfig> {\n const baseConfig: Partial<BridgeConfig> = {\n mode: 'peer',\n instanceName: env.projectName || `${env.type}-instance`,\n };\n\n if (env.isContainer) {\n // Container environments: listen on all interfaces, connect to host\n return {\n ...baseConfig,\n listen: {\n port: 8765,\n host: '0.0.0.0',\n },\n connect: {\n url: `ws://${env.hostGateway || 'host.docker.internal'}:8766`,\n hostGateway: true,\n },\n };\n }\n\n // Native environment: listen on localhost with different port\n return {\n ...baseConfig,\n listen: {\n port: 8766,\n host: '0.0.0.0',\n },\n connect: {\n url: 'ws://localhost:8765',\n hostGateway: false,\n },\n };\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { parse as parseYaml } from 'yaml';\n\n/**\n * Configuration for the bridge's listening socket\n */\nexport interface ListenConfig {\n port: number;\n host: string;\n}\n\n/**\n * Configuration for connecting to a remote bridge\n */\nexport interface ConnectConfig {\n url?: string;\n hostGateway?: boolean;\n port?: number;\n}\n\n/**\n * Configuration for context sharing behavior\n */\nexport interface ContextSharingConfig {\n autoSync: boolean;\n syncInterval: number;\n maxChunkTokens: number;\n includePatterns: string[];\n excludePatterns: string[];\n}\n\n/**\n * Configuration for interaction behavior\n */\nexport interface InteractionConfig {\n requireConfirmation: boolean;\n notifyOnActivity: boolean;\n taskTimeout: number;\n}\n\n/**\n * Full bridge configuration\n */\nexport interface BridgeConfig {\n instanceName?: string;\n mode?: 'host' | 'client' | 'peer';\n listen: ListenConfig;\n connect?: ConnectConfig;\n contextSharing: ContextSharingConfig;\n interaction: InteractionConfig;\n}\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONFIG: BridgeConfig = {\n listen: {\n port: 8765,\n host: '0.0.0.0',\n },\n contextSharing: {\n autoSync: true,\n syncInterval: 5000,\n maxChunkTokens: 4000,\n includePatterns: ['src/**/*.ts', 'src/**/*.tsx', '*.json'],\n excludePatterns: ['node_modules/**', 'dist/**', '.git/**'],\n },\n interaction: {\n requireConfirmation: false,\n notifyOnActivity: true,\n taskTimeout: 300000, // 5 minutes\n },\n};\n\n/**\n * Deep merges a partial config with the default config\n *\n * @param partial - Partial configuration to merge\n * @returns Complete configuration with defaults for missing values\n */\nexport function mergeConfig(partial: Partial<BridgeConfig>): BridgeConfig {\n return {\n ...DEFAULT_CONFIG,\n ...partial,\n listen: {\n ...DEFAULT_CONFIG.listen,\n ...(partial.listen ?? {}),\n },\n connect: partial.connect\n ? {\n ...partial.connect,\n }\n : undefined,\n contextSharing: {\n ...DEFAULT_CONFIG.contextSharing,\n ...(partial.contextSharing ?? {}),\n },\n interaction: {\n ...DEFAULT_CONFIG.interaction,\n ...(partial.interaction ?? {}),\n },\n };\n}\n\n/**\n * Attempts to read and parse a YAML config file\n *\n * @param filePath - Path to the config file\n * @returns Parsed config or null if file doesn't exist\n */\nfunction readConfigFile(filePath: string): Partial<BridgeConfig> | null {\n try {\n if (!fs.existsSync(filePath)) {\n return null;\n }\n const content = fs.readFileSync(filePath, 'utf-8');\n const parsed = parseYaml(content);\n return parsed as Partial<BridgeConfig>;\n } catch {\n // Return null if file can't be read or parsed\n return null;\n }\n}\n\n/**\n * Gets the default config file paths to search\n *\n * @returns Array of config file paths in priority order\n */\nfunction getDefaultConfigPaths(): string[] {\n const homeDir = os.homedir();\n const cwd = process.cwd();\n\n return [\n // Project-local config takes priority\n path.join(cwd, '.claude-bridge.yml'),\n path.join(cwd, '.claude-bridge.yaml'),\n // User home config as fallback\n path.join(homeDir, '.claude-bridge', 'config.yml'),\n path.join(homeDir, '.claude-bridge', 'config.yaml'),\n ];\n}\n\n/**\n * Loads configuration from file(s) and merges with defaults\n *\n * Searches for config files in the following order:\n * 1. Explicit path (if provided)\n * 2. .claude-bridge.yml in current working directory\n * 3. ~/.claude-bridge/config.yml\n *\n * @param configPath - Optional explicit path to config file\n * @returns Complete configuration with defaults for missing values\n *\n * @example\n * ```typescript\n * // Load from default locations\n * const config = await loadConfig();\n *\n * // Load from specific path\n * const config = await loadConfig('/path/to/config.yml');\n * ```\n */\nexport async function loadConfig(configPath?: string): Promise<BridgeConfig> {\n // If explicit path provided, try to load it\n if (configPath) {\n const parsed = readConfigFile(configPath);\n if (parsed) {\n return mergeConfig(parsed);\n }\n // If explicit path doesn't exist, return defaults\n return { ...DEFAULT_CONFIG };\n }\n\n // Search default paths\n const searchPaths = getDefaultConfigPaths();\n\n for (const searchPath of searchPaths) {\n const parsed = readConfigFile(searchPath);\n if (parsed) {\n return mergeConfig(parsed);\n }\n }\n\n // No config file found, return defaults\n return { ...DEFAULT_CONFIG };\n}\n\n/**\n * Synchronous version of loadConfig for simpler usage patterns\n *\n * @param configPath - Optional explicit path to config file\n * @returns Complete configuration with defaults for missing values\n */\nexport function loadConfigSync(configPath?: string): BridgeConfig {\n // If explicit path provided, try to load it\n if (configPath) {\n const parsed = readConfigFile(configPath);\n if (parsed) {\n return mergeConfig(parsed);\n }\n // If explicit path doesn't exist, return defaults\n return { ...DEFAULT_CONFIG };\n }\n\n // Search default paths\n const searchPaths = getDefaultConfigPaths();\n\n for (const searchPath of searchPaths) {\n const parsed = readConfigFile(searchPath);\n if (parsed) {\n return mergeConfig(parsed);\n }\n }\n\n // No config file found, return defaults\n return { ...DEFAULT_CONFIG };\n}\n"],"mappings":"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","names":["ConnectionState","uuidv4","logger","uuidv4","peer","logger","existsSync","fs","path","os"]}
package/dist/cli.js CHANGED
@@ -12,7 +12,7 @@ import {
12
12
  getDefaultConfig,
13
13
  getHostGateway,
14
14
  loadConfigSync
15
- } from "./chunk-BRH476VK.js";
15
+ } from "./chunk-IMMNNIX7.js";
16
16
 
17
17
  // src/cli/index.ts
18
18
  import { Command as Command7 } from "commander";
package/dist/index.d.ts CHANGED
@@ -782,6 +782,22 @@ declare class Bridge {
782
782
  * Clean up all resources
783
783
  */
784
784
  private cleanup;
785
+ /**
786
+ * Get the status file path
787
+ */
788
+ private getStatusFilePath;
789
+ /**
790
+ * Ensure the .claude-bridge directory exists
791
+ */
792
+ private ensureBridgeDir;
793
+ /**
794
+ * Write current status to status file
795
+ */
796
+ private writeStatusFile;
797
+ /**
798
+ * Remove the status file
799
+ */
800
+ private removeStatusFile;
785
801
  /**
786
802
  * Check if the bridge is started
787
803
  */
package/dist/index.js CHANGED
@@ -37,7 +37,7 @@ import {
37
37
  safeValidateMessage,
38
38
  serializeMessage,
39
39
  validateMessage
40
- } from "./chunk-BRH476VK.js";
40
+ } from "./chunk-IMMNNIX7.js";
41
41
 
42
42
  // src/bridge/context.ts
43
43
  import { readdirSync, readFileSync, statSync, realpathSync } from "fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@willjackson/claude-code-bridge",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Bidirectional communication system for Claude Code instances across environments",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/logger.ts","../src/bridge/protocol.ts","../src/transport/interface.ts","../src/transport/websocket.ts","../src/bridge/messages.ts","../src/bridge/core.ts","../src/transport/discovery.ts","../src/environment/detect.ts","../src/utils/config.ts"],"sourcesContent":["import pino from 'pino';\n\n/**\n * Log levels supported by the logger\n */\nexport type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';\n\n/**\n * Logger interface (subset of pino.Logger for public API)\n */\nexport type Logger = pino.Logger;\n\n/**\n * Determines if we're in a development environment\n */\nfunction isDevelopment(): boolean {\n return process.env.NODE_ENV !== 'production';\n}\n\n/**\n * Gets the default log level from environment or falls back to 'info'\n */\nfunction getDefaultLevel(): LogLevel {\n const envLevel = process.env.LOG_LEVEL?.toLowerCase() as LogLevel | undefined;\n const validLevels: LogLevel[] = ['trace', 'debug', 'info', 'warn', 'error', 'fatal'];\n if (envLevel && validLevels.includes(envLevel)) {\n return envLevel;\n }\n return 'info';\n}\n\n/**\n * Creates a logger instance with the given component name\n *\n * @param name - Component name to include in log output\n * @param level - Optional log level override (defaults to LOG_LEVEL env var or 'info')\n * @returns A pino logger instance configured for the component\n *\n * @example\n * ```typescript\n * const logger = createLogger('bridge');\n * logger.info('Bridge started');\n * logger.error({ err }, 'Connection failed');\n * ```\n */\nexport function createLogger(name: string, level?: LogLevel): Logger {\n const logLevel = level ?? getDefaultLevel();\n\n const options: pino.LoggerOptions = {\n name,\n level: logLevel,\n };\n\n // Use pretty printing in development for better readability\n if (isDevelopment()) {\n options.transport = {\n target: 'pino-pretty',\n options: {\n colorize: true,\n translateTime: 'SYS:standard',\n ignore: 'pid,hostname',\n },\n };\n }\n\n return pino(options);\n}\n\n/**\n * Creates a child logger from an existing logger with additional context\n *\n * @param parent - Parent logger instance\n * @param bindings - Additional context to include in all log messages\n * @returns A child logger instance\n */\nexport function createChildLogger(parent: Logger, bindings: Record<string, unknown>): Logger {\n return parent.child(bindings);\n}\n","/**\n * Protocol definitions for Claude Code Bridge\n * Defines message types, schemas, and serialization utilities\n */\n\nimport { z } from 'zod';\nimport { v4 as uuidv4 } from 'uuid';\n\n// ============================================================================\n// Message Type Enum\n// ============================================================================\n\nexport const MessageType = z.enum([\n 'request',\n 'response',\n 'context_sync',\n 'task_delegate',\n 'notification',\n]);\n\nexport type MessageType = z.infer<typeof MessageType>;\n\n// ============================================================================\n// File and Directory Schemas\n// ============================================================================\n\nexport const FileChunkSchema = z.object({\n path: z.string(),\n content: z.string(),\n startLine: z.number().optional(),\n endLine: z.number().optional(),\n language: z.string().optional(),\n});\n\nexport type FileChunk = z.infer<typeof FileChunkSchema>;\n\nexport const DirectoryTreeSchema: z.ZodType<DirectoryTree> = z.lazy(() =>\n z.object({\n name: z.string(),\n type: z.enum(['file', 'directory']),\n children: z.array(DirectoryTreeSchema).optional(),\n })\n);\n\nexport interface DirectoryTree {\n name: string;\n type: 'file' | 'directory';\n children?: DirectoryTree[];\n}\n\n// ============================================================================\n// Artifact Schema\n// ============================================================================\n\nexport const ArtifactSchema = z.object({\n path: z.string(),\n action: z.enum(['created', 'modified', 'deleted']),\n diff: z.string().optional(),\n});\n\nexport type Artifact = z.infer<typeof ArtifactSchema>;\n\n// ============================================================================\n// Context Schema\n// ============================================================================\n\nexport const ContextSchema = z.object({\n files: z.array(FileChunkSchema).optional(),\n tree: DirectoryTreeSchema.optional(),\n summary: z.string().optional(),\n variables: z.record(z.any()).optional(),\n});\n\nexport type Context = z.infer<typeof ContextSchema>;\n\n// ============================================================================\n// Task Request Schema\n// ============================================================================\n\nexport const TaskRequestSchema = z.object({\n id: z.string(),\n description: z.string(),\n scope: z.enum(['execute', 'analyze', 'suggest']),\n constraints: z.array(z.string()).optional(),\n returnFormat: z.enum(['full', 'summary', 'diff']).optional(),\n timeout: z.number().optional(),\n});\n\nexport type TaskRequest = z.infer<typeof TaskRequestSchema>;\n\n// ============================================================================\n// Task Result Schema\n// ============================================================================\n\nexport const TaskResultSchema = z.object({\n taskId: z.string().optional(),\n success: z.boolean(),\n data: z.any(),\n artifacts: z.array(ArtifactSchema).optional(),\n followUp: z.string().optional(),\n error: z.string().optional(),\n});\n\nexport type TaskResult = z.infer<typeof TaskResultSchema>;\n\n// ============================================================================\n// Bridge Message Schema\n// ============================================================================\n\nexport const BridgeMessageSchema = z.object({\n id: z.string().uuid(),\n type: MessageType,\n source: z.string(),\n timestamp: z.number(),\n context: ContextSchema.optional(),\n task: TaskRequestSchema.optional(),\n result: TaskResultSchema.optional(),\n});\n\nexport type BridgeMessage = z.infer<typeof BridgeMessageSchema>;\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Creates a base message with auto-generated UUID and timestamp\n * @param type The message type\n * @param source The source instance identifier\n * @returns A partial BridgeMessage with id, type, source, and timestamp\n */\nexport function createMessage(\n type: MessageType,\n source: string\n): BridgeMessage {\n return {\n id: uuidv4(),\n type,\n source,\n timestamp: Date.now(),\n };\n}\n\n/**\n * Validates a message against the BridgeMessage schema\n * @param data The data to validate\n * @returns The validated BridgeMessage or throws if invalid\n */\nexport function validateMessage(data: unknown): BridgeMessage {\n return BridgeMessageSchema.parse(data);\n}\n\n/**\n * Safe validation that returns a result object instead of throwing\n * @param data The data to validate\n * @returns A Zod SafeParseReturnType with success/error information\n */\nexport function safeValidateMessage(data: unknown) {\n return BridgeMessageSchema.safeParse(data);\n}\n\n/**\n * Serializes a BridgeMessage to JSON string\n * @param message The message to serialize\n * @returns JSON string representation\n */\nexport function serializeMessage(message: BridgeMessage): string {\n return JSON.stringify(message);\n}\n\n/**\n * Deserializes a JSON string to a validated BridgeMessage\n * @param json The JSON string to deserialize\n * @returns The validated BridgeMessage\n * @throws Error if JSON is invalid or message doesn't match schema\n */\nexport function deserializeMessage(json: string): BridgeMessage {\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch {\n throw new Error('Invalid JSON');\n }\n return validateMessage(parsed);\n}\n\n/**\n * Safe deserialization that returns a result object instead of throwing\n * @param json The JSON string to deserialize\n * @returns A Zod SafeParseReturnType with success/error information\n */\nexport function safeDeserializeMessage(json: string) {\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch {\n return {\n success: false as const,\n error: new z.ZodError([\n {\n code: 'custom',\n message: 'Invalid JSON',\n path: [],\n },\n ]),\n };\n }\n return BridgeMessageSchema.safeParse(parsed);\n}\n","/**\n * Transport layer interface and types for Claude Code Bridge\n * Defines the abstract transport interface for communication between bridge instances\n */\n\nimport type { BridgeMessage } from '../bridge/protocol.js';\n\n// ============================================================================\n// Connection State Enum\n// ============================================================================\n\n/**\n * Represents the current state of a transport connection\n */\nexport enum ConnectionState {\n /** Not connected to any peer */\n DISCONNECTED = 'DISCONNECTED',\n /** Currently attempting to establish connection */\n CONNECTING = 'CONNECTING',\n /** Successfully connected and ready for communication */\n CONNECTED = 'CONNECTED',\n /** Connection lost, attempting to reconnect */\n RECONNECTING = 'RECONNECTING',\n}\n\n// ============================================================================\n// Connection Configuration\n// ============================================================================\n\n/**\n * Authentication configuration for transport connections\n */\nexport interface AuthConfig {\n /** Authentication type */\n type: 'token' | 'none';\n /** Authentication token (required if type is 'token') */\n token?: string;\n}\n\n/**\n * Configuration for establishing a transport connection\n */\nexport interface ConnectionConfig {\n /** Full WebSocket URL (e.g., ws://localhost:8765) */\n url?: string;\n /** Host to connect to (used if url is not provided) */\n host?: string;\n /** Port to connect to (used if url is not provided) */\n port?: number;\n /** Enable automatic reconnection on disconnect */\n reconnect?: boolean;\n /** Interval between reconnection attempts in milliseconds */\n reconnectInterval?: number;\n /** Maximum number of reconnection attempts before giving up */\n maxReconnectAttempts?: number;\n /** Authentication configuration */\n auth?: AuthConfig;\n}\n\n// ============================================================================\n// Event Handler Types\n// ============================================================================\n\n/**\n * Handler for incoming messages\n */\nexport type MessageHandler = (message: BridgeMessage) => void;\n\n/**\n * Handler for disconnect events\n */\nexport type DisconnectHandler = () => void;\n\n/**\n * Handler for error events\n */\nexport type ErrorHandler = (error: Error) => void;\n\n// ============================================================================\n// Transport Interface\n// ============================================================================\n\n/**\n * Abstract transport interface for bridge communication\n * Implementations handle the actual network protocol (WebSocket, TCP, etc.)\n */\nexport interface Transport {\n /**\n * Establish connection to a remote peer\n * @param config Connection configuration\n * @returns Promise that resolves when connection is established\n * @throws Error if connection fails\n */\n connect(config: ConnectionConfig): Promise<void>;\n\n /**\n * Cleanly close the current connection\n * @returns Promise that resolves when disconnection is complete\n */\n disconnect(): Promise<void>;\n\n /**\n * Send a message to the connected peer\n * @param message The message to send\n * @returns Promise that resolves when message is sent\n * @throws Error if not connected and message cannot be queued\n */\n send(message: BridgeMessage): Promise<void>;\n\n /**\n * Register a handler for incoming messages\n * @param handler Function to call when a message is received\n */\n onMessage(handler: MessageHandler): void;\n\n /**\n * Register a handler for disconnect events\n * @param handler Function to call when connection is lost\n */\n onDisconnect(handler: DisconnectHandler): void;\n\n /**\n * Register a handler for error events\n * @param handler Function to call when an error occurs\n */\n onError(handler: ErrorHandler): void;\n\n /**\n * Check if the transport is currently connected\n * @returns true if connected, false otherwise\n */\n isConnected(): boolean;\n\n /**\n * Get the current connection state\n * @returns The current ConnectionState\n */\n getState(): ConnectionState;\n}\n\n// ============================================================================\n// Transport Events (for EventEmitter pattern)\n// ============================================================================\n\n/**\n * Transport event types for EventEmitter-based implementations\n */\nexport interface TransportEvents {\n /** Emitted when a message is received */\n message: BridgeMessage;\n /** Emitted when connection is established */\n connect: void;\n /** Emitted when connection is closed */\n disconnect: void;\n /** Emitted when an error occurs */\n error: Error;\n /** Emitted when reconnection is attempted */\n reconnecting: { attempt: number; maxAttempts: number };\n}\n","/**\n * WebSocket Transport implementation for Claude Code Bridge\n * Provides WebSocket-based communication between bridge instances\n */\n\nimport WebSocket from 'ws';\nimport type { BridgeMessage } from '../bridge/protocol.js';\nimport { serializeMessage, safeDeserializeMessage } from '../bridge/protocol.js';\nimport {\n ConnectionState,\n type ConnectionConfig,\n type Transport,\n type MessageHandler,\n type DisconnectHandler,\n type ErrorHandler,\n} from './interface.js';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('websocket-transport');\n\n/** Default reconnection interval in milliseconds */\nconst DEFAULT_RECONNECT_INTERVAL = 1000;\n\n/** Default maximum reconnection attempts */\nconst DEFAULT_MAX_RECONNECT_ATTEMPTS = 10;\n\n/** Default heartbeat interval in milliseconds */\nconst DEFAULT_HEARTBEAT_INTERVAL = 30000;\n\n/** Heartbeat timeout - how long to wait for pong response */\nconst HEARTBEAT_TIMEOUT = 10000;\n\n/**\n * WebSocket-based transport implementation\n * Handles connection lifecycle, message sending/receiving, and event handling\n * Supports auto-reconnection, message queuing, and heartbeat monitoring\n */\nexport class WebSocketTransport implements Transport {\n private ws: WebSocket | null = null;\n private state: ConnectionState = ConnectionState.DISCONNECTED;\n private config: ConnectionConfig | null = null;\n\n // Reconnection state\n private reconnectAttempts: number = 0;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private intentionalDisconnect: boolean = false;\n\n // Message queue for offline messages\n private messageQueue: BridgeMessage[] = [];\n\n // Heartbeat state\n private heartbeatInterval: ReturnType<typeof setInterval> | null = null;\n private heartbeatTimeout: ReturnType<typeof setTimeout> | null = null;\n private awaitingPong: boolean = false;\n\n // Event handlers\n private messageHandlers: MessageHandler[] = [];\n private disconnectHandlers: DisconnectHandler[] = [];\n private errorHandlers: ErrorHandler[] = [];\n private reconnectingHandlers: Array<(attempt: number, maxAttempts: number) => void> = [];\n\n /**\n * Build the WebSocket URL from the connection configuration\n */\n private buildUrl(config: ConnectionConfig): string {\n if (config.url) {\n return config.url;\n }\n\n const host = config.host ?? 'localhost';\n const port = config.port ?? 8765;\n return `ws://${host}:${port}`;\n }\n\n /**\n * Establish connection to a remote peer\n */\n async connect(config: ConnectionConfig): Promise<void> {\n if (this.state === ConnectionState.CONNECTED) {\n throw new Error('Already connected');\n }\n\n this.config = config;\n this.intentionalDisconnect = false;\n this.reconnectAttempts = 0;\n\n return this.establishConnection();\n }\n\n /**\n * Internal method to establish WebSocket connection\n * Used for both initial connection and reconnection attempts\n */\n private async establishConnection(): Promise<void> {\n if (!this.config) {\n throw new Error('No configuration set');\n }\n\n this.state = ConnectionState.CONNECTING;\n\n const url = this.buildUrl(this.config);\n logger.debug({ url, attempt: this.reconnectAttempts }, 'Connecting to WebSocket server');\n\n return new Promise<void>((resolve, reject) => {\n try {\n this.ws = new WebSocket(url);\n\n // Handle connection open\n this.ws.on('open', () => {\n this.state = ConnectionState.CONNECTED;\n this.reconnectAttempts = 0;\n logger.info({ url }, 'WebSocket connection established');\n\n // Start heartbeat monitoring\n this.startHeartbeat();\n\n // Flush queued messages\n this.flushMessageQueue();\n\n resolve();\n });\n\n // Handle incoming messages\n this.ws.on('message', (data: WebSocket.RawData) => {\n this.handleIncomingMessage(data);\n });\n\n // Handle pong responses for heartbeat\n this.ws.on('pong', () => {\n this.handlePong();\n });\n\n // Handle connection close\n this.ws.on('close', (code, reason) => {\n const wasConnected = this.state === ConnectionState.CONNECTED;\n const wasReconnecting = this.state === ConnectionState.RECONNECTING;\n\n // Stop heartbeat\n this.stopHeartbeat();\n\n logger.info({ code, reason: reason.toString() }, 'WebSocket connection closed');\n\n // Notify disconnect handlers only if we were previously connected\n if (wasConnected) {\n this.notifyDisconnect();\n }\n\n // Attempt reconnection if enabled and not intentional disconnect\n if (!this.intentionalDisconnect && this.shouldReconnect()) {\n this.scheduleReconnect();\n } else if (!wasReconnecting) {\n this.state = ConnectionState.DISCONNECTED;\n }\n });\n\n // Handle errors\n this.ws.on('error', (error: Error) => {\n logger.error({ error: error.message }, 'WebSocket error');\n\n // If we're still connecting (initial connection), reject the promise\n if (this.state === ConnectionState.CONNECTING && this.reconnectAttempts === 0) {\n this.state = ConnectionState.DISCONNECTED;\n reject(error);\n return;\n }\n\n // Notify error handlers\n this.notifyError(error);\n });\n } catch (error) {\n this.state = ConnectionState.DISCONNECTED;\n reject(error);\n }\n });\n }\n\n /**\n * Cleanly close the current connection\n */\n async disconnect(): Promise<void> {\n // Mark as intentional to prevent reconnection\n this.intentionalDisconnect = true;\n\n // Clear any pending reconnection timer\n this.clearReconnectTimer();\n\n // Stop heartbeat\n this.stopHeartbeat();\n\n // Clear message queue on intentional disconnect\n this.messageQueue = [];\n\n if (!this.ws || this.state === ConnectionState.DISCONNECTED) {\n this.state = ConnectionState.DISCONNECTED;\n return;\n }\n\n logger.debug('Disconnecting WebSocket');\n\n return new Promise<void>((resolve) => {\n if (!this.ws) {\n this.state = ConnectionState.DISCONNECTED;\n resolve();\n return;\n }\n\n // Set up close handler before closing\n const onClose = () => {\n this.state = ConnectionState.DISCONNECTED;\n this.ws = null;\n resolve();\n };\n\n // If already closed, resolve immediately\n if (this.ws.readyState === WebSocket.CLOSED) {\n onClose();\n return;\n }\n\n // Set up timeout in case close doesn't happen\n const timeout = setTimeout(() => {\n this.state = ConnectionState.DISCONNECTED;\n this.ws = null;\n resolve();\n }, 5000);\n\n this.ws.once('close', () => {\n clearTimeout(timeout);\n onClose();\n });\n\n // Initiate close\n this.ws.close(1000, 'Disconnect requested');\n });\n }\n\n /**\n * Send a message to the connected peer\n * If disconnected and reconnection is enabled, queues the message for later delivery\n */\n async send(message: BridgeMessage): Promise<void> {\n // If connected, send immediately\n if (this.ws && this.state === ConnectionState.CONNECTED) {\n return this.sendImmediate(message);\n }\n\n // If reconnecting and reconnection is enabled, queue the message\n if (this.shouldReconnect() && (this.state === ConnectionState.RECONNECTING || this.state === ConnectionState.DISCONNECTED)) {\n this.queueMessage(message);\n return;\n }\n\n throw new Error('Not connected');\n }\n\n /**\n * Immediately send a message over the WebSocket\n */\n private async sendImmediate(message: BridgeMessage): Promise<void> {\n if (!this.ws || this.state !== ConnectionState.CONNECTED) {\n throw new Error('Not connected');\n }\n\n const serialized = serializeMessage(message);\n logger.debug({ messageId: message.id, type: message.type }, 'Sending message');\n\n return new Promise<void>((resolve, reject) => {\n this.ws!.send(serialized, (error) => {\n if (error) {\n logger.error({ error: error.message, messageId: message.id }, 'Failed to send message');\n reject(error);\n } else {\n resolve();\n }\n });\n });\n }\n\n /**\n * Queue a message for later delivery when reconnected\n */\n private queueMessage(message: BridgeMessage): void {\n this.messageQueue.push(message);\n logger.debug({ messageId: message.id, queueLength: this.messageQueue.length }, 'Message queued for delivery');\n }\n\n /**\n * Flush all queued messages after reconnection\n */\n private async flushMessageQueue(): Promise<void> {\n if (this.messageQueue.length === 0) {\n return;\n }\n\n logger.info({ queueLength: this.messageQueue.length }, 'Flushing message queue');\n\n const messages = [...this.messageQueue];\n this.messageQueue = [];\n\n for (const message of messages) {\n try {\n await this.sendImmediate(message);\n } catch (error) {\n logger.error({ error: (error as Error).message, messageId: message.id }, 'Failed to send queued message');\n // Re-queue the failed message\n this.messageQueue.unshift(message);\n break;\n }\n }\n }\n\n /**\n * Register a handler for incoming messages\n */\n onMessage(handler: MessageHandler): void {\n this.messageHandlers.push(handler);\n }\n\n /**\n * Register a handler for disconnect events\n */\n onDisconnect(handler: DisconnectHandler): void {\n this.disconnectHandlers.push(handler);\n }\n\n /**\n * Register a handler for error events\n */\n onError(handler: ErrorHandler): void {\n this.errorHandlers.push(handler);\n }\n\n /**\n * Register a handler for reconnecting events\n */\n onReconnecting(handler: (attempt: number, maxAttempts: number) => void): void {\n this.reconnectingHandlers.push(handler);\n }\n\n /**\n * Check if the transport is currently connected\n */\n isConnected(): boolean {\n return this.state === ConnectionState.CONNECTED;\n }\n\n /**\n * Get the current connection state\n */\n getState(): ConnectionState {\n return this.state;\n }\n\n /**\n * Handle incoming WebSocket messages\n */\n private handleIncomingMessage(data: WebSocket.RawData): void {\n const messageString = data.toString();\n logger.debug({ dataLength: messageString.length }, 'Received message');\n\n const result = safeDeserializeMessage(messageString);\n\n if (!result.success) {\n logger.warn({ error: result.error.message }, 'Failed to parse incoming message');\n this.notifyError(new Error(`Invalid message format: ${result.error.message}`));\n return;\n }\n\n const message = result.data;\n logger.debug({ messageId: message.id, type: message.type }, 'Parsed message');\n\n // Notify all message handlers\n for (const handler of this.messageHandlers) {\n try {\n handler(message);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Message handler threw error');\n }\n }\n }\n\n /**\n * Notify all disconnect handlers\n */\n private notifyDisconnect(): void {\n for (const handler of this.disconnectHandlers) {\n try {\n handler();\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Disconnect handler threw error');\n }\n }\n }\n\n /**\n * Notify all error handlers\n */\n private notifyError(error: Error): void {\n for (const handler of this.errorHandlers) {\n try {\n handler(error);\n } catch (handlerError) {\n logger.error({ error: (handlerError as Error).message }, 'Error handler threw error');\n }\n }\n }\n\n /**\n * Notify all reconnecting handlers\n */\n private notifyReconnecting(attempt: number, maxAttempts: number): void {\n for (const handler of this.reconnectingHandlers) {\n try {\n handler(attempt, maxAttempts);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Reconnecting handler threw error');\n }\n }\n }\n\n // ============================================================================\n // Reconnection Methods\n // ============================================================================\n\n /**\n * Check if reconnection should be attempted\n */\n private shouldReconnect(): boolean {\n if (!this.config?.reconnect) {\n return false;\n }\n\n const maxAttempts = this.config.maxReconnectAttempts ?? DEFAULT_MAX_RECONNECT_ATTEMPTS;\n return this.reconnectAttempts < maxAttempts;\n }\n\n /**\n * Schedule a reconnection attempt\n */\n private scheduleReconnect(): void {\n if (this.reconnectTimer) {\n return; // Already scheduled\n }\n\n this.state = ConnectionState.RECONNECTING;\n this.reconnectAttempts++;\n\n const maxAttempts = this.config?.maxReconnectAttempts ?? DEFAULT_MAX_RECONNECT_ATTEMPTS;\n const interval = this.config?.reconnectInterval ?? DEFAULT_RECONNECT_INTERVAL;\n\n logger.info(\n { attempt: this.reconnectAttempts, maxAttempts, interval },\n 'Scheduling reconnection attempt'\n );\n\n // Notify reconnecting handlers\n this.notifyReconnecting(this.reconnectAttempts, maxAttempts);\n\n this.reconnectTimer = setTimeout(async () => {\n this.reconnectTimer = null;\n\n try {\n await this.establishConnection();\n logger.info({ attempts: this.reconnectAttempts }, 'Reconnection successful');\n } catch (error) {\n logger.warn({ error: (error as Error).message }, 'Reconnection attempt failed');\n\n // Schedule another attempt if we haven't reached the limit\n if (this.shouldReconnect()) {\n this.scheduleReconnect();\n } else {\n logger.error({ maxAttempts }, 'Max reconnection attempts reached, giving up');\n this.state = ConnectionState.DISCONNECTED;\n this.notifyError(new Error(`Failed to reconnect after ${maxAttempts} attempts`));\n }\n }\n }, interval);\n }\n\n /**\n * Clear any pending reconnection timer\n */\n private clearReconnectTimer(): void {\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n }\n\n // ============================================================================\n // Heartbeat Methods\n // ============================================================================\n\n /**\n * Start the heartbeat monitoring\n */\n private startHeartbeat(): void {\n this.stopHeartbeat(); // Clear any existing heartbeat\n\n this.heartbeatInterval = setInterval(() => {\n this.sendPing();\n }, DEFAULT_HEARTBEAT_INTERVAL);\n\n logger.debug({ interval: DEFAULT_HEARTBEAT_INTERVAL }, 'Heartbeat monitoring started');\n }\n\n /**\n * Stop the heartbeat monitoring\n */\n private stopHeartbeat(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n this.heartbeatInterval = null;\n }\n\n if (this.heartbeatTimeout) {\n clearTimeout(this.heartbeatTimeout);\n this.heartbeatTimeout = null;\n }\n\n this.awaitingPong = false;\n }\n\n /**\n * Send a ping to the peer\n */\n private sendPing(): void {\n if (!this.ws || this.state !== ConnectionState.CONNECTED) {\n return;\n }\n\n if (this.awaitingPong) {\n // We didn't receive a pong for the previous ping - connection may be dead\n logger.warn('No pong received, connection may be dead');\n this.handleHeartbeatTimeout();\n return;\n }\n\n this.awaitingPong = true;\n this.ws.ping();\n\n // Set timeout for pong response\n this.heartbeatTimeout = setTimeout(() => {\n if (this.awaitingPong) {\n this.handleHeartbeatTimeout();\n }\n }, HEARTBEAT_TIMEOUT);\n\n logger.debug('Ping sent');\n }\n\n /**\n * Handle pong response from peer\n */\n private handlePong(): void {\n this.awaitingPong = false;\n\n if (this.heartbeatTimeout) {\n clearTimeout(this.heartbeatTimeout);\n this.heartbeatTimeout = null;\n }\n\n logger.debug('Pong received');\n }\n\n /**\n * Handle heartbeat timeout (no pong received)\n */\n private handleHeartbeatTimeout(): void {\n logger.warn('Heartbeat timeout - closing connection');\n this.awaitingPong = false;\n\n if (this.heartbeatTimeout) {\n clearTimeout(this.heartbeatTimeout);\n this.heartbeatTimeout = null;\n }\n\n // Close the connection to trigger reconnection if enabled\n if (this.ws) {\n this.ws.terminate();\n }\n }\n\n // ============================================================================\n // Getters for testing/debugging\n // ============================================================================\n\n /**\n * Get the current message queue length (for testing)\n */\n getQueueLength(): number {\n return this.messageQueue.length;\n }\n\n /**\n * Get the number of reconnection attempts (for testing)\n */\n getReconnectAttempts(): number {\n return this.reconnectAttempts;\n }\n}\n","/**\n * Message builder factory functions for Claude Code Bridge\n * Provides convenient functions to create specific message types\n */\n\nimport { createMessage, type BridgeMessage, type Context, type TaskRequest, type TaskResult } from './protocol.js';\n\n/**\n * Notification data structure for notification messages\n */\nexport interface NotificationData {\n type: string;\n message: string;\n data?: Record<string, unknown>;\n}\n\n/**\n * Creates a context synchronization message\n * Used to share context (files, tree, summary) with a peer\n * @param source The source instance identifier\n * @param context The context to synchronize\n * @returns A BridgeMessage with type 'context_sync'\n */\nexport function createContextSyncMessage(\n source: string,\n context: Context\n): BridgeMessage {\n const message = createMessage('context_sync', source);\n return {\n ...message,\n context,\n };\n}\n\n/**\n * Creates a task delegation message\n * Used to delegate a task to a peer instance\n * @param source The source instance identifier\n * @param task The task to delegate\n * @returns A BridgeMessage with type 'task_delegate'\n */\nexport function createTaskDelegateMessage(\n source: string,\n task: TaskRequest\n): BridgeMessage {\n const message = createMessage('task_delegate', source);\n return {\n ...message,\n task,\n };\n}\n\n/**\n * Creates a task response message\n * Used to respond to a delegated task\n * @param source The source instance identifier\n * @param taskId The ID of the task being responded to\n * @param result The result of the task execution\n * @returns A BridgeMessage with type 'response'\n */\nexport function createTaskResponseMessage(\n source: string,\n taskId: string,\n result: Omit<TaskResult, 'taskId'>\n): BridgeMessage {\n const message = createMessage('response', source);\n return {\n ...message,\n result: {\n ...result,\n taskId,\n },\n };\n}\n\n/**\n * Creates a context request message\n * Used to request specific context from a peer\n * @param source The source instance identifier\n * @param query A description of what context is being requested\n * @returns A BridgeMessage with type 'request'\n */\nexport function createContextRequestMessage(\n source: string,\n query: string\n): BridgeMessage {\n const message = createMessage('request', source);\n return {\n ...message,\n context: {\n summary: query,\n },\n };\n}\n\n/**\n * Creates a notification message\n * Used to send notifications to peers (events, status updates, etc.)\n * @param source The source instance identifier\n * @param notification The notification data\n * @returns A BridgeMessage with type 'notification'\n */\nexport function createNotificationMessage(\n source: string,\n notification: NotificationData\n): BridgeMessage {\n const message = createMessage('notification', source);\n return {\n ...message,\n context: {\n summary: notification.message,\n variables: {\n notificationType: notification.type,\n ...notification.data,\n },\n },\n };\n}\n","/**\n * Bridge Core - Main orchestration class for Claude Code Bridge\n * Handles peer connections, message routing, and lifecycle management\n */\n\nimport { WebSocketServer, WebSocket as WsWebSocket } from 'ws';\nimport { v4 as uuidv4 } from 'uuid';\nimport { createLogger } from '../utils/logger.js';\nimport { WebSocketTransport } from '../transport/websocket.js';\nimport { ConnectionState, type Transport } from '../transport/interface.js';\nimport {\n type BridgeMessage,\n type TaskRequest,\n type TaskResult,\n type Context,\n type FileChunk,\n safeDeserializeMessage,\n serializeMessage,\n} from './protocol.js';\nimport {\n createTaskDelegateMessage,\n createTaskResponseMessage,\n createContextSyncMessage,\n createContextRequestMessage,\n} from './messages.js';\n\nconst logger = createLogger('bridge');\n\n// ============================================================================\n// Type Definitions\n// ============================================================================\n\n/**\n * Bridge operation mode\n * - 'host': Listen for incoming connections only\n * - 'client': Connect to a remote bridge only\n * - 'peer': Both listen and connect (bidirectional)\n */\nexport type BridgeMode = 'host' | 'client' | 'peer';\n\n/**\n * Configuration for the bridge's listening server\n */\nexport interface BridgeListenConfig {\n /** Port to listen on */\n port: number;\n /** Host to bind to (default: 0.0.0.0) */\n host?: string;\n}\n\n/**\n * Configuration for connecting to a remote bridge\n */\nexport interface BridgeConnectConfig {\n /** Full WebSocket URL (e.g., ws://localhost:8765) */\n url?: string;\n /** Use host.docker.internal for container-to-host connection */\n hostGateway?: boolean;\n /** Port to connect to (used if url is not provided) */\n port?: number;\n}\n\n/**\n * Context sharing configuration\n */\nexport interface ContextSharingConfig {\n /** Enable automatic context synchronization */\n autoSync?: boolean;\n /** Interval in milliseconds for auto-sync (default: 5000) */\n syncInterval?: number;\n}\n\n/**\n * Full configuration for Bridge initialization\n */\nexport interface BridgeConfig {\n /** Operation mode: 'host', 'client', or 'peer' */\n mode: BridgeMode;\n /** Unique identifier for this bridge instance */\n instanceName: string;\n /** Server configuration (required for 'host' and 'peer' modes) */\n listen?: BridgeListenConfig;\n /** Connection configuration (required for 'client' and 'peer' modes) */\n connect?: BridgeConnectConfig;\n /** Task timeout in milliseconds (default: 300000 / 5 minutes) */\n taskTimeout?: number;\n /** Context sharing configuration */\n contextSharing?: ContextSharingConfig;\n}\n\n/**\n * Information about a connected peer\n */\nexport interface PeerInfo {\n /** Unique identifier for the peer connection */\n id: string;\n /** Name of the peer instance */\n name: string;\n /** Environment type of the peer */\n environment?: string;\n /** Timestamp when the peer connected */\n connectedAt: number;\n /** Timestamp of last activity from the peer */\n lastActivity: number;\n}\n\n/**\n * Internal peer connection tracking\n */\ninterface PeerConnection {\n /** Peer information */\n info: PeerInfo;\n /** WebSocket connection (for server-side connections) */\n ws?: WsWebSocket;\n /** Transport instance (for client-side connections) */\n transport?: Transport;\n}\n\n/**\n * Handler for peer connection events\n */\nexport type PeerConnectedHandler = (peer: PeerInfo) => void;\n\n/**\n * Handler for peer disconnection events\n */\nexport type PeerDisconnectedHandler = (peer: PeerInfo) => void;\n\n/**\n * Handler for incoming messages from peers\n */\nexport type MessageReceivedHandler = (message: BridgeMessage, peerId: string) => void;\n\n/**\n * Handler for incoming task delegation requests\n * Returns a TaskResult or Promise<TaskResult>\n */\nexport type TaskReceivedHandler = (task: TaskRequest, peerId: string) => TaskResult | Promise<TaskResult>;\n\n/**\n * Handler for incoming context synchronization\n */\nexport type ContextReceivedHandler = (context: Context, peerId: string) => void;\n\n/**\n * Handler for incoming context requests\n * Returns FileChunk[] or Promise<FileChunk[]>\n */\nexport type ContextRequestedHandler = (query: string, peerId: string) => FileChunk[] | Promise<FileChunk[]>;\n\n/**\n * Pending task tracking for response correlation\n */\ninterface PendingTask {\n taskId: string;\n peerId: string;\n resolve: (result: TaskResult) => void;\n reject: (error: Error) => void;\n timeoutId: ReturnType<typeof setTimeout>;\n}\n\n/**\n * Pending context request tracking for response correlation\n */\ninterface PendingContextRequest {\n requestId: string;\n peerId: string;\n resolve: (chunks: FileChunk[]) => void;\n reject: (error: Error) => void;\n timeoutId: ReturnType<typeof setTimeout>;\n}\n\n// ============================================================================\n// Bridge Class\n// ============================================================================\n\n/**\n * Main Bridge class for managing peer-to-peer communication\n * Supports three modes of operation:\n * - 'host': Acts as a server, accepting incoming connections\n * - 'client': Acts as a client, connecting to a remote server\n * - 'peer': Both listens for connections and connects to a remote peer\n */\nexport class Bridge {\n private config: BridgeConfig;\n private server: WebSocketServer | null = null;\n private clientTransport: WebSocketTransport | null = null;\n private peers: Map<string, PeerConnection> = new Map();\n private started: boolean = false;\n\n // Event handlers\n private peerConnectedHandlers: PeerConnectedHandler[] = [];\n private peerDisconnectedHandlers: PeerDisconnectedHandler[] = [];\n private messageReceivedHandlers: MessageReceivedHandler[] = [];\n private taskReceivedHandler: TaskReceivedHandler | null = null;\n private contextReceivedHandlers: ContextReceivedHandler[] = [];\n private contextRequestedHandler: ContextRequestedHandler | null = null;\n\n // Task correlation\n private pendingTasks: Map<string, PendingTask> = new Map();\n\n // Context request correlation\n private pendingContextRequests: Map<string, PendingContextRequest> = new Map();\n\n // Auto-sync interval timer\n private autoSyncIntervalId: ReturnType<typeof setInterval> | null = null;\n\n /**\n * Create a new Bridge instance\n * @param config Bridge configuration\n */\n constructor(config: BridgeConfig) {\n this.config = config;\n this.validateConfig();\n logger.info({ instanceName: config.instanceName, mode: config.mode }, 'Bridge instance created');\n }\n\n /**\n * Validate the configuration based on mode requirements\n */\n private validateConfig(): void {\n const { mode, listen, connect } = this.config;\n\n if (mode === 'host' && !listen) {\n throw new Error(\"'host' mode requires 'listen' configuration\");\n }\n\n if (mode === 'client' && !connect) {\n throw new Error(\"'client' mode requires 'connect' configuration\");\n }\n\n if (mode === 'peer' && !listen && !connect) {\n throw new Error(\"'peer' mode requires either 'listen' or 'connect' configuration (or both)\");\n }\n }\n\n /**\n * Start the bridge based on configured mode\n * - 'host': Starts WebSocket server\n * - 'client': Connects to remote bridge\n * - 'peer': Both starts server and connects to remote\n */\n async start(): Promise<void> {\n if (this.started) {\n throw new Error('Bridge is already started');\n }\n\n const { mode } = this.config;\n logger.info({ mode }, 'Starting bridge');\n\n try {\n // Start server if in host or peer mode\n if ((mode === 'host' || mode === 'peer') && this.config.listen) {\n await this.startServer();\n }\n\n // Connect to remote if in client or peer mode\n if ((mode === 'client' || mode === 'peer') && this.config.connect) {\n await this.connectToRemote();\n }\n\n this.started = true;\n logger.info({ mode, instanceName: this.config.instanceName }, 'Bridge started successfully');\n } catch (error) {\n // Cleanup on failure\n await this.cleanup();\n throw error;\n }\n }\n\n /**\n * Stop the bridge and close all connections\n */\n async stop(): Promise<void> {\n if (!this.started) {\n return;\n }\n\n logger.info('Stopping bridge');\n await this.cleanup();\n this.started = false;\n logger.info('Bridge stopped');\n }\n\n /**\n * Get list of connected peers\n */\n getPeers(): PeerInfo[] {\n return Array.from(this.peers.values()).map(p => p.info);\n }\n\n /**\n * Connect to a remote bridge\n * @param url WebSocket URL to connect to\n */\n async connectToPeer(url: string): Promise<void> {\n const transport = new WebSocketTransport();\n\n // Set up message handler\n transport.onMessage((message) => {\n this.handleMessage(message, transport);\n });\n\n // Set up disconnect handler\n transport.onDisconnect(() => {\n this.handleClientDisconnect(transport);\n });\n\n try {\n await transport.connect({\n url,\n reconnect: true,\n reconnectInterval: 1000,\n maxReconnectAttempts: 10,\n });\n\n // Create peer info for the connected remote\n const peerId = uuidv4();\n const peerInfo: PeerInfo = {\n id: peerId,\n name: 'remote', // Will be updated when we receive peer info\n connectedAt: Date.now(),\n lastActivity: Date.now(),\n };\n\n this.peers.set(peerId, {\n info: peerInfo,\n transport,\n });\n\n // Store peerId on transport for lookup\n (transport as WebSocketTransport & { _peerId?: string })._peerId = peerId;\n\n this.notifyPeerConnected(peerInfo);\n logger.info({ peerId, url }, 'Connected to remote peer');\n } catch (error) {\n logger.error({ error: (error as Error).message, url }, 'Failed to connect to remote peer');\n throw error;\n }\n }\n\n /**\n * Disconnect from a specific peer\n * @param peerId ID of the peer to disconnect from\n */\n async disconnectFromPeer(peerId: string): Promise<void> {\n const peer = this.peers.get(peerId);\n if (!peer) {\n throw new Error(`Peer not found: ${peerId}`);\n }\n\n if (peer.transport) {\n await peer.transport.disconnect();\n }\n\n if (peer.ws) {\n peer.ws.close(1000, 'Disconnect requested');\n }\n\n this.peers.delete(peerId);\n this.notifyPeerDisconnected(peer.info);\n logger.info({ peerId }, 'Disconnected from peer');\n }\n\n /**\n * Send a message to a specific peer\n * @param peerId ID of the peer to send to\n * @param message Message to send\n */\n async sendToPeer(peerId: string, message: BridgeMessage): Promise<void> {\n const peer = this.peers.get(peerId);\n if (!peer) {\n throw new Error(`Peer not found: ${peerId}`);\n }\n\n if (peer.transport) {\n await peer.transport.send(message);\n } else if (peer.ws) {\n const serialized = serializeMessage(message);\n await new Promise<void>((resolve, reject) => {\n peer.ws!.send(serialized, (error) => {\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n });\n } else {\n throw new Error('No transport available for peer');\n }\n\n logger.debug({ peerId, messageId: message.id, type: message.type }, 'Sent message to peer');\n }\n\n /**\n * Broadcast a message to all connected peers\n * @param message Message to broadcast\n */\n async broadcast(message: BridgeMessage): Promise<void> {\n const sendPromises = Array.from(this.peers.keys()).map(peerId =>\n this.sendToPeer(peerId, message).catch(error => {\n logger.error({ error: (error as Error).message, peerId }, 'Failed to send to peer');\n })\n );\n\n await Promise.all(sendPromises);\n logger.debug({ messageId: message.id, peerCount: this.peers.size }, 'Broadcast message sent');\n }\n\n // ============================================================================\n // Event Registration\n // ============================================================================\n\n /**\n * Register a handler for peer connection events\n */\n onPeerConnected(handler: PeerConnectedHandler): void {\n this.peerConnectedHandlers.push(handler);\n }\n\n /**\n * Register a handler for peer disconnection events\n */\n onPeerDisconnected(handler: PeerDisconnectedHandler): void {\n this.peerDisconnectedHandlers.push(handler);\n }\n\n /**\n * Register a handler for incoming messages\n */\n onMessage(handler: MessageReceivedHandler): void {\n this.messageReceivedHandlers.push(handler);\n }\n\n /**\n * Register a handler for incoming task delegation requests\n * Only one handler can be registered at a time\n * @param handler Function that receives a TaskRequest and returns a TaskResult\n */\n onTaskReceived(handler: TaskReceivedHandler): void {\n this.taskReceivedHandler = handler;\n }\n\n /**\n * Register a handler for incoming context synchronization\n * Multiple handlers can be registered\n * @param handler Function that receives context and peerId\n */\n onContextReceived(handler: ContextReceivedHandler): void {\n this.contextReceivedHandlers.push(handler);\n }\n\n /**\n * Register a handler for incoming context requests\n * Only one handler can be registered at a time\n * @param handler Function that receives a query and returns FileChunk[]\n */\n onContextRequested(handler: ContextRequestedHandler): void {\n this.contextRequestedHandler = handler;\n }\n\n // ============================================================================\n // Task Delegation\n // ============================================================================\n\n /**\n * Delegate a task to a peer and wait for the result\n * @param task The task request to delegate\n * @param peerId Optional peer ID to send to (defaults to first peer)\n * @returns Promise that resolves with the task result\n * @throws Error if no peers are connected or task times out\n */\n async delegateTask(task: TaskRequest, peerId?: string): Promise<TaskResult> {\n // Get target peer\n if (!peerId) {\n const peers = this.getPeers();\n if (peers.length === 0) {\n throw new Error('No peers connected to delegate task to');\n }\n peerId = peers[0].id;\n }\n\n // Validate peer exists\n if (!this.peers.has(peerId)) {\n throw new Error(`Peer not found: ${peerId}`);\n }\n\n // Determine timeout\n const timeout = task.timeout ?? this.config.taskTimeout ?? 300000; // Default 5 minutes\n\n // Create promise to track task completion\n return new Promise<TaskResult>((resolve, reject) => {\n // Create the task delegate message\n const message = createTaskDelegateMessage(this.config.instanceName, task);\n\n // Set up timeout\n const timeoutId = setTimeout(() => {\n const pending = this.pendingTasks.get(task.id);\n if (pending) {\n this.pendingTasks.delete(task.id);\n reject(new Error(`Task '${task.id}' timed out after ${timeout}ms`));\n }\n }, timeout);\n\n // Store pending task for correlation\n this.pendingTasks.set(task.id, {\n taskId: task.id,\n peerId,\n resolve,\n reject,\n timeoutId,\n });\n\n // Send the task\n this.sendToPeer(peerId, message).catch((error) => {\n // Clean up on send error\n clearTimeout(timeoutId);\n this.pendingTasks.delete(task.id);\n reject(error);\n });\n\n logger.debug({ taskId: task.id, peerId, timeout }, 'Task delegated');\n });\n }\n\n // ============================================================================\n // Context Synchronization\n // ============================================================================\n\n /**\n * Synchronize context with connected peers\n * @param context Optional context to sync. If not provided, broadcasts to all peers\n * @param peerId Optional peer ID to send to (defaults to all peers)\n */\n async syncContext(context?: Context, peerId?: string): Promise<void> {\n // Use empty context if not provided\n const contextToSync = context ?? {};\n\n // Create the context sync message\n const message = createContextSyncMessage(this.config.instanceName, contextToSync);\n\n if (peerId) {\n // Send to specific peer\n await this.sendToPeer(peerId, message);\n logger.debug({ peerId, messageId: message.id }, 'Context synced to peer');\n } else {\n // Broadcast to all peers\n await this.broadcast(message);\n logger.debug({ peerCount: this.peers.size, messageId: message.id }, 'Context synced to all peers');\n }\n }\n\n /**\n * Request context from a peer based on a query\n * @param query Description of what context is being requested\n * @param peerId Optional peer ID to request from (defaults to first peer)\n * @param timeout Optional timeout in milliseconds (default: 30000)\n * @returns Promise that resolves with FileChunk[] from the peer\n * @throws Error if no peers are connected or request times out\n */\n async requestContext(query: string, peerId?: string, timeout: number = 30000): Promise<FileChunk[]> {\n // Get target peer\n if (!peerId) {\n const peers = this.getPeers();\n if (peers.length === 0) {\n throw new Error('No peers connected to request context from');\n }\n peerId = peers[0].id;\n }\n\n // Validate peer exists\n if (!this.peers.has(peerId)) {\n throw new Error(`Peer not found: ${peerId}`);\n }\n\n // Create promise to track request completion\n return new Promise<FileChunk[]>((resolve, reject) => {\n // Create the context request message\n const message = createContextRequestMessage(this.config.instanceName, query);\n\n // Set up timeout\n const timeoutId = setTimeout(() => {\n const pending = this.pendingContextRequests.get(message.id);\n if (pending) {\n this.pendingContextRequests.delete(message.id);\n reject(new Error(`Context request timed out after ${timeout}ms`));\n }\n }, timeout);\n\n // Store pending request for correlation\n this.pendingContextRequests.set(message.id, {\n requestId: message.id,\n peerId,\n resolve,\n reject,\n timeoutId,\n });\n\n // Send the request\n this.sendToPeer(peerId, message).catch((error) => {\n // Clean up on send error\n clearTimeout(timeoutId);\n this.pendingContextRequests.delete(message.id);\n reject(error);\n });\n\n logger.debug({ requestId: message.id, peerId, query }, 'Context requested');\n });\n }\n\n /**\n * Start automatic context synchronization\n * Uses interval from config.contextSharing.syncInterval (default: 5000ms)\n * @param contextProvider Optional function that returns context to sync\n */\n startAutoSync(contextProvider?: () => Context | Promise<Context>): void {\n // Stop any existing auto-sync\n this.stopAutoSync();\n\n const interval = this.config.contextSharing?.syncInterval ?? 5000;\n\n this.autoSyncIntervalId = setInterval(async () => {\n try {\n // Get context from provider if available\n const context = contextProvider ? await contextProvider() : undefined;\n await this.syncContext(context);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Auto-sync error');\n }\n }, interval);\n\n logger.info({ interval }, 'Auto-sync started');\n }\n\n /**\n * Stop automatic context synchronization\n */\n stopAutoSync(): void {\n if (this.autoSyncIntervalId) {\n clearInterval(this.autoSyncIntervalId);\n this.autoSyncIntervalId = null;\n logger.info('Auto-sync stopped');\n }\n }\n\n // ============================================================================\n // Private Methods - Server\n // ============================================================================\n\n /**\n * Start the WebSocket server\n */\n private async startServer(): Promise<void> {\n const { listen } = this.config;\n if (!listen) {\n throw new Error('Listen configuration is required');\n }\n\n return new Promise<void>((resolve, reject) => {\n const host = listen.host ?? '0.0.0.0';\n const port = listen.port;\n\n logger.debug({ host, port }, 'Starting WebSocket server');\n\n this.server = new WebSocketServer({ host, port });\n\n this.server.on('listening', () => {\n logger.info({ host, port }, 'WebSocket server listening');\n resolve();\n });\n\n this.server.on('error', (error) => {\n logger.error({ error: (error as Error).message }, 'WebSocket server error');\n reject(error);\n });\n\n this.server.on('connection', (ws, request) => {\n this.handleNewConnection(ws, request);\n });\n });\n }\n\n /**\n * Handle a new incoming connection\n */\n private handleNewConnection(ws: WsWebSocket, request: { url?: string }): void {\n const peerId = uuidv4();\n const peerInfo: PeerInfo = {\n id: peerId,\n name: 'client', // Will be updated when we receive peer info\n connectedAt: Date.now(),\n lastActivity: Date.now(),\n };\n\n this.peers.set(peerId, {\n info: peerInfo,\n ws,\n });\n\n logger.info({ peerId, url: request.url }, 'New peer connected');\n\n // Set up message handler\n ws.on('message', (data) => {\n const messageString = data.toString();\n const result = safeDeserializeMessage(messageString);\n\n if (result.success) {\n peerInfo.lastActivity = Date.now();\n this.handleMessage(result.data, ws, peerId);\n } else {\n logger.warn({ peerId, error: result.error.message }, 'Invalid message received');\n }\n });\n\n // Set up close handler\n ws.on('close', (code, reason) => {\n logger.info({ peerId, code, reason: reason.toString() }, 'Peer disconnected');\n this.peers.delete(peerId);\n this.notifyPeerDisconnected(peerInfo);\n });\n\n // Set up error handler\n ws.on('error', (error) => {\n logger.error({ peerId, error: (error as Error).message }, 'Peer connection error');\n });\n\n // Notify peer connected handlers\n this.notifyPeerConnected(peerInfo);\n }\n\n // ============================================================================\n // Private Methods - Client\n // ============================================================================\n\n /**\n * Connect to a remote bridge as a client\n */\n private async connectToRemote(): Promise<void> {\n const { connect } = this.config;\n if (!connect) {\n throw new Error('Connect configuration is required');\n }\n\n // Build URL from config\n let url = connect.url;\n if (!url) {\n const host = connect.hostGateway ? 'host.docker.internal' : 'localhost';\n const port = connect.port ?? 8765;\n url = `ws://${host}:${port}`;\n }\n\n this.clientTransport = new WebSocketTransport();\n\n // Set up message handler\n this.clientTransport.onMessage((message) => {\n this.handleMessage(message, this.clientTransport!);\n });\n\n // Set up disconnect handler\n this.clientTransport.onDisconnect(() => {\n this.handleClientDisconnect(this.clientTransport!);\n });\n\n try {\n await this.clientTransport.connect({\n url,\n reconnect: true,\n reconnectInterval: 1000,\n maxReconnectAttempts: 10,\n });\n\n // Create peer info for the connected server\n const peerId = uuidv4();\n const peerInfo: PeerInfo = {\n id: peerId,\n name: 'server',\n connectedAt: Date.now(),\n lastActivity: Date.now(),\n };\n\n this.peers.set(peerId, {\n info: peerInfo,\n transport: this.clientTransport,\n });\n\n // Store peerId on transport for lookup\n (this.clientTransport as WebSocketTransport & { _peerId?: string })._peerId = peerId;\n\n this.notifyPeerConnected(peerInfo);\n logger.info({ peerId, url }, 'Connected to remote bridge');\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Failed to connect to remote bridge');\n this.clientTransport = null;\n throw error;\n }\n }\n\n /**\n * Handle client transport disconnect\n */\n private handleClientDisconnect(transport: Transport): void {\n // Find peer by transport\n const typedTransport = transport as WebSocketTransport & { _peerId?: string };\n const peerId = typedTransport._peerId;\n\n if (peerId) {\n const peer = this.peers.get(peerId);\n if (peer) {\n this.peers.delete(peerId);\n this.notifyPeerDisconnected(peer.info);\n logger.info({ peerId }, 'Client transport disconnected');\n }\n }\n }\n\n // ============================================================================\n // Private Methods - Message Handling\n // ============================================================================\n\n /**\n * Handle an incoming message\n */\n private handleMessage(\n message: BridgeMessage,\n source: WsWebSocket | Transport,\n peerId?: string\n ): void {\n // Find peerId if not provided\n if (!peerId) {\n const typedSource = source as WebSocketTransport & { _peerId?: string };\n peerId = typedSource._peerId;\n }\n\n if (!peerId) {\n // Try to find by ws reference\n for (const [id, peer] of this.peers) {\n if (peer.ws === source || peer.transport === source) {\n peerId = id;\n break;\n }\n }\n }\n\n if (!peerId) {\n logger.warn({ messageId: message.id }, 'Received message from unknown peer');\n return;\n }\n\n // Update last activity\n const peer = this.peers.get(peerId);\n if (peer) {\n peer.info.lastActivity = Date.now();\n }\n\n logger.debug({ peerId, messageId: message.id, type: message.type }, 'Received message');\n\n // Handle task delegation messages\n if (message.type === 'task_delegate' && message.task) {\n this.handleTaskDelegate(message, peerId);\n return;\n }\n\n // Handle task response messages\n if (message.type === 'response' && message.result?.taskId) {\n this.handleTaskResponse(message);\n return;\n }\n\n // Handle context sync messages\n if (message.type === 'context_sync' && message.context) {\n this.handleContextSync(message, peerId);\n return;\n }\n\n // Handle context request messages\n if (message.type === 'request' && message.context?.summary) {\n this.handleContextRequest(message, peerId);\n return;\n }\n\n // Handle context response messages (responses to context requests)\n if (message.type === 'response' && message.context?.files !== undefined) {\n this.handleContextResponse(message);\n return;\n }\n\n // Notify message handlers for other message types\n this.notifyMessageReceived(message, peerId);\n }\n\n /**\n * Handle incoming task delegation request\n */\n private async handleTaskDelegate(message: BridgeMessage, peerId: string): Promise<void> {\n const task = message.task!;\n logger.debug({ taskId: task.id, peerId }, 'Received task delegation');\n\n // If no handler registered, send error response\n if (!this.taskReceivedHandler) {\n logger.warn({ taskId: task.id }, 'No task handler registered');\n const response = createTaskResponseMessage(\n this.config.instanceName,\n task.id,\n {\n success: false,\n data: null,\n error: 'No task handler registered on peer',\n }\n );\n await this.sendToPeer(peerId, response).catch((err) => {\n logger.error({ error: (err as Error).message, taskId: task.id }, 'Failed to send error response');\n });\n return;\n }\n\n try {\n // Execute the task handler\n const result = await this.taskReceivedHandler(task, peerId);\n\n // Send successful response\n const response = createTaskResponseMessage(\n this.config.instanceName,\n task.id,\n result\n );\n await this.sendToPeer(peerId, response);\n logger.debug({ taskId: task.id, success: result.success }, 'Task response sent');\n } catch (error) {\n // Send error response\n const response = createTaskResponseMessage(\n this.config.instanceName,\n task.id,\n {\n success: false,\n data: null,\n error: (error as Error).message,\n }\n );\n await this.sendToPeer(peerId, response).catch((err) => {\n logger.error({ error: (err as Error).message, taskId: task.id }, 'Failed to send error response');\n });\n logger.error({ taskId: task.id, error: (error as Error).message }, 'Task handler error');\n }\n }\n\n /**\n * Handle task response message (correlate with pending task)\n */\n private handleTaskResponse(message: BridgeMessage): void {\n const taskId = message.result!.taskId!;\n const pending = this.pendingTasks.get(taskId);\n\n if (!pending) {\n logger.warn({ taskId }, 'Received response for unknown task');\n return;\n }\n\n // Clear timeout and remove from pending\n clearTimeout(pending.timeoutId);\n this.pendingTasks.delete(taskId);\n\n // Resolve the promise with the result\n const result: TaskResult = {\n taskId: message.result!.taskId,\n success: message.result!.success,\n data: message.result!.data,\n artifacts: message.result!.artifacts,\n followUp: message.result!.followUp,\n error: message.result!.error,\n };\n\n logger.debug({ taskId, success: result.success }, 'Task result received');\n pending.resolve(result);\n }\n\n /**\n * Handle incoming context sync message\n */\n private handleContextSync(message: BridgeMessage, peerId: string): void {\n const context = message.context!;\n logger.debug({ peerId, messageId: message.id }, 'Received context sync');\n\n // Notify all context received handlers\n this.notifyContextReceived(context, peerId);\n }\n\n /**\n * Handle incoming context request message\n */\n private async handleContextRequest(message: BridgeMessage, peerId: string): Promise<void> {\n const query = message.context!.summary!;\n logger.debug({ peerId, messageId: message.id, query }, 'Received context request');\n\n // If no handler registered, send empty response\n if (!this.contextRequestedHandler) {\n logger.warn({ messageId: message.id }, 'No context request handler registered');\n const response = createContextSyncMessage(this.config.instanceName, { files: [] });\n // Change type to response and add request ID for correlation\n const responseMessage: BridgeMessage = {\n ...response,\n type: 'response',\n context: {\n ...response.context,\n variables: { requestId: message.id },\n },\n };\n await this.sendToPeer(peerId, responseMessage).catch((err) => {\n logger.error({ error: (err as Error).message, messageId: message.id }, 'Failed to send empty context response');\n });\n return;\n }\n\n try {\n // Execute the context request handler\n const files = await this.contextRequestedHandler(query, peerId);\n\n // Create and send response\n const response = createContextSyncMessage(this.config.instanceName, { files });\n const responseMessage: BridgeMessage = {\n ...response,\n type: 'response',\n context: {\n ...response.context,\n variables: { requestId: message.id },\n },\n };\n await this.sendToPeer(peerId, responseMessage);\n logger.debug({ messageId: message.id, fileCount: files.length }, 'Context response sent');\n } catch (error) {\n // Send error response with empty files\n const response = createContextSyncMessage(this.config.instanceName, {\n files: [],\n summary: (error as Error).message,\n });\n const responseMessage: BridgeMessage = {\n ...response,\n type: 'response',\n context: {\n ...response.context,\n variables: { requestId: message.id, error: (error as Error).message },\n },\n };\n await this.sendToPeer(peerId, responseMessage).catch((err) => {\n logger.error({ error: (err as Error).message, messageId: message.id }, 'Failed to send error context response');\n });\n logger.error({ messageId: message.id, error: (error as Error).message }, 'Context request handler error');\n }\n }\n\n /**\n * Handle context response message (correlate with pending context request)\n */\n private handleContextResponse(message: BridgeMessage): void {\n const requestId = message.context?.variables?.requestId as string;\n if (!requestId) {\n logger.warn({ messageId: message.id }, 'Context response without requestId');\n return;\n }\n\n const pending = this.pendingContextRequests.get(requestId);\n if (!pending) {\n logger.warn({ requestId }, 'Received response for unknown context request');\n return;\n }\n\n // Clear timeout and remove from pending\n clearTimeout(pending.timeoutId);\n this.pendingContextRequests.delete(requestId);\n\n // Check for error\n const error = message.context?.variables?.error as string | undefined;\n if (error) {\n pending.reject(new Error(error));\n return;\n }\n\n // Resolve the promise with the files\n const files = message.context?.files ?? [];\n logger.debug({ requestId, fileCount: files.length }, 'Context response received');\n pending.resolve(files);\n }\n\n // ============================================================================\n // Private Methods - Event Notification\n // ============================================================================\n\n private notifyPeerConnected(peer: PeerInfo): void {\n for (const handler of this.peerConnectedHandlers) {\n try {\n handler(peer);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Peer connected handler error');\n }\n }\n }\n\n private notifyPeerDisconnected(peer: PeerInfo): void {\n // Reject any pending tasks for this peer\n for (const [taskId, pending] of this.pendingTasks) {\n if (pending.peerId === peer.id) {\n clearTimeout(pending.timeoutId);\n this.pendingTasks.delete(taskId);\n pending.reject(new Error(`Peer '${peer.id}' disconnected while task '${taskId}' was pending`));\n }\n }\n\n // Reject any pending context requests for this peer\n for (const [requestId, pending] of this.pendingContextRequests) {\n if (pending.peerId === peer.id) {\n clearTimeout(pending.timeoutId);\n this.pendingContextRequests.delete(requestId);\n pending.reject(new Error(`Peer '${peer.id}' disconnected while context request '${requestId}' was pending`));\n }\n }\n\n for (const handler of this.peerDisconnectedHandlers) {\n try {\n handler(peer);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Peer disconnected handler error');\n }\n }\n }\n\n private notifyMessageReceived(message: BridgeMessage, peerId: string): void {\n for (const handler of this.messageReceivedHandlers) {\n try {\n handler(message, peerId);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Message received handler error');\n }\n }\n }\n\n private notifyContextReceived(context: Context, peerId: string): void {\n for (const handler of this.contextReceivedHandlers) {\n try {\n handler(context, peerId);\n } catch (error) {\n logger.error({ error: (error as Error).message }, 'Context received handler error');\n }\n }\n }\n\n // ============================================================================\n // Private Methods - Cleanup\n // ============================================================================\n\n /**\n * Clean up all resources\n */\n private async cleanup(): Promise<void> {\n logger.debug('Starting cleanup');\n\n // Stop auto-sync\n this.stopAutoSync();\n logger.debug('Auto-sync stopped');\n\n // Reject all pending tasks\n const pendingTaskCount = this.pendingTasks.size;\n for (const [taskId, pending] of this.pendingTasks) {\n clearTimeout(pending.timeoutId);\n pending.reject(new Error('Bridge is shutting down'));\n }\n this.pendingTasks.clear();\n if (pendingTaskCount > 0) {\n logger.debug({ count: pendingTaskCount }, 'Pending tasks cancelled');\n }\n\n // Reject all pending context requests\n const pendingContextCount = this.pendingContextRequests.size;\n for (const [requestId, pending] of this.pendingContextRequests) {\n clearTimeout(pending.timeoutId);\n pending.reject(new Error('Bridge is shutting down'));\n }\n this.pendingContextRequests.clear();\n if (pendingContextCount > 0) {\n logger.debug({ count: pendingContextCount }, 'Pending context requests cancelled');\n }\n\n // Disconnect client transport\n if (this.clientTransport) {\n logger.debug('Disconnecting client transport');\n try {\n await this.clientTransport.disconnect();\n logger.debug('Client transport disconnected');\n } catch {\n // Ignore disconnect errors during cleanup\n }\n this.clientTransport = null;\n }\n\n // Close all peer WebSocket connections\n const peerCount = this.peers.size;\n if (peerCount > 0) {\n logger.debug({ count: peerCount }, 'Closing peer connections');\n }\n for (const [peerId, peer] of this.peers) {\n if (peer.ws) {\n try {\n peer.ws.close(1000, 'Bridge stopping');\n } catch {\n // Ignore close errors during cleanup\n }\n }\n if (peer.transport) {\n try {\n await peer.transport.disconnect();\n } catch {\n // Ignore disconnect errors during cleanup\n }\n }\n logger.debug({ peerId }, 'Peer disconnected');\n }\n this.peers.clear();\n\n // Close server\n if (this.server) {\n logger.debug('Closing WebSocket server');\n await new Promise<void>((resolve) => {\n this.server!.close(() => {\n resolve();\n });\n });\n this.server = null;\n logger.debug('WebSocket server closed');\n }\n\n logger.debug('Cleanup complete');\n }\n\n // ============================================================================\n // Getters for State Inspection\n // ============================================================================\n\n /**\n * Check if the bridge is started\n */\n isStarted(): boolean {\n return this.started;\n }\n\n /**\n * Get the instance name\n */\n getInstanceName(): string {\n return this.config.instanceName;\n }\n\n /**\n * Get the operation mode\n */\n getMode(): BridgeMode {\n return this.config.mode;\n }\n\n /**\n * Get the number of connected peers\n */\n getPeerCount(): number {\n return this.peers.size;\n }\n}\n","/**\n * Peer Discovery Module\n *\n * Provides functions to discover bridge-enabled Docker containers\n * and development environment projects.\n */\n\nimport { execSync } from 'child_process';\nimport { createLogger } from '../utils/logger.js';\n\nconst logger = createLogger('transport:discovery');\n\n/**\n * Discovered peer information\n */\nexport interface DiscoveredPeer {\n name: string;\n source: 'docker' | 'docksal' | 'ddev' | 'lando';\n url: string;\n containerId?: string;\n status?: string;\n}\n\n/**\n * Bridge label configuration parsed from Docker container labels\n */\nexport interface BridgeLabelConfig {\n enabled: boolean;\n port?: number;\n name?: string;\n}\n\n/**\n * Parse Docker container labels to extract bridge configuration\n *\n * @param labels - Comma-separated label string from Docker\n * @returns Parsed bridge configuration or null if bridge not enabled\n */\nexport function parseDockerLabels(labels: string): BridgeLabelConfig | null {\n if (!labels) {\n return null;\n }\n\n const labelMap: Record<string, string> = {};\n\n // Parse comma-separated labels into map\n for (const label of labels.split(',')) {\n const [key, value] = label.split('=');\n if (key && value) {\n labelMap[key.trim()] = value.trim();\n }\n }\n\n // Check if bridge is enabled\n if (labelMap['claude.bridge.enabled'] !== 'true') {\n return null;\n }\n\n return {\n enabled: true,\n port: labelMap['claude.bridge.port']\n ? parseInt(labelMap['claude.bridge.port'], 10)\n : undefined,\n name: labelMap['claude.bridge.name'],\n };\n}\n\n/**\n * Check if Docker daemon is available and running\n */\nexport function isDockerAvailable(): boolean {\n try {\n execSync('docker info', { stdio: 'pipe', timeout: 5000 });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Discover Docker containers with bridge labels\n *\n * Searches for running containers that have the claude.bridge.enabled=true label\n * and extracts connection information from their labels.\n *\n * @returns Array of discovered peers with connection URLs\n */\nexport function discoverDockerPeers(): DiscoveredPeer[] {\n const peers: DiscoveredPeer[] = [];\n\n if (!isDockerAvailable()) {\n logger.debug('Docker is not available');\n return peers;\n }\n\n try {\n // Get all running containers with their labels and ports\n const output = execSync(\n 'docker ps --format \"{{.ID}}|{{.Names}}|{{.Labels}}|{{.Status}}|{{.Ports}}\"',\n {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: 10000,\n }\n );\n\n const lines = output.trim().split('\\n').filter(Boolean);\n\n for (const line of lines) {\n const [id, names, labels, status, ports] = line.split('|');\n\n if (!id || !names) continue;\n\n const bridgeConfig = parseDockerLabels(labels);\n if (!bridgeConfig) continue;\n\n // Determine port from config or from exposed ports\n let port = bridgeConfig.port;\n if (!port && ports) {\n // Try to extract port from ports string like \"0.0.0.0:8765->8765/tcp\"\n const portMatch = ports.match(/0\\.0\\.0\\.0:(\\d+)/);\n if (portMatch) {\n port = parseInt(portMatch[1], 10);\n }\n }\n\n if (port) {\n peers.push({\n name: bridgeConfig.name || names,\n source: 'docker',\n url: `ws://localhost:${port}`,\n containerId: id,\n status: status,\n });\n\n logger.debug(\n { containerId: id, name: bridgeConfig.name || names, port },\n 'Found bridge-enabled container'\n );\n }\n }\n } catch (error) {\n logger.debug(\n { error: (error as Error).message },\n 'Failed to discover Docker peers'\n );\n }\n\n return peers;\n}\n\n/**\n * Discover Docksal projects with bridges\n *\n * Uses the `fin project list` command to find running Docksal projects.\n *\n * @returns Array of discovered peers with connection URLs\n */\nexport function discoverDocksalProjects(): DiscoveredPeer[] {\n const peers: DiscoveredPeer[] = [];\n\n try {\n // Check if fin command is available\n execSync('which fin', { stdio: 'pipe' });\n\n // List Docksal projects\n const output = execSync('fin project list 2>/dev/null || echo \"\"', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: 10000,\n });\n\n const lines = output.trim().split('\\n').filter(Boolean);\n\n for (const line of lines) {\n // Skip header lines\n if (line.includes('NAME') || line.startsWith('-')) continue;\n\n // Parse project line - format varies but typically: NAME STATUS\n const parts = line.trim().split(/\\s+/);\n const projectName = parts[0];\n const status = parts.slice(1).join(' ');\n\n if (projectName && status.toLowerCase().includes('running')) {\n // Default Docksal bridge port\n peers.push({\n name: projectName,\n source: 'docksal',\n url: `ws://${projectName}.docksal:8765`,\n status: 'running',\n });\n\n logger.debug({ projectName }, 'Found Docksal project');\n }\n }\n } catch (error) {\n logger.debug(\n { error: (error as Error).message },\n 'Docksal not available or no projects found'\n );\n }\n\n return peers;\n}\n\n/**\n * Discover DDEV projects with bridges\n *\n * Uses the `ddev list` command to find running DDEV projects.\n *\n * @returns Array of discovered peers with connection URLs\n */\nexport function discoverDdevProjects(): DiscoveredPeer[] {\n const peers: DiscoveredPeer[] = [];\n\n try {\n // Check if ddev command is available\n execSync('which ddev', { stdio: 'pipe' });\n\n // List DDEV projects in JSON format\n const output = execSync('ddev list --json-output 2>/dev/null || echo \"[]\"', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: 10000,\n });\n\n try {\n const data = JSON.parse(output);\n const projects = data.raw || [];\n\n for (const project of projects) {\n if (project.status === 'running') {\n peers.push({\n name: project.name,\n source: 'ddev',\n url: `ws://${project.name}.ddev.site:8765`,\n status: 'running',\n });\n\n logger.debug({ projectName: project.name }, 'Found DDEV project');\n }\n }\n } catch {\n // JSON parse failed, try text parsing\n logger.debug('Failed to parse DDEV JSON output, trying text parsing');\n\n const lines = output.trim().split('\\n').filter(Boolean);\n for (const line of lines) {\n if (line.includes('running')) {\n const parts = line.trim().split(/\\s+/);\n if (parts[0]) {\n peers.push({\n name: parts[0],\n source: 'ddev',\n url: `ws://${parts[0]}.ddev.site:8765`,\n status: 'running',\n });\n }\n }\n }\n }\n } catch (error) {\n logger.debug(\n { error: (error as Error).message },\n 'DDEV not available or no projects found'\n );\n }\n\n return peers;\n}\n\n/**\n * Discover Lando projects with bridges\n *\n * Uses the `lando list` command to find running Lando apps.\n *\n * @returns Array of discovered peers with connection URLs\n */\nexport function discoverLandoProjects(): DiscoveredPeer[] {\n const peers: DiscoveredPeer[] = [];\n\n try {\n // Check if lando command is available\n execSync('which lando', { stdio: 'pipe' });\n\n // List Lando apps in JSON format\n const output = execSync('lando list --format json 2>/dev/null || echo \"[]\"', {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'],\n timeout: 10000,\n });\n\n try {\n const apps = JSON.parse(output);\n\n for (const app of apps) {\n if (app.running) {\n peers.push({\n name: app.app || app.name,\n source: 'lando',\n url: `ws://localhost:8765`, // Would need to check app config for actual port\n status: 'running',\n });\n\n logger.debug({ appName: app.app || app.name }, 'Found Lando app');\n }\n }\n } catch {\n logger.debug('Failed to parse Lando JSON output');\n }\n } catch (error) {\n logger.debug(\n { error: (error as Error).message },\n 'Lando not available or no projects found'\n );\n }\n\n return peers;\n}\n\n/**\n * Discover all peers from all sources\n *\n * Aggregates peers from Docker containers and all supported development\n * environments (Docksal, DDEV, Lando).\n *\n * @returns Array of all discovered peers\n */\nexport function discoverAllPeers(): DiscoveredPeer[] {\n const allPeers: DiscoveredPeer[] = [];\n\n // Discover from all sources\n const dockerPeers = discoverDockerPeers();\n allPeers.push(...dockerPeers);\n logger.debug({ count: dockerPeers.length }, 'Docker peers discovered');\n\n const docksalPeers = discoverDocksalProjects();\n allPeers.push(...docksalPeers);\n logger.debug({ count: docksalPeers.length }, 'Docksal peers discovered');\n\n const ddevPeers = discoverDdevProjects();\n allPeers.push(...ddevPeers);\n logger.debug({ count: ddevPeers.length }, 'DDEV peers discovered');\n\n const landoPeers = discoverLandoProjects();\n allPeers.push(...landoPeers);\n logger.debug({ count: landoPeers.length }, 'Lando peers discovered');\n\n return allPeers;\n}\n","/**\n * Environment detection utilities for Claude Code Bridge\n *\n * Detects the runtime environment (Docksal, DDEV, Lando, Docker, or native)\n * and provides appropriate configuration defaults.\n */\n\nimport { existsSync } from 'fs';\nimport type { BridgeConfig } from '../utils/config.js';\n\n/**\n * Supported Docker environment types\n */\nexport type DockerEnvironment =\n | 'docksal'\n | 'ddev'\n | 'lando'\n | 'docker-compose'\n | 'docker'\n | 'native';\n\n/**\n * Information about the detected runtime environment\n */\nexport interface EnvironmentInfo {\n /** The type of environment detected */\n type: DockerEnvironment;\n /** Whether running inside a container */\n isContainer: boolean;\n /** Project name (if applicable) */\n projectName?: string;\n /** Project root path (if applicable) */\n projectRoot?: string;\n /** Host gateway address for container-to-host communication */\n hostGateway?: string;\n /** Operating system platform */\n platform: NodeJS.Platform;\n /** Additional environment-specific metadata */\n meta?: Record<string, string>;\n}\n\n/**\n * Check if running inside a Docker container\n *\n * Checks for the presence of /.dockerenv file which Docker creates\n * in all containers.\n */\nfunction isInDocker(): boolean {\n return existsSync('/.dockerenv');\n}\n\n/**\n * Check if running in a Docksal environment\n *\n * Docksal sets DOCKSAL_STACK environment variable in all CLI containers.\n */\nfunction isDocksalEnvironment(): boolean {\n return !!process.env.DOCKSAL_STACK;\n}\n\n/**\n * Check if running in a DDEV environment\n *\n * DDEV sets IS_DDEV_PROJECT=true in web containers.\n */\nfunction isDdevEnvironment(): boolean {\n return process.env.IS_DDEV_PROJECT === 'true';\n}\n\n/**\n * Check if running in a Lando environment\n *\n * Lando sets LANDO=ON in all service containers.\n */\nfunction isLandoEnvironment(): boolean {\n return process.env.LANDO === 'ON';\n}\n\n/**\n * Check if running in a docker-compose managed container\n *\n * Docker Compose sets COMPOSE_PROJECT_NAME in containers.\n */\nfunction isDockerComposeEnvironment(): boolean {\n return !!process.env.COMPOSE_PROJECT_NAME;\n}\n\n/**\n * Detect the current runtime environment\n *\n * Detection order (first match wins):\n * 1. Docksal (DOCKSAL_STACK env var)\n * 2. DDEV (IS_DDEV_PROJECT=true env var)\n * 3. Lando (LANDO=ON env var)\n * 4. Docker Compose (COMPOSE_PROJECT_NAME env var)\n * 5. Generic Docker (/.dockerenv file exists)\n * 6. Native (fallback)\n *\n * @returns EnvironmentInfo object with detected environment details\n */\nexport function detectEnvironment(): EnvironmentInfo {\n const platform = process.platform;\n const inDocker = isInDocker();\n\n // Check Docksal first (highest priority)\n if (isDocksalEnvironment()) {\n return {\n type: 'docksal',\n isContainer: true,\n projectName: process.env.DOCKSAL_PROJECT,\n projectRoot: process.env.PROJECT_ROOT,\n hostGateway: getHostGateway(),\n platform,\n meta: {\n stack: process.env.DOCKSAL_STACK || '',\n environment: process.env.DOCKSAL_ENVIRONMENT || '',\n },\n };\n }\n\n // Check DDEV\n if (isDdevEnvironment()) {\n return {\n type: 'ddev',\n isContainer: true,\n projectName: process.env.DDEV_PROJECT,\n projectRoot: process.env.DDEV_DOCROOT,\n hostGateway: getHostGateway(),\n platform,\n meta: {\n hostname: process.env.DDEV_HOSTNAME || '',\n primaryUrl: process.env.DDEV_PRIMARY_URL || '',\n },\n };\n }\n\n // Check Lando\n if (isLandoEnvironment()) {\n return {\n type: 'lando',\n isContainer: true,\n projectName: process.env.LANDO_APP_NAME,\n projectRoot: process.env.LANDO_APP_ROOT,\n hostGateway: getHostGateway(),\n platform,\n meta: {\n service: process.env.LANDO_SERVICE_NAME || '',\n type: process.env.LANDO_SERVICE_TYPE || '',\n },\n };\n }\n\n // Check Docker Compose (before generic Docker)\n if (isDockerComposeEnvironment() && inDocker) {\n return {\n type: 'docker-compose',\n isContainer: true,\n projectName: process.env.COMPOSE_PROJECT_NAME,\n hostGateway: getHostGateway(),\n platform,\n meta: {\n service: process.env.COMPOSE_SERVICE || '',\n },\n };\n }\n\n // Check generic Docker\n if (inDocker) {\n return {\n type: 'docker',\n isContainer: true,\n hostGateway: getHostGateway(),\n platform,\n };\n }\n\n // Fallback: Native environment\n return {\n type: 'native',\n isContainer: false,\n platform,\n };\n}\n\n/**\n * Get the host gateway address for container-to-host communication\n *\n * - macOS and Windows: Use host.docker.internal (provided by Docker Desktop)\n * - Linux: May need to use bridge gateway IP or host-gateway flag\n *\n * @returns The hostname or IP to reach the Docker host from inside a container\n */\nexport function getHostGateway(): string {\n // Check for explicit override via environment variable\n if (process.env.DOCKER_HOST_GATEWAY) {\n return process.env.DOCKER_HOST_GATEWAY;\n }\n\n // macOS and Windows Docker Desktop provide host.docker.internal\n if (process.platform === 'darwin' || process.platform === 'win32') {\n return 'host.docker.internal';\n }\n\n // Linux: Modern Docker (20.10+) supports host.docker.internal with --add-host\n // but it needs to be configured. Try it first, fallback to gateway IP.\n // The host-gateway special name resolves to the host's gateway IP.\n\n // Check if running in container on Linux\n if (isInDocker()) {\n // Use host.docker.internal which should work if configured properly\n // This is the recommended approach for Docker 20.10+\n return 'host.docker.internal';\n }\n\n // Native Linux - just use localhost\n return 'localhost';\n}\n\n/**\n * Get default bridge configuration based on the detected environment\n *\n * Different environments may have different port defaults or connection\n * preferences.\n *\n * @param env - The detected environment info\n * @returns Partial BridgeConfig with environment-specific defaults\n */\nexport function getDefaultConfig(env: EnvironmentInfo): Partial<BridgeConfig> {\n const baseConfig: Partial<BridgeConfig> = {\n mode: 'peer',\n instanceName: env.projectName || `${env.type}-instance`,\n };\n\n if (env.isContainer) {\n // Container environments: listen on all interfaces, connect to host\n return {\n ...baseConfig,\n listen: {\n port: 8765,\n host: '0.0.0.0',\n },\n connect: {\n url: `ws://${env.hostGateway || 'host.docker.internal'}:8766`,\n hostGateway: true,\n },\n };\n }\n\n // Native environment: listen on localhost with different port\n return {\n ...baseConfig,\n listen: {\n port: 8766,\n host: '0.0.0.0',\n },\n connect: {\n url: 'ws://localhost:8765',\n hostGateway: false,\n },\n };\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { parse as parseYaml } from 'yaml';\n\n/**\n * Configuration for the bridge's listening socket\n */\nexport interface ListenConfig {\n port: number;\n host: string;\n}\n\n/**\n * Configuration for connecting to a remote bridge\n */\nexport interface ConnectConfig {\n url?: string;\n hostGateway?: boolean;\n port?: number;\n}\n\n/**\n * Configuration for context sharing behavior\n */\nexport interface ContextSharingConfig {\n autoSync: boolean;\n syncInterval: number;\n maxChunkTokens: number;\n includePatterns: string[];\n excludePatterns: string[];\n}\n\n/**\n * Configuration for interaction behavior\n */\nexport interface InteractionConfig {\n requireConfirmation: boolean;\n notifyOnActivity: boolean;\n taskTimeout: number;\n}\n\n/**\n * Full bridge configuration\n */\nexport interface BridgeConfig {\n instanceName?: string;\n mode?: 'host' | 'client' | 'peer';\n listen: ListenConfig;\n connect?: ConnectConfig;\n contextSharing: ContextSharingConfig;\n interaction: InteractionConfig;\n}\n\n/**\n * Default configuration values\n */\nexport const DEFAULT_CONFIG: BridgeConfig = {\n listen: {\n port: 8765,\n host: '0.0.0.0',\n },\n contextSharing: {\n autoSync: true,\n syncInterval: 5000,\n maxChunkTokens: 4000,\n includePatterns: ['src/**/*.ts', 'src/**/*.tsx', '*.json'],\n excludePatterns: ['node_modules/**', 'dist/**', '.git/**'],\n },\n interaction: {\n requireConfirmation: false,\n notifyOnActivity: true,\n taskTimeout: 300000, // 5 minutes\n },\n};\n\n/**\n * Deep merges a partial config with the default config\n *\n * @param partial - Partial configuration to merge\n * @returns Complete configuration with defaults for missing values\n */\nexport function mergeConfig(partial: Partial<BridgeConfig>): BridgeConfig {\n return {\n ...DEFAULT_CONFIG,\n ...partial,\n listen: {\n ...DEFAULT_CONFIG.listen,\n ...(partial.listen ?? {}),\n },\n connect: partial.connect\n ? {\n ...partial.connect,\n }\n : undefined,\n contextSharing: {\n ...DEFAULT_CONFIG.contextSharing,\n ...(partial.contextSharing ?? {}),\n },\n interaction: {\n ...DEFAULT_CONFIG.interaction,\n ...(partial.interaction ?? {}),\n },\n };\n}\n\n/**\n * Attempts to read and parse a YAML config file\n *\n * @param filePath - Path to the config file\n * @returns Parsed config or null if file doesn't exist\n */\nfunction readConfigFile(filePath: string): Partial<BridgeConfig> | null {\n try {\n if (!fs.existsSync(filePath)) {\n return null;\n }\n const content = fs.readFileSync(filePath, 'utf-8');\n const parsed = parseYaml(content);\n return parsed as Partial<BridgeConfig>;\n } catch {\n // Return null if file can't be read or parsed\n return null;\n }\n}\n\n/**\n * Gets the default config file paths to search\n *\n * @returns Array of config file paths in priority order\n */\nfunction getDefaultConfigPaths(): string[] {\n const homeDir = os.homedir();\n const cwd = process.cwd();\n\n return [\n // Project-local config takes priority\n path.join(cwd, '.claude-bridge.yml'),\n path.join(cwd, '.claude-bridge.yaml'),\n // User home config as fallback\n path.join(homeDir, '.claude-bridge', 'config.yml'),\n path.join(homeDir, '.claude-bridge', 'config.yaml'),\n ];\n}\n\n/**\n * Loads configuration from file(s) and merges with defaults\n *\n * Searches for config files in the following order:\n * 1. Explicit path (if provided)\n * 2. .claude-bridge.yml in current working directory\n * 3. ~/.claude-bridge/config.yml\n *\n * @param configPath - Optional explicit path to config file\n * @returns Complete configuration with defaults for missing values\n *\n * @example\n * ```typescript\n * // Load from default locations\n * const config = await loadConfig();\n *\n * // Load from specific path\n * const config = await loadConfig('/path/to/config.yml');\n * ```\n */\nexport async function loadConfig(configPath?: string): Promise<BridgeConfig> {\n // If explicit path provided, try to load it\n if (configPath) {\n const parsed = readConfigFile(configPath);\n if (parsed) {\n return mergeConfig(parsed);\n }\n // If explicit path doesn't exist, return defaults\n return { ...DEFAULT_CONFIG };\n }\n\n // Search default paths\n const searchPaths = getDefaultConfigPaths();\n\n for (const searchPath of searchPaths) {\n const parsed = readConfigFile(searchPath);\n if (parsed) {\n return mergeConfig(parsed);\n }\n }\n\n // No config file found, return defaults\n return { ...DEFAULT_CONFIG };\n}\n\n/**\n * Synchronous version of loadConfig for simpler usage patterns\n *\n * @param configPath - Optional explicit path to config file\n * @returns Complete configuration with defaults for missing values\n */\nexport function loadConfigSync(configPath?: string): BridgeConfig {\n // If explicit path provided, try to load it\n if (configPath) {\n const parsed = readConfigFile(configPath);\n if (parsed) {\n return mergeConfig(parsed);\n }\n // If explicit path doesn't exist, return defaults\n return { ...DEFAULT_CONFIG };\n }\n\n // Search default paths\n const searchPaths = getDefaultConfigPaths();\n\n for (const searchPath of searchPaths) {\n const parsed = readConfigFile(searchPath);\n if (parsed) {\n return mergeConfig(parsed);\n }\n }\n\n // No config file found, return defaults\n return { ...DEFAULT_CONFIG };\n}\n"],"mappings":"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","names":["ConnectionState","uuidv4","logger","uuidv4","peer","logger"]}