withruntime 0.8.1__tar.gz → 0.8.2__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 (183) hide show
  1. {withruntime-0.8.1 → withruntime-0.8.2}/PKG-INFO +9 -6
  2. {withruntime-0.8.1 → withruntime-0.8.2}/README.md +8 -5
  3. {withruntime-0.8.1 → withruntime-0.8.2}/pyproject.toml +1 -1
  4. withruntime-0.8.2/tests/test_files_upload_parallel.py +76 -0
  5. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_client.py +9 -3
  6. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_client.py +9 -3
  7. withruntime-0.8.2/withruntime/_version.py +1 -0
  8. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/inspect_ai.py +2 -1
  9. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime.egg-info/PKG-INFO +9 -6
  10. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime.egg-info/SOURCES.txt +1 -0
  11. withruntime-0.8.1/withruntime/_version.py +0 -1
  12. {withruntime-0.8.1 → withruntime-0.8.2}/LICENSE +0 -0
  13. {withruntime-0.8.1 → withruntime-0.8.2}/setup.cfg +0 -0
  14. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_account_errors.py +0 -0
  15. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_async_stream_cleanup.py +0 -0
  16. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_audit.py +0 -0
  17. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_billing.py +0 -0
  18. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_blaxel.py +0 -0
  19. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_capacity_wait.py +0 -0
  20. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_client.py +0 -0
  21. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_daytona.py +0 -0
  22. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_deepagents.py +0 -0
  23. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_e2b_code_interpreter.py +0 -0
  24. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_e2b_sandbox.py +0 -0
  25. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_eval_sandbox.py +0 -0
  26. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_exec_stream.py +0 -0
  27. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_files_download.py +0 -0
  28. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_files_mode.py +0 -0
  29. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_harbor.py +0 -0
  30. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_http_tls_close.py +0 -0
  31. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_identity_token.py +0 -0
  32. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_images_v2.py +0 -0
  33. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_images_volumes_interpreter.py +0 -0
  34. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_inspect_ai.py +0 -0
  35. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_late_answer.py +0 -0
  36. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_lifecycle_settings.py +0 -0
  37. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_limits.py +0 -0
  38. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_mounts.py +0 -0
  39. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_network_funding.py +0 -0
  40. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_network_products.py +0 -0
  41. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_observability.py +0 -0
  42. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_openai_agents.py +0 -0
  43. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_previews_network_desktop.py +0 -0
  44. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_proxy.py +0 -0
  45. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_referrals.py +0 -0
  46. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_secrets.py +0 -0
  47. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_snapshot_after_fork.py +0 -0
  48. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_sso.py +0 -0
  49. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_stream_exit_close.py +0 -0
  50. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_switching.py +0 -0
  51. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_tools.py +0 -0
  52. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_unpack.py +0 -0
  53. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_vercel.py +0 -0
  54. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_volume_backups.py +0 -0
  55. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_wake_awake.py +0 -0
  56. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_wallet.py +0 -0
  57. {withruntime-0.8.1 → withruntime-0.8.2}/tests/test_watch.py +0 -0
  58. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/__init__.py +0 -0
  59. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/__init__.py +0 -0
  60. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/audit.py +0 -0
  61. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/billing.py +0 -0
  62. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/desktop.py +0 -0
  63. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/images.py +0 -0
  64. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/interpreter.py +0 -0
  65. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/limits.py +0 -0
  66. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/mcp.py +0 -0
  67. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/mounts.py +0 -0
  68. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/network.py +0 -0
  69. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/network_products.py +0 -0
  70. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/observability.py +0 -0
  71. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/previews.py +0 -0
  72. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/referrals.py +0 -0
  73. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/secrets.py +0 -0
  74. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/sso.py +0 -0
  75. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/switching.py +0 -0
  76. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/volumes.py +0 -0
  77. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_async_products/watch.py +0 -0
  78. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_clock.py +0 -0
  79. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_connection.py +0 -0
  80. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_errors.py +0 -0
  81. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_eval_sandbox.py +0 -0
  82. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_http.py +0 -0
  83. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_proxy.py +0 -0
  84. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/__init__.py +0 -0
  85. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/audit.py +0 -0
  86. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/billing.py +0 -0
  87. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/desktop.py +0 -0
  88. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/images.py +0 -0
  89. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/interpreter.py +0 -0
  90. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/limits.py +0 -0
  91. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/mcp.py +0 -0
  92. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/mounts.py +0 -0
  93. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/network.py +0 -0
  94. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/network_products.py +0 -0
  95. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/observability.py +0 -0
  96. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/previews.py +0 -0
  97. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/referrals.py +0 -0
  98. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/secrets.py +0 -0
  99. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/sso.py +0 -0
  100. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/switching.py +0 -0
  101. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/volumes.py +0 -0
  102. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_sync_products/watch.py +0 -0
  103. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_tunnel.py +0 -0
  104. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_unpack.py +0 -0
  105. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/_ws.py +0 -0
  106. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/__init__.py +0 -0
  107. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/_async_io.py +0 -0
  108. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/_async_sandbox.py +0 -0
  109. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/_core.py +0 -0
  110. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/_sync_io.py +0 -0
  111. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/_sync_sandbox.py +0 -0
  112. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/__init__.py +0 -0
  113. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/agents.py +0 -0
  114. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/__init__.py +0 -0
  115. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/api/__init__.py +0 -0
  116. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/api/applications/__init__.py +0 -0
  117. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/api/applications/list_application_revisions.py +0 -0
  118. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/api/compute/__init__.py +0 -0
  119. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/api/compute/get_sandbox.py +0 -0
  120. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/api/compute/update_sandbox.py +0 -0
  121. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/api/functions/__init__.py +0 -0
  122. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/api/functions/create_function.py +0 -0
  123. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/api/images.py +0 -0
  124. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/api/workspaces.py +0 -0
  125. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/client.py +0 -0
  126. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/models/__init__.py +0 -0
  127. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/models/create_job_execution_request.py +0 -0
  128. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/models/create_job_execution_request_env.py +0 -0
  129. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/models/env.py +0 -0
  130. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/models/function.py +0 -0
  131. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/models/function_runtime.py +0 -0
  132. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/models/function_spec.py +0 -0
  133. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/models/metadata.py +0 -0
  134. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/models/workspace.py +0 -0
  135. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/client/types.py +0 -0
  136. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/common.py +0 -0
  137. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/drive.py +0 -0
  138. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/jobs.py +0 -0
  139. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/sandbox/__init__.py +0 -0
  140. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/core/sandbox/types.py +0 -0
  141. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/crewai.py +0 -0
  142. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/googleadk.py +0 -0
  143. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/langgraph.py +0 -0
  144. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/livekit.py +0 -0
  145. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/llamaindex.py +0 -0
  146. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/openai.py +0 -0
  147. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/pydantic.py +0 -0
  148. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/blaxel/telemetry.py +0 -0
  149. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/daytona/__init__.py +0 -0
  150. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/daytona/_async_daytona.py +0 -0
  151. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/daytona/_async_io.py +0 -0
  152. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/daytona/_core.py +0 -0
  153. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/daytona/_sync_daytona.py +0 -0
  154. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/daytona/_sync_io.py +0 -0
  155. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/deepagents.py +0 -0
  156. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/e2b/__init__.py +0 -0
  157. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/e2b/_async_io.py +0 -0
  158. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/e2b/_async_sandbox.py +0 -0
  159. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/e2b/_core.py +0 -0
  160. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/e2b/_sync_io.py +0 -0
  161. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/e2b/_sync_sandbox.py +0 -0
  162. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/e2b/code_interpreter/__init__.py +0 -0
  163. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/e2b/code_interpreter/_async_ci.py +0 -0
  164. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/e2b/code_interpreter/_models.py +0 -0
  165. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/e2b/code_interpreter/_sync_ci.py +0 -0
  166. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/harbor.py +0 -0
  167. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/openai_agents.py +0 -0
  168. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/tools.py +0 -0
  169. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/vercel/__init__.py +0 -0
  170. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/vercel/_async_io.py +0 -0
  171. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/vercel/_async_sandbox.py +0 -0
  172. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/vercel/_core.py +0 -0
  173. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/vercel/_sync_io.py +0 -0
  174. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/vercel/_sync_sandbox.py +0 -0
  175. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/vercel/api.py +0 -0
  176. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/vercel/sandbox/__init__.py +0 -0
  177. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/vercel/sandbox/sync.py +0 -0
  178. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/wallet.py +0 -0
  179. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime/webhooks.py +0 -0
  180. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime.egg-info/dependency_links.txt +0 -0
  181. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime.egg-info/entry_points.txt +0 -0
  182. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime.egg-info/requires.txt +0 -0
  183. {withruntime-0.8.1 → withruntime-0.8.2}/withruntime.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: withruntime
