diff --git a/openapi.json b/openapi.json index 44bd03d..f823c31 100644 --- a/openapi.json +++ b/openapi.json @@ -1668,7 +1668,22 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Browser" + "oneOf": [ + { + "$ref": "#/components/schemas/Browser" + }, + { + "$ref": "#/components/schemas/Desktop" + } + ], + "discriminator": { + "propertyName": "kind", + "mapping": { + "web": "#/components/schemas/Browser", + "desktop": "#/components/schemas/Desktop" + } + }, + "title": "Create" } } } @@ -1920,7 +1935,22 @@ "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/Browser" + "oneOf": [ + { + "$ref": "#/components/schemas/Browser" + }, + { + "$ref": "#/components/schemas/Desktop" + } + ], + "discriminator": { + "propertyName": "kind", + "mapping": { + "web": "#/components/schemas/Browser", + "desktop": "#/components/schemas/Desktop" + } + }, + "title": "Update" } } } @@ -4550,6 +4580,16 @@ "title": "Kind", "default": "web" }, + "host": { + "type": "string", + "enum": [ + "user_device", + "cloud" + ], + "title": "Host", + "description": "Where the browser runs: 'cloud' on H Company infrastructure, or 'user_device' on your own machine.", + "default": "cloud" + }, "start_url": { "type": "string", "title": "Start Url", @@ -4562,6 +4602,18 @@ "description": "Run the browser without a visible window.", "default": false }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Session Id", + "description": "Connect to an existing browser session by id instead of starting a new one." + }, "mode": { "oneOf": [ { @@ -4592,7 +4644,7 @@ } ], "title": "Vault Id", - "description": "Id of a vault config to bind to this browser, letting the agent sign in to sites with secrets resolved from the vault. The vault must belong to the caller's organization. Omit to run without secret access." + "description": "Id of a vault config to bind to this browser, letting the agent sign in to sites with secrets resolved from the vault. The vault must belong to the caller's organization. Only supported on cloud-hosted browsers. Omit to run without secret access." }, "browser_profile_id": { "anyOf": [ @@ -4605,7 +4657,13 @@ } ], "title": "Browser Profile Id", - "description": "Id of a browser profile to load into this browser, restoring saved cookies and storage state from a prior session. The profile must belong to the caller's organization. Omit to run with a fresh profile." + "description": "Id of a browser profile to load into this browser, restoring saved cookies and storage state from a prior session. The profile must belong to the caller's organization. Only supported on cloud-hosted browsers. Omit to run with a fresh profile." + }, + "persist_browser_profile": { + "type": "boolean", + "title": "Persist Browser Profile", + "description": "When true, the browser profile is updated with this session's final browser state (cookies, storage) when the session ends. Requires browser_profile_id. Only one active session at a time may persist a given profile; concurrent read-only use is always allowed.", + "default": false }, "network": { "anyOf": [ @@ -5013,13 +5071,68 @@ "title": "CronTiming", "description": "Cron cadence evaluated in an IANA timezone." }, + "Desktop": { + "properties": { + "id": { + "type": "string", + "minLength": 1, + "title": "Id", + "description": "Catalog identifier for this environment." + }, + "kind": { + "type": "string", + "const": "desktop", + "title": "Kind", + "default": "desktop" + }, + "host": { + "type": "string", + "title": "Host", + "const": "user_device" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Session Id", + "description": "Connect to an existing desktop session by id instead of starting a new one." + } + }, + "type": "object", + "required": [ + "id", + "host" + ], + "title": "Desktop", + "description": "A desktop the agent controls via mouse, keyboard, and screenshots." + }, "Environment": { - "$ref": "#/components/schemas/Browser" + "oneOf": [ + { + "$ref": "#/components/schemas/Browser" + }, + { + "$ref": "#/components/schemas/Desktop" + } + ], + "discriminator": { + "propertyName": "kind", + "mapping": { + "desktop": "#/components/schemas/Desktop", + "web": "#/components/schemas/Browser" + } + } }, "EnvironmentKind": { "type": "string", "enum": [ - "web" + "web", + "desktop" ], "title": "EnvironmentKind", "description": "Environment family." @@ -5937,6 +6050,21 @@ }, "PatchEnvironment": { "properties": { + "host": { + "anyOf": [ + { + "type": "string", + "enum": [ + "user_device", + "cloud" + ] + }, + { + "type": "null" + } + ], + "title": "Host" + }, "start_url": { "anyOf": [ { @@ -5959,6 +6087,17 @@ ], "title": "Headless" }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Session Id" + }, "mode": { "anyOf": [ { @@ -6008,6 +6147,17 @@ ], "title": "Browser Profile Id" }, + "persist_browser_profile": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Persist Browser Profile" + }, "network": { "anyOf": [ { diff --git a/pyproject.toml b/pyproject.toml index 4de7b92..9d894d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "hai-agents" -version = "1.0.5" +version = "1.0.6" description = "Python SDK for H Company's Computer-Use Agents: autonomous agents powered by Holo." requires-python = ">=3.10" readme = "README.md" diff --git a/src/hai_agents/__init__.py b/src/hai_agents/__init__.py index edc03f3..3caa0a9 100644 --- a/src/hai_agents/__init__.py +++ b/src/hai_agents/__init__.py @@ -37,7 +37,7 @@ AnswerEventAnswer, AnswerOutcome, Browser, - BrowserKind, + BrowserHost, BrowserMode, BrowserMode_Text, BrowserMode_Visual, @@ -48,9 +48,13 @@ BrowserVisualMode, CronTiming, CronTimingType, + Desktop, + DesktopHost, Environment, EnvironmentKind, EnvironmentPage, + Environment_Desktop, + Environment_Web, ErrorEvent, ErrorEventKind, Feedback, @@ -154,10 +158,17 @@ from .client import AsyncClient, Client from .environment import HaiAgentsEnvironment from .environments import ( + CreateEnvironmentRequest, + CreateEnvironmentRequest_Desktop, + CreateEnvironmentRequest_Web, ListEnvironmentsRequestSortItem, + PatchEnvironmentHost, PatchEnvironmentMode, PatchEnvironmentMode_Text, PatchEnvironmentMode_Visual, + UpdateEnvironmentRequestBody, + UpdateEnvironmentRequestBody_Desktop, + UpdateEnvironmentRequestBody_Web, ) from .polling import ( AnswerValidationError, @@ -225,7 +236,7 @@ "AsyncClient": ".client", "AsyncSessionHandle": ".polling", "Browser": ".types", - "BrowserKind": ".types", + "BrowserHost": ".types", "BrowserMode": ".types", "BrowserMode_Text": ".types", "BrowserMode_Visual": ".types", @@ -235,13 +246,20 @@ "BrowserTextMode": ".types", "BrowserVisualMode": ".types", "Client": ".client", + "CreateEnvironmentRequest": ".environments", + "CreateEnvironmentRequest_Desktop": ".environments", + "CreateEnvironmentRequest_Web": ".environments", "CronTiming": ".types", "CronTimingType": ".types", "DefaultAioHttpClient": "._default_clients", "DefaultAsyncHttpxClient": "._default_clients", + "Desktop": ".types", + "DesktopHost": ".types", "Environment": ".types", "EnvironmentKind": ".types", "EnvironmentPage": ".types", + "Environment_Desktop": ".types", + "Environment_Web": ".types", "ErrorEvent": ".types", "ErrorEventKind": ".types", "Feedback": ".types", @@ -286,6 +304,7 @@ "PatchAgentEnvironmentsItem": ".agents", "PatchAgentSkillsItem": ".agents", "PatchAgentSubagentsItem": ".agents", + "PatchEnvironmentHost": ".environments", "PatchEnvironmentMode": ".environments", "PatchEnvironmentMode_Text": ".environments", "PatchEnvironmentMode_Visual": ".environments", @@ -346,6 +365,9 @@ "TrajectoryEvent": ".types", "TrajectoryStatus": ".types", "UnprocessableEntityError": ".errors", + "UpdateEnvironmentRequestBody": ".environments", + "UpdateEnvironmentRequestBody_Desktop": ".environments", + "UpdateEnvironmentRequestBody_Web": ".environments", "UserMessageBatch": ".types", "UserMessageEvent": ".types", "UserMessageEventType": ".types", @@ -442,7 +464,7 @@ def __dir__(): "AsyncClient", "AsyncSessionHandle", "Browser", - "BrowserKind", + "BrowserHost", "BrowserMode", "BrowserMode_Text", "BrowserMode_Visual", @@ -452,13 +474,20 @@ def __dir__(): "BrowserTextMode", "BrowserVisualMode", "Client", + "CreateEnvironmentRequest", + "CreateEnvironmentRequest_Desktop", + "CreateEnvironmentRequest_Web", "CronTiming", "CronTimingType", "DefaultAioHttpClient", "DefaultAsyncHttpxClient", + "Desktop", + "DesktopHost", "Environment", "EnvironmentKind", "EnvironmentPage", + "Environment_Desktop", + "Environment_Web", "ErrorEvent", "ErrorEventKind", "Feedback", @@ -503,6 +532,7 @@ def __dir__(): "PatchAgentEnvironmentsItem", "PatchAgentSkillsItem", "PatchAgentSubagentsItem", + "PatchEnvironmentHost", "PatchEnvironmentMode", "PatchEnvironmentMode_Text", "PatchEnvironmentMode_Visual", @@ -563,6 +593,9 @@ def __dir__(): "TrajectoryEvent", "TrajectoryStatus", "UnprocessableEntityError", + "UpdateEnvironmentRequestBody", + "UpdateEnvironmentRequestBody_Desktop", + "UpdateEnvironmentRequestBody_Web", "UserMessageBatch", "UserMessageEvent", "UserMessageEventType", diff --git a/src/hai_agents/client.py b/src/hai_agents/client.py index d84ec71..82e5354 100644 --- a/src/hai_agents/client.py +++ b/src/hai_agents/client.py @@ -24,6 +24,7 @@ ) from .polling import async_run_session as _async_run_session from .polling import run_session as _run_session +from .sessions.client import AsyncSessionsClient, SessionsClient from .tools import ToolInput, as_tools @@ -75,6 +76,14 @@ def session(self, id: str) -> SessionHandle: """Wrap an existing session id in a handle.""" return SessionHandle(self, id) + @property + def sessions(self) -> SessionsClient: + if self._sessions is None: + from hai_agents_local.sessions import LocalSessionsClient + + self._sessions = LocalSessionsClient(client_wrapper=self._client_wrapper) + return self._sessions + class AsyncClient(AsyncBaseClient): async def run_session( @@ -123,3 +132,11 @@ async def start_session( def session(self, id: str) -> AsyncSessionHandle: """Wrap an existing session id in a handle.""" return AsyncSessionHandle(self, id) + + @property + def sessions(self) -> AsyncSessionsClient: + if self._sessions is None: + from hai_agents_local.sessions import LocalAsyncSessionsClient + + self._sessions = LocalAsyncSessionsClient(client_wrapper=self._client_wrapper) + return self._sessions diff --git a/src/hai_agents/core/client_wrapper.py b/src/hai_agents/core/client_wrapper.py index 8a6d738..e64eb3a 100644 --- a/src/hai_agents/core/client_wrapper.py +++ b/src/hai_agents/core/client_wrapper.py @@ -29,9 +29,9 @@ def get_headers(self) -> typing.Dict[str, str]: import platform headers: typing.Dict[str, str] = { - "User-Agent": "hai_agents/1.0.5", + "User-Agent": "hai_agents/1.0.6", "X-HCompany-Client-Name": "hai_agents", - "X-HCompany-Client-Version": "1.0.5", + "X-HCompany-Client-Version": "1.0.6", "X-HCompany-Client-Type": "sdk", "X-HCompany-Language": "Python", "X-HCompany-Runtime": f"python/{platform.python_version()}", diff --git a/src/hai_agents/environments/__init__.py b/src/hai_agents/environments/__init__.py index fd094dd..24ac494 100644 --- a/src/hai_agents/environments/__init__.py +++ b/src/hai_agents/environments/__init__.py @@ -7,16 +7,30 @@ if typing.TYPE_CHECKING: from .types import ( + CreateEnvironmentRequest, + CreateEnvironmentRequest_Desktop, + CreateEnvironmentRequest_Web, ListEnvironmentsRequestSortItem, + PatchEnvironmentHost, PatchEnvironmentMode, PatchEnvironmentMode_Text, PatchEnvironmentMode_Visual, + UpdateEnvironmentRequestBody, + UpdateEnvironmentRequestBody_Desktop, + UpdateEnvironmentRequestBody_Web, ) _dynamic_imports: typing.Dict[str, str] = { + "CreateEnvironmentRequest": ".types", + "CreateEnvironmentRequest_Desktop": ".types", + "CreateEnvironmentRequest_Web": ".types", "ListEnvironmentsRequestSortItem": ".types", + "PatchEnvironmentHost": ".types", "PatchEnvironmentMode": ".types", "PatchEnvironmentMode_Text": ".types", "PatchEnvironmentMode_Visual": ".types", + "UpdateEnvironmentRequestBody": ".types", + "UpdateEnvironmentRequestBody_Desktop": ".types", + "UpdateEnvironmentRequestBody_Web": ".types", } @@ -42,8 +56,15 @@ def __dir__(): __all__ = [ + "CreateEnvironmentRequest", + "CreateEnvironmentRequest_Desktop", + "CreateEnvironmentRequest_Web", "ListEnvironmentsRequestSortItem", + "PatchEnvironmentHost", "PatchEnvironmentMode", "PatchEnvironmentMode_Text", "PatchEnvironmentMode_Visual", + "UpdateEnvironmentRequestBody", + "UpdateEnvironmentRequestBody_Desktop", + "UpdateEnvironmentRequestBody_Web", ] diff --git a/src/hai_agents/environments/client.py b/src/hai_agents/environments/client.py index 5e17ac9..7e174e2 100644 --- a/src/hai_agents/environments/client.py +++ b/src/hai_agents/environments/client.py @@ -4,15 +4,16 @@ from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper from ..core.request_options import RequestOptions -from ..types.browser_kind import BrowserKind -from ..types.browser_mode import BrowserMode from ..types.browser_network import BrowserNetwork from ..types.environment import Environment from ..types.environment_kind import EnvironmentKind from ..types.environment_page import EnvironmentPage from .raw_client import AsyncRawEnvironmentsClient, RawEnvironmentsClient +from .types.create_environment_request import CreateEnvironmentRequest from .types.list_environments_request_sort_item import ListEnvironmentsRequestSortItem +from .types.patch_environment_host import PatchEnvironmentHost from .types.patch_environment_mode import PatchEnvironmentMode +from .types.update_environment_request_body import UpdateEnvironmentRequestBody # this is used as the default value for optional parameters OMIT = typing.cast(typing.Any, ...) @@ -90,45 +91,14 @@ def list_environments( return _response.data def create_environment( - self, - *, - id: str, - kind: typing.Optional[BrowserKind] = OMIT, - start_url: typing.Optional[str] = OMIT, - headless: typing.Optional[bool] = OMIT, - mode: typing.Optional[BrowserMode] = OMIT, - vault_id: typing.Optional[str] = OMIT, - browser_profile_id: typing.Optional[str] = OMIT, - network: typing.Optional[BrowserNetwork] = OMIT, - request_options: typing.Optional[RequestOptions] = None, + self, *, request: CreateEnvironmentRequest, request_options: typing.Optional[RequestOptions] = None ) -> Environment: """ Create an environment. Parameters ---------- - id : str - Catalog identifier for this environment. - - kind : typing.Optional[BrowserKind] - - start_url : typing.Optional[str] - Initial URL to open. - - headless : typing.Optional[bool] - Run the browser without a visible window. - - mode : typing.Optional[BrowserMode] - How the agent perceives and drives the browser. - - vault_id : typing.Optional[str] - Id of a vault config to bind to this browser, letting the agent sign in to sites with secrets resolved from the vault. The vault must belong to the caller's organization. Omit to run without secret access. - - browser_profile_id : typing.Optional[str] - Id of a browser profile to load into this browser, restoring saved cookies and storage state from a prior session. The profile must belong to the caller's organization. Omit to run with a fresh profile. - - network : typing.Optional[BrowserNetwork] - Optional network configuration for the remote browser session. Applied only when a new runner session is provisioned (not when session_id is set). + request : CreateEnvironmentRequest request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -141,25 +111,18 @@ def create_environment( Examples -------- from hai_agents import Client + from hai_agents.environments import CreateEnvironmentRequest_Web client = Client( api_key="YOUR_API_KEY", ) client.environments.create_environment( - id="id", + request=CreateEnvironmentRequest_Web( + id="id", + ), ) """ - _response = self._raw_client.create_environment( - id=id, - kind=kind, - start_url=start_url, - headless=headless, - mode=mode, - vault_id=vault_id, - browser_profile_id=browser_profile_id, - network=network, - request_options=request_options, - ) + _response = self._raw_client.create_environment(request=request, request_options=request_options) return _response.data def get_environment(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Environment: @@ -193,48 +156,16 @@ def get_environment(self, id: str, *, request_options: typing.Optional[RequestOp return _response.data def update_environment( - self, - id_: str, - *, - id: str, - kind: typing.Optional[BrowserKind] = OMIT, - start_url: typing.Optional[str] = OMIT, - headless: typing.Optional[bool] = OMIT, - mode: typing.Optional[BrowserMode] = OMIT, - vault_id: typing.Optional[str] = OMIT, - browser_profile_id: typing.Optional[str] = OMIT, - network: typing.Optional[BrowserNetwork] = OMIT, - request_options: typing.Optional[RequestOptions] = None, + self, id: str, *, request: UpdateEnvironmentRequestBody, request_options: typing.Optional[RequestOptions] = None ) -> Environment: """ Replace the environment spec. Parameters ---------- - id_ : str - id : str - Catalog identifier for this environment. - - kind : typing.Optional[BrowserKind] - - start_url : typing.Optional[str] - Initial URL to open. - - headless : typing.Optional[bool] - Run the browser without a visible window. - - mode : typing.Optional[BrowserMode] - How the agent perceives and drives the browser. - vault_id : typing.Optional[str] - Id of a vault config to bind to this browser, letting the agent sign in to sites with secrets resolved from the vault. The vault must belong to the caller's organization. Omit to run without secret access. - - browser_profile_id : typing.Optional[str] - Id of a browser profile to load into this browser, restoring saved cookies and storage state from a prior session. The profile must belong to the caller's organization. Omit to run with a fresh profile. - - network : typing.Optional[BrowserNetwork] - Optional network configuration for the remote browser session. Applied only when a new runner session is provisioned (not when session_id is set). + request : UpdateEnvironmentRequestBody request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -247,27 +178,19 @@ def update_environment( Examples -------- from hai_agents import Client + from hai_agents.environments import UpdateEnvironmentRequestBody_Web client = Client( api_key="YOUR_API_KEY", ) client.environments.update_environment( - id_="id", id="id", + request=UpdateEnvironmentRequestBody_Web( + id="id", + ), ) """ - _response = self._raw_client.update_environment( - id_, - id=id, - kind=kind, - start_url=start_url, - headless=headless, - mode=mode, - vault_id=vault_id, - browser_profile_id=browser_profile_id, - network=network, - request_options=request_options, - ) + _response = self._raw_client.update_environment(id, request=request, request_options=request_options) return _response.data def delete_environment(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: @@ -303,11 +226,14 @@ def patch_environment( self, id: str, *, + host: typing.Optional[PatchEnvironmentHost] = OMIT, start_url: typing.Optional[str] = OMIT, headless: typing.Optional[bool] = OMIT, + session_id: typing.Optional[str] = OMIT, mode: typing.Optional[PatchEnvironmentMode] = OMIT, vault_id: typing.Optional[str] = OMIT, browser_profile_id: typing.Optional[str] = OMIT, + persist_browser_profile: typing.Optional[bool] = OMIT, network: typing.Optional[BrowserNetwork] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Environment: @@ -318,16 +244,22 @@ def patch_environment( ---------- id : str + host : typing.Optional[PatchEnvironmentHost] + start_url : typing.Optional[str] headless : typing.Optional[bool] + session_id : typing.Optional[str] + mode : typing.Optional[PatchEnvironmentMode] vault_id : typing.Optional[str] browser_profile_id : typing.Optional[str] + persist_browser_profile : typing.Optional[bool] + network : typing.Optional[BrowserNetwork] request_options : typing.Optional[RequestOptions] @@ -351,11 +283,14 @@ def patch_environment( """ _response = self._raw_client.patch_environment( id, + host=host, start_url=start_url, headless=headless, + session_id=session_id, mode=mode, vault_id=vault_id, browser_profile_id=browser_profile_id, + persist_browser_profile=persist_browser_profile, network=network, request_options=request_options, ) @@ -442,45 +377,14 @@ async def main() -> None: return _response.data async def create_environment( - self, - *, - id: str, - kind: typing.Optional[BrowserKind] = OMIT, - start_url: typing.Optional[str] = OMIT, - headless: typing.Optional[bool] = OMIT, - mode: typing.Optional[BrowserMode] = OMIT, - vault_id: typing.Optional[str] = OMIT, - browser_profile_id: typing.Optional[str] = OMIT, - network: typing.Optional[BrowserNetwork] = OMIT, - request_options: typing.Optional[RequestOptions] = None, + self, *, request: CreateEnvironmentRequest, request_options: typing.Optional[RequestOptions] = None ) -> Environment: """ Create an environment. Parameters ---------- - id : str - Catalog identifier for this environment. - - kind : typing.Optional[BrowserKind] - - start_url : typing.Optional[str] - Initial URL to open. - - headless : typing.Optional[bool] - Run the browser without a visible window. - - mode : typing.Optional[BrowserMode] - How the agent perceives and drives the browser. - - vault_id : typing.Optional[str] - Id of a vault config to bind to this browser, letting the agent sign in to sites with secrets resolved from the vault. The vault must belong to the caller's organization. Omit to run without secret access. - - browser_profile_id : typing.Optional[str] - Id of a browser profile to load into this browser, restoring saved cookies and storage state from a prior session. The profile must belong to the caller's organization. Omit to run with a fresh profile. - - network : typing.Optional[BrowserNetwork] - Optional network configuration for the remote browser session. Applied only when a new runner session is provisioned (not when session_id is set). + request : CreateEnvironmentRequest request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -495,6 +399,7 @@ async def create_environment( import asyncio from hai_agents import AsyncClient + from hai_agents.environments import CreateEnvironmentRequest_Web client = AsyncClient( api_key="YOUR_API_KEY", @@ -503,23 +408,15 @@ async def create_environment( async def main() -> None: await client.environments.create_environment( - id="id", + request=CreateEnvironmentRequest_Web( + id="id", + ), ) asyncio.run(main()) """ - _response = await self._raw_client.create_environment( - id=id, - kind=kind, - start_url=start_url, - headless=headless, - mode=mode, - vault_id=vault_id, - browser_profile_id=browser_profile_id, - network=network, - request_options=request_options, - ) + _response = await self._raw_client.create_environment(request=request, request_options=request_options) return _response.data async def get_environment(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Environment: @@ -561,48 +458,16 @@ async def main() -> None: return _response.data async def update_environment( - self, - id_: str, - *, - id: str, - kind: typing.Optional[BrowserKind] = OMIT, - start_url: typing.Optional[str] = OMIT, - headless: typing.Optional[bool] = OMIT, - mode: typing.Optional[BrowserMode] = OMIT, - vault_id: typing.Optional[str] = OMIT, - browser_profile_id: typing.Optional[str] = OMIT, - network: typing.Optional[BrowserNetwork] = OMIT, - request_options: typing.Optional[RequestOptions] = None, + self, id: str, *, request: UpdateEnvironmentRequestBody, request_options: typing.Optional[RequestOptions] = None ) -> Environment: """ Replace the environment spec. Parameters ---------- - id_ : str - id : str - Catalog identifier for this environment. - - kind : typing.Optional[BrowserKind] - - start_url : typing.Optional[str] - Initial URL to open. - - headless : typing.Optional[bool] - Run the browser without a visible window. - - mode : typing.Optional[BrowserMode] - How the agent perceives and drives the browser. - vault_id : typing.Optional[str] - Id of a vault config to bind to this browser, letting the agent sign in to sites with secrets resolved from the vault. The vault must belong to the caller's organization. Omit to run without secret access. - - browser_profile_id : typing.Optional[str] - Id of a browser profile to load into this browser, restoring saved cookies and storage state from a prior session. The profile must belong to the caller's organization. Omit to run with a fresh profile. - - network : typing.Optional[BrowserNetwork] - Optional network configuration for the remote browser session. Applied only when a new runner session is provisioned (not when session_id is set). + request : UpdateEnvironmentRequestBody request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -617,6 +482,7 @@ async def update_environment( import asyncio from hai_agents import AsyncClient + from hai_agents.environments import UpdateEnvironmentRequestBody_Web client = AsyncClient( api_key="YOUR_API_KEY", @@ -625,25 +491,16 @@ async def update_environment( async def main() -> None: await client.environments.update_environment( - id_="id", id="id", + request=UpdateEnvironmentRequestBody_Web( + id="id", + ), ) asyncio.run(main()) """ - _response = await self._raw_client.update_environment( - id_, - id=id, - kind=kind, - start_url=start_url, - headless=headless, - mode=mode, - vault_id=vault_id, - browser_profile_id=browser_profile_id, - network=network, - request_options=request_options, - ) + _response = await self._raw_client.update_environment(id, request=request, request_options=request_options) return _response.data async def delete_environment(self, id: str, *, request_options: typing.Optional[RequestOptions] = None) -> None: @@ -687,11 +544,14 @@ async def patch_environment( self, id: str, *, + host: typing.Optional[PatchEnvironmentHost] = OMIT, start_url: typing.Optional[str] = OMIT, headless: typing.Optional[bool] = OMIT, + session_id: typing.Optional[str] = OMIT, mode: typing.Optional[PatchEnvironmentMode] = OMIT, vault_id: typing.Optional[str] = OMIT, browser_profile_id: typing.Optional[str] = OMIT, + persist_browser_profile: typing.Optional[bool] = OMIT, network: typing.Optional[BrowserNetwork] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> Environment: @@ -702,16 +562,22 @@ async def patch_environment( ---------- id : str + host : typing.Optional[PatchEnvironmentHost] + start_url : typing.Optional[str] headless : typing.Optional[bool] + session_id : typing.Optional[str] + mode : typing.Optional[PatchEnvironmentMode] vault_id : typing.Optional[str] browser_profile_id : typing.Optional[str] + persist_browser_profile : typing.Optional[bool] + network : typing.Optional[BrowserNetwork] request_options : typing.Optional[RequestOptions] @@ -743,11 +609,14 @@ async def main() -> None: """ _response = await self._raw_client.patch_environment( id, + host=host, start_url=start_url, headless=headless, + session_id=session_id, mode=mode, vault_id=vault_id, browser_profile_id=browser_profile_id, + persist_browser_profile=persist_browser_profile, network=network, request_options=request_options, ) diff --git a/src/hai_agents/environments/raw_client.py b/src/hai_agents/environments/raw_client.py index 37ff859..59a76d0 100644 --- a/src/hai_agents/environments/raw_client.py +++ b/src/hai_agents/environments/raw_client.py @@ -12,15 +12,16 @@ from ..core.request_options import RequestOptions from ..core.serialization import convert_and_respect_annotation_metadata from ..errors.unprocessable_entity_error import UnprocessableEntityError -from ..types.browser_kind import BrowserKind -from ..types.browser_mode import BrowserMode from ..types.browser_network import BrowserNetwork from ..types.environment import Environment from ..types.environment_kind import EnvironmentKind from ..types.environment_page import EnvironmentPage from ..types.http_validation_error import HttpValidationError +from .types.create_environment_request import CreateEnvironmentRequest from .types.list_environments_request_sort_item import ListEnvironmentsRequestSortItem +from .types.patch_environment_host import PatchEnvironmentHost from .types.patch_environment_mode import PatchEnvironmentMode +from .types.update_environment_request_body import UpdateEnvironmentRequestBody from pydantic import ValidationError # this is used as the default value for optional parameters @@ -117,45 +118,14 @@ def list_environments( raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def create_environment( - self, - *, - id: str, - kind: typing.Optional[BrowserKind] = OMIT, - start_url: typing.Optional[str] = OMIT, - headless: typing.Optional[bool] = OMIT, - mode: typing.Optional[BrowserMode] = OMIT, - vault_id: typing.Optional[str] = OMIT, - browser_profile_id: typing.Optional[str] = OMIT, - network: typing.Optional[BrowserNetwork] = OMIT, - request_options: typing.Optional[RequestOptions] = None, + self, *, request: CreateEnvironmentRequest, request_options: typing.Optional[RequestOptions] = None ) -> HttpResponse[Environment]: """ Create an environment. Parameters ---------- - id : str - Catalog identifier for this environment. - - kind : typing.Optional[BrowserKind] - - start_url : typing.Optional[str] - Initial URL to open. - - headless : typing.Optional[bool] - Run the browser without a visible window. - - mode : typing.Optional[BrowserMode] - How the agent perceives and drives the browser. - - vault_id : typing.Optional[str] - Id of a vault config to bind to this browser, letting the agent sign in to sites with secrets resolved from the vault. The vault must belong to the caller's organization. Omit to run without secret access. - - browser_profile_id : typing.Optional[str] - Id of a browser profile to load into this browser, restoring saved cookies and storage state from a prior session. The profile must belong to the caller's organization. Omit to run with a fresh profile. - - network : typing.Optional[BrowserNetwork] - Optional network configuration for the remote browser session. Applied only when a new runner session is provisioned (not when session_id is set). + request : CreateEnvironmentRequest request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -168,20 +138,9 @@ def create_environment( _response = self._client_wrapper.httpx_client.request( "api/v2/environments", method="POST", - json={ - "id": id, - "kind": kind, - "start_url": start_url, - "headless": headless, - "mode": convert_and_respect_annotation_metadata( - object_=mode, annotation=BrowserMode, direction="write" - ), - "vault_id": vault_id, - "browser_profile_id": browser_profile_id, - "network": convert_and_respect_annotation_metadata( - object_=network, annotation=typing.Optional[BrowserNetwork], direction="write" - ), - }, + json=convert_and_respect_annotation_metadata( + object_=request, annotation=CreateEnvironmentRequest, direction="write" + ), headers={ "content-type": "application/json", }, @@ -272,48 +231,16 @@ def get_environment( raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) def update_environment( - self, - id_: str, - *, - id: str, - kind: typing.Optional[BrowserKind] = OMIT, - start_url: typing.Optional[str] = OMIT, - headless: typing.Optional[bool] = OMIT, - mode: typing.Optional[BrowserMode] = OMIT, - vault_id: typing.Optional[str] = OMIT, - browser_profile_id: typing.Optional[str] = OMIT, - network: typing.Optional[BrowserNetwork] = OMIT, - request_options: typing.Optional[RequestOptions] = None, + self, id: str, *, request: UpdateEnvironmentRequestBody, request_options: typing.Optional[RequestOptions] = None ) -> HttpResponse[Environment]: """ Replace the environment spec. Parameters ---------- - id_ : str - id : str - Catalog identifier for this environment. - - kind : typing.Optional[BrowserKind] - - start_url : typing.Optional[str] - Initial URL to open. - - headless : typing.Optional[bool] - Run the browser without a visible window. - - mode : typing.Optional[BrowserMode] - How the agent perceives and drives the browser. - - vault_id : typing.Optional[str] - Id of a vault config to bind to this browser, letting the agent sign in to sites with secrets resolved from the vault. The vault must belong to the caller's organization. Omit to run without secret access. - - browser_profile_id : typing.Optional[str] - Id of a browser profile to load into this browser, restoring saved cookies and storage state from a prior session. The profile must belong to the caller's organization. Omit to run with a fresh profile. - network : typing.Optional[BrowserNetwork] - Optional network configuration for the remote browser session. Applied only when a new runner session is provisioned (not when session_id is set). + request : UpdateEnvironmentRequestBody request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -324,22 +251,11 @@ def update_environment( Successful Response """ _response = self._client_wrapper.httpx_client.request( - f"api/v2/environments/{encode_path_param(id_)}", + f"api/v2/environments/{encode_path_param(id)}", method="PUT", - json={ - "id": id, - "kind": kind, - "start_url": start_url, - "headless": headless, - "mode": convert_and_respect_annotation_metadata( - object_=mode, annotation=BrowserMode, direction="write" - ), - "vault_id": vault_id, - "browser_profile_id": browser_profile_id, - "network": convert_and_respect_annotation_metadata( - object_=network, annotation=typing.Optional[BrowserNetwork], direction="write" - ), - }, + json=convert_and_respect_annotation_metadata( + object_=request, annotation=UpdateEnvironmentRequestBody, direction="write" + ), headers={ "content-type": "application/json", }, @@ -425,11 +341,14 @@ def patch_environment( self, id: str, *, + host: typing.Optional[PatchEnvironmentHost] = OMIT, start_url: typing.Optional[str] = OMIT, headless: typing.Optional[bool] = OMIT, + session_id: typing.Optional[str] = OMIT, mode: typing.Optional[PatchEnvironmentMode] = OMIT, vault_id: typing.Optional[str] = OMIT, browser_profile_id: typing.Optional[str] = OMIT, + persist_browser_profile: typing.Optional[bool] = OMIT, network: typing.Optional[BrowserNetwork] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> HttpResponse[Environment]: @@ -440,16 +359,22 @@ def patch_environment( ---------- id : str + host : typing.Optional[PatchEnvironmentHost] + start_url : typing.Optional[str] headless : typing.Optional[bool] + session_id : typing.Optional[str] + mode : typing.Optional[PatchEnvironmentMode] vault_id : typing.Optional[str] browser_profile_id : typing.Optional[str] + persist_browser_profile : typing.Optional[bool] + network : typing.Optional[BrowserNetwork] request_options : typing.Optional[RequestOptions] @@ -464,13 +389,16 @@ def patch_environment( f"api/v2/environments/{encode_path_param(id)}", method="PATCH", json={ + "host": host, "start_url": start_url, "headless": headless, + "session_id": session_id, "mode": convert_and_respect_annotation_metadata( object_=mode, annotation=typing.Optional[PatchEnvironmentMode], direction="write" ), "vault_id": vault_id, "browser_profile_id": browser_profile_id, + "persist_browser_profile": persist_browser_profile, "network": convert_and_respect_annotation_metadata( object_=network, annotation=typing.Optional[BrowserNetwork], direction="write" ), @@ -602,45 +530,14 @@ async def list_environments( raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def create_environment( - self, - *, - id: str, - kind: typing.Optional[BrowserKind] = OMIT, - start_url: typing.Optional[str] = OMIT, - headless: typing.Optional[bool] = OMIT, - mode: typing.Optional[BrowserMode] = OMIT, - vault_id: typing.Optional[str] = OMIT, - browser_profile_id: typing.Optional[str] = OMIT, - network: typing.Optional[BrowserNetwork] = OMIT, - request_options: typing.Optional[RequestOptions] = None, + self, *, request: CreateEnvironmentRequest, request_options: typing.Optional[RequestOptions] = None ) -> AsyncHttpResponse[Environment]: """ Create an environment. Parameters ---------- - id : str - Catalog identifier for this environment. - - kind : typing.Optional[BrowserKind] - - start_url : typing.Optional[str] - Initial URL to open. - - headless : typing.Optional[bool] - Run the browser without a visible window. - - mode : typing.Optional[BrowserMode] - How the agent perceives and drives the browser. - - vault_id : typing.Optional[str] - Id of a vault config to bind to this browser, letting the agent sign in to sites with secrets resolved from the vault. The vault must belong to the caller's organization. Omit to run without secret access. - - browser_profile_id : typing.Optional[str] - Id of a browser profile to load into this browser, restoring saved cookies and storage state from a prior session. The profile must belong to the caller's organization. Omit to run with a fresh profile. - - network : typing.Optional[BrowserNetwork] - Optional network configuration for the remote browser session. Applied only when a new runner session is provisioned (not when session_id is set). + request : CreateEnvironmentRequest request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -653,20 +550,9 @@ async def create_environment( _response = await self._client_wrapper.httpx_client.request( "api/v2/environments", method="POST", - json={ - "id": id, - "kind": kind, - "start_url": start_url, - "headless": headless, - "mode": convert_and_respect_annotation_metadata( - object_=mode, annotation=BrowserMode, direction="write" - ), - "vault_id": vault_id, - "browser_profile_id": browser_profile_id, - "network": convert_and_respect_annotation_metadata( - object_=network, annotation=typing.Optional[BrowserNetwork], direction="write" - ), - }, + json=convert_and_respect_annotation_metadata( + object_=request, annotation=CreateEnvironmentRequest, direction="write" + ), headers={ "content-type": "application/json", }, @@ -757,48 +643,16 @@ async def get_environment( raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json) async def update_environment( - self, - id_: str, - *, - id: str, - kind: typing.Optional[BrowserKind] = OMIT, - start_url: typing.Optional[str] = OMIT, - headless: typing.Optional[bool] = OMIT, - mode: typing.Optional[BrowserMode] = OMIT, - vault_id: typing.Optional[str] = OMIT, - browser_profile_id: typing.Optional[str] = OMIT, - network: typing.Optional[BrowserNetwork] = OMIT, - request_options: typing.Optional[RequestOptions] = None, + self, id: str, *, request: UpdateEnvironmentRequestBody, request_options: typing.Optional[RequestOptions] = None ) -> AsyncHttpResponse[Environment]: """ Replace the environment spec. Parameters ---------- - id_ : str - id : str - Catalog identifier for this environment. - - kind : typing.Optional[BrowserKind] - - start_url : typing.Optional[str] - Initial URL to open. - - headless : typing.Optional[bool] - Run the browser without a visible window. - - mode : typing.Optional[BrowserMode] - How the agent perceives and drives the browser. - - vault_id : typing.Optional[str] - Id of a vault config to bind to this browser, letting the agent sign in to sites with secrets resolved from the vault. The vault must belong to the caller's organization. Omit to run without secret access. - - browser_profile_id : typing.Optional[str] - Id of a browser profile to load into this browser, restoring saved cookies and storage state from a prior session. The profile must belong to the caller's organization. Omit to run with a fresh profile. - network : typing.Optional[BrowserNetwork] - Optional network configuration for the remote browser session. Applied only when a new runner session is provisioned (not when session_id is set). + request : UpdateEnvironmentRequestBody request_options : typing.Optional[RequestOptions] Request-specific configuration. @@ -809,22 +663,11 @@ async def update_environment( Successful Response """ _response = await self._client_wrapper.httpx_client.request( - f"api/v2/environments/{encode_path_param(id_)}", + f"api/v2/environments/{encode_path_param(id)}", method="PUT", - json={ - "id": id, - "kind": kind, - "start_url": start_url, - "headless": headless, - "mode": convert_and_respect_annotation_metadata( - object_=mode, annotation=BrowserMode, direction="write" - ), - "vault_id": vault_id, - "browser_profile_id": browser_profile_id, - "network": convert_and_respect_annotation_metadata( - object_=network, annotation=typing.Optional[BrowserNetwork], direction="write" - ), - }, + json=convert_and_respect_annotation_metadata( + object_=request, annotation=UpdateEnvironmentRequestBody, direction="write" + ), headers={ "content-type": "application/json", }, @@ -910,11 +753,14 @@ async def patch_environment( self, id: str, *, + host: typing.Optional[PatchEnvironmentHost] = OMIT, start_url: typing.Optional[str] = OMIT, headless: typing.Optional[bool] = OMIT, + session_id: typing.Optional[str] = OMIT, mode: typing.Optional[PatchEnvironmentMode] = OMIT, vault_id: typing.Optional[str] = OMIT, browser_profile_id: typing.Optional[str] = OMIT, + persist_browser_profile: typing.Optional[bool] = OMIT, network: typing.Optional[BrowserNetwork] = OMIT, request_options: typing.Optional[RequestOptions] = None, ) -> AsyncHttpResponse[Environment]: @@ -925,16 +771,22 @@ async def patch_environment( ---------- id : str + host : typing.Optional[PatchEnvironmentHost] + start_url : typing.Optional[str] headless : typing.Optional[bool] + session_id : typing.Optional[str] + mode : typing.Optional[PatchEnvironmentMode] vault_id : typing.Optional[str] browser_profile_id : typing.Optional[str] + persist_browser_profile : typing.Optional[bool] + network : typing.Optional[BrowserNetwork] request_options : typing.Optional[RequestOptions] @@ -949,13 +801,16 @@ async def patch_environment( f"api/v2/environments/{encode_path_param(id)}", method="PATCH", json={ + "host": host, "start_url": start_url, "headless": headless, + "session_id": session_id, "mode": convert_and_respect_annotation_metadata( object_=mode, annotation=typing.Optional[PatchEnvironmentMode], direction="write" ), "vault_id": vault_id, "browser_profile_id": browser_profile_id, + "persist_browser_profile": persist_browser_profile, "network": convert_and_respect_annotation_metadata( object_=network, annotation=typing.Optional[BrowserNetwork], direction="write" ), diff --git a/src/hai_agents/environments/types/__init__.py b/src/hai_agents/environments/types/__init__.py index ee1d7f1..a431ae2 100644 --- a/src/hai_agents/environments/types/__init__.py +++ b/src/hai_agents/environments/types/__init__.py @@ -6,13 +6,31 @@ from importlib import import_module if typing.TYPE_CHECKING: + from .create_environment_request import ( + CreateEnvironmentRequest, + CreateEnvironmentRequest_Desktop, + CreateEnvironmentRequest_Web, + ) from .list_environments_request_sort_item import ListEnvironmentsRequestSortItem + from .patch_environment_host import PatchEnvironmentHost from .patch_environment_mode import PatchEnvironmentMode, PatchEnvironmentMode_Text, PatchEnvironmentMode_Visual + from .update_environment_request_body import ( + UpdateEnvironmentRequestBody, + UpdateEnvironmentRequestBody_Desktop, + UpdateEnvironmentRequestBody_Web, + ) _dynamic_imports: typing.Dict[str, str] = { + "CreateEnvironmentRequest": ".create_environment_request", + "CreateEnvironmentRequest_Desktop": ".create_environment_request", + "CreateEnvironmentRequest_Web": ".create_environment_request", "ListEnvironmentsRequestSortItem": ".list_environments_request_sort_item", + "PatchEnvironmentHost": ".patch_environment_host", "PatchEnvironmentMode": ".patch_environment_mode", "PatchEnvironmentMode_Text": ".patch_environment_mode", "PatchEnvironmentMode_Visual": ".patch_environment_mode", + "UpdateEnvironmentRequestBody": ".update_environment_request_body", + "UpdateEnvironmentRequestBody_Desktop": ".update_environment_request_body", + "UpdateEnvironmentRequestBody_Web": ".update_environment_request_body", } @@ -38,8 +56,15 @@ def __dir__(): __all__ = [ + "CreateEnvironmentRequest", + "CreateEnvironmentRequest_Desktop", + "CreateEnvironmentRequest_Web", "ListEnvironmentsRequestSortItem", + "PatchEnvironmentHost", "PatchEnvironmentMode", "PatchEnvironmentMode_Text", "PatchEnvironmentMode_Visual", + "UpdateEnvironmentRequestBody", + "UpdateEnvironmentRequestBody_Desktop", + "UpdateEnvironmentRequestBody_Web", ] diff --git a/src/hai_agents/environments/types/create_environment_request.py b/src/hai_agents/environments/types/create_environment_request.py new file mode 100644 index 0000000..9a7ee06 --- /dev/null +++ b/src/hai_agents/environments/types/create_environment_request.py @@ -0,0 +1,57 @@ +# This file was auto-generated by Fern from our API Definition. + +from __future__ import annotations + +import typing + +import pydantic +import typing_extensions +from ...core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ...types.browser_host import BrowserHost +from ...types.browser_mode import BrowserMode +from ...types.browser_network import BrowserNetwork +from ...types.desktop_host import DesktopHost + + +class CreateEnvironmentRequest_Web(UniversalBaseModel): + kind: typing.Literal["web"] = "web" + id: str + host: typing.Optional[BrowserHost] = None + start_url: typing.Optional[str] = None + headless: typing.Optional[bool] = None + session_id: typing.Optional[str] = None + mode: typing.Optional[BrowserMode] = None + vault_id: typing.Optional[str] = None + browser_profile_id: typing.Optional[str] = None + persist_browser_profile: typing.Optional[bool] = None + network: typing.Optional[BrowserNetwork] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class CreateEnvironmentRequest_Desktop(UniversalBaseModel): + kind: typing.Literal["desktop"] = "desktop" + id: str + host: DesktopHost + session_id: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +CreateEnvironmentRequest = typing_extensions.Annotated[ + typing.Union[CreateEnvironmentRequest_Web, CreateEnvironmentRequest_Desktop], pydantic.Field(discriminator="kind") +] diff --git a/src/hai_agents/environments/types/patch_environment_host.py b/src/hai_agents/environments/types/patch_environment_host.py new file mode 100644 index 0000000..6a25e83 --- /dev/null +++ b/src/hai_agents/environments/types/patch_environment_host.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +PatchEnvironmentHost = typing.Union[typing.Literal["user_device", "cloud"], typing.Any] diff --git a/src/hai_agents/environments/types/update_environment_request_body.py b/src/hai_agents/environments/types/update_environment_request_body.py new file mode 100644 index 0000000..5ad5952 --- /dev/null +++ b/src/hai_agents/environments/types/update_environment_request_body.py @@ -0,0 +1,58 @@ +# This file was auto-generated by Fern from our API Definition. + +from __future__ import annotations + +import typing + +import pydantic +import typing_extensions +from ...core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from ...types.browser_host import BrowserHost +from ...types.browser_mode import BrowserMode +from ...types.browser_network import BrowserNetwork +from ...types.desktop_host import DesktopHost + + +class UpdateEnvironmentRequestBody_Web(UniversalBaseModel): + kind: typing.Literal["web"] = "web" + id: str + host: typing.Optional[BrowserHost] = None + start_url: typing.Optional[str] = None + headless: typing.Optional[bool] = None + session_id: typing.Optional[str] = None + mode: typing.Optional[BrowserMode] = None + vault_id: typing.Optional[str] = None + browser_profile_id: typing.Optional[str] = None + persist_browser_profile: typing.Optional[bool] = None + network: typing.Optional[BrowserNetwork] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class UpdateEnvironmentRequestBody_Desktop(UniversalBaseModel): + kind: typing.Literal["desktop"] = "desktop" + id: str + host: DesktopHost + session_id: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +UpdateEnvironmentRequestBody = typing_extensions.Annotated[ + typing.Union[UpdateEnvironmentRequestBody_Web, UpdateEnvironmentRequestBody_Desktop], + pydantic.Field(discriminator="kind"), +] diff --git a/src/hai_agents/types/__init__.py b/src/hai_agents/types/__init__.py index 0d5ad57..72a161b 100644 --- a/src/hai_agents/types/__init__.py +++ b/src/hai_agents/types/__init__.py @@ -38,7 +38,7 @@ from .answer_event_answer import AnswerEventAnswer from .answer_outcome import AnswerOutcome from .browser import Browser - from .browser_kind import BrowserKind + from .browser_host import BrowserHost from .browser_mode import BrowserMode, BrowserMode_Text, BrowserMode_Visual from .browser_network import BrowserNetwork from .browser_profile_list import BrowserProfileList @@ -47,7 +47,9 @@ from .browser_visual_mode import BrowserVisualMode from .cron_timing import CronTiming from .cron_timing_type import CronTimingType - from .environment import Environment + from .desktop import Desktop + from .desktop_host import DesktopHost + from .environment import Environment, Environment_Desktop, Environment_Web from .environment_kind import EnvironmentKind from .environment_page import EnvironmentPage from .error_event import ErrorEvent @@ -175,7 +177,7 @@ "AnswerEventAnswer": ".answer_event_answer", "AnswerOutcome": ".answer_outcome", "Browser": ".browser", - "BrowserKind": ".browser_kind", + "BrowserHost": ".browser_host", "BrowserMode": ".browser_mode", "BrowserMode_Text": ".browser_mode", "BrowserMode_Visual": ".browser_mode", @@ -186,9 +188,13 @@ "BrowserVisualMode": ".browser_visual_mode", "CronTiming": ".cron_timing", "CronTimingType": ".cron_timing_type", + "Desktop": ".desktop", + "DesktopHost": ".desktop_host", "Environment": ".environment", "EnvironmentKind": ".environment_kind", "EnvironmentPage": ".environment_page", + "Environment_Desktop": ".environment", + "Environment_Web": ".environment", "ErrorEvent": ".error_event", "ErrorEventKind": ".error_event_kind", "Feedback": ".feedback", @@ -334,7 +340,7 @@ def __dir__(): "AnswerEventAnswer", "AnswerOutcome", "Browser", - "BrowserKind", + "BrowserHost", "BrowserMode", "BrowserMode_Text", "BrowserMode_Visual", @@ -345,9 +351,13 @@ def __dir__(): "BrowserVisualMode", "CronTiming", "CronTimingType", + "Desktop", + "DesktopHost", "Environment", "EnvironmentKind", "EnvironmentPage", + "Environment_Desktop", + "Environment_Web", "ErrorEvent", "ErrorEventKind", "Feedback", diff --git a/src/hai_agents/types/browser.py b/src/hai_agents/types/browser.py index 948c285..bd55196 100644 --- a/src/hai_agents/types/browser.py +++ b/src/hai_agents/types/browser.py @@ -4,7 +4,7 @@ import pydantic from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel -from .browser_kind import BrowserKind +from .browser_host import BrowserHost from .browser_mode import BrowserMode from .browser_network import BrowserNetwork @@ -19,7 +19,11 @@ class Browser(UniversalBaseModel): Catalog identifier for this environment. """ - kind: typing.Optional[BrowserKind] = "web" + host: typing.Optional[BrowserHost] = pydantic.Field(default=None) + """ + Where the browser runs: 'cloud' on H Company infrastructure, or 'user_device' on your own machine. + """ + start_url: typing.Optional[str] = pydantic.Field(default=None) """ Initial URL to open. @@ -30,6 +34,11 @@ class Browser(UniversalBaseModel): Run the browser without a visible window. """ + session_id: typing.Optional[str] = pydantic.Field(default=None) + """ + Connect to an existing browser session by id instead of starting a new one. + """ + mode: typing.Optional[BrowserMode] = pydantic.Field(default=None) """ How the agent perceives and drives the browser. @@ -37,12 +46,17 @@ class Browser(UniversalBaseModel): vault_id: typing.Optional[str] = pydantic.Field(default=None) """ - Id of a vault config to bind to this browser, letting the agent sign in to sites with secrets resolved from the vault. The vault must belong to the caller's organization. Omit to run without secret access. + Id of a vault config to bind to this browser, letting the agent sign in to sites with secrets resolved from the vault. The vault must belong to the caller's organization. Only supported on cloud-hosted browsers. Omit to run without secret access. """ browser_profile_id: typing.Optional[str] = pydantic.Field(default=None) """ - Id of a browser profile to load into this browser, restoring saved cookies and storage state from a prior session. The profile must belong to the caller's organization. Omit to run with a fresh profile. + Id of a browser profile to load into this browser, restoring saved cookies and storage state from a prior session. The profile must belong to the caller's organization. Only supported on cloud-hosted browsers. Omit to run with a fresh profile. + """ + + persist_browser_profile: typing.Optional[bool] = pydantic.Field(default=None) + """ + When true, the browser profile is updated with this session's final browser state (cookies, storage) when the session ends. Requires browser_profile_id. Only one active session at a time may persist a given profile; concurrent read-only use is always allowed. """ network: typing.Optional[BrowserNetwork] = pydantic.Field(default=None) diff --git a/src/hai_agents/types/browser_host.py b/src/hai_agents/types/browser_host.py new file mode 100644 index 0000000..d358c62 --- /dev/null +++ b/src/hai_agents/types/browser_host.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +BrowserHost = typing.Union[typing.Literal["user_device", "cloud"], typing.Any] diff --git a/src/hai_agents/types/desktop.py b/src/hai_agents/types/desktop.py new file mode 100644 index 0000000..57ebb69 --- /dev/null +++ b/src/hai_agents/types/desktop.py @@ -0,0 +1,33 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +import pydantic +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .desktop_host import DesktopHost + + +class Desktop(UniversalBaseModel): + """ + A desktop the agent controls via mouse, keyboard, and screenshots. + """ + + id: str = pydantic.Field() + """ + Catalog identifier for this environment. + """ + + host: DesktopHost + session_id: typing.Optional[str] = pydantic.Field(default=None) + """ + Connect to an existing desktop session by id instead of starting a new one. + """ + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/hai_agents/types/browser_kind.py b/src/hai_agents/types/desktop_host.py similarity index 53% rename from src/hai_agents/types/browser_kind.py rename to src/hai_agents/types/desktop_host.py index 3d8467f..b76605d 100644 --- a/src/hai_agents/types/browser_kind.py +++ b/src/hai_agents/types/desktop_host.py @@ -2,4 +2,4 @@ import typing -BrowserKind = typing.Union[typing.Literal["web"], typing.Any] +DesktopHost = typing.Union[typing.Literal["user_device"], typing.Any] diff --git a/src/hai_agents/types/environment.py b/src/hai_agents/types/environment.py index be66f73..f3b24ec 100644 --- a/src/hai_agents/types/environment.py +++ b/src/hai_agents/types/environment.py @@ -1,5 +1,57 @@ # This file was auto-generated by Fern from our API Definition. -from .browser import Browser +from __future__ import annotations -Environment = Browser +import typing + +import pydantic +import typing_extensions +from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel +from .browser_host import BrowserHost +from .browser_mode import BrowserMode +from .browser_network import BrowserNetwork +from .desktop_host import DesktopHost + + +class Environment_Desktop(UniversalBaseModel): + kind: typing.Literal["desktop"] = "desktop" + id: str + host: DesktopHost + session_id: typing.Optional[str] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +class Environment_Web(UniversalBaseModel): + kind: typing.Literal["web"] = "web" + id: str + host: typing.Optional[BrowserHost] = None + start_url: typing.Optional[str] = None + headless: typing.Optional[bool] = None + session_id: typing.Optional[str] = None + mode: typing.Optional[BrowserMode] = None + vault_id: typing.Optional[str] = None + browser_profile_id: typing.Optional[str] = None + persist_browser_profile: typing.Optional[bool] = None + network: typing.Optional[BrowserNetwork] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow + + +Environment = typing_extensions.Annotated[ + typing.Union[Environment_Desktop, Environment_Web], pydantic.Field(discriminator="kind") +] diff --git a/src/hai_agents/types/environment_kind.py b/src/hai_agents/types/environment_kind.py index f5a5c80..a793826 100644 --- a/src/hai_agents/types/environment_kind.py +++ b/src/hai_agents/types/environment_kind.py @@ -2,4 +2,4 @@ import typing -EnvironmentKind = typing.Union[typing.Literal["web"], typing.Any] +EnvironmentKind = typing.Union[typing.Literal["web", "desktop"], typing.Any] diff --git a/uv.lock b/uv.lock index ce86f2c..c268779 100644 --- a/uv.lock +++ b/uv.lock @@ -88,7 +88,7 @@ wheels = [ [[package]] name = "hai-agents" -version = "1.0.5" +version = "1.0.6" source = { editable = "." } dependencies = [ { name = "httpx" },