import hapi from '@hapi/hapi' ; import Joi from '@hapi/joi' ; import { badGateway } from '@hapi/boom' ; import { Server } from '../../types' ; import AssistantV2 from 'ibm-watson/assistant/v2' ; import { IamAuthenticator } from 'ibm-watson/auth' ; const defaultApiVersion = '2018-09-19' ; function handleUpstreamError ( prefix , e ) { const message = e . response ? `[HTTP ${ e . response . statusCode }] ${ JSON . stringify ( e . response . body ) }` : e . message ; throw badGateway ( `${ prefix }: ${ message }` ) ; } interface Request extends hapi . Request { payload : { session : string ; message : string ; } ; server : Server ; } async function handleRequest ( { apiUrl , apiKey , assistantId , apiVersion } , req ) { const { message } = req . payload ; try { const assistant = new AssistantV2 ( { authenticator : new IamAuthenticator ( { apikey : apiKey } ) , url : apiUrl , version : apiVersion } ) ; const session = await assistant . createSession ( { assistantId : assistantId } ) ; const response = await assistant . message ( { input : { text : message } , assistantId : assistantId , sessionId : session . result . session_id } ) ; if ( response ?. result ?. output ?. generic ) { return { text : response . result . output . generic [ 0 ] . text } ; } } catch ( e ) { handleUpstreamError ( 'Unable to open a session with Watson' , e ) ; } return false ; } interface Options { apiKey : string ; apiUrl : string ; assistantId : string ; apiVersion ? : string ; } interface ExtendedJoi extends Joi . Root { coerce : Joi . CoerceFunction ; } const plugin = { name : 'assistant' , version : '1.0.0' , async register ( server , options ) { if ( ! options . apiVersion ) { options . apiVersion = defaultApiVersion ; } server . decorate ( 'server' , 'watsonSessions' , ( ) => new Map < string , string > ( ) ) ; const custom = Joi . extend ( ( joi ) : Joi . Extension => { return { type : 'object' , base : joi . object ( ) , coerce : ( value ) : Joi . CoerceResult => { if ( value [ 0 ] !== '{' && ! /^\s*\{/ . test ( value ) ) { return { value : null } ; } try { return { value : JSON . parse ( value ) } ; } catch ( err ) { console . log ( err ) ; return { errors : err } ; } } } ; } ) ; server . route ( { method : 'POST' , path : '/assistant/ask' , handler : handleRequest . bind ( null , options ) , options : { validate : { failAction : async ( _request , _h , err ) => { if ( process . env . NODE_ENV === 'production' ) { console . error ( 'ValidationError:' , ! ! err && err . message ) ; } else { console . error ( err ) ; throw err ; } } , payload : custom . object ( ) . required ( ) . keys ( { message : Joi . string ( ) . min ( 1 ) . required ( ) , session : Joi . string ( ) . min ( 1 ) . required ( ) } ) } } } ) ; } } ; export default plugin ;