diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3cb6257..4c56f2a 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.63.0" + ".": "0.64.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index b53121e..d9e9753 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 117 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-8f84f4214a8024d8ea62ee639eeaf2fa26900fabe23c8b87accb41d529a0bf4f.yml -openapi_spec_hash: db14f415438b3d338d9376bddc83a5cf -config_hash: 590bf8cb85948cf1e63b7b5ef60686c8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-9d489e3e43edfa64a754d4281241718e01c85d9a82ef3687df12bbd3c4ff5b42.yml +openapi_spec_hash: a953cafb7f40ec8495dbd7df8bab8bad +config_hash: bb7acce8576a50dd449b0c8f58ef0f1d diff --git a/CHANGELOG.md b/CHANGELOG.md index 04be67f..7f4edf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.64.0 (2026-06-05) + +Full Changelog: [v0.63.0...v0.64.0](https://github.com/kernel/kernel-python-sdk/compare/v0.63.0...v0.64.0) + +### Features + +* Telemetry: expose opt-in categories + full event taxonomy (public API) ([a1502dd](https://github.com/kernel/kernel-python-sdk/commit/a1502dd2639b97fb14ec57bfef5e37668b379db7)) + ## 0.63.0 (2026-06-05) Full Changelog: [v0.62.0...v0.63.0](https://github.com/kernel/kernel-python-sdk/compare/v0.62.0...v0.63.0) diff --git a/api.md b/api.md index fe9135b..c501955 100644 --- a/api.md +++ b/api.md @@ -108,7 +108,11 @@ Types: ```python from kernel.types.browsers import ( + BrowserAPICallEvent, BrowserCallStack, + BrowserCaptchaSolveResultEvent, + BrowserCdpConnectEvent, + BrowserCdpDisconnectEvent, BrowserConsoleErrorEvent, BrowserConsoleLogEvent, BrowserEventContext, @@ -117,6 +121,8 @@ from kernel.types.browsers import ( BrowserInteractionClickEvent, BrowserInteractionKeyEvent, BrowserInteractionScrollSettledEvent, + BrowserLiveViewConnectEvent, + BrowserLiveViewDisconnectEvent, BrowserMonitorDisconnectedEvent, BrowserMonitorInitFailedEvent, BrowserMonitorReconnectFailedEvent, @@ -134,6 +140,8 @@ from kernel.types.browsers import ( BrowserPageNavigationEvent, BrowserPageNavigationSettledEvent, BrowserPageTabOpenedEvent, + BrowserServiceCrashedEvent, + BrowserSystemOomKillEvent, BrowserTelemetryCategoriesConfig, BrowserTelemetryCategoryConfig, BrowserTelemetryConfig, diff --git a/pyproject.toml b/pyproject.toml index 710e7a0..a312a05 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "kernel" -version = "0.63.0" +version = "0.64.0" description = "The official Python library for the kernel API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/kernel/_version.py b/src/kernel/_version.py index 52d2f61..b55ca85 100644 --- a/src/kernel/_version.py +++ b/src/kernel/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "kernel" -__version__ = "0.63.0" # x-release-please-version +__version__ = "0.64.0" # x-release-please-version diff --git a/src/kernel/types/browser_create_params.py b/src/kernel/types/browser_create_params.py index fe62f31..6d7b80b 100644 --- a/src/kernel/types/browser_create_params.py +++ b/src/kernel/types/browser_create_params.py @@ -131,17 +131,18 @@ class Telemetry(TypedDict, total=False): """ browser: BrowserTelemetryCategoriesConfigParam - """Per-category enable/disable flags. + """Per-category capture flags. - If enabled is true and browser is omitted or empty, the VM default category set - is used. Explicitly disabling all four categories stops capture on update and - starts no capture on create. + Selection is opt-in: only the categories set to enabled=true are captured; + anything omitted is off. If enabled is true and browser is omitted or empty, the + default category set is used. A browser config that enables nothing stops + capture on update and starts no capture on create. """ enabled: bool """Request shortcut for browser telemetry capture. - True enables capture using VM defaults unless browser category settings are - provided. False stops capture on update and starts no capture on create. - enabled=false cannot be combined with browser category settings. + True enables capture using the default category set unless browser category + settings are provided. False stops capture on update and starts no capture on + create. enabled=false cannot be combined with browser category settings. """ diff --git a/src/kernel/types/browser_update_params.py b/src/kernel/types/browser_update_params.py index 837c178..2626917 100644 --- a/src/kernel/types/browser_update_params.py +++ b/src/kernel/types/browser_update_params.py @@ -52,19 +52,20 @@ class Telemetry(TypedDict, total=False): """ browser: BrowserTelemetryCategoriesConfigParam - """Per-category enable/disable flags. + """Per-category capture flags. - If enabled is true and browser is omitted or empty, the VM default category set - is used. Explicitly disabling all four categories stops capture on update and - starts no capture on create. + Selection is opt-in: only the categories set to enabled=true are captured; + anything omitted is off. If enabled is true and browser is omitted or empty, the + default category set is used. A browser config that enables nothing stops + capture on update and starts no capture on create. """ enabled: bool """Request shortcut for browser telemetry capture. - True enables capture using VM defaults unless browser category settings are - provided. False stops capture on update and starts no capture on create. - enabled=false cannot be combined with browser category settings. + True enables capture using the default category set unless browser category + settings are provided. False stops capture on update and starts no capture on + create. enabled=false cannot be combined with browser category settings. """ diff --git a/src/kernel/types/browsers/__init__.py b/src/kernel/types/browsers/__init__.py index 34f4fd6..5f14ecd 100644 --- a/src/kernel/types/browsers/__init__.py +++ b/src/kernel/types/browsers/__init__.py @@ -28,6 +28,7 @@ from .process_kill_response import ProcessKillResponse as ProcessKillResponse from .process_resize_params import ProcessResizeParams as ProcessResizeParams from .replay_start_response import ReplayStartResponse as ReplayStartResponse +from .browser_api_call_event import BrowserAPICallEvent as BrowserAPICallEvent from .browser_page_lcp_event import BrowserPageLcpEvent as BrowserPageLcpEvent from .computer_scroll_params import ComputerScrollParams as ComputerScrollParams from .process_spawn_response import ProcessSpawnResponse as ProcessSpawnResponse @@ -37,6 +38,7 @@ from .process_resize_response import ProcessResizeResponse as ProcessResizeResponse from .process_status_response import ProcessStatusResponse as ProcessStatusResponse from .browser_telemetry_config import BrowserTelemetryConfig as BrowserTelemetryConfig +from .browser_cdp_connect_event import BrowserCdpConnectEvent as BrowserCdpConnectEvent from .browser_console_log_event import BrowserConsoleLogEvent as BrowserConsoleLogEvent from .computer_press_key_params import ComputerPressKeyParams as ComputerPressKeyParams from .computer_type_text_params import ComputerTypeTextParams as ComputerTypeTextParams @@ -51,14 +53,18 @@ from .browser_console_error_event import BrowserConsoleErrorEvent as BrowserConsoleErrorEvent from .computer_click_mouse_params import ComputerClickMouseParams as ComputerClickMouseParams from .playwright_execute_response import PlaywrightExecuteResponse as PlaywrightExecuteResponse +from .browser_cdp_disconnect_event import BrowserCdpDisconnectEvent as BrowserCdpDisconnectEvent from .browser_interaction_key_event import BrowserInteractionKeyEvent as BrowserInteractionKeyEvent from .browser_network_request_event import BrowserNetworkRequestEvent as BrowserNetworkRequestEvent from .browser_page_navigation_event import BrowserPageNavigationEvent as BrowserPageNavigationEvent from .browser_page_tab_opened_event import BrowserPageTabOpenedEvent as BrowserPageTabOpenedEvent +from .browser_service_crashed_event import BrowserServiceCrashedEvent as BrowserServiceCrashedEvent +from .browser_system_oom_kill_event import BrowserSystemOomKillEvent as BrowserSystemOomKillEvent from .f_set_file_permissions_params import FSetFilePermissionsParams as FSetFilePermissionsParams from .browser_network_response_event import BrowserNetworkResponseEvent as BrowserNetworkResponseEvent from .process_stdout_stream_response import ProcessStdoutStreamResponse as ProcessStdoutStreamResponse from .browser_interaction_click_event import BrowserInteractionClickEvent as BrowserInteractionClickEvent +from .browser_live_view_connect_event import BrowserLiveViewConnectEvent as BrowserLiveViewConnectEvent from .browser_page_layout_shift_event import BrowserPageLayoutShiftEvent as BrowserPageLayoutShiftEvent from .computer_write_clipboard_params import ComputerWriteClipboardParams as ComputerWriteClipboardParams from .browser_monitor_screenshot_event import BrowserMonitorScreenshotEvent as BrowserMonitorScreenshotEvent @@ -67,6 +73,8 @@ from .browser_monitor_reconnected_event import BrowserMonitorReconnectedEvent as BrowserMonitorReconnectedEvent from .browser_page_layout_settled_event import BrowserPageLayoutSettledEvent as BrowserPageLayoutSettledEvent from .browser_telemetry_category_config import BrowserTelemetryCategoryConfig as BrowserTelemetryCategoryConfig +from .browser_captcha_solve_result_event import BrowserCaptchaSolveResultEvent as BrowserCaptchaSolveResultEvent +from .browser_live_view_disconnect_event import BrowserLiveViewDisconnectEvent as BrowserLiveViewDisconnectEvent from .browser_monitor_disconnected_event import BrowserMonitorDisconnectedEvent as BrowserMonitorDisconnectedEvent from .computer_capture_screenshot_params import ComputerCaptureScreenshotParams as ComputerCaptureScreenshotParams from .browser_telemetry_categories_config import BrowserTelemetryCategoriesConfig as BrowserTelemetryCategoriesConfig diff --git a/src/kernel/types/browsers/browser_api_call_event.py b/src/kernel/types/browsers/browser_api_call_event.py new file mode 100644 index 0000000..702596d --- /dev/null +++ b/src/kernel/types/browsers/browser_api_call_event.py @@ -0,0 +1,42 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from ..._models import BaseModel +from .browser_event_source import BrowserEventSource + +__all__ = ["BrowserAPICallEvent", "Data"] + + +class Data(BaseModel): + duration_ms: float + """Wall-clock duration of the handler in milliseconds.""" + + operation_id: str + """OpenAPI operationId of the matched route (e.g. processExec, takeScreenshot).""" + + request_id: str + """Per-request identifier from the in-VM API request middleware.""" + + status: int + """HTTP response status code.""" + + +class BrowserAPICallEvent(BaseModel): + """An agent-driven HTTP call handled by the in-VM API server.""" + + category: Literal["control"] + + source: BrowserEventSource + """Provenance metadata identifying which producer emitted the event.""" + + ts: int + """Event timestamp in Unix microseconds.""" + + type: Literal["api_call"] + + data: Optional[Data] = None + + truncated: Optional[bool] = None + """True if the data field was truncated due to size limits.""" diff --git a/src/kernel/types/browsers/browser_captcha_solve_result_event.py b/src/kernel/types/browsers/browser_captcha_solve_result_event.py new file mode 100644 index 0000000..fb8476d --- /dev/null +++ b/src/kernel/types/browsers/browser_captcha_solve_result_event.py @@ -0,0 +1,63 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from ..._models import BaseModel +from .browser_event_source import BrowserEventSource + +__all__ = ["BrowserCaptchaSolveResultEvent", "Data"] + + +class Data(BaseModel): + captcha_type: Literal["hcaptcha", "recaptcha_v2", "recaptcha_v3", "turnstile", "geetest", "other"] + """Captcha vendor family. + + Provider-specific task names are normalized into this set; anything not covered + is reported as other. + """ + + duration_ms: float + """Wall-clock duration from solve start to terminal outcome.""" + + status: Literal["success", "failure", "timeout", "abandoned"] + """Terminal outcome. + + success: solver returned a usable solution. failure: solver returned an error + (see error_code). timeout: solver did not return within the caller's wait + budget. abandoned: caller cancelled or the page navigated away mid-solve. + """ + + error_code: Optional[str] = None + """Solver-specific error code on failure (e.g. + + ERROR_CAPTCHA_UNSOLVABLE). Absent on success. + """ + + task_id: Optional[str] = None + """Solver-assigned identifier. Opaque, useful for support cross-references.""" + + website_host: Optional[str] = None + """Host of the page where the captcha was solved.""" + + website_path: Optional[str] = None + """Path of the page where the captcha was solved. Query string excluded.""" + + +class BrowserCaptchaSolveResultEvent(BaseModel): + """A captcha solve attempt reached a terminal outcome.""" + + category: Literal["captcha"] + + source: BrowserEventSource + """Provenance metadata identifying which producer emitted the event.""" + + ts: int + """Event timestamp in Unix microseconds.""" + + type: Literal["captcha_solve_result"] + + data: Optional[Data] = None + + truncated: Optional[bool] = None + """True if the data field was truncated due to size limits.""" diff --git a/src/kernel/types/browsers/browser_cdp_connect_event.py b/src/kernel/types/browsers/browser_cdp_connect_event.py new file mode 100644 index 0000000..ebbc7fa --- /dev/null +++ b/src/kernel/types/browsers/browser_cdp_connect_event.py @@ -0,0 +1,29 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from ..._models import BaseModel +from .browser_event_source import BrowserEventSource + +__all__ = ["BrowserCdpConnectEvent"] + + +class BrowserCdpConnectEvent(BaseModel): + """An external client (e.g. + + customer SDK, Playwright, Puppeteer) connected to the CDP WebSocket proxy on this VM. + """ + + category: Literal["connection"] + + source: BrowserEventSource + """Provenance metadata identifying which producer emitted the event.""" + + ts: int + """Event timestamp in Unix microseconds.""" + + type: Literal["cdp_connect"] + + truncated: Optional[bool] = None + """True if the data field was truncated due to size limits.""" diff --git a/src/kernel/types/browsers/browser_cdp_disconnect_event.py b/src/kernel/types/browsers/browser_cdp_disconnect_event.py new file mode 100644 index 0000000..d9260eb --- /dev/null +++ b/src/kernel/types/browsers/browser_cdp_disconnect_event.py @@ -0,0 +1,49 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from ..._models import BaseModel +from .browser_event_source import BrowserEventSource + +__all__ = ["BrowserCdpDisconnectEvent", "Data"] + + +class Data(BaseModel): + duration_ms: float + """Wall-clock duration of the connection in milliseconds.""" + + message_count: int + """Number of CDP messages relayed across the connection in either direction.""" + + reason: Literal["client_close", "upstream_changed", "upstream_error", "context_cancelled"] + """Why the connection ended. + + client_close: the client initiated the close. upstream_changed: Chromium + restarted mid-session and the proxy tore down so the client could reconnect + against the new upstream. upstream_error: upstream dial or message pump errored. + context_cancelled: the request context was cancelled (typically server + shutdown). + """ + + +class BrowserCdpDisconnectEvent(BaseModel): + """An external client disconnected from the CDP WebSocket proxy on this VM. + + Pair with the immediately preceding cdp_connect on the same stream. + """ + + category: Literal["connection"] + + source: BrowserEventSource + """Provenance metadata identifying which producer emitted the event.""" + + ts: int + """Event timestamp in Unix microseconds.""" + + type: Literal["cdp_disconnect"] + + data: Optional[Data] = None + + truncated: Optional[bool] = None + """True if the data field was truncated due to size limits.""" diff --git a/src/kernel/types/browsers/browser_live_view_connect_event.py b/src/kernel/types/browsers/browser_live_view_connect_event.py new file mode 100644 index 0000000..620e3d3 --- /dev/null +++ b/src/kernel/types/browsers/browser_live_view_connect_event.py @@ -0,0 +1,40 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from ..._models import BaseModel +from .browser_event_source import BrowserEventSource + +__all__ = ["BrowserLiveViewConnectEvent", "Data"] + + +class Data(BaseModel): + session_id: str + """Live view session identifier. + + Stable across reconnects, so a transient network blip can emit two events with + the same session_id. + """ + + +class BrowserLiveViewConnectEvent(BaseModel): + """A live view client connected to the headful browser's WebRTC server. + + Headful only; not emitted for headless images. + """ + + category: Literal["connection"] + + source: BrowserEventSource + """Provenance metadata identifying which producer emitted the event.""" + + ts: int + """Event timestamp in Unix microseconds.""" + + type: Literal["live_view_connect"] + + data: Optional[Data] = None + + truncated: Optional[bool] = None + """True if the data field was truncated due to size limits.""" diff --git a/src/kernel/types/browsers/browser_live_view_disconnect_event.py b/src/kernel/types/browsers/browser_live_view_disconnect_event.py new file mode 100644 index 0000000..a847d34 --- /dev/null +++ b/src/kernel/types/browsers/browser_live_view_disconnect_event.py @@ -0,0 +1,41 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from ..._models import BaseModel +from .browser_event_source import BrowserEventSource + +__all__ = ["BrowserLiveViewDisconnectEvent", "Data"] + + +class Data(BaseModel): + duration_ms: float + """Wall-clock duration of the connection in milliseconds.""" + + session_id: str + """ + Live view session identifier; matches the corresponding live_view_connect event. + """ + + +class BrowserLiveViewDisconnectEvent(BaseModel): + """A live view client disconnected from the headful browser's WebRTC server. + + Pair with live_view_connect by session_id. + """ + + category: Literal["connection"] + + source: BrowserEventSource + """Provenance metadata identifying which producer emitted the event.""" + + ts: int + """Event timestamp in Unix microseconds.""" + + type: Literal["live_view_disconnect"] + + data: Optional[Data] = None + + truncated: Optional[bool] = None + """True if the data field was truncated due to size limits.""" diff --git a/src/kernel/types/browsers/browser_monitor_disconnected_event.py b/src/kernel/types/browsers/browser_monitor_disconnected_event.py index ac37ec6..2ea3afe 100644 --- a/src/kernel/types/browsers/browser_monitor_disconnected_event.py +++ b/src/kernel/types/browsers/browser_monitor_disconnected_event.py @@ -20,7 +20,7 @@ class BrowserMonitorDisconnectedEvent(BaseModel): Telemetry events may be dropped until monitor_reconnected arrives. Treat any in-progress computed state (network_idle, page_layout_settled) as unreliable until then. """ - category: Literal["system"] + category: Literal["monitor"] source: BrowserEventSource """Provenance metadata identifying which producer emitted the event.""" diff --git a/src/kernel/types/browsers/browser_monitor_init_failed_event.py b/src/kernel/types/browsers/browser_monitor_init_failed_event.py index dba0e5d..c3a7cfd 100644 --- a/src/kernel/types/browsers/browser_monitor_init_failed_event.py +++ b/src/kernel/types/browsers/browser_monitor_init_failed_event.py @@ -17,7 +17,7 @@ class Data(BaseModel): class BrowserMonitorInitFailedEvent(BaseModel): """The CDP session could not be initialized.""" - category: Literal["system"] + category: Literal["monitor"] source: BrowserEventSource """Provenance metadata identifying which producer emitted the event.""" diff --git a/src/kernel/types/browsers/browser_monitor_reconnect_failed_event.py b/src/kernel/types/browsers/browser_monitor_reconnect_failed_event.py index 57eec69..c71bf53 100644 --- a/src/kernel/types/browsers/browser_monitor_reconnect_failed_event.py +++ b/src/kernel/types/browsers/browser_monitor_reconnect_failed_event.py @@ -23,7 +23,7 @@ class BrowserMonitorReconnectFailedEvent(BaseModel): The CDP connection to Chrome could not be re-established after exhausting all reconnection attempts. No further telemetry events will arrive on this session. """ - category: Literal["system"] + category: Literal["monitor"] source: BrowserEventSource """Provenance metadata identifying which producer emitted the event.""" diff --git a/src/kernel/types/browsers/browser_monitor_reconnected_event.py b/src/kernel/types/browsers/browser_monitor_reconnected_event.py index 3936336..c27340c 100644 --- a/src/kernel/types/browsers/browser_monitor_reconnected_event.py +++ b/src/kernel/types/browsers/browser_monitor_reconnected_event.py @@ -19,7 +19,7 @@ class BrowserMonitorReconnectedEvent(BaseModel): The CDP connection to Chrome was successfully re-established after a disconnection. Events emitted during the gap are lost. Computed state is reset, so navigation and network tracking restart fresh from this point. """ - category: Literal["system"] + category: Literal["monitor"] source: BrowserEventSource """Provenance metadata identifying which producer emitted the event.""" diff --git a/src/kernel/types/browsers/browser_monitor_screenshot_event.py b/src/kernel/types/browsers/browser_monitor_screenshot_event.py index bd2dc65..02135b4 100644 --- a/src/kernel/types/browsers/browser_monitor_screenshot_event.py +++ b/src/kernel/types/browsers/browser_monitor_screenshot_event.py @@ -17,7 +17,7 @@ class Data(BaseModel): class BrowserMonitorScreenshotEvent(BaseModel): """A periodic screenshot of the browser viewport.""" - category: Literal["system"] + category: Literal["screenshot"] source: BrowserEventSource """Provenance metadata identifying which producer emitted the event.""" diff --git a/src/kernel/types/browsers/browser_service_crashed_event.py b/src/kernel/types/browsers/browser_service_crashed_event.py new file mode 100644 index 0000000..7bc6f1c --- /dev/null +++ b/src/kernel/types/browsers/browser_service_crashed_event.py @@ -0,0 +1,50 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import Optional +from typing_extensions import Literal + +from ..._models import BaseModel +from .browser_event_source import BrowserEventSource + +__all__ = ["BrowserServiceCrashedEvent", "Data"] + + +class Data(BaseModel): + phase: Literal["startup", "running", "gave_up"] + """Lifecycle phase the crash occurred in. + + startup: the process died before reaching a healthy running state. running: a + previously healthy process died unexpectedly. gave_up: the process manager + exhausted its restart attempts and stopped trying. + """ + + service_name: str + """Program name of the crashed service (e.g. chromium, mutter, kernel-images-api).""" + + pid: Optional[int] = None + """PID of the crashed process. + + Absent when the process manager gave up after exhausting restart attempts. + """ + + +class BrowserServiceCrashedEvent(BaseModel): + """A managed service exited unexpectedly. + + Intentional stops do not produce this event; only unexpected exits and terminal restart-give-up transitions do. + """ + + category: Literal["system"] + + source: BrowserEventSource + """Provenance metadata identifying which producer emitted the event.""" + + ts: int + """Event timestamp in Unix microseconds.""" + + type: Literal["service_crashed"] + + data: Optional[Data] = None + + truncated: Optional[bool] = None + """True if the data field was truncated due to size limits.""" diff --git a/src/kernel/types/browsers/browser_system_oom_kill_event.py b/src/kernel/types/browsers/browser_system_oom_kill_event.py new file mode 100644 index 0000000..2cafb81 --- /dev/null +++ b/src/kernel/types/browsers/browser_system_oom_kill_event.py @@ -0,0 +1,99 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Optional +from typing_extensions import Literal + +from ..._models import BaseModel +from .browser_event_source import BrowserEventSource + +__all__ = ["BrowserSystemOomKillEvent", "Data", "DataTopTask"] + + +class DataTopTask(BaseModel): + name: str + """Comm of the process (max 15 chars, truncated by the kernel).""" + + pid: int + """PID of the process.""" + + rss_kb: int + """Resident set size in KiB at the moment of the kill.""" + + +class Data(BaseModel): + pid: int + """PID of the killed process.""" + + process_name: str + """ + Comm of the killed process as reported by the kernel (max 15 chars, truncated by + the kernel). + """ + + rss_kb: int + """ + Resident set size of the killed process in KiB (sum of anon-rss, file-rss, and + shmem-rss). + """ + + constraint: Optional[Literal["none", "memcg", "cpuset", "memory_policy"]] = None + """Why the kernel decided to OOM-kill. + + none means global memory exhaustion; memcg means a cgroup memory limit was hit; + cpuset / memory_policy are NUMA/policy-driven kills. Absent on kernels older + than 5.0. + """ + + mem_free_kb: Optional[int] = None + """Free system memory in KiB at the time of the kill. + + Assumes a 4 KiB page size. Does not include reclaimable caches. Absent if the + kernel did not emit a parseable Mem-Info section. + """ + + mem_total_kb: Optional[int] = None + """Total system memory in KiB at the time of the kill. + + Assumes a 4 KiB page size. Absent if the kernel did not emit a parseable + Mem-Info section. + """ + + top_tasks: Optional[List[DataTopTask]] = None + """Top processes by resident-set-size at the moment of the kill, sorted descending. + + Empty if the kernel did not emit the Tasks state table. Capped at 5 entries. + """ + + trigger_pid: Optional[int] = None + """PID of the triggering process. + + Absent if the kernel did not emit the standard header line. + """ + + trigger_process_name: Optional[str] = None + """ + Comm of the process whose allocation request caused the kernel to invoke the + OOM-killer. Often the same as process_name but can differ. Max 15 chars. + """ + + +class BrowserSystemOomKillEvent(BaseModel): + """The Linux kernel OOM-killer terminated a process inside the VM. + + Fires for any process killed by the kernel due to memory exhaustion, including Chrome renderer subprocesses that are not supervised. + """ + + category: Literal["system"] + + source: BrowserEventSource + """Provenance metadata identifying which producer emitted the event.""" + + ts: int + """Event timestamp in Unix microseconds.""" + + type: Literal["system_oom_kill"] + + data: Optional[Data] = None + + truncated: Optional[bool] = None + """True if the data field was truncated due to size limits.""" diff --git a/src/kernel/types/browsers/browser_telemetry_categories_config.py b/src/kernel/types/browsers/browser_telemetry_categories_config.py index 82cdb1d..0013fee 100644 --- a/src/kernel/types/browsers/browser_telemetry_categories_config.py +++ b/src/kernel/types/browsers/browser_telemetry_categories_config.py @@ -9,24 +9,59 @@ class BrowserTelemetryCategoriesConfig(BaseModel): - """Per-category telemetry capture settings.""" + """Per-category telemetry capture settings. + + Selection is opt-in: set a category to enabled=true to capture it; anything omitted is off. The default set (used by enabled=true with no per-category settings) is the lightweight operational signals: control, connection, system, captcha. The CDP categories (console, network, page, interaction) and screenshot are off by default and must be opted into. + """ + + captcha: Optional[BrowserTelemetryCategoryConfig] = None + """Captcha solve attempt outcomes. On by default.""" + + connection: Optional[BrowserTelemetryCategoryConfig] = None + """Client attach/detach lifecycle for the CDP proxy and live view. On by default.""" console: Optional[BrowserTelemetryCategoryConfig] = None - """Console output (log, warn, error) and uncaught exceptions.""" + """Console output (log, warn, error) and uncaught exceptions. + + CDP category; off by default. + """ + + control: Optional[BrowserTelemetryCategoryConfig] = None + """Agent-driven actions against the browser, such as inbound calls to the in-VM + API. + + On by default. + """ interaction: Optional[BrowserTelemetryCategoryConfig] = None - """User interaction events including clicks, keydowns, and scroll-settled events.""" + """User interaction events including clicks, keydowns, and scroll-settled events. + + CDP category; off by default. + """ network: Optional[BrowserTelemetryCategoryConfig] = None """ HTTP request and response metadata including URL, method, status code, and timing. Request post data is forwarded as-is from CDP. Text response bodies are truncated at 8 KB for structured types (JSON, XML, form data) and 4 KB for other - text types. Binary responses (images, fonts, media) are excluded. + text types. Binary responses (images, fonts, media) are excluded. CDP category; + off by default. """ page: Optional[BrowserTelemetryCategoryConfig] = None """ Page lifecycle events including navigation, DOMContentLoaded, load, layout - shifts, and LCP. + shifts, and LCP. CDP category; off by default. + """ + + screenshot: Optional[BrowserTelemetryCategoryConfig] = None + """Periodic base64-encoded viewport screenshots. + + High volume; off by default and must be opted into. + """ + + system: Optional[BrowserTelemetryCategoryConfig] = None + """Browser VM health, such as out-of-memory kills and managed-service crashes. + + On by default. """ diff --git a/src/kernel/types/browsers/browser_telemetry_categories_config_param.py b/src/kernel/types/browsers/browser_telemetry_categories_config_param.py index 75a3a79..a1520d7 100644 --- a/src/kernel/types/browsers/browser_telemetry_categories_config_param.py +++ b/src/kernel/types/browsers/browser_telemetry_categories_config_param.py @@ -10,24 +10,59 @@ class BrowserTelemetryCategoriesConfigParam(TypedDict, total=False): - """Per-category telemetry capture settings.""" + """Per-category telemetry capture settings. + + Selection is opt-in: set a category to enabled=true to capture it; anything omitted is off. The default set (used by enabled=true with no per-category settings) is the lightweight operational signals: control, connection, system, captcha. The CDP categories (console, network, page, interaction) and screenshot are off by default and must be opted into. + """ + + captcha: BrowserTelemetryCategoryConfigParam + """Captcha solve attempt outcomes. On by default.""" + + connection: BrowserTelemetryCategoryConfigParam + """Client attach/detach lifecycle for the CDP proxy and live view. On by default.""" console: BrowserTelemetryCategoryConfigParam - """Console output (log, warn, error) and uncaught exceptions.""" + """Console output (log, warn, error) and uncaught exceptions. + + CDP category; off by default. + """ + + control: BrowserTelemetryCategoryConfigParam + """Agent-driven actions against the browser, such as inbound calls to the in-VM + API. + + On by default. + """ interaction: BrowserTelemetryCategoryConfigParam - """User interaction events including clicks, keydowns, and scroll-settled events.""" + """User interaction events including clicks, keydowns, and scroll-settled events. + + CDP category; off by default. + """ network: BrowserTelemetryCategoryConfigParam """ HTTP request and response metadata including URL, method, status code, and timing. Request post data is forwarded as-is from CDP. Text response bodies are truncated at 8 KB for structured types (JSON, XML, form data) and 4 KB for other - text types. Binary responses (images, fonts, media) are excluded. + text types. Binary responses (images, fonts, media) are excluded. CDP category; + off by default. """ page: BrowserTelemetryCategoryConfigParam """ Page lifecycle events including navigation, DOMContentLoaded, load, layout - shifts, and LCP. + shifts, and LCP. CDP category; off by default. + """ + + screenshot: BrowserTelemetryCategoryConfigParam + """Periodic base64-encoded viewport screenshots. + + High volume; off by default and must be opted into. + """ + + system: BrowserTelemetryCategoryConfigParam + """Browser VM health, such as out-of-memory kills and managed-service crashes. + + On by default. """ diff --git a/src/kernel/types/browsers/browser_telemetry_category_config.py b/src/kernel/types/browsers/browser_telemetry_category_config.py index 4a2da2c..f75616c 100644 --- a/src/kernel/types/browsers/browser_telemetry_category_config.py +++ b/src/kernel/types/browsers/browser_telemetry_category_config.py @@ -11,4 +11,7 @@ class BrowserTelemetryCategoryConfig(BaseModel): """Per-category telemetry configuration.""" enabled: Optional[bool] = None - """Whether this category is captured. Defaults to true if omitted.""" + """Whether this category is captured. + + Selection is opt-in, so an omitted category is not captured. + """ diff --git a/src/kernel/types/browsers/browser_telemetry_category_config_param.py b/src/kernel/types/browsers/browser_telemetry_category_config_param.py index 3824b4c..3958f7d 100644 --- a/src/kernel/types/browsers/browser_telemetry_category_config_param.py +++ b/src/kernel/types/browsers/browser_telemetry_category_config_param.py @@ -11,4 +11,7 @@ class BrowserTelemetryCategoryConfigParam(TypedDict, total=False): """Per-category telemetry configuration.""" enabled: bool - """Whether this category is captured. Defaults to true if omitted.""" + """Whether this category is captured. + + Selection is opt-in, so an omitted category is not captured. + """ diff --git a/src/kernel/types/browsers/browser_telemetry_event.py b/src/kernel/types/browsers/browser_telemetry_event.py index d8506bf..26750b0 100644 --- a/src/kernel/types/browsers/browser_telemetry_event.py +++ b/src/kernel/types/browsers/browser_telemetry_event.py @@ -6,22 +6,30 @@ from typing_extensions import Annotated, TypeAlias from ..._utils import PropertyInfo +from .browser_api_call_event import BrowserAPICallEvent from .browser_page_lcp_event import BrowserPageLcpEvent from .browser_page_load_event import BrowserPageLoadEvent from .browser_console_log_event import BrowserConsoleLogEvent +from .browser_cdp_connect_event import BrowserCdpConnectEvent from .browser_network_idle_event import BrowserNetworkIdleEvent from .browser_console_error_event import BrowserConsoleErrorEvent +from .browser_cdp_disconnect_event import BrowserCdpDisconnectEvent from .browser_interaction_key_event import BrowserInteractionKeyEvent from .browser_network_request_event import BrowserNetworkRequestEvent from .browser_page_navigation_event import BrowserPageNavigationEvent from .browser_page_tab_opened_event import BrowserPageTabOpenedEvent +from .browser_service_crashed_event import BrowserServiceCrashedEvent +from .browser_system_oom_kill_event import BrowserSystemOomKillEvent from .browser_network_response_event import BrowserNetworkResponseEvent from .browser_interaction_click_event import BrowserInteractionClickEvent +from .browser_live_view_connect_event import BrowserLiveViewConnectEvent from .browser_page_layout_shift_event import BrowserPageLayoutShiftEvent from .browser_monitor_screenshot_event import BrowserMonitorScreenshotEvent from .browser_monitor_init_failed_event import BrowserMonitorInitFailedEvent from .browser_monitor_reconnected_event import BrowserMonitorReconnectedEvent from .browser_page_layout_settled_event import BrowserPageLayoutSettledEvent +from .browser_captcha_solve_result_event import BrowserCaptchaSolveResultEvent +from .browser_live_view_disconnect_event import BrowserLiveViewDisconnectEvent from .browser_monitor_disconnected_event import BrowserMonitorDisconnectedEvent from .browser_network_loading_failed_event import BrowserNetworkLoadingFailedEvent from .browser_page_dom_content_loaded_event import BrowserPageDomContentLoadedEvent @@ -55,6 +63,14 @@ BrowserMonitorReconnectedEvent, BrowserMonitorReconnectFailedEvent, BrowserMonitorInitFailedEvent, + BrowserAPICallEvent, + BrowserCdpConnectEvent, + BrowserCdpDisconnectEvent, + BrowserLiveViewConnectEvent, + BrowserLiveViewDisconnectEvent, + BrowserCaptchaSolveResultEvent, + BrowserSystemOomKillEvent, + BrowserServiceCrashedEvent, ], PropertyInfo(discriminator="type"), ] diff --git a/src/kernel/types/browsers/telemetry_stream_response.py b/src/kernel/types/browsers/telemetry_stream_response.py index fef04b3..25dd665 100644 --- a/src/kernel/types/browsers/telemetry_stream_response.py +++ b/src/kernel/types/browsers/telemetry_stream_response.py @@ -16,11 +16,13 @@ class TelemetryStreamResponse(BaseModel): event: "BrowserTelemetryEvent" """Union type representing any browser telemetry event. - Discriminated on `type`. Events with a `monitor_` prefix (monitor_screenshot, - monitor_disconnected, monitor_reconnected, monitor_reconnect_failed, - monitor_init_failed) are always emitted regardless of the category configuration - in BrowserTelemetryConfig. All other event types are controlled by the - per-category enable/disable flags. + Discriminated on `type`. Each event's `category` determines when it is captured. + The CDP collector-health events (monitor_disconnected, monitor_reconnected, + monitor_reconnect_failed, monitor_init_failed) use the `monitor` category, which + is not user-configurable: it flows automatically whenever any CDP category + (console, network, page, interaction) is captured, and is silent otherwise. + monitor_screenshot uses the opt-in `screenshot` category. All other event types + are controlled by their per-category enable/disable flags. """ seq: int diff --git a/tests/api_resources/test_browsers.py b/tests/api_resources/test_browsers.py index 590640c..5284214 100644 --- a/tests/api_resources/test_browsers.py +++ b/tests/api_resources/test_browsers.py @@ -60,10 +60,15 @@ def test_method_create_with_all_params(self, client: Kernel) -> None: }, telemetry={ "browser": { + "captcha": {"enabled": True}, + "connection": {"enabled": True}, "console": {"enabled": True}, + "control": {"enabled": True}, "interaction": {"enabled": True}, "network": {"enabled": True}, "page": {"enabled": True}, + "screenshot": {"enabled": True}, + "system": {"enabled": True}, }, "enabled": True, }, @@ -171,10 +176,15 @@ def test_method_update_with_all_params(self, client: Kernel) -> None: proxy_id="proxy_id", telemetry={ "browser": { + "captcha": {"enabled": True}, + "connection": {"enabled": True}, "console": {"enabled": True}, + "control": {"enabled": True}, "interaction": {"enabled": True}, "network": {"enabled": True}, "page": {"enabled": True}, + "screenshot": {"enabled": True}, + "system": {"enabled": True}, }, "enabled": True, }, @@ -472,10 +482,15 @@ async def test_method_create_with_all_params(self, async_client: AsyncKernel) -> }, telemetry={ "browser": { + "captcha": {"enabled": True}, + "connection": {"enabled": True}, "console": {"enabled": True}, + "control": {"enabled": True}, "interaction": {"enabled": True}, "network": {"enabled": True}, "page": {"enabled": True}, + "screenshot": {"enabled": True}, + "system": {"enabled": True}, }, "enabled": True, }, @@ -583,10 +598,15 @@ async def test_method_update_with_all_params(self, async_client: AsyncKernel) -> proxy_id="proxy_id", telemetry={ "browser": { + "captcha": {"enabled": True}, + "connection": {"enabled": True}, "console": {"enabled": True}, + "control": {"enabled": True}, "interaction": {"enabled": True}, "network": {"enabled": True}, "page": {"enabled": True}, + "screenshot": {"enabled": True}, + "system": {"enabled": True}, }, "enabled": True, },