@ajna-inc/webrtc 0.1.1 → 0.2.1

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 (38) hide show
  1. package/README.md +143 -17
  2. package/build/index.d.ts +6 -2
  3. package/build/index.js +5 -1
  4. package/build/index.js.map +1 -1
  5. package/build/webrtc/WebRTCApi.d.ts +90 -5
  6. package/build/webrtc/WebRTCApi.js +105 -2
  7. package/build/webrtc/WebRTCApi.js.map +1 -1
  8. package/build/webrtc/WebRTCEvents.d.ts +84 -5
  9. package/build/webrtc/WebRTCEvents.js +8 -0
  10. package/build/webrtc/WebRTCEvents.js.map +1 -1
  11. package/build/webrtc/WebRTCModule.d.ts +50 -0
  12. package/build/webrtc/WebRTCModule.js +17 -2
  13. package/build/webrtc/WebRTCModule.js.map +1 -1
  14. package/build/webrtc/handlers/RenegotiateHandler.d.ts +9 -0
  15. package/build/webrtc/handlers/RenegotiateHandler.js +31 -0
  16. package/build/webrtc/handlers/RenegotiateHandler.js.map +1 -0
  17. package/build/webrtc/handlers/index.d.ts +1 -0
  18. package/build/webrtc/handlers/index.js +1 -0
  19. package/build/webrtc/handlers/index.js.map +1 -1
  20. package/build/webrtc/messages/AnswerMessage.d.ts +8 -0
  21. package/build/webrtc/messages/AnswerMessage.js +10 -0
  22. package/build/webrtc/messages/AnswerMessage.js.map +1 -1
  23. package/build/webrtc/messages/OfferMessage.d.ts +28 -1
  24. package/build/webrtc/messages/OfferMessage.js +35 -1
  25. package/build/webrtc/messages/OfferMessage.js.map +1 -1
  26. package/build/webrtc/messages/ProposeMessage.d.ts +51 -0
  27. package/build/webrtc/messages/ProposeMessage.js +48 -2
  28. package/build/webrtc/messages/ProposeMessage.js.map +1 -1
  29. package/build/webrtc/messages/RenegotiateMessage.d.ts +52 -0
  30. package/build/webrtc/messages/RenegotiateMessage.js +65 -0
  31. package/build/webrtc/messages/RenegotiateMessage.js.map +1 -0
  32. package/build/webrtc/messages/index.d.ts +1 -0
  33. package/build/webrtc/messages/index.js +1 -0
  34. package/build/webrtc/messages/index.js.map +1 -1
  35. package/build/webrtc/services/WebRTCService.d.ts +64 -3
  36. package/build/webrtc/services/WebRTCService.js +115 -12
  37. package/build/webrtc/services/WebRTCService.js.map +1 -1
  38. package/package.json +1 -1
package/README.md CHANGED
@@ -1,38 +1,95 @@
1
- # @credo-ts/webrtc
1
+ # @ajna-inc/webrtc
2
2
 
3
- DIDComm v2 signaling protocol for WebRTC P2P calls.
3
+ DIDComm v2 signaling protocol for WebRTC P2P calls with full NAT/firewall traversal support.
4
4
 
5
5
  - PIURI: `https://didcomm.org/webrtc/1.0`
6
- - Messages: `propose`, `offer`, `answer`, `ice`, `end`
6
+ - Messages: `propose`, `offer`, `answer`, `ice`, `renegotiate`, `end`
7
7
  - Advertises support via Discover Features; works with mediators and message pickup.
8
8
 
9
+ ## Features
10
+
11
+ - **Module-level ICE server defaults** - Configure STUN/TURN servers once
12
+ - **ICE policy control** - `all`, `relay-preferred`, or `relay-only` for strict firewall environments
13
+ - **ICE restart support** - Recover from failed connections
14
+ - **Trickle ICE** - Efficient candidate exchange
15
+ - **Propose message** - Share ICE servers before SDP exchange
16
+
9
17
  ## Install
10
18
 
11
19
  This package is part of the monorepo. Add the module to your Agent options:
12
20
 
