From 353682c022fb89b44de94d41ab02bf548aa6dd1a Mon Sep 17 00:00:00 2001 From: Tomas Valenta Date: Wed, 1 May 2024 12:40:04 -0700 Subject: [PATCH] Remove runCode and runCmd; Cleanup --- .devcontainer/devcontainer.json | 30 - .../simple-gpt4-code-interpreter/page.mdx | 479 --------------- .../docs/src/app/sandbox/api/execute/page.mdx | 12 +- apps/docs/src/code/js/code_exec/run_code.js | 10 - .../src/code/python/code_exec/run_code.py | 12 - packages/cli/package.json | 3 +- .../complementing-ignore-files/.dockerignore | 5 - packages/cli/vitest.config.ts | 13 - packages/js-sdk/etc/sdk.api.md | 579 ------------------ packages/js-sdk/example.mts | 16 + packages/js-sdk/package.json | 4 +- packages/js-sdk/src/index.ts | 1 - packages/js-sdk/src/runCmd.ts | 16 - packages/js-sdk/src/runCode.ts | 75 --- packages/js-sdk/temp/sdk.api.md | 579 ------------------ packages/js-sdk/test/run.mjs | 14 - packages/js-sdk/test/runCode.test.mjs | 21 - packages/python-sdk/e2b/__init__.py | 1 - packages/python-sdk/e2b/sandbox/__init__.py | 1 - packages/python-sdk/e2b/sandbox/main.py | 2 - packages/python-sdk/e2b/sandbox/run_code.py | 65 -- packages/python-sdk/example.py | 2 +- packages/python-sdk/python-sdk-example.ipynb | 538 ---------------- packages/python-sdk/tests/test_run_code.py | 18 - pnpm-lock.yaml | 21 +- sandboxes/code-interpreter/README.md | 3 + 26 files changed, 41 insertions(+), 2479 deletions(-) delete mode 100644 .devcontainer/devcontainer.json delete mode 100644 apps/docs/src/app/guide/simple-gpt4-code-interpreter/page.mdx delete mode 100644 apps/docs/src/code/js/code_exec/run_code.js delete mode 100644 apps/docs/src/code/python/code_exec/run_code.py delete mode 100644 packages/cli/test/fixtures/complementing-ignore-files/.dockerignore delete mode 100644 packages/cli/vitest.config.ts delete mode 100644 packages/js-sdk/etc/sdk.api.md create mode 100644 packages/js-sdk/example.mts delete mode 100644 packages/js-sdk/src/runCmd.ts delete mode 100644 packages/js-sdk/src/runCode.ts delete mode 100644 packages/js-sdk/temp/sdk.api.md delete mode 100644 packages/js-sdk/test/run.mjs delete mode 100644 packages/js-sdk/test/runCode.test.mjs delete mode 100644 packages/python-sdk/e2b/sandbox/run_code.py delete mode 100644 packages/python-sdk/python-sdk-example.ipynb delete mode 100644 packages/python-sdk/tests/test_run_code.py create mode 100644 sandboxes/code-interpreter/README.md diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index d9624848c..000000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,30 +0,0 @@ -// For format details, see https://aka.ms/devcontainer.json. For config options, see the -// README at: https://github.com/devcontainers/templates/tree/main/src/ubuntu -{ - "name": "Ubuntu", - // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile - "image": "mcr.microsoft.com/devcontainers/base:jammy", - "features": { - "ghcr.io/devcontainers/features/docker-in-docker:2": {}, - "ghcr.io/devcontainers/features/github-cli:1": {}, - "ghcr.io/devcontainers/features/node:1": {}, - "ghcr.io/devcontainers/features/python:1": {}, - "ghcr.io/devcontainers-contrib/features/actions-runner:1": {}, - "ghcr.io/devcontainers-contrib/features/poetry:2": {} - } - - // Features to add to the dev container. More info: https://containers.dev/features. - // "features": {}, - - // Use 'forwardPorts' to make a list of ports inside the container available locally. - // "forwardPorts": [], - - // Use 'postCreateCommand' to run commands after the container is created. - // "postCreateCommand": "uname -a", - - // Configure tool-specific properties. - // "customizations": {}, - - // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. - // "remoteUser": "root" -} diff --git a/apps/docs/src/app/guide/simple-gpt4-code-interpreter/page.mdx b/apps/docs/src/app/guide/simple-gpt4-code-interpreter/page.mdx deleted file mode 100644 index 6bc8d8b6c..000000000 --- a/apps/docs/src/app/guide/simple-gpt4-code-interpreter/page.mdx +++ /dev/null @@ -1,479 +0,0 @@ -import { - PlusCircle, - Plus, - ChevronsUp, -} from 'lucide-react' - -export const ExtraIcon = ( - -) - -export const sections = [ - { title: 'Install E2B and OpenAI', id: 'install-e2-b-and-open-ai', }, - { title: 'Get API keys', id: 'get-api-keys', }, - { title: 'Import packages', id: 'import-packages', }, - { title: 'Make calls to GPT', id: 'make-calls-to-gpt', }, - { title: 'Prepare OpenAI functions', id: 'prepare-open-ai-functions', }, - { title: 'Parse GPT response', id: 'parse-gpt-response', }, - { title: 'Run GPT-generated code with E2B', id: 'run-gpt-generated-code-with-e2-b', }, - // { title: 'Let GPT install missing libraries', id: 'upgrade-let-gpt-install-missing-libraries', icon: ExtraIcon, }, - // { title: 'Let GPT fix generated code', id: 'upgrade-let-gpt-fix-generated-code', icon: ExtraIcon, }, - { title: 'Final code', id: 'final-code', }, -] - -# Build Custom Code Interpreter with E2B and GPT-4 - -This is an example of how to build a custom simple code interpreter that can execute JavaScript using [OpenAI GPT-4](https://platform.openai.com/docs/models) and [E2B](https://e2b.dev). {{ className: 'lead' }} - -## What is a Code Interpreter? - -[Code Interpreter](https://openai.com/blog/chatgpt-plugins?ref=blog.roboflow.com#code-interpreter) is a [ChatGPT plugin](https://platform.openai.com/docs/plugins/introduction) released by OpenAI that gives ChatGPT capabilities to run code. - -This guide will show you how to build your own custom code interpreter that can execute JavaScript code using E2B and GPT-4. {{ className: 'lead' }} - -You can find the final code for both Python and JavaScript in [this GitHub repository](https://github.com/e2b-dev/e2b-cookbook/tree/main). {{ className: 'lead' }} - -## Why to use E2B? -E2B allows you to execute the GPT-generated code in a sandboxed cloud environment. This means you can run the code without worrying about security issues and the potential harm the generated code can cause to your machine. {{ className: 'lead' }} - -## Install E2B and OpenAI - -First, install the required packages. We need to install the E2B package and OpenAI package. - - -```bash {{ language: 'js' }} -npm install e2b -npm install openai -``` - -```bash {{ language: 'python' }} -pip install e2b -pip install openai -``` - - -## Get API keys - -Let's get our API keys for E2B and OpenAI. We'll need them to use the APIs. - -1. Get your E2B API Key from [here](/getting-started/api-key) -2. Get your GPT-4 or GPT-3.5 at the [OpenAI website](https://platform.openai.com/) - -## Import packages - -Now we need to import the packages we installed in the previous step. - - -```js -import e2b from 'e2b' -import OpenAI from 'openai' -``` - -```python -import e2b -import openai - -# We'll need these later -import asyncio -import json -``` - - -## Make calls to GPT - -Here we set up the OpenAI chat completion endpoint that allows to call the GPT-4 (or GPT-3.5) models. - - -```js -const openai = new OpenAI() -const chatCompletion = await openai.chat.completions.create({ - model: 'gpt-4', // Or use 'gpt-3.5-turbo' - messages: [ - { - role: 'system', - content: 'You are a senior developer who can code in JavaScript. Always produce valid JSON.', - } - ], -}) -``` - -```python -response = openai.ChatCompletion.create( - model="gpt-4", # Or use gpt-3.5-turbo - messages=[ - { - "role": "system", - "content": "You are a senior developer who can code in JavaScript. Always produce valid JSON." - }, - ] -) -``` - - -If you print the response, you should see something like this: - -```json -{ - "id": "chatcmpl-846e96G7wm4s7dSqgWvnaPaanyQ3j", - "object": "chat.completion", - "created": 1695989553, - "model": "gpt-4-0613", - "choices": [ - { - "index": 0, - "message": { - "role": "assistant", - "content": "Great! How can I assist you today? Are you looking for help with JavaScript solutions, or do you need some general advice about software development?" - }, - "finish_reason": "stop" - } - ], - "usage": { - "prompt_tokens": 18, - "completion_tokens": 29, - "total_tokens": 47 - } -} -``` - -## Prepare OpenAI functions - -We're going to take advantage of the [OpenAI functions](https://openai.com/blog/function-calling-and-other-api-updates). Defining these functions will make it easier to instruct the model that it can write JavaScript code to complete requests from the user. We'll execute this code later using E2B. - - -```js -const functions = [ - { - name: 'exec_code', - description: 'Executes the passed JavaScript code using Nodejs and returns the stdout and stderr', - parameters: { - type: 'object', - properties: { - code: { - type: 'string', - description: 'The JavaScript code to execute.', - }, - }, - required: ['code'], - }, - }, -] -``` - -```python -functions = [ - { - "name": "exec_code", - "description": "Executes the passed JavaScript code using Nodejs and returns the stdout and stderr.", - "parameters": { - "type": "object", - "properties": { - "code": { - "type": "string", - "description": "The JavaScript code to execute.", - }, - }, - "required": ["code"], - }, - } -] -``` - - -We created an OpenAI function `exec_code` that expects a single parameter `code`. The `code` parameter will be the Python code generated by GPT that we'll execute. - -Now we pass the `functions` variable to the GPT call we made earlier and also add a few messages to show the model how to use the `exec_code` function. -The new code is marked by the highlighted lines. - - -```js -const chatCompletion = await openai.chat.completions.create({ - model: 'gpt-4', - messages: [ - { - role: 'system', - content: 'You are a senior developer who can code in JavaScript. Always produce valid JSON.', - }, - { // $HighlightLine - role: 'user', // $HighlightLine - content: 'Write hello world', // $HighlightLine - }, // $HighlightLine - { // $HighlightLine - role: 'assistant', // $HighlightLine - content: '{"code": "print("hello world")"}', // $HighlightLine - name: 'exec_code', // $HighlightLine - }, // $HighlightLine - { // $HighlightLine - role: 'user', // $HighlightLine - content: 'Generate first 100 fibonacci numbers', // $HighlightLine - }, // $HighlightLine - ], - functions, // $HighlightLine -}) -``` - -```python -response = openai.ChatCompletion.create( - model="gpt-4", - messages=[ - {"role": "system", "content": "You are a senior developer that can code in JavaScript. Always produce valid JSON."}, - {"role": "user", "content": "Write hello world"}, # $HighlightLine - {"role": "assistant", "content": "print(\"hello world\")", "name":"exec_code"}, # $HighlightLine - {"role": "user", "content": "Generate first 100 Fibonacci numbers"}, # $HighlightLine - ], - functions=functions, # $HighlightLine -) -``` - - -If you print the GPT response now, you'll most likely see the model is calling the `exec_code` function we defined earlier and is passing code for generating Fibonacci numbers in the first element of the `choices` JSON array. - -```json -{ - ... - "choices": [ - { - "index": 0, - "message": { - "role": "assistant", - "content": null, - "function_call": { - "name": "exec_code", - "arguments": "{\n \"code\": \"\n var fibonacciSequence = [0, 1];\n for(var i=2; i<100; i++){\n fibonacciSequence[i] = fibonacciSequence[i-1] + fibonacciSequence[i-2];\n }\n console.log(fibonacciSequence);\n \"\n}" - } - }, - "finish_reason": "function_call" - } - ], - ... -} -``` - -## Parse GPT response - -We need to parse the GPT's response and detect if it contains a function call. If it does and it's actually the `exec_code` function, we need to parse the `arguments` field, get the `code` argument and actually run the code using E2B (we'll do it in the next step). - - -```js -// ... previous code - -const message = chatCompletion.choices[0].message; -const func = message["function_call"]; -if (func) { - const funcName = func["name"]; - - // Get rid of newlines and leading/trailing spaces in the raw function arguments JSON string. - // This sometimes help to avoid JSON parsing errors. - let args = func["arguments"]; - args = args.trim().replace(/\n|\r/g, ""); - // Parse the cleaned up JSON string. - const funcArgs = JSON.parse(args); - - // If the model is calling the exec_code function we defined in the `functions` variable, we want to save the `code` argument to a variable. - if (funcName === "exec_code") { - const code = funcArgs["code"]; - // TODO: Execute the code using E2B. - } -} else { - // The model didn't call a function, so we just printed the message. - const content = message["content"]; - console.log(content); -} -``` - -```python -# ... previous code - -message = response["choices"][0]["message"] -if (func := message.get("function_call")): - func_name = func["name"] - - # Get rid of newlines and leading/trailing spaces in the raw function arguments JSON string. - # This sometimes help to avoid JSON parsing errors. - args = func["arguments"].strip().replace("\n", "") - # Parse the cleaned up JSON string. - func_args = json.loads(args) - - # If the model is calling the exec_code function we defined in the `functions` variable, we want to save the `code` argument to a variable. - if func_name == "exec_code": - code = func_args["code"] - # TODO: Execute the code using E2B. -else: - # The model didn't call a function, so we just printed the message. - content = message["content"] - print(content) -``` - - - - -## Run GPT-generated code with E2B - -It's time to actually run the code generated by GPT. We'll be using the `e2b.runCode`/`e2b.run_code` to execute the code in E2B's sandboxed playground. -All we need to add is just a single line of code. I highlighted it in the code snippets below. - - - - -```js -// ... previous code - -// If the model is calling the exec_code function we defined in the `functions` variable, we want to save the `code` argument to a variable. -if (funcName === "exec_code") { - const code = funcArgs["code"]; - // Execute the code using E2B. - const { stdout, stderr } = await e2b.runCode("Node16", code); // $HighlightLine - console.log(stdout); // $HighlightLine - console.error(stderr); // $HighlightLine -} - -// ... rest of the code -``` - -```python -# ... previous code - -# If the model is calling the exec_code function we defined in the `functions` variable, we want to save the `code` argument to a variable. -if func_name == "exec_code": - code = func_args["code"] - stdout, stderr = await e2b.run_code("Node16", code) # $HighlightLine - print(stdout) # $HighlightLine - print(stderr) # $HighlightLine - -# ... rest of the code -``` - - -And this is what the executed code for the "Generate first 100 Fibonacci numbers" prompt prints: -``` -[ - 0, 1, 1, - 2, 3, 5, - 8, 13, 21, - 34, 55, 89, - 144, 233, 377, - 610, 987, 1597, - 2584, 4181, 6765, - 10946, 17711, 28657, - 46368, 75025, 121393, - 196418, 317811, 514229, - 832040, 1346269, 2178309, - 3524578, 5702887, 9227465, - 14930352, 24157817, 39088169, - 63245986, 102334155, 165580141, - 267914296, 433494437, 701408733, - 1134903170, 1836311903, 2971215073, - 4807526976, 7778742049, 12586269025, - 20365011074, 32951280099, 53316291173, - 86267571272, 139583862445, 225851433717, - 365435296162, 591286729879, 956722026041, - 1548008755920, 2504730781961, 4052739537881, - 6557470319842, 10610209857723, 17167680177565, - 27777890035288, 44945570212853, 72723460248141, - 117669030460994, 190392490709135, 308061521170129, - 498454011879264, 806515533049393, 1304969544928657, - 2111485077978050, 3416454622906707, 5527939700884757, - 8944394323791464, 14472334024676220, 23416728348467684, - 37889062373143900, 61305790721611580, 99194853094755490, - 160500643816367070, 259695496911122560, 420196140727489660, - 679891637638612200, 1100087778366101900, 1779979416004714000, - 2880067194370816000, 4660046610375530000, 7540113804746346000, - 12200160415121877000, 19740274219868226000, 31940434634990100000, - 51680708854858330000, 83621143489848430000, 135301852344706760000, - 218922995834555200000 -] -``` - - -{/* ## Upgrade: Let GPT install missing libraries -The current version of our code interpreter has one big flaw. It doesn't allow to install missing libraries. If GPT decides to generate code that uses a library that is not installed, the code will fail to execute. -We're going to solve this problem by letting GPT install missing libraries by adding a new OpenAI function called `install_package`. - -This is what our new `functions` variable looks like. The highlighted lines are the new code. - - -```js -const functions = [ - { - name: "exec_code", - description: - "Executes the passed JavaScript code using Nodejs and returns the stdout and stderr.", - parameters: { - type: "object", - properties: { - code: { - type: "string", - description: "The JavaScript code to execute.", - }, - }, - required: ["code"], - }, - }, - { // $HighlightLine - name: "install_package", // $HighlightLine - description: "Installs the passed npm package.", // $HighlightLine - parameters: { // $HighlightLine - type: "object", // $HighlightLine - properties: { // $HighlightLine - name: { // $HighlightLine - type: "string", // $HighlightLine - description: "The name of an npm package to install.", // $HighlightLine - }, // $HighlightLine - }, // $HighlightLine - required: ["name"], // $HighlightLine - }, // $HighlightLine - }, // $HighlightLine -]; -``` -```python -functions = [ - { - "name": "exec_code", - "description": "Executes the passed JavaScript code using Nodejs and returns the stdout and stderr.", - "parameters": { - "type": "object", - "properties": { - "code": { - "type": "string", - "description": "The JavaScript code to execute.", - }, - }, - "required": ["code"], - }, - }, - { # $HighlightLine - "name": "install_package", # $HighlightLine - "description": "Installs the passed npm package.", # $HighlightLine - "parameters": { # $HighlightLine - "type": "object", # $HighlightLine - "properties": { # $HighlightLine - "name": { # $HighlightLine - "type": "string", # $HighlightLine - "description": "The name of an npm package to install.", # $HighlightLine - }, # $HighlightLine - }, # $HighlightLine - "required": ["name"], # $HighlightLine - }, # $HighlightLine - } # $HighlightLine -] -``` - - -Now we need to add a new `if` statement to our code that will detect if the model is calling the `install_package` function and if it does, we need to install the package using E2B. - - - - -### Switch to long-running session with E2B -TODO - -## Upgrade: Let GPT fix generated code -TODO - */} - - -## Final code -You can find the final code for both Python and JavaScript in [this GitHub repository](https://github.com/e2b-dev/e2b-cookbook/tree/main). {{ className: 'lead' }} diff --git a/apps/docs/src/app/sandbox/api/execute/page.mdx b/apps/docs/src/app/sandbox/api/execute/page.mdx index d965037f7..13fddcc03 100644 --- a/apps/docs/src/app/sandbox/api/execute/page.mdx +++ b/apps/docs/src/app/sandbox/api/execute/page.mdx @@ -1,18 +1,8 @@ # Code Execution You can use E2B SDK to safely execute code generated by LLM inside the sandbox. {{ className: 'lead' }} -There are 2 ways to run code with E2B SDK. {{ className: 'lead' }} -### 1. Use the `runCode`/`run_code` methods in JS and Python SDK to run the LLM-generated code {{ className: 'lead' }} - -This approach is very straightforward and you don't need to worry about managing the sandbox lifecycle or the process lifecycle. - - - -### 2. Run the LLM-generated code using the low-level sandbox.process module {{ className: 'lead' }} +### 1. Run the LLM-generated code using the low-level sandbox.process module {{ className: 'lead' }} This approach gives you more control over the underlying sandbox and the running process. You can for example stream stdout and stderr, or kill the process that's running the code. diff --git a/apps/docs/src/code/js/code_exec/run_code.js b/apps/docs/src/code/js/code_exec/run_code.js deleted file mode 100644 index b7f5c3d13..000000000 --- a/apps/docs/src/code/js/code_exec/run_code.js +++ /dev/null @@ -1,10 +0,0 @@ -// 1. Import e2b -import {runCode} from 'e2b' - -// 2. Save LLM-generated code -const llmGeneratedCode = 'print("This code was generated by LLM")' - -// 3. Select runtime & run code in a sandboxed remote environment -const {stdout, stderr} = await runCode('Python3', llmGeneratedCode) // $HighlightLine -console.log(stdout) -console.log(stderr) diff --git a/apps/docs/src/code/python/code_exec/run_code.py b/apps/docs/src/code/python/code_exec/run_code.py deleted file mode 100644 index 7c80f7b20..000000000 --- a/apps/docs/src/code/python/code_exec/run_code.py +++ /dev/null @@ -1,12 +0,0 @@ -from e2b import run_code - -llm_generated_code = 'print("This code was generated by LLM")' - - -def main(): - stdout, stderr = run_code('Python3', llm_generated_code) # $HighlightLine - print(stdout) - print(stderr) - - -main() diff --git a/packages/cli/package.json b/packages/cli/package.json index f6d616d2d..bc8ae347c 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -35,8 +35,7 @@ "knip": "^2.33.4", "npm-check-updates": "^16.14.6", "tsup": "^7.2.0", - "typescript": "^5.2.2", - "vitest": "^0.34.6" + "typescript": "^5.2.2" }, "files": [ "dist", diff --git a/packages/cli/test/fixtures/complementing-ignore-files/.dockerignore b/packages/cli/test/fixtures/complementing-ignore-files/.dockerignore deleted file mode 100644 index 539121bdb..000000000 --- a/packages/cli/test/fixtures/complementing-ignore-files/.dockerignore +++ /dev/null @@ -1,5 +0,0 @@ -.dockerignore -.gitignore -Dockerfile -README.md -assets-to-be-ignored diff --git a/packages/cli/vitest.config.ts b/packages/cli/vitest.config.ts deleted file mode 100644 index e18526b02..000000000 --- a/packages/cli/vitest.config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineConfig } from 'vitest/config' - -export default defineConfig({ - test: { - threads: false, - globals: false, - environment: 'node', - server: {}, - deps: { - interopDefault: true, - }, - }, -}) diff --git a/packages/js-sdk/etc/sdk.api.md b/packages/js-sdk/etc/sdk.api.md deleted file mode 100644 index 71dc72aad..000000000 --- a/packages/js-sdk/etc/sdk.api.md +++ /dev/null @@ -1,579 +0,0 @@ -## API Report File for "@e2b/sdk" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts - -import * as fetcher from 'openapi-typescript-fetch'; -import { OpArgType } from 'openapi-typescript-fetch'; -import * as openapi_typescript_fetch_dist_cjs_types from 'openapi-typescript-fetch/dist/cjs/types'; -import { Run } from 'openai/resources/beta/threads/runs/runs'; -import { RunSubmitToolOutputsParams } from 'openai/resources/beta/threads/runs/runs'; -import { TypedFetch } from 'openapi-typescript-fetch'; - -// @public (undocumented) -export interface Action { - // (undocumented) - (sandbox: S, args: T): string | Promise; -} - -// @public (undocumented) -export const api: { - configure: (config: openapi_typescript_fetch_dist_cjs_types.FetchConfig) => void; - use: (mw: fetcher.Middleware) => number; - path:

