blanchon commited on
Commit
8344179
·
1 Parent(s): c9dc57e
client/js/dist/index.d.ts ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * LeRobot Arena Client Library - TypeScript/JavaScript
3
+ *
4
+ * Main entry point for the robotics client library.
5
+ */
6
+ export * as robotics from './robotics/index.js';
7
+ export * as video from './video/index.js';
8
+ export declare const VERSION = "1.0.0";
client/js/dist/robotics/consumer.d.ts ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Consumer client for receiving robot commands in LeRobot Arena
3
+ */
4
+ import { RoboticsClientCore } from './core.js';
5
+ import type { WebSocketMessage, ClientOptions, JointUpdateCallback, StateSyncCallback } from './types.js';
6
+ export declare class RoboticsConsumer extends RoboticsClientCore {
7
+ private onStateSyncCallback;
8
+ private onJointUpdateCallback;
9
+ constructor(baseUrl?: string, options?: ClientOptions);
10
+ connect(workspaceId: string, roomId: string, participantId?: string): Promise<boolean>;
11
+ getStateSyncAsync(): Promise<Record<string, number>>;
12
+ onStateSync(callback: StateSyncCallback): void;
13
+ onJointUpdate(callback: JointUpdateCallback): void;
14
+ protected handleRoleSpecificMessage(message: WebSocketMessage): void;
15
+ private handleStateSync;
16
+ private handleJointUpdate;
17
+ /**
18
+ * Create a consumer and automatically connect to a room
19
+ */
20
+ static createAndConnect(workspaceId: string, roomId: string, baseUrl?: string, participantId?: string): Promise<RoboticsConsumer>;
21
+ }
client/js/dist/robotics/core.d.ts ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Core robotics client for LeRobot Arena
3
+ * Base class providing REST API and WebSocket functionality
4
+ */
5
+ import { EventEmitter } from 'eventemitter3';
6
+ import type { ParticipantRole, RoomInfo, RoomState, ConnectionInfo, WebSocketMessage, ClientOptions, ErrorCallback, ConnectedCallback, DisconnectedCallback } from './types.js';
7
+ export declare class RoboticsClientCore extends EventEmitter {
8
+ protected baseUrl: string;
9
+ protected apiBase: string;
10
+ protected websocket: WebSocket | null;
11
+ protected workspaceId: string | null;
12
+ protected roomId: string | null;
13
+ protected role: ParticipantRole | null;
14
+ protected participantId: string | null;
15
+ protected connected: boolean;
16
+ protected options: ClientOptions;
17
+ protected onErrorCallback: ErrorCallback | null;
18
+ protected onConnectedCallback: ConnectedCallback | null;
19
+ protected onDisconnectedCallback: DisconnectedCallback | null;
20
+ constructor(baseUrl?: string, options?: ClientOptions);
21
+ listRooms(workspaceId: string): Promise<RoomInfo[]>;
22
+ createRoom(workspaceId?: string, roomId?: string): Promise<{
23
+ workspaceId: string;
24
+ roomId: string;
25
+ }>;
26
+ deleteRoom(workspaceId: string, roomId: string): Promise<boolean>;
27
+ getRoomState(workspaceId: string, roomId: string): Promise<RoomState>;
28
+ getRoomInfo(workspaceId: string, roomId: string): Promise<RoomInfo>;
29
+ connectToRoom(workspaceId: string, roomId: string, role: ParticipantRole, participantId?: string): Promise<boolean>;
30
+ disconnect(): Promise<void>;
31
+ protected sendJoinMessage(): void;
32
+ protected handleMessage(message: WebSocketMessage): void;
33
+ protected handleRoleSpecificMessage(message: WebSocketMessage): void;
34
+ protected handleError(errorMessage: string): void;
35
+ sendHeartbeat(): Promise<void>;
36
+ isConnected(): boolean;
37
+ getConnectionInfo(): ConnectionInfo;
38
+ onError(callback: ErrorCallback): void;
39
+ onConnected(callback: ConnectedCallback): void;
40
+ onDisconnected(callback: DisconnectedCallback): void;
41
+ private fetchApi;
42
+ protected generateWorkspaceId(): string;
43
+ }
client/js/dist/robotics/factory.d.ts ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Factory functions for creating LeRobot Arena robotics clients
3
+ */
4
+ import { RoboticsProducer } from './producer.js';
5
+ import { RoboticsConsumer } from './consumer.js';
6
+ import type { ParticipantRole, ClientOptions } from './types.js';
7
+ /**
8
+ * Factory function to create the appropriate client based on role
9
+ */
10
+ export declare function createClient(role: ParticipantRole, baseUrl?: string, options?: ClientOptions): RoboticsProducer | RoboticsConsumer;
11
+ /**
12
+ * Create and connect a producer client
13
+ */
14
+ export declare function createProducerClient(baseUrl?: string, workspaceId?: string, roomId?: string, participantId?: string, options?: ClientOptions): Promise<RoboticsProducer>;
15
+ /**
16
+ * Create and connect a consumer client
17
+ */
18
+ export declare function createConsumerClient(workspaceId: string, roomId: string, baseUrl?: string, participantId?: string, options?: ClientOptions): Promise<RoboticsConsumer>;
client/js/dist/robotics/index.d.ts ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * LeRobot Arena Robotics Client - Main Module
3
+ *
4
+ * TypeScript/JavaScript client for robotics control and monitoring
5
+ */
6
+ export { RoboticsClientCore } from './core.js';
7
+ export { RoboticsProducer } from './producer.js';
8
+ export { RoboticsConsumer } from './consumer.js';
9
+ export * from './types.js';
10
+ export { createProducerClient, createConsumerClient, createClient } from './factory.js';
client/js/dist/robotics/producer.d.ts ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Producer client for controlling robots in LeRobot Arena
3
+ */
4
+ import { RoboticsClientCore } from './core.js';
5
+ import type { JointData, WebSocketMessage, ClientOptions } from './types.js';
6
+ export declare class RoboticsProducer extends RoboticsClientCore {
7
+ constructor(baseUrl?: string, options?: ClientOptions);
8
+ connect(workspaceId: string, roomId: string, participantId?: string): Promise<boolean>;
9
+ sendJointUpdate(joints: JointData[]): Promise<void>;
10
+ sendStateSync(state: Record<string, number>): Promise<void>;
11
+ sendEmergencyStop(reason?: string): Promise<void>;
12
+ protected handleRoleSpecificMessage(message: WebSocketMessage): void;
13
+ /**
14
+ * Create a room and automatically connect as producer
15
+ */
16
+ static createAndConnect(baseUrl?: string, workspaceId?: string, roomId?: string, participantId?: string): Promise<RoboticsProducer>;
17
+ /**
18
+ * Get the current room ID (useful when auto-created)
19
+ */
20
+ get currentRoomId(): string | null;
21
+ }
client/js/dist/robotics/types.d.ts ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Type definitions for LeRobot Arena Robotics Client
3
+ */
4
+ export type ParticipantRole = 'producer' | 'consumer';
5
+ export type MessageType = 'joint_update' | 'state_sync' | 'heartbeat' | 'heartbeat_ack' | 'emergency_stop' | 'joined' | 'error';
6
+ export interface JointData {
7
+ name: string;
8
+ value: number;
9
+ speed?: number;
10
+ }
11
+ export interface RoomInfo {
12
+ id: string;
13
+ workspace_id: string;
14
+ participants: {
15
+ producer: string | null;
16
+ consumers: string[];
17
+ total: number;
18
+ };
19
+ joints_count: number;
20
+ has_producer?: boolean;
21
+ active_consumers?: number;
22
+ }
23
+ export interface RoomState {
24
+ room_id: string;
25
+ workspace_id: string;
26
+ joints: Record<string, number>;
27
+ participants: {
28
+ producer: string | null;
29
+ consumers: string[];
30
+ total: number;
31
+ };
32
+ timestamp: string;
33
+ }
34
+ export interface ConnectionInfo {
35
+ connected: boolean;
36
+ workspace_id: string | null;
37
+ room_id: string | null;
38
+ role: ParticipantRole | null;
39
+ participant_id: string | null;
40
+ base_url: string;
41
+ }
42
+ export interface BaseMessage {
43
+ type: MessageType;
44
+ timestamp?: string;
45
+ }
46
+ export interface JointUpdateMessage extends BaseMessage {
47
+ type: 'joint_update';
48
+ data: JointData[];
49
+ source?: string;
50
+ }
51
+ export interface StateSyncMessage extends BaseMessage {
52
+ type: 'state_sync';
53
+ data: Record<string, number>;
54
+ }
55
+ export interface HeartbeatMessage extends BaseMessage {
56
+ type: 'heartbeat';
57
+ }
58
+ export interface HeartbeatAckMessage extends BaseMessage {
59
+ type: 'heartbeat_ack';
60
+ }
61
+ export interface EmergencyStopMessage extends BaseMessage {
62
+ type: 'emergency_stop';
63
+ reason: string;
64
+ source?: string;
65
+ }
66
+ export interface JoinedMessage extends BaseMessage {
67
+ type: 'joined';
68
+ room_id: string;
69
+ role: ParticipantRole;
70
+ }
71
+ export interface ErrorMessage extends BaseMessage {
72
+ type: 'error';
73
+ message: string;
74
+ }
75
+ export type WebSocketMessage = JointUpdateMessage | StateSyncMessage | HeartbeatMessage | HeartbeatAckMessage | EmergencyStopMessage | JoinedMessage | ErrorMessage;
76
+ export interface ApiResponse<T = unknown> {
77
+ success: boolean;
78
+ data?: T;
79
+ error?: string;
80
+ message?: string;
81
+ }
82
+ export interface ListRoomsResponse {
83
+ success: boolean;
84
+ workspace_id: string;
85
+ rooms: RoomInfo[];
86
+ total: number;
87
+ }
88
+ export interface CreateRoomResponse {
89
+ success: boolean;
90
+ workspace_id: string;
91
+ room_id: string;
92
+ message: string;
93
+ }
94
+ export interface GetRoomResponse {
95
+ success: boolean;
96
+ workspace_id: string;
97
+ room: RoomInfo;
98
+ }
99
+ export interface GetRoomStateResponse {
100
+ success: boolean;
101
+ workspace_id: string;
102
+ state: RoomState;
103
+ }
104
+ export interface DeleteRoomResponse {
105
+ success: boolean;
106
+ workspace_id: string;
107
+ message: string;
108
+ }
109
+ export interface CreateRoomRequest {
110
+ room_id?: string;
111
+ workspace_id?: string;
112
+ }
113
+ export interface JoinMessage {
114
+ participant_id: string;
115
+ role: ParticipantRole;
116
+ }
117
+ export type JointUpdateCallback = (joints: JointData[]) => void;
118
+ export type StateSyncCallback = (state: Record<string, number>) => void;
119
+ export type ErrorCallback = (error: string) => void;
120
+ export type ConnectedCallback = () => void;
121
+ export type DisconnectedCallback = () => void;
122
+ export interface ClientOptions {
123
+ base_url?: string;
124
+ timeout?: number;
125
+ reconnect_attempts?: number;
126
+ heartbeat_interval?: number;
127
+ }
client/js/dist/video/consumer.d.ts ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Consumer client for receiving video streams in LeRobot Arena
3
+ */
4
+ import { VideoClientCore } from './core.js';
5
+ import type { WebSocketMessage, ClientOptions, WebRTCStats, FrameUpdateCallback, VideoConfigUpdateCallback, StreamStartedCallback, StreamStoppedCallback, RecoveryTriggeredCallback, StatusUpdateCallback, StreamStatsCallback, WebRTCOfferMessage } from './types.js';
6
+ export declare class VideoConsumer extends VideoClientCore {
7
+ private onFrameUpdateCallback;
8
+ private onVideoConfigUpdateCallback;
9
+ private onStreamStartedCallback;
10
+ private onStreamStoppedCallback;
11
+ private onRecoveryTriggeredCallback;
12
+ private onStatusUpdateCallback;
13
+ private onStreamStatsCallback;
14
+ private iceCandidateQueue;
15
+ private hasRemoteDescription;
16
+ constructor(baseUrl?: string, options?: ClientOptions);
17
+ connect(workspaceId: string, roomId: string, participantId?: string): Promise<boolean>;
18
+ startReceiving(): Promise<void>;
19
+ stopReceiving(): Promise<void>;
20
+ handleWebRTCOffer(message: WebRTCOfferMessage): Promise<void>;
21
+ private handleWebRTCIce;
22
+ private processQueuedIceCandidates;
23
+ createPeerConnection(): RTCPeerConnection;
24
+ private sendIceCandidateToProducer;
25
+ private handleStreamStarted;
26
+ onFrameUpdate(callback: FrameUpdateCallback): void;
27
+ onVideoConfigUpdate(callback: VideoConfigUpdateCallback): void;
28
+ onStreamStarted(callback: StreamStartedCallback): void;
29
+ onStreamStopped(callback: StreamStoppedCallback): void;
30
+ onRecoveryTriggered(callback: RecoveryTriggeredCallback): void;
31
+ onStatusUpdate(callback: StatusUpdateCallback): void;
32
+ onStreamStats(callback: StreamStatsCallback): void;
33
+ protected handleRoleSpecificMessage(message: WebSocketMessage): void;
34
+ private handleFrameUpdate;
35
+ private handleVideoConfigUpdate;
36
+ private handleStreamStopped;
37
+ private handleRecoveryTriggered;
38
+ private handleStatusUpdate;
39
+ private handleStreamStats;
40
+ /**
41
+ * Create a consumer and automatically connect to a room
42
+ */
43
+ static createAndConnect(workspaceId: string, roomId: string, baseUrl?: string, participantId?: string): Promise<VideoConsumer>;
44
+ /**
45
+ * Get the video element for displaying the remote stream
46
+ */
47
+ attachToVideoElement(videoElement: HTMLVideoElement): void;
48
+ /**
49
+ * Get current video statistics
50
+ */
51
+ getVideoStats(): Promise<WebRTCStats | null>;
52
+ }
client/js/dist/video/core.d.ts ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Core video client for LeRobot Arena
3
+ * Base class providing REST API, WebSocket, and WebRTC functionality
4
+ */
5
+ import { EventEmitter } from 'eventemitter3';
6
+ import type { ParticipantRole, RoomInfo, RoomState, ConnectionInfo, WebSocketMessage, WebRTCSignalResponse, ClientOptions, WebRTCConfig, WebRTCStats, VideoConfig, RecoveryConfig, ErrorCallback, ConnectedCallback, DisconnectedCallback } from './types.js';
7
+ export declare class VideoClientCore extends EventEmitter {
8
+ protected baseUrl: string;
9
+ protected apiBase: string;
10
+ protected websocket: WebSocket | null;
11
+ protected peerConnection: RTCPeerConnection | null;
12
+ protected localStream: MediaStream | null;
13
+ protected remoteStream: MediaStream | null;
14
+ protected workspaceId: string | null;
15
+ protected roomId: string | null;
16
+ protected role: ParticipantRole | null;
17
+ protected participantId: string | null;
18
+ protected connected: boolean;
19
+ protected options: ClientOptions;
20
+ protected webrtcConfig: WebRTCConfig;
21
+ protected onErrorCallback: ErrorCallback | null;
22
+ protected onConnectedCallback: ConnectedCallback | null;
23
+ protected onDisconnectedCallback: DisconnectedCallback | null;
24
+ constructor(baseUrl?: string, options?: ClientOptions);
25
+ listRooms(workspaceId: string): Promise<RoomInfo[]>;
26
+ createRoom(workspaceId?: string, roomId?: string, config?: VideoConfig, recoveryConfig?: RecoveryConfig): Promise<{
27
+ workspaceId: string;
28
+ roomId: string;
29
+ }>;
30
+ deleteRoom(workspaceId: string, roomId: string): Promise<boolean>;
31
+ getRoomState(workspaceId: string, roomId: string): Promise<RoomState>;
32
+ getRoomInfo(workspaceId: string, roomId: string): Promise<RoomInfo>;
33
+ sendWebRTCSignal(workspaceId: string, roomId: string, clientId: string, message: RTCSessionDescriptionInit | RTCIceCandidateInit | Record<string, unknown>): Promise<WebRTCSignalResponse>;
34
+ connectToRoom(workspaceId: string, roomId: string, role: ParticipantRole, participantId?: string): Promise<boolean>;
35
+ disconnect(): Promise<void>;
36
+ createPeerConnection(): RTCPeerConnection;
37
+ createOffer(): Promise<RTCSessionDescriptionInit>;
38
+ createAnswer(offer: RTCSessionDescriptionInit): Promise<RTCSessionDescriptionInit>;
39
+ setRemoteDescription(description: RTCSessionDescriptionInit): Promise<void>;
40
+ addIceCandidate(candidate: RTCIceCandidateInit): Promise<void>;
41
+ startProducing(constraints?: MediaStreamConstraints): Promise<MediaStream>;
42
+ startScreenShare(): Promise<MediaStream>;
43
+ stopProducing(): void;
44
+ getLocalStream(): MediaStream | null;
45
+ getRemoteStream(): MediaStream | null;
46
+ getPeerConnection(): RTCPeerConnection | null;
47
+ getStats(): Promise<WebRTCStats | null>;
48
+ protected sendJoinMessage(): void;
49
+ protected handleMessage(message: WebSocketMessage): void;
50
+ protected handleRoleSpecificMessage(message: WebSocketMessage): void;
51
+ protected handleError(errorMessage: string): void;
52
+ sendHeartbeat(): Promise<void>;
53
+ isConnected(): boolean;
54
+ getConnectionInfo(): ConnectionInfo;
55
+ onError(callback: ErrorCallback): void;
56
+ onConnected(callback: ConnectedCallback): void;
57
+ onDisconnected(callback: DisconnectedCallback): void;
58
+ private fetchApi;
59
+ private extractVideoStats;
60
+ protected generateWorkspaceId(): string;
61
+ }
client/js/dist/video/factory.d.ts ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Factory functions for creating LeRobot Arena video clients
3
+ */
4
+ import { VideoProducer } from './producer.js';
5
+ import { VideoConsumer } from './consumer.js';
6
+ import type { ParticipantRole, ClientOptions } from './types.js';
7
+ /**
8
+ * Factory function to create the appropriate client based on role
9
+ */
10
+ export declare function createClient(role: ParticipantRole, baseUrl?: string, options?: ClientOptions): VideoProducer | VideoConsumer;
11
+ /**
12
+ * Create and connect a producer client
13
+ */
14
+ export declare function createProducerClient(baseUrl?: string, workspaceId?: string, roomId?: string, participantId?: string, options?: ClientOptions): Promise<VideoProducer>;
15
+ /**
16
+ * Create and connect a consumer client
17
+ */
18
+ export declare function createConsumerClient(workspaceId: string, roomId: string, baseUrl?: string, participantId?: string, options?: ClientOptions): Promise<VideoConsumer>;
client/js/dist/video/index.d.ts ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * LeRobot Arena Video Client - Main Module
3
+ *
4
+ * TypeScript/JavaScript client for video streaming and monitoring
5
+ */
6
+ export { VideoClientCore } from './core.js';
7
+ export { VideoProducer } from './producer.js';
8
+ export { VideoConsumer } from './consumer.js';
9
+ export * from './types.js';
10
+ export { createProducerClient, createConsumerClient, createClient } from './factory.js';
client/js/dist/video/producer.d.ts ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Producer client for video streaming in LeRobot Arena
3
+ */
4
+ import { VideoClientCore } from './core.js';
5
+ import type { WebSocketMessage, ClientOptions, VideoConfig } from './types.js';
6
+ export declare class VideoProducer extends VideoClientCore {
7
+ private consumerConnections;
8
+ constructor(baseUrl?: string, options?: ClientOptions);
9
+ connect(workspaceId: string, roomId: string, participantId?: string): Promise<boolean>;
10
+ private connectToExistingConsumers;
11
+ private createPeerConnectionForConsumer;
12
+ private restartConnectionToConsumer;
13
+ private handleConsumerLeft;
14
+ private restartConnectionsWithNewStream;
15
+ startCamera(constraints?: MediaStreamConstraints): Promise<MediaStream>;
16
+ startScreenShare(): Promise<MediaStream>;
17
+ stopStreaming(): Promise<void>;
18
+ updateVideoConfig(config: VideoConfig): Promise<void>;
19
+ sendEmergencyStop(reason?: string): Promise<void>;
20
+ initiateWebRTCWithConsumer(consumerId: string): Promise<void>;
21
+ private handleWebRTCAnswer;
22
+ private handleWebRTCIce;
23
+ protected handleRoleSpecificMessage(message: WebSocketMessage): void;
24
+ private handleStatusUpdate;
25
+ private handleStreamStats;
26
+ private notifyStreamStarted;
27
+ private notifyStreamStopped;
28
+ /**
29
+ * Create a room and automatically connect as producer
30
+ */
31
+ static createAndConnect(baseUrl?: string, workspaceId?: string, roomId?: string, participantId?: string): Promise<VideoProducer>;
32
+ /**
33
+ * Get the current room ID (useful when auto-created)
34
+ */
35
+ get currentRoomId(): string | null;
36
+ }
client/js/dist/video/types.d.ts ADDED
@@ -0,0 +1,249 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Type definitions for LeRobot Arena Video Client
3
+ * ✅ Fully synchronized with server-side models.py
4
+ */
5
+ export type ParticipantRole = 'producer' | 'consumer';
6
+ export type MessageType = 'frame_update' | 'video_config_update' | 'stream_started' | 'stream_stopped' | 'recovery_triggered' | 'heartbeat' | 'heartbeat_ack' | 'emergency_stop' | 'joined' | 'error' | 'participant_joined' | 'participant_left' | 'webrtc_offer' | 'webrtc_answer' | 'webrtc_ice' | 'status_update' | 'stream_stats';
7
+ export interface VideoConfig {
8
+ encoding?: VideoEncoding;
9
+ resolution?: Resolution;
10
+ framerate?: number;
11
+ bitrate?: number;
12
+ quality?: number;
13
+ }
14
+ export interface Resolution {
15
+ width: number;
16
+ height: number;
17
+ }
18
+ export type VideoEncoding = 'jpeg' | 'h264' | 'vp8' | 'vp9';
19
+ export type RecoveryPolicy = 'freeze_last_frame' | 'connection_info' | 'black_screen' | 'fade_to_black' | 'overlay_status';
20
+ export interface RecoveryConfig {
21
+ frame_timeout_ms?: number;
22
+ max_frame_reuse_count?: number;
23
+ recovery_policy?: RecoveryPolicy;
24
+ fallback_policy?: RecoveryPolicy;
25
+ show_hold_indicators?: boolean;
26
+ info_frame_bg_color?: [number, number, number];
27
+ info_frame_text_color?: [number, number, number];
28
+ fade_intensity?: number;
29
+ overlay_opacity?: number;
30
+ }
31
+ export interface FrameData {
32
+ data: ArrayBuffer;
33
+ metadata?: Record<string, unknown>;
34
+ }
35
+ export interface StreamStats {
36
+ stream_id: string;
37
+ duration_seconds: number;
38
+ frame_count: number;
39
+ total_bytes: number;
40
+ average_fps: number;
41
+ average_bitrate: number;
42
+ }
43
+ export interface ParticipantInfo {
44
+ producer: string | null;
45
+ consumers: string[];
46
+ total: number;
47
+ }
48
+ export interface RoomInfo {
49
+ id: string;
50
+ workspace_id: string;
51
+ participants: ParticipantInfo;
52
+ frame_count: number;
53
+ config: VideoConfig;
54
+ has_producer: boolean;
55
+ active_consumers: number;
56
+ }
57
+ export interface RoomState {
58
+ room_id: string;
59
+ workspace_id: string;
60
+ participants: ParticipantInfo;
61
+ frame_count: number;
62
+ last_frame_time: string | null;
63
+ current_config: VideoConfig;
64
+ timestamp: string;
65
+ }
66
+ export interface ConnectionInfo {
67
+ connected: boolean;
68
+ workspace_id: string | null;
69
+ room_id: string | null;
70
+ role: ParticipantRole | null;
71
+ participant_id: string | null;
72
+ base_url: string;
73
+ }
74
+ export interface BaseMessage {
75
+ type: MessageType;
76
+ timestamp?: string;
77
+ }
78
+ export interface FrameUpdateMessage extends BaseMessage {
79
+ type: 'frame_update';
80
+ data: ArrayBuffer;
81
+ metadata?: Record<string, unknown>;
82
+ }
83
+ export interface VideoConfigUpdateMessage extends BaseMessage {
84
+ type: 'video_config_update';
85
+ config: VideoConfig;
86
+ source?: string;
87
+ }
88
+ export interface StreamStartedMessage extends BaseMessage {
89
+ type: 'stream_started';
90
+ config: VideoConfig;
91
+ participant_id: string;
92
+ }
93
+ export interface StreamStoppedMessage extends BaseMessage {
94
+ type: 'stream_stopped';
95
+ participant_id: string;
96
+ reason?: string;
97
+ }
98
+ export interface RecoveryTriggeredMessage extends BaseMessage {
99
+ type: 'recovery_triggered';
100
+ policy: RecoveryPolicy;
101
+ reason: string;
102
+ }
103
+ export interface HeartbeatMessage extends BaseMessage {
104
+ type: 'heartbeat';
105
+ }
106
+ export interface HeartbeatAckMessage extends BaseMessage {
107
+ type: 'heartbeat_ack';
108
+ }
109
+ export interface EmergencyStopMessage extends BaseMessage {
110
+ type: 'emergency_stop';
111
+ reason: string;
112
+ source?: string;
113
+ }
114
+ export interface JoinedMessage extends BaseMessage {
115
+ type: 'joined';
116
+ room_id: string;
117
+ role: ParticipantRole;
118
+ }
119
+ export interface ErrorMessage extends BaseMessage {
120
+ type: 'error';
121
+ message: string;
122
+ code?: string;
123
+ }
124
+ export interface ParticipantJoinedMessage extends BaseMessage {
125
+ type: 'participant_joined';
126
+ room_id: string;
127
+ participant_id: string;
128
+ role: ParticipantRole;
129
+ }
130
+ export interface ParticipantLeftMessage extends BaseMessage {
131
+ type: 'participant_left';
132
+ room_id: string;
133
+ participant_id: string;
134
+ role: ParticipantRole;
135
+ }
136
+ export interface WebRTCOfferMessage extends BaseMessage {
137
+ type: 'webrtc_offer';
138
+ offer: RTCSessionDescriptionInit;
139
+ from_producer: string;
140
+ }
141
+ export interface WebRTCAnswerMessage extends BaseMessage {
142
+ type: 'webrtc_answer';
143
+ answer: RTCSessionDescriptionInit;
144
+ from_consumer: string;
145
+ }
146
+ export interface WebRTCIceMessage extends BaseMessage {
147
+ type: 'webrtc_ice';
148
+ candidate: RTCIceCandidateInit;
149
+ from_producer?: string;
150
+ from_consumer?: string;
151
+ }
152
+ export interface StatusUpdateMessage extends BaseMessage {
153
+ type: 'status_update';
154
+ status: string;
155
+ data?: Record<string, unknown>;
156
+ }
157
+ export interface StreamStatsMessage extends BaseMessage {
158
+ type: 'stream_stats';
159
+ stats: StreamStats;
160
+ }
161
+ export type WebSocketMessage = FrameUpdateMessage | VideoConfigUpdateMessage | StreamStartedMessage | StreamStoppedMessage | RecoveryTriggeredMessage | HeartbeatMessage | HeartbeatAckMessage | EmergencyStopMessage | JoinedMessage | ErrorMessage | ParticipantJoinedMessage | ParticipantLeftMessage | WebRTCOfferMessage | WebRTCAnswerMessage | WebRTCIceMessage | StatusUpdateMessage | StreamStatsMessage;
162
+ export interface ApiResponse<T = unknown> {
163
+ success: boolean;
164
+ data?: T;
165
+ error?: string;
166
+ message?: string;
167
+ }
168
+ export interface ListRoomsResponse {
169
+ success: boolean;
170
+ workspace_id: string;
171
+ rooms: RoomInfo[];
172
+ total: number;
173
+ }
174
+ export interface CreateRoomResponse {
175
+ success: boolean;
176
+ workspace_id: string;
177
+ room_id: string;
178
+ message: string;
179
+ }
180
+ export interface GetRoomResponse {
181
+ success: boolean;
182
+ workspace_id: string;
183
+ room: RoomInfo;
184
+ }
185
+ export interface GetRoomStateResponse {
186
+ success: boolean;
187
+ workspace_id: string;
188
+ state: RoomState;
189
+ }
190
+ export interface DeleteRoomResponse {
191
+ success: boolean;
192
+ workspace_id: string;
193
+ message: string;
194
+ }
195
+ export interface WebRTCSignalResponse {
196
+ success: boolean;
197
+ workspace_id: string;
198
+ response?: RTCSessionDescriptionInit | RTCIceCandidateInit;
199
+ message?: string;
200
+ }
201
+ export interface CreateRoomRequest {
202
+ room_id?: string;
203
+ workspace_id?: string;
204
+ name?: string;
205
+ config?: VideoConfig;
206
+ recovery_config?: RecoveryConfig;
207
+ max_consumers?: number;
208
+ }
209
+ export interface WebRTCSignalRequest {
210
+ client_id: string;
211
+ message: RTCSessionDescriptionInit | RTCIceCandidateInit | Record<string, unknown>;
212
+ }
213
+ export interface JoinMessage {
214
+ participant_id: string;
215
+ role: ParticipantRole;
216
+ }
217
+ export interface WebRTCConfig {
218
+ iceServers?: RTCIceServer[];
219
+ constraints?: MediaStreamConstraints;
220
+ bitrate?: number;
221
+ framerate?: number;
222
+ resolution?: Resolution;
223
+ codecPreferences?: string[];
224
+ }
225
+ export interface WebRTCStats {
226
+ videoBitsPerSecond: number;
227
+ framesPerSecond: number;
228
+ frameWidth: number;
229
+ frameHeight: number;
230
+ packetsLost: number;
231
+ totalPackets: number;
232
+ }
233
+ export type FrameUpdateCallback = (frame: FrameData) => void;
234
+ export type VideoConfigUpdateCallback = (config: VideoConfig) => void;
235
+ export type StreamStartedCallback = (config: VideoConfig, participantId: string) => void;
236
+ export type StreamStoppedCallback = (participantId: string, reason?: string) => void;
237
+ export type RecoveryTriggeredCallback = (policy: RecoveryPolicy, reason: string) => void;
238
+ export type StatusUpdateCallback = (status: string, data?: Record<string, unknown>) => void;
239
+ export type StreamStatsCallback = (stats: StreamStats) => void;
240
+ export type ErrorCallback = (error: string) => void;
241
+ export type ConnectedCallback = () => void;
242
+ export type DisconnectedCallback = () => void;
243
+ export interface ClientOptions {
244
+ base_url?: string;
245
+ timeout?: number;
246
+ reconnect_attempts?: number;
247
+ heartbeat_interval?: number;
248
+ webrtc_config?: WebRTCConfig;
249
+ }
client/js/tsconfig.json CHANGED
@@ -6,7 +6,6 @@
6
  "moduleResolution": "bundler",
7
  "allowImportingTsExtensions": true,
8
  "verbatimModuleSyntax": true,
9
- "noEmit": true,
10
  "declaration": true,
11
  "emitDeclarationOnly": true,
12
  "outDir": "dist",
 
6
  "moduleResolution": "bundler",
7
  "allowImportingTsExtensions": true,
8
  "verbatimModuleSyntax": true,
 
9
  "declaration": true,
10
  "emitDeclarationOnly": true,
11
  "outDir": "dist",