abox-sdk 0.1.0__tar.gz

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.
Files changed (195) hide show
  1. abox_sdk-0.1.0/LICENSE +10 -0
  2. abox_sdk-0.1.0/NOTICE +1 -0
  3. abox_sdk-0.1.0/PKG-INFO +57 -0
  4. abox_sdk-0.1.0/README.md +30 -0
  5. abox_sdk-0.1.0/agentbox/__init__.py +96 -0
  6. abox_sdk-0.1.0/agentbox/api/__init__.py +274 -0
  7. abox_sdk-0.1.0/agentbox/api/client/__init__.py +8 -0
  8. abox_sdk-0.1.0/agentbox/api/client/api/__init__.py +1 -0
  9. abox_sdk-0.1.0/agentbox/api/client/api/sandboxes/__init__.py +1 -0
  10. abox_sdk-0.1.0/agentbox/api/client/api/sandboxes/delete_sandboxes_sandbox_id.py +169 -0
  11. abox_sdk-0.1.0/agentbox/api/client/api/sandboxes/get_sandboxes_metrics.py +181 -0
  12. abox_sdk-0.1.0/agentbox/api/client/api/sandboxes/get_sandboxes_sandbox_id.py +171 -0
  13. abox_sdk-0.1.0/agentbox/api/client/api/sandboxes/get_sandboxes_sandbox_id_metrics.py +220 -0
  14. abox_sdk-0.1.0/agentbox/api/client/api/sandboxes/get_v2_sandboxes.py +238 -0
  15. abox_sdk-0.1.0/agentbox/api/client/api/sandboxes/get_v_2_sandboxes_sandbox_id_logs.py +277 -0
  16. abox_sdk-0.1.0/agentbox/api/client/api/sandboxes/post_sandboxes.py +180 -0
  17. abox_sdk-0.1.0/agentbox/api/client/api/sandboxes/post_sandboxes_sandbox_id_connect.py +201 -0
  18. abox_sdk-0.1.0/agentbox/api/client/api/sandboxes/post_sandboxes_sandbox_id_fork.py +218 -0
  19. abox_sdk-0.1.0/agentbox/api/client/api/sandboxes/post_sandboxes_sandbox_id_pause.py +195 -0
  20. abox_sdk-0.1.0/agentbox/api/client/api/sandboxes/post_sandboxes_sandbox_id_refreshes.py +187 -0
  21. abox_sdk-0.1.0/agentbox/api/client/api/sandboxes/post_sandboxes_sandbox_id_snapshots.py +201 -0
  22. abox_sdk-0.1.0/agentbox/api/client/api/sandboxes/post_sandboxes_sandbox_id_timeout.py +199 -0
  23. abox_sdk-0.1.0/agentbox/api/client/api/sandboxes/put_sandboxes_sandbox_id_network.py +207 -0
  24. abox_sdk-0.1.0/agentbox/api/client/api/snapshots/__init__.py +1 -0
  25. abox_sdk-0.1.0/agentbox/api/client/api/snapshots/get_snapshots.py +225 -0
  26. abox_sdk-0.1.0/agentbox/api/client/api/tags/__init__.py +1 -0
  27. abox_sdk-0.1.0/agentbox/api/client/api/tags/delete_templates_tags.py +182 -0
  28. abox_sdk-0.1.0/agentbox/api/client/api/tags/get_templates_template_id_tags.py +180 -0
  29. abox_sdk-0.1.0/agentbox/api/client/api/tags/post_templates_tags.py +184 -0
  30. abox_sdk-0.1.0/agentbox/api/client/api/templates/__init__.py +1 -0
  31. abox_sdk-0.1.0/agentbox/api/client/api/templates/delete_templates_template_id.py +165 -0
  32. abox_sdk-0.1.0/agentbox/api/client/api/templates/get_templates_aliases_alias.py +175 -0
  33. abox_sdk-0.1.0/agentbox/api/client/api/templates/get_templates_template_id.py +203 -0
  34. abox_sdk-0.1.0/agentbox/api/client/api/templates/get_templates_template_id_builds_build_id_logs.py +295 -0
  35. abox_sdk-0.1.0/agentbox/api/client/api/templates/get_templates_template_id_builds_build_id_status.py +240 -0
  36. abox_sdk-0.1.0/agentbox/api/client/api/templates/get_templates_template_id_files_hash.py +188 -0
  37. abox_sdk-0.1.0/agentbox/api/client/api/templates/get_v2_templates.py +218 -0
  38. abox_sdk-0.1.0/agentbox/api/client/api/templates/patch_v_2_templates_template_id.py +193 -0
  39. abox_sdk-0.1.0/agentbox/api/client/api/templates/post_v3_templates.py +184 -0
  40. abox_sdk-0.1.0/agentbox/api/client/api/templates/post_v_2_templates_template_id_builds_build_id.py +200 -0
  41. abox_sdk-0.1.0/agentbox/api/client/client.py +286 -0
  42. abox_sdk-0.1.0/agentbox/api/client/errors.py +16 -0
  43. abox_sdk-0.1.0/agentbox/api/client/models/__init__.py +175 -0
  44. abox_sdk-0.1.0/agentbox/api/client/models/admin_build_cancel_result.py +67 -0
  45. abox_sdk-0.1.0/agentbox/api/client/models/admin_sandbox_kill_result.py +67 -0
  46. abox_sdk-0.1.0/agentbox/api/client/models/assign_template_tags_request.py +67 -0
  47. abox_sdk-0.1.0/agentbox/api/client/models/assigned_template_tags.py +68 -0
  48. abox_sdk-0.1.0/agentbox/api/client/models/aws_registry.py +85 -0
  49. abox_sdk-0.1.0/agentbox/api/client/models/aws_registry_type.py +8 -0
  50. abox_sdk-0.1.0/agentbox/api/client/models/build_log_entry.py +98 -0
  51. abox_sdk-0.1.0/agentbox/api/client/models/build_status_reason.py +95 -0
  52. abox_sdk-0.1.0/agentbox/api/client/models/connect_sandbox.py +59 -0
  53. abox_sdk-0.1.0/agentbox/api/client/models/created_team_api_key.py +166 -0
  54. abox_sdk-0.1.0/agentbox/api/client/models/delete_template_tags_request.py +67 -0
  55. abox_sdk-0.1.0/agentbox/api/client/models/disk_metrics.py +91 -0
  56. abox_sdk-0.1.0/agentbox/api/client/models/error.py +67 -0
  57. abox_sdk-0.1.0/agentbox/api/client/models/gcp_registry.py +69 -0
  58. abox_sdk-0.1.0/agentbox/api/client/models/gcp_registry_type.py +8 -0
  59. abox_sdk-0.1.0/agentbox/api/client/models/general_registry.py +77 -0
  60. abox_sdk-0.1.0/agentbox/api/client/models/general_registry_type.py +8 -0
  61. abox_sdk-0.1.0/agentbox/api/client/models/identifier_masking_details.py +83 -0
  62. abox_sdk-0.1.0/agentbox/api/client/models/listed_sandbox.py +146 -0
  63. abox_sdk-0.1.0/agentbox/api/client/models/log_level.py +11 -0
  64. abox_sdk-0.1.0/agentbox/api/client/models/logs_direction.py +9 -0
  65. abox_sdk-0.1.0/agentbox/api/client/models/logs_source.py +9 -0
  66. abox_sdk-0.1.0/agentbox/api/client/models/machine_info.py +83 -0
  67. abox_sdk-0.1.0/agentbox/api/client/models/max_team_metric.py +68 -0
  68. abox_sdk-0.1.0/agentbox/api/client/models/mcp_type_0.py +44 -0
  69. abox_sdk-0.1.0/agentbox/api/client/models/new_sandbox.py +222 -0
  70. abox_sdk-0.1.0/agentbox/api/client/models/new_team_api_key.py +59 -0
  71. abox_sdk-0.1.0/agentbox/api/client/models/node.py +170 -0
  72. abox_sdk-0.1.0/agentbox/api/client/models/node_detail.py +162 -0
  73. abox_sdk-0.1.0/agentbox/api/client/models/node_metrics.py +154 -0
  74. abox_sdk-0.1.0/agentbox/api/client/models/node_status.py +12 -0
  75. abox_sdk-0.1.0/agentbox/api/client/models/node_status_change.py +82 -0
  76. abox_sdk-0.1.0/agentbox/api/client/models/resumed_sandbox.py +59 -0
  77. abox_sdk-0.1.0/agentbox/api/client/models/sandbox.py +137 -0
  78. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_auto_resume_config.py +60 -0
  79. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_detail.py +238 -0
  80. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_fork_request.py +70 -0
  81. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_fork_result.py +92 -0
  82. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_iam.py +73 -0
  83. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_iam_token.py +67 -0
  84. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_iam_tokens.py +59 -0
  85. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_lifecycle.py +70 -0
  86. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_log.py +70 -0
  87. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_log_entry.py +103 -0
  88. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_log_entry_fields.py +44 -0
  89. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_logs.py +91 -0
  90. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_logs_v2_response.py +84 -0
  91. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_metric.py +116 -0
  92. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_network_config.py +118 -0
  93. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_network_config_rules.py +72 -0
  94. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_network_rule.py +74 -0
  95. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_network_transform.py +79 -0
  96. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_network_transform_headers.py +47 -0
  97. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_network_update_config.py +114 -0
  98. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_network_update_config_rules.py +71 -0
  99. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_on_timeout.py +9 -0
  100. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_pause_request.py +62 -0
  101. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_refresh_request.py +59 -0
  102. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_snapshot_request.py +60 -0
  103. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_state.py +9 -0
  104. abox_sdk-0.1.0/agentbox/api/client/models/sandbox_timeout_request.py +59 -0
  105. abox_sdk-0.1.0/agentbox/api/client/models/sandboxes_with_metrics.py +59 -0
  106. abox_sdk-0.1.0/agentbox/api/client/models/snapshot_info.py +70 -0
  107. abox_sdk-0.1.0/agentbox/api/client/models/team.py +83 -0
  108. abox_sdk-0.1.0/agentbox/api/client/models/team_api_key.py +158 -0
  109. abox_sdk-0.1.0/agentbox/api/client/models/team_metric.py +76 -0
  110. abox_sdk-0.1.0/agentbox/api/client/models/team_user.py +60 -0
  111. abox_sdk-0.1.0/agentbox/api/client/models/template.py +217 -0
  112. abox_sdk-0.1.0/agentbox/api/client/models/template_alias_response.py +67 -0
  113. abox_sdk-0.1.0/agentbox/api/client/models/template_build.py +139 -0
  114. abox_sdk-0.1.0/agentbox/api/client/models/template_build_file_upload.py +70 -0
  115. abox_sdk-0.1.0/agentbox/api/client/models/template_build_info.py +126 -0
  116. abox_sdk-0.1.0/agentbox/api/client/models/template_build_logs_response.py +101 -0
  117. abox_sdk-0.1.0/agentbox/api/client/models/template_build_request.py +115 -0
  118. abox_sdk-0.1.0/agentbox/api/client/models/template_build_request_v2.py +79 -0
  119. abox_sdk-0.1.0/agentbox/api/client/models/template_build_request_v3.py +89 -0
  120. abox_sdk-0.1.0/agentbox/api/client/models/template_build_start_v2.py +184 -0
  121. abox_sdk-0.1.0/agentbox/api/client/models/template_build_status.py +11 -0
  122. abox_sdk-0.1.0/agentbox/api/client/models/template_request_response_v3.py +91 -0
  123. abox_sdk-0.1.0/agentbox/api/client/models/template_step.py +91 -0
  124. abox_sdk-0.1.0/agentbox/api/client/models/template_tag.py +78 -0
  125. abox_sdk-0.1.0/agentbox/api/client/models/template_update_request.py +59 -0
  126. abox_sdk-0.1.0/agentbox/api/client/models/template_update_response.py +59 -0
  127. abox_sdk-0.1.0/agentbox/api/client/models/template_with_builds.py +148 -0
  128. abox_sdk-0.1.0/agentbox/api/client/models/update_team_api_key.py +59 -0
  129. abox_sdk-0.1.0/agentbox/api/client/py.typed +1 -0
  130. abox_sdk-0.1.0/agentbox/api/client/types.py +54 -0
  131. abox_sdk-0.1.0/agentbox/api/client_async/__init__.py +192 -0
  132. abox_sdk-0.1.0/agentbox/api/client_sync/__init__.py +191 -0
  133. abox_sdk-0.1.0/agentbox/api/metadata.py +14 -0
  134. abox_sdk-0.1.0/agentbox/client.py +72 -0
  135. abox_sdk-0.1.0/agentbox/connection_config.py +370 -0
  136. abox_sdk-0.1.0/agentbox/envd/__init__.py +1 -0
  137. abox_sdk-0.1.0/agentbox/envd/api.py +169 -0
  138. abox_sdk-0.1.0/agentbox/envd/client_async/__init__.py +143 -0
  139. abox_sdk-0.1.0/agentbox/envd/client_shared.py +143 -0
  140. abox_sdk-0.1.0/agentbox/envd/client_sync/__init__.py +93 -0
  141. abox_sdk-0.1.0/agentbox/envd/filesystem/__init__.py +1 -0
  142. abox_sdk-0.1.0/agentbox/envd/filesystem/filesystem_connect.py +668 -0
  143. abox_sdk-0.1.0/agentbox/envd/filesystem/filesystem_pb.py +843 -0
  144. abox_sdk-0.1.0/agentbox/envd/interceptors.py +227 -0
  145. abox_sdk-0.1.0/agentbox/envd/process/__init__.py +1 -0
  146. abox_sdk-0.1.0/agentbox/envd/process/process_connect.py +603 -0
  147. abox_sdk-0.1.0/agentbox/envd/process/process_pb.py +938 -0
  148. abox_sdk-0.1.0/agentbox/envd/rpc.py +147 -0
  149. abox_sdk-0.1.0/agentbox/envd/utils.py +57 -0
  150. abox_sdk-0.1.0/agentbox/envd/versions.py +11 -0
  151. abox_sdk-0.1.0/agentbox/exceptions.py +97 -0
  152. abox_sdk-0.1.0/agentbox/io_utils.py +57 -0
  153. abox_sdk-0.1.0/agentbox/paginator.py +52 -0
  154. abox_sdk-0.1.0/agentbox/py.typed +0 -0
  155. abox_sdk-0.1.0/agentbox/sandbox/commands/command_handle.py +69 -0
  156. abox_sdk-0.1.0/agentbox/sandbox/commands/main.py +39 -0
  157. abox_sdk-0.1.0/agentbox/sandbox/filesystem/filesystem.py +378 -0
  158. abox_sdk-0.1.0/agentbox/sandbox/filesystem/watch_handle.py +70 -0
  159. abox_sdk-0.1.0/agentbox/sandbox/iam.py +93 -0
  160. abox_sdk-0.1.0/agentbox/sandbox/main.py +232 -0
  161. abox_sdk-0.1.0/agentbox/sandbox/mcp.py +2530 -0
  162. abox_sdk-0.1.0/agentbox/sandbox/network.py +8 -0
  163. abox_sdk-0.1.0/agentbox/sandbox/sandbox_api.py +935 -0
  164. abox_sdk-0.1.0/agentbox/sandbox/signature.py +47 -0
  165. abox_sdk-0.1.0/agentbox/sandbox/utils.py +34 -0
  166. abox_sdk-0.1.0/agentbox/sandbox_async/commands/command.py +406 -0
  167. abox_sdk-0.1.0/agentbox/sandbox_async/commands/command_handle.py +307 -0
  168. abox_sdk-0.1.0/agentbox/sandbox_async/commands/pty.py +259 -0
  169. abox_sdk-0.1.0/agentbox/sandbox_async/filesystem/filesystem.py +760 -0
  170. abox_sdk-0.1.0/agentbox/sandbox_async/filesystem/watch_handle.py +100 -0
  171. abox_sdk-0.1.0/agentbox/sandbox_async/main.py +1131 -0
  172. abox_sdk-0.1.0/agentbox/sandbox_async/paginator.py +141 -0
  173. abox_sdk-0.1.0/agentbox/sandbox_async/sandbox_api.py +568 -0
  174. abox_sdk-0.1.0/agentbox/sandbox_async/utils.py +7 -0
  175. abox_sdk-0.1.0/agentbox/sandbox_domains.py +5 -0
  176. abox_sdk-0.1.0/agentbox/sandbox_sync/commands/command.py +390 -0
  177. abox_sdk-0.1.0/agentbox/sandbox_sync/commands/command_handle.py +249 -0
  178. abox_sdk-0.1.0/agentbox/sandbox_sync/commands/pty.py +245 -0
  179. abox_sdk-0.1.0/agentbox/sandbox_sync/filesystem/filesystem.py +698 -0
  180. abox_sdk-0.1.0/agentbox/sandbox_sync/filesystem/watch_handle.py +103 -0
  181. abox_sdk-0.1.0/agentbox/sandbox_sync/main.py +1127 -0
  182. abox_sdk-0.1.0/agentbox/sandbox_sync/paginator.py +141 -0
  183. abox_sdk-0.1.0/agentbox/sandbox_sync/sandbox_api.py +555 -0
  184. abox_sdk-0.1.0/agentbox/template/consts.py +33 -0
  185. abox_sdk-0.1.0/agentbox/template/dockerfile_parser.py +286 -0
  186. abox_sdk-0.1.0/agentbox/template/logger.py +232 -0
  187. abox_sdk-0.1.0/agentbox/template/main.py +1318 -0
  188. abox_sdk-0.1.0/agentbox/template/readycmd.py +144 -0
  189. abox_sdk-0.1.0/agentbox/template/types.py +189 -0
  190. abox_sdk-0.1.0/agentbox/template/utils.py +429 -0
  191. abox_sdk-0.1.0/agentbox/template_async/build_api.py +435 -0
  192. abox_sdk-0.1.0/agentbox/template_async/main.py +509 -0
  193. abox_sdk-0.1.0/agentbox/template_sync/build_api.py +425 -0
  194. abox_sdk-0.1.0/agentbox/template_sync/main.py +511 -0
  195. abox_sdk-0.1.0/pyproject.toml +65 -0
