aillom-vox-client 1.0.0

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.
Files changed (45) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +272 -0
  3. package/dist/AillomVox.d.ts +36 -0
  4. package/dist/AillomVox.js +152 -0
  5. package/dist/index.d.ts +2 -0
  6. package/dist/index.js +18 -0
  7. package/dist/types.d.ts +36 -0
  8. package/dist/types.js +2 -0
  9. package/docs/ASTERISK.md +411 -0
  10. package/docs/PROTOCOL.md +156 -0
  11. package/docs/PROVIDERS.md +40 -0
  12. package/docs/TOOLS.md +314 -0
  13. package/docs/TROUBLESHOOTING.md +86 -0
  14. package/docs/VOICES.md +219 -0
  15. package/docs/providers/AILLOMVOX.md +185 -0
  16. package/docs/providers/AWS.md +32 -0
  17. package/docs/providers/GEMINI.md +33 -0
  18. package/docs/providers/GROK.md +25 -0
  19. package/docs/providers/OPENAI.md +39 -0
  20. package/docs/providers/QWEN.md +27 -0
  21. package/docs/providers/ULTRAVOX.md +29 -0
  22. package/examples/01-basic/app.js +196 -0
  23. package/examples/01-basic/index.html +27 -0
  24. package/examples/02-advanced-dashboard/app.js +465 -0
  25. package/examples/02-advanced-dashboard/index.html +200 -0
  26. package/examples/02-advanced-dashboard/style.css +501 -0
  27. package/examples/03-smart-home/index.html +377 -0
  28. package/examples/04-customer-support/index.html +474 -0
  29. package/examples/sdk-usage.ts +44 -0
  30. package/integrations/n8n-nodes-aillomvox/README.md +56 -0
  31. package/integrations/n8n-nodes-aillomvox/credentials/AillomVoxApi.credentials.ts +29 -0
  32. package/integrations/n8n-nodes-aillomvox/dist/credentials/AillomVoxApi.credentials.js +30 -0
  33. package/integrations/n8n-nodes-aillomvox/dist/nodes/AillomVox/AillomVox.node.js +219 -0
  34. package/integrations/n8n-nodes-aillomvox/dist/nodes/AillomVox/aillomvox.svg +6 -0
  35. package/integrations/n8n-nodes-aillomvox/gulpfile.js +10 -0
  36. package/integrations/n8n-nodes-aillomvox/nodes/AillomVox/AillomVox.node.ts +229 -0
  37. package/integrations/n8n-nodes-aillomvox/nodes/AillomVox/aillomvox.svg +6 -0
  38. package/integrations/n8n-nodes-aillomvox/package-lock.json +11741 -0
  39. package/integrations/n8n-nodes-aillomvox/package.json +56 -0
  40. package/integrations/n8n-nodes-aillomvox/tsconfig.json +32 -0
  41. package/package.json +55 -0
  42. package/src/AillomVox.ts +169 -0
  43. package/src/index.ts +2 -0
  44. package/src/types.ts +50 -0
  45. package/tsconfig.json +23 -0
