SDK Java 21 Open Source

JBrave: corrección de búsqueda que se puede inspeccionar.

Un caso técnico sobre convertir llamadas a Brave Search en flujos Java tipados y reproducibles: modelado de consulta, exportación de petición, control de ejecución, extracción de respuestas y JSON apto para fixtures.

Rol

Ingeniería liderada por fundador

Modelado de API, ejecución y documentación

Tipo

SDK Java open source

Tooling no oficial para Brave Search API

Estado

Alpha / 0.1.0

Modelo activo, API pública en evolución

Stack

Java 21

Maven, JDK HTTP client, Jackson 3

Evidencia

157 pruebas

Builders, fixtures, opciones y respuestas

Licencia

Apache 2.0

Proyecto independiente de YGBStudio

Problema

Una llamada a una API de búsqueda deja de ser solo una URL cuando entra a un sistema.

Un SDK de búsqueda debe hacer más que armar una URL: tiene límites de consulta, ejecución opcional, señales de cuota, éxito y error tipados, y fixtures que deben sobrevivir sin una API viva.

El contrato sellado mantiene cada vertical de búsqueda en el mismo ciclo: exportar una petición, ejecutar solo cuando hace falta, inspeccionar cuota y deserializar éxito o error.

BraveQueryBuilder.java superficie sellada
public sealed interface BraveQueryBuilder<T, E extends ApiResponse>
    permits BraveNewsQuery, BraveWebQuery, BraveImageQuery,
            BraveVideoQuery, BraveSuggestQuery, BraveSpellcheckQuery {

  // exportación de petición y ejecución opcional
  URI toURI();
  HttpRequest toHttpRequest();
  T execute();
  boolean hasExecuted();
  Optional<HttpResponse<String>> getHttpResponse();

  // señales de cuota desde la respuesta ejecutada
  Optional<XRateLimit> getRateLimits();
  Optional<XRateLimitPolicy> getRateLimitPolicy();
  Optional<XRateLimitRemaining> getRateLimitRemaining();

  // extracción tipada de éxito/error
  Class<E> getResponseType();
  Optional<E> getPOJO();
  Optional<ErrorResponse> getErrorPOJO();
  Optional<ApiResponse> getEitherPOJO();

  T reset();
}

Flujo

El SDK modela la interacción completa, no solo la petición.

Cada etapa tiene una responsabilidad separada, lo que evita mezclar transporte productivo, pruebas y análisis offline en un helper improvisado.

  1. 01 BraveWebQuery

    Modelar la consulta

    El builder conserva el vertical de búsqueda y reúne idioma, mercado, filtros, headers, operadores y token.

  2. 02 AbstractQueryUrlBuilder

    Validar antes de HTTP

    La construcción de URL rechaza consultas vacías o demasiado grandes antes de convertir un error local en una falla remota.

  3. 03 toURI / toHttpRequest / execute

    Exportar o ejecutar

    La misma consulta puede convertirse en URI, HttpRequest estándar o sesión ejecutada por el SDK.

  4. 04 AbstractRequestExecutor

    Decodificar respuesta

    El ejecutor lee bytes, maneja gzip cuando aparece y adapta el resultado a una respuesta de texto.

  5. 05 getPOJO / getEitherPOJO

    Extraer resultado

    El consumidor puede pedir éxito tipado, error tipado o ApiResponse unificado después de una sola ejecución.

  6. 06 WebSearchApiResponse.from

    Reproducir JSON

    Los records de respuesta leen archivos, strings, readers o HttpResponse, y luego escriben JSON portable.

Evidencia de Código

Lo que la implementación vuelve visible.

El código muestra cómo el SDK trata la validación, la coordinación de ejecución, la decodificación de respuestas y el replay como decisiones de diseño.

Validación

El builder codifica límites de Brave como invariantes locales.

Fuente

core/builders/AbstractQueryUrlBuilder.java

int chars = queryTerm.codePointCount(0, queryTerm.length());
int words = queryTerm.trim().isEmpty()
    ? 0
    : queryTerm.trim().split("\\s+").length;

return chars <= 400 && words <= 50;

Lectura

La regla de validación queda como invariante: una búsqueda mal formada falla localmente antes de tocar la API.

Ejecución

La ejecución ligada al token se serializa de forma justa antes de aplicar reintentos por límite.