3
- Version: 0.8.1
3
+ Version: 0.8.2
4
4
  Summary: Runtime Cloud: one client (sync and async) for every Runtime product. Sandboxes first.
5
5
  License: Apache-2.0
6
6
  Project-URL: Homepage, https://withruntime.com
@@ -73,7 +73,10 @@ list, glob, stat, move, remove, upload and download directories), `pause`,
73
73
  `wake`, `extend`, `update`, `keep_alive`, `fork` and `snapshot`, and the
74
74
  `interpreter`, `network`, `previews` and `desktop` products. A paused sandbox
75
75
  also wakes by itself on the next call, and `Sandbox.get_or_create(name)` returns
76
- the sandbox with that name or creates it. The client has `sandboxes`, `images`,
76
+ the sandbox with that name or creates it. A sandbox pauses itself after 60 seconds
77
+ with nothing happening in it, keeping its memory and processes, so an
78
+ idle sandbox costs no compute; `idle_pause_seconds` sets 10 to 86,400, or 0 for
79
+ never. The client has `sandboxes`, `images`,
77
80
  `volumes`, `snapshots`, `limits`, `feedback` and `support`;
78
81
  `runtime.limits.get()` (0.3.1 and later) says whether the key is read-only and
79
82
  what its agent may still spend today. Every write carries an
