opensandbox-code-interpreter 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,343 @@
1
+ #
2
+ # Copyright 2025 Alibaba Group Holding Ltd.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ """
17
+ Code Interpreter SDK providing secure, isolated code execution capabilities.
18
+
19
+ This module provides the main CodeInterpreter class that extends basic Sandbox
20
+ functionality with specialized code execution features, including multi-language
21
+ support, session management, and variable persistence.
22
+ """
23
+
24
+ import logging
25
+ from datetime import datetime, timedelta, timezone
26
+ from uuid import UUID
27
+
28
+ from opensandbox.exceptions import (
29
+ InvalidArgumentException,
30
+ SandboxException,
31
+ SandboxInternalException,
32
+ )
33
+ from opensandbox.models.sandboxes import (
34
+ SandboxEndpoint,
35
+ SandboxInfo,
36
+ SandboxMetrics,
37
+ )
38
+ from opensandbox.sandbox import Sandbox
39
+
40
+ from code_interpreter.adapters.factory import AdapterFactory
41
+ from code_interpreter.services.code import Codes
42
+
43
+ logger = logging.getLogger(__name__)
44
+
45
+
46
+ class CodeInterpreter:
47
+ """
48
+ Code Interpreter SDK providing secure, isolated code execution capabilities.
49
+
50
+ This class extends the basic Sandbox functionality with specialized code execution features,
51
+ including multi-language support, session management, and variable persistence.
52
+
53
+ Key Features:
54
+
55
+ - Multi-language Code Execution: Support for Python, JavaScript, Bash, Java, Kotlin
56
+ - Session Management: Persistent execution contexts with variable state
57
+ - Sandbox Integration: Full access to underlying sandbox file system and command execution
58
+ - Streaming Execution: Real-time code execution with output streaming
59
+ - Variable Inspection: Access to execution variables and state
60
+
61
+ Usage Example:
62
+
63
+ ```python
64
+ # First create a sandbox instance
65
+
66
+ sandbox = await Sandbox.create(
67
+ "python:3.11",
68
+ resource={"cpu": "1", "memory": "2Gi"}
69
+ )
70
+
71
+ # Then create a code interpreter wrapping the sandbox
72
+ interpreter = await CodeInterpreter.create(sandbox=sandbox)
73
+
74
+ # Execute code with context
75
+ from code_interpreter.models.code import SupportedLanguage
76
+ context = await interpreter.codes.create_context(SupportedLanguage.PYTHON)
77
+ result = await interpreter.codes.run("print('Hello World')", context=context)
78
+ print(result.logs.stdout) # Output: Hello World
79
+
80
+ # Access underlying sandbox for file operations
81
+ await interpreter.sandbox.files.write_files([
82
+ WriteEntry(path="data.txt", data="Hello")
83
+ ])
84
+ file_result = await interpreter.codes.run(
85
+ "with open('data.txt') as f: print(f.read())",
86
+ context=context,
87
+ )
88
+
89
+ # Always clean up resources
90
+ await interpreter.kill()
91
+ await interpreter.sandbox.close()
92
+ ```
93
+ """
94
+
95
+ def __init__(self, sandbox: Sandbox, code_service: Codes) -> None:
96
+ """
97
+ Initialize CodeInterpreter with sandbox and code service.
98
+
99
+ Note: This constructor is for internal use. Use CodeInterpreter.create() instead.
100
+
101
+ Args:
102
+ sandbox: Underlying sandbox instance
103
+ code_service: Code execution implementation
104
+ """
105
+ self._sandbox = sandbox
106
+ self._code_service = code_service
107
+
108
+ @property
109
+ def sandbox(self) -> Sandbox:
110
+ """
111
+ Provides access to the underlying sandbox instance.
112
+
113
+ Returns:
114
+ The underlying sandbox instance
115
+ """
116
+ return self._sandbox
117
+
118
+ @property
119
+ def id(self) -> UUID:
120
+ """
121
+ Gets the unique identifier of this code interpreter (same as underlying sandbox ID).
122
+
123
+ Returns:
124
+ UUID of the code interpreter/sandbox
125
+ """
126
+ return self._sandbox.id
127
+
128
+ @property
129
+ def files(self):
130
+ """
131
+ Provides access to file system operations within the sandbox.
132
+
133
+ Allows writing, reading, listing, and deleting files and directories.
134
+
135
+ Returns:
136
+ Service for filesystem manipulation
137
+ """
138
+ return self._sandbox.files
139
+
140
+ @property
141
+ def commands(self):
142
+ """
143
+ Provides access to command execution operations.
144
+
145
+ Allows running shell commands, capturing output, and managing processes.
146
+
147
+ Returns:
148
+ Service for command execution
149
+ """
150
+ return self._sandbox.commands
151
+
152
+ @property
153
+ def metrics(self):
154
+ """
155
+ Provides access to sandbox metrics and monitoring.
156
+
157
+ Allows retrieving resource usage statistics (CPU, memory) and other performance metrics.
158
+
159
+ Returns:
160
+ Service for metrics retrieval
161
+ """
162
+ return self._sandbox.metrics
163
+
164
+ @property
165
+ def codes(self) -> Codes:
166
+ """
167
+ Provides access to code execution operations.
168
+
169
+ This service enables:
170
+ - Multi-language code execution (Python, JavaScript, Bash, etc.)
171
+ - Execution context management with persistent variables
172
+ - Real-time output streaming and interruption capabilities
173
+
174
+ Returns:
175
+ Service for advanced code execution with session support
176
+ """
177
+ return self._code_service
178
+
179
+ async def get_endpoint(self, port: int) -> SandboxEndpoint:
180
+ """
181
+ Gets a specific network endpoint for the underlying sandbox.
182
+
183
+ This allows access to specific ports exposed by the sandbox, which can be
184
+ useful for connecting to additional services or debugging interfaces.
185
+
186
+ Args:
187
+ port: The port number to get the endpoint for
188
+
189
+ Returns:
190
+ Endpoint information including host, port, and connection details
191
+
192
+ Raises:
193
+ SandboxException: If endpoint cannot be retrieved
194
+ """
195
+ return await self._sandbox.get_endpoint(port)
196
+
197
+ async def get_info(self) -> SandboxInfo:
198
+ """
199
+ Gets the current status of this sandbox.
200
+
201
+ Returns:
202
+ Current sandbox status including state and metadata
203
+
204
+ Raises:
205
+ SandboxException: If status cannot be retrieved
206
+ """
207
+ return await self._sandbox.get_info()
208
+
209
+ async def get_metrics(self) -> SandboxMetrics:
210
+ """
211
+ Gets the current resource usage metrics for the underlying sandbox.
212
+
213
+ Provides real-time information about CPU usage, memory consumption,
214
+ disk I/O, and other performance metrics.
215
+
216
+ Returns:
217
+ Current sandbox metrics including CPU, memory, and I/O statistics
218
+
219
+ Raises:
220
+ SandboxException: If metrics cannot be retrieved
221
+ """
222
+ return await self._sandbox.get_metrics()
223
+
224
+ async def renew(self, timeout: timedelta | int) -> None:
225
+ """
226
+ Renew the sandbox expiration time to delay automatic termination.
227
+
228
+ The new expiration time will be set to the current time plus the provided duration.
229
+
230
+ Args:
231
+ timeout: Duration to add to the current time to set the new expiration.
232
+ Can be timedelta or seconds as int.
233
+
234
+ Raises:
235
+ SandboxException: If the operation fails
236
+ """
237
+ if isinstance(timeout, int):
238
+ timeout = timedelta(seconds=timeout)
239
+
240
+ logger.info(
241
+ "Renew code interpreter %s timeout, estimated expiration to %s",
242
+ self.id,
243
+ datetime.now(timezone.utc) + timeout,
244
+ )
245
+ await self._sandbox.renew(timeout)
246
+
247
+ async def pause(self) -> None:
248
+ """
249
+ Pauses the sandbox while preserving its state.
250
+
251
+ The sandbox will transition to PAUSED state and can be resumed later.
252
+ All running processes will be suspended.
253
+
254
+ Raises:
255
+ SandboxException: If pause operation fails
256
+ """
257
+ logger.info("Pausing code interpreter: %s", self.id)
258
+ await self._sandbox.pause()
259
+
260
+ async def resume(self) -> None:
261
+ """
262
+ Resumes a previously paused code interpreter.
263
+
264
+ The sandbox will transition from PAUSED to RUNNING state and all
265
+ suspended processes will be resumed.
266
+
267
+ Raises:
268
+ SandboxException: If resume operation fails
269
+ """
270
+ logger.info("Resuming code interpreter: %s", self.id)
271
+ await self._sandbox.resume()
272
+
273
+ async def kill(self) -> None:
274
+ """
275
+ This method sends a termination signal to the remote sandbox instance, causing it to stop immediately.
276
+ This is an irreversible operation.
277
+
278
+ Note: This method does NOT close the local `Sandbox` object resources (like connection pools).
279
+ You should call `close()` or use async context manager to clean up local resources.
280
+
281
+ Raises:
282
+ SandboxException: If termination fails
283
+ """
284
+ logger.info("Killing code interpreter: %s", self.id)
285
+ await self._sandbox.kill()
286
+
287
+ async def is_healthy(self) -> bool:
288
+ """
289
+ Checks if the code interpreter and its underlying sandbox are healthy and responsive.
290
+
291
+ This performs health checks on both the sandbox infrastructure and code execution services.
292
+
293
+ Returns:
294
+ True if both sandbox and code execution services are healthy, False otherwise
295
+ """
296
+ return await self._sandbox.is_healthy()
297
+
298
+ @classmethod
299
+ async def create(cls, sandbox: Sandbox) -> "CodeInterpreter":
300
+ """
301
+ Creates a CodeInterpreter from an existing Sandbox instance.
302
+
303
+ This factory method handles the creation and initialization of CodeInterpreter
304
+ services, including the code execution service and language configuration.
305
+
306
+ CodeInterpreter must be created by wrapping an existing Sandbox instance with
307
+ code execution capabilities. This design ensures clear separation of concerns:
308
+ - Sandbox handles infrastructure (containers, resources, networking)
309
+ - CodeInterpreter adds code execution capabilities on top
310
+
311
+ Args:
312
+ sandbox: Existing sandbox instance to wrap with code execution capabilities
313
+
314
+ Returns:
315
+ CodeInterpreter instance wrapping the sandbox
316
+
317
+ Raises:
318
+ InvalidArgumentException: If sandbox is not provided
319
+ SandboxException: If creation fails
320
+ SandboxInternalException: If internal service initialization fails
321
+ """
322
+ if sandbox is None:
323
+ raise InvalidArgumentException("Sandbox instance must be provided")
324
+
325
+ logger.info("Creating code interpreter from sandbox: %s", sandbox.id)
326
+
327
+ factory = AdapterFactory(sandbox.connection_config)
328
+
329
+ try:
330
+ # Connect to the execd daemon endpoint for code execution services
331
+ from opensandbox.constants import DEFAULT_EXECD_PORT
332
+ code_interpreter_endpoint = await sandbox.get_endpoint(DEFAULT_EXECD_PORT)
333
+ code_execution_service = factory.create_code_execution_service(code_interpreter_endpoint)
334
+
335
+ logger.info("Code interpreter %s created successfully", sandbox.id)
336
+
337
+ return cls(sandbox, code_execution_service)
338
+ except Exception as e:
339
+ if isinstance(e, SandboxException):
340
+ raise
341
+ raise SandboxInternalException(
342
+ f"Failed to create code interpreter: {e}", cause=e
343
+ ) from e
@@ -0,0 +1,28 @@
1
+ #
2
+ # Copyright 2025 Alibaba Group Holding Ltd.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ """
17
+ Data models for code execution and interpretation.
18
+ """
19
+
20
+ from code_interpreter.models.code import (
21
+ CodeContext,
22
+ SupportedLanguage,
23
+ )
24
+
25
+ __all__ = [
26
+ "CodeContext",
27
+ "SupportedLanguage",
28
+ ]
@@ -0,0 +1,67 @@
1
+ #
2
+ # Copyright 2025 Alibaba Group Holding Ltd.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ """
17
+ Code execution models.
18
+
19
+ Models for code contexts, execution requests, and language support.
20
+ """
21
+
22
+
23
+ from pydantic import BaseModel, ConfigDict, Field, field_validator
24
+
25
+
26
+ class SupportedLanguage:
27
+ """
28
+ Supported programming languages for code execution.
29
+
30
+ This class defines the languages that are officially supported by the code interpreter.
31
+ When adding new languages, ensure corresponding execution environments are available.
32
+ """
33
+ PYTHON = "python"
34
+ JAVA = "java"
35
+ GO = "go"
36
+ TYPESCRIPT = "typescript"
37
+ BASH = "bash"
38
+
39
+
40
+ class CodeContext(BaseModel):
41
+ """
42
+ Represents an execution context for code interpretation.
43
+
44
+ A CodeContext maintains the execution environment for a specific programming
45
+ language, including the working directory, language configuration, and
46
+ persistent state across multiple code executions.
47
+
48
+ Context Lifecycle:
49
+
50
+ 1. Creation: Context is created with language and working directory
51
+ 2. Execution: Code runs within this context, building up state
52
+ 3. Persistence: Variables, imports, and functions persist between executions
53
+ 4. Cleanup: Context can be explicitly destroyed or garbage collected
54
+ """
55
+
56
+ id: str | None = Field(default=None, description="Unique identifier for this execution context")
57
+ language: str = Field(description="Programming language for this context (e.g., 'python', 'javascript')")
58
+
59
+ @field_validator('language')
60
+ @classmethod
61
+ def language_must_not_be_empty(cls, v: str) -> str:
62
+ if not v.strip():
63
+ raise ValueError("Language cannot be blank")
64
+ return v
65
+
66
+
67
+ model_config = ConfigDict(arbitrary_types_allowed=True)
@@ -0,0 +1,41 @@
1
+ #
2
+ # Copyright 2025 Alibaba Group Holding Ltd.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ """
17
+ Synchronous code execution models for Code Interpreter SDK.
18
+ """
19
+
20
+ from pydantic import BaseModel, Field, field_validator
21
+
22
+
23
+ class SupportedLanguageSync:
24
+ # kept for symmetry; values match SupportedLanguage
25
+ PYTHON = "python"
26
+ JAVA = "java"
27
+ GO = "go"
28
+ TYPESCRIPT = "typescript"
29
+ BASH = "bash"
30
+
31
+
32
+ class CodeContextSync(BaseModel):
33
+ id: str | None = Field(default=None)
34
+ language: str = Field(description="Programming language for this context")
35
+
36
+ @field_validator("language")
37
+ @classmethod
38
+ def language_must_not_be_empty(cls, v: str) -> str:
39
+ if not v.strip():
40
+ raise ValueError("Language cannot be blank")
41
+ return v
File without changes
@@ -0,0 +1,24 @@
1
+ #
2
+ # Copyright 2025 Alibaba Group Holding Ltd.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ """
17
+ Services for code execution and interpretation.
18
+ """
19
+
20
+ from code_interpreter.services.code import Codes
21
+
22
+ __all__ = [
23
+ "Codes",
24
+ ]
@@ -0,0 +1,149 @@
1
+ #
2
+ # Copyright 2025 Alibaba Group Holding Ltd.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ """
17
+ Code execution service interface.
18
+
19
+ Defines the contract for multi-language code interpretation with context management,
20
+ session persistence, and real-time execution capabilities.
21
+ """
22
+
23
+ from typing import Protocol
24
+
25
+ from opensandbox.models.execd import Execution, ExecutionHandlers
26
+
27
+ from code_interpreter.models.code import CodeContext
28
+
29
+
30
+ class Codes(Protocol):
31
+ """
32
+ Code execution service for multi-language code interpretation.
33
+
34
+ This service provides advanced code execution capabilities with context management,
35
+ session persistence, and multi-language support. It extends basic command execution
36
+ with interpreter-specific features like variable inspection and execution history.
37
+
38
+ Supported Languages:
39
+
40
+ - Python: Full Python 3.x support with package management
41
+ - JavaScript/Node.js: ES6+ with npm package support
42
+ - Bash: Shell scripting with full system access
43
+ - Java: Compilation and execution with classpath management
44
+ - Kotlin: Script and compiled Kotlin execution
45
+
46
+ Key Features:
47
+
48
+ - Execution Contexts: Isolated environments with persistent state
49
+ - Variable Persistence: Variables and imports persist across executions
50
+ - Real-time Interruption: Stop long-running code execution safely
51
+ - Output Streaming: Real-time stdout/stderr with proper buffering
52
+ - Error Handling: Language-specific error parsing and reporting
53
+
54
+ Usage Example:
55
+
56
+ ```python
57
+ # Create execution context
58
+ context = await code_service.create_context(SupportedLanguage.PYTHON)
59
+
60
+ # Execute code with persistent state
61
+ result1 = await code_service.run(
62
+ "import numpy as np; x = 42",
63
+ context=context,
64
+ )
65
+
66
+ result2 = await code_service.run(
67
+ "print(f'Value: {x}, NumPy version: {np.__version__}')",
68
+ context=context,
69
+ )
70
+ # Variables 'x' and 'np' persist between executions
71
+ ```
72
+ """
73
+
74
+ async def create_context(self, language: str) -> CodeContext:
75
+ """
76
+ Creates a new execution context for code interpretation.
77
+
78
+ An execution context maintains the state of variables, imports, and working
79
+ directory across multiple code executions. This allows for interactive
80
+ programming sessions where subsequent code can reference previously
81
+ defined variables and functions.
82
+
83
+ Args:
84
+ language: The programming language for this context (e.g., "python", "javascript")
85
+
86
+ Returns:
87
+ A new CodeContext with the specified configuration
88
+
89
+ Raises:
90
+ SandboxException: If the language is not supported or context creation fails
91
+ """
92
+ ...
93
+
94
+ async def run(
95
+ self,
96
+ code: str,
97
+ *,
98
+ context: CodeContext | None = None,
99
+ handlers: ExecutionHandlers | None = None,
100
+ ) -> Execution:
101
+ """
102
+ Executes code within the specified context.
103
+
104
+ This method runs the provided code string in the language interpreter,
105
+ capturing all output, errors, and execution metadata. The execution
106
+ happens within the context's environment, preserving variable state
107
+ and working directory.
108
+
109
+ Execution Behavior:
110
+
111
+ - Asynchronous: Non-blocking execution with proper async handling
112
+ - Stateful: Variables and imports persist in the context
113
+ - Streaming: Output is captured in real-time as it's produced
114
+ - Interruptible: Can be stopped using interrupt() method
115
+
116
+ Args:
117
+ code: Source code to execute.
118
+ context: Execution context (language + optional id). If None, a temporary Python context is used.
119
+ handlers: Optional streaming handlers for stdout/stderr/events.
120
+
121
+ Returns:
122
+ Execution with stdout, stderr, exit code, and execution metadata
123
+
124
+ Raises:
125
+ SandboxException: If execution fails or times out
126
+ """
127
+ ...
128
+
129
+ async def interrupt(self, execution_id: str) -> None:
130
+ """
131
+ Interrupts a currently running code execution.
132
+
133
+ This method safely terminates a running code execution, cleaning up
134
+ resources and ensuring the interpreter remains in a consistent state.
135
+ The interruption is cooperative and may take some time to complete.
136
+
137
+ Interruption Behavior:
138
+
139
+ - Safe: Preserves interpreter state and doesn't corrupt the context
140
+ - Cooperative: Respects language-specific interruption mechanisms
141
+ - Timeout: Will force-kill after a reasonable timeout if needed
142
+
143
+ Args:
144
+ execution_id: The unique identifier of the execution to interrupt
145
+
146
+ Raises:
147
+ SandboxException: If interruption fails
148
+ """
149
+ ...
@@ -0,0 +1,18 @@
1
+ #
2
+ # Copyright 2025 Alibaba Group Holding Ltd.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+ from code_interpreter.sync.code_interpreter import CodeInterpreterSync
17
+
18
+ __all__ = ["CodeInterpreterSync"]