abox_sdk-0.1.0/LICENSE ADDED
@@ -0,0 +1,10 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 FOUNDRYLABS, INC.
4
+ Copyright (c) 2026 RetailDriver LLC
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
7
+
8
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9
+
10
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
abox_sdk-0.1.0/NOTICE ADDED
@@ -0,0 +1 @@
1
+ This package is part of AgentBox SDK. It contains software derived from the E2B SDK by FOUNDRYLABS, INC. at commit 5a56c87e9db0e221b138662805af7743e75f1082. See https://github.com/abox-dev/sdk/blob/main/UPSTREAM.md.
@@ -0,0 +1,57 @@
1
+ Metadata-Version: 2.4
2
+ Name: abox-sdk
3
+ Version: 0.1.0
4
+ Summary: AgentBox SDK for secure cloud sandboxes
5
+ Author: RetailDriver LLC
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ License-File: NOTICE
9
+ Requires-Dist: python-dateutil>=2.8.2
10
+ Requires-Dist: wcmatch>=10.1,<12
11
+ Requires-Dist: protobuf-py>=0.1.1,<0.2
12
+ Requires-Dist: httpx>=0.27.0,<1.0.0
13
+ Requires-Dist: h2>=4.4.1,<5
14
+ Requires-Dist: attrs>=23.2.0
15
+ Requires-Dist: packaging>=24.1
16
+ Requires-Dist: typing-extensions>=4.10.0
17
+ Requires-Dist: dockerfile-parse>=2.0.1,<3
18
+ Requires-Dist: rich>=14.0.0
19
+ Requires-Dist: connectrpc>=0.11.1,<0.12
20
+ Requires-Dist: pyqwest>=0.10.0,<0.11
21
+ Requires-Python: >=3.10
22
+ Project-URL: Homepage, https://docs.agentbox.ru/en/sdk/
23
+ Project-URL: Documentation, https://docs.agentbox.ru/en/sdk/api-reference/python/
24
+ Project-URL: Repository, https://github.com/abox-dev/sdk/tree/main/packages/python-sdk
25
+ Project-URL: Bug Tracker, https://github.com/abox-dev/sdk/issues
26
+ Description-Content-Type: text/markdown
27
+
28
+ <p align="center"><img src="https://raw.githubusercontent.com/abox-dev/sdk/main/readme-assets/agentbox-logo-email.png" alt="AgentBox" width="240"></p>
29
+
30
+ # `abox-sdk`
31
+
32
+ The official Python SDK for AgentBox sandboxes and templates. The distribution is named `abox-sdk`; the Python package is `agentbox`.
33
+
34
+ ```bash
35
+ pip install abox-sdk
36
+ ```
37
+
38
+ Create an API key using the [API key guide](https://docs.agentbox.ru/en/quickstart/api-key/) and set `AGENTBOX_API_KEY`.
39
+
40
+ ```python
41
+ from agentbox import Sandbox
42
+
43
+ with Sandbox.create() as sandbox:
44
+ result = sandbox.commands.run('echo "Hello from AgentBox"')
45
+ print(result.stdout)
46
+ ```
47
+
48
+ Async and explicitly configured clients are supported:
49
+
50
+ ```python
51
+ from agentbox import AgentBox
52
+
53
+ client = AgentBox(api_key="ab_...")
54
+ sandbox = await client.AsyncSandbox.create()
55
+ ```
56
+
57
+ Documentation: [core SDK](https://docs.agentbox.ru/en/sdk/), [sandboxes](https://docs.agentbox.ru/en/sdk/sandboxes/), [commands](https://docs.agentbox.ru/en/sdk/commands/), [files](https://docs.agentbox.ru/en/sdk/files/), [templates](https://docs.agentbox.ru/en/sdk/templates/), and [API reference](https://docs.agentbox.ru/en/sdk/api-reference/python/).
@@ -0,0 +1,30 @@
1
+ <p align="center"><img src="https://raw.githubusercontent.com/abox-dev/sdk/main/readme-assets/agentbox-logo-email.png" alt="AgentBox" width="240"></p>
2
+
3
+ # `abox-sdk`
4
+
5
+ The official Python SDK for AgentBox sandboxes and templates. The distribution is named `abox-sdk`; the Python package is `agentbox`.
6
+
7
+ ```bash
8
+ pip install abox-sdk
9
+ ```
10
+
11
+ Create an API key using the [API key guide](https://docs.agentbox.ru/en/quickstart/api-key/) and set `AGENTBOX_API_KEY`.
12
+
13
+ ```python
14
+ from agentbox import Sandbox
15
+
16
+ with Sandbox.create() as sandbox:
17
+ result = sandbox.commands.run('echo "Hello from AgentBox"')
18
+ print(result.stdout)
19
+ ```
20
+
21
+ Async and explicitly configured clients are supported:
22
+
23
+ ```python
24
+ from agentbox import AgentBox
25
+
26
+ client = AgentBox(api_key="ab_...")
27
+ sandbox = await client.AsyncSandbox.create()
28
+ ```
29
+
30
+ Documentation: [core SDK](https://docs.agentbox.ru/en/sdk/), [sandboxes](https://docs.agentbox.ru/en/sdk/sandboxes/), [commands](https://docs.agentbox.ru/en/sdk/commands/), [files](https://docs.agentbox.ru/en/sdk/files/), [templates](https://docs.agentbox.ru/en/sdk/templates/), and [API reference](https://docs.agentbox.ru/en/sdk/api-reference/python/).
@@ -0,0 +1,96 @@
1
+ """AgentBox SDK for secure cloud sandboxes."""
2
+
3
+ from .api import ApiClient, client
4
+ from .client import AgentBox, AgentBoxClientParams
5
+ from .connection_config import ApiParams, ConnectionConfig, ProxyTypes, Username
6
+ from .exceptions import (
7
+ AuthenticationException,
8
+ BuildException,
9
+ FileNotFoundException,
10
+ FileUploadException,
11
+ InvalidArgumentException,
12
+ NotEnoughSpaceException,
13
+ RateLimitException,
14
+ SandboxException,
15
+ SandboxNotFoundException,
16
+ TemplateException,
17
+ TimeoutException,
18
+ )
19
+ from .sandbox.commands.command_handle import (
20
+ CommandExitException,
21
+ CommandResult,
22
+ PtyOutput,
23
+ PtySize,
24
+ Stderr,
25
+ Stdout,
26
+ )
27
+ from .sandbox.commands.main import ProcessInfo
28
+ from .sandbox.filesystem.filesystem import EntryInfo, FileType, WriteInfo
29
+ from .sandbox.filesystem.watch_handle import FilesystemEvent, FilesystemEventType
30
+ from .sandbox.network import ALL_TRAFFIC
31
+ from .sandbox.sandbox_api import (
32
+ GitHubMcpServer,
33
+ GitHubMcpServerConfig,
34
+ McpServer,
35
+ SandboxIamOpts,
36
+ SandboxIamToken,
37
+ SandboxIamTokenType,
38
+ SandboxInfo,
39
+ SandboxInfoLifecycle,
40
+ SandboxLifecycle,
41
+ SandboxMetrics,
42
+ SandboxNetworkInfo,
43
+ SandboxNetworkOpts,
44
+ SandboxNetworkRule,
45
+ SandboxNetworkRuleInfo,
46
+ SandboxNetworkRules,
47
+ SandboxNetworkSelector,
48
+ SandboxNetworkSelectorContext,
49
+ SandboxNetworkTransform,
50
+ SandboxNetworkTransformContext,
51
+ SandboxNetworkTransformResolver,
52
+ SandboxNetworkUpdate,
53
+ SandboxOnTimeout,
54
+ SandboxQuery,
55
+ SandboxState,
56
+ SnapshotInfo,
57
+ )
58
+ from .sandbox.signature import get_signature
59
+ from .sandbox_async.commands.command_handle import AsyncCommandHandle
60
+ from .sandbox_async.filesystem.watch_handle import AsyncWatchHandle
61
+ from .sandbox_async.main import AsyncSandbox
62
+ from .sandbox_async.paginator import AsyncSandboxPaginator, AsyncSnapshotPaginator
63
+ from .sandbox_async.utils import OutputHandler
64
+ from .sandbox_sync.commands.command_handle import CommandHandle
65
+ from .sandbox_sync.filesystem.watch_handle import WatchHandle
66
+ from .sandbox_sync.main import Sandbox
67
+ from .sandbox_sync.paginator import SandboxPaginator, SnapshotPaginator
68
+ from .template.logger import (
69
+ LogEntry,
70
+ LogEntryEnd,
71
+ LogEntryLevel,
72
+ LogEntryStart,
73
+ default_build_logger,
74
+ )
75
+ from .template.main import TemplateBase, TemplateClass
76
+ from .template.readycmd import (
77
+ ReadyCmd,
78
+ wait_for_file,
79
+ wait_for_port,
80
+ wait_for_process,
81
+ wait_for_timeout,
82
+ wait_for_url,
83
+ )
84
+ from .template.types import (
85
+ BuildInfo,
86
+ BuildStatusReason,
87
+ CopyItem,
88
+ TemplateBuildStatus,
89
+ TemplateBuildStatusResponse,
90
+ TemplateTag,
91
+ TemplateTagInfo,
92
+ )
93
+ from .template_async.main import AsyncTemplate
94
+ from .template_sync.main import Template
95
+
96
+ __all__ = [name for name in globals() if not name.startswith("_")]
@@ -0,0 +1,274 @@
1
+ import json
2
+ import logging
3
+ import os
4
+ from dataclasses import dataclass
5
+ from types import TracebackType
6
+ from typing import NamedTuple, Optional, Protocol, Tuple, Union
7
+ from urllib.parse import quote
8
+
9
+ import httpx
10
+ from httpx import AsyncBaseTransport, BaseTransport, Timeout
11
+ from pyqwest import Proxy
12
+
13
+ from agentbox.api.client.client import AuthenticatedClient
14
+ from agentbox.api.client.types import Response
15
+ from agentbox.api.metadata import default_headers
16
+ from agentbox.connection_config import ConnectionConfig, ProxyTypes
17
+ from agentbox.exceptions import (
18
+ AuthenticationException,
19
+ InvalidArgumentException,
20
+ RateLimitException,
21
+ SandboxException,
22
+ )
23
+
24
+
25
+ def encode_path_param(value: str) -> str:
26
+ """
27
+ Percent-encode a template ID, name, or alias for use as one URL path segment.
28
+
29
+ Endpoints that take a template ID also accept a name, which may be
30
+ namespaced (``namespace/name``) and carry a ``:tag``. Escaping those
31
+ separators keeps the value inside a single segment instead of splitting the
32
+ route, matching the JS SDK's ``encodeURIComponent``.
33
+ """
34
+ return quote(value, safe="")
35
+
36
+
37
+ def make_logging_event_hooks(log: Optional[logging.Logger]) -> dict:
38
+ """Build synchronous httpx ``event_hooks`` that log requests and responses
39
+ to the given ``logging.Logger``. Requests log at ``INFO``, successful
40
+ responses at ``INFO`` and responses with status >= 400 at ``ERROR``.
41
+
42
+ Returns no hooks when ``log`` is ``None`` so that nothing is logged unless a
43
+ logger was explicitly supplied."""
44
+ if log is None:
45
+ return {}
46
+
47
+ def on_request(request) -> None:
48
+ log.info(f"Request {request.method} {request.url}")
49
+
50
+ def on_response(response: Response) -> None:
51
+ if response.status_code >= 400:
52
+ log.error(f"Response {response.status_code}")
53
+ else:
54
+ log.info(f"Response {response.status_code}")
55
+
56
+ return {"request": [on_request], "response": [on_response]}
57
+
58
+
59
+ def make_async_logging_event_hooks(log: Optional[logging.Logger]) -> dict:
60
+ """Asynchronous counterpart of :func:`make_logging_event_hooks`."""
61
+ if log is None:
62
+ return {}
63
+
64
+ async def on_request(request) -> None:
65
+ log.info(f"Request {request.method} {request.url}")
66
+
67
+ async def on_response(response: Response) -> None:
68
+ if response.status_code >= 400:
69
+ log.error(f"Response {response.status_code}")
70
+ else:
71
+ log.info(f"Response {response.status_code}")
72
+
73
+ return {"request": [on_request], "response": [on_response]}
74
+
75
+
76
+ connection_retries = int(os.getenv("AGENTBOX_CONNECTION_RETRIES") or "3")
77
+
78
+ # Pool tuning for the pyqwest transports, shared by the REST API, envd RPC,
79
+ # and envd HTTP API stacks. `pool_max_idle_per_host` is per host rather than
80
+ # the global idle cap the httpx transports took, which suits both: API traffic
81
+ # goes to a single host and each sandbox is its own host. `AGENTBOX_MAX_CONNECTIONS`
82
+ # has no counterpart left — reqwest does not cap concurrent connections — so it
83
+ # is no longer read.
84
+ pool_idle_timeout = float(os.getenv("AGENTBOX_KEEPALIVE_EXPIRY") or "300")
85
+ pool_max_idle_per_host = int(os.getenv("AGENTBOX_MAX_KEEPALIVE_CONNECTIONS") or "20")
86
+
87
+
88
+ class ProxyConfig(NamedTuple):
89
+ """The ``proxy`` connection option in the shape pyqwest transports take.
90
+
91
+ A tuple so it can key the transport caches directly: it is hashable and
92
+ compares by value, where a ``pyqwest.Proxy`` compares by identity and
93
+ would hand every call its own connection pool."""
94
+
95
+ url: str
96
+ auth: Optional[Tuple[str, str]] = None
97
+ headers: Tuple[Tuple[str, str], ...] = ()
98
+
99
+ def to_pyqwest(self) -> Proxy:
100
+ """The ``pyqwest.Proxy`` to hand a transport."""
101
+ return Proxy(self.url, auth=self.auth, headers=self.headers or None)
102
+
103
+
104
+ def proxy_to_config(proxy: Optional[ProxyTypes]) -> Optional[ProxyConfig]:
105
+ """Convert the ``proxy`` connection option — a URL string, an
106
+ ``httpx.URL``, or an ``httpx.Proxy`` — to the proxy configuration pyqwest
107
+ transports take: a proxy URL (scheme http, https, socks5, or socks5h,
108
+ credentials allowed in the userinfo), basic-auth credentials, and headers
109
+ to send to the proxy. An ``httpx.Proxy`` ``ssl_context`` has no pyqwest
110
+ counterpart and is rejected rather than silently dropped."""
111
+ if proxy is None:
112
+ return None
113
+ if isinstance(proxy, str):
114
+ return ProxyConfig(proxy)
115
+ if isinstance(proxy, httpx.URL):
116
+ return ProxyConfig(str(proxy))
117
+ if isinstance(proxy, httpx.Proxy):
118
+ if proxy.ssl_context is not None:
119
+ raise InvalidArgumentException("httpx.Proxy ssl_context is not supported")
120
+ # httpx.Proxy splits userinfo out of the URL into `.auth`; pyqwest
121
+ # takes the credentials the same way, so they pass straight through.
122
+ return ProxyConfig(
123
+ str(proxy.url),
124
+ auth=proxy.auth,
125
+ headers=tuple(proxy.headers.items()),
126
+ )
127
+ raise InvalidArgumentException(
128
+ "Only URL-string, httpx.URL, and httpx.Proxy proxies are supported, "
129
+ 'e.g. proxy="http://user:pass@localhost:8030"'
130
+ )
131
+
132
+
133
+ @dataclass
134
+ class SandboxCreateResponse:
135
+ sandbox_id: str
136
+ sandbox_domain: Optional[str]
137
+ envd_version: str
138
+ envd_access_token: Optional[str]
139
+ traffic_access_token: Optional[str]
140
+
141
+
142
+ def api_exception_from_code(
143
+ status_code: int,
144
+ message: Optional[str] = None,
145
+ default_exception_class: type[Exception] = SandboxException,
146
+ stack_trace: Optional[TracebackType] = None,
147
+ ) -> Exception:
148
+ """Map an API error code and message to the matching exception class — the
149
+ same mapping :func:`handle_api_exception` applies to HTTP responses, usable
150
+ for error objects embedded in response bodies (e.g. per-fork results)."""
151
+ if status_code == 401:
152
+ text = f"{status_code}: Unauthorized, please check your credentials."
153
+ if message:
154
+ text += f" - {message}"
155
+ return AuthenticationException(text)
156
+
157
+ if status_code == 429:
158
+ text = f"{status_code}: Rate limit exceeded, please try again later."
159
+ if message:
160
+ text += f" - {message}"
161
+ return RateLimitException(text)
162
+
163
+ return default_exception_class(f"{status_code}: {message}").with_traceback(
164
+ stack_trace
165
+ )
166
+
167
+
168
+ def handle_api_exception(
169
+ e: "SupportsApiErrorResponse",
170
+ default_exception_class: type[Exception] = SandboxException,
171
+ stack_trace: Optional[TracebackType] = None,
172
+ ):
173
+ try:
174
+ body = json.loads(e.content) if e.content else {}
175
+ except json.JSONDecodeError:
176
+ body = {}
177
+
178
+ message = body["message"] if "message" in body else None
179
+ if message is None and e.status_code not in (401, 429):
180
+ return default_exception_class(f"{e.status_code}: {e.content}").with_traceback(
181
+ stack_trace
182
+ )
183
+
184
+ return api_exception_from_code(
185
+ e.status_code, message, default_exception_class, stack_trace
186
+ )
187
+
188
+
189
+ class SupportsApiErrorResponse(Protocol):
190
+ @property
191
+ def status_code(self) -> int: ...
192
+
193
+ @property
194
+ def content(self) -> Union[str, bytes]: ...
195
+
196
+
197
+ class ApiClient(AuthenticatedClient):
198
+ """
199
+ The client for interacting with the AgentBox API.
200
+
201
+ A single lazily-created httpx client (see the generated
202
+ ``AuthenticatedClient``) serves all threads and event loops: the pyqwest
203
+ transports it delegates to are thread-safe and loop-independent, and
204
+ ``httpx.Client`` is documented thread-safe.
205
+ """
206
+
207
+ def __init__(
208
+ self,
209
+ config: ConnectionConfig,
210
+ transport: Optional[Union[BaseTransport, AsyncBaseTransport]] = None,
211
+ *args,
212
+ **kwargs,
213
+ ):
214
+ self._proxy = config.proxy
215
+
216
+ if config.api_key is None:
217
+ raise AuthenticationException(
218
+ "AgentBox API key is required. See https://docs.agentbox.ru/en/quickstart/api-key/ for setup instructions. "
219
+ "You can either set the environment variable `AGENTBOX_API_KEY` "
220
+ 'or pass it directly to the method like api_key="ab_...".',
221
+ )
222
+
223
+ token = config.api_key
224
+ auth_header_name = "X-API-KEY"
225
+ prefix = ""
226
+
227
+ self._logger = config.logger
228
+
229
+ headers = {
230
+ **default_headers,
231
+ **(config.headers or {}),
232
+ }
233
+
234
+ # Prevent passing these parameters twice
235
+ more_headers: Optional[dict] = kwargs.pop("headers", None)
236
+ if more_headers:
237
+ headers.update(more_headers)
238
+ kwargs.pop("token", None)
239
+ kwargs.pop("auth_header_name", None)
240
+ kwargs.pop("prefix", None)
241
+
242
+ httpx_args = {
243
+ "event_hooks": self._logging_event_hooks(),
244
+ }
245
+ if transport is not None:
246
+ # The proxy lives in the transport; passing `proxy` here too
247
+ # would mount a fresh, never-closed proxy transport per client.
248
+ httpx_args["transport"] = transport
249
+ else:
250
+ httpx_args["proxy"] = config.proxy
251
+
252
+ # config.request_timeout is None when the timeout is explicitly
253
+ # disabled (request_timeout=0), which httpx.Timeout(None) preserves.
254
+ kwargs.setdefault("timeout", Timeout(config.request_timeout))
255
+
256
+ super().__init__(
257
+ base_url=config.api_url,
258
+ httpx_args=httpx_args,
259
+ headers=headers,
260
+ token=token or "",
261
+ auth_header_name=auth_header_name,
262
+ prefix=prefix,
263
+ *args,
264
+ **kwargs,
265
+ )
266
+
267
+ def _logging_event_hooks(self) -> dict:
268
+ return make_logging_event_hooks(self._logger)
269
+
270
+
271
+ # We need to override the logging hooks for the async usage
272
+ class AsyncApiClient(ApiClient):
273
+ def _logging_event_hooks(self) -> dict:
274
+ return make_async_logging_event_hooks(self._logger)
@@ -0,0 +1,8 @@
1
+ """A client library for accessing AgentBox API"""
2
+
3
+ from .client import AuthenticatedClient, Client
4
+
5
+ __all__ = (
6
+ "AuthenticatedClient",
7
+ "Client",
8
+ )
@@ -0,0 +1 @@
1
+ """Contains methods for accessing the API"""
@@ -0,0 +1 @@
1
+ """Contains endpoint functions for accessing the API"""
@@ -0,0 +1,169 @@
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: Union[AuthenticatedClient, Client],
62
+ ) -> Response[Union[Any, Error]]:
63
+ """Kill sandbox
64
+
65
+ Kill a sandbox
66
+
67
+ Args:
68
+ sandbox_id (str):
69
+
70
+ Raises:
71
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
72
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
73
+
74
+ Returns:
75
+ Response[Union[Any, Error]]
76
+ """
77
+
78
+ kwargs = _get_kwargs(
79
+ sandbox_id=sandbox_id,
80
+ )
81
+
82
+ response = client.get_httpx_client().request(
83
+ **kwargs,
84
+ )
85
+
86
+ return _build_response(client=client, response=response)
87
+
88
+
89
+ def sync(
90
+ sandbox_id: str,
91
+ *,
92
+ client: Union[AuthenticatedClient, Client],
93
+ ) -> Optional[Union[Any, Error]]:
94
+ """Kill sandbox
95
+
96
+ Kill a sandbox
97
+
98
+ Args:
99
+ sandbox_id (str):
100
+
101
+ Raises:
102
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
103
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
104
+
105
+ Returns:
106
+ Union[Any, Error]
107
+ """
108
+
109
+ return sync_detailed(
110
+ sandbox_id=sandbox_id,
111
+ client=client,
112
+ ).parsed
113
+
114
+
115
+ async def asyncio_detailed(
116
+ sandbox_id: str,
117
+ *,
118
+ client: Union[AuthenticatedClient, Client],
119
+ ) -> Response[Union[Any, Error]]:
120
+ """Kill sandbox
121
+
122
+ Kill a sandbox
123
+
124
+ Args:
125
+ sandbox_id (str):
126
+
127
+ Raises:
128
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
129
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
130
+
131
+ Returns:
132
+ Response[Union[Any, Error]]
133
+ """
134
+
135
+ kwargs = _get_kwargs(
136
+ sandbox_id=sandbox_id,
137
+ )
138
+
139
+ response = await client.get_async_httpx_client().request(**kwargs)
140
+
141
+ return _build_response(client=client, response=response)
142
+
143
+
144
+ async def asyncio(
145
+ sandbox_id: str,
146
+ *,
147
+ client: Union[AuthenticatedClient, Client],
148
+ ) -> Optional[Union[Any, Error]]:
149
+ """Kill sandbox
150
+
151
+ Kill a sandbox
152
+
153
+ Args:
154
+ sandbox_id (str):
155
+
156
+ Raises:
157
+ errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True.
158
+ httpx.TimeoutException: If the request takes longer than Client.timeout.
159
+
160
+ Returns:
161
+ Union[Any, Error]
162
+ """
163
+
164
+ return (
165
+ await asyncio_detailed(
166
+ sandbox_id=sandbox_id,
167
+ client=client,
168
+ )
169
+ ).parsed