Spec ID: OVOS-INSTALL-1 · Version: 1 · Status: Draft
This specification defines the bus surface by which an administration client installs and uninstalls Python packages into a running OVOS service: two topics, the payload field that addresses one service among several, and the reply they produce.
A deployment split across containers runs each plugin family in the service that loads it. A speech-to-text plugin installed into the skills container is never loaded, so a client needs to name the environment an install lands in. It names it in the payload, and a request that names nobody reaches every installer.
Dependencies: OVOS-MSG-1 (envelope and the reply derivation).
The key words MUST, MUST NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY are used as in RFC 2119.
This specification defines: the install and uninstall request topics, the payload field that addresses one service, the form of a service name, the request payload, the reply topics and their payloads, the error vocabulary, the enablement gate, the fan-out a client must expect, and the pre-spec suffixed topics it replaces.
It does not define: how a service loads a plugin once installed, plugin discovery, the package manager or constraint files an installer uses, which plugin families belong to which service, package naming, or any authorization beyond the single enablement flag of §5. Authorization of who may install is a layer-2 concern (OVOS-MSG-1 §3.4).
| Topic | Meaning |
|---|---|
ovos.pip.install |
Install the named packages. |
ovos.pip.uninstall |
Uninstall the named packages. |
Both are static dotted strings. A service that installs plugins MUST subscribe to both.
No topic carries the target. OVOS-MSG-1 §2.1.1 puts addressing in the
payload: "Nothing about a Message's target travels in a dotted topic:
addressing beyond the topic is payload (data)", and it admits only
two enumerable runtime-shaped dotted patterns, a per-component
introspection topic and a per-component scheduled event. A topic naming
the service to install into is neither, so the target is a payload field
(§2.2). The suffixed spelling deployments already use is catalogued in
§8.
data.service_name names the single service a request is for.
data.service_name |
Effect |
|---|---|
| absent | Every installer acts and answers. |
| present | Only the installer whose own service name matches acts. |
An installer that receives a request naming a different service MUST ignore it: it installs nothing and MUST NOT answer, not even to decline. A refusal from every other installer on the bus would turn one addressed request into a burst of replies that a client cannot tell from the real answer.
An installer MUST compare service_name exactly. It is an
identifier, not a pattern: no case folding, no prefix matching.
A service_name naming a service that is not on the bus is answered by
nobody, exactly as a request to a stopped service is (§6).
A service_name is the service's own process or module name written with
underscores, in the case the service itself uses. It is not lowercased:
ovos_PHAL is the name PHAL registers, not ovos_phal.
The names in use:
service_name |
Service |
|---|---|
ovos_audio |
the audio output service |
ovos_dinkum_listener |
the audio input service |
ovos_gui |
the GUI service |
ovos_PHAL |
the PHAL daemon |
ovos_PHAL_admin |
the privileged PHAL daemon, a separate process |
ovos_core |
the skills service |
A service that is not listed chooses its own name by the same rule. Two services on one bus MUST NOT share a service name, since the name is the whole of the addressing.
Both topics carry the package list, and optionally the service that the request is for:
{
"type": "ovos.pip.install",
"data": {
"packages": ["ovos-tts-plugin-piper"],
"service_name": "ovos_audio"
}
}packages is a list of package requirement strings. An installer
MUST treat a request whose packages is absent or empty as a failure
and answer with the no packages to install error of §4.2 rather than
succeeding silently, and MUST apply the §2.2 addressing check first,
so a request for another service produces no reply at all.
service_name is optional (§2.2).
An installer answers with the reply derivation of OVOS-MSG-1 §5.2, on
the base topic, never on a suffixed one:
| Request | Reply on success | Reply on failure |
|---|---|---|
ovos.pip.install |
ovos.pip.install.complete |
ovos.pip.install.failed |
ovos.pip.uninstall |
ovos.pip.uninstall.complete |
ovos.pip.uninstall.failed |
The reply topic does not vary with service_name. An installer MUST
NOT answer on a service_name-suffixed reply topic, and a client
MUST NOT subscribe to one. A client tells replies apart by the
service_name it addressed, not by the topic it hears.
The success reply carries no data. The failure reply carries an error
key (§4.2).
ovos.pip.install.failed and ovos.pip.uninstall.failed carry an
error string from this vocabulary:
error |
Meaning | Scope |
|---|---|---|
pip disabled in mycroft.conf |
Installation is not enabled (§5). | the answering configuration |
no packages to install |
packages was absent or empty (§3). |
the request |
skill url validation failed |
A supplied URL was rejected. | the request |
error in pip subprocess |
The package manager failed. | the answering environment |
The scope column is normative for a client waiting on a broadcast. The
first three describe the request or one configuration and are the same
answer whichever installer sends them. error in pip subprocess
describes one environment only: another service may still succeed, so a
client MUST NOT treat it as the outcome of a broadcast.
Installation is gated by the deployment's skills.installer.allow_pip
configuration key, and the RECOMMENDED default is disabled. An installer
whose gate is closed MUST NOT install or uninstall anything, and
MUST answer with the pip disabled in mycroft.conf error rather than
staying silent.
A silent refusal is indistinguishable from an absent service, and leaves a client waiting out its own timeout for an answer that will never come.
A request with no service_name is answered once per installer on the
bus. A client MUST NOT assume it produces a single reply, and
MUST NOT treat the first reply as the outcome of the whole request,
since a later installer may still answer.
A request naming a service_name is answered exactly once, by that
service, because every other installer ignores it in silence (§2.2).
A service_name naming a service that is not on the bus is answered by
nobody. A client MUST bound its own wait rather than block forever.
- subscribe to
ovos.pip.installandovos.pip.uninstall(§2.1); - act on a request whose
data.service_nameis absent or matches its own service name, and ignore any other in silence, answering nothing (§2.2); - answer every request it accepts on the base reply topic, using the
replyderivation (§4.1); - answer a request with no packages with the
no packages to installerror rather than reporting success (§3); - answer with
pip disabled in mycroft.conf, and install nothing, when the enablement gate is closed (§5); - use an
errorvalue from the §4.2 vocabulary.
- accept the pre-spec suffixed topics for one stable cycle, so a client
that has not moved to
data.service_namekeeps working (§8); - unregister its handlers on shutdown, so a stopped service stops answering for an environment it no longer owns.
- accept more than one reply to a broadcast (§6);
- bound its wait, since a
service_namemay name a service that is not running (§6); - treat
error in pip subprocessas describing one environment rather than the whole broadcast (§4.2).
- set
data.service_namewhenever it knows which service loads the plugin family being installed, and leave it absent otherwise (§2.2); - emit the canonical topics rather than the pre-spec suffixed forms, which are removed after one stable cycle (§8).
Deployments predating this specification address one service with a suffixed topic rather than a payload field:
| Pre-spec topic | Canonical equivalent |
|---|---|
ovos.pip.install.<service_name> |
ovos.pip.install with data.service_name |
ovos.pip.uninstall.<service_name> |
ovos.pip.uninstall with data.service_name |
These are catalogued, not specified. They put the target in the topic, which OVOS-MSG-1 §2.1.1 reserves for the payload, and they match neither enumerable dotted pattern that clause allows.
An installer SHOULD keep answering them for one stable cycle so a client that has not moved is not broken, and SHOULD log their use as deprecated. They are removed at the next major version. A client MUST NOT emit them, and a specification MUST NOT define a new topic of this shape.
- OVOS-MSG-1 — the envelope, the
replyderivation, and §2.1.1, which puts a Message's target in the payload rather than the topic.