openvibers/openvibe.contracts Commits

openvibe-contracts 0.418.0: bot.robot-manifest@1, a robot's own manifest (LOOI 1.0.0 frozen) (#470)

OP OpenVibers committed 14 h ago · c3de6ec3a6 · 60 files, +2433 −95

* openvibe-contracts 0.418.0: bot.robot-manifest@1, a robot's own manifest (LOOI 1.0.0 frozen)

**A robot's own manifest:** `bot.robot-manifest@1` (public, ADR-043) is what a robot's driver says the robot can do,
written and versioned by the driver's maker, so a new control is a version bump of the manifest instead of an
OpenVibe release (the plan in Maticus's LOOI thread, 11-10; his P7 command list on 11-12 is its first frozen version).

- **Commands:** kind, class (`motion`, `state`, `action`), the value's fields and ranges, `lifetime_ms`, the
  `delivery_ms` window Bot gives it, `min_left_ms` on arrival, `rate_per_s`, `release` (`stop`, `hold`, `none`;
  motion must stop or hold), `latched`, the telemetry key that `confirm`s it, and the `control` the panel draws
  (stick, slider, toggle, button, pad). An actuator names which one.
- **Telemetry:** a key, its fields (ranges, `boolean`, `string`, `ms`, `integer`, `number`, or a list of values),
  unit and range, `source` (`poll`, `push`, `connect`), `fresh_ms`, and its control (meter, readout, badge, list).
- **`frozen`:** true once the maker and OpenVibe have checked a version against the driver's real command list.
- Fixtures: LOOI 1.0.0 through the P7 tray (drive 500 ms life, delivery 1–300, release stop; head 500 ms, hold;
  headlights delivery 1–250, 50 ms left, 2 a second, latched; battery by poll with `at` in ms; who is driving), and
  three refusals (motion without a release, an actuator without its name, motion that is never released).

* ui.surface@1 parts say what they send or show (command, reads), in the robot manifest's terms

Changes

ddiff --git a/CHANGELOG.md b/CHANGELOG.md
iindex d064e857..54b4bd5d 100644
---- a/CHANGELOG.md
++++ b/CHANGELOG.md
@@@ -1,5 +1,25 @@
# Changelog
++## 0.418.0 — 2026-11-12
++
++**A robot's own manifest:** `bot.robot-manifest@1` (public, ADR-043) is what a robot's driver says the robot can do,
++written and versioned by the driver's maker, so a new control is a version bump of the manifest instead of an
++OpenVibe release (the plan in Maticus's LOOI thread, 11-10; his P7 command list on 11-12 is its first frozen version).
++
++- **Commands:** kind, class (`motion`, `state`, `action`), the value's fields and ranges, `lifetime_ms`, the
++ `delivery_ms` window Bot gives it, `min_left_ms` on arrival, `rate_per_s`, `release` (`stop`, `hold`, `none`;
++ motion must stop or hold), `latched`, the telemetry key that `confirm`s it, and the `control` the panel draws
++ (stick, slider, toggle, button, pad). An actuator names which one.
++- **Telemetry:** a key, its fields (ranges, `boolean`, `string`, `ms`, `integer`, `number`, or a list of values),
++ unit and range, `source` (`poll`, `push`, `connect`), `fresh_ms`, and its control (meter, readout, badge, list).
++- **`frozen`:** true once the maker and OpenVibe have checked a version against the driver's real command list.
++- **`ui.surface@1` parts say what they send or show:** optional `command` and `reads`, in the manifest's terms, so
++ OpenVibe AI knows a part's ranges, lifetime, release and rate when it arranges a panel or writes a control. They
++ grant nothing: the product's gate still checks every command. A new example is LOOI's panel built from its manifest.
++- Fixtures: LOOI 1.0.0 through the P7 tray (drive 500 ms life, delivery 1–300, release stop; head 500 ms, hold;
++ headlights delivery 1–250, 50 ms left, 2 a second, latched; battery by poll with `at` in ms; who is driving), and
++ three refusals (motion without a release, an actuator without its name, motion that is never released).
++
## 0.417.0 — 2026-11-12
**The agent engine's next shapes:** who asked, what a run continues, how several agents share one ask, and where the
ddiff --git a/contracts/bot/robot-manifest.v1.json b/contracts/bot/robot-manifest.v1.json
nnew file mode 100644
iindex 00000000..866df295
---- /dev/null
++++ b/contracts/bot/robot-manifest.v1.json
@@@ -0,0 +1,109 @@
++{
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/bot/robot-manifest.v1.json",
++ "title": "BotRobotManifest",
++ "description": "bot.robot-manifest@1: what a robot's driver says the robot can do, written and versioned by the driver's maker (a Link plugin's author), so a new control is a version bump of the manifest instead of an OpenVibe release. Each command names its kind, its class (motion moves something and is held to a lifetime and a release; state sets something that stays, like a light; action happens once), its value's fields and ranges, how long it lives, the delivery window Bot gives it, the time it must still have left when the robot reads it, how often it may be sent, what the robot does when no fresh command comes (release), and which control draws it. Each telemetry entry names a reading the driver reports, its fields, its unit and range, where it comes from, and the control that shows it. Bot derives the panel and the ui.surface@1 parts from it, Link forwards only the kinds it declares, and OpenVibe AI reads the same facts when it suggests a layout or writes a control. The manifest is data: no code and no addresses.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": ["id", "name", "version", "commands"],
++ "properties": {
++ "id": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_-]{0,39}$",
++ "description": "The robot model this manifest describes, e.g. looi. The same id as its Bot profile."
++ },
++ "name": { "type": "string", "minLength": 1, "maxLength": 80, "description": "What people call the robot." },
++ "by": { "type": "string", "pattern": "^[A-Za-z0-9_.-]{1,40}$", "description": "The maker of the driver that publishes this manifest (an OpenVibe username)." },
++ "version": {
++ "type": "string",
++ "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$",
++ "description": "The manifest's own version (semver). A new or changed command is a new version; a frozen version is never edited."
++ },
++ "frozen": { "type": "boolean", "description": "True once the maker and OpenVibe have checked this version against the driver's real command list: it is the contract both sides hold to." },
++ "description": { "type": "string", "maxLength": 500 },
++ "commands": {
++ "type": "array",
++ "minItems": 1,
++ "maxItems": 32,
++ "items": { "$ref": "#/$defs/command" }
++ },
++ "telemetry": {
++ "type": "array",
++ "maxItems": 32,
++ "items": { "$ref": "#/$defs/reading" }
++ }
++ },
++ "$defs": {
++ "range": {
++ "type": "array",
++ "minItems": 2,
++ "maxItems": 2,
++ "items": { "type": "number" },
++ "description": "[least, most], inclusive."
++ },
++ "field": {
++ "description": "One field of a value or a reading: a numeric range, \"boolean\", \"string\", \"ms\" (a time in milliseconds since the epoch), or the list of the values it may take.",
++ "oneOf": [
++ { "$ref": "#/$defs/range" },
++ { "enum": ["boolean", "string", "ms", "integer", "number"] },
++ { "type": "array", "minItems": 1, "maxItems": 16, "uniqueItems": true, "items": { "type": "string", "pattern": "^[a-z][a-z0-9_-]{0,31}$" } }
++ ]
++ },
++ "fields": {
++ "type": "object",
++ "minProperties": 1,
++ "maxProperties": 12,
++ "propertyNames": { "pattern": "^[a-z][a-z0-9_]{0,31}$" },
++ "additionalProperties": { "$ref": "#/$defs/field" }
++ },
++ "window": {
++ "type": "object",
++ "additionalProperties": false,
++ "required": ["min", "max"],
++ "properties": {
++ "min": { "type": "integer", "minimum": 1, "maximum": 60000 },
++ "max": { "type": "integer", "minimum": 1, "maximum": 60000 }
++ },
++ "description": "A window in milliseconds, inclusive."
++ },
++ "command": {
++ "type": "object",
++ "additionalProperties": false,
++ "required": ["kind", "class", "value", "control"],
++ "properties": {
++ "kind": { "type": "string", "pattern": "^[a-z][a-z0-9_]{0,31}$", "description": "The command kind on the wire (drive, actuator, headlight, ...)." },
++ "name": { "type": "string", "pattern": "^[a-z][a-z0-9_]{0,31}$", "description": "For a kind that carries a name (actuator): which one, e.g. head." },
++ "class": { "enum": ["motion", "state", "action"], "description": "motion moves something and has a lifetime and a release; state sets something that stays (a light); action happens once." },
++ "label": { "type": "string", "minLength": 1, "maxLength": 40 },
++ "value": { "$ref": "#/$defs/fields", "description": "The value's fields: for drive { throttle: [-1, 1], steer: [-1, 1] }, for a light { on: \"boolean\" }." },
++ "lifetime_ms": { "type": "integer", "minimum": 1, "maximum": 60000, "description": "The longest one command may act for (a cap the robot enforces too)." },
++ "delivery_ms": { "$ref": "#/$defs/window", "description": "The deadline Bot gives the command after issuing it: the window the driver accepts it in." },
++ "min_left_ms": { "type": "integer", "minimum": 0, "maximum": 60000, "description": "The time a command must still have left of its life when the robot reads it, or the robot refuses it." },
++ "rate_per_s": { "type": "number", "exclusiveMinimum": 0, "maximum": 100, "description": "At most this many a second, shared by every source." },
++ "release": { "enum": ["stop", "hold", "none"], "description": "What the robot does when no fresh command comes in time: stop (to zero), hold (stays where it is), none (a state is not released)." },
++ "latched": { "type": "boolean", "description": "The robot keeps the last state until it is told otherwise (a light)." },
++ "confirm": { "type": "string", "pattern": "^[a-z][a-z0-9_]{0,39}$", "description": "The telemetry key that reports what the robot really did." },
++ "control": { "enum": ["stick", "slider", "toggle", "button", "pad"], "description": "The control the panel draws for it." }
++ },
++ "allOf": [
++ { "if": { "properties": { "class": { "const": "motion" } } }, "then": { "required": ["lifetime_ms", "release"], "properties": { "release": { "enum": ["stop", "hold"] } } } },
++ { "if": { "properties": { "kind": { "const": "actuator" } } }, "then": { "required": ["name"] } }
++ ]
++ },
++ "reading": {
++ "type": "object",
++ "additionalProperties": false,
++ "required": ["key", "control"],
++ "properties": {
++ "key": { "type": "string", "pattern": "^[a-z][a-z0-9_]{0,39}$", "description": "Where the reading arrives: a top-level telemetry key (battery) or a sensors key (p7_commander)." },
++ "label": { "type": "string", "minLength": 1, "maxLength": 40 },
++ "unit": { "type": "string", "maxLength": 12 },
++ "range": { "$ref": "#/$defs/range" },
++ "fields": { "$ref": "#/$defs/fields" },
++ "source": { "enum": ["poll", "push", "connect"], "description": "poll: read again on a timer (fresh); push: sent when it changes; connect: read once when the robot connects (provisional after)." },
++ "fresh_ms": { "type": "integer", "minimum": 1, "maximum": 3600000, "description": "A reading older than this is shown as stale." },
++ "control": { "enum": ["meter", "readout", "badge", "list"], "description": "The control that shows it." }
++ }
++ }
++ }
++}
ddiff --git a/contracts/catalog.json b/contracts/catalog.json
iindex ee550629..14fb3cda 100644
---- a/contracts/catalog.json
++++ b/contracts/catalog.json
@@@ -7247,6 +7247,16 @@
"status": "active",
"adr": "ADR-043"
},
++ {
++ "id": "bot.robot-manifest",
++ "version": "1.0.0",
++ "owner": "bot",
++ "schema": "bot/robot-manifest.v1.json",
++ "visibility": "public",
++ "compatibility": "backward",
++ "status": "active",
++ "adr": "ADR-043"
++ },
{
"id": "bot.device-message",
"version": "1.0.0",
ddiff --git a/contracts/ui/surface.v1.json b/contracts/ui/surface.v1.json
iindex 41302440..66c5e36f 100644
---- a/contracts/ui/surface.v1.json
++++ b/contracts/ui/surface.v1.json
@@@ -193,6 +193,14 @@
"uniqueItems": true,
"items": { "type": "string", "pattern": "^[a-z][a-z0-9_.-]{0,39}$" },
"description": "The parts this part must never cover, in addition to the surface-wide rule that nothing covers a required part."
++ },
++ "command": {
++ "$ref": "../bot/robot-manifest.v1.json#/$defs/command",
++ "description": "What pressing or moving this part sends, in the robot manifest's terms (bot.robot-manifest@1, 0.418.0): kind and class, the value's ranges, lifetime, delivery window, release and rate. OpenVibe AI reads it when it suggests a layout or writes a control; it grants nothing: the product's gate checks every command."
++ },
++ "reads": {
++ "$ref": "../bot/robot-manifest.v1.json#/$defs/reading",
++ "description": "What this part shows, in the robot manifest's terms: the telemetry key, its fields, unit, range and source."
}
}
}
ddiff --git a/fixtures/bot.robot-manifest/invalid/actuator-without-name.json b/fixtures/bot.robot-manifest/invalid/actuator-without-name.json
nnew file mode 100644
iindex 00000000..5c2d71fb
---- /dev/null
++++ b/fixtures/bot.robot-manifest/invalid/actuator-without-name.json
@@@ -0,0 +1,117 @@
++{
++ "id": "looi",
++ "name": "LOOI",
++ "by": "maticus",
++ "version": "1.0.0",
++ "frozen": true,
++ "description": "LOOI through the P7 tray (Maticus's driver), as checked against the tray's real command list on 2026-11-12.",
++ "commands": [
++ {
++ "kind": "drive",
++ "class": "motion",
++ "label": "Drive",
++ "value": {
++ "throttle": [
++ -1,
++ 1
++ ],
++ "steer": [
++ -1,
++ 1
++ ]
++ },
++ "lifetime_ms": 500,
++ "delivery_ms": {
++ "min": 1,
++ "max": 300
++ },
++ "release": "stop",
++ "control": "stick"
++ },
++ {
++ "kind": "actuator",
++ "class": "motion",
++ "label": "Head",
++ "value": {
++ "head": [
++ -1,
++ 1
++ ]
++ },
++ "lifetime_ms": 500,
++ "release": "hold",
++ "control": "slider"
++ },
++ {
++ "kind": "headlight",
++ "class": "state",
++ "label": "Headlights",
++ "value": {
++ "on": "boolean"
++ },
++ "delivery_ms": {
++ "min": 1,
++ "max": 250
++ },
++ "min_left_ms": 50,
++ "rate_per_s": 2,
++ "release": "none",
++ "latched": true,
++ "confirm": "p7_headlight",
++ "control": "toggle"
++ }
++ ],
++ "telemetry": [
++ {
++ "key": "p7_battery",
++ "label": "Battery",
++ "unit": "%",
++ "range": [
++ 0,
++ 100
++ ],
++ "fields": {
++ "pct": [
++ 0,
++ 100
++ ],
++ "usb": "boolean",
++ "raw": "integer",
++ "at": "ms"
++ },
++ "source": "poll",
++ "control": "meter"
++ },
++ {
++ "key": "p7_commander",
++ "label": "Who is driving",
++ "fields": {
++ "subject": "string",
++ "role": [
++ "owner",
++ "mod",
++ "operator"
++ ],
++ "channel": [
++ "drive",
++ "head",
++ "headlight"
++ ],
++ "at": "ms"
++ },
++ "source": "push",
++ "control": "badge"
++ },
++ {
++ "key": "p7_headlight",
++ "label": "Headlights",
++ "fields": {
++ "commanded": "boolean",
++ "pending": "boolean",
++ "physical_state_verified": "boolean"
++ },
++ "source": "push",
++ "control": "badge"
++ }
++ ]
++}
\\ No newline at end of file
ddiff --git a/fixtures/bot.robot-manifest/invalid/motion-released-never.json b/fixtures/bot.robot-manifest/invalid/motion-released-never.json
nnew file mode 100644
iindex 00000000..e150f5c7
---- /dev/null
++++ b/fixtures/bot.robot-manifest/invalid/motion-released-never.json
@@@ -0,0 +1,118 @@
++{
++ "id": "looi",
++ "name": "LOOI",
++ "by": "maticus",
++ "version": "1.0.0",
++ "frozen": true,
++ "description": "LOOI through the P7 tray (Maticus's driver), as checked against the tray's real command list on 2026-11-12.",
++ "commands": [
++ {
++ "kind": "drive",
++ "class": "motion",
++ "label": "Drive",
++ "value": {
++ "throttle": [
++ -1,
++ 1
++ ],
++ "steer": [
++ -1,
++ 1
++ ]
++ },
++ "lifetime_ms": 500,
++ "delivery_ms": {
++ "min": 1,
++ "max": 300
++ },
++ "release": "none",
++ "control": "stick"
++ },
++ {
++ "kind": "actuator",
++ "name": "head",
++ "class": "motion",
++ "label": "Head",
++ "value": {
++ "head": [
++ -1,
++ 1
++ ]
++ },
++ "lifetime_ms": 500,
++ "release": "hold",
++ "control": "slider"
++ },
++ {
++ "kind": "headlight",
++ "class": "state",
++ "label": "Headlights",
++ "value": {
++ "on": "boolean"
++ },
++ "delivery_ms": {
++ "min": 1,
++ "max": 250
++ },
++ "min_left_ms": 50,
++ "rate_per_s": 2,
++ "release": "none",
++ "latched": true,
++ "confirm": "p7_headlight",
++ "control": "toggle"
++ }
++ ],
++ "telemetry": [
++ {
++ "key": "p7_battery",
++ "label": "Battery",
++ "unit": "%",
++ "range": [
++ 0,
++ 100
++ ],
++ "fields": {
++ "pct": [
++ 0,
++ 100
++ ],
++ "usb": "boolean",
++ "raw": "integer",
++ "at": "ms"
++ },
++ "source": "poll",
++ "control": "meter"
++ },
++ {
++ "key": "p7_commander",
++ "label": "Who is driving",
++ "fields": {
++ "subject": "string",
++ "role": [
++ "owner",
++ "mod",
++ "operator"
++ ],
++ "channel": [
++ "drive",
++ "head",
++ "headlight"
++ ],
++ "at": "ms"
++ },
++ "source": "push",
++ "control": "badge"
++ },
++ {
++ "key": "p7_headlight",
++ "label": "Headlights",
++ "fields": {
++ "commanded": "boolean",
++ "pending": "boolean",
++ "physical_state_verified": "boolean"
++ },
++ "source": "push",
++ "control": "badge"
++ }
++ ]
++}
\\ No newline at end of file
ddiff --git a/fixtures/bot.robot-manifest/invalid/motion-without-release.json b/fixtures/bot.robot-manifest/invalid/motion-without-release.json
nnew file mode 100644
iindex 00000000..8e251af3
---- /dev/null
++++ b/fixtures/bot.robot-manifest/invalid/motion-without-release.json
@@@ -0,0 +1,117 @@
++{
++ "id": "looi",
++ "name": "LOOI",
++ "by": "maticus",
++ "version": "1.0.0",
++ "frozen": true,
++ "description": "LOOI through the P7 tray (Maticus's driver), as checked against the tray's real command list on 2026-11-12.",
++ "commands": [
++ {
++ "kind": "drive",
++ "class": "motion",
++ "label": "Drive",
++ "value": {
++ "throttle": [
++ -1,
++ 1
++ ],
++ "steer": [
++ -1,
++ 1
++ ]
++ },
++ "lifetime_ms": 500,
++ "delivery_ms": {
++ "min": 1,
++ "max": 300
++ },
++ "control": "stick"
++ },
++ {
++ "kind": "actuator",
++ "name": "head",
++ "class": "motion",
++ "label": "Head",
++ "value": {
++ "head": [
++ -1,
++ 1
++ ]
++ },
++ "lifetime_ms": 500,
++ "release": "hold",
++ "control": "slider"
++ },
++ {
++ "kind": "headlight",
++ "class": "state",
++ "label": "Headlights",
++ "value": {
++ "on": "boolean"
++ },
++ "delivery_ms": {
++ "min": 1,
++ "max": 250
++ },
++ "min_left_ms": 50,
++ "rate_per_s": 2,
++ "release": "none",
++ "latched": true,
++ "confirm": "p7_headlight",
++ "control": "toggle"
++ }
++ ],
++ "telemetry": [
++ {
++ "key": "p7_battery",
++ "label": "Battery",
++ "unit": "%",
++ "range": [
++ 0,
++ 100
++ ],
++ "fields": {
++ "pct": [
++ 0,
++ 100
++ ],
++ "usb": "boolean",
++ "raw": "integer",
++ "at": "ms"
++ },
++ "source": "poll",
++ "control": "meter"
++ },
++ {
++ "key": "p7_commander",
++ "label": "Who is driving",
++ "fields": {
++ "subject": "string",
++ "role": [
++ "owner",
++ "mod",
++ "operator"
++ ],
++ "channel": [
++ "drive",
++ "head",
++ "headlight"
++ ],
++ "at": "ms"
++ },
++ "source": "push",
++ "control": "badge"
++ },
++ {
++ "key": "p7_headlight",
++ "label": "Headlights",
++ "fields": {
++ "commanded": "boolean",
++ "pending": "boolean",
++ "physical_state_verified": "boolean"
++ },
++ "source": "push",
++ "control": "badge"
++ }
++ ]
++}
\\ No newline at end of file
ddiff --git a/fixtures/bot.robot-manifest/valid/looi.json b/fixtures/bot.robot-manifest/valid/looi.json
nnew file mode 100644
iindex 00000000..3719263e
---- /dev/null
++++ b/fixtures/bot.robot-manifest/valid/looi.json
@@@ -0,0 +1,118 @@
++{
++ "id": "looi",
++ "name": "LOOI",
++ "by": "maticus",
++ "version": "1.0.0",
++ "frozen": true,
++ "description": "LOOI through the P7 tray (Maticus's driver), as checked against the tray's real command list on 2026-11-12.",
++ "commands": [
++ {
++ "kind": "drive",
++ "class": "motion",
++ "label": "Drive",
++ "value": {
++ "throttle": [
++ -1,
++ 1
++ ],
++ "steer": [
++ -1,
++ 1
++ ]
++ },
++ "lifetime_ms": 500,
++ "delivery_ms": {
++ "min": 1,
++ "max": 300
++ },
++ "release": "stop",
++ "control": "stick"
++ },
++ {
++ "kind": "actuator",
++ "name": "head",
++ "class": "motion",
++ "label": "Head",
++ "value": {
++ "head": [
++ -1,
++ 1
++ ]
++ },
++ "lifetime_ms": 500,
++ "release": "hold",
++ "control": "slider"
++ },
++ {
++ "kind": "headlight",
++ "class": "state",
++ "label": "Headlights",
++ "value": {
++ "on": "boolean"
++ },
++ "delivery_ms": {
++ "min": 1,
++ "max": 250
++ },
++ "min_left_ms": 50,
++ "rate_per_s": 2,
++ "release": "none",
++ "latched": true,
++ "confirm": "p7_headlight",
++ "control": "toggle"
++ }
++ ],
++ "telemetry": [
++ {
++ "key": "p7_battery",
++ "label": "Battery",
++ "unit": "%",
++ "range": [
++ 0,
++ 100
++ ],
++ "fields": {
++ "pct": [
++ 0,
++ 100
++ ],
++ "usb": "boolean",
++ "raw": "integer",
++ "at": "ms"
++ },
++ "source": "poll",
++ "control": "meter"
++ },
++ {
++ "key": "p7_commander",
++ "label": "Who is driving",
++ "fields": {
++ "subject": "string",
++ "role": [
++ "owner",
++ "mod",
++ "operator"
++ ],
++ "channel": [
++ "drive",
++ "head",
++ "headlight"
++ ],
++ "at": "ms"
++ },
++ "source": "push",
++ "control": "badge"
++ },
++ {
++ "key": "p7_headlight",
++ "label": "Headlights",
++ "fields": {
++ "commanded": "boolean",
++ "pending": "boolean",
++ "physical_state_verified": "boolean"
++ },
++ "source": "push",
++ "control": "badge"
++ }
++ ]
++}
ddiff --git a/fixtures/ui.surface/invalid/command-motion-without-release.json b/fixtures/ui.surface/invalid/command-motion-without-release.json
nnew file mode 100644
iindex 00000000..ca75637c
---- /dev/null
++++ b/fixtures/ui.surface/invalid/command-motion-without-release.json
@@@ -0,0 +1,339 @@
++{
++ "id": "bot.controls",
++ "version": 1,
++ "name": "Robot controls",
++ "description": "LOOI's panel from its manifest (LOOI 1.0.0): each part says what it sends or shows, for the AI that arranges it.",
++ "devices": [
++ "phone",
++ "tablet",
++ "computer"
++ ],
++ "grid": {
++ "columns": {
++ "phone": 4,
++ "tablet": 8,
++ "computer": 12
++ },
++ "cell_px": {
++ "phone": 44,
++ "tablet": 44,
++ "computer": 44
++ }
++ },
++ "theme_tokens": [
++ "accent",
++ "surface",
++ "surface-raised",
++ "text",
++ "muted",
++ "danger",
++ "warning",
++ "success"
++ ],
++ "parts": [
++ {
++ "id": "stick",
++ "name": "Drive stick",
++ "kind": "stick",
++ "required": false,
++ "pressed": true,
++ "min": {
++ "w": 2,
++ "h": 2
++ },
++ "styles": {
++ "tints": [
++ "surface",
++ "accent"
++ ],
++ "shapes": [
++ "round",
++ "pill",
++ "square"
++ ],
++ "opacity": {
++ "min": 0.4,
++ "max": 1
++ },
++ "label": true
++ },
++ "bindings": {
++ "keys": [
++ "ArrowUp",
++ "ArrowDown",
++ "ArrowLeft",
++ "ArrowRight"
++ ],
++ "gamepad": [
++ "left-stick"
++ ]
++ },
++ "never_covers": [
++ "stop"
++ ],
++ "command": {
++ "kind": "drive",
++ "class": "motion",
++ "label": "Drive",
++ "value": {
++ "throttle": [
++ -1,
++ 1
++ ],
++ "steer": [
++ -1,
++ 1
++ ]
++ },
++ "lifetime_ms": 500,
++ "delivery_ms": {
++ "min": 1,
++ "max": 300
++ },
++ "control": "stick"
++ }
++ },
++ {
++ "id": "head",
++ "name": "Head",
++ "kind": "slider",
++ "required": false,
++ "pressed": true,
++ "min": {
++ "w": 2,
++ "h": 1
++ },
++ "styles": {
++ "tints": [
++ "accent",
++ "surface"
++ ],
++ "shapes": [
++ "round",
++ "pill",
++ "square"
++ ],
++ "opacity": {
++ "min": 0.4,
++ "max": 1
++ },
++ "label": true
++ },
++ "bindings": {
++ "keys": [
++ "q",
++ "e"
++ ],
++ "gamepad": []
++ },
++ "never_covers": [
++ "stop"
++ ],
++ "command": {
++ "kind": "actuator",
++ "name": "head",
++ "class": "motion",
++ "label": "Head",
++ "value": {
++ "head": [
++ -1,
++ 1
++ ]
++ },
++ "lifetime_ms": 500,
++ "release": "hold",
++ "control": "slider"
++ }
++ },
++ {
++ "id": "headlight",
++ "name": "Headlights",
++ "kind": "button",
++ "required": false,
++ "pressed": true,
++ "min": {
++ "w": 2,
++ "h": 1
++ },
++ "styles": {
++ "tints": [
++ "surface",
++ "accent"
++ ],
++ "shapes": [
++ "round",
++ "pill",
++ "square"
++ ],
++ "opacity": {
++ "min": 0.4,
++ "max": 1
++ },
++ "label": true
++ },
++ "bindings": {
++ "keys": [
++ "l"
++ ],
++ "gamepad": []
++ },
++ "never_covers": [
++ "stop"
++ ],
++ "command": {
++ "kind": "headlight",
++ "class": "state",
++ "label": "Headlights",
++ "value": {
++ "on": "boolean"
++ },
++ "delivery_ms": {
++ "min": 1,
++ "max": 250
++ },
++ "min_left_ms": 50,
++ "rate_per_s": 2,
++ "release": "none",
++ "latched": true,
++ "confirm": "p7_headlight",
++ "control": "toggle"
++ }
++ },
++ {
++ "id": "battery",
++ "name": "Battery",
++ "kind": "readout",
++ "required": false,
++ "pressed": false,
++ "min": {
++ "w": 1,
++ "h": 1
++ },
++ "styles": {
++ "tints": [
++ "text",
++ "surface"
++ ],
++ "shapes": [
++ "round",
++ "pill",
++ "square"
++ ],
++ "opacity": {
++ "min": 0.4,
++ "max": 1
++ },
++ "label": true
++ },
++ "bindings": {
++ "keys": [],
++ "gamepad": []
++ },
++ "reads": {
++ "key": "p7_battery",
++ "label": "Battery",
++ "unit": "%",
++ "range": [
++ 0,
++ 100
++ ],
++ "fields": {
++ "pct": [
++ 0,
++ 100
++ ],
++ "usb": "boolean",
++ "raw": "integer",
++ "at": "ms"
++ },
++ "source": "poll",
++ "control": "meter"
++ }
++ },
++ {
++ "id": "commander",
++ "name": "Who is driving",
++ "kind": "readout",
++ "required": false,
++ "pressed": false,
++ "min": {
++ "w": 2,
++ "h": 1
++ },
++ "styles": {
++ "tints": [
++ "text",
++ "surface"
++ ],
++ "shapes": [
++ "round",
++ "pill",
++ "square"
++ ],
++ "opacity": {
++ "min": 0.4,
++ "max": 1
++ },
++ "label": true
++ },
++ "bindings": {
++ "keys": [],
++ "gamepad": []
++ },
++ "reads": {
++ "key": "p7_commander",
++ "label": "Who is driving",
++ "fields": {
++ "subject": "string",
++ "role": [
++ "owner",
++ "mod",
++ "operator"
++ ],
++ "channel": [
++ "drive",
++ "head",
++ "headlight"
++ ],
++ "at": "ms"
++ },
++ "source": "push",
++ "control": "badge"
++ }
++ },
++ {
++ "id": "stop",
++ "name": "Stop",
++ "kind": "button",
++ "required": false,
++ "pressed": true,
++ "min": {
++ "w": 1,
++ "h": 1,
++ "px": 44
++ },
++ "styles": {
++ "tints": [
++ "surface"
++ ],
++ "shapes": [
++ "pill",
++ "square"
++ ],
++ "opacity": {
++ "min": 0.4,
++ "max": 1
++ },
++ "label": true
++ },
++ "bindings": {
++ "keys": [
++ "Space"
++ ],
++ "gamepad": [
++ "south"
++ ]
++ }
++ }
++ ]
++}
\\ No newline at end of file
ddiff --git a/fixtures/ui.surface/valid/looi-controls.json b/fixtures/ui.surface/valid/looi-controls.json
nnew file mode 100644
iindex 00000000..72c51216
---- /dev/null
++++ b/fixtures/ui.surface/valid/looi-controls.json
@@@ -0,0 +1,340 @@
++{
++ "id": "bot.controls",
++ "version": 1,
++ "name": "Robot controls",
++ "description": "LOOI's panel from its manifest (LOOI 1.0.0): each part says what it sends or shows, for the AI that arranges it.",
++ "devices": [
++ "phone",
++ "tablet",
++ "computer"
++ ],
++ "grid": {
++ "columns": {
++ "phone": 4,
++ "tablet": 8,
++ "computer": 12
++ },
++ "cell_px": {
++ "phone": 44,
++ "tablet": 44,
++ "computer": 44
++ }
++ },
++ "theme_tokens": [
++ "accent",
++ "surface",
++ "surface-raised",
++ "text",
++ "muted",
++ "danger",
++ "warning",
++ "success"
++ ],
++ "parts": [
++ {
++ "id": "stick",
++ "name": "Drive stick",
++ "kind": "stick",
++ "required": false,
++ "pressed": true,
++ "min": {
++ "w": 2,
++ "h": 2
++ },
++ "styles": {
++ "tints": [
++ "surface",
++ "accent"
++ ],
++ "shapes": [
++ "round",
++ "pill",
++ "square"
++ ],
++ "opacity": {
++ "min": 0.4,
++ "max": 1
++ },
++ "label": true
++ },
++ "bindings": {
++ "keys": [
++ "ArrowUp",
++ "ArrowDown",
++ "ArrowLeft",
++ "ArrowRight"
++ ],
++ "gamepad": [
++ "left-stick"
++ ]
++ },
++ "never_covers": [
++ "stop"
++ ],
++ "command": {
++ "kind": "drive",
++ "class": "motion",
++ "label": "Drive",
++ "value": {
++ "throttle": [
++ -1,
++ 1
++ ],
++ "steer": [
++ -1,
++ 1
++ ]
++ },
++ "lifetime_ms": 500,
++ "delivery_ms": {
++ "min": 1,
++ "max": 300
++ },
++ "release": "stop",
++ "control": "stick"
++ }
++ },
++ {
++ "id": "head",
++ "name": "Head",
++ "kind": "slider",
++ "required": false,
++ "pressed": true,
++ "min": {
++ "w": 2,
++ "h": 1
++ },
++ "styles": {
++ "tints": [
++ "accent",
++ "surface"
++ ],
++ "shapes": [
++ "round",
++ "pill",
++ "square"
++ ],
++ "opacity": {
++ "min": 0.4,
++ "max": 1
++ },
++ "label": true
++ },
++ "bindings": {
++ "keys": [
++ "q",
++ "e"
++ ],
++ "gamepad": []
++ },
++ "never_covers": [
++ "stop"
++ ],
++ "command": {
++ "kind": "actuator",
++ "name": "head",
++ "class": "motion",
++ "label": "Head",
++ "value": {
++ "head": [
++ -1,
++ 1
++ ]
++ },
++ "lifetime_ms": 500,
++ "release": "hold",
++ "control": "slider"
++ }
++ },
++ {
++ "id": "headlight",
++ "name": "Headlights",
++ "kind": "button",
++ "required": false,
++ "pressed": true,
++ "min": {
++ "w": 2,
++ "h": 1
++ },
++ "styles": {
++ "tints": [
++ "surface",
++ "accent"
++ ],
++ "shapes": [
++ "round",
++ "pill",
++ "square"
++ ],
++ "opacity": {
++ "min": 0.4,
++ "max": 1
++ },
++ "label": true
++ },
++ "bindings": {
++ "keys": [
++ "l"
++ ],
++ "gamepad": []
++ },
++ "never_covers": [
++ "stop"
++ ],
++ "command": {
++ "kind": "headlight",
++ "class": "state",
++ "label": "Headlights",
++ "value": {
++ "on": "boolean"
++ },
++ "delivery_ms": {
++ "min": 1,
++ "max": 250
++ },
++ "min_left_ms": 50,
++ "rate_per_s": 2,
++ "release": "none",
++ "latched": true,
++ "confirm": "p7_headlight",
++ "control": "toggle"
++ }
++ },
++ {
++ "id": "battery",
++ "name": "Battery",
++ "kind": "readout",
++ "required": false,
++ "pressed": false,
++ "min": {
++ "w": 1,
++ "h": 1
++ },
++ "styles": {
++ "tints": [
++ "text",
++ "surface"
++ ],
++ "shapes": [
++ "round",
++ "pill",
++ "square"
++ ],
++ "opacity": {
++ "min": 0.4,
++ "max": 1
++ },
++ "label": true
++ },
++ "bindings": {
++ "keys": [],
++ "gamepad": []
++ },
++ "reads": {
++ "key": "p7_battery",
++ "label": "Battery",
++ "unit": "%",
++ "range": [
++ 0,
++ 100
++ ],
++ "fields": {
++ "pct": [
++ 0,
++ 100
++ ],
++ "usb": "boolean",
++ "raw": "integer",
++ "at": "ms"
++ },
++ "source": "poll",
++ "control": "meter"
++ }
++ },
++ {
++ "id": "commander",
++ "name": "Who is driving",
++ "kind": "readout",
++ "required": false,
++ "pressed": false,
++ "min": {
++ "w": 2,
++ "h": 1
++ },
++ "styles": {
++ "tints": [
++ "text",
++ "surface"
++ ],
++ "shapes": [
++ "round",
++ "pill",
++ "square"
++ ],
++ "opacity": {
++ "min": 0.4,
++ "max": 1
++ },
++ "label": true
++ },
++ "bindings": {
++ "keys": [],
++ "gamepad": []
++ },
++ "reads": {
++ "key": "p7_commander",
++ "label": "Who is driving",
++ "fields": {
++ "subject": "string",
++ "role": [
++ "owner",
++ "mod",
++ "operator"
++ ],
++ "channel": [
++ "drive",
++ "head",
++ "headlight"
++ ],
++ "at": "ms"
++ },
++ "source": "push",
++ "control": "badge"
++ }
++ },
++ {
++ "id": "stop",
++ "name": "Stop",
++ "kind": "button",
++ "required": false,
++ "pressed": true,
++ "min": {
++ "w": 1,
++ "h": 1,
++ "px": 44
++ },
++ "styles": {
++ "tints": [
++ "surface"
++ ],
++ "shapes": [
++ "pill",
++ "square"
++ ],
++ "opacity": {
++ "min": 0.4,
++ "max": 1
++ },
++ "label": true
++ },
++ "bindings": {
++ "keys": [
++ "Space"
++ ],
++ "gamepad": [
++ "south"
++ ]
++ }
++ }
++ ]
++}
ddiff --git a/generated/json-schema/bundle.json b/generated/json-schema/bundle.json
iindex a7553128..07a35ef7 100644
---- a/generated/json-schema/bundle.json
++++ b/generated/json-schema/bundle.json
@@@ -82435,6 +82435,321 @@
}
}
},
++ "bot.robot-manifest": {
++ "version": "1.0.0",
++ "owner": "bot",
++ "status": "active",
++ "schema": {
++ "$schema": "https://json-schema.org/draft/2020-12/schema",
++ "$id": "https://openvibe.network/contracts/bot/robot-manifest.v1.json",
++ "title": "BotRobotManifest",
++ "description": "bot.robot-manifest@1: what a robot's driver says the robot can do, written and versioned by the driver's maker (a Link plugin's author), so a new control is a version bump of the manifest instead of an OpenVibe release. Each command names its kind, its class (motion moves something and is held to a lifetime and a release; state sets something that stays, like a light; action happens once), its value's fields and ranges, how long it lives, the delivery window Bot gives it, the time it must still have left when the robot reads it, how often it may be sent, what the robot does when no fresh command comes (release), and which control draws it. Each telemetry entry names a reading the driver reports, its fields, its unit and range, where it comes from, and the control that shows it. Bot derives the panel and the ui.surface@1 parts from it, Link forwards only the kinds it declares, and OpenVibe AI reads the same facts when it suggests a layout or writes a control. The manifest is data: no code and no addresses.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "id",
++ "name",
++ "version",
++ "commands"
++ ],
++ "properties": {
++ "id": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_-]{0,39}$",
++ "description": "The robot model this manifest describes, e.g. looi. The same id as its Bot profile."
++ },
++ "name": {
++ "type": "string",
++ "minLength": 1,
++ "maxLength": 80,
++ "description": "What people call the robot."
++ },
++ "by": {
++ "type": "string",
++ "pattern": "^[A-Za-z0-9_.-]{1,40}$",
++ "description": "The maker of the driver that publishes this manifest (an OpenVibe username)."
++ },
++ "version": {
++ "type": "string",
++ "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$",
++ "description": "The manifest's own version (semver). A new or changed command is a new version; a frozen version is never edited."
++ },
++ "frozen": {
++ "type": "boolean",
++ "description": "True once the maker and OpenVibe have checked this version against the driver's real command list: it is the contract both sides hold to."
++ },
++ "description": {
++ "type": "string",
++ "maxLength": 500
++ },
++ "commands": {
++ "type": "array",
++ "minItems": 1,
++ "maxItems": 32,
++ "items": {
++ "$ref": "#/$defs/command"
++ }
++ },
++ "telemetry": {
++ "type": "array",
++ "maxItems": 32,
++ "items": {
++ "$ref": "#/$defs/reading"
++ }
++ }
++ },
++ "$defs": {
++ "range": {
++ "type": "array",
++ "minItems": 2,
++ "maxItems": 2,
++ "items": {
++ "type": "number"
++ },
++ "description": "[least, most], inclusive."
++ },
++ "field": {
++ "description": "One field of a value or a reading: a numeric range, \"boolean\", \"string\", \"ms\" (a time in milliseconds since the epoch), or the list of the values it may take.",
++ "oneOf": [
++ {
++ "$ref": "#/$defs/range"
++ },
++ {
++ "enum": [
++ "boolean",
++ "string",
++ "ms",
++ "integer",
++ "number"
++ ]
++ },
++ {
++ "type": "array",
++ "minItems": 1,
++ "maxItems": 16,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_-]{0,31}$"
++ }
++ }
++ ]
++ },
++ "fields": {
++ "type": "object",
++ "minProperties": 1,
++ "maxProperties": 12,
++ "propertyNames": {
++ "pattern": "^[a-z][a-z0-9_]{0,31}$"
++ },
++ "additionalProperties": {
++ "$ref": "#/$defs/field"
++ }
++ },
++ "window": {
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "min",
++ "max"
++ ],
++ "properties": {
++ "min": {
++ "type": "integer",
++ "minimum": 1,
++ "maximum": 60000
++ },
++ "max": {
++ "type": "integer",
++ "minimum": 1,
++ "maximum": 60000
++ }
++ },
++ "description": "A window in milliseconds, inclusive."
++ },
++ "command": {
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "kind",
++ "class",
++ "value",
++ "control"
++ ],
++ "properties": {
++ "kind": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]{0,31}$",
++ "description": "The command kind on the wire (drive, actuator, headlight, ...)."
++ },
++ "name": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]{0,31}$",
++ "description": "For a kind that carries a name (actuator): which one, e.g. head."
++ },
++ "class": {
++ "enum": [
++ "motion",
++ "state",
++ "action"
++ ],
++ "description": "motion moves something and has a lifetime and a release; state sets something that stays (a light); action happens once."
++ },
++ "label": {
++ "type": "string",
++ "minLength": 1,
++ "maxLength": 40
++ },
++ "value": {
++ "$ref": "#/$defs/fields",
++ "description": "The value's fields: for drive { throttle: [-1, 1], steer: [-1, 1] }, for a light { on: \"boolean\" }."
++ },
++ "lifetime_ms": {
++ "type": "integer",
++ "minimum": 1,
++ "maximum": 60000,
++ "description": "The longest one command may act for (a cap the robot enforces too)."
++ },
++ "delivery_ms": {
++ "$ref": "#/$defs/window",
++ "description": "The deadline Bot gives the command after issuing it: the window the driver accepts it in."
++ },
++ "min_left_ms": {
++ "type": "integer",
++ "minimum": 0,
++ "maximum": 60000,
++ "description": "The time a command must still have left of its life when the robot reads it, or the robot refuses it."
++ },
++ "rate_per_s": {
++ "type": "number",
++ "exclusiveMinimum": 0,
++ "maximum": 100,
++ "description": "At most this many a second, shared by every source."
++ },
++ "release": {
++ "enum": [
++ "stop",
++ "hold",
++ "none"
++ ],
++ "description": "What the robot does when no fresh command comes in time: stop (to zero), hold (stays where it is), none (a state is not released)."
++ },
++ "latched": {
++ "type": "boolean",
++ "description": "The robot keeps the last state until it is told otherwise (a light)."
++ },
++ "confirm": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]{0,39}$",
++ "description": "The telemetry key that reports what the robot really did."
++ },
++ "control": {
++ "enum": [
++ "stick",
++ "slider",
++ "toggle",
++ "button",
++ "pad"
++ ],
++ "description": "The control the panel draws for it."
++ }
++ },
++ "allOf": [
++ {
++ "if": {
++ "properties": {
++ "class": {
++ "const": "motion"
++ }
++ }
++ },
++ "then": {
++ "required": [
++ "lifetime_ms",
++ "release"
++ ],
++ "properties": {
++ "release": {
++ "enum": [
++ "stop",
++ "hold"
++ ]
++ }
++ }
++ }
++ },
++ {
++ "if": {
++ "properties": {
++ "kind": {
++ "const": "actuator"
++ }
++ }
++ },
++ "then": {
++ "required": [
++ "name"
++ ]
++ }
++ }
++ ]
++ },
++ "reading": {
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "key",
++ "control"
++ ],
++ "properties": {
++ "key": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]{0,39}$",
++ "description": "Where the reading arrives: a top-level telemetry key (battery) or a sensors key (p7_commander)."
++ },
++ "label": {
++ "type": "string",
++ "minLength": 1,
++ "maxLength": 40
++ },
++ "unit": {
++ "type": "string",
++ "maxLength": 12
++ },
++ "range": {
++ "$ref": "#/$defs/range"
++ },
++ "fields": {
++ "$ref": "#/$defs/fields"
++ },
++ "source": {
++ "enum": [
++ "poll",
++ "push",
++ "connect"
++ ],
++ "description": "poll: read again on a timer (fresh); push: sent when it changes; connect: read once when the robot connects (provisional after)."
++ },
++ "fresh_ms": {
++ "type": "integer",
++ "minimum": 1,
++ "maximum": 3600000,
++ "description": "A reading older than this is shown as stale."
++ },
++ "control": {
++ "enum": [
++ "meter",
++ "readout",
++ "badge",
++ "list"
++ ],
++ "description": "The control that shows it."
++ }
++ }
++ }
++ }
++ }
++ },
"bot.device-message": {
"version": "1.0.0",
"owner": "bot",
@@@ -131433,6 +131748,14 @@
"pattern": "^[a-z][a-z0-9_.-]{0,39}$"
},
"description": "The parts this part must never cover, in addition to the surface-wide rule that nothing covers a required part."
++ },
++ "command": {
++ "$ref": "../bot/robot-manifest.v1.json#/$defs/command",
++ "description": "What pressing or moving this part sends, in the robot manifest's terms (bot.robot-manifest@1, 0.418.0): kind and class, the value's ranges, lifetime, delivery window, release and rate. OpenVibe AI reads it when it suggests a layout or writes a control; it grants nothing: the product's gate checks every command."
++ },
++ "reads": {
++ "$ref": "../bot/robot-manifest.v1.json#/$defs/reading",
++ "description": "What this part shows, in the robot manifest's terms: the telemetry key, its fields, unit, range and source."
}
}
}
ddiff --git a/generated/openapi/actor.json b/generated/openapi/actor.json
iindex ad66dc80..25b1d440 100644
---- a/generated/openapi/actor.json
++++ b/generated/openapi/actor.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Actor API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Actor as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/ai.json b/generated/openapi/ai.json
iindex 9941f4e8..b200a918 100644
---- a/generated/openapi/ai.json
++++ b/generated/openapi/ai.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.AI API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.AI as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
@@@ -9107,6 +9107,314 @@
}
]
},
++ "bot.robot-manifest.v1": {
++ "title": "BotRobotManifest",
++ "description": "bot.robot-manifest@1: what a robot's driver says the robot can do, written and versioned by the driver's maker (a Link plugin's author), so a new control is a version bump of the manifest instead of an OpenVibe release. Each command names its kind, its class (motion moves something and is held to a lifetime and a release; state sets something that stays, like a light; action happens once), its value's fields and ranges, how long it lives, the delivery window Bot gives it, the time it must still have left when the robot reads it, how often it may be sent, what the robot does when no fresh command comes (release), and which control draws it. Each telemetry entry names a reading the driver reports, its fields, its unit and range, where it comes from, and the control that shows it. Bot derives the panel and the ui.surface@1 parts from it, Link forwards only the kinds it declares, and OpenVibe AI reads the same facts when it suggests a layout or writes a control. The manifest is data: no code and no addresses.",
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "id",
++ "name",
++ "version",
++ "commands"
++ ],
++ "properties": {
++ "id": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_-]{0,39}$",
++ "description": "The robot model this manifest describes, e.g. looi. The same id as its Bot profile."
++ },
++ "name": {
++ "type": "string",
++ "minLength": 1,
++ "maxLength": 80,
++ "description": "What people call the robot."
++ },
++ "by": {
++ "type": "string",
++ "pattern": "^[A-Za-z0-9_.-]{1,40}$",
++ "description": "The maker of the driver that publishes this manifest (an OpenVibe username)."
++ },
++ "version": {
++ "type": "string",
++ "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)$",
++ "description": "The manifest's own version (semver). A new or changed command is a new version; a frozen version is never edited."
++ },
++ "frozen": {
++ "type": "boolean",
++ "description": "True once the maker and OpenVibe have checked this version against the driver's real command list: it is the contract both sides hold to."
++ },
++ "description": {
++ "type": "string",
++ "maxLength": 500
++ },
++ "commands": {
++ "type": "array",
++ "minItems": 1,
++ "maxItems": 32,
++ "items": {
++ "$ref": "#/components/schemas/bot.robot-manifest.v1/$defs/command"
++ }
++ },
++ "telemetry": {
++ "type": "array",
++ "maxItems": 32,
++ "items": {
++ "$ref": "#/components/schemas/bot.robot-manifest.v1/$defs/reading"
++ }
++ }
++ },
++ "$defs": {
++ "range": {
++ "type": "array",
++ "minItems": 2,
++ "maxItems": 2,
++ "items": {
++ "type": "number"
++ },
++ "description": "[least, most], inclusive."
++ },
++ "field": {
++ "description": "One field of a value or a reading: a numeric range, \"boolean\", \"string\", \"ms\" (a time in milliseconds since the epoch), or the list of the values it may take.",
++ "oneOf": [
++ {
++ "$ref": "#/components/schemas/bot.robot-manifest.v1/$defs/range"
++ },
++ {
++ "enum": [
++ "boolean",
++ "string",
++ "ms",
++ "integer",
++ "number"
++ ]
++ },
++ {
++ "type": "array",
++ "minItems": 1,
++ "maxItems": 16,
++ "uniqueItems": true,
++ "items": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_-]{0,31}$"
++ }
++ }
++ ]
++ },
++ "fields": {
++ "type": "object",
++ "minProperties": 1,
++ "maxProperties": 12,
++ "propertyNames": {
++ "pattern": "^[a-z][a-z0-9_]{0,31}$"
++ },
++ "additionalProperties": {
++ "$ref": "#/components/schemas/bot.robot-manifest.v1/$defs/field"
++ }
++ },
++ "window": {
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "min",
++ "max"
++ ],
++ "properties": {
++ "min": {
++ "type": "integer",
++ "minimum": 1,
++ "maximum": 60000
++ },
++ "max": {
++ "type": "integer",
++ "minimum": 1,
++ "maximum": 60000
++ }
++ },
++ "description": "A window in milliseconds, inclusive."
++ },
++ "command": {
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "kind",
++ "class",
++ "value",
++ "control"
++ ],
++ "properties": {
++ "kind": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]{0,31}$",
++ "description": "The command kind on the wire (drive, actuator, headlight, ...)."
++ },
++ "name": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]{0,31}$",
++ "description": "For a kind that carries a name (actuator): which one, e.g. head."
++ },
++ "class": {
++ "enum": [
++ "motion",
++ "state",
++ "action"
++ ],
++ "description": "motion moves something and has a lifetime and a release; state sets something that stays (a light); action happens once."
++ },
++ "label": {
++ "type": "string",
++ "minLength": 1,
++ "maxLength": 40
++ },
++ "value": {
++ "$ref": "#/components/schemas/bot.robot-manifest.v1/$defs/fields",
++ "description": "The value's fields: for drive { throttle: [-1, 1], steer: [-1, 1] }, for a light { on: \"boolean\" }."
++ },
++ "lifetime_ms": {
++ "type": "integer",
++ "minimum": 1,
++ "maximum": 60000,
++ "description": "The longest one command may act for (a cap the robot enforces too)."
++ },
++ "delivery_ms": {
++ "$ref": "#/components/schemas/bot.robot-manifest.v1/$defs/window",
++ "description": "The deadline Bot gives the command after issuing it: the window the driver accepts it in."
++ },
++ "min_left_ms": {
++ "type": "integer",
++ "minimum": 0,
++ "maximum": 60000,
++ "description": "The time a command must still have left of its life when the robot reads it, or the robot refuses it."
++ },
++ "rate_per_s": {
++ "type": "number",
++ "exclusiveMinimum": 0,
++ "maximum": 100,
++ "description": "At most this many a second, shared by every source."
++ },
++ "release": {
++ "enum": [
++ "stop",
++ "hold",
++ "none"
++ ],
++ "description": "What the robot does when no fresh command comes in time: stop (to zero), hold (stays where it is), none (a state is not released)."
++ },
++ "latched": {
++ "type": "boolean",
++ "description": "The robot keeps the last state until it is told otherwise (a light)."
++ },
++ "confirm": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]{0,39}$",
++ "description": "The telemetry key that reports what the robot really did."
++ },
++ "control": {
++ "enum": [
++ "stick",
++ "slider",
++ "toggle",
++ "button",
++ "pad"
++ ],
++ "description": "The control the panel draws for it."
++ }
++ },
++ "allOf": [
++ {
++ "if": {
++ "properties": {
++ "class": {
++ "const": "motion"
++ }
++ }
++ },
++ "then": {
++ "required": [
++ "lifetime_ms",
++ "release"
++ ],
++ "properties": {
++ "release": {
++ "enum": [
++ "stop",
++ "hold"
++ ]
++ }
++ }
++ }
++ },
++ {
++ "if": {
++ "properties": {
++ "kind": {
++ "const": "actuator"
++ }
++ }
++ },
++ "then": {
++ "required": [
++ "name"
++ ]
++ }
++ }
++ ]
++ },
++ "reading": {
++ "type": "object",
++ "additionalProperties": false,
++ "required": [
++ "key",
++ "control"
++ ],
++ "properties": {
++ "key": {
++ "type": "string",
++ "pattern": "^[a-z][a-z0-9_]{0,39}$",
++ "description": "Where the reading arrives: a top-level telemetry key (battery) or a sensors key (p7_commander)."
++ },
++ "label": {
++ "type": "string",
++ "minLength": 1,
++ "maxLength": 40
++ },
++ "unit": {
++ "type": "string",
++ "maxLength": 12
++ },
++ "range": {
++ "$ref": "#/components/schemas/bot.robot-manifest.v1/$defs/range"
++ },
++ "fields": {
++ "$ref": "#/components/schemas/bot.robot-manifest.v1/$defs/fields"
++ },
++ "source": {
++ "enum": [
++ "poll",
++ "push",
++ "connect"
++ ],
++ "description": "poll: read again on a timer (fresh); push: sent when it changes; connect: read once when the robot connects (provisional after)."
++ },
++ "fresh_ms": {
++ "type": "integer",
++ "minimum": 1,
++ "maximum": 3600000,
++ "description": "A reading older than this is shown as stale."
++ },
++ "control": {
++ "enum": [
++ "meter",
++ "readout",
++ "badge",
++ "list"
++ ],
++ "description": "The control that shows it."
++ }
++ }
++ }
++ }
++ },
"common.action-item.v1": {
"title": "ActionItem",
"description": "One piece of a person's agent work in the Action Center (plan 2026-10-28 §3.10): an agent task, a coding task, an AI run, or an approval waiting on them. Each authority answers its own items in this shape (common.action-list-result@1); OpenVibe.Network merges them into buckets (network.me-actions-result@1). Text is plain (no markup); a cost is what the person was charged in USD, null when unknown or free; href is a page on the authority's own public site.",
@@@ -10906,6 +11214,14 @@
"pattern": "^[a-z][a-z0-9_.-]{0,39}$"
},
"description": "The parts this part must never cover, in addition to the surface-wide rule that nothing covers a required part."
++ },
++ "command": {
++ "$ref": "#/components/schemas/bot.robot-manifest.v1/$defs/command",
++ "description": "What pressing or moving this part sends, in the robot manifest's terms (bot.robot-manifest@1, 0.418.0): kind and class, the value's ranges, lifetime, delivery window, release and rate. OpenVibe AI reads it when it suggests a layout or writes a control; it grants nothing: the product's gate checks every command."
++ },
++ "reads": {
++ "$ref": "#/components/schemas/bot.robot-manifest.v1/$defs/reading",
++ "description": "What this part shows, in the robot manifest's terms: the telemetry key, its fields, unit, range and source."
}
}
}
ddiff --git a/generated/openapi/bench.json b/generated/openapi/bench.json
iindex de65b6c7..440c5feb 100644
---- a/generated/openapi/bench.json
++++ b/generated/openapi/bench.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Bench API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Bench as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/billing.json b/generated/openapi/billing.json
iindex 4beea02a..067c0305 100644
---- a/generated/openapi/billing.json
++++ b/generated/openapi/billing.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Billing API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Billing as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/blog.json b/generated/openapi/blog.json
iindex ba8cf99c..07c198bc 100644
---- a/generated/openapi/blog.json
++++ b/generated/openapi/blog.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Blog API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Blog as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/bot.json b/generated/openapi/bot.json
iindex c7cdfc0e..1f6917bd 100644
---- a/generated/openapi/bot.json
++++ b/generated/openapi/bot.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Bot API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Bot as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/chat.json b/generated/openapi/chat.json
iindex 0e685129..aa0ea55d 100644
---- a/generated/openapi/chat.json
++++ b/generated/openapi/chat.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Chat API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Chat as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/codes.json b/generated/openapi/codes.json
iindex 46abb0d9..04101f63 100644
---- a/generated/openapi/codes.json
++++ b/generated/openapi/codes.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Codes API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Codes as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/community.json b/generated/openapi/community.json
iindex 7c0407e9..6e2cfcd8 100644
---- a/generated/openapi/community.json
++++ b/generated/openapi/community.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Community API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Community as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/connect.json b/generated/openapi/connect.json
iindex 83d39fa3..aac3b8d2 100644
---- a/generated/openapi/connect.json
++++ b/generated/openapi/connect.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe Connect API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe Connect as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe Connect as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/coupons.json b/generated/openapi/coupons.json
iindex 4bbb4c63..1281bd65 100644
---- a/generated/openapi/coupons.json
++++ b/generated/openapi/coupons.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Coupons API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Coupons as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/deals.json b/generated/openapi/deals.json
iindex 6614ceb7..d178b2f0 100644
---- a/generated/openapi/deals.json
++++ b/generated/openapi/deals.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Deals API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Deals as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/design.json b/generated/openapi/design.json
iindex 8af146f9..cf557613 100644
---- a/generated/openapi/design.json
++++ b/generated/openapi/design.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Design API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Design as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Design as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/domains.json b/generated/openapi/domains.json
iindex bf3dbfc6..fc32eada 100644
---- a/generated/openapi/domains.json
++++ b/generated/openapi/domains.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Domains API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Domains as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/events.json b/generated/openapi/events.json
iindex e5e893cd..94e75708 100644
---- a/generated/openapi/events.json
++++ b/generated/openapi/events.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Events API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Events as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/exchange.json b/generated/openapi/exchange.json
iindex afdce858..91051377 100644
---- a/generated/openapi/exchange.json
++++ b/generated/openapi/exchange.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Exchange API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Exchange as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Exchange as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/food.json b/generated/openapi/food.json
iindex 36168299..04179670 100644
---- a/generated/openapi/food.json
++++ b/generated/openapi/food.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Food API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Food as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/games.json b/generated/openapi/games.json
iindex 932f793d..37fcfe82 100644
---- a/generated/openapi/games.json
++++ b/generated/openapi/games.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Games API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Games as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/git.json b/generated/openapi/git.json
iindex 856c4b02..68cdecbf 100644
---- a/generated/openapi/git.json
++++ b/generated/openapi/git.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Git API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Git as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Git as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/host.json b/generated/openapi/host.json
iindex cf368c9b..7e88b338 100644
---- a/generated/openapi/host.json
++++ b/generated/openapi/host.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Host API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Host as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/inventory.json b/generated/openapi/inventory.json
iindex 7ffb70c9..f529834c 100644
---- a/generated/openapi/inventory.json
++++ b/generated/openapi/inventory.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Inventory API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Inventory as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/live.json b/generated/openapi/live.json
iindex 89c19c39..abd64fc6 100644
---- a/generated/openapi/live.json
++++ b/generated/openapi/live.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Live API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Live as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/mail.json b/generated/openapi/mail.json
iindex 64317775..f4e451fc 100644
---- a/generated/openapi/mail.json
++++ b/generated/openapi/mail.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Mail API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Mail as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Mail as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/media-hub.json b/generated/openapi/media-hub.json
iindex 949e70da..d684bef7 100644
---- a/generated/openapi/media-hub.json
++++ b/generated/openapi/media-hub.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.MediaHub API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.MediaHub as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/media.json b/generated/openapi/media.json
iindex a10f4138..2ffbf750 100644
---- a/generated/openapi/media.json
++++ b/generated/openapi/media.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Media API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Media as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/network.json b/generated/openapi/network.json
iindex 449ac1fc..5d42a98d 100644
---- a/generated/openapi/network.json
++++ b/generated/openapi/network.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Network API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Network as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/news.json b/generated/openapi/news.json
iindex aa9030f3..42a50131 100644
---- a/generated/openapi/news.json
++++ b/generated/openapi/news.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.News API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.News as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/openre.json b/generated/openapi/openre.json
iindex 55c5acfb..6c462b40 100644
---- a/generated/openapi/openre.json
++++ b/generated/openapi/openre.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenRestream API",
-- "version": "0.417.0",
-- "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenRestream as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/play.json b/generated/openapi/play.json
iindex c419a2f5..91f7321d 100644
---- a/generated/openapi/play.json
++++ b/generated/openapi/play.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Play API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Play as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/quest.json b/generated/openapi/quest.json
iindex 8a9a7a60..21a1bb83 100644
---- a/generated/openapi/quest.json
++++ b/generated/openapi/quest.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Quest API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Quest as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/report.json b/generated/openapi/report.json
iindex 205566a4..0d405fde 100644
---- a/generated/openapi/report.json
++++ b/generated/openapi/report.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Report API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Report as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/reviews.json b/generated/openapi/reviews.json
iindex 4f2da014..fa9f27da 100644
---- a/generated/openapi/reviews.json
++++ b/generated/openapi/reviews.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Reviews API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Reviews as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/run.json b/generated/openapi/run.json
iindex da796e40..bdabd187 100644
---- a/generated/openapi/run.json
++++ b/generated/openapi/run.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Run API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Run as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/search.json b/generated/openapi/search.json
iindex 20003847..60dee6cf 100644
---- a/generated/openapi/search.json
++++ b/generated/openapi/search.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Search API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Search as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/services.json b/generated/openapi/services.json
iindex 847615f6..95ddc940 100644
---- a/generated/openapi/services.json
++++ b/generated/openapi/services.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Services API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Services as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/sources.json b/generated/openapi/sources.json
iindex df87d34a..e920b772 100644
---- a/generated/openapi/sources.json
++++ b/generated/openapi/sources.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Sources API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Sources as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/space.json b/generated/openapi/space.json
iindex e6e146e6..8a14971c 100644
---- a/generated/openapi/space.json
++++ b/generated/openapi/space.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Space API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Space as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/tips.json b/generated/openapi/tips.json
iindex 8da7636d..8f984d17 100644
---- a/generated/openapi/tips.json
++++ b/generated/openapi/tips.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Tips API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Tips as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/today.json b/generated/openapi/today.json
iindex 6e9d0b23..190a45ca 100644
---- a/generated/openapi/today.json
++++ b/generated/openapi/today.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Today API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Today as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/tools.json b/generated/openapi/tools.json
iindex 81aec6ef..c61dab48 100644
---- a/generated/openapi/tools.json
++++ b/generated/openapi/tools.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Tools API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Tools as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/trade.json b/generated/openapi/trade.json
iindex 6c6c286b..763a5b4f 100644
---- a/generated/openapi/trade.json
++++ b/generated/openapi/trade.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Trade API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Trade as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/vip.json b/generated/openapi/vip.json
iindex 5df38992..7faee44c 100644
---- a/generated/openapi/vip.json
++++ b/generated/openapi/vip.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.VIP API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.VIP as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/vision.json b/generated/openapi/vision.json
iindex f3487b93..d002e3c0 100644
---- a/generated/openapi/vision.json
++++ b/generated/openapi/vision.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Vision API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Vision as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/watch.json b/generated/openapi/watch.json
iindex 16406465..ea0e821d 100644
---- a/generated/openapi/watch.json
++++ b/generated/openapi/watch.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Watch API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Watch as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/wiki.json b/generated/openapi/wiki.json
iindex d0a7debf..02933cc1 100644
---- a/generated/openapi/wiki.json
++++ b/generated/openapi/wiki.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Wiki API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Wiki as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/work.json b/generated/openapi/work.json
iindex 234b3efe..ea5dd7c1 100644
---- a/generated/openapi/work.json
++++ b/generated/openapi/work.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Work API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Work as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/openapi/zone.json b/generated/openapi/zone.json
iindex 2b5fdbae..3188c11a 100644
---- a/generated/openapi/zone.json
++++ b/generated/openapi/zone.json
@@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"title": "OpenVibe.Zone API",
-- "version": "0.417.0",
-- "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.417.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
++ "version": "0.418.0",
++ "description": "Routes of OpenVibe.Zone as the OpenVibe contracts describe them (openvibe-contracts 0.418.0): each operation lists the capabilities it performs; a token for the service's audience must carry one of them unless the route is open. Generated by openvibe-contracts lib/openapi.js; do not edit.",
"license": {
"name": "MIT",
"identifier": "MIT"
ddiff --git a/generated/typescript/index.d.ts b/generated/typescript/index.d.ts
iindex 1aea96a0..20161508 100644
---- a/generated/typescript/index.d.ts
++++ b/generated/typescript/index.d.ts
@@@ -219410,6 +219410,155 @@ export interface BotRobotProfile {
};
}
++/** [email protected] (owner: bot) */
++/**
++ * bot.robot-manifest@1: what a robot's driver says the robot can do, written and versioned by the driver's maker (a Link plugin's author), so a new control is a version bump of the manifest instead of an OpenVibe release. Each command names its kind, its class (motion moves something and is held to a lifetime and a release; state sets something that stays, like a light; action happens once), its value's fields and ranges, how long it lives, the delivery window Bot gives it, the time it must still have left when the robot reads it, how often it may be sent, what the robot does when no fresh command comes (release), and which control draws it. Each telemetry entry names a reading the driver reports, its fields, its unit and range, where it comes from, and the control that shows it. Bot derives the panel and the ui.surface@1 parts from it, Link forwards only the kinds it declares, and OpenVibe AI reads the same facts when it suggests a layout or writes a control. The manifest is data: no code and no addresses.
++ */
++export interface BotRobotManifest {
++ /**
++ * The robot model this manifest describes, e.g. looi. The same id as its Bot profile.
++ */
++ id: string;
++ /**
++ * What people call the robot.
++ */
++ name: string;
++ /**
++ * The maker of the driver that publishes this manifest (an OpenVibe username).
++ */
++ by?: string;
++ /**
++ * The manifest's own version (semver). A new or changed command is a new version; a frozen version is never edited.
++ */
++ version: string;
++ /**
++ * True once the maker and OpenVibe have checked this version against the driver's real command list: it is the contract both sides hold to.
++ */
++ frozen?: boolean;
++ description?: string;
++ /**
++ * @minItems 1
++ * @maxItems 32
++ */
++ commands: [
++ {
++ [k: string]: unknown | undefined;
++ } & {
++ [k: string]: unknown | undefined;
++ },
++ ...({
++ [k: string]: unknown | undefined;
++ } & {
++ [k: string]: unknown | undefined;
++ })[]
++ ];
++ /**
++ * @maxItems 32
++ */
++ telemetry?: {
++ /**
++ * Where the reading arrives: a top-level telemetry key (battery) or a sensors key (p7_commander).
++ */
++ key: string;
++ label?: string;
++ unit?: string;
++ /**
++ * [least, most], inclusive.
++ *
++ * @minItems 2
++ * @maxItems 2
++ */
++ range?: [number, number];
++ fields?: {
++ /**
++ * One field of a value or a reading: a numeric range, "boolean", "string", "ms" (a time in milliseconds since the epoch), or the list of the values it may take.
++ */
++ [k: string]:
++ | (
++ | [number, number]
++ | ("boolean" | "string" | "ms" | "integer" | "number")
++ | [string]
++ | [string, string]
++ | [string, string, string]
++ | [string, string, string, string]
++ | [string, string, string, string, string]
++ | [string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string, string, string, string, string]
++ | [
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string
++ ]
++ | [
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string
++ ]
++ | [
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string
++ ]
++ )
++ | undefined;
++ };
++ /**
++ * poll: read again on a timer (fresh); push: sent when it changes; connect: read once when the robot connects (provisional after).
++ */
++ source?: "poll" | "push" | "connect";
++ /**
++ * A reading older than this is shown as stale.
++ */
++ fresh_ms?: number;
++ /**
++ * The control that shows it.
++ */
++ control: "meter" | "readout" | "badge" | "list";
++ }[];
++}
++
/** [email protected] (owner: bot) */
/**
* bot.device-message@1 (ADR-043 decision 5): one frame on OpenVibe.Bot's device WebSocket (wss://openvibe.bot/device), JSON with v, seq and ts on every frame. Server to device: hello, config, command, estop, heartbeat_ack, error, paired (after a pair frame), rotate (a Network-paired machine is asked to rotate its credential with Network), voice_answer (Vibe's answer to a voice_ask). Device to server: pair (the only frame an unauthenticated socket may send), status, telemetry, ack, nack, heartbeat, reauth (Network-paired machines), estop_state, voice_ask (what the person asked after the machine's call word). The job frames on the same socket are platform.job-frame@1, not this contract. This duplicates two implementations that must not drift: OpenVibe.Bot server/realtime.js (the sender and reader in Bot) and OpenVibe Link internal/protocol/protocol.go (the Go structs of the device agent).
@@@ -338866,6 +339015,133 @@ export interface UiSurface {
* @maxItems 32
*/
never_covers?: string[];
++ /**
++ * What pressing or moving this part sends, in the robot manifest's terms (bot.robot-manifest@1, 0.418.0): kind and class, the value's ranges, lifetime, delivery window, release and rate. OpenVibe AI reads it when it suggests a layout or writes a control; it grants nothing: the product's gate checks every command.
++ */
++ command?: {
++ [k: string]: unknown | undefined;
++ } & {
++ [k: string]: unknown | undefined;
++ };
++ /**
++ * What this part shows, in the robot manifest's terms: the telemetry key, its fields, unit, range and source.
++ */
++ reads?: {
++ /**
++ * Where the reading arrives: a top-level telemetry key (battery) or a sensors key (p7_commander).
++ */
++ key: string;
++ label?: string;
++ unit?: string;
++ /**
++ * [least, most], inclusive.
++ *
++ * @minItems 2
++ * @maxItems 2
++ */
++ range?: [number, number];
++ fields?: {
++ /**
++ * One field of a value or a reading: a numeric range, "boolean", "string", "ms" (a time in milliseconds since the epoch), or the list of the values it may take.
++ */
++ [k: string]:
++ | (
++ | [number, number]
++ | ("boolean" | "string" | "ms" | "integer" | "number")
++ | [string]
++ | [string, string]
++ | [string, string, string]
++ | [string, string, string, string]
++ | [string, string, string, string, string]
++ | [string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string, string, string, string]
++ | [
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string
++ ]
++ | [
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string
++ ]
++ | [
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string
++ ]
++ | [
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string
++ ]
++ )
++ | undefined;
++ };
++ /**
++ * poll: read again on a timer (fresh); push: sent when it changes; connect: read once when the robot connects (provisional after).
++ */
++ source?: "poll" | "push" | "connect";
++ /**
++ * A reading older than this is shown as stale.
++ */
++ fresh_ms?: number;
++ /**
++ * The control that shows it.
++ */
++ control: "meter" | "readout" | "badge" | "list";
++ };
},
...{
/**
@@@ -339344,6 +339620,133 @@ export interface UiSurface {
* @maxItems 32
*/
never_covers?: string[];
++ /**
++ * What pressing or moving this part sends, in the robot manifest's terms (bot.robot-manifest@1, 0.418.0): kind and class, the value's ranges, lifetime, delivery window, release and rate. OpenVibe AI reads it when it suggests a layout or writes a control; it grants nothing: the product's gate checks every command.
++ */
++ command?: {
++ [k: string]: unknown | undefined;
++ } & {
++ [k: string]: unknown | undefined;
++ };
++ /**
++ * What this part shows, in the robot manifest's terms: the telemetry key, its fields, unit, range and source.
++ */
++ reads?: {
++ /**
++ * Where the reading arrives: a top-level telemetry key (battery) or a sensors key (p7_commander).
++ */
++ key: string;
++ label?: string;
++ unit?: string;
++ /**
++ * [least, most], inclusive.
++ *
++ * @minItems 2
++ * @maxItems 2
++ */
++ range?: [number, number];
++ fields?: {
++ /**
++ * One field of a value or a reading: a numeric range, "boolean", "string", "ms" (a time in milliseconds since the epoch), or the list of the values it may take.
++ */
++ [k: string]:
++ | (
++ | [number, number]
++ | ("boolean" | "string" | "ms" | "integer" | "number")
++ | [string]
++ | [string, string]
++ | [string, string, string]
++ | [string, string, string, string]
++ | [string, string, string, string, string]
++ | [string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string, string, string]
++ | [string, string, string, string, string, string, string, string, string, string, string, string]
++ | [
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string
++ ]
++ | [
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string
++ ]
++ | [
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string
++ ]
++ | [
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string,
++ string
++ ]
++ )
++ | undefined;
++ };
++ /**
++ * poll: read again on a timer (fresh); push: sent when it changes; connect: read once when the robot connects (provisional after).
++ */
++ source?: "poll" | "push" | "connect";
++ /**
++ * A reading older than this is shown as stale.
++ */
++ fresh_ms?: number;
++ /**
++ * The control that shows it.
++ */
++ control: "meter" | "readout" | "badge" | "list";
++ };
}[]
];
}
ddiff --git a/package.json b/package.json
iindex 3304d702..f1bb510a 100644
---- a/package.json
++++ b/package.json
@@@ -1,6 +1,6 @@
{
"name": "openvibe-contracts",
-- "version": "0.417.0",
++ "version": "0.418.0",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"main": "index.js",
"types": "generated/typescript/index.d.ts",