Skip to content

Commit 3ad8836

Browse files
committed
fixing formatting
Signed-off-by: Jerry Guan <jerryguan777@gmail.com>
1 parent 4e2bd17 commit 3ad8836

24 files changed

Lines changed: 122 additions & 208 deletions

examples/sandbox_agent/src/nat_sandbox_agent/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
15-
1615
"""
1716
Sandbox Agent - A general-purpose agent with sandboxed execution capabilities.
1817

examples/sandbox_agent/src/nat_sandbox_agent/prompts/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
15-
1615
"""Prompts module - System prompts for the sandbox agent."""
1716

1817
from nat_sandbox_agent.prompts.system_prompt import SANDBOX_AGENT_SYSTEM_PROMPT

examples/sandbox_agent/src/nat_sandbox_agent/prompts/system_prompt.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,8 @@
1212
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
15-
1615
"""System prompts for the sandbox agent."""
1716

18-
1917
SANDBOX_AGENT_SYSTEM_PROMPT = """You are a powerful AI assistant with access to an isolated \
2018
sandbox environment where you can execute code, browse the web, and manipulate files.
2119
@@ -121,6 +119,7 @@
121119
122120
Remember: You are operating in a sandboxed environment. ALWAYS use tools to solve problems - never guess or assume."""
123121

122+
124123
def get_system_prompt(
125124
additional_instructions: str | None = None,
126125
available_tools: list[str] | None = None,

examples/sandbox_agent/src/nat_sandbox_agent/register.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
15-
1615
"""Sandbox Agent workflow registration for NAT framework."""
1716

1817
import logging
@@ -45,6 +44,7 @@
4544

4645
# ============ Configuration Classes ============
4746

47+
4848
class SandboxAgentWorkflowConfig(FunctionBaseConfig, name="sandbox_agent"):
4949
"""Configuration for the Sandbox Agent workflow.
5050
@@ -76,8 +76,7 @@ class SandboxAgentWorkflowConfig(FunctionBaseConfig, name="sandbox_agent"):
7676
"image": "python:3.12-slim",
7777
"memory_limit": "1g",
7878
"cpu_limit": 2.0,
79-
"network_enabled": True,
80-
},
79+
"network_enabled": True, },
8180
description="Sandbox configuration dictionary.",
8281
)
8382

@@ -97,17 +96,21 @@ class SandboxAgentWorkflowConfig(FunctionBaseConfig, name="sandbox_agent"):
9796
description="Additional instructions to append to the system prompt.",
9897
)
9998

99+
100100
# ============ Agent State ============
101101

102+
102103
class AgentState(TypedDict):
103104
"""State for the sandbox agent graph."""
104105

105106
messages: Annotated[list, add_messages]
106107
iteration_count: int
107108
sandbox_id: str
108109

110+
109111
# ============ Workflow Registration ============
110112

