← Volver a proyectos

Smart Expansion History

Una extensión de Chrome, History Chat, que encuentra una página que visitaste cuando solo recuerdas de qué trataba, no su título ni su URL. La construí con React y Vite durante mi pasantía en DevFortress: la búsqueda corre sobre el historial local de Chrome, y la API Gemini de Google solo se usa si agregas tu propia clave.

Arquitectura

Ventana de la extensión (React)Historial de ChromeGemini (opcional)
Gemini solo se llama cuando el usuario agrega una clave, para convertir la pregunta en palabras clave y ordenar hasta 100 candidatos locales.

La extensión es una ventana emergente Manifest V3 hecha con React, sin servidor propio y sin scripts de contenido. Sin clave, el texto escrito va directo a chrome.history.search en el rango de tiempo que elige el usuario, de las últimas 24 horas a los últimos 3 meses, y los resultados se limpian y se muestran al instante. Con clave, Gemini 2.5 Flash primero convierte la pregunta en palabras clave ordenadas por relevancia, la ventana busca en el historial local una palabra clave a la vez hasta juntar 100 candidatos limpios o agotar la lista, y luego Gemini elige hasta 5 con una razón corta. La configuración, incluida la clave de Gemini, se guarda en el almacenamiento sincronizado de Chrome, y el historial del chat en el almacenamiento local.

Decisiones clave

Cuatro niveles de búsqueda, a elección del usuario

Dejo que el usuario elija cuánto amplía la IA una pregunta: Superficial le pide a Gemini 5 palabras clave, Regular (el predeterminado) 20, Exhaustive 50 y Sheerlock hasta 100. El prompt pide palabras sueltas y sin repetir, ordenadas de la más a la menos relevante, y le dice al modelo que no rellene la lista. Una búsqueda rápida se mantiene pequeña, y el modo profundo queda para las páginas difíciles de encontrar.

Un presupuesto fijo de 100 candidatos

Sea cual sea la profundidad, se envían como máximo 100 páginas a Gemini para ordenar. Las 10 primeras palabras clave tienen hasta 10 lugares cada una, las 20 siguientes 5, el resto 2, y una segunda pasada llena los lugares libres con lo que sobró, siempre en el orden de las palabras clave. Con esta recuperación progresiva, la extensión encontró más páginas correctas y usó alrededor de un 40% menos de tokens de Gemini.

Limpiar la lista antes de que la vea el modelo

Normalizo cada URL candidata: quito la parte después del # y los parámetros de rastreo como utm_source, gclid y fbclid, y luego ordeno el resto. Después los duplicados se juntan en una sola entrada, y se dejan fuera las páginas de búsqueda de Google, las páginas chrome:// y los archivos locales. Así, ningún lugar del presupuesto se gasta dos veces en la misma página ni en ruido de búsqueda.

La parte difícil

Cuando el JSON del modelo no es JSON válido

Las dos llamadas a Gemini esperan JSON puro, y los dos prompts lo piden, pero igual quito los delimitadores de bloque de código markdown antes de parsear y saco el arreglo entre corchetes de la respuesta de palabras clave. Si las palabras clave siguen sin poder leerse, o la llamada falla, la extensión recurre a las palabras de la pregunta de más de tres caracteres y busca con esas. Si la clasificación no se puede leer, el usuario igual ve los primeros 5 candidatos en vez de un error.

Seguridad y rendimiento

  • Sin clave de API, la extensión no hace ninguna llamada de red: la búsqueda corre sobre la API de historial de Chrome. Con una clave de Gemini, la pregunta y el título, la URL y la hora de la última visita de hasta 100 páginas candidatas se envían a la API Gemini de Google, pero nunca el historial completo.
  • Aparte del acceso a los hosts de las API de IA, el manifiesto solo pide los permisos history y storage, y no se inyecta nada en las páginas que visitas. El historial del chat, con los resultados anteriores, se queda en el almacenamiento local de la extensión, y los mensajes más antiguos que el periodo de retención elegido se borran al abrir la ventana.

Stack

ReactViteTailwind CSSChrome Manifest V3Gemini API

Enlaces