@ariaflowagents/livekit-plugin-transport-sip-jssip 0.9.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/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # @ariaflow/livekit-plugin-transport-sip-jssip
2
+
3
+ SIP over WebSocket/WebRTC signaling utilities built on JsSIP.
4
+
5
+ Use this package for:
6
+ - Browser or WebRTC SIP endpoints
7
+ - SIP over WebSocket (WS/WSS)
8
+ - JsSIP session lifecycle handling
9
+
10
+ This package focuses on signaling/session lifecycle. RTP trunk media bridging is provided by:
11
+ - `@ariaflow/livekit-plugin-transport-sip`
@@ -0,0 +1,3 @@
1
+ export { JsSIPSignaling } from './jssip_signaling.js';
2
+ export type { JsSIPSignalingOptions, OnSessionCallback, OnByeCallback, } from './types.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EACV,qBAAqB,EACrB,iBAAiB,EACjB,aAAa,GACd,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { JsSIPSignaling } from './jssip_signaling.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { RTCSession } from 'jssip/lib/RTCSession.js';
2
+ import type { JsSIPSignalingOptions, OnByeCallback, OnSessionCallback } from './types.js';
3
+ /**
4
+ * SIP signaling/session lifecycle utility for SIP over WebSocket (JsSIP).
5
+ *
6
+ * This class handles SIP signaling and WebRTC session lifecycle only.
7
+ * Media playout/capture should be handled via the RTCSession APIs.
8
+ */
9
+ export declare class JsSIPSignaling {
10
+ private options;
11
+ private ua;
12
+ private activeSessions;
13
+ constructor(options: JsSIPSignalingOptions);
14
+ start(onSession: OnSessionCallback, onBye?: OnByeCallback): Promise<void>;
15
+ makeCall(targetUri: string, onSession?: OnSessionCallback, onBye?: OnByeCallback): Promise<string>;
16
+ hangup(callId: string): Promise<void>;
17
+ stop(): Promise<void>;
18
+ getSession(callId: string): RTCSession | undefined;
19
+ get isRegistered(): boolean;
20
+ get status(): 'disconnected' | 'connecting' | 'connected';
21
+ private attachSession;
22
+ private extractCallId;
23
+ }
24
+ //# sourceMappingURL=jssip_signaling.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jssip_signaling.d.ts","sourceRoot":"","sources":["../src/jssip_signaling.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,qBAAqB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE1F;;;;;GAKG;AACH,qBAAa,cAAc;IAIb,OAAO,CAAC,OAAO;IAH3B,OAAO,CAAC,EAAE,CAAmB;IAC7B,OAAO,CAAC,cAAc,CAAsC;gBAExC,OAAO,EAAE,qBAAqB;IAE5C,KAAK,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAsCzE,QAAQ,CACZ,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,iBAAiB,EAC7B,KAAK,CAAC,EAAE,aAAa,GACpB,OAAO,CAAC,MAAM,CAAC;IAeZ,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAarC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB3B,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAIlD,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED,IAAI,MAAM,IAAI,cAAc,GAAG,YAAY,GAAG,WAAW,CAMxD;IAED,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,aAAa;CAItB"}
@@ -0,0 +1,119 @@
1
+ import { UA, WebSocketInterface } from 'jssip';
2
+ /**
3
+ * SIP signaling/session lifecycle utility for SIP over WebSocket (JsSIP).
4
+ *
5
+ * This class handles SIP signaling and WebRTC session lifecycle only.
6
+ * Media playout/capture should be handled via the RTCSession APIs.
7
+ */
8
+ export class JsSIPSignaling {
9
+ options;
10
+ ua = null;
11
+ activeSessions = new Map();
12
+ constructor(options) {
13
+ this.options = options;
14
+ }
15
+ async start(onSession, onBye) {
16
+ const wsProtocol = this.options.secureWebSocket === false ? 'ws' : 'wss';
17
+ const wsUrl = `${wsProtocol}://${this.options.wsServerHost || this.options.localAddress}:${this.options.wsServerPort || 8080}/ws`;
18
+ const sipUri = `sip:${this.options.sipUsername || 'agent'}@${this.options.sipDomain || this.options.localAddress}`;
19
+ this.ua = new UA({
20
+ uri: sipUri,
21
+ sockets: [new WebSocketInterface(wsUrl)],
22
+ password: this.options.sipPassword,
23
+ register: this.options.shouldRegister !== false,
24
+ });
25
+ this.ua.on('newRTCSession', (data) => {
26
+ const session = data.session;
27
+ const callId = this.extractCallId(session);
28
+ this.attachSession(callId, session, onBye);
29
+ onSession(callId, session);
30
+ });
31
+ this.ua.on('connected', () => {
32
+ console.log(`[JsSIPSignaling] Connected to SIP server: ${wsUrl}`);
33
+ });
34
+ this.ua.on('disconnected', () => {
35
+ console.warn('[JsSIPSignaling] Disconnected from SIP server');
36
+ });
37
+ this.ua.on('registered', () => {
38
+ console.log(`[JsSIPSignaling] Registered as: ${sipUri}`);
39
+ });
40
+ this.ua.on('registrationFailed', (event) => {
41
+ console.error('[JsSIPSignaling] Registration failed:', event);
42
+ });
43
+ this.ua.start();
44
+ }
45
+ async makeCall(targetUri, onSession, onBye) {
46
+ if (!this.ua) {
47
+ throw new Error('[JsSIPSignaling] User agent not started');
48
+ }
49
+ const session = this.ua.call(targetUri, {
50
+ mediaConstraints: { audio: true, video: false },
51
+ });
52
+ const callId = this.extractCallId(session);
53
+ this.attachSession(callId, session, onBye);
54
+ onSession?.(callId, session);
55
+ return callId;
56
+ }
57
+ async hangup(callId) {
58
+ const session = this.activeSessions.get(callId);
59
+ if (!session) {
60
+ return;
61
+ }
62
+ try {
63
+ await session.terminate();
64
+ }
65
+ finally {
66
+ this.activeSessions.delete(callId);
67
+ }
68
+ }
69
+ async stop() {
70
+ if (!this.ua) {
71
+ return;
72
+ }
73
+ const hangupPromises = Array.from(this.activeSessions.values()).map(async (session) => {
74
+ try {
75
+ await session.terminate();
76
+ }
77
+ catch (error) {
78
+ console.error('[JsSIPSignaling] Error terminating session during shutdown:', error);
79
+ }
80
+ });
81
+ await Promise.allSettled(hangupPromises);
82
+ this.activeSessions.clear();
83
+ this.ua.stop();
84
+ this.ua = null;
85
+ }
86
+ getSession(callId) {
87
+ return this.activeSessions.get(callId);
88
+ }
89
+ get isRegistered() {
90
+ return this.ua?.isRegistered() ?? false;
91
+ }
92
+ get status() {
93
+ if (!this.ua)
94
+ return 'disconnected';
95
+ const uaStatus = this.ua.status;
96
+ if (uaStatus === 0)
97
+ return 'connecting';
98
+ if (uaStatus === 1 || uaStatus === 2)
99
+ return 'connected';
100
+ return 'disconnected';
101
+ }
102
+ attachSession(callId, session, onBye) {
103
+ this.activeSessions.set(callId, session);
104
+ session.on('ended', () => {
105
+ this.activeSessions.delete(callId);
106
+ onBye?.(callId);
107
+ });
108
+ session.on('failed', (error) => {
109
+ console.error(`[JsSIPSignaling] Session ${callId} failed:`, error);
110
+ this.activeSessions.delete(callId);
111
+ onBye?.(callId);
112
+ });
113
+ }
114
+ extractCallId(session) {
115
+ const req = session.request;
116
+ return req?.call_id || req?.callId || `call-${Date.now()}`;
117
+ }
118
+ }
119
+ //# sourceMappingURL=jssip_signaling.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jssip_signaling.js","sourceRoot":"","sources":["../src/jssip_signaling.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { RTCSession } from 'jssip/lib/RTCSession.js';
2
+ export interface JsSIPSignalingOptions {
3
+ localAddress: string;
4
+ wsServerHost?: string;
5
+ wsServerPort?: number;
6
+ secureWebSocket?: boolean;
7
+ sipUsername?: string;
8
+ sipPassword?: string;
9
+ sipDomain?: string;
10
+ shouldRegister?: boolean;
11
+ }
12
+ export type OnSessionCallback = (callId: string, session: RTCSession) => void;
13
+ export type OnByeCallback = (callId: string) => void;
14
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,MAAM,WAAW,qBAAqB;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;AAC9E,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@ariaflowagents/livekit-plugin-transport-sip-jssip",
3
+ "version": "0.9.0",
4
+ "description": "SIP over WebSocket/WebRTC signaling utilities using JsSIP for LiveKit transport integrations.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": ["dist"],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "clean": "rm -rf dist"
18
+ },
19
+ "dependencies": {
20
+ "jssip": "^3.13.5"
21
+ },
22
+ "devDependencies": {
23
+ "@types/node": "^22.10.0",
24
+ "typescript": "^5.5.0"
25
+ },
26
+ "license": "Apache-2.0"
27
+ }