(path: P) => { - method: (method: M) => { - create: openapi_typescript_fetch_dist_cjs_types.CreateFetch; - }; - }; -}; - -// @public (undocumented) -export const API_HOST: string; - -// @public (undocumented) -export class Artifact { - constructor(path: string, sandbox: S); - // (undocumented) - readonly path: string; - // (undocumented) - readonly _sandbox: S; -} - -// @public (undocumented) -export type ClientType = typeof api; - -// @public (undocumented) -export enum CodeRuntime { - // (undocumented) - Bash = "Bash", - // (undocumented) - Node16 = "Node16", - // (undocumented) - Python3 = "Python3", - // (undocumented) - Python3_DataAnalysis = "Python3-DataAnalysis" -} - -// @public (undocumented) -export interface components { - // (undocumented) - parameters: { - envID: string; - buildID: string; - instanceID: string; - }; - // (undocumented) - responses: { - 400: { - content: { - "application/json": components["schemas"]["Error"]; - }; - }; - 401: { - content: { - "application/json": components["schemas"]["Error"]; - }; - }; - 404: { - content: { - "application/json": components["schemas"]["Error"]; - }; - }; - 500: { - content: { - "application/json": components["schemas"]["Error"]; - }; - }; - }; - // (undocumented) - schemas: { - NewInstance: { - envID: string; - }; - Environment: { - envID: string; - buildID: string; - public: boolean; - aliases?: string[]; - }; - EnvironmentBuild: { - logs: string[]; - envID: string; - buildID: string; - status?: "building" | "ready" | "error"; - } & { - finished: unknown; - }; - Instance: { - envID: string; - instanceID: string; - clientID: string; - }; - Error: { - code: number; - message: string; - }; - }; -} - -// @public (undocumented) -class DataAnalysis extends Sandbox { - constructor(opts: Omit); - // (undocumented) - static create(): Promise; - // (undocumented) - static create(opts: Omit): Promise; - // (undocumented) - installPythonPackages(packageNames: string | string[]): Promise; - // (undocumented) - installSystemPackages(packageNames: string | string[]): Promise; - // (undocumented) - runPython(code: string, opts?: RunPythonOpts): Promise<{ - stdout: string; - stderr: string; - artifacts: Artifact[]; - }>; -} -export { DataAnalysis as CodeInterpreter } -export { DataAnalysis } - -// @public (undocumented) -export type DownloadFileFormat = 'base64' | 'blob' | 'buffer' | 'arraybuffer' | 'text'; - -// @public (undocumented) -export type EnvVars = { - [key: string]: string; -}; - -// @public (undocumented) -export interface FileInfo { - // (undocumented) - isDir: boolean; - // (undocumented) - name: string; -} - -// @public (undocumented) -export interface FilesystemEvent { - // (undocumented) - isDir: boolean; - // (undocumented) - name: string; - // (undocumented) - operation: FilesystemOperation; - // (undocumented) - path: string; - // (undocumented) - timestamp: number; -} - -// @public (undocumented) -export type FilesystemEventListener = (event: FilesystemEvent) => Promise | void; - -// @public -export interface FilesystemManager { - list(path: string, opts?: CallOpts): Promise; - makeDir(path: string, opts?: CallOpts): Promise; - read(path: string, opts?: CallOpts): Promise; - readBytes(path: string): Promise; - remove(path: string, opts?: CallOpts): Promise; - watchDir(path: string): FilesystemWatcher; - // Warning: (ae-forgotten-export) The symbol "CallOpts" needs to be exported by the entry point index.d.ts - write(path: string, content: string, opts?: CallOpts): Promise; - writeBytes(path: string, content: Uint8Array): Promise; -} - -// @public (undocumented) -export enum FilesystemOperation { - // (undocumented) - Chmod = "Chmod", - // (undocumented) - Create = "Create", - // (undocumented) - Remove = "Remove", - // (undocumented) - Rename = "Rename", - // (undocumented) - Write = "Write" -} - -// @public (undocumented) -export class FilesystemWatcher { - // Warning: (ae-forgotten-export) The symbol "SandboxConnection" needs to be exported by the entry point index.d.ts - constructor(sessConn: SandboxConnection, path: string); - // (undocumented) - addEventListener(l: FilesystemEventListener): () => boolean; - // (undocumented) - start(opts?: CallOpts): Promise; - // (undocumented) - stop(): Promise; -} - -// @public (undocumented) -export interface OpenPort { - // (undocumented) - ip: string; - // (undocumented) - port: number; - // (undocumented) - state: string; -} - -// @public -export interface paths { - // (undocumented) - "/envs": { - get: { - responses: { - 200: { - content: { - "application/json": components["schemas"]["Environment"][]; - }; - }; - 401: components["responses"]["401"]; - 500: components["responses"]["500"]; - }; - }; - post: { - responses: { - 202: { - content: { - "application/json": components["schemas"]["Environment"]; - }; - }; - 401: components["responses"]["401"]; - 500: components["responses"]["500"]; - }; - requestBody: { - content: { - "multipart/form-data": { - alias?: string; - buildContext: string; - dockerfile: string; - startCmd?: string; - }; - }; - }; - }; - }; - // (undocumented) - "/envs/{envID}": { - post: { - parameters: { - path: { - envID: components["parameters"]["envID"]; - }; - }; - responses: { - 202: { - content: { - "application/json": components["schemas"]["Environment"]; - }; - }; - 401: components["responses"]["401"]; - 500: components["responses"]["500"]; - }; - requestBody: { - content: { - "multipart/form-data": { - alias?: string; - buildContext: string; - dockerfile: string; - startCmd?: string; - }; - }; - }; - }; - delete: { - parameters: { - path: { - envID: components["parameters"]["envID"]; - }; - }; - responses: { - 204: never; - 401: components["responses"]["401"]; - 500: components["responses"]["500"]; - }; - }; - }; - // (undocumented) - "/envs/{envID}/builds/{buildID}": { - get: { - parameters: { - path: { - envID: components["parameters"]["envID"]; - buildID: components["parameters"]["buildID"]; - }; - query: { - logsOffset?: number; - }; - }; - responses: { - 200: { - content: { - "application/json": components["schemas"]["EnvironmentBuild"]; - }; - }; - 401: components["responses"]["401"]; - 404: components["responses"]["404"]; - 500: components["responses"]["500"]; - }; - }; - }; - // (undocumented) - "/envs/{envID}/builds/{buildID}/logs": { - post: { - parameters: { - path: { - envID: components["parameters"]["envID"]; - buildID: components["parameters"]["buildID"]; - }; - }; - responses: { - 201: unknown; - 401: components["responses"]["401"]; - 404: components["responses"]["404"]; - }; - requestBody: { - content: { - "application/json": { - apiSecret: string; - logs: string[]; - }; - }; - }; - }; - }; - // (undocumented) - "/health": { - get: { - responses: { - 200: unknown; - 401: components["responses"]["401"]; - }; - }; - }; - // (undocumented) - "/instances": { - post: { - responses: { - 201: { - content: { - "application/json": components["schemas"]["Instance"]; - }; - }; - 400: components["responses"]["400"]; - 401: components["responses"]["401"]; - 500: components["responses"]["500"]; - }; - requestBody: { - content: { - "application/json": components["schemas"]["NewInstance"]; - }; - }; - }; - }; - // (undocumented) - "/instances/{instanceID}/refreshes": { - post: { - parameters: { - path: { - instanceID: components["parameters"]["instanceID"]; - }; - }; - responses: { - 204: never; - 401: components["responses"]["401"]; - 404: components["responses"]["404"]; - }; - requestBody: { - content: { - "application/json": { - duration?: number; - }; - }; - }; - }; - }; -} - -// @public -export class Process { - constructor(processID: string, sandbox: SandboxConnection, triggerExit: () => void, finished: Promise, output: ProcessOutput); - // @deprecated (undocumented) - readonly finished: Promise; - kill(): Promise; - // (undocumented) - readonly output: ProcessOutput; - // (undocumented) - readonly processID: string; - sendStdin(data: string, opts?: CallOpts): Promise; - wait(): Promise; -} - -// @public -export interface ProcessManager { - start(cmd: string): Promise; - // Warning: (ae-forgotten-export) The symbol "ProcessOpts" needs to be exported by the entry point index.d.ts - start(opts: ProcessOpts): Promise; - startAndWait(cmd: string): Promise; - startAndWait(opts: ProcessOpts): Promise; -} - -// @public -export class ProcessMessage { - constructor(line: string, - timestamp: number, error: boolean); - // (undocumented) - readonly error: boolean; - // (undocumented) - readonly line: string; - readonly timestamp: number; - // (undocumented) - toString(): string; -} - -// @public -export class ProcessOutput { - // (undocumented) - addStderr(message: ProcessMessage): void; - // (undocumented) - addStdout(message: ProcessMessage): void; - get error(): boolean; - get exitCode(): number | undefined; - // (undocumented) - setExitCode(exitCode: number): void; - get stderr(): string; - get stdout(): string; -} - -// @public -export function runCode(runtime: CodeRuntime, code: string, opts?: { - apiKey?: string; -}): Promise<{ - stdout: string; - stderr: string; -}>; - -// @public (undocumented) -export interface RunPythonOpts extends Omit { - // (undocumented) - onArtifact?: (artifact: Artifact) => Promise | void; -} - -// @public -class Sandbox extends SandboxConnection { - protected constructor(opts?: SandboxOpts); - get actions(): Map>; - // (undocumented) - readonly _actions: Map>; - addAction(action: Action): this; - addAction(name: string, action: Action): this; - static create(): Promise; - static create(template: string): Promise; - static create(opts: SandboxOpts): Promise; - downloadFile(remotePath: string, format?: DownloadFileFormat): Promise; - readonly filesystem: FilesystemManager; - get fileURL(): string; - // (undocumented) - protected _open(opts: CallOpts): Promise; - get openai(): { - readonly actions: Actions; - }; - readonly process: ProcessManager; - static reconnect(sandboxID: string): Promise; - static reconnect(opts: Omit & { - sandboxID: string; - }): Promise; - removeAction(name: string): this; - readonly terminal: TerminalManager; - uploadFile(file: Buffer | Blob, filename: string): Promise; -} -export { Sandbox } -export default Sandbox; - -// @public (undocumented) -export const SANDBOX_DOMAIN: string; - -// Warning: (ae-forgotten-export) The symbol "SandboxConnectionOpts" needs to be exported by the entry point index.d.ts -// -// @public (undocumented) -export interface SandboxOpts extends SandboxConnectionOpts { - // (undocumented) - onExit?: (() => Promise | void) | ((exitCode: number) => Promise | void); - // Warning: (ae-forgotten-export) The symbol "ScanOpenedPortsHandler" needs to be exported by the entry point index.d.ts - // - // (undocumented) - onScanPorts?: ScanOpenedPortsHandler; - // (undocumented) - onStderr?: (out: ProcessMessage) => Promise | void; - // (undocumented) - onStdout?: (out: ProcessMessage) => Promise | void; - timeout?: number; -} - -// @public -export class Terminal { - constructor(terminalID: string, sandbox: SandboxConnection, triggerExit: () => void, finished: Promise, output: TerminalOutput); - // (undocumented) - get data(): string; - // @deprecated (undocumented) - readonly finished: Promise; - kill(): Promise; - // (undocumented) - readonly output: TerminalOutput; - resize({ cols, rows }: { - cols: number; - rows: number; - }): Promise; - sendData(data: string): Promise; - // (undocumented) - readonly terminalID: string; - wait(): Promise; -} - -// @public -export interface TerminalManager { - // Warning: (ae-forgotten-export) The symbol "TerminalOpts" needs to be exported by the entry point index.d.ts - // - // (undocumented) - start(opts: TerminalOpts): Promise; -} - -// @public (undocumented) -export class TerminalOutput { - // (undocumented) - addData(data: string): void; - // (undocumented) - get data(): string; -} - -// Warning: (ae-forgotten-export) The symbol "WithAccessToken" needs to be exported by the entry point index.d.ts -// -// @public (undocumented) -export function withAccessToken(f: TypedFetch): WithAccessToken & { - Error: typeof f.Error; -}; - -// Warning: (ae-forgotten-export) The symbol "WithAPIKey" needs to be exported by the entry point index.d.ts -// -// @public (undocumented) -export function withAPIKey(f: TypedFetch): WithAPIKey & { - Error: typeof f.Error; -}; - -// Warnings were encountered during analysis: -// -// dist/index.d.ts:834:9 - (ae-forgotten-export) The symbol "Actions" needs to be exported by the entry point index.d.ts - -// (No @packageDocumentation comment for this package) - -``` diff --git a/packages/js-sdk/example.mts b/packages/js-sdk/example.mts new file mode 100644 index 000000000..1394d744a --- /dev/null +++ b/packages/js-sdk/example.mts @@ -0,0 +1,16 @@ +import { config } from 'dotenv' + +import { Sandbox } from './dist' + +config() + +const sandbox = await Sandbox.create({ + logger: { + error: console.error, + warn: console.warn, + info: console.info, + }, +}) +console.log(sandbox.id) + +await sandbox.close() diff --git a/packages/js-sdk/package.json b/packages/js-sdk/package.json index 06e7b0e02..1710766f9 100644 --- a/packages/js-sdk/package.json +++ b/packages/js-sdk/package.json @@ -27,7 +27,7 @@ "build": "tsc --noEmit && tsup", "dev": "tsup --watch", "measure": "node test/performance.mjs", - "run": "node test/run.mjs", + "example": "tsx example.mts", "test": "vitest run", "test:coverage": "vitest run --coverage", "generate": "openapi-typescript ../../spec/openapi.yml -x api_key --support-array-length --alphabetize --output src/api/schema.gen.ts", @@ -88,4 +88,4 @@ "bufferutil": "^4.0.8", "utf-8-validate": "^6.0.3" } -} +} \ No newline at end of file diff --git a/packages/js-sdk/src/index.ts b/packages/js-sdk/src/index.ts index e68a9df15..757da4371 100644 --- a/packages/js-sdk/src/index.ts +++ b/packages/js-sdk/src/index.ts @@ -20,7 +20,6 @@ export { AuthenticationError, CurrentWorkingDirectoryDoesntExistError, TimeoutEr export { Process, ProcessMessage, ProcessOutput } from './sandbox/process' export type { ProcessManager } from './sandbox/process' export type { EnvVars } from './sandbox/envVars' -export { runCode, CodeRuntime } from './runCode' // Export CodeRuntime enum as value, not as type, so it can be actually used in consumer code import { Sandbox } from './sandbox' export type { SandboxMetadata, RunningSandbox } from './sandbox/sandboxConnection' diff --git a/packages/js-sdk/src/runCmd.ts b/packages/js-sdk/src/runCmd.ts deleted file mode 100644 index c96b0ac39..000000000 --- a/packages/js-sdk/src/runCmd.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Sandbox } from './sandbox' - -export async function runCmd(command: string, opts?: { apiKey?: string }) { - const sandbox = await Sandbox.create({ - apiKey: opts?.apiKey || process?.env?.E2B_API_KEY || '', // Sandbox.create will throw an error if the API key is not provided so no need to check here - }) - - const out = await sandbox.process.startAndWait(command) - - await sandbox.close() - - return { - stdout: out.stdout, - stderr: out.stderr, - } -} diff --git a/packages/js-sdk/src/runCode.ts b/packages/js-sdk/src/runCode.ts deleted file mode 100644 index 875feec12..000000000 --- a/packages/js-sdk/src/runCode.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Sandbox } from './sandbox' - -export enum CodeRuntime { - Node16 = 'Node16', - Python3 = 'Python3', - Bash = 'Bash', - Python3_DataAnalysis = 'Python3-DataAnalysis', -} - -/** - * Run code in a sandboxed cloud playground. - * `runCode` wraps the `Sandbox` class and provides a simple interface for running code in a sandboxed environment - * without any need to manage lifecycle of the sandbox. - * `runCode` automatically loads the E2B API key from the `E2B_API_KEY` environment variable. - * - * @param runtime The runtime to use when running the code. Can be one of the following: - * - "Node16" - * - "Python3" - * - * **Let us know if you need support for other runtimes.** - * @param code The code to run - * @param opts Optional parameters to pass - * @returns - */ -export async function runCode( - runtime: CodeRuntime, - code: string, - opts?: { apiKey?: string }, -) { - let binary = '' - let filepath = '' - let envID = '' - switch (runtime) { - case CodeRuntime.Node16: - envID = 'base' - binary = 'node' - filepath = '/index.js' - break - case CodeRuntime.Python3: - envID = 'base' - binary = 'python3' - filepath = '/main.py' - break - case CodeRuntime.Python3_DataAnalysis: - envID = 'Python3-DataAnalysis' - binary = 'python3' - filepath = '/main.py' - break - case CodeRuntime.Bash: - envID = 'base' - binary = 'bash' - filepath = '/main.sh' - break - default: - throw new Error( - `The "${runtime}" runtime isn't supported. Please contact us (hello@e2b.dev) if you need support for this runtime`, - ) - } - - const sandbox = await Sandbox.create({ - template: envID, - apiKey: opts?.apiKey || process?.env?.E2B_API_KEY || '', // Sandbox.create will throw an error if the API key is not provided so no need to check here - }) - - await sandbox.filesystem.write(filepath, code) - - const out = await sandbox.process.startAndWait(`${binary} ${filepath}`) - - await sandbox.close() - - return { - stdout: out.stdout, - stderr: out.stderr, - } -} diff --git a/packages/js-sdk/temp/sdk.api.md b/packages/js-sdk/temp/sdk.api.md deleted file mode 100644 index 71dc72aad..000000000 --- a/packages/js-sdk/temp/sdk.api.md +++ /dev/null @@ -1,579 +0,0 @@ -## API Report File for "@e2b/sdk" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts - -import * as fetcher from 'openapi-typescript-fetch'; -import { OpArgType } from 'openapi-typescript-fetch'; -import * as openapi_typescript_fetch_dist_cjs_types from 'openapi-typescript-fetch/dist/cjs/types'; -import { Run } from 'openai/resources/beta/threads/runs/runs'; -import { RunSubmitToolOutputsParams } from 'openai/resources/beta/threads/runs/runs'; -import { TypedFetch } from 'openapi-typescript-fetch'; - -// @public (undocumented) -export interface Action { - // (undocumented) - (sandbox: S, args: T): string | Promise; -} - -// @public (undocumented) -export const api: { - configure: (config: openapi_typescript_fetch_dist_cjs_types.FetchConfig) => void; - use: (mw: fetcher.Middleware) => number; - path:

