@llmrtc/llmrtc-core 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.
@@ -0,0 +1,450 @@
1
+ import { createTimingInfo, callHookSafe } from './hooks.js';
2
+ import { MetricNames, NoopMetrics } from './metrics.js';
3
+ // Sentence boundary regex: matches .!? followed by space or end of string
4
+ // Handles common abbreviations by requiring whitespace after punctuation
5
+ const SENTENCE_BOUNDARY = /[.!?]+(?:\s+|$)/;
6
+ export class ConversationOrchestrator {
7
+ constructor(config) {
8
+ Object.defineProperty(this, "config", {
9
+ enumerable: true,
10
+ configurable: true,
11
+ writable: true,
12
+ value: config
13
+ });
14
+ Object.defineProperty(this, "providers", {
15
+ enumerable: true,
16
+ configurable: true,
17
+ writable: true,
18
+ value: void 0
19
+ });
20
+ Object.defineProperty(this, "history", {
21
+ enumerable: true,
22
+ configurable: true,
23
+ writable: true,
24
+ value: []
25
+ });
26
+ Object.defineProperty(this, "systemPrompt", {
27
+ enumerable: true,
28
+ configurable: true,
29
+ writable: true,
30
+ value: void 0
31
+ });
32
+ Object.defineProperty(this, "historyLimit", {
33
+ enumerable: true,
34
+ configurable: true,
35
+ writable: true,
36
+ value: void 0
37
+ });
38
+ Object.defineProperty(this, "logger", {
39
+ enumerable: true,
40
+ configurable: true,
41
+ writable: true,
42
+ value: void 0
43
+ });
44
+ Object.defineProperty(this, "streamingTTS", {
45
+ enumerable: true,
46
+ configurable: true,
47
+ writable: true,
48
+ value: void 0
49
+ });
50
+ Object.defineProperty(this, "sessionId", {
51
+ enumerable: true,
52
+ configurable: true,
53
+ writable: true,
54
+ value: void 0
55
+ });
56
+ Object.defineProperty(this, "hooks", {
57
+ enumerable: true,
58
+ configurable: true,
59
+ writable: true,
60
+ value: void 0
61
+ });
62
+ Object.defineProperty(this, "metrics", {
63
+ enumerable: true,
64
+ configurable: true,
65
+ writable: true,
66
+ value: void 0
67
+ });
68
+ Object.defineProperty(this, "sentenceChunker", {
69
+ enumerable: true,
70
+ configurable: true,
71
+ writable: true,
72
+ value: void 0
73
+ });
74
+ this.providers = config.providers;
75
+ this.systemPrompt = config.systemPrompt;
76
+ this.historyLimit = config.historyLimit ?? 8;
77
+ this.logger = config.logger ?? console;
78
+ this.streamingTTS = config.streamingTTS ?? true;
79
+ this.sessionId = config.sessionId;
80
+ this.hooks = config.hooks ?? {};
81
+ this.metrics = config.metrics ?? new NoopMetrics();
82
+ this.sentenceChunker = config.sentenceChunker;
83
+ }
84
+ async init() {
85
+ await Promise.all([
86
+ this.providers.llm.init?.(),
87
+ this.providers.stt.init?.(),
88
+ this.providers.tts.init?.(),
89
+ this.providers.vision?.init?.()
90
+ ]);
91
+ }
92
+ /**
93
+ * Run a single voice+vision turn: audio -> STT -> LLM (+optional vision) -> TTS.
94
+ */
95
+ async runTurn(audio, attachments = []) {
96
+ const transcript = await this.providers.stt.transcribe(audio);
97
+ this.logger.debug?.('[orchestrator] transcript', transcript.text);
98
+ const userMessage = {
99
+ role: 'user',
100
+ content: transcript.text,
101
+ attachments: attachments.length ? attachments : undefined
102
+ };
103
+ if (this.systemPrompt && !this.history.length) {
104
+ this.history.push({ role: 'system', content: this.systemPrompt });
105
+ }
106
+ this.pushHistory(userMessage);
107
+ const llmRequest = {
108
+ messages: this.history.slice(-this.historyLimit),
109
+ config: {
110
+ systemPrompt: this.systemPrompt,
111
+ historyLimit: this.historyLimit,
112
+ temperature: this.config.temperature,
113
+ topP: this.config.topP,
114
+ maxTokens: this.config.maxTokens
115
+ }
116
+ };
117
+ const llm = await this.providers.llm.complete(llmRequest);
118
+ this.logger.debug?.('[orchestrator] llm response', llm.fullText);
119
+ const assistantMessage = { role: 'assistant', content: llm.fullText };
120
+ this.pushHistory(assistantMessage);
121
+ const tts = await this.providers.tts.speak(llm.fullText);
122
+ return { transcript, llm, tts };
123
+ }
124
+ /**
125
+ * Streaming version: yields LLM chunks as they arrive.
126
+ *
127
+ * With streaming TTS enabled (when provider supports speakStream):
128
+ * - Detects sentence boundaries during LLM streaming
129
+ * - Starts TTS generation as soon as each sentence is complete
130
+ * - Yields TTSChunk events with PCM audio data
131
+ * - User hears audio while LLM is still generating
132
+ *
133
+ * Hooks and metrics are called throughout the turn lifecycle.
134
+ */
135
+ async *runTurnStream(audio, attachments = []) {
136
+ // Generate turn context
137
+ const turnStartTime = Date.now();
138
+ const ctx = {
139
+ turnId: globalThis.crypto.randomUUID(),
140
+ sessionId: this.sessionId,
141
+ startTime: turnStartTime
142
+ };
143
+ // Call onTurnStart hook
144
+ await callHookSafe(this.hooks.onTurnStart, ctx, audio);
145
+ // -------------------------------------------------------------------------
146
+ // STT Phase
147
+ // -------------------------------------------------------------------------
148
+ const sttStartTime = Date.now();
149
+ await callHookSafe(this.hooks.onSTTStart, ctx, audio);
150
+ let transcript;
151
+ try {
152
+ transcript = await this.providers.stt.transcribe(audio);
153
+ const sttTiming = createTimingInfo(sttStartTime, Date.now());
154
+ this.metrics.timing(MetricNames.STT_DURATION, sttTiming.durationMs, {
155
+ provider: this.providers.stt.name
156
+ });
157
+ await callHookSafe(this.hooks.onSTTEnd, ctx, transcript, sttTiming);
158
+ }
159
+ catch (error) {
160
+ const err = error instanceof Error ? error : new Error(String(error));
161
+ await callHookSafe(this.hooks.onSTTError, ctx, err);
162
+ this.metrics.increment(MetricNames.ERRORS, 1, { component: 'stt' });
163
+ throw error;
164
+ }
165
+ this.pushHistory({ role: 'user', content: transcript.text, attachments: attachments.length ? attachments : undefined });
166
+ yield transcript;
167
+ const llmRequest = {
168
+ messages: this.history.slice(-this.historyLimit),
169
+ config: {
170
+ systemPrompt: this.systemPrompt,
171
+ historyLimit: this.historyLimit,
172
+ temperature: this.config.temperature,
173
+ topP: this.config.topP,
174
+ maxTokens: this.config.maxTokens
175
+ },
176
+ stream: true
177
+ };
178
+ // -------------------------------------------------------------------------
179
+ // LLM Phase
180
+ // -------------------------------------------------------------------------
181
+ const llmStartTime = Date.now();
182
+ await callHookSafe(this.hooks.onLLMStart, ctx, llmRequest);
183
+ let llmFirstChunkTime;
184
+ // Non-streaming LLM fallback
185
+ if (!this.providers.llm.stream) {
186
+ try {
187
+ const llm = await this.providers.llm.complete(llmRequest);
188
+ const llmTiming = createTimingInfo(llmStartTime, Date.now());
189
+ this.metrics.timing(MetricNames.LLM_DURATION, llmTiming.durationMs, {
190
+ provider: this.providers.llm.name
191
+ });
192
+ await callHookSafe(this.hooks.onLLMEnd, ctx, llm, llmTiming);
193
+ this.pushHistory({ role: 'assistant', content: llm.fullText });
194
+ yield llm;
195
+ yield* this.generateTTSWithHooks(ctx, llm.fullText);
196
+ // Turn complete
197
+ const turnTiming = createTimingInfo(turnStartTime, Date.now());
198
+ this.metrics.timing(MetricNames.TURN_DURATION, turnTiming.durationMs);
199
+ await callHookSafe(this.hooks.onTurnEnd, ctx, turnTiming);
200
+ return;
201
+ }
202
+ catch (error) {
203
+ const err = error instanceof Error ? error : new Error(String(error));
204
+ await callHookSafe(this.hooks.onLLMError, ctx, err);
205
+ this.metrics.increment(MetricNames.ERRORS, 1, { component: 'llm' });
206
+ throw error;
207
+ }
208
+ }
209
+ // Check if we can do streaming TTS (requires config enabled AND provider support)
210
+ const canStreamTTS = this.streamingTTS && !!this.providers.tts.speakStream;
211
+ let assembled = '';
212
+ let pendingText = '';
213
+ let ttsStarted = false;
214
+ let chunkIndex = 0;
215
+ const ttsStartTime = Date.now();
216
+ try {
217
+ for await (const chunk of this.providers.llm.stream(llmRequest)) {
218
+ // Track time to first token
219
+ if (chunkIndex === 0 && chunk.content) {
220
+ llmFirstChunkTime = Date.now();
221
+ this.metrics.timing(MetricNames.LLM_TTFT, llmFirstChunkTime - llmStartTime, {
222
+ provider: this.providers.llm.name
223
+ });
224
+ }
225
+ if (chunk.content) {
226
+ assembled += chunk.content;
227
+ pendingText += chunk.content;
228
+ }
229
+ // Call LLM chunk hook
230
+ await callHookSafe(this.hooks.onLLMChunk, ctx, chunk, chunkIndex);
231
+ chunkIndex++;
232
+ yield chunk;
233
+ // Only do sentence-boundary TTS if provider supports streaming
234
+ if (canStreamTTS && pendingText) {
235
+ // Check for complete sentences using custom chunker or default
236
+ const sentences = this.splitIntoSentences(pendingText);
237
+ if (sentences.length > 1) {
238
+ // We have at least one complete sentence
239
+ const completeSentences = sentences.slice(0, -1);
240
+ pendingText = sentences[sentences.length - 1];
241
+ for (const completeSentence of completeSentences) {
242
+ if (completeSentence.trim()) {
243
+ // Signal TTS start on first sentence
244
+ if (!ttsStarted) {
245
+ ttsStarted = true;
246
+ await callHookSafe(this.hooks.onTTSStart, ctx, completeSentence.trim());
247
+ yield { type: 'tts-start' };
248
+ }
249
+ // Stream TTS for this sentence
250
+ yield* this.streamTTSChunksWithHooks(ctx, completeSentence.trim());
251
+ }
252
+ }
253
+ }
254
+ }
255
+ }
256
+ // LLM complete
257
+ const llmEndTime = Date.now();
258
+ const llmTiming = createTimingInfo(llmStartTime, llmEndTime);
259
+ this.metrics.timing(MetricNames.LLM_DURATION, llmTiming.durationMs, {
260
+ provider: this.providers.llm.name
261
+ });
262
+ const llmResult = { fullText: assembled };
263
+ await callHookSafe(this.hooks.onLLMEnd, ctx, llmResult, llmTiming);
264
+ this.pushHistory({ role: 'assistant', content: assembled });
265
+ yield llmResult;
266
+ }
267
+ catch (error) {
268
+ const err = error instanceof Error ? error : new Error(String(error));
269
+ await callHookSafe(this.hooks.onLLMError, ctx, err);
270
+ this.metrics.increment(MetricNames.ERRORS, 1, { component: 'llm' });
271
+ throw error;
272
+ }
273
+ // -------------------------------------------------------------------------
274
+ // TTS Phase (remaining text)
275
+ // -------------------------------------------------------------------------
276
+ try {
277
+ // Handle remaining text after LLM completes
278
+ if (canStreamTTS) {
279
+ const remainingText = pendingText.trim();
280
+ if (remainingText) {
281
+ if (!ttsStarted) {
282
+ ttsStarted = true;
283
+ await callHookSafe(this.hooks.onTTSStart, ctx, remainingText);
284
+ yield { type: 'tts-start' };
285
+ }
286
+ yield* this.streamTTSChunksWithHooks(ctx, remainingText);
287
+ }
288
+ // Signal TTS complete
289
+ if (ttsStarted) {
290
+ const ttsTiming = createTimingInfo(ttsStartTime, Date.now());
291
+ this.metrics.timing(MetricNames.TTS_DURATION, ttsTiming.durationMs, {
292
+ provider: this.providers.tts.name
293
+ });
294
+ await callHookSafe(this.hooks.onTTSEnd, ctx, ttsTiming);
295
+ yield { type: 'tts-complete' };
296
+ }
297
+ }
298
+ else {
299
+ // Fallback to non-streaming TTS
300
+ yield* this.generateTTSWithHooks(ctx, assembled);
301
+ }
302
+ }
303
+ catch (error) {
304
+ const err = error instanceof Error ? error : new Error(String(error));
305
+ await callHookSafe(this.hooks.onTTSError, ctx, err);
306
+ this.metrics.increment(MetricNames.ERRORS, 1, { component: 'tts' });
307
+ throw error;
308
+ }
309
+ // Turn complete
310
+ const turnTiming = createTimingInfo(turnStartTime, Date.now());
311
+ this.metrics.timing(MetricNames.TURN_DURATION, turnTiming.durationMs);
312
+ await callHookSafe(this.hooks.onTurnEnd, ctx, turnTiming);
313
+ }
314
+ /**
315
+ * Split text into sentences using custom chunker or default regex
316
+ */
317
+ splitIntoSentences(text) {
318
+ if (this.sentenceChunker) {
319
+ return this.sentenceChunker(text);
320
+ }
321
+ // Default: split on sentence boundaries, keep last part as incomplete
322
+ const parts = text.split(SENTENCE_BOUNDARY);
323
+ // The split removes the delimiter, so we need to reconstruct
324
+ const matches = text.match(new RegExp(SENTENCE_BOUNDARY.source, 'g')) || [];
325
+ const result = [];
326
+ for (let i = 0; i < parts.length - 1; i++) {
327
+ result.push(parts[i] + (matches[i] || ''));
328
+ }
329
+ // Last part is incomplete (no boundary yet)
330
+ if (parts.length > 0) {
331
+ result.push(parts[parts.length - 1]);
332
+ }
333
+ return result;
334
+ }
335
+ /**
336
+ * Stream TTS chunks for a sentence using PCM format with hooks.
337
+ * Yields TTSChunk events as audio data arrives.
338
+ */
339
+ async *streamTTSChunksWithHooks(ctx, text) {
340
+ if (!this.providers.tts.speakStream)
341
+ return;
342
+ let chunkIndex = 0;
343
+ try {
344
+ for await (const audioChunk of this.providers.tts.speakStream(text, { format: 'pcm' })) {
345
+ const ttsChunk = {
346
+ type: 'tts-chunk',
347
+ audio: audioChunk,
348
+ format: 'pcm',
349
+ sampleRate: 24000, // OpenAI/ElevenLabs PCM is 24kHz
350
+ sentence: text
351
+ };
352
+ await callHookSafe(this.hooks.onTTSChunk, ctx, ttsChunk, chunkIndex);
353
+ chunkIndex++;
354
+ yield ttsChunk;
355
+ }
356
+ }
357
+ catch (err) {
358
+ this.logger.error?.('[orchestrator] TTS stream error:', err);
359
+ // Fallback: try non-streaming TTS
360
+ try {
361
+ const tts = await this.providers.tts.speak(text, { format: 'pcm' });
362
+ const ttsChunk = {
363
+ type: 'tts-chunk',
364
+ audio: tts.audio,
365
+ format: 'pcm',
366
+ sampleRate: 24000,
367
+ sentence: text
368
+ };
369
+ await callHookSafe(this.hooks.onTTSChunk, ctx, ttsChunk, chunkIndex);
370
+ yield ttsChunk;
371
+ }
372
+ catch (fallbackErr) {
373
+ this.logger.error?.('[orchestrator] TTS fallback also failed:', fallbackErr);
374
+ throw fallbackErr;
375
+ }
376
+ }
377
+ }
378
+ /**
379
+ * Non-streaming TTS with hooks: generates complete audio and yields as single TTSResult.
380
+ */
381
+ async *generateTTSWithHooks(ctx, text) {
382
+ const ttsStartTime = Date.now();
383
+ await callHookSafe(this.hooks.onTTSStart, ctx, text);
384
+ yield { type: 'tts-start' };
385
+ const tts = await this.providers.tts.speak(text);
386
+ yield tts;
387
+ const ttsTiming = createTimingInfo(ttsStartTime, Date.now());
388
+ this.metrics.timing(MetricNames.TTS_DURATION, ttsTiming.durationMs, {
389
+ provider: this.providers.tts.name
390
+ });
391
+ await callHookSafe(this.hooks.onTTSEnd, ctx, ttsTiming);
392
+ yield { type: 'tts-complete' };
393
+ }
394
+ /**
395
+ * @deprecated Use streamTTSChunksWithHooks instead
396
+ * Stream TTS chunks for a sentence using PCM format.
397
+ */
398
+ async *streamTTSChunks(text) {
399
+ if (!this.providers.tts.speakStream)
400
+ return;
401
+ try {
402
+ for await (const audioChunk of this.providers.tts.speakStream(text, { format: 'pcm' })) {
403
+ yield {
404
+ type: 'tts-chunk',
405
+ audio: audioChunk,
406
+ format: 'pcm',
407
+ sampleRate: 24000, // OpenAI/ElevenLabs PCM is 24kHz
408
+ sentence: text
409
+ };
410
+ }
411
+ }
412
+ catch (err) {
413
+ this.logger.error?.('[orchestrator] TTS stream error:', err);
414
+ // Fallback: try non-streaming TTS
415
+ try {
416
+ const tts = await this.providers.tts.speak(text, { format: 'pcm' });
417
+ yield {
418
+ type: 'tts-chunk',
419
+ audio: tts.audio,
420
+ format: 'pcm',
421
+ sampleRate: 24000,
422
+ sentence: text
423
+ };
424
+ }
425
+ catch (fallbackErr) {
426
+ this.logger.error?.('[orchestrator] TTS fallback also failed:', fallbackErr);
427
+ }
428
+ }
429
+ }
430
+ /**
431
+ * @deprecated Use generateTTSWithHooks instead
432
+ * Non-streaming TTS: generates complete audio and yields as single TTSResult.
433
+ */
434
+ async *generateTTS(text) {
435
+ yield { type: 'tts-start' };
436
+ const tts = await this.providers.tts.speak(text);
437
+ yield tts;
438
+ yield { type: 'tts-complete' };
439
+ }
440
+ pushHistory(message) {
441
+ this.history.push(message);
442
+ if (this.history.length > this.historyLimit + 2) {
443
+ // keep system prompt if present
444
+ const start = this.history[0]?.role === 'system' ? 1 : 0;
445
+ const overflow = this.history.length - (this.historyLimit + 2);
446
+ this.history.splice(start, overflow);
447
+ }
448
+ }
449
+ }
450
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Playbook Engine
3
+ *
4
+ * Evaluates transition rules and manages stage transitions in a playbook.
5
+ */
6
+ import type { Playbook, PlaybookState, Stage, Transition, TransitionEvaluationResult } from './playbook.js';
7
+ /**
8
+ * Options for the playbook engine
9
+ */
10
+ export interface PlaybookEngineOptions {
11
+ /** Enable debug logging */
12
+ debug?: boolean;
13
+ /** Custom logger */
14
+ logger?: {
15
+ debug: (msg: string, ...args: unknown[]) => void;
16
+ info: (msg: string, ...args: unknown[]) => void;
17
+ warn: (msg: string, ...args: unknown[]) => void;
18
+ error: (msg: string, ...args: unknown[]) => void;
19
+ };
20
+ }
21
+ /**
22
+ * Event emitted during playbook execution
23
+ */
24
+ export type PlaybookEvent = {
25
+ type: 'stage_enter';
26
+ stage: Stage;
27
+ previousStage?: Stage;
28
+ } | {
29
+ type: 'stage_exit';
30
+ stage: Stage;
31
+ nextStage: Stage;
32
+ } | {
33
+ type: 'transition';
34
+ transition: Transition;
35
+ from: Stage;
36
+ to: Stage;
37
+ } | {
38
+ type: 'turn_complete';
39
+ stage: Stage;
40
+ turnCount: number;
41
+ } | {
42
+ type: 'playbook_complete';
43
+ finalStage: Stage;
44
+ };
45
+ /**
46
+ * Listener for playbook events
47
+ */
48
+ export type PlaybookEventListener = (event: PlaybookEvent) => void | Promise<void>;
49
+ /**
50
+ * Playbook Engine - Evaluates transitions and manages playbook state
51
+ */
52
+ export declare class PlaybookEngine {
53
+ private readonly playbook;
54
+ private state;
55
+ private readonly options;
56
+ private readonly listeners;
57
+ private sessionMetadata;
58
+ constructor(playbook: Playbook, options?: PlaybookEngineOptions);
59
+ /**
60
+ * Get current playbook state
61
+ */
62
+ getState(): Readonly<PlaybookState>;
63
+ /**
64
+ * Get current stage
65
+ */
66
+ getCurrentStage(): Stage;
67
+ /**
68
+ * Get the playbook
69
+ */
70
+ getPlaybook(): Playbook;
71
+ /**
72
+ * Set session metadata
73
+ */
74
+ setSessionMetadata(metadata: Record<string, unknown>): void;
75
+ /**
76
+ * Update conversation context
77
+ */
78
+ updateContext(updates: Record<string, unknown>): void;
79
+ /**
80
+ * Subscribe to playbook events
81
+ */
82
+ on(listener: PlaybookEventListener): () => void;
83
+ /**
84
+ * Emit an event to all listeners
85
+ */
86
+ private emit;
87
+ /**
88
+ * Log a debug message
89
+ */
90
+ private log;
91
+ /**
92
+ * Build transition context for evaluation
93
+ */
94
+ private buildTransitionContext;
95
+ /**
96
+ * Evaluate a single transition condition
97
+ */
98
+ private evaluateCondition;
99
+ /**
100
+ * Evaluate all applicable transitions and return the highest priority match
101
+ */
102
+ evaluateTransitions(lastAssistantMessage?: string, lastToolCalls?: Array<{
103
+ name: string;
104
+ arguments: Record<string, unknown>;
105
+ }>): Promise<TransitionEvaluationResult>;
106
+ /**
107
+ * Check if a specific transition should be triggered (e.g., from playbook_transition tool)
108
+ */
109
+ evaluateExplicitTransition(targetStage: string, reason: string, data?: Record<string, unknown>): Promise<TransitionEvaluationResult>;
110
+ /**
111
+ * Execute a stage transition
112
+ */
113
+ executeTransition(transition: Transition, overrideData?: Record<string, unknown>): Promise<void>;
114
+ /**
115
+ * Increment turn count and emit event
116
+ */
117
+ completeTurn(): Promise<void>;
118
+ /**
119
+ * Mark playbook as complete
120
+ */
121
+ complete(): Promise<void>;
122
+ /**
123
+ * Get the effective system prompt for current stage
124
+ * (combines global prompt with stage-specific prompt)
125
+ */
126
+ getEffectiveSystemPrompt(): string;
127
+ /**
128
+ * Get all tools available in current stage
129
+ * (combines global tools with stage-specific tools)
130
+ */
131
+ getAvailableTools(): import('./tools.js').ToolDefinition[];
132
+ /**
133
+ * Get effective LLM config for current stage
134
+ */
135
+ getEffectiveLLMConfig(): import('./playbook.js').StageLLMConfig;
136
+ /**
137
+ * Reset engine to initial state
138
+ */
139
+ reset(): void;
140
+ }