import * as client from '@botpress/client'; import * as plugin from '../../plugin'; import type { Request } from '../../serve'; import * as utils from '../../utils/type-utils'; import { type BotLogger } from '../bot-logger'; import { BotSpecificClient } from '../client'; import * as common from '../common'; import type * as workflowProxy from '../workflow-proxy/types'; export type BotOperation = 'event_received' | 'register' | 'unregister' | 'ping' | 'action_triggered'; export type BotContext = { botId: string; type: string; operation: BotOperation; configuration: { payload: string; }; }; type _IncomingEvents = { [K in utils.StringKeys>]: utils.Merge[K]; }>; }; type _IncomingMessages = { [K in utils.StringKeys>]: utils.Merge[K]; }>; }; type _IncomingStates = { [K in utils.StringKeys>]: utils.Merge[K]['type']; payload: common.EnumerateStates[K]['payload']; }>; }; type _OutgoingMessageRequests = { [K in utils.StringKeys>]: utils.Merge[K]; }>; }; type _OutgoingMessageResponses = { [K in utils.StringKeys>]: utils.Merge[K]; }>; }>; }; type _OutgoingCallActionRequests = { [K in utils.StringKeys>]: utils.Merge[K]; }>; }; type _OutgoingCallActionResponses = { [K in utils.StringKeys>]: utils.Merge[K]; }>; }; type _IncomingCallActionRequest = { [K in utils.StringKeys]: { type: K; input: TBot['actions'][K]['input']; }; }; type _IncomingCallActionResponses = { [K in utils.StringKeys]: { type: K; output: TBot['actions'][K]['output']; }; }; export type AnyIncomingEvent = utils.ValueOf<_IncomingEvents>; export type AnyIncomingMessage = utils.ValueOf<_IncomingMessages>; export type AnyOutgoingMessageRequest = utils.ValueOf<_OutgoingMessageRequests>; export type AnyOutgoingMessageResponse = utils.ValueOf<_OutgoingMessageResponses>; export type AnyOutgoingCallActionRequest = utils.ValueOf<_OutgoingCallActionRequests>; export type AnyOutgoingCallActionResponse = utils.ValueOf<_OutgoingCallActionResponses>; export type AnyIncomingCallActionRequest = utils.ValueOf<_IncomingCallActionRequest>; export type AnyIncomingCallActionResponse = utils.ValueOf<_IncomingCallActionResponses>; export type IncomingEvents = _IncomingEvents & { '*': AnyIncomingEvent; }; export type IncomingMessages = _IncomingMessages & { '*': AnyIncomingMessage; }; export type IncomingStates<_TBot extends common.BaseBot> = _IncomingStates<_TBot> & { '*': client.State; }; export type OutgoingMessageRequests = _OutgoingMessageRequests & { '*': AnyOutgoingMessageRequest; }; export type OutgoingMessageResponses = _OutgoingMessageResponses & { '*': AnyOutgoingMessageResponse; }; export type OutgoingCallActionRequests = _OutgoingCallActionRequests & { '*': AnyOutgoingCallActionRequest; }; export type OutgoingCallActionResponses = _OutgoingCallActionResponses & { '*': AnyOutgoingCallActionResponse; }; export type IncomingCallActionRequest = _IncomingCallActionRequest & { '*': AnyIncomingCallActionRequest; }; export type IncomingCallActionResponses = _IncomingCallActionResponses & { '*': AnyIncomingCallActionResponse; }; export type BotClient = BotSpecificClient; export type CommonHandlerProps = { ctx: BotContext; logger: BotLogger; client: BotClient; }; export type InjectedHandlerProps = { /** * # EXPERIMENTAL * This API is experimental and may change in the future. */ workflows: workflowProxy.WorkflowProxy; }; export type ExtendedHandlerProps = CommonHandlerProps & InjectedHandlerProps; export type MessagePayloads = { [TMessageName in utils.StringKeys>]: ExtendedHandlerProps & { message: IncomingMessages[TMessageName]; user: client.User; conversation: client.Conversation; event: client.Event; }; }; export type MessageHandlers = { [TMessageName in utils.StringKeys>]: (args: MessagePayloads[TMessageName]) => Promise; }; export type EventPayloads = { [TEventName in utils.StringKeys>]: ExtendedHandlerProps & { event: IncomingEvents[TEventName]; }; }; export type EventHandlers = { [TEventName in utils.StringKeys>]: (args: EventPayloads[TEventName]) => Promise; }; export type StateExpiredPayloads = { [TSateName in utils.StringKeys>]: ExtendedHandlerProps & { state: IncomingStates[TSateName]; }; }; export type StateExpiredHandlers = { [TSateName in utils.StringKeys>]: (args: StateExpiredPayloads[TSateName]) => Promise; }; export type ActionHandlerPayloads = { [TActionName in utils.StringKeys]: ExtendedHandlerProps & { type?: TActionName; input: TBot['actions'][TActionName]['input']; }; }; export type ActionHandlers = { [TActionName in utils.StringKeys]: (props: ActionHandlerPayloads[TActionName]) => Promise; }; export type ActionHandlersMap = { [TActionName in utils.StringKeys]?: (props: Omit[TActionName]>[0], keyof InjectedHandlerProps>) => Promise[TActionName]>>>; }; export type BridgeWorkflowUpdateType = 'child_workflow_deleted' | 'child_workflow_finished' | 'workflow_timedout' | 'workflow_started' | 'workflow_continued'; export type WorkflowUpdateEventPayload = { type: BridgeWorkflowUpdateType; childWorkflow?: client.Workflow; workflow: client.Workflow; conversation?: client.Conversation; user?: client.User; }; export type WorkflowUpdateEvent = utils.Merge; export type WorkflowPayloads = { [TWorkflowName in utils.StringKeys]: ExtendedHandlerProps & { conversation?: client.Conversation; user?: client.User; event: WorkflowUpdateEvent; /** * # EXPERIMENTAL * This API is experimental and may change in the future. */ workflow: workflowProxy.ActionableWorkflow; }; }; export type WorkflowHandlers = { [TWorkflowName in utils.StringKeys]: (props: WorkflowPayloads[TWorkflowName]) => Promise; }; type BaseHookDefinition = { stoppable?: boolean; data: any; }; type HookDefinition = THookDef; /** * TODO: add hooks for: * - before_register * - after_register * - before_state_expired * - after_state_expired */ export type HookDefinitions = { before_incoming_event: HookDefinition<{ stoppable: true; data: _IncomingEvents & { '*': AnyIncomingEvent; }; }>; before_incoming_message: HookDefinition<{ stoppable: true; data: _IncomingMessages & { '*': AnyIncomingMessage; }; }>; before_outgoing_message: HookDefinition<{ stoppable: false; data: _OutgoingMessageRequests & { '*': AnyOutgoingMessageRequest; }; }>; before_outgoing_call_action: HookDefinition<{ stoppable: false; data: _OutgoingCallActionRequests & { '*': AnyOutgoingCallActionRequest; }; }>; before_incoming_call_action: HookDefinition<{ stoppable: false; data: _IncomingCallActionRequest & { '*': AnyIncomingCallActionRequest; }; }>; after_incoming_event: HookDefinition<{ stoppable: true; data: _IncomingEvents & { '*': AnyIncomingEvent; }; }>; after_incoming_message: HookDefinition<{ stoppable: true; data: _IncomingMessages & { '*': AnyIncomingMessage; }; }>; after_outgoing_message: HookDefinition<{ stoppable: false; data: _OutgoingMessageResponses & { '*': AnyOutgoingMessageResponse; }; }>; after_outgoing_call_action: HookDefinition<{ stoppable: false; data: _OutgoingCallActionResponses & { '*': AnyOutgoingCallActionResponse; }; }>; after_incoming_call_action: HookDefinition<{ stoppable: false; data: _IncomingCallActionResponses & { '*': AnyIncomingCallActionResponse; }; }>; }; export type HookData = { [THookType in utils.StringKeys>]: { [THookDataName in utils.StringKeys[THookType]['data']>]: HookDefinitions[THookType]['data'][THookDataName]; }; }; export type HookInputs = { [THookType in utils.StringKeys>]: { [THookDataName in utils.StringKeys[THookType]>]: ExtendedHandlerProps & { data: HookData[THookType][THookDataName]; }; }; }; export type HookOutputs = { [THookType in utils.StringKeys>]: { [THookDataName in utils.StringKeys[THookType]>]: { data?: HookData[THookType][THookDataName]; } & (HookDefinitions[THookType]['stoppable'] extends true ? { stop?: boolean; } : {}); }; }; export type HookHandlers = { [THookType in utils.StringKeys>]: { [THookDataName in utils.StringKeys[THookType]>]: (input: HookInputs[THookType][THookDataName]) => Promise[THookType][THookDataName] | undefined>; }; }; export type MessageHandlersMap = { [TMessageName in utils.StringKeys>]?: ((props: Omit[TMessageName]>[0], keyof InjectedHandlerProps>) => Promise)[]; }; export type EventHandlersMap = { [TEventName in utils.StringKeys>]?: ((props: Omit[TEventName]>[0], keyof InjectedHandlerProps>) => Promise)[]; }; export type StateExpiredHandlersMap = { [TStateName in utils.StringKeys>]?: ((props: Omit[TStateName]>[0], keyof InjectedHandlerProps>) => Promise)[]; }; export type HookHandlersMap = { [THookType in utils.StringKeys>]: { [THookDataName in utils.StringKeys[THookType]>]?: ((props: Omit[THookType][THookDataName]>[0], keyof InjectedHandlerProps>) => Promise[THookType][THookDataName]>>>)[]; }; }; export type WorkflowUpdateType = 'started' | 'continued' | 'timed_out'; export type WorkflowHandlersMap = { [TWorkflowUpdateType in WorkflowUpdateType]: { [TWorkflowName in utils.StringKeys]?: ((props: Omit[TWorkflowName]>[0], keyof InjectedHandlerProps | 'workflow'> & { workflow: client.Workflow; }) => Promise)[]; }; }; export type OrderedMessageHandlersMap = { [TMessageName in utils.StringKeys>]?: { handler: MessageHandlers[TMessageName]; order: number; }[]; }; export type OrderedEventHandlersMap = { [TEventName in utils.StringKeys>]?: { handler: EventHandlers[TEventName]; order: number; }[]; }; export type OrderedStateExpiredHandlersMap = { [TStateName in utils.StringKeys>]?: { handler: StateExpiredHandlers[TStateName]; order: number; }[]; }; export type OrderedHookHandlersMap = { [THookType in utils.StringKeys>]: { [THookDataName in utils.StringKeys[THookType]>]?: { handler: HookHandlers[THookType][THookDataName]; order: number; }[]; }; }; export type OrderedWorkflowHandlersMap = { [TWorkflowUpdateType in WorkflowUpdateType]: { [TWorkflowName in utils.StringKeys]?: { handler: WorkflowHandlers[TWorkflowName]; order: number; }[]; }; }; export type RegisterHandler = (props: CommonHandlerProps) => Promise; /** * Bot handlers without InjectedHandlerProps * * TODO: * the consumer of this type shouldnt be able to access "*" directly; * "*" is meant the user who registers an handler, not for the user who calls the handler */ export type BotHandlers = { registerHandler?: RegisterHandler; actionHandlers: ActionHandlersMap; messageHandlers: MessageHandlersMap; eventHandlers: EventHandlersMap; stateExpiredHandlers: StateExpiredHandlersMap; hookHandlers: HookHandlersMap; workflowHandlers: WorkflowHandlersMap; }; /** identical to BotHandlers, but contains the injected properties */ export type InjectedBotHandlers = { registerHandler?: RegisterHandler; actionHandlers: ActionHandlers; messageHandlers: { [TMessageName in utils.StringKeys>]?: MessageHandlers[TMessageName][]; }; eventHandlers: { [TEventName in utils.StringKeys>]?: EventHandlers[TEventName][]; }; stateExpiredHandlers: { [TStateName in utils.StringKeys>]?: StateExpiredHandlers[TStateName][]; }; hookHandlers: { [THookType in utils.StringKeys>]: { [THookDataName in utils.StringKeys[THookType]>]?: HookHandlers[THookType][THookDataName][]; }; }; workflowHandlers: { [TWorkflowUpdateType in WorkflowUpdateType]: { [TWorkflowName in utils.StringKeys]?: WorkflowHandlers[TWorkflowName][]; }; }; }; type _GetPluginPrefix = `${TKey}#`; type ImplementedActions<_TBot extends common.BaseBot, TPlugins extends Record> = utils.UnionToIntersection]: { [TAction in utils.StringKeys as `${_GetPluginPrefix>}${utils.Cast}`]: TPlugins[TPlugin]['actions'][TAction]; }; }>>; type UnimplementedActions> = Omit>>; export type ImplementedActionHandlers> = { [K in utils.StringKeys>]: ActionHandlers[utils.Cast>]; }; export type UnimplementedActionHandlers> = { [K in utils.StringKeys>]: ActionHandlers[utils.Cast>]; }; export type ServerProps = CommonHandlerProps & { req: Request; self: BotHandlers; }; export {};