(path: P) => { - method: (method: M) => { - create: openapi_typescript_fetch_dist_cjs_types.CreateFetch; - }; - }; -}; - -// @public (undocumented) -export const API_HOST: string; - -// @public (undocumented) -export class Artifact { - constructor(path: string, sandbox: S); - // (undocumented) - readonly path: string; - // (undocumented) - readonly _sandbox: S; -} - -// @public (undocumented) -export type ClientType = typeof api; - -// @public (undocumented) -export enum CodeRuntime { - // (undocumented) - Bash = "Bash", - // (undocumented) - Node16 = "Node16", - // (undocumented) - Python3 = "Python3", - // (undocumented) - Python3_DataAnalysis = "Python3-DataAnalysis" -} - -// @public (undocumented) -export interface components { - // (undocumented) - parameters: { - envID: string; - buildID: string; - instanceID: string; - }; - // (undocumented) - responses: { - 400: { - content: { - "application/json": components["schemas"]["Error"]; - }; - }; - 401: { - content: { - "application/json": components["schemas"]["Error"]; - }; - }; - 404: { - content: { - "application/json": components["schemas"]["Error"]; - }; - }; - 500: { - content: { - "application/json": components["schemas"]["Error"]; - }; - }; - }; - // (undocumented) - schemas: { - NewInstance: { - envID: string; - }; - Environment: { - envID: string; - buildID: string; - public: boolean; - aliases?: string[]; - }; - EnvironmentBuild: { - logs: string[]; - envID: string; - buildID: string; - status?: "building" | "ready" | "error"; - } & { - finished: unknown; - }; - Instance: { - envID: string; - instanceID: string; - clientID: string; - }; - Error: { - code: number; - message: string; - }; - }; -} - -// @public (undocumented) -class DataAnalysis extends Sandbox { - constructor(opts: Omit); - // (undocumented) - static create(): Promise; - // (undocumented) - static create(opts: Omit): Promise; - // (undocumented) - installPythonPackages(packageNames: string | string[]): Promise; - // (undocumented) - installSystemPackages(packageNames: string | string[]): Promise; - // (undocumented) - runPython(code: string, opts?: RunPythonOpts): Promise<{ - stdout: string; - stderr: string; - artifacts: Artifact[]; - }>; -} -export { DataAnalysis as CodeInterpreter } -export { DataAnalysis } - -// @public (undocumented) -export type DownloadFileFormat = 'base64' | 'blob' | 'buffer' | 'arraybuffer' | 'text'; - -// @public (undocumented) -export type EnvVars = { - [key: string]: string; -}; - -// @public (undocumented) -export interface FileInfo { - // (undocumented) - isDir: boolean; - // (undocumented) - name: string; -} - -// @public (undocumented) -export interface FilesystemEvent { - // (undocumented) - isDir: boolean; - // (undocumented) - name: string; - // (undocumented) - operation: FilesystemOperation; - // (undocumented) - path: string; - // (undocumented) - timestamp: number; -} - -// @public (undocumented) -export type FilesystemEventListener = (event: FilesystemEvent) => Promise | void; - -// @public -export interface FilesystemManager { - list(path: string, opts?: CallOpts): Promise; - makeDir(path: string, opts?: CallOpts): Promise; - read(path: string, opts?: CallOpts): Promise; - readBytes(path: string): Promise; - remove(path: string, opts?: CallOpts): Promise; - watchDir(path: string): FilesystemWatcher; - // Warning: (ae-forgotten-export) The symbol "CallOpts" needs to be exported by the entry point index.d.ts - write(path: string, content: string, opts?: CallOpts): Promise; - writeBytes(path: string, content: Uint8Array): Promise; -} - -// @public (undocumented) -export enum FilesystemOperation { - // (undocumented) - Chmod = "Chmod", - // (undocumented) - Create = "Create", - // (undocumented) - Remove = "Remove", - // (undocumented) - Rename = "Rename", - // (undocumented) - Write = "Write" -} - -// @public (undocumented) -export class FilesystemWatcher { - // Warning: (ae-forgotten-export) The symbol "SandboxConnection" needs to be exported by the entry point index.d.ts - constructor(sessConn: SandboxConnection, path: string); - // (undocumented) - addEventListener(l: FilesystemEventListener): () => boolean; - // (undocumented) - start(opts?: CallOpts): Promise; - // (undocumented) - stop(): Promise; -} - -// @public (undocumented) -export interface OpenPort { - // (undocumented) - ip: string; - // (undocumented) - port: number; - // (undocumented) - state: string; -} - -// @public -export interface paths { - // (undocumented) - "/envs": { - get: { - responses: { - 200: { - content: { - "application/json": components["schemas"]["Environment"][]; - }; - }; - 401: components["responses"]["401"]; - 500: components["responses"]["500"]; - }; - }; - post: { - responses: { - 202: { - content: { - "application/json": components["schemas"]["Environment"]; - }; - }; - 401: components["responses"]["401"]; - 500: components["responses"]["500"]; - }; - requestBody: { - content: { - "multipart/form-data": { - alias?: string; - buildContext: string; - dockerfile: string; - startCmd?: string; - }; - }; - }; - }; - }; - // (undocumented) - "/envs/{envID}": { - post: { - parameters: { - path: { - envID: components["parameters"]["envID"]; - }; - }; - responses: { - 202: { - content: { - "application/json": components["schemas"]["Environment"]; - }; - }; - 401: components["responses"]["401"]; - 500: components["responses"]["500"]; - }; - requestBody: { - content: { - "multipart/form-data": { - alias?: string; - buildContext: string; - dockerfile: string; - startCmd?: string; - }; - }; - }; - }; - delete: { - parameters: { - path: { - envID: components["parameters"]["envID"]; - }; - }; - responses: { - 204: never; - 401: components["responses"]["401"]; - 500: components["responses"]["500"]; - }; - }; - }; - // (undocumented) - "/envs/{envID}/builds/{buildID}": { - get: { - parameters: { - path: { - envID: components["parameters"]["envID"]; - buildID: components["parameters"]["buildID"]; - }; - query: { - logsOffset?: number; - }; - }; - responses: { - 200: { - content: { - "application/json": components["schemas"]["EnvironmentBuild"]; - }; - }; - 401: components["responses"]["401"]; - 404: components["responses"]["404"]; - 500: components["responses"]["500"]; - }; - }; - }; - // (undocumented) - "/envs/{envID}/builds/{buildID}/logs": { - post: { - parameters: { - path: { - envID: components["parameters"]["envID"]; - buildID: components["parameters"]["buildID"]; - }; - }; - responses: { - 201: unknown; - 401: components["responses"]["401"]; - 404: components["responses"]["404"]; - }; - requestBody: { - content: { - "application/json": { - apiSecret: string; - logs: string[]; - }; - }; - }; - }; - }; - // (undocumented) - "/health": { - get: { - responses: { - 200: unknown; - 401: components["responses"]["401"]; - }; - }; - }; - // (undocumented) - "/instances": { - post: { - responses: { - 201: { - content: { - "application/json": components["schemas"]["Instance"]; - }; - }; - 400: components["responses"]["400"]; - 401: components["responses"]["401"]; - 500: components["responses"]["500"]; - }; - requestBody: { - content: { - "application/json": components["schemas"]["NewInstance"]; - }; - }; - }; - }; - // (undocumented) - "/instances/{instanceID}/refreshes": { - post: { - parameters: { - path: { - instanceID: components["parameters"]["instanceID"]; - }; - }; - responses: { - 204: never; - 401: components["responses"]["401"]; - 404: components["responses"]["404"]; - }; - requestBody: { - content: { - "application/json": { - duration?: number; - }; - }; - }; - }; - }; -} - -// @public -export class Process { - constructor(processID: string, sandbox: SandboxConnection, triggerExit: () => void, finished: Promise, output: ProcessOutput); - // @deprecated (undocumented) - readonly finished: Promise; - kill(): Promise; - // (undocumented) - readonly output: ProcessOutput; - // (undocumented) - readonly processID: string; - sendStdin(data: string, opts?: CallOpts): Promise; - wait(): Promise; -} - -// @public -export interface ProcessManager { - start(cmd: string): Promise; - // Warning: (ae-forgotten-export) The symbol "ProcessOpts" needs to be exported by the entry point index.d.ts - start(opts: ProcessOpts): Promise; - startAndWait(cmd: string): Promise; - startAndWait(opts: ProcessOpts): Promise; -} - -// @public -export class ProcessMessage { - constructor(line: string, - timestamp: number, error: boolean); - // (undocumented) - readonly error: boolean; - // (undocumented) - readonly line: string; - readonly timestamp: number; - // (undocumented) - toString(): string; -} - -// @public -export class ProcessOutput { - // (undocumented) - addStderr(message: ProcessMessage): void; - // (undocumented) - addStdout(message: ProcessMessage): void; - get error(): boolean; - get exitCode(): number | undefined; - // (undocumented) - setExitCode(exitCode: number): void; - get stderr(): string; - get stdout(): string; -} - -// @public -export function runCode(runtime: CodeRuntime, code: string, opts?: { - apiKey?: string; -}): Promise<{ - stdout: string; - stderr: string; -}>; - -// @public (undocumented) -export interface RunPythonOpts extends Omit { - // (undocumented) - onArtifact?: (artifact: Artifact) => Promise | void; -} - -// @public -class Sandbox extends SandboxConnection { - protected constructor(opts?: SandboxOpts); - get actions(): Map>; - // (undocumented) - readonly _actions: Map>; - addAction(action: Action): this; - addAction(name: string, action: Action): this; - static create(): Promise; - static create(template: string): Promise; - static create(opts: SandboxOpts): Promise; - downloadFile(remotePath: string, format?: DownloadFileFormat): Promise; - readonly filesystem: FilesystemManager; - get fileURL(): string; - // (undocumented) - protected _open(opts: CallOpts): Promise; - get openai(): { - readonly actions: Actions; - }; - readonly process: ProcessManager; - static reconnect(sandboxID: string): Promise; - static reconnect(opts: Omit & { - sandboxID: string; - }): Promise; - removeAction(name: string): this; - readonly terminal: TerminalManager; - uploadFile(file: Buffer | Blob, filename: string): Promise; -} -export { Sandbox } -export default Sandbox; - -// @public (undocumented) -export const SANDBOX_DOMAIN: string; - -// Warning: (ae-forgotten-export) The symbol "SandboxConnectionOpts" needs to be exported by the entry point index.d.ts -// -// @public (undocumented) -export interface SandboxOpts extends SandboxConnectionOpts { - // (undocumented) - onExit?: (() => Promise | void) | ((exitCode: number) => Promise | void); - // Warning: (ae-forgotten-export) The symbol "ScanOpenedPortsHandler" needs to be exported by the entry point index.d.ts - // - // (undocumented) - onScanPorts?: ScanOpenedPortsHandler; - // (undocumented) - onStderr?: (out: ProcessMessage) => Promise | void; - // (undocumented) - onStdout?: (out: ProcessMessage) => Promise | void; - timeout?: number; -} - -// @public -export class Terminal { - constructor(terminalID: string, sandbox: SandboxConnection, triggerExit: () => void, finished: Promise, output: TerminalOutput); - // (undocumented) - get data(): string; - // @deprecated (undocumented) - readonly finished: Promise; - kill(): Promise; - // (undocumented) - readonly output: TerminalOutput; - resize({ cols, rows }: { - cols: number; - rows: number; - }): Promise; - sendData(data: string): Promise; - // (undocumented) - readonly terminalID: string; - wait(): Promise; -} - -// @public -export interface TerminalManager { - // Warning: (ae-forgotten-export) The symbol "TerminalOpts" needs to be exported by the entry point index.d.ts - // - // (undocumented) - start(opts: TerminalOpts): Promise; -} - -// @public (undocumented) -export class TerminalOutput { - // (undocumented) - addData(data: string): void; - // (undocumented) - get data(): string; -} - -// Warning: (ae-forgotten-export) The symbol "WithAccessToken" needs to be exported by the entry point index.d.ts -// -// @public (undocumented) -export function withAccessToken(f: TypedFetch): WithAccessToken & { - Error: typeof f.Error; -}; - -// Warning: (ae-forgotten-export) The symbol "WithAPIKey" needs to be exported by the entry point index.d.ts -// -// @public (undocumented) -export function withAPIKey(f: TypedFetch): WithAPIKey & { - Error: typeof f.Error; -}; - -// Warnings were encountered during analysis: -// -// dist/index.d.ts:834:9 - (ae-forgotten-export) The symbol "Actions" needs to be exported by the entry point index.d.ts - -// (No @packageDocumentation comment for this package) - -``` diff --git a/packages/js-sdk/test/run.mjs b/packages/js-sdk/test/run.mjs deleted file mode 100644 index a59945d0d..000000000 --- a/packages/js-sdk/test/run.mjs +++ /dev/null @@ -1,14 +0,0 @@ -import { Sandbox } from '../dist/index.js' -import { config } from 'dotenv' - -config() - -const sandbox = await Sandbox.create({ - apiKey: process.env.E2B_API_KEY - // __debug_hostname: 'localhost', - // __debug_port: 49982, - // __debug_devEnv: 'local', -}) -console.log(sandbox.id) - -await sandbox.close() diff --git a/packages/js-sdk/test/runCode.test.mjs b/packages/js-sdk/test/runCode.test.mjs deleted file mode 100644 index 09e5a3f1d..000000000 --- a/packages/js-sdk/test/runCode.test.mjs +++ /dev/null @@ -1,21 +0,0 @@ -import { runCode } from '../src' -import { expect, test } from 'vitest' - -test('run code', async () => { - const code = ` -test="test\\n" -print(10*test) -raise Exception("err") -` - const { stdout, stderr } = await runCode('Python3', code) - console.log('stdout', stdout) - console.log('stderr', stderr) - expect(stdout.length).toEqual(50) - expect(stderr).toContain('Exception: err') -}, 10000) - -test('run code using unsupported runtime', async () => { - await expect(() => runCode('Unsupported', 'print("hello")')).rejects.toThrowError( - 'isn\'t supported' - ) -}) diff --git a/packages/python-sdk/e2b/__init__.py b/packages/python-sdk/e2b/__init__.py index 405416bb8..96237920a 100644 --- a/packages/python-sdk/e2b/__init__.py +++ b/packages/python-sdk/e2b/__init__.py @@ -49,6 +49,5 @@ ProcessMessage, ProcessOutput, TerminalOutput, - run_code, RunningSandbox, ) diff --git a/packages/python-sdk/e2b/sandbox/__init__.py b/packages/python-sdk/e2b/sandbox/__init__.py index 4e8a09820..47a0d1873 100644 --- a/packages/python-sdk/e2b/sandbox/__init__.py +++ b/packages/python-sdk/e2b/sandbox/__init__.py @@ -26,7 +26,6 @@ ProcessMessage, ProcessOutput, ) -from .run_code import run_code from .terminal import ( Terminal, TerminalManager, diff --git a/packages/python-sdk/e2b/sandbox/main.py b/packages/python-sdk/e2b/sandbox/main.py index a940f76cd..cc5acd0d7 100644 --- a/packages/python-sdk/e2b/sandbox/main.py +++ b/packages/python-sdk/e2b/sandbox/main.py @@ -81,8 +81,6 @@ def __init__( :param template: ID of the sandbox template or the name of prepared template. If not specified a 'base' template will be used. Can be one of the following premade sandbox templates or a custom sandbox template ID: - `base` - A basic sandbox with a Linux environment - - `Python3-DataAnalysis` - A Python3 sandbox with data analysis tools - :param api_key: The API key to use, if not provided, the `E2B_API_KEY` environment variable is used :param cwd: The current working directory to use diff --git a/packages/python-sdk/e2b/sandbox/run_code.py b/packages/python-sdk/e2b/sandbox/run_code.py deleted file mode 100644 index 55846a77b..000000000 --- a/packages/python-sdk/e2b/sandbox/run_code.py +++ /dev/null @@ -1,65 +0,0 @@ -from os import getenv -from typing import Literal, Union, Optional - -from . import Sandbox -from .exception import UnsupportedRuntimeException - -CodeRuntime = Literal[ - "Node16", - "Python3", - "Bash", - "Python3-DataAnalysis", -] - - -def run_code( - runtime: Union[CodeRuntime, str], - code: str, - api_key: Optional[str] = None, -): - """ - Run code in a sandboxed cloud playground and return the stdout and stderr. - - `run_code` wraps the `Sandbox` class and provides a simple interface for running code in a sandbox - without any need to manage lifecycle of the sandbox. - `run_code` automatically loads the E2B API key from the `E2B_API_KEY` environment variable. - - :param runtime: The runtime to run the code in. One of "Node16" or "Python3". - :param code: The code to run - :param api_key: The E2B API key to use. If not provided, the `E2B_API_KEY` environment variable is used. - - :return: A string touple of stdout and stderr - """ - - if api_key is None: - api_key = getenv("E2B_API_KEY") - - if runtime == "Node16": - template_id = "base" - binary = "node" - filepath = "/index.js" - elif runtime == "Python3": - template_id = "base" - binary = "python3" - filepath = "/index.py" - elif runtime == "Python3-DataAnalysis": - template_id = "Python3-DataAnalysis" - binary = "python3" - filepath = "/index.py" - elif runtime == "Bash": - template_id = "base" - binary = "bash" - filepath = "/main.sh" - else: - raise UnsupportedRuntimeException( - f'Invalid runtime "{runtime}". Please contact us (hello@e2b.dev) if you need support for this runtime' - ) - - sandbox = Sandbox(template=template_id, api_key=api_key) - sandbox.filesystem.write(filepath, code) - - output = sandbox.process.start_and_wait(cmd=f"{binary} {filepath}") - - sandbox.close() - - return output.stdout, output.stderr diff --git a/packages/python-sdk/example.py b/packages/python-sdk/example.py index a9593bd68..6975bcf51 100644 --- a/packages/python-sdk/example.py +++ b/packages/python-sdk/example.py @@ -5,7 +5,7 @@ load_dotenv() -logging.basicConfig(level=logging.ERROR) +logging.basicConfig(level=logging.INFO) with Sandbox() as sandbox: print(sandbox.id) diff --git a/packages/python-sdk/python-sdk-example.ipynb b/packages/python-sdk/python-sdk-example.ipynb deleted file mode 100644 index 1a8da47a5..000000000 --- a/packages/python-sdk/python-sdk-example.ipynb +++ /dev/null @@ -1,538 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# E2B Python SDK\n", - "The E2B Python SDK provides an interface for managing cloud environments for AI agents.\n", - "\n", - "This SDK gives your agent a full cloud development environment that's sandboxed. That means:\n", - "\n", - "- Access to Linux OS\n", - "- Using filesystem (create, list, and delete files and dirs)\n", - "- Run processes\n", - "- Sandboxed - you can run any code\n", - "- Access to the internet\n", - "\n", - "These cloud environments are meant to be used for agents. Like a sandboxed playgrounds, where the agent can do whatever it wants.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Installation" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "vscode": { - "languageId": "shellscript" - } - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Collecting e2b==0.1.4\n", - " Downloading e2b-0.1.4-py3-none-any.whl (71 kB)\n", - "\u001B[2K \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m71.3/71.3 kB\u001B[0m \u001B[31m3.2 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\n", - "\u001B[?25hRequirement already satisfied: aenum>=3.1.11 in /opt/homebrew/lib/python3.11/site-packages (from e2b==0.1.4) (3.1.15)\n", - "Requirement already satisfied: aiohttp>=3.8.4 in /opt/homebrew/lib/python3.11/site-packages (from e2b==0.1.4) (3.8.4)\n", - "Requirement already satisfied: jsonrpcclient<5.0.0,>=4.0.3 in /opt/homebrew/lib/python3.11/site-packages (from e2b==0.1.4) (4.0.3)\n", - "Requirement already satisfied: pydantic<2.0.0,>=1.10.5 in /opt/homebrew/lib/python3.11/site-packages (from e2b==0.1.4) (1.10.7)\n", - "Requirement already satisfied: python-dateutil>=2.8.2 in /opt/homebrew/lib/python3.11/site-packages (from e2b==0.1.4) (2.8.2)\n", - "Requirement already satisfied: urllib3>=1.25.3 in /opt/homebrew/lib/python3.11/site-packages (from e2b==0.1.4) (1.26.16)\n", - "Requirement already satisfied: websockets<12.0.0,>=11.0.3 in /opt/homebrew/lib/python3.11/site-packages (from e2b==0.1.4) (11.0.3)\n", - "Requirement already satisfied: attrs>=17.3.0 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp>=3.8.4->e2b==0.1.4) (23.1.0)\n", - "Requirement already satisfied: charset-normalizer<4.0,>=2.0 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp>=3.8.4->e2b==0.1.4) (3.1.0)\n", - "Requirement already satisfied: multidict<7.0,>=4.5 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp>=3.8.4->e2b==0.1.4) (6.0.4)\n", - "Requirement already satisfied: async-timeout<5.0,>=4.0.0a3 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp>=3.8.4->e2b==0.1.4) (4.0.2)\n", - "Requirement already satisfied: yarl<2.0,>=1.0 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp>=3.8.4->e2b==0.1.4) (1.9.2)\n", - "Requirement already satisfied: frozenlist>=1.1.1 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp>=3.8.4->e2b==0.1.4) (1.3.3)\n", - "Requirement already satisfied: aiosignal>=1.1.2 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp>=3.8.4->e2b==0.1.4) (1.3.1)\n", - "Requirement already satisfied: typing-extensions>=4.2.0 in /opt/homebrew/lib/python3.11/site-packages (from pydantic<2.0.0,>=1.10.5->e2b==0.1.4) (4.5.0)\n", - "Requirement already satisfied: six>=1.5 in /opt/homebrew/lib/python3.11/site-packages (from python-dateutil>=2.8.2->e2b==0.1.4) (1.16.0)\n", - "Requirement already satisfied: idna>=2.0 in /opt/homebrew/lib/python3.11/site-packages (from yarl<2.0,>=1.0->aiohttp>=3.8.4->e2b==0.1.4) (3.4)\n", - "Installing collected packages: e2b\n", - " Attempting uninstall: e2b\n", - " Found existing installation: e2b 0.1.3\n", - " Uninstalling e2b-0.1.3:\n", - " Successfully uninstalled e2b-0.1.3\n", - "Successfully installed e2b-0.1.4\n", - "\n", - "\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m A new release of pip is available: \u001B[0m\u001B[31;49m23.0.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m23.2.1\u001B[0m\n", - "\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m To update, run: \u001B[0m\u001B[32;49mpython3.11 -m pip install --upgrade pip\u001B[0m\n", - "Note: you may need to restart the kernel to use updated packages.\n" - ] - } - ], - "source": [ - "pip install e2b" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Usage" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "from e2b import Sandbox\n", - "\n", - "id = \"Nodejs\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Initialization" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "# You can use some of the predefined environments by using specific id:\n", - "# 'Nodejs', 'Bash', 'Python3', 'Java', 'Go', 'Rust', 'PHP', 'Perl', 'DotNET'\n", - "sandbox = Sandbox.create(id)\n", - "\n", - "# Close the session after you are done\n", - "sandbox.close()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Filesystem" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hello World!\n" - ] - } - ], - "source": [ - "# Create, read and delete file\n", - "\n", - "sandbox = Sandbox.create(id)\n", - "\n", - "sandbox.filesystem.write(\"/tmp/test.txt\", \"Hello World!\")\n", - "\n", - "content = sandbox.filesystem.read(\"/tmp/test.txt\")\n", - "print(content)\n", - "\n", - "sandbox.filesystem.remove(\"/tmp/test.txt\")\n", - "\n", - "sandbox.close()" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[]\n", - "['test']\n", - "[]\n" - ] - } - ], - "source": [ - "# List files in a directory, create a new directory and remove a directory\n", - "\n", - "sandbox = Sandbox.create(id)\n", - "\n", - "ls = sandbox.filesystem.list(\"/\")\n", - "print([x.name for x in ls if x.name.startswith(\"test\")])\n", - "\n", - "sandbox.filesystem.make_dir(\"/test/new\")\n", - "\n", - "ls = sandbox.filesystem.list(\"/\")\n", - "print([x.name for x in ls if x.name.startswith(\"test\")])\n", - "\n", - "sandbox.filesystem.remove(\"/test\")\n", - "\n", - "ls = sandbox.filesystem.list(\"/\")\n", - "print([x.name for x in ls if x.name.startswith(\"test\")])\n", - "\n", - "sandbox.close()" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Event {'path': '//test.txt', 'name': 'test.txt', 'operation': 'Create', 'timestamp': 1691532768257138654, 'isDir': False}\n", - "Event {'path': '//test.txt', 'name': 'test.txt', 'operation': 'Write', 'timestamp': 1691532768259136251, 'isDir': False}\n" - ] - } - ], - "source": [ - "# Watch directory for changes (WIP)\n", - "\n", - "sandbox = Sandbox(id)\n", - "sandbox.open()\n", - "\n", - "watcher = sandbox.filesystem.watch_dir(\"/\")\n", - "watcher.add_event_listener(lambda event: print(\"Event\", event))\n", - "watcher.start()\n", - "\n", - "sandbox.filesystem.write(\"/test.txt\", \"Hello World!\")\n", - "\n", - "watcher.stop()\n", - "\n", - "sandbox.close()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Process" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "tags": [ - "process" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Process session ID wI6N300SFSvq\n", - "Current output []\n", - "Stdout line='/code' error=False timestamp=1691532768326208600\n", - "Exit\n", - "Output [ProcessMessage(line='/code', error=False, timestamp=1691532768326208600)]\n", - "Stdout /code\n", - "Stderr \n" - ] - } - ], - "source": [ - "# Execute a command and get the output\n", - "\n", - "sandbox = Sandbox.create(id)\n", - "\n", - "proc = sandbox.process.start(\n", - " \"pwd\",\n", - " # If you add a callback for stdout you will get the stderr data as it comes in. \n", - " # You can still access the stdout after `output = proc.wait()` as `output.stdout` or anytime as `proc.output.stdout`.\n", - " on_stdout=lambda data: print(\"Stdout\", data),\n", - " # If you add a callback for stderr you will get the stderr data as it comes in.\n", - " # You can still access the stderr after `output = proc.wait()` as `output.stderr` or anytime as `proc.output.stderr`.\n", - " on_stderr=lambda data: print(\"Stderr\", data),\n", - " on_exit=lambda: print(\"Exit\"),\n", - " cwd=\"/code\",\n", - ")\n", - "print(\"Process session ID\", proc.process_id)\n", - "\n", - "# You can access `proc.output...` even before the process finishes\n", - "print(\"Current output\", proc.output.messages)\n", - "\n", - "# You can wait for the process to end\n", - "output = proc.wait()\n", - "\n", - "# List of all output messages\n", - "print(\"Output\", output.messages)\n", - "# Concatenated stdout\n", - "print(\"Stdout\", output.stdout)\n", - "# Concatenated stderr\n", - "print(\"Stderr\", output.stderr)\n", - "sandbox.close()" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "tags": [ - "process", - "stdin", - "kill" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Stdout line='marco' error=False timestamp=1691532768254368795\n", - "Exit\n", - "Output [ProcessMessage(line='marco', error=False, timestamp=1691532768254368795)]\n", - "Stdout marco\n", - "Stdout \n" - ] - } - ], - "source": [ - "# Start command, send stdin to it and then kill it\n", - "\n", - "sandbox = Sandbox.create(id)\n", - "\n", - "proc = sandbox.process.start(\n", - " \"while IFS= read -r line; do echo \\\"$line\\\"; sleep 1; done\",\n", - " # If you add a callback for stdout you will get the stderr data as it comes in. \n", - " # You can still access the stdout after `output = proc.wait()` as `output.stdout` or anytime as `proc.output.stdout`.\n", - " on_stdout=lambda data: print(\"Stdout\", data),\n", - " # If you add a callback for stderr you will get the stderr data as it comes in.\n", - " # You can still access the stderr after `output = proc.wait()` as `output.stderr` or anytime as `proc.output.stderr`.\n", - " on_stderr=lambda data: print(\"Stderr\", data),\n", - " on_exit=lambda: print(\"Exit\"),\n", - " cwd=\"/code\",\n", - ")\n", - "proc.send_stdin(\"marco\\n\")\n", - "proc.kill()\n", - "\n", - "print(\"Output\", proc.output.messages)\n", - "print(\"Stdout\", proc.output.stdout)\n", - "print(\"Stdout\", proc.output.stderr)\n", - "\n", - "sandbox.close()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Terminal" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Terminal session ID FSSpmurO9BNP\n", - "\u001B[?2004h\n", - "/code $ \n", - "ls -a\n", - "\u001B[?2004l\n", - "\u001B[0m\u001B[01;34m.\u001B[0m \u001B[01;34m..\u001B[0m package.json\n", - "\n", - "\u001B[?2004h/code $ \n", - "Exit\n" - ] - } - ], - "source": [ - "# Start and interact with a terminal session\n", - "\n", - "sandbox = Sandbox.create(id)\n", - "\n", - "term = sandbox.terminal.start(\n", - " on_data=lambda data: print(data),\n", - " on_exit=lambda: print(\"Exit\"),\n", - " cols=80,\n", - " rows=24,\n", - " cwd=\"/code\",\n", - ")\n", - "print(\"Terminal session ID\", term.terminal_id)\n", - "term.resize(80, 30)\n", - "\n", - "term.send_data(\"ls -a\\n\")\n", - "\n", - "term.kill()\n", - "\n", - "sandbox.close()" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Data: Hello World\n", - "\n", - "Exit\n" - ] - } - ], - "source": [ - "# Execute one command inside a terminal session\n", - "\n", - "sandbox = Sandbox.create(id)\n", - "\n", - "term = sandbox.terminal.start(\n", - " on_data=lambda data: print(\"Data:\", data),\n", - " on_exit=lambda: print(\"Exit\"),\n", - " cols=80,\n", - " rows=24,\n", - " cwd=\"/code\",\n", - " # If you specify a command, the terminal will be closed after the command finishes.\n", - " cmd=\"echo Hello World\",\n", - ")\n", - "\n", - "term.wait()\n", - "\n", - "sandbox.close()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Ports and hostnames - connecting to environment" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": { - "tags": [ - "process", - "ports", - "hostname" - ] - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hostname: https://8000-s2t6u9y1-fce131d5.ondevbook.com\n", - "Open ports: [49982, 22, 53, 49982]\n", - "Open ports: [22, 49982, 8000, 49982, 53]\n", - "Open ports: [49982, 49982, 22, 8000, 53]\n", - "Open ports: [49982, 49982, 22, 8000, 53]\n", - "Open ports: [22, 53, 49982, 49982, 8000]\n", - "Open ports: [49982, 8000, 49982, 53, 22]\n", - "Open ports: [22, 49982, 8000, 53, 49982]\n", - "Open ports: [49982, 53, 49982, 8000, 22]\n", - "Open ports: [49982, 49982, 22, 8000, 53]\n", - "Open ports: [49982, 49982, 8000, 22, 53]\n" - ] - } - ], - "source": [ - "# Get notified when a port opens and how to get a public hostname for an open port in the cloud environment\n", - "import time\n", - "\n", - "sandbox = Sandbox.create(\n", - " id,\n", - " on_scan_ports=lambda ports: print(\"Open ports:\", [port.port for port in ports]),\n", - ")\n", - "\n", - "port = 8000\n", - "proc = sandbox.process.start(f\"python3 -m http.server {port}\")\n", - "\n", - "hostname = sandbox.get_hostname(port)\n", - "print(f\"Hostname: https://{hostname}\")\n", - "\n", - "time.sleep(10)\n", - "\n", - "proc.kill()\n", - "\n", - "sandbox.close()" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Current output []\n", - "Output [ProcessMessage(line='/code', error=False, timestamp=1691532768216519914)]\n", - "Stdout /code\n", - "Stderr \n" - ] - } - ], - "source": [ - "# One line initialization\n", - "sandbox = Sandbox.create(id)\n", - "\n", - "proc = sandbox.process.start(\n", - " \"pwd\",\n", - " cwd=\"/code\",\n", - ")\n", - "\n", - "# You can access `proc.output...` even before the process finishes\n", - "print(\"Current output\", proc.output.messages)\n", - "\n", - "# You can wait for the result\n", - "output = proc.wait()\n", - "\n", - "# List of all output messages\n", - "print(\"Output\", output.messages)\n", - "# Concatenated stdout\n", - "print(\"Stdout\", output.stdout)\n", - "# Concatenated stderr\n", - "print(\"Stderr\", output.stderr)\n", - "\n", - "sandbox.close()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - }, - "orig_nbformat": 4 - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/packages/python-sdk/tests/test_run_code.py b/packages/python-sdk/tests/test_run_code.py deleted file mode 100644 index 2f71a4787..000000000 --- a/packages/python-sdk/tests/test_run_code.py +++ /dev/null @@ -1,18 +0,0 @@ -import pytest - -from e2b import run_code -from e2b.sandbox.exception import UnsupportedRuntimeException - - -def test_run_code(): - code = "console.log('hello\\n'.repeat(10)); throw new Error('error')" - stdout, stderr = run_code("Node16", code) - - assert len(stdout) == 60 - assert "Error: error" in stderr - - -def test_unsupported_runtime(): - code = "console.log('hello'); throw new Error('error')" - with pytest.raises(UnsupportedRuntimeException) as e: - run_code("unsupported", code) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bf1e07744..5aa080c72 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -312,9 +312,6 @@ importers: typescript: specifier: ^5.2.2 version: 5.2.2 - vitest: - specifier: ^0.34.6 - version: 0.34.6 packages/js-sdk: dependencies: @@ -8887,6 +8884,22 @@ packages: yaml: 1.10.2 dev: true + /postcss-load-config@4.0.1: + resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + dependencies: + lilconfig: 2.1.0 + yaml: 2.3.2 + dev: true + /postcss-load-config@4.0.1(postcss@8.4.30): resolution: {integrity: sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==} engines: {node: '>= 14'} @@ -10559,7 +10572,7 @@ packages: execa: 5.1.1 globby: 11.1.0 joycon: 3.1.1 - postcss-load-config: 4.0.1(postcss@8.4.30) + postcss-load-config: 4.0.1 resolve-from: 5.0.0 rollup: 3.29.4 source-map: 0.8.0-beta.0 diff --git a/sandboxes/code-interpreter/README.md b/sandboxes/code-interpreter/README.md new file mode 100644 index 000000000..3bcc51800 --- /dev/null +++ b/sandboxes/code-interpreter/README.md @@ -0,0 +1,3 @@ +# Code Interpreter Sandbox Template + +This template is deprecated. Please use the [code-interpreter-sandbox](https://github.com/e2b-dev/code-interpreter) package instead.