@moss-tools/voice-server 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/README.md +130 -0
- package/dist/MossVoiceServer.d.ts +84 -0
- package/dist/MossVoiceServer.js +151 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +50 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to @moss-tools/voice-server will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [1.0.0-beta.1] - 2026-02-11
|
|
6
|
+
|
|
7
|
+
Initial beta release.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- `MossVoiceServer` class for managing voice agent connections
|
|
11
|
+
- `MossVoiceServer.create()` - Fetch and initialize credentials from Moss API
|
|
12
|
+
- `voiceServer.getServerUrl()` - Get voice agent server URL
|
|
13
|
+
- `voiceServer.createParticipantToken()` - Generate participant tokens
|
|
14
|
+
- `voiceServer.getAgentName()` - Get configured agent name
|
|
15
|
+
- Automatic credential caching
|
|
16
|
+
- Full TypeScript support with JSDoc
|
|
17
|
+
|
|
18
|
+
[1.0.0-beta.1]: https://github.com/InferEdge-Inc/moss/releases/tag/voice-server-v1.0.0-beta.1
|
package/README.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# @moss-tools/voice-server
|
|
2
|
+
|
|
3
|
+
Optimized server-side utilities for LiveKit-based Moss voice agents. Handles secure token generation and connection management.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Token generation** - Create participant tokens with optimized permissions
|
|
8
|
+
- **Clean class-based API** - Simple, intuitive interface
|
|
9
|
+
- **Type-safe** - Full TypeScript support with detailed JSDoc comments
|
|
10
|
+
|
|
11
|
+
## Requirements
|
|
12
|
+
|
|
13
|
+
- Node.js 18.0.0 or higher
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @moss-tools/voice-server
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { MossVoiceServer } from "@moss-tools/voice-server";
|
|
25
|
+
|
|
26
|
+
// Create and initialize (call once at app startup)
|
|
27
|
+
const voiceServer = await MossVoiceServer.create({
|
|
28
|
+
projectId: process.env.MOSS_PROJECT_ID!,
|
|
29
|
+
projectKey: process.env.MOSS_PROJECT_KEY!,
|
|
30
|
+
voiceAgentId: process.env.MOSS_VOICE_AGENT_ID!,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Get voice agent server URL for clients
|
|
34
|
+
const serverUrl = voiceServer.getServerUrl();
|
|
35
|
+
|
|
36
|
+
// Create participant tokens
|
|
37
|
+
const token = await voiceServer.createParticipantToken(
|
|
38
|
+
{ identity: "user_123", name: "John Doe" },
|
|
39
|
+
"support_room_456"
|
|
40
|
+
);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The MossVoiceServer class securely fetches and caches your voice agent credentials, then uses them to generate participant tokens.
|
|
44
|
+
|
|
45
|
+
## API
|
|
46
|
+
|
|
47
|
+
### `MossVoiceServer.create(config): Promise<MossVoiceServer>`
|
|
48
|
+
|
|
49
|
+
Create and initialize a MossVoiceServer instance by fetching credentials from Moss API.
|
|
50
|
+
|
|
51
|
+
**Parameters:**
|
|
52
|
+
- `config.projectId` - Your Moss project ID
|
|
53
|
+
- `config.projectKey` - Your Moss project key
|
|
54
|
+
- `config.voiceAgentId` - Voice agent ID to use
|
|
55
|
+
|
|
56
|
+
**Returns:** Initialized `MossVoiceServer` instance
|
|
57
|
+
|
|
58
|
+
**Example:**
|
|
59
|
+
```ts
|
|
60
|
+
const voiceServer = await MossVoiceServer.create({
|
|
61
|
+
projectId: "your-project-id",
|
|
62
|
+
projectKey: "your-project-key",
|
|
63
|
+
voiceAgentId: "your-voice-agent-id",
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### `voiceServer.getServerUrl(): string`
|
|
68
|
+
|
|
69
|
+
Get the voice agent server URL for client connections.
|
|
70
|
+
|
|
71
|
+
**Returns:** Voice agent server URL (e.g., `wss://your-agent.livekit.cloud`)
|
|
72
|
+
|
|
73
|
+
**Note:** Credentials are kept secure on the server and never exposed.
|
|
74
|
+
|
|
75
|
+
### `voiceServer.createParticipantToken(userInfo, roomName, agentName?): Promise<string>`
|
|
76
|
+
|
|
77
|
+
Create and sign a participant token for joining a voice session.
|
|
78
|
+
|
|
79
|
+
**Parameters:**
|
|
80
|
+
- `userInfo` - User identity and name
|
|
81
|
+
- `identity` - Unique user identifier
|
|
82
|
+
- `name` - Display name for the participant
|
|
83
|
+
- `roomName` - Room name to join
|
|
84
|
+
- `agentName` - (Optional) Override default voice agent name
|
|
85
|
+
|
|
86
|
+
**Returns:** Signed JWT token valid for 15 minutes
|
|
87
|
+
|
|
88
|
+
**Example:**
|
|
89
|
+
```ts
|
|
90
|
+
const token = await voiceServer.createParticipantToken(
|
|
91
|
+
{ identity: "user_123", name: "John Doe" },
|
|
92
|
+
"support_room_456"
|
|
93
|
+
);
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### `voiceServer.getAgentName(): string`
|
|
97
|
+
|
|
98
|
+
Get the configured voice agent name.
|
|
99
|
+
|
|
100
|
+
**Returns:** Voice agent name
|
|
101
|
+
|
|
102
|
+
## Environment Variables
|
|
103
|
+
|
|
104
|
+
Configure using environment variables:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
MOSS_PROJECT_ID=your-project-id
|
|
108
|
+
MOSS_PROJECT_KEY=your-project-key
|
|
109
|
+
MOSS_VOICE_AGENT_ID=your-voice-agent-id
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Then in your code:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
const voiceServer = await MossVoiceServer.create({
|
|
116
|
+
projectId: process.env.MOSS_PROJECT_ID!,
|
|
117
|
+
projectKey: process.env.MOSS_PROJECT_KEY!,
|
|
118
|
+
voiceAgentId: process.env.MOSS_VOICE_AGENT_ID!,
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Development
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
npm install
|
|
126
|
+
npm run build
|
|
127
|
+
npm test
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Build output is emitted to `dist/`.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { type AccessTokenOptions } from "livekit-server-sdk";
|
|
2
|
+
type MossVoiceServerConfig = {
|
|
3
|
+
projectId: string;
|
|
4
|
+
projectKey: string;
|
|
5
|
+
voiceAgentId: string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Voice server client for managing voice agent connections and tokens.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const voiceServer = await MossVoiceServer.create({
|
|
13
|
+
* projectId: process.env.MOSS_PROJECT_ID!,
|
|
14
|
+
* projectKey: process.env.MOSS_PROJECT_KEY!,
|
|
15
|
+
* voiceAgentId: process.env.MOSS_VOICE_AGENT_ID!,
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* const url = voiceServer.getServerUrl();
|
|
19
|
+
* const token = await voiceServer.createParticipantToken(
|
|
20
|
+
* { identity: "user_123", name: "John" },
|
|
21
|
+
* "room_name"
|
|
22
|
+
* );
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare class MossVoiceServer {
|
|
26
|
+
private config;
|
|
27
|
+
private credentials;
|
|
28
|
+
private constructor();
|
|
29
|
+
/**
|
|
30
|
+
* Create and initialize a MossVoiceServer instance.
|
|
31
|
+
*
|
|
32
|
+
* @param config - Configuration object
|
|
33
|
+
* @param config.projectId - Moss project ID
|
|
34
|
+
* @param config.projectKey - Moss project key
|
|
35
|
+
* @param config.voiceAgentId - Voice agent ID to use
|
|
36
|
+
* @returns Initialized MossVoiceServer instance
|
|
37
|
+
*
|
|
38
|
+
* @throws Error if credentials cannot be fetched
|
|
39
|
+
*/
|
|
40
|
+
static create(config: MossVoiceServerConfig): Promise<MossVoiceServer>;
|
|
41
|
+
/**
|
|
42
|
+
* Initialize by fetching credentials from the Moss API.
|
|
43
|
+
* Called automatically by MossVoiceServer.create().
|
|
44
|
+
*/
|
|
45
|
+
private initialize;
|
|
46
|
+
/**
|
|
47
|
+
* Get the voice agent server URL for client connections.
|
|
48
|
+
*
|
|
49
|
+
* @returns Voice agent server URL (e.g., "wss://your-agent.livekit.cloud")
|
|
50
|
+
* @throws Error if not initialized
|
|
51
|
+
*/
|
|
52
|
+
getServerUrl(): string;
|
|
53
|
+
/**
|
|
54
|
+
* Create a participant token for joining a voice session.
|
|
55
|
+
*
|
|
56
|
+
* @param userInfo - LiveKit AccessTokenOptions (identity, name, metadata, etc.)
|
|
57
|
+
* @param roomName - Room name to join
|
|
58
|
+
* @param agentName - (Optional) Override default voice agent name
|
|
59
|
+
* @returns Signed JWT token valid for 15 minutes
|
|
60
|
+
*
|
|
61
|
+
* @throws Error if not initialized
|
|
62
|
+
*
|
|
63
|
+
* @remarks
|
|
64
|
+
* Token TTL is automatically set to 15 minutes. If userInfo.ttl is provided, it will be overridden.
|
|
65
|
+
* Commonly used userInfo fields: identity (required), name, metadata.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* const token = await voiceServer.createParticipantToken(
|
|
70
|
+
* { identity: "user_123", name: "John Doe" },
|
|
71
|
+
* "support_room_456"
|
|
72
|
+
* );
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
createParticipantToken(userInfo: AccessTokenOptions, roomName: string, agentName?: string): Promise<string>;
|
|
76
|
+
/**
|
|
77
|
+
* Get the voice agent name from credentials.
|
|
78
|
+
*
|
|
79
|
+
* @returns Voice agent name
|
|
80
|
+
* @throws Error if not initialized
|
|
81
|
+
*/
|
|
82
|
+
getAgentName(): string;
|
|
83
|
+
}
|
|
84
|
+
export {};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { AccessToken, RoomConfiguration, } from "livekit-server-sdk";
|
|
2
|
+
const VOICE_AGENT_API_URL = "https://service.usemoss.dev/api/voice-agent-deploy/get-voice-agent";
|
|
3
|
+
/**
|
|
4
|
+
* Voice server client for managing voice agent connections and tokens.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const voiceServer = await MossVoiceServer.create({
|
|
9
|
+
* projectId: process.env.MOSS_PROJECT_ID!,
|
|
10
|
+
* projectKey: process.env.MOSS_PROJECT_KEY!,
|
|
11
|
+
* voiceAgentId: process.env.MOSS_VOICE_AGENT_ID!,
|
|
12
|
+
* });
|
|
13
|
+
*
|
|
14
|
+
* const url = voiceServer.getServerUrl();
|
|
15
|
+
* const token = await voiceServer.createParticipantToken(
|
|
16
|
+
* { identity: "user_123", name: "John" },
|
|
17
|
+
* "room_name"
|
|
18
|
+
* );
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export class MossVoiceServer {
|
|
22
|
+
config;
|
|
23
|
+
credentials = null;
|
|
24
|
+
constructor(config) {
|
|
25
|
+
this.config = config;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Create and initialize a MossVoiceServer instance.
|
|
29
|
+
*
|
|
30
|
+
* @param config - Configuration object
|
|
31
|
+
* @param config.projectId - Moss project ID
|
|
32
|
+
* @param config.projectKey - Moss project key
|
|
33
|
+
* @param config.voiceAgentId - Voice agent ID to use
|
|
34
|
+
* @returns Initialized MossVoiceServer instance
|
|
35
|
+
*
|
|
36
|
+
* @throws Error if credentials cannot be fetched
|
|
37
|
+
*/
|
|
38
|
+
static async create(config) {
|
|
39
|
+
const instance = new MossVoiceServer(config);
|
|
40
|
+
await instance.initialize();
|
|
41
|
+
return instance;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Initialize by fetching credentials from the Moss API.
|
|
45
|
+
* Called automatically by MossVoiceServer.create().
|
|
46
|
+
*/
|
|
47
|
+
async initialize() {
|
|
48
|
+
const { projectId, projectKey, voiceAgentId } = this.config;
|
|
49
|
+
if (!projectId || !projectKey || !voiceAgentId) {
|
|
50
|
+
throw new Error("projectId, projectKey, and voiceAgentId are required");
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const url = `${VOICE_AGENT_API_URL}?voice_agent_id=${encodeURIComponent(voiceAgentId)}`;
|
|
54
|
+
// Add 10 second timeout to prevent indefinite hangs
|
|
55
|
+
const response = await fetch(url, {
|
|
56
|
+
method: "GET",
|
|
57
|
+
headers: {
|
|
58
|
+
"X-Project-Id": projectId,
|
|
59
|
+
"X-Project-Key": projectKey,
|
|
60
|
+
},
|
|
61
|
+
signal: AbortSignal.timeout(10000),
|
|
62
|
+
});
|
|
63
|
+
if (!response.ok) {
|
|
64
|
+
const errorText = await response.text().catch(() => "Unknown error");
|
|
65
|
+
throw new Error(`Failed to fetch credentials: ${response.status} ${errorText}`);
|
|
66
|
+
}
|
|
67
|
+
this.credentials = (await response.json());
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
if (error instanceof Error) {
|
|
71
|
+
// Provide clear error message for timeout
|
|
72
|
+
if (error.name === "TimeoutError" || error.name === "AbortError") {
|
|
73
|
+
throw new Error("Failed to initialize MossVoiceServer: Request timed out after 10 seconds");
|
|
74
|
+
}
|
|
75
|
+
throw new Error(`Failed to initialize MossVoiceServer: ${error.message}`);
|
|
76
|
+
}
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get the voice agent server URL for client connections.
|
|
82
|
+
*
|
|
83
|
+
* @returns Voice agent server URL (e.g., "wss://your-agent.livekit.cloud")
|
|
84
|
+
* @throws Error if not initialized
|
|
85
|
+
*/
|
|
86
|
+
getServerUrl() {
|
|
87
|
+
if (!this.credentials) {
|
|
88
|
+
throw new Error("MossVoiceServer not initialized");
|
|
89
|
+
}
|
|
90
|
+
return this.credentials.voice_agent_url;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Create a participant token for joining a voice session.
|
|
94
|
+
*
|
|
95
|
+
* @param userInfo - LiveKit AccessTokenOptions (identity, name, metadata, etc.)
|
|
96
|
+
* @param roomName - Room name to join
|
|
97
|
+
* @param agentName - (Optional) Override default voice agent name
|
|
98
|
+
* @returns Signed JWT token valid for 15 minutes
|
|
99
|
+
*
|
|
100
|
+
* @throws Error if not initialized
|
|
101
|
+
*
|
|
102
|
+
* @remarks
|
|
103
|
+
* Token TTL is automatically set to 15 minutes. If userInfo.ttl is provided, it will be overridden.
|
|
104
|
+
* Commonly used userInfo fields: identity (required), name, metadata.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```ts
|
|
108
|
+
* const token = await voiceServer.createParticipantToken(
|
|
109
|
+
* { identity: "user_123", name: "John Doe" },
|
|
110
|
+
* "support_room_456"
|
|
111
|
+
* );
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
async createParticipantToken(userInfo, roomName, agentName) {
|
|
115
|
+
if (!this.credentials) {
|
|
116
|
+
throw new Error("MossVoiceServer not initialized");
|
|
117
|
+
}
|
|
118
|
+
const { voice_agent_api_key, voice_agent_api_secret, voice_agent_name } = this.credentials;
|
|
119
|
+
const at = new AccessToken(voice_agent_api_key, voice_agent_api_secret, {
|
|
120
|
+
...userInfo,
|
|
121
|
+
ttl: "15m",
|
|
122
|
+
});
|
|
123
|
+
const grant = {
|
|
124
|
+
room: roomName,
|
|
125
|
+
roomJoin: true,
|
|
126
|
+
canPublish: true,
|
|
127
|
+
canPublishData: true,
|
|
128
|
+
canSubscribe: true,
|
|
129
|
+
};
|
|
130
|
+
at.addGrant(grant);
|
|
131
|
+
const effectiveAgentName = agentName ?? voice_agent_name;
|
|
132
|
+
if (effectiveAgentName) {
|
|
133
|
+
at.roomConfig = new RoomConfiguration({
|
|
134
|
+
agents: [{ agentName: effectiveAgentName }],
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
return at.toJwt();
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Get the voice agent name from credentials.
|
|
141
|
+
*
|
|
142
|
+
* @returns Voice agent name
|
|
143
|
+
* @throws Error if not initialized
|
|
144
|
+
*/
|
|
145
|
+
getAgentName() {
|
|
146
|
+
if (!this.credentials) {
|
|
147
|
+
throw new Error("MossVoiceServer not initialized");
|
|
148
|
+
}
|
|
149
|
+
return this.credentials.voice_agent_name;
|
|
150
|
+
}
|
|
151
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MossVoiceServer } from "./MossVoiceServer.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MossVoiceServer } from "./MossVoiceServer.js";
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@moss-tools/voice-server",
|
|
3
|
+
"version": "1.0.0-beta.1",
|
|
4
|
+
"description": "Optimized server-side utilities for LiveKit-based Moss voice agents.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md",
|
|
17
|
+
"CHANGELOG.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc -p tsconfig.json",
|
|
21
|
+
"test": "npm run build && tsx --test test/voice-server.test.ts"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"moss",
|
|
25
|
+
"voice",
|
|
26
|
+
"agent",
|
|
27
|
+
"livekit",
|
|
28
|
+
"realtime",
|
|
29
|
+
"token",
|
|
30
|
+
"server"
|
|
31
|
+
],
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "https://github.com/InferEdge-Inc/moss.git",
|
|
35
|
+
"directory": "javascript/voice-server"
|
|
36
|
+
},
|
|
37
|
+
"author": "Moss Team",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"engines": {
|
|
40
|
+
"node": ">=18.0.0"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"livekit-server-sdk": "^2.15.0"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "^24.3.0",
|
|
47
|
+
"tsx": "^4.21.0",
|
|
48
|
+
"typescript": "^5.9.3"
|
|
49
|
+
}
|
|
50
|
+
}
|