kernel 0.49.0__tar.gz → 0.51.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 (279) hide show
  1. kernel-0.51.0/.release-please-manifest.json +3 -0
  2. {kernel-0.49.0 → kernel-0.51.0}/CHANGELOG.md +69 -0
  3. {kernel-0.49.0 → kernel-0.51.0}/PKG-INFO +1 -1
  4. {kernel-0.49.0 → kernel-0.51.0}/api.md +2 -0
  5. kernel-0.51.0/examples/browser_routing.py +25 -0
  6. {kernel-0.49.0 → kernel-0.51.0}/pyproject.toml +1 -1
  7. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_client.py +88 -1
  8. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_files.py +53 -3
  9. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/__init__.py +0 -1
  10. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_utils.py +3 -17
  11. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_version.py +1 -1
  12. kernel-0.51.0/src/kernel/lib/browser_routing/__init__.py +3 -0
  13. kernel-0.51.0/src/kernel/lib/browser_routing/raw_http.py +150 -0
  14. kernel-0.51.0/src/kernel/lib/browser_routing/routing.py +243 -0
  15. kernel-0.51.0/src/kernel/lib/browser_routing/util.py +58 -0
  16. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/browsers.py +270 -4
  17. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/fs/fs.py +10 -8
  18. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/deployments.py +8 -5
  19. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/extensions.py +8 -5
  20. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/projects/projects.py +4 -4
  21. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/__init__.py +2 -0
  22. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/connection_follow_response.py +6 -0
  23. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/managed_auth.py +33 -2
  24. kernel-0.51.0/src/kernel/types/browser_curl_params.py +28 -0
  25. kernel-0.51.0/src/kernel/types/browser_curl_response.py +23 -0
  26. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_browsers.py +121 -0
  27. kernel-0.51.0/tests/test_browser_routing.py +323 -0
  28. {kernel-0.49.0 → kernel-0.51.0}/tests/test_extract_files.py +9 -0
  29. kernel-0.51.0/tests/test_files.py +148 -0
  30. kernel-0.49.0/.release-please-manifest.json +0 -3
  31. kernel-0.49.0/tests/test_deepcopy.py +0 -58
  32. kernel-0.49.0/tests/test_files.py +0 -51
  33. {kernel-0.49.0 → kernel-0.51.0}/.gitignore +0 -0
  34. {kernel-0.49.0 → kernel-0.51.0}/CONTRIBUTING.md +0 -0
  35. {kernel-0.49.0 → kernel-0.51.0}/LICENSE +0 -0
  36. {kernel-0.49.0 → kernel-0.51.0}/README.md +0 -0
  37. {kernel-0.49.0 → kernel-0.51.0}/SECURITY.md +0 -0
  38. {kernel-0.49.0 → kernel-0.51.0}/bin/check-release-environment +0 -0
  39. {kernel-0.49.0 → kernel-0.51.0}/bin/publish-pypi +0 -0
  40. {kernel-0.49.0 → kernel-0.51.0}/examples/.keep +0 -0
  41. {kernel-0.49.0 → kernel-0.51.0}/noxfile.py +0 -0
  42. {kernel-0.49.0 → kernel-0.51.0}/release-please-config.json +0 -0
  43. {kernel-0.49.0 → kernel-0.51.0}/requirements-dev.lock +0 -0
  44. {kernel-0.49.0 → kernel-0.51.0}/requirements.lock +0 -0
  45. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/__init__.py +0 -0
  46. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_base_client.py +0 -0
  47. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_compat.py +0 -0
  48. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_constants.py +0 -0
  49. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_exceptions.py +0 -0
  50. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_models.py +0 -0
  51. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_qs.py +0 -0
  52. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_resource.py +0 -0
  53. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_response.py +0 -0
  54. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_streaming.py +0 -0
  55. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_types.py +0 -0
  56. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_compat.py +0 -0
  57. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_datetime_parse.py +0 -0
  58. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_json.py +0 -0
  59. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_logs.py +0 -0
  60. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_path.py +0 -0
  61. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_proxy.py +0 -0
  62. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_reflection.py +0 -0
  63. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_resources_proxy.py +0 -0
  64. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_streams.py +0 -0
  65. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_sync.py +0 -0
  66. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_transform.py +0 -0
  67. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_typing.py +0 -0
  68. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/app_framework.py +0 -0
  69. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/lib/.keep +0 -0
  70. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/pagination.py +0 -0
  71. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/py.typed +0 -0
  72. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/__init__.py +0 -0
  73. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/apps.py +0 -0
  74. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/auth/__init__.py +0 -0
  75. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/auth/auth.py +0 -0
  76. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/auth/connections.py +0 -0
  77. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browser_pools.py +0 -0
  78. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/__init__.py +0 -0
  79. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/computer.py +0 -0
  80. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/fs/__init__.py +0 -0
  81. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/fs/watch.py +0 -0
  82. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/logs.py +0 -0
  83. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/playwright.py +0 -0
  84. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/process.py +0 -0
  85. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/replays.py +0 -0
  86. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/credential_providers.py +0 -0
  87. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/credentials.py +0 -0
  88. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/invocations.py +0 -0
  89. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/profiles.py +0 -0
  90. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/projects/__init__.py +0 -0
  91. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/projects/limits.py +0 -0
  92. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/proxies.py +0 -0
  93. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/app_list_params.py +0 -0
  94. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/app_list_response.py +0 -0
  95. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/__init__.py +0 -0
  96. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/connection_create_params.py +0 -0
  97. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/connection_list_params.py +0 -0
  98. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/connection_login_params.py +0 -0
  99. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/connection_submit_params.py +0 -0
  100. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/connection_update_params.py +0 -0
  101. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/login_response.py +0 -0
  102. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/submit_fields_response.py +0 -0
  103. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_create_params.py +0 -0
  104. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_create_response.py +0 -0
  105. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_delete_params.py +0 -0
  106. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_list_params.py +0 -0
  107. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_list_response.py +0 -0
  108. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_load_extensions_params.py +0 -0
  109. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_persistence.py +0 -0
  110. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_persistence_param.py +0 -0
  111. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool.py +0 -0
  112. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool_acquire_params.py +0 -0
  113. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool_acquire_response.py +0 -0
  114. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool_create_params.py +0 -0
  115. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool_delete_params.py +0 -0
  116. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool_list_response.py +0 -0
  117. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool_ref.py +0 -0
  118. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool_release_params.py +0 -0
  119. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool_update_params.py +0 -0
  120. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_retrieve_params.py +0 -0
  121. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_retrieve_response.py +0 -0
  122. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_update_params.py +0 -0
  123. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_update_response.py +0 -0
  124. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_usage.py +0 -0
  125. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/__init__.py +0 -0
  126. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_batch_params.py +0 -0
  127. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_capture_screenshot_params.py +0 -0
  128. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_click_mouse_params.py +0 -0
  129. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_drag_mouse_params.py +0 -0
  130. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_get_mouse_position_response.py +0 -0
  131. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_move_mouse_params.py +0 -0
  132. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_press_key_params.py +0 -0
  133. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_read_clipboard_response.py +0 -0
  134. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_scroll_params.py +0 -0
  135. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_set_cursor_visibility_params.py +0 -0
  136. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_set_cursor_visibility_response.py +0 -0
  137. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_type_text_params.py +0 -0
  138. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_write_clipboard_params.py +0 -0
  139. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_create_directory_params.py +0 -0
  140. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_delete_directory_params.py +0 -0
  141. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_delete_file_params.py +0 -0
  142. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_download_dir_zip_params.py +0 -0
  143. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_file_info_params.py +0 -0
  144. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_file_info_response.py +0 -0
  145. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_list_files_params.py +0 -0
  146. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_list_files_response.py +0 -0
  147. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_move_params.py +0 -0
  148. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_read_file_params.py +0 -0
  149. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_set_file_permissions_params.py +0 -0
  150. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_upload_params.py +0 -0
  151. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_upload_zip_params.py +0 -0
  152. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_write_file_params.py +0 -0
  153. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/fs/__init__.py +0 -0
  154. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/fs/watch_events_response.py +0 -0
  155. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/fs/watch_start_params.py +0 -0
  156. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/fs/watch_start_response.py +0 -0
  157. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/log_stream_params.py +0 -0
  158. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/playwright_execute_params.py +0 -0
  159. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/playwright_execute_response.py +0 -0
  160. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_exec_params.py +0 -0
  161. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_exec_response.py +0 -0
  162. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_kill_params.py +0 -0
  163. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_kill_response.py +0 -0
  164. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_resize_params.py +0 -0
  165. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_resize_response.py +0 -0
  166. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_spawn_params.py +0 -0
  167. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_spawn_response.py +0 -0
  168. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_status_response.py +0 -0
  169. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_stdin_params.py +0 -0
  170. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_stdin_response.py +0 -0
  171. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_stdout_stream_response.py +0 -0
  172. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/replay_list_response.py +0 -0
  173. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/replay_start_params.py +0 -0
  174. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/replay_start_response.py +0 -0
  175. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential.py +0 -0
  176. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_create_params.py +0 -0
  177. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_list_params.py +0 -0
  178. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_provider.py +0 -0
  179. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_provider_create_params.py +0 -0
  180. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_provider_item.py +0 -0
  181. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_provider_list_items_response.py +0 -0
  182. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_provider_list_response.py +0 -0
  183. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_provider_test_result.py +0 -0
  184. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_provider_update_params.py +0 -0
  185. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_totp_code_response.py +0 -0
  186. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_update_params.py +0 -0
  187. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/deployment_create_params.py +0 -0
  188. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/deployment_create_response.py +0 -0
  189. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/deployment_follow_params.py +0 -0
  190. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/deployment_follow_response.py +0 -0
  191. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/deployment_list_params.py +0 -0
  192. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/deployment_list_response.py +0 -0
  193. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/deployment_retrieve_response.py +0 -0
  194. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/deployment_state_event.py +0 -0
  195. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/extension_download_from_chrome_store_params.py +0 -0
  196. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/extension_list_response.py +0 -0
  197. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/extension_upload_params.py +0 -0
  198. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/extension_upload_response.py +0 -0
  199. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_create_params.py +0 -0
  200. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_create_response.py +0 -0
  201. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_follow_params.py +0 -0
  202. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_follow_response.py +0 -0
  203. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_list_browsers_response.py +0 -0
  204. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_list_params.py +0 -0
  205. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_list_response.py +0 -0
  206. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_retrieve_response.py +0 -0
  207. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_state_event.py +0 -0
  208. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_update_params.py +0 -0
  209. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_update_response.py +0 -0
  210. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/profile.py +0 -0
  211. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/profile_create_params.py +0 -0
  212. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/profile_list_params.py +0 -0
  213. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/project.py +0 -0
  214. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/project_create_params.py +0 -0
  215. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/project_list_params.py +0 -0
  216. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/project_update_params.py +0 -0
  217. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/projects/__init__.py +0 -0
  218. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/projects/limit_update_params.py +0 -0
  219. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/projects/project_limits.py +0 -0
  220. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/proxy_check_params.py +0 -0
  221. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/proxy_check_response.py +0 -0
  222. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/proxy_create_params.py +0 -0
  223. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/proxy_create_response.py +0 -0
  224. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/proxy_list_response.py +0 -0
  225. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/proxy_retrieve_response.py +0 -0
  226. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/__init__.py +0 -0
  227. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/app_action.py +0 -0
  228. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/browser_extension.py +0 -0
  229. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/browser_profile.py +0 -0
  230. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/browser_viewport.py +0 -0
  231. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/error_detail.py +0 -0
  232. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/error_event.py +0 -0
  233. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/error_model.py +0 -0
  234. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/heartbeat_event.py +0 -0
  235. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/log_event.py +0 -0
  236. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared_params/__init__.py +0 -0
  237. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared_params/browser_extension.py +0 -0
  238. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared_params/browser_profile.py +0 -0
  239. {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared_params/browser_viewport.py +0 -0
  240. {kernel-0.49.0 → kernel-0.51.0}/tests/__init__.py +0 -0
  241. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/__init__.py +0 -0
  242. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/auth/__init__.py +0 -0
  243. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/auth/test_connections.py +0 -0
  244. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/__init__.py +0 -0
  245. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/fs/__init__.py +0 -0
  246. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/fs/test_watch.py +0 -0
  247. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/test_computer.py +0 -0
  248. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/test_fs.py +0 -0
  249. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/test_logs.py +0 -0
  250. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/test_playwright.py +0 -0
  251. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/test_process.py +0 -0
  252. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/test_replays.py +0 -0
  253. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/projects/__init__.py +0 -0
  254. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/projects/test_limits.py +0 -0
  255. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_apps.py +0 -0
  256. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_browser_pools.py +0 -0
  257. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_credential_providers.py +0 -0
  258. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_credentials.py +0 -0
  259. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_deployments.py +0 -0
  260. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_extensions.py +0 -0
  261. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_invocations.py +0 -0
  262. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_profiles.py +0 -0
  263. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_projects.py +0 -0
  264. {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_proxies.py +0 -0
  265. {kernel-0.49.0 → kernel-0.51.0}/tests/conftest.py +0 -0
  266. {kernel-0.49.0 → kernel-0.51.0}/tests/sample_file.txt +0 -0
  267. {kernel-0.49.0 → kernel-0.51.0}/tests/test_client.py +0 -0
  268. {kernel-0.49.0 → kernel-0.51.0}/tests/test_models.py +0 -0
  269. {kernel-0.49.0 → kernel-0.51.0}/tests/test_qs.py +0 -0
  270. {kernel-0.49.0 → kernel-0.51.0}/tests/test_required_args.py +0 -0
  271. {kernel-0.49.0 → kernel-0.51.0}/tests/test_response.py +0 -0
  272. {kernel-0.49.0 → kernel-0.51.0}/tests/test_streaming.py +0 -0
  273. {kernel-0.49.0 → kernel-0.51.0}/tests/test_transform.py +0 -0
  274. {kernel-0.49.0 → kernel-0.51.0}/tests/test_utils/test_datetime_parse.py +0 -0
  275. {kernel-0.49.0 → kernel-0.51.0}/tests/test_utils/test_json.py +0 -0
  276. {kernel-0.49.0 → kernel-0.51.0}/tests/test_utils/test_path.py +0 -0
  277. {kernel-0.49.0 → kernel-0.51.0}/tests/test_utils/test_proxy.py +0 -0
  278. {kernel-0.49.0 → kernel-0.51.0}/tests/test_utils/test_typing.py +0 -0
  279. {kernel-0.49.0 → kernel-0.51.0}/tests/utils.py +0 -0
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "0.51.0"
3
+ }
@@ -1,5 +1,74 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.51.0 (2026-04-25)
4
+
5
+ Full Changelog: [v0.50.0...v0.51.0](https://github.com/kernel/kernel-python-sdk/compare/v0.50.0...v0.51.0)
6
+
7
+ ### Features
8
+
9
+ * add browser-scoped session client ([7ca6887](https://github.com/kernel/kernel-python-sdk/commit/7ca68877e7011bb83862b7cc810a20d8254ea7dd))
10
+ * Expire stuck IN_PROGRESS managed auth sessions via background worker ([7781a3b](https://github.com/kernel/kernel-python-sdk/commit/7781a3b4635ded02dea60adf85878f50f7b7fb27))
11
+ * Expose browser_session_id on managed auth connection ([0ccb507](https://github.com/kernel/kernel-python-sdk/commit/0ccb50744032b4c31e0575fa7b06fb20503c8f55))
12
+ * generate browser-scoped resource bindings ([53b17c8](https://github.com/kernel/kernel-python-sdk/commit/53b17c8241cc71261d1e96f5929cbd4f05b2064b))
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * address python browser routing ci follow-ups ([9690923](https://github.com/kernel/kernel-python-sdk/commit/9690923666cfe07de76267eee050d7743a8bad6f))
18
+ * evict deleted browser routes ([a873a18](https://github.com/kernel/kernel-python-sdk/commit/a873a18eba3f36937dc177ab981372e395722f8b))
19
+ * finish python browser routing cleanup ([694907a](https://github.com/kernel/kernel-python-sdk/commit/694907ab3419477e7058b85a7365ac4cce941105))
20
+ * normalize browser route cache session IDs ([f4c247b](https://github.com/kernel/kernel-python-sdk/commit/f4c247b425680b54d0ce3c7738fb82313bca7918))
21
+ * normalize python browser request string bodies ([3ce80e7](https://github.com/kernel/kernel-python-sdk/commit/3ce80e767d373b638ba1c2959bf18bf999629db0))
22
+ * quiet generator-script pyright noise ([0bdf85e](https://github.com/kernel/kernel-python-sdk/commit/0bdf85e0c38d4813056b61599273e88c7a64713a))
23
+ * reserve internal browser request query params ([b2c7aac](https://github.com/kernel/kernel-python-sdk/commit/b2c7aacac09a1bb7680cf493e9985438b169286c))
24
+ * satisfy browser-scoped lint checks ([8e8dde2](https://github.com/kernel/kernel-python-sdk/commit/8e8dde241c8817944baaacd155fe196f200868e8))
25
+ * satisfy generated browser-scoped type checks ([b410245](https://github.com/kernel/kernel-python-sdk/commit/b410245e1ad4bf8e29c17c59a5931654567b141f))
26
+ * sniff browser pool route cache updates ([5328730](https://github.com/kernel/kernel-python-sdk/commit/532873072f0400029768d1b7cf54b9fb1428ada9))
27
+ * type-check browser-scoped helpers ([cfff5b4](https://github.com/kernel/kernel-python-sdk/commit/cfff5b4c3635d327dd1ac0779d4e17e395efbec0))
28
+
29
+
30
+ ### Chores
31
+
32
+ * fix browser-scoped test import order ([fc34859](https://github.com/kernel/kernel-python-sdk/commit/fc34859c4f60f84038b425d9930c512e58134dea))
33
+ * **internal:** more robust bootstrap script ([6c9cdf3](https://github.com/kernel/kernel-python-sdk/commit/6c9cdf3ce828fab358c7e060f4e3313408cad257))
34
+ * keep browser-scoped generator lint clean ([a80716b](https://github.com/kernel/kernel-python-sdk/commit/a80716b791bf1f707aa7869290c47caefb0d9e27))
35
+
36
+
37
+ ### Documentation
38
+
39
+ * flesh out browser-scoped example ([ca5d188](https://github.com/kernel/kernel-python-sdk/commit/ca5d1884b590634df5623945e9585e0a66228ec3))
40
+
41
+
42
+ ### Refactors
43
+
44
+ * clean up python browser routing diff ([622f844](https://github.com/kernel/kernel-python-sdk/commit/622f8448a8a32f00b41d6e4890bfaf0a9374bd3e))
45
+ * drop browser-scoped wrapper clients ([dba503e](https://github.com/kernel/kernel-python-sdk/commit/dba503e832d54aa8d462d3d74b3027f8a9e865b6))
46
+ * inline browser resource passthrough returns ([02a2f59](https://github.com/kernel/kernel-python-sdk/commit/02a2f595c7e76ae7f0cea2ec1e88075df3a25be1))
47
+ * move python browser routing rollout to env ([0647d5c](https://github.com/kernel/kernel-python-sdk/commit/0647d5cab166e680bcb3436d1b502c3215492400))
48
+ * rename browser routing subresources config ([3ae9dab](https://github.com/kernel/kernel-python-sdk/commit/3ae9dab6b841e6f1191cdde073e36696f97feb39))
49
+ * simplify browser routing cache ([de0476f](https://github.com/kernel/kernel-python-sdk/commit/de0476fc043df48a58dd4067bb4b3c0fe7a83f0e))
50
+ * sniff browser routes in response hooks ([563de7d](https://github.com/kernel/kernel-python-sdk/commit/563de7d0ac8f141320edb060b4671935808e473a))
51
+
52
+ ## 0.50.0 (2026-04-20)
53
+
54
+ Full Changelog: [v0.49.0...v0.50.0](https://github.com/kernel/kernel-python-sdk/compare/v0.49.0...v0.50.0)
55
+
56
+ ### Features
57
+
58
+ * add POST /browsers/{id}/curl and /curl/raw endpoints ([e91bc38](https://github.com/kernel/kernel-python-sdk/commit/e91bc387e5ef74c1b02f62e19e9ae31867296af4))
59
+ * remove paid plan gating from project endpoints ([284c2d4](https://github.com/kernel/kernel-python-sdk/commit/284c2d434be9d098efbaf33b14b416acd4c78e18))
60
+
61
+
62
+ ### Bug Fixes
63
+
64
+ * ensure file data are only sent as 1 parameter ([e566aa5](https://github.com/kernel/kernel-python-sdk/commit/e566aa50a9022d5b284c6334b3704df2a96643cc))
65
+ * include MFA and sign-in options in CUA SSO-only step response ([ea9576b](https://github.com/kernel/kernel-python-sdk/commit/ea9576b87a17b903f880ab8d14379b8ca5fe53d5))
66
+
67
+
68
+ ### Performance Improvements
69
+
70
+ * **client:** optimize file structure copying in multipart requests ([d46c711](https://github.com/kernel/kernel-python-sdk/commit/d46c711588904a9e249a0e852a790c3431d12aa1))
71
+
3
72
  ## 0.49.0 (2026-04-10)
4
73
 
5
74
  Full Changelog: [v0.48.0...v0.49.0](https://github.com/kernel/kernel-python-sdk/compare/v0.48.0...v0.49.0)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: kernel
3
- Version: 0.49.0
3
+ Version: 0.51.0
4
4
  Summary: The official Python library for the kernel API
5
5
  Project-URL: Homepage, https://github.com/kernel/kernel-python-sdk
6
6
  Project-URL: Repository, https://github.com/kernel/kernel-python-sdk
@@ -88,6 +88,7 @@ from kernel.types import (
88
88
  BrowserRetrieveResponse,
89
89
  BrowserUpdateResponse,
90
90
  BrowserListResponse,
91
+ BrowserCurlResponse,
91
92
  )
92
93
  ```
93
94
 
@@ -98,6 +99,7 @@ Methods:
98
99
  - <code title="patch /browsers/{id}">client.browsers.<a href="./src/kernel/resources/browsers/browsers.py">update</a>(id, \*\*<a href="src/kernel/types/browser_update_params.py">params</a>) -> <a href="./src/kernel/types/browser_update_response.py">BrowserUpdateResponse</a></code>
99
100
  - <code title="get /browsers">client.browsers.<a href="./src/kernel/resources/browsers/browsers.py">list</a>(\*\*<a href="src/kernel/types/browser_list_params.py">params</a>) -> <a href="./src/kernel/types/browser_list_response.py">SyncOffsetPagination[BrowserListResponse]</a></code>
100
101
  - <code title="delete /browsers">client.browsers.<a href="./src/kernel/resources/browsers/browsers.py">delete</a>(\*\*<a href="src/kernel/types/browser_delete_params.py">params</a>) -> None</code>
102
+ - <code title="post /browsers/{id}/curl">client.browsers.<a href="./src/kernel/resources/browsers/browsers.py">curl</a>(id, \*\*<a href="src/kernel/types/browser_curl_params.py">params</a>) -> <a href="./src/kernel/types/browser_curl_response.py">BrowserCurlResponse</a></code>
101
103
  - <code title="delete /browsers/{id}">client.browsers.<a href="./src/kernel/resources/browsers/browsers.py">delete_by_id</a>(id) -> None</code>
102
104
  - <code title="post /browsers/{id}/extensions">client.browsers.<a href="./src/kernel/resources/browsers/browsers.py">load_extensions</a>(id, \*\*<a href="src/kernel/types/browser_load_extensions_params.py">params</a>) -> None</code>
103
105
 
@@ -0,0 +1,25 @@
1
+ """Example: direct-to-VM browser routing for process exec and raw HTTP."""
2
+
3
+ from typing import Any, cast
4
+
5
+ import httpx
6
+
7
+ from kernel import Kernel
8
+
9
+
10
+ def main() -> None:
11
+ with Kernel() as client:
12
+ browsers = cast(Any, client.browsers)
13
+ browser = browsers.create(headless=True)
14
+ try:
15
+ response = cast(httpx.Response, browsers.request(browser.session_id, "GET", "https://example.com"))
16
+ print("status", response.status_code)
17
+
18
+ with browsers.stream(browser.session_id, "GET", "https://example.com") as streamed:
19
+ print("streamed-bytes", len(streamed.read()))
20
+ finally:
21
+ browsers.delete_by_id(browser.session_id)
22
+
23
+
24
+ if __name__ == "__main__":
25
+ main()
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kernel"
3
- version = "0.49.0"
3
+ version = "0.51.0"
4
4
  description = "The official Python library for the kernel API"
5
5
  dynamic = ["readme"]
6
6
  license = "Apache-2.0"
@@ -3,7 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import os
6
- from typing import TYPE_CHECKING, Any, Dict, Mapping, cast
6
+ from typing import TYPE_CHECKING, Any, Dict, Type, Mapping, cast
7
7
  from typing_extensions import Self, Literal, override
8
8
 
9
9
  import httpx
@@ -14,6 +14,7 @@ from ._types import (
14
14
  Omit,
15
15
  Timeout,
16
16
  NotGiven,
17
+ ResponseT,
17
18
  Transport,
18
19
  ProxiesTypes,
19
20
  RequestOptions,
@@ -21,6 +22,7 @@ from ._types import (
21
22
  )
22
23
  from ._utils import is_given, get_async_library
23
24
  from ._compat import cached_property
25
+ from ._models import FinalRequestOptions
24
26
  from ._version import __version__
25
27
  from ._streaming import Stream as Stream, AsyncStream as AsyncStream
26
28
  from ._exceptions import KernelError, APIStatusError
@@ -29,6 +31,15 @@ from ._base_client import (
29
31
  SyncAPIClient,
30
32
  AsyncAPIClient,
31
33
  )
34
+ from .lib.browser_routing.routing import (
35
+ BrowserRouteCache,
36
+ BrowserRoutingConfig,
37
+ strip_direct_vm_auth,
38
+ rewrite_direct_vm_options,
39
+ browser_routing_config_from_env,
40
+ maybe_evict_browser_route_from_response,
41
+ maybe_populate_browser_route_cache_from_response,
42
+ )
32
43
 
33
44
  if TYPE_CHECKING:
34
45
  from .resources import (
@@ -79,8 +90,10 @@ ENVIRONMENTS: Dict[str, str] = {
79
90
  class Kernel(SyncAPIClient):
80
91
  # client options
81
92
  api_key: str
93
+ browser_route_cache: BrowserRouteCache
82
94
 
83
95
  _environment: Literal["production", "development"] | NotGiven
96
+ _browser_routing: BrowserRoutingConfig
84
97
 
85
98
  def __init__(
86
99
  self,
@@ -105,6 +118,7 @@ class Kernel(SyncAPIClient):
105
118
  # outlining your use-case to help us decide if it should be
106
119
  # part of our public interface in the future.
107
120
  _strict_response_validation: bool = False,
121
+ _browser_route_cache: BrowserRouteCache | None = None,
108
122
  ) -> None:
109
123
  """Construct a new synchronous Kernel client instance.
110
124
 
@@ -154,6 +168,8 @@ class Kernel(SyncAPIClient):
154
168
  custom_query=default_query,
155
169
  _strict_response_validation=_strict_response_validation,
156
170
  )
171
+ self.browser_route_cache = _browser_route_cache or BrowserRouteCache()
172
+ self._browser_routing = browser_routing_config_from_env()
157
173
 
158
174
  @cached_property
159
175
  def deployments(self) -> DeploymentsResource:
@@ -266,6 +282,37 @@ class Kernel(SyncAPIClient):
266
282
  **self._custom_headers,
267
283
  }
268
284
 
285
+ @override
286
+ def _prepare_options(self, options: Any) -> Any:
287
+ options = cast(Any, super()._prepare_options(options))
288
+ return rewrite_direct_vm_options(options, cache=self.browser_route_cache, config=self._browser_routing)
289
+
290
+ @override
291
+ def _prepare_request(self, request: httpx.Request) -> None:
292
+ strip_direct_vm_auth(request, cache=self.browser_route_cache)
293
+
294
+ @override
295
+ def _process_response(
296
+ self,
297
+ *,
298
+ cast_to: Type[ResponseT],
299
+ options: FinalRequestOptions,
300
+ response: httpx.Response,
301
+ stream: bool,
302
+ stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None,
303
+ retries_taken: int = 0,
304
+ ) -> ResponseT:
305
+ maybe_populate_browser_route_cache_from_response(response, cache=self.browser_route_cache)
306
+ maybe_evict_browser_route_from_response(response, cache=self.browser_route_cache)
307
+ return super()._process_response(
308
+ cast_to=cast_to,
309
+ options=options,
310
+ response=response,
311
+ stream=stream,
312
+ stream_cls=stream_cls,
313
+ retries_taken=retries_taken,
314
+ )
315
+
269
316
  def copy(
270
317
  self,
271
318
  *,
@@ -279,6 +326,7 @@ class Kernel(SyncAPIClient):
279
326
  set_default_headers: Mapping[str, str] | None = None,
280
327
  default_query: Mapping[str, object] | None = None,
281
328
  set_default_query: Mapping[str, object] | None = None,
329
+ _browser_route_cache: BrowserRouteCache | None = None,
282
330
  _extra_kwargs: Mapping[str, Any] = {},
283
331
  ) -> Self:
284
332
  """
@@ -312,6 +360,7 @@ class Kernel(SyncAPIClient):
312
360
  max_retries=max_retries if is_given(max_retries) else self.max_retries,
313
361
  default_headers=headers,
314
362
  default_query=params,
363
+ _browser_route_cache=_browser_route_cache or self.browser_route_cache,
315
364
  **_extra_kwargs,
316
365
  )
317
366
 
@@ -356,8 +405,10 @@ class Kernel(SyncAPIClient):
356
405
  class AsyncKernel(AsyncAPIClient):
357
406
  # client options
358
407
  api_key: str
408
+ browser_route_cache: BrowserRouteCache
359
409
 
360
410
  _environment: Literal["production", "development"] | NotGiven
411
+ _browser_routing: BrowserRoutingConfig
361
412
 
362
413
  def __init__(
363
414
  self,
@@ -382,6 +433,7 @@ class AsyncKernel(AsyncAPIClient):
382
433
  # outlining your use-case to help us decide if it should be
383
434
  # part of our public interface in the future.
384
435
  _strict_response_validation: bool = False,
436
+ _browser_route_cache: BrowserRouteCache | None = None,
385
437
  ) -> None:
386
438
  """Construct a new async AsyncKernel client instance.
387
439
 
@@ -431,6 +483,8 @@ class AsyncKernel(AsyncAPIClient):
431
483
  custom_query=default_query,
432
484
  _strict_response_validation=_strict_response_validation,
433
485
  )
486
+ self.browser_route_cache = _browser_route_cache or BrowserRouteCache()
487
+ self._browser_routing = browser_routing_config_from_env()
434
488
 
435
489
  @cached_property
436
490
  def deployments(self) -> AsyncDeploymentsResource:
@@ -543,6 +597,37 @@ class AsyncKernel(AsyncAPIClient):
543
597
  **self._custom_headers,
544
598
  }
545
599
 
600
+ @override
601
+ async def _prepare_options(self, options: Any) -> Any:
602
+ options = cast(Any, await super()._prepare_options(options))
603
+ return rewrite_direct_vm_options(options, cache=self.browser_route_cache, config=self._browser_routing)
604
+
605
+ @override
606
+ async def _prepare_request(self, request: httpx.Request) -> None:
607
+ strip_direct_vm_auth(request, cache=self.browser_route_cache)
608
+
609
+ @override
610
+ async def _process_response(
611
+ self,
612
+ *,
613
+ cast_to: Type[ResponseT],
614
+ options: FinalRequestOptions,
615
+ response: httpx.Response,
616
+ stream: bool,
617
+ stream_cls: type[Stream[Any]] | type[AsyncStream[Any]] | None,
618
+ retries_taken: int = 0,
619
+ ) -> ResponseT:
620
+ maybe_populate_browser_route_cache_from_response(response, cache=self.browser_route_cache)
621
+ maybe_evict_browser_route_from_response(response, cache=self.browser_route_cache)
622
+ return await super()._process_response(
623
+ cast_to=cast_to,
624
+ options=options,
625
+ response=response,
626
+ stream=stream,
627
+ stream_cls=stream_cls,
628
+ retries_taken=retries_taken,
629
+ )
630
+
546
631
  def copy(
547
632
  self,
548
633
  *,
@@ -556,6 +641,7 @@ class AsyncKernel(AsyncAPIClient):
556
641
  set_default_headers: Mapping[str, str] | None = None,
557
642
  default_query: Mapping[str, object] | None = None,
558
643
  set_default_query: Mapping[str, object] | None = None,
644
+ _browser_route_cache: BrowserRouteCache | None = None,
559
645
  _extra_kwargs: Mapping[str, Any] = {},
560
646
  ) -> Self:
561
647
  """
@@ -589,6 +675,7 @@ class AsyncKernel(AsyncAPIClient):
589
675
  max_retries=max_retries if is_given(max_retries) else self.max_retries,
590
676
  default_headers=headers,
591
677
  default_query=params,
678
+ _browser_route_cache=_browser_route_cache or self.browser_route_cache,
592
679
  **_extra_kwargs,
593
680
  )
594
681
 
@@ -3,8 +3,8 @@ from __future__ import annotations
3
3
  import io
4
4
  import os
5
5
  import pathlib
6
- from typing import overload
7
- from typing_extensions import TypeGuard
6
+ from typing import Sequence, cast, overload
7
+ from typing_extensions import TypeVar, TypeGuard
8
8
 
9
9
  import anyio
10
10
 
@@ -17,7 +17,9 @@ from ._types import (
17
17
  HttpxFileContent,
18
18
  HttpxRequestFiles,
19
19
  )
20
- from ._utils import is_tuple_t, is_mapping_t, is_sequence_t
20
+ from ._utils import is_list, is_mapping, is_tuple_t, is_mapping_t, is_sequence_t
21
+
22
+ _T = TypeVar("_T")
21
23
 
22
24
 
23
25
  def is_base64_file_input(obj: object) -> TypeGuard[Base64FileInput]:
@@ -121,3 +123,51 @@ async def async_read_file_content(file: FileContent) -> HttpxFileContent:
121
123
  return await anyio.Path(file).read_bytes()
122
124
 
123
125
  return file
126
+
127
+
128
+ def deepcopy_with_paths(item: _T, paths: Sequence[Sequence[str]]) -> _T:
129
+ """Copy only the containers along the given paths.
130
+
131
+ Used to guard against mutation by extract_files without copying the entire structure.
132
+ Only dicts and lists that lie on a path are copied; everything else
133
+ is returned by reference.
134
+
135
+ For example, given paths=[["foo", "files", "file"]] and the structure:
136
+ {
137
+ "foo": {
138
+ "bar": {"baz": {}},
139
+ "files": {"file": <content>}
140
+ }
141
+ }
142
+ The root dict, "foo", and "files" are copied (they lie on the path).
143
+ "bar" and "baz" are returned by reference (off the path).
144
+ """
145
+ return _deepcopy_with_paths(item, paths, 0)
146
+
147
+
148
+ def _deepcopy_with_paths(item: _T, paths: Sequence[Sequence[str]], index: int) -> _T:
149
+ if not paths:
150
+ return item
151
+ if is_mapping(item):
152
+ key_to_paths: dict[str, list[Sequence[str]]] = {}
153
+ for path in paths:
154
+ if index < len(path):
155
+ key_to_paths.setdefault(path[index], []).append(path)
156
+
157
+ # if no path continues through this mapping, it won't be mutated and copying it is redundant
158
+ if not key_to_paths:
159
+ return item
160
+
161
+ result = dict(item)
162
+ for key, subpaths in key_to_paths.items():
163
+ if key in result:
164
+ result[key] = _deepcopy_with_paths(result[key], subpaths, index + 1)
165
+ return cast(_T, result)
166
+ if is_list(item):
167
+ array_paths = [path for path in paths if index < len(path) and path[index] == "<array>"]
168
+
169
+ # if no path expects a list here, nothing will be mutated inside it - return by reference
170
+ if not array_paths:
171
+ return cast(_T, item)
172
+ return cast(_T, [_deepcopy_with_paths(entry, array_paths, index + 1) for entry in item])
173
+ return item
@@ -24,7 +24,6 @@ from ._utils import (
24
24
  coerce_integer as coerce_integer,
25
25
  file_from_path as file_from_path,
26
26
  strip_not_given as strip_not_given,
27
- deepcopy_minimal as deepcopy_minimal,
28
27
  get_async_library as get_async_library,
29
28
  maybe_coerce_float as maybe_coerce_float,
30
29
  get_required_header as get_required_header,
@@ -86,8 +86,9 @@ def _extract_items(
86
86
  index += 1
87
87
  if is_dict(obj):
88
88
  try:
89
- # We are at the last entry in the path so we must remove the field
90
- if (len(path)) == index:
89
+ # Remove the field if there are no more dict keys in the path,
90
+ # only "<array>" traversal markers or end.
91
+ if all(p == "<array>" for p in path[index:]):
91
92
  item = obj.pop(key)
92
93
  else:
93
94
  item = obj[key]
@@ -176,21 +177,6 @@ def is_iterable(obj: object) -> TypeGuard[Iterable[object]]:
176
177
  return isinstance(obj, Iterable)
177
178
 
178
179
 
179
- def deepcopy_minimal(item: _T) -> _T:
180
- """Minimal reimplementation of copy.deepcopy() that will only copy certain object types:
181
-
182
- - mappings, e.g. `dict`
183
- - list
184
-
185
- This is done for performance reasons.
186
- """
187
- if is_mapping(item):
188
- return cast(_T, {k: deepcopy_minimal(v) for k, v in item.items()})
189
- if is_list(item):
190
- return cast(_T, [deepcopy_minimal(entry) for entry in item])
191
- return item
192
-
193
-
194
180
  # copied from https://github.com/Rapptz/RoboDanny
195
181
  def human_join(seq: Sequence[str], *, delim: str = ", ", final: str = "or") -> str:
196
182
  size = len(seq)
@@ -1,4 +1,4 @@
1
1
  # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2
2
 
3
3
  __title__ = "kernel"
4
- __version__ = "0.49.0" # x-release-please-version
4
+ __version__ = "0.51.0" # x-release-please-version
@@ -0,0 +1,3 @@
1
+ from __future__ import annotations
2
+
3
+ __all__: list[str] = []
@@ -0,0 +1,150 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import IO, Any, Union, Mapping, cast
4
+ from contextlib import contextmanager, asynccontextmanager
5
+ from collections.abc import Iterable, Iterator, AsyncIterator
6
+
7
+ import httpx
8
+
9
+ from .util import sanitize_curl_raw_params
10
+ from .routing import BrowserRoute
11
+ from ..._types import Body, Timeout, NotGiven, not_given
12
+ from ..._models import FinalRequestOptions
13
+
14
+ BrowserRawContent = Union[bytes, bytearray, memoryview, str, IO[bytes], Iterable[bytes]]
15
+
16
+
17
+ def request_via_browser_route(
18
+ parent: Any,
19
+ route: BrowserRoute,
20
+ method: str,
21
+ url: str,
22
+ *,
23
+ content: BrowserRawContent | None = None,
24
+ json: Body | None = None,
25
+ headers: Mapping[str, str] | None = None,
26
+ params: Mapping[str, object] | None = None,
27
+ timeout: float | Timeout | None | NotGiven = not_given,
28
+ ) -> httpx.Response:
29
+ if json is not None and content is not None:
30
+ raise TypeError("Passing both `json` and `content` is not supported")
31
+ query: dict[str, object] = {**sanitize_curl_raw_params(params), "url": url, "jwt": route.jwt}
32
+ options = FinalRequestOptions.construct(
33
+ method=method.upper(),
34
+ url=route.base_url.rstrip("/") + "/curl/raw",
35
+ params=query,
36
+ headers=headers or {},
37
+ content=_normalize_binary_content(content),
38
+ json_data=json,
39
+ timeout=_normalize_timeout(timeout),
40
+ )
41
+ return cast(httpx.Response, parent.request(httpx.Response, options))
42
+
43
+
44
+ @contextmanager
45
+ def stream_via_browser_route(
46
+ parent: Any,
47
+ route: BrowserRoute,
48
+ method: str,
49
+ url: str,
50
+ *,
51
+ content: BrowserRawContent | None = None,
52
+ headers: Mapping[str, str] | None = None,
53
+ params: Mapping[str, object] | None = None,
54
+ timeout: float | Timeout | None | NotGiven = not_given,
55
+ ) -> Iterator[httpx.Response]:
56
+ query: dict[str, Any] = sanitize_curl_raw_params(params)
57
+ query["jwt"] = route.jwt
58
+ query["url"] = url
59
+ request_headers = {k: v for k, v in parent.default_headers.items() if isinstance(v, str)}
60
+ if content is None:
61
+ request_headers.pop("Content-Type", None)
62
+ if headers:
63
+ request_headers.update(headers)
64
+ request_headers.pop("Authorization", None)
65
+ effective_timeout = parent.timeout if isinstance(timeout, NotGiven) else timeout
66
+ with parent._client.stream(
67
+ method.upper(),
68
+ route.base_url.rstrip("/") + "/curl/raw",
69
+ params=query,
70
+ headers=request_headers,
71
+ content=_normalize_binary_content(content),
72
+ timeout=_normalize_timeout(effective_timeout),
73
+ ) as response:
74
+ yield response
75
+
76
+
77
+ async def async_request_via_browser_route(
78
+ parent: Any,
79
+ route: BrowserRoute,
80
+ method: str,
81
+ url: str,
82
+ *,
83
+ content: BrowserRawContent | None = None,
84
+ json: Body | None = None,
85
+ headers: Mapping[str, str] | None = None,
86
+ params: Mapping[str, object] | None = None,
87
+ timeout: float | Timeout | None | NotGiven = not_given,
88
+ ) -> httpx.Response:
89
+ if json is not None and content is not None:
90
+ raise TypeError("Passing both `json` and `content` is not supported")
91
+ query: dict[str, object] = {**sanitize_curl_raw_params(params), "url": url, "jwt": route.jwt}
92
+ options = FinalRequestOptions.construct(
93
+ method=method.upper(),
94
+ url=route.base_url.rstrip("/") + "/curl/raw",
95
+ params=query,
96
+ headers=headers or {},
97
+ content=_normalize_binary_content(content),
98
+ json_data=json,
99
+ timeout=_normalize_timeout(timeout),
100
+ )
101
+ return cast(httpx.Response, await parent.request(httpx.Response, options))
102
+
103
+
104
+ @asynccontextmanager
105
+ async def async_stream_via_browser_route(
106
+ parent: Any,
107
+ route: BrowserRoute,
108
+ method: str,
109
+ url: str,
110
+ *,
111
+ content: BrowserRawContent | None = None,
112
+ headers: Mapping[str, str] | None = None,
113
+ params: Mapping[str, object] | None = None,
114
+ timeout: float | Timeout | None | NotGiven = not_given,
115
+ ) -> AsyncIterator[httpx.Response]:
116
+ query: dict[str, Any] = sanitize_curl_raw_params(params)
117
+ query["jwt"] = route.jwt
118
+ query["url"] = url
119
+ request_headers = {k: v for k, v in parent.default_headers.items() if isinstance(v, str)}
120
+ if content is None:
121
+ request_headers.pop("Content-Type", None)
122
+ if headers:
123
+ request_headers.update(headers)
124
+ request_headers.pop("Authorization", None)
125
+ effective_timeout = parent.timeout if isinstance(timeout, NotGiven) else timeout
126
+ async with parent._client.stream(
127
+ method.upper(),
128
+ route.base_url.rstrip("/") + "/curl/raw",
129
+ params=query,
130
+ headers=request_headers,
131
+ content=_normalize_binary_content(content),
132
+ timeout=_normalize_timeout(effective_timeout),
133
+ ) as response:
134
+ yield response
135
+
136
+
137
+ def _normalize_timeout(timeout: float | Timeout | None | NotGiven) -> float | Timeout | None:
138
+ return None if isinstance(timeout, NotGiven) else timeout
139
+
140
+
141
+ def _normalize_binary_content(content: BrowserRawContent | None) -> bytes | IO[bytes] | Iterable[bytes] | None:
142
+ if content is None:
143
+ return None
144
+ if isinstance(content, str):
145
+ return content.encode()
146
+ if isinstance(content, bytearray):
147
+ return bytes(content)
148
+ if isinstance(content, memoryview):
149
+ return content.tobytes()
150
+ return content