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,435 @@
1
+ /**
2
+ * Native LLM Pipeline (llama.cpp)
3
+ * Server-only - requires native binary (llama-completion)
4
+ *
5
+ * When tools are provided, uses GBNF grammar that allows either:
6
+ * - TOOL: [{"name": "...", "arguments": {...}}] for tool invocations
7
+ * - SAY: natural language for direct responses (streamable!)
8
+ *
9
+ * This allows real token streaming for text responses while maintaining
10
+ * structured tool calling when needed.
11
+ */
12
+ import { spawn } from 'child_process';
13
+ import { existsSync, writeFileSync, unlinkSync } from 'fs';
14
+ import { tmpdir } from 'os';
15
+ import { join } from 'path';
16
+ import { LLMLogger, LLMConversationTracker } from '../../services';
17
+ export class NativeLLM {
18
+ config;
19
+ ready = false;
20
+ tracker;
21
+ constructor(config) {
22
+ this.config = config;
23
+ this.tracker = new LLMConversationTracker(new LLMLogger());
24
+ }
25
+ async initialize(_onProgress) {
26
+ console.log('Initializing native LLM (llama-completion)...');
27
+ if (!existsSync(this.config.binaryPath)) {
28
+ throw new Error(`llama-completion binary not found at: ${this.config.binaryPath}`);
29
+ }
30
+ if (!existsSync(this.config.modelPath)) {
31
+ throw new Error(`LLM model not found at: ${this.config.modelPath}`);
32
+ }
33
+ this.ready = true;
34
+ console.log(`Native LLM ready. Model: ${this.config.modelPath}`);
35
+ }
36
+ supportsTools() {
37
+ return true;
38
+ }
39
+ async generate(messages, options) {
40
+ if (!this.ready) {
41
+ throw new Error('LLM pipeline not initialized');
42
+ }
43
+ // If tools are provided, use grammar mode for guaranteed valid JSON
44
+ if (options?.tools && options.tools.length > 0) {
45
+ return this.generateWithGrammar(messages, options);
46
+ }
47
+ // No tools: regular freeform generation
48
+ return this.generateFreeform(messages, options);
49
+ }
50
+ /**
51
+ * Build the tool system prompt
52
+ */
53
+ buildToolSystemPrompt(tools) {
54
+ const toolsJson = JSON.stringify(tools.map(t => ({
55
+ type: 'function',
56
+ function: {
57
+ name: t.name,
58
+ description: t.description,
59
+ parameters: t.parameters,
60
+ },
61
+ })), null, 2);
62
+ return `
63
+ You have access to tools, but ONLY use them when explicitly needed:
64
+ <tools>${toolsJson}</tools>
65
+
66
+ IMPORTANT: Default to SAY for most interactions. Only use tools when the user EXPLICITLY asks for something the tool provides.
67
+
68
+ Response formats:
69
+ - SAY: Your natural language response — USE THIS BY DEFAULT for greetings, conversation, questions, explanations, and any response where you don't need external data.
70
+ - TOOL: [{"name": "tool_name", "arguments": {"arg1": "value1"}}] — ONLY use when the user specifically requests information that requires a tool (e.g., "what time is it?" needs get_current_time).
71
+
72
+ Examples of when NOT to use tools:
73
+ - "Hello" / "Hi" / "Hey" → just greet back with SAY:
74
+ - "How are you?" → respond naturally with SAY:
75
+ - "Tell me a joke" → respond with SAY:
76
+ - "What can you do?" → describe capabilities with SAY:`;
77
+ }
78
+ /**
79
+ * Generate with GBNF grammar constraint
80
+ * Allows either:
81
+ * - TOOL: [{...}] for tool invocations
82
+ * - SAY: text for streamable text responses
83
+ */
84
+ async generateWithGrammar(messages, options) {
85
+ const tools = options.tools ?? [];
86
+ // Build grammar that allows say OR tool_call
87
+ const grammar = this.buildToolGrammar(tools);
88
+ // Write grammar to temp file (llama-completion needs a file path)
89
+ const grammarPath = join(tmpdir(), `grammar-${Date.now()}.gbnf`);
90
+ writeFileSync(grammarPath, grammar);
91
+ try {
92
+ const prompt = this.formatChatPromptWithTools(messages, tools);
93
+ // llama-completion args for clean non-interactive output
94
+ const args = [
95
+ '-m', this.config.modelPath,
96
+ '-n', String(this.config.maxNewTokens),
97
+ '--temp', String(this.config.temperature ?? 0.7),
98
+ '--grammar-file', grammarPath,
99
+ '--no-display-prompt', // Don't echo the prompt back
100
+ '--simple-io', // Clean output without ANSI codes
101
+ '-no-cnv', // Non-conversation mode (single completion)
102
+ '-p', prompt,
103
+ ];
104
+ if (this.config.gpuLayers) {
105
+ args.push('-ngl', String(this.config.gpuLayers));
106
+ }
107
+ // Use streaming completion that handles both formats
108
+ const result = await this.runLlamaCompletionWithStreaming(args, messages, options);
109
+ return result;
110
+ }
111
+ finally {
112
+ // Clean up temp grammar file
113
+ try {
114
+ unlinkSync(grammarPath);
115
+ }
116
+ catch {
117
+ // Ignore cleanup errors
118
+ }
119
+ }
120
+ }
121
+ /**
122
+ * Parse tool call output
123
+ * TOOL: [{"name": "...", "arguments": {...}}]
124
+ */
125
+ parseToolCallOutput(output) {
126
+ // The output should already be just the JSON array (TOOL: prefix stripped)
127
+ const jsonStr = output.trim();
128
+ try {
129
+ const parsed = JSON.parse(jsonStr.trim());
130
+ // Handle array format
131
+ if (Array.isArray(parsed)) {
132
+ return parsed.filter(tc => tc && typeof tc.name === 'string');
133
+ }
134
+ // Handle single object format (legacy)
135
+ if (parsed && typeof parsed.name === 'string') {
136
+ return [parsed];
137
+ }
138
+ return null;
139
+ }
140
+ catch {
141
+ return null;
142
+ }
143
+ }
144
+ /**
145
+ * Build GBNF grammar that allows either:
146
+ * - TOOL: [{"name": "...", "arguments": {...}}]
147
+ * - SAY: free text
148
+ */
149
+ buildToolGrammar(tools) {
150
+ // Build tool name alternatives: "get_weather" | "search"
151
+ const toolNames = tools.map(t => `"\\"${t.name}\\""`).join(' | ');
152
+ return `# Grammar allowing text responses OR tool calls
153
+ # Output: SAY: text OR TOOL: [json]
154
+
155
+ root ::= say-response | tool-call
156
+
157
+ # Say response - free form text (streamable)
158
+ say-response ::= "SAY:" ws text-content
159
+ text-content ::= text-char+
160
+ text-char ::= [a-zA-Z0-9 .,!?'\"():;\\n\\t\\r-]
161
+
162
+ # Tool call - structured JSON
163
+ tool-call ::= "TOOL:" ws tool-array
164
+
165
+ tool-array ::= "[" ws tool-obj ws "]"
166
+
167
+ tool-obj ::= "{" ws "\\"name\\":" ws tool-name "," ws "\\"arguments\\":" ws arguments ws "}"
168
+
169
+ tool-name ::= ${toolNames}
170
+
171
+ arguments ::= "{" ws (keyval ("," ws keyval)*)? ws "}"
172
+ keyval ::= string ":" ws value
173
+
174
+ value ::= string | number | bool | null | object | array
175
+ string ::= "\\"" chars "\\""
176
+ chars ::= char*
177
+ char ::= [^"\\\\\\x00-\\x1f] | "\\\\" escape
178
+ escape ::= ["\\\\/bfnrt] | "u" [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F]
179
+ number ::= "-"? ("0" | [1-9] [0-9]*) ("." [0-9]+)? ([eE] [+-]? [0-9]+)?
180
+ bool ::= "true" | "false"
181
+ null ::= "null"
182
+ object ::= "{" ws (keyval ("," ws keyval)*)? ws "}"
183
+ array ::= "[" ws (value ("," ws value)*)? ws "]"
184
+
185
+ ws ::= [ \\t\\n]*
186
+ `;
187
+ }
188
+ /**
189
+ * Format chat prompt with tool definitions (for grammar mode)
190
+ * Uses ChatML format with tool instructions
191
+ */
192
+ formatChatPromptWithTools(messages, tools) {
193
+ const toolSystemPrompt = this.buildToolSystemPrompt(tools);
194
+ let prompt = '';
195
+ for (const msg of messages) {
196
+ if (msg.role === 'system') {
197
+ // Combine system prompt with tool instructions
198
+ prompt += `<|im_start|>system\n${msg.content}\n\n${toolSystemPrompt}<|im_end|>\n`;
199
+ }
200
+ else if (msg.role === 'user') {
201
+ prompt += `<|im_start|>user\n${msg.content}<|im_end|>\n`;
202
+ }
203
+ else if (msg.role === 'assistant') {
204
+ const assistantMsg = msg;
205
+ if (assistantMsg.toolCalls && assistantMsg.toolCalls.length > 0) {
206
+ // Format tool calls
207
+ const toolCallJson = JSON.stringify(assistantMsg.toolCalls.map(tc => ({
208
+ name: tc.name,
209
+ arguments: tc.arguments,
210
+ })));
211
+ prompt += `<|im_start|>assistant\nTOOL: ${toolCallJson}<|im_end|>\n`;
212
+ }
213
+ else if (assistantMsg.content) {
214
+ // Format say response
215
+ prompt += `<|im_start|>assistant\nSAY: ${msg.content}<|im_end|>\n`;
216
+ }
217
+ }
218
+ else if (msg.role === 'tool') {
219
+ prompt += `<|im_start|>tool\n${msg.content}<|im_end|>\n`;
220
+ }
221
+ }
222
+ // If no system message was in history, add tool prompt as system
223
+ if (!messages.some(m => m.role === 'system')) {
224
+ prompt = `<|im_start|>system\n${toolSystemPrompt}<|im_end|>\n` + prompt;
225
+ }
226
+ prompt += '<|im_start|>assistant\n';
227
+ return prompt;
228
+ }
229
+ /** Special tokens to filter from output */
230
+ static SPECIAL_TOKENS = /\[end of text\]|<\|im_end\|>|<\|im_start\|>|<\|endoftext\|>/gi;
231
+ /**
232
+ * Run llama-completion and capture output
233
+ * Output goes to stdout, debug/timing info goes to stderr (ignored)
234
+ */
235
+ runLlamaCompletion(args, messages, options) {
236
+ // Log the input messages (use conversation ID if provided, else default)
237
+ const conversationId = options?.conversationId ?? 'default';
238
+ this.tracker.logInput(conversationId, messages);
239
+ return new Promise((resolve, reject) => {
240
+ const proc = spawn(this.config.binaryPath, args, {
241
+ stdio: ['pipe', 'pipe', 'pipe'],
242
+ });
243
+ let output = '';
244
+ proc.stdout.on('data', (data) => {
245
+ const chunk = data.toString();
246
+ output += chunk;
247
+ // Stream tokens if callback provided, filtering out special markers
248
+ // llama.cpp sends special tokens as complete strings, not split across chunks
249
+ if (options?.onToken) {
250
+ const filtered = chunk.replace(NativeLLM.SPECIAL_TOKENS, '');
251
+ for (const char of filtered) {
252
+ options.onToken(char);
253
+ }
254
+ }
255
+ });
256
+ proc.stderr.on('data', () => {
257
+ // Ignore stderr (Metal init messages, timing info, etc.)
258
+ });
259
+ proc.on('close', (code) => {
260
+ if (code !== 0) {
261
+ reject(new Error(`llama-completion exited with code ${code}`));
262
+ return;
263
+ }
264
+ // Clean up output - remove special tokens
265
+ const cleaned = output.replace(NativeLLM.SPECIAL_TOKENS, '').trim();
266
+ this.tracker.logRawOutput(conversationId, cleaned);
267
+ resolve(cleaned);
268
+ });
269
+ proc.on('error', reject);
270
+ });
271
+ }
272
+ /**
273
+ * Run llama-completion with smart streaming
274
+ * - SAY: streams tokens as they arrive
275
+ * - TOOL: buffers until complete, then parses
276
+ */
277
+ runLlamaCompletionWithStreaming(args, messages, options) {
278
+ const conversationId = options?.conversationId ?? 'default';
279
+ this.tracker.logInput(conversationId, messages);
280
+ return new Promise((resolve, reject) => {
281
+ const proc = spawn(this.config.binaryPath, args, {
282
+ stdio: ['pipe', 'pipe', 'pipe'],
283
+ });
284
+ let buffer = '';
285
+ let mode = 'detecting';
286
+ let textContent = '';
287
+ let isStreaming = false;
288
+ const SAY_PREFIX = 'SAY:';
289
+ const TOOL_PREFIX = 'TOOL:';
290
+ proc.stdout.on('data', (data) => {
291
+ const chunk = data.toString().replace(NativeLLM.SPECIAL_TOKENS, '');
292
+ buffer += chunk;
293
+ // Detect mode from prefix
294
+ if (mode === 'detecting') {
295
+ // Trim leading whitespace for detection
296
+ const trimmed = buffer.trimStart();
297
+ if (trimmed.startsWith(SAY_PREFIX)) {
298
+ mode = 'say';
299
+ isStreaming = true;
300
+ // Remove everything up to and including SAY:
301
+ const sayIndex = buffer.indexOf(SAY_PREFIX);
302
+ buffer = buffer.slice(sayIndex + SAY_PREFIX.length).trimStart();
303
+ }
304
+ else if (trimmed.startsWith(TOOL_PREFIX)) {
305
+ mode = 'tool_call';
306
+ // Remove everything up to and including TOOL:
307
+ const toolIndex = buffer.indexOf(TOOL_PREFIX);
308
+ buffer = buffer.slice(toolIndex + TOOL_PREFIX.length).trimStart();
309
+ }
310
+ else if (trimmed.length >= TOOL_PREFIX.length) {
311
+ // Buffer is long enough but doesn't match expected prefixes
312
+ // This shouldn't happen with grammar, but handle gracefully
313
+ mode = 'say';
314
+ isStreaming = true;
315
+ }
316
+ }
317
+ // Stream say content (no closing tag needed - just stream everything)
318
+ if (mode === 'say' && isStreaming && options?.onToken) {
319
+ for (const char of buffer) {
320
+ options.onToken(char);
321
+ }
322
+ textContent += buffer;
323
+ buffer = '';
324
+ }
325
+ });
326
+ proc.stderr.on('data', () => {
327
+ // Ignore stderr
328
+ });
329
+ proc.on('close', (code) => {
330
+ if (code !== 0) {
331
+ reject(new Error(`llama-completion exited with code ${code}`));
332
+ return;
333
+ }
334
+ // Final processing based on mode
335
+ const fullOutput = (mode === 'say' ? SAY_PREFIX + ' ' : TOOL_PREFIX + ' ') +
336
+ (textContent || '') + buffer;
337
+ this.tracker.logRawOutput(conversationId, fullOutput.replace(NativeLLM.SPECIAL_TOKENS, '').trim());
338
+ if (mode === 'say') {
339
+ // Any remaining content in buffer
340
+ const remaining = buffer.trim();
341
+ if (remaining && options?.onToken) {
342
+ for (const char of remaining) {
343
+ options.onToken(char);
344
+ }
345
+ }
346
+ const finalContent = textContent + remaining;
347
+ resolve({
348
+ content: finalContent,
349
+ finishReason: 'stop',
350
+ });
351
+ }
352
+ else if (mode === 'tool_call') {
353
+ // Parse tool call JSON
354
+ const toolCalls = this.parseToolCallOutput(buffer);
355
+ if (toolCalls && toolCalls.length > 0) {
356
+ resolve({
357
+ content: '',
358
+ toolCalls: toolCalls.map((tc, i) => ({
359
+ id: `native-${Date.now()}-${i}-${Math.random().toString(36).slice(2, 9)}`,
360
+ name: tc.name,
361
+ arguments: tc.arguments || {},
362
+ })),
363
+ finishReason: 'tool_calls',
364
+ });
365
+ }
366
+ else {
367
+ // Failed to parse tool call
368
+ resolve({
369
+ content: buffer,
370
+ finishReason: 'stop',
371
+ });
372
+ }
373
+ }
374
+ else {
375
+ // Detection never completed - return raw buffer
376
+ resolve({
377
+ content: buffer,
378
+ finishReason: 'stop',
379
+ });
380
+ }
381
+ });
382
+ proc.on('error', reject);
383
+ });
384
+ }
385
+ /**
386
+ * Freeform generation (no grammar) - used when no tools are provided
387
+ */
388
+ async generateFreeform(messages, options) {
389
+ const prompt = this.formatChatPrompt(messages);
390
+ // llama-completion args for clean non-interactive output
391
+ const args = [
392
+ '-m', this.config.modelPath,
393
+ '-n', String(this.config.maxNewTokens),
394
+ '--temp', String(this.config.temperature ?? 0.7),
395
+ '--no-display-prompt', // Don't echo the prompt back
396
+ '--simple-io', // Clean output without ANSI codes
397
+ '-no-cnv', // Non-conversation mode (single completion)
398
+ '-p', prompt,
399
+ ];
400
+ if (this.config.gpuLayers) {
401
+ args.push('-ngl', String(this.config.gpuLayers));
402
+ }
403
+ const output = await this.runLlamaCompletion(args, messages, options);
404
+ return {
405
+ content: output,
406
+ finishReason: 'stop',
407
+ };
408
+ }
409
+ /**
410
+ * Format basic chat prompt (for non-tool mode)
411
+ */
412
+ formatChatPrompt(messages) {
413
+ let prompt = '';
414
+ for (const msg of messages) {
415
+ if (msg.role === 'system') {
416
+ prompt += `<|im_start|>system\n${msg.content}<|im_end|>\n`;
417
+ }
418
+ else if (msg.role === 'user') {
419
+ prompt += `<|im_start|>user\n${msg.content}<|im_end|>\n`;
420
+ }
421
+ else if (msg.role === 'assistant') {
422
+ prompt += `<|im_start|>assistant\n${msg.content}<|im_end|>\n`;
423
+ }
424
+ else if (msg.role === 'tool') {
425
+ prompt += `<|im_start|>tool\n${msg.content}<|im_end|>\n`;
426
+ }
427
+ }
428
+ prompt += '<|im_start|>assistant\n';
429
+ return prompt;
430
+ }
431
+ isReady() {
432
+ return this.ready;
433
+ }
434
+ }
435
+ //# sourceMappingURL=llm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm.js","sourceRoot":"","sources":["../../../src/backends/native/llm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Native STT Pipeline (whisper.cpp)
3
+ * Server-only - requires native binary
4
+ */
5
+ import type { STTPipeline, NativeSTTConfig, ProgressCallback } from '../../types';
6
+ export declare class NativeSTT implements STTPipeline {
7
+ private config;
8
+ private ready;
9
+ constructor(config: NativeSTTConfig);
10
+ initialize(_onProgress?: ProgressCallback): Promise<void>;
11
+ transcribe(audio: Float32Array): Promise<string>;
12
+ isReady(): boolean;
13
+ private writeWav;
14
+ }
15
+ //# sourceMappingURL=stt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stt.d.ts","sourceRoot":"","sources":["../../../src/backends/native/stt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAElF,qBAAa,SAAU,YAAW,WAAW;IAC3C,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,KAAK,CAAS;gBAEV,MAAM,EAAE,eAAe;IAI7B,UAAU,CAAC,WAAW,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAczD,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IA6BtD,OAAO,IAAI,OAAO;IAIlB,OAAO,CAAC,QAAQ;CAkCjB"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Native STT Pipeline (whisper.cpp)
3
+ * Server-only - requires native binary
4
+ */
5
+ import { execSync } from 'child_process';
6
+ import { writeFileSync, unlinkSync, existsSync } from 'fs';
7
+ import { join } from 'path';
8
+ export class NativeSTT {
9
+ config;
10
+ ready = false;
11
+ constructor(config) {
12
+ this.config = config;
13
+ }
14
+ async initialize(_onProgress) {
15
+ console.log('Initializing native STT (whisper.cpp)...');
16
+ if (!existsSync(this.config.binaryPath)) {
17
+ throw new Error(`whisper.cpp binary not found at: ${this.config.binaryPath}`);
18
+ }
19
+ if (!existsSync(this.config.modelPath)) {
20
+ throw new Error(`Whisper model not found at: ${this.config.modelPath}`);
21
+ }
22
+ this.ready = true;
23
+ console.log('Native STT ready.');
24
+ }
25
+ async transcribe(audio) {
26
+ if (!this.ready) {
27
+ throw new Error('STT pipeline not initialized');
28
+ }
29
+ const tempPath = join('/tmp', `whisper-${Date.now()}-${Math.random().toString(36).slice(2)}.wav`);
30
+ try {
31
+ this.writeWav(tempPath, audio, 16000);
32
+ const result = execSync(`"${this.config.binaryPath}" ` +
33
+ `-m "${this.config.modelPath}" ` +
34
+ `-l ${this.config.language} ` +
35
+ `--no-timestamps ` +
36
+ `--suppress-nst ` + // Suppress non-speech tokens like "(upbeat music)"
37
+ `-np ` + // No prints except results
38
+ `-f "${tempPath}"`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
39
+ return result.trim();
40
+ }
41
+ finally {
42
+ if (existsSync(tempPath)) {
43
+ unlinkSync(tempPath);
44
+ }
45
+ }
46
+ }
47
+ isReady() {
48
+ return this.ready;
49
+ }
50
+ writeWav(path, audio, sampleRate) {
51
+ const numChannels = 1;
52
+ const bitsPerSample = 16;
53
+ const byteRate = sampleRate * numChannels * (bitsPerSample / 8);
54
+ const blockAlign = numChannels * (bitsPerSample / 8);
55
+ const dataSize = audio.length * (bitsPerSample / 8);
56
+ const fileSize = 36 + dataSize;
57
+ const buffer = Buffer.alloc(44 + dataSize);
58
+ let offset = 0;
59
+ buffer.write('RIFF', offset);
60
+ offset += 4;
61
+ buffer.writeUInt32LE(fileSize, offset);
62
+ offset += 4;
63
+ buffer.write('WAVE', offset);
64
+ offset += 4;
65
+ buffer.write('fmt ', offset);
66
+ offset += 4;
67
+ buffer.writeUInt32LE(16, offset);
68
+ offset += 4;
69
+ buffer.writeUInt16LE(1, offset);
70
+ offset += 2;
71
+ buffer.writeUInt16LE(numChannels, offset);
72
+ offset += 2;
73
+ buffer.writeUInt32LE(sampleRate, offset);
74
+ offset += 4;
75
+ buffer.writeUInt32LE(byteRate, offset);
76
+ offset += 4;
77
+ buffer.writeUInt16LE(blockAlign, offset);
78
+ offset += 2;
79
+ buffer.writeUInt16LE(bitsPerSample, offset);
80
+ offset += 2;
81
+ buffer.write('data', offset);
82
+ offset += 4;
83
+ buffer.writeUInt32LE(dataSize, offset);
84
+ offset += 4;
85
+ for (let i = 0; i < audio.length; i++) {
86
+ const sample = Math.max(-1, Math.min(1, audio[i]));
87
+ const int16 = sample < 0 ? sample * 32768 : sample * 32767;
88
+ buffer.writeInt16LE(Math.round(int16), offset);
89
+ offset += 2;
90
+ }
91
+ writeFileSync(path, buffer);
92
+ }
93
+ }
94
+ //# sourceMappingURL=stt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stt.js","sourceRoot":"","sources":["../../../src/backends/native/stt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Native TTS Pipeline (sherpa-onnx)
3
+ * Server-only - requires sherpa-onnx binary
4
+ *
5
+ * Uses sherpa-onnx-offline-tts which supports Piper ONNX models.
6
+ * See: https://github.com/k2-fsa/sherpa-onnx
7
+ */
8
+ import type { TTSPipeline, SherpaOnnxTTSConfig, ProgressCallback, AudioPlayable } from '../../types';
9
+ export declare class NativeTTS implements TTSPipeline {
10
+ private config;
11
+ private ready;
12
+ private modelPath;
13
+ private tokensPath;
14
+ private dataDir;
15
+ constructor(config: SherpaOnnxTTSConfig);
16
+ initialize(_onProgress?: ProgressCallback): Promise<void>;
17
+ synthesize(text: string): Promise<AudioPlayable>;
18
+ private parseWav;
19
+ isReady(): boolean;
20
+ }
21
+ //# sourceMappingURL=tts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tts.d.ts","sourceRoot":"","sources":["../../../src/backends/native/tts.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,WAAW,EAAE,mBAAmB,EAAE,gBAAgB,EAAe,aAAa,EAAE,MAAM,aAAa,CAAC;AAGlH,qBAAa,SAAU,YAAW,WAAW;IAC3C,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,OAAO,CAAc;gBAEjB,MAAM,EAAE,mBAAmB;IAQjC,UAAU,CAAC,WAAW,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAuCzD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAmCtD,OAAO,CAAC,QAAQ;IAsBhB,OAAO,IAAI,OAAO;CAGnB"}