routeStream method

Stream<AIStreamChunk> routeStream(
  1. List<AIMessage> messages, {
  2. int? maxTokens,
  3. double? temperature,
  4. AICapability? requiredCapability,
  5. List<AITool>? tools,
})

Routes a streaming request to the best available provider.

Implementation

Stream<AIStreamChunk> routeStream(
  List<AIMessage> messages, {
  int? maxTokens,
  double? temperature,
  AICapability? requiredCapability,
  List<AITool>? tools,
}) async* {
  final selectedProviders = _selectProviders(requiredCapability);
  if (selectedProviders.isEmpty) {
    throw StateError('No providers available for the requested capability');
  }

  AIError? lastError;

  for (final provider in selectedProviders) {
    final breaker = _circuitBreakers[provider.name];
    if (breaker != null && !breaker.isAllowed) continue;

    bool hasYielded = false;
    try {
      final stream = provider.completeStream(
        messages,
        maxTokens: maxTokens,
        temperature: temperature,
        tools: tools,
      );

      await for (final chunk in stream) {
        hasYielded = true;
        yield chunk;
      }

      if (breaker != null) breaker.recordSuccess();
      return; // Successfully completed
    } on AIError catch (e) {
      lastError = e;
      if (breaker != null) breaker.recordFailure();

      // If we already yielded chunks, we can't cleanly fallback
      // Or if the error is fatal (auth, content filter)
      if (hasYielded || !e.isRetryable) {
        rethrow;
      }
      // If it's a network error before yielding, try the next provider
      continue;
    } catch (e) {
      if (breaker != null) breaker.recordFailure();
      rethrow;
    }
  }

  throw lastError ??
      AIUnknownError(
        provider: 'AIRouter',
        message: 'All providers failed to stream',
      );
}