@@ -159,8 +162,8 @@ How it maps:
159
162
  (every `/` becomes `-`; the tag is `latest` when none is given), so the
160
163
  code keeps Blaxel's image string. A missing one raises `NotSupportedError`
161
164
  with the build command, for example `npx withruntime image build
162
- --dockerfile Dockerfile --name my-company-agent-image -t
163
- my-company-agent-image:latest`. Volumes mount Runtime volumes of the same
165
+ --dockerfile Dockerfile --name my-company-agent-image -t
166
+ my-company-agent-image:latest`. Volumes mount Runtime volumes of the same
164
167
  name. On the free trial a sandbox has at most 4096 MB of memory (2 vCPUs).
165
168
  - **Standby.** A sandbox pauses after a minute with no call (Blaxel: about 15
166
169
  seconds). It keeps its memory and processes, and wakes on the next command,
@@ -200,8 +203,8 @@ Differences you can hit:
200
203
  (`/workspace`). File calls act as the sandbox user and fall back to `sudo`
201
204
  where only root may: they reach files a root process made, including private
202
205
  ones, and a file they write is the sandbox user's.
203
- - A sandbox is visible only to the key that created it: another key of the
204
- same account gets 404 for it
206
+ - A key sees the sandboxes it made, and another key's answer 404, unless an
207
+ owner or admin makes the key account-wide, as a Blaxel workspace key is
205
208
  ([teams](https://withruntime.com/docs/teams#keys-in-a-team)).
206
209
  - Public previews need a paid sandbox.
207
210
  - A process's `pid` is Runtime's process id, not an operating-system number.
@@ -50,7 +50,10 @@ list, glob, stat, move, remove, upload and download directories), `pause`,
50
50
  `wake`, `extend`, `update`, `keep_alive`, `fork` and `snapshot`, and the
51
51
  `interpreter`, `network`, `previews` and `desktop` products. A paused sandbox
52
52
  also wakes by itself on the next call, and `Sandbox.get_or_create(name)` returns
53
- the sandbox with that name or creates it. The client has `sandboxes`, `images`,
53
+ the sandbox with that name or creates it. A sandbox pauses itself after 60 seconds
54
+ with nothing happening in it, keeping its memory and processes, so an
55
+ idle sandbox costs no compute; `idle_pause_seconds` sets 10 to 86,400, or 0 for
56
+ never. The client has `sandboxes`, `images`,
54
57
  `volumes`, `snapshots`, `limits`, `feedback` and `support`;
55
58
  `runtime.limits.get()` (0.3.1 and later) says whether the key is read-only and
56
59
  what its agent may still spend today. Every write carries an
@@ -136,8 +139,8 @@ How it maps:
136
139
  (every `/` becomes `-`; the tag is `latest` when none is given), so the
137
140
  code keeps Blaxel's image string. A missing one raises `NotSupportedError`
138
141
  with the build command, for example `npx withruntime image build
139
- --dockerfile Dockerfile --name my-company-agent-image -t
140
- my-company-agent-image:latest`. Volumes mount Runtime volumes of the same
142
+ --dockerfile Dockerfile --name my-company-agent-image -t
143
+ my-company-agent-image:latest`. Volumes mount Runtime volumes of the same
141
144
  name. On the free trial a sandbox has at most 4096 MB of memory (2 vCPUs).
