Microsoft Bot Framework Direct Line JS Client

repository·master·Indexed 42 days ago

https://github.com/microsoft/botframework-directlinejs

A JavaScript client library for the Microsoft Bot Framework Direct Line 3.0 protocol. It enables communication between client applications and bots using a state-machine based connection lifecycle, supporting WebSockets, polling, and activity streaming. Key features include conversation resumption via conversationId and watermarks, activity monitoring through RxJs observables, and support for voice/multimodal capabilities. Version 0.16.1-0.

Tokens
7.3K
Snippets
31
Records
37
Agent score
52%

What's inside Direct Line JS

  1. Understand the DirectLineJS state machine

    master

    DirectLineJS operates as a state machine where the current state is defined by the connectionStatus$ observable. Understanding these states is critical for managing connection lifecycles and error handling:

    • Uninitialized: The initial state after calling new DirectLine().
    • Connecting: The adapter is attempting to establish a connection. This state includes automatic retries with backoff.
    • Online: The connection is established. A connection is considered "stable" after being in this state for more than 1 minute, which resets the retry counter and removes backoff on the first retry attempt after a subsequent disconnection.
    • FailedToConnect: The state reached when all retry attempts are exhausted.
    • Ended: The terminal state reached after calling end(). All resources are released, and activity$ and connectionStatus$ observables are completed.
  2. Subscribe to activities and connection status

    master

    Both activity$ and connectionStatus$ are shared observables.

    • The first subscriber triggers the connection.
    • Subsequent subscribers will only observe activities that occur from the moment they subscribe (they do not receive a replay of past activities).
    • connectionStatus$ allows you to monitor the state machine transitions (e.g., moving from Connecting to Online).
  3. Resume an existing conversation

    master

    To prevent losing context when a page refreshes or a tab closes, you can resume a conversation using a stored conversationId.

    When using a secret: Provide the conversationId during initialization.

    When using a token: Provide the token, streamUrl (retrieved via the Reconnect API), and the conversationId.

    Retrieving history: You can replay conversation history by providing a watermark (an activity 'bookmark') along with the conversationId.

    import { DirectLine } from 'botframework-directlinejs';
    
    // Resuming with a secret
    const dlSecret = new DirectLine({
        secret: /* SECRET */,
        conversationId: /* the conversationid you stored from previous conversation */
    });
    
    // Resuming with a token and streamUrl
    const dlToken = new DirectLine({
        token: /* the token you retrieved while reconnecting */,
        streamUrl: /* the streamUrl you retrieved while reconnecting */,
        conversationId: /* the conversationid you stored from previous conversation */
    });
    
    // Resuming with history via watermark
    const dlHistory = new DirectLine({
        token: /* token */,
        streamUrl: /* streamUrl */,
        conversationId: /* conversationId */,
        watermark: /* a watermark you saved from a previous conversation */,
        webSocket: false
    });
  4. Run automated tests for Direct Line Streaming Extensions

    master

    To verify the codebase, you can run the automated test suite using Jest. Jest will rebuild the source code on-the-fly, so a manual build step is not required before testing.

    Steps:

    1. Clone the repository branch.
    2. Run npm ci (ignore node-gyp warnings).
    3. Run npm test.

    To run tests in watch mode, use: npm test -- --watch

    npm ci
    npm test
  5. Build the development bundle for Direct Line Streaming Extensions

    master

    To create a development-ready JavaScript bundle, clone the repository and run the build command. The resulting bundle at /dist/directline.js is not minified and includes instrumentation for code coverage.

    Steps:

    1. Clone the repository.
    2. Run npm ci to install dependencies.
    3. Run npm run build.

    Note: You may see node-gyp errors during npm ci; these are warnings and can be ignored.

    npm ci
    npm run build
  6. Establish a connection to the bot

    master

    To initiate a connection, you must subscribe to the activity$ observable.

    Important: Subscribing to connectionStatus$ alone will not establish a connection. The first subscription to activity$ triggers the connection process.

    // This triggers the connection
    directLine.activity$.subscribe(activity => {
      console.log('Received activity:', activity);
    });
  7. Recover from connection failure with reconnect()

    master

    If the adapter reaches the FailedToConnect state (all retries exhausted), it enters a "hibernation" mode. You can revive the adapter by calling reconnect().

    • reconnect() resets the retry counter and attempts to establish a connection.
    • It is safe to call reconnect() multiple times or call it during app visibility changes, as calling it while the adapter is already active (e.g., Online) does nothing.
    • You cannot call reconnect() once end() has been called.
    // Call this to wake up the adapter after a FailedToConnect state
    directLine.reconnect();
  8. Integrate Direct Line Streaming Extensions with Web Chat

    master

    You can use the latest DirectLineJS bundle with Web Chat 4.5.2 by including the specific scripts in your HTML. This allows Web Chat to utilize the streaming extensions via the directLine option in renderWebChat.

    <!DOCTYPE html>
    <html lang="en-US">
      <head>
        <title>Web Chat with Streaming Extensions</title>
        <script src="https://cdn.botframework.com/botframework-webchat/latest/webchat-es5.js"></script>
        <script src="https://github.com/microsoft/BotFramework-DirectLineJS/releases/download/dev-streamingextensions/directline.js"></script>
        <style type="text/css">
          html, body, body > div { height: 100%; }
          body { margin: 0; }
        </style>
      </head>
      <body>
        <script>
          const { DirectLine } = window.DirectLine;
          const webChatElement = document.createElement('div');
    
          window.WebChat.renderWebChat({
            directLine: new DirectLine({
              conversationId: '<required>',
              domain: 'https://.../.bot/v3/directline',
              token: '<required>',
              webSocket: true
            })
          }, webChatElement);
    
          document.body.append(webChatElement);
        </script>
      </body>
    </html>
  9. Use botframework-directlinejs in a Node.js environment

    master

    The library uses RxJs/Ajax which is designed for DOM environments. To use it in Node.js, you must provide polyfills for XMLHttpRequest and WebSocket by installing ws and xhr2 and assigning them to the global object at the start of your application.

    // 1. Install dependencies:
    // npm install --save ws xhr2
    
    // 2. Add to the top of your main application file:
    global.XMLHttpRequest = require('xhr2');
    global.WebSocket = require('ws');
  10. Test Streaming Extensions in Web Chat and MockBot

    master

    You can manually test the latest successful build using the Web Chat loader and MockBot:

    1. Navigate to https://compulim.github.io/webchat-loader/
    2. Click Dev or select <Latest development bit> from the dropdown.
    3. Click [Public] MockBot with Streaming Extensions.
    4. Click Open Web Chat in a new window.

    Once in the chat, type help to see a list of available commands for the MockBot.

  11. Initialize DirectLineStreaming with options

    master

    To use streaming connections, instantiate the DirectLineStreaming class. You must provide a token and the domain of your Direct Line service. You can optionally provide a conversationId to resume a session, a botAgent string to identify your client, and a networkInformation object to enable automatic reconnection on network changes.

    Note: The networkInformation option must be a NetworkInformation-like instance that extends the EventTarget interface and has a type property.

    const streamingClient = new DirectLineStreaming({
      token: 'YOUR_TOKEN',
      domain: 'https://directline.botframework.com',
      conversationId: 'YOUR_CONVERSATION_ID',
      botAgent: 'my-custom-agent',
      networkInformation: window.navigator.connection // Example for browser
    });