13
21
  ```ts
14
- import { WebRTCModule } from '@credo-ts/webrtc'
22
+ import { WebRTCModule } from '@ajna-inc/webrtc'
15
23
 
16
24
  const agent = new Agent({
17
25
  config: { /* ... */ },
18
26
  dependencies: agentDependencies,
19
27
  modules: {
20
- webrtc: new WebRTCModule(),
28
+ webrtc: new WebRTCModule({
29
+ // Configure default ICE servers (optional - has sensible defaults)
30
+ iceServers: [
31
+ { urls: 'stun:stun.l.google.com:19302' },
32
+ { urls: 'turn:turn.example.org:3478', username: 'user', credential: 'pass' },
33
+ ],
34
+ // Default ICE policy: 'all' | 'relay-preferred' | 'relay-only'
35
+ defaultPolicy: 'relay-preferred',
36
+ // Enable trickle ICE by default
37
+ defaultTrickle: true,
38
+ }),
39
+ },
40
+ })
41
+ ```
42
+
43
+ ## NAT/Firewall Traversal
44
+
45
+ For peers behind restrictive NAT or firewalls, use TURN servers:
46
+
47
+ ```ts
48
+ const agent = new Agent({
49
+ modules: {
50
+ webrtc: new WebRTCModule({
51
+ iceServers: [
52
+ // STUN for simple NAT
53
+ { urls: 'stun:stun.l.google.com:19302' },
54
+ // TURN for symmetric NAT and firewalls
55
+ { urls: 'turn:turn.yourserver.com:3478', username: 'user', credential: 'pass' },
56
+ // TURNS (TLS) for stricter firewalls
57
+ { urls: 'turns:turn.yourserver.com:5349', username: 'user', credential: 'pass' },
58
+ ],
59
+ // Force relay-only for maximum compatibility (hides IP addresses too)
60
+ defaultPolicy: 'relay-only',
61
+ }),
21
62
  },
22
63
  })
23
64
  ```
24
65
 
25
66
  ## Frontend usage (browser)
26
67
 
27
- Below is a minimal setup for P2P WebRTC using Credo TS for signaling.
68
+ Below is a setup for P2P WebRTC using Credo TS for signaling.
28
69
 