142
145
  - **Standby.** A sandbox pauses after a minute with no call (Blaxel: about 15
143
146
  seconds). It keeps its memory and processes, and wakes on the next command,
@@ -177,8 +180,8 @@ Differences you can hit:
177
180
  (`/workspace`). File calls act as the sandbox user and fall back to `sudo`
178
181
  where only root may: they reach files a root process made, including private
179
182
  ones, and a file they write is the sandbox user's.
180
- - A sandbox is visible only to the key that created it: another key of the
181
- same account gets 404 for it
183
+ - A key sees the sandboxes it made, and another key's answer 404, unless an
184
+ owner or admin makes the key account-wide, as a Blaxel workspace key is
182
185
  ([teams](https://withruntime.com/docs/teams#keys-in-a-team)).
183
186
  - Public previews need a paid sandbox.
184
187
  - A process's `pid` is Runtime's process id, not an operating-system number.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "withruntime"
7
- version = "0.8.1"
7
+ version = "0.8.2"
8
8
  description = "Runtime Cloud: one client (sync and async) for every Runtime product. Sandboxes first."
9
9
  readme = "README.md"
10
10
  license = { text = "Apache-2.0" }
@@ -0,0 +1,76 @@
1
+ """A large write keeps eight chunks in flight, in both client forms.
2
+
3
+ Each chunk's reply waits on the API and the guest, so the link idles while
4
+ every chunk in flight waits: four in flight took 100 MB 17-18 s from a
5
+ 12.6 MB/s home link, eight took 11 s (27 September 2026)."""
6
+ import asyncio
7
+ import threading
8
+ import time
9
+ import unittest
10
+ from withruntime._async_client import AsyncFiles
11
+ from withruntime._sync_client import Files
12
+
13
+ MIB = 1048576
14
+
15
+
16
+ class Counter:
17
+ def __init__(self):
18
+ self.now = self.most = self.chunks = 0
19
+ self.lock = threading.Lock()
20
+
21
+ def enter(self):
22
+ with self.lock:
23
+ self.now += 1
24
+ self.chunks += 1
25
+ self.most = max(self.most, self.now)
26
+
27
+ def leave(self):
28
+ with self.lock:
29
+ self.now -= 1
30
+
31
+
32
+ class Transport:
33
+ def __init__(self):
34
+ self.count = Counter()
35
+
36
+ def json(self, method, path, body):
37
+ return {'uploadId': 'upload', 'chunkBytes': MIB} if path.endswith('/uploads') else {}
38
+
39
+ def send(self, method, path, **kwargs):
40
+ self.count.enter()
41
+ time.sleep(0.02)
42
+ self.count.leave()
43
+ return self
44
+
45
+ def read(self):
46
+ return b''
47
+
48
+
49
+ class AsyncTransport(Transport):
50
+ async def json(self, *args, **kwargs):
51
+ return super().json(*args, **kwargs)
52
+
53
+ async def send(self, method, path, **kwargs):
54
+ self.count.enter()
55
+ await asyncio.sleep(0.02)
56
+ self.count.leave()
57
+ return self
58
+
59
+ async def read(self):
60
+ return b''
61
+
62
+
63
+ class UploadParallel(unittest.TestCase):
64
+ def test_sync_keeps_eight_chunks_in_flight(self):
65
+ transport = Transport()
66
+ Files(transport, 'sandbox').write('/workspace/big.bin', b'x' * (16 * MIB))
67
+ self.assertEqual((transport.count.chunks, transport.count.most), (16, 8))
68
+
69
+ def test_async_keeps_eight_chunks_in_flight(self):
70
+ transport = AsyncTransport()
71
+ asyncio.run(AsyncFiles(transport, 'sandbox').write('/workspace/big.bin', b'x' * (16 * MIB)))
72
+ self.assertEqual((transport.count.chunks, transport.count.most), (16, 8))
73
+
74
+
75
+ if __name__ == '__main__':
76
+ unittest.main()
@@ -31,6 +31,11 @@ from ._async_products.watch import AsyncWatches, AsyncWatchHandle
31
31
 
32
32
  DEFAULT_BASE_URL = "https://api.withruntime.com"
33
33
  CHUNK = 1_048_576
34
+ # Chunks of a large write in flight at once. Each chunk's reply waits on the
35
+ # API and the guest, and the link idles while every chunk in flight waits: from
36
+ # a home link (12.6 MB/s up, 27 September 2026) 100 MB took 17-18 s at four and
37
+ # 11 s at eight, and sixteen was no faster. The TypeScript SDK sends eight too.
38
+ PARALLEL_CHUNKS = 8
34
39
  _KEY_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789_.:-"
35
40
 
36
41
 
@@ -672,7 +677,7 @@ class AsyncFiles:
672
677
  raw=payload[offset:offset + step])
673
678
  await response.read()
674
679
  try:
675
- await parallel(chunk, range(0, len(payload), step), 4)
680
+ await parallel(chunk, range(0, len(payload), step), PARALLEL_CHUNKS)
676
681
  await self._t.json("POST", self._path(f"/uploads/{_enc(upload)}:commit"), body={})
677
682
  if octal and begin.get("mode") != octal: # Older images need chmod after commit.
678
683
  await self._t.json("POST", self._path("/files:chmod"), body={"path": path, "mode": octal})
@@ -990,7 +995,8 @@ class AsyncSandbox:
990
995
  """Changes its settings; what you leave out stays as it is: ``name``,
991
996
  ``labels``, ``auto_wake`` (a request wakes it when paused),
992
997
  ``idle_pause_seconds`` (pause after this long with no activity, counted
993
- from now; 0 never), ``persistent`` (keep it running while credit lasts
998
+ from now; 0 never, otherwise 10 to 86400; a new sandbox has 60),
999
+ ``persistent`` (keep it running while credit lasts
994
1000
  and keep its disk after a stop; paid only) and
995
1001
  ``max_total_cost_micros`` (None removes the cap)."""
996
1002
  return await self._lifecycle("update", False, {_camel(k): v for k, v in settings.items()}, idempotency_key)
@@ -1287,7 +1293,7 @@ class AsyncRuntime:
1287
1293
  and ``takenBack`` (the part of spent that refunds and disputes took);
1288
1294
  ``trial`` is in milliseconds, or None; ``outbound`` is this month's
1289
1295
  outbound traffic in bytes, with ``chargedMicros`` for what went past
1290
- the free 100 GiB."""
1296
+ the month's free ``allowanceBytes``."""
1291
1297
  return await self._t.json("GET", "/v1/usage")
1292
1298
 
1293
1299
  async def request(self, method: str, path: str, **kwargs: Any) -> Any:
@@ -30,6 +30,11 @@ from ._sync_products.watch import Watches, WatchHandle
30
30
 
31
31
  DEFAULT_BASE_URL = "https://api.withruntime.com"
32
32
  CHUNK = 1_048_576
33
+ # Chunks of a large write in flight at once. Each chunk's reply waits on the
34
+ # API and the guest, and the link idles while every chunk in flight waits: from
35
+ # a home link (12.6 MB/s up, 27 September 2026) 100 MB took 17-18 s at four and
36
+ # 11 s at eight, and sixteen was no faster. The TypeScript SDK sends eight too.
37
+ PARALLEL_CHUNKS = 8
33
38
  _KEY_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789_.:-"
34
39
 
35
40
 
@@ -671,7 +676,7 @@ class Files:
671
676
  raw=payload[offset:offset + step])
