npm package: @imolko/crewmaster-protocol
Description: ## Instalación
Author: Roberto Matute
Latest version: 1.0.5

# Crewmaster Protocol

## Instalación

```bash
npm install @crewmaster/protocol@1.x.x
```

## Uso

Este protocolo se usa para la comunicación entre el cliente-app y el servidor de Crewmaster.

El siguiente codigo debe ser implementado por el cliente-app para usar el protocolo en cada interacción con el servidor. Es decir, cada vez que en el chat el usuario agregue un mensaje y se requiera alguna interacción con el LLM.

Para usar el protocolo, se debe instanciar un objeto de la clase `RequestHandler` y pasarle los siguientes parámetros:
    - bearerToken: Token de autenticación
    - serverUrl: URL del servidor
    - threadId: Identificador del hilo de conversación actual (establecido por el cliente-app)
    - eventConfig: Configuración de eventos (opcional)

Para hacer un request al servidor, se debe llamar al método `newRequest` del objeto `RequestHandler` y pasarle los siguientes parámetros:
    - body: Lista de mensajes intercambiados en el hilo de la conversación (el último mensaje es el mensaje nuevo agregado por el usuario)
    - responseStreamHandler: Objeto de la clase `ResponseStreamHandler` que contiene la instancia de la clase que implementa el contrato `PluginPort`, la cual es encargada de manejar la respuesta del serivdor
    - answeredClarifications: Lista de aclaraciones respondidas por el usuario (instancia de la clase `AnsweredClarifications`)

```typescript

    const request = new RequestHandler({
        bearerToken: this.bearerToken,                    // Token autenticacion
        serverUrl: this.serverUrl,                        // URL del servidor
        threadId: this.threadId,                          // Identificador del hilo de conversacion actual (establecido por el cliente-app)
        eventConfig: {
            scope: ScopeType.Answer,                      // opcional
            moments: [MomentType.Start, MomentType.End],  // opcional
            format: FormatType.Compact                    // opcional
        }
    });

    const reponseHandler: PluginPort; // Esta es una clase desarrollada por el cliente que implementa el contrato PluginPort
    const responseStreamHandler = new ResponseStreamHandler(responseHandler);

    request.newRequest(
        body,                           // Lista de mensajes intercambiados en el hilo de la conversacion
                                        // El ultimo mensaje es el mensaje nuevo agreagado por el ususario
        responseStreamHandler,          
        this.answeredClarifications
    );
```

Los tipos y clases relacionadas con el RequestHandler se importan de la siguiente manera:

```typescript
import { RequestHandler,  AnsweredClarifications } from '@imolko/crewmaster-protocol/request-handler';
```

Los tipos y clases relacionadas con el ResponseStreamHandler se importan de la siguiente manera:

```typescript
import { ResponseStreamHandler, PluginPort } from '@imolko/crewmaster-protocol/response-stream-handler';
```

## Sobre RequestHandler

La clase `RequestHandler` es la encargada de manejar las peticiones al servidor. Esta clase acepta y valida solo dos tipos de solicitudes:
    - **Fresh**: Solicitudes de tipo `Fresh` que es un mensaje nuevo agregado por el usuario al chat como parte del inicio o el seguimiento de una conversación con el LLM
    - **Clarification**: Solicitudes de tipo `Clarification` en la que el usuario responde a una aclaración requerida por el LLM (crewmaster)

La clase `RequestHandler` tiene una logica implementada para saber si el mensaje que se esta enviando es una aclaración o un mensaje nuevo. Para esto, se valida si el mensaje es una respuesta a una aclaración previa o si es un mensaje nuevo agregado por el usuario.

Dicha validacion se hace con ayuda de la clase `AnsweredClarifications` que es un objeto que contiene una lista de aclaraciones respondidas por el usuario. La forma en como se hace esa validacion es haciendo match entre el mensaje nuevo agregado por el usuario al chat y las aclaraciones respondidas por el usuario existentes en el objeto `AnsweredClarifications`.

**Ejemplo teorico:**
Cuando un usuario responde a una aclaración el cliente-app agrega a su objeto `AnsweredClarifications` la aclaración respondida por el usuario con un mensaje especifico como `key` y payload como `value`. Luego cuando se ejecuta el RequestHandler.newRequest() esa clase valida si hay match entre el mensaje nuevo agregado por el usuario y las aclaraciones respondidas por el usuario. Si hay match, entonces se envia una solicitud de tipo `Clarification` al servidor, de lo contrario se envia una solicitud de tipo `Fresh`.

**Ejemplo practico:**
El cliente-app implmenta en su logica una aclaracion para confirmar una operacion, en donde en la interfaz le da dos opciones que el usuario debe seleccionar: 'Confirmar operacion' o 'Rechazar operacion`.

La opcion que el usuario seleccione el cliente-app la debe agregar a su objeto `AnsweredClarifications`.

Suponganmos que el cliente selecciona 'Confirmar operacion', entonces el cliente-app agrega a su objeto `AnsweredClarifications`:

```
    key: 'Confirmar operacion'
    payload: {
        confirmation: 'y'
    }
```

Luego el cliente-app debe agregar como ultimo mensaje enviado por el usuario en el chat el mensaje 'Confirmar operacion' para que el RequestHandler pueda validar si hay match entre el mensaje nuevo agregado por el usuario y las aclaraciones respondidas por el usuario.

Y de esa forma el RequestHandler sabra si el mensaje que se esta enviando es una aclaracion o un mensaje nuevo y enviara la solicitud correspondiente al servidor.


## Sobre el manejo de respuestas del servidor (ResponseStreamHandler + PluginPort)

La clase `ResponseStreamHandler` es la encargada de manejar las respuestas del servidor. Usando el plugin (instancia de una clase propia del cliente-app que implementa el contrato `PluginPort`) que se le pase como parametro al constructor de ésta clase.

El contrato PluginPort es una interfaz que debe ser implementada por el cliente-app para manejar las respuestas del servidor. Los metodos que debe implementar el cliente-app son:

- **connectionStarted()**: Este metodo debe manejar cualquier accion que el cliente-app necesite ejecutar cuando sepa que se ha establecido conexion con el serividor, es decir, cuando sepa que se envio correctamente el request al servidor y se esta esperando una respuesta.
    
- **publishMessage()**: Este metodo debe manejar cada mensaje que se reciba del LLM, puede ser uno o mas mensajes y estan identificados, el cliente-app debe poder manejar cada uno de esos mensajes para mostrarlos al usuario en el chat o ejecutar la logica que requiera.

    Si hay errores, la respuesta que se pasa al metodo `publishMessage()` indica que hubo un error y el cliente-app debe manejarlo.
    
    Cuando hay errores, se envia el error por publishMessage() y seguidamente se ejecuta el metodo `connectionFinished()`.
    
- **connectionFinished()**: Este metodo indica que la interaccion con el servidor y el LLM finalizo, el cliente-app debe manejar cualquier accion que necesite ejecutar cuando sepa que la interaccion con el servidor y el LLM finalizo.