@ariaflowagents/livekit-plugin 0.9.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 (154) hide show
  1. package/README.md +155 -0
  2. package/dist/agent/AriaFlowAgent.d.ts +11 -0
  3. package/dist/agent/AriaFlowAgent.d.ts.map +1 -0
  4. package/dist/agent/AriaFlowAgent.js +22 -0
  5. package/dist/agent/AriaFlowAgent.js.map +1 -0
  6. package/dist/audio_byte_stream.d.ts +29 -0
  7. package/dist/audio_byte_stream.d.ts.map +1 -0
  8. package/dist/audio_byte_stream.js +62 -0
  9. package/dist/audio_byte_stream.js.map +1 -0
  10. package/dist/audio_frame.d.ts +2 -0
  11. package/dist/audio_frame.d.ts.map +1 -0
  12. package/dist/audio_frame.js +6 -0
  13. package/dist/audio_frame.js.map +1 -0
  14. package/dist/codec/g711.d.ts +14 -0
  15. package/dist/codec/g711.d.ts.map +1 -0
  16. package/dist/codec/g711.js +51 -0
  17. package/dist/codec/g711.js.map +1 -0
  18. package/dist/errors.d.ts +14 -0
  19. package/dist/errors.d.ts.map +1 -0
  20. package/dist/errors.js +27 -0
  21. package/dist/errors.js.map +1 -0
  22. package/dist/filler/FillerCoordinator.d.ts +7 -0
  23. package/dist/filler/FillerCoordinator.d.ts.map +1 -0
  24. package/dist/filler/FillerCoordinator.js +29 -0
  25. package/dist/filler/FillerCoordinator.js.map +1 -0
  26. package/dist/gemini/filler.d.ts +14 -0
  27. package/dist/gemini/filler.d.ts.map +1 -0
  28. package/dist/gemini/filler.js +48 -0
  29. package/dist/gemini/filler.js.map +1 -0
  30. package/dist/gemini/index.d.ts +4 -0
  31. package/dist/gemini/index.d.ts.map +1 -0
  32. package/dist/gemini/index.js +4 -0
  33. package/dist/gemini/index.js.map +1 -0
  34. package/dist/gemini/stt.d.ts +106 -0
  35. package/dist/gemini/stt.d.ts.map +1 -0
  36. package/dist/gemini/stt.js +528 -0
  37. package/dist/gemini/stt.js.map +1 -0
  38. package/dist/gemini/tts.d.ts +57 -0
  39. package/dist/gemini/tts.d.ts.map +1 -0
  40. package/dist/gemini/tts.js +529 -0
  41. package/dist/gemini/tts.js.map +1 -0
  42. package/dist/index.d.ts +29 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +33 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/livekit_io.d.ts +44 -0
  47. package/dist/livekit_io.d.ts.map +1 -0
  48. package/dist/livekit_io.js +101 -0
  49. package/dist/livekit_io.js.map +1 -0
  50. package/dist/llm/AriaRuntimeLLMAdapter.d.ts +65 -0
  51. package/dist/llm/AriaRuntimeLLMAdapter.d.ts.map +1 -0
  52. package/dist/llm/AriaRuntimeLLMAdapter.js +296 -0
  53. package/dist/llm/AriaRuntimeLLMAdapter.js.map +1 -0
  54. package/dist/llm/LiveKitRealtimeAdapter.d.ts +99 -0
  55. package/dist/llm/LiveKitRealtimeAdapter.d.ts.map +1 -0
  56. package/dist/llm/LiveKitRealtimeAdapter.js +206 -0
  57. package/dist/llm/LiveKitRealtimeAdapter.js.map +1 -0
  58. package/dist/metrics/bridge.d.ts +35 -0
  59. package/dist/metrics/bridge.d.ts.map +1 -0
  60. package/dist/metrics/bridge.js +89 -0
  61. package/dist/metrics/bridge.js.map +1 -0
  62. package/dist/metrics/index.d.ts +3 -0
  63. package/dist/metrics/index.d.ts.map +1 -0
  64. package/dist/metrics/index.js +2 -0
  65. package/dist/metrics/index.js.map +1 -0
  66. package/dist/metrics/types.d.ts +84 -0
  67. package/dist/metrics/types.d.ts.map +1 -0
  68. package/dist/metrics/types.js +22 -0
  69. package/dist/metrics/types.js.map +1 -0
  70. package/dist/recording/index.d.ts +4 -0
  71. package/dist/recording/index.d.ts.map +1 -0
  72. package/dist/recording/index.js +3 -0
  73. package/dist/recording/index.js.map +1 -0
  74. package/dist/recording/manager.d.ts +14 -0
  75. package/dist/recording/manager.d.ts.map +1 -0
  76. package/dist/recording/manager.js +80 -0
  77. package/dist/recording/manager.js.map +1 -0
  78. package/dist/recording/s3_adapter.d.ts +26 -0
  79. package/dist/recording/s3_adapter.d.ts.map +1 -0
  80. package/dist/recording/s3_adapter.js +120 -0
  81. package/dist/recording/s3_adapter.js.map +1 -0
  82. package/dist/recording/storage.d.ts +19 -0
  83. package/dist/recording/storage.d.ts.map +1 -0
  84. package/dist/recording/storage.js +2 -0
  85. package/dist/recording/storage.js.map +1 -0
  86. package/dist/session/AriaFlowLivekitSession.d.ts +50 -0
  87. package/dist/session/AriaFlowLivekitSession.d.ts.map +1 -0
  88. package/dist/session/AriaFlowLivekitSession.js +85 -0
  89. package/dist/session/AriaFlowLivekitSession.js.map +1 -0
  90. package/dist/session/AriaFlowVoiceSession.d.ts +71 -0
  91. package/dist/session/AriaFlowVoiceSession.d.ts.map +1 -0
  92. package/dist/session/AriaFlowVoiceSession.js +105 -0
  93. package/dist/session/AriaFlowVoiceSession.js.map +1 -0
  94. package/dist/session/createAriaFlowSession.d.ts +21 -0
  95. package/dist/session/createAriaFlowSession.d.ts.map +1 -0
  96. package/dist/session/createAriaFlowSession.js +8 -0
  97. package/dist/session/createAriaFlowSession.js.map +1 -0
  98. package/dist/session/createAriaVoicePipeline.d.ts +29 -0
  99. package/dist/session/createAriaVoicePipeline.d.ts.map +1 -0
  100. package/dist/session/createAriaVoicePipeline.js +28 -0
  101. package/dist/session/createAriaVoicePipeline.js.map +1 -0
  102. package/dist/session/voice_defaults.d.ts +34 -0
  103. package/dist/session/voice_defaults.d.ts.map +1 -0
  104. package/dist/session/voice_defaults.js +42 -0
  105. package/dist/session/voice_defaults.js.map +1 -0
  106. package/dist/session_manager.d.ts +42 -0
  107. package/dist/session_manager.d.ts.map +1 -0
  108. package/dist/session_manager.js +97 -0
  109. package/dist/session_manager.js.map +1 -0
  110. package/dist/transport_adapter.d.ts +19 -0
  111. package/dist/transport_adapter.d.ts.map +1 -0
  112. package/dist/transport_adapter.js +10 -0
  113. package/dist/transport_adapter.js.map +1 -0
  114. package/dist/turn_detection/eou_detector.d.ts +93 -0
  115. package/dist/turn_detection/eou_detector.d.ts.map +1 -0
  116. package/dist/turn_detection/eou_detector.js +190 -0
  117. package/dist/turn_detection/eou_detector.js.map +1 -0
  118. package/dist/turn_detection/eou_text_normalizer.d.ts +9 -0
  119. package/dist/turn_detection/eou_text_normalizer.d.ts.map +1 -0
  120. package/dist/turn_detection/eou_text_normalizer.js +17 -0
  121. package/dist/turn_detection/eou_text_normalizer.js.map +1 -0
  122. package/dist/turn_detection/eou_turn_detector_adapter.d.ts +40 -0
  123. package/dist/turn_detection/eou_turn_detector_adapter.d.ts.map +1 -0
  124. package/dist/turn_detection/eou_turn_detector_adapter.js +54 -0
  125. package/dist/turn_detection/eou_turn_detector_adapter.js.map +1 -0
  126. package/dist/turn_detection/index.d.ts +7 -0
  127. package/dist/turn_detection/index.d.ts.map +1 -0
  128. package/dist/turn_detection/index.js +8 -0
  129. package/dist/turn_detection/index.js.map +1 -0
  130. package/dist/turn_detection/llm_turn_marker_prompt.d.ts +13 -0
  131. package/dist/turn_detection/llm_turn_marker_prompt.d.ts.map +1 -0
  132. package/dist/turn_detection/llm_turn_marker_prompt.js +39 -0
  133. package/dist/turn_detection/llm_turn_marker_prompt.js.map +1 -0
  134. package/dist/turn_detection/llm_turn_markers.d.ts +57 -0
  135. package/dist/turn_detection/llm_turn_markers.d.ts.map +1 -0
  136. package/dist/turn_detection/llm_turn_markers.js +79 -0
  137. package/dist/turn_detection/llm_turn_markers.js.map +1 -0
  138. package/dist/turn_detection/turn_detector.d.ts +72 -0
  139. package/dist/turn_detection/turn_detector.d.ts.map +1 -0
  140. package/dist/turn_detection/turn_detector.js +84 -0
  141. package/dist/turn_detection/turn_detector.js.map +1 -0
  142. package/dist/turn_detection/vad_loader.d.ts +13 -0
  143. package/dist/turn_detection/vad_loader.d.ts.map +1 -0
  144. package/dist/turn_detection/vad_loader.js +34 -0
  145. package/dist/turn_detection/vad_loader.js.map +1 -0
  146. package/dist/types.d.ts +22 -0
  147. package/dist/types.d.ts.map +1 -0
  148. package/dist/types.js +9 -0
  149. package/dist/types.js.map +1 -0
  150. package/dist/utils/resample.d.ts +26 -0
  151. package/dist/utils/resample.d.ts.map +1 -0
  152. package/dist/utils/resample.js +48 -0
  153. package/dist/utils/resample.js.map +1 -0
  154. package/package.json +65 -0