672
677
  response.read()
673
678
  try:
674
- parallel(chunk, range(0, len(payload), step), 4)
679
+ parallel(chunk, range(0, len(payload), step), PARALLEL_CHUNKS)
675
680
  self._t.json("POST", self._path(f"/uploads/{_enc(upload)}:commit"), body={})
676
681
  if octal and begin.get("mode") != octal: # Older images need chmod after commit.
677
682
  self._t.json("POST", self._path("/files:chmod"), body={"path": path, "mode": octal})
@@ -989,7 +994,8 @@ class Sandbox:
989
994
  """Changes its settings; what you leave out stays as it is: ``name``,
990
995
  ``labels``, ``auto_wake`` (a request wakes it when paused),
991
996
  ``idle_pause_seconds`` (pause after this long with no activity, counted
992
- from now; 0 never), ``persistent`` (keep it running while credit lasts
997
+ from now; 0 never, otherwise 10 to 86400; a new sandbox has 60),
998
+ ``persistent`` (keep it running while credit lasts
993
999
  and keep its disk after a stop; paid only) and
994
1000
  ``max_total_cost_micros`` (None removes the cap)."""
995
1001
  return self._lifecycle("update", False, {_camel(k): v for k, v in settings.items()}, idempotency_key)
@@ -1286,7 +1292,7 @@ class Runtime:
1286
1292
  and ``takenBack`` (the part of spent that refunds and disputes took);
