complete method

  1. @override
Future<ChatResult> complete(
  1. ChatRequest request
)
override

Executes a non-streaming completion request.

Implementation

@override
Future<ChatResult> complete(ChatRequest request) async {
  String? system;
  final messages = <Map<String, dynamic>>[];

  for (final message in request.messages) {
    if (message.role == 'system') {
      system =
          system == null ? message.content : '$system\n${message.content}';
      continue;
    }
    messages.add({
      'role': message.role,
      'content': message.content,
    });
  }

  AiHttpResponse response;
  try {
    response = await httpClient.send(
      AiHttpRequest(
        method: 'POST',
        uri: endpoint,
        headers: {
          'Content-Type': 'application/json',
          'x-api-key': apiKey,
          'anthropic-version': '2023-06-01',
        },
        body: jsonEncode({
          'model': request.model,
          'messages': messages,
          'max_tokens': request.maxTokens ?? 1024,
          if (request.temperature != null) 'temperature': request.temperature,
          if (system != null && system.isNotEmpty) 'system': system,
          ...request.metadata,
        }),
      ),
    );
  } catch (error) {
    throw AiProviderException(
      providerId: id,
      message: 'Anthropic request transport failed',
      cause: error,
    );
  }

  if (!response.isSuccess) {
    throw AiProviderException(
      providerId: id,
      message: 'Anthropic request failed',
      statusCode: response.statusCode,
      responseBody: response.body,
    );
  }

  final payload = Map<String, dynamic>.from(response.jsonBody() as Map);
  final content = payload['content'] as List? ?? const [];
  final first = content.isEmpty
      ? const <String, dynamic>{}
      : Map<String, dynamic>.from(content.first as Map);
  final usage =
      Map<String, dynamic>.from(payload['usage'] as Map? ?? const {});

  return ChatResult(
    providerId: id,
    model: request.model,
    content: first['text']?.toString() ?? '',
    usage: ChatUsage(
      inputTokens: usage['input_tokens'] as int?,
      outputTokens: usage['output_tokens'] as int?,
    ),
    raw: payload,
  );
}