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.
- package/README.md +482 -422
- package/dist/client.d.ts +31 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +33 -0
- package/dist/client.js.map +1 -0
- package/dist/error.d.ts +29 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +52 -0
- package/dist/error.js.map +1 -0
- package/dist/http.d.ts +20 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +108 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/api-access.d.ts +21 -0
- package/dist/resources/api-access.d.ts.map +1 -0
- package/dist/resources/api-access.js +32 -0
- package/dist/resources/api-access.js.map +1 -0
- package/dist/resources/base.d.ts +17 -0
- package/dist/resources/base.d.ts.map +1 -0
- package/dist/resources/base.js +21 -0
- package/dist/resources/base.js.map +1 -0
- package/dist/resources/images.d.ts +11 -0
- package/dist/resources/images.d.ts.map +1 -0
- package/dist/resources/images.js +16 -0
- package/dist/resources/images.js.map +1 -0
- package/dist/resources/lifecycle.d.ts +23 -0
- package/dist/resources/lifecycle.d.ts.map +1 -0
- package/dist/resources/lifecycle.js +32 -0
- package/dist/resources/lifecycle.js.map +1 -0
- package/dist/resources/logs.d.ts +25 -0
- package/dist/resources/logs.d.ts.map +1 -0
- package/dist/resources/logs.js +51 -0
- package/dist/resources/logs.js.map +1 -0
- package/dist/resources/metadata.d.ts +15 -0
- package/dist/resources/metadata.d.ts.map +1 -0
- package/dist/resources/metadata.js +20 -0
- package/dist/resources/metadata.js.map +1 -0
- package/dist/resources/metrics.d.ts +17 -0
- package/dist/resources/metrics.d.ts.map +1 -0
- package/dist/resources/metrics.js +27 -0
- package/dist/resources/metrics.js.map +1 -0
- package/dist/resources/network.d.ts +17 -0
- package/dist/resources/network.d.ts.map +1 -0
- package/dist/resources/network.js +20 -0
- package/dist/resources/network.js.map +1 -0
- package/dist/resources/public-access.d.ts +15 -0
- package/dist/resources/public-access.d.ts.map +1 -0
- package/dist/resources/public-access.js +21 -0
- package/dist/resources/public-access.js.map +1 -0
- package/dist/resources/resources.d.ts +15 -0
- package/dist/resources/resources.d.ts.map +1 -0
- package/dist/resources/resources.js +20 -0
- package/dist/resources/resources.js.map +1 -0
- package/dist/resources/snapshots.d.ts +27 -0
- package/dist/resources/snapshots.d.ts.map +1 -0
- package/dist/resources/snapshots.js +45 -0
- package/dist/resources/snapshots.js.map +1 -0
- package/dist/resources/ssh.d.ts +19 -0
- package/dist/resources/ssh.d.ts.map +1 -0
- package/dist/resources/ssh.js +28 -0
- package/dist/resources/ssh.js.map +1 -0
- package/dist/resources/usage.d.ts +25 -0
- package/dist/resources/usage.d.ts.map +1 -0
- package/dist/resources/usage.js +44 -0
- package/dist/resources/usage.js.map +1 -0
- package/dist/resources/workloads.d.ts +39 -0
- package/dist/resources/workloads.d.ts.map +1 -0
- package/dist/resources/workloads.js +83 -0
- package/dist/resources/workloads.js.map +1 -0
- package/dist/runtime/exec.d.ts +71 -0
- package/dist/runtime/exec.d.ts.map +1 -0
- package/dist/runtime/exec.js +163 -0
- package/dist/runtime/exec.js.map +1 -0
- package/dist/runtime/files.d.ts +39 -0
- package/dist/runtime/files.d.ts.map +1 -0
- package/dist/runtime/files.js +143 -0
- package/dist/runtime/files.js.map +1 -0
- package/dist/runtime/search.d.ts +23 -0
- package/dist/runtime/search.d.ts.map +1 -0
- package/dist/runtime/search.js +65 -0
- package/dist/runtime/search.js.map +1 -0
- package/dist/runtime/terminal.d.ts +29 -0
- package/dist/runtime/terminal.d.ts.map +1 -0
- package/dist/runtime/terminal.js +58 -0
- package/dist/runtime/terminal.js.map +1 -0
- package/dist/runtime/watcher.d.ts +27 -0
- package/dist/runtime/watcher.d.ts.map +1 -0
- package/dist/runtime/watcher.js +53 -0
- package/dist/runtime/watcher.js.map +1 -0
- package/dist/runtime/ws.d.ts +92 -0
- package/dist/runtime/ws.d.ts.map +1 -0
- package/dist/runtime/ws.js +228 -0
- package/dist/runtime/ws.js.map +1 -0
- package/dist/runtime-http.d.ts +35 -0
- package/dist/runtime-http.d.ts.map +1 -0
- package/dist/runtime-http.js +99 -0
- package/dist/runtime-http.js.map +1 -0
- package/dist/runtime.d.ts +77 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +97 -0
- package/dist/runtime.js.map +1 -0
- package/dist/types/client.d.ts +7 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/client.js +3 -0
- package/dist/types/client.js.map +1 -0
- package/dist/types/common.d.ts +13 -0
- package/dist/types/common.d.ts.map +1 -0
- package/dist/types/common.js +3 -0
- package/dist/types/common.js.map +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/network.d.ts +15 -0
- package/dist/types/network.d.ts.map +1 -0
- package/dist/types/network.js +3 -0
- package/dist/types/network.js.map +1 -0
- package/dist/types/resources.d.ts +10 -0
- package/dist/types/resources.d.ts.map +1 -0
- package/dist/types/resources.js +3 -0
- package/dist/types/resources.js.map +1 -0
- package/dist/types/runtime.d.ts +302 -0
- package/dist/types/runtime.d.ts.map +1 -0
- package/dist/types/runtime.js +3 -0
- package/dist/types/runtime.js.map +1 -0
- package/dist/types/workspace-resources.d.ts +186 -0
- package/dist/types/workspace-resources.d.ts.map +1 -0
- package/dist/types/workspace-resources.js +3 -0
- package/dist/types/workspace-resources.js.map +1 -0
- package/dist/types/workspace.d.ts +41 -0
- package/dist/types/workspace.d.ts.map +1 -0
- package/dist/types/workspace.js +3 -0
- package/dist/types/workspace.js.map +1 -0
- package/dist/workspace.d.ts +135 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +194 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +30 -69
- package/LICENSE +0 -21
- package/agents.js +0 -14
- package/browser.js +0 -6
- package/cdn.js +0 -6
- package/chat.js +0 -21
- package/credits.js +0 -11
- package/icons.js +0 -11
- package/index.d.ts +0 -986
- package/index.js +0 -63
- package/namespaces.js +0 -12
- package/sandbox.js +0 -12
- package/search.js +0 -11
- package/src/agents/agent.js +0 -229
- package/src/agents/index.js +0 -227
- package/src/agents/settings.js +0 -100
- package/src/agents/tools.js +0 -155
- package/src/browser/index.js +0 -474
- package/src/cdn/index.js +0 -769
- package/src/chat/index.js +0 -724
- package/src/chat/session.js +0 -93
- package/src/client.js +0 -175
- package/src/credits/index.js +0 -492
- package/src/icons/index.js +0 -185
- package/src/namespaces/index.js +0 -236
- package/src/namespaces/namespace.js +0 -274
- package/src/sandbox/core/api/base.js +0 -89
- package/src/sandbox/core/api/database.js +0 -340
- package/src/sandbox/core/api/files.js +0 -141
- package/src/sandbox/core/api/git.js +0 -174
- package/src/sandbox/core/api/search.js +0 -29
- package/src/sandbox/core/api/snapshots.js +0 -132
- package/src/sandbox/core/api/terminal.js +0 -20
- package/src/sandbox/core/auth.js +0 -256
- package/src/sandbox/core/client.js +0 -197
- package/src/sandbox/core/index.js +0 -22
- package/src/sandbox/core/managers/terminal.js +0 -453
- package/src/sandbox/core/managers/watcher.js +0 -197
- package/src/sandbox/core/types.js +0 -92
- package/src/sandbox/core/utils/http.js +0 -89
- package/src/sandbox/core/websocket/connection.js +0 -479
- package/src/sandbox/index.d.ts +0 -542
- package/src/sandbox/index.js +0 -234
- package/src/sandbox/sandbox.js +0 -313
- package/src/search/index.js +0 -206
- 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
|
-
|