question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

We need two things, to make it perfect.

See original GitHub issue

A release made up with rollup or webpack, and a .rive loader for webpack.

Almost solved the loader issue with CopyWebpackPlugin

  plugins: [
  new CopyWebpackPlugin([{
      from: path.resolve(__dirname, '../client/views/ai/brain'),
      to: path.resolve(__dirname, './dist/brain'),
      test: /\.rive$/
    }], {
      debug: 'info'
    }),
  ],

But I am getting that error

brain.js?add9:278 Uncaught (in promise) TypeError: Cannot read property ‘length’ of undefined at Brain._getReply (brain.js?add9:278) at Brain.reply (brain.js?add9:36) at RiveScript.replyAsync (rivescript.js?16fe:600) at VueComponent._callee3$ (index.js?1bf1:61) at tryCatch (runtime.js?4a57:65) at Generator.invoke [as _invoke] (runtime.js?4a57:303) at Generator.prototype.(:8080/anonymous function) [as next] (webpack-internal:///433:117:21) at step (index.js?1bf1:2) at eval (index.js?1bf1:2) at new Promise (<anonymous>)

Its something related to this line in brain.js if (this.master._sorted.thats[top].length) {

That

// constructor polyfill
if (!USE_NATIVE) {
  // 25.4.3.1 Promise(executor)
  $Promise = function Promise(executor) {
    anInstance(this, $Promise, PROMISE, '_h');
    aFunction(executor);
    Internal.call(this);
    try {
      executor(ctx($resolve, this, 1), ctx($reject, this, 1));
    } catch (err) {
      $reject.call(this, err);
    }
  };

and that

if (this.master._topics.__begin__) {
      begin = this._getReply(user, "request", "begin", 0, scope);
      if (begin.indexOf("{ok}") > -1) {
        reply = this._getReply(user, msg, "normal", 0, scope);
        begin = begin.replace(/\{ok\}/g, reply);
      }
      reply = begin;
      reply = this.processTags(user, msg, reply, [], [], 0, scope);
    } else {
      reply = this._getReply(user, msg, "normal", 0, scope);
    }

My guess, is babel-loader fucking up things (edit isn’t I’ve tested, its probably babel-polyfill) Edit: Wasn’t babel, I’ve tested it, and I can’t remove babel-polyfill because of async await support.

Issue Analytics

  • State:open
  • Created 5 years ago
  • Comments:22 (10 by maintainers)

github_iconTop GitHub Comments

3reactions
kjleitzcommented, Aug 5, 2018

This is a simplified version of the pattern I use:

// this can be found in 'bot/bot_engine'

import RiveScript from 'rivescript';
import config from 'bot/config';

class BotEngine {
  queue(onSuccess = () => {}, onError = () => {}) {
    if (this._engine) {
      onSuccess(this._engine);
      return;
    }
    const rsEngine = new RiveScript();
    rsEngine.loadFile(config.brainFiles).then(() => {
      rsEngine.sortReplies();
      this._engine = rsEngine;
      onSuccess(this._engine);
    }).catch((error) => {
      console.warn(`Error loading brainfiles: ${error}`);
      if (this._engine) delete this._engine;
      onError(error);
    });
  }
}

const botEngine = new BotEngine();

export default botEngine;

The BotEngine class allows me to wrap the engine so that I can pass messages to it without worrying if everything’s been initialized yet. An example of its use in a Vue component might be like this:

<template>
  <div>
    <ul class="responses">
      <li v-for="message in messages">{{message}}</li>
    </ul>
    <input v-model="inputMessage" @keyup.enter="sendMessage"/>
  </div>
</template>

<script>
import botEngine from 'bot/bot_engine';

export default {
  data() {
    return {
      messages: [],
      inputMessage: '',
    };
  },

  methods: {
    sendMessage() {
      this.messages.push(this.inputMessage);
      botEngine.queue((engine) => {
        engine.reply('keegan', this.inputMessage, this).then((outputMessage) => {
          this.messages.push(outputMessage);
        });
        this.inputMessage = '';
      });
    },
  },
};
</script>

You probably don’t even need the queue, really, as long as you’re not immediately sending messages to the bot before it has a chance to asynchronously load the files and sort the replies… but if you are, then that might be a pattern you should consider. Hope it helps.

2reactions
kjleitzcommented, Mar 27, 2020

@IdealPress no worries! I left config kind of ambiguous. I was imagining that you’d make a separate file (bot/config.js) for your project configuration, and you’d have an array of URIs (which point to your .rive files) there in a property called brainFiles. Like this:

// in bot/config.js

const config = {
  // ...other config...

  brainFiles: [
    // These are your `.rive` files; if you're in the browser it'll try to get them
    // over the network from "https://www.your.website/brain/begin.rive", and then
    // "https://www.your.website/brain/main.rive", and so on (you get the picture)
    '/brain/begin.rive',
    '/brain/main.rive',
    '/brain/some_other_stuff.rive',
    '/brain/et_cetera.rive',
  ],

  // ...other config...
};

export default config;

…but you don’t have to do it that way if you don’t have a separate config-like object in your project. You could just as easily plant it right in place, like:

// in bot/bot_engine.js

// ...

class BotEngine {
  queue(onSuccess = () => {}, onError = () => {}) {
    // ...
    rsEngine.loadFile([
      // These are your `.rive` files; if you're in the browser it'll try to get them
      // over the network from "https://www.your.website/brain/begin.rive", and then
      // "https://www.your.website/brain/main.rive", and so on (you get the picture)
      '/brain/begin.rive',
      '/brain/main.rive',
      '/brain/some_other_stuff.rive',
      '/brain/et_cetera.rive',
    ]).then(() => {
      // ...
    }
  }
}

// ...

Hope that helps!

Read more comments on GitHub >

github_iconTop Results From Across the Web

a plan and not quite enough time. Leonard Bernstein | Life ...
May 10, 2016 - To achieve great things, two things are needed: a plan, and not quite enough time. – Leonard Bernstein.
Read more >
Benjamin Franklin's last great quote and the Constitution
“I have the Honor to be with the greatest Esteem and Respect Sir, Your most obedient and most humble Servant,” Franklin said in...
Read more >
10 Reasons Why Imperfect is the New Perfect
1) Being imperfect is perfectly human. We all have flaws and embracing those flaws can be the difference between feeling happiness and ...
Read more >
200+ Time quotes: The best quotes about time - Clockify
Time quotes on waiting for the perfect moment ... 2. “Time is a created thing. To say 'I don't have time,' is to...
Read more >
13 Things You Should Give Up If You Want To Be Successful
First you have to take care of your health, and there are only two things you need to keep in mind: 1. Healthy...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found