npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@centive/aria-sdk

v0.9.3

Published

Production-ready React SDK for Anam AI with dual-mode operation, WebSocket integration, and message accumulation

Readme

Aria SDK

A production-ready SDK for integrating Anam AI into your web application. Simple initialization, automatic session management, and a beautiful AI assistant interface.

npm version License: MIT

Quick Start

import { Aria } from '@centive/aria-sdk';

// Initialize with just 3 lines
Aria.init({
  websocketUrl: 'wss://your-server.com/ws',
  userId: 'user_123',
});

// That's it! The floating button appears automatically.

Installation

npm install @centive/aria-sdk

Peer Dependencies

npm install react@^18.0.0 react-dom@^18.0.0 @anam-ai/js-sdk@^4.7.0

Features

| Feature | Description | |---------|-------------| | Simple Init | Single function call to set up everything | | Auto Session Management | WebSocket connection, token refresh, reconnection - all automatic | | Dual-Mode UI | Floating button + center modal for WebSocket-triggered events | | Session Persistence | Sessions survive page navigation and widget close/reopen | | Error Recovery | Automatic reconnection with exponential backoff | | Tool Call Indicators | Visual feedback when AI executes functions | | Theme Support | Light and dark themes |

Configuration

Aria.init({
  // Required
  websocketUrl: string,  // Your backend WebSocket URL
  userId: string,        // Unique user identifier

  // Optional
  theme?: 'light' | 'dark',           // UI theme (default: 'light')
  triggerLabel?: string,              // Button label (default: 'Talk to Aria')
  onError?: (error: Error) => void,   // Error callback
});

Example with All Options

import { Aria } from '@centive/aria-sdk';

Aria.init({
  websocketUrl: 'wss://api.example.com/ws',
  userId: 'user_123',
  theme: 'dark',
  triggerLabel: 'Need Help?',
  onError: (error) => {
    console.error('Aria SDK error:', error);
  },
});

API Reference

| Method | Description | |--------|-------------| | Aria.init(config) | Initialize the SDK | | Aria.open(mode?) | Open assistant widget ('user' or 'websocket') | | Aria.close() | Close assistant widget | | Aria.minimize() | Minimize to compact state | | Aria.maximize() | Restore from minimized | | Aria.destroy() | Cleanup and remove SDK | | Aria.isInitialized() | Check if SDK is initialized | | Aria.isOpen() | Check if widget is open | | Aria.isConnected() | Check WebSocket connection | | Aria.getSessionId() | Get current session ID | | Aria.refreshSession() | Manually refresh session |

Programmatic Control

// Open the assistant
Aria.open();

// Open in center mode (like incoming call)
Aria.open('websocket');

// Close the assistant
Aria.close();

// Minimize/maximize
Aria.minimize();
Aria.maximize();

// Check status
if (Aria.isConnected()) {
  console.log('Session ID:', Aria.getSessionId());
}

// Cleanup when done
Aria.destroy();

Backend Requirements

The SDK connects to your backend via WebSocket. Your backend handles:

  1. User Authentication - Validate the connecting user
  2. Session Token Generation - Create Anam AI sessions
  3. Persona Configuration - Control AI behavior server-side (avatar, voice, LLM, system prompt)
  4. Message Storage - Store conversation history (optional)

Messages from SDK to Backend

1. Session Request (user_trigger)

Sent when user opens the widget to request a new session token.

{
  "user_trigger": true,
  "userId": "user_123",
  "skip_greeting": true  // true after first session (to skip greeting on reopen)
}

| Field | Type | Description | |-------|------|-------------| | user_trigger | boolean | Always true when requesting a session | | userId | string | User identifier passed to Aria.init() | | skip_greeting | boolean | true if user has already had a session (skip greeting on subsequent opens) |

2. Message History

Sent when conversation messages are updated.

{
  "type": "message_history",
  "session_id": "anam_session_abc123",
  "user_id": "user_123",
  "messages": [
    { "role": "persona", "content": "Hello! How can I help?", "timestamp": "2026-01-29T12:00:00.000Z" },
    { "role": "user", "content": "I need help with my account", "timestamp": "2026-01-29T12:00:05.000Z" }
  ]
}

3. Message Stream

Sent for real-time message streaming (as user/persona speaks).

{
  "type": "message_stream",
  "session_id": "anam_session_abc123",
  "user_id": "user_123",
  "message": {
    "role": "user",
    "content": "partial transcript...",
    "timestamp": "2026-01-29T12:00:05.000Z",
    "is_final": false
  }
}

4. Session End

Sent when user closes the widget (hangs up).

{
  "type": "session_end",
  "session_id": "anam_session_abc123",
  "user_id": "user_123"
}

Expected Response Format