29
70
  ```ts
71
+ // Get configured ICE servers from module
72
+ const iceServers = agent.modules.webrtc.getDefaultIceServers()
73
+
30
74
  // Subscribe to inbound signaling
75
+ agent.events.on('WebRTCEvents.IncomingPropose', async ({ payload }) => {
76
+ const { thid, iceServers, policy, media } = payload
77
+ // Caller is proposing a call - you can accept by sending an offer
78
+ // The iceServers from propose can be used to configure RTCPeerConnection
79
+ console.log('Incoming call proposal:', { media, iceServers })
80
+ })
81
+
31
82
  agent.events.on('WebRTCEvents.IncomingOffer', async ({ payload }) => {
32
- const { thid, sdp, context } = payload
33
- const pc = ensurePeer(thid)
34
- await pc.setRemoteDescription({ type: 'offer', sdp })
83
+ const { thid, sdp, iceServers, policy, context } = payload
35
84
 
85
+ // Use ICE servers from offer (or fall back to module defaults)
86
+ const pc = new RTCPeerConnection({
87
+ iceServers: iceServers ?? agent.modules.webrtc.getDefaultIceServers(),
88
+ iceTransportPolicy: policy === 'relay-only' ? 'relay' : 'all',
89
+ })
90
+ peers.set(thid, pc)
91
+
92
+ await pc.setRemoteDescription({ type: 'offer', sdp })
36
93
  const answer = await pc.createAnswer()
37
94
  await pc.setLocalDescription(answer)
38
95
 
@@ -44,8 +101,11 @@ agent.events.on('WebRTCEvents.IncomingOffer', async ({ payload }) => {
44
101
  })
45
102
 
46
103
  agent.events.on('WebRTCEvents.IncomingAnswer', async ({ payload }) => {
47
- const { thid, sdp } = payload
48
- const pc = ensurePeer(thid)
104
+ const { thid, sdp, iceServers } = payload
105
+ const pc = peers.get(thid)
106
+ if (!pc) return
107
+
108
+ // If callee provided additional ICE servers, you might want to restart ICE
49
109
  await pc.setRemoteDescription({ type: 'answer', sdp })
50
110
  })
51
111
 
@@ -57,16 +117,41 @@ agent.events.on('WebRTCEvents.IncomingIce', async ({ payload }) => {
57
117
  else await pc.addIceCandidate(candidate as RTCIceCandidateInit)
58
118
  })
59
119
 
120
+ // Handle renegotiation requests (e.g., ICE restart)
121
+ agent.events.on('WebRTCEvents.RenegotiateRequested', async ({ payload }) => {
122
+ const { thid, iceRestart, iceServers, reason } = payload
123
+ const pc = peers.get(thid)
124
+ if (!pc) return
125
+
126
+ if (iceRestart) {
127
+ // Perform ICE restart
128
+ const offer = await pc.createOffer({ iceRestart: true })
129
+ await pc.setLocalDescription(offer)
130
+ // Send new offer...
131
+ }
132
+ })
133
+
60
134
  // Start call (caller)
61
135
  async function startCall(connectionId: string, localStream: MediaStream) {
62
136
  const thid = crypto.randomUUID()
63
- const pc = new RTCPeerConnection({
64
- iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],
65
- })
137
+
138
+ // Use module's default ICE servers
139
+ const iceServers = agent.modules.webrtc.getDefaultIceServers()
140
+
141
+ const pc = new RTCPeerConnection({ iceServers })
66
142
  peers.set(thid, pc)
67
143
 
144
+ // Handle ICE connection failures
145
+ pc.oniceconnectionstatechange = () => {
146
+ if (pc.iceConnectionState === 'failed') {
147
+ // Request ICE restart
148
+ agent.modules.webrtc.restartIce({ connectionId, threadId: thid })
149
+ }
150
+ }
151
+
68
152
  // Render remote stream
69
153
  pc.ontrack = e => (remoteVideo.srcObject = e.streams[0])
154
+
70
155
  // Send ICE via DIDComm
71
156
  pc.onicecandidate = e => agent.modules.webrtc.sendIce({
72
157
  connectionId,
@@ -74,23 +159,64 @@ async function startCall(connectionId: string, localStream: MediaStream) {
74
159
  candidate: e.candidate ?? undefined,
75
160
  endOfCandidates: e.candidate == null,
76
161
  })
162
+
77
163
  // Add local tracks
78
164
  for (const track of localStream.getTracks()) pc.addTrack(track, localStream)
79
165
 
80
166
  const offer = await pc.createOffer({ offerToReceiveVideo: true, offerToReceiveAudio: true })
81
167
  await pc.setLocalDescription(offer)
82
168
 
169
+ // Start call - ICE servers are automatically included from module config
83
170
  await agent.modules.webrtc.startCall({
84
171
  connectionId,
85
172
  threadId: thid,
86
173
  sdp: offer.sdp!,
87
- iceServers: [{ urls: 'stun:stun.l.google.com:19302' }],
174
+ // Optionally override policy for this specific call
175
+ policy: 'relay-preferred',
176
+ })
177
+ }
178
+
179
+ // Request ICE restart when connection fails
180
+ async function handleConnectionFailure(connectionId: string, thid: string) {
181
+ await agent.modules.webrtc.restartIce({
182
+ connectionId,
183
+ threadId: thid,
184
+ // Optionally provide new ICE servers
185
+ iceServers: [{ urls: 'turn:backup-turn.example.org:3478', username: 'u', credential: 'p' }],
88
186
  })
89
187
  }
90
188
  ```
91
189
 
92
- Notes:
190
+ ## API Reference
191
+
192
+ ### WebRTCApi Methods
193
+
194
+ | Method | Description |
195
+ |--------|-------------|
196
+ | `proposeCall()` | Send a call proposal with ICE servers before offer |
197
+ | `startCall()` | Send SDP offer with ICE servers |
198
+ | `acceptCall()` | Send SDP answer |
199
+ | `sendIce()` | Send ICE candidate |
200
+ | `renegotiate()` | Request renegotiation (track changes, codec changes) |
201
+ | `restartIce()` | Request ICE restart (connection recovery) |
202
+ | `endCall()` | End the call |
203
+ | `getDefaultIceServers()` | Get configured default ICE servers |
204
+
205
+ ### Events
206
+
207
+ | Event | Description |
208
+ |-------|-------------|
209
+ | `IncomingPropose` | Call proposal received (includes ICE servers) |
210
+ | `IncomingOffer` | SDP offer received |
211
+ | `IncomingAnswer` | SDP answer received |
212
+ | `IncomingIce` | ICE candidate received |
213
+ | `RenegotiateRequested` | Renegotiation requested (e.g., ICE restart) |
214
+ | `CallEnded` | Call ended |
215
+
216
+ ## Notes
217
+
93
218
  - This module moves only signaling over DIDComm; media flows via WebRTC/DTLS-SRTP.
