Skills and Apps¶
One of the benefits writing your bots in Bubblescript is the fact that you can reuse code in different dialogs. With Skills, you can reuse parts of one bot, within another bot. Skills can therefore be thought of as a tool that you can buy. Programmers can think of Skills as libraries or packages. A skill can depend on other skills, just as a drill can depend on a drill-bit to perform its function. Skills are developed in a bot, and then a version of it can published as a package. This published skill can then later be installed in a different bot.
Apps can be seen as a template bot that is preconfigured for a specific purpose. In an app-bot, the Bubblescript code of the bot cannot be changed anymore, it is read-only, because the app has a specific purpose and should not be used for something else. However, the bot configuration, CMS and Flows of an app-bot can of course still be changed by the end user, to be able to customize the bot up to a certain point. Just like skills, apps are versioned, can be published, and are developed inside a bot.
Managing Skills¶
Installing an external Skill¶
Skills provided by DialoX can be installed through the Packages main-menu item. There, on the Store subpage, you can find an overview of skills that are available for installation and the skills that are already installed in your bot. A skill is installed using the "Install" button in the pop-up.
All the dependencies for a skill will be installed automatically.
Configuring a Skill¶
Once a skill is installed, it can, depending on the skill, be configured to perform its task in a way you desire. Configuration of the Skill is done in the "Installed" section by clicking on the cogwheel of a Skill, or via the entry in the Settings main menu.
Uninstalling a Skill¶
Skills can be uninstalled in the "Installed Skills" by clicking on a Skill and then on the "Uninstall Skill" button. If the Skill you are trying to uninstall has another installed Skill that depends on it, an error will be shown with the name(s) of the Skill(s) that depend on it. Uninstall those skills first.
Disabling a skill¶
Skills can be temporarily disabled. This functionality can be used to first install the skill and then configure it, without exposing the skill yet to the world.
Skill development¶
A skill exists in its own folder in the bot, where all the files that are
necessary for the Skill to function properly are stored. A skill name is always
formatted as namespace/skill_name
, where namespace
is a common prefix to
group related skills together (e.g a company name). The folder name where a
skill resides in MUST be equal to the same namespace/skill_name
.
Skills that are being developed ("native skills") live always in a subfolder in
its 'host bot'. For instance, when developing a skill named acme/example
, the
skill metadata file must be called acme/example/skill
and all files live in
that same folder (sharing the acme/example/
prefix) are considered skill files
and are treated as a single package of files.
Through the 'packages' menu item, it is possible to publish native skills into
the app store. For this to work, as a developer you must have access to the
skill's namespace (acme
in the previous example). When publishing a skill, you
give a change log text and then the skills files are packaged and stored in a
separate package repository, independent of the host bot.
Published skills are available for installation in other bots, if the environment of those bots is configured to show the published skill(s) in its skill store, or when a skill is listed as an optional dependency of a bot app (see Bot Apps).
Skill Metadata¶
The information about the Skill is stored in the skill
YAML file that resides
in the directory of the Skill. This file has the following fields:
- name
string
, mandatory, unique identifier of the Skill, - title
string
, mandatory, a display title for the Skill, - icon
string
, mandatory, the icon that is displayed in the Skills section (blueprintjs icon), - subtitle
string
, mandatory, a small description of what the Skill does. - author
string
, - dependencies
list of string
, a list of names of other Skills that this Skill depends on, - optional_dependencies
list of string
, a list of names of other Skills that need to be ordered below this skill, - settings
settings schema
, a CMS definition of the settings for this Skill, - tags
list of strings
, a list of tags that apply to this Skill, - version
string
, a semantic version of the Skill at the time of publishing.
A minimal skill
YAML file:
name: "company/skill"
title: "My Skill"
subtitle: "Provides basic behaviour"
icon: "badge"
version: "1.0.0"
dependencies:
- "bsqd/base"
Skills optionally have a settings
key which can expose a configuration / settings screen for the skill:
name: "company/skill"
title: "My Skill"
subtitle: "Provides basic behaviour"
icon: "badge"
version: "1.0.0"
settings:
type: form
storage:
type: script
script_title: config/company_skill
title: Users
icon: people
form:
schema:
type: object
properties:
name:
title: "A configurable string field"
type: string
Dependencies¶
Skill dependencies give a list of other skills that must be installed if this skill is to be used. They can be in the form of a simple array of strings:
dependencies:
- bsqd/base
or in the form of a skill name + requirement string, to better specify the version constraint the dependent skill must meet:
dependencies:
- bsqd/base == 1.0.0
This specifies that only bsqd/base
version 1.0.0 should be used as the
dependency. See the Elixir docs on version
requirements
for more information on how to specify these requirements.
Testing¶
Often you develop multiple skills inside a single bot. In that case, you might want to write test cases that only cover a single skill. In such cases, it is best to disable the other skills in the bot that are not the focus of the current test.
It is possible to automatically disable certain skills for certain test files,
by setting the @disabled_skills
constant in the test file, like this:
@disabled_skills ["b"]
test "Only testing skill a"
expect "Hello from a"
end
Migrations¶
Sometimes it can be necessary to run code when a skill upgrades its version, or
when it is installed. For this purpose, skill migrations exist. Migrations are
tasks, which live within the folder of the skill, which are annotated with a
migrate_to:
attribute.
Skill upgrade migrations¶
When a skill is upgraded, the following happens:
- The source version of the skill is retrieved; this is the currently published version number of the skill;
- The target version of the skill is retrieved from the skill in the store;
- From the skill's scripts, all tasks are gathered which have a
migrate_to
attribute with a version number which lies between the source and the target version - These tasks, ordered by their version number, are then performed in the bot.
All log
statements in the tasks are collected and presented to the developer
afterwards. When a migration task fails, the upgrade of the skill is cancelled.
An error can be raised from within a task by using the
fatal
statement.
Typically, the write_script(title, contents)
function is used inside the
migration task to modify some of the content on the bot while the skill is
upgrading.
Example:
task migrate_to: "5.1.4" do
log "Starting content migration"
data = []
repeat i in keys(@answers) do
data[i] = @answers[i]
# add a new attribute
data[i].enabled = true
end
write_script("answers", data)
log "All done"
end
The
write_script
function can only be called from inside the studio, and called by a developer with enough permissions to change the bot's script.Migration tasks can be tested in the studio by giving the task a name, and from the debug console calling
perform
on the task.
Skill installation migration¶
To run a migration when a skill is newly installed into a bot, specify :install
as the version:
task migrate_to: :install do
log "Installing the skill..."
# do your things here
log "All done"
end
App development¶
A bot containing an app can be in three states:
Installed - in this case, the bot has an app
YAML file at the top level
with all the bot metadata. The rest of the bot, with the exception of its
content / flow files, are locked for editing. To change the bot's code, an
update of the app must be published and then the target bot must be updated to
that new version.
Native - in this case, the bot is used to develop the app. To be able to
edit the bot in this case, there must be an app YAML file but it is called
app.dev
. A minimal app.dev
file looks like the following:
name: company/first_app
version: 1.0.0
title: My first app
subtitle: This will say hello and then hang up
For native apps, the Packages main menu has a Development section from which the app can be published to the store. If the app requires any skills, these must be installed inside the native app bot.
A third app state exists, unlocked. In this case the "unlock" operation in
the bot advanced settings renames the app
file to app.unlocked
, causing the
bot to behave like a normal bot. This also disables any app updates et
cetera. Unlock should only be used in emergency cases. To lock a bot again,
rename the file back to app
.
Editable scripts¶
Once an app is installed, all its scripts are in principle fixed and users are not able to edit the scripts of the bot. This is fine for most scripts because they are part of the "app" and should not be touched. However, exceptions need to be specified for "content" files.
In the app.dev
file you can add an editable_scripts
section that specifies a
list of script patterns which will be editable once the app is installed:
editable_scripts:
- translations
- flows/*
- content/*
- settings/*
App publishing¶
Once an app is being published, the following checks are done:
-
The bot does not contain any native skills. Only skills inside deps/ are allowed in apps.
-
All skills that are installed in the bot must be part of the
dependencies[]
oroptional_dependencies[]
arrays in the app metadata (installing a skill from the store adds it todependencies
automatically when anapp.dev
file is present) -
The apps' namespace must exist and developer is allowed to publish to it.
-
All the apps' dependencies have an equivalent published skill release.
-
The app name is not already published as a skill.
-
If app is already published earlier, it must not be archived
-
The app name + version is not already published and the version bigger than the latest published version.
If all checks are OK, the app.dev
YAML file is transformed into the app
file:
-
The apps' dependencies and optional dependencies are both "frozen" at their installed versions. This means that the version requirement for the dependent skills are strictly set to their version numbers. This ensures that a certain version of an app always installs a well-known combination of skills plus their versions.
-
The bot's profile picture is set as the
icon
in the app metadata -
A list of
supported_locales
is added to the app metadata: only the locales that are configured in the bot settings will be allowed to set in a bot that installs this app. This is to ensure that a target bot explicitly supports certain languages and no untranslated strings occur. -
The list of
supported_frontends
is taken from theallowed_frontends
list in the studio.yml file, to ensure that only those explicitly listed channels can be used in this app. -
All bot scripts are collected, with the exception of the deps/ folder, and uploaded in a tarball, similar to how skill publishing is done.
App upgrade process¶
- All installed skills which are not part of the new app's dependencies (and optional dependencies) are removed.
- All new versions of the app skills are installed
- All new versions of the app optional skills are installed
- Skill migrations are run
Content files are not overwritten by an app update, except if they were not changed by the user between app updates.
Disolvable apps¶
To support legacy bot development flows, where the user installs a template bot
(instead of an app), and then starts editing its code, without ever wanting to
update the template to a newer version, a special app metadata attribute is
introduced: dissolve: true
.
When an app is installed that has dissolve: true
specified, the installation
process will remove the app
file from the bot: therefore the bot behaves again
like an oldschool, non-updateable, editable "template bot".