Session Token Response

{
  "status": "success",
  "message": "Session created successfully",
  "session_data": {
    "session_id": "sess_abc123",
    "token": "eyJhbGciOiJIUzI1NiIs...",
    "expires_at": "2026-01-27T12:00:00Z"
  },
  "time_taken": 1234
}

Message Acknowledgments (Optional)

// Message history acknowledgment
{ "status": "ok", "type": "message_history_ack", "message_count": 5 }

// Message stream acknowledgment (for is_final: true)
{ "status": "ok", "type": "message_stream_ack" }

// Session end acknowledgment
{ "status": "ok", "type": "session_end_ack", "message": "Session ended", "saved_count": 10 }

Backend Example (Node.js)

const WebSocket = require('ws');
const axios = require('axios');

const wss = new WebSocket.Server({ port: 8000 });

wss.on('connection', (ws) => {
  ws.on('message', async (message) => {
    const data = JSON.parse(message);
    
    // Handle session request
    if (data.user_trigger !== undefined) {
      const startTime = Date.now();
      const session = await createAnamSession(data.userId, data.skip_greeting);
      
      ws.send(JSON.stringify({
        status: 'success',
        message: 'Session created',
        session_data: {
          session_id: session.id,
          token: session.sessionToken,
          expires_at: session.expiresAt,
        },
        time_taken: Date.now() - startTime,
      }));
    }
    
    // Handle message history (store in database)
    if (data.type === 'message_history') {
      await storeMessages(data.session_id, data.user_id, data.messages);
      ws.send(JSON.stringify({
        status: 'ok',
        type: 'message_history_ack',
        message_count: data.messages.length,
      }));
    }
    
    // Handle session end
    if (data.type === 'session_end') {
      await finalizeSession(data.session_id, data.user_id);
      ws.send(JSON.stringify({
        status: 'ok',
        type: 'session_end_ack',
        message: 'Session ended',
        saved_count: 10,
      }));
    }
  });
});

async function createAnamSession(userId, skipGreeting = false) {
  const response = await axios.post(
    'https://api.anam.ai/v1/auth/session-token',
    {
      personaConfig: {
        name: 'Aria',
        avatarId: 'your-avatar-id',
        voiceId: 'your-voice-id',
        llmId: 'your-llm-id',
        systemPrompt: 'You are Aria, a helpful AI assistant.',
        skip_greeting: skipGreeting,  // Pass skip_greeting to Anam
      },
    },
    {
      headers: { 'Authorization': `Bearer ${process.env.ANAM_API_KEY}` },
    }
  );
  
  return response.data;
}

async function storeMessages(sessionId, userId, messages) {
  // Store messages in your database
  console.log(`Storing ${messages.length} messages for user ${userId}`);
}

async function finalizeSession(sessionId, userId) {
  // Mark session as complete, perform any cleanup
  console.log(`Session ${sessionId} ended for user ${userId}`);
}

Session Lifecycle

The SDK manages Anam sessions automatically:

| Event | What Happens | |-------|--------------| | Widget Opens (first time) | Sends user_trigger with skip_greeting: false → Creates Anam session with greeting | | Widget Closes (hang up) | Sends session_end → Ends Anam session to free resources | | Widget Reopens | Sends user_trigger with skip_greeting: true → Creates new session without greeting | | Page Refresh | Sends user_trigger with skip_greeting: false → Fresh session with greeting |

This ensures:

  • Anam resources are freed when the widget is closed
  • Users don't hear the greeting repeatedly when reopening the widget
  • Conversation context can be restored via your backend's message storage

Session Persistence

For video sessions to persist across page navigation, initialize the SDK at the root level of your application:

// App.tsx - Correct placement
import { Aria } from '@centive/aria-sdk';

// Initialize once at app startup
Aria.init({
  websocketUrl: 'wss://your-server.com/ws',
  userId: 'user_123',
});

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<HomePage />} />
        <Route path="/dashboard" element={<DashboardPage />} />
      </Routes>
    </Router>
  );
}

Bundler Configuration

The @anam-ai/js-sdk requires a Buffer polyfill. See the Integration Guide for Vite, Webpack, and Next.js configurations.

Quick fix for Vite:

npm install buffer
// main.tsx (at the very top)
import { Buffer } from 'buffer';
globalThis.Buffer = Buffer;

Security Best Practices

  • Use secure WebSocket connections (wss://) in production
  • Store Anam API keys only on the backend
  • Validate user IDs on your backend
  • Never expose API keys in frontend code

Browser Support

  • Chrome/Edge (latest)
  • Firefox (latest)
  • Safari (latest)
  • Opera (latest)

Requires WebRTC support for video streaming.

Documentation

License

MIT © Centive

Support