Skip to content

6) Your first skill

Antoine Duval edited this page Sep 4, 2022 · 11 revisions

Prerequisites: If you haven't already, check out our Introduction to Skill development.

Architecture

The blank skill

We have created an empty skill for you which we have called "Blank Skill" which you can find here.
It is from this skill that we will base our work.

Here is the architecture of the skill that we will explain.

Not all of these files are necessary.

resources

This folder is not essential for the proper functioning of the skill.
It will contain files used by the "Store" tab of the server's GUI.
We still advise you to fill it in before publishing your skill.

screenshots

This folder will contain all the images you want users to see when they select your skill in the "Store" tab of the server's GUI.
It is important that you name them as follows: "1.jpg", "2.jpg", "3.jpg" ...

We recommend that your images are all the same size.
Your images will appear as a carousel (here in red).

info.json

This file is essential for your skill to be offered to NOVA users.
Here is an example of content:

{
	"worksOffline" : true, // This attribute is used to inform if the skill works offline.
	"description" : { // This attribute is used to describe the skill. It will be displayed in the language set by the user in the "Settings" tab of the server.
		"fr-FR": "Cette compétence est vraiment incroyable, elle vous permettra de ...",
		"en-US": "This skill is really amazing, it will allow you to..."
	},
	"language": [ // This attribute is used to inform users which languages your skill is compatible with.
		"fr-FR",
		"en-US",
		"es-ES",
		"it-IT",
		"de-DE"
	]
}

github-screenshot.jpg

Usually, for a GitHub user to understand the usefulness of your skill, you are asked to provide a screenshot of your skill in action.
This screenshot can be seen in the "README" file (here in red).

nova-icon.png

This image represents the application icon visible in the store.

nova-wallpaper.jpg

This image will be present in large in the skill store, behind "nova-icon.png", here in red.

src

This folder will contain all the files useful for your skill.
You will find examples below.

corpus

This folder contains other folders, one folder per language.
You will be able to define the means of giving instructions to NOVA (triggers), and the way in which it will respond to you.

fr-FR

This file contains in this example, the instruction sentences and their answers in French.

corpus.json

This file contains in this example, the instruction sentences and their answers in French.
You will notice that the utterance variables are represented by the sign {myVariableName} and that the response variables are represented by the sign %myVariableName%.
If the extraction of variables from utterances does not go well, you can try to specify the maximum number of words they can contain like this: {myVariableName|2} In this case, the variable cannot contain more than two words.
This text comprehension works without learning, which is a good thing, since we don't have enough data, but its operation requires you to fill in all the ways to trigger your actions. It might be redundant, but usually we only have about ten different ways to request an action, and it's fully customizable, you can even put funny things 😁.

If you want to know more about text recognition, I invite you to look at it repo.

{
  "name": "Random", // The name of your skill.
  "data": [
    {
      "intent": "Random.dice", // The name of the intent
      "utterances": [ // The ways to trigger it
        "Lance un dé",
        "Jette un dé"
      ],
      "answers": [ // The answers
        "Le dé est tomber sur %result%.",
        "%result%"
      ]
    },
    {
      "intent": "Random.between", // The name of the intent
      "utterances": [ // The ways to trigger it
        "Donne-moi un chiffre entre {first|1} et {last|1}",
        "Donne-moi un nombre entre {first|1} et {last|1}",
        "Donne-moi un chiffre aléatoire entre {first|1} et {last|1}",
        "Donne-moi un nombre aléatoire entre {first|1} et {last|1}",
        "Donne-moi un chiffre au hasard entre {first|1} et {last|1}",
        "Donne-moi un nombre au hasard entre {first|1} et {last|1}",
        "Donnez-moi un chiffre entre {first|1} et {last|1}",
        "Donnez-moi un nombre entre {first|1} et {last|1}",
        "Donnez-moi un chiffre aléatoire entre {first|1} et {last|1}",
        "Donnez-moi un nombre aléatoire entre {first|1} et {last|1}",
        "Donnez-moi un chiffre au hasard entre {first|1} et {last|1}",
        "Donnez-moi un nombre au hasard entre {first|1} et {last|1}",
        "Donne-moi un chiffre compris entre {first|1} et {last|1}",
        "Donne-moi un nombre compris entre {first|1} et {last|1}",
        "Donne-moi un chiffre aléatoire compris entre {first|1} et {last|1}",
        "Donne-moi un nombre aléatoire compris entre {first|1} et {last|1}",
        "Donne-moi un chiffre au hasard compris entre {first|1} et {last|1}",
        "Donne-moi un nombre au hasard compris entre {first|1} et {last|1}",
        "Donnez-moi un chiffre compris entre {first|1} et {last|1}",
        "Donnez-moi un nombre compris entre {first|1} et {last|1}",
        "Donnez-moi un chiffre aléatoire compris entre {first|1} et {last|1}",
        "Donnez-moi un nombre aléatoire compris entre {first|1} et {last|1}",
        "Donnez-moi un chiffre au hasard compris entre {first|1} et {last|1}",
        "Donnez-moi un nombre au hasard compris entre {first|1} et {last|1}"
      ],
      "answers": [ // The answers
        "%result%"
      ]
    }
  ]
}

public

...

CLIENT

...

css

This folder contains all the CSS files you want to use on the NOVA client GUI.
The file names don't matter.

img

This folder contains all the images you want to use on the NOVA client GUI.

js

This folder contains all the javascript files you want to use on the NOVA client GUI.
The file names don't matter.

client.js

This file will be executed by the server of a NOVA client.
Among other things, you can add code that will transfer socket calls from the client to the NOVA server and vice versa.

index.js

This file will be executed by the server of NOVA.
In the following example, we define actions linked to previous utterances.

const LIBRARIES = {
  Skill: require("../../../Libraries/Skill")
};

class Random extends LIBRARIES.Skill{
  constructor(_main, _settings) {
    super(_main, _settings);
    const SELF = this;

    this.Main.Manager.addAction("Random.dice", function(_intent, _socket){
      _intent.Variables.result = SELF.Random(1, 6);
      _intent.answer(_socket);
    });

    this.Main.Manager.addAction("Random.between", function(_intent, _socket){
      _intent.Variables.result = SELF.Random(_intent.Variables.first, _intent.Variables.last);
      _intent.answer(_socket);
    });
  }

  Random(_first_number, _last_number){
    const SMALLER = _first_number < _last_number ? _first_number : _last_number;
    const BIGGER = _last_number > _first_number ? _last_number : _first_number;
    return Math.floor(Math.random() * (BIGGER - (SMALLER - 1))) + SMALLER;
  }
}

module.exports = Random;

settings.json

This file will contain the user-editable settings for your skill.

{
  "Settings": {
    "serverIP": "http://192.168.1.12",
    "serverPort": "32400",
    "token": "abcdefghijklmnopqrstuvwxyz"
  }
}

package.json

This file is initialized by the "npm init" command.
It contains some info like the list of dependencies of your project.




Do you need more information?
Feel free to ask us questions on Discord.
Discord