diff --git a/README.md b/README.md index 4a19e899..5956cb5a 100644 --- a/README.md +++ b/README.md @@ -43,8 +43,8 @@ ANTHROPIC_API_KEY="" OPENAI_API_KEY="" GOOGLE_API_KEY="" -# E2B API key for accessing and modifying the code in the cloud sandbox. -E2B_API_KEY="" +# Daytona API key for accessing and modifying the code in the cloud sandbox. +DAYTONA_API_KEY="" # Your GitHub PAT with access to the repositories you want to modify. GITHUB_PAT="" diff --git a/apps/open-swe/.env.example b/apps/open-swe/.env.example index 1a045132..001dd51b 100644 --- a/apps/open-swe/.env.example +++ b/apps/open-swe/.env.example @@ -9,8 +9,8 @@ ANTHROPIC_API_KEY="" OPENAI_API_KEY="" GOOGLE_API_KEY="" -# E2B API key for accessing and modifying the code in the cloud sandbox. -E2B_API_KEY="" +# Daytona API key for accessing and modifying the code in the cloud sandbox. +DAYTONA_API_KEY="" # Your GitHub PAT with access to the repositories you want to modify. GITHUB_PAT="" diff --git a/apps/open-swe/e2b.Dockerfile b/apps/open-swe/e2b.Dockerfile deleted file mode 100644 index 3b63976a..00000000 --- a/apps/open-swe/e2b.Dockerfile +++ /dev/null @@ -1,29 +0,0 @@ -# Always start from the base E2B image -FROM e2bdev/code-interpreter:latest - -# Install dependencies in a single layer -RUN apt-get update && apt-get install -y \ - git \ - curl \ - ripgrep \ - python3 \ - python3-pip \ - && rm -rf /var/lib/apt/lists/* - -# Install Node.js (LTS version) via NodeSource -RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - \ - && apt-get install -y nodejs \ - && rm -rf /var/lib/apt/lists/* - -# Update corepack to latest version (to avoid outdated signature issues) -RUN npm install -g corepack@latest - -# Enable corepack for yarn and pnpm (creates shims) -RUN corepack enable yarn pnpm - -# Pre-download specific versions to avoid download on first use -RUN corepack prepare yarn@stable --activate \ - && corepack prepare pnpm@latest --activate - -# Set the working directory -WORKDIR /app \ No newline at end of file diff --git a/apps/open-swe/e2b.toml b/apps/open-swe/e2b.toml deleted file mode 100644 index 7adc8b49..00000000 --- a/apps/open-swe/e2b.toml +++ /dev/null @@ -1,18 +0,0 @@ -# This is a config for E2B sandbox template. -# You can use template ID (eh0860emqx28qyxmbctu) to create a sandbox: - -# Python SDK -# from e2b import Sandbox, AsyncSandbox -# sandbox = Sandbox("eh0860emqx28qyxmbctu") # Sync sandbox -# sandbox = await AsyncSandbox.create("eh0860emqx28qyxmbctu") # Async sandbox - -# JS SDK -# import { Sandbox } from 'e2b' -# const sandbox = await Sandbox.create('eh0860emqx28qyxmbctu') - -team_id = "af4eaf9c-3d40-415c-bb98-4831c47745cf" -memory_mb = 2_048 -cpu_count = 4 -start_cmd = "/root/.jupyter/start-up.sh" -dockerfile = "e2b.Dockerfile" -template_id = "eh0860emqx28qyxmbctu" diff --git a/apps/open-swe/package.json b/apps/open-swe/package.json index 8d7be831..39b386a5 100644 --- a/apps/open-swe/package.json +++ b/apps/open-swe/package.json @@ -22,7 +22,7 @@ "run:from-plan": "npx tsx scripts/run-from-plan.ts" }, "dependencies": { - "@e2b/code-interpreter": "1.2.0-beta.4", + "@daytonaio/sdk": "^0.18.1", "@langchain/anthropic": "^0.3.20", "@langchain/core": "^0.3.56", "@langchain/google-genai": "^0.2.9", diff --git a/apps/open-swe/scripts/run-from-plan.ts b/apps/open-swe/scripts/run-from-plan.ts index a5d1e42d..8aa00657 100644 --- a/apps/open-swe/scripts/run-from-plan.ts +++ b/apps/open-swe/scripts/run-from-plan.ts @@ -3,6 +3,7 @@ import { Client } from "@langchain/langgraph-sdk"; import { v4 as uuidv4 } from "uuid"; import { graph } from "../src/index.js"; import { createLogger, LogLevel } from "../src/utils/logger.js"; +import { SANDBOX_ROOT_DIR } from "../src/constants.js"; const logger = createLogger(LogLevel.INFO, "From Plan Script"); @@ -88,11 +89,11 @@ The user wants to implement a GitHub OAuth authentication server in the \`/apps/ 3. Making pull requests and pushing changes ## Codebase Files and Descriptions -- **Project root**: \`/home/user/open-swe/\` - Main monorepo directory -- **Apps directory**: \`/home/user/open-swe/apps/\` - Contains multiple apps including auth, docs, and open-swe -- **Auth app directory**: \`/home/user/open-swe/apps/auth/\` - Target directory for implementation, currently contains only scaffolding -- **Auth package.json**: \`/home/user/open-swe/apps/auth/package.json\` - Contains basic TypeScript/Node.js setup with name "@open-swe/auth", includes dev dependencies for TypeScript, Jest, ESLint, Prettier -- **Auth src directory**: \`/home/user/open-swe/apps/auth/src/\` - Contains only an empty \`index.ts\` file +- **Project root**: \`${SANDBOX_ROOT_DIR}/open-swe/\` - Main monorepo directory +- **Apps directory**: \`${SANDBOX_ROOT_DIR}/open-swe/apps/\` - Contains multiple apps including auth, docs, and open-swe +- **Auth app directory**: \`${SANDBOX_ROOT_DIR}/open-swe/apps/auth/\` - Target directory for implementation, currently contains only scaffolding +- **Auth package.json**: \`${SANDBOX_ROOT_DIR}/open-swe/apps/auth/package.json\` - Contains basic TypeScript/Node.js setup with name "@open-swe/auth", includes dev dependencies for TypeScript, Jest, ESLint, Prettier +- **Auth src directory**: \`${SANDBOX_ROOT_DIR}/open-swe/apps/auth/src/\` - Contains only an empty \`index.ts\` file - **Auth config files**: Directory includes standard config files (.gitignore, .dockerignore, .prettierrc, eslint.config.js, jest.config.js, tsconfig.json, turbo.json) ## Key Repository Insights and Learnings diff --git a/apps/open-swe/src/constants.ts b/apps/open-swe/src/constants.ts index 63af2e5a..6a43f088 100644 --- a/apps/open-swe/src/constants.ts +++ b/apps/open-swe/src/constants.ts @@ -3,3 +3,5 @@ export const TIMEOUT_MS = 300_000; // 5 minutes export const TIMEOUT_EXTENSION_OPT = { timeoutMs: TIMEOUT_MS, }; +export const SANDBOX_ROOT_DIR = "/home/daytona"; +export const SNAPSHOT_NAME = "daytonaio/langchain-open-swe:0.1.0"; diff --git a/apps/open-swe/src/nodes/generate-message.ts b/apps/open-swe/src/nodes/generate-message.ts index fe2505a9..9bbef5e3 100644 --- a/apps/open-swe/src/nodes/generate-message.ts +++ b/apps/open-swe/src/nodes/generate-message.ts @@ -7,7 +7,7 @@ import { } from "../tools/index.js"; import { getRepoAbsolutePath } from "../utils/git/index.js"; import { formatPlanPrompt } from "../utils/plan-prompt.js"; -import { pauseSandbox } from "../utils/sandbox.js"; +import { stopSandbox } from "../utils/sandbox.js"; import { createLogger, LogLevel } from "../utils/logger.js"; import { getCurrentTask } from "../utils/current-task.js"; import { getMessageContentString } from "../utils/message/content.js"; @@ -134,11 +134,11 @@ export async function generateAction( ]); const hasToolCalls = !!response.tool_calls?.length; - // No tool calls means the graph is going to end. Pause the sandbox. + // No tool calls means the graph is going to end. Stop the sandbox. let newSandboxSessionId: string | undefined; if (!hasToolCalls && state.sandboxSessionId) { - logger.info("No tool calls found. Pausing sandbox..."); - newSandboxSessionId = await pauseSandbox(state.sandboxSessionId); + logger.info("No tool calls found. Stopping sandbox..."); + newSandboxSessionId = await stopSandbox(state.sandboxSessionId); } logger.info("Generated action", { diff --git a/apps/open-swe/src/nodes/initialize.ts b/apps/open-swe/src/nodes/initialize.ts index 8ecc3bce..8eab41a5 100644 --- a/apps/open-swe/src/nodes/initialize.ts +++ b/apps/open-swe/src/nodes/initialize.ts @@ -1,4 +1,4 @@ -import { Sandbox } from "@e2b/code-interpreter"; +import { Sandbox } from "@daytonaio/sdk"; import { createLogger, LogLevel } from "../utils/logger.js"; import { GraphState, @@ -6,7 +6,6 @@ import { GraphUpdate, TargetRepository, } from "../types.js"; -import { TIMEOUT_EXTENSION_OPT } from "../constants.js"; import { checkoutBranch, configureGitUserInRepo, @@ -15,11 +14,11 @@ import { pullLatestChanges, } from "../utils/git/index.js"; import { getSandboxErrorFields } from "../utils/sandbox-error-fields.js"; +import { daytonaClient } from "../utils/sandbox.js"; +import { SNAPSHOT_NAME } from "../constants.js"; const logger = createLogger(LogLevel.INFO, "Initialize"); -const SANDBOX_TEMPLATE_ID = "eh0860emqx28qyxmbctu"; - async function cloneRepo(sandbox: Sandbox, targetRepository: TargetRepository) { if (!process.env.GITHUB_PAT) { throw new Error("GITHUB_PAT environment variable not set."); @@ -39,10 +38,7 @@ async function cloneRepo(sandbox: Sandbox, targetRepository: TargetRepository) { logger.info("Cloning repository", { command: gitCloneCommand.join(" "), }); - return await sandbox.commands.run( - gitCloneCommand.join(" "), - TIMEOUT_EXTENSION_OPT, - ); + return await sandbox.process.executeCommand(gitCloneCommand.join(" ")); } catch (e) { const errorFields = getSandboxErrorFields(e); logger.error("Failed to clone repository", errorFields ?? e); @@ -78,13 +74,10 @@ export async function initialize( sandboxSessionId, }); // Resume the sandbox if the session ID is in the config. - const newSandbox = await Sandbox.resume( - sandboxSessionId, - TIMEOUT_EXTENSION_OPT, - ); - await pullLatestChanges(absoluteRepoDir, newSandbox); + const existingSandbox = await daytonaClient().get(sandboxSessionId); + await pullLatestChanges(absoluteRepoDir, existingSandbox); return { - sandboxSessionId: newSandbox.sandboxId, + sandboxSessionId: existingSandbox.id, }; } catch (e) { // Error thrown, log it and continue. Will create a new sandbox session since the resumption failed. @@ -93,16 +86,15 @@ export async function initialize( } logger.info("Creating sandbox..."); - const sandbox = await Sandbox.create( - SANDBOX_TEMPLATE_ID, - TIMEOUT_EXTENSION_OPT, - ); + const sandbox = await daytonaClient().create({ + image: SNAPSHOT_NAME, + }); const res = await cloneRepo(sandbox, targetRepository); - if (res.error) { + if (res.exitCode !== 0) { // TODO: This should probably be an interrupt. - logger.error("Failed to clone repository", res.error); - throw new Error(`Failed to clone repository.\n${res.error}`); + logger.error("Failed to clone repository", res.result); + throw new Error(`Failed to clone repository.\n${res.result}`); } logger.info("Repository cloned successfully."); @@ -123,7 +115,7 @@ export async function initialize( } return { - sandboxSessionId: sandbox.sandboxId, + sandboxSessionId: sandbox.id, targetRepository, }; } diff --git a/apps/open-swe/src/nodes/interrupt-plan.ts b/apps/open-swe/src/nodes/interrupt-plan.ts index ca2d4f40..7703b5bf 100644 --- a/apps/open-swe/src/nodes/interrupt-plan.ts +++ b/apps/open-swe/src/nodes/interrupt-plan.ts @@ -5,7 +5,7 @@ import { HumanInterrupt, HumanResponse, } from "@langchain/langgraph/prebuilt"; -import { resumeSandbox } from "../utils/sandbox.js"; +import { startSandbox } from "../utils/sandbox.js"; export async function interruptPlan(state: GraphState): Promise { const { proposedPlan } = state; @@ -36,8 +36,7 @@ export async function interruptPlan(state: GraphState): Promise { } if (interruptRes.type === "accept") { - const newSandboxSessionId = (await resumeSandbox(state.sandboxSessionId)) - .sandboxId; + const newSandboxSessionId = (await startSandbox(state.sandboxSessionId)).id; // Plan was accepted, route to the generate-action node to start taking actions. return new Command({ @@ -55,8 +54,7 @@ export async function interruptPlan(state: GraphState): Promise { } if (interruptRes.type === "edit") { - const newSandboxSessionId = (await resumeSandbox(state.sandboxSessionId)) - .sandboxId; + const newSandboxSessionId = (await startSandbox(state.sandboxSessionId)).id; // Plan was edited, route to the generate-action node to start taking actions. const editedPlan = (interruptRes.args as ActionRequest).args.plan diff --git a/apps/open-swe/src/nodes/open-pr.ts b/apps/open-swe/src/nodes/open-pr.ts index 7be9313c..88870d33 100644 --- a/apps/open-swe/src/nodes/open-pr.ts +++ b/apps/open-swe/src/nodes/open-pr.ts @@ -1,5 +1,4 @@ import { GraphConfig, GraphState, GraphUpdate, PlanItem } from "../types.js"; -import { Sandbox } from "@e2b/code-interpreter"; import { checkoutBranchAndCommit, createPullRequest, @@ -13,6 +12,7 @@ import { loadModel, Task } from "../utils/load-model.js"; import { formatPlanPromptWithSummaries } from "../utils/plan-prompt.js"; import { isHumanMessage, ToolMessage } from "@langchain/core/messages"; import { getMessageContentString } from "../utils/message/content.js"; +import { daytonaClient } from "../utils/sandbox.js"; const logger = createLogger(LogLevel.INFO, "Open PR"); @@ -66,7 +66,7 @@ export async function openPullRequest( ); } - const sandbox = await Sandbox.connect(sandboxSessionId); + const sandbox = await daytonaClient().get(sandboxSessionId); const { owner, repo } = state.targetRepository; diff --git a/apps/open-swe/src/nodes/request-help.ts b/apps/open-swe/src/nodes/request-help.ts index a65ab0bf..38755fe6 100644 --- a/apps/open-swe/src/nodes/request-help.ts +++ b/apps/open-swe/src/nodes/request-help.ts @@ -2,7 +2,7 @@ import { isAIMessage } from "@langchain/core/messages"; import { GraphState } from "../types.js"; import { HumanInterrupt, HumanResponse } from "@langchain/langgraph/prebuilt"; import { END, interrupt, Command } from "@langchain/langgraph"; -import { pauseSandbox, resumeSandbox } from "../utils/sandbox.js"; +import { stopSandbox, startSandbox } from "../utils/sandbox.js"; const constructDescription = (helpRequest: string): string => { return `The agent has requested help. Here is the help request: @@ -21,7 +21,7 @@ export async function requestHelp(state: GraphState): Promise { if (!sandboxSessionId) { throw new Error("Sandbox session ID not found."); } - await pauseSandbox(sandboxSessionId); + await stopSandbox(sandboxSessionId); const toolCall = lastMessage.tool_calls[0]; @@ -52,7 +52,7 @@ export async function requestHelp(state: GraphState): Promise { if (typeof interruptRes.args !== "string") { throw new Error("Interrupt response expected to be a string."); } - await resumeSandbox(sandboxSessionId); + await startSandbox(sandboxSessionId); return new Command({ goto: "generate-action", update: { diff --git a/apps/open-swe/src/nodes/take-action.ts b/apps/open-swe/src/nodes/take-action.ts index 340f0518..a19b0963 100644 --- a/apps/open-swe/src/nodes/take-action.ts +++ b/apps/open-swe/src/nodes/take-action.ts @@ -11,13 +11,13 @@ import { getChangedFilesStatus, getRepoAbsolutePath, } from "../utils/git/index.js"; -import { Sandbox } from "@e2b/code-interpreter"; import { formatBadArgsError, zodSchemaToString, } from "../utils/zod-to-string.js"; import { Command } from "@langchain/langgraph"; import { truncateOutput } from "../utils/truncate-outputs.js"; +import { daytonaClient } from "../utils/sandbox.js"; const logger = createLogger(LogLevel.INFO, "TakeAction"); @@ -127,7 +127,7 @@ export async function takeAction( // Always check if there are changed files after running a tool. // If there are, commit them. - const sandbox = await Sandbox.connect(state.sandboxSessionId); + const sandbox = await daytonaClient().get(state.sandboxSessionId); const changedFiles = await getChangedFilesStatus( getRepoAbsolutePath(state.targetRepository), sandbox, diff --git a/apps/open-swe/src/subgraphs/planner/nodes/generate-plan.ts b/apps/open-swe/src/subgraphs/planner/nodes/generate-plan.ts index 11c114a6..9a4e4da7 100644 --- a/apps/open-swe/src/subgraphs/planner/nodes/generate-plan.ts +++ b/apps/open-swe/src/subgraphs/planner/nodes/generate-plan.ts @@ -7,7 +7,7 @@ import { sessionPlanTool } from "../../../tools/index.js"; import { GraphConfig } from "../../../types.js"; import { loadModel, Task } from "../../../utils/load-model.js"; import { PlannerGraphState, PlannerGraphUpdate } from "../types.js"; -import { pauseSandbox } from "../../../utils/sandbox.js"; +import { stopSandbox } from "../../../utils/sandbox.js"; const systemPrompt = `You are operating as a terminal-based agentic coding assistant built by LangChain. It wraps LLM models to enable natural language interaction with a local codebase. You are expected to be precise, safe, and helpful. @@ -68,8 +68,8 @@ export async function generatePlan( let newSessionId: string | undefined; if (state.sandboxSessionId) { - // Pause before returning, as the next step will be to interrupt the graph. - newSessionId = await pauseSandbox(state.sandboxSessionId); + // Stop before returning, as the next step will be to interrupt the graph. + newSessionId = await stopSandbox(state.sandboxSessionId); } return { diff --git a/apps/open-swe/src/tools/apply-patch.ts b/apps/open-swe/src/tools/apply-patch.ts index dde967ca..fcd85fed 100644 --- a/apps/open-swe/src/tools/apply-patch.ts +++ b/apps/open-swe/src/tools/apply-patch.ts @@ -2,11 +2,12 @@ import { tool } from "@langchain/core/tools"; import { z } from "zod"; import { applyPatch } from "diff"; import { GraphState } from "../types.js"; -import { Sandbox } from "@e2b/code-interpreter"; import { readFile, writeFile } from "../utils/read-write.js"; import { getCurrentTaskInput } from "@langchain/langgraph"; import { fixGitPatch } from "../utils/diff.js"; import { createLogger, LogLevel } from "../utils/logger.js"; +import { daytonaClient } from "../utils/sandbox.js"; +import { SANDBOX_ROOT_DIR } from "../constants.js"; const logger = createLogger(LogLevel.INFO, "ApplyPatchTool"); @@ -19,9 +20,9 @@ const applyPatchToolSchema = z.object({ file_path: z.string().describe("The file path to apply the diff to."), workdir: z .string() - .default("/home/user") + .default(SANDBOX_ROOT_DIR) .describe( - "The working directory for the command. Ensure this path is NOT included in any command arguments, as it will be added automatically. Defaults to '/home/user' as this is the root directory of the sandbox.", + `The working directory for the command. Ensure this path is NOT included in any command arguments, as it will be added automatically. Defaults to '${SANDBOX_ROOT_DIR}' as this is the root directory of the sandbox.`, ), }); @@ -38,7 +39,7 @@ export const applyPatchTool = tool( const { diff, file_path, workdir } = input; - const sandbox = await Sandbox.connect(sandboxSessionId); + const sandbox = await daytonaClient().get(sandboxSessionId); const { success: readFileSuccess, output: readFileOutput } = await readFile( sandbox, diff --git a/apps/open-swe/src/tools/shell.ts b/apps/open-swe/src/tools/shell.ts index c8529b20..9f7321d8 100644 --- a/apps/open-swe/src/tools/shell.ts +++ b/apps/open-swe/src/tools/shell.ts @@ -1,11 +1,12 @@ import { tool } from "@langchain/core/tools"; import { z } from "zod"; -import { Sandbox } from "@e2b/code-interpreter"; +import { Sandbox } from "@daytonaio/sdk"; import { GraphState } from "../types.js"; import { getCurrentTaskInput } from "@langchain/langgraph"; -import { TIMEOUT_MS } from "../constants.js"; import { getSandboxErrorFields } from "../utils/sandbox-error-fields.js"; import { createLogger, LogLevel } from "../utils/logger.js"; +import { daytonaClient } from "../utils/sandbox.js"; +import { SANDBOX_ROOT_DIR } from "../constants.js"; const logger = createLogger(LogLevel.INFO, "ShellTool"); @@ -20,9 +21,9 @@ const shellToolSchema = z.object({ command: z.array(z.string()).describe("The command to run"), workdir: z .string() - .default("/home/user") + .default(SANDBOX_ROOT_DIR) .describe( - "The working directory for the command. Ensure this path is NOT included in any command arguments, as it will be added automatically. Defaults to '/home/user' as this is the root directory of the sandbox.", + `The working directory for the command. Ensure this path is NOT included in any command arguments, as it will be added automatically. Defaults to '${SANDBOX_ROOT_DIR}' as this is the root directory of the sandbox.`, ), timeout: z .number() @@ -48,28 +49,29 @@ export const shellTool = tool( ); } - sandbox = await Sandbox.connect(sandboxSessionId); + sandbox = await daytonaClient().get(sandboxSessionId); const { command, workdir, timeout } = input; - const result = await sandbox.commands.run(command.join(" "), { - timeoutMs: timeout ?? DEFAULT_COMMAND_TIMEOUT, - cwd: workdir, - envs: DEFAULT_ENV, - }); + const response = await sandbox.process.executeCommand( + command.join(" "), + workdir, + DEFAULT_ENV, + timeout ?? DEFAULT_COMMAND_TIMEOUT, + ); - if (result.error) { + if (response.exitCode !== 0) { logger.error("Failed to run command", { - error: result.error, - error_result: result, + error: response.result, + error_result: response, input, }); return { - result: `Command failed. Exit code: ${result.exitCode}\nError: ${result.error}\nStderr:\n${result.stderr}`, + result: `Command failed. Exit code: ${response.exitCode}\nResult: ${response.result}\nStdout:\n${response.artifacts?.stdout}`, status: "error", }; } return { - result: result.stdout, + result: response.result, status: "success", }; } catch (e) { @@ -80,7 +82,7 @@ export const shellTool = tool( error: errorFields, }); return { - result: `Command failed. Exit code: ${errorFields.exitCode}\nError: ${errorFields.error}\nStderr:\n${errorFields.stderr}\nStdout:\n${errorFields.stdout}`, + result: `Command failed. Exit code: ${errorFields.exitCode}\nError: ${errorFields.result}\nStdout:\n${errorFields.artifacts?.stdout}`, status: "error", }; } @@ -97,17 +99,6 @@ export const shellTool = tool( "FAILED TO RUN COMMAND: " + (e instanceof Error ? e.message : "Unknown error"), ); - } finally { - try { - if (sandbox) { - // Add an extra 5 min timeout to the sandbox. - await sandbox.setTimeout(TIMEOUT_MS); - } - } catch (_) { - logger.warn( - "Failed to set timeout for sandbox inside 'finally' block for shell tool.", - ); - } } }, { diff --git a/apps/open-swe/src/utils/git/index.ts b/apps/open-swe/src/utils/git/index.ts index 3297f12b..b7564a82 100644 --- a/apps/open-swe/src/utils/git/index.ts +++ b/apps/open-swe/src/utils/git/index.ts @@ -1,9 +1,10 @@ import { Octokit } from "@octokit/rest"; -import { CommandResult, Sandbox } from "@e2b/code-interpreter"; +import { Sandbox } from "@daytonaio/sdk"; import { createLogger, LogLevel } from "../logger.js"; import { GraphConfig, TargetRepository } from "../../types.js"; -import { TIMEOUT_MS } from "../../constants.js"; +import { TIMEOUT_MS, SANDBOX_ROOT_DIR } from "../../constants.js"; import { getSandboxErrorFields } from "../sandbox-error-fields.js"; +import { ExecuteResponse } from "@daytonaio/sdk/dist/types/ExecuteResponse.js"; const logger = createLogger(LogLevel.INFO, "GitUtil"); @@ -15,7 +16,7 @@ export function getRepoAbsolutePath( throw new Error("No repository name provided"); } - return `/home/user/${repoName}`; + return `${SANDBOX_ROOT_DIR}/${repoName}`; } export function getBranchName(config: GraphConfig): string { @@ -31,27 +32,27 @@ export async function checkoutBranch( absoluteRepoDir: string, branchName: string, sandbox: Sandbox, -): Promise { +): Promise { logger.info(`Checking out branch '${branchName}'...`); try { - const getCurrentBranchOutput = await sandbox.commands.run( + const getCurrentBranchOutput = await sandbox.process.executeCommand( "git branch --show-current", - { cwd: absoluteRepoDir }, + absoluteRepoDir, + undefined, + TIMEOUT_MS, ); - await sandbox.setTimeout(TIMEOUT_MS); if (getCurrentBranchOutput.exitCode !== 0) { logger.error(`Failed to get current branch`, { getCurrentBranchOutput, }); } else { - const currentBranch = getCurrentBranchOutput.stdout.trim(); + const currentBranch = getCurrentBranchOutput.result.trim(); if (currentBranch === branchName) { logger.info(`Already on branch '${branchName}'. No checkout needed.`); return { - stdout: `Already on branch ${branchName}`, - stderr: "", + result: `Already on branch ${branchName}`, exitCode: 0, }; } @@ -75,11 +76,12 @@ export async function checkoutBranch( `Checking if branch 'refs/heads/${branchName}' exists using 'git rev-parse --verify --quiet'`, ); // Check if branch exists using git rev-parse for robustness - const checkBranchExistsOutput = await sandbox.commands.run( + const checkBranchExistsOutput = await sandbox.process.executeCommand( `git rev-parse --verify --quiet "refs/heads/${branchName}"`, - { cwd: absoluteRepoDir }, + absoluteRepoDir, + undefined, + TIMEOUT_MS, ); - await sandbox.setTimeout(TIMEOUT_MS); if (checkBranchExistsOutput.exitCode === 0) { // Branch exists (rev-parse exit code 0 means success) @@ -94,7 +96,7 @@ export async function checkoutBranch( if ( errorFields && errorFields.exitCode === 1 && - errorFields.stderr === "" + errorFields.result === "" ) { checkoutCommand = `git checkout -b "${branchName}"`; } else { @@ -110,9 +112,12 @@ export async function checkoutBranch( } try { - const gitCheckoutOutput = await sandbox.commands.run(checkoutCommand, { - cwd: absoluteRepoDir, - }); + const gitCheckoutOutput = await sandbox.process.executeCommand( + checkoutCommand, + absoluteRepoDir, + undefined, + TIMEOUT_MS, + ); if (gitCheckoutOutput.exitCode !== 0) { logger.error(`Failed to checkout branch`, { @@ -212,20 +217,24 @@ export async function configureGitUserInRepo( ): Promise { let needsGitConfig = false; try { - const nameCheck = await sandbox.commands.run("git config user.name", { - cwd: absoluteRepoDir, - }); - await sandbox.setTimeout(TIMEOUT_MS); - const emailCheck = await sandbox.commands.run("git config user.email", { - cwd: absoluteRepoDir, - }); - await sandbox.setTimeout(TIMEOUT_MS); + const nameCheck = await sandbox.process.executeCommand( + "git config user.name", + absoluteRepoDir, + undefined, + TIMEOUT_MS, + ); + const emailCheck = await sandbox.process.executeCommand( + "git config user.email", + absoluteRepoDir, + undefined, + TIMEOUT_MS, + ); if ( nameCheck.exitCode !== 0 || - nameCheck.stdout.trim() === "" || + nameCheck.result.trim() === "" || emailCheck.exitCode !== 0 || - emailCheck.stdout.trim() === "" + emailCheck.result.trim() === "" ) { needsGitConfig = true; } @@ -244,11 +253,12 @@ export async function configureGitUserInRepo( const { userName, userEmail } = await getGitUserDetailsFromGitHub(); if (userName) { - const configUserNameOutput = await sandbox.commands.run( + const configUserNameOutput = await sandbox.process.executeCommand( `git config user.name "${userName}"`, - { cwd: absoluteRepoDir }, + absoluteRepoDir, + undefined, + TIMEOUT_MS, ); - await sandbox.setTimeout(TIMEOUT_MS); if (configUserNameOutput.exitCode !== 0) { logger.error(`Failed to set git user.name`, { configUserNameOutput, @@ -259,11 +269,12 @@ export async function configureGitUserInRepo( } if (userEmail) { - const configUserEmailOutput = await sandbox.commands.run( + const configUserEmailOutput = await sandbox.process.executeCommand( `git config user.email "${userEmail}"`, - { cwd: absoluteRepoDir }, + absoluteRepoDir, + undefined, + TIMEOUT_MS, ); - await sandbox.setTimeout(TIMEOUT_MS); if (configUserEmailOutput.exitCode !== 0) { logger.error(`Failed to set git user.email`, { configUserEmailOutput, @@ -283,13 +294,14 @@ export async function commitAll( absoluteRepoDir: string, message: string, sandbox: Sandbox, -): Promise { +): Promise { try { - const gitAddOutput = await sandbox.commands.run( + const gitAddOutput = await sandbox.process.executeCommand( `git add -A && git commit -m "${message}"`, - { cwd: absoluteRepoDir }, + absoluteRepoDir, + undefined, + TIMEOUT_MS, ); - await sandbox.setTimeout(TIMEOUT_MS); if (gitAddOutput.exitCode !== 0) { logger.error(`Failed to commit all changes to git repository`, { @@ -315,7 +327,7 @@ export async function commitAllAndPush( absoluteRepoDir: string, message: string, sandbox: Sandbox, -): Promise { +): Promise { try { const commitOutput = await commitAll(absoluteRepoDir, message, sandbox); @@ -326,10 +338,12 @@ export async function commitAllAndPush( return false; } - const gitPushOutput = await sandbox.commands.run(pushCurrentBranchCmd, { - cwd: absoluteRepoDir, - }); - await sandbox.setTimeout(TIMEOUT_MS); + const gitPushOutput = await sandbox.process.executeCommand( + pushCurrentBranchCmd, + absoluteRepoDir, + undefined, + TIMEOUT_MS, + ); if (gitPushOutput.exitCode !== 0) { logger.error(`Failed to push changes to git repository`, { @@ -357,9 +371,12 @@ export async function getChangedFilesStatus( absoluteRepoDir: string, sandbox: Sandbox, ): Promise { - const gitStatusOutput = await sandbox.commands.run("git status --porcelain", { - cwd: absoluteRepoDir, - }); + const gitStatusOutput = await sandbox.process.executeCommand( + "git status --porcelain", + absoluteRepoDir, + undefined, + TIMEOUT_MS, + ); if (gitStatusOutput.exitCode !== 0) { logger.error(`Failed to get changed files status`, { @@ -368,7 +385,7 @@ export async function getChangedFilesStatus( return []; } - return gitStatusOutput.stdout + return gitStatusOutput.result .split("\n") .map((line) => line.trim()) .filter((line) => line !== ""); @@ -453,12 +470,14 @@ export async function createPullRequest({ export async function pullLatestChanges( absoluteRepoDir: string, sandbox: Sandbox, -): Promise { +): Promise { try { - const gitPullOutput = await sandbox.commands.run("git pull", { - cwd: absoluteRepoDir, - }); - await sandbox.setTimeout(TIMEOUT_MS); + const gitPullOutput = await sandbox.process.executeCommand( + "git pull", + absoluteRepoDir, + undefined, + TIMEOUT_MS, + ); return gitPullOutput; } catch (e) { const errorFields = getSandboxErrorFields(e); diff --git a/apps/open-swe/src/utils/read-write.ts b/apps/open-swe/src/utils/read-write.ts index 764b2eed..d4b443cd 100644 --- a/apps/open-swe/src/utils/read-write.ts +++ b/apps/open-swe/src/utils/read-write.ts @@ -1,6 +1,5 @@ -import { Sandbox } from "@e2b/code-interpreter"; +import { Sandbox } from "@daytonaio/sdk"; import { createLogger, LogLevel } from "./logger.js"; -import { TIMEOUT_MS } from "../constants.js"; import { getSandboxErrorFields } from "./sandbox-error-fields.js"; import { traceable } from "langsmith/traceable"; @@ -15,9 +14,10 @@ async function handleCreateFile( ) { try { const touchCommand = `touch "${filePath}"`; - const touchOutput = await sandbox.commands.run(touchCommand, { - cwd: args?.workDir, - }); + const touchOutput = await sandbox.process.executeCommand( + touchCommand, + args?.workDir, + ); return touchOutput; } catch (e) { const errorFields = getSandboxErrorFields(e); @@ -44,9 +44,10 @@ async function readFileFunc( output: string; }> { try { - const readOutput = await sandbox.commands.run(`cat "${filePath}"`, { - cwd: args?.workDir, - }); + const readOutput = await sandbox.process.executeCommand( + `cat "${filePath}"`, + args?.workDir, + ); if (readOutput.exitCode !== 0) { logger.error(`Error reading file '${filePath}' from sandbox via cat:`, { @@ -54,13 +55,13 @@ async function readFileFunc( }); return { success: false, - output: `FAILED TO READ FILE from sandbox '${filePath}'. Exit code: ${readOutput.exitCode}.\nStderr: ${readOutput.stderr}\nStdout: ${readOutput.stdout}`, + output: `FAILED TO READ FILE from sandbox '${filePath}'. Exit code: ${readOutput.exitCode}.\nResult: ${readOutput.result}\nStdout: ${readOutput.artifacts?.stdout}`, }; } return { success: true, - output: readOutput.stdout, + output: readOutput.result, }; } catch (e: any) { if (e instanceof Error && e.message.includes("No such file or directory")) { @@ -87,7 +88,7 @@ async function readFileFunc( let outputMessage = `FAILED TO EXECUTE READ COMMAND for sandbox '${filePath}'.`; const errorFields = getSandboxErrorFields(e); if (errorFields) { - outputMessage += `\nExit code: ${errorFields.exitCode}\nStderr: ${errorFields.stderr}\nStdout: ${errorFields.stdout}`; + outputMessage += `\nExit code: ${errorFields.exitCode}\nResult: ${errorFields.result}\nStdout: ${errorFields.artifacts?.stdout}`; } else { outputMessage += ` Error: ${(e as Error).message || String(e)}`; } @@ -100,17 +101,6 @@ async function readFileFunc( success: false, output: outputMessage, }; - } finally { - try { - if (sandbox) { - // Add an extra 5 min timeout to the sandbox. - await sandbox.setTimeout(TIMEOUT_MS); - } - } catch (_) { - logger.warn( - "Failed to set timeout for sandbox inside 'finally' block for read file.", - ); - } } } @@ -134,9 +124,10 @@ async function writeFileFunc( const writeCommand = `cat > "${filePath}" << '${delimiter}' ${content} ${delimiter}`; - const writeOutput = await sandbox.commands.run(writeCommand, { - cwd: args?.workDir, - }); + const writeOutput = await sandbox.process.executeCommand( + writeCommand, + args?.workDir, + ); if (writeOutput.exitCode !== 0) { logger.error(`Error writing file '${filePath}' to sandbox via cat:`, { @@ -144,14 +135,9 @@ ${delimiter}`; }); return { success: false, - output: `FAILED TO WRITE FILE to sandbox '${filePath}'. Exit code: ${writeOutput.exitCode}\nStderr: ${writeOutput.stderr}\nStdout: ${writeOutput.stdout}`, + output: `FAILED TO WRITE FILE to sandbox '${filePath}'. Exit code: ${writeOutput.exitCode}\nResult: ${writeOutput.result}\nStdout: ${writeOutput.artifacts?.stdout}`, }; } - if (writeOutput.stderr) { - logger.warn( - `Stderr while writing file '${filePath}' to sandbox via cat: ${writeOutput.stderr}`, - ); - } return { success: true, output: `Successfully wrote file '${filePath}' to sandbox via cat.`, @@ -169,7 +155,7 @@ ${delimiter}`; let outputMessage = `FAILED TO EXECUTE WRITE COMMAND for sandbox '${filePath}'.`; const errorFields = getSandboxErrorFields(e); if (errorFields) { - outputMessage += `\nExit code: ${errorFields.exitCode}\nStderr: ${errorFields.stderr}\nStdout: ${errorFields.stdout}`; + outputMessage += `\nExit code: ${errorFields.exitCode}\nResult: ${errorFields.result}\nStdout: ${errorFields.artifacts?.stdout}`; } else { outputMessage += ` Error: ${(e as Error).message || String(e)}`; } @@ -178,17 +164,6 @@ ${delimiter}`; success: false, output: outputMessage, }; - } finally { - try { - if (sandbox) { - // Add an extra 5 min timeout to the sandbox. - await sandbox.setTimeout(TIMEOUT_MS); - } - } catch (_) { - logger.warn( - "Failed to set timeout for sandbox inside 'finally' block for write file.", - ); - } } } diff --git a/apps/open-swe/src/utils/sandbox-error-fields.ts b/apps/open-swe/src/utils/sandbox-error-fields.ts index d03ccf87..a3be0857 100644 --- a/apps/open-swe/src/utils/sandbox-error-fields.ts +++ b/apps/open-swe/src/utils/sandbox-error-fields.ts @@ -1,8 +1,8 @@ -import { CommandResult } from "@e2b/code-interpreter"; +import { ExecuteResponse } from "@daytonaio/sdk/dist/types/ExecuteResponse.js"; export function getSandboxErrorFields( error: unknown, -): CommandResult | undefined { +): ExecuteResponse | undefined { if ( !error || typeof error !== "object" || @@ -16,5 +16,5 @@ export function getSandboxErrorFields( return undefined; } - return error.result as CommandResult; + return error.result as unknown as ExecuteResponse; } diff --git a/apps/open-swe/src/utils/sandbox.ts b/apps/open-swe/src/utils/sandbox.ts index 4a5a2607..6eed0072 100644 --- a/apps/open-swe/src/utils/sandbox.ts +++ b/apps/open-swe/src/utils/sandbox.ts @@ -1,28 +1,52 @@ -import { Sandbox } from "@e2b/code-interpreter"; +import { Daytona, Sandbox, SandboxState } from "@daytonaio/sdk"; + +// Singleton instance of Daytona +let daytonaInstance: Daytona | null = null; /** - * Pauses the sandbox. Either pass an existing sandbox client, or a sandbox session ID. + * Returns a shared Daytona instance + */ +export function daytonaClient(): Daytona { + if (!daytonaInstance) { + daytonaInstance = new Daytona(); + } + return daytonaInstance; +} + +/** + * Stops the sandbox. Either pass an existing sandbox client, or a sandbox session ID. * If no sandbox client is provided, the sandbox will be connected to. - * @param sandboxSessionId The ID of the sandbox to pause. - * @param sandbox The sandbox client to pause. If not provided, the sandbox will be connected to. + * @param sandboxSessionId The ID of the sandbox to stop. + * @param sandbox The sandbox client to stop. If not provided, the sandbox will be connected to. * @returns The sandbox session ID. */ -export async function pauseSandbox( - sandboxSessionId: string, - sandbox?: Sandbox, -): Promise { - const sandboxClient = sandbox ?? (await Sandbox.connect(sandboxSessionId)); - return await sandboxClient.pause(); +export async function stopSandbox(sandboxSessionId: string): Promise { + const sandbox = await daytonaClient().get(sandboxSessionId); + if ( + sandbox.instance.state == SandboxState.STOPPED || + sandbox.instance.state == SandboxState.ARCHIVED + ) { + return sandboxSessionId; + } else if (sandbox.instance.state == "started") { + await daytonaClient().stop(sandbox); + } + + return sandbox.id; } /** - * Resumes the sandbox. - * @param sandboxSessionId The ID of the sandbox to resume. + * Starts the sandbox. + * @param sandboxSessionId The ID of the sandbox to start. * @returns The sandbox client. */ -export async function resumeSandbox( - sandboxSessionId: string, -): Promise { - return await Sandbox.resume(sandboxSessionId); +export async function startSandbox(sandboxSessionId: string): Promise { + const sandbox = await daytonaClient().get(sandboxSessionId); + if ( + sandbox.instance.state == SandboxState.STOPPED || + sandbox.instance.state == SandboxState.ARCHIVED + ) { + await daytonaClient().start(sandbox); + } + return sandbox; } diff --git a/yarn.lock b/yarn.lock index f02ce46f..84af03cb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -449,13 +449,6 @@ __metadata: languageName: node linkType: hard -"@bufbuild/protobuf@npm:^2.2.2": - version: 2.5.0 - resolution: "@bufbuild/protobuf@npm:2.5.0" - checksum: ff7f015e3ab7243461ac480efcc58a6b36473fef036aaa118361eb45871587d97a0bebc9daf77127ef86cdf08f1af990469e51c54b59b1818997c032dd221407 - languageName: node - linkType: hard - "@cfworker/json-schema@npm:^4.0.2": version: 4.1.1 resolution: "@cfworker/json-schema@npm:4.1.1" @@ -479,25 +472,6 @@ __metadata: languageName: node linkType: hard -"@connectrpc/connect-web@npm:2.0.0-rc.3": - version: 2.0.0-rc.3 - resolution: "@connectrpc/connect-web@npm:2.0.0-rc.3" - peerDependencies: - "@bufbuild/protobuf": ^2.2.0 - "@connectrpc/connect": 2.0.0-rc.3 - checksum: 2889806b7161507f20d01a472b8173ea8fec4db664e89a3c46b2a04690abafb3b73a7541334d34b70be5d4867b2c4e51558bec7dfb3cead061f66fcc42076f8d - languageName: node - linkType: hard - -"@connectrpc/connect@npm:2.0.0-rc.3": - version: 2.0.0-rc.3 - resolution: "@connectrpc/connect@npm:2.0.0-rc.3" - peerDependencies: - "@bufbuild/protobuf": ^2.2.0 - checksum: 78e993f48b4ff7dd290a919eb34578ca97848f12576a1fb8e988af50a100c6aa790c2cfaa0aca6fae658e56c652c81db5be9cbf650a4a69f18fa0a8a3b94b58d - languageName: node - linkType: hard - "@dabh/diagnostics@npm:^2.0.2": version: 2.0.3 resolution: "@dabh/diagnostics@npm:2.0.3" @@ -509,12 +483,54 @@ __metadata: languageName: node linkType: hard -"@e2b/code-interpreter@npm:1.2.0-beta.4": - version: 1.2.0-beta.4 - resolution: "@e2b/code-interpreter@npm:1.2.0-beta.4" +"@daytonaio/api-client@npm:^0.19.1": + version: 0.19.1 + resolution: "@daytonaio/api-client@npm:0.19.1" dependencies: - e2b: 1.2.0-beta.4 - checksum: c08fb0381482156301f1147bf5cf71bab7c817afa7c02613bde3dc1b8c7011f9aca14b9edd1e4e9c365cec486818b8d3e5c54b1e7bcc70248bdf722a5b4026bd + axios: ^1.6.1 + checksum: fc5402ff535b4299d9e5124795f02e09f86f22d0e07153943452e2771038c803fe11153d52c9b5f1b618bd17d18a4af76aa421547f640b86cbcdc6dec1d4d063 + languageName: node + linkType: hard + +"@daytonaio/sdk@npm:^0.18.1": + version: 0.18.1 + resolution: "@daytonaio/sdk@npm:0.18.1" + dependencies: + "@daytonaio/api-client": ^0.19.1 + "@dotenvx/dotenvx": ^1.25.1 + axios: ^1.6.0 + form-data: ^4.0.0 + uuid: ^11.0.3 + checksum: a3e0afd4e60a8f631f78579e8defed206dcd97ebe6e005d3bb75bb0e289be7bbf51e68075c255638beba98eea272f642a2c6872dbc6689d0d8bab7ba660fd475 + languageName: node + linkType: hard + +"@dotenvx/dotenvx@npm:^1.25.1": + version: 1.44.1 + resolution: "@dotenvx/dotenvx@npm:1.44.1" + dependencies: + commander: ^11.1.0 + dotenv: ^16.4.5 + eciesjs: ^0.4.10 + execa: ^5.1.1 + fdir: ^6.2.0 + ignore: ^5.3.0 + object-treeify: 1.1.33 + picomatch: ^4.0.2 + which: ^4.0.0 + bin: + dotenvx: src/cli/dotenvx.js + git-dotenvx: src/cli/dotenvx.js + checksum: a868270e4fdb0d3ac307fc44728630dbfb3a17685799de8483fdb3e2e8543cc4eb6f576fe6284804d0aeccbf9cbf5ca4b14906ff554d090960f3223d88db93b5 + languageName: node + linkType: hard + +"@ecies/ciphers@npm:^0.2.3": + version: 0.2.3 + resolution: "@ecies/ciphers@npm:0.2.3" + peerDependencies: + "@noble/ciphers": ^1.0.0 + checksum: fdf01fd5e687a74802df60d21ff9be5aa6cdf692dcf671186e94eb17e9c260a4652b64c7127b277af20c35d3ccc733003cefb2fdaee93e8b516fa71d317d503f languageName: node linkType: hard @@ -2416,6 +2432,29 @@ __metadata: languageName: node linkType: hard +"@noble/ciphers@npm:^1.3.0": + version: 1.3.0 + resolution: "@noble/ciphers@npm:1.3.0" + checksum: 19722c35475df9bc78db60d261d0b5ef8a6d722561efc2135453f943eaa421b492195dc666e3e4df2b755bca3739e04f04b9c660198559f5dd05d3cfbf1b9e92 + languageName: node + linkType: hard + +"@noble/curves@npm:^1.9.1": + version: 1.9.1 + resolution: "@noble/curves@npm:1.9.1" + dependencies: + "@noble/hashes": 1.8.0 + checksum: 4f3483a1001538d2f55516cdcb19319d1eaef79550633f670e7d570b989cdbc0129952868b72bb67643329746b8ffefe8e4cd791c8cc35574e05a37f873eef42 + languageName: node + linkType: hard + +"@noble/hashes@npm:1.8.0, @noble/hashes@npm:^1.8.0": + version: 1.8.0 + resolution: "@noble/hashes@npm:1.8.0" + checksum: c94e98b941963676feaba62475b1ccfa8341e3f572adbb3b684ee38b658df44100187fa0ef4220da580b13f8d27e87d5492623c8a02ecc61f23fb9960c7918f5 + languageName: node + linkType: hard + "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -2608,7 +2647,7 @@ __metadata: version: 0.0.0-use.local resolution: "@open-swe/agent@workspace:apps/open-swe" dependencies: - "@e2b/code-interpreter": 1.2.0-beta.4 + "@daytonaio/sdk": ^0.18.1 "@eslint/eslintrc": ^3.1.0 "@eslint/js": ^9.19.0 "@jest/globals": ^29.7.0 @@ -5375,7 +5414,7 @@ __metadata: languageName: node linkType: hard -"axios@npm:^1.4.0, axios@npm:^1.6.2": +"axios@npm:^1.4.0, axios@npm:^1.6.0, axios@npm:^1.6.1, axios@npm:^1.6.2": version: 1.9.0 resolution: "axios@npm:1.9.0" dependencies: @@ -6240,6 +6279,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:^11.1.0": + version: 11.1.0 + resolution: "commander@npm:11.1.0" + checksum: fd1a8557c6b5b622c89ecdfde703242ab7db3b628ea5d1755784c79b8e7cb0d74d65b4a262289b533359cd58e1bfc0bf50245dfbcd2954682a6f367c828b79ef + languageName: node + linkType: hard + "commander@npm:^13.0.0": version: 13.1.0 resolution: "commander@npm:13.1.0" @@ -6254,13 +6300,6 @@ __metadata: languageName: node linkType: hard -"compare-versions@npm:^6.1.0": - version: 6.1.1 - resolution: "compare-versions@npm:6.1.1" - checksum: 73fe6c4f52d22efe28f0a3be10df2afd704e10b3593360cd963e86b33a7a263c263b41a1361b69c30a0fe68bfa70fef90860c1cf2ef41502629d4402890fcd57 - languageName: node - linkType: hard - "concat-map@npm:0.0.1": version: 0.0.1 resolution: "concat-map@npm:0.0.1" @@ -6876,7 +6915,7 @@ __metadata: languageName: node linkType: hard -"dotenv@npm:^16.4.7": +"dotenv@npm:^16.4.5, dotenv@npm:^16.4.7": version: 16.5.0 resolution: "dotenv@npm:16.5.0" checksum: 6543fe87b5ddf2d60dd42df6616eec99148a5fc150cb4530fef5bda655db5204a3afa0e6f25f7cd64b20657ace4d79c0ef974bec32fdb462cad18754191e7a90 @@ -6894,20 +6933,6 @@ __metadata: languageName: node linkType: hard -"e2b@npm:1.2.0-beta.4": - version: 1.2.0-beta.4 - resolution: "e2b@npm:1.2.0-beta.4" - dependencies: - "@bufbuild/protobuf": ^2.2.2 - "@connectrpc/connect": 2.0.0-rc.3 - "@connectrpc/connect-web": 2.0.0-rc.3 - compare-versions: ^6.1.0 - openapi-fetch: ^0.9.7 - platform: ^1.3.6 - checksum: 98adde94c74d18313d71fca2fdc8bf99992940238e667f797d99e1b1987887b2ef20cd94d4275cf4033026f74486929a090fb3789def02a20b3361693f6950ae - languageName: node - linkType: hard - "eastasianwidth@npm:^0.2.0": version: 0.2.0 resolution: "eastasianwidth@npm:0.2.0" @@ -6915,6 +6940,18 @@ __metadata: languageName: node linkType: hard +"eciesjs@npm:^0.4.10": + version: 0.4.15 + resolution: "eciesjs@npm:0.4.15" + dependencies: + "@ecies/ciphers": ^0.2.3 + "@noble/ciphers": ^1.3.0 + "@noble/curves": ^1.9.1 + "@noble/hashes": ^1.8.0 + checksum: 133a0ded69da0579d7082fe89b6a15225cf5cf503f653438355c2106cfc42576ab75835421f6a1ad099b9b802f389fc0077e72a951fd0e7dbc5c1e5220457ac9 + languageName: node + linkType: hard + "ee-first@npm:1.1.1": version: 1.1.1 resolution: "ee-first@npm:1.1.1" @@ -7879,7 +7916,7 @@ __metadata: languageName: node linkType: hard -"execa@npm:^5.0.0": +"execa@npm:^5.0.0, execa@npm:^5.1.1": version: 5.1.1 resolution: "execa@npm:5.1.1" dependencies: @@ -8189,6 +8226,18 @@ __metadata: languageName: node linkType: hard +"fdir@npm:^6.2.0": + version: 6.4.5 + resolution: "fdir@npm:6.4.5" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 14efd2d6617a6f9fb314916ccff64e00bdb96216f26542ec9dfa532ed60a7ebb45463f7009aa215c14071566bf43caeb8ba268ccb52a11e6b51e4aaa8cb58d81 + languageName: node + linkType: hard + "fdir@npm:^6.4.4": version: 6.4.4 resolution: "fdir@npm:6.4.4" @@ -9284,7 +9333,7 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.2.0, ignore@npm:^5.3.1": +"ignore@npm:^5.2.0, ignore@npm:^5.3.0, ignore@npm:^5.3.1": version: 5.3.2 resolution: "ignore@npm:5.3.2" checksum: 2acfd32a573260ea522ea0bfeff880af426d68f6831f973129e2ba7363f422923cf53aab62f8369cbf4667c7b25b6f8a3761b34ecdb284ea18e87a5262a865be @@ -12549,6 +12598,13 @@ __metadata: languageName: node linkType: hard +"object-treeify@npm:1.1.33": + version: 1.1.33 + resolution: "object-treeify@npm:1.1.33" + checksum: 3af7f889349571ee73f5bdfb5ac478270c85eda8bcba950b454eb598ce41759a1ed6b0b43fbd624cb449080a4eb2df906b602e5138b6186b9563b692231f1694 + languageName: node + linkType: hard + "object.assign@npm:^4.1.4, object.assign@npm:^4.1.7": version: 4.1.7 resolution: "object.assign@npm:4.1.7" @@ -12703,15 +12759,6 @@ __metadata: languageName: node linkType: hard -"openapi-fetch@npm:^0.9.7": - version: 0.9.8 - resolution: "openapi-fetch@npm:0.9.8" - dependencies: - openapi-typescript-helpers: ^0.0.8 - checksum: 32a32698942b12b4c2fe2249eb90f745fa8dfde16d3312966e009fb7aaf7a233f883536ed58b1cdd58b6cafd6b55784e6aa7d13fefaf7c990929868e335d6cbe - languageName: node - linkType: hard - "openapi-types@npm:^12.0.0, openapi-types@npm:^12.1.3": version: 12.1.3 resolution: "openapi-types@npm:12.1.3" @@ -12719,13 +12766,6 @@ __metadata: languageName: node linkType: hard -"openapi-typescript-helpers@npm:^0.0.8": - version: 0.0.8 - resolution: "openapi-typescript-helpers@npm:0.0.8" - checksum: e309d7d297cf78308c41c324ffe094c3ef194117bf104b5300e45535d158265f665c69e810a143f1d3db7020575c3041e370d2ee93fc8094f5aabc14a366fc39 - languageName: node - linkType: hard - "optionator@npm:^0.9.3": version: 0.9.4 resolution: "optionator@npm:0.9.4" @@ -13111,13 +13151,6 @@ __metadata: languageName: node linkType: hard -"platform@npm:^1.3.6": - version: 1.3.6 - resolution: "platform@npm:1.3.6" - checksum: 6f472a09c61d418c7e26c1c16d0bdc029549d512dbec6526216a1e59ec68100d07007d0097dcba69dddad883d6f2a83361b4bdfe0094a3d9a2af24158643d85e - languageName: node - linkType: hard - "pony-cause@npm:^1.1.1": version: 1.1.1 resolution: "pony-cause@npm:1.1.1" @@ -16184,7 +16217,7 @@ __metadata: languageName: node linkType: hard -"uuid@npm:^11.0.5, uuid@npm:^11.1.0": +"uuid@npm:^11.0.3, uuid@npm:^11.0.5, uuid@npm:^11.1.0": version: 11.1.0 resolution: "uuid@npm:11.1.0" bin: @@ -16403,6 +16436,17 @@ __metadata: languageName: node linkType: hard +"which@npm:^4.0.0": + version: 4.0.0 + resolution: "which@npm:4.0.0" + dependencies: + isexe: ^3.1.1 + bin: + node-which: bin/which.js + checksum: f17e84c042592c21e23c8195108cff18c64050b9efb8459589116999ea9da6dd1509e6a1bac3aeebefd137be00fabbb61b5c2bc0aa0f8526f32b58ee2f545651 + languageName: node + linkType: hard + "which@npm:^5.0.0": version: 5.0.0 resolution: "which@npm:5.0.0"