runpod 2.1.0__tar.gz → 2.2.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 (388) hide show
  1. {runpod-2.1.0 → runpod-2.2.0}/CHANGELOG.md +27 -0
  2. {runpod-2.1.0/runpod.egg-info → runpod-2.2.0}/PKG-INFO +13 -2
  3. {runpod-2.1.0 → runpod-2.2.0}/README.md +12 -0
  4. {runpod-2.1.0 → runpod-2.2.0}/docs/cli/references/command_line_interface.md +40 -0
  5. {runpod-2.1.0 → runpod-2.2.0}/docs/cli/start_here.md +2 -0
  6. runpod-2.2.0/docs/getting_started.md +34 -0
  7. {runpod-2.1.0 → runpod-2.2.0}/requirements.txt +0 -1
  8. {runpod-2.1.0 → runpod-2.2.0}/runpod/__init__.py +15 -2
  9. runpod-2.2.0/runpod/_hosts.py +54 -0
  10. runpod-2.2.0/runpod/_serialization.py +21 -0
  11. {runpod-2.1.0 → runpod-2.2.0}/runpod/_version.py +3 -3
  12. runpod-2.2.0/runpod/_volume_transfer_utils.py +171 -0
  13. {runpod-2.1.0 → runpod-2.2.0}/runpod/api/graphql.py +2 -1
  14. {runpod-2.1.0 → runpod-2.2.0}/runpod/api/mutations/apps.py +6 -0
  15. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/__init__.py +2 -1
  16. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/api.py +42 -0
  17. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/app.py +11 -1
  18. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/auth.py +2 -3
  19. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/build.py +0 -1
  20. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/context.py +22 -1
  21. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/datacenter.py +16 -0
  22. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/deploy.py +127 -31
  23. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/handles.py +27 -5
  24. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/images.py +3 -5
  25. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/placement.py +8 -4
  26. runpod-2.2.0/runpod/apps/protocol.py +86 -0
  27. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/serialization.py +28 -35
  28. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/spec.py +32 -4
  29. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/stubs.py +31 -2
  30. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/targets.py +121 -59
  31. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/tasks.py +130 -82
  32. runpod-2.2.0/runpod/apps/utils/network.py +65 -0
  33. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/volume.py +96 -2
  34. {runpod-2.1.0 → runpod-2.2.0}/runpod/cli/groups/config/functions.py +46 -18
  35. runpod-2.2.0/runpod/network_volume_transfer.py +981 -0
  36. {runpod-2.1.0 → runpod-2.2.0}/runpod/rp_cli/console.py +9 -9
  37. {runpod-2.1.0 → runpod-2.2.0}/runpod/rp_cli/endpoint.py +2 -1
  38. {runpod-2.1.0 → runpod-2.2.0}/runpod/rp_cli/main.py +19 -7
  39. {runpod-2.1.0 → runpod-2.2.0}/runpod/rp_cli/pod.py +2 -1
  40. runpod-2.2.0/runpod/rp_cli/volume.py +610 -0
  41. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/modules/rp_fastapi.py +13 -4
  42. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/modules/rp_http.py +15 -2
  43. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/modules/rp_job.py +10 -1
  44. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/modules/rp_scale.py +7 -2
  45. {runpod-2.1.0 → runpod-2.2.0/runpod.egg-info}/PKG-INFO +13 -2
  46. {runpod-2.1.0 → runpod-2.2.0}/runpod.egg-info/SOURCES.txt +15 -1
  47. {runpod-2.1.0 → runpod-2.2.0}/runpod.egg-info/requires.txt +0 -1
  48. {runpod-2.1.0 → runpod-2.2.0}/runpod.egg-info/scm_file_list.json +15 -1
  49. runpod-2.2.0/runpod.egg-info/scm_version.json +8 -0
  50. runpod-2.2.0/tests/e2e/test_network_volume_transfer_live.py +74 -0
  51. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_auth.py +5 -0
  52. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_config_params.py +54 -0
  53. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_deploy.py +35 -4
  54. runpod-2.2.0/tests/test_apps/test_deployed_tasks.py +471 -0
  55. runpod-2.2.0/tests/test_apps/test_deployment_validation.py +345 -0
  56. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_dispatch.py +25 -9
  57. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_placement.py +44 -0
  58. runpod-2.2.0/tests/test_apps/test_runtime_call_validation.py +172 -0
  59. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_tasks.py +15 -13
  60. runpod-2.2.0/tests/test_apps/test_transport_parity.py +170 -0
  61. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_volume.py +16 -0
  62. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_console.py +7 -0
  63. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_deploy_command.py +28 -0
  64. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_endpoint_command.py +18 -0
  65. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_management_commands.py +29 -0
  66. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_pod_command.py +8 -0
  67. runpod-2.2.0/tests/test_hosts.py +67 -0
  68. runpod-2.2.0/tests/test_network_volume_transfer.py +2004 -0
  69. runpod-2.2.0/tests/test_profile.py +79 -0
  70. runpod-2.2.0/tests/test_serialization.py +231 -0
  71. runpod-2.2.0/tests/test_serverless/test_refresh_worker.py +640 -0
  72. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_utils/test_rp_volume_cache.py +3 -0
  73. runpod-2.1.0/docs/getting_Started.md +0 -21
  74. runpod-2.1.0/runpod/apps/protocol.py +0 -60
  75. runpod-2.1.0/runpod/apps/utils/network.py +0 -33
  76. runpod-2.1.0/runpod/rp_cli/volume.py +0 -298
  77. runpod-2.1.0/runpod.egg-info/scm_version.json +0 -8
  78. {runpod-2.1.0 → runpod-2.2.0}/.dockerignore +0 -0
  79. {runpod-2.1.0 → runpod-2.2.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  80. {runpod-2.1.0 → runpod-2.2.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  81. {runpod-2.1.0 → runpod-2.2.0}/.github/dependabot.yml +0 -0
  82. {runpod-2.1.0 → runpod-2.2.0}/.github/tape_collection/cli_config.tape +0 -0
  83. {runpod-2.1.0 → runpod-2.2.0}/.github/tape_collection/cli_help.tape +0 -0
  84. {runpod-2.1.0 → runpod-2.2.0}/.github/tape_collection/cli_ssh.tape +0 -0
  85. {runpod-2.1.0 → runpod-2.2.0}/.github/tests.json +0 -0
  86. {runpod-2.1.0 → runpod-2.2.0}/.github/workflows/cd.yml +0 -0
  87. {runpod-2.1.0 → runpod-2.2.0}/.github/workflows/ci.yml +0 -0
  88. {runpod-2.1.0 → runpod-2.2.0}/.github/workflows/vhs.yml +0 -0
  89. {runpod-2.1.0 → runpod-2.2.0}/.gitignore +0 -0
  90. {runpod-2.1.0 → runpod-2.2.0}/ARCHITECTURE.md +0 -0
  91. {runpod-2.1.0 → runpod-2.2.0}/CONTRIBUTING.md +0 -0
  92. {runpod-2.1.0 → runpod-2.2.0}/LICENSE +0 -0
  93. {runpod-2.1.0 → runpod-2.2.0}/MANIFEST.in +0 -0
  94. {runpod-2.1.0 → runpod-2.2.0}/Makefile +0 -0
  95. {runpod-2.1.0 → runpod-2.2.0}/SECURITY.md +0 -0
  96. {runpod-2.1.0 → runpod-2.2.0}/build_tools/compile_gpu_test.sh +0 -0
  97. {runpod-2.1.0 → runpod-2.2.0}/build_tools/gpu_test.c +0 -0
  98. {runpod-2.1.0 → runpod-2.2.0}/docs/api/handling_errors.md +0 -0
  99. {runpod-2.1.0 → runpod-2.2.0}/docs/api/queries.md +0 -0
  100. {runpod-2.1.0 → runpod-2.2.0}/docs/cli/demos/config.gif +0 -0
  101. {runpod-2.1.0 → runpod-2.2.0}/docs/cli/demos/help.gif +0 -0
  102. {runpod-2.1.0 → runpod-2.2.0}/docs/cli/demos/ssh.gif +0 -0
  103. {runpod-2.1.0 → runpod-2.2.0}/docs/cli/references/projects.md +0 -0
  104. {runpod-2.1.0 → runpod-2.2.0}/docs/cli/references/runpod.toml.md +0 -0
  105. {runpod-2.1.0 → runpod-2.2.0}/docs/images/env_var_location.png +0 -0
  106. {runpod-2.1.0 → runpod-2.2.0}/docs/serverless/functions/error_handling.md +0 -0
  107. {runpod-2.1.0 → runpod-2.2.0}/docs/serverless/functions/logging.md +0 -0
  108. {runpod-2.1.0 → runpod-2.2.0}/docs/serverless/gpu_binary_compilation.md +0 -0
  109. {runpod-2.1.0 → runpod-2.2.0}/docs/serverless/local_testing.md +0 -0
  110. {runpod-2.1.0 → runpod-2.2.0}/docs/serverless/utils/rp_cleanup.md +0 -0
  111. {runpod-2.1.0 → runpod-2.2.0}/docs/serverless/utils/rp_debugger.md +0 -0
  112. {runpod-2.1.0 → runpod-2.2.0}/docs/serverless/utils/rp_download.md +0 -0
  113. {runpod-2.1.0 → runpod-2.2.0}/docs/serverless/utils/rp_upload.md +0 -0
  114. {runpod-2.1.0 → runpod-2.2.0}/docs/serverless/utils/rp_validator.md +0 -0
  115. {runpod-2.1.0 → runpod-2.2.0}/docs/serverless/volume_cache.md +0 -0
  116. {runpod-2.1.0 → runpod-2.2.0}/docs/serverless/worker.md +0 -0
  117. {runpod-2.1.0 → runpod-2.2.0}/docs/serverless/worker_fitness_checks.md +0 -0
  118. {runpod-2.1.0 → runpod-2.2.0}/docs/serverless/worker_realtime.md +0 -0
  119. {runpod-2.1.0 → runpod-2.2.0}/examples/api/create_container_registry_auth.py +0 -0
  120. {runpod-2.1.0 → runpod-2.2.0}/examples/api/create_endpoint.py +0 -0
  121. {runpod-2.1.0 → runpod-2.2.0}/examples/api/create_template.py +0 -0
  122. {runpod-2.1.0 → runpod-2.2.0}/examples/api/get_endpoints.py +0 -0
  123. {runpod-2.1.0 → runpod-2.2.0}/examples/apps/README.md +0 -0
  124. {runpod-2.1.0 → runpod-2.2.0}/examples/apps/gpu_inference.py +0 -0
  125. {runpod-2.1.0 → runpod-2.2.0}/examples/apps/hello_world.py +0 -0
  126. {runpod-2.1.0 → runpod-2.2.0}/examples/apps/streaming.py +0 -0
  127. {runpod-2.1.0 → runpod-2.2.0}/examples/apps/train_and_eval.py +0 -0
  128. {runpod-2.1.0 → runpod-2.2.0}/examples/apps/web_service.py +0 -0
  129. {runpod-2.1.0 → runpod-2.2.0}/examples/endpoints/asyncio_job_request.py +0 -0
  130. {runpod-2.1.0 → runpod-2.2.0}/examples/endpoints/health.py +0 -0
  131. {runpod-2.1.0 → runpod-2.2.0}/examples/endpoints/run.py +0 -0
  132. {runpod-2.1.0 → runpod-2.2.0}/examples/endpoints/run_sync.py +0 -0
  133. {runpod-2.1.0 → runpod-2.2.0}/examples/endpoints/streaming.py +0 -0
  134. {runpod-2.1.0 → runpod-2.2.0}/examples/rest_wrapper.py +0 -0
  135. {runpod-2.1.0 → runpod-2.2.0}/examples/serverless/concurrent_handler.py +0 -0
  136. {runpod-2.1.0 → runpod-2.2.0}/examples/serverless/logger.py +0 -0
  137. {runpod-2.1.0 → runpod-2.2.0}/examples/serverless/simple_handler.py +0 -0
  138. {runpod-2.1.0 → runpod-2.2.0}/examples/serverless/volume_cache_handler.py +0 -0
  139. {runpod-2.1.0 → runpod-2.2.0}/pyproject.toml +0 -0
  140. {runpod-2.1.0 → runpod-2.2.0}/pytest.ini +0 -0
  141. {runpod-2.1.0 → runpod-2.2.0}/runpod/_binary_helpers.py +0 -0
  142. {runpod-2.1.0 → runpod-2.2.0}/runpod/_health/__init__.py +0 -0
  143. {runpod-2.1.0 → runpod-2.2.0}/runpod/_health/cuda.py +0 -0
  144. {runpod-2.1.0 → runpod-2.2.0}/runpod/_health/fitness.py +0 -0
  145. {runpod-2.1.0 → runpod-2.2.0}/runpod/_health/gpu.py +0 -0
  146. {runpod-2.1.0 → runpod-2.2.0}/runpod/_health/system.py +0 -0
  147. {runpod-2.1.0 → runpod-2.2.0}/runpod/_logger.py +0 -0
  148. {runpod-2.1.0 → runpod-2.2.0}/runpod/_startup.py +0 -0
  149. {runpod-2.1.0 → runpod-2.2.0}/runpod/agent.py +0 -0
  150. {runpod-2.1.0 → runpod-2.2.0}/runpod/api/__init__.py +0 -0
  151. {runpod-2.1.0 → runpod-2.2.0}/runpod/api/_rate_limit.py +0 -0
  152. {runpod-2.1.0 → runpod-2.2.0}/runpod/api/ctl_commands.py +0 -0
  153. {runpod-2.1.0 → runpod-2.2.0}/runpod/api/mutations/__init__.py +0 -0
  154. {runpod-2.1.0 → runpod-2.2.0}/runpod/api/mutations/container_register_auth.py +0 -0
  155. {runpod-2.1.0 → runpod-2.2.0}/runpod/api/queries/__init__.py +0 -0
  156. {runpod-2.1.0 → runpod-2.2.0}/runpod/api/queries/apps.py +0 -0
  157. {runpod-2.1.0 → runpod-2.2.0}/runpod/api/queries/user.py +0 -0
  158. {runpod-2.1.0 → runpod-2.2.0}/runpod/api/rest.py +0 -0
  159. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/dev.py +0 -0
  160. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/discovery.py +0 -0
  161. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/discovery_state.py +0 -0
  162. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/entrypoint.py +0 -0
  163. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/errors.py +0 -0
  164. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/gpu.py +0 -0
  165. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/init.py +0 -0
  166. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/invoker.py +0 -0
  167. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/job.py +0 -0
  168. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/logs.py +0 -0
  169. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/manage.py +0 -0
  170. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/markers.py +0 -0
  171. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/model.py +0 -0
  172. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/monitor.py +0 -0
  173. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/registry.py +0 -0
  174. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/schedule.py +0 -0
  175. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/secret.py +0 -0
  176. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/shim.py +0 -0
  177. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/utils/__init__.py +0 -0
  178. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/utils/client.py +0 -0
  179. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/utils/events.py +0 -0
  180. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/utils/lookup.py +0 -0
  181. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/utils/names.py +0 -0
  182. {runpod-2.1.0 → runpod-2.2.0}/runpod/apps/watch.py +0 -0
  183. {runpod-2.1.0 → runpod-2.2.0}/runpod/cli/__init__.py +0 -0
  184. {runpod-2.1.0 → runpod-2.2.0}/runpod/cli/entry.py +0 -0
  185. {runpod-2.1.0 → runpod-2.2.0}/runpod/cli/groups/__init__.py +0 -0
  186. {runpod-2.1.0 → runpod-2.2.0}/runpod/cli/groups/config/__init__.py +0 -0
  187. {runpod-2.1.0 → runpod-2.2.0}/runpod/cli/groups/pod/__init__.py +0 -0
  188. {runpod-2.1.0 → runpod-2.2.0}/runpod/cli/groups/pod/commands.py +0 -0
  189. {runpod-2.1.0 → runpod-2.2.0}/runpod/cli/groups/ssh/__init__.py +0 -0
  190. {runpod-2.1.0 → runpod-2.2.0}/runpod/cli/groups/ssh/commands.py +0 -0
  191. {runpod-2.1.0 → runpod-2.2.0}/runpod/cli/groups/ssh/functions.py +0 -0
  192. {runpod-2.1.0 → runpod-2.2.0}/runpod/cli/utils/__init__.py +0 -0
  193. {runpod-2.1.0 → runpod-2.2.0}/runpod/cli/utils/rp_info.py +0 -0
  194. {runpod-2.1.0 → runpod-2.2.0}/runpod/cli/utils/rp_runpodignore.py +0 -0
  195. {runpod-2.1.0 → runpod-2.2.0}/runpod/cli/utils/rp_userspace.py +0 -0
  196. {runpod-2.1.0 → runpod-2.2.0}/runpod/cli/utils/ssh_cmd.py +0 -0
  197. {runpod-2.1.0 → runpod-2.2.0}/runpod/endpoint/__init__.py +0 -0
  198. {runpod-2.1.0 → runpod-2.2.0}/runpod/endpoint/asyncio/__init__.py +0 -0
  199. {runpod-2.1.0 → runpod-2.2.0}/runpod/endpoint/asyncio/asyncio_runner.py +0 -0
  200. {runpod-2.1.0 → runpod-2.2.0}/runpod/endpoint/helpers.py +0 -0
  201. {runpod-2.1.0 → runpod-2.2.0}/runpod/endpoint/runner.py +0 -0
  202. {runpod-2.1.0 → runpod-2.2.0}/runpod/error.py +0 -0
  203. {runpod-2.1.0 → runpod-2.2.0}/runpod/http_client.py +0 -0
  204. {runpod-2.1.0 → runpod-2.2.0}/runpod/rp_cli/__init__.py +0 -0
  205. {runpod-2.1.0 → runpod-2.2.0}/runpod/rp_cli/api.py +0 -0
  206. {runpod-2.1.0 → runpod-2.2.0}/runpod/rp_cli/catalog.py +0 -0
  207. {runpod-2.1.0 → runpod-2.2.0}/runpod/rp_cli/compute.py +0 -0
  208. {runpod-2.1.0 → runpod-2.2.0}/runpod/rp_cli/endpoint_config.py +0 -0
  209. {runpod-2.1.0 → runpod-2.2.0}/runpod/rp_cli/logs.py +0 -0
  210. {runpod-2.1.0 → runpod-2.2.0}/runpod/rp_cli/options.py +0 -0
  211. {runpod-2.1.0 → runpod-2.2.0}/runpod/rp_cli/output.py +0 -0
  212. {runpod-2.1.0 → runpod-2.2.0}/runpod/rp_cli/update.py +0 -0
  213. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/__init__.py +0 -0
  214. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/binaries/README.md +0 -0
  215. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/binaries/__init__.py +0 -0
  216. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/binaries/gpu_test +0 -0
  217. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/modules/__init__.py +0 -0
  218. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/modules/rp_capture.py +0 -0
  219. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/modules/rp_fitness.py +0 -0
  220. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/modules/rp_gpu_fitness.py +0 -0
  221. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/modules/rp_handler.py +0 -0
  222. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/modules/rp_local.py +0 -0
  223. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/modules/rp_logger.py +0 -0
  224. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/modules/rp_ping.py +0 -0
  225. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/modules/rp_prestart.py +0 -0
  226. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/modules/rp_progress.py +0 -0
  227. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/modules/rp_system_fitness.py +0 -0
  228. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/modules/rp_tips.py +0 -0
  229. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/modules/worker_state.py +0 -0
  230. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/utils/__init__.py +0 -0
  231. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/utils/rp_cleanup.py +0 -0
  232. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/utils/rp_cuda.py +0 -0
  233. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/utils/rp_debugger.py +0 -0
  234. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/utils/rp_download.py +0 -0
  235. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/utils/rp_model_cache.py +0 -0
  236. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/utils/rp_ssrf.py +0 -0
  237. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/utils/rp_upload.py +0 -0
  238. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/utils/rp_validator.py +0 -0
  239. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/utils/rp_volume_cache.py +0 -0
  240. {runpod-2.1.0 → runpod-2.2.0}/runpod/serverless/worker.py +0 -0
  241. {runpod-2.1.0 → runpod-2.2.0}/runpod/user_agent.py +0 -0
  242. {runpod-2.1.0 → runpod-2.2.0}/runpod/version.py +0 -0
  243. {runpod-2.1.0 → runpod-2.2.0}/runpod.egg-info/dependency_links.txt +0 -0
  244. {runpod-2.1.0 → runpod-2.2.0}/runpod.egg-info/entry_points.txt +0 -0
  245. {runpod-2.1.0 → runpod-2.2.0}/runpod.egg-info/top_level.txt +0 -0
  246. {runpod-2.1.0 → runpod-2.2.0}/scripts/README.md +0 -0
  247. {runpod-2.1.0 → runpod-2.2.0}/scripts/benchmark_cold_start.sh +0 -0
  248. {runpod-2.1.0 → runpod-2.2.0}/scripts/compare_benchmarks.py +0 -0
  249. {runpod-2.1.0 → runpod-2.2.0}/setup.cfg +0 -0
  250. {runpod-2.1.0 → runpod-2.2.0}/setup.py +0 -0
  251. {runpod-2.1.0 → runpod-2.2.0}/tests/__init__.py +0 -0
  252. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/__init__.py +0 -0
  253. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/apps_live_smoke.py +0 -0
  254. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/conftest.py +0 -0
  255. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/e2e_provisioner.py +0 -0
  256. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/examples/01_hello_world.py +0 -0
  257. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/examples/02_invocation_styles.py +0 -0
  258. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/examples/03_gpu.py +0 -0
  259. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/examples/04_dependencies.py +0 -0
  260. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/examples/05_api_service.py +0 -0
  261. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/examples/06_tasks.py +0 -0
  262. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/examples/07_pipelines.py +0 -0
  263. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/examples/08_volumes.py +0 -0
  264. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/examples/09_secrets.py +0 -0
  265. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/examples/10_cached_models.py +0 -0
  266. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/examples/11_train_eval.py +0 -0
  267. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/examples/12_custom_image.py +0 -0
  268. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/examples/13_streaming.py +0 -0
  269. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/examples/README.md +0 -0
  270. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/examples/run_all.sh +0 -0
  271. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/fixtures/cold_start/handler.py +0 -0
  272. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/fixtures/cold_start/pyproject.toml +0 -0
  273. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/matrix/main.py +0 -0
  274. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/matrix/run.py +0 -0
  275. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/task_pod_smoke.py +0 -0
  276. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/test_cold_start.py +0 -0
  277. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/test_mock_worker.py +0 -0
  278. {runpod-2.1.0 → runpod-2.2.0}/tests/e2e/tests.json +0 -0
  279. {runpod-2.1.0 → runpod-2.2.0}/tests/fixtures/mock_gpu_test +0 -0
  280. {runpod-2.1.0 → runpod-2.2.0}/tests/test_agent.py +0 -0
  281. {runpod-2.1.0 → runpod-2.2.0}/tests/test_api/__init__.py +0 -0
  282. {runpod-2.1.0 → runpod-2.2.0}/tests/test_api/test_ctl_commands.py +0 -0
  283. {runpod-2.1.0 → runpod-2.2.0}/tests/test_api/test_rate_limit.py +0 -0
  284. {runpod-2.1.0 → runpod-2.2.0}/tests/test_api/test_rest.py +0 -0
  285. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/__init__.py +0 -0
  286. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/conftest.py +0 -0
  287. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_agent_auth.py +0 -0
  288. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_api_client.py +0 -0
  289. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_app.py +0 -0
  290. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_build.py +0 -0
  291. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_compat_lock.py +0 -0
  292. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_dev.py +0 -0
  293. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_discovery.py +0 -0
  294. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_gpu_catalog.py +0 -0
  295. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_images.py +0 -0
  296. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_job.py +0 -0
  297. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_logs.py +0 -0
  298. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_manage.py +0 -0
  299. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_markers.py +0 -0
  300. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_model.py +0 -0
  301. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_monitor.py +0 -0
  302. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_registry.py +0 -0
  303. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_retry.py +0 -0
  304. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_secret.py +0 -0
  305. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_shim.py +0 -0
  306. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_targets.py +0 -0
  307. {runpod-2.1.0 → runpod-2.2.0}/tests/test_apps/test_watch.py +0 -0
  308. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/__init__.py +0 -0
  309. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_agent_login.py +0 -0
  310. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_catalog_command.py +0 -0
  311. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_cli_api.py +0 -0
  312. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_cli_groups/__init__.py +0 -0
  313. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_cli_groups/test_config_functions.py +0 -0
  314. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_cli_groups/test_pod_commands.py +0 -0
  315. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_cli_groups/test_ssh_commands.py +0 -0
  316. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_cli_groups/test_ssh_dispatch.py +0 -0
  317. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_cli_groups/test_ssh_functions.py +0 -0
  318. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_cli_logs.py +0 -0
  319. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_cli_options.py +0 -0
  320. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_cli_output.py +0 -0
  321. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_cli_utils/__init__.py +0 -0
  322. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_cli_utils/test_info.py +0 -0
  323. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_cli_utils/test_runpodignore.py +0 -0
  324. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_cli_utils/test_ssh_cmd.py +0 -0
  325. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_cli_utils/test_userspace.py +0 -0
  326. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_compute.py +0 -0
  327. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_init_command.py +0 -0
  328. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_update_command.py +0 -0
  329. {runpod-2.1.0 → runpod-2.2.0}/tests/test_cli/test_volume_command.py +0 -0
  330. {runpod-2.1.0 → runpod-2.2.0}/tests/test_endpoint/__init__.py +0 -0
  331. {runpod-2.1.0 → runpod-2.2.0}/tests/test_endpoint/test_asyncio_init.py +0 -0
  332. {runpod-2.1.0 → runpod-2.2.0}/tests/test_endpoint/test_asyncio_runner.py +0 -0
  333. {runpod-2.1.0 → runpod-2.2.0}/tests/test_endpoint/test_init.py +0 -0
  334. {runpod-2.1.0 → runpod-2.2.0}/tests/test_endpoint/test_runner.py +0 -0
  335. {runpod-2.1.0 → runpod-2.2.0}/tests/test_error.py +0 -0
  336. {runpod-2.1.0 → runpod-2.2.0}/tests/test_init.py +0 -0
  337. {runpod-2.1.0 → runpod-2.2.0}/tests/test_performance/__init__.py +0 -0
  338. {runpod-2.1.0 → runpod-2.2.0}/tests/test_performance/test_cold_start.py +0 -0
  339. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/__init__.py +0 -0
  340. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/local_sim/.env_example +0 -0
  341. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/local_sim/Makefile +0 -0
  342. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/local_sim/localhost.py +0 -0
  343. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/local_sim/worker.py +0 -0
  344. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_capture.py +0 -0
  345. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_init.py +0 -0
  346. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_integration_worker_state.py +0 -0
  347. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/__init__.py +0 -0
  348. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_fastapi.py +0 -0
  349. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_fitness/__init__.py +0 -0
  350. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_fitness/conftest.py +0 -0
  351. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_fitness/test_force_kill.py +0 -0
  352. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_fitness/test_gpu_checks.py +0 -0
  353. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_fitness/test_gpu_integration.py +0 -0
  354. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_fitness/test_registration.py +0 -0
  355. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_fitness/test_safe_startup.py +0 -0
  356. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_fitness/test_startup.py +0 -0
  357. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_fitness/test_system_checks.py +0 -0
  358. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_handler.py +0 -0
  359. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_http.py +0 -0
  360. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_job.py +0 -0
  361. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_local.py +0 -0
  362. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_logger.py +0 -0
  363. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_ping.py +0 -0
  364. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_progress.py +0 -0
  365. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_scale.py +0 -0
  366. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_state.py +0 -0
  367. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_modules/test_tips.py +0 -0
  368. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_prestart.py +0 -0
  369. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_prestart_lifecycle.py +0 -0
  370. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_rp_scale.py +0 -0
  371. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_scale_mirror.py +0 -0
  372. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_utils/__init__.py +0 -0
  373. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_utils/test_cleanup.py +0 -0
  374. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_utils/test_cuda.py +0 -0
  375. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_utils/test_debugger.py +0 -0
  376. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_utils/test_download.py +0 -0
  377. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_utils/test_model_cache.py +0 -0
  378. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_utils/test_ssrf.py +0 -0
  379. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_utils/test_upload.py +0 -0
  380. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_utils/test_validate.py +0 -0
  381. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_utils_init.py +0 -0
  382. {runpod-2.1.0 → runpod-2.2.0}/tests/test_serverless/test_worker.py +0 -0
  383. {runpod-2.1.0 → runpod-2.2.0}/tests/test_shared/__init__.py +0 -0
  384. {runpod-2.1.0 → runpod-2.2.0}/tests/test_shared/test_auth.py +0 -0
  385. {runpod-2.1.0 → runpod-2.2.0}/tests/test_user_agent.py +0 -0
  386. {runpod-2.1.0 → runpod-2.2.0}/tests/test_version.py +0 -0
  387. {runpod-2.1.0 → runpod-2.2.0}/tests/test_whatever.py +0 -0
  388. {runpod-2.1.0 → runpod-2.2.0}/tests/whatever.py +0 -0
@@ -5,6 +5,13 @@
5
5
  ### Features
6
6
 
7
7
  * Apps expose `NetworkVolume` and `GlobalVolume` resources with explicit path-keyed mounts, lazy create-if-missing provisioning, and execution-bound filesystem access. Global volumes use GraphQL for lookup and creation.
8
+ * Deployed Flash calls use endpoint or pod runtime credentials. Release requires deployed support from [RunPod#6686](https://github.com/runpod/RunPod/pull/6686), [ai-api#1176](https://github.com/runpod/ai-api/pull/1176), and [sdk-runtime#4](https://github.com/runpod-workers/sdk-runtime/pull/4).
9
+
10
+ ### Breaking Changes
11
+
12
+ * Production endpoint environment variables reserve `RUNPOD_API_KEY` and runtime identity fields. Workers authenticate Flash calls with platform-issued runtime credentials; application credentials must use non-reserved environment names.
13
+ * Deployed workers can invoke Flash resources only within their own app and environment, including through `Queue`, `Api`, and `Task` stubs. Local clients use account credentials subject to their permissions.
14
+ * Remote queues, tasks, and JSON API calls require finite JSON-compatible arguments and results in local, dev, and deployed execution. Dev workers receive source separately from the JSON argument contract. Explicit `.local()` calls run Python directly.
8
15
 
9
16
  ### Bug Fixes
10
17
 
@@ -15,6 +22,26 @@
15
22
  * Deployment artifacts apply project ignore rules and mandatory secret-file exclusions while preserving vendored dependency assets.
16
23
  * Synchronous calls wait across polling timeouts on Python 3.10 and propagate operation timeouts.
17
24
 
25
+ ## [2.2.0](https://github.com/runpod/runpod-python/compare/v2.1.0...v2.2.0) (2026-11-09)
26
+
27
+
28
+ ### Features
29
+
30
+ * invoke deployed flash tasks with runtime credentials (SEC-375 CON-1833) ([#644](https://github.com/runpod/runpod-python/issues/644)) ([367f174](https://github.com/runpod/runpod-python/commit/367f174ef14cc7fcf909a3b26413c3f2d38cbd9b))
31
+ * make console, proxy, and endpoint hosts configurable ([#684](https://github.com/runpod/runpod-python/issues/684)) ([b9583f7](https://github.com/runpod/runpod-python/commit/b9583f7c0a02e6c0cbb9598538393fc239d88852))
32
+ * resumable network volume upload and download ([#655](https://github.com/runpod/runpod-python/issues/655)) ([a677ee9](https://github.com/runpod/runpod-python/commit/a677ee9f08f21da5a29cc126ed63032fc1063365))
33
+
34
+
35
+ ### Bug Fixes
36
+
37
+ * **apps:** accept datacenter ids outside the built-in list ([#690](https://github.com/runpod/runpod-python/issues/690)) ([dbc251a](https://github.com/runpod/runpod-python/commit/dbc251ac8ba87ed4cc53f71010bc8c87dba1c77d))
38
+ * **serverless:** stop taking jobs after a per-job refresh_worker (SLS-900) ([#663](https://github.com/runpod/runpod-python/issues/663)) ([8ca9d9b](https://github.com/runpod/runpod-python/commit/8ca9d9bcfdc0ad1792e899cdef49a4fd172fbb13))
39
+
40
+
41
+ ### Documentation
42
+
43
+ * rename getting_Started.md to getting_started.md ([#697](https://github.com/runpod/runpod-python/issues/697)) ([fbcabcd](https://github.com/runpod/runpod-python/commit/fbcabcd73889783d8e03b6261154891f13b0d9d6))
44
+
18
45
  ## [2.1.0](https://github.com/runpod/runpod-python/compare/v2.0.0...v2.1.0) (2026-11-03)
19
46
 
20
47
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: runpod
3
- Version: 2.1.0
3
+ Version: 2.2.0
4
4
  Summary: 🐍 | Python library for Runpod API and serverless worker SDK.
5
5
  Home-page: https://runpod.io
6
6
  Author: Runpod
@@ -34,7 +34,6 @@ Requires-Dist: backoff>=2.2.1
34
34
  Requires-Dist: boto3>=1.43.118
35
35
  Requires-Dist: certifi>=2026.10.19
36
36
  Requires-Dist: click>=8.5.0
37
- Requires-Dist: cloudpickle>=3.1.2
38
37
  Requires-Dist: colorama<0.4.7,>=0.4.6
39
38
  Requires-Dist: cryptography>=50.0.2
40
39
  Requires-Dist: fastapi[all]>=0.162.0
@@ -143,6 +142,18 @@ make setup
143
142
  make test
144
143
  ```
145
144
 
145
+ ## Remote values
146
+
147
+ Queue and task calls use finite JSON-compatible arguments, return values,
148
+ and stream chunks. JSON conversion turns tuples into lists and supported
149
+ dictionary keys into strings, including in same-worker remote calls.
150
+ Bytes, custom objects, circular references, and non-finite numbers produce
151
+ explicit errors. `.local()` remains a direct Python call.
152
+
153
+ Successful function responses contain `json_result`, including for a null
154
+ return value. SDK and worker runtimes share the JSON protocol validators;
155
+ use compatible package releases when building worker images.
156
+
146
157
  ## ⚡ | Serverless Worker (SDK)
147
158
 
148
159
  This python package can also be used to create a serverless worker that can be deployed to Runpod as a custom endpoint API.
@@ -84,6 +84,18 @@ make setup
84
84
  make test
85
85
  ```
86
86
 
87
+ ## Remote values
88
+
89
+ Queue and task calls use finite JSON-compatible arguments, return values,
90
+ and stream chunks. JSON conversion turns tuples into lists and supported
91
+ dictionary keys into strings, including in same-worker remote calls.
92
+ Bytes, custom objects, circular references, and non-finite numbers produce
93
+ explicit errors. `.local()` remains a direct Python call.
94
+
95
+ Successful function responses contain `json_result`, including for a null
96
+ return value. SDK and worker runtimes share the JSON protocol validators;
97
+ use compatible package releases when building worker images.
98
+
87
99
  ## ⚡ | Serverless Worker (SDK)
88
100
 
89
101
  This python package can also be used to create a serverless worker that can be deployed to Runpod as a custom endpoint API.
@@ -23,6 +23,10 @@ rp ssh POD_ID # open a terminal on a pod
23
23
  rp pod list
24
24
  rp pod create
25
25
  rp pod connect POD_ID
26
+
27
+ # Network volume files
28
+ rp volume upload VOLUME ./dataset datasets/dataset
29
+ rp volume download VOLUME outputs/ ./outputs
26
30
  ```
27
31
 
28
32
  ## Overview
@@ -44,6 +48,7 @@ rp login --profile staging # save browser credentials in a named profile
44
48
 
45
49
  Credentials are stored in `~/.runpod/config.toml`.
46
50
  Use `--profile NAME` with either login method to update only that profile; the default is `default`.
51
+ Set `RUNPOD_PROFILE=NAME` to select the profile for all commands and for `runpod` in Python; `--profile` overrides it, and `RUNPOD_API_KEY` overrides any stored profile.
47
52
 
48
53
  ### Flash apps
49
54
 
@@ -62,3 +67,38 @@ entrypoint or a resource function; interrupt discovery if an import blocks.
62
67
  On Ctrl-C, a dev session waits for its running local entrypoint to finish before
63
68
  deleting endpoints. Blocking entrypoint code can delay shutdown. Cleanup failures
64
69
  exit with an error and report the endpoint IDs that still need deletion.
70
+
71
+ ### Network volume files
72
+
73
+ ```bash
74
+ rp volume upload VOLUME ./model.safetensors models/
75
+ rp volume upload VOLUME ./dataset datasets/dataset
76
+ rp volume download VOLUME models/model.safetensors
77
+ rp volume download VOLUME outputs/ ./outputs
78
+ ```
79
+
80
+ Transfers use the volume's S3-compatible API, so they need S3 API keys
81
+ (separate from the API key): set `RUNPOD_S3_ACCESS_KEY` and
82
+ `RUNPOD_S3_SECRET_KEY`, pass `--s3-access-key` / `--s3-secret-key`, or save
83
+ `s3_access_key` / `s3_secret_key` in `~/.runpod/config.toml`. The CLI prompts
84
+ for missing keys and offers to save them. You can omit `VOLUME` in an
85
+ interactive session to pick a volume from a list. The
86
+ volume must be in a [datacenter with the S3 API](https://docs.runpod.io/storage/s3-api).
87
+ `VOLUME` is the volume's ID or name, looked up with your API key.
88
+
89
+ To resume an interrupted transfer, run the same command again. Files that
90
+ are unchanged (same size, destination not older) are skipped, a large upload
91
+ reuses the parts it already sent, and a large download keeps its finished
92
+ chunks in `<name>.rpdownload`. `--force` transfers every file. Parts of an
93
+ upload that is never resumed stay in the volume's hidden `.s3compat_uploads`
94
+ folder and count toward its size.
95
+
96
+ The same transfers are available from Python:
97
+
98
+ ```python
99
+ from runpod import NetworkVolume
100
+
101
+ volume = NetworkVolume("my-volume")
102
+ volume.upload("./dataset", "datasets/dataset")
103
+ volume.download("outputs/", "./outputs")
104
+ ```
@@ -12,6 +12,8 @@ Store your Runpod API key by running `rp login` (approve in the browser, then pa
12
12
 
13
13
  Pass `--profile staging` with either login method to update a named credential profile without changing the others. The default profile is `default`.
14
14
 
15
+ Set `RUNPOD_PROFILE=staging` to use that profile for every command, including `rp login`. `--profile` takes precedence over `RUNPOD_PROFILE`, and `RUNPOD_API_KEY` takes precedence over any stored profile.
16
+
15
17
  ### SSH
16
18
 
17
19
  Add an SSH key to your account by running `rp ssh add`. To use an existing key pass `--key` or `--key-file`. Keys are stored in `~/.runpod/ssh/`. If no key is specified a new one is generated and stored.
@@ -0,0 +1,34 @@
1
+ # Getting Started
2
+
3
+ The Runpod python library is a powerful library providing SDK functions, API access, and CLI commands for interacting with the Runpod platform.
4
+
5
+ ## Credentials File
6
+
7
+ `rp login` stores your API key in `~/.runpod/config.toml`, one table per profile:
8
+
9
+ ```toml
10
+ [default]
11
+ api_key = "YOUR_RUNPOD_API_KEY"
12
+ ```
13
+
14
+ ### Profile
15
+
16
+ By default, credentials are stored under and read from the `default` profile. To store a key under another profile, pass `--profile` to `rp login`:
17
+
18
+ ```bash
19
+ rp login --profile my_profile
20
+ ```
21
+
22
+ To use that profile, set the `RUNPOD_PROFILE` environment variable before importing `runpod`. The library reads the profile and its API key once, at import time.
23
+
24
+ ```bash
25
+ export RUNPOD_PROFILE=my_profile
26
+ ```
27
+
28
+ `RUNPOD_API_KEY`, when set, takes precedence over any stored profile. Inside a script, you can also set the key directly:
29
+
30
+ ```python
31
+ import runpod
32
+
33
+ runpod.api_key = "YOUR_RUNPOD_API_KEY"
34
+ ```
@@ -5,7 +5,6 @@ backoff >= 2.2.1
5
5
  boto3 >= 1.43.118
6
6
  certifi >= 2026.10.19
7
7
  click >= 8.5.0
8
- cloudpickle >= 3.1.2
9
8
  colorama >= 0.4.6, < 0.4.7
10
9
  cryptography >= 50.0.2
11
10
  fastapi[all] >= 0.162.0
@@ -54,6 +54,7 @@ _LAZY_ATTRS = {
54
54
  "Model": "runpod.apps",
55
55
  "NetworkVolume": "runpod.apps",
56
56
  "Queue": "runpod.apps",
57
+ "Task": "runpod.apps",
57
58
  "Secret": "runpod.apps",
58
59
  "Volume": "runpod.apps",
59
60
  "is_local": "runpod.apps",
@@ -86,6 +87,18 @@ __all__ = [
86
87
  ]
87
88
 
88
89
 
90
+ DEFAULT_PROFILE = "default"
91
+
92
+
93
+ def _selected_profile() -> str:
94
+ """credential profile in ~/.runpod/config.toml to use.
95
+
96
+ set RUNPOD_PROFILE to pick a named profile (saved with
97
+ `rp login --profile NAME`); unset or blank means "default".
98
+ """
99
+ return os.environ.get("RUNPOD_PROFILE", "").strip() or DEFAULT_PROFILE
100
+
101
+
89
102
  def _load_api_key():
90
103
  """resolve the api key from the environment, then stored credentials.
91
104
 
@@ -102,7 +115,7 @@ def _load_api_key():
102
115
  ).get_credentials(profile)
103
116
  except Exception: # noqa: BLE001 - no stored key is a valid state
104
117
  return None
105
- return creds["api_key"] if creds else None
118
+ return creds.get("api_key") if creds else None
106
119
 
107
120
 
108
121
  def __getattr__(name):
@@ -118,7 +131,7 @@ def __getattr__(name):
118
131
  # ------------------------------- Config Paths ------------------------------- #
119
132
  SSH_KEY_PATH = os.path.expanduser("~/.runpod/ssh")
120
133
 
121
- profile = "default" # pylint: disable=invalid-name
134
+ profile = _selected_profile() # pylint: disable=invalid-name
122
135
 
123
136
  api_key = _load_api_key() # pylint: disable=invalid-name
124
137
 
@@ -0,0 +1,54 @@
1
+ """Service hosts used to build console, proxy, and endpoint URLs.
2
+
3
+ Each host can be overridden with an environment variable, which is read on
4
+ every call so a change takes effect without re-importing ``runpod``. Unset or
5
+ blank values fall back to the public Runpod hosts.
6
+
7
+ RUNPOD_CONSOLE_URL web console base URL (default https://console.runpod.io)
8
+ RUNPOD_PROXY_DOMAIN pod HTTP proxy domain (default proxy.runpod.net)
9
+ RUNPOD_ENDPOINT_BASE_URL serverless base URL (default https://api.runpod.ai/v2)
10
+
11
+ The endpoint domain is the host of ``RUNPOD_ENDPOINT_BASE_URL``. When that is
12
+ unset or blank, a non-blank ``runpod.endpoint_url_base`` set programmatically
13
+ is used instead.
14
+
15
+ Example:
16
+ >>> proxy_url("abc123", 8080)
17
+ 'https://abc123-8080.proxy.runpod.net'
18
+ """
19
+
20
+ import os
21
+ from typing import Union
22
+
23
+ DEFAULT_CONSOLE_URL = "https://console.runpod.io"
24
+ DEFAULT_PROXY_DOMAIN = "proxy.runpod.net"
25
+ DEFAULT_ENDPOINT_BASE_URL = "https://api.runpod.ai/v2"
26
+
27
+
28
+ def _env(name: str, default: str) -> str:
29
+ value = os.environ.get(name, "").strip()
30
+ return value or default
31
+
32
+
33
+ def console_url() -> str:
34
+ """Web console base URL, without a trailing slash."""
35
+ return _env("RUNPOD_CONSOLE_URL", DEFAULT_CONSOLE_URL).rstrip("/")
36
+
37
+
38
+ def proxy_url(pod_id: str, port: Union[int, str]) -> str:
39
+ """Public HTTP proxy URL for ``port`` on ``pod_id``."""
40
+ domain = _env("RUNPOD_PROXY_DOMAIN", DEFAULT_PROXY_DOMAIN).strip("/")
41
+ return f"https://{pod_id}-{port}.{domain}"
42
+
43
+
44
+ def endpoint_domain() -> str:
45
+ """Host of the serverless data plane, e.g. ``api.runpod.ai``.
46
+
47
+ Load-balanced endpoints are served on ``<endpoint_id>.<endpoint_domain>``.
48
+ """
49
+ import runpod
50
+
51
+ module_base = (runpod.endpoint_url_base or "").strip()
52
+ base = _env("RUNPOD_ENDPOINT_BASE_URL", module_base or DEFAULT_ENDPOINT_BASE_URL)
53
+ host = base.split("://", 1)[-1]
54
+ return host.split("/", 1)[0]
@@ -0,0 +1,21 @@
1
+ """finite json validation and wire-value conversion for callers and workers."""
2
+
3
+ import json
4
+ from typing import Any
5
+
6
+
7
+ def _json_text(value: Any, label: str) -> str:
8
+ try:
9
+ return json.dumps(value, allow_nan=False)
10
+ except (TypeError, ValueError, RecursionError) as exc:
11
+ raise TypeError(f"{label} must be json-serializable: {exc}") from exc
12
+
13
+
14
+ def validate_json(value: Any, label: str = "value") -> None:
15
+ """require values encodable as finite json."""
16
+ _json_text(value, label)
17
+
18
+
19
+ def normalize_json(value: Any, label: str = "value") -> Any:
20
+ """apply json's container and key conversions without a network roundtrip."""
21
+ return json.loads(_json_text(value, label))
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '2.1.0'
22
- __version_tuple__ = version_tuple = (2, 1, 0)
21
+ __version__ = version = '2.2.0'
22
+ __version_tuple__ = version_tuple = (2, 2, 0)
23
23
 
24
- __commit_id__ = commit_id = 'g0d59088b9'
24
+ __commit_id__ = commit_id = 'g89d72b8c4'
@@ -0,0 +1,171 @@
1
+ """Filesystem and checksum helpers for resumable transfers.
2
+
3
+ This private module keeps disk state and path safety details out of the S3
4
+ request orchestration. network_volume_transfer re-exports the error type.
5
+ """
6
+
7
+ import hashlib
8
+ import json
9
+ import os
10
+ import unicodedata
11
+ from pathlib import Path, PurePosixPath
12
+ from typing import Any, Dict, List, Optional
13
+
14
+ MIB = 1024 * 1024
15
+ PARTIAL_SUFFIX = ".rpdownload"
16
+ SIDECAR_SUFFIX = ".rpdownload.json"
17
+ # every file a download writes next to its target
18
+ TRANSFER_SUFFIXES = (PARTIAL_SUFFIX, SIDECAR_SUFFIX, SIDECAR_SUFFIX + ".tmp")
19
+
20
+
21
+ class NetworkVolumeTransferError(RuntimeError):
22
+ """a transfer failed. `resumable` says whether re-running can help."""
23
+
24
+ def __init__(self, message: str, resumable: bool = False):
25
+ super().__init__(message)
26
+ self.resumable = resumable
27
+
28
+
29
+ def _read_json(path: Path) -> Optional[Dict[str, Any]]:
30
+ try:
31
+ data = json.loads(path.read_text(encoding="utf-8"))
32
+ except (OSError, ValueError):
33
+ return None
34
+ return data if isinstance(data, dict) else None
35
+
36
+
37
+ def _write_json(path: Path, data: Dict[str, Any]) -> None:
38
+ """replace path atomically, synced, so a crash leaves the old state or
39
+ the new one."""
40
+ path.parent.mkdir(parents=True, exist_ok=True)
41
+ tmp = path.with_name(path.name + ".tmp")
42
+ with open(tmp, "w", encoding="utf-8") as handle:
43
+ json.dump(data, handle)
44
+ handle.flush()
45
+ os.fsync(handle.fileno())
46
+ os.replace(tmp, path)
47
+ _sync_dir(path.parent)
48
+
49
+
50
+ def _sync_dir(path: Path) -> None:
51
+ """make a rename in path survive a power loss. best effort: windows
52
+ cannot open a directory."""
53
+ try:
54
+ fd = os.open(path, os.O_RDONLY)
55
+ except OSError:
56
+ return
57
+ try:
58
+ os.fsync(fd)
59
+ except OSError:
60
+ # some filesystems refuse fsync on a directory; the rename stands
61
+ pass
62
+ finally:
63
+ os.close(fd)
64
+
65
+
66
+ def _md5_hex(path: Path, offset: int, length: int) -> str:
67
+ digest = hashlib.md5() # noqa: S324 - etag comparison, not security
68
+ with open(path, "rb") as handle:
69
+ handle.seek(offset)
70
+ while length > 0 and (block := handle.read(min(8 * MIB, length))):
71
+ digest.update(block)
72
+ length -= len(block)
73
+ return digest.hexdigest()
74
+
75
+
76
+ def _etag(value: Any) -> str:
77
+ return str(value or "").strip('"')
78
+
79
+
80
+ def _is_md5(etag: str) -> bool:
81
+ return len(etag) == 32 and all(c in "0123456789abcdef" for c in etag.lower())
82
+
83
+
84
+ def _multipart_etag(parts: List[Dict[str, Any]]) -> str:
85
+ """the etag s3 (and runpod, verified) gives an object assembled from
86
+ parts: md5 of the parts' binary md5s, then "-<count>". "" when a part
87
+ etag is not an md5."""
88
+ etags = [_etag(part["ETag"]) for part in parts]
89
+ if not all(_is_md5(etag) for etag in etags):
90
+ return ""
91
+ digest = hashlib.md5(b"".join(bytes.fromhex(etag) for etag in etags)) # noqa: S324
92
+ return f"{digest.hexdigest()}-{len(parts)}"
93
+
94
+
95
+ def _same_version(a: os.stat_result, b: os.stat_result) -> bool:
96
+ return a.st_size == b.st_size and a.st_mtime_ns == b.st_mtime_ns
97
+
98
+
99
+ def _not_older(a: float, b: float) -> bool:
100
+ """a >= b in whole seconds; s3 dates carry no finer precision."""
101
+ return int(a) >= int(b)
102
+
103
+
104
+ def _check_remote_path(remote_path: Optional[str]) -> None:
105
+ if remote_path and ".." in remote_path.replace("\\", "/").split("/"):
106
+ raise ValueError(f"remote path {remote_path!r} must not contain '..'")
107
+
108
+
109
+ def _check_local_names(targets: List[Path], root: Path) -> None:
110
+ """refuse targets that would share a path on disk: two that are one name
111
+ on a case-insensitive or normalizing filesystem ("Model.bin" and
112
+ "model.bin"), a file whose name is also a folder another file lives in
113
+ ("a" beside "A/b"), or a file whose partial, sidecar or sidecar temp name
114
+ is also a target or a folder one lives in ("x" beside "x.rpdownload/y").
115
+ names are compared nfc-normalized (apfs ignores normalization) and case
116
+ folded, which can refuse a listing a case-sensitive filesystem would
117
+ take: the safe direction."""
118
+
119
+ def fold(path: PurePosixPath) -> str:
120
+ return unicodedata.normalize("NFC", str(path)).casefold()
121
+
122
+ rels = [PurePosixPath(target.relative_to(root).as_posix()) for target in targets]
123
+ files: Dict[str, PurePosixPath] = {}
124
+ dirs: Dict[str, PurePosixPath] = {}
125
+ for rel in rels:
126
+ if fold(rel) in files:
127
+ raise NetworkVolumeTransferError(
128
+ f"cannot download both {files[fold(rel)]} and {rel}: they would be one "
129
+ "file on a case-insensitive or normalizing filesystem"
130
+ )
131
+ files[fold(rel)] = rel
132
+ dirs.update({fold(parent): rel for parent in rel.parents if str(parent) != "."})
133
+ for rel in rels:
134
+ if fold(rel) in dirs:
135
+ raise NetworkVolumeTransferError(
136
+ f"cannot download both {rel} and {dirs[fold(rel)]}: "
137
+ "the first would have to be a file and a folder"
138
+ )
139
+ for suffix in TRANSFER_SUFFIXES:
140
+ twin = fold(rel.with_name(rel.name + suffix))
141
+ other = files.get(twin) or dirs.get(twin)
142
+ if other is not None:
143
+ raise NetworkVolumeTransferError(
144
+ f"cannot download both {rel} and {other}: "
145
+ f"{rel.name + suffix} is used for the first's partial download"
146
+ )
147
+
148
+
149
+ def _safe_target(root: Path, rel: str) -> Path:
150
+ """local path for a remote relative key, refusing anything outside root.
151
+ "." and empty segments are refused too: "a/./b" would alias "a/b"."""
152
+ segments = rel.split("/")
153
+ if (
154
+ rel.startswith("/")
155
+ or "\\" in rel
156
+ or any(seg in ("..", ".", "") for seg in segments)
157
+ or ":" in segments[0]
158
+ ):
159
+ raise NetworkVolumeTransferError(f"refusing unsafe remote path: {rel!r}")
160
+ target = root.joinpath(*segments)
161
+ if root.resolve() not in target.resolve().parents:
162
+ raise NetworkVolumeTransferError(f"refusing unsafe remote path: {rel!r}")
163
+ # a symlinked folder would let two remote paths share one local file,
164
+ # which the name collision check cannot see
165
+ for depth in range(1, len(segments)):
166
+ if root.joinpath(*segments[:depth]).is_symlink():
167
+ raise NetworkVolumeTransferError(
168
+ f"{root.joinpath(*segments[:depth])} is a symlink; "
169
+ "download into a folder without symlinked subfolders"
170
+ )
171
+ return target
@@ -87,6 +87,7 @@ async def run_graphql_query_async(
87
87
  variables: Optional[Dict[str, Any]] = None,
88
88
  timeout: float = 60.0,
89
89
  anonymous: bool = False,
90
+ headers: Optional[Dict[str, str]] = None,
90
91
  ) -> Dict[str, Any]:
91
92
  """
92
93
  Async variant of run_graphql_query, sharing the same url, headers,
@@ -109,7 +110,7 @@ async def run_graphql_query_async(
109
110
  async with aiohttp.ClientSession(timeout=client_timeout) as session:
110
111
  async with session.post(
111
112
  _graphql_url(),
112
- headers=_build_headers(effective_api_key),
113
+ headers={**_build_headers(effective_api_key), **(headers or {})},
113
114
  json=_build_payload(query, variables),
114
115
  ) as response:
115
116
  if response.status == HTTP_STATUS_UNAUTHORIZED:
@@ -92,6 +92,12 @@ mutation FinalizeArtifactUpload($input: FinalizeFlashArtifactUploadInput!) {
92
92
  }
93
93
  """
94
94
 
95
+ MUTATION_FINALIZE_TASK_ARTIFACT_UPLOAD = """
96
+ mutation FinalizeArtifactUpload($input: FinalizeFlashArtifactUploadInput!) {
97
+ finalizeFlashArtifactUpload(input: $input) { id manifest resourceSpec }
98
+ }
99
+ """
100
+
95
101
  MUTATION_DEPLOY_BUILD = """
96
102
  mutation deployBuildToEnvironment($input: DeployBuildToEnvironmentInput!) {
97
103
  deployBuildToEnvironment(input: $input) { id name }
@@ -15,7 +15,7 @@ from .job import Job
15
15
  from .markers import delete, get, init, patch, post, put
16
16
  from .schedule import schedule
17
17
  from .spec import ResourceKind, ResourceSpec, RouteSpec
18
- from .stubs import Api, Queue
18
+ from .stubs import Api, Queue, Task
19
19
  from .model import Model
20
20
  from .secret import Secret
21
21
  from .volume import GlobalVolume, NetworkVolume, Volume
@@ -34,6 +34,7 @@ __all__ = [
34
34
  "Model",
35
35
  "NetworkVolume",
36
36
  "Queue",
37
+ "Task",
37
38
  "Secret",
38
39
  "Volume",
39
40
  "RemoteExecutionError",
@@ -20,6 +20,46 @@ from ..error import AuthenticationError, QueryError
20
20
  _TRANSPORT_RETRIES = 4
21
21
 
22
22
 
23
+ class FlashTaskApiClient:
24
+ """named task lifecycle operations with runtime-scoped authentication."""
25
+
26
+ async def _execute(self, query: str, task_input: Dict[str, Any]) -> Dict[str, Any]:
27
+ from .utils.network import api_key, runtime_headers
28
+
29
+ headers = runtime_headers()
30
+ response = await run_graphql_query_async(
31
+ query,
32
+ variables={"input": task_input},
33
+ api_key=(headers["Authorization"][7:] if headers else api_key()),
34
+ headers=headers,
35
+ )
36
+ return response["data"]
37
+
38
+ async def create(self, task_input: Dict[str, Any]) -> Dict[str, Any]:
39
+ from .utils.network import validate_runtime_target
40
+
41
+ validate_runtime_target(
42
+ task_input.get("flashAppName"), task_input.get("flashEnvironmentName")
43
+ )
44
+ data = await self._execute(
45
+ """mutation FlashTaskCreate($input: FlashTaskCreateInput!) {
46
+ flashTaskCreate(input: $input) { podId flashBuildId resourceName }
47
+ }""",
48
+ task_input,
49
+ )
50
+ return data["flashTaskCreate"]
51
+
52
+ async def terminate(self, pod_id: str, token: str) -> None:
53
+ data = await self._execute(
54
+ """mutation FlashTaskTerminate($input: FlashTaskTerminateInput!) {
55
+ flashTaskTerminate(input: $input)
56
+ }""",
57
+ {"podId": pod_id, "executionToken": token},
58
+ )
59
+ if data.get("flashTaskTerminate") is not True:
60
+ raise RuntimeError("task termination was not acknowledged")
61
+
62
+
23
63
  def _rest_endpoint_input(endpoint: Dict[str, Any]) -> Optional[Dict[str, Any]]:
24
64
  """translate only saves whose capabilities rest can preserve atomically."""
25
65
  fields = {
@@ -583,6 +623,8 @@ class AppsApiClient:
583
623
  self, app_id: str, object_key: str, manifest: Dict[str, Any]
584
624
  ) -> Dict[str, Any]:
585
625
  mutation = app_mutations.MUTATION_FINALIZE_ARTIFACT_UPLOAD
626
+ if any(r.get("kind") == "task" for r in manifest.get("resources", [])):
627
+ mutation = app_mutations.MUTATION_FINALIZE_TASK_ARTIFACT_UPLOAD
586
628
  data = await self._execute(
587
629
  mutation,
588
630
  {
@@ -151,7 +151,11 @@ class App:
151
151
  accelerate_downloads: bool = True,
152
152
  container_disk_gb: Optional[int] = None,
153
153
  ) -> Callable[[Callable], FunctionHandle]:
154
- """declare ephemeral pod compute from a function."""
154
+ """declare ephemeral pod compute from a function.
155
+
156
+ remote task arguments and results use json in every execution
157
+ context. use .local() for direct python execution without transport.
158
+ """
155
159
 
156
160
  def decorator(fn: Callable) -> FunctionHandle:
157
161
  spec = ResourceSpec(
@@ -259,6 +263,12 @@ class App:
259
263
  """resolve a resource spec to an invocation target."""
260
264
  spec.validate()
261
265
  if spec.kind is ResourceKind.TASK:
266
+ from .context import deployed_identity
267
+ from .targets import DeployedTaskTarget
268
+
269
+ identity = deployed_identity()
270
+ if identity is not None:
271
+ return DeployedTaskTarget(self.name, identity[1], spec.name)
262
272
  handle = self._resources.get(spec.name)
263
273
  fn = getattr(handle, "_fn", None)
264
274
  return PodTarget(