oblien 1.3.0 → 2.0.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 (187) hide show
  1. package/README.md +482 -422
  2. package/dist/client.d.ts +31 -0
  3. package/dist/client.d.ts.map +1 -0
  4. package/dist/client.js +33 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/error.d.ts +29 -0
  7. package/dist/error.d.ts.map +1 -0
  8. package/dist/error.js +52 -0
  9. package/dist/error.js.map +1 -0
  10. package/dist/http.d.ts +20 -0
  11. package/dist/http.d.ts.map +1 -0
  12. package/dist/http.js +108 -0
  13. package/dist/http.js.map +1 -0
  14. package/dist/index.d.ts +8 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +10 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/resources/api-access.d.ts +21 -0
  19. package/dist/resources/api-access.d.ts.map +1 -0
  20. package/dist/resources/api-access.js +32 -0
  21. package/dist/resources/api-access.js.map +1 -0
  22. package/dist/resources/base.d.ts +17 -0
  23. package/dist/resources/base.d.ts.map +1 -0
  24. package/dist/resources/base.js +21 -0
  25. package/dist/resources/base.js.map +1 -0
  26. package/dist/resources/images.d.ts +11 -0
  27. package/dist/resources/images.d.ts.map +1 -0
  28. package/dist/resources/images.js +16 -0
  29. package/dist/resources/images.js.map +1 -0
  30. package/dist/resources/lifecycle.d.ts +23 -0
  31. package/dist/resources/lifecycle.d.ts.map +1 -0
  32. package/dist/resources/lifecycle.js +32 -0
  33. package/dist/resources/lifecycle.js.map +1 -0
  34. package/dist/resources/logs.d.ts +25 -0
  35. package/dist/resources/logs.d.ts.map +1 -0
  36. package/dist/resources/logs.js +51 -0
  37. package/dist/resources/logs.js.map +1 -0
  38. package/dist/resources/metadata.d.ts +15 -0
  39. package/dist/resources/metadata.d.ts.map +1 -0
  40. package/dist/resources/metadata.js +20 -0
  41. package/dist/resources/metadata.js.map +1 -0
  42. package/dist/resources/metrics.d.ts +17 -0
  43. package/dist/resources/metrics.d.ts.map +1 -0
  44. package/dist/resources/metrics.js +27 -0
  45. package/dist/resources/metrics.js.map +1 -0
  46. package/dist/resources/network.d.ts +17 -0
  47. package/dist/resources/network.d.ts.map +1 -0
  48. package/dist/resources/network.js +20 -0
  49. package/dist/resources/network.js.map +1 -0
  50. package/dist/resources/public-access.d.ts +15 -0
  51. package/dist/resources/public-access.d.ts.map +1 -0
  52. package/dist/resources/public-access.js +21 -0
  53. package/dist/resources/public-access.js.map +1 -0
  54. package/dist/resources/resources.d.ts +15 -0
  55. package/dist/resources/resources.d.ts.map +1 -0
  56. package/dist/resources/resources.js +20 -0
  57. package/dist/resources/resources.js.map +1 -0
  58. package/dist/resources/snapshots.d.ts +27 -0
  59. package/dist/resources/snapshots.d.ts.map +1 -0
  60. package/dist/resources/snapshots.js +45 -0
  61. package/dist/resources/snapshots.js.map +1 -0
  62. package/dist/resources/ssh.d.ts +19 -0
  63. package/dist/resources/ssh.d.ts.map +1 -0
  64. package/dist/resources/ssh.js +28 -0
  65. package/dist/resources/ssh.js.map +1 -0
  66. package/dist/resources/usage.d.ts +25 -0
  67. package/dist/resources/usage.d.ts.map +1 -0
  68. package/dist/resources/usage.js +44 -0
  69. package/dist/resources/usage.js.map +1 -0
  70. package/dist/resources/workloads.d.ts +39 -0
  71. package/dist/resources/workloads.d.ts.map +1 -0
  72. package/dist/resources/workloads.js +83 -0
  73. package/dist/resources/workloads.js.map +1 -0
  74. package/dist/runtime/exec.d.ts +71 -0
  75. package/dist/runtime/exec.d.ts.map +1 -0
  76. package/dist/runtime/exec.js +163 -0
  77. package/dist/runtime/exec.js.map +1 -0
  78. package/dist/runtime/files.d.ts +39 -0
  79. package/dist/runtime/files.d.ts.map +1 -0
  80. package/dist/runtime/files.js +143 -0
  81. package/dist/runtime/files.js.map +1 -0
  82. package/dist/runtime/search.d.ts +23 -0
  83. package/dist/runtime/search.d.ts.map +1 -0
  84. package/dist/runtime/search.js +65 -0
  85. package/dist/runtime/search.js.map +1 -0
  86. package/dist/runtime/terminal.d.ts +29 -0
  87. package/dist/runtime/terminal.d.ts.map +1 -0
  88. package/dist/runtime/terminal.js +58 -0
  89. package/dist/runtime/terminal.js.map +1 -0
  90. package/dist/runtime/watcher.d.ts +27 -0
  91. package/dist/runtime/watcher.d.ts.map +1 -0
  92. package/dist/runtime/watcher.js +53 -0
  93. package/dist/runtime/watcher.js.map +1 -0
  94. package/dist/runtime/ws.d.ts +92 -0
  95. package/dist/runtime/ws.d.ts.map +1 -0
  96. package/dist/runtime/ws.js +228 -0
  97. package/dist/runtime/ws.js.map +1 -0
  98. package/dist/runtime-http.d.ts +35 -0
  99. package/dist/runtime-http.d.ts.map +1 -0
  100. package/dist/runtime-http.js +99 -0
  101. package/dist/runtime-http.js.map +1 -0
  102. package/dist/runtime.d.ts +77 -0
  103. package/dist/runtime.d.ts.map +1 -0
  104. package/dist/runtime.js +97 -0
  105. package/dist/runtime.js.map +1 -0
  106. package/dist/types/client.d.ts +7 -0
  107. package/dist/types/client.d.ts.map +1 -0
  108. package/dist/types/client.js +3 -0
  109. package/dist/types/client.js.map +1 -0
  110. package/dist/types/common.d.ts +13 -0
  111. package/dist/types/common.d.ts.map +1 -0
  112. package/dist/types/common.js +3 -0
  113. package/dist/types/common.js.map +1 -0
  114. package/dist/types/index.d.ts +8 -0
  115. package/dist/types/index.d.ts.map +1 -0
  116. package/dist/types/index.js +2 -0
  117. package/dist/types/index.js.map +1 -0
  118. package/dist/types/network.d.ts +15 -0
  119. package/dist/types/network.d.ts.map +1 -0
  120. package/dist/types/network.js +3 -0
  121. package/dist/types/network.js.map +1 -0
  122. package/dist/types/resources.d.ts +10 -0
  123. package/dist/types/resources.d.ts.map +1 -0
  124. package/dist/types/resources.js +3 -0
  125. package/dist/types/resources.js.map +1 -0
  126. package/dist/types/runtime.d.ts +302 -0
  127. package/dist/types/runtime.d.ts.map +1 -0
  128. package/dist/types/runtime.js +3 -0
  129. package/dist/types/runtime.js.map +1 -0
  130. package/dist/types/workspace-resources.d.ts +186 -0
  131. package/dist/types/workspace-resources.d.ts.map +1 -0
  132. package/dist/types/workspace-resources.js +3 -0
  133. package/dist/types/workspace-resources.js.map +1 -0
  134. package/dist/types/workspace.d.ts +41 -0
  135. package/dist/types/workspace.d.ts.map +1 -0
  136. package/dist/types/workspace.js +3 -0
  137. package/dist/types/workspace.js.map +1 -0
  138. package/dist/workspace.d.ts +135 -0
  139. package/dist/workspace.d.ts.map +1 -0
  140. package/dist/workspace.js +194 -0
  141. package/dist/workspace.js.map +1 -0
  142. package/package.json +30 -69
  143. package/LICENSE +0 -21
  144. package/agents.js +0 -14
  145. package/browser.js +0 -6
  146. package/cdn.js +0 -6
  147. package/chat.js +0 -21
  148. package/credits.js +0 -11
  149. package/icons.js +0 -11
  150. package/index.d.ts +0 -986
  151. package/index.js +0 -63
  152. package/namespaces.js +0 -12
  153. package/sandbox.js +0 -12
  154. package/search.js +0 -11
  155. package/src/agents/agent.js +0 -229
  156. package/src/agents/index.js +0 -227
  157. package/src/agents/settings.js +0 -100
  158. package/src/agents/tools.js +0 -155
  159. package/src/browser/index.js +0 -474
  160. package/src/cdn/index.js +0 -769
  161. package/src/chat/index.js +0 -724
  162. package/src/chat/session.js +0 -93
  163. package/src/client.js +0 -175
  164. package/src/credits/index.js +0 -492
  165. package/src/icons/index.js +0 -185
  166. package/src/namespaces/index.js +0 -236
  167. package/src/namespaces/namespace.js +0 -274
  168. package/src/sandbox/core/api/base.js +0 -89
  169. package/src/sandbox/core/api/database.js +0 -340
  170. package/src/sandbox/core/api/files.js +0 -141
  171. package/src/sandbox/core/api/git.js +0 -174
  172. package/src/sandbox/core/api/search.js +0 -29
  173. package/src/sandbox/core/api/snapshots.js +0 -132
  174. package/src/sandbox/core/api/terminal.js +0 -20
  175. package/src/sandbox/core/auth.js +0 -256
  176. package/src/sandbox/core/client.js +0 -197
  177. package/src/sandbox/core/index.js +0 -22
  178. package/src/sandbox/core/managers/terminal.js +0 -453
  179. package/src/sandbox/core/managers/watcher.js +0 -197
  180. package/src/sandbox/core/types.js +0 -92
  181. package/src/sandbox/core/utils/http.js +0 -89
  182. package/src/sandbox/core/websocket/connection.js +0 -479
  183. package/src/sandbox/index.d.ts +0 -542
  184. package/src/sandbox/index.js +0 -234
  185. package/src/sandbox/sandbox.js +0 -313
  186. package/src/search/index.js +0 -206
  187. package/src/utils/guest-manager.js +0 -454
