@absolutejs/voice 0.0.22-beta.658 → 0.0.22-beta.659
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/index.js +75 -23
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -39836,6 +39836,10 @@ var createVoiceMonitorRunnerRoutes = (options) => {
|
|
|
39836
39836
|
|
|
39837
39837
|
// src/core/plugin.ts
|
|
39838
39838
|
var socketIdentity = (ws) => ws.raw && typeof ws.raw === "object" ? ws.raw : ws;
|
|
39839
|
+
var socketIsOpen = (ws) => {
|
|
39840
|
+
const identity = socketIdentity(ws);
|
|
39841
|
+
return identity.readyState === undefined || identity.readyState === 1;
|
|
39842
|
+
};
|
|
39839
39843
|
var resolveQueryScenario = (query) => {
|
|
39840
39844
|
if (typeof query?.scenarioId === "string" && query.scenarioId.trim()) {
|
|
39841
39845
|
return query.scenarioId.trim();
|
|
@@ -40160,6 +40164,7 @@ var voice = (config) => {
|
|
|
40160
40164
|
socketSessions: new WeakMap
|
|
40161
40165
|
};
|
|
40162
40166
|
const authorizedSockets = new WeakSet;
|
|
40167
|
+
const closedSockets = new WeakSet;
|
|
40163
40168
|
const pendingSocketAuthorizations = new WeakMap;
|
|
40164
40169
|
const authorizeSocket = (ws, sessionId, scenarioId) => {
|
|
40165
40170
|
const identity = socketIdentity(ws);
|
|
@@ -40167,6 +40172,8 @@ var voice = (config) => {
|
|
|
40167
40172
|
if (existing)
|
|
40168
40173
|
return existing;
|
|
40169
40174
|
const authorization = (async () => {
|
|
40175
|
+
if (closedSockets.has(identity) || !socketIsOpen(ws))
|
|
40176
|
+
return false;
|
|
40170
40177
|
if (!config.authorizeConnection) {
|
|
40171
40178
|
authorizedSockets.add(identity);
|
|
40172
40179
|
return true;
|
|
@@ -40184,6 +40191,8 @@ var voice = (config) => {
|
|
|
40184
40191
|
} catch (error) {
|
|
40185
40192
|
runtime.logger.warn?.(`[voice] connection authorization failed for session "${sessionId}": ${error instanceof Error ? error.message : String(error)}`);
|
|
40186
40193
|
}
|
|
40194
|
+
if (closedSockets.has(identity) || !socketIsOpen(ws))
|
|
40195
|
+
return false;
|
|
40187
40196
|
if (!authorized) {
|
|
40188
40197
|
ws.close(4401, "unauthorized");
|
|
40189
40198
|
return false;
|
|
@@ -40196,12 +40205,14 @@ var voice = (config) => {
|
|
|
40196
40205
|
};
|
|
40197
40206
|
const waitForSocketAuthorization = async (ws) => {
|
|
40198
40207
|
const identity = socketIdentity(ws);
|
|
40208
|
+
if (closedSockets.has(identity) || !socketIsOpen(ws))
|
|
40209
|
+
return false;
|
|
40199
40210
|
if (authorizedSockets.has(identity))
|
|
40200
40211
|
return true;
|
|
40201
40212
|
const pending = pendingSocketAuthorizations.get(identity);
|
|
40202
40213
|
if (!pending)
|
|
40203
40214
|
return false;
|
|
40204
|
-
return pending;
|
|
40215
|
+
return await pending && !closedSockets.has(identity) && socketIsOpen(ws);
|
|
40205
40216
|
};
|
|
40206
40217
|
const { monitor } = config;
|
|
40207
40218
|
const registerMonitorSession = (sessionId, handle) => {
|
|
@@ -40370,28 +40381,59 @@ var voice = (config) => {
|
|
|
40370
40381
|
});
|
|
40371
40382
|
};
|
|
40372
40383
|
const createAndConnectSession = async (ws, sessionId, scenarioId) => {
|
|
40384
|
+
const identity = socketIdentity(ws);
|
|
40373
40385
|
const session = await createManagedSession(ws, sessionId, scenarioId);
|
|
40374
40386
|
const typedSession = session;
|
|
40387
|
+
if (closedSockets.has(identity) || !socketIsOpen(ws) || runtime.activeSockets.get(sessionId) !== identity) {
|
|
40388
|
+
ws.close(1000, "superseded");
|
|
40389
|
+
throw new Error("Voice socket was superseded during session creation");
|
|
40390
|
+
}
|
|
40391
|
+
try {
|
|
40392
|
+
await session.connect(buildSocketAdapter(ws, sessionId));
|
|
40393
|
+
} catch (error) {
|
|
40394
|
+
runtime.logger.warn?.(`[voice] session initialization failed for "${sessionId}": ${error instanceof Error ? error.message : String(error)}`);
|
|
40395
|
+
closedSockets.add(identity);
|
|
40396
|
+
ws.close(1011, "voice session initialization failed");
|
|
40397
|
+
throw error;
|
|
40398
|
+
}
|
|
40399
|
+
if (closedSockets.has(identity) || !socketIsOpen(ws) || runtime.activeSockets.get(sessionId) !== identity) {
|
|
40400
|
+
await session.disconnect({
|
|
40401
|
+
code: 1000,
|
|
40402
|
+
reason: "superseded",
|
|
40403
|
+
recoverable: true,
|
|
40404
|
+
type: "close"
|
|
40405
|
+
});
|
|
40406
|
+
ws.close(1000, "superseded");
|
|
40407
|
+
throw new Error("Voice socket was superseded during session connection");
|
|
40408
|
+
}
|
|
40375
40409
|
runtime.activeSessions.set(sessionId, typedSession);
|
|
40376
40410
|
registerMonitorSession(sessionId, typedSession);
|
|
40377
|
-
await session.connect(buildSocketAdapter(ws, sessionId));
|
|
40378
40411
|
return typedSession;
|
|
40379
40412
|
};
|
|
40380
40413
|
const ensureManagedSession = async (ws, sessionId, scenarioId) => {
|
|
40414
|
+
const identity = socketIdentity(ws);
|
|
40415
|
+
if (closedSockets.has(identity) || !socketIsOpen(ws) || runtime.activeSockets.get(sessionId) !== identity) {
|
|
40416
|
+
throw new Error("Voice socket is no longer active");
|
|
40417
|
+
}
|
|
40381
40418
|
const active = runtime.activeSessions.get(sessionId);
|
|
40382
40419
|
if (active) {
|
|
40383
40420
|
return active;
|
|
40384
40421
|
}
|
|
40385
40422
|
const inFlight = runtime.pendingSessions.get(sessionId);
|
|
40386
|
-
if (inFlight) {
|
|
40387
|
-
return inFlight;
|
|
40423
|
+
if (inFlight?.identity === identity) {
|
|
40424
|
+
return inFlight.promise;
|
|
40388
40425
|
}
|
|
40389
40426
|
const creation = createAndConnectSession(ws, sessionId, scenarioId);
|
|
40390
|
-
runtime.pendingSessions.set(sessionId,
|
|
40427
|
+
runtime.pendingSessions.set(sessionId, {
|
|
40428
|
+
identity,
|
|
40429
|
+
promise: creation
|
|
40430
|
+
});
|
|
40391
40431
|
try {
|
|
40392
40432
|
return await creation;
|
|
40393
40433
|
} finally {
|
|
40394
|
-
runtime.pendingSessions.
|
|
40434
|
+
if (runtime.pendingSessions.get(sessionId)?.promise === creation) {
|
|
40435
|
+
runtime.pendingSessions.delete(sessionId);
|
|
40436
|
+
}
|
|
40395
40437
|
}
|
|
40396
40438
|
};
|
|
40397
40439
|
const mountSurface = (app, value, factory) => {
|
|
@@ -40512,6 +40554,7 @@ var voice = (config) => {
|
|
|
40512
40554
|
return new Elysia70({ name: "absolutejs-voice" }).ws(config.path, {
|
|
40513
40555
|
close: async (ws, code, reason) => {
|
|
40514
40556
|
const identity = socketIdentity(ws);
|
|
40557
|
+
closedSockets.add(identity);
|
|
40515
40558
|
const socketState = runtime.socketSessions.get(identity);
|
|
40516
40559
|
if (!socketState || runtime.activeSockets.get(socketState.sessionId) !== identity) {
|
|
40517
40560
|
return;
|
|
@@ -40639,24 +40682,33 @@ var voice = (config) => {
|
|
|
40639
40682
|
const session = current ?? await ensureManagedSession(ws, sessionState.sessionId, sessionState.scenarioId ?? undefined);
|
|
40640
40683
|
await session.receiveAudio(audio);
|
|
40641
40684
|
},
|
|
40642
|
-
open:
|
|
40685
|
+
open: (ws) => {
|
|
40643
40686
|
const sessionState = resolveSessionId3(runtime, ws);
|
|
40644
|
-
|
|
40645
|
-
|
|
40646
|
-
|
|
40647
|
-
|
|
40648
|
-
|
|
40649
|
-
|
|
40650
|
-
|
|
40651
|
-
|
|
40652
|
-
|
|
40653
|
-
|
|
40654
|
-
|
|
40655
|
-
|
|
40656
|
-
|
|
40657
|
-
|
|
40658
|
-
|
|
40659
|
-
|
|
40687
|
+
(async () => {
|
|
40688
|
+
if (!await authorizeSocket(ws, sessionState.sessionId, sessionState.scenarioId ?? undefined)) {
|
|
40689
|
+
return;
|
|
40690
|
+
}
|
|
40691
|
+
const identity = socketIdentity(ws);
|
|
40692
|
+
if (closedSockets.has(identity) || !socketIsOpen(ws))
|
|
40693
|
+
return;
|
|
40694
|
+
const existing = runtime.activeSessions.get(sessionState.sessionId);
|
|
40695
|
+
runtime.activeSockets.set(sessionState.sessionId, identity);
|
|
40696
|
+
if (existing) {
|
|
40697
|
+
await existing.disconnect({
|
|
40698
|
+
code: 1006,
|
|
40699
|
+
reason: "superseded",
|
|
40700
|
+
recoverable: true,
|
|
40701
|
+
type: "close"
|
|
40702
|
+
});
|
|
40703
|
+
runtime.activeSessions.delete(sessionState.sessionId);
|
|
40704
|
+
deregisterMonitorSession(sessionState.sessionId, "superseded");
|
|
40705
|
+
}
|
|
40706
|
+
await ensureManagedSession(ws, sessionState.sessionId, sessionState.scenarioId ?? undefined);
|
|
40707
|
+
})().catch((error) => {
|
|
40708
|
+
if (closedSockets.has(socketIdentity(ws)))
|
|
40709
|
+
return;
|
|
40710
|
+
runtime.logger.warn?.(`[voice] session initialization failed for "${sessionState.sessionId}": ${error instanceof Error ? error.message : String(error)}`);
|
|
40711
|
+
});
|
|
40660
40712
|
}
|
|
40661
40713
|
}).use(htmxRoutes()).use(surfaceRoutes());
|
|
40662
40714
|
};
|