📦 Recordatorio de reparto por voz
Archivo: /Users/user/rifai-agents/agentes/voice/voice-delivery-reminder.ts · Plist: ninguno (no existe com.rifai.voice-delivery-reminder.plist ni en cron/ ni en ~/Library/LaunchAgents/) · Horario: no programado actualmente. El comentario de cabecera dice "cron cada 1h", pero no hay plist cargado, así que hoy solo corre si se ejecuta a mano. Como el resto, solo llamaría dentro de 10:00–22:00 Madrid y nunca en domingo.
Qué hace
Llama a los clientes cuyo pedido COD está EN REPARTO con GLS (estado out_for_delivery) para recordarles que tengan el efectivo exacto preparado, mantengan el teléfono encendido, dejen quien lo reciba si no están, y no rechacen el paquete sin abrirlo. No es una venta: es un recordatorio amable de máximo 60–90s con un guion propio (persona "Cristina"). Reduce paquetes rechazados/devueltos en contra reembolso. Deja de llamar cuando el pedido pasa a entregado/cancelado y respeta un mínimo de 3h entre llamadas al mismo pedido.
Cómo funciona
1. Carga .env y comprueba ventana horaria (isCallableNow()).
2. Abre/crea la tabla delivery_reminders en data/voice-calls.db (registro propio de recordatorios, separado de calls).
3. Pide a Shopify los pedidos fulfillment_status=shipped de los últimos 14 días (máx 100) con sus fulfillments.
4. Filtra: descarta entregados/cancelados/rechazados; se queda con COD; exige tracking_number; exige shipment_status === 'out_for_delivery' (o tag en_reparto/out_for_delivery).
5. Por candidato: salta si fue llamado hace menos de 3h (lastReminderAt); extrae teléfono; prepara variables en español.
6. Construye un system prompt y un firstMessage específicos del recordatorio (guion de la persona "Cristina") y lanza la llamada con createOutboundCall pasando systemPromptOverride, firstMessageOverride y extraMetadata (tracking, call_type=delivery_reminder, gls_status).
7. Guarda la llamada en delivery_reminders. Throttle 2s. Imprime 📊 N llamadas lanzadas · M saltadas.
> ⚠️ Nota de código: usa phone.ok / phone.number, pero extractPhoneFromOrder en lib/phone-normalizer.ts devuelve string | null, no un objeto {ok, number}. Tal cual está, la condición fallaría/lanzaría en tiempo de ejecución. Probablemente es la razón por la que aún no tiene plist (pendiente de arreglar antes de programarlo).
Datos/APIs
- Shopify Admin REST (
2024-10): pedidos enviados + fulfillments (tracking_number, shipment_status). Vars:SHOPIFY_STORE,SHOPIFY_ACCESS_TOKEN. - Vapi (
lib/vapi-client.ts) con overrides de prompt. Vars:VAPI_API_KEY,VAPI_ASSISTANT_ID_COD_CONFIRM,VAPI_PHONE_NUMBER_ID. - GLS: indirecto — usa el
shipment_status/tracking que Shopify guarda en el fulfillment (el estado real de GLS lo escriben otros crons de tracking en los tags/fulfillment). - SQLite
data/voice-calls.db, tabla propiadelivery_reminders(víabetter-sqlite3directo, novoice-db.ts). - Helpers:
lib/phone-normalizer.ts,lib/spanish-converter.ts. No notifica Telegram.
Cómo probarlo
cd /Users/user/rifai-agents && npx tsx agentes/voice/voice-delivery-reminder.ts
Esperado: 📦 Voice Delivery Reminder ..., nº de pedidos enviados en 14d y nº de candidatos COD en reparto. Si no hay candidatos, termina en 📊 0 llamadas lanzadas. Fuera de horario sale con ⏸. OJO: con candidatos válidos lanza llamadas reales de pago. Antes de programarlo, validar el bug del teléfono descrito arriba.
Si se rompe / recuperar
No hay plist. Para programarlo (cada 1h) habría que crear com.rifai.voice-delivery-reminder.plist con StartInterval 3600, copiarlo a ~/Library/LaunchAgents/ y:
launchctl load ~/Library/LaunchAgents/com.rifai.voice-delivery-reminder.plist
Logs sugeridos: /Users/user/rifai-agents/logs/voice-delivery-reminder.log (definir StandardOutPath/StandardErrorPath en el plist). Mientras no exista plist, solo corre manualmente.
Cómo replicarlo
- Carga
.envestándar. - Lectura Shopify de pedidos enviados + fulfillments, filtro COD +
out_for_delivery. - Cliente Vapi con soporte de
systemPromptOverride/firstMessageOverride/extraMetadata(ya soportado envapi-client.ts). - Guion de la persona "Cristina" (system prompt + firstMessage).
- Normalizador de teléfono (corregir el contrato
string|nullvs{ok,number}) + conversor español + ventana horaria. - SQLite con tabla
delivery_reminderspara anti-spam (mín 3h entre llamadas). - Plist launchd
StartInterval 3600(a crear).