export type AftRpcEndpoint = { port: number; token: string | null; }; export interface AftRpcCallOptions { signal?: AbortSignal; /** * Optional gate over WARM (non-placeholder) responses. With multiple RPC * servers alive for one project hash (multi-project hosts, stale long-lived * processes), a warm response can describe ANOTHER project's bridge * (cross-project contamination). Return false to skip that response and * keep trying other ports instead of returning it — so a stray server can't * mask the right one. Skipped responses are never cached as the good port * and never returned; if only strays and placeholders answer, the * placeholder wins. */ accept?: (result: unknown) => boolean; /** * Internal one-hop guard for verified-directory redirects. A redirected * call must never redirect again (placeholder chains would otherwise * ping-pong between two bridgeless instances). */ noRedirect?: boolean; } export declare function subscribeRpcRedirects(listener: (from: string, to: string) => void): () => void; export declare function __resetRpcRedirectsForTest(): void; export declare function __recordRpcRedirectForTest(from: string, to: string): void; export declare class AftRpcClient { private port; private token; private portsDir; private legacyPortFile; private stalePortFailures; private storageDir; private directory; constructor(storageDir: string, directory: string); /** Call an RPC method. Retries port resolution if the server isn't ready yet. */ call>(method: string, params?: Record, options?: AftRpcCallOptions): Promise; /** * One-hop redirect to the instance that owns the session's bridge. Returns * null (caller keeps the placeholder) unless the redirected call produced a * warm response — a placeholder from the target is not an improvement, and * failures must not mask the original placeholder. */ private followVerifiedDirectory; private callOne; /** * Heuristic for "this response is the lazy-spawn placeholder, not the real * data." We treat any `not_initialized` status as a placeholder so the * client knows to try the next port (the warm one). */ private looksLikePlaceholder; /** Check if any RPC server is reachable. */ isAvailable(): Promise; /** Resolve the freshest live endpoint for the persistent TUI WebSocket. * Follows a learned verified-directory redirect so the socket subscribes * to the instance that owns the session's bridge (the one that will * actually push status-changed frames), not this directory's bridgeless * placeholder instance. */ resolveEndpoint(signal?: AbortSignal): Promise; /** * Discover all live RPC port files for this project. Tries the per-instance * directory first (v0.28.2+), then the single legacy `port` file (older * plugin versions in mixed deployments) as the final fallback candidate. */ private resolvePortInfos; private readAllPortFiles; /** Delete a port file whose owning process is provably dead (best-effort). */ private reclaimDeadPortFile; private parsePortFile; private portFailureKey; private clearPortFailure; private recordPortFailure; private healthCheck; private fetchWithTimeout; reset(): void; } //# sourceMappingURL=rpc-client.d.ts.map