npm package: @proteus-ai/sdk
Description: This ProteusAI SDK aims to help the development of integrations with ProteusAI that use JavaScript, providing an easy interface to communicate with ProteusAI services.
Author: Wale Ayandiran
Latest version: 0.1.1

# @proteus-ai/sdk

This ProteusAI SDK aims to help the development of integrations with ProteusAI that use JavaScript, providing an easy interface to communicate with ProteusAI services.

## Installation

To install the ProteusAI SDK, use npm or yarn:

```bash
npm install @proteus-ai/sdk
```

or

```bash
yarn add @proteus-ai/sdk
```

## Usage

### Importing the SDK

First, import the ProteusAI SDK into your project:

```typescript
import ProteusAI from '@proteus-ai/sdk';
```

### Initializing the SDK

Create an instance of the ProteusAI class by providing your API key and optional configuration options:

```typescript
const proteus = new ProteusAI({
  apiKey: '' // get from your proteus AI account dashboard
});
```

### Connecting to the Service

You can register a callback to be invoked when the connection is successful:

```typescript
proteus.connected(() => {
  // You can be sure that the connection was successful inside this function.
  // Run events or emitters that need a guarantee or rely on a successful connection.
  console.log('Connected to ProteusAI');
});
```

### Checking Connection Status

You can check if the service is connected or connecting:

```typescript
if (proteus.isConnected) {
  console.log('ProteusAI is connected');
}

if (proteus.isConnecting) {
  console.log('ProteusAI is connecting');
}
```

### Disconnecting from the Service

To disconnect from the ProteusAI service:

```typescript
proteus.disconnect();
console.log('Disconnected from ProteusAI');
```

### Conversation API

The conversation API allows you start a conversation and to get an existing conversation created by the SKD with its ID.

#### Create Conversation

You can create a conversation by calling the `proteus.conversations.create({ characterId })`

```typescript
  const newConversation = await proteus.conversations.create({ characterId: 'characterId' });
  console.log('conversation id', newConversation.id);
```

You can also pass in a `String` representing the character ID.

```typescript
  const newConversation = await proteus.conversations.create('characterId');
  console.log('conversation id', newConversation.id);
```

First, you'll need to get the ID of the trained character you'd like to start a conversation with. This can be done on the ProteusAI app. Click on a character and then click the blue info icon next to the character's name.

