import type { AgentConfig } from '../types/index.js'; export type MessageHandler = (msg: Record) => void; export declare class AgentWebSocketClient { private ws; private config; private heartbeatTimer; private reconnectTimer; private reconnectAttempts; private maxReconnectDelay; private running; private onMessage; private onAuthFailed?; private getAgentMetrics?; /** Pending flow command callbacks keyed by request ID */ private _flowCallbacks; constructor(config: AgentConfig, onMessage: MessageHandler, onAuthFailed?: (code: number, reason: string) => void); connect(): void; disconnect(): void; /** Register a callback to get agent metrics for heartbeat. */ setMetricsProvider(fn: () => Record): void; /** * Send a message to the API server. */ send(data: Record): boolean; /** * Send task progress event. */ sendProgress(taskId: string, event: string, data: Record): boolean; /** * Send task done event. */ sendTaskDone(taskId: string, result: Record): boolean; /** * Send task failed event. */ sendTaskFailed(taskId: string, error: string): boolean; /** * Send plan_ready event with full plan data. */ sendPlanReady(taskId: string, plan: { summary: string; contracts?: Array>; subtasks: Array>; }): boolean; /** * Send subtask_start event. */ sendSubtaskStart(taskId: string, subtask: { id: string; role: string; description: string; }): boolean; /** * Send subtask_done event with session result. */ sendSubtaskDone(taskId: string, session: { subtaskId: string; status: string; result?: string; durationMs?: number; sessionId?: string; }): boolean; /** * Send needs_input event when a subtask requires user input. */ sendNeedsInput(taskId: string, question: { subtaskId: string; question: string; options?: string[]; context?: string; }): boolean; /** * Send streaming PM text chunk (real-time token streaming). */ sendPMStream(taskId: string, text: string): boolean; /** * Send PM stream end marker (signals full response is complete). */ sendPMStreamEnd(taskId: string, messageId: string): boolean; /** * Send permission_request event when Claude Code asks for tool approval. */ sendPermissionRequest(taskId: string, data: { subtaskId: string; tool: string; detail: string; requestId: string; }): boolean; /** * Strip internal protocol markers from user-facing text. The executor protocol * asks the model to end with {"status":"NEEDS_INPUT"} — models often append it * to a conversational message instead of emitting it alone, and it leaked * verbatim into Discord/app chat (seen 2026-07-17 on Trương Phi's release ask). */ private static sanitizeUserText; /** * Send PM chat message (user-facing conversation). */ sendPMMessage(taskId: string, message: { sender: 'pm' | 'user' | 'system'; content: string; options?: string[]; context?: string; startedAt?: string; }): boolean; /** * Stream a text chunk back to the Chrome extension for an extension task. */ sendExtensionStream(code: string, taskId: string, text: string): boolean; /** * Signal that an extension task is complete. */ sendExtensionDone(code: string, taskId: string, result: Record): boolean; /** * Send progress update for an extension task. */ sendExtensionProgress(code: string, taskId: string, progress: number): boolean; /** * Send a custom-typed event to the extension (generic forwarder via extension_event action). */ sendExtensionEvent(code: string, event: Record): boolean; /** * Send a flow command to the extension and wait for the result. * Returns a Promise that resolves with the command result. */ sendFlowCommand(code: string, command: Record, timeout?: number): Promise>; /** * Resolve a pending flow command callback (called from message handler). * Returns true if the callback was found and resolved. */ resolveFlowCommand(id: string, result: Record): boolean; get isConnected(): boolean; private _connect; private _startHeartbeat; private _stopHeartbeat; private _scheduleReconnect; }