Interface
The Nyra framework's messaging system facilitates interaction at the level of individual messages. However, real-world functionalities often require a series of coordinated messages, such as multiple commands and data exchanges. For instance, Speech-to-Text (STT) functionality involves a combination of commands and data messages, collectively referred to as an interface. An extension that supports all the messages defined by an interface can seamlessly operate in any context requiring that interface.
To simplify development, the Nyra framework aggregates messages within an interface. Extensions can declare their support for or dependence on an interface, avoiding the need to explicitly list every individual message in their manifest.
The framework provides the following primitive APIs to enable this functionality:
cmd_incmd_outdata_indata_outaudio_frame_inaudio_frame_outvideo_frame_invideo_frame_out
In addition to these, the framework also supports composite API mechanisms:
interface_ininterface_out
Interface Syntax
The basic syntax for defining an interface includes a mandatory name field. This name serves the same purpose as the name field in cmd_in and cmd_out, representing the name of the interface. It is significant only within the extension’s context and must be unique within that scope.
{
"api": {
"interface_in": [
{
"name": "foo"
}
],
"interface_out": [
{
"name": "foo"
}
]
}
}Using Interfaces in Graphs
The name of an interface is primarily utilized in graphs to define routing between extensions. In the example below, src_extension relies on the foo interface provided by dest_extension.
src_extensionidentifies thefoointerface through itsinterface_outdefinition.dest_extensionidentifies thefoointerface through itsinterface_indefinition.
{
"predefined_graphs": [{
"name": "default",
"auto_start": true,
"nodes": [
{
"type": "extension_group",
"name": "default_extension_group",
"addon": "default_extension_group"
},
{
"type": "extension",
"name": "src_extension",
"addon": "src_extension",
"extension_group": "default_extension_group"
},
{
"type": "extension",
"name": "dest_extension",
"addon": "dest_extension",
"extension_group": "default_extension_group"
}
],
"connections": [{
"extension": "src_extension",
"interface": [{
"name": "foo",
"dest": [{
"extension": "dest_extension"
}]
}]
}]
}]
}Meaning of interface_in and interface_out
interface_in and interface_outinterface_in
Indicates that the extension supports the specified interface's functionality.
{
"api": {
"interface_in": [
{
"name": "foo"
// Interface content
}
]
}
}interface_out
Indicates that the extension requires another extension to provide the specified interface's functionality.
{
"api": {
"interface_out": [
{
"name": "foo"
// Interface content
}
]
}
}Interface and Message Declaration
Declaring the interface in
interface_inimplicitly includes the three commands incmd_inand the data message indata_in.Declaring the interface in
interface_outimplicitly includes the three commands incmd_outand the data message indata_out.
If an interface specifies three commands and one data message:
Example: Interface with Multiple Messages
Extensions declaring an interface in their manifest are not required to explicitly list the messages contained in that interface. When the extension sends or receives a command, such as foo, the Nyra runtime references the interface definition in the manifest to process the command appropriately.
Manifest Implications
This interface mechanism acts as syntactic sugar, bundling a predefined set of messages for reuse across multiple extensions.
interface_in: The extension provides these three commands as part of the interface.interface_out: The extension requires these three commands from another extension.
When an extension declares an interface in its manifest, it implicitly includes all the messages defined within that interface. For example, if an interface foo specifies three commands, the following applies:
Supporting Multiple Interfaces with the Same Message Name
In the current design, an extension cannot declare support for two interfaces that define messages with the same name under a single API item. For instance, if both the foo and bar interfaces define a command named xxx, the following scenarios are either permitted or restricted:
Not allowed
{
"api": {
"interface_in": [
{
"name": "foo"
// Interface foo content
},
{
"name": "bar"
// Interface bar content
}
]
}
}Allowed
{
"api": {
"interface_out": [
{
"name": "foo"
// Interface foo content
},
{
"name": "bar"
// Interface bar content
}
]
}
}{
"api": {
"interface_in": [
{
"name": "foo"
// Interface foo content
}
],
"interface_out": [
{
"name": "bar"
// Interface bar content
}
]
}
}Interface Definition Content
An interface definition closely resembles the api field in a manifest. Below is an example of how an interface is defined:
{
"cmd": [
{
"name": "cmd_foo",
"property": {
"foo": {
"type": "int8"
},
"bar": {
"type": "string"
}
},
"result": {
"property": {
"aaa": {
"type": "int8"
},
"bbb": {
"type": "string"
}
}
}
}
],
"data": [
{
"name": "data_foo",
"property": {
"foo": {
"type": "int8"
},
"bar": {
"type": "string"
}
}
}
],
"video_frame": [],
"audio_frame": []
}The Nyra framework incorporates an interface's definitions into the extension's manifest under the api field. For example, commands specified in interface_in are mapped to cmd_in, while those in interface_out are integrated into cmd_out.
Specifying Interface Content
There are two ways to specify the content of an interface:
Directly embed the interface definition in the manifest. Example:
{
"api": {
"interface_in": [
{
"name": "foo",
"cmd": [],
"data": [],
"video_frame": [],
"audio_frame": []
}
]
}
}Utilize a reference to define the interface, analogous to the $ref syntax used in JSON schemas.
{
"api": {
"interface_in": [
{
"name": "foo",
"$ref": "http://www.github.com/darth_vader/fight.json"
}
]
}
}Determining Interface Compatibility
As an interface serves as syntactic sugar, its connectivity is determined by the compatibility of the underlying messages. When a source extension specifies an output interface foo, and a destination extension specifies an input interface bar, the Nyra runtime verifies whether the foo interface from the source is compatible with the bar interface at the destination.
{
"api": {
"interface_out": "foo"
// Interface content
}
}{
"api": {
"interface_in": "bar"
// Interface content
}
}{
"extension_group": {
"addon": "default_extension_group",
"name": "default_extension_group"
},
"extension": {
"addon": "extension_A",
"name": "extension_A"
},
"interface": [
{
"name": "foo",
"dest": [
{
"extension_group": {
"addon": "default_extension_group",
"name": "default_extension_group"
},
"extension": {
"addon": "dest_extension",
"name": "dest_extension"
}
}
]
}
]
}The Nyra framework examines the foo interface definition in the interface_out section of the source extension's manifest. It validates each message defined within the interface against the destination extension’s manifest, including its explicit message definitions and any interfaces declared in interface_in. If any message fails to meet the schema validation rules enforced by the Nyra framework, the graph configuration is deemed invalid.
Last updated