npm package: @sindarin/persona-react-native
Description: Sindarin Persona React Native SDK
Author: Sindarin Ventures
Latest version: 0.0.13

# Sindarin Persona SDK for React Native

[![Version](https://img.shields.io/npm/v/%40sindarin%2Fpersona-react-native)](https://www.npmjs.org/package/%40sindarin%2Fpersona-react-native)

**Sindarin Persona** enables you to add lifelike conversational speech AI agents to your webapp.
It features ultra low latency, industry-leading turn-taking and transcription, and high-fidelity speech synthesis.

Demo: https://sindarin.tech

## Installation

Install the package with:

```sh
npm install @sindarin/persona-react-native
# or
yarn add @sindarin/persona-react-native
```

## Usage

The package needs to be configured with your account's secret key, which is
available in the [Persona Web App / Settings][api-keys].

```js
import PersonaClient from "@sindarin/persona-react-native";

const personaClient = new PersonaClient();

useEffect(() => {
	const messages = personaClient.events.addListener(
		"messages_update",
		(messages) => {
			console.log("messages_update :", messages);

		},
	);

	const ready = personaClient.events.addListener("ready", () => {
		console.log("ready");
	});

	const error = personaClient.events.addListener("error", (error) => {
		console.log(error);
	});

	return () => {
		messages.remove();
		ready.remove();
		error.remove();
	};
}, []);

const handleStartChatButtonClick = () => {
  // Example config using a persona defined in the Playground; there are many ways to do things!
  const config = {
			url: "https://api.prod.centralus.az.sindarin.tech",
			apiKey: "$apiKey",
			userId: "admin",
			personaName: "John",
			options: {
				shouldNotSaveConversation: true,
				debugMode: true,
				streamTranscripts: true,
			},
  };

  try {
    personaClient.init(config);
  } catch (error) {
    console.log(error);
  }
};

const handlePauseChatButtonClick = () => {
    personaClient.pause();
};

const handleResumeChatButtonClick = () => {
    personaClient.resume();
};

const handleStopChatButtonClick =  () => {
    await personaClient.end();
};

const handleUpdateState = (newState) => {
    personaClient.updateState(newState);
};

const handleReactTo = (thought) => {
    personaClient.reactTo(thought);
};

```

## Configuration

### Initialize with config object

You can initialize a conversation with the following config fields:

```js
const config = {
  userId: "admin", // optional
  personaName: "John", // optional
  personaId: "example_id", // optional; this is found in the Persona Playground
  details: { firstName: "John" }, // optional; arbitrary data you can inject into your prompt with {{details.x}}
  metadata: { orderId: "1" }, // optional; arbitrary data used for conversation retrieval / filtering later
  personaConfig: {
    initialMessage: "Hello {{details.firstName}}!",
    prompt: "You are a fun and helpful persona.",
    actions: { properties: {} },
    ttsConfig: {
      voiceId: "example_id", // voice IDs can be found and tested in the Playground
    },
    llmConfig: {
      llm: "example_llm_name", // e.g. llama-3-70b, llama-3-8b, gpt-4o, hermes-2-mixtral-8x7B-dpo
      temperature: 0.8, // 0 to 1
      repetitionPenalty: 1 // -3.5 to 3.5 for non-openai models; -2 to 2 for openai models
    },
    interjections: { // the ability for the persona to speak spontaneously
      enabled: true,
      minWait: 7500,
      maxWait: 10000,
      thought: "Nobody has said anything in a while. I should nudge the conversation along."
    },
    chargeLimitEnabled: true, // optional; should the conversation be cut off after a certain amount of charges incurred?
    chargeLimit: 2, // optional; the charge limit
    lifecycleEvents: { // optional; if the webhook endpoint returns { state } or { details } in the response body, they will be injected
      onInit: {
        webhook: {
          url: "http://example.com",
          method: "GET",
          body: {},
          headers: {}
        }
      },
      onStateChange: { /* ... */ },
      onEnd: { /* ... */ }
    }
  },
  options: {
    debugMode: true, // emit debug events in messages
    streamTranscripts: true, // stream transcripts in realtime
    shouldNotSaveConversation: true, // do not save transcripts
  },
};

try {
  await personaClient.init(config);
} catch (error) {
  console.log(error);
}
```

| Option                              | Default | Description                                                                                                                          |
| ----------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `userId`                            | `null`  | [Optional] Your unique ID for the current user.                                                               |
| `personaName`                       | `null`  | [Optional; this or personaId or personaConfig required] The persona name in the Playground specifying a particular persona config.                                                           |
| `personaId`                         | `null`  | [Optional; this or personaName or personaConfig required] The persona ID in the Playground specifying a particular persona config. This takes priority over `personaName` if both are provided. |
| `details`                           | `null`  | [Optional] An object containing arbitrary information that you can inject into your prompt before the conversation starts using {{details.x}}.                |
| `metadata`                          | `null`  | [Optional] An object containing arbitrary information for the developer to retrieve the conversation by.                                        |
| `personaConfig`                     | `null`  | [Optional; this or personaName or personaId required] An ad hoc persona configuration specified entirely in your code.  |
| `options`                           | -       | [Optional] Additional options (below).                                                                                                                  |
| `options.debugMode`                 | `false` | `Messages` array will contain additional debug events (info, warn, error) for debugging purposes during a conversation.                 | 
| `options.streamTranscripts`         | `false` | Temporary transcripts will be rendered in the `messages` array.
| `options.shouldNotSaveConversation` | `false` | If true, the transcript will not be saved after the conversation ends.                                |

## Error Handling Options

```js

personaClient.on("error", (error) => {
  console.log(error);
});

personaClient.on("connect_error", (error) => {
  console.log(error);
});
```

[api-keys]: https://persona-webapp-beta.vercel.app/