@livekit/agents 1.0.34 → 1.0.36-dev.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.
- package/dist/cli.cjs.map +1 -1
- package/dist/index.cjs +3 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/inference/api_protos.d.cts +4 -4
- package/dist/inference/api_protos.d.ts +4 -4
- package/dist/inference/interruption/AdaptiveInterruptionDetector.cjs +152 -0
- package/dist/inference/interruption/AdaptiveInterruptionDetector.cjs.map +1 -0
- package/dist/inference/interruption/AdaptiveInterruptionDetector.d.cts +50 -0
- package/dist/inference/interruption/AdaptiveInterruptionDetector.d.ts +50 -0
- package/dist/inference/interruption/AdaptiveInterruptionDetector.d.ts.map +1 -0
- package/dist/inference/interruption/AdaptiveInterruptionDetector.js +125 -0
- package/dist/inference/interruption/AdaptiveInterruptionDetector.js.map +1 -0
- package/dist/inference/interruption/InterruptionStream.cjs +310 -0
- package/dist/inference/interruption/InterruptionStream.cjs.map +1 -0
- package/dist/inference/interruption/InterruptionStream.d.cts +57 -0
- package/dist/inference/interruption/InterruptionStream.d.ts +57 -0
- package/dist/inference/interruption/InterruptionStream.d.ts.map +1 -0
- package/dist/inference/interruption/InterruptionStream.js +288 -0
- package/dist/inference/interruption/InterruptionStream.js.map +1 -0
- package/dist/inference/interruption/defaults.cjs +76 -0
- package/dist/inference/interruption/defaults.cjs.map +1 -0
- package/dist/inference/interruption/defaults.d.cts +14 -0
- package/dist/inference/interruption/defaults.d.ts +14 -0
- package/dist/inference/interruption/defaults.d.ts.map +1 -0
- package/dist/inference/interruption/defaults.js +42 -0
- package/dist/inference/interruption/defaults.js.map +1 -0
- package/dist/inference/interruption/errors.cjs +2 -0
- package/dist/inference/interruption/errors.cjs.map +1 -0
- package/dist/inference/interruption/errors.d.cts +2 -0
- package/dist/inference/interruption/errors.d.ts +2 -0
- package/dist/inference/interruption/errors.d.ts.map +1 -0
- package/dist/inference/interruption/errors.js +1 -0
- package/dist/inference/interruption/errors.js.map +1 -0
- package/dist/inference/interruption/http_transport.cjs +57 -0
- package/dist/inference/interruption/http_transport.cjs.map +1 -0
- package/dist/inference/interruption/http_transport.d.cts +23 -0
- package/dist/inference/interruption/http_transport.d.ts +23 -0
- package/dist/inference/interruption/http_transport.d.ts.map +1 -0
- package/dist/inference/interruption/http_transport.js +33 -0
- package/dist/inference/interruption/http_transport.js.map +1 -0
- package/dist/inference/interruption/index.cjs +34 -0
- package/dist/inference/interruption/index.cjs.map +1 -0
- package/dist/inference/interruption/index.d.cts +5 -0
- package/dist/inference/interruption/index.d.ts +5 -0
- package/dist/inference/interruption/index.d.ts.map +1 -0
- package/dist/inference/interruption/index.js +7 -0
- package/dist/inference/interruption/index.js.map +1 -0
- package/dist/inference/interruption/interruption.cjs +85 -0
- package/dist/inference/interruption/interruption.cjs.map +1 -0
- package/dist/inference/interruption/interruption.d.cts +48 -0
- package/dist/inference/interruption/interruption.d.ts +48 -0
- package/dist/inference/interruption/interruption.d.ts.map +1 -0
- package/dist/inference/interruption/interruption.js +59 -0
- package/dist/inference/interruption/interruption.js.map +1 -0
- package/dist/inference/llm.cjs +30 -3
- package/dist/inference/llm.cjs.map +1 -1
- package/dist/inference/llm.d.cts +3 -1
- package/dist/inference/llm.d.ts +3 -1
- package/dist/inference/llm.d.ts.map +1 -1
- package/dist/inference/llm.js +30 -3
- package/dist/inference/llm.js.map +1 -1
- package/dist/inference/utils.cjs +15 -2
- package/dist/inference/utils.cjs.map +1 -1
- package/dist/inference/utils.d.cts +1 -0
- package/dist/inference/utils.d.ts +1 -0
- package/dist/inference/utils.d.ts.map +1 -1
- package/dist/inference/utils.js +13 -1
- package/dist/inference/utils.js.map +1 -1
- package/dist/inference/utils.test.cjs +20 -0
- package/dist/inference/utils.test.cjs.map +1 -0
- package/dist/inference/utils.test.js +19 -0
- package/dist/inference/utils.test.js.map +1 -0
- package/dist/ipc/inference_proc_executor.cjs.map +1 -1
- package/dist/ipc/job_proc_executor.cjs.map +1 -1
- package/dist/ipc/job_proc_lazy_main.cjs +1 -1
- package/dist/ipc/job_proc_lazy_main.cjs.map +1 -1
- package/dist/ipc/job_proc_lazy_main.js +1 -1
- package/dist/ipc/job_proc_lazy_main.js.map +1 -1
- package/dist/llm/chat_context.cjs +20 -2
- package/dist/llm/chat_context.cjs.map +1 -1
- package/dist/llm/chat_context.d.cts +9 -0
- package/dist/llm/chat_context.d.ts +9 -0
- package/dist/llm/chat_context.d.ts.map +1 -1
- package/dist/llm/chat_context.js +20 -2
- package/dist/llm/chat_context.js.map +1 -1
- package/dist/llm/llm.cjs.map +1 -1
- package/dist/llm/llm.d.cts +1 -0
- package/dist/llm/llm.d.ts +1 -0
- package/dist/llm/llm.d.ts.map +1 -1
- package/dist/llm/llm.js.map +1 -1
- package/dist/llm/provider_format/openai.cjs +43 -20
- package/dist/llm/provider_format/openai.cjs.map +1 -1
- package/dist/llm/provider_format/openai.d.ts.map +1 -1
- package/dist/llm/provider_format/openai.js +43 -20
- package/dist/llm/provider_format/openai.js.map +1 -1
- package/dist/llm/provider_format/openai.test.cjs +35 -0
- package/dist/llm/provider_format/openai.test.cjs.map +1 -1
- package/dist/llm/provider_format/openai.test.js +35 -0
- package/dist/llm/provider_format/openai.test.js.map +1 -1
- package/dist/llm/provider_format/utils.cjs +1 -1
- package/dist/llm/provider_format/utils.cjs.map +1 -1
- package/dist/llm/provider_format/utils.d.ts.map +1 -1
- package/dist/llm/provider_format/utils.js +1 -1
- package/dist/llm/provider_format/utils.js.map +1 -1
- package/dist/stream/stream_channel.cjs +3 -0
- package/dist/stream/stream_channel.cjs.map +1 -1
- package/dist/stream/stream_channel.d.cts +3 -2
- package/dist/stream/stream_channel.d.ts +3 -2
- package/dist/stream/stream_channel.d.ts.map +1 -1
- package/dist/stream/stream_channel.js +3 -0
- package/dist/stream/stream_channel.js.map +1 -1
- package/dist/telemetry/trace_types.cjs +15 -0
- package/dist/telemetry/trace_types.cjs.map +1 -1
- package/dist/telemetry/trace_types.d.cts +5 -0
- package/dist/telemetry/trace_types.d.ts +5 -0
- package/dist/telemetry/trace_types.d.ts.map +1 -1
- package/dist/telemetry/trace_types.js +10 -0
- package/dist/telemetry/trace_types.js.map +1 -1
- package/dist/utils/ws_transport.cjs +51 -0
- package/dist/utils/ws_transport.cjs.map +1 -0
- package/dist/utils/ws_transport.d.cts +9 -0
- package/dist/utils/ws_transport.d.ts +9 -0
- package/dist/utils/ws_transport.d.ts.map +1 -0
- package/dist/utils/ws_transport.js +17 -0
- package/dist/utils/ws_transport.js.map +1 -0
- package/dist/utils/ws_transport.test.cjs +212 -0
- package/dist/utils/ws_transport.test.cjs.map +1 -0
- package/dist/utils/ws_transport.test.js +211 -0
- package/dist/utils/ws_transport.test.js.map +1 -0
- package/dist/voice/agent_activity.cjs +49 -0
- package/dist/voice/agent_activity.cjs.map +1 -1
- package/dist/voice/agent_activity.d.cts +14 -0
- package/dist/voice/agent_activity.d.ts +14 -0
- package/dist/voice/agent_activity.d.ts.map +1 -1
- package/dist/voice/agent_activity.js +49 -0
- package/dist/voice/agent_activity.js.map +1 -1
- package/dist/voice/agent_session.cjs +12 -1
- package/dist/voice/agent_session.cjs.map +1 -1
- package/dist/voice/agent_session.d.cts +3 -0
- package/dist/voice/agent_session.d.ts +3 -0
- package/dist/voice/agent_session.d.ts.map +1 -1
- package/dist/voice/agent_session.js +12 -1
- package/dist/voice/agent_session.js.map +1 -1
- package/dist/voice/audio_recognition.cjs +124 -2
- package/dist/voice/audio_recognition.cjs.map +1 -1
- package/dist/voice/audio_recognition.d.cts +32 -1
- package/dist/voice/audio_recognition.d.ts +32 -1
- package/dist/voice/audio_recognition.d.ts.map +1 -1
- package/dist/voice/audio_recognition.js +127 -2
- package/dist/voice/audio_recognition.js.map +1 -1
- package/dist/voice/background_audio.cjs.map +1 -1
- package/dist/voice/generation.cjs +2 -1
- package/dist/voice/generation.cjs.map +1 -1
- package/dist/voice/generation.d.ts.map +1 -1
- package/dist/voice/generation.js +2 -1
- package/dist/voice/generation.js.map +1 -1
- package/package.json +2 -1
- package/src/index.ts +2 -0
- package/src/inference/interruption/AdaptiveInterruptionDetector.ts +166 -0
- package/src/inference/interruption/InterruptionStream.ts +397 -0
- package/src/inference/interruption/defaults.ts +33 -0
- package/src/inference/interruption/errors.ts +0 -0
- package/src/inference/interruption/http_transport.ts +61 -0
- package/src/inference/interruption/index.ts +4 -0
- package/src/inference/interruption/interruption.ts +88 -0
- package/src/inference/llm.ts +42 -3
- package/src/inference/utils.test.ts +31 -0
- package/src/inference/utils.ts +15 -0
- package/src/ipc/job_proc_lazy_main.ts +1 -1
- package/src/llm/chat_context.ts +32 -2
- package/src/llm/llm.ts +1 -0
- package/src/llm/provider_format/openai.test.ts +40 -0
- package/src/llm/provider_format/openai.ts +46 -19
- package/src/llm/provider_format/utils.ts +5 -1
- package/src/stream/stream_channel.ts +6 -2
- package/src/telemetry/trace_types.ts +7 -0
- package/src/utils/ws_transport.test.ts +282 -0
- package/src/utils/ws_transport.ts +22 -0
- package/src/voice/agent_activity.ts +61 -0
- package/src/voice/agent_session.ts +22 -2
- package/src/voice/audio_recognition.ts +161 -1
- package/src/voice/generation.ts +1 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { AudioFrame, AudioResampler } from "@livekit/rtc-node";
|
|
2
|
+
import { traceTypes } from "../../telemetry/index.js";
|
|
3
|
+
import { TransformStream, WritableStream } from "stream/web";
|
|
4
|
+
import { log } from "../../log.js";
|
|
5
|
+
import { createStreamChannel } from "../../stream/stream_channel.js";
|
|
6
|
+
import { createAccessToken } from "../utils.js";
|
|
7
|
+
import { apiConnectDefaults } from "./defaults.js";
|
|
8
|
+
import { predictHTTP } from "./http_transport.js";
|
|
9
|
+
import {
|
|
10
|
+
InterruptionCacheEntry,
|
|
11
|
+
InterruptionEventType
|
|
12
|
+
} from "./interruption.js";
|
|
13
|
+
class InterruptionStreamSentinel {
|
|
14
|
+
static speechStarted() {
|
|
15
|
+
return { type: "agent-speech-started" };
|
|
16
|
+
}
|
|
17
|
+
static speechEnded() {
|
|
18
|
+
return { type: "agent-speech-ended" };
|
|
19
|
+
}
|
|
20
|
+
static overlapSpeechStarted(speechDuration, userSpeakingSpan) {
|
|
21
|
+
return { type: "overlap-speech-started", speechDuration, userSpeakingSpan };
|
|
22
|
+
}
|
|
23
|
+
static overlapSpeechEnded() {
|
|
24
|
+
return { type: "overlap-speech-ended" };
|
|
25
|
+
}
|
|
26
|
+
static flush() {
|
|
27
|
+
return { type: "flush" };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function updateUserSpeakingSpan(span, entry) {
|
|
31
|
+
span.setAttribute(
|
|
32
|
+
traceTypes.ATTR_IS_INTERRUPTION,
|
|
33
|
+
(entry.isInterruption ?? false).toString().toLowerCase()
|
|
34
|
+
);
|
|
35
|
+
span.setAttribute(traceTypes.ATTR_INTERRUPTION_PROBABILITY, entry.probability);
|
|
36
|
+
span.setAttribute(traceTypes.ATTR_INTERRUPTION_TOTAL_DURATION, entry.totalDuration);
|
|
37
|
+
span.setAttribute(traceTypes.ATTR_INTERRUPTION_PREDICTION_DURATION, entry.predictionDuration);
|
|
38
|
+
span.setAttribute(traceTypes.ATTR_INTERRUPTION_DETECTION_DELAY, entry.detectionDelay);
|
|
39
|
+
}
|
|
40
|
+
class InterruptionStreamBase {
|
|
41
|
+
inputStream;
|
|
42
|
+
eventStream;
|
|
43
|
+
resampler;
|
|
44
|
+
userSpeakingSpan;
|
|
45
|
+
overlapSpeechStartedAt;
|
|
46
|
+
options;
|
|
47
|
+
apiOptions;
|
|
48
|
+
model;
|
|
49
|
+
constructor(model, apiOptions) {
|
|
50
|
+
this.inputStream = createStreamChannel();
|
|
51
|
+
this.eventStream = createStreamChannel();
|
|
52
|
+
this.model = model;
|
|
53
|
+
this.options = model.options;
|
|
54
|
+
this.apiOptions = { ...apiConnectDefaults, ...apiOptions };
|
|
55
|
+
this.setupTransform();
|
|
56
|
+
}
|
|
57
|
+
setupTransform() {
|
|
58
|
+
let agentSpeechStarted = false;
|
|
59
|
+
let startIdx = 0;
|
|
60
|
+
let accumulatedSamples = 0;
|
|
61
|
+
let overlapSpeechStarted = false;
|
|
62
|
+
const cache = /* @__PURE__ */ new Map();
|
|
63
|
+
const inferenceS16Data = new Int16Array(
|
|
64
|
+
Math.ceil(this.options.maxAudioDuration * this.options.sampleRate)
|
|
65
|
+
).fill(0);
|
|
66
|
+
const transformer = new TransformStream(
|
|
67
|
+
{
|
|
68
|
+
transform: (chunk, controller) => {
|
|
69
|
+
if (chunk instanceof AudioFrame) {
|
|
70
|
+
if (!agentSpeechStarted) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (this.options.sampleRate !== chunk.sampleRate) {
|
|
74
|
+
controller.error("the sample rate of the input frames must be consistent");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const result = writeToInferenceS16Data(
|
|
78
|
+
chunk,
|
|
79
|
+
startIdx,
|
|
80
|
+
inferenceS16Data,
|
|
81
|
+
this.options.maxAudioDuration
|
|
82
|
+
);
|
|
83
|
+
startIdx = result.startIdx;
|
|
84
|
+
accumulatedSamples += result.samplesWritten;
|
|
85
|
+
if (accumulatedSamples >= Math.floor(this.options.detectionInterval * this.options.sampleRate) && overlapSpeechStarted) {
|
|
86
|
+
const audioSlice = inferenceS16Data.slice(0, startIdx);
|
|
87
|
+
accumulatedSamples = 0;
|
|
88
|
+
controller.enqueue(audioSlice);
|
|
89
|
+
}
|
|
90
|
+
} else if (chunk.type === "agent-speech-started") {
|
|
91
|
+
log().debug("agent speech started");
|
|
92
|
+
agentSpeechStarted = true;
|
|
93
|
+
overlapSpeechStarted = false;
|
|
94
|
+
accumulatedSamples = 0;
|
|
95
|
+
startIdx = 0;
|
|
96
|
+
cache.clear();
|
|
97
|
+
} else if (chunk.type === "agent-speech-ended") {
|
|
98
|
+
log().debug("agent speech ended");
|
|
99
|
+
agentSpeechStarted = false;
|
|
100
|
+
overlapSpeechStarted = false;
|
|
101
|
+
accumulatedSamples = 0;
|
|
102
|
+
startIdx = 0;
|
|
103
|
+
cache.clear();
|
|
104
|
+
} else if (chunk.type === "overlap-speech-started" && agentSpeechStarted) {
|
|
105
|
+
this.userSpeakingSpan = chunk.userSpeakingSpan;
|
|
106
|
+
log().debug("overlap speech started, starting interruption inference");
|
|
107
|
+
overlapSpeechStarted = true;
|
|
108
|
+
accumulatedSamples = 0;
|
|
109
|
+
const shiftSize = Math.min(
|
|
110
|
+
startIdx,
|
|
111
|
+
Math.round(chunk.speechDuration * this.options.sampleRate) + Math.round(this.options.audioPrefixDuration * this.options.sampleRate)
|
|
112
|
+
);
|
|
113
|
+
inferenceS16Data.copyWithin(0, startIdx - shiftSize, startIdx);
|
|
114
|
+
startIdx = shiftSize;
|
|
115
|
+
cache.clear();
|
|
116
|
+
} else if (chunk.type === "overlap-speech-ended") {
|
|
117
|
+
log().debug("overlap speech ended");
|
|
118
|
+
if (overlapSpeechStarted) {
|
|
119
|
+
this.userSpeakingSpan = void 0;
|
|
120
|
+
let latestEntry = Array.from(cache.values()).at(-1);
|
|
121
|
+
if (!latestEntry) {
|
|
122
|
+
log().debug("no request made for overlap speech");
|
|
123
|
+
latestEntry = InterruptionCacheEntry.default();
|
|
124
|
+
} else {
|
|
125
|
+
cache.delete(latestEntry.createdAt);
|
|
126
|
+
}
|
|
127
|
+
const event = {
|
|
128
|
+
type: InterruptionEventType.OVERLAP_SPEECH_ENDED,
|
|
129
|
+
timestamp: Date.now(),
|
|
130
|
+
isInterruption: false,
|
|
131
|
+
overlapSpeechStartedAt: this.overlapSpeechStartedAt,
|
|
132
|
+
speechInput: latestEntry.speechInput,
|
|
133
|
+
probabilities: latestEntry.probabilities,
|
|
134
|
+
totalDuration: latestEntry.totalDuration,
|
|
135
|
+
detectionDelay: latestEntry.detectionDelay,
|
|
136
|
+
predictionDuration: latestEntry.predictionDuration,
|
|
137
|
+
probability: latestEntry.probability
|
|
138
|
+
};
|
|
139
|
+
this.eventStream.write(event);
|
|
140
|
+
}
|
|
141
|
+
} else if (chunk.type === "flush") {
|
|
142
|
+
log().debug("flushing");
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
{ highWaterMark: Number.MAX_SAFE_INTEGER },
|
|
147
|
+
{ highWaterMark: Number.MAX_SAFE_INTEGER }
|
|
148
|
+
);
|
|
149
|
+
const httpPostWriter = new WritableStream(
|
|
150
|
+
{
|
|
151
|
+
// Implement the sink
|
|
152
|
+
write: async (chunk) => {
|
|
153
|
+
if (!this.overlapSpeechStartedAt) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const resp = await predictHTTP(
|
|
157
|
+
chunk,
|
|
158
|
+
{ threshold: this.options.threshold, minFrames: this.options.minFrames },
|
|
159
|
+
{
|
|
160
|
+
baseUrl: this.options.baseUrl,
|
|
161
|
+
timeout: this.options.inferenceTimeout,
|
|
162
|
+
token: await createAccessToken(this.options.apiKey, this.options.apiSecret)
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
console.log("received inference response", resp);
|
|
166
|
+
const { createdAt, isBargein, probabilities, predictionDuration } = resp;
|
|
167
|
+
const entry = new InterruptionCacheEntry({
|
|
168
|
+
createdAt,
|
|
169
|
+
probabilities,
|
|
170
|
+
isInterruption: isBargein,
|
|
171
|
+
speechInput: chunk,
|
|
172
|
+
totalDuration: (performance.now() - createdAt) / 1e9,
|
|
173
|
+
detectionDelay: Date.now() - this.overlapSpeechStartedAt,
|
|
174
|
+
predictionDuration
|
|
175
|
+
});
|
|
176
|
+
cache.set(createdAt, entry);
|
|
177
|
+
if (overlapSpeechStarted && entry.isInterruption) {
|
|
178
|
+
if (this.userSpeakingSpan) {
|
|
179
|
+
updateUserSpeakingSpan(this.userSpeakingSpan, entry);
|
|
180
|
+
}
|
|
181
|
+
const event = {
|
|
182
|
+
type: InterruptionEventType.INTERRUPTION,
|
|
183
|
+
timestamp: Date.now(),
|
|
184
|
+
overlapSpeechStartedAt: this.overlapSpeechStartedAt,
|
|
185
|
+
isInterruption: entry.isInterruption,
|
|
186
|
+
speechInput: entry.speechInput,
|
|
187
|
+
probabilities: entry.probabilities,
|
|
188
|
+
totalDuration: entry.totalDuration,
|
|
189
|
+
predictionDuration: entry.predictionDuration,
|
|
190
|
+
detectionDelay: entry.detectionDelay,
|
|
191
|
+
probability: entry.probability
|
|
192
|
+
};
|
|
193
|
+
this.eventStream.write(event);
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
close() {
|
|
197
|
+
console.log("closing http writer");
|
|
198
|
+
},
|
|
199
|
+
abort(err) {
|
|
200
|
+
console.log("Sink error:", err);
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
{ highWaterMark: Number.MAX_SAFE_INTEGER }
|
|
204
|
+
);
|
|
205
|
+
this.inputStream.stream().pipeThrough(transformer).pipeTo(httpPostWriter);
|
|
206
|
+
}
|
|
207
|
+
ensureInputNotEnded() {
|
|
208
|
+
if (this.inputStream.closed) {
|
|
209
|
+
throw new Error("input stream is closed");
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
ensureStreamsNotEnded() {
|
|
213
|
+
this.ensureInputNotEnded();
|
|
214
|
+
}
|
|
215
|
+
getResamplerFor(inputSampleRate) {
|
|
216
|
+
if (!this.resampler) {
|
|
217
|
+
this.resampler = new AudioResampler(inputSampleRate, this.options.sampleRate);
|
|
218
|
+
}
|
|
219
|
+
return this.resampler;
|
|
220
|
+
}
|
|
221
|
+
get stream() {
|
|
222
|
+
return this.eventStream.stream();
|
|
223
|
+
}
|
|
224
|
+
async pushFrame(frame) {
|
|
225
|
+
this.ensureStreamsNotEnded();
|
|
226
|
+
if (!(frame instanceof AudioFrame)) {
|
|
227
|
+
if (frame.type === "overlap-speech-started") {
|
|
228
|
+
this.overlapSpeechStartedAt = Date.now() - frame.speechDuration;
|
|
229
|
+
}
|
|
230
|
+
return this.inputStream.write(frame);
|
|
231
|
+
} else if (this.options.sampleRate !== frame.sampleRate) {
|
|
232
|
+
const resampler = this.getResamplerFor(frame.sampleRate);
|
|
233
|
+
if (resampler.inputRate !== frame.sampleRate) {
|
|
234
|
+
throw new Error("the sample rate of the input frames must be consistent");
|
|
235
|
+
}
|
|
236
|
+
for (const resampledFrame of resampler.push(frame)) {
|
|
237
|
+
await this.inputStream.write(resampledFrame);
|
|
238
|
+
}
|
|
239
|
+
} else {
|
|
240
|
+
await this.inputStream.write(frame);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
async flush() {
|
|
244
|
+
this.ensureStreamsNotEnded();
|
|
245
|
+
this.inputStream.write(InterruptionStreamSentinel.flush());
|
|
246
|
+
}
|
|
247
|
+
async endInput() {
|
|
248
|
+
await this.flush();
|
|
249
|
+
await this.inputStream.close();
|
|
250
|
+
}
|
|
251
|
+
async close() {
|
|
252
|
+
if (!this.inputStream.closed) await this.inputStream.close();
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
function writeToInferenceS16Data(frame, startIdx, outData, maxAudioDuration) {
|
|
256
|
+
const maxWindowSize = Math.floor(maxAudioDuration * frame.sampleRate);
|
|
257
|
+
if (frame.samplesPerChannel > outData.length) {
|
|
258
|
+
throw new Error("frame samples are greater than the max window size");
|
|
259
|
+
}
|
|
260
|
+
const shift = startIdx + frame.samplesPerChannel - maxWindowSize;
|
|
261
|
+
if (shift > 0) {
|
|
262
|
+
outData.copyWithin(0, shift, startIdx);
|
|
263
|
+
startIdx -= shift;
|
|
264
|
+
}
|
|
265
|
+
const frameData = new Int16Array(
|
|
266
|
+
frame.data.buffer,
|
|
267
|
+
frame.data.byteOffset,
|
|
268
|
+
frame.samplesPerChannel * frame.channels
|
|
269
|
+
);
|
|
270
|
+
if (frame.channels > 1) {
|
|
271
|
+
for (let i = 0; i < frame.samplesPerChannel; i++) {
|
|
272
|
+
let sum = 0;
|
|
273
|
+
for (let ch = 0; ch < frame.channels; ch++) {
|
|
274
|
+
sum += frameData[i * frame.channels + ch] ?? 0;
|
|
275
|
+
}
|
|
276
|
+
outData[startIdx + i] = Math.floor(sum / frame.channels);
|
|
277
|
+
}
|
|
278
|
+
} else {
|
|
279
|
+
outData.set(frameData, startIdx);
|
|
280
|
+
}
|
|
281
|
+
startIdx += frame.samplesPerChannel;
|
|
282
|
+
return { startIdx, samplesWritten: frame.samplesPerChannel };
|
|
283
|
+
}
|
|
284
|
+
export {
|
|
285
|
+
InterruptionStreamBase,
|
|
286
|
+
InterruptionStreamSentinel
|
|
287
|
+
};
|
|
288
|
+
//# sourceMappingURL=InterruptionStream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/inference/interruption/InterruptionStream.ts"],"sourcesContent":["import { AudioFrame, AudioResampler } from '@livekit/rtc-node';\nimport type { Span } from '@opentelemetry/api';\nimport { traceTypes } from '../../telemetry/index.js';\nimport { type ReadableStream, TransformStream, WritableStream } from 'stream/web';\nimport { log } from '../../log.js';\nimport { type StreamChannel, createStreamChannel } from '../../stream/stream_channel.js';\nimport { createAccessToken } from '../utils.js';\nimport type {\n AdaptiveInterruptionDetector,\n InterruptionOptions,\n} from './AdaptiveInterruptionDetector.js';\nimport { apiConnectDefaults } from './defaults.js';\nimport { predictHTTP } from './http_transport.js';\nimport {\n InterruptionCacheEntry,\n type InterruptionDetectionError,\n type InterruptionEvent,\n InterruptionEventType,\n} from './interruption.js';\n\nexport interface AgentSpeechStarted {\n type: 'agent-speech-started';\n}\n\nexport interface AgentSpeechEnded {\n type: 'agent-speech-ended';\n}\n\nexport interface OverlapSpeechStarted {\n type: 'overlap-speech-started';\n speechDuration: number;\n userSpeakingSpan: Span;\n}\n\nexport interface OverlapSpeechEnded {\n type: 'overlap-speech-ended';\n}\n\nexport interface Flush {\n type: 'flush';\n}\n\nexport type InterruptionSentinel =\n | AgentSpeechStarted\n | AgentSpeechEnded\n | OverlapSpeechStarted\n | OverlapSpeechEnded\n | Flush;\n\nexport class InterruptionStreamSentinel {\n static speechStarted(): AgentSpeechStarted {\n return { type: 'agent-speech-started' };\n }\n\n static speechEnded(): AgentSpeechEnded {\n return { type: 'agent-speech-ended' };\n }\n\n static overlapSpeechStarted(\n speechDuration: number,\n userSpeakingSpan: Span,\n ): OverlapSpeechStarted {\n return { type: 'overlap-speech-started', speechDuration, userSpeakingSpan };\n }\n\n static overlapSpeechEnded(): OverlapSpeechEnded {\n return { type: 'overlap-speech-ended' };\n }\n\n static flush(): Flush {\n return { type: 'flush' };\n }\n}\n\nexport interface ApiConnectOptions {\n maxRetries: number;\n retryInterval: number;\n timeout: number;\n}\n\nfunction updateUserSpeakingSpan(span: Span, entry: InterruptionCacheEntry) {\n span.setAttribute(\n traceTypes.ATTR_IS_INTERRUPTION,\n (entry.isInterruption ?? false).toString().toLowerCase(),\n );\n span.setAttribute(traceTypes.ATTR_INTERRUPTION_PROBABILITY, entry.probability);\n span.setAttribute(traceTypes.ATTR_INTERRUPTION_TOTAL_DURATION, entry.totalDuration);\n span.setAttribute(traceTypes.ATTR_INTERRUPTION_PREDICTION_DURATION, entry.predictionDuration);\n span.setAttribute(traceTypes.ATTR_INTERRUPTION_DETECTION_DELAY, entry.detectionDelay);\n}\n\nexport class InterruptionStreamBase {\n private inputStream: StreamChannel<InterruptionSentinel | AudioFrame, InterruptionDetectionError>;\n\n private eventStream: StreamChannel<InterruptionEvent, InterruptionDetectionError>;\n\n private resampler?: AudioResampler;\n\n private userSpeakingSpan: Span | undefined;\n\n private overlapSpeechStartedAt: number | undefined;\n\n private options: InterruptionOptions;\n\n private apiOptions: ApiConnectOptions;\n\n private model: AdaptiveInterruptionDetector;\n\n constructor(model: AdaptiveInterruptionDetector, apiOptions: Partial<ApiConnectOptions>) {\n this.inputStream = createStreamChannel<\n InterruptionSentinel | AudioFrame,\n InterruptionDetectionError\n >();\n\n this.eventStream = createStreamChannel<InterruptionEvent, InterruptionDetectionError>();\n\n this.model = model;\n this.options = model.options;\n this.apiOptions = { ...apiConnectDefaults, ...apiOptions };\n\n this.setupTransform();\n }\n\n private setupTransform() {\n let agentSpeechStarted = false;\n let startIdx = 0;\n let accumulatedSamples = 0;\n let overlapSpeechStarted = false;\n const cache = new Map<number, InterruptionCacheEntry>(); // TODO limit cache size\n const inferenceS16Data = new Int16Array(\n Math.ceil(this.options.maxAudioDuration * this.options.sampleRate),\n ).fill(0);\n\n const transformer = new TransformStream<InterruptionSentinel | AudioFrame, Int16Array>(\n {\n transform: (chunk, controller) => {\n if (chunk instanceof AudioFrame) {\n if (!agentSpeechStarted) {\n return;\n }\n if (this.options.sampleRate !== chunk.sampleRate) {\n controller.error('the sample rate of the input frames must be consistent');\n return;\n }\n const result = writeToInferenceS16Data(\n chunk,\n startIdx,\n inferenceS16Data,\n this.options.maxAudioDuration,\n );\n startIdx = result.startIdx;\n accumulatedSamples += result.samplesWritten;\n\n // Send data for inference when enough samples accumulated during overlap\n if (\n accumulatedSamples >=\n Math.floor(this.options.detectionInterval * this.options.sampleRate) &&\n overlapSpeechStarted\n ) {\n // Send a copy of the audio data up to startIdx for inference\n const audioSlice = inferenceS16Data.slice(0, startIdx);\n // TODO: send to data channel - dataChan.send(audioSlice);\n accumulatedSamples = 0;\n controller.enqueue(audioSlice);\n }\n } else if (chunk.type === 'agent-speech-started') {\n log().debug('agent speech started');\n\n agentSpeechStarted = true;\n overlapSpeechStarted = false;\n accumulatedSamples = 0;\n startIdx = 0;\n cache.clear();\n } else if (chunk.type === 'agent-speech-ended') {\n log().debug('agent speech ended');\n\n agentSpeechStarted = false;\n overlapSpeechStarted = false;\n accumulatedSamples = 0;\n startIdx = 0;\n cache.clear();\n } else if (chunk.type === 'overlap-speech-started' && agentSpeechStarted) {\n this.userSpeakingSpan = chunk.userSpeakingSpan;\n log().debug('overlap speech started, starting interruption inference');\n overlapSpeechStarted = true;\n accumulatedSamples = 0;\n // Include both speech duration and audio prefix duration for context\n const shiftSize = Math.min(\n startIdx,\n Math.round(chunk.speechDuration * this.options.sampleRate) +\n Math.round(this.options.audioPrefixDuration * this.options.sampleRate),\n );\n // Shift the buffer: copy the last `shiftSize` samples before startIdx\n // to the beginning of the buffer. This preserves recent audio context\n // (the user's speech that occurred just before overlap was detected).\n inferenceS16Data.copyWithin(0, startIdx - shiftSize, startIdx);\n startIdx = shiftSize;\n cache.clear();\n } else if (chunk.type === 'overlap-speech-ended') {\n log().debug('overlap speech ended');\n\n if (overlapSpeechStarted) {\n this.userSpeakingSpan = undefined;\n let latestEntry = Array.from(cache.values()).at(-1);\n if (!latestEntry) {\n log().debug('no request made for overlap speech');\n latestEntry = InterruptionCacheEntry.default();\n } else {\n cache.delete(latestEntry.createdAt);\n }\n const event: InterruptionEvent = {\n type: InterruptionEventType.OVERLAP_SPEECH_ENDED,\n timestamp: Date.now(),\n isInterruption: false,\n overlapSpeechStartedAt: this.overlapSpeechStartedAt,\n speechInput: latestEntry.speechInput,\n probabilities: latestEntry.probabilities,\n totalDuration: latestEntry.totalDuration,\n detectionDelay: latestEntry.detectionDelay,\n predictionDuration: latestEntry.predictionDuration,\n probability: latestEntry.probability,\n };\n this.eventStream.write(event);\n }\n } else if (chunk.type === 'flush') {\n log().debug('flushing');\n // do nothing\n }\n },\n },\n { highWaterMark: Number.MAX_SAFE_INTEGER },\n { highWaterMark: Number.MAX_SAFE_INTEGER },\n );\n\n const httpPostWriter = new WritableStream<Int16Array>(\n {\n // Implement the sink\n write: async (chunk) => {\n if (!this.overlapSpeechStartedAt) {\n return;\n }\n const resp = await predictHTTP(\n chunk,\n { threshold: this.options.threshold, minFrames: this.options.minFrames },\n {\n baseUrl: this.options.baseUrl,\n timeout: this.options.inferenceTimeout,\n token: await createAccessToken(this.options.apiKey, this.options.apiSecret),\n },\n );\n console.log('received inference response', resp);\n const { createdAt, isBargein, probabilities, predictionDuration } = resp;\n const entry = new InterruptionCacheEntry({\n createdAt,\n probabilities,\n isInterruption: isBargein,\n speechInput: chunk,\n totalDuration: (performance.now() - createdAt) / 1e9,\n detectionDelay: Date.now() - this.overlapSpeechStartedAt,\n predictionDuration,\n });\n cache.set(createdAt, entry);\n if (overlapSpeechStarted && entry.isInterruption) {\n if (this.userSpeakingSpan) {\n updateUserSpeakingSpan(this.userSpeakingSpan, entry);\n }\n const event: InterruptionEvent = {\n type: InterruptionEventType.INTERRUPTION,\n timestamp: Date.now(),\n overlapSpeechStartedAt: this.overlapSpeechStartedAt,\n isInterruption: entry.isInterruption,\n speechInput: entry.speechInput,\n probabilities: entry.probabilities,\n totalDuration: entry.totalDuration,\n predictionDuration: entry.predictionDuration,\n detectionDelay: entry.detectionDelay,\n probability: entry.probability,\n };\n this.eventStream.write(event);\n }\n },\n close() {\n console.log('closing http writer');\n },\n abort(err) {\n console.log('Sink error:', err);\n },\n },\n { highWaterMark: Number.MAX_SAFE_INTEGER },\n );\n\n this.inputStream.stream().pipeThrough(transformer).pipeTo(httpPostWriter);\n }\n\n private ensureInputNotEnded() {\n if (this.inputStream.closed) {\n throw new Error('input stream is closed');\n }\n }\n\n private ensureStreamsNotEnded() {\n this.ensureInputNotEnded();\n }\n\n private getResamplerFor(inputSampleRate: number): AudioResampler {\n if (!this.resampler) {\n this.resampler = new AudioResampler(inputSampleRate, this.options.sampleRate);\n }\n return this.resampler;\n }\n\n get stream(): ReadableStream<InterruptionEvent> {\n return this.eventStream.stream();\n }\n\n async pushFrame(frame: InterruptionSentinel | AudioFrame): Promise<void> {\n this.ensureStreamsNotEnded();\n if (!(frame instanceof AudioFrame)) {\n if (frame.type === 'overlap-speech-started') {\n this.overlapSpeechStartedAt = Date.now() - frame.speechDuration;\n }\n return this.inputStream.write(frame);\n } else if (this.options.sampleRate !== frame.sampleRate) {\n const resampler = this.getResamplerFor(frame.sampleRate);\n if (resampler.inputRate !== frame.sampleRate) {\n throw new Error('the sample rate of the input frames must be consistent');\n }\n for (const resampledFrame of resampler.push(frame)) {\n await this.inputStream.write(resampledFrame);\n }\n } else {\n await this.inputStream.write(frame);\n }\n }\n\n async flush(): Promise<void> {\n this.ensureStreamsNotEnded();\n this.inputStream.write(InterruptionStreamSentinel.flush());\n }\n\n async endInput(): Promise<void> {\n await this.flush();\n await this.inputStream.close();\n }\n\n async close(): Promise<void> {\n if (!this.inputStream.closed) await this.inputStream.close();\n }\n}\n\n/**\n * Write the audio frame to the output data array and return the new start index\n * and the number of samples written.\n */\nfunction writeToInferenceS16Data(\n frame: AudioFrame,\n startIdx: number,\n outData: Int16Array,\n maxAudioDuration: number,\n): { startIdx: number; samplesWritten: number } {\n const maxWindowSize = Math.floor(maxAudioDuration * frame.sampleRate);\n\n if (frame.samplesPerChannel > outData.length) {\n throw new Error('frame samples are greater than the max window size');\n }\n\n // Shift the data to the left if the window would overflow\n const shift = startIdx + frame.samplesPerChannel - maxWindowSize;\n if (shift > 0) {\n outData.copyWithin(0, shift, startIdx);\n startIdx -= shift;\n }\n\n // Get the frame data as Int16Array\n const frameData = new Int16Array(\n frame.data.buffer,\n frame.data.byteOffset,\n frame.samplesPerChannel * frame.channels,\n );\n\n if (frame.channels > 1) {\n // Mix down multiple channels to mono by averaging\n for (let i = 0; i < frame.samplesPerChannel; i++) {\n let sum = 0;\n for (let ch = 0; ch < frame.channels; ch++) {\n sum += frameData[i * frame.channels + ch] ?? 0;\n }\n outData[startIdx + i] = Math.floor(sum / frame.channels);\n }\n } else {\n // Single channel - copy directly\n outData.set(frameData, startIdx);\n }\n\n startIdx += frame.samplesPerChannel;\n return { startIdx, samplesWritten: frame.samplesPerChannel };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var defaults_exports = {};
|
|
20
|
+
__export(defaults_exports, {
|
|
21
|
+
AUDIO_PREFIX_DURATION: () => AUDIO_PREFIX_DURATION,
|
|
22
|
+
DEFAULT_BASE_URL: () => DEFAULT_BASE_URL,
|
|
23
|
+
DETECTION_INTERVAL: () => DETECTION_INTERVAL,
|
|
24
|
+
FRAMES_PER_SECOND: () => FRAMES_PER_SECOND,
|
|
25
|
+
MAX_AUDIO_DURATION: () => MAX_AUDIO_DURATION,
|
|
26
|
+
MIN_INTERRUPTION_DURATION: () => MIN_INTERRUPTION_DURATION,
|
|
27
|
+
REMOTE_INFERENCE_TIMEOUT: () => REMOTE_INFERENCE_TIMEOUT,
|
|
28
|
+
SAMPLE_RATE: () => SAMPLE_RATE,
|
|
29
|
+
THRESHOLD: () => THRESHOLD,
|
|
30
|
+
apiConnectDefaults: () => apiConnectDefaults,
|
|
31
|
+
interruptionOptionDefaults: () => interruptionOptionDefaults
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(defaults_exports);
|
|
34
|
+
const MIN_INTERRUPTION_DURATION = 0.025 * 2;
|
|
35
|
+
const THRESHOLD = 0.65;
|
|
36
|
+
const MAX_AUDIO_DURATION = 3;
|
|
37
|
+
const AUDIO_PREFIX_DURATION = 0.5;
|
|
38
|
+
const DETECTION_INTERVAL = 0.1;
|
|
39
|
+
const REMOTE_INFERENCE_TIMEOUT = 1;
|
|
40
|
+
const SAMPLE_RATE = 16e3;
|
|
41
|
+
const FRAMES_PER_SECOND = 40;
|
|
42
|
+
const DEFAULT_BASE_URL = "https://agent-gateway.livekit.cloud/v1";
|
|
43
|
+
const apiConnectDefaults = {
|
|
44
|
+
maxRetries: 3,
|
|
45
|
+
retryInterval: 2e3,
|
|
46
|
+
timeout: 1e4
|
|
47
|
+
};
|
|
48
|
+
const interruptionOptionDefaults = {
|
|
49
|
+
sampleRate: SAMPLE_RATE,
|
|
50
|
+
threshold: THRESHOLD,
|
|
51
|
+
minFrames: Math.ceil(MIN_INTERRUPTION_DURATION * FRAMES_PER_SECOND),
|
|
52
|
+
maxAudioDuration: MAX_AUDIO_DURATION,
|
|
53
|
+
audioPrefixDuration: AUDIO_PREFIX_DURATION,
|
|
54
|
+
detectionInterval: DETECTION_INTERVAL,
|
|
55
|
+
inferenceTimeout: 1e4,
|
|
56
|
+
baseUrl: DEFAULT_BASE_URL,
|
|
57
|
+
apiKey: process.env.LIVEKIT_API_KEY || "",
|
|
58
|
+
apiSecret: process.env.LIVEKIT_API_SECRET || "",
|
|
59
|
+
useProxy: false,
|
|
60
|
+
minInterruptionDuration: MIN_INTERRUPTION_DURATION
|
|
61
|
+
};
|
|
62
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
63
|
+
0 && (module.exports = {
|
|
64
|
+
AUDIO_PREFIX_DURATION,
|
|
65
|
+
DEFAULT_BASE_URL,
|
|
66
|
+
DETECTION_INTERVAL,
|
|
67
|
+
FRAMES_PER_SECOND,
|
|
68
|
+
MAX_AUDIO_DURATION,
|
|
69
|
+
MIN_INTERRUPTION_DURATION,
|
|
70
|
+
REMOTE_INFERENCE_TIMEOUT,
|
|
71
|
+
SAMPLE_RATE,
|
|
72
|
+
THRESHOLD,
|
|
73
|
+
apiConnectDefaults,
|
|
74
|
+
interruptionOptionDefaults
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=defaults.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/inference/interruption/defaults.ts"],"sourcesContent":["import type { InterruptionOptions } from './AdaptiveInterruptionDetector.js';\nimport type { ApiConnectOptions } from './InterruptionStream.js';\n\nexport const MIN_INTERRUPTION_DURATION = 0.025 * 2; // 25ms per frame, 2 consecutive frames\nexport const THRESHOLD = 0.65;\nexport const MAX_AUDIO_DURATION = 3.0;\nexport const AUDIO_PREFIX_DURATION = 0.5;\nexport const DETECTION_INTERVAL = 0.1;\nexport const REMOTE_INFERENCE_TIMEOUT = 1.0;\nexport const SAMPLE_RATE = 16000;\nexport const FRAMES_PER_SECOND = 40;\nexport const DEFAULT_BASE_URL = 'https://agent-gateway.livekit.cloud/v1';\n\nexport const apiConnectDefaults: ApiConnectOptions = {\n maxRetries: 3,\n retryInterval: 2_000,\n timeout: 10_000,\n} as const;\n\nexport const interruptionOptionDefaults: InterruptionOptions = {\n sampleRate: SAMPLE_RATE,\n threshold: THRESHOLD,\n minFrames: Math.ceil(MIN_INTERRUPTION_DURATION * FRAMES_PER_SECOND),\n maxAudioDuration: MAX_AUDIO_DURATION,\n audioPrefixDuration: AUDIO_PREFIX_DURATION,\n detectionInterval: DETECTION_INTERVAL,\n inferenceTimeout: 10_000,\n baseUrl: DEFAULT_BASE_URL,\n apiKey: process.env.LIVEKIT_API_KEY || '',\n apiSecret: process.env.LIVEKIT_API_SECRET || '',\n useProxy: false,\n minInterruptionDuration: MIN_INTERRUPTION_DURATION,\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,MAAM,4BAA4B,QAAQ;AAC1C,MAAM,YAAY;AAClB,MAAM,qBAAqB;AAC3B,MAAM,wBAAwB;AAC9B,MAAM,qBAAqB;AAC3B,MAAM,2BAA2B;AACjC,MAAM,cAAc;AACpB,MAAM,oBAAoB;AAC1B,MAAM,mBAAmB;AAEzB,MAAM,qBAAwC;AAAA,EACnD,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,SAAS;AACX;AAEO,MAAM,6BAAkD;AAAA,EAC7D,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,WAAW,KAAK,KAAK,4BAA4B,iBAAiB;AAAA,EAClE,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,SAAS;AAAA,EACT,QAAQ,QAAQ,IAAI,mBAAmB;AAAA,EACvC,WAAW,QAAQ,IAAI,sBAAsB;AAAA,EAC7C,UAAU;AAAA,EACV,yBAAyB;AAC3B;","names":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { InterruptionOptions } from './AdaptiveInterruptionDetector.js';
|
|
2
|
+
import type { ApiConnectOptions } from './InterruptionStream.js';
|
|
3
|
+
export declare const MIN_INTERRUPTION_DURATION: number;
|
|
4
|
+
export declare const THRESHOLD = 0.65;
|
|
5
|
+
export declare const MAX_AUDIO_DURATION = 3;
|
|
6
|
+
export declare const AUDIO_PREFIX_DURATION = 0.5;
|
|
7
|
+
export declare const DETECTION_INTERVAL = 0.1;
|
|
8
|
+
export declare const REMOTE_INFERENCE_TIMEOUT = 1;
|
|
9
|
+
export declare const SAMPLE_RATE = 16000;
|
|
10
|
+
export declare const FRAMES_PER_SECOND = 40;
|
|
11
|
+
export declare const DEFAULT_BASE_URL = "https://agent-gateway.livekit.cloud/v1";
|
|
12
|
+
export declare const apiConnectDefaults: ApiConnectOptions;
|
|
13
|
+
export declare const interruptionOptionDefaults: InterruptionOptions;
|
|
14
|
+
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { InterruptionOptions } from './AdaptiveInterruptionDetector.js';
|
|
2
|
+
import type { ApiConnectOptions } from './InterruptionStream.js';
|
|
3
|
+
export declare const MIN_INTERRUPTION_DURATION: number;
|
|
4
|
+
export declare const THRESHOLD = 0.65;
|
|
5
|
+
export declare const MAX_AUDIO_DURATION = 3;
|
|
6
|
+
export declare const AUDIO_PREFIX_DURATION = 0.5;
|
|
7
|
+
export declare const DETECTION_INTERVAL = 0.1;
|
|
8
|
+
export declare const REMOTE_INFERENCE_TIMEOUT = 1;
|
|
9
|
+
export declare const SAMPLE_RATE = 16000;
|
|
10
|
+
export declare const FRAMES_PER_SECOND = 40;
|
|
11
|
+
export declare const DEFAULT_BASE_URL = "https://agent-gateway.livekit.cloud/v1";
|
|
12
|
+
export declare const apiConnectDefaults: ApiConnectOptions;
|
|
13
|
+
export declare const interruptionOptionDefaults: InterruptionOptions;
|
|
14
|
+
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../../src/inference/interruption/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAC7E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,eAAO,MAAM,yBAAyB,QAAY,CAAC;AACnD,eAAO,MAAM,SAAS,OAAO,CAAC;AAC9B,eAAO,MAAM,kBAAkB,IAAM,CAAC;AACtC,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AACtC,eAAO,MAAM,wBAAwB,IAAM,CAAC;AAC5C,eAAO,MAAM,WAAW,QAAQ,CAAC;AACjC,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC,eAAO,MAAM,gBAAgB,2CAA2C,CAAC;AAEzE,eAAO,MAAM,kBAAkB,EAAE,iBAIvB,CAAC;AAEX,eAAO,MAAM,0BAA0B,EAAE,mBAa/B,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const MIN_INTERRUPTION_DURATION = 0.025 * 2;
|
|
2
|
+
const THRESHOLD = 0.65;
|
|
3
|
+
const MAX_AUDIO_DURATION = 3;
|
|
4
|
+
const AUDIO_PREFIX_DURATION = 0.5;
|
|
5
|
+
const DETECTION_INTERVAL = 0.1;
|
|
6
|
+
const REMOTE_INFERENCE_TIMEOUT = 1;
|
|
7
|
+
const SAMPLE_RATE = 16e3;
|
|
8
|
+
const FRAMES_PER_SECOND = 40;
|
|
9
|
+
const DEFAULT_BASE_URL = "https://agent-gateway.livekit.cloud/v1";
|
|
10
|
+
const apiConnectDefaults = {
|
|
11
|
+
maxRetries: 3,
|
|
12
|
+
retryInterval: 2e3,
|
|
13
|
+
timeout: 1e4
|
|
14
|
+
};
|
|
15
|
+
const interruptionOptionDefaults = {
|
|
16
|
+
sampleRate: SAMPLE_RATE,
|
|
17
|
+
threshold: THRESHOLD,
|
|
18
|
+
minFrames: Math.ceil(MIN_INTERRUPTION_DURATION * FRAMES_PER_SECOND),
|
|
19
|
+
maxAudioDuration: MAX_AUDIO_DURATION,
|
|
20
|
+
audioPrefixDuration: AUDIO_PREFIX_DURATION,
|
|
21
|
+
detectionInterval: DETECTION_INTERVAL,
|
|
22
|
+
inferenceTimeout: 1e4,
|
|
23
|
+
baseUrl: DEFAULT_BASE_URL,
|
|
24
|
+
apiKey: process.env.LIVEKIT_API_KEY || "",
|
|
25
|
+
apiSecret: process.env.LIVEKIT_API_SECRET || "",
|
|
26
|
+
useProxy: false,
|
|
27
|
+
minInterruptionDuration: MIN_INTERRUPTION_DURATION
|
|
28
|
+
};
|
|
29
|
+
export {
|
|
30
|
+
AUDIO_PREFIX_DURATION,
|
|
31
|
+
DEFAULT_BASE_URL,
|
|
32
|
+
DETECTION_INTERVAL,
|
|
33
|
+
FRAMES_PER_SECOND,
|
|
34
|
+
MAX_AUDIO_DURATION,
|
|
35
|
+
MIN_INTERRUPTION_DURATION,
|
|
36
|
+
REMOTE_INFERENCE_TIMEOUT,
|
|
37
|
+
SAMPLE_RATE,
|
|
38
|
+
THRESHOLD,
|
|
39
|
+
apiConnectDefaults,
|
|
40
|
+
interruptionOptionDefaults
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/inference/interruption/defaults.ts"],"sourcesContent":["import type { InterruptionOptions } from './AdaptiveInterruptionDetector.js';\nimport type { ApiConnectOptions } from './InterruptionStream.js';\n\nexport const MIN_INTERRUPTION_DURATION = 0.025 * 2; // 25ms per frame, 2 consecutive frames\nexport const THRESHOLD = 0.65;\nexport const MAX_AUDIO_DURATION = 3.0;\nexport const AUDIO_PREFIX_DURATION = 0.5;\nexport const DETECTION_INTERVAL = 0.1;\nexport const REMOTE_INFERENCE_TIMEOUT = 1.0;\nexport const SAMPLE_RATE = 16000;\nexport const FRAMES_PER_SECOND = 40;\nexport const DEFAULT_BASE_URL = 'https://agent-gateway.livekit.cloud/v1';\n\nexport const apiConnectDefaults: ApiConnectOptions = {\n maxRetries: 3,\n retryInterval: 2_000,\n timeout: 10_000,\n} as const;\n\nexport const interruptionOptionDefaults: InterruptionOptions = {\n sampleRate: SAMPLE_RATE,\n threshold: THRESHOLD,\n minFrames: Math.ceil(MIN_INTERRUPTION_DURATION * FRAMES_PER_SECOND),\n maxAudioDuration: MAX_AUDIO_DURATION,\n audioPrefixDuration: AUDIO_PREFIX_DURATION,\n detectionInterval: DETECTION_INTERVAL,\n inferenceTimeout: 10_000,\n baseUrl: DEFAULT_BASE_URL,\n apiKey: process.env.LIVEKIT_API_KEY || '',\n apiSecret: process.env.LIVEKIT_API_SECRET || '',\n useProxy: false,\n minInterruptionDuration: MIN_INTERRUPTION_DURATION,\n} as const;\n"],"mappings":"AAGO,MAAM,4BAA4B,QAAQ;AAC1C,MAAM,YAAY;AAClB,MAAM,qBAAqB;AAC3B,MAAM,wBAAwB;AAC9B,MAAM,qBAAqB;AAC3B,MAAM,2BAA2B;AACjC,MAAM,cAAc;AACpB,MAAM,oBAAoB;AAC1B,MAAM,mBAAmB;AAEzB,MAAM,qBAAwC;AAAA,EACnD,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,SAAS;AACX;AAEO,MAAM,6BAAkD;AAAA,EAC7D,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,WAAW,KAAK,KAAK,4BAA4B,iBAAiB;AAAA,EAClE,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,SAAS;AAAA,EACT,QAAQ,QAAQ,IAAI,mBAAmB;AAAA,EACvC,WAAW,QAAQ,IAAI,sBAAsB;AAAA,EAC7C,UAAU;AAAA,EACV,yBAAyB;AAC3B;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/inference/interruption/errors.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var http_transport_exports = {};
|
|
20
|
+
__export(http_transport_exports, {
|
|
21
|
+
predictHTTP: () => predictHTTP
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(http_transport_exports);
|
|
24
|
+
var import_ofetch = require("ofetch");
|
|
25
|
+
async function predictHTTP(data, predictOptions, options) {
|
|
26
|
+
const createdAt = performance.now();
|
|
27
|
+
const url = new URL(`/bargein`, options.baseUrl);
|
|
28
|
+
url.searchParams.append("threshold", predictOptions.threshold.toString());
|
|
29
|
+
url.searchParams.append("min_frames", predictOptions.minFrames.toFixed());
|
|
30
|
+
url.searchParams.append("created_at", createdAt.toFixed());
|
|
31
|
+
const { created_at, is_bargein, probabilities } = await (0, import_ofetch.ofetch)(
|
|
32
|
+
url.toString(),
|
|
33
|
+
{
|
|
34
|
+
retry: 1,
|
|
35
|
+
retryDelay: 100,
|
|
36
|
+
headers: {
|
|
37
|
+
"Content-Type": "application/octet-stream",
|
|
38
|
+
Authorization: `Bearer ${options.token}`
|
|
39
|
+
},
|
|
40
|
+
signal: options.signal,
|
|
41
|
+
timeout: options.timeout,
|
|
42
|
+
method: "POST",
|
|
43
|
+
body: data
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
return {
|
|
47
|
+
createdAt: created_at,
|
|
48
|
+
isBargein: is_bargein,
|
|
49
|
+
probabilities: new Float32Array(probabilities),
|
|
50
|
+
predictionDuration: (performance.now() - createdAt) / 1e9
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
54
|
+
0 && (module.exports = {
|
|
55
|
+
predictHTTP
|
|
56
|
+
});
|
|
57
|
+
//# sourceMappingURL=http_transport.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/inference/interruption/http_transport.ts"],"sourcesContent":["import { ofetch } from 'ofetch';\n\nexport interface PostOptions {\n baseUrl: string;\n token: string;\n signal?: AbortSignal;\n timeout?: number;\n}\n\nexport interface PredictOptions {\n threshold: number;\n minFrames: number;\n}\n\nexport interface PredictEndpointResponse {\n created_at: number;\n is_bargein: boolean;\n probabilities: number[];\n}\n\nexport interface PredictResponse {\n createdAt: number;\n isBargein: boolean;\n probabilities: Float32Array;\n predictionDuration: number;\n}\n\nexport async function predictHTTP(\n data: Int16Array,\n predictOptions: PredictOptions,\n options: PostOptions,\n): Promise<PredictResponse> {\n const createdAt = performance.now();\n const url = new URL(`/bargein`, options.baseUrl);\n url.searchParams.append('threshold', predictOptions.threshold.toString());\n url.searchParams.append('min_frames', predictOptions.minFrames.toFixed());\n url.searchParams.append('created_at', createdAt.toFixed());\n\n const { created_at, is_bargein, probabilities } = await ofetch<PredictEndpointResponse>(\n url.toString(),\n {\n retry: 1,\n retryDelay: 100,\n headers: {\n 'Content-Type': 'application/octet-stream',\n Authorization: `Bearer ${options.token}`,\n },\n signal: options.signal,\n timeout: options.timeout,\n method: 'POST',\n body: data,\n },\n );\n\n return {\n createdAt: created_at,\n isBargein: is_bargein,\n probabilities: new Float32Array(probabilities),\n predictionDuration: (performance.now() - createdAt) / 1e9,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAuB;AA2BvB,eAAsB,YACpB,MACA,gBACA,SAC0B;AAC1B,QAAM,YAAY,YAAY,IAAI;AAClC,QAAM,MAAM,IAAI,IAAI,YAAY,QAAQ,OAAO;AAC/C,MAAI,aAAa,OAAO,aAAa,eAAe,UAAU,SAAS,CAAC;AACxE,MAAI,aAAa,OAAO,cAAc,eAAe,UAAU,QAAQ,CAAC;AACxE,MAAI,aAAa,OAAO,cAAc,UAAU,QAAQ,CAAC;AAEzD,QAAM,EAAE,YAAY,YAAY,cAAc,IAAI,UAAM;AAAA,IACtD,IAAI,SAAS;AAAA,IACb;AAAA,MACE,OAAO;AAAA,MACP,YAAY;AAAA,MACZ,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,eAAe,UAAU,QAAQ,KAAK;AAAA,MACxC;AAAA,MACA,QAAQ,QAAQ;AAAA,MAChB,SAAS,QAAQ;AAAA,MACjB,QAAQ;AAAA,MACR,MAAM;AAAA,IACR;AAAA,EACF;AAEA,SAAO;AAAA,IACL,WAAW;AAAA,IACX,WAAW;AAAA,IACX,eAAe,IAAI,aAAa,aAAa;AAAA,IAC7C,qBAAqB,YAAY,IAAI,IAAI,aAAa;AAAA,EACxD;AACF;","names":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface PostOptions {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
token: string;
|
|
4
|
+
signal?: AbortSignal;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface PredictOptions {
|
|
8
|
+
threshold: number;
|
|
9
|
+
minFrames: number;
|
|
10
|
+
}
|
|
11
|
+
export interface PredictEndpointResponse {
|
|
12
|
+
created_at: number;
|
|
13
|
+
is_bargein: boolean;
|
|
14
|
+
probabilities: number[];
|
|
15
|
+
}
|
|
16
|
+
export interface PredictResponse {
|
|
17
|
+
createdAt: number;
|
|
18
|
+
isBargein: boolean;
|
|
19
|
+
probabilities: Float32Array;
|
|
20
|
+
predictionDuration: number;
|
|
21
|
+
}
|
|
22
|
+
export declare function predictHTTP(data: Int16Array, predictOptions: PredictOptions, options: PostOptions): Promise<PredictResponse>;
|
|
23
|
+
//# sourceMappingURL=http_transport.d.ts.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface PostOptions {
|
|
2
|
+
baseUrl: string;
|
|
3
|
+
token: string;
|
|
4
|
+
signal?: AbortSignal;
|
|
5
|
+
timeout?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface PredictOptions {
|
|
8
|
+
threshold: number;
|
|
9
|
+
minFrames: number;
|
|
10
|
+
}
|
|
11
|
+
export interface PredictEndpointResponse {
|
|
12
|
+
created_at: number;
|
|
13
|
+
is_bargein: boolean;
|
|
14
|
+
probabilities: number[];
|
|
15
|
+
}
|
|
16
|
+
export interface PredictResponse {
|
|
17
|
+
createdAt: number;
|
|
18
|
+
isBargein: boolean;
|
|
19
|
+
probabilities: Float32Array;
|
|
20
|
+
predictionDuration: number;
|
|
21
|
+
}
|
|
22
|
+
export declare function predictHTTP(data: Int16Array, predictOptions: PredictOptions, options: PostOptions): Promise<PredictResponse>;
|
|
23
|
+
//# sourceMappingURL=http_transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http_transport.d.ts","sourceRoot":"","sources":["../../../src/inference/interruption/http_transport.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,YAAY,CAAC;IAC5B,kBAAkB,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,UAAU,EAChB,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,eAAe,CAAC,CA6B1B"}
|