@daytonaio/sdk 0.19.0-alpha.3 → 0.19.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Daytona.d.ts +393 -0
- package/dist/Daytona.js +497 -0
- package/dist/FileSystem.d.ts +271 -0
- package/dist/FileSystem.js +298 -0
- package/dist/Git.d.ts +177 -0
- package/dist/Git.js +218 -0
- package/dist/Image.d.ts +261 -0
- package/dist/Image.js +563 -0
- package/dist/LspServer.d.ts +174 -0
- package/dist/LspServer.js +204 -0
- package/dist/ObjectStorage.d.ts +85 -0
- package/dist/ObjectStorage.js +227 -0
- package/dist/Process.d.ts +246 -0
- package/dist/Process.js +277 -0
- package/dist/Sandbox.d.ts +336 -0
- package/dist/Sandbox.js +344 -0
- package/dist/Volume.d.ts +79 -0
- package/dist/Volume.js +95 -0
- package/dist/code-toolbox/SandboxPythonCodeToolbox.d.ts +12 -0
- package/dist/code-toolbox/SandboxPythonCodeToolbox.js +360 -0
- package/dist/code-toolbox/SandboxTsCodeToolbox.d.ts +6 -0
- package/dist/code-toolbox/SandboxTsCodeToolbox.js +19 -0
- package/dist/errors/DaytonaError.d.ts +10 -0
- package/dist/errors/DaytonaError.js +19 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.js +41 -0
- package/dist/types/Charts.d.ts +151 -0
- package/dist/types/Charts.js +45 -0
- package/dist/types/ExecuteResponse.d.ts +26 -0
- package/dist/types/ExecuteResponse.js +6 -0
- package/dist/utils/ArtifactParser.d.ts +13 -0
- package/dist/utils/ArtifactParser.js +54 -0
- package/dist/utils/Path.d.ts +1 -0
- package/dist/utils/Path.js +60 -0
- package/dist/utils/Stream.d.ts +13 -0
- package/dist/utils/Stream.js +81 -0
- package/package.json +1 -1
package/dist/Daytona.js
ADDED
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2025 Daytona Platforms Inc.
|
|
4
|
+
* SPDX-License-Identifier: AGPL-3.0
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.Daytona = exports.CodeLanguage = void 0;
|
|
41
|
+
const api_client_1 = require("@daytonaio/api-client");
|
|
42
|
+
const axios_1 = __importStar(require("axios"));
|
|
43
|
+
const dotenv = __importStar(require("dotenv"));
|
|
44
|
+
const SandboxPythonCodeToolbox_1 = require("./code-toolbox/SandboxPythonCodeToolbox");
|
|
45
|
+
const SandboxTsCodeToolbox_1 = require("./code-toolbox/SandboxTsCodeToolbox");
|
|
46
|
+
const DaytonaError_1 = require("./errors/DaytonaError");
|
|
47
|
+
const Image_1 = require("./Image");
|
|
48
|
+
const ObjectStorage_1 = require("./ObjectStorage");
|
|
49
|
+
const Sandbox_1 = require("./Sandbox");
|
|
50
|
+
const Stream_1 = require("./utils/Stream");
|
|
51
|
+
const Volume_1 = require("./Volume");
|
|
52
|
+
/**
|
|
53
|
+
* Supported programming languages for code execution
|
|
54
|
+
*/
|
|
55
|
+
var CodeLanguage;
|
|
56
|
+
(function (CodeLanguage) {
|
|
57
|
+
CodeLanguage["PYTHON"] = "python";
|
|
58
|
+
CodeLanguage["TYPESCRIPT"] = "typescript";
|
|
59
|
+
CodeLanguage["JAVASCRIPT"] = "javascript";
|
|
60
|
+
})(CodeLanguage || (exports.CodeLanguage = CodeLanguage = {}));
|
|
61
|
+
/**
|
|
62
|
+
* Main class for interacting with the Daytona API.
|
|
63
|
+
* Provides methods for creating, managing, and interacting with Daytona Sandboxes.
|
|
64
|
+
* Can be initialized either with explicit configuration or using environment variables.
|
|
65
|
+
*
|
|
66
|
+
* @property {VolumeService} volume - Service for managing Daytona Volumes
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* // Using environment variables
|
|
70
|
+
* // Uses DAYTONA_API_KEY, DAYTONA_API_URL, DAYTONA_TARGET
|
|
71
|
+
* const daytona = new Daytona();
|
|
72
|
+
* const sandbox = await daytona.create();
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* // Using explicit configuration
|
|
76
|
+
* const config: DaytonaConfig = {
|
|
77
|
+
* apiKey: "your-api-key",
|
|
78
|
+
* apiUrl: "https://your-api.com",
|
|
79
|
+
* target: "us"
|
|
80
|
+
* };
|
|
81
|
+
* const daytona = new Daytona(config);
|
|
82
|
+
*
|
|
83
|
+
* @class
|
|
84
|
+
*/
|
|
85
|
+
class Daytona {
|
|
86
|
+
/**
|
|
87
|
+
* Creates a new Daytona client instance.
|
|
88
|
+
*
|
|
89
|
+
* @param {DaytonaConfig} [config] - Configuration options
|
|
90
|
+
* @throws {DaytonaError} - `DaytonaError` - When API key is missing
|
|
91
|
+
*/
|
|
92
|
+
constructor(config) {
|
|
93
|
+
this.remove = this.delete.bind(this);
|
|
94
|
+
dotenv.config();
|
|
95
|
+
dotenv.config({ path: '.env.local', override: true });
|
|
96
|
+
const apiKey = !(config === null || config === void 0 ? void 0 : config.apiKey) && (config === null || config === void 0 ? void 0 : config.jwtToken) ? undefined : (config === null || config === void 0 ? void 0 : config.apiKey) || (process === null || process === void 0 ? void 0 : process.env['DAYTONA_API_KEY']);
|
|
97
|
+
const jwtToken = (config === null || config === void 0 ? void 0 : config.jwtToken) || (process === null || process === void 0 ? void 0 : process.env['DAYTONA_JWT_TOKEN']);
|
|
98
|
+
const organizationId = (config === null || config === void 0 ? void 0 : config.organizationId) || (process === null || process === void 0 ? void 0 : process.env['DAYTONA_ORGANIZATION_ID']);
|
|
99
|
+
if (!apiKey && !jwtToken) {
|
|
100
|
+
throw new DaytonaError_1.DaytonaError('API key or JWT token is required');
|
|
101
|
+
}
|
|
102
|
+
const apiUrl = (config === null || config === void 0 ? void 0 : config.apiUrl) ||
|
|
103
|
+
(config === null || config === void 0 ? void 0 : config.serverUrl) ||
|
|
104
|
+
(process === null || process === void 0 ? void 0 : process.env['DAYTONA_API_URL']) ||
|
|
105
|
+
(process === null || process === void 0 ? void 0 : process.env['DAYTONA_SERVER_URL']) ||
|
|
106
|
+
'https://app.daytona.io/api';
|
|
107
|
+
const envTarget = process === null || process === void 0 ? void 0 : process.env['DAYTONA_TARGET'];
|
|
108
|
+
const target = (config === null || config === void 0 ? void 0 : config.target) || envTarget || api_client_1.CreateWorkspaceTargetEnum.US;
|
|
109
|
+
if ((process === null || process === void 0 ? void 0 : process.env['DAYTONA_SERVER_URL']) && !(process === null || process === void 0 ? void 0 : process.env['DAYTONA_API_URL'])) {
|
|
110
|
+
console.warn('[Deprecation Warning] Environment variable `DAYTONA_SERVER_URL` is deprecated and will be removed in future versions. Use `DAYTONA_API_URL` instead.');
|
|
111
|
+
}
|
|
112
|
+
this.apiKey = apiKey;
|
|
113
|
+
this.jwtToken = jwtToken;
|
|
114
|
+
this.organizationId = organizationId;
|
|
115
|
+
this.apiUrl = apiUrl;
|
|
116
|
+
this.target = target;
|
|
117
|
+
const orgHeader = {};
|
|
118
|
+
if (!this.apiKey) {
|
|
119
|
+
if (!this.organizationId) {
|
|
120
|
+
throw new DaytonaError_1.DaytonaError('Organization ID is required when using JWT token');
|
|
121
|
+
}
|
|
122
|
+
orgHeader['X-Daytona-Organization-ID'] = this.organizationId;
|
|
123
|
+
}
|
|
124
|
+
const configuration = new api_client_1.Configuration({
|
|
125
|
+
basePath: this.apiUrl,
|
|
126
|
+
baseOptions: {
|
|
127
|
+
headers: {
|
|
128
|
+
Authorization: `Bearer ${this.apiKey || this.jwtToken}`,
|
|
129
|
+
'X-Daytona-Source': 'typescript-sdk',
|
|
130
|
+
...orgHeader,
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
const axiosInstance = axios_1.default.create({
|
|
135
|
+
timeout: 24 * 60 * 60 * 1000, // 24 hours
|
|
136
|
+
});
|
|
137
|
+
axiosInstance.interceptors.response.use((response) => {
|
|
138
|
+
return response;
|
|
139
|
+
}, (error) => {
|
|
140
|
+
var _a, _b, _c, _d, _e;
|
|
141
|
+
let errorMessage;
|
|
142
|
+
if (error instanceof axios_1.AxiosError && error.message.includes('timeout of')) {
|
|
143
|
+
errorMessage = 'Operation timed out';
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
errorMessage = ((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.message) || ((_c = error.response) === null || _c === void 0 ? void 0 : _c.data) || error.message || String(error);
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
errorMessage = JSON.stringify(errorMessage);
|
|
150
|
+
}
|
|
151
|
+
catch (_f) {
|
|
152
|
+
errorMessage = String(errorMessage);
|
|
153
|
+
}
|
|
154
|
+
switch ((_e = (_d = error.response) === null || _d === void 0 ? void 0 : _d.data) === null || _e === void 0 ? void 0 : _e.statusCode) {
|
|
155
|
+
case 404:
|
|
156
|
+
throw new DaytonaError_1.DaytonaNotFoundError(errorMessage);
|
|
157
|
+
default:
|
|
158
|
+
throw new DaytonaError_1.DaytonaError(errorMessage);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
this.sandboxApi = new api_client_1.WorkspaceApi(configuration, '', axiosInstance);
|
|
162
|
+
this.toolboxApi = new api_client_1.ToolboxApi(configuration, '', axiosInstance);
|
|
163
|
+
this.volume = new Volume_1.VolumeService(new api_client_1.VolumesApi(configuration, '', axiosInstance));
|
|
164
|
+
this.imagesApi = new api_client_1.ImagesApi(configuration, '', axiosInstance);
|
|
165
|
+
this.objectStorageApi = new api_client_1.ObjectStorageApi(configuration, '', axiosInstance);
|
|
166
|
+
}
|
|
167
|
+
async create(params, options = { timeout: 60 }) {
|
|
168
|
+
var _a, _b, _c, _d;
|
|
169
|
+
const startTime = Date.now();
|
|
170
|
+
options = typeof options === 'number' ? { timeout: options } : { ...options };
|
|
171
|
+
if (options.timeout == undefined || options.timeout == null) {
|
|
172
|
+
options.timeout = 60;
|
|
173
|
+
}
|
|
174
|
+
if (params == null) {
|
|
175
|
+
params = { language: 'python' };
|
|
176
|
+
}
|
|
177
|
+
const labels = params.labels || {};
|
|
178
|
+
if (params.language) {
|
|
179
|
+
labels['code-toolbox-language'] = params.language;
|
|
180
|
+
}
|
|
181
|
+
// remove this when params.timeout is removed
|
|
182
|
+
const effectiveTimeout = params.timeout || options.timeout;
|
|
183
|
+
if (effectiveTimeout < 0) {
|
|
184
|
+
throw new DaytonaError_1.DaytonaError('Timeout must be a non-negative number');
|
|
185
|
+
}
|
|
186
|
+
if (params.autoStopInterval !== undefined &&
|
|
187
|
+
(!Number.isInteger(params.autoStopInterval) || params.autoStopInterval < 0)) {
|
|
188
|
+
throw new DaytonaError_1.DaytonaError('autoStopInterval must be a non-negative integer');
|
|
189
|
+
}
|
|
190
|
+
const codeToolbox = this.getCodeToolbox(params.language);
|
|
191
|
+
try {
|
|
192
|
+
// Handle Image instance if provided
|
|
193
|
+
let imageStr;
|
|
194
|
+
let buildInfo;
|
|
195
|
+
if (typeof params.image === 'string') {
|
|
196
|
+
imageStr = params.image;
|
|
197
|
+
}
|
|
198
|
+
else if (params.image instanceof Image_1.Image) {
|
|
199
|
+
const contextHashes = await this.processImageContext(params.image);
|
|
200
|
+
buildInfo = {
|
|
201
|
+
contextHashes,
|
|
202
|
+
dockerfileContent: params.image.dockerfile,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const response = await this.sandboxApi.createWorkspace({
|
|
206
|
+
image: imageStr,
|
|
207
|
+
buildInfo,
|
|
208
|
+
user: params.user,
|
|
209
|
+
env: params.envVars || {},
|
|
210
|
+
labels: params.labels,
|
|
211
|
+
public: params.public,
|
|
212
|
+
target: this.target,
|
|
213
|
+
cpu: (_a = params.resources) === null || _a === void 0 ? void 0 : _a.cpu,
|
|
214
|
+
gpu: (_b = params.resources) === null || _b === void 0 ? void 0 : _b.gpu,
|
|
215
|
+
memory: (_c = params.resources) === null || _c === void 0 ? void 0 : _c.memory,
|
|
216
|
+
disk: (_d = params.resources) === null || _d === void 0 ? void 0 : _d.disk,
|
|
217
|
+
autoStopInterval: params.autoStopInterval,
|
|
218
|
+
volumes: params.volumes,
|
|
219
|
+
}, undefined, {
|
|
220
|
+
timeout: effectiveTimeout * 1000,
|
|
221
|
+
});
|
|
222
|
+
let sandboxInstance = response.data;
|
|
223
|
+
if (sandboxInstance.state === api_client_1.WorkspaceState.PENDING_BUILD && options.onImageBuildLogs) {
|
|
224
|
+
const terminalStates = [api_client_1.WorkspaceState.STARTED, api_client_1.WorkspaceState.STARTING, api_client_1.WorkspaceState.ERROR];
|
|
225
|
+
while (sandboxInstance.state === api_client_1.WorkspaceState.PENDING_BUILD) {
|
|
226
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
227
|
+
sandboxInstance = (await this.sandboxApi.getWorkspace(sandboxInstance.id)).data;
|
|
228
|
+
}
|
|
229
|
+
await (0, Stream_1.processStreamingResponse)(() => this.sandboxApi.getBuildLogs(sandboxInstance.id, undefined, true, { responseType: 'stream' }), options.onImageBuildLogs, async () => {
|
|
230
|
+
sandboxInstance = (await this.sandboxApi.getWorkspace(sandboxInstance.id)).data;
|
|
231
|
+
return sandboxInstance.state !== undefined && terminalStates.includes(sandboxInstance.state);
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
const sandboxInfo = Sandbox_1.Sandbox.toSandboxInfo(sandboxInstance);
|
|
235
|
+
sandboxInstance.info = {
|
|
236
|
+
...sandboxInfo,
|
|
237
|
+
name: '',
|
|
238
|
+
};
|
|
239
|
+
const sandbox = new Sandbox_1.Sandbox(sandboxInstance.id, sandboxInstance, this.sandboxApi, this.toolboxApi, codeToolbox);
|
|
240
|
+
if (!params.async && sandbox.instance.state !== 'started') {
|
|
241
|
+
const timeElapsed = Date.now() - startTime;
|
|
242
|
+
await sandbox.waitUntilStarted(effectiveTimeout ? effectiveTimeout - timeElapsed / 1000 : 0);
|
|
243
|
+
}
|
|
244
|
+
return sandbox;
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
if (error instanceof DaytonaError_1.DaytonaError && error.message.includes('Operation timed out')) {
|
|
248
|
+
throw new DaytonaError_1.DaytonaError(`Failed to create and start sandbox within ${effectiveTimeout} seconds. Operation timed out.`);
|
|
249
|
+
}
|
|
250
|
+
throw error;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Gets a Sandbox by its ID.
|
|
255
|
+
*
|
|
256
|
+
* @param {string} sandboxId - The ID of the Sandbox to retrieve
|
|
257
|
+
* @returns {Promise<Sandbox>} The Sandbox
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* const sandbox = await daytona.get('my-sandbox-id');
|
|
261
|
+
* console.log(`Sandbox state: ${sandbox.instance.state}`);
|
|
262
|
+
*/
|
|
263
|
+
async get(sandboxId) {
|
|
264
|
+
const response = await this.sandboxApi.getWorkspace(sandboxId);
|
|
265
|
+
const sandboxInstance = response.data;
|
|
266
|
+
const language = sandboxInstance.labels && sandboxInstance.labels['code-toolbox-language'];
|
|
267
|
+
const codeToolbox = this.getCodeToolbox(language);
|
|
268
|
+
const sandboxInfo = Sandbox_1.Sandbox.toSandboxInfo(sandboxInstance);
|
|
269
|
+
sandboxInstance.info = {
|
|
270
|
+
...sandboxInfo,
|
|
271
|
+
name: '',
|
|
272
|
+
};
|
|
273
|
+
return new Sandbox_1.Sandbox(sandboxId, sandboxInstance, this.sandboxApi, this.toolboxApi, codeToolbox);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Finds a Sandbox by its ID or labels.
|
|
277
|
+
*
|
|
278
|
+
* @param {SandboxFilter} filter - Filter for Sandboxes
|
|
279
|
+
* @returns {Promise<Sandbox>} First Sandbox that matches the ID or labels.
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
* const sandbox = await daytona.findOne({ labels: { 'my-label': 'my-value' } });
|
|
283
|
+
* console.log(`Sandbox: ${await sandbox.info()}`);
|
|
284
|
+
*/
|
|
285
|
+
async findOne(filter) {
|
|
286
|
+
if (filter.id) {
|
|
287
|
+
return this.get(filter.id);
|
|
288
|
+
}
|
|
289
|
+
const sandboxes = await this.list(filter.labels);
|
|
290
|
+
if (sandboxes.length === 0) {
|
|
291
|
+
throw new DaytonaError_1.DaytonaError(`No sandbox found with labels ${JSON.stringify(filter.labels)}`);
|
|
292
|
+
}
|
|
293
|
+
return sandboxes[0];
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Lists all Sandboxes filtered by labels.
|
|
297
|
+
*
|
|
298
|
+
* @param {Record<string, string>} [labels] - Labels to filter Sandboxes
|
|
299
|
+
* @returns {Promise<Sandbox[]>} Array of Sandboxes that match the labels.
|
|
300
|
+
*
|
|
301
|
+
* @example
|
|
302
|
+
* const sandboxes = await daytona.list({ 'my-label': 'my-value' });
|
|
303
|
+
* for (const sandbox of sandboxes) {
|
|
304
|
+
* console.log(`${sandbox.id}: ${sandbox.instance.state}`);
|
|
305
|
+
* }
|
|
306
|
+
*/
|
|
307
|
+
async list(labels) {
|
|
308
|
+
const response = await this.sandboxApi.listWorkspaces(undefined, undefined, labels ? JSON.stringify(labels) : undefined);
|
|
309
|
+
return response.data.map((sandbox) => {
|
|
310
|
+
var _a;
|
|
311
|
+
const language = (_a = sandbox.labels) === null || _a === void 0 ? void 0 : _a['code-toolbox-language'];
|
|
312
|
+
const sandboxInfo = Sandbox_1.Sandbox.toSandboxInfo(sandbox);
|
|
313
|
+
sandbox.info = {
|
|
314
|
+
...sandboxInfo,
|
|
315
|
+
name: '',
|
|
316
|
+
};
|
|
317
|
+
return new Sandbox_1.Sandbox(sandbox.id, sandbox, this.sandboxApi, this.toolboxApi, this.getCodeToolbox(language));
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Starts a Sandbox and waits for it to be ready.
|
|
322
|
+
*
|
|
323
|
+
* @param {Sandbox} sandbox - The Sandbox to start
|
|
324
|
+
* @param {number} [timeout] - Optional timeout in seconds (0 means no timeout)
|
|
325
|
+
* @returns {Promise<void>}
|
|
326
|
+
*
|
|
327
|
+
* @example
|
|
328
|
+
* const sandbox = await daytona.get('my-sandbox-id');
|
|
329
|
+
* // Wait up to 60 seconds for the sandbox to start
|
|
330
|
+
* await daytona.start(sandbox, 60);
|
|
331
|
+
*/
|
|
332
|
+
async start(sandbox, timeout) {
|
|
333
|
+
await sandbox.start(timeout);
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Stops a Sandbox.
|
|
337
|
+
*
|
|
338
|
+
* @param {Sandbox} sandbox - The Sandbox to stop
|
|
339
|
+
* @returns {Promise<void>}
|
|
340
|
+
*
|
|
341
|
+
* @example
|
|
342
|
+
* const sandbox = await daytona.get('my-sandbox-id');
|
|
343
|
+
* await daytona.stop(sandbox);
|
|
344
|
+
*/
|
|
345
|
+
async stop(sandbox) {
|
|
346
|
+
await sandbox.stop();
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Deletes a Sandbox.
|
|
350
|
+
*
|
|
351
|
+
* @param {Sandbox} sandbox - The Sandbox to delete
|
|
352
|
+
* @param {number} timeout - Timeout in seconds (0 means no timeout, default is 60)
|
|
353
|
+
* @returns {Promise<void>}
|
|
354
|
+
*
|
|
355
|
+
* @example
|
|
356
|
+
* const sandbox = await daytona.get('my-sandbox-id');
|
|
357
|
+
* await daytona.delete(sandbox);
|
|
358
|
+
*/
|
|
359
|
+
async delete(sandbox, timeout = 60) {
|
|
360
|
+
await this.sandboxApi.deleteWorkspace(sandbox.id, true, undefined, { timeout: timeout * 1000 });
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Gets the Sandbox by ID.
|
|
364
|
+
*
|
|
365
|
+
* @param {string} workspaceId - The ID of the Sandbox to retrieve
|
|
366
|
+
* @returns {Promise<Workspace>} The Sandbox
|
|
367
|
+
*
|
|
368
|
+
* @deprecated Use `getCurrentSandbox` instead. This method will be removed in a future version.
|
|
369
|
+
*/
|
|
370
|
+
async getCurrentWorkspace(workspaceId) {
|
|
371
|
+
return await this.getCurrentSandbox(workspaceId);
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Gets the Sandbox by ID.
|
|
375
|
+
*
|
|
376
|
+
* @param {string} sandboxId - The ID of the Sandbox to retrieve
|
|
377
|
+
* @returns {Promise<Sandbox>} The Sandbox
|
|
378
|
+
*
|
|
379
|
+
* @example
|
|
380
|
+
* const sandbox = await daytona.getCurrentSandbox('my-sandbox-id');
|
|
381
|
+
* console.log(`Current sandbox state: ${sandbox.instance.state}`);
|
|
382
|
+
*/
|
|
383
|
+
async getCurrentSandbox(sandboxId) {
|
|
384
|
+
return await this.get(sandboxId);
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Creates and registers a new image from the given Image definition.
|
|
388
|
+
*
|
|
389
|
+
* @param {string} name - The name of the image to create.
|
|
390
|
+
* @param {Image} image - The Image instance.
|
|
391
|
+
* @param {object} options - Options for the create operation.
|
|
392
|
+
* @param {boolean} options.verbose - Default is false. Whether to log progress information upon each state change of the image.
|
|
393
|
+
* @param {number} options.timeout - Default is no timeout. Timeout in seconds (0 means no timeout).
|
|
394
|
+
* @returns {Promise<void>}
|
|
395
|
+
*
|
|
396
|
+
* @example
|
|
397
|
+
* const image = Image.debianSlim('3.12').pipInstall('numpy');
|
|
398
|
+
* await daytona.createImage('my-python-image', image);
|
|
399
|
+
*/
|
|
400
|
+
async createImage(name, image, options = {}) {
|
|
401
|
+
const contextHashes = await this.processImageContext(image);
|
|
402
|
+
let builtImage = (await this.imagesApi.buildImage({
|
|
403
|
+
name,
|
|
404
|
+
buildInfo: {
|
|
405
|
+
contextHashes,
|
|
406
|
+
dockerfileContent: image.dockerfile,
|
|
407
|
+
},
|
|
408
|
+
}, undefined, {
|
|
409
|
+
timeout: (options.timeout || 0) * 1000,
|
|
410
|
+
})).data;
|
|
411
|
+
const terminalStates = [api_client_1.ImageState.ACTIVE, api_client_1.ImageState.ERROR];
|
|
412
|
+
const imageRef = { builtImage };
|
|
413
|
+
let streamPromise;
|
|
414
|
+
const startLogStreaming = async () => {
|
|
415
|
+
if (!streamPromise) {
|
|
416
|
+
streamPromise = (0, Stream_1.processStreamingResponse)(() => this.imagesApi.getImageBuildLogs(builtImage.id, undefined, true, { responseType: 'stream' }), options.onLogs, async () => terminalStates.includes(imageRef.builtImage.state));
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
if (options.onLogs) {
|
|
420
|
+
options.onLogs(`Building image ${builtImage.name} (${builtImage.state})`);
|
|
421
|
+
if (builtImage.state !== api_client_1.ImageState.BUILD_PENDING) {
|
|
422
|
+
await startLogStreaming();
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
let previousState = builtImage.state;
|
|
426
|
+
while (!terminalStates.includes(builtImage.state)) {
|
|
427
|
+
if (options.onLogs && previousState !== builtImage.state) {
|
|
428
|
+
if (builtImage.state !== api_client_1.ImageState.BUILD_PENDING && !streamPromise) {
|
|
429
|
+
await startLogStreaming();
|
|
430
|
+
}
|
|
431
|
+
options.onLogs(`Building image ${builtImage.name} (${builtImage.state})`);
|
|
432
|
+
previousState = builtImage.state;
|
|
433
|
+
}
|
|
434
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
435
|
+
builtImage = (await this.imagesApi.getImage(builtImage.id)).data;
|
|
436
|
+
imageRef.builtImage = builtImage;
|
|
437
|
+
}
|
|
438
|
+
if (options.onLogs) {
|
|
439
|
+
if (streamPromise) {
|
|
440
|
+
await streamPromise;
|
|
441
|
+
}
|
|
442
|
+
if (builtImage.state === api_client_1.ImageState.ACTIVE) {
|
|
443
|
+
options.onLogs(`Built image ${builtImage.name} (${builtImage.state})`);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
if (builtImage.state === api_client_1.ImageState.ERROR) {
|
|
447
|
+
throw new DaytonaError_1.DaytonaError(`Failed to build image. Image ended in the ERROR state. name: ${builtImage.name}; error reason: ${builtImage.errorReason}`);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Gets the appropriate code toolbox based on language.
|
|
452
|
+
*
|
|
453
|
+
* @private
|
|
454
|
+
* @param {CodeLanguage} [language] - Programming language for the toolbox
|
|
455
|
+
* @returns {SandboxCodeToolbox} The appropriate code toolbox instance
|
|
456
|
+
* @throws {DaytonaError} - `DaytonaError` - When an unsupported language is specified
|
|
457
|
+
*/
|
|
458
|
+
getCodeToolbox(language) {
|
|
459
|
+
switch (language) {
|
|
460
|
+
case CodeLanguage.JAVASCRIPT:
|
|
461
|
+
case CodeLanguage.TYPESCRIPT:
|
|
462
|
+
return new SandboxTsCodeToolbox_1.SandboxTsCodeToolbox();
|
|
463
|
+
case CodeLanguage.PYTHON:
|
|
464
|
+
case undefined:
|
|
465
|
+
return new SandboxPythonCodeToolbox_1.SandboxPythonCodeToolbox();
|
|
466
|
+
default:
|
|
467
|
+
throw new DaytonaError_1.DaytonaError(`Unsupported language: ${language}, supported languages: ${Object.values(CodeLanguage).join(', ')}`);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Processes the image contexts by uploading them to object storage
|
|
472
|
+
*
|
|
473
|
+
* @private
|
|
474
|
+
* @param {Image} image - The Image instance.
|
|
475
|
+
* @returns {Promise<string[]>} The list of context hashes stored in object storage.
|
|
476
|
+
*/
|
|
477
|
+
async processImageContext(image) {
|
|
478
|
+
if (!image.contextList || !image.contextList.length) {
|
|
479
|
+
return [];
|
|
480
|
+
}
|
|
481
|
+
const pushAccessCreds = (await this.objectStorageApi.getPushAccess()).data;
|
|
482
|
+
const objectStorage = new ObjectStorage_1.ObjectStorage({
|
|
483
|
+
endpointUrl: pushAccessCreds.storageUrl,
|
|
484
|
+
accessKeyId: pushAccessCreds.accessKey,
|
|
485
|
+
secretAccessKey: pushAccessCreds.secret,
|
|
486
|
+
sessionToken: pushAccessCreds.sessionToken,
|
|
487
|
+
bucketName: pushAccessCreds.bucket,
|
|
488
|
+
});
|
|
489
|
+
const contextHashes = [];
|
|
490
|
+
for (const context of image.contextList) {
|
|
491
|
+
const contextHash = await objectStorage.upload(context.sourcePath, pushAccessCreds.organizationId, context.archivePath);
|
|
492
|
+
contextHashes.push(contextHash);
|
|
493
|
+
}
|
|
494
|
+
return contextHashes;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
exports.Daytona = Daytona;
|