createMessageStream method

  1. @override
Stream<StreamEvent> createMessageStream({
  1. required List<Message> messages,
  2. required String systemPrompt,
  3. List<ToolDefinition> tools = const [],
  4. int? maxTokens,
})
override

Stream a message completion via the Anthropic Messages API.

Implementation

@override
Stream<StreamEvent> createMessageStream({
  required List<Message> messages,
  required String systemPrompt,
  List<ToolDefinition> tools = const [],
  int? maxTokens,
}) async* {
  final body = _buildRequestBody(
    messages: messages,
    systemPrompt: systemPrompt,
    tools: tools,
    maxTokens: maxTokens,
    stream: true,
  );

  final url = '${config.baseUrl}/v1/messages';
  final maskedKey = '${config.apiKey!.substring(0, 4)}...${config.apiKey!.substring(config.apiKey!.length - 4)}';
  SintSentinel.logger.d('AnthropicClient.createMessageStream: POST $url (key: $maskedKey)');

  final request = http.Request('POST', Uri.parse(url));
  request.headers.addAll(_headers);
  request.body = jsonEncode(body);

  final client = http.Client();
  final response = await SintSentinel.guard(
    () => client.send(request),
    tag: 'AnthropicClient.createMessageStream',
  );

  SintSentinel.logger.d('AnthropicClient response status: ${response.statusCode}');

  if (response.statusCode != 200) {
    final errorBody = await response.stream.bytesToString();
    client.close();
    SintSentinel.logger.e('AnthropicClient API error ${response.statusCode}: $errorBody');
    final classified = classifyApiError(
      statusCode: response.statusCode,
      body: errorBody,
      retryAfterHeader: response.headers['retry-after'],
    );
    yield ErrorEvent(message: classified.message, type: classified.type.name);
    return;
  }

  yield* _parseSSEStream(response.stream);
  client.close();
}