![character id](https://proteus-ai-cdn.s3.eu-west-1.amazonaws.com/docs/character-id.png)

#### Get Conversation

```typescript
  const conversation = await proteus.conversations.getById('conversationId');
  console.log(conversation);
```

### Messaging API

The MessagesAPI allows you to handle messaging-related operations on the messages instance `proteus.messages`.

#### Sending Messages

To send a message, use the `send` method on the messages instance `proteus.messages`:

```typescript
const messagePayload = {
  conversationId: "conversation123",
  content: "Hello, ProteusAI!",
  type: "TEXT",
}

proteus.messages.send(messagePayload);
```

The `send` method is also available in the `Conversation` object you get from `proteus.conversations`.
In this case there is no need to include a `conversationId` in the payload of the `send` method.

```typescript
const conversation = await proteus.conversations.getById('conversation123');
conversation.send({
  content: "Hello, ProteusAI!",
  type: "TEXT",
})
```

The response from the `send` method is **not** the AI character's reply to the message sent.
The response is the same message sent, but with a few more fields, including the ProteusAI `id` of the message.

```typescript
const messagePayload = {
  conversationId: "conversation123",
  content: "Hello, ProteusAI!",
  type: "TEXT",
}

const messageResponse =  await proteus.messages.send(messagePayload);
console.log(`ProteusAI ID for this message is ${messageResponse.id}`);
console.log(`${messageResponse.conversationId} === ${messagePayload.conversationId}`);
console.log(`${messageResponse.content} === ${messagePayload.content}`);
```

#### Listening for Messages

To get AI responses to your messages you have to listen for the `CHARACTER_MESSAGE_SENT` events.

```typescript
proteus.messages.on('CHARACTER_MESSAGE_SENT', (message: any) => {
  console.log(`The message with ID ${message.id} was sent by an AI character`);
});

const messagePayload = {
  conversationId: "conversation123",
  content: "Hello, ProteusAI!",
  type: "TEXT",
}
proteus.messages.send(messagePayload);
```

To get all messages sent, listen for the `MESSAGE_SENT` event.

```typescript
proteus.messages.on('MESSAGE_SENT', (message: any) => {
  console.log(`The message with ID ${message.id} is either the original message sent or a response to the original message`);
});

const messagePayload = {
  conversationId: "conversation123",
  content: "Hello, ProteusAI!",
  type: "TEXT",
}
proteus.messages.send(messagePayload);
```

You can listen for messages sent to a specific conversation by using the `Conversation` object.

```typescript
const conversation = await proteus.conversations.getById('conversation123');

conversation.on('CHARACTER_MESSAGE_SENT', (message: any) => {
  console.log(`The message with ID ${message.id} was sent by an AI character`);
  console.log(`${message.conversationId} === ${conversation.id} === conversation123`);
});

conversation.send({
  content: "Hello, ProteusAI!",
  type: "TEXT",
})
```

To get all messages sent to a specific conversation, use the `Conversation` object to listen for the `MESSAGE_SENT` event.

```typescript
const conversation = await proteus.conversations.getById('conversation123');

conversation.on('MESSAGE_SENT', (message: any) => {
  console.log(`The message with ID ${message.id} was sent in this conversation`);
  console.log(`${message.conversationId} === ${conversation.id} === conversation123`);
});

conversation.send({
  content: "Hello, ProteusAI!",
  type: "TEXT",
})
```

**NOTE:** Ensure that the connection to ProteusAI is fully established before attempting to send a message. To guarantee this, you can call the `send` method inside the `proteus.connected` callback:

```typescript
const messagePayload = {
  conversationId: "conversation123",
  type: "TEXT",
  content: "Hello, ProteusAI!"
}

// Send is called only when a connection is fully established
proteus.connected(() => {
  proteus.messages.send(messagePayload);
})
```

**NOTE:**  You can only get or send messages to conversations that has been created within the SDK.

#### Message Streaming

Messages from AI characters that are of type `TEXT` get streamed from the server to clients.
This means the server does not need to wait for the character to construct the entire message before sending it to clients;
it continuously streams the message in packets until the entire message has been constructed.
This improves user experience as users no longer have to wait a long time just to be hit by the entire message at once.

To know if a message is still being streamed, see if the `isStreaming` field is `true`.

To see the content generated in the current packet, see the `contentDelta` field.

```typescript
import ProteusAI from '@proteus-ai/sdk';
const proteus = new ProteusAI({ apiKey: '66563d92e59961d11fc67a39' });
const conversation = await proteus.conversations.create({
    characterId: '659a21168ad10b77542a3587'
});
conversation.on('CHARACTER_MESSAGE_SENT', (message) => {
  if (message.isStreaming) {
    console.log('This message is still being streamed');
    console.log(`This portion of the message generated in the current packet is: ${message.contentDelta}`);
    console.log(`This message generated thus far is: ${message.content}`);
  } else {
    console.log('This message has now been fully constructed');
    console.log(`This complete message is: ${message.content}`);
  }
});
```

To get an AI character's response without streaming, set `streamReply` to false in the request payload

```typescript
const messagePayload = {
  conversationId: "conversation123",
  content: "Hello, ProteusAI!",
  type: "TEXT",
}

// To send a message without streaming set 'streamReply' to false in the payload
proteus.messages.send({
  ...messagePayload,
  streamReply: false
});
```

#### Error Handling

If an error occurs during a non-streaming message send, it will be logged to the console and then thrown.

## Development

### Building the SDK

To build the SDK, run:

```bash
npm run build
```

### License

This project is licensed under the MIT License - see the [LICENSE](https://docs.useproteus.ai/) file for details.

### Contact

For questions or feedback, please reach out to <hello@proteusai.app>.