modular-voice-agent-sdk 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 (125) hide show
  1. package/README.md +102 -0
  2. package/USAGE.md +567 -0
  3. package/dist/backends/cloud/index.d.ts +7 -0
  4. package/dist/backends/cloud/index.d.ts.map +1 -0
  5. package/dist/backends/cloud/index.js +6 -0
  6. package/dist/backends/cloud/index.js.map +1 -0
  7. package/dist/backends/cloud/llm.d.ts +22 -0
  8. package/dist/backends/cloud/llm.d.ts.map +1 -0
  9. package/dist/backends/cloud/llm.js +234 -0
  10. package/dist/backends/cloud/llm.js.map +1 -0
  11. package/dist/backends/index.d.ts +2 -0
  12. package/dist/backends/index.d.ts.map +1 -0
  13. package/dist/backends/index.js +6 -0
  14. package/dist/backends/index.js.map +1 -0
  15. package/dist/backends/native/index.d.ts +5 -0
  16. package/dist/backends/native/index.d.ts.map +1 -0
  17. package/dist/backends/native/index.js +6 -0
  18. package/dist/backends/native/index.js.map +1 -0
  19. package/dist/backends/native/llm.d.ts +71 -0
  20. package/dist/backends/native/llm.d.ts.map +1 -0
  21. package/dist/backends/native/llm.js +435 -0
  22. package/dist/backends/native/llm.js.map +1 -0
  23. package/dist/backends/native/stt.d.ts +15 -0
  24. package/dist/backends/native/stt.d.ts.map +1 -0
  25. package/dist/backends/native/stt.js +94 -0
  26. package/dist/backends/native/stt.js.map +1 -0
  27. package/dist/backends/native/tts.d.ts +21 -0
  28. package/dist/backends/native/tts.d.ts.map +1 -0
  29. package/dist/backends/native/tts.js +105 -0
  30. package/dist/backends/native/tts.js.map +1 -0
  31. package/dist/backends/transformers/index.d.ts +4 -0
  32. package/dist/backends/transformers/index.d.ts.map +1 -0
  33. package/dist/backends/transformers/index.js +4 -0
  34. package/dist/backends/transformers/index.js.map +1 -0
  35. package/dist/backends/transformers/llm.d.ts +29 -0
  36. package/dist/backends/transformers/llm.d.ts.map +1 -0
  37. package/dist/backends/transformers/llm.js +117 -0
  38. package/dist/backends/transformers/llm.js.map +1 -0
  39. package/dist/backends/transformers/stt.d.ts +17 -0
  40. package/dist/backends/transformers/stt.d.ts.map +1 -0
  41. package/dist/backends/transformers/stt.js +43 -0
  42. package/dist/backends/transformers/stt.js.map +1 -0
  43. package/dist/backends/transformers/tts.d.ts +17 -0
  44. package/dist/backends/transformers/tts.d.ts.map +1 -0
  45. package/dist/backends/transformers/tts.js +40 -0
  46. package/dist/backends/transformers/tts.js.map +1 -0
  47. package/dist/cache.d.ts +37 -0
  48. package/dist/cache.d.ts.map +1 -0
  49. package/dist/cache.js +49 -0
  50. package/dist/cache.js.map +1 -0
  51. package/dist/cli.d.ts +11 -0
  52. package/dist/cli.d.ts.map +1 -0
  53. package/dist/cli.js +392 -0
  54. package/dist/cli.js.map +1 -0
  55. package/dist/client/audio-player.d.ts +45 -0
  56. package/dist/client/audio-player.d.ts.map +1 -0
  57. package/dist/client/audio-player.js +90 -0
  58. package/dist/client/audio-player.js.map +1 -0
  59. package/dist/client/audio-recorder.d.ts +42 -0
  60. package/dist/client/audio-recorder.d.ts.map +1 -0
  61. package/dist/client/audio-recorder.js +128 -0
  62. package/dist/client/audio-recorder.js.map +1 -0
  63. package/dist/client/index.d.ts +34 -0
  64. package/dist/client/index.d.ts.map +1 -0
  65. package/dist/client/index.js +33 -0
  66. package/dist/client/index.js.map +1 -0
  67. package/dist/client/protocol.d.ts +80 -0
  68. package/dist/client/protocol.d.ts.map +1 -0
  69. package/dist/client/protocol.js +29 -0
  70. package/dist/client/protocol.js.map +1 -0
  71. package/dist/client/voice-client.d.ts +249 -0
  72. package/dist/client/voice-client.d.ts.map +1 -0
  73. package/dist/client/voice-client.js +826 -0
  74. package/dist/client/voice-client.js.map +1 -0
  75. package/dist/client/web-speech-stt.d.ts +65 -0
  76. package/dist/client/web-speech-stt.d.ts.map +1 -0
  77. package/dist/client/web-speech-stt.js +122 -0
  78. package/dist/client/web-speech-stt.js.map +1 -0
  79. package/dist/client/web-speech-tts.d.ts +59 -0
  80. package/dist/client/web-speech-tts.d.ts.map +1 -0
  81. package/dist/client/web-speech-tts.js +145 -0
  82. package/dist/client/web-speech-tts.js.map +1 -0
  83. package/dist/index.d.ts +10 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +13 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/server/encoding.d.ts +18 -0
  88. package/dist/server/encoding.d.ts.map +1 -0
  89. package/dist/server/encoding.js +41 -0
  90. package/dist/server/encoding.js.map +1 -0
  91. package/dist/server/handler.d.ts +86 -0
  92. package/dist/server/handler.d.ts.map +1 -0
  93. package/dist/server/handler.js +224 -0
  94. package/dist/server/handler.js.map +1 -0
  95. package/dist/server/index.d.ts +31 -0
  96. package/dist/server/index.d.ts.map +1 -0
  97. package/dist/server/index.js +32 -0
  98. package/dist/server/index.js.map +1 -0
  99. package/dist/services/function-service.d.ts +17 -0
  100. package/dist/services/function-service.d.ts.map +1 -0
  101. package/dist/services/function-service.js +82 -0
  102. package/dist/services/function-service.js.map +1 -0
  103. package/dist/services/index.d.ts +4 -0
  104. package/dist/services/index.d.ts.map +1 -0
  105. package/dist/services/index.js +3 -0
  106. package/dist/services/index.js.map +1 -0
  107. package/dist/services/llm-logger.d.ts +136 -0
  108. package/dist/services/llm-logger.d.ts.map +1 -0
  109. package/dist/services/llm-logger.js +275 -0
  110. package/dist/services/llm-logger.js.map +1 -0
  111. package/dist/services/text-normalizer.d.ts +17 -0
  112. package/dist/services/text-normalizer.d.ts.map +1 -0
  113. package/dist/services/text-normalizer.js +100 -0
  114. package/dist/services/text-normalizer.js.map +1 -0
  115. package/dist/types.d.ts +195 -0
  116. package/dist/types.d.ts.map +1 -0
  117. package/dist/types.js +48 -0
  118. package/dist/types.js.map +1 -0
  119. package/dist/voice-pipeline.d.ts +125 -0
  120. package/dist/voice-pipeline.d.ts.map +1 -0
  121. package/dist/voice-pipeline.js +390 -0
  122. package/dist/voice-pipeline.js.map +1 -0
  123. package/package.json +96 -0
  124. package/scripts/setup-binaries.sh +159 -0
  125. package/scripts/setup.sh +201 -0
