@livekit/agents 1.0.35 → 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.
Files changed (131) hide show
  1. package/dist/index.cjs +3 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +1 -0
  4. package/dist/index.d.ts +1 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/inference/interruption/AdaptiveInterruptionDetector.cjs +152 -0
  9. package/dist/inference/interruption/AdaptiveInterruptionDetector.cjs.map +1 -0
  10. package/dist/inference/interruption/AdaptiveInterruptionDetector.d.cts +50 -0
  11. package/dist/inference/interruption/AdaptiveInterruptionDetector.d.ts +50 -0
  12. package/dist/inference/interruption/AdaptiveInterruptionDetector.d.ts.map +1 -0
  13. package/dist/inference/interruption/AdaptiveInterruptionDetector.js +125 -0
  14. package/dist/inference/interruption/AdaptiveInterruptionDetector.js.map +1 -0
  15. package/dist/inference/interruption/InterruptionStream.cjs +310 -0
  16. package/dist/inference/interruption/InterruptionStream.cjs.map +1 -0
  17. package/dist/inference/interruption/InterruptionStream.d.cts +57 -0
  18. package/dist/inference/interruption/InterruptionStream.d.ts +57 -0
  19. package/dist/inference/interruption/InterruptionStream.d.ts.map +1 -0
  20. package/dist/inference/interruption/InterruptionStream.js +288 -0
  21. package/dist/inference/interruption/InterruptionStream.js.map +1 -0
  22. package/dist/inference/interruption/defaults.cjs +76 -0
  23. package/dist/inference/interruption/defaults.cjs.map +1 -0
  24. package/dist/inference/interruption/defaults.d.cts +14 -0
  25. package/dist/inference/interruption/defaults.d.ts +14 -0
  26. package/dist/inference/interruption/defaults.d.ts.map +1 -0
  27. package/dist/inference/interruption/defaults.js +42 -0
  28. package/dist/inference/interruption/defaults.js.map +1 -0
  29. package/dist/inference/interruption/errors.cjs +2 -0
  30. package/dist/inference/interruption/errors.cjs.map +1 -0
  31. package/dist/inference/interruption/errors.d.cts +2 -0
  32. package/dist/inference/interruption/errors.d.ts +2 -0
  33. package/dist/inference/interruption/errors.d.ts.map +1 -0
  34. package/dist/inference/interruption/errors.js +1 -0
  35. package/dist/inference/interruption/errors.js.map +1 -0
  36. package/dist/inference/interruption/http_transport.cjs +57 -0
  37. package/dist/inference/interruption/http_transport.cjs.map +1 -0
  38. package/dist/inference/interruption/http_transport.d.cts +23 -0
  39. package/dist/inference/interruption/http_transport.d.ts +23 -0
  40. package/dist/inference/interruption/http_transport.d.ts.map +1 -0
  41. package/dist/inference/interruption/http_transport.js +33 -0
  42. package/dist/inference/interruption/http_transport.js.map +1 -0
  43. package/dist/inference/interruption/index.cjs +34 -0
  44. package/dist/inference/interruption/index.cjs.map +1 -0
  45. package/dist/inference/interruption/index.d.cts +5 -0
  46. package/dist/inference/interruption/index.d.ts +5 -0
  47. package/dist/inference/interruption/index.d.ts.map +1 -0
  48. package/dist/inference/interruption/index.js +7 -0
  49. package/dist/inference/interruption/index.js.map +1 -0
  50. package/dist/inference/interruption/interruption.cjs +85 -0
  51. package/dist/inference/interruption/interruption.cjs.map +1 -0
  52. package/dist/inference/interruption/interruption.d.cts +48 -0
  53. package/dist/inference/interruption/interruption.d.ts +48 -0
  54. package/dist/inference/interruption/interruption.d.ts.map +1 -0
  55. package/dist/inference/interruption/interruption.js +59 -0
  56. package/dist/inference/interruption/interruption.js.map +1 -0
  57. package/dist/inference/utils.cjs +15 -2
  58. package/dist/inference/utils.cjs.map +1 -1
  59. package/dist/inference/utils.d.cts +1 -0
  60. package/dist/inference/utils.d.ts +1 -0
  61. package/dist/inference/utils.d.ts.map +1 -1
  62. package/dist/inference/utils.js +13 -1
  63. package/dist/inference/utils.js.map +1 -1
  64. package/dist/inference/utils.test.cjs +20 -0
  65. package/dist/inference/utils.test.cjs.map +1 -0
  66. package/dist/inference/utils.test.js +19 -0
  67. package/dist/inference/utils.test.js.map +1 -0
  68. package/dist/stream/stream_channel.cjs +3 -0
  69. package/dist/stream/stream_channel.cjs.map +1 -1
  70. package/dist/stream/stream_channel.d.cts +3 -2
  71. package/dist/stream/stream_channel.d.ts +3 -2
  72. package/dist/stream/stream_channel.d.ts.map +1 -1
  73. package/dist/stream/stream_channel.js +3 -0
  74. package/dist/stream/stream_channel.js.map +1 -1
  75. package/dist/telemetry/trace_types.cjs +15 -0
  76. package/dist/telemetry/trace_types.cjs.map +1 -1
  77. package/dist/telemetry/trace_types.d.cts +5 -0
  78. package/dist/telemetry/trace_types.d.ts +5 -0
  79. package/dist/telemetry/trace_types.d.ts.map +1 -1
  80. package/dist/telemetry/trace_types.js +10 -0
  81. package/dist/telemetry/trace_types.js.map +1 -1
  82. package/dist/utils/ws_transport.cjs +51 -0
  83. package/dist/utils/ws_transport.cjs.map +1 -0
  84. package/dist/utils/ws_transport.d.cts +9 -0
  85. package/dist/utils/ws_transport.d.ts +9 -0
  86. package/dist/utils/ws_transport.d.ts.map +1 -0
  87. package/dist/utils/ws_transport.js +17 -0
  88. package/dist/utils/ws_transport.js.map +1 -0
  89. package/dist/utils/ws_transport.test.cjs +212 -0
  90. package/dist/utils/ws_transport.test.cjs.map +1 -0
  91. package/dist/utils/ws_transport.test.js +211 -0
  92. package/dist/utils/ws_transport.test.js.map +1 -0
  93. package/dist/voice/agent_activity.cjs +49 -0
  94. package/dist/voice/agent_activity.cjs.map +1 -1
  95. package/dist/voice/agent_activity.d.cts +14 -0
  96. package/dist/voice/agent_activity.d.ts +14 -0
  97. package/dist/voice/agent_activity.d.ts.map +1 -1
  98. package/dist/voice/agent_activity.js +49 -0
  99. package/dist/voice/agent_activity.js.map +1 -1
  100. package/dist/voice/agent_session.cjs +12 -1
  101. package/dist/voice/agent_session.cjs.map +1 -1
  102. package/dist/voice/agent_session.d.cts +3 -0
  103. package/dist/voice/agent_session.d.ts +3 -0
  104. package/dist/voice/agent_session.d.ts.map +1 -1
  105. package/dist/voice/agent_session.js +12 -1
  106. package/dist/voice/agent_session.js.map +1 -1
  107. package/dist/voice/audio_recognition.cjs +124 -2
  108. package/dist/voice/audio_recognition.cjs.map +1 -1
  109. package/dist/voice/audio_recognition.d.cts +32 -1
  110. package/dist/voice/audio_recognition.d.ts +32 -1
  111. package/dist/voice/audio_recognition.d.ts.map +1 -1
  112. package/dist/voice/audio_recognition.js +127 -2
  113. package/dist/voice/audio_recognition.js.map +1 -1
  114. package/package.json +2 -1
  115. package/src/index.ts +2 -0
  116. package/src/inference/interruption/AdaptiveInterruptionDetector.ts +166 -0
  117. package/src/inference/interruption/InterruptionStream.ts +397 -0
  118. package/src/inference/interruption/defaults.ts +33 -0
  119. package/src/inference/interruption/errors.ts +0 -0
  120. package/src/inference/interruption/http_transport.ts +61 -0
  121. package/src/inference/interruption/index.ts +4 -0
  122. package/src/inference/interruption/interruption.ts +88 -0
  123. package/src/inference/utils.test.ts +31 -0
  124. package/src/inference/utils.ts +15 -0
  125. package/src/stream/stream_channel.ts +6 -2
  126. package/src/telemetry/trace_types.ts +7 -0
  127. package/src/utils/ws_transport.test.ts +282 -0
  128. package/src/utils/ws_transport.ts +22 -0
  129. package/src/voice/agent_activity.ts +61 -0
  130. package/src/voice/agent_session.ts +22 -2
  131. package/src/voice/audio_recognition.ts +161 -1