Fuente

core/executors/BraveExecutionGate.java

startLock = new ReentrantLock(true);

startLock.lockInterruptibly();
HttpResponse<String> response = processNext(request, maxRetries);

RateLimitResponse limit = RateLimitResponse.from(response);
TimeUnit.SECONDS.sleep(
    limit.xRateLimitReset().secondsUntilNextRequest()
);

Lectura

JBrave trata la búsqueda con cuota como un recurso coordinado, no como sleeps sueltos en la aplicación.

Transporte

El ejecutor incluido mantiene la decodificación explícita y reemplazable.

Fuente

core/executors/AbstractRequestExecutor.java

HttpResponse<byte[]> bytes =
    client.send(request, HttpResponse.BodyHandlers.ofByteArray());

String body = decodeByteHttpResponse(bytes);

return adaptHttpResponse(bytes, body);

Lectura

Los equipos pueden usar el ejecutor incluido o conservar su infraestructura si solo necesitan URI y HttpRequest seguros.

Replay

Los records de respuesta se mueven entre llamadas vivas y fixtures offline.

Fuente

api/response/WebSearchApiResponse.java

WebSearchApiResponse.from(new File("response.json"));
WebSearchApiResponse.from(jsonString);
WebSearchApiResponse.from(reader);
WebSearchApiResponse.from(httpResponse);

response.write(new File("fixture.json"));
String json = response.toJson();

Lectura

El mismo modelo de respuesta sirve para llamadas vivas, fixtures guardadas, experimentos de ranking y pruebas de regresión.

Casos de Uso

Dónde JBrave aporta valor después de que la primera llamada ya funciona.

Estos escenarios muestran el valor práctico de separar modelado de petición, control de ejecución y respuestas aptas para fixtures.

Caso de uso

Integración de gateway de búsqueda

Problema

Un servicio necesita integrar Brave Search, pero el stack productivo ya tiene clientes HTTP, logging, reintentos y políticas propias.

Cómo ayuda

JBrave construye URI y HttpRequest seguros sin obligar a usar su ejecutor.

Por qué importa

La integración gana tipos y validación sin meter una segunda abstracción HTTP en producción.

Caso de uso

Fixtures para RAG y ranking

Problema

Experimentos de RAG y ranking necesitan inputs de búsqueda repetibles, no resultados vivos que cambian en cada corrida.

Cómo ayuda

Los records de respuesta se serializan, deserializan y reproducen desde fixtures JSON congeladas.

Por qué importa

Los datos de búsqueda se vuelven entrada determinista para enriquecimiento, features y regresiones.

Caso de uso

Sesiones de investigación por lotes

Problema

La recolección por lotes debe respetar límites de consulta, metadatos de cuota y análisis posterior por tipo de resultado.

Cómo ayuda

Las sesiones retienen la respuesta, exponen metadatos de rate limit y soportan web, image, news, video, suggest y spellcheck.

Por qué importa

La colección se puede pausar, auditar y analizar sin parsear URLs o headers a mano.

Límites

Los bordes útiles se documentan, no se esconden.

JBrave es lo bastante pequeño para inspeccionarse. Por eso debe quedar claro dónde ayuda, dónde termina y qué implica su estado alpha.

Diseñado para

  • Servicios Java que necesitan modelar peticiones de búsqueda explícitamente.
  • Stacks HTTP propios que igual se benefician de URI y HttpRequest tipados.
  • Fixtures offline para pruebas, experimentos de ranking y análisis de búsqueda.
  • Desarrolladores que quieren superficies públicas de Brave Search como objetos Java inspeccionables.

No diseñado para

  • Reemplazar la documentación oficial de Brave o sus reglas de planes y cuentas.
  • Ocultar cada detalle HTTP detrás de un cliente genérico.
  • Compartir un builder mutable como singleton thread-safe.
  • Garantizar firmas estables antes de que el API alpha madure.

Estado

Alpha 0.1.0: el modelo de ciclo de vida es claro, pero algunas firmas públicas pueden evolucionar antes de una versión estable.

Independencia

JBrave es un proyecto independiente Apache 2.0 de YGBStudio. No está afiliado, respaldado ni mantenido por Brave Software, Inc.

Si te gusta lo que ves

Siempre estoy abierto a trabajo interesante. Saluda.

Estudio independiente. Open source.