@@ -1,92 +0,0 @@
1
- /**
2
- * Type definitions for the Sandbox SDK
3
- * These are JSDoc type definitions that can be used for IntelliSense
4
- */
5
-
6
- /**
7
- * @typedef {Object} SandboxConfig
8
- * @property {string} baseURL - Base URL of the sandbox API
9
- * @property {string} token - Authentication token
10
- */
11
-
12
- /**
13
- * @typedef {Object} FileListOptions
14
- * @property {string} dirPath - Directory path to list
15
- * @property {boolean} [recursive] - List recursively
16
- * @property {Array<string>} [ignorePatterns] - Patterns to ignore
17
- */
18
-
19
- /**
20
- * @typedef {Object} FileGetOptions
21
- * @property {string} filePath - File path to read
22
- * @property {Object} [range] - Line range {start, end}
23
- * @property {boolean} [withLineNumbers] - Include line numbers
24
- */
25
-
26
- /**
27
- * @typedef {Object} FileCreateOptions
28
- * @property {string} [parentPath] - Parent directory path
29
- * @property {string} [fileName] - File name
30
- * @property {string} [fullPath] - Full file path
31
- * @property {string} [filePath] - File path (alternative)
32
- * @property {string} [content] - File content
33
- * @property {boolean} [isFolder] - Create as folder
34
- * @property {boolean} [withWatcher=true] - Trigger file watcher
35
- */
36
-
37
- /**
38
- * @typedef {Object} FileDeleteOptions
39
- * @property {string} filePath - Path to delete
40
- * @property {boolean} [withWatcher=true] - Trigger file watcher
41
- */
42
-
43
- /**
44
- * @typedef {Object} FileRenameOptions
45
- * @property {string} sourcePath - Source path
46
- * @property {string} destinationPath - Destination path
47
- * @property {boolean} [withWatcher=true] - Trigger file watcher
48
- */
49
-
50
- /**
51
- * @typedef {Object} GitCloneOptions
52
- * @property {string} url - Repository URL
53
- * @property {string} targetDir - Target directory
54
- * @property {string} [branch] - Branch to clone
55
- * @property {Object} [auth] - Authentication config
56
- * @property {boolean} [root=true] - Clone at root
57
- */
58
-
59
- /**
60
- * @typedef {Object} GitCommitOptions
61
- * @property {string} repoPath - Repository path
62
- * @property {string} message - Commit message
63
- * @property {Object} [author] - Author info {name, email}
64
- */
65
-
66
- /**
67
- * @typedef {Object} SearchOptions
68
- * @property {string} query - Search query
69
- * @property {Object} [options] - Search options
70
- */
71
-
72
- /**
73
- * @typedef {Object} TerminalOptions
74
- * @property {string} command - Command to execute
75
- * @property {string} [cwd] - Working directory
76
- * @property {Object} [env] - Environment variables
77
- * @property {number} [timeout] - Execution timeout
78
- */
79
-
80
- /**
81
- * @typedef {Object} SnapshotCommitOptions
82
- * @property {string} message - Commit message
83
- */
84
-
85
- /**
86
- * @typedef {Object} SnapshotArchiveOptions
87
- * @property {string} id - Archive ID
88
- * @property {Object} [options] - Additional options
89
- */
90
-
91
- export default {};
92
-
@@ -1,89 +0,0 @@
1
- /**
2
- * HTTP utilities for making API requests
3
- */
4
-
5
- /**
6
- * Makes an HTTP request with proper error handling
7
- * @param {string} url - The URL to request
8
- * @param {Object} options - Fetch options
9
- * @returns {Promise<any>} Response data
10
- * @throws {Error} If request fails
11
- */
12
- export async function request(url, options = {}) {
13
- try {
14
- const response = await fetch(url, {
15
- ...options,
16
- headers: {
17
- 'Content-Type': 'application/json',
18
- ...options.headers,
19
- },
20
- });
21
-
22
- const data = await response.json();
23
-
24
- return data;
25
- } catch (error) {
26
- console.log(error)
27
- return {
28
- success: false,
29
- error: error.message || 'An unexpected error occurred',
30
- }
31
- }
32
- }
33
-
34
- /**
35
- * Makes a GET request
36
- * @param {string} url - The URL to request
37
- * @param {Object} headers - Additional headers
38
- * @returns {Promise<any>} Response data
39
- */
40
- export async function get(url, headers = {}) {
41
- return request(url, {
42
- method: 'GET',
43
- headers,
44
- });
45
- }
46
-
47
- /**
48
- * Makes a POST request
49
- * @param {string} url - The URL to request
50
- * @param {Object} body - Request body
51
- * @param {Object} headers - Additional headers
52
- * @returns {Promise<any>} Response data
53
- */
54
- export async function post(url, body = {}, headers = {}) {
55
- return request(url, {
56
- method: 'POST',
57
- headers,
58
- body: JSON.stringify(body),
59
- });
60
- }
61
-
62
- /**
63
- * Makes a PUT request
64
- * @param {string} url - The URL to request
65
- * @param {Object} body - Request body
66
- * @param {Object} headers - Additional headers
67
- * @returns {Promise<any>} Response data
68
- */
69
- export async function put(url, body = {}, headers = {}) {
70
- return request(url, {
71
- method: 'PUT',
72
- headers,
73
- body: JSON.stringify(body),
74
- });
75
- }
76
-
77
- /**
78
- * Makes a DELETE request
79
- * @param {string} url - The URL to request
80
- * @param {Object} headers - Additional headers
81
- * @returns {Promise<any>} Response data
82
- */
83
- export async function del(url, headers = {}) {
84
- return request(url, {
85
- method: 'DELETE',
86
- headers,
87
- });
88
- }
89
-
@@ -1,479 +0,0 @@
1
- /**
2
- * WebSocket Connection Manager
3
- * Central WebSocket connection handler for sandbox with retry logic and status checking
4
- * One connection per sandbox instance
5
- */
6
-
7
- export class WebSocketConnection {
8
- /**
9
- * @param {Object} config - Connection configuration
10
- * @param {string} config.baseURL - Sandbox base URL
11
- * @param {string} config.token - Sandbox authentication token
12
- * @param {string} [config.sandboxId] - Sandbox ID
13
- * @param {Function} [config.onStatusCheck] - Function to check if sandbox is active
14
- */
15
- constructor(config) {
16
- this.baseURL = config.baseURL;
17
- this.token = config.token;
18
- this.sandboxId = config.sandboxId;
19
- this.onStatusCheck = config.onStatusCheck;
20
-
21
- // Connection state
22
- this.ws = null;
23
- this.isConnected = false;
24
- this.isConnecting = false;
25
- this.shouldReconnect = true;
26
-
27
- // Retry configuration
28
- this.reconnectAttempts = 0;
29
- this.maxReconnectAttempts = 10;
30
- this.baseReconnectDelay = 1000; // 1 second
31
- this.maxReconnectDelay = 30000; // 30 seconds
32
- this.reconnectTimeout = null;
33
-
34
- // Request/response handling
35
- this.pendingRequests = new Map();
36
- this.requestTimeout = 30000; // 30 seconds
37
-
38
- // Event handling
39
- this.eventHandlers = new Map();
40
-
41
- // Connection options
42
- this.connectionOptions = {
43
- binary: true,
44
- silent: false
45
- };
46
- }
47
-
48
- /**
49
- * Connect to WebSocket with retry logic
50
- * @param {Object} [options] - Connection options
51
- * @param {boolean} [options.binary] - Enable binary mode
52
- * @param {boolean} [options.silent] - Silent mode (no broadcasts)
53
- * @returns {Promise<void>}
54
- */
55
- async connect(options = {}) {
56
- // Merge options
57
- this.connectionOptions = { ...this.connectionOptions, ...options };
58
-
59
- // Check if already connected
60
- if (this.isConnected) {
61
- return;
62
- }
63
-
64
- // Check if already connecting
65
- if (this.isConnecting) {
66
- return new Promise((resolve, reject) => {
67
- const checkInterval = setInterval(() => {
68
- if (this.isConnected) {
69
- clearInterval(checkInterval);
70
- resolve();
71
- } else if (!this.isConnecting) {
72
- clearInterval(checkInterval);
73
- reject(new Error('Connection failed'));
74
- }
75
- }, 100);
76
-
77
- setTimeout(() => {
78
- clearInterval(checkInterval);
79
- reject(new Error('Connection timeout'));
80
- }, 10000);
81
- });
82
- }
83
-
84
- // Check sandbox status before connecting
85
- if (this.onStatusCheck) {
86
- try {
87
- const isActive = await this.onStatusCheck();
88
- if (!isActive) {
89
- throw new Error('Sandbox is not active');
90
- }
91
- } catch (error) {
92
- console.error('Sandbox status check failed:', error.message);
93
- throw error;
94
- }
95
- }
96
-
97
- return this._connect();
98
- }
99
-
100
- /**
101
- * Internal connection logic
102
- * @private
103
- */
104
- async _connect() {
105
- return new Promise((resolve, reject) => {
106
- this.isConnecting = true;
107
-
108
- try {
109
- // Remove path and trailing slash from baseURL
110
- let wsUrl = this.baseURL.replace(/^http/, 'ws').replace(/\/$/, '');
111
-
112
- const queryParams = new URLSearchParams();
113
-
114
- // Add token as query parameter (works in both Node.js and browser)
115
- queryParams.append('token', this.token);
116
-
117
- if (this.connectionOptions.binary) {
118
- queryParams.append('binary', 'true');
119
- }
120
-
121
- if (this.connectionOptions.silent) {
122
- queryParams.append('silent', 'true');
123
- }
124
-
125
- const fullUrl = `${wsUrl}?${queryParams.toString()}`;
126
-
127
-
128
-
129
- // Check if we're in Node.js or browser
130
- const isNode = typeof process !== 'undefined' && process.versions?.node;
131
-
132
- if (isNode) {
133
- // Node.js: Can also use Authorization header
134
- this.ws = new WebSocket(fullUrl, {
135
- headers: {
136
- 'Authorization': `Bearer ${this.token}`,
137
- ...(this.connectionOptions.silent && { 'x-notify-type': 'silent' })
138
- }
139
- });
140
- } else {
141
- // Browser: No custom headers support
142
- this.ws = new WebSocket(fullUrl);
143
- }
144
-
145
- this.ws.binaryType = 'arraybuffer';
146
-
147
- // Connection opened
148
- this.ws.onopen = () => {
149
-
150
- };
151
-
152
- // Handle messages
153
- this.ws.onmessage = (event) => {
154
- if (event.data instanceof ArrayBuffer) {
155
- this._handleBinaryMessage(event.data);
156
- } else {
157
- this._handleTextMessage(event.data);
158
- }
159
- };
160
-
161
- // Handle errors
162
- this.ws.onerror = (error) => {
163
- this.emit('error', error);
164
- };
165
-
166
- // Handle close
167
- this.ws.onclose = (event) => {
168
- const wasConnected = this.isConnected;
169
- this.isConnected = false;
170
- this.isConnecting = false;
171
-
172
- this.emit('close', { code: event.code, reason: event.reason });
173
-
174
- // Attempt reconnection if needed
175
- if (this.shouldReconnect && wasConnected) {
176
- this._scheduleReconnect();
177
- }
178
- };
179
-
180
- // Wait for connection confirmation
181
- const connectionTimeout = setTimeout(() => {
182
- this.isConnecting = false;
183
- resolve({ error: 'Connection timeout - no confirmation received, check sandbox status' });
184
- }, 10000);
185
-
186
- this.once('connected', () => {
187
- clearTimeout(connectionTimeout);
188
- this.isConnected = true;
189
- this.isConnecting = false;
190
- this.reconnectAttempts = 0; // Reset on successful connection
191
- resolve();
192
- });
193
-
194
- } catch (error) {
195
- this.isConnecting = false;
196
- resolve({ error: error.message });
197
- }
198
- });
199
- }
200
-
201
- /**
202
- * Schedule reconnection with exponential backoff
203
- * @private
204
- */
205
- _scheduleReconnect() {
206
- // Clear any existing timeout
207
- if (this.reconnectTimeout) {
208
- clearTimeout(this.reconnectTimeout);
209
- }
210
-
211
- // Check if we've exceeded max attempts
212
- if (this.reconnectAttempts >= this.maxReconnectAttempts) {
213
- this.emit('reconnect_failed');
214
- return;
215
- }
216
-
217
- // Calculate delay with exponential backoff
218
- const delay = Math.min(
219
- this.baseReconnectDelay * Math.pow(2, this.reconnectAttempts),
220
- this.maxReconnectDelay
221
- );
222
-
223
- this.reconnectAttempts++;
224
-
225
- this.reconnectTimeout = setTimeout(async () => {
226
- try {
227
- await this.connect(this.connectionOptions);
228
- this.emit('reconnected');
229
- } catch (error) {
230
- this._scheduleReconnect();
231
- }
232
- }, delay);
233
- }
234
-
235
- /**
236
- * Handle text messages
237
- * @private
238
- */
239
- _handleTextMessage(data) {
240
- try {
241
- const message = JSON.parse(data);
242
-
243
-
244
- // Handle connection confirmation
245
- if (message.type === 'connected') {
246
- this.emit('connected', message);
247
- return;
248
- }
249
-
250
- // Handle request responses (with requestId)
251
- if (message.requestId && this.pendingRequests.has(message.requestId)) {
252
- const { resolve, timeout, expectedTypes } = this.pendingRequests.get(message.requestId);
253
-
254
- // If expectedTypes is specified, only resolve on matching type
255
- if (expectedTypes && expectedTypes.length > 0) {
256
- if (expectedTypes.includes(message.type)) {
257
- clearTimeout(timeout);
258
- this.pendingRequests.delete(message.requestId);
259
- resolve(message);
260
- return;
261
- }
262
- // Not the expected type, emit as event but don't resolve
263
- } else {
264
- // No expected types, resolve on any message with requestId
265
- clearTimeout(timeout);
266
- this.pendingRequests.delete(message.requestId);
267
- resolve(message);
268
- return;
269
- }
270
- }
271
-
272
- // Emit event for general listeners
273
- this.emit(message.type, message);
274
- } catch (error) {
275
- }
276
- }
277
-
278
- /**
279
- * Handle binary messages (terminal output)
280
- * @private
281
- */
282
- _handleBinaryMessage(data) {
283
- const buffer = new Uint8Array(data);
284
- const terminalId = buffer[0];
285
- const output = buffer.slice(1);
286
-
287
- // Emit to terminal-specific handler
288
- this.emit(`terminal:${terminalId}`, output);
289
-
290
- // Emit to generic binary handler
291
- this.emit('binary', { terminalId, output });
292
- }
293
-
294
- /**
295
- * Send request and wait for response
296
- * @param {Object} message - Message to send
297
- * @param {Array<string>} [expectedTypes] - Expected response types (resolves on first match)
298
- * @returns {Promise<Object>} Response message
299
- */
300
- async sendRequest(message, expectedTypes = null) {
301
- if (!this.isConnected) {
302
- return { error: 'WebSocket not connected check sandbox status' };
303
- }
304
-
305
- return new Promise((resolve, reject) => {
306
- // Generate UUID for request ID
307
- const requestId = this._generateRequestId();
308
- const fullMessage = { ...message, requestId };
309
-
310
- // Determine expected response types based on action
311
- if (!expectedTypes) {
312
- expectedTypes = this._getExpectedResponseTypes(message.action || message.type);
313
- }
314
-
315
- // Set timeout for request
316
- const timeout = setTimeout(() => {
317
- if (this.pendingRequests.has(requestId)) {
318
- this.pendingRequests.delete(requestId);
319
- resolve({ error: 'Request timeout check sandbox status' });
320
- }
321
- }, this.requestTimeout);
322
-
323
- this.pendingRequests.set(requestId, { resolve, reject, timeout, expectedTypes });
324
-
325
- try {
326
- this.ws.send(JSON.stringify(fullMessage));
327
- } catch (error) {
328
- clearTimeout(timeout);
329
- this.pendingRequests.delete(requestId);
330
- resolve({ error: error.message });
331
- }
332
- });
333
- }
334
-
335
- /**
336
- * Generate unique request ID (UUID v4)
337
- * @private
338
- */
339
- _generateRequestId() {
340
- // Check if we're in Node.js or browser
341
- if (typeof crypto !== 'undefined' && crypto.randomUUID) {
342
- return crypto.randomUUID();
343
- } else if (typeof randomUUID !== 'undefined') {
344
- return randomUUID();
345
- } else {
346
- // Fallback for older environments
347
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
348
- const r = Math.random() * 16 | 0;
349
- const v = c === 'x' ? r : (r & 0x3 | 0x8);
350
- return v.toString(16);
351
- });
352
- }
353
- }
354
-
355
- /**
356
- * Get expected response types for a request action
357
- * @private
358
- */
359
- _getExpectedResponseTypes(action) {
360
- const responseMap = {
361
- 'terminal_create': ['terminal_created', 'terminal_error'],
362
- 'terminal_close': ['terminal_closed', 'terminal_error'],
363
- 'terminal_list': ['terminal_list', 'terminal_error'],
364
- 'get_state': ['terminal_state', 'terminal_error'],
365
- 'i': null, // input - no response expected
366
- 'r': ['terminal_resized', 'terminal_error']
367
- };
368
-
369
- return responseMap[action] || null;
370
- }
371
-
372
- /**
373
- * Send message without waiting for response
374
- * @param {Object} message - Message to send
375
- */
376
- send(message) {
377
- if (!this.isConnected) {
378
- return { error: 'WebSocket not connected' };
379
- }
380
- this.ws.send(JSON.stringify(message));
381
- }
382
-
383
- /**
384
- * Register event handler
385
- * @param {string} event - Event name
386
- * @param {Function} handler - Handler function
387
- */
388
- on(event, handler) {
389
- if (!this.eventHandlers.has(event)) {
390
- this.eventHandlers.set(event, []);
391
- }
392
- this.eventHandlers.get(event).push(handler);
393
- }
394
-
395
- /**
396
- * Register one-time event handler
397
- * @param {string} event - Event name
398
- * @param {Function} handler - Handler function
399
- */
400
- once(event, handler) {
401
- const wrapper = (...args) => {
402
- handler(...args);
403
- this.off(event, wrapper);
404
- };
405
- this.on(event, wrapper);
406
- }
407
-
408
- /**
409
- * Remove event handler
410
- * @param {string} event - Event name
411
- * @param {Function} handler - Handler function
412
- */
413
- off(event, handler) {
414
- if (this.eventHandlers.has(event)) {
415
- const handlers = this.eventHandlers.get(event);
416
- const index = handlers.indexOf(handler);
417
- if (index > -1) {
418
- handlers.splice(index, 1);
419
- }
420
- }
421
- }
422
-
423
- /**
424
- * Emit event
425
- * @private
426
- */
427
- emit(event, ...args) {
428
- if (this.eventHandlers.has(event)) {
429
- this.eventHandlers.get(event).forEach(handler => {
430
- try {
431
- handler(...args);
432
- } catch (error) {
433
-
434
- }
435
- });
436
- }
437
- }
438
-
439
- /**
440
- * Disconnect WebSocket
441
- */
442
- disconnect() {
443
- this.shouldReconnect = false;
444
-
445
- // Clear reconnect timeout
446
- if (this.reconnectTimeout) {
447
- clearTimeout(this.reconnectTimeout);
448
- this.reconnectTimeout = null;
449
- }
450
-
451
- // Reject all pending requests
452
- this.pendingRequests.forEach(({ reject, timeout }) => {
453
- clearTimeout(timeout);
454
- resolve({ error: 'Connection closed' });
455
- });
456
- this.pendingRequests.clear();
457
-
458
- // Close WebSocket
459
- if (this.ws) {
460
- this.ws.close();
461
- this.ws = null;
462
- }
463
-
464
- this.isConnected = false;
465
- this.isConnecting = false;
466
- this.reconnectAttempts = 0;
467
-
468
-
469
- }
470
-
471
- /**
472
- * Check if connected
473
- * @returns {boolean}
474
- */
475
- get connected() {
476
- return this.isConnected;
477
- }
478
- }
479
-