package/docs/TOOLS.md ADDED
@@ -0,0 +1,314 @@
1
+ # 🛠️ Client Tools Guide
2
+
3
+ Client Tools allow the AI to interact with your application's UI. When the AI determines that a specific action is needed (like ending a call or showing an alert), it calls a tool, and your application executes it.
4
+
5
+ ---
6
+
7
+ ## 📋 Architecture
8
+
9
+ ### CLIENT-side Tools
10
+ Executed **locally** in your application (browser, mobile app, CLI):
11
+ - Control UI elements
12
+ - Handle navigation
13
+ - Manage connections
14
+ - Display notifications
15
+
16
+ ### SERVER-side Tools
17
+ Executed on **AillomVox servers** (you cannot register these):
18
+ - Access databases
19
+ - Call external APIs
20
+ - Query RAG systems
21
+ - Server-side logic
22
+
23
+ > **Rule**: If it controls **your app's UI**, it's a CLIENT tool. If it accesses **server resources**, it's a SERVER tool.
24
+
25
+ ---
26
+
27
+ ## 🚀 Quick Start
28
+
29
+ ### 1. Register Tools
30
+
31
+ ```javascript
32
+ await client.connect({
33
+ provider: 'gemini',
34
+ voice: 'Puck',
35
+ tools: [
36
+ {
37
+ name: 'hangup',
38
+ description: 'End the current call',
39
+ parameters: {
40
+ type: 'object',
41
+ properties: {},
42
+ required: []
43
+ }
44
+ }
45
+ ]
46
+ });
47
+ ```
48
+
49
+ ### 2. Handle Tool Calls
50
+
51
+ ```javascript
52
+ client.on('tool_call', async (tool) => {
53
+ console.log(`AI requested: ${tool.name}`, tool.args);
54
+
55
+ if (tool.name === 'hangup') {
56
+ await client.disconnect();
57
+ return 'Call ended successfully';
58
+ }
59
+ });
60
+ ```
61
+
62
+ ### 3. Send Result Back
63
+
64
+ The return value from your handler is automatically sent back to the AI, allowing it to continue the conversation.
65
+
66
+ ---
67
+
68
+ ## 📦 Tool Definition Format
69
+
70
+ ```javascript
71
+ {
72
+ name: 'tool_name', // Unique identifier (match in handler)
73
+ description: 'What it does', // AI uses this to decide when to call
74
+ parameters: { // JSON Schema for arguments
75
+ type: 'object',
76
+ properties: {
77
+ arg1: {
78
+ type: 'string',
79
+ description: 'First argument'
80
+ },
81
+ arg2: {
82
+ type: 'number',
83
+ description: 'Second argument'
84
+ }
85
+ },
86
+ required: ['arg1'] // Mandatory arguments
87
+ }
88
+ }
89
+ ```
90
+
91
+ ---
92
+
93
+ ## 🎯 Common Tools
94
+
95
+ ### 1. Hangup (End Call)
96
+
97
+ ```javascript
98
+ {
99
+ name: 'hangup',
100
+ description: 'End the call when user says goodbye',
101
+ parameters: { type: 'object', properties: {} }
102
+ }
103
+
104
+ // Handler
105
+ client.on('tool_call', async (tool) => {
106
+ if (tool.name === 'hangup') {
107
+ await client.disconnect();
108
+ return 'Call ended';
109
+ }
110
+ });
111
+ ```
112
+
113
+ ### 2. Show Alert
114
+
115
+ ```javascript
116
+ {
117
+ name: 'show_alert',
118
+ description: 'Display important message to user',
119
+ parameters: {
120
+ type: 'object',
121
+ properties: {
122
+ message: {
123
+ type: 'string',
124
+ description: 'Alert message'
125
+ },
126
+ severity: {
127
+ type: 'string',
128
+ enum: ['info', 'warning', 'error'],
129
+ description: 'Alert type'
130
+ }
131
+ },
132
+ required: ['message']
133
+ }
134
+ }
135
+
136
+ // Handler
137
+ client.on('tool_call', async (tool) => {
138
+ if (tool.name === 'show_alert') {
139
+ alert(`[${tool.args.severity}] ${tool.args.message}`);
140
+ return 'Alert displayed';
141
+ }
142
+ });
143
+ ```
144
+
145
+ ### 3. Navigate to Page
146
+
147
+ ```javascript
148
+ {
149
+ name: 'navigate_to_page',
150
+ description: 'Navigate user to a specific page',
151
+ parameters: {
152
+ type: 'object',
153
+ properties: {
154
+ url: {
155
+ type: 'string',
156
+ description: 'Target URL'
157
+ }
158
+ },
159
+ required: ['url']
160
+ }
161
+ }
162
+
163
+ // Handler
164
+ client.on('tool_call', async (tool) => {
165
+ if (tool.name === 'navigate_to_page') {
166
+ window.location.href = tool.args.url;
167
+ return 'Navigating';
168
+ }
169
+ });
170
+ ```
171
+
172
+ ### 4. Update UI Element
173
+
174
+ ```javascript
175
+ {
176
+ name: 'highlight_element',
177
+ description: 'Highlight UI element to draw user attention',
178
+ parameters: {
179
+ type: 'object',
180
+ properties: {
181
+ element_id: { type: 'string', description: 'DOM element ID' },
182
+ color: { type: 'string', description: 'Highlight color' }
183
+ },
184
+ required: ['element_id']
185
+ }
186
+ }
187
+
188
+ // Handler
189
+ client.on('tool_call', async (tool) => {
190
+ if (tool.name === 'highlight_element') {
191
+ const el = document.getElementById(tool.args.element_id);
192
+ el.style.border = `3px solid ${tool.args.color || 'yellow'}`;
193
+ return 'Element highlighted';
194
+ }
195
+ });
196
+ ```
197
+
198
+ ---
199
+
200
+ ## 🧪 Testing Tools
201
+
202
+ ### Manual Testing
203
+
204
+ ```javascript
205
+ // Simulate AI calling a tool
206
+ client.emit('tool_call', {
207
+ name: 'show_alert',
208
+ args: { message: 'Test alert', severity: 'info' }
209
+ });
210
+ ```
211
+
212
+ ### Debugging
213
+
214
+ ```javascript
215
+ client.on('tool_call', async (tool) => {
216
+ console.log('=== TOOL CALL ===');
217
+ console.log('Name:', tool.name);
218
+ console.log('Args:', tool.args);
219
+ console.log('ID:', tool.call_id);
220
+
221
+ // Your handler logic here
222
+ const result = await handleTool(tool);
223
+
224
+ console.log('Result:', result);
225
+ return result;
226
+ });
227
+ ```
228
+
229
+ ---
230
+
231
+ ## ⚠️ Best Practices
232
+
233
+ ### 1. Clear Descriptions
234
+ ```javascript
235
+ // ❌ Bad
236
+ description: 'Does something'
237
+
238
+ // ✅ Good
239
+ description: 'End the call when user says goodbye or wants to finish'
240
+ ```
241
+
242
+ ### 2. Validate Arguments
243
+ ```javascript
244
+ client.on('tool_call', async (tool) => {
245
+ if (tool.name === 'navigate_to_page') {
246
+ // Validate
247
+ if (!tool.args.url || !tool.args.url.startsWith('http')) {
248
+ return 'Error: Invalid URL';
249
+ }
250
+
251
+ window.location.href = tool.args.url;
252
+ return 'Navigating to ' + tool.args.url;
253
+ }
254
+ });
255
+ ```
256
+
257
+ ### 3. Return Meaningful Results
258
+ ```javascript
259
+ // ❌ Bad
260
+ return 'ok';
261
+
262
+ // ✅ Good
263
+ return 'Alert shown successfully with message: "' + tool.args.message + '"';
264
+ ```
265
+
266
+ This helps the AI understand what happened and continue the conversation naturally.
267
+
268
+ ---
269
+
270
+ ## 🔒 Security
271
+
272
+ ### Client Tools are Safe
273
+ - Executed in **your app**, not on our servers
274
+ - You have **full control** over what they do
275
+ - No sensitive data is sent to the server
276
+
277
+ ### Never Trust User Input
278
+ ```javascript
279
+ // ❌ Dangerous
280
+ client.on('tool_call', async (tool) => {
281
+ eval(tool.args.code); // NEVER DO THIS
282
+ });
283
+
284
+ // ✅ Safe
285
+ client.on('tool_call', async (tool) => {
286
+ const allowedUrls = ['https://myapp.com/dashboard', 'https://myapp.com/profile'];
287
+ if (allowedUrls.includes(tool.args.url)) {
288
+ window.location.href = tool.args.url;
289
+ }
290
+ });
291
+ ```
292
+
293
+ ---
294
+
295
+ ## 📚 Examples
296
+
297
+ See complete working examples in:
298
+ - [Browser Example](../examples/browser/) - Full UI with tools
299
+ - [Node.js CLI](../examples/nodejs/) - CLI bot with hangup
300
+ - [Python Example](../examples/python/) - Python integration
301
+
302
+ ---
303
+
304
+ ## 💡 Tips
305
+
306
+ 1. **Start Simple**: Begin with just `hangup`, then add more
307
+ 2. **Test Locally**: Use manual emit to test without calling the AI
308
+ 3. **Return Clear Messages**: AI uses return value to continue conversation
309
+ 4. **Validate Everything**: Never trust arguments blindly
310
+ 5. **Keep it Fast**: Tool execution should be instant (< 100ms)
311
+
312
+ ---
313
+
314
+ Happy building! 🎉
@@ -0,0 +1,86 @@
1
+ # Troubleshooting Guide
2
+
3
+ Common issues and how to resolve them when using AillomVox.
4
+
5
+ ---
6
+
7
+ ## Authentication Errors
8
+
9
+ ### `401 Unauthorized` / `error: unauthorized`
10
+ - **Cause**: API Key is missing, invalid, or expired.
11
+ - **Fix**: Check that you're sending `apikey` in your config handshake. Ensure you are copying the key exactly as provided in your dashboard.
12
+
13
+ ### `error: insufficient_balance`
14
+ - **Cause**: Your account balance is $0.00 or below.
15
+ - **Fix**: Add credits via the [Billing page](https://vox.aillom.com/billing).
16
+
17
+ ---
18
+
19
+ ## Connection Issues
20
+
21
+ ### `Connection Refused` / `Socket Hang Up`
22
+ - **Cause**: Server unreachable or firewall blocking outbound port 443 (WSS).
23
+ - **Fix**: Ensure you can reach `https://vox.aillom.com/health`. Check your network settings.
24
+
25
+ ### `1008 Policy Violation`
26
+ - **Cause**: Sent binary data before the config handshake.
27
+ - **Fix**: The **first message** must be a JSON config. Wait for it to be acknowledged before sending audio.
28
+
29
+ ### `1006 Abnormal Closure`
30
+ - **Cause**: Generic WebSocket error. Often caused by:
31
+ - Sending malformed JSON
32
+ - Sending audio in wrong format (e.g., MP3 instead of PCM)
33
+ - Network timeout (keep-alive)
34
+
35
+ ---
36
+
37
+ ## Audio Problems
38
+
39
+ ### "Static" or "Noise" instead of Voice
40
+ - **Cause**: Wrong encoding or endianness.
41
+ - **Fix**: AillomVox expects **PCM 16-bit Signed Little Endian**.
42
+ - If you send Float32 (Web Audio API default), you get static. Convert to Int16 first.
43
+ - If you send Big Endian, you get static. Use `true` for little-endian in `DataView.setInt16()`.
44
+
45
+ ### High Latency
46
+ - **Cause**: Buffering too much audio before sending.
47
+ - **Fix**: Send small chunks (20ms–50ms) as soon as recorded. Do not batch 1 second of audio.
48
+
49
+ ### "Choppy" Audio Output
50
+ - **Cause**: Network jitter or empty buffer underruns.
51
+ - **Fix**: Implement a jitter buffer — wait for 2–3 chunks before starting playback.
52
+
53
+ ### No Audio Received
54
+ - **Cause**: `sample_rate` mismatch or missing `system_prompt`.
55
+ - **Fix**: Ensure `sample_rate` is `8000`, `16000`, or `24000`. The `system_prompt` field is mandatory.
56
+
57
+ ---
58
+
59
+ ## Tool Call Issues
60
+
61
+ ### AI Hangs After Tool Call
62
+ - **Cause**: Missing `tool_result` response.
63
+ - **Fix**: Always respond to `tool_call` events with a `tool_result` within 15 seconds:
64
+ ```javascript
65
+ ws.send(JSON.stringify({
66
+ type: "tool_result",
67
+ call_id: msg.call_id,
68
+ result: "Success"
69
+ }));
70
+ ```
71
+
72
+ ### Tools Not Triggering
73
+ - **Cause**: Vague tool descriptions or wrong provider.
74
+ - **Fix**: Use clear, specific descriptions. Note: Qwen does not support tools — use AillomVox, OpenAI, Gemini, or AWS.
75
+
76
+ ---
77
+
78
+ ## Session Issues
79
+
80
+ ### `max_duration_reached`
81
+ - **Cause**: Session exceeded the `max_duration` limit.
82
+ - **Fix**: Increase `max_duration` (up to 3600) or handle the farewell message gracefully.
83
+
84
+ ### Multiple Connections Rejected
85
+ - **Cause**: Exceeded concurrent connection limit (3 per user, 2 per API key).
86
+ - **Fix**: Close unused connections before opening new ones.
package/docs/VOICES.md ADDED
@@ -0,0 +1,219 @@
1
+ # Voice Catalog
2
+
3
+ Complete reference of all available voices across providers.
4
+
5
+ ---
6
+
7
+ ## AillomVox (Inworld TTS 1.5)
8
+
9
+ **65 voices** verified via the Inworld TTS API. Each voice has a native language but supports multilingual synthesis across all 15 languages.
10
+
11
+ ### English (25 voices)
12
+
13
+ **Male (14)**
14
+
15
+ | Voice | Style |
16
+ | :--- | :--- |
17
+ | **Edward** | Fast-talking, emphatic (default EN) |
18
+ | **Dennis** | Smooth, calm, friendly |
19
+ | **Alex** | Energetic, expressive |
20
+ | **Craig** | Older British, refined |
21
+ | **Mark** | Energetic, rapid delivery |
22
+ | **Ronald** | Confident British, deep |
23
+ | **Shaun** | Friendly, dynamic |
24
+ | **Theodore** | Gravelly, time-worn |
25
+ | **Timothy** | Lively, upbeat American |
26
+ | **Carter** | Mature radio announcer |
27
+ | **Blake** | Rich, intimate |
28
+ | **Clive** | British, calm, cordial |
29
+ | **Dominus** | Robotic, deep, menacing |
30
+ | **Hades** | Commanding, gruff |
31
+
32
+ **Female (11)**
33
+
34
+ | Voice | Style |
35
+ | :--- | :--- |
36
+ | **Ashley** | Warm, natural |
37
+ | **Deborah** | Gentle, elegant |
38
+ | **Elizabeth** | Professional, narrations |
39
+ | **Julia** | Quirky, high-pitched |
40
+ | **Olivia** | Young British, upbeat |
41
+ | **Priya** | Even-toned, Indian accent |
42
+ | **Sarah** | Fast-talking, curious |
43
+ | **Wendy** | Posh British |
44
+ | **Luna** | Calm, relaxing |
45
+ | **Hana** | Bright, expressive |
46
+ | **Pixie** | High-pitched, childlike |
47
+
48
+ ### Portuguese (2)
49
+
50
+ | Voice | Gender | Style |
51
+ | :--- | :--- | :--- |
52
+ | **Heitor** | Male | Composed, neutral (default PT) |
53
+ | **Maitê** | Female | Middle-aged, professional |
54
+
55
+ ### Spanish (4)
56
+
57
+ | Voice | Gender | Style |
58
+ | :--- | :--- | :--- |
59
+ | **Diego** | Male | Soothing, gentle (default ES) |
60
+ | **Miguel** | Male | Calm, storytelling |
61
+ | **Rafael** | Male | Deep, composed |
62
+ | **Lupita** | Female | Vibrant, energetic |
63
+
64
+ ### French (4)
65
+
66
+ | Voice | Gender | Style |
67
+ | :--- | :--- | :--- |
68
+ | **Alain** | Male | Deep, smooth |
69
+ | **Mathieu** | Male | Nasal quality |
70
+ | **Étienne** | Male | Calm, young adult |
71
+ | **Hélène** | Female | Musical, graceful |
72
+
73
+ ### German (2)
74
+
75
+ | Voice | Gender | Style |
76
+ | :--- | :--- | :--- |
77
+ | **Josef** | Male | Articulate, announcer |
78
+ | **Johanna** | Female | Calm, low, smoky |
79
+
80
+ ### Italian (2)
81
+
82
+ | Voice | Gender | Style |
83
+ | :--- | :--- | :--- |
84
+ | **Gianni** | Male | Deep, smooth, rapid |
85
+ | **Orietta** | Female | Calm, soothing |
86
+
87
+ ### Chinese (4)
88
+
89
+ | Voice | Gender | Style |
90
+ | :--- | :--- | :--- |
91
+ | **Yichen** | Male | Calm, flat |
92
+ | **Xiaoyin** | Female | Youthful, sweet |
93
+ | **Xinyi** | Female | Neutral, narrations |
94
+ | **Jing** | Female | Energetic, fast |
95
+
96
+ ### Dutch (4)
97
+
98
+ | Voice | Gender | Style |
99
+ | :--- | :--- | :--- |
100
+ | **Erik** | Male | Older, weathered |
101
+ | **Lennart** | Male | Confident, calm |
102
+ | **Katrien** | Female | Expressive |
103
+ | **Lore** | Female | Clear, calm |
104
+
105
+ ### Japanese (2)
106
+
107
+ | Voice | Gender | Style |
108
+ | :--- | :--- | :--- |
109
+ | **Satoshi** | Male | Dramatic, expressive |
110
+ | **Asuka** | Female | Friendly, young |
111
+
112
+ ### Korean (4)
113
+
114
+ | Voice | Gender | Style |
115
+ | :--- | :--- | :--- |
116
+ | **Hyunwoo** | Male | Young adult |
117
+ | **Seojun** | Male | Deep, mature |
118
+ | **Minji** | Female | Energetic, friendly |
119
+ | **Yoona** | Female | Gentle, soothing |
120
+
121
+ ### Polish (2)
122
+
123
+ | Voice | Gender | Style |
124
+ | :--- | :--- | :--- |
125
+ | **Szymon** | Male | Warm, friendly |
126
+ | **Wojciech** | Male | Middle-aged |
127
+
128
+ ### Russian (4)
129
+
130
+ | Voice | Gender | Style |
131
+ | :--- | :--- | :--- |
132
+ | **Dmitry** | Male | Deep, commanding |
133
+ | **Nikolai** | Male | Deep, theatrical |
134
+ | **Svetlana** | Female | Soft, high-pitched |
135
+ | **Elena** | Female | Clear, smooth |
136
+
137
+ ### Hindi (2)
138
+
139
+ | Voice | Gender | Style |
140
+ | :--- | :--- | :--- |
141
+ | **Manoj** | Male | Professional |
142
+ | **Riya** | Female | Polished, approachable |
143
+
144
+ ### Hebrew (2)
145
+
146
+ | Voice | Gender | Style |
147
+ | :--- | :--- | :--- |
148
+ | **Oren** | Male | Steady |
149
+ | **Yael** | Female | Mid-range, narrations |
150
+
151
+ ### Arabic (2)
152
+
153
+ | Voice | Gender | Style |
154
+ | :--- | :--- | :--- |
155
+ | **Omar** | Male | Bright, confident |
156
+ | **Nour** | Female | Polished, friendly |
157
+
158
+ ---
159
+
160
+ ## OpenAI Realtime
161
+
162
+ | Voice | Style |
163
+ | :--- | :--- |
164
+ | **alloy** | Neutral, balanced |
165
+ | **ash** | Warm, conversational |
166
+ | **coral** | Clear, professional |
167
+ | **echo** | Smooth, calm |
168
+ | **sage** | Wise, measured |
169
+ | **shimmer** | Bright, energetic |
170
+
171
+ ---
172
+
173
+ ## Google Gemini
174
+
175
+ | Voice | Style |
176
+ | :--- | :--- |
177
+ | **Puck** | Soft, higher pitch |
178
+ | **Kore** | Soft, higher pitch |
179
+ | **Charon** | Deep, confident |
180
+ | **Fenrir** | Deep, confident |
181
+ | **Aoede** | Confident, higher pitch |
182
+
183
+ ---
184
+
185
+ ## AWS Bedrock (Nova Sonic)
186
+
187
+ | Voice | Style |
188
+ | :--- | :--- |
189
+ | **matthew** | Male, neutral |
190
+ | **ruth** | Female, professional |
191
+ | **tiffany** | Female, warm |
192
+
193
+ ---
194
+
195
+ ## Ultravox
196
+
197
+ | Voice | Style |
198
+ | :--- | :--- |
199
+ | **Mark** | Male |
200
+ | **Jessica** | Female |
201
+
202
+ ---
203
+
204
+ ## Language Support
205
+
206
+ ### AillomVox Languages (15)
207
+
208
+ ```
209
+ en, pt, es, fr, de, it, ja, zh, ko, hi, ar, ru, pl, nl, he
210
+ ```
211
+
212
+ ### Language Defaults (AillomVox)
213
+
214
+ | Code | Language | Default Voice |
215
+ | :--- | :--- | :--- |
216
+ | `en-US` | English | Edward |
217
+ | `pt-BR` | Portuguese (Brazil) | Heitor |
218
+ | `es-ES` | Spanish | Diego |
219
+ | All others | — | Edward |