writeInbound method

Future<void> writeInbound(
  1. Object? frame, {
  2. AcpServerRoute route = const AcpConnectionRoute(),
  3. bool inferSessionRoute = true,
  4. bool validateClientResponseRoute = true,
})

Serializes one incoming transport frame into the application.

route records where a later response should be emitted. A client response must return through the same route as the agent request. By default a top-level params.sessionId refines a connection route; set inferSessionRoute to false when the transport contract deliberately routes a response elsewhere, such as an HTTP session/load response. Headerless transports may set validateClientResponseRoute to false after establishing that every response arrived over the same connection.

Implementation

Future<void> writeInbound(
  Object? frame, {
  AcpServerRoute route = const AcpConnectionRoute(),
  bool inferSessionRoute = true,
  bool validateClientResponseRoute = true,
}) {
  if (_isClosed) {
    return Future<void>.error(
      _closeReason ?? StateError('ACP server connection is closed'),
    );
  }
  if (frame is List<Object?> && !_allowBatches) {
    return Future<void>.error(
      StateError('JSON-RPC batches are not enabled for this connection'),
    );
  }
  final _InboundRouteChanges changes;
  try {
    changes = _recordInboundRoutes(
      frame,
      route,
      inferSessionRoute,
      validateClientResponseRoute,
    );
  } on Object catch (error, stackTrace) {
    return Future<void>.error(error, stackTrace);
  }

  final completer = Completer<void>();
  final Future<void> previous = _writeTail;
  _writeTail = () async {
    try {
      await previous;
    } on Object {
      // An individual failed write must not poison later serialized writes.
    }
    try {
      if (_isClosed) {
        changes.rollback(this);
        completer.completeError(
          _closeReason ?? StateError('ACP server connection is closed'),
        );
        return;
      }
      await _inbound.write(frame);
      changes.commit(this);
      completer.complete();
    } on Object catch (error, stackTrace) {
      changes.rollback(this);
      completer.completeError(error, stackTrace);
    }
  }();
  return completer.future;
}