handleReport, onReportApply y handleExtras se disparan al final de un flujo. No te dicen nada de lo que pasa mientras tanto: si el médico está grabando, si está escribiendo, si SofIA está generando la nota. onEvent cubre ese hueco con un flujo de eventos tipados y sin datos clínicos.
El caso de uso que lo motivó: un HIS que cierra la sesión por inactividad no puede distinguir “el médico lleva veinte minutos grabando una consulta sin tocar el teclado” de “el médico se fue hace veinte minutos”. Con el micrófono activo y sin otra actividad, deslogueaba al médico a mitad de consulta.
Los eventos nunca llevan texto clínico, contenido del informe, lo que se escribió ni identificadores de paciente o médico. Cada campo del payload es un enumerado, un booleano o un número. Si necesitas el contenido clínico, ya tienes canales dedicados para ello (
handleReport, onReportApply, handleExtras).Las dos props
eventSubscriptions (o con un array vacío) no se entrega ningún evento, y el SDK registra un aviso en consola si pasas onEvent sin ella. Admite nombres exactos ("recording.started"), comodines de familia ("recording.*") o todo ("*").
- React
- Web Component
Forma de un evento
sessionId es el mismo identificador aleatorio que el SDK usa para su analítica interna. Cambia con cada paciente, así que te sirve para correlacionar una ráfaga de eventos con una consulta y para descartar los que lleguen tras un cambio de paciente.
Catálogo de eventos
recording — grabación
activity — actividad del médico
Ambos se limitan a un evento cada 5 segundos por tipo/superficie, en el flanco de subida: la primera pulsación o tecla se emite al instante y las siguientes se silencian durante la ventana. Para detectar inactividad, emitir de más es inocuo (tu temporizador se reinicia); emitir de menos cerraría la app con el médico a mitad de frase.
report — generación del informe
lifecycle — ciclo de vida
Mantener viva una sesión externa
Si tu sistema cierra la sesión por inactividad, lo que necesita son pings periódicos de actividad, no los flancosstarted/stopped. Para eso existe recording.heartbeat.
Receta completa para un temporizador de inactividad
eventSubscriptions={['recording.*', 'activity.*', 'report.*']}. Un recording.audio_lost o recording.microphone_disconnected también reinicia el temporizador aquí —es razonable: el médico sigue delante de la pantalla viendo el aviso—, pero si prefieres tratarlos como el fin de la actividad, compáralos por event.name.
Garantías de entrega
- Asíncrona. Cada evento se entrega en un microtask posterior, nunca dentro del render de React ni en la ruta de audio. Tu handler puede hacer
setStatesin problema, y un handler lento no retrasa la grabación. - Ordenada.
seqes monotónico y los eventos llegan en ese orden. - Aislada. Si tu handler lanza una excepción, el SDK la captura y sigue funcionando; registra un único aviso en consola por carga de página.
- Estable entre pacientes. Cambiar
patientidouseridremonta el widget por dentro, pero tu suscripción y tu handler sobreviven sin que tengas que volver a asignarlos. Pasar una función inline en cada render tampoco re-suscribe. - Un widget por página. El SDK admite una sola instancia de
<Omniscribe>/<sofia-sdk>. Si se registrara un segundoonEvent, gana el último y se avisa en consola. - Nombres abiertos. Pueden añadirse eventos nuevos en versiones menores. Compara por
event.nameoevent.familyy trata los nombres desconocidos como “algo pasó”; no asumas un conjunto cerrado.
Si en TypeScript quieres un
switch exhaustivo, estrecha event.name a KnownSdkEventName. Los tipos SdkEvent, SdkEventName, KnownSdkEventName, SdkEventFamily, SdkEventHandler, SdkEventPayloadMap y SdkEventSubscription se exportan desde @omniloy/sofia-sdk.Privacidad
El diseño parte de una invariante que el propio compilador del SDK hace cumplir: ningún campo de ningún payload es una cadena libre. Los errores viajan como códigos, los informes como booleanos, la escritura como el nombre de la superficie. El SDK tiene un test que lee la definición de tipos y falla la build si aparece unstring sin acotar.
Por eso onEvent no es un volcado del log interno del SDK: los mensajes de log son prosa escrita a mano que interpola identificadores y objetos de error completos, y eso no se puede hacer seguro con un filtro. Si necesitas depurar, usa la prop debug y la consola; si necesitas contenido clínico, usa los callbacks dedicados.
Próximos pasos
Propiedades opcionales
Todas las props y callbacks del componente
Vista previa de inserción
De dónde sale
activity.typing con surface: 'note'