113+
111114
@register_function(
112115
config_type=SandboxAgentWorkflowConfig,
113116
framework_wrappers=[LLMFrameworkEnum.LANGCHAIN],
@@ -171,7 +174,6 @@ async def sandbox_agent_workflow(config: SandboxAgentWorkflowConfig, builder: Bu
171174
)
172175

173176
# ============ Define Agent Nodes ============
174-
175177
async def agent_node(state: AgentState) -> dict:
176178
"""Agent reasoning node - decides what action to take."""
177179
messages = state["messages"]
@@ -182,10 +184,8 @@ async def agent_node(state: AgentState) -> dict:
182184
logger.warning(f"Reached max iterations ({config.max_iterations})")
183185
return {
184186
"messages": [
185-
AIMessage(
186-
content="I've reached the maximum number of steps. "
187-
"Here's a summary of what was accomplished so far."
188-
)
187+
AIMessage(content="I've reached the maximum number of steps. "
188+
"Here's a summary of what was accomplished so far.")
189189
],
190190
"iteration_count": iteration,
191191
}
@@ -229,7 +229,9 @@ def should_continue(state: AgentState) -> str:
229229
graph.add_conditional_edges(
230230
"agent",
231231
should_continue,
232-
{"tools": "tools", END: END},
232+
{
233+
"tools": "tools", END: END
234+
},
233235
)
234236
graph.add_edge("tools", "agent")
235237

@@ -244,7 +246,6 @@ def should_continue(state: AgentState) -> str:
244246
logger.info("Agent graph compiled successfully")
245247

246248
# ============ Response Function ============
247-
248249
async def _response_fn(input_message: str) -> str:
249250
"""Process user input and return agent response.
250251

examples/sandbox_agent/src/nat_sandbox_agent/sandbox/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
15-
1615
"""Sandbox module - Provides isolated execution environments."""
1716

1817
from nat_sandbox_agent.sandbox.base import BaseSandbox

examples/sandbox_agent/src/nat_sandbox_agent/sandbox/base.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
15-
1615
"""Base sandbox interface - Abstract base class for sandbox implementations."""
1716

1817
from abc import ABC
@@ -31,9 +30,7 @@
3130
WORKSPACE_DOWNLOADS = f"{WORKSPACE_ROOT}/downloads"
3231

3332
# Command to initialize workspace directories
34-
WORKSPACE_INIT_COMMAND = (
35-
f"mkdir -p {WORKSPACE_INPUT} {WORKSPACE_OUTPUT} {WORKSPACE_TEMP} {WORKSPACE_DOWNLOADS}"
36-
)
33+
WORKSPACE_INIT_COMMAND = (f"mkdir -p {WORKSPACE_INPUT} {WORKSPACE_OUTPUT} {WORKSPACE_TEMP} {WORKSPACE_DOWNLOADS}")
3734

3835
# Default script path for Python execution
3936
DEFAULT_SCRIPT_PATH = f"{WORKSPACE_TEMP}/_script.py"

examples/sandbox_agent/src/nat_sandbox_agent/sandbox/daytona_sandbox.py

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
15-
1615
"""Daytona cloud-based sandbox implementation."""
1716

1817
import asyncio
@@ -38,15 +37,15 @@ class DaytonaSandbox(BaseSandbox):
3837
DEFAULT_IMAGE = "daytonaio/workspace:latest"
3938

4039
def __init__(
41-
self,
42-
api_key: str,
43-
server_url: str = "https://api.daytona.io",
44-
target: str = "us",
45-
image: str = DEFAULT_IMAGE,
46-
cpu: int = 2,
47-
memory: int = 4, # GB
48-
disk: int = 10, # GB
49-
auto_stop_interval: int = 30, # minutes
40+
self,
41+
api_key: str,
42+
server_url: str = "https://api.daytona.io",
43+
target: str = "us",
44+
image: str = DEFAULT_IMAGE,
45+
cpu: int = 2,
46+
memory: int = 4, # GB
47+
disk: int = 10, # GB
48+
auto_stop_interval: int = 30, # minutes
5049
):
5150
"""Initialize Daytona sandbox configuration.
5251
@@ -79,15 +78,11 @@ def _get_client(self):
7978
from daytona_sdk import Daytona
8079
from daytona_sdk import DaytonaConfig
8180

82-
config = DaytonaConfig(
83-
api_key=self._api_key,
84-
)
81+
config = DaytonaConfig(api_key=self._api_key, )
8582
self._client = Daytona(config)
8683
except ImportError:
87-
raise ImportError(
88-
"daytona-sdk package is required for DaytonaSandbox. "
89-
"Install it with: pip install daytona-sdk"
90-
)
84+
raise ImportError("daytona-sdk package is required for DaytonaSandbox. "
85+
"Install it with: pip install daytona-sdk")
9186
return self._client
9287

9388
async def start(self) -> None:
@@ -112,9 +107,7 @@ async def start(self) -> None:
112107
)
113108

114109
# Create and start the sandbox (wrap sync call to avoid blocking)
115-
self._sandbox = await asyncio.get_running_loop().run_in_executor(
116-
None, lambda: client.create(params)
117-
)
110+
self._sandbox = await asyncio.get_running_loop().run_in_executor(None, lambda: client.create(params))
118111

119112
# Initialize workspace directories
120113
await self.run_command(WORKSPACE_INIT_COMMAND)
@@ -131,9 +124,7 @@ async def cleanup(self) -> None:
131124
logger.info(f"Cleaning up Daytona sandbox: {self._sandbox.id}")
132125
try:
133126
# Wrap sync call to avoid blocking
134-
await asyncio.get_running_loop().run_in_executor(
135-
None, self._sandbox.delete
136-
)
127+
await asyncio.get_running_loop().run_in_executor(None, self._sandbox.delete)
137128
self._sandbox = None
138129
except Exception as e:
139130
logger.error(f"Failed to cleanup Daytona sandbox: {e}")
@@ -163,8 +154,7 @@ async def run_command(
163154
command,
164155
cwd=working_dir,
165156
env=env,
166-
timeout=int(timeout),
167-
),
157+
timeout=int(timeout), ),
168158
),
169159
timeout=timeout,
170160
)
@@ -199,9 +189,7 @@ async def read_file(self, path: str) -> str:
199189
try:
200190
# Wrap sync call to avoid blocking
201191
# Daytona SDK uses download_file() which returns bytes
202-
data = await asyncio.get_running_loop().run_in_executor(
203-
None, lambda: self._sandbox.fs.download_file(path)
204-
)
192+
data = await asyncio.get_running_loop().run_in_executor(None, lambda: self._sandbox.fs.download_file(path))
205193
return data.decode("utf-8", errors="replace")
206194
except Exception as e:
207195
if "not found" in str(e).lower():
@@ -223,8 +211,7 @@ async def write_file(self, path: str, content: str) -> None:
223211
# Wrap sync call to avoid blocking
224212
# Daytona SDK uses upload_file(data, path) which takes bytes
225213
await asyncio.get_running_loop().run_in_executor(
226-
None, lambda: self._sandbox.fs.upload_file(content.encode("utf-8"), path)
227-
)
214+
None, lambda: self._sandbox.fs.upload_file(content.encode("utf-8"), path))
228215
except Exception as e:
229216
logger.error(f"Failed to write file {path}: {e}")
230217
raise

