npm package: @inves/voiceai-client
Description: Client SDK for VoiceAI real-time voice conversation platform
Latest version: 1.0.2

# @inves/voiceai-client

Client SDK for [VoiceAI](https://voice.inves.dev) — real-time voice conversations with AI agents over WebRTC.

## Features

- **WebRTC audio** — bidirectional voice streaming with echo cancellation & noise suppression
- **React hook** — `useVoiceAI()` with state management & automatic cleanup
- **Vanilla JS** — framework-agnostic `VoiceAIClient` class
- **TypeScript** — full type definitions included
- **Lightweight** — zero runtime dependencies (React is an optional peer dep)

## Install

```bash
npm install @inves/voiceai-client
```

## Quick Start — Vanilla JS

```typescript
import { VoiceAIClient } from '@inves/voiceai-client';

const client = new VoiceAIClient({
  serverUrl: 'https://voice.yourdomain.com',
  apiKey: 'vai_your_api_key',
  onStateChange: (state) => console.log('State:', state),
  onTranscript: (msg) => console.log(`${msg.role}: ${msg.content}`),
  onError: (err) => console.error(err.code, err.message),
});

// Start a conversation
const sessionId = await client.startSession({
  assistantType: 'interview',
  contextVariables: { candidate_name: 'Alice' },
});

// ... conversation happens over WebRTC audio ...

// Get transcript & end session
const transcript = await client.getTranscript();
await client.endSession();
```

## Quick Start — React

```tsx
import { useVoiceAI } from '@inves/voiceai-client/react';

function VoiceChat() {
  const {
    state, transcript, error, audioLevel,
    startSession, endSession, isActive,
  } = useVoiceAI({
    serverUrl: 'https://voice.yourdomain.com',
    apiKey: 'vai_your_api_key',
  });

  return (
    <div>
      <p>Status: {state}</p>
      <button onClick={() => startSession({ assistantType: 'support' })}>
        Start Call
      </button>
      <button onClick={endSession} disabled={!isActive}>
        End Call
      </button>
      {transcript.map((msg, i) => (
        <p key={i}><b>{msg.role}:</b> {msg.content}</p>
      ))}
    </div>
  );
}
```

## API Reference

### `VoiceAIClient`

| Method | Description |
|---|---|
| `startSession(options)` | Start a voice session. Returns session ID. |
| `endSession()` | End session, stop mic, close WebRTC. |
| `getTranscript(sessionId?)` | Fetch full transcript from server. |
| `getSessionStatus(sessionId?)` | Get current session status. |
| `currentState` | Current `SessionState` value. |
| `activeSessionId` | Current session ID or `null`. |
| `isActive` | `true` if in an active conversation. |

### `useVoiceAI(options)` (React)

Returns: `{ state, sessionId, transcript, error, audioLevel, startSession, endSession, getTranscript, isIdle, isConnected, isActive }`

Automatically cleans up on component unmount.

### Session States

`idle` → `connecting` → `connected` → `listening` → `processing` → `speaking` → `ended`

### Error Codes

| Code | Meaning |
|---|---|
| `NETWORK_ERROR` | Server unreachable |
| `AUTH_ERROR` | Invalid API key (401/403) |
| `SESSION_ERROR` | Session creation/lookup failed |
| `CAPACITY_ERROR` | Max concurrent sessions (503) |
| `WEBRTC_ERROR` | SDP exchange or connection failed |
| `MEDIA_ERROR` | Microphone access denied |
| `CONNECTION_LOST` | WebRTC dropped mid-session |

## Requirements

- Browser with WebRTC support (Chrome, Firefox, Safari, Edge)
- Microphone access
- A running VoiceAI server instance

## License

MIT