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
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "n8n-nodes-aillomvox",
3
+ "version": "0.1.0",
4
+ "description": "Official AillomVox node for n8n. Easy integration with Voice Gateway, Recordings Management, and AI Providers.",
5
+ "keywords": [
6
+ "n8n-community-node-package",
7
+ "aillomvox",
8
+ "voice",
9
+ "ai",
10
+ "gateway"
11
+ ],
12
+ "license": "MIT",
13
+ "homepage": "https://vox.aillom.com",
14
+ "author": {
15
+ "name": "Aillom AI",
16
+ "email": "dev@aillom.com"
17
+ },
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "git+https://github.com/aillom/aillom-vox-client.git"
21
+ },
22
+ "main": "index.js",
23
+ "scripts": {
24
+ "build": "tsc && gulp build:icons",
25
+ "dev": "tsc --watch",
26
+ "format": "prettier nodes/**/*.ts --write",
27
+ "lint": "eslint nodes package.json",
28
+ "lintfix": "eslint nodes package.json --fix",
29
+ "prepublishOnly": "npm run build"
30
+ },
31
+ "files": [
32
+ "dist"
33
+ ],
34
+ "n8n": {
35
+ "nodes": [
36
+ "dist/nodes/AillomVox/AillomVox.node.js"
37
+ ],
38
+ "credentials": [
39
+ "dist/credentials/AillomVoxApi.credentials.js"
40
+ ]
41
+ },
42
+ "devDependencies": {
43
+ "@types/express": "^4.17.6",
44
+ "@types/request-promise-native": "~1.0.15",
45
+ "@typescript-eslint/parser": "~5.45",
46
+ "eslint-plugin-n8n-nodes-base": "^1.11.0",
47
+ "gulp": "^4.0.2",
48
+ "n8n-core": "^1.122.14",
49
+ "n8n-workflow": "*",
50
+ "prettier": "^2.7.1",
51
+ "typescript": "^5.0.0"
52
+ },
53
+ "peerDependencies": {
54
+ "n8n-workflow": "*"
55
+ }
56
+ }
@@ -0,0 +1,32 @@
1
+ {
2
+ "compilerOptions": {
3
+ "rootDirs": [
4
+ "nodes",
5
+ "credentials"
6
+ ],
7
+ "outDir": "dist",
8
+ "target": "es2019",
9
+ "lib": [
10
+ "es2019",
11
+ "dom"
12
+ ],
13
+ "module": "commonjs",
14
+ "moduleResolution": "node",
15
+ "allowJs": true,
16
+ "checkJs": false,
17
+ "strict": false,
18
+ "noImplicitAny": false, // Relaxed for easier build in mixed envs
19
+ "esModuleInterop": true,
20
+ "resolveJsonModule": true,
21
+ "skipLibCheck": true,
22
+ "forceConsistentCasingInFileNames": true
23
+ },
24
+ "include": [
25
+ "nodes/**/*",
26
+ "credentials/**/*"
27
+ ],
28
+ "exclude": [
29
+ "node_modules",
30
+ "dist"
31
+ ]
32
+ }
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "aillom-vox-client",
3
+ "version": "1.0.0",
4
+ "description": "Enterprise-Grade Voice AI SDK for Speech-to-Speech, Audio-to-Audio, and Realtime Multimodal applications.",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "dev": "tsc --watch",
10
+ "test": "echo \"Error: no test specified\" && exit 1"
11
+ },
12
+ "dependencies": {
13
+ "isomorphic-ws": "^5.0.0",
14
+ "ws": "^8.16.0"
15
+ },
16
+ "devDependencies": {
17
+ "@types/ws": "^8.5.10",
18
+ "typescript": "^5.3.3",
19
+ "ts-node": "^10.9.2",
20
+ "@types/node": "^20.11.19"
21
+ },
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/aillom/aillom-vox-client.git"
25
+ },
26
+ "keywords": [
27
+ "voice-ai",
28
+ "speech-to-speech",
29
+ "audio-to-audio",
30
+ "realtime-api",
31
+ "websocket-client",
32
+ "openai-realtime",
33
+ "gemini-multimodal",
34
+ "low-latency",
35
+ "voice-gateway",
36
+ "sip-trunking",
37
+ "asterisk",
38
+ "inworld-ai",
39
+ "gpt-4o-realtime",
40
+ "telephony",
41
+ "ultravox",
42
+ "nova-sonic"
43
+ ],
44
+ "author": "Aillom Technologies <contato@aillom.com.br>",
45
+ "license": "ISC",
46
+ "bugs": {
47
+ "url": "https://github.com/aillom/aillom-vox-client/issues"
48
+ },
49
+ "homepage": "https://vox.aillom.com",
50
+ "devDependencies": {
51
+ "@types/node": "^25.2.2",
52
+ "ts-node": "^10.9.2",
53
+ "typescript": "^5.9.3"
54
+ }
55
+ }
@@ -0,0 +1,169 @@
1
+ import { AillomVoxConfig, TranscriptEvent, ToolCallEvent, EventHandler } from './types';
2
+ import WebSocket from 'isomorphic-ws';
3
+
4
+ export class AillomVox {
5
+ private ws: WebSocket | null = null;
6
+ private config: AillomVoxConfig;
7
+ private eventListeners: Map<string, EventHandler[]> = new Map();
8
+ private isConnected: boolean = false;
9
+ private url: string = 'wss://vox.aillom.com/ws';
10
+
11
+ constructor(config: AillomVoxConfig) {
12
+ this.config = config;
13
+ if (!this.config.apiKey) {
14
+ throw new Error('AillomVox: apiKey is required');
15
+ }
16
+ }
17
+
18
+ /**
19
+ * Connects to the AillomVox Gateway
20
+ */
21
+ public connect(): Promise<void> {
22
+ return new Promise((resolve, reject) => {
23
+ try {
24
+ this.ws = new WebSocket(this.url);
25
+ this.ws.binaryType = 'arraybuffer';
26
+
27
+ this.ws.onopen = () => {
28
+ this.isConnected = true;
29
+ this.sendConfig();
30
+ this.emit('connected', {});
31
+ resolve();
32
+ };
33
+
34
+ this.ws.onmessage = (event: WebSocket.MessageEvent) => {
35
+ this.handleMessage(event);
36
+ };
37
+
38
+ this.ws.onerror = (error: WebSocket.ErrorEvent) => {
39
+ this.emit('error', error);
40
+ if (!this.isConnected) reject(error);
41
+ };
42
+
43
+ this.ws.onclose = (event: WebSocket.CloseEvent) => {
44
+ this.isConnected = false;
45
+ this.emit('disconnected', { code: event.code, reason: event.reason });
46
+ };
47
+
48
+ } catch (err) {
49
+ reject(err);
50
+ }
51
+ });
52
+ }
53
+
54
+ /**
55
+ * Sends audio chunk (PCM 16-bit) to the AI
56
+ */
57
+ public sendAudio(chunk: ArrayBuffer | Int16Array | Buffer): void {
58
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
59
+ this.ws.send(chunk);
60
+ }
61
+
62
+ /**
63
+ * Sends a tool result back to the AI
64
+ */
65
+ public sendToolResult(callId: string, result: any): void {
66
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;
67
+ this.ws.send(JSON.stringify({
68
+ type: 'tool_result',
69
+ call_id: callId,
70
+ result: result
71
+ }));
72
+ }
73
+
74
+ /**
75
+ * Disconnects the session
76
+ */
77
+ public disconnect(): void {
78
+ if (this.ws) {
79
+ this.ws.close();
80
+ this.ws = null;
81
+ this.isConnected = false;
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Subscribes to an event
87
+ */
88
+ public on(event: 'audio', handler: (data: ArrayBuffer) => void): void;
89
+ public on(event: 'transcript', handler: (data: TranscriptEvent) => void): void;
90
+ public on(event: 'tool_call', handler: (data: ToolCallEvent) => void): void;
91
+ public on(event: 'error', handler: (error: any) => void): void;
92
+ public on(event: 'connected' | 'disconnected' | 'interruption', handler: (data: any) => void): void;
93
+ public on(event: string, handler: EventHandler): void {
94
+ if (!this.eventListeners.has(event)) {
95
+ this.eventListeners.set(event, []);
96
+ }
97
+ this.eventListeners.get(event)?.push(handler);
98
+ }
99
+
100
+ private sendConfig() {
101
+ if (!this.ws) return;
102
+
103
+ const payload = {
104
+ type: 'config',
105
+ apikey: this.config.apiKey,
106
+ provider: this.config.provider || 'aillomvox',
107
+ voice: this.config.voice || 'Edward',
108
+ language: this.config.language || 'en-US',
109
+ sample_rate: this.config.sampleRate || 16000,
110
+ system_prompt: this.config.systemPrompt,
111
+ tools: this.config.tools,
112
+ webhook_url: this.config.webhookUrl,
113
+ max_duration: this.config.maxDuration
114
+ };
115
+
116
+ if (this.config.debug) {
117
+ console.log('[AillomVox] Sending config:', JSON.stringify(payload, null, 2));
118
+ }
119
+
120
+ this.ws.send(JSON.stringify(payload));
121
+ }
122
+
123
+ private handleMessage(event: WebSocket.MessageEvent) {
124
+ const data = event.data;
125
+
126
+ // Handle Binary Audio
127
+ if (data instanceof ArrayBuffer || (typeof Buffer !== 'undefined' && Buffer.isBuffer(data))) {
128
+ this.emit('audio', data);
129
+ return;
130
+ }
131
+
132
+ // Handle JSON Control Messages
133
+ if (typeof data === 'string') {
134
+ try {
135
+ const msg = JSON.parse(data);
136
+
137
+ switch (msg.type) {
138
+ case 'transcript':
139
+ this.emit('transcript', msg);
140
+ break;
141
+ case 'tool_call':
142
+ this.emit('tool_call', msg);
143
+ break;
144
+ case 'error':
145
+ this.emit('error', msg);
146
+ break;
147
+ case 'interruption':
148
+ this.emit('interruption', {});
149
+ break;
150
+ case 'hangup':
151
+ this.disconnect();
152
+ this.emit('disconnected', { reason: 'agent_hangup' });
153
+ break;
154
+ default:
155
+ if (this.config.debug) console.log('[AillomVox] Data:', msg);
156
+ }
157
+ } catch (e) {
158
+ console.error('[AillomVox] Failed to parse message:', e);
159
+ }
160
+ }
161
+ }
162
+
163
+ private emit(event: string, data: any) {
164
+ const listeners = this.eventListeners.get(event);
165
+ if (listeners) {
166
+ listeners.forEach(handler => handler(data));
167
+ }
168
+ }
169
+ }
package/src/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './types';
2
+ export * from './AillomVox';
package/src/types.ts ADDED
@@ -0,0 +1,50 @@
1
+ export type ProviderType =
2
+ | 'aillomvox'
3
+ | 'gemini'
4
+ | 'openai'
5
+ | 'aws'
6
+ | 'qwen'
7
+ | 'grok'
8
+ | 'ultravox';
9
+
10
+ export interface MicrophoneConfig {
11
+ sampleRate?: 8000 | 16000 | 24000;
12
+ inputSampleRate?: number;
13
+ }
14
+
15
+ export interface ClientTool {
16
+ name: string;
17
+ description: string;
18
+ parameters: Record<string, any>;
19
+ }
20
+
21
+ export interface AillomVoxConfig {
22
+ apiKey: string;
23
+ provider?: ProviderType;
24
+ voice?: string;
25
+ language?: string;
26
+ systemPrompt?: string;
27
+ sampleRate?: 8000 | 16000 | 24000;
28
+ debug?: boolean;
29
+ tools?: ClientTool[];
30
+ webhookUrl?: string;
31
+ maxDuration?: number;
32
+ }
33
+
34
+ export interface TranscriptEvent {
35
+ role: 'user' | 'assistant';
36
+ text: string;
37
+ final: boolean;
38
+ }
39
+
40
+ export interface ToolCallEvent {
41
+ call_id: string;
42
+ name: string;
43
+ args: any;
44
+ }
45
+
46
+ export interface AudioEvent {
47
+ buffer: ArrayBuffer;
48
+ }
49
+
50
+ export type EventHandler<T = any> = (data: T) => void;
package/tsconfig.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2020",
4
+ "module": "commonjs",
5
+ "lib": [
6
+ "es2020",
7
+ "dom"
8
+ ],
9
+ "declaration": true,
10
+ "outDir": "dist",
11
+ "strict": true,
12
+ "esModuleInterop": true,
13
+ "skipLibCheck": true,
14
+ "forceConsistentCasingInFileNames": true
15
+ },
16
+ "include": [
17
+ "src/**/*"
18
+ ],
19
+ "exclude": [
20
+ "node_modules",
21
+ "dist"
22
+ ]
23
+ }