examples/sandbox_agent/src/nat_sandbox_agent/sandbox/docker_sandbox.py

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
15-
1615
"""Docker-based sandbox implementation."""
1716

1817
import asyncio
@@ -22,11 +21,11 @@
2221
import tarfile
2322
import uuid
2423

24+
import docker
2525
from docker.errors import ContainerError
2626
from docker.errors import ImageNotFound
2727
from docker.errors import NotFound
2828

29-
import docker
3029
from nat_sandbox_agent.sandbox.base import WORKSPACE_INIT_COMMAND
3130
from nat_sandbox_agent.sandbox.base import WORKSPACE_ROOT
3231
from nat_sandbox_agent.sandbox.base import BaseSandbox
@@ -96,9 +95,7 @@ async def start(self) -> None:
9695
self._client.images.get(self._image)
9796
except ImageNotFound:
9897
logger.info(f"Pulling image: {self._image}")
99-
await asyncio.get_running_loop().run_in_executor(
100-
None, self._client.images.pull, self._image
101-
)
98+
await asyncio.get_running_loop().run_in_executor(None, self._client.images.pull, self._image)
10299

103100
# Container configuration
104101
container_config = {
@@ -123,12 +120,9 @@ async def start(self) -> None:
123120

124121
# Create and start container
125122
self._container = await asyncio.get_running_loop().run_in_executor(
126-
None, lambda: self._client.containers.create(**container_config)
127-
)
123+
None, lambda: self._client.containers.create(**container_config))
128124

129-
await asyncio.get_running_loop().run_in_executor(
130-
None, self._container.start
131-
)
125+
await asyncio.get_running_loop().run_in_executor(None, self._container.start)
132126

133127
# Initialize workspace directories
134128
await self.run_command(WORKSPACE_INIT_COMMAND)
@@ -148,9 +142,7 @@ async def cleanup(self) -> None:
148142
if self._container:
149143
logger.info(f"Cleaning up Docker sandbox: {self._container_name}")
150144
try:
151-
await asyncio.get_running_loop().run_in_executor(
152-
None, lambda: self._container.remove(force=True)
153-
)
145+
await asyncio.get_running_loop().run_in_executor(None, lambda: self._container.remove(force=True))
154146
self._container = None
155147
except NotFound:
156148
# Container already removed
@@ -190,8 +182,7 @@ async def run_command(
190182
cmd=wrapped_command,
191183
workdir=working_dir,
192184
environment=env,
193-
demux=True,
194-
),
185+
demux=True, ),
195186
),
196187
timeout=timeout + 5, # Give container timeout a chance to fire first
197188
)
@@ -263,9 +254,7 @@ def _extract_from_archive():
263254

264255
try:
265256
# Wrap all blocking I/O in run_in_executor
266-
return await asyncio.get_running_loop().run_in_executor(
267-
None, _extract_from_archive
268-
)
257+
return await asyncio.get_running_loop().run_in_executor(None, _extract_from_archive)
269258

270259
except NotFound:
271260
raise FileNotFoundError(f"File not found: {path}") from None

examples/sandbox_agent/src/nat_sandbox_agent/sandbox/factory.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
15-
1615
"""Factory for creating sandbox instances."""
1716

1817
import os
@@ -159,7 +158,9 @@ def create_sandbox(config: SandboxConfig) -> BaseSandbox:
159158
volumes = None
160159
if config.volumes:
161160
volumes = {
162-
host_path: {"bind": container_path, "mode": "rw"}
161+
host_path: {
162+
"bind": container_path, "mode": "rw"
163+
}
163164
for host_path, container_path in config.volumes.items()
164165
}
165166

examples/sandbox_agent/src/nat_sandbox_agent/tools/__init__.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
15-
1615
"""Tools module - Modular tool implementations.
1716
1817
Tool Architecture:
@@ -31,13 +30,10 @@
3130
__all__ = [
3231
# Factory
3332
"create_all_tools",
34-
"get_tool_descriptions",
35-
# Sandbox
33+
"get_tool_descriptions", # Sandbox
3634
"create_sandbox_tools",
37-
"SandboxToolExecutor",
38-
# Host
39-
"create_host_tools",
40-
# Utilities
35+
"SandboxToolExecutor", # Host
36+
"create_host_tools", # Utilities
4137
"DEFAULT_MAX_OUTPUT_CHARS",
4238
"truncate_output",
4339
]

0 commit comments

Comments
 (0)