Añade llamada saliente con Retell al funnel B2C

Integra el agente de voz de Retell (Arquitectura A para la demo): tras la
pre-llamada, el orquestador lanza una llamada saliente real con override de
agente y dynamic variables (empresa + cliente), mientras el render y el
presupuesto se siguen generando con los datos del formulario.

- src/lib/env.ts: esquema zod de RETELL_* (claves opcionales -> sin ellas el
  funnel sigue en modo simulado y el build no se rompe)
- src/lib/voice/retell.ts: cliente fino con fetch a create-phone-call
  (sin nueva dependencia), normalización E.164 y builder de variables
- orchestrator: dispara la llamada best-effort y guarda el callId
- tests del normalizador de teléfono y del builder de variables

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Carlos Narro
2026-06-02 21:55:29 +02:00
parent 0651d964f5
commit 372ad560bf
5 changed files with 196 additions and 3 deletions

28
mvp/b2c/src/lib/env.ts Normal file
View File

@@ -0,0 +1,28 @@
import { z } from 'zod';
// Variables de entorno de integraciones externas, validadas con zod (lo exige CLAUDE.md).
// Son OPCIONALES a propósito: sin ellas el funnel sigue en modo simulado, y ni el build ni
// la demo dependen de tener claves cargadas.
const opcional = z.preprocess(
(v) => (v === '' || v === undefined ? undefined : v),
z.string().min(1).optional(),
);
const schema = z.object({
RETELL_API_KEY: opcional,
RETELL_AGENT_ID: opcional,
RETELL_FROM_NUMBER: opcional,
});
export const env = schema.parse({
RETELL_API_KEY: process.env.RETELL_API_KEY,
RETELL_AGENT_ID: process.env.RETELL_AGENT_ID,
RETELL_FROM_NUMBER: process.env.RETELL_FROM_NUMBER,
});
// Mínimo para lanzar una llamada saliente: clave de API + número de origen. El agente puede
// ir ligado al número en el panel; si además se define RETELL_AGENT_ID, se manda como
// override_agent_id en cada llamada.
export function retellConfigurado(): boolean {
return Boolean(env.RETELL_API_KEY && env.RETELL_FROM_NUMBER);
}