package/README.md ADDED
@@ -0,0 +1,155 @@
1
+ # @ariaflow/livekit-plugin
2
+
3
+ AriaFlow plugin for [LiveKit Agents](https://docs.livekit.io/agents/) — connects AriaFlow Runtime to LiveKit's voice infrastructure for building production voice agents.
4
+
5
+ ## Features
6
+
7
+ - **Runtime Adapter** — wraps AriaFlow Runtime as a LiveKit LLM provider (`AriaRuntimeLLMAdapter`)
8
+ - **Voice Sessions** — `AriaFlowVoiceSession` (WebSocket) and `AriaFlowLivekitSession` (LiveKit rooms)
9
+ - **Two-Layer Turn Detection** — Silero VAD + EOU text model + LLM turn markers
10
+ - **Gemini STT/TTS** — Google Gemini Live speech-to-text and text-to-speech
11
+ - **Filler Coordinator** — audio filler management during tool execution
12
+ - **Recording** — session recording with pluggable storage adapters
13
+ - **Codec Utilities** — G.711 (PCMU/PCMA) encode/decode, resampling
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ bun add @ariaflow/livekit-plugin
19
+ ```
20
+
21
+ Peer dependencies:
22
+
23
+ ```bash
24
+ bun add @livekit/agents @livekit/rtc-node @ariaflowagents/core
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ```typescript
30
+ import { WebSocketAgentServer } from '@ariaflow/livekit-plugin-transport-ws';
31
+ import { AriaFlowVoiceSession, TurnDetector } from '@ariaflow/livekit-plugin';
32
+ import { GeminiLiveSTT, GeminiLiveTTS } from '@ariaflow/livekit-plugin/gemini';
33
+ import { Runtime } from '@ariaflowagents/core';
34
+ import { openai } from '@ai-sdk/openai';
35
+
36
+ const runtime = new Runtime({
37
+ agents: [{
38
+ id: 'assistant',
39
+ name: 'Voice Assistant',
40
+ model: openai('gpt-4o-mini'),
41
+ prompt: 'You are a helpful voice assistant.',
42
+ }],
43
+ defaultAgentId: 'assistant',
44
+ defaultModel: openai('gpt-4o-mini'),
45
+ });
46
+
47
+ // Load turn detection models once at startup
48
+ const detector = new TurnDetector();
49
+ await detector.initialize();
50
+
51
+ const server = new WebSocketAgentServer({ port: 8080 });
52
+
53
+ server.onConnection(async (transport) => {
54
+ const voiceSession = new AriaFlowVoiceSession({
55
+ runtime,
56
+ stt: new GeminiLiveSTT(),
57
+ tts: new GeminiLiveTTS(),
58
+ vad: detector.vad ?? undefined,
59
+ turnDetection: detector.eouTurnDetector ?? undefined,
60
+ turnMarkerConfig: detector.turnMarkerConfig,
61
+ greeting: 'Hello! How can I help you?',
62
+ });
63
+
64
+ await server.startSession(transport, voiceSession);
65
+ });
66
+
67
+ await server.listen();
68
+ ```
69
+
70
+ ## Turn Detection
71
+
72
+ The plugin implements a two-layer turn detection system:
73
+
74
+ **Layer 1: VAD + EOU text model**
75
+ - Silero VAD detects speech boundaries (start/end of speech)
76
+ - EOU (End-of-Utterance) ONNX model predicts whether the transcript looks like a complete turn
77
+ - These run at the audio/STT level inside LiveKit's `AgentSession`
78
+
79
+ **Layer 2: LLM turn markers**
80
+ - The LLM is instructed to prefix responses with a Unicode marker indicating turn completeness
81
+ - `✓` — user's turn is complete, respond normally
82
+ - `○` — user will likely continue shortly, suppress response
83
+ - `◐` — user needs more time to think, suppress and wait longer
84
+
85
+ ```typescript
86
+ const detector = new TurnDetector({
87
+ // Disable individual layers:
88
+ // disableVAD: true,
89
+ // disableEOU: true,
90
+
91
+ // Custom marker config:
92
+ turnMarkerConfig: {
93
+ enabled: true,
94
+ incompleteShortWaitMs: 5000,
95
+ incompleteLongWaitMs: 10000,
96
+ },
97
+ });
98
+ await detector.initialize();
99
+ ```
100
+
101
+ ## Exports
102
+
103
+ | Export Path | Contents |
104
+ |-------------|----------|
105
+ | `@ariaflow/livekit-plugin` | Core: sessions, LLM adapter, turn detection, transport, codecs |
106
+ | `@ariaflow/livekit-plugin/gemini` | Gemini Live STT/TTS |
107
+ | `@ariaflow/livekit-plugin/recording` | Recording manager and storage adapters |
108
+ | `@ariaflow/livekit-plugin/codec/g711` | G.711 PCMU/PCMA encode/decode |
109
+ | `@ariaflow/livekit-plugin/utils/resample` | Audio resampling utilities |
110
+
111
+ ## Examples
112
+
113
+ See [`examples/`](./examples/) for runnable examples:
114
+
115
+ - **basic_voice_agent.ts** — minimal agent with a tool
116
+ - **multi_agent_handoff.ts** — router + game agent handoff
117
+ - **restaurant_agent.ts** — 4-agent restaurant system
118
+ - **turn_detection_demo.ts** — turn detection configuration
119
+ - **livekit_room_agent.ts** — LiveKit room (WebRTC) agent
120
+ - **livekit_room_with_tools.ts** — room agent with tools
121
+
122
+ ## Changelog
123
+
124
+ ### 0.1.0
125
+
126
+ **Turn Detection** (RFC-011, RFC-012)
127
+ - Added two-layer turn detection system (`src/turn_detection/`)
128
+ - `TurnDetector` — orchestrator that loads VAD and EOU models in parallel
129
+ - `loadSileroVAD()` — process-level singleton loader for Silero VAD with concurrent-call deduplication
130
+ - `EOUDetector` — standalone port of LiveKit's EOU ONNX model, no `getJobContext()` dependency
131
+ - `EOUTurnDetectorAdapter` — bridges `EOUDetector` to LiveKit's `_TurnDetector` interface
132
+ - `detectTurnMarker()` / `stripMarker()` — LLM turn marker detection and stripping
133
+ - `TURN_MARKER_SYSTEM_PROMPT` — system prompt fragment for LLM marker compliance
134
+ - Modified `AriaRuntimeLLMAdapter` to intercept turn markers in LLM responses when configured
135
+ - Modified `AriaFlowVoiceSession` to accept `turnMarkerConfig` option
136
+ - Modified `AriaFlowLivekitSession` to accept `turnMarkerConfig` option
137
+ - Added dependencies: `@livekit/agents-plugin-silero`, `onnxruntime-node`, `@huggingface/hub`, `@huggingface/transformers`
138
+
139
+ **Examples**
140
+ - Added `basic_voice_agent.ts` — minimal voice agent with turn detection
141
+ - Added `multi_agent_handoff.ts` — multi-agent routing demo
142
+ - Added `restaurant_agent.ts` — 4-agent restaurant system
143
+ - Added `turn_detection_demo.ts` — turn detection configuration demo
144
+ - Added `livekit_room_with_tools.ts` — room-based agent with tools
145
+ - Updated `livekit_room_agent.ts` — added turn detection, migrated to `ServerOptions`/`defineAgent` API
146
+
147
+ **Initial Release**
148
+ - `AriaRuntimeLLMAdapter` — wraps AriaFlow Runtime as a LiveKit LLM provider
149
+ - `AriaFlowVoiceSession` — WebSocket-based voice session
150
+ - `AriaFlowLivekitSession` — LiveKit room-based voice session
151
+ - `FillerCoordinator` — audio filler management during tool execution
152
+ - Gemini Live STT/TTS integration
153
+ - Recording with pluggable storage adapters (S3)
154
+ - G.711 codec utilities (PCMU/PCMA)
155
+ - Audio resampling utilities
@@ -0,0 +1,11 @@
1
+ import { voice } from '@livekit/agents';
2
+ import type { AriaRuntimeLLMAdapter } from '../llm/AriaRuntimeLLMAdapter.js';
3
+ export interface AriaFlowAgentOptions {
4
+ greeting?: string | null;
5
+ }
6
+ export declare class AriaFlowAgent extends voice.Agent {
7
+ #private;
8
+ constructor(ariaLlm: AriaRuntimeLLMAdapter, opts?: AriaFlowAgentOptions);
9
+ onEnter(): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=AriaFlowAgent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AriaFlowAgent.d.ts","sourceRoot":"","sources":["../../src/agent/AriaFlowAgent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAE7E,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,qBAAa,aAAc,SAAQ,KAAK,CAAC,KAAK;;gBAGhC,OAAO,EAAE,qBAAqB,EAAE,IAAI,GAAE,oBAAyB;IASrE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAW/B"}
@@ -0,0 +1,22 @@
1
+ import { voice } from '@livekit/agents';
2
+ export class AriaFlowAgent extends voice.Agent {
3
+ #opts;
4
+ constructor(ariaLlm, opts = {}) {
5
+ super({
6
+ instructions: 'AriaFlow-managed voice agent',
7
+ llm: ariaLlm,
8
+ });
9
+ this.#opts = opts;
10
+ }
11
+ async onEnter() {
12
+ if (this.#opts.greeting === null) {
13
+ return;
14
+ }
15
+ const greeting = this.#opts.greeting ?? "Hello! I'm your AI assistant. How can I help?";
16
+ this.session.say(greeting, {
17
+ allowInterruptions: true,
18
+ addToChatCtx: false,
19
+ });
20
+ }
21
+ }
22
+ //# sourceMappingURL=AriaFlowAgent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AriaFlowAgent.js","sourceRoot":"","sources":["../../src/agent/AriaFlowAgent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAOxC,MAAM,OAAO,aAAc,SAAQ,KAAK,CAAC,KAAK;IAC5C,KAAK,CAAuB;IAE5B,YAAY,OAA8B,EAAE,OAA6B,EAAE;QACzE,KAAK,CAAC;YACJ,YAAY,EAAE,8BAA8B;YAC5C,GAAG,EAAE,OAAO;SACb,CAAC,CAAC;QAEH,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YACjC,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,+CAA+C,CAAC;QACxF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE;YACzB,kBAAkB,EAAE,IAAI;YACxB,YAAY,EAAE,KAAK;SACpB,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,29 @@
1
+ import { AudioFrame } from './audio_frame.js';
2
+ /**
3
+ * Accumulates raw PCM bytes and produces AudioFrame objects when enough
4
+ * data has been buffered for a complete frame.
5
+ *
6
+ * This is the primary utility for transport adapters that receive audio
7
+ * as a continuous byte stream (WebSocket binary messages, RTP packets,
8
+ * HTTP chunked transfer, etc.).
9
+ *
10
+ * The default frame size is 100ms of audio (sampleRate / 10 samples).
11
+ */
12
+ export declare class AudioByteStream {
13
+ private sampleRate;
14
+ private numChannels;
15
+ private bytesPerFrame;
16
+ private buf;
17
+ constructor(sampleRate: number, numChannels: number, samplesPerChannel?: number | null);
18
+ /**
19
+ * Write raw PCM bytes. Returns zero or more complete AudioFrame objects.
20
+ * Incomplete data is buffered internally.
21
+ */
22
+ write(data: ArrayBuffer): AudioFrame[];
23
+ /**
24
+ * Flush remaining buffered data as a final (potentially short) frame.
25
+ * Returns empty array if remaining buffer is not sample-aligned.
26
+ */
27
+ flush(): AudioFrame[];
28
+ }
29
+ //# sourceMappingURL=audio_byte_stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio_byte_stream.d.ts","sourceRoot":"","sources":["../src/audio_byte_stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C;;;;;;;;;GASG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,GAAG,CAAY;gBAGrB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,iBAAiB,GAAE,MAAM,GAAG,IAAW;IAazC;;;OAGG;IACH,KAAK,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,EAAE;IAyBtC;;;OAGG;IACH,KAAK,IAAI,UAAU,EAAE;CAqBtB"}
@@ -0,0 +1,62 @@
1
+ import { AudioFrame } from './audio_frame.js';
2
+ /**
3
+ * Accumulates raw PCM bytes and produces AudioFrame objects when enough
4
+ * data has been buffered for a complete frame.
5
+ *
6
+ * This is the primary utility for transport adapters that receive audio
7
+ * as a continuous byte stream (WebSocket binary messages, RTP packets,
8
+ * HTTP chunked transfer, etc.).
9
+ *
10
+ * The default frame size is 100ms of audio (sampleRate / 10 samples).
11
+ */
12
+ export class AudioByteStream {
13
+ sampleRate;
14
+ numChannels;
15
+ bytesPerFrame;
16
+ buf;
17
+ constructor(sampleRate, numChannels, samplesPerChannel = null) {
18
+ this.sampleRate = sampleRate;
19
+ this.numChannels = numChannels;
20
+ if (samplesPerChannel === null) {
21
+ samplesPerChannel = Math.floor(sampleRate / 10);
22
+ }
23
+ this.bytesPerFrame = numChannels * samplesPerChannel * 2;
24
+ this.buf = new Int8Array();
25
+ }
26
+ /**
27
+ * Write raw PCM bytes. Returns zero or more complete AudioFrame objects.
28
+ * Incomplete data is buffered internally.
29
+ */
30
+ write(data) {
31
+ const incoming = new Int8Array(data);
32
+ const next = new Int8Array(this.buf.length + incoming.length);
33
+ next.set(this.buf, 0);
34
+ next.set(incoming, this.buf.length);
35
+ this.buf = next;
36
+ const frames = [];
37
+ while (this.buf.length >= this.bytesPerFrame) {
38
+ const frameData = this.buf.slice(0, this.bytesPerFrame);
39
+ this.buf = this.buf.slice(this.bytesPerFrame);
40
+ frames.push(new AudioFrame(new Int16Array(frameData.buffer), this.sampleRate, this.numChannels, frameData.length / (2 * this.numChannels)));
41
+ }
42
+ return frames;
43
+ }
44
+ /**
45
+ * Flush remaining buffered data as a final (potentially short) frame.
46
+ * Returns empty array if remaining buffer is not sample-aligned.
47
+ */
48
+ flush() {
49
+ if (this.buf.length === 0) {
50
+ return [];
51
+ }
52
+ if (this.buf.length % (2 * this.numChannels) !== 0) {
53
+ return [];
54
+ }
55
+ const frames = [
56
+ new AudioFrame(new Int16Array(this.buf.buffer), this.sampleRate, this.numChannels, this.buf.length / (2 * this.numChannels)),
57
+ ];
58
+ this.buf = new Int8Array();
59
+ return frames;
60
+ }
61
+ }
62
+ //# sourceMappingURL=audio_byte_stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio_byte_stream.js","sourceRoot":"","sources":["../src/audio_byte_stream.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C;;;;;;;;;GASG;AACH,MAAM,OAAO,eAAe;IAClB,UAAU,CAAS;IACnB,WAAW,CAAS;IACpB,aAAa,CAAS;IACtB,GAAG,CAAY;IAEvB,YACE,UAAkB,EAClB,WAAmB,EACnB,oBAAmC,IAAI;QAEvC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAE/B,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;YAC/B,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,GAAG,EAAE,CAAC,CAAC;QAClD,CAAC;QAED,IAAI,CAAC,aAAa,GAAG,WAAW,GAAG,iBAAiB,GAAG,CAAC,CAAC;QACzD,IAAI,CAAC,GAAG,GAAG,IAAI,SAAS,EAAE,CAAC;IAC7B,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,IAAiB;QACrB,MAAM,QAAQ,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC9D,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;QAEhB,MAAM,MAAM,GAAiB,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;YACxD,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAE9C,MAAM,CAAC,IAAI,CACT,IAAI,UAAU,CACZ,IAAI,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,EAChC,IAAI,CAAC,UAAU,EACf,IAAI,CAAC,WAAW,EAChB,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAC1C,CACF,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,KAAK;QACH,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;YACnD,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,MAAM,GAAG;YACb,IAAI,UAAU,CACZ,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAC/B,IAAI,CAAC,UAAU,EACf,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CACzC;SACF,CAAC;QAEF,IAAI,CAAC,GAAG,GAAG,IAAI,SAAS,EAAE,CAAC;QAC3B,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
@@ -0,0 +1,2 @@
1
+ export { AudioFrame } from '@livekit/rtc-node';
2
+ //# sourceMappingURL=audio_frame.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio_frame.d.ts","sourceRoot":"","sources":["../src/audio_frame.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,6 @@
1
+ // Re-export AudioFrame from @livekit/rtc-node.
2
+ // This single indirection point isolates all downstream packages from the
3
+ // native dependency. When a pure-JS AudioFrame shim is available, only
4
+ // this file needs to change.
5
+ export { AudioFrame } from '@livekit/rtc-node';
6
+ //# sourceMappingURL=audio_frame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio_frame.js","sourceRoot":"","sources":["../src/audio_frame.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,0EAA0E;AAC1E,uEAAuE;AACvE,6BAA6B;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,14 @@
1
+ export interface Codec {
2
+ readonly name: string;
3
+ readonly payloadType: number;
4
+ readonly sampleRate: number;
5
+ readonly channels: number;
6
+ decode(input: Uint8Array): Int16Array;
7
+ encode(input: Int16Array): Uint8Array;
8
+ }
9
+ export declare const PCMU: Codec;
10
+ export declare const PCMA: Codec;
11
+ /** Convenience wrappers matching the Twilio transport API surface. */
12
+ export declare function mulawEncodeArray(pcm: Int16Array): Uint8Array;
13
+ export declare function mulawDecodeArray(mulawBytes: Uint8Array): Int16Array;
14
+ //# sourceMappingURL=g711.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"g711.d.ts","sourceRoot":"","sources":["../../src/codec/g711.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,KAAK;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAAC;IACtC,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAAC;CACvC;AAED,eAAO,MAAM,IAAI,EAAE,KAWlB,CAAC;AAEF,eAAO,MAAM,IAAI,EAAE,KAWlB,CAAC;AAEF,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,UAAU,GAAG,UAAU,CAE5D;AAED,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,UAAU,GAAG,UAAU,CAEnE"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * G.711 mu-law and A-law codec (CCITT/ITU-T compliant).
3
+ *
4
+ * Delegates to the `alawmulaw` npm package which implements the standard
5
+ * CCITT G.711 algorithm with BIAS=0x84 (132). This matches the Sun
6
+ * Microsystems / Columbia University reference implementation exactly
7
+ * across all 65536 Int16 input values.
8
+ *
9
+ * Previous implementation used BIAS=33 (the 14-bit variant mistakenly
10
+ * applied in 16-bit context), producing 16503 encode mismatches and
11
+ * 50x worse roundtrip error vs the CCITT reference. See LIBRARY-RESEARCH.md.
12
+ */
13
+ // `alawmulaw` publishes a CJS/UMD `main` entry and an ESM `module` entry.
14
+ // Node's ESM resolver ignores `module`, so importing from the package root
15
+ // resolves to the CJS bundle and breaks named imports under `tsx`.
16
+ // Import the ESM submodules directly to keep this codec usable in both Node
17
+ // ESM test runners and the existing Bun workspace.
18
+ import * as mulaw from 'alawmulaw/lib/mulaw.js';
19
+ import * as alaw from 'alawmulaw/lib/alaw.js';
20
+ export const PCMU = {
21
+ name: 'PCMU',
22
+ payloadType: 0,
23
+ sampleRate: 8000,
24
+ channels: 1,
25
+ decode(input) {
26
+ return mulaw.decode(input);
27
+ },
28
+ encode(input) {
29
+ return mulaw.encode(input);
30
+ },
31
+ };
32
+ export const PCMA = {
33
+ name: 'PCMA',
34
+ payloadType: 8,
35
+ sampleRate: 8000,
36
+ channels: 1,
37
+ decode(input) {
38
+ return alaw.decode(input);
39
+ },
40
+ encode(input) {
41
+ return alaw.encode(input);
42
+ },
43
+ };
44
+ /** Convenience wrappers matching the Twilio transport API surface. */
45
+ export function mulawEncodeArray(pcm) {
46
+ return PCMU.encode(pcm);
47
+ }
48
+ export function mulawDecodeArray(mulawBytes) {
49
+ return PCMU.decode(mulawBytes);
50
+ }
51
+ //# sourceMappingURL=g711.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"g711.js","sourceRoot":"","sources":["../../src/codec/g711.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,0EAA0E;AAC1E,2EAA2E;AAC3E,mEAAmE;AACnE,4EAA4E;AAC5E,mDAAmD;AACnD,OAAO,KAAK,KAAK,MAAM,wBAAwB,CAAC;AAChD,OAAO,KAAK,IAAI,MAAM,uBAAuB,CAAC;AAW9C,MAAM,CAAC,MAAM,IAAI,GAAU;IACzB,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,CAAC;IACd,UAAU,EAAE,IAAI;IAChB,QAAQ,EAAE,CAAC;IACX,MAAM,CAAC,KAAiB;QACtB,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,MAAM,CAAC,KAAiB;QACtB,OAAO,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,IAAI,GAAU;IACzB,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,CAAC;IACd,UAAU,EAAE,IAAI;IAChB,QAAQ,EAAE,CAAC;IACX,MAAM,CAAC,KAAiB;QACtB,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IACD,MAAM,CAAC,KAAiB;QACtB,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;CACF,CAAC;AAEF,sEAAsE;AACtE,MAAM,UAAU,gBAAgB,CAAC,GAAe;IAC9C,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,UAAsB;IACrD,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,14 @@
1
+ export declare class TransportError extends Error {
2
+ readonly cause?: Error | undefined;
3
+ constructor(message: string, cause?: Error | undefined);
4
+ }
5
+ export declare class TransportDisconnectedError extends TransportError {
6
+ constructor(message?: string, cause?: Error);
7
+ }
8
+ export declare class TransportProtocolError extends TransportError {
9
+ constructor(message: string, cause?: Error);
10
+ }
11
+ export declare class AudioConfigError extends TransportError {
12
+ constructor(message: string, cause?: Error);
13
+ }
14
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,cAAe,SAAQ,KAAK;aAGrB,KAAK,CAAC,EAAE,KAAK;gBAD7B,OAAO,EAAE,MAAM,EACC,KAAK,CAAC,EAAE,KAAK,YAAA;CAKhC;AAED,qBAAa,0BAA2B,SAAQ,cAAc;gBAChD,OAAO,GAAE,MAAsC,EAAE,KAAK,CAAC,EAAE,KAAK;CAI3E;AAED,qBAAa,sBAAuB,SAAQ,cAAc;gBAC5C,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAI3C;AAED,qBAAa,gBAAiB,SAAQ,cAAc;gBACtC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAI3C"}
package/dist/errors.js ADDED
@@ -0,0 +1,27 @@
1
+ export class TransportError extends Error {
2
+ cause;
3
+ constructor(message, cause) {
4
+ super(message);
5
+ this.cause = cause;
6
+ this.name = 'TransportError';
7
+ }
8
+ }
9
+ export class TransportDisconnectedError extends TransportError {
10
+ constructor(message = 'Transport connection closed', cause) {
11
+ super(message, cause);
12
+ this.name = 'TransportDisconnectedError';
13
+ }
14
+ }
15
+ export class TransportProtocolError extends TransportError {
16
+ constructor(message, cause) {
17
+ super(message, cause);
18
+ this.name = 'TransportProtocolError';
19
+ }
20
+ }
21
+ export class AudioConfigError extends TransportError {
22
+ constructor(message, cause) {
23
+ super(message, cause);
24
+ this.name = 'AudioConfigError';
25
+ }
26
+ }
27
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,cAAe,SAAQ,KAAK;IAGrB;IAFlB,YACE,OAAe,EACC,KAAa;QAE7B,KAAK,CAAC,OAAO,CAAC,CAAC;QAFC,UAAK,GAAL,KAAK,CAAQ;QAG7B,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED,MAAM,OAAO,0BAA2B,SAAQ,cAAc;IAC5D,YAAY,UAAkB,6BAA6B,EAAE,KAAa;QACxE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC3C,CAAC;CACF;AAED,MAAM,OAAO,sBAAuB,SAAQ,cAAc;IACxD,YAAY,OAAe,EAAE,KAAa;QACxC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAED,MAAM,OAAO,gBAAiB,SAAQ,cAAc;IAClD,YAAY,OAAe,EAAE,KAAa;QACxC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACtB,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ import type { voice } from '@livekit/agents';
2
+ export declare class FillerCoordinator {
3
+ #private;
4
+ speakFiller(session: voice.AgentSession, filler: string): Promise<void>;
5
+ waitForActiveFillers(): Promise<void>;
6
+ }
7
+ //# sourceMappingURL=FillerCoordinator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FillerCoordinator.d.ts","sourceRoot":"","sources":["../../src/filler/FillerCoordinator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAE7C,qBAAa,iBAAiB;;IAGtB,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBvE,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;CAO5C"}
@@ -0,0 +1,29 @@
1
+ export class FillerCoordinator {
2
+ #activeFillers = new Set();
3
+ async speakFiller(session, filler) {
4
+ const text = filler.trim();
5
+ if (!text) {
6
+ return;
7
+ }
8
+ const handle = session.say(text, {
9
+ allowInterruptions: true,
10
+ addToChatCtx: false,
11
+ });
12
+ const playout = handle
13
+ .waitForPlayout()
14
+ .catch(() => {
15
+ // Barge-in interruptions are expected and should not fail the pipeline.
16
+ })
17
+ .finally(() => {
18
+ this.#activeFillers.delete(playout);
19
+ });
20
+ this.#activeFillers.add(playout);
21
+ }
22
+ async waitForActiveFillers() {
23
+ if (this.#activeFillers.size === 0) {
24
+ return;
25
+ }
26
+ await Promise.allSettled([...this.#activeFillers]);
27
+ }
28
+ }
29
+ //# sourceMappingURL=FillerCoordinator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FillerCoordinator.js","sourceRoot":"","sources":["../../src/filler/FillerCoordinator.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,iBAAiB;IAC5B,cAAc,GAAuB,IAAI,GAAG,EAAE,CAAC;IAE/C,KAAK,CAAC,WAAW,CAAC,OAA2B,EAAE,MAAc;QAC3D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE;YAC/B,kBAAkB,EAAE,IAAI;YACxB,YAAY,EAAE,KAAK;SACpB,CAAC,CAAC;QAEH,MAAM,OAAO,GAAG,MAAM;aACnB,cAAc,EAAE;aAChB,KAAK,CAAC,GAAG,EAAE;YACV,wEAAwE;QAC1E,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACZ,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEL,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,oBAAoB;QACxB,IAAI,IAAI,CAAC,cAAc,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO;QACT,CAAC;QAED,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;IACrD,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ export interface ParsedFillerResponse {
2
+ transcript: string;
3
+ filler: string;
4
+ parsedAsJson: boolean;
5
+ }
6
+ export interface BuildFillerInstructionOptions {
7
+ baseInstruction?: string;
8
+ fillerPrompt?: string;
9
+ fillerMinTranscriptLength: number;
10
+ }
11
+ export declare const DEFAULT_FILLER_PROMPT: string;
12
+ export declare function buildFillerInstruction(opts: BuildFillerInstructionOptions): string;
13
+ export declare function parseFillerResponse(raw: string): ParsedFillerResponse;
14
+ //# sourceMappingURL=filler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filler.d.ts","sourceRoot":"","sources":["../../src/gemini/filler.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,6BAA6B;IAC5C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yBAAyB,EAAE,MAAM,CAAC;CACnC;AAED,eAAO,MAAM,qBAAqB,QAStB,CAAC;AAEb,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,6BAA6B,GAAG,MAAM,CAWlF;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,CA2BrE"}
@@ -0,0 +1,48 @@
1
+ export const DEFAULT_FILLER_PROMPT = [
2
+ 'You are a speech transcription service for a voice assistant.',
3
+ 'Return STRICT JSON only in this schema:',
4
+ '{"transcript":"<exact user speech>","filler":"<short natural acknowledgement>"}',
5
+ 'Rules for filler:',
6
+ '- Keep it to one short sentence.',
7
+ '- Do not invent facts or outcomes.',
8
+ '- Use empty string for very short replies (yes/no/okay).',
9
+ '- Keep tone conversational and neutral.',
10
+ ].join('\n');
11
+ export function buildFillerInstruction(opts) {
12
+ const prefix = opts.baseInstruction?.trim();
13
+ const prompt = (opts.fillerPrompt?.trim() || DEFAULT_FILLER_PROMPT).trim();
14
+ return [
15
+ prefix,
16
+ prompt,
17
+ `Emit empty filler when transcript length is below ${opts.fillerMinTranscriptLength} characters.`,
18
+ ]
19
+ .filter(Boolean)
20
+ .join('\n\n');
21
+ }
22
+ export function parseFillerResponse(raw) {
23
+ const text = raw.trim();
24
+ if (!text) {
25
+ return { transcript: '', filler: '', parsedAsJson: false };
26
+ }
27
+ try {
28
+ const parsed = JSON.parse(text);
29
+ const transcript = typeof parsed.transcript === 'string' ? parsed.transcript.trim() : '';
30
+ const filler = typeof parsed.filler === 'string' ? parsed.filler.trim() : '';
31
+ if (!transcript) {
32
+ return { transcript: text, filler: '', parsedAsJson: false };
33
+ }
34
+ return {
35
+ transcript,
36
+ filler,
37
+ parsedAsJson: true,
38
+ };
39
+ }
40
+ catch {
41
+ return {
42
+ transcript: text,
43
+ filler: '',
44
+ parsedAsJson: false,
45
+ };
46
+ }
47
+ }
48
+ //# sourceMappingURL=filler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filler.js","sourceRoot":"","sources":["../../src/gemini/filler.ts"],"names":[],"mappings":"AAYA,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,+DAA+D;IAC/D,yCAAyC;IACzC,iFAAiF;IACjF,mBAAmB;IACnB,kCAAkC;IAClC,oCAAoC;IACpC,0DAA0D;IAC1D,yCAAyC;CAC1C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,MAAM,UAAU,sBAAsB,CAAC,IAAmC;IACxE,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,IAAI,EAAE,CAAC;IAC5C,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,qBAAqB,CAAC,CAAC,IAAI,EAAE,CAAC;IAE3E,OAAO;QACL,MAAM;QACN,MAAM;QACN,qDAAqD,IAAI,CAAC,yBAAyB,cAAc;KAClG;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC7C,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACxB,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IAC7D,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA+C,CAAC;QAC9E,MAAM,UAAU,GAAG,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzF,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAE7E,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;QAC/D,CAAC;QAED,OAAO;YACL,UAAU;YACV,MAAM;YACN,YAAY,EAAE,IAAI;SACnB,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,UAAU,EAAE,IAAI;YAChB,MAAM,EAAE,EAAE;YACV,YAAY,EAAE,KAAK;SACpB,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { GeminiLiveSTT, GeminiLiveSpeechStream, type GeminiLiveSTTOptions, type GeminiFillerEvent, type GeminiFillerPayload, type GeminiLiveClient, type GeminiLiveSession, } from './stt.js';
2
+ export { GeminiLiveTTS, GeminiLiveSynthesizeStream, GeminiLiveChunkedStream, type GeminiLiveTTSOptions, type GeminiVoice, } from './tts.js';
3
+ export { DEFAULT_FILLER_PROMPT, buildFillerInstruction, parseFillerResponse, type ParsedFillerResponse, type BuildFillerInstructionOptions, } from './filler.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/gemini/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,GACvB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,aAAa,EACb,0BAA0B,EAC1B,uBAAuB,EACvB,KAAK,oBAAoB,EACzB,KAAK,WAAW,GACjB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,KAAK,oBAAoB,EACzB,KAAK,6BAA6B,GACnC,MAAM,aAAa,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { GeminiLiveSTT, GeminiLiveSpeechStream, } from './stt.js';
2
+ export { GeminiLiveTTS, GeminiLiveSynthesizeStream, GeminiLiveChunkedStream, } from './tts.js';
3
+ export { DEFAULT_FILLER_PROMPT, buildFillerInstruction, parseFillerResponse, } from './filler.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gemini/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,sBAAsB,GAMvB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,aAAa,EACb,0BAA0B,EAC1B,uBAAuB,GAGxB,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,GAGpB,MAAM,aAAa,CAAC"}