openvibers/openvibe.contracts Commits
openvibe-contracts 0.418.0: bot.robot-manifest@1, a robot's own manifest (LOOI 1.0.0 frozen) (#470)
Changes
@@@ -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 thennew file mode 100644@@@ -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." }++ }++ }++ }++}@@@ -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",@@@ -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."}}}nnew file mode 100644@@@ -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 filennew file mode 100644@@@ -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 filennew file mode 100644@@@ -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 filennew file mode 100644@@@ -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"++ }++ ]++}nnew file mode 100644@@@ -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 filennew file mode 100644@@@ -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"++ ]++ }++ }++ ]++}@@@ -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."}}}@@@ -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"@@@ -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."}}}@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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"@@@ -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";++ };}[]];}@@@ -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",
@@ -1,5 +1,25 @@
@@ -1,5 +1,25 @@
# Changelog
# 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
## 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
**The agent engine's next shapes:** who asked, what a run continues, how several agents share one ask, and where the
new file mode 100644
new file mode 100644
@@ -0,0 +1,109 @@
@@ -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." }
+ }
+ }
+ }
+}
@@ -7247,6 +7247,16 @@
@@ -7247,6 +7247,16 @@
"status": "active",
"status": "active",
"adr": "ADR-043"
"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",
"id": "bot.device-message",
"version": "1.0.0",
"version": "1.0.0",
@@ -193,6 +193,14 @@
@@ -193,6 +193,14 @@
"uniqueItems": true,
"uniqueItems": true,
"items": { "type": "string", "pattern": "^[a-z][a-z0-9_.-]{0,39}$" },
"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."
"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."
}
}
}
}
}
}
new file mode 100644
new file mode 100644
@@ -0,0 +1,117 @@
@@ -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
\ No newline at end of file
new file mode 100644
new file mode 100644
@@ -0,0 +1,118 @@
@@ -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
\ No newline at end of file
new file mode 100644
new file mode 100644
@@ -0,0 +1,117 @@
@@ -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
\ No newline at end of file
new file mode 100644
new file mode 100644
@@ -0,0 +1,118 @@
@@ -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"
+ }
+ ]
+}
new file mode 100644
new file mode 100644
@@ -0,0 +1,339 @@
@@ -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
\ No newline at end of file
new file mode 100644
new file mode 100644
@@ -0,0 +1,340 @@
@@ -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"
+ ]
+ }
+ }
+ ]
+}
@@ -82435,6 +82435,321 @@
@@ -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": {
"bot.device-message": {
"version": "1.0.0",
"version": "1.0.0",
"owner": "bot",
"owner": "bot",
@@ -131433,6 +131748,14 @@
@@ -131433,6 +131748,14 @@
"pattern": "^[a-z][a-z0-9_.-]{0,39}$"
"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."
"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."
}
}
}
}
}
}
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Actor API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.AI API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -9107,6 +9107,314 @@
@@ -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": {
"common.action-item.v1": {
"title": "ActionItem",
"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.",
"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 @@
@@ -10906,6 +11214,14 @@
"pattern": "^[a-z][a-z0-9_.-]{0,39}$"
"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."
"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."
}
}
}
}
}
}
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Bench API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Billing API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Blog API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Bot API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Chat API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Codes API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Community API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe Connect API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Coupons API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Deals API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Design API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Domains API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Events API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Exchange API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Food API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Games API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Git API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Host API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Inventory API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Live API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Mail API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.MediaHub API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Media API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Network API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.News API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenRestream API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Play API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Quest API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Report API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Reviews API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Run API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Search API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Services API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Sources API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Space API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Tips API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Today API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Tools API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Trade API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.VIP API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Vision API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Watch API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Wiki API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Work API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -3,8 +3,8 @@
@@ -3,8 +3,8 @@
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
"info": {
"info": {
"title": "OpenVibe.Zone API",
"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": {
"license": {
"name": "MIT",
"name": "MIT",
"identifier": "MIT"
"identifier": "MIT"
@@ -219410,6 +219410,155 @@ export interface BotRobotProfile {
@@ -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) */
/** [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).
* 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 {
@@ -338866,6 +339015,133 @@ export interface UiSurface {
* @maxItems 32
* @maxItems 32
*/
*/
never_covers?: string[];
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 {
@@ -339344,6 +339620,133 @@ export interface UiSurface {
* @maxItems 32
* @maxItems 32
*/
*/
never_covers?: string[];
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";
+ };
}[]
}[]
];
];
}
}
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
{
{
"name": "openvibe-contracts",
"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.",
"description": "Machine-readable contracts for the OpenVibe network: schemas, manifests, ids, error envelope, capability checks.",
"main": "index.js",
"main": "index.js",
"types": "generated/typescript/index.d.ts",
"types": "generated/typescript/index.d.ts",