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.
- kernel-0.51.0/.release-please-manifest.json +3 -0
- {kernel-0.49.0 → kernel-0.51.0}/CHANGELOG.md +69 -0
- {kernel-0.49.0 → kernel-0.51.0}/PKG-INFO +1 -1
- {kernel-0.49.0 → kernel-0.51.0}/api.md +2 -0
- kernel-0.51.0/examples/browser_routing.py +25 -0
- {kernel-0.49.0 → kernel-0.51.0}/pyproject.toml +1 -1
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_client.py +88 -1
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_files.py +53 -3
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/__init__.py +0 -1
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_utils.py +3 -17
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_version.py +1 -1
- kernel-0.51.0/src/kernel/lib/browser_routing/__init__.py +3 -0
- kernel-0.51.0/src/kernel/lib/browser_routing/raw_http.py +150 -0
- kernel-0.51.0/src/kernel/lib/browser_routing/routing.py +243 -0
- kernel-0.51.0/src/kernel/lib/browser_routing/util.py +58 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/browsers.py +270 -4
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/fs/fs.py +10 -8
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/deployments.py +8 -5
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/extensions.py +8 -5
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/projects/projects.py +4 -4
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/__init__.py +2 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/connection_follow_response.py +6 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/managed_auth.py +33 -2
- kernel-0.51.0/src/kernel/types/browser_curl_params.py +28 -0
- kernel-0.51.0/src/kernel/types/browser_curl_response.py +23 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_browsers.py +121 -0
- kernel-0.51.0/tests/test_browser_routing.py +323 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/test_extract_files.py +9 -0
- kernel-0.51.0/tests/test_files.py +148 -0
- kernel-0.49.0/.release-please-manifest.json +0 -3
- kernel-0.49.0/tests/test_deepcopy.py +0 -58
- kernel-0.49.0/tests/test_files.py +0 -51
- {kernel-0.49.0 → kernel-0.51.0}/.gitignore +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/CONTRIBUTING.md +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/LICENSE +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/README.md +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/SECURITY.md +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/bin/check-release-environment +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/bin/publish-pypi +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/examples/.keep +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/noxfile.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/release-please-config.json +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/requirements-dev.lock +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/requirements.lock +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_base_client.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_compat.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_constants.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_exceptions.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_models.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_qs.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_resource.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_streaming.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_types.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_compat.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_datetime_parse.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_json.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_logs.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_path.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_proxy.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_reflection.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_resources_proxy.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_streams.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_sync.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_transform.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/_utils/_typing.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/app_framework.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/lib/.keep +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/pagination.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/py.typed +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/apps.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/auth/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/auth/auth.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/auth/connections.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browser_pools.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/computer.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/fs/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/fs/watch.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/logs.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/playwright.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/process.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/browsers/replays.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/credential_providers.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/credentials.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/invocations.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/profiles.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/projects/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/projects/limits.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/resources/proxies.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/app_list_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/app_list_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/connection_create_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/connection_list_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/connection_login_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/connection_submit_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/connection_update_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/login_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/auth/submit_fields_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_create_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_create_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_delete_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_list_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_list_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_load_extensions_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_persistence.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_persistence_param.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool_acquire_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool_acquire_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool_create_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool_delete_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool_list_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool_ref.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool_release_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_pool_update_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_retrieve_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_retrieve_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_update_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_update_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browser_usage.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_batch_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_capture_screenshot_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_click_mouse_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_drag_mouse_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_get_mouse_position_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_move_mouse_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_press_key_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_read_clipboard_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_scroll_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_set_cursor_visibility_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_set_cursor_visibility_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_type_text_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/computer_write_clipboard_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_create_directory_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_delete_directory_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_delete_file_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_download_dir_zip_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_file_info_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_file_info_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_list_files_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_list_files_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_move_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_read_file_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_set_file_permissions_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_upload_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_upload_zip_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/f_write_file_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/fs/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/fs/watch_events_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/fs/watch_start_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/fs/watch_start_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/log_stream_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/playwright_execute_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/playwright_execute_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_exec_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_exec_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_kill_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_kill_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_resize_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_resize_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_spawn_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_spawn_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_status_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_stdin_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_stdin_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/process_stdout_stream_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/replay_list_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/replay_start_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/browsers/replay_start_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_create_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_list_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_provider.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_provider_create_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_provider_item.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_provider_list_items_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_provider_list_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_provider_test_result.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_provider_update_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_totp_code_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/credential_update_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/deployment_create_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/deployment_create_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/deployment_follow_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/deployment_follow_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/deployment_list_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/deployment_list_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/deployment_retrieve_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/deployment_state_event.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/extension_download_from_chrome_store_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/extension_list_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/extension_upload_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/extension_upload_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_create_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_create_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_follow_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_follow_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_list_browsers_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_list_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_list_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_retrieve_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_state_event.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_update_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/invocation_update_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/profile.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/profile_create_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/profile_list_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/project.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/project_create_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/project_list_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/project_update_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/projects/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/projects/limit_update_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/projects/project_limits.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/proxy_check_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/proxy_check_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/proxy_create_params.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/proxy_create_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/proxy_list_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/proxy_retrieve_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/app_action.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/browser_extension.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/browser_profile.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/browser_viewport.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/error_detail.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/error_event.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/error_model.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/heartbeat_event.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared/log_event.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared_params/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared_params/browser_extension.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared_params/browser_profile.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/src/kernel/types/shared_params/browser_viewport.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/auth/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/auth/test_connections.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/fs/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/fs/test_watch.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/test_computer.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/test_fs.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/test_logs.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/test_playwright.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/test_process.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/browsers/test_replays.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/projects/__init__.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/projects/test_limits.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_apps.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_browser_pools.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_credential_providers.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_credentials.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_deployments.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_extensions.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_invocations.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_profiles.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_projects.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/api_resources/test_proxies.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/conftest.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/sample_file.txt +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/test_client.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/test_models.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/test_qs.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/test_required_args.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/test_response.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/test_streaming.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/test_transform.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/test_utils/test_datetime_parse.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/test_utils/test_json.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/test_utils/test_path.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/test_utils/test_proxy.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/test_utils/test_typing.py +0 -0
- {kernel-0.49.0 → kernel-0.51.0}/tests/utils.py +0 -0
|
@@ -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.
|
|
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()
|
|
@@ -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
|
-
#
|
|
90
|
-
|
|
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)
|
|
@@ -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
|