@livekit/agents 1.0.48 → 1.1.0-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/constants.cjs +27 -0
- package/dist/constants.cjs.map +1 -1
- package/dist/constants.d.cts +9 -0
- package/dist/constants.d.ts +9 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +18 -0
- package/dist/constants.js.map +1 -1
- package/dist/inference/api_protos.d.cts +71 -71
- package/dist/inference/api_protos.d.ts +71 -71
- package/dist/inference/interruption/defaults.cjs +81 -0
- package/dist/inference/interruption/defaults.cjs.map +1 -0
- package/dist/inference/interruption/defaults.d.cts +19 -0
- package/dist/inference/interruption/defaults.d.ts +19 -0
- package/dist/inference/interruption/defaults.d.ts.map +1 -0
- package/dist/inference/interruption/defaults.js +46 -0
- package/dist/inference/interruption/defaults.js.map +1 -0
- package/dist/inference/interruption/errors.cjs +44 -0
- package/dist/inference/interruption/errors.cjs.map +1 -0
- package/dist/inference/interruption/errors.d.cts +12 -0
- package/dist/inference/interruption/errors.d.ts +12 -0
- package/dist/inference/interruption/errors.d.ts.map +1 -0
- package/dist/inference/interruption/errors.js +20 -0
- package/dist/inference/interruption/errors.js.map +1 -0
- package/dist/inference/interruption/http_transport.cjs +147 -0
- package/dist/inference/interruption/http_transport.cjs.map +1 -0
- package/dist/inference/interruption/http_transport.d.cts +63 -0
- package/dist/inference/interruption/http_transport.d.ts +63 -0
- package/dist/inference/interruption/http_transport.d.ts.map +1 -0
- package/dist/inference/interruption/http_transport.js +121 -0
- package/dist/inference/interruption/http_transport.js.map +1 -0
- package/dist/inference/interruption/interruption_cache_entry.cjs +58 -0
- package/dist/inference/interruption/interruption_cache_entry.cjs.map +1 -0
- package/dist/inference/interruption/interruption_cache_entry.d.cts +30 -0
- package/dist/inference/interruption/interruption_cache_entry.d.ts +30 -0
- package/dist/inference/interruption/interruption_cache_entry.d.ts.map +1 -0
- package/dist/inference/interruption/interruption_cache_entry.js +34 -0
- package/dist/inference/interruption/interruption_cache_entry.js.map +1 -0
- package/dist/inference/interruption/interruption_detector.cjs +181 -0
- package/dist/inference/interruption/interruption_detector.cjs.map +1 -0
- package/dist/inference/interruption/interruption_detector.d.cts +59 -0
- package/dist/inference/interruption/interruption_detector.d.ts +59 -0
- package/dist/inference/interruption/interruption_detector.d.ts.map +1 -0
- package/dist/inference/interruption/interruption_detector.js +147 -0
- package/dist/inference/interruption/interruption_detector.js.map +1 -0
- package/dist/inference/interruption/interruption_stream.cjs +368 -0
- package/dist/inference/interruption/interruption_stream.cjs.map +1 -0
- package/dist/inference/interruption/interruption_stream.d.cts +46 -0
- package/dist/inference/interruption/interruption_stream.d.ts +46 -0
- package/dist/inference/interruption/interruption_stream.d.ts.map +1 -0
- package/dist/inference/interruption/interruption_stream.js +344 -0
- package/dist/inference/interruption/interruption_stream.js.map +1 -0
- package/dist/inference/interruption/types.cjs +17 -0
- package/dist/inference/interruption/types.cjs.map +1 -0
- package/dist/inference/interruption/types.d.cts +66 -0
- package/dist/inference/interruption/types.d.ts +66 -0
- package/dist/inference/interruption/types.d.ts.map +1 -0
- package/dist/inference/interruption/types.js +1 -0
- package/dist/inference/interruption/types.js.map +1 -0
- package/dist/inference/interruption/utils.cjs +130 -0
- package/dist/inference/interruption/utils.cjs.map +1 -0
- package/dist/inference/interruption/utils.d.cts +41 -0
- package/dist/inference/interruption/utils.d.ts +41 -0
- package/dist/inference/interruption/utils.d.ts.map +1 -0
- package/dist/inference/interruption/utils.js +105 -0
- package/dist/inference/interruption/utils.js.map +1 -0
- package/dist/inference/interruption/utils.test.cjs +105 -0
- package/dist/inference/interruption/utils.test.cjs.map +1 -0
- package/dist/inference/interruption/utils.test.js +104 -0
- package/dist/inference/interruption/utils.test.js.map +1 -0
- package/dist/inference/interruption/ws_transport.cjs +329 -0
- package/dist/inference/interruption/ws_transport.cjs.map +1 -0
- package/dist/inference/interruption/ws_transport.d.cts +33 -0
- package/dist/inference/interruption/ws_transport.d.ts +33 -0
- package/dist/inference/interruption/ws_transport.d.ts.map +1 -0
- package/dist/inference/interruption/ws_transport.js +295 -0
- package/dist/inference/interruption/ws_transport.js.map +1 -0
- package/dist/inference/llm.cjs +14 -10
- package/dist/inference/llm.cjs.map +1 -1
- package/dist/inference/llm.d.cts +2 -1
- package/dist/inference/llm.d.ts +2 -1
- package/dist/inference/llm.d.ts.map +1 -1
- package/dist/inference/llm.js +8 -10
- package/dist/inference/llm.js.map +1 -1
- package/dist/inference/stt.cjs +7 -2
- package/dist/inference/stt.cjs.map +1 -1
- package/dist/inference/stt.d.cts +2 -0
- package/dist/inference/stt.d.ts +2 -0
- package/dist/inference/stt.d.ts.map +1 -1
- package/dist/inference/stt.js +8 -3
- package/dist/inference/stt.js.map +1 -1
- package/dist/inference/tts.cjs +7 -2
- package/dist/inference/tts.cjs.map +1 -1
- package/dist/inference/tts.d.cts +2 -0
- package/dist/inference/tts.d.ts +2 -0
- package/dist/inference/tts.d.ts.map +1 -1
- package/dist/inference/tts.js +8 -3
- package/dist/inference/tts.js.map +1 -1
- package/dist/inference/utils.cjs +26 -7
- package/dist/inference/utils.cjs.map +1 -1
- package/dist/inference/utils.d.cts +13 -0
- package/dist/inference/utils.d.ts +13 -0
- package/dist/inference/utils.d.ts.map +1 -1
- package/dist/inference/utils.js +18 -2
- package/dist/inference/utils.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 +19 -1
- package/dist/llm/chat_context.d.ts +19 -1
- 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/index.cjs.map +1 -1
- package/dist/llm/index.d.cts +1 -1
- package/dist/llm/index.d.ts +1 -1
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/llm.cjs +16 -1
- package/dist/llm/llm.cjs.map +1 -1
- package/dist/llm/llm.d.cts +9 -0
- package/dist/llm/llm.d.ts +9 -0
- package/dist/llm/llm.d.ts.map +1 -1
- package/dist/llm/llm.js +16 -1
- package/dist/llm/llm.js.map +1 -1
- package/dist/llm/realtime.cjs +3 -0
- package/dist/llm/realtime.cjs.map +1 -1
- package/dist/llm/realtime.d.cts +1 -0
- package/dist/llm/realtime.d.ts +1 -0
- package/dist/llm/realtime.d.ts.map +1 -1
- package/dist/llm/realtime.js +3 -0
- package/dist/llm/realtime.js.map +1 -1
- package/dist/metrics/base.cjs.map +1 -1
- package/dist/metrics/base.d.cts +45 -1
- package/dist/metrics/base.d.ts +45 -1
- package/dist/metrics/base.d.ts.map +1 -1
- package/dist/metrics/index.cjs +5 -0
- package/dist/metrics/index.cjs.map +1 -1
- package/dist/metrics/index.d.cts +2 -1
- package/dist/metrics/index.d.ts +2 -1
- package/dist/metrics/index.d.ts.map +1 -1
- package/dist/metrics/index.js +6 -0
- package/dist/metrics/index.js.map +1 -1
- package/dist/metrics/model_usage.cjs +189 -0
- package/dist/metrics/model_usage.cjs.map +1 -0
- package/dist/metrics/model_usage.d.cts +92 -0
- package/dist/metrics/model_usage.d.ts +92 -0
- package/dist/metrics/model_usage.d.ts.map +1 -0
- package/dist/metrics/model_usage.js +164 -0
- package/dist/metrics/model_usage.js.map +1 -0
- package/dist/metrics/model_usage.test.cjs +474 -0
- package/dist/metrics/model_usage.test.cjs.map +1 -0
- package/dist/metrics/model_usage.test.js +476 -0
- package/dist/metrics/model_usage.test.js.map +1 -0
- package/dist/metrics/usage_collector.cjs +3 -0
- package/dist/metrics/usage_collector.cjs.map +1 -1
- package/dist/metrics/usage_collector.d.cts +9 -0
- package/dist/metrics/usage_collector.d.ts +9 -0
- package/dist/metrics/usage_collector.d.ts.map +1 -1
- package/dist/metrics/usage_collector.js +3 -0
- package/dist/metrics/usage_collector.js.map +1 -1
- package/dist/metrics/utils.cjs +9 -0
- package/dist/metrics/utils.cjs.map +1 -1
- package/dist/metrics/utils.d.ts.map +1 -1
- package/dist/metrics/utils.js +9 -0
- package/dist/metrics/utils.js.map +1 -1
- package/dist/stream/multi_input_stream.test.cjs +4 -0
- package/dist/stream/multi_input_stream.test.cjs.map +1 -1
- package/dist/stream/multi_input_stream.test.js +5 -1
- package/dist/stream/multi_input_stream.test.js.map +1 -1
- package/dist/stream/stream_channel.cjs +31 -0
- package/dist/stream/stream_channel.cjs.map +1 -1
- package/dist/stream/stream_channel.d.cts +4 -2
- package/dist/stream/stream_channel.d.ts +4 -2
- package/dist/stream/stream_channel.d.ts.map +1 -1
- package/dist/stream/stream_channel.js +31 -0
- package/dist/stream/stream_channel.js.map +1 -1
- package/dist/stt/stt.cjs +34 -2
- package/dist/stt/stt.cjs.map +1 -1
- package/dist/stt/stt.d.cts +22 -0
- package/dist/stt/stt.d.ts +22 -0
- package/dist/stt/stt.d.ts.map +1 -1
- package/dist/stt/stt.js +34 -2
- package/dist/stt/stt.js.map +1 -1
- package/dist/telemetry/otel_http_exporter.cjs +24 -5
- package/dist/telemetry/otel_http_exporter.cjs.map +1 -1
- package/dist/telemetry/otel_http_exporter.d.cts +1 -0
- package/dist/telemetry/otel_http_exporter.d.ts +1 -0
- package/dist/telemetry/otel_http_exporter.d.ts.map +1 -1
- package/dist/telemetry/otel_http_exporter.js +24 -5
- package/dist/telemetry/otel_http_exporter.js.map +1 -1
- package/dist/telemetry/trace_types.cjs +5 -5
- package/dist/telemetry/trace_types.cjs.map +1 -1
- package/dist/telemetry/trace_types.d.cts +9 -5
- package/dist/telemetry/trace_types.d.ts +9 -5
- package/dist/telemetry/trace_types.d.ts.map +1 -1
- package/dist/telemetry/trace_types.js +5 -5
- package/dist/telemetry/trace_types.js.map +1 -1
- package/dist/telemetry/traces.cjs +47 -8
- package/dist/telemetry/traces.cjs.map +1 -1
- package/dist/telemetry/traces.d.ts.map +1 -1
- package/dist/telemetry/traces.js +47 -8
- package/dist/telemetry/traces.js.map +1 -1
- package/dist/tts/tts.cjs +64 -2
- package/dist/tts/tts.cjs.map +1 -1
- package/dist/tts/tts.d.cts +34 -0
- package/dist/tts/tts.d.ts +34 -0
- package/dist/tts/tts.d.ts.map +1 -1
- package/dist/tts/tts.js +64 -2
- package/dist/tts/tts.js.map +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.js +1 -1
- package/dist/voice/agent.cjs +25 -4
- package/dist/voice/agent.cjs.map +1 -1
- package/dist/voice/agent.d.cts +10 -2
- package/dist/voice/agent.d.ts +10 -2
- package/dist/voice/agent.d.ts.map +1 -1
- package/dist/voice/agent.js +25 -4
- package/dist/voice/agent.js.map +1 -1
- package/dist/voice/agent_activity.cjs +261 -36
- package/dist/voice/agent_activity.cjs.map +1 -1
- package/dist/voice/agent_activity.d.cts +20 -6
- package/dist/voice/agent_activity.d.ts +20 -6
- package/dist/voice/agent_activity.d.ts.map +1 -1
- package/dist/voice/agent_activity.js +262 -37
- package/dist/voice/agent_activity.js.map +1 -1
- package/dist/voice/agent_session.cjs +105 -48
- package/dist/voice/agent_session.cjs.map +1 -1
- package/dist/voice/agent_session.d.cts +90 -20
- package/dist/voice/agent_session.d.ts +90 -20
- package/dist/voice/agent_session.d.ts.map +1 -1
- package/dist/voice/agent_session.js +105 -46
- package/dist/voice/agent_session.js.map +1 -1
- package/dist/voice/audio_recognition.cjs +287 -6
- package/dist/voice/audio_recognition.cjs.map +1 -1
- package/dist/voice/audio_recognition.d.cts +42 -3
- package/dist/voice/audio_recognition.d.ts +42 -3
- package/dist/voice/audio_recognition.d.ts.map +1 -1
- package/dist/voice/audio_recognition.js +289 -7
- package/dist/voice/audio_recognition.js.map +1 -1
- package/dist/voice/client_events.cjs +554 -0
- package/dist/voice/client_events.cjs.map +1 -0
- package/dist/voice/client_events.d.cts +195 -0
- package/dist/voice/client_events.d.ts +195 -0
- package/dist/voice/client_events.d.ts.map +1 -0
- package/dist/voice/client_events.js +548 -0
- package/dist/voice/client_events.js.map +1 -0
- package/dist/voice/events.cjs +1 -0
- package/dist/voice/events.cjs.map +1 -1
- package/dist/voice/events.d.cts +8 -5
- package/dist/voice/events.d.ts +8 -5
- package/dist/voice/events.d.ts.map +1 -1
- package/dist/voice/events.js +1 -0
- package/dist/voice/events.js.map +1 -1
- package/dist/voice/generation.cjs +43 -8
- package/dist/voice/generation.cjs.map +1 -1
- package/dist/voice/generation.d.cts +3 -3
- package/dist/voice/generation.d.ts +3 -3
- package/dist/voice/generation.d.ts.map +1 -1
- package/dist/voice/generation.js +43 -8
- package/dist/voice/generation.js.map +1 -1
- package/dist/voice/index.cjs +1 -0
- package/dist/voice/index.cjs.map +1 -1
- package/dist/voice/index.d.cts +1 -0
- package/dist/voice/index.d.ts +1 -0
- package/dist/voice/index.d.ts.map +1 -1
- package/dist/voice/index.js +1 -0
- package/dist/voice/index.js.map +1 -1
- package/dist/voice/report.cjs +20 -8
- package/dist/voice/report.cjs.map +1 -1
- package/dist/voice/report.d.cts +5 -0
- package/dist/voice/report.d.ts +5 -0
- package/dist/voice/report.d.ts.map +1 -1
- package/dist/voice/report.js +20 -8
- package/dist/voice/report.js.map +1 -1
- package/dist/voice/report.test.cjs +106 -0
- package/dist/voice/report.test.cjs.map +1 -0
- package/dist/voice/report.test.js +105 -0
- package/dist/voice/report.test.js.map +1 -0
- package/dist/voice/room_io/room_io.cjs +5 -39
- package/dist/voice/room_io/room_io.cjs.map +1 -1
- package/dist/voice/room_io/room_io.d.cts +4 -9
- package/dist/voice/room_io/room_io.d.ts +4 -9
- package/dist/voice/room_io/room_io.d.ts.map +1 -1
- package/dist/voice/room_io/room_io.js +5 -40
- package/dist/voice/room_io/room_io.js.map +1 -1
- package/dist/voice/turn_config/endpointing.cjs +33 -0
- package/dist/voice/turn_config/endpointing.cjs.map +1 -0
- package/dist/voice/turn_config/endpointing.d.cts +30 -0
- package/dist/voice/turn_config/endpointing.d.ts +30 -0
- package/dist/voice/turn_config/endpointing.d.ts.map +1 -0
- package/dist/voice/turn_config/endpointing.js +9 -0
- package/dist/voice/turn_config/endpointing.js.map +1 -0
- package/dist/voice/turn_config/interruption.cjs +37 -0
- package/dist/voice/turn_config/interruption.cjs.map +1 -0
- package/dist/voice/turn_config/interruption.d.cts +53 -0
- package/dist/voice/turn_config/interruption.d.ts +53 -0
- package/dist/voice/turn_config/interruption.d.ts.map +1 -0
- package/dist/voice/turn_config/interruption.js +13 -0
- package/dist/voice/turn_config/interruption.js.map +1 -0
- package/dist/voice/turn_config/turn_handling.cjs +35 -0
- package/dist/voice/turn_config/turn_handling.cjs.map +1 -0
- package/dist/voice/turn_config/turn_handling.d.cts +36 -0
- package/dist/voice/turn_config/turn_handling.d.ts +36 -0
- package/dist/voice/turn_config/turn_handling.d.ts.map +1 -0
- package/dist/voice/turn_config/turn_handling.js +11 -0
- package/dist/voice/turn_config/turn_handling.js.map +1 -0
- package/dist/voice/turn_config/utils.cjs +97 -0
- package/dist/voice/turn_config/utils.cjs.map +1 -0
- package/dist/voice/turn_config/utils.d.cts +25 -0
- package/dist/voice/turn_config/utils.d.ts +25 -0
- package/dist/voice/turn_config/utils.d.ts.map +1 -0
- package/dist/voice/turn_config/utils.js +73 -0
- package/dist/voice/turn_config/utils.js.map +1 -0
- package/dist/voice/turn_config/utils.test.cjs +86 -0
- package/dist/voice/turn_config/utils.test.cjs.map +1 -0
- package/dist/voice/turn_config/utils.test.js +85 -0
- package/dist/voice/turn_config/utils.test.js.map +1 -0
- package/dist/voice/wire_format.cjs +798 -0
- package/dist/voice/wire_format.cjs.map +1 -0
- package/dist/voice/wire_format.d.cts +5503 -0
- package/dist/voice/wire_format.d.ts +5503 -0
- package/dist/voice/wire_format.d.ts.map +1 -0
- package/dist/voice/wire_format.js +728 -0
- package/dist/voice/wire_format.js.map +1 -0
- package/package.json +2 -1
- package/src/constants.ts +13 -0
- package/src/inference/interruption/defaults.ts +51 -0
- package/src/inference/interruption/errors.ts +25 -0
- package/src/inference/interruption/http_transport.ts +187 -0
- package/src/inference/interruption/interruption_cache_entry.ts +50 -0
- package/src/inference/interruption/interruption_detector.ts +188 -0
- package/src/inference/interruption/interruption_stream.ts +467 -0
- package/src/inference/interruption/types.ts +84 -0
- package/src/inference/interruption/utils.test.ts +132 -0
- package/src/inference/interruption/utils.ts +137 -0
- package/src/inference/interruption/ws_transport.ts +402 -0
- package/src/inference/llm.ts +9 -12
- package/src/inference/stt.ts +10 -3
- package/src/inference/tts.ts +10 -3
- package/src/inference/utils.ts +29 -1
- package/src/llm/chat_context.ts +40 -2
- package/src/llm/index.ts +1 -0
- package/src/llm/llm.ts +16 -0
- package/src/llm/realtime.ts +4 -0
- package/src/metrics/base.ts +48 -1
- package/src/metrics/index.ts +11 -0
- package/src/metrics/model_usage.test.ts +545 -0
- package/src/metrics/model_usage.ts +262 -0
- package/src/metrics/usage_collector.ts +11 -0
- package/src/metrics/utils.ts +11 -0
- package/src/stream/multi_input_stream.test.ts +6 -1
- package/src/stream/stream_channel.ts +34 -2
- package/src/stt/stt.ts +38 -0
- package/src/telemetry/otel_http_exporter.ts +28 -5
- package/src/telemetry/trace_types.ts +11 -8
- package/src/telemetry/traces.ts +111 -54
- package/src/tts/tts.ts +69 -1
- package/src/voice/agent.ts +30 -3
- package/src/voice/agent_activity.ts +327 -28
- package/src/voice/agent_session.ts +207 -59
- package/src/voice/audio_recognition.ts +385 -9
- package/src/voice/client_events.ts +838 -0
- package/src/voice/events.ts +14 -4
- package/src/voice/generation.ts +52 -9
- package/src/voice/index.ts +1 -0
- package/src/voice/report.test.ts +117 -0
- package/src/voice/report.ts +29 -6
- package/src/voice/room_io/room_io.ts +7 -61
- package/src/voice/turn_config/endpointing.ts +33 -0
- package/src/voice/turn_config/interruption.ts +56 -0
- package/src/voice/turn_config/turn_handling.ts +45 -0
- package/src/voice/turn_config/utils.test.ts +100 -0
- package/src/voice/turn_config/utils.ts +103 -0
- package/src/voice/wire_format.ts +827 -0
|
@@ -0,0 +1,130 @@
|
|
|
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 utils_exports = {};
|
|
20
|
+
__export(utils_exports, {
|
|
21
|
+
BoundedCache: () => BoundedCache,
|
|
22
|
+
estimateProbability: () => estimateProbability
|
|
23
|
+
});
|
|
24
|
+
module.exports = __toCommonJS(utils_exports);
|
|
25
|
+
var import_defaults = require("./defaults.cjs");
|
|
26
|
+
class BoundedCache {
|
|
27
|
+
cache = /* @__PURE__ */ new Map();
|
|
28
|
+
maxLen;
|
|
29
|
+
constructor(maxLen = 10) {
|
|
30
|
+
this.maxLen = maxLen;
|
|
31
|
+
}
|
|
32
|
+
set(key, value) {
|
|
33
|
+
this.cache.set(key, value);
|
|
34
|
+
if (this.cache.size > this.maxLen) {
|
|
35
|
+
const firstKey = this.cache.keys().next().value;
|
|
36
|
+
this.cache.delete(firstKey);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Update existing value fields if present and defined.
|
|
41
|
+
* Mirrors python BoundedDict.update_value behavior.
|
|
42
|
+
*/
|
|
43
|
+
updateValue(key, fields) {
|
|
44
|
+
const value = this.cache.get(key);
|
|
45
|
+
if (!value) return value;
|
|
46
|
+
for (const [fieldName, fieldValue] of Object.entries(fields)) {
|
|
47
|
+
if (fieldValue === void 0) continue;
|
|
48
|
+
if (fieldName in value) {
|
|
49
|
+
value[String(fieldName)] = fieldValue;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Set a new value with factory when missing; otherwise update in place.
|
|
56
|
+
* Mirrors python BoundedDict.set_or_update behavior.
|
|
57
|
+
*/
|
|
58
|
+
setOrUpdate(key, factory, fields) {
|
|
59
|
+
if (!this.cache.has(key)) {
|
|
60
|
+
this.set(key, factory());
|
|
61
|
+
}
|
|
62
|
+
const result = this.updateValue(key, fields);
|
|
63
|
+
if (!result) {
|
|
64
|
+
throw new Error("setOrUpdate invariant failed: entry should exist after set");
|
|
65
|
+
}
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
get(key) {
|
|
69
|
+
return this.cache.get(key);
|
|
70
|
+
}
|
|
71
|
+
has(key) {
|
|
72
|
+
return this.cache.has(key);
|
|
73
|
+
}
|
|
74
|
+
delete(key) {
|
|
75
|
+
return this.cache.delete(key);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Pop an entry if it satisfies the predicate.
|
|
79
|
+
* - No predicate: pop oldest (FIFO)
|
|
80
|
+
* - With predicate: search in reverse order and pop first match
|
|
81
|
+
*/
|
|
82
|
+
pop(predicate) {
|
|
83
|
+
if (predicate === void 0) {
|
|
84
|
+
const first = this.cache.entries().next().value;
|
|
85
|
+
if (!first) return void 0;
|
|
86
|
+
const [key, value] = first;
|
|
87
|
+
this.cache.delete(key);
|
|
88
|
+
return value;
|
|
89
|
+
}
|
|
90
|
+
const keys = Array.from(this.cache.keys());
|
|
91
|
+
for (let i = keys.length - 1; i >= 0; i--) {
|
|
92
|
+
const key = keys[i];
|
|
93
|
+
const value = this.cache.get(key);
|
|
94
|
+
if (predicate(value)) {
|
|
95
|
+
this.cache.delete(key);
|
|
96
|
+
return value;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return void 0;
|
|
100
|
+
}
|
|
101
|
+
clear() {
|
|
102
|
+
this.cache.clear();
|
|
103
|
+
}
|
|
104
|
+
get size() {
|
|
105
|
+
return this.cache.size;
|
|
106
|
+
}
|
|
107
|
+
values() {
|
|
108
|
+
return this.cache.values();
|
|
109
|
+
}
|
|
110
|
+
keys() {
|
|
111
|
+
return this.cache.keys();
|
|
112
|
+
}
|
|
113
|
+
entries() {
|
|
114
|
+
return this.cache.entries();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function estimateProbability(probabilities, windowSizeInS = import_defaults.MIN_INTERRUPTION_DURATION_IN_S) {
|
|
118
|
+
const nTh = Math.ceil(windowSizeInS / import_defaults.FRAME_DURATION_IN_S);
|
|
119
|
+
if (probabilities.length < nTh) {
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
122
|
+
const sorted = [...probabilities].sort((a, b) => b - a);
|
|
123
|
+
return sorted[nTh - 1];
|
|
124
|
+
}
|
|
125
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
126
|
+
0 && (module.exports = {
|
|
127
|
+
BoundedCache,
|
|
128
|
+
estimateProbability
|
|
129
|
+
});
|
|
130
|
+
//# sourceMappingURL=utils.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/inference/interruption/utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2026 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { FRAME_DURATION_IN_S, MIN_INTERRUPTION_DURATION_IN_S } from './defaults.js';\n\n/**\n * A bounded cache that automatically evicts the oldest entries when the cache exceeds max size.\n * Uses FIFO eviction strategy.\n */\nexport class BoundedCache<K, V extends object> {\n private cache: Map<K, V> = new Map();\n private readonly maxLen: number;\n\n constructor(maxLen: number = 10) {\n this.maxLen = maxLen;\n }\n\n set(key: K, value: V): void {\n this.cache.set(key, value);\n if (this.cache.size > this.maxLen) {\n // Remove the oldest entry (first inserted)\n const firstKey = this.cache.keys().next().value as K;\n this.cache.delete(firstKey);\n }\n }\n\n /**\n * Update existing value fields if present and defined.\n * Mirrors python BoundedDict.update_value behavior.\n */\n updateValue(key: K, fields: Partial<V>): V | undefined {\n const value = this.cache.get(key);\n if (!value) return value;\n\n for (const [fieldName, fieldValue] of Object.entries(fields) as [keyof V, V[keyof V]][]) {\n if (fieldValue === undefined) continue;\n // Runtime field update parity with python's hasattr + setattr.\n if (fieldName in (value as object)) {\n (value as Record<string, unknown>)[String(fieldName)] = fieldValue;\n }\n }\n return value;\n }\n\n /**\n * Set a new value with factory when missing; otherwise update in place.\n * Mirrors python BoundedDict.set_or_update behavior.\n */\n setOrUpdate(key: K, factory: () => V, fields: Partial<V>): V {\n if (!this.cache.has(key)) {\n this.set(key, factory());\n }\n const result = this.updateValue(key, fields);\n if (!result) {\n throw new Error('setOrUpdate invariant failed: entry should exist after set');\n }\n return result;\n }\n\n get(key: K): V | undefined {\n return this.cache.get(key);\n }\n\n has(key: K): boolean {\n return this.cache.has(key);\n }\n\n delete(key: K): boolean {\n return this.cache.delete(key);\n }\n\n /**\n * Pop an entry if it satisfies the predicate.\n * - No predicate: pop oldest (FIFO)\n * - With predicate: search in reverse order and pop first match\n */\n pop(predicate?: (value: V) => boolean): V | undefined {\n if (predicate === undefined) {\n const first = this.cache.entries().next().value as [K, V] | undefined;\n if (!first) return undefined;\n const [key, value] = first;\n this.cache.delete(key);\n return value;\n }\n\n const keys = Array.from(this.cache.keys());\n for (let i = keys.length - 1; i >= 0; i--) {\n const key = keys[i]!;\n const value = this.cache.get(key)!;\n if (predicate(value)) {\n this.cache.delete(key);\n return value;\n }\n }\n return undefined;\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n get size(): number {\n return this.cache.size;\n }\n\n values(): IterableIterator<V> {\n return this.cache.values();\n }\n\n keys(): IterableIterator<K> {\n return this.cache.keys();\n }\n\n entries(): IterableIterator<[K, V]> {\n return this.cache.entries();\n }\n}\n\n/**\n * Estimate probability by finding the n-th maximum value in the probabilities array.\n * The n-th position is determined by the window size (25ms per frame).\n * Returns 0 if there are insufficient probabilities.\n */\nexport function estimateProbability(\n probabilities: number[],\n windowSizeInS: number = MIN_INTERRUPTION_DURATION_IN_S,\n): number {\n const nTh = Math.ceil(windowSizeInS / FRAME_DURATION_IN_S);\n if (probabilities.length < nTh) {\n return 0;\n }\n\n // Find the n-th maximum value by sorting in descending order\n // Create a copy to avoid mutating the original array\n const sorted = [...probabilities].sort((a, b) => b - a);\n return sorted[nTh - 1]!;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,sBAAoE;AAM7D,MAAM,aAAkC;AAAA,EACrC,QAAmB,oBAAI,IAAI;AAAA,EAClB;AAAA,EAEjB,YAAY,SAAiB,IAAI;AAC/B,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,IAAI,KAAQ,OAAgB;AAC1B,SAAK,MAAM,IAAI,KAAK,KAAK;AACzB,QAAI,KAAK,MAAM,OAAO,KAAK,QAAQ;AAEjC,YAAM,WAAW,KAAK,MAAM,KAAK,EAAE,KAAK,EAAE;AAC1C,WAAK,MAAM,OAAO,QAAQ;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,KAAQ,QAAmC;AACrD,UAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;AAChC,QAAI,CAAC,MAAO,QAAO;AAEnB,eAAW,CAAC,WAAW,UAAU,KAAK,OAAO,QAAQ,MAAM,GAA8B;AACvF,UAAI,eAAe,OAAW;AAE9B,UAAI,aAAc,OAAkB;AAClC,QAAC,MAAkC,OAAO,SAAS,CAAC,IAAI;AAAA,MAC1D;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,KAAQ,SAAkB,QAAuB;AAC3D,QAAI,CAAC,KAAK,MAAM,IAAI,GAAG,GAAG;AACxB,WAAK,IAAI,KAAK,QAAQ,CAAC;AAAA,IACzB;AACA,UAAM,SAAS,KAAK,YAAY,KAAK,MAAM;AAC3C,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,4DAA4D;AAAA,IAC9E;AACA,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,KAAuB;AACzB,WAAO,KAAK,MAAM,IAAI,GAAG;AAAA,EAC3B;AAAA,EAEA,IAAI,KAAiB;AACnB,WAAO,KAAK,MAAM,IAAI,GAAG;AAAA,EAC3B;AAAA,EAEA,OAAO,KAAiB;AACtB,WAAO,KAAK,MAAM,OAAO,GAAG;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,WAAkD;AACpD,QAAI,cAAc,QAAW;AAC3B,YAAM,QAAQ,KAAK,MAAM,QAAQ,EAAE,KAAK,EAAE;AAC1C,UAAI,CAAC,MAAO,QAAO;AACnB,YAAM,CAAC,KAAK,KAAK,IAAI;AACrB,WAAK,MAAM,OAAO,GAAG;AACrB,aAAO;AAAA,IACT;AAEA,UAAM,OAAO,MAAM,KAAK,KAAK,MAAM,KAAK,CAAC;AACzC,aAAS,IAAI,KAAK,SAAS,GAAG,KAAK,GAAG,KAAK;AACzC,YAAM,MAAM,KAAK,CAAC;AAClB,YAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;AAChC,UAAI,UAAU,KAAK,GAAG;AACpB,aAAK,MAAM,OAAO,GAAG;AACrB,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,QAAc;AACZ,SAAK,MAAM,MAAM;AAAA,EACnB;AAAA,EAEA,IAAI,OAAe;AACjB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA,EAEA,SAA8B;AAC5B,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B;AAAA,EAEA,OAA4B;AAC1B,WAAO,KAAK,MAAM,KAAK;AAAA,EACzB;AAAA,EAEA,UAAoC;AAClC,WAAO,KAAK,MAAM,QAAQ;AAAA,EAC5B;AACF;AAOO,SAAS,oBACd,eACA,gBAAwB,gDAChB;AACR,QAAM,MAAM,KAAK,KAAK,gBAAgB,mCAAmB;AACzD,MAAI,cAAc,SAAS,KAAK;AAC9B,WAAO;AAAA,EACT;AAIA,QAAM,SAAS,CAAC,GAAG,aAAa,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACtD,SAAO,OAAO,MAAM,CAAC;AACvB;","names":[]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A bounded cache that automatically evicts the oldest entries when the cache exceeds max size.
|
|
3
|
+
* Uses FIFO eviction strategy.
|
|
4
|
+
*/
|
|
5
|
+
export declare class BoundedCache<K, V extends object> {
|
|
6
|
+
private cache;
|
|
7
|
+
private readonly maxLen;
|
|
8
|
+
constructor(maxLen?: number);
|
|
9
|
+
set(key: K, value: V): void;
|
|
10
|
+
/**
|
|
11
|
+
* Update existing value fields if present and defined.
|
|
12
|
+
* Mirrors python BoundedDict.update_value behavior.
|
|
13
|
+
*/
|
|
14
|
+
updateValue(key: K, fields: Partial<V>): V | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Set a new value with factory when missing; otherwise update in place.
|
|
17
|
+
* Mirrors python BoundedDict.set_or_update behavior.
|
|
18
|
+
*/
|
|
19
|
+
setOrUpdate(key: K, factory: () => V, fields: Partial<V>): V;
|
|
20
|
+
get(key: K): V | undefined;
|
|
21
|
+
has(key: K): boolean;
|
|
22
|
+
delete(key: K): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Pop an entry if it satisfies the predicate.
|
|
25
|
+
* - No predicate: pop oldest (FIFO)
|
|
26
|
+
* - With predicate: search in reverse order and pop first match
|
|
27
|
+
*/
|
|
28
|
+
pop(predicate?: (value: V) => boolean): V | undefined;
|
|
29
|
+
clear(): void;
|
|
30
|
+
get size(): number;
|
|
31
|
+
values(): IterableIterator<V>;
|
|
32
|
+
keys(): IterableIterator<K>;
|
|
33
|
+
entries(): IterableIterator<[K, V]>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Estimate probability by finding the n-th maximum value in the probabilities array.
|
|
37
|
+
* The n-th position is determined by the window size (25ms per frame).
|
|
38
|
+
* Returns 0 if there are insufficient probabilities.
|
|
39
|
+
*/
|
|
40
|
+
export declare function estimateProbability(probabilities: number[], windowSizeInS?: number): number;
|
|
41
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A bounded cache that automatically evicts the oldest entries when the cache exceeds max size.
|
|
3
|
+
* Uses FIFO eviction strategy.
|
|
4
|
+
*/
|
|
5
|
+
export declare class BoundedCache<K, V extends object> {
|
|
6
|
+
private cache;
|
|
7
|
+
private readonly maxLen;
|
|
8
|
+
constructor(maxLen?: number);
|
|
9
|
+
set(key: K, value: V): void;
|
|
10
|
+
/**
|
|
11
|
+
* Update existing value fields if present and defined.
|
|
12
|
+
* Mirrors python BoundedDict.update_value behavior.
|
|
13
|
+
*/
|
|
14
|
+
updateValue(key: K, fields: Partial<V>): V | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Set a new value with factory when missing; otherwise update in place.
|
|
17
|
+
* Mirrors python BoundedDict.set_or_update behavior.
|
|
18
|
+
*/
|
|
19
|
+
setOrUpdate(key: K, factory: () => V, fields: Partial<V>): V;
|
|
20
|
+
get(key: K): V | undefined;
|
|
21
|
+
has(key: K): boolean;
|
|
22
|
+
delete(key: K): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Pop an entry if it satisfies the predicate.
|
|
25
|
+
* - No predicate: pop oldest (FIFO)
|
|
26
|
+
* - With predicate: search in reverse order and pop first match
|
|
27
|
+
*/
|
|
28
|
+
pop(predicate?: (value: V) => boolean): V | undefined;
|
|
29
|
+
clear(): void;
|
|
30
|
+
get size(): number;
|
|
31
|
+
values(): IterableIterator<V>;
|
|
32
|
+
keys(): IterableIterator<K>;
|
|
33
|
+
entries(): IterableIterator<[K, V]>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Estimate probability by finding the n-th maximum value in the probabilities array.
|
|
37
|
+
* The n-th position is determined by the window size (25ms per frame).
|
|
38
|
+
* Returns 0 if there are insufficient probabilities.
|
|
39
|
+
*/
|
|
40
|
+
export declare function estimateProbability(probabilities: number[], windowSizeInS?: number): number;
|
|
41
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/inference/interruption/utils.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,qBAAa,YAAY,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM;IAC3C,OAAO,CAAC,KAAK,CAAwB;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,MAAM,GAAE,MAAW;IAI/B,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAS3B;;;OAGG;IACH,WAAW,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,SAAS;IActD;;;OAGG;IACH,WAAW,CAAC,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAW5D,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS;IAI1B,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO;IAIpB,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO;IAIvB;;;;OAIG;IACH,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,CAAC,GAAG,SAAS;IAqBrD,KAAK,IAAI,IAAI;IAIb,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,MAAM,IAAI,gBAAgB,CAAC,CAAC,CAAC;IAI7B,IAAI,IAAI,gBAAgB,CAAC,CAAC,CAAC;IAI3B,OAAO,IAAI,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CAGpC;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,MAAM,EAAE,EACvB,aAAa,GAAE,MAAuC,GACrD,MAAM,CAUR"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { FRAME_DURATION_IN_S, MIN_INTERRUPTION_DURATION_IN_S } from "./defaults.js";
|
|
2
|
+
class BoundedCache {
|
|
3
|
+
cache = /* @__PURE__ */ new Map();
|
|
4
|
+
maxLen;
|
|
5
|
+
constructor(maxLen = 10) {
|
|
6
|
+
this.maxLen = maxLen;
|
|
7
|
+
}
|
|
8
|
+
set(key, value) {
|
|
9
|
+
this.cache.set(key, value);
|
|
10
|
+
if (this.cache.size > this.maxLen) {
|
|
11
|
+
const firstKey = this.cache.keys().next().value;
|
|
12
|
+
this.cache.delete(firstKey);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Update existing value fields if present and defined.
|
|
17
|
+
* Mirrors python BoundedDict.update_value behavior.
|
|
18
|
+
*/
|
|
19
|
+
updateValue(key, fields) {
|
|
20
|
+
const value = this.cache.get(key);
|
|
21
|
+
if (!value) return value;
|
|
22
|
+
for (const [fieldName, fieldValue] of Object.entries(fields)) {
|
|
23
|
+
if (fieldValue === void 0) continue;
|
|
24
|
+
if (fieldName in value) {
|
|
25
|
+
value[String(fieldName)] = fieldValue;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Set a new value with factory when missing; otherwise update in place.
|
|
32
|
+
* Mirrors python BoundedDict.set_or_update behavior.
|
|
33
|
+
*/
|
|
34
|
+
setOrUpdate(key, factory, fields) {
|
|
35
|
+
if (!this.cache.has(key)) {
|
|
36
|
+
this.set(key, factory());
|
|
37
|
+
}
|
|
38
|
+
const result = this.updateValue(key, fields);
|
|
39
|
+
if (!result) {
|
|
40
|
+
throw new Error("setOrUpdate invariant failed: entry should exist after set");
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
get(key) {
|
|
45
|
+
return this.cache.get(key);
|
|
46
|
+
}
|
|
47
|
+
has(key) {
|
|
48
|
+
return this.cache.has(key);
|
|
49
|
+
}
|
|
50
|
+
delete(key) {
|
|
51
|
+
return this.cache.delete(key);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Pop an entry if it satisfies the predicate.
|
|
55
|
+
* - No predicate: pop oldest (FIFO)
|
|
56
|
+
* - With predicate: search in reverse order and pop first match
|
|
57
|
+
*/
|
|
58
|
+
pop(predicate) {
|
|
59
|
+
if (predicate === void 0) {
|
|
60
|
+
const first = this.cache.entries().next().value;
|
|
61
|
+
if (!first) return void 0;
|
|
62
|
+
const [key, value] = first;
|
|
63
|
+
this.cache.delete(key);
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
const keys = Array.from(this.cache.keys());
|
|
67
|
+
for (let i = keys.length - 1; i >= 0; i--) {
|
|
68
|
+
const key = keys[i];
|
|
69
|
+
const value = this.cache.get(key);
|
|
70
|
+
if (predicate(value)) {
|
|
71
|
+
this.cache.delete(key);
|
|
72
|
+
return value;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return void 0;
|
|
76
|
+
}
|
|
77
|
+
clear() {
|
|
78
|
+
this.cache.clear();
|
|
79
|
+
}
|
|
80
|
+
get size() {
|
|
81
|
+
return this.cache.size;
|
|
82
|
+
}
|
|
83
|
+
values() {
|
|
84
|
+
return this.cache.values();
|
|
85
|
+
}
|
|
86
|
+
keys() {
|
|
87
|
+
return this.cache.keys();
|
|
88
|
+
}
|
|
89
|
+
entries() {
|
|
90
|
+
return this.cache.entries();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function estimateProbability(probabilities, windowSizeInS = MIN_INTERRUPTION_DURATION_IN_S) {
|
|
94
|
+
const nTh = Math.ceil(windowSizeInS / FRAME_DURATION_IN_S);
|
|
95
|
+
if (probabilities.length < nTh) {
|
|
96
|
+
return 0;
|
|
97
|
+
}
|
|
98
|
+
const sorted = [...probabilities].sort((a, b) => b - a);
|
|
99
|
+
return sorted[nTh - 1];
|
|
100
|
+
}
|
|
101
|
+
export {
|
|
102
|
+
BoundedCache,
|
|
103
|
+
estimateProbability
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/inference/interruption/utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2026 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { FRAME_DURATION_IN_S, MIN_INTERRUPTION_DURATION_IN_S } from './defaults.js';\n\n/**\n * A bounded cache that automatically evicts the oldest entries when the cache exceeds max size.\n * Uses FIFO eviction strategy.\n */\nexport class BoundedCache<K, V extends object> {\n private cache: Map<K, V> = new Map();\n private readonly maxLen: number;\n\n constructor(maxLen: number = 10) {\n this.maxLen = maxLen;\n }\n\n set(key: K, value: V): void {\n this.cache.set(key, value);\n if (this.cache.size > this.maxLen) {\n // Remove the oldest entry (first inserted)\n const firstKey = this.cache.keys().next().value as K;\n this.cache.delete(firstKey);\n }\n }\n\n /**\n * Update existing value fields if present and defined.\n * Mirrors python BoundedDict.update_value behavior.\n */\n updateValue(key: K, fields: Partial<V>): V | undefined {\n const value = this.cache.get(key);\n if (!value) return value;\n\n for (const [fieldName, fieldValue] of Object.entries(fields) as [keyof V, V[keyof V]][]) {\n if (fieldValue === undefined) continue;\n // Runtime field update parity with python's hasattr + setattr.\n if (fieldName in (value as object)) {\n (value as Record<string, unknown>)[String(fieldName)] = fieldValue;\n }\n }\n return value;\n }\n\n /**\n * Set a new value with factory when missing; otherwise update in place.\n * Mirrors python BoundedDict.set_or_update behavior.\n */\n setOrUpdate(key: K, factory: () => V, fields: Partial<V>): V {\n if (!this.cache.has(key)) {\n this.set(key, factory());\n }\n const result = this.updateValue(key, fields);\n if (!result) {\n throw new Error('setOrUpdate invariant failed: entry should exist after set');\n }\n return result;\n }\n\n get(key: K): V | undefined {\n return this.cache.get(key);\n }\n\n has(key: K): boolean {\n return this.cache.has(key);\n }\n\n delete(key: K): boolean {\n return this.cache.delete(key);\n }\n\n /**\n * Pop an entry if it satisfies the predicate.\n * - No predicate: pop oldest (FIFO)\n * - With predicate: search in reverse order and pop first match\n */\n pop(predicate?: (value: V) => boolean): V | undefined {\n if (predicate === undefined) {\n const first = this.cache.entries().next().value as [K, V] | undefined;\n if (!first) return undefined;\n const [key, value] = first;\n this.cache.delete(key);\n return value;\n }\n\n const keys = Array.from(this.cache.keys());\n for (let i = keys.length - 1; i >= 0; i--) {\n const key = keys[i]!;\n const value = this.cache.get(key)!;\n if (predicate(value)) {\n this.cache.delete(key);\n return value;\n }\n }\n return undefined;\n }\n\n clear(): void {\n this.cache.clear();\n }\n\n get size(): number {\n return this.cache.size;\n }\n\n values(): IterableIterator<V> {\n return this.cache.values();\n }\n\n keys(): IterableIterator<K> {\n return this.cache.keys();\n }\n\n entries(): IterableIterator<[K, V]> {\n return this.cache.entries();\n }\n}\n\n/**\n * Estimate probability by finding the n-th maximum value in the probabilities array.\n * The n-th position is determined by the window size (25ms per frame).\n * Returns 0 if there are insufficient probabilities.\n */\nexport function estimateProbability(\n probabilities: number[],\n windowSizeInS: number = MIN_INTERRUPTION_DURATION_IN_S,\n): number {\n const nTh = Math.ceil(windowSizeInS / FRAME_DURATION_IN_S);\n if (probabilities.length < nTh) {\n return 0;\n }\n\n // Find the n-th maximum value by sorting in descending order\n // Create a copy to avoid mutating the original array\n const sorted = [...probabilities].sort((a, b) => b - a);\n return sorted[nTh - 1]!;\n}\n"],"mappings":"AAGA,SAAS,qBAAqB,sCAAsC;AAM7D,MAAM,aAAkC;AAAA,EACrC,QAAmB,oBAAI,IAAI;AAAA,EAClB;AAAA,EAEjB,YAAY,SAAiB,IAAI;AAC/B,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,IAAI,KAAQ,OAAgB;AAC1B,SAAK,MAAM,IAAI,KAAK,KAAK;AACzB,QAAI,KAAK,MAAM,OAAO,KAAK,QAAQ;AAEjC,YAAM,WAAW,KAAK,MAAM,KAAK,EAAE,KAAK,EAAE;AAC1C,WAAK,MAAM,OAAO,QAAQ;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,KAAQ,QAAmC;AACrD,UAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;AAChC,QAAI,CAAC,MAAO,QAAO;AAEnB,eAAW,CAAC,WAAW,UAAU,KAAK,OAAO,QAAQ,MAAM,GAA8B;AACvF,UAAI,eAAe,OAAW;AAE9B,UAAI,aAAc,OAAkB;AAClC,QAAC,MAAkC,OAAO,SAAS,CAAC,IAAI;AAAA,MAC1D;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,KAAQ,SAAkB,QAAuB;AAC3D,QAAI,CAAC,KAAK,MAAM,IAAI,GAAG,GAAG;AACxB,WAAK,IAAI,KAAK,QAAQ,CAAC;AAAA,IACzB;AACA,UAAM,SAAS,KAAK,YAAY,KAAK,MAAM;AAC3C,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,4DAA4D;AAAA,IAC9E;AACA,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,KAAuB;AACzB,WAAO,KAAK,MAAM,IAAI,GAAG;AAAA,EAC3B;AAAA,EAEA,IAAI,KAAiB;AACnB,WAAO,KAAK,MAAM,IAAI,GAAG;AAAA,EAC3B;AAAA,EAEA,OAAO,KAAiB;AACtB,WAAO,KAAK,MAAM,OAAO,GAAG;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,IAAI,WAAkD;AACpD,QAAI,cAAc,QAAW;AAC3B,YAAM,QAAQ,KAAK,MAAM,QAAQ,EAAE,KAAK,EAAE;AAC1C,UAAI,CAAC,MAAO,QAAO;AACnB,YAAM,CAAC,KAAK,KAAK,IAAI;AACrB,WAAK,MAAM,OAAO,GAAG;AACrB,aAAO;AAAA,IACT;AAEA,UAAM,OAAO,MAAM,KAAK,KAAK,MAAM,KAAK,CAAC;AACzC,aAAS,IAAI,KAAK,SAAS,GAAG,KAAK,GAAG,KAAK;AACzC,YAAM,MAAM,KAAK,CAAC;AAClB,YAAM,QAAQ,KAAK,MAAM,IAAI,GAAG;AAChC,UAAI,UAAU,KAAK,GAAG;AACpB,aAAK,MAAM,OAAO,GAAG;AACrB,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,QAAc;AACZ,SAAK,MAAM,MAAM;AAAA,EACnB;AAAA,EAEA,IAAI,OAAe;AACjB,WAAO,KAAK,MAAM;AAAA,EACpB;AAAA,EAEA,SAA8B;AAC5B,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B;AAAA,EAEA,OAA4B;AAC1B,WAAO,KAAK,MAAM,KAAK;AAAA,EACzB;AAAA,EAEA,UAAoC;AAClC,WAAO,KAAK,MAAM,QAAQ;AAAA,EAC5B;AACF;AAOO,SAAS,oBACd,eACA,gBAAwB,gCAChB;AACR,QAAM,MAAM,KAAK,KAAK,gBAAgB,mBAAmB;AACzD,MAAI,cAAc,SAAS,KAAK;AAC9B,WAAO;AAAA,EACT;AAIA,QAAM,SAAS,CAAC,GAAG,aAAa,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AACtD,SAAO,OAAO,MAAM,CAAC;AACvB;","names":[]}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var import_vitest = require("vitest");
|
|
3
|
+
var import_utils = require("./utils.cjs");
|
|
4
|
+
class Entry {
|
|
5
|
+
createdAt;
|
|
6
|
+
totalDurationInS = void 0;
|
|
7
|
+
predictionDurationInS = void 0;
|
|
8
|
+
note = void 0;
|
|
9
|
+
constructor(createdAt, note) {
|
|
10
|
+
this.createdAt = createdAt;
|
|
11
|
+
this.note = note;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
(0, import_vitest.describe)("BoundedCache", () => {
|
|
15
|
+
(0, import_vitest.it)("evicts oldest entry when maxLen is exceeded", () => {
|
|
16
|
+
const cache = new import_utils.BoundedCache(2);
|
|
17
|
+
cache.set(1, new Entry(1));
|
|
18
|
+
cache.set(2, new Entry(2));
|
|
19
|
+
cache.set(3, new Entry(3));
|
|
20
|
+
(0, import_vitest.expect)(cache.size).toBe(2);
|
|
21
|
+
(0, import_vitest.expect)([...cache.keys()]).toEqual([2, 3]);
|
|
22
|
+
(0, import_vitest.expect)(cache.get(1)).toBeUndefined();
|
|
23
|
+
(0, import_vitest.expect)(cache.get(2).createdAt).toBe(2);
|
|
24
|
+
(0, import_vitest.expect)(cache.get(3).createdAt).toBe(3);
|
|
25
|
+
});
|
|
26
|
+
(0, import_vitest.it)("setOrUpdate creates a value via factory when key is missing", () => {
|
|
27
|
+
var _a;
|
|
28
|
+
const cache = new import_utils.BoundedCache(10);
|
|
29
|
+
const factory = import_vitest.vi.fn(() => new Entry(100));
|
|
30
|
+
const value = cache.setOrUpdate(1, factory, { predictionDurationInS: 0.42 });
|
|
31
|
+
(0, import_vitest.expect)(factory).toHaveBeenCalledTimes(1);
|
|
32
|
+
(0, import_vitest.expect)(value.createdAt).toBe(100);
|
|
33
|
+
(0, import_vitest.expect)(value.predictionDurationInS).toBe(0.42);
|
|
34
|
+
(0, import_vitest.expect)((_a = cache.get(1)) == null ? void 0 : _a.predictionDurationInS).toBe(0.42);
|
|
35
|
+
});
|
|
36
|
+
(0, import_vitest.it)("setOrUpdate updates existing value and does not call factory", () => {
|
|
37
|
+
const cache = new import_utils.BoundedCache(10);
|
|
38
|
+
cache.set(1, new Entry(1, "before"));
|
|
39
|
+
const factory = import_vitest.vi.fn(() => new Entry(999));
|
|
40
|
+
const value = cache.setOrUpdate(1, factory, { note: "after", totalDurationInS: 1.5 });
|
|
41
|
+
(0, import_vitest.expect)(factory).not.toHaveBeenCalled();
|
|
42
|
+
(0, import_vitest.expect)(value.createdAt).toBe(1);
|
|
43
|
+
(0, import_vitest.expect)(value.note).toBe("after");
|
|
44
|
+
(0, import_vitest.expect)(value.totalDurationInS).toBe(1.5);
|
|
45
|
+
});
|
|
46
|
+
(0, import_vitest.it)("updateValue returns undefined for missing key", () => {
|
|
47
|
+
const cache = new import_utils.BoundedCache(10);
|
|
48
|
+
const result = cache.updateValue(404, { note: "missing" });
|
|
49
|
+
(0, import_vitest.expect)(result).toBeUndefined();
|
|
50
|
+
});
|
|
51
|
+
(0, import_vitest.it)("updateValue ignores undefined fields", () => {
|
|
52
|
+
const cache = new import_utils.BoundedCache(10);
|
|
53
|
+
cache.set(1, new Entry(1, "keep"));
|
|
54
|
+
const result = cache.updateValue(1, {
|
|
55
|
+
note: void 0,
|
|
56
|
+
predictionDurationInS: 0.1
|
|
57
|
+
});
|
|
58
|
+
(0, import_vitest.expect)(result == null ? void 0 : result.createdAt).toBe(1);
|
|
59
|
+
(0, import_vitest.expect)(result == null ? void 0 : result.note).toBe("keep");
|
|
60
|
+
(0, import_vitest.expect)(result == null ? void 0 : result.predictionDurationInS).toBe(0.1);
|
|
61
|
+
});
|
|
62
|
+
(0, import_vitest.it)("pop without predicate removes the oldest entry (python parity)", () => {
|
|
63
|
+
const cache = new import_utils.BoundedCache(10);
|
|
64
|
+
cache.set(1, new Entry(1));
|
|
65
|
+
cache.set(2, new Entry(2));
|
|
66
|
+
cache.set(3, new Entry(3));
|
|
67
|
+
const popped = cache.pop();
|
|
68
|
+
(0, import_vitest.expect)(popped == null ? void 0 : popped.createdAt).toBe(1);
|
|
69
|
+
(0, import_vitest.expect)([...cache.keys()]).toEqual([2, 3]);
|
|
70
|
+
});
|
|
71
|
+
(0, import_vitest.it)("pop with predicate removes the most recent matching entry", () => {
|
|
72
|
+
const cache = new import_utils.BoundedCache(10);
|
|
73
|
+
const e1 = new Entry(1);
|
|
74
|
+
e1.totalDurationInS = 0;
|
|
75
|
+
const e2 = new Entry(2);
|
|
76
|
+
e2.totalDurationInS = 1;
|
|
77
|
+
const e3 = new Entry(3);
|
|
78
|
+
e3.totalDurationInS = 2;
|
|
79
|
+
cache.set(1, e1);
|
|
80
|
+
cache.set(2, e2);
|
|
81
|
+
cache.set(3, e3);
|
|
82
|
+
const popped = cache.pop((entry) => (entry.totalDurationInS ?? 0) > 0);
|
|
83
|
+
(0, import_vitest.expect)(popped == null ? void 0 : popped.createdAt).toBe(3);
|
|
84
|
+
(0, import_vitest.expect)(popped == null ? void 0 : popped.totalDurationInS).toBe(2);
|
|
85
|
+
(0, import_vitest.expect)([...cache.keys()]).toEqual([1, 2]);
|
|
86
|
+
});
|
|
87
|
+
(0, import_vitest.it)("pop with predicate returns undefined when no match exists", () => {
|
|
88
|
+
const cache = new import_utils.BoundedCache(10);
|
|
89
|
+
const e1 = new Entry(1);
|
|
90
|
+
e1.totalDurationInS = 0;
|
|
91
|
+
cache.set(1, e1);
|
|
92
|
+
const popped = cache.pop((entry) => (entry.totalDurationInS ?? 0) > 10);
|
|
93
|
+
(0, import_vitest.expect)(popped).toBeUndefined();
|
|
94
|
+
(0, import_vitest.expect)(cache.size).toBe(1);
|
|
95
|
+
});
|
|
96
|
+
(0, import_vitest.it)("clear removes all entries", () => {
|
|
97
|
+
const cache = new import_utils.BoundedCache(10);
|
|
98
|
+
cache.set(1, new Entry(1));
|
|
99
|
+
cache.set(2, new Entry(2));
|
|
100
|
+
cache.clear();
|
|
101
|
+
(0, import_vitest.expect)(cache.size).toBe(0);
|
|
102
|
+
(0, import_vitest.expect)([...cache.keys()]).toEqual([]);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
//# sourceMappingURL=utils.test.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/inference/interruption/utils.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2026 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { describe, expect, it, vi } from 'vitest';\nimport { BoundedCache } from './utils.js';\n\nclass Entry {\n createdAt: number;\n totalDurationInS: number | undefined = undefined;\n predictionDurationInS: number | undefined = undefined;\n note: string | undefined = undefined;\n\n constructor(createdAt: number, note?: string) {\n this.createdAt = createdAt;\n this.note = note;\n }\n}\n\ndescribe('BoundedCache', () => {\n it('evicts oldest entry when maxLen is exceeded', () => {\n const cache = new BoundedCache<number, Entry>(2);\n cache.set(1, new Entry(1));\n cache.set(2, new Entry(2));\n cache.set(3, new Entry(3));\n\n expect(cache.size).toBe(2);\n expect([...cache.keys()]).toEqual([2, 3]);\n expect(cache.get(1)).toBeUndefined();\n expect(cache.get(2)!.createdAt).toBe(2);\n expect(cache.get(3)!.createdAt).toBe(3);\n });\n\n it('setOrUpdate creates a value via factory when key is missing', () => {\n const cache = new BoundedCache<number, Entry>(10);\n const factory = vi.fn(() => new Entry(100));\n\n const value = cache.setOrUpdate(1, factory, { predictionDurationInS: 0.42 });\n\n expect(factory).toHaveBeenCalledTimes(1);\n expect(value.createdAt).toBe(100);\n expect(value.predictionDurationInS).toBe(0.42);\n expect(cache.get(1)?.predictionDurationInS).toBe(0.42);\n });\n\n it('setOrUpdate updates existing value and does not call factory', () => {\n const cache = new BoundedCache<number, Entry>(10);\n cache.set(1, new Entry(1, 'before'));\n const factory = vi.fn(() => new Entry(999));\n\n const value = cache.setOrUpdate(1, factory, { note: 'after', totalDurationInS: 1.5 });\n\n expect(factory).not.toHaveBeenCalled();\n expect(value.createdAt).toBe(1);\n expect(value.note).toBe('after');\n expect(value.totalDurationInS).toBe(1.5);\n });\n\n it('updateValue returns undefined for missing key', () => {\n const cache = new BoundedCache<number, Entry>(10);\n const result = cache.updateValue(404, { note: 'missing' });\n\n expect(result).toBeUndefined();\n });\n\n it('updateValue ignores undefined fields', () => {\n const cache = new BoundedCache<number, Entry>(10);\n cache.set(1, new Entry(1, 'keep'));\n\n const result = cache.updateValue(1, {\n note: undefined,\n predictionDurationInS: 0.1,\n });\n\n expect(result?.createdAt).toBe(1);\n expect(result?.note).toBe('keep');\n expect(result?.predictionDurationInS).toBe(0.1);\n });\n\n it('pop without predicate removes the oldest entry (python parity)', () => {\n const cache = new BoundedCache<number, Entry>(10);\n cache.set(1, new Entry(1));\n cache.set(2, new Entry(2));\n cache.set(3, new Entry(3));\n\n const popped = cache.pop();\n\n expect(popped?.createdAt).toBe(1);\n expect([...cache.keys()]).toEqual([2, 3]);\n });\n\n it('pop with predicate removes the most recent matching entry', () => {\n const cache = new BoundedCache<number, Entry>(10);\n const e1 = new Entry(1);\n e1.totalDurationInS = 0;\n const e2 = new Entry(2);\n e2.totalDurationInS = 1;\n const e3 = new Entry(3);\n e3.totalDurationInS = 2;\n cache.set(1, e1);\n cache.set(2, e2);\n cache.set(3, e3);\n\n const popped = cache.pop((entry) => (entry.totalDurationInS ?? 0) > 0);\n\n expect(popped?.createdAt).toBe(3);\n expect(popped?.totalDurationInS).toBe(2);\n expect([...cache.keys()]).toEqual([1, 2]);\n });\n\n it('pop with predicate returns undefined when no match exists', () => {\n const cache = new BoundedCache<number, Entry>(10);\n const e1 = new Entry(1);\n e1.totalDurationInS = 0;\n cache.set(1, e1);\n\n const popped = cache.pop((entry) => (entry.totalDurationInS ?? 0) > 10);\n\n expect(popped).toBeUndefined();\n expect(cache.size).toBe(1);\n });\n\n it('clear removes all entries', () => {\n const cache = new BoundedCache<number, Entry>(10);\n cache.set(1, new Entry(1));\n cache.set(2, new Entry(2));\n\n cache.clear();\n\n expect(cache.size).toBe(0);\n expect([...cache.keys()]).toEqual([]);\n });\n});\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { BoundedCache } from "./utils.js";
|
|
3
|
+
class Entry {
|
|
4
|
+
createdAt;
|
|
5
|
+
totalDurationInS = void 0;
|
|
6
|
+
predictionDurationInS = void 0;
|
|
7
|
+
note = void 0;
|
|
8
|
+
constructor(createdAt, note) {
|
|
9
|
+
this.createdAt = createdAt;
|
|
10
|
+
this.note = note;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
describe("BoundedCache", () => {
|
|
14
|
+
it("evicts oldest entry when maxLen is exceeded", () => {
|
|
15
|
+
const cache = new BoundedCache(2);
|
|
16
|
+
cache.set(1, new Entry(1));
|
|
17
|
+
cache.set(2, new Entry(2));
|
|
18
|
+
cache.set(3, new Entry(3));
|
|
19
|
+
expect(cache.size).toBe(2);
|
|
20
|
+
expect([...cache.keys()]).toEqual([2, 3]);
|
|
21
|
+
expect(cache.get(1)).toBeUndefined();
|
|
22
|
+
expect(cache.get(2).createdAt).toBe(2);
|
|
23
|
+
expect(cache.get(3).createdAt).toBe(3);
|
|
24
|
+
});
|
|
25
|
+
it("setOrUpdate creates a value via factory when key is missing", () => {
|
|
26
|
+
var _a;
|
|
27
|
+
const cache = new BoundedCache(10);
|
|
28
|
+
const factory = vi.fn(() => new Entry(100));
|
|
29
|
+
const value = cache.setOrUpdate(1, factory, { predictionDurationInS: 0.42 });
|
|
30
|
+
expect(factory).toHaveBeenCalledTimes(1);
|
|
31
|
+
expect(value.createdAt).toBe(100);
|
|
32
|
+
expect(value.predictionDurationInS).toBe(0.42);
|
|
33
|
+
expect((_a = cache.get(1)) == null ? void 0 : _a.predictionDurationInS).toBe(0.42);
|
|
34
|
+
});
|
|
35
|
+
it("setOrUpdate updates existing value and does not call factory", () => {
|
|
36
|
+
const cache = new BoundedCache(10);
|
|
37
|
+
cache.set(1, new Entry(1, "before"));
|
|
38
|
+
const factory = vi.fn(() => new Entry(999));
|
|
39
|
+
const value = cache.setOrUpdate(1, factory, { note: "after", totalDurationInS: 1.5 });
|
|
40
|
+
expect(factory).not.toHaveBeenCalled();
|
|
41
|
+
expect(value.createdAt).toBe(1);
|
|
42
|
+
expect(value.note).toBe("after");
|
|
43
|
+
expect(value.totalDurationInS).toBe(1.5);
|
|
44
|
+
});
|
|
45
|
+
it("updateValue returns undefined for missing key", () => {
|
|
46
|
+
const cache = new BoundedCache(10);
|
|
47
|
+
const result = cache.updateValue(404, { note: "missing" });
|
|
48
|
+
expect(result).toBeUndefined();
|
|
49
|
+
});
|
|
50
|
+
it("updateValue ignores undefined fields", () => {
|
|
51
|
+
const cache = new BoundedCache(10);
|
|
52
|
+
cache.set(1, new Entry(1, "keep"));
|
|
53
|
+
const result = cache.updateValue(1, {
|
|
54
|
+
note: void 0,
|
|
55
|
+
predictionDurationInS: 0.1
|
|
56
|
+
});
|
|
57
|
+
expect(result == null ? void 0 : result.createdAt).toBe(1);
|
|
58
|
+
expect(result == null ? void 0 : result.note).toBe("keep");
|
|
59
|
+
expect(result == null ? void 0 : result.predictionDurationInS).toBe(0.1);
|
|
60
|
+
});
|
|
61
|
+
it("pop without predicate removes the oldest entry (python parity)", () => {
|
|
62
|
+
const cache = new BoundedCache(10);
|
|
63
|
+
cache.set(1, new Entry(1));
|
|
64
|
+
cache.set(2, new Entry(2));
|
|
65
|
+
cache.set(3, new Entry(3));
|
|
66
|
+
const popped = cache.pop();
|
|
67
|
+
expect(popped == null ? void 0 : popped.createdAt).toBe(1);
|
|
68
|
+
expect([...cache.keys()]).toEqual([2, 3]);
|
|
69
|
+
});
|
|
70
|
+
it("pop with predicate removes the most recent matching entry", () => {
|
|
71
|
+
const cache = new BoundedCache(10);
|
|
72
|
+
const e1 = new Entry(1);
|
|
73
|
+
e1.totalDurationInS = 0;
|
|
74
|
+
const e2 = new Entry(2);
|
|
75
|
+
e2.totalDurationInS = 1;
|
|
76
|
+
const e3 = new Entry(3);
|
|
77
|
+
e3.totalDurationInS = 2;
|
|
78
|
+
cache.set(1, e1);
|
|
79
|
+
cache.set(2, e2);
|
|
80
|
+
cache.set(3, e3);
|
|
81
|
+
const popped = cache.pop((entry) => (entry.totalDurationInS ?? 0) > 0);
|
|
82
|
+
expect(popped == null ? void 0 : popped.createdAt).toBe(3);
|
|
83
|
+
expect(popped == null ? void 0 : popped.totalDurationInS).toBe(2);
|
|
84
|
+
expect([...cache.keys()]).toEqual([1, 2]);
|
|
85
|
+
});
|
|
86
|
+
it("pop with predicate returns undefined when no match exists", () => {
|
|
87
|
+
const cache = new BoundedCache(10);
|
|
88
|
+
const e1 = new Entry(1);
|
|
89
|
+
e1.totalDurationInS = 0;
|
|
90
|
+
cache.set(1, e1);
|
|
91
|
+
const popped = cache.pop((entry) => (entry.totalDurationInS ?? 0) > 10);
|
|
92
|
+
expect(popped).toBeUndefined();
|
|
93
|
+
expect(cache.size).toBe(1);
|
|
94
|
+
});
|
|
95
|
+
it("clear removes all entries", () => {
|
|
96
|
+
const cache = new BoundedCache(10);
|
|
97
|
+
cache.set(1, new Entry(1));
|
|
98
|
+
cache.set(2, new Entry(2));
|
|
99
|
+
cache.clear();
|
|
100
|
+
expect(cache.size).toBe(0);
|
|
101
|
+
expect([...cache.keys()]).toEqual([]);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
//# sourceMappingURL=utils.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/inference/interruption/utils.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2026 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { describe, expect, it, vi } from 'vitest';\nimport { BoundedCache } from './utils.js';\n\nclass Entry {\n createdAt: number;\n totalDurationInS: number | undefined = undefined;\n predictionDurationInS: number | undefined = undefined;\n note: string | undefined = undefined;\n\n constructor(createdAt: number, note?: string) {\n this.createdAt = createdAt;\n this.note = note;\n }\n}\n\ndescribe('BoundedCache', () => {\n it('evicts oldest entry when maxLen is exceeded', () => {\n const cache = new BoundedCache<number, Entry>(2);\n cache.set(1, new Entry(1));\n cache.set(2, new Entry(2));\n cache.set(3, new Entry(3));\n\n expect(cache.size).toBe(2);\n expect([...cache.keys()]).toEqual([2, 3]);\n expect(cache.get(1)).toBeUndefined();\n expect(cache.get(2)!.createdAt).toBe(2);\n expect(cache.get(3)!.createdAt).toBe(3);\n });\n\n it('setOrUpdate creates a value via factory when key is missing', () => {\n const cache = new BoundedCache<number, Entry>(10);\n const factory = vi.fn(() => new Entry(100));\n\n const value = cache.setOrUpdate(1, factory, { predictionDurationInS: 0.42 });\n\n expect(factory).toHaveBeenCalledTimes(1);\n expect(value.createdAt).toBe(100);\n expect(value.predictionDurationInS).toBe(0.42);\n expect(cache.get(1)?.predictionDurationInS).toBe(0.42);\n });\n\n it('setOrUpdate updates existing value and does not call factory', () => {\n const cache = new BoundedCache<number, Entry>(10);\n cache.set(1, new Entry(1, 'before'));\n const factory = vi.fn(() => new Entry(999));\n\n const value = cache.setOrUpdate(1, factory, { note: 'after', totalDurationInS: 1.5 });\n\n expect(factory).not.toHaveBeenCalled();\n expect(value.createdAt).toBe(1);\n expect(value.note).toBe('after');\n expect(value.totalDurationInS).toBe(1.5);\n });\n\n it('updateValue returns undefined for missing key', () => {\n const cache = new BoundedCache<number, Entry>(10);\n const result = cache.updateValue(404, { note: 'missing' });\n\n expect(result).toBeUndefined();\n });\n\n it('updateValue ignores undefined fields', () => {\n const cache = new BoundedCache<number, Entry>(10);\n cache.set(1, new Entry(1, 'keep'));\n\n const result = cache.updateValue(1, {\n note: undefined,\n predictionDurationInS: 0.1,\n });\n\n expect(result?.createdAt).toBe(1);\n expect(result?.note).toBe('keep');\n expect(result?.predictionDurationInS).toBe(0.1);\n });\n\n it('pop without predicate removes the oldest entry (python parity)', () => {\n const cache = new BoundedCache<number, Entry>(10);\n cache.set(1, new Entry(1));\n cache.set(2, new Entry(2));\n cache.set(3, new Entry(3));\n\n const popped = cache.pop();\n\n expect(popped?.createdAt).toBe(1);\n expect([...cache.keys()]).toEqual([2, 3]);\n });\n\n it('pop with predicate removes the most recent matching entry', () => {\n const cache = new BoundedCache<number, Entry>(10);\n const e1 = new Entry(1);\n e1.totalDurationInS = 0;\n const e2 = new Entry(2);\n e2.totalDurationInS = 1;\n const e3 = new Entry(3);\n e3.totalDurationInS = 2;\n cache.set(1, e1);\n cache.set(2, e2);\n cache.set(3, e3);\n\n const popped = cache.pop((entry) => (entry.totalDurationInS ?? 0) > 0);\n\n expect(popped?.createdAt).toBe(3);\n expect(popped?.totalDurationInS).toBe(2);\n expect([...cache.keys()]).toEqual([1, 2]);\n });\n\n it('pop with predicate returns undefined when no match exists', () => {\n const cache = new BoundedCache<number, Entry>(10);\n const e1 = new Entry(1);\n e1.totalDurationInS = 0;\n cache.set(1, e1);\n\n const popped = cache.pop((entry) => (entry.totalDurationInS ?? 0) > 10);\n\n expect(popped).toBeUndefined();\n expect(cache.size).toBe(1);\n });\n\n it('clear removes all entries', () => {\n const cache = new BoundedCache<number, Entry>(10);\n cache.set(1, new Entry(1));\n cache.set(2, new Entry(2));\n\n cache.clear();\n\n expect(cache.size).toBe(0);\n expect([...cache.keys()]).toEqual([]);\n });\n});\n"],"mappings":"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","names":[]}
|