npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@kognitalabs/shallot-framework

v1.0.1

Published

Small mild-flavored onion - or code clustered bulbs used for seasoning your chatbot.

Downloads

2

Readme

🧅 Shallot Framework (Kognita Lab)

Small mild-flavored onion - or code - clustered bulbs used for seasoning your chatbot.

Requirements

The Shallot Framework was made to have a perfect integration with a few services, making them required, are them:

  • Microsoft Language Understanding (LUIS) - A machine learning-based service to build natural language into apps, bots, and IoT devices. Quickly create enterprise-ready, custom models that continuously improve. - Paid Account Required

  • Sunshine: Omnichannel messaging platform - Sunshine Conversations connects your business software to all the world’s messaging channels for a more human customer experience. - Paid Account Required

  • MySQL Database - MySQL is a relational database management system based on SQL – Structured Query Language.

  • RabbitMQ Message Broker - With tens of thousands of users, RabbitMQ is one of the most popular open source message brokers. From T-Mobile to Runtastic, RabbitMQ is used worldwide at small startups and large enterprises.

If your stack already meet the requirements. You can skip to the next step of the README.

What is Shallot? / Why use Shallot?

The Shallot Framework is a framework that facilitates the development of chatbots.

With a simple language, it allows chatbot actions to be as action-oriented writing. You basically describe what the dialog will do.

