@agentuity/react 1.0.1 → 1.0.2

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/webrtc.js ADDED
@@ -0,0 +1,301 @@
1
+ import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
2
+ import { WebRTCManager, buildUrl, } from '@agentuity/frontend';
3
+ import { AgentuityContext } from './context';
4
+ /**
5
+ * React hook for WebRTC peer-to-peer audio/video/data calls.
6
+ *
7
+ * Supports multi-peer mesh networking, screen sharing, recording, and stats.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * function VideoCall({ roomId }: { roomId: string }) {
12
+ * const {
13
+ * localVideoRef,
14
+ * state,
15
+ * remotePeerIds,
16
+ * remoteStreams,
17
+ * hangup,
18
+ * muteAudio,
19
+ * isAudioMuted,
20
+ * startScreenShare,
21
+ * } = useWebRTCCall({
22
+ * roomId,
23
+ * signalUrl: '/call/signal',
24
+ * callbacks: {
25
+ * onStateChange: (from, to, reason) => console.log(`${from} → ${to}`, reason),
26
+ * onRemoteStream: (peerId, stream) => console.log(`Got stream from ${peerId}`),
27
+ * },
28
+ * });
29
+ *
30
+ * return (
31
+ * <div>
32
+ * <video ref={localVideoRef} autoPlay muted playsInline />
33
+ * {remotePeerIds.map((peerId) => (
34
+ * <RemoteVideo key={peerId} stream={remoteStreams.get(peerId)} />
35
+ * ))}
36
+ * <p>State: {state}</p>
37
+ * <button onClick={() => muteAudio(!isAudioMuted)}>
38
+ * {isAudioMuted ? 'Unmute' : 'Mute'}
39
+ * </button>
40
+ * <button onClick={hangup}>Hang Up</button>
41
+ * </div>
42
+ * );
43
+ * }
44
+ * ```
45
+ */
46
+ export function useWebRTCCall(options) {
47
+ const context = useContext(AgentuityContext);
48
+ const managerRef = useRef(null);
49
+ const localVideoRef = useRef(null);
50
+ const [state, setState] = useState('idle');
51
+ const [error, setError] = useState(null);
52
+ const [peerId, setPeerId] = useState(null);
53
+ const [remotePeerIds, setRemotePeerIds] = useState([]);
54
+ const [remoteStreams, setRemoteStreams] = useState(new Map());
55
+ const [isAudioMuted, setIsAudioMuted] = useState(false);
56
+ const [isVideoMuted, setIsVideoMuted] = useState(false);
57
+ const [isScreenSharing, setIsScreenSharing] = useState(false);
58
+ const userCallbacksRef = useRef(options.callbacks);
59
+ userCallbacksRef.current = options.callbacks;
60
+ const signalUrl = useMemo(() => {
61
+ if (options.signalUrl.startsWith('ws://') || options.signalUrl.startsWith('wss://')) {
62
+ return options.signalUrl;
63
+ }
64
+ const base = context?.baseUrl ?? window.location.origin;
65
+ const wsBase = base.replace(/^http(s?):/, 'ws$1:');
66
+ return buildUrl(wsBase, options.signalUrl);
67
+ }, [context?.baseUrl, options.signalUrl]);
68
+ const managerOptions = useMemo(() => {
69
+ return {
70
+ signalUrl,
71
+ roomId: options.roomId,
72
+ polite: options.polite,
73
+ iceServers: options.iceServers,
74
+ media: options.media,
75
+ dataChannels: options.dataChannels,
76
+ autoReconnect: options.autoReconnect,
77
+ maxReconnectAttempts: options.maxReconnectAttempts,
78
+ connectionTimeout: options.connectionTimeout,
79
+ iceGatheringTimeout: options.iceGatheringTimeout,
80
+ callbacks: {
81
+ onStateChange: (from, to, reason) => {
82
+ setState(to);
83
+ if (managerRef.current) {
84
+ const managerState = managerRef.current.getState();
85
+ setPeerId(managerState.peerId);
86
+ setRemotePeerIds(managerState.remotePeerIds);
87
+ setIsScreenSharing(managerState.isScreenSharing);
88
+ }
89
+ userCallbacksRef.current?.onStateChange?.(from, to, reason);
90
+ },
91
+ onConnect: () => {
92
+ userCallbacksRef.current?.onConnect?.();
93
+ },
94
+ onDisconnect: (reason) => {
95
+ userCallbacksRef.current?.onDisconnect?.(reason);
96
+ },
97
+ onLocalStream: (stream) => {
98
+ if (localVideoRef.current) {
99
+ localVideoRef.current.srcObject = stream;
100
+ }
101
+ userCallbacksRef.current?.onLocalStream?.(stream);
102
+ },
103
+ onRemoteStream: (remotePeerId, stream) => {
104
+ setRemoteStreams((prev) => {
105
+ const next = new Map(prev);
106
+ next.set(remotePeerId, stream);
107
+ return next;
108
+ });
109
+ userCallbacksRef.current?.onRemoteStream?.(remotePeerId, stream);
110
+ },
111
+ onTrackAdded: (remotePeerId, track, stream) => {
112
+ userCallbacksRef.current?.onTrackAdded?.(remotePeerId, track, stream);
113
+ },
114
+ onTrackRemoved: (remotePeerId, track) => {
115
+ userCallbacksRef.current?.onTrackRemoved?.(remotePeerId, track);
116
+ },
117
+ onPeerJoined: (id) => {
118
+ setRemotePeerIds((prev) => (prev.includes(id) ? prev : [...prev, id]));
119
+ userCallbacksRef.current?.onPeerJoined?.(id);
120
+ },
121
+ onPeerLeft: (id) => {
122
+ setRemotePeerIds((prev) => prev.filter((p) => p !== id));
123
+ setRemoteStreams((prev) => {
124
+ const next = new Map(prev);
125
+ next.delete(id);
126
+ return next;
127
+ });
128
+ userCallbacksRef.current?.onPeerLeft?.(id);
129
+ },
130
+ onNegotiationStart: (remotePeerId) => {
131
+ userCallbacksRef.current?.onNegotiationStart?.(remotePeerId);
132
+ },
133
+ onNegotiationComplete: (remotePeerId) => {
134
+ userCallbacksRef.current?.onNegotiationComplete?.(remotePeerId);
135
+ },
136
+ onIceCandidate: (remotePeerId, candidate) => {
137
+ userCallbacksRef.current?.onIceCandidate?.(remotePeerId, candidate);
138
+ },
139
+ onIceStateChange: (remotePeerId, iceState) => {
140
+ userCallbacksRef.current?.onIceStateChange?.(remotePeerId, iceState);
141
+ },
142
+ onError: (err, currentState) => {
143
+ setError(err);
144
+ userCallbacksRef.current?.onError?.(err, currentState);
145
+ },
146
+ onDataChannelOpen: (remotePeerId, label) => {
147
+ userCallbacksRef.current?.onDataChannelOpen?.(remotePeerId, label);
148
+ },
149
+ onDataChannelClose: (remotePeerId, label) => {
150
+ userCallbacksRef.current?.onDataChannelClose?.(remotePeerId, label);
151
+ },
152
+ onDataChannelMessage: (remotePeerId, label, data) => {
153
+ userCallbacksRef.current?.onDataChannelMessage?.(remotePeerId, label, data);
154
+ },
155
+ onDataChannelError: (remotePeerId, label, err) => {
156
+ userCallbacksRef.current?.onDataChannelError?.(remotePeerId, label, err);
157
+ },
158
+ onScreenShareStart: () => {
159
+ setIsScreenSharing(true);
160
+ userCallbacksRef.current?.onScreenShareStart?.();
161
+ },
162
+ onScreenShareStop: () => {
163
+ setIsScreenSharing(false);
164
+ userCallbacksRef.current?.onScreenShareStop?.();
165
+ },
166
+ onReconnecting: (attempt) => {
167
+ userCallbacksRef.current?.onReconnecting?.(attempt);
168
+ },
169
+ onReconnected: () => {
170
+ userCallbacksRef.current?.onReconnected?.();
171
+ },
172
+ onReconnectFailed: () => {
173
+ userCallbacksRef.current?.onReconnectFailed?.();
174
+ },
175
+ },
176
+ };
177
+ }, [
178
+ signalUrl,
179
+ options.roomId,
180
+ options.polite,
181
+ options.iceServers,
182
+ options.media,
183
+ options.dataChannels,
184
+ options.autoReconnect,
185
+ options.maxReconnectAttempts,
186
+ options.connectionTimeout,
187
+ options.iceGatheringTimeout,
188
+ ]);
189
+ useEffect(() => {
190
+ const manager = new WebRTCManager(managerOptions);
191
+ managerRef.current = manager;
192
+ if (options.autoConnect !== false) {
193
+ manager.connect();
194
+ }
195
+ return () => {
196
+ manager.dispose();
197
+ managerRef.current = null;
198
+ };
199
+ }, [managerOptions, options.autoConnect]);
200
+ const connect = useCallback(() => {
201
+ managerRef.current?.connect();
202
+ }, []);
203
+ const hangup = useCallback(() => {
204
+ managerRef.current?.hangup();
205
+ setRemotePeerIds([]);
206
+ setRemoteStreams(new Map());
207
+ }, []);
208
+ const muteAudio = useCallback((muted) => {
209
+ managerRef.current?.muteAudio(muted);
210
+ setIsAudioMuted(muted);
211
+ }, []);
212
+ const muteVideo = useCallback((muted) => {
213
+ managerRef.current?.muteVideo(muted);
214
+ setIsVideoMuted(muted);
215
+ }, []);
216
+ const startScreenShare = useCallback(async (opts) => {
217
+ await managerRef.current?.startScreenShare(opts);
218
+ }, []);
219
+ const stopScreenShare = useCallback(async () => {
220
+ await managerRef.current?.stopScreenShare();
221
+ }, []);
222
+ const createDataChannel = useCallback((config) => {
223
+ return managerRef.current?.createDataChannel(config) ?? new Map();
224
+ }, []);
225
+ const getDataChannelLabels = useCallback(() => {
226
+ return managerRef.current?.getDataChannelLabels() ?? [];
227
+ }, []);
228
+ const getDataChannelState = useCallback((remotePeerId, label) => {
229
+ return managerRef.current?.getDataChannelState(remotePeerId, label) ?? null;
230
+ }, []);
231
+ const sendString = useCallback((label, data) => {
232
+ return managerRef.current?.sendString(label, data) ?? false;
233
+ }, []);
234
+ const sendStringTo = useCallback((remotePeerId, label, data) => {
235
+ return managerRef.current?.sendStringTo(remotePeerId, label, data) ?? false;
236
+ }, []);
237
+ const sendBinary = useCallback((label, data) => {
238
+ return managerRef.current?.sendBinary(label, data) ?? false;
239
+ }, []);
240
+ const sendBinaryTo = useCallback((remotePeerId, label, data) => {
241
+ return managerRef.current?.sendBinaryTo(remotePeerId, label, data) ?? false;
242
+ }, []);
243
+ const sendJSON = useCallback((label, data) => {
244
+ return managerRef.current?.sendJSON(label, data) ?? false;
245
+ }, []);
246
+ const sendJSONTo = useCallback((remotePeerId, label, data) => {
247
+ return managerRef.current?.sendJSONTo(remotePeerId, label, data) ?? false;
248
+ }, []);
249
+ const closeDataChannel = useCallback((label) => {
250
+ return managerRef.current?.closeDataChannel(label) ?? false;
251
+ }, []);
252
+ const getQualitySummary = useCallback(async (remotePeerId) => {
253
+ return managerRef.current?.getQualitySummary(remotePeerId) ?? null;
254
+ }, []);
255
+ const getAllQualitySummaries = useCallback(async () => {
256
+ return managerRef.current?.getAllQualitySummaries() ?? new Map();
257
+ }, []);
258
+ const startRecording = useCallback((streamId, opts) => {
259
+ return managerRef.current?.startRecording(streamId, opts) ?? null;
260
+ }, []);
261
+ const isRecordingFn = useCallback((streamId) => {
262
+ return managerRef.current?.isRecording(streamId) ?? false;
263
+ }, []);
264
+ const stopAllRecordings = useCallback(async () => {
265
+ return managerRef.current?.stopAllRecordings() ?? new Map();
266
+ }, []);
267
+ return {
268
+ localVideoRef,
269
+ state,
270
+ error,
271
+ peerId,
272
+ remotePeerIds,
273
+ remoteStreams,
274
+ isAudioMuted,
275
+ isVideoMuted,
276
+ isDataOnly: options.media === false,
277
+ isScreenSharing,
278
+ connect,
279
+ hangup,
280
+ muteAudio,
281
+ muteVideo,
282
+ startScreenShare,
283
+ stopScreenShare,
284
+ createDataChannel,
285
+ getDataChannelLabels,
286
+ getDataChannelState,
287
+ sendString,
288
+ sendStringTo,
289
+ sendBinary,
290
+ sendBinaryTo,
291
+ sendJSON,
292
+ sendJSONTo,
293
+ closeDataChannel,
294
+ getQualitySummary,
295
+ getAllQualitySummaries,
296
+ startRecording,
297
+ isRecording: isRecordingFn,
298
+ stopAllRecordings,
299
+ };
300
+ }
301
+ //# sourceMappingURL=webrtc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webrtc.js","sourceRoot":"","sources":["../src/webrtc.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentuity/react",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "license": "Apache-2.0",
5
5
  "author": "Agentuity employees and contributors",
