Search code examples
javascriptnode.jstypescriptbotframework

What determines when 'bot.dialog' passes to the next function of the waterfall in Microsoft Bot Framework? (Node.js)


I'm working with Microsoft Bot Framework v3 in a company that has built a huge library on top of it. Their library is not documented, and it's hard for me to know when in bot.dialog you pass on to the next function of the waterfall 'automatically' and when you need to call next.

In the MS Bot Framework, things like builder.Prompts.text will pass the results on to the next function in the waterfall automatically, without having to call next. For example enter image description here

Is there something somewhere down in the MS Bot Framework original code that gets called every time the waterfall passes on to the next function? Then perhaps I could put a trace statement on that code and see which functions of their library call that and then trigger the transition automatically, without me having to call next explicitly.

Thanks for any help -- I'm aware that this function seems quite vague, but it's simply that I'm left on my own to understand their library, without documentation, and I'm unclear how their functions work (in contrast I understand how the original MS Bot Framework functions work, because there is documentation).


Solution

  • If you don't count the pseudo-waterfalls created by WaterfallDialog.createHandler, the only place the waterfall step counter gets incremented is in WaterfallDialog.dialogResumed, and that's only when the resume reason is not reprompt or back:

    public dialogResumed(session: Session, result: IDialogResult<any>): void {
        let step = session.dialogData[consts.Data.WaterfallStep];
        switch (result.resumed) {
            case ResumeReason.reprompt:
                // Ignore re-prompts
                return;
            case ResumeReason.back:
                step--;
                break;
            default:
                step++;
                break;
    
        }
        this.doStep(session, step, result);
    }
    

    When you talk about calling next, I presume you mean skip. It's worth noting that skip itself calls dialogResumed:

    var skip = (result?: IDialogResult<any>) => {
        result = result || <any>{};
        if (result.resumed == null) {
            result.resumed = ResumeReason.forward;
        }
        this.dialogResumed(session, result);
    };
    

    Apart from that, dialogResumed will only be called when a dialog on top of the waterfall dialog ends, so you're supposed to include prompts in your waterfall steps if you want the waterfall to advance automatically on subsequent steps.

    Since you mentioned wanting to use some kind of trace statement, there's no obvious place to put a trace statement in your own code that would execute whenever the waterfall advances to the next step. However, you could use WaterfallDialog.onBeforeStep to include a BeforeWaterfallStepHandler that executes before any step is processed, whether it's the next step or not:

    export type BeforeWaterfallStepHandler = (session: Session, step: number, args: any, next: (step: number, args: any) => void) => void;
    

    Notice that a BeforeWaterfallStepHandler does include a next parameter, but calling it just proceeds to the next handler rather than the next waterfall step (though you could call it with an incremented step value).

    Please remember that the v3 SDK is deprecated and everyone is encouraged to migrate to v4 as soon as possible. It will become increasingly difficult for you to get any help with v3.