/** * Protocol Peer * * Manages bidirectional JSON communication with Claude CLI process. * * @module agents/claude/protocol/protocol-peer */ import type { Readable, Writable } from 'stream'; import type { ClaudeStreamMessage } from '../types/messages.js'; import type { ControlRequest, ControlResponse, HookConfig, PermissionMode } from '../types/control.js'; /** * Client interface for handling control requests * * Implemented by ClaudeAgentClient to provide approval logic. */ export interface IProtocolClient { /** * Handle a control request from Claude CLI * * @param request - Control request (can_use_tool or hook_callback) * @returns Control response (success or error) */ handleControlRequest(request: ControlRequest, requestId: string): Promise; } /** * Message handler callback * * Called for each non-control message received from Claude CLI. */ export type MessageHandler = (message: ClaudeStreamMessage) => void; /** * Error handler callback * * Called when an error occurs during message processing. */ export type ErrorHandler = (error: Error) => void; /** * Protocol Peer * * Manages bidirectional stream-json communication with Claude CLI. * Handles: * - Reading and parsing stream-json messages from stdout * - Routing control requests to the client * - Sending control responses to stdin * - Sending user messages and SDK control requests * * @example * ```typescript * const peer = new ProtocolPeer(stdin, stdout, client); * * // Handle non-control messages * peer.onMessage((msg) => { * if (msg.type === 'assistant') { * console.log('Assistant:', msg.message.content); * } * }); * * // Start the background read loop * peer.start(); * * // Initialize hooks * await peer.initialize({ preToolUse: { enabled: true } }); * * // Send user message * await peer.sendUserMessage('List files in the current directory'); * * // Clean up * await peer.stop(); * ``` */ export declare class ProtocolPeer { private readonly stdin; private readonly stdout; private readonly client; private messageHandlers; private errorHandlers; private readLoopPromise; private stopRequested; /** * Create a new ProtocolPeer * * @param stdin - Writable stream to send messages to Claude CLI * @param stdout - Readable stream to receive messages from Claude CLI * @param client - Client to handle control requests */ constructor(stdin: Writable, stdout: Readable, client: IProtocolClient); /** * Register a message handler * * Called for each non-control message (system, user, assistant, tool_use, result). * * @param handler - Message handler callback */ onMessage(handler: MessageHandler): void; /** * Register an error handler * * Called when an error occurs during message processing. * * @param handler - Error handler callback */ onError(handler: ErrorHandler): void; /** * Start the background read loop * * Begins reading messages from stdout and routing them appropriately. * Call this before sending any messages to Claude CLI. */ start(): void; /** * Stop the background read loop * * Waits for the read loop to finish processing current message. */ stop(): Promise; /** * Initialize the protocol * * Sends initialization request with hook configuration. * Call this after starting the read loop. * * @param hooks - Hook configuration * * @example * ```typescript * await peer.initialize({ * preToolUse: { enabled: true } * }); * ``` */ initialize(hooks: HookConfig): Promise; /** * Set permission mode * * Updates the permission mode for tool approvals. * * @param mode - Permission mode ('ask' or 'bypass_permissions') * @param destination - Where to store the permission ('session' or 'global') * * @example * ```typescript * // Bypass permissions for this session * await peer.setPermissionMode('bypass_permissions', 'session'); * ``` */ setPermissionMode(mode: PermissionMode, destination?: 'session' | 'global'): Promise; /** * Send a user message to Claude CLI * * @param content - Message content (string or content blocks) * @param sessionId - Optional session ID * * @example * ```typescript * await peer.sendUserMessage('List files'); * ``` */ sendUserMessage(content: string | Array<{ type: string; [key: string]: unknown; }>, sessionId?: string): Promise; /** * Send interrupt signal to Claude CLI * * Sends a control message requesting Claude to stop the current operation. * The interrupt is "graceful" - Claude decides how to handle it, typically * finishing the current tool operation before stopping. * * @example * ```typescript * // User wants to cancel the current task * await peer.sendInterrupt(); * ``` */ sendInterrupt(): Promise; /** * Send a control response to Claude CLI * * Internal method used by the read loop to send responses. * * @param requestId - Request ID from control request * @param response - Control response (success or error) */ private sendControlResponse; /** * Write a message to stdin * * @param message - Message to write */ private writeMessage; /** * Background read loop * * Reads messages from stdout and routes them appropriately. */ private runReadLoop; /** * Handle a received message * * Routes control requests to client, emits other messages to handlers. * * @param message - Received message */ private handleMessage; /** * Handle a control request message * * Routes the request to the client and sends the response. * * @param message - Control request message */ private handleControlRequestMessage; /** * Emit a message to all registered handlers * * @param message - Message to emit */ private emitMessage; /** * Emit an error to all registered handlers * * @param error - Error to emit */ private emitError; } //# sourceMappingURL=protocol-peer.d.ts.map