moru 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.
- moru/__init__.py +174 -0
- moru/api/__init__.py +164 -0
- moru/api/client/__init__.py +8 -0
- moru/api/client/api/__init__.py +1 -0
- moru/api/client/api/sandboxes/__init__.py +1 -0
- moru/api/client/api/sandboxes/delete_sandboxes_sandbox_id.py +161 -0
- moru/api/client/api/sandboxes/get_sandboxes.py +176 -0
- moru/api/client/api/sandboxes/get_sandboxes_metrics.py +173 -0
- moru/api/client/api/sandboxes/get_sandboxes_sandbox_id.py +163 -0
- moru/api/client/api/sandboxes/get_sandboxes_sandbox_id_logs.py +199 -0
- moru/api/client/api/sandboxes/get_sandboxes_sandbox_id_metrics.py +212 -0
- moru/api/client/api/sandboxes/get_v2_sandboxes.py +230 -0
- moru/api/client/api/sandboxes/post_sandboxes.py +172 -0
- moru/api/client/api/sandboxes/post_sandboxes_sandbox_id_connect.py +193 -0
- moru/api/client/api/sandboxes/post_sandboxes_sandbox_id_pause.py +165 -0
- moru/api/client/api/sandboxes/post_sandboxes_sandbox_id_refreshes.py +181 -0
- moru/api/client/api/sandboxes/post_sandboxes_sandbox_id_resume.py +189 -0
- moru/api/client/api/sandboxes/post_sandboxes_sandbox_id_timeout.py +193 -0
- moru/api/client/api/templates/__init__.py +1 -0
- moru/api/client/api/templates/delete_templates_template_id.py +157 -0
- moru/api/client/api/templates/get_templates.py +172 -0
- moru/api/client/api/templates/get_templates_template_id.py +195 -0
- moru/api/client/api/templates/get_templates_template_id_builds_build_id_status.py +217 -0
- moru/api/client/api/templates/get_templates_template_id_files_hash.py +180 -0
- moru/api/client/api/templates/patch_templates_template_id.py +183 -0
- moru/api/client/api/templates/post_templates.py +172 -0
- moru/api/client/api/templates/post_templates_template_id.py +181 -0
- moru/api/client/api/templates/post_templates_template_id_builds_build_id.py +170 -0
- moru/api/client/api/templates/post_v2_templates.py +172 -0
- moru/api/client/api/templates/post_v3_templates.py +172 -0
- moru/api/client/api/templates/post_v_2_templates_template_id_builds_build_id.py +192 -0
- moru/api/client/client.py +286 -0
- moru/api/client/errors.py +16 -0
- moru/api/client/models/__init__.py +123 -0
- moru/api/client/models/aws_registry.py +85 -0
- moru/api/client/models/aws_registry_type.py +8 -0
- moru/api/client/models/build_log_entry.py +89 -0
- moru/api/client/models/build_status_reason.py +95 -0
- moru/api/client/models/connect_sandbox.py +59 -0
- moru/api/client/models/created_access_token.py +100 -0
- moru/api/client/models/created_team_api_key.py +166 -0
- moru/api/client/models/disk_metrics.py +91 -0
- moru/api/client/models/error.py +67 -0
- moru/api/client/models/gcp_registry.py +69 -0
- moru/api/client/models/gcp_registry_type.py +8 -0
- moru/api/client/models/general_registry.py +77 -0
- moru/api/client/models/general_registry_type.py +8 -0
- moru/api/client/models/identifier_masking_details.py +83 -0
- moru/api/client/models/listed_sandbox.py +154 -0
- moru/api/client/models/log_level.py +11 -0
- moru/api/client/models/max_team_metric.py +78 -0
- moru/api/client/models/mcp_type_0.py +44 -0
- moru/api/client/models/new_access_token.py +59 -0
- moru/api/client/models/new_sandbox.py +172 -0
- moru/api/client/models/new_team_api_key.py +59 -0
- moru/api/client/models/node.py +155 -0
- moru/api/client/models/node_detail.py +165 -0
- moru/api/client/models/node_metrics.py +122 -0
- moru/api/client/models/node_status.py +11 -0
- moru/api/client/models/node_status_change.py +79 -0
- moru/api/client/models/post_sandboxes_sandbox_id_refreshes_body.py +59 -0
- moru/api/client/models/post_sandboxes_sandbox_id_timeout_body.py +59 -0
- moru/api/client/models/resumed_sandbox.py +68 -0
- moru/api/client/models/sandbox.py +145 -0
- moru/api/client/models/sandbox_detail.py +183 -0
- moru/api/client/models/sandbox_log.py +70 -0
- moru/api/client/models/sandbox_log_entry.py +93 -0
- moru/api/client/models/sandbox_log_entry_fields.py +44 -0
- moru/api/client/models/sandbox_logs.py +91 -0
- moru/api/client/models/sandbox_metric.py +118 -0
- moru/api/client/models/sandbox_network_config.py +92 -0
- moru/api/client/models/sandbox_state.py +9 -0
- moru/api/client/models/sandboxes_with_metrics.py +59 -0
- moru/api/client/models/team.py +83 -0
- moru/api/client/models/team_api_key.py +158 -0
- moru/api/client/models/team_metric.py +86 -0
- moru/api/client/models/team_user.py +68 -0
- moru/api/client/models/template.py +217 -0
- moru/api/client/models/template_build.py +139 -0
- moru/api/client/models/template_build_file_upload.py +70 -0
- moru/api/client/models/template_build_info.py +126 -0
- moru/api/client/models/template_build_request.py +115 -0
- moru/api/client/models/template_build_request_v2.py +88 -0
- moru/api/client/models/template_build_request_v3.py +88 -0
- moru/api/client/models/template_build_start_v2.py +184 -0
- moru/api/client/models/template_build_status.py +11 -0
- moru/api/client/models/template_legacy.py +207 -0
- moru/api/client/models/template_request_response_v3.py +83 -0
- moru/api/client/models/template_step.py +91 -0
- moru/api/client/models/template_update_request.py +59 -0
- moru/api/client/models/template_with_builds.py +148 -0
- moru/api/client/models/update_team_api_key.py +59 -0
- moru/api/client/py.typed +1 -0
- moru/api/client/types.py +54 -0
- moru/api/client_async/__init__.py +50 -0
- moru/api/client_sync/__init__.py +52 -0
- moru/api/metadata.py +14 -0
- moru/connection_config.py +217 -0
- moru/envd/api.py +59 -0
- moru/envd/filesystem/filesystem_connect.py +193 -0
- moru/envd/filesystem/filesystem_pb2.py +76 -0
- moru/envd/filesystem/filesystem_pb2.pyi +233 -0
- moru/envd/process/process_connect.py +155 -0
- moru/envd/process/process_pb2.py +92 -0
- moru/envd/process/process_pb2.pyi +304 -0
- moru/envd/rpc.py +61 -0
- moru/envd/versions.py +6 -0
- moru/exceptions.py +95 -0
- moru/sandbox/commands/command_handle.py +69 -0
- moru/sandbox/commands/main.py +39 -0
- moru/sandbox/filesystem/filesystem.py +94 -0
- moru/sandbox/filesystem/watch_handle.py +60 -0
- moru/sandbox/main.py +210 -0
- moru/sandbox/mcp.py +1120 -0
- moru/sandbox/network.py +8 -0
- moru/sandbox/sandbox_api.py +210 -0
- moru/sandbox/signature.py +45 -0
- moru/sandbox/utils.py +34 -0
- moru/sandbox_async/commands/command.py +336 -0
- moru/sandbox_async/commands/command_handle.py +196 -0
- moru/sandbox_async/commands/pty.py +240 -0
- moru/sandbox_async/filesystem/filesystem.py +531 -0
- moru/sandbox_async/filesystem/watch_handle.py +62 -0
- moru/sandbox_async/main.py +734 -0
- moru/sandbox_async/paginator.py +69 -0
- moru/sandbox_async/sandbox_api.py +325 -0
- moru/sandbox_async/utils.py +7 -0
- moru/sandbox_sync/commands/command.py +328 -0
- moru/sandbox_sync/commands/command_handle.py +150 -0
- moru/sandbox_sync/commands/pty.py +230 -0
- moru/sandbox_sync/filesystem/filesystem.py +518 -0
- moru/sandbox_sync/filesystem/watch_handle.py +69 -0
- moru/sandbox_sync/main.py +726 -0
- moru/sandbox_sync/paginator.py +69 -0
- moru/sandbox_sync/sandbox_api.py +308 -0
- moru/template/consts.py +30 -0
- moru/template/dockerfile_parser.py +275 -0
- moru/template/logger.py +232 -0
- moru/template/main.py +1360 -0
- moru/template/readycmd.py +138 -0
- moru/template/types.py +105 -0
- moru/template/utils.py +320 -0
- moru/template_async/build_api.py +202 -0
- moru/template_async/main.py +366 -0
- moru/template_sync/build_api.py +199 -0
- moru/template_sync/main.py +371 -0
- moru-0.1.0.dist-info/METADATA +63 -0
- moru-0.1.0.dist-info/RECORD +152 -0
- moru-0.1.0.dist-info/WHEEL +4 -0
- moru-0.1.0.dist-info/licenses/LICENSE +9 -0
- moru_connect/__init__.py +1 -0
- moru_connect/client.py +493 -0
moru/__init__.py
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Secure sandboxed cloud environments made for AI agents and AI apps.
|
|
3
|
+
|
|
4
|
+
Check docs [here](https://moru.io/docs).
|
|
5
|
+
|
|
6
|
+
Moru Sandbox is a secure cloud sandbox environment made for AI agents and AI
|
|
7
|
+
apps.
|
|
8
|
+
Sandboxes allow AI agents and apps to have long running cloud secure environments.
|
|
9
|
+
In these environments, large language models can use the same tools as humans do.
|
|
10
|
+
|
|
11
|
+
Moru Python SDK supports both sync and async API:
|
|
12
|
+
|
|
13
|
+
```py
|
|
14
|
+
from moru import Sandbox
|
|
15
|
+
|
|
16
|
+
# Create sandbox
|
|
17
|
+
sandbox = Sandbox.create()
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
```py
|
|
21
|
+
from moru import AsyncSandbox
|
|
22
|
+
|
|
23
|
+
# Create sandbox
|
|
24
|
+
sandbox = await AsyncSandbox.create()
|
|
25
|
+
```
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from .api import (
|
|
29
|
+
ApiClient,
|
|
30
|
+
client,
|
|
31
|
+
)
|
|
32
|
+
from .connection_config import (
|
|
33
|
+
ConnectionConfig,
|
|
34
|
+
ProxyTypes,
|
|
35
|
+
)
|
|
36
|
+
from .exceptions import (
|
|
37
|
+
AuthenticationException,
|
|
38
|
+
BuildException,
|
|
39
|
+
FileUploadException,
|
|
40
|
+
InvalidArgumentException,
|
|
41
|
+
NotEnoughSpaceException,
|
|
42
|
+
NotFoundException,
|
|
43
|
+
SandboxException,
|
|
44
|
+
TemplateException,
|
|
45
|
+
TimeoutException,
|
|
46
|
+
)
|
|
47
|
+
from .sandbox.commands.command_handle import (
|
|
48
|
+
CommandExitException,
|
|
49
|
+
CommandResult,
|
|
50
|
+
PtyOutput,
|
|
51
|
+
PtySize,
|
|
52
|
+
Stderr,
|
|
53
|
+
Stdout,
|
|
54
|
+
)
|
|
55
|
+
from .sandbox.commands.main import ProcessInfo
|
|
56
|
+
from .sandbox.filesystem.filesystem import EntryInfo, FileType, WriteInfo
|
|
57
|
+
from .sandbox.filesystem.watch_handle import (
|
|
58
|
+
FilesystemEvent,
|
|
59
|
+
FilesystemEventType,
|
|
60
|
+
)
|
|
61
|
+
from .sandbox.network import ALL_TRAFFIC
|
|
62
|
+
from .sandbox.sandbox_api import (
|
|
63
|
+
GitHubMcpServer,
|
|
64
|
+
GitHubMcpServerConfig,
|
|
65
|
+
McpServer,
|
|
66
|
+
SandboxInfo,
|
|
67
|
+
SandboxMetrics,
|
|
68
|
+
SandboxNetworkOpts,
|
|
69
|
+
SandboxQuery,
|
|
70
|
+
SandboxState,
|
|
71
|
+
)
|
|
72
|
+
from .sandbox_async.commands.command_handle import AsyncCommandHandle
|
|
73
|
+
from .sandbox_async.filesystem.watch_handle import AsyncWatchHandle
|
|
74
|
+
from .sandbox_async.main import AsyncSandbox
|
|
75
|
+
from .sandbox_async.paginator import AsyncSandboxPaginator
|
|
76
|
+
from .sandbox_async.utils import OutputHandler
|
|
77
|
+
from .sandbox_sync.commands.command_handle import CommandHandle
|
|
78
|
+
from .sandbox_sync.filesystem.watch_handle import WatchHandle
|
|
79
|
+
from .sandbox_sync.main import Sandbox
|
|
80
|
+
from .sandbox_sync.paginator import SandboxPaginator
|
|
81
|
+
from .template.logger import (
|
|
82
|
+
LogEntry,
|
|
83
|
+
LogEntryEnd,
|
|
84
|
+
LogEntryLevel,
|
|
85
|
+
LogEntryStart,
|
|
86
|
+
default_build_logger,
|
|
87
|
+
)
|
|
88
|
+
from .template.main import TemplateBase, TemplateClass
|
|
89
|
+
from .template.readycmd import (
|
|
90
|
+
ReadyCmd,
|
|
91
|
+
wait_for_file,
|
|
92
|
+
wait_for_port,
|
|
93
|
+
wait_for_process,
|
|
94
|
+
wait_for_timeout,
|
|
95
|
+
wait_for_url,
|
|
96
|
+
)
|
|
97
|
+
from .template.types import BuildInfo, CopyItem
|
|
98
|
+
from .template_async.main import AsyncTemplate
|
|
99
|
+
from .template_sync.main import Template
|
|
100
|
+
|
|
101
|
+
__all__ = [
|
|
102
|
+
# API
|
|
103
|
+
"ApiClient",
|
|
104
|
+
"client",
|
|
105
|
+
# Connection config
|
|
106
|
+
"ConnectionConfig",
|
|
107
|
+
"ProxyTypes",
|
|
108
|
+
# Exceptions
|
|
109
|
+
"SandboxException",
|
|
110
|
+
"TimeoutException",
|
|
111
|
+
"NotFoundException",
|
|
112
|
+
"AuthenticationException",
|
|
113
|
+
"InvalidArgumentException",
|
|
114
|
+
"NotEnoughSpaceException",
|
|
115
|
+
"TemplateException",
|
|
116
|
+
"BuildException",
|
|
117
|
+
"FileUploadException",
|
|
118
|
+
# Sandbox API
|
|
119
|
+
"SandboxInfo",
|
|
120
|
+
"SandboxMetrics",
|
|
121
|
+
"ProcessInfo",
|
|
122
|
+
"SandboxQuery",
|
|
123
|
+
"SandboxState",
|
|
124
|
+
"SandboxMetrics",
|
|
125
|
+
# Command handle
|
|
126
|
+
"CommandResult",
|
|
127
|
+
"Stderr",
|
|
128
|
+
"Stdout",
|
|
129
|
+
"CommandExitException",
|
|
130
|
+
"PtyOutput",
|
|
131
|
+
"PtySize",
|
|
132
|
+
# Filesystem
|
|
133
|
+
"FilesystemEvent",
|
|
134
|
+
"FilesystemEventType",
|
|
135
|
+
"EntryInfo",
|
|
136
|
+
"WriteInfo",
|
|
137
|
+
"FileType",
|
|
138
|
+
# Network
|
|
139
|
+
"SandboxNetworkOpts",
|
|
140
|
+
"ALL_TRAFFIC",
|
|
141
|
+
# Sync sandbox
|
|
142
|
+
"Sandbox",
|
|
143
|
+
"SandboxPaginator",
|
|
144
|
+
"WatchHandle",
|
|
145
|
+
"CommandHandle",
|
|
146
|
+
# Async sandbox
|
|
147
|
+
"OutputHandler",
|
|
148
|
+
"AsyncSandboxPaginator",
|
|
149
|
+
"AsyncSandbox",
|
|
150
|
+
"AsyncWatchHandle",
|
|
151
|
+
"AsyncCommandHandle",
|
|
152
|
+
# Template
|
|
153
|
+
"Template",
|
|
154
|
+
"AsyncTemplate",
|
|
155
|
+
"TemplateBase",
|
|
156
|
+
"TemplateClass",
|
|
157
|
+
"CopyItem",
|
|
158
|
+
"BuildInfo",
|
|
159
|
+
"ReadyCmd",
|
|
160
|
+
"wait_for_file",
|
|
161
|
+
"wait_for_url",
|
|
162
|
+
"wait_for_port",
|
|
163
|
+
"wait_for_process",
|
|
164
|
+
"wait_for_timeout",
|
|
165
|
+
"LogEntry",
|
|
166
|
+
"LogEntryStart",
|
|
167
|
+
"LogEntryEnd",
|
|
168
|
+
"LogEntryLevel",
|
|
169
|
+
"default_build_logger",
|
|
170
|
+
# MCP
|
|
171
|
+
"McpServer",
|
|
172
|
+
"GitHubMcpServer",
|
|
173
|
+
"GitHubMcpServerConfig",
|
|
174
|
+
]
|
moru/api/__init__.py
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import logging
|
|
3
|
+
import os
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from types import TracebackType
|
|
6
|
+
from typing import Optional, Union
|
|
7
|
+
|
|
8
|
+
from httpx import AsyncBaseTransport, BaseTransport, Limits
|
|
9
|
+
|
|
10
|
+
from moru.api.client.client import AuthenticatedClient
|
|
11
|
+
from moru.api.client.types import Response
|
|
12
|
+
from moru.api.metadata import default_headers
|
|
13
|
+
from moru.connection_config import ConnectionConfig
|
|
14
|
+
from moru.exceptions import (
|
|
15
|
+
AuthenticationException,
|
|
16
|
+
RateLimitException,
|
|
17
|
+
SandboxException,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
limits = Limits(
|
|
23
|
+
max_keepalive_connections=int(os.getenv("MORU_MAX_KEEPALIVE_CONNECTIONS", "20")),
|
|
24
|
+
max_connections=int(os.getenv("MORU_MAX_CONNECTIONS", "2000")),
|
|
25
|
+
keepalive_expiry=int(os.getenv("MORU_KEEPALIVE_EXPIRY", "300")),
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class SandboxCreateResponse:
|
|
31
|
+
sandbox_id: str
|
|
32
|
+
sandbox_domain: Optional[str]
|
|
33
|
+
envd_version: str
|
|
34
|
+
envd_access_token: str
|
|
35
|
+
traffic_access_token: Optional[str]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def handle_api_exception(
|
|
39
|
+
e: Response,
|
|
40
|
+
default_exception_class: type[Exception] = SandboxException,
|
|
41
|
+
stack_trace: Optional[TracebackType] = None,
|
|
42
|
+
):
|
|
43
|
+
try:
|
|
44
|
+
body = json.loads(e.content) if e.content else {}
|
|
45
|
+
except json.JSONDecodeError:
|
|
46
|
+
body = {}
|
|
47
|
+
|
|
48
|
+
if e.status_code == 401:
|
|
49
|
+
message = f"{e.status_code}: Unauthorized, please check your credentials."
|
|
50
|
+
if body.get("message"):
|
|
51
|
+
message += f" - {body['message']}"
|
|
52
|
+
return AuthenticationException(message)
|
|
53
|
+
|
|
54
|
+
if e.status_code == 429:
|
|
55
|
+
message = f"{e.status_code}: Rate limit exceeded, please try again later."
|
|
56
|
+
if body.get("message"):
|
|
57
|
+
message += f" - {body['message']}"
|
|
58
|
+
return RateLimitException(message)
|
|
59
|
+
|
|
60
|
+
if "message" in body:
|
|
61
|
+
return default_exception_class(
|
|
62
|
+
f"{e.status_code}: {body['message']}"
|
|
63
|
+
).with_traceback(stack_trace)
|
|
64
|
+
return default_exception_class(f"{e.status_code}: {e.content}").with_traceback(
|
|
65
|
+
stack_trace
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class ApiClient(AuthenticatedClient):
|
|
70
|
+
"""
|
|
71
|
+
The client for interacting with the Moru API.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
def __init__(
|
|
75
|
+
self,
|
|
76
|
+
config: ConnectionConfig,
|
|
77
|
+
require_api_key: bool = True,
|
|
78
|
+
require_access_token: bool = False,
|
|
79
|
+
transport: Optional[Union[BaseTransport, AsyncBaseTransport]] = None,
|
|
80
|
+
*args,
|
|
81
|
+
**kwargs,
|
|
82
|
+
):
|
|
83
|
+
if require_api_key and require_access_token:
|
|
84
|
+
raise AuthenticationException(
|
|
85
|
+
"Only one of api_key or access_token can be required, not both",
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
if not require_api_key and not require_access_token:
|
|
89
|
+
raise AuthenticationException(
|
|
90
|
+
"Either api_key or access_token is required",
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
token = None
|
|
94
|
+
if require_api_key:
|
|
95
|
+
if config.api_key is None:
|
|
96
|
+
raise AuthenticationException(
|
|
97
|
+
"API key is required. "
|
|
98
|
+
"You can either set the environment variable `MORU_API_KEY` "
|
|
99
|
+
'or you can pass it directly to the method like api_key="..."',
|
|
100
|
+
)
|
|
101
|
+
token = config.api_key
|
|
102
|
+
|
|
103
|
+
if require_access_token:
|
|
104
|
+
if config.access_token is None:
|
|
105
|
+
raise AuthenticationException(
|
|
106
|
+
"Access token is required. "
|
|
107
|
+
"You can set the environment variable `MORU_ACCESS_TOKEN` or pass the `access_token` in options.",
|
|
108
|
+
)
|
|
109
|
+
token = config.access_token
|
|
110
|
+
|
|
111
|
+
auth_header_name = "X-API-KEY" if require_api_key else "Authorization"
|
|
112
|
+
prefix = "" if require_api_key else "Bearer"
|
|
113
|
+
|
|
114
|
+
headers = {
|
|
115
|
+
**default_headers,
|
|
116
|
+
**(config.headers or {}),
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
# Prevent passing these parameters twice
|
|
120
|
+
more_headers: Optional[dict] = kwargs.pop("headers", None)
|
|
121
|
+
if more_headers:
|
|
122
|
+
headers.update(more_headers)
|
|
123
|
+
kwargs.pop("token", None)
|
|
124
|
+
kwargs.pop("auth_header_name", None)
|
|
125
|
+
kwargs.pop("prefix", None)
|
|
126
|
+
|
|
127
|
+
super().__init__(
|
|
128
|
+
base_url=config.api_url,
|
|
129
|
+
httpx_args={
|
|
130
|
+
"event_hooks": {
|
|
131
|
+
"request": [self._log_request],
|
|
132
|
+
"response": [self._log_response],
|
|
133
|
+
},
|
|
134
|
+
"proxy": config.proxy,
|
|
135
|
+
"transport": transport,
|
|
136
|
+
},
|
|
137
|
+
headers=headers,
|
|
138
|
+
token=token,
|
|
139
|
+
auth_header_name=auth_header_name,
|
|
140
|
+
prefix=prefix,
|
|
141
|
+
*args,
|
|
142
|
+
**kwargs,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
def _log_request(self, request):
|
|
146
|
+
logger.info(f"Request {request.method} {request.url}")
|
|
147
|
+
|
|
148
|
+
def _log_response(self, response: Response):
|
|
149
|
+
if response.status_code >= 400:
|
|
150
|
+
logger.error(f"Response {response.status_code}")
|
|
151
|
+
else:
|
|
152
|
+
logger.info(f"Response {response.status_code}")
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
# We need to override the logging hooks for the async usage
|
|
156
|
+
class AsyncApiClient(ApiClient):
|
|
157
|
+
async def _log_request(self, request):
|
|
158
|
+
logger.info(f"Request {request.method} {request.url}")
|
|
159
|
+
|
|
160
|
+
async def _log_response(self, response: Response):
|
|
161
|
+
if response.status_code >= 400:
|
|
162
|
+
logger.error(f"Response {response.status_code}")
|
|
163
|
+
else:
|
|
164
|
+
logger.info(f"Response {response.status_code}")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Contains methods for accessing the API"""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Contains endpoint functions for accessing the API"""
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
from http import HTTPStatus
|
|
2
|
+
from typing import Any, Optional, Union, cast
|
|
3
|
+
|
|
4
|
+
import httpx
|
|
5
|
+
|
|
6
|
+
from ... import errors
|
|
7
|
+
from ...client import AuthenticatedClient, Client
|
|
8
|
+
from ...models.error import Error
|
|
9
|
+
from ...types import Response
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _get_kwargs(
|
|
13
|
+
sandbox_id: str,
|
|
14
|
+
) -> dict[str, Any]:
|
|
15
|
+
_kwargs: dict[str, Any] = {
|
|
16
|
+
"method": "delete",
|
|
17
|
+
"url": f"/sandboxes/{sandbox_id}",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return _kwargs
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _parse_response(
|
|
24
|
+
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
|
25
|
+
) -> Optional[Union[Any, Error]]:
|
|
26
|
+
if response.status_code == 204:
|
|
27
|
+
response_204 = cast(Any, None)
|
|
28
|
+
return response_204
|
|
29
|
+
if response.status_code == 401:
|
|
30
|
+
response_401 = Error.from_dict(response.json())
|
|
31
|
+
|
|
32
|
+
return response_401
|
|
33
|
+
if response.status_code == 404:
|
|
34
|
+
response_404 = Error.from_dict(response.json())
|
|
35
|
+
|
|
36
|
+
return response_404
|
|
37
|
+
if response.status_code == 500:
|
|
38
|
+
response_500 = Error.from_dict(response.json())
|
|
39
|
+
|
|
40
|
+
return response_500
|
|
41
|
+
if client.raise_on_unexpected_status:
|
|
42
|
+
raise errors.UnexpectedStatus(response.status_code, response.content)
|
|
43
|
+
else:
|
|
44
|
+
return None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _build_response(
|
|
48
|
+
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
|
49
|
+
) -> Response[Union[Any, Error]]:
|
|
50
|
+
return Response(
|
|
51
|
+
status_code=HTTPStatus(response.status_code),
|
|
52
|
+
content=response.content,
|
|
53
|
+
headers=response.headers,
|
|
54
|
+
parsed=_parse_response(client=client, response=response),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def sync_detailed(
|
|
59
|
+
sandbox_id: str,
|
|
60
|
+
*,
|
|
61
|
+
client: AuthenticatedClient,
|
|
62
|
+
) -> Response[Union[Any, Error]]:
|
|
63
|
+
"""Kill a sandbox
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
sandbox_id (str):
|
|
67
|
+
|
|
68
|
+
Raises:
|
|
69
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
70
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
Response[Union[Any, Error]]
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
kwargs = _get_kwargs(
|
|
77
|
+
sandbox_id=sandbox_id,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
response = client.get_httpx_client().request(
|
|
81
|
+
**kwargs,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
return _build_response(client=client, response=response)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def sync(
|
|
88
|
+
sandbox_id: str,
|
|
89
|
+
*,
|
|
90
|
+
client: AuthenticatedClient,
|
|
91
|
+
) -> Optional[Union[Any, Error]]:
|
|
92
|
+
"""Kill a sandbox
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
sandbox_id (str):
|
|
96
|
+
|
|
97
|
+
Raises:
|
|
98
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
99
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Union[Any, Error]
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
return sync_detailed(
|
|
106
|
+
sandbox_id=sandbox_id,
|
|
107
|
+
client=client,
|
|
108
|
+
).parsed
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
async def asyncio_detailed(
|
|
112
|
+
sandbox_id: str,
|
|
113
|
+
*,
|
|
114
|
+
client: AuthenticatedClient,
|
|
115
|
+
) -> Response[Union[Any, Error]]:
|
|
116
|
+
"""Kill a sandbox
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
sandbox_id (str):
|
|
120
|
+
|
|
121
|
+
Raises:
|
|
122
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
123
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
Response[Union[Any, Error]]
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
kwargs = _get_kwargs(
|
|
130
|
+
sandbox_id=sandbox_id,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
response = await client.get_async_httpx_client().request(**kwargs)
|
|
134
|
+
|
|
135
|
+
return _build_response(client=client, response=response)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
async def asyncio(
|
|
139
|
+
sandbox_id: str,
|
|
140
|
+
*,
|
|
141
|
+
client: AuthenticatedClient,
|
|
142
|
+
) -> Optional[Union[Any, Error]]:
|
|
143
|
+
"""Kill a sandbox
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
sandbox_id (str):
|
|
147
|
+
|
|
148
|
+
Raises:
|
|
149
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
150
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
Union[Any, Error]
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
return (
|
|
157
|
+
await asyncio_detailed(
|
|
158
|
+
sandbox_id=sandbox_id,
|
|
159
|
+
client=client,
|
|
160
|
+
)
|
|
161
|
+
).parsed
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
from http import HTTPStatus
|
|
2
|
+
from typing import Any, Optional, Union
|
|
3
|
+
|
|
4
|
+
import httpx
|
|
5
|
+
|
|
6
|
+
from ... import errors
|
|
7
|
+
from ...client import AuthenticatedClient, Client
|
|
8
|
+
from ...models.error import Error
|
|
9
|
+
from ...models.listed_sandbox import ListedSandbox
|
|
10
|
+
from ...types import UNSET, Response, Unset
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _get_kwargs(
|
|
14
|
+
*,
|
|
15
|
+
metadata: Union[Unset, str] = UNSET,
|
|
16
|
+
) -> dict[str, Any]:
|
|
17
|
+
params: dict[str, Any] = {}
|
|
18
|
+
|
|
19
|
+
params["metadata"] = metadata
|
|
20
|
+
|
|
21
|
+
params = {k: v for k, v in params.items() if v is not UNSET and v is not None}
|
|
22
|
+
|
|
23
|
+
_kwargs: dict[str, Any] = {
|
|
24
|
+
"method": "get",
|
|
25
|
+
"url": "/sandboxes",
|
|
26
|
+
"params": params,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return _kwargs
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _parse_response(
|
|
33
|
+
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
|
34
|
+
) -> Optional[Union[Error, list["ListedSandbox"]]]:
|
|
35
|
+
if response.status_code == 200:
|
|
36
|
+
response_200 = []
|
|
37
|
+
_response_200 = response.json()
|
|
38
|
+
for response_200_item_data in _response_200:
|
|
39
|
+
response_200_item = ListedSandbox.from_dict(response_200_item_data)
|
|
40
|
+
|
|
41
|
+
response_200.append(response_200_item)
|
|
42
|
+
|
|
43
|
+
return response_200
|
|
44
|
+
if response.status_code == 400:
|
|
45
|
+
response_400 = Error.from_dict(response.json())
|
|
46
|
+
|
|
47
|
+
return response_400
|
|
48
|
+
if response.status_code == 401:
|
|
49
|
+
response_401 = Error.from_dict(response.json())
|
|
50
|
+
|
|
51
|
+
return response_401
|
|
52
|
+
if response.status_code == 500:
|
|
53
|
+
response_500 = Error.from_dict(response.json())
|
|
54
|
+
|
|
55
|
+
return response_500
|
|
56
|
+
if client.raise_on_unexpected_status:
|
|
57
|
+
raise errors.UnexpectedStatus(response.status_code, response.content)
|
|
58
|
+
else:
|
|
59
|
+
return None
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _build_response(
|
|
63
|
+
*, client: Union[AuthenticatedClient, Client], response: httpx.Response
|
|
64
|
+
) -> Response[Union[Error, list["ListedSandbox"]]]:
|
|
65
|
+
return Response(
|
|
66
|
+
status_code=HTTPStatus(response.status_code),
|
|
67
|
+
content=response.content,
|
|
68
|
+
headers=response.headers,
|
|
69
|
+
parsed=_parse_response(client=client, response=response),
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def sync_detailed(
|
|
74
|
+
*,
|
|
75
|
+
client: AuthenticatedClient,
|
|
76
|
+
metadata: Union[Unset, str] = UNSET,
|
|
77
|
+
) -> Response[Union[Error, list["ListedSandbox"]]]:
|
|
78
|
+
"""List all running sandboxes
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
metadata (Union[Unset, str]):
|
|
82
|
+
|
|
83
|
+
Raises:
|
|
84
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
85
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
Response[Union[Error, list['ListedSandbox']]]
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
kwargs = _get_kwargs(
|
|
92
|
+
metadata=metadata,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
response = client.get_httpx_client().request(
|
|
96
|
+
**kwargs,
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
return _build_response(client=client, response=response)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def sync(
|
|
103
|
+
*,
|
|
104
|
+
client: AuthenticatedClient,
|
|
105
|
+
metadata: Union[Unset, str] = UNSET,
|
|
106
|
+
) -> Optional[Union[Error, list["ListedSandbox"]]]:
|
|
107
|
+
"""List all running sandboxes
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
metadata (Union[Unset, str]):
|
|
111
|
+
|
|
112
|
+
Raises:
|
|
113
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
114
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
Union[Error, list['ListedSandbox']]
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
return sync_detailed(
|
|
121
|
+
client=client,
|
|
122
|
+
metadata=metadata,
|
|
123
|
+
).parsed
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
async def asyncio_detailed(
|
|
127
|
+
*,
|
|
128
|
+
client: AuthenticatedClient,
|
|
129
|
+
metadata: Union[Unset, str] = UNSET,
|
|
130
|
+
) -> Response[Union[Error, list["ListedSandbox"]]]:
|
|
131
|
+
"""List all running sandboxes
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
metadata (Union[Unset, str]):
|
|
135
|
+
|
|
136
|
+
Raises:
|
|
137
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
138
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
Response[Union[Error, list['ListedSandbox']]]
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
kwargs = _get_kwargs(
|
|
145
|
+
metadata=metadata,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
response = await client.get_async_httpx_client().request(**kwargs)
|
|
149
|
+
|
|
150
|
+
return _build_response(client=client, response=response)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
async def asyncio(
|
|
154
|
+
*,
|
|
155
|
+
client: AuthenticatedClient,
|
|
156
|
+
metadata: Union[Unset, str] = UNSET,
|
|
157
|
+
) -> Optional[Union[Error, list["ListedSandbox"]]]:
|
|
158
|
+
"""List all running sandboxes
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
metadata (Union[Unset, str]):
|
|
162
|
+
|
|
163
|
+
Raises:
|
|
164
|
+
errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
|
|
165
|
+
httpx.TimeoutException: If the request takes longer than Client.timeout.
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
Union[Error, list['ListedSandbox']]
|
|
169
|
+
"""
|
|
170
|
+
|
|
171
|
+
return (
|
|
172
|
+
await asyncio_detailed(
|
|
173
|
+
client=client,
|
|
174
|
+
metadata=metadata,
|
|
175
|
+
)
|
|
176
|
+
).parsed
|