@@ -0,0 +1,33 @@
1
+ import { ofetch } from "ofetch";
2
+ async function predictHTTP(data, predictOptions, options) {
3
+ const createdAt = performance.now();
4
+ const url = new URL(`/bargein`, options.baseUrl);
5
+ url.searchParams.append("threshold", predictOptions.threshold.toString());
6
+ url.searchParams.append("min_frames", predictOptions.minFrames.toFixed());
7
+ url.searchParams.append("created_at", createdAt.toFixed());
8
+ const { created_at, is_bargein, probabilities } = await ofetch(
9
+ url.toString(),
10
+ {
11
+ retry: 1,
12
+ retryDelay: 100,
13
+ headers: {
14
+ "Content-Type": "application/octet-stream",
15
+ Authorization: `Bearer ${options.token}`
16
+ },
17
+ signal: options.signal,
18
+ timeout: options.timeout,
19
+ method: "POST",
20
+ body: data
21
+ }
22
+ );
23
+ return {
24
+ createdAt: created_at,
25
+ isBargein: is_bargein,
26
+ probabilities: new Float32Array(probabilities),
27
+ predictionDuration: (performance.now() - createdAt) / 1e9
28
+ };
29
+ }
30
+ export {
31
+ predictHTTP
32
+ };
33
+ //# sourceMappingURL=http_transport.js.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,SAAS,cAAc;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,MAAM;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,34 @@
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 __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var interruption_exports = {};
21
+ __export(interruption_exports, {
22
+ InterruptionStreamSentinel: () => import_InterruptionStream.InterruptionStreamSentinel
23
+ });
24
+ module.exports = __toCommonJS(interruption_exports);
25
+ __reExport(interruption_exports, require("./AdaptiveInterruptionDetector.cjs"), module.exports);
26
+ __reExport(interruption_exports, require("./interruption.cjs"), module.exports);
27
+ var import_InterruptionStream = require("./InterruptionStream.cjs");
28
+ // Annotate the CommonJS export names for ESM import in node:
29
+ 0 && (module.exports = {
30
+ InterruptionStreamSentinel,
31
+ ...require("./AdaptiveInterruptionDetector.cjs"),
32
+ ...require("./interruption.cjs")
33
+ });
34
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/inference/interruption/index.ts"],"sourcesContent":["export * from './AdaptiveInterruptionDetector.js';\nexport * from './interruption.js';\nexport { InterruptionStreamSentinel } from './InterruptionStream.js';\nexport type { InterruptionSentinel } from './InterruptionStream.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iCAAc,8CAAd;AACA,iCAAc,8BADd;AAEA,gCAA2C;","names":[]}
@@ -0,0 +1,5 @@
1
+ export * from './AdaptiveInterruptionDetector.js';
2
+ export * from './interruption.js';
3
+ export { InterruptionStreamSentinel } from './InterruptionStream.js';
4
+ export type { InterruptionSentinel } from './InterruptionStream.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,5 @@
1
+ export * from './AdaptiveInterruptionDetector.js';
2
+ export * from './interruption.js';
3
+ export { InterruptionStreamSentinel } from './InterruptionStream.js';
4
+ export type { InterruptionSentinel } from './InterruptionStream.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/inference/interruption/index.ts"],"names":[],"mappings":"AAAA,cAAc,mCAAmC,CAAC;AAClD,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AACrE,YAAY,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export * from "./AdaptiveInterruptionDetector.js";
2
+ export * from "./interruption.js";
3
+ import { InterruptionStreamSentinel } from "./InterruptionStream.js";
4
+ export {
5
+ InterruptionStreamSentinel
6
+ };
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/inference/interruption/index.ts"],"sourcesContent":["export * from './AdaptiveInterruptionDetector.js';\nexport * from './interruption.js';\nexport { InterruptionStreamSentinel } from './InterruptionStream.js';\nexport type { InterruptionSentinel } from './InterruptionStream.js';\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,SAAS,kCAAkC;","names":[]}
@@ -0,0 +1,85 @@
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 interruption_exports = {};
20
+ __export(interruption_exports, {
21
+ InterruptionCacheEntry: () => InterruptionCacheEntry,
22
+ InterruptionDetectionError: () => InterruptionDetectionError,
23
+ InterruptionEventType: () => InterruptionEventType
24
+ });
25
+ module.exports = __toCommonJS(interruption_exports);
26
+ var import_utils = require("../utils.cjs");
27
+ var import_defaults = require("./defaults.cjs");
28
+ var InterruptionEventType = /* @__PURE__ */ ((InterruptionEventType2) => {
29
+ InterruptionEventType2["INTERRUPTION"] = "interruption";
30
+ InterruptionEventType2["OVERLAP_SPEECH_ENDED"] = "overlap_speech_ended";
31
+ return InterruptionEventType2;
32
+ })(InterruptionEventType || {});
33
+ class InterruptionDetectionError extends Error {
34
+ type = "InterruptionDetectionError";
35
+ timestamp;
36
+ label;
37
+ recoverable;
38
+ constructor(message, timestamp, label, recoverable) {
39
+ super(message);
40
+ this.name = "InterruptionDetectionError";
41
+ this.timestamp = timestamp;
42
+ this.label = label;
43
+ this.recoverable = recoverable;
44
+ }
45
+ toString() {
46
+ return `${this.name}: ${this.message} (label=${this.label}, timestamp=${this.timestamp}, recoverable=${this.recoverable})`;
47
+ }
48
+ }
49
+ function estimateProbability(probabilities, windowSize = import_defaults.MIN_INTERRUPTION_DURATION) {
50
+ const minWindow = Math.ceil(windowSize / 0.025);
51
+ if (probabilities.length < minWindow) {
52
+ return 0;
53
+ }
54
+ return (0, import_utils.slidingWindowMinMax)(probabilities, windowSize);
55
+ }
56
+ class InterruptionCacheEntry {
57
+ createdAt;
58
+ totalDuration;
59
+ predictionDuration;
60
+ detectionDelay;
61
+ speechInput;
62
+ probabilities;
63
+ isInterruption;
64
+ probability;
65
+ constructor(params) {
66
+ this.createdAt = params.createdAt;
67
+ this.totalDuration = params.totalDuration ?? 0;
68
+ this.predictionDuration = params.predictionDuration ?? 0;
69
+ this.detectionDelay = params.detectionDelay ?? 0;
70
+ this.speechInput = params.speechInput;
71
+ this.probabilities = params.probabilities;
72
+ this.isInterruption = params.isInterruption;
73
+ this.probability = this.probabilities ? estimateProbability(this.probabilities) : 0;
74
+ }
75
+ static default() {
76
+ return new InterruptionCacheEntry({ createdAt: 0 });
77
+ }
78
+ }
79
+ // Annotate the CommonJS export names for ESM import in node:
80
+ 0 && (module.exports = {
81
+ InterruptionCacheEntry,
82
+ InterruptionDetectionError,
83
+ InterruptionEventType
84
+ });
85
+ //# sourceMappingURL=interruption.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/inference/interruption/interruption.ts"],"sourcesContent":["import { slidingWindowMinMax } from '../utils.js';\nimport { MIN_INTERRUPTION_DURATION } from './defaults.js';\n\nexport enum InterruptionEventType {\n INTERRUPTION = 'interruption',\n OVERLAP_SPEECH_ENDED = 'overlap_speech_ended',\n}\nexport interface InterruptionEvent {\n type: InterruptionEventType;\n timestamp: number;\n isInterruption: boolean;\n totalDuration: number;\n predictionDuration: number;\n detectionDelay: number;\n overlapSpeechStartedAt?: number;\n speechInput?: Int16Array;\n probabilities?: Float32Array;\n probability: number;\n}\n\nexport class InterruptionDetectionError extends Error {\n readonly type = 'InterruptionDetectionError';\n\n readonly timestamp: number;\n readonly label: string;\n readonly recoverable: boolean;\n\n constructor(message: string, timestamp: number, label: string, recoverable: boolean) {\n super(message);\n this.name = 'InterruptionDetectionError';\n this.timestamp = timestamp;\n this.label = label;\n this.recoverable = recoverable;\n }\n\n toString(): string {\n return `${this.name}: ${this.message} (label=${this.label}, timestamp=${this.timestamp}, recoverable=${this.recoverable})`;\n }\n}\n\nfunction estimateProbability(\n probabilities: Float32Array,\n windowSize: number = MIN_INTERRUPTION_DURATION,\n): number {\n const minWindow = Math.ceil(windowSize / 0.025); // 25ms per frame\n if (probabilities.length < minWindow) {\n return 0;\n }\n\n return slidingWindowMinMax(probabilities, windowSize);\n}\n\n/**\n * Typed cache entry for interruption inference results.\n */\nexport class InterruptionCacheEntry {\n readonly createdAt: number;\n readonly totalDuration: number;\n readonly predictionDuration: number;\n readonly detectionDelay: number;\n readonly speechInput?: Int16Array;\n readonly probabilities?: Float32Array;\n readonly isInterruption?: boolean;\n readonly probability: number;\n\n constructor(params: {\n createdAt: number;\n speechInput?: Int16Array;\n totalDuration?: number;\n predictionDuration?: number;\n detectionDelay?: number;\n probabilities?: Float32Array;\n isInterruption?: boolean;\n }) {\n this.createdAt = params.createdAt;\n this.totalDuration = params.totalDuration ?? 0;\n this.predictionDuration = params.predictionDuration ?? 0;\n this.detectionDelay = params.detectionDelay ?? 0;\n this.speechInput = params.speechInput;\n this.probabilities = params.probabilities;\n this.isInterruption = params.isInterruption;\n this.probability = this.probabilities ? estimateProbability(this.probabilities) : 0;\n }\n\n static default(): InterruptionCacheEntry {\n return new InterruptionCacheEntry({ createdAt: 0 });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAoC;AACpC,sBAA0C;AAEnC,IAAK,wBAAL,kBAAKA,2BAAL;AACL,EAAAA,uBAAA,kBAAe;AACf,EAAAA,uBAAA,0BAAuB;AAFb,SAAAA;AAAA,GAAA;AAiBL,MAAM,mCAAmC,MAAM;AAAA,EAC3C,OAAO;AAAA,EAEP;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,WAAmB,OAAe,aAAsB;AACnF,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,YAAY;AACjB,SAAK,QAAQ;AACb,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,WAAmB;AACjB,WAAO,GAAG,KAAK,IAAI,KAAK,KAAK,OAAO,WAAW,KAAK,KAAK,eAAe,KAAK,SAAS,iBAAiB,KAAK,WAAW;AAAA,EACzH;AACF;AAEA,SAAS,oBACP,eACA,aAAqB,2CACb;AACR,QAAM,YAAY,KAAK,KAAK,aAAa,KAAK;AAC9C,MAAI,cAAc,SAAS,WAAW;AACpC,WAAO;AAAA,EACT;AAEA,aAAO,kCAAoB,eAAe,UAAU;AACtD;AAKO,MAAM,uBAAuB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,QAQT;AACD,SAAK,YAAY,OAAO;AACxB,SAAK,gBAAgB,OAAO,iBAAiB;AAC7C,SAAK,qBAAqB,OAAO,sBAAsB;AACvD,SAAK,iBAAiB,OAAO,kBAAkB;AAC/C,SAAK,cAAc,OAAO;AAC1B,SAAK,gBAAgB,OAAO;AAC5B,SAAK,iBAAiB,OAAO;AAC7B,SAAK,cAAc,KAAK,gBAAgB,oBAAoB,KAAK,aAAa,IAAI;AAAA,EACpF;AAAA,EAEA,OAAO,UAAkC;AACvC,WAAO,IAAI,uBAAuB,EAAE,WAAW,EAAE,CAAC;AAAA,EACpD;AACF;","names":["InterruptionEventType"]}
@@ -0,0 +1,48 @@
1
+ export declare enum InterruptionEventType {
2
+ INTERRUPTION = "interruption",
3
+ OVERLAP_SPEECH_ENDED = "overlap_speech_ended"
4
+ }
5
+ export interface InterruptionEvent {
6
+ type: InterruptionEventType;
7
+ timestamp: number;
8
+ isInterruption: boolean;
9
+ totalDuration: number;
10
+ predictionDuration: number;
11
+ detectionDelay: number;
12
+ overlapSpeechStartedAt?: number;
13
+ speechInput?: Int16Array;
14
+ probabilities?: Float32Array;
15
+ probability: number;
16
+ }
17
+ export declare class InterruptionDetectionError extends Error {
18
+ readonly type = "InterruptionDetectionError";
19
+ readonly timestamp: number;
20
+ readonly label: string;
21
+ readonly recoverable: boolean;
22
+ constructor(message: string, timestamp: number, label: string, recoverable: boolean);
23
+ toString(): string;
24
+ }
25
+ /**
26
+ * Typed cache entry for interruption inference results.
27
+ */
28
+ export declare class InterruptionCacheEntry {
29
+ readonly createdAt: number;
30
+ readonly totalDuration: number;
31
+ readonly predictionDuration: number;
32
+ readonly detectionDelay: number;
33
+ readonly speechInput?: Int16Array;
34
+ readonly probabilities?: Float32Array;
35
+ readonly isInterruption?: boolean;
36
+ readonly probability: number;
37
+ constructor(params: {
38
+ createdAt: number;
39
+ speechInput?: Int16Array;
40
+ totalDuration?: number;
41
+ predictionDuration?: number;
42
+ detectionDelay?: number;
43
+ probabilities?: Float32Array;
44
+ isInterruption?: boolean;
45
+ });
46
+ static default(): InterruptionCacheEntry;
47
+ }
48
+ //# sourceMappingURL=interruption.d.ts.map
@@ -0,0 +1,48 @@
1
+ export declare enum InterruptionEventType {
2
+ INTERRUPTION = "interruption",
3
+ OVERLAP_SPEECH_ENDED = "overlap_speech_ended"
4
+ }
5
+ export interface InterruptionEvent {
6
+ type: InterruptionEventType;
7
+ timestamp: number;
8
+ isInterruption: boolean;
9
+ totalDuration: number;
10
+ predictionDuration: number;
11
+ detectionDelay: number;
12
+ overlapSpeechStartedAt?: number;
13
+ speechInput?: Int16Array;
14
+ probabilities?: Float32Array;
15
+ probability: number;
16
+ }
17
+ export declare class InterruptionDetectionError extends Error {
18
+ readonly type = "InterruptionDetectionError";
19
+ readonly timestamp: number;
20
+ readonly label: string;
21
+ readonly recoverable: boolean;
22
+ constructor(message: string, timestamp: number, label: string, recoverable: boolean);
23
+ toString(): string;
24
+ }
25
+ /**
26
+ * Typed cache entry for interruption inference results.
27
+ */
28
+ export declare class InterruptionCacheEntry {
29
+ readonly createdAt: number;
30
+ readonly totalDuration: number;
31
+ readonly predictionDuration: number;
32
+ readonly detectionDelay: number;
33
+ readonly speechInput?: Int16Array;
34
+ readonly probabilities?: Float32Array;
35
+ readonly isInterruption?: boolean;
36
+ readonly probability: number;
37
+ constructor(params: {
38
+ createdAt: number;
39
+ speechInput?: Int16Array;
40
+ totalDuration?: number;
41
+ predictionDuration?: number;
42
+ detectionDelay?: number;
43
+ probabilities?: Float32Array;
44
+ isInterruption?: boolean;
45
+ });
46
+ static default(): InterruptionCacheEntry;
47
+ }
48
+ //# sourceMappingURL=interruption.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interruption.d.ts","sourceRoot":"","sources":["../../../src/inference/interruption/interruption.ts"],"names":[],"mappings":"AAGA,oBAAY,qBAAqB;IAC/B,YAAY,iBAAiB;IAC7B,oBAAoB,yBAAyB;CAC9C;AACD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,qBAAqB,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,0BAA2B,SAAQ,KAAK;IACnD,QAAQ,CAAC,IAAI,gCAAgC;IAE7C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;gBAElB,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO;IAQnF,QAAQ,IAAI,MAAM;CAGnB;AAcD;;GAEG;AACH,qBAAa,sBAAsB;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC;IAClC,QAAQ,CAAC,aAAa,CAAC,EAAE,YAAY,CAAC;IACtC,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;gBAEjB,MAAM,EAAE;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,UAAU,CAAC;QACzB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;QAC5B,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,aAAa,CAAC,EAAE,YAAY,CAAC;QAC7B,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B;IAWD,MAAM,CAAC,OAAO,IAAI,sBAAsB;CAGzC"}
@@ -0,0 +1,59 @@
1
+ import { slidingWindowMinMax } from "../utils.js";
2
+ import { MIN_INTERRUPTION_DURATION } from "./defaults.js";
3
+ var InterruptionEventType = /* @__PURE__ */ ((InterruptionEventType2) => {
4
+ InterruptionEventType2["INTERRUPTION"] = "interruption";
5
+ InterruptionEventType2["OVERLAP_SPEECH_ENDED"] = "overlap_speech_ended";
6
+ return InterruptionEventType2;
7
+ })(InterruptionEventType || {});
8
+ class InterruptionDetectionError extends Error {
9
+ type = "InterruptionDetectionError";
10
+ timestamp;
11
+ label;
12
+ recoverable;
13
+ constructor(message, timestamp, label, recoverable) {
14
+ super(message);
15
+ this.name = "InterruptionDetectionError";
16
+ this.timestamp = timestamp;
17
+ this.label = label;
18
+ this.recoverable = recoverable;
19
+ }
20
+ toString() {
21
+ return `${this.name}: ${this.message} (label=${this.label}, timestamp=${this.timestamp}, recoverable=${this.recoverable})`;
22
+ }
23
+ }
24
+ function estimateProbability(probabilities, windowSize = MIN_INTERRUPTION_DURATION) {
25
+ const minWindow = Math.ceil(windowSize / 0.025);
26
+ if (probabilities.length < minWindow) {
27
+ return 0;
28
+ }
29
+ return slidingWindowMinMax(probabilities, windowSize);
30
+ }
31
+ class InterruptionCacheEntry {
32
+ createdAt;
33
+ totalDuration;
34
+ predictionDuration;
35
+ detectionDelay;
36
+ speechInput;
37
+ probabilities;
38
+ isInterruption;
39
+ probability;
40
+ constructor(params) {
41
+ this.createdAt = params.createdAt;
42
+ this.totalDuration = params.totalDuration ?? 0;
43
+ this.predictionDuration = params.predictionDuration ?? 0;
44
+ this.detectionDelay = params.detectionDelay ?? 0;
45
+ this.speechInput = params.speechInput;
46
+ this.probabilities = params.probabilities;
47
+ this.isInterruption = params.isInterruption;
48
+ this.probability = this.probabilities ? estimateProbability(this.probabilities) : 0;
49
+ }
50
+ static default() {
51
+ return new InterruptionCacheEntry({ createdAt: 0 });
52
+ }
53
+ }
54
+ export {
55
+ InterruptionCacheEntry,
56
+ InterruptionDetectionError,
57
+ InterruptionEventType
58
+ };
59
+ //# sourceMappingURL=interruption.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/inference/interruption/interruption.ts"],"sourcesContent":["import { slidingWindowMinMax } from '../utils.js';\nimport { MIN_INTERRUPTION_DURATION } from './defaults.js';\n\nexport enum InterruptionEventType {\n INTERRUPTION = 'interruption',\n OVERLAP_SPEECH_ENDED = 'overlap_speech_ended',\n}\nexport interface InterruptionEvent {\n type: InterruptionEventType;\n timestamp: number;\n isInterruption: boolean;\n totalDuration: number;\n predictionDuration: number;\n detectionDelay: number;\n overlapSpeechStartedAt?: number;\n speechInput?: Int16Array;\n probabilities?: Float32Array;\n probability: number;\n}\n\nexport class InterruptionDetectionError extends Error {\n readonly type = 'InterruptionDetectionError';\n\n readonly timestamp: number;\n readonly label: string;\n readonly recoverable: boolean;\n\n constructor(message: string, timestamp: number, label: string, recoverable: boolean) {\n super(message);\n this.name = 'InterruptionDetectionError';\n this.timestamp = timestamp;\n this.label = label;\n this.recoverable = recoverable;\n }\n\n toString(): string {\n return `${this.name}: ${this.message} (label=${this.label}, timestamp=${this.timestamp}, recoverable=${this.recoverable})`;\n }\n}\n\nfunction estimateProbability(\n probabilities: Float32Array,\n windowSize: number = MIN_INTERRUPTION_DURATION,\n): number {\n const minWindow = Math.ceil(windowSize / 0.025); // 25ms per frame\n if (probabilities.length < minWindow) {\n return 0;\n }\n\n return slidingWindowMinMax(probabilities, windowSize);\n}\n\n/**\n * Typed cache entry for interruption inference results.\n */\nexport class InterruptionCacheEntry {\n readonly createdAt: number;\n readonly totalDuration: number;\n readonly predictionDuration: number;\n readonly detectionDelay: number;\n readonly speechInput?: Int16Array;\n readonly probabilities?: Float32Array;\n readonly isInterruption?: boolean;\n readonly probability: number;\n\n constructor(params: {\n createdAt: number;\n speechInput?: Int16Array;\n totalDuration?: number;\n predictionDuration?: number;\n detectionDelay?: number;\n probabilities?: Float32Array;\n isInterruption?: boolean;\n }) {\n this.createdAt = params.createdAt;\n this.totalDuration = params.totalDuration ?? 0;\n this.predictionDuration = params.predictionDuration ?? 0;\n this.detectionDelay = params.detectionDelay ?? 0;\n this.speechInput = params.speechInput;\n this.probabilities = params.probabilities;\n this.isInterruption = params.isInterruption;\n this.probability = this.probabilities ? estimateProbability(this.probabilities) : 0;\n }\n\n static default(): InterruptionCacheEntry {\n return new InterruptionCacheEntry({ createdAt: 0 });\n }\n}\n"],"mappings":"AAAA,SAAS,2BAA2B;AACpC,SAAS,iCAAiC;AAEnC,IAAK,wBAAL,kBAAKA,2BAAL;AACL,EAAAA,uBAAA,kBAAe;AACf,EAAAA,uBAAA,0BAAuB;AAFb,SAAAA;AAAA,GAAA;AAiBL,MAAM,mCAAmC,MAAM;AAAA,EAC3C,OAAO;AAAA,EAEP;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,WAAmB,OAAe,aAAsB;AACnF,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,YAAY;AACjB,SAAK,QAAQ;AACb,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,WAAmB;AACjB,WAAO,GAAG,KAAK,IAAI,KAAK,KAAK,OAAO,WAAW,KAAK,KAAK,eAAe,KAAK,SAAS,iBAAiB,KAAK,WAAW;AAAA,EACzH;AACF;AAEA,SAAS,oBACP,eACA,aAAqB,2BACb;AACR,QAAM,YAAY,KAAK,KAAK,aAAa,KAAK;AAC9C,MAAI,cAAc,SAAS,WAAW;AACpC,WAAO;AAAA,EACT;AAEA,SAAO,oBAAoB,eAAe,UAAU;AACtD;AAKO,MAAM,uBAAuB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,QAQT;AACD,SAAK,YAAY,OAAO;AACxB,SAAK,gBAAgB,OAAO,iBAAiB;AAC7C,SAAK,qBAAqB,OAAO,sBAAsB;AACvD,SAAK,iBAAiB,OAAO,kBAAkB;AAC/C,SAAK,cAAc,OAAO;AAC1B,SAAK,gBAAgB,OAAO;AAC5B,SAAK,iBAAiB,OAAO;AAC7B,SAAK,cAAc,KAAK,gBAAgB,oBAAoB,KAAK,aAAa,IAAI;AAAA,EACpF;AAAA,EAEA,OAAO,UAAkC;AACvC,WAAO,IAAI,uBAAuB,EAAE,WAAW,EAAE,CAAC;AAAA,EACpD;AACF;","names":["InterruptionEventType"]}
@@ -19,7 +19,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var utils_exports = {};
20
20
  __export(utils_exports, {
21
21
  connectWs: () => connectWs,
22
- createAccessToken: () => createAccessToken
22
+ createAccessToken: () => createAccessToken,
23
+ slidingWindowMinMax: () => slidingWindowMinMax
23
24
  });
