@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.
- 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,64 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
import { Route } from "@kuralle-syrinx/core";
|
|
3
|
+
const PROGRESS_THROTTLE_MS = 200;
|
|
4
|
+
/**
|
|
5
|
+
* Tracks realtime playout position per context for one connection and emits
|
|
6
|
+
* `tts.playout_progress` as paced audio reaches the wire. This makes the output
|
|
7
|
+
* transport the authoritative playout clock that the engine's turn-taking (and,
|
|
8
|
+
* later, recording) consume — instead of reconstructing timing from TTS
|
|
9
|
+
* generation arrival, which is provider-stream-rate dependent.
|
|
10
|
+
*
|
|
11
|
+
* - `onFramePlayed` is wired to the PacedPlayoutQueue and called per frame; it
|
|
12
|
+
* accumulates and emits throttled progress.
|
|
13
|
+
* - `complete` is called from the transport's end-of-context drain (the control
|
|
14
|
+
* frame that runs after all audio has been paced out) and is authoritative.
|
|
15
|
+
* - `discard` drops a context on interrupt/clear without emitting completion.
|
|
16
|
+
*/
|
|
17
|
+
export class PlayoutProgressEmitter {
|
|
18
|
+
bus;
|
|
19
|
+
playedOutMs = new Map();
|
|
20
|
+
lastEmittedMs = new Map();
|
|
21
|
+
playoutStarted = new Set();
|
|
22
|
+
constructor(bus) {
|
|
23
|
+
this.bus = bus;
|
|
24
|
+
}
|
|
25
|
+
onFramePlayed = (contextId, durationMs) => {
|
|
26
|
+
if (contextId === undefined || durationMs <= 0)
|
|
27
|
+
return;
|
|
28
|
+
if (!this.playoutStarted.has(contextId)) {
|
|
29
|
+
this.playoutStarted.add(contextId);
|
|
30
|
+
this.bus.push(Route.Main, {
|
|
31
|
+
kind: "tts.playout_started",
|
|
32
|
+
contextId,
|
|
33
|
+
timestampMs: Date.now(),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
const total = (this.playedOutMs.get(contextId) ?? 0) + durationMs;
|
|
37
|
+
this.playedOutMs.set(contextId, total);
|
|
38
|
+
const lastEmitted = this.lastEmittedMs.get(contextId) ?? 0;
|
|
39
|
+
if (total - lastEmitted >= PROGRESS_THROTTLE_MS) {
|
|
40
|
+
this.lastEmittedMs.set(contextId, total);
|
|
41
|
+
this.emit(contextId, total, false);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
complete(contextId) {
|
|
45
|
+
const total = this.playedOutMs.get(contextId) ?? 0;
|
|
46
|
+
this.discard(contextId);
|
|
47
|
+
this.emit(contextId, total, true);
|
|
48
|
+
}
|
|
49
|
+
discard(contextId) {
|
|
50
|
+
this.playedOutMs.delete(contextId);
|
|
51
|
+
this.lastEmittedMs.delete(contextId);
|
|
52
|
+
this.playoutStarted.delete(contextId);
|
|
53
|
+
}
|
|
54
|
+
emit(contextId, playedOutMs, complete) {
|
|
55
|
+
this.bus.push(Route.Main, {
|
|
56
|
+
kind: "tts.playout_progress",
|
|
57
|
+
contextId,
|
|
58
|
+
timestampMs: Date.now(),
|
|
59
|
+
playedOutMs,
|
|
60
|
+
complete,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=playout-progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playout-progress.js","sourceRoot":"","sources":["../src/playout-progress.ts"],"names":[],"mappings":"AAAA,+BAA+B;AAE/B,OAAO,EAAE,KAAK,EAAoB,MAAM,sBAAsB,CAAC;AAE/D,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAEjC;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,sBAAsB;IAKJ;IAJZ,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;IACxC,aAAa,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC1C,cAAc,GAAG,IAAI,GAAG,EAAU,CAAC;IAEpD,YAA6B,GAAgB;QAAhB,QAAG,GAAH,GAAG,CAAa;IAAG,CAAC;IAEjD,aAAa,GAAG,CAAC,SAA6B,EAAE,UAAkB,EAAQ,EAAE;QAC1E,IAAI,SAAS,KAAK,SAAS,IAAI,UAAU,IAAI,CAAC;YAAE,OAAO;QACvD,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YACnC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;gBACxB,IAAI,EAAE,qBAAqB;gBAC3B,SAAS;gBACT,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;aACxB,CAAC,CAAC;QACL,CAAC;QACD,MAAM,KAAK,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,UAAU,CAAC;QAClE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACvC,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC3D,IAAI,KAAK,GAAG,WAAW,IAAI,oBAAoB,EAAE,CAAC;YAChD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YACzC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QACrC,CAAC;IACH,CAAC,CAAC;IAEF,QAAQ,CAAC,SAAiB;QACxB,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,CAAC,SAAiB;QACvB,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACnC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACrC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACxC,CAAC;IAEO,IAAI,CAAC,SAAiB,EAAE,WAAmB,EAAE,QAAiB;QACpE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;YACxB,IAAI,EAAE,sBAAsB;YAC5B,SAAS;YACT,WAAW,EAAE,IAAI,CAAC,GAAG,EAAE;YACvB,WAAW;YACX,QAAQ;SACT,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { VoiceAgentSession } from "@kuralle-syrinx/core";
|
|
2
|
+
import type { TurnTimestampState } from "./turn-metrics.js";
|
|
3
|
+
export interface AudioSequenceState {
|
|
4
|
+
lastSequence: number | null;
|
|
5
|
+
}
|
|
6
|
+
export interface ManagedSession {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly session: VoiceAgentSession;
|
|
9
|
+
currentContextId: string;
|
|
10
|
+
readonly contextSampleRates: Map<string, number>;
|
|
11
|
+
readonly inputSequence: AudioSequenceState;
|
|
12
|
+
readonly turnMetricsTurns: Map<string, TurnTimestampState>;
|
|
13
|
+
closeTimer: ReturnType<typeof setTimeout> | null;
|
|
14
|
+
connectionCount: number;
|
|
15
|
+
}
|
|
16
|
+
export interface ManagedSessionLease {
|
|
17
|
+
readonly managed: ManagedSession;
|
|
18
|
+
readonly resumed: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface SessionStore {
|
|
21
|
+
lease(sessionId: string, create: () => Promise<ManagedSession>): Promise<ManagedSessionLease>;
|
|
22
|
+
release(sessionId: string, retainMs: number): Promise<void>;
|
|
23
|
+
update(sessionId: string, mutate: (managed: ManagedSession) => void): void;
|
|
24
|
+
get(sessionId: string): Promise<ManagedSession | null>;
|
|
25
|
+
listAll(): Promise<readonly ManagedSession[]>;
|
|
26
|
+
clear(): Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
export declare class InMemorySessionStore implements SessionStore {
|
|
29
|
+
private readonly sessions;
|
|
30
|
+
private readonly pendingLeases;
|
|
31
|
+
lease(sessionId: string, create: () => Promise<ManagedSession>): Promise<ManagedSessionLease>;
|
|
32
|
+
release(sessionId: string, retainMs: number): Promise<void>;
|
|
33
|
+
update(sessionId: string, mutate: (managed: ManagedSession) => void): void;
|
|
34
|
+
get(sessionId: string): Promise<ManagedSession | null>;
|
|
35
|
+
listAll(): Promise<readonly ManagedSession[]>;
|
|
36
|
+
clear(): Promise<void>;
|
|
37
|
+
private attachConnection;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=session-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-store.d.ts","sourceRoot":"","sources":["../src/session-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAE5D,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IACpC,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,QAAQ,CAAC,aAAa,EAAE,kBAAkB,CAAC;IAC3C,QAAQ,CAAC,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC3D,UAAU,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,GAAG,IAAI,CAAC;IACjD,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAC9F,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI,CAAC;IAC3E,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;IACvD,OAAO,IAAI,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAAC;IAC9C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAOD,qBAAa,oBAAqB,YAAW,YAAY;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAC9D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmC;IAE3D,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,mBAAmB,CAAC;IA6B7F,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBjE,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI;IAMpE,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAItD,OAAO,IAAI,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC;IAI7C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,OAAO,CAAC,gBAAgB;CAQzB"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
export class InMemorySessionStore {
|
|
3
|
+
sessions = new Map();
|
|
4
|
+
pendingLeases = new Map();
|
|
5
|
+
async lease(sessionId, create) {
|
|
6
|
+
const existing = this.sessions.get(sessionId);
|
|
7
|
+
if (existing) {
|
|
8
|
+
return this.attachConnection(existing, true);
|
|
9
|
+
}
|
|
10
|
+
let pending = this.pendingLeases.get(sessionId);
|
|
11
|
+
if (!pending) {
|
|
12
|
+
const promise = create()
|
|
13
|
+
.then((managed) => {
|
|
14
|
+
this.sessions.set(sessionId, managed);
|
|
15
|
+
return managed;
|
|
16
|
+
})
|
|
17
|
+
.finally(() => {
|
|
18
|
+
this.pendingLeases.delete(sessionId);
|
|
19
|
+
});
|
|
20
|
+
pending = { promise, waiters: 0 };
|
|
21
|
+
this.pendingLeases.set(sessionId, pending);
|
|
22
|
+
}
|
|
23
|
+
const waiterIndex = pending.waiters;
|
|
24
|
+
pending.waiters += 1;
|
|
25
|
+
const managed = await pending.promise;
|
|
26
|
+
if (waiterIndex === 0) {
|
|
27
|
+
return { managed, resumed: false };
|
|
28
|
+
}
|
|
29
|
+
return this.attachConnection(managed, true);
|
|
30
|
+
}
|
|
31
|
+
async release(sessionId, retainMs) {
|
|
32
|
+
const managed = this.sessions.get(sessionId);
|
|
33
|
+
if (!managed)
|
|
34
|
+
return;
|
|
35
|
+
if (retainMs <= 0) {
|
|
36
|
+
if (managed.closeTimer) {
|
|
37
|
+
clearTimeout(managed.closeTimer);
|
|
38
|
+
managed.closeTimer = null;
|
|
39
|
+
}
|
|
40
|
+
if (managed.connectionCount > 0)
|
|
41
|
+
return;
|
|
42
|
+
this.sessions.delete(sessionId);
|
|
43
|
+
await managed.session.close().catch(() => undefined);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (managed.connectionCount > 0 || managed.closeTimer)
|
|
47
|
+
return;
|
|
48
|
+
managed.closeTimer = setTimeout(() => {
|
|
49
|
+
managed.closeTimer = null;
|
|
50
|
+
if (managed.connectionCount > 0)
|
|
51
|
+
return;
|
|
52
|
+
this.sessions.delete(sessionId);
|
|
53
|
+
void managed.session.close().catch(() => undefined);
|
|
54
|
+
}, retainMs);
|
|
55
|
+
}
|
|
56
|
+
update(sessionId, mutate) {
|
|
57
|
+
const managed = this.sessions.get(sessionId);
|
|
58
|
+
if (!managed)
|
|
59
|
+
return;
|
|
60
|
+
mutate(managed);
|
|
61
|
+
}
|
|
62
|
+
async get(sessionId) {
|
|
63
|
+
return this.sessions.get(sessionId) ?? null;
|
|
64
|
+
}
|
|
65
|
+
async listAll() {
|
|
66
|
+
return [...this.sessions.values()];
|
|
67
|
+
}
|
|
68
|
+
async clear() {
|
|
69
|
+
this.sessions.clear();
|
|
70
|
+
}
|
|
71
|
+
attachConnection(managed, resumed) {
|
|
72
|
+
if (managed.closeTimer) {
|
|
73
|
+
clearTimeout(managed.closeTimer);
|
|
74
|
+
managed.closeTimer = null;
|
|
75
|
+
}
|
|
76
|
+
managed.connectionCount += 1;
|
|
77
|
+
return { managed, resumed };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=session-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-store.js","sourceRoot":"","sources":["../src/session-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { IncomingMessage } from "node:http";
|
|
2
|
+
import { type Server as HttpServer } from "node:http";
|
|
3
|
+
import { WebSocketServer } from "ws";
|
|
4
|
+
import { type VoiceAgentSession } from "@kuralle-syrinx/core";
|
|
5
|
+
import { type GracefulCloseOptions } from "./transport-host.js";
|
|
6
|
+
import { type BackgroundAudioConfig } from "./background-audio.js";
|
|
7
|
+
export interface SmartPbxMediaStreamServerOptions {
|
|
8
|
+
readonly server?: HttpServer;
|
|
9
|
+
readonly port?: number;
|
|
10
|
+
readonly host?: string;
|
|
11
|
+
readonly path?: string;
|
|
12
|
+
readonly createSession: (request: IncomingMessage) => VoiceAgentSession | Promise<VoiceAgentSession>;
|
|
13
|
+
readonly contextId?: (start: SmartPbxStartPayload) => string;
|
|
14
|
+
readonly inputSampleRateHz?: number;
|
|
15
|
+
readonly outputSampleRateHz?: number;
|
|
16
|
+
readonly outboundFrameDurationMs?: number;
|
|
17
|
+
readonly maxQueuedOutputAudioMs?: number;
|
|
18
|
+
/** Ambient/thinking bed mixed (ducked) under assistant speech (see BackgroundAudioConfig). */
|
|
19
|
+
readonly backgroundAudio?: BackgroundAudioConfig;
|
|
20
|
+
readonly heartbeatIntervalMs?: number;
|
|
21
|
+
readonly startupTimeoutMs?: number;
|
|
22
|
+
readonly maxSessionDurationMs?: number;
|
|
23
|
+
readonly maxBufferedAmountBytes?: number;
|
|
24
|
+
readonly maxInboundMessageBytes?: number;
|
|
25
|
+
readonly maxConcurrentSessions?: number;
|
|
26
|
+
readonly maxConcurrentSessionsScope?: "path" | "server";
|
|
27
|
+
readonly onTransportMetric?: (name: string) => void;
|
|
28
|
+
}
|
|
29
|
+
export interface SmartPbxMediaStreamServer {
|
|
30
|
+
readonly httpServer: HttpServer;
|
|
31
|
+
readonly wsServer: WebSocketServer;
|
|
32
|
+
address(): ReturnType<HttpServer["address"]>;
|
|
33
|
+
close(opts?: GracefulCloseOptions): Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
export interface SmartPbxStartPayload {
|
|
36
|
+
readonly callId?: string;
|
|
37
|
+
readonly otherLegCallId?: string;
|
|
38
|
+
readonly callerIdNumber?: string;
|
|
39
|
+
readonly calleeIdNumber?: string;
|
|
40
|
+
readonly accountId?: string;
|
|
41
|
+
readonly mediaFormat?: {
|
|
42
|
+
readonly encoding?: string;
|
|
43
|
+
readonly sampleRate?: number | string;
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
export declare function createSmartPbxMediaStreamServer(options: SmartPbxMediaStreamServerOptions): Promise<SmartPbxMediaStreamServer>;
|
|
47
|
+
//# sourceMappingURL=smartpbx.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"smartpbx.d.ts","sourceRoot":"","sources":["../src/smartpbx.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAgB,KAAK,MAAM,IAAI,UAAU,EAAE,MAAM,WAAW,CAAC;AACpE,OAAO,EAAa,eAAe,EAAgB,MAAM,IAAI,CAAC;AAE9D,OAAO,EAAS,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAkBrE,OAAO,EAA0B,KAAK,oBAAoB,EAAwF,MAAM,qBAAqB,CAAC;AAC9K,OAAO,EAAwB,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAUzF,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,aAAa,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACrG,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,MAAM,CAAC;IAC7D,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IAC1C,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;IACzC,8FAA8F;IAC9F,QAAQ,CAAC,eAAe,CAAC,EAAE,qBAAqB,CAAC;IACjD,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC,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,sBAAsB,CAAC,EAAE,MAAM,CAAC;IACzC,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,0BAA0B,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IACxD,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACrD;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,OAAO,IAAI,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;IAC7C,KAAK,CAAC,IAAI,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,CAAC,EAAE;QACrB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;KACvC,CAAC;CACH;AA0CD,wBAAsB,+BAA+B,CACnD,OAAO,EAAE,gCAAgC,GACxC,OAAO,CAAC,yBAAyB,CAAC,CA6RpC"}
|