@computesdk/daytona
Version:
Daytona provider for ComputeSDK
251 lines • 10.3 kB
JavaScript
// src/index.ts
import { Daytona } from "@daytonaio/sdk";
import { createProvider } from "computesdk";
var daytona = createProvider({
name: "daytona",
methods: {
sandbox: {
// Collection operations (compute.sandbox.*)
create: async (config, options) => {
const apiKey = config.apiKey || typeof process !== "undefined" && process.env?.DAYTONA_API_KEY || "";
if (!apiKey) {
throw new Error(
`Missing Daytona API key. Provide 'apiKey' in config or set DAYTONA_API_KEY environment variable. Get your API key from https://daytona.io/`
);
}
const runtime = options?.runtime || config.runtime || "node";
try {
const daytona2 = new Daytona({ apiKey });
let session;
let sandboxId;
if (options?.sandboxId) {
session = await daytona2.get(options.sandboxId);
sandboxId = options.sandboxId;
} else {
session = await daytona2.create({
language: runtime === "python" ? "python" : "javascript"
});
sandboxId = session.id;
}
return {
sandbox: session,
sandboxId
};
} catch (error) {
if (error instanceof Error) {
if (error.message.includes("unauthorized") || error.message.includes("API key")) {
throw new Error(
`Daytona authentication failed. Please check your DAYTONA_API_KEY environment variable. Get your API key from https://daytona.io/`
);
}
if (error.message.includes("quota") || error.message.includes("limit")) {
throw new Error(
`Daytona quota exceeded. Please check your usage at https://daytona.io/`
);
}
}
throw new Error(
`Failed to create Daytona sandbox: ${error instanceof Error ? error.message : String(error)}`
);
}
},
getById: async (config, sandboxId) => {
const apiKey = config.apiKey || process.env.DAYTONA_API_KEY;
try {
const daytona2 = new Daytona({ apiKey });
const session = await daytona2.get(sandboxId);
return {
sandbox: session,
sandboxId
};
} catch (error) {
return null;
}
},
list: async (config) => {
const apiKey = config.apiKey || process.env.DAYTONA_API_KEY;
try {
const daytona2 = new Daytona({ apiKey });
const sandboxes = await daytona2.list();
return sandboxes.map((session) => ({
sandbox: session,
sandboxId: session.id
}));
} catch (error) {
return [];
}
},
destroy: async (config, sandboxId) => {
const apiKey = config.apiKey || process.env.DAYTONA_API_KEY;
try {
const daytona2 = new Daytona({ apiKey });
const sandbox = await daytona2.get(sandboxId);
await sandbox.delete();
} catch (error) {
}
},
// Instance operations (sandbox.*)
runCode: async (sandbox, code, runtime) => {
const startTime = Date.now();
try {
const effectiveRuntime = runtime || // Strong Python indicators
(code.includes("print(") || code.includes("import ") || code.includes("def ") || code.includes("sys.") || code.includes("json.") || code.includes("__") || code.includes('f"') || code.includes("f'") ? "python" : "node");
let response;
const encoded = Buffer.from(code).toString("base64");
if (effectiveRuntime === "python") {
response = await sandbox.process.executeCommand(`echo "${encoded}" | base64 -d | python3`);
} else {
response = await sandbox.process.executeCommand(`echo "${encoded}" | base64 -d | node`);
}
const output = response.result || "";
const hasError = output.includes("Error:") || output.includes("error TS") || output.includes("SyntaxError:") || output.includes("TypeError:") || output.includes("ReferenceError:") || output.includes("Traceback (most recent call last)");
if (hasError && (output.includes("SyntaxError:") || output.includes("invalid syntax") || output.includes("Unexpected token") || output.includes("Unexpected identifier") || output.includes("error TS1434"))) {
throw new Error(`Syntax error: ${output.trim()}`);
}
const actualExitCode = hasError ? 1 : response.exitCode || 0;
return {
stdout: hasError ? "" : output,
stderr: hasError ? output : "",
exitCode: actualExitCode,
executionTime: Date.now() - startTime,
sandboxId: sandbox.id,
provider: "daytona"
};
} catch (error) {
if (error instanceof Error && error.message.includes("Syntax error")) {
throw error;
}
throw new Error(
`Daytona execution failed: ${error instanceof Error ? error.message : String(error)}`
);
}
},
runCommand: async (sandbox, command, args = []) => {
const startTime = Date.now();
try {
const fullCommand = args.length > 0 ? `${command} ${args.join(" ")}` : command;
const response = await sandbox.process.executeCommand(fullCommand);
return {
stdout: response.result || "",
stderr: "",
// Daytona doesn't separate stderr in the response
exitCode: response.exitCode || 0,
executionTime: Date.now() - startTime,
sandboxId: sandbox.id,
provider: "daytona"
};
} catch (error) {
throw new Error(
`Daytona command execution failed: ${error instanceof Error ? error.message : String(error)}`
);
}
},
getInfo: async (sandbox) => {
return {
id: sandbox.id,
provider: "daytona",
runtime: "python",
// Daytona default
status: "running",
createdAt: /* @__PURE__ */ new Date(),
timeout: 3e5,
metadata: {
daytonaSandboxId: sandbox.id
}
};
},
// Filesystem operations via terminal commands
filesystem: {
readFile: async (sandbox, path) => {
try {
const response = await sandbox.process.executeCommand(`cat "${path}"`);
if (response.exitCode !== 0) {
throw new Error(`File not found or cannot be read: ${path}`);
}
return response.result || "";
} catch (error) {
throw new Error(`Failed to read file ${path}: ${error instanceof Error ? error.message : String(error)}`);
}
},
writeFile: async (sandbox, path, content) => {
try {
const encoded = Buffer.from(content).toString("base64");
const response = await sandbox.process.executeCommand(`echo "${encoded}" | base64 -d > "${path}"`);
if (response.exitCode !== 0) {
throw new Error(`Failed to write to file: ${path}`);
}
} catch (error) {
throw new Error(`Failed to write file ${path}: ${error instanceof Error ? error.message : String(error)}`);
}
},
mkdir: async (sandbox, path) => {
try {
const response = await sandbox.process.executeCommand(`mkdir -p "${path}"`);
if (response.exitCode !== 0) {
throw new Error(`Failed to create directory: ${path}`);
}
} catch (error) {
throw new Error(`Failed to create directory ${path}: ${error instanceof Error ? error.message : String(error)}`);
}
},
readdir: async (sandbox, path) => {
try {
const response = await sandbox.process.executeCommand(`ls -la "${path}"`);
if (response.exitCode !== 0) {
throw new Error(`Directory not found or cannot be read: ${path}`);
}
const lines = response.result.split("\n").filter((line) => line.trim());
const entries = [];
for (const line of lines) {
if (line.startsWith("total ") || line.endsWith(" .") || line.endsWith(" ..")) {
continue;
}
const parts = line.trim().split(/\s+/);
if (parts.length >= 9) {
const permissions = parts[0];
const name = parts.slice(8).join(" ");
const isDirectory = permissions.startsWith("d");
const size = parseInt(parts[4]) || 0;
entries.push({
name,
path: `${path}/${name}`.replace(/\/+/g, "/"),
// Clean up double slashes
isDirectory,
size,
lastModified: /* @__PURE__ */ new Date()
// ls -la date parsing is complex, use current time
});
}
}
return entries;
} catch (error) {
throw new Error(`Failed to read directory ${path}: ${error instanceof Error ? error.message : String(error)}`);
}
},
exists: async (sandbox, path) => {
try {
const response = await sandbox.process.executeCommand(`test -e "${path}"`);
return response.exitCode === 0;
} catch (error) {
return false;
}
},
remove: async (sandbox, path) => {
try {
const response = await sandbox.process.executeCommand(`rm -rf "${path}"`);
if (response.exitCode !== 0) {
throw new Error(`Failed to remove: ${path}`);
}
} catch (error) {
throw new Error(`Failed to remove ${path}: ${error instanceof Error ? error.message : String(error)}`);
}
}
}
// Terminal operations not implemented - Daytona session API needs verification
}
}
});
export {
daytona
};
//# sourceMappingURL=index.mjs.map