24
25
  module.exports = __toCommonJS(utils_exports);
25
26
  var import_livekit_server_sdk = require("livekit-server-sdk");
@@ -68,9 +69,21 @@ async function connectWs(url, headers, timeoutMs) {
68
69
  socket.once("close", onClose);
69
70
  });
70
71
  }
72
+ function slidingWindowMinMax(probabilities, minWindow) {
73
+ if (probabilities.length < minWindow) {
74
+ return -Infinity;
75
+ }
76
+ let maxOfMins = -Infinity;
77
+ for (let i = 0; i <= probabilities.length - minWindow; i++) {
78
+ const windowMin = Math.min(...probabilities.slice(i, i + minWindow));
79
+ maxOfMins = Math.max(maxOfMins, windowMin);
80
+ }
81
+ return maxOfMins;
82
+ }
71
83
  // Annotate the CommonJS export names for ESM import in node:
72
84
  0 && (module.exports = {
73
85
  connectWs,
74
- createAccessToken
86
+ createAccessToken,
87
+ slidingWindowMinMax
75
88
  });
76
89
  //# sourceMappingURL=utils.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/inference/utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { AccessToken } from 'livekit-server-sdk';\nimport { WebSocket } from 'ws';\nimport { APIConnectionError, APIStatusError } from '../index.js';\n\nexport type AnyString = string & NonNullable<unknown>;\n\nexport async function createAccessToken(\n apiKey: string,\n apiSecret: string,\n ttl: number = 600,\n): Promise<string> {\n const token = new AccessToken(apiKey, apiSecret, { identity: 'agent', ttl });\n token.addInferenceGrant({ perform: true });\n\n return await token.toJwt();\n}\n\nexport async function connectWs(\n url: string,\n headers: Record<string, string>,\n timeoutMs: number,\n): Promise<WebSocket> {\n return new Promise<WebSocket>((resolve, reject) => {\n const socket = new WebSocket(url, { headers: headers });\n\n const timeout = setTimeout(() => {\n reject(new APIConnectionError({ message: 'Timeout connecting to LiveKit WebSocket' }));\n }, timeoutMs);\n\n const onOpen = () => {\n clearTimeout(timeout);\n resolve(socket);\n };\n\n const onError = (err: unknown) => {\n clearTimeout(timeout);\n if (err && typeof err === 'object' && 'code' in err && (err as any).code === 429) {\n reject(\n new APIStatusError({\n message: 'LiveKit gateway quota exceeded',\n options: { statusCode: 429 },\n }),\n );\n } else {\n reject(new APIConnectionError({ message: 'Error connecting to LiveKit WebSocket' }));\n }\n };\n\n const onClose = (code: number) => {\n clearTimeout(timeout);\n if (code !== 1000) {\n reject(\n new APIConnectionError({\n message: 'Connection closed unexpectedly',\n }),\n );\n }\n };\n socket.once('open', onOpen);\n socket.once('error', onError);\n socket.once('close', onClose);\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,gCAA4B;AAC5B,gBAA0B;AAC1B,eAAmD;AAInD,eAAsB,kBACpB,QACA,WACA,MAAc,KACG;AACjB,QAAM,QAAQ,IAAI,sCAAY,QAAQ,WAAW,EAAE,UAAU,SAAS,IAAI,CAAC;AAC3E,QAAM,kBAAkB,EAAE,SAAS,KAAK,CAAC;AAEzC,SAAO,MAAM,MAAM,MAAM;AAC3B;AAEA,eAAsB,UACpB,KACA,SACA,WACoB;AACpB,SAAO,IAAI,QAAmB,CAAC,SAAS,WAAW;AACjD,UAAM,SAAS,IAAI,oBAAU,KAAK,EAAE,QAAiB,CAAC;AAEtD,UAAM,UAAU,WAAW,MAAM;AAC/B,aAAO,IAAI,4BAAmB,EAAE,SAAS,0CAA0C,CAAC,CAAC;AAAA,IACvF,GAAG,SAAS;AAEZ,UAAM,SAAS,MAAM;AACnB,mBAAa,OAAO;AACpB,cAAQ,MAAM;AAAA,IAChB;AAEA,UAAM,UAAU,CAAC,QAAiB;AAChC,mBAAa,OAAO;AACpB,UAAI,OAAO,OAAO,QAAQ,YAAY,UAAU,OAAQ,IAAY,SAAS,KAAK;AAChF;AAAA,UACE,IAAI,wBAAe;AAAA,YACjB,SAAS;AAAA,YACT,SAAS,EAAE,YAAY,IAAI;AAAA,UAC7B,CAAC;AAAA,QACH;AAAA,MACF,OAAO;AACL,eAAO,IAAI,4BAAmB,EAAE,SAAS,wCAAwC,CAAC,CAAC;AAAA,MACrF;AAAA,IACF;AAEA,UAAM,UAAU,CAAC,SAAiB;AAChC,mBAAa,OAAO;AACpB,UAAI,SAAS,KAAM;AACjB;AAAA,UACE,IAAI,4BAAmB;AAAA,YACrB,SAAS;AAAA,UACX,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK,QAAQ,MAAM;AAC1B,WAAO,KAAK,SAAS,OAAO;AAC5B,WAAO,KAAK,SAAS,OAAO;AAAA,EAC9B,CAAC;AACH;","names":[]}
