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
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.