6
6
  "type": "module",
@@ -34,12 +34,12 @@
34
34
  "prepublishOnly": "bun run clean && bun run build"
35
35
  },
36
36
  "dependencies": {
37
- "@agentuity/core": "1.0.1",
38
- "@agentuity/frontend": "1.0.1"
37
+ "@agentuity/core": "1.0.2",
38
+ "@agentuity/frontend": "1.0.2"
39
39
  },
40
40
  "devDependencies": {
41
- "@agentuity/schema": "1.0.1",
42
- "@agentuity/test-utils": "1.0.1",
41
+ "@agentuity/schema": "1.0.2",
42
+ "@agentuity/test-utils": "1.0.2",
43
43
  "@types/bun": "latest",
44
44
  "bun-types": "latest",
45
45
  "typescript": "^5.9.0"
@@ -49,6 +49,9 @@ export interface EventStreamOptions {
49
49
  * the SSERouteRegistry generated from your routes.
50
50
  *
51
51
  * @template TRoute - SSE route key from SSERouteRegistry (e.g., '/events', '/notifications')
52
+ * @template TOutput - Optional type override for SSE event data. When provided, this type
53
+ * is used instead of the inferred type from the route registry. This is useful for SSE
54
+ * routes where outputSchema is `never` in the generated types.
52
55
  *
53
56
  * @example Simple SSE connection
54
57
  * ```typescript
@@ -63,14 +66,29 @@ export interface EventStreamOptions {
63
66
  * query: new URLSearchParams({ userId: '123' })
64
67
  * });
65
68
  * ```
69
+ *
70
+ * @example SSE with custom output type (when registry has outputSchema: never)
71
+ * ```typescript
72
+ * interface StreamMessage {
73
+ * type: 'token' | 'complete';
74
+ * content?: string;
75
+ * }
76
+ *
77
+ * const { isConnected, data } = useEventStream<'/api/search', StreamMessage>('/api/search');
78
+ *
79
+ * // data is typed as StreamMessage | undefined
80
+ * if (data?.type === 'token') {
81
+ * console.log(data.content);
82
+ * }
83
+ * ```
66
84
  */
67
- export function useEventStream<TRoute extends SSERouteKey>(
85
+ export function useEventStream<TRoute extends SSERouteKey, TOutput = SSERouteOutput<TRoute>>(
68
86
  route: TRoute,
69
87
  options?: EventStreamOptions
70
88
  ): {
71
89
  isConnected: boolean;
72
90
  close: () => void;
73
- data?: SSERouteOutput<TRoute>;
91
+ data?: TOutput;
74
92
  error: Error | null;
75
93
  isError: boolean;
76
94
  reset: () => void;
@@ -82,23 +100,28 @@ export function useEventStream<TRoute extends SSERouteKey>(
82
100
  throw new Error('useEventStream must be used within a AgentuityProvider');
83
101
  }
84
102
 
85
- const managerRef = useRef<EventStreamManager<SSERouteOutput<TRoute>> | null>(null);
103
+ const managerRef = useRef<EventStreamManager<TOutput> | null>(null);
86
104
 
87
- const [data, setData] = useState<SSERouteOutput<TRoute>>();
105
+ const [data, setData] = useState<TOutput>();
88
106
  const [error, setError] = useState<Error | null>(null);
89
107
  const [isError, setIsError] = useState(false);
90
108
  const [isConnected, setIsConnected] = useState(false);
91
109
  const [readyState, setReadyState] = useState<number>(2); // EventSource.CLOSED = 2
92
110
 
93
111
  // Build EventStream URL
112
+ // Track both query object and its string representation to detect mutations.
113
+ // URLSearchParams can be mutated in-place without changing object identity,
114
+ // so we compare the string value to trigger recomputation when params change.
115
+ const queryString = options?.query?.toString();
94
116
  const esUrl = useMemo(
95
117
  () => buildUrl(context.baseUrl!, route as string, options?.subpath, options?.query),
96
- [context.baseUrl, route, options?.subpath, options?.query?.toString()]
118
+ // biome-ignore lint/correctness/useExhaustiveDependencies: queryString tracks URLSearchParams mutations that options?.query reference wouldn't catch
119
+ [context.baseUrl, route, options?.subpath, options?.query, queryString]
97
120
  );
98
121
 
99
122
  // Initialize manager and connect
100
123
  useEffect(() => {
101
- const manager = new EventStreamManager<SSERouteOutput<TRoute>>({
124
+ const manager = new EventStreamManager<TOutput>({
102
125
  url: esUrl,
103
126
  callbacks: {
104
127
  onConnect: () => {
package/src/index.ts CHANGED
@@ -29,6 +29,13 @@ export {
29
29
  type SSERouteOutput,
30
30
  type EventStreamOptions,
31
31
  } from './eventstream';
32
+ export {
33
+ useWebRTCCall,
34
+ type UseWebRTCCallOptions,
35
+ type UseWebRTCCallResult,
36
+ type WebRTCConnectionState,
37
+ type WebRTCClientCallbacks,
38
+ } from './webrtc';
32
39
  export {
33
40
  useAPI,
34
41
  type RouteKey,
@@ -82,6 +89,13 @@ export {
82
89
  type EventStreamCallbacks,
83
90
  type EventStreamManagerOptions,
84
91
  type EventStreamManagerState,
92
+ WebRTCManager,
93
+ UserMediaSource,
94
+ DisplayMediaSource,
95
+ CustomStreamSource,
96
+ type WebRTCManagerOptions,
97
+ type WebRTCManagerState,
98
+ type WebRTCDisconnectReason,
85
99
  // Client type exports (createClient is exported from ./client.ts)
86
100
  type Client,
87
101
  type ClientOptions,