94
- - For NAT traversal, pass TURN servers in `iceServers` in `offer` if needed.
219
+ - For NAT traversal, configure TURN servers in the module config or per-call.
220
+ - Use `relay-only` policy for maximum firewall compatibility (also hides IP addresses).
95
221
  - Works with mediators and message pickup (offline delivery), as with any DIDComm message.
96
222
 
package/build/index.d.ts CHANGED
@@ -1,4 +1,8 @@
1
- export { WebRTCModule } from './webrtc/WebRTCModule';
1
+ export { WebRTCModule, WebRTCModuleConfigToken } from './webrtc/WebRTCModule';
2
+ export type { WebRTCModuleConfig, WebRTCIceServerConfig } from './webrtc/WebRTCModule';
2
3
  export { WebRTCApi } from './webrtc/WebRTCApi';
3
- export { WebRTCEvents, type IncomingOfferEvent, type IncomingIceEvent } from './webrtc/WebRTCEvents';
4
+ export { WebRTCEvents, type IceServerEventConfig, type IncomingProposeEvent, type IncomingOfferEvent, type IncomingAnswerEvent, type IncomingIceEvent, type RenegotiateRequestedEvent, type CallEndedEvent, } from './webrtc/WebRTCEvents';
4
5
  export * from './webrtc/messages';
6
+ export type { IcePolicy, IceServerConfig } from './webrtc/messages/OfferMessage';
7
+ export type { MediaType } from './webrtc/messages/ProposeMessage';
8
+ export type { RenegotiateReason } from './webrtc/messages/RenegotiateMessage';
package/build/index.js CHANGED
@@ -14,12 +14,16 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.WebRTCEvents = exports.WebRTCApi = exports.WebRTCModule = void 0;
17
+ exports.WebRTCEvents = exports.WebRTCApi = exports.WebRTCModuleConfigToken = exports.WebRTCModule = void 0;
18
+ // Module and API
18
19
  var WebRTCModule_1 = require("./webrtc/WebRTCModule");
19
20
  Object.defineProperty(exports, "WebRTCModule", { enumerable: true, get: function () { return WebRTCModule_1.WebRTCModule; } });
21
+ Object.defineProperty(exports, "WebRTCModuleConfigToken", { enumerable: true, get: function () { return WebRTCModule_1.WebRTCModuleConfigToken; } });
20
22
  var WebRTCApi_1 = require("./webrtc/WebRTCApi");
21
23
  Object.defineProperty(exports, "WebRTCApi", { enumerable: true, get: function () { return WebRTCApi_1.WebRTCApi; } });
24
+ // Events
22
25
  var WebRTCEvents_1 = require("./webrtc/WebRTCEvents");
23
26
  Object.defineProperty(exports, "WebRTCEvents", { enumerable: true, get: function () { return WebRTCEvents_1.WebRTCEvents; } });
27
+ // Messages
24
28
  __exportStar(require("./webrtc/messages"), exports);
25
29
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,sDAAoD;AAA3C,4GAAA,YAAY,OAAA;AACrB,gDAA8C;AAArC,sGAAA,SAAS,OAAA;AAClB,sDAAoG;AAA3F,4GAAA,YAAY,OAAA;AACrB,oDAAiC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,iBAAiB;AACjB,sDAA6E;AAApE,4GAAA,YAAY,OAAA;AAAE,uHAAA,uBAAuB,OAAA;AAE9C,gDAA8C;AAArC,sGAAA,SAAS,OAAA;AAElB,SAAS;AACT,sDAS8B;AAR5B,4GAAA,YAAY,OAAA;AAUd,WAAW;AACX,oDAAiC"}
@@ -1,29 +1,75 @@
1
1
  import { ConnectionService, MessageSender, AgentContext } from '@credo-ts/core';
2
2
  import { WebRTCService } from './services/WebRTCService';
