eve-engine-sdk
v0.1.1
Published
JavaScript SDK for the EVE engine — voice, video, and chat
Readme
eve-engine-sdk
JavaScript/TypeScript SDK for the EVE engine. Provides voice, video, and chat capabilities for web applications.
Install
npm install eve-engine-sdkPeer dependencies
The SDK wraps VAPI and Daily.co for WebRTC. Install them alongside the SDK:
npm install @vapi-ai/web @daily-co/daily-jsAuthentication
The SDK uses short-lived JWT tokens (5-minute expiry) minted by your backend. Your server calls POST /api/auth/sdk-token with its API key to generate a token for the browser client.
Token flow:
- Your backend holds a partner API key (
sk_live_...). - Browser requests a token from your server.
- Your server calls
POST /api/auth/sdk-tokenon the EVE engine, passing the API key and the user's ID + scopes. - The engine returns a short-lived JWT.
- Your server passes the JWT to the browser.
- The browser creates an
EngineClientwith the JWT.
Token refresh: JWTs expire after 5 minutes. When an AuthError is thrown, request a new token from your backend and call client.setToken(newToken) to continue.
import { EngineClient, AuthError } from 'eve-engine-sdk'
const client = new EngineClient({ baseUrl: 'https://your-engine-url', token: '<jwt>' })
async function withTokenRefresh<T>(fn: () => Promise<T>): Promise<T> {
try {
return await fn()
} catch (err) {
if (err instanceof AuthError) {
const newToken = await fetchNewTokenFromYourBackend()
client.setToken(newToken)
return await fn()
}
throw err
}
}API Reference
EngineClient
import { EngineClient } from 'eve-engine-sdk'
const client = new EngineClient({
baseUrl: 'https://your-engine-url', // required
token: '<short-lived-jwt>', // required
timeoutMs: 30000, // optional, default 30s
})Methods:
| Method | Description |
|--------|-------------|
| startVoiceCall(options) | Fetch voice config and start a VAPI WebRTC call. Returns Promise<VoiceCall>. |
| startVideoCall(options) | Fetch video config and start a Daily.co call. Returns Promise<VideoCall>. |
| setToken(token) | Replace the JWT (for token refresh). Throws ConfigError if empty. |
| request(path, init?) | Low-level HTTP helper. Not part of the stable consumer API. |
Constructor options (EngineClientOptions):
| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| baseUrl | string | yes | - | Engine URL. Must be HTTPS (http://localhost allowed for dev). |
| token | string | yes | - | Short-lived JWT from POST /api/auth/sdk-token. |
| timeoutMs | number | no | 30000 | Request timeout in milliseconds. |
VoiceCall
Obtain via client.startVoiceCall({ personaId }).
Options (StartVoiceCallOptions):
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| personaId | string | yes | The persona to use. |
| voiceId | string | no | Override the persona's default voice. |
| model | string | no | Override the persona's default LLM model. |
Events:
| Event | Payload | Description |
|-------|---------|-------------|
| 'started' | (none) | Call connected. Replayed for the first subscriber if already started. |
| 'transcript' | string | Final transcript segment from the assistant. |
| 'ended' | VoiceCallEndedPayload | Call ended (client or server). |
VoiceCallEndedPayload:
| Field | Type | Description |
|-------|------|-------------|
| duration | number | Call duration in seconds. |
| transcript | string | Concatenated final transcript segments. |
Methods:
| Method | Description |
|--------|-------------|
| on(event, handler) | Subscribe to an event. Returns this for chaining. |
| hangup() | End the call, remove listeners, fire ended. Returns Promise<void>. |
| dispose() | Remove listeners without ending the call. Use after hangup() rejects. |
VideoCall
Obtain via client.startVideoCall({ personaId }).
Options (StartVideoCallOptions):
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| personaId | string | yes | The persona to use. |
| replicaId | string | no | Tavus replica ID (required if persona has no default). |
Events:
| Event | Payload | Description |
|-------|---------|-------------|
| 'started' | (none) | Joined the Daily.co room. Replayed for the first subscriber if already joined. |
| 'ended' | VideoCallEndedPayload | Call ended (client or server). |
VideoCallEndedPayload:
| Field | Type | Description |
|-------|------|-------------|
| duration | number | Call duration in seconds. |
Methods:
| Method | Description |
|--------|-------------|
| on(event, handler) | Subscribe to an event. Returns this for chaining. |
| hangup() | Leave the call, destroy Daily object, fire ended. Returns Promise<void>. |
| dispose() | Remove listeners without leaving the call. Use after hangup() rejects. |
Tool calls from the Tavus avatar are handled automatically — no code needed.
Errors
All errors extend EngineError (which extends Error).
| Class | Code | When |
|-------|------|------|
| ConfigError | CONFIG_ERROR | Invalid baseUrl, missing token, path traversal, bad server config. |
| AuthError | AUTH_ERROR | HTTP 401/403 from the engine. Token expired or invalid. |
| NetworkError | NETWORK_ERROR | Network failure, non-2xx response, invalid JSON. Carries optional status. |
import { AuthError, NetworkError } from 'eve-engine-sdk'
try {
const call = await client.startVoiceCall({ personaId: 'p_001' })
} catch (err) {
if (err instanceof AuthError) {
// Token expired — refresh it
} else if (err instanceof NetworkError) {
console.log('Status:', err.status) // e.g. 503
}
}VERSION
import { VERSION } from 'eve-engine-sdk'
console.log(VERSION) // matches package.json versionTypeScript types
The SDK ships built-in TypeScript declarations. All public types are exported:
import type {
EngineClientOptions,
StartVoiceCallOptions,
StartVideoCallOptions,
VoiceCallEndedPayload,
VideoCallEndedPayload,
ErrorCode,
} from 'eve-engine-sdk'Usage
import { EngineClient } from 'eve-engine-sdk'
const engine = new EngineClient({
baseUrl: 'https://your-engine-url',
token: '<short-lived-jwt>', // minted by your backend
})
// Voice call
const call = await engine.startVoiceCall({ personaId: 'p_001' })
call.on('started', () => console.log('call started'))
call.on('transcript', (text) => console.log(text))
call.on('ended', ({ duration }) => console.log('ended after', duration, 's'))
call.hangup()
// Video call
const video = await engine.startVideoCall({ personaId: 'p_001' })
video.on('started', () => console.log('video started'))
video.on('ended', ({ duration }) => console.log('ended after', duration, 's'))
video.hangup()Development
npm install
npm run build # ESM + CJS + .d.ts
npm test # Vitest
npm run typecheckLinks
- Partner Integration Guide — full auth flow, API key management, REST API reference
