# @rainbird/sdk

[![pipeline status](https://gitlab.com/rainbird-ai/sdk-js/badges/master/pipeline.svg)](https://gitlab.com/rainbird-ai/sdk-js/badges/master/pipeline.svg) [![coverage status](https://gitlab.com/rainbird-ai/sdk-js/badges/master/coverage.svg)](https://gitlab.com/rainbird-ai/sdk-js/badges/master/coverage.svg)

This package is designed to be a lightweight way to interact with Rainbird. Minimal dependencies to support older (>25% usage, not dead) browsers.

## Installation

```bash
yarn add @rainbird/sdk
```

```bash
npm i @rainbird/sdk
```

## Usage

##### Common arguments

| Name      | Type              | Description                                                                                    | Example/Help                                                      |
| --------- | ----------------- | ---------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| baseURL   | String            | The url to be targeted without any params                                                      | 'https://api.rainbird.ai'                                         |
| apiKey    | String            | The api key that allows access to the api                                                      | This can be found in the 'account' section of the Rainbird Studio |
| kmID      | String            | The ID of the specific knowledge map that you will query                                       | This can be found in the map view of the Rainbird Studio          |
| sessionID | String            | The ID of the current session                                                                  | Returned from the 'start' endpoint                                |
| options   | Object (optional) | Options provided to Rainbird, currently used to interact with different versions of the engine | `{ engine: 'v2.0' }`                                              |

#### Start

**Description**: A function to start a session to begin interaction with Rainbird.

**Args**: [baseURL](#common-arguments), [apiKey](#common-arguments), [kmID](#common-arguments), [options](#common-arguments)

**Returns**: `{` [sessionID](#common-arguments), kmVersionID: String `}`

**Example**:

```javascript
const sdk = require("@rainbird/sdk");

async function interact(baseURL, apiKey, kmID) {
    try {
        const { sessionID, kmVersionID } = await sdk.start(
            baseURL,
            apiKey,
            kmID,
            options,
        );
    } catch (e) {
        return e;
    }
}
```

#### Inject

**Description**: A function to create facts prior to, or during, a Rainbird query. (Can only be called after starting a session, see [start](#start))

**Args**: [baseURL](#common-arguments), [sessionID](#common-arguments), data (example below), [options](#common-arguments)

**Returns**: `{ ok: Bool }`

**Example**:

```javascript
const sdk = require("@rainbird/sdk");

async function interact(baseURL, sessionID) {
    const data = [
        { subject: "Bob", relationship: "speaks", object: "English", cf: 100 },
        { subject: "Bob", relationship: "lives in", object: "France", cf: 100 },
    ];

    try {
        const { ok } = await sdk.inject(baseURL, sessionID, data, options);
    } catch (e) {
        return e;
    }
}
```

#### Query

**Description**: A function to ask Rainbird an initial question

**Args**: [baseURL](#common-arguments), [sessionID](#common-arguments), subject: `String`, relationship: `String`, object: `String`, [options](#common-arguments)

**Returns**:

```json
{
    "question": {
        "allowCF": Bool,
        "allowUnknown": Bool,
        "canAdd": Bool,
        "concepts": [
            {
                "conceptType": String,
                "name": String,
                "type": String,
                "value": String,
                "fsid": Num
            }
        ],
        "dataType": String,
        "knownAnswers": Array,
        "object": String,
        "plural": Bool,
        "prompt": String,
        "relationship": String,
        "subject": String,
        "type": String
    },
    "extraQuestions": [{
        "allowCF": Bool,
        "allowUnknown": Bool,
        "canAdd": Bool,
        "concepts": [
            {
                "conceptType": String,
                "name": String,
                "type": String,
                "value": String,
                "fsid": Num
            }
        ],
        "dataType": String,
        "knownAnswers": Array,
        "object": String,
        "plural": Bool,
        "prompt": String,
        "relationship": String,
        "subject": String,
        "type": String
    }, ...],
    "sid": String
}
```

**Example**:

```javascript
const sdk = require("@rainbird/sdk");

async function interact(baseURL, apiKey) {
    try {
        const { data } = await sdk.query(
            baseURL,
            sessionID,
            "Person",
            "Speaks",
            "",
        );
        return data.question.prompt;
    } catch (e) {
        return e;
    }
}
```

#### Response

**Description**: A function to respond to a question from Rainbird

**Args**: [baseURL](#common-arguments), [sessionID](#common-arguments), answers: `Array[ Object{ subject: String, relationship: String, object: String, cf: Num } ]`, [options](#common-arguments)

**Returns**:

```json
{
    "data": {
        "question": {
            "allowCF": Bool,
            "allowUnknown": Bool,
            "canAdd": Bool,
            "concepts": [
                {
                    "conceptType": String,
                    "name": String,
                    "type": String,
                    "value": String,
                    "fsid": Num
                "}
            ],
            "dataType": String,
            "knownAnswers": Array,
            "object": String,
            "plural": Bool,
            "prompt": String,
            "relationship": String,
            "subject": String,
            "type": String
        },
        "extraQuestions": [{
            "allowCF": Bool,
            "allowUnknown": Bool,
            "canAdd": Bool,
            "concepts": [
                {
                    "conceptType": String,
                    "name": String,
                    "type": String,
                    "value": String,
                    "fsid": Num
                }
            ],
            "dataType": String,
            "knownAnswers": Array,
            "object": String,
            "plural": Bool,
            "prompt": String,
            "relationship": String,
            "subject": String,
            "type": String
        }, ...],
        "sid": String
    },
    "type": RESPONSE_TYPE_QUESTION
}
```

OR

```json
{
    "data": {
        "result": [
            {
                "certainty": Num,
                "factID": String,
                "object": String,
                "objectMetadata": Object,
                "relationship": String,
                "relationshipType": String,
                "subject": String,
                "subjectMetadata": Object
            }
        ],
        "sid": String
    },
    "type": RESPONSE_TYPE_RESULT
}
```

OR

```json
{
    "data": Any,
    "type": RESPONSE_TYPE_UNKNOWN
}
```

**Example**:

```javascript
const sdk = require("@rainbird/sdk");

async function interact(baseURL, apiKey) {
    const answers = [
        { subject: "Bob", relationship: "speaks", object: "French", cf: 100 },
    ];
    try {
        const { data, type } = await sdk.response(
            baseURL,
            sessionID,
            answers,
            {},
        );
    } catch (e) {
        return e;
    }
}
```

#### Response Types

**Description**: Symbols that explain the type of response returned from the response endpoint

**Usage**:

```javascript
const sdk = require("@rainbird/sdk");

data.type === sdk.RESPONSE_TYPE_QUESTION;
data.type === sdk.RESPONSE_TYPE_RESULT;
data.type === sdk.RESPONSE_TYPE_UNKNOWN;
```

#### Undo

**Description**: A function to go back a step in the interaction

**Args**: [baseURL](#common-arguments), [sessionID](#common-arguments), data: Object?, [options](#common-arguments)

**Returns**: [Response](#response)

**Example**:

```javascript
const sdk = require("@rainbird/sdk");

async function interact(baseURL, apiKey) {
    const answers = [
        { subject: "Bob", relationship: "speaks", object: "French", cf: 100 },
    ];
    try {
        const response = await sdk.response(baseURL, sessionID, answers, {});
        const { data, type } = await sdk.undo(baseURL, sessionID);
        // ...
    } catch (e) {
        return e;
    }
}
```

#### Evidence

**Description**: A function that provides the basis for a decision of a fact or rule

**Args**: [baseURL](#common-arguments), [sessionID](#common-arguments), factID: String (returned from result type response), [Options](#common-arguments) {engine: String, securityKey: String (to access secured evidence, you should pass your evidence key)}

**Returns**:

```json
{
    "fact": {
        "factID": String,
        "certainty": Num,
        "object": {
            "type": String,
            "value": String,
            "dataType": String
        },
        "relationship": {
            "type": String
        },
        "subject": {
            "type": String,
            "value": String,
            "dataType": String
        }
    },
    "rule": {
        "bindings": {
            "S": String,
            "O": String
            ...
        },
        "conditions": [
            {
                "certainty": Num,
                "factID": String,
                "factKey": Num,
                "object": String,
                "objectType": String,
                "relationship": String,
                "salience": Num,
                "subject": String
            }
        ]
    },
    "source": String,
    "time": Num
}
```

**Example**:

```javascript
const sdk = require("@rainbird/sdk");

async function getEvidence(baseURL, sessionID, factID) {
    try {
        const response = await sdk.evidence(baseURL, sessionID, factID);
        // ...
    } catch (e) {
        return e;
    }
}
```

#### Full Evidence

**Description**: A function that recursively retrieves an array of decisions of a fact or rule

**Args**: [baseURL](#common-arguments), [sessionID](#common-arguments), factID: String (returned from result type response), [Options](#common-arguments) {engine: String, securityKey: String (to access secured evidence, you should pass your evidence key)}

**Returns**:

```json
[{
    "fact": {
        "factID": String,
        "certainty": Num,
        "object": {
            "type": String,
            "value": String,
            "dataType": String
        },
        "relationship": {
            "type": String
        },
        "subject": {
            "type": String,
            "value": String,
            "dataType": String
        }
    },
    "rule": {
        "bindings": {
            "S": String,
            "O": String
            ...
        },
        "conditions": [
            {
                "certainty": Num,
                "factID": String,
                "factKey": Num,
                "object": String,
                "objectType": String,
                "relationship": String,
                "salience": Num,
                "subject": String
            }
        ]
    },
    "source": String,
    "time": Num
}, {
 ...
}]
```

**Example**:

```javascript
const sdk = require("@rainbird/sdk");

async function getFullEvidence(baseURL, sessionID, factID) {
    try {
        const response = await sdk.fullEvidence(baseURL, sessionID, factID);
        // ...
    } catch (e) {
        return e;
    }
}
```

#### Interaction log

**Description**: A function that provides an interaction log of events from a session

**Args**: [baseURL](#common-arguments), [sessionID](#common-arguments), interactionKey: String (to access secured interaction logs, you should pass your interaction key)

**Query params**: `format=csv` or `format=json` -- no query param defaults to JSON.

**Returns**:

```json
[
    {
        "values": {
            "start": {
                "useDraft": Boolean,
                "kmVersionID": String,
                "sessionID": String
            }
        },
        "event": String,
        "created": String
    }
]
```

OR

```json
[
    {
        "values": {
            "questions": {
                "subject": String OR Boolean OR Num,
                "relationship": String,
                "object": String OR Boolean OR Num,
                "prompt": String
            }
        },
        "event": String,
        "created": String
    }
]
```

OR

```json
[
    {
        "values": {
            "query": {
                "subject": String OR Boolean OR Num,
                "relationship": String,
                "object": String OR Boolean OR Num
            }
        },
        "event": String,
        "created": String
    }
]
```

OR

```json
[
    {
        "values": {
            "answers": {
                "subject": String OR Boolean OR Num,
                "relationship": String,
                "object": String OR Boolean OR Num,
                "certainty": Num
            }
        },
        "event": String,
        "created": String
    }
]
```

OR

```json
[
    {
        "values": {
            "results": {
                "subject": String OR Boolean OR Num,
                "relationship": String,
                "object": String OR Boolean OR Num,
                "certainty": Num
            }
        },
        "event": String,
        "created": String
    }
]
```

OR

```json
[
    {
        "values": {
            "facts": {
                "subject": String OR Boolean OR Num,
                "relationship": String,
                "object": String OR Boolean OR Num,
                "certainty": Num
            }
        },
        "event": String,
        "created": String
    }
]
```

OR

```json
[
    {
        "values": {
            "datasources": {
                "relationship": String,
                "certainty": Num
            }
        },
        "event": String,
        "created": String 
    }
]
```

**Engine compatibility**

```text
>= v2.0
```

**Example**:

```javascript
const sdk = require("@rainbird/sdk");

async function getInteractionLog(baseURL, sessionID) {
    try {
        const response = await sdk.interactionLog(baseURL, sessionID);
        // ...
    } catch (e) {
        return e;
    }
}
```

#### KnowledgeMap

**Description**: A function that returns information about the knowledge map used in the given session

**Args**: [baseURL](#common-arguments), [apiKey](#common-arguments), [sessionID](#common-arguments)

**Returns**:

```json
{
    "km": {
        "id": String,
        "name": String,
        "versionID": String,
        "versionCreated": String (ISO-8601 formatted),
        "versionStatus": String
    }
}
```

**Engine compatibility**

```text
>= v2.0
```

**Example**:

```javascript
const sdk = require("@rainbird/sdk");

async function getKnowledgeMapData(baseURL, apiKey, sessionID) {
    try {
        const response = await sdk.knowledgeMap(baseURL, apiKey, sessionID);
        // ...
    } catch (e) {
        return e;
    }
}
```


#### Facts

**Description**: A function that returns facts from the given session

**Args**: [baseURL](#common-arguments), [apiKey](#common-arguments), [sessionID](#common-arguments)

**Returns**:

```json
{
    "facts": {
        "global":[],
        "context":[],
        "local": [
            {
                "id": String,
                "subject": {
                    "concept": String,
                    "value": String OR Boolean OR Num,
                    "dataType": String ("string" OR "number" OR "boolean" OR "date")
                },
                "relationship": String,
                "object": {
                    "concept": String,
                    "value": String OR Boolean OR Num,
                    "dataType": String
                },
                "certainty": Num,
                "source": String
            }
        ]
    }
}
```

**Engine compatibility**

```text
>= v2.0
```

**Example**:

```javascript
const sdk = require("@rainbird/sdk");

async function getFacts(baseURL, apiKey, sessionID) {
    try {
        const response = await sdk.facts(baseURL, apiKey, sessionID);
        // ...
    } catch (e) {
        return e;
    }
}
```
