🤖 Router Central (cerebro conversacional de Sec)
Archivo: /Users/user/rifai-agents/agentes/sec/router-central.ts · Plist: ninguno propio (no hay com.rifai.router-central.plist) · Horario: no es un cron. Su función procesar la importa bot-telegram.ts (daemon com.rifai.bot, KeepAlive), que es quien recibe los mensajes del bot de Sec en tiempo real. También se puede ejecutar a mano en modo CLI o polling.
Qué hace
Es el cerebro conversacional del Secretario: recibe los mensajes que el CEO escribe al bot de Sec, los clasifica con la IA local (tools/gemini-cli, modelo haiku) usando como contexto las tareas de Notion, los pedidos sin enviar y los borradores de Shopify, y ejecuta la acción adecuada. Sabe crear/listar/completar tareas Notion, crear citas en Google Calendar (con eco en Notion como tarea tipo Calendar), listar pedidos/borradores Shopify, buscar precios, consultar la rutina del día on-demand, y gestionar un carrito del proveedor PatinePlus (pedir / ver / limpiar). Es el ÚNICO componente que debe leer getUpdates del bot ceosec (TELEGRAM_BOT_TOKEN); por eso Sec se quita de bot-listener.ts (dos lectores del mismo token se pisan).
Cómo funciona
1. Parsea .env y define constantes (Shopify, Notion TASKS_DB, binario tools/gemini-cli, ficheros de estado en data/).
2. buildContext(): consulta Notion (hasta 50 tareas con id/estado/prioridad/fecha), pedidos Shopify status=open&fulfillment_status=unshipped con financial_status=pending (excluye los etiquetados auto-cod-shipped) y draft_orders abiertos; todo filtrado desde CONTAR_DESDE (2026-06-04, pizarra limpia).
3. buildPrompt(): inyecta fecha/hora Madrid + los tres bloques de contexto en un prompt que obliga a responder SOLO JSON con un campo action y los parámetros (taskName, dueDate, startTime, etc.).
4. callAI(): ejecuta gemini-cli --print --model haiku --system-prompt ... por spawnSync, parsea el JSON (limpia ``json), y normaliza el action` (remap de variantes sin guion bajo).
5. procesar(): hace switch sobre action:
create→notionCreateTask;complete→notionComplete(PATCH Status=Done porpageId).calendar_create→ crea tarea Notion tipoCalendar+ evento Google Calendar víatools/secretary-data.ts > createCalendarEvent.rutina→leerRutina()recorre Notion (mismo camino que el Notificador) y devuelve el checklist del turno/día pedido en tiempo real.patineteplus_order/cart/clear→patineteplus(): busca en el catálogo públicopatineteplus.com/products.json, hace match por keywords, y mantiene un carrito endata/pp-cart.json; "ver carrito" devuelve un enlacepatineteplus.com/cart/<vid:qty,...>.list / shopify_list / price_search / chat→ devuelve elresponseque generó la IA.
6. Modo ejecución (entry): si recibe argumento → modo CLI test (imprime, y si SEND=1 envía a Telegram). Sin argumento → pollLoop(): getUpdates con offset persistido en data/router-central-state.json, procesa los mensajes del chat del CEO y responde. En producción real es bot-telegram.ts quien importa procesar y le pasa el texto.
Datos/APIs
- Notion API (
2022-06-28): query DB tareas32602a86-b28a-80ab-9fbb-d88bbe3367db, crear/patch páginas, search+blocks para la rutina. Var:NOTION_TOKEN. - Shopify Admin API (
2024-10):orders.json,draft_orders.json. Vars:SHOPIFY_STORE,SHOPIFY_ACCESS_TOKEN. - Google Calendar vía
tools/secretary-data.ts(createCalendarEvent). Vars:GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET,GOOGLE_REFRESH_TOKEN. - Telegram Bot API (bot de Sec / ceosec):
getUpdates+sendMessage. Vars:TELEGRAM_BOT_TOKEN,TELEGRAM_CHAT_ID. - IA local: binario
/Users/user/rifai-agents/tools/gemini-cli(modelo haiku). No usa OpenAI. - PatinePlus: catálogo público
https://patineteplus.com/products.json(sin auth). Carrito localdata/pp-cart.json.
Cómo probarlo
Modo CLI (no envía a menos que pongas SEND=1):
cd /Users/user/rifai-agents && npx tsx agentes/sec/router-central.ts "crea tarea probar el router"
Esperado: imprime TEST: "...", la acción clasificada (p.ej. create) y la respuesta. Otros ejemplos: "qué tareas tengo", "qué pedidos tengo", "rutina", "pedir patinete kukirin en patineteplus", "ver carrito proveedor". Para probar polling/Telegram: npx tsx agentes/sec/router-central.ts (sin argumento) lee el bot de Sec una vez — NO hacerlo si el daemon com.rifai.bot está activo (se pisarían los getUpdates).
Si se rompe / recuperar
No tiene plist propio. Vive dentro del daemon bot-telegram.ts:
launchctl unload ~/Library/LaunchAgents/com.rifai.bot.plist
launchctl load ~/Library/LaunchAgents/com.rifai.bot.plist
Logs: el daemon escribe en /Users/user/rifai-agents/logs/bot.log (no hay router-central.log propio). Invariante crítico: solo este módulo puede leer getUpdates del token ceosec; si Sec vuelve a leerse desde bot-listener.ts "deja de responder a ratos". Otras causas: gemini-cli ausente/colgado (timeout 45s), NOTION_TOKEN/SHOPIFY_ACCESS_TOKEN caducados, o data/ no escribible.
Cómo replicarlo
.envconTELEGRAM_BOT_TOKEN,TELEGRAM_CHAT_ID,NOTION_TOKEN,SHOPIFY_STORE,SHOPIFY_ACCESS_TOKEN,GOOGLE_CLIENT_ID/SECRET/REFRESH_TOKEN.- Binario IA local
tools/gemini-clique acepte--print --model haiku --system-prompty lea el mensaje por stdin devolviendo JSON. - Librería
tools/secretary-data.tsconcreateCalendarEvent. - Base Notion de tareas (
Task name/Status/Priority/Due date/Task type) y páginas "Rutina <día>". - Construcción de contexto (Notion + Shopify orders/drafts) + prompt que fuerza JSON con
action. - Router de acciones (switch) + handlers Notion/Calendar/Shopify/PatinePlus + carrito en fichero.
- Un host que invoque
procesar(texto)(daemon de Telegram) o elpollLooppropio. Persistencia de offset y carrito endata/.