3
+ import type { IcePolicy, IceServerConfig } from './messages/OfferMessage';
4
+ import type { MediaType } from './messages/ProposeMessage';
5
+ import type { RenegotiateReason } from './messages/RenegotiateMessage';
6
+ import { type WebRTCModuleConfig } from './WebRTCModule';
3
7
  export declare class WebRTCApi {
4
8
  private connectionService;
5
9
  private messageSender;
6
10
  private webrtcService;
7
11
  private agentContext;
12
+ private config;
8
13
  constructor(connectionService: ConnectionService, messageSender: MessageSender, webrtcService: WebRTCService, agentContext: AgentContext);
9
14
  onAgentReady: boolean;
15
+ /**
16
+ * Get the configured default ICE servers
17
+ */
18
+ getDefaultIceServers(): WebRTCModuleConfig['iceServers'];
19
+ /**
20
+ * Propose a call to a peer (before sending offer)
21
+ * This allows sharing ICE servers and negotiating capabilities before the SDP exchange
22
+ */
23
+ proposeCall(options: {
24
+ connectionId: string;
25
+ threadId?: string;
26
+ parentThreadId?: string;
27
+ /** Requested media types */
28
+ media?: MediaType[];
29
+ /** Whether data channel is requested */
30
+ data?: boolean;
31
+ /** Topology: 'mesh' (P2P) or 'sfu' */
32
+ topology?: 'mesh' | 'sfu';
33
+ /** Whether trickle ICE is supported (defaults to module config) */
34
+ trickle?: boolean;
35
+ /** ICE policy (defaults to module config) */
36
+ policy?: IcePolicy;
37
+ /** ICE servers - uses module defaults if not provided */
38
+ iceServers?: IceServerConfig[];
39
+ /** Optional reason/context */
40
+ reason?: string;
41
+ }): Promise<{
42
+ threadId: string;
43
+ }>;
44
+ /**
45
+ * Start a call by sending an SDP offer
46
+ */
10
47
  startCall(options: {
11
48
  connectionId: string;
12
49
  threadId: string;
13
50
  parentThreadId?: string;
14
51
  sdp: string;
15
- iceServers?: {
16
- urls: string;
17
- username?: string;
18
- credential?: string;
19
- }[];
52
+ /** ICE servers - uses module defaults if not provided */
53
+ iceServers?: IceServerConfig[];
54
+ /** ICE policy (defaults to module config) */
55
+ policy?: IcePolicy;
56
+ /** Whether trickle ICE is enabled (defaults to module config) */
57
+ trickle?: boolean;
20
58
  }): Promise<import("./repository/WebRTCCallRecord").WebRTCCallRecord>;
59
+ /**
60
+ * Accept a call by sending an SDP answer
61
+ */
21
62
  acceptCall(options: {
22
63
  connectionId: string;
23
64
  threadId: string;
24
65
  parentThreadId?: string;
25
66
  sdp: string;
67
+ /** Optional ICE servers from callee (if different from caller's) */
68
+ iceServers?: IceServerConfig[];
26
69
  }): Promise<void>;
70
+ /**
71
+ * Send an ICE candidate
72
+ */
27
73
  sendIce(options: {
28
74
  connectionId: string;
29
75
  threadId: string;
@@ -31,6 +77,45 @@ export declare class WebRTCApi {
31
77
  candidate?: Record<string, unknown>;
32
78
  endOfCandidates?: boolean;
33
79
  }): Promise<void>;
80
+ /**
81
+ * Request renegotiation (for ICE restart, adding/removing tracks, etc.)
82
+ *
83
+ * Use this when:
84
+ * - ICE connection failed and needs restart
85
+ * - Adding screenshare or switching cameras
86
+ * - Network changed (WiFi to cellular)
87
+ * - Changing codec or bandwidth settings
88
+ */
89
+ renegotiate(options: {
90
+ connectionId: string;
91
+ threadId: string;
92
+ parentThreadId?: string;
93
+ /** Reason for renegotiation */
94
+ reason: RenegotiateReason | string;
95
+ /** Whether to perform ICE restart (required for recovering failed connections) */
96
+ iceRestart?: boolean;
97
+ /** New ICE servers (useful when switching networks) */
98
+ iceServers?: IceServerConfig[];
99
+ /** Updated ICE policy */
100
+ policy?: IcePolicy;
101
+ }): Promise<void>;
102
+ /**
103
+ * Request ICE restart (convenience method for renegotiate with iceRestart=true)
104
+ *
105
+ * Use when the WebRTC connection has failed or disconnected
106
+ */
107
+ restartIce(options: {
108
+ connectionId: string;
109
+ threadId: string;
110
+ parentThreadId?: string;
111
+ /** New ICE servers (optional, useful when original servers are unreachable) */
112
+ iceServers?: IceServerConfig[];
113
+ /** Updated ICE policy */
114
+ policy?: IcePolicy;
115
+ }): Promise<void>;
116
+ /**
117
+ * End a call
118
+ */
34
119
  endCall(options: {
35
120
  connectionId: string;
36
121
  threadId: string;
@@ -15,6 +15,7 @@ const tsyringe_1 = require("tsyringe");
15
15
  const core_2 = require("@credo-ts/core");
16
16
  const WebRTCService_1 = require("./services/WebRTCService");
17
17
  const handlers_1 = require("./handlers");
18
+ const WebRTCModule_1 = require("./WebRTCModule");
18
19
  let WebRTCApi = class WebRTCApi {
19
20
  constructor(connectionService, messageSender, webrtcService, agentContext) {
20
21
  this.connectionService = connectionService;
@@ -27,15 +28,71 @@ let WebRTCApi = class WebRTCApi {
27
28
  new handlers_1.OfferHandler(this.webrtcService),
28
29
  new handlers_1.AnswerHandler(this.webrtcService),
29
30
  new handlers_1.IceHandler(this.webrtcService),
31
+ new handlers_1.RenegotiateHandler(this.webrtcService),
30
32
  new handlers_1.EndHandler(this.webrtcService),
31
33
  new handlers_1.ProposeHandler(this.webrtcService),
32
34
  ]);
33
35
  return true;
34
36
  })();
37
+ // Get config from dependency manager, with fallback defaults
38
+ try {
39
+ this.config = this.agentContext.dependencyManager.resolve(WebRTCModule_1.WebRTCModuleConfigToken);
40
+ }
41
+ catch {
42
+ this.config = {
43
+ iceServers: [
44
+ { urls: 'stun:stun.l.google.com:19302' },
45
+ { urls: 'stun:stun1.l.google.com:19302' },
46
+ ],
47
+ defaultPolicy: 'all',
48
+ defaultTrickle: true,
49
+ };
50
+ }
35
51
  }
52
+ /**
53
+ * Get the configured default ICE servers
54
+ */
55
+ getDefaultIceServers() {
56
+ return this.config.iceServers;
57
+ }
58
+ /**
59
+ * Propose a call to a peer (before sending offer)
60
+ * This allows sharing ICE servers and negotiating capabilities before the SDP exchange
61
+ */
62
+ async proposeCall(options) {
63
+ const connection = await this.connectionService.getById(this.agentContext, options.connectionId);
64
+ // Use module defaults for missing options
65
+ const iceServers = options.iceServers ?? this.config.iceServers;
66
+ const policy = options.policy ?? this.config.defaultPolicy;
67
+ const trickle = options.trickle ?? this.config.defaultTrickle;
68
+ const { message } = this.webrtcService.createPropose({
69
+ threadId: options.threadId,
70
+ parentThreadId: options.parentThreadId,
71
+ media: options.media,
72
+ data: options.data,
73
+ topology: options.topology ?? 'mesh',
74
+ trickle,
75
+ policy,
76
+ iceServers,
77
+ reason: options.reason,
78
+ });
79
+ const outbound = await (0, core_2.getOutboundMessageContext)(this.agentContext, {
80
+ message,
81
+ connectionRecord: connection,
82
+ });
83
+ await this.messageSender.sendMessage(outbound);
84
+ return { threadId: message.threadId ?? message.id };
85
+ }
86
+ /**
87
+ * Start a call by sending an SDP offer
88
+ */
36
89
  async startCall(options) {
37
90
  const connection = await this.connectionService.getById(this.agentContext, options.connectionId);
38
- const { message, record } = this.webrtcService.createOffer(this.agentContext, connection, options.threadId, options.parentThreadId, options.sdp, options.iceServers);
91
+ // Use module defaults for missing options
92
+ const iceServers = options.iceServers ?? this.config.iceServers;
93
+ const policy = options.policy ?? this.config.defaultPolicy;
94
+ const trickle = options.trickle ?? this.config.defaultTrickle;
95
+ const { message, record } = this.webrtcService.createOffer(this.agentContext, connection, options.threadId, options.parentThreadId, options.sdp, iceServers, policy, trickle);
39
96
  const outbound = await (0, core_2.getOutboundMessageContext)(this.agentContext, {
40
97
  message,
41
98
  associatedRecord: record,
@@ -44,15 +101,21 @@ let WebRTCApi = class WebRTCApi {
44
101
  await this.messageSender.sendMessage(outbound);
45
102
  return record;
46
103
  }
104
+ /**
105
+ * Accept a call by sending an SDP answer
106
+ */
47
107
  async acceptCall(options) {
48
108
  const connection = await this.connectionService.getById(this.agentContext, options.connectionId);
49
- const { message } = this.webrtcService.createAnswer(this.agentContext, connection, options.threadId, options.parentThreadId, options.sdp);
109
+ const { message } = this.webrtcService.createAnswer(this.agentContext, connection, options.threadId, options.parentThreadId, options.sdp, options.iceServers);
50
110
  const outbound = await (0, core_2.getOutboundMessageContext)(this.agentContext, {
51
111
  message,
52
112
  connectionRecord: connection,
53
113
  });
54
114
  await this.messageSender.sendMessage(outbound);
55
115
  }
116
+ /**
117
+ * Send an ICE candidate
118
+ */
56
119
  async sendIce(options) {
57
120
  const connection = await this.connectionService.getById(this.agentContext, options.connectionId);
58
121
  const message = this.webrtcService.createIce(options.threadId, options.parentThreadId, options.candidate, options.endOfCandidates);
@@ -62,6 +125,46 @@ let WebRTCApi = class WebRTCApi {
62
125
  });
63
126
  await this.messageSender.sendMessage(outbound);
64
127
  }
128
+ /**
129
+ * Request renegotiation (for ICE restart, adding/removing tracks, etc.)
130
+ *
131
+ * Use this when:
132
+ * - ICE connection failed and needs restart
133
+ * - Adding screenshare or switching cameras
134
+ * - Network changed (WiFi to cellular)
135
+ * - Changing codec or bandwidth settings
136
+ */
137
+ async renegotiate(options) {
138
+ const connection = await this.connectionService.getById(this.agentContext, options.connectionId);
139
+ const message = this.webrtcService.createRenegotiate({
140
+ threadId: options.threadId,
141
+ parentThreadId: options.parentThreadId,
142
+ reason: options.reason,
143
+ iceRestart: options.iceRestart,
144
+ iceServers: options.iceServers,
145
+ policy: options.policy,
146
+ });
147
+ const outbound = await (0, core_2.getOutboundMessageContext)(this.agentContext, {
148
+ message,
149
+ connectionRecord: connection,
150
+ });
151
+ await this.messageSender.sendMessage(outbound);
152
+ }
153
+ /**
154
+ * Request ICE restart (convenience method for renegotiate with iceRestart=true)
155
+ *
156
+ * Use when the WebRTC connection has failed or disconnected
157
+ */
158
+ async restartIce(options) {
159
+ return this.renegotiate({
160
+ ...options,
161
+ reason: 'ice-restart',
162
+ iceRestart: true,
163
+ });
164
+ }
165
+ /**
166
+ * End a call
167
+ */
65
168
  async endCall(options) {
66
169
  const connection = await this.connectionService.getById(this.agentContext, options.connectionId);
67
170
  const message = this.webrtcService.createEnd(options.threadId, options.parentThreadId, options.reason);
@@ -1 +1 @@
1
- {"version":3,"file":"WebRTCApi.js","sourceRoot":"","sources":["../../src/webrtc/WebRTCApi.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WebRTCApi.js","sourceRoot":"","sources":["../../src/webrtc/WebRTCApi.ts"],"names":[],"mappings":"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"}
@@ -1,27 +1,81 @@
1
1
  import type { InboundMessageContext } from '@credo-ts/core';
2
+ import type { IcePolicy } from './messages/OfferMessage';
3
+ import type { MediaType } from './messages/ProposeMessage';
4
+ import type { RenegotiateReason } from './messages/RenegotiateMessage';
2
5
  export declare enum WebRTCEvents {
6
+ /** Incoming call proposal (before offer) */
7
+ IncomingPropose = "WebRTCEvents.IncomingPropose",
8
+ /** Incoming SDP offer */
3
9
  IncomingOffer = "WebRTCEvents.IncomingOffer",
10
+ /** Incoming SDP answer */
4
11
  IncomingAnswer = "WebRTCEvents.IncomingAnswer",
12
+ /** Incoming ICE candidate */
5
13
  IncomingIce = "WebRTCEvents.IncomingIce",
14
+ /** Renegotiation requested (track changes, ICE restart) */
15
+ RenegotiateRequested = "WebRTCEvents.RenegotiateRequested",
16
+ /** Call ended */
6
17
  CallEnded = "WebRTCEvents.CallEnded"
7
18
  }
19
+ /**
20
+ * ICE server configuration in events
21
+ */
22
+ export interface IceServerEventConfig {
23
+ urls: string | string[];
24
+ username?: string;
25
+ credential?: string;
26
+ credentialType?: 'password' | 'oauth';
27
+ }
28
+ /**
29
+ * Event emitted when a call proposal is received
30
+ */
31
+ export interface IncomingProposeEvent {
32
+ context: InboundMessageContext;
33
+ thid: string;
34
+ pthid?: string;
35
+ /** Requested media types */
36
+ media?: MediaType[];
37
+ /** Whether data channel is requested */
38
+ data?: boolean;
39
+ /** Topology: 'mesh' or 'sfu' */
40
+ topology?: 'mesh' | 'sfu';
41
+ /** Whether trickle ICE is supported */
42
+ trickle?: boolean;
43
+ /** ICE policy */
44
+ policy?: IcePolicy;
45
+ /** ICE servers for NAT traversal */
46
+ iceServers?: IceServerEventConfig[];
47
+ /** Optional reason/context */
48
+ reason?: string;
49
+ }
50
+ /**
51
+ * Event emitted when an SDP offer is received
52
+ */
8
53
  export interface IncomingOfferEvent {
9
54
  context: InboundMessageContext;
10
55
  thid: string;
11
56
  pthid?: string;
12
57
  sdp: string;
13
- iceServers?: Array<{
14
- urls: string | string[];
15
- username?: string;
16
- credential?: string;
17
- }>;
58
+ /** ICE servers for NAT traversal */
59
+ iceServers?: IceServerEventConfig[];
60
+ /** ICE policy */
61
+ policy?: IcePolicy;
62
+ /** Whether trickle ICE is enabled */
63
+ trickle?: boolean;
18
64
  }
65
+ /**
66
+ * Event emitted when an SDP answer is received
67
+ */
19
68
  export interface IncomingAnswerEvent {
20
69
  context: InboundMessageContext;
21
70
  thid: string;
22
71
  pthid?: string;
23
72
  sdp: string;
73
+ /** Optional ICE servers from callee */
74
+ iceServers?: IceServerEventConfig[];
24
75
  }
76
+ /**
77
+ * Event emitted when an ICE candidate is received
78
+ */
25
79
  export interface IncomingIceEvent {
26
80
  context: InboundMessageContext;
27
81
  thid: string;
@@ -29,3 +83,28 @@ export interface IncomingIceEvent {
29
83
  candidate: Record<string, unknown>;
30
84
  endOfCandidates?: boolean;
31
85
  }
86
+ /**
87
+ * Event emitted when renegotiation is requested
88
+ */
89
+ export interface RenegotiateRequestedEvent {
90
+ context: InboundMessageContext;
91
+ thid: string;
92
+ pthid?: string;
93
+ /** Reason for renegotiation */
94
+ reason: RenegotiateReason | string;
95
+ /** Whether ICE restart is requested */
96
+ iceRestart?: boolean;
97
+ /** New ICE servers (if changed) */
98
+ iceServers?: IceServerEventConfig[];
99
+ /** Updated ICE policy */
100
+ policy?: IcePolicy;
101
+ }
102
+ /**
103
+ * Event emitted when a call ends
104
+ */
105
+ export interface CallEndedEvent {
106
+ context: InboundMessageContext;
107
+ thid: string;
108
+ pthid?: string;
109
+ reason?: string;
110
+ }