Metadata-Version: 2.4
Name: moss-voice-server
Version: 0.1.0
Summary: Backend token generation for Moss voice agents. Mint LiveKit JWTs server-side so clients never see API secrets.
Author-email: Moss Team <support@moss.dev>
License-Expression: MIT
Project-URL: Homepage, https://github.com/InferEdge-Inc/moss
Project-URL: Repository, https://github.com/InferEdge-Inc/moss
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE.txt
Requires-Dist: httpx<1.0.0,>=0.27.0
Requires-Dist: livekit-api<2.0.0,>=1.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
Requires-Dist: black>=22.0; extra == "dev"
Dynamic: license-file

# moss-voice-server

Backend token generation for Moss voice agents. Mints short-lived LiveKit
participant JWTs server-side so your API secrets never reach the browser.

A Node.js equivalent is available as [`@moss-tools/voice-server`](https://www.npmjs.com/package/@moss-tools/voice-server) on npm.

## Why

Browser clients shouldn't hold LiveKit API secrets. The recommended flow:

1. Your frontend asks **your backend** for a join token.
2. Your backend calls `MossVoiceServer.create_participant_token(...)` and
   returns the signed JWT + server URL.
3. The frontend connects to LiveKit with that token.

This package handles steps 1–2 from Python (FastAPI, Flask, Django, etc.).

## Install

```bash
pip install moss-voice-server
```

Python 3.10+.

## Usage — async (FastAPI, asyncio)

```python
import os
from contextlib import asynccontextmanager
from fastapi import FastAPI
from moss_voice_server import MossVoiceServer, ParticipantInfo


@asynccontextmanager
async def lifespan(app: FastAPI):
    app.state.voice_server = await MossVoiceServer.create(
        project_id=os.environ["MOSS_PROJECT_ID"],
        project_key=os.environ["MOSS_PROJECT_KEY"],
        voice_agent_id=os.environ["MOSS_VOICE_AGENT_ID"],
    )
    yield


app = FastAPI(lifespan=lifespan)


@app.post("/voice/token")
async def issue_token(user_id: str, room: str) -> dict[str, str]:
    server: MossVoiceServer = app.state.voice_server
    token = server.create_participant_token(
        ParticipantInfo(identity=user_id),
        room_name=room,
    )
    return {"token": token, "url": server.get_server_url()}
```

## Usage — sync (Flask, Django)

```python
import os
from moss_voice_server import MossVoiceServerSync, ParticipantInfo

voice_server = MossVoiceServerSync.create(
    project_id=os.environ["MOSS_PROJECT_ID"],
    project_key=os.environ["MOSS_PROJECT_KEY"],
    voice_agent_id=os.environ["MOSS_VOICE_AGENT_ID"],
)

token = voice_server.create_participant_token(
    ParticipantInfo(identity="user_123", name="Jane"),
    room_name="support_456",
)
```

## API

### `MossVoiceServer.create(project_id, project_key, voice_agent_id, api_url=...)`

Async factory. Fetches credentials from the Moss API and returns an initialized
instance. Raises ``RuntimeError`` on network failure or invalid credentials.

### `MossVoiceServerSync.create(...)`

Same arguments, sync. Use in Flask/Django.

### `server.create_participant_token(participant, room_name, agent_name=None) -> str`

Mint a signed JWT for ``participant`` to join ``room_name``. Token TTL is
15 minutes. Pass ``agent_name`` only when you need to override LiveKit's
default dispatch rules.

### `server.get_server_url() -> str`

LiveKit WebSocket URL the client should connect to.

### `server.get_agent_name() -> str`

Configured voice agent name.

### `ParticipantInfo(identity, name=None, metadata=None, attributes=None)`

Identity payload for the token. ``identity`` is required and must be unique
per user.

## Environment variables

The library accepts credentials as arguments. By convention, applications
typically read them from these env vars:

```bash
MOSS_PROJECT_ID=<your project id>
MOSS_PROJECT_KEY=<your project key>
MOSS_VOICE_AGENT_ID=<your voice agent id>
```

## Development

```bash
pip install -e ".[dev]"
pytest
```

## License

MIT
