{ "cells": [ { "cell_type": "markdown", "id": "39c2dcc0", "metadata": {}, "source": [ "# Executor: LocalCodeExecutor Basic Examples\n", "\n", "This notebook shows how to execute Python and shell snippets in **isolated, cached virtual environments**" ] }, { "cell_type": "markdown", "id": "c4ff4b2b", "metadata": {}, "source": [ "## Install Required Libraries\n", "Before starting, ensure the required libraries are installed:" ] }, { "cell_type": "code", "execution_count": null, "id": "5b41a66a", "metadata": {}, "outputs": [], "source": [ "!pip install dapr-agents" ] }, { "cell_type": "markdown", "id": "a9c01be3", "metadata": {}, "source": [ "## Setup" ] }, { "cell_type": "code", "execution_count": 1, "id": "508fd446", "metadata": {}, "outputs": [], "source": [ "import logging\n", "\n", "from dapr_agents.executors.local import LocalCodeExecutor\n", "from dapr_agents.types.executor import CodeSnippet, ExecutionRequest\n", "from rich.console import Console\n", "from rich.ansi import AnsiDecoder\n", "import shutil" ] }, { "cell_type": "code", "execution_count": 2, "id": "27594072", "metadata": {}, "outputs": [], "source": [ "logging.basicConfig(level=logging.INFO)\n", "\n", "executor = LocalCodeExecutor()\n", "console = Console()\n", "decoder = AnsiDecoder()" ] }, { "cell_type": "markdown", "id": "4d663475", "metadata": {}, "source": [ "## Running a basic Python Code Snippet" ] }, { "cell_type": "code", "execution_count": 3, "id": "ba45ddc8", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO:dapr_agents.executors.local:Sandbox backend enabled: seatbelt\n", "INFO:dapr_agents.executors.local:Created a new virtual environment\n", "INFO:dapr_agents.executors.local:Installing print, rich\n", "INFO:dapr_agents.executors.local:Snippet 1 finished in 2.442s\n" ] }, { "data": { "text/html": [ "
Hello executor!\n",
       "
\n" ], "text/plain": [ "\u001b[1;32mHello executor!\u001b[0m\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "code = \"\"\"\n", "from rich import print\n", "print(\"[bold green]Hello executor![/bold green]\")\n", "\"\"\"\n", "\n", "request = ExecutionRequest(snippets=[\n", " CodeSnippet(language='python', code=code, timeout=10)\n", "])\n", "\n", "results = await executor.execute(request)\n", "results[0] # raw result\n", "\n", "# pretty‑print with Rich\n", "console.print(*decoder.decode(results[0].output))" ] }, { "cell_type": "markdown", "id": "d28c7531", "metadata": {}, "source": [ "## Run a Shell Snipper" ] }, { "cell_type": "code", "execution_count": 4, "id": "4ea89b85", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO:dapr_agents.executors.local:Sandbox backend enabled: seatbelt\n", "INFO:dapr_agents.executors.local:Snippet 1 finished in 0.019s\n" ] }, { "data": { "text/plain": [ "[ExecutionResult(status='success', output='4\\n', exit_code=0)]" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "shell_request = ExecutionRequest(snippets=[\n", " CodeSnippet(language='sh', code='echo $((2+2))', timeout=5)\n", "])\n", "\n", "await executor.execute(shell_request)" ] }, { "cell_type": "markdown", "id": "da281b6e", "metadata": {}, "source": [ "## Reuse the cached virtual environment" ] }, { "cell_type": "code", "execution_count": 5, "id": "3e9e7e9b", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO:dapr_agents.executors.local:Sandbox backend enabled: seatbelt\n", "INFO:dapr_agents.executors.local:Reusing cached virtual environment.\n", "INFO:dapr_agents.executors.local:Installing print, rich\n", "INFO:dapr_agents.executors.local:Snippet 1 finished in 0.297s\n" ] }, { "data": { "text/plain": [ "[ExecutionResult(status='success', output='\\x1b[1;32mHello executor!\\x1b[0m\\n', exit_code=0)]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Re‑running the same Python request will reuse the cached venv, so it is faster\n", "await executor.execute(request)" ] }, { "cell_type": "markdown", "id": "14dc3e4c", "metadata": {}, "source": [ "## Inject Helper Functions" ] }, { "cell_type": "code", "execution_count": 6, "id": "82f9a168", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO:dapr_agents.executors.local:Sandbox backend enabled: seatbelt\n", "INFO:dapr_agents.executors.local:Created a new virtual environment\n", "INFO:dapr_agents.executors.local:Snippet 1 finished in 1.408s\n" ] }, { "data": { "text/plain": [ "[ExecutionResult(status='success', output='42\\n', exit_code=0)]" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def fancy_sum(a: int, b: int) -> int:\n", " return a + b\n", "\n", "executor.user_functions.append(fancy_sum)\n", "\n", "helper_request = ExecutionRequest(snippets=[\n", " CodeSnippet(language='python', code='print(fancy_sum(40, 2))', timeout=5)\n", "])\n", "\n", "await executor.execute(helper_request)" ] }, { "cell_type": "markdown", "id": "25f9718c", "metadata": {}, "source": [ "## Clean Up" ] }, { "cell_type": "code", "execution_count": 7, "id": "b09059f1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Cache directory removed ✅\n" ] } ], "source": [ "shutil.rmtree(executor.cache_dir, ignore_errors=True)\n", "print(\"Cache directory removed ✅\")" ] }, { "cell_type": "markdown", "id": "2c93cdef", "metadata": {}, "source": [ "## Package-manager detection & automatic bootstrap" ] }, { "cell_type": "code", "execution_count": 8, "id": "8691f3e3", "metadata": {}, "outputs": [], "source": [ "from dapr_agents.executors.utils import package_manager as pm\n", "import pathlib, tempfile" ] }, { "cell_type": "markdown", "id": "e9e08d81", "metadata": {}, "source": [ "### Create a throw-away project" ] }, { "cell_type": "code", "execution_count": 9, "id": "4c7dd9c3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "tmp project: /var/folders/9z/8xhqw8x1611fcbhzl339yrs40000gn/T/tmpmssk0m2b\n" ] } ], "source": [ "tmp_proj = pathlib.Path(tempfile.mkdtemp())\n", "(tmp_proj / \"requirements.txt\").write_text(\"rich==13.7.0\\n\")\n", "print(\"tmp project:\", tmp_proj)" ] }, { "cell_type": "markdown", "id": "03558a95", "metadata": {}, "source": [ "### Show what the helper detects" ] }, { "cell_type": "code", "execution_count": 10, "id": "3b5acbfb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "detect_package_managers -> []\n", "get_install_command -> pip install -r requirements.txt\n" ] } ], "source": [ "print(\"detect_package_managers ->\",\n", " [m.name for m in pm.detect_package_managers(tmp_proj)])\n", "print(\"get_install_command ->\",\n", " pm.get_install_command(tmp_proj))" ] }, { "cell_type": "markdown", "id": "42f1ae7c", "metadata": {}, "source": [ "### Point the executor at that directory" ] }, { "cell_type": "code", "execution_count": 11, "id": "81e53cf4", "metadata": {}, "outputs": [], "source": [ "import os\n", "from contextlib import contextmanager, ExitStack\n", "\n", "@contextmanager\n", "def chdir(path):\n", " \"\"\"\n", " Temporarily change the process CWD to *path*.\n", "\n", " Works on every CPython ≥ 3.6 (and PyPy) and restores the old directory\n", " even if an exception is raised inside the block.\n", " \"\"\"\n", " old_cwd = os.getcwd()\n", " os.chdir(path)\n", " try:\n", " yield\n", " finally:\n", " os.chdir(old_cwd)" ] }, { "cell_type": "code", "execution_count": 12, "id": "fb2f5052", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "INFO:dapr_agents.executors.local:bootstrapping python project with 'pip install -r requirements.txt'\n", "INFO:dapr_agents.executors.local:Sandbox backend enabled: seatbelt\n", "INFO:dapr_agents.executors.local:Created a new virtual environment\n", "INFO:dapr_agents.executors.local:Snippet 1 finished in 1.433s\n" ] }, { "data": { "text/html": [ "
bootstrap OK\n",
       "\n",
       "
\n" ], "text/plain": [ "bootstrap OK\n", "\n" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "with ExitStack() as stack:\n", " # keep a directory handle open (optional but handy if you’ll delete tmp_proj later)\n", " stack.enter_context(os.scandir(tmp_proj))\n", "\n", " # <-- our portable replacement for contextlib.chdir()\n", " stack.enter_context(chdir(tmp_proj))\n", "\n", " # run a trivial snippet; executor will bootstrap because it now “sees”\n", " # requirements.txt in the current working directory\n", " out = await executor.execute(\n", " ExecutionRequest(snippets=[\n", " CodeSnippet(language=\"python\", code=\"print('bootstrap OK')\", timeout=5)\n", " ])\n", " )\n", " console.print(out[0].output)" ] }, { "cell_type": "markdown", "id": "45de2386", "metadata": {}, "source": [ "### Clean Up the throw-away project " ] }, { "cell_type": "code", "execution_count": 13, "id": "0c7aa010", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Cache directory removed ✅\n", "temporary project removed ✅\n" ] } ], "source": [ "shutil.rmtree(executor.cache_dir, ignore_errors=True)\n", "print(\"Cache directory removed ✅\")\n", "shutil.rmtree(tmp_proj, ignore_errors=True)\n", "print(\"temporary project removed ✅\")" ] }, { "cell_type": "code", "execution_count": null, "id": "36ea4010", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": ".venv", "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.13.1" } }, "nbformat": 4, "nbformat_minor": 5 }