search method

  1. @override
Future<WebSearchResponse> search(
  1. WebSearchRequest request
)
override

Runs one search. Throws WebSearchException on failure so the chain advances to the next provider.

Implementation

@override
Future<WebSearchResponse> search(WebSearchRequest request) async {
  final apiKey = request.secrets[apiKeyName];
  if (apiKey == null || apiKey.isEmpty) {
    throw WebSearchException(id, 'TAVILY_API_KEY not found in secrets');
  }

  final response = await _send(
    this,
    request,
    () => request.client.post(
      Uri.parse(tavilySearchUrl),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $apiKey',
      },
      body: jsonEncode(buildRequestBody(request)),
    ),
  );

  if (response.statusCode < 200 || response.statusCode >= 300) {
    throw WebSearchException(
      id,
      'Tavily API error (${response.statusCode}): '
      '${_truncateErrorBody(response.body)}',
      response.statusCode,
    );
  }

  final Object? data = jsonDecode(response.body);
  if (data is! Map) {
    throw WebSearchException(id, 'Tavily returned malformed JSON');
  }
  final answer = data['answer'] as String?;
  final sources = _mapJsonResults(
    data['results'],
    request.count,
    (item) => (item['content'] as String?)?.trim(),
  );
  return WebSearchResponse(
    provider: id,
    answer: answer?.trim().isNotEmpty == true ? answer!.trim() : null,
    sources: sources,
  );
}