@kuralle-syrinx/server-websocket 4.4.1 → 4.5.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 (132) hide show
  1. package/dist/backchannel-cue-fixtures.d.ts +4 -0
  2. package/dist/backchannel-cue-fixtures.d.ts.map +1 -0
  3. package/dist/backchannel-cue-fixtures.js +25 -0
  4. package/dist/backchannel-cue-fixtures.js.map +1 -0
  5. package/dist/background-audio.d.ts +59 -0
  6. package/dist/background-audio.d.ts.map +1 -0
  7. package/dist/background-audio.js +248 -0
  8. package/dist/background-audio.js.map +1 -0
  9. package/dist/browser-opus.d.ts +12 -0
  10. package/dist/browser-opus.d.ts.map +1 -0
  11. package/dist/browser-opus.js +48 -0
  12. package/dist/browser-opus.js.map +1 -0
  13. package/dist/carrier-commands.d.ts +124 -0
  14. package/dist/carrier-commands.d.ts.map +1 -0
  15. package/dist/carrier-commands.js +193 -0
  16. package/dist/carrier-commands.js.map +1 -0
  17. package/dist/edge-telnyx.d.ts +37 -0
  18. package/dist/edge-telnyx.d.ts.map +1 -0
  19. package/dist/edge-telnyx.js +320 -0
  20. package/dist/edge-telnyx.js.map +1 -0
  21. package/dist/edge-twilio.d.ts +31 -0
  22. package/dist/edge-twilio.d.ts.map +1 -0
  23. package/dist/edge-twilio.js +286 -0
  24. package/dist/edge-twilio.js.map +1 -0
  25. package/dist/edge.d.ts +71 -0
  26. package/dist/edge.d.ts.map +1 -0
  27. package/dist/edge.js +560 -0
  28. package/dist/edge.js.map +1 -0
  29. package/dist/inbound-audio.d.ts +13 -0
  30. package/dist/inbound-audio.d.ts.map +1 -0
  31. package/dist/inbound-audio.js +66 -0
  32. package/dist/inbound-audio.js.map +1 -0
  33. package/dist/index.d.ts +81 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +718 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/json-message.d.ts +7 -0
  38. package/dist/json-message.d.ts.map +1 -0
  39. package/dist/json-message.js +41 -0
  40. package/dist/json-message.js.map +1 -0
  41. package/dist/outbound-playout-pipeline.d.ts +53 -0
  42. package/dist/outbound-playout-pipeline.d.ts.map +1 -0
  43. package/dist/outbound-playout-pipeline.js +148 -0
  44. package/dist/outbound-playout-pipeline.js.map +1 -0
  45. package/dist/paced-playout.d.ts +42 -0
  46. package/dist/paced-playout.d.ts.map +1 -0
  47. package/dist/paced-playout.js +151 -0
  48. package/dist/paced-playout.js.map +1 -0
  49. package/dist/playout-progress.d.ts +26 -0
  50. package/dist/playout-progress.d.ts.map +1 -0
  51. package/dist/playout-progress.js +64 -0
  52. package/dist/playout-progress.js.map +1 -0
  53. package/dist/session-store.d.ts +39 -0
  54. package/dist/session-store.d.ts.map +1 -0
  55. package/dist/session-store.js +80 -0
  56. package/dist/session-store.js.map +1 -0
  57. package/dist/smartpbx.d.ts +47 -0
  58. package/dist/smartpbx.d.ts.map +1 -0
  59. package/dist/smartpbx.js +437 -0
  60. package/dist/smartpbx.js.map +1 -0
  61. package/dist/telnyx-codec.d.ts +41 -0
  62. package/dist/telnyx-codec.d.ts.map +1 -0
  63. package/dist/telnyx-codec.js +114 -0
  64. package/dist/telnyx-codec.js.map +1 -0
  65. package/dist/telnyx.d.ts +52 -0
  66. package/dist/telnyx.d.ts.map +1 -0
  67. package/dist/telnyx.js +550 -0
  68. package/dist/telnyx.js.map +1 -0
  69. package/dist/test-helpers.d.ts +20 -0
  70. package/dist/test-helpers.d.ts.map +1 -0
  71. package/dist/test-helpers.js +242 -0
  72. package/dist/test-helpers.js.map +1 -0
  73. package/dist/transport-helpers.d.ts +12 -0
  74. package/dist/transport-helpers.d.ts.map +1 -0
  75. package/dist/transport-helpers.js +90 -0
  76. package/dist/transport-helpers.js.map +1 -0
  77. package/dist/transport-host.d.ts +56 -0
  78. package/dist/transport-host.d.ts.map +1 -0
  79. package/dist/transport-host.js +110 -0
  80. package/dist/transport-host.js.map +1 -0
  81. package/dist/turn-metrics.d.ts +79 -0
  82. package/dist/turn-metrics.d.ts.map +1 -0
  83. package/dist/turn-metrics.js +208 -0
  84. package/dist/turn-metrics.js.map +1 -0
  85. package/dist/twilio-auth.d.ts +12 -0
  86. package/dist/twilio-auth.d.ts.map +1 -0
  87. package/dist/twilio-auth.js +44 -0
  88. package/dist/twilio-auth.js.map +1 -0
  89. package/dist/twilio.d.ts +56 -0
  90. package/dist/twilio.d.ts.map +1 -0
  91. package/dist/twilio.js +511 -0
  92. package/dist/twilio.js.map +1 -0
  93. package/dist/websocket-close.d.ts +12 -0
  94. package/dist/websocket-close.d.ts.map +1 -0
  95. package/dist/websocket-close.js +58 -0
  96. package/dist/websocket-close.js.map +1 -0
  97. package/dist/websocket-lifecycle.d.ts +29 -0
  98. package/dist/websocket-lifecycle.d.ts.map +1 -0
  99. package/dist/websocket-lifecycle.js +87 -0
  100. package/dist/websocket-lifecycle.js.map +1 -0
  101. package/dist/websocket-upgrade.d.ts +9 -0
  102. package/dist/websocket-upgrade.d.ts.map +1 -0
  103. package/dist/websocket-upgrade.js +91 -0
  104. package/dist/websocket-upgrade.js.map +1 -0
  105. package/dist/wire-carrier-control.d.ts +27 -0
  106. package/dist/wire-carrier-control.d.ts.map +1 -0
  107. package/dist/wire-carrier-control.js +116 -0
  108. package/dist/wire-carrier-control.js.map +1 -0
  109. package/package.json +32 -11
  110. package/src/admission-control.test.ts +270 -0
  111. package/src/background-audio.test.ts +224 -0
  112. package/src/browser-opus.test.ts +41 -0
  113. package/src/browser-pacing.test.ts +440 -0
  114. package/src/carrier-commands.test.ts +198 -0
  115. package/src/edge-telnyx.test.ts +333 -0
  116. package/src/edge-twilio.test.ts +293 -0
  117. package/src/edge.test.ts +727 -0
  118. package/src/graceful-drain.test.ts +306 -0
  119. package/src/inbound-audio.test.ts +58 -0
  120. package/src/index.test.ts +2078 -0
  121. package/src/outbound-playout-pipeline.test.ts +314 -0
  122. package/src/paced-playout.test.ts +247 -0
  123. package/src/playout-progress.test.ts +56 -0
  124. package/src/session-store.test.ts +274 -0
  125. package/src/smartpbx.test.ts +986 -0
  126. package/src/telnyx.test.ts +1633 -0
  127. package/src/transport-host.test.ts +51 -0
  128. package/src/turn-metrics.test.ts +503 -0
  129. package/src/twilio-auth.test.ts +36 -0
  130. package/src/twilio.test.ts +1274 -0
  131. package/src/websocket-close.test.ts +63 -0
  132. package/src/websocket-lifecycle.test.ts +49 -0
