← Volver al catálogo

🤖 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:

  • createnotionCreateTask; completenotionComplete (PATCH Status=Done por pageId).
  • calendar_create → crea tarea Notion tipo Calendar + evento Google Calendar vía tools/secretary-data.ts > createCalendarEvent.
  • rutinaleerRutina() recorre Notion (mismo camino que el Notificador) y devuelve el checklist del turno/día pedido en tiempo real.
  • patineteplus_order/cart/clearpatineteplus(): busca en el catálogo público patineteplus.com/products.json, hace match por keywords, y mantiene un carrito en data/pp-cart.json; "ver carrito" devuelve un enlace patineteplus.com/cart/<vid:qty,...>.
  • list / shopify_list / price_search / chat → devuelve el response que 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 tareas 32602a86-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 local data/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

  • .env con TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID, NOTION_TOKEN, SHOPIFY_STORE, SHOPIFY_ACCESS_TOKEN, GOOGLE_CLIENT_ID/SECRET/REFRESH_TOKEN.
  • Binario IA local tools/gemini-cli que acepte --print --model haiku --system-prompt y lea el mensaje por stdin devolviendo JSON.
  • Librería tools/secretary-data.ts con createCalendarEvent.
  • 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 el pollLoop propio. Persistencia de offset y carrito en data/.