NaomiProject / Naomi

The Naomi Project is an open source, technology agnostic platform for developing always-on, voice-controlled applications!
https://projectnaomi.com/
MIT License
242 stars 47 forks source link

[Feature-Request] - RESTful API #46

Open TuxSeb opened 6 years ago

TuxSeb commented 6 years ago

Based on this Pull Request: https://github.com/jasperproject/jasper-client/pull/439

That would allow us to interact with Naomi using basic HTTP requests

sbernhard commented 5 years ago

Is there already working on this feature? I would love to have this, too.

redragonx commented 5 years ago

@shbhrsaha I don't see any work yet. You can go ahead and start working on this. We can touch base later with @TuxSeb

Please join our Discord server when you can.

aaronchantrill commented 4 years ago

Here are some thoughts I have about what I'd like to see in a RESTful API. These are just based on the sorts of things we are currently communicating to the terminal interface, so this just describes the minimum api that would allow the current functionality to shift from the command line to a web or desktop application interface.

The major functionalities right now are configuring user options and responding to events.

Since this is a complex topic, I think it's a good idea to get a good idea on what exactly this should look like before starting to work on it.

These are just my initial thoughts and by no means complete.

Settings

Settings are created by plugin authors and are read into Naomi while parsing plugins. They contain the basic information for collecting any data from the user. For instance, a weather plugin could need to know what city to provide weather for by default. A service (like google calendar or google stt cloud) may need an authentication key or token. Thus the only verb that needs to be used here is GET for retrieving the structure of a setting. We probably also want to group settings by plugin.

Sample requests:

GET /v1/settings?locale=en_US GET /v1/setting/{path}?locale=en_US GET /v1/settings/{plugin}?locale=en_US

Sample transaction

Request: GET /v1/setting/active_stt/engine?locale=en_US

Response:

[
    {
        "plugin": "core",
        "path": ["active_stt","engine"],
        "title": "Please select an active speech to text engine",
        "type": "listbox",
        "description": "After I hear my wake word, this engine processes everything I hear. I recommend an offline option, but you could also use an online option like Google Cloud STT."
        "options": ["Pocketsphinx", "Google Cloud STT", "DeepSpeech", "Julius", "Kaldi"],
        "default": "Pocketsphinx"
    }
]

ProfileVariables

Profile variables are the actual variables being set by settings, or otherwise existing in the profile. These can be created (POST), retrieved (GET), updated (PUT), deleted (DELETE). I think we should consider having two special verbs also, which are "validate" and "active".

Validation would validate a value entered for a variable without actually setting it on the server. This would allow a user to know after leaving a text field if the value they have entered will be accepted or rejected by the server. This uses the profile.validate(["path"], "value") function on the server side, keeping validation consistent.

Active tells the client whether a specific setting should even be made available to the user. For instance, if the user decides not to enter their email address, then the server, port, username and password are meaningless. Once the user enters the email address, then the other fields become available. Since this will usually be dependent on information that has not actually been submitted to the server yet, we would need to work out a method for passing the client-side status of the form. This would have to be checked for every field every time a value is updated on the client side, so should probably be limited to the currently visible fields.

Sample requests:

GET /v1/profilevars GET /v1/profilevar/{path} POST /v1/profilevar/{path} POST /v1/profilevar/{path}?validate POST /v1/profilevar/{path}?active PUT /v1/profilevar/{path} DELETE /v1/profilevar/{path}

Sample transaction

Request: GET /v1/profilevar/active_stt/engine

Response:

[
    {
        "path": ["active_stt", "engine"],
        "value": "Pocketsphinx"
    }
]

Event Subscriptions

Subscribing to an event should allow external scripts to react to Visualizations events, like displaying volume, displaying conversation transcriptions, etc. This can be achieved either by opening a connection to the server and holding it open, processing events as they arrive until either the client or server closes the connection, or by setting up a polling interval from the client.

Sample requests:

POST /v1/stream/{visualization} GET /v1/streams DELETE /v1/stream/{visualization}

Sample transaction

Request: POST /v1/stream/mic_volume

Response:

[
    {
        "mic_volume": {
            "min": -11,
            "max": 23,
            "mean": 10,
            "threshold": 16,
            "volume": 11
        }
    }
]