@kuralle-syrinx/server-websocket 4.4.0 → 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.
- package/dist/backchannel-cue-fixtures.d.ts +4 -0
- package/dist/backchannel-cue-fixtures.d.ts.map +1 -0
- package/dist/backchannel-cue-fixtures.js +25 -0
- package/dist/backchannel-cue-fixtures.js.map +1 -0
- package/dist/background-audio.d.ts +59 -0
- package/dist/background-audio.d.ts.map +1 -0
- package/dist/background-audio.js +248 -0
- package/dist/background-audio.js.map +1 -0
- package/dist/browser-opus.d.ts +12 -0
- package/dist/browser-opus.d.ts.map +1 -0
- package/dist/browser-opus.js +48 -0
- package/dist/browser-opus.js.map +1 -0
- package/dist/carrier-commands.d.ts +124 -0
- package/dist/carrier-commands.d.ts.map +1 -0
- package/dist/carrier-commands.js +193 -0
- package/dist/carrier-commands.js.map +1 -0
- package/dist/edge-telnyx.d.ts +37 -0
- package/dist/edge-telnyx.d.ts.map +1 -0
- package/dist/edge-telnyx.js +320 -0
- package/dist/edge-telnyx.js.map +1 -0
- package/dist/edge-twilio.d.ts +31 -0
- package/dist/edge-twilio.d.ts.map +1 -0
- package/dist/edge-twilio.js +286 -0
- package/dist/edge-twilio.js.map +1 -0
- package/dist/edge.d.ts +71 -0
- package/dist/edge.d.ts.map +1 -0
- package/dist/edge.js +560 -0
- package/dist/edge.js.map +1 -0
- package/dist/inbound-audio.d.ts +13 -0
- package/dist/inbound-audio.d.ts.map +1 -0
- package/dist/inbound-audio.js +66 -0
- package/dist/inbound-audio.js.map +1 -0
- package/dist/index.d.ts +81 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +718 -0
- package/dist/index.js.map +1 -0
- package/dist/json-message.d.ts +7 -0
- package/dist/json-message.d.ts.map +1 -0
- package/dist/json-message.js +41 -0
- package/dist/json-message.js.map +1 -0
- package/dist/outbound-playout-pipeline.d.ts +53 -0
- package/dist/outbound-playout-pipeline.d.ts.map +1 -0
- package/dist/outbound-playout-pipeline.js +148 -0
- package/dist/outbound-playout-pipeline.js.map +1 -0
- package/dist/paced-playout.d.ts +42 -0
- package/dist/paced-playout.d.ts.map +1 -0
- package/dist/paced-playout.js +151 -0
- package/dist/paced-playout.js.map +1 -0
- package/dist/playout-progress.d.ts +26 -0
- package/dist/playout-progress.d.ts.map +1 -0
- package/dist/playout-progress.js +64 -0
- package/dist/playout-progress.js.map +1 -0
- package/dist/session-store.d.ts +39 -0
- package/dist/session-store.d.ts.map +1 -0
- package/dist/session-store.js +80 -0
- package/dist/session-store.js.map +1 -0
- package/dist/smartpbx.d.ts +47 -0
- package/dist/smartpbx.d.ts.map +1 -0
- package/dist/smartpbx.js +437 -0
- package/dist/smartpbx.js.map +1 -0
- package/dist/telnyx-codec.d.ts +41 -0
- package/dist/telnyx-codec.d.ts.map +1 -0
- package/dist/telnyx-codec.js +114 -0
- package/dist/telnyx-codec.js.map +1 -0
- package/dist/telnyx.d.ts +52 -0
- package/dist/telnyx.d.ts.map +1 -0
- package/dist/telnyx.js +550 -0
- package/dist/telnyx.js.map +1 -0
- package/dist/test-helpers.d.ts +20 -0
- package/dist/test-helpers.d.ts.map +1 -0
- package/dist/test-helpers.js +242 -0
- package/dist/test-helpers.js.map +1 -0
- package/dist/transport-helpers.d.ts +12 -0
- package/dist/transport-helpers.d.ts.map +1 -0
- package/dist/transport-helpers.js +90 -0
- package/dist/transport-helpers.js.map +1 -0
- package/dist/transport-host.d.ts +56 -0
- package/dist/transport-host.d.ts.map +1 -0
- package/dist/transport-host.js +110 -0
- package/dist/transport-host.js.map +1 -0
- package/dist/turn-metrics.d.ts +79 -0
- package/dist/turn-metrics.d.ts.map +1 -0
- package/dist/turn-metrics.js +208 -0
- package/dist/turn-metrics.js.map +1 -0
- package/dist/twilio-auth.d.ts +12 -0
- package/dist/twilio-auth.d.ts.map +1 -0
- package/dist/twilio-auth.js +44 -0
- package/dist/twilio-auth.js.map +1 -0
- package/dist/twilio.d.ts +56 -0
- package/dist/twilio.d.ts.map +1 -0
- package/dist/twilio.js +511 -0
- package/dist/twilio.js.map +1 -0
- package/dist/websocket-close.d.ts +12 -0
- package/dist/websocket-close.d.ts.map +1 -0
- package/dist/websocket-close.js +58 -0
- package/dist/websocket-close.js.map +1 -0
- package/dist/websocket-lifecycle.d.ts +29 -0
- package/dist/websocket-lifecycle.d.ts.map +1 -0
- package/dist/websocket-lifecycle.js +87 -0
- package/dist/websocket-lifecycle.js.map +1 -0
- package/dist/websocket-upgrade.d.ts +9 -0
- package/dist/websocket-upgrade.d.ts.map +1 -0
- package/dist/websocket-upgrade.js +91 -0
- package/dist/websocket-upgrade.js.map +1 -0
- package/dist/wire-carrier-control.d.ts +27 -0
- package/dist/wire-carrier-control.d.ts.map +1 -0
- package/dist/wire-carrier-control.js +116 -0
- package/dist/wire-carrier-control.js.map +1 -0
- package/package.json +32 -11
- package/src/admission-control.test.ts +270 -0
- package/src/background-audio.test.ts +224 -0
- package/src/browser-opus.test.ts +41 -0
- package/src/browser-pacing.test.ts +440 -0
- package/src/carrier-commands.test.ts +198 -0
- package/src/edge-telnyx.test.ts +333 -0
- package/src/edge-twilio.test.ts +293 -0
- package/src/edge.test.ts +727 -0
- package/src/graceful-drain.test.ts +306 -0
- package/src/inbound-audio.test.ts +58 -0
- package/src/index.test.ts +2078 -0
- package/src/outbound-playout-pipeline.test.ts +314 -0
- package/src/paced-playout.test.ts +247 -0
- package/src/playout-progress.test.ts +56 -0
- package/src/session-store.test.ts +274 -0
- package/src/smartpbx.test.ts +986 -0
- package/src/telnyx.test.ts +1633 -0
- package/src/transport-host.test.ts +51 -0
- package/src/turn-metrics.test.ts +503 -0
- package/src/twilio-auth.test.ts +36 -0
- package/src/twilio.test.ts +1274 -0
- package/src/websocket-close.test.ts +63 -0
- package/src/websocket-lifecycle.test.ts +49 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
//
|
|
3
|
+
// Twilio Media Streams ingress for the Workers edge: bridges Twilio's WebSocket
|
|
4
|
+
// protocol (base64 μ-law 8 kHz both ways) to a VoiceAgentSession, mirroring the
|
|
5
|
+
// session-lease/heartbeat pattern of edge.ts. Provider-agnostic — the bridge only
|
|
6
|
+
// speaks core packets (user.audio_received / tts.audio / interrupt.detected).
|
|
7
|
+
//
|
|
8
|
+
// Barge-in: interrupt.detected → Twilio `clear` event, which drops Twilio's
|
|
9
|
+
// buffered playout instantly (their barge-in mechanism). Playout-clock caveat:
|
|
10
|
+
// like the browser edge path, turn-taking uses the estimate fallback (no paced
|
|
11
|
+
// transport progress events on the edge yet).
|
|
12
|
+
import { Route, TimerScheduler, } from "@kuralle-syrinx/core";
|
|
13
|
+
import { decodeMuLawToPcm16, encodePcm16ToMuLaw, pcm16BytesToSamples, pcm16SamplesToBytes, resamplePcm16Streaming, } from "@kuralle-syrinx/core/audio";
|
|
14
|
+
import { BackgroundAudioMixer, wireBackgroundAudio, } from "./background-audio.js";
|
|
15
|
+
import { createWorkersInboundSocket, } from "@kuralle-syrinx/ws/workers";
|
|
16
|
+
const TWILIO_SAMPLE_RATE_HZ = 8_000;
|
|
17
|
+
const DEFAULT_RESUME_WINDOW_MS = 15_000;
|
|
18
|
+
const DEFAULT_KEEP_ALIVE_INTERVAL_MS = 15_000;
|
|
19
|
+
const DEFAULT_IDLE_TIMEOUT_MS = 60_000;
|
|
20
|
+
const DEFAULT_STARTUP_TIMEOUT_MS = 15_000;
|
|
21
|
+
const KEEP_ALIVE_KEY = "voice.edge.twilio.keep_alive";
|
|
22
|
+
export function createTwilioEdgeWebSocketUpgrade(request, options, ctx) {
|
|
23
|
+
const inbound = createWorkersInboundSocket(ctx);
|
|
24
|
+
void runTwilioEdgeWebSocketConnection(inbound.socket, request, options);
|
|
25
|
+
return { response: inbound.response, controller: inbound.controller };
|
|
26
|
+
}
|
|
27
|
+
export async function runTwilioEdgeWebSocketConnection(socket, request, options) {
|
|
28
|
+
const scheduler = options.scheduler ?? new TimerScheduler();
|
|
29
|
+
const engineRate = options.engineSampleRateHz ?? 16_000;
|
|
30
|
+
const resumeWindowMs = options.resumeWindowMs ?? DEFAULT_RESUME_WINDOW_MS;
|
|
31
|
+
const keepAliveIntervalMs = options.keepAliveIntervalMs ?? DEFAULT_KEEP_ALIVE_INTERVAL_MS;
|
|
32
|
+
const idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
33
|
+
const startupTimeoutMs = options.startupTimeoutMs ?? DEFAULT_STARTUP_TIMEOUT_MS;
|
|
34
|
+
const uplinkResamplers = new Map();
|
|
35
|
+
const downlinkResamplers = new Map();
|
|
36
|
+
const disposers = [];
|
|
37
|
+
let session = null;
|
|
38
|
+
let managed = null;
|
|
39
|
+
let pendingLease = null;
|
|
40
|
+
let sessionId = "";
|
|
41
|
+
let streamSid = "";
|
|
42
|
+
let contextId = "";
|
|
43
|
+
let contextBase = "";
|
|
44
|
+
let turnCounter = 0;
|
|
45
|
+
let closed = false;
|
|
46
|
+
let stopped = false;
|
|
47
|
+
let lastClientMessageMs = Date.now();
|
|
48
|
+
const sendTwilioJson = (value) => {
|
|
49
|
+
if (!socket.isOpen)
|
|
50
|
+
return;
|
|
51
|
+
socket.send(JSON.stringify(value));
|
|
52
|
+
};
|
|
53
|
+
const cleanup = () => {
|
|
54
|
+
if (closed)
|
|
55
|
+
return;
|
|
56
|
+
closed = true;
|
|
57
|
+
scheduler.cancel(KEEP_ALIVE_KEY);
|
|
58
|
+
scheduler.cancel("voice.edge.twilio.startup");
|
|
59
|
+
for (const dispose of disposers.splice(0))
|
|
60
|
+
dispose();
|
|
61
|
+
if (managed && sessionId) {
|
|
62
|
+
// Decrement the connection count BEFORE releasing (R1) — otherwise release
|
|
63
|
+
// early-returns while connectionCount > 0 and session.close() never runs, so
|
|
64
|
+
// Deepgram/TTS provider sockets + the reasoner leak until DO eviction. A
|
|
65
|
+
// caller-hangup (`stopped`) releases immediately (retain 0); a transient drop
|
|
66
|
+
// keeps the session warm for the resume window.
|
|
67
|
+
managed.connectionCount = Math.max(0, managed.connectionCount - 1);
|
|
68
|
+
void options.sessionStore.release(sessionId, stopped ? 0 : resumeWindowMs);
|
|
69
|
+
}
|
|
70
|
+
else if (pendingLease && sessionId) {
|
|
71
|
+
// Closed before the lease was adopted (e.g. startup-timeout race): tear the
|
|
72
|
+
// in-flight session down when it resolves so it is never orphaned in the store.
|
|
73
|
+
const id = sessionId;
|
|
74
|
+
void pendingLease
|
|
75
|
+
.then((leased) => {
|
|
76
|
+
leased.managed.connectionCount = Math.max(0, leased.managed.connectionCount - 1);
|
|
77
|
+
return options.sessionStore.release(id, 0);
|
|
78
|
+
})
|
|
79
|
+
.catch(() => undefined);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
socket.onClose(() => {
|
|
83
|
+
cleanup();
|
|
84
|
+
});
|
|
85
|
+
socket.onError(() => {
|
|
86
|
+
cleanup();
|
|
87
|
+
});
|
|
88
|
+
// Twilio sends connected/start (and media) immediately after the upgrade —
|
|
89
|
+
// before the session lease (provider sockets, kuralle init) resolves. Buffer
|
|
90
|
+
// until the handler is live or the start event is lost and the whole call
|
|
91
|
+
// streams into the void.
|
|
92
|
+
const pendingMessages = [];
|
|
93
|
+
let pendingBytes = 0;
|
|
94
|
+
let liveHandler = null;
|
|
95
|
+
socket.onMessage((data, isBinary) => {
|
|
96
|
+
lastClientMessageMs = Date.now();
|
|
97
|
+
if (liveHandler) {
|
|
98
|
+
liveHandler(data, isBinary);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const byteLength = typeof data === "string" ? data.length : data.byteLength;
|
|
102
|
+
if (pendingBytes + byteLength > 2 * 1024 * 1024)
|
|
103
|
+
return; // cap startup buffering
|
|
104
|
+
pendingBytes += byteLength;
|
|
105
|
+
pendingMessages.push({ data, isBinary });
|
|
106
|
+
});
|
|
107
|
+
try {
|
|
108
|
+
const url = new URL(request.url);
|
|
109
|
+
sessionId = url.searchParams.get("sessionId")?.trim() || crypto.randomUUID();
|
|
110
|
+
const startupTimer = new Promise((_, reject) => {
|
|
111
|
+
scheduler.schedule("voice.edge.twilio.startup", startupTimeoutMs, () => {
|
|
112
|
+
reject(new Error("twilio session startup timeout"));
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
pendingLease = options.sessionStore.lease(sessionId, async () => {
|
|
116
|
+
const sess = await options.createSession(request);
|
|
117
|
+
await sess.start();
|
|
118
|
+
return {
|
|
119
|
+
id: sessionId,
|
|
120
|
+
session: sess,
|
|
121
|
+
currentContextId: "",
|
|
122
|
+
contextSampleRates: new Map(),
|
|
123
|
+
inputSequence: { lastSequence: null },
|
|
124
|
+
turnMetricsTurns: new Map(),
|
|
125
|
+
closeTimer: null,
|
|
126
|
+
connectionCount: 1,
|
|
127
|
+
};
|
|
128
|
+
});
|
|
129
|
+
const leased = await Promise.race([pendingLease, startupTimer]);
|
|
130
|
+
pendingLease = null;
|
|
131
|
+
scheduler.cancel("voice.edge.twilio.startup");
|
|
132
|
+
managed = leased.managed;
|
|
133
|
+
session = managed.session;
|
|
134
|
+
if (closed) {
|
|
135
|
+
// The socket closed while the session was starting up — tear the just-started
|
|
136
|
+
// session down instead of orphaning it (decrement so release actually closes it).
|
|
137
|
+
managed.connectionCount = Math.max(0, managed.connectionCount - 1);
|
|
138
|
+
await options.sessionStore.release(sessionId, 0);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
// Background bed: ducked under speech in the tts.audio handler below, and
|
|
142
|
+
// sent as idle comfort-noise frames between turns — a phone line carrying
|
|
143
|
+
// pure digital silence reads as "the call died". Twilio's `clear` on
|
|
144
|
+
// barge-in drops any queued bed audio; the ticker refills on the next tick.
|
|
145
|
+
const backgroundAudio = options.backgroundAudio
|
|
146
|
+
? new BackgroundAudioMixer(options.backgroundAudio)
|
|
147
|
+
: null;
|
|
148
|
+
if (backgroundAudio) {
|
|
149
|
+
wireBackgroundAudio(session, backgroundAudio);
|
|
150
|
+
const idleFrameMs = options.backgroundIdleFrameMs ?? 200;
|
|
151
|
+
const idleTimer = setInterval(() => {
|
|
152
|
+
if (!streamSid || stopped || closed || !socket.isOpen)
|
|
153
|
+
return;
|
|
154
|
+
const frame = backgroundAudio.idleFrame(idleFrameMs, TWILIO_SAMPLE_RATE_HZ);
|
|
155
|
+
if (!frame)
|
|
156
|
+
return;
|
|
157
|
+
const mulaw = encodePcm16ToMuLaw(pcm16BytesToSamples(frame));
|
|
158
|
+
sendTwilioJson({ event: "media", streamSid, media: { payload: bytesToBase64(mulaw) } });
|
|
159
|
+
}, idleFrameMs);
|
|
160
|
+
disposers.push(() => clearInterval(idleTimer));
|
|
161
|
+
}
|
|
162
|
+
// Downlink: engine PCM → 8 kHz μ-law media frames; barge-in → clear.
|
|
163
|
+
disposers.push(session.bus.on("tts.audio", (pkt) => {
|
|
164
|
+
if (!streamSid)
|
|
165
|
+
return;
|
|
166
|
+
const audio = pkt;
|
|
167
|
+
const sourceRate = audio.sampleRateHz ?? engineRate;
|
|
168
|
+
const wireAudio = backgroundAudio ? backgroundAudio.mix(audio.audio, sourceRate) : audio.audio;
|
|
169
|
+
const samples = pcm16BytesToSamples(wireAudio);
|
|
170
|
+
const resampled = resamplePcm16Streaming(downlinkResamplers, samples, sourceRate, TWILIO_SAMPLE_RATE_HZ);
|
|
171
|
+
const mulaw = encodePcm16ToMuLaw(resampled);
|
|
172
|
+
sendTwilioJson({
|
|
173
|
+
event: "media",
|
|
174
|
+
streamSid,
|
|
175
|
+
media: { payload: bytesToBase64(mulaw) },
|
|
176
|
+
});
|
|
177
|
+
}), session.bus.on("interrupt.detected", () => {
|
|
178
|
+
if (!streamSid)
|
|
179
|
+
return;
|
|
180
|
+
sendTwilioJson({ event: "clear", streamSid });
|
|
181
|
+
}),
|
|
182
|
+
// The phone mic streams continuously on one call, but the engine finishes a
|
|
183
|
+
// turn per contextId — rotate on turn_complete exactly like the browser
|
|
184
|
+
// client does, or only the first utterance is ever heard (the STT plugin
|
|
185
|
+
// drops transcripts for already-finalized contexts).
|
|
186
|
+
session.bus.on("eos.turn_complete", () => {
|
|
187
|
+
if (!contextBase)
|
|
188
|
+
return;
|
|
189
|
+
turnCounter += 1;
|
|
190
|
+
contextId = `${contextBase}-t${String(turnCounter)}`;
|
|
191
|
+
}));
|
|
192
|
+
if (keepAliveIntervalMs > 0) {
|
|
193
|
+
const heartbeat = () => {
|
|
194
|
+
if (closed)
|
|
195
|
+
return;
|
|
196
|
+
if (idleTimeoutMs > 0 && Date.now() - lastClientMessageMs > idleTimeoutMs) {
|
|
197
|
+
socket.dispose();
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
scheduler.schedule(KEEP_ALIVE_KEY, keepAliveIntervalMs, heartbeat);
|
|
201
|
+
};
|
|
202
|
+
scheduler.schedule(KEEP_ALIVE_KEY, keepAliveIntervalMs, heartbeat);
|
|
203
|
+
}
|
|
204
|
+
const handleMessage = (data, isBinary) => {
|
|
205
|
+
if (isBinary || closed || !session)
|
|
206
|
+
return;
|
|
207
|
+
let message;
|
|
208
|
+
try {
|
|
209
|
+
message = JSON.parse(socketDataToText(data));
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
const event = message["event"];
|
|
215
|
+
if (event === "connected" || event === "mark" || event === "dtmf")
|
|
216
|
+
return;
|
|
217
|
+
if (event === "start") {
|
|
218
|
+
const start = (message["start"] ?? {});
|
|
219
|
+
streamSid =
|
|
220
|
+
(typeof start["streamSid"] === "string" && start["streamSid"]) ||
|
|
221
|
+
(typeof message["streamSid"] === "string" && message["streamSid"]) ||
|
|
222
|
+
"";
|
|
223
|
+
const callSid = typeof start["callSid"] === "string" ? start["callSid"] : "";
|
|
224
|
+
contextBase = callSid ? `twilio-${callSid}` : `twilio-${streamSid || sessionId}`;
|
|
225
|
+
contextId = contextBase;
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (event === "media") {
|
|
229
|
+
const media = (message["media"] ?? {});
|
|
230
|
+
const payload = typeof media["payload"] === "string" ? media["payload"] : "";
|
|
231
|
+
if (!payload || !contextId)
|
|
232
|
+
return;
|
|
233
|
+
const mulaw = base64ToBytes(payload);
|
|
234
|
+
const pcm8k = decodeMuLawToPcm16(mulaw);
|
|
235
|
+
const pcm16k = resamplePcm16Streaming(uplinkResamplers, pcm8k, TWILIO_SAMPLE_RATE_HZ, engineRate);
|
|
236
|
+
session.bus.push(Route.Main, {
|
|
237
|
+
kind: "user.audio_received",
|
|
238
|
+
contextId,
|
|
239
|
+
timestampMs: Date.now(),
|
|
240
|
+
audio: pcm16SamplesToBytes(pcm16k),
|
|
241
|
+
sampleRateHz: engineRate,
|
|
242
|
+
});
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (event === "stop") {
|
|
246
|
+
stopped = true;
|
|
247
|
+
socket.dispose();
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
liveHandler = handleMessage;
|
|
251
|
+
for (const queued of pendingMessages.splice(0)) {
|
|
252
|
+
handleMessage(queued.data, queued.isBinary);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
catch (err) {
|
|
256
|
+
sendTwilioJson({
|
|
257
|
+
event: "error",
|
|
258
|
+
message: err instanceof Error ? err.message : String(err),
|
|
259
|
+
});
|
|
260
|
+
socket.dispose();
|
|
261
|
+
cleanup();
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function socketDataToText(data) {
|
|
265
|
+
if (typeof data === "string")
|
|
266
|
+
return data;
|
|
267
|
+
if (data instanceof ArrayBuffer)
|
|
268
|
+
return new TextDecoder().decode(new Uint8Array(data));
|
|
269
|
+
return new TextDecoder().decode(data);
|
|
270
|
+
}
|
|
271
|
+
function base64ToBytes(value) {
|
|
272
|
+
const binary = atob(value);
|
|
273
|
+
const bytes = new Uint8Array(binary.length);
|
|
274
|
+
for (let i = 0; i < binary.length; i += 1)
|
|
275
|
+
bytes[i] = binary.charCodeAt(i);
|
|
276
|
+
return bytes;
|
|
277
|
+
}
|
|
278
|
+
function bytesToBase64(bytes) {
|
|
279
|
+
let binary = "";
|
|
280
|
+
const chunkSize = 0x8000;
|
|
281
|
+
for (let offset = 0; offset < bytes.length; offset += chunkSize) {
|
|
282
|
+
binary += String.fromCharCode(...bytes.subarray(offset, offset + chunkSize));
|
|
283
|
+
}
|
|
284
|
+
return btoa(binary);
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=edge-twilio.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edge-twilio.js","sourceRoot":"","sources":["../src/edge-twilio.ts"],"names":[],"mappings":"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"}
|
package/dist/edge.d.ts
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { type VoiceAgentSession } from "@kuralle-syrinx/core";
|
|
2
|
+
import { type Scheduler } from "@kuralle-syrinx/core";
|
|
3
|
+
import { type BackgroundAudioConfig } from "./background-audio.js";
|
|
4
|
+
export type { BackgroundAudioConfig, BackgroundAudioSource } from "./background-audio.js";
|
|
5
|
+
import { type WorkersDurableObjectWebSocketContext, type WorkersInboundSocketController } from "@kuralle-syrinx/ws/workers";
|
|
6
|
+
import type { ManagedSocket } from "@kuralle-syrinx/ws";
|
|
7
|
+
import { type SessionStore } from "./session-store.js";
|
|
8
|
+
/**
|
|
9
|
+
* Sink for per-conversation audio recording. The edge taps inbound caller audio
|
|
10
|
+
* and outbound TTS audio and hands raw PCM16 frames to this sink; the concrete
|
|
11
|
+
* implementation (e.g. an R2-backed recorder in the Workers host) decides where
|
|
12
|
+
* and how to persist. Kept runtime-agnostic here — no storage types leak into
|
|
13
|
+
* the transport layer.
|
|
14
|
+
*/
|
|
15
|
+
export interface EdgeRecorder {
|
|
16
|
+
onUserAudio(contextId: string, audio: Uint8Array, sampleRateHz: number): void;
|
|
17
|
+
onAssistantAudio(contextId: string, audio: Uint8Array, sampleRateHz: number): void;
|
|
18
|
+
finalize(meta: {
|
|
19
|
+
sessionId: string;
|
|
20
|
+
closedAtMs: number;
|
|
21
|
+
}): void | Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
export interface VoiceEdgeWebSocketOptions {
|
|
24
|
+
readonly createSession: (request: Request) => VoiceAgentSession | Promise<VoiceAgentSession>;
|
|
25
|
+
readonly recorder?: EdgeRecorder;
|
|
26
|
+
/** Explicit resolver for the session identity; when set, it takes precedence over the request query. */
|
|
27
|
+
readonly sessionId?: (request: Request) => string;
|
|
28
|
+
readonly contextId?: () => string;
|
|
29
|
+
readonly inputSampleRateHz?: number;
|
|
30
|
+
readonly outputSampleRateHz?: number;
|
|
31
|
+
readonly startupTimeoutMs?: number;
|
|
32
|
+
readonly maxSessionDurationMs?: number;
|
|
33
|
+
readonly maxInboundMessageBytes?: number;
|
|
34
|
+
readonly resumeWindowMs?: number;
|
|
35
|
+
/**
|
|
36
|
+
* Heartbeat cadence. While a connection is open the edge re-arms a scheduler
|
|
37
|
+
* task at this interval; on the Workers DO scheduler that alarm keeps the
|
|
38
|
+
* Durable Object from being evicted mid-call (the equivalent of Cloudflare
|
|
39
|
+
* agents' `keepAlive()` lease), and it is where idle/stale connections are
|
|
40
|
+
* detected. 0 disables the heartbeat.
|
|
41
|
+
*/
|
|
42
|
+
readonly keepAliveIntervalMs?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Close a connection that has sent no message within this window. Catches
|
|
45
|
+
* half-open clients (network dropped with no close frame) that the standard
|
|
46
|
+
* WebSocket cannot detect via a ping frame. 0 disables idle close.
|
|
47
|
+
*/
|
|
48
|
+
readonly idleTimeoutMs?: number;
|
|
49
|
+
/**
|
|
50
|
+
* Raw binary inbound PCM16 lacks turn, sample-rate, sequence, and duration
|
|
51
|
+
* metadata. Keep disabled for production clients; use JSON audio frames or
|
|
52
|
+
* the Syrinx binary envelope instead.
|
|
53
|
+
*/
|
|
54
|
+
readonly rawBinaryInput?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Ambient/thinking bed mixed (ducked) under assistant speech. Browser edge
|
|
57
|
+
* sends no idle bed between turns — a web client can loop ambience locally;
|
|
58
|
+
* the server-side bed exists for wires with no client runtime (telephony).
|
|
59
|
+
*/
|
|
60
|
+
readonly backgroundAudio?: BackgroundAudioConfig;
|
|
61
|
+
readonly sessionStore: SessionStore;
|
|
62
|
+
readonly scheduler?: Scheduler;
|
|
63
|
+
}
|
|
64
|
+
export interface VoiceEdgeWebSocketUpgrade {
|
|
65
|
+
readonly response: Response;
|
|
66
|
+
readonly controller?: WorkersInboundSocketController;
|
|
67
|
+
}
|
|
68
|
+
export declare function createVoiceEdgeWebSocketResponse(request: Request, options: VoiceEdgeWebSocketOptions, ctx?: WorkersDurableObjectWebSocketContext): Response;
|
|
69
|
+
export declare function createVoiceEdgeWebSocketUpgrade(request: Request, options: VoiceEdgeWebSocketOptions, ctx?: WorkersDurableObjectWebSocketContext): VoiceEdgeWebSocketUpgrade;
|
|
70
|
+
export declare function runVoiceEdgeWebSocketConnection(socket: ManagedSocket, request: Request, options: VoiceEdgeWebSocketOptions): Promise<void>;
|
|
71
|
+
//# sourceMappingURL=edge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edge.d.ts","sourceRoot":"","sources":["../src/edge.ts"],"names":[],"mappings":"AAEA,OAAO,EASL,KAAK,iBAAiB,EAEvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtE,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC1F,OAAO,EAEL,KAAK,oCAAoC,EACzC,KAAK,8BAA8B,EACpC,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,aAAa,EAAc,MAAM,oBAAoB,CAAC;AACpE,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAS5B;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9E,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACnF,QAAQ,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACjF;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,aAAa,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAC7F,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC;IACjC,wGAAwG;IACxG,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAC;IAClD,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,MAAM,CAAC;IAClC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IACzC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;;;;;;OAMG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC;;;;OAIG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC;;;;OAIG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC;;;;OAIG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACjD,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC;CAChC;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,8BAA8B,CAAC;CACtD;AAwBD,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,yBAAyB,EAClC,GAAG,CAAC,EAAE,oCAAoC,GACzC,QAAQ,CAEV;AAED,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,yBAAyB,EAClC,GAAG,CAAC,EAAE,oCAAoC,GACzC,yBAAyB,CAI3B;AAED,wBAAsB,+BAA+B,CACnD,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,IAAI,CAAC,CAgOf"}
|