1
+ {"version":3,"sources":["../../src/inference/utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { AccessToken } from 'livekit-server-sdk';\nimport { WebSocket } from 'ws';\nimport { APIConnectionError, APIStatusError } from '../index.js';\n\nexport type AnyString = string & NonNullable<unknown>;\n\nexport async function createAccessToken(\n apiKey: string,\n apiSecret: string,\n ttl: number = 600,\n): Promise<string> {\n const token = new AccessToken(apiKey, apiSecret, { identity: 'agent', ttl });\n token.addInferenceGrant({ perform: true });\n\n return await token.toJwt();\n}\n\nexport async function connectWs(\n url: string,\n headers: Record<string, string>,\n timeoutMs: number,\n): Promise<WebSocket> {\n return new Promise<WebSocket>((resolve, reject) => {\n const socket = new WebSocket(url, { headers: headers });\n\n const timeout = setTimeout(() => {\n reject(new APIConnectionError({ message: 'Timeout connecting to LiveKit WebSocket' }));\n }, timeoutMs);\n\n const onOpen = () => {\n clearTimeout(timeout);\n resolve(socket);\n };\n\n const onError = (err: unknown) => {\n clearTimeout(timeout);\n if (err && typeof err === 'object' && 'code' in err && (err as any).code === 429) {\n reject(\n new APIStatusError({\n message: 'LiveKit gateway quota exceeded',\n options: { statusCode: 429 },\n }),\n );\n } else {\n reject(new APIConnectionError({ message: 'Error connecting to LiveKit WebSocket' }));\n }\n };\n\n const onClose = (code: number) => {\n clearTimeout(timeout);\n if (code !== 1000) {\n reject(\n new APIConnectionError({\n message: 'Connection closed unexpectedly',\n }),\n );\n }\n };\n socket.once('open', onOpen);\n socket.once('error', onError);\n socket.once('close', onClose);\n });\n}\n\nexport function slidingWindowMinMax(probabilities: Float32Array, minWindow: number): number {\n if (probabilities.length < minWindow) {\n return -Infinity;\n }\n\n let maxOfMins = -Infinity;\n\n for (let i = 0; i <= probabilities.length - minWindow; i++) {\n const windowMin = Math.min(...probabilities.slice(i, i + minWindow));\n maxOfMins = Math.max(maxOfMins, windowMin);\n }\n\n return maxOfMins;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,gCAA4B;AAC5B,gBAA0B;AAC1B,eAAmD;AAInD,eAAsB,kBACpB,QACA,WACA,MAAc,KACG;AACjB,QAAM,QAAQ,IAAI,sCAAY,QAAQ,WAAW,EAAE,UAAU,SAAS,IAAI,CAAC;AAC3E,QAAM,kBAAkB,EAAE,SAAS,KAAK,CAAC;AAEzC,SAAO,MAAM,MAAM,MAAM;AAC3B;AAEA,eAAsB,UACpB,KACA,SACA,WACoB;AACpB,SAAO,IAAI,QAAmB,CAAC,SAAS,WAAW;AACjD,UAAM,SAAS,IAAI,oBAAU,KAAK,EAAE,QAAiB,CAAC;AAEtD,UAAM,UAAU,WAAW,MAAM;AAC/B,aAAO,IAAI,4BAAmB,EAAE,SAAS,0CAA0C,CAAC,CAAC;AAAA,IACvF,GAAG,SAAS;AAEZ,UAAM,SAAS,MAAM;AACnB,mBAAa,OAAO;AACpB,cAAQ,MAAM;AAAA,IAChB;AAEA,UAAM,UAAU,CAAC,QAAiB;AAChC,mBAAa,OAAO;AACpB,UAAI,OAAO,OAAO,QAAQ,YAAY,UAAU,OAAQ,IAAY,SAAS,KAAK;AAChF;AAAA,UACE,IAAI,wBAAe;AAAA,YACjB,SAAS;AAAA,YACT,SAAS,EAAE,YAAY,IAAI;AAAA,UAC7B,CAAC;AAAA,QACH;AAAA,MACF,OAAO;AACL,eAAO,IAAI,4BAAmB,EAAE,SAAS,wCAAwC,CAAC,CAAC;AAAA,MACrF;AAAA,IACF;AAEA,UAAM,UAAU,CAAC,SAAiB;AAChC,mBAAa,OAAO;AACpB,UAAI,SAAS,KAAM;AACjB;AAAA,UACE,IAAI,4BAAmB;AAAA,YACrB,SAAS;AAAA,UACX,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK,QAAQ,MAAM;AAC1B,WAAO,KAAK,SAAS,OAAO;AAC5B,WAAO,KAAK,SAAS,OAAO;AAAA,EAC9B,CAAC;AACH;AAEO,SAAS,oBAAoB,eAA6B,WAA2B;AAC1F,MAAI,cAAc,SAAS,WAAW;AACpC,WAAO;AAAA,EACT;AAEA,MAAI,YAAY;AAEhB,WAAS,IAAI,GAAG,KAAK,cAAc,SAAS,WAAW,KAAK;AAC1D,UAAM,YAAY,KAAK,IAAI,GAAG,cAAc,MAAM,GAAG,IAAI,SAAS,CAAC;AACnE,gBAAY,KAAK,IAAI,WAAW,SAAS;AAAA,EAC3C;AAEA,SAAO;AACT;","names":[]}
@@ -2,4 +2,5 @@ import { WebSocket } from 'ws';
2
2
  export type AnyString = string & NonNullable<unknown>;
3
3
  export declare function createAccessToken(apiKey: string, apiSecret: string, ttl?: number): Promise<string>;
4
4
  export declare function connectWs(url: string, headers: Record<string, string>, timeoutMs: number): Promise<WebSocket>;
5
+ export declare function slidingWindowMinMax(probabilities: Float32Array, minWindow: number): number;
5
6
  //# sourceMappingURL=utils.d.ts.map
@@ -2,4 +2,5 @@ import { WebSocket } from 'ws';
2
2
  export type AnyString = string & NonNullable<unknown>;
3
3
  export declare function createAccessToken(apiKey: string, apiSecret: string, ttl?: number): Promise<string>;
4
4
  export declare function connectWs(url: string, headers: Record<string, string>, timeoutMs: number): Promise<WebSocket>;
5
+ export declare function slidingWindowMinMax(probabilities: Float32Array, minWindow: number): number;
5
6
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/inference/utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAG/B,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;AAEtD,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,MAAY,GAChB,OAAO,CAAC,MAAM,CAAC,CAKjB;AAED,wBAAsB,SAAS,CAC7B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,SAAS,CAAC,CAyCpB"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/inference/utils.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAG/B,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;AAEtD,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,GAAG,GAAE,MAAY,GAChB,OAAO,CAAC,MAAM,CAAC,CAKjB;AAED,wBAAsB,SAAS,CAC7B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,SAAS,CAAC,CAyCpB;AAED,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAa1F"}
@@ -44,8 +44,20 @@ async function connectWs(url, headers, timeoutMs) {
44
44
  socket.once("close", onClose);
45
45
  });
