@robosystems/client 0.1.12 → 0.1.13
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/extensions/OperationClient.js +237 -283
- package/extensions/QueryClient.js +175 -230
- package/extensions/SSEClient.js +138 -156
- package/extensions/config.js +51 -43
- package/extensions/hooks.js +289 -353
- package/extensions/index.js +98 -106
- package/package.json +1 -1
- package/prepare.js +15 -23
- package/extensions/OperationClient.d.js +0 -45
- package/extensions/QueryClient.d.js +0 -22
- package/extensions/SSEClient.d.js +0 -35
- package/extensions/config.d.js +0 -25
- package/extensions/hooks.d.js +0 -80
- package/extensions/index.d.js +0 -35
package/extensions/SSEClient.js
CHANGED
|
@@ -1,166 +1,148 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
1
|
+
'use client';
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.SSEClient = exports.EventType = void 0;
|
|
5
|
+
var EventType;
|
|
6
|
+
(function (EventType) {
|
|
7
|
+
EventType["OPERATION_STARTED"] = "operation_started";
|
|
8
|
+
EventType["OPERATION_PROGRESS"] = "operation_progress";
|
|
9
|
+
EventType["OPERATION_COMPLETED"] = "operation_completed";
|
|
10
|
+
EventType["OPERATION_ERROR"] = "operation_error";
|
|
11
|
+
EventType["OPERATION_CANCELLED"] = "operation_cancelled";
|
|
12
|
+
EventType["DATA_CHUNK"] = "data_chunk";
|
|
13
|
+
EventType["METADATA"] = "metadata";
|
|
14
|
+
EventType["HEARTBEAT"] = "heartbeat";
|
|
15
|
+
EventType["QUEUE_UPDATE"] = "queue_update";
|
|
16
|
+
})(EventType || (exports.EventType = EventType = {}));
|
|
17
|
+
class SSEClient {
|
|
18
|
+
constructor(config) {
|
|
19
|
+
this.reconnectAttempts = 0;
|
|
20
|
+
this.closed = false;
|
|
21
|
+
this.listeners = new Map();
|
|
22
|
+
this.config = {
|
|
23
|
+
maxRetries: 5,
|
|
24
|
+
retryDelay: 1000,
|
|
25
|
+
heartbeatInterval: 30000,
|
|
26
|
+
...config,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
async connect(operationId, fromSequence = 0) {
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
const url = `${this.config.baseUrl}/v1/operations/${operationId}/stream?from_sequence=${fromSequence}`;
|
|
32
|
+
this.eventSource = new EventSource(url, {
|
|
33
|
+
withCredentials: this.config.credentials === 'include',
|
|
34
|
+
});
|
|
35
|
+
const connectionTimeout = setTimeout(() => {
|
|
36
|
+
reject(new Error('Connection timeout'));
|
|
37
|
+
this.close();
|
|
38
|
+
}, 10000);
|
|
39
|
+
this.eventSource.onopen = () => {
|
|
40
|
+
clearTimeout(connectionTimeout);
|
|
41
|
+
this.reconnectAttempts = 0;
|
|
42
|
+
this.emit('connected', null);
|
|
43
|
+
resolve();
|
|
44
|
+
};
|
|
45
|
+
this.eventSource.onerror = (error) => {
|
|
46
|
+
clearTimeout(connectionTimeout);
|
|
47
|
+
if (!this.closed) {
|
|
48
|
+
this.handleError(error, operationId, fromSequence);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
this.eventSource.onmessage = (event) => {
|
|
52
|
+
this.handleMessage(event);
|
|
53
|
+
};
|
|
54
|
+
// Set up specific event listeners
|
|
55
|
+
Object.values(EventType).forEach((eventType) => {
|
|
56
|
+
this.eventSource.addEventListener(eventType, (event) => {
|
|
57
|
+
this.handleTypedEvent(eventType, event);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
handleMessage(event) {
|
|
63
|
+
try {
|
|
64
|
+
const data = JSON.parse(event.data);
|
|
65
|
+
const sseEvent = {
|
|
66
|
+
event: event.type || 'message',
|
|
67
|
+
data,
|
|
68
|
+
id: event.lastEventId,
|
|
69
|
+
timestamp: new Date(),
|
|
70
|
+
};
|
|
71
|
+
this.lastEventId = event.lastEventId;
|
|
72
|
+
this.emit('event', sseEvent);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
this.emit('parse_error', { error, rawData: event.data });
|
|
76
|
+
}
|
|
38
77
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
this.eventSource.onopen = () => {
|
|
55
|
-
clearTimeout(connectionTimeout)
|
|
56
|
-
this.reconnectAttempts = 0
|
|
57
|
-
this.emit('connected', null)
|
|
58
|
-
resolve()
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
this.eventSource.onerror = (error) => {
|
|
62
|
-
clearTimeout(connectionTimeout)
|
|
63
|
-
if (!this.closed) {
|
|
64
|
-
this.handleError(error, operationId, fromSequence)
|
|
78
|
+
handleTypedEvent(eventType, event) {
|
|
79
|
+
try {
|
|
80
|
+
const data = JSON.parse(event.data);
|
|
81
|
+
this.lastEventId = event.lastEventId;
|
|
82
|
+
this.emit(eventType, data);
|
|
83
|
+
// Check for completion events
|
|
84
|
+
if (eventType === EventType.OPERATION_COMPLETED ||
|
|
85
|
+
eventType === EventType.OPERATION_ERROR ||
|
|
86
|
+
eventType === EventType.OPERATION_CANCELLED) {
|
|
87
|
+
this.close();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
this.emit('parse_error', { error, rawData: event.data });
|
|
65
92
|
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
this.eventSource.onmessage = (event) => {
|
|
69
|
-
this.handleMessage(event)
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Set up specific event listeners
|
|
73
|
-
Object.values(EventType).forEach((eventType) => {
|
|
74
|
-
this.eventSource!.addEventListener(eventType, (event) => {
|
|
75
|
-
this.handleTypedEvent(eventType, event)
|
|
76
|
-
})
|
|
77
|
-
})
|
|
78
|
-
})
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
private handleMessage(event) {
|
|
82
|
-
try {
|
|
83
|
-
const data = JSON.parse(event.data)
|
|
84
|
-
const sseEvent = {
|
|
85
|
-
event.type || 'message',
|
|
86
|
-
data,
|
|
87
|
-
id.lastEventId,
|
|
88
|
-
timestamp Date(),
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
this.lastEventId = event.lastEventId
|
|
92
|
-
this.emit('event', sseEvent)
|
|
93
|
-
} catch (error) {
|
|
94
|
-
this.emit('parse_error', { error, rawData.data })
|
|
95
93
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
94
|
+
async handleError(error, operationId, fromSequence) {
|
|
95
|
+
if (this.closed)
|
|
96
|
+
return;
|
|
97
|
+
if (this.reconnectAttempts < this.config.maxRetries) {
|
|
98
|
+
this.reconnectAttempts++;
|
|
99
|
+
const delay = this.config.retryDelay * Math.pow(2, this.reconnectAttempts - 1);
|
|
100
|
+
this.emit('reconnecting', {
|
|
101
|
+
attempt: this.reconnectAttempts,
|
|
102
|
+
delay,
|
|
103
|
+
lastEventId: this.lastEventId,
|
|
104
|
+
});
|
|
105
|
+
setTimeout(() => {
|
|
106
|
+
const resumeFrom = this.lastEventId ? parseInt(this.lastEventId) + 1 : fromSequence;
|
|
107
|
+
this.connect(operationId, resumeFrom).catch(() => {
|
|
108
|
+
// Error handled in connect
|
|
109
|
+
});
|
|
110
|
+
}, delay);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
this.emit('max_retries_exceeded', error);
|
|
114
|
+
this.close();
|
|
115
|
+
}
|
|
114
116
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (this.reconnectAttempts {
|
|
121
|
-
const resumeFrom = this.lastEventId ? parseInt(this.lastEventId) + 1
|
|
122
|
-
this.connect(operationId, resumeFrom).catch(() => {
|
|
123
|
-
// Error handled in connect
|
|
124
|
-
})
|
|
125
|
-
}, delay)
|
|
126
|
-
} else {
|
|
127
|
-
this.emit('max_retries_exceeded', error)
|
|
128
|
-
this.close()
|
|
117
|
+
on(event, listener) {
|
|
118
|
+
if (!this.listeners.has(event)) {
|
|
119
|
+
this.listeners.set(event, new Set());
|
|
120
|
+
}
|
|
121
|
+
this.listeners.get(event).add(listener);
|
|
129
122
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
123
|
+
off(event, listener) {
|
|
124
|
+
const listeners = this.listeners.get(event);
|
|
125
|
+
if (listeners) {
|
|
126
|
+
listeners.delete(listener);
|
|
127
|
+
}
|
|
135
128
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (listeners) {
|
|
142
|
-
listeners.delete(listener)
|
|
129
|
+
emit(event, data) {
|
|
130
|
+
const listeners = this.listeners.get(event);
|
|
131
|
+
if (listeners) {
|
|
132
|
+
listeners.forEach((listener) => listener(data));
|
|
133
|
+
}
|
|
143
134
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
135
|
+
close() {
|
|
136
|
+
this.closed = true;
|
|
137
|
+
if (this.eventSource) {
|
|
138
|
+
this.eventSource.close();
|
|
139
|
+
this.eventSource = undefined;
|
|
140
|
+
}
|
|
141
|
+
this.emit('closed', null);
|
|
142
|
+
this.listeners.clear();
|
|
150
143
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
close() {
|
|
154
|
-
this.closed = true
|
|
155
|
-
if (this.eventSource) {
|
|
156
|
-
this.eventSource.close()
|
|
157
|
-
this.eventSource = undefined
|
|
144
|
+
isConnected() {
|
|
145
|
+
return this.eventSource !== undefined && this.eventSource.readyState === EventSource.OPEN;
|
|
158
146
|
}
|
|
159
|
-
this.emit('closed', null)
|
|
160
|
-
this.listeners.clear()
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
isConnected() {
|
|
164
|
-
return this.eventSource !== undefined && this.eventSource.readyState === EventSource.OPEN
|
|
165
|
-
}
|
|
166
147
|
}
|
|
148
|
+
exports.SSEClient = SSEClient;
|
package/extensions/config.js
CHANGED
|
@@ -1,66 +1,74 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
'use client';
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.setSDKExtensionsConfig = setSDKExtensionsConfig;
|
|
5
|
+
exports.getSDKExtensionsConfig = getSDKExtensionsConfig;
|
|
6
|
+
exports.resetSDKExtensionsConfig = resetSDKExtensionsConfig;
|
|
7
|
+
exports.getEnvironmentConfig = getEnvironmentConfig;
|
|
10
8
|
// Default configuration
|
|
11
9
|
const defaultConfig = {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
10
|
+
baseUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000',
|
|
11
|
+
credentials: 'include',
|
|
12
|
+
timeout: 30000,
|
|
13
|
+
maxRetries: 3,
|
|
14
|
+
retryDelay: 1000,
|
|
15
|
+
};
|
|
19
16
|
// Global configuration singleton
|
|
20
|
-
let globalConfig = { ...defaultConfig }
|
|
21
|
-
|
|
17
|
+
let globalConfig = { ...defaultConfig };
|
|
22
18
|
/**
|
|
23
19
|
* Set global configuration for SDK extensions
|
|
24
20
|
* @param config Partial configuration to merge with defaults
|
|
25
21
|
*/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
22
|
+
function setSDKExtensionsConfig(config) {
|
|
23
|
+
globalConfig = {
|
|
24
|
+
...globalConfig,
|
|
25
|
+
...config,
|
|
26
|
+
};
|
|
31
27
|
}
|
|
32
|
-
|
|
33
28
|
/**
|
|
34
29
|
* Get current SDK extensions configuration
|
|
35
30
|
* @returns Current configuration
|
|
36
31
|
*/
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
function getSDKExtensionsConfig() {
|
|
33
|
+
return { ...globalConfig };
|
|
39
34
|
}
|
|
40
|
-
|
|
41
35
|
/**
|
|
42
36
|
* Reset configuration to defaults
|
|
43
37
|
*/
|
|
44
|
-
|
|
45
|
-
|
|
38
|
+
function resetSDKExtensionsConfig() {
|
|
39
|
+
globalConfig = { ...defaultConfig };
|
|
46
40
|
}
|
|
47
|
-
|
|
48
41
|
/**
|
|
49
42
|
* Get configuration for a specific environment
|
|
50
43
|
* @param env Environment name (production, staging, development)
|
|
51
44
|
* @returns Environment-specific configuration
|
|
52
45
|
*/
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
46
|
+
function getEnvironmentConfig(env = 'development') {
|
|
47
|
+
const baseConfigs = {
|
|
48
|
+
production: {
|
|
49
|
+
baseUrl: process.env.NEXT_PUBLIC_API_URL || 'https://api.robosystems.ai',
|
|
50
|
+
credentials: 'include',
|
|
51
|
+
timeout: 60000,
|
|
52
|
+
maxRetries: 5,
|
|
53
|
+
retryDelay: 2000,
|
|
54
|
+
},
|
|
55
|
+
staging: {
|
|
56
|
+
baseUrl: process.env.NEXT_PUBLIC_API_URL || 'https://staging-api.robosystems.ai',
|
|
57
|
+
credentials: 'include',
|
|
58
|
+
timeout: 45000,
|
|
59
|
+
maxRetries: 3,
|
|
60
|
+
retryDelay: 1500,
|
|
61
|
+
},
|
|
62
|
+
development: {
|
|
63
|
+
baseUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000',
|
|
64
|
+
credentials: 'include',
|
|
65
|
+
timeout: 30000,
|
|
66
|
+
maxRetries: 3,
|
|
67
|
+
retryDelay: 1000,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
return {
|
|
71
|
+
...defaultConfig,
|
|
72
|
+
...baseConfigs[env],
|
|
73
|
+
};
|
|
66
74
|
}
|