Let's assume we have the welcome dialog. Just use set dialog.name and at the first parameter we use 'welcome', after that in the second parameter we use a callback which will receive the actions to take for the dialog specified.

  event.dialog.name('welcome', async (dialog) => {

Inside the callback just specify as example: For the HumanHelp intent forIntent change the dialog to human_help changeDialogTo and send the predicted intent response sendPredictedIntentAnswer.

  await dialog.forIntent('HumanHelp')
    .changeDialogTo('human_help')
    .sendPredictedIntentAnswer();

When putting it all together the result would be the following:

event.dialog.name('welcome', async (dialog) => {
  await dialog.forIntent('HumanHelp')
    .changeDialogTo('human_help')
    .sendPredictedIntentAnswer();
})

Installation

Install Shallot Framework with yarn:

  yarn add @kognitalabs/shallot-framework

Usage/Examples

Do you know how to create a chatbot? It's very easy, follow the steps below:

import { ShallotFramework as framework } from '@kognitalabs/shallot-framework';

framework.instance(async (shallot) => {
  /**
   * CONNECT REQUIRED SERVICES
   */
  await shallot.connectDatabase({
    host: process.env.MYSQL_HOST,
    port: process.env.MYSQL_PORT,
    username: process.env.MYSQL_USERNAME,
    password: process.env.MYSQL_PASSWORD,
    database: process.env.MYSQL_DATABASE,
    synchronize: true // When executing for the first time, set as true for database tables sync.
  });

  await shallot.connectLUIS({
    applicationId: process.env.LUIS_BOT_ID,
    endpoint: process.env.LUIS_ENDPOINT,
    endpointKey: process.env.LUIS_PREDICTION_KEY,
    name: process.env.LUIS_BOT_NAME
  });

  await shallot.connectSunshine({
    appId: process.env.SMOOCH_APP_ID,
    keyId: process.env.SMOOCH_API_KEY_ID,
    keySecret: process.env.SMOOCH_API_KEY_SECRET
  });

  await shallot.connectAMQP(process.env.AMQP_URL);

  /**
   * CONTROL YOUR BOT ACTIONS
   */

  /**
   * When the Sunshine event was conversation:message on RabbitMQ queue named conversation execute this callback(err, event) => Promise<AMQP.EventManager>
   */
  void shallot.when(
    'conversation:message', 'conversation', async (err, event) => {
      if (err !== undefined) {
        return event;
      }

      /**
       * If the conversation dialog in the received event is named 'welcome' returns a callback(dialog).
       */
      void event.dialog.name('welcome', async (dialog) => {
        await dialog.forNotListedOnes()
          .changeDialogTo('default')
          .sendIntentReplaceableAnswer('Greeting', {
            displayName: () => {
              const nameCompose = [];
              nameCompose.push(dialog.props.customer.props.givenName);
              nameCompose.push(dialog.props.customer.props.surname);

              return nameCompose.join(' ');
            }
          });
      });

      /**
       * If the conversation dialog in the received event is named 'default' returns a callback(dialog).
       */
      void event.dialog.name('default', async (dialog) => {
        await dialog.forIntent('HumanHelp')
          .changeDialogTo('human_help')
          .sendPredictedIntentAnswer();

        await dialog.forIntent('HowTo')
          .sendIntentAnswer('PostGreeting');

        await dialog.forIntent('Greeting')
          .sendHandWritedAnswer('Como posso ajudar?');

        await dialog.forIntent('None')
          .changeDialogTo('confusing')
          .sendPredictedIntentAnswer();

        await dialog.forNotListedOnes()
          .sendPredictedIntentAnswer();
      });

      /**
       * If the conversation dialog in the received event is named 'chating_with_human' returns a callback(dialog).
       */
      void event.dialog.name('chating_with_human', async (dialog) => {
        // Since this is an human help case, skip bot interference.
        dialog.skip();
      });

      void event.dialog.noneOf(['chating_with_human', 'default', 'welcome'], async (dialog) => {
        await dialog.forIntent('HowTo')
          .sendIntentAnswer('PostGreeting');

        await dialog.forNotListedOnes()
          .changeDialogTo('default')
          .sendPredictedIntentAnswer();
      });

      /**
       * Required function at the end, always run execute()
       */
      event.dialog.execute();
      return event;
    }
  );
});

Classes & Functions

(class): ShallotFramework

This class is a singleton and an instance can be received when you call for the method instance(callback) as you can see here:

ShallotFramework.instance(async (shallot) => {
  ...
  // The shallot receveid value is the singleton instance itself.
});

(method): ShallotFramework.when(event: EventType, queue: string, callback: CallbackFunction<AMQP.EventManager>): Promise< void >

This is one of the main methods of Shallot. It is the first line of the three-level callback structure. It is responsible to filter the event type, set a queue to list to and return the all formated Smooch Event into a Callback. So to make it work, use it!

You can define multiple events to the same queue.

@param event — The Event type as 'conversation:message'.

@param queue — The RabbitMQ queue to attach to.

@param callback — The magic portal to process the action! The callback return two values, are them Error and EventManager.

e.g: usage and return:

...
void shallot.when(
    'conversation:message', 'conversation', async (err, event) => {
      if (err !== undefined) {
        return event;
      }

      void event.dialog.name('welcome', async (dialog) => {
        ...

(class): EventManager

This class is the non-error return value of the ShallotFramework.when method.

Test Coverage

Currently our tests cover 51.06% percent of the lines in all files:

File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
:-------------------------------------------|---------|----------|---------|---------|---------------------------------------- All files |42.42| 33.9 |39.82|51.06|
src | 80 | 73.91 | 60 | 86.66 |
envvars.ts | 100 | 85.71 | 100 | 100 | 3
index.ts | 73.33 | 68.75 | 50 | 80 | 6-7
src/core | 31.42 | 17.84 | 28.12 | 37.18 |
framework.module.ts | 21.96 | 16.74 | 14.81 | 26.19 | ...162,167-175,181-210,216-237,252-286 injection.module.ts | 96.77 | 75 | 100 | 96.77 | 41
src/core/domain | 71.26 | 43.85 | 64.28 | 74.69 |
aggregate-root.abstract.ts | 75 | 55.55 | 66.66 | 81.81 | 5-6,11,33
entity.abstract.ts | 55.55 | 25 | 50 | 55.55 | 7,15-24
identifier.class.ts | 64.7 | 0 | 60 | 64.7 | 11-17,27
mapper.abstract.ts | 100 | 100 | 50 | 100 |
unique-id.abstract.ts | 78.26 | 57.14 | 75 | 85.71 | 5-6,11
src/core/logic | 50.25 | 36.48 | 51.28 | 55.97 |
generic-app.error.ts | 70.73 | 52.08 | 72.72 | 78.78 | 5-6,11,20,39-44
guard.class.ts | 39.74 | 31.66 | 44.44 | 42.62 | 10-16,46,59-81,88-96,104-128
result.class.ts | 50 | 25 | 42.1 | 56.92 | ...4-35,50-64,71,74,77,84,87,90,96,100 src/infrastructure/amqplib | 15.98 | 16.26 | 15 | 18.77 |
amqp.module.ts | 15.98 | 16.26 | 15 | 18.77 | ...,94-123,129-133,139-211,223-319,323 src/infrastructure/smooch | 29.54 | 23.23 | 21.95 | 40.67 |
smooch.module.ts | 29.54 | 23.23 | 21.95 | 40.67 | ...114-126,132-151,182-189,193-195,200 src/infrastructure/typeorm/entities | 75.45 | 55.4 | 59.61 | 85.62 |
answer-action.entity.ts | 76.47 | 53.06 | 61.53 | 85.71 | 5-6,11,20,44,70
answer.entity.ts | 77.19 | 59.18 | 60 | 87.23 | 5-6,11,20,67,77
bot-message.entity.ts | 73.58 | 53.06 | 53.33 | 83.72 | 5-6,11,20,42,83,94
conversation.entity.ts | 73.58 | 53.06 | 53.33 | 83.72 | 5-6,11,20,44,74,85
customer.entity.ts | 75.55 | 57.44 | 66.66 | 86.11 | 5-6,11,20,73
intent.entity.ts | 73.8 | 57.44 | 66.66 | 84.84 | 5-6,11,20,47
standard-column-group.abstract.ts | 86.2 | 58.06 | 100 | 95.65 | 5
user-message.entity.ts | 71.92 | 53.06 | 47.05 | 82.6 | 5-6,11,20,43,86,93,104
src/modules/dialogs | 78.57 | 68.75 | 75 | 77.77 |
index.ts | 78.57 | 68.75 | 75 | 77.77 | 6-7
src/modules/dialogs/cases | 50 | 49.13 | 55.67 | 62 |
create-bot-answer.case.ts | 72.02 | 65.11 | 91.3 | 88 | 5,15,32-33,120,142-144,148,153-155
create-conversation.case.ts | 70.18 | 65.71 | 87.09 | 82.09 | ...123,161,182-184,197-198,232,240-241 predict-user-message-utterance.case.ts | 22.31 | 19.81 | 13.04 | 30.76 | 5,12-17,21-44,69,77-85,97-121
send-customer-answer.case.ts | 18.18 | 19.13 | 15 | 23.59 | 5,12-17,21-44,67,75-135
src/modules/dialogs/domain | 57.14 | 44.84 | 52.5 | 67.76 |
bot-answer.entity.ts | 79.41 | 56.52 | 70 | 84.37 | 5-6,11,43,73
conversation.aggregate.ts | 44.86 | 40.45 | 40.81 | 56.84 | ...192,195-197,200-204,209-210,213-214 customer.entity.ts | 78.12 | 52.63 | 70 | 83.33 | 5-6,11,31,39
message.entity.ts | 80.55 | 52.38 | 72.72 | 85.29 | 5-6,11,36,53
src/modules/dialogs/errors | 82.53 | 42.85 | 68 | 85.24 |
dialog.errors.ts | 82.53 | 42.85 | 68 | 85.24 | 5-6,11,38,48,58,78,88,98
src/modules/dialogs/infrastructure | 20.17 | 15.83 | 16.43 | 22.89 |
composite-query.ts | 20.17 | 15.83 | 16.43 | 22.89 | ...393,396-433,444,447-471,482,485-487 src/modules/dialogs/infrastructure/mappers | 57.26 | 39.65 | 56 | 60.69 |
bot-answer.mapper.ts | 55.93 | 41.81 | 58.33 | 58.82 | 5-6,11,20,40,43-57,62-75
conversation.mapper.ts | 57.37 | 41.81 | 50 | 61.53 | 5-6,11,20,41,44-58,63-70
customer.mapper.ts | 58.92 | 45.09 | 58.33 | 62.5 | 5-6,11,20,38,41-52,56-62
message.mapper.ts | 56.89 | 32.39 | 58.33 | 60 | 5-6,11,20,38,42-59,64-75
src/modules/dialogs/repositories | 23.19 | 17.67 | 20.54 | 33.25 |
answer.repository.ts | 19.49 | 17.51 | 19.35 | 28.71 | ...29,33-56,60-68,80-82,85-101,107-144 bot-answer.repository.ts | 25.89 | 18.75 | 24 | 39.7 | 5-6,11,20,24-29,33-56,69,72-90
conversation.repository.ts | 22.02 | 15.67 | 17.64 | 28.45 | ...,75-79,82-91,98-121,127-144,150-176 customer.repository.ts | 25.42 | 18.42 | 21.42 | 37.83 | 5-6,11,20,24-29,33-56,70,73-83,89-103
message.repository.ts | 25 | 18.42 | 21.42 | 36.84 | 5-6,11,20,24-29,33-56,69,72-86,92-101


Authored/Licensed

All rights reserved to:

Contributors