package/dist/edge.js ADDED
@@ -0,0 +1,560 @@
1
+ // SPDX-License-Identifier: MIT
2
+ import { Route, SYRINX_AUDIO_ENVELOPE_NAME, encodeSyrinxAudioEnvelope, } from "@kuralle-syrinx/core";
3
+ import { TimerScheduler } from "@kuralle-syrinx/core";
4
+ import { BackgroundAudioMixer, wireBackgroundAudio, } from "./background-audio.js";
5
+ import { createWorkersInboundSocket, } from "@kuralle-syrinx/ws/workers";
6
+ import { decodeInboundBinaryAudio, rememberContextSampleRate, resampleAudioBytes, socketDataToBytes, } from "./inbound-audio.js";
7
+ import { TurnMetricsTracker } from "./turn-metrics.js";
8
+ const DEFAULT_STARTUP_TIMEOUT_MS = 15_000;
9
+ const DEFAULT_MAX_SESSION_DURATION_MS = 30 * 60_000;
10
+ const DEFAULT_MAX_INBOUND_MESSAGE_BYTES = 2 * 1024 * 1024;
11
+ const DEFAULT_RESUME_WINDOW_MS = 15_000;
12
+ const DEFAULT_KEEP_ALIVE_INTERVAL_MS = 15_000;
13
+ const DEFAULT_IDLE_TIMEOUT_MS = 60_000;
14
+ const KEEP_ALIVE_KEY = "voice.edge.keep_alive";
15
+ export function createVoiceEdgeWebSocketResponse(request, options, ctx) {
16
+ return createVoiceEdgeWebSocketUpgrade(request, options, ctx).response;
17
+ }
18
+ export function createVoiceEdgeWebSocketUpgrade(request, options, ctx) {
19
+ const inbound = createWorkersInboundSocket(ctx);
20
+ void runVoiceEdgeWebSocketConnection(inbound.socket, request, options);
21
+ return { response: inbound.response, controller: inbound.controller };
22
+ }
23
+ export async function runVoiceEdgeWebSocketConnection(socket, request, options) {
24
+ const scheduler = options.scheduler ?? new TimerScheduler();
25
+ const contextIdFn = options.contextId ?? defaultContextId;
26
+ const inputSampleRateHz = positiveInteger(options.inputSampleRateHz) ?? 16000;
27
+ const outputSampleRateHz = positiveInteger(options.outputSampleRateHz) ?? 16000;
28
+ const startupTimeoutMs = nonNegativeInteger(options.startupTimeoutMs) ?? DEFAULT_STARTUP_TIMEOUT_MS;
29
+ const maxSessionDurationMs = nonNegativeInteger(options.maxSessionDurationMs) ?? DEFAULT_MAX_SESSION_DURATION_MS;
30
+ const maxInboundMessageBytes = positiveInteger(options.maxInboundMessageBytes) ?? DEFAULT_MAX_INBOUND_MESSAGE_BYTES;
31
+ const resumeWindowMs = nonNegativeInteger(options.resumeWindowMs) ?? DEFAULT_RESUME_WINDOW_MS;
32
+ const keepAliveIntervalMs = nonNegativeInteger(options.keepAliveIntervalMs) ?? DEFAULT_KEEP_ALIVE_INTERVAL_MS;
33
+ const idleTimeoutMs = nonNegativeInteger(options.idleTimeoutMs) ?? DEFAULT_IDLE_TIMEOUT_MS;
34
+ const rawBinaryInput = options.rawBinaryInput ?? false;
35
+ const state = {
36
+ managed: null,
37
+ initialContextId: contextIdFn(),
38
+ streamingResamplers: new Map(),
39
+ };
40
+ const disposers = [];
41
+ const pendingMessages = [];
42
+ let pendingMessageBytes = 0;
43
+ let ready = false;
44
+ let closed = false;
45
+ let maxSessionTimedOut = false;
46
+ let lastClientMessageMs = Date.now();
47
+ let session = null;
48
+ const sendError = (message) => {
49
+ sendJson(socket, {
50
+ type: "error",
51
+ component: "transport",
52
+ category: "invalid_input",
53
+ message,
54
+ });
55
+ };
56
+ const processMessage = (data, isBinary) => {
57
+ if (!session || !state.managed)
58
+ return;
59
+ const managed = state.managed;
60
+ options.sessionStore.update(managed.id, (stored) => {
61
+ stored.currentContextId = handleClientMessage(session, data, isBinary, stored.currentContextId, contextIdFn, inputSampleRateHz, rawBinaryInput, stored.contextSampleRates, stored.inputSequence, state.streamingResamplers);
62
+ });
63
+ };
64
+ socket.onMessage((data, isBinary) => {
65
+ try {
66
+ lastClientMessageMs = Date.now();
67
+ const byteLength = socketDataByteLength(data);
68
+ if (byteLength > maxInboundMessageBytes) {
69
+ sendError(`Websocket message exceeds maxInboundMessageBytes (${String(maxInboundMessageBytes)})`);
70
+ socket.dispose();
71
+ return;
72
+ }
73
+ if (!ready) {
74
+ pendingMessageBytes += byteLength;
75
+ if (pendingMessageBytes > maxInboundMessageBytes) {
76
+ sendError(`Pending websocket input exceeds maxInboundMessageBytes (${String(maxInboundMessageBytes)}) before session ready`);
77
+ socket.dispose();
78
+ return;
79
+ }
80
+ pendingMessages.push({ data: cloneSocketData(data), isBinary, byteLength });
81
+ return;
82
+ }
83
+ processMessage(data, isBinary);
84
+ }
85
+ catch (err) {
86
+ sendError(err instanceof Error ? err.message : String(err));
87
+ }
88
+ });
89
+ // Tear down on EITHER a clean close or an error-path disconnect, exactly once (guarded by
90
+ // `closed`). On Cloudflare Workers a DO webSocketError surfaces here as onError with no
91
+ // matching onClose, so finalize/release must also run on the error path — otherwise the
92
+ // in-memory recording is lost and the session lease never releases.
93
+ const teardownConnection = () => {
94
+ if (closed)
95
+ return;
96
+ closed = true;
97
+ for (const dispose of disposers.splice(0))
98
+ dispose();
99
+ if (state.managed) {
100
+ state.managed.connectionCount = Math.max(0, state.managed.connectionCount - 1);
101
+ void options.sessionStore.release(state.managed.id, maxSessionTimedOut ? 0 : resumeWindowMs);
102
+ }
103
+ if (options.recorder) {
104
+ void Promise.resolve(options.recorder.finalize({ sessionId: state.managed?.id ?? "unknown", closedAtMs: Date.now() })).catch(() => undefined);
105
+ }
106
+ };
107
+ socket.onClose(teardownConnection);
108
+ socket.onError(teardownConnection);
109
+ try {
110
+ // An explicit resolver is authoritative. Hosts such as cf-agents resolve the
111
+ // id before creating the session so the reasoner, session store, and transport
112
+ // all use the same identity even when the request carries a different wire id.
113
+ const requestedSessionId = sanitizeSessionId(options.sessionId?.(request) ?? sessionIdFromRequest(request) ?? defaultSessionId());
114
+ const leased = await withScheduledTimeout(options.sessionStore.lease(requestedSessionId, async () => {
115
+ const sess = await options.createSession(request);
116
+ if (closed) {
117
+ await sess.close().catch(() => undefined);
118
+ throw new Error("websocket session startup aborted");
119
+ }
120
+ await sess.start();
121
+ if (closed) {
122
+ await sess.close().catch(() => undefined);
123
+ throw new Error("websocket session startup aborted");
124
+ }
125
+ return {
126
+ id: requestedSessionId,
127
+ session: sess,
128
+ currentContextId: state.initialContextId,
129
+ contextSampleRates: new Map(),
130
+ inputSequence: { lastSequence: null },
131
+ turnMetricsTurns: new Map(),
132
+ closeTimer: null,
133
+ connectionCount: 1,
134
+ };
135
+ }), startupTimeoutMs, scheduler, "voice.edge.startup_timeout");
136
+ state.managed = leased.managed;
137
+ session = leased.managed.session;
138
+ if (closed) {
139
+ await options.sessionStore.release(leased.managed.id, 0);
140
+ return;
141
+ }
142
+ wireEdgeSessionEvents(session, socket, disposers, outputSampleRateHz, leased.managed.turnMetricsTurns, options.recorder, options.backgroundAudio ? new BackgroundAudioMixer(options.backgroundAudio) : undefined);
143
+ if (options.recorder) {
144
+ const recorder = options.recorder;
145
+ disposers.push(session.bus.on("user.audio_received", (pkt) => {
146
+ const audio = pkt;
147
+ recorder.onUserAudio(audio.contextId, audio.audio, inputSampleRateHz);
148
+ }));
149
+ }
150
+ if (maxSessionDurationMs > 0) {
151
+ scheduler.schedule("voice.edge.max_session_duration", maxSessionDurationMs, () => {
152
+ maxSessionTimedOut = true;
153
+ sendJson(socket, {
154
+ type: "error",
155
+ component: "transport",
156
+ category: "session_timeout",
157
+ message: "Websocket max session duration exceeded",
158
+ });
159
+ socket.dispose();
160
+ });
161
+ disposers.push(() => scheduler.cancel("voice.edge.max_session_duration"));
162
+ }
163
+ if (keepAliveIntervalMs > 0) {
164
+ const heartbeat = () => {
165
+ if (closed)
166
+ return;
167
+ if (idleTimeoutMs > 0 && Date.now() - lastClientMessageMs > idleTimeoutMs) {
168
+ sendJson(socket, {
169
+ type: "error",
170
+ component: "transport",
171
+ category: "idle_timeout",
172
+ message: `Websocket idle for more than idleTimeoutMs (${String(idleTimeoutMs)})`,
173
+ });
174
+ socket.dispose();
175
+ return;
176
+ }
177
+ // Re-arm: on the Workers DO scheduler this keeps the alarm (and thus the
178
+ // Durable Object) alive while the client is active; on Node it is a plain
179
+ // interval. Cancelled on close so an idle DO can be evicted.
180
+ scheduler.schedule(KEEP_ALIVE_KEY, keepAliveIntervalMs, heartbeat);
181
+ };
182
+ scheduler.schedule(KEEP_ALIVE_KEY, keepAliveIntervalMs, heartbeat);
183
+ disposers.push(() => scheduler.cancel(KEEP_ALIVE_KEY));
184
+ }
185
+ sendJson(socket, {
186
+ type: "ready",
187
+ sessionId: leased.managed.id,
188
+ turnId: leased.managed.currentContextId,
189
+ resumed: leased.resumed,
190
+ resumeWindowMs,
191
+ maxSessionDurationMs,
192
+ audio: {
193
+ inputSampleRateHz,
194
+ outputSampleRateHz,
195
+ encoding: "pcm_s16le",
196
+ supportedInputCodecs: ["pcm_s16le"],
197
+ channels: 1,
198
+ binaryEnvelope: SYRINX_AUDIO_ENVELOPE_NAME,
199
+ rawBinaryInput,
200
+ maxInboundMessageBytes,
201
+ },
202
+ });
203
+ ready = true;
204
+ for (const pending of pendingMessages.splice(0)) {
205
+ pendingMessageBytes -= pending.byteLength;
206
+ processMessage(pending.data, pending.isBinary);
207
+ }
208
+ }
209
+ catch (err) {
210
+ sendJson(socket, {
211
+ type: "error",
212
+ component: "session",
213
+ category: "initialization",
214
+ message: err instanceof Error ? err.message : String(err),
215
+ });
216
+ socket.dispose();
217
+ }
218
+ }
219
+ function wireEdgeSessionEvents(session, socket, disposers, outputSampleRateHz, turnMetricsTurns, recorder, backgroundAudio) {
220
+ if (backgroundAudio)
221
+ wireBackgroundAudio(session, backgroundAudio);
222
+ // Same per-turn latency decomposition the Node websocket path emits (turn-metrics.ts) —
223
+ // the browser/edge protocol is shared, so the `metrics` message must be too. Unlike
224
+ // Node, this transport is client-paced (no server-side pacer guarantees a
225
+ // `tts.playout_progress` completion), so also finalize on `tts.end` — see
226
+ // TurnMetricsTrackerOptions.finalizeOnTtsEnd.
227
+ const turnMetrics = new TurnMetricsTracker(session.bus, (message) => sendJson(socket, message), turnMetricsTurns, { finalizeOnTtsEnd: true });
228
+ turnMetrics.wire(disposers);
229
+ const onSession = (event, handler) => {
230
+ session.on(event, handler);
231
+ disposers.push(() => session.off(event, handler));
232
+ };
233
+ onSession("user_input_final", (event) => {
234
+ // Skip empty transcripts — a trailing-silence turn (e.g. realtime VAD re-triggering on silence)
235
+ // produces an empty user input that would render as a blank transcript bubble.
236
+ if (!event.text.trim())
237
+ return;
238
+ sendJson(socket, { type: "stt_output", turnId: event.turnId, transcript: event.text, confidence: event.confidence });
239
+ });
240
+ onSession("agent_text_delta", (event) => {
241
+ sendJson(socket, { type: "agent_chunk", turnId: event.turnId, text: event.delta });
242
+ });
243
+ // G3 (RFC bimodel-delegate-seam): typed preamble/filler lifecycle. The standard
244
+ // "thinking" wire cue — clients key earcons/indicators on these instead of an
245
+ // app-invented message. started fires before the reasoner runs; delayed is the
246
+ // time-triggered "still working"; complete/failed end the wait (incl. barge-in).
247
+ onSession("tool_call_cue", (event) => {
248
+ sendJson(socket, {
249
+ type: `tool_call_${event.phase}`,
250
+ turnId: event.turnId,
251
+ toolId: event.toolId,
252
+ toolName: event.toolName,
253
+ ...(event.afterMs !== undefined ? { afterMs: event.afterMs } : {}),
254
+ });
255
+ });
256
+ onSession("agent_finished", (event) => {
257
+ sendJson(socket, { type: "agent_end", turnId: event.turnId });
258
+ });
259
+ onSession("error", (event) => {
260
+ sendJson(socket, { type: "error", component: event.stage, category: event.category, message: event.message });
261
+ });
262
+ disposers.push(session.bus.on("tts.audio", (pkt) => {
263
+ const audio = pkt;
264
+ const ttsSampleRate = requireTtsAudioSampleRate(audio.sampleRateHz) ?? outputSampleRateHz;
265
+ // Recorder gets the CLEAN assistant track; the bed is a wire-level effect.
266
+ recorder?.onAssistantAudio(audio.contextId, audio.audio, ttsSampleRate);
267
+ const wireAudio = backgroundAudio ? backgroundAudio.mix(audio.audio, ttsSampleRate) : audio.audio;
268
+ sendJson(socket, {
269
+ type: "tts_chunk",
270
+ turnId: audio.contextId,
271
+ sequence: 1,
272
+ sampleRateHz: ttsSampleRate,
273
+ encoding: "pcm_s16le",
274
+ channels: 1,
275
+ byteLength: wireAudio.byteLength,
276
+ durationMs: pcm16DurationMs(wireAudio, outputSampleRateHz),
277
+ });
278
+ socket.send(encodeSyrinxAudioEnvelope({
279
+ type: "audio",
280
+ contextId: audio.contextId,
281
+ sequence: 1,
282
+ sampleRateHz: ttsSampleRate,
283
+ encoding: "pcm_s16le",
284
+ channels: 1,
285
+ byteLength: wireAudio.byteLength,
286
+ durationMs: pcm16DurationMs(wireAudio, outputSampleRateHz),
287
+ }, wireAudio));
288
+ }), session.bus.on("tts.end", (pkt) => {
289
+ const end = pkt;
290
+ sendJson(socket, { type: "tts_end", ...(end.contextId ? { turnId: end.contextId } : {}) });
291
+ }), session.bus.on("eos.turn_complete", (pkt) => {
292
+ const turn = pkt;
293
+ sendJson(socket, { type: "turn_complete", turnId: turn.contextId, transcript: turn.text ?? "" });
294
+ }),
295
+ // Barge-in: tell the client to flush queued playout immediately (same wire
296
+ // messages as the Node server path — the browser client flushes its jitter
297
+ // buffer on either).
298
+ session.bus.on("interrupt.detected", (pkt) => {
299
+ const interrupt = pkt;
300
+ sendJson(socket, { type: "audio_clear", turnId: interrupt.contextId, reason: "barge_in" });
301
+ sendJson(socket, { type: "agent_interrupted", turnId: interrupt.contextId, reason: "barge_in" });
302
+ }));
303
+ }
304
+ function handleClientMessage(session, data, isBinary, currentContextId, contextId, inputSampleRateHz, rawBinaryInput, contextSampleRates, inputSequence, streamingResamplers) {
305
+ if (isBinary) {
306
+ const binaryAudio = decodeInboundBinaryAudio(socketDataToBytes(data), inputSampleRateHz, rawBinaryInput, inputSampleRateHz, streamingResamplers, null);
307
+ const nextContextId = binaryAudio.contextId ?? currentContextId;
308
+ if (nextContextId !== currentContextId) {
309
+ session.bus.push(Route.Main, {
310
+ kind: "turn.change",
311
+ contextId: nextContextId,
312
+ previousContextId: currentContextId,
313
+ reason: "websocket_binary_audio_turn",
314
+ timestampMs: Date.now(),
315
+ });
316
+ }
317
+ rememberContextSampleRate(contextSampleRates, nextContextId, binaryAudio.sampleRateHz);
318
+ rememberInputSequence(session, inputSequence, nextContextId, binaryAudio.sequence);
319
+ const audio = resampleAudioBytes(binaryAudio.audio, binaryAudio.sampleRateHz, inputSampleRateHz, streamingResamplers);
320
+ session.bus.push(Route.Main, {
321
+ kind: "user.audio_received",
322
+ contextId: nextContextId,
323
+ timestampMs: Date.now(),
324
+ audio,
325
+ sampleRateHz: inputSampleRateHz,
326
+ });
327
+ return nextContextId;
328
+ }
329
+ const message = parseClientMessage(JSON.parse(typeof data === "string" ? data : textDecoder.decode(data)));
330
+ if (message.type === "ping")
331
+ return currentContextId;
332
+ if (message.type === "codec_capability")
333
+ return currentContextId; // edge sends pcm_s16le downlink; no-op
334
+ if (message.type === "client_interrupt") {
335
+ const interruptedContextId = message.assistantContextId ?? message.contextId ?? currentContextId;
336
+ if (interruptedContextId)
337
+ session.requestClientInterrupt(interruptedContextId);
338
+ return currentContextId;
339
+ }
340
+ if (message.type === "playout_progress") {
341
+ // On client-rendered-audio transports the browser is the playout clock: the server streams
342
+ // audio envelopes and the client schedules them. Map its reported position onto the same
343
+ // `tts.playout_progress` packet the server-paced path emits, so turn-truncation (realtime
344
+ // barge-in) and turn-metrics consume an accurate played-out offset instead of a stale 0.
345
+ const progressContextId = message.contextId ?? currentContextId;
346
+ if (progressContextId) {
347
+ session.bus.push(Route.Main, {
348
+ kind: "tts.playout_progress",
349
+ contextId: progressContextId,
350
+ timestampMs: Date.now(),
351
+ playedOutMs: message.playedOutMs,
352
+ complete: message.complete ?? false,
353
+ });
354
+ }
355
+ return currentContextId;
356
+ }
357
+ if (message.type === "text") {
358
+ const nextContextId = message.contextId ?? contextId();
359
+ session.bus.push(Route.Main, {
360
+ kind: "turn.change",
361
+ contextId: nextContextId,
362
+ previousContextId: currentContextId,
363
+ reason: "websocket_text_turn",
364
+ timestampMs: Date.now(),
365
+ });
366
+ session.bus.push(Route.Main, {
367
+ kind: "user.text_received",
368
+ contextId: nextContextId,
369
+ timestampMs: Date.now(),
370
+ text: message.text,
371
+ });
372
+ return nextContextId;
373
+ }
374
+ const nextContextId = message.contextId ?? currentContextId;
375
+ if (nextContextId !== currentContextId) {
376
+ session.bus.push(Route.Main, {
377
+ kind: "turn.change",
378
+ contextId: nextContextId,
379
+ previousContextId: currentContextId,
380
+ reason: "websocket_audio_turn",
381
+ timestampMs: Date.now(),
382
+ });
383
+ }
384
+ rememberContextSampleRate(contextSampleRates, nextContextId, message.sampleRateHz);
385
+ rememberInputSequence(session, inputSequence, nextContextId, message.sequence);
386
+ const audio = resampleAudioBytes(decodeBase64(message.audio), message.sampleRateHz, inputSampleRateHz, streamingResamplers);
387
+ session.bus.push(Route.Main, {
388
+ kind: "user.audio_received",
389
+ contextId: nextContextId,
390
+ timestampMs: Date.now(),
391
+ audio,
392
+ sampleRateHz: inputSampleRateHz,
393
+ });
394
+ return nextContextId;
395
+ }
396
+ function parseClientMessage(value) {
397
+ if (!isRecord(value))
398
+ throw new Error("Websocket JSON message must be an object");
399
+ if (value.type === "ping")
400
+ return { type: "ping" };
401
+ if (value.type === "codec_capability") {
402
+ // The edge transmits pcm_s16le downlink only (no opus encoder on workerd); accept the client's
403
+ // capability advert and no-op it. The client decodes per-frame `encoding`, so pcm is always safe.
404
+ const downlinkEncoding = value.downlinkEncoding === "opus" ? "opus" : "pcm_s16le";
405
+ return { type: "codec_capability", downlinkEncoding };
406
+ }
407
+ if (value.type === "client_interrupt") {
408
+ return {
409
+ type: "client_interrupt",
410
+ assistantContextId: optionalString(value.assistantContextId),
411
+ contextId: optionalString(value.contextId),
412
+ };
413
+ }
414
+ if (value.type === "playout_progress") {
415
+ const playedOutMs = nonNegativeInteger(value.playedOutMs);
416
+ if (playedOutMs === null) {
417
+ throw new Error("Websocket playout_progress playedOutMs must be a non-negative integer");
418
+ }
419
+ return {
420
+ type: "playout_progress",
421
+ contextId: optionalString(value.contextId),
422
+ playedOutMs,
423
+ complete: typeof value.complete === "boolean" ? value.complete : undefined,
424
+ };
425
+ }
426
+ if (value.type === "text") {
427
+ const text = optionalString(value.text);
428
+ if (!text)
429
+ throw new Error("Websocket JSON text must be a non-empty string");
430
+ return { type: "text", text, contextId: optionalString(value.contextId) };
431
+ }
432
+ if (value.type === "audio") {
433
+ const audio = optionalString(value.audio);
434
+ const sampleRateHz = positiveInteger(value.sampleRateHz);
435
+ if (!audio)
436
+ throw new Error("Websocket JSON audio must be a non-empty base64 string");
437
+ if (!sampleRateHz)
438
+ throw new Error("JSON websocket audio sampleRateHz must be a positive integer");
439
+ return {
440
+ type: "audio",
441
+ audio,
442
+ contextId: optionalString(value.contextId),
443
+ sampleRateHz,
444
+ sequence: nonNegativeInteger(value.sequence) ?? undefined,
445
+ };
446
+ }
447
+ throw new Error("Unsupported client message type");
448
+ }
449
+ function rememberInputSequence(session, state, contextId, sequence) {
450
+ if (sequence === undefined)
451
+ return;
452
+ const previous = state.lastSequence;
453
+ if (previous !== null && sequence <= previous) {
454
+ throw new Error(`Websocket audio sequence must increase monotonically: ${String(previous)} -> ${String(sequence)}`);
455
+ }
456
+ if (previous !== null && sequence > previous + 1) {
457
+ session.bus.push(Route.Background, {
458
+ kind: "metric.conversation",
459
+ contextId,
460
+ timestampMs: Date.now(),
461
+ name: "websocket.audio_sequence_gap",
462
+ value: JSON.stringify({ expected: previous + 1, actual: sequence, missed: sequence - previous - 1 }),
463
+ });
464
+ }
465
+ state.lastSequence = sequence;
466
+ }
467
+ function sendJson(socket, value) {
468
+ if (!socket.isOpen)
469
+ return;
470
+ socket.send(JSON.stringify(value));
471
+ }
472
+ const textEncoder = new TextEncoder();
473
+ const textDecoder = new TextDecoder();
474
+ function decodeBase64(value) {
475
+ const raw = globalThis.atob(value);
476
+ const bytes = new Uint8Array(raw.length);
477
+ for (let i = 0; i < raw.length; i += 1)
478
+ bytes[i] = raw.charCodeAt(i);
479
+ return bytes;
480
+ }
481
+ function socketDataByteLength(data) {
482
+ return typeof data === "string" ? textEncoder.encode(data).byteLength : data.byteLength;
483
+ }
484
+ function cloneSocketData(data) {
485
+ return typeof data === "string" ? data : data.slice();
486
+ }
487
+ function sessionIdFromRequest(request) {
488
+ try {
489
+ const parsed = new URL(request.url);
490
+ return parsed.searchParams.get("sessionId") ?? parsed.searchParams.get("session_id");
491
+ }
492
+ catch {
493
+ return null;
494
+ }
495
+ }
496
+ function sanitizeSessionId(value) {
497
+ const trimmed = value.trim();
498
+ if (/^[A-Za-z0-9_.:-]{1,128}$/.test(trimmed))
499
+ return trimmed;
500
+ return defaultSessionId();
501
+ }
502
+ function isRecord(value) {
503
+ return typeof value === "object" && value !== null;
504
+ }
505
+ function optionalString(value) {
506
+ return typeof value === "string" && value.length > 0 ? value : undefined;
507
+ }
508
+ function positiveInteger(value) {
509
+ if (typeof value !== "number" || !Number.isInteger(value) || value <= 0)
510
+ return null;
511
+ return value;
512
+ }
513
+ function nonNegativeInteger(value) {
514
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 0)
515
+ return null;
516
+ return value;
517
+ }
518
+ function requireTtsAudioSampleRate(value) {
519
+ return positiveInteger(value);
520
+ }
521
+ function pcm16DurationMs(audio, sampleRateHz) {
522
+ if (sampleRateHz <= 0)
523
+ return 0;
524
+ return Math.round((audio.byteLength / 2 / sampleRateHz) * 1000);
525
+ }
526
+ function defaultContextId() {
527
+ return `turn-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
528
+ }
529
+ function defaultSessionId() {
530
+ return `session-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
531
+ }
532
+ async function withScheduledTimeout(promise, timeoutMs, scheduler, key) {
533
+ if (timeoutMs <= 0)
534
+ return await promise;
535
+ let settled = false;
536
+ return await new Promise((resolve, reject) => {
537
+ scheduler.schedule(key, timeoutMs, () => {
538
+ if (settled)
539
+ return;
540
+ settled = true;
541
+ reject(new Error(`websocket session startup exceeded ${String(timeoutMs)}ms`));
542
+ });
543
+ promise
544
+ .then((value) => {
545
+ if (settled)
546
+ return;
547
+ settled = true;
548
+ scheduler.cancel(key);
549
+ resolve(value);
550
+ })
551
+ .catch((err) => {
552
+ if (settled)
553
+ return;
554
+ settled = true;
555
+ scheduler.cancel(key);
556
+ reject(err);
557
+ });
558
+ });
559
+ }
560
+ //# sourceMappingURL=edge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edge.js","sourceRoot":"","sources":["../src/edge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { type StreamingPcm16Resampler } from "@kuralle-syrinx/core/audio";
2
+ export type OpusIngressDecoder = (wire: Uint8Array, sampleRateHz: number) => Uint8Array;
3
+ export interface DecodedInboundBinaryAudio {
4
+ readonly contextId?: string;
5
+ readonly sampleRateHz: number;
6
+ readonly sequence?: number;
7
+ readonly audio: Uint8Array;
8
+ }
9
+ export declare function socketDataToBytes(data: string | Uint8Array): Uint8Array;
10
+ export declare function decodeInboundBinaryAudio(data: Uint8Array, defaultSampleRateHz: number, rawBinaryInput: boolean, engineInputSampleRateHz: number, streamingResamplers: Map<string, StreamingPcm16Resampler>, decodeOpusIngress: OpusIngressDecoder | null): DecodedInboundBinaryAudio;
11
+ export declare function rememberContextSampleRate(contextSampleRates: Map<string, number>, contextId: string, sampleRateHz: number): void;
12
+ export declare function resampleAudioBytes(audio: Uint8Array, sourceSampleRateHz: number, targetSampleRateHz: number, streamingResamplers: Map<string, StreamingPcm16Resampler>): Uint8Array;
13
+ //# sourceMappingURL=inbound-audio.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inbound-audio.d.ts","sourceRoot":"","sources":["../src/inbound-audio.ts"],"names":[],"mappings":"AAOA,OAAO,EAIL,KAAK,uBAAuB,EAC7B,MAAM,4BAA4B,CAAC;AAEpC,MAAM,MAAM,kBAAkB,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,KAAK,UAAU,CAAC;AAExF,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;CAC5B;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,UAAU,CAGvE;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,UAAU,EAChB,mBAAmB,EAAE,MAAM,EAC3B,cAAc,EAAE,OAAO,EACvB,uBAAuB,EAAE,MAAM,EAC/B,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,uBAAuB,CAAC,EACzD,iBAAiB,EAAE,kBAAkB,GAAG,IAAI,GAC3C,yBAAyB,CAyB3B;AAkBD,wBAAgB,yBAAyB,CACvC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACvC,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,IAAI,CAMN;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,UAAU,EACjB,kBAAkB,EAAE,MAAM,EAC1B,kBAAkB,EAAE,MAAM,EAC1B,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,uBAAuB,CAAC,GACxD,UAAU,CAQZ"}