@actuallab/rpc 14.1.5 → 14.3.5

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.
package/dist/index.d.cts CHANGED
@@ -371,6 +371,7 @@ declare class RpcWebSocketConnection implements RpcConnection {
371
371
  sendBinaryBatch(messages: Uint8Array[]): void;
372
372
  /** Split a binary frame using the format (compact-aware) or default splitter. */
373
373
  private _splitBinary;
374
+ private _dispatchBinary;
374
375
  close(code?: number, reason?: string): void;
375
376
  private _sendRaw;
376
377
  private _flush;
@@ -591,10 +592,16 @@ declare class RpcError extends Error {
591
592
  }
592
593
  declare const REMOTE_EXCEPTION_TYPE_REF = "ActualLab.Serialization.RemoteException, ActualLab.Core";
593
594
  /** Wire shape of .NET `ExceptionInfo` for a JS error sent to a .NET peer. */
594
- declare function toExceptionInfo(error: unknown): {
595
+ interface RpcExceptionInfo {
595
596
  TypeRef: string;
596
597
  Message: string;
597
- };
598
+ }
599
+ /** Reshapes what a remote peer gets to see of a local error. */
600
+ type RpcErrorFilter = (error: unknown, info: RpcExceptionInfo) => RpcExceptionInfo;
601
+ /** Opt-in {@link RpcErrorFilter} that hides the original message — Node error
602
+ * text routinely embeds absolute paths, connection strings and SQL. */
603
+ declare const genericErrorFilter: RpcErrorFilter;
604
+ declare function toExceptionInfo(error: unknown, filter?: RpcErrorFilter): RpcExceptionInfo;
598
605
 
599
606
  /**
600
607
  * Compresses and decompresses monotonically increasing sequences of
@@ -772,6 +779,11 @@ declare class RpcSystemCallSender {
772
779
  private readonly _ackEndArgs;
773
780
  private static readonly NO_ERROR;
774
781
  registry?: RpcMethodRegistry;
782
+ /** Applied to every error this hub sends to a remote peer. Undefined means
783
+ * pass through, i.e. the peer sees the original message — set it (e.g. to
784
+ * {@link genericErrorFilter}) on a TS-hosted server, where handler errors
785
+ * would otherwise disclose internal details to unauthenticated callers. */
786
+ errorFilter?: RpcErrorFilter;
775
787
  protected _send(conn: RpcConnection, format: RpcSerializationFormat, envelope: RpcMessage, args?: unknown[]): void;
776
788
  handshake(conn: RpcConnection, format: RpcSerializationFormat, peerId: string, hubId: string, index: number): void;
777
789
  ok(conn: RpcConnection, format: RpcSerializationFormat, relatedId: number, result: unknown): void;
@@ -910,13 +922,22 @@ declare class RpcSharedObjectTracker {
910
922
  disconnectAll(): void;
911
923
  }
912
924
 
925
+ /** The `c` / `p` query parameter pair for one connect attempt. */
926
+ interface RpcReconnectProofParameters {
927
+ counter: string;
928
+ proof: string;
929
+ }
930
+ declare function isReconnectProofSupported(): boolean;
931
+ declare function computeReconnectProof(secret: string, clientId: string, counterText: string): Promise<string>;
932
+
913
933
  /** WebSocket close code sent by the server when the client's serialization format is unsupported. */
914
934
  declare const RPC_CLOSE_CODE_UNSUPPORTED_FORMAT = 4001;
915
935
  /** Builds the WebSocket connection URL for an RpcClientPeer. */
916
936
  type RpcConnectionUrlResolver = (peer: RpcClientPeer) => string | Promise<string>;
917
937
  /** Default connection URL provider — sets `clientId` and `f` query parameters,
918
938
  * replacing any existing values to keep the wire format consistent with the
919
- * peer's actual `serializationFormat`. */
939
+ * peer's actual `serializationFormat`. Adds the reconnect proof (`c` + `p`)
940
+ * once the peer holds a server-issued secret. */
920
941
  declare const defaultConnectionUrlResolver: RpcConnectionUrlResolver;
921
942
  /** Options for RpcPeer.call() — allows custom call types and cancellation. */
922
943
  interface RpcCallOptions {
@@ -937,6 +958,8 @@ interface RemoteHandshake {
937
958
  RemoteHubId?: string;
938
959
  ProtocolVersion?: number;
939
960
  Index?: number;
961
+ /** Server-issued reconnect secret. Server→client only — a client never sends one. */
962
+ Secret?: string;
940
963
  }
941
964
  /** Base class for RPC peers — handles bidirectional message dispatch. */
942
965
  declare abstract class RpcPeer {
@@ -1016,6 +1039,7 @@ declare abstract class RpcPeer {
1016
1039
  /** Override in subclasses to handle the remote peer's handshake response. */
1017
1040
  protected _onHandshakeReceived(_handshake: RemoteHandshake): void;
1018
1041
  private _handleMessage;
1042
+ private _processMessage;
1019
1043
  private _handleInbound;
1020
1044
  /** Start sending `$sys.KeepAlive` pings and arm the silence watchdog.
1021
1045
  * Called when the peer transitions into `Connected` (after handshake).
@@ -1058,6 +1082,16 @@ declare class RpcClientPeer extends RpcPeer {
1058
1082
  private _lastRemotePeerId;
1059
1083
  private _pendingHandshake;
1060
1084
  private _reconnectsAt;
1085
+ /** Server-issued reconnect secret, from the most recent handshake that
1086
+ * carried one. In-memory only — never localStorage/sessionStorage/cookie.
1087
+ * A tab reload mints a new `clientId`, so a persisted secret would be
1088
+ * useless anyway. */
1089
+ private _reconnectSecret;
1090
+ /** Incremented once per *connect attempt*, in `computeReconnectProof()`. A
1091
+ * failed attempt still burns its value: the server may have advanced its
1092
+ * own counter at the gate before the connection died, and reusing the
1093
+ * value would then be rejected forever. */
1094
+ private _reconnectCounter;
1061
1095
  /** Base64url-encoded peer ID — matches .NET's RpcClientPeer.ClientId (Guid.ToBase64Url). */
1062
1096
  readonly clientId: string;
1063
1097
  /** Builds the WebSocket URL for this peer. Replace to customize URL construction. */
@@ -1117,6 +1151,11 @@ declare class RpcClientPeer extends RpcPeer {
1117
1151
  * promise. Customize `peer.webSocketFactory` first if you need a
1118
1152
  * non-default WebSocket constructor. */
1119
1153
  start(): void;
1154
+ /** Builds the `c` / `p` connect-URL parameters proving possession of the
1155
+ * server-issued reconnect secret, or `undefined` when there is no secret
1156
+ * yet or WebCrypto is unavailable. Consumes one counter value per proof
1157
+ * produced, so call it exactly once per connect attempt. */
1158
+ computeReconnectProof(): Promise<RpcReconnectProofParameters | undefined>;
1120
1159
  /** The reconnect loop itself. Exposed as `protected` so subclasses (and
1121
1160
  * `start()`) can drive it; public callers should use {@link start}. */
1122
1161
  protected run(): Promise<void>;
@@ -1286,7 +1325,12 @@ declare class RpcStreamSender<T> implements IRpcObject {
1286
1325
  get lastAckIndex(): number;
1287
1326
  get skipCount(): number;
1288
1327
  get minRttMs(): number;
1289
- private _acks;
1328
+ /** Newest unprocessed ACK index; -1 means "nothing pending". */
1329
+ private _ackIndex;
1330
+ private _ackMustReset;
1331
+ /** Highest ACK index accepted so far — the monotonicity baseline a
1332
+ * non-reset ACK may not regress below. */
1333
+ private _maxAckIndex;
1290
1334
  private _whenAckReady;
1291
1335
  constructor(peer: RpcPeer, ackPeriod?: number, ackAdvance?: number, allowReconnect?: boolean, isRealTime?: boolean, canSkipTo?: (item: T) => boolean, sourceUsesAbortSignal?: boolean, bufferSize?: number);
1292
1336
  /** AbortSignal that is aborted when the sender is disconnected. */
@@ -1332,12 +1376,13 @@ declare class RpcStreamSender<T> implements IRpcObject {
1332
1376
  * in-flight window — real-time mode uses the extra space to pre-buffer.
1333
1377
  */
1334
1378
  private _run;
1335
- /** Drain all queued ACKs, returning the most recent one (or null if none).
1336
- * A reconnect's reset ACK may be drained in one batch with regular
1337
- * consumption ACKs the client sends right after it, so `mustReset` is
1338
- * OR-ed over the whole batch — the last ACK alone can't represent it. */
1379
+ private get _hasPendingAck();
1380
+ /** Consume the coalesced ACK state (or null if nothing is pending).
1381
+ * A reconnect's reset ACK may be coalesced with the regular consumption
1382
+ * ACKs the client sends right after it, so `mustReset` accumulates across
1383
+ * the whole batch — the newest ACK alone can't represent it. */
1339
1384
  private _tryProcessAcks;
1340
- /** Wait for the ACK queue to have at least one entry (or `_ended`). */
1385
+ /** Wait until an ACK is pending (or `_ended`). */
1341
1386
  private _waitAckReady;
1342
1387
  private _sampleRtt;
1343
1388
  reconnect(): void;
@@ -1469,6 +1514,9 @@ declare class RpcStream<T> implements AsyncIterable<T>, IRpcObject {
1469
1514
  [Symbol.asyncIterator](): AsyncIterator<T>;
1470
1515
  dispose(): void;
1471
1516
  private _complete;
1517
+ private _failProtocol;
1518
+ private _isBeyondAckWindow;
1519
+ private _ackWindowError;
1472
1520
  private _gapError;
1473
1521
  private _notifyConsumer;
1474
1522
  private _maybeSendAck;
@@ -1477,12 +1525,19 @@ declare class RpcStream<T> implements AsyncIterable<T>, IRpcObject {
1477
1525
  private _sendAckEnd;
1478
1526
  }
1479
1527
  /**
1480
- * Recursively walks a deserialized value and replaces any stream ref strings
1481
- * with live RpcStream<unknown> instances registered on the given peer.
1482
- * This handles nested stream refs inside complex return types (e.g. Table<T>
1483
- * containing RpcStream<Row<T>> fields serialized as "{hostId},{localId},{ackPeriod},{ackAdvance}").
1528
+ * Converts a wire value that *is* a stream reference — the comma-separated
1529
+ * string the text formats use, or the object shape the binary ones use — into a
1530
+ * live remote {@link RpcStream}. Returns `null` when the value is not a
1531
+ * reference.
1532
+ *
1533
+ * Call results are deliberately **not** scanned for stream references. A
1534
+ * TypeScript client has no typed method definitions, so "is this string a
1535
+ * stream ref?" can only be a shape heuristic, and ordinary data matches it
1536
+ * constantly ("1,2,3,4", a CSV row, a coordinate tuple). Deciding that a value
1537
+ * is a stream is therefore the caller's job — it is the only side that knows
1538
+ * which positions carry streams.
1484
1539
  */
1485
- declare function resolveStreamRefs(value: unknown, peer: RpcPeer): unknown;
1540
+ declare function toRpcStream<T>(value: unknown, peer: RpcPeer): RpcStream<T> | null;
1486
1541
 
1487
1542
  declare class RpcRefBuilder {
1488
1543
  /** Build a client peer ref from a WebSocket URL, optionally baking in the
@@ -1559,4 +1614,4 @@ declare function xxh3_64str(input: string, seed?: bigint): bigint;
1559
1614
  */
1560
1615
  declare function computeMethodHash(methodName: string): number;
1561
1616
 
1562
- export { ARG_DELIMITER, ENVELOPE_DELIMITER, FRAME_DELIMITER, type IRpcObject, IncreasingSeqCompressor, type MethodMeta, REMOTE_EXCEPTION_TYPE_REF, RPC_CLOSE_CODE_UNSUPPORTED_FORMAT, type RemoteHandshake, type RpcCallOptions, RpcCallStage, RpcCallTimeouts, RpcCallTypeId, RpcClientPeer, RpcClientPeerReconnectDelayer, type RpcConnection, RpcConnectionState, type RpcConnectionUrlResolver, type RpcDeserializedMessage, type RpcDispatchContext, RpcError, RpcHub, RpcInboundCall, RpcInboundCallTracker, RpcJsonSerializationFormat, RpcLimits, type RpcLogScope, type RpcMessage, RpcMessageChannelConnection, RpcMessagePackCompactSerializationFormat, RpcMessagePackSerializationFormat, type RpcMethodDef, type RpcMethodDefInput, RpcMethodRegistry, type RpcObjectId, RpcObjectKind, RpcOutboundCall, RpcOutboundCallTracker, RpcPeer, type RpcPeerFactory, type RpcPeerState, RpcPeerStateKind, RpcPeerStateMonitor, type RpcReceivedMessage, RpcRefBuilder, RpcRemoteExecutionMode, RpcRemoteObjectTracker, RpcSerializationFormat, RpcSerializationFormatResolver, RpcServerPeer, type RpcServiceDef, RpcServiceHost, type RpcServiceImpl, RpcSharedObjectTracker, RpcStream, type RpcStreamOptions, type RpcStreamRef, RpcStreamSender, type RpcStreamSource, RpcSystemCallHandler, RpcSystemCallSender, RpcSystemCalls, RpcType, RpcWebSocketConnection, type RpcWireData, type ServiceMeta, type WebSocketLike, type WebSocketServer, WebSocketState, computeMethodHash, createBinaryEncoder, createMessageChannelPair, createRpcClient, defaultBinaryDecoder, defaultBinaryEncoder, defaultConnectionUrlResolver, defineRpcService, deserializeBinaryMessage, deserializeCompactBinaryMessage, deserializeMessage, getLogs, getMethodsMeta, getServiceMeta, getStateDescription, isConnected, likelyConnected, parseStreamRef, readPolymorphismMarker, resolveStreamRefs, rpcMethod, rpcService, serializeBinaryFrame, serializeBinaryMessage, serializeCompactBinaryMessage, serializeFrame, serializeMessage, splitBinaryFrame, splitCompactBinaryFrame, splitFrame, toExceptionInfo, wireMethodName, xxh3_64, xxh3_64str };
1617
+ export { ARG_DELIMITER, ENVELOPE_DELIMITER, FRAME_DELIMITER, type IRpcObject, IncreasingSeqCompressor, type MethodMeta, REMOTE_EXCEPTION_TYPE_REF, RPC_CLOSE_CODE_UNSUPPORTED_FORMAT, type RemoteHandshake, type RpcCallOptions, RpcCallStage, RpcCallTimeouts, RpcCallTypeId, RpcClientPeer, RpcClientPeerReconnectDelayer, type RpcConnection, RpcConnectionState, type RpcConnectionUrlResolver, type RpcDeserializedMessage, type RpcDispatchContext, RpcError, type RpcErrorFilter, type RpcExceptionInfo, RpcHub, RpcInboundCall, RpcInboundCallTracker, RpcJsonSerializationFormat, RpcLimits, type RpcLogScope, type RpcMessage, RpcMessageChannelConnection, RpcMessagePackCompactSerializationFormat, RpcMessagePackSerializationFormat, type RpcMethodDef, type RpcMethodDefInput, RpcMethodRegistry, type RpcObjectId, RpcObjectKind, RpcOutboundCall, RpcOutboundCallTracker, RpcPeer, type RpcPeerFactory, type RpcPeerState, RpcPeerStateKind, RpcPeerStateMonitor, type RpcReceivedMessage, type RpcReconnectProofParameters, RpcRefBuilder, RpcRemoteExecutionMode, RpcRemoteObjectTracker, RpcSerializationFormat, RpcSerializationFormatResolver, RpcServerPeer, type RpcServiceDef, RpcServiceHost, type RpcServiceImpl, RpcSharedObjectTracker, RpcStream, type RpcStreamOptions, type RpcStreamRef, RpcStreamSender, type RpcStreamSource, RpcSystemCallHandler, RpcSystemCallSender, RpcSystemCalls, RpcType, RpcWebSocketConnection, type RpcWireData, type ServiceMeta, type WebSocketLike, type WebSocketServer, WebSocketState, computeMethodHash, computeReconnectProof, createBinaryEncoder, createMessageChannelPair, createRpcClient, defaultBinaryDecoder, defaultBinaryEncoder, defaultConnectionUrlResolver, defineRpcService, deserializeBinaryMessage, deserializeCompactBinaryMessage, deserializeMessage, genericErrorFilter, getLogs, getMethodsMeta, getServiceMeta, getStateDescription, isConnected, isReconnectProofSupported, likelyConnected, parseStreamRef, readPolymorphismMarker, rpcMethod, rpcService, serializeBinaryFrame, serializeBinaryMessage, serializeCompactBinaryMessage, serializeFrame, serializeMessage, splitBinaryFrame, splitCompactBinaryFrame, splitFrame, toExceptionInfo, toRpcStream, wireMethodName, xxh3_64, xxh3_64str };
package/dist/index.d.ts CHANGED
@@ -371,6 +371,7 @@ declare class RpcWebSocketConnection implements RpcConnection {
371
371
  sendBinaryBatch(messages: Uint8Array[]): void;
372
372
  /** Split a binary frame using the format (compact-aware) or default splitter. */
373
373
  private _splitBinary;
374
+ private _dispatchBinary;
374
375
  close(code?: number, reason?: string): void;
375
376
  private _sendRaw;
376
377
  private _flush;
@@ -591,10 +592,16 @@ declare class RpcError extends Error {
591
592
  }
592
593
  declare const REMOTE_EXCEPTION_TYPE_REF = "ActualLab.Serialization.RemoteException, ActualLab.Core";
593
594
  /** Wire shape of .NET `ExceptionInfo` for a JS error sent to a .NET peer. */
594
- declare function toExceptionInfo(error: unknown): {
595
+ interface RpcExceptionInfo {
595
596
  TypeRef: string;
596
597
  Message: string;
597
- };
598
+ }
599
+ /** Reshapes what a remote peer gets to see of a local error. */
600
+ type RpcErrorFilter = (error: unknown, info: RpcExceptionInfo) => RpcExceptionInfo;
601
+ /** Opt-in {@link RpcErrorFilter} that hides the original message — Node error
602
+ * text routinely embeds absolute paths, connection strings and SQL. */
603
+ declare const genericErrorFilter: RpcErrorFilter;
604
+ declare function toExceptionInfo(error: unknown, filter?: RpcErrorFilter): RpcExceptionInfo;
598
605
 
599
606
  /**
600
607
  * Compresses and decompresses monotonically increasing sequences of
@@ -772,6 +779,11 @@ declare class RpcSystemCallSender {
772
779
  private readonly _ackEndArgs;
773
780
  private static readonly NO_ERROR;
774
781
  registry?: RpcMethodRegistry;
782
+ /** Applied to every error this hub sends to a remote peer. Undefined means
783
+ * pass through, i.e. the peer sees the original message — set it (e.g. to
784
+ * {@link genericErrorFilter}) on a TS-hosted server, where handler errors
785
+ * would otherwise disclose internal details to unauthenticated callers. */
786
+ errorFilter?: RpcErrorFilter;
775
787
  protected _send(conn: RpcConnection, format: RpcSerializationFormat, envelope: RpcMessage, args?: unknown[]): void;
776
788
  handshake(conn: RpcConnection, format: RpcSerializationFormat, peerId: string, hubId: string, index: number): void;
777
789
  ok(conn: RpcConnection, format: RpcSerializationFormat, relatedId: number, result: unknown): void;
@@ -910,13 +922,22 @@ declare class RpcSharedObjectTracker {
910
922
  disconnectAll(): void;
911
923
  }
912
924
 
925
+ /** The `c` / `p` query parameter pair for one connect attempt. */
926
+ interface RpcReconnectProofParameters {
927
+ counter: string;
928
+ proof: string;
929
+ }
930
+ declare function isReconnectProofSupported(): boolean;
931
+ declare function computeReconnectProof(secret: string, clientId: string, counterText: string): Promise<string>;
932
+
913
933
  /** WebSocket close code sent by the server when the client's serialization format is unsupported. */
914
934
  declare const RPC_CLOSE_CODE_UNSUPPORTED_FORMAT = 4001;
915
935
  /** Builds the WebSocket connection URL for an RpcClientPeer. */
916
936
  type RpcConnectionUrlResolver = (peer: RpcClientPeer) => string | Promise<string>;
917
937
  /** Default connection URL provider — sets `clientId` and `f` query parameters,
918
938
  * replacing any existing values to keep the wire format consistent with the
919
- * peer's actual `serializationFormat`. */
939
+ * peer's actual `serializationFormat`. Adds the reconnect proof (`c` + `p`)
940
+ * once the peer holds a server-issued secret. */
920
941
  declare const defaultConnectionUrlResolver: RpcConnectionUrlResolver;
921
942
  /** Options for RpcPeer.call() — allows custom call types and cancellation. */
922
943
  interface RpcCallOptions {
@@ -937,6 +958,8 @@ interface RemoteHandshake {
937
958
  RemoteHubId?: string;
938
959
  ProtocolVersion?: number;
939
960
  Index?: number;
961
+ /** Server-issued reconnect secret. Server→client only — a client never sends one. */
962
+ Secret?: string;
940
963
  }
941
964
  /** Base class for RPC peers — handles bidirectional message dispatch. */
942
965
  declare abstract class RpcPeer {
@@ -1016,6 +1039,7 @@ declare abstract class RpcPeer {
1016
1039
  /** Override in subclasses to handle the remote peer's handshake response. */
1017
1040
  protected _onHandshakeReceived(_handshake: RemoteHandshake): void;
1018
1041
  private _handleMessage;
1042
+ private _processMessage;
1019
1043
  private _handleInbound;
1020
1044
  /** Start sending `$sys.KeepAlive` pings and arm the silence watchdog.
1021
1045
  * Called when the peer transitions into `Connected` (after handshake).
@@ -1058,6 +1082,16 @@ declare class RpcClientPeer extends RpcPeer {
1058
1082
  private _lastRemotePeerId;
1059
1083
  private _pendingHandshake;
1060
1084
  private _reconnectsAt;
1085
+ /** Server-issued reconnect secret, from the most recent handshake that
1086
+ * carried one. In-memory only — never localStorage/sessionStorage/cookie.
1087
+ * A tab reload mints a new `clientId`, so a persisted secret would be
1088
+ * useless anyway. */
1089
+ private _reconnectSecret;
1090
+ /** Incremented once per *connect attempt*, in `computeReconnectProof()`. A
1091
+ * failed attempt still burns its value: the server may have advanced its
1092
+ * own counter at the gate before the connection died, and reusing the
1093
+ * value would then be rejected forever. */
1094
+ private _reconnectCounter;
1061
1095
  /** Base64url-encoded peer ID — matches .NET's RpcClientPeer.ClientId (Guid.ToBase64Url). */
1062
1096
  readonly clientId: string;
1063
1097
  /** Builds the WebSocket URL for this peer. Replace to customize URL construction. */
@@ -1117,6 +1151,11 @@ declare class RpcClientPeer extends RpcPeer {
1117
1151
  * promise. Customize `peer.webSocketFactory` first if you need a
1118
1152
  * non-default WebSocket constructor. */
1119
1153
  start(): void;
1154
+ /** Builds the `c` / `p` connect-URL parameters proving possession of the
1155
+ * server-issued reconnect secret, or `undefined` when there is no secret
1156
+ * yet or WebCrypto is unavailable. Consumes one counter value per proof
1157
+ * produced, so call it exactly once per connect attempt. */
1158
+ computeReconnectProof(): Promise<RpcReconnectProofParameters | undefined>;
1120
1159
  /** The reconnect loop itself. Exposed as `protected` so subclasses (and
1121
1160
  * `start()`) can drive it; public callers should use {@link start}. */
1122
1161
  protected run(): Promise<void>;
@@ -1286,7 +1325,12 @@ declare class RpcStreamSender<T> implements IRpcObject {
1286
1325
  get lastAckIndex(): number;
1287
1326
  get skipCount(): number;
1288
1327
  get minRttMs(): number;
1289
- private _acks;
1328
+ /** Newest unprocessed ACK index; -1 means "nothing pending". */
1329
+ private _ackIndex;
1330
+ private _ackMustReset;
1331
+ /** Highest ACK index accepted so far — the monotonicity baseline a
1332
+ * non-reset ACK may not regress below. */
1333
+ private _maxAckIndex;
1290
1334
  private _whenAckReady;
1291
1335
  constructor(peer: RpcPeer, ackPeriod?: number, ackAdvance?: number, allowReconnect?: boolean, isRealTime?: boolean, canSkipTo?: (item: T) => boolean, sourceUsesAbortSignal?: boolean, bufferSize?: number);
1292
1336
  /** AbortSignal that is aborted when the sender is disconnected. */
@@ -1332,12 +1376,13 @@ declare class RpcStreamSender<T> implements IRpcObject {
1332
1376
  * in-flight window — real-time mode uses the extra space to pre-buffer.
1333
1377
  */
1334
1378
  private _run;
1335
- /** Drain all queued ACKs, returning the most recent one (or null if none).
1336
- * A reconnect's reset ACK may be drained in one batch with regular
1337
- * consumption ACKs the client sends right after it, so `mustReset` is
1338
- * OR-ed over the whole batch — the last ACK alone can't represent it. */
1379
+ private get _hasPendingAck();
1380
+ /** Consume the coalesced ACK state (or null if nothing is pending).
1381
+ * A reconnect's reset ACK may be coalesced with the regular consumption
1382
+ * ACKs the client sends right after it, so `mustReset` accumulates across
1383
+ * the whole batch — the newest ACK alone can't represent it. */
1339
1384
  private _tryProcessAcks;
1340
- /** Wait for the ACK queue to have at least one entry (or `_ended`). */
1385
+ /** Wait until an ACK is pending (or `_ended`). */
1341
1386
  private _waitAckReady;
1342
1387
  private _sampleRtt;
1343
1388
  reconnect(): void;
@@ -1469,6 +1514,9 @@ declare class RpcStream<T> implements AsyncIterable<T>, IRpcObject {
1469
1514
  [Symbol.asyncIterator](): AsyncIterator<T>;
1470
1515
  dispose(): void;
1471
1516
  private _complete;
1517
+ private _failProtocol;
1518
+ private _isBeyondAckWindow;
1519
+ private _ackWindowError;
1472
1520
  private _gapError;
1473
1521
  private _notifyConsumer;
1474
1522
  private _maybeSendAck;
@@ -1477,12 +1525,19 @@ declare class RpcStream<T> implements AsyncIterable<T>, IRpcObject {
1477
1525
  private _sendAckEnd;
1478
1526
  }
1479
1527
  /**
1480
- * Recursively walks a deserialized value and replaces any stream ref strings
1481
- * with live RpcStream<unknown> instances registered on the given peer.
1482
- * This handles nested stream refs inside complex return types (e.g. Table<T>
1483
- * containing RpcStream<Row<T>> fields serialized as "{hostId},{localId},{ackPeriod},{ackAdvance}").
1528
+ * Converts a wire value that *is* a stream reference — the comma-separated
1529
+ * string the text formats use, or the object shape the binary ones use — into a
1530
+ * live remote {@link RpcStream}. Returns `null` when the value is not a
1531
+ * reference.
1532
+ *
1533
+ * Call results are deliberately **not** scanned for stream references. A
1534
+ * TypeScript client has no typed method definitions, so "is this string a
1535
+ * stream ref?" can only be a shape heuristic, and ordinary data matches it
1536
+ * constantly ("1,2,3,4", a CSV row, a coordinate tuple). Deciding that a value
1537
+ * is a stream is therefore the caller's job — it is the only side that knows
1538
+ * which positions carry streams.
1484
1539
  */
1485
- declare function resolveStreamRefs(value: unknown, peer: RpcPeer): unknown;
1540
+ declare function toRpcStream<T>(value: unknown, peer: RpcPeer): RpcStream<T> | null;
1486
1541
 
1487
1542
  declare class RpcRefBuilder {
1488
1543
  /** Build a client peer ref from a WebSocket URL, optionally baking in the
@@ -1559,4 +1614,4 @@ declare function xxh3_64str(input: string, seed?: bigint): bigint;
1559
1614
  */
1560
1615
  declare function computeMethodHash(methodName: string): number;
1561
1616
 
1562
- export { ARG_DELIMITER, ENVELOPE_DELIMITER, FRAME_DELIMITER, type IRpcObject, IncreasingSeqCompressor, type MethodMeta, REMOTE_EXCEPTION_TYPE_REF, RPC_CLOSE_CODE_UNSUPPORTED_FORMAT, type RemoteHandshake, type RpcCallOptions, RpcCallStage, RpcCallTimeouts, RpcCallTypeId, RpcClientPeer, RpcClientPeerReconnectDelayer, type RpcConnection, RpcConnectionState, type RpcConnectionUrlResolver, type RpcDeserializedMessage, type RpcDispatchContext, RpcError, RpcHub, RpcInboundCall, RpcInboundCallTracker, RpcJsonSerializationFormat, RpcLimits, type RpcLogScope, type RpcMessage, RpcMessageChannelConnection, RpcMessagePackCompactSerializationFormat, RpcMessagePackSerializationFormat, type RpcMethodDef, type RpcMethodDefInput, RpcMethodRegistry, type RpcObjectId, RpcObjectKind, RpcOutboundCall, RpcOutboundCallTracker, RpcPeer, type RpcPeerFactory, type RpcPeerState, RpcPeerStateKind, RpcPeerStateMonitor, type RpcReceivedMessage, RpcRefBuilder, RpcRemoteExecutionMode, RpcRemoteObjectTracker, RpcSerializationFormat, RpcSerializationFormatResolver, RpcServerPeer, type RpcServiceDef, RpcServiceHost, type RpcServiceImpl, RpcSharedObjectTracker, RpcStream, type RpcStreamOptions, type RpcStreamRef, RpcStreamSender, type RpcStreamSource, RpcSystemCallHandler, RpcSystemCallSender, RpcSystemCalls, RpcType, RpcWebSocketConnection, type RpcWireData, type ServiceMeta, type WebSocketLike, type WebSocketServer, WebSocketState, computeMethodHash, createBinaryEncoder, createMessageChannelPair, createRpcClient, defaultBinaryDecoder, defaultBinaryEncoder, defaultConnectionUrlResolver, defineRpcService, deserializeBinaryMessage, deserializeCompactBinaryMessage, deserializeMessage, getLogs, getMethodsMeta, getServiceMeta, getStateDescription, isConnected, likelyConnected, parseStreamRef, readPolymorphismMarker, resolveStreamRefs, rpcMethod, rpcService, serializeBinaryFrame, serializeBinaryMessage, serializeCompactBinaryMessage, serializeFrame, serializeMessage, splitBinaryFrame, splitCompactBinaryFrame, splitFrame, toExceptionInfo, wireMethodName, xxh3_64, xxh3_64str };
1617
+ export { ARG_DELIMITER, ENVELOPE_DELIMITER, FRAME_DELIMITER, type IRpcObject, IncreasingSeqCompressor, type MethodMeta, REMOTE_EXCEPTION_TYPE_REF, RPC_CLOSE_CODE_UNSUPPORTED_FORMAT, type RemoteHandshake, type RpcCallOptions, RpcCallStage, RpcCallTimeouts, RpcCallTypeId, RpcClientPeer, RpcClientPeerReconnectDelayer, type RpcConnection, RpcConnectionState, type RpcConnectionUrlResolver, type RpcDeserializedMessage, type RpcDispatchContext, RpcError, type RpcErrorFilter, type RpcExceptionInfo, RpcHub, RpcInboundCall, RpcInboundCallTracker, RpcJsonSerializationFormat, RpcLimits, type RpcLogScope, type RpcMessage, RpcMessageChannelConnection, RpcMessagePackCompactSerializationFormat, RpcMessagePackSerializationFormat, type RpcMethodDef, type RpcMethodDefInput, RpcMethodRegistry, type RpcObjectId, RpcObjectKind, RpcOutboundCall, RpcOutboundCallTracker, RpcPeer, type RpcPeerFactory, type RpcPeerState, RpcPeerStateKind, RpcPeerStateMonitor, type RpcReceivedMessage, type RpcReconnectProofParameters, RpcRefBuilder, RpcRemoteExecutionMode, RpcRemoteObjectTracker, RpcSerializationFormat, RpcSerializationFormatResolver, RpcServerPeer, type RpcServiceDef, RpcServiceHost, type RpcServiceImpl, RpcSharedObjectTracker, RpcStream, type RpcStreamOptions, type RpcStreamRef, RpcStreamSender, type RpcStreamSource, RpcSystemCallHandler, RpcSystemCallSender, RpcSystemCalls, RpcType, RpcWebSocketConnection, type RpcWireData, type ServiceMeta, type WebSocketLike, type WebSocketServer, WebSocketState, computeMethodHash, computeReconnectProof, createBinaryEncoder, createMessageChannelPair, createRpcClient, defaultBinaryDecoder, defaultBinaryEncoder, defaultConnectionUrlResolver, defineRpcService, deserializeBinaryMessage, deserializeCompactBinaryMessage, deserializeMessage, genericErrorFilter, getLogs, getMethodsMeta, getServiceMeta, getStateDescription, isConnected, isReconnectProofSupported, likelyConnected, parseStreamRef, readPolymorphismMarker, rpcMethod, rpcService, serializeBinaryFrame, serializeBinaryMessage, serializeCompactBinaryMessage, serializeFrame, serializeMessage, splitBinaryFrame, splitCompactBinaryFrame, splitFrame, toExceptionInfo, toRpcStream, wireMethodName, xxh3_64, xxh3_64str };