46
46
  }
47
+ function slidingWindowMinMax(probabilities, minWindow) {
48
+ if (probabilities.length < minWindow) {
49
+ return -Infinity;
50
+ }
51
+ let maxOfMins = -Infinity;
52
+ for (let i = 0; i <= probabilities.length - minWindow; i++) {
53
+ const windowMin = Math.min(...probabilities.slice(i, i + minWindow));
54
+ maxOfMins = Math.max(maxOfMins, windowMin);
55
+ }
56
+ return maxOfMins;
57
+ }
47
58
  export {
48
59
  connectWs,
49
- createAccessToken
60
+ createAccessToken,
61
+ slidingWindowMinMax
50
62
  };
51
63
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/inference/utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { AccessToken } from 'livekit-server-sdk';\nimport { WebSocket } from 'ws';\nimport { APIConnectionError, APIStatusError } from '../index.js';\n\nexport type AnyString = string & NonNullable<unknown>;\n\nexport async function createAccessToken(\n apiKey: string,\n apiSecret: string,\n ttl: number = 600,\n): Promise<string> {\n const token = new AccessToken(apiKey, apiSecret, { identity: 'agent', ttl });\n token.addInferenceGrant({ perform: true });\n\n return await token.toJwt();\n}\n\nexport async function connectWs(\n url: string,\n headers: Record<string, string>,\n timeoutMs: number,\n): Promise<WebSocket> {\n return new Promise<WebSocket>((resolve, reject) => {\n const socket = new WebSocket(url, { headers: headers });\n\n const timeout = setTimeout(() => {\n reject(new APIConnectionError({ message: 'Timeout connecting to LiveKit WebSocket' }));\n }, timeoutMs);\n\n const onOpen = () => {\n clearTimeout(timeout);\n resolve(socket);\n };\n\n const onError = (err: unknown) => {\n clearTimeout(timeout);\n if (err && typeof err === 'object' && 'code' in err && (err as any).code === 429) {\n reject(\n new APIStatusError({\n message: 'LiveKit gateway quota exceeded',\n options: { statusCode: 429 },\n }),\n );\n } else {\n reject(new APIConnectionError({ message: 'Error connecting to LiveKit WebSocket' }));\n }\n };\n\n const onClose = (code: number) => {\n clearTimeout(timeout);\n if (code !== 1000) {\n reject(\n new APIConnectionError({\n message: 'Connection closed unexpectedly',\n }),\n );\n }\n };\n socket.once('open', onOpen);\n socket.once('error', onError);\n socket.once('close', onClose);\n });\n}\n"],"mappings":"AAGA,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB;AAC1B,SAAS,oBAAoB,sBAAsB;AAInD,eAAsB,kBACpB,QACA,WACA,MAAc,KACG;AACjB,QAAM,QAAQ,IAAI,YAAY,QAAQ,WAAW,EAAE,UAAU,SAAS,IAAI,CAAC;AAC3E,QAAM,kBAAkB,EAAE,SAAS,KAAK,CAAC;AAEzC,SAAO,MAAM,MAAM,MAAM;AAC3B;AAEA,eAAsB,UACpB,KACA,SACA,WACoB;AACpB,SAAO,IAAI,QAAmB,CAAC,SAAS,WAAW;AACjD,UAAM,SAAS,IAAI,UAAU,KAAK,EAAE,QAAiB,CAAC;AAEtD,UAAM,UAAU,WAAW,MAAM;AAC/B,aAAO,IAAI,mBAAmB,EAAE,SAAS,0CAA0C,CAAC,CAAC;AAAA,IACvF,GAAG,SAAS;AAEZ,UAAM,SAAS,MAAM;AACnB,mBAAa,OAAO;AACpB,cAAQ,MAAM;AAAA,IAChB;AAEA,UAAM,UAAU,CAAC,QAAiB;AAChC,mBAAa,OAAO;AACpB,UAAI,OAAO,OAAO,QAAQ,YAAY,UAAU,OAAQ,IAAY,SAAS,KAAK;AAChF;AAAA,UACE,IAAI,eAAe;AAAA,YACjB,SAAS;AAAA,YACT,SAAS,EAAE,YAAY,IAAI;AAAA,UAC7B,CAAC;AAAA,QACH;AAAA,MACF,OAAO;AACL,eAAO,IAAI,mBAAmB,EAAE,SAAS,wCAAwC,CAAC,CAAC;AAAA,MACrF;AAAA,IACF;AAEA,UAAM,UAAU,CAAC,SAAiB;AAChC,mBAAa,OAAO;AACpB,UAAI,SAAS,KAAM;AACjB;AAAA,UACE,IAAI,mBAAmB;AAAA,YACrB,SAAS;AAAA,UACX,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK,QAAQ,MAAM;AAC1B,WAAO,KAAK,SAAS,OAAO;AAC5B,WAAO,KAAK,SAAS,OAAO;AAAA,EAC9B,CAAC;AACH;","names":[]}
1
+ {"version":3,"sources":["../../src/inference/utils.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { AccessToken } from 'livekit-server-sdk';\nimport { WebSocket } from 'ws';\nimport { APIConnectionError, APIStatusError } from '../index.js';\n\nexport type AnyString = string & NonNullable<unknown>;\n\nexport async function createAccessToken(\n apiKey: string,\n apiSecret: string,\n ttl: number = 600,\n): Promise<string> {\n const token = new AccessToken(apiKey, apiSecret, { identity: 'agent', ttl });\n token.addInferenceGrant({ perform: true });\n\n return await token.toJwt();\n}\n\nexport async function connectWs(\n url: string,\n headers: Record<string, string>,\n timeoutMs: number,\n): Promise<WebSocket> {\n return new Promise<WebSocket>((resolve, reject) => {\n const socket = new WebSocket(url, { headers: headers });\n\n const timeout = setTimeout(() => {\n reject(new APIConnectionError({ message: 'Timeout connecting to LiveKit WebSocket' }));\n }, timeoutMs);\n\n const onOpen = () => {\n clearTimeout(timeout);\n resolve(socket);\n };\n\n const onError = (err: unknown) => {\n clearTimeout(timeout);\n if (err && typeof err === 'object' && 'code' in err && (err as any).code === 429) {\n reject(\n new APIStatusError({\n message: 'LiveKit gateway quota exceeded',\n options: { statusCode: 429 },\n }),\n );\n } else {\n reject(new APIConnectionError({ message: 'Error connecting to LiveKit WebSocket' }));\n }\n };\n\n const onClose = (code: number) => {\n clearTimeout(timeout);\n if (code !== 1000) {\n reject(\n new APIConnectionError({\n message: 'Connection closed unexpectedly',\n }),\n );\n }\n };\n socket.once('open', onOpen);\n socket.once('error', onError);\n socket.once('close', onClose);\n });\n}\n\nexport function slidingWindowMinMax(probabilities: Float32Array, minWindow: number): number {\n if (probabilities.length < minWindow) {\n return -Infinity;\n }\n\n let maxOfMins = -Infinity;\n\n for (let i = 0; i <= probabilities.length - minWindow; i++) {\n const windowMin = Math.min(...probabilities.slice(i, i + minWindow));\n maxOfMins = Math.max(maxOfMins, windowMin);\n }\n\n return maxOfMins;\n}\n"],"mappings":"AAGA,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB;AAC1B,SAAS,oBAAoB,sBAAsB;AAInD,eAAsB,kBACpB,QACA,WACA,MAAc,KACG;AACjB,QAAM,QAAQ,IAAI,YAAY,QAAQ,WAAW,EAAE,UAAU,SAAS,IAAI,CAAC;AAC3E,QAAM,kBAAkB,EAAE,SAAS,KAAK,CAAC;AAEzC,SAAO,MAAM,MAAM,MAAM;AAC3B;AAEA,eAAsB,UACpB,KACA,SACA,WACoB;AACpB,SAAO,IAAI,QAAmB,CAAC,SAAS,WAAW;AACjD,UAAM,SAAS,IAAI,UAAU,KAAK,EAAE,QAAiB,CAAC;AAEtD,UAAM,UAAU,WAAW,MAAM;AAC/B,aAAO,IAAI,mBAAmB,EAAE,SAAS,0CAA0C,CAAC,CAAC;AAAA,IACvF,GAAG,SAAS;AAEZ,UAAM,SAAS,MAAM;AACnB,mBAAa,OAAO;AACpB,cAAQ,MAAM;AAAA,IAChB;AAEA,UAAM,UAAU,CAAC,QAAiB;AAChC,mBAAa,OAAO;AACpB,UAAI,OAAO,OAAO,QAAQ,YAAY,UAAU,OAAQ,IAAY,SAAS,KAAK;AAChF;AAAA,UACE,IAAI,eAAe;AAAA,YACjB,SAAS;AAAA,YACT,SAAS,EAAE,YAAY,IAAI;AAAA,UAC7B,CAAC;AAAA,QACH;AAAA,MACF,OAAO;AACL,eAAO,IAAI,mBAAmB,EAAE,SAAS,wCAAwC,CAAC,CAAC;AAAA,MACrF;AAAA,IACF;AAEA,UAAM,UAAU,CAAC,SAAiB;AAChC,mBAAa,OAAO;AACpB,UAAI,SAAS,KAAM;AACjB;AAAA,UACE,IAAI,mBAAmB;AAAA,YACrB,SAAS;AAAA,UACX,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK,QAAQ,MAAM;AAC1B,WAAO,KAAK,SAAS,OAAO;AAC5B,WAAO,KAAK,SAAS,OAAO;AAAA,EAC9B,CAAC;AACH;AAEO,SAAS,oBAAoB,eAA6B,WAA2B;AAC1F,MAAI,cAAc,SAAS,WAAW;AACpC,WAAO;AAAA,EACT;AAEA,MAAI,YAAY;AAEhB,WAAS,IAAI,GAAG,KAAK,cAAc,SAAS,WAAW,KAAK;AAC1D,UAAM,YAAY,KAAK,IAAI,GAAG,cAAc,MAAM,GAAG,IAAI,SAAS,CAAC;AACnE,gBAAY,KAAK,IAAI,WAAW,SAAS;AAAA,EAC3C;AAEA,SAAO;AACT;","names":[]}
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var import_vitest = require("vitest");
3
+ var import_utils = require("./utils.cjs");
4
+ (0, import_vitest.describe)("slidingWindowMinMax", () => {
5
+ (0, import_vitest.it)("returns -Infinity when array is shorter than window size", () => {
6
+ (0, import_vitest.expect)((0, import_utils.slidingWindowMinMax)([0.5, 0.6], 3)).toBe(-Infinity);
7
+ (0, import_vitest.expect)((0, import_utils.slidingWindowMinMax)([], 1)).toBe(-Infinity);
8
+ });
9
+ (0, import_vitest.it)("returns the max value when window size is 1", () => {
10
+ (0, import_vitest.expect)((0, import_utils.slidingWindowMinMax)([0.1, 0.5, 0.3, 0.8, 0.2], 1)).toBe(0.8);
11
+ });
12
+ (0, import_vitest.it)("finds the best sustained probability across windows", () => {
13
+ (0, import_vitest.expect)((0, import_utils.slidingWindowMinMax)([0.2, 0.8, 0.7, 0.3, 0.9], 3)).toBe(0.3);
14
+ });
15
+ (0, import_vitest.it)("returns the single element when array length equals window size", () => {
16
+ (0, import_vitest.expect)((0, import_utils.slidingWindowMinMax)([0.5, 0.9, 0.7], 3)).toBe(0.5);
17
+ (0, import_vitest.expect)((0, import_utils.slidingWindowMinMax)([0.8], 1)).toBe(0.8);
18
+ });
19
+ });
20
+ //# sourceMappingURL=utils.test.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/inference/utils.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { describe, expect, it } from 'vitest';\nimport { slidingWindowMinMax } from './utils.js';\n\ndescribe('slidingWindowMinMax', () => {\n it('returns -Infinity when array is shorter than window size', () => {\n expect(slidingWindowMinMax([0.5, 0.6], 3)).toBe(-Infinity);\n expect(slidingWindowMinMax([], 1)).toBe(-Infinity);\n });\n\n it('returns the max value when window size is 1', () => {\n // With window size 1, min of each window is the element itself,\n // so max of mins is just the max of the array\n expect(slidingWindowMinMax([0.1, 0.5, 0.3, 0.8, 0.2], 1)).toBe(0.8);\n });\n\n it('finds the best sustained probability across windows', () => {\n // Windows of size 3: [0.2, 0.8, 0.7], [0.8, 0.7, 0.3], [0.7, 0.3, 0.9]\n // Mins: 0.2, 0.3, 0.3\n // Max of mins: 0.3\n expect(slidingWindowMinMax([0.2, 0.8, 0.7, 0.3, 0.9], 3)).toBe(0.3);\n });\n\n it('returns the single element when array length equals window size', () => {\n // Only one window covering the entire array, return min of that window\n expect(slidingWindowMinMax([0.5, 0.9, 0.7], 3)).toBe(0.5);\n expect(slidingWindowMinMax([0.8], 1)).toBe(0.8);\n });\n});\n"],"mappings":";AAGA,oBAAqC;AACrC,mBAAoC;AAAA,IAEpC,wBAAS,uBAAuB,MAAM;AACpC,wBAAG,4DAA4D,MAAM;AACnE,kCAAO,kCAAoB,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,EAAE,KAAK,SAAS;AACzD,kCAAO,kCAAoB,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,SAAS;AAAA,EACnD,CAAC;AAED,wBAAG,+CAA+C,MAAM;AAGtD,kCAAO,kCAAoB,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG;AAAA,EACpE,CAAC;AAED,wBAAG,uDAAuD,MAAM;AAI9D,kCAAO,kCAAoB,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG;AAAA,EACpE,CAAC;AAED,wBAAG,mEAAmE,MAAM;AAE1E,kCAAO,kCAAoB,CAAC,KAAK,KAAK,GAAG,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG;AACxD,kCAAO,kCAAoB,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG;AAAA,EAChD,CAAC;AACH,CAAC;","names":[]}
@@ -0,0 +1,19 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { slidingWindowMinMax } from "./utils.js";
3
+ describe("slidingWindowMinMax", () => {
4
+ it("returns -Infinity when array is shorter than window size", () => {
5
+ expect(slidingWindowMinMax([0.5, 0.6], 3)).toBe(-Infinity);
6
+ expect(slidingWindowMinMax([], 1)).toBe(-Infinity);
7
+ });
8
+ it("returns the max value when window size is 1", () => {
9
+ expect(slidingWindowMinMax([0.1, 0.5, 0.3, 0.8, 0.2], 1)).toBe(0.8);
10
+ });
11
+ it("finds the best sustained probability across windows", () => {
12
+ expect(slidingWindowMinMax([0.2, 0.8, 0.7, 0.3, 0.9], 3)).toBe(0.3);
13
+ });
14
+ it("returns the single element when array length equals window size", () => {
15
+ expect(slidingWindowMinMax([0.5, 0.9, 0.7], 3)).toBe(0.5);
16
+ expect(slidingWindowMinMax([0.8], 1)).toBe(0.8);
17
+ });
18
+ });
19
+ //# sourceMappingURL=utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/inference/utils.test.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport { describe, expect, it } from 'vitest';\nimport { slidingWindowMinMax } from './utils.js';\n\ndescribe('slidingWindowMinMax', () => {\n it('returns -Infinity when array is shorter than window size', () => {\n expect(slidingWindowMinMax([0.5, 0.6], 3)).toBe(-Infinity);\n expect(slidingWindowMinMax([], 1)).toBe(-Infinity);\n });\n\n it('returns the max value when window size is 1', () => {\n // With window size 1, min of each window is the element itself,\n // so max of mins is just the max of the array\n expect(slidingWindowMinMax([0.1, 0.5, 0.3, 0.8, 0.2], 1)).toBe(0.8);\n });\n\n it('finds the best sustained probability across windows', () => {\n // Windows of size 3: [0.2, 0.8, 0.7], [0.8, 0.7, 0.3], [0.7, 0.3, 0.9]\n // Mins: 0.2, 0.3, 0.3\n // Max of mins: 0.3\n expect(slidingWindowMinMax([0.2, 0.8, 0.7, 0.3, 0.9], 3)).toBe(0.3);\n });\n\n it('returns the single element when array length equals window size', () => {\n // Only one window covering the entire array, return min of that window\n expect(slidingWindowMinMax([0.5, 0.9, 0.7], 3)).toBe(0.5);\n expect(slidingWindowMinMax([0.8], 1)).toBe(0.8);\n });\n});\n"],"mappings":"AAGA,SAAS,UAAU,QAAQ,UAAU;AACrC,SAAS,2BAA2B;AAEpC,SAAS,uBAAuB,MAAM;AACpC,KAAG,4DAA4D,MAAM;AACnE,WAAO,oBAAoB,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,EAAE,KAAK,SAAS;AACzD,WAAO,oBAAoB,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,SAAS;AAAA,EACnD,CAAC;AAED,KAAG,+CAA+C,MAAM;AAGtD,WAAO,oBAAoB,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG;AAAA,EACpE,CAAC;AAED,KAAG,uDAAuD,MAAM;AAI9D,WAAO,oBAAoB,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG;AAAA,EACpE,CAAC;AAED,KAAG,mEAAmE,MAAM;AAE1E,WAAO,oBAAoB,CAAC,KAAK,KAAK,GAAG,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG;AACxD,WAAO,oBAAoB,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG;AAAA,EAChD,CAAC;AACH,CAAC;","names":[]}
@@ -29,6 +29,9 @@ function createStreamChannel() {
29
29
  return {
30
30
  write: (chunk) => writer.write(chunk),
31
31
  stream: () => transform.readable,
32
+ abort: (error) => {
33
+ return writer.abort(error);
34
+ },
32
35
  close: async () => {
33
36
  try {
34
37
  const result = await writer.close();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/stream/stream_channel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { ReadableStream } from 'node:stream/web';\nimport { IdentityTransform } from './identity_transform.js';\n\nexport interface StreamChannel<T> {\n write(chunk: T): Promise<void>;\n close(): Promise<void>;\n stream(): ReadableStream<T>;\n readonly closed: boolean;\n}\n\nexport function createStreamChannel<T>(): StreamChannel<T> {\n const transform = new IdentityTransform<T>();\n const writer = transform.writable.getWriter();\n let isClosed = false;\n\n return {\n write: (chunk: T) => writer.write(chunk),\n stream: () => transform.readable,\n close: async () => {\n try {\n const result = await writer.close();\n isClosed = true;\n return result;\n } catch (e) {\n if (e instanceof Error && e.name === 'TypeError') {\n // Ignore error if the stream is already closed\n isClosed = true;\n return;\n }\n throw e;\n }\n },\n get closed() {\n return isClosed;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,gCAAkC;AAS3B,SAAS,sBAA2C;AACzD,QAAM,YAAY,IAAI,4CAAqB;AAC3C,QAAM,SAAS,UAAU,SAAS,UAAU;AAC5C,MAAI,WAAW;AAEf,SAAO;AAAA,IACL,OAAO,CAAC,UAAa,OAAO,MAAM,KAAK;AAAA,IACvC,QAAQ,MAAM,UAAU;AAAA,IACxB,OAAO,YAAY;AACjB,UAAI;AACF,cAAM,SAAS,MAAM,OAAO,MAAM;AAClC,mBAAW;AACX,eAAO;AAAA,MACT,SAAS,GAAG;AACV,YAAI,aAAa,SAAS,EAAE,SAAS,aAAa;AAEhD,qBAAW;AACX;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,IAAI,SAAS;AACX,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/stream/stream_channel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\nimport type { ReadableStream } from 'node:stream/web';\nimport { IdentityTransform } from './identity_transform.js';\n\nexport interface StreamChannel<T, E extends Error = Error> {\n write(chunk: T): Promise<void>;\n close(): Promise<void>;\n stream(): ReadableStream<T>;\n abort(error: E): Promise<void>;\n readonly closed: boolean;\n}\n\nexport function createStreamChannel<T, E extends Error = Error>(): StreamChannel<T, E> {\n const transform = new IdentityTransform<T>();\n const writer = transform.writable.getWriter();\n let isClosed = false;\n\n return {\n write: (chunk: T) => writer.write(chunk),\n stream: () => transform.readable,\n abort: (error: E) => {\n return writer.abort(error);\n },\n close: async () => {\n try {\n const result = await writer.close();\n isClosed = true;\n return result;\n } catch (e) {\n if (e instanceof Error && e.name === 'TypeError') {\n // Ignore error if the stream is already closed\n isClosed = true;\n return;\n }\n throw e;\n }\n },\n get closed() {\n return isClosed;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,gCAAkC;AAU3B,SAAS,sBAAuE;AACrF,QAAM,YAAY,IAAI,4CAAqB;AAC3C,QAAM,SAAS,UAAU,SAAS,UAAU;AAC5C,MAAI,WAAW;AAEf,SAAO;AAAA,IACL,OAAO,CAAC,UAAa,OAAO,MAAM,KAAK;AAAA,IACvC,QAAQ,MAAM,UAAU;AAAA,IACxB,OAAO,CAAC,UAAa;AACnB,aAAO,OAAO,MAAM,KAAK;AAAA,IAC3B;AAAA,IACA,OAAO,YAAY;AACjB,UAAI;AACF,cAAM,SAAS,MAAM,OAAO,MAAM;AAClC,mBAAW;AACX,eAAO;AAAA,MACT,SAAS,GAAG;AACV,YAAI,aAAa,SAAS,EAAE,SAAS,aAAa;AAEhD,qBAAW;AACX;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA,IAAI,SAAS;AACX,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
@@ -1,10 +1,11 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
2
  import type { ReadableStream } from 'node:stream/web';
3
- export interface StreamChannel<T> {
3
+ export interface StreamChannel<T, E extends Error = Error> {
4
4
  write(chunk: T): Promise<void>;
5
5
  close(): Promise<void>;
6
6
  stream(): ReadableStream<T>;
7
+ abort(error: E): Promise<void>;
7
8
  readonly closed: boolean;
8
9
  }
9
- export declare function createStreamChannel<T>(): StreamChannel<T>;
10
+ export declare function createStreamChannel<T, E extends Error = Error>(): StreamChannel<T, E>;
10
11
  //# sourceMappingURL=stream_channel.d.ts.map
@@ -1,10 +1,11 @@
1
1
  /// <reference types="node" resolution-mode="require"/>
2
2
  import type { ReadableStream } from 'node:stream/web';
3
- export interface StreamChannel<T> {
3
+ export interface StreamChannel<T, E extends Error = Error> {
4
4
  write(chunk: T): Promise<void>;
5
5
  close(): Promise<void>;
6
6
  stream(): ReadableStream<T>;
7
+ abort(error: E): Promise<void>;
7
8
  readonly closed: boolean;
8
9
  }
9
- export declare function createStreamChannel<T>(): StreamChannel<T>;
10
+ export declare function createStreamChannel<T, E extends Error = Error>(): StreamChannel<T, E>;
10
11
  //# sourceMappingURL=stream_channel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stream_channel.d.ts","sourceRoot":"","sources":["../../src/stream/stream_channel.ts"],"names":[],"mappings":";AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGtD,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CAAC,CAAC,KAAK,aAAa,CAAC,CAAC,CAAC,CA0BzD"}
1
+ {"version":3,"file":"stream_channel.d.ts","sourceRoot":"","sources":["../../src/stream/stream_channel.ts"],"names":[],"mappings":";AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGtD,MAAM,WAAW,aAAa,CAAC,CAAC,EAAE,CAAC,SAAS,KAAK,GAAG,KAAK;IACvD,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,MAAM,IAAI,cAAc,CAAC,CAAC,CAAC,CAAC;IAC5B,KAAK,CAAC,KAAK,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,CAAC,SAAS,KAAK,GAAG,KAAK,KAAK,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CA6BrF"}
@@ -6,6 +6,9 @@ function createStreamChannel() {
6
6
  return {
7
7
  write: (chunk) => writer.write(chunk),
8
8
  stream: () => transform.readable,
9
+ abort: (error) => {
10
+ return writer.abort(error);
11
+ },
9
12
  close: async () => {
10
13
  try {
11
14
  const result = await writer.close();