1287
1293
  ``trial`` is in milliseconds, or None; ``outbound`` is this month's
1288
1294
  outbound traffic in bytes, with ``chargedMicros`` for what went past
1289
- the free 100 GiB."""
1295
+ the month's free ``allowanceBytes``."""
1290
1296
  return self._t.json("GET", "/v1/usage")
1291
1297
 
1292
1298
  def request(self, method: str, path: str, **kwargs: Any) -> Any:
@@ -0,0 +1 @@
1
+ VERSION = "0.8.2"
@@ -274,7 +274,8 @@ class RuntimeSandboxEnvironment(SandboxEnvironment):
274
274
 
275
275
  @classmethod
276
276
  def default_concurrency(cls) -> Optional[int]:
277
- # The free trial runs eight sandboxes at once; raise it with --max-sandboxes on a paid account.
277
+ # The free trial's concurrency, which packages/cloud-guide/src/facts.test.ts holds to
278
+ # the API's limit; raise it with --max-sandboxes on a paid account.
278
279
  return 8
279
280
 
280
281
  @classmethod
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: withruntime
3
- Version: 0.8.1
3
+ Version: 0.8.2
4
4
  Summary: Runtime Cloud: one client (sync and async) for every Runtime product. Sandboxes first.
5
5
  License: Apache-2.0
6
6
  Project-URL: Homepage, https://withruntime.com
@@ -73,7 +73,10 @@ list, glob, stat, move, remove, upload and download directories), `pause`,
73
73
  `wake`, `extend`, `update`, `keep_alive`, `fork` and `snapshot`, and the
74
74
  `interpreter`, `network`, `previews` and `desktop` products. A paused sandbox
75
75
  also wakes by itself on the next call, and `Sandbox.get_or_create(name)` returns
76
- the sandbox with that name or creates it. The client has `sandboxes`, `images`,
76
+ the sandbox with that name or creates it. A sandbox pauses itself after 60 seconds
77
+ with nothing happening in it, keeping its memory and processes, so an
78
+ idle sandbox costs no compute; `idle_pause_seconds` sets 10 to 86,400, or 0 for
79
+ never. The client has `sandboxes`, `images`,
77
80
  `volumes`, `snapshots`, `limits`, `feedback` and `support`;
78
81
  `runtime.limits.get()` (0.3.1 and later) says whether the key is read-only and
79
82
  what its agent may still spend today. Every write carries an
@@ -159,8 +162,8 @@ How it maps:
159
162
  (every `/` becomes `-`; the tag is `latest` when none is given), so the
160
163
  code keeps Blaxel's image string. A missing one raises `NotSupportedError`
161
164
  with the build command, for example `npx withruntime image build
162
- --dockerfile Dockerfile --name my-company-agent-image -t
163
- my-company-agent-image:latest`. Volumes mount Runtime volumes of the same
165
+ --dockerfile Dockerfile --name my-company-agent-image -t
166
+ my-company-agent-image:latest`. Volumes mount Runtime volumes of the same
164
167
  name. On the free trial a sandbox has at most 4096 MB of memory (2 vCPUs).
165
168
  - **Standby.** A sandbox pauses after a minute with no call (Blaxel: about 15
166
169
  seconds). It keeps its memory and processes, and wakes on the next command,
@@ -200,8 +203,8 @@ Differences you can hit:
200
203
  (`/workspace`). File calls act as the sandbox user and fall back to `sudo`
201
204
  where only root may: they reach files a root process made, including private
202
205
  ones, and a file they write is the sandbox user's.
203
- - A sandbox is visible only to the key that created it: another key of the
204
- same account gets 404 for it
206
+ - A key sees the sandboxes it made, and another key's answer 404, unless an
207
+ owner or admin makes the key account-wide, as a Blaxel workspace key is
205
208
  ([teams](https://withruntime.com/docs/teams#keys-in-a-team)).
206
209
  - Public previews need a paid sandbox.
207
210
  - A process's `pid` is Runtime's process id, not an operating-system number.
@@ -16,6 +16,7 @@ tests/test_eval_sandbox.py
16
16
  tests/test_exec_stream.py
17
17
  tests/test_files_download.py
18
18
  tests/test_files_mode.py
19
+ tests/test_files_upload_parallel.py
19
20
  tests/test_harbor.py
20
21
  tests/test_http_tls_close.py
21
22
  tests/test_identity_token.py
@@ -1 +0,0 @@
1
- VERSION = "0.8.1"
File without changes
File without changes