Files
e2b-dev--e2b/packages/python-sdk/python-sdk-example.ipynb
T
2023-08-14 14:54:45 +02:00

540 lines
16 KiB
Plaintext

{
"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==0.1.4"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Usage"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from e2b import Session\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",
"session = await Session.create(id)\n",
"\n",
"# Close the session after you are done\n",
"await session.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",
"session = await Session.create(id)\n",
"\n",
"await session.filesystem.write(\"/tmp/test.txt\", \"Hello World!\")\n",
"\n",
"content = await session.filesystem.read(\"/tmp/test.txt\")\n",
"print(content)\n",
"\n",
"await session.filesystem.remove(\"/tmp/test.txt\")\n",
"\n",
"await session.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",
"session = await Session.create(id)\n",
"\n",
"ls = await session.filesystem.list(\"/\")\n",
"print([x.name for x in ls if x.name.startswith(\"test\")])\n",
"\n",
"await session.filesystem.make_dir(\"/test/new\")\n",
"\n",
"ls = await session.filesystem.list(\"/\")\n",
"print([x.name for x in ls if x.name.startswith(\"test\")])\n",
"\n",
"await session.filesystem.remove(\"/test\")\n",
"\n",
"ls = await session.filesystem.list(\"/\")\n",
"print([x.name for x in ls if x.name.startswith(\"test\")])\n",
"\n",
"await session.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",
"session = Session(id)\n",
"await session.open()\n",
"\n",
"watcher = await session.filesystem.watch_dir(\"/\")\n",
"watcher.add_event_listener(lambda event: print(\"Event\", event))\n",
"await watcher.start()\n",
"\n",
"await session.filesystem.write(\"/test.txt\", \"Hello World!\")\n",
"\n",
"await watcher.stop()\n",
"\n",
"await session.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",
"session = await Session.create(id)\n",
"\n",
"proc = await session.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 = await proc` 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 = await proc` as `output.stderr` or anytime as `proc.output.stderr`.\n",
" on_stderr=lambda data: print(\"Stderr\", data),\n",
" on_exit=lambda: print(\"Exit\"),\n",
" rootdir=\"/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 directly await the started process to wait for exit\n",
"output = await proc\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",
"await session.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",
"session = await Session.create(id)\n",
"\n",
"proc = await session.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 = await proc` 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 = await proc` as `output.stderr` or anytime as `proc.output.stderr`.\n",
" on_stderr=lambda data: print(\"Stderr\", data),\n",
" on_exit=lambda: print(\"Exit\"),\n",
" rootdir=\"/code\",\n",
")\n",
"await proc.send_stdin(\"marco\\n\")\n",
"await proc.kill()\n",
"\n",
"print(\"Output\", proc.output.messages)\n",
"print(\"Stdout\", proc.output.stdout)\n",
"print(\"Stdout\", proc.output.stderr)\n",
"\n",
"await session.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",
"session = await Session.create(id)\n",
"\n",
"term = await session.terminal.start(\n",
" on_data=lambda data: print(data),\n",
" on_exit=lambda: print(\"Exit\"),\n",
" cols=80,\n",
" rows=24,\n",
" rootdir=\"/code\",\n",
")\n",
"print(\"Terminal session ID\", term.terminal_id)\n",
"await term.resize(80, 30)\n",
"\n",
"await term.send_data(\"ls -a\\n\")\n",
"\n",
"await term.kill()\n",
"\n",
"await session.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 of a terminal session\n",
"\n",
"session = await Session.create(id)\n",
"\n",
"term = await session.terminal.start(\n",
" on_data=lambda data: print(\"Data:\", data),\n",
" on_exit=lambda: print(\"Exit\"),\n",
" cols=80,\n",
" rows=24,\n",
" rootdir=\"/code\",\n",
" # If you specify a command, the terminal will be closed after the command finishes.\n",
" cmd=\"echo Hello World\",\n",
")\n",
"\n",
"await term\n",
"\n",
"await session.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",
"\n",
"import asyncio\n",
"\n",
"session = await Session.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 = await session.process.start(f\"python3 -m http.server {port}\")\n",
"\n",
"hostname = session.get_hostname(port)\n",
"print(f\"Hostname: https://{hostname}\")\n",
"\n",
"await asyncio.sleep(10)\n",
"\n",
"await proc.kill()\n",
"\n",
"await session.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",
"session = await Session.create(id)\n",
"\n",
"proc = await session.process.start(\n",
" \"pwd\",\n",
" rootdir=\"/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 directly await the started process to wait for exit\n",
"output = await proc\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",
"await session.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
}