@@ -0,0 +1,275 @@
1
+ /**
2
+ * LLM Logger Service
3
+ *
4
+ * Provides structured, backend-agnostic logging for LLM interactions.
5
+ * Backends emit structured events, the logger handles all formatting.
6
+ */
7
+ // ============================================================================
8
+ // Logger Implementation
9
+ // ============================================================================
10
+ /**
11
+ * Formats and displays structured LLM log events
12
+ * All formatting (colors, icons, layout) is centralized here
13
+ */
14
+ export class LLMLogger {
15
+ static COLORS = {
16
+ reset: '\x1b[0m',
17
+ dim: '\x1b[2m',
18
+ cyan: '\x1b[36m',
19
+ yellow: '\x1b[33m',
20
+ green: '\x1b[32m',
21
+ magenta: '\x1b[35m',
22
+ blue: '\x1b[34m',
23
+ red: '\x1b[31m',
24
+ };
25
+ static ICONS = {
26
+ system: '⚙',
27
+ user: '👤',
28
+ toolCall: '🔧',
29
+ toolResult: '✓',
30
+ response: '💬',
31
+ error: '✗',
32
+ arrow: '→',
33
+ };
34
+ enabled;
35
+ constructor(options = {}) {
36
+ this.enabled = options.enabled ?? true;
37
+ }
38
+ /**
39
+ * Log a structured event
40
+ */
41
+ log(event) {
42
+ if (!this.enabled)
43
+ return;
44
+ const { COLORS: C, ICONS } = LLMLogger;
45
+ switch (event.type) {
46
+ case 'new_conversation':
47
+ console.log(`\n${C.cyan}━━━━━━━━━━━━━━ NEW CONVERSATION ━━━━━━━━━━━━━━${C.reset}`);
48
+ break;
49
+ case 'llm_call_start':
50
+ console.log(`\n${C.dim}┌───────────────────────────────────────────────${C.reset}`);
51
+ if (event.isFirstCall) {
52
+ console.log(`${C.dim}│${C.reset} ${C.cyan}LLM${C.reset}`);
53
+ }
54
+ else {
55
+ console.log(`${C.dim}│${C.reset} ${C.cyan}LLM${C.reset} ${C.dim}(continued)${C.reset}`);
56
+ }
57
+ console.log(`${C.dim}├───────────────────────────────────────────────${C.reset}`);
58
+ break;
59
+ case 'llm_call_output':
60
+ console.log(`${C.dim}├─────────────────── ${C.reset}${C.cyan}output${C.reset} ${C.dim}─────────────────${C.reset}`);
61
+ break;
62
+ case 'llm_call_end':
63
+ console.log(`${C.dim}└───────────────────────────────────────────────${C.reset}\n`);
64
+ break;
65
+ case 'system': {
66
+ const lines = event.content.split('\n');
67
+ console.log(`${C.dim}│${C.reset} ${ICONS.system} ${C.magenta}SYSTEM${C.reset}`);
68
+ for (const line of lines) {
69
+ console.log(`${C.dim}│${C.reset} ${C.dim}${line}${C.reset}`);
70
+ }
71
+ break;
72
+ }
73
+ case 'user':
74
+ console.log(`${C.dim}│${C.reset} ${ICONS.user} ${C.yellow}USER${C.reset}: ${event.content}`);
75
+ break;
76
+ case 'tool_call': {
77
+ const argsStr = this.formatArgs(event.args);
78
+ console.log(`${C.dim}│${C.reset} ${ICONS.arrow} ${ICONS.toolCall} ${C.blue}${event.name}${C.reset}(${C.dim}${argsStr}${C.reset})`);
79
+ break;
80
+ }
81
+ case 'tool_result':
82
+ console.log(`${C.dim}│${C.reset} ${ICONS.toolResult} ${C.green}RESULT${C.reset}: ${C.dim}${event.content}${C.reset}`);
83
+ break;
84
+ case 'assistant':
85
+ console.log(`${C.dim}│${C.reset} ${ICONS.response} ${C.green}ASSISTANT${C.reset}: ${event.content}`);
86
+ break;
87
+ case 'response':
88
+ console.log(`${C.dim}│${C.reset} ${ICONS.arrow} ${ICONS.response} ${event.content}`);
89
+ break;
90
+ case 'error':
91
+ console.log(`${C.dim}│${C.reset} ${ICONS.error} ${C.red}ERROR${C.reset}: ${event.message}`);
92
+ break;
93
+ }
94
+ }
95
+ /**
96
+ * Format tool arguments for display
97
+ */
98
+ formatArgs(args) {
99
+ const entries = Object.entries(args);
100
+ if (entries.length === 0)
101
+ return '';
102
+ return entries.map(([k, v]) => `${k}=${JSON.stringify(v)}`).join(', ');
103
+ }
104
+ /**
105
+ * Enable or disable logging
106
+ */
107
+ setEnabled(enabled) {
108
+ this.enabled = enabled;
109
+ }
110
+ }
111
+ /**
112
+ * Tracks conversation state and emits structured events for new messages.
113
+ * Works with Message[] arrays directly - used by all backends.
114
+ * Supports multiple simultaneous conversations via conversation IDs.
115
+ */
116
+ export class LLMConversationTracker {
117
+ conversations = new Map();
118
+ logger;
119
+ constructor(logger) {
120
+ this.logger = logger;
121
+ }
122
+ /**
123
+ * Get or create state for a conversation
124
+ */
125
+ getState(conversationId) {
126
+ let state = this.conversations.get(conversationId);
127
+ if (!state) {
128
+ // New conversation!
129
+ state = { loggedMessages: [], callCount: 0 };
130
+ this.conversations.set(conversationId, state);
131
+ this.logger.log({ type: 'new_conversation' });
132
+ }
133
+ return state;
134
+ }
135
+ /**
136
+ * Process messages array and emit events for new messages
137
+ */
138
+ logInput(conversationId, messages) {
139
+ const state = this.getState(conversationId);
140
+ // Find which messages are new
141
+ const newMessages = [];
142
+ for (let i = 0; i < messages.length; i++) {
143
+ const msgKey = this.messageKey(messages[i]);
144
+ if (i >= state.loggedMessages.length || state.loggedMessages[i] !== msgKey) {
145
+ newMessages.push(messages[i]);
146
+ state.loggedMessages[i] = msgKey;
147
+ }
148
+ }
149
+ state.loggedMessages.length = messages.length;
150
+ const isFirstCall = state.callCount === 0;
151
+ state.callCount++;
152
+ // Emit events
153
+ this.logger.log({ type: 'llm_call_start', isFirstCall });
154
+ for (const msg of newMessages) {
155
+ this.emitMessageEvent(msg);
156
+ }
157
+ }
158
+ /**
159
+ * Log an LLM response (text content and/or tool calls)
160
+ */
161
+ logOutput(conversationId, content, toolCalls) {
162
+ // Ensure conversation exists (in case logOutput is called without logInput)
163
+ this.getState(conversationId);
164
+ this.logger.log({ type: 'llm_call_output' });
165
+ if (toolCalls && toolCalls.length > 0) {
166
+ for (const tc of toolCalls) {
167
+ this.logger.log({ type: 'tool_call', name: tc.name, args: tc.arguments });
168
+ }
169
+ }
170
+ else if (content) {
171
+ this.logger.log({ type: 'response', content });
172
+ }
173
+ this.logger.log({ type: 'llm_call_end' });
174
+ }
175
+ /**
176
+ * Log a raw response string (for backends that return tool calls as formatted strings)
177
+ * Parses <tool_call> tags and handles accordingly
178
+ */
179
+ logRawOutput(conversationId, response) {
180
+ const toolCall = this.parseToolCall(response);
181
+ if (toolCall) {
182
+ this.logOutput(conversationId, '', [toolCall]);
183
+ }
184
+ else {
185
+ this.logOutput(conversationId, response);
186
+ }
187
+ }
188
+ /**
189
+ * Remove a conversation's tracking state (called when session ends)
190
+ */
191
+ removeConversation(conversationId) {
192
+ this.conversations.delete(conversationId);
193
+ }
194
+ /**
195
+ * Reset tracker state for a specific conversation
196
+ */
197
+ resetConversation(conversationId) {
198
+ this.conversations.delete(conversationId);
199
+ }
200
+ /**
201
+ * Reset all tracker state (e.g., for testing)
202
+ */
203
+ reset() {
204
+ this.conversations.clear();
205
+ }
206
+ /**
207
+ * Generate a unique key for a message (for deduplication)
208
+ */
209
+ messageKey(msg) {
210
+ if (msg.toolCalls && msg.toolCalls.length > 0) {
211
+ return `${msg.role}:toolcalls:${JSON.stringify(msg.toolCalls)}`;
212
+ }
213
+ return `${msg.role}:${msg.content}`;
214
+ }
215
+ /**
216
+ * Emit the appropriate log event for a message
217
+ */
218
+ emitMessageEvent(msg) {
219
+ switch (msg.role) {
220
+ case 'system':
221
+ this.logger.log({ type: 'system', content: msg.content });
222
+ break;
223
+ case 'user':
224
+ this.logger.log({ type: 'user', content: msg.content });
225
+ break;
226
+ case 'assistant':
227
+ // Skip assistant messages in input - they're our previous outputs
228
+ // We don't need to show them again
229
+ break;
230
+ case 'tool':
231
+ this.logger.log({ type: 'tool_result', content: msg.content });
232
+ break;
233
+ }
234
+ }
235
+ /**
236
+ * Parse tool call from SmolLM2/HuggingFace format: <tool_call>[...]</tool_call>
237
+ */
238
+ parseToolCall(content) {
239
+ const match = content.match(/<tool_call>\s*([\s\S]*?)\s*<\/tool_call>/);
240
+ if (!match)
241
+ return null;
242
+ try {
243
+ const parsed = JSON.parse(match[1].trim());
244
+ const call = Array.isArray(parsed) ? parsed[0] : parsed;
245
+ return { name: call.name, arguments: call.arguments || {} };
246
+ }
247
+ catch {
248
+ return null;
249
+ }
250
+ }
251
+ }
252
+ // ============================================================================
253
+ // Singleton instance for convenience
254
+ // ============================================================================
255
+ let defaultLogger = null;
256
+ let defaultTracker = null;
257
+ /**
258
+ * Get the default logger instance (creates one if needed)
259
+ */
260
+ export function getDefaultLogger() {
261
+ if (!defaultLogger) {
262
+ defaultLogger = new LLMLogger();
263
+ }
264
+ return defaultLogger;
265
+ }
266
+ /**
267
+ * Get the default tracker instance (creates one if needed)
268
+ */
269
+ export function getDefaultTracker() {
270
+ if (!defaultTracker) {
271
+ defaultTracker = new LLMConversationTracker(getDefaultLogger());
272
+ }
273
+ return defaultTracker;
274
+ }
275
+ //# sourceMappingURL=llm-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm-logger.js","sourceRoot":"","sources":["../../src/services/llm-logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Text Normalizer
3
+ * Converts text to TTS-friendly format
4
+ */
5
+ export declare class TextNormalizer {
6
+ normalize(text: string): string;
7
+ private normalizeTimes;
8
+ private normalizeDecimalNumbers;
9
+ private normalizeOrdinals;
10
+ private normalizeCurrency;
11
+ private normalizePercentages;
12
+ private normalizeYears;
13
+ private normalizeStandaloneNumbers;
14
+ private normalizeSymbols;
15
+ private normalizePunctuation;
16
+ }
17
+ //# sourceMappingURL=text-normalizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-normalizer.d.ts","sourceRoot":"","sources":["../../src/services/text-normalizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,qBAAa,cAAc;IACzB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAe/B,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,uBAAuB;IAQ/B,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,iBAAiB;IAczB,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,cAAc;IAkBtB,OAAO,CAAC,0BAA0B;IAIlC,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,oBAAoB;CAU7B"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Text Normalizer
3
+ * Converts text to TTS-friendly format
4
+ */
5
+ import numberToWords from 'number-to-words';
6
+ const { toWords, toWordsOrdinal } = numberToWords;
7
+ export class TextNormalizer {
8
+ normalize(text) {
9
+ let result = text;
10
+ result = this.normalizeTimes(result);
11
+ result = this.normalizeDecimalNumbers(result);
12
+ result = this.normalizeOrdinals(result);
13
+ result = this.normalizeCurrency(result);
14
+ result = this.normalizePercentages(result);
15
+ result = this.normalizeYears(result);
16
+ result = this.normalizeStandaloneNumbers(result);
17
+ result = this.normalizeSymbols(result);
18
+ result = this.normalizePunctuation(result);
19
+ result = result.replace(/\s+/g, ' ').trim();
20
+ return result;
21
+ }
22
+ normalizeTimes(text) {
23
+ return text.replace(/\b(\d{1,2}):(\d{2})\s*(AM|PM|am|pm)?\b/g, (_, hourStr, minuteStr, period) => {
24
+ const hour = parseInt(hourStr, 10);
25
+ const minute = parseInt(minuteStr, 10);
26
+ const hourWord = toWords(hour);
27
+ let minuteWord = minute === 0 ? '' : minute < 10 ? 'oh ' + toWords(minute) : toWords(minute);
28
+ const periodWord = period ? ' ' + period.toUpperCase().split('').join(' ') : '';
29
+ return (hourWord + ' ' + minuteWord + periodWord).trim();
30
+ });
31
+ }
32
+ normalizeDecimalNumbers(text) {
33
+ return text.replace(/(\d+)\.(\d+)/g, (_, whole, decimal) => {
34
+ const wholeWords = toWords(parseInt(whole, 10));
35
+ const decimalDigits = decimal.split('').map((d) => toWords(parseInt(d, 10))).join(' ');
36
+ return `${wholeWords} point ${decimalDigits}`;
37
+ });
38
+ }
39
+ normalizeOrdinals(text) {
40
+ return text.replace(/(\d+)(st|nd|rd|th)\b/gi, (_, num) => toWordsOrdinal(parseInt(num, 10)));
41
+ }
42
+ normalizeCurrency(text) {
43
+ let result = text.replace(/\$(\d+)\.(\d{2})\b/g, (_, dollars, cents) => {
44
+ const d = parseInt(dollars, 10);
45
+ const c = parseInt(cents, 10);
46
+ let phrase = toWords(d) + (d === 1 ? ' dollar' : ' dollars');
47
+ if (c > 0)
48
+ phrase += ' and ' + toWords(c) + (c === 1 ? ' cent' : ' cents');
49
+ return phrase;
50
+ });
51
+ return result.replace(/\$(\d+)\b/g, (_, dollars) => {
52
+ const d = parseInt(dollars, 10);
53
+ return toWords(d) + (d === 1 ? ' dollar' : ' dollars');
54
+ });
55
+ }
56
+ normalizePercentages(text) {
57
+ return text.replace(/(\d+)%/g, (_, num) => toWords(parseInt(num, 10)) + ' percent');
58
+ }
59
+ normalizeYears(text) {
60
+ return text.replace(/\b(1\d{3}|2\d{3})\b/g, (match) => {
61
+ const year = parseInt(match, 10);
62
+ if (year >= 2000 && year < 2010)
63
+ return 'two thousand ' + (year === 2000 ? '' : toWords(year - 2000));
64
+ if (year >= 2010 && year < 3000) {
65
+ const first = Math.floor(year / 100);
66
+ const last = year % 100;
67
+ return toWords(first) + ' ' + (last < 10 ? 'oh ' + toWords(last) : toWords(last));
68
+ }
69
+ if (year >= 1000 && year < 2000) {
70
+ const first = Math.floor(year / 100);
71
+ const last = year % 100;
72
+ return toWords(first) + ' ' + (last === 0 ? 'hundred' : last < 10 ? 'oh ' + toWords(last) : toWords(last));
73
+ }
74
+ return toWords(year);
75
+ });
76
+ }
77
+ normalizeStandaloneNumbers(text) {
78
+ return text.replace(/\b(\d+)\b/g, (match) => toWords(parseInt(match, 10)));
79
+ }
80
+ normalizeSymbols(text) {
81
+ return text
82
+ .replace(/&/g, ' and ')
83
+ .replace(/@/g, ' at ')
84
+ .replace(/\+/g, ' plus ')
85
+ .replace(/=/g, ' equals ')
86
+ .replace(/#(\w+)/g, 'hashtag $1')
87
+ .replace(/#/g, ' number ');
88
+ }
89
+ normalizePunctuation(text) {
90
+ return text
91
+ .replace(/\.\.\./g, ', ')
92
+ .replace(/[;:]/g, ', ')
93
+ .replace(/[()[\]{}]/g, ' ')
94
+ .replace(/[""«»]/g, '')
95
+ .replace(/(?<!\w)[''']|['''](?!\w)/g, '')
96
+ .replace(/[*_~`]/g, '')
97
+ .replace(/-/g, ' ');
98
+ }
99
+ }
100
+ //# sourceMappingURL=text-normalizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-normalizer.js","sourceRoot":"","sources":["../../src/services/text-normalizer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Voice Pipeline Library - Type Definitions
3
+ */
4
+ /**
5
+ * JSON Schema for tool parameters
6
+ */
7
+ export interface ToolParameterSchema {
8
+ type: 'object';
9
+ properties: Record<string, {
10
+ type: string;
11
+ description?: string;
12
+ enum?: string[];
13
+ }>;
14
+ required?: string[];
15
+ }
16
+ /**
17
+ * Tool definition - describes a callable function
18
+ */
19
+ export interface ToolDefinition {
20
+ name: string;
21
+ description: string;
22
+ parameters: ToolParameterSchema;
23
+ }
24
+ /**
25
+ * Registered tool with execute function
26
+ */
27
+ export interface Tool extends ToolDefinition {
28
+ execute: (args: Record<string, unknown>) => Promise<unknown> | unknown;
29
+ }
30
+ /**
31
+ * Tool call request from LLM
32
+ */
33
+ export interface ToolCall {
34
+ id: string;
35
+ name: string;
36
+ arguments: Record<string, unknown>;
37
+ }
38
+ /**
39
+ * Result of executing a tool
40
+ */
41
+ export interface ToolResult {
42
+ toolCallId: string;
43
+ result: unknown;
44
+ error?: string;
45
+ }
46
+ export type MessageRole = 'system' | 'user' | 'assistant' | 'tool';
47
+ export interface BaseMessage {
48
+ role: MessageRole;
49
+ content: string;
50
+ }
51
+ export interface ToolMessage extends BaseMessage {
52
+ role: 'tool';
53
+ toolCallId: string;
54
+ }
55
+ export interface AssistantMessage extends BaseMessage {
56
+ role: 'assistant';
57
+ toolCalls?: ToolCall[];
58
+ }
59
+ export type Message = BaseMessage | ToolMessage | AssistantMessage;
60
+ export interface AudioResult {
61
+ audio: Float32Array;
62
+ sampleRate: number;
63
+ }
64
+ /**
65
+ * AudioPlayable - Uniform interface for TTS output
66
+ * Allows backends to either provide raw audio data OR direct playback
67
+ */
68
+ export interface AudioPlayable {
69
+ /** Get raw audio data (null if backend doesn't support raw audio, e.g., Web Speech) */
70
+ getRawAudio(): AudioResult | null;
71
+ /** Play the audio - works uniformly across all backends */
72
+ play(): Promise<void>;
73
+ /** Stop playback */
74
+ stop(): void;
75
+ }
76
+ /**
77
+ * BufferedAudioPlayable - For backends that produce raw audio data
78
+ * Used by: Native TTS, Transformers TTS
79
+ */
80
+ export declare class BufferedAudioPlayable implements AudioPlayable {
81
+ private audio;
82
+ private sampleRate;
83
+ private audioContext;
84
+ private sourceNode;
85
+ constructor(audio: Float32Array, sampleRate: number);
86
+ getRawAudio(): AudioResult;
87
+ play(): Promise<void>;
88
+ stop(): void;
89
+ }
90
+ export interface ProgressInfo {
91
+ status: 'initiate' | 'download' | 'progress' | 'done' | 'ready';
92
+ file?: string;
93
+ progress?: number;
94
+ loaded?: number;
95
+ total?: number;
96
+ }
97
+ export type ProgressCallback = (progress: ProgressInfo) => void;
98
+ export interface STTPipeline {
99
+ initialize(onProgress?: ProgressCallback): Promise<void>;
100
+ transcribe(audio: Float32Array): Promise<string>;
101
+ isReady(): boolean;
102
+ }
103
+ /**
104
+ * LLM generation options
105
+ */
106
+ export interface LLMGenerateOptions {
107
+ /** Tools available for the LLM to call */
108
+ tools?: ToolDefinition[];
109
+ /** Callback for streaming tokens */
110
+ onToken?: (token: string) => void;
111
+ /** Callback when tool calls are detected */
112
+ onToolCall?: (toolCall: ToolCall) => void;
113
+ /** Conversation ID for tracking/logging (supports multiple simultaneous conversations) */
114
+ conversationId?: string;
115
+ }
116
+ /**
117
+ * LLM generation result
118
+ */
119
+ export interface LLMGenerateResult {
120
+ /** Text content of the response */
121
+ content: string;
122
+ /** Tool calls requested by the LLM (if any) */
123
+ toolCalls?: ToolCall[];
124
+ /** Whether the response is complete or waiting for tool results */
125
+ finishReason: 'stop' | 'tool_calls';
126
+ }
127
+ export interface LLMPipeline {
128
+ initialize(onProgress?: ProgressCallback): Promise<void>;
129
+ /**
130
+ * Generate a response from the LLM
131
+ * @param messages - Conversation history
132
+ * @param options - Generation options including tools and callbacks
133
+ * @returns Generation result with content and optional tool calls
134
+ */
135
+ generate(messages: Message[], options?: LLMGenerateOptions): Promise<LLMGenerateResult>;
136
+ /** @deprecated Use generate() with options.onToken instead */
137
+ generateLegacy?(messages: Message[], onToken: (token: string) => void): Promise<string>;
138
+ isReady(): boolean;
139
+ /** Whether this backend supports native tool calling */
140
+ supportsTools?(): boolean;
141
+ }
142
+ export interface TTSPipeline {
143
+ initialize(onProgress?: ProgressCallback): Promise<void>;
144
+ synthesize(text: string): Promise<AudioPlayable>;
145
+ isReady(): boolean;
146
+ }
147
+ export interface TransformersSTTConfig {
148
+ model: string;
149
+ dtype: string;
150
+ language?: string;
151
+ device?: 'webgpu' | 'cpu';
152
+ }
153
+ export interface TransformersLLMConfig {
154
+ model: string;
155
+ dtype: string;
156
+ maxNewTokens: number;
157
+ temperature: number;
158
+ device?: 'webgpu' | 'cpu';
159
+ }
160
+ export interface TransformersTTSConfig {
161
+ model: string;
162
+ dtype: string;
163
+ speakerEmbeddings: string;
164
+ device?: 'webgpu' | 'cpu';
165
+ }
166
+ export interface NativeSTTConfig {
167
+ binaryPath: string;
168
+ modelPath: string;
169
+ language: string;
170
+ }
171
+ export interface NativeLLMConfig {
172
+ binaryPath: string;
173
+ modelPath: string;
174
+ maxNewTokens: number;
175
+ temperature: number;
176
+ gpuLayers?: number;
177
+ }
178
+ export interface NativeTTSConfig {
179
+ binaryPath: string;
180
+ modelPath: string;
181
+ }
182
+ export interface SherpaOnnxTTSConfig {
183
+ binaryPath: string;
184
+ modelDir: string;
185
+ speakerId?: number;
186
+ speedScale?: number;
187
+ }
188
+ export interface CloudLLMConfig {
189
+ baseUrl: string;
190
+ apiKey?: string;
191
+ model: string;
192
+ maxTokens?: number;
193
+ temperature?: number;
194
+ }
195
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Voice Pipeline Library - Type Definitions
3
+ */
4
+ /**
5
+ * BufferedAudioPlayable - For backends that produce raw audio data
6
+ * Used by: Native TTS, Transformers TTS
7
+ */
8
+ export class BufferedAudioPlayable {
9
+ audio;
10
+ sampleRate;
11
+ audioContext = null;
12
+ sourceNode = null;
13
+ constructor(audio, sampleRate) {
14
+ this.audio = audio;
15
+ this.sampleRate = sampleRate;
16
+ }
17
+ getRawAudio() {
18
+ return { audio: this.audio, sampleRate: this.sampleRate };
19
+ }
20
+ async play() {
21
+ if (this.audio.length === 0)
22
+ return;
23
+ // Create AudioContext on demand (handles browser autoplay policies)
24
+ if (!this.audioContext) {
25
+ this.audioContext = new AudioContext({ sampleRate: this.sampleRate });
26
+ }
27
+ // Resume if suspended (browser autoplay policy)
28
+ if (this.audioContext.state === 'suspended') {
29
+ await this.audioContext.resume();
30
+ }
31
+ const audioBuffer = this.audioContext.createBuffer(1, this.audio.length, this.sampleRate);
32
+ // Copy data to channel (create a standard Float32Array to satisfy TS)
33
+ const channelData = audioBuffer.getChannelData(0);
34
+ channelData.set(this.audio);
35
+ this.sourceNode = this.audioContext.createBufferSource();
36
+ this.sourceNode.buffer = audioBuffer;
37
+ this.sourceNode.connect(this.audioContext.destination);
38
+ return new Promise((resolve) => {
39
+ this.sourceNode.onended = () => resolve();
40
+ this.sourceNode.start();
41
+ });
42
+ }
43
+ stop() {
44
+ this.sourceNode?.stop();
45
+ this.sourceNode = null;
46
+ }
47
+